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: Aneesh Kumar K.V <aneesh.ku...@linux.ibm.com> --- arch/powerpc/include/asm/book3s/64/mmu.h | 6 +++ arch/powerpc/include/asm/mmu.h | 6 +++ arch/powerpc/kernel/prom.c | 5 +++ arch/powerpc/mm/book3s64/pkeys.c | 54 ++++++++++++++---------- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index f0a9ff690881..10f54288b3b7 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h @@ -209,6 +209,12 @@ extern int mmu_io_psize; void mmu_early_init_devtree(void); void hash__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 radix__early_init_mmu(void); static inline void early_init_mmu(void) diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index 0699cfeeb8c9..0e5d7ed9fcd6 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h @@ -23,6 +23,7 @@ /* Radix page table supported and enabled */ #define MMU_FTR_TYPE_RADIX ASM_CONST(0x00000040) +#define MMU_FTR_PKEY ASM_CONST(0x00000080) /* * Individual features below. @@ -176,6 +177,9 @@ enum { MMU_FTR_RADIX_KUAP | #endif /* CONFIG_PPC_KUAP */ #endif /* CONFIG_PPC_RADIX_MMU */ +#ifdef CONFIG_PPC_MEM_KEYS + MMU_FTR_PKEY | +#endif 0, }; @@ -364,6 +368,8 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base, phys_addr_t first_memblock_size); static inline void mmu_early_init_devtree(void) { } +static inline void pkey_early_init_devtree(void) {} + extern void *abatron_pteptrs[2]; #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 6620f37abe73..6266bfb72aae 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -791,6 +791,11 @@ void __init early_init_devtree(void *params) /* Now try to figure out if we are running on LPAR and so on */ pseries_probe_fw_features(); + /* + * Initialize pkey features and default AMR/IAMR values + */ + pkey_early_init_devtree(); + #ifdef CONFIG_PPC_PS3 /* Identify PS3 firmware */ if (of_flat_dt_is_compatible(of_get_flat_dt_root(), "sony,ps3")) diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c index 0ff59acdbb84..bbba9c601e14 100644 --- a/arch/powerpc/mm/book3s64/pkeys.c +++ b/arch/powerpc/mm/book3s64/pkeys.c @@ -10,7 +10,8 @@ #include <asm/mmu.h> #include <asm/setup.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(execute_pkey_disabled); @@ -38,38 +39,45 @@ static int execute_only_key = 2; #define PKEY_REG_BITS (sizeof(u64) * 8) #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; + + /* 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 pkeys_total; +} + static int scan_pkey_feature(void) { - u32 vals[2]; - int pkeys_total = 0; - struct device_node *cpu; + int pkeys_total; /* * 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; + pkeys_total = of_scan_flat_dt(dt_scan_storage_keys, NULL); + if (pkeys_total == 0) { - if (of_property_read_u32_array(cpu, - "ibm,processor-storage-keys", vals, 2) == 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]; - /* Should we check for IAMR support FIXME!! */ - } else { /* * Let's assume 32 pkeys on P8 bare metal, if its not defined by device * tree. We make this exception since skiboot forgot to expose this * property on power8. */ if (!firmware_has_feature(FW_FEATURE_LPAR) && - cpu_has_feature(CPU_FTRS_POWER8)) + early_cpu_has_feature(CPU_FTRS_POWER8)) pkeys_total = 32; } @@ -82,7 +90,7 @@ static int scan_pkey_feature(void) return pkeys_total; } -static int pkey_initialize(void) +void __init pkey_early_init_devtree(void) { int pkeys_total, i; @@ -107,9 +115,11 @@ static int pkey_initialize(void) if (!pkeys_total) { /* No support for pkey. Mark it 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 * execute_disable support. Instead we use a PVR check. @@ -187,11 +197,9 @@ static int pkey_initialize(void) */ initial_allocation_mask |= reserved_allocation_mask; - return 0; + return; } -arch_initcall(pkey_initialize); - void pkey_mm_init(struct mm_struct *mm) { if (static_branch_likely(&pkey_disabled)) -- 2.26.2