enable full (64bit) APIC support

- no SMP support
This commit is contained in:
Stefan Lankes 2012-06-11 21:49:17 +02:00
parent 44ea32c241
commit 08bcc19626
2 changed files with 93 additions and 16 deletions

View file

@ -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; i<MAX_CORES; i++) {
if (apic_processors[i] && (old != (((size_t)apic_processors[i]) & 0xFFFFF000)))
old = map_region(((size_t) apic_processors[i]) & 0xFFFFF000, ((size_t) apic_processors[i]) & 0xFFFFF000, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE);
old = map_region(((size_t) apic_processors[i]) & 0xFFFFF000, ((size_t) apic_processors[i]) & 0xFFFFF000, 1, MAP_REMAP|MAP_KERNEL_SPACE|MAP_NO_CACHE);
}
}
@ -563,8 +572,10 @@ 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);
@ -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;

View file

@ -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