[U-Boot] [RFC 00/14] x86 touch-ups (Includes new init sequence!)

Merry Christmas everyone
After some positive feedback on my new x86 init sequence, I've reworked it onto the tail end of some patches that have been sitting around in my staging branch for the last few weeks.
Patches 1-8 should not be that interesting to most of you (although patch 3 is a precursor for what happens from patches 9 onward)
A note of warning, patches 1-8 have been run-tested on a new board I've been working on - I have not tested them for regression on the sc520 eNET board or coreboot yet
Patches 9-14 have been compile tested but not run (and these have not been run through checkpatch yet - sorry, but it's late and this is the last chance for me to get anything out before the new year)
This series is against u-boot-x86/next and _should_ apply to u-boot/next
Patches 9-14 transition x86 away from the very ad-hoc init sequence into a clearly defined series of init loops - It should be capable of being the back-bone of a new unified init sequence. From there, we should be able to tackle the 'ifdef hell' (misc_init_r? what-the!)
So a quick overview of the new sequence and it's associated elegance (IMHO) (keep in mind this is x86 centric) - CPU boots and runs the reset vector code - early_board_init performs any insanely-low-level init that is needed - car_init sets up Cache-As-RAM (and clears it so gd is zero'd) - set up a stack in CAR - call board_init_f() passing the address of gd in CAR[1][2] - board_init_f() runs the 'init_sequence_f' functions which should initialise console and SDRAM - board_init_f() calls back into the assembler routine board_init_f_r_trampoline - This routine is very simple - It creates a new stack in SDRAM and calls back into board_init_f_r - board_init_f_r is running in Flash, but with SDRAM initialised. It runs an init loop which copies gd from CAR to SDRAM, initialises the CPU cache (which destroys all data in CAR, but that is all safely in RAM by now), copies U-Boot to RAM, clears BSS and jumps to the in-RAM version of board_init_r which finishes the initialisation and enters the main loop
The memory layout for x86 is pretty simple right now - gd is at top-of-RAM and the stack sits just below it. U-Boot .text, .data, .bss etc are below the stack and the heap is below U-Boot. I understand that other arch's are more complex (LCD frame buffers in top-of-RAM for example) - I think this can all be dealt with elegantly with this code as well, but I have not attempted to do so
[1] The board_init_f() has different meanings for different arch's already [2] This parameter is not used, but could be in future to remove the 'gd pointer in a fixed register' hack
Graeme Russ (14): x86: Import glibc memcpy implementation x86: Speed up copy-to-RAM and clear BSS operations x86: Allow cache before copy to RAM x86: Import MSR/MTRR code from Linux x86: Create weak init_cache() function x86: cache tidy-ups CHECKPATCH: arch/x86/cpu/* CHECKPATCH: arch/x86/lib/* x86: Move do_go_exec() out of board.c x86: Move setup_pcat_compatibility() out of board.c x86: remove gd->start_addr_sp x86: Move relocation code out of board.c x86: Simplify board.c x86: Tweak initialisation procedure
arch/x86/cpu/cpu.c | 28 ++- arch/x86/cpu/interrupts.c | 2 +- arch/x86/cpu/start.S | 52 ++-- arch/x86/cpu/start16.S | 54 +++- arch/x86/include/asm/global_data.h | 1 - arch/x86/include/asm/init_helpers.h | 42 +++ arch/x86/include/asm/init_wrappers.h | 42 +++ arch/x86/include/asm/msr-index.h | 447 +++++++++++++++++++++++++++++++ arch/x86/include/asm/msr.h | 216 +++++++++++++++ arch/x86/include/asm/mtrr.h | 203 ++++++++++++++ arch/x86/include/asm/string.h | 2 +- arch/x86/include/asm/u-boot-x86.h | 3 +- arch/x86/lib/Makefile | 4 + arch/x86/lib/bios.S | 134 ++++++---- arch/x86/lib/board.c | 483 ++++++++++------------------------ arch/x86/lib/cmd_boot.c | 64 +++++ arch/x86/lib/init_helpers.c | 154 +++++++++++ arch/x86/lib/init_wrappers.c | 137 ++++++++++ arch/x86/lib/realmode_switch.S | 61 +++-- arch/x86/lib/relocate.c | 117 ++++++++ arch/x86/lib/string.c | 61 +++++ arch/x86/lib/zimage.c | 7 + include/common.h | 11 +- 23 files changed, 1854 insertions(+), 471 deletions(-) create mode 100644 arch/x86/include/asm/init_helpers.h create mode 100644 arch/x86/include/asm/init_wrappers.h create mode 100644 arch/x86/include/asm/msr-index.h create mode 100644 arch/x86/include/asm/msr.h create mode 100644 arch/x86/include/asm/mtrr.h create mode 100644 arch/x86/lib/cmd_boot.c create mode 100644 arch/x86/lib/init_helpers.c create mode 100644 arch/x86/lib/init_wrappers.c create mode 100644 arch/x86/lib/relocate.c
-- 1.7.5.2.317.g391b14

Taken from glibc version 2.14.90 --- arch/x86/include/asm/string.h | 2 +- arch/x86/lib/string.c | 61 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletions(-)
diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h index 3aa6c11..0ad612f 100644 --- a/arch/x86/include/asm/string.h +++ b/arch/x86/include/asm/string.h @@ -14,7 +14,7 @@ extern char * strrchr(const char * s, int c); #undef __HAVE_ARCH_STRCHR extern char * strchr(const char * s, int c);
-#undef __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMCPY extern void * memcpy(void *, const void *, __kernel_size_t);
#undef __HAVE_ARCH_MEMMOVE diff --git a/arch/x86/lib/string.c b/arch/x86/lib/string.c index f2ea7e4..1fde81b 100644 --- a/arch/x86/lib/string.c +++ b/arch/x86/lib/string.c @@ -85,3 +85,64 @@ void *memset(void *dstpp, int c, size_t len)
return dstpp; } + +#define OP_T_THRES 8 +#define OPSIZ (sizeof(op_t)) + +#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) \ +do { \ + int __d0; \ + asm volatile( \ + /* Clear the direction flag, so copying goes forward. */ \ + "cld\n" \ + /* Copy bytes. */ \ + "rep\n" \ + "movsb" : \ + "=D" (dst_bp), "=S" (src_bp), "=c" (__d0) : \ + "0" (dst_bp), "1" (src_bp), "2" (nbytes) : \ + "memory"); \ +} while (0) + +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ +do { \ + int __d0; \ + asm volatile( \ + /* Clear the direction flag, so copying goes forward. */ \ + "cld\n" \ + /* Copy longwords. */ \ + "rep\n" \ + "movsl" : \ + "=D" (dst_bp), "=S" (src_bp), "=c" (__d0) : \ + "0" (dst_bp), "1" (src_bp), "2" ((nbytes) / 4) : \ + "memory"); \ + (nbytes_left) = (nbytes) % 4; \ +} while (0) + +void *memcpy(void *dstpp, const void *srcpp, size_t len) +{ + unsigned long int dstp = (long int)dstpp; + unsigned long int srcp = (long int)srcpp; + + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD(dstp, srcp, (-dstp) % OPSIZ); + + /* Copy from SRCP to DSTP taking advantage of the known + * alignment of DSTP. Number of bytes remaining is put + * in the third argument, i.e. in LEN. This number may + * vary from machine to machine. + */ + WORD_COPY_FWD(dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD(dstp, srcp, len); + + return dstpp; +}

The implementations of memcpy and memset are now the optimised versions from glibc, so use them instead of simple copy loops --- arch/x86/lib/board.c | 17 +++++------------ 1 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index d742fec..ba6b59f 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -188,26 +188,19 @@ static int calculate_relocation_address(void)
static int copy_uboot_to_ram(void) { - ulong *dst_addr = (ulong *)gd->relocaddr; - ulong *src_addr = (ulong *)&__text_start; - ulong *end_addr = (ulong *)&__data_end; + size_t len = (size_t)(&__data_end) - (size_t)(&__text_start);
- while (src_addr < end_addr) - *dst_addr++ = *src_addr++; + memcpy((void *)gd->relocaddr, (void *)&__text_start, len);
return 0; }
static int clear_bss(void) { - void *bss_start = &__bss_start; - void *bss_end = &__bss_end; + ulong dst_addr = (ulong)(&__bss_start) + gd->reloc_off; + size_t len = (size_t)(&__bss_end) - (size_t)(&__bss_start);
- ulong *dst_addr = (ulong *)(bss_start + gd->reloc_off); - ulong *end_addr = (ulong *)(bss_end + gd->reloc_off); - - while (dst_addr < end_addr) - *dst_addr++ = 0x00000000; + memset((void *)dst_addr, 0x00, len);
return 0; }

--- arch/x86/cpu/start.S | 37 +++++++----------- arch/x86/include/asm/u-boot-x86.h | 1 + arch/x86/lib/board.c | 76 +++++++++++++++++++++++------------- 3 files changed, 64 insertions(+), 50 deletions(-)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index f87633b..be21d97 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -95,32 +95,25 @@ car_init_ret: movw $0x85, %ax jmp die
-.globl relocate_code -.type relocate_code, @function -relocate_code: +.globl setup_sdram_environment +.type setup_sdram_environment, @function +setup_sdram_environment: + /* Leave room for Global Data - Round down to 16 byte boundary */ + subl %edx, %eax + andl $~15, %eax + + /* Create a new stack */ + movl %eax, %esp + /* - * SDRAM has been initialised, U-Boot code has been copied into - * RAM, BSS has been cleared and relocation adjustments have been - * made. It is now time to jump into the in-RAM copy of U-Boot - * + * relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr) * %eax = Address of top of stack * %edx = Address of Global Data - * %ecx = Base address of in-RAM copy of U-Boot + * %ecx = Base address of in-RAM copy of U-Boot (ignored) */ - - /* Setup stack in RAM */ - movl %eax, %esp - - /* Setup call address of in-RAM copy of board_init_r() */ - movl $board_init_r, %ebp - addl (GENERATED_GD_RELOC_OFF)(%edx), %ebp - - /* Setup parameters to board_init_r() */ - movl %edx, %eax - movl %ecx, %edx - - /* Jump to in-RAM copy of board_init_r() */ - call *%ebp + movl %eax, %edx + xorl %ecx, %ecx + call relocate_code
die: hlt diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 755f88a..757a8ee 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -61,5 +61,6 @@ u32 isa_map_rom(u32 bus_addr, int size); int video_bios_init(void); int video_init(void);
+void setup_sdram_environment(phys_size_t ram_size, ulong gd_size);
#endif /* _U_BOOT_I386_H_ */ diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index ba6b59f..4736477 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -124,10 +124,10 @@ static void display_flash_config(ulong size) */ typedef int (init_fnc_t) (void);
-static int calculate_relocation_address(void); -static int copy_uboot_to_ram(void); -static int clear_bss(void); -static int do_elf_reloc_fixups(void); +static int calculate_relocation_address(gd_t *); +static int copy_uboot_to_ram(gd_t *); +static int clear_bss(gd_t *); +static int do_elf_reloc_fixups(gd_t *);
init_fnc_t *init_sequence_f[] = { cpu_init_f, @@ -137,10 +137,6 @@ init_fnc_t *init_sequence_f[] = { serial_init, console_init_f, dram_init_f, - calculate_relocation_address, - copy_uboot_to_ram, - clear_bss, - do_elf_reloc_fixups,
NULL, }; @@ -159,7 +155,7 @@ init_fnc_t *init_sequence_r[] = {
gd_t *gd;
-static int calculate_relocation_address(void) +static int calculate_relocation_address(gd_t *id) { ulong text_start = (ulong)&__text_start; ulong bss_end = (ulong)&__bss_end; @@ -167,7 +163,7 @@ static int calculate_relocation_address(void) ulong rel_offset;
/* Calculate destination RAM Address and relocation offset */ - dest_addr = gd->ram_size; + dest_addr = id->start_addr_sp; dest_addr -= CONFIG_SYS_STACK_SIZE; dest_addr -= (bss_end - text_start);
@@ -179,33 +175,32 @@ static int calculate_relocation_address(void)
rel_offset = dest_addr - text_start;
- gd->start_addr_sp = gd->ram_size; - gd->relocaddr = dest_addr; - gd->reloc_off = rel_offset; + id->relocaddr = dest_addr; + id->reloc_off = rel_offset;
return 0; }
-static int copy_uboot_to_ram(void) +static int copy_uboot_to_ram(gd_t *id) { - size_t len = (size_t)(&__data_end) - (size_t)(&__text_start); + size_t len = (size_t)&__data_end - (size_t)&__text_start;
- memcpy((void *)gd->relocaddr, (void *)&__text_start, len); + memcpy((void *)id->relocaddr, (void *)&__text_start, len);
return 0; }
-static int clear_bss(void) +static int clear_bss(gd_t *id) { - ulong dst_addr = (ulong)(&__bss_start) + gd->reloc_off; - size_t len = (size_t)(&__bss_end) - (size_t)(&__bss_start); + ulong dst_addr = (ulong)&__bss_start + id->reloc_off; + size_t len = (size_t)&__bss_end - (size_t)&__bss_start;
memset((void *)dst_addr, 0x00, len);
return 0; }
-static int do_elf_reloc_fixups(void) +static int do_elf_reloc_fixups(gd_t *id) { Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); @@ -225,13 +220,13 @@ static int do_elf_reloc_fixups(void)
/* Switch to the in-RAM version */ offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + - gd->reloc_off); + id->reloc_off);
/* Check that the target points into .text */ if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE && *offset_ptr_ram < (CONFIG_SYS_TEXT_BASE + size)) { - *offset_ptr_ram += gd->reloc_off; + *offset_ptr_ram += id->reloc_off; } } } while (re_src++ < re_end); @@ -251,10 +246,35 @@ void board_init_f(ulong boot_flags) hang(); }
- gd->flags |= GD_FLG_RELOC; + /* SDRAM is now initialised setup a new stack in SDRAM */ + setup_sdram_environment(gd->ram_size, GENERATED_GBL_DATA_SIZE); + + /* NOTREACHED - relocate_code() does not return */ + while (1) + ; +}
- /* Enter the relocated U-Boot! */ - relocate_code(gd->start_addr_sp, gd, gd->relocaddr); +typedef void (board_init_r_t) (gd_t *, ulong); + +void relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr) +{ + board_init_r_t *board_init_r_func; + + /* We are running from flash, but the stack is now in SDRAM */ + + /* gd is still in CAR - Copy it into SDRAM */ + memcpy(id, gd, sizeof(gd_t)); + + id->start_addr_sp = stack_ptr; + + calculate_relocation_address(id); + copy_uboot_to_ram(id); + clear_bss(id); + do_elf_reloc_fixups(id); + + board_init_r_func = board_init_r; + board_init_r_func += id->reloc_off; + board_init_r_func(id, id->relocaddr);
/* NOTREACHED - relocate_code() does not return */ while (1) @@ -270,14 +290,14 @@ void board_init_r(gd_t *id, ulong dest_addr) ulong size; #endif static bd_t bd_data; - static gd_t gd_data; init_fnc_t **init_fnc_ptr;
show_boot_progress(0x21);
/* Global data pointer is now writable */ - gd = &gd_data; - memcpy(gd, id, sizeof(gd_t)); + gd = id; + + gd->flags |= GD_FLG_RELOC;
/* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("" : : : "memory");

Imported from Linux 3.1 with a few modifications to suit U-Boot --- arch/x86/include/asm/msr-index.h | 447 ++++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/msr.h | 216 ++++++++++++++++++ arch/x86/include/asm/mtrr.h | 203 +++++++++++++++++ 3 files changed, 866 insertions(+), 0 deletions(-) create mode 100644 arch/x86/include/asm/msr-index.h create mode 100644 arch/x86/include/asm/msr.h create mode 100644 arch/x86/include/asm/mtrr.h
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h new file mode 100644 index 0000000..2d4a20a --- /dev/null +++ b/arch/x86/include/asm/msr-index.h @@ -0,0 +1,447 @@ +#ifndef _ASM_X86_MSR_INDEX_H +#define _ASM_X86_MSR_INDEX_H + +/* CPU model specific register (MSR) numbers */ + +/* x86-64 specific MSRs */ +#define MSR_EFER 0xc0000080 /* extended feature register */ +#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target */ +#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */ +#define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target */ +#define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */ +#define MSR_FS_BASE 0xc0000100 /* 64bit FS base */ +#define MSR_GS_BASE 0xc0000101 /* 64bit GS base */ +#define MSR_KERNEL_GS_BASE 0xc0000102 /* SwapGS GS shadow */ +#define MSR_TSC_AUX 0xc0000103 /* Auxiliary TSC */ + +/* EFER bits: */ +#define _EFER_SCE 0 /* SYSCALL/SYSRET */ +#define _EFER_LME 8 /* Long mode enable */ +#define _EFER_LMA 10 /* Long mode active (read-only) */ +#define _EFER_NX 11 /* No execute enable */ +#define _EFER_SVME 12 /* Enable virtualization */ +#define _EFER_LMSLE 13 /* Long Mode Segment Limit Enable */ +#define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */ + +#define EFER_SCE (1<<_EFER_SCE) +#define EFER_LME (1<<_EFER_LME) +#define EFER_LMA (1<<_EFER_LMA) +#define EFER_NX (1<<_EFER_NX) +#define EFER_SVME (1<<_EFER_SVME) +#define EFER_LMSLE (1<<_EFER_LMSLE) +#define EFER_FFXSR (1<<_EFER_FFXSR) + +/* Intel MSRs. Some also available on other CPUs */ +#define MSR_IA32_PERFCTR0 0x000000c1 +#define MSR_IA32_PERFCTR1 0x000000c2 +#define MSR_FSB_FREQ 0x000000cd + +#define MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2 +#define NHM_C3_AUTO_DEMOTE (1UL << 25) +#define NHM_C1_AUTO_DEMOTE (1UL << 26) +#define ATM_LNC_C6_AUTO_DEMOTE (1UL << 25) + +#define MSR_MTRRcap 0x000000fe +#define MSR_IA32_BBL_CR_CTL 0x00000119 +#define MSR_IA32_BBL_CR_CTL3 0x0000011e + +#define MSR_IA32_SYSENTER_CS 0x00000174 +#define MSR_IA32_SYSENTER_ESP 0x00000175 +#define MSR_IA32_SYSENTER_EIP 0x00000176 + +#define MSR_IA32_MCG_CAP 0x00000179 +#define MSR_IA32_MCG_STATUS 0x0000017a +#define MSR_IA32_MCG_CTL 0x0000017b + +#define MSR_OFFCORE_RSP_0 0x000001a6 +#define MSR_OFFCORE_RSP_1 0x000001a7 + +#define MSR_IA32_PEBS_ENABLE 0x000003f1 +#define MSR_IA32_DS_AREA 0x00000600 +#define MSR_IA32_PERF_CAPABILITIES 0x00000345 + +#define MSR_MTRRfix64K_00000 0x00000250 +#define MSR_MTRRfix16K_80000 0x00000258 +#define MSR_MTRRfix16K_A0000 0x00000259 +#define MSR_MTRRfix4K_C0000 0x00000268 +#define MSR_MTRRfix4K_C8000 0x00000269 +#define MSR_MTRRfix4K_D0000 0x0000026a +#define MSR_MTRRfix4K_D8000 0x0000026b +#define MSR_MTRRfix4K_E0000 0x0000026c +#define MSR_MTRRfix4K_E8000 0x0000026d +#define MSR_MTRRfix4K_F0000 0x0000026e +#define MSR_MTRRfix4K_F8000 0x0000026f +#define MSR_MTRRdefType 0x000002ff + +#define MSR_IA32_CR_PAT 0x00000277 + +#define MSR_IA32_DEBUGCTLMSR 0x000001d9 +#define MSR_IA32_LASTBRANCHFROMIP 0x000001db +#define MSR_IA32_LASTBRANCHTOIP 0x000001dc +#define MSR_IA32_LASTINTFROMIP 0x000001dd +#define MSR_IA32_LASTINTTOIP 0x000001de + +/* DEBUGCTLMSR bits (others vary by model): */ +#define DEBUGCTLMSR_LBR (1UL << 0) +#define DEBUGCTLMSR_BTF (1UL << 1) +#define DEBUGCTLMSR_TR (1UL << 6) +#define DEBUGCTLMSR_BTS (1UL << 7) +#define DEBUGCTLMSR_BTINT (1UL << 8) +#define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9) +#define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10) +#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11) + +#define MSR_IA32_MC0_CTL 0x00000400 +#define MSR_IA32_MC0_STATUS 0x00000401 +#define MSR_IA32_MC0_ADDR 0x00000402 +#define MSR_IA32_MC0_MISC 0x00000403 + +#define MSR_AMD64_MC0_MASK 0xc0010044 + +#define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x)) +#define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4*(x)) +#define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x)) +#define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x)) + +#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x)) + +/* These are consecutive and not in the normal 4er MCE bank block */ +#define MSR_IA32_MC0_CTL2 0x00000280 +#define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x)) + +#define MSR_P6_PERFCTR0 0x000000c1 +#define MSR_P6_PERFCTR1 0x000000c2 +#define MSR_P6_EVNTSEL0 0x00000186 +#define MSR_P6_EVNTSEL1 0x00000187 + +/* AMD64 MSRs. Not complete. See the architecture manual for a more + complete list. */ + +#define MSR_AMD64_PATCH_LEVEL 0x0000008b +#define MSR_AMD64_NB_CFG 0xc001001f +#define MSR_AMD64_PATCH_LOADER 0xc0010020 +#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140 +#define MSR_AMD64_OSVW_STATUS 0xc0010141 +#define MSR_AMD64_DC_CFG 0xc0011022 +#define MSR_AMD64_IBSFETCHCTL 0xc0011030 +#define MSR_AMD64_IBSFETCHLINAD 0xc0011031 +#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032 +#define MSR_AMD64_IBSOPCTL 0xc0011033 +#define MSR_AMD64_IBSOPRIP 0xc0011034 +#define MSR_AMD64_IBSOPDATA 0xc0011035 +#define MSR_AMD64_IBSOPDATA2 0xc0011036 +#define MSR_AMD64_IBSOPDATA3 0xc0011037 +#define MSR_AMD64_IBSDCLINAD 0xc0011038 +#define MSR_AMD64_IBSDCPHYSAD 0xc0011039 +#define MSR_AMD64_IBSCTL 0xc001103a +#define MSR_AMD64_IBSBRTARGET 0xc001103b + +/* Fam 15h MSRs */ +#define MSR_F15H_PERF_CTL 0xc0010200 +#define MSR_F15H_PERF_CTR 0xc0010201 + +/* Fam 10h MSRs */ +#define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058 +#define FAM10H_MMIO_CONF_ENABLE (1<<0) +#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf +#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2 +#define FAM10H_MMIO_CONF_BASE_MASK 0xfffffffULL +#define FAM10H_MMIO_CONF_BASE_SHIFT 20 +#define MSR_FAM10H_NODE_ID 0xc001100c + +/* K8 MSRs */ +#define MSR_K8_TOP_MEM1 0xc001001a +#define MSR_K8_TOP_MEM2 0xc001001d +#define MSR_K8_SYSCFG 0xc0010010 +#define MSR_K8_INT_PENDING_MSG 0xc0010055 +/* C1E active bits in int pending message */ +#define K8_INTP_C1E_ACTIVE_MASK 0x18000000 +#define MSR_K8_TSEG_ADDR 0xc0010112 +#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */ +#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */ +#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */ + +/* K7 MSRs */ +#define MSR_K7_EVNTSEL0 0xc0010000 +#define MSR_K7_PERFCTR0 0xc0010004 +#define MSR_K7_EVNTSEL1 0xc0010001 +#define MSR_K7_PERFCTR1 0xc0010005 +#define MSR_K7_EVNTSEL2 0xc0010002 +#define MSR_K7_PERFCTR2 0xc0010006 +#define MSR_K7_EVNTSEL3 0xc0010003 +#define MSR_K7_PERFCTR3 0xc0010007 +#define MSR_K7_CLK_CTL 0xc001001b +#define MSR_K7_HWCR 0xc0010015 +#define MSR_K7_FID_VID_CTL 0xc0010041 +#define MSR_K7_FID_VID_STATUS 0xc0010042 + +/* K6 MSRs */ +#define MSR_K6_WHCR 0xc0000082 +#define MSR_K6_UWCCR 0xc0000085 +#define MSR_K6_EPMR 0xc0000086 +#define MSR_K6_PSOR 0xc0000087 +#define MSR_K6_PFIR 0xc0000088 + +/* Centaur-Hauls/IDT defined MSRs. */ +#define MSR_IDT_FCR1 0x00000107 +#define MSR_IDT_FCR2 0x00000108 +#define MSR_IDT_FCR3 0x00000109 +#define MSR_IDT_FCR4 0x0000010a + +#define MSR_IDT_MCR0 0x00000110 +#define MSR_IDT_MCR1 0x00000111 +#define MSR_IDT_MCR2 0x00000112 +#define MSR_IDT_MCR3 0x00000113 +#define MSR_IDT_MCR4 0x00000114 +#define MSR_IDT_MCR5 0x00000115 +#define MSR_IDT_MCR6 0x00000116 +#define MSR_IDT_MCR7 0x00000117 +#define MSR_IDT_MCR_CTRL 0x00000120 + +/* VIA Cyrix defined MSRs*/ +#define MSR_VIA_FCR 0x00001107 +#define MSR_VIA_LONGHAUL 0x0000110a +#define MSR_VIA_RNG 0x0000110b +#define MSR_VIA_BCR2 0x00001147 + +/* Transmeta defined MSRs */ +#define MSR_TMTA_LONGRUN_CTRL 0x80868010 +#define MSR_TMTA_LONGRUN_FLAGS 0x80868011 +#define MSR_TMTA_LRTI_READOUT 0x80868018 +#define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a + +/* Intel defined MSRs. */ +#define MSR_IA32_P5_MC_ADDR 0x00000000 +#define MSR_IA32_P5_MC_TYPE 0x00000001 +#define MSR_IA32_TSC 0x00000010 +#define MSR_IA32_PLATFORM_ID 0x00000017 +#define MSR_IA32_EBL_CR_POWERON 0x0000002a +#define MSR_EBC_FREQUENCY_ID 0x0000002c +#define MSR_IA32_FEATURE_CONTROL 0x0000003a + +#define FEATURE_CONTROL_LOCKED (1<<0) +#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) +#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2) + +#define MSR_IA32_APICBASE 0x0000001b +#define MSR_IA32_APICBASE_BSP (1<<8) +#define MSR_IA32_APICBASE_ENABLE (1<<11) +#define MSR_IA32_APICBASE_BASE (0xfffff<<12) + +#define MSR_IA32_UCODE_WRITE 0x00000079 +#define MSR_IA32_UCODE_REV 0x0000008b + +#define MSR_IA32_PERF_STATUS 0x00000198 +#define MSR_IA32_PERF_CTL 0x00000199 + +#define MSR_IA32_MPERF 0x000000e7 +#define MSR_IA32_APERF 0x000000e8 + +#define MSR_IA32_THERM_CONTROL 0x0000019a +#define MSR_IA32_THERM_INTERRUPT 0x0000019b + +#define THERM_INT_HIGH_ENABLE (1 << 0) +#define THERM_INT_LOW_ENABLE (1 << 1) +#define THERM_INT_PLN_ENABLE (1 << 24) + +#define MSR_IA32_THERM_STATUS 0x0000019c + +#define THERM_STATUS_PROCHOT (1 << 0) +#define THERM_STATUS_POWER_LIMIT (1 << 10) + +#define MSR_THERM2_CTL 0x0000019d + +#define MSR_THERM2_CTL_TM_SELECT (1ULL << 16) + +#define MSR_IA32_MISC_ENABLE 0x000001a0 + +#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2 + +#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 + +#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1 + +#define PACKAGE_THERM_STATUS_PROCHOT (1 << 0) +#define PACKAGE_THERM_STATUS_POWER_LIMIT (1 << 10) + +#define MSR_IA32_PACKAGE_THERM_INTERRUPT 0x000001b2 + +#define PACKAGE_THERM_INT_HIGH_ENABLE (1 << 0) +#define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1) +#define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24) + +/* Thermal Thresholds Support */ +#define THERM_INT_THRESHOLD0_ENABLE (1 << 15) +#define THERM_SHIFT_THRESHOLD0 8 +#define THERM_MASK_THRESHOLD0 (0x7f << THERM_SHIFT_THRESHOLD0) +#define THERM_INT_THRESHOLD1_ENABLE (1 << 23) +#define THERM_SHIFT_THRESHOLD1 16 +#define THERM_MASK_THRESHOLD1 (0x7f << THERM_SHIFT_THRESHOLD1) +#define THERM_STATUS_THRESHOLD0 (1 << 6) +#define THERM_LOG_THRESHOLD0 (1 << 7) +#define THERM_STATUS_THRESHOLD1 (1 << 8) +#define THERM_LOG_THRESHOLD1 (1 << 9) + +/* MISC_ENABLE bits: architectural */ +#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0) +#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1) +#define MSR_IA32_MISC_ENABLE_EMON (1ULL << 7) +#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1ULL << 11) +#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1ULL << 12) +#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << 16) +#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18) +#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << 22) +#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1ULL << 23) +#define MSR_IA32_MISC_ENABLE_XD_DISABLE (1ULL << 34) + +/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */ +#define MSR_IA32_MISC_ENABLE_X87_COMPAT (1ULL << 2) +#define MSR_IA32_MISC_ENABLE_TM1 (1ULL << 3) +#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE (1ULL << 4) +#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE (1ULL << 6) +#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK (1ULL << 8) +#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE (1ULL << 9) +#define MSR_IA32_MISC_ENABLE_FERR (1ULL << 10) +#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX (1ULL << 10) +#define MSR_IA32_MISC_ENABLE_TM2 (1ULL << 13) +#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE (1ULL << 19) +#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << 20) +#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT (1ULL << 24) +#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE (1ULL << 37) +#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38) +#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39) + +/* P4/Xeon+ specific */ +#define MSR_IA32_MCG_EAX 0x00000180 +#define MSR_IA32_MCG_EBX 0x00000181 +#define MSR_IA32_MCG_ECX 0x00000182 +#define MSR_IA32_MCG_EDX 0x00000183 +#define MSR_IA32_MCG_ESI 0x00000184 +#define MSR_IA32_MCG_EDI 0x00000185 +#define MSR_IA32_MCG_EBP 0x00000186 +#define MSR_IA32_MCG_ESP 0x00000187 +#define MSR_IA32_MCG_EFLAGS 0x00000188 +#define MSR_IA32_MCG_EIP 0x00000189 +#define MSR_IA32_MCG_RESERVED 0x0000018a + +/* Pentium IV performance counter MSRs */ +#define MSR_P4_BPU_PERFCTR0 0x00000300 +#define MSR_P4_BPU_PERFCTR1 0x00000301 +#define MSR_P4_BPU_PERFCTR2 0x00000302 +#define MSR_P4_BPU_PERFCTR3 0x00000303 +#define MSR_P4_MS_PERFCTR0 0x00000304 +#define MSR_P4_MS_PERFCTR1 0x00000305 +#define MSR_P4_MS_PERFCTR2 0x00000306 +#define MSR_P4_MS_PERFCTR3 0x00000307 +#define MSR_P4_FLAME_PERFCTR0 0x00000308 +#define MSR_P4_FLAME_PERFCTR1 0x00000309 +#define MSR_P4_FLAME_PERFCTR2 0x0000030a +#define MSR_P4_FLAME_PERFCTR3 0x0000030b +#define MSR_P4_IQ_PERFCTR0 0x0000030c +#define MSR_P4_IQ_PERFCTR1 0x0000030d +#define MSR_P4_IQ_PERFCTR2 0x0000030e +#define MSR_P4_IQ_PERFCTR3 0x0000030f +#define MSR_P4_IQ_PERFCTR4 0x00000310 +#define MSR_P4_IQ_PERFCTR5 0x00000311 +#define MSR_P4_BPU_CCCR0 0x00000360 +#define MSR_P4_BPU_CCCR1 0x00000361 +#define MSR_P4_BPU_CCCR2 0x00000362 +#define MSR_P4_BPU_CCCR3 0x00000363 +#define MSR_P4_MS_CCCR0 0x00000364 +#define MSR_P4_MS_CCCR1 0x00000365 +#define MSR_P4_MS_CCCR2 0x00000366 +#define MSR_P4_MS_CCCR3 0x00000367 +#define MSR_P4_FLAME_CCCR0 0x00000368 +#define MSR_P4_FLAME_CCCR1 0x00000369 +#define MSR_P4_FLAME_CCCR2 0x0000036a +#define MSR_P4_FLAME_CCCR3 0x0000036b +#define MSR_P4_IQ_CCCR0 0x0000036c +#define MSR_P4_IQ_CCCR1 0x0000036d +#define MSR_P4_IQ_CCCR2 0x0000036e +#define MSR_P4_IQ_CCCR3 0x0000036f +#define MSR_P4_IQ_CCCR4 0x00000370 +#define MSR_P4_IQ_CCCR5 0x00000371 +#define MSR_P4_ALF_ESCR0 0x000003ca +#define MSR_P4_ALF_ESCR1 0x000003cb +#define MSR_P4_BPU_ESCR0 0x000003b2 +#define MSR_P4_BPU_ESCR1 0x000003b3 +#define MSR_P4_BSU_ESCR0 0x000003a0 +#define MSR_P4_BSU_ESCR1 0x000003a1 +#define MSR_P4_CRU_ESCR0 0x000003b8 +#define MSR_P4_CRU_ESCR1 0x000003b9 +#define MSR_P4_CRU_ESCR2 0x000003cc +#define MSR_P4_CRU_ESCR3 0x000003cd +#define MSR_P4_CRU_ESCR4 0x000003e0 +#define MSR_P4_CRU_ESCR5 0x000003e1 +#define MSR_P4_DAC_ESCR0 0x000003a8 +#define MSR_P4_DAC_ESCR1 0x000003a9 +#define MSR_P4_FIRM_ESCR0 0x000003a4 +#define MSR_P4_FIRM_ESCR1 0x000003a5 +#define MSR_P4_FLAME_ESCR0 0x000003a6 +#define MSR_P4_FLAME_ESCR1 0x000003a7 +#define MSR_P4_FSB_ESCR0 0x000003a2 +#define MSR_P4_FSB_ESCR1 0x000003a3 +#define MSR_P4_IQ_ESCR0 0x000003ba +#define MSR_P4_IQ_ESCR1 0x000003bb +#define MSR_P4_IS_ESCR0 0x000003b4 +#define MSR_P4_IS_ESCR1 0x000003b5 +#define MSR_P4_ITLB_ESCR0 0x000003b6 +#define MSR_P4_ITLB_ESCR1 0x000003b7 +#define MSR_P4_IX_ESCR0 0x000003c8 +#define MSR_P4_IX_ESCR1 0x000003c9 +#define MSR_P4_MOB_ESCR0 0x000003aa +#define MSR_P4_MOB_ESCR1 0x000003ab +#define MSR_P4_MS_ESCR0 0x000003c0 +#define MSR_P4_MS_ESCR1 0x000003c1 +#define MSR_P4_PMH_ESCR0 0x000003ac +#define MSR_P4_PMH_ESCR1 0x000003ad +#define MSR_P4_RAT_ESCR0 0x000003bc +#define MSR_P4_RAT_ESCR1 0x000003bd +#define MSR_P4_SAAT_ESCR0 0x000003ae +#define MSR_P4_SAAT_ESCR1 0x000003af +#define MSR_P4_SSU_ESCR0 0x000003be +#define MSR_P4_SSU_ESCR1 0x000003bf /* guess: not in manual */ + +#define MSR_P4_TBPU_ESCR0 0x000003c2 +#define MSR_P4_TBPU_ESCR1 0x000003c3 +#define MSR_P4_TC_ESCR0 0x000003c4 +#define MSR_P4_TC_ESCR1 0x000003c5 +#define MSR_P4_U2L_ESCR0 0x000003b0 +#define MSR_P4_U2L_ESCR1 0x000003b1 + +#define MSR_P4_PEBS_MATRIX_VERT 0x000003f2 + +/* Intel Core-based CPU performance counters */ +#define MSR_CORE_PERF_FIXED_CTR0 0x00000309 +#define MSR_CORE_PERF_FIXED_CTR1 0x0000030a +#define MSR_CORE_PERF_FIXED_CTR2 0x0000030b +#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x0000038d +#define MSR_CORE_PERF_GLOBAL_STATUS 0x0000038e +#define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390 + +/* Geode defined MSRs */ +#define MSR_GEODE_BUSCONT_CONF0 0x00001900 + +/* Intel VT MSRs */ +#define MSR_IA32_VMX_BASIC 0x00000480 +#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481 +#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482 +#define MSR_IA32_VMX_EXIT_CTLS 0x00000483 +#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484 +#define MSR_IA32_VMX_MISC 0x00000485 +#define MSR_IA32_VMX_CR0_FIXED0 0x00000486 +#define MSR_IA32_VMX_CR0_FIXED1 0x00000487 +#define MSR_IA32_VMX_CR4_FIXED0 0x00000488 +#define MSR_IA32_VMX_CR4_FIXED1 0x00000489 +#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a +#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b +#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c + +/* AMD-V MSRs */ + +#define MSR_VM_CR 0xc0010114 +#define MSR_VM_IGNNE 0xc0010115 +#define MSR_VM_HSAVE_PA 0xc0010117 + +#endif /* _ASM_X86_MSR_INDEX_H */ diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h new file mode 100644 index 0000000..1865c64 --- /dev/null +++ b/arch/x86/include/asm/msr.h @@ -0,0 +1,216 @@ +#ifndef _ASM_X86_MSR_H +#define _ASM_X86_MSR_H + +#include <asm/msr-index.h> + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> +#include <linux/ioctl.h> + +#define X86_IOC_RDMSR_REGS _IOWR('c', 0xA0, __u32[8]) +#define X86_IOC_WRMSR_REGS _IOWR('c', 0xA1, __u32[8]) + +#ifdef __KERNEL__ + +#include <asm/errno.h> + +struct msr { + union { + struct { + u32 l; + u32 h; + }; + u64 q; + }; +}; + +struct msr_info { + u32 msr_no; + struct msr reg; + struct msr *msrs; + int err; +}; + +struct msr_regs_info { + u32 *regs; + int err; +}; + +static inline unsigned long long native_read_tscp(unsigned int *aux) +{ + unsigned long low, high; + asm volatile(".byte 0x0f,0x01,0xf9" + : "=a" (low), "=d" (high), "=c" (*aux)); + return low | ((u64)high << 32); +} + +/* + * both i386 and x86_64 returns 64-bit value in edx:eax, but gcc's "A" + * constraint has different meanings. For i386, "A" means exactly + * edx:eax, while for x86_64 it doesn't mean rdx:rax or edx:eax. Instead, + * it means rax *or* rdx. + */ +#ifdef CONFIG_X86_64 +#define DECLARE_ARGS(val, low, high) unsigned low, high +#define EAX_EDX_VAL(val, low, high) ((low) | ((u64)(high) << 32)) +#define EAX_EDX_ARGS(val, low, high) "a" (low), "d" (high) +#define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high) +#else +#define DECLARE_ARGS(val, low, high) unsigned long long val +#define EAX_EDX_VAL(val, low, high) (val) +#define EAX_EDX_ARGS(val, low, high) "A" (val) +#define EAX_EDX_RET(val, low, high) "=A" (val) +#endif + +static inline unsigned long long native_read_msr(unsigned int msr) +{ + DECLARE_ARGS(val, low, high); + + asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr)); + return EAX_EDX_VAL(val, low, high); +} + +static inline void native_write_msr(unsigned int msr, + unsigned low, unsigned high) +{ + asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); +} + +extern unsigned long long native_read_tsc(void); + +extern int native_rdmsr_safe_regs(u32 regs[8]); +extern int native_wrmsr_safe_regs(u32 regs[8]); + +static inline unsigned long long native_read_pmc(int counter) +{ + DECLARE_ARGS(val, low, high); + + asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter)); + return EAX_EDX_VAL(val, low, high); +} + +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#include <errno.h> +/* + * Access to machine-specific registers (available on 586 and better only) + * Note: the rd* operations modify the parameters directly (without using + * pointer indirection), this allows gcc to optimize better + */ + +#define rdmsr(msr, val1, val2) \ +do { \ + u64 __val = native_read_msr((msr)); \ + (void)((val1) = (u32)__val); \ + (void)((val2) = (u32)(__val >> 32)); \ +} while (0) + +static inline void wrmsr(unsigned msr, unsigned low, unsigned high) +{ + native_write_msr(msr, low, high); +} + +#define rdmsrl(msr, val) \ + ((val) = native_read_msr((msr))) + +#define wrmsrl(msr, val) \ + native_write_msr((msr), (u32)((u64)(val)), (u32)((u64)(val) >> 32)) + +/* rdmsr with exception handling */ +#define rdmsr_safe(msr, p1, p2) \ +({ \ + int __err; \ + u64 __val = native_read_msr_safe((msr), &__err); \ + (*p1) = (u32)__val; \ + (*p2) = (u32)(__val >> 32); \ + __err; \ +}) + +static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) +{ + u32 gprs[8] = { 0 }; + int err; + + gprs[1] = msr; + gprs[7] = 0x9c5a203a; + + err = native_rdmsr_safe_regs(gprs); + + *p = gprs[0] | ((u64)gprs[2] << 32); + + return err; +} + +static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) +{ + u32 gprs[8] = { 0 }; + + gprs[0] = (u32)val; + gprs[1] = msr; + gprs[2] = val >> 32; + gprs[7] = 0x9c5a203a; + + return native_wrmsr_safe_regs(gprs); +} + +static inline int rdmsr_safe_regs(u32 regs[8]) +{ + return native_rdmsr_safe_regs(regs); +} + +static inline int wrmsr_safe_regs(u32 regs[8]) +{ + return native_wrmsr_safe_regs(regs); +} + +#define rdtscl(low) \ + ((low) = (u32)__native_read_tsc()) + +#define rdtscll(val) \ + ((val) = __native_read_tsc()) + +#define rdpmc(counter, low, high) \ +do { \ + u64 _l = native_read_pmc((counter)); \ + (low) = (u32)_l; \ + (high) = (u32)(_l >> 32); \ +} while (0) + +#define rdtscp(low, high, aux) \ +do { \ + unsigned long long _val = native_read_tscp(&(aux)); \ + (low) = (u32)_val; \ + (high) = (u32)(_val >> 32); \ +} while (0) + +#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux)) + +#endif /* !CONFIG_PARAVIRT */ + + +#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \ + (u32)((val) >> 32)) + +#define write_tsc(val1, val2) wrmsr(MSR_IA32_TSC, (val1), (val2)) + +#define write_rdtscp_aux(val) wrmsr(MSR_TSC_AUX, (val), 0) + +struct msr *msrs_alloc(void); +void msrs_free(struct msr *msrs); + +#ifdef CONFIG_SMP +int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); +int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); +void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); +void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); +int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); +int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); +int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); +int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); + +#endif /* CONFIG_SMP */ +#endif /* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_X86_MSR_H */ diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h new file mode 100644 index 0000000..b75203c --- /dev/null +++ b/arch/x86/include/asm/mtrr.h @@ -0,0 +1,203 @@ +/* Generic MTRR (Memory Type Range Register) ioctls. + + Copyright (C) 1997-1999 Richard Gooch + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Richard Gooch may be reached by email at rgooch@atnf.csiro.au + The postal address is: + Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. +*/ +#ifndef _ASM_X86_MTRR_H +#define _ASM_X86_MTRR_H + +#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) +#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> +#include <linux/ioctl.h> +#include <errno.h> + +#define MTRR_IOCTL_BASE 'M' + +struct mtrr_sentry { + unsigned long base; /* Base address */ + unsigned int size; /* Size of region */ + unsigned int type; /* Type of region */ +}; + +/* + * Warning: this structure has a different order from i386 + * on x86-64. The 32bit emulation code takes care of that. + * But you need to use this for 64bit, otherwise your X server + * will break. + */ + +#ifdef __i386__ +struct mtrr_gentry { + unsigned int regnum; /* Register number */ + unsigned long base; /* Base address */ + unsigned int size; /* Size of region */ + unsigned int type; /* Type of region */ +}; + +#else /* __i386__ */ + +struct mtrr_gentry { + unsigned long base; /* Base address */ + unsigned int size; /* Size of region */ + unsigned int regnum; /* Register number */ + unsigned int type; /* Type of region */ +}; +#endif /* !__i386__ */ + +struct mtrr_var_range { + __u32 base_lo; + __u32 base_hi; + __u32 mask_lo; + __u32 mask_hi; +}; + +/* + * In the Intel processor's MTRR interface, the MTRR type is always held in + * an 8 bit field: + */ +typedef __u8 mtrr_type; + +#define MTRR_NUM_FIXED_RANGES 88 +#define MTRR_MAX_VAR_RANGES 256 + +struct mtrr_state_type { + struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES]; + mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES]; + unsigned char enabled; + unsigned char have_fixed; + mtrr_type def_type; +}; + +/* These are the various ioctls */ +#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry) +#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry) +#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry) +#define MTRRIOC_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry) +#define MTRRIOC_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry) +#define MTRRIOC_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry) +#define MTRRIOC_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry) +#define MTRRIOC_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry) +#define MTRRIOC_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry) +#define MTRRIOC_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry) + +/* These are the region types */ +#define MTRR_TYPE_UNCACHABLE 0 +#define MTRR_TYPE_WRCOMB 1 +/*#define MTRR_TYPE_ 2*/ +/*#define MTRR_TYPE_ 3*/ +#define MTRR_TYPE_WRTHROUGH 4 +#define MTRR_TYPE_WRPROT 5 +#define MTRR_TYPE_WRBACK 6 +#define MTRR_NUM_TYPES 7 + +#ifdef __KERNEL__ + +/* The following functions are for use by other drivers */ +# ifdef CONFIG_MTRR +extern u8 mtrr_type_lookup(u64 addr, u64 end); +extern void mtrr_save_fixed_ranges(void *); +extern void mtrr_save_state(void); +extern int mtrr_add(unsigned long base, unsigned long size, + unsigned int type, bool increment); +extern int mtrr_add_page(unsigned long base, unsigned long size, + unsigned int type, bool increment); +extern int mtrr_del(int reg, unsigned long base, unsigned long size); +extern int mtrr_del_page(int reg, unsigned long base, unsigned long size); +extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi); +extern void mtrr_ap_init(void); +extern void mtrr_bp_init(void); +extern void set_mtrr_aps_delayed_init(void); +extern void mtrr_aps_init(void); +extern void mtrr_bp_restore(void); +extern int mtrr_trim_uncached_memory(unsigned long end_pfn); +extern int amd_special_default_mtrr(void); +# else +static inline u8 mtrr_type_lookup(u64 addr, u64 end) +{ + /* + * Return no-MTRRs: + */ + return 0xff; +} +#define mtrr_save_fixed_ranges(arg) do {} while (0) +#define mtrr_save_state() do {} while (0) +static inline int mtrr_del(int reg, unsigned long base, unsigned long size) +{ + return -ENODEV; +} +static inline int mtrr_del_page(int reg, unsigned long base, unsigned long size) +{ + return -ENODEV; +} +static inline int mtrr_trim_uncached_memory(unsigned long end_pfn) +{ + return 0; +} +static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) +{ +} + +#define mtrr_ap_init() do {} while (0) +#define mtrr_bp_init() do {} while (0) +#define set_mtrr_aps_delayed_init() do {} while (0) +#define mtrr_aps_init() do {} while (0) +#define mtrr_bp_restore() do {} while (0) +# endif + +#ifdef CONFIG_COMPAT +#include <linux/compat.h> + +struct mtrr_sentry32 { + compat_ulong_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ +}; + +struct mtrr_gentry32 { + compat_ulong_t regnum; /* Register number */ + compat_uint_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ +}; + +#define MTRR_IOCTL_BASE 'M' + +#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32) +#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32) +#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32) +#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32) +#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32) +#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32) +#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32) +#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32) +#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32) +#define MTRRIOC32_KILL_PAGE_ENTRY \ + _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32) +#endif /* CONFIG_COMPAT */ + +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_X86_MTRR_H */

--- arch/x86/cpu/cpu.c | 16 +++++++++++----- arch/x86/include/asm/u-boot-x86.h | 2 ++ arch/x86/lib/board.c | 3 +++ 3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 61d0b69..a8069ad 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -105,6 +105,16 @@ int cpu_init_f(void) __attribute__((weak, alias("x86_cpu_init_f")));
int x86_cpu_init_r(void) { + reload_gdt(); + + /* Initialize core interrupt and exception functionality of CPU */ + cpu_init_interrupts(); + return 0; +} +int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r"))); + +int x86_init_cache(void) +{ const u32 nw_cd_rst = ~(X86_CR0_NW | X86_CR0_CD);
/* turn on the cache and disable write through */ @@ -113,13 +123,9 @@ int x86_cpu_init_r(void) "movl %%eax, %%cr0\n" "wbinvd\n" : : "i" (nw_cd_rst) : "eax");
- reload_gdt(); - - /* Initialize core interrupt and exception functionality of CPU */ - cpu_init_interrupts(); return 0; } -int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r"))); +int init_cache(void) __attribute__((weak, alias("x86_init_cache")));
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 757a8ee..eaa50cc 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -37,6 +37,8 @@ int x86_cpu_init_r(void); int cpu_init_r(void); int x86_cpu_init_f(void); int cpu_init_f(void); +int x86_init_cache(void); +int init_cache(void);
/* cpu/.../timer.c */ void timer_isr(void *); diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 4736477..fb2b92c 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -267,6 +267,9 @@ void relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr)
id->start_addr_sp = stack_ptr;
+ if (init_cache() != 0) + hang(); + calculate_relocation_address(id); copy_uboot_to_ram(id); clear_bss(id);

Hi Graeme,
On Fri, Dec 23, 2011 at 4:25 AM, Graeme Russ graeme.russ@gmail.com wrote:
arch/x86/cpu/cpu.c         |  16 +++++++++++-----  arch/x86/include/asm/u-boot-x86.h |   2 ++  arch/x86/lib/board.c        |   3 +++  3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 61d0b69..a8069ad 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -105,6 +105,16 @@ int cpu_init_f(void) __attribute__((weak, alias("x86_cpu_init_f")));
int x86_cpu_init_r(void) Â {
- reload_gdt();
- /* Initialize core interrupt and exception functionality of CPU */
- cpu_init_interrupts();
- return 0;
+} +int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r")));
+int x86_init_cache(void)
Could this be called dcache_init() or does it deal with I$ also?
Regards, Simon
+{ Â Â Â Â const u32 nw_cd_rst = ~(X86_CR0_NW | X86_CR0_CD);
/* turn on the cache and disable write through */ @@ -113,13 +123,9 @@ int x86_cpu_init_r(void)       "movl    %%eax, %%cr0\n"       "wbinvd\n" : : "i" (nw_cd_rst) : "eax");
- reload_gdt();
- /* Initialize core interrupt and exception functionality of CPU */
- cpu_init_interrupts();
return 0; Â } -int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r"))); +int init_cache(void) __attribute__((weak, alias("x86_init_cache")));
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) Â { diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 757a8ee..eaa50cc 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -37,6 +37,8 @@ int x86_cpu_init_r(void); Â int cpu_init_r(void); Â int x86_cpu_init_f(void); Â int cpu_init_f(void); +int x86_init_cache(void); +int init_cache(void);
/* cpu/.../timer.c */ Â void timer_isr(void *); diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 4736477..fb2b92c 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -267,6 +267,9 @@ void relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr)
id->start_addr_sp = stack_ptr;
- if (init_cache() != 0)
- hang();
calculate_relocation_address(id); Â Â Â Â copy_uboot_to_ram(id); Â Â Â Â clear_bss(id); -- 1.7.5.2.317.g391b14

--- arch/x86/cpu/cpu.c | 20 ++++++++++++-------- 1 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index a8069ad..7ec0c12 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -115,14 +115,6 @@ int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r")));
int x86_init_cache(void) { - const u32 nw_cd_rst = ~(X86_CR0_NW | X86_CR0_CD); - - /* turn on the cache and disable write through */ - asm("movl %%cr0, %%eax\n" - "andl %0, %%eax\n" - "movl %%eax, %%cr0\n" - "wbinvd\n" : : "i" (nw_cd_rst) : "eax"); - return 0; } int init_cache(void) __attribute__((weak, alias("x86_init_cache"))); @@ -140,6 +132,18 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; }
+void enable_caches(void) +{ + const u32 nw_cd_rst = ~(X86_CR0_NW | X86_CR0_CD); + + /* turn on the cache and disable write through */ + asm("movl %%cr0, %%eax\n" + "andl %0, %%eax\n" + "movl %%eax, %%cr0\n" : : "i" (nw_cd_rst) : "eax"); + + flush_cache(0, 0); +} + void flush_cache(unsigned long dummy1, unsigned long dummy2) { asm("wbinvd\n");

--- arch/x86/cpu/cpu.c | 2 +- arch/x86/cpu/interrupts.c | 2 +- arch/x86/cpu/start16.S | 54 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 45 insertions(+), 13 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 7ec0c12..70a864d 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -61,7 +61,7 @@ static void reload_gdt(void) * There are machines which are known to not boot with the GDT * being 8-byte unaligned. Intel recommends 16 byte alignment */ - static const u64 boot_gdt[] __attribute__((aligned(16))) = { + static const u64 boot_gdt[] __aligned(16) = { /* CS: code, read/execute, 4 GB, base 0 */ [GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff), /* DS: data, read/write, 4 GB, base 0 */ diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index e0958eb..43ec3f8 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -174,7 +174,7 @@ struct desc_ptr { unsigned short segment; } __packed;
-struct idt_entry idt[256] __attribute__((aligned(16))); +struct idt_entry idt[256] __aligned(16);
struct desc_ptr idt_ptr;
diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S index 33e53cd..f454827 100644 --- a/arch/x86/cpu/start16.S +++ b/arch/x86/cpu/start16.S @@ -86,7 +86,8 @@ gdt_ptr: .word 0x20 /* limit (32 bytes = 4 GDT entries) */ .long BOOT_SEG + gdt /* base */
- /* The GDT table ... + /* + * The GDT table ... * * Selector Type * 0x00 NULL @@ -96,15 +97,46 @@ gdt_ptr: */
gdt: - .word 0, 0, 0, 0 /* NULL */ - .word 0, 0, 0, 0 /* unused */ + /* The NULL Desciptor - Mandatory */ + .word 0x0000 /* limit_low */ + .word 0x0000 /* base_low */ + .byte 0x00 /* base_middle */ + .byte 0x00 /* access */ + .byte 0x00 /* flags + limit_high */ + .byte 0x00 /* base_high */ + + /* Unused Desciptor - (matches Linux) */ + .word 0x0000 /* limit_low */ + .word 0x0000 /* base_low */ + .byte 0x00 /* base_middle */ + .byte 0x00 /* access */ + .byte 0x00 /* flags + limit_high */ + .byte 0x00 /* base_high */
- .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ - .word 0 /* base address = 0 */ - .word 0x9B00 /* code read/exec */ - .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ + /* + * The Code Segment Descriptor: + * - Base = 0x00000000 + * - Size = 4GB + * - Access = Present, Ring 0, Exec (Code), Readable + * - Flags = 4kB Granularity, 32-bit + */ + .word 0xffff /* limit_low */ + .word 0x0000 /* base_low */ + .byte 0x00 /* base_middle */ + .byte 0x9a /* access */ + .byte 0xcf /* flags + limit_high */ + .byte 0x00 /* base_high */
- .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ - .word 0x0 /* base address = 0 */ - .word 0x9300 /* data read/write */ - .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ + /* + * The Data Segment Descriptor: + * - Base = 0x00000000 + * - Size = 4GB + * - Access = Present, Ring 0, Non-Exec (Data), Writable + * - Flags = 4kB Granularity, 32-bit + */ + .word 0xffff /* limit_low */ + .word 0x0000 /* base_low */ + .byte 0x00 /* base_middle */ + .byte 0x93 /* access */ + .byte 0xcf /* flags + limit_high */ + .byte 0x00 /* base_high */

--- arch/x86/lib/bios.S | 134 +++++++++++++++++++++++++-------------- arch/x86/lib/realmode_switch.S | 61 +++++++++++-------- 2 files changed, 122 insertions(+), 73 deletions(-)
diff --git a/arch/x86/lib/bios.S b/arch/x86/lib/bios.S index ce8deb5..239aaa9 100644 --- a/arch/x86/lib/bios.S +++ b/arch/x86/lib/bios.S @@ -246,11 +246,9 @@ rm_int1f: rm_def_int: iret
- /* - * All interrupt jumptable entries jump to here - * after pushing the interrupt vector number onto the - * stack. + * All interrupt jumptable entries jump to here after pushing the + * interrupt vector number onto the stack. */ any_interrupt16: MAKE_BIOS_STACK @@ -272,7 +270,8 @@ gs movw OFFS_VECTOR(%bp), %ax je Lint_1ah movw $0xffff, %ax jmp Lout -Lint_10h: /* VGA BIOS services */ +Lint_10h: + /* VGA BIOS services */ call bios_10h jmp Lout Lint_11h: @@ -281,35 +280,42 @@ Lint_11h: Lint_12h: call bios_12h jmp Lout -Lint_13h: /* BIOS disk services */ +Lint_13h: + /* BIOS disk services */ call bios_13h jmp Lout -Lint_15h: /* Misc. BIOS services */ +Lint_15h: + /* Misc. BIOS services */ call bios_15h jmp Lout -Lint_16h: /* keyboard services */ +Lint_16h: + /* keyboard services */ call bios_16h jmp Lout -Lint_1ah: /* PCI bios */ +Lint_1ah: + /* PCI bios */ call bios_1ah jmp Lout Lout: cmpw $0, %ax je Lhandeled
- /* Insert code for unhandeled INTs here. + /* + * Insert code for unhandeled INTs here. * - * ROLO prints a message to the console - * (we could do that but then we're in 16bit mode - * so we'll have to get back into 32bit mode - * to use the console I/O routines (if we do this - * we shuls make int 0x10 and int 0x16 work as well)) + * ROLO prints a message to the console we could do that but then + * we're in 16bit mode so we'll have to get back into 32bit mode + * to use the console I/O routines (if we do this we should make + * int 0x10 and int 0x16 work as well) */ Lhandeled: RESTORE_CALLERS_STACK - addw $2,%sp /* dump vector number */ - iret /* return from interrupt */
+ /* dump vector number */ + addw $2,%sp + + /* return from interrupt */ + iret
/* ************************************************************ @@ -327,22 +333,24 @@ gs movw OFFS_AX(%bp), %ax je Lvid_cfg movw $0xffff, %ax ret -Lcur_pos: /* Read Cursor Position and Size */ +Lcur_pos: + /* Read Cursor Position and Size */ gs movw $0, OFFS_CX(%bp) gs movw $0, OFFS_DX(%bp) xorw %ax, %ax ret -Lvid_state: /* Get Video State */ -gs movw $(80 << 8|0x03), OFFS_AX(%bp) /* 80 columns, 80x25, 16 colors */ +Lvid_state: + /* Get Video State - 80 columns, 80x25, 16 colors */ +gs movw $(80 << 8|0x03), OFFS_AX(%bp) gs movw $0, OFFS_BX(%bp) xorw %ax, %ax ret -Lvid_cfg: /* Video Subsystem Configuration (EGA/VGA) */ -gs movw $0x10, OFFS_BX(%bp) /* indicate CGA/MDA/HGA */ +Lvid_cfg: + /* Video Subsystem Configuration (EGA/VGA) - indicate CGA/MDA/HGA */ +gs movw $0x10, OFFS_BX(%bp) xorw %ax, %ax ret
- /* ************************************************************ * BIOS interrupt 11h -- Equipment determination @@ -355,7 +363,6 @@ gs movw %ax, OFFS_AX(%bp) xorw %ax, %ax ret
- /* ************************************************************ * BIOS interrupt 12h -- Get Memory Size @@ -370,16 +377,18 @@ cs movw ram_in_64kb_chunks, %ax b12_more_than_640k: movw $0x280, %ax b12_return: -gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes in ax */ + /* return number of kilobytes in ax */ +gs movw %ax, OFFS_AX(%bp)
gs movw OFFS_FLAGS(%bp), %ax - andw $0xfffe, %ax /* clear carry -- function succeeded */ + + /* clear carry -- function succeeded */ + andw $0xfffe, %ax gs movw %ax, OFFS_FLAGS(%bp)
xorw %ax, %ax ret
- /* ************************************************************ * BIOS interrupt 13h -- Disk services @@ -394,12 +403,13 @@ gs movw OFFS_AX(%bp), %ax ret Lfunc_15h: gs movw OFFS_AX(%bp), %ax - andw $0xff, %ax /* return AH=0->drive not present */ + + /* return AH=0->drive not present */ + andw $0x00ff, %ax gs movw %ax, OFFS_AX(%bp) xorw %ax, %ax ret
- /* *********************************************************** * BIOS interrupt 15h -- Miscellaneous services @@ -417,9 +427,12 @@ gs movw OFFS_AX(%bp), %ax movw $0xffff, %ax ret
-Lfunc_c0h: /* Return System Configuration Parameters (PS2 only) */ +Lfunc_c0h: + /* Return System Configuration Parameters (PS2 only) */ gs movw OFFS_FLAGS(%bp), %ax - orw $1, %ax /* return carry -- function not supported */ + + /* return carry -- function not supported */ + orw $1, %ax gs movw %ax, OFFS_FLAGS(%bp) xorw %ax, %ax ret @@ -430,38 +443,56 @@ gs movw OFFS_AX(%bp), %ax cmpw $1, %ax je Lfunc_e801h gs movw OFFS_FLAGS(%bp), %ax - orw $1, %ax /* return carry -- function not supported */ + + /* return carry -- function not supported */ + orw $1, %ax gs movw %ax, OFFS_FLAGS(%bp) xorw %ax, %ax ret
-Lfunc_e801h: /* Get memory size for >64M Configurations */ +Lfunc_e801h: + /* Get memory size for >64M Configurations */ cs movw ram_in_64kb_chunks, %ax cmpw $0x100, %ax ja e801_more_than_16mb - shlw $6, %ax /* multiply by 64 */ - subw $0x400, %ax /* 1st meg does not count */
-gs movw %ax, OFFS_AX(%bp) /* return memory size between 1M and 16M in 1kb chunks in AX and CX */ + /* multiply by 64 */ + shlw $6, %ax + + /* 1st meg does not count */ + subw $0x400, %ax + + /* return memory size between 1M and 16M in 1kb chunks in AX and CX */ +gs movw %ax, OFFS_AX(%bp) gs movw %ax, OFFS_CX(%bp) -gs movw $0, OFFS_BX(%bp) /* set BX and DX to 0*/ + + /* set BX and DX to 0*/ +gs movw $0, OFFS_BX(%bp) gs movw $0, OFFS_DX(%bp) gs movw OFFS_FLAGS(%bp), %ax - andw $0xfffe, %ax /* clear carry -- function succeeded */ + + /* clear carry -- function succeeded */ + andw $0xfffe, %ax gs movw %ax, OFFS_FLAGS(%bp) xorw %ax, %ax ret
e801_more_than_16mb: - subw $0x100, %ax /* subtract 16MB */ + /* subtract 16MB */ + subw $0x100, %ax
-gs movw $0x3c00, OFFS_AX(%bp) /* return 0x3c00 (16MB-1MB) in AX and CX */ + /* return 0x3c00 (16MB-1MB) in AX and CX */ +gs movw $0x3c00, OFFS_AX(%bp) gs movw $0x3c00, OFFS_CX(%bp) -gs movw %ax, OFFS_BX(%bp) /* set BX and DX to number of 64kb chunks above 16MB */ + + /* set BX and DX to number of 64kb chunks above 16MB */ +gs movw %ax, OFFS_BX(%bp) gs movw %ax, OFFS_DX(%bp)
gs movw OFFS_FLAGS(%bp), %ax - andw $0xfffe, %ax /* clear carry -- function succeeded */ + + /* clear carry -- function succeeded */ + andw $0xfffe, %ax gs movw %ax, OFFS_FLAGS(%bp) xorw %ax, %ax ret @@ -473,18 +504,22 @@ cs movw ram_in_64kb_chunks, %ax movw $0x100, %ax b88_not_more_than16: shlw $6, %ax - subw $0x400, %ax /* 1st meg does not count */
-gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes between 16MB and 16MB in ax */ + /* 1st meg does not count */ + subw $0x400, %ax + + /* return number of kilobytes between 16MB and 16MB in ax */ +gs movw %ax, OFFS_AX(%bp)
gs movw OFFS_FLAGS(%bp), %ax - andw $0xfffe, %ax /* clear carry -- function succeeded */ + + /* clear carry -- function succeeded */ + andw $0xfffe, %ax gs movw %ax, OFFS_FLAGS(%bp)
xorw %ax, %ax ret
- /* ************************************************************ * BIOS interrupt 16h -- keyboard services @@ -498,7 +533,8 @@ gs movw OFFS_AX(%bp), %ax movw $0xffff, %ax ret Lfunc_03h: - xorw %ax, %ax /* do nothing -- function not supported */ + /* do nothing -- function not supported */ + xorw %ax, %ax ret
/* @@ -514,7 +550,9 @@ gs movw OFFS_AX(%bp), %ax ret Lfunc_b1h: call realmode_pci_bios - xorw %ax, %ax /* do nothing -- function not supported */ + + /* do nothing -- function not supported */ + xorw %ax, %ax ret
diff --git a/arch/x86/lib/realmode_switch.S b/arch/x86/lib/realmode_switch.S index 7ee709a..c4c4c43 100644 --- a/arch/x86/lib/realmode_switch.S +++ b/arch/x86/lib/realmode_switch.S @@ -44,12 +44,13 @@ * e40 ss; */
-#define a32 .byte 0x67; /* address size prefix 32 */ -#define o32 .byte 0x66; /* operand size prefix 32 */ +#define a32 .byte 0x67; /* address size prefix 32 */ +#define o32 .byte 0x66; /* operand size prefix 32 */
.section .realmode, "ax" .code16 - /* 16bit protected mode code here */ + + /* 16bit protected mode code here */ .globl realmode_enter realmode_enter: o32 pusha @@ -69,20 +70,23 @@ o32 pushf movw %ax, %gs
lidt realmode_idt_ptr - movl %cr0, %eax /* Go back into real mode by */ - andl $0x7ffffffe, %eax /* clearing PE to 0 */ + /* Go back into real mode by clearing PE to 0 */ + movl %cr0, %eax + andl $0x7ffffffe, %eax movl %eax, %cr0 - ljmp $0x0,$do_realmode /* switch to real mode */
-do_realmode: /* realmode code from here */ + /* switch to real mode */ + ljmp $0x0,$do_realmode + +do_realmode: + /* realmode code from here */ movw %cs,%ax movw %ax,%ds movw %ax,%es movw %ax,%fs movw %ax,%gs
- /* create a temporary stack */ - + /* create a temporary stack */ movw $0xc0, %ax movw %ax, %ss movw $0x200, %ax @@ -114,26 +118,29 @@ o32 popf popw %ss movl %eax, %esp cs movl temp_eax, %eax - wbinvd /* self-modifying code, - * better flush the cache */ + + /* self-modifying code, better flush the cache */ + wbinvd
.byte 0x9a /* lcall */ temp_ip: .word 0 /* new ip */ temp_cs: .word 0 /* new cs */ + realmode_ret: - /* save eax, esp and ss */ + /* save eax, esp and ss */ cs movl %eax, saved_eax movl %esp, %eax cs movl %eax, saved_esp movw %ss, %ax cs movw %ax, saved_ss
- /* restore the stack, note that we set sp to 0x244; + /* + * restore the stack, note that we set sp to 0x244; * pt_regs is 0x44 bytes long and we push the structure - * backwards on to the stack, bottom first */ - + * backwards on to the stack, bottom first + */ movw $0xc0, %ax movw %ax, %ss movw $0x244, %ax @@ -169,12 +176,15 @@ cs movw temp_ip, %ax pushl %ebx
o32 cs lidt saved_idt -o32 cs lgdt saved_gdt /* Set GDTR */ +o32 cs lgdt saved_gdt
- movl %cr0, %eax /* Go back into protected mode */ - orl $1,%eax /* reset PE to 1 */ + /* Go back into protected mode reset PE to 1 */ + movl %cr0, %eax + orl $1,%eax movl %eax, %cr0 - jmp next_line /* flush prefetch queue */ + + /* flush prefetch queue */ + jmp next_line next_line: movw $return_ptr, %ax movw %ax,%bp @@ -182,12 +192,13 @@ o32 cs ljmp *(%bp)
.code32 protected_mode: - movl $0x18,%eax /* reload GDT[3] */ - movw %ax,%fs /* reset FS */ - movw %ax,%ds /* reset DS */ - movw %ax,%gs /* reset GS */ - movw %ax,%es /* reset ES */ - movw %ax,%ss /* reset SS */ + /* Reload segment registers */ + movl $0x18, %eax + movw %ax, %fs + movw %ax, %ds + movw %ax, %gs + movw %ax, %es + movw %ax, %ss movl saved_protected_mode_esp, %eax movl %eax, %esp popf

--- arch/x86/lib/Makefile | 1 + arch/x86/lib/board.c | 27 ------------------- arch/x86/lib/cmd_boot.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 arch/x86/lib/cmd_boot.c
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index d584aa4..7820895 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -32,6 +32,7 @@ SOBJS-$(CONFIG_SYS_X86_REALMODE) += realmode_switch.o COBJS-$(CONFIG_SYS_PC_BIOS) += bios_setup.o COBJS-y += board.o COBJS-y += bootm.o +COBJS-y += cmd_boot.o COBJS-y += gcc.o COBJS-y += interrupts.o COBJS-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index fb2b92c..2b97b47 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -464,33 +464,6 @@ void hang(void) ; }
-unsigned long do_go_exec(ulong (*entry)(int, char * const []), - int argc, char * const argv[]) -{ - unsigned long ret = 0; - char **argv_tmp; - - /* - * x86 does not use a dedicated register to pass the pointer to - * the global_data, so it is instead passed as argv[-1]. By using - * argv[-1], the called 'Application' can use the contents of - * argv natively. However, to safely use argv[-1] a new copy of - * argv is needed with the extra element - */ - argv_tmp = malloc(sizeof(char *) * (argc + 1)); - - if (argv_tmp) { - argv_tmp[0] = (char *)gd; - - memcpy(&argv_tmp[1], argv, (size_t)(sizeof(char *) * argc)); - - ret = (entry) (argc, &argv_tmp[1]); - free(argv_tmp); - } - - return ret; -} - void setup_pcat_compatibility(void) __attribute__((weak, alias("__setup_pcat_compatibility")));
diff --git a/arch/x86/lib/cmd_boot.c b/arch/x86/lib/cmd_boot.c new file mode 100644 index 0000000..a81a9a3 --- /dev/null +++ b/arch/x86/lib/cmd_boot.c @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2008-2011 + * Graeme Russ, graeme.russ@gmail.com + * + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger mgroeger@sysgo.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <malloc.h> +#include <asm/u-boot-x86.h> + +unsigned long do_go_exec(ulong (*entry)(int, char * const []), + int argc, char * const argv[]) +{ + unsigned long ret = 0; + char **argv_tmp; + + /* + * x86 does not use a dedicated register to pass the pointer to + * the global_data, so it is instead passed as argv[-1]. By using + * argv[-1], the called 'Application' can use the contents of + * argv natively. However, to safely use argv[-1] a new copy of + * argv is needed with the extra element + */ + argv_tmp = malloc(sizeof(char *) * (argc + 1)); + + if (argv_tmp) { + argv_tmp[0] = (char *)gd; + + memcpy(&argv_tmp[1], argv, (size_t)(sizeof(char *) * argc)); + + ret = (entry) (argc, &argv_tmp[1]); + free(argv_tmp); + } + + return ret; +}

--- arch/x86/lib/board.c | 7 ------- arch/x86/lib/zimage.c | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 2b97b47..f201542 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -463,10 +463,3 @@ void hang(void) for (;;) ; } - -void setup_pcat_compatibility(void) - __attribute__((weak, alias("__setup_pcat_compatibility"))); - -void __setup_pcat_compatibility(void) -{ -} diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index bb40517..2214286 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -314,6 +314,13 @@ void boot_zimage(void *setup_base, void *load_address) #endif }
+void setup_pcat_compatibility(void) + __attribute__((weak, alias("__setup_pcat_compatibility"))); + +void __setup_pcat_compatibility(void) +{ +} + int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { struct boot_params *base_ptr;

It's not used for anything useful --- arch/x86/include/asm/global_data.h | 1 - arch/x86/lib/board.c | 4 +--- 2 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 05a2139..ad15509 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -50,7 +50,6 @@ typedef struct global_data { unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long bus_clk; unsigned long relocaddr; /* Start address of U-Boot in RAM */ - unsigned long start_addr_sp; /* start_addr_stackpointer */ phys_size_t ram_size; /* RAM size */ unsigned long reset_status; /* reset status register at boot */ void **jt; /* jump table */ diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index f201542..e8274bf 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -163,7 +163,7 @@ static int calculate_relocation_address(gd_t *id) ulong rel_offset;
/* Calculate destination RAM Address and relocation offset */ - dest_addr = id->start_addr_sp; + dest_addr = (ulong)id; dest_addr -= CONFIG_SYS_STACK_SIZE; dest_addr -= (bss_end - text_start);
@@ -265,8 +265,6 @@ void relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr) /* gd is still in CAR - Copy it into SDRAM */ memcpy(id, gd, sizeof(gd_t));
- id->start_addr_sp = stack_ptr; - if (init_cache() != 0) hang();

--- arch/x86/lib/Makefile | 1 + arch/x86/lib/board.c | 113 ----------------------------------- arch/x86/lib/relocate.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 113 deletions(-) create mode 100644 arch/x86/lib/relocate.c
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 7820895..57b6896 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -40,6 +40,7 @@ COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o COBJS-$(CONFIG_PCI) += pci.o COBJS-$(CONFIG_PCI) += pci_type1.o COBJS-$(CONFIG_SYS_X86_REALMODE) += realmode.o +COBJS-y += relocate.o COBJS-y += string.o COBJS-$(CONFIG_SYS_X86_ISR_TIMER) += timer.o COBJS-$(CONFIG_VIDEO) += video_bios.o diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index e8274bf..a6596ef 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -41,7 +41,6 @@ #include <ide.h> #include <serial.h> #include <asm/u-boot-x86.h> -#include <elf.h>
#ifdef CONFIG_BITBANGMII #include <miiphy.h> @@ -124,11 +123,6 @@ static void display_flash_config(ulong size) */ typedef int (init_fnc_t) (void);
-static int calculate_relocation_address(gd_t *); -static int copy_uboot_to_ram(gd_t *); -static int clear_bss(gd_t *); -static int do_elf_reloc_fixups(gd_t *); - init_fnc_t *init_sequence_f[] = { cpu_init_f, board_early_init_f, @@ -155,85 +149,6 @@ init_fnc_t *init_sequence_r[] = {
gd_t *gd;
-static int calculate_relocation_address(gd_t *id) -{ - ulong text_start = (ulong)&__text_start; - ulong bss_end = (ulong)&__bss_end; - ulong dest_addr; - ulong rel_offset; - - /* Calculate destination RAM Address and relocation offset */ - dest_addr = (ulong)id; - dest_addr -= CONFIG_SYS_STACK_SIZE; - dest_addr -= (bss_end - text_start); - - /* - * Round destination address down to 16-byte boundary to keep - * IDT and GDT 16-byte aligned - */ - dest_addr &= ~15; - - rel_offset = dest_addr - text_start; - - id->relocaddr = dest_addr; - id->reloc_off = rel_offset; - - return 0; -} - -static int copy_uboot_to_ram(gd_t *id) -{ - size_t len = (size_t)&__data_end - (size_t)&__text_start; - - memcpy((void *)id->relocaddr, (void *)&__text_start, len); - - return 0; -} - -static int clear_bss(gd_t *id) -{ - ulong dst_addr = (ulong)&__bss_start + id->reloc_off; - size_t len = (size_t)&__bss_end - (size_t)&__bss_start; - - memset((void *)dst_addr, 0x00, len); - - return 0; -} - -static int do_elf_reloc_fixups(gd_t *id) -{ - Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); - Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); - - Elf32_Addr *offset_ptr_rom; - Elf32_Addr *offset_ptr_ram; - - /* The size of the region of u-boot that runs out of RAM. */ - uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; - - do { - /* Get the location from the relocation entry */ - offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; - - /* Check that the location of the relocation is in .text */ - if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) { - - /* Switch to the in-RAM version */ - offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + - id->reloc_off); - - /* Check that the target points into .text */ - if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE && - *offset_ptr_ram < - (CONFIG_SYS_TEXT_BASE + size)) { - *offset_ptr_ram += id->reloc_off; - } - } - } while (re_src++ < re_end); - - return 0; -} - /* Load U-Boot into RAM, initialize BSS, perform relocation adjustments */ void board_init_f(ulong boot_flags) { @@ -254,34 +169,6 @@ void board_init_f(ulong boot_flags) ; }
-typedef void (board_init_r_t) (gd_t *, ulong); - -void relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr) -{ - board_init_r_t *board_init_r_func; - - /* We are running from flash, but the stack is now in SDRAM */ - - /* gd is still in CAR - Copy it into SDRAM */ - memcpy(id, gd, sizeof(gd_t)); - - if (init_cache() != 0) - hang(); - - calculate_relocation_address(id); - copy_uboot_to_ram(id); - clear_bss(id); - do_elf_reloc_fixups(id); - - board_init_r_func = board_init_r; - board_init_r_func += id->reloc_off; - board_init_r_func(id, id->relocaddr); - - /* NOTREACHED - relocate_code() does not return */ - while (1) - ; -} - void board_init_r(gd_t *id, ulong dest_addr) { #if defined(CONFIG_CMD_NET) diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c new file mode 100644 index 0000000..f8c0b3f --- /dev/null +++ b/arch/x86/lib/relocate.c @@ -0,0 +1,150 @@ +/* + * (C) Copyright 2008-2011 + * Graeme Russ, graeme.russ@gmail.com + * + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger mgroeger@sysgo.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <asm/u-boot-x86.h> +#include <elf.h> + +static int calculate_relocation_address(gd_t *); +static int copy_uboot_to_ram(gd_t *); +static int clear_bss(gd_t *); +static int do_elf_reloc_fixups(gd_t *); + +static int calculate_relocation_address(gd_t *id) +{ + ulong text_start = (ulong)&__text_start; + ulong bss_end = (ulong)&__bss_end; + ulong dest_addr; + ulong rel_offset; + + /* Calculate destination RAM Address and relocation offset */ + dest_addr = (ulong)id; + dest_addr -= CONFIG_SYS_STACK_SIZE; + dest_addr -= (bss_end - text_start); + + /* + * Round destination address down to 16-byte boundary to keep + * IDT and GDT 16-byte aligned + */ + dest_addr &= ~15; + + rel_offset = dest_addr - text_start; + + id->relocaddr = dest_addr; + id->reloc_off = rel_offset; + + return 0; +} + +static int copy_uboot_to_ram(gd_t *id) +{ + size_t len = (size_t)&__data_end - (size_t)&__text_start; + + memcpy((void *)id->relocaddr, (void *)&__text_start, len); + + return 0; +} + +static int clear_bss(gd_t *id) +{ + ulong dst_addr = (ulong)&__bss_start + id->reloc_off; + size_t len = (size_t)&__bss_end - (size_t)&__bss_start; + + memset((void *)dst_addr, 0x00, len); + + return 0; +} + +static int do_elf_reloc_fixups(gd_t *id) +{ + Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); + Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); + + Elf32_Addr *offset_ptr_rom; + Elf32_Addr *offset_ptr_ram; + + /* The size of the region of u-boot that runs out of RAM. */ + uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; + + do { + /* Get the location from the relocation entry */ + offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; + + /* Check that the location of the relocation is in .text */ + if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) { + + /* Switch to the in-RAM version */ + offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + + id->reloc_off); + + /* Check that the target points into .text */ + if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE && + *offset_ptr_ram < + (CONFIG_SYS_TEXT_BASE + size)) { + *offset_ptr_ram += id->reloc_off; + } + } + } while (re_src++ < re_end); + + return 0; +} + +typedef void (board_init_r_t) (gd_t *, ulong); + +__attribute__ ((__noreturn__)) +void relocate_code(ulong dummy_1, gd_t *id, ulong dummy_2) +{ + board_init_r_t *board_init_r_func; + + /* We are running from flash, but the stack is now in SDRAM */ + + /* gd is still in CAR - Copy it into SDRAM */ + memcpy(id, gd, sizeof(gd_t)); + + if (init_cache() != 0) + hang(); + + calculate_relocation_address(id); + copy_uboot_to_ram(id); + clear_bss(id); + do_elf_reloc_fixups(id); + + board_init_r_func = board_init_r; + board_init_r_func += id->reloc_off; + board_init_r_func(id, id->relocaddr); + + /* NOTREACHED - relocate_code() does not return */ + while (1) + ; +}

--- arch/x86/include/asm/init_helpers.h | 39 +++++ arch/x86/include/asm/init_wrappers.h | 42 +++++ arch/x86/lib/Makefile | 2 + arch/x86/lib/board.c | 289 +++++++++------------------------- arch/x86/lib/init_helpers.c | 140 ++++++++++++++++ arch/x86/lib/init_wrappers.c | 137 ++++++++++++++++ 6 files changed, 435 insertions(+), 214 deletions(-) create mode 100644 arch/x86/include/asm/init_helpers.h create mode 100644 arch/x86/include/asm/init_wrappers.h create mode 100644 arch/x86/lib/init_helpers.c create mode 100644 arch/x86/lib/init_wrappers.c
diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h new file mode 100644 index 0000000..14ef11a --- /dev/null +++ b/arch/x86/include/asm/init_helpers.h @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2011 + * Graeme Russ, graeme.russ@gmail.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _INIT_HELPERS_H_ +#define _INIT_HELPERS_H_ + +int display_banner(void); +int display_dram_config(void); +int init_baudrate_f(void); + +int mem_malloc_init_r(void); +int init_bd_struct_r(void); +int flash_init_r(void); +int init_ip_address_r(void); +int status_led_set_r(void); +int set_bootfile_r(void); +int set_load_addr_r(void); + +#endif /* !_INIT_HELPERS_H_ */ diff --git a/arch/x86/include/asm/init_wrappers.h b/arch/x86/include/asm/init_wrappers.h new file mode 100644 index 0000000..899ffb1 --- /dev/null +++ b/arch/x86/include/asm/init_wrappers.h @@ -0,0 +1,42 @@ +/* + * (C) Copyright 2011 + * Graeme Russ, graeme.russ@gmail.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _INIT_WRAPPERS_H_ +#define _INIT_WRAPPERS_H_ + +int serial_initialize_r(void); +int env_relocate_r(void); +int pci_init_r(void); +int jumptable_init_r(void); +int pcmcia_init_r(void); +int kgdb_init_r(void); +int enable_interrupts_r(void); +int eth_initialize_r(void); +int reset_phy_r(void); +int ide_init_r(void); +int scsi_init_r(void); +int doc_init_r(void); +int bb_miiphy_init_r(void); +int post_run_r(void); + +#endif /* !_INIT_WRAPPERS_H_ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 57b6896..51836da 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -34,6 +34,8 @@ COBJS-y += board.o COBJS-y += bootm.o COBJS-y += cmd_boot.o COBJS-y += gcc.o +COBJS-y += init_helpers.o +COBJS-y += init_wrappers.o COBJS-y += interrupts.o COBJS-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index a6596ef..b06063a 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -33,18 +33,11 @@
#include <common.h> #include <watchdog.h> -#include <command.h> #include <stdio_dev.h> -#include <version.h> -#include <malloc.h> -#include <net.h> -#include <ide.h> -#include <serial.h> #include <asm/u-boot-x86.h>
-#ifdef CONFIG_BITBANGMII -#include <miiphy.h> -#endif +#include <asm/init_helpers.h> +#include <asm/init_wrappers.h>
/* * Pointer to initial global data area @@ -55,49 +48,6 @@ #define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */ DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR);
-/************************************************************************ - * Init Utilities * - ************************************************************************ - * Some of this code should be moved into the core functions, - * or dropped completely, - * but let's get it working (again) first... - */ -static int init_baudrate(void) -{ - gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); - return 0; -} - -static int display_banner(void) -{ - - printf("\n\n%s\n\n", version_string); - - return 0; -} - -static int display_dram_config(void) -{ - int i; - - puts("DRAM Configuration:\n"); - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); - print_size(gd->bd->bi_dram[i].size, "\n"); - } - - return 0; -} - -#ifndef CONFIG_SYS_NO_FLASH -static void display_flash_config(ulong size) -{ - puts("Flash: "); - print_size(size, "\n"); -} -#endif - /* * Breath some life into the board... * @@ -127,7 +77,7 @@ init_fnc_t *init_sequence_f[] = { cpu_init_f, board_early_init_f, env_init, - init_baudrate, + init_baudrate_f, serial_init, console_init_f, dram_init_f, @@ -136,204 +86,115 @@ init_fnc_t *init_sequence_f[] = { };
init_fnc_t *init_sequence_r[] = { - cpu_init_r, /* basic cpu dependent setup */ - board_early_init_r, /* basic board dependent setup */ - dram_init, /* configure available RAM banks */ - interrupt_init, /* set up exceptions */ + init_bd_struct_r, + mem_malloc_init_r, + cpu_init_r, + board_early_init_r, + dram_init, + interrupt_init, timer_init, display_banner, display_dram_config, - - NULL, -}; - -gd_t *gd; - -/* Load U-Boot into RAM, initialize BSS, perform relocation adjustments */ -void board_init_f(ulong boot_flags) -{ - init_fnc_t **init_fnc_ptr; - - gd->flags = boot_flags; - - for (init_fnc_ptr = init_sequence_f; *init_fnc_ptr; ++init_fnc_ptr) { - if ((*init_fnc_ptr)() != 0) - hang(); - } - - /* SDRAM is now initialised setup a new stack in SDRAM */ - setup_sdram_environment(gd->ram_size, GENERATED_GBL_DATA_SIZE); - - /* NOTREACHED - relocate_code() does not return */ - while (1) - ; -} - -void board_init_r(gd_t *id, ulong dest_addr) -{ -#if defined(CONFIG_CMD_NET) - char *s; -#endif -#ifndef CONFIG_SYS_NO_FLASH - ulong size; -#endif - static bd_t bd_data; - init_fnc_t **init_fnc_ptr; - - show_boot_progress(0x21); - - /* Global data pointer is now writable */ - gd = id; - - gd->flags |= GD_FLG_RELOC; - - /* compiler optimization barrier needed for GCC >= 3.4 */ - __asm__ __volatile__("" : : : "memory"); - - gd->bd = &bd_data; - memset(gd->bd, 0, sizeof(bd_t)); - show_boot_progress(0x22); - - gd->baudrate = CONFIG_BAUDRATE; - - mem_malloc_init((((ulong)dest_addr - CONFIG_SYS_MALLOC_LEN)+3)&~3, - CONFIG_SYS_MALLOC_LEN); - - for (init_fnc_ptr = init_sequence_r; *init_fnc_ptr; ++init_fnc_ptr) { - if ((*init_fnc_ptr)() != 0) - hang(); - } - show_boot_progress(0x23); - #ifdef CONFIG_SERIAL_MULTI - serial_initialize(); + serial_initialize_r, #endif - #ifndef CONFIG_SYS_NO_FLASH - /* configure available FLASH banks */ - size = flash_init(); - display_flash_config(size); - show_boot_progress(0x24); + flash_init_r, #endif - - show_boot_progress(0x25); - - /* initialize environment */ - env_relocate(); - show_boot_progress(0x26); - - + env_relocate_r, #ifdef CONFIG_CMD_NET - /* IP Address */ - bd_data.bi_ip_addr = getenv_IPaddr("ipaddr"); + init_ip_address_r, #endif - -#if defined(CONFIG_PCI) - /* - * Do pci configuration - */ - pci_init(); +#ifdef CONFIG_PCI + pci_init_r, #endif - - show_boot_progress(0x27); - - - stdio_init(); - - jumptable_init(); - - /* Initialize the console (after the relocation and devices init) */ - console_init_r(); - + stdio_init, + jumptable_init_r, + console_init_r, #ifdef CONFIG_MISC_INIT_R - /* miscellaneous platform dependent initialisations */ - misc_init_r(); + misc_init_r, #endif - #if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE) - WATCHDOG_RESET(); - puts("PCMCIA:"); - pcmcia_init(); + pci_init_r, #endif - #if defined(CONFIG_CMD_KGDB) - WATCHDOG_RESET(); - puts("KGDB: "); - kgdb_init(); + kgdb_init_r, #endif - - /* enable exceptions */ - enable_interrupts(); - show_boot_progress(0x28); - + enable_interrupts_r, #ifdef CONFIG_STATUS_LED - status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); + status_led_set_r, #endif - - udelay(20); - - /* Initialize from environment */ - load_addr = getenv_ulong("loadaddr", 16, load_addr); + set_load_addr_r, #if defined(CONFIG_CMD_NET) - s = getenv("bootfile"); - - if (s != NULL) - copy_filename(BootFile, s, sizeof(BootFile)); + set_bootfile_r, #endif - - WATCHDOG_RESET(); - #if defined(CONFIG_CMD_IDE) - WATCHDOG_RESET(); - puts("IDE: "); - ide_init(); + ide_init_r, #endif - #if defined(CONFIG_CMD_SCSI) - WATCHDOG_RESET(); - puts("SCSI: "); - scsi_init(); + scsi_init_r, #endif - #if defined(CONFIG_CMD_DOC) - WATCHDOG_RESET(); - puts("DOC: "); - doc_init(); + doc_init_r, #endif - #ifdef CONFIG_BITBANGMII - bb_miiphy_init(); + bb_miiphy_init_r, #endif #if defined(CONFIG_CMD_NET) - WATCHDOG_RESET(); - puts("Net: "); - eth_initialize(gd->bd); + eth_initialize_r, +#ifdef CONFIG_RESET_PHY_R + reset_phy_r, #endif - -#if (defined(CONFIG_CMD_NET)) && (0) - WATCHDOG_RESET(); -# ifdef DEBUG - puts("Reset Ethernet PHY\n"); -# endif - reset_phy(); #endif - #ifdef CONFIG_LAST_STAGE_INIT - WATCHDOG_RESET(); + last_stage_init, +#endif + NULL, +}; + +static void do_init_loop(init_fnc_t **init_fnc_ptr) +{ + for (; *init_fnc_ptr; ++init_fnc_ptr) { + WATCHDOG_RESET(); + if ((*init_fnc_ptr)() != 0) + hang(); + } +} + +/* Perform all steps necessary to get RAM initialised ready for relocation */ +void board_init_f(ulong boot_flags) +{ + gd->flags = boot_flags; + + do_init_loop(init_sequence_f); + /* - * Some parts can be only initialized if all others (like - * Interrupts) are up and running (i.e. the PC-style ISA - * keyboard). + * SDRAM is now initialised setup a new stack in SDRAM + * + * Code execution will continue in Flash, but with the stack + * in SDRAM. This allows us to copy global data out of the CPU + * cache prior to copying U-Boot into RAM which means we can + * enable caching for the copy operation (which speeds it up + * considerably) */ - last_stage_init(); -#endif + setup_sdram_environment(gd->ram_size, GENERATED_GBL_DATA_SIZE);
+ /* NOTREACHED - setup_sdram_environment() does not return */ + while (1) + ; +}
-#ifdef CONFIG_POST - post_run(NULL, POST_RAM | post_bootmode_get(0)); -#endif +void board_init_r(gd_t *id, ulong dest_addr) +{ + /* Global data pointer is now writable */ + gd = id; + + gd->flags |= GD_FLG_RELOC; + + /* compiler optimization barrier needed for GCC >= 3.4 */ + __asm__ __volatile__("" : : : "memory");
- show_boot_progress(0x29); + do_init_loop(init_sequence_r);
/* main_loop() can return to retry autoboot, if so just run it again. */ for (;;) diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c new file mode 100644 index 0000000..a589fd3 --- /dev/null +++ b/arch/x86/lib/init_helpers.c @@ -0,0 +1,140 @@ +/* + * (C) Copyright 2011 + * Graeme Russ, graeme.russ@gmail.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <command.h> +#include <stdio_dev.h> +#include <version.h> +#include <malloc.h> +#include <net.h> +#include <ide.h> +#include <serial.h> +#include <status_led.h> +#include <asm/u-boot-x86.h> + +#include <asm/init_helpers.h> + +DECLARE_GLOBAL_DATA_PTR; + +/************************************************************************ + * Init Utilities * + ************************************************************************ + * Some of this code should be moved into the core functions, + * or dropped completely, + * but let's get it working (again) first... + */ + +int display_banner(void) +{ + printf("\n\n%s\n\n", version_string); + + return 0; +} + +int display_dram_config(void) +{ + int i; + + puts("DRAM Configuration:\n"); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); + print_size(gd->bd->bi_dram[i].size, "\n"); + } + + return 0; +} + +int init_baudrate_f(void) +{ + gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); + return 0; +} + +int mem_malloc_init_r(void) +{ + mem_malloc_init(((gd->relocaddr - CONFIG_SYS_MALLOC_LEN)+3)&~3, + CONFIG_SYS_MALLOC_LEN); + + return 0; +} + +bd_t bd_data; + +int init_bd_struct_r(void) +{ + gd->bd = &bd_data; + memset(gd->bd, 0, sizeof(bd_t)); + + return 0; +} + +int flash_init_r(void) +{ + ulong size; + + puts("Flash: "); + + /* configure available FLASH banks */ + size = flash_init(); + + print_size(size, "\n"); + + return 0; +} + +int init_ip_address_r(void) +{ + /* IP Address */ + bd_data.bi_ip_addr = getenv_IPaddr("ipaddr"); + + return 0; +} + +#ifdef CONFIG_STATUS_LED +int status_led_set_r(void) +{ + status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); + + return 0; +} +#endif + +int set_bootfile_r(void) +{ + char *s; + + s = getenv("bootfile"); + + if (s != NULL) + copy_filename(BootFile, s, sizeof(BootFile)); + + return 0; +} + +int set_load_addr_r(void) +{ + /* Initialize from environment */ + load_addr = getenv_ulong("loadaddr", 16, load_addr); + + return 0; +} diff --git a/arch/x86/lib/init_wrappers.c b/arch/x86/lib/init_wrappers.c new file mode 100644 index 0000000..71449fe --- /dev/null +++ b/arch/x86/lib/init_wrappers.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2011 + * Graeme Russ, graeme.russ@gmail.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <serial.h> +#include <kgdb.h> +#include <scsi.h> +#include <post.h> +#include <miiphy.h> + +#include <asm/init_wrappers.h> + +int serial_initialize_r(void) +{ + serial_initialize(); + + return 0; +} + +int env_relocate_r(void) +{ + /* initialize environment */ + env_relocate(); + + return 0; +} + + +int pci_init_r(void) +{ + /* Do pci configuration */ + pci_init(); + + return 0; +} + +int jumptable_init_r(void) +{ + jumptable_init(); + + return 0; +} + +int pcmcia_init_r(void) +{ + puts("PCMCIA:"); + pcmcia_init(); + + return 0; +} + +int kgdb_init_r(void) +{ + puts("KGDB: "); + kgdb_init(); + + return 0; +} + +int enable_interrupts_r(void) +{ + /* enable exceptions */ + enable_interrupts(); + + return 0; +} + +int eth_initialize_r(void) +{ + puts("Net: "); + eth_initialize(gd->bd); + + return 0; +} + +int reset_phy_r(void) +{ +#ifdef DEBUG + puts("Reset Ethernet PHY\n"); +#endif + reset_phy(); + + return 0; +} + +int ide_init_r(void) +{ + puts("IDE: "); + ide_init(); + + return 0; +} + +int scsi_init_r(void) +{ + puts("SCSI: "); + scsi_init(); + + return 0; +} + +#ifdef CONFIG_BITBANGMII +int bb_miiphy_init_r(void) +{ + bb_miiphy_init(); + + return 0; +} +#endif + +#ifdef CONFIG_POST +int post_run_r(void) +{ + post_run(NULL, POST_RAM | post_bootmode_get(0)); + + return 0; +} +#endif

--- arch/x86/cpu/start.S | 43 ++++++++++-------- arch/x86/include/asm/init_helpers.h | 3 + arch/x86/include/asm/u-boot-x86.h | 2 - arch/x86/lib/board.c | 87 ++++++++++++++++++++++++++++++---- arch/x86/lib/init_helpers.c | 14 ++++++ arch/x86/lib/relocate.c | 43 ++--------------- include/common.h | 11 ++++- 7 files changed, 131 insertions(+), 72 deletions(-)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index be21d97..9cfd54d 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -30,7 +30,7 @@ #include <version.h> #include <asm/global_data.h> #include <asm/processor-flags.h> -#include <generated/asm-offsets.h> +#include <generated/generic-asm-offsets.h>
.section .text .code32 @@ -84,36 +84,41 @@ car_init_ret: */ movl $CONFIG_SYS_INIT_SP_ADDR, %esp
- /* Set parameter to board_init_f() to boot flags */ - xorl %eax, %eax - movw %bx, %ax + /* + * Any setting of Global Data member need to be done here + * NOTE: car_init must clear CAR so that Global Data is initialised + * to zero! + */
- /* Enter, U-boot! */ + /* + * Enter U-boot by calling: + * board_init_f(location_of_gd_in_temporary_memory) + */ + movl $CONFIG_SYS_INIT_GD_ADDR, %eax call board_init_f
/* indicate (lack of) progress */ movw $0x85, %ax jmp die
-.globl setup_sdram_environment -.type setup_sdram_environment, @function -setup_sdram_environment: - /* Leave room for Global Data - Round down to 16 byte boundary */ - subl %edx, %eax +.globl board_init_f_r_trampoline +.type board_init_f_r_trampoline, @function +board_init_f_r_trampoline: + /* + * %eax contains the upper address of usable RAM. Create a fresh + * stack in RAM. x86 stack grows down, global data sits immediately + * above the stack, so we have to leave enough room between the top + * of the stack and top of RAM for global data + */ + subl $GENERATED_GBL_DATA_SIZE, %eax andl $~15, %eax - - /* Create a new stack */ movl %eax, %esp
/* - * relocate_code(ulong stack_ptr, gd_t *id, ulong reloc_addr) - * %eax = Address of top of stack - * %edx = Address of Global Data - * %ecx = Base address of in-RAM copy of U-Boot (ignored) + * Re-enter U-Boot by calling: + * board_init_f_r(location_of_gd_in_RAM) */ - movl %eax, %edx - xorl %ecx, %ecx - call relocate_code + call board_init_f_r
die: hlt diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h index 14ef11a..2d08834 100644 --- a/arch/x86/include/asm/init_helpers.h +++ b/arch/x86/include/asm/init_helpers.h @@ -28,6 +28,9 @@ int display_banner(void); int display_dram_config(void); int init_baudrate_f(void);
+int copy_gd_to_ram_f_r(gd_t *id); +int init_cache_f_r(gd_t *id); + int mem_malloc_init_r(void); int init_bd_struct_r(void); int flash_init_r(void); diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index eaa50cc..093ad11 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -63,6 +63,4 @@ u32 isa_map_rom(u32 bus_addr, int size); int video_bios_init(void); int video_init(void);
-void setup_sdram_environment(phys_size_t ram_size, ulong gd_size); - #endif /* _U_BOOT_I386_H_ */ diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index b06063a..05d362d 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -35,6 +35,7 @@ #include <watchdog.h> #include <stdio_dev.h> #include <asm/u-boot-x86.h> +#include <asm/relocate.h>
#include <asm/init_helpers.h> #include <asm/init_wrappers.h> @@ -51,12 +52,35 @@ DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR); /* * Breath some life into the board... * - * Initialize an SMC for serial comms, and carry out some hardware - * tests. + * Getting the board up and running is a three-stage process: + * 1) Execute from Flash, SDRAM Uninitialised + * At this point, there is a limited amount of non-SDRAM memory + * (typically the CPU cache, but can also be SRAM or even a buffer of + * of some peripheral). This limited memory is used to hold the initial + * copy of the Global Data Structure and a temporary stack. * - * The first part of initialization is running from Flash memory; - * its main purpose is to initialize the RAM so that we - * can relocate the monitor code to RAM. + * The following is performed during this phase of execution: + * - Core low-level CPU initialisation + * - Console initialisation + * - SDRAM initialisation + * + * 2) Execute from Flash, SDRAM Initialised + * At this point we copy Global Data from the initial non-SDRAM + * memory and set up the permanent stack in SDRAM. The CPU cache is no + * longer being used as temporary memory, so we can now fully enable + * it. + * + * The following is performed during this phase of execution: + * - Create final stack in SDRAM + * - Copy Global Data from temporary memory to SDRAM + * - Enabling of CPU cache(s), + * - Copying of U-Boot code and data from Flash to RAM + * - Clearing of the BSS + * - ELF relocation adjustments + * + * 3) Execute from SDRAM + * The following is performed during this phase of execution: + * - All remaining initialisation */
/* @@ -72,6 +96,7 @@ DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR); * "continue" and != 0 means "fatal error, hang the system". */ typedef int (init_fnc_t) (void); +typedef int (init_fnc_gd_t) (gd_t *);
init_fnc_t *init_sequence_f[] = { cpu_init_f, @@ -85,6 +110,18 @@ init_fnc_t *init_sequence_f[] = { NULL, };
+init_fnc_gd_t *init_sequence_f_r[] = { + copy_gd_to_ram_f_r, + init_cache_f_r, + calculate_relocation_address, + copy_uboot_to_ram, + clear_bss, + do_elf_reloc_fixups, + + NULL, +}; + + init_fnc_t *init_sequence_r[] = { init_bd_struct_r, mem_malloc_init_r, @@ -161,15 +198,28 @@ static void do_init_loop(init_fnc_t **init_fnc_ptr) } }
+static void do_init_loop_gt(init_fnc_gd_t **init_fnc_ptr, gd_t *id) +{ + for (; *init_fnc_ptr; ++init_fnc_ptr) { + WATCHDOG_RESET(); + if ((*init_fnc_ptr)(id) != 0) + hang(); + } +} + /* Perform all steps necessary to get RAM initialised ready for relocation */ -void board_init_f(ulong boot_flags) +void board_init_f(gd_t *id) { - gd->flags = boot_flags; + /* + * NOTE: The gd_t pointer parameter is not used, but should be, in + * future, passed to the init_xxx_f functions which would + * allow the DECLARE_GLOBAL_DATA_PTR 'hack' to be removed + */
do_init_loop(init_sequence_f);
/* - * SDRAM is now initialised setup a new stack in SDRAM + * SDRAM is now initialised - setup the final stack in SDRAM * * Code execution will continue in Flash, but with the stack * in SDRAM. This allows us to copy global data out of the CPU @@ -177,14 +227,29 @@ void board_init_f(ulong boot_flags) * enable caching for the copy operation (which speeds it up * considerably) */ - setup_sdram_environment(gd->ram_size, GENERATED_GBL_DATA_SIZE); + board_init_f_r_trampoline(gd->ram_size); + + /* NOTREACHED - board_init_f_r_trampoline() does not return */ + while (1) + ; +} + +void board_init_f_r(gd_t *id) +{ + do_init_loop_gt(init_sequence_f_r, id); + + /* + * Transfer execution from Flash to RAM by calculating the address + * of the in-RAM copy of board_init_r() and calling it + */ + (board_init_r + id->reloc_off)(id);
- /* NOTREACHED - setup_sdram_environment() does not return */ + /* NOTREACHED - board_init_r() does not return */ while (1) ; }
-void board_init_r(gd_t *id, ulong dest_addr) +void board_init_r(gd_t *id) { /* Global data pointer is now writable */ gd = id; diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index a589fd3..c932812 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -70,6 +70,20 @@ int init_baudrate_f(void) return 0; }
+ +int copy_gd_to_ram_f_r(gd_t *id) +{ + memcpy(id, gd, sizeof(gd_t)); + + return 0; +} + +int init_cache_f_r(gd_t *id) +{ + /* Initialise the CPU cache(s) */ + return init_cache(); +} + int mem_malloc_init_r(void) { mem_malloc_init(((gd->relocaddr - CONFIG_SYS_MALLOC_LEN)+3)&~3, diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index f8c0b3f..cbce22b 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -34,14 +34,10 @@ #include <common.h> #include <malloc.h> #include <asm/u-boot-x86.h> +#include <asm/relocate.h> #include <elf.h>
-static int calculate_relocation_address(gd_t *); -static int copy_uboot_to_ram(gd_t *); -static int clear_bss(gd_t *); -static int do_elf_reloc_fixups(gd_t *); - -static int calculate_relocation_address(gd_t *id) +int calculate_relocation_address(gd_t *id) { ulong text_start = (ulong)&__text_start; ulong bss_end = (ulong)&__bss_end; @@ -67,7 +63,7 @@ static int calculate_relocation_address(gd_t *id) return 0; }
-static int copy_uboot_to_ram(gd_t *id) +int copy_uboot_to_ram(gd_t *id) { size_t len = (size_t)&__data_end - (size_t)&__text_start;
@@ -76,7 +72,7 @@ static int copy_uboot_to_ram(gd_t *id) return 0; }
-static int clear_bss(gd_t *id) +int clear_bss(gd_t *id) { ulong dst_addr = (ulong)&__bss_start + id->reloc_off; size_t len = (size_t)&__bss_end - (size_t)&__bss_start; @@ -86,7 +82,7 @@ static int clear_bss(gd_t *id) return 0; }
-static int do_elf_reloc_fixups(gd_t *id) +int do_elf_reloc_fixups(gd_t *id) { Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); @@ -119,32 +115,3 @@ static int do_elf_reloc_fixups(gd_t *id)
return 0; } - -typedef void (board_init_r_t) (gd_t *, ulong); - -__attribute__ ((__noreturn__)) -void relocate_code(ulong dummy_1, gd_t *id, ulong dummy_2) -{ - board_init_r_t *board_init_r_func; - - /* We are running from flash, but the stack is now in SDRAM */ - - /* gd is still in CAR - Copy it into SDRAM */ - memcpy(id, gd, sizeof(gd_t)); - - if (init_cache() != 0) - hang(); - - calculate_relocation_address(id); - copy_uboot_to_ram(id); - clear_bss(id); - do_elf_reloc_fixups(id); - - board_init_r_func = board_init_r; - board_init_r_func += id->reloc_off; - board_init_r_func(id, id->relocaddr); - - /* NOTREACHED - relocate_code() does not return */ - while (1) - ; -} diff --git a/include/common.h b/include/common.h index 05a658c..4ef2a80 100644 --- a/include/common.h +++ b/include/common.h @@ -275,8 +275,15 @@ int abortboot(int bootdelay); extern char console_buffer[];
/* arch/$(ARCH)/lib/board.c */ -void board_init_f (ulong) __attribute__ ((noreturn)); -void board_init_r (gd_t *, ulong) __attribute__ ((noreturn)); +#ifndef CONFIG_X86 /* Horrible Hack */ +void board_init_f (ulong) __attribute__ ((noreturn)); +void board_init_r (gd_t *, ulong) __attribute__ ((noreturn)); +#else +void board_init_f(gd_t *) __attribute__ ((noreturn)); +void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn)); +void board_init_f_r(gd_t *) __attribute__ ((noreturn)); +void board_init_r(gd_t *) __attribute__ ((noreturn)); +#endif int checkboard (void); int checkflash (void); int checkdram (void);

On 23/12/11 23:25, Graeme Russ wrote:
[snip]
So a quick overview of the new sequence and it's associated elegance (IMHO) (keep in mind this is x86 centric)
- CPU boots and runs the reset vector code
- early_board_init performs any insanely-low-level init that is needed
- car_init sets up Cache-As-RAM (and clears it so gd is zero'd)
- set up a stack in CAR
- call board_init_f() passing the address of gd in CAR[1][2]
- board_init_f() runs the 'init_sequence_f' functions which should initialise console and SDRAM
- board_init_f() calls back into the assembler routine board_init_f_r_trampoline - This routine is very simple - It creates a new stack in SDRAM and calls back into board_init_f_r
- board_init_f_r is running in Flash, but with SDRAM initialised. It runs an init loop which copies gd from CAR to SDRAM, initialises the CPU cache (which destroys all data in CAR, but that is all safely in RAM by now), copies U-Boot to RAM, clears BSS and jumps to the in-RAM version of board_init_r which finishes the initialisation and enters the main loop
The memory layout for x86 is pretty simple right now - gd is at top-of-RAM and the stack sits just below it. U-Boot .text, .data, .bss etc are below the stack and the heap is below U-Boot. I understand that other arch's are more complex (LCD frame buffers in top-of-RAM for example) - I think this can all be dealt with elegantly with this code as well, but I have not attempted to do so
[1] The board_init_f() has different meanings for different arch's already [2] This parameter is not used, but could be in future to remove the 'gd pointer in a fixed register' hack
This will not work as printf() and friends require a functional Global Data pointer
Passing a Global Data pointer to board_init_f_r() like I do is also problematic - I move Global Data to RAM and trash the in-cache copy, but the gd still points to the (now trashed) cache copy until we jump to RAM (quite frankly, I don't know how it worked in the first place...)
The only way this can work is if I either: 1) Reserve a register, or 2) Reserve a writeable location in some memory location which is available prior to SDRAM init
x86 is the only arch that does not use a reserved register for the global data pointer, but I have proved previously that x86 is capable of this construct:
http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/88462
So I'll adjust this patch set accordingly
Regards,
Graeme

Hi Graeme,
On Sun, Dec 25, 2011 at 9:18 PM, Graeme Russ graeme.russ@gmail.com wrote:
On 23/12/11 23:25, Graeme Russ wrote:
[snip]
So a quick overview of the new sequence and it's associated elegance
(IMHO)
(keep in mind this is x86 centric)
- CPU boots and runs the reset vector code
- early_board_init performs any insanely-low-level init that is needed
- car_init sets up Cache-As-RAM (and clears it so gd is zero'd)
- set up a stack in CAR
- call board_init_f() passing the address of gd in CAR[1][2]
- board_init_f() runs the 'init_sequence_f' functions which should initialise console and SDRAM
- board_init_f() calls back into the assembler routine board_init_f_r_trampoline - This routine is very simple - It creates a new stack in SDRAM and calls back into board_init_f_r
- board_init_f_r is running in Flash, but with SDRAM initialised. It runs an init loop which copies gd from CAR to SDRAM, initialises the CPU cache (which destroys all data in CAR, but that is all safely in RAM by now), copies U-Boot to RAM, clears BSS and jumps to the in-RAM version of board_init_r which finishes the initialisation and enters the main loop
The memory layout for x86 is pretty simple right now - gd is at
top-of-RAM
and the stack sits just below it. U-Boot .text, .data, .bss etc are below the stack and the heap is below U-Boot. I understand that other arch's
are
more complex (LCD frame buffers in top-of-RAM for example) - I think this can all be dealt with elegantly with this code as well, but I have not attempted to do so
[1] The board_init_f() has different meanings for different arch's
already
[2] This parameter is not used, but could be in future to remove the 'gd pointer in a fixed register' hack
This will not work as printf() and friends require a functional Global
Data
pointer
Passing a Global Data pointer to board_init_f_r() like I do is also problematic - I move Global Data to RAM and trash the in-cache copy, but the gd still points to the (now trashed) cache copy until we jump to RAM (quite frankly, I don't know how it worked in the first place...)
The only way this can work is if I either:
- Reserve a register, or
- Reserve a writeable location in some memory location which is
available
prior to SDRAM init
x86 is the only arch that does not use a reserved register for the global data pointer, but I have proved previously that x86 is capable of this construct:
http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/88462
So I'll adjust this patch set accordingly
I have a unified board series for ARM and x86 so will see if I can send it. Still needs work on x86.
Regards, Simon
Regards,
Graeme
participants (2)
-
Graeme Russ
-
Simon Glass