aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/xen
diff options
context:
space:
mode:
authorIsaku Yamahata <yamahata@valinux.co.jp>2009-03-04 07:05:39 -0500
committerTony Luck <tony.luck@intel.com>2009-03-26 13:50:32 -0400
commit496203b15b7249599712525c2b6aafe231b4628d (patch)
treeee8c5dbe02b820ac208fe6f3b7982a49a502cc28 /arch/ia64/xen
parent94752a794ddfdef65289a16627faefa7e2e62d58 (diff)
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>
Diffstat (limited to 'arch/ia64/xen')
-rw-r--r--arch/ia64/xen/xen_pv_ops.c80
1 files changed, 79 insertions, 1 deletions
diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c
index fe72308321b6..d91336114344 100644
--- a/arch/ia64/xen/xen_pv_ops.c
+++ b/arch/ia64/xen/xen_pv_ops.c
@@ -183,6 +183,75 @@ struct pv_fsys_data xen_fsys_data __initdata = {
183 * intrinsics hooks. 183 * intrinsics hooks.
184 */ 184 */
185 185
186static void
187xen_set_itm_with_offset(unsigned long val)
188{
189 /* ia64_cpu_local_tick() calls this with interrupt enabled. */
190 /* WARN_ON(!irqs_disabled()); */
191 xen_set_itm(val - XEN_MAPPEDREGS->itc_offset);
192}
193
194static unsigned long
195xen_get_itm_with_offset(void)
196{
197 /* unused at this moment */
198 printk(KERN_DEBUG "%s is called.\n", __func__);
199
200 WARN_ON(!irqs_disabled());
201 return ia64_native_getreg(_IA64_REG_CR_ITM) +
202 XEN_MAPPEDREGS->itc_offset;
203}
204
205/* ia64_set_itc() is only called by
206 * cpu_init() with ia64_set_itc(0) and ia64_sync_itc().
207 * So XEN_MAPPEDRESG->itc_offset cal be considered as almost constant.
208 */
209static void
210xen_set_itc(unsigned long val)
211{
212 unsigned long mitc;
213
214 WARN_ON(!irqs_disabled());
215 mitc = ia64_native_getreg(_IA64_REG_AR_ITC);
216 XEN_MAPPEDREGS->itc_offset = val - mitc;
217 XEN_MAPPEDREGS->itc_last = val;
218}
219
220static unsigned long
221xen_get_itc(void)
222{
223 unsigned long res;
224 unsigned long itc_offset;
225 unsigned long itc_last;
226 unsigned long ret_itc_last;
227
228 itc_offset = XEN_MAPPEDREGS->itc_offset;
229 do {
230 itc_last = XEN_MAPPEDREGS->itc_last;
231 res = ia64_native_getreg(_IA64_REG_AR_ITC);
232 res += itc_offset;
233 if (itc_last >= res)
234 res = itc_last + 1;
235 ret_itc_last = cmpxchg(&XEN_MAPPEDREGS->itc_last,
236 itc_last, res);
237 } while (unlikely(ret_itc_last != itc_last));
238 return res;
239
240#if 0
241 /* ia64_itc_udelay() calls ia64_get_itc() with interrupt enabled.
242 Should it be paravirtualized instead? */
243 WARN_ON(!irqs_disabled());
244 itc_offset = XEN_MAPPEDREGS->itc_offset;
245 itc_last = XEN_MAPPEDREGS->itc_last;
246 res = ia64_native_getreg(_IA64_REG_AR_ITC);
247 res += itc_offset;
248 if (itc_last >= res)
249 res = itc_last + 1;
250 XEN_MAPPEDREGS->itc_last = res;
251 return res;
252#endif
253}
254
186static void xen_setreg(int regnum, unsigned long val) 255static void xen_setreg(int regnum, unsigned long val)
187{ 256{
188 switch (regnum) { 257 switch (regnum) {
@@ -194,11 +263,14 @@ static void xen_setreg(int regnum, unsigned long val)
194 xen_set_eflag(val); 263 xen_set_eflag(val);
195 break; 264 break;
196#endif 265#endif
266 case _IA64_REG_AR_ITC:
267 xen_set_itc(val);
268 break;
197 case _IA64_REG_CR_TPR: 269 case _IA64_REG_CR_TPR:
198 xen_set_tpr(val); 270 xen_set_tpr(val);
199 break; 271 break;
200 case _IA64_REG_CR_ITM: 272 case _IA64_REG_CR_ITM:
201 xen_set_itm(val); 273 xen_set_itm_with_offset(val);
202 break; 274 break;
203 case _IA64_REG_CR_EOI: 275 case _IA64_REG_CR_EOI:
204 xen_eoi(val); 276 xen_eoi(val);
@@ -222,6 +294,12 @@ static unsigned long xen_getreg(int regnum)
222 res = xen_get_eflag(); 294 res = xen_get_eflag();
223 break; 295 break;
224#endif 296#endif
297 case _IA64_REG_AR_ITC:
298 res = xen_get_itc();
299 break;
300 case _IA64_REG_CR_ITM:
301 res = xen_get_itm_with_offset();
302 break;
225 case _IA64_REG_CR_IVR: 303 case _IA64_REG_CR_IVR:
226 res = xen_get_ivr(); 304 res = xen_get_ivr();
227 break; 305 break;