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