asmacros.h revision 335570
1329462Skib/* -*- mode: asm -*- */ 21817Sdg/*- 31817Sdg * Copyright (c) 1993 The Regents of the University of California. 41817Sdg * All rights reserved. 51817Sdg * 6329462Skib * Copyright (c) 2018 The FreeBSD Foundation 7329462Skib * All rights reserved. 8329462Skib * 9329462Skib * Portions of this software were developed by 10329462Skib * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from 11329462Skib * the FreeBSD Foundation. 12329462Skib * 131817Sdg * Redistribution and use in source and binary forms, with or without 141817Sdg * modification, are permitted provided that the following conditions 151817Sdg * are met: 161817Sdg * 1. Redistributions of source code must retain the above copyright 171817Sdg * notice, this list of conditions and the following disclaimer. 181817Sdg * 2. Redistributions in binary form must reproduce the above copyright 191817Sdg * notice, this list of conditions and the following disclaimer in the 201817Sdg * documentation and/or other materials provided with the distribution. 211817Sdg * 4. Neither the name of the University nor the names of its contributors 221817Sdg * may be used to endorse or promote products derived from this software 231817Sdg * without specific prior written permission. 241817Sdg * 251817Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261817Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271817Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281817Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291817Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301817Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311817Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321817Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331817Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341817Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351817Sdg * SUCH DAMAGE. 361817Sdg * 3750477Speter * $FreeBSD: stable/11/sys/amd64/include/asmacros.h 335570 2018-06-22 23:52:20Z kib $ 381817Sdg */ 391817Sdg 402579Sbde#ifndef _MACHINE_ASMACROS_H_ 412579Sbde#define _MACHINE_ASMACROS_H_ 422123Sjkh 4316029Speter#include <sys/cdefs.h> 442579Sbde 4518961Sbde/* XXX too much duplication in various asm*.h's. */ 4613107Sbde 4725083Sjdp/* 48163726Sbde * CNAME is used to manage the relationship between symbol names in C 4925083Sjdp * and the equivalent assembly language names. CNAME is given a name as 5025083Sjdp * it would be used in a C program. It expands to the equivalent assembly 51163726Sbde * language name. 5225083Sjdp */ 5325083Sjdp#define CNAME(csym) csym 5425083Sjdp 55114349Speter#define ALIGN_DATA .p2align 3 /* 8 byte alignment, zero filled */ 5622636Sbde#ifdef GPROF 5725083Sjdp#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */ 5822636Sbde#else 59114349Speter#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */ 6022636Sbde#endif 6125083Sjdp#define SUPERALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */ 62757Sdg 6325083Sjdp#define GEN_ENTRY(name) ALIGN_TEXT; .globl CNAME(name); \ 6446548Sbde .type CNAME(name),@function; CNAME(name): 6513107Sbde#define NON_GPROF_ENTRY(name) GEN_ENTRY(name) 6618961Sbde#define NON_GPROF_RET .byte 0xc3 /* opcode for `ret' */ 67757Sdg 68171914Sjkoshy#define END(name) .size name, . - name 69171914Sjkoshy 70757Sdg#ifdef GPROF 71757Sdg/* 7246548Sbde * __mcount is like [.]mcount except that doesn't require its caller to set 7313107Sbde * up a frame pointer. It must be called before pushing anything onto the 7413107Sbde * stack. gcc should eventually generate code to call __mcount in most 7513107Sbde * cases. This would make -pg in combination with -fomit-frame-pointer 7613107Sbde * useful. gcc has a configuration variable PROFILE_BEFORE_PROLOGUE to 7713107Sbde * allow profiling before setting up the frame pointer, but this is 7813107Sbde * inadequate for good handling of special cases, e.g., -fpic works best 7913107Sbde * with profiling after the prologue. 8013107Sbde * 8146548Sbde * [.]mexitcount is a new function to support non-statistical profiling if an 8218961Sbde * accurate clock is available. For C sources, calls to it are generated 8318961Sbde * by the FreeBSD extension `-mprofiler-epilogue' to gcc. It is best to 8446548Sbde * call [.]mexitcount at the end of a function like the MEXITCOUNT macro does, 8518961Sbde * but gcc currently generates calls to it at the start of the epilogue to 8618961Sbde * avoid problems with -fpic. 8713107Sbde * 8846548Sbde * [.]mcount and __mcount may clobber the call-used registers and %ef. 8946548Sbde * [.]mexitcount may clobber %ecx and %ef. 9013107Sbde * 9118961Sbde * Cross-jumping makes non-statistical profiling timing more complicated. 9246548Sbde * It is handled in many cases by calling [.]mexitcount before jumping. It 9346548Sbde * is handled for conditional jumps using CROSSJUMP() and CROSSJUMP_LABEL(). 9418961Sbde * It is handled for some fault-handling jumps by not sharing the exit 9518961Sbde * routine. 9613107Sbde * 9713107Sbde * ALTENTRY() must be before a corresponding ENTRY() so that it can jump to 9813107Sbde * the main entry point. Note that alt entries are counted twice. They 9913107Sbde * have to be counted as ordinary entries for gprof to get the call times 10013107Sbde * right for the ordinary entries. 10113107Sbde * 10213107Sbde * High local labels are used in macros to avoid clashes with local labels 10313107Sbde * in functions. 10413107Sbde * 10518961Sbde * Ordinary `ret' is used instead of a macro `RET' because there are a lot 10618961Sbde * of `ret's. 0xc3 is the opcode for `ret' (`#define ret ... ret' can't 10718961Sbde * be used because this file is sometimes preprocessed in traditional mode). 10818961Sbde * `ret' clobbers eflags but this doesn't matter. 109757Sdg */ 11013107Sbde#define ALTENTRY(name) GEN_ENTRY(name) ; MCOUNT ; MEXITCOUNT ; jmp 9f 11118961Sbde#define CROSSJUMP(jtrue, label, jfalse) \ 11218961Sbde jfalse 8f; MEXITCOUNT; jmp __CONCAT(to,label); 8: 11318961Sbde#define CROSSJUMPTARGET(label) \ 11418961Sbde ALIGN_TEXT; __CONCAT(to,label): ; MCOUNT; jmp label 11513107Sbde#define ENTRY(name) GEN_ENTRY(name) ; 9: ; MCOUNT 116122940Speter#define FAKE_MCOUNT(caller) pushq caller ; call __mcount ; popq %rcx 11713107Sbde#define MCOUNT call __mcount 11813107Sbde#define MCOUNT_LABEL(name) GEN_ENTRY(name) ; nop ; ALIGN_TEXT 119163722Sbde#ifdef GUPROF 120163726Sbde#define MEXITCOUNT call .mexitcount 12118961Sbde#define ret MEXITCOUNT ; NON_GPROF_RET 122163722Sbde#else 123163722Sbde#define MEXITCOUNT 124163722Sbde#endif 12518961Sbde 12618961Sbde#else /* !GPROF */ 127757Sdg/* 128757Sdg * ALTENTRY() has to align because it is before a corresponding ENTRY(). 129757Sdg * ENTRY() has to align to because there may be no ALTENTRY() before it. 13013107Sbde * If there is a previous ALTENTRY() then the alignment code for ENTRY() 13113107Sbde * is empty. 132757Sdg */ 13313107Sbde#define ALTENTRY(name) GEN_ENTRY(name) 13418961Sbde#define CROSSJUMP(jtrue, label, jfalse) jtrue label 13518961Sbde#define CROSSJUMPTARGET(label) 13613107Sbde#define ENTRY(name) GEN_ENTRY(name) 13713107Sbde#define FAKE_MCOUNT(caller) 1381321Sdg#define MCOUNT 13913107Sbde#define MCOUNT_LABEL(name) 14013107Sbde#define MEXITCOUNT 14113107Sbde#endif /* GPROF */ 142757Sdg 143274489Sscottl/* 144274489Sscottl * Convenience for adding frame pointers to hand-coded ASM. Useful for 145274489Sscottl * DTrace, HWPMC, and KDB. 146274489Sscottl */ 147274489Sscottl#define PUSH_FRAME_POINTER \ 148274489Sscottl pushq %rbp ; \ 149274489Sscottl movq %rsp, %rbp ; 150274489Sscottl#define POP_FRAME_POINTER \ 151274489Sscottl popq %rbp 152274489Sscottl 153122849Speter#ifdef LOCORE 154122849Speter/* 155329462Skib * Access per-CPU data. 156329462Skib */ 157329462Skib#define PCPU(member) %gs:PC_ ## member 158329462Skib#define PCPU_ADDR(member, reg) \ 159329462Skib movq %gs:PC_PRVSPACE, reg ; \ 160329462Skib addq $PC_ ## member, reg 161329462Skib 162329462Skib/* 163156699Speter * Convenience macro for declaring interrupt entry points. 164122849Speter */ 165122849Speter#define IDTVEC(name) ALIGN_TEXT; .globl __CONCAT(X,name); \ 166122849Speter .type __CONCAT(X,name),@function; __CONCAT(X,name): 167122849Speter 168329462Skib .macro SAVE_SEGS 169329462Skib movw %fs,TF_FS(%rsp) 170329462Skib movw %gs,TF_GS(%rsp) 171329462Skib movw %es,TF_ES(%rsp) 172329462Skib movw %ds,TF_DS(%rsp) 173329462Skib .endm 174153241Sjhb 175329462Skib .macro MOVE_STACKS qw 176329462Skib .L.offset=0 177329462Skib .rept \qw 178329462Skib movq .L.offset(%rsp),%rdx 179329462Skib movq %rdx,.L.offset(%rax) 180329462Skib .L.offset=.L.offset+8 181329462Skib .endr 182329462Skib .endm 183153241Sjhb 184329462Skib .macro PTI_UUENTRY has_err 185329462Skib movq PCPU(KCR3),%rax 186329462Skib movq %rax,%cr3 187329462Skib movq PCPU(RSP0),%rax 188329462Skib subq $PTI_SIZE,%rax 189329462Skib MOVE_STACKS ((PTI_SIZE / 8) - 1 + \has_err) 190329462Skib movq %rax,%rsp 191329462Skib popq %rdx 192329462Skib popq %rax 193329462Skib .endm 194153241Sjhb 195329462Skib .macro PTI_UENTRY has_err 196329462Skib swapgs 197335570Skib cmpq $~0,PCPU(UCR3) 198335570Skib je 1f 199329462Skib pushq %rax 200329462Skib pushq %rdx 201329462Skib PTI_UUENTRY \has_err 202335570Skib1: 203329462Skib .endm 204329462Skib 205329462Skib .macro PTI_ENTRY name, cont, has_err=0 206329462Skib ALIGN_TEXT 207329462Skib .globl X\name\()_pti 208329462Skib .type X\name\()_pti,@function 209329462SkibX\name\()_pti: 210329462Skib /* %rax, %rdx and possibly err not yet pushed */ 211329462Skib testb $SEL_RPL_MASK,PTI_CS-(2+1-\has_err)*8(%rsp) 212329462Skib jz \cont 213329462Skib PTI_UENTRY \has_err 214329462Skib swapgs 215329462Skib jmp \cont 216329462Skib .endm 217329462Skib 218329462Skib .macro PTI_INTRENTRY vec_name 219329462Skib SUPERALIGN_TEXT 220329462Skib .globl X\vec_name\()_pti 221329462Skib .type X\vec_name\()_pti,@function 222329462SkibX\vec_name\()_pti: 223329462Skib testb $SEL_RPL_MASK,PTI_CS-3*8(%rsp) /* err, %rax, %rdx not pushed */ 224334330Sjhb jz .L\vec_name\()_u 225329462Skib PTI_UENTRY has_err=0 226334330Sjhb jmp .L\vec_name\()_u 227329462Skib .endm 228329462Skib 229329462Skib .macro INTR_PUSH_FRAME vec_name 230329462Skib SUPERALIGN_TEXT 231329462Skib .globl X\vec_name 232329462Skib .type X\vec_name,@function 233329462SkibX\vec_name: 234329462Skib testb $SEL_RPL_MASK,PTI_CS-3*8(%rsp) /* come from kernel? */ 235334330Sjhb jz .L\vec_name\()_u /* Yes, dont swapgs again */ 236329462Skib swapgs 237334330Sjhb.L\vec_name\()_u: 238329462Skib subq $TF_RIP,%rsp /* skip dummy tf_err and tf_trapno */ 239329462Skib movq %rdi,TF_RDI(%rsp) 240329462Skib movq %rsi,TF_RSI(%rsp) 241329462Skib movq %rdx,TF_RDX(%rsp) 242329462Skib movq %rcx,TF_RCX(%rsp) 243329462Skib movq %r8,TF_R8(%rsp) 244329462Skib movq %r9,TF_R9(%rsp) 245329462Skib movq %rax,TF_RAX(%rsp) 246329462Skib movq %rbx,TF_RBX(%rsp) 247329462Skib movq %rbp,TF_RBP(%rsp) 248329462Skib movq %r10,TF_R10(%rsp) 249329462Skib movq %r11,TF_R11(%rsp) 250329462Skib movq %r12,TF_R12(%rsp) 251329462Skib movq %r13,TF_R13(%rsp) 252329462Skib movq %r14,TF_R14(%rsp) 253329462Skib movq %r15,TF_R15(%rsp) 254329462Skib SAVE_SEGS 255329462Skib movl $TF_HASSEGS,TF_FLAGS(%rsp) 256329462Skib cld 257329462Skib testb $SEL_RPL_MASK,TF_CS(%rsp) /* come from kernel ? */ 258329462Skib jz 1f /* yes, leave PCB_FULL_IRET alone */ 259329462Skib movq PCPU(CURPCB),%r8 260329462Skib andl $~PCB_FULL_IRET,PCB_FLAGS(%r8) 261334327Skib call handle_ibrs_entry 262329462Skib1: 263329462Skib .endm 264329462Skib 265329462Skib .macro INTR_HANDLER vec_name 266329462Skib .text 267329462Skib PTI_INTRENTRY \vec_name 268329462Skib INTR_PUSH_FRAME \vec_name 269329462Skib .endm 270329462Skib 271329462Skib .macro RESTORE_REGS 272329462Skib movq TF_RDI(%rsp),%rdi 273329462Skib movq TF_RSI(%rsp),%rsi 274329462Skib movq TF_RDX(%rsp),%rdx 275329462Skib movq TF_RCX(%rsp),%rcx 276329462Skib movq TF_R8(%rsp),%r8 277329462Skib movq TF_R9(%rsp),%r9 278329462Skib movq TF_RAX(%rsp),%rax 279329462Skib movq TF_RBX(%rsp),%rbx 280329462Skib movq TF_RBP(%rsp),%rbp 281329462Skib movq TF_R10(%rsp),%r10 282329462Skib movq TF_R11(%rsp),%r11 283329462Skib movq TF_R12(%rsp),%r12 284329462Skib movq TF_R13(%rsp),%r13 285329462Skib movq TF_R14(%rsp),%r14 286329462Skib movq TF_R15(%rsp),%r15 287329462Skib .endm 288329462Skib 289122849Speter#endif /* LOCORE */ 290122849Speter 291263002Sroyger#ifdef __STDC__ 292263002Sroyger#define ELFNOTE(name, type, desctype, descdata...) \ 293263002Sroyger.pushsection .note.name ; \ 294263002Sroyger .align 4 ; \ 295263002Sroyger .long 2f - 1f /* namesz */ ; \ 296263002Sroyger .long 4f - 3f /* descsz */ ; \ 297263002Sroyger .long type ; \ 298263002Sroyger1:.asciz #name ; \ 299263002Sroyger2:.align 4 ; \ 300263002Sroyger3:desctype descdata ; \ 301263002Sroyger4:.align 4 ; \ 302263002Sroyger.popsection 303263002Sroyger#else /* !__STDC__, i.e. -traditional */ 304263002Sroyger#define ELFNOTE(name, type, desctype, descdata) \ 305263002Sroyger.pushsection .note.name ; \ 306263002Sroyger .align 4 ; \ 307263002Sroyger .long 2f - 1f /* namesz */ ; \ 308263002Sroyger .long 4f - 3f /* descsz */ ; \ 309263002Sroyger .long type ; \ 310263002Sroyger1:.asciz "name" ; \ 311263002Sroyger2:.align 4 ; \ 312263002Sroyger3:desctype descdata ; \ 313263002Sroyger4:.align 4 ; \ 314263002Sroyger.popsection 315263002Sroyger#endif /* __STDC__ */ 316263002Sroyger 3172579Sbde#endif /* !_MACHINE_ASMACROS_H_ */ 318