Skip to content

Commit 2843cae

Browse files
Sebastian Ottoupton
authored andcommitted
KVM: arm64: Treat CTR_EL0 as a VM feature ID register
CTR_EL0 is currently handled as an invariant register, thus guests will be presented with the host value of that register. Add emulation for CTR_EL0 based on a per VM value. Userspace can switch off DIC and IDC bits and reduce DminLine and IminLine sizes. Naturally, ensure CTR_EL0 is trapped (HCR_EL2.TID2=1) any time that a VM's CTR_EL0 differs from hardware. Signed-off-by: Sebastian Ott <[email protected]> Reviewed-by: Shaoqin Huang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent f1ff3fc commit 2843cae

File tree

2 files changed

+14
-10
lines changed

2 files changed

+14
-10
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ struct kvm_arch {
329329
#define KVM_ARM_ID_REG_NUM (IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1)
330330
u64 id_regs[KVM_ARM_ID_REG_NUM];
331331

332+
u64 ctr_el0;
333+
332334
/* Masks for VNCR-baked sysregs */
333335
struct kvm_sysreg_masks *sysreg_masks;
334336

@@ -1335,6 +1337,8 @@ static inline u64 *__vm_id_reg(struct kvm_arch *ka, u32 reg)
13351337
switch (reg) {
13361338
case sys_reg(3, 0, 0, 1, 0) ... sys_reg(3, 0, 0, 7, 7):
13371339
return &ka->id_regs[IDREG_IDX(reg)];
1340+
case SYS_CTR_EL0:
1341+
return &ka->ctr_el0;
13381342
default:
13391343
WARN_ON_ONCE(1);
13401344
return NULL;

arch/arm64/kvm/sys_regs.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,9 @@ static bool is_feature_id_reg(u32 encoding)
15831583
*/
15841584
static inline bool is_vm_ftr_id_reg(u32 id)
15851585
{
1586+
if (id == SYS_CTR_EL0)
1587+
return true;
1588+
15861589
return (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 &&
15871590
sys_reg_CRn(id) == 0 && sys_reg_CRm(id) >= 1 &&
15881591
sys_reg_CRm(id) < 8);
@@ -1898,7 +1901,7 @@ static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
18981901
if (p->is_write)
18991902
return write_to_read_only(vcpu, p, r);
19001903

1901-
p->regval = read_sanitised_ftr_reg(SYS_CTR_EL0);
1904+
p->regval = kvm_read_vm_id_reg(vcpu->kvm, SYS_CTR_EL0);
19021905
return true;
19031906
}
19041907

@@ -2487,7 +2490,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
24872490
{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
24882491
{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
24892492
{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
2490-
{ SYS_DESC(SYS_CTR_EL0), access_ctr },
2493+
ID_WRITABLE(CTR_EL0, CTR_EL0_DIC_MASK |
2494+
CTR_EL0_IDC_MASK |
2495+
CTR_EL0_DminLine_MASK |
2496+
CTR_EL0_IminLine_MASK),
24912497
{ SYS_DESC(SYS_SVCR), undef_access },
24922498

24932499
{ PMU_SYS_REG(PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr,
@@ -3725,18 +3731,11 @@ FUNCTION_INVARIANT(midr_el1)
37253731
FUNCTION_INVARIANT(revidr_el1)
37263732
FUNCTION_INVARIANT(aidr_el1)
37273733

3728-
static u64 get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r)
3729-
{
3730-
((struct sys_reg_desc *)r)->val = read_sanitised_ftr_reg(SYS_CTR_EL0);
3731-
return ((struct sys_reg_desc *)r)->val;
3732-
}
3733-
37343734
/* ->val is filled in by kvm_sys_reg_table_init() */
37353735
static struct sys_reg_desc invariant_sys_regs[] __ro_after_init = {
37363736
{ SYS_DESC(SYS_MIDR_EL1), NULL, get_midr_el1 },
37373737
{ SYS_DESC(SYS_REVIDR_EL1), NULL, get_revidr_el1 },
37383738
{ SYS_DESC(SYS_AIDR_EL1), NULL, get_aidr_el1 },
3739-
{ SYS_DESC(SYS_CTR_EL0), NULL, get_ctr_el0 },
37403739
};
37413740

37423741
static int get_invariant_sys_reg(u64 id, u64 __user *uaddr)
@@ -4086,7 +4085,8 @@ static void vcpu_set_hcr(struct kvm_vcpu *vcpu)
40864085
vcpu->arch.hcr_el2 |= HCR_FWB;
40874086

40884087
if (cpus_have_final_cap(ARM64_HAS_EVT) &&
4089-
!cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE))
4088+
!cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE) &&
4089+
kvm_read_vm_id_reg(kvm, SYS_CTR_EL0) == read_sanitised_ftr_reg(SYS_CTR_EL0))
40904090
vcpu->arch.hcr_el2 |= HCR_TID4;
40914091
else
40924092
vcpu->arch.hcr_el2 |= HCR_TID2;

0 commit comments

Comments
 (0)