Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 
0003 #ifndef _PKEYS_X86_H
0004 #define _PKEYS_X86_H
0005 
0006 #ifdef __i386__
0007 
0008 #ifndef SYS_mprotect_key
0009 # define SYS_mprotect_key   380
0010 #endif
0011 
0012 #ifndef SYS_pkey_alloc
0013 # define SYS_pkey_alloc     381
0014 # define SYS_pkey_free      382
0015 #endif
0016 
0017 #define REG_IP_IDX      REG_EIP
0018 #define si_pkey_offset      0x14
0019 
0020 #else
0021 
0022 #ifndef SYS_mprotect_key
0023 # define SYS_mprotect_key   329
0024 #endif
0025 
0026 #ifndef SYS_pkey_alloc
0027 # define SYS_pkey_alloc     330
0028 # define SYS_pkey_free      331
0029 #endif
0030 
0031 #define REG_IP_IDX      REG_RIP
0032 #define si_pkey_offset      0x20
0033 
0034 #endif
0035 
0036 #ifndef PKEY_DISABLE_ACCESS
0037 # define PKEY_DISABLE_ACCESS    0x1
0038 #endif
0039 
0040 #ifndef PKEY_DISABLE_WRITE
0041 # define PKEY_DISABLE_WRITE 0x2
0042 #endif
0043 
0044 #define NR_PKEYS        16
0045 #define NR_RESERVED_PKEYS   2 /* pkey-0 and exec-only-pkey */
0046 #define PKEY_BITS_PER_PKEY  2
0047 #define HPAGE_SIZE      (1UL<<21)
0048 #define PAGE_SIZE       4096
0049 #define MB          (1<<20)
0050 
0051 static inline void __page_o_noops(void)
0052 {
0053     /* 8-bytes of instruction * 512 bytes = 1 page */
0054     asm(".rept 512 ; nopl 0x7eeeeeee(%eax) ; .endr");
0055 }
0056 
0057 static inline u64 __read_pkey_reg(void)
0058 {
0059     unsigned int eax, edx;
0060     unsigned int ecx = 0;
0061     unsigned pkey_reg;
0062 
0063     asm volatile(".byte 0x0f,0x01,0xee\n\t"
0064              : "=a" (eax), "=d" (edx)
0065              : "c" (ecx));
0066     pkey_reg = eax;
0067     return pkey_reg;
0068 }
0069 
0070 static inline void __write_pkey_reg(u64 pkey_reg)
0071 {
0072     unsigned int eax = pkey_reg;
0073     unsigned int ecx = 0;
0074     unsigned int edx = 0;
0075 
0076     dprintf4("%s() changing %016llx to %016llx\n", __func__,
0077             __read_pkey_reg(), pkey_reg);
0078     asm volatile(".byte 0x0f,0x01,0xef\n\t"
0079              : : "a" (eax), "c" (ecx), "d" (edx));
0080     assert(pkey_reg == __read_pkey_reg());
0081 }
0082 
0083 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx) */
0084 #define X86_FEATURE_PKU        (1<<3) /* Protection Keys for Userspace */
0085 #define X86_FEATURE_OSPKE      (1<<4) /* OS Protection Keys Enable */
0086 
0087 static inline int cpu_has_pkeys(void)
0088 {
0089     unsigned int eax;
0090     unsigned int ebx;
0091     unsigned int ecx;
0092     unsigned int edx;
0093 
0094     __cpuid_count(0x7, 0x0, eax, ebx, ecx, edx);
0095 
0096     if (!(ecx & X86_FEATURE_PKU)) {
0097         dprintf2("cpu does not have PKU\n");
0098         return 0;
0099     }
0100     if (!(ecx & X86_FEATURE_OSPKE)) {
0101         dprintf2("cpu does not have OSPKE\n");
0102         return 0;
0103     }
0104     return 1;
0105 }
0106 
0107 static inline u32 pkey_bit_position(int pkey)
0108 {
0109     return pkey * PKEY_BITS_PER_PKEY;
0110 }
0111 
0112 #define XSTATE_PKEY_BIT (9)
0113 #define XSTATE_PKEY 0x200
0114 #define XSTATE_BV_OFFSET    512
0115 
0116 int pkey_reg_xstate_offset(void)
0117 {
0118     unsigned int eax;
0119     unsigned int ebx;
0120     unsigned int ecx;
0121     unsigned int edx;
0122     int xstate_offset;
0123     int xstate_size;
0124     unsigned long XSTATE_CPUID = 0xd;
0125     int leaf;
0126 
0127     /* assume that XSTATE_PKEY is set in XCR0 */
0128     leaf = XSTATE_PKEY_BIT;
0129     {
0130         __cpuid_count(XSTATE_CPUID, leaf, eax, ebx, ecx, edx);
0131 
0132         if (leaf == XSTATE_PKEY_BIT) {
0133             xstate_offset = ebx;
0134             xstate_size = eax;
0135         }
0136     }
0137 
0138     if (xstate_size == 0) {
0139         printf("could not find size/offset of PKEY in xsave state\n");
0140         return 0;
0141     }
0142 
0143     return xstate_offset;
0144 }
0145 
0146 static inline int get_arch_reserved_keys(void)
0147 {
0148     return NR_RESERVED_PKEYS;
0149 }
0150 
0151 void expect_fault_on_read_execonly_key(void *p1, int pkey)
0152 {
0153     int ptr_contents;
0154 
0155     ptr_contents = read_ptr(p1);
0156     dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
0157     expected_pkey_fault(pkey);
0158 }
0159 
0160 void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey)
0161 {
0162     return PTR_ERR_ENOTSUP;
0163 }
0164 
0165 #endif /* _PKEYS_X86_H */