1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #ifndef _PKEYS_POWERPC_H 4 #define _PKEYS_POWERPC_H 5 6 #ifndef SYS_mprotect_key 7 # define SYS_mprotect_key 386 8 #endif 9 #ifndef SYS_pkey_alloc 10 # define SYS_pkey_alloc 384 11 # define SYS_pkey_free 385 12 #endif 13 #define REG_IP_IDX PT_NIP 14 #define REG_TRAPNO PT_TRAP 15 #define gregs gp_regs 16 #define fpregs fp_regs 17 #define si_pkey_offset 0x20 18 19 #undef PKEY_DISABLE_ACCESS 20 #define PKEY_DISABLE_ACCESS 0x3 /* disable read and write */ 21 22 #undef PKEY_DISABLE_WRITE 23 #define PKEY_DISABLE_WRITE 0x2 24 25 #define NR_PKEYS 32 26 #define NR_RESERVED_PKEYS_4K 27 /* pkey-0, pkey-1, exec-only-pkey 27 and 24 other keys that cannot be 28 represented in the PTE */ 29 #define NR_RESERVED_PKEYS_64K_3KEYS 3 /* PowerNV and KVM: pkey-0, 30 pkey-1 and exec-only key */ 31 #define NR_RESERVED_PKEYS_64K_4KEYS 4 /* PowerVM: pkey-0, pkey-1, 32 pkey-31 and exec-only key */ 33 #define PKEY_BITS_PER_PKEY 2 34 #define HPAGE_SIZE (1UL << 24) 35 #define PAGE_SIZE sysconf(_SC_PAGESIZE) 36 37 static inline u32 pkey_bit_position(int pkey) 38 { 39 return (NR_PKEYS - pkey - 1) * PKEY_BITS_PER_PKEY; 40 } 41 42 static inline u64 __read_pkey_reg(void) 43 { 44 u64 pkey_reg; 45 46 asm volatile("mfspr %0, 0xd" : "=r" (pkey_reg)); 47 48 return pkey_reg; 49 } 50 51 static inline void __write_pkey_reg(u64 pkey_reg) 52 { 53 u64 amr = pkey_reg; 54 55 dprintf4("%s() changing %016llx to %016llx\n", 56 __func__, __read_pkey_reg(), pkey_reg); 57 58 asm volatile("isync; mtspr 0xd, %0; isync" 59 : : "r" ((unsigned long)(amr)) : "memory"); 60 61 dprintf4("%s() pkey register after changing %016llx to %016llx\n", 62 __func__, __read_pkey_reg(), pkey_reg); 63 } 64 65 static inline int cpu_has_pkeys(void) 66 { 67 /* No simple way to determine this */ 68 return 1; 69 } 70 71 static inline bool arch_is_powervm() 72 { 73 struct stat buf; 74 75 if ((stat("/sys/firmware/devicetree/base/ibm,partition-name", &buf) == 0) && 76 (stat("/sys/firmware/devicetree/base/hmc-managed?", &buf) == 0) && 77 (stat("/sys/firmware/devicetree/base/chosen/qemu,graphic-width", &buf) == -1) ) 78 return true; 79 80 return false; 81 } 82 83 static inline int get_arch_reserved_keys(void) 84 { 85 if (sysconf(_SC_PAGESIZE) == 4096) 86 return NR_RESERVED_PKEYS_4K; 87 else 88 if (arch_is_powervm()) 89 return NR_RESERVED_PKEYS_64K_4KEYS; 90 else 91 return NR_RESERVED_PKEYS_64K_3KEYS; 92 } 93 94 void expect_fault_on_read_execonly_key(void *p1, int pkey) 95 { 96 /* 97 * powerpc does not allow userspace to change permissions of exec-only 98 * keys since those keys are not allocated by userspace. The signal 99 * handler wont be able to reset the permissions, which means the code 100 * will infinitely continue to segfault here. 101 */ 102 return; 103 } 104 105 /* 4-byte instructions * 16384 = 64K page */ 106 #define __page_o_noops() asm(".rept 16384 ; nop; .endr") 107 108 void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey) 109 { 110 void *ptr; 111 int ret; 112 113 dprintf1("doing %s(size=%ld, prot=0x%x, pkey=%d)\n", __func__, 114 size, prot, pkey); 115 pkey_assert(pkey < NR_PKEYS); 116 ptr = mmap(NULL, size, prot, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 117 pkey_assert(ptr != (void *)-1); 118 119 ret = syscall(__NR_subpage_prot, ptr, size, NULL); 120 if (ret) { 121 perror("subpage_perm"); 122 return PTR_ERR_ENOTSUP; 123 } 124 125 ret = mprotect_pkey((void *)ptr, PAGE_SIZE, prot, pkey); 126 pkey_assert(!ret); 127 record_pkey_malloc(ptr, size, prot); 128 129 dprintf1("%s() for pkey %d @ %p\n", __func__, pkey, ptr); 130 return ptr; 131 } 132 133 #endif /* _PKEYS_POWERPC_H */ 134