1412042e2SAndrew Turner /*- 2412042e2SAndrew Turner * Copyright (c) 2014 Andrew Turner 3412042e2SAndrew Turner * All rights reserved. 4412042e2SAndrew Turner * 5412042e2SAndrew Turner * Redistribution and use in source and binary forms, with or without 6412042e2SAndrew Turner * modification, are permitted provided that the following conditions 7412042e2SAndrew Turner * are met: 8412042e2SAndrew Turner * 1. Redistributions of source code must retain the above copyright 9412042e2SAndrew Turner * notice, this list of conditions and the following disclaimer. 10412042e2SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright 11412042e2SAndrew Turner * notice, this list of conditions and the following disclaimer in the 12412042e2SAndrew Turner * documentation and/or other materials provided with the distribution. 13412042e2SAndrew Turner * 14412042e2SAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15412042e2SAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16412042e2SAndrew Turner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17412042e2SAndrew Turner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18412042e2SAndrew Turner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19412042e2SAndrew Turner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20412042e2SAndrew Turner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21412042e2SAndrew Turner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22412042e2SAndrew Turner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23412042e2SAndrew Turner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24412042e2SAndrew Turner * SUCH DAMAGE. 25412042e2SAndrew Turner */ 26412042e2SAndrew Turner 27d5d97bedSMike Karels #ifdef __arm__ 28d5d97bedSMike Karels #include <arm/asm.h> 29d5d97bedSMike Karels #else /* !__arm__ */ 30d5d97bedSMike Karels 31412042e2SAndrew Turner #ifndef _MACHINE_ASM_H_ 32412042e2SAndrew Turner #define _MACHINE_ASM_H_ 33412042e2SAndrew Turner 34412042e2SAndrew Turner #undef __FBSDID 35412042e2SAndrew Turner #if !defined(lint) && !defined(STRIP_FBSDID) 36412042e2SAndrew Turner #define __FBSDID(s) .ident s 37412042e2SAndrew Turner #else 38412042e2SAndrew Turner #define __FBSDID(s) /* nothing */ 39412042e2SAndrew Turner #endif 40412042e2SAndrew Turner 41412042e2SAndrew Turner #define _C_LABEL(x) x 42412042e2SAndrew Turner 4328d94520SAndrew Turner #ifdef KDTRACE_HOOKS 4428d94520SAndrew Turner #define DTRACE_NOP nop 4528d94520SAndrew Turner #else 4628d94520SAndrew Turner #define DTRACE_NOP 4728d94520SAndrew Turner #endif 4828d94520SAndrew Turner 496f8866afSAndrew Turner #define LENTRY(sym) \ 506f8866afSAndrew Turner .text; .align 2; .type sym,#function; sym: \ 51e340882dSAndrew Turner .cfi_startproc; BTI_C; DTRACE_NOP 526f8866afSAndrew Turner #define ENTRY(sym) \ 536f8866afSAndrew Turner .globl sym; LENTRY(sym) 54412042e2SAndrew Turner #define EENTRY(sym) \ 5504b46559SAndrew Turner .globl sym; .text; .align 2; .type sym,#function; sym: 56449ebf13SAndrew Turner #define LEND(sym) .ltorg; .cfi_endproc; .size sym, . - sym 576f8866afSAndrew Turner #define END(sym) LEND(sym) 58412042e2SAndrew Turner #define EEND(sym) 59412042e2SAndrew Turner 60412042e2SAndrew Turner #define WEAK_REFERENCE(sym, alias) \ 61412042e2SAndrew Turner .weak alias; \ 62412042e2SAndrew Turner .set alias,sym 63412042e2SAndrew Turner 64412042e2SAndrew Turner #define UINT64_C(x) (x) 65412042e2SAndrew Turner 66412042e2SAndrew Turner #if defined(PIC) 67412042e2SAndrew Turner #define PIC_SYM(x,y) x ## @ ## y 68412042e2SAndrew Turner #else 69412042e2SAndrew Turner #define PIC_SYM(x,y) x 70412042e2SAndrew Turner #endif 71412042e2SAndrew Turner 728b609ea5SAlexander Kabaev /* Alias for link register x30 */ 738b609ea5SAlexander Kabaev #define lr x30 748b609ea5SAlexander Kabaev 75412042e2SAndrew Turner /* 76*05f6f65cSHarry Moulton * Check whether a given cpu feature is present, in the case it is not we jump 77*05f6f65cSHarry Moulton * to the given label. The tmp register should be a register able to hold the 78*05f6f65cSHarry Moulton * temporary data. 79*05f6f65cSHarry Moulton */ 80*05f6f65cSHarry Moulton #define CHECK_CPU_FEAT(tmp, feat_reg, feat, label) \ 81*05f6f65cSHarry Moulton mrs tmp, ##feat_reg##_el1; \ 82*05f6f65cSHarry Moulton ubfx tmp, tmp, ##feat_reg##_##feat##_SHIFT, ##feat_reg##_##feat##_WIDTH; \ 83*05f6f65cSHarry Moulton cbz tmp, label 84*05f6f65cSHarry Moulton 85*05f6f65cSHarry Moulton /* 86412042e2SAndrew Turner * Sets the trap fault handler. The exception handler will return to the 87412042e2SAndrew Turner * address in the handler register on a data abort or the xzr register to 88412042e2SAndrew Turner * clear the handler. The tmp parameter should be a register able to hold 89412042e2SAndrew Turner * the temporary data. 90412042e2SAndrew Turner */ 91412042e2SAndrew Turner #define SET_FAULT_HANDLER(handler, tmp) \ 92412042e2SAndrew Turner ldr tmp, [x18, #PC_CURTHREAD]; /* Load curthread */ \ 93412042e2SAndrew Turner ldr tmp, [tmp, #TD_PCB]; /* Load the pcb */ \ 94412042e2SAndrew Turner str handler, [tmp, #PCB_ONFAULT] /* Set the handler */ 95412042e2SAndrew Turner 96d6a0af23SAndrew Turner #define ENTER_USER_ACCESS(reg, tmp) \ 97d6a0af23SAndrew Turner ldr tmp, =has_pan; /* Get the addr of has_pan */ \ 98d6a0af23SAndrew Turner ldr reg, [tmp]; /* Read it */ \ 99d6a0af23SAndrew Turner cbz reg, 997f; /* If no PAN skip */ \ 100938e4b13SAndrew Turner .arch_extension pan; \ 101938e4b13SAndrew Turner msr pan, #0; /* Disable PAN checks */ \ 102938e4b13SAndrew Turner .arch_extension nopan; \ 103d6a0af23SAndrew Turner 997: 104d6a0af23SAndrew Turner 105d6a0af23SAndrew Turner #define EXIT_USER_ACCESS(reg) \ 106d6a0af23SAndrew Turner cbz reg, 998f; /* If no PAN skip */ \ 107938e4b13SAndrew Turner .arch_extension pan; \ 108938e4b13SAndrew Turner msr pan, #1; /* Enable PAN checks */ \ 109938e4b13SAndrew Turner .arch_extension nopan; \ 110d6a0af23SAndrew Turner 998: 111d6a0af23SAndrew Turner 112d6a0af23SAndrew Turner #define EXIT_USER_ACCESS_CHECK(reg, tmp) \ 113d6a0af23SAndrew Turner ldr tmp, =has_pan; /* Get the addr of has_pan */ \ 114d6a0af23SAndrew Turner ldr reg, [tmp]; /* Read it */ \ 115d6a0af23SAndrew Turner cbz reg, 999f; /* If no PAN skip */ \ 116938e4b13SAndrew Turner .arch_extension pan; \ 117938e4b13SAndrew Turner msr pan, #1; /* Enable PAN checks */ \ 118938e4b13SAndrew Turner .arch_extension nopan; \ 119d6a0af23SAndrew Turner 999: 120d6a0af23SAndrew Turner 121494278bbSAndrew Turner /* 122494278bbSAndrew Turner * Some AArch64 CPUs speculate past an eret instruction. As the user may 123494278bbSAndrew Turner * control the registers at this point add a speculation barrier usable on 124494278bbSAndrew Turner * all AArch64 CPUs after the eret instruction. 125494278bbSAndrew Turner * TODO: ARMv8.5 adds a specific instruction for this, we could use that 126494278bbSAndrew Turner * if we know we are running on something that supports it. 127494278bbSAndrew Turner */ 128494278bbSAndrew Turner #define ERET \ 129494278bbSAndrew Turner eret; \ 130494278bbSAndrew Turner dsb sy; \ 131494278bbSAndrew Turner isb 132494278bbSAndrew Turner 133e340882dSAndrew Turner /* 134e340882dSAndrew Turner * When a CPU that implements FEAT_BTI uses a BR/BLR instruction (or the 135e340882dSAndrew Turner * pointer authentication variants, e.g. BLRAA) and the target location 136e340882dSAndrew Turner * has the GP attribute in its page table, then the target of the BR/BLR 137e340882dSAndrew Turner * needs to be a valid BTI landing pad. 138e340882dSAndrew Turner * 139e340882dSAndrew Turner * BTI_C should be used at the start of a function and is used in the 140e340882dSAndrew Turner * ENTRY macro. It can be replaced by PACIASP or PACIBSP, however these 141e340882dSAndrew Turner * also need an appropriate authenticate instruction before returning. 142e340882dSAndrew Turner * 143e340882dSAndrew Turner * BTI_J should be used as the target instruction when branching with a 144e340882dSAndrew Turner * BR instruction within a function. 145e340882dSAndrew Turner * 146e340882dSAndrew Turner * When using a BR to branch to a new function, e.g. a tail call, then 147e340882dSAndrew Turner * the target register should be x16 or x17 so it is compatible with 148e340882dSAndrew Turner * the BRI_C instruction. 149e340882dSAndrew Turner * 150e340882dSAndrew Turner * As these instructions are in the hint space they are a NOP when 151e340882dSAndrew Turner * the CPU doesn't implement FEAT_BTI so are safe to use. 152e340882dSAndrew Turner */ 153e340882dSAndrew Turner #ifdef __ARM_FEATURE_BTI_DEFAULT 154e340882dSAndrew Turner #define BTI_C hint #34 155e340882dSAndrew Turner #define BTI_J hint #36 156e340882dSAndrew Turner #else 157e340882dSAndrew Turner #define BTI_C 158e340882dSAndrew Turner #define BTI_J 159e340882dSAndrew Turner #endif 160e340882dSAndrew Turner 16182597d21SAndrew Turner /* 1622b39a6f6SAndrew Turner * To help protect against ROP attacks we can use Pointer Authentication 1632b39a6f6SAndrew Turner * to sign the return address before pushing it to the stack. 1642b39a6f6SAndrew Turner * 1652b39a6f6SAndrew Turner * PAC_LR_SIGN can be used at the start of a function to sign the link 1662b39a6f6SAndrew Turner * register with the stack pointer as the modifier. As this is in the hint 1672b39a6f6SAndrew Turner * space it is safe to use on CPUs that don't implement pointer 1682b39a6f6SAndrew Turner * authentication. It can be used in place of the BTI_C instruction above as 1692b39a6f6SAndrew Turner * a valid BTI landing pad instruction. 1702b39a6f6SAndrew Turner * 1712b39a6f6SAndrew Turner * PAC_LR_AUTH is used to authenticate the link register using the stack 1722b39a6f6SAndrew Turner * pointer as the modifier. It should be used in any function that uses 1732b39a6f6SAndrew Turner * PAC_LR_SIGN. The stack pointer must be identical in each case. 1742b39a6f6SAndrew Turner */ 1752b39a6f6SAndrew Turner #ifdef __ARM_FEATURE_PAC_DEFAULT 1762b39a6f6SAndrew Turner #define PAC_LR_SIGN hint #25 /* paciasp */ 1772b39a6f6SAndrew Turner #define PAC_LR_AUTH hint #29 /* autiasp */ 1782b39a6f6SAndrew Turner #else 1792b39a6f6SAndrew Turner #define PAC_LR_SIGN 1802b39a6f6SAndrew Turner #define PAC_LR_AUTH 1812b39a6f6SAndrew Turner #endif 1822b39a6f6SAndrew Turner 1832b39a6f6SAndrew Turner /* 18482597d21SAndrew Turner * GNU_PROPERTY_AARCH64_FEATURE_1_NOTE can be used to insert a note that 18582597d21SAndrew Turner * the current assembly file is built with Pointer Authentication (PAC) or 18682597d21SAndrew Turner * Branch Target Identification support (BTI). As the linker requires all 18782597d21SAndrew Turner * object files in an executable or library to have the GNU property 18882597d21SAndrew Turner * note to emit it in the created elf file we need to add a note to all 18982597d21SAndrew Turner * assembly files that support BTI so the kernel and dynamic linker can 19082597d21SAndrew Turner * mark memory used by the file as guarded. 19182597d21SAndrew Turner * 19282597d21SAndrew Turner * The GNU_PROPERTY_AARCH64_FEATURE_1_VAL macro encodes the combination 19382597d21SAndrew Turner * of PAC and BTI that have been enabled. It can be used as follows: 19482597d21SAndrew Turner * GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL); 19582597d21SAndrew Turner * 19682597d21SAndrew Turner * To use this you need to include <sys/elf_common.h> for 19782597d21SAndrew Turner * GNU_PROPERTY_AARCH64_FEATURE_1_* 19882597d21SAndrew Turner */ 19982597d21SAndrew Turner #if defined(__ARM_FEATURE_BTI_DEFAULT) 20082597d21SAndrew Turner #if defined(__ARM_FEATURE_PAC_DEFAULT) 20182597d21SAndrew Turner /* BTI, PAC */ 20282597d21SAndrew Turner #define GNU_PROPERTY_AARCH64_FEATURE_1_VAL \ 20382597d21SAndrew Turner (GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC) 20482597d21SAndrew Turner #else 20582597d21SAndrew Turner /* BTI, no PAC */ 20682597d21SAndrew Turner #define GNU_PROPERTY_AARCH64_FEATURE_1_VAL \ 20782597d21SAndrew Turner (GNU_PROPERTY_AARCH64_FEATURE_1_BTI) 20882597d21SAndrew Turner #endif 20982597d21SAndrew Turner #elif defined(__ARM_FEATURE_PAC_DEFAULT) 21082597d21SAndrew Turner /* No BTI, PAC */ 21182597d21SAndrew Turner #define GNU_PROPERTY_AARCH64_FEATURE_1_VAL \ 21282597d21SAndrew Turner (GNU_PROPERTY_AARCH64_FEATURE_1_PAC) 21382597d21SAndrew Turner #else 21482597d21SAndrew Turner /* No BTI, no PAC */ 21582597d21SAndrew Turner #define GNU_PROPERTY_AARCH64_FEATURE_1_VAL 0 21682597d21SAndrew Turner #endif 21782597d21SAndrew Turner 21882597d21SAndrew Turner #if defined(__ARM_FEATURE_BTI_DEFAULT) || defined(__ARM_FEATURE_PAC_DEFAULT) 21982597d21SAndrew Turner #define GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(x) \ 22082597d21SAndrew Turner .section .note.gnu.property, "a"; \ 22182597d21SAndrew Turner .balign 8; \ 22282597d21SAndrew Turner .4byte 0x4; /* sizeof(vendor) */ \ 22382597d21SAndrew Turner .4byte 0x10; /* sizeof(note data) */ \ 22482597d21SAndrew Turner .4byte (NT_GNU_PROPERTY_TYPE_0); \ 22582597d21SAndrew Turner .asciz "GNU"; /* vendor */ \ 22682597d21SAndrew Turner /* note data: */ \ 22782597d21SAndrew Turner .4byte (GNU_PROPERTY_AARCH64_FEATURE_1_AND); \ 22882597d21SAndrew Turner .4byte 0x4; /* sizeof(property) */ \ 22982597d21SAndrew Turner .4byte (x); /* property */ \ 23082597d21SAndrew Turner .4byte 0 23182597d21SAndrew Turner #else 23282597d21SAndrew Turner #define GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(x) 23382597d21SAndrew Turner #endif 23482597d21SAndrew Turner 235412042e2SAndrew Turner #endif /* _MACHINE_ASM_H_ */ 236d5d97bedSMike Karels 237d5d97bedSMike Karels #endif /* !__arm__ */ 238