|
@@ -766,6 +766,57 @@ static void xen_pt_destroy(PCIDevice *d) {
|
|
}
|
|
}
|
|
/* init */
|
|
/* init */
|
|
|
|
|
|
|
|
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 42000
|
|
|
|
+static bool xen_pt_need_gsi(void)
|
|
|
|
+{
|
|
|
|
+ FILE *fp;
|
|
|
|
+ int len;
|
|
|
|
+ /*
|
|
|
|
+ * The max length of guest_type is "PVH"+'\n'+'\0', it is 5,
|
|
|
|
+ * so here set the length of type to be twice.
|
|
|
|
+ */
|
|
|
|
+ char type[10];
|
|
|
|
+ const char *guest_type = "/sys/hypervisor/guest_type";
|
|
|
|
+
|
|
|
|
+ fp = fopen(guest_type, "r");
|
|
|
|
+ if (!fp) {
|
|
|
|
+ error_report("Cannot open %s: %s", guest_type, strerror(errno));
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (fgets(type, sizeof(type), fp)) {
|
|
|
|
+ len = strlen(type);
|
|
|
|
+ if (len) {
|
|
|
|
+ type[len - 1] = '\0';
|
|
|
|
+ if (!strcmp(type, "PVH")) {
|
|
|
|
+ fclose(fp);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fclose(fp);
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int xen_pt_map_pirq_for_gsi(PCIDevice *d, int *pirq)
|
|
|
|
+{
|
|
|
|
+ int gsi;
|
|
|
|
+ XenPCIPassthroughState *s = XEN_PT_DEVICE(d);
|
|
|
|
+
|
|
|
|
+ gsi = xc_pcidev_get_gsi(xen_xc,
|
|
|
|
+ PCI_SBDF(s->real_device.domain,
|
|
|
|
+ s->real_device.bus,
|
|
|
|
+ s->real_device.dev,
|
|
|
|
+ s->real_device.func));
|
|
|
|
+ if (gsi >= 0) {
|
|
|
|
+ return xc_physdev_map_pirq_gsi(xen_xc, xen_domid, gsi, pirq);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return gsi;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
static void xen_pt_realize(PCIDevice *d, Error **errp)
|
|
static void xen_pt_realize(PCIDevice *d, Error **errp)
|
|
{
|
|
{
|
|
ERRP_GUARD();
|
|
ERRP_GUARD();
|
|
@@ -847,7 +898,16 @@ static void xen_pt_realize(PCIDevice *d, Error **errp)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 42000
|
|
|
|
+ if (xen_pt_need_gsi()) {
|
|
|
|
+ rc = xen_pt_map_pirq_for_gsi(d, &pirq);
|
|
|
|
+ } else {
|
|
|
|
+ rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq);
|
|
|
|
+ }
|
|
|
|
+#else
|
|
rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq);
|
|
rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq);
|
|
|
|
+#endif
|
|
|
|
+
|
|
if (rc < 0) {
|
|
if (rc < 0) {
|
|
XEN_PT_ERR(d, "Mapping machine irq %u to pirq %i failed, (err: %d)\n",
|
|
XEN_PT_ERR(d, "Mapping machine irq %u to pirq %i failed, (err: %d)\n",
|
|
machine_irq, pirq, errno);
|
|
machine_irq, pirq, errno);
|