diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> | 2020-07-09 08:59:36 +0530 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2020-07-20 22:57:58 +1000 |
commit | d3cd91fb8d2e202cf8ebb6f271898aaf37ecda8f (patch) | |
tree | 437b21687e27c4730add32f1ac70f54bff231024 | |
parent | 3e4352aeb8b17eb1040ba288f586620e8294389d (diff) |
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: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200709032946.881753-14-aneesh.kumar@linux.ibm.com
-rw-r--r-- | arch/powerpc/include/asm/book3s/64/mmu.h | 6 | ||||
-rw-r--r-- | arch/powerpc/include/asm/mmu.h | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 5 | ||||
-rw-r--r-- | arch/powerpc/mm/book3s64/pkeys.c | 52 |
4 files changed, 51 insertions, 22 deletions
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 15aae924f41c..55442d45c597 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h @@ -214,6 +214,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 __init early_init_mmu(void) diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index 884d51995934..17cbaf132631 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h @@ -28,6 +28,11 @@ * Individual features below. */ +/* + * Support for memory protection keys. + */ +#define MMU_FTR_PKEY ASM_CONST(0x00000800) + /* Guest Translation Shootdown Enable */ #define MMU_FTR_GTSE ASM_CONST(0x00001000) @@ -181,6 +186,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, }; @@ -360,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 033d43819ed8..dfe0103ad131 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -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 */ 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 d84bf55369a3..028b17c2c511 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); int num_pkey; /* Max number of pkeys supported */ @@ -46,31 +47,38 @@ 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 = (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) { - u32 vals[2]; + int ret; int pkeys_total = 0; - struct device_node *cpu; /* * Pkey is not supported with Radix translation. */ - if (radix_enabled()) - return 0; - - cpu = of_find_node_by_type(NULL, "cpu"); - if (!cpu) + if (early_radix_enabled()) return 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]; - } else { - + ret = of_scan_flat_dt(dt_scan_storage_keys, &pkeys_total); + if (ret == 0) { /* * 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 @@ -94,7 +102,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; @@ -119,9 +127,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. @@ -201,11 +211,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)) |