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

[Xen-devel] [PATCH v3 5/6] xen/x86: add PHYSDEVOP_msi_msix_set_enable



Allow device model running in stubdomain to enable/disable MSI(-X),
bypassing pciback. While pciback is still used to access config space
from within stubdomain, it refuse to write to
PCI_MSI_FLAGS_ENABLE/PCI_MSIX_FLAGS_ENABLE in non-permissive mode. Which
is the right thing to do for PV domain (the main use case for pciback),
as PV domain should use XEN_PCI_OP_* commands for that. Unfortunately
those commands are not good for stubdomain use, as they configure MSI in
dom0's kernel too, which should not happen for HVM domain.

This new physdevop is allowed only for stubdomain controlling the domain
which own the device.

Signed-off-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
---
Changes in v3:
 - new patch

This is rather RFC. Any suggestions for shorter name? Also, I'm not sure
if physdev_msi_msix_set_enable.flag is the best name/idea.

Should it be plugged into XSM? Any suggestions how exactly? New
function with XSM_DM_PRIV default action? Should it get target domain
only, or also machine_bdf?
---
 xen/arch/x86/msi.c           | 16 ++++++++++++++++
 xen/arch/x86/physdev.c       | 24 ++++++++++++++++++++++++
 xen/include/asm-x86/msi.h    |  1 +
 xen/include/public/physdev.h | 13 +++++++++++++
 4 files changed, 54 insertions(+)

diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index babc414..9ba934c 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -1474,6 +1474,22 @@ int pci_restore_msi_state(struct pci_dev *pdev)
     return 0;
 }
 
+int msi_msix_set_enable(struct pci_dev *pdev, int flag, int enable)
+{
+    if ( !current->domain->target || pdev->domain != current->domain->target )
+        return -EPERM;
+
+    switch ( flag ) {
+        case PHYSDEVOP_MSI_MSIX_SET_ENABLE_MSI:
+            msi_set_enable(pdev, enable);
+            break;
+        case PHYSDEVOP_MSI_MSIX_SET_ENABLE_MSIX:
+            msix_set_enable(pdev, enable);
+            break;
+    }
+    return 0;
+}
+
 void __init early_msi_init(void)
 {
     if ( use_msi < 0 )
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index de59e39..822846a 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -671,6 +671,30 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) 
arg)
         break;
     }
 
+    case PHYSDEVOP_msi_msix_set_enable: {
+        struct physdev_msi_msix_set_enable op;
+        struct pci_dev *pdev;
+
+        ret = -EFAULT;
+        if ( copy_from_guest(&op, arg, 1) )
+            break;
+
+        ret = -EINVAL;
+        if ( op.flag != PHYSDEVOP_MSI_MSIX_SET_ENABLE_MSI &&
+                op.flag != PHYSDEVOP_MSI_MSIX_SET_ENABLE_MSIX )
+            break;
+
+        pcidevs_lock();
+        pdev = pci_get_pdev(op.pci.seg, op.pci.bus, op.pci.devfn);
+        if ( pdev )
+            ret = msi_msix_set_enable(pdev, op.flag, !!op.enable);
+        else
+            ret = -ENODEV;
+        pcidevs_unlock();
+        break;
+
+    }
+
     default:
         ret = -ENOSYS;
         break;
diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
index 10387dc..080bf24 100644
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -252,5 +252,6 @@ void guest_mask_msi_irq(struct irq_desc *, bool mask);
 void ack_nonmaskable_msi_irq(struct irq_desc *);
 void end_nonmaskable_msi_irq(struct irq_desc *, u8 vector);
 void set_msi_affinity(struct irq_desc *, const cpumask_t *);
+int msi_msix_set_enable(struct pci_dev *pdev, int flag, int enable);
 
 #endif /* __ASM_MSI_H */
diff --git a/xen/include/public/physdev.h b/xen/include/public/physdev.h
index b6faf83..fd797c6 100644
--- a/xen/include/public/physdev.h
+++ b/xen/include/public/physdev.h
@@ -344,6 +344,19 @@ struct physdev_dbgp_op {
 typedef struct physdev_dbgp_op physdev_dbgp_op_t;
 DEFINE_XEN_GUEST_HANDLE(physdev_dbgp_op_t);
 
+#define PHYSDEVOP_MSI_MSIX_SET_ENABLE_MSI  0
+#define PHYSDEVOP_MSI_MSIX_SET_ENABLE_MSIX 1
+
+#define PHYSDEVOP_msi_msix_set_enable   32
+struct physdev_msi_msix_set_enable {
+    /* IN */
+    struct physdev_pci_device pci;
+    uint8_t flag;
+    uint8_t enable;
+};
+typedef struct physdev_msi_msix_set_enable physdev_msi_msix_set_enable_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_msi_msix_set_enable_t);
+
 /*
  * Notify that some PIRQ-bound event channels have been unmasked.
  * ** This command is obsolete since interface version 0x00030202 and is **
-- 
git-series 0.9.1

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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