# HG changeset patch
# User yamahata@xxxxxxxxxxxxx
# Date 1192100096 -32400
# Node ID a04cedb034ea936890485d6989d01b5712151748
# Parent 905a46fbe0d8f1c51e4eec565434b6e0069454ad
implement arch_get_info_guest(), arch_set_info_guest() more.
PATCHNAME: implement_arch_get_set_info_guest
Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
diff -r 905a46fbe0d8 -r a04cedb034ea xen/arch/ia64/vmx/Makefile
--- a/xen/arch/ia64/vmx/Makefile Wed Oct 10 19:45:29 2007 +0900
+++ b/xen/arch/ia64/vmx/Makefile Thu Oct 11 19:54:56 2007 +0900
@@ -19,3 +19,4 @@ obj-y += vtlb.o
obj-y += vtlb.o
obj-y += optvfault.o
obj-y += vacpi.o
+obj-y += vmx_vcpu_save.o
diff -r 905a46fbe0d8 -r a04cedb034ea xen/arch/ia64/vmx/vmx_vcpu_save.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/vmx/vmx_vcpu_save.c Thu Oct 11 19:54:56 2007 +0900
@@ -0,0 +1,203 @@
+/******************************************************************************
+ * vmx_vcpu_save.c
+ *
+ * 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
+ *
+ */
+
+#include <asm/vmx_vcpu.h>
+#include <asm/vmx_vcpu_save.h>
+
+void
+vmx_arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
+{
+ vpd_t *vpd = (void *)v->arch.privregs;
+ struct mapped_regs *vpd_low = &vpd->vpd_low;
+ unsigned long nats;
+ unsigned long bnats;
+
+ union vcpu_ar_regs *ar = &c.nat->regs.ar;
+ union vcpu_cr_regs *cr = &c.nat->regs.cr;
+ int i;
+
+ // banked registers
+ if (vpd_low->vpsr & IA64_PSR_BN) {
+ for (i = 0; i < 16; i++) {
+ //c.nat->regs.r[i + 16] = vpd_low->vgr[i];
+ c.nat->regs.bank[i] = vpd_low->vbgr[i];
+ }
+ nats = vpd_low->vnat;
+ bnats = vpd_low->vbnat;
+ } else {
+ for (i = 0; i < 16; i++) {
+ c.nat->regs.bank[i] = vpd_low->vgr[i];
+ //c.nat->regs.r[i + 16] = vpd_low->vbgr[i];
+ }
+ bnats = vpd_low->vnat;
+ nats = vpd_low->vbnat;
+ }
+ // c.nat->regs.nats[0:15] is already set. we shouldn't overwrite.
+ c.nat->regs.nats =
+ (c.nat->regs.nats & MASK(0, 16)) | (nats & MASK(16, 16));
+ c.nat->regs.bnats = bnats & MASK(16, 16);
+
+ //c.nat->regs.psr = vpd_low->vpsr;
+ //c.nat->regs.pr = vpd_low->vpr;
+
+ // ar
+ ar->kr[0] = v->arch.arch_vmx.vkr[0];
+ ar->kr[1] = v->arch.arch_vmx.vkr[1];
+ ar->kr[2] = v->arch.arch_vmx.vkr[2];
+ ar->kr[3] = v->arch.arch_vmx.vkr[3];
+ ar->kr[4] = v->arch.arch_vmx.vkr[4];
+ ar->kr[5] = v->arch.arch_vmx.vkr[5];
+ ar->kr[6] = v->arch.arch_vmx.vkr[6];
+ ar->kr[7] = v->arch.arch_vmx.vkr[7];
+#ifdef CONFIG_IA32_SUPPORT
+ // csd and ssd are done by arch_get_info_guest()
+ ar->fcr = v->arch._thread.fcr;
+ ar->eflag = v->arch._thread.eflag;
+ ar->cflg = v->arch._thread.cflg;
+ ar->fsr = v->arch._thread.fsr;
+ ar->fir = v->arch._thread.fir;
+ ar->fdr = v->arch._thread.fdr;
+#endif
+ //ar->itc = vpd_low->itc;//see vtime
+
+ // cr
+ //cr->dcr = vpd_low->dcr;
+ //cr->itm = vpd_low->itm;
+ //cr->iva = vpd_low->iva;
+ //cr->pta = vpd_low->pta;
+ //cr->ipsr = vpd_low->ipsr;
+ //cr->isr = vpd_low->isr;
+ //cr->iip = vpd_low->iip;
+ //cr->ifa = vpd_low->ifa;
+ //cr->itir = vpd_low->itir;
+ cr->iipa = vpd_low->iipa;
+ cr->ifs = vpd_low->ifs;
+ //cr->iim = vpd_low->iim;
+ //cr->iha = vpd_low->iha;
+ cr->lid = vpd_low->lid;
+ cr->ivr = vpd_low->ivr;
+ //cr->tpr = vpd_low->tpr;
+ cr->eoi = vpd_low->eoi;
+ //cr->irr[0] = vpd_low->irr[0];
+ //cr->irr[1] = vpd_low->irr[1];
+ //cr->irr[2] = vpd_low->irr[2];
+ //cr->irr[3] = vpd_low->irr[3];
+ //cr->itv = vpd_low->itv;
+ //cr->pmv = vpd_low->pmv;
+ //cr->cmcv = vpd_low->cmcv;
+ cr->lrr0 = vpd_low->lrr0;
+ cr->lrr1 = vpd_low->lrr1;
+}
+
+int
+vmx_arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
+{
+ vpd_t *vpd = (void *)v->arch.privregs;
+ struct mapped_regs *vpd_low = &vpd->vpd_low;
+ unsigned long vnat;
+ unsigned long vbnat;
+
+ union vcpu_ar_regs *ar = &c.nat->regs.ar;
+ union vcpu_cr_regs *cr = &c.nat->regs.cr;
+ int i;
+
+ // banked registers
+ if (c.nat->regs.psr & IA64_PSR_BN) {
+ for (i = 0; i < 16; i++) {
+ //vpd_low->vgr[i] = c.nat->regs.r[i + 16];
+ vpd_low->vbgr[i] = c.nat->regs.bank[i];
+ }
+ vnat = c.nat->regs.nats;
+ vbnat = c.nat->regs.bnats;
+ } else {
+ for (i = 0; i < 16; i++) {
+ vpd_low->vgr[i] = c.nat->regs.bank[i];
+ //vpd_low->vbgr[i] = c.nat->regs.r[i + 16];
+ }
+ vbnat = c.nat->regs.nats;
+ vnat = c.nat->regs.bnats;
+ }
+ vpd_low->vnat = vnat & MASK(16, 16);
+ vpd_low->vbnat = vbnat & MASK(16, 16);
+ //vpd_low->vpsr = c.nat->regs.psr;
+ //vpd_low->vpr = c.nat->regs.pr;
+
+ // ar
+ v->arch.arch_vmx.vkr[0] = ar->kr[0];
+ v->arch.arch_vmx.vkr[1] = ar->kr[1];
+ v->arch.arch_vmx.vkr[2] = ar->kr[2];
+ v->arch.arch_vmx.vkr[3] = ar->kr[3];
+ v->arch.arch_vmx.vkr[4] = ar->kr[4];
+ v->arch.arch_vmx.vkr[5] = ar->kr[5];
+ v->arch.arch_vmx.vkr[6] = ar->kr[6];
+ v->arch.arch_vmx.vkr[7] = ar->kr[7];
+#ifdef CONFIG_IA32_SUPPORT
+ v->arch._thread.fcr = ar->fcr;
+ v->arch._thread.eflag = ar->eflag;
+ v->arch._thread.cflg = ar->cflg;
+ v->arch._thread.fsr = ar->fsr;
+ v->arch._thread.fir = ar->fir;
+ v->arch._thread.fdr = ar->fdr;
+#endif
+ //vpd_low->itc = ar->itc;// see vtime.
+
+ // cr
+ vpd_low->dcr = cr->dcr;
+ vpd_low->itm = cr->itm;
+ //vpd_low->iva = cr->iva;
+ vpd_low->pta = cr->pta;
+ vpd_low->ipsr = cr->ipsr;
+ vpd_low->isr = cr->isr;
+ vpd_low->iip = cr->iip;
+ vpd_low->ifa = cr->ifa;
+ vpd_low->itir = cr->itir;
+ vpd_low->iipa = cr->iipa;
+ vpd_low->ifs = cr->ifs;
+ vpd_low->iim = cr->iim;
+ vpd_low->iha = cr->iha;
+ vpd_low->lid = cr->lid;
+ vpd_low->ivr = cr->ivr; //XXX vlsapic
+ vpd_low->tpr = cr->tpr;
+ vpd_low->eoi = cr->eoi;
+ vpd_low->irr[0] = cr->irr[0];
+ vpd_low->irr[1] = cr->irr[1];
+ vpd_low->irr[2] = cr->irr[2];
+ vpd_low->irr[3] = cr->irr[3];
+ vpd_low->itv = cr->itv;
+ vpd_low->pmv = cr->pmv;
+ vpd_low->cmcv = cr->cmcv;
+ vpd_low->lrr0 = cr->lrr0;
+ vpd_low->lrr1 = cr->lrr1;
+
+ v->arch.irq_new_condition = 1;
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 905a46fbe0d8 -r a04cedb034ea xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Wed Oct 10 19:45:29 2007 +0900
+++ b/xen/arch/ia64/xen/domain.c Thu Oct 11 19:54:56 2007 +0900
@@ -41,6 +41,7 @@
#include <asm/vmx_vcpu.h>
#include <asm/vmx_vpd.h>
#include <asm/vmx_phy_mode.h>
+#include <asm/vmx_vcpu_save.h>
#include <asm/vhpt.h>
#include <asm/vcpu.h>
#include <asm/tlbflush.h>
@@ -54,6 +55,7 @@
#include <public/vcpu.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
+#include <asm/debugger.h>
/* dom0_size: default memory allocation for dom0 (~4GB) */
static unsigned long __initdata dom0_size = 4096UL*1024UL*1024UL;
@@ -516,6 +518,12 @@ void vcpu_destroy(struct vcpu *v)
relinquish_vcpu_resources(v);
}
+static unsigned long*
+vcpu_to_rbs_bottom(struct vcpu *v)
+{
+ return (unsigned long*)((char *)v + IA64_RBS_OFFSET);
+}
+
static void init_switch_stack(struct vcpu *v)
{
struct pt_regs *regs = vcpu_regs (v);
@@ -523,7 +531,7 @@ static void init_switch_stack(struct vcp
extern void ia64_ret_from_clone;
memset(sw, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs));
- sw->ar_bspstore = (unsigned long)v + IA64_RBS_OFFSET;
+ sw->ar_bspstore = (unsigned long)vcpu_to_rbs_bottom(v);
sw->b0 = (unsigned long) &ia64_ret_from_clone;
sw->ar_fpsr = FPSR_DEFAULT;
v->arch._thread.ksp = (unsigned long) sw - 16;
@@ -628,19 +636,100 @@ int arch_vcpu_reset(struct vcpu *v)
return 0;
}
+static unsigned long num_phys_stacked;
+static int __init
+init_num_phys_stacked(void)
+{
+ switch (ia64_pal_rse_info(&num_phys_stacked, NULL)) {
+ case 0L:
+ printk("the number of physical stacked general registers"
+ "(RSE.N_STACKED_PHYS) = %ld\n", num_phys_stacked);
+ return 0;
+ case -2L:
+ case -3L:
+ default:
+ break;
+ }
+ printk("WARNING: PAL_RSE_INFO call failed. "
+ "domain save/restore may NOT work!\n");
+ return -EINVAL;
+}
+__initcall(init_num_phys_stacked);
+
#define COPY_FPREG(dst, src) memcpy(dst, src, sizeof(struct ia64_fpreg))
+
+#define AR_PFS_PEC_SHIFT 51
+#define AR_PFS_REC_SIZE 6
+#define AR_PFS_PEC_MASK (((1UL << 6) - 1) << 51)
+
+/*
+ * See init_swtich_stack() and ptrace.h
+ */
+static struct switch_stack*
+vcpu_to_switch_stack(struct vcpu* v)
+{
+ return (struct switch_stack *)(v->arch._thread.ksp + 16);
+}
+
+static int
+vcpu_has_not_run(struct vcpu* v)
+{
+ extern void ia64_ret_from_clone;
+ struct switch_stack *sw = vcpu_to_switch_stack(v);
+
+ return (sw == (struct switch_stack *)(vcpu_regs(v)) - 1) &&
+ (sw->b0 == (unsigned long)&ia64_ret_from_clone);
+}
+
+static void
+nats_update(unsigned int* nats, unsigned int reg, char nat)
+{
+ BUG_ON(reg > 31);
+
+ if (nat)
+ *nats |= (1UL << reg);
+ else
+ *nats &= ~(1UL << reg);
+}
void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
{
int i;
struct vcpu_tr_regs *tr = &c.nat->regs.tr;
struct cpu_user_regs *uregs = vcpu_regs(v);
+ struct switch_stack *sw = vcpu_to_switch_stack(v);
+ struct unw_frame_info info;
int is_hvm = VMX_DOMAIN(v);
unsigned int rbs_size;
-
+ unsigned long * const rbs_bottom = vcpu_to_rbs_bottom(v);
+ unsigned long *rbs_top;
+ unsigned long *rbs_rnat_addr;
+ unsigned int top_slot;
+ unsigned int num_regs;
+
+ memset(c.nat, 0, sizeof(*c.nat));
c.nat->regs.b[6] = uregs->b6;
c.nat->regs.b[7] = uregs->b7;
+ memset(&info, 0, sizeof(info));
+ unw_init_from_blocked_task(&info, v);
+ if (vcpu_has_not_run(v)) {
+ c.nat->regs.ar.lc = sw->ar_lc;
+ c.nat->regs.ar.ec =
+ (sw->ar_pfs & AR_PFS_PEC_MASK) >> AR_PFS_PEC_SHIFT;
+ } else if (unw_unwind_to_user(&info) < 0) {
+ /* warn: should panic? */
+ gdprintk(XENLOG_ERR, "vcpu=%d unw_unwind_to_user() failed.\n",
+ v->vcpu_id);
+ show_stack(v, NULL);
+
+ /* can't return error */
+ c.nat->regs.ar.lc = 0;
+ c.nat->regs.ar.ec = 0;
+ } else {
+ unw_get_ar(&info, UNW_AR_LC, &c.nat->regs.ar.lc);
+ unw_get_ar(&info, UNW_AR_EC, &c.nat->regs.ar.ec);
+ }
c.nat->regs.ar.csd = uregs->ar_csd;
c.nat->regs.ar.ssd = uregs->ar_ssd;
@@ -666,7 +755,11 @@ void arch_get_info_guest(struct vcpu *v,
c.nat->regs.pr = uregs->pr;
c.nat->regs.b[0] = uregs->b0;
rbs_size = uregs->loadrs >> 16;
- c.nat->regs.ar.bsp = uregs->ar_bspstore + rbs_size;
+ num_regs = ia64_rse_num_regs(rbs_bottom,
+ (unsigned long*)((char*)rbs_bottom + rbs_size));
+ c.nat->regs.ar.bsp = (unsigned long)ia64_rse_skip_regs(
+ (unsigned long*)c.nat->regs.ar.bspstore, num_regs);
+ BUG_ON(num_regs > num_phys_stacked);
c.nat->regs.r[1] = uregs->r1;
c.nat->regs.r[12] = uregs->r12;
@@ -696,6 +789,11 @@ void arch_get_info_guest(struct vcpu *v,
c.nat->regs.ar.ccv = uregs->ar_ccv;
+ COPY_FPREG(&c.nat->regs.f[2], &sw->f2);
+ COPY_FPREG(&c.nat->regs.f[3], &sw->f3);
+ COPY_FPREG(&c.nat->regs.f[4], &sw->f4);
+ COPY_FPREG(&c.nat->regs.f[5], &sw->f5);
+
COPY_FPREG(&c.nat->regs.f[6], &uregs->f6);
COPY_FPREG(&c.nat->regs.f[7], &uregs->f7);
COPY_FPREG(&c.nat->regs.f[8], &uregs->f8);
@@ -703,24 +801,155 @@ void arch_get_info_guest(struct vcpu *v,
COPY_FPREG(&c.nat->regs.f[10], &uregs->f10);
COPY_FPREG(&c.nat->regs.f[11], &uregs->f11);
- c.nat->regs.r[4] = uregs->r4;
- c.nat->regs.r[5] = uregs->r5;
- c.nat->regs.r[6] = uregs->r6;
- c.nat->regs.r[7] = uregs->r7;
-
- /* FIXME: to be reordered. */
- c.nat->regs.nats = uregs->eml_unat;
+ COPY_FPREG(&c.nat->regs.f[12], &sw->f12);
+ COPY_FPREG(&c.nat->regs.f[13], &sw->f13);
+ COPY_FPREG(&c.nat->regs.f[14], &sw->f14);
+ COPY_FPREG(&c.nat->regs.f[15], &sw->f15);
+ COPY_FPREG(&c.nat->regs.f[16], &sw->f16);
+ COPY_FPREG(&c.nat->regs.f[17], &sw->f17);
+ COPY_FPREG(&c.nat->regs.f[18], &sw->f18);
+ COPY_FPREG(&c.nat->regs.f[19], &sw->f19);
+ COPY_FPREG(&c.nat->regs.f[20], &sw->f20);
+ COPY_FPREG(&c.nat->regs.f[21], &sw->f21);
+ COPY_FPREG(&c.nat->regs.f[22], &sw->f22);
+ COPY_FPREG(&c.nat->regs.f[23], &sw->f23);
+ COPY_FPREG(&c.nat->regs.f[24], &sw->f24);
+ COPY_FPREG(&c.nat->regs.f[25], &sw->f25);
+ COPY_FPREG(&c.nat->regs.f[26], &sw->f26);
+ COPY_FPREG(&c.nat->regs.f[27], &sw->f27);
+ COPY_FPREG(&c.nat->regs.f[28], &sw->f28);
+ COPY_FPREG(&c.nat->regs.f[29], &sw->f29);
+ COPY_FPREG(&c.nat->regs.f[30], &sw->f30);
+ COPY_FPREG(&c.nat->regs.f[31], &sw->f31);
+
+ for (i = 0; i < 96; i++)
+ COPY_FPREG(&c.nat->regs.f[i + 32], &v->arch._thread.fph[i]);
+
+#define NATS_UPDATE(reg) \
+ nats_update(&c.nat->regs.nats, (reg), \
+ !!(uregs->eml_unat & \
+ (1UL << ia64_unat_pos(&uregs->r ## reg))))
+
+ // corresponding bit in ar.unat is determined by
+ // (&uregs->rN){8:3}.
+ // r8: the lowest gr member of struct cpu_user_regs.
+ // r7: the highest gr member of struct cpu_user_regs.
+ BUILD_BUG_ON(offsetof(struct cpu_user_regs, r7) -
+ offsetof(struct cpu_user_regs, r8) >
+ 64 * sizeof(unsigned long));
+
+ NATS_UPDATE(1);
+ NATS_UPDATE(2);
+ NATS_UPDATE(3);
+
+ NATS_UPDATE(8);
+ NATS_UPDATE(9);
+ NATS_UPDATE(10);
+ NATS_UPDATE(11);
+ NATS_UPDATE(12);
+ NATS_UPDATE(13);
+ NATS_UPDATE(14);
+ NATS_UPDATE(15);
+ NATS_UPDATE(16);
+ NATS_UPDATE(17);
+ NATS_UPDATE(18);
+ NATS_UPDATE(19);
+ NATS_UPDATE(20);
+ NATS_UPDATE(21);
+ NATS_UPDATE(22);
+ NATS_UPDATE(23);
+ NATS_UPDATE(24);
+ NATS_UPDATE(25);
+ NATS_UPDATE(26);
+ NATS_UPDATE(27);
+ NATS_UPDATE(28);
+ NATS_UPDATE(29);
+ NATS_UPDATE(30);
+ NATS_UPDATE(31);
+
+ if (!is_hvm) {
+ c.nat->regs.r[4] = uregs->r4;
+ c.nat->regs.r[5] = uregs->r5;
+ c.nat->regs.r[6] = uregs->r6;
+ c.nat->regs.r[7] = uregs->r7;
+
+ NATS_UPDATE(4);
+ NATS_UPDATE(5);
+ NATS_UPDATE(6);
+ NATS_UPDATE(7);
+#undef NATS_UPDATE
+ } else {
+ /*
+ * for VTi domain, r[4-7] are saved sometimes both in
+ * uregs->r[4-7] and memory stack or only in memory stack.
+ * So it is ok to get them from memory stack.
+ */
+ c.nat->regs.nats = uregs->eml_unat;
+
+ if (vcpu_has_not_run(v)) {
+ c.nat->regs.r[4] = sw->r4;
+ c.nat->regs.r[5] = sw->r5;
+ c.nat->regs.r[6] = sw->r6;
+ c.nat->regs.r[7] = sw->r7;
+
+ nats_update(&c.nat->regs.nats, 4,
+ !!(sw->ar_unat &
+ (1UL << ia64_unat_pos(&sw->r4))));
+ nats_update(&c.nat->regs.nats, 5,
+ !!(sw->ar_unat &
+ (1UL << ia64_unat_pos(&sw->r5))));
+ nats_update(&c.nat->regs.nats, 6,
+ !!(sw->ar_unat &
+ (1UL << ia64_unat_pos(&sw->r6))));
+ nats_update(&c.nat->regs.nats, 7,
+ !!(sw->ar_unat &
+ (1UL << ia64_unat_pos(&sw->r7))));
+ } else {
+ char nat;
+
+ unw_get_gr(&info, 4, &c.nat->regs.r[4], &nat);
+ nats_update(&c.nat->regs.nats, 4, nat);
+ unw_get_gr(&info, 5, &c.nat->regs.r[5], &nat);
+ nats_update(&c.nat->regs.nats, 5, nat);
+ unw_get_gr(&info, 6, &c.nat->regs.r[6], &nat);
+ nats_update(&c.nat->regs.nats, 6, nat);
+ unw_get_gr(&info, 7, &c.nat->regs.r[7], &nat);
+ nats_update(&c.nat->regs.nats, 7, nat);
+ }
+ }
c.nat->regs.rbs_voff = (IA64_RBS_OFFSET / 8) % 64;
- if (rbs_size < sizeof (c.nat->regs.rbs))
- memcpy(c.nat->regs.rbs, (char *)v + IA64_RBS_OFFSET, rbs_size);
+ if (unlikely(rbs_size > sizeof(c.nat->regs.rbs)))
+ gdprintk(XENLOG_INFO,
+ "rbs_size is too large 0x%x > 0x%lx\n",
+ rbs_size, sizeof(c.nat->regs.rbs));
+ else
+ memcpy(c.nat->regs.rbs, rbs_bottom, rbs_size);
+
+ rbs_top = (unsigned long*)((char *)rbs_bottom + rbs_size) - 1;
+ rbs_rnat_addr = ia64_rse_rnat_addr(rbs_top);
+ if ((unsigned long)rbs_rnat_addr >= sw->ar_bspstore)
+ rbs_rnat_addr = &sw->ar_rnat;
+
+ top_slot = ia64_rse_slot_num(rbs_top);
+
+ c.nat->regs.rbs_rnat = (*rbs_rnat_addr) & ((1UL << top_slot) - 1);
+ if (ia64_rse_rnat_addr(rbs_bottom) == ia64_rse_rnat_addr(rbs_top)) {
+ unsigned int bottom_slot = ia64_rse_slot_num(rbs_bottom);
+ c.nat->regs.rbs_rnat &= ~((1UL << bottom_slot) - 1);
+ }
c.nat->privregs_pfn = get_gpfn_from_mfn
(virt_to_maddr(v->arch.privregs) >> PAGE_SHIFT);
for (i = 0; i < IA64_NUM_DBG_REGS; i++) {
- vcpu_get_dbr(v, i, &c.nat->regs.dbr[i]);
- vcpu_get_ibr(v, i, &c.nat->regs.ibr[i]);
+ if (VMX_DOMAIN(v)) {
+ vmx_vcpu_get_dbr(v, i, &c.nat->regs.dbr[i]);
+ vmx_vcpu_get_ibr(v, i, &c.nat->regs.ibr[i]);
+ } else {
+ vcpu_get_dbr(v, i, &c.nat->regs.dbr[i]);
+ vcpu_get_ibr(v, i, &c.nat->regs.ibr[i]);
+ }
}
for (i = 0; i < 8; i++)
@@ -762,7 +991,12 @@ void arch_get_info_guest(struct vcpu *v,
vcpu_get_ifa(v, &c.nat->regs.cr.ifa);
vcpu_get_itir(v, &c.nat->regs.cr.itir);
vcpu_get_iha(v, &c.nat->regs.cr.iha);
- vcpu_get_ivr(v, &c.nat->regs.cr.ivr);
+
+ //XXX change irr[] and arch.insvc[]
+ if (v->domain->arch.is_vti)
+ /* c.nat->regs.cr.ivr = vmx_vcpu_get_ivr(v)*/;//XXXnot SMP-safe
+ else
+ vcpu_get_ivr (v, &c.nat->regs.cr.ivr);
vcpu_get_iim(v, &c.nat->regs.cr.iim);
vcpu_get_tpr(v, &c.nat->regs.cr.tpr);
@@ -770,18 +1004,172 @@ void arch_get_info_guest(struct vcpu *v,
vcpu_get_irr1(v, &c.nat->regs.cr.irr[1]);
vcpu_get_irr2(v, &c.nat->regs.cr.irr[2]);
vcpu_get_irr3(v, &c.nat->regs.cr.irr[3]);
- vcpu_get_itv(v, &c.nat->regs.cr.itv);
+ vcpu_get_itv(v, &c.nat->regs.cr.itv);//XXX vlsapic
vcpu_get_pmv(v, &c.nat->regs.cr.pmv);
vcpu_get_cmcv(v, &c.nat->regs.cr.cmcv);
+
+ if (is_hvm)
+ vmx_arch_get_info_guest(v, c);
+}
+
+#if 0
+// for debug
+static void
+__rbs_print(const char* func, int line, const char* name,
+ const unsigned long* rbs, unsigned int rbs_size)
+{
+ unsigned int i;
+ printk("%s:%d %s rbs %p\n", func, line, name, rbs);
+ printk(" rbs_size 0x%016x no 0x%lx\n",
+ rbs_size, rbs_size / sizeof(unsigned long));
+
+ for (i = 0; i < rbs_size / sizeof(unsigned long); i++) {
+ const char* zero_or_n = "0x";
+ if (ia64_rse_is_rnat_slot((unsigned long*)&rbs[i]))
+ zero_or_n = "Nx";
+
+ if ((i % 3) == 0)
+ printk("0x%02x:", i);
+ printk(" %s%016lx", zero_or_n, rbs[i]);
+ if ((i % 3) == 2)
+ printk("\n");
+ }
+ printk("\n");
+}
+
+#define rbs_print(rbs, rbs_size) \
+ __rbs_print(__func__, __LINE__, (#rbs), (rbs), (rbs_size))
+#endif
+
+static int
+copy_rbs(struct vcpu* v, unsigned long* dst_rbs_size,
+ const unsigned long* rbs, unsigned long rbs_size,
+ unsigned long src_rnat, unsigned long rbs_voff)
+{
+ int rc = -EINVAL;
+ struct page_info* page;
+ unsigned char* vaddr;
+ unsigned long* src_bsp;
+ unsigned long* src_bspstore;
+
+ struct switch_stack* sw = vcpu_to_switch_stack(v);
+ unsigned long num_regs;
+ unsigned long* dst_bsp;
+ unsigned long* dst_bspstore;
+ unsigned long* dst_rnat;
+ unsigned long dst_rnat_tmp;
+ unsigned long dst_rnat_mask;
+ unsigned long flags;
+ extern void ia64_copy_rbs(unsigned long* dst_bspstore,
+ unsigned long* dst_rbs_size,
+ unsigned long* dst_rnat_p,
+ unsigned long* src_bsp,
+ unsigned long src_rbs_size,
+ unsigned long src_rnat);
+
+ dst_bspstore = vcpu_to_rbs_bottom(v);
+ *dst_rbs_size = rbs_size;
+ if (rbs_size == 0)
+ return 0;
+
+ // rbs offset depends on sizeof(struct vcpu) so that
+ // it's too unstable for hypercall ABI.
+ // we need to take rbs offset into acount.
+ //memcpy(dst_bspstore, c.nat->regs.rbs, rbs_size);
+
+ // It is assumed that rbs_size is small enough compared
+ // to KERNEL_STACK_SIZE.
+ page = alloc_domheap_pages(NULL, KERNEL_STACK_SIZE_ORDER, 0);
+ if (page == NULL)
+ return -ENOMEM;
+ vaddr = page_to_virt(page);
+
+ src_bspstore = (unsigned long*)(vaddr + rbs_voff * 8);
+ src_bsp = (unsigned long*)((unsigned char*)src_bspstore + rbs_size);
+ if ((unsigned long)src_bsp >= (unsigned long)vaddr + PAGE_SIZE)
+ goto out;
+ memcpy(src_bspstore, rbs, rbs_size);
+
+ num_regs = ia64_rse_num_regs(src_bspstore, src_bsp);
+ dst_bsp = ia64_rse_skip_regs(dst_bspstore, num_regs);
+ *dst_rbs_size = (unsigned long)dst_bsp - (unsigned long)dst_bspstore;
+
+ // rough check.
+ if (((unsigned long)dst_bsp & ~PAGE_MASK) > KERNEL_STACK_SIZE / 2)
+ goto out;
+
+ //XXX TODO
+ // ia64_copy_rbs() uses real cpu's stack register.
+ // So it may fault with an Illigal Operation fault resulting
+ // in panic if rbs_size is too large to load compared to
+ // the number of physical stacked registers, RSE.N_STACKED_PHYS,
+ // which is cpu implementatin specific.
+ // See SDM vol. 2 Register Stack Engine 6, especially 6.5.5.
+ //
+ // For safe operation and cpu model independency,
+ // we need to copy them by hand without loadrs and flushrs
+ // However even if we implement that, similar issue still occurs
+ // when running guest. CPU context restore routine issues loadrs
+ // resulting in Illegal Operation fault. For such a case,
+ // we need to emulate RSE store.
+ // So it would be better to implement only RSE store emulation
+ // and copy stacked registers directly into guest RBS.
+ if (num_regs > num_phys_stacked) {
+ rc = -ENOSYS;
+ gdprintk(XENLOG_WARNING,
+ "%s:%d domain %d: can't load stacked registres\n"
+ "requested size 0x%lx => 0x%lx, num regs %ld"
+ "RSE.N_STACKED_PHYS %ld\n",
+ __func__, __LINE__, v->domain->domain_id,
+ rbs_size, *dst_rbs_size, num_regs,
+ num_phys_stacked);
+ goto out;
+ }
+
+ // we mask interrupts to avoid using register backing store.
+ local_irq_save(flags);
+ ia64_copy_rbs(dst_bspstore, dst_rbs_size, &dst_rnat_tmp,
+ src_bsp, rbs_size, src_rnat);
+ local_irq_restore(flags);
+
+ dst_rnat_mask = (1UL << ia64_rse_slot_num(dst_bsp)) - 1;
+ dst_rnat = ia64_rse_rnat_addr(dst_bsp);
+ if ((unsigned long)dst_rnat > sw->ar_bspstore)
+ dst_rnat = &sw->ar_rnat;
+ // if ia64_rse_rnat_addr(dst_bsp) ==
+ // ia64_rse_rnat_addr(vcpu_to_rbs_bottom(v)), the lsb bit of rnat
+ // is just ignored. so we don't have to mask it out.
+ *dst_rnat =
+ (*dst_rnat & ~dst_rnat_mask) | (dst_rnat_tmp & dst_rnat_mask);
+
+ rc = 0;
+out:
+ free_domheap_pages(page, KERNEL_STACK_SIZE_ORDER);
+ return rc;
+}
+
+static void
+unat_update(unsigned long *unat_eml, unsigned long *spill_addr, char nat)
+{
+ unsigned int pos = ia64_unat_pos(spill_addr);
+ if (nat)
+ *unat_eml |= (1UL << pos);
+ else
+ *unat_eml &= ~(1UL << pos);
}
int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
{
struct cpu_user_regs *uregs = vcpu_regs(v);
struct domain *d = v->domain;
+ struct switch_stack *sw = vcpu_to_switch_stack(v);
int was_initialised = v->is_initialised;
+ struct unw_frame_info info;
unsigned int rbs_size;
- int rc, i;
+ unsigned int num_regs;
+ unsigned long * const rbs_bottom = vcpu_to_rbs_bottom(v);
+ int rc = 0;
+ int i;
/* Finish vcpu initialization. */
if (!was_initialised) {
@@ -806,6 +1194,26 @@ int arch_set_info_guest(struct vcpu *v,
uregs->b6 = c.nat->regs.b[6];
uregs->b7 = c.nat->regs.b[7];
+ memset(&info, 0, sizeof(info));
+ unw_init_from_blocked_task(&info, v);
+ if (vcpu_has_not_run(v)) {
+ sw->ar_lc = c.nat->regs.ar.lc;
+ sw->ar_pfs =
+ (sw->ar_pfs & ~AR_PFS_PEC_MASK) |
+ ((c.nat->regs.ar.ec << AR_PFS_PEC_SHIFT) &
+ AR_PFS_PEC_MASK);
+ } else if (unw_unwind_to_user(&info) < 0) {
+ /* warn: should panic? */
+ gdprintk(XENLOG_ERR,
+ "vcpu=%d unw_unwind_to_user() failed.\n",
+ v->vcpu_id);
+ show_stack(v, NULL);
+
+ //return -ENOSYS;
+ } else {
+ unw_set_ar(&info, UNW_AR_LC, c.nat->regs.ar.lc);
+ unw_set_ar(&info, UNW_AR_EC, c.nat->regs.ar.ec);
+ }
uregs->ar_csd = c.nat->regs.ar.csd;
uregs->ar_ssd = c.nat->regs.ar.ssd;
@@ -820,7 +1228,7 @@ int arch_set_info_guest(struct vcpu *v,
vmx_vcpu_set_psr(v, c.nat->regs.psr);
uregs->cr_iip = c.nat->regs.ip;
uregs->cr_ifs = c.nat->regs.cfm;
-
+
uregs->ar_unat = c.nat->regs.ar.unat;
uregs->ar_pfs = c.nat->regs.ar.pfs;
uregs->ar_rsc = c.nat->regs.ar.rsc;
@@ -829,12 +1237,46 @@ int arch_set_info_guest(struct vcpu *v,
uregs->pr = c.nat->regs.pr;
uregs->b0 = c.nat->regs.b[0];
- rbs_size = c.nat->regs.ar.bsp - c.nat->regs.ar.bspstore;
+ if (((IA64_RBS_OFFSET / 8) % 64) != c.nat->regs.rbs_voff)
+ gdprintk(XENLOG_INFO,
+ "rbs stack offset is different! xen 0x%x given 0x%x",
+ (IA64_RBS_OFFSET / 8) % 64, c.nat->regs.rbs_voff);
+ num_regs = ia64_rse_num_regs((unsigned long*)c.nat->regs.ar.bspstore,
+ (unsigned long*)c.nat->regs.ar.bsp);
+ rbs_size = (unsigned long)ia64_rse_skip_regs(rbs_bottom, num_regs) -
+ (unsigned long)rbs_bottom;
+ if (rbs_size > sizeof (c.nat->regs.rbs)) {
+ gdprintk(XENLOG_INFO,
+ "rbs size is too large %x > %lx\n",
+ rbs_size, sizeof (c.nat->regs.rbs));
+ return -EINVAL;
+ }
+
/* Protection against crazy user code. */
if (!was_initialised)
- uregs->loadrs = (rbs_size) << 16;
- if (rbs_size == (uregs->loadrs >> 16))
- memcpy((char *)v + IA64_RBS_OFFSET, c.nat->regs.rbs, rbs_size);
+ uregs->loadrs = (rbs_size << 16);
+ if (rbs_size == (uregs->loadrs >> 16)) {
+ unsigned long dst_rbs_size = 0;
+ if (vcpu_has_not_run(v))
+ sw->ar_bspstore = (unsigned long)rbs_bottom;
+
+ rc = copy_rbs(v, &dst_rbs_size,
+ c.nat->regs.rbs, rbs_size,
+ c.nat->regs.rbs_rnat,
+ c.nat->regs.rbs_voff);
+ if (rc < 0)
+ return rc;
+
+ /* In case of newly created vcpu, ar_bspstore points to
+ * the bottom of register stack. Move it up.
+ * See also init_switch_stack().
+ */
+ if (vcpu_has_not_run(v)) {
+ uregs->loadrs = (dst_rbs_size << 16);
+ sw->ar_bspstore = (unsigned long)((char*)rbs_bottom +
+ dst_rbs_size);
+ }
+ }
uregs->r1 = c.nat->regs.r[1];
uregs->r12 = c.nat->regs.r[12];
@@ -863,22 +1305,117 @@ int arch_set_info_guest(struct vcpu *v,
uregs->r31 = c.nat->regs.r[31];
uregs->ar_ccv = c.nat->regs.ar.ccv;
-
+
+ COPY_FPREG(&sw->f2, &c.nat->regs.f[2]);
+ COPY_FPREG(&sw->f3, &c.nat->regs.f[3]);
+ COPY_FPREG(&sw->f4, &c.nat->regs.f[4]);
+ COPY_FPREG(&sw->f5, &c.nat->regs.f[5]);
+
COPY_FPREG(&uregs->f6, &c.nat->regs.f[6]);
COPY_FPREG(&uregs->f7, &c.nat->regs.f[7]);
COPY_FPREG(&uregs->f8, &c.nat->regs.f[8]);
COPY_FPREG(&uregs->f9, &c.nat->regs.f[9]);
COPY_FPREG(&uregs->f10, &c.nat->regs.f[10]);
COPY_FPREG(&uregs->f11, &c.nat->regs.f[11]);
+
+ COPY_FPREG(&sw->f12, &c.nat->regs.f[12]);
+ COPY_FPREG(&sw->f13, &c.nat->regs.f[13]);
+ COPY_FPREG(&sw->f14, &c.nat->regs.f[14]);
+ COPY_FPREG(&sw->f15, &c.nat->regs.f[15]);
+ COPY_FPREG(&sw->f16, &c.nat->regs.f[16]);
+ COPY_FPREG(&sw->f17, &c.nat->regs.f[17]);
+ COPY_FPREG(&sw->f18, &c.nat->regs.f[18]);
+ COPY_FPREG(&sw->f19, &c.nat->regs.f[19]);
+ COPY_FPREG(&sw->f20, &c.nat->regs.f[20]);
+ COPY_FPREG(&sw->f21, &c.nat->regs.f[21]);
+ COPY_FPREG(&sw->f22, &c.nat->regs.f[22]);
+ COPY_FPREG(&sw->f23, &c.nat->regs.f[23]);
+ COPY_FPREG(&sw->f24, &c.nat->regs.f[24]);
+ COPY_FPREG(&sw->f25, &c.nat->regs.f[25]);
+ COPY_FPREG(&sw->f26, &c.nat->regs.f[26]);
+ COPY_FPREG(&sw->f27, &c.nat->regs.f[27]);
+ COPY_FPREG(&sw->f28, &c.nat->regs.f[28]);
+ COPY_FPREG(&sw->f29, &c.nat->regs.f[29]);
+ COPY_FPREG(&sw->f30, &c.nat->regs.f[30]);
+ COPY_FPREG(&sw->f31, &c.nat->regs.f[31]);
+
+ for (i = 0; i < 96; i++)
+ COPY_FPREG(&v->arch._thread.fph[i], &c.nat->regs.f[i + 32]);
+
+
+#define UNAT_UPDATE(reg) \
+ unat_update(&uregs->eml_unat, &uregs->r ## reg, \
+ !!(c.nat->regs.nats & (1UL << (reg))));
+
+ uregs->eml_unat = 0;
+ UNAT_UPDATE(1);
+ UNAT_UPDATE(2);
+ UNAT_UPDATE(3);
+
+ UNAT_UPDATE(8);
+ UNAT_UPDATE(9);
+ UNAT_UPDATE(10);
+ UNAT_UPDATE(11);
+ UNAT_UPDATE(12);
+ UNAT_UPDATE(13);
+ UNAT_UPDATE(14);
+ UNAT_UPDATE(15);
+ UNAT_UPDATE(16);
+ UNAT_UPDATE(17);
+ UNAT_UPDATE(18);
+ UNAT_UPDATE(19);
+ UNAT_UPDATE(20);
+ UNAT_UPDATE(21);
+ UNAT_UPDATE(22);
+ UNAT_UPDATE(23);
+ UNAT_UPDATE(24);
+ UNAT_UPDATE(25);
+ UNAT_UPDATE(26);
+ UNAT_UPDATE(27);
+ UNAT_UPDATE(28);
+ UNAT_UPDATE(29);
+ UNAT_UPDATE(30);
+ UNAT_UPDATE(31);
+ /*
+ * r4-r7 is saved sometimes both in pt_regs->r[4-7] and memory stack or
+ * only in memory stack.
+ * for both cases, both memory stack and pt_regs->r[4-7] are updated.
+ */
uregs->r4 = c.nat->regs.r[4];
uregs->r5 = c.nat->regs.r[5];
uregs->r6 = c.nat->regs.r[6];
uregs->r7 = c.nat->regs.r[7];
-
- /* FIXME: to be reordered and restored. */
- /* uregs->eml_unat = c.nat->regs.nat; */
- uregs->eml_unat = 0;
+
+ UNAT_UPDATE(4);
+ UNAT_UPDATE(5);
+ UNAT_UPDATE(6);
+ UNAT_UPDATE(7);
+#undef UNAT_UPDATE
+ if (vcpu_has_not_run(v)) {
+ sw->r4 = c.nat->regs.r[4];
+ sw->r5 = c.nat->regs.r[5];
+ sw->r6 = c.nat->regs.r[6];
+ sw->r7 = c.nat->regs.r[7];
+
+ unat_update(&sw->ar_unat, &sw->r4,
+ !!(c.nat->regs.nats & (1UL << 4)));
+ unat_update(&sw->ar_unat, &sw->r5,
+ !!(c.nat->regs.nats & (1UL << 5)));
+ unat_update(&sw->ar_unat, &sw->r6,
+ !!(c.nat->regs.nats & (1UL << 6)));
+ unat_update(&sw->ar_unat, &sw->r7,
+ !!(c.nat->regs.nats & (1UL << 7)));
+ } else {
+ unw_set_gr(&info, 4, c.nat->regs.r[4],
+ !!(c.nat->regs.nats & (1UL << 4)));
+ unw_set_gr(&info, 5, c.nat->regs.r[5],
+ !!(c.nat->regs.nats & (1UL << 5)));
+ unw_set_gr(&info, 6, c.nat->regs.r[6],
+ !!(c.nat->regs.nats & (1UL << 6)));
+ unw_set_gr(&info, 7, c.nat->regs.r[7],
+ !!(c.nat->regs.nats & (1UL << 7)));
+ }
if (!d->arch.is_vti) {
/* domain runs at PL2/3 */
@@ -888,8 +1425,31 @@ int arch_set_info_guest(struct vcpu *v,
}
for (i = 0; i < IA64_NUM_DBG_REGS; i++) {
- vcpu_set_dbr(v, i, c.nat->regs.dbr[i]);
- vcpu_set_ibr(v, i, c.nat->regs.ibr[i]);
+ if (d->arch.is_vti) {
+ vmx_vcpu_set_dbr(v, i, c.nat->regs.dbr[i]);
+ vmx_vcpu_set_ibr(v, i, c.nat->regs.ibr[i]);
+ } else {
+ vcpu_set_dbr(v, i, c.nat->regs.dbr[i]);
+ vcpu_set_ibr(v, i, c.nat->regs.ibr[i]);
+ }
+ }
+
+ /* rr[] must be set before setting itrs[] dtrs[] */
+ for (i = 0; i < 8; i++) {
+ //XXX TODO integrity check.
+ // if invalid value is given,
+ // vmx_load_all_rr() and load_region_regs()
+ // result in General exception, reserved register/field
+ // failt causing panicing xen.
+ if (d->arch.is_vti) {
+ //without VGCF_EXTRA_REGS check,
+ //VTi domain doesn't boot.
+ if (c.nat->flags & VGCF_EXTRA_REGS)
+ vmx_vcpu_set_rr(v, (unsigned long)i << 61,
+ c.nat->regs.rr[i]);
+ } else
+ vcpu_set_rr(v, (unsigned long)i << 61,
+ c.nat->regs.rr[i]);
}
if (c.nat->flags & VGCF_EXTRA_REGS) {
@@ -898,25 +1458,38 @@ int arch_set_info_guest(struct vcpu *v,
for (i = 0;
(i < sizeof(tr->itrs) / sizeof(tr->itrs[0])) && i < NITRS;
i++) {
- vcpu_set_itr(v, i, tr->itrs[i].pte,
- tr->itrs[i].itir,
- tr->itrs[i].vadr,
- tr->itrs[i].rid);
+ if (d->arch.is_vti)
+ vmx_vcpu_itr_i(v, i, tr->itrs[i].pte,
+ tr->itrs[i].itir,
+ tr->itrs[i].vadr);
+ else
+ vcpu_set_itr(v, i, tr->itrs[i].pte,
+ tr->itrs[i].itir,
+ tr->itrs[i].vadr,
+ tr->itrs[i].rid);
}
for (i = 0;
(i < sizeof(tr->dtrs) / sizeof(tr->dtrs[0])) && i < NDTRS;
i++) {
- vcpu_set_dtr(v, i,
- tr->dtrs[i].pte,
- tr->dtrs[i].itir,
- tr->dtrs[i].vadr,
- tr->dtrs[i].rid);
+ if (d->arch.is_vti)
+ vmx_vcpu_itr_d(v, i, tr->dtrs[i].pte,
+ tr->dtrs[i].itir,
+ tr->dtrs[i].vadr);
+ else
+ vcpu_set_dtr(v, i,
+ tr->dtrs[i].pte,
+ tr->dtrs[i].itir,
+ tr->dtrs[i].vadr,
+ tr->dtrs[i].rid);
}
v->arch.event_callback_ip = c.nat->event_callback_ip;
vcpu_set_iva(v, c.nat->regs.cr.iva);
}
- return 0;
+ if (d->arch.is_vti)
+ rc = vmx_arch_set_info_guest(v, c);
+
+ return rc;
}
static void relinquish_memory(struct domain *d, struct list_head *list)
diff -r 905a46fbe0d8 -r a04cedb034ea xen/arch/ia64/xen/xenasm.S
--- a/xen/arch/ia64/xen/xenasm.S Wed Oct 10 19:45:29 2007 +0900
+++ b/xen/arch/ia64/xen/xenasm.S Thu Oct 11 19:54:56 2007 +0900
@@ -3,6 +3,10 @@
*
* Copyright (C) 2004 Hewlett-Packard Co
* Dan Magenheimer <dan.magenheimer@xxxxxx>
+ *
+ * Copyright (C) 2007 VA Linux Systems Japan K.K.
+ * Isaku Yamahata <yamahata at valinux co jp>
+ * ia64_copy_rbs()
*/
#include <linux/config.h>
@@ -357,3 +361,145 @@ stacked:
br.ret.sptk.few rp
END(pal_emulator_static)
+// void ia64_copy_rbs(unsigned long* dst_bspstore, unsigned long* dst_rbs_size,
+// unsigned long* dst_rnat_p,
+// unsigned long* src_bsp, unsigned long src_rbs_size,
+// unsigned long src_rnat);
+// Caller must mask interrupions.
+// Caller must ensure that src_rbs_size isn't larger than the number
+// of physical stacked registers. otherwise loadrs fault with Illegal
+// Operation fault resulting in panic.
+//
+// r14 = r32 = dst_bspstore
+// r15 = r33 = dst_rbs_size_p
+// r16 = r34 = dst_rnat_p
+// r17 = r35 = src_bsp
+// r18 = r36 = src_rbs_size
+// r19 = r37 = src_rnat
+//
+// r20 = saved ar.rsc
+// r21 = saved ar.bspstore
+//
+// r22 = saved_ar_rnat
+// r23 = saved_ar_rp
+// r24 = saved_ar_pfs
+//
+// we save the value in this register and store it into [dst_rbs_size_p] and
+// [dst_rnat_p] after rse opeation is done.
+// r30 = return value of __ia64_copy_rbs to ia64_copy_to_rbs = dst_rbs_size
+// r31 = return value of __ia64_copy_rbs to ia64_copy_to_rbs = dst_rnat
+//
+#define dst_bspstore r14
+#define dst_rbs_size_p r15
+#define dst_rnat_p r16
+#define src_bsp r17
+#define src_rbs_size r18
+#define src_rnat r19
+
+#define saved_ar_rsc r20
+#define saved_ar_bspstore r21
+#define saved_ar_rnat r22
+#define saved_rp r23
+#define saved_ar_pfs r24
+
+#define dst_rbs_size r30
+#define dst_rnat r31
+ENTRY(__ia64_copy_rbs)
+ .prologue
+ .fframe 0
+
+ // Here cfm.{sof, sol, sor, rrb}=0
+ //
+ // flush current register stack to backing store
+{
+ flushrs // must be first isns in group
+ srlz.i
+}
+
+ // switch to enforced lazy mode
+ mov saved_ar_rsc = ar.rsc
+ ;;
+ mov ar.rsc = 0
+ ;;
+
+ .save ar.bspstore, saved_ar_bspstore
+ mov saved_ar_bspstore = ar.bspstore
+ .save ar.rnat, saved_ar_rnat
+ mov saved_ar_rnat = ar.rnat
+ ;;
+
+ .body
+ // load from src
+ mov ar.bspstore = src_bsp
+ ;;
+ mov ar.rnat = src_rnat
+ shl src_rbs_size = src_rbs_size,16
+ ;;
+ mov ar.rsc = src_rbs_size
+ ;;
+{
+ loadrs // must be first isns in group
+ ;;
+}
+
+ // flush to dst
+ mov ar.bspstore = dst_bspstore
+ ;;
+{
+ flushrs // must be first isns in group
+ srlz.i
+}
+ ;;
+ mov dst_rbs_size = ar.bsp
+ mov dst_rnat = ar.rnat
+ ;;
+ sub dst_rbs_size = dst_rbs_size, dst_bspstore
+
+ // switch back to the original backing store
+ .restorereg ar.bspstore
+ mov ar.bspstore = saved_ar_bspstore
+ ;;
+ .restorereg ar.rnat
+ mov ar.rnat = saved_ar_rnat
+ ;;
+ // restore rsc
+ mov ar.rsc = saved_ar_rsc
+
+ ;;
+ br.ret.sptk.many rp
+END(__ia64_copy_rbs)
+
+GLOBAL_ENTRY(ia64_copy_rbs)
+ .prologue
+ .fframe 0
+ .save ar.pfs, saved_ar_pfs
+ alloc saved_ar_pfs = ar.pfs, 6, 0, 0, 0
+ .save.b 0x1, saved_rp
+ mov saved_rp = rp
+
+ .body
+ // we play with register backing store so that we can't use
+ // stacked registers.
+ // save in0-in5 to static scratch registres
+ mov dst_bspstore = r32
+ mov dst_rbs_size_p = r33
+ mov dst_rnat_p = r34
+ mov src_bsp = r35
+ mov src_rbs_size = r36
+ mov src_rnat = r37
+ ;;
+ // set cfm.{sof, sol, sor, rrb}=0 to avoid nasty stacked register
+ // issues related to cover by calling void __ia64_copy_rbs(void).
+ // cfm.{sof, sol, sor, rrb}=0 makes things easy.
+ br.call.sptk.many rp = __ia64_copy_rbs
+
+ st8 [dst_rbs_size_p] = dst_rbs_size
+ st8 [dst_rnat_p] = dst_rnat
+
+ .restorereg ar.pfs
+ mov ar.pfs = saved_ar_pfs
+ .restorereg rp
+ mov rp = saved_rp
+ ;;
+ br.ret.sptk.many rp
+END(ia64_copy_rbs)
diff -r 905a46fbe0d8 -r a04cedb034ea xen/include/asm-ia64/vmx_vcpu_save.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-ia64/vmx_vcpu_save.h Thu Oct 11 19:54:56 2007 +0900
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * vmx_vcpu_save.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 __ASM_IA64_VMX_VCPU_SAVE_H__
+#define __ASM_IA64_VMX_VCPU_SAVE_H__
+
+#include <xen/sched.h>
+#include <xen/domain.h>
+
+void vmx_arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c);
+int vmx_arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c);
+
+#endif /* __ASM_IA64_VMX_VCPU_SAVE_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 905a46fbe0d8 -r a04cedb034ea xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h Wed Oct 10 19:45:29 2007 +0900
+++ b/xen/include/public/arch-ia64.h Thu Oct 11 19:54:56 2007 +0900
@@ -421,7 +421,7 @@ struct vcpu_guest_context_regs {
};
struct vcpu_guest_context {
-#define VGCF_EXTRA_REGS (1<<1) /* Get/Set extra regs. */
+#define VGCF_EXTRA_REGS (1UL << 1) /* Get/Set extra regs. */
unsigned long flags; /* VGCF_* flags */
struct vcpu_guest_context_regs regs;
16064_a04cedb034ea_implement_arch_get_set_info_guest.patch
Description: Text Data
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|