From owner-svn-soc-all@FreeBSD.ORG Thu Aug 14 22:01:29 2014 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 04672C02 for ; Thu, 14 Aug 2014 22:01:29 +0000 (UTC) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 3AAA0306A for ; Thu, 14 Aug 2014 20:33:39 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.9/8.14.9) with ESMTP id s7EKXdu8084084 for ; Thu, 14 Aug 2014 20:33:39 GMT (envelope-from op@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.9/8.14.9/Submit) id s7EKXcFW084082 for svn-soc-all@FreeBSD.org; Thu, 14 Aug 2014 20:33:38 GMT (envelope-from op@FreeBSD.org) Date: Thu, 14 Aug 2014 20:33:38 GMT Message-Id: <201408142033.s7EKXcFW084082@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to op@FreeBSD.org using -f From: op@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r272441 - soc2014/op/patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Aug 2014 22:01:29 -0000 Author: op Date: Thu Aug 14 20:33:38 2014 New Revision: 272441 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=272441 Log: added final version of patch freebsd-head+intel-smap+selfpatch-all.diff Signed-off-by: Oliver Pinter Added: soc2014/op/patches/ soc2014/op/patches/freebsd-head+intel-smap+selfpatch-all.diff Added: soc2014/op/patches/freebsd-head+intel-smap+selfpatch-all.diff ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2014/op/patches/freebsd-head+intel-smap+selfpatch-all.diff Thu Aug 14 20:33:38 2014 (r272441) @@ -0,0 +1,2265 @@ +diff --git a/.gitignore b/.gitignore +new file mode 100644 +index 0000000..f3b9484 +--- /dev/null ++++ b/.gitignore +@@ -0,0 +1 @@ ++.clang_complete +diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S +index 7c37a41..a50a80a 100644 +--- a/sys/amd64/amd64/cpu_switch.S ++++ b/sys/amd64/amd64/cpu_switch.S +@@ -35,6 +35,7 @@ + + #include + #include ++#include + + #include "assym.s" + #include "opt_sched.h" +@@ -121,10 +122,7 @@ done_store_dr: + 1: movq %rdx,%rcx + movl xsave_mask,%eax + movl xsave_mask+4,%edx +- .globl ctx_switch_xsave +-ctx_switch_xsave: +- /* This is patched to xsaveopt if supported, see fpuinit_bsp1() */ +- xsave (%r8) ++ _xsave_xsaveopt (%r8) + movq %rcx,%rdx + 2: smsw %ax + orb $CR0_TS,%al +diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S +index 2a908a9..1aed663 100644 +--- a/sys/amd64/amd64/exception.S ++++ b/sys/amd64/amd64/exception.S +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + #include "assym.s" + +@@ -198,6 +199,7 @@ alltraps_pushregs_no_rdi: + movq %r14,TF_R14(%rsp) + movq %r15,TF_R15(%rsp) + movl $TF_HASSEGS,TF_FLAGS(%rsp) ++ _clac + cld + FAKE_MCOUNT(TF_RIP(%rsp)) + #ifdef KDTRACE_HOOKS +@@ -278,6 +280,7 @@ IDTVEC(dblfault) + movw %es,TF_ES(%rsp) + movw %ds,TF_DS(%rsp) + movl $TF_HASSEGS,TF_FLAGS(%rsp) ++ _clac + cld + testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */ + jz 1f /* already running with kernel GS.base */ +@@ -381,6 +384,7 @@ IDTVEC(fast_syscall) + movq %r14,TF_R14(%rsp) /* C preserved */ + movq %r15,TF_R15(%rsp) /* C preserved */ + movl $TF_HASSEGS,TF_FLAGS(%rsp) ++ _clac + cld + FAKE_MCOUNT(TF_RIP(%rsp)) + movq PCPU(CURTHREAD),%rdi +@@ -452,6 +456,7 @@ IDTVEC(fast_syscall32) + */ + + IDTVEC(nmi) ++ _clac + subq $TF_RIP,%rsp + movl $(T_NMI),TF_TRAPNO(%rsp) + movq $0,TF_ADDR(%rsp) +@@ -535,6 +540,7 @@ nmi_calltrap: + movq %rdx,%rdi /* destination stack pointer */ + + shrq $3,%rcx /* trap frame size in long words */ ++ _clac + cld + rep + movsq /* copy trapframe */ +diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c +index 0f4b2b5..a897ef7 100644 +--- a/sys/amd64/amd64/fpu.c ++++ b/sys/amd64/amd64/fpu.c +@@ -203,16 +203,6 @@ fpuinit_bsp1(void) + xsave_mask &= ~XFEATURE_AVX512; + if ((xsave_mask & XFEATURE_MPX) != XFEATURE_MPX) + xsave_mask &= ~XFEATURE_MPX; +- +- cpuid_count(0xd, 0x1, cp); +- if ((cp[0] & CPUID_EXTSTATE_XSAVEOPT) != 0) { +- /* +- * Patch the XSAVE instruction in the cpu_switch code +- * to XSAVEOPT. We assume that XSAVE encoding used +- * REX byte, and set the bit 4 of the r/m byte. +- */ +- ctx_switch_xsave[3] |= 0x10; +- } + } + + /* +diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c +index 3b66369..226389e 100644 +--- a/sys/amd64/amd64/identcpu.c ++++ b/sys/amd64/amd64/identcpu.c +@@ -566,13 +566,21 @@ identify_cpu(void) + */ + if (cpu_feature2 & CPUID2_HV) { + cpu_stdext_disable = CPUID_STDEXT_FSGSBASE | +- CPUID_STDEXT_SMEP; ++ CPUID_STDEXT_SMEP | CPUID_STDEXT_SMAP; + } else + cpu_stdext_disable = 0; + TUNABLE_INT_FETCH("hw.cpu_stdext_disable", &cpu_stdext_disable); + cpu_stdext_feature &= ~cpu_stdext_disable; + } + ++ if (cpu_high >= 13) { ++ if (cpu_feature2 & CPUID2_XSAVE) { ++ cpuid_count(13, 1, regs); ++ cpu_extstate = regs[0]; ++ } else ++ cpu_extstate = 0; ++ } ++ + if (cpu_vendor_id == CPU_VENDOR_INTEL || + cpu_vendor_id == CPU_VENDOR_AMD || + cpu_vendor_id == CPU_VENDOR_CENTAUR) { +diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c +index 34a362d..f5976eb 100644 +--- a/sys/amd64/amd64/initcpu.c ++++ b/sys/amd64/amd64/initcpu.c +@@ -78,6 +78,7 @@ u_int cpu_max_ext_state_size; + u_int cpu_mon_mwait_flags; /* MONITOR/MWAIT flags (CPUID.05H.ECX) */ + u_int cpu_mon_min_size; /* MONITOR minimum range size, bytes */ + u_int cpu_mon_max_size; /* MONITOR minimum range size, bytes */ ++u_int cpu_extstate; /* Extended State features */ + + SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD, + &via_feature_rng, 0, "VIA RNG feature available in CPU"); +@@ -168,13 +169,17 @@ initializecpu(void) + cr4 |= CR4_FSGSBASE; + + /* +- * Postpone enabling the SMEP on the boot CPU until the page +- * tables are switched from the boot loader identity mapping ++ * Postpone enabling the SMEP and SMAP on the boot CPU until the ++ * page tables are switched from the boot loader identity mapping + * to the kernel tables. The boot loader enables the U bit in + * its tables. + */ + if (!IS_BSP() && (cpu_stdext_feature & CPUID_STDEXT_SMEP)) + cr4 |= CR4_SMEP; ++#ifdef INTEL_SMAP_SUPPORT ++ if (!IS_BSP() && (cpu_stdext_feature & CPUID_STDEXT_SMAP)) ++ cr4 |= CR4_SMAP; ++#endif + load_cr4(cr4); + if ((amd_feature & AMDID_NX) != 0) { + msr = rdmsr(MSR_EFER) | EFER_NXE; +diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c +index f02045d..237cc7f 100644 +--- a/sys/amd64/amd64/machdep.c ++++ b/sys/amd64/amd64/machdep.c +@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); + #include "opt_perfmon.h" + #include "opt_platform.h" + #include "opt_sched.h" ++#include "opt_selfpatch.h" + + #include + #include +@@ -81,6 +82,7 @@ __FBSDID("$FreeBSD$"); + #include + #include + #include ++#include + #include + #ifdef SMP + #include +@@ -1998,6 +2000,11 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) + initializecpu(); /* Initialize CPU registers */ + initializecpucache(); + ++#if defined(KSP_FRAMEWORK) || defined(INTEL_SMAP_SUPPORT) ++ /* selfmodify kernel text, when needed */ ++ lf_selfpatch(linker_kernel_file, 0); ++#endif ++ + /* doublefault stack space, runs on ist1 */ + common_tss[0].tss_ist1 = (long)&dblfault_stack[sizeof(dblfault_stack)]; + +diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c +index 6adc86d..508dcdd 100644 +--- a/sys/amd64/amd64/pmap.c ++++ b/sys/amd64/amd64/pmap.c +@@ -100,6 +100,7 @@ __FBSDID("$FreeBSD$"); + * and to when physical maps must be made correct. + */ + ++#include "opt_cpu.h" + #include "opt_pmap.h" + #include "opt_vm.h" + +@@ -429,7 +430,6 @@ static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, + vm_page_t m, vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp); + static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte); + static int pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); +-static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode); + static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va); + static void pmap_pde_attr(pd_entry_t *pde, int cache_bits, int mask); + static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, +@@ -836,6 +836,15 @@ pmap_bootstrap(vm_paddr_t *firstaddr) + if (cpu_stdext_feature & CPUID_STDEXT_SMEP) + load_cr4(rcr4() | CR4_SMEP); + ++#ifdef INTEL_SMAP_SUPPORT ++ if (cpu_stdext_feature & CPUID_STDEXT_SMAP) { ++ printf("Intel SMAP: enabled\n"); ++ load_cr4(rcr4() | CR4_SMAP); ++ } else { ++ printf("Intel SMAP: not supported or disabled\n"); ++ } ++#endif ++ + /* + * Initialize the kernel pmap (which is statically allocated). + */ +@@ -1915,7 +1924,7 @@ pmap_kenter(vm_offset_t va, vm_paddr_t pa) + pte_store(pte, pa | X86_PG_RW | X86_PG_V | X86_PG_G); + } + +-static __inline void ++__inline void + pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode) + { + pt_entry_t *pte; +diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S +index 77dbf63..ed92e36 100644 +--- a/sys/amd64/amd64/support.S ++++ b/sys/amd64/amd64/support.S +@@ -35,6 +35,8 @@ + #include + #include + #include ++#include ++#include + + #include "assym.s" + +@@ -59,7 +61,7 @@ ENTRY(bzero) + stosb + ret + END(bzero) +- ++ + /* Address: %rdi */ + ENTRY(pagezero) + movq $-PAGE_SIZE,%rdx +@@ -137,7 +139,7 @@ ENTRY(bcopy) + cld + ret + END(bcopy) +- ++ + /* + * Note: memcpy does not support overlapping copies + */ +@@ -181,10 +183,10 @@ ENTRY(pagecopy) + ret + END(pagecopy) + +-/* fillw(pat, base, cnt) */ ++/* fillw(pat, base, cnt) */ + /* %rdi,%rsi, %rdx */ + ENTRY(fillw) +- movq %rdi,%rax ++ movq %rdi,%rax + movq %rsi,%rdi + movq %rdx,%rcx + cld +@@ -203,6 +205,9 @@ END(fillw) + * These routines set curpcb->pcb_onfault for the time they execute. When a + * protection violation occurs inside the functions, the trap handler + * returns to *curpcb->pcb_onfault instead of the function. ++ * ++ * Warning: when Intel SMAP are enabled on CPU, the EFLAGS.AC bit gets ++ * cleared before reaches the fault handler. + */ + + /* +@@ -244,12 +249,16 @@ ENTRY(copyout) + + shrq $3,%rcx + cld ++ _stac /* open user-space */ + rep + movsq ++ _clac /* close user-space */ + movb %dl,%cl + andb $7,%cl ++ _stac /* open user-space */ + rep + movsb ++ _clac /* close user-space */ + + done_copyout: + xorl %eax,%eax +@@ -259,6 +268,9 @@ done_copyout: + + ALIGN_TEXT + copyout_fault: ++ /* ++ * WARNING: on fault EFLAGS.AC gets cleared by Intel SMAP if available ++ */ + movq PCPU(CURPCB),%rdx + movq $0,PCB_ONFAULT(%rdx) + movq $EFAULT,%rax +@@ -290,12 +302,16 @@ ENTRY(copyin) + movb %cl,%al + shrq $3,%rcx /* copy longword-wise */ + cld ++ _stac /* open user-space */ + rep + movsq ++ _clac /* close user-space */ + movb %al,%cl + andb $7,%cl /* copy remaining bytes */ ++ _stac /* open user-space */ + rep + movsb ++ _clac /* close user-space */ + + done_copyin: + xorl %eax,%eax +@@ -305,6 +321,9 @@ done_copyin: + + ALIGN_TEXT + copyin_fault: ++ /* ++ * WARNING: on fault EFLAGS.AC gets cleared by Intel SMAP if available ++ */ + movq PCPU(CURPCB),%rdx + movq $0,PCB_ONFAULT(%rdx) + movq $EFAULT,%rax +@@ -324,10 +343,12 @@ ENTRY(casuword32) + ja fusufault + + movl %esi,%eax /* old */ ++ _stac /* open user-space */ + #ifdef SMP + lock + #endif + cmpxchgl %edx,(%rdi) /* new = %edx */ ++ _clac /* close user-space */ + + /* + * The old value is in %eax. If the store succeeded it will be the +@@ -353,10 +374,12 @@ ENTRY(casuword) + ja fusufault + + movq %rsi,%rax /* old */ ++ _stac /* open user-space */ + #ifdef SMP + lock + #endif + cmpxchgq %rdx,(%rdi) /* new = %rdx */ ++ _clac /* close user-space */ + + /* + * The old value is in %eax. If the store succeeded it will be the +@@ -385,10 +408,12 @@ ENTRY(fuword) + cmpq %rax,%rdi /* verify address is valid */ + ja fusufault + ++ _stac /* open user-space */ + movq (%rdi),%rax ++ _clac /* close user-space */ + movq $0,PCB_ONFAULT(%rcx) + ret +-END(fuword64) ++END(fuword64) + END(fuword) + + ENTRY(fuword32) +@@ -399,7 +424,9 @@ ENTRY(fuword32) + cmpq %rax,%rdi /* verify address is valid */ + ja fusufault + ++ _stac /* open user-space */ + movl (%rdi),%eax ++ _clac /* close user-space */ + movq $0,PCB_ONFAULT(%rcx) + ret + END(fuword32) +@@ -426,7 +453,9 @@ ENTRY(fuword16) + cmpq %rax,%rdi + ja fusufault + ++ _stac /* open user-space */ + movzwl (%rdi),%eax ++ _clac /* close user-space */ + movq $0,PCB_ONFAULT(%rcx) + ret + END(fuword16) +@@ -439,13 +468,18 @@ ENTRY(fubyte) + cmpq %rax,%rdi + ja fusufault + ++ _stac /* open user-space */ + movzbl (%rdi),%eax ++ _clac /* close user-space */ + movq $0,PCB_ONFAULT(%rcx) + ret + END(fubyte) + + ALIGN_TEXT + fusufault: ++ /* ++ * WARNING: on fault EFLAGS.AC gets cleared by Intel SMAP if available ++ */ + movq PCPU(CURPCB),%rcx + xorl %eax,%eax + movq %rax,PCB_ONFAULT(%rcx) +@@ -466,7 +500,9 @@ ENTRY(suword) + cmpq %rax,%rdi /* verify address validity */ + ja fusufault + ++ _stac /* open user-space */ + movq %rsi,(%rdi) ++ _clac /* close user-space */ + xorl %eax,%eax + movq PCPU(CURPCB),%rcx + movq %rax,PCB_ONFAULT(%rcx) +@@ -482,7 +518,9 @@ ENTRY(suword32) + cmpq %rax,%rdi /* verify address validity */ + ja fusufault + ++ _stac /* open user-space */ + movl %esi,(%rdi) ++ _clac /* close user-space */ + xorl %eax,%eax + movq PCPU(CURPCB),%rcx + movq %rax,PCB_ONFAULT(%rcx) +@@ -497,7 +535,9 @@ ENTRY(suword16) + cmpq %rax,%rdi /* verify address validity */ + ja fusufault + ++ _stac /* open user-space */ + movw %si,(%rdi) ++ _clac /* close user-space */ + xorl %eax,%eax + movq PCPU(CURPCB),%rcx /* restore trashed register */ + movq %rax,PCB_ONFAULT(%rcx) +@@ -513,7 +553,9 @@ ENTRY(subyte) + ja fusufault + + movl %esi,%eax ++ _stac /* open user-space */ + movb %al,(%rdi) ++ _clac /* close user-space */ + xorl %eax,%eax + movq PCPU(CURPCB),%rcx /* restore trashed register */ + movq %rax,PCB_ONFAULT(%rcx) +@@ -555,7 +597,9 @@ ENTRY(copyinstr) + decq %rdx + jz 3f + ++ _stac /* open user-space */ + lodsb ++ _clac /* close user-space */ + stosb + orb %al,%al + jnz 2b +@@ -584,7 +628,9 @@ cpystrflt_x: + testq %r9,%r9 + jz 1f + subq %rdx,%r8 ++ _stac /* open user-space */ + movq %r8,(%r9) ++ _clac /* close user-space */ + 1: + ret + END(copyinstr) +diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c +index f6459f4..de7fe00 100644 +--- a/sys/amd64/amd64/trap.c ++++ b/sys/amd64/amd64/trap.c +@@ -104,6 +104,7 @@ void dblfault_handler(struct trapframe *frame); + + static int trap_pfault(struct trapframe *, int); + static void trap_fatal(struct trapframe *, vm_offset_t); ++static bool smap_access_violation(struct trapframe *, int usermode); + + #define MAX_TRAP_MSG 32 + static char *trap_msg[] = { +@@ -697,6 +698,20 @@ trap_pfault(frame, usermode) + + map = &vm->vm_map; + ++#ifdef INTEL_SMAP_SUPPORT ++ /* ++ * If CPL < 3, SMAP protections are disabled if EFLAGS.AC = 1. ++ * If CPL = 3, SMAP applies to all supervisor-mode data accesses ++ * (these are implicit supervisor accesses) regardless of the ++ * value of EFLAGS.AC." - Intel Ref. # 319433-014 9.3.2 ++ */ ++ if (__predict_false(smap_access_violation(frame, usermode))) { ++ printf("\nSupervisor Mode Access Prevention\n"); ++ trap_fatal(frame, eva); ++ return(-1); ++ } ++#endif ++ + /* + * When accessing a usermode address, kernel must be + * ready to accept the page fault, and provide a +@@ -868,6 +883,33 @@ trap_fatal(frame, eva) + panic("unknown/reserved trap"); + } + ++#ifdef INTEL_SMAP_SUPPORT ++/* ++ * Supervisor Mode Access Prevention violation ++ * ++ * If CPL < 3, SMAP protections are disabled if EFLAGS.AC = 1. ++ * If CPL = 3, SMAP applies to all supervisor-mode data accesses ++ * (these are implicit supervisor accesses) regardless of the ++ * value of EFLAGS.AC." - Intel Ref. # 319433-014 9.3.2 ++ */ ++static bool ++smap_access_violation(struct trapframe *frame, int usermode) ++{ ++ /* SMAP disabled */ ++ if ((cpu_stdext_feature & CPUID_STDEXT_SMAP) == 0) ++ return (false); ++ ++ /* CPL == 3 or EFLAGS.AC == 1 */ ++ if (usermode || (frame->tf_rflags & PSL_AC) != 0) ++ return (false); ++ ++ /* ++ * CPL < 3 and EFLAGS.AC == 0 ++ */ ++ return (true); ++} ++#endif ++ + /* + * Double fault handler. Called when a fault occurs while writing + * a frame for a trap/exception onto the stack. This usually occurs +diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC +index 4269889..3a0ccf9 100644 +--- a/sys/amd64/conf/GENERIC ++++ b/sys/amd64/conf/GENERIC +@@ -26,6 +26,7 @@ makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support + + options SCHED_ULE # ULE scheduler + options PREEMPTION # Enable kernel thread preemption ++options KSP_FRAMEWORK # Kernel run-time selfpatches and updates + options INET # InterNETworking + options INET6 # IPv6 communications protocols + options TCP_OFFLOAD # TCP offload +@@ -88,6 +89,9 @@ options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones + # Make an SMP-capable kernel by default + options SMP # Symmetric MultiProcessor Kernel + ++# Intel Supervisor Mode Access Prevention ++options INTEL_SMAP_SUPPORT ++ + # CPU frequency control + device cpufreq + +diff --git a/sys/amd64/ia32/ia32_exception.S b/sys/amd64/ia32/ia32_exception.S +index fe1a676..8ba7c88 100644 +--- a/sys/amd64/ia32/ia32_exception.S ++++ b/sys/amd64/ia32/ia32_exception.S +@@ -27,6 +27,8 @@ + */ + + #include ++#include ++#include + + #include "assym.s" + +@@ -67,6 +69,7 @@ IDTVEC(int0x80_syscall) + movq %r14,TF_R14(%rsp) + movq %r15,TF_R15(%rsp) + movl $TF_HASSEGS,TF_FLAGS(%rsp) ++ _clac + cld + FAKE_MCOUNT(TF_RIP(%rsp)) + movq %rsp, %rdi +diff --git a/sys/amd64/include/asmacros.h b/sys/amd64/include/asmacros.h +index ce8dce4..d08cab9 100644 +--- a/sys/amd64/include/asmacros.h ++++ b/sys/amd64/include/asmacros.h +@@ -33,6 +33,8 @@ + #define _MACHINE_ASMACROS_H_ + + #include ++#include ++#include + + /* XXX too much duplication in various asm*.h's. */ + +@@ -167,6 +169,7 @@ + movw %es,TF_ES(%rsp) ; \ + movw %ds,TF_DS(%rsp) ; \ + movl $TF_HASSEGS,TF_FLAGS(%rsp) ; \ ++ _clac; \ + cld + + #define POP_FRAME \ +diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h +index 7464739..acec833 100644 +--- a/sys/amd64/include/cpufunc.h ++++ b/sys/amd64/include/cpufunc.h +@@ -43,6 +43,9 @@ + #error this file needs sys/cdefs.h as a prerequisite + #endif + ++#include ++#include ++ + struct region_descriptor; + + #define readb(va) (*(volatile uint8_t *) (va)) +@@ -587,6 +590,59 @@ cpu_mwait(u_long extensions, u_int hints) + __asm __volatile("mwait" : : "a" (hints), "c" (extensions)); + } + ++/* ++ * Intel SMAP related functions. ++ */ ++static __inline void ++clac(void) ++{ ++ ++ __asm __volatile( ++ "0723: " ++ " " KSP_INSTR_NOP3_C "; " ++ "0724: " ++ " .pushsection set_selfpatch_patch_set, \"ax\" ; " ++ "0725: " ++ " clac ; " ++ "0726: " ++ " .popsection " ++ " .pushsection set_selfpatch_set, \"a\" ; " ++ " .quad 0723b ; " ++ " .quad 0725b ; " ++ " .int 0724b-0723b ; " ++ " .int 0726b-0725b ; " ++ " .int " __XSTRING(KSP_CPUID_STDEXT) " ; " ++ " .int " __XSTRING(CPUID_STDEXT_SMAP) " ; " ++ " .quad 0 ; " ++ " .popsection ; " ++ : : : "memory"); ++} ++ ++static __inline void ++stac(void) ++{ ++ ++ __asm __volatile( ++ "0723: " ++ " " KSP_INSTR_NOP3_C "; " ++ "0724: " ++ " .pushsection set_selfpatch_patch_set, \"ax\" ; " ++ "0725: " ++ " stac ; " ++ "0726: " ++ " .popsection " ++ " .pushsection set_selfpatch_set, \"a\" ; " ++ " .quad 0723b ; " ++ " .quad 0725b ; " ++ " .int 0724b-0723b ; " ++ " .int 0726b-0725b ; " ++ " .int " __XSTRING(KSP_CPUID_STDEXT) " ; " ++ " .int " __XSTRING(CPUID_STDEXT_SMAP) " ; " ++ " .quad 0 ; " ++ " .popsection ; " ++ : : : "memory"); ++} ++ + #ifdef _KERNEL + /* This is defined in but is too painful to get to */ + #ifndef MSR_FSBASE +diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h +index 5ddfbbd..643623b 100644 +--- a/sys/amd64/include/md_var.h ++++ b/sys/amd64/include/md_var.h +@@ -61,7 +61,7 @@ extern u_int cpu_vendor_id; + extern u_int cpu_mon_mwait_flags; + extern u_int cpu_mon_min_size; + extern u_int cpu_mon_max_size; +-extern char ctx_switch_xsave[]; ++extern u_int cpu_extstate; + extern char kstack[]; + extern char sigcode[]; + extern int szsigcode; +diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h +index e83e07e..c6f3a89 100644 +--- a/sys/amd64/include/pmap.h ++++ b/sys/amd64/include/pmap.h +@@ -380,6 +380,7 @@ int pmap_change_attr(vm_offset_t, vm_size_t, int); + void pmap_demote_DMAP(vm_paddr_t base, vm_size_t len, boolean_t invalidate); + void pmap_init_pat(void); + void pmap_kenter(vm_offset_t va, vm_paddr_t pa); ++void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode); + void *pmap_kenter_temporary(vm_paddr_t pa, int i); + vm_paddr_t pmap_kextract(vm_offset_t); + void pmap_kremove(vm_offset_t); +diff --git a/sys/amd64/include/selfpatch-asmacros.h b/sys/amd64/include/selfpatch-asmacros.h +new file mode 100644 +index 0000000..fb723de +--- /dev/null ++++ b/sys/amd64/include/selfpatch-asmacros.h +@@ -0,0 +1,34 @@ ++/*- ++ * Copyright (c) 2014, by Oliver Pinter ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * $FreeBSD$ ++ */ ++ ++#ifndef __AMD64_SELFPATH_ASMACROS_H__ ++#define __AMD64_SELFPATH_ASMACROS_H__ ++ ++#include ++ ++#endif /* __AMD64_SELFPATH_ASMACROS_H__ */ +diff --git a/sys/amd64/include/selfpatch-machdep.h b/sys/amd64/include/selfpatch-machdep.h +new file mode 100644 +index 0000000..caa22f7 +--- /dev/null ++++ b/sys/amd64/include/selfpatch-machdep.h +@@ -0,0 +1,34 @@ ++/*- ++ * Copyright (c) 2014, by Oliver Pinter ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * $FreeBSD$ ++ */ ++ ++#ifndef __AMD64_SELFPATH_MACHDEP_H__ ++#define __AMD64_SELFPATH_MACHDEP_H__ ++ ++#include ++ ++#endif /* __AMD64_SELFPATH_MACHDEP_H__ */ +diff --git a/sys/conf/NOTES b/sys/conf/NOTES +index 6959425..dd49c17 100644 +--- a/sys/conf/NOTES ++++ b/sys/conf/NOTES +@@ -2986,3 +2986,7 @@ options RANDOM_RWFILE # Read and write entropy cache + + # Module to enable execution of application via emulators like QEMU + options IMAGACT_BINMISC ++ ++# Kernel selfpatch framework ++options KSP_FRAMEWORK ++options KSP_DEBUG +diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 +index b63044d..d4f4803 100644 +--- a/sys/conf/files.amd64 ++++ b/sys/conf/files.amd64 +@@ -439,6 +439,7 @@ dev/virtio/random/virtio_random.c optional virtio_random + isa/syscons_isa.c optional sc + isa/vga_isa.c optional vga + kern/kern_clocksource.c standard ++kern/kern_selfpatch.c optional ksp_framework | intel_smap_support + kern/link_elf_obj.c standard + # + # IA32 binary support +@@ -553,6 +554,7 @@ x86/x86/msi.c optional pci + x86/x86/nexus.c standard + x86/x86/tsc.c standard + x86/x86/delay.c standard ++x86/x86/selfpatch_machdep.c optional ksp_framework | intel_smap_support + x86/xen/hvm.c optional xenhvm + x86/xen/xen_intr.c optional xen | xenhvm + x86/xen/pv.c optional xenhvm +diff --git a/sys/conf/ldscript.amd64 b/sys/conf/ldscript.amd64 +index 9210a73..5a97c52 100644 +--- a/sys/conf/ldscript.amd64 ++++ b/sys/conf/ldscript.amd64 +@@ -30,6 +30,10 @@ SECTIONS + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } ++ .rel.set_selfpatch_set : { *(.rel.set_selfpatch_set) } ++ .rela.set_selfpatch_set : { *(.rela.set_selfpatch_set) } ++ .rel.set_selfpatch_patch_set : { *(.rel.set_selfpatch_patch_set) } ++ .rela.set_selfpatch_patch_set : { *(.rela.set_selfpatch_patch_set) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } +@@ -140,6 +144,18 @@ SECTIONS + .got : { *(.got) } + . = DATA_SEGMENT_RELRO_END (24, .); + .got.plt : { *(.got.plt) } ++ set_selfpatch_set : ++ { ++ PROVIDE ( __start_set_selfpatch_set = . ); ++ KEEP (*(set_selfpatch_set)); ++ PROVIDE ( __stop_set_selfpatch_set = . ); ++ } ++ set_selfpatch_patch_set : ++ { ++ PROVIDE ( __start_set_selfpatch_patch_set = . ); ++ KEEP (*(set_selfpatch_patch_set)); ++ PROVIDE ( __stop_set_selfpatch_patch_set = . ); ++ } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) +diff --git a/sys/conf/options b/sys/conf/options +index 6ed7ce9..1e9f21d 100644 +--- a/sys/conf/options ++++ b/sys/conf/options +@@ -927,3 +927,7 @@ RANDOM_YARROW opt_random.h + RANDOM_FORTUNA opt_random.h + RANDOM_DEBUG opt_random.h + RANDOM_RWFILE opt_random.h ++ ++# kernel selfpatch ++KSP_FRAMEWORK opt_selfpatch.h ++KSP_DEBUG opt_selfpatch.h +diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64 +index f1d4b4a..cebe69c 100644 +--- a/sys/conf/options.amd64 ++++ b/sys/conf/options.amd64 +@@ -65,3 +65,6 @@ XENHVM opt_global.h + + # options for the Intel C600 SAS driver (isci) + ISCI_LOGGING opt_isci.h ++ ++# Intel Supervisor Mode Access Prevention ++INTEL_SMAP_SUPPORT opt_cpu.h +diff --git a/sys/i386/i386/db_disasm.c b/sys/i386/i386/db_disasm.c +index 719c9f7..b0176a9 100644 +--- a/sys/i386/i386/db_disasm.c ++++ b/sys/i386/i386/db_disasm.c +@@ -1266,13 +1266,23 @@ db_disasm(loc, altfmt) + case 0xc8: + i_name = "monitor"; + i_size = NONE; +- i_mode = 0; ++ i_mode = 0; + break; + case 0xc9: + i_name = "mwait"; + i_size = NONE; + i_mode = 0; + break; ++ case 0xca: ++ i_name = "clac"; ++ i_size = NONE; ++ i_mode = 0; ++ break; ++ case 0xcb: ++ i_name = "stac"; ++ i_size = NONE; ++ i_mode = 0; ++ break; + } + } + if (ip->i_extra == db_Grp15 && f_mod(regmodrm) == 3) { +diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s +index 39a8828..ff0c25e 100644 +--- a/sys/i386/i386/exception.s ++++ b/sys/i386/i386/exception.s +@@ -162,6 +162,7 @@ alltraps: + pushl %fs + alltraps_with_regs_pushed: + SET_KERNEL_SREGS ++ clac + cld + FAKE_MCOUNT(TF_EIP(%esp)) + calltrap: +diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c +index 9a09adb..4cea372 100644 +--- a/sys/i386/i386/identcpu.c ++++ b/sys/i386/i386/identcpu.c +@@ -860,6 +860,47 @@ printcpuinfo(void) + ); + } + ++ if (cpu_stdext_feature != 0) { ++ printf("\n Structured Extended Features=0x%b", ++ cpu_stdext_feature, ++ "\020" ++ /* RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE */ ++ "\001FSGSBASE" ++ "\002TSCADJ" ++ /* Bit Manipulation Instructions */ ++ "\004BMI1" ++ /* Hardware Lock Elision */ ++ "\005HLE" ++ /* Advanced Vector Instructions 2 */ ++ "\006AVX2" ++ /* Supervisor Mode Execution Prot. */ ++ "\010SMEP" ++ /* Bit Manipulation Instructions */ ++ "\011BMI2" ++ "\012ERMS" ++ /* Invalidate Processor Context ID */ ++ "\013INVPCID" ++ /* Restricted Transactional Memory */ ++ "\014RTM" ++ /* Intel Memory Protection Extensions */ ++ "\017MPX" ++ /* AVX512 Foundation */ ++ "\021AVX512F" ++ /* Enhanced NRBG */ ++ "\023RDSEED" ++ /* ADCX + ADOX */ ++ "\024ADX" ++ /* Supervisor Mode Access Prevention */ ++ "\025SMAP" ++ "\030CLFLUSHOPT" ++ "\032PROCTRACE" ++ "\033AVX512PF" ++ "\034AVX512ER" ++ "\035AVX512CD" ++ "\036SHA" ++ ); ++ } ++ + if (via_feature_rng != 0 || via_feature_xcrypt != 0) + print_via_padlock_info(); + +@@ -1099,7 +1140,7 @@ finishidentcpu(void) + { + int isblue = 0; + u_char ccr3; +- u_int regs[4]; ++ u_int regs[4], cpu_stdext_disable; + + cpu_vendor_id = find_cpu_vendor_id(); + +@@ -1128,6 +1169,25 @@ finishidentcpu(void) + cpu_mon_max_size = regs[1] & CPUID5_MON_MAX_SIZE; + } + ++ if (cpu_high >= 7) { ++ cpuid_count(7, 0, regs); ++ cpu_stdext_feature = regs[1]; ++ ++ /* *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***