add LAPIC support of the 64bit kernel

This commit is contained in:
Stefan Lankes 2012-06-10 21:38:01 +02:00
parent 609500a6d8
commit 654e91b0a2
3 changed files with 46 additions and 7 deletions

View file

@ -151,7 +151,7 @@ inline static void wmb(void) { asm volatile("sfence" ::: "memory"); }
* @param d EDX value will be stores here
*/
inline static void cpuid(uint32_t code, uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d) {
asm volatile ("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(code));
asm volatile ("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(code), "2"(*c));
}
/** @brief Read MSR
@ -335,9 +335,7 @@ uint32_t read_eip(void);
inline static int system_init(void)
{
gdt_install();
#ifdef CONFIG_X86_32
apic_init();
#endif
#ifdef CONFIG_PCI
pci_init();
#endif

View file

@ -42,6 +42,13 @@
#error RockCreek is not a SMP system
#endif
/*
* Note that linker symbols are not variables, they have no memory allocated for
* maintaining a value, rather their address is their value.
*/
extern const void kernel_start;
extern const void kernel_end;
// IO APIC MMIO structure: write reg, then read or write data.
typedef struct {
uint32_t reg;
@ -53,7 +60,7 @@ static const apic_processor_entry_t* apic_processors[MAX_CORES] = {[0 ... MAX_CO
static uint32_t boot_processor = MAX_CORES;
static apic_mp_t* apic_mp = NULL;
static apic_config_table_t* apic_config = NULL;
static uint32_t lapic = 0;
static size_t lapic = 0;
static volatile ioapic_t* ioapic = NULL;
static uint32_t icr = 0;
static uint32_t ncores = 1;
@ -329,7 +336,7 @@ void smp_start(uint32_t id)
}
#endif
#if 1
#ifdef CONFIG_X86_32
static apic_mp_t* search_apic(size_t base, size_t limit) {
size_t ptr;
apic_mp_t* tmp;
@ -446,9 +453,11 @@ int map_apic(void)
if (!has_apic())
return -ENXIO;
#ifdef CONFIG_X86_32
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);
if (ioapic) {
@ -569,12 +578,15 @@ static int apic_probe(void)
int isa_bus = -1;
#if 1
#ifdef CONFIG_X86_32
apic_mp = search_apic(0xF0000, 0x100000);
if (apic_mp)
goto found_mp;
apic_mp = search_apic(0x9F000, 0xA0000);
if (apic_mp)
goto found_mp;
#elif defined(CONFIG_X86_64)
#endif
#else
// searching MP signature in the reserved memory areas
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_MEM_MAP)) {
@ -620,7 +632,7 @@ found_mp:
goto no_mp;
}
apic_config = (apic_config_table_t*) apic_mp->mp_config;
apic_config = (apic_config_table_t*) ((size_t) apic_mp->mp_config);
if (!apic_config || strncmp((void*) &apic_config->signature, "PCMP", 4) !=0) {
kputs("Invalid MP config table\n");
goto no_mp;
@ -693,11 +705,16 @@ check_lapic:
if (apic_config) {
lapic = apic_config->lapic;
} else {
uint32_t edx, dummy;
uint32_t edx, dummy=0;
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
}
if (!lapic)

View file

@ -177,6 +177,30 @@ L0:
or ebx, 0x00000003
mov DWORD [edi], ebx
; check if lapic is available
push eax
push ebx
push ecx
push edx
mov eax, 1
cpuid
and edx, 0x200
cmp edx, 0
je no_lapic
; map lapic at 0xFEE00000 below the kernel
mov edi, kernel_start
sub edi, 0x1000
shr edi, 9 ; (edi >> 12) * 8
add edi, boot_pt
mov ebx, 0xFEE00000
or ebx, 0x00000013
mov DWORD [edi], ebx
no_lapic:
pop edx
pop ecx
pop ebx
pop eax
extern kernel_start ; defined in linker script
extern kernel_end
mov edi, kernel_start