Module Name: src Committed By: maxv Date: Sun Jan 21 11:21:40 UTC 2018
Modified Files: src/sys/arch/amd64/amd64: amd64_trap.S locore.S machdep.c vector.S src/sys/arch/amd64/conf: kern.ldscript kern.ldscript.kaslr src/sys/arch/amd64/include: frameasm.h Log Message: Unmap the kernel from userland in SVS, and leave only the needed trampolines. As explained below, SVS should now completely mitigate Meltdown on GENERIC kernels, even though it needs some more tweaking for GENERIC_KASLR. Until now the kernel entry points looked like: FUNC(intr) pushq $ERR pushq $TRAPNO INTRENTRY ... handle interrupt ... INTRFASTEXIT END(intr) With this change they are split and become: FUNC(handle) ... handle interrupt ... INTRFASTEXIT END(handle) TEXT_USER_BEGIN FUNC(intr) pushq $ERR pushq $TRAPNO INTRENTRY jmp handle END(intr) TEXT_USER_END A new section is introduced, .text.user, that contains minimal kernel entry/exit points. In order to choose what to put in this section, two macros are introduced, TEXT_USER_BEGIN and TEXT_USER_END. The section is mapped in userland with normal 4K pages. In GENERIC, the section is 4K-page-aligned and embedded in .text, which is mapped with large pages. That is to say, when an interrupt comes in, the CPU has the user page tables loaded and executes the 'intr' functions on 4K pages; after calling SVS_ENTER (in INTRENTRY) these 4K pages become 2MB large pages, and remain so when executing in kernel mode. In GENERIC_KASLR, the section is 4K-page-aligned and independent from the other kernel texts. The prekern just picks it up and maps it at a random address. In GENERIC, SVS should now completely mitigate Meltdown: what we put in .text.user is not secret. In GENERIC_KASLR, SVS would have to be improved a bit more: the 'jmp handle' instruction is actually secret, since it leaks the address of the section we are jumping into. By exploiting Meltdown on Intel, this theoretically allows a local user to reconstruct the address of the first text section. But given that our KASLR produces several texts, and that each section is not correlated with the others, the level of protection KASLR provides is still good. To generate a diff of this commit: cvs rdiff -u -r1.22 -r1.23 src/sys/arch/amd64/amd64/amd64_trap.S cvs rdiff -u -r1.147 -r1.148 src/sys/arch/amd64/amd64/locore.S cvs rdiff -u -r1.294 -r1.295 src/sys/arch/amd64/amd64/machdep.c cvs rdiff -u -r1.55 -r1.56 src/sys/arch/amd64/amd64/vector.S cvs rdiff -u -r1.25 -r1.26 src/sys/arch/amd64/conf/kern.ldscript cvs rdiff -u -r1.4 -r1.5 src/sys/arch/amd64/conf/kern.ldscript.kaslr cvs rdiff -u -r1.30 -r1.31 src/sys/arch/amd64/include/frameasm.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/amd64/amd64_trap.S diff -u src/sys/arch/amd64/amd64/amd64_trap.S:1.22 src/sys/arch/amd64/amd64/amd64_trap.S:1.23 --- src/sys/arch/amd64/amd64/amd64_trap.S:1.22 Sat Jan 20 14:27:15 2018 +++ src/sys/arch/amd64/amd64/amd64_trap.S Sun Jan 21 11:21:40 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: amd64_trap.S,v 1.22 2018/01/20 14:27:15 maxv Exp $ */ +/* $NetBSD: amd64_trap.S,v 1.23 2018/01/21 11:21:40 maxv Exp $ */ /* * Copyright (c) 1998, 2007, 2008, 2017 The NetBSD Foundation, Inc. @@ -95,13 +95,19 @@ #define PRE_TRAP #endif +#define TRAPENTRY \ + INTRENTRY ; \ + jmp .Lalltraps_noentry + #define TRAP_NJ(a) PRE_TRAP ; pushq $(a) #define ZTRAP_NJ(a) PRE_TRAP ; pushq $0 ; pushq $(a) -#define TRAP(a) TRAP_NJ(a) ; jmp _C_LABEL(alltraps) -#define ZTRAP(a) ZTRAP_NJ(a) ; jmp _C_LABEL(alltraps) +#define TRAP(a) TRAP_NJ(a) ; TRAPENTRY +#define ZTRAP(a) ZTRAP_NJ(a) ; TRAPENTRY .text + TEXT_USER_BEGIN + IDTVEC(trap00) ZTRAP(T_DIVIDE) IDTVEC_END(trap00) @@ -361,24 +367,6 @@ IDTVEC(intrspurious) jmp .Lalltraps_checkusr IDTVEC_END(intrspurious) -/* - * trap() calls here when it detects a fault in INTRFASTEXIT (loading the - * segment registers or during the iret itself). The address of the (possibly - * reconstructed) user trap frame is passed as an argument. - * - * Typically the code will have raised a SIGSEGV which will be actioned - * by the code below. - */ - .type _C_LABEL(trap_return_fault_return), @function -LABEL(trap_return_fault_return) - mov %rdi,%rsp /* frame for user return */ -#ifdef DIAGNOSTIC - /* We can't recover the saved %rbx, so suppress warning */ - movl CPUVAR(ILEVEL),%ebx -#endif - jmp .Lalltraps_checkusr -END(trap_return_fault_return) - #ifndef check_swapgs /* * We need to worry about traps in kernel mode while the kernel %gs isn't @@ -423,12 +411,33 @@ NENTRY(check_swapgs) END(check_swapgs) #endif + TEXT_USER_END + +/* + * trap() calls here when it detects a fault in INTRFASTEXIT (loading the + * segment registers or during the iret itself). The address of the (possibly + * reconstructed) user trap frame is passed as an argument. + * + * Typically the code will have raised a SIGSEGV which will be actioned + * by the code below. + */ + .type _C_LABEL(trap_return_fault_return), @function +LABEL(trap_return_fault_return) + mov %rdi,%rsp /* frame for user return */ +#ifdef DIAGNOSTIC + /* We can't recover the saved %rbx, so suppress warning */ + movl CPUVAR(ILEVEL),%ebx +#endif + jmp .Lalltraps_checkusr +END(trap_return_fault_return) + /* * All traps go through here. Call the generic trap handler, and * check for ASTs afterwards. */ NENTRY(alltraps) INTRENTRY +.Lalltraps_noentry: STI(si) calltrap: Index: src/sys/arch/amd64/amd64/locore.S diff -u src/sys/arch/amd64/amd64/locore.S:1.147 src/sys/arch/amd64/amd64/locore.S:1.148 --- src/sys/arch/amd64/amd64/locore.S:1.147 Thu Jan 18 07:25:34 2018 +++ src/sys/arch/amd64/amd64/locore.S Sun Jan 21 11:21:40 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.147 2018/01/18 07:25:34 maxv Exp $ */ +/* $NetBSD: locore.S,v 1.148 2018/01/21 11:21:40 maxv Exp $ */ /* * Copyright-o-rama! @@ -1248,76 +1248,12 @@ ENTRY(savectx) ret END(savectx) -IDTVEC(syscall32) - sysret /* go away please */ -IDTVEC_END(syscall32) - /* - * syscall() - * - * syscall insn entry. + * Syscall handler. */ -IDTVEC(syscall) -#ifndef XEN - /* - * The user %rip is in %rcx and the user %rflags in %r11. The kernel %cs - * and %ss are loaded, but nothing else is. - * - * The 'swapgs' instruction gives us access to cpu-specific memory where - * we can save a user register and then read the LWP's kernel stack - * pointer. - * - * This code doesn't seem to set %ds, this may not matter since it is - * ignored in 64bit mode, OTOH the syscall instruction sets %ss and that - * is ignored as well. - */ - swapgs - -#ifdef SVS - movq %rax,SVS_UTLS+UTLS_SCRATCH - movq SVS_UTLS+UTLS_RSP0,%rax -#define SP(x) (x)-(TF_SS+8)(%rax) -#else - movq %r15,CPUVAR(SCRATCH) - movq CPUVAR(CURLWP),%r15 - movq L_PCB(%r15),%r15 - movq PCB_RSP0(%r15),%r15 /* LWP's kernel stack pointer */ -#define SP(x) (x)-(TF_SS+8)(%r15) -#endif - - /* Make stack look like an 'int nn' frame */ - movq $(LSEL(LUDATA_SEL, SEL_UPL)),SP(TF_SS) /* user %ss */ - movq %rsp,SP(TF_RSP) /* user %rsp */ - movq %r11,SP(TF_RFLAGS) /* user %rflags */ - movq $(LSEL(LUCODE_SEL, SEL_UPL)),SP(TF_CS) /* user %cs */ - movq %rcx,SP(TF_RIP) /* user %rip */ - - leaq SP(0),%rsp /* %rsp now valid after frame */ -#ifdef SVS - movq SVS_UTLS+UTLS_SCRATCH,%rax -#else - movq CPUVAR(SCRATCH),%r15 -#endif - - movq $2,TF_ERR(%rsp) /* syscall instruction size */ - movq $T_ASTFLT,TF_TRAPNO(%rsp) -#else - /* Xen already switched to kernel stack */ - addq $0x10,%rsp /* gap to match cs:rip */ - pushq $2 /* error code */ - pushq $T_ASTFLT - subq $TF_REGSIZE,%rsp - cld -#endif - INTR_SAVE_GPRS - movw $GSEL(GUDATA_SEL, SEL_UPL),TF_DS(%rsp) - movw $GSEL(GUDATA_SEL, SEL_UPL),TF_ES(%rsp) - movw $0,TF_FS(%rsp) - movw $0,TF_GS(%rsp) - SVS_ENTER +NENTRY(handle_syscall) STI(si) -.Ldo_syscall: movq CPUVAR(CURLWP),%r14 incq CPUVAR(NSYSCALL) /* count it atomically */ movq %rsp,L_MD_REGS(%r14) /* save pointer to frame */ @@ -1353,20 +1289,7 @@ IDTVEC(syscall) testl $(MDL_IRET|MDL_COMPAT32),L_MD_FLAGS(%r14) jnz intrfastexit - SVS_LEAVE - INTR_RESTORE_GPRS - SWAPGS -#ifndef XEN - movq TF_RIP(%rsp),%rcx /* %rip for sysret */ - movq TF_RFLAGS(%rsp),%r11 /* %flags for sysret */ - movq TF_RSP(%rsp),%rsp -do_sysret: - sysretq -#else - addq $TF_RIP,%rsp - pushq $256 /* VGCF_IN_SYSCALL */ - jmp HYPERVISOR_iret -#endif + jmp syscall_sysret #ifdef DIAGNOSTIC /* Report SPL error */ @@ -1398,7 +1321,7 @@ do_sysret: movq %rsp,%rdi call _C_LABEL(trap) jmp .Lsyscall_checkast /* re-check ASTs */ -IDTVEC_END(syscall) +END(handle_syscall) /* * void lwp_trampoline(void); @@ -1418,10 +1341,83 @@ NENTRY(lwp_trampoline) END(lwp_trampoline) /* + * Entry points of the 'syscall' instruction, 64bit and 32bit mode. + */ + TEXT_USER_BEGIN + +IDTVEC(syscall) +#ifndef XEN + /* + * The user %rip is in %rcx and the user %rflags in %r11. The kernel %cs + * and %ss are loaded, but nothing else is. + * + * The 'swapgs' instruction gives us access to cpu-specific memory where + * we can save a user register and then read the LWP's kernel stack + * pointer. + * + * This code doesn't seem to set %ds, this may not matter since it is + * ignored in 64bit mode, OTOH the syscall instruction sets %ss and that + * is ignored as well. + */ + swapgs + +#ifdef SVS + movq %rax,SVS_UTLS+UTLS_SCRATCH + movq SVS_UTLS+UTLS_RSP0,%rax +#define SP(x) (x)-(TF_SS+8)(%rax) +#else + movq %r15,CPUVAR(SCRATCH) + movq CPUVAR(CURLWP),%r15 + movq L_PCB(%r15),%r15 + movq PCB_RSP0(%r15),%r15 /* LWP's kernel stack pointer */ +#define SP(x) (x)-(TF_SS+8)(%r15) +#endif + + /* Make stack look like an 'int nn' frame */ + movq $(LSEL(LUDATA_SEL, SEL_UPL)),SP(TF_SS) /* user %ss */ + movq %rsp,SP(TF_RSP) /* user %rsp */ + movq %r11,SP(TF_RFLAGS) /* user %rflags */ + movq $(LSEL(LUCODE_SEL, SEL_UPL)),SP(TF_CS) /* user %cs */ + movq %rcx,SP(TF_RIP) /* user %rip */ + + leaq SP(0),%rsp /* %rsp now valid after frame */ +#ifdef SVS + movq SVS_UTLS+UTLS_SCRATCH,%rax +#else + movq CPUVAR(SCRATCH),%r15 +#endif + + movq $2,TF_ERR(%rsp) /* syscall instruction size */ + movq $T_ASTFLT,TF_TRAPNO(%rsp) +#else + /* Xen already switched to kernel stack */ + addq $0x10,%rsp /* gap to match cs:rip */ + pushq $2 /* error code */ + pushq $T_ASTFLT + subq $TF_REGSIZE,%rsp + cld +#endif + INTR_SAVE_GPRS + movw $GSEL(GUDATA_SEL, SEL_UPL),TF_DS(%rsp) + movw $GSEL(GUDATA_SEL, SEL_UPL),TF_ES(%rsp) + movw $0,TF_FS(%rsp) + movw $0,TF_GS(%rsp) + SVS_ENTER + jmp handle_syscall +IDTVEC_END(syscall) + +IDTVEC(syscall32) + sysret /* go away please */ +IDTVEC_END(syscall32) + + TEXT_USER_END + +/* * osyscall() * * Trap gate entry for int $80 syscall, also used by sigreturn. */ + TEXT_USER_BEGIN IDTVEC(osyscall) #ifdef XEN movq (%rsp),%rcx @@ -1431,9 +1427,32 @@ IDTVEC(osyscall) pushq $2 /* size of instruction for restart */ pushq $T_ASTFLT /* trap # for doing ASTs */ INTRENTRY - STI(si) - jmp .Ldo_syscall + jmp handle_syscall IDTVEC_END(osyscall) + TEXT_USER_END + +/* + * Return to userland via 'sysret'. + */ + TEXT_USER_BEGIN + _ALIGN_TEXT +LABEL(syscall_sysret) + SVS_LEAVE + INTR_RESTORE_GPRS + SWAPGS +#ifndef XEN + movq TF_RIP(%rsp),%rcx /* %rip for sysret */ + movq TF_RFLAGS(%rsp),%r11 /* %flags for sysret */ + movq TF_RSP(%rsp),%rsp +do_sysret: + sysretq +#else + addq $TF_RIP,%rsp + pushq $256 /* VGCF_IN_SYSCALL */ + jmp HYPERVISOR_iret +#endif +END(syscall_sysret) + TEXT_USER_END /* * bool sse2_idlezero_page(void *pg) @@ -1496,7 +1515,10 @@ ENTRY(pagezero) ret END(pagezero) -ENTRY(intrfastexit) + TEXT_USER_BEGIN + + _ALIGN_TEXT +LABEL(intrfastexit) NOT_XEN(cli;) SVS_LEAVE INTR_RESTORE_GPRS Index: src/sys/arch/amd64/amd64/machdep.c diff -u src/sys/arch/amd64/amd64/machdep.c:1.294 src/sys/arch/amd64/amd64/machdep.c:1.295 --- src/sys/arch/amd64/amd64/machdep.c:1.294 Sun Jan 21 08:20:30 2018 +++ src/sys/arch/amd64/amd64/machdep.c Sun Jan 21 11:21:40 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.294 2018/01/21 08:20:30 maxv Exp $ */ +/* $NetBSD: machdep.c,v 1.295 2018/01/21 11:21:40 maxv Exp $ */ /* * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011 @@ -110,7 +110,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.294 2018/01/21 08:20:30 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.295 2018/01/21 11:21:40 maxv Exp $"); /* #define XENDEBUG_LOW */ @@ -2266,7 +2266,7 @@ mm_md_direct_mapped_phys(paddr_t paddr, * Direct Map [OK] * Remote PCPU Areas [OK] * Kernel Heap [OK] - * Kernel Image [TODO] + * Kernel Image [OK] */ struct svs_utls { @@ -2450,6 +2450,8 @@ svs_range_add(struct cpu_info *ci, vaddr void cpu_svs_init(struct cpu_info *ci) { + extern char __text_user_start; + extern char __text_user_end; const cpuid_t cid = cpu_index(ci); struct vm_page *pg; @@ -2480,6 +2482,8 @@ cpu_svs_init(struct cpu_info *ci) svs_page_add(ci, (vaddr_t)&pcpuarea->ldt); svs_range_add(ci, (vaddr_t)&pcpuarea->ent[cid], offsetof(struct pcpu_entry, rsp0)); + svs_range_add(ci, (vaddr_t)&__text_user_start, + (vaddr_t)&__text_user_end - (vaddr_t)&__text_user_start); svs_rsp0_init(ci); svs_utls_init(ci); @@ -2595,10 +2599,6 @@ svs_pdir_switch(struct pmap *pmap) ci->ci_svs_updir[i] = pte; } - /* Kernel image. */ - pte = svs_pte_atomic_read(pmap, 511); - ci->ci_svs_updir[511] = pte; - mutex_exit(&ci->ci_svs_mtx); } #endif Index: src/sys/arch/amd64/amd64/vector.S diff -u src/sys/arch/amd64/amd64/vector.S:1.55 src/sys/arch/amd64/amd64/vector.S:1.56 --- src/sys/arch/amd64/amd64/vector.S:1.55 Sat Jan 20 14:27:15 2018 +++ src/sys/arch/amd64/amd64/vector.S Sun Jan 21 11:21:40 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: vector.S,v 1.55 2018/01/20 14:27:15 maxv Exp $ */ +/* $NetBSD: vector.S,v 1.56 2018/01/21 11:21:40 maxv Exp $ */ /* * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc. @@ -116,10 +116,7 @@ IDTVEC(recurse_lapic_ipi) INTRENTRY jmp 1f IDTVEC_END(recurse_lapic_ipi) -IDTVEC(intr_x2apic_ipi) - pushq $0 - pushq $T_ASTFLT - INTRENTRY +NENTRY(handle_x2apic_ipi) movl $(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx xorl %eax,%eax xorl %edx,%edx @@ -128,18 +125,15 @@ IDTVEC(intr_x2apic_ipi) cmpl $IPL_HIGH,%ebx jae 2f jmp 1f -IDTVEC_END(intr_x2apic_ipi) -IDTVEC(intr_lapic_ipi) - pushq $0 - pushq $T_ASTFLT - INTRENTRY +END(handle_x2apic_ipi) +NENTRY(handle_lapic_ipi) movq _C_LABEL(local_apic_va),%rbx movl $0,LAPIC_EOI(%rbx) movl CPUVAR(ILEVEL),%ebx cmpl $IPL_HIGH,%ebx jae 2f jmp 1f -IDTVEC_END(intr_lapic_ipi) +END(handle_lapic_ipi) IDTVEC(resume_lapic_ipi) 1: incl CPUVAR(IDEPTH) @@ -153,12 +147,23 @@ IDTVEC(resume_lapic_ipi) INTRFASTEXIT IDTVEC_END(resume_lapic_ipi) -#if defined(DDB) -IDTVEC(intrddbipi) -1: + TEXT_USER_BEGIN +IDTVEC(intr_x2apic_ipi) pushq $0 - pushq $T_BPTFLT + pushq $T_ASTFLT INTRENTRY + jmp _C_LABEL(handle_x2apic_ipi) +IDTVEC_END(intr_x2apic_ipi) +IDTVEC(intr_lapic_ipi) + pushq $0 + pushq $T_ASTFLT + INTRENTRY + jmp _C_LABEL(handle_lapic_ipi) +IDTVEC_END(intr_lapic_ipi) + TEXT_USER_END + +#if defined(DDB) +NENTRY(handle_intrddbipi) movl $0xf,%eax movq %rax,%cr8 movq _C_LABEL(local_apic_va),%rbx @@ -168,13 +173,8 @@ IDTVEC(intrddbipi) xorl %eax,%eax movq %rax,%cr8 INTRFASTEXIT -IDTVEC_END(intrddbipi) - -IDTVEC(x2apic_intrddbipi) -1: - pushq $0 - pushq $T_BPTFLT - INTRENTRY +END(handle_intrddbipi) +NENTRY(handle_x2apic_intrddbipi) movl $0xf,%eax movq %rax,%cr8 movl $(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx @@ -186,7 +186,23 @@ IDTVEC(x2apic_intrddbipi) xorl %eax,%eax movq %rax,%cr8 INTRFASTEXIT +END(handle_x2apic_intrddbipi) + + TEXT_USER_BEGIN +IDTVEC(intrddbipi) + pushq $0 + pushq $T_BPTFLT + INTRENTRY + jmp _C_LABEL(handle_intrddbipi) +IDTVEC_END(intrddbipi) +IDTVEC(x2apic_intrddbipi) + pushq $0 + pushq $T_BPTFLT + INTRENTRY + jmp _C_LABEL(handle_x2apic_intrddbipi) IDTVEC_END(x2apic_intrddbipi) + TEXT_USER_END + #endif /* DDB */ #endif /* MULTIPROCESSOR */ @@ -200,10 +216,7 @@ IDTVEC(recurse_lapic_ltimer) INTRENTRY jmp 1f IDTVEC_END(recurse_lapic_ltimer) -IDTVEC(intr_x2apic_ltimer) - pushq $0 - pushq $T_ASTFLT - INTRENTRY +NENTRY(handle_x2apic_ltimer) movl $(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx xorl %eax,%eax xorl %edx,%edx @@ -212,18 +225,15 @@ IDTVEC(intr_x2apic_ltimer) cmpl $IPL_CLOCK,%ebx jae 2f jmp 1f -IDTVEC_END(intr_x2apic_ltimer) -IDTVEC(intr_lapic_ltimer) - pushq $0 - pushq $T_ASTFLT - INTRENTRY +END(handle_x2apic_ltimer) +NENTRY(handle_lapic_ltimer) movq _C_LABEL(local_apic_va),%rbx movl $0,LAPIC_EOI(%rbx) movl CPUVAR(ILEVEL),%ebx cmpl $IPL_CLOCK,%ebx jae 2f jmp 1f -IDTVEC_END(intr_lapic_ltimer) +END(handle_lapic_ltimer) IDTVEC(resume_lapic_ltimer) 1: incl CPUVAR(IDEPTH) @@ -238,33 +248,57 @@ IDTVEC(resume_lapic_ltimer) orl $(1 << LIR_TIMER),CPUVAR(IPENDING) INTRFASTEXIT IDTVEC_END(resume_lapic_ltimer) + + TEXT_USER_BEGIN +IDTVEC(intr_x2apic_ltimer) + pushq $0 + pushq $T_ASTFLT + INTRENTRY + jmp _C_LABEL(handle_x2apic_ltimer) +IDTVEC_END(intr_x2apic_ltimer) +IDTVEC(intr_lapic_ltimer) + pushq $0 + pushq $T_ASTFLT + INTRENTRY + jmp _C_LABEL(handle_lapic_ltimer) +IDTVEC_END(intr_lapic_ltimer) + TEXT_USER_END + #endif /* NLAPIC > 0 */ #ifndef XEN /* * TLB shootdown handler. */ -IDTVEC(intr_lapic_tlb) - pushq $0 - pushq $T_ASTFLT - INTRENTRY +NENTRY(handle_lapic_tlb) movq _C_LABEL(local_apic_va),%rax movl $0,LAPIC_EOI(%rax) callq _C_LABEL(pmap_tlb_intr) INTRFASTEXIT -IDTVEC_END(intr_lapic_tlb) - -IDTVEC(intr_x2apic_tlb) - pushq $0 - pushq $T_ASTFLT - INTRENTRY +END(handle_lapic_tlb) +NENTRY(handle_x2apic_tlb) movl $(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx xorl %eax,%eax xorl %edx,%edx wrmsr callq _C_LABEL(pmap_tlb_intr) INTRFASTEXIT +END(handle_x2apic_tlb) + + TEXT_USER_BEGIN +IDTVEC(intr_lapic_tlb) + pushq $0 + pushq $T_ASTFLT + INTRENTRY + jmp _C_LABEL(handle_lapic_tlb) +IDTVEC_END(intr_lapic_tlb) +IDTVEC(intr_x2apic_tlb) + pushq $0 + pushq $T_ASTFLT + INTRENTRY + jmp _C_LABEL(handle_x2apic_tlb) IDTVEC_END(intr_x2apic_tlb) + TEXT_USER_END #endif /* !XEN */ @@ -292,10 +326,7 @@ IDTVEC(resume_ ## name ## num) \ movl IS_MAXLEVEL(%r14),%ebx ;\ jmp 1f ;\ IDTVEC_END(resume_ ## name ## num) ;\ -IDTVEC(intr_ ## name ## num) ;\ - pushq $0 /* dummy error code */ ;\ - pushq $T_ASTFLT /* trap # for doing ASTs */ ;\ - INTRENTRY ;\ +NENTRY(handle_ ## name ## num) ;\ movq CPUVAR(ISOURCES) + (num) * 8,%r14 ;\ mask(num) /* mask it in hardware */ ;\ early_ack(num) /* and allow other intrs */ ;\ @@ -347,7 +378,15 @@ IDTVEC(intr_ ## name ## num) ;\ unmask(num) ;\ late_ack(num) ;\ INTRFASTEXIT ;\ -IDTVEC_END(intr_ ## name ## num) +END(handle_ ## name ## num) ;\ + TEXT_USER_BEGIN ;\ +IDTVEC(intr_ ## name ## num) ;\ + pushq $0 /* dummy error code */ ;\ + pushq $T_ASTFLT /* trap # for doing ASTs */ ;\ + INTRENTRY ;\ + jmp _C_LABEL(handle_ ## name ## num) ;\ +IDTVEC_END(intr_ ## name ## num) ;\ + TEXT_USER_END #define ICUADDR IO_ICU1 Index: src/sys/arch/amd64/conf/kern.ldscript diff -u src/sys/arch/amd64/conf/kern.ldscript:1.25 src/sys/arch/amd64/conf/kern.ldscript:1.26 --- src/sys/arch/amd64/conf/kern.ldscript:1.25 Sun Jan 7 12:42:46 2018 +++ src/sys/arch/amd64/conf/kern.ldscript Sun Jan 21 11:21:40 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: kern.ldscript,v 1.25 2018/01/07 12:42:46 maxv Exp $ */ +/* $NetBSD: kern.ldscript,v 1.26 2018/01/21 11:21:40 maxv Exp $ */ #include "assym.h" @@ -15,6 +15,12 @@ SECTIONS { .text : AT (ADDR(.text) & 0x0fffffff) { + . = ALIGN(__PAGE_SIZE); + __text_user_start = . ; + *(.text.user) + . = ALIGN(__PAGE_SIZE); + __text_user_end = . ; + *(.text) *(.text.*) *(.stub) Index: src/sys/arch/amd64/conf/kern.ldscript.kaslr diff -u src/sys/arch/amd64/conf/kern.ldscript.kaslr:1.4 src/sys/arch/amd64/conf/kern.ldscript.kaslr:1.5 --- src/sys/arch/amd64/conf/kern.ldscript.kaslr:1.4 Sun Jan 7 12:42:46 2018 +++ src/sys/arch/amd64/conf/kern.ldscript.kaslr Sun Jan 21 11:21:40 2018 @@ -1,10 +1,18 @@ -/* $NetBSD: kern.ldscript.kaslr,v 1.4 2018/01/07 12:42:46 maxv Exp $ */ +/* $NetBSD: kern.ldscript.kaslr,v 1.5 2018/01/21 11:21:40 maxv Exp $ */ #include "assym.h" ENTRY(_start) SECTIONS { + .text.user : SUBALIGN(PAGE_SIZE) + { + __text_user_start = . ; + *(.text.user) + . = ALIGN(PAGE_SIZE); + __text_user_end = . ; + } =0xCC + .text : { *(.text) Index: src/sys/arch/amd64/include/frameasm.h diff -u src/sys/arch/amd64/include/frameasm.h:1.30 src/sys/arch/amd64/include/frameasm.h:1.31 --- src/sys/arch/amd64/include/frameasm.h:1.30 Sat Jan 20 14:39:21 2018 +++ src/sys/arch/amd64/include/frameasm.h Sun Jan 21 11:21:40 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: frameasm.h,v 1.30 2018/01/20 14:39:21 maxv Exp $ */ +/* $NetBSD: frameasm.h,v 1.31 2018/01/21 11:21:40 maxv Exp $ */ #ifndef _AMD64_MACHINE_FRAMEASM_H #define _AMD64_MACHINE_FRAMEASM_H @@ -96,6 +96,9 @@ movq TF_RBX(%rsp),%rbx ; \ movq TF_RAX(%rsp),%rax +#define TEXT_USER_BEGIN .pushsection .text.user, "ax" +#define TEXT_USER_END .popsection + #ifdef SVS /* XXX: put this somewhere else */