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

[Xen-changelog] [xen-unstable] [IA64] Self IO EMUlator (sioemu) - Hypervisor part



# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1203433882 25200
# Node ID 430a036ab26115335698230c815051b3ee327363
# Parent  c750c7177d63c1c6aa44917bff4b996ea745ea96
[IA64] Self IO EMUlator (sioemu) - Hypervisor part

Implements Self IO-EMUlator.  It's an hybrid domain: looks
like PV from an external point of view but runs with VTI enabled.

All MMIO/IO writes/reads are reflected to the firmware, which converts the
access to PV drivers requests.

Signed-off-by: Tristan Gingold <tgingold@xxxxxxx>
---
 xen/arch/ia64/vmx/Makefile            |    1 
 xen/arch/ia64/vmx/mmio.c              |   42 +++++-
 xen/arch/ia64/vmx/sioemu.c            |  219 ++++++++++++++++++++++++++++++++++
 xen/arch/ia64/vmx/vmx_fault.c         |  184 +++++++++++++++-------------
 xen/arch/ia64/vmx/vmx_hypercall.c     |   10 +
 xen/arch/ia64/vmx/vmx_init.c          |   36 ++++-
 xen/arch/ia64/xen/dom0_ops.c          |    6 
 xen/arch/ia64/xen/hypercall.c         |    8 +
 xen/arch/ia64/xen/xensetup.c          |    9 -
 xen/arch/ia64/xen/xentime.c           |    7 +
 xen/include/asm-ia64/dom_fw.h         |    3 
 xen/include/asm-ia64/domain.h         |    5 
 xen/include/asm-ia64/sioemu.h         |   30 ++++
 xen/include/asm-ia64/time.h           |    2 
 xen/include/asm-ia64/vmmu.h           |    1 
 xen/include/asm-ia64/vmx_vpd.h        |    3 
 xen/include/public/arch-ia64/sioemu.h |   42 ++++++
 xen/include/public/domctl.h           |    2 
 18 files changed, 503 insertions(+), 107 deletions(-)

diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/vmx/Makefile
--- a/xen/arch/ia64/vmx/Makefile        Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/vmx/Makefile        Tue Feb 19 08:11:22 2008 -0700
@@ -21,3 +21,4 @@ obj-y += vacpi.o
 obj-y += vacpi.o
 obj-y += vmx_vcpu_save.o
 obj-y += save.o
+obj-y += sioemu.o
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/vmx/mmio.c
--- a/xen/arch/ia64/vmx/mmio.c  Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/vmx/mmio.c  Tue Feb 19 08:11:22 2008 -0700
@@ -39,6 +39,8 @@
 #include <asm/hvm/vacpi.h>
 #include <asm/hvm/support.h>
 #include <public/hvm/save.h>
+#include <public/arch-ia64/sioemu.h>
+#include <asm/sioemu.h>
 
 #define HVM_BUFFERED_IO_RANGE_NR 1
 
@@ -388,6 +390,8 @@ static void mmio_access(VCPU *vcpu, u64 
     return;
 }
 
+enum inst_type_en { SL_INTEGER, SL_FLOATING, SL_FLOATING_FP8 };
+
 /*
    dir 1: read 0:write
  */
@@ -396,11 +400,12 @@ void emulate_io_inst(VCPU *vcpu, u64 pad
     REGS *regs;
     IA64_BUNDLE bundle;
     int slot, dir=0;
-    enum { SL_INTEGER, SL_FLOATING, SL_FLOATING_FP8 } inst_type;
+    enum inst_type_en inst_type;
     size_t size;
     u64 data, data1, temp, update_reg;
     s32 imm;
     INST64 inst;
+    unsigned long update_word;
 
     regs = vcpu_regs(vcpu);
     if (IA64_RETRY == __vmx_get_domain_bundle(regs->cr_iip, &bundle)) {
@@ -523,24 +528,53 @@ void emulate_io_inst(VCPU *vcpu, u64 pad
              inst.inst, regs->cr_iip);
     }
 
+    update_word = size | (dir << 7) | (ma << 8) | (inst_type << 12);
+    if (dir == IOREQ_READ) {
+        if (inst_type == SL_INTEGER)
+            update_word |= (inst.M1.r1 << 16);
+        else if (inst_type == SL_FLOATING_FP8)
+            update_word |= (inst.M12.f1 << 16) | (inst.M12.f2 << 24);
+    }
+
+    if (vcpu->domain->arch.is_sioemu) {
+        unsigned long iot = __gpfn_is_io(vcpu->domain, padr >> PAGE_SHIFT);
+
+        if (iot != GPFN_PIB && iot != GPFN_IOSAPIC) {
+            sioemu_io_emulate(padr, data, data1, update_word);
+            return;
+        }
+    }
+
     if (size == 4) {
         mmio_access(vcpu, padr + 8, &data1, 1 << 3, ma, dir);
         size = 3;
     }
     mmio_access(vcpu, padr, &data, 1 << size, ma, dir);
 
+    emulate_io_update(vcpu, update_word, data, data1);
+}
+
+void
+emulate_io_update(VCPU *vcpu, u64 word, u64 data, u64 data1)
+{
+    int dir = (word >> 7) & 1;
+
     if (dir == IOREQ_READ) {
+        int r1 = (word >> 16) & 0xff;
+        int r2 = (word >> 24) & 0xff;
+        enum inst_type_en inst_type = (word >> 12) & 0x0f;
+
         if (inst_type == SL_INTEGER) {
-            vcpu_set_gr(vcpu, inst.M1.r1, data, 0);
+            vcpu_set_gr(vcpu, r1, data, 0);
         } else if (inst_type == SL_FLOATING_FP8) {
             struct ia64_fpreg v;
 
             v.u.bits[0] = data;
             v.u.bits[1] = 0x1003E;
-            vcpu_set_fpreg(vcpu, inst.M12.f1, &v);
+            vcpu_set_fpreg(vcpu, r1, &v);
             v.u.bits[0] = data1;
             v.u.bits[1] = 0x1003E;
-            vcpu_set_fpreg(vcpu, inst.M12.f2, &v);
+            vcpu_set_fpreg(vcpu, r2, &v);
         } else {
             panic_domain(NULL, "Don't support ldfd now !");
         }
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/vmx/sioemu.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/vmx/sioemu.c        Tue Feb 19 08:11:22 2008 -0700
@@ -0,0 +1,219 @@
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
+/*
+ * sioemu.c: Self IO emulation - hypercall and return.
+ * Copyright (c) 2008, Tristan Gingold <tgingold@xxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <asm/vcpu.h>
+#include <asm/vmx_vcpu.h>
+#include <asm/sioemu.h>
+#include <public/arch-ia64/sioemu.h>
+#include <asm/dom_fw.h>
+#include <asm/debugger.h>
+
+static REGS *
+sioemu_deliver (void)
+{
+    VCPU *vcpu = current;
+    REGS *regs = vcpu_regs(vcpu);
+    unsigned long psr = vmx_vcpu_get_psr(vcpu);
+
+    if (vcpu->vcpu_info->evtchn_upcall_mask)
+        panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n");
+
+    /* All cleared, but keep BN.  */
+    vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN));
+
+    /* Save registers. */
+    vcpu->arch.arch_vmx.stub_saved[0] = regs->r16;
+    vcpu->arch.arch_vmx.stub_saved[1] = regs->r17;
+    vcpu->arch.arch_vmx.stub_saved[2] = regs->r18;
+    vcpu->arch.arch_vmx.stub_saved[3] = regs->r19;
+    vcpu->arch.arch_vmx.stub_saved[4] = regs->r20;
+    vcpu->arch.arch_vmx.stub_saved[5] = regs->r21;
+    vcpu->arch.arch_vmx.stub_saved[6] = regs->r22;
+    vcpu->arch.arch_vmx.stub_saved[7] = regs->r23;
+    vcpu->arch.arch_vmx.stub_saved[8] = regs->r24;
+    vcpu->arch.arch_vmx.stub_saved[9] = regs->r25;
+    vcpu->arch.arch_vmx.stub_saved[10] = regs->r26;
+    vcpu->arch.arch_vmx.stub_saved[11] = regs->r27;
+    vcpu->arch.arch_vmx.stub_saved[12] = regs->r28;
+    vcpu->arch.arch_vmx.stub_saved[13] = regs->r29;
+    vcpu->arch.arch_vmx.stub_saved[14] = regs->r30;
+    vcpu->arch.arch_vmx.stub_saved[15] = regs->r31;
+    vcpu->arch.arch_vmx.stub_nats =
+        (regs->eml_unat >> IA64_PT_REGS_R16_SLOT) & 0xffff;
+
+    /* Context. */
+    regs->r28 = regs->cr_iip;
+    regs->r29 = psr;
+    regs->r30 = regs->cr_ifs;
+
+    regs->cr_ifs = 0;  // pre-cover
+
+    regs->cr_iip = vcpu->arch.event_callback_ip;
+    regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
+
+    /* Parameters.  */
+    regs->r16 = 0;
+    regs->r17 = vcpu->arch.arch_vmx.stub_buffer;
+
+    /* Mask events.  */
+    vcpu->vcpu_info->evtchn_upcall_mask = 1;
+
+    debugger_event(XEN_IA64_DEBUG_ON_EVENT);
+
+    return regs;
+}
+
+void
+sioemu_callback_return (void)
+{
+    VCPU *vcpu = current;
+    REGS *regs = vcpu_regs(vcpu);
+    u64 cmd = regs->r16;
+    u64 arg1 = regs->r19;
+    u64 arg2 = regs->r20;
+    u64 arg3 = regs->r21;
+
+    if ((cmd & ~0x1UL) != 0)
+        panic_domain (NULL,
+                      "sioemu_callback_return: bad operation (%lx)\n", cmd);
+
+    /* First restore registers.  */
+    regs->cr_iip = regs->r28;
+    regs->cr_ifs = regs->r30;
+    vmx_vcpu_set_psr (vcpu, regs->r29);
+
+    regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
+    regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT;
+
+    regs->r16 = vcpu->arch.arch_vmx.stub_saved[0];
+    regs->r17 = vcpu->arch.arch_vmx.stub_saved[1];
+    regs->r18 = vcpu->arch.arch_vmx.stub_saved[2];
+    regs->r19 = vcpu->arch.arch_vmx.stub_saved[3];
+    regs->r20 = vcpu->arch.arch_vmx.stub_saved[4];
+    regs->r21 = vcpu->arch.arch_vmx.stub_saved[5];
+    regs->r22 = vcpu->arch.arch_vmx.stub_saved[6];
+    regs->r23 = vcpu->arch.arch_vmx.stub_saved[7];
+    regs->r24 = vcpu->arch.arch_vmx.stub_saved[8];
+    regs->r25 = vcpu->arch.arch_vmx.stub_saved[9];
+    regs->r26 = vcpu->arch.arch_vmx.stub_saved[10];
+    regs->r27 = vcpu->arch.arch_vmx.stub_saved[11];
+    regs->r28 = vcpu->arch.arch_vmx.stub_saved[12];
+    regs->r29 = vcpu->arch.arch_vmx.stub_saved[13];
+    regs->r30 = vcpu->arch.arch_vmx.stub_saved[14];
+    regs->r31 = vcpu->arch.arch_vmx.stub_saved[15];
+
+    /* Unmask events.  */
+    vcpu->vcpu_info->evtchn_upcall_mask = 0;
+
+    /* Then apply commands.  */
+    if (cmd & 1) {
+        emulate_io_update (vcpu, arg1, arg2, arg3);
+    }
+}
+
+void
+sioemu_deliver_event (void)
+{
+    REGS *regs;
+
+    regs = sioemu_deliver ();
+
+    regs->r16 = 0;
+}
+
+void
+sioemu_io_emulate (unsigned long padr, unsigned long data,
+                  unsigned long data1, unsigned long word)
+{
+    REGS *regs;
+
+    regs = sioemu_deliver ();
+    regs->r16 = 1;
+    regs->r19 = padr;
+    regs->r20 = data;
+    regs->r21 = data1;
+    regs->r22 = word;
+}
+
+static int
+sioemu_add_io_physmap (struct domain *d, unsigned long start,
+                      unsigned long size, unsigned long type)
+{
+    unsigned long i;
+    int res;
+
+    /* Check type.  */
+    if (type == 0 || (type & GPFN_IO_MASK) != type)
+        return -EINVAL;
+    if ((start & (PAGE_SIZE -1)) || (size & (PAGE_SIZE - 1)))
+        return -EINVAL;
+
+    /* Check area is currently unassigned.  */
+    for (i = start; i < start + size; i += PAGE_SIZE) {
+        unsigned long mpa = ____lookup_domain_mpa(d, i);
+        if (mpa != GPFN_INV_MASK && mpa != INVALID_MFN)
+            return -EBUSY;
+    }
+
+    /* Set.  */
+    for (i = start; i < start + size; i += PAGE_SIZE) {
+        res = __assign_domain_page(d, i, type, ASSIGN_writable);
+        if (res != 0)
+            return res;
+    }
+
+    return 0;
+}
+
+void
+sioemu_hypercall (struct pt_regs *regs)
+{
+    //printk ("sioemu_hypercall: r2=%lx r8=%lx r9=%lx\n",
+    //        regs->r2, regs->r8, regs->r9);
+
+    if (current->vcpu_info->evtchn_upcall_mask == 0)
+        panic_domain (NULL, "sioemu_hypercall: not in stub mode\n");
+
+    switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW)
+    {
+    case SIOEMU_HYPERCALL_SET_CALLBACK:
+        current->arch.event_callback_ip = regs->r8;
+        current->arch.arch_vmx.stub_buffer = regs->r9;
+        break;
+    case SIOEMU_HYPERCALL_START_FW:
+        regs->cr_iip = regs->r8;
+        vmx_vcpu_set_psr (current, regs->r9);
+        current->vcpu_info->evtchn_upcall_mask = 0;
+        break;
+    case SIOEMU_HYPERCALL_ADD_IO_PHYSMAP:
+        regs->r8 = sioemu_add_io_physmap (current->domain,
+                                          regs->r8, regs->r9, regs->r10);
+        break;
+    case SIOEMU_HYPERCALL_GET_TIME:
+    {
+        uint64_t sec, nsec;
+        get_wallclock (&sec, &nsec);
+        regs->r8 = (sec << 30) + nsec;
+        break;
+    }
+    default:
+        panic_domain (NULL, "bad sioemu hypercall %lx\n", regs->r2);
+        break;
+    }
+}
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/vmx/vmx_fault.c
--- a/xen/arch/ia64/vmx/vmx_fault.c     Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/vmx/vmx_fault.c     Tue Feb 19 08:11:22 2008 -0700
@@ -42,7 +42,6 @@
 #include <asm/privop.h>
 #include <asm/ia64_int.h>
 #include <asm/debugger.h>
-//#include <asm/hpsim_ssc.h>
 #include <asm/dom_fw.h>
 #include <asm/vmx_vcpu.h>
 #include <asm/kregs.h>
@@ -53,6 +52,9 @@
 #include <xen/mm.h>
 #include <asm/vmx_pal.h>
 #include <asm/shadow.h>
+#include <asm/sioemu.h>
+#include <public/arch-ia64/sioemu.h>
+
 /* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */
 #define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
 
@@ -178,34 +180,44 @@ vmx_ia64_handle_break (unsigned long ifa
             show_registers(regs);
         debugger_trap_fatal(0 /* don't care */, regs);
         regs_increment_iip(regs);
-    } else
+        return IA64_NO_FAULT;
+    }
 #endif
-    {
-        if (!vmx_user_mode(regs)) {
-            show_registers(regs);
-            gdprintk(XENLOG_DEBUG, "%s:%d imm %lx\n", __func__, __LINE__, iim);
-            ia64_fault(11 /* break fault */, isr, ifa, iim,
-                       0 /* cr.itir */, 0, 0, 0, (unsigned long)regs);
-        }
-
-        if (ia64_psr(regs)->cpl == 0) {
-            /* Allow hypercalls only when cpl = 0.  */
-
-            /* normal hypercalls are handled by vmx_break_fault */
-            BUG_ON(iim == d->arch.breakimm);
-
-            if (iim == DOMN_PAL_REQUEST) {
-                pal_emul(v);
-                vcpu_increment_iip(v);
-                return IA64_NO_FAULT;
-            } else if (iim == DOMN_SAL_REQUEST) {
-                sal_emul(v);
-                vcpu_increment_iip(v);
-                return IA64_NO_FAULT;
-            }
-        }
-        vmx_reflect_interruption(ifa, isr, iim, 11, regs);
-    }
+    if (!vmx_user_mode(regs)) {
+        show_registers(regs);
+        gdprintk(XENLOG_DEBUG, "%s:%d imm %lx\n", __func__, __LINE__, iim);
+        ia64_fault(11 /* break fault */, isr, ifa, iim,
+                   0 /* cr.itir */, 0, 0, 0, (unsigned long)regs);
+    }
+
+    if (ia64_psr(regs)->cpl == 0) {
+        /* Allow hypercalls only when cpl = 0.  */
+
+        /* Only common hypercalls are handled by vmx_break_fault. */
+        if (iim == d->arch.breakimm) {
+            ia64_hypercall(regs);
+            vcpu_increment_iip(v);
+            return IA64_NO_FAULT;
+        }
+
+        /* normal hypercalls are handled by vmx_break_fault */
+        BUG_ON(iim == d->arch.breakimm);
+        
+        if (iim == DOMN_PAL_REQUEST) {
+            pal_emul(v);
+            vcpu_increment_iip(v);
+            return IA64_NO_FAULT;
+        } else if (iim == DOMN_SAL_REQUEST) {
+            sal_emul(v);
+            vcpu_increment_iip(v);
+            return IA64_NO_FAULT;
+        } else if (d->arch.is_sioemu
+                   && iim == SIOEMU_HYPERPRIVOP_CALLBACK_RETURN) {
+            sioemu_callback_return ();
+            return IA64_NO_FAULT;
+        }
+    }
+    vmx_reflect_interruption(ifa, isr, iim, 11, regs);
     return IA64_NO_FAULT;
 }
 
@@ -214,10 +226,11 @@ void save_banked_regs_to_vpd(VCPU *v, RE
 {
     unsigned long i=0UL, * src,* dst, *sunat, *dunat;
     IA64_PSR vpsr;
-    src=&regs->r16;
-    sunat=&regs->eml_unat;
+
+    src = &regs->r16;
+    sunat = &regs->eml_unat;
     vpsr.val = VCPU(v, vpsr);
-    if(vpsr.bn){
+    if (vpsr.bn) {
         dst = &VCPU(v, vgr[0]);
         dunat =&VCPU(v, vnat);
         __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;; \
@@ -225,7 +238,7 @@ void save_banked_regs_to_vpd(VCPU *v, RE
                             st8 [%3] = %2;;"
        
::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
 
-    }else{
+    } else {
         dst = &VCPU(v, vbgr[0]);
 //        dunat =&VCPU(v, vbnat);
 //        __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;;
@@ -234,7 +247,7 @@ void save_banked_regs_to_vpd(VCPU *v, RE
 //       
::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
 
     }
-    for(i=0; i<16; i++)
+    for (i = 0; i < 16; i++)
         *dst++ = *src++;
 }
 
@@ -247,58 +260,61 @@ void leave_hypervisor_tail(void)
     struct domain *d = current->domain;
     struct vcpu *v = current;
 
+    /* FIXME: can this happen ?  */
+    if (is_idle_domain(current->domain))
+        return;
+
+    // A softirq may generate an interrupt.  So call softirq early.
+    local_irq_enable();
+    do_softirq();
+    local_irq_disable();
+
     // FIXME: Will this work properly if doing an RFI???
-    if (!is_idle_domain(d) ) { // always comes from guest
-//        struct pt_regs *user_regs = vcpu_regs(current);
-        local_irq_enable();
-        do_softirq();
-        local_irq_disable();
-
-        if (v->vcpu_id == 0) {
-            unsigned long callback_irq =
-                d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
-
-            if ( v->arch.arch_vmx.pal_init_pending ) {
-                /*inject INIT interruption to guest pal*/
-                v->arch.arch_vmx.pal_init_pending = 0;
-                deliver_pal_init(v);
-                return;
-            }
-
-            /*
-             * val[63:56] == 1: val[55:0] is a delivery PCI INTx line:
-             *                  Domain = val[47:32], Bus  = val[31:16],
-             *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
-             * val[63:56] == 0: val[55:0] is a delivery as GSI
-             */
-            if (callback_irq != 0 && local_events_need_delivery()) {
-                /* change level for para-device callback irq */
-                /* use level irq to send discrete event */
-                if ((uint8_t)(callback_irq >> 56) == 1) {
-                    /* case of using PCI INTx line as callback irq */
-                    int pdev = (callback_irq >> 11) & 0x1f;
-                    int pintx = callback_irq & 3;
-                    viosapic_set_pci_irq(d, pdev, pintx, 1);
-                    viosapic_set_pci_irq(d, pdev, pintx, 0);
-                } else {
-                    /* case of using GSI as callback irq */
-                    viosapic_set_irq(d, callback_irq, 1);
-                    viosapic_set_irq(d, callback_irq, 0);
-                }
-            }
-        }
-
-        rmb();
-        if (xchg(&v->arch.irq_new_pending, 0)) {
-            v->arch.irq_new_condition = 0;
-            vmx_check_pending_irq(v);
-            return;
-        }
-
-        if (v->arch.irq_new_condition) {
-            v->arch.irq_new_condition = 0;
-            vhpi_detection(v);
-        }
+    if (d->arch.is_sioemu) {
+        if (local_events_need_delivery()) {
+            sioemu_deliver_event();
+        }
+    } else if (v->vcpu_id == 0) {
+        unsigned long callback_irq =
+            d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
+        
+        if (v->arch.arch_vmx.pal_init_pending) {
+            /* inject INIT interruption to guest pal */
+            v->arch.arch_vmx.pal_init_pending = 0;
+            deliver_pal_init(v);
+            return;
+        }
+
+        /*
+         * val[63:56] == 1: val[55:0] is a delivery PCI INTx line:
+         *                  Domain = val[47:32], Bus  = val[31:16],
+         *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
+         * val[63:56] == 0: val[55:0] is a delivery as GSI
+         */
+        if (callback_irq != 0 && local_events_need_delivery()) {
+            /* change level for para-device callback irq */
+            /* use level irq to send discrete event */
+            if ((uint8_t)(callback_irq >> 56) == 1) {
+                /* case of using PCI INTx line as callback irq */
+                int pdev = (callback_irq >> 11) & 0x1f;
+                int pintx = callback_irq & 3;
+                viosapic_set_pci_irq(d, pdev, pintx, 1);
+                viosapic_set_pci_irq(d, pdev, pintx, 0);
+            } else {
+                /* case of using GSI as callback irq */
+                viosapic_set_irq(d, callback_irq, 1);
+                viosapic_set_irq(d, callback_irq, 0);
+            }
+        }
+    }
+
+    rmb();
+    if (xchg(&v->arch.irq_new_pending, 0)) {
+        v->arch.irq_new_condition = 0;
+        vmx_check_pending_irq(v);
+    } else if (v->arch.irq_new_condition) {
+        v->arch.irq_new_condition = 0;
+        vhpi_detection(v);
     }
 }
 
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/vmx/vmx_hypercall.c
--- a/xen/arch/ia64/vmx/vmx_hypercall.c Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/vmx/vmx_hypercall.c Tue Feb 19 08:11:22 2008 -0700
@@ -50,12 +50,15 @@ static int hvmop_set_isa_irq_level(
     if ( op.isa_irq > 15 )
         return -EINVAL;
 
+    if ( op.domid == DOMID_SELF )
+        op.domid = current->domain->domain_id;
+
     d = rcu_lock_domain_by_id(op.domid);
     if ( d == NULL )
         return -ESRCH;
 
     rc = -EPERM;
-    if ( !IS_PRIV_FOR(current->domain, d) )
+    if ( !IS_PRIV_FOR(current->domain, d) && d != current->domain )
         goto out;
 
     rc = -EINVAL;
@@ -83,12 +86,15 @@ static int hvmop_set_pci_intx_level(
     if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) )
         return -EINVAL;
 
+    if ( op.domid == DOMID_SELF )
+        op.domid = current->domain->domain_id;
+
     d = rcu_lock_domain_by_id(op.domid);
     if ( d == NULL )
         return -ESRCH;
 
     rc = -EPERM;
-    if ( !IS_PRIV_FOR(current->domain, d) )
+    if ( !IS_PRIV_FOR(current->domain, d) && d != current->domain )
         goto out;
 
     rc = -EINVAL;
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/vmx/vmx_init.c
--- a/xen/arch/ia64/vmx/vmx_init.c      Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/vmx/vmx_init.c      Tue Feb 19 08:11:22 2008 -0700
@@ -494,9 +494,11 @@ vmx_final_setup_guest(struct vcpu *v)
        if (rc)
                return rc;
 
-       rc = vmx_create_event_channels(v);
-       if (rc)
-               return rc;
+       if (!v->domain->arch.is_sioemu) {
+               rc = vmx_create_event_channels(v);
+               if (rc)
+                       return rc;
+       }
 
        /* v->arch.schedule_tail = arch_vmx_do_launch; */
        vmx_create_vp(v);
@@ -523,6 +525,9 @@ vmx_relinquish_guest_resources(struct do
 vmx_relinquish_guest_resources(struct domain *d)
 {
        struct vcpu *v;
+
+       if (d->arch.is_sioemu)
+               return;
 
        for_each_vcpu(d, v)
                vmx_release_assist_channel(v);
@@ -579,12 +584,13 @@ int vmx_setup_platform(struct domain *d)
 {
        ASSERT(d != dom0); /* only for non-privileged vti domain */
 
-       vmx_build_io_physmap_table(d);
-
-       vmx_init_ioreq_page(d, &d->arch.vmx_platform.ioreq);
-       vmx_init_ioreq_page(d, &d->arch.vmx_platform.buf_ioreq);
-       vmx_init_ioreq_page(d, &d->arch.vmx_platform.buf_pioreq);
-
+       if (!d->arch.is_sioemu) {
+               vmx_build_io_physmap_table(d);
+
+               vmx_init_ioreq_page(d, &d->arch.vmx_platform.ioreq);
+               vmx_init_ioreq_page(d, &d->arch.vmx_platform.buf_ioreq);
+               vmx_init_ioreq_page(d, &d->arch.vmx_platform.buf_pioreq);
+       }
        /* TEMP */
        d->arch.vmx_platform.pib_base = 0xfee00000UL;
 
@@ -599,7 +605,14 @@ int vmx_setup_platform(struct domain *d)
        /* Initialize iosapic model within hypervisor */
        viosapic_init(d);
 
-       vacpi_init(d);
+       if (!d->arch.is_sioemu)
+               vacpi_init(d);
+
+       if (d->arch.is_sioemu) {
+               int i;
+               for (i = 1; i < MAX_VIRT_CPUS; i++)
+                       d->shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
+       }
 
        return 0;
 }
@@ -609,6 +622,9 @@ void vmx_do_resume(struct vcpu *v)
        ioreq_t *p;
 
        vmx_load_state(v);
+
+       if (v->domain->arch.is_sioemu)
+               return;
 
        /* stolen from hvm_do_resume() in arch/x86/hvm/hvm.c */
        /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/xen/dom0_ops.c
--- a/xen/arch/ia64/xen/dom0_ops.c      Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/xen/dom0_ops.c      Tue Feb 19 08:11:22 2008 -0700
@@ -114,12 +114,16 @@ long arch_do_domctl(xen_domctl_t *op, XE
                 ret = -EFAULT;
         }
         else {
-            if (is_hvm_domain(d) || (ds->flags & XEN_DOMAINSETUP_hvm_guest)) {
+            if (is_hvm_domain(d)
+                || (ds->flags & (XEN_DOMAINSETUP_hvm_guest
+                                 | XEN_DOMAINSETUP_sioemu_guest))) {
                 if (!vmx_enabled) {
                     printk("No VMX hardware feature for vmx domain.\n");
                     ret = -EINVAL;
                 } else {
                     d->is_hvm = 1;
+                    if (ds->flags & XEN_DOMAINSETUP_sioemu_guest)
+                        d->arch.is_sioemu = 1;
                     xen_ia64_set_convmem_end(d, ds->maxmem);
                     ret = vmx_setup_platform(d);
                 }
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c     Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/xen/hypercall.c     Tue Feb 19 08:11:22 2008 -0700
@@ -33,6 +33,8 @@
 #include <xen/event.h>
 #include <xen/perfc.h>
 #include <public/arch-ia64/debug_op.h>
+#include <asm/sioemu.h>
+#include <public/arch-ia64/sioemu.h>
 
 static IA64FAULT
 xen_hypercall (struct pt_regs *regs)
@@ -222,7 +224,8 @@ ia64_hypercall(struct pt_regs *regs)
                regs->r10 = fpswa_ret.err1;
                regs->r11 = fpswa_ret.err2;
                break;
-       case __HYPERVISOR_opt_feature: {
+       case __HYPERVISOR_opt_feature:
+       {
                XEN_GUEST_HANDLE(void) arg;
                struct xen_ia64_opt_feature optf;
                set_xen_guest_handle(arg, (void*)(vcpu_get_gr(v, 32)));
@@ -232,6 +235,9 @@ ia64_hypercall(struct pt_regs *regs)
                        regs->r8 = -EFAULT;
                break;
        }
+       case FW_HYPERCALL_SIOEMU:
+               sioemu_hypercall(regs);
+               break;
        default:
                printk("unknown ia64 fw hypercall %lx\n", regs->r2);
                regs->r8 = do_ni_hypercall();
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c      Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/xen/xensetup.c      Tue Feb 19 08:11:22 2008 -0700
@@ -693,6 +693,9 @@ void arch_get_xen_caps(xen_capabilities_
     {
         snprintf(s, sizeof(s), "hvm-%d.%d-ia64 ", major, minor);
         safe_strcat(*info, s);
-    }
-}
-
+
+        snprintf(s, sizeof(s), "hvm-%d.%d-ia64-sioemu ", major, minor);
+        safe_strcat(*info, s);
+    }
+}
+
diff -r c750c7177d63 -r 430a036ab261 xen/arch/ia64/xen/xentime.c
--- a/xen/arch/ia64/xen/xentime.c       Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/arch/ia64/xen/xentime.c       Tue Feb 19 08:11:22 2008 -0700
@@ -252,3 +252,10 @@ struct tm wallclock_time(void)
     do_div(seconds, NSEC_PER_SEC);
     return gmtime(seconds);
 }
+
+void get_wallclock(uint64_t *sec, uint64_t *nsec)
+{
+    uint64_t nano = NOW() + wc_nsec;
+    *sec = wc_sec + nano / NSEC_PER_SEC;
+    *nsec = nano % NSEC_PER_SEC;
+}
diff -r c750c7177d63 -r 430a036ab261 xen/include/asm-ia64/dom_fw.h
--- a/xen/include/asm-ia64/dom_fw.h     Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/include/asm-ia64/dom_fw.h     Tue Feb 19 08:11:22 2008 -0700
@@ -168,6 +168,9 @@
 /* Set the shared_info base virtual address.  */
 #define FW_HYPERCALL_SET_SHARED_INFO_VA                        0x600UL
 
+/* Hvmstub hypercalls.  See details in hvm_stub.h  */
+#define FW_HYPERCALL_SIOEMU                            0x800UL
+
 /* Hypercalls index bellow _FIRST_ARCH are reserved by Xen, while those above
    are for the architecture.
    Note: this limit was defined by Xen/ia64 (and not by Xen).
diff -r c750c7177d63 -r 430a036ab261 xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h     Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/include/asm-ia64/domain.h     Tue Feb 19 08:11:22 2008 -0700
@@ -133,12 +133,13 @@ struct arch_domain {
     /* Flags.  */
     union {
         unsigned long flags;
+        struct {
+            unsigned int is_sioemu : 1;
 #ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
-        struct {
             unsigned int has_pervcpu_vhpt : 1;
             unsigned int vhpt_size_log2 : 6;
+#endif
         };
-#endif
     };
 
     /* maximum metaphysical address of conventional memory */
diff -r c750c7177d63 -r 430a036ab261 xen/include/asm-ia64/sioemu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-ia64/sioemu.h     Tue Feb 19 08:11:22 2008 -0700
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * sioemu.h
+ * 
+ * Copyright (c) 2008 Tristan Gingold <tgingold@xxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __ASM_SIOEMU_H_
+#define __ASM_SIOEMU_H_
+extern void sioemu_hypercall (struct pt_regs *regs);
+extern void sioemu_deliver_event (void);
+extern void sioemu_callback_return (void);
+extern void sioemu_io_emulate (unsigned long padr, unsigned long data,
+                              unsigned long data1, unsigned long word);
+
+#endif /* __ASM_SIOEMU_H_ */
diff -r c750c7177d63 -r 430a036ab261 xen/include/asm-ia64/time.h
--- a/xen/include/asm-ia64/time.h       Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/include/asm-ia64/time.h       Tue Feb 19 08:11:22 2008 -0700
@@ -7,4 +7,6 @@ struct tm;
 struct tm;
 struct tm wallclock_time(void);
 
+void get_wallclock(uint64_t *sec, uint64_t *nsec);
+
 #endif /* _ASM_TIME_H_ */
diff -r c750c7177d63 -r 430a036ab261 xen/include/asm-ia64/vmmu.h
--- a/xen/include/asm-ia64/vmmu.h       Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/include/asm-ia64/vmmu.h       Tue Feb 19 08:11:22 2008 -0700
@@ -197,6 +197,7 @@ extern thash_data_t * vhpt_lookup(u64 va
 extern thash_data_t * vhpt_lookup(u64 va);
 extern unsigned long fetch_code(struct vcpu *vcpu, u64 gip, IA64_BUNDLE 
*pbundle);
 extern void emulate_io_inst(struct vcpu *vcpu, u64 padr, u64 ma);
+extern void emulate_io_update(struct vcpu *vcpu, u64 word, u64 d, u64 d1);
 extern int vhpt_enabled(struct vcpu *vcpu, uint64_t vadr, vhpt_ref_t ref);
 extern void thash_vhpt_insert(struct vcpu *v, u64 pte, u64 itir, u64 ifa,
                               int type);
diff -r c750c7177d63 -r 430a036ab261 xen/include/asm-ia64/vmx_vpd.h
--- a/xen/include/asm-ia64/vmx_vpd.h    Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/include/asm-ia64/vmx_vpd.h    Tue Feb 19 08:11:22 2008 -0700
@@ -74,6 +74,9 @@ struct arch_vmx_struct {
     unsigned long  ivt_current;
     struct ivt_debug ivt_debug[IVT_DEBUG_MAX];
 #endif
+    unsigned long stub_saved[16];
+    unsigned long stub_buffer;
+    unsigned int  stub_nats;
 };
 
 #define VMX_DOMAIN(v)   v->arch.arch_vmx.flags
diff -r c750c7177d63 -r 430a036ab261 xen/include/public/arch-ia64/sioemu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/public/arch-ia64/sioemu.h     Tue Feb 19 08:11:22 2008 -0700
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * sioemu.h
+ *
+ * Copyright (c) 2008 Tristan Gingold <tgingold@xxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __XEN_PUBLIC_IA64_SIOEMU_H__
+#define __XEN_PUBLIC_IA64_SIOEMU_H__
+
+/* Defines the callback entry point.  r8=ip, r9=data.
+   Must be called per-vcpu.  */
+#define SIOEMU_HYPERCALL_SET_CALLBACK 0x01
+
+/* Finish sioemu fw initialization and start firmware.  r8=ip.  */
+#define SIOEMU_HYPERCALL_START_FW 0x02
+
+/* Add IO pages in physmap.  */
+#define SIOEMU_HYPERCALL_ADD_IO_PHYSMAP 0x03
+
+/* Get wallclock time.  */
+#define SIOEMU_HYPERCALL_GET_TIME 0x04
+
+/* Return from callback.  r16=0.
+   Unmask vcpu events.  */
+#define SIOEMU_HYPERPRIVOP_CALLBACK_RETURN 0x01
+
+#endif /* __XEN_PUBLIC_IA64_SIOEMU_H__ */
diff -r c750c7177d63 -r 430a036ab261 xen/include/public/domctl.h
--- a/xen/include/public/domctl.h       Tue Feb 19 07:51:25 2008 -0700
+++ b/xen/include/public/domctl.h       Tue Feb 19 08:11:22 2008 -0700
@@ -376,6 +376,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_hyper
 #define XEN_DOMAINSETUP_hvm_guest  (1UL<<_XEN_DOMAINSETUP_hvm_guest)
 #define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save)  */
 #define XEN_DOMAINSETUP_query  (1UL<<_XEN_DOMAINSETUP_query)
+#define _XEN_DOMAINSETUP_sioemu_guest 2
+#define XEN_DOMAINSETUP_sioemu_guest  (1UL<<_XEN_DOMAINSETUP_sioemu_guest)
 typedef struct xen_domctl_arch_setup {
     uint64_aligned_t flags;  /* XEN_DOMAINSETUP_* */
 #ifdef __ia64__

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