brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · 580e1b0 Raw
140 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * Copyright (C) 2023 Arm Ltd.4 */5 6#ifndef _PKEYS_ARM64_H7#define _PKEYS_ARM64_H8 9#include "vm_util.h"10/* for signal frame parsing */11#include "../arm64/signal/testcases/testcases.h"12 13#ifndef SYS_mprotect_key14# define SYS_mprotect_key	28815#endif16#ifndef SYS_pkey_alloc17# define SYS_pkey_alloc		28918# define SYS_pkey_free		29019#endif20#define MCONTEXT_IP(mc)		mc.pc21#define MCONTEXT_TRAPNO(mc)	-122 23#define PKEY_MASK		0xf24 25#define POE_NONE		0x026#define POE_X			0x227#define POE_RX			0x328#define POE_RWX			0x729 30#define NR_PKEYS		831#define NR_RESERVED_PKEYS	1 /* pkey-0 */32 33#define PKEY_ALLOW_ALL		0x7777777734 35#define PKEY_BITS_PER_PKEY	436#define PAGE_SIZE		sysconf(_SC_PAGESIZE)37#undef HPAGE_SIZE38#define HPAGE_SIZE		default_huge_page_size()39 40/* 4-byte instructions * 16384 = 64K page */41#define __page_o_noops() asm(".rept 16384 ; nop; .endr")42 43static inline u64 __read_pkey_reg(void)44{45	u64 pkey_reg = 0;46 47	// POR_EL048	asm volatile("mrs %0, S3_3_c10_c2_4" : "=r" (pkey_reg));49 50	return pkey_reg;51}52 53static inline void __write_pkey_reg(u64 pkey_reg)54{55	u64 por = pkey_reg;56 57	dprintf4("%s() changing %016llx to %016llx\n",58			 __func__, __read_pkey_reg(), pkey_reg);59 60	// POR_EL061	asm volatile("msr S3_3_c10_c2_4, %0\nisb" :: "r" (por) :);62 63	dprintf4("%s() pkey register after changing %016llx to %016llx\n",64			__func__, __read_pkey_reg(), pkey_reg);65}66 67static inline int cpu_has_pkeys(void)68{69	/* No simple way to determine this */70	return 1;71}72 73static inline u32 pkey_bit_position(int pkey)74{75	return pkey * PKEY_BITS_PER_PKEY;76}77 78static inline int get_arch_reserved_keys(void)79{80	return NR_RESERVED_PKEYS;81}82 83void expect_fault_on_read_execonly_key(void *p1, int pkey)84{85}86 87void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey)88{89	return PTR_ERR_ENOTSUP;90}91 92#define set_pkey_bits	set_pkey_bits93static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)94{95	u32 shift = pkey_bit_position(pkey);96	u64 new_val = POE_RWX;97 98	/* mask out bits from pkey in old value */99	reg &= ~((u64)PKEY_MASK << shift);100 101	if (flags & PKEY_DISABLE_ACCESS)102		new_val = POE_X;103	else if (flags & PKEY_DISABLE_WRITE)104		new_val = POE_RX;105 106	/* OR in new bits for pkey */107	reg |= new_val << shift;108 109	return reg;110}111 112#define get_pkey_bits	get_pkey_bits113static inline u64 get_pkey_bits(u64 reg, int pkey)114{115	u32 shift = pkey_bit_position(pkey);116	/*117	 * shift down the relevant bits to the lowest four, then118	 * mask off all the other higher bits119	 */120	u32 perm = (reg >> shift) & PKEY_MASK;121 122	if (perm == POE_X)123		return PKEY_DISABLE_ACCESS;124	if (perm == POE_RX)125		return PKEY_DISABLE_WRITE;126	return 0;127}128 129static void aarch64_write_signal_pkey(ucontext_t *uctxt, u64 pkey)130{131	struct _aarch64_ctx *ctx = GET_UC_RESV_HEAD(uctxt);132	struct poe_context *poe_ctx =133		(struct poe_context *) get_header(ctx, POE_MAGIC,134						sizeof(uctxt->uc_mcontext), NULL);135	if (poe_ctx)136		poe_ctx->por_el0 = pkey;137}138 139#endif /* _PKEYS_ARM64_H */140