diff options
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio-v2.c | 4 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio.c | 56 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio.h | 11 |
3 files changed, 69 insertions, 2 deletions
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index d812c933708a..d5355b502f4a 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c | |||
@@ -72,10 +72,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = { | |||
72 | vgic_mmio_read_rao, vgic_mmio_write_wi, 1, | 72 | vgic_mmio_read_rao, vgic_mmio_write_wi, 1, |
73 | VGIC_ACCESS_32bit), | 73 | VGIC_ACCESS_32bit), |
74 | REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET, | 74 | REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET, |
75 | vgic_mmio_read_raz, vgic_mmio_write_wi, 1, | 75 | vgic_mmio_read_enable, vgic_mmio_write_senable, 1, |
76 | VGIC_ACCESS_32bit), | 76 | VGIC_ACCESS_32bit), |
77 | REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR, | 77 | REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR, |
78 | vgic_mmio_read_raz, vgic_mmio_write_wi, 1, | 78 | vgic_mmio_read_enable, vgic_mmio_write_cenable, 1, |
79 | VGIC_ACCESS_32bit), | 79 | VGIC_ACCESS_32bit), |
80 | REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET, | 80 | REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET, |
81 | vgic_mmio_read_raz, vgic_mmio_write_wi, 1, | 81 | vgic_mmio_read_raz, vgic_mmio_write_wi, 1, |
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c index 1a977654681d..32ed8dbd93d6 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.c +++ b/virt/kvm/arm/vgic/vgic-mmio.c | |||
@@ -39,6 +39,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, | |||
39 | /* Ignore */ | 39 | /* Ignore */ |
40 | } | 40 | } |
41 | 41 | ||
42 | /* | ||
43 | * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value | ||
44 | * of the enabled bit, so there is only one function for both here. | ||
45 | */ | ||
46 | unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu, | ||
47 | gpa_t addr, unsigned int len) | ||
48 | { | ||
49 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | ||
50 | u32 value = 0; | ||
51 | int i; | ||
52 | |||
53 | /* Loop over all IRQs affected by this read */ | ||
54 | for (i = 0; i < len * 8; i++) { | ||
55 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | ||
56 | |||
57 | if (irq->enabled) | ||
58 | value |= (1U << i); | ||
59 | } | ||
60 | |||
61 | return value; | ||
62 | } | ||
63 | |||
64 | void vgic_mmio_write_senable(struct kvm_vcpu *vcpu, | ||
65 | gpa_t addr, unsigned int len, | ||
66 | unsigned long val) | ||
67 | { | ||
68 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | ||
69 | int i; | ||
70 | |||
71 | for_each_set_bit(i, &val, len * 8) { | ||
72 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | ||
73 | |||
74 | spin_lock(&irq->irq_lock); | ||
75 | irq->enabled = true; | ||
76 | vgic_queue_irq_unlock(vcpu->kvm, irq); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu, | ||
81 | gpa_t addr, unsigned int len, | ||
82 | unsigned long val) | ||
83 | { | ||
84 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | ||
85 | int i; | ||
86 | |||
87 | for_each_set_bit(i, &val, len * 8) { | ||
88 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | ||
89 | |||
90 | spin_lock(&irq->irq_lock); | ||
91 | |||
92 | irq->enabled = false; | ||
93 | |||
94 | spin_unlock(&irq->irq_lock); | ||
95 | } | ||
96 | } | ||
97 | |||
42 | static int match_region(const void *key, const void *elt) | 98 | static int match_region(const void *key, const void *elt) |
43 | { | 99 | { |
44 | const unsigned int offset = (unsigned long)key; | 100 | const unsigned int offset = (unsigned long)key; |
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h index 5b928d4b197e..57e19fe8df55 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.h +++ b/virt/kvm/arm/vgic/vgic-mmio.h | |||
@@ -96,6 +96,17 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu, | |||
96 | void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, | 96 | void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, |
97 | unsigned int len, unsigned long val); | 97 | unsigned int len, unsigned long val); |
98 | 98 | ||
99 | unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu, | ||
100 | gpa_t addr, unsigned int len); | ||
101 | |||
102 | void vgic_mmio_write_senable(struct kvm_vcpu *vcpu, | ||
103 | gpa_t addr, unsigned int len, | ||
104 | unsigned long val); | ||
105 | |||
106 | void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu, | ||
107 | gpa_t addr, unsigned int len, | ||
108 | unsigned long val); | ||
109 | |||
99 | unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev); | 110 | unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev); |
100 | 111 | ||
101 | #endif | 112 | #endif |