[RFC PATCH 4/7] arm64: cpufeature: Enable PBHA bits for stage1

Marc Zyngier maz at kernel.org
Sat Oct 16 06:50:54 PDT 2021


On Fri, 15 Oct 2021 17:14:13 +0100,
James Morse <james.morse at arm.com> wrote:
> 
> If the CPUs support HPDS2, and there is a DT description of PBHA values
> that only affect performance, enable those bits for both TTBR0 and TTBR1.
> 
> Enabling PBHA requires the hierarchical-permissions to be disabled.
> Commit 87143f404f33 ("arm64: mm: use XN table mapping attributes for
> the linear region") used these, but only as an optimisation.
> 
> Only the necessary PBHA bits are enabled to reduce the risk of an
> unsafe bit/value being used by accident.
> 
> Signed-off-by: James Morse <james.morse at arm.com>
> ---
>  arch/arm64/Kconfig                     | 13 +++++
>  arch/arm64/include/asm/pgtable-hwdef.h |  4 ++
>  arch/arm64/kernel/cpufeature.c         | 81 ++++++++++++++++++++++++++
>  arch/arm64/tools/cpucaps               |  1 +
>  4 files changed, 99 insertions(+)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 077f2ec4eeb2..9196bb932aba 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -1461,6 +1461,19 @@ config ARM64_CNP
>  	  at runtime, and does not affect PEs that do not implement
>  	  this feature.
>  
> +config ARM64_PBHA
> +	bool "Enable support for Page Based Hardware Attributes (PBHA)"
> +	default n
> +	help
> +	  Page Based Hardware Attributes (PBHA) allow the SoC hardware to
> +	  change behaviour depending on which mapping was used to access
> +	  a page of memory. e.g. access via one mapping may always result
> +	  in the data being cached, whereas using another mapping of the same
> +	  physical memory.
> +
> +	  The behaviour of each PBHA bit is not defined. Say no unless you
> +	  are very sure you want this
> +
>  endmenu
>  
>  menu "ARMv8.3 architectural features"
> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> index 40085e53f573..3d41242c52b0 100644
> --- a/arch/arm64/include/asm/pgtable-hwdef.h
> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> @@ -268,6 +268,10 @@
>  #define TCR_TBI1		(UL(1) << 38)
>  #define TCR_HA			(UL(1) << 39)
>  #define TCR_HD			(UL(1) << 40)
> +#define TCR_HPD0		(UL(1) << 41)
> +#define TCR_HPD1		(UL(1) << 42)
> +#define TCR_HWU0nn_MASK		(UL(0xf) << 43)
> +#define TCR_HWU1nn_MASK		(UL(0xf) << 47)
>  #define TCR_TBID1		(UL(1) << 52)
>  #define TCR_NFD0		(UL(1) << 53)
>  #define TCR_NFD1		(UL(1) << 54)
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 8694f9dec5e5..548c6f96a878 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -71,6 +71,7 @@
>  #include <linux/types.h>
>  #include <linux/minmax.h>
>  #include <linux/mm.h>
> +#include <linux/of.h>
>  #include <linux/cpu.h>
>  #include <linux/kasan.h>
>  #include <asm/cpu.h>
> @@ -110,6 +111,8 @@ DECLARE_BITMAP(boot_capabilities, ARM64_NPATCHABLE);
>  bool arm64_use_ng_mappings = false;
>  EXPORT_SYMBOL(arm64_use_ng_mappings);
>  
> +unsigned long __ro_after_init arm64_pbha_perf_only_values;
> +
>  /*
>   * Permit PER_LINUX32 and execve() of 32-bit binaries even if not all CPUs
>   * support it?
> @@ -1676,6 +1679,71 @@ static bool has_hw_dbm(const struct arm64_cpu_capabilities *cap,
>  
>  #endif
>  
> +#ifdef CONFIG_ARM64_PBHA
> +static u8 pbha_stage1_enable_bits;
> +
> +static bool plat_can_use_pbha_stage1(const struct arm64_cpu_capabilities *cap,
> +				     int scope)
> +{
> +	u8 val;
> +	struct device_node *cpus;
> +	const u8 *perf_only_vals;
> +	int num_perf_only_vals, i;
> +
> +	if (!has_cpuid_feature(cap, scope))
> +		return false;
> +
> +	/*
> +	 * Calls with scope == SCOPE_LOCAL_CPU need only testing whether this
> +	 * cpu has the feature. A later 'system' scope call will check for a
> +	 * firmware description.
> +	 */
> +	if (scope == SCOPE_LOCAL_CPU)
> +		return true;
> +
> +	cpus = of_find_node_by_path("/cpus");
> +	if (!cpus)
> +		goto done;
> +
> +	perf_only_vals = of_get_property(cpus, "arm,pbha-performance-only",
> +					 &num_perf_only_vals);
> +	if (!perf_only_vals)
> +		goto done;
> +
> +	/* any listed value is usable at stage 1 */
> +	for (i = 0 ; i < num_perf_only_vals; i++) {
> +		val = perf_only_vals[i];
> +		if (val > 0xf)
> +			continue;
> +
> +		pbha_stage1_enable_bits |= val;
> +		set_bit(val, &arm64_pbha_perf_only_values);
> +	}

Somehow, this would need to be exposed to userspace so that a VMM
could tell a guest what it can use.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.



More information about the linux-arm-kernel mailing list