# 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=®s->r16;
- sunat=®s->eml_unat;
+
+ src = ®s->r16;
+ sunat = ®s->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
|