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

[Xen-changelog] [xen-unstable] x86: Add a new operation in HVMOP to inject emulated MSI.



# HG changeset patch
# User Wei Liu <liuw@xxxxxxxxx>
# Date 1306418308 -3600
# Node ID 5024faf7c92986a86843b977bd63b3c54d688647
# Parent  996c7726a3768f17af2fe6f435d2dd3497f41238
x86: Add a new operation in HVMOP to inject emulated MSI.

The original vmsi_deliver is renamed to vmsi_deliver_pirq. New
vmsi_deliver is dedicated to the actually delivering.

Original HVMOP number is unchanged. New operation is numbered 16
and enclosed by (__XEN__) and (__XEN_TOOLS__).

Signed-off-by: Wei Liu <liuw@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxx>
---


diff -r 996c7726a376 -r 5024faf7c929 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Thu May 26 14:49:50 2011 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Thu May 26 14:58:28 2011 +0100
@@ -3285,6 +3285,36 @@
     return rc;
 }
 
+static int hvmop_inj_msi(
+    XEN_GUEST_HANDLE(xen_hvm_inj_msi_t) uop)
+{
+    struct xen_hvm_inj_msi op;
+    struct domain *d;
+    int rc;
+
+    if ( copy_from_guest(&op, uop, 1) )
+        return -EFAULT;
+
+    rc = rcu_lock_remote_target_domain_by_id(op.domid, &d);
+    if ( rc != 0 )
+        return rc;
+
+    rc = -EINVAL;
+    if ( !is_hvm_domain(d) )
+        goto out;
+
+    rc = xsm_hvm_inj_msi(d);
+    if ( rc )
+        goto out;
+
+    rc = 0;
+    hvm_inj_msi(d, op.addr, op.data);
+
+ out:
+    rcu_unlock_domain(d);
+    return rc;
+}
+
 static int hvmop_flush_tlb_all(void)
 {
     struct domain *d = current->domain;
@@ -3563,6 +3593,11 @@
             guest_handle_cast(arg, xen_hvm_set_isa_irq_level_t));
         break;
 
+    case HVMOP_inj_msi:
+        rc = hvmop_inj_msi(
+            guest_handle_cast(arg, xen_hvm_inj_msi_t));
+        break;
+
     case HVMOP_set_pci_link_route:
         rc = hvmop_set_pci_link_route(
             guest_handle_cast(arg, xen_hvm_set_pci_link_route_t));
diff -r 996c7726a376 -r 5024faf7c929 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Thu May 26 14:49:50 2011 +0100
+++ b/xen/arch/x86/hvm/irq.c    Thu May 26 14:58:28 2011 +0100
@@ -26,6 +26,7 @@
 #include <xen/irq.h>
 #include <asm/hvm/domain.h>
 #include <asm/hvm/support.h>
+#include <asm/msi.h>
 
 /* Must be called with hvm_domain->irq_lock hold */
 static void assert_irq(struct domain *d, unsigned ioapic_gsi, unsigned pic_irq)
@@ -259,6 +260,20 @@
             d->domain_id, link, old_isa_irq, isa_irq);
 }
 
+void hvm_inj_msi(struct domain *d, uint64_t addr, uint32_t data)
+{
+    uint32_t tmp = (uint32_t) addr;
+    uint8_t  dest = (tmp & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
+    uint8_t  dest_mode = !!(tmp & MSI_ADDR_DESTMODE_MASK);
+    uint8_t  delivery_mode = (data & MSI_DATA_DELIVERY_MODE_MASK)
+        >> MSI_DATA_DELIVERY_MODE_SHIFT;
+    uint8_t trig_mode = (data & MSI_DATA_TRIGGER_MASK)
+        >> MSI_DATA_TRIGGER_SHIFT;
+    uint8_t vector = data & MSI_DATA_VECTOR_MASK;
+
+    vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
+}
+
 void hvm_set_callback_via(struct domain *d, uint64_t via)
 {
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
diff -r 996c7726a376 -r 5024faf7c929 xen/arch/x86/hvm/vmsi.c
--- a/xen/arch/x86/hvm/vmsi.c   Thu May 26 14:49:50 2011 +0100
+++ b/xen/arch/x86/hvm/vmsi.c   Thu May 26 14:58:28 2011 +0100
@@ -65,29 +65,14 @@
     }
 }
 
-int vmsi_deliver(struct domain *d, int pirq)
+int vmsi_deliver(
+    struct domain *d, int vector,
+    uint8_t dest, uint8_t dest_mode,
+    uint8_t delivery_mode, uint8_t trig_mode)
 {
-    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
-    uint32_t flags = hvm_irq_dpci->mirq[pirq].gmsi.gflags;
-    int vector = hvm_irq_dpci->mirq[pirq].gmsi.gvec;
-    uint8_t dest = (uint8_t)flags;
-    uint8_t dest_mode = !!(flags & VMSI_DM_MASK);
-    uint8_t delivery_mode = (flags & VMSI_DELIV_MASK) >> 
GFLAGS_SHIFT_DELIV_MODE;
-    uint8_t trig_mode = (flags & VMSI_TRIG_MODE) >> GFLAGS_SHIFT_TRG_MODE;
     struct vlapic *target;
     struct vcpu *v;
 
-    HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
-                "msi: dest=%x dest_mode=%x delivery_mode=%x "
-                "vector=%x trig_mode=%x\n",
-                dest, dest_mode, delivery_mode, vector, trig_mode);
-
-    if ( !( hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_GUEST_MSI ) )
-    {
-        gdprintk(XENLOG_WARNING, "pirq %x not msi \n", pirq);
-        return 0;
-    }
-
     switch ( delivery_mode )
     {
     case dest_LowestPrio:
@@ -125,6 +110,32 @@
     return 1;
 }
 
+int vmsi_deliver_pirq(struct domain *d, int pirq)
+{
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    uint32_t flags = hvm_irq_dpci->mirq[pirq].gmsi.gflags;
+    int vector = hvm_irq_dpci->mirq[pirq].gmsi.gvec;
+    uint8_t dest = (uint8_t)flags;
+    uint8_t dest_mode = !!(flags & VMSI_DM_MASK);
+    uint8_t delivery_mode = (flags & VMSI_DELIV_MASK)
+        >> GFLAGS_SHIFT_DELIV_MODE;
+    uint8_t trig_mode = (flags&VMSI_TRIG_MODE) >> GFLAGS_SHIFT_TRG_MODE;
+
+    HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
+                "msi: dest=%x dest_mode=%x delivery_mode=%x "
+                "vector=%x trig_mode=%x\n",
+                dest, dest_mode, delivery_mode, vector, trig_mode);
+
+    if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_GUEST_MSI) )
+    {
+        gdprintk(XENLOG_WARNING, "pirq %x not msi \n", pirq);
+        return 0;
+    }
+
+    vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
+    return 1;
+}
+
 /* Return value, -1 : multi-dests, non-negative value: dest_vcpu_id */
 int hvm_girq_dest_2_vcpu_id(struct domain *d, uint8_t dest, uint8_t dest_mode)
 {
diff -r 996c7726a376 -r 5024faf7c929 xen/drivers/passthrough/io.c
--- a/xen/drivers/passthrough/io.c      Thu May 26 14:49:50 2011 +0100
+++ b/xen/drivers/passthrough/io.c      Thu May 26 14:58:28 2011 +0100
@@ -454,10 +454,9 @@
 
 static int hvm_pci_msi_assert(struct domain *d, int pirq)
 {
-    if ( hvm_domain_use_pirq(d, pirq) )
-        return send_guest_pirq(d, pirq);
-    else
-        return vmsi_deliver(d, pirq);
+    return (hvm_domain_use_pirq(d, pirq)
+            ? send_guest_pirq(d, pirq)
+            : vmsi_deliver_pirq(d, pirq));
 }
 #endif
 
diff -r 996c7726a376 -r 5024faf7c929 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Thu May 26 14:49:50 2011 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h     Thu May 26 14:58:28 2011 +0100
@@ -199,7 +199,11 @@
 void hvm_set_guest_time(struct vcpu *v, u64 guest_time);
 u64 hvm_get_guest_time(struct vcpu *v);
 
-int vmsi_deliver(struct domain *d, int pirq);
+int vmsi_deliver(
+    struct domain *d, int vector,
+    uint8_t dest, uint8_t dest_mode,
+    uint8_t delivery_mode, uint8_t trig_mode);
+int vmsi_deliver_pirq(struct domain *d, int pirq);
 int hvm_girq_dest_2_vcpu_id(struct domain *d, uint8_t dest, uint8_t dest_mode);
 
 #define hvm_paging_enabled(v) \
diff -r 996c7726a376 -r 5024faf7c929 xen/include/asm-x86/msi.h
--- a/xen/include/asm-x86/msi.h Thu May 26 14:49:50 2011 +0100
+++ b/xen/include/asm-x86/msi.h Thu May 26 14:58:28 2011 +0100
@@ -19,6 +19,7 @@
 #define MSI_DATA_DELIVERY_MODE_SHIFT   8
 #define  MSI_DATA_DELIVERY_FIXED       (0 << MSI_DATA_DELIVERY_MODE_SHIFT)
 #define  MSI_DATA_DELIVERY_LOWPRI      (1 << MSI_DATA_DELIVERY_MODE_SHIFT)
+#define  MSI_DATA_DELIVERY_MODE_MASK    0x00000700
 
 #define MSI_DATA_LEVEL_SHIFT           14
 #define         MSI_DATA_LEVEL_DEASSERT        (0 << MSI_DATA_LEVEL_SHIFT)
@@ -27,6 +28,7 @@
 #define MSI_DATA_TRIGGER_SHIFT         15
 #define  MSI_DATA_TRIGGER_EDGE         (0 << MSI_DATA_TRIGGER_SHIFT)
 #define  MSI_DATA_TRIGGER_LEVEL                (1 << MSI_DATA_TRIGGER_SHIFT)
+#define  MSI_DATA_TRIGGER_MASK          0x00008000
 
 /*
  * Shift/mask fields for msi address
@@ -39,6 +41,7 @@
 #define MSI_ADDR_DESTMODE_SHIFT     2
 #define MSI_ADDR_DESTMODE_PHYS      (0 << MSI_ADDR_DESTMODE_SHIFT)
 #define MSI_ADDR_DESTMODE_LOGIC     (1 << MSI_ADDR_DESTMODE_SHIFT)
+#define MSI_ADDR_DESTMODE_MASK      0x4
 
 #define MSI_ADDR_REDIRECTION_SHIFT  3
 #define MSI_ADDR_REDIRECTION_CPU    (0 << MSI_ADDR_REDIRECTION_SHIFT)
diff -r 996c7726a376 -r 5024faf7c929 xen/include/public/hvm/hvm_op.h
--- a/xen/include/public/hvm/hvm_op.h   Thu May 26 14:49:50 2011 +0100
+++ b/xen/include/public/hvm/hvm_op.h   Thu May 26 14:58:28 2011 +0100
@@ -240,4 +240,22 @@
 typedef struct xen_hvm_get_mem_type xen_hvm_get_mem_type_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_type_t);
 
+/* Following tools-only interfaces may change in future. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/* MSI injection for emulated devices */
+#define HVMOP_inj_msi         16
+struct xen_hvm_inj_msi {
+    /* Domain to be injected */
+    domid_t   domid;
+    /* Data -- lower 32 bits */
+    uint32_t  data;
+    /* Address (0xfeexxxxx) */
+    uint64_t  addr;
+};
+typedef struct xen_hvm_inj_msi xen_hvm_inj_msi_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_inj_msi_t);
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
diff -r 996c7726a376 -r 5024faf7c929 xen/include/xen/hvm/irq.h
--- a/xen/include/xen/hvm/irq.h Thu May 26 14:49:50 2011 +0100
+++ b/xen/include/xen/hvm/irq.h Thu May 26 14:58:28 2011 +0100
@@ -116,6 +116,8 @@
 
 void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
 
+void hvm_inj_msi(struct domain *d, uint64_t addr, uint32_t data);
+
 void hvm_maybe_deassert_evtchn_irq(void);
 void hvm_assert_evtchn_irq(struct vcpu *v);
 void hvm_set_callback_via(struct domain *d, uint64_t via);
diff -r 996c7726a376 -r 5024faf7c929 xen/include/xsm/xsm.h
--- a/xen/include/xsm/xsm.h     Thu May 26 14:49:50 2011 +0100
+++ b/xen/include/xsm/xsm.h     Thu May 26 14:58:28 2011 +0100
@@ -123,6 +123,7 @@
     int (*hvm_set_pci_intx_level) (struct domain *d);
     int (*hvm_set_isa_irq_level) (struct domain *d);
     int (*hvm_set_pci_link_route) (struct domain *d);
+    int (*hvm_inj_msi) (struct domain *d);
     int (*apic) (struct domain *d, int cmd);
     int (*assign_vector) (struct domain *d, uint32_t pirq);
     int (*xen_settime) (void);
@@ -507,6 +508,11 @@
     return xsm_call(hvm_set_pci_link_route(d));
 }
 
+static inline int xsm_hvm_inj_msi (struct domain *d)
+{
+    return xsm_call(hvm_inj_msi(d));
+}
+
 static inline int xsm_apic (struct domain *d, int cmd)
 {
     return xsm_call(apic(d, cmd));

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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