From: mlarkin Date: Sun, 7 Jan 2018 19:56:19 +0000 (+0000) Subject: remove all PG_G global page mappings from the kernel when running on X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=ca88a4fb6ab1d28866f47b6481a10197030dfaee;p=openbsd remove all PG_G global page mappings from the kernel when running on Intel CPUs. Part of an ongoing set of commits to mitigate the Intel "meltdown" CVE. This diff does not confer any immunity to that vulnerability - subsequent commits are still needed and are being worked on presently. ok guenther, deraadt --- diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S index 2b85fc65dab..6e00ce3dddf 100644 --- a/sys/arch/amd64/amd64/locore.S +++ b/sys/arch/amd64/amd64/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.92 2018/01/06 22:03:12 guenther Exp $ */ +/* $OpenBSD: locore.S,v 1.93 2018/01/07 19:56:19 mlarkin Exp $ */ /* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */ /* @@ -175,6 +175,7 @@ _C_LABEL(lapic_isr): .globl _C_LABEL(biosbasemem) .globl _C_LABEL(bootapiver) .globl _C_LABEL(pg_nx) + .globl _C_LABEL(pg_g_kern) _C_LABEL(cpu_id): .long 0 # saved from `cpuid' instruction _C_LABEL(cpu_feature): .long 0 # feature flags from 'cpuid' # instruction @@ -207,6 +208,9 @@ _C_LABEL(biosextmem): .long 0 # extended memory reported by BIOS _C_LABEL(biosextmem): .long REALEXTMEM #endif _C_LABEL(pg_nx): .quad 0 # NX PTE bit (if CPU supports) +_C_LABEL(pg_g_kern): .quad 0 # 0x100 if global pages should be used + # in kernel mappings, 0 otherwise (for + # Intel) #define _RELOC(x) ((x) - KERNBASE) #define RELOC(x) _RELOC(_C_LABEL(x)) diff --git a/sys/arch/amd64/amd64/locore0.S b/sys/arch/amd64/amd64/locore0.S index aacda66c551..50f0c7ecd82 100644 --- a/sys/arch/amd64/amd64/locore0.S +++ b/sys/arch/amd64/amd64/locore0.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore0.S,v 1.5 2017/10/14 21:42:17 mlarkin Exp $ */ +/* $OpenBSD: locore0.S,v 1.6 2018/01/07 19:56:19 mlarkin Exp $ */ /* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */ /* @@ -204,6 +204,27 @@ bi_size_ok: movl %ecx,8(%ebp) movl $0, 12(%ebp) + /* + * Determine if CPU is Intel. Intel CPUs cannot use PG_G (global + * pages) in kernel mappings. If CPU is not Intel, this is safe. + * Cache the result in pg_g_kern - 0 if not supported or PG_G (0x100) + * if supported. + * + * This treatment is required for the meltdown CVE mitigation. + */ + cmpl $0x756e6547, %ebx # "Genu" + jne not_intel + cmpl $0x6c65746e, %ecx # "ntel" + jne not_intel + cmpl $0x49656e69, %edx # "ineI" + jne not_intel + + jmp pg_g_check_finished + +not_intel: + movl $PG_G, RELOC(pg_g_kern) + +pg_g_check_finished: movl $1,%eax cpuid movl %eax,RELOC(cpu_id) @@ -470,7 +491,8 @@ map_tables: leal (PROC0_DMP2_OFF)(%esi), %ebx xorl %eax, %eax movl $(NDML2_ENTRIES * NPDPG), %ecx -1: orl $(PG_V|PG_KW|PG_PS|PG_G), %eax +1: orl $(PG_V|PG_KW|PG_PS), %eax + orl RELOC(pg_g_kern), %eax cmpl $__kernel_base_phys, %eax jl store_pte cmpl $__kernel_end_phys, %eax diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 85598eed545..bb7ba397bbe 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.107 2018/01/07 05:35:10 mlarkin Exp $ */ +/* $OpenBSD: pmap.c,v 1.108 2018/01/07 19:56:19 mlarkin Exp $ */ /* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */ /* @@ -513,7 +513,7 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) /* special 1:1 mappings in the first 2MB must not be global */ if (va >= (vaddr_t)NBPD_L2) - npte |= PG_G; + npte |= pg_g_kern; if (!(prot & PROT_EXEC)) npte |= pg_nx; @@ -655,7 +655,7 @@ pmap_bootstrap(paddr_t first_avail, paddr_t max_pa) kva += PAGE_SIZE) { p1i = pl1_i(kva); if (pmap_valid_entry(PTE_BASE[p1i])) - PTE_BASE[p1i] |= PG_G; + PTE_BASE[p1i] |= pg_g_kern; } /* @@ -680,7 +680,7 @@ pmap_bootstrap(paddr_t first_avail, paddr_t max_pa) va = PMAP_DIRECT_MAP(pdp); *((pd_entry_t *)va) = ((paddr_t)i << L2_SHIFT); - *((pd_entry_t *)va) |= PG_RW | PG_V | PG_PS | PG_G | PG_U | + *((pd_entry_t *)va) |= PG_RW | PG_V | PG_PS | pg_g_kern | PG_U | PG_M | pg_nx; } @@ -2155,7 +2155,7 @@ enter_now: else if (va < VM_MAX_ADDRESS) npte |= (PG_u | PG_RW); /* XXXCDC: no longer needed? */ if (pmap == pmap_kernel()) - npte |= PG_G; + npte |= pg_g_kern; ptes[pl1_i(va)] = npte; /* zap! */ diff --git a/sys/arch/amd64/include/pte.h b/sys/arch/amd64/include/pte.h index 8aa59aeab7c..397ec75341b 100644 --- a/sys/arch/amd64/include/pte.h +++ b/sys/arch/amd64/include/pte.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pte.h,v 1.13 2015/11/09 00:49:33 mlarkin Exp $ */ +/* $OpenBSD: pte.h,v 1.14 2018/01/07 19:56:19 mlarkin Exp $ */ /* $NetBSD: pte.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */ /* @@ -158,6 +158,7 @@ typedef u_int64_t pt_entry_t; /* PTE */ #ifdef _KERNEL extern pt_entry_t pg_nx; /* NX pte bit */ +extern pt_entry_t pg_g_kern; /* PG_G if glbl mappings can be used in kern */ #endif /* _KERNEL */ #endif /* _MACHINE_PTE_H_ */