pkey-arm64.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2023 Arm Ltd.
  4. */
  5. #ifndef _PKEYS_ARM64_H
  6. #define _PKEYS_ARM64_H
  7. #include "vm_util.h"
  8. /* for signal frame parsing */
  9. #include "../arm64/signal/testcases/testcases.h"
  10. #ifndef SYS_mprotect_key
  11. # define SYS_mprotect_key 288
  12. #endif
  13. #ifndef SYS_pkey_alloc
  14. # define SYS_pkey_alloc 289
  15. # define SYS_pkey_free 290
  16. #endif
  17. #define MCONTEXT_IP(mc) mc.pc
  18. #define MCONTEXT_TRAPNO(mc) -1
  19. #define PKEY_MASK 0xf
  20. #define POE_NONE 0x0
  21. #define POE_X 0x2
  22. #define POE_RX 0x3
  23. #define POE_RWX 0x7
  24. #define NR_PKEYS 8
  25. #define NR_RESERVED_PKEYS 1 /* pkey-0 */
  26. #define PKEY_ALLOW_ALL 0x77777777
  27. #define PKEY_BITS_PER_PKEY 4
  28. #define PAGE_SIZE sysconf(_SC_PAGESIZE)
  29. #undef HPAGE_SIZE
  30. #define HPAGE_SIZE default_huge_page_size()
  31. /* 4-byte instructions * 16384 = 64K page */
  32. #define __page_o_noops() asm(".rept 16384 ; nop; .endr")
  33. static inline u64 __read_pkey_reg(void)
  34. {
  35. u64 pkey_reg = 0;
  36. // POR_EL0
  37. asm volatile("mrs %0, S3_3_c10_c2_4" : "=r" (pkey_reg));
  38. return pkey_reg;
  39. }
  40. static inline void __write_pkey_reg(u64 pkey_reg)
  41. {
  42. u64 por = pkey_reg;
  43. dprintf4("%s() changing %016llx to %016llx\n",
  44. __func__, __read_pkey_reg(), pkey_reg);
  45. // POR_EL0
  46. asm volatile("msr S3_3_c10_c2_4, %0\nisb" :: "r" (por) :);
  47. dprintf4("%s() pkey register after changing %016llx to %016llx\n",
  48. __func__, __read_pkey_reg(), pkey_reg);
  49. }
  50. static inline int cpu_has_pkeys(void)
  51. {
  52. /* No simple way to determine this */
  53. return 1;
  54. }
  55. static inline u32 pkey_bit_position(int pkey)
  56. {
  57. return pkey * PKEY_BITS_PER_PKEY;
  58. }
  59. static inline int get_arch_reserved_keys(void)
  60. {
  61. return NR_RESERVED_PKEYS;
  62. }
  63. void expect_fault_on_read_execonly_key(void *p1, int pkey)
  64. {
  65. }
  66. void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey)
  67. {
  68. return PTR_ERR_ENOTSUP;
  69. }
  70. #define set_pkey_bits set_pkey_bits
  71. static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
  72. {
  73. u32 shift = pkey_bit_position(pkey);
  74. u64 new_val = POE_RWX;
  75. /* mask out bits from pkey in old value */
  76. reg &= ~((u64)PKEY_MASK << shift);
  77. if (flags & PKEY_DISABLE_ACCESS)
  78. new_val = POE_X;
  79. else if (flags & PKEY_DISABLE_WRITE)
  80. new_val = POE_RX;
  81. /* OR in new bits for pkey */
  82. reg |= new_val << shift;
  83. return reg;
  84. }
  85. #define get_pkey_bits get_pkey_bits
  86. static inline u64 get_pkey_bits(u64 reg, int pkey)
  87. {
  88. u32 shift = pkey_bit_position(pkey);
  89. /*
  90. * shift down the relevant bits to the lowest four, then
  91. * mask off all the other higher bits
  92. */
  93. u32 perm = (reg >> shift) & PKEY_MASK;
  94. if (perm == POE_X)
  95. return PKEY_DISABLE_ACCESS;
  96. if (perm == POE_RX)
  97. return PKEY_DISABLE_WRITE;
  98. return 0;
  99. }
  100. static void aarch64_write_signal_pkey(ucontext_t *uctxt, u64 pkey)
  101. {
  102. struct _aarch64_ctx *ctx = GET_UC_RESV_HEAD(uctxt);
  103. struct poe_context *poe_ctx =
  104. (struct poe_context *) get_header(ctx, POE_MAGIC,
  105. sizeof(uctxt->uc_mcontext), NULL);
  106. if (poe_ctx)
  107. poe_ctx->por_el0 = pkey;
  108. }
  109. #endif /* _PKEYS_ARM64_H */