add LAPIC support of the 64bit kernel
This commit is contained in:
parent
609500a6d8
commit
654e91b0a2
3 changed files with 46 additions and 7 deletions
|
@ -151,7 +151,7 @@ inline static void wmb(void) { asm volatile("sfence" ::: "memory"); }
|
||||||
* @param d EDX value will be stores here
|
* @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) {
|
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
|
/** @brief Read MSR
|
||||||
|
@ -335,9 +335,7 @@ uint32_t read_eip(void);
|
||||||
inline static int system_init(void)
|
inline static int system_init(void)
|
||||||
{
|
{
|
||||||
gdt_install();
|
gdt_install();
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
apic_init();
|
apic_init();
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
pci_init();
|
pci_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,6 +42,13 @@
|
||||||
#error RockCreek is not a SMP system
|
#error RockCreek is not a SMP system
|
||||||
#endif
|
#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.
|
// IO APIC MMIO structure: write reg, then read or write data.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t reg;
|
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 uint32_t boot_processor = MAX_CORES;
|
||||||
static apic_mp_t* apic_mp = NULL;
|
static apic_mp_t* apic_mp = NULL;
|
||||||
static apic_config_table_t* apic_config = 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 volatile ioapic_t* ioapic = NULL;
|
||||||
static uint32_t icr = 0;
|
static uint32_t icr = 0;
|
||||||
static uint32_t ncores = 1;
|
static uint32_t ncores = 1;
|
||||||
|
@ -329,7 +336,7 @@ void smp_start(uint32_t id)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
#ifdef CONFIG_X86_32
|
||||||
static apic_mp_t* search_apic(size_t base, size_t limit) {
|
static apic_mp_t* search_apic(size_t base, size_t limit) {
|
||||||
size_t ptr;
|
size_t ptr;
|
||||||
apic_mp_t* tmp;
|
apic_mp_t* tmp;
|
||||||
|
@ -446,9 +453,11 @@ int map_apic(void)
|
||||||
if (!has_apic())
|
if (!has_apic())
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
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;
|
||||||
|
#endif
|
||||||
kprintf("Mapped LAPIC at 0x%x\n", lapic);
|
kprintf("Mapped LAPIC at 0x%x\n", lapic);
|
||||||
|
|
||||||
if (ioapic) {
|
if (ioapic) {
|
||||||
|
@ -569,12 +578,15 @@ static int apic_probe(void)
|
||||||
int isa_bus = -1;
|
int isa_bus = -1;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
apic_mp = search_apic(0xF0000, 0x100000);
|
apic_mp = search_apic(0xF0000, 0x100000);
|
||||||
if (apic_mp)
|
if (apic_mp)
|
||||||
goto found_mp;
|
goto found_mp;
|
||||||
apic_mp = search_apic(0x9F000, 0xA0000);
|
apic_mp = search_apic(0x9F000, 0xA0000);
|
||||||
if (apic_mp)
|
if (apic_mp)
|
||||||
goto found_mp;
|
goto found_mp;
|
||||||
|
#elif defined(CONFIG_X86_64)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
// searching MP signature in the reserved memory areas
|
// searching MP signature in the reserved memory areas
|
||||||
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_MEM_MAP)) {
|
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_MEM_MAP)) {
|
||||||
|
@ -620,7 +632,7 @@ found_mp:
|
||||||
goto no_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) {
|
if (!apic_config || strncmp((void*) &apic_config->signature, "PCMP", 4) !=0) {
|
||||||
kputs("Invalid MP config table\n");
|
kputs("Invalid MP config table\n");
|
||||||
goto no_mp;
|
goto no_mp;
|
||||||
|
@ -693,11 +705,16 @@ check_lapic:
|
||||||
if (apic_config) {
|
if (apic_config) {
|
||||||
lapic = apic_config->lapic;
|
lapic = apic_config->lapic;
|
||||||
} else {
|
} else {
|
||||||
uint32_t edx, dummy;
|
uint32_t edx, dummy=0;
|
||||||
|
|
||||||
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
|
||||||
|
// On a x64 system, we already map the lapic below the kernel
|
||||||
|
lapic = (size_t)&kernel_start - 0x1000;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lapic)
|
if (!lapic)
|
||||||
|
|
|
@ -177,6 +177,30 @@ L0:
|
||||||
or ebx, 0x00000003
|
or ebx, 0x00000003
|
||||||
mov DWORD [edi], ebx
|
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_start ; defined in linker script
|
||||||
extern kernel_end
|
extern kernel_end
|
||||||
mov edi, kernel_start
|
mov edi, kernel_start
|
||||||
|
|
Loading…
Add table
Reference in a new issue