# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1231125898 -32400
# Node ID 4422219acd938d8a7b6bdd14c604c215a6aace20
# Parent ecdc570407ecfa1264c043eecc4a14ffb175579f
[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>
---
tools/libxc/ia64/xc_ia64_linux_restore.c | 3 +
xen/arch/ia64/xen/domain.c | 50 +++++++++++++++++++++++++++++++
xen/include/public/arch-ia64.h | 10 ++++++
3 files changed, 62 insertions(+), 1 deletion(-)
diff -r ecdc570407ec -r 4422219acd93 tools/libxc/ia64/xc_ia64_linux_restore.c
--- a/tools/libxc/ia64/xc_ia64_linux_restore.c Mon Jan 05 12:24:58 2009 +0900
+++ b/tools/libxc/ia64/xc_ia64_linux_restore.c Mon Jan 05 12:24:58 2009 +0900
@@ -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 -r ecdc570407ec -r 4422219acd93 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Mon Jan 05 12:24:58 2009 +0900
+++ b/xen/arch/ia64/xen/domain.c Mon Jan 05 12:24:58 2009 +0900
@@ -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 -r ecdc570407ec -r 4422219acd93 xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h Mon Jan 05 12:24:58 2009 +0900
+++ b/xen/include/public/arch-ia64.h Mon Jan 05 12:24:58 2009 +0900
@@ -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;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|