Wei Liu
2011-May-26 03:08 UTC
[Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
commit 176dc2a26b4b9dd0fe30fab3b168722766218245
Author: Wei Liu <liuw@liuw.name>
Date: Thu May 26 10:23:01 2011 +0800
x86: Add a new operation in HVMOP to inject emulated MSI.
The original vmsi_deliver is renamed to vmsi_deliver_irq. New
vmsi_deliver is dedicated to the actually delivering.
Signed-off-by: Wei Liu <liuw@liuw.name>
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index b02be7b..d88e8b8 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3293,6 +3293,36 @@ static int hvmop_set_pci_link_route(
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;
@@ -3571,6 +3601,11 @@ long do_hvm_op(unsigned long op,
XEN_GUEST_HANDLE(void) arg)
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 --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index f560e39..57271e6 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -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,24 @@ void hvm_set_pci_link_route(struct domain *d, u8
link, u8 isa_irq)
d->domain_id, link, old_isa_irq, isa_irq);
}
+
+extern void vmsi_deliver(struct domain *d, int vector,
+ uint8_t dest, uint8_t dest_mode,
+ uint8_t delivery_mode, uint8_t trig_mode);
+void hvm_inj_msi(struct domain *d, u64 addr, u32 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 --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index eee802a..cc6de8b 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -65,29 +65,13 @@ static void vmsi_inj_irq(
}
}
-int vmsi_deliver(struct domain *d, int pirq)
+void 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:
@@ -122,6 +106,30 @@ int vmsi_deliver(struct domain *d, int pirq)
delivery_mode);
break;
}
+}
+
+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;
}
diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c
index 67b0223..848c3e5 100644
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -452,13 +452,13 @@ void hvm_dpci_msi_eoi(struct domain *d, int vector)
spin_unlock(&d->event_lock);
}
-extern int vmsi_deliver(struct domain *d, int pirq);
+extern int vmsi_deliver_pirq(struct domain *d, int pirq);
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 vmsi_deliver_pirq(d, pirq);
}
#endif
diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
index 0848616..ba114a4 100644
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -17,6 +17,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)
@@ -25,6 +26,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
@@ -37,6 +39,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 --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
index 2a597da..e9f7994 100644
--- a/xen/include/public/hvm/hvm_op.h
+++ b/xen/include/public/hvm/hvm_op.h
@@ -82,11 +82,24 @@ typedef enum {
HVMMEM_mmio_dm, /* Reads and write go to the device model */
} hvmmem_type_t;
+/* MSI injection for emulated devices */
+#define HVMOP_inj_msi 6
+struct xen_hvm_inj_msi {
+ /* Domain to be injected */
+ domid_t domid;
+ /* Address (0xfeeXXXXX) */
+ uint64_t addr;
+ /* Data -- lower 32 bits */
+ uint32_t data;
+};
+typedef struct xen_hvm_inj_msi xen_hvm_inj_msi_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_inj_msi_t);
+
/* Following tools-only interfaces may change in future. */
#if defined(__XEN__) || defined(__XEN_TOOLS__)
/* Track dirty VRAM. */
-#define HVMOP_track_dirty_vram 6
+#define HVMOP_track_dirty_vram 7
struct xen_hvm_track_dirty_vram {
/* Domain to be tracked. */
domid_t domid;
@@ -102,7 +115,7 @@ typedef struct xen_hvm_track_dirty_vram
xen_hvm_track_dirty_vram_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t);
/* Notify that some pages got modified by the Device Model. */
-#define HVMOP_modified_memory 7
+#define HVMOP_modified_memory 8
struct xen_hvm_modified_memory {
/* Domain to be updated. */
domid_t domid;
@@ -114,7 +127,7 @@ struct xen_hvm_modified_memory {
typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t);
-#define HVMOP_set_mem_type 8
+#define HVMOP_set_mem_type 9
/* Notify that a region of memory is to be treated in a specific way. */
struct xen_hvm_set_mem_type {
/* Domain to be updated. */
@@ -132,7 +145,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_type_t);
#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
/* Hint from PV drivers for pagetable destruction. */
-#define HVMOP_pagetable_dying 9
+#define HVMOP_pagetable_dying 10
struct xen_hvm_pagetable_dying {
/* Domain with a pagetable about to be destroyed. */
domid_t domid;
@@ -144,14 +157,14 @@ typedef struct xen_hvm_pagetable_dying
xen_hvm_pagetable_dying_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_pagetable_dying_t);
/* Get the current Xen time, in nanoseconds since system boot. */
-#define HVMOP_get_time 10
+#define HVMOP_get_time 11
struct xen_hvm_get_time {
uint64_t now; /* OUT */
};
typedef struct xen_hvm_get_time xen_hvm_get_time_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_time_t);
-#define HVMOP_xentrace 11
+#define HVMOP_xentrace 12
struct xen_hvm_xentrace {
uint16_t event, extra_bytes;
uint8_t extra[TRACE_EXTRA_MAX * sizeof(uint32_t)];
@@ -162,7 +175,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t);
/* Following tools-only interfaces may change in future. */
#if defined(__XEN__) || defined(__XEN_TOOLS__)
-#define HVMOP_set_mem_access 12
+#define HVMOP_set_mem_access 13
typedef enum {
HVMMEM_access_n,
HVMMEM_access_r,
@@ -190,7 +203,7 @@ struct xen_hvm_set_mem_access {
typedef struct xen_hvm_set_mem_access xen_hvm_set_mem_access_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_access_t);
-#define HVMOP_get_mem_access 13
+#define HVMOP_get_mem_access 14
/* Get the specific access type for that region of memory */
struct xen_hvm_get_mem_access {
/* Domain to be queried. */
@@ -203,7 +216,7 @@ struct xen_hvm_get_mem_access {
typedef struct xen_hvm_get_mem_access xen_hvm_get_mem_access_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_access_t);
-#define HVMOP_inject_trap 14
+#define HVMOP_inject_trap 15
/* Inject a trap into a VCPU, which will get taken up on the next
* scheduling of it. Note that the caller should know enough of the
* state of the CPU before injecting, to know what the effect of
@@ -226,7 +239,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_trap_t);
#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
-#define HVMOP_get_mem_type 15
+#define HVMOP_get_mem_type 16
/* Return hvmmem_type_t for the specified pfn. */
struct xen_hvm_get_mem_type {
/* Domain to be queried. */
diff --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h
index ae0531b..129a880 100644
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -115,6 +115,7 @@ void hvm_isa_irq_deassert(
struct domain *d, unsigned int isa_irq);
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
+void hvm_inj_msi(struct domain *d, u64 addr, u32 data);
void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 7539cc7..c16818c 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -123,6 +123,7 @@ struct xsm_operations {
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 @@ static inline int xsm_hvm_set_pci_link_route
(struct domain *d)
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));
--
Best regards
Wei Liu
Twitter: @iliuw
Site: http://liuw.name
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Tian, Kevin
2011-May-26 03:21 UTC
RE: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
> From: Wei Liu > Sent: Thursday, May 26, 2011 11:09 AM > > commit 176dc2a26b4b9dd0fe30fab3b168722766218245 > Author: Wei Liu <liuw@liuw.name> > Date: Thu May 26 10:23:01 2011 +0800 > > x86: Add a new operation in HVMOP to inject emulated MSI. > > The original vmsi_deliver is renamed to vmsi_deliver_irq. Newin your patch you mean vmsi_deliver_pirq which is inconsistent.> vmsi_deliver is dedicated to the actually delivering. > > Signed-off-by: Wei Liu <liuw@liuw.name> > > --- a/xen/include/public/hvm/hvm_op.h > +++ b/xen/include/public/hvm/hvm_op.h > @@ -82,11 +82,24 @@ typedef enum { > HVMMEM_mmio_dm, /* Reads and write go to the device > model */ > } hvmmem_type_t; > > +/* MSI injection for emulated devices */ > +#define HVMOP_inj_msi 6 > +struct xen_hvm_inj_msi { > + /* Domain to be injected */ > + domid_t domid; > + /* Address (0xfeeXXXXX) */ > + uint64_t addr; > + /* Data -- lower 32 bits */ > + uint32_t data; > +}; > +typedef struct xen_hvm_inj_msi xen_hvm_inj_msi_t; > +DEFINE_XEN_GUEST_HANDLE(xen_hvm_inj_msi_t); > + > /* Following tools-only interfaces may change in future. */ > #if defined(__XEN__) || defined(__XEN_TOOLS__) > > /* Track dirty VRAM. */ > -#define HVMOP_track_dirty_vram 6 > +#define HVMOP_track_dirty_vram 7 > struct xen_hvm_track_dirty_vram { > /* Domain to be tracked. */ > domid_t domid;This breaks backward API compatibility. Thanks Kevin _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Liu
2011-May-26 03:30 UTC
Re: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
On Thu, May 26, 2011 at 11:21 AM, Tian, Kevin <kevin.tian@intel.com> wrote:>> From: Wei Liu >> Sent: Thursday, May 26, 2011 11:09 AM >> >> commit 176dc2a26b4b9dd0fe30fab3b168722766218245 >> Author: Wei Liu <liuw@liuw.name> >> Date: Thu May 26 10:23:01 2011 +0800 >> >> x86: Add a new operation in HVMOP to inject emulated MSI. >> >> The original vmsi_deliver is renamed to vmsi_deliver_irq. New > > in your patch you mean vmsi_deliver_pirq which is inconsistent. > >> vmsi_deliver is dedicated to the actually delivering. >> >> Signed-off-by: Wei Liu <liuw@liuw.name> >> >> --- a/xen/include/public/hvm/hvm_op.h >> +++ b/xen/include/public/hvm/hvm_op.h >> @@ -82,11 +82,24 @@ typedef enum { >> HVMMEM_mmio_dm, /* Reads and write go to the device >> model */ >> } hvmmem_type_t; >> >> +/* MSI injection for emulated devices */ >> +#define HVMOP_inj_msi 6 >> +struct xen_hvm_inj_msi { >> + /* Domain to be injected */ >> + domid_t domid; >> + /* Address (0xfeeXXXXX) */ >> + uint64_t addr; >> + /* Data -- lower 32 bits */ >> + uint32_t data; >> +}; >> +typedef struct xen_hvm_inj_msi xen_hvm_inj_msi_t; >> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_inj_msi_t); >> + >> /* Following tools-only interfaces may change in future. */ >> #if defined(__XEN__) || defined(__XEN_TOOLS__) >> >> /* Track dirty VRAM. */ >> -#define HVMOP_track_dirty_vram 6 >> +#define HVMOP_track_dirty_vram 7 >> struct xen_hvm_track_dirty_vram { >> /* Domain to be tracked. */ >> domid_t domid; > > This breaks backward API compatibility. > > Thanks > Kevin >Stefano suggests this rename. The only function that invokes vmsi_deliver() is hvm_pci_msi_assert(), IIRC. That has been taken care of. -- Best regards Wei Liu Twitter: @iliuw Site: http://liuw.name _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Tian, Kevin
2011-May-26 05:26 UTC
RE: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
> From: Wei Liu [mailto:liuw@liuw.name] > Sent: Thursday, May 26, 2011 11:30 AM > > On Thu, May 26, 2011 at 11:21 AM, Tian, Kevin <kevin.tian@intel.com> wrote: > >> From: Wei Liu > >> Sent: Thursday, May 26, 2011 11:09 AM > >> > >> commit 176dc2a26b4b9dd0fe30fab3b168722766218245 > >> Author: Wei Liu <liuw@liuw.name> > >> Date: Thu May 26 10:23:01 2011 +0800 > >> > >> x86: Add a new operation in HVMOP to inject emulated MSI. > >> > >> The original vmsi_deliver is renamed to vmsi_deliver_irq. New > > > > in your patch you mean vmsi_deliver_pirq which is inconsistent.the comment says vmsi_deliver_irq while your code has vmsi_deliver_pirq...> > > >> vmsi_deliver is dedicated to the actually delivering. > >> > >> Signed-off-by: Wei Liu <liuw@liuw.name> > >> > >> --- a/xen/include/public/hvm/hvm_op.h > >> +++ b/xen/include/public/hvm/hvm_op.h > >> @@ -82,11 +82,24 @@ typedef enum { > >> HVMMEM_mmio_dm, /* Reads and write go to the > device > >> model */ > >> } hvmmem_type_t; > >> > >> +/* MSI injection for emulated devices */ > >> +#define HVMOP_inj_msi 6 > >> +struct xen_hvm_inj_msi { > >> + /* Domain to be injected */ > >> + domid_t domid; > >> + /* Address (0xfeeXXXXX) */ > >> + uint64_t addr; > >> + /* Data -- lower 32 bits */ > >> + uint32_t data; > >> +}; > >> +typedef struct xen_hvm_inj_msi xen_hvm_inj_msi_t; > >> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_inj_msi_t); > >> + > >> /* Following tools-only interfaces may change in future. */ > >> #if defined(__XEN__) || defined(__XEN_TOOLS__) > >> > >> /* Track dirty VRAM. */ > >> -#define HVMOP_track_dirty_vram 6 > >> +#define HVMOP_track_dirty_vram 7 > >> struct xen_hvm_track_dirty_vram { > >> /* Domain to be tracked. */ > >> domid_t domid; > > > > This breaks backward API compatibility. > > > > Thanks > > Kevin > > > > Stefano suggests this rename. > > The only function that invokes vmsi_deliver() is hvm_pci_msi_assert(), > IIRC. That has been taken care of. >You didn't catch my comment. you change existing HVMOP command index which breaks backward compatibility. Thanks Kevin _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Liu
2011-May-26 05:43 UTC
Re: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
On Thu, May 26, 2011 at 1:26 PM, Tian, Kevin <kevin.tian@intel.com> wrote:>> From: Wei Liu [mailto:liuw@liuw.name] >> Sent: Thursday, May 26, 2011 11:30 AM >> >> On Thu, May 26, 2011 at 11:21 AM, Tian, Kevin <kevin.tian@intel.com> wrote: >> >> From: Wei Liu >> >> Sent: Thursday, May 26, 2011 11:09 AM >> >> >> >> commit 176dc2a26b4b9dd0fe30fab3b168722766218245 >> >> Author: Wei Liu <liuw@liuw.name> >> >> Date: Thu May 26 10:23:01 2011 +0800 >> >> >> >> x86: Add a new operation in HVMOP to inject emulated MSI. >> >> >> >> The original vmsi_deliver is renamed to vmsi_deliver_irq. New >> > >> > in your patch you mean vmsi_deliver_pirq which is inconsistent. > > the comment says vmsi_deliver_irq while your code has vmsi_deliver_pirq... > >> > >> >> vmsi_deliver is dedicated to the actually delivering. >> >> >> >> Signed-off-by: Wei Liu <liuw@liuw.name> >> >> >> >> --- a/xen/include/public/hvm/hvm_op.h >> >> +++ b/xen/include/public/hvm/hvm_op.h >> >> @@ -82,11 +82,24 @@ typedef enum { >> >> HVMMEM_mmio_dm, /* Reads and write go to the >> device >> >> model */ >> >> } hvmmem_type_t; >> >> >> >> +/* MSI injection for emulated devices */ >> >> +#define HVMOP_inj_msi 6 >> >> +struct xen_hvm_inj_msi { >> >> + /* Domain to be injected */ >> >> + domid_t domid; >> >> + /* Address (0xfeeXXXXX) */ >> >> + uint64_t addr; >> >> + /* Data -- lower 32 bits */ >> >> + uint32_t data; >> >> +}; >> >> +typedef struct xen_hvm_inj_msi xen_hvm_inj_msi_t; >> >> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_inj_msi_t); >> >> + >> >> /* Following tools-only interfaces may change in future. */ >> >> #if defined(__XEN__) || defined(__XEN_TOOLS__) >> >> >> >> /* Track dirty VRAM. */ >> >> -#define HVMOP_track_dirty_vram 6 >> >> +#define HVMOP_track_dirty_vram 7 >> >> struct xen_hvm_track_dirty_vram { >> >> /* Domain to be tracked. */ >> >> domid_t domid; >> > >> > This breaks backward API compatibility. >> > >> > Thanks >> > Kevin >> > >> >> Stefano suggests this rename. >> >> The only function that invokes vmsi_deliver() is hvm_pci_msi_assert(), >> IIRC. That has been taken care of. >> > > You didn''t catch my comment. > > you change existing HVMOP command index which breaks backward > compatibility. > > Thanks > Kevin >Hmm... I see. Keir pointed out that problem too. I will revise it and push this patch again. -- Best regards Wei Liu Twitter: @iliuw Site: http://liuw.name _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Liu
2011-May-26 06:31 UTC
Re: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
Revised version of the patch.
---------------------------------------------------------
commit 75c48132b664b0220712a3855f93bc9eadfd35c6
Author: Wei Liu <liuw@liuw.name>
Date: Thu May 26 14:18:07 2011 +0800
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@liuw.name>
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index b02be7b..d88e8b8 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3293,6 +3293,36 @@ static int hvmop_set_pci_link_route(
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;
@@ -3571,6 +3601,11 @@ long do_hvm_op(unsigned long op,
XEN_GUEST_HANDLE(void) arg)
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 --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index f560e39..57271e6 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -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,24 @@ void hvm_set_pci_link_route(struct domain *d, u8
link, u8 isa_irq)
d->domain_id, link, old_isa_irq, isa_irq);
}
+
+extern void vmsi_deliver(struct domain *d, int vector,
+ uint8_t dest, uint8_t dest_mode,
+ uint8_t delivery_mode, uint8_t trig_mode);
+void hvm_inj_msi(struct domain *d, u64 addr, u32 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 --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index eee802a..cc6de8b 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -65,29 +65,13 @@ static void vmsi_inj_irq(
}
}
-int vmsi_deliver(struct domain *d, int pirq)
+void 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:
@@ -122,6 +106,30 @@ int vmsi_deliver(struct domain *d, int pirq)
delivery_mode);
break;
}
+}
+
+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;
}
diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c
index 67b0223..848c3e5 100644
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -452,13 +452,13 @@ void hvm_dpci_msi_eoi(struct domain *d, int vector)
spin_unlock(&d->event_lock);
}
-extern int vmsi_deliver(struct domain *d, int pirq);
+extern int vmsi_deliver_pirq(struct domain *d, int pirq);
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 vmsi_deliver_pirq(d, pirq);
}
#endif
diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
index 0848616..ba114a4 100644
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -17,6 +17,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)
@@ -25,6 +26,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
@@ -37,6 +39,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 --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
index 2a597da..7617341 100644
--- a/xen/include/public/hvm/hvm_op.h
+++ b/xen/include/public/hvm/hvm_op.h
@@ -240,4 +240,23 @@ struct xen_hvm_get_mem_type {
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;
+ /* Address (0xfeeXXXXX) */
+ uint64_t addr;
+ /* Data -- lower 32 bits */
+ uint32_t data;
+};
+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 --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h
index ae0531b..129a880 100644
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -115,6 +115,7 @@ void hvm_isa_irq_deassert(
struct domain *d, unsigned int isa_irq);
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
+void hvm_inj_msi(struct domain *d, u64 addr, u32 data);
void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 7539cc7..c16818c 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -123,6 +123,7 @@ struct xsm_operations {
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 @@ static inline int xsm_hvm_set_pci_link_route
(struct domain *d)
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));
--
Best regards
Wei Liu
Twitter: @iliuw
Site: http://liuw.name
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Tim Deegan
2011-May-26 08:43 UTC
Re: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
Hi, At 07:31 +0100 on 26 May (1306395103), Wei Liu wrote:> > + > +extern void vmsi_deliver(struct domain *d, int vector, > + uint8_t dest, uint8_t dest_mode, > + uint8_t delivery_mode, uint8_t trig_mode);Please put this declaration in a header file rather than in the C file. xen/pci.h seems to have some of the other functions from the same file in it.> diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c > index 67b0223..848c3e5 100644 > --- a/xen/drivers/passthrough/io.c > +++ b/xen/drivers/passthrough/io.c > @@ -452,13 +452,13 @@ void hvm_dpci_msi_eoi(struct domain *d, int vector) > spin_unlock(&d->event_lock); > } > > -extern int vmsi_deliver(struct domain *d, int pirq); > +extern int vmsi_deliver_pirq(struct domain *d, int pirq);Likewise (I know this one was like this already but you might as well fix it since you''re alraedy touching this line).> diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h > index 2a597da..7617341 100644 > --- a/xen/include/public/hvm/hvm_op.h > +++ b/xen/include/public/hvm/hvm_op.h > @@ -240,4 +240,23 @@ struct xen_hvm_get_mem_type { > 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; > + /* Address (0xfeeXXXXX) */ > + uint64_t addr; > + /* Data -- lower 32 bits */ > + uint32_t data; > +};Please rearrange this so that it has the same size and layout on 32-bit and 64-bit builds. Cheers, Tim. -- Tim Deegan <Tim.Deegan@citrix.com> Principal Software Engineer, Xen Platform Team Citrix Systems UK Ltd. (Company #02937203, SL9 0BG) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2011-May-26 09:10 UTC
Re: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
On 26/05/2011 09:43, "Tim Deegan" <Tim.Deegan@citrix.com> wrote:>> +/* MSI injection for emulated devices */ >> +#define HVMOP_inj_msi 16 >> +struct xen_hvm_inj_msi { >> + /* Domain to be injected */ >> + domid_t domid; >> + /* Address (0xfeeXXXXX) */ >> + uint64_t addr; >> + /* Data -- lower 32 bits */ >> + uint32_t data; >> +}; > > Please rearrange this so that it has the same size and layout on 32-bit > and 64-bit builds.You can do this most easily be simply swapping the second and third fields. -- Keir _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Stefano Stabellini
2011-May-26 11:25 UTC
Re: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
On Thu, 26 May 2011, Wei Liu wrote:> Revised version of the patch. > > 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@liuw.name> >Apart from the other comments (Tim''s comments are still not addressed) I think is OK _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2011-May-26 11:49 UTC
Re: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
On 26/05/2011 12:25, "Stefano Stabellini" <Stefano.Stabellini@eu.citrix.com> wrote:> On Thu, 26 May 2011, Wei Liu wrote: >> Revised version of the patch. >> >> 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@liuw.name> >> > > Apart from the other comments (Tim''s comments are still not addressed) I > think is OKI will fix up and apply the patch. -- Keir> > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Liu
2011-May-26 12:51 UTC
Re: [Xen-devel] [PATCH 1/2] Xen: enabling emulated MSI injection
On Thu, May 26, 2011 at 7:25 PM, Stefano Stabellini <stefano.stabellini@eu.citrix.com> wrote:> On Thu, 26 May 2011, Wei Liu wrote: >> Revised version of the patch. >> >> 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@liuw.name> >> > > Apart from the other comments (Tim''s comments are still not addressed) I > think is OK > >Cleaned up the patch. Put declarations in xen/pci and rearrange struct hvm_inj_msi. -----8<---------------- commit ef545e8fe99c85b60ea2630c0da40ba0cd1f9674 Author: Wei Liu <liuw@liuw.name> Date: Thu May 26 20:24:40 2011 +0800 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@liuw.name> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index b02be7b..d88e8b8 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3293,6 +3293,36 @@ static int hvmop_set_pci_link_route( 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; @@ -3571,6 +3601,11 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) 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 --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c index f560e39..c9d080c 100644 --- a/xen/arch/x86/hvm/irq.c +++ b/xen/arch/x86/hvm/irq.c @@ -24,8 +24,10 @@ #include <xen/event.h> #include <xen/sched.h> #include <xen/irq.h> +#include <xen/pci.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 +261,20 @@ void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq) d->domain_id, link, old_isa_irq, isa_irq); } +void hvm_inj_msi(struct domain *d, u64 addr, u32 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 --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c index eee802a..cc6de8b 100644 --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -65,29 +65,13 @@ static void vmsi_inj_irq( } } -int vmsi_deliver(struct domain *d, int pirq) +void 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: @@ -122,6 +106,30 @@ int vmsi_deliver(struct domain *d, int pirq) delivery_mode); break; } +} + +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; } diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c index 67b0223..b21294c 100644 --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -25,6 +25,7 @@ #include <asm/hvm/support.h> #include <xen/hvm/irq.h> #include <xen/tasklet.h> +#include <xen/pci.h> struct rangeset *__read_mostly mmio_ro_ranges; @@ -452,13 +453,12 @@ void hvm_dpci_msi_eoi(struct domain *d, int vector) spin_unlock(&d->event_lock); } -extern int vmsi_deliver(struct domain *d, int pirq); 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 vmsi_deliver_pirq(d, pirq); } #endif diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h index 0848616..ba114a4 100644 --- a/xen/include/asm-x86/msi.h +++ b/xen/include/asm-x86/msi.h @@ -17,6 +17,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) @@ -25,6 +26,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 @@ -37,6 +39,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 --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h index 2a597da..b8a9c8c 100644 --- a/xen/include/public/hvm/hvm_op.h +++ b/xen/include/public/hvm/hvm_op.h @@ -240,4 +240,23 @@ struct xen_hvm_get_mem_type { 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 --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h index ae0531b..129a880 100644 --- a/xen/include/xen/hvm/irq.h +++ b/xen/include/xen/hvm/irq.h @@ -115,6 +115,7 @@ void hvm_isa_irq_deassert( struct domain *d, unsigned int isa_irq); void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq); +void hvm_inj_msi(struct domain *d, u64 addr, u32 data); void hvm_maybe_deassert_evtchn_irq(void); void hvm_assert_evtchn_irq(struct vcpu *v); diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h index 40c9847..cf8f254 100644 --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -121,4 +121,10 @@ int msixtbl_pt_register(struct domain *d, int pirq, uint64_t gtable); void msixtbl_pt_unregister(struct domain *d, int pirq); void pci_enable_acs(struct pci_dev *pdev); +/* VMSI delivery */ +void 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); + #endif /* __XEN_PCI_H__ */ diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 7539cc7..c16818c 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -123,6 +123,7 @@ struct xsm_operations { 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 @@ static inline int xsm_hvm_set_pci_link_route (struct domain *d) 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)); -- Best regards Wei Liu Twitter: @iliuw Site: http://liuw.name _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel