mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
KVM: arm64: nv: Use accessors for modifying ID registers
In the interest of abstracting away the underlying storage of feature ID registers, rework the nested code to go through the accessors instead of directly iterating the id_regs array. This means we now lose the property that ID registers unknown to the nested code get zeroed, but we really ought to be handling those explicitly going forward. Link: https://lore.kernel.org/r/20240619174036.483943-6-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
parent
d7508d27dd
commit
44241f34fa
2 changed files with 116 additions and 129 deletions
|
@ -326,7 +326,6 @@ struct kvm_arch {
|
|||
* Atomic access to multiple idregs are guarded by kvm_arch.config_lock.
|
||||
*/
|
||||
#define IDREG_IDX(id) (((sys_reg_CRm(id) - 1) << 3) | sys_reg_Op2(id))
|
||||
#define IDX_IDREG(idx) sys_reg(3, 0, 0, ((idx) >> 3) + 1, (idx) & Op2_mask)
|
||||
#define KVM_ARM_ID_REG_NUM (IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1)
|
||||
u64 id_regs[KVM_ARM_ID_REG_NUM];
|
||||
|
||||
|
|
|
@ -23,25 +23,24 @@
|
|||
* This list should get updated as new features get added to the NV
|
||||
* support, and new extension to the architecture.
|
||||
*/
|
||||
static u64 limit_nv_id_reg(u32 id, u64 val)
|
||||
static void limit_nv_id_regs(struct kvm *kvm)
|
||||
{
|
||||
u64 tmp;
|
||||
u64 val, tmp;
|
||||
|
||||
switch (id) {
|
||||
case SYS_ID_AA64ISAR0_EL1:
|
||||
/* Support everything but TME, O.S. and Range TLBIs */
|
||||
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1);
|
||||
val &= ~(NV_FTR(ISAR0, TLB) |
|
||||
NV_FTR(ISAR0, TME));
|
||||
break;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1, val);
|
||||
|
||||
case SYS_ID_AA64ISAR1_EL1:
|
||||
/* Support everything but Spec Invalidation */
|
||||
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1);
|
||||
val &= ~(GENMASK_ULL(63, 56) |
|
||||
NV_FTR(ISAR1, SPECRES));
|
||||
break;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1, val);
|
||||
|
||||
case SYS_ID_AA64PFR0_EL1:
|
||||
/* No AMU, MPAM, S-EL2, RAS or SVE */
|
||||
kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1);
|
||||
val &= ~(GENMASK_ULL(55, 52) |
|
||||
NV_FTR(PFR0, AMU) |
|
||||
NV_FTR(PFR0, MPAM) |
|
||||
|
@ -55,15 +54,15 @@ static u64 limit_nv_id_reg(u32 id, u64 val)
|
|||
val |= FIELD_PREP(NV_FTR(PFR0, EL1), 0b0001);
|
||||
val |= FIELD_PREP(NV_FTR(PFR0, EL2), 0b0001);
|
||||
val |= FIELD_PREP(NV_FTR(PFR0, EL3), 0b0001);
|
||||
break;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, val);
|
||||
|
||||
case SYS_ID_AA64PFR1_EL1:
|
||||
/* Only support SSBS */
|
||||
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1);
|
||||
val &= NV_FTR(PFR1, SSBS);
|
||||
break;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1, val);
|
||||
|
||||
case SYS_ID_AA64MMFR0_EL1:
|
||||
/* Hide ECV, ExS, Secure Memory */
|
||||
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1);
|
||||
val &= ~(NV_FTR(MMFR0, ECV) |
|
||||
NV_FTR(MMFR0, EXS) |
|
||||
NV_FTR(MMFR0, TGRAN4_2) |
|
||||
|
@ -106,18 +105,18 @@ static u64 limit_nv_id_reg(u32 id, u64 val)
|
|||
val &= ~NV_FTR(MMFR0, PARANGE);
|
||||
val |= FIELD_PREP(NV_FTR(MMFR0, PARANGE), 0b0101);
|
||||
}
|
||||
break;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1, val);
|
||||
|
||||
case SYS_ID_AA64MMFR1_EL1:
|
||||
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1);
|
||||
val &= (NV_FTR(MMFR1, HCX) |
|
||||
NV_FTR(MMFR1, PAN) |
|
||||
NV_FTR(MMFR1, LO) |
|
||||
NV_FTR(MMFR1, HPDS) |
|
||||
NV_FTR(MMFR1, VH) |
|
||||
NV_FTR(MMFR1, VMIDBits));
|
||||
break;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1, val);
|
||||
|
||||
case SYS_ID_AA64MMFR2_EL1:
|
||||
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1);
|
||||
val &= ~(NV_FTR(MMFR2, BBM) |
|
||||
NV_FTR(MMFR2, TTL) |
|
||||
GENMASK_ULL(47, 44) |
|
||||
|
@ -127,17 +126,16 @@ static u64 limit_nv_id_reg(u32 id, u64 val)
|
|||
|
||||
/* Force TTL support */
|
||||
val |= FIELD_PREP(NV_FTR(MMFR2, TTL), 0b0001);
|
||||
break;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1, val);
|
||||
|
||||
case SYS_ID_AA64MMFR4_EL1:
|
||||
val = 0;
|
||||
if (!cpus_have_final_cap(ARM64_HAS_HCR_NV1))
|
||||
val |= FIELD_PREP(NV_FTR(MMFR4, E2H0),
|
||||
ID_AA64MMFR4_EL1_E2H0_NI_NV1);
|
||||
break;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val);
|
||||
|
||||
case SYS_ID_AA64DFR0_EL1:
|
||||
/* Only limited support for PMU, Debug, BPs and WPs */
|
||||
val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1);
|
||||
val &= (NV_FTR(DFR0, PMUVer) |
|
||||
NV_FTR(DFR0, WRPs) |
|
||||
NV_FTR(DFR0, BRPs) |
|
||||
|
@ -149,15 +147,7 @@ static u64 limit_nv_id_reg(u32 id, u64 val)
|
|||
val &= ~NV_FTR(DFR0, DebugVer);
|
||||
val |= FIELD_PREP(NV_FTR(DFR0, DebugVer), 0b0111);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown register, just wipe it clean */
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
kvm_set_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val);
|
||||
}
|
||||
|
||||
u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *vcpu, enum vcpu_sysreg sr)
|
||||
|
@ -202,9 +192,7 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
|
|||
goto out;
|
||||
}
|
||||
|
||||
for (int i = 0; i < KVM_ARM_ID_REG_NUM; i++)
|
||||
kvm_set_vm_id_reg(kvm, IDX_IDREG(i), limit_nv_id_reg(IDX_IDREG(i),
|
||||
kvm->arch.id_regs[i]));
|
||||
limit_nv_id_regs(kvm);
|
||||
|
||||
/* VTTBR_EL2 */
|
||||
res0 = res1 = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue