Skip to content

Commit 2ddc53f

Browse files
Ram Paimpe
authored andcommitted
powerpc: implementation for arch_set_user_pkey_access()
This patch provides the detailed implementation for a user to allocate a key and enable it in the hardware. It provides the plumbing, but it cannot be used till the system call is implemented. The next patch will do so. Reviewed-by: Thiago Jung Bauermann <[email protected]> Signed-off-by: Ram Pai <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 0685f21 commit 2ddc53f

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

arch/powerpc/include/asm/pkeys.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,14 @@ static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
128128
return 0;
129129
}
130130

131+
extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
132+
unsigned long init_val);
131133
static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
132134
unsigned long init_val)
133135
{
134-
return 0;
136+
if (static_branch_likely(&pkey_disabled))
137+
return -EINVAL;
138+
return __arch_set_user_pkey_access(tsk, pkey, init_val);
135139
}
136140

137141
extern void pkey_mm_init(struct mm_struct *mm);

arch/powerpc/mm/pkeys.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright 2017, Ram Pai, IBM Corporation.
66
*/
77

8+
#include <asm/mman.h>
89
#include <linux/pkeys.h>
910

1011
DEFINE_STATIC_KEY_TRUE(pkey_disabled);
@@ -13,6 +14,9 @@ int pkeys_total; /* Total pkeys as per device tree */
1314
u32 initial_allocation_mask; /* Bits set for reserved keys */
1415

1516
#define AMR_BITS_PER_PKEY 2
17+
#define AMR_RD_BIT 0x1UL
18+
#define AMR_WR_BIT 0x2UL
19+
#define IAMR_EX_BIT 0x1UL
1620
#define PKEY_REG_BITS (sizeof(u64)*8)
1721
#define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY))
1822

@@ -108,6 +112,20 @@ static inline void write_uamor(u64 value)
108112
mtspr(SPRN_UAMOR, value);
109113
}
110114

115+
static bool is_pkey_enabled(int pkey)
116+
{
117+
u64 uamor = read_uamor();
118+
u64 pkey_bits = 0x3ul << pkeyshift(pkey);
119+
u64 uamor_pkey_bits = (uamor & pkey_bits);
120+
121+
/*
122+
* Both the bits in UAMOR corresponding to the key should be set or
123+
* reset.
124+
*/
125+
WARN_ON(uamor_pkey_bits && (uamor_pkey_bits != pkey_bits));
126+
return !!(uamor_pkey_bits);
127+
}
128+
111129
static inline void init_amr(int pkey, u8 init_bits)
112130
{
113131
u64 new_amr_bits = (((u64)init_bits & 0x3UL) << pkeyshift(pkey));
@@ -150,3 +168,25 @@ void __arch_deactivate_pkey(int pkey)
150168
{
151169
pkey_status_change(pkey, false);
152170
}
171+
172+
/*
173+
* Set the access rights in AMR IAMR and UAMOR registers for @pkey to that
174+
* specified in @init_val.
175+
*/
176+
int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
177+
unsigned long init_val)
178+
{
179+
u64 new_amr_bits = 0x0ul;
180+
181+
if (!is_pkey_enabled(pkey))
182+
return -EINVAL;
183+
184+
/* Set the bits we need in AMR: */
185+
if (init_val & PKEY_DISABLE_ACCESS)
186+
new_amr_bits |= AMR_RD_BIT | AMR_WR_BIT;
187+
else if (init_val & PKEY_DISABLE_WRITE)
188+
new_amr_bits |= AMR_WR_BIT;
189+
190+
init_amr(pkey, new_amr_bits);
191+
return 0;
192+
}

0 commit comments

Comments
 (0)