diff -r 092232fa1fbd xen/arch/ia64/vmx/Makefile
--- a/xen/arch/ia64/vmx/Makefile Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/vmx/Makefile Thu Nov 22 04:47:43 2007 +0100
@@ -21,3 +21,4 @@ obj-y += vacpi.o
obj-y += vacpi.o
obj-y += vmx_vcpu_save.o
obj-y += save.o
+obj-y += hvm_stub.o
diff -r 092232fa1fbd xen/arch/ia64/vmx/hvm_stub.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/vmx/hvm_stub.c Thu Nov 22 03:37:39 2007 +0100
@@ -0,0 +1,160 @@
+#include <asm/vcpu.h>
+#include <asm/vmx_vcpu.h>
+#include <asm/hvm_stub.h>
+#include <asm/dom_fw.h>
+#include <asm/debugger.h>
+
+static REGS *
+hvmstub_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, "hvmstub_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
+hvmstub_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, "hvmstub_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
+hvmstub_deliver_event (void)
+{
+ REGS *regs;
+
+ regs = hvmstub_deliver ();
+
+ regs->r16 = 0;
+}
+
+void
+hvmstub_io_emulate (unsigned long padr,
+ unsigned long data, unsigned long data1,
+ unsigned long word)
+{
+ REGS *regs;
+
+ regs = hvmstub_deliver ();
+ regs->r16 = 1;
+ regs->r19 = padr;
+ regs->r20 = data;
+ regs->r21 = data1;
+ regs->r22 = word;
+}
+
+void
+hvmstub_hypercall (struct pt_regs *regs)
+{
+ printk ("hvmstub_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, "hvmstub_hypercall: not in stub mode\n");
+
+
+ switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW)
+ {
+ case HVMSTUB_HYPERCALL_SET_CALLBACK:
+ current->arch.event_callback_ip = regs->r8;
+ current->arch.arch_vmx.stub_buffer = regs->r9;
+ break;
+ case HVMSTUB_HYPERCALL_START_FW:
+ regs->cr_iip = regs->r8;
+ vmx_vcpu_set_psr (current, regs->r9);
+ current->vcpu_info->evtchn_upcall_mask = 0;
+ break;
+ default:
+ panic_domain (NULL, "bad hvmstub hypercall\n");
+ break;
+ }
+}
diff -r 092232fa1fbd xen/arch/ia64/vmx/mmio.c
--- a/xen/arch/ia64/vmx/mmio.c Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/vmx/mmio.c Thu Nov 22 03:48:26 2007 +0100
@@ -39,6 +39,7 @@
#include <asm/hvm/vacpi.h>
#include <asm/hvm/support.h>
#include <public/hvm/save.h>
+#include <asm/hvm_stub.h>
#define HVM_BUFFERED_IO_RANGE_NR 1
@@ -423,6 +424,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
*/
@@ -431,11 +434,13 @@ 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)) {
@@ -558,24 +563,54 @@ 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_hvmstub) {
+ unsigned long iot;
+ iot = __gpfn_is_io(vcpu->domain, padr >> PAGE_SHIFT);
+
+ if (iot != GPFN_PIB && iot != GPFN_IOSAPIC) {
+ hvmstub_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 092232fa1fbd xen/arch/ia64/vmx/vmx_fault.c
--- a/xen/arch/ia64/vmx/vmx_fault.c Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/vmx/vmx_fault.c Thu Nov 22 03:37:39 2007 +0100
@@ -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>
@@ -52,6 +51,8 @@
#include <asm/vmx_phy_mode.h>
#include <xen/mm.h>
#include <asm/vmx_pal.h>
+#include <asm/hvm_stub.h>
+
/* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */
#define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
@@ -182,31 +183,36 @@ vmx_ia64_handle_break (unsigned long ifa
if (iim == 0)
show_registers(regs);
debugger_trap_fatal(0 /* don't care */, regs);
- } else
+ }
#endif
- {
- if (iim == 0)
- vmx_die_if_kernel("Break 0 in Hypervisor.", regs, iim);
-
- if (ia64_psr(regs)->cpl == 0) {
- /* Allow hypercalls only when cpl = 0. */
- if (iim == d->arch.breakimm) {
- ia64_hypercall(regs);
- vcpu_increment_iip(v);
+ if (iim == 0)
+ vmx_die_if_kernel("Break 0 in Hypervisor.", regs, iim);
+
+ if (ia64_psr(regs)->cpl == 0) {
+ /* Allow hypercalls only when cpl = 0. */
+ if (iim == d->arch.breakimm) {
+ ia64_hypercall(regs);
+ vcpu_increment_iip(v);
+ return IA64_NO_FAULT;
+ }
+ if (iim == DOMN_PAL_REQUEST) {
+ pal_emul(v);
+ vcpu_increment_iip(v);
+ return IA64_NO_FAULT;
+ }
+ if (iim == DOMN_SAL_REQUEST) {
+ sal_emul(v);
+ vcpu_increment_iip(v);
+ return IA64_NO_FAULT;
+ }
+ if (d->arch.is_hvmstub) {
+ if (iim == HVMSTUB_HYPERPRIVOP_CALLBACK_RETURN) {
+ hvmstub_callback_return ();
return IA64_NO_FAULT;
}
- else 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);
- }
+ }
+ }
+ vmx_reflect_interruption(ifa, isr, iim, 11, regs);
return IA64_NO_FAULT;
}
@@ -215,10 +221,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;; \
@@ -226,7 +233,8 @@ 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;;
@@ -235,7 +243,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++;
}
@@ -248,59 +256,62 @@ 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;
+
+ if (d->arch.is_hvmstub) {
+ if (local_events_need_delivery()) {
+ hvmstub_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);
+ }
+
// 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);
- }
- }
+ local_irq_enable();
+ do_softirq();
+ local_irq_disable();
}
static int vmx_handle_lds(REGS* regs)
diff -r 092232fa1fbd xen/arch/ia64/vmx/vmx_hypercall.c
--- a/xen/arch/ia64/vmx/vmx_hypercall.c Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/vmx/vmx_hypercall.c Thu Nov 22 03:37:39 2007 +0100
@@ -47,15 +47,19 @@ static int hvmop_set_isa_irq_level(
if ( copy_from_guest(&op, uop, 1) )
return -EFAULT;
- if ( !IS_PRIV(current->domain) )
- return -EPERM;
-
if ( op.isa_irq > 15 )
return -EINVAL;
- d = get_domain_by_id(op.domid);
- if ( d == NULL )
- return -ESRCH;
+ if ( op.domid == DOMID_SELF ) {
+ d = get_current_domain();
+ }
+ else {
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+ d = get_domain_by_id(op.domid);
+ if ( d == NULL )
+ return -ESRCH;
+ }
rc = -EINVAL;
if ( !is_hvm_domain(d) )
@@ -79,15 +83,19 @@ static int hvmop_set_pci_intx_level(
if ( copy_from_guest(&op, uop, 1) )
return -EFAULT;
- if ( !IS_PRIV(current->domain) )
- return -EPERM;
-
if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) )
return -EINVAL;
- d = get_domain_by_id(op.domid);
- if ( d == NULL )
- return -ESRCH;
+ if ( op.domid == DOMID_SELF ) {
+ d = get_current_domain();
+ }
+ else {
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+ d = get_domain_by_id(op.domid);
+ if ( d == NULL )
+ return -ESRCH;
+ }
rc = -EINVAL;
if ( !is_hvm_domain(d) )
diff -r 092232fa1fbd xen/arch/ia64/vmx/vmx_init.c
--- a/xen/arch/ia64/vmx/vmx_init.c Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/vmx/vmx_init.c Thu Nov 22 04:35:11 2007 +0100
@@ -404,9 +404,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_hvmstub) {
+ rc = vmx_create_event_channels(v);
+ if (rc)
+ return rc;
+ }
/* v->arch.schedule_tail = arch_vmx_do_launch; */
vmx_create_vp(v);
@@ -434,14 +436,16 @@ vmx_relinquish_guest_resources(struct do
{
struct vcpu *v;
- for_each_vcpu(d, v)
- vmx_release_assist_channel(v);
-
- vacpi_relinquish_resources(d);
-
- vmx_destroy_ioreq_page(d, &d->arch.vmx_platform.ioreq);
- vmx_destroy_ioreq_page(d, &d->arch.vmx_platform.buf_ioreq);
- vmx_destroy_ioreq_page(d, &d->arch.vmx_platform.buf_pioreq);
+ if (!d->arch.is_hvmstub) {
+ for_each_vcpu(d, v)
+ vmx_release_assist_channel(v);
+
+ vacpi_relinquish_resources(d);
+
+ vmx_destroy_ioreq_page(d, &d->arch.vmx_platform.ioreq);
+ vmx_destroy_ioreq_page(d, &d->arch.vmx_platform.buf_ioreq);
+ vmx_destroy_ioreq_page(d, &d->arch.vmx_platform.buf_pioreq);
+ }
}
void
@@ -491,10 +495,11 @@ int vmx_setup_platform(struct domain *d)
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_hvmstub) {
+ 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;
@@ -509,7 +514,14 @@ int vmx_setup_platform(struct domain *d)
/* Initialize iosapic model within hypervisor */
viosapic_init(d);
- vacpi_init(d);
+ if (!d->arch.is_hvmstub)
+ vacpi_init(d);
+
+ if (d->arch.is_hvmstub) {
+ int i;
+ for ( i = 1; i < MAX_VIRT_CPUS; i++ )
+ d->shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
+ }
return 0;
}
@@ -521,25 +533,27 @@ void vmx_do_resume(struct vcpu *v)
vmx_load_all_rr(v);
migrate_timer(&v->arch.arch_vmx.vtm.vtm_timer, v->processor);
- /* stolen from hvm_do_resume() in arch/x86/hvm/hvm.c */
- /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
- p = &get_vio(v)->vp_ioreq;
- while (p->state != STATE_IOREQ_NONE) {
- switch (p->state) {
- case STATE_IORESP_READY: /* IORESP_READY -> NONE */
- vmx_io_assist(v);
- break;
- case STATE_IOREQ_READY:
- case STATE_IOREQ_INPROCESS:
- /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
- wait_on_xen_event_channel(v->arch.arch_vmx.xen_port,
- (p->state != STATE_IOREQ_READY) &&
- (p->state != STATE_IOREQ_INPROCESS));
- break;
- default:
- gdprintk(XENLOG_ERR,
- "Weird HVM iorequest state %d.\n", p->state);
- domain_crash_synchronous();
- }
- }
-}
+ if (!v->domain->arch.is_hvmstub) {
+ /* stolen from hvm_do_resume() in arch/x86/hvm/hvm.c */
+ /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
+ p = &get_vio(v)->vp_ioreq;
+ while (p->state != STATE_IOREQ_NONE) {
+ switch (p->state) {
+ case STATE_IORESP_READY: /* IORESP_READY -> NONE */
+ vmx_io_assist(v);
+ break;
+ case STATE_IOREQ_READY:
+ case STATE_IOREQ_INPROCESS:
+ /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
+ wait_on_xen_event_channel(v->arch.arch_vmx.xen_port,
+ (p->state != STATE_IOREQ_READY) &&
+ (p->state != STATE_IOREQ_INPROCESS));
+ break;
+ default:
+ gdprintk(XENLOG_ERR,
+ "Weird HVM iorequest state %d.\n", p->state);
+ domain_crash_synchronous();
+ }
+ }
+ }
+}
diff -r 092232fa1fbd xen/arch/ia64/vmx/vmx_ivt.S
--- a/xen/arch/ia64/vmx/vmx_ivt.S Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/vmx/vmx_ivt.S Thu Nov 22 03:37:39 2007 +0100
@@ -472,7 +472,7 @@ ENTRY(vmx_break_fault)
;;
ld4 r22=[r22]
extr.u r24=r29,IA64_PSR_CPL0_BIT,2
- cmp.eq p0,p6=r0,r0
+ cmp.ltu p6,p0=NR_hypercalls,r2
;;
cmp.ne.or p6,p0=r22,r17
cmp.ne.or p6,p0=r0,r24
diff -r 092232fa1fbd xen/arch/ia64/vmx/vmx_phy_mode.c
--- a/xen/arch/ia64/vmx/vmx_phy_mode.c Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/vmx/vmx_phy_mode.c Thu Nov 22 03:37:39 2007 +0100
@@ -35,6 +35,7 @@
#define SW_BAD 0 /* Bad mode transitition */
#define SW_V2P_DT 1 /* Physical emulation is activated */
#define SW_V2P_D 2 /* Physical emulation is activated (only for data) */
+#define SW_P2P_D 2 /* Physical emulation is activated (only for data) */
#define SW_P2V 3 /* Exit physical mode emulation */
#define SW_SELF 4 /* No mode transition */
#define SW_NOP 5 /* Mode transition, but without action required */
@@ -60,7 +61,7 @@ static const unsigned char mm_switch_tab
* data access can be satisfied though itlb entry for physical
* emulation is hit.
*/
- {SW_SELF,0, 0, SW_NOP, 0, 0, 0, SW_P2V},
+ {SW_SELF,0, 0, SW_NOP, 0, SW_P2P_D, 0, SW_P2V},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
/*
@@ -79,7 +80,7 @@ static const unsigned char mm_switch_tab
* from the low level TLB miss handlers.
* (see "arch/ia64/kernel/ivt.S")
*/
- {0, 0, 0, 0, 0, SW_SELF,0, SW_P2V},
+ {SW_V2P_DT, 0, 0, 0, 0, SW_SELF,0, SW_P2V},
{0, 0, 0, 0, 0, 0, 0, 0},
/*
* (it,dt,rt): (1,1,1) -> (1,0,1)
diff -r 092232fa1fbd xen/arch/ia64/xen/dom0_ops.c
--- a/xen/arch/ia64/xen/dom0_ops.c Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/xen/dom0_ops.c Thu Nov 22 03:37:39 2007 +0100
@@ -104,13 +104,17 @@ long arch_do_domctl(xen_domctl_t *op, XE
ret = -EFAULT;
}
else {
- if (ds->flags & XEN_DOMAINSETUP_hvm_guest) {
+ if (ds->flags & (XEN_DOMAINSETUP_hvm_guest
+ | XEN_DOMAINSETUP_hvmstub_guest)) {
if (!vmx_enabled) {
printk("No VMX hardware feature for vmx domain.\n");
ret = -EINVAL;
} else {
d->arch.is_vti = 1;
+ d->is_hvm = 1;
xen_ia64_set_convmem_end(d, ds->maxmem);
+ if (ds->flags & XEN_DOMAINSETUP_hvmstub_guest)
+ d->arch.is_hvmstub = 1;
ret = vmx_setup_platform(d);
}
}
diff -r 092232fa1fbd xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/arch/ia64/xen/hypercall.c Thu Nov 22 03:37:39 2007 +0100
@@ -32,6 +32,7 @@
#include <public/callback.h>
#include <xen/event.h>
#include <xen/perfc.h>
+#include <asm/hvm_stub.h>
extern long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg);
extern long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg);
@@ -224,7 +225,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)));
@@ -234,6 +236,9 @@ ia64_hypercall(struct pt_regs *regs)
regs->r8 = -EFAULT;
break;
}
+ case FW_HYPERCALL_HVMSTUB:
+ hvmstub_hypercall (regs);
+ break;
default:
printk("unknown ia64 fw hypercall %lx\n", regs->r2);
regs->r8 = do_ni_hypercall();
diff -r 092232fa1fbd xen/include/asm-ia64/dom_fw.h
--- a/xen/include/asm-ia64/dom_fw.h Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/include/asm-ia64/dom_fw.h Thu Nov 22 03:37:39 2007 +0100
@@ -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_HVMSTUB 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 092232fa1fbd xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/include/asm-ia64/domain.h Thu Nov 22 03:37:39 2007 +0100
@@ -126,6 +126,7 @@ struct arch_domain {
unsigned long flags;
struct {
unsigned int is_vti : 1;
+ unsigned int is_hvmstub : 1;
#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
unsigned int has_pervcpu_vhpt : 1;
unsigned int vhpt_size_log2 : 6;
diff -r 092232fa1fbd xen/include/asm-ia64/hvm_stub.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-ia64/hvm_stub.h Thu Nov 22 03:37:39 2007 +0100
@@ -0,0 +1,23 @@
+/* Hvm stub hypercalls. */
+
+/* Defines the callback entry point. r8=ip, r9=data.
+ Must be called per-vcpu. */
+#define HVMSTUB_HYPERCALL_SET_CALLBACK 0x01
+
+/* Finish stub initialization and start firmware. r8=ip. */
+#define HVMSTUB_HYPERCALL_START_FW 0x02
+
+/* Return from callback. r16=0.
+ Unmask vcpu events. */
+#define HVMSTUB_HYPERPRIVOP_CALLBACK_RETURN 0x01
+
+
+#ifdef __XEN__
+extern void hvmstub_hypercall (struct pt_regs *regs);
+extern void hvmstub_deliver_event (void);
+extern void hvmstub_callback_return (void);
+extern void hvmstub_io_emulate (unsigned long padr, unsigned long data,
+ unsigned long data1, unsigned long word);
+
+#endif
+
diff -r 092232fa1fbd xen/include/asm-ia64/vmmu.h
--- a/xen/include/asm-ia64/vmmu.h Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/include/asm-ia64/vmmu.h Thu Nov 22 03:37:39 2007 +0100
@@ -215,6 +215,7 @@ extern void machine_tlb_purge(u64 va, u6
extern void machine_tlb_purge(u64 va, u64 ps);
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 u64 translate_phy_pte(struct vcpu *v, u64 *pte, u64 itir, u64 va);
extern void thash_vhpt_insert(struct vcpu *v, u64 pte, u64 itir, u64 ifa,
diff -r 092232fa1fbd xen/include/asm-ia64/vmx_vpd.h
--- a/xen/include/asm-ia64/vmx_vpd.h Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/include/asm-ia64/vmx_vpd.h Thu Nov 22 03:37:39 2007 +0100
@@ -64,6 +64,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 092232fa1fbd xen/include/public/domctl.h
--- a/xen/include/public/domctl.h Thu Nov 22 03:34:09 2007 +0100
+++ b/xen/include/public/domctl.h Thu Nov 22 03:37:39 2007 +0100
@@ -373,6 +373,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_hvmstub_guest 2
+#define XEN_DOMAINSETUP_hvmstub_guest (1UL<<_XEN_DOMAINSETUP_hvmstub_guest)
typedef struct xen_domctl_arch_setup {
uint64_aligned_t flags; /* XEN_DOMAINSETUP_* */
#ifdef __ia64__
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|