Skip to content

Commit d97e66f

Browse files
committed
KVM: arm64: nv: Reinject traps that take effect in Host EL0
Wire up the other end of traps that affect host EL0 by actually injecting them into the guest hypervisor. Skip over FGT entirely, as a cursory glance suggests no FGT is effective in host EL0. Note that kvm_inject_nested() is already equipped for handling exceptions while the VM is already in a host context. Reviewed-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent a4063b5 commit d97e66f

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ static inline bool is_hyp_ctxt(const struct kvm_vcpu *vcpu)
225225
return vcpu_has_nv(vcpu) && __is_hyp_ctxt(&vcpu->arch.ctxt);
226226
}
227227

228+
static inline bool vcpu_is_host_el0(const struct kvm_vcpu *vcpu)
229+
{
230+
return is_hyp_ctxt(vcpu) && !vcpu_is_el2(vcpu);
231+
}
232+
228233
/*
229234
* The layout of SPSR for an AArch32 state is different when observed from an
230235
* AArch64 SPSR_ELx or an AArch32 SPSR_*. This function generates the AArch32

arch/arm64/kvm/emulate-nested.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ enum trap_behaviour {
2020
BEHAVE_FORWARD_READ = BIT(0),
2121
BEHAVE_FORWARD_WRITE = BIT(1),
2222
BEHAVE_FORWARD_RW = BEHAVE_FORWARD_READ | BEHAVE_FORWARD_WRITE,
23+
24+
/* Traps that take effect in Host EL0, this is rare! */
25+
BEHAVE_FORWARD_IN_HOST_EL0 = BIT(2),
2326
};
2427

2528
struct trap_bits {
@@ -2128,11 +2131,19 @@ static u64 kvm_get_sysreg_res0(struct kvm *kvm, enum vcpu_sysreg sr)
21282131
return masks->mask[sr - __VNCR_START__].res0;
21292132
}
21302133

2131-
static bool check_fgt_bit(struct kvm *kvm, bool is_read,
2134+
static bool check_fgt_bit(struct kvm_vcpu *vcpu, bool is_read,
21322135
u64 val, const union trap_config tc)
21332136
{
2137+
struct kvm *kvm = vcpu->kvm;
21342138
enum vcpu_sysreg sr;
21352139

2140+
/*
2141+
* KVM doesn't know about any FGTs that apply to the host, and hopefully
2142+
* that'll remain the case.
2143+
*/
2144+
if (is_hyp_ctxt(vcpu))
2145+
return false;
2146+
21362147
if (tc.pol)
21372148
return (val & BIT(tc.bit));
21382149

@@ -2209,7 +2220,15 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)
22092220
* If we're not nesting, immediately return to the caller, with the
22102221
* sysreg index, should we have it.
22112222
*/
2212-
if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
2223+
if (!vcpu_has_nv(vcpu))
2224+
goto local;
2225+
2226+
/*
2227+
* There are a few traps that take effect InHost, but are constrained
2228+
* to EL0. Don't bother with computing the trap behaviour if the vCPU
2229+
* isn't in EL0.
2230+
*/
2231+
if (is_hyp_ctxt(vcpu) && !vcpu_is_host_el0(vcpu))
22132232
goto local;
22142233

22152234
switch ((enum fgt_group_id)tc.fgt) {
@@ -2255,12 +2274,14 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)
22552274
goto local;
22562275
}
22572276

2258-
if (tc.fgt != __NO_FGT_GROUP__ && check_fgt_bit(vcpu->kvm, is_read,
2259-
val, tc))
2277+
if (tc.fgt != __NO_FGT_GROUP__ && check_fgt_bit(vcpu, is_read, val, tc))
22602278
goto inject;
22612279

22622280
b = compute_trap_behaviour(vcpu, tc);
22632281

2282+
if (!(b & BEHAVE_FORWARD_IN_HOST_EL0) && vcpu_is_host_el0(vcpu))
2283+
goto local;
2284+
22642285
if (((b & BEHAVE_FORWARD_READ) && is_read) ||
22652286
((b & BEHAVE_FORWARD_WRITE) && !is_read))
22662287
goto inject;

0 commit comments

Comments
 (0)