diff options
Diffstat (limited to 'src/arch/x86/boot')
-rw-r--r-- | src/arch/x86/boot/boot.c | 66 | ||||
-rw-r--r-- | src/arch/x86/boot/gdt.c | 8 | ||||
-rw-r--r-- | src/arch/x86/boot/mpspec.c | 5 | ||||
-rw-r--r-- | src/arch/x86/boot/wakeup.S | 5 |
4 files changed, 79 insertions, 5 deletions
diff --git a/src/arch/x86/boot/boot.c b/src/arch/x86/boot/boot.c index d86a6c35b8..7eb87fbef6 100644 --- a/src/arch/x86/boot/boot.c +++ b/src/arch/x86/boot/boot.c @@ -39,17 +39,74 @@ static void jmp_payload(void *entry, unsigned long buffer, unsigned long size) /* Jump to kernel */ __asm__ __volatile__( " cld \n\t" +#ifdef __x86_64__ + /* switch back to 32-bit mode */ + " push %4\n\t" + " push %3\n\t" + " push %2\n\t" + " push %1\n\t" + " push %0\n\t" + + ".intel_syntax noprefix\n\t" + /* use iret to switch to 32-bit code segment */ + " xor rax,rax\n\t" + " mov ax, ss\n\t" + " push rax\n\t" + " mov rax, rsp\n\t" + " add rax, 8\n\t" + " push rax\n\t" + " pushfq\n\t" + " push 0x10\n\t" + " lea rax,[rip+3]\n\t" + " push rax\n\t" + " iretq\n\t" + ".code32\n\t" + /* disable paging */ + " mov eax, cr0\n\t" + " btc eax, 31\n\t" + " mov cr0, eax\n\t" + /* disable long mode */ + " mov ecx, 0xC0000080\n\t" + " rdmsr\n\t" + " btc eax, 8\n\t" + " wrmsr\n\t" + + " pop eax\n\t" + " add esp, 4\n\t" + " pop ebx\n\t" + " add esp, 4\n\t" + " pop ecx\n\t" + + " add esp, 4\n\t" + " pop edx\n\t" + " add esp, 4\n\t" + " pop esi\n\t" + " add esp, 4\n\t" + + ".att_syntax prefix\n\t" +#endif + /* Save the callee save registers... */ " pushl %%esi\n\t" " pushl %%edi\n\t" " pushl %%ebx\n\t" /* Save the parameters I was passed */ +#ifdef __x86_64__ + " pushl $0\n\t" /* 20 adjust */ + " pushl %%eax\n\t" /* 16 lb_start */ + " pushl %%ebx\n\t" /* 12 buffer */ + " pushl %%ecx\n\t" /* 8 lb_size */ + " pushl %%edx\n\t" /* 4 entry */ + " pushl %%esi\n\t" /* 0 elf_boot_notes */ +#else " pushl $0\n\t" /* 20 adjust */ " pushl %0\n\t" /* 16 lb_start */ " pushl %1\n\t" /* 12 buffer */ " pushl %2\n\t" /* 8 lb_size */ " pushl %3\n\t" /* 4 entry */ " pushl %4\n\t" /* 0 elf_boot_notes */ + +#endif /* Compute the adjustment */ " xorl %%eax, %%eax\n\t" " subl 16(%%esp), %%eax\n\t" @@ -115,7 +172,9 @@ static void jmp_payload(void *entry, unsigned long buffer, unsigned long size) " popl %%ebx\n\t" " popl %%edi\n\t" " popl %%esi\n\t" - +#ifdef __x86_64__ + ".code64\n\t" +#endif :: "ri" (lb_start), "ri" (buffer), "ri" (lb_size), "ri" (entry), @@ -140,7 +199,12 @@ void arch_prog_run(struct prog *prog) if (ENV_RAMSTAGE) try_payload(prog); __asm__ volatile ( +#ifdef __x86_64__ + "jmp *%%rdi\n" +#else "jmp *%%edi\n" +#endif + :: "D"(prog_entry(prog)) ); } diff --git a/src/arch/x86/boot/gdt.c b/src/arch/x86/boot/gdt.c index 44156ea3f6..a21fab24ad 100644 --- a/src/arch/x86/boot/gdt.c +++ b/src/arch/x86/boot/gdt.c @@ -26,7 +26,11 @@ /* i386 lgdt argument */ struct gdtarg { u16 limit; +#ifdef __x86_64__ + u64 base; +#else u32 base; +#endif } __attribute__((packed)); /* Copy GDT to new location and reload it. @@ -35,7 +39,7 @@ struct gdtarg { static void move_gdt(int is_recovery) { void *newgdt; - u16 num_gdt_bytes = (u32)&gdt_end - (u32)&gdt; + u16 num_gdt_bytes = (uintptr_t)&gdt_end - (uintptr_t)&gdt; struct gdtarg gdtarg; newgdt = cbmem_find(CBMEM_ID_GDT); @@ -49,7 +53,7 @@ static void move_gdt(int is_recovery) memcpy((void*)newgdt, &gdt, num_gdt_bytes); } - gdtarg.base = (u32)newgdt; + gdtarg.base = (uintptr_t)newgdt; gdtarg.limit = num_gdt_bytes - 1; __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg)); diff --git a/src/arch/x86/boot/mpspec.c b/src/arch/x86/boot/mpspec.c index 4474d7c6bd..1a0ac31fd0 100644 --- a/src/arch/x86/boot/mpspec.c +++ b/src/arch/x86/boot/mpspec.c @@ -73,7 +73,7 @@ static unsigned char smp_compute_checksum(void *v, int len) return checksum; } -static void *smp_write_floating_table_physaddr(u32 addr, u32 mpf_physptr, unsigned int virtualwire) +static void *smp_write_floating_table_physaddr(uintptr_t addr, uintptr_t mpf_physptr, unsigned int virtualwire) { struct intel_mp_floating *mf; void *v; @@ -591,6 +591,7 @@ unsigned long __attribute__((weak)) write_smp_table(unsigned long addr) mptable_lintsrc(mc, isa_bus); tmp = mptable_finalize(mc); - printk(BIOS_INFO, "MPTABLE len: %d\n", (unsigned int)tmp - (unsigned int)v); + printk(BIOS_INFO, "MPTABLE len: %d\n", (unsigned int)((uintptr_t)tmp - + (uintptr_t)v)); return (unsigned long)tmp; } diff --git a/src/arch/x86/boot/wakeup.S b/src/arch/x86/boot/wakeup.S index a614b55f03..38d6ea43ae 100644 --- a/src/arch/x86/boot/wakeup.S +++ b/src/arch/x86/boot/wakeup.S @@ -24,7 +24,12 @@ /* CR0 bits */ #define PE (1 << 0) +#ifdef __x86_64__ + .code64 +#else .code32 +#endif + .globl __wakeup __wakeup: /* First prepare the jmp to the resume vector */ |