1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 2 /* 3 * Copyright (C) 2023 Arm Ltd. 3 * Copyright (C) 2023 Arm Ltd. 4 */ 4 */ 5 5 6 #ifndef _PKEYS_ARM64_H 6 #ifndef _PKEYS_ARM64_H 7 #define _PKEYS_ARM64_H 7 #define _PKEYS_ARM64_H 8 8 9 #include "vm_util.h" 9 #include "vm_util.h" 10 /* for signal frame parsing */ 10 /* for signal frame parsing */ 11 #include "../arm64/signal/testcases/testcases. 11 #include "../arm64/signal/testcases/testcases.h" 12 12 13 #ifndef SYS_mprotect_key 13 #ifndef SYS_mprotect_key 14 # define SYS_mprotect_key 288 14 # define SYS_mprotect_key 288 15 #endif 15 #endif 16 #ifndef SYS_pkey_alloc 16 #ifndef SYS_pkey_alloc 17 # define SYS_pkey_alloc 289 17 # define SYS_pkey_alloc 289 18 # define SYS_pkey_free 290 18 # define SYS_pkey_free 290 19 #endif 19 #endif 20 #define MCONTEXT_IP(mc) mc.pc 20 #define MCONTEXT_IP(mc) mc.pc 21 #define MCONTEXT_TRAPNO(mc) -1 21 #define MCONTEXT_TRAPNO(mc) -1 22 22 23 #define PKEY_MASK 0xf 23 #define PKEY_MASK 0xf 24 24 25 #define POE_NONE 0x0 25 #define POE_NONE 0x0 26 #define POE_X 0x2 26 #define POE_X 0x2 27 #define POE_RX 0x3 27 #define POE_RX 0x3 28 #define POE_RWX 0x7 28 #define POE_RWX 0x7 29 29 30 #define NR_PKEYS 8 30 #define NR_PKEYS 8 31 #define NR_RESERVED_PKEYS 1 /* pkey-0 */ 31 #define NR_RESERVED_PKEYS 1 /* pkey-0 */ 32 32 33 #define PKEY_ALLOW_ALL 0x77777777 33 #define PKEY_ALLOW_ALL 0x77777777 34 34 35 #define PKEY_BITS_PER_PKEY 4 35 #define PKEY_BITS_PER_PKEY 4 36 #define PAGE_SIZE sysconf(_SC_PA 36 #define PAGE_SIZE sysconf(_SC_PAGESIZE) 37 #undef HPAGE_SIZE 37 #undef HPAGE_SIZE 38 #define HPAGE_SIZE default_huge_p 38 #define HPAGE_SIZE default_huge_page_size() 39 39 40 /* 4-byte instructions * 16384 = 64K page */ 40 /* 4-byte instructions * 16384 = 64K page */ 41 #define __page_o_noops() asm(".rept 16384 ; no 41 #define __page_o_noops() asm(".rept 16384 ; nop; .endr") 42 42 43 static inline u64 __read_pkey_reg(void) 43 static inline u64 __read_pkey_reg(void) 44 { 44 { 45 u64 pkey_reg = 0; 45 u64 pkey_reg = 0; 46 46 47 // POR_EL0 47 // POR_EL0 48 asm volatile("mrs %0, S3_3_c10_c2_4" : 48 asm volatile("mrs %0, S3_3_c10_c2_4" : "=r" (pkey_reg)); 49 49 50 return pkey_reg; 50 return pkey_reg; 51 } 51 } 52 52 53 static inline void __write_pkey_reg(u64 pkey_r 53 static inline void __write_pkey_reg(u64 pkey_reg) 54 { 54 { 55 u64 por = pkey_reg; 55 u64 por = pkey_reg; 56 56 57 dprintf4("%s() changing %016llx to %01 57 dprintf4("%s() changing %016llx to %016llx\n", 58 __func__, __read_pkey 58 __func__, __read_pkey_reg(), pkey_reg); 59 59 60 // POR_EL0 60 // POR_EL0 61 asm volatile("msr S3_3_c10_c2_4, %0\ni 61 asm volatile("msr S3_3_c10_c2_4, %0\nisb" :: "r" (por) :); 62 62 63 dprintf4("%s() pkey register after cha 63 dprintf4("%s() pkey register after changing %016llx to %016llx\n", 64 __func__, __read_pkey_ 64 __func__, __read_pkey_reg(), pkey_reg); 65 } 65 } 66 66 67 static inline int cpu_has_pkeys(void) 67 static inline int cpu_has_pkeys(void) 68 { 68 { 69 /* No simple way to determine this */ 69 /* No simple way to determine this */ 70 return 1; 70 return 1; 71 } 71 } 72 72 73 static inline u32 pkey_bit_position(int pkey) 73 static inline u32 pkey_bit_position(int pkey) 74 { 74 { 75 return pkey * PKEY_BITS_PER_PKEY; 75 return pkey * PKEY_BITS_PER_PKEY; 76 } 76 } 77 77 78 static inline int get_arch_reserved_keys(void) 78 static inline int get_arch_reserved_keys(void) 79 { 79 { 80 return NR_RESERVED_PKEYS; 80 return NR_RESERVED_PKEYS; 81 } 81 } 82 82 83 void expect_fault_on_read_execonly_key(void *p 83 void expect_fault_on_read_execonly_key(void *p1, int pkey) 84 { 84 { 85 } 85 } 86 86 87 void *malloc_pkey_with_mprotect_subpage(long s 87 void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey) 88 { 88 { 89 return PTR_ERR_ENOTSUP; 89 return PTR_ERR_ENOTSUP; 90 } 90 } 91 91 92 #define set_pkey_bits set_pkey_bits 92 #define set_pkey_bits set_pkey_bits 93 static inline u64 set_pkey_bits(u64 reg, int p 93 static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags) 94 { 94 { 95 u32 shift = pkey_bit_position(pkey); 95 u32 shift = pkey_bit_position(pkey); 96 u64 new_val = POE_RWX; 96 u64 new_val = POE_RWX; 97 97 98 /* mask out bits from pkey in old valu 98 /* mask out bits from pkey in old value */ 99 reg &= ~((u64)PKEY_MASK << shift); 99 reg &= ~((u64)PKEY_MASK << shift); 100 100 101 if (flags & PKEY_DISABLE_ACCESS) 101 if (flags & PKEY_DISABLE_ACCESS) 102 new_val = POE_X; 102 new_val = POE_X; 103 else if (flags & PKEY_DISABLE_WRITE) 103 else if (flags & PKEY_DISABLE_WRITE) 104 new_val = POE_RX; 104 new_val = POE_RX; 105 105 106 /* OR in new bits for pkey */ 106 /* OR in new bits for pkey */ 107 reg |= new_val << shift; 107 reg |= new_val << shift; 108 108 109 return reg; 109 return reg; 110 } 110 } 111 111 112 #define get_pkey_bits get_pkey_bits 112 #define get_pkey_bits get_pkey_bits 113 static inline u64 get_pkey_bits(u64 reg, int p 113 static inline u64 get_pkey_bits(u64 reg, int pkey) 114 { 114 { 115 u32 shift = pkey_bit_position(pkey); 115 u32 shift = pkey_bit_position(pkey); 116 /* 116 /* 117 * shift down the relevant bits to the 117 * shift down the relevant bits to the lowest four, then 118 * mask off all the other higher bits 118 * mask off all the other higher bits 119 */ 119 */ 120 u32 perm = (reg >> shift) & PKEY_MASK; 120 u32 perm = (reg >> shift) & PKEY_MASK; 121 121 122 if (perm == POE_X) 122 if (perm == POE_X) 123 return PKEY_DISABLE_ACCESS; 123 return PKEY_DISABLE_ACCESS; 124 if (perm == POE_RX) 124 if (perm == POE_RX) 125 return PKEY_DISABLE_WRITE; 125 return PKEY_DISABLE_WRITE; 126 return 0; 126 return 0; 127 } 127 } 128 128 129 static void aarch64_write_signal_pkey(ucontext 129 static void aarch64_write_signal_pkey(ucontext_t *uctxt, u64 pkey) 130 { 130 { 131 struct _aarch64_ctx *ctx = GET_UC_RESV 131 struct _aarch64_ctx *ctx = GET_UC_RESV_HEAD(uctxt); 132 struct poe_context *poe_ctx = 132 struct poe_context *poe_ctx = 133 (struct poe_context *) get_hea 133 (struct poe_context *) get_header(ctx, POE_MAGIC, 134 134 sizeof(uctxt->uc_mcontext), NULL); 135 if (poe_ctx) 135 if (poe_ctx) 136 poe_ctx->por_el0 = pkey; 136 poe_ctx->por_el0 = pkey; 137 } 137 } 138 138 139 #endif /* _PKEYS_ARM64_H */ 139 #endif /* _PKEYS_ARM64_H */ 140 140
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.