summaryrefslogtreecommitdiffstats
path: root/include/kvm
diff options
context:
space:
mode:
authorChristoffer Dall <christoffer.dall@linaro.org>2014-06-14 21:54:51 +0200
committerChristoffer Dall <christoffer.dall@linaro.org>2014-09-18 18:44:31 -0700
commitfaa1b46c3e9f4d40359aee04ff275eea5f4cae3a (patch)
treeee960c075d6d84402892f8d1025812208b105326 /include/kvm
parentcced50c9280ef7ca1af48080707a170efa1adfa0 (diff)
downloadop-kernel-dev-faa1b46c3e9f4d40359aee04ff275eea5f4cae3a.zip
op-kernel-dev-faa1b46c3e9f4d40359aee04ff275eea5f4cae3a.tar.gz
arm/arm64: KVM: vgic: Improve handling of GICD_I{CS}PENDRn
Writes to GICD_ISPENDRn and GICD_ICPENDRn are currently not handled correctly for level-triggered interrupts. The spec states that for level-triggered interrupts, writes to the GICD_ISPENDRn activate the output of a flip-flop which is in turn or'ed with the actual input interrupt signal. Correspondingly, writes to GICD_ICPENDRn simply deactivates the output of that flip-flop, but does not (of course) affect the external input signal. Reads from GICC_IAR will also deactivate the flip-flop output. This requires us to track the state of the level-input separately from the state in the flip-flop. We therefore introduce two new variables on the distributor struct to track these two states. Astute readers may notice that this is introducing more state than required (because an OR of the two states gives you the pending state), but the remaining vgic code uses the pending bitmap for optimized operations to figure out, at the end of the day, if an interrupt is pending or not on the distributor side. Refactoring the code to consider the two state variables all the places where we currently access the precomputed pending value, did not look pretty. Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'include/kvm')
-rw-r--r--include/kvm/arm_vgic.h16
1 files changed, 15 insertions, 1 deletions
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 7d8e61f..f074539 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -140,9 +140,23 @@ struct vgic_dist {
/* Interrupt enabled (one bit per IRQ) */
struct vgic_bitmap irq_enabled;
- /* Interrupt state is pending on the distributor */
+ /* Level-triggered interrupt external input is asserted */
+ struct vgic_bitmap irq_level;
+
+ /*
+ * Interrupt state is pending on the distributor
+ */
struct vgic_bitmap irq_pending;
+ /*
+ * Tracks writes to GICD_ISPENDRn and GICD_ICPENDRn for level-triggered
+ * interrupts. Essentially holds the state of the flip-flop in
+ * Figure 4-10 on page 4-101 in ARM IHI 0048B.b.
+ * Once set, it is only cleared for level-triggered interrupts on
+ * guest ACKs (when we queue it) or writes to GICD_ICPENDRn.
+ */
+ struct vgic_bitmap irq_soft_pend;
+
/* Level-triggered interrupt queued on VCPU interface */
struct vgic_bitmap irq_queued;
OpenPOWER on IntegriCloud