This patch is needed for save/restore pv_ops domU.
Since old non-pv_ops domU (Linux 2.6.18-xen) ignores the
new member in shared_info, itc_offset, itc_last,
save/restore also continues to work with the old kernel.
thanks,
[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@xxxxxxxxxxxxx>
diff -r 48db4eee7d58 tools/libxc/ia64/xc_ia64_linux_restore.c
--- a/tools/libxc/ia64/xc_ia64_linux_restore.c Mon Aug 25 19:04:37 2008 +0900
+++ b/tools/libxc/ia64/xc_ia64_linux_restore.c Fri Aug 29 16:20:15 2008 +0900
@@ -128,7 +128,8 @@
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 -r 48db4eee7d58 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/arch/ia64/xen/domain.c Fri Aug 29 16:20:15 2008 +0900
@@ -706,6 +706,48 @@
*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;
@@ -744,6 +786,10 @@
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;
@@ -1231,6 +1277,10 @@
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 -r 48db4eee7d58 xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h Mon Aug 25 19:04:37 2008 +0900
+++ b/xen/include/public/arch-ia64.h Fri Aug 29 16:20:15 2008 +0900
@@ -198,6 +198,15 @@
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 @@
#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@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|