aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@hp.com>2007-10-21 14:39:07 -0600
committerAlex Williamson <alex.williamson@hp.com>2007-10-21 14:39:07 -0600
commit4ef8c22a173dda6e462f69e13d28f4c593d1ee72 (patch)
tree1857846730ab836dda596bfff7283fd5c7f505c8
parent0f93dc4f9817d08c84f88b17092d5ff66e10cacb (diff)
downloadxen-4ef8c22a173dda6e462f69e13d28f4c593d1ee72.tar.gz
xen-4ef8c22a173dda6e462f69e13d28f4c593d1ee72.tar.bz2
xen-4ef8c22a173dda6e462f69e13d28f4c593d1ee72.zip
[IA64] vti domain save/restore: implement hvm_save/load. work in progress.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
-rw-r--r--xen/arch/ia64/Rules.mk1
-rw-r--r--xen/arch/ia64/vmx/Makefile1
-rw-r--r--xen/arch/ia64/vmx/save.c71
-rw-r--r--xen/arch/ia64/vmx/vacpi.c69
-rw-r--r--xen/arch/ia64/vmx/viosapic.c69
-rw-r--r--xen/arch/ia64/vmx/vlsapic.c125
-rw-r--r--xen/arch/ia64/vmx/vmx_vcpu_save.c162
-rw-r--r--xen/common/Makefile1
-rw-r--r--xen/include/asm-ia64/hvm/support.h28
-rw-r--r--xen/include/asm-ia64/hvm/vacpi.h12
-rw-r--r--xen/include/asm-ia64/viosapic.h25
-rw-r--r--xen/include/public/arch-ia64/hvm/save.h195
-rw-r--r--xen/include/public/hvm/save.h2
13 files changed, 727 insertions, 34 deletions
diff --git a/xen/arch/ia64/Rules.mk b/xen/arch/ia64/Rules.mk
index 6e8eabad51..7f9ade7930 100644
--- a/xen/arch/ia64/Rules.mk
+++ b/xen/arch/ia64/Rules.mk
@@ -1,6 +1,7 @@
########################################
# ia64-specific definitions
+ia64 := y
HAS_ACPI := y
HAS_VGA := y
xenoprof := y
diff --git a/xen/arch/ia64/vmx/Makefile b/xen/arch/ia64/vmx/Makefile
index d4e0898785..8f693a6a11 100644
--- a/xen/arch/ia64/vmx/Makefile
+++ b/xen/arch/ia64/vmx/Makefile
@@ -20,3 +20,4 @@ obj-y += vtlb.o
obj-y += optvfault.o
obj-y += vacpi.o
obj-y += vmx_vcpu_save.o
+obj-y += save.o
diff --git a/xen/arch/ia64/vmx/save.c b/xen/arch/ia64/vmx/save.c
new file mode 100644
index 0000000000..3d4eddd44f
--- /dev/null
+++ b/xen/arch/ia64/vmx/save.c
@@ -0,0 +1,71 @@
+/*
+ * hvm/save.c: Save and restore HVM guest's emulated hardware state.
+ *
+ * Copyright (c) 2007, Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ * IA64 support
+ *
+ * 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
+ */
+
+#include <xen/types.h>
+#include <xen/hvm/save.h>
+
+void
+arch_hvm_save(struct hvm_save_header *hdr)
+{
+ unsigned int i;
+
+ for (i = 0; i < 5; ++i)
+ hdr->cpuid[i] = ia64_get_cpuid(i);
+}
+
+int
+arch_hvm_load(struct hvm_save_header *hdr)
+{
+ unsigned int i;
+ if (hdr->magic != HVM_FILE_MAGIC) {
+ gdprintk(XENLOG_ERR,
+ "HVM restore: bad magic number %#"PRIx64"\n", hdr->magic);
+ return -1;
+ }
+
+ if (hdr->version != HVM_FILE_VERSION) {
+ gdprintk(XENLOG_ERR,
+ "HVM restore: unsupported version %"PRIx64"\n", hdr->version);
+ return -1;
+ }
+
+ for (i = 0; i < 5; ++i) {
+ unsigned long cpuid = ia64_get_cpuid(i);
+ /* TODO: need to define how big a difference is acceptable */
+ if (hdr->cpuid[i] != cpuid)
+ gdprintk(XENLOG_WARNING,
+ "HVM restore: saved CPUID[%d] (%#lx) "
+ "does not match host (%#lx).\n", i, hdr->cpuid[i], cpuid);
+ }
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/ia64/vmx/vacpi.c b/xen/arch/ia64/vmx/vacpi.c
index 650cd1bd9a..49d3ca380f 100644
--- a/xen/arch/ia64/vmx/vacpi.c
+++ b/xen/arch/ia64/vmx/vacpi.c
@@ -7,6 +7,7 @@
* Copyright (c) 2007 VA Linux Systems Japan K.K
* Isaku Yamahata <yamahata at valinux co jp>
* SMP support
+ * save/restore support
*
* Copyright (c) 2007, XenSource inc.
* Copyright (c) 2006, Intel Corporation.
@@ -28,6 +29,8 @@
#include <asm/vmx_vcpu.h>
#include <asm/vmx.h>
#include <asm/hvm/vacpi.h>
+#include <asm/hvm/support.h>
+#include <public/hvm/save.h>
/* The interesting bits of the PM1a_STS register */
#define TMR_STS (1 << 0)
@@ -197,3 +200,69 @@ void vacpi_relinquish_resources(struct domain *d)
struct vacpi *s = &d->arch.hvm_domain.vacpi;
kill_timer(&s->timer);
}
+
+// stolen from xen/arch/x86/hvm/pmtimer.c
+static int vacpi_save(struct domain *d, hvm_domain_context_t *h)
+{
+ struct vacpi *s = &d->arch.hvm_domain.vacpi;
+ unsigned long delta;
+ uint32_t msb = s->regs.tmr_val & TMR_VAL_MSB;
+ struct hvm_hw_ia64_vacpi vacpi_save;
+ int rc;
+
+ stop_timer(&s->timer); //XXX
+
+ spin_lock(&s->lock);
+
+ /* Update the counter to the guest's current time. We always save
+ * with the domain paused, so the saved time should be after the
+ * last_gtime, but just in case, make sure we only go forwards */
+
+ //XXX NOW() should be the time that domais paused
+ delta = NOW() - s->last_gtime;
+ delta = ((delta >> 8) * ((FREQUENCE_PMTIMER << 32) / SECONDS(1))) >> 24;
+ if ( delta < 1UL<<31 )
+ s->regs.tmr_val += delta;
+ if ( (s->regs.tmr_val & TMR_VAL_MSB) != msb )
+ s->regs.pm1a_sts |= TMR_STS;
+ /* No point in setting the SCI here because we'll already have saved the
+ * IRQ and *PIC state; we'll fix it up when we restore the domain */
+
+ vacpi_save.regs = s->regs;
+ rc = hvm_save_entry(VACPI, 0, h, &vacpi_save);
+
+ spin_unlock(&s->lock);
+
+ pmt_timer_callback(d);//XXX This might change the domain state.
+ return 0;
+}
+
+static int vacpi_load(struct domain *d, hvm_domain_context_t *h)
+{
+ struct vacpi *s = &d->arch.hvm_domain.vacpi;
+ struct hvm_hw_ia64_vacpi vacpi_load;
+
+ /* Reload the registers */
+ if ( hvm_load_entry(VACPI, h, &vacpi_load) )
+ return -EINVAL;
+
+ stop_timer(&s->timer);//XXX
+
+ spin_lock(&s->lock);
+
+ s->regs = vacpi_load.regs;
+
+ /* Calculate future counter values from now. */
+ //XXX NOW(); last_gtime should be set when domain is unpaused
+ s->last_gtime = NOW();
+
+ /* Set the SCI state from the registers */
+ pmt_update_sci(d, s);
+
+ spin_unlock(&s->lock);
+
+ pmt_timer_callback(d);//XXX
+ return 0;
+}
+
+HVM_REGISTER_SAVE_RESTORE(VACPI, vacpi_save, vacpi_load, 1, HVMSR_PER_DOM);
diff --git a/xen/arch/ia64/vmx/viosapic.c b/xen/arch/ia64/vmx/viosapic.c
index fe166005d0..b67c045d3e 100644
--- a/xen/arch/ia64/vmx/viosapic.c
+++ b/xen/arch/ia64/vmx/viosapic.c
@@ -27,6 +27,7 @@
* Copyright (C) 2007 VA Linux Systems Japan K.K.
* Isaku Yamahata <yamahata at valinux co jp>
* SMP support
+ * xen save/restore support
*/
#include <xen/config.h>
@@ -40,6 +41,8 @@
#include <asm/viosapic.h>
#include <asm/current.h>
#include <asm/event.h>
+#include <asm/hvm/support.h>
+#include <public/hvm/save.h>
static void viosapic_deliver(struct viosapic *viosapic, int irq)
{
@@ -356,3 +359,69 @@ void viosapic_init(struct domain *d)
viosapic->base_address = VIOSAPIC_DEFAULT_BASE_ADDRESS;
}
+
+#define VIOSAPIC_INVALID_VCPU_ID (-1UL)
+static int viosapic_save(struct domain *d, hvm_domain_context_t *h)
+{
+ struct viosapic *viosapic = domain_viosapic(d);
+ struct hvm_hw_ia64_viosapic viosapic_save;
+ int i;
+
+ memset(&viosapic_save, 0, sizeof(viosapic_save));
+
+ spin_lock(&viosapic->lock);
+ viosapic_save.irr = viosapic->irr;
+ viosapic_save.isr = viosapic->isr;
+ viosapic_save.ioregsel = viosapic->ioregsel;
+ if (viosapic->lowest_vcpu != NULL)
+ viosapic_save.lowest_vcpu_id = viosapic->lowest_vcpu->vcpu_id;
+ else
+ viosapic_save.lowest_vcpu_id = VIOSAPIC_INVALID_VCPU_ID;
+ viosapic_save.base_address = viosapic->base_address;
+
+ for (i = 0; i < VIOSAPIC_NUM_PINS; i++)
+ viosapic_save.redirtbl[i] = viosapic->redirtbl[i];
+ spin_unlock(&viosapic->lock);
+
+ return hvm_save_entry(VIOSAPIC, 0, h, &viosapic_save);
+}
+
+static int viosapic_load(struct domain *d, hvm_domain_context_t *h)
+{
+ struct viosapic *viosapic = domain_viosapic(d);
+ struct hvm_hw_ia64_viosapic viosapic_load;
+ struct vcpu *lowest_vcpu;
+ int i;
+
+ if (hvm_load_entry(VIOSAPIC, h, &viosapic_load))
+ return -EINVAL;
+
+ lowest_vcpu = NULL;
+ if (viosapic_load.lowest_vcpu_id < MAX_VIRT_CPUS)
+ lowest_vcpu = d->vcpu[viosapic_load.lowest_vcpu_id];
+ else if (viosapic_load.lowest_vcpu_id != VIOSAPIC_INVALID_VCPU_ID)
+ return -EINVAL;
+
+ if (viosapic_load.base_address != VIOSAPIC_DEFAULT_BASE_ADDRESS)
+ return -EINVAL;
+
+ spin_lock(&viosapic->lock);
+ viosapic->irr = viosapic_load.irr;
+ viosapic->isr = viosapic_load.isr;
+ viosapic->ioregsel = viosapic_load.ioregsel;
+
+ viosapic->lowest_vcpu = lowest_vcpu;
+
+ viosapic->base_address = viosapic_load.base_address;
+
+ for (i = 0; i < VIOSAPIC_NUM_PINS; i++)
+ viosapic->redirtbl[i] = viosapic_load.redirtbl[i];
+
+ service_iosapic(viosapic);//XXX
+ spin_unlock(&viosapic->lock);
+
+ return 0;
+}
+
+HVM_REGISTER_SAVE_RESTORE(VIOSAPIC, viosapic_save, viosapic_load,
+ 1, HVMSR_PER_DOM);
diff --git a/xen/arch/ia64/vmx/vlsapic.c b/xen/arch/ia64/vmx/vlsapic.c
index 2457743277..2dbae71950 100644
--- a/xen/arch/ia64/vmx/vlsapic.c
+++ b/xen/arch/ia64/vmx/vlsapic.c
@@ -4,6 +4,10 @@
* vlsapic.c: virtual lsapic model including ITC timer.
* Copyright (c) 2005, Intel Corporation.
*
+ * Copyright (c) 2007, Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ * save/restore support
+ *
* 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.
@@ -40,6 +44,8 @@
#include <asm/vlsapic.h>
#include <asm/linux/jiffies.h>
#include <xen/domain.h>
+#include <asm/hvm/support.h>
+#include <public/hvm/save.h>
#ifdef IPI_DEBUG
#define IPI_DPRINTK(x...) printk(x)
@@ -820,3 +826,122 @@ void vlsapic_write(struct vcpu *v,
}
}
+static int vlsapic_save(struct domain *d, hvm_domain_context_t *h)
+{
+ struct vcpu *v;
+
+ for_each_vcpu(d, v) {
+ struct hvm_hw_ia64_vlsapic vlsapic;
+ int i;
+
+ if (test_bit(_VPF_down, &v->pause_flags))
+ continue;
+
+ memset(&vlsapic, 0, sizeof(vlsapic));
+ for (i = 0; i < 4; i++)
+ vlsapic.insvc[i] = VLSAPIC_INSVC(v,i);
+
+ vlsapic.vhpi = VCPU(v, vhpi);
+ vlsapic.xtp = VLSAPIC_XTP(v);
+ vlsapic.pal_init_pending = v->arch.arch_vmx.pal_init_pending;
+
+ if (hvm_save_entry(VLSAPIC, v->vcpu_id, h, &vlsapic))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vlsapic_load(struct domain *d, hvm_domain_context_t *h)
+{
+ uint16_t vcpuid;
+ struct vcpu *v;
+ struct hvm_hw_ia64_vlsapic vlsapic;
+ int i;
+
+ vcpuid = hvm_load_instance(h);
+ if (vcpuid > MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL) {
+ gdprintk(XENLOG_ERR,
+ "%s: domain has no vlsapic %u\n", __func__, vcpuid);
+ return -EINVAL;
+ }
+
+ if (hvm_load_entry(VLSAPIC, h, &vlsapic) != 0)
+ return -EINVAL;
+
+ for (i = 0; i < 4; i++)
+ VLSAPIC_INSVC(v,i) = vlsapic.insvc[i];
+
+ VCPU(v, vhpi) = vlsapic.vhpi;
+ VLSAPIC_XTP(v) = vlsapic.xtp;
+ v->arch.arch_vmx.pal_init_pending = vlsapic.pal_init_pending;
+ v->arch.irq_new_pending = 1; /* to force checking irq */
+
+ return 0;
+}
+
+HVM_REGISTER_SAVE_RESTORE(VLSAPIC, vlsapic_save, vlsapic_load,
+ 1, HVMSR_PER_VCPU);
+
+static int vtime_save(struct domain *d, hvm_domain_context_t *h)
+{
+ struct vcpu *v;
+
+ for_each_vcpu(d, v) {
+ vtime_t *vtm = &VMX(v, vtm);
+ struct hvm_hw_ia64_vtime vtime;
+
+ if (test_bit(_VPF_down, &v->pause_flags))
+ continue;
+
+ stop_timer(&vtm->vtm_timer);//XXX should wait for callback not running.
+
+ memset(&vtime, 0, sizeof(vtime));
+ vtime.itc = now_itc(vtm);
+ vtime.itm = VCPU(v, itm);
+ vtime.last_itc = vtm->last_itc;
+ vtime.pending = vtm->pending;
+
+ vtm_set_itm(v, vtime.itm);// this may start timer.
+
+ if (hvm_save_entry(VTIME, v->vcpu_id, h, &vtime))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vtime_load(struct domain *d, hvm_domain_context_t *h)
+{
+ uint16_t vcpuid;
+ struct vcpu *v;
+ struct hvm_hw_ia64_vtime vtime;
+ vtime_t *vtm;
+
+ vcpuid = hvm_load_instance(h);
+ if (vcpuid > MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL) {
+ gdprintk(XENLOG_ERR,
+ "%s: domain has no vtime %u\n", __func__, vcpuid);
+ return -EINVAL;
+ }
+
+ if (hvm_load_entry(VTIME, h, &vtime) != 0)
+ return -EINVAL;
+
+ vtm = &VMX(v, vtm);
+ stop_timer(&vtm->vtm_timer); //XXX should wait for callback not running.
+
+ vtm->last_itc = vtime.last_itc;
+ vtm->pending = vtime.pending;
+
+ migrate_timer(&vtm->vtm_timer, v->processor);
+ vtm_set_itm(v, vtime.itm);
+ vtm_set_itc(v, vtime.itc); // This may start timer.
+
+ if (test_and_clear_bit(_VPF_down, &v->pause_flags))
+ vcpu_wake(v);
+
+ return 0;
+}
+
+HVM_REGISTER_SAVE_RESTORE(VTIME, vtime_save, vtime_load, 1, HVMSR_PER_VCPU);
diff --git a/xen/arch/ia64/vmx/vmx_vcpu_save.c b/xen/arch/ia64/vmx/vmx_vcpu_save.c
index ba2ac21779..f435bddd1f 100644
--- a/xen/arch/ia64/vmx/vmx_vcpu_save.c
+++ b/xen/arch/ia64/vmx/vmx_vcpu_save.c
@@ -22,6 +22,8 @@
#include <asm/vmx_vcpu.h>
#include <asm/vmx_vcpu_save.h>
+#include <asm/hvm/support.h>
+#include <public/hvm/save.h>
void
vmx_arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
@@ -192,6 +194,166 @@ vmx_arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
return 0;
}
+
+static int vmx_cpu_save(struct domain *d, hvm_domain_context_t *h)
+{
+ struct vcpu *v;
+
+ for_each_vcpu(d, v) {
+ struct pt_regs *regs = vcpu_regs(v);
+ struct hvm_hw_ia64_cpu ia64_cpu;
+
+ if (test_bit(_VPF_down, &v->pause_flags))
+ continue;
+
+ memset(&ia64_cpu, 0, sizeof(ia64_cpu));
+
+ ia64_cpu.ipsr = regs->cr_ipsr;
+
+ if (hvm_save_entry(CPU, v->vcpu_id, h, &ia64_cpu))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vmx_cpu_load(struct domain *d, hvm_domain_context_t *h)
+{
+ int rc = 0;
+ uint16_t vcpuid;
+ struct vcpu *v;
+ struct hvm_hw_ia64_cpu ia64_cpu;
+ struct pt_regs *regs;
+
+ vcpuid = hvm_load_instance(h);
+ if (vcpuid > MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL) {
+ gdprintk(XENLOG_ERR,
+ "%s: domain has no vcpu %u\n", __func__, vcpuid);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (hvm_load_entry(CPU, h, &ia64_cpu) != 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ regs = vcpu_regs(v);
+ regs->cr_ipsr = ia64_cpu.ipsr | IA64_PSR_VM;
+
+ out:
+ return rc;
+}
+
+HVM_REGISTER_SAVE_RESTORE(CPU, vmx_cpu_save, vmx_cpu_load, 1, HVMSR_PER_VCPU);
+
+static int vmx_vpd_save(struct domain *d, hvm_domain_context_t *h)
+{
+ struct vcpu *v;
+
+ for_each_vcpu(d, v) {
+ vpd_t *vpd = (void *)v->arch.privregs;
+
+ if (test_bit(_VPF_down, &v->pause_flags))
+ continue;
+
+ // currently struct hvm_hw_ia64_vpd = struct vpd
+ // if it is changed, this must be revised.
+ if (hvm_save_entry(VPD, v->vcpu_id, h, (struct hvm_hw_ia64_vpd*)vpd))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vmx_vpd_load(struct domain *d, hvm_domain_context_t *h)
+{
+ int rc = 0;
+ uint16_t vcpuid;
+ struct vcpu *v;
+ vpd_t *vpd;
+ struct hvm_hw_ia64_vpd *ia64_vpd = NULL;
+ int i;
+
+ vcpuid = hvm_load_instance(h);
+ if (vcpuid > MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL) {
+ gdprintk(XENLOG_ERR,
+ "%s: domain has no vcpu %u\n", __func__, vcpuid);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ ia64_vpd = xmalloc(struct hvm_hw_ia64_vpd);
+ if (ia64_vpd == NULL) {
+ gdprintk(XENLOG_ERR,
+ "%s: can't allocate memory %d\n", __func__, vcpuid);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ if (hvm_load_entry(VPD, h, ia64_vpd) != 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ vpd = (void *)v->arch.privregs;
+#define VPD_COPY(x) vpd->vpd_low.x = ia64_vpd->vpd.vpd_low.x
+
+ for (i = 0; i < 16; i++)
+ VPD_COPY(vgr[i]);
+ for (i = 0; i < 16; i++)
+ VPD_COPY(vbgr[i]);
+ VPD_COPY(vnat);
+ VPD_COPY(vbnat);
+ for (i = 0; i < 5; i++)
+ VPD_COPY(vcpuid[i]);
+ VPD_COPY(vpsr);
+ VPD_COPY(vpr);
+
+ // cr
+#if 0
+ VPD_COPY(dcr);
+ VPD_COPY(itm);
+ VPD_COPY(iva);
+ VPD_COPY(pta);
+ VPD_COPY(ipsr);
+ VPD_COPY(isr);
+ VPD_COPY(iip);
+ VPD_COPY(ifa);
+ VPD_COPY(itir);
+ VPD_COPY(iipa);
+ VPD_COPY(ifs);
+ VPD_COPY(iim);
+ VPD_COPY(iha);
+ VPD_COPY(lid);
+ VPD_COPY(ivr);
+ VPD_COPY(tpr);
+ VPD_COPY(eoi);
+ VPD_COPY(irr[0]);
+ VPD_COPY(irr[1]);
+ VPD_COPY(irr[2]);
+ VPD_COPY(irr[3]);
+ VPD_COPY(itv);
+ VPD_COPY(pmv);
+ VPD_COPY(cmcv);
+ VPD_COPY(lrr0);
+ VPD_COPY(lrr1);
+#else
+ memcpy(&vpd->vpd_low.vcr[0], &ia64_vpd->vpd.vpd_low.vcr[0],
+ sizeof(vpd->vpd_low.vcr));
+#endif
+#undef VPD_COPY
+
+ v->arch.irq_new_condition = 1;
+
+ out:
+ if (ia64_vpd != NULL)
+ xfree(ia64_vpd);
+ return rc;
+}
+
+HVM_REGISTER_SAVE_RESTORE(VPD, vmx_vpd_save, vmx_vpd_load, 1, HVMSR_PER_VCPU);
+
/*
* Local variables:
* mode: C
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 2e8e111e32..1bf38310bf 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -37,6 +37,7 @@ subdir-$(CONFIG_COMPAT) += compat
subdir-$(x86_32) += hvm
subdir-$(x86_64) += hvm
+subdir-$(ia64) += hvm
subdir-y += libelf
diff --git a/xen/include/asm-ia64/hvm/support.h b/xen/include/asm-ia64/hvm/support.h
new file mode 100644
index 0000000000..19191674bd
--- /dev/null
+++ b/xen/include/asm-ia64/hvm/support.h
@@ -0,0 +1,28 @@
+/*
+ * xen/include/asm-ia64/hvm/save.h
+ *
+ * Copyright (c) 2007, Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ * IA64 support
+ *
+ * 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_IA64_HVM_SUPPORT_H__
+#define __ASM_IA64_HVM_SUPPORT_H__
+
+#include <xen/hvm/save.h>
+
+#endif /* __ASM_IA64_HVM_SUPPORT_H__ */
diff --git a/xen/include/asm-ia64/hvm/vacpi.h b/xen/include/asm-ia64/hvm/vacpi.h
index 00de009b38..44c4e81bbc 100644
--- a/xen/include/asm-ia64/hvm/vacpi.h
+++ b/xen/include/asm-ia64/hvm/vacpi.h
@@ -21,6 +21,7 @@
#ifndef __ASM_IA64_HVM_VACPI_H__
#define __ASM_IA64_HVM_VACPI_H__
+#include <public/arch-ia64/hvm/save.h> /* for struct vacpi_regs */
#include <public/hvm/ioreq.h>
#define ACPI_PM1A_EVT_BLK_ADDRESS 0x0000000000001f40
@@ -31,17 +32,6 @@
#define FREQUENCE_PMTIMER 3579545UL /* Timer should run at 3.579545 MHz */
-struct vacpi_regs {
- union {
- struct {
- uint32_t pm1a_sts:16;
- uint32_t pm1a_en:16;
- };
- uint32_t evt_blk;
- };
- uint32_t tmr_val;
-};
-
struct vacpi {
struct vacpi_regs regs;
s_time_t last_gtime;
diff --git a/xen/include/asm-ia64/viosapic.h b/xen/include/asm-ia64/viosapic.h
index fdc91d56cf..869c284e4f 100644
--- a/xen/include/asm-ia64/viosapic.h
+++ b/xen/include/asm-ia64/viosapic.h
@@ -29,6 +29,8 @@
#include <xen/config.h>
#include <xen/types.h>
#include <xen/smp.h>
+#include <public/arch-ia64/hvm/save.h> /* for VIOSAPIC_NUM_PINS and
+ union viosapic_rte */
/* Direct registers. */
#define VIOSAPIC_REG_SELECT 0x00
@@ -42,8 +44,6 @@
#define VIOSAPIC_VERSION_ID 0x21 /* IOSAPIC version */
-#define VIOSAPIC_NUM_PINS 48
-
#define VIOSAPIC_DEFAULT_BASE_ADDRESS 0xfec00000
#define VIOSAPIC_MEM_LENGTH 0x100
@@ -52,27 +52,6 @@
arch.hvm_domain.viosapic))
#define vcpu_viosapic(v) (&(v)->domain->arch.hvm_domain.viosapic)
-union viosapic_rte
-{
- uint64_t bits;
- struct {
- uint8_t vector;
-
- uint8_t delivery_mode : 3;
- uint8_t reserve1 : 1;
- uint8_t delivery_status: 1;
- uint8_t polarity : 1;
- uint8_t reserve2 : 1;
- uint8_t trig_mode : 1;
-
- uint8_t mask : 1;
- uint8_t reserve3 : 7;
-
- uint8_t reserved[3];
- uint16_t dest_id;
- };
-};
-
struct viosapic {
uint64_t irr;
uint64_t isr; /* This is used for level trigger */
diff --git a/xen/include/public/arch-ia64/hvm/save.h b/xen/include/public/arch-ia64/hvm/save.h
new file mode 100644
index 0000000000..e6d08a1904
--- /dev/null
+++ b/xen/include/public/arch-ia64/hvm/save.h
@@ -0,0 +1,195 @@
+/******************************************************************************
+ * save_types.h
+ *
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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_HVM_SAVE_IA64_H__
+#define __XEN_PUBLIC_HVM_SAVE_IA64_H__
+
+#include <public/hvm/save.h>
+#include <public/arch-ia64.h>
+
+/*
+ * Save/restore header: general info about the save file.
+ */
+
+/* x86 uses 0x54381286 */
+#define HVM_FILE_MAGIC 0x343641492f6e6558UL /* "Xen/IA64" */
+#define HVM_FILE_VERSION 0x0000000000000001UL
+
+struct hvm_save_header {
+ uint64_t magic; /* Must be HVM_FILE_MAGIC */
+ uint64_t version; /* File format version */
+ uint64_t changeset; /* Version of Xen that saved this file */
+ uint64_t cpuid[5]; /* CPUID[0x01][%eax] on the saving machine */
+};
+
+DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
+
+/*
+ * CPU
+ */
+struct hvm_hw_ia64_cpu {
+ uint64_t ipsr;
+};
+DECLARE_HVM_SAVE_TYPE(CPU, 2, struct hvm_hw_ia64_cpu);
+
+/*
+ * CPU
+ */
+struct hvm_hw_ia64_vpd {
+ struct vpd vpd;
+};
+DECLARE_HVM_SAVE_TYPE(VPD, 3, struct hvm_hw_ia64_vpd);
+
+/*
+ * device dependency
+ * vacpi => viosapic => vlsapic
+ */
+/*
+ * vlsapic
+ */
+struct hvm_hw_ia64_vlsapic {
+ uint64_t insvc[4];
+ uint64_t vhpi; // ??? should this be saved in vpd
+ uint8_t xtp;
+ uint8_t pal_init_pending;
+ uint8_t pad[2];
+};
+DECLARE_HVM_SAVE_TYPE(VLSAPIC, 4, struct hvm_hw_ia64_vlsapic);
+// unconditionaly set v->arch.irq_new_peding = 1
+// unconditionaly set v->arch.irq_new_condition = 0
+
+/*
+ * vtime
+ */
+// itc, itm, itv are saved by arch vcpu context
+struct hvm_hw_ia64_vtime {
+ uint64_t itc;
+ uint64_t itm;
+
+ uint64_t last_itc;
+ uint64_t pending;
+};
+DECLARE_HVM_SAVE_TYPE(VTIME, 5, struct hvm_hw_ia64_vtime);
+// calculate v->vtm.vtm_offset
+// ??? Or should vtm_offset be set by leave_hypervisor_tail()?
+// start vtm_timer if necessary by vtm_set_itm().
+// ??? Or should vtm_timer be set by leave_hypervisor_tail()?
+//
+// ??? or should be done by schedule_tail()
+// => schedule_tail() should do.
+
+/*
+ * viosapic
+ */
+#define VIOSAPIC_NUM_PINS 48
+
+union viosapic_rte
+{
+ uint64_t bits;
+ struct {
+ uint8_t vector;
+
+ uint8_t delivery_mode : 3;
+ uint8_t reserve1 : 1;
+ uint8_t delivery_status: 1;
+ uint8_t polarity : 1;
+ uint8_t reserve2 : 1;
+ uint8_t trig_mode : 1;
+
+ uint8_t mask : 1;
+ uint8_t reserve3 : 7;
+
+ uint8_t reserved[3];
+ uint16_t dest_id;
+ };
+};
+
+struct hvm_hw_ia64_viosapic {
+ uint64_t irr;
+ uint64_t isr;
+ uint32_t ioregsel;
+ uint32_t pad;
+ uint64_t lowest_vcpu_id;
+ uint64_t base_address;
+ union viosapic_rte redirtbl[VIOSAPIC_NUM_PINS];
+};
+DECLARE_HVM_SAVE_TYPE(VIOSAPIC, 6, struct hvm_hw_ia64_viosapic);
+
+/*
+ * vacpi
+ * PM timer
+ */
+#if 0
+struct hvm_hw_ia64_pmtimer {
+ uint32_t tmr_val; /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */
+ uint16_t pm1a_sts; /* PM1a_EVT_BLK.PM1a_STS: status register */
+ uint16_t pm1a_en; /* PM1a_EVT_BLK.PM1a_EN: enable register */
+};
+DECLARE_HVM_SAVE_TYPE(PMTIMER, 7, struct hvm_hw_ia64_pmtimer);
+#else
+struct vacpi_regs {
+ union {
+ struct {
+ uint32_t pm1a_sts:16;
+ uint32_t pm1a_en:16;
+ };
+ uint32_t evt_blk;
+ };
+ uint32_t tmr_val;
+};
+
+struct hvm_hw_ia64_vacpi {
+ struct vacpi_regs regs;
+};
+DECLARE_HVM_SAVE_TYPE(VACPI, 7, struct hvm_hw_ia64_vacpi);
+// update last_gtime and setup timer of struct vacpi
+#endif
+
+#if 0
+/*
+ * guest os type
+ * XXX Xen guest os specific optimization
+ * This isn't hvm specific so this should be addressed genericly
+ * including paravirtualized domain.
+ */
+struct hvm_hw_ia64_gos {
+ uint64_t gos_type;
+};
+DECLARE_HVM_SAVE_TYPE(GOS_TYPE, 8, struct hvm_hw_ia64_gos);
+#endif
+
+/*
+ * Largest type-code in use
+ */
+#define HVM_SAVE_CODE_MAX 7
+
+#endif /* __XEN_PUBLIC_HVM_SAVE_IA64_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h
index 0746a8439a..3ffe182a50 100644
--- a/xen/include/public/hvm/save.h
+++ b/xen/include/public/hvm/save.h
@@ -75,6 +75,8 @@ DECLARE_HVM_SAVE_TYPE(END, 0, struct hvm_save_end);
#if defined(__i386__) || defined(__x86_64__)
#include "../arch-x86/hvm/save.h"
+#elif defined(__ia64__)
+#include "../arch-ia64/hvm/save.h"
#else
#error "unsupported architecture"
#endif