Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _PKEYS_X86_H #define _PKEYS_X86_H #ifdef __i386__ #define REG_IP_IDX REG_EIP #define si_pkey_offset 0x14 #else #define REG_IP_IDX REG_RIP #define si_pkey_offset 0x20 #endif #ifndef PKEY_DISABLE_ACCESS # define PKEY_DISABLE_ACCESS 0x1 #endif #ifndef PKEY_DISABLE_WRITE # define PKEY_DISABLE_WRITE 0x2 #endif #define NR_PKEYS 16 #define NR_RESERVED_PKEYS 2 /* pkey-0 and exec-only-pkey */ #define PKEY_BITS_PER_PKEY 2 #define HPAGE_SIZE (1UL<<21) #define PAGE_SIZE 4096 #define MB (1<<20) static inline void __page_o_noops(void) { /* 8-bytes of instruction * 512 bytes = 1 page */ asm(".rept 512 ; nopl 0x7eeeeeee(%eax) ; .endr"); } static inline u64 __read_pkey_reg(void) { unsigned int eax, edx; unsigned int ecx = 0; unsigned pkey_reg; asm volatile(".byte 0x0f,0x01,0xee\n\t" : "=a" (eax), "=d" (edx) : "c" (ecx)); pkey_reg = eax; return pkey_reg; } static inline void __write_pkey_reg(u64 pkey_reg) { unsigned int eax = pkey_reg; unsigned int ecx = 0; unsigned int edx = 0; dprintf4("%s() changing %016llx to %016llx\n", __func__, __read_pkey_reg(), pkey_reg); asm volatile(".byte 0x0f,0x01,0xef\n\t" : : "a" (eax), "c" (ecx), "d" (edx)); assert(pkey_reg == __read_pkey_reg()); } /* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx) */ #define X86_FEATURE_PKU (1<<3) /* Protection Keys for Userspace */ #define X86_FEATURE_OSPKE (1<<4) /* OS Protection Keys Enable */ static inline int cpu_has_pkeys(void) { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; __cpuid_count(0x7, 0x0, eax, ebx, ecx, edx); if (!(ecx & X86_FEATURE_PKU)) { dprintf2("cpu does not have PKU\n"); return 0; } if (!(ecx & X86_FEATURE_OSPKE)) { dprintf2("cpu does not have OSPKE\n"); return 0; } return 1; } static inline int cpu_max_xsave_size(void) { unsigned long XSTATE_CPUID = 0xd; unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; __cpuid_count(XSTATE_CPUID, 0, eax, ebx, ecx, edx); return ecx; } static inline u32 pkey_bit_position(int pkey) { return pkey * PKEY_BITS_PER_PKEY; } #define XSTATE_PKEY_BIT (9) #define XSTATE_PKEY 0x200 #define XSTATE_BV_OFFSET 512 int pkey_reg_xstate_offset(void) { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; int xstate_offset; int xstate_size = 0; unsigned long XSTATE_CPUID = 0xd; int leaf; /* assume that XSTATE_PKEY is set in XCR0 */ leaf = XSTATE_PKEY_BIT; { __cpuid_count(XSTATE_CPUID, leaf, eax, ebx, ecx, edx); if (leaf == XSTATE_PKEY_BIT) { xstate_offset = ebx; xstate_size = eax; } } if (xstate_size == 0) { printf("could not find size/offset of PKEY in xsave state\n"); return 0; } return xstate_offset; } static inline int get_arch_reserved_keys(void) { return NR_RESERVED_PKEYS; } void expect_fault_on_read_execonly_key(void *p1, int pkey) { int ptr_contents; ptr_contents = read_ptr(p1); dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); expected_pkey_fault(pkey); } void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey) { return PTR_ERR_ENOTSUP; } #endif /* _PKEYS_X86_H */ |