ia64/xen-unstable

view xen/arch/ia64/xen/vcpu.c @ 19848:5839491bbf20

[IA64] replace MAX_VCPUS with d->max_vcpus where necessary.

don't use MAX_VCPUS, and use vcpu::max_vcpus.
The changeset of 2f9e1348aa98 introduced max_vcpus to allow more vcpus
per guest. This patch is ia64 counter part.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Mon Jun 29 11:26:05 2009 +0900 (2009-06-29)
parents e239a47180fb
children
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 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 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
311 imm = *(struct ia64_psr *)&imm24;
312 // interrupt flag
313 if (imm.i)
314 vcpu->vcpu_info->evtchn_upcall_mask = 1;
315 if (imm.ic)
316 PSCB(vcpu, interrupt_collection_enabled) = 0;
317 // interrupt collection flag
318 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
319 // just handle psr.up and psr.pp for now
320 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
321 IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
322 IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_PK))
323 return IA64_ILLOP_FAULT;
324 if (imm.dfh) {
325 ipsr->dfh = PSCB(vcpu, hpsr_dfh);
326 PSCB(vcpu, vpsr_dfh) = 0;
327 }
328 if (imm.dfl)
329 ipsr->dfl = 0;
330 if (imm.pp) {
331 // xenoprof:
332 // Don't change psr.pp and ipsr->pp
333 // They are manipulated by xenoprof
334 // psr.pp = 1;
335 // ipsr->pp = 1;
336 PSCB(vcpu, vpsr_pp) = 0; // but fool the domain if it gets psr
337 }
338 if (imm.up)
339 ipsr->up = 0;
340 if (imm.sp)
341 ipsr->sp = 0;
342 if (imm.be)
343 ipsr->be = 0;
344 if (imm.dt)
345 vcpu_set_metaphysical_mode(vcpu, TRUE);
346 if (imm.pk) {
347 ipsr->pk = 0;
348 vcpu_pkr_use_unset(vcpu);
349 }
350 return IA64_NO_FAULT;
351 }
353 IA64FAULT vcpu_set_psr_dt(VCPU * vcpu)
354 {
355 vcpu_set_metaphysical_mode(vcpu, FALSE);
356 return IA64_NO_FAULT;
357 }
359 IA64FAULT vcpu_set_psr_i(VCPU * vcpu)
360 {
361 vcpu->vcpu_info->evtchn_upcall_mask = 0;
362 PSCB(vcpu, interrupt_collection_enabled) = 1;
363 return IA64_NO_FAULT;
364 }
366 IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24)
367 {
368 struct ia64_psr imm, *ipsr;
369 REGS *regs = vcpu_regs(vcpu);
370 u64 mask, enabling_interrupts = 0;
372 //PRIVOP_COUNT_ADDR(regs,_SSM);
373 // TODO: All of these bits need to be virtualized
374 imm = *(struct ia64_psr *)&imm24;
375 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
376 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
377 mask =
378 IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
379 IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE |
380 IA64_PSR_PK;
381 if (imm24 & ~mask)
382 return IA64_ILLOP_FAULT;
383 if (imm.dfh) {
384 PSCB(vcpu, vpsr_dfh) = 1;
385 ipsr->dfh = 1;
386 }
387 if (imm.dfl)
388 ipsr->dfl = 1;
389 if (imm.pp) {
390 // xenoprof:
391 // Don't change psr.pp and ipsr->pp
392 // They are manipulated by xenoprof
393 // psr.pp = 1;
394 // ipsr->pp = 1;
395 PSCB(vcpu, vpsr_pp) = 1;
396 }
397 if (imm.sp)
398 ipsr->sp = 1;
399 if (imm.i) {
400 if (vcpu->vcpu_info->evtchn_upcall_mask) {
401 //printk("vcpu_set_psr_sm: psr.ic 0->1\n");
402 enabling_interrupts = 1;
403 }
404 vcpu->vcpu_info->evtchn_upcall_mask = 0;
405 }
406 if (imm.ic)
407 PSCB(vcpu, interrupt_collection_enabled) = 1;
408 // TODO: do this faster
409 if (imm.mfl)
410 ipsr->mfl = 1;
411 if (imm.mfh)
412 ipsr->mfh = 1;
413 if (imm.ac)
414 ipsr->ac = 1;
415 if (imm.up)
416 ipsr->up = 1;
417 if (imm.be)
418 ipsr->be = 1;
419 if (imm.dt)
420 vcpu_set_metaphysical_mode(vcpu, FALSE);
421 if (imm.pk) {
422 vcpu_pkr_set_psr_handling(vcpu);
423 ipsr->pk = 1;
424 }
425 if (enabling_interrupts &&
426 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
427 PSCB(vcpu, pending_interruption) = 1;
428 return IA64_NO_FAULT;
429 }
431 IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val)
432 {
433 struct ia64_psr newpsr, *ipsr;
434 REGS *regs = vcpu_regs(vcpu);
435 u64 enabling_interrupts = 0;
437 newpsr = *(struct ia64_psr *)&val;
438 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
440 ipsr->be = newpsr.be;
441 ipsr->up = newpsr.up;
442 ipsr->ac = newpsr.ac;
443 ipsr->mfl = newpsr.mfl;
444 ipsr->mfh = newpsr.mfh;
446 PSCB(vcpu, interrupt_collection_enabled) = newpsr.ic;
448 if (newpsr.i && vcpu->vcpu_info->evtchn_upcall_mask)
449 enabling_interrupts = 1;
451 vcpu->vcpu_info->evtchn_upcall_mask = !(newpsr.i);
453 if (newpsr.pk) {
454 vcpu_pkr_set_psr_handling(vcpu);
455 ipsr->pk = 1;
456 } else
457 vcpu_pkr_use_unset(vcpu);
459 vcpu_set_metaphysical_mode(vcpu, !(newpsr.dt && newpsr.rt));
461 ipsr->dfl = newpsr.dfl;
462 PSCB(vcpu, vpsr_dfh) = newpsr.dfh;
463 ipsr->dfh = newpsr.dfh ? 1 : PSCB(vcpu, hpsr_dfh);
465 ipsr->sp = newpsr.sp;
467 /* xenoprof: Don't change ipsr->pp, it is manipulated by xenoprof */
468 PSCB(vcpu, vpsr_pp) = newpsr.pp;
470 if (enabling_interrupts &&
471 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
472 PSCB(vcpu, pending_interruption) = 1;
474 return IA64_NO_FAULT;
475 }
477 IA64FAULT vcpu_set_psr(VCPU * vcpu, u64 val)
478 {
479 IA64_PSR newpsr, vpsr;
480 REGS *regs = vcpu_regs(vcpu);
481 u64 enabling_interrupts = 0;
483 /* Copy non-virtualized bits. */
484 newpsr.val = val & IA64_PSR_NON_VIRT_BITS;
486 /* Bits forced to 1 (psr.si, psr.is and psr.mc are forced to 0) */
487 newpsr.val |= IA64_PSR_DI;
489 newpsr.val |= IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT |
490 IA64_PSR_IT | IA64_PSR_BN | IA64_PSR_DI;
491 /*
492 * xenoprof:
493 * keep psr.pp unchanged for xenoprof.
494 */
495 if (regs->cr_ipsr & IA64_PSR_PP)
496 newpsr.val |= IA64_PSR_PP;
497 else
498 newpsr.val &= ~IA64_PSR_PP;
500 vpsr.val = val;
502 if (val & IA64_PSR_DFH) {
503 newpsr.dfh = 1;
504 PSCB(vcpu, vpsr_dfh) = 1;
505 } else {
506 newpsr.dfh = PSCB(vcpu, hpsr_dfh);
507 PSCB(vcpu, vpsr_dfh) = 0;
508 }
510 PSCB(vcpu, vpsr_pp) = vpsr.pp;
512 if (vpsr.i) {
513 if (vcpu->vcpu_info->evtchn_upcall_mask)
514 enabling_interrupts = 1;
516 vcpu->vcpu_info->evtchn_upcall_mask = 0;
518 if (enabling_interrupts &&
519 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
520 PSCB(vcpu, pending_interruption) = 1;
521 } else
522 vcpu->vcpu_info->evtchn_upcall_mask = 1;
524 PSCB(vcpu, interrupt_collection_enabled) = vpsr.ic;
525 vcpu_set_metaphysical_mode(vcpu, !(vpsr.dt && vpsr.rt && vpsr.it));
527 newpsr.cpl |= max_t(u64, vpsr.cpl, CONFIG_CPL0_EMUL);
529 if (PSCB(vcpu, banknum) != vpsr.bn) {
530 if (vpsr.bn)
531 vcpu_bsw1(vcpu);
532 else
533 vcpu_bsw0(vcpu);
534 }
535 if (vpsr.pk) {
536 vcpu_pkr_set_psr_handling(vcpu);
537 newpsr.pk = 1;
538 } else
539 vcpu_pkr_use_unset(vcpu);
541 regs->cr_ipsr = newpsr.val;
543 return IA64_NO_FAULT;
544 }
546 u64 vcpu_get_psr(VCPU * vcpu)
547 {
548 REGS *regs = vcpu_regs(vcpu);
549 PSR newpsr;
550 PSR ipsr;
552 ipsr.i64 = regs->cr_ipsr;
554 /* Copy non-virtualized bits. */
555 newpsr.i64 = ipsr.i64 & IA64_PSR_NON_VIRT_BITS;
557 /* Bits forced to 1 (psr.si and psr.is are forced to 0) */
558 newpsr.i64 |= IA64_PSR_DI;
560 /* System mask. */
561 newpsr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled);
562 newpsr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
564 if (!PSCB(vcpu, metaphysical_mode))
565 newpsr.i64 |= IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_IT;
567 newpsr.ia64_psr.dfh = PSCB(vcpu, vpsr_dfh);
568 newpsr.ia64_psr.pp = PSCB(vcpu, vpsr_pp);
570 /* Fool cpl. */
571 if (ipsr.ia64_psr.cpl <= CONFIG_CPL0_EMUL)
572 newpsr.ia64_psr.cpl = 0;
573 else
574 newpsr.ia64_psr.cpl = ipsr.ia64_psr.cpl;
576 newpsr.ia64_psr.bn = PSCB(vcpu, banknum);
578 return newpsr.i64;
579 }
581 IA64FAULT vcpu_get_psr_masked(VCPU * vcpu, u64 * pval)
582 {
583 u64 psr = vcpu_get_psr(vcpu);
584 *pval = psr & (MASK(0, 32) | MASK(35, 2));
585 return IA64_NO_FAULT;
586 }
588 BOOLEAN vcpu_get_psr_ic(VCPU * vcpu)
589 {
590 return !!PSCB(vcpu, interrupt_collection_enabled);
591 }
593 BOOLEAN vcpu_get_psr_i(VCPU * vcpu)
594 {
595 return !vcpu->vcpu_info->evtchn_upcall_mask;
596 }
599 /**************************************************************************
600 VCPU interrupt control register access routines
601 **************************************************************************/
603 void vcpu_pend_unspecified_interrupt(VCPU * vcpu)
604 {
605 PSCB(vcpu, pending_interruption) = 1;
606 }
608 void vcpu_pend_interrupt(VCPU * vcpu, u64 vector)
609 {
610 if (vector & ~0xff) {
611 printk("vcpu_pend_interrupt: bad vector\n");
612 return;
613 }
615 if (vcpu->arch.event_callback_ip) {
616 printk("Deprecated interface. Move to new event based "
617 "solution\n");
618 return;
619 }
621 if (VMX_DOMAIN(vcpu)) {
622 set_bit(vector, VCPU(vcpu, irr));
623 } else {
624 set_bit(vector, PSCBX(vcpu, irr));
625 PSCB(vcpu, pending_interruption) = 1;
626 }
627 }
629 #define IA64_TPR_MMI 0x10000
630 #define IA64_TPR_MIC 0x000f0
632 /* checks to see if a VCPU has any unmasked pending interrupts
633 * if so, returns the highest, else returns SPURIOUS_VECTOR */
634 /* NOTE: Since this gets called from vcpu_get_ivr() and the
635 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
636 * this routine also ignores pscb.interrupt_delivery_enabled
637 * and this must be checked independently; see vcpu_deliverable interrupts() */
638 u64 vcpu_check_pending_interrupts(VCPU * vcpu)
639 {
640 u64 *p, *r, bits, bitnum, mask, i, vector;
642 if (vcpu->arch.event_callback_ip)
643 return SPURIOUS_VECTOR;
645 /* Always check pending event, since guest may just ack the
646 * event injection without handle. Later guest may throw out
647 * the event itself.
648 */
649 check_start:
650 if (event_pending(vcpu) &&
651 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
652 &PSCBX(vcpu, insvc[0])))
653 vcpu_pend_interrupt(vcpu,
654 vcpu->domain->shared_info->arch.
655 evtchn_vector);
657 p = &PSCBX(vcpu, irr[3]);
658 r = &PSCBX(vcpu, insvc[3]);
659 for (i = 3 ;; p--, r--, i--) {
660 bits = *p;
661 if (bits)
662 break; // got a potential interrupt
663 if (*r) {
664 // nothing in this word which is pending+inservice
665 // but there is one inservice which masks lower
666 return SPURIOUS_VECTOR;
667 }
668 if (i == 0) {
669 // checked all bits... nothing pending+inservice
670 return SPURIOUS_VECTOR;
671 }
672 }
673 // have a pending,deliverable interrupt... see if it is masked
674 bitnum = ia64_fls(bits);
675 //printk("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
676 vector = bitnum + (i * 64);
677 mask = 1L << bitnum;
678 /* sanity check for guest timer interrupt */
679 if (vector == (PSCB(vcpu, itv) & 0xff)) {
680 uint64_t now = ia64_get_itc();
681 if (now < PSCBX(vcpu, domain_itm)) {
682 // printk("Ooops, pending guest timer before its due\n");
683 PSCBX(vcpu, irr[i]) &= ~mask;
684 goto check_start;
685 }
686 }
687 //printk("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
688 if (*r >= mask) {
689 // masked by equal inservice
690 //printk("but masked by equal inservice\n");
691 return SPURIOUS_VECTOR;
692 }
693 if (PSCB(vcpu, tpr) & IA64_TPR_MMI) {
694 // tpr.mmi is set
695 //printk("but masked by tpr.mmi\n");
696 return SPURIOUS_VECTOR;
697 }
698 if (((PSCB(vcpu, tpr) & IA64_TPR_MIC) + 15) >= vector) {
699 //tpr.mic masks class
700 //printk("but masked by tpr.mic\n");
701 return SPURIOUS_VECTOR;
702 }
703 //printk("returned to caller\n");
704 return vector;
705 }
707 u64 vcpu_deliverable_interrupts(VCPU * vcpu)
708 {
709 return (vcpu_get_psr_i(vcpu) &&
710 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
711 }
713 u64 vcpu_deliverable_timer(VCPU * vcpu)
714 {
715 return (vcpu_get_psr_i(vcpu) &&
716 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu, itv));
717 }
719 IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval)
720 {
721 /* Use EID=0, ID=vcpu_id. */
722 *pval = vcpu->vcpu_id << 24;
723 return IA64_NO_FAULT;
724 }
726 IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval)
727 {
728 int i;
729 u64 vector, mask;
731 #define HEARTBEAT_FREQ 16 // period in seconds
732 #ifdef HEARTBEAT_FREQ
733 #define N_DOMS 16 // period in seconds
734 #if 0
735 static long count[N_DOMS] = { 0 };
736 #endif
737 static long nonclockcount[N_DOMS] = { 0 };
738 unsigned domid = vcpu->domain->domain_id;
739 #endif
740 #ifdef IRQ_DEBUG
741 static char firstivr = 1;
742 static char firsttime[256];
743 if (firstivr) {
744 int i;
745 for (i = 0; i < 256; i++)
746 firsttime[i] = 1;
747 firstivr = 0;
748 }
749 #endif
751 vector = vcpu_check_pending_interrupts(vcpu);
752 if (vector == SPURIOUS_VECTOR) {
753 PSCB(vcpu, pending_interruption) = 0;
754 *pval = vector;
755 return IA64_NO_FAULT;
756 }
757 #ifdef HEARTBEAT_FREQ
758 if (domid >= N_DOMS)
759 domid = N_DOMS - 1;
760 #if 0
761 if (vector == (PSCB(vcpu, itv) & 0xff)) {
762 if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) {
763 printk("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
764 domid, count[domid], nonclockcount[domid]);
765 //count[domid] = 0;
766 //dump_runq();
767 }
768 }
769 #endif
770 else
771 nonclockcount[domid]++;
772 #endif
773 // now have an unmasked, pending, deliverable vector!
774 // getting ivr has "side effects"
775 #ifdef IRQ_DEBUG
776 if (firsttime[vector]) {
777 printk("*** First get_ivr on vector=%lu,itc=%lx\n",
778 vector, ia64_get_itc());
779 firsttime[vector] = 0;
780 }
781 #endif
782 /* if delivering a timer interrupt, remember domain_itm, which
783 * needs to be done before clearing irr
784 */
785 if (vector == (PSCB(vcpu, itv) & 0xff)) {
786 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
787 }
789 i = vector >> 6;
790 mask = 1L << (vector & 0x3f);
791 //printk("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
792 PSCBX(vcpu, insvc[i]) |= mask;
793 PSCBX(vcpu, irr[i]) &= ~mask;
794 //PSCB(vcpu,pending_interruption)--;
795 *pval = vector;
796 return IA64_NO_FAULT;
797 }
799 IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval)
800 {
801 *pval = PSCB(vcpu, tpr);
802 return IA64_NO_FAULT;
803 }
805 IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval)
806 {
807 *pval = 0L; // reads of eoi always return 0
808 return IA64_NO_FAULT;
809 }
811 IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval)
812 {
813 *pval = PSCBX(vcpu, irr[0]);
814 return IA64_NO_FAULT;
815 }
817 IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval)
818 {
819 *pval = PSCBX(vcpu, irr[1]);
820 return IA64_NO_FAULT;
821 }
823 IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval)
824 {
825 *pval = PSCBX(vcpu, irr[2]);
826 return IA64_NO_FAULT;
827 }
829 IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval)
830 {
831 *pval = PSCBX(vcpu, irr[3]);
832 return IA64_NO_FAULT;
833 }
835 IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval)
836 {
837 *pval = PSCB(vcpu, itv);
838 return IA64_NO_FAULT;
839 }
841 IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval)
842 {
843 *pval = PSCB(vcpu, pmv);
844 return IA64_NO_FAULT;
845 }
847 IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval)
848 {
849 *pval = PSCB(vcpu, cmcv);
850 return IA64_NO_FAULT;
851 }
853 IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval)
854 {
855 // fix this when setting values other than m-bit is supported
856 gdprintk(XENLOG_DEBUG,
857 "vcpu_get_lrr0: Unmasked interrupts unsupported\n");
858 *pval = (1L << 16);
859 return IA64_NO_FAULT;
860 }
862 IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval)
863 {
864 // fix this when setting values other than m-bit is supported
865 gdprintk(XENLOG_DEBUG,
866 "vcpu_get_lrr1: Unmasked interrupts unsupported\n");
867 *pval = (1L << 16);
868 return IA64_NO_FAULT;
869 }
871 IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val)
872 {
873 printk("vcpu_set_lid: Setting cr.lid is unsupported\n");
874 return IA64_ILLOP_FAULT;
875 }
877 IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val)
878 {
879 if (val & 0xff00)
880 return IA64_RSVDREG_FAULT;
881 PSCB(vcpu, tpr) = val;
882 /* This can unmask interrupts. */
883 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
884 PSCB(vcpu, pending_interruption) = 1;
885 return IA64_NO_FAULT;
886 }
888 IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val)
889 {
890 u64 *p, bits, vec, bitnum;
891 int i;
893 p = &PSCBX(vcpu, insvc[3]);
894 for (i = 3; (i >= 0) && !(bits = *p); i--, p--)
895 ;
896 if (i < 0) {
897 printk("Trying to EOI interrupt when none are in-service.\n");
898 return IA64_NO_FAULT;
899 }
900 bitnum = ia64_fls(bits);
901 vec = bitnum + (i * 64);
902 /* clear the correct bit */
903 bits &= ~(1L << bitnum);
904 *p = bits;
905 /* clearing an eoi bit may unmask another pending interrupt... */
906 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
907 // worry about this later... Linux only calls eoi
908 // with interrupts disabled
909 printk("Trying to EOI interrupt with interrupts enabled\n");
910 }
911 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
912 PSCB(vcpu, pending_interruption) = 1;
913 //printk("YYYYY vcpu_set_eoi: Successful\n");
914 return IA64_NO_FAULT;
915 }
917 IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val)
918 {
919 if (!(val & (1L << 16))) {
920 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
921 return IA64_ILLOP_FAULT;
922 }
923 // no place to save this state but nothing to do anyway
924 return IA64_NO_FAULT;
925 }
927 IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val)
928 {
929 if (!(val & (1L << 16))) {
930 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
931 return IA64_ILLOP_FAULT;
932 }
933 // no place to save this state but nothing to do anyway
934 return IA64_NO_FAULT;
935 }
937 IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val)
938 {
939 /* Check reserved fields. */
940 if (val & 0xef00)
941 return IA64_ILLOP_FAULT;
942 PSCB(vcpu, itv) = val;
943 if (val & 0x10000) {
944 /* Disable itm. */
945 PSCBX(vcpu, domain_itm) = 0;
946 } else
947 vcpu_set_next_timer(vcpu);
948 return IA64_NO_FAULT;
949 }
951 IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val)
952 {
953 if (val & 0xef00) /* reserved fields */
954 return IA64_RSVDREG_FAULT;
955 PSCB(vcpu, pmv) = val;
956 return IA64_NO_FAULT;
957 }
959 IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val)
960 {
961 if (val & 0xef00) /* reserved fields */
962 return IA64_RSVDREG_FAULT;
963 PSCB(vcpu, cmcv) = val;
964 return IA64_NO_FAULT;
965 }
967 /**************************************************************************
968 VCPU temporary register access routines
969 **************************************************************************/
970 u64 vcpu_get_tmp(VCPU * vcpu, u64 index)
971 {
972 if (index > 7)
973 return 0;
974 return PSCB(vcpu, tmp[index]);
975 }
977 void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val)
978 {
979 if (index <= 7)
980 PSCB(vcpu, tmp[index]) = val;
981 }
983 /**************************************************************************
984 Interval timer routines
985 **************************************************************************/
987 BOOLEAN vcpu_timer_disabled(VCPU * vcpu)
988 {
989 u64 itv = PSCB(vcpu, itv);
990 return (!itv || !!(itv & 0x10000));
991 }
993 BOOLEAN vcpu_timer_inservice(VCPU * vcpu)
994 {
995 u64 itv = PSCB(vcpu, itv);
996 return test_bit(itv, PSCBX(vcpu, insvc));
997 }
999 BOOLEAN vcpu_timer_expired(VCPU * vcpu)
1001 unsigned long domain_itm = PSCBX(vcpu, domain_itm);
1002 unsigned long now = ia64_get_itc();
1004 if (!domain_itm)
1005 return FALSE;
1006 if (now < domain_itm)
1007 return FALSE;
1008 if (vcpu_timer_disabled(vcpu))
1009 return FALSE;
1010 return TRUE;
1013 void vcpu_safe_set_itm(unsigned long val)
1015 unsigned long epsilon = 100;
1016 unsigned long flags;
1017 u64 now = ia64_get_itc();
1019 local_irq_save(flags);
1020 while (1) {
1021 //printk("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1022 ia64_set_itm(val);
1023 if (val > (now = ia64_get_itc()))
1024 break;
1025 val = now + epsilon;
1026 epsilon <<= 1;
1028 local_irq_restore(flags);
1031 void vcpu_set_next_timer(VCPU * vcpu)
1033 u64 d = PSCBX(vcpu, domain_itm);
1034 //u64 s = PSCBX(vcpu,xen_itm);
1035 u64 s = local_cpu_data->itm_next;
1036 u64 now = ia64_get_itc();
1038 /* gloss over the wraparound problem for now... we know it exists
1039 * but it doesn't matter right now */
1041 if (is_idle_domain(vcpu->domain)) {
1042 // printk("****** vcpu_set_next_timer called during idle!!\n");
1043 vcpu_safe_set_itm(s);
1044 return;
1046 //s = PSCBX(vcpu,xen_itm);
1047 if (d && (d > now) && (d < s)) {
1048 vcpu_safe_set_itm(d);
1049 //using_domain_as_itm++;
1050 } else {
1051 vcpu_safe_set_itm(s);
1052 //using_xen_as_itm++;
1056 IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val)
1058 //UINT now = ia64_get_itc();
1060 //if (val < now) val = now + 1000;
1061 //printk("*** vcpu_set_itm: called with %lx\n",val);
1062 PSCBX(vcpu, domain_itm) = val;
1063 vcpu_set_next_timer(vcpu);
1064 return IA64_NO_FAULT;
1067 IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val)
1069 #define DISALLOW_SETTING_ITC_FOR_NOW
1070 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1071 static int did_print;
1072 if (!did_print) {
1073 printk("vcpu_set_itc: Setting ar.itc is currently disabled "
1074 "(this message is only displayed once)\n");
1075 did_print = 1;
1077 #else
1078 u64 oldnow = ia64_get_itc();
1079 u64 olditm = PSCBX(vcpu, domain_itm);
1080 unsigned long d = olditm - oldnow;
1081 unsigned long x = local_cpu_data->itm_next - oldnow;
1083 u64 newnow = val, min_delta;
1085 local_irq_disable();
1086 if (olditm) {
1087 printk("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val,
1088 newnow + d);
1089 PSCBX(vcpu, domain_itm) = newnow + d;
1091 local_cpu_data->itm_next = newnow + x;
1092 d = PSCBX(vcpu, domain_itm);
1093 x = local_cpu_data->itm_next;
1095 ia64_set_itc(newnow);
1096 if (d && (d > newnow) && (d < x)) {
1097 vcpu_safe_set_itm(d);
1098 //using_domain_as_itm++;
1099 } else {
1100 vcpu_safe_set_itm(x);
1101 //using_xen_as_itm++;
1103 local_irq_enable();
1104 #endif
1105 return IA64_NO_FAULT;
1108 IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval)
1110 //FIXME: Implement this
1111 printk("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1112 return IA64_NO_FAULT;
1113 //return IA64_ILLOP_FAULT;
1116 IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval)
1118 //TODO: Implement this
1119 printk("vcpu_get_itc: Getting ar.itc is unsupported\n");
1120 return IA64_ILLOP_FAULT;
1123 void vcpu_pend_timer(VCPU * vcpu)
1125 u64 itv = PSCB(vcpu, itv) & 0xff;
1127 if (vcpu_timer_disabled(vcpu))
1128 return;
1129 //if (vcpu_timer_inservice(vcpu)) return;
1130 if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) {
1131 // already delivered an interrupt for this so
1132 // don't deliver another
1133 return;
1135 if (vcpu->arch.event_callback_ip) {
1136 /* A small window may occur when injecting vIRQ while related
1137 * handler has not been registered. Don't fire in such case.
1138 */
1139 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1140 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1141 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1143 } else
1144 vcpu_pend_interrupt(vcpu, itv);
1147 // returns true if ready to deliver a timer interrupt too early
1148 u64 vcpu_timer_pending_early(VCPU * vcpu)
1150 u64 now = ia64_get_itc();
1151 u64 itm = PSCBX(vcpu, domain_itm);
1153 if (vcpu_timer_disabled(vcpu))
1154 return 0;
1155 if (!itm)
1156 return 0;
1157 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1160 /**************************************************************************
1161 Privileged operation emulation routines
1162 **************************************************************************/
1164 static void vcpu_force_tlb_miss(VCPU * vcpu, u64 ifa)
1166 PSCB(vcpu, ifa) = ifa;
1167 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1168 vcpu_thash(current, ifa, &PSCB(current, iha));
1171 IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa)
1173 vcpu_force_tlb_miss(vcpu, ifa);
1174 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_INST_TLB_VECTOR :
1175 IA64_ALT_INST_TLB_VECTOR;
1178 IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa)
1180 vcpu_force_tlb_miss(vcpu, ifa);
1181 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_DATA_TLB_VECTOR :
1182 IA64_ALT_DATA_TLB_VECTOR;
1185 IA64FAULT vcpu_rfi(VCPU * vcpu)
1187 u64 ifs;
1188 REGS *regs = vcpu_regs(vcpu);
1190 vcpu_set_psr(vcpu, PSCB(vcpu, ipsr));
1192 ifs = PSCB(vcpu, ifs);
1193 if (ifs & 0x8000000000000000UL)
1194 regs->cr_ifs = ifs;
1196 regs->cr_iip = PSCB(vcpu, iip);
1198 return IA64_NO_FAULT;
1201 IA64FAULT vcpu_cover(VCPU * vcpu)
1203 // TODO: Only allowed for current vcpu
1204 REGS *regs = vcpu_regs(vcpu);
1206 if (!PSCB(vcpu, interrupt_collection_enabled)) {
1207 PSCB(vcpu, ifs) = regs->cr_ifs;
1209 regs->cr_ifs = 0;
1210 return IA64_NO_FAULT;
1213 IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval)
1215 u64 pta = PSCB(vcpu, pta);
1216 u64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1217 u64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT) - 1);
1218 u64 Mask = (1L << pta_sz) - 1;
1219 u64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1220 u64 compMask_60_15 = ~Mask_60_15;
1221 u64 rr_ps = vcpu_get_rr_ps(vcpu, vadr);
1222 u64 VHPT_offset = (vadr >> rr_ps) << 3;
1223 u64 VHPT_addr1 = vadr & 0xe000000000000000L;
1224 u64 VHPT_addr2a =
1225 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1226 u64 VHPT_addr2b =
1227 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1228 u64 VHPT_addr3 = VHPT_offset & 0x7fff;
1229 u64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1230 VHPT_addr3;
1232 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1233 *pval = VHPT_addr;
1234 return IA64_NO_FAULT;
1237 IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr)
1239 printk("vcpu_ttag: ttag instruction unsupported\n");
1240 return IA64_ILLOP_FAULT;
1243 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1245 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1246 static inline int range_overlap(u64 b1, u64 e1, u64 b2, u64 e2)
1248 return (b1 <= e2) && (e1 >= b2);
1251 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1252 Note: LSBs of base inside page_size are ignored. */
1253 static inline void
1254 check_xen_space_overlap(const char *func, u64 base, u64 page_size)
1256 /* Overlaps can occur only in region 7.
1257 (This is an optimization to bypass all the checks). */
1258 if (REGION_NUMBER(base) != 7)
1259 return;
1261 /* Mask LSBs of base. */
1262 base &= ~(page_size - 1);
1264 /* FIXME: ideally an MCA should be generated... */
1265 if (range_overlap(HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
1266 base, base + page_size)
1267 || range_overlap(current->domain->arch.shared_info_va,
1268 current->domain->arch.shared_info_va
1269 + XSI_SIZE + XMAPPEDREGS_SIZE,
1270 base, base + page_size))
1271 panic_domain(NULL, "%s on Xen virtual space (%lx)\n",
1272 func, base);
1275 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1276 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY * trp, u64 ifa,
1277 u64 rid)
1279 return trp->rid == rid
1280 && ifa >= trp->vadr && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1283 static inline int vcpu_match_tr_entry(TR_ENTRY * trp, u64 ifa, u64 rid)
1285 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1288 static inline int
1289 vcpu_match_tr_entry_range(TR_ENTRY * trp, u64 rid, u64 b, u64 e)
1291 return trp->rid == rid
1292 && trp->pte.p
1293 && range_overlap(b, e, trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1297 static TR_ENTRY *vcpu_tr_lookup(VCPU * vcpu, unsigned long va, u64 rid,
1298 BOOLEAN is_data)
1300 unsigned char *regions;
1301 TR_ENTRY *trp;
1302 int tr_max;
1303 int i;
1305 if (is_data) {
1306 // data
1307 regions = &vcpu->arch.dtr_regions;
1308 trp = vcpu->arch.dtrs;
1309 tr_max = sizeof(vcpu->arch.dtrs) / sizeof(vcpu->arch.dtrs[0]);
1310 } else {
1311 // instruction
1312 regions = &vcpu->arch.itr_regions;
1313 trp = vcpu->arch.itrs;
1314 tr_max = sizeof(vcpu->arch.itrs) / sizeof(vcpu->arch.itrs[0]);
1317 if (!vcpu_quick_region_check(*regions, va)) {
1318 return NULL;
1320 for (i = 0; i < tr_max; i++, trp++) {
1321 if (vcpu_match_tr_entry(trp, va, rid)) {
1322 return trp;
1325 return NULL;
1328 // return value
1329 // 0: failure
1330 // 1: success
1331 int
1332 vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
1333 IA64_BUNDLE * bundle)
1335 u64 gpip; // guest pseudo phyiscal ip
1336 unsigned long vaddr;
1337 struct page_info *page;
1339 again:
1340 #if 0
1341 // Currently xen doesn't track psr.it bits.
1342 // it assumes always psr.it = 1.
1343 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1344 gpip = gip;
1345 } else
1346 #endif
1348 unsigned long region = REGION_NUMBER(gip);
1349 unsigned long rr = PSCB(vcpu, rrs)[region];
1350 unsigned long rid = rr & RR_RID_MASK;
1351 BOOLEAN swap_rr0;
1352 TR_ENTRY *trp;
1354 // vcpu->arch.{i, d}tlb are volatile,
1355 // copy its value to the variable, tr, before use.
1356 TR_ENTRY tr;
1358 // fast path:
1359 // try to access gip with guest virtual address directly.
1360 // This may cause tlb miss. see vcpu_translate(). Be careful!
1361 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1362 if (swap_rr0) {
1363 set_virtual_rr0();
1365 *bundle = __get_domain_bundle(gip);
1366 if (swap_rr0) {
1367 set_metaphysical_rr0();
1370 if (!bundle->i64[0] && !bundle->i64[1]) {
1371 dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
1372 } else {
1373 // Okay, mDTC successed
1374 return 1;
1376 // mDTC failed, so try vTLB.
1378 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1379 if (trp != NULL) {
1380 tr = *trp;
1381 goto found;
1383 // When it failed to get a bundle, itlb miss is reflected.
1384 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1385 tr = PSCBX(vcpu, itlb);
1386 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1387 //dprintk(XENLOG_WARNING,
1388 // "%s gip 0x%lx gpip 0x%lx\n", __func__,
1389 // gip, gpip);
1390 goto found;
1392 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1393 if (trp != NULL) {
1394 tr = *trp;
1395 goto found;
1397 tr = PSCBX(vcpu, dtlb);
1398 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1399 goto found;
1402 // mDTC and vTLB failed. so reflect tlb miss into the guest.
1403 return 0;
1405 found:
1406 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1407 (gip & ((1 << tr.ps) - 1));
1410 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1411 page = virt_to_page(vaddr);
1412 if (get_page(page, vcpu->domain) == 0) {
1413 if (page_get_owner(page) != vcpu->domain) {
1414 // This page might be a page granted by another
1415 // domain.
1416 panic_domain(regs, "domain tries to execute foreign "
1417 "domain page which might be mapped by "
1418 "grant table.\n");
1420 goto again;
1422 *bundle = *((IA64_BUNDLE *) vaddr);
1423 put_page(page);
1424 return 1;
1427 IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
1428 u64 * pteval, u64 * itir, u64 * iha)
1430 unsigned long region = REGION_NUMBER(address);
1431 unsigned long pta, rid, rr, key = 0;
1432 union pte_flags pte;
1433 TR_ENTRY *trp;
1435 if (PSCB(vcpu, metaphysical_mode) && !(!is_data && region)) {
1436 // dom0 may generate an uncacheable physical address (msb=1)
1437 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1438 // FIXME: This seems to happen even though it shouldn't. Need to track
1439 // this down, but since it has been apparently harmless, just flag it for now
1440 // panic_domain(vcpu_regs(vcpu),
1442 /*
1443 * Guest may execute itc.d and rfi with psr.dt=0
1444 * When VMM try to fetch opcode, tlb miss may happen,
1445 * At this time PSCB(vcpu,metaphysical_mode)=1,
1446 * region=5,VMM need to handle this tlb miss as if
1447 * PSCB(vcpu,metaphysical_mode)=0
1448 */
1449 printk("vcpu_translate: bad physical address: 0x%lx "
1450 "at %lx\n", address, vcpu_regs(vcpu)->cr_iip);
1452 } else {
1453 *pteval = (address & _PAGE_PPN_MASK) |
1454 __DIRTY_BITS | _PAGE_PL_PRIV | _PAGE_AR_RWX;
1455 *itir = vcpu->arch.vhpt_pg_shift << 2;
1456 perfc_incr(phys_translate);
1457 return IA64_NO_FAULT;
1459 } else if (!region && warn_region0_address) {
1460 REGS *regs = vcpu_regs(vcpu);
1461 unsigned long viip = PSCB(vcpu, iip);
1462 unsigned long vipsr = PSCB(vcpu, ipsr);
1463 unsigned long iip = regs->cr_iip;
1464 unsigned long ipsr = regs->cr_ipsr;
1465 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, "
1466 "vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1467 address, viip, vipsr, iip, ipsr);
1470 rr = PSCB(vcpu, rrs)[region];
1471 rid = rr & RR_RID_MASK;
1472 if (is_data) {
1473 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1474 if (trp != NULL) {
1475 *pteval = trp->pte.val;
1476 *itir = trp->itir;
1477 perfc_incr(tr_translate);
1478 return IA64_NO_FAULT;
1481 // FIXME?: check itr's for data accesses too, else bad things happen?
1482 /* else */ {
1483 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1484 if (trp != NULL) {
1485 *pteval = trp->pte.val;
1486 *itir = trp->itir;
1487 perfc_incr(tr_translate);
1488 return IA64_NO_FAULT;
1492 /* check 1-entry TLB */
1493 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1494 trp = &vcpu->arch.dtlb;
1495 pte = trp->pte;
1496 if ( /* is_data && */ pte.p
1497 && vcpu_match_tr_entry_no_p(trp, address, rid)) {
1498 *pteval = pte.val;
1499 *itir = trp->itir;
1500 perfc_incr(dtlb_translate);
1501 return IA64_USE_TLB;
1504 /* check guest VHPT */
1505 pta = PSCB(vcpu, pta);
1507 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1508 // note: architecturally, iha is optionally set for alt faults but
1509 // xenlinux depends on it so should document it as part of PV interface
1510 vcpu_thash(vcpu, address, iha);
1511 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE)) {
1512 REGS *regs = vcpu_regs(vcpu);
1513 struct opt_feature* optf = &(vcpu->domain->arch.opt_feature);
1515 /* Optimization for identity mapped region 7 OS (linux) */
1516 if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG7_FLG &&
1517 region == 7 && ia64_psr(regs)->cpl == CONFIG_CPL0_EMUL &&
1518 REGION_OFFSET(address) < _PAGE_PPN_MASK) {
1519 pte.val = address & _PAGE_PPN_MASK;
1520 pte.val = pte.val | optf->im_reg7.pgprot;
1521 key = optf->im_reg7.key;
1522 goto out;
1524 return is_data ? IA64_ALT_DATA_TLB_VECTOR :
1525 IA64_ALT_INST_TLB_VECTOR;
1528 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1529 /*
1530 * minimal support: vhpt walker is really dumb and won't find
1531 * anything
1532 */
1533 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1535 /* avoid recursively walking (short format) VHPT */
1536 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1537 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1539 if (!__access_ok(*iha)
1540 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1541 // virtual VHPT walker "missed" in TLB
1542 return IA64_VHPT_FAULT;
1544 /*
1545 * Optimisation: this VHPT walker aborts on not-present pages
1546 * instead of inserting a not-present translation, this allows
1547 * vectoring directly to the miss handler.
1548 */
1549 if (!pte.p)
1550 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1552 /* found mapping in guest VHPT! */
1553 out:
1554 *itir = (rr & RR_PS_MASK) | (key << IA64_ITIR_KEY);
1555 *pteval = pte.val;
1556 perfc_incr(vhpt_translate);
1557 return IA64_NO_FAULT;
1560 IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr)
1562 u64 pteval, itir, mask, iha;
1563 IA64FAULT fault;
1565 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1566 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
1567 mask = itir_mask(itir);
1568 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1569 return IA64_NO_FAULT;
1571 return vcpu_force_data_miss(vcpu, vadr);
1574 IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
1576 u64 pteval, itir, iha;
1577 IA64FAULT fault;
1579 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1580 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB)
1581 *key = itir & IA64_ITIR_KEY_MASK;
1582 else
1583 *key = 1;
1585 return IA64_NO_FAULT;
1588 /**************************************************************************
1589 VCPU debug breakpoint register access routines
1590 **************************************************************************/
1592 IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
1594 if (reg >= IA64_NUM_DBG_REGS)
1595 return IA64_RSVDREG_FAULT;
1596 if ((reg & 1) == 0) {
1597 /* Validate address. */
1598 if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END)
1599 return IA64_ILLOP_FAULT;
1600 } else {
1601 if (!VMX_DOMAIN(vcpu)) {
1602 /* Mask PL0. */
1603 val &= ~(1UL << 56);
1606 if (val != 0)
1607 vcpu->arch.dbg_used |= (1 << reg);
1608 else
1609 vcpu->arch.dbg_used &= ~(1 << reg);
1610 vcpu->arch.dbr[reg] = val;
1611 if (vcpu == current)
1612 ia64_set_dbr(reg, val);
1613 return IA64_NO_FAULT;
1616 IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
1618 if (reg >= IA64_NUM_DBG_REGS)
1619 return IA64_RSVDREG_FAULT;
1620 if ((reg & 1) == 0) {
1621 /* Validate address. */
1622 if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END)
1623 return IA64_ILLOP_FAULT;
1624 } else {
1625 if (!VMX_DOMAIN(vcpu)) {
1626 /* Mask PL0. */
1627 val &= ~(1UL << 56);
1630 if (val != 0)
1631 vcpu->arch.dbg_used |= (1 << (reg + IA64_NUM_DBG_REGS));
1632 else
1633 vcpu->arch.dbg_used &= ~(1 << (reg + IA64_NUM_DBG_REGS));
1634 vcpu->arch.ibr[reg] = val;
1635 if (vcpu == current)
1636 ia64_set_ibr(reg, val);
1637 return IA64_NO_FAULT;
1640 IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
1642 if (reg >= IA64_NUM_DBG_REGS)
1643 return IA64_RSVDREG_FAULT;
1644 *pval = vcpu->arch.dbr[reg];
1645 return IA64_NO_FAULT;
1648 IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
1650 if (reg >= IA64_NUM_DBG_REGS)
1651 return IA64_RSVDREG_FAULT;
1652 *pval = vcpu->arch.ibr[reg];
1653 return IA64_NO_FAULT;
1656 /**************************************************************************
1657 VCPU performance monitor register access routines
1658 **************************************************************************/
1660 IA64FAULT vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val)
1662 // TODO: Should set Logical CPU state, not just physical
1663 // NOTE: Writes to unimplemented PMC registers are discarded
1664 #ifdef DEBUG_PFMON
1665 printk("vcpu_set_pmc(%x,%lx)\n", reg, val);
1666 #endif
1667 ia64_set_pmc(reg, val);
1668 return IA64_NO_FAULT;
1671 IA64FAULT vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val)
1673 // TODO: Should set Logical CPU state, not just physical
1674 // NOTE: Writes to unimplemented PMD registers are discarded
1675 #ifdef DEBUG_PFMON
1676 printk("vcpu_set_pmd(%x,%lx)\n", reg, val);
1677 #endif
1678 ia64_set_pmd(reg, val);
1679 return IA64_NO_FAULT;
1682 IA64FAULT vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval)
1684 // NOTE: Reads from unimplemented PMC registers return zero
1685 u64 val = (u64) ia64_get_pmc(reg);
1686 #ifdef DEBUG_PFMON
1687 printk("%lx=vcpu_get_pmc(%x)\n", val, reg);
1688 #endif
1689 *pval = val;
1690 return IA64_NO_FAULT;
1693 IA64FAULT vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval)
1695 // NOTE: Reads from unimplemented PMD registers return zero
1696 u64 val = (u64) ia64_get_pmd(reg);
1697 #ifdef DEBUG_PFMON
1698 printk("%lx=vcpu_get_pmd(%x)\n", val, reg);
1699 #endif
1700 *pval = val;
1701 return IA64_NO_FAULT;
1704 /**************************************************************************
1705 VCPU banked general register access routines
1706 **************************************************************************/
1707 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1708 do{ \
1709 __asm__ __volatile__ ( \
1710 ";;extr.u %0 = %3,%6,16;;\n" \
1711 "dep %1 = %0, %1, 0, 16;;\n" \
1712 "st8 [%4] = %1\n" \
1713 "extr.u %0 = %2, 16, 16;;\n" \
1714 "dep %3 = %0, %3, %6, 16;;\n" \
1715 "st8 [%5] = %3\n" \
1716 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1717 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1718 }while(0)
1720 IA64FAULT vcpu_bsw0(VCPU * vcpu)
1722 // TODO: Only allowed for current vcpu
1723 REGS *regs = vcpu_regs(vcpu);
1724 unsigned long *r = &regs->r16;
1725 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1726 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1727 unsigned long *runat = &regs->eml_unat;
1728 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1729 unsigned long *b1unat = &PSCB(vcpu, vnat);
1731 unsigned long i;
1733 if (VMX_DOMAIN(vcpu)) {
1734 if (VCPU(vcpu, vpsr) & IA64_PSR_BN) {
1735 for (i = 0; i < 16; i++) {
1736 *b1++ = *r;
1737 *r++ = *b0++;
1739 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1740 IA64_PT_REGS_R16_SLOT);
1741 VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
1743 } else {
1744 if (PSCB(vcpu, banknum)) {
1745 for (i = 0; i < 16; i++) {
1746 *b1++ = *r;
1747 *r++ = *b0++;
1749 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1750 IA64_PT_REGS_R16_SLOT);
1751 PSCB(vcpu, banknum) = 0;
1754 return IA64_NO_FAULT;
1757 #define vcpu_bsw1_unat(i, b0unat, b1unat, runat, IA64_PT_REGS_R16_SLOT) \
1758 do { \
1759 __asm__ __volatile__ (";;extr.u %0 = %3,%6,16;;\n" \
1760 "dep %1 = %0, %1, 16, 16;;\n" \
1761 "st8 [%4] = %1\n" \
1762 "extr.u %0 = %2, 0, 16;;\n" \
1763 "dep %3 = %0, %3, %6, 16;;\n" \
1764 "st8 [%5] = %3\n" \
1765 ::"r"(i), "r"(*b0unat), "r"(*b1unat), \
1766 "r"(*runat), "r"(b0unat), "r"(runat), \
1767 "i"(IA64_PT_REGS_R16_SLOT): "memory"); \
1768 } while(0)
1770 IA64FAULT vcpu_bsw1(VCPU * vcpu)
1772 // TODO: Only allowed for current vcpu
1773 REGS *regs = vcpu_regs(vcpu);
1774 unsigned long *r = &regs->r16;
1775 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1776 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1777 unsigned long *runat = &regs->eml_unat;
1778 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1779 unsigned long *b1unat = &PSCB(vcpu, vnat);
1781 unsigned long i;
1783 if (VMX_DOMAIN(vcpu)) {
1784 if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
1785 for (i = 0; i < 16; i++) {
1786 *b0++ = *r;
1787 *r++ = *b1++;
1789 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1790 IA64_PT_REGS_R16_SLOT);
1791 VCPU(vcpu, vpsr) |= IA64_PSR_BN;
1793 } else {
1794 if (!PSCB(vcpu, banknum)) {
1795 for (i = 0; i < 16; i++) {
1796 *b0++ = *r;
1797 *r++ = *b1++;
1799 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1800 IA64_PT_REGS_R16_SLOT);
1801 PSCB(vcpu, banknum) = 1;
1804 return IA64_NO_FAULT;
1807 /**************************************************************************
1808 VCPU cpuid access routines
1809 **************************************************************************/
1811 IA64FAULT vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval)
1813 // FIXME: This could get called as a result of a rsvd-reg fault
1814 // if reg > 3
1815 switch (reg) {
1816 case 0:
1817 memcpy(pval, "Xen/ia64", 8);
1818 break;
1819 case 1:
1820 *pval = 0;
1821 break;
1822 case 2:
1823 *pval = 0;
1824 break;
1825 case 3:
1826 *pval = ia64_get_cpuid(3);
1827 break;
1828 case 4:
1829 *pval = ia64_get_cpuid(4);
1830 break;
1831 default:
1832 if (reg > (ia64_get_cpuid(3) & 0xff))
1833 return IA64_RSVDREG_FAULT;
1834 *pval = ia64_get_cpuid(reg);
1835 break;
1837 return IA64_NO_FAULT;
1840 /**************************************************************************
1841 VCPU region register access routines
1842 **************************************************************************/
1844 unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
1846 ia64_rr rr;
1848 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
1849 return rr.ve;
1852 IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val)
1854 if (unlikely(is_reserved_rr_field(vcpu, val))) {
1855 gdprintk(XENLOG_DEBUG, "use of invalid rrval %lx\n", val);
1856 return IA64_RSVDREG_FAULT;
1859 PSCB(vcpu, rrs)[reg >> 61] = val;
1860 if (likely(vcpu == current)) {
1861 int rc = set_one_rr(reg, val);
1862 BUG_ON(rc == 0);
1864 return IA64_NO_FAULT;
1867 IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval)
1869 if (VMX_DOMAIN(vcpu))
1870 *pval = VMX(vcpu, vrr[reg >> 61]);
1871 else
1872 *pval = PSCB(vcpu, rrs)[reg >> 61];
1874 return IA64_NO_FAULT;
1877 IA64FAULT vcpu_set_rr0_to_rr4(VCPU * vcpu, u64 val0, u64 val1, u64 val2,
1878 u64 val3, u64 val4)
1880 u64 reg0 = 0x0000000000000000UL;
1881 u64 reg1 = 0x2000000000000000UL;
1882 u64 reg2 = 0x4000000000000000UL;
1883 u64 reg3 = 0x6000000000000000UL;
1884 u64 reg4 = 0x8000000000000000UL;
1886 if (unlikely(is_reserved_rr_field(vcpu, val0) ||
1887 is_reserved_rr_field(vcpu, val1) ||
1888 is_reserved_rr_field(vcpu, val2) ||
1889 is_reserved_rr_field(vcpu, val3) ||
1890 is_reserved_rr_field(vcpu, val4))) {
1891 gdprintk(XENLOG_DEBUG,
1892 "use of invalid rrval %lx %lx %lx %lx %lx\n",
1893 val0, val1, val2, val3, val4);
1894 return IA64_RSVDREG_FAULT;
1897 PSCB(vcpu, rrs)[reg0 >> 61] = val0;
1898 PSCB(vcpu, rrs)[reg1 >> 61] = val1;
1899 PSCB(vcpu, rrs)[reg2 >> 61] = val2;
1900 PSCB(vcpu, rrs)[reg3 >> 61] = val3;
1901 PSCB(vcpu, rrs)[reg4 >> 61] = val4;
1902 if (likely(vcpu == current)) {
1903 int rc;
1904 rc = !set_one_rr(reg0, val0);
1905 rc |= !set_one_rr(reg1, val1);
1906 rc |= !set_one_rr(reg2, val2);
1907 rc |= !set_one_rr(reg3, val3);
1908 rc |= !set_one_rr(reg4, val4);
1909 BUG_ON(rc != 0);
1911 return IA64_NO_FAULT;
1914 /**************************************************************************
1915 VCPU protection key register access routines
1916 **************************************************************************/
1918 IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
1920 if (reg > XEN_IA64_NPKRS)
1921 return IA64_RSVDREG_FAULT; /* register index to large */
1923 *pval = (u64) PSCBX(vcpu, pkrs[reg]);
1924 return IA64_NO_FAULT;
1927 IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
1929 ia64_pkr_t pkr_new;
1931 if (reg >= XEN_IA64_NPKRS)
1932 return IA64_RSVDREG_FAULT; /* index to large */
1934 pkr_new.val = val;
1935 if (pkr_new.reserved1)
1936 return IA64_RSVDREG_FAULT; /* reserved field */
1938 if (pkr_new.reserved2)
1939 return IA64_RSVDREG_FAULT; /* reserved field */
1941 PSCBX(vcpu, pkrs[reg]) = pkr_new.val;
1942 ia64_set_pkr(reg, pkr_new.val);
1944 return IA64_NO_FAULT;
1947 /**************************************************************************
1948 VCPU translation register access routines
1949 **************************************************************************/
1951 static void
1952 vcpu_set_tr_entry_rid(TR_ENTRY * trp, u64 pte,
1953 u64 itir, u64 ifa, u64 rid)
1955 u64 ps;
1956 union pte_flags new_pte;
1958 trp->itir = itir;
1959 trp->rid = rid;
1960 ps = trp->ps;
1961 new_pte.val = pte;
1962 if (new_pte.pl < CONFIG_CPL0_EMUL)
1963 new_pte.pl = CONFIG_CPL0_EMUL;
1964 trp->vadr = ifa & ~0xfff;
1965 if (ps > 12) { // "ignore" relevant low-order bits
1966 new_pte.ppn &= ~((1UL << (ps - 12)) - 1);
1967 trp->vadr &= ~((1UL << ps) - 1);
1970 /* Atomic write. */
1971 trp->pte.val = new_pte.val;
1974 static inline void
1975 vcpu_set_tr_entry(TR_ENTRY * trp, u64 pte, u64 itir, u64 ifa)
1977 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
1978 VCPU(current, rrs[ifa >> 61]) & RR_RID_MASK);
1981 IA64FAULT vcpu_itr_d(VCPU * vcpu, u64 slot, u64 pte,
1982 u64 itir, u64 ifa)
1984 TR_ENTRY *trp;
1986 if (slot >= NDTRS)
1987 return IA64_RSVDREG_FAULT;
1989 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
1991 trp = &PSCBX(vcpu, dtrs[slot]);
1992 //printk("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
1993 vcpu_set_tr_entry(trp, pte, itir, ifa);
1994 vcpu_quick_region_set(PSCBX(vcpu, dtr_regions), ifa);
1996 /*
1997 * FIXME According to spec, vhpt should be purged, but this
1998 * incurs considerable performance loss, since it is safe for
1999 * linux not to purge vhpt, vhpt purge is disabled until a
2000 * feasible way is found.
2002 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2003 */
2005 return IA64_NO_FAULT;
2008 IA64FAULT vcpu_itr_i(VCPU * vcpu, u64 slot, u64 pte,
2009 u64 itir, u64 ifa)
2011 TR_ENTRY *trp;
2013 if (slot >= NITRS)
2014 return IA64_RSVDREG_FAULT;
2016 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2018 trp = &PSCBX(vcpu, itrs[slot]);
2019 //printk("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
2020 vcpu_set_tr_entry(trp, pte, itir, ifa);
2021 vcpu_quick_region_set(PSCBX(vcpu, itr_regions), ifa);
2023 /*
2024 * FIXME According to spec, vhpt should be purged, but this
2025 * incurs considerable performance loss, since it is safe for
2026 * linux not to purge vhpt, vhpt purge is disabled until a
2027 * feasible way is found.
2029 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2030 */
2032 return IA64_NO_FAULT;
2035 IA64FAULT vcpu_set_itr(VCPU * vcpu, u64 slot, u64 pte,
2036 u64 itir, u64 ifa, u64 rid)
2038 TR_ENTRY *trp;
2040 if (slot >= NITRS)
2041 return IA64_RSVDREG_FAULT;
2042 trp = &PSCBX(vcpu, itrs[slot]);
2043 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2045 /* Recompute the itr_region. */
2046 vcpu->arch.itr_regions = 0;
2047 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
2048 if (trp->pte.p)
2049 vcpu_quick_region_set(vcpu->arch.itr_regions,
2050 trp->vadr);
2051 return IA64_NO_FAULT;
2054 IA64FAULT vcpu_set_dtr(VCPU * vcpu, u64 slot, u64 pte,
2055 u64 itir, u64 ifa, u64 rid)
2057 TR_ENTRY *trp;
2059 if (slot >= NDTRS)
2060 return IA64_RSVDREG_FAULT;
2061 trp = &PSCBX(vcpu, dtrs[slot]);
2062 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2064 /* Recompute the dtr_region. */
2065 vcpu->arch.dtr_regions = 0;
2066 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
2067 if (trp->pte.p)
2068 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2069 trp->vadr);
2070 return IA64_NO_FAULT;
2073 /**************************************************************************
2074 VCPU translation cache access routines
2075 **************************************************************************/
2077 static void
2078 vcpu_rebuild_vhpt(VCPU * vcpu, u64 ps)
2080 #ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
2081 printk("vhpt rebuild: using page_shift %d\n", (int)ps);
2082 vcpu->arch.vhpt_pg_shift = ps;
2083 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2084 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2085 local_vhpt_flush();
2086 load_region_regs(vcpu);
2087 #else
2088 panic_domain(NULL, "domain trying to use smaller page size!\n");
2089 #endif
2092 void
2093 vcpu_itc_no_srlz(VCPU * vcpu, u64 IorD, u64 vaddr, u64 pte,
2094 u64 mp_pte, u64 itir, struct p2m_entry *entry)
2096 ia64_itir_t _itir = {.itir = itir};
2097 unsigned long psr;
2099 check_xen_space_overlap("itc", vaddr, 1UL << _itir.ps);
2101 // FIXME, must be inlined or potential for nested fault here!
2102 if ((vcpu->domain == dom0) && (_itir.ps < PAGE_SHIFT))
2103 panic_domain(NULL, "vcpu_itc_no_srlz: domain trying to use "
2104 "smaller page size!\n");
2106 BUG_ON(_itir.ps > PAGE_SHIFT);
2107 vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry);
2108 psr = ia64_clear_ic();
2109 pte &= ~(_PAGE_RV2 | _PAGE_RV1); // Mask out the reserved bits.
2110 // FIXME: look for bigger mappings
2111 ia64_itc(IorD, vaddr, pte, _itir.itir);
2112 ia64_set_psr(psr);
2113 // ia64_srlz_i(); // no srls req'd, will rfi later
2114 if (vcpu->domain == dom0 && ((vaddr >> 61) == 7)) {
2115 // FIXME: this is dangerous... vhpt_flush_address ensures these
2116 // addresses never get flushed. More work needed if this
2117 // ever happens.
2118 //printk("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2119 if (_itir.ps > vcpu->arch.vhpt_pg_shift)
2120 vhpt_multiple_insert(vaddr, pte, _itir.itir);
2121 else
2122 vhpt_insert(vaddr, pte, _itir.itir);
2124 // even if domain pagesize is larger than PAGE_SIZE, just put
2125 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2126 else {
2127 vhpt_insert(vaddr, pte, _itir.itir);
2131 IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2133 unsigned long pteval;
2134 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2135 struct p2m_entry entry;
2136 ia64_itir_t _itir = {.itir = itir};
2138 if (_itir.ps < vcpu->arch.vhpt_pg_shift)
2139 vcpu_rebuild_vhpt(vcpu, _itir.ps);
2141 again:
2142 //itir = (itir & ~0xfc) | (vcpu->arch.vhpt_pg_shift<<2); // ign dom pgsz
2143 pteval = translate_domain_pte(pte, ifa, itir, &(_itir.itir), &entry);
2144 if (!pteval)
2145 return IA64_ILLOP_FAULT;
2146 if (swap_rr0)
2147 set_virtual_rr0();
2148 vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, _itir.itir, &entry);
2149 if (swap_rr0)
2150 set_metaphysical_rr0();
2151 if (p2m_entry_retry(&entry)) {
2152 vcpu_flush_tlb_vhpt_range(ifa, _itir.ps);
2153 goto again;
2155 vcpu_set_tr_entry(&PSCBX(vcpu, dtlb), pte, itir, ifa);
2156 return IA64_NO_FAULT;
2159 IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2161 unsigned long pteval;
2162 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2163 struct p2m_entry entry;
2164 ia64_itir_t _itir = {.itir = itir};
2166 if (_itir.ps < vcpu->arch.vhpt_pg_shift)
2167 vcpu_rebuild_vhpt(vcpu, _itir.ps);
2169 again:
2170 //itir = (itir & ~0xfc) | (vcpu->arch.vhpt_pg_shift<<2); // ign dom pgsz
2171 pteval = translate_domain_pte(pte, ifa, itir, &(_itir.itir), &entry);
2172 if (!pteval)
2173 return IA64_ILLOP_FAULT;
2174 if (swap_rr0)
2175 set_virtual_rr0();
2176 vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, _itir.itir, &entry);
2177 if (swap_rr0)
2178 set_metaphysical_rr0();
2179 if (p2m_entry_retry(&entry)) {
2180 vcpu_flush_tlb_vhpt_range(ifa, _itir.ps);
2181 goto again;
2183 vcpu_set_tr_entry(&PSCBX(vcpu, itlb), pte, itir, ifa);
2184 return IA64_NO_FAULT;
2187 IA64FAULT vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 log_range)
2189 BUG_ON(vcpu != current);
2191 check_xen_space_overlap("ptc_l", vadr, 1UL << log_range);
2193 /* Purge TC */
2194 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2195 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2197 /* Purge all tlb and vhpt */
2198 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2200 return IA64_NO_FAULT;
2203 // At privlvl=0, fc performs no access rights or protection key checks, while
2204 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2205 // read but no protection key check. Thus in order to avoid an unexpected
2206 // access rights fault, we have to translate the virtual address to a
2207 // physical address (possibly via a metaphysical address) and do the fc
2208 // on the physical address, which is guaranteed to flush the same cache line
2209 IA64FAULT vcpu_fc(VCPU * vcpu, u64 vadr)
2211 // TODO: Only allowed for current vcpu
2212 u64 mpaddr, paddr;
2213 IA64FAULT fault;
2215 again:
2216 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2217 if (fault == IA64_NO_FAULT) {
2218 struct p2m_entry entry;
2219 paddr = translate_domain_mpaddr(mpaddr, &entry);
2220 ia64_fc(__va(paddr));
2221 if (p2m_entry_retry(&entry))
2222 goto again;
2224 return fault;
2227 IA64FAULT vcpu_ptc_e(VCPU * vcpu, u64 vadr)
2229 // Note that this only needs to be called once, i.e. the
2230 // architected loop to purge the entire TLB, should use
2231 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2233 vcpu_flush_vtlb_all(current);
2235 return IA64_NO_FAULT;
2238 IA64FAULT vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 addr_range)
2240 printk("vcpu_ptc_g: called, not implemented yet\n");
2241 return IA64_ILLOP_FAULT;
2244 IA64FAULT vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 addr_range)
2246 // FIXME: validate not flushing Xen addresses
2247 // if (Xen address) return(IA64_ILLOP_FAULT);
2248 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2249 //printk("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2251 check_xen_space_overlap("ptc_ga", vadr, addr_range);
2253 domain_flush_vtlb_range(vcpu->domain, vadr, addr_range);
2255 return IA64_NO_FAULT;
2258 IA64FAULT vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 log_range)
2260 unsigned long region = vadr >> 61;
2261 u64 addr_range = 1UL << log_range;
2262 unsigned long rid, rr;
2263 int i;
2264 TR_ENTRY *trp;
2266 BUG_ON(vcpu != current);
2267 check_xen_space_overlap("ptr_d", vadr, 1UL << log_range);
2269 rr = PSCB(vcpu, rrs)[region];
2270 rid = rr & RR_RID_MASK;
2272 /* Purge TC */
2273 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2275 /* Purge tr and recompute dtr_regions. */
2276 vcpu->arch.dtr_regions = 0;
2277 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2278 if (vcpu_match_tr_entry_range
2279 (trp, rid, vadr, vadr + addr_range))
2280 vcpu_purge_tr_entry(trp);
2281 else if (trp->pte.p)
2282 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2283 trp->vadr);
2285 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2287 return IA64_NO_FAULT;
2290 IA64FAULT vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 log_range)
2292 unsigned long region = vadr >> 61;
2293 u64 addr_range = 1UL << log_range;
2294 unsigned long rid, rr;
2295 int i;
2296 TR_ENTRY *trp;
2298 BUG_ON(vcpu != current);
2299 check_xen_space_overlap("ptr_i", vadr, 1UL << log_range);
2301 rr = PSCB(vcpu, rrs)[region];
2302 rid = rr & RR_RID_MASK;
2304 /* Purge TC */
2305 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2307 /* Purge tr and recompute itr_regions. */
2308 vcpu->arch.itr_regions = 0;
2309 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2310 if (vcpu_match_tr_entry_range
2311 (trp, rid, vadr, vadr + addr_range))
2312 vcpu_purge_tr_entry(trp);
2313 else if (trp->pte.p)
2314 vcpu_quick_region_set(vcpu->arch.itr_regions,
2315 trp->vadr);
2317 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2319 return IA64_NO_FAULT;