[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v3 6/7] x86/dmop: Add XEN_DMOP_enable_ext_dest_id DM op



Xen cannot simply advertise XEN_HVM_CPUID_EXT_DEST_ID to the guest
without knowing that the device model will handle extended destination
IDs correctly for passthrough MSIs. A device model that still uses
XEN_DOMCTL_bind_pt_irq would pass only the low 8 bits of the destination
ID, misrouting interrupts to vCPUs with APIC IDs greater than 255. So,
add a DM op XEN_DMOP_enable_ext_dest_id that the device model can call
during domain setup (before vCPUs are started) to signal that it will
use XEN_DMOP_bind_pt_msi_irq for all passthrough MSI bindings. When
called, Xen sets ext_dest_id_enabled in struct hvm_domain, so it's
visible to the guest via CPUID.

Signed-off-by: Julian Vetter <julian.vetter@xxxxxxxxxx>
---
Changes in V3:
- New patch addressing feedback from Roger
---
 tools/include/xendevicemodel.h        | 14 ++++++++++++++
 tools/libs/devicemodel/core.c         | 10 ++++++++++
 xen/arch/x86/hvm/dm.c                 |  5 +++++
 xen/arch/x86/include/asm/hvm/domain.h |  7 +++++++
 xen/include/public/hvm/dm_op.h        |  9 +++++++++
 5 files changed, 45 insertions(+)

diff --git a/tools/include/xendevicemodel.h b/tools/include/xendevicemodel.h
index 0d5d7b0ff1..270d76fe9c 100644
--- a/tools/include/xendevicemodel.h
+++ b/tools/include/xendevicemodel.h
@@ -412,6 +412,20 @@ int xendevicemodel_unbind_pt_msi_irq(
     xendevicemodel_handle *dmod, domid_t domid, uint32_t machine_irq,
     uint8_t gvec, uint64_t msi_addr, uint32_t msi_data);
 
+/**
+ * This function signals to Xen that this device model will use
+ * xendevicemodel_bind_pt_msi_irq() for all passthrough MSI bindings.
+ * After this call, Xen will advertise XEN_HVM_CPUID_EXT_DEST_ID to the
+ * guest, enabling 15-bit destination IDs. Must be called before the
+ * guest vCPUs are started!
+ *
+ * @parm dmod a handle to an open devicemodel interface.
+ * @parm domid the domain id to be serviced.
+ * @return 0 on success, -1 on failure.
+ */
+int xendevicemodel_enable_ext_dest_id(
+    xendevicemodel_handle *dmod, domid_t domid);
+
 #endif /* XENDEVICEMODEL_H */
 
 /*
diff --git a/tools/libs/devicemodel/core.c b/tools/libs/devicemodel/core.c
index 4a52fe4750..03838aa37b 100644
--- a/tools/libs/devicemodel/core.c
+++ b/tools/libs/devicemodel/core.c
@@ -689,6 +689,16 @@ int xendevicemodel_unbind_pt_msi_irq(
     return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op));
 }
 
+int xendevicemodel_enable_ext_dest_id(
+    xendevicemodel_handle *dmod, domid_t domid)
+{
+    struct xen_dm_op op = {
+        .op = XEN_DMOP_enable_ext_dest_id,
+    };
+
+    return xendevicemodel_op(dmod, domid, 1, &op, sizeof(op));
+}
+
 int xendevicemodel_restrict(xendevicemodel_handle *dmod, domid_t domid)
 {
     return osdep_xendevicemodel_restrict(dmod, domid);
diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
index 3d530d948f..7738400540 100644
--- a/xen/arch/x86/hvm/dm.c
+++ b/xen/arch/x86/hvm/dm.c
@@ -374,6 +374,7 @@ int dm_op(const struct dmop_args *op_args)
         [XEN_DMOP_nr_vcpus]                         = sizeof(struct 
xen_dm_op_nr_vcpus),
         [XEN_DMOP_bind_pt_msi_irq]                  = sizeof(struct 
xen_dm_op_bind_pt_msi_irq),
         [XEN_DMOP_unbind_pt_msi_irq]                = sizeof(struct 
xen_dm_op_bind_pt_msi_irq),
+        [XEN_DMOP_enable_ext_dest_id]               = 0,
     };
 
     rc = rcu_lock_remote_domain_by_id(op_args->domid, &d);
@@ -708,6 +709,10 @@ int dm_op(const struct dmop_args *op_args)
         break;
     }
 
+    case XEN_DMOP_enable_ext_dest_id:
+        d->arch.hvm.ext_dest_id_enabled = true;
+        break;
+
     default:
         rc = ioreq_server_dm_op(&op, d, &const_op);
         break;
diff --git a/xen/arch/x86/include/asm/hvm/domain.h 
b/xen/arch/x86/include/asm/hvm/domain.h
index abf9bc448d..770bc96970 100644
--- a/xen/arch/x86/include/asm/hvm/domain.h
+++ b/xen/arch/x86/include/asm/hvm/domain.h
@@ -105,6 +105,13 @@ struct hvm_domain {
     /* Compatibility setting for a bug in x2APIC LDR */
     bool bug_x2apic_ldr_vcpu_id;
 
+    /*
+     * Set by the device model via XEN_DMOP_enable_ext_dest_id to indicate
+     * it uses XEN_DMOP_bind_pt_msi_irq (raw MSI addr/data) for passthrough.
+     * Controls advertisement of XEN_HVM_CPUID_EXT_DEST_ID to the guest.
+     */
+    bool ext_dest_id_enabled;
+
     /* hypervisor intercepted msix table */
     struct list_head       msixtbl_list;
 
diff --git a/xen/include/public/hvm/dm_op.h b/xen/include/public/hvm/dm_op.h
index fd0f3a6a99..2814fe1c3d 100644
--- a/xen/include/public/hvm/dm_op.h
+++ b/xen/include/public/hvm/dm_op.h
@@ -447,6 +447,15 @@ typedef struct xen_dm_op_nr_vcpus xen_dm_op_nr_vcpus_t;
 #define XEN_DMOP_bind_pt_msi_irq   21
 #define XEN_DMOP_unbind_pt_msi_irq 22
 
+/*
+ * XEN_DMOP_enable_ext_dest_id: Signal to Xen that this device model will use
+ * XEN_DMOP_bind_pt_msi_irq for all passthrough MSI bindings, passing raw MSI
+ * address/data fields. Once called, Xen will advertise
+ * XEN_HVM_CPUID_EXT_DEST_ID to the guest. Must be called before the guest
+ * starts.
+ */
+#define XEN_DMOP_enable_ext_dest_id 23
+
 struct xen_dm_op_bind_pt_msi_irq {
     /* IN - physical IRQ (pirq) */
     uint32_t machine_irq;
-- 
2.51.0



--
Julian Vetter | Vates Hypervisor & Kernel Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.