diff options
| -rw-r--r-- | include/kvm/arm_vgic.h | 1 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic-v2.c | 8 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic-v3.c | 8 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic.c | 16 |
4 files changed, 33 insertions, 0 deletions
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 7c55dd5dd2c9..66203b268984 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h | |||
| @@ -114,6 +114,7 @@ struct vgic_ops { | |||
| 114 | void (*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr); | 114 | void (*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr); |
| 115 | u64 (*get_elrsr)(const struct kvm_vcpu *vcpu); | 115 | u64 (*get_elrsr)(const struct kvm_vcpu *vcpu); |
| 116 | u64 (*get_eisr)(const struct kvm_vcpu *vcpu); | 116 | u64 (*get_eisr)(const struct kvm_vcpu *vcpu); |
| 117 | void (*clear_eisr)(struct kvm_vcpu *vcpu); | ||
| 117 | u32 (*get_interrupt_status)(const struct kvm_vcpu *vcpu); | 118 | u32 (*get_interrupt_status)(const struct kvm_vcpu *vcpu); |
| 118 | void (*enable_underflow)(struct kvm_vcpu *vcpu); | 119 | void (*enable_underflow)(struct kvm_vcpu *vcpu); |
| 119 | void (*disable_underflow)(struct kvm_vcpu *vcpu); | 120 | void (*disable_underflow)(struct kvm_vcpu *vcpu); |
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c index a0a7b5d1a070..f9b9c7c51372 100644 --- a/virt/kvm/arm/vgic-v2.c +++ b/virt/kvm/arm/vgic-v2.c | |||
| @@ -72,6 +72,8 @@ static void vgic_v2_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr, | |||
| 72 | { | 72 | { |
| 73 | if (!(lr_desc.state & LR_STATE_MASK)) | 73 | if (!(lr_desc.state & LR_STATE_MASK)) |
| 74 | vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr |= (1ULL << lr); | 74 | vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr |= (1ULL << lr); |
| 75 | else | ||
| 76 | vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr &= ~(1ULL << lr); | ||
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu) | 79 | static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu) |
| @@ -84,6 +86,11 @@ static u64 vgic_v2_get_eisr(const struct kvm_vcpu *vcpu) | |||
| 84 | return vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr; | 86 | return vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr; |
| 85 | } | 87 | } |
| 86 | 88 | ||
| 89 | static void vgic_v2_clear_eisr(struct kvm_vcpu *vcpu) | ||
| 90 | { | ||
| 91 | vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr = 0; | ||
| 92 | } | ||
| 93 | |||
| 87 | static u32 vgic_v2_get_interrupt_status(const struct kvm_vcpu *vcpu) | 94 | static u32 vgic_v2_get_interrupt_status(const struct kvm_vcpu *vcpu) |
| 88 | { | 95 | { |
| 89 | u32 misr = vcpu->arch.vgic_cpu.vgic_v2.vgic_misr; | 96 | u32 misr = vcpu->arch.vgic_cpu.vgic_v2.vgic_misr; |
| @@ -148,6 +155,7 @@ static const struct vgic_ops vgic_v2_ops = { | |||
| 148 | .sync_lr_elrsr = vgic_v2_sync_lr_elrsr, | 155 | .sync_lr_elrsr = vgic_v2_sync_lr_elrsr, |
| 149 | .get_elrsr = vgic_v2_get_elrsr, | 156 | .get_elrsr = vgic_v2_get_elrsr, |
| 150 | .get_eisr = vgic_v2_get_eisr, | 157 | .get_eisr = vgic_v2_get_eisr, |
| 158 | .clear_eisr = vgic_v2_clear_eisr, | ||
| 151 | .get_interrupt_status = vgic_v2_get_interrupt_status, | 159 | .get_interrupt_status = vgic_v2_get_interrupt_status, |
| 152 | .enable_underflow = vgic_v2_enable_underflow, | 160 | .enable_underflow = vgic_v2_enable_underflow, |
| 153 | .disable_underflow = vgic_v2_disable_underflow, | 161 | .disable_underflow = vgic_v2_disable_underflow, |
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index 3a62d8a9a2c6..dff06021e748 100644 --- a/virt/kvm/arm/vgic-v3.c +++ b/virt/kvm/arm/vgic-v3.c | |||
| @@ -104,6 +104,8 @@ static void vgic_v3_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr, | |||
| 104 | { | 104 | { |
| 105 | if (!(lr_desc.state & LR_STATE_MASK)) | 105 | if (!(lr_desc.state & LR_STATE_MASK)) |
| 106 | vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr |= (1U << lr); | 106 | vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr |= (1U << lr); |
| 107 | else | ||
| 108 | vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr &= ~(1U << lr); | ||
| 107 | } | 109 | } |
| 108 | 110 | ||
| 109 | static u64 vgic_v3_get_elrsr(const struct kvm_vcpu *vcpu) | 111 | static u64 vgic_v3_get_elrsr(const struct kvm_vcpu *vcpu) |
| @@ -116,6 +118,11 @@ static u64 vgic_v3_get_eisr(const struct kvm_vcpu *vcpu) | |||
| 116 | return vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr; | 118 | return vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr; |
| 117 | } | 119 | } |
| 118 | 120 | ||
| 121 | static void vgic_v3_clear_eisr(struct kvm_vcpu *vcpu) | ||
| 122 | { | ||
| 123 | vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr = 0; | ||
| 124 | } | ||
| 125 | |||
| 119 | static u32 vgic_v3_get_interrupt_status(const struct kvm_vcpu *vcpu) | 126 | static u32 vgic_v3_get_interrupt_status(const struct kvm_vcpu *vcpu) |
| 120 | { | 127 | { |
| 121 | u32 misr = vcpu->arch.vgic_cpu.vgic_v3.vgic_misr; | 128 | u32 misr = vcpu->arch.vgic_cpu.vgic_v3.vgic_misr; |
| @@ -192,6 +199,7 @@ static const struct vgic_ops vgic_v3_ops = { | |||
| 192 | .sync_lr_elrsr = vgic_v3_sync_lr_elrsr, | 199 | .sync_lr_elrsr = vgic_v3_sync_lr_elrsr, |
| 193 | .get_elrsr = vgic_v3_get_elrsr, | 200 | .get_elrsr = vgic_v3_get_elrsr, |
| 194 | .get_eisr = vgic_v3_get_eisr, | 201 | .get_eisr = vgic_v3_get_eisr, |
| 202 | .clear_eisr = vgic_v3_clear_eisr, | ||
| 195 | .get_interrupt_status = vgic_v3_get_interrupt_status, | 203 | .get_interrupt_status = vgic_v3_get_interrupt_status, |
| 196 | .enable_underflow = vgic_v3_enable_underflow, | 204 | .enable_underflow = vgic_v3_enable_underflow, |
| 197 | .disable_underflow = vgic_v3_disable_underflow, | 205 | .disable_underflow = vgic_v3_disable_underflow, |
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 4b2c2e7856a3..c9f60f524588 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
| @@ -883,6 +883,11 @@ static inline u64 vgic_get_eisr(struct kvm_vcpu *vcpu) | |||
| 883 | return vgic_ops->get_eisr(vcpu); | 883 | return vgic_ops->get_eisr(vcpu); |
| 884 | } | 884 | } |
| 885 | 885 | ||
| 886 | static inline void vgic_clear_eisr(struct kvm_vcpu *vcpu) | ||
| 887 | { | ||
| 888 | vgic_ops->clear_eisr(vcpu); | ||
| 889 | } | ||
| 890 | |||
| 886 | static inline u32 vgic_get_interrupt_status(struct kvm_vcpu *vcpu) | 891 | static inline u32 vgic_get_interrupt_status(struct kvm_vcpu *vcpu) |
| 887 | { | 892 | { |
| 888 | return vgic_ops->get_interrupt_status(vcpu); | 893 | return vgic_ops->get_interrupt_status(vcpu); |
| @@ -922,6 +927,7 @@ static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu) | |||
| 922 | vgic_set_lr(vcpu, lr_nr, vlr); | 927 | vgic_set_lr(vcpu, lr_nr, vlr); |
| 923 | clear_bit(lr_nr, vgic_cpu->lr_used); | 928 | clear_bit(lr_nr, vgic_cpu->lr_used); |
| 924 | vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY; | 929 | vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY; |
| 930 | vgic_sync_lr_elrsr(vcpu, lr_nr, vlr); | ||
| 925 | } | 931 | } |
| 926 | 932 | ||
| 927 | /* | 933 | /* |
| @@ -978,6 +984,7 @@ bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) | |||
| 978 | BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); | 984 | BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); |
| 979 | vlr.state |= LR_STATE_PENDING; | 985 | vlr.state |= LR_STATE_PENDING; |
| 980 | vgic_set_lr(vcpu, lr, vlr); | 986 | vgic_set_lr(vcpu, lr, vlr); |
| 987 | vgic_sync_lr_elrsr(vcpu, lr, vlr); | ||
| 981 | return true; | 988 | return true; |
| 982 | } | 989 | } |
| 983 | } | 990 | } |
| @@ -999,6 +1006,7 @@ bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) | |||
| 999 | vlr.state |= LR_EOI_INT; | 1006 | vlr.state |= LR_EOI_INT; |
| 1000 | 1007 | ||
| 1001 | vgic_set_lr(vcpu, lr, vlr); | 1008 | vgic_set_lr(vcpu, lr, vlr); |
| 1009 | vgic_sync_lr_elrsr(vcpu, lr, vlr); | ||
| 1002 | 1010 | ||
| 1003 | return true; | 1011 | return true; |
| 1004 | } | 1012 | } |
| @@ -1136,6 +1144,14 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) | |||
| 1136 | if (status & INT_STATUS_UNDERFLOW) | 1144 | if (status & INT_STATUS_UNDERFLOW) |
| 1137 | vgic_disable_underflow(vcpu); | 1145 | vgic_disable_underflow(vcpu); |
| 1138 | 1146 | ||
| 1147 | /* | ||
| 1148 | * In the next iterations of the vcpu loop, if we sync the vgic state | ||
| 1149 | * after flushing it, but before entering the guest (this happens for | ||
| 1150 | * pending signals and vmid rollovers), then make sure we don't pick | ||
| 1151 | * up any old maintenance interrupts here. | ||
| 1152 | */ | ||
| 1153 | vgic_clear_eisr(vcpu); | ||
| 1154 | |||
| 1139 | return level_pending; | 1155 | return level_pending; |
| 1140 | } | 1156 | } |
| 1141 | 1157 | ||
