17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*f0089e39SRichard Lowe * Common Development and Distribution License (the "License"). 6*f0089e39SRichard Lowe * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*f0089e39SRichard Lowe 227c478bd9Sstevel@tonic-gate /* 23*f0089e39SRichard Lowe * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*f0089e39SRichard Lowe /* 28*f0089e39SRichard Lowe * Copyright 2019 Joyent, Inc. 29*f0089e39SRichard Lowe */ 30*f0089e39SRichard Lowe 317c478bd9Sstevel@tonic-gate #ifndef _SYS_ASM_LINKAGE_H 327c478bd9Sstevel@tonic-gate #define _SYS_ASM_LINKAGE_H 337c478bd9Sstevel@tonic-gate 34*f0089e39SRichard Lowe #include <sys/stack.h> 35*f0089e39SRichard Lowe #include <sys/trap.h> 36*f0089e39SRichard Lowe 37*f0089e39SRichard Lowe #ifdef __cplusplus 38*f0089e39SRichard Lowe extern "C" { 39*f0089e39SRichard Lowe #endif 40*f0089e39SRichard Lowe 41*f0089e39SRichard Lowe #ifdef _ASM /* The remainder of this file is only for assembly files */ 42*f0089e39SRichard Lowe 43*f0089e39SRichard Lowe /* 44*f0089e39SRichard Lowe * make annoying differences in assembler syntax go away 45*f0089e39SRichard Lowe */ 46*f0089e39SRichard Lowe 47*f0089e39SRichard Lowe /* 48*f0089e39SRichard Lowe * D16 and A16 are used to insert instructions prefixes; the 49*f0089e39SRichard Lowe * macros help the assembler code be slightly more portable. 50*f0089e39SRichard Lowe */ 51*f0089e39SRichard Lowe #if !defined(__GNUC_AS__) 52*f0089e39SRichard Lowe /* 53*f0089e39SRichard Lowe * /usr/ccs/bin/as prefixes are parsed as separate instructions 54*f0089e39SRichard Lowe */ 55*f0089e39SRichard Lowe #define D16 data16; 56*f0089e39SRichard Lowe #define A16 addr16; 57*f0089e39SRichard Lowe 58*f0089e39SRichard Lowe /* 59*f0089e39SRichard Lowe * (There are some weird constructs in constant expressions) 60*f0089e39SRichard Lowe */ 61*f0089e39SRichard Lowe #define _CONST(const) [const] 62*f0089e39SRichard Lowe #define _BITNOT(const) -1!_CONST(const) 63*f0089e39SRichard Lowe #define _MUL(a, b) _CONST(a \* b) 64*f0089e39SRichard Lowe 65*f0089e39SRichard Lowe #else 66*f0089e39SRichard Lowe /* 67*f0089e39SRichard Lowe * Why not use the 'data16' and 'addr16' prefixes .. well, the 68*f0089e39SRichard Lowe * assembler doesn't quite believe in real mode, and thus argues with 69*f0089e39SRichard Lowe * us about what we're trying to do. 70*f0089e39SRichard Lowe */ 71*f0089e39SRichard Lowe #define D16 .byte 0x66; 72*f0089e39SRichard Lowe #define A16 .byte 0x67; 73*f0089e39SRichard Lowe 74*f0089e39SRichard Lowe #define _CONST(const) (const) 75*f0089e39SRichard Lowe #define _BITNOT(const) ~_CONST(const) 76*f0089e39SRichard Lowe #define _MUL(a, b) _CONST(a * b) 77*f0089e39SRichard Lowe 78*f0089e39SRichard Lowe #endif 79*f0089e39SRichard Lowe 80*f0089e39SRichard Lowe /* 81*f0089e39SRichard Lowe * C pointers are different sizes between i386 and amd64. 82*f0089e39SRichard Lowe * These constants can be used to compute offsets into pointer arrays. 83*f0089e39SRichard Lowe */ 84*f0089e39SRichard Lowe #if defined(__amd64) 85*f0089e39SRichard Lowe #define CLONGSHIFT 3 86*f0089e39SRichard Lowe #define CLONGSIZE 8 87*f0089e39SRichard Lowe #define CLONGMASK 7 88*f0089e39SRichard Lowe #elif defined(__i386) 89*f0089e39SRichard Lowe #define CLONGSHIFT 2 90*f0089e39SRichard Lowe #define CLONGSIZE 4 91*f0089e39SRichard Lowe #define CLONGMASK 3 92*f0089e39SRichard Lowe #endif 93*f0089e39SRichard Lowe 94*f0089e39SRichard Lowe /* 95*f0089e39SRichard Lowe * Since we know we're either ILP32 or LP64 .. 96*f0089e39SRichard Lowe */ 97*f0089e39SRichard Lowe #define CPTRSHIFT CLONGSHIFT 98*f0089e39SRichard Lowe #define CPTRSIZE CLONGSIZE 99*f0089e39SRichard Lowe #define CPTRMASK CLONGMASK 100*f0089e39SRichard Lowe 101*f0089e39SRichard Lowe #if CPTRSIZE != (1 << CPTRSHIFT) || CLONGSIZE != (1 << CLONGSHIFT) 102*f0089e39SRichard Lowe #error "inconsistent shift constants" 103*f0089e39SRichard Lowe #endif 104*f0089e39SRichard Lowe 105*f0089e39SRichard Lowe #if CPTRMASK != (CPTRSIZE - 1) || CLONGMASK != (CLONGSIZE - 1) 106*f0089e39SRichard Lowe #error "inconsistent mask constants" 107*f0089e39SRichard Lowe #endif 108*f0089e39SRichard Lowe 109*f0089e39SRichard Lowe #define ASM_ENTRY_ALIGN 16 110*f0089e39SRichard Lowe 111*f0089e39SRichard Lowe /* 112*f0089e39SRichard Lowe * SSE register alignment and save areas 113*f0089e39SRichard Lowe */ 114*f0089e39SRichard Lowe 115*f0089e39SRichard Lowe #define XMM_SIZE 16 116*f0089e39SRichard Lowe #define XMM_ALIGN 16 117*f0089e39SRichard Lowe 118*f0089e39SRichard Lowe #if defined(__amd64) 119*f0089e39SRichard Lowe 120*f0089e39SRichard Lowe #define SAVE_XMM_PROLOG(sreg, nreg) \ 121*f0089e39SRichard Lowe subq $_CONST(_MUL(XMM_SIZE, nreg)), %rsp; \ 122*f0089e39SRichard Lowe movq %rsp, sreg 123*f0089e39SRichard Lowe 124*f0089e39SRichard Lowe #define RSTOR_XMM_EPILOG(sreg, nreg) \ 125*f0089e39SRichard Lowe addq $_CONST(_MUL(XMM_SIZE, nreg)), %rsp 126*f0089e39SRichard Lowe 127*f0089e39SRichard Lowe #elif defined(__i386) 128*f0089e39SRichard Lowe 129*f0089e39SRichard Lowe #define SAVE_XMM_PROLOG(sreg, nreg) \ 130*f0089e39SRichard Lowe subl $_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp; \ 131*f0089e39SRichard Lowe movl %esp, sreg; \ 132*f0089e39SRichard Lowe addl $XMM_ALIGN, sreg; \ 133*f0089e39SRichard Lowe andl $_BITNOT(XMM_ALIGN-1), sreg 134*f0089e39SRichard Lowe 135*f0089e39SRichard Lowe #define RSTOR_XMM_EPILOG(sreg, nreg) \ 136*f0089e39SRichard Lowe addl $_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp; 137*f0089e39SRichard Lowe 138*f0089e39SRichard Lowe #endif /* __i386 */ 139*f0089e39SRichard Lowe 140*f0089e39SRichard Lowe /* 141*f0089e39SRichard Lowe * profiling causes definitions of the MCOUNT and RTMCOUNT 142*f0089e39SRichard Lowe * particular to the type 143*f0089e39SRichard Lowe */ 144*f0089e39SRichard Lowe #ifdef GPROF 145*f0089e39SRichard Lowe 146*f0089e39SRichard Lowe #define MCOUNT(x) \ 147*f0089e39SRichard Lowe pushl %ebp; \ 148*f0089e39SRichard Lowe movl %esp, %ebp; \ 149*f0089e39SRichard Lowe call _mcount; \ 150*f0089e39SRichard Lowe popl %ebp 151*f0089e39SRichard Lowe 152*f0089e39SRichard Lowe #endif /* GPROF */ 153*f0089e39SRichard Lowe 154*f0089e39SRichard Lowe #ifdef PROF 155*f0089e39SRichard Lowe 156*f0089e39SRichard Lowe #define MCOUNT(x) \ 157*f0089e39SRichard Lowe /* CSTYLED */ \ 158*f0089e39SRichard Lowe .lcomm .L_/**/x/**/1, 4, 4; \ 159*f0089e39SRichard Lowe pushl %ebp; \ 160*f0089e39SRichard Lowe movl %esp, %ebp; \ 161*f0089e39SRichard Lowe /* CSTYLED */ \ 162*f0089e39SRichard Lowe movl $.L_/**/x/**/1, %edx; \ 163*f0089e39SRichard Lowe call _mcount; \ 164*f0089e39SRichard Lowe popl %ebp 165*f0089e39SRichard Lowe 166*f0089e39SRichard Lowe #endif /* PROF */ 167*f0089e39SRichard Lowe 168*f0089e39SRichard Lowe /* 169*f0089e39SRichard Lowe * if we are not profiling, MCOUNT should be defined to nothing 170*f0089e39SRichard Lowe */ 171*f0089e39SRichard Lowe #if !defined(PROF) && !defined(GPROF) 172*f0089e39SRichard Lowe #define MCOUNT(x) 173*f0089e39SRichard Lowe #endif /* !defined(PROF) && !defined(GPROF) */ 174*f0089e39SRichard Lowe 175*f0089e39SRichard Lowe #define RTMCOUNT(x) MCOUNT(x) 176*f0089e39SRichard Lowe 177*f0089e39SRichard Lowe /* 178*f0089e39SRichard Lowe * Macro to define weak symbol aliases. These are similar to the ANSI-C 179*f0089e39SRichard Lowe * #pragma weak _name = name 180*f0089e39SRichard Lowe * except a compiler can determine type. The assembler must be told. Hence, 181*f0089e39SRichard Lowe * the second parameter must be the type of the symbol (i.e.: function,...) 182*f0089e39SRichard Lowe */ 183*f0089e39SRichard Lowe #define ANSI_PRAGMA_WEAK(sym, stype) \ 184*f0089e39SRichard Lowe /* CSTYLED */ \ 185*f0089e39SRichard Lowe .weak _/**/sym; \ 186*f0089e39SRichard Lowe /* CSTYLED */ \ 187*f0089e39SRichard Lowe .type _/**/sym, @stype; \ 188*f0089e39SRichard Lowe /* CSTYLED */ \ 189*f0089e39SRichard Lowe _/**/sym = sym 190*f0089e39SRichard Lowe 191*f0089e39SRichard Lowe /* 192*f0089e39SRichard Lowe * Like ANSI_PRAGMA_WEAK(), but for unrelated names, as in: 193*f0089e39SRichard Lowe * #pragma weak sym1 = sym2 194*f0089e39SRichard Lowe */ 195*f0089e39SRichard Lowe #define ANSI_PRAGMA_WEAK2(sym1, sym2, stype) \ 196*f0089e39SRichard Lowe .weak sym1; \ 197*f0089e39SRichard Lowe .type sym1, @stype; \ 198*f0089e39SRichard Lowe sym1 = sym2 199*f0089e39SRichard Lowe 200*f0089e39SRichard Lowe /* 201*f0089e39SRichard Lowe * ENTRY provides the standard procedure entry code and an easy way to 202*f0089e39SRichard Lowe * insert the calls to mcount for profiling. ENTRY_NP is identical, but 203*f0089e39SRichard Lowe * never calls mcount. 204*f0089e39SRichard Lowe */ 205*f0089e39SRichard Lowe #define ENTRY(x) \ 206*f0089e39SRichard Lowe .text; \ 207*f0089e39SRichard Lowe .align ASM_ENTRY_ALIGN; \ 208*f0089e39SRichard Lowe .globl x; \ 209*f0089e39SRichard Lowe .type x, @function; \ 210*f0089e39SRichard Lowe x: MCOUNT(x) 211*f0089e39SRichard Lowe 212*f0089e39SRichard Lowe #define ENTRY_NP(x) \ 213*f0089e39SRichard Lowe .text; \ 214*f0089e39SRichard Lowe .align ASM_ENTRY_ALIGN; \ 215*f0089e39SRichard Lowe .globl x; \ 216*f0089e39SRichard Lowe .type x, @function; \ 217*f0089e39SRichard Lowe x: 218*f0089e39SRichard Lowe 219*f0089e39SRichard Lowe #define RTENTRY(x) \ 220*f0089e39SRichard Lowe .text; \ 221*f0089e39SRichard Lowe .align ASM_ENTRY_ALIGN; \ 222*f0089e39SRichard Lowe .globl x; \ 223*f0089e39SRichard Lowe .type x, @function; \ 224*f0089e39SRichard Lowe x: RTMCOUNT(x) 225*f0089e39SRichard Lowe 226*f0089e39SRichard Lowe /* 227*f0089e39SRichard Lowe * ENTRY2 is identical to ENTRY but provides two labels for the entry point. 228*f0089e39SRichard Lowe */ 229*f0089e39SRichard Lowe #define ENTRY2(x, y) \ 230*f0089e39SRichard Lowe .text; \ 231*f0089e39SRichard Lowe .align ASM_ENTRY_ALIGN; \ 232*f0089e39SRichard Lowe .globl x, y; \ 233*f0089e39SRichard Lowe .type x, @function; \ 234*f0089e39SRichard Lowe .type y, @function; \ 235*f0089e39SRichard Lowe /* CSTYLED */ \ 236*f0089e39SRichard Lowe x: ; \ 237*f0089e39SRichard Lowe y: MCOUNT(x) 238*f0089e39SRichard Lowe 239*f0089e39SRichard Lowe #define ENTRY_NP2(x, y) \ 240*f0089e39SRichard Lowe .text; \ 241*f0089e39SRichard Lowe .align ASM_ENTRY_ALIGN; \ 242*f0089e39SRichard Lowe .globl x, y; \ 243*f0089e39SRichard Lowe .type x, @function; \ 244*f0089e39SRichard Lowe .type y, @function; \ 245*f0089e39SRichard Lowe /* CSTYLED */ \ 246*f0089e39SRichard Lowe x: ; \ 247*f0089e39SRichard Lowe y: 248*f0089e39SRichard Lowe 249*f0089e39SRichard Lowe 250*f0089e39SRichard Lowe /* 251*f0089e39SRichard Lowe * ALTENTRY provides for additional entry points. 252*f0089e39SRichard Lowe */ 253*f0089e39SRichard Lowe #define ALTENTRY(x) \ 254*f0089e39SRichard Lowe .globl x; \ 255*f0089e39SRichard Lowe .type x, @function; \ 256*f0089e39SRichard Lowe x: 257*f0089e39SRichard Lowe 258*f0089e39SRichard Lowe /* 259*f0089e39SRichard Lowe * DGDEF and DGDEF2 provide global data declarations. 260*f0089e39SRichard Lowe * 261*f0089e39SRichard Lowe * DGDEF provides a word aligned word of storage. 262*f0089e39SRichard Lowe * 263*f0089e39SRichard Lowe * DGDEF2 allocates "sz" bytes of storage with **NO** alignment. This 264*f0089e39SRichard Lowe * implies this macro is best used for byte arrays. 265*f0089e39SRichard Lowe * 266*f0089e39SRichard Lowe * DGDEF3 allocates "sz" bytes of storage with "algn" alignment. 267*f0089e39SRichard Lowe */ 268*f0089e39SRichard Lowe #define DGDEF2(name, sz) \ 269*f0089e39SRichard Lowe .data; \ 270*f0089e39SRichard Lowe .globl name; \ 271*f0089e39SRichard Lowe .type name, @object; \ 272*f0089e39SRichard Lowe .size name, sz; \ 273*f0089e39SRichard Lowe name: 274*f0089e39SRichard Lowe 275*f0089e39SRichard Lowe #define DGDEF3(name, sz, algn) \ 276*f0089e39SRichard Lowe .data; \ 277*f0089e39SRichard Lowe .align algn; \ 278*f0089e39SRichard Lowe .globl name; \ 279*f0089e39SRichard Lowe .type name, @object; \ 280*f0089e39SRichard Lowe .size name, sz; \ 281*f0089e39SRichard Lowe name: 282*f0089e39SRichard Lowe 283*f0089e39SRichard Lowe #define DGDEF(name) DGDEF3(name, 4, 4) 284*f0089e39SRichard Lowe 285*f0089e39SRichard Lowe /* 286*f0089e39SRichard Lowe * SET_SIZE trails a function and set the size for the ELF symbol table. 287*f0089e39SRichard Lowe */ 288*f0089e39SRichard Lowe #define SET_SIZE(x) \ 289*f0089e39SRichard Lowe .size x, [.-x] 290*f0089e39SRichard Lowe 291*f0089e39SRichard Lowe /* 292*f0089e39SRichard Lowe * NWORD provides native word value. 293*f0089e39SRichard Lowe */ 294*f0089e39SRichard Lowe #if defined(__amd64) 295*f0089e39SRichard Lowe 296*f0089e39SRichard Lowe /*CSTYLED*/ 297*f0089e39SRichard Lowe #define NWORD quad 298*f0089e39SRichard Lowe 299*f0089e39SRichard Lowe #elif defined(__i386) 300*f0089e39SRichard Lowe 301*f0089e39SRichard Lowe #define NWORD long 302*f0089e39SRichard Lowe 303*f0089e39SRichard Lowe #endif /* __i386 */ 304*f0089e39SRichard Lowe 305*f0089e39SRichard Lowe /* 306*f0089e39SRichard Lowe * These macros should be used when making indirect calls in the kernel. They 307*f0089e39SRichard Lowe * will perform a jump or call to the corresponding register in a way that knows 308*f0089e39SRichard Lowe * about retpolines and handles whether such mitigations are enabled or not. 309*f0089e39SRichard Lowe * 310*f0089e39SRichard Lowe * INDIRECT_JMP_REG will jump to named register. INDIRECT_CALL_REG will instead 311*f0089e39SRichard Lowe * do a call. These macros cannot be used to dereference a register. For 312*f0089e39SRichard Lowe * example, if you need to do something that looks like the following: 313*f0089e39SRichard Lowe * 314*f0089e39SRichard Lowe * call *24(%rdi) 315*f0089e39SRichard Lowe * jmp *(%r15) 316*f0089e39SRichard Lowe * 317*f0089e39SRichard Lowe * You must instead first do a movq into the corresponding location. You need to 318*f0089e39SRichard Lowe * be careful to make sure that the register that its loaded into is safe to 319*f0089e39SRichard Lowe * use. Often that register may be saved or used elsewhere so it may not be safe 320*f0089e39SRichard Lowe * to clobber the value. Usually, loading into %rax would be safe. These would 321*f0089e39SRichard Lowe * turn into something like: 322*f0089e39SRichard Lowe * 323*f0089e39SRichard Lowe * movq 24(%rdi), %rdi; INDIRECT_CALL_REG(rdi) 324*f0089e39SRichard Lowe * movq (%r15), %r15; INDIRECT_JMP_REG(r15) 325*f0089e39SRichard Lowe * 326*f0089e39SRichard Lowe * If you are trying to call a global function, then use the following pattern 327*f0089e39SRichard Lowe * (substituting the register in question): 328*f0089e39SRichard Lowe * 329*f0089e39SRichard Lowe * leaq my_favorite_function(%rip), %rax 330*f0089e39SRichard Lowe * INDIRECT_CALL_REG(rax) 331*f0089e39SRichard Lowe * 332*f0089e39SRichard Lowe * If you instead have a function pointer (say gethrtimef for example), then you 333*f0089e39SRichard Lowe * need to do: 334*f0089e39SRichard Lowe * 335*f0089e39SRichard Lowe * movq my_favorite_function_pointer(%rip), %rax 336*f0089e39SRichard Lowe * INDIRECT_CALL_REG(rax) 337*f0089e39SRichard Lowe */ 338*f0089e39SRichard Lowe 339*f0089e39SRichard Lowe /* CSTYLED */ 340*f0089e39SRichard Lowe #define INDIRECT_JMP_REG(reg) jmp __x86_indirect_thunk_/**/reg; 3417c478bd9Sstevel@tonic-gate 342*f0089e39SRichard Lowe /* CSTYLED */ 343*f0089e39SRichard Lowe #define INDIRECT_CALL_REG(reg) call __x86_indirect_thunk_/**/reg; 3447c478bd9Sstevel@tonic-gate 345*f0089e39SRichard Lowe #endif /* _ASM */ 3467c478bd9Sstevel@tonic-gate 347*f0089e39SRichard Lowe #ifdef __cplusplus 348*f0089e39SRichard Lowe } 3497c478bd9Sstevel@tonic-gate #endif 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate #endif /* _SYS_ASM_LINKAGE_H */ 352