Skip to content

Commit 50f77dc

Browse files
author
Marc Zyngier
committed
KVM: arm64: Populate level on S1PTW SEA injection
Our fault injection mechanism is mildly primitive, and doesn't really implement the architecture when it comes to reporting the level of a failing S1 PTW (we blindly report a SEA outside of a PTW). Now that we can walk the S1 page tables and look for a particular IPA in the descriptors, it is pretty easy to improve the SEA injection code. Note that we only do it for AArch64 guests, and that 32bit guests are left to their own device (oddly enough, I don't fancy writing a 32bit PTW...). Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent b8e6251 commit 50f77dc

1 file changed

Lines changed: 25 additions & 2 deletions

File tree

arch/arm64/kvm/inject_fault.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,30 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
106106
{
107107
unsigned long cpsr = *vcpu_cpsr(vcpu);
108108
bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
109-
u64 esr = 0;
109+
u64 esr = 0, fsc;
110+
int level;
111+
112+
/*
113+
* If injecting an abort from a failed S1PTW, rewalk the S1 PTs to
114+
* find the failing level. If we can't find it, assume the error was
115+
* transient and restart without changing the state.
116+
*/
117+
if (kvm_vcpu_abt_iss1tw(vcpu)) {
118+
u64 hpfar = kvm_vcpu_get_fault_ipa(vcpu);
119+
int ret;
120+
121+
if (hpfar == INVALID_GPA)
122+
return;
123+
124+
ret = __kvm_find_s1_desc_level(vcpu, addr, hpfar, &level);
125+
if (ret)
126+
return;
127+
128+
WARN_ON_ONCE(level < -1 || level > 3);
129+
fsc = ESR_ELx_FSC_SEA_TTW(level);
130+
} else {
131+
fsc = ESR_ELx_FSC_EXTABT;
132+
}
110133

111134
/* This delight is brought to you by FEAT_DoubleFault2. */
112135
if (effective_sctlr2_ease(vcpu))
@@ -133,7 +156,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
133156
if (!is_iabt)
134157
esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
135158

136-
esr |= ESR_ELx_FSC_EXTABT;
159+
esr |= fsc;
137160

138161
vcpu_write_sys_reg(vcpu, addr, exception_far_elx(vcpu));
139162
vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));

0 commit comments

Comments
 (0)