diff --git a/PROTOCOL.md b/PROTOCOL.md index 96d41cec..16a65e54 100644 --- a/PROTOCOL.md +++ b/PROTOCOL.md @@ -137,10 +137,9 @@ IF flag, VM flag, and direction flag are cleared on entry. Other flags undefined. PG is enabled (`cr0`), PE is enabled (`cr0`), PAE is enabled (`cr4`), -LME is enabled (`EFER`). +WP is enabled (`cr0`), LME is enabled (`EFER`), NX is enabled (`EFER`). If 5-level paging is requested and available, then 5-level paging is enabled (LA57 bit in `cr4`). -The NX bit will be enabled (NX bit in `EFER`). The A20 gate is opened. diff --git a/common/protos/limine.c b/common/protos/limine.c index 514a53b8..d17160a0 100644 --- a/common/protos/limine.c +++ b/common/protos/limine.c @@ -699,7 +699,7 @@ FEAT_START &cpu_count, &bsp_lapic_id, true, want_5lv, pagemap, smp_request->flags & LIMINE_SMP_X2APIC, true, - direct_map_offset); + direct_map_offset, true); if (smp_info == NULL) { break; @@ -800,7 +800,7 @@ FEAT_END term_runtime = true; stivale_spinup(64, want_5lv, &pagemap, entry_point, 0, - reported_addr(stack), true, (uintptr_t)local_gdt); + reported_addr(stack), true, true, (uintptr_t)local_gdt); __builtin_unreachable(); } diff --git a/common/protos/stivale.32.c b/common/protos/stivale.32.c index ed06a5f2..63fc4072 100644 --- a/common/protos/stivale.32.c +++ b/common/protos/stivale.32.c @@ -5,7 +5,7 @@ #include noreturn void stivale_spinup_32( - int bits, bool level5pg, bool enable_nx, uint32_t pagemap_top_lv, + int bits, bool level5pg, bool enable_nx, bool wp, uint32_t pagemap_top_lv, uint32_t entry_point_lo, uint32_t entry_point_hi, uint32_t stivale_struct_lo, uint32_t stivale_struct_hi, uint32_t stack_lo, uint32_t stack_hi, @@ -38,6 +38,15 @@ noreturn void stivale_spinup_32( ); } + if (wp) { + asm volatile ( + "movl %%cr0, %%eax\n\t" + "btsl $16, %%eax\n\t" + "movl %%eax, %%cr0\n\t" + ::: "eax", "memory" + ); + } + asm volatile ( "cld\n\t" "movl %%eax, %%cr3\n\t" diff --git a/common/protos/stivale.c b/common/protos/stivale.c index a8cae28d..5ffdfa52 100644 --- a/common/protos/stivale.c +++ b/common/protos/stivale.c @@ -368,7 +368,7 @@ bool stivale_load(char *config, char *cmdline) { stivale_spinup(bits, want_5lv, &pagemap, entry_point, REPORTED_ADDR((uint64_t)(uintptr_t)stivale_struct), - stivale_hdr.stack, false, (uintptr_t)local_gdt); + stivale_hdr.stack, false, false, (uintptr_t)local_gdt); __builtin_unreachable(); @@ -487,7 +487,7 @@ noreturn void stivale_spinup_32( noreturn void stivale_spinup( int bits, bool level5pg, pagemap_t *pagemap, uint64_t entry_point, uint64_t _stivale_struct, uint64_t stack, - bool enable_nx, uint32_t local_gdt) { + bool enable_nx, bool wp, uint32_t local_gdt) { #if bios == 1 if (bits == 64) { // If we're going 64, we might as well call this BIOS interrupt @@ -509,8 +509,8 @@ noreturn void stivale_spinup( irq_flush_type = IRQ_PIC_APIC_FLUSH; - common_spinup(stivale_spinup_32, 11, - bits, level5pg, enable_nx, (uint32_t)(uintptr_t)pagemap->top_level, + common_spinup(stivale_spinup_32, 12, + bits, level5pg, enable_nx, wp, (uint32_t)(uintptr_t)pagemap->top_level, (uint32_t)entry_point, (uint32_t)(entry_point >> 32), (uint32_t)_stivale_struct, (uint32_t)(_stivale_struct >> 32), (uint32_t)stack, (uint32_t)(stack >> 32), local_gdt); diff --git a/common/protos/stivale.h b/common/protos/stivale.h index 9b7e8e67..83c99d53 100644 --- a/common/protos/stivale.h +++ b/common/protos/stivale.h @@ -17,6 +17,6 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range noreturn void stivale_spinup( int bits, bool level5pg, pagemap_t *pagemap, uint64_t entry_point, uint64_t stivale_struct, uint64_t stack, - bool enable_nx, uint32_t local_gdt); + bool enable_nx, bool wp, uint32_t local_gdt); #endif diff --git a/common/protos/stivale2.c b/common/protos/stivale2.c index 87be3cd1..bc002f09 100644 --- a/common/protos/stivale2.c +++ b/common/protos/stivale2.c @@ -765,7 +765,8 @@ have_tm_tag:; &cpu_count, &bsp_lapic_id, bits == 64, want_5lv, pagemap, smp_hdr_tag->flags & 1, want_pmrs, - stivale2_hdr.flags & (1 << 1) ? direct_map_offset : 0); + stivale2_hdr.flags & (1 << 1) ? direct_map_offset : 0, + want_pmrs); if (smp_info != NULL) { tag->tag.identifier = STIVALE2_STRUCT_TAG_SMP_ID; @@ -833,7 +834,7 @@ have_tm_tag:; stivale_spinup(bits, want_5lv, &pagemap, entry_point, REPORTED_ADDR((uint64_t)(uintptr_t)stivale2_struct), - stivale2_hdr.stack, want_pmrs, (uintptr_t)local_gdt); + stivale2_hdr.stack, want_pmrs, want_pmrs, (uintptr_t)local_gdt); __builtin_unreachable(); diff --git a/common/sys/smp.c b/common/sys/smp.c index 3c60518c..2c29b353 100644 --- a/common/sys/smp.c +++ b/common/sys/smp.c @@ -54,7 +54,7 @@ struct trampoline_passed_info { static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr, struct smp_information *info_struct, bool longmode, bool lv5, uint32_t pagemap, - bool x2apic, bool nx, uint64_t hhdm) { + bool x2apic, bool nx, uint64_t hhdm, bool wp) { size_t trampoline_size = (size_t)_binary_smp_trampoline_bin_end - (size_t)_binary_smp_trampoline_bin_start; @@ -78,6 +78,7 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr, passed_info->smp_tpl_target_mode = ((uint32_t)x2apic << 2) | ((uint32_t)lv5 << 1) | ((uint32_t)nx << 3) + | ((uint32_t)wp << 4) | (uint32_t)longmode; passed_info->smp_tpl_gdt = *gdtr; passed_info->smp_tpl_booted_flag = 0; @@ -122,7 +123,8 @@ struct smp_information *init_smp(size_t header_hack_size, pagemap_t pagemap, bool x2apic, bool nx, - uint64_t hhdm) { + uint64_t hhdm, + bool wp) { if (!lapic_check()) return NULL; @@ -227,7 +229,7 @@ struct smp_information *init_smp(size_t header_hack_size, // Try to start the AP if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct, longmode, lv5, (uintptr_t)pagemap.top_level, - x2apic, nx, hhdm)) { + x2apic, nx, hhdm, wp)) { print("smp: FAILED to bring-up AP\n"); continue; } @@ -264,7 +266,7 @@ struct smp_information *init_smp(size_t header_hack_size, // Try to start the AP if (!smp_start_ap(x2lapic->x2apic_id, &gdtr, info_struct, longmode, lv5, (uintptr_t)pagemap.top_level, - true, nx, hhdm)) { + true, nx, hhdm, wp)) { print("smp: FAILED to bring-up AP\n"); continue; } diff --git a/common/sys/smp.h b/common/sys/smp.h index df272871..6ac759e0 100644 --- a/common/sys/smp.h +++ b/common/sys/smp.h @@ -23,6 +23,7 @@ struct smp_information *init_smp(size_t header_hack_size, pagemap_t pagemap, bool x2apic, bool nx, - uint64_t hhdm); + uint64_t hhdm, + bool wp); #endif diff --git a/common/sys/smp_trampoline.real b/common/sys/smp_trampoline.real index 0bf44d0d..56b94e08 100644 --- a/common/sys/smp_trampoline.real +++ b/common/sys/smp_trampoline.real @@ -101,6 +101,14 @@ smp_trampoline: wrmsr .nonx: + test dword [rbx + passed_info.target_mode], (1 << 4) + jz .nowp + + mov rax, cr0 + bts rax, 16 + mov cr0, rax + + .nowp: mov rax, qword [rbx + passed_info.hhdm] add qword [rbx + passed_info.gdtr + 2], rax lgdt [rbx + passed_info.gdtr]