Commit d3cd91fb authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Michael Ellerman

powerpc/book3s64/pkeys: Add MMU_FTR_PKEY

Parse storage keys related device tree entry in early_init_devtree
and enable MMU feature MMU_FTR_PKEY if pkeys are supported.

MMU feature is used instead of CPU feature because this enables us
to group MMU_FTR_KUAP and MMU_FTR_PKEY in asm feature fixup code.
Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200709032946.881753-14-aneesh.kumar@linux.ibm.com
parent 3e4352ae
...@@ -214,6 +214,12 @@ extern int mmu_io_psize; ...@@ -214,6 +214,12 @@ extern int mmu_io_psize;
void mmu_early_init_devtree(void); void mmu_early_init_devtree(void);
void hash__early_init_devtree(void); void hash__early_init_devtree(void);
void radix__early_init_devtree(void); void radix__early_init_devtree(void);
#ifdef CONFIG_PPC_MEM_KEYS
void pkey_early_init_devtree(void);
#else
static inline void pkey_early_init_devtree(void) {}
#endif
extern void hash__early_init_mmu(void); extern void hash__early_init_mmu(void);
extern void radix__early_init_mmu(void); extern void radix__early_init_mmu(void);
static inline void __init early_init_mmu(void) static inline void __init early_init_mmu(void)
......
...@@ -28,6 +28,11 @@ ...@@ -28,6 +28,11 @@
* Individual features below. * Individual features below.
*/ */
/*
* Support for memory protection keys.
*/
#define MMU_FTR_PKEY ASM_CONST(0x00000800)
/* Guest Translation Shootdown Enable */ /* Guest Translation Shootdown Enable */
#define MMU_FTR_GTSE ASM_CONST(0x00001000) #define MMU_FTR_GTSE ASM_CONST(0x00001000)
...@@ -181,6 +186,9 @@ enum { ...@@ -181,6 +186,9 @@ enum {
MMU_FTR_RADIX_KUAP | MMU_FTR_RADIX_KUAP |
#endif /* CONFIG_PPC_KUAP */ #endif /* CONFIG_PPC_KUAP */
#endif /* CONFIG_PPC_RADIX_MMU */ #endif /* CONFIG_PPC_RADIX_MMU */
#ifdef CONFIG_PPC_MEM_KEYS
MMU_FTR_PKEY |
#endif
0, 0,
}; };
...@@ -360,6 +368,8 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base, ...@@ -360,6 +368,8 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size); phys_addr_t first_memblock_size);
static inline void mmu_early_init_devtree(void) { } static inline void mmu_early_init_devtree(void) { }
static inline void pkey_early_init_devtree(void) {}
extern void *abatron_pteptrs[2]; extern void *abatron_pteptrs[2];
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif #endif
......
...@@ -815,6 +815,11 @@ void __init early_init_devtree(void *params) ...@@ -815,6 +815,11 @@ void __init early_init_devtree(void *params)
/* Now try to figure out if we are running on LPAR and so on */ /* Now try to figure out if we are running on LPAR and so on */
pseries_probe_fw_features(); pseries_probe_fw_features();
/*
* Initialize pkey features and default AMR/IAMR values
*/
pkey_early_init_devtree();
#ifdef CONFIG_PPC_PS3 #ifdef CONFIG_PPC_PS3
/* Identify PS3 firmware */ /* Identify PS3 firmware */
if (of_flat_dt_is_compatible(of_get_flat_dt_root(), "sony,ps3")) if (of_flat_dt_is_compatible(of_get_flat_dt_root(), "sony,ps3"))
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <linux/pkeys.h> #include <linux/pkeys.h>
#include <linux/of_device.h> #include <linux/of_fdt.h>
DEFINE_STATIC_KEY_FALSE(pkey_disabled); DEFINE_STATIC_KEY_FALSE(pkey_disabled);
int num_pkey; /* Max number of pkeys supported */ int num_pkey; /* Max number of pkeys supported */
...@@ -46,31 +47,38 @@ static int execute_only_key = 2; ...@@ -46,31 +47,38 @@ static int execute_only_key = 2;
#define PKEY_REG_BITS (sizeof(u64) * 8) #define PKEY_REG_BITS (sizeof(u64) * 8)
#define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY)) #define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY))
static int __init dt_scan_storage_keys(unsigned long node,
const char *uname, int depth,
void *data)
{
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
const __be32 *prop;
int *pkeys_total = (int *) data;
/* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0)
return 0;
prop = of_get_flat_dt_prop(node, "ibm,processor-storage-keys", NULL);
if (!prop)
return 0;
*pkeys_total = be32_to_cpu(prop[0]);
return 1;
}
static int scan_pkey_feature(void) static int scan_pkey_feature(void)
{ {
u32 vals[2]; int ret;
int pkeys_total = 0; int pkeys_total = 0;
struct device_node *cpu;
/* /*
* Pkey is not supported with Radix translation. * Pkey is not supported with Radix translation.
*/ */
if (radix_enabled()) if (early_radix_enabled())
return 0;
cpu = of_find_node_by_type(NULL, "cpu");
if (!cpu)
return 0; return 0;
if (of_property_read_u32_array(cpu, ret = of_scan_flat_dt(dt_scan_storage_keys, &pkeys_total);
"ibm,processor-storage-keys", vals, 2) == 0) { if (ret == 0) {
/*
* Since any pkey can be used for data or execute, we will
* just treat all keys as equal and track them as one entity.
*/
pkeys_total = vals[0];
} else {
/* /*
* Let's assume 32 pkeys on P8/P9 bare metal, if its not defined by device * Let's assume 32 pkeys on P8/P9 bare metal, if its not defined by device
* tree. We make this exception since some version of skiboot forgot to * tree. We make this exception since some version of skiboot forgot to
...@@ -94,7 +102,7 @@ static int scan_pkey_feature(void) ...@@ -94,7 +102,7 @@ static int scan_pkey_feature(void)
return pkeys_total; return pkeys_total;
} }
static int pkey_initialize(void) void __init pkey_early_init_devtree(void)
{ {
int pkeys_total, i; int pkeys_total, i;
...@@ -119,9 +127,11 @@ static int pkey_initialize(void) ...@@ -119,9 +127,11 @@ static int pkey_initialize(void)
if (!pkeys_total) { if (!pkeys_total) {
/* No support for pkey. Mark it disabled */ /* No support for pkey. Mark it disabled */
static_branch_enable(&pkey_disabled); static_branch_enable(&pkey_disabled);
return 0; return;
} }
cur_cpu_spec->mmu_features |= MMU_FTR_PKEY;
/* /*
* The device tree cannot be relied to indicate support for * The device tree cannot be relied to indicate support for
* execute_disable support. Instead we use a PVR check. * execute_disable support. Instead we use a PVR check.
...@@ -201,11 +211,9 @@ static int pkey_initialize(void) ...@@ -201,11 +211,9 @@ static int pkey_initialize(void)
*/ */
initial_allocation_mask |= reserved_allocation_mask; initial_allocation_mask |= reserved_allocation_mask;
return 0; return;
} }
arch_initcall(pkey_initialize);
void pkey_mm_init(struct mm_struct *mm) void pkey_mm_init(struct mm_struct *mm)
{ {
if (static_branch_likely(&pkey_disabled)) if (static_branch_likely(&pkey_disabled))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment