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
This commit is contained in:
committed by
Michael Ellerman
parent
3e4352aeb8
commit
d3cd91fb8d
@@ -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 @@
|
|||||||
* 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 {
|
|||||||
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,
|
|||||||
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)
|
|||||||
/* 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 @@
|
|||||||
#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;
|
|||||||
#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;
|
return 0;
|
||||||
|
|
||||||
cpu = of_find_node_by_type(NULL, "cpu");
|
ret = of_scan_flat_dt(dt_scan_storage_keys, &pkeys_total);
|
||||||
if (!cpu)
|
if (ret == 0) {
|
||||||
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 {
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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))
|
||||||
|
Reference in New Issue
Block a user