Skip to content

Commit bc2e325

Browse files
committed
Merge branch kvm-arm64/nv-tcr2 into kvmarm/next
* kvm-arm64/nv-tcr2: : Fixes to the handling of TCR_EL1, courtesy of Marc Zyngier : : Series addresses a couple gaps that are present in KVM (from cover : letter): : : - VM configuration: HCRX_EL2.TCR2En is forced to 1, and we blindly : save/restore stuff. : : - trap bit description and routing: none, obviously, since we make a : point in not trapping. KVM: arm64: Honor trap routing for TCR2_EL1 KVM: arm64: Make PIR{,E0}_EL1 save/restore conditional on FEAT_TCRX KVM: arm64: Make TCR2_EL1 save/restore dependent on the VM features KVM: arm64: Get rid of HCRX_GUEST_FLAGS KVM: arm64: Correctly honor the presence of FEAT_TCRX Signed-off-by: Oliver Upton <[email protected]>
2 parents 8c2899e + 91e9cc7 commit bc2e325

File tree

4 files changed

+54
-12
lines changed

4 files changed

+54
-12
lines changed

arch/arm64/include/asm/kvm_arm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@
102102
#define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC)
103103
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
104104

105-
#define HCRX_GUEST_FLAGS (HCRX_EL2_SMPME | HCRX_EL2_TCR2En)
106105
#define HCRX_HOST_FLAGS (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En | HCRX_EL2_EnFPM)
107106

108107
/* TCR_EL2 Registers bits */

arch/arm64/kvm/emulate-nested.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ enum cgt_group_id {
8383
CGT_CPTR_TAM,
8484
CGT_CPTR_TCPAC,
8585

86+
CGT_HCRX_TCR2En,
87+
8688
/*
8789
* Anything after this point is a combination of coarse trap
8890
* controls, which must all be evaluated to decide what to do.
@@ -93,6 +95,7 @@ enum cgt_group_id {
9395
CGT_HCR_TTLB_TTLBIS,
9496
CGT_HCR_TTLB_TTLBOS,
9597
CGT_HCR_TVM_TRVM,
98+
CGT_HCR_TVM_TRVM_HCRX_TCR2En,
9699
CGT_HCR_TPU_TICAB,
97100
CGT_HCR_TPU_TOCU,
98101
CGT_HCR_NV1_nNV2_ENSCXT,
@@ -369,6 +372,12 @@ static const struct trap_bits coarse_trap_bits[] = {
369372
.mask = CPTR_EL2_TCPAC,
370373
.behaviour = BEHAVE_FORWARD_ANY,
371374
},
375+
[CGT_HCRX_TCR2En] = {
376+
.index = HCRX_EL2,
377+
.value = 0,
378+
.mask = HCRX_EL2_TCR2En,
379+
.behaviour = BEHAVE_FORWARD_ANY,
380+
},
372381
};
373382

374383
#define MCB(id, ...) \
@@ -383,6 +392,8 @@ static const enum cgt_group_id *coarse_control_combo[] = {
383392
MCB(CGT_HCR_TTLB_TTLBIS, CGT_HCR_TTLB, CGT_HCR_TTLBIS),
384393
MCB(CGT_HCR_TTLB_TTLBOS, CGT_HCR_TTLB, CGT_HCR_TTLBOS),
385394
MCB(CGT_HCR_TVM_TRVM, CGT_HCR_TVM, CGT_HCR_TRVM),
395+
MCB(CGT_HCR_TVM_TRVM_HCRX_TCR2En,
396+
CGT_HCR_TVM, CGT_HCR_TRVM, CGT_HCRX_TCR2En),
386397
MCB(CGT_HCR_TPU_TICAB, CGT_HCR_TPU, CGT_HCR_TICAB),
387398
MCB(CGT_HCR_TPU_TOCU, CGT_HCR_TPU, CGT_HCR_TOCU),
388399
MCB(CGT_HCR_NV1_nNV2_ENSCXT, CGT_HCR_NV1_nNV2, CGT_HCR_ENSCXT),
@@ -660,6 +671,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
660671
SR_TRAP(SYS_MAIR_EL1, CGT_HCR_TVM_TRVM),
661672
SR_TRAP(SYS_AMAIR_EL1, CGT_HCR_TVM_TRVM),
662673
SR_TRAP(SYS_CONTEXTIDR_EL1, CGT_HCR_TVM_TRVM),
674+
SR_TRAP(SYS_TCR2_EL1, CGT_HCR_TVM_TRVM_HCRX_TCR2En),
663675
SR_TRAP(SYS_DC_ZVA, CGT_HCR_TDZ),
664676
SR_TRAP(SYS_DC_GVA, CGT_HCR_TDZ),
665677
SR_TRAP(SYS_DC_GZVA, CGT_HCR_TDZ),
@@ -1162,6 +1174,7 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
11621174
SR_FGT(SYS_TPIDRRO_EL0, HFGxTR, TPIDRRO_EL0, 1),
11631175
SR_FGT(SYS_TPIDR_EL1, HFGxTR, TPIDR_EL1, 1),
11641176
SR_FGT(SYS_TCR_EL1, HFGxTR, TCR_EL1, 1),
1177+
SR_FGT(SYS_TCR2_EL1, HFGxTR, TCR_EL1, 1),
11651178
SR_FGT(SYS_SCXTNUM_EL0, HFGxTR, SCXTNUM_EL0, 1),
11661179
SR_FGT(SYS_SCXTNUM_EL1, HFGxTR, SCXTNUM_EL1, 1),
11671180
SR_FGT(SYS_SCTLR_EL1, HFGxTR, SCTLR_EL1, 1),

arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,32 @@ static inline bool ctxt_has_s1pie(struct kvm_cpu_context *ctxt)
5555
return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, S1PIE, IMP);
5656
}
5757

58+
static inline bool ctxt_has_tcrx(struct kvm_cpu_context *ctxt)
59+
{
60+
struct kvm_vcpu *vcpu;
61+
62+
if (!cpus_have_final_cap(ARM64_HAS_TCR2))
63+
return false;
64+
65+
vcpu = ctxt_to_vcpu(ctxt);
66+
return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, TCRX, IMP);
67+
}
68+
5869
static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
5970
{
6071
ctxt_sys_reg(ctxt, SCTLR_EL1) = read_sysreg_el1(SYS_SCTLR);
6172
ctxt_sys_reg(ctxt, CPACR_EL1) = read_sysreg_el1(SYS_CPACR);
6273
ctxt_sys_reg(ctxt, TTBR0_EL1) = read_sysreg_el1(SYS_TTBR0);
6374
ctxt_sys_reg(ctxt, TTBR1_EL1) = read_sysreg_el1(SYS_TTBR1);
6475
ctxt_sys_reg(ctxt, TCR_EL1) = read_sysreg_el1(SYS_TCR);
65-
if (cpus_have_final_cap(ARM64_HAS_TCR2))
76+
if (ctxt_has_tcrx(ctxt)) {
6677
ctxt_sys_reg(ctxt, TCR2_EL1) = read_sysreg_el1(SYS_TCR2);
78+
79+
if (ctxt_has_s1pie(ctxt)) {
80+
ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR);
81+
ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0);
82+
}
83+
}
6784
ctxt_sys_reg(ctxt, ESR_EL1) = read_sysreg_el1(SYS_ESR);
6885
ctxt_sys_reg(ctxt, AFSR0_EL1) = read_sysreg_el1(SYS_AFSR0);
6986
ctxt_sys_reg(ctxt, AFSR1_EL1) = read_sysreg_el1(SYS_AFSR1);
@@ -73,10 +90,6 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
7390
ctxt_sys_reg(ctxt, CONTEXTIDR_EL1) = read_sysreg_el1(SYS_CONTEXTIDR);
7491
ctxt_sys_reg(ctxt, AMAIR_EL1) = read_sysreg_el1(SYS_AMAIR);
7592
ctxt_sys_reg(ctxt, CNTKCTL_EL1) = read_sysreg_el1(SYS_CNTKCTL);
76-
if (ctxt_has_s1pie(ctxt)) {
77-
ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR);
78-
ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0);
79-
}
8093
ctxt_sys_reg(ctxt, PAR_EL1) = read_sysreg_par();
8194
ctxt_sys_reg(ctxt, TPIDR_EL1) = read_sysreg(tpidr_el1);
8295

@@ -138,8 +151,14 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
138151
write_sysreg_el1(ctxt_sys_reg(ctxt, CPACR_EL1), SYS_CPACR);
139152
write_sysreg_el1(ctxt_sys_reg(ctxt, TTBR0_EL1), SYS_TTBR0);
140153
write_sysreg_el1(ctxt_sys_reg(ctxt, TTBR1_EL1), SYS_TTBR1);
141-
if (cpus_have_final_cap(ARM64_HAS_TCR2))
154+
if (ctxt_has_tcrx(ctxt)) {
142155
write_sysreg_el1(ctxt_sys_reg(ctxt, TCR2_EL1), SYS_TCR2);
156+
157+
if (ctxt_has_s1pie(ctxt)) {
158+
write_sysreg_el1(ctxt_sys_reg(ctxt, PIR_EL1), SYS_PIR);
159+
write_sysreg_el1(ctxt_sys_reg(ctxt, PIRE0_EL1), SYS_PIRE0);
160+
}
161+
}
143162
write_sysreg_el1(ctxt_sys_reg(ctxt, ESR_EL1), SYS_ESR);
144163
write_sysreg_el1(ctxt_sys_reg(ctxt, AFSR0_EL1), SYS_AFSR0);
145164
write_sysreg_el1(ctxt_sys_reg(ctxt, AFSR1_EL1), SYS_AFSR1);
@@ -149,10 +168,6 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
149168
write_sysreg_el1(ctxt_sys_reg(ctxt, CONTEXTIDR_EL1), SYS_CONTEXTIDR);
150169
write_sysreg_el1(ctxt_sys_reg(ctxt, AMAIR_EL1), SYS_AMAIR);
151170
write_sysreg_el1(ctxt_sys_reg(ctxt, CNTKCTL_EL1), SYS_CNTKCTL);
152-
if (ctxt_has_s1pie(ctxt)) {
153-
write_sysreg_el1(ctxt_sys_reg(ctxt, PIR_EL1), SYS_PIR);
154-
write_sysreg_el1(ctxt_sys_reg(ctxt, PIRE0_EL1), SYS_PIRE0);
155-
}
156171
write_sysreg(ctxt_sys_reg(ctxt, PAR_EL1), par_el1);
157172
write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL1), tpidr_el1);
158173

arch/arm64/kvm/sys_regs.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
384384
bool was_enabled = vcpu_has_cache_enabled(vcpu);
385385
u64 val, mask, shift;
386386

387+
if (reg_to_encoding(r) == SYS_TCR2_EL1 &&
388+
!kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, TCRX, IMP)) {
389+
kvm_inject_undefined(vcpu);
390+
return false;
391+
}
392+
387393
BUG_ON(!p->is_write);
388394

389395
get_access_mask(r, &mask, &shift);
@@ -4541,10 +4547,19 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
45414547
vcpu_set_hcr(vcpu);
45424548

45434549
if (cpus_have_final_cap(ARM64_HAS_HCX)) {
4544-
vcpu->arch.hcrx_el2 = HCRX_GUEST_FLAGS;
4550+
/*
4551+
* In general, all HCRX_EL2 bits are gated by a feature.
4552+
* The only reason we can set SMPME without checking any
4553+
* feature is that its effects are not directly observable
4554+
* from the guest.
4555+
*/
4556+
vcpu->arch.hcrx_el2 = HCRX_EL2_SMPME;
45454557

45464558
if (kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
45474559
vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
4560+
4561+
if (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP))
4562+
vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En;
45484563
}
45494564

45504565
if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags))

0 commit comments

Comments
 (0)