pkey-powerpc.h (3364B)
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 37static inline u32 pkey_bit_position(int pkey) 38{ 39 return (NR_PKEYS - pkey - 1) * PKEY_BITS_PER_PKEY; 40} 41 42static 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 51static 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 65static inline int cpu_has_pkeys(void) 66{ 67 /* No simple way to determine this */ 68 return 1; 69} 70 71static 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 83static 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 94void 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 108void *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 */