diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index e0abceb3..4d61ee83 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -58,7 +58,7 @@ typedef struct { static const apic_processor_entry_t* apic_processors[MAX_CORES] = {[0 ... MAX_CORES-1] = NULL}; static uint32_t boot_processor = MAX_CORES; -static apic_mp_t* apic_mp = NULL; +apic_mp_t* apic_mp __attribute__ ((section (".data"))) = NULL; static apic_config_table_t* apic_config = NULL; static size_t lapic = 0; static volatile ioapic_t* ioapic = NULL; @@ -82,12 +82,15 @@ static inline uint32_t lapic_read(uint32_t addr) static inline void lapic_write(uint32_t addr, uint32_t value) { +#ifdef CONFIG_X86_32 /* * to avoid a pentium bug, we have to read a apic register * before we write a value to this register */ asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx"); - //*((volatile uint32_t*) (lapic+addr)) = value; +#else + *((volatile uint32_t*) (lapic+addr)) = value; +#endif } static inline uint32_t ioapic_read(uint32_t reg) @@ -457,6 +460,12 @@ int map_apic(void) lapic = map_region(0 /*lapic*/, lapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE); if (BUILTIN_EXPECT(!lapic, 0)) return -ENXIO; +#else + if (lapic != (size_t)&kernel_start - 0x1000) { + lapic = map_region(0 /*lapic*/, lapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE); + if (BUILTIN_EXPECT(!lapic, 0)) + return -ENXIO; + } #endif kprintf("Mapped LAPIC at 0x%x\n", lapic); @@ -469,7 +478,7 @@ int map_apic(void) // map all processor entries for(i=0; iid); } initialized = 1; +#ifdef CONFIG_X86_32 #if MAX_CORES > 1 smp_init(); +#endif #endif irq_nested_enable(flags); @@ -681,8 +692,8 @@ found_mp: apic_io_entry_t* io_entry = (apic_io_entry_t*) addr; ioapic = (ioapic_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 (ver. 0x%x)\n", ioapic, ioapic_read(IOAPIC_REG_VER)); + kprintf("Found IOAPIC at 0x%x\n", ioapic); } else if (*((uint8_t*) addr) == 3) { // IO_INT apic_ioirq_entry_t* extint = (apic_ioirq_entry_t*) addr; if (extint->src_bus == isa_bus) { @@ -701,6 +712,7 @@ found_mp: ncores = count; check_lapic: +#ifdef CONFIG_X86_32 if (apic_config) { lapic = apic_config->lapic; } else { @@ -708,13 +720,16 @@ check_lapic: cpuid(0x1, &dummy, &dummy, &dummy, &edx); if (edx & (1 << 9)) -#ifdef CONFIG_X86_32 lapic = 0xFEE00000; -#else - // On a x64 system, we already map the lapic below the kernel - lapic = (size_t)&kernel_start - 0x1000; -#endif } +#else + if (apic_config->lapic == 0xFEE00000) { + // On a x64 system, we already map the lapic below the kernel + lapic = (size_t)&kernel_start - 0x1000; + } else { + lapic = apic_config->lapic; + } +#endif if (!lapic) goto out; diff --git a/arch/x86/kernel/entry64.asm b/arch/x86/kernel/entry64.asm index e9400a2f..357950cd 100644 --- a/arch/x86/kernel/entry64.asm +++ b/arch/x86/kernel/entry64.asm @@ -24,6 +24,11 @@ %include "config.inc" [BITS 32] + +extern kernel_start ; defined in linker script +extern kernel_end +extern apic_mp + ; We use a special name to map this section at the begin of our kernel ; => Multiboot needs its magic number at the begin of the kernel SECTION .mboot @@ -90,6 +95,36 @@ boot_pd times 512 DQ 0 boot_pt times (NOPTS*512) DQ 0 SECTION .text +search_apic: + push ebp + mov ebp, esp + push ecx + + xor eax, eax + mov ecx, [ebp+8] +L1: + cmp [ecx], DWORD 0x5f504d5f ; MP_FLT_SIGNATURE + jne L2 + mov al, BYTE [ecx+9] + cmp eax, 4 + ja L2 + mov al, BYTE [ecx+11] + cmp eax, 0 + jne L2 + mov eax, ecx + jmp L3 + +L2: + add ecx, 4 + cmp ecx, [ebp+12] + jb L1 + xor eax, eax + +L3: + pop ecx + pop ebp + ret + ALIGN 4 stublet: mov esp, startup_stack-4 @@ -180,8 +215,7 @@ L0: cmp edx, 0 je no_lapic ; map lapic at 0xFEE00000 below the kernel - mov edi, kernel_start - sub edi, 0x1000 + mov edi, kernel_start - 0x1000 shr edi, 9 ; (edi >> 12) * 8 add edi, boot_pt mov ebx, 0xFEE00000 @@ -193,8 +227,36 @@ no_lapic: pop ebx pop eax - extern kernel_start ; defined in linker script - extern kernel_end + ; search APIC + push DWORD 0x100000 + push DWORD 0xF0000 + call search_apic + add esp, 8 + + cmp eax, 0 + jne La + + push DWORD 0xA0000 + push DWORD 0x9F000 + call search_apic + add esp, 8 + + cmp eax, 0 + je Lb + +La: + ; map MP Floating Pointer Structure + mov DWORD [apic_mp], eax + mov edi, eax + and edi, 0xFFFFF000 + shr edi, 9 ; (edi >> 12) * 8 + add edi, boot_pt + mov ebx, eax + and ebx, 0xFFFFF000 + or ebx, 0x00000013 + mov DWORD [edi], ebx + +Lb: mov edi, kernel_start shr edi, 9 ; (kernel_start >> 12) * 8 add edi, boot_pt @@ -205,11 +267,11 @@ no_lapic: shr ecx, 12 inc ecx -L1: +Lc: mov DWORD [edi], ebx ; Set the double word at the destination index to the B-register. add edi, 8 add ebx, 0x1000 - loop L1 + loop Lc ; we need to enable PAE modus mov eax, cr4