1*376bcb54Sriastradh /* $NetBSD: frameasm.h,v 1.55 2022/07/30 14:11:00 riastradh Exp $ */ 281918bf8Sfvdl 381918bf8Sfvdl #ifndef _AMD64_MACHINE_FRAMEASM_H 481918bf8Sfvdl #define _AMD64_MACHINE_FRAMEASM_H 591ca02fcSad 691ca02fcSad #ifdef _KERNEL_OPT 74e541343Sbouyer #include "opt_xen.h" 8da72fac8Smaxv #include "opt_svs.h" 9e7e5aa03Smaxv #include "opt_kcov.h" 1010c5b023Smaxv #include "opt_kmsan.h" 1191ca02fcSad #endif 1281918bf8Sfvdl 1381918bf8Sfvdl /* 1481918bf8Sfvdl * Macros to define pushing/popping frames for interrupts, traps 1581918bf8Sfvdl * and system calls. Currently all the same; will diverge later. 1681918bf8Sfvdl */ 1781918bf8Sfvdl 18427af037Scherry #ifdef XENPV 194e541343Sbouyer #define HYPERVISOR_iret hypercall_page + (__HYPERVISOR_iret * 32) 204e541343Sbouyer /* Xen do not need swapgs, done by hypervisor */ 214e541343Sbouyer #define swapgs 224e541343Sbouyer #define iretq pushq $0 ; jmp HYPERVISOR_iret 2353a9a10fSdsl #define XEN_ONLY2(x,y) x,y 2453a9a10fSdsl #define NOT_XEN(x) 2553a9a10fSdsl 2653a9a10fSdsl #define CLI(temp_reg) \ 2753a9a10fSdsl movq CPUVAR(VCPU),%r ## temp_reg ; \ 2853a9a10fSdsl movb $1,EVTCHN_UPCALL_MASK(%r ## temp_reg); 2953a9a10fSdsl 3053a9a10fSdsl #define STI(temp_reg) \ 3153a9a10fSdsl movq CPUVAR(VCPU),%r ## temp_reg ; \ 3253a9a10fSdsl movb $0,EVTCHN_UPCALL_MASK(%r ## temp_reg); 3353a9a10fSdsl 34c24c993fSbouyer #define PUSHF(temp_reg) \ 35c24c993fSbouyer movq CPUVAR(VCPU),%r ## temp_reg ; \ 36c24c993fSbouyer movzbl EVTCHN_UPCALL_MASK(%r ## temp_reg), %e ## temp_reg; \ 37c24c993fSbouyer pushq %r ## temp_reg 38c24c993fSbouyer 39c24c993fSbouyer #define POPF \ 40c24c993fSbouyer popq %rdi; \ 41c24c993fSbouyer call _C_LABEL(xen_write_psl) 42c24c993fSbouyer 43c24c993fSbouyer 44427af037Scherry #else /* XENPV */ 4553a9a10fSdsl #define XEN_ONLY2(x,y) 4653a9a10fSdsl #define NOT_XEN(x) x 4753a9a10fSdsl #define CLI(temp_reg) cli 4853a9a10fSdsl #define STI(temp_reg) sti 49c24c993fSbouyer #define PUSHF(temp_reg) pushf 50c24c993fSbouyer #define POPL popl 51c1ac8a41Sbouyer #endif /* XENPV */ 524e541343Sbouyer 5399d8611cSmaxv #define HP_NAME_CLAC 1 5499d8611cSmaxv #define HP_NAME_STAC 2 559ef803feSmaxv #define HP_NAME_NOLOCK 3 566fcf3f0aSmaxv #define HP_NAME_RETFENCE 4 57ebc1f703Smaxv #define HP_NAME_SVS_ENTER 5 58ebc1f703Smaxv #define HP_NAME_SVS_LEAVE 6 59ebc1f703Smaxv #define HP_NAME_SVS_ENTER_ALT 7 60ebc1f703Smaxv #define HP_NAME_SVS_LEAVE_ALT 8 610223f0c8Smaxv #define HP_NAME_IBRS_ENTER 9 620223f0c8Smaxv #define HP_NAME_IBRS_LEAVE 10 638b7b3795Smaxv #define HP_NAME_SVS_ENTER_NMI 11 648b7b3795Smaxv #define HP_NAME_SVS_LEAVE_NMI 12 6574b8eea5Smaxv #define HP_NAME_MDS_LEAVE 13 6699d8611cSmaxv 6799d8611cSmaxv #define HOTPATCH(name, size) \ 6899d8611cSmaxv 123: ; \ 6903af2da1Smaxv .pushsection .rodata.hotpatch, "a" ; \ 7099d8611cSmaxv .byte name ; \ 7199d8611cSmaxv .byte size ; \ 7299d8611cSmaxv .quad 123b ; \ 7303af2da1Smaxv .popsection 7499d8611cSmaxv 7599d8611cSmaxv #define SMAP_ENABLE \ 7699d8611cSmaxv HOTPATCH(HP_NAME_CLAC, 3) ; \ 7799d8611cSmaxv .byte 0x0F, 0x1F, 0x00 ; \ 7899d8611cSmaxv 7999d8611cSmaxv #define SMAP_DISABLE \ 8099d8611cSmaxv HOTPATCH(HP_NAME_STAC, 3) ; \ 8199d8611cSmaxv .byte 0x0F, 0x1F, 0x00 ; \ 8299d8611cSmaxv 830223f0c8Smaxv /* 840223f0c8Smaxv * IBRS 850223f0c8Smaxv */ 860223f0c8Smaxv 87125e142fSmaxv #define IBRS_ENTER_BYTES 12 880223f0c8Smaxv #define IBRS_ENTER \ 890223f0c8Smaxv HOTPATCH(HP_NAME_IBRS_ENTER, IBRS_ENTER_BYTES) ; \ 900223f0c8Smaxv NOIBRS_ENTER 910223f0c8Smaxv #define NOIBRS_ENTER \ 920223f0c8Smaxv .byte 0xEB, (IBRS_ENTER_BYTES-2) /* jmp */ ; \ 930223f0c8Smaxv .fill (IBRS_ENTER_BYTES-2),1,0xCC 940223f0c8Smaxv 95125e142fSmaxv #define IBRS_LEAVE_BYTES 12 960223f0c8Smaxv #define IBRS_LEAVE \ 970223f0c8Smaxv HOTPATCH(HP_NAME_IBRS_LEAVE, IBRS_LEAVE_BYTES) ; \ 980223f0c8Smaxv NOIBRS_LEAVE 990223f0c8Smaxv #define NOIBRS_LEAVE \ 1000223f0c8Smaxv .byte 0xEB, (IBRS_LEAVE_BYTES-2) /* jmp */ ; \ 1010223f0c8Smaxv .fill (IBRS_LEAVE_BYTES-2),1,0xCC 1020223f0c8Smaxv 10374b8eea5Smaxv /* 10474b8eea5Smaxv * MDS 10574b8eea5Smaxv */ 10674b8eea5Smaxv 107125e142fSmaxv #define MDS_LEAVE_BYTES 10 10874b8eea5Smaxv #define MDS_LEAVE \ 10974b8eea5Smaxv HOTPATCH(HP_NAME_MDS_LEAVE, MDS_LEAVE_BYTES) ; \ 11074b8eea5Smaxv NOMDS_LEAVE 11174b8eea5Smaxv #define NOMDS_LEAVE \ 11274b8eea5Smaxv .byte 0xEB, (MDS_LEAVE_BYTES-2) /* jmp */ ; \ 11374b8eea5Smaxv .fill (MDS_LEAVE_BYTES-2),1,0xCC 11474b8eea5Smaxv 115c578e8d2Sdsl #define SWAPGS NOT_XEN(swapgs) 116c578e8d2Sdsl 11781918bf8Sfvdl /* 11881918bf8Sfvdl * These are used on interrupt or trap entry or exit. 11981918bf8Sfvdl */ 12081918bf8Sfvdl #define INTR_SAVE_GPRS \ 12181918bf8Sfvdl movq %rdi,TF_RDI(%rsp) ; \ 12281918bf8Sfvdl movq %rsi,TF_RSI(%rsp) ; \ 12381918bf8Sfvdl movq %rdx,TF_RDX(%rsp) ; \ 12481918bf8Sfvdl movq %rcx,TF_RCX(%rsp) ; \ 12589a3551aSdsl movq %r8,TF_R8(%rsp) ; \ 12689a3551aSdsl movq %r9,TF_R9(%rsp) ; \ 12789a3551aSdsl movq %r10,TF_R10(%rsp) ; \ 12889a3551aSdsl movq %r11,TF_R11(%rsp) ; \ 12989a3551aSdsl movq %r12,TF_R12(%rsp) ; \ 13089a3551aSdsl movq %r13,TF_R13(%rsp) ; \ 13189a3551aSdsl movq %r14,TF_R14(%rsp) ; \ 13289a3551aSdsl movq %r15,TF_R15(%rsp) ; \ 13389a3551aSdsl movq %rbp,TF_RBP(%rsp) ; \ 13489a3551aSdsl movq %rbx,TF_RBX(%rsp) ; \ 135aa64020bSmaxv movq %rax,TF_RAX(%rsp) 13681918bf8Sfvdl 13781918bf8Sfvdl #define INTR_RESTORE_GPRS \ 13881918bf8Sfvdl movq TF_RDI(%rsp),%rdi ; \ 13981918bf8Sfvdl movq TF_RSI(%rsp),%rsi ; \ 14081918bf8Sfvdl movq TF_RDX(%rsp),%rdx ; \ 14181918bf8Sfvdl movq TF_RCX(%rsp),%rcx ; \ 14289a3551aSdsl movq TF_R8(%rsp),%r8 ; \ 14389a3551aSdsl movq TF_R9(%rsp),%r9 ; \ 14489a3551aSdsl movq TF_R10(%rsp),%r10 ; \ 14589a3551aSdsl movq TF_R11(%rsp),%r11 ; \ 14689a3551aSdsl movq TF_R12(%rsp),%r12 ; \ 14789a3551aSdsl movq TF_R13(%rsp),%r13 ; \ 14889a3551aSdsl movq TF_R14(%rsp),%r14 ; \ 14989a3551aSdsl movq TF_R15(%rsp),%r15 ; \ 15089a3551aSdsl movq TF_RBP(%rsp),%rbp ; \ 15189a3551aSdsl movq TF_RBX(%rsp),%rbx ; \ 15289a3551aSdsl movq TF_RAX(%rsp),%rax 15381918bf8Sfvdl 154cea874c7Smaxv #define TEXT_USER_BEGIN .pushsection .text.user, "ax" 155cea874c7Smaxv #define TEXT_USER_END .popsection 156cea874c7Smaxv 157da72fac8Smaxv #ifdef SVS 15868bdfac8Smaxv 15968bdfac8Smaxv /* XXX: put this somewhere else */ 160afb643e1Smaxv #define SVS_UTLS 0xffffff0000000000 /* PMAP_PCPU_BASE */ 16168bdfac8Smaxv #define UTLS_KPDIRPA 0 16268bdfac8Smaxv #define UTLS_SCRATCH 8 16368bdfac8Smaxv #define UTLS_RSP0 16 16468bdfac8Smaxv 165ebc1f703Smaxv #define SVS_ENTER_BYTES 22 1665ab8a4e7Smaxv #define NOSVS_ENTER \ 167ebc1f703Smaxv .byte 0xEB, (SVS_ENTER_BYTES-2) /* jmp */ ; \ 168ebc1f703Smaxv .fill (SVS_ENTER_BYTES-2),1,0xCC 1695ab8a4e7Smaxv #define SVS_ENTER \ 1705ab8a4e7Smaxv HOTPATCH(HP_NAME_SVS_ENTER, SVS_ENTER_BYTES) ; \ 1715ab8a4e7Smaxv NOSVS_ENTER 17268bdfac8Smaxv 173125e142fSmaxv #define SVS_LEAVE_BYTES 21 1745ab8a4e7Smaxv #define NOSVS_LEAVE \ 175ebc1f703Smaxv .byte 0xEB, (SVS_LEAVE_BYTES-2) /* jmp */ ; \ 176ebc1f703Smaxv .fill (SVS_LEAVE_BYTES-2),1,0xCC 1775ab8a4e7Smaxv #define SVS_LEAVE \ 1785ab8a4e7Smaxv HOTPATCH(HP_NAME_SVS_LEAVE, SVS_LEAVE_BYTES) ; \ 1795ab8a4e7Smaxv NOSVS_LEAVE 18068bdfac8Smaxv 181ebc1f703Smaxv #define SVS_ENTER_ALT_BYTES 23 1825ab8a4e7Smaxv #define NOSVS_ENTER_ALTSTACK \ 183ebc1f703Smaxv .byte 0xEB, (SVS_ENTER_ALT_BYTES-2) /* jmp */ ; \ 184ebc1f703Smaxv .fill (SVS_ENTER_ALT_BYTES-2),1,0xCC 1855ab8a4e7Smaxv #define SVS_ENTER_ALTSTACK \ 1865ab8a4e7Smaxv HOTPATCH(HP_NAME_SVS_ENTER_ALT, SVS_ENTER_ALT_BYTES) ; \ 1875ab8a4e7Smaxv NOSVS_ENTER_ALTSTACK 18868bdfac8Smaxv 189ebc1f703Smaxv #define SVS_LEAVE_ALT_BYTES 22 1905ab8a4e7Smaxv #define NOSVS_LEAVE_ALTSTACK \ 191ebc1f703Smaxv .byte 0xEB, (SVS_LEAVE_ALT_BYTES-2) /* jmp */ ; \ 192ebc1f703Smaxv .fill (SVS_LEAVE_ALT_BYTES-2),1,0xCC 1935ab8a4e7Smaxv #define SVS_LEAVE_ALTSTACK \ 1945ab8a4e7Smaxv HOTPATCH(HP_NAME_SVS_LEAVE_ALT, SVS_LEAVE_ALT_BYTES) ; \ 1955ab8a4e7Smaxv NOSVS_LEAVE_ALTSTACK 196ebc1f703Smaxv 1978b7b3795Smaxv #define SVS_ENTER_NMI_BYTES 22 1988b7b3795Smaxv #define NOSVS_ENTER_NMI \ 1998b7b3795Smaxv .byte 0xEB, (SVS_ENTER_NMI_BYTES-2) /* jmp */ ; \ 2008b7b3795Smaxv .fill (SVS_ENTER_NMI_BYTES-2),1,0xCC 2018b7b3795Smaxv #define SVS_ENTER_NMI \ 2028b7b3795Smaxv HOTPATCH(HP_NAME_SVS_ENTER_NMI, SVS_ENTER_NMI_BYTES) ; \ 2038b7b3795Smaxv NOSVS_ENTER_NMI 2048b7b3795Smaxv 2058b7b3795Smaxv #define SVS_LEAVE_NMI_BYTES 11 2068b7b3795Smaxv #define NOSVS_LEAVE_NMI \ 2078b7b3795Smaxv .byte 0xEB, (SVS_LEAVE_NMI_BYTES-2) /* jmp */ ; \ 2088b7b3795Smaxv .fill (SVS_LEAVE_NMI_BYTES-2),1,0xCC 2098b7b3795Smaxv #define SVS_LEAVE_NMI \ 2108b7b3795Smaxv HOTPATCH(HP_NAME_SVS_LEAVE_NMI, SVS_LEAVE_NMI_BYTES) ; \ 2118b7b3795Smaxv NOSVS_LEAVE_NMI 2128b7b3795Smaxv 213da72fac8Smaxv #else 214da72fac8Smaxv #define SVS_ENTER /* nothing */ 2152681a041Smartin #define SVS_ENTER_NMI /* nothing */ 216da72fac8Smaxv #define SVS_LEAVE /* nothing */ 2172681a041Smartin #define SVS_LEAVE_NMI /* nothing */ 21868bdfac8Smaxv #define SVS_ENTER_ALTSTACK /* nothing */ 21968bdfac8Smaxv #define SVS_LEAVE_ALTSTACK /* nothing */ 220da72fac8Smaxv #endif 221da72fac8Smaxv 22210c5b023Smaxv #ifdef KMSAN 223248fe10bSad /* XXX this belongs somewhere else. */ 22410c5b023Smaxv #define KMSAN_ENTER \ 22510c5b023Smaxv movq %rsp,%rdi ; \ 22610c5b023Smaxv movq $TF_REGSIZE+16+40,%rsi ; \ 22710c5b023Smaxv xorq %rdx,%rdx ; \ 22810c5b023Smaxv callq kmsan_mark ; \ 22910c5b023Smaxv callq kmsan_intr_enter 23010c5b023Smaxv #define KMSAN_LEAVE \ 23110c5b023Smaxv pushq %rbp ; \ 23210c5b023Smaxv movq %rsp,%rbp ; \ 23310c5b023Smaxv callq kmsan_intr_leave ; \ 23410c5b023Smaxv popq %rbp 23510c5b023Smaxv #define KMSAN_INIT_ARG(sz) \ 23610c5b023Smaxv pushq %rax ; \ 23710c5b023Smaxv pushq %rcx ; \ 23810c5b023Smaxv pushq %rdx ; \ 23910c5b023Smaxv pushq %rsi ; \ 24010c5b023Smaxv pushq %rdi ; \ 24110c5b023Smaxv pushq %r8 ; \ 24210c5b023Smaxv pushq %r9 ; \ 24310c5b023Smaxv pushq %r10 ; \ 24410c5b023Smaxv pushq %r11 ; \ 24510c5b023Smaxv movq $sz,%rdi ; \ 24610c5b023Smaxv callq _C_LABEL(kmsan_init_arg); \ 24710c5b023Smaxv popq %r11 ; \ 24810c5b023Smaxv popq %r10 ; \ 24910c5b023Smaxv popq %r9 ; \ 25010c5b023Smaxv popq %r8 ; \ 25110c5b023Smaxv popq %rdi ; \ 25210c5b023Smaxv popq %rsi ; \ 25310c5b023Smaxv popq %rdx ; \ 25410c5b023Smaxv popq %rcx ; \ 25510c5b023Smaxv popq %rax 25610c5b023Smaxv #define KMSAN_INIT_RET(sz) \ 25710c5b023Smaxv pushq %rax ; \ 25810c5b023Smaxv pushq %rcx ; \ 25910c5b023Smaxv pushq %rdx ; \ 26010c5b023Smaxv pushq %rsi ; \ 26110c5b023Smaxv pushq %rdi ; \ 26210c5b023Smaxv pushq %r8 ; \ 26310c5b023Smaxv pushq %r9 ; \ 26410c5b023Smaxv pushq %r10 ; \ 26510c5b023Smaxv pushq %r11 ; \ 26610c5b023Smaxv movq $sz,%rdi ; \ 26710c5b023Smaxv callq _C_LABEL(kmsan_init_ret); \ 26810c5b023Smaxv popq %r11 ; \ 26910c5b023Smaxv popq %r10 ; \ 27010c5b023Smaxv popq %r9 ; \ 27110c5b023Smaxv popq %r8 ; \ 27210c5b023Smaxv popq %rdi ; \ 27310c5b023Smaxv popq %rsi ; \ 27410c5b023Smaxv popq %rdx ; \ 27510c5b023Smaxv popq %rcx ; \ 27610c5b023Smaxv popq %rax 27710c5b023Smaxv #else 27810c5b023Smaxv #define KMSAN_ENTER /* nothing */ 27910c5b023Smaxv #define KMSAN_LEAVE /* nothing */ 28010c5b023Smaxv #define KMSAN_INIT_ARG(sz) /* nothing */ 28110c5b023Smaxv #define KMSAN_INIT_RET(sz) /* nothing */ 28210c5b023Smaxv #endif 28310c5b023Smaxv 284e7e5aa03Smaxv #ifdef KCOV 285e7e5aa03Smaxv #define KCOV_DISABLE \ 286e7e5aa03Smaxv incl CPUVAR(IDEPTH) 287e7e5aa03Smaxv #define KCOV_ENABLE \ 288e7e5aa03Smaxv decl CPUVAR(IDEPTH) 289e7e5aa03Smaxv #else 290e7e5aa03Smaxv #define KCOV_DISABLE /* nothing */ 291e7e5aa03Smaxv #define KCOV_ENABLE /* nothing */ 292e7e5aa03Smaxv #endif 293e7e5aa03Smaxv 294ccc038a8Smaxv #define INTRENTRY \ 29589a3551aSdsl subq $TF_REGSIZE,%rsp ; \ 29653a9a10fSdsl INTR_SAVE_GPRS ; \ 297aa64020bSmaxv cld ; \ 29899d8611cSmaxv SMAP_ENABLE ; \ 29953a9a10fSdsl testb $SEL_UPL,TF_CS(%rsp) ; \ 300ccc038a8Smaxv je 98f ; \ 301c578e8d2Sdsl SWAPGS ; \ 3020223f0c8Smaxv IBRS_ENTER ; \ 303da72fac8Smaxv SVS_ENTER ; \ 30489a3551aSdsl movw %gs,TF_GS(%rsp) ; \ 30589a3551aSdsl movw %fs,TF_FS(%rsp) ; \ 30689a3551aSdsl movw %es,TF_ES(%rsp) ; \ 307ccc038a8Smaxv movw %ds,TF_DS(%rsp) ; \ 30810c5b023Smaxv 98: KMSAN_ENTER 30953a9a10fSdsl 31081918bf8Sfvdl #define INTRFASTEXIT \ 311faf0f614Smaxv jmp intrfastexit 31281918bf8Sfvdl 31381918bf8Sfvdl #define INTR_RECURSE_HWFRAME \ 31481918bf8Sfvdl movq %rsp,%r10 ; \ 31581918bf8Sfvdl movl %ss,%r11d ; \ 31681918bf8Sfvdl pushq %r11 ; \ 31781918bf8Sfvdl pushq %r10 ; \ 31881918bf8Sfvdl pushfq ; \ 3192e43b1e6Smaxv pushq $GSEL(GCODE_SEL,SEL_KPL); \ 32053a9a10fSdsl /* XEN: We must fixup CS, as even kernel mode runs at CPL 3 */ \ 32132a80534Sdsl XEN_ONLY2(andb $0xfc,(%rsp);) \ 32281918bf8Sfvdl pushq %r13 ; 32381918bf8Sfvdl 3247318ea98Smaxv #define INTR_RECURSE_ENTRY \ 3257318ea98Smaxv subq $TF_REGSIZE,%rsp ; \ 3267318ea98Smaxv INTR_SAVE_GPRS ; \ 32710c5b023Smaxv cld ; \ 32810c5b023Smaxv KMSAN_ENTER 3297318ea98Smaxv 33024a1632cSyamt #define CHECK_DEFERRED_SWITCH \ 331ffa744f4Schs cmpl $0, CPUVAR(WANT_PMAPLOAD) 33281918bf8Sfvdl 3336c336cd7Syamt #define CHECK_ASTPENDING(reg) cmpl $0, L_MD_ASTPENDING(reg) 334b07ec3fcSad #define CLEAR_ASTPENDING(reg) movl $0, L_MD_ASTPENDING(reg) 33581918bf8Sfvdl 336560337f7Smaxv /* 337560337f7Smaxv * If the FPU state is not in the CPU, restore it. Executed with interrupts 338560337f7Smaxv * disabled. 339560337f7Smaxv * 340560337f7Smaxv * %r14 is curlwp, must not be modified 341560337f7Smaxv * %rbx must not be modified 342560337f7Smaxv */ 343560337f7Smaxv #define HANDLE_DEFERRED_FPU \ 344560337f7Smaxv testl $MDL_FPU_IN_CPU,L_MD_FLAGS(%r14) ; \ 345560337f7Smaxv jnz 1f ; \ 346560337f7Smaxv call _C_LABEL(fpu_handle_deferred) ; \ 347560337f7Smaxv orl $MDL_FPU_IN_CPU,L_MD_FLAGS(%r14) ; \ 348560337f7Smaxv 1: 349560337f7Smaxv 35081918bf8Sfvdl #endif /* _AMD64_MACHINE_FRAMEASM_H */ 351