ia64/xen-unstable

changeset 16170:ff1f49f62204

[IA64] vti domain save/restore: implement arch_get/set_info_guest() more

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Sun Oct 21 13:38:57 2007 -0600 (2007-10-21)
parents d261b2d5e988
children e7d7a4adf357
files xen/arch/ia64/vmx/Makefile xen/arch/ia64/vmx/vmx_vcpu_save.c xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/xenasm.S xen/include/asm-ia64/vmx_vcpu_save.h xen/include/public/arch-ia64.h
line diff
     1.1 --- a/xen/arch/ia64/vmx/Makefile	Sun Oct 21 13:38:05 2007 -0600
     1.2 +++ b/xen/arch/ia64/vmx/Makefile	Sun Oct 21 13:38:57 2007 -0600
     1.3 @@ -19,3 +19,4 @@ obj-y += vmx_vsa.o
     1.4  obj-y += vtlb.o
     1.5  obj-y += optvfault.o
     1.6  obj-y += vacpi.o
     1.7 +obj-y += vmx_vcpu_save.o
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xen/arch/ia64/vmx/vmx_vcpu_save.c	Sun Oct 21 13:38:57 2007 -0600
     2.3 @@ -0,0 +1,203 @@
     2.4 +/******************************************************************************
     2.5 + * vmx_vcpu_save.c
     2.6 + *
     2.7 + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
     2.8 + *                    VA Linux Systems Japan K.K.
     2.9 + *
    2.10 + * This program is free software; you can redistribute it and/or modify
    2.11 + * it under the terms of the GNU General Public License as published by
    2.12 + * the Free Software Foundation; either version 2 of the License, or
    2.13 + * (at your option) any later version.
    2.14 + *
    2.15 + * This program is distributed in the hope that it will be useful,
    2.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.18 + * GNU General Public License for more details.
    2.19 + *
    2.20 + * You should have received a copy of the GNU General Public License
    2.21 + * along with this program; if not, write to the Free Software
    2.22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.23 + *
    2.24 + */
    2.25 +
    2.26 +#include <asm/vmx_vcpu.h>
    2.27 +#include <asm/vmx_vcpu_save.h>
    2.28 +
    2.29 +void
    2.30 +vmx_arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
    2.31 +{
    2.32 +    vpd_t *vpd = (void *)v->arch.privregs;
    2.33 +    struct mapped_regs *vpd_low = &vpd->vpd_low;
    2.34 +    unsigned long nats;
    2.35 +    unsigned long bnats;
    2.36 +
    2.37 +    union vcpu_ar_regs *ar = &c.nat->regs.ar;
    2.38 +    union vcpu_cr_regs *cr = &c.nat->regs.cr;
    2.39 +    int i;
    2.40 +
    2.41 +    // banked registers
    2.42 +    if (vpd_low->vpsr & IA64_PSR_BN) {
    2.43 +        for (i = 0; i < 16; i++) {
    2.44 +            //c.nat->regs.r[i + 16] = vpd_low->vgr[i];
    2.45 +            c.nat->regs.bank[i] = vpd_low->vbgr[i];
    2.46 +        }
    2.47 +        nats = vpd_low->vnat;
    2.48 +        bnats = vpd_low->vbnat;
    2.49 +    } else {
    2.50 +        for (i = 0; i < 16; i++) {
    2.51 +            c.nat->regs.bank[i] = vpd_low->vgr[i];
    2.52 +            //c.nat->regs.r[i + 16] = vpd_low->vbgr[i];
    2.53 +        }
    2.54 +        bnats = vpd_low->vnat;
    2.55 +        nats = vpd_low->vbnat;
    2.56 +    }
    2.57 +    // c.nat->regs.nats[0:15] is already set. we shouldn't overwrite.
    2.58 +    c.nat->regs.nats =
    2.59 +        (c.nat->regs.nats & MASK(0, 16)) | (nats & MASK(16, 16));
    2.60 +    c.nat->regs.bnats = bnats & MASK(16, 16);
    2.61 +
    2.62 +    //c.nat->regs.psr = vpd_low->vpsr;
    2.63 +    //c.nat->regs.pr = vpd_low->vpr;
    2.64 +
    2.65 +    // ar
    2.66 +    ar->kr[0] = v->arch.arch_vmx.vkr[0];
    2.67 +    ar->kr[1] = v->arch.arch_vmx.vkr[1];
    2.68 +    ar->kr[2] = v->arch.arch_vmx.vkr[2];
    2.69 +    ar->kr[3] = v->arch.arch_vmx.vkr[3];
    2.70 +    ar->kr[4] = v->arch.arch_vmx.vkr[4];
    2.71 +    ar->kr[5] = v->arch.arch_vmx.vkr[5];
    2.72 +    ar->kr[6] = v->arch.arch_vmx.vkr[6];
    2.73 +    ar->kr[7] = v->arch.arch_vmx.vkr[7];
    2.74 +#ifdef CONFIG_IA32_SUPPORT
    2.75 +    // csd and ssd are done by arch_get_info_guest()
    2.76 +    ar->fcr = v->arch._thread.fcr;
    2.77 +    ar->eflag = v->arch._thread.eflag;
    2.78 +    ar->cflg = v->arch._thread.cflg;
    2.79 +    ar->fsr = v->arch._thread.fsr;
    2.80 +    ar->fir = v->arch._thread.fir;
    2.81 +    ar->fdr = v->arch._thread.fdr;
    2.82 +#endif
    2.83 +    //ar->itc = vpd_low->itc;//see vtime
    2.84 +
    2.85 +    // cr
    2.86 +    //cr->dcr = vpd_low->dcr;
    2.87 +    //cr->itm = vpd_low->itm;
    2.88 +    //cr->iva = vpd_low->iva;
    2.89 +    //cr->pta = vpd_low->pta;
    2.90 +    //cr->ipsr = vpd_low->ipsr;
    2.91 +    //cr->isr = vpd_low->isr;
    2.92 +    //cr->iip = vpd_low->iip;
    2.93 +    //cr->ifa = vpd_low->ifa;
    2.94 +    //cr->itir = vpd_low->itir;
    2.95 +    cr->iipa = vpd_low->iipa;
    2.96 +    cr->ifs = vpd_low->ifs;
    2.97 +    //cr->iim = vpd_low->iim;
    2.98 +    //cr->iha = vpd_low->iha;
    2.99 +    cr->lid = vpd_low->lid;
   2.100 +    cr->ivr = vpd_low->ivr;
   2.101 +    //cr->tpr = vpd_low->tpr;
   2.102 +    cr->eoi = vpd_low->eoi;
   2.103 +    //cr->irr[0] = vpd_low->irr[0];
   2.104 +    //cr->irr[1] = vpd_low->irr[1];
   2.105 +    //cr->irr[2] = vpd_low->irr[2];
   2.106 +    //cr->irr[3] = vpd_low->irr[3];
   2.107 +    //cr->itv = vpd_low->itv;
   2.108 +    //cr->pmv = vpd_low->pmv;
   2.109 +    //cr->cmcv = vpd_low->cmcv;
   2.110 +    cr->lrr0 = vpd_low->lrr0;
   2.111 +    cr->lrr1 = vpd_low->lrr1;
   2.112 +}
   2.113 +
   2.114 +int
   2.115 +vmx_arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
   2.116 +{
   2.117 +    vpd_t *vpd = (void *)v->arch.privregs;
   2.118 +    struct mapped_regs *vpd_low = &vpd->vpd_low;
   2.119 +    unsigned long vnat;
   2.120 +    unsigned long vbnat;
   2.121 +
   2.122 +     union vcpu_ar_regs *ar = &c.nat->regs.ar;
   2.123 +     union vcpu_cr_regs *cr = &c.nat->regs.cr;
   2.124 +    int i;
   2.125 +
   2.126 +    // banked registers
   2.127 +    if (c.nat->regs.psr & IA64_PSR_BN) {
   2.128 +        for (i = 0; i < 16; i++) {
   2.129 +            //vpd_low->vgr[i] = c.nat->regs.r[i + 16];
   2.130 +            vpd_low->vbgr[i] = c.nat->regs.bank[i];
   2.131 +        }
   2.132 +        vnat = c.nat->regs.nats;
   2.133 +        vbnat = c.nat->regs.bnats;
   2.134 +    } else {
   2.135 +        for (i = 0; i < 16; i++) {
   2.136 +            vpd_low->vgr[i] = c.nat->regs.bank[i];
   2.137 +            //vpd_low->vbgr[i] = c.nat->regs.r[i + 16];
   2.138 +        }
   2.139 +        vbnat = c.nat->regs.nats;
   2.140 +        vnat = c.nat->regs.bnats;
   2.141 +    }
   2.142 +    vpd_low->vnat = vnat & MASK(16, 16);
   2.143 +    vpd_low->vbnat = vbnat & MASK(16, 16);
   2.144 +    //vpd_low->vpsr = c.nat->regs.psr;
   2.145 +    //vpd_low->vpr = c.nat->regs.pr;
   2.146 +
   2.147 +    // ar
   2.148 +    v->arch.arch_vmx.vkr[0] = ar->kr[0];
   2.149 +    v->arch.arch_vmx.vkr[1] = ar->kr[1];
   2.150 +    v->arch.arch_vmx.vkr[2] = ar->kr[2];
   2.151 +    v->arch.arch_vmx.vkr[3] = ar->kr[3];
   2.152 +    v->arch.arch_vmx.vkr[4] = ar->kr[4];
   2.153 +    v->arch.arch_vmx.vkr[5] = ar->kr[5];
   2.154 +    v->arch.arch_vmx.vkr[6] = ar->kr[6];
   2.155 +    v->arch.arch_vmx.vkr[7] = ar->kr[7];
   2.156 +#ifdef CONFIG_IA32_SUPPORT
   2.157 +    v->arch._thread.fcr = ar->fcr;
   2.158 +    v->arch._thread.eflag = ar->eflag;
   2.159 +    v->arch._thread.cflg = ar->cflg;
   2.160 +    v->arch._thread.fsr = ar->fsr;
   2.161 +    v->arch._thread.fir = ar->fir;
   2.162 +    v->arch._thread.fdr = ar->fdr;
   2.163 +#endif
   2.164 +    //vpd_low->itc = ar->itc;// see vtime.
   2.165 +
   2.166 +    // cr
   2.167 +    vpd_low->dcr = cr->dcr;
   2.168 +    vpd_low->itm = cr->itm;
   2.169 +    //vpd_low->iva = cr->iva;
   2.170 +    vpd_low->pta = cr->pta;
   2.171 +    vpd_low->ipsr = cr->ipsr;
   2.172 +    vpd_low->isr = cr->isr;
   2.173 +    vpd_low->iip = cr->iip;
   2.174 +    vpd_low->ifa = cr->ifa;
   2.175 +    vpd_low->itir = cr->itir;
   2.176 +    vpd_low->iipa = cr->iipa;
   2.177 +    vpd_low->ifs = cr->ifs;
   2.178 +    vpd_low->iim = cr->iim;
   2.179 +    vpd_low->iha = cr->iha;
   2.180 +    vpd_low->lid = cr->lid;
   2.181 +    vpd_low->ivr = cr->ivr; //XXX vlsapic
   2.182 +    vpd_low->tpr = cr->tpr;
   2.183 +    vpd_low->eoi = cr->eoi;
   2.184 +    vpd_low->irr[0] = cr->irr[0];
   2.185 +    vpd_low->irr[1] = cr->irr[1];
   2.186 +    vpd_low->irr[2] = cr->irr[2];
   2.187 +    vpd_low->irr[3] = cr->irr[3];
   2.188 +    vpd_low->itv = cr->itv;
   2.189 +    vpd_low->pmv = cr->pmv;
   2.190 +    vpd_low->cmcv = cr->cmcv;
   2.191 +    vpd_low->lrr0 = cr->lrr0;
   2.192 +    vpd_low->lrr1 = cr->lrr1;
   2.193 +
   2.194 +    v->arch.irq_new_condition = 1;
   2.195 +    return 0;
   2.196 +}
   2.197 +
   2.198 +/*
   2.199 + * Local variables:
   2.200 + * mode: C
   2.201 + * c-set-style: "BSD"
   2.202 + * c-basic-offset: 4
   2.203 + * tab-width: 4
   2.204 + * indent-tabs-mode: nil
   2.205 + * End:
   2.206 + */
     3.1 --- a/xen/arch/ia64/xen/domain.c	Sun Oct 21 13:38:05 2007 -0600
     3.2 +++ b/xen/arch/ia64/xen/domain.c	Sun Oct 21 13:38:57 2007 -0600
     3.3 @@ -41,6 +41,7 @@
     3.4  #include <asm/vmx_vcpu.h>
     3.5  #include <asm/vmx_vpd.h>
     3.6  #include <asm/vmx_phy_mode.h>
     3.7 +#include <asm/vmx_vcpu_save.h>
     3.8  #include <asm/vhpt.h>
     3.9  #include <asm/vcpu.h>
    3.10  #include <asm/tlbflush.h>
    3.11 @@ -54,6 +55,7 @@
    3.12  #include <public/vcpu.h>
    3.13  #include <linux/cpu.h>
    3.14  #include <linux/notifier.h>
    3.15 +#include <asm/debugger.h>
    3.16  
    3.17  /* dom0_size: default memory allocation for dom0 (~4GB) */
    3.18  static unsigned long __initdata dom0_size = 4096UL*1024UL*1024UL;
    3.19 @@ -516,6 +518,12 @@ void vcpu_destroy(struct vcpu *v)
    3.20  		relinquish_vcpu_resources(v);
    3.21  }
    3.22  
    3.23 +static unsigned long*
    3.24 +vcpu_to_rbs_bottom(struct vcpu *v)
    3.25 +{
    3.26 +	return (unsigned long*)((char *)v + IA64_RBS_OFFSET);
    3.27 +}
    3.28 +
    3.29  static void init_switch_stack(struct vcpu *v)
    3.30  {
    3.31  	struct pt_regs *regs = vcpu_regs (v);
    3.32 @@ -523,7 +531,7 @@ static void init_switch_stack(struct vcp
    3.33  	extern void ia64_ret_from_clone;
    3.34  
    3.35  	memset(sw, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs));
    3.36 -	sw->ar_bspstore = (unsigned long)v + IA64_RBS_OFFSET;
    3.37 +	sw->ar_bspstore = (unsigned long)vcpu_to_rbs_bottom(v);
    3.38  	sw->b0 = (unsigned long) &ia64_ret_from_clone;
    3.39  	sw->ar_fpsr = FPSR_DEFAULT;
    3.40  	v->arch._thread.ksp = (unsigned long) sw - 16;
    3.41 @@ -628,19 +636,100 @@ int arch_vcpu_reset(struct vcpu *v)
    3.42  	return 0;
    3.43  }
    3.44  
    3.45 +static unsigned long num_phys_stacked;
    3.46 +static int __init
    3.47 +init_num_phys_stacked(void)
    3.48 +{
    3.49 +	switch (ia64_pal_rse_info(&num_phys_stacked, NULL)) {
    3.50 +	case 0L:
    3.51 +		printk("the number of physical stacked general registers"
    3.52 +		       "(RSE.N_STACKED_PHYS) = %ld\n", num_phys_stacked);
    3.53 +		return 0;
    3.54 +	case -2L:
    3.55 +	case -3L:
    3.56 +	default:
    3.57 +		break;
    3.58 +	}
    3.59 +	printk("WARNING: PAL_RSE_INFO call failed. "
    3.60 +	       "domain save/restore may NOT work!\n");
    3.61 +	return -EINVAL;
    3.62 +}
    3.63 +__initcall(init_num_phys_stacked);
    3.64 +
    3.65  #define COPY_FPREG(dst, src) memcpy(dst, src, sizeof(struct ia64_fpreg))
    3.66  
    3.67 +#define AR_PFS_PEC_SHIFT	51
    3.68 +#define AR_PFS_REC_SIZE		6
    3.69 +#define AR_PFS_PEC_MASK		(((1UL << 6) - 1) << 51)
    3.70 +
    3.71 +/*
    3.72 + * See init_swtich_stack() and ptrace.h
    3.73 + */
    3.74 +static struct switch_stack*
    3.75 +vcpu_to_switch_stack(struct vcpu* v)
    3.76 +{
    3.77 +	return (struct switch_stack *)(v->arch._thread.ksp + 16);
    3.78 +}
    3.79 +
    3.80 +static int
    3.81 +vcpu_has_not_run(struct vcpu* v)
    3.82 +{
    3.83 +	extern void ia64_ret_from_clone;
    3.84 +	struct switch_stack *sw = vcpu_to_switch_stack(v);
    3.85 +
    3.86 +	return (sw == (struct switch_stack *)(vcpu_regs(v)) - 1) &&
    3.87 +		(sw->b0 == (unsigned long)&ia64_ret_from_clone);
    3.88 +}
    3.89 +
    3.90 +static void
    3.91 +nats_update(unsigned int* nats, unsigned int reg, char nat)
    3.92 +{
    3.93 +	BUG_ON(reg > 31);
    3.94 +
    3.95 +	if (nat)
    3.96 +		*nats |= (1UL << reg);
    3.97 +	else
    3.98 +		*nats &= ~(1UL << reg);
    3.99 +}
   3.100 +
   3.101  void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
   3.102  {
   3.103  	int i;
   3.104  	struct vcpu_tr_regs *tr = &c.nat->regs.tr;
   3.105  	struct cpu_user_regs *uregs = vcpu_regs(v);
   3.106 +	struct switch_stack *sw = vcpu_to_switch_stack(v);
   3.107 +	struct unw_frame_info info;
   3.108  	int is_hvm = VMX_DOMAIN(v);
   3.109  	unsigned int rbs_size;
   3.110 +	unsigned long *const rbs_bottom = vcpu_to_rbs_bottom(v);
   3.111 +	unsigned long *rbs_top;
   3.112 +	unsigned long *rbs_rnat_addr;
   3.113 +	unsigned int top_slot;
   3.114 +	unsigned int num_regs;
   3.115  
   3.116 +	memset(c.nat, 0, sizeof(*c.nat));
   3.117  	c.nat->regs.b[6] = uregs->b6;
   3.118  	c.nat->regs.b[7] = uregs->b7;
   3.119  
   3.120 +	memset(&info, 0, sizeof(info));
   3.121 +	unw_init_from_blocked_task(&info, v);
   3.122 +	if (vcpu_has_not_run(v)) {
   3.123 +		c.nat->regs.ar.lc = sw->ar_lc;
   3.124 +		c.nat->regs.ar.ec =
   3.125 +			(sw->ar_pfs & AR_PFS_PEC_MASK) >> AR_PFS_PEC_SHIFT;
   3.126 +	} else if (unw_unwind_to_user(&info) < 0) {
   3.127 +		/* warn: should panic? */
   3.128 +		gdprintk(XENLOG_ERR, "vcpu=%d unw_unwind_to_user() failed.\n",
   3.129 +			 v->vcpu_id);
   3.130 +		show_stack(v, NULL);
   3.131 +
   3.132 +		/* can't return error */
   3.133 +		c.nat->regs.ar.lc = 0;
   3.134 +		c.nat->regs.ar.ec = 0;
   3.135 +	} else {
   3.136 +		unw_get_ar(&info, UNW_AR_LC, &c.nat->regs.ar.lc);
   3.137 +		unw_get_ar(&info, UNW_AR_EC, &c.nat->regs.ar.ec);
   3.138 +	}
   3.139  	c.nat->regs.ar.csd = uregs->ar_csd;
   3.140  	c.nat->regs.ar.ssd = uregs->ar_ssd;
   3.141  
   3.142 @@ -666,7 +755,11 @@ void arch_get_info_guest(struct vcpu *v,
   3.143  	c.nat->regs.pr = uregs->pr;
   3.144  	c.nat->regs.b[0] = uregs->b0;
   3.145  	rbs_size = uregs->loadrs >> 16;
   3.146 -	c.nat->regs.ar.bsp = uregs->ar_bspstore + rbs_size;
   3.147 +	num_regs = ia64_rse_num_regs(rbs_bottom,
   3.148 +			(unsigned long*)((char*)rbs_bottom + rbs_size));
   3.149 +	c.nat->regs.ar.bsp = (unsigned long)ia64_rse_skip_regs(
   3.150 +		(unsigned long*)c.nat->regs.ar.bspstore, num_regs);
   3.151 +	BUG_ON(num_regs > num_phys_stacked);
   3.152  
   3.153  	c.nat->regs.r[1] = uregs->r1;
   3.154  	c.nat->regs.r[12] = uregs->r12;
   3.155 @@ -696,6 +789,11 @@ void arch_get_info_guest(struct vcpu *v,
   3.156  
   3.157  	c.nat->regs.ar.ccv = uregs->ar_ccv;
   3.158  
   3.159 +	COPY_FPREG(&c.nat->regs.f[2], &sw->f2);
   3.160 +	COPY_FPREG(&c.nat->regs.f[3], &sw->f3);
   3.161 +	COPY_FPREG(&c.nat->regs.f[4], &sw->f4);
   3.162 +	COPY_FPREG(&c.nat->regs.f[5], &sw->f5);
   3.163 +
   3.164  	COPY_FPREG(&c.nat->regs.f[6], &uregs->f6);
   3.165  	COPY_FPREG(&c.nat->regs.f[7], &uregs->f7);
   3.166  	COPY_FPREG(&c.nat->regs.f[8], &uregs->f8);
   3.167 @@ -703,24 +801,155 @@ void arch_get_info_guest(struct vcpu *v,
   3.168  	COPY_FPREG(&c.nat->regs.f[10], &uregs->f10);
   3.169  	COPY_FPREG(&c.nat->regs.f[11], &uregs->f11);
   3.170  
   3.171 -	c.nat->regs.r[4] = uregs->r4;
   3.172 -	c.nat->regs.r[5] = uregs->r5;
   3.173 -	c.nat->regs.r[6] = uregs->r6;
   3.174 -	c.nat->regs.r[7] = uregs->r7;
   3.175 +	COPY_FPREG(&c.nat->regs.f[12], &sw->f12);
   3.176 +	COPY_FPREG(&c.nat->regs.f[13], &sw->f13);
   3.177 +	COPY_FPREG(&c.nat->regs.f[14], &sw->f14);
   3.178 +	COPY_FPREG(&c.nat->regs.f[15], &sw->f15);
   3.179 +	COPY_FPREG(&c.nat->regs.f[16], &sw->f16);
   3.180 +	COPY_FPREG(&c.nat->regs.f[17], &sw->f17);
   3.181 +	COPY_FPREG(&c.nat->regs.f[18], &sw->f18);
   3.182 +	COPY_FPREG(&c.nat->regs.f[19], &sw->f19);
   3.183 +	COPY_FPREG(&c.nat->regs.f[20], &sw->f20);
   3.184 +	COPY_FPREG(&c.nat->regs.f[21], &sw->f21);
   3.185 +	COPY_FPREG(&c.nat->regs.f[22], &sw->f22);
   3.186 +	COPY_FPREG(&c.nat->regs.f[23], &sw->f23);
   3.187 +	COPY_FPREG(&c.nat->regs.f[24], &sw->f24);
   3.188 +	COPY_FPREG(&c.nat->regs.f[25], &sw->f25);
   3.189 +	COPY_FPREG(&c.nat->regs.f[26], &sw->f26);
   3.190 +	COPY_FPREG(&c.nat->regs.f[27], &sw->f27);
   3.191 +	COPY_FPREG(&c.nat->regs.f[28], &sw->f28);
   3.192 +	COPY_FPREG(&c.nat->regs.f[29], &sw->f29);
   3.193 +	COPY_FPREG(&c.nat->regs.f[30], &sw->f30);
   3.194 +	COPY_FPREG(&c.nat->regs.f[31], &sw->f31);
   3.195  
   3.196 -	/* FIXME: to be reordered.  */
   3.197 -	c.nat->regs.nats = uregs->eml_unat;
   3.198 +	for (i = 0; i < 96; i++)
   3.199 +		COPY_FPREG(&c.nat->regs.f[i + 32], &v->arch._thread.fph[i]);
   3.200 +
   3.201 +#define NATS_UPDATE(reg)						\
   3.202 +	nats_update(&c.nat->regs.nats, (reg),				\
   3.203 +		    !!(uregs->eml_unat &				\
   3.204 +		       (1UL << ia64_unat_pos(&uregs->r ## reg))))
   3.205 +
   3.206 +	// corresponding bit in ar.unat is determined by
   3.207 +	// (&uregs->rN){8:3}.
   3.208 +	// r8: the lowest gr member of struct cpu_user_regs.
   3.209 +	// r7: the highest gr member of struct cpu_user_regs.
   3.210 +	BUILD_BUG_ON(offsetof(struct cpu_user_regs, r7) -
   3.211 +		     offsetof(struct cpu_user_regs, r8) >
   3.212 +		     64 * sizeof(unsigned long));
   3.213 +
   3.214 +	NATS_UPDATE(1);
   3.215 +	NATS_UPDATE(2);
   3.216 +	NATS_UPDATE(3);
   3.217 +
   3.218 +	NATS_UPDATE(8);
   3.219 +	NATS_UPDATE(9);
   3.220 +	NATS_UPDATE(10);
   3.221 +	NATS_UPDATE(11);
   3.222 +	NATS_UPDATE(12);
   3.223 +	NATS_UPDATE(13);
   3.224 +	NATS_UPDATE(14);
   3.225 +	NATS_UPDATE(15);
   3.226 +	NATS_UPDATE(16);
   3.227 +	NATS_UPDATE(17);
   3.228 +	NATS_UPDATE(18);
   3.229 +	NATS_UPDATE(19);
   3.230 +	NATS_UPDATE(20);
   3.231 +	NATS_UPDATE(21);
   3.232 +	NATS_UPDATE(22);
   3.233 +	NATS_UPDATE(23);
   3.234 +	NATS_UPDATE(24);
   3.235 +	NATS_UPDATE(25);
   3.236 +	NATS_UPDATE(26);
   3.237 +	NATS_UPDATE(27);
   3.238 +	NATS_UPDATE(28);
   3.239 +	NATS_UPDATE(29);
   3.240 +	NATS_UPDATE(30);
   3.241 +	NATS_UPDATE(31);
   3.242 +	
   3.243 +	if (!is_hvm) {
   3.244 +		c.nat->regs.r[4] = uregs->r4;
   3.245 +		c.nat->regs.r[5] = uregs->r5;
   3.246 +		c.nat->regs.r[6] = uregs->r6;
   3.247 +		c.nat->regs.r[7] = uregs->r7;
   3.248 +
   3.249 +		NATS_UPDATE(4);
   3.250 +		NATS_UPDATE(5);
   3.251 +		NATS_UPDATE(6);
   3.252 +		NATS_UPDATE(7);
   3.253 +#undef NATS_UPDATE
   3.254 +	} else {
   3.255 +		/*
   3.256 +		 * for VTi domain, r[4-7] are saved sometimes both in
   3.257 +		 * uregs->r[4-7] and memory stack or only in memory stack.
   3.258 +		 * So it is ok to get them from memory stack.
   3.259 +		 */
   3.260 +		c.nat->regs.nats = uregs->eml_unat;
   3.261 +
   3.262 +		if (vcpu_has_not_run(v)) {
   3.263 +			c.nat->regs.r[4] = sw->r4;
   3.264 +			c.nat->regs.r[5] = sw->r5;
   3.265 +			c.nat->regs.r[6] = sw->r6;
   3.266 +			c.nat->regs.r[7] = sw->r7;
   3.267 +
   3.268 +			nats_update(&c.nat->regs.nats, 4,
   3.269 +				    !!(sw->ar_unat &
   3.270 +				       (1UL << ia64_unat_pos(&sw->r4))));
   3.271 +			nats_update(&c.nat->regs.nats, 5,
   3.272 +				    !!(sw->ar_unat &
   3.273 +				       (1UL << ia64_unat_pos(&sw->r5))));
   3.274 +			nats_update(&c.nat->regs.nats, 6,
   3.275 +				    !!(sw->ar_unat &
   3.276 +				       (1UL << ia64_unat_pos(&sw->r6))));
   3.277 +			nats_update(&c.nat->regs.nats, 7,
   3.278 +				    !!(sw->ar_unat &
   3.279 +				       (1UL << ia64_unat_pos(&sw->r7))));
   3.280 +		} else {
   3.281 +			char nat;
   3.282 +
   3.283 +			unw_get_gr(&info, 4, &c.nat->regs.r[4], &nat);
   3.284 +			nats_update(&c.nat->regs.nats, 4, nat);
   3.285 +			unw_get_gr(&info, 5, &c.nat->regs.r[5], &nat);
   3.286 +			nats_update(&c.nat->regs.nats, 5, nat);
   3.287 +			unw_get_gr(&info, 6, &c.nat->regs.r[6], &nat);
   3.288 +			nats_update(&c.nat->regs.nats, 6, nat);
   3.289 +			unw_get_gr(&info, 7, &c.nat->regs.r[7], &nat);
   3.290 +			nats_update(&c.nat->regs.nats, 7, nat);
   3.291 +		}
   3.292 +	}
   3.293  
   3.294  	c.nat->regs.rbs_voff = (IA64_RBS_OFFSET / 8) % 64;
   3.295 -	if (rbs_size < sizeof (c.nat->regs.rbs))
   3.296 -		memcpy(c.nat->regs.rbs, (char *)v + IA64_RBS_OFFSET, rbs_size);
   3.297 +	if (unlikely(rbs_size > sizeof(c.nat->regs.rbs)))
   3.298 +		gdprintk(XENLOG_INFO,
   3.299 +			 "rbs_size is too large 0x%x > 0x%lx\n",
   3.300 +			 rbs_size, sizeof(c.nat->regs.rbs));
   3.301 +	else
   3.302 +		memcpy(c.nat->regs.rbs, rbs_bottom, rbs_size);
   3.303 +
   3.304 +	rbs_top = (unsigned long*)((char *)rbs_bottom + rbs_size) - 1;
   3.305 +	rbs_rnat_addr = ia64_rse_rnat_addr(rbs_top);
   3.306 +	if ((unsigned long)rbs_rnat_addr >= sw->ar_bspstore)
   3.307 +		rbs_rnat_addr = &sw->ar_rnat;
   3.308 +
   3.309 +	top_slot = ia64_rse_slot_num(rbs_top);
   3.310 +
   3.311 +	c.nat->regs.rbs_rnat = (*rbs_rnat_addr) & ((1UL << top_slot) - 1);
   3.312 +	if (ia64_rse_rnat_addr(rbs_bottom) == ia64_rse_rnat_addr(rbs_top)) {
   3.313 +		unsigned int bottom_slot = ia64_rse_slot_num(rbs_bottom);
   3.314 +		c.nat->regs.rbs_rnat &= ~((1UL << bottom_slot) - 1);
   3.315 +	}
   3.316  
   3.317   	c.nat->privregs_pfn = get_gpfn_from_mfn
   3.318  		(virt_to_maddr(v->arch.privregs) >> PAGE_SHIFT);
   3.319  
   3.320  	for (i = 0; i < IA64_NUM_DBG_REGS; i++) {
   3.321 -		vcpu_get_dbr(v, i, &c.nat->regs.dbr[i]);
   3.322 -		vcpu_get_ibr(v, i, &c.nat->regs.ibr[i]);
   3.323 +		if (VMX_DOMAIN(v)) {
   3.324 +			vmx_vcpu_get_dbr(v, i, &c.nat->regs.dbr[i]);
   3.325 +			vmx_vcpu_get_ibr(v, i, &c.nat->regs.ibr[i]);
   3.326 +		} else {
   3.327 +			vcpu_get_dbr(v, i, &c.nat->regs.dbr[i]);
   3.328 +			vcpu_get_ibr(v, i, &c.nat->regs.ibr[i]);
   3.329 +		}
   3.330  	}
   3.331  
   3.332  	for (i = 0; i < 8; i++)
   3.333 @@ -762,7 +991,12 @@ void arch_get_info_guest(struct vcpu *v,
   3.334  	vcpu_get_ifa(v, &c.nat->regs.cr.ifa);
   3.335  	vcpu_get_itir(v, &c.nat->regs.cr.itir);
   3.336  	vcpu_get_iha(v, &c.nat->regs.cr.iha);
   3.337 -	vcpu_get_ivr(v, &c.nat->regs.cr.ivr);
   3.338 +
   3.339 +	//XXX change irr[] and arch.insvc[]
   3.340 +	if (v->domain->arch.is_vti)
   3.341 +		/* c.nat->regs.cr.ivr = vmx_vcpu_get_ivr(v)*/;//XXXnot SMP-safe
   3.342 +	else
   3.343 +		vcpu_get_ivr (v, &c.nat->regs.cr.ivr);
   3.344  	vcpu_get_iim(v, &c.nat->regs.cr.iim);
   3.345  
   3.346  	vcpu_get_tpr(v, &c.nat->regs.cr.tpr);
   3.347 @@ -770,18 +1004,172 @@ void arch_get_info_guest(struct vcpu *v,
   3.348  	vcpu_get_irr1(v, &c.nat->regs.cr.irr[1]);
   3.349  	vcpu_get_irr2(v, &c.nat->regs.cr.irr[2]);
   3.350  	vcpu_get_irr3(v, &c.nat->regs.cr.irr[3]);
   3.351 -	vcpu_get_itv(v, &c.nat->regs.cr.itv);
   3.352 +	vcpu_get_itv(v, &c.nat->regs.cr.itv);//XXX vlsapic
   3.353  	vcpu_get_pmv(v, &c.nat->regs.cr.pmv);
   3.354  	vcpu_get_cmcv(v, &c.nat->regs.cr.cmcv);
   3.355 +
   3.356 +	if (is_hvm)
   3.357 +		vmx_arch_get_info_guest(v, c);
   3.358 +}
   3.359 +
   3.360 +#if 0
   3.361 +// for debug
   3.362 +static void
   3.363 +__rbs_print(const char* func, int line, const char* name,
   3.364 +	    const unsigned long* rbs, unsigned int rbs_size)
   3.365 +{
   3.366 +	unsigned int i;
   3.367 +	printk("%s:%d %s rbs %p\n", func, line, name, rbs);
   3.368 +	printk("   rbs_size 0x%016x no 0x%lx\n",
   3.369 +	       rbs_size, rbs_size / sizeof(unsigned long));
   3.370 +
   3.371 +	for (i = 0; i < rbs_size / sizeof(unsigned long); i++) {
   3.372 +		const char* zero_or_n = "0x";
   3.373 +		if (ia64_rse_is_rnat_slot((unsigned long*)&rbs[i]))
   3.374 +			zero_or_n = "Nx";
   3.375 +
   3.376 +		if ((i % 3) == 0)
   3.377 +			printk("0x%02x:", i);
   3.378 +		printk(" %s%016lx", zero_or_n, rbs[i]);
   3.379 +		if ((i % 3) == 2)
   3.380 +			printk("\n");
   3.381 +	}
   3.382 +	printk("\n");		
   3.383 +}
   3.384 +
   3.385 +#define rbs_print(rbs, rbs_size)				\
   3.386 +	__rbs_print(__func__, __LINE__, (#rbs), (rbs), (rbs_size))
   3.387 +#endif
   3.388 +
   3.389 +static int
   3.390 +copy_rbs(struct vcpu* v, unsigned long* dst_rbs_size,
   3.391 +	 const unsigned long* rbs, unsigned long rbs_size,
   3.392 +	 unsigned long src_rnat, unsigned long rbs_voff)
   3.393 +{
   3.394 +	int rc = -EINVAL;
   3.395 +	struct page_info* page;
   3.396 +	unsigned char* vaddr;
   3.397 +	unsigned long* src_bsp;
   3.398 +	unsigned long* src_bspstore;
   3.399 +
   3.400 +	struct switch_stack* sw = vcpu_to_switch_stack(v);
   3.401 +	unsigned long num_regs;
   3.402 +	unsigned long* dst_bsp;
   3.403 +	unsigned long* dst_bspstore;
   3.404 +	unsigned long* dst_rnat;
   3.405 +	unsigned long dst_rnat_tmp;
   3.406 +	unsigned long dst_rnat_mask;
   3.407 +	unsigned long flags;
   3.408 +	extern void ia64_copy_rbs(unsigned long* dst_bspstore,
   3.409 +				  unsigned long* dst_rbs_size,
   3.410 +				  unsigned long* dst_rnat_p,
   3.411 +				  unsigned long* src_bsp,
   3.412 +				  unsigned long src_rbs_size,
   3.413 +				  unsigned long src_rnat);
   3.414 +
   3.415 +	dst_bspstore = vcpu_to_rbs_bottom(v);
   3.416 +	*dst_rbs_size = rbs_size;
   3.417 +	if (rbs_size == 0)
   3.418 +		return 0;
   3.419 +	
   3.420 +	// rbs offset depends on sizeof(struct vcpu) so that
   3.421 +	// it's too unstable for hypercall ABI.
   3.422 +	// we need to take rbs offset into acount.
   3.423 +	//memcpy(dst_bspstore, c.nat->regs.rbs, rbs_size);
   3.424 +
   3.425 +	// It is assumed that rbs_size is small enough compared
   3.426 +	// to KERNEL_STACK_SIZE.
   3.427 +	page = alloc_domheap_pages(NULL, KERNEL_STACK_SIZE_ORDER, 0);
   3.428 +	if (page == NULL)
   3.429 +		return -ENOMEM;
   3.430 +	vaddr = page_to_virt(page);
   3.431 +
   3.432 +	src_bspstore = (unsigned long*)(vaddr + rbs_voff * 8);
   3.433 +	src_bsp = (unsigned long*)((unsigned char*)src_bspstore + rbs_size);
   3.434 +	if ((unsigned long)src_bsp >= (unsigned long)vaddr + PAGE_SIZE)
   3.435 +		goto out;
   3.436 +	memcpy(src_bspstore, rbs, rbs_size);
   3.437 +	
   3.438 +	num_regs = ia64_rse_num_regs(src_bspstore, src_bsp);
   3.439 +	dst_bsp = ia64_rse_skip_regs(dst_bspstore, num_regs);
   3.440 +	*dst_rbs_size = (unsigned long)dst_bsp - (unsigned long)dst_bspstore;
   3.441 +
   3.442 +	// rough check.
   3.443 +	if (((unsigned long)dst_bsp & ~PAGE_MASK) > KERNEL_STACK_SIZE / 2)
   3.444 +		goto out;
   3.445 +
   3.446 +	//XXX TODO
   3.447 +	// ia64_copy_rbs() uses real cpu's stack register.
   3.448 +	// So it may fault with an Illigal Operation fault resulting
   3.449 +	// in panic if rbs_size is too large to load compared to
   3.450 +	// the number of physical stacked registers, RSE.N_STACKED_PHYS,
   3.451 +	// which is cpu implementatin specific.
   3.452 +	// See SDM vol. 2  Register Stack Engine 6, especially 6.5.5.
   3.453 +	//
   3.454 +	// For safe operation and cpu model independency, 
   3.455 +	// we need to copy them by hand without loadrs and flushrs
   3.456 +	// However even if we implement that, similar issue still occurs
   3.457 +	// when running guest. CPU context restore routine issues loadrs
   3.458 +	// resulting in Illegal Operation fault. For such a case,
   3.459 +	// we need to emulate RSE store.
   3.460 +	// So it would be better to implement only RSE store emulation
   3.461 +	// and copy stacked registers directly into guest RBS.
   3.462 +	if (num_regs > num_phys_stacked) {
   3.463 +		rc = -ENOSYS;
   3.464 +		gdprintk(XENLOG_WARNING,
   3.465 +			 "%s:%d domain %d: can't load stacked registres\n"
   3.466 +			 "requested size 0x%lx => 0x%lx, num regs %ld"
   3.467 +			 "RSE.N_STACKED_PHYS %ld\n",
   3.468 +			 __func__, __LINE__, v->domain->domain_id, 
   3.469 +			 rbs_size, *dst_rbs_size, num_regs,
   3.470 +			 num_phys_stacked);
   3.471 +		goto out;
   3.472 +	}
   3.473 +
   3.474 +	// we mask interrupts to avoid using register backing store.
   3.475 +	local_irq_save(flags);
   3.476 +	ia64_copy_rbs(dst_bspstore, dst_rbs_size, &dst_rnat_tmp,
   3.477 +		      src_bsp, rbs_size, src_rnat);
   3.478 +	local_irq_restore(flags);
   3.479 +
   3.480 +	dst_rnat_mask = (1UL << ia64_rse_slot_num(dst_bsp)) - 1;
   3.481 +	dst_rnat = ia64_rse_rnat_addr(dst_bsp);
   3.482 +	if ((unsigned long)dst_rnat > sw->ar_bspstore)
   3.483 +		dst_rnat = &sw->ar_rnat;
   3.484 +	// if ia64_rse_rnat_addr(dst_bsp) ==
   3.485 +	// ia64_rse_rnat_addr(vcpu_to_rbs_bottom(v)), the lsb bit of rnat
   3.486 +	// is just ignored. so we don't have to mask it out.
   3.487 +	*dst_rnat =
   3.488 +		(*dst_rnat & ~dst_rnat_mask) | (dst_rnat_tmp & dst_rnat_mask);
   3.489 +	
   3.490 +	rc = 0;
   3.491 +out:
   3.492 +	free_domheap_pages(page, KERNEL_STACK_SIZE_ORDER);
   3.493 +	return rc;
   3.494 +}
   3.495 +
   3.496 +static void
   3.497 +unat_update(unsigned long *unat_eml, unsigned long *spill_addr, char nat)
   3.498 +{
   3.499 +	unsigned int pos = ia64_unat_pos(spill_addr);
   3.500 +	if (nat)
   3.501 +		*unat_eml |= (1UL << pos);
   3.502 +	else
   3.503 +		*unat_eml &= ~(1UL << pos);
   3.504  }
   3.505  
   3.506  int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
   3.507  {
   3.508  	struct cpu_user_regs *uregs = vcpu_regs(v);
   3.509  	struct domain *d = v->domain;
   3.510 +	struct switch_stack *sw = vcpu_to_switch_stack(v);
   3.511  	int was_initialised = v->is_initialised;
   3.512 +	struct unw_frame_info info;
   3.513  	unsigned int rbs_size;
   3.514 -	int rc, i;
   3.515 +	unsigned int num_regs;
   3.516 +	unsigned long * const rbs_bottom = vcpu_to_rbs_bottom(v);
   3.517 +	int rc = 0;
   3.518 +	int i;
   3.519  
   3.520  	/* Finish vcpu initialization.  */
   3.521  	if (!was_initialised) {
   3.522 @@ -806,6 +1194,26 @@ int arch_set_info_guest(struct vcpu *v, 
   3.523  	uregs->b6 = c.nat->regs.b[6];
   3.524  	uregs->b7 = c.nat->regs.b[7];
   3.525  	
   3.526 +	memset(&info, 0, sizeof(info));
   3.527 +	unw_init_from_blocked_task(&info, v);
   3.528 +	if (vcpu_has_not_run(v)) {
   3.529 +		sw->ar_lc = c.nat->regs.ar.lc;
   3.530 +		sw->ar_pfs =
   3.531 +			(sw->ar_pfs & ~AR_PFS_PEC_MASK) |
   3.532 +			((c.nat->regs.ar.ec << AR_PFS_PEC_SHIFT) &
   3.533 +			 AR_PFS_PEC_MASK);
   3.534 +	} else if (unw_unwind_to_user(&info) < 0) {
   3.535 +		/* warn: should panic? */
   3.536 +		gdprintk(XENLOG_ERR,
   3.537 +			 "vcpu=%d unw_unwind_to_user() failed.\n",
   3.538 +			 v->vcpu_id);
   3.539 +		show_stack(v, NULL);
   3.540 +
   3.541 +		//return -ENOSYS;
   3.542 +	} else {
   3.543 +		unw_set_ar(&info, UNW_AR_LC, c.nat->regs.ar.lc);
   3.544 +		unw_set_ar(&info, UNW_AR_EC, c.nat->regs.ar.ec);
   3.545 +	}
   3.546  	uregs->ar_csd = c.nat->regs.ar.csd;
   3.547  	uregs->ar_ssd = c.nat->regs.ar.ssd;
   3.548  	
   3.549 @@ -820,7 +1228,7 @@ int arch_set_info_guest(struct vcpu *v, 
   3.550  		vmx_vcpu_set_psr(v, c.nat->regs.psr);
   3.551  	uregs->cr_iip = c.nat->regs.ip;
   3.552  	uregs->cr_ifs = c.nat->regs.cfm;
   3.553 -	
   3.554 +
   3.555  	uregs->ar_unat = c.nat->regs.ar.unat;
   3.556  	uregs->ar_pfs = c.nat->regs.ar.pfs;
   3.557  	uregs->ar_rsc = c.nat->regs.ar.rsc;
   3.558 @@ -829,12 +1237,46 @@ int arch_set_info_guest(struct vcpu *v, 
   3.559  	
   3.560  	uregs->pr = c.nat->regs.pr;
   3.561  	uregs->b0 = c.nat->regs.b[0];
   3.562 -	rbs_size = c.nat->regs.ar.bsp - c.nat->regs.ar.bspstore;
   3.563 +	if (((IA64_RBS_OFFSET / 8) % 64) != c.nat->regs.rbs_voff)
   3.564 +		gdprintk(XENLOG_INFO,
   3.565 +			 "rbs stack offset is different! xen 0x%x given 0x%x",
   3.566 +			 (IA64_RBS_OFFSET / 8) % 64, c.nat->regs.rbs_voff);
   3.567 +	num_regs = ia64_rse_num_regs((unsigned long*)c.nat->regs.ar.bspstore,
   3.568 +				     (unsigned long*)c.nat->regs.ar.bsp);
   3.569 +	rbs_size = (unsigned long)ia64_rse_skip_regs(rbs_bottom, num_regs) -
   3.570 +		(unsigned long)rbs_bottom;
   3.571 +	if (rbs_size > sizeof (c.nat->regs.rbs)) {
   3.572 +		gdprintk(XENLOG_INFO,
   3.573 +			 "rbs size is too large %x > %lx\n",
   3.574 +			 rbs_size, sizeof (c.nat->regs.rbs));
   3.575 +		return -EINVAL;
   3.576 +	}
   3.577 +	
   3.578  	/* Protection against crazy user code.  */
   3.579  	if (!was_initialised)
   3.580 -		uregs->loadrs = (rbs_size) << 16;
   3.581 -	if (rbs_size == (uregs->loadrs >> 16))
   3.582 -		memcpy((char *)v + IA64_RBS_OFFSET, c.nat->regs.rbs, rbs_size);
   3.583 +		uregs->loadrs = (rbs_size << 16);
   3.584 +	if (rbs_size == (uregs->loadrs >> 16)) {
   3.585 +		unsigned long dst_rbs_size = 0;
   3.586 +		if (vcpu_has_not_run(v))
   3.587 +			sw->ar_bspstore = (unsigned long)rbs_bottom;
   3.588 +		
   3.589 +		rc = copy_rbs(v, &dst_rbs_size,
   3.590 +			      c.nat->regs.rbs, rbs_size,
   3.591 +			      c.nat->regs.rbs_rnat,
   3.592 +			      c.nat->regs.rbs_voff);
   3.593 +		if (rc < 0)
   3.594 +			return rc;
   3.595 +
   3.596 +		/* In case of newly created vcpu, ar_bspstore points to
   3.597 +		 * the bottom of register stack. Move it up.
   3.598 +		 * See also init_switch_stack().
   3.599 +		 */
   3.600 +		if (vcpu_has_not_run(v)) {
   3.601 +			uregs->loadrs = (dst_rbs_size << 16);
   3.602 +			sw->ar_bspstore = (unsigned long)((char*)rbs_bottom +
   3.603 +							  dst_rbs_size);
   3.604 +		}
   3.605 +	}
   3.606  
   3.607  	uregs->r1 = c.nat->regs.r[1];
   3.608  	uregs->r12 = c.nat->regs.r[12];
   3.609 @@ -863,22 +1305,117 @@ int arch_set_info_guest(struct vcpu *v, 
   3.610  	uregs->r31 = c.nat->regs.r[31];
   3.611  	
   3.612  	uregs->ar_ccv = c.nat->regs.ar.ccv;
   3.613 -	
   3.614 +
   3.615 +	COPY_FPREG(&sw->f2, &c.nat->regs.f[2]);
   3.616 +	COPY_FPREG(&sw->f3, &c.nat->regs.f[3]);
   3.617 +	COPY_FPREG(&sw->f4, &c.nat->regs.f[4]);
   3.618 +	COPY_FPREG(&sw->f5, &c.nat->regs.f[5]);
   3.619 +
   3.620  	COPY_FPREG(&uregs->f6, &c.nat->regs.f[6]);
   3.621  	COPY_FPREG(&uregs->f7, &c.nat->regs.f[7]);
   3.622  	COPY_FPREG(&uregs->f8, &c.nat->regs.f[8]);
   3.623  	COPY_FPREG(&uregs->f9, &c.nat->regs.f[9]);
   3.624  	COPY_FPREG(&uregs->f10, &c.nat->regs.f[10]);
   3.625  	COPY_FPREG(&uregs->f11, &c.nat->regs.f[11]);
   3.626 +
   3.627 +	COPY_FPREG(&sw->f12, &c.nat->regs.f[12]);
   3.628 +	COPY_FPREG(&sw->f13, &c.nat->regs.f[13]);
   3.629 +	COPY_FPREG(&sw->f14, &c.nat->regs.f[14]);
   3.630 +	COPY_FPREG(&sw->f15, &c.nat->regs.f[15]);
   3.631 +	COPY_FPREG(&sw->f16, &c.nat->regs.f[16]);
   3.632 +	COPY_FPREG(&sw->f17, &c.nat->regs.f[17]);
   3.633 +	COPY_FPREG(&sw->f18, &c.nat->regs.f[18]);
   3.634 +	COPY_FPREG(&sw->f19, &c.nat->regs.f[19]);
   3.635 +	COPY_FPREG(&sw->f20, &c.nat->regs.f[20]);
   3.636 +	COPY_FPREG(&sw->f21, &c.nat->regs.f[21]);
   3.637 +	COPY_FPREG(&sw->f22, &c.nat->regs.f[22]);
   3.638 +	COPY_FPREG(&sw->f23, &c.nat->regs.f[23]);
   3.639 +	COPY_FPREG(&sw->f24, &c.nat->regs.f[24]);
   3.640 +	COPY_FPREG(&sw->f25, &c.nat->regs.f[25]);
   3.641 +	COPY_FPREG(&sw->f26, &c.nat->regs.f[26]);
   3.642 +	COPY_FPREG(&sw->f27, &c.nat->regs.f[27]);
   3.643 +	COPY_FPREG(&sw->f28, &c.nat->regs.f[28]);
   3.644 +	COPY_FPREG(&sw->f29, &c.nat->regs.f[29]);
   3.645 +	COPY_FPREG(&sw->f30, &c.nat->regs.f[30]);
   3.646 +	COPY_FPREG(&sw->f31, &c.nat->regs.f[31]);
   3.647 +
   3.648 +	for (i = 0; i < 96; i++)
   3.649 +		COPY_FPREG(&v->arch._thread.fph[i], &c.nat->regs.f[i + 32]);
   3.650 +
   3.651 +
   3.652 +#define UNAT_UPDATE(reg)					\
   3.653 +	unat_update(&uregs->eml_unat, &uregs->r ## reg,		\
   3.654 +		    !!(c.nat->regs.nats & (1UL << (reg))));
   3.655 +
   3.656 +	uregs->eml_unat = 0;
   3.657 +	UNAT_UPDATE(1);
   3.658 +	UNAT_UPDATE(2);
   3.659 +	UNAT_UPDATE(3);
   3.660 +
   3.661 +	UNAT_UPDATE(8);
   3.662 +	UNAT_UPDATE(9);
   3.663 +	UNAT_UPDATE(10);
   3.664 +	UNAT_UPDATE(11);
   3.665 +	UNAT_UPDATE(12);
   3.666 +	UNAT_UPDATE(13);
   3.667 +	UNAT_UPDATE(14);
   3.668 +	UNAT_UPDATE(15);
   3.669 +	UNAT_UPDATE(16);
   3.670 +	UNAT_UPDATE(17);
   3.671 +	UNAT_UPDATE(18);
   3.672 +	UNAT_UPDATE(19);
   3.673 +	UNAT_UPDATE(20);
   3.674 +	UNAT_UPDATE(21);
   3.675 +	UNAT_UPDATE(22);
   3.676 +	UNAT_UPDATE(23);
   3.677 +	UNAT_UPDATE(24);
   3.678 +	UNAT_UPDATE(25);
   3.679 +	UNAT_UPDATE(26);
   3.680 +	UNAT_UPDATE(27);
   3.681 +	UNAT_UPDATE(28);
   3.682 +	UNAT_UPDATE(29);
   3.683 +	UNAT_UPDATE(30);
   3.684 +	UNAT_UPDATE(31);
   3.685  	
   3.686 +	/*
   3.687 +	 * r4-r7 is saved sometimes both in pt_regs->r[4-7] and memory stack or
   3.688 +	 * only in memory stack.
   3.689 +	 * for both cases, both memory stack and pt_regs->r[4-7] are updated.
   3.690 +	 */
   3.691  	uregs->r4 = c.nat->regs.r[4];
   3.692  	uregs->r5 = c.nat->regs.r[5];
   3.693  	uregs->r6 = c.nat->regs.r[6];
   3.694  	uregs->r7 = c.nat->regs.r[7];
   3.695 -	
   3.696 -	/* FIXME: to be reordered and restored.  */
   3.697 -	/* uregs->eml_unat = c.nat->regs.nat; */
   3.698 -	uregs->eml_unat = 0;
   3.699 +
   3.700 +	UNAT_UPDATE(4);
   3.701 +	UNAT_UPDATE(5);
   3.702 +	UNAT_UPDATE(6);
   3.703 +	UNAT_UPDATE(7);
   3.704 +#undef UNAT_UPDATE
   3.705 +	if (vcpu_has_not_run(v)) {
   3.706 +		sw->r4 = c.nat->regs.r[4];
   3.707 +		sw->r5 = c.nat->regs.r[5];
   3.708 +		sw->r6 = c.nat->regs.r[6];
   3.709 +		sw->r7 = c.nat->regs.r[7];
   3.710 +
   3.711 +		unat_update(&sw->ar_unat, &sw->r4,
   3.712 +			    !!(c.nat->regs.nats & (1UL << 4)));
   3.713 +		unat_update(&sw->ar_unat, &sw->r5,
   3.714 +			    !!(c.nat->regs.nats & (1UL << 5)));
   3.715 +		unat_update(&sw->ar_unat, &sw->r6,
   3.716 +			    !!(c.nat->regs.nats & (1UL << 6)));
   3.717 +		unat_update(&sw->ar_unat, &sw->r7,
   3.718 +			    !!(c.nat->regs.nats & (1UL << 7)));
   3.719 +	} else {
   3.720 +		unw_set_gr(&info, 4, c.nat->regs.r[4],
   3.721 +			   !!(c.nat->regs.nats & (1UL << 4)));
   3.722 +		unw_set_gr(&info, 5, c.nat->regs.r[5],
   3.723 +			   !!(c.nat->regs.nats & (1UL << 5)));
   3.724 +		unw_set_gr(&info, 6, c.nat->regs.r[6],
   3.725 +			   !!(c.nat->regs.nats & (1UL << 6)));
   3.726 +		unw_set_gr(&info, 7, c.nat->regs.r[7],
   3.727 +			   !!(c.nat->regs.nats & (1UL << 7)));
   3.728 +	}
   3.729  	
   3.730   	if (!d->arch.is_vti) {
   3.731   		/* domain runs at PL2/3 */
   3.732 @@ -888,8 +1425,31 @@ int arch_set_info_guest(struct vcpu *v, 
   3.733   	}
   3.734  
   3.735  	for (i = 0; i < IA64_NUM_DBG_REGS; i++) {
   3.736 -		vcpu_set_dbr(v, i, c.nat->regs.dbr[i]);
   3.737 -		vcpu_set_ibr(v, i, c.nat->regs.ibr[i]);
   3.738 +		if (d->arch.is_vti) {
   3.739 +			vmx_vcpu_set_dbr(v, i, c.nat->regs.dbr[i]);
   3.740 +			vmx_vcpu_set_ibr(v, i, c.nat->regs.ibr[i]);
   3.741 +		} else {
   3.742 +			vcpu_set_dbr(v, i, c.nat->regs.dbr[i]);
   3.743 +			vcpu_set_ibr(v, i, c.nat->regs.ibr[i]);
   3.744 +		}
   3.745 +	}
   3.746 +
   3.747 +	/* rr[] must be set before setting itrs[] dtrs[] */
   3.748 +	for (i = 0; i < 8; i++) {
   3.749 +		//XXX TODO integrity check.
   3.750 +		//    if invalid value is given, 
   3.751 +		//    vmx_load_all_rr() and load_region_regs()
   3.752 +		//    result in General exception, reserved register/field
   3.753 +		//    failt causing panicing xen.
   3.754 +		if (d->arch.is_vti) {
   3.755 +			//without VGCF_EXTRA_REGS check,
   3.756 +			//VTi domain doesn't boot.
   3.757 +			if (c.nat->flags & VGCF_EXTRA_REGS)
   3.758 +				vmx_vcpu_set_rr(v, (unsigned long)i << 61,
   3.759 +						c.nat->regs.rr[i]);
   3.760 +		} else
   3.761 +			vcpu_set_rr(v, (unsigned long)i << 61,
   3.762 +				    c.nat->regs.rr[i]);
   3.763  	}
   3.764  
   3.765  	if (c.nat->flags & VGCF_EXTRA_REGS) {
   3.766 @@ -898,25 +1458,38 @@ int arch_set_info_guest(struct vcpu *v, 
   3.767  		for (i = 0;
   3.768  		     (i < sizeof(tr->itrs) / sizeof(tr->itrs[0])) && i < NITRS;
   3.769  		     i++) {
   3.770 -			vcpu_set_itr(v, i, tr->itrs[i].pte,
   3.771 -			             tr->itrs[i].itir,
   3.772 -			             tr->itrs[i].vadr,
   3.773 -			             tr->itrs[i].rid);
   3.774 +			if (d->arch.is_vti)
   3.775 +				vmx_vcpu_itr_i(v, i, tr->itrs[i].pte,
   3.776 +					       tr->itrs[i].itir,
   3.777 +					       tr->itrs[i].vadr);
   3.778 +			else
   3.779 +				vcpu_set_itr(v, i, tr->itrs[i].pte,
   3.780 +					     tr->itrs[i].itir,
   3.781 +					     tr->itrs[i].vadr,
   3.782 +					     tr->itrs[i].rid);
   3.783  		}
   3.784  		for (i = 0;
   3.785  		     (i < sizeof(tr->dtrs) / sizeof(tr->dtrs[0])) && i < NDTRS;
   3.786  		     i++) {
   3.787 -			vcpu_set_dtr(v, i,
   3.788 -			             tr->dtrs[i].pte,
   3.789 -			             tr->dtrs[i].itir,
   3.790 -			             tr->dtrs[i].vadr,
   3.791 -			             tr->dtrs[i].rid);
   3.792 +			if (d->arch.is_vti)
   3.793 +				vmx_vcpu_itr_d(v, i, tr->dtrs[i].pte,
   3.794 +					       tr->dtrs[i].itir,
   3.795 +					       tr->dtrs[i].vadr);
   3.796 +			else
   3.797 +				vcpu_set_dtr(v, i,
   3.798 +					     tr->dtrs[i].pte,
   3.799 +					     tr->dtrs[i].itir,
   3.800 +					     tr->dtrs[i].vadr,
   3.801 +					     tr->dtrs[i].rid);
   3.802  		}
   3.803  		v->arch.event_callback_ip = c.nat->event_callback_ip;
   3.804  		vcpu_set_iva(v, c.nat->regs.cr.iva);
   3.805  	}
   3.806  
   3.807 -	return 0;
   3.808 +	if (d->arch.is_vti)
   3.809 +		rc = vmx_arch_set_info_guest(v, c);
   3.810 +
   3.811 +	return rc;
   3.812  }
   3.813  
   3.814  static void relinquish_memory(struct domain *d, struct list_head *list)
     4.1 --- a/xen/arch/ia64/xen/xenasm.S	Sun Oct 21 13:38:05 2007 -0600
     4.2 +++ b/xen/arch/ia64/xen/xenasm.S	Sun Oct 21 13:38:57 2007 -0600
     4.3 @@ -3,6 +3,10 @@
     4.4   *
     4.5   * Copyright (C) 2004 Hewlett-Packard Co
     4.6   *	Dan Magenheimer <dan.magenheimer@hp.com>
     4.7 + *
     4.8 + * Copyright (C) 2007 VA Linux Systems Japan K.K.
     4.9 + *      Isaku Yamahata <yamahata at valinux co jp>
    4.10 + *      ia64_copy_rbs()
    4.11   */
    4.12  
    4.13  #include <linux/config.h>
    4.14 @@ -357,3 +361,145 @@ stacked:
    4.15  	br.ret.sptk.few rp
    4.16  END(pal_emulator_static)
    4.17  
    4.18 +// void ia64_copy_rbs(unsigned long* dst_bspstore, unsigned long* dst_rbs_size,
    4.19 +//                    unsigned long* dst_rnat_p,
    4.20 +//                    unsigned long* src_bsp, unsigned long src_rbs_size,
    4.21 +//                    unsigned long src_rnat);
    4.22 +// Caller must mask interrupions.
    4.23 +// Caller must ensure that src_rbs_size isn't larger than the number
    4.24 +// of physical stacked registers. otherwise loadrs fault with Illegal
    4.25 +// Operation fault resulting in panic.
    4.26 +//
    4.27 +// r14 = r32 = dst_bspstore
    4.28 +// r15 = r33 = dst_rbs_size_p	
    4.29 +// r16 = r34 = dst_rnat_p
    4.30 +// r17 = r35 = src_bsp
    4.31 +// r18 = r36 = src_rbs_size
    4.32 +// r19 = r37 = src_rnat	
    4.33 +//
    4.34 +// r20 = saved ar.rsc
    4.35 +// r21 = saved ar.bspstore
    4.36 +//	
    4.37 +// r22 = saved_ar_rnat
    4.38 +// r23 = saved_ar_rp
    4.39 +// r24 = saved_ar_pfs	
    4.40 +//
    4.41 +// we save the value in this register and store it into [dst_rbs_size_p] and
    4.42 +// [dst_rnat_p] after rse opeation is done.
    4.43 +// r30 = return value of __ia64_copy_rbs to ia64_copy_to_rbs = dst_rbs_size
    4.44 +// r31 = return value of __ia64_copy_rbs to ia64_copy_to_rbs = dst_rnat
    4.45 +//
    4.46 +#define dst_bspstore		r14
    4.47 +#define dst_rbs_size_p		r15
    4.48 +#define dst_rnat_p		r16
    4.49 +#define src_bsp			r17
    4.50 +#define src_rbs_size		r18
    4.51 +#define src_rnat		r19
    4.52 +
    4.53 +#define saved_ar_rsc		r20
    4.54 +#define saved_ar_bspstore	r21
    4.55 +#define saved_ar_rnat		r22
    4.56 +#define saved_rp		r23
    4.57 +#define saved_ar_pfs		r24
    4.58 +
    4.59 +#define dst_rbs_size		r30
    4.60 +#define dst_rnat		r31
    4.61 +ENTRY(__ia64_copy_rbs)
    4.62 +	.prologue
    4.63 +	.fframe 0
    4.64 +
    4.65 +	// Here cfm.{sof, sol, sor, rrb}=0 
    4.66 +	//
    4.67 +	// flush current register stack to backing store
    4.68 +{
    4.69 +	flushrs	// must be first isns in group
    4.70 +	srlz.i
    4.71 +}
    4.72 +
    4.73 +	// switch to enforced lazy mode	
    4.74 +	mov saved_ar_rsc = ar.rsc
    4.75 +	;; 
    4.76 +	mov ar.rsc = 0
    4.77 +	;; 
    4.78 +
    4.79 +	.save ar.bspstore, saved_ar_bspstore
    4.80 +	mov saved_ar_bspstore = ar.bspstore
    4.81 +	.save ar.rnat, saved_ar_rnat
    4.82 +	mov saved_ar_rnat = ar.rnat
    4.83 +	;;
    4.84 +
    4.85 +	.body
    4.86 +	// load from src
    4.87 +	mov ar.bspstore = src_bsp
    4.88 +	;; 
    4.89 +	mov ar.rnat = src_rnat
    4.90 +	shl src_rbs_size = src_rbs_size,16
    4.91 +	;; 
    4.92 +	mov ar.rsc = src_rbs_size
    4.93 +	;;
    4.94 +{
    4.95 +	loadrs // must be first isns in group
    4.96 +	;;
    4.97 +}
    4.98 +
    4.99 +	// flush to dst
   4.100 +	mov ar.bspstore = dst_bspstore
   4.101 +	;;
   4.102 +{
   4.103 +	flushrs	// must be first isns in group
   4.104 +	srlz.i
   4.105 +}
   4.106 +	;;
   4.107 +	mov dst_rbs_size = ar.bsp
   4.108 +	mov dst_rnat = ar.rnat
   4.109 +	;;
   4.110 +	sub dst_rbs_size = dst_rbs_size, dst_bspstore
   4.111 +
   4.112 +	// switch back to the original backing store
   4.113 +	.restorereg ar.bspstore
   4.114 +	mov ar.bspstore = saved_ar_bspstore
   4.115 +	;;
   4.116 +	.restorereg ar.rnat
   4.117 +	mov ar.rnat = saved_ar_rnat
   4.118 +	;; 
   4.119 +	// restore rsc		
   4.120 +	mov ar.rsc = saved_ar_rsc
   4.121 +
   4.122 +	;; 
   4.123 +	br.ret.sptk.many rp
   4.124 +END(__ia64_copy_rbs)
   4.125 +
   4.126 +GLOBAL_ENTRY(ia64_copy_rbs)
   4.127 +	.prologue
   4.128 +	.fframe 0
   4.129 +	.save ar.pfs, saved_ar_pfs
   4.130 +	alloc saved_ar_pfs = ar.pfs, 6, 0, 0, 0
   4.131 +	.save.b 0x1, saved_rp
   4.132 +	mov saved_rp = rp
   4.133 +
   4.134 +	.body
   4.135 +	// we play with register backing store so that we can't use
   4.136 +	// stacked registers.
   4.137 +	// save in0-in5 to static scratch registres
   4.138 +	mov dst_bspstore   = r32
   4.139 +	mov dst_rbs_size_p = r33
   4.140 +	mov dst_rnat_p     = r34
   4.141 +	mov src_bsp        = r35
   4.142 +	mov src_rbs_size   = r36
   4.143 +	mov src_rnat       = r37
   4.144 +	;;
   4.145 +	// set cfm.{sof, sol, sor, rrb}=0 to avoid nasty stacked register
   4.146 +	// issues related to cover by calling void __ia64_copy_rbs(void).
   4.147 +	// cfm.{sof, sol, sor, rrb}=0 makes things easy.
   4.148 +	br.call.sptk.many rp = __ia64_copy_rbs
   4.149 +
   4.150 +	st8 [dst_rbs_size_p] = dst_rbs_size
   4.151 +	st8 [dst_rnat_p]     = dst_rnat
   4.152 +
   4.153 +	.restorereg ar.pfs
   4.154 +	mov ar.pfs = saved_ar_pfs
   4.155 +	.restorereg rp
   4.156 +	mov rp = saved_rp
   4.157 +	;; 
   4.158 +	br.ret.sptk.many rp
   4.159 +END(ia64_copy_rbs)
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/include/asm-ia64/vmx_vcpu_save.h	Sun Oct 21 13:38:57 2007 -0600
     5.3 @@ -0,0 +1,40 @@
     5.4 +/******************************************************************************
     5.5 + * vmx_vcpu_save.h
     5.6 + *
     5.7 + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
     5.8 + *                    VA Linux Systems Japan K.K.
     5.9 + *
    5.10 + * This program is free software; you can redistribute it and/or modify
    5.11 + * it under the terms of the GNU General Public License as published by
    5.12 + * the Free Software Foundation; either version 2 of the License, or
    5.13 + * (at your option) any later version.
    5.14 + *
    5.15 + * This program is distributed in the hope that it will be useful,
    5.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.18 + * GNU General Public License for more details.
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License
    5.21 + * along with this program; if not, write to the Free Software
    5.22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.23 + *
    5.24 + */
    5.25 +#ifndef __ASM_IA64_VMX_VCPU_SAVE_H__
    5.26 +#define __ASM_IA64_VMX_VCPU_SAVE_H__
    5.27 +
    5.28 +#include <xen/sched.h>
    5.29 +#include <xen/domain.h>
    5.30 +
    5.31 +void vmx_arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c);
    5.32 +int vmx_arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c);
    5.33 +
    5.34 +#endif /* __ASM_IA64_VMX_VCPU_SAVE_H__ */
    5.35 +/*
    5.36 + * Local variables:
    5.37 + * mode: C
    5.38 + * c-set-style: "BSD"
    5.39 + * c-basic-offset: 4
    5.40 + * tab-width: 4
    5.41 + * indent-tabs-mode: nil
    5.42 + * End:
    5.43 + */
     6.1 --- a/xen/include/public/arch-ia64.h	Sun Oct 21 13:38:05 2007 -0600
     6.2 +++ b/xen/include/public/arch-ia64.h	Sun Oct 21 13:38:57 2007 -0600
     6.3 @@ -421,7 +421,7 @@ struct vcpu_guest_context_regs {
     6.4  };
     6.5  
     6.6  struct vcpu_guest_context {
     6.7 -#define VGCF_EXTRA_REGS (1<<1)	/* Get/Set extra regs.  */
     6.8 +#define VGCF_EXTRA_REGS (1UL << 1)	/* Get/Set extra regs.  */
     6.9      unsigned long flags;       /* VGCF_* flags */
    6.10  
    6.11      struct vcpu_guest_context_regs regs;