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