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;
*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;
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;
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;
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;
};
};
};
#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;