Skip to content

Commit a738b5e

Browse files
committed
Merge tag 'kvmarm-fixes-for-5.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm fixes for 5.3, take #2 - Fix our system register reset so that we stop writing non-sensical values to them, and track which registers get reset instead. - Sync VMCR back from the GIC on WFI so that KVM has an exact vue of PMR. - Reevaluate state of HW-mapped, level triggered interrupts on enable.
2 parents 0e1c438 + 16e604a commit a738b5e

File tree

9 files changed

+88
-24
lines changed

9 files changed

+88
-24
lines changed

arch/arm/kvm/coproc.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -651,13 +651,22 @@ int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
651651
}
652652

653653
static void reset_coproc_regs(struct kvm_vcpu *vcpu,
654-
const struct coproc_reg *table, size_t num)
654+
const struct coproc_reg *table, size_t num,
655+
unsigned long *bmap)
655656
{
656657
unsigned long i;
657658

658659
for (i = 0; i < num; i++)
659-
if (table[i].reset)
660+
if (table[i].reset) {
661+
int reg = table[i].reg;
662+
660663
table[i].reset(vcpu, &table[i]);
664+
if (reg > 0 && reg < NR_CP15_REGS) {
665+
set_bit(reg, bmap);
666+
if (table[i].is_64bit)
667+
set_bit(reg + 1, bmap);
668+
}
669+
}
661670
}
662671

663672
static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
@@ -1432,17 +1441,15 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
14321441
{
14331442
size_t num;
14341443
const struct coproc_reg *table;
1435-
1436-
/* Catch someone adding a register without putting in reset entry. */
1437-
memset(vcpu->arch.ctxt.cp15, 0x42, sizeof(vcpu->arch.ctxt.cp15));
1444+
DECLARE_BITMAP(bmap, NR_CP15_REGS) = { 0, };
14381445

14391446
/* Generic chip reset first (so target could override). */
1440-
reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
1447+
reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs), bmap);
14411448

14421449
table = get_target_table(vcpu->arch.target, &num);
1443-
reset_coproc_regs(vcpu, table, num);
1450+
reset_coproc_regs(vcpu, table, num, bmap);
14441451

14451452
for (num = 1; num < NR_CP15_REGS; num++)
1446-
WARN(vcpu_cp15(vcpu, num) == 0x42424242,
1453+
WARN(!test_bit(num, bmap),
14471454
"Didn't reset vcpu_cp15(vcpu, %zi)", num);
14481455
}

arch/arm64/kvm/sys_regs.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
632632
*/
633633
val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
634634
| (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
635-
__vcpu_sys_reg(vcpu, PMCR_EL0) = val;
635+
__vcpu_sys_reg(vcpu, r->reg) = val;
636636
}
637637

638638
static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
@@ -981,13 +981,13 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
981981
/* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
982982
#define DBG_BCR_BVR_WCR_WVR_EL1(n) \
983983
{ SYS_DESC(SYS_DBGBVRn_EL1(n)), \
984-
trap_bvr, reset_bvr, n, 0, get_bvr, set_bvr }, \
984+
trap_bvr, reset_bvr, 0, 0, get_bvr, set_bvr }, \
985985
{ SYS_DESC(SYS_DBGBCRn_EL1(n)), \
986-
trap_bcr, reset_bcr, n, 0, get_bcr, set_bcr }, \
986+
trap_bcr, reset_bcr, 0, 0, get_bcr, set_bcr }, \
987987
{ SYS_DESC(SYS_DBGWVRn_EL1(n)), \
988-
trap_wvr, reset_wvr, n, 0, get_wvr, set_wvr }, \
988+
trap_wvr, reset_wvr, 0, 0, get_wvr, set_wvr }, \
989989
{ SYS_DESC(SYS_DBGWCRn_EL1(n)), \
990-
trap_wcr, reset_wcr, n, 0, get_wcr, set_wcr }
990+
trap_wcr, reset_wcr, 0, 0, get_wcr, set_wcr }
991991

992992
/* Macro to expand the PMEVCNTRn_EL0 register */
993993
#define PMU_PMEVCNTR_EL0(n) \
@@ -1540,7 +1540,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
15401540
{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
15411541
{ SYS_DESC(SYS_CTR_EL0), access_ctr },
15421542

1543-
{ SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, },
1543+
{ SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, PMCR_EL0 },
15441544
{ SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
15451545
{ SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, NULL, PMCNTENSET_EL0 },
15461546
{ SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, NULL, PMOVSSET_EL0 },
@@ -2254,13 +2254,19 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
22542254
}
22552255

22562256
static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
2257-
const struct sys_reg_desc *table, size_t num)
2257+
const struct sys_reg_desc *table, size_t num,
2258+
unsigned long *bmap)
22582259
{
22592260
unsigned long i;
22602261

22612262
for (i = 0; i < num; i++)
2262-
if (table[i].reset)
2263+
if (table[i].reset) {
2264+
int reg = table[i].reg;
2265+
22632266
table[i].reset(vcpu, &table[i]);
2267+
if (reg > 0 && reg < NR_SYS_REGS)
2268+
set_bit(reg, bmap);
2269+
}
22642270
}
22652271

22662272
/**
@@ -2774,18 +2780,16 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
27742780
{
27752781
size_t num;
27762782
const struct sys_reg_desc *table;
2777-
2778-
/* Catch someone adding a register without putting in reset entry. */
2779-
memset(&vcpu->arch.ctxt.sys_regs, 0x42, sizeof(vcpu->arch.ctxt.sys_regs));
2783+
DECLARE_BITMAP(bmap, NR_SYS_REGS) = { 0, };
27802784

27812785
/* Generic chip reset first (so target could override). */
2782-
reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
2786+
reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs), bmap);
27832787

27842788
table = get_target_table(vcpu->arch.target, true, &num);
2785-
reset_sys_reg_descs(vcpu, table, num);
2789+
reset_sys_reg_descs(vcpu, table, num, bmap);
27862790

27872791
for (num = 1; num < NR_SYS_REGS; num++) {
2788-
if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242,
2792+
if (WARN(!test_bit(num, bmap),
27892793
"Didn't reset __vcpu_sys_reg(%zi)\n", num))
27902794
break;
27912795
}

include/kvm/arm_vgic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
350350

351351
void kvm_vgic_load(struct kvm_vcpu *vcpu);
352352
void kvm_vgic_put(struct kvm_vcpu *vcpu);
353+
void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu);
353354

354355
#define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
355356
#define vgic_initialized(k) ((k)->arch.vgic.initialized)

virt/kvm/arm/arm.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,17 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
318318

319319
void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
320320
{
321+
/*
322+
* If we're about to block (most likely because we've just hit a
323+
* WFI), we need to sync back the state of the GIC CPU interface
324+
* so that we have the lastest PMR and group enables. This ensures
325+
* that kvm_arch_vcpu_runnable has up-to-date data to decide
326+
* whether we have pending interrupts.
327+
*/
328+
preempt_disable();
329+
kvm_vgic_vmcr_sync(vcpu);
330+
preempt_enable();
331+
321332
kvm_vgic_v4_enable_doorbell(vcpu);
322333
}
323334

virt/kvm/arm/vgic/vgic-mmio.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,22 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
113113
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
114114

115115
raw_spin_lock_irqsave(&irq->irq_lock, flags);
116+
if (vgic_irq_is_mapped_level(irq)) {
117+
bool was_high = irq->line_level;
118+
119+
/*
120+
* We need to update the state of the interrupt because
121+
* the guest might have changed the state of the device
122+
* while the interrupt was disabled at the VGIC level.
123+
*/
124+
irq->line_level = vgic_get_phys_line_level(irq);
125+
/*
126+
* Deactivate the physical interrupt so the GIC will let
127+
* us know when it is asserted again.
128+
*/
129+
if (!irq->active && was_high && !irq->line_level)
130+
vgic_irq_set_phys_active(irq, false);
131+
}
116132
irq->enabled = true;
117133
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
118134

virt/kvm/arm/vgic/vgic-v2.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,10 +484,17 @@ void vgic_v2_load(struct kvm_vcpu *vcpu)
484484
kvm_vgic_global_state.vctrl_base + GICH_APR);
485485
}
486486

487-
void vgic_v2_put(struct kvm_vcpu *vcpu)
487+
void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu)
488488
{
489489
struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
490490

491491
cpu_if->vgic_vmcr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VMCR);
492+
}
493+
494+
void vgic_v2_put(struct kvm_vcpu *vcpu)
495+
{
496+
struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
497+
498+
vgic_v2_vmcr_sync(vcpu);
492499
cpu_if->vgic_apr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_APR);
493500
}

virt/kvm/arm/vgic/vgic-v3.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,12 +662,17 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
662662
__vgic_v3_activate_traps(vcpu);
663663
}
664664

665-
void vgic_v3_put(struct kvm_vcpu *vcpu)
665+
void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
666666
{
667667
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
668668

669669
if (likely(cpu_if->vgic_sre))
670670
cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr);
671+
}
672+
673+
void vgic_v3_put(struct kvm_vcpu *vcpu)
674+
{
675+
vgic_v3_vmcr_sync(vcpu);
671676

672677
kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
673678

virt/kvm/arm/vgic/vgic.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,17 @@ void kvm_vgic_put(struct kvm_vcpu *vcpu)
919919
vgic_v3_put(vcpu);
920920
}
921921

922+
void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu)
923+
{
924+
if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
925+
return;
926+
927+
if (kvm_vgic_global_state.type == VGIC_V2)
928+
vgic_v2_vmcr_sync(vcpu);
929+
else
930+
vgic_v3_vmcr_sync(vcpu);
931+
}
932+
922933
int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
923934
{
924935
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;

virt/kvm/arm/vgic/vgic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
193193
void vgic_v2_init_lrs(void);
194194
void vgic_v2_load(struct kvm_vcpu *vcpu);
195195
void vgic_v2_put(struct kvm_vcpu *vcpu);
196+
void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu);
196197

197198
void vgic_v2_save_state(struct kvm_vcpu *vcpu);
198199
void vgic_v2_restore_state(struct kvm_vcpu *vcpu);
@@ -223,6 +224,7 @@ bool vgic_v3_check_base(struct kvm *kvm);
223224

224225
void vgic_v3_load(struct kvm_vcpu *vcpu);
225226
void vgic_v3_put(struct kvm_vcpu *vcpu);
227+
void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu);
226228

227229
bool vgic_has_its(struct kvm *kvm);
228230
int kvm_vgic_register_its_device(void);

0 commit comments

Comments
 (0)