GNU Linux-libre 4.9.283-gnu1
[releases.git] / arch / x86 / include / asm / pkeys.h
1 #ifndef _ASM_X86_PKEYS_H
2 #define _ASM_X86_PKEYS_H
3
4 #define ARCH_DEFAULT_PKEY       0
5
6 /*
7  * If more than 16 keys are ever supported, a thorough audit
8  * will be necessary to ensure that the types that store key
9  * numbers and masks have sufficient capacity.
10  */
11 #define arch_max_pkey() (boot_cpu_has(X86_FEATURE_OSPKE) ? 16 : 1)
12
13 extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
14                 unsigned long init_val);
15
16 /*
17  * Try to dedicate one of the protection keys to be used as an
18  * execute-only protection key.
19  */
20 extern int __execute_only_pkey(struct mm_struct *mm);
21 static inline int execute_only_pkey(struct mm_struct *mm)
22 {
23         if (!boot_cpu_has(X86_FEATURE_OSPKE))
24                 return ARCH_DEFAULT_PKEY;
25
26         return __execute_only_pkey(mm);
27 }
28
29 extern int __arch_override_mprotect_pkey(struct vm_area_struct *vma,
30                 int prot, int pkey);
31 static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
32                 int prot, int pkey)
33 {
34         if (!boot_cpu_has(X86_FEATURE_OSPKE))
35                 return 0;
36
37         return __arch_override_mprotect_pkey(vma, prot, pkey);
38 }
39
40 extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
41                 unsigned long init_val);
42
43 #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | VM_PKEY_BIT3)
44
45 #define mm_pkey_allocation_map(mm)      (mm->context.pkey_allocation_map)
46 #define mm_set_pkey_allocated(mm, pkey) do {            \
47         mm_pkey_allocation_map(mm) |= (1U << pkey);     \
48 } while (0)
49 #define mm_set_pkey_free(mm, pkey) do {                 \
50         mm_pkey_allocation_map(mm) &= ~(1U << pkey);    \
51 } while (0)
52
53 static inline
54 bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
55 {
56         /*
57          * "Allocated" pkeys are those that have been returned
58          * from pkey_alloc() or pkey 0 which is allocated
59          * implicitly when the mm is created.
60          */
61         if (pkey < 0)
62                 return false;
63         if (pkey >= arch_max_pkey())
64                 return false;
65         /*
66          * The exec-only pkey is set in the allocation map, but
67          * is not available to any of the user interfaces like
68          * mprotect_pkey().
69          */
70         if (pkey == mm->context.execute_only_pkey)
71                 return false;
72
73         return mm_pkey_allocation_map(mm) & (1U << pkey);
74 }
75
76 /*
77  * Returns a positive, 4-bit key on success, or -1 on failure.
78  */
79 static inline
80 int mm_pkey_alloc(struct mm_struct *mm)
81 {
82         /*
83          * Note: this is the one and only place we make sure
84          * that the pkey is valid as far as the hardware is
85          * concerned.  The rest of the kernel trusts that
86          * only good, valid pkeys come out of here.
87          */
88         u16 all_pkeys_mask = ((1U << arch_max_pkey()) - 1);
89         int ret;
90
91         /*
92          * Are we out of pkeys?  We must handle this specially
93          * because ffz() behavior is undefined if there are no
94          * zeros.
95          */
96         if (mm_pkey_allocation_map(mm) == all_pkeys_mask)
97                 return -1;
98
99         ret = ffz(mm_pkey_allocation_map(mm));
100
101         mm_set_pkey_allocated(mm, ret);
102
103         return ret;
104 }
105
106 static inline
107 int mm_pkey_free(struct mm_struct *mm, int pkey)
108 {
109         if (!mm_pkey_is_allocated(mm, pkey))
110                 return -EINVAL;
111
112         mm_set_pkey_free(mm, pkey);
113
114         return 0;
115 }
116
117 extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
118                 unsigned long init_val);
119 extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
120                 unsigned long init_val);
121 extern void copy_init_pkru_to_fpregs(void);
122
123 #endif /*_ASM_X86_PKEYS_H */