| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- /* SPDX-License-Identifier: GPL-2.0 */
- /*
- * Copyright (C) 2023 Arm Ltd.
- */
- #ifndef _PKEYS_ARM64_H
- #define _PKEYS_ARM64_H
- #include "vm_util.h"
- /* for signal frame parsing */
- #include "../arm64/signal/testcases/testcases.h"
- #ifndef SYS_mprotect_key
- # define SYS_mprotect_key 288
- #endif
- #ifndef SYS_pkey_alloc
- # define SYS_pkey_alloc 289
- # define SYS_pkey_free 290
- #endif
- #define MCONTEXT_IP(mc) mc.pc
- #define MCONTEXT_TRAPNO(mc) -1
- #define PKEY_MASK 0xf
- #define POE_NONE 0x0
- #define POE_X 0x2
- #define POE_RX 0x3
- #define POE_RWX 0x7
- #define NR_PKEYS 8
- #define NR_RESERVED_PKEYS 1 /* pkey-0 */
- #define PKEY_ALLOW_ALL 0x77777777
- #define PKEY_BITS_PER_PKEY 4
- #define PAGE_SIZE sysconf(_SC_PAGESIZE)
- #undef HPAGE_SIZE
- #define HPAGE_SIZE default_huge_page_size()
- /* 4-byte instructions * 16384 = 64K page */
- #define __page_o_noops() asm(".rept 16384 ; nop; .endr")
- static inline u64 __read_pkey_reg(void)
- {
- u64 pkey_reg = 0;
- // POR_EL0
- asm volatile("mrs %0, S3_3_c10_c2_4" : "=r" (pkey_reg));
- return pkey_reg;
- }
- static inline void __write_pkey_reg(u64 pkey_reg)
- {
- u64 por = pkey_reg;
- dprintf4("%s() changing %016llx to %016llx\n",
- __func__, __read_pkey_reg(), pkey_reg);
- // POR_EL0
- asm volatile("msr S3_3_c10_c2_4, %0\nisb" :: "r" (por) :);
- dprintf4("%s() pkey register after changing %016llx to %016llx\n",
- __func__, __read_pkey_reg(), pkey_reg);
- }
- static inline int cpu_has_pkeys(void)
- {
- /* No simple way to determine this */
- return 1;
- }
- static inline u32 pkey_bit_position(int pkey)
- {
- return pkey * PKEY_BITS_PER_PKEY;
- }
- static inline int get_arch_reserved_keys(void)
- {
- return NR_RESERVED_PKEYS;
- }
- void expect_fault_on_read_execonly_key(void *p1, int pkey)
- {
- }
- void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey)
- {
- return PTR_ERR_ENOTSUP;
- }
- #define set_pkey_bits set_pkey_bits
- static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
- {
- u32 shift = pkey_bit_position(pkey);
- u64 new_val = POE_RWX;
- /* mask out bits from pkey in old value */
- reg &= ~((u64)PKEY_MASK << shift);
- if (flags & PKEY_DISABLE_ACCESS)
- new_val = POE_X;
- else if (flags & PKEY_DISABLE_WRITE)
- new_val = POE_RX;
- /* OR in new bits for pkey */
- reg |= new_val << shift;
- return reg;
- }
- #define get_pkey_bits get_pkey_bits
- static inline u64 get_pkey_bits(u64 reg, int pkey)
- {
- u32 shift = pkey_bit_position(pkey);
- /*
- * shift down the relevant bits to the lowest four, then
- * mask off all the other higher bits
- */
- u32 perm = (reg >> shift) & PKEY_MASK;
- if (perm == POE_X)
- return PKEY_DISABLE_ACCESS;
- if (perm == POE_RX)
- return PKEY_DISABLE_WRITE;
- return 0;
- }
- static void aarch64_write_signal_pkey(ucontext_t *uctxt, u64 pkey)
- {
- struct _aarch64_ctx *ctx = GET_UC_RESV_HEAD(uctxt);
- struct poe_context *poe_ctx =
- (struct poe_context *) get_header(ctx, POE_MAGIC,
- sizeof(uctxt->uc_mcontext), NULL);
- if (poe_ctx)
- poe_ctx->por_el0 = pkey;
- }
- #endif /* _PKEYS_ARM64_H */
|