ia64/pv_ops/xen: paravirtualize read/write ar.itc and ar.itm

paravirtualize ar.itc and ar.itm in order to support save/restore.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Bu işleme şunda yer alıyor:
Isaku Yamahata
2009-03-04 21:05:39 +09:00
işlemeyi yapan: Tony Luck
ebeveyn 94752a794d
işleme 496203b15b
6 değiştirilmiş dosya ile 123 ekleme ve 2 silme

Dosyayı Görüntüle

@@ -183,6 +183,75 @@ struct pv_fsys_data xen_fsys_data __initdata = {
* intrinsics hooks.
*/
static void
xen_set_itm_with_offset(unsigned long val)
{
/* ia64_cpu_local_tick() calls this with interrupt enabled. */
/* WARN_ON(!irqs_disabled()); */
xen_set_itm(val - XEN_MAPPEDREGS->itc_offset);
}
static unsigned long
xen_get_itm_with_offset(void)
{
/* unused at this moment */
printk(KERN_DEBUG "%s is called.\n", __func__);
WARN_ON(!irqs_disabled());
return ia64_native_getreg(_IA64_REG_CR_ITM) +
XEN_MAPPEDREGS->itc_offset;
}
/* ia64_set_itc() is only called by
* cpu_init() with ia64_set_itc(0) and ia64_sync_itc().
* So XEN_MAPPEDRESG->itc_offset cal be considered as almost constant.
*/
static void
xen_set_itc(unsigned long val)
{
unsigned long mitc;
WARN_ON(!irqs_disabled());
mitc = ia64_native_getreg(_IA64_REG_AR_ITC);
XEN_MAPPEDREGS->itc_offset = val - mitc;
XEN_MAPPEDREGS->itc_last = val;
}
static unsigned long
xen_get_itc(void)
{
unsigned long res;
unsigned long itc_offset;
unsigned long itc_last;
unsigned long ret_itc_last;
itc_offset = XEN_MAPPEDREGS->itc_offset;
do {
itc_last = XEN_MAPPEDREGS->itc_last;
res = ia64_native_getreg(_IA64_REG_AR_ITC);
res += itc_offset;
if (itc_last >= res)
res = itc_last + 1;
ret_itc_last = cmpxchg(&XEN_MAPPEDREGS->itc_last,
itc_last, res);
} while (unlikely(ret_itc_last != itc_last));
return res;
#if 0
/* ia64_itc_udelay() calls ia64_get_itc() with interrupt enabled.
Should it be paravirtualized instead? */
WARN_ON(!irqs_disabled());
itc_offset = XEN_MAPPEDREGS->itc_offset;
itc_last = XEN_MAPPEDREGS->itc_last;
res = ia64_native_getreg(_IA64_REG_AR_ITC);
res += itc_offset;
if (itc_last >= res)
res = itc_last + 1;
XEN_MAPPEDREGS->itc_last = res;
return res;
#endif
}
static void xen_setreg(int regnum, unsigned long val)
{
switch (regnum) {
@@ -194,11 +263,14 @@ static void xen_setreg(int regnum, unsigned long val)
xen_set_eflag(val);
break;
#endif
case _IA64_REG_AR_ITC:
xen_set_itc(val);
break;
case _IA64_REG_CR_TPR:
xen_set_tpr(val);
break;
case _IA64_REG_CR_ITM:
xen_set_itm(val);
xen_set_itm_with_offset(val);
break;
case _IA64_REG_CR_EOI:
xen_eoi(val);
@@ -222,6 +294,12 @@ static unsigned long xen_getreg(int regnum)
res = xen_get_eflag();
break;
#endif
case _IA64_REG_AR_ITC:
res = xen_get_itc();
break;
case _IA64_REG_CR_ITM:
res = xen_get_itm_with_offset();
break;
case _IA64_REG_CR_IVR:
res = xen_get_ivr();
break;