@@ -143,6 +143,10 @@ static int acpi_register_gsi_xen_pvh(struct device *dev, u32 gsi,
else if (rc)
printk(KERN_ERR "Failed to setup GSI :%u, err_code:%d\n", gsi, rc);
+ rc = xen_pvh_add_gsi_irq_map(gsi, irq);
+ if (rc == -EEXIST)
+ printk(KERN_INFO "Already map the GSI :%u and IRQ: %d\n", gsi, irq);
+
return irq;
}
@@ -967,6 +967,43 @@ int xen_irq_from_gsi(unsigned gsi)
}
EXPORT_SYMBOL_GPL(xen_irq_from_gsi);
+int xen_gsi_from_irq(unsigned irq)
+{
+ struct irq_info *info;
+
+ list_for_each_entry(info, &xen_irq_list_head, list) {
+ if (info->type != IRQT_PIRQ)
+ continue;
+
+ if (info->irq == irq)
+ return info->u.pirq.gsi;
+ }
+
+ return -1;
+}
+EXPORT_SYMBOL_GPL(xen_gsi_from_irq);
+
+int xen_pvh_add_gsi_irq_map(unsigned gsi, unsigned irq)
+{
+ int tmp_irq;
+ struct irq_info *info;
+
+ tmp_irq = xen_irq_from_gsi(gsi);
+ if (tmp_irq != -1)
+ return -EEXIST;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (info == NULL)
+ panic("Unable to allocate metadata for GSI%d\n", gsi);
+
+ info->type = IRQT_PIRQ;
+ info->irq = irq;
+ info->u.pirq.gsi = gsi;
+ list_add_tail(&info->list, &xen_irq_list_head);
+
+ return 0;
+}
+
static void __unbind_from_irq(unsigned int irq)
{
evtchn_port_t evtchn = evtchn_from_irq(irq);
@@ -37,6 +37,7 @@
#include <xen/page.h>
#include <xen/xen-ops.h>
#include <xen/balloon.h>
+#include <xen/events.h>
#include "privcmd.h"
@@ -833,6 +834,21 @@ static long privcmd_ioctl_mmap_resource(struct file *file,
return rc;
}
+static long privcmd_ioctl_gsi_from_irq(struct file *file, void __user *udata)
+{
+ struct privcmd_gsi_from_irq kdata;
+
+ if (copy_from_user(&kdata, udata, sizeof(kdata)))
+ return -EFAULT;
+
+ kdata.gsi = xen_gsi_from_irq(kdata.irq);
+
+ if (copy_to_user(udata, &kdata, sizeof(kdata)))
+ return -EFAULT;
+
+ return 0;
+}
+
static long privcmd_ioctl(struct file *file,
unsigned int cmd, unsigned long data)
{
@@ -868,6 +884,10 @@ static long privcmd_ioctl(struct file *file,
ret = privcmd_ioctl_mmap_resource(file, udata);
break;
+ case IOCTL_PRIVCMD_GSI_FROM_IRQ:
+ ret = privcmd_ioctl_gsi_from_irq(file, udata);
+ break;
+
default:
break;
}
@@ -98,6 +98,11 @@ struct privcmd_mmap_resource {
__u64 addr;
};
+struct privcmd_gsi_from_irq {
+ __u32 irq;
+ __u32 gsi;
+};
+
/*
* @cmd: IOCTL_PRIVCMD_HYPERCALL
* @arg: &privcmd_hypercall_t
@@ -125,5 +130,7 @@ struct privcmd_mmap_resource {
_IOC(_IOC_NONE, 'P', 6, sizeof(domid_t))
#define IOCTL_PRIVCMD_MMAP_RESOURCE \
_IOC(_IOC_NONE, 'P', 7, sizeof(struct privcmd_mmap_resource))
+#define IOCTL_PRIVCMD_GSI_FROM_IRQ \
+ _IOC(_IOC_NONE, 'P', 8, sizeof(struct privcmd_gsi_from_irq))
#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
@@ -133,6 +133,11 @@ int xen_pirq_from_irq(unsigned irq);
/* Return the irq allocated to the gsi */
int xen_irq_from_gsi(unsigned gsi);
+/* Return the gsi from irq */
+int xen_gsi_from_irq(unsigned irq);
+
+int xen_pvh_add_gsi_irq_map(unsigned gsi, unsigned irq);
+
/* Determine whether to ignore this IRQ if it is passed to a guest. */
int xen_test_irq_shared(int irq);