From e06d910514d065cecf1d68d2fee660d831d4e00b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 12 Jun 2012 23:42:02 +0200 Subject: [PATCH 1/3] enable SMP support for 64bit systems --- arch/x86/kernel/apic.c | 20 +++++++++---- arch/x86/kernel/entry64.asm | 58 ++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 4d61ee83..e0f68580 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -290,6 +290,13 @@ extern void cpu_init(void); */ extern int smp_main(void); +#ifdef CONFIG_X86_64 +/* + * 32bit entry point, which jumps to the 64bit code smp_start + */ +extern void smp_entry(void); +#endif + void smp_start(uint32_t id) { size_t i; @@ -385,8 +392,13 @@ int smp_init(void) { // replace 0xDEADC0DE with the address of the smp entry code if (*((uint32_t*) (bootaddr+j)) == 0xDEADC0DE) { - *((uint32_t*) (bootaddr+j)) = (size_t) smp_start; - kprintf("Set entry point of the application processors at 0x%x\n", (size_t) smp_start); +#ifdef CONFIG_X86_32 + *((uint32_t*) (bootaddr+j)) = (uint32_t) smp_start; + kprintf("Set entry point of the application processors at 0x%x\n", (uint32_t) smp_start); +#else + *((uint32_t*) (bootaddr+j)) = (uint32_t) smp_entry; + kprintf("Set entry point of the application processors at 0x%lx\n", (size_t) smp_entry); +#endif } // replace APIC ID 0xDEADDEAD @@ -572,10 +584,8 @@ int apic_calibration(void) ioapic_inton(i, apic_processors[boot_processor]->id); } initialized = 1; -#ifdef CONFIG_X86_32 #if MAX_CORES > 1 smp_init(); -#endif #endif irq_nested_enable(flags); @@ -690,7 +700,7 @@ found_mp: addr += 20; } else if (*((uint8_t*) addr) == 2) { // IO_APIC apic_io_entry_t* io_entry = (apic_io_entry_t*) addr; - ioapic = (ioapic_t*) io_entry->addr; + ioapic = (ioapic_t*) ((size_t) io_entry->addr); addr += 8; //kprintf("Found IOAPIC at 0x%x (ver. 0x%x)\n", ioapic, ioapic_read(IOAPIC_REG_VER)); kprintf("Found IOAPIC at 0x%x\n", ioapic); diff --git a/arch/x86/kernel/entry64.asm b/arch/x86/kernel/entry64.asm index 00b3697f..04108c2d 100644 --- a/arch/x86/kernel/entry64.asm +++ b/arch/x86/kernel/entry64.asm @@ -95,6 +95,48 @@ boot_pd times 512 DQ 0 boot_pt times (NOPTS*512) DQ 0 SECTION .text +ALIGN 8 +global smp_entry +smp_entry: +; enable caching, disable paging and fpu emulation + and eax, 0x1ffffffb +; ...and turn on FPU exceptions + or eax, 0x22 + mov cr0, eax +; clears the current pgd entry + xor eax, eax + mov cr3, eax +; at this stage, we disable the SSE support + mov eax, cr4 + and eax, 0xfffbf9ff + mov cr4, eax + +; initialize page table + mov edi, boot_pgd + mov cr3, edi + +; we need to enable PAE modus + mov eax, cr4 + or eax, 1 << 5 + mov cr4, eax + +; switch to the compatibility mode (which is part of long mode) + mov ecx, 0xC0000080 + rdmsr + or eax, 1 << 8 + wrmsr + +; enable paging + mov eax, cr0 + or eax, 1 << 31 | 1 << 0 ; Set the PG-bit, which is the 31nd bit, and the PM-bit, which is the 0th bit. + mov cr0, eax + + mov edi, [esp+4] ; set argumet for smp_start + lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table. + jmp GDT64.Code:smp_start64 ; Set the code segment and enter 64-bit long mode. + + jmp $ ; endless loop + search_apic: push ebp mov ebp, esp @@ -322,11 +364,25 @@ start64: extern multiboot_init mov rdi, rbx call multiboot_init - ; jump to the boot processors's C code +; jump to the boot processors's C code extern main call main jmp $ +smp_start64: +; initialize segment registers + mov ax, GDT64.Data + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + +; jump to the boot processors's C code + extern smp_start + call smp_start + jmp $ + global cpu_init cpu_init: ; mov eax, cr0 From ab27285843a05cccb9a45f3ebd6b5d40ff5278c4 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 13 Jun 2012 11:22:38 +0200 Subject: [PATCH 2/3] disable obsolete 64bit code --- arch/x86/kernel/apic.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index e0f68580..9cb50922 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -299,7 +299,9 @@ extern void smp_entry(void); void smp_start(uint32_t id) { +#ifdef CONFIG_X86_32 size_t i; +#endif atomic_int32_inc(&cpu_online); @@ -318,6 +320,8 @@ void smp_start(uint32_t id) // install IDT idt_install(); + // On 64bit system, paging is already enabled +#ifdef CONFIG_X86_32 /* enable paging */ write_cr3((size_t)get_boot_pgd()); i = read_cr0(); @@ -327,6 +331,7 @@ void smp_start(uint32_t id) // reset APIC and set id lapic_reset(); // sets also the timer interrupt apic_set_cpu_id(id); +#endif /* * we turned on paging From be3eed681e01a44b87e11a99d4b677666250bc82 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 13 Jun 2012 11:23:05 +0200 Subject: [PATCH 3/3] use the correct data type for the CR4 register --- arch/x86/kernel/processor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/processor.c b/arch/x86/kernel/processor.c index d66c1125..5a0a86c0 100644 --- a/arch/x86/kernel/processor.c +++ b/arch/x86/kernel/processor.c @@ -31,7 +31,8 @@ static uint32_t cpu_freq = 0; int cpu_detection(void) { - uint32_t a, b, cr4; + uint32_t a, b; + size_t cr4; cpuid(1, &a, &b, &cpu_info.feature2, &cpu_info.feature1);