diff options
author | Isaku Yamahata <yamahata@valinux.co.jp> | 2008-10-16 22:18:00 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2008-10-17 13:03:24 -0400 |
commit | 4b83ce4367943aa3eb960df56759f45d70722a4c (patch) | |
tree | 5016104e05b1293c3f06eb7f039dd8cf978575bb /arch/ia64 | |
parent | b5a26e4db818d4647a019d5c462f6778b8213112 (diff) |
ia64/pv_ops/xen: define xen pv_cpu_ops.
define xen pv_cpu_ops which implementes xen paravirtualized
privileged instructions.
Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com>
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/xen/xen_pv_ops.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c index fc9d599b62ae..c236f04ffad5 100644 --- a/arch/ia64/xen/xen_pv_ops.c +++ b/arch/ia64/xen/xen_pv_ops.c | |||
@@ -163,6 +163,119 @@ static const struct pv_init_ops xen_init_ops __initdata = { | |||
163 | }; | 163 | }; |
164 | 164 | ||
165 | /*************************************************************************** | 165 | /*************************************************************************** |
166 | * pv_cpu_ops | ||
167 | * intrinsics hooks. | ||
168 | */ | ||
169 | |||
170 | static void xen_setreg(int regnum, unsigned long val) | ||
171 | { | ||
172 | switch (regnum) { | ||
173 | case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: | ||
174 | xen_set_kr(regnum - _IA64_REG_AR_KR0, val); | ||
175 | break; | ||
176 | #ifdef CONFIG_IA32_SUPPORT | ||
177 | case _IA64_REG_AR_EFLAG: | ||
178 | xen_set_eflag(val); | ||
179 | break; | ||
180 | #endif | ||
181 | case _IA64_REG_CR_TPR: | ||
182 | xen_set_tpr(val); | ||
183 | break; | ||
184 | case _IA64_REG_CR_ITM: | ||
185 | xen_set_itm(val); | ||
186 | break; | ||
187 | case _IA64_REG_CR_EOI: | ||
188 | xen_eoi(val); | ||
189 | break; | ||
190 | default: | ||
191 | ia64_native_setreg_func(regnum, val); | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static unsigned long xen_getreg(int regnum) | ||
197 | { | ||
198 | unsigned long res; | ||
199 | |||
200 | switch (regnum) { | ||
201 | case _IA64_REG_PSR: | ||
202 | res = xen_get_psr(); | ||
203 | break; | ||
204 | #ifdef CONFIG_IA32_SUPPORT | ||
205 | case _IA64_REG_AR_EFLAG: | ||
206 | res = xen_get_eflag(); | ||
207 | break; | ||
208 | #endif | ||
209 | case _IA64_REG_CR_IVR: | ||
210 | res = xen_get_ivr(); | ||
211 | break; | ||
212 | case _IA64_REG_CR_TPR: | ||
213 | res = xen_get_tpr(); | ||
214 | break; | ||
215 | default: | ||
216 | res = ia64_native_getreg_func(regnum); | ||
217 | break; | ||
218 | } | ||
219 | return res; | ||
220 | } | ||
221 | |||
222 | /* turning on interrupts is a bit more complicated.. write to the | ||
223 | * memory-mapped virtual psr.i bit first (to avoid race condition), | ||
224 | * then if any interrupts were pending, we have to execute a hyperprivop | ||
225 | * to ensure the pending interrupt gets delivered; else we're done! */ | ||
226 | static void | ||
227 | xen_ssm_i(void) | ||
228 | { | ||
229 | int old = xen_get_virtual_psr_i(); | ||
230 | xen_set_virtual_psr_i(1); | ||
231 | barrier(); | ||
232 | if (!old && xen_get_virtual_pend()) | ||
233 | xen_hyper_ssm_i(); | ||
234 | } | ||
235 | |||
236 | /* turning off interrupts can be paravirtualized simply by writing | ||
237 | * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */ | ||
238 | static void | ||
239 | xen_rsm_i(void) | ||
240 | { | ||
241 | xen_set_virtual_psr_i(0); | ||
242 | barrier(); | ||
243 | } | ||
244 | |||
245 | static unsigned long | ||
246 | xen_get_psr_i(void) | ||
247 | { | ||
248 | return xen_get_virtual_psr_i() ? IA64_PSR_I : 0; | ||
249 | } | ||
250 | |||
251 | static void | ||
252 | xen_intrin_local_irq_restore(unsigned long mask) | ||
253 | { | ||
254 | if (mask & IA64_PSR_I) | ||
255 | xen_ssm_i(); | ||
256 | else | ||
257 | xen_rsm_i(); | ||
258 | } | ||
259 | |||
260 | static const struct pv_cpu_ops xen_cpu_ops __initdata = { | ||
261 | .fc = xen_fc, | ||
262 | .thash = xen_thash, | ||
263 | .get_cpuid = xen_get_cpuid, | ||
264 | .get_pmd = xen_get_pmd, | ||
265 | .getreg = xen_getreg, | ||
266 | .setreg = xen_setreg, | ||
267 | .ptcga = xen_ptcga, | ||
268 | .get_rr = xen_get_rr, | ||
269 | .set_rr = xen_set_rr, | ||
270 | .set_rr0_to_rr4 = xen_set_rr0_to_rr4, | ||
271 | .ssm_i = xen_ssm_i, | ||
272 | .rsm_i = xen_rsm_i, | ||
273 | .get_psr_i = xen_get_psr_i, | ||
274 | .intrin_local_irq_restore | ||
275 | = xen_intrin_local_irq_restore, | ||
276 | }; | ||
277 | |||
278 | /*************************************************************************** | ||
166 | * pv_ops initialization | 279 | * pv_ops initialization |
167 | */ | 280 | */ |
168 | 281 | ||
@@ -172,4 +285,5 @@ xen_setup_pv_ops(void) | |||
172 | xen_info_init(); | 285 | xen_info_init(); |
173 | pv_info = xen_info; | 286 | pv_info = xen_info; |
174 | pv_init_ops = xen_init_ops; | 287 | pv_init_ops = xen_init_ops; |
288 | pv_cpu_ops = xen_cpu_ops; | ||
175 | } | 289 | } |