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