[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