|
@@ -1431,7 +1431,7 @@ static void vgic_mmio_write_its_baser(struct kvm *kvm,
|
|
|
unsigned long val)
|
|
|
{
|
|
|
const struct vgic_its_abi *abi = vgic_its_get_abi(its);
|
|
|
- u64 entry_size, device_type;
|
|
|
+ u64 entry_size, table_type;
|
|
|
u64 reg, *regptr, clearbits = 0;
|
|
|
|
|
|
/* When GITS_CTLR.Enable is 1, we ignore write accesses. */
|
|
@@ -1442,12 +1442,12 @@ static void vgic_mmio_write_its_baser(struct kvm *kvm,
|
|
|
case 0:
|
|
|
regptr = &its->baser_device_table;
|
|
|
entry_size = abi->dte_esz;
|
|
|
- device_type = GITS_BASER_TYPE_DEVICE;
|
|
|
+ table_type = GITS_BASER_TYPE_DEVICE;
|
|
|
break;
|
|
|
case 1:
|
|
|
regptr = &its->baser_coll_table;
|
|
|
entry_size = abi->cte_esz;
|
|
|
- device_type = GITS_BASER_TYPE_COLLECTION;
|
|
|
+ table_type = GITS_BASER_TYPE_COLLECTION;
|
|
|
clearbits = GITS_BASER_INDIRECT;
|
|
|
break;
|
|
|
default:
|
|
@@ -1459,10 +1459,24 @@ static void vgic_mmio_write_its_baser(struct kvm *kvm,
|
|
|
reg &= ~clearbits;
|
|
|
|
|
|
reg |= (entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT;
|
|
|
- reg |= device_type << GITS_BASER_TYPE_SHIFT;
|
|
|
+ reg |= table_type << GITS_BASER_TYPE_SHIFT;
|
|
|
reg = vgic_sanitise_its_baser(reg);
|
|
|
|
|
|
*regptr = reg;
|
|
|
+
|
|
|
+ if (!(reg & GITS_BASER_VALID)) {
|
|
|
+ /* Take the its_lock to prevent a race with a save/restore */
|
|
|
+ mutex_lock(&its->its_lock);
|
|
|
+ switch (table_type) {
|
|
|
+ case GITS_BASER_TYPE_DEVICE:
|
|
|
+ vgic_its_free_device_list(kvm, its);
|
|
|
+ break;
|
|
|
+ case GITS_BASER_TYPE_COLLECTION:
|
|
|
+ vgic_its_free_collection_list(kvm, its);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ mutex_unlock(&its->its_lock);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static unsigned long vgic_mmio_read_its_ctlr(struct kvm *vcpu,
|