From: Oliver Upton <oliver.upton@linux.dev> mainline inclusion from mainline-v6.11-rc1 commit 97ca3fcc15cc0b19ccacb56d25545f1df080fbc0 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBN3WI CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------------------------------------------------------------ IDREG() expands to the storage of a particular ID reg, which can be useful for handling both reads and writes. However, outside of a select few situations, the ID registers should be considered read only. Replace current readers with a new macro that expands to the value of the field rather than the field itself. Reviewed-by: Sebastian Ott <sebott@redhat.com> Link: https://lore.kernel.org/r/20240619174036.483943-4-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev> --- arch/arm64/include/asm/kvm_host.h | 14 ++++++++++++++ arch/arm64/kvm/pmu-emul.c | 4 ++-- arch/arm64/kvm/rme.c | 2 +- arch/arm64/kvm/sys_regs.c | 8 ++++---- include/kvm/arm_pmu.h | 2 +- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 10b17aa8ec1c..cda7d2376714 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1328,6 +1328,20 @@ extern unsigned int twedel; void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu); bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu); +static inline u64 *__vm_id_reg(struct kvm_arch *ka, u32 reg) +{ + switch (reg) { + case sys_reg(3, 0, 0, 1, 0) ... sys_reg(3, 0, 0, 7, 7): + return &ka->id_regs[IDREG_IDX(reg)]; + default: + WARN_ON_ONCE(1); + return NULL; + } +} + +#define kvm_read_vm_id_reg(kvm, reg) \ + ({ u64 __val = *__vm_id_reg(&(kvm)->arch, reg); __val; }) + extern bool force_wfi_trap; extern bool kvm_ncsnp_support; extern bool kvm_dvmbm_support; diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 7f4acb4361a5..2cf3c4462b64 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -56,7 +56,7 @@ static u32 __kvm_pmu_event_mask(unsigned int pmuver) static u32 kvm_pmu_event_mask(struct kvm *kvm) { - u64 dfr0 = IDREG(kvm, SYS_ID_AA64DFR0_EL1); + u64 dfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1); u8 pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer, dfr0); return __kvm_pmu_event_mask(pmuver); @@ -66,7 +66,7 @@ u64 kvm_pmu_evtyper_mask(struct kvm *kvm) { u64 mask = ARMV8_PMU_EXCLUDE_EL1 | ARMV8_PMU_EXCLUDE_EL0 | kvm_pmu_event_mask(kvm); - u64 pfr0 = IDREG(kvm, SYS_ID_AA64PFR0_EL1); + u64 pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1); if (SYS_FIELD_GET(ID_AA64PFR0_EL1, EL2, pfr0)) mask |= ARMV8_PMU_INCLUDE_EL2; diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c index d60f99899bb8..59671460ff0a 100644 --- a/arch/arm64/kvm/rme.c +++ b/arch/arm64/kvm/rme.c @@ -458,7 +458,7 @@ static int realm_create_rd(struct kvm *kvm) void *rd = NULL; phys_addr_t rd_phys, params_phys; size_t pgd_size = kvm_pgtable_stage2_pgd_size(kvm->arch.vtcr); - u64 dfr0 = IDREG(kvm, SYS_ID_AA64DFR0_EL1); + u64 dfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1); int i, r; int rtt_num_start; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2046bc18ae4b..289a723de53c 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -395,7 +395,7 @@ static bool trap_loregion(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - u64 val = IDREG(vcpu->kvm, SYS_ID_AA64MMFR1_EL1); + u64 val = kvm_read_vm_id_reg(vcpu->kvm, SYS_ID_AA64MMFR1_EL1); u32 sr = reg_to_encoding(r); if (!(val & (0xfUL << ID_AA64MMFR1_EL1_LO_SHIFT))) { @@ -1453,7 +1453,7 @@ static u64 kvm_read_sanitised_id_reg(struct kvm_vcpu *vcpu, static u64 read_id_reg(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { - return IDREG(vcpu->kvm, reg_to_encoding(r)); + return kvm_read_vm_id_reg(vcpu->kvm, reg_to_encoding(r)); } static bool is_feature_id_reg(u32 encoding) @@ -2778,8 +2778,8 @@ static bool trap_dbgdidr(struct kvm_vcpu *vcpu, if (p->is_write) { return ignore_write(vcpu, p); } else { - u64 dfr = IDREG(vcpu->kvm, SYS_ID_AA64DFR0_EL1); - u64 pfr = IDREG(vcpu->kvm, SYS_ID_AA64PFR0_EL1); + u64 dfr = kvm_read_vm_id_reg(vcpu->kvm, SYS_ID_AA64DFR0_EL1); + u64 pfr = kvm_read_vm_id_reg(vcpu->kvm, SYS_ID_AA64PFR0_EL1); u32 el3 = !!SYS_FIELD_GET(ID_AA64PFR0_EL1, EL3, pfr); p->regval = ((SYS_FIELD_GET(ID_AA64DFR0_EL1, WRPs, dfr) << 28) | diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h index 6906a7b77911..04ea570496d8 100644 --- a/include/kvm/arm_pmu.h +++ b/include/kvm/arm_pmu.h @@ -96,7 +96,7 @@ void kvm_vcpu_pmu_resync_el0(void); * Evaluates as true when emulating PMUv3p5, and false otherwise. */ #define kvm_pmu_is_3p5(vcpu) ({ \ - u64 val = IDREG(vcpu->kvm, SYS_ID_AA64DFR0_EL1); \ + u64 val = kvm_read_vm_id_reg(vcpu->kvm, SYS_ID_AA64DFR0_EL1); \ u8 pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer, val); \ \ pmuver >= ID_AA64DFR0_EL1_PMUVer_V3P5; \ -- 2.33.0