/* -*- mode: asm -*- */1/*-2* SPDX-License-Identifier: BSD-3-Clause3*4* Copyright (c) 1993 The Regents of the University of California.5* All rights reserved.6*7* Copyright (c) 2018 The FreeBSD Foundation8* All rights reserved.9*10* Portions of this software were developed by11* Konstantin Belousov <[email protected]> under sponsorship from12* the FreeBSD Foundation.13*14* Redistribution and use in source and binary forms, with or without15* modification, are permitted provided that the following conditions16* are met:17* 1. Redistributions of source code must retain the above copyright18* notice, this list of conditions and the following disclaimer.19* 2. Redistributions in binary form must reproduce the above copyright20* notice, this list of conditions and the following disclaimer in the21* documentation and/or other materials provided with the distribution.22* 3. Neither the name of the University nor the names of its contributors23* may be used to endorse or promote products derived from this software24* without specific prior written permission.25*26* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND27* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE28* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE29* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE30* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL31* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS32* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)33* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT34* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY35* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF36* SUCH DAMAGE.37*/3839#if defined(__i386__)40#include <i386/asmacros.h>41#else /* !__i386__ */4243#ifndef _MACHINE_ASMACROS_H_44#define _MACHINE_ASMACROS_H_4546#include <sys/cdefs.h>4748/* XXX too much duplication in various asm*.h's. */4950/*51* CNAME is used to manage the relationship between symbol names in C52* and the equivalent assembly language names. CNAME is given a name as53* it would be used in a C program. It expands to the equivalent assembly54* language name.55*/56#define CNAME(csym) csym5758#define ALIGN_DATA .p2align 3 /* 8 byte alignment, zero filled */59#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */60#define SUPERALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */6162#define GEN_ENTRY(name) ALIGN_TEXT; .globl CNAME(name); \63.type CNAME(name),@function; CNAME(name):64#define ENTRY(name) GEN_ENTRY(name)65#define ALTENTRY(name) GEN_ENTRY(name)66#define END(name) .size name, . - name6768/*69* Convenience for adding frame pointers to hand-coded ASM. Useful for70* DTrace, HWPMC, and KDB.71*/72#define PUSH_FRAME_POINTER \73pushq %rbp ; \74movq %rsp, %rbp ;75#define POP_FRAME_POINTER \76popq %rbp7778#ifdef LOCORE79/*80* Access per-CPU data.81*/82#define PCPU(member) %gs:PC_ ## member83#define PCPU_ADDR(member, reg) \84movq %gs:PC_PRVSPACE, reg ; \85addq $PC_ ## member, reg8687/*88* Convenience macro for declaring interrupt entry points.89*/90#define IDTVEC(name) ALIGN_TEXT; .globl __CONCAT(X,name); \91.type __CONCAT(X,name),@function; __CONCAT(X,name):9293.macro SAVE_SEGS94movw %fs,TF_FS(%rsp)95movw %gs,TF_GS(%rsp)96movw %es,TF_ES(%rsp)97movw %ds,TF_DS(%rsp)98.endm99100.macro MOVE_STACKS qw101.L.offset=0102.rept \qw103movq .L.offset(%rsp),%rdx104movq %rdx,.L.offset(%rax)105.L.offset=.L.offset+8106.endr107.endm108109.macro PTI_UUENTRY has_err110movq PCPU(KCR3),%rax111movq %rax,%cr3112movq PCPU(RSP0),%rax113subq $PTI_SIZE - 8 * (1 - \has_err),%rax114MOVE_STACKS ((PTI_SIZE / 8) - 1 + \has_err)115movq %rax,%rsp116popq %rdx117popq %rax118.endm119120.macro PTI_UENTRY has_err121swapgs122lfence123cmpq $~0,PCPU(UCR3)124je 1f125pushq %rax126pushq %rdx127PTI_UUENTRY \has_err1281:129.endm130131.macro PTI_ENTRY name, contk, contu, has_err=0132ALIGN_TEXT133.globl X\name\()_pti134.type X\name\()_pti,@function135X\name\()_pti:136/* %rax, %rdx, and possibly err are not yet pushed */137testb $SEL_RPL_MASK,PTI_CS-PTI_ERR-((1-\has_err)*8)(%rsp)138jz \contk139PTI_UENTRY \has_err140jmp \contu141.endm142143.macro PTI_INTRENTRY vec_name144SUPERALIGN_TEXT145.globl X\vec_name\()_pti146.type X\vec_name\()_pti,@function147X\vec_name\()_pti:148testb $SEL_RPL_MASK,PTI_CS-3*8(%rsp) /* err, %rax, %rdx not pushed */149jz .L\vec_name\()_u150PTI_UENTRY has_err=0151jmp .L\vec_name\()_u152.endm153154.macro INTR_PUSH_FRAME vec_name155SUPERALIGN_TEXT156.globl X\vec_name157.type X\vec_name,@function158X\vec_name:159testb $SEL_RPL_MASK,PTI_CS-3*8(%rsp) /* come from kernel? */160jz .L\vec_name\()_u /* Yes, dont swapgs again */161swapgs162.L\vec_name\()_u:163lfence164subq $TF_RIP,%rsp /* skip dummy tf_err and tf_trapno */165movq %rdi,TF_RDI(%rsp)166movq %rsi,TF_RSI(%rsp)167movq %rdx,TF_RDX(%rsp)168movq %rcx,TF_RCX(%rsp)169movq %r8,TF_R8(%rsp)170movq %r9,TF_R9(%rsp)171movq %rax,TF_RAX(%rsp)172movq %rbx,TF_RBX(%rsp)173movq %rbp,TF_RBP(%rsp)174movq %r10,TF_R10(%rsp)175movq %r11,TF_R11(%rsp)176movq %r12,TF_R12(%rsp)177movq %r13,TF_R13(%rsp)178movq %r14,TF_R14(%rsp)179movq %r15,TF_R15(%rsp)180SAVE_SEGS181movl $TF_HASSEGS,TF_FLAGS(%rsp)182pushfq183andq $~(PSL_D|PSL_AC),(%rsp)184popfq185testb $SEL_RPL_MASK,TF_CS(%rsp) /* come from kernel ? */186jz 1f /* yes, leave PCB_FULL_IRET alone */187movq PCPU(CURPCB),%r8188andl $~PCB_FULL_IRET,PCB_FLAGS(%r8)189call handle_ibrs_entry1901:191.endm192193.macro INTR_HANDLER vec_name194.text195PTI_INTRENTRY \vec_name196INTR_PUSH_FRAME \vec_name197.endm198199.macro RESTORE_REGS200movq TF_RDI(%rsp),%rdi201movq TF_RSI(%rsp),%rsi202movq TF_RDX(%rsp),%rdx203movq TF_RCX(%rsp),%rcx204movq TF_R8(%rsp),%r8205movq TF_R9(%rsp),%r9206movq TF_RAX(%rsp),%rax207movq TF_RBX(%rsp),%rbx208movq TF_RBP(%rsp),%rbp209movq TF_R10(%rsp),%r10210movq TF_R11(%rsp),%r11211movq TF_R12(%rsp),%r12212movq TF_R13(%rsp),%r13213movq TF_R14(%rsp),%r14214movq TF_R15(%rsp),%r15215.endm216217#ifdef KMSAN218/*219* The KMSAN runtime relies on a TLS block to track initialization and origin220* state for function parameters and return values. To keep this state221* consistent in the face of asynchronous kernel-mode traps, the runtime222* maintains a stack of blocks: when handling an exception or interrupt,223* kmsan_intr_enter() pushes the new block to be used until the handler is224* complete, at which point kmsan_intr_leave() restores the previous block.225*226* Thus, KMSAN_ENTER/LEAVE hooks are required only in handlers for events that227* may have happened while in kernel-mode. In particular, they are not required228* around amd64_syscall() or ast() calls. Otherwise, kmsan_intr_enter() can be229* called unconditionally, without distinguishing between entry from user-mode230* or kernel-mode.231*/232#define KMSAN_ENTER callq kmsan_intr_enter233#define KMSAN_LEAVE callq kmsan_intr_leave234#else235#define KMSAN_ENTER236#define KMSAN_LEAVE237#endif238239#endif /* LOCORE */240241#ifdef __STDC__242#define ELFNOTE(name, type, desctype, descdata...) \243.pushsection .note.name, "a", @note ; \244.align 4 ; \245.long 2f - 1f /* namesz */ ; \246.long 4f - 3f /* descsz */ ; \247.long type ; \2481:.asciz #name ; \2492:.align 4 ; \2503:desctype descdata ; \2514:.align 4 ; \252.popsection253#else /* !__STDC__, i.e. -traditional */254#define ELFNOTE(name, type, desctype, descdata) \255.pushsection .note.name, "a", @note ; \256.align 4 ; \257.long 2f - 1f /* namesz */ ; \258.long 4f - 3f /* descsz */ ; \259.long type ; \2601:.asciz "name" ; \2612:.align 4 ; \2623:desctype descdata ; \2634:.align 4 ; \264.popsection265#endif /* __STDC__ */266267#endif /* !_MACHINE_ASMACROS_H_ */268269#endif /* __i386__ */270271272