WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ia64-devel

[Xen-ia64-devel] [PATCH 16/23] [RFC] vti domain save/restore: implement

To: xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-ia64-devel] [PATCH 16/23] [RFC] vti domain save/restore: implement arch_get/set_info_guest() more
From: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Date: Fri, 12 Oct 2007 12:51:36 +0900
Cc: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Delivery-date: Thu, 11 Oct 2007 20:54:24 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-ia64-devel-request@lists.xensource.com?subject=help>
List-id: Discussion of the ia64 port of Xen <xen-ia64-devel.lists.xensource.com>
List-post: <mailto:xen-ia64-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ia64-devel>, <mailto:xen-ia64-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ia64-devel>, <mailto:xen-ia64-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-ia64-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.4.2.1i
# 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;

Attachment: 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
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-ia64-devel] [PATCH 16/23] [RFC] vti domain save/restore: implement arch_get/set_info_guest() more, Isaku Yamahata <=