mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 04:23:03 +02:00
arm64 fixes for -rc2
- Disable interrupts during page-table walk in show_pte()
- Fix kexec_file_load() with 52-bit capable kernels on machines without
52-bit addressing
- Fix MIDR matching in CPU errata handling for KVM guests
- Avoid reading MTE-specific ID registers when MTE support is disabled
-----BEGIN PGP SIGNATURE-----
iQFEBAABCgAuFiEEPxTL6PPUbjXGY88ct6xw3ITBYzQFAmqayVUQHHdpbGxAa2Vy
bmVsLm9yZwAKCRC3rHDchMFjNIG6B/47THEr7Wqq00c1s7loGtwGJiN8dMcfSMpp
r86zeLL37erJQ9K/OeaUFR0bQEgfh7gXSqXXJ8N1wqAObrAfzek7X0lxxXMkVz4p
tpNPFgEgP9jwvtYbKH2W9apmP8xxT7MJHF/FnLQVkdVdJBBU+nmrpYcEz37e7O6a
PmSdl4grWL6AG/CifSCnGvyVFsWVzLeaDgJSAXQWgalefZJzar8dki6W7HfZULo0
I9uizj52+lG2tVpIz6MUcy9k1cwOyTDl061qrD4/oD6aC67U6aS3tRPmwX3qKF7a
rvuwEBwRckmKoK1bxzd3wjzkEH/Urhom1Op8SwJ72s1ex6m5EUJ4
=QWAE
-----END PGP SIGNATURE-----
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon:
"Nothing Earth-shattering, but worthwhile fixes nonetheless:
- Disable interrupts during page-table walk in show_pte()
- Fix kexec_file_load() with 52-bit capable kernels on machines
without 52-bit addressing
- Fix MIDR matching in CPU errata handling for KVM guests
- Avoid reading MTE-specific ID registers when MTE support is
disabled"
* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: Don't read GMID_EL1 when MTE is disabled
arm64: errata: pass REVIDR when matching target implementation CPUs
arm64: trans_pgd: clone only the linear map that exists at runtime
arm64: mm: Fix the lockless page-table walk in show_pte()
This commit is contained in:
commit
3f17a52d47
|
|
@ -78,5 +78,6 @@ void __init cpuinfo_store_boot_cpu(void);
|
|||
void __init init_cpu_features(struct cpuinfo_arm64 *info);
|
||||
void update_cpu_features(int cpu, struct cpuinfo_arm64 *info,
|
||||
struct cpuinfo_arm64 *boot);
|
||||
bool gmid_el1_accessible(const struct cpuinfo_arm64 *info);
|
||||
|
||||
#endif /* __ASM_CPU_H */
|
||||
|
|
|
|||
|
|
@ -627,13 +627,6 @@ static inline bool id_aa64pfr1_mpamfrac(u64 pfr1)
|
|||
return val > 0;
|
||||
}
|
||||
|
||||
static inline bool id_aa64pfr1_mte(u64 pfr1)
|
||||
{
|
||||
u32 val = cpuid_feature_extract_unsigned_field(pfr1, ID_AA64PFR1_EL1_MTE_SHIFT);
|
||||
|
||||
return val >= ID_AA64PFR1_EL1_MTE_MTE2;
|
||||
}
|
||||
|
||||
void __init setup_boot_cpu_features(void);
|
||||
void __init setup_system_features(void);
|
||||
void __init setup_user_features(void);
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
|
|||
|
||||
for (i = 0; i < target_impl_cpu_num; i++) {
|
||||
if (__is_affected_midr_range(entry, target_impl_cpus[i].midr,
|
||||
target_impl_cpus[i].midr))
|
||||
target_impl_cpus[i].revidr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1178,6 +1178,33 @@ static bool detect_ftr_has_mpam(void)
|
|||
return id_aa64pfr0_mpam(pfr0) || id_aa64pfr1_mpamfrac(pfr1);
|
||||
}
|
||||
|
||||
bool gmid_el1_accessible(const struct cpuinfo_arm64 *info)
|
||||
{
|
||||
const struct arm64_ftr_bits *ftrp;
|
||||
s64 mte, ovr;
|
||||
u64 ftr_mask;
|
||||
|
||||
/* No ID register reflects CONFIG_ARM64_MTE. */
|
||||
if (!IS_ENABLED(CONFIG_ARM64_MTE))
|
||||
return false;
|
||||
|
||||
for (ftrp = ftr_id_aa64pfr1; ftrp->width; ftrp++) {
|
||||
if (ftrp->shift == ID_AA64PFR1_EL1_MTE_SHIFT)
|
||||
break;
|
||||
}
|
||||
|
||||
ftr_mask = arm64_ftr_mask(ftrp);
|
||||
mte = arm64_ftr_value(ftrp, info->reg_id_aa64pfr1);
|
||||
|
||||
/* The boot CPU runs before init_cpu_ftr_reg() strips unsafe overrides. */
|
||||
if ((id_aa64pfr1_override.mask & ftr_mask) == ftr_mask) {
|
||||
ovr = arm64_ftr_value(ftrp, id_aa64pfr1_override.val);
|
||||
mte = arm64_ftr_safe_value(ftrp, ovr, mte);
|
||||
}
|
||||
|
||||
return mte >= ID_AA64PFR1_EL1_MTE_MTE2;
|
||||
}
|
||||
|
||||
void __init init_cpu_features(struct cpuinfo_arm64 *info)
|
||||
{
|
||||
/* Before we start using the tables, make sure it is sorted */
|
||||
|
|
@ -1230,7 +1257,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
|
|||
init_cpu_ftr_reg(SYS_MPAMIDR_EL1, info->reg_mpamidr);
|
||||
}
|
||||
|
||||
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
|
||||
if (gmid_el1_accessible(info))
|
||||
init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
|
||||
}
|
||||
|
||||
|
|
@ -1492,11 +1519,9 @@ void update_cpu_features(int cpu,
|
|||
* they read/write depends on the GMID_EL1.BS field. Check that the
|
||||
* value is the same on all CPUs.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_ARM64_MTE) &&
|
||||
id_aa64pfr1_mte(info->reg_id_aa64pfr1)) {
|
||||
if (gmid_el1_accessible(info))
|
||||
taint |= check_update_ftr_reg(SYS_GMID_EL1, cpu,
|
||||
info->reg_gmid, boot->reg_gmid);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we don't have AArch32 at all then skip the checks entirely
|
||||
|
|
|
|||
|
|
@ -502,7 +502,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
|
|||
info->reg_id_aa64smfr0 = read_cpuid(ID_AA64SMFR0_EL1);
|
||||
info->reg_id_aa64fpfr0 = read_cpuid(ID_AA64FPFR0_EL1);
|
||||
|
||||
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
|
||||
if (gmid_el1_accessible(info))
|
||||
info->reg_gmid = read_cpuid(GMID_EL1);
|
||||
|
||||
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
|
||||
|
|
|
|||
|
|
@ -129,7 +129,8 @@ int machine_kexec_post_load(struct kimage *kimage)
|
|||
}
|
||||
|
||||
/* Create a copy of the linear map */
|
||||
rc = trans_pgd_create_copy(&info, &trans_pgd, PAGE_OFFSET, PAGE_END);
|
||||
rc = trans_pgd_create_copy(&info, &trans_pgd,
|
||||
_PAGE_OFFSET(vabits_actual), PAGE_END);
|
||||
if (rc)
|
||||
return rc;
|
||||
kimage->arch.ttbr1 = __pa(trans_pgd);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irqflags.h>
|
||||
#include <linux/kasan.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
|
@ -154,6 +155,9 @@ static void show_pte(unsigned long addr)
|
|||
pr_alert("%s pgtable: %luk pages, %llu-bit VAs, pgdp=%016lx\n",
|
||||
mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K,
|
||||
vabits_actual, mm_to_pgd_phys(mm));
|
||||
|
||||
guard(irqsave)();
|
||||
|
||||
pgdp = pgd_offset(mm, addr);
|
||||
pgd = READ_ONCE(*pgdp);
|
||||
pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd));
|
||||
|
|
@ -167,25 +171,25 @@ static void show_pte(unsigned long addr)
|
|||
if (pgd_none(pgd) || pgd_bad(pgd))
|
||||
break;
|
||||
|
||||
p4dp = p4d_offset(pgdp, addr);
|
||||
p4dp = p4d_offset_lockless(pgdp, pgd, addr);
|
||||
p4d = READ_ONCE(*p4dp);
|
||||
pr_cont(", p4d=%016llx", p4d_val(p4d));
|
||||
if (p4d_none(p4d) || p4d_bad(p4d))
|
||||
break;
|
||||
|
||||
pudp = pud_offset(p4dp, addr);
|
||||
pudp = pud_offset_lockless(p4dp, p4d, addr);
|
||||
pud = READ_ONCE(*pudp);
|
||||
pr_cont(", pud=%016llx", pud_val(pud));
|
||||
if (pud_none(pud) || pud_bad(pud))
|
||||
break;
|
||||
|
||||
pmdp = pmd_offset(pudp, addr);
|
||||
pmdp = pmd_offset_lockless(pudp, pud, addr);
|
||||
pmd = READ_ONCE(*pmdp);
|
||||
pr_cont(", pmd=%016llx", pmd_val(pmd));
|
||||
if (pmd_none(pmd) || pmd_bad(pmd))
|
||||
break;
|
||||
|
||||
ptep = pte_offset_map(pmdp, addr);
|
||||
ptep = pte_offset_map(&pmd, addr);
|
||||
if (!ptep)
|
||||
break;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user