summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kvm/coproc.c23
-rw-r--r--arch/arm64/kvm/sys_regs.c32
-rw-r--r--include/kvm/arm_vgic.h1
-rw-r--r--virt/kvm/arm/arm.c11
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio.c16
-rw-r--r--virt/kvm/arm/vgic/vgic-v2.c9
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c7
-rw-r--r--virt/kvm/arm/vgic/vgic.c11
-rw-r--r--virt/kvm/arm/vgic/vgic.h2
9 files changed, 88 insertions, 24 deletions
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index d2806bcff8bb..07745ee022a1 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -651,13 +651,22 @@ int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
651} 651}
652 652
653static void reset_coproc_regs(struct kvm_vcpu *vcpu, 653static 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)
655{ 656{
656 unsigned long i; 657 unsigned long i;
657 658
658 for (i = 0; i < num; i++) 659 for (i = 0; i < num; i++)
659 if (table[i].reset) 660 if (table[i].reset) {
661 int reg = table[i].reg;
662
660 table[i].reset(vcpu, &table[i]); 663 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 }
661} 670}
662 671
663static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu) 672static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
@@ -1432,17 +1441,15 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
1432{ 1441{
1433 size_t num; 1442 size_t num;
1434 const struct coproc_reg *table; 1443 const struct coproc_reg *table;
1435 1444 DECLARE_BITMAP(bmap, NR_CP15_REGS) = { 0, };
1436 /* Catch someone adding a register without putting in reset entry. */
1437 memset(vcpu->arch.ctxt.cp15, 0x42, sizeof(vcpu->arch.ctxt.cp15));
1438 1445
1439 /* Generic chip reset first (so target could override). */ 1446 /* 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);
1441 1448
1442 table = get_target_table(vcpu->arch.target, &num); 1449 table = get_target_table(vcpu->arch.target, &num);
1443 reset_coproc_regs(vcpu, table, num); 1450 reset_coproc_regs(vcpu, table, num, bmap);
1444 1451
1445 for (num = 1; num < NR_CP15_REGS; num++) 1452 for (num = 1; num < NR_CP15_REGS; num++)
1446 WARN(vcpu_cp15(vcpu, num) == 0x42424242, 1453 WARN(!test_bit(num, bmap),
1447 "Didn't reset vcpu_cp15(vcpu, %zi)", num); 1454 "Didn't reset vcpu_cp15(vcpu, %zi)", num);
1448} 1455}
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index f26e181d881c..2071260a275b 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -632,7 +632,7 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
632 */ 632 */
633 val = ((pmcr & ~ARMV8_PMU_PMCR_MASK) 633 val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
634 | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E); 634 | (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;
636} 636}
637 637
638static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags) 638static 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,
981/* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */ 981/* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
982#define DBG_BCR_BVR_WCR_WVR_EL1(n) \ 982#define DBG_BCR_BVR_WCR_WVR_EL1(n) \
983 { SYS_DESC(SYS_DBGBVRn_EL1(n)), \ 983 { 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 }, \
985 { SYS_DESC(SYS_DBGBCRn_EL1(n)), \ 985 { 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 }, \
987 { SYS_DESC(SYS_DBGWVRn_EL1(n)), \ 987 { 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 }, \
989 { SYS_DESC(SYS_DBGWCRn_EL1(n)), \ 989 { 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 }
991 991
992/* Macro to expand the PMEVCNTRn_EL0 register */ 992/* Macro to expand the PMEVCNTRn_EL0 register */
993#define PMU_PMEVCNTR_EL0(n) \ 993#define PMU_PMEVCNTR_EL0(n) \
@@ -1540,7 +1540,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
1540 { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 }, 1540 { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
1541 { SYS_DESC(SYS_CTR_EL0), access_ctr }, 1541 { SYS_DESC(SYS_CTR_EL0), access_ctr },
1542 1542
1543 { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, }, 1543 { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, PMCR_EL0 },
1544 { SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 }, 1544 { SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
1545 { SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, NULL, PMCNTENSET_EL0 }, 1545 { SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, NULL, PMCNTENSET_EL0 },
1546 { SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, NULL, PMOVSSET_EL0 }, 1546 { SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, NULL, PMOVSSET_EL0 },
@@ -2254,13 +2254,19 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
2254} 2254}
2255 2255
2256static void reset_sys_reg_descs(struct kvm_vcpu *vcpu, 2256static 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)
2258{ 2259{
2259 unsigned long i; 2260 unsigned long i;
2260 2261
2261 for (i = 0; i < num; i++) 2262 for (i = 0; i < num; i++)
2262 if (table[i].reset) 2263 if (table[i].reset) {
2264 int reg = table[i].reg;
2265
2263 table[i].reset(vcpu, &table[i]); 2266 table[i].reset(vcpu, &table[i]);
2267 if (reg > 0 && reg < NR_SYS_REGS)
2268 set_bit(reg, bmap);
2269 }
2264} 2270}
2265 2271
2266/** 2272/**
@@ -2774,18 +2780,16 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
2774{ 2780{
2775 size_t num; 2781 size_t num;
2776 const struct sys_reg_desc *table; 2782 const struct sys_reg_desc *table;
2777 2783 DECLARE_BITMAP(bmap, NR_SYS_REGS) = { 0, };
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));
2780 2784
2781 /* Generic chip reset first (so target could override). */ 2785 /* 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);
2783 2787
2784 table = get_target_table(vcpu->arch.target, true, &num); 2788 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);
2786 2790
2787 for (num = 1; num < NR_SYS_REGS; num++) { 2791 for (num = 1; num < NR_SYS_REGS; num++) {
2788 if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242, 2792 if (WARN(!test_bit(num, bmap),
2789 "Didn't reset __vcpu_sys_reg(%zi)\n", num)) 2793 "Didn't reset __vcpu_sys_reg(%zi)\n", num))
2790 break; 2794 break;
2791 } 2795 }
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 46bbc949c20a..7a30524a80ee 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -350,6 +350,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
350 350
351void kvm_vgic_load(struct kvm_vcpu *vcpu); 351void kvm_vgic_load(struct kvm_vcpu *vcpu);
352void kvm_vgic_put(struct kvm_vcpu *vcpu); 352void kvm_vgic_put(struct kvm_vcpu *vcpu);
353void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu);
353 354
354#define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel)) 355#define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel))
355#define vgic_initialized(k) ((k)->arch.vgic.initialized) 356#define vgic_initialized(k) ((k)->arch.vgic.initialized)
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 3f7bea930acf..35a069815baf 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -318,6 +318,17 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
318 318
319void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) 319void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
320{ 320{
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
321 kvm_vgic_v4_enable_doorbell(vcpu); 332 kvm_vgic_v4_enable_doorbell(vcpu);
322} 333}
323 334
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 3ba7278fb533..44efc2ff863f 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -113,6 +113,22 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
113 struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); 113 struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
114 114
115 raw_spin_lock_irqsave(&irq->irq_lock, flags); 115 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 }
116 irq->enabled = true; 132 irq->enabled = true;
117 vgic_queue_irq_unlock(vcpu->kvm, irq, flags); 133 vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
118 134
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 6dd5ad706c92..96aab77d0471 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -484,10 +484,17 @@ void vgic_v2_load(struct kvm_vcpu *vcpu)
484 kvm_vgic_global_state.vctrl_base + GICH_APR); 484 kvm_vgic_global_state.vctrl_base + GICH_APR);
485} 485}
486 486
487void vgic_v2_put(struct kvm_vcpu *vcpu) 487void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu)
488{ 488{
489 struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2; 489 struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
490 490
491 cpu_if->vgic_vmcr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VMCR); 491 cpu_if->vgic_vmcr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VMCR);
492}
493
494void 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);
492 cpu_if->vgic_apr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_APR); 499 cpu_if->vgic_apr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_APR);
493} 500}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index c2c9ce009f63..0c653a1e5215 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -662,12 +662,17 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
662 __vgic_v3_activate_traps(vcpu); 662 __vgic_v3_activate_traps(vcpu);
663} 663}
664 664
665void vgic_v3_put(struct kvm_vcpu *vcpu) 665void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
666{ 666{
667 struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; 667 struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
668 668
669 if (likely(cpu_if->vgic_sre)) 669 if (likely(cpu_if->vgic_sre))
670 cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr); 670 cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr);
671}
672
673void vgic_v3_put(struct kvm_vcpu *vcpu)
674{
675 vgic_v3_vmcr_sync(vcpu);
671 676
672 kvm_call_hyp(__vgic_v3_save_aprs, vcpu); 677 kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
673 678
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 04786c8ec77e..13d4b38a94ec 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -919,6 +919,17 @@ void kvm_vgic_put(struct kvm_vcpu *vcpu)
919 vgic_v3_put(vcpu); 919 vgic_v3_put(vcpu);
920} 920}
921 921
922void 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
922int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu) 933int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
923{ 934{
924 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 935 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 3b7525deec80..797e05004d80 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -193,6 +193,7 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
193void vgic_v2_init_lrs(void); 193void vgic_v2_init_lrs(void);
194void vgic_v2_load(struct kvm_vcpu *vcpu); 194void vgic_v2_load(struct kvm_vcpu *vcpu);
195void vgic_v2_put(struct kvm_vcpu *vcpu); 195void vgic_v2_put(struct kvm_vcpu *vcpu);
196void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu);
196 197
197void vgic_v2_save_state(struct kvm_vcpu *vcpu); 198void vgic_v2_save_state(struct kvm_vcpu *vcpu);
198void vgic_v2_restore_state(struct kvm_vcpu *vcpu); 199void vgic_v2_restore_state(struct kvm_vcpu *vcpu);
@@ -223,6 +224,7 @@ bool vgic_v3_check_base(struct kvm *kvm);
223 224
224void vgic_v3_load(struct kvm_vcpu *vcpu); 225void vgic_v3_load(struct kvm_vcpu *vcpu);
225void vgic_v3_put(struct kvm_vcpu *vcpu); 226void vgic_v3_put(struct kvm_vcpu *vcpu);
227void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu);
226 228
227bool vgic_has_its(struct kvm *kvm); 229bool vgic_has_its(struct kvm *kvm);
228int kvm_vgic_register_its_device(void); 230int kvm_vgic_register_its_device(void);