enable full (64bit) APIC support
- no SMP support
This commit is contained in:
parent
44ea32c241
commit
08bcc19626
2 changed files with 93 additions and 16 deletions
|
@ -58,7 +58,7 @@ typedef struct {
|
||||||
|
|
||||||
static const apic_processor_entry_t* apic_processors[MAX_CORES] = {[0 ... MAX_CORES-1] = NULL};
|
static const apic_processor_entry_t* apic_processors[MAX_CORES] = {[0 ... MAX_CORES-1] = NULL};
|
||||||
static uint32_t boot_processor = MAX_CORES;
|
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 apic_config_table_t* apic_config = NULL;
|
||||||
static size_t lapic = 0;
|
static size_t lapic = 0;
|
||||||
static volatile ioapic_t* ioapic = NULL;
|
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)
|
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
|
* to avoid a pentium bug, we have to read a apic register
|
||||||
* before we write a value to this register
|
* before we write a value to this register
|
||||||
*/
|
*/
|
||||||
asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx");
|
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)
|
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);
|
lapic = map_region(0 /*lapic*/, lapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||||
if (BUILTIN_EXPECT(!lapic, 0))
|
if (BUILTIN_EXPECT(!lapic, 0))
|
||||||
return -ENXIO;
|
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
|
#endif
|
||||||
kprintf("Mapped LAPIC at 0x%x\n", lapic);
|
kprintf("Mapped LAPIC at 0x%x\n", lapic);
|
||||||
|
|
||||||
|
@ -469,7 +478,7 @@ int map_apic(void)
|
||||||
// map all processor entries
|
// map all processor entries
|
||||||
for(i=0; i<MAX_CORES; i++) {
|
for(i=0; i<MAX_CORES; i++) {
|
||||||
if (apic_processors[i] && (old != (((size_t)apic_processors[i]) & 0xFFFFF000)))
|
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);
|
ioapic_inton(i, apic_processors[boot_processor]->id);
|
||||||
}
|
}
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
#if MAX_CORES > 1
|
#if MAX_CORES > 1
|
||||||
smp_init();
|
smp_init();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
irq_nested_enable(flags);
|
irq_nested_enable(flags);
|
||||||
|
|
||||||
|
@ -681,8 +692,8 @@ found_mp:
|
||||||
apic_io_entry_t* io_entry = (apic_io_entry_t*) addr;
|
apic_io_entry_t* io_entry = (apic_io_entry_t*) addr;
|
||||||
ioapic = (ioapic_t*) io_entry->addr;
|
ioapic = (ioapic_t*) io_entry->addr;
|
||||||
addr += 8;
|
addr += 8;
|
||||||
kprintf("Found IOAPIC at 0x%x (ver. 0x%x)\n", ioapic,
|
//kprintf("Found IOAPIC at 0x%x (ver. 0x%x)\n", ioapic, ioapic_read(IOAPIC_REG_VER));
|
||||||
ioapic_read(IOAPIC_REG_VER));
|
kprintf("Found IOAPIC at 0x%x\n", ioapic);
|
||||||
} else if (*((uint8_t*) addr) == 3) { // IO_INT
|
} else if (*((uint8_t*) addr) == 3) { // IO_INT
|
||||||
apic_ioirq_entry_t* extint = (apic_ioirq_entry_t*) addr;
|
apic_ioirq_entry_t* extint = (apic_ioirq_entry_t*) addr;
|
||||||
if (extint->src_bus == isa_bus) {
|
if (extint->src_bus == isa_bus) {
|
||||||
|
@ -701,6 +712,7 @@ found_mp:
|
||||||
ncores = count;
|
ncores = count;
|
||||||
|
|
||||||
check_lapic:
|
check_lapic:
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
if (apic_config) {
|
if (apic_config) {
|
||||||
lapic = apic_config->lapic;
|
lapic = apic_config->lapic;
|
||||||
} else {
|
} else {
|
||||||
|
@ -708,13 +720,16 @@ check_lapic:
|
||||||
|
|
||||||
cpuid(0x1, &dummy, &dummy, &dummy, &edx);
|
cpuid(0x1, &dummy, &dummy, &dummy, &edx);
|
||||||
if (edx & (1 << 9))
|
if (edx & (1 << 9))
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
lapic = 0xFEE00000;
|
lapic = 0xFEE00000;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
if (apic_config->lapic == 0xFEE00000) {
|
||||||
// On a x64 system, we already map the lapic below the kernel
|
// On a x64 system, we already map the lapic below the kernel
|
||||||
lapic = (size_t)&kernel_start - 0x1000;
|
lapic = (size_t)&kernel_start - 0x1000;
|
||||||
#endif
|
} else {
|
||||||
|
lapic = apic_config->lapic;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!lapic)
|
if (!lapic)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
%include "config.inc"
|
%include "config.inc"
|
||||||
|
|
||||||
[BITS 32]
|
[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
|
; 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
|
; => Multiboot needs its magic number at the begin of the kernel
|
||||||
SECTION .mboot
|
SECTION .mboot
|
||||||
|
@ -90,6 +95,36 @@ boot_pd times 512 DQ 0
|
||||||
boot_pt times (NOPTS*512) DQ 0
|
boot_pt times (NOPTS*512) DQ 0
|
||||||
|
|
||||||
SECTION .text
|
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
|
ALIGN 4
|
||||||
stublet:
|
stublet:
|
||||||
mov esp, startup_stack-4
|
mov esp, startup_stack-4
|
||||||
|
@ -180,8 +215,7 @@ L0:
|
||||||
cmp edx, 0
|
cmp edx, 0
|
||||||
je no_lapic
|
je no_lapic
|
||||||
; map lapic at 0xFEE00000 below the kernel
|
; map lapic at 0xFEE00000 below the kernel
|
||||||
mov edi, kernel_start
|
mov edi, kernel_start - 0x1000
|
||||||
sub edi, 0x1000
|
|
||||||
shr edi, 9 ; (edi >> 12) * 8
|
shr edi, 9 ; (edi >> 12) * 8
|
||||||
add edi, boot_pt
|
add edi, boot_pt
|
||||||
mov ebx, 0xFEE00000
|
mov ebx, 0xFEE00000
|
||||||
|
@ -193,8 +227,36 @@ no_lapic:
|
||||||
pop ebx
|
pop ebx
|
||||||
pop eax
|
pop eax
|
||||||
|
|
||||||
extern kernel_start ; defined in linker script
|
; search APIC
|
||||||
extern kernel_end
|
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
|
mov edi, kernel_start
|
||||||
shr edi, 9 ; (kernel_start >> 12) * 8
|
shr edi, 9 ; (kernel_start >> 12) * 8
|
||||||
add edi, boot_pt
|
add edi, boot_pt
|
||||||
|
@ -205,11 +267,11 @@ no_lapic:
|
||||||
shr ecx, 12
|
shr ecx, 12
|
||||||
inc ecx
|
inc ecx
|
||||||
|
|
||||||
L1:
|
Lc:
|
||||||
mov DWORD [edi], ebx ; Set the double word at the destination index to the B-register.
|
mov DWORD [edi], ebx ; Set the double word at the destination index to the B-register.
|
||||||
add edi, 8
|
add edi, 8
|
||||||
add ebx, 0x1000
|
add ebx, 0x1000
|
||||||
loop L1
|
loop Lc
|
||||||
|
|
||||||
; we need to enable PAE modus
|
; we need to enable PAE modus
|
||||||
mov eax, cr4
|
mov eax, cr4
|
||||||
|
|
Loading…
Add table
Reference in a new issue