Skip to content

Commit cf43d3b

Browse files
Ram Paimpe
Ram Pai
authored andcommitted
powerpc: Enable pkey subsystem
PAPR defines 'ibm,processor-storage-keys' property. It exports two values. The first value holds the number of data-access keys and the second holds the number of instruction-access keys. Due to a bug in the firmware, instruction-access keys is always reported as zero. However any key can be configured to disable data-access and/or disable execution-access. The inavailablity of the second value is not a big handicap, though it could have been used to determine if the platform supported disable-execution-access. Non-PAPR platforms do not define this property in the device tree yet. Fortunately power8 is the only released Non-PAPR platform that is supported. Here, we hardcode the number of supported pkey to 32, by consulting the PowerISA3.0 This patch calculates the number of keys supported by the platform. Also it determines the platform support for read/write/execution access support for pkeys. Signed-off-by: Ram Pai <[email protected]> [mpe: Use a PVR check instead of CPU_FTR for execute. Restrict to Power7/8/9 for now until older CPUs are tested.] Signed-off-by: Michael Ellerman <[email protected]>
1 parent c5cc1f4 commit cf43d3b

File tree

3 files changed

+63
-13
lines changed

3 files changed

+63
-13
lines changed

arch/powerpc/include/asm/cputable.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ static inline void cpu_feature_keys_init(void) { }
195195
#define CPU_FTR_STCX_CHECKS_ADDRESS LONG_ASM_CONST(0x0004000000000000)
196196
#define CPU_FTR_POPCNTB LONG_ASM_CONST(0x0008000000000000)
197197
#define CPU_FTR_POPCNTD LONG_ASM_CONST(0x0010000000000000)
198-
/* Free LONG_ASM_CONST(0x0020000000000000) */
198+
#define CPU_FTR_PKEY LONG_ASM_CONST(0x0020000000000000)
199199
#define CPU_FTR_VMX_COPY LONG_ASM_CONST(0x0040000000000000)
200200
#define CPU_FTR_TM LONG_ASM_CONST(0x0080000000000000)
201201
#define CPU_FTR_CFAR LONG_ASM_CONST(0x0100000000000000)
@@ -442,7 +442,7 @@ static inline void cpu_feature_keys_init(void) { }
442442
CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \
443443
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
444444
CPU_FTR_CFAR | CPU_FTR_HVMODE | \
445-
CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR | CPU_FTR_DABRX)
445+
CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR | CPU_FTR_DABRX | CPU_FTR_PKEY)
446446
#define CPU_FTRS_POWER8 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
447447
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\
448448
CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -452,7 +452,7 @@ static inline void cpu_feature_keys_init(void) { }
452452
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
453453
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
454454
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
455-
CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP)
455+
CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_PKEY)
456456
#define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG)
457457
#define CPU_FTRS_POWER8_DD1 (CPU_FTRS_POWER8 & ~CPU_FTR_DBELL)
458458
#define CPU_FTRS_POWER9 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
@@ -464,7 +464,8 @@ static inline void cpu_feature_keys_init(void) { }
464464
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
465465
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
466466
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
467-
CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300)
467+
CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | \
468+
CPU_FTR_PKEY)
468469
#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
469470
(~CPU_FTR_SAO))
470471
#define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9

arch/powerpc/include/asm/pkeys.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define _ASM_POWERPC_KEYS_H
1010

1111
#include <linux/jump_label.h>
12+
#include <asm/firmware.h>
1213

1314
DECLARE_STATIC_KEY_TRUE(pkey_disabled);
1415
extern int pkeys_total; /* total pkeys as per device tree */
@@ -208,6 +209,8 @@ static inline bool arch_pkeys_enabled(void)
208209
}
209210

210211
extern void pkey_mm_init(struct mm_struct *mm);
212+
extern bool arch_supports_pkeys(int cap);
213+
extern unsigned int arch_usable_pkeys(void);
211214
extern void thread_pkey_regs_save(struct thread_struct *thread);
212215
extern void thread_pkey_regs_restore(struct thread_struct *new_thread,
213216
struct thread_struct *old_thread);

arch/powerpc/mm/pkeys.c

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
*/
77

88
#include <asm/mman.h>
9+
#include <asm/setup.h>
910
#include <linux/pkeys.h>
11+
#include <linux/of_device.h>
1012

1113
DEFINE_STATIC_KEY_TRUE(pkey_disabled);
1214
bool pkey_execute_disable_supported;
1315
int pkeys_total; /* Total pkeys as per device tree */
16+
bool pkeys_devtree_defined; /* pkey property exported by device tree */
1417
u32 initial_allocation_mask; /* Bits set for reserved keys */
1518
u64 pkey_amr_uamor_mask; /* Bits in AMR/UMOR not to be touched */
1619
u64 pkey_iamr_mask; /* Bits in AMR not to be touched */
@@ -22,6 +25,35 @@ u64 pkey_iamr_mask; /* Bits in AMR not to be touched */
2225
#define PKEY_REG_BITS (sizeof(u64)*8)
2326
#define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY))
2427

28+
static void scan_pkey_feature(void)
29+
{
30+
u32 vals[2];
31+
struct device_node *cpu;
32+
33+
cpu = of_find_node_by_type(NULL, "cpu");
34+
if (!cpu)
35+
return;
36+
37+
if (of_property_read_u32_array(cpu,
38+
"ibm,processor-storage-keys", vals, 2))
39+
return;
40+
41+
/*
42+
* Since any pkey can be used for data or execute, we will just treat
43+
* all keys as equal and track them as one entity.
44+
*/
45+
pkeys_total = be32_to_cpu(vals[0]);
46+
pkeys_devtree_defined = true;
47+
}
48+
49+
static inline bool pkey_mmu_enabled(void)
50+
{
51+
if (firmware_has_feature(FW_FEATURE_LPAR))
52+
return pkeys_total;
53+
else
54+
return cpu_has_feature(CPU_FTR_PKEY);
55+
}
56+
2557
int pkey_initialize(void)
2658
{
2759
int os_reserved, i;
@@ -42,14 +74,17 @@ int pkey_initialize(void)
4274
__builtin_popcountl(ARCH_VM_PKEY_FLAGS >> VM_PKEY_SHIFT)
4375
!= (sizeof(u64) * BITS_PER_BYTE));
4476

77+
/* scan the device tree for pkey feature */
78+
scan_pkey_feature();
79+
4580
/*
46-
* Disable the pkey system till everything is in place. A subsequent
47-
* patch will enable it.
81+
* Let's assume 32 pkeys on P8 bare metal, if its not defined by device
82+
* tree. We make this exception since skiboot forgot to expose this
83+
* property on power8.
4884
*/
49-
static_branch_enable(&pkey_disabled);
50-
51-
/* Lets assume 32 keys */
52-
pkeys_total = 32;
85+
if (!pkeys_devtree_defined && !firmware_has_feature(FW_FEATURE_LPAR) &&
86+
cpu_has_feature(CPU_FTRS_POWER8))
87+
pkeys_total = 32;
5388

5489
/*
5590
* Adjust the upper limit, based on the number of bits supported by
@@ -58,11 +93,22 @@ int pkey_initialize(void)
5893
pkeys_total = min_t(int, pkeys_total,
5994
(ARCH_VM_PKEY_FLAGS >> VM_PKEY_SHIFT));
6095

96+
if (!pkey_mmu_enabled() || radix_enabled() || !pkeys_total)
97+
static_branch_enable(&pkey_disabled);
98+
else
99+
static_branch_disable(&pkey_disabled);
100+
101+
if (static_branch_likely(&pkey_disabled))
102+
return 0;
103+
61104
/*
62-
* Disable execute_disable support for now. A subsequent patch will
63-
* enable it.
105+
* The device tree cannot be relied to indicate support for
106+
* execute_disable support. Instead we use a PVR check.
64107
*/
65-
pkey_execute_disable_supported = false;
108+
if (pvr_version_is(PVR_POWER7) || pvr_version_is(PVR_POWER7p))
109+
pkey_execute_disable_supported = false;
110+
else
111+
pkey_execute_disable_supported = true;
66112

67113
#ifdef CONFIG_PPC_4K_PAGES
68114
/*

0 commit comments

Comments
 (0)