Commit 21771eaa authored by James Morse's avatar James Morse Committed by Zeng Heng
Browse files

arm64: cpufeature: discover CPU support for MPAM

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8T2RT

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/morse/linux.git/log/?h=mpam/snapshot/v6.7-rc2



---------------------------

ARMv8.4 adds support for 'Memory Partitioning And Monitoring' (MPAM)
which describes an interface to cache and bandwidth controls wherever
they appear in the system.

Add support to detect MPAM. Like SVE, MPAM has an extra id register that
describes the virtualisation support, which is optional. Detect this
separately so we can detect mismatched/insane systems, but still use
MPAM on the host even if the virtualisation support is missing.

MPAM needs enabling at the highest implemented exception level, otherwise
the register accesses trap. The 'enabled' flag is accessible to lower
exception levels, but its in a register that traps when MPAM isn't enabled.
The cpufeature 'matches' hook is extended to test this on one of the
CPUs, so that firwmare can emulate MPAM as disabled if it is reserved
for use by secure world.

(If you have a boot failure that bisects here its likely your CPUs
advertise MPAM in the id registers, but firmware failed to either enable
or MPAM, or emulate the trap as if it were disabled)

Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarZeng Heng <zengheng4@huawei.com>
parent a01fda35
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -152,6 +152,8 @@ infrastructure:
     +------------------------------+---------+---------+
     | DIT                          | [51-48] |    y    |
     +------------------------------+---------+---------+
     | MPAM                         | [43-40] |    n    |
     +------------------------------+---------+---------+
     | SVE                          | [35-32] |    y    |
     +------------------------------+---------+---------+
     | GIC                          | [27-24] |    n    |
+18 −1
Original line number Diff line number Diff line
@@ -2056,7 +2056,24 @@ config ARM64_TLB_RANGE
	  The feature introduces new assembly instructions, and they were
	  support when binutils >= 2.30.

endmenu # "ARMv8.4 architectural features"
config ARM64_MPAM
	bool "Enable support for MPAM"
	help
	  Memory Partitioning and Monitoring is an optional extension
	  that allows the CPUs to mark load and store transactions with
	  labels for partition-id and performance-monitoring-group.
	  System components, such as the caches, can use the partition-id
	  to apply a performance policy. MPAM monitors can use the
	  partition-id and performance-monitoring-group to measure the
	  cache occupancy or data throughput.

	  Use of this extension requires CPU support, support in the
	  memory system components (MSC), and a description from firmware
	  of where the MSC are in the address space.

	  MPAM is exposed to user-space via the resctrl pseudo filesystem.

endmenu

menu "ARMv8.5 architectural features"

+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ struct cpuinfo_arm64 {
	u64		reg_revidr;
	u64		reg_gmid;
	u64		reg_smidr;
	u64		reg_mpamidr;

	u64		reg_id_aa64dfr0;
	u64		reg_id_aa64dfr1;
+13 −0
Original line number Diff line number Diff line
@@ -619,6 +619,13 @@ static inline bool id_aa64pfr1_sme(u64 pfr1)
	return val > 0;
}

static inline bool id_aa64pfr0_mpam(u64 pfr0)
{
	u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL1_MPAM_SHIFT);

	return val > 0;
}

static inline bool id_aa64pfr1_mte(u64 pfr1)
{
	u32 val = cpuid_feature_extract_unsigned_field(pfr1, ID_AA64PFR1_EL1_MTE_SHIFT);
@@ -831,6 +838,12 @@ static inline bool system_supports_tlb_range(void)
		cpus_have_const_cap(ARM64_HAS_TLB_RANGE);
}

static inline bool cpus_support_mpam(void)
{
	return IS_ENABLED(CONFIG_ARM64_MPAM) &&
		cpus_have_final_cap(ARM64_MPAM);
}

int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
bool try_emulate_mrs(struct pt_regs *regs, u32 isn);

+76 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2021 Arm Ltd. */

#ifndef __ASM__MPAM_H
#define __ASM__MPAM_H

#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/jump_label.h>

#include <asm/cpucaps.h>
#include <asm/cpufeature.h>
#include <asm/sysreg.h>

/* CPU Registers */
#define MPAM_SYSREG_EN			BIT_ULL(63)
#define MPAM_SYSREG_TRAP_IDR		BIT_ULL(58)
#define MPAM_SYSREG_TRAP_MPAM0_EL1	BIT_ULL(49)
#define MPAM_SYSREG_TRAP_MPAM1_EL1	BIT_ULL(48)
#define MPAM_SYSREG_PMG_D		GENMASK(47, 40)
#define MPAM_SYSREG_PMG_I		GENMASK(39, 32)
#define MPAM_SYSREG_PARTID_D		GENMASK(31, 16)
#define MPAM_SYSREG_PARTID_I		GENMASK(15, 0)

#define MPAMIDR_PMG_MAX			GENMASK(40, 32)
#define MPAMIDR_PMG_MAX_SHIFT		32
#define MPAMIDR_PMG_MAX_LEN		8
#define MPAMIDR_VPMR_MAX		GENMASK(20, 18)
#define MPAMIDR_VPMR_MAX_SHIFT		18
#define MPAMIDR_VPMR_MAX_LEN		3
#define MPAMIDR_HAS_HCR			BIT(17)
#define MPAMIDR_HAS_HCR_SHIFT		17
#define MPAMIDR_PARTID_MAX		GENMASK(15, 0)
#define MPAMIDR_PARTID_MAX_SHIFT	0
#define MPAMIDR_PARTID_MAX_LEN		15

#define MPAMHCR_EL0_VPMEN		BIT_ULL(0)
#define MPAMHCR_EL1_VPMEN		BIT_ULL(1)
#define MPAMHCR_GSTAPP_PLK		BIT_ULL(8)
#define MPAMHCR_TRAP_MPAMIDR		BIT_ULL(31)

/* Properties of the VPM registers */
#define MPAM_VPM_NUM_REGS		8
#define MPAM_VPM_PARTID_LEN		16
#define MPAM_VPM_PARTID_MASK		0xffff
#define MPAM_VPM_REG_LEN		64
#define MPAM_VPM_PARTIDS_PER_REG	(MPAM_VPM_REG_LEN / MPAM_VPM_PARTID_LEN)
#define MPAM_VPM_MAX_PARTID		(MPAM_VPM_NUM_REGS * MPAM_VPM_PARTIDS_PER_REG)


DECLARE_STATIC_KEY_FALSE(arm64_mpam_has_hcr);

/* check whether all CPUs have MPAM support */
static inline bool mpam_cpus_have_feature(void)
{
	if (IS_ENABLED(CONFIG_ARM64_MPAM))
		return cpus_have_final_cap(ARM64_MPAM);
	return false;
}

/* check whether all CPUs have MPAM virtualisation support */
static inline bool mpam_cpus_have_mpam_hcr(void)
{
	if (IS_ENABLED(CONFIG_ARM64_MPAM))
		return static_branch_unlikely(&arm64_mpam_has_hcr);
	return false;
}

/* enable MPAM virtualisation support */
static inline void __init __enable_mpam_hcr(void)
{
	if (IS_ENABLED(CONFIG_ARM64_MPAM))
		static_branch_enable(&arm64_mpam_has_hcr);
}

#endif /* __ASM__MPAM_H */
Loading