debuggers.hg

view xen/arch/ia64/xen/vcpu.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children 5c0bf00e371d
line source
1 /*
2 * Virtualized CPU functions
3 *
4 * Copyright (C) 2004-2005 Hewlett-Packard Co.
5 * Dan Magenheimer (dan.magenheimer@hp.com)
6 *
7 */
9 #include <linux/sched.h>
10 #include <public/xen.h>
11 #include <xen/mm.h>
12 #include <asm/ia64_int.h>
13 #include <asm/vcpu.h>
14 #include <asm/regionreg.h>
15 #include <asm/tlb.h>
16 #include <asm/processor.h>
17 #include <asm/delay.h>
18 #include <asm/vmx_vcpu.h>
19 #include <asm/vhpt.h>
20 #include <asm/tlbflush.h>
21 #include <asm/privop.h>
22 #include <xen/event.h>
23 #include <asm/vmx_phy_mode.h>
24 #include <asm/bundle.h>
25 #include <asm/privop_stat.h>
26 #include <asm/uaccess.h>
27 #include <asm/p2m_entry.h>
28 #include <asm/tlb_track.h>
30 /* FIXME: where these declarations should be there ? */
31 extern void getreg(unsigned long regnum, unsigned long *val, int *nat,
32 struct pt_regs *regs);
33 extern void setreg(unsigned long regnum, unsigned long val, int nat,
34 struct pt_regs *regs);
35 extern void getfpreg(unsigned long regnum, struct ia64_fpreg *fpval,
36 struct pt_regs *regs);
38 extern void setfpreg(unsigned long regnum, struct ia64_fpreg *fpval,
39 struct pt_regs *regs);
41 typedef union {
42 struct ia64_psr ia64_psr;
43 unsigned long i64;
44 } PSR;
46 // this def for vcpu_regs won't work if kernel stack is present
47 //#define vcpu_regs(vcpu) ((struct pt_regs *) vcpu->arch.regs
49 #define IA64_PTA_SZ_BIT 2
50 #define IA64_PTA_VF_BIT 8
51 #define IA64_PTA_BASE_BIT 15
52 #define IA64_PTA_SZ(x) (x##UL << IA64_PTA_SZ_BIT)
54 #define IA64_PSR_NON_VIRT_BITS \
55 (IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | \
56 IA64_PSR_MFL| IA64_PSR_MFH| IA64_PSR_PK | \
57 IA64_PSR_DFL| IA64_PSR_SP | IA64_PSR_DB | \
58 IA64_PSR_LP | IA64_PSR_TB | IA64_PSR_ID | \
59 IA64_PSR_DA | IA64_PSR_DD | IA64_PSR_SS | \
60 IA64_PSR_RI | IA64_PSR_ED | IA64_PSR_IA)
62 unsigned long vcpu_verbose = 0;
64 /**************************************************************************
65 VCPU general register access routines
66 **************************************************************************/
67 #ifdef XEN
68 u64 vcpu_get_gr(VCPU * vcpu, unsigned long reg)
69 {
70 REGS *regs = vcpu_regs(vcpu);
71 u64 val;
73 if (!reg)
74 return 0;
75 getreg(reg, &val, 0, regs); // FIXME: handle NATs later
76 return val;
77 }
79 IA64FAULT vcpu_get_gr_nat(VCPU * vcpu, unsigned long reg, u64 * val)
80 {
81 REGS *regs = vcpu_regs(vcpu);
82 int nat;
84 getreg(reg, val, &nat, regs); // FIXME: handle NATs later
85 if (nat)
86 return IA64_NAT_CONSUMPTION_VECTOR;
87 return 0;
88 }
90 // returns:
91 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
92 // IA64_NO_FAULT otherwise
93 IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value, int nat)
94 {
95 REGS *regs = vcpu_regs(vcpu);
96 long sof = (regs->cr_ifs) & 0x7f;
98 if (!reg)
99 return IA64_ILLOP_FAULT;
100 if (reg >= sof + 32)
101 return IA64_ILLOP_FAULT;
102 setreg(reg, value, nat, regs); // FIXME: handle NATs later
103 return IA64_NO_FAULT;
104 }
106 IA64FAULT
107 vcpu_get_fpreg(VCPU * vcpu, unsigned long reg, struct ia64_fpreg * val)
108 {
109 REGS *regs = vcpu_regs(vcpu);
110 getfpreg(reg, val, regs); // FIXME: handle NATs later
111 return IA64_NO_FAULT;
112 }
114 IA64FAULT
115 vcpu_set_fpreg(VCPU * vcpu, unsigned long reg, struct ia64_fpreg * val)
116 {
117 REGS *regs = vcpu_regs(vcpu);
118 if (reg > 1)
119 setfpreg(reg, val, regs); // FIXME: handle NATs later
120 return IA64_NO_FAULT;
121 }
123 #else
124 // returns:
125 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
126 // IA64_NO_FAULT otherwise
127 IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value)
128 {
129 REGS *regs = vcpu_regs(vcpu);
130 long sof = (regs->cr_ifs) & 0x7f;
132 if (!reg)
133 return IA64_ILLOP_FAULT;
134 if (reg >= sof + 32)
135 return IA64_ILLOP_FAULT;
136 setreg(reg, value, 0, regs); // FIXME: handle NATs later
137 return IA64_NO_FAULT;
138 }
140 #endif
142 void vcpu_init_regs(struct vcpu *v)
143 {
144 struct pt_regs *regs;
146 regs = vcpu_regs(v);
147 if (VMX_DOMAIN(v)) {
148 /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
149 regs->cr_ipsr = IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_IT |
150 IA64_PSR_I | IA64_PSR_IC | IA64_PSR_SI |
151 IA64_PSR_AC | IA64_PSR_BN | IA64_PSR_VM;
152 /* lazy fp */
153 FP_PSR(v) = IA64_PSR_DFH;
154 regs->cr_ipsr |= IA64_PSR_DFH;
155 } else {
156 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
157 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
158 regs->cr_ipsr &= ~(IA64_PSR_BITS_TO_CLEAR
159 | IA64_PSR_RI | IA64_PSR_IS);
160 // domain runs at PL2
161 regs->cr_ipsr = vcpu_pl_adjust(regs->cr_ipsr,IA64_PSR_CPL0_BIT);
162 // lazy fp
163 PSCB(v, hpsr_dfh) = 1;
164 PSCB(v, hpsr_mfh) = 0;
165 regs->cr_ipsr |= IA64_PSR_DFH;
166 }
167 regs->cr_ifs = 1UL << 63; /* or clear? */
168 regs->ar_fpsr = FPSR_DEFAULT;
170 if (VMX_DOMAIN(v)) {
171 vmx_init_all_rr(v);
172 /* Virtual processor context setup */
173 VCPU(v, vpsr) = IA64_PSR_BN;
174 VCPU(v, dcr) = 0;
175 } else {
176 init_all_rr(v);
177 regs->ar_rsc = vcpu_pl_adjust(regs->ar_rsc, 2);
178 VCPU(v, banknum) = 1;
179 VCPU(v, metaphysical_mode) = 1;
180 VCPU(v, interrupt_mask_addr) =
181 (unsigned char *)v->domain->arch.shared_info_va +
182 INT_ENABLE_OFFSET(v);
183 VCPU(v, itv) = (1 << 16); /* timer vector masked */
185 v->vcpu_info->evtchn_upcall_pending = 0;
186 v->vcpu_info->evtchn_upcall_mask = -1;
187 }
189 /* pta.size must not be 0. The minimum is 15 (32k) */
190 VCPU(v, pta) = 15 << 2;
192 v->arch.domain_itm_last = -1L;
193 }
195 /**************************************************************************
196 VCPU privileged application register access routines
197 **************************************************************************/
199 void vcpu_load_kernel_regs(VCPU * vcpu)
200 {
201 ia64_set_kr(0, VCPU(vcpu, krs[0]));
202 ia64_set_kr(1, VCPU(vcpu, krs[1]));
203 ia64_set_kr(2, VCPU(vcpu, krs[2]));
204 ia64_set_kr(3, VCPU(vcpu, krs[3]));
205 ia64_set_kr(4, VCPU(vcpu, krs[4]));
206 ia64_set_kr(5, VCPU(vcpu, krs[5]));
207 ia64_set_kr(6, VCPU(vcpu, krs[6]));
208 ia64_set_kr(7, VCPU(vcpu, krs[7]));
209 }
211 /* GCC 4.0.2 seems not to be able to suppress this call!. */
212 #define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
214 IA64FAULT vcpu_set_ar(VCPU * vcpu, u64 reg, u64 val)
215 {
216 if (reg == 44)
217 return vcpu_set_itc(vcpu, val);
218 else if (reg == 27)
219 return IA64_ILLOP_FAULT;
220 else if (reg == 24)
221 printk("warning: setting ar.eflg is a no-op; no IA-32 "
222 "support\n");
223 else if (reg > 7)
224 return IA64_ILLOP_FAULT;
225 else {
226 PSCB(vcpu, krs[reg]) = val;
227 ia64_set_kr(reg, val);
228 }
229 return IA64_NO_FAULT;
230 }
232 IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 reg, u64 * val)
233 {
234 if (reg == 24)
235 printk("warning: getting ar.eflg is a no-op; no IA-32 "
236 "support\n");
237 else if (reg > 7)
238 return IA64_ILLOP_FAULT;
239 else
240 *val = PSCB(vcpu, krs[reg]);
241 return IA64_NO_FAULT;
242 }
244 /**************************************************************************
245 VCPU protection key emulating for PV
246 This first implementation reserves 1 pkr for the hypervisor key.
247 On setting psr.pk the hypervisor key is loaded in pkr[15], therewith the
248 hypervisor may run with psr.pk==1. The key for the hypervisor is 0.
249 Furthermore the VCPU is flagged to use the protection keys.
250 Currently the domU has to take care of the used keys, because on setting
251 a pkr there is no check against other pkr's whether this key is already
252 used.
253 **************************************************************************/
255 /* The function loads the protection key registers from the struct arch_vcpu
256 * into the processor pkr's! Called in context_switch().
257 * TODO: take care of the order of writing pkr's!
258 */
259 void vcpu_pkr_load_regs(VCPU * vcpu)
260 {
261 int i;
263 for (i = 0; i <= XEN_IA64_NPKRS; i++)
264 ia64_set_pkr(i, PSCBX(vcpu, pkrs[i]));
265 }
267 /* The function activates the pkr handling. */
268 static void vcpu_pkr_set_psr_handling(VCPU * vcpu)
269 {
270 if (PSCBX(vcpu, pkr_flags) & XEN_IA64_PKR_IN_USE)
271 return;
273 vcpu_pkr_use_set(vcpu);
274 PSCBX(vcpu, pkrs[XEN_IA64_NPKRS]) = XEN_IA64_PKR_VAL;
276 /* Write the special key for the hypervisor into pkr[15]. */
277 ia64_set_pkr(XEN_IA64_NPKRS, XEN_IA64_PKR_VAL);
278 }
280 /**************************************************************************
281 VCPU processor status register access routines
282 **************************************************************************/
284 static void vcpu_set_metaphysical_mode(VCPU * vcpu, BOOLEAN newmode)
285 {
286 /* only do something if mode changes */
287 if (!!newmode ^ !!PSCB(vcpu, metaphysical_mode)) {
288 PSCB(vcpu, metaphysical_mode) = newmode;
289 if (newmode)
290 set_metaphysical_rr0();
291 else
292 set_virtual_rr0();
293 }
294 }
296 IA64FAULT vcpu_reset_psr_dt(VCPU * vcpu)
297 {
298 vcpu_set_metaphysical_mode(vcpu, TRUE);
299 return IA64_NO_FAULT;
300 }
302 IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24)
303 {
304 struct ia64_psr psr, imm, *ipsr;
305 REGS *regs = vcpu_regs(vcpu);
307 //PRIVOP_COUNT_ADDR(regs,_RSM);
308 // TODO: All of these bits need to be virtualized
309 // TODO: Only allowed for current vcpu
310 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
311 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
312 imm = *(struct ia64_psr *)&imm24;
313 // interrupt flag
314 if (imm.i)
315 vcpu->vcpu_info->evtchn_upcall_mask = 1;
316 if (imm.ic)
317 PSCB(vcpu, interrupt_collection_enabled) = 0;
318 // interrupt collection flag
319 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
320 // just handle psr.up and psr.pp for now
321 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
322 IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
323 IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_PK))
324 return IA64_ILLOP_FAULT;
325 if (imm.dfh) {
326 ipsr->dfh = PSCB(vcpu, hpsr_dfh);
327 PSCB(vcpu, vpsr_dfh) = 0;
328 }
329 if (imm.dfl)
330 ipsr->dfl = 0;
331 if (imm.pp) {
332 // xenoprof:
333 // Don't change psr.pp and ipsr->pp
334 // They are manipulated by xenoprof
335 // psr.pp = 1;
336 // ipsr->pp = 1;
337 PSCB(vcpu, vpsr_pp) = 0; // but fool the domain if it gets psr
338 }
339 if (imm.up) {
340 ipsr->up = 0;
341 psr.up = 0;
342 }
343 if (imm.sp) {
344 ipsr->sp = 0;
345 psr.sp = 0;
346 }
347 if (imm.be)
348 ipsr->be = 0;
349 if (imm.dt)
350 vcpu_set_metaphysical_mode(vcpu, TRUE);
351 if (imm.pk) {
352 ipsr->pk = 0;
353 vcpu_pkr_use_unset(vcpu);
354 }
355 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
356 return IA64_NO_FAULT;
357 }
359 IA64FAULT vcpu_set_psr_dt(VCPU * vcpu)
360 {
361 vcpu_set_metaphysical_mode(vcpu, FALSE);
362 return IA64_NO_FAULT;
363 }
365 IA64FAULT vcpu_set_psr_i(VCPU * vcpu)
366 {
367 vcpu->vcpu_info->evtchn_upcall_mask = 0;
368 PSCB(vcpu, interrupt_collection_enabled) = 1;
369 return IA64_NO_FAULT;
370 }
372 IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24)
373 {
374 struct ia64_psr psr, imm, *ipsr;
375 REGS *regs = vcpu_regs(vcpu);
376 u64 mask, enabling_interrupts = 0;
378 //PRIVOP_COUNT_ADDR(regs,_SSM);
379 // TODO: All of these bits need to be virtualized
380 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
381 imm = *(struct ia64_psr *)&imm24;
382 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
383 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
384 mask =
385 IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
386 IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE |
387 IA64_PSR_PK;
388 if (imm24 & ~mask)
389 return IA64_ILLOP_FAULT;
390 if (imm.dfh) {
391 PSCB(vcpu, vpsr_dfh) = 1;
392 ipsr->dfh = 1;
393 }
394 if (imm.dfl)
395 ipsr->dfl = 1;
396 if (imm.pp) {
397 // xenoprof:
398 // Don't change psr.pp and ipsr->pp
399 // They are manipulated by xenoprof
400 // psr.pp = 1;
401 // ipsr->pp = 1;
402 PSCB(vcpu, vpsr_pp) = 1;
403 }
404 if (imm.sp) {
405 ipsr->sp = 1;
406 psr.sp = 1;
407 }
408 if (imm.i) {
409 if (vcpu->vcpu_info->evtchn_upcall_mask) {
410 //printk("vcpu_set_psr_sm: psr.ic 0->1\n");
411 enabling_interrupts = 1;
412 }
413 vcpu->vcpu_info->evtchn_upcall_mask = 0;
414 }
415 if (imm.ic)
416 PSCB(vcpu, interrupt_collection_enabled) = 1;
417 // TODO: do this faster
418 if (imm.mfl) {
419 ipsr->mfl = 1;
420 psr.mfl = 1;
421 }
422 if (imm.mfh) {
423 ipsr->mfh = 1;
424 psr.mfh = 1;
425 }
426 if (imm.ac) {
427 ipsr->ac = 1;
428 psr.ac = 1;
429 }
430 if (imm.up) {
431 ipsr->up = 1;
432 psr.up = 1;
433 }
434 if (imm.be)
435 ipsr->be = 1;
436 if (imm.dt)
437 vcpu_set_metaphysical_mode(vcpu, FALSE);
438 if (imm.pk) {
439 vcpu_pkr_set_psr_handling(vcpu);
440 ipsr->pk = 1;
441 }
442 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
443 if (enabling_interrupts &&
444 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
445 PSCB(vcpu, pending_interruption) = 1;
446 return IA64_NO_FAULT;
447 }
449 IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val)
450 {
451 struct ia64_psr newpsr, *ipsr;
452 REGS *regs = vcpu_regs(vcpu);
453 u64 enabling_interrupts = 0;
455 newpsr = *(struct ia64_psr *)&val;
456 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
458 ipsr->be = newpsr.be;
459 ipsr->up = newpsr.up;
460 ipsr->ac = newpsr.ac;
461 ipsr->mfl = newpsr.mfl;
462 ipsr->mfh = newpsr.mfh;
464 PSCB(vcpu, interrupt_collection_enabled) = newpsr.ic;
466 if (newpsr.i && vcpu->vcpu_info->evtchn_upcall_mask)
467 enabling_interrupts = 1;
469 vcpu->vcpu_info->evtchn_upcall_mask = !(newpsr.i);
471 if (newpsr.pk) {
472 vcpu_pkr_set_psr_handling(vcpu);
473 ipsr->pk = 1;
474 } else
475 vcpu_pkr_use_unset(vcpu);
477 vcpu_set_metaphysical_mode(vcpu, !(newpsr.dt && newpsr.rt));
479 ipsr->dfl = newpsr.dfl;
480 PSCB(vcpu, vpsr_dfh) = newpsr.dfh;
481 ipsr->dfh = newpsr.dfh ? 1 : PSCB(vcpu, hpsr_dfh);
483 ipsr->sp = newpsr.sp;
485 /* xenoprof: Don't change ipsr->pp, it is manipulated by xenoprof */
486 PSCB(vcpu, vpsr_pp) = newpsr.pp;
488 if (enabling_interrupts &&
489 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
490 PSCB(vcpu, pending_interruption) = 1;
492 return IA64_NO_FAULT;
493 }
495 IA64FAULT vcpu_set_psr(VCPU * vcpu, u64 val)
496 {
497 IA64_PSR newpsr, vpsr;
498 REGS *regs = vcpu_regs(vcpu);
499 u64 enabling_interrupts = 0;
501 /* Copy non-virtualized bits. */
502 newpsr.val = val & IA64_PSR_NON_VIRT_BITS;
504 /* Bits forced to 1 (psr.si, psr.is and psr.mc are forced to 0) */
505 newpsr.val |= IA64_PSR_DI;
507 newpsr.val |= IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT |
508 IA64_PSR_IT | IA64_PSR_BN | IA64_PSR_DI;
509 /*
510 * xenoprof:
511 * keep psr.pp unchanged for xenoprof.
512 */
513 if (regs->cr_ipsr & IA64_PSR_PP)
514 newpsr.val |= IA64_PSR_PP;
515 else
516 newpsr.val &= ~IA64_PSR_PP;
518 vpsr.val = val;
520 if (val & IA64_PSR_DFH) {
521 newpsr.dfh = 1;
522 PSCB(vcpu, vpsr_dfh) = 1;
523 } else {
524 newpsr.dfh = PSCB(vcpu, hpsr_dfh);
525 PSCB(vcpu, vpsr_dfh) = 0;
526 }
528 PSCB(vcpu, vpsr_pp) = vpsr.pp;
530 if (vpsr.i) {
531 if (vcpu->vcpu_info->evtchn_upcall_mask)
532 enabling_interrupts = 1;
534 vcpu->vcpu_info->evtchn_upcall_mask = 0;
536 if (enabling_interrupts &&
537 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
538 PSCB(vcpu, pending_interruption) = 1;
539 } else
540 vcpu->vcpu_info->evtchn_upcall_mask = 1;
542 PSCB(vcpu, interrupt_collection_enabled) = vpsr.ic;
543 vcpu_set_metaphysical_mode(vcpu, !(vpsr.dt && vpsr.rt && vpsr.it));
545 newpsr.cpl |= max_t(u64, vpsr.cpl, CONFIG_CPL0_EMUL);
547 if (PSCB(vcpu, banknum) != vpsr.bn) {
548 if (vpsr.bn)
549 vcpu_bsw1(vcpu);
550 else
551 vcpu_bsw0(vcpu);
552 }
553 if (vpsr.pk) {
554 vcpu_pkr_set_psr_handling(vcpu);
555 newpsr.pk = 1;
556 } else
557 vcpu_pkr_use_unset(vcpu);
559 regs->cr_ipsr = newpsr.val;
561 return IA64_NO_FAULT;
562 }
564 u64 vcpu_get_psr(VCPU * vcpu)
565 {
566 REGS *regs = vcpu_regs(vcpu);
567 PSR newpsr;
568 PSR ipsr;
570 ipsr.i64 = regs->cr_ipsr;
572 /* Copy non-virtualized bits. */
573 newpsr.i64 = ipsr.i64 & IA64_PSR_NON_VIRT_BITS;
575 /* Bits forced to 1 (psr.si and psr.is are forced to 0) */
576 newpsr.i64 |= IA64_PSR_DI;
578 /* System mask. */
579 newpsr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled);
580 newpsr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
582 if (!PSCB(vcpu, metaphysical_mode))
583 newpsr.i64 |= IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_IT;
585 newpsr.ia64_psr.dfh = PSCB(vcpu, vpsr_dfh);
586 newpsr.ia64_psr.pp = PSCB(vcpu, vpsr_pp);
588 /* Fool cpl. */
589 if (ipsr.ia64_psr.cpl <= CONFIG_CPL0_EMUL)
590 newpsr.ia64_psr.cpl = 0;
591 else
592 newpsr.ia64_psr.cpl = ipsr.ia64_psr.cpl;
594 newpsr.ia64_psr.bn = PSCB(vcpu, banknum);
596 return newpsr.i64;
597 }
599 IA64FAULT vcpu_get_psr_masked(VCPU * vcpu, u64 * pval)
600 {
601 u64 psr = vcpu_get_psr(vcpu);
602 *pval = psr & (MASK(0, 32) | MASK(35, 2));
603 return IA64_NO_FAULT;
604 }
606 BOOLEAN vcpu_get_psr_ic(VCPU * vcpu)
607 {
608 return !!PSCB(vcpu, interrupt_collection_enabled);
609 }
611 BOOLEAN vcpu_get_psr_i(VCPU * vcpu)
612 {
613 return !vcpu->vcpu_info->evtchn_upcall_mask;
614 }
617 /**************************************************************************
618 VCPU interrupt control register access routines
619 **************************************************************************/
621 void vcpu_pend_unspecified_interrupt(VCPU * vcpu)
622 {
623 PSCB(vcpu, pending_interruption) = 1;
624 }
626 void vcpu_pend_interrupt(VCPU * vcpu, u64 vector)
627 {
628 if (vector & ~0xff) {
629 printk("vcpu_pend_interrupt: bad vector\n");
630 return;
631 }
633 if (vcpu->arch.event_callback_ip) {
634 printk("Deprecated interface. Move to new event based "
635 "solution\n");
636 return;
637 }
639 if (VMX_DOMAIN(vcpu)) {
640 set_bit(vector, VCPU(vcpu, irr));
641 } else {
642 set_bit(vector, PSCBX(vcpu, irr));
643 PSCB(vcpu, pending_interruption) = 1;
644 }
645 }
647 #define IA64_TPR_MMI 0x10000
648 #define IA64_TPR_MIC 0x000f0
650 /* checks to see if a VCPU has any unmasked pending interrupts
651 * if so, returns the highest, else returns SPURIOUS_VECTOR */
652 /* NOTE: Since this gets called from vcpu_get_ivr() and the
653 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
654 * this routine also ignores pscb.interrupt_delivery_enabled
655 * and this must be checked independently; see vcpu_deliverable interrupts() */
656 u64 vcpu_check_pending_interrupts(VCPU * vcpu)
657 {
658 u64 *p, *r, bits, bitnum, mask, i, vector;
660 if (vcpu->arch.event_callback_ip)
661 return SPURIOUS_VECTOR;
663 /* Always check pending event, since guest may just ack the
664 * event injection without handle. Later guest may throw out
665 * the event itself.
666 */
667 check_start:
668 if (event_pending(vcpu) &&
669 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
670 &PSCBX(vcpu, insvc[0])))
671 vcpu_pend_interrupt(vcpu,
672 vcpu->domain->shared_info->arch.
673 evtchn_vector);
675 p = &PSCBX(vcpu, irr[3]);
676 r = &PSCBX(vcpu, insvc[3]);
677 for (i = 3 ;; p--, r--, i--) {
678 bits = *p;
679 if (bits)
680 break; // got a potential interrupt
681 if (*r) {
682 // nothing in this word which is pending+inservice
683 // but there is one inservice which masks lower
684 return SPURIOUS_VECTOR;
685 }
686 if (i == 0) {
687 // checked all bits... nothing pending+inservice
688 return SPURIOUS_VECTOR;
689 }
690 }
691 // have a pending,deliverable interrupt... see if it is masked
692 bitnum = ia64_fls(bits);
693 //printk("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
694 vector = bitnum + (i * 64);
695 mask = 1L << bitnum;
696 /* sanity check for guest timer interrupt */
697 if (vector == (PSCB(vcpu, itv) & 0xff)) {
698 uint64_t now = ia64_get_itc();
699 if (now < PSCBX(vcpu, domain_itm)) {
700 // printk("Ooops, pending guest timer before its due\n");
701 PSCBX(vcpu, irr[i]) &= ~mask;
702 goto check_start;
703 }
704 }
705 //printk("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
706 if (*r >= mask) {
707 // masked by equal inservice
708 //printk("but masked by equal inservice\n");
709 return SPURIOUS_VECTOR;
710 }
711 if (PSCB(vcpu, tpr) & IA64_TPR_MMI) {
712 // tpr.mmi is set
713 //printk("but masked by tpr.mmi\n");
714 return SPURIOUS_VECTOR;
715 }
716 if (((PSCB(vcpu, tpr) & IA64_TPR_MIC) + 15) >= vector) {
717 //tpr.mic masks class
718 //printk("but masked by tpr.mic\n");
719 return SPURIOUS_VECTOR;
720 }
721 //printk("returned to caller\n");
722 return vector;
723 }
725 u64 vcpu_deliverable_interrupts(VCPU * vcpu)
726 {
727 return (vcpu_get_psr_i(vcpu) &&
728 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
729 }
731 u64 vcpu_deliverable_timer(VCPU * vcpu)
732 {
733 return (vcpu_get_psr_i(vcpu) &&
734 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu, itv));
735 }
737 IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval)
738 {
739 /* Use EID=0, ID=vcpu_id. */
740 *pval = vcpu->vcpu_id << 24;
741 return IA64_NO_FAULT;
742 }
744 IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval)
745 {
746 int i;
747 u64 vector, mask;
749 #define HEARTBEAT_FREQ 16 // period in seconds
750 #ifdef HEARTBEAT_FREQ
751 #define N_DOMS 16 // period in seconds
752 #if 0
753 static long count[N_DOMS] = { 0 };
754 #endif
755 static long nonclockcount[N_DOMS] = { 0 };
756 unsigned domid = vcpu->domain->domain_id;
757 #endif
758 #ifdef IRQ_DEBUG
759 static char firstivr = 1;
760 static char firsttime[256];
761 if (firstivr) {
762 int i;
763 for (i = 0; i < 256; i++)
764 firsttime[i] = 1;
765 firstivr = 0;
766 }
767 #endif
769 vector = vcpu_check_pending_interrupts(vcpu);
770 if (vector == SPURIOUS_VECTOR) {
771 PSCB(vcpu, pending_interruption) = 0;
772 *pval = vector;
773 return IA64_NO_FAULT;
774 }
775 #ifdef HEARTBEAT_FREQ
776 if (domid >= N_DOMS)
777 domid = N_DOMS - 1;
778 #if 0
779 if (vector == (PSCB(vcpu, itv) & 0xff)) {
780 if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) {
781 printk("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
782 domid, count[domid], nonclockcount[domid]);
783 //count[domid] = 0;
784 //dump_runq();
785 }
786 }
787 #endif
788 else
789 nonclockcount[domid]++;
790 #endif
791 // now have an unmasked, pending, deliverable vector!
792 // getting ivr has "side effects"
793 #ifdef IRQ_DEBUG
794 if (firsttime[vector]) {
795 printk("*** First get_ivr on vector=%lu,itc=%lx\n",
796 vector, ia64_get_itc());
797 firsttime[vector] = 0;
798 }
799 #endif
800 /* if delivering a timer interrupt, remember domain_itm, which
801 * needs to be done before clearing irr
802 */
803 if (vector == (PSCB(vcpu, itv) & 0xff)) {
804 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
805 }
807 i = vector >> 6;
808 mask = 1L << (vector & 0x3f);
809 //printk("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
810 PSCBX(vcpu, insvc[i]) |= mask;
811 PSCBX(vcpu, irr[i]) &= ~mask;
812 //PSCB(vcpu,pending_interruption)--;
813 *pval = vector;
814 return IA64_NO_FAULT;
815 }
817 IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval)
818 {
819 *pval = PSCB(vcpu, tpr);
820 return IA64_NO_FAULT;
821 }
823 IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval)
824 {
825 *pval = 0L; // reads of eoi always return 0
826 return IA64_NO_FAULT;
827 }
829 IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval)
830 {
831 *pval = PSCBX(vcpu, irr[0]);
832 return IA64_NO_FAULT;
833 }
835 IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval)
836 {
837 *pval = PSCBX(vcpu, irr[1]);
838 return IA64_NO_FAULT;
839 }
841 IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval)
842 {
843 *pval = PSCBX(vcpu, irr[2]);
844 return IA64_NO_FAULT;
845 }
847 IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval)
848 {
849 *pval = PSCBX(vcpu, irr[3]);
850 return IA64_NO_FAULT;
851 }
853 IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval)
854 {
855 *pval = PSCB(vcpu, itv);
856 return IA64_NO_FAULT;
857 }
859 IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval)
860 {
861 *pval = PSCB(vcpu, pmv);
862 return IA64_NO_FAULT;
863 }
865 IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval)
866 {
867 *pval = PSCB(vcpu, cmcv);
868 return IA64_NO_FAULT;
869 }
871 IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval)
872 {
873 // fix this when setting values other than m-bit is supported
874 gdprintk(XENLOG_DEBUG,
875 "vcpu_get_lrr0: Unmasked interrupts unsupported\n");
876 *pval = (1L << 16);
877 return IA64_NO_FAULT;
878 }
880 IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval)
881 {
882 // fix this when setting values other than m-bit is supported
883 gdprintk(XENLOG_DEBUG,
884 "vcpu_get_lrr1: Unmasked interrupts unsupported\n");
885 *pval = (1L << 16);
886 return IA64_NO_FAULT;
887 }
889 IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val)
890 {
891 printk("vcpu_set_lid: Setting cr.lid is unsupported\n");
892 return IA64_ILLOP_FAULT;
893 }
895 IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val)
896 {
897 if (val & 0xff00)
898 return IA64_RSVDREG_FAULT;
899 PSCB(vcpu, tpr) = val;
900 /* This can unmask interrupts. */
901 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
902 PSCB(vcpu, pending_interruption) = 1;
903 return IA64_NO_FAULT;
904 }
906 IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val)
907 {
908 u64 *p, bits, vec, bitnum;
909 int i;
911 p = &PSCBX(vcpu, insvc[3]);
912 for (i = 3; (i >= 0) && !(bits = *p); i--, p--)
913 ;
914 if (i < 0) {
915 printk("Trying to EOI interrupt when none are in-service.\n");
916 return IA64_NO_FAULT;
917 }
918 bitnum = ia64_fls(bits);
919 vec = bitnum + (i * 64);
920 /* clear the correct bit */
921 bits &= ~(1L << bitnum);
922 *p = bits;
923 /* clearing an eoi bit may unmask another pending interrupt... */
924 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
925 // worry about this later... Linux only calls eoi
926 // with interrupts disabled
927 printk("Trying to EOI interrupt with interrupts enabled\n");
928 }
929 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
930 PSCB(vcpu, pending_interruption) = 1;
931 //printk("YYYYY vcpu_set_eoi: Successful\n");
932 return IA64_NO_FAULT;
933 }
935 IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val)
936 {
937 if (!(val & (1L << 16))) {
938 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
939 return IA64_ILLOP_FAULT;
940 }
941 // no place to save this state but nothing to do anyway
942 return IA64_NO_FAULT;
943 }
945 IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val)
946 {
947 if (!(val & (1L << 16))) {
948 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
949 return IA64_ILLOP_FAULT;
950 }
951 // no place to save this state but nothing to do anyway
952 return IA64_NO_FAULT;
953 }
955 IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val)
956 {
957 /* Check reserved fields. */
958 if (val & 0xef00)
959 return IA64_ILLOP_FAULT;
960 PSCB(vcpu, itv) = val;
961 if (val & 0x10000) {
962 /* Disable itm. */
963 PSCBX(vcpu, domain_itm) = 0;
964 } else
965 vcpu_set_next_timer(vcpu);
966 return IA64_NO_FAULT;
967 }
969 IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val)
970 {
971 if (val & 0xef00) /* reserved fields */
972 return IA64_RSVDREG_FAULT;
973 PSCB(vcpu, pmv) = val;
974 return IA64_NO_FAULT;
975 }
977 IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val)
978 {
979 if (val & 0xef00) /* reserved fields */
980 return IA64_RSVDREG_FAULT;
981 PSCB(vcpu, cmcv) = val;
982 return IA64_NO_FAULT;
983 }
985 /**************************************************************************
986 VCPU temporary register access routines
987 **************************************************************************/
988 u64 vcpu_get_tmp(VCPU * vcpu, u64 index)
989 {
990 if (index > 7)
991 return 0;
992 return PSCB(vcpu, tmp[index]);
993 }
995 void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val)
996 {
997 if (index <= 7)
998 PSCB(vcpu, tmp[index]) = val;
999 }
1001 /**************************************************************************
1002 Interval timer routines
1003 **************************************************************************/
1005 BOOLEAN vcpu_timer_disabled(VCPU * vcpu)
1007 u64 itv = PSCB(vcpu, itv);
1008 return (!itv || !!(itv & 0x10000));
1011 BOOLEAN vcpu_timer_inservice(VCPU * vcpu)
1013 u64 itv = PSCB(vcpu, itv);
1014 return test_bit(itv, PSCBX(vcpu, insvc));
1017 BOOLEAN vcpu_timer_expired(VCPU * vcpu)
1019 unsigned long domain_itm = PSCBX(vcpu, domain_itm);
1020 unsigned long now = ia64_get_itc();
1022 if (!domain_itm)
1023 return FALSE;
1024 if (now < domain_itm)
1025 return FALSE;
1026 if (vcpu_timer_disabled(vcpu))
1027 return FALSE;
1028 return TRUE;
1031 void vcpu_safe_set_itm(unsigned long val)
1033 unsigned long epsilon = 100;
1034 unsigned long flags;
1035 u64 now = ia64_get_itc();
1037 local_irq_save(flags);
1038 while (1) {
1039 //printk("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1040 ia64_set_itm(val);
1041 if (val > (now = ia64_get_itc()))
1042 break;
1043 val = now + epsilon;
1044 epsilon <<= 1;
1046 local_irq_restore(flags);
1049 void vcpu_set_next_timer(VCPU * vcpu)
1051 u64 d = PSCBX(vcpu, domain_itm);
1052 //u64 s = PSCBX(vcpu,xen_itm);
1053 u64 s = local_cpu_data->itm_next;
1054 u64 now = ia64_get_itc();
1056 /* gloss over the wraparound problem for now... we know it exists
1057 * but it doesn't matter right now */
1059 if (is_idle_domain(vcpu->domain)) {
1060 // printk("****** vcpu_set_next_timer called during idle!!\n");
1061 vcpu_safe_set_itm(s);
1062 return;
1064 //s = PSCBX(vcpu,xen_itm);
1065 if (d && (d > now) && (d < s)) {
1066 vcpu_safe_set_itm(d);
1067 //using_domain_as_itm++;
1068 } else {
1069 vcpu_safe_set_itm(s);
1070 //using_xen_as_itm++;
1074 IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val)
1076 //UINT now = ia64_get_itc();
1078 //if (val < now) val = now + 1000;
1079 //printk("*** vcpu_set_itm: called with %lx\n",val);
1080 PSCBX(vcpu, domain_itm) = val;
1081 vcpu_set_next_timer(vcpu);
1082 return IA64_NO_FAULT;
1085 IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val)
1087 #define DISALLOW_SETTING_ITC_FOR_NOW
1088 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1089 static int did_print;
1090 if (!did_print) {
1091 printk("vcpu_set_itc: Setting ar.itc is currently disabled "
1092 "(this message is only displayed once)\n");
1093 did_print = 1;
1095 #else
1096 u64 oldnow = ia64_get_itc();
1097 u64 olditm = PSCBX(vcpu, domain_itm);
1098 unsigned long d = olditm - oldnow;
1099 unsigned long x = local_cpu_data->itm_next - oldnow;
1101 u64 newnow = val, min_delta;
1103 local_irq_disable();
1104 if (olditm) {
1105 printk("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val,
1106 newnow + d);
1107 PSCBX(vcpu, domain_itm) = newnow + d;
1109 local_cpu_data->itm_next = newnow + x;
1110 d = PSCBX(vcpu, domain_itm);
1111 x = local_cpu_data->itm_next;
1113 ia64_set_itc(newnow);
1114 if (d && (d > newnow) && (d < x)) {
1115 vcpu_safe_set_itm(d);
1116 //using_domain_as_itm++;
1117 } else {
1118 vcpu_safe_set_itm(x);
1119 //using_xen_as_itm++;
1121 local_irq_enable();
1122 #endif
1123 return IA64_NO_FAULT;
1126 IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval)
1128 //FIXME: Implement this
1129 printk("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1130 return IA64_NO_FAULT;
1131 //return IA64_ILLOP_FAULT;
1134 IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval)
1136 //TODO: Implement this
1137 printk("vcpu_get_itc: Getting ar.itc is unsupported\n");
1138 return IA64_ILLOP_FAULT;
1141 void vcpu_pend_timer(VCPU * vcpu)
1143 u64 itv = PSCB(vcpu, itv) & 0xff;
1145 if (vcpu_timer_disabled(vcpu))
1146 return;
1147 //if (vcpu_timer_inservice(vcpu)) return;
1148 if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) {
1149 // already delivered an interrupt for this so
1150 // don't deliver another
1151 return;
1153 if (vcpu->arch.event_callback_ip) {
1154 /* A small window may occur when injecting vIRQ while related
1155 * handler has not been registered. Don't fire in such case.
1156 */
1157 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1158 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1159 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1161 } else
1162 vcpu_pend_interrupt(vcpu, itv);
1165 // returns true if ready to deliver a timer interrupt too early
1166 u64 vcpu_timer_pending_early(VCPU * vcpu)
1168 u64 now = ia64_get_itc();
1169 u64 itm = PSCBX(vcpu, domain_itm);
1171 if (vcpu_timer_disabled(vcpu))
1172 return 0;
1173 if (!itm)
1174 return 0;
1175 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1178 /**************************************************************************
1179 Privileged operation emulation routines
1180 **************************************************************************/
1182 static void vcpu_force_tlb_miss(VCPU * vcpu, u64 ifa)
1184 PSCB(vcpu, ifa) = ifa;
1185 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1186 vcpu_thash(current, ifa, &PSCB(current, iha));
1189 IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa)
1191 vcpu_force_tlb_miss(vcpu, ifa);
1192 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_INST_TLB_VECTOR :
1193 IA64_ALT_INST_TLB_VECTOR;
1196 IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa)
1198 vcpu_force_tlb_miss(vcpu, ifa);
1199 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_DATA_TLB_VECTOR :
1200 IA64_ALT_DATA_TLB_VECTOR;
1203 IA64FAULT vcpu_rfi(VCPU * vcpu)
1205 u64 ifs;
1206 REGS *regs = vcpu_regs(vcpu);
1208 vcpu_set_psr(vcpu, PSCB(vcpu, ipsr));
1210 ifs = PSCB(vcpu, ifs);
1211 if (ifs & 0x8000000000000000UL)
1212 regs->cr_ifs = ifs;
1214 regs->cr_iip = PSCB(vcpu, iip);
1216 return IA64_NO_FAULT;
1219 IA64FAULT vcpu_cover(VCPU * vcpu)
1221 // TODO: Only allowed for current vcpu
1222 REGS *regs = vcpu_regs(vcpu);
1224 if (!PSCB(vcpu, interrupt_collection_enabled)) {
1225 PSCB(vcpu, ifs) = regs->cr_ifs;
1227 regs->cr_ifs = 0;
1228 return IA64_NO_FAULT;
1231 IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval)
1233 u64 pta = PSCB(vcpu, pta);
1234 u64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1235 u64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT) - 1);
1236 u64 Mask = (1L << pta_sz) - 1;
1237 u64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1238 u64 compMask_60_15 = ~Mask_60_15;
1239 u64 rr_ps = vcpu_get_rr_ps(vcpu, vadr);
1240 u64 VHPT_offset = (vadr >> rr_ps) << 3;
1241 u64 VHPT_addr1 = vadr & 0xe000000000000000L;
1242 u64 VHPT_addr2a =
1243 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1244 u64 VHPT_addr2b =
1245 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1246 u64 VHPT_addr3 = VHPT_offset & 0x7fff;
1247 u64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1248 VHPT_addr3;
1250 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1251 *pval = VHPT_addr;
1252 return IA64_NO_FAULT;
1255 IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr)
1257 printk("vcpu_ttag: ttag instruction unsupported\n");
1258 return IA64_ILLOP_FAULT;
1261 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1263 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1264 static inline int range_overlap(u64 b1, u64 e1, u64 b2, u64 e2)
1266 return (b1 <= e2) && (e1 >= b2);
1269 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1270 Note: LSBs of base inside page_size are ignored. */
1271 static inline void
1272 check_xen_space_overlap(const char *func, u64 base, u64 page_size)
1274 /* Overlaps can occur only in region 7.
1275 (This is an optimization to bypass all the checks). */
1276 if (REGION_NUMBER(base) != 7)
1277 return;
1279 /* Mask LSBs of base. */
1280 base &= ~(page_size - 1);
1282 /* FIXME: ideally an MCA should be generated... */
1283 if (range_overlap(HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
1284 base, base + page_size)
1285 || range_overlap(current->domain->arch.shared_info_va,
1286 current->domain->arch.shared_info_va
1287 + XSI_SIZE + XMAPPEDREGS_SIZE,
1288 base, base + page_size))
1289 panic_domain(NULL, "%s on Xen virtual space (%lx)\n",
1290 func, base);
1293 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1294 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY * trp, u64 ifa,
1295 u64 rid)
1297 return trp->rid == rid
1298 && ifa >= trp->vadr && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1301 static inline int vcpu_match_tr_entry(TR_ENTRY * trp, u64 ifa, u64 rid)
1303 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1306 static inline int
1307 vcpu_match_tr_entry_range(TR_ENTRY * trp, u64 rid, u64 b, u64 e)
1309 return trp->rid == rid
1310 && trp->pte.p
1311 && range_overlap(b, e, trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1315 static TR_ENTRY *vcpu_tr_lookup(VCPU * vcpu, unsigned long va, u64 rid,
1316 BOOLEAN is_data)
1318 unsigned char *regions;
1319 TR_ENTRY *trp;
1320 int tr_max;
1321 int i;
1323 if (is_data) {
1324 // data
1325 regions = &vcpu->arch.dtr_regions;
1326 trp = vcpu->arch.dtrs;
1327 tr_max = sizeof(vcpu->arch.dtrs) / sizeof(vcpu->arch.dtrs[0]);
1328 } else {
1329 // instruction
1330 regions = &vcpu->arch.itr_regions;
1331 trp = vcpu->arch.itrs;
1332 tr_max = sizeof(vcpu->arch.itrs) / sizeof(vcpu->arch.itrs[0]);
1335 if (!vcpu_quick_region_check(*regions, va)) {
1336 return NULL;
1338 for (i = 0; i < tr_max; i++, trp++) {
1339 if (vcpu_match_tr_entry(trp, va, rid)) {
1340 return trp;
1343 return NULL;
1346 // return value
1347 // 0: failure
1348 // 1: success
1349 int
1350 vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
1351 IA64_BUNDLE * bundle)
1353 u64 gpip; // guest pseudo phyiscal ip
1354 unsigned long vaddr;
1355 struct page_info *page;
1357 again:
1358 #if 0
1359 // Currently xen doesn't track psr.it bits.
1360 // it assumes always psr.it = 1.
1361 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1362 gpip = gip;
1363 } else
1364 #endif
1366 unsigned long region = REGION_NUMBER(gip);
1367 unsigned long rr = PSCB(vcpu, rrs)[region];
1368 unsigned long rid = rr & RR_RID_MASK;
1369 BOOLEAN swap_rr0;
1370 TR_ENTRY *trp;
1372 // vcpu->arch.{i, d}tlb are volatile,
1373 // copy its value to the variable, tr, before use.
1374 TR_ENTRY tr;
1376 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1377 if (trp != NULL) {
1378 tr = *trp;
1379 goto found;
1381 // When it failed to get a bundle, itlb miss is reflected.
1382 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1383 tr = PSCBX(vcpu, itlb);
1384 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1385 //dprintk(XENLOG_WARNING,
1386 // "%s gip 0x%lx gpip 0x%lx\n", __func__,
1387 // gip, gpip);
1388 goto found;
1390 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1391 if (trp != NULL) {
1392 tr = *trp;
1393 goto found;
1395 #if 0
1396 tr = PSCBX(vcpu, dtlb);
1397 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1398 goto found;
1400 #endif
1402 // try to access gip with guest virtual address
1403 // This may cause tlb miss. see vcpu_translate(). Be careful!
1404 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1405 if (swap_rr0) {
1406 set_virtual_rr0();
1408 *bundle = __get_domain_bundle(gip);
1409 if (swap_rr0) {
1410 set_metaphysical_rr0();
1412 if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
1413 dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
1414 return 0;
1416 return 1;
1418 found:
1419 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1420 (gip & ((1 << tr.ps) - 1));
1423 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1424 page = virt_to_page(vaddr);
1425 if (get_page(page, vcpu->domain) == 0) {
1426 if (page_get_owner(page) != vcpu->domain) {
1427 // This page might be a page granted by another
1428 // domain.
1429 panic_domain(regs, "domain tries to execute foreign "
1430 "domain page which might be mapped by "
1431 "grant table.\n");
1433 goto again;
1435 *bundle = *((IA64_BUNDLE *) vaddr);
1436 put_page(page);
1437 return 1;
1440 IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
1441 u64 * pteval, u64 * itir, u64 * iha)
1443 unsigned long region = REGION_NUMBER(address);
1444 unsigned long pta, rid, rr, key = 0;
1445 union pte_flags pte;
1446 TR_ENTRY *trp;
1448 if (PSCB(vcpu, metaphysical_mode) && !(!is_data && region)) {
1449 // dom0 may generate an uncacheable physical address (msb=1)
1450 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1451 // FIXME: This seems to happen even though it shouldn't. Need to track
1452 // this down, but since it has been apparently harmless, just flag it for now
1453 // panic_domain(vcpu_regs(vcpu),
1455 /*
1456 * Guest may execute itc.d and rfi with psr.dt=0
1457 * When VMM try to fetch opcode, tlb miss may happen,
1458 * At this time PSCB(vcpu,metaphysical_mode)=1,
1459 * region=5,VMM need to handle this tlb miss as if
1460 * PSCB(vcpu,metaphysical_mode)=0
1461 */
1462 printk("vcpu_translate: bad physical address: 0x%lx "
1463 "at %lx\n", address, vcpu_regs(vcpu)->cr_iip);
1465 } else {
1466 *pteval = (address & _PAGE_PPN_MASK) |
1467 __DIRTY_BITS | _PAGE_PL_PRIV | _PAGE_AR_RWX;
1468 *itir = vcpu->arch.vhpt_pg_shift << 2;
1469 perfc_incr(phys_translate);
1470 return IA64_NO_FAULT;
1472 } else if (!region && warn_region0_address) {
1473 REGS *regs = vcpu_regs(vcpu);
1474 unsigned long viip = PSCB(vcpu, iip);
1475 unsigned long vipsr = PSCB(vcpu, ipsr);
1476 unsigned long iip = regs->cr_iip;
1477 unsigned long ipsr = regs->cr_ipsr;
1478 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, "
1479 "vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1480 address, viip, vipsr, iip, ipsr);
1483 rr = PSCB(vcpu, rrs)[region];
1484 rid = rr & RR_RID_MASK;
1485 if (is_data) {
1486 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1487 if (trp != NULL) {
1488 *pteval = trp->pte.val;
1489 *itir = trp->itir;
1490 perfc_incr(tr_translate);
1491 return IA64_NO_FAULT;
1494 // FIXME?: check itr's for data accesses too, else bad things happen?
1495 /* else */ {
1496 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1497 if (trp != NULL) {
1498 *pteval = trp->pte.val;
1499 *itir = trp->itir;
1500 perfc_incr(tr_translate);
1501 return IA64_NO_FAULT;
1505 /* check 1-entry TLB */
1506 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1507 trp = &vcpu->arch.dtlb;
1508 pte = trp->pte;
1509 if ( /* is_data && */ pte.p
1510 && vcpu_match_tr_entry_no_p(trp, address, rid)) {
1511 *pteval = pte.val;
1512 *itir = trp->itir;
1513 perfc_incr(dtlb_translate);
1514 return IA64_USE_TLB;
1517 /* check guest VHPT */
1518 pta = PSCB(vcpu, pta);
1520 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1521 // note: architecturally, iha is optionally set for alt faults but
1522 // xenlinux depends on it so should document it as part of PV interface
1523 vcpu_thash(vcpu, address, iha);
1524 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE)) {
1525 REGS *regs = vcpu_regs(vcpu);
1526 struct opt_feature* optf = &(vcpu->domain->arch.opt_feature);
1528 /* Optimization for identity mapped region 7 OS (linux) */
1529 if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG7_FLG &&
1530 region == 7 && ia64_psr(regs)->cpl == CONFIG_CPL0_EMUL &&
1531 REGION_OFFSET(address) < _PAGE_PPN_MASK) {
1532 pte.val = address & _PAGE_PPN_MASK;
1533 pte.val = pte.val | optf->im_reg7.pgprot;
1534 key = optf->im_reg7.key;
1535 goto out;
1537 return is_data ? IA64_ALT_DATA_TLB_VECTOR :
1538 IA64_ALT_INST_TLB_VECTOR;
1541 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1542 /*
1543 * minimal support: vhpt walker is really dumb and won't find
1544 * anything
1545 */
1546 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1548 /* avoid recursively walking (short format) VHPT */
1549 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1550 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1552 if (!__access_ok(*iha)
1553 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1554 // virtual VHPT walker "missed" in TLB
1555 return IA64_VHPT_FAULT;
1557 /*
1558 * Optimisation: this VHPT walker aborts on not-present pages
1559 * instead of inserting a not-present translation, this allows
1560 * vectoring directly to the miss handler.
1561 */
1562 if (!pte.p)
1563 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1565 /* found mapping in guest VHPT! */
1566 out:
1567 *itir = (rr & RR_PS_MASK) | (key << IA64_ITIR_KEY);
1568 *pteval = pte.val;
1569 perfc_incr(vhpt_translate);
1570 return IA64_NO_FAULT;
1573 IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr)
1575 u64 pteval, itir, mask, iha;
1576 IA64FAULT fault;
1578 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1579 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
1580 mask = itir_mask(itir);
1581 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1582 return IA64_NO_FAULT;
1584 return vcpu_force_data_miss(vcpu, vadr);
1587 IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
1589 u64 pteval, itir, iha;
1590 IA64FAULT fault;
1592 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1593 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB)
1594 *key = itir & IA64_ITIR_KEY_MASK;
1595 else
1596 *key = 1;
1598 return IA64_NO_FAULT;
1601 /**************************************************************************
1602 VCPU debug breakpoint register access routines
1603 **************************************************************************/
1605 IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
1607 if (reg >= IA64_NUM_DBG_REGS)
1608 return IA64_RSVDREG_FAULT;
1609 if ((reg & 1) == 0) {
1610 /* Validate address. */
1611 if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END)
1612 return IA64_ILLOP_FAULT;
1613 } else {
1614 if (!VMX_DOMAIN(vcpu)) {
1615 /* Mask PL0. */
1616 val &= ~(1UL << 56);
1619 if (val != 0)
1620 vcpu->arch.dbg_used |= (1 << reg);
1621 else
1622 vcpu->arch.dbg_used &= ~(1 << reg);
1623 vcpu->arch.dbr[reg] = val;
1624 if (vcpu == current)
1625 ia64_set_dbr(reg, val);
1626 return IA64_NO_FAULT;
1629 IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
1631 if (reg >= IA64_NUM_DBG_REGS)
1632 return IA64_RSVDREG_FAULT;
1633 if ((reg & 1) == 0) {
1634 /* Validate address. */
1635 if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END)
1636 return IA64_ILLOP_FAULT;
1637 } else {
1638 if (!VMX_DOMAIN(vcpu)) {
1639 /* Mask PL0. */
1640 val &= ~(1UL << 56);
1643 if (val != 0)
1644 vcpu->arch.dbg_used |= (1 << (reg + IA64_NUM_DBG_REGS));
1645 else
1646 vcpu->arch.dbg_used &= ~(1 << (reg + IA64_NUM_DBG_REGS));
1647 vcpu->arch.ibr[reg] = val;
1648 if (vcpu == current)
1649 ia64_set_ibr(reg, val);
1650 return IA64_NO_FAULT;
1653 IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
1655 if (reg >= IA64_NUM_DBG_REGS)
1656 return IA64_RSVDREG_FAULT;
1657 *pval = vcpu->arch.dbr[reg];
1658 return IA64_NO_FAULT;
1661 IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
1663 if (reg >= IA64_NUM_DBG_REGS)
1664 return IA64_RSVDREG_FAULT;
1665 *pval = vcpu->arch.ibr[reg];
1666 return IA64_NO_FAULT;
1669 /**************************************************************************
1670 VCPU performance monitor register access routines
1671 **************************************************************************/
1673 IA64FAULT vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val)
1675 // TODO: Should set Logical CPU state, not just physical
1676 // NOTE: Writes to unimplemented PMC registers are discarded
1677 #ifdef DEBUG_PFMON
1678 printk("vcpu_set_pmc(%x,%lx)\n", reg, val);
1679 #endif
1680 ia64_set_pmc(reg, val);
1681 return IA64_NO_FAULT;
1684 IA64FAULT vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val)
1686 // TODO: Should set Logical CPU state, not just physical
1687 // NOTE: Writes to unimplemented PMD registers are discarded
1688 #ifdef DEBUG_PFMON
1689 printk("vcpu_set_pmd(%x,%lx)\n", reg, val);
1690 #endif
1691 ia64_set_pmd(reg, val);
1692 return IA64_NO_FAULT;
1695 IA64FAULT vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval)
1697 // NOTE: Reads from unimplemented PMC registers return zero
1698 u64 val = (u64) ia64_get_pmc(reg);
1699 #ifdef DEBUG_PFMON
1700 printk("%lx=vcpu_get_pmc(%x)\n", val, reg);
1701 #endif
1702 *pval = val;
1703 return IA64_NO_FAULT;
1706 IA64FAULT vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval)
1708 // NOTE: Reads from unimplemented PMD registers return zero
1709 u64 val = (u64) ia64_get_pmd(reg);
1710 #ifdef DEBUG_PFMON
1711 printk("%lx=vcpu_get_pmd(%x)\n", val, reg);
1712 #endif
1713 *pval = val;
1714 return IA64_NO_FAULT;
1717 /**************************************************************************
1718 VCPU banked general register access routines
1719 **************************************************************************/
1720 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1721 do{ \
1722 __asm__ __volatile__ ( \
1723 ";;extr.u %0 = %3,%6,16;;\n" \
1724 "dep %1 = %0, %1, 0, 16;;\n" \
1725 "st8 [%4] = %1\n" \
1726 "extr.u %0 = %2, 16, 16;;\n" \
1727 "dep %3 = %0, %3, %6, 16;;\n" \
1728 "st8 [%5] = %3\n" \
1729 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1730 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1731 }while(0)
1733 IA64FAULT vcpu_bsw0(VCPU * vcpu)
1735 // TODO: Only allowed for current vcpu
1736 REGS *regs = vcpu_regs(vcpu);
1737 unsigned long *r = &regs->r16;
1738 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1739 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1740 unsigned long *runat = &regs->eml_unat;
1741 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1742 unsigned long *b1unat = &PSCB(vcpu, vnat);
1744 unsigned long i;
1746 if (VMX_DOMAIN(vcpu)) {
1747 if (VCPU(vcpu, vpsr) & IA64_PSR_BN) {
1748 for (i = 0; i < 16; i++) {
1749 *b1++ = *r;
1750 *r++ = *b0++;
1752 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1753 IA64_PT_REGS_R16_SLOT);
1754 VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
1756 } else {
1757 if (PSCB(vcpu, banknum)) {
1758 for (i = 0; i < 16; i++) {
1759 *b1++ = *r;
1760 *r++ = *b0++;
1762 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1763 IA64_PT_REGS_R16_SLOT);
1764 PSCB(vcpu, banknum) = 0;
1767 return IA64_NO_FAULT;
1770 #define vcpu_bsw1_unat(i, b0unat, b1unat, runat, IA64_PT_REGS_R16_SLOT) \
1771 do { \
1772 __asm__ __volatile__ (";;extr.u %0 = %3,%6,16;;\n" \
1773 "dep %1 = %0, %1, 16, 16;;\n" \
1774 "st8 [%4] = %1\n" \
1775 "extr.u %0 = %2, 0, 16;;\n" \
1776 "dep %3 = %0, %3, %6, 16;;\n" \
1777 "st8 [%5] = %3\n" \
1778 ::"r"(i), "r"(*b0unat), "r"(*b1unat), \
1779 "r"(*runat), "r"(b0unat), "r"(runat), \
1780 "i"(IA64_PT_REGS_R16_SLOT): "memory"); \
1781 } while(0)
1783 IA64FAULT vcpu_bsw1(VCPU * vcpu)
1785 // TODO: Only allowed for current vcpu
1786 REGS *regs = vcpu_regs(vcpu);
1787 unsigned long *r = &regs->r16;
1788 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1789 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1790 unsigned long *runat = &regs->eml_unat;
1791 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1792 unsigned long *b1unat = &PSCB(vcpu, vnat);
1794 unsigned long i;
1796 if (VMX_DOMAIN(vcpu)) {
1797 if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
1798 for (i = 0; i < 16; i++) {
1799 *b0++ = *r;
1800 *r++ = *b1++;
1802 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1803 IA64_PT_REGS_R16_SLOT);
1804 VCPU(vcpu, vpsr) |= IA64_PSR_BN;
1806 } else {
1807 if (!PSCB(vcpu, banknum)) {
1808 for (i = 0; i < 16; i++) {
1809 *b0++ = *r;
1810 *r++ = *b1++;
1812 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1813 IA64_PT_REGS_R16_SLOT);
1814 PSCB(vcpu, banknum) = 1;
1817 return IA64_NO_FAULT;
1820 /**************************************************************************
1821 VCPU cpuid access routines
1822 **************************************************************************/
1824 IA64FAULT vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval)
1826 // FIXME: This could get called as a result of a rsvd-reg fault
1827 // if reg > 3
1828 switch (reg) {
1829 case 0:
1830 memcpy(pval, "Xen/ia64", 8);
1831 break;
1832 case 1:
1833 *pval = 0;
1834 break;
1835 case 2:
1836 *pval = 0;
1837 break;
1838 case 3:
1839 *pval = ia64_get_cpuid(3);
1840 break;
1841 case 4:
1842 *pval = ia64_get_cpuid(4);
1843 break;
1844 default:
1845 if (reg > (ia64_get_cpuid(3) & 0xff))
1846 return IA64_RSVDREG_FAULT;
1847 *pval = ia64_get_cpuid(reg);
1848 break;
1850 return IA64_NO_FAULT;
1853 /**************************************************************************
1854 VCPU region register access routines
1855 **************************************************************************/
1857 unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
1859 ia64_rr rr;
1861 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
1862 return rr.ve;
1865 IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val)
1867 if (unlikely(is_reserved_rr_field(vcpu, val))) {
1868 gdprintk(XENLOG_DEBUG, "use of invalid rrval %lx\n", val);
1869 return IA64_RSVDREG_FAULT;
1872 PSCB(vcpu, rrs)[reg >> 61] = val;
1873 if (likely(vcpu == current)) {
1874 int rc = set_one_rr(reg, val);
1875 BUG_ON(rc == 0);
1877 return IA64_NO_FAULT;
1880 IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval)
1882 if (VMX_DOMAIN(vcpu))
1883 *pval = VMX(vcpu, vrr[reg >> 61]);
1884 else
1885 *pval = PSCB(vcpu, rrs)[reg >> 61];
1887 return IA64_NO_FAULT;
1890 IA64FAULT vcpu_set_rr0_to_rr4(VCPU * vcpu, u64 val0, u64 val1, u64 val2,
1891 u64 val3, u64 val4)
1893 u64 reg0 = 0x0000000000000000UL;
1894 u64 reg1 = 0x2000000000000000UL;
1895 u64 reg2 = 0x4000000000000000UL;
1896 u64 reg3 = 0x6000000000000000UL;
1897 u64 reg4 = 0x8000000000000000UL;
1899 if (unlikely(is_reserved_rr_field(vcpu, val0) ||
1900 is_reserved_rr_field(vcpu, val1) ||
1901 is_reserved_rr_field(vcpu, val2) ||
1902 is_reserved_rr_field(vcpu, val3) ||
1903 is_reserved_rr_field(vcpu, val4))) {
1904 gdprintk(XENLOG_DEBUG,
1905 "use of invalid rrval %lx %lx %lx %lx %lx\n",
1906 val0, val1, val2, val3, val4);
1907 return IA64_RSVDREG_FAULT;
1910 PSCB(vcpu, rrs)[reg0 >> 61] = val0;
1911 PSCB(vcpu, rrs)[reg1 >> 61] = val1;
1912 PSCB(vcpu, rrs)[reg2 >> 61] = val2;
1913 PSCB(vcpu, rrs)[reg3 >> 61] = val3;
1914 PSCB(vcpu, rrs)[reg4 >> 61] = val4;
1915 if (likely(vcpu == current)) {
1916 int rc;
1917 rc = !set_one_rr(reg0, val0);
1918 rc |= !set_one_rr(reg1, val1);
1919 rc |= !set_one_rr(reg2, val2);
1920 rc |= !set_one_rr(reg3, val3);
1921 rc |= !set_one_rr(reg4, val4);
1922 BUG_ON(rc != 0);
1924 return IA64_NO_FAULT;
1927 /**************************************************************************
1928 VCPU protection key register access routines
1929 **************************************************************************/
1931 IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
1933 if (reg > XEN_IA64_NPKRS)
1934 return IA64_RSVDREG_FAULT; /* register index to large */
1936 *pval = (u64) PSCBX(vcpu, pkrs[reg]);
1937 return IA64_NO_FAULT;
1940 IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
1942 ia64_pkr_t pkr_new;
1944 if (reg >= XEN_IA64_NPKRS)
1945 return IA64_RSVDREG_FAULT; /* index to large */
1947 pkr_new.val = val;
1948 if (pkr_new.reserved1)
1949 return IA64_RSVDREG_FAULT; /* reserved field */
1951 if (pkr_new.reserved2)
1952 return IA64_RSVDREG_FAULT; /* reserved field */
1954 PSCBX(vcpu, pkrs[reg]) = pkr_new.val;
1955 ia64_set_pkr(reg, pkr_new.val);
1957 return IA64_NO_FAULT;
1960 /**************************************************************************
1961 VCPU translation register access routines
1962 **************************************************************************/
1964 static void
1965 vcpu_set_tr_entry_rid(TR_ENTRY * trp, u64 pte,
1966 u64 itir, u64 ifa, u64 rid)
1968 u64 ps;
1969 union pte_flags new_pte;
1971 trp->itir = itir;
1972 trp->rid = rid;
1973 ps = trp->ps;
1974 new_pte.val = pte;
1975 if (new_pte.pl < CONFIG_CPL0_EMUL)
1976 new_pte.pl = CONFIG_CPL0_EMUL;
1977 trp->vadr = ifa & ~0xfff;
1978 if (ps > 12) { // "ignore" relevant low-order bits
1979 new_pte.ppn &= ~((1UL << (ps - 12)) - 1);
1980 trp->vadr &= ~((1UL << ps) - 1);
1983 /* Atomic write. */
1984 trp->pte.val = new_pte.val;
1987 static inline void
1988 vcpu_set_tr_entry(TR_ENTRY * trp, u64 pte, u64 itir, u64 ifa)
1990 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
1991 VCPU(current, rrs[ifa >> 61]) & RR_RID_MASK);
1994 IA64FAULT vcpu_itr_d(VCPU * vcpu, u64 slot, u64 pte,
1995 u64 itir, u64 ifa)
1997 TR_ENTRY *trp;
1999 if (slot >= NDTRS)
2000 return IA64_RSVDREG_FAULT;
2002 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2004 trp = &PSCBX(vcpu, dtrs[slot]);
2005 //printk("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
2006 vcpu_set_tr_entry(trp, pte, itir, ifa);
2007 vcpu_quick_region_set(PSCBX(vcpu, dtr_regions), ifa);
2009 /*
2010 * FIXME According to spec, vhpt should be purged, but this
2011 * incurs considerable performance loss, since it is safe for
2012 * linux not to purge vhpt, vhpt purge is disabled until a
2013 * feasible way is found.
2015 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2016 */
2018 return IA64_NO_FAULT;
2021 IA64FAULT vcpu_itr_i(VCPU * vcpu, u64 slot, u64 pte,
2022 u64 itir, u64 ifa)
2024 TR_ENTRY *trp;
2026 if (slot >= NITRS)
2027 return IA64_RSVDREG_FAULT;
2029 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2031 trp = &PSCBX(vcpu, itrs[slot]);
2032 //printk("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
2033 vcpu_set_tr_entry(trp, pte, itir, ifa);
2034 vcpu_quick_region_set(PSCBX(vcpu, itr_regions), ifa);
2036 /*
2037 * FIXME According to spec, vhpt should be purged, but this
2038 * incurs considerable performance loss, since it is safe for
2039 * linux not to purge vhpt, vhpt purge is disabled until a
2040 * feasible way is found.
2042 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2043 */
2045 return IA64_NO_FAULT;
2048 IA64FAULT vcpu_set_itr(VCPU * vcpu, u64 slot, u64 pte,
2049 u64 itir, u64 ifa, u64 rid)
2051 TR_ENTRY *trp;
2053 if (slot >= NITRS)
2054 return IA64_RSVDREG_FAULT;
2055 trp = &PSCBX(vcpu, itrs[slot]);
2056 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2058 /* Recompute the itr_region. */
2059 vcpu->arch.itr_regions = 0;
2060 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
2061 if (trp->pte.p)
2062 vcpu_quick_region_set(vcpu->arch.itr_regions,
2063 trp->vadr);
2064 return IA64_NO_FAULT;
2067 IA64FAULT vcpu_set_dtr(VCPU * vcpu, u64 slot, u64 pte,
2068 u64 itir, u64 ifa, u64 rid)
2070 TR_ENTRY *trp;
2072 if (slot >= NDTRS)
2073 return IA64_RSVDREG_FAULT;
2074 trp = &PSCBX(vcpu, dtrs[slot]);
2075 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2077 /* Recompute the dtr_region. */
2078 vcpu->arch.dtr_regions = 0;
2079 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
2080 if (trp->pte.p)
2081 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2082 trp->vadr);
2083 return IA64_NO_FAULT;
2086 /**************************************************************************
2087 VCPU translation cache access routines
2088 **************************************************************************/
2090 static void
2091 vcpu_rebuild_vhpt(VCPU * vcpu, u64 ps)
2093 #ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
2094 printk("vhpt rebuild: using page_shift %d\n", (int)ps);
2095 vcpu->arch.vhpt_pg_shift = ps;
2096 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2097 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2098 local_vhpt_flush();
2099 load_region_regs(vcpu);
2100 #else
2101 panic_domain(NULL, "domain trying to use smaller page size!\n");
2102 #endif
2105 void
2106 vcpu_itc_no_srlz(VCPU * vcpu, u64 IorD, u64 vaddr, u64 pte,
2107 u64 mp_pte, u64 itir, struct p2m_entry *entry)
2109 ia64_itir_t _itir = {.itir = itir};
2110 unsigned long psr;
2112 check_xen_space_overlap("itc", vaddr, 1UL << _itir.ps);
2114 // FIXME, must be inlined or potential for nested fault here!
2115 if ((vcpu->domain == dom0) && (_itir.ps < PAGE_SHIFT))
2116 panic_domain(NULL, "vcpu_itc_no_srlz: domain trying to use "
2117 "smaller page size!\n");
2119 BUG_ON(_itir.ps > PAGE_SHIFT);
2120 vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry);
2121 psr = ia64_clear_ic();
2122 pte &= ~(_PAGE_RV2 | _PAGE_RV1); // Mask out the reserved bits.
2123 // FIXME: look for bigger mappings
2124 ia64_itc(IorD, vaddr, pte, _itir.itir);
2125 ia64_set_psr(psr);
2126 // ia64_srlz_i(); // no srls req'd, will rfi later
2127 if (vcpu->domain == dom0 && ((vaddr >> 61) == 7)) {
2128 // FIXME: this is dangerous... vhpt_flush_address ensures these
2129 // addresses never get flushed. More work needed if this
2130 // ever happens.
2131 //printk("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2132 if (_itir.ps > vcpu->arch.vhpt_pg_shift)
2133 vhpt_multiple_insert(vaddr, pte, _itir.itir);
2134 else
2135 vhpt_insert(vaddr, pte, _itir.itir);
2137 // even if domain pagesize is larger than PAGE_SIZE, just put
2138 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2139 else {
2140 vhpt_insert(vaddr, pte, _itir.itir);
2144 IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2146 unsigned long pteval;
2147 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2148 struct p2m_entry entry;
2149 ia64_itir_t _itir = {.itir = itir};
2151 if (_itir.ps < vcpu->arch.vhpt_pg_shift)
2152 vcpu_rebuild_vhpt(vcpu, _itir.ps);
2154 again:
2155 //itir = (itir & ~0xfc) | (vcpu->arch.vhpt_pg_shift<<2); // ign dom pgsz
2156 pteval = translate_domain_pte(pte, ifa, itir, &(_itir.itir), &entry);
2157 if (!pteval)
2158 return IA64_ILLOP_FAULT;
2159 if (swap_rr0)
2160 set_virtual_rr0();
2161 vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, _itir.itir, &entry);
2162 if (swap_rr0)
2163 set_metaphysical_rr0();
2164 if (p2m_entry_retry(&entry)) {
2165 vcpu_flush_tlb_vhpt_range(ifa, _itir.ps);
2166 goto again;
2168 vcpu_set_tr_entry(&PSCBX(vcpu, dtlb), pte, itir, ifa);
2169 return IA64_NO_FAULT;
2172 IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2174 unsigned long pteval;
2175 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2176 struct p2m_entry entry;
2177 ia64_itir_t _itir = {.itir = itir};
2179 if (_itir.ps < vcpu->arch.vhpt_pg_shift)
2180 vcpu_rebuild_vhpt(vcpu, _itir.ps);
2182 again:
2183 //itir = (itir & ~0xfc) | (vcpu->arch.vhpt_pg_shift<<2); // ign dom pgsz
2184 pteval = translate_domain_pte(pte, ifa, itir, &(_itir.itir), &entry);
2185 if (!pteval)
2186 return IA64_ILLOP_FAULT;
2187 if (swap_rr0)
2188 set_virtual_rr0();
2189 vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, _itir.itir, &entry);
2190 if (swap_rr0)
2191 set_metaphysical_rr0();
2192 if (p2m_entry_retry(&entry)) {
2193 vcpu_flush_tlb_vhpt_range(ifa, _itir.ps);
2194 goto again;
2196 vcpu_set_tr_entry(&PSCBX(vcpu, itlb), pte, itir, ifa);
2197 return IA64_NO_FAULT;
2200 IA64FAULT vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 log_range)
2202 BUG_ON(vcpu != current);
2204 check_xen_space_overlap("ptc_l", vadr, 1UL << log_range);
2206 /* Purge TC */
2207 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2208 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2210 /* Purge all tlb and vhpt */
2211 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2213 return IA64_NO_FAULT;
2216 // At privlvl=0, fc performs no access rights or protection key checks, while
2217 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2218 // read but no protection key check. Thus in order to avoid an unexpected
2219 // access rights fault, we have to translate the virtual address to a
2220 // physical address (possibly via a metaphysical address) and do the fc
2221 // on the physical address, which is guaranteed to flush the same cache line
2222 IA64FAULT vcpu_fc(VCPU * vcpu, u64 vadr)
2224 // TODO: Only allowed for current vcpu
2225 u64 mpaddr, paddr;
2226 IA64FAULT fault;
2228 again:
2229 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2230 if (fault == IA64_NO_FAULT) {
2231 struct p2m_entry entry;
2232 paddr = translate_domain_mpaddr(mpaddr, &entry);
2233 ia64_fc(__va(paddr));
2234 if (p2m_entry_retry(&entry))
2235 goto again;
2237 return fault;
2240 IA64FAULT vcpu_ptc_e(VCPU * vcpu, u64 vadr)
2242 // Note that this only needs to be called once, i.e. the
2243 // architected loop to purge the entire TLB, should use
2244 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2246 vcpu_flush_vtlb_all(current);
2248 return IA64_NO_FAULT;
2251 IA64FAULT vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 addr_range)
2253 printk("vcpu_ptc_g: called, not implemented yet\n");
2254 return IA64_ILLOP_FAULT;
2257 IA64FAULT vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 addr_range)
2259 // FIXME: validate not flushing Xen addresses
2260 // if (Xen address) return(IA64_ILLOP_FAULT);
2261 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2262 //printk("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2264 check_xen_space_overlap("ptc_ga", vadr, addr_range);
2266 domain_flush_vtlb_range(vcpu->domain, vadr, addr_range);
2268 return IA64_NO_FAULT;
2271 IA64FAULT vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 log_range)
2273 unsigned long region = vadr >> 61;
2274 u64 addr_range = 1UL << log_range;
2275 unsigned long rid, rr;
2276 int i;
2277 TR_ENTRY *trp;
2279 BUG_ON(vcpu != current);
2280 check_xen_space_overlap("ptr_d", vadr, 1UL << log_range);
2282 rr = PSCB(vcpu, rrs)[region];
2283 rid = rr & RR_RID_MASK;
2285 /* Purge TC */
2286 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2288 /* Purge tr and recompute dtr_regions. */
2289 vcpu->arch.dtr_regions = 0;
2290 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2291 if (vcpu_match_tr_entry_range
2292 (trp, rid, vadr, vadr + addr_range))
2293 vcpu_purge_tr_entry(trp);
2294 else if (trp->pte.p)
2295 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2296 trp->vadr);
2298 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2300 return IA64_NO_FAULT;
2303 IA64FAULT vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 log_range)
2305 unsigned long region = vadr >> 61;
2306 u64 addr_range = 1UL << log_range;
2307 unsigned long rid, rr;
2308 int i;
2309 TR_ENTRY *trp;
2311 BUG_ON(vcpu != current);
2312 check_xen_space_overlap("ptr_i", vadr, 1UL << log_range);
2314 rr = PSCB(vcpu, rrs)[region];
2315 rid = rr & RR_RID_MASK;
2317 /* Purge TC */
2318 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2320 /* Purge tr and recompute itr_regions. */
2321 vcpu->arch.itr_regions = 0;
2322 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2323 if (vcpu_match_tr_entry_range
2324 (trp, rid, vadr, vadr + addr_range))
2325 vcpu_purge_tr_entry(trp);
2326 else if (trp->pte.p)
2327 vcpu_quick_region_set(vcpu->arch.itr_regions,
2328 trp->vadr);
2330 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2332 return IA64_NO_FAULT;