On Fri, 15 Oct 2021 17:14:13 +0100,
James Morse <[email protected]> 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 <[email protected]>
> ---
>  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.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to