diff --git a/arch/x86/apic.c b/arch/x86/apic.c index 17fa946b..1ca2feb9 100644 --- a/arch/x86/apic.c +++ b/arch/x86/apic.c @@ -161,7 +161,7 @@ void init_apic(unsigned int cpu_id, apic_mode_t mode) { * X2APIC uses MSRs for accesses, so no mapping needed. */ if (apic_mode == APIC_MODE_XAPIC) - vmap_kern_4k(apic_get_base(apic_base), apic_base.base, L1_PROT_NOCACHE); + vmap_kern_4k(apic_get_base(apic_base), apic_base.base, L1_PROT_NOCACHE_GLOB); spiv.reg = apic_read(APIC_SPIV); spiv.vector = APIC_SPI_VECTOR; diff --git a/arch/x86/pagetables.c b/arch/x86/pagetables.c index 684a106b..f7716994 100644 --- a/arch/x86/pagetables.c +++ b/arch/x86/pagetables.c @@ -430,7 +430,7 @@ static void map_tmp_mapping_entry(void) { pte_t *entry = l1_table_entry(mfn_to_virt(l1e->mfn), _tmp_mapping); /* Map _tmp_mapping_entry PTE of new page tables */ - vmap_kern_4k(mfn_to_virt_kern(l1e->mfn), l1e->mfn, L1_PROT); + vmap_kern_4k(mfn_to_virt_kern(l1e->mfn), l1e->mfn, L1_PROT_GLOB); /* Point _tmp_mapping_entry at new page tables location */ _tmp_mapping_entry = paddr_to_virt_kern(_paddr(entry)); @@ -1122,5 +1122,6 @@ void init_pagetables(void) { map_multiboot_areas(); map_tmp_mapping_entry(); + setup_tlb_global(); write_cr3(cr3.paddr); } diff --git a/common/cmdline.c b/common/cmdline.c index e510056e..bbc48692 100644 --- a/common/cmdline.c +++ b/common/cmdline.c @@ -76,6 +76,9 @@ bool_cmd("fb_scroll", opt_fb_scroll); unsigned long opt_reboot_timeout = 0; /* Disabled by default */ ulong_cmd("reboot_timeout", opt_reboot_timeout); +bool opt_tlb_global = true; +bool_cmd("tlb_global", opt_tlb_global); + const char *kernel_cmdline; void __text_init cmdline_parse(const char *cmdline) { diff --git a/common/usermode.c b/common/usermode.c index 38724584..030a11ac 100644 --- a/common/usermode.c +++ b/common/usermode.c @@ -107,17 +107,17 @@ static void init_sysenter(percpu_t *percpu) { } void init_usermode(percpu_t *percpu) { - vmap_user_4k(&cr3, virt_to_mfn(&cr3), L1_PROT); + vmap_user_4k(&cr3, virt_to_mfn(&cr3), L1_PROT_GLOB); vmap_user_4k(&user_cr3, virt_to_mfn(&user_cr3), L1_PROT); BUG_ON(end_exception_handlers - exception_handlers > (long) PAGE_SIZE); - vmap_user_4k(exception_handlers, virt_to_mfn(exception_handlers), L1_PROT); + vmap_user_4k(exception_handlers, virt_to_mfn(exception_handlers), L1_PROT_RO_GLOB); BUG_ON(end_interrupt_handlers - interrupt_handlers > (long) PAGE_SIZE); - vmap_user_4k(interrupt_handlers, virt_to_mfn(interrupt_handlers), L1_PROT); + vmap_user_4k(interrupt_handlers, virt_to_mfn(interrupt_handlers), L1_PROT_RO_GLOB); BUG_ON(end_usermode_helpers - usermode_helpers > (long) PAGE_SIZE); - vmap_user_4k(usermode_helpers, virt_to_mfn(usermode_helpers), L1_PROT); + vmap_user_4k(usermode_helpers, virt_to_mfn(usermode_helpers), L1_PROT_RO_GLOB); init_syscall(); init_sysenter(percpu); diff --git a/drivers/fb/fb.c b/drivers/fb/fb.c index e1dcd0a6..cae015f8 100644 --- a/drivers/fb/fb.c +++ b/drivers/fb/fb.c @@ -54,7 +54,7 @@ static uint64_t line_width; static void (*put_pixel)(uint32_t x, uint32_t y, uint32_t color); static void map_fb_area(paddr_t start, size_t size) { - vmap_range(start, size, L1_PROT_NOCACHE, VMAP_KERNEL | VMAP_IDENT); + vmap_range(start, size, L1_PROT_NOCACHE_GLOB, VMAP_KERNEL | VMAP_IDENT); } static void put_pixel8(uint32_t x, uint32_t y, uint32_t color) { diff --git a/drivers/hpet.c b/drivers/hpet.c index 448358b9..3b7532be 100644 --- a/drivers/hpet.c +++ b/drivers/hpet.c @@ -60,7 +60,7 @@ bool init_hpet(const cpu_t *cpu) { #endif hpet_base_mfn = paddr_to_mfn(address); - vmap_kern_4k(_ptr(address), hpet_base_mfn, L1_PROT_NOCACHE); + vmap_kern_4k(_ptr(address), hpet_base_mfn, L1_PROT_NOCACHE_GLOB); config = (acpi_hpet_timer_t *) (address + HPET_OFFSET_TIMER_0_CONFIG_CAP_REG); general = (acpi_hpet_general_t *) (address + HPET_OFFSET_GENERAL_CAP_REG); main_counter = (uint64_t *) (address + HPET_OFFSET_GENERAL_MAIN_COUNTER_REG); diff --git a/drivers/vga.c b/drivers/vga.c index 42b35363..33bb4088 100644 --- a/drivers/vga.c +++ b/drivers/vga.c @@ -81,6 +81,6 @@ void vga_write(void *vga_memory, const char *buf, size_t len, vga_color_t color) } void map_vga_area(void) { - vmap_range(VGA_START_ADDR, VGA_END_ADDR - VGA_START_ADDR, L1_PROT_NOCACHE, + vmap_range(VGA_START_ADDR, VGA_END_ADDR - VGA_START_ADDR, L1_PROT_NOCACHE_GLOB, VMAP_IDENT | VMAP_KERNEL); } diff --git a/include/arch/x86/page.h b/include/arch/x86/page.h index 3de15428..992835de 100644 --- a/include/arch/x86/page.h +++ b/include/arch/x86/page.h @@ -70,11 +70,14 @@ #define PT_NO_FLAGS 0 -#define L1_PROT (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -#define L1_PROT_RO (_PAGE_PRESENT | _PAGE_ACCESSED) -#define L1_PROT_NOCACHE (L1_PROT | _PAGE_PCD) -#define L1_PROT_USER (L1_PROT | _PAGE_USER) -#define L1_PROT_USER_RO (L1_PROT_RO | _PAGE_USER) +#define L1_PROT (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) +#define L1_PROT_GLOB (L1_PROT | _PAGE_GLOBAL) +#define L1_PROT_RO (_PAGE_PRESENT | _PAGE_ACCESSED) +#define L1_PROT_RO_GLOB (L1_PROT_RO | _PAGE_GLOBAL) +#define L1_PROT_NOCACHE (L1_PROT | _PAGE_PCD) +#define L1_PROT_NOCACHE_GLOB (L1_PROT_NOCACHE | _PAGE_GLOBAL) +#define L1_PROT_USER (L1_PROT | _PAGE_USER) +#define L1_PROT_USER_RO (L1_PROT_RO | _PAGE_USER) #define L2_PROT (L1_PROT | _PAGE_DIRTY) #define L2_PROT_RO (L1_PROT_RO | _PAGE_DIRTY) diff --git a/include/arch/x86/pagetable.h b/include/arch/x86/pagetable.h index 92881032..b0dbd7e1 100644 --- a/include/arch/x86/pagetable.h +++ b/include/arch/x86/pagetable.h @@ -381,6 +381,11 @@ static inline void *vmap_user_4k(void *va, mfn_t mfn, unsigned long l1_flags) { return vmap_4k(&user_cr3, va, mfn, l1_flags, true); } +static inline void setup_tlb_global(void) { + unsigned long cr4 = read_cr4(); + write_cr4(opt_tlb_global ? (cr4 | X86_CR4_PGE) : (cr4 & ~X86_CR4_PGE)); +} + #endif /* __ASSEMBLY__ */ #endif /* KTF_PAGETABLE_H */ diff --git a/include/cmdline.h b/include/cmdline.h index 56b2c107..9b1fba1e 100644 --- a/include/cmdline.h +++ b/include/cmdline.h @@ -69,6 +69,7 @@ extern bool opt_qemu_console; extern bool opt_poweroff; extern bool opt_fb_scroll; extern unsigned long opt_reboot_timeout; +extern bool opt_tlb_global; extern const char *kernel_cmdline; diff --git a/mm/regions.c b/mm/regions.c index 3cbac2a5..287be2dd 100644 --- a/mm/regions.c +++ b/mm/regions.c @@ -59,12 +59,12 @@ addr_range_t addr_ranges[] = { USER_RANGE( ".data.user", L1_PROT_USER, __start_data_user, __end_data_user ), USER_RANGE( ".bss.user", L1_PROT_USER, __start_bss_user, __end_bss_user ), - KERNEL_RANGE( ".text", L1_PROT_RO, __start_text, __end_text ), - KERNEL_RANGE( ".data", L1_PROT, __start_data, __end_data ), - KERNEL_RANGE( ".extables", L1_PROT_RO, __start_extables, __end_extables ), - KERNEL_RANGE( ".bss", L1_PROT, __start_bss, __end_bss ), - KERNEL_RANGE( ".rodata", L1_PROT_RO, __start_rodata, __end_rodata ), - KERNEL_RANGE( ".symbols", L1_PROT_RO, __start_symbols, __end_symbols ), + KERNEL_RANGE( ".text", L1_PROT_RO_GLOB, __start_text, __end_text ), + KERNEL_RANGE( ".data", L1_PROT_GLOB, __start_data, __end_data ), + KERNEL_RANGE( ".bss", L1_PROT_GLOB, __start_bss, __end_bss ), + KERNEL_RANGE( ".rodata", L1_PROT_RO, __start_rodata, __end_rodata ), + KERNEL_RANGE( ".extables", L1_PROT_RO_GLOB, __start_extables, __end_extables ), + KERNEL_RANGE( ".symbols", L1_PROT_RO, __start_symbols, __end_symbols ), /* clang-format on */ {0x0} /* NULL array terminator */ diff --git a/smp/smp.c b/smp/smp.c index 66b7dd53..a73ec9bd 100644 --- a/smp/smp.c +++ b/smp/smp.c @@ -50,6 +50,7 @@ cr3_t __data_init ap_cr3; void __noreturn ap_startup(void) { WRITE_SP(ap_new_sp); + setup_tlb_global(); cpu_t *cpu = get_cpu(ap_cpuid);