summaryrefslogtreecommitdiff
path: root/src/arch/x86/boot
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/boot')
-rw-r--r--src/arch/x86/boot/boot.c66
-rw-r--r--src/arch/x86/boot/gdt.c8
-rw-r--r--src/arch/x86/boot/mpspec.c5
-rw-r--r--src/arch/x86/boot/wakeup.S5
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 */