@@ -155,13 +155,27 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
155155 unsigned long val )
156156{
157157 struct vgic_dist * dist = & vcpu -> kvm -> arch .vgic ;
158+ u32 reg ;
158159
159160 switch (addr & 0x0c ) {
160161 case GICD_TYPER2 :
161- case GICD_IIDR :
162162 if (val != vgic_mmio_read_v3_misc (vcpu , addr , len ))
163163 return - EINVAL ;
164164 return 0 ;
165+ case GICD_IIDR :
166+ reg = vgic_mmio_read_v3_misc (vcpu , addr , len );
167+ if ((reg ^ val ) & ~GICD_IIDR_REVISION_MASK )
168+ return - EINVAL ;
169+
170+ reg = FIELD_GET (GICD_IIDR_REVISION_MASK , reg );
171+ switch (reg ) {
172+ case KVM_VGIC_IMP_REV_2 :
173+ case KVM_VGIC_IMP_REV_3 :
174+ dist -> implementation_rev = reg ;
175+ return 0 ;
176+ default :
177+ return - EINVAL ;
178+ }
165179 case GICD_CTLR :
166180 /* Not a GICv4.1? No HW SGIs */
167181 if (!kvm_vgic_global_state .has_gicv4_1 )
@@ -221,34 +235,58 @@ static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
221235 vgic_put_irq (vcpu -> kvm , irq );
222236}
223237
238+ bool vgic_lpis_enabled (struct kvm_vcpu * vcpu )
239+ {
240+ struct vgic_cpu * vgic_cpu = & vcpu -> arch .vgic_cpu ;
241+
242+ return atomic_read (& vgic_cpu -> ctlr ) == GICR_CTLR_ENABLE_LPIS ;
243+ }
244+
224245static unsigned long vgic_mmio_read_v3r_ctlr (struct kvm_vcpu * vcpu ,
225246 gpa_t addr , unsigned int len )
226247{
227248 struct vgic_cpu * vgic_cpu = & vcpu -> arch .vgic_cpu ;
249+ unsigned long val ;
228250
229- return vgic_cpu -> lpis_enabled ? GICR_CTLR_ENABLE_LPIS : 0 ;
230- }
251+ val = atomic_read (& vgic_cpu -> ctlr );
252+ if (vgic_get_implementation_rev (vcpu ) >= KVM_VGIC_IMP_REV_3 )
253+ val |= GICR_CTLR_IR | GICR_CTLR_CES ;
231254
255+ return val ;
256+ }
232257
233258static void vgic_mmio_write_v3r_ctlr (struct kvm_vcpu * vcpu ,
234259 gpa_t addr , unsigned int len ,
235260 unsigned long val )
236261{
237262 struct vgic_cpu * vgic_cpu = & vcpu -> arch .vgic_cpu ;
238- bool was_enabled = vgic_cpu -> lpis_enabled ;
263+ u32 ctlr ;
239264
240265 if (!vgic_has_its (vcpu -> kvm ))
241266 return ;
242267
243- vgic_cpu -> lpis_enabled = val & GICR_CTLR_ENABLE_LPIS ;
268+ if (!(val & GICR_CTLR_ENABLE_LPIS )) {
269+ /*
270+ * Don't disable if RWP is set, as there already an
271+ * ongoing disable. Funky guest...
272+ */
273+ ctlr = atomic_cmpxchg_acquire (& vgic_cpu -> ctlr ,
274+ GICR_CTLR_ENABLE_LPIS ,
275+ GICR_CTLR_RWP );
276+ if (ctlr != GICR_CTLR_ENABLE_LPIS )
277+ return ;
244278
245- if (was_enabled && !vgic_cpu -> lpis_enabled ) {
246279 vgic_flush_pending_lpis (vcpu );
247280 vgic_its_invalidate_cache (vcpu -> kvm );
248- }
281+ atomic_set_release (& vgic_cpu -> ctlr , 0 );
282+ } else {
283+ ctlr = atomic_cmpxchg_acquire (& vgic_cpu -> ctlr , 0 ,
284+ GICR_CTLR_ENABLE_LPIS );
285+ if (ctlr != 0 )
286+ return ;
249287
250- if (!was_enabled && vgic_cpu -> lpis_enabled )
251288 vgic_enable_lpis (vcpu );
289+ }
252290}
253291
254292static bool vgic_mmio_vcpu_rdist_is_last (struct kvm_vcpu * vcpu )
@@ -478,11 +516,10 @@ static void vgic_mmio_write_propbase(struct kvm_vcpu *vcpu,
478516 unsigned long val )
479517{
480518 struct vgic_dist * dist = & vcpu -> kvm -> arch .vgic ;
481- struct vgic_cpu * vgic_cpu = & vcpu -> arch .vgic_cpu ;
482519 u64 old_propbaser , propbaser ;
483520
484521 /* Storing a value with LPIs already enabled is undefined */
485- if (vgic_cpu -> lpis_enabled )
522+ if (vgic_lpis_enabled ( vcpu ) )
486523 return ;
487524
488525 do {
@@ -513,7 +550,7 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
513550 u64 old_pendbaser , pendbaser ;
514551
515552 /* Storing a value with LPIs already enabled is undefined */
516- if (vgic_cpu -> lpis_enabled )
553+ if (vgic_lpis_enabled ( vcpu ) )
517554 return ;
518555
519556 do {
@@ -525,6 +562,63 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
525562 pendbaser ) != old_pendbaser );
526563}
527564
565+ static unsigned long vgic_mmio_read_sync (struct kvm_vcpu * vcpu ,
566+ gpa_t addr , unsigned int len )
567+ {
568+ return !!atomic_read (& vcpu -> arch .vgic_cpu .syncr_busy );
569+ }
570+
571+ static void vgic_set_rdist_busy (struct kvm_vcpu * vcpu , bool busy )
572+ {
573+ if (busy ) {
574+ atomic_inc (& vcpu -> arch .vgic_cpu .syncr_busy );
575+ smp_mb__after_atomic ();
576+ } else {
577+ smp_mb__before_atomic ();
578+ atomic_dec (& vcpu -> arch .vgic_cpu .syncr_busy );
579+ }
580+ }
581+
582+ static void vgic_mmio_write_invlpi (struct kvm_vcpu * vcpu ,
583+ gpa_t addr , unsigned int len ,
584+ unsigned long val )
585+ {
586+ struct vgic_irq * irq ;
587+
588+ /*
589+ * If the guest wrote only to the upper 32bit part of the
590+ * register, drop the write on the floor, as it is only for
591+ * vPEs (which we don't support for obvious reasons).
592+ *
593+ * Also discard the access if LPIs are not enabled.
594+ */
595+ if ((addr & 4 ) || !vgic_lpis_enabled (vcpu ))
596+ return ;
597+
598+ vgic_set_rdist_busy (vcpu , true);
599+
600+ irq = vgic_get_irq (vcpu -> kvm , NULL , lower_32_bits (val ));
601+ if (irq ) {
602+ vgic_its_inv_lpi (vcpu -> kvm , irq );
603+ vgic_put_irq (vcpu -> kvm , irq );
604+ }
605+
606+ vgic_set_rdist_busy (vcpu , false);
607+ }
608+
609+ static void vgic_mmio_write_invall (struct kvm_vcpu * vcpu ,
610+ gpa_t addr , unsigned int len ,
611+ unsigned long val )
612+ {
613+ /* See vgic_mmio_write_invlpi() for the early return rationale */
614+ if ((addr & 4 ) || !vgic_lpis_enabled (vcpu ))
615+ return ;
616+
617+ vgic_set_rdist_busy (vcpu , true);
618+ vgic_its_invall (vcpu );
619+ vgic_set_rdist_busy (vcpu , false);
620+ }
621+
528622/*
529623 * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
530624 * redistributors, while SPIs are covered by registers in the distributor
@@ -630,6 +724,15 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
630724 REGISTER_DESC_WITH_LENGTH (GICR_PENDBASER ,
631725 vgic_mmio_read_pendbase , vgic_mmio_write_pendbase , 8 ,
632726 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit ),
727+ REGISTER_DESC_WITH_LENGTH (GICR_INVLPIR ,
728+ vgic_mmio_read_raz , vgic_mmio_write_invlpi , 8 ,
729+ VGIC_ACCESS_64bit | VGIC_ACCESS_32bit ),
730+ REGISTER_DESC_WITH_LENGTH (GICR_INVALLR ,
731+ vgic_mmio_read_raz , vgic_mmio_write_invall , 8 ,
732+ VGIC_ACCESS_64bit | VGIC_ACCESS_32bit ),
733+ REGISTER_DESC_WITH_LENGTH (GICR_SYNCR ,
734+ vgic_mmio_read_sync , vgic_mmio_write_wi , 4 ,
735+ VGIC_ACCESS_32bit ),
633736 REGISTER_DESC_WITH_LENGTH (GICR_IDREGS ,
634737 vgic_mmio_read_v3_idregs , vgic_mmio_write_wi , 48 ,
635738 VGIC_ACCESS_32bit ),
0 commit comments