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

[Xen-changelog] [xen-unstable] [IA64] catch up `new Xen event channels'



# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 66c27919578f374b3d239b3db63830f7c1afb5df
# Parent  36b76e5514567dbf1a1b93f4a0decc4fb4bf1433
[IA64] catch up `new Xen event channels'

DM over to using the new Xen event channels for IPF

Signed-off-by: Tsunehisa Doi <Doi.Tsunehisa@xxxxxxxxxxxxxx>
Signed-off-by: Tomonari Horikoshi <t.horikoshi@xxxxxxxxxxxxxx>
---
 xen/arch/ia64/vmx/mmio.c        |   15 +---
 xen/arch/ia64/vmx/vmx_init.c    |   44 ++++++++++---
 xen/arch/ia64/vmx/vmx_support.c |  132 ++++++++++++++++++----------------------
 xen/arch/ia64/xen/domain.c      |    3 
 xen/include/asm-ia64/vmx.h      |    7 --
 xen/include/asm-ia64/vmx_vpd.h  |    3 
 6 files changed, 107 insertions(+), 97 deletions(-)

diff -r 36b76e551456 -r 66c27919578f xen/arch/ia64/vmx/mmio.c
--- a/xen/arch/ia64/vmx/mmio.c  Wed Aug 23 12:56:10 2006 -0600
+++ b/xen/arch/ia64/vmx/mmio.c  Wed Aug 23 13:13:51 2006 -0600
@@ -155,10 +155,9 @@ static void low_mmio_access(VCPU *vcpu, 
     p->type = 1;
     p->df = 0;
 
-    set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
-    p->state = STATE_IOREQ_READY;
-    evtchn_send(iopacket_port(v));
-    vmx_wait_io();
+    p->io_count++;
+
+    vmx_send_assist_req(v);
     if(dir==IOREQ_READ){ //read
         *val=p->u.data;
     }
@@ -187,11 +186,9 @@ static void legacy_io_access(VCPU *vcpu,
     p->type = 0;
     p->df = 0;
 
-    set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
-    p->state = STATE_IOREQ_READY;
-    evtchn_send(iopacket_port(v));
-
-    vmx_wait_io();
+    p->io_count++;
+
+    vmx_send_assist_req(v);
     if(dir==IOREQ_READ){ //read
         *val=p->u.data;
     }
diff -r 36b76e551456 -r 66c27919578f xen/arch/ia64/vmx/vmx_init.c
--- a/xen/arch/ia64/vmx/vmx_init.c      Wed Aug 23 12:56:10 2006 -0600
+++ b/xen/arch/ia64/vmx/vmx_init.c      Wed Aug 23 13:13:51 2006 -0600
@@ -206,7 +206,7 @@ vmx_create_vp(struct vcpu *v)
        u64 ret;
        vpd_t *vpd = (vpd_t *)v->arch.privregs;
        u64 ivt_base;
-    extern char vmx_ia64_ivt;
+       extern char vmx_ia64_ivt;
        /* ia64_ivt is function pointer, so need this tranlation */
        ivt_base = (u64) &vmx_ia64_ivt;
        printk("ivt_base: 0x%lx\n", ivt_base);
@@ -265,6 +265,29 @@ vmx_load_state(struct vcpu *v)
         * anchored in vcpu */
 }
 
+static void vmx_create_event_channels(struct vcpu *v)
+{
+       vcpu_iodata_t *p;
+       struct vcpu *o;
+
+       if (v->vcpu_id == 0) {
+               /* Ugly: create event channels for every vcpu when vcpu 0
+                  starts, so that they're available for ioemu to bind to. */
+               for_each_vcpu(v->domain, o) {
+                       p = get_vio(v->domain, o->vcpu_id);
+                       o->arch.arch_vmx.xen_port = p->vp_eport =
+                                       alloc_unbound_xen_event_channel(o, 0);
+                       DPRINTK("Allocated port %d for hvm.\n",
+                               o->arch.arch_vmx.xen_port);
+               }
+       }
+}
+
+static void vmx_release_assist_channel(struct vcpu *v)
+{
+       free_xen_event_channel(v, v->arch.arch_vmx.xen_port);
+}
+
 /*
  * Initialize VMX envirenment for guest. Only the 1st vp/vcpu
  * is registered here.
@@ -286,6 +309,8 @@ vmx_final_setup_guest(struct vcpu *v)
 #ifndef HASH_VHPT     
         init_domain_tlb(v);
 #endif
+       vmx_create_event_channels(v);
+
        /* v->arch.schedule_tail = arch_vmx_do_launch; */
        vmx_create_vp(v);
 
@@ -301,6 +326,15 @@ vmx_final_setup_guest(struct vcpu *v)
        set_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags);
        /* Set up guest 's indicator for VTi domain*/
        set_bit(ARCH_VMX_DOMAIN, &v->arch.arch_vmx.flags);
+}
+
+void
+vmx_relinquish_guest_resources(struct domain *d)
+{
+       struct vcpu *v;
+
+       for_each_vcpu(d, v)
+               vmx_release_assist_channel(v);
 }
 
 void
@@ -420,13 +454,5 @@ void vmx_setup_platform(struct domain *d
 
 void vmx_do_launch(struct vcpu *v)
 {
-       if (evtchn_bind_vcpu(iopacket_port(v), v->vcpu_id) < 0) {
-           printk("VMX domain bind port %d to vcpu %d failed!\n",
-               iopacket_port(v), v->vcpu_id);
-           domain_crash_synchronous();
-       }
-
-       clear_bit(iopacket_port(v), &v->domain->shared_info->evtchn_mask[0]);
-
        vmx_load_all_rr(v);
 }
diff -r 36b76e551456 -r 66c27919578f xen/arch/ia64/vmx/vmx_support.c
--- a/xen/arch/ia64/vmx/vmx_support.c   Wed Aug 23 12:56:10 2006 -0600
+++ b/xen/arch/ia64/vmx/vmx_support.c   Wed Aug 23 13:13:51 2006 -0600
@@ -1,4 +1,3 @@
-
 /* -*-  Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
 /*
  * vmx_support.c: vmx specific support interface.
@@ -22,45 +21,11 @@
 #include <xen/config.h>
 #include <xen/sched.h>
 #include <xen/hypercall.h>
+#include <xen/event.h>
 #include <public/sched.h>
 #include <public/hvm/ioreq.h>
 #include <asm/vmx.h>
 #include <asm/vmx_vcpu.h>
-
-/*
- * I/O emulation should be atomic from domain point of view. However,
- * when emulation code is waiting for I/O completion by blocking,
- * other events like DM interrupt, VBD, etc. may come and unblock
- * current exection flow. So we have to prepare for re-block if unblocked
- * by non I/O completion event. After io emulation is done, re-enable
- * pending indicaion if other ports are pending
- */
-void vmx_wait_io(void)
-{
-    struct vcpu *v = current;
-    struct domain *d = v->domain;
-    int port = iopacket_port(v);
-
-    for (;;) {
-        if (test_and_clear_bit(0, &v->vcpu_info->evtchn_upcall_pending) &&
-            test_and_clear_bit(port / BITS_PER_LONG,
-                                     &v->vcpu_info->evtchn_pending_sel) &&
-            test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]))
-            vmx_io_assist(v);
-
-        if (!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
-            break;
-
-        do_sched_op_compat(SCHEDOP_block, 0);
-    }
-
-    /* re-enable indication if other pending events */
-    if (d->shared_info->evtchn_pending[port / BITS_PER_LONG])
-        set_bit(port / BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
-
-    if (v->vcpu_info->evtchn_pending_sel)
-        set_bit(0, &v->vcpu_info->evtchn_upcall_pending);
-}
 
 /*
  * Only place to call vmx_io_assist is mmio/legacy_io emulation.
@@ -83,17 +48,15 @@ void vmx_io_assist(struct vcpu *v)
 
     p = &vio->vp_ioreq;
 
-    if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
-       if (p->state != STATE_IORESP_READY) {
-           /* Can't block here, for the same reason as other places to
-            * use vmx_wait_io. Simple return is safe since vmx_wait_io will
-            * try to block again
-            */
-           return; 
-       } else
-           p->state = STATE_INVALID;
-
-       clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+    if (p->state == STATE_IORESP_READY) {
+        p->state = STATE_INVALID;
+    }
+    else {
+        /* Can't block here, for the same reason as other places to
+         * use vmx_wait_io. Simple return is safe since vmx_wait_io will
+         * try to block again
+         */
+        return;
     }
 }
 
@@ -108,31 +71,6 @@ void vmx_io_assist(struct vcpu *v)
  */
 void vmx_intr_assist(struct vcpu *v)
 {
-    vcpu_iodata_t *vio;
-    struct domain *d = v->domain;
-    extern void vmx_vcpu_pend_batch_interrupt(VCPU *vcpu,
-                                       unsigned long *pend_irr);
-    int port = iopacket_port(v);
-
-    if (test_bit(port, &d->shared_info->evtchn_pending[0]) ||
-       test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
-       vmx_wait_io();
-
-    /* I/O emulation is atomic, so it's impossible to see execution flow
-     * out of vmx_wait_io, when guest is still waiting for response.
-     */
-    if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
-       panic_domain(vcpu_regs(v),"!!!Bad resume to guest before I/O emulation 
is done.\n");
-
-    /* Even without event pending, we still need to sync pending bits
-     * between DM and vlsapic. The reason is that interrupt delivery
-     * shares same event channel as I/O emulation, with corresponding
-     * indicator possibly cleared when vmx_wait_io().
-     */
-    vio = get_vio(v->domain, v->vcpu_id);
-    if (!vio)
-       panic_domain(vcpu_regs(v),"Corruption: bad shared page: %lx\n", 
(unsigned long)vio);
-
 #ifdef V_IOSAPIC_READY
     /* Confirm virtual interrupt line signals, and set pending bits in vpd */
     if(v->vcpu_id==0)
@@ -140,3 +78,53 @@ void vmx_intr_assist(struct vcpu *v)
 #endif
     return;
 }
+
+void vmx_send_assist_req(struct vcpu *v)
+{
+    ioreq_t *p;
+
+    p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
+    if (unlikely(p->state != STATE_INVALID)) {
+        /* This indicates a bug in the device model.  Crash the
+           domain. */
+        printk("Device model set bad IO state %d.\n", p->state);
+        domain_crash(v->domain);
+        return;
+    }
+    wmb();
+    p->state = STATE_IOREQ_READY;
+    notify_via_xen_event_channel(v->arch.arch_vmx.xen_port);
+
+    /*
+     * Waiting for MMIO completion
+     *   like the wait_on_xen_event_channel() macro like...
+     *   but, we can't call do_softirq() at this point..
+     */
+    for (;;) {
+        if (p->state != STATE_IOREQ_READY &&
+            p->state != STATE_IOREQ_INPROCESS)
+            break;
+
+        set_bit(_VCPUF_blocked_in_xen, &current->vcpu_flags);
+        mb(); /* set blocked status /then/ re-evaluate condition */
+        if (p->state != STATE_IOREQ_READY &&
+            p->state != STATE_IOREQ_INPROCESS)
+        {
+            clear_bit(_VCPUF_blocked_in_xen, &current->vcpu_flags);
+            break;
+        }
+
+        /* I want to call __enter_scheduler() only */
+        do_sched_op_compat(SCHEDOP_yield, 0);
+        mb();
+    }
+
+    /* the code under this line is completer phase... */
+    vmx_io_assist(v);
+}
+
+/* Wake up a vcpu whihc is waiting for interrupts to come in */
+void vmx_prod_vcpu(struct vcpu *v)
+{
+    vcpu_unblock(v);
+}
diff -r 36b76e551456 -r 66c27919578f xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Wed Aug 23 12:56:10 2006 -0600
+++ b/xen/arch/ia64/xen/domain.c        Wed Aug 23 13:13:51 2006 -0600
@@ -543,6 +543,9 @@ void domain_relinquish_resources(struct 
     // relase page traversing d->arch.mm.
     relinquish_mm(d);
 
+    if (d->vcpu[0] && VMX_DOMAIN(d->vcpu[0]))
+           vmx_relinquish_guest_resources(d);
+
     relinquish_memory(d, &d->xenpage_list);
     relinquish_memory(d, &d->page_list);
 
diff -r 36b76e551456 -r 66c27919578f xen/include/asm-ia64/vmx.h
--- a/xen/include/asm-ia64/vmx.h        Wed Aug 23 12:56:10 2006 -0600
+++ b/xen/include/asm-ia64/vmx.h        Wed Aug 23 13:13:51 2006 -0600
@@ -35,7 +35,6 @@ extern void vmx_save_state(struct vcpu *
 extern void vmx_save_state(struct vcpu *v);
 extern void vmx_load_state(struct vcpu *v);
 extern void vmx_setup_platform(struct domain *d);
-extern void vmx_wait_io(void);
 extern void vmx_io_assist(struct vcpu *v);
 extern int ia64_hypercall (struct pt_regs *regs);
 extern void vmx_save_state(struct vcpu *v);
@@ -53,17 +52,13 @@ extern void vmx_intr_assist(struct vcpu 
 extern void vmx_intr_assist(struct vcpu *v);
 extern void set_illegal_op_isr (struct vcpu *vcpu);
 extern void illegal_op (struct vcpu *vcpu);
+extern void vmx_relinquish_guest_resources(struct domain *d);
 extern void vmx_relinquish_vcpu_resources(struct vcpu *v);
 extern void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err);
 
 static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu)
 {
     return &((shared_iopage_t 
*)d->arch.vmx_platform.shared_page_va)->vcpu_iodata[cpu];
-}
-
-static inline int iopacket_port(struct vcpu *v)
-{
-    return get_vio(v->domain, v->vcpu_id)->vp_eport;
 }
 
 static inline shared_iopage_t *get_sp(struct domain *d)
diff -r 36b76e551456 -r 66c27919578f xen/include/asm-ia64/vmx_vpd.h
--- a/xen/include/asm-ia64/vmx_vpd.h    Wed Aug 23 12:56:10 2006 -0600
+++ b/xen/include/asm-ia64/vmx_vpd.h    Wed Aug 23 13:13:51 2006 -0600
@@ -96,7 +96,8 @@ struct arch_vmx_struct {
 //    unsigned long   rfi_ipsr;
 //    unsigned long   rfi_ifs;
 //     unsigned long   in_service[4];  // vLsapic inservice IRQ bits
-       unsigned long   flags;
+    unsigned long   flags;
+    unsigned long   xen_port;
 #ifdef VTI_DEBUG
     unsigned long  ivt_current;
     struct ivt_debug ivt_debug[IVT_DEBUG_MAX];

_______________________________________________
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®.