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