ia64/xen-unstable

changeset 18954:4422219acd93

[IA64] paravirtualize itc and support save/restore.

ia64 linux 2.6.18 only use ar.itc for local ticks so that
ar.itc didn't need paravirtualization and it can be work arounded
when save/restore.
However recent ia64 linux uses ar.itc for sched_clock() and
CONFIG_VIRT_CPU_ACCOUNTING and other issues. So ar.itc needs
paravirtualization. Although Most part is done in guest OS,
save/restore needs hypervisor support.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Mon Jan 05 12:24:58 2009 +0900 (2009-01-05)
parents ecdc570407ec
children 636c685d9622
files tools/libxc/ia64/xc_ia64_linux_restore.c xen/arch/ia64/xen/domain.c xen/include/public/arch-ia64.h
line diff
     1.1 --- a/tools/libxc/ia64/xc_ia64_linux_restore.c	Mon Jan 05 12:24:58 2009 +0900
     1.2 +++ b/tools/libxc/ia64/xc_ia64_linux_restore.c	Mon Jan 05 12:24:58 2009 +0900
     1.3 @@ -128,7 +128,8 @@ xc_ia64_recv_vcpu_context(int xc_handle,
     1.4      fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt->regs.ip, ctxt->regs.b[0]);
     1.5  
     1.6      /* Initialize and set registers.  */
     1.7 -    ctxt->flags = VGCF_EXTRA_REGS | VGCF_SET_CR_IRR | VGCF_online;
     1.8 +    ctxt->flags = VGCF_EXTRA_REGS | VGCF_SET_CR_IRR | VGCF_online |
     1.9 +        VGCF_SET_AR_ITC;
    1.10      if (xc_vcpu_setcontext(xc_handle, dom, vcpu, ctxt_any) != 0) {
    1.11          ERROR("Couldn't set vcpu context");
    1.12          return -1;
     2.1 --- a/xen/arch/ia64/xen/domain.c	Mon Jan 05 12:24:58 2009 +0900
     2.2 +++ b/xen/arch/ia64/xen/domain.c	Mon Jan 05 12:24:58 2009 +0900
     2.3 @@ -719,6 +719,48 @@ nats_update(unsigned int* nats, unsigned
     2.4  		*nats &= ~(1UL << reg);
     2.5  }
     2.6  
     2.7 +static unsigned long
     2.8 +__vcpu_get_itc(struct vcpu *v)
     2.9 +{
    2.10 +	unsigned long itc_last;
    2.11 +	unsigned long itc_offset;
    2.12 +	unsigned long itc;
    2.13 +
    2.14 +	if (unlikely(v->arch.privregs == NULL))
    2.15 +		return ia64_get_itc();
    2.16 +	
    2.17 +	itc_last = v->arch.privregs->itc_last;
    2.18 +	itc_offset = v->arch.privregs->itc_offset;
    2.19 +	itc = ia64_get_itc();
    2.20 +	itc += itc_offset;
    2.21 +	if (itc_last >= itc)
    2.22 +		itc = itc_last;
    2.23 +	return itc;
    2.24 +}
    2.25 +
    2.26 +static void
    2.27 +__vcpu_set_itc(struct vcpu *v, u64 val)
    2.28 +{
    2.29 +	unsigned long itc;
    2.30 +	unsigned long itc_offset;
    2.31 +	unsigned long itc_last;
    2.32 +
    2.33 +	BUG_ON(v->arch.privregs == NULL);
    2.34 +
    2.35 +	if (v != current)
    2.36 +		vcpu_pause(v);
    2.37 +	
    2.38 +	itc = ia64_get_itc();
    2.39 +	itc_offset = val - itc;
    2.40 +	itc_last = val;
    2.41 +	
    2.42 +	v->arch.privregs->itc_offset = itc_offset;
    2.43 +	v->arch.privregs->itc_last = itc_last;
    2.44 +
    2.45 +	if (v != current)
    2.46 +		vcpu_unpause(v);
    2.47 +}
    2.48 +
    2.49  void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
    2.50  {
    2.51  	int i;
    2.52 @@ -757,6 +799,10 @@ void arch_get_info_guest(struct vcpu *v,
    2.53  		unw_get_ar(&info, UNW_AR_LC, &c.nat->regs.ar.lc);
    2.54  		unw_get_ar(&info, UNW_AR_EC, &c.nat->regs.ar.ec);
    2.55  	}
    2.56 +
    2.57 +	if (!is_hvm)
    2.58 +		c.nat->regs.ar.itc = __vcpu_get_itc(v);
    2.59 +
    2.60  	c.nat->regs.ar.csd = uregs->ar_csd;
    2.61  	c.nat->regs.ar.ssd = uregs->ar_ssd;
    2.62  
    2.63 @@ -1244,6 +1290,10 @@ int arch_set_info_guest(struct vcpu *v, 
    2.64  		unw_set_ar(&info, UNW_AR_LC, c.nat->regs.ar.lc);
    2.65  		unw_set_ar(&info, UNW_AR_EC, c.nat->regs.ar.ec);
    2.66  	}
    2.67 +
    2.68 +	if (!is_hvm_domain(d) && (c.nat->flags & VGCF_SET_AR_ITC))
    2.69 +		__vcpu_set_itc(v, c.nat->regs.ar.itc);
    2.70 +
    2.71  	uregs->ar_csd = c.nat->regs.ar.csd;
    2.72  	uregs->ar_ssd = c.nat->regs.ar.ssd;
    2.73  	
     3.1 --- a/xen/include/public/arch-ia64.h	Mon Jan 05 12:24:58 2009 +0900
     3.2 +++ b/xen/include/public/arch-ia64.h	Mon Jan 05 12:24:58 2009 +0900
     3.3 @@ -198,6 +198,15 @@ struct mapped_regs {
     3.4              unsigned long rrs[8]; // region registers
     3.5              unsigned long krs[8]; // kernel registers
     3.6              unsigned long tmp[16]; // temp registers (e.g. for hyperprivops)
     3.7 +
     3.8 +            /* itc paravirtualization
     3.9 +             * vAR.ITC = mAR.ITC + itc_offset
    3.10 +             * itc_last is one which was lastly passed to
    3.11 +             * the guest OS in order to prevent it from
    3.12 +             * going backwords.
    3.13 +             */
    3.14 +            unsigned long itc_offset;
    3.15 +            unsigned long itc_last;
    3.16          };
    3.17      };
    3.18  };
    3.19 @@ -392,6 +401,7 @@ struct vcpu_guest_context {
    3.20  #define VGCF_EXTRA_REGS (1UL << 1)	/* Set extra regs.  */
    3.21  #define VGCF_SET_CR_IRR (1UL << 2)	/* Set cr_irr[0:3]. */
    3.22  #define VGCF_online     (1UL << 3)  /* make this vcpu online */
    3.23 +#define VGCF_SET_AR_ITC (1UL << 4)  /* set pv ar.itc. itc_offset, itc_last */
    3.24      unsigned long flags;       /* VGCF_* flags */
    3.25  
    3.26      struct vcpu_guest_context_regs regs;