Skip to content

Commit 17179d0

Browse files
committed
Merge tag 'kvmarm-fixes-5.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 fixes for 5.17, take #1 - Correctly update the shadow register on exception injection when running in nVHE mode - Correctly use the mm_ops indirection when performing cache invalidation from the page-table walker - Restrict the vgic-v3 workaround for SEIS to the two known broken implementations
2 parents 6a0c617 + 2785830 commit 17179d0

File tree

4 files changed

+28
-15
lines changed

4 files changed

+28
-15
lines changed

arch/arm64/kvm/hyp/exception.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ static inline void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
3838

3939
static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, u64 val)
4040
{
41-
write_sysreg_el1(val, SYS_SPSR);
41+
if (has_vhe())
42+
write_sysreg_el1(val, SYS_SPSR);
43+
else
44+
__vcpu_sys_reg(vcpu, SPSR_EL1) = val;
4245
}
4346

4447
static void __vcpu_write_spsr_abt(struct kvm_vcpu *vcpu, u64 val)

arch/arm64/kvm/hyp/pgtable.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -983,13 +983,9 @@ static int stage2_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
983983
*/
984984
stage2_put_pte(ptep, mmu, addr, level, mm_ops);
985985

986-
if (need_flush) {
987-
kvm_pte_t *pte_follow = kvm_pte_follow(pte, mm_ops);
988-
989-
dcache_clean_inval_poc((unsigned long)pte_follow,
990-
(unsigned long)pte_follow +
991-
kvm_granule_size(level));
992-
}
986+
if (need_flush && mm_ops->dcache_clean_inval_poc)
987+
mm_ops->dcache_clean_inval_poc(kvm_pte_follow(pte, mm_ops),
988+
kvm_granule_size(level));
993989

994990
if (childp)
995991
mm_ops->put_page(childp);
@@ -1151,15 +1147,13 @@ static int stage2_flush_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
11511147
struct kvm_pgtable *pgt = arg;
11521148
struct kvm_pgtable_mm_ops *mm_ops = pgt->mm_ops;
11531149
kvm_pte_t pte = *ptep;
1154-
kvm_pte_t *pte_follow;
11551150

11561151
if (!kvm_pte_valid(pte) || !stage2_pte_cacheable(pgt, pte))
11571152
return 0;
11581153

1159-
pte_follow = kvm_pte_follow(pte, mm_ops);
1160-
dcache_clean_inval_poc((unsigned long)pte_follow,
1161-
(unsigned long)pte_follow +
1162-
kvm_granule_size(level));
1154+
if (mm_ops->dcache_clean_inval_poc)
1155+
mm_ops->dcache_clean_inval_poc(kvm_pte_follow(pte, mm_ops),
1156+
kvm_granule_size(level));
11631157
return 0;
11641158
}
11651159

arch/arm64/kvm/hyp/vgic-v3-sr.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,9 @@ static void __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
983983
val = ((vtr >> 29) & 7) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
984984
/* IDbits */
985985
val |= ((vtr >> 23) & 7) << ICC_CTLR_EL1_ID_BITS_SHIFT;
986+
/* SEIS */
987+
if (kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_SEIS_MASK)
988+
val |= BIT(ICC_CTLR_EL1_SEIS_SHIFT);
986989
/* A3V */
987990
val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
988991
/* EOImode */

arch/arm64/kvm/vgic/vgic-v3.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,18 @@ static int __init early_gicv4_enable(char *buf)
609609
}
610610
early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
611611

612+
static const struct midr_range broken_seis[] = {
613+
MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
614+
MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
615+
{},
616+
};
617+
618+
static bool vgic_v3_broken_seis(void)
619+
{
620+
return ((kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_SEIS_MASK) &&
621+
is_midr_in_range_list(read_cpuid_id(), broken_seis));
622+
}
623+
612624
/**
613625
* vgic_v3_probe - probe for a VGICv3 compatible interrupt controller
614626
* @info: pointer to the GIC description
@@ -676,9 +688,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
676688
group1_trap = true;
677689
}
678690

679-
if (kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_SEIS_MASK) {
680-
kvm_info("GICv3 with locally generated SEI\n");
691+
if (vgic_v3_broken_seis()) {
692+
kvm_info("GICv3 with broken locally generated SEI\n");
681693

694+
kvm_vgic_global_state.ich_vtr_el2 &= ~ICH_VTR_SEIS_MASK;
682695
group0_trap = true;
683696
group1_trap = true;
684697
if (ich_vtr_el2 & ICH_VTR_TDS_MASK)

0 commit comments

Comments
 (0)