This patch is necessary for save/restore support of ia64 pv_ops 
domU linux.
I posted this patch before, but didn't commit it because
it wasn't clear how the save/restore support was integrated.
I'm posting this patch again for those who want to try 
ia64 pv_ops domU Linux save/restore.


[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 <[EMAIL PROTECTED]>

diff --git a/tools/libxc/ia64/xc_ia64_linux_restore.c 
b/tools/libxc/ia64/xc_ia64_linux_restore.c
--- a/tools/libxc/ia64/xc_ia64_linux_restore.c
+++ b/tools/libxc/ia64/xc_ia64_linux_restore.c
@@ -128,7 +128,8 @@ xc_ia64_recv_vcpu_context(int xc_handle,
     fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt->regs.ip, ctxt->regs.b[0]);
 
     /* Initialize and set registers.  */
-    ctxt->flags = VGCF_EXTRA_REGS | VGCF_SET_CR_IRR | VGCF_online;
+    ctxt->flags = VGCF_EXTRA_REGS | VGCF_SET_CR_IRR | VGCF_online |
+        VGCF_SET_AR_ITC;
     if (xc_vcpu_setcontext(xc_handle, dom, vcpu, ctxt_any) != 0) {
         ERROR("Couldn't set vcpu context");
         return -1;
diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c
+++ b/xen/arch/ia64/xen/domain.c
@@ -719,6 +719,48 @@ nats_update(unsigned int* nats, unsigned
                *nats &= ~(1UL << reg);
 }
 
+static unsigned long
+__vcpu_get_itc(struct vcpu *v)
+{
+       unsigned long itc_last;
+       unsigned long itc_offset;
+       unsigned long itc;
+
+       if (unlikely(v->arch.privregs == NULL))
+               return ia64_get_itc();
+       
+       itc_last = v->arch.privregs->itc_last;
+       itc_offset = v->arch.privregs->itc_offset;
+       itc = ia64_get_itc();
+       itc += itc_offset;
+       if (itc_last >= itc)
+               itc = itc_last;
+       return itc;
+}
+
+static void
+__vcpu_set_itc(struct vcpu *v, u64 val)
+{
+       unsigned long itc;
+       unsigned long itc_offset;
+       unsigned long itc_last;
+
+       BUG_ON(v->arch.privregs == NULL);
+
+       if (v != current)
+               vcpu_pause(v);
+       
+       itc = ia64_get_itc();
+       itc_offset = val - itc;
+       itc_last = val;
+       
+       v->arch.privregs->itc_offset = itc_offset;
+       v->arch.privregs->itc_last = itc_last;
+
+       if (v != current)
+               vcpu_unpause(v);
+}
+
 void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
 {
        int i;
@@ -757,6 +799,10 @@ void arch_get_info_guest(struct vcpu *v,
                unw_get_ar(&info, UNW_AR_LC, &c.nat->regs.ar.lc);
                unw_get_ar(&info, UNW_AR_EC, &c.nat->regs.ar.ec);
        }
+
+       if (!is_hvm)
+               c.nat->regs.ar.itc = __vcpu_get_itc(v);
+
        c.nat->regs.ar.csd = uregs->ar_csd;
        c.nat->regs.ar.ssd = uregs->ar_ssd;
 
@@ -1244,6 +1290,10 @@ int arch_set_info_guest(struct vcpu *v, 
                unw_set_ar(&info, UNW_AR_LC, c.nat->regs.ar.lc);
                unw_set_ar(&info, UNW_AR_EC, c.nat->regs.ar.ec);
        }
+
+       if (!is_hvm_domain(d) && (c.nat->flags & VGCF_SET_AR_ITC))
+               __vcpu_set_itc(v, c.nat->regs.ar.itc);
+
        uregs->ar_csd = c.nat->regs.ar.csd;
        uregs->ar_ssd = c.nat->regs.ar.ssd;
        
diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h
+++ b/xen/include/public/arch-ia64.h
@@ -198,6 +198,15 @@ struct mapped_regs {
             unsigned long rrs[8]; // region registers
             unsigned long krs[8]; // kernel registers
             unsigned long tmp[16]; // temp registers (e.g. for hyperprivops)
+
+            /* itc paravirtualization
+             * vAR.ITC = mAR.ITC + itc_offset
+             * itc_last is one which was lastly passed to
+             * the guest OS in order to prevent it from
+             * going backwords.
+             */
+            unsigned long itc_offset;
+            unsigned long itc_last;
         };
     };
 };
@@ -392,6 +401,7 @@ struct vcpu_guest_context {
 #define VGCF_EXTRA_REGS (1UL << 1)     /* Set extra regs.  */
 #define VGCF_SET_CR_IRR (1UL << 2)     /* Set cr_irr[0:3]. */
 #define VGCF_online     (1UL << 3)  /* make this vcpu online */
+#define VGCF_SET_AR_ITC (1UL << 4)  /* set pv ar.itc. itc_offset, itc_last */
     unsigned long flags;       /* VGCF_* flags */
 
     struct vcpu_guest_context_regs regs;


-- 
yamahata

_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@lists.xensource.com
http://lists.xensource.com/xen-ia64-devel

Reply via email to