|
| 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 | +#ifndef PKEY_DISABLE_ACCESS |
| 20 | +# define PKEY_DISABLE_ACCESS 0x3 /* disable read and write */ |
| 21 | +#endif |
| 22 | + |
| 23 | +#ifndef PKEY_DISABLE_WRITE |
| 24 | +# define PKEY_DISABLE_WRITE 0x2 |
| 25 | +#endif |
| 26 | + |
| 27 | +#define NR_PKEYS 32 |
| 28 | +#define NR_RESERVED_PKEYS_4K 27 /* pkey-0, pkey-1, exec-only-pkey |
| 29 | + and 24 other keys that cannot be |
| 30 | + represented in the PTE */ |
| 31 | +#define NR_RESERVED_PKEYS_64K 3 /* pkey-0, pkey-1 and exec-only-pkey */ |
| 32 | +#define PKEY_BITS_PER_PKEY 2 |
| 33 | +#define HPAGE_SIZE (1UL << 24) |
| 34 | +#define PAGE_SIZE (1UL << 16) |
| 35 | + |
| 36 | +static inline u32 pkey_bit_position(int pkey) |
| 37 | +{ |
| 38 | + return (NR_PKEYS - pkey - 1) * PKEY_BITS_PER_PKEY; |
| 39 | +} |
| 40 | + |
| 41 | +static inline u64 __read_pkey_reg(void) |
| 42 | +{ |
| 43 | + u64 pkey_reg; |
| 44 | + |
| 45 | + asm volatile("mfspr %0, 0xd" : "=r" (pkey_reg)); |
| 46 | + |
| 47 | + return pkey_reg; |
| 48 | +} |
| 49 | + |
| 50 | +static inline void __write_pkey_reg(u64 pkey_reg) |
| 51 | +{ |
| 52 | + u64 amr = pkey_reg; |
| 53 | + |
| 54 | + dprintf4("%s() changing %016llx to %016llx\n", |
| 55 | + __func__, __read_pkey_reg(), pkey_reg); |
| 56 | + |
| 57 | + asm volatile("isync; mtspr 0xd, %0; isync" |
| 58 | + : : "r" ((unsigned long)(amr)) : "memory"); |
| 59 | + |
| 60 | + dprintf4("%s() pkey register after changing %016llx to %016llx\n", |
| 61 | + __func__, __read_pkey_reg(), pkey_reg); |
| 62 | +} |
| 63 | + |
| 64 | +static inline int cpu_has_pku(void) |
| 65 | +{ |
| 66 | + return 1; |
| 67 | +} |
| 68 | + |
| 69 | +static inline int get_arch_reserved_keys(void) |
| 70 | +{ |
| 71 | + if (sysconf(_SC_PAGESIZE) == 4096) |
| 72 | + return NR_RESERVED_PKEYS_4K; |
| 73 | + else |
| 74 | + return NR_RESERVED_PKEYS_64K; |
| 75 | +} |
| 76 | + |
| 77 | +void expect_fault_on_read_execonly_key(void *p1, int pkey) |
| 78 | +{ |
| 79 | + /* |
| 80 | + * powerpc does not allow userspace to change permissions of exec-only |
| 81 | + * keys since those keys are not allocated by userspace. The signal |
| 82 | + * handler wont be able to reset the permissions, which means the code |
| 83 | + * will infinitely continue to segfault here. |
| 84 | + */ |
| 85 | + return; |
| 86 | +} |
| 87 | + |
| 88 | +/* 4-byte instructions * 16384 = 64K page */ |
| 89 | +#define __page_o_noops() asm(".rept 16384 ; nop; .endr") |
| 90 | + |
| 91 | +#endif /* _PKEYS_POWERPC_H */ |
0 commit comments