diff options
author | Isaku Yamahata <yamahata@valinux.co.jp> | 2009-03-04 07:05:39 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2009-03-26 13:50:32 -0400 |
commit | 496203b15b7249599712525c2b6aafe231b4628d (patch) | |
tree | ee8c5dbe02b820ac208fe6f3b7982a49a502cc28 /arch/ia64/xen | |
parent | 94752a794ddfdef65289a16627faefa7e2e62d58 (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.c | 80 |
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 | ||
186 | static void | ||
187 | xen_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 | |||
194 | static unsigned long | ||
195 | xen_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 | */ | ||
209 | static void | ||
210 | xen_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 | |||
220 | static unsigned long | ||
221 | xen_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 | |||
186 | static void xen_setreg(int regnum, unsigned long val) | 255 | static 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; |