aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
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
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')
-rw-r--r--arch/ia64/include/asm/xen/inst.h21
-rw-r--r--arch/ia64/include/asm/xen/interface.h9
-rw-r--r--arch/ia64/include/asm/xen/minstate.h11
-rw-r--r--arch/ia64/include/asm/xen/privop.h2
-rw-r--r--arch/ia64/kernel/asm-offsets.c2
-rw-r--r--arch/ia64/xen/xen_pv_ops.c80
6 files changed, 123 insertions, 2 deletions
diff --git a/arch/ia64/include/asm/xen/inst.h b/arch/ia64/include/asm/xen/inst.h
index e8e01b28d2ae..90537dc15efe 100644
--- a/arch/ia64/include/asm/xen/inst.h
+++ b/arch/ia64/include/asm/xen/inst.h
@@ -113,6 +113,27 @@
113.endm 113.endm
114#define MOV_FROM_PSR(pred, reg, clob) __MOV_FROM_PSR pred, reg, clob 114#define MOV_FROM_PSR(pred, reg, clob) __MOV_FROM_PSR pred, reg, clob
115 115
116/* assuming ar.itc is read with interrupt disabled. */
117#define MOV_FROM_ITC(pred, pred_clob, reg, clob) \
118(pred) movl clob = XSI_ITC_OFFSET; \
119 ;; \
120(pred) ld8 clob = [clob]; \
121(pred) mov reg = ar.itc; \
122 ;; \
123(pred) add reg = reg, clob; \
124 ;; \
125(pred) movl clob = XSI_ITC_LAST; \
126 ;; \
127(pred) ld8 clob = [clob]; \
128 ;; \
129(pred) cmp.geu.unc pred_clob, p0 = clob, reg; \
130 ;; \
131(pred_clob) add reg = 1, clob; \
132 ;; \
133(pred) movl clob = XSI_ITC_LAST; \
134 ;; \
135(pred) st8 [clob] = reg
136
116 137
117#define MOV_TO_IFA(reg, clob) \ 138#define MOV_TO_IFA(reg, clob) \
118 movl clob = XSI_IFA; \ 139 movl clob = XSI_IFA; \
diff --git a/arch/ia64/include/asm/xen/interface.h b/arch/ia64/include/asm/xen/interface.h
index f00fab40854d..e951e740bdf2 100644
--- a/arch/ia64/include/asm/xen/interface.h
+++ b/arch/ia64/include/asm/xen/interface.h
@@ -209,6 +209,15 @@ struct mapped_regs {
209 unsigned long krs[8]; /* kernel registers */ 209 unsigned long krs[8]; /* kernel registers */
210 unsigned long tmp[16]; /* temp registers 210 unsigned long tmp[16]; /* temp registers
211 (e.g. for hyperprivops) */ 211 (e.g. for hyperprivops) */
212
213 /* itc paravirtualization
214 * vAR.ITC = mAR.ITC + itc_offset
215 * itc_last is one which was lastly passed to
216 * the guest OS in order to prevent it from
217 * going backwords.
218 */
219 unsigned long itc_offset;
220 unsigned long itc_last;
212 }; 221 };
213 }; 222 };
214}; 223};
diff --git a/arch/ia64/include/asm/xen/minstate.h b/arch/ia64/include/asm/xen/minstate.h
index 4d92d9bbda7b..c57fa910f2c9 100644
--- a/arch/ia64/include/asm/xen/minstate.h
+++ b/arch/ia64/include/asm/xen/minstate.h
@@ -1,3 +1,12 @@
1
2#ifdef CONFIG_VIRT_CPU_ACCOUNTING
3/* read ar.itc in advance, and use it before leaving bank 0 */
4#define XEN_ACCOUNT_GET_STAMP \
5 MOV_FROM_ITC(pUStk, p6, r20, r2);
6#else
7#define XEN_ACCOUNT_GET_STAMP
8#endif
9
1/* 10/*
2 * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves 11 * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
3 * the minimum state necessary that allows us to turn psr.ic back 12 * the minimum state necessary that allows us to turn psr.ic back
@@ -123,7 +132,7 @@
123 ;; \ 132 ;; \
124.mem.offset 0,0; st8.spill [r16]=r2,16; \ 133.mem.offset 0,0; st8.spill [r16]=r2,16; \
125.mem.offset 8,0; st8.spill [r17]=r3,16; \ 134.mem.offset 8,0; st8.spill [r17]=r3,16; \
126 ACCOUNT_GET_STAMP \ 135 XEN_ACCOUNT_GET_STAMP \
127 adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ 136 adds r2=IA64_PT_REGS_R16_OFFSET,r1; \
128 ;; \ 137 ;; \
129 EXTRA; \ 138 EXTRA; \
diff --git a/arch/ia64/include/asm/xen/privop.h b/arch/ia64/include/asm/xen/privop.h
index 71ec7546e100..2261dda578ff 100644
--- a/arch/ia64/include/asm/xen/privop.h
+++ b/arch/ia64/include/asm/xen/privop.h
@@ -55,6 +55,8 @@
55#define XSI_BANK1_R16 (XSI_BASE + XSI_BANK1_R16_OFS) 55#define XSI_BANK1_R16 (XSI_BASE + XSI_BANK1_R16_OFS)
56#define XSI_BANKNUM (XSI_BASE + XSI_BANKNUM_OFS) 56#define XSI_BANKNUM (XSI_BASE + XSI_BANKNUM_OFS)
57#define XSI_IHA (XSI_BASE + XSI_IHA_OFS) 57#define XSI_IHA (XSI_BASE + XSI_IHA_OFS)
58#define XSI_ITC_OFFSET (XSI_BASE + XSI_ITC_OFFSET_OFS)
59#define XSI_ITC_LAST (XSI_BASE + XSI_ITC_LAST_OFS)
58#endif 60#endif
59 61
60#ifndef __ASSEMBLY__ 62#ifndef __ASSEMBLY__
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index 742dbb1d5a4f..af5650169043 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -316,5 +316,7 @@ void foo(void)
316 DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]); 316 DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]);
317 DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat); 317 DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat);
318 DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat); 318 DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat);
319 DEFINE_MAPPED_REG_OFS(XSI_ITC_OFFSET_OFS, itc_offset);
320 DEFINE_MAPPED_REG_OFS(XSI_ITC_LAST_OFS, itc_last);
319#endif /* CONFIG_XEN */ 321#endif /* CONFIG_XEN */
320} 322}
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;