Zeng Heng (2): Revert "arm64: head.S: Initialise MPAM EL2 registers and disable traps" arm64/mpam: Check mpam_detect_is_enabled() before accessing MPAM registers
arch/arm64/include/asm/cpufeature.h | 9 +++++++ arch/arm64/include/asm/el2_setup.h | 16 ------------ arch/arm64/kernel/cpufeature.c | 39 ++++++++++++++++++++++++++--- arch/arm64/kernel/cpuinfo.c | 1 + arch/arm64/kernel/mpam.c | 15 ++++++++--- 5 files changed, 56 insertions(+), 24 deletions(-)
-- 2.25.1
Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9OXPO
--------------------------------
This reverts commit a01fda352718f178db2effe5e9d2c1b6a5602356.
If BIOS firmware doesn't enable MPAM function under EL3 environment, while the hardware has the MPAM ability, that would cause illegal instruction fault when access MPAM registers.
It should be noted that this will bring potential risks to Kdump. If the previous kernel has an unhandled MPAM exception interrupt, it would cause Kdump crash after re-enable interrupt capability.
Fixes: a01fda352718 ("arm64: head.S: Initialise MPAM EL2 registers and disable traps") Signed-off-by: Zeng Heng zengheng4@huawei.com --- arch/arm64/include/asm/el2_setup.h | 16 ---------------- 1 file changed, 16 deletions(-)
diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h index 3dc7c58d55b6..e4546b29dd0c 100644 --- a/arch/arm64/include/asm/el2_setup.h +++ b/arch/arm64/include/asm/el2_setup.h @@ -209,21 +209,6 @@ msr spsr_el2, x0 .endm
-.macro __init_el2_mpam -#ifdef CONFIG_ARM64_MPAM - /* Memory Partioning And Monitoring: disable EL2 traps */ - mrs x1, id_aa64pfr0_el1 - ubfx x0, x1, #ID_AA64PFR0_EL1_MPAM_SHIFT, #4 - cbz x0, .Lskip_mpam_@ // skip if no MPAM - msr_s SYS_MPAM2_EL2, xzr // use the default partition - // and disable lower traps - mrs_s x0, SYS_MPAMIDR_EL1 - tbz x0, #17, .Lskip_mpam_@ // skip if no MPAMHCR reg - msr_s SYS_MPAMHCR_EL2, xzr // clear TRAP_MPAMIDR_EL1 -> EL2 -.Lskip_mpam_@: -#endif /* CONFIG_ARM64_MPAM */ -.endm - /** * Initialize EL2 registers to sane values. This should be called early on all * cores that were booted in EL2. Note that everything gets initialised as @@ -241,7 +226,6 @@ __init_el2_stage2 __init_el2_gicv3 __init_el2_hstr - __init_el2_mpam __init_el2_nvhe_idregs __init_el2_cptr __init_el2_fgt
Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9OXPO
--------------------------------
If BIOS firmware doesn't enable MPAM function under EL3 environment, while the hardware has the MPAM ability, that would cause illegal instruction fault when access MPAM registers.
In order to be compatible with this scenario and avoid crashes during startup, only by adding the 'arm64.mpam' boot parameter in kernel command line make the MPAM feature be enabled.
Fixes: 21771eaaf93a ("arm64: cpufeature: discover CPU support for MPAM") Signed-off-by: Zeng Heng zengheng4@huawei.com --- arch/arm64/include/asm/cpufeature.h | 9 +++++++ arch/arm64/kernel/cpufeature.c | 39 ++++++++++++++++++++++++++--- arch/arm64/kernel/cpuinfo.c | 1 + arch/arm64/kernel/mpam.c | 15 ++++++++--- 4 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 2af4c7ad7dc5..f8ec4b20fa69 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -858,6 +858,15 @@ static inline bool cpus_support_mpam(void) cpus_have_final_cap(ARM64_MPAM); }
+#ifdef CONFIG_ARM64_MPAM +bool mpam_detect_is_enabled(void); +#else +static inline bool mpam_detect_is_enabled(void) +{ + return false; +} +#endif + int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt); bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index f94bc6eb83e0..a7b4ccd7983e 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1078,8 +1078,9 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info) vec_init_vq_map(ARM64_VEC_SME); }
- if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0) || - id_aa64pfr1_mpamfrac(info->reg_id_aa64pfr1)) + if (mpam_detect_is_enabled() && + (id_aa64pfr0_mpam(info->reg_id_aa64pfr0) || + id_aa64pfr1_mpamfrac(info->reg_id_aa64pfr1))) init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1)) @@ -1341,8 +1342,9 @@ void update_cpu_features(int cpu, vec_update_vq_map(ARM64_VEC_SME); }
- if (id_aa64pfr0_mpam(info->reg_id_aa64pfr0) || - id_aa64pfr1_mpamfrac(info->reg_id_aa64pfr1)) { + if (mpam_detect_is_enabled() && + (id_aa64pfr0_mpam(info->reg_id_aa64pfr0) || + id_aa64pfr1_mpamfrac(info->reg_id_aa64pfr1))) { taint |= check_update_ftr_reg(SYS_MPAMIDR_EL1, cpu, info->reg_mpamidr, boot->reg_mpamidr); } @@ -2307,6 +2309,19 @@ cpucap_panic_on_conflict(const struct arm64_cpu_capabilities *cap) return !!(cap->type & ARM64_CPUCAP_PANIC_ON_CONFLICT); }
+static bool __read_mostly mpam_force_enabled; +bool mpam_detect_is_enabled(void) +{ + return mpam_force_enabled; +} + +static int __init mpam_setup(char *str) +{ + mpam_force_enabled = true; + return 0; +} +early_param("arm64.mpam", mpam_setup); + static bool __maybe_unused test_has_mpam(const struct arm64_cpu_capabilities *entry, int scope) { @@ -2317,6 +2332,12 @@ test_has_mpam(const struct arm64_cpu_capabilities *entry, int scope) !id_aa64pfr1_mpamfrac(pfr1)) return false;
+ if (is_kdump_kernel()) + return false; + + if (!mpam_detect_is_enabled()) + return false; + /* Check firmware actually enabled MPAM on this cpu. */ return (read_sysreg_s(SYS_MPAM1_EL1) & MPAM_SYSREG_EN); } @@ -2324,6 +2345,16 @@ test_has_mpam(const struct arm64_cpu_capabilities *entry, int scope) static void __maybe_unused cpu_enable_mpam(const struct arm64_cpu_capabilities *entry) { + u64 idr = read_sanitised_ftr_reg(SYS_MPAMIDR_EL1); + + /* + * Initialise MPAM EL2 registers and disable EL2 traps. + */ + write_sysreg_s(0, SYS_MPAM2_EL2); + + if (idr & MPAMIDR_HAS_HCR) + write_sysreg_s(0, SYS_MPAMHCR_EL2); + /* * Access by the kernel (at EL1) should use the reserved PARTID * which is configured unrestricted. This avoids priority-inversion diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index 5ad8d8697d56..7466b6066d87 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -461,6 +461,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) __cpuinfo_store_cpu_32bit(&info->aarch32);
if (IS_ENABLED(CONFIG_ARM64_MPAM) && + mpam_detect_is_enabled() && (id_aa64pfr0_mpam(info->reg_id_aa64pfr0) || id_aa64pfr1_mpamfrac(info->reg_id_aa64pfr1))) info->reg_mpamidr = read_cpuid(MPAMIDR_EL1); diff --git a/arch/arm64/kernel/mpam.c b/arch/arm64/kernel/mpam.c index 8fd9dbdc2b01..d8891d5c59c0 100644 --- a/arch/arm64/kernel/mpam.c +++ b/arch/arm64/kernel/mpam.c @@ -15,13 +15,20 @@ DEFINE_PER_CPU(u64, arm64_mpam_current);
static int __init arm64_mpam_register_cpus(void) { + u16 partid_max; + u64 mpamidr; + u8 pmg_max; + if (is_kdump_kernel()) return 0;
- u64 mpamidr = read_sanitised_ftr_reg(SYS_MPAMIDR_EL1); - u16 partid_max = FIELD_GET(MPAMIDR_PARTID_MAX, mpamidr); - u8 pmg_max = FIELD_GET(MPAMIDR_PMG_MAX, mpamidr); + if (!mpam_cpus_have_feature()) + return 0; + + mpamidr = read_sanitised_ftr_reg(SYS_MPAMIDR_EL1); + partid_max = FIELD_GET(MPAMIDR_PARTID_MAX, mpamidr); + pmg_max = FIELD_GET(MPAMIDR_PMG_MAX, mpamidr);
return mpam_register_requestor(partid_max, pmg_max); } -arch_initcall(arm64_mpam_register_cpus) +arch_initcall(arm64_mpam_register_cpus);
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/11756 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/L...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/11756 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/L...