Skip to content

Commit 47f1574

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/nv-misc-6.18 into kvmarm-master/next
* kvm-arm64/nv-misc-6.18: : . : Various NV-related fixes: : : - Relax KVM's SError injection to consider that HCR_EL2.AMO's : effective value is 1 when HCR_EL2.{E2H,TGE)=={1,0}. : (20250918164632.410404-1-oliver.upton@linux.dev) : : - Allow userspace to disable some S2 base granule sizes : (20250918165505.415017-1-oliver.upton@linux.dev) : . KVM: arm64: nv: Allow userspace to de-feature stage-2 TGRANs KVM: arm64: nv: Treat AMO as 1 when at EL2 and {E2H,TGE} = {1, 0} Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents 46bd74e + 5aea409 commit 47f1574

2 files changed

Lines changed: 32 additions & 5 deletions

File tree

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,20 @@ static inline bool vcpu_el2_tge_is_set(const struct kvm_vcpu *vcpu)
220220

221221
static inline bool vcpu_el2_amo_is_set(const struct kvm_vcpu *vcpu)
222222
{
223+
/*
224+
* DDI0487L.b Known Issue D22105
225+
*
226+
* When executing at EL2 and HCR_EL2.{E2H,TGE} = {1, 0} it is
227+
* IMPLEMENTATION DEFINED whether the effective value of HCR_EL2.AMO
228+
* is the value programmed or 1.
229+
*
230+
* Make the implementation choice of treating the effective value as 1 as
231+
* we cannot subsequently catch changes to TGE or AMO that would
232+
* otherwise lead to the SError becoming deliverable.
233+
*/
234+
if (vcpu_is_el2(vcpu) && vcpu_el2_e2h_is_set(vcpu) && !vcpu_el2_tge_is_set(vcpu))
235+
return true;
236+
223237
return ctxt_sys_reg(&vcpu->arch.ctxt, HCR_EL2) & HCR_AMO;
224238
}
225239

arch/arm64/kvm/sys_regs.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,16 +2173,29 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
21732173
return set_id_reg(vcpu, rd, user_val);
21742174
}
21752175

2176+
/*
2177+
* Allow userspace to de-feature a stage-2 translation granule but prevent it
2178+
* from claiming the impossible.
2179+
*/
2180+
#define tgran2_val_allowed(tg, safe, user) \
2181+
({ \
2182+
u8 __s = SYS_FIELD_GET(ID_AA64MMFR0_EL1, tg, safe); \
2183+
u8 __u = SYS_FIELD_GET(ID_AA64MMFR0_EL1, tg, user); \
2184+
\
2185+
__s == __u || __u == ID_AA64MMFR0_EL1_##tg##_NI; \
2186+
})
2187+
21762188
static int set_id_aa64mmfr0_el1(struct kvm_vcpu *vcpu,
21772189
const struct sys_reg_desc *rd, u64 user_val)
21782190
{
21792191
u64 sanitized_val = kvm_read_sanitised_id_reg(vcpu, rd);
2180-
u64 tgran2_mask = ID_AA64MMFR0_EL1_TGRAN4_2_MASK |
2181-
ID_AA64MMFR0_EL1_TGRAN16_2_MASK |
2182-
ID_AA64MMFR0_EL1_TGRAN64_2_MASK;
21832192

2184-
if (vcpu_has_nv(vcpu) &&
2185-
((sanitized_val & tgran2_mask) != (user_val & tgran2_mask)))
2193+
if (!vcpu_has_nv(vcpu))
2194+
return set_id_reg(vcpu, rd, user_val);
2195+
2196+
if (!tgran2_val_allowed(TGRAN4_2, sanitized_val, user_val) ||
2197+
!tgran2_val_allowed(TGRAN16_2, sanitized_val, user_val) ||
2198+
!tgran2_val_allowed(TGRAN64_2, sanitized_val, user_val))
21862199
return -EINVAL;
21872200

21882201
return set_id_reg(vcpu, rd, user_val);

0 commit comments

Comments
 (0)