#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <linux/interrupt.h>
+#include <linux/list.h>
#include <linux/irqchip/arm-gic-v3.h>
#include <kvm/arm_vgic.h>
#include "vgic.h"
#include "its-emul.h"
+struct its_device {
+ struct list_head dev_list;
+ struct list_head itt;
+ u32 device_id;
+};
+
+struct its_collection {
+ struct list_head coll_list;
+ u32 collection_id;
+ u32 target_addr;
+};
+
+struct its_itte {
+ struct list_head itte_list;
+ struct its_collection *collection;
+ u32 lpi;
+ u32 event_id;
+};
+
#define BASER_BASE_ADDRESS(x) ((x) & 0xfffffffff000ULL)
/* The distributor lock is held by the VGIC MMIO handler. */
spin_lock_init(&its->lock);
+ INIT_LIST_HEAD(&its->device_list);
+ INIT_LIST_HEAD(&its->collection_list);
+
its->enabled = false;
return -ENXIO;
{
struct vgic_dist *dist = &kvm->arch.vgic;
struct vgic_its *its = &dist->its;
+ struct its_device *dev;
+ struct its_itte *itte;
+ struct list_head *dev_cur, *dev_temp;
+ struct list_head *cur, *temp;
if (!vgic_has_its(kvm))
return;
+ if (!its->device_list.next)
+ return;
+
+ spin_lock(&its->lock);
+ list_for_each_safe(dev_cur, dev_temp, &its->device_list) {
+ dev = container_of(dev_cur, struct its_device, dev_list);
+ list_for_each_safe(cur, temp, &dev->itt) {
+ itte = (container_of(cur, struct its_itte, itte_list));
+ list_del(cur);
+ kfree(itte);
+ }
+ list_del(dev_cur);
+ kfree(dev);
+ }
+
+ list_for_each_safe(cur, temp, &its->collection_list) {
+ list_del(cur);
+ kfree(container_of(cur, struct its_collection, coll_list));
+ }
+
kfree(dist->pendbaser);
its->enabled = false;
+ spin_unlock(&its->lock);
}