smp: Fix bug where started APs would not be aware of 5-level paging

This commit is contained in:
mintsuki 2020-09-18 20:21:16 +02:00
parent 927851e24d
commit 73fa01d1d0
5 changed files with 22 additions and 10 deletions

Binary file not shown.

View File

@ -327,8 +327,8 @@ void stivale2_load(char *cmdline, int boot_drive) {
if (smp_hdr_tag != NULL) { if (smp_hdr_tag != NULL) {
struct stivale2_struct_tag_smp *tag = balloc(sizeof(struct stivale2_struct_tag_smp)); struct stivale2_struct_tag_smp *tag = balloc(sizeof(struct stivale2_struct_tag_smp));
init_smp((size_t*)&tag->cpu_count, bits == 64, pagemap, init_smp((size_t*)&tag->cpu_count, bits == 64, level5pg && level5pg_requested,
smp_hdr_tag->flags & 1); pagemap, smp_hdr_tag->flags & 1);
append_tag(&stivale2_struct, (struct stivale2_tag *)tag); append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
} }

View File

@ -47,12 +47,12 @@ uint8_t smp_tpl_target_mode;
static bool smp_start_ap(uint8_t lapic_id, struct gdtr *gdtr, static bool smp_start_ap(uint8_t lapic_id, struct gdtr *gdtr,
struct smp_information *info_struct, struct smp_information *info_struct,
uint8_t target_mode, uint32_t pagemap) { bool longmode, bool lv5, uint32_t pagemap) {
// Prepare the trampoline // Prepare the trampoline
smp_tpl_info_struct = info_struct; smp_tpl_info_struct = info_struct;
smp_tpl_booted_flag = 0; smp_tpl_booted_flag = 0;
smp_tpl_pagemap = pagemap; smp_tpl_pagemap = pagemap;
smp_tpl_target_mode = target_mode; smp_tpl_target_mode = ((uint32_t)lv5 << 1) | (uint32_t)longmode;
smp_tpl_gdt = *gdtr; smp_tpl_gdt = *gdtr;
// Send the INIT IPI // Send the INIT IPI
@ -76,6 +76,7 @@ static bool smp_start_ap(uint8_t lapic_id, struct gdtr *gdtr,
struct smp_information *init_smp(size_t *cpu_count, struct smp_information *init_smp(size_t *cpu_count,
bool longmode, bool longmode,
bool lv5,
pagemap_t pagemap, pagemap_t pagemap,
bool x2apic) { bool x2apic) {
// Search for MADT table // Search for MADT table
@ -120,12 +121,14 @@ struct smp_information *init_smp(size_t *cpu_count,
// Try to start the AP // Try to start the AP
if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct, if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct,
longmode ? 1 : 0, (uint32_t)pagemap.top_level)) { longmode, lv5, (uint32_t)pagemap.top_level)) {
print("smp: FAILED to bring-up AP\n"); print("smp: FAILED to bring-up AP\n");
brewind(sizeof(struct smp_information)); brewind(sizeof(struct smp_information));
continue; continue;
} }
print("smp: Successfully brought up AP\n");
(*cpu_count)++; (*cpu_count)++;
break; break;
} }

View File

@ -15,6 +15,7 @@ struct smp_information {
struct smp_information *init_smp(size_t *cpu_count, struct smp_information *init_smp(size_t *cpu_count,
bool longmode, bool longmode,
bool lv5,
pagemap_t pagemap, pagemap_t pagemap,
bool x2apic); bool x2apic);

View File

@ -36,16 +36,24 @@ smp_trampoline:
btr eax, 30 btr eax, 30
mov cr0, eax mov cr0, eax
cmp dword [smp_tpl_target_mode], 0 test dword [smp_tpl_target_mode], (1 << 0)
je parking32 jz parking32
mov eax, dword [smp_tpl_pagemap]
mov cr3, eax
mov eax, cr4 mov eax, cr4
bts eax, 5 bts eax, 5
mov cr4, eax mov cr4, eax
test dword [smp_tpl_target_mode], (1 << 1)
jz .no5lv
mov eax, cr4
bts eax, 12
mov cr4, eax
.no5lv:
mov eax, dword [smp_tpl_pagemap]
mov cr3, eax
mov ecx, 0xc0000080 mov ecx, 0xc0000080
rdmsr rdmsr
bts eax, 8 bts eax, 8