direct-io.hg

view xen/arch/ia64/xen/vcpu.c @ 13450:912f8af36878

[IA64] tidy up vcpu_set_itc error message

This patch enhances the error message in question in two minor ways

* typo fix: one -> once
* Print the entire message at once, otherwise it
seems to end up geting interlaced with other dom0 kernel
messages on the console (on my system at least).

Signed-Off-By: Simon Horman <horms@verge.net.au>
author awilliam@xenbuild2.aw
date Tue Jan 02 16:42:09 2007 -0700 (2007-01-02)
parents a50fd1fed61e
children b440f5dbca1f
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_LFMT (1UL << IA64_PTA_VF_BIT)
53 #define IA64_PTA_SZ(x) (x##UL << IA64_PTA_SZ_BIT)
55 unsigned long vcpu_verbose = 0;
57 /**************************************************************************
58 VCPU general register access routines
59 **************************************************************************/
60 #ifdef XEN
61 u64 vcpu_get_gr(VCPU * vcpu, unsigned long reg)
62 {
63 REGS *regs = vcpu_regs(vcpu);
64 u64 val;
66 if (!reg)
67 return 0;
68 getreg(reg, &val, 0, regs); // FIXME: handle NATs later
69 return val;
70 }
72 IA64FAULT vcpu_get_gr_nat(VCPU * vcpu, unsigned long reg, u64 * val)
73 {
74 REGS *regs = vcpu_regs(vcpu);
75 int nat;
77 getreg(reg, val, &nat, regs); // FIXME: handle NATs later
78 if (nat)
79 return IA64_NAT_CONSUMPTION_VECTOR;
80 return 0;
81 }
83 // returns:
84 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
85 // IA64_NO_FAULT otherwise
86 IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value, int nat)
87 {
88 REGS *regs = vcpu_regs(vcpu);
89 long sof = (regs->cr_ifs) & 0x7f;
91 if (!reg)
92 return IA64_ILLOP_FAULT;
93 if (reg >= sof + 32)
94 return IA64_ILLOP_FAULT;
95 setreg(reg, value, nat, regs); // FIXME: handle NATs later
96 return IA64_NO_FAULT;
97 }
99 IA64FAULT
100 vcpu_get_fpreg(VCPU * vcpu, unsigned long reg, struct ia64_fpreg * val)
101 {
102 REGS *regs = vcpu_regs(vcpu);
103 getfpreg(reg, val, regs); // FIXME: handle NATs later
104 return IA64_NO_FAULT;
105 }
107 IA64FAULT
108 vcpu_set_fpreg(VCPU * vcpu, unsigned long reg, struct ia64_fpreg * val)
109 {
110 REGS *regs = vcpu_regs(vcpu);
111 if (reg > 1)
112 setfpreg(reg, val, regs); // FIXME: handle NATs later
113 return IA64_NO_FAULT;
114 }
116 #else
117 // returns:
118 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
119 // IA64_NO_FAULT otherwise
120 IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value)
121 {
122 REGS *regs = vcpu_regs(vcpu);
123 long sof = (regs->cr_ifs) & 0x7f;
125 if (!reg)
126 return IA64_ILLOP_FAULT;
127 if (reg >= sof + 32)
128 return IA64_ILLOP_FAULT;
129 setreg(reg, value, 0, regs); // FIXME: handle NATs later
130 return IA64_NO_FAULT;
131 }
133 #endif
135 void vcpu_init_regs(struct vcpu *v)
136 {
137 struct pt_regs *regs;
139 regs = vcpu_regs(v);
140 if (VMX_DOMAIN(v)) {
141 /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
142 /* Need to be expanded as macro */
143 regs->cr_ipsr = 0x501008826008;
144 } else {
145 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
146 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
147 regs->cr_ipsr &= ~(IA64_PSR_BITS_TO_CLEAR
148 | IA64_PSR_RI | IA64_PSR_IS);
149 // domain runs at PL2
150 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
151 }
152 regs->cr_ifs = 1UL << 63; /* or clear? */
153 regs->ar_fpsr = FPSR_DEFAULT;
155 if (VMX_DOMAIN(v)) {
156 vmx_init_all_rr(v);
157 /* Virtual processor context setup */
158 VCPU(v, vpsr) = IA64_PSR_BN;
159 VCPU(v, dcr) = 0;
160 } else {
161 init_all_rr(v);
162 regs->ar_rsc |= (2 << 2); /* force PL2/3 */
163 VCPU(v, banknum) = 1;
164 VCPU(v, metaphysical_mode) = 1;
165 VCPU(v, interrupt_mask_addr) =
166 (unsigned char *)v->domain->arch.shared_info_va +
167 INT_ENABLE_OFFSET(v);
168 VCPU(v, itv) = (1 << 16); /* timer vector masked */
169 }
171 v->arch.domain_itm_last = -1L;
172 }
174 /**************************************************************************
175 VCPU privileged application register access routines
176 **************************************************************************/
178 void vcpu_load_kernel_regs(VCPU * vcpu)
179 {
180 ia64_set_kr(0, VCPU(vcpu, krs[0]));
181 ia64_set_kr(1, VCPU(vcpu, krs[1]));
182 ia64_set_kr(2, VCPU(vcpu, krs[2]));
183 ia64_set_kr(3, VCPU(vcpu, krs[3]));
184 ia64_set_kr(4, VCPU(vcpu, krs[4]));
185 ia64_set_kr(5, VCPU(vcpu, krs[5]));
186 ia64_set_kr(6, VCPU(vcpu, krs[6]));
187 ia64_set_kr(7, VCPU(vcpu, krs[7]));
188 }
190 /* GCC 4.0.2 seems not to be able to suppress this call!. */
191 #define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
193 IA64FAULT vcpu_set_ar(VCPU * vcpu, u64 reg, u64 val)
194 {
195 if (reg == 44)
196 return vcpu_set_itc(vcpu, val);
197 else if (reg == 27)
198 return IA64_ILLOP_FAULT;
199 else if (reg == 24)
200 printk("warning: setting ar.eflg is a no-op; no IA-32 "
201 "support\n");
202 else if (reg > 7)
203 return IA64_ILLOP_FAULT;
204 else {
205 PSCB(vcpu, krs[reg]) = val;
206 ia64_set_kr(reg, val);
207 }
208 return IA64_NO_FAULT;
209 }
211 IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 reg, u64 * val)
212 {
213 if (reg == 24)
214 printk("warning: getting ar.eflg is a no-op; no IA-32 "
215 "support\n");
216 else if (reg > 7)
217 return IA64_ILLOP_FAULT;
218 else
219 *val = PSCB(vcpu, krs[reg]);
220 return IA64_NO_FAULT;
221 }
223 /**************************************************************************
224 VCPU processor status register access routines
225 **************************************************************************/
227 void vcpu_set_metaphysical_mode(VCPU * vcpu, BOOLEAN newmode)
228 {
229 /* only do something if mode changes */
230 if (!!newmode ^ !!PSCB(vcpu, metaphysical_mode)) {
231 PSCB(vcpu, metaphysical_mode) = newmode;
232 if (newmode)
233 set_metaphysical_rr0();
234 else if (PSCB(vcpu, rrs[0]) != -1)
235 set_one_rr(0, PSCB(vcpu, rrs[0]));
236 }
237 }
239 IA64FAULT vcpu_reset_psr_dt(VCPU * vcpu)
240 {
241 vcpu_set_metaphysical_mode(vcpu, TRUE);
242 return IA64_NO_FAULT;
243 }
245 IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24)
246 {
247 struct ia64_psr psr, imm, *ipsr;
248 REGS *regs = vcpu_regs(vcpu);
250 //PRIVOP_COUNT_ADDR(regs,_RSM);
251 // TODO: All of these bits need to be virtualized
252 // TODO: Only allowed for current vcpu
253 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
254 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
255 imm = *(struct ia64_psr *)&imm24;
256 // interrupt flag
257 if (imm.i)
258 vcpu->vcpu_info->evtchn_upcall_mask = 1;
259 if (imm.ic)
260 PSCB(vcpu, interrupt_collection_enabled) = 0;
261 // interrupt collection flag
262 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
263 // just handle psr.up and psr.pp for now
264 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
265 IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
266 IA64_PSR_DFL | IA64_PSR_DFH))
267 return IA64_ILLOP_FAULT;
268 if (imm.dfh)
269 ipsr->dfh = 0;
270 if (imm.dfl)
271 ipsr->dfl = 0;
272 if (imm.pp) {
273 ipsr->pp = 1;
274 psr.pp = 1; // priv perf ctrs always enabled
275 PSCB(vcpu, vpsr_pp) = 0; // but fool the domain if it gets psr
276 }
277 if (imm.up) {
278 ipsr->up = 0;
279 psr.up = 0;
280 }
281 if (imm.sp) {
282 ipsr->sp = 0;
283 psr.sp = 0;
284 }
285 if (imm.be)
286 ipsr->be = 0;
287 if (imm.dt)
288 vcpu_set_metaphysical_mode(vcpu, TRUE);
289 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
290 return IA64_NO_FAULT;
291 }
293 IA64FAULT vcpu_set_psr_dt(VCPU * vcpu)
294 {
295 vcpu_set_metaphysical_mode(vcpu, FALSE);
296 return IA64_NO_FAULT;
297 }
299 IA64FAULT vcpu_set_psr_i(VCPU * vcpu)
300 {
301 vcpu->vcpu_info->evtchn_upcall_mask = 0;
302 PSCB(vcpu, interrupt_collection_enabled) = 1;
303 return IA64_NO_FAULT;
304 }
306 IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24)
307 {
308 struct ia64_psr psr, imm, *ipsr;
309 REGS *regs = vcpu_regs(vcpu);
310 u64 mask, enabling_interrupts = 0;
312 //PRIVOP_COUNT_ADDR(regs,_SSM);
313 // TODO: All of these bits need to be virtualized
314 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
315 imm = *(struct ia64_psr *)&imm24;
316 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
317 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
318 mask =
319 IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
320 IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH;
321 if (imm24 & ~mask)
322 return IA64_ILLOP_FAULT;
323 if (imm.dfh)
324 ipsr->dfh = 1;
325 if (imm.dfl)
326 ipsr->dfl = 1;
327 if (imm.pp) {
328 ipsr->pp = 1;
329 psr.pp = 1;
330 PSCB(vcpu, vpsr_pp) = 1;
331 }
332 if (imm.sp) {
333 ipsr->sp = 1;
334 psr.sp = 1;
335 }
336 if (imm.i) {
337 if (vcpu->vcpu_info->evtchn_upcall_mask) {
338 //printk("vcpu_set_psr_sm: psr.ic 0->1\n");
339 enabling_interrupts = 1;
340 }
341 vcpu->vcpu_info->evtchn_upcall_mask = 0;
342 }
343 if (imm.ic)
344 PSCB(vcpu, interrupt_collection_enabled) = 1;
345 // TODO: do this faster
346 if (imm.mfl) {
347 ipsr->mfl = 1;
348 psr.mfl = 1;
349 }
350 if (imm.mfh) {
351 ipsr->mfh = 1;
352 psr.mfh = 1;
353 }
354 if (imm.ac) {
355 ipsr->ac = 1;
356 psr.ac = 1;
357 }
358 if (imm.up) {
359 ipsr->up = 1;
360 psr.up = 1;
361 }
362 if (imm.be) {
363 printk("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
364 return IA64_ILLOP_FAULT;
365 }
366 if (imm.dt)
367 vcpu_set_metaphysical_mode(vcpu, FALSE);
368 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
369 if (enabling_interrupts &&
370 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
371 PSCB(vcpu, pending_interruption) = 1;
372 return IA64_NO_FAULT;
373 }
375 IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val)
376 {
377 struct ia64_psr psr, newpsr, *ipsr;
378 REGS *regs = vcpu_regs(vcpu);
379 u64 enabling_interrupts = 0;
381 // TODO: All of these bits need to be virtualized
382 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
383 newpsr = *(struct ia64_psr *)&val;
384 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
385 // just handle psr.up and psr.pp for now
386 //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP))
387 // return IA64_ILLOP_FAULT;
388 // however trying to set other bits can't be an error as it is in ssm
389 if (newpsr.dfh)
390 ipsr->dfh = 1;
391 if (newpsr.dfl)
392 ipsr->dfl = 1;
393 if (newpsr.pp) {
394 ipsr->pp = 1;
395 psr.pp = 1;
396 PSCB(vcpu, vpsr_pp) = 1;
397 } else {
398 ipsr->pp = 1;
399 psr.pp = 1;
400 PSCB(vcpu, vpsr_pp) = 0;
401 }
402 if (newpsr.up) {
403 ipsr->up = 1;
404 psr.up = 1;
405 }
406 if (newpsr.sp) {
407 ipsr->sp = 1;
408 psr.sp = 1;
409 }
410 if (newpsr.i) {
411 if (vcpu->vcpu_info->evtchn_upcall_mask)
412 enabling_interrupts = 1;
413 vcpu->vcpu_info->evtchn_upcall_mask = 0;
414 }
415 if (newpsr.ic)
416 PSCB(vcpu, interrupt_collection_enabled) = 1;
417 if (newpsr.mfl) {
418 ipsr->mfl = 1;
419 psr.mfl = 1;
420 }
421 if (newpsr.mfh) {
422 ipsr->mfh = 1;
423 psr.mfh = 1;
424 }
425 if (newpsr.ac) {
426 ipsr->ac = 1;
427 psr.ac = 1;
428 }
429 if (newpsr.up) {
430 ipsr->up = 1;
431 psr.up = 1;
432 }
433 if (newpsr.dt && newpsr.rt)
434 vcpu_set_metaphysical_mode(vcpu, FALSE);
435 else
436 vcpu_set_metaphysical_mode(vcpu, TRUE);
437 if (newpsr.be) {
438 printk("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
439 return IA64_ILLOP_FAULT;
440 }
441 if (enabling_interrupts &&
442 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
443 PSCB(vcpu, pending_interruption) = 1;
444 return IA64_NO_FAULT;
445 }
447 IA64FAULT vcpu_get_psr(VCPU * vcpu, u64 * pval)
448 {
449 REGS *regs = vcpu_regs(vcpu);
450 struct ia64_psr newpsr;
452 newpsr = *(struct ia64_psr *)&regs->cr_ipsr;
453 if (!vcpu->vcpu_info->evtchn_upcall_mask)
454 newpsr.i = 1;
455 else
456 newpsr.i = 0;
457 if (PSCB(vcpu, interrupt_collection_enabled))
458 newpsr.ic = 1;
459 else
460 newpsr.ic = 0;
461 if (PSCB(vcpu, metaphysical_mode))
462 newpsr.dt = 0;
463 else
464 newpsr.dt = 1;
465 if (PSCB(vcpu, vpsr_pp))
466 newpsr.pp = 1;
467 else
468 newpsr.pp = 0;
469 *pval = *(unsigned long *)&newpsr;
470 *pval &= (MASK(0, 32) | MASK(35, 2));
471 return IA64_NO_FAULT;
472 }
474 BOOLEAN vcpu_get_psr_ic(VCPU * vcpu)
475 {
476 return !!PSCB(vcpu, interrupt_collection_enabled);
477 }
479 BOOLEAN vcpu_get_psr_i(VCPU * vcpu)
480 {
481 return !vcpu->vcpu_info->evtchn_upcall_mask;
482 }
484 u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr)
485 {
486 u64 dcr = PSCBX(vcpu, dcr);
487 PSR psr;
489 //printk("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr);
490 psr.i64 = prevpsr;
491 psr.ia64_psr.be = 0;
492 if (dcr & IA64_DCR_BE)
493 psr.ia64_psr.be = 1;
494 psr.ia64_psr.pp = 0;
495 if (dcr & IA64_DCR_PP)
496 psr.ia64_psr.pp = 1;
497 psr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled);
498 psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
499 psr.ia64_psr.bn = PSCB(vcpu, banknum);
500 psr.ia64_psr.dt = 1;
501 psr.ia64_psr.it = 1;
502 psr.ia64_psr.rt = 1;
503 if (psr.ia64_psr.cpl == 2)
504 psr.ia64_psr.cpl = 0; // !!!! fool domain
505 // psr.pk = 1;
506 //printk("returns 0x%016lx...\n",psr.i64);
507 return psr.i64;
508 }
510 /**************************************************************************
511 VCPU control register access routines
512 **************************************************************************/
514 IA64FAULT vcpu_get_dcr(VCPU * vcpu, u64 * pval)
515 {
516 //verbose("vcpu_get_dcr: called @%p\n",PSCB(vcpu,iip));
517 // Reads of cr.dcr on Xen always have the sign bit set, so
518 // a domain can differentiate whether it is running on SP or not
519 *pval = PSCBX(vcpu, dcr) | 0x8000000000000000L;
520 return IA64_NO_FAULT;
521 }
523 IA64FAULT vcpu_get_iva(VCPU * vcpu, u64 * pval)
524 {
525 if (VMX_DOMAIN(vcpu))
526 *pval = PSCB(vcpu, iva) & ~0x7fffL;
527 else
528 *pval = PSCBX(vcpu, iva) & ~0x7fffL;
530 return IA64_NO_FAULT;
531 }
533 IA64FAULT vcpu_get_pta(VCPU * vcpu, u64 * pval)
534 {
535 *pval = PSCB(vcpu, pta);
536 return IA64_NO_FAULT;
537 }
539 IA64FAULT vcpu_get_ipsr(VCPU * vcpu, u64 * pval)
540 {
541 //REGS *regs = vcpu_regs(vcpu);
542 //*pval = regs->cr_ipsr;
543 *pval = PSCB(vcpu, ipsr);
544 return IA64_NO_FAULT;
545 }
547 IA64FAULT vcpu_get_isr(VCPU * vcpu, u64 * pval)
548 {
549 *pval = PSCB(vcpu, isr);
550 return IA64_NO_FAULT;
551 }
553 IA64FAULT vcpu_get_iip(VCPU * vcpu, u64 * pval)
554 {
555 //REGS *regs = vcpu_regs(vcpu);
556 //*pval = regs->cr_iip;
557 *pval = PSCB(vcpu, iip);
558 return IA64_NO_FAULT;
559 }
561 IA64FAULT vcpu_get_ifa(VCPU * vcpu, u64 * pval)
562 {
563 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_get_ifa);
564 *pval = PSCB(vcpu, ifa);
565 return IA64_NO_FAULT;
566 }
568 unsigned long vcpu_get_rr_ps(VCPU * vcpu, u64 vadr)
569 {
570 ia64_rr rr;
572 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
573 return rr.ps;
574 }
576 unsigned long vcpu_get_rr_rid(VCPU * vcpu, u64 vadr)
577 {
578 ia64_rr rr;
580 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
581 return rr.rid;
582 }
584 unsigned long vcpu_get_itir_on_fault(VCPU * vcpu, u64 ifa)
585 {
586 ia64_rr rr;
588 rr.rrval = 0;
589 rr.ps = vcpu_get_rr_ps(vcpu, ifa);
590 rr.rid = vcpu_get_rr_rid(vcpu, ifa);
591 return rr.rrval;
592 }
594 IA64FAULT vcpu_get_itir(VCPU * vcpu, u64 * pval)
595 {
596 u64 val = PSCB(vcpu, itir);
597 *pval = val;
598 return IA64_NO_FAULT;
599 }
601 IA64FAULT vcpu_get_iipa(VCPU * vcpu, u64 * pval)
602 {
603 u64 val = PSCB(vcpu, iipa);
604 // SP entry code does not save iipa yet nor does it get
605 // properly delivered in the pscb
606 // printk("*** vcpu_get_iipa: cr.iipa not fully implemented yet!!\n");
607 *pval = val;
608 return IA64_NO_FAULT;
609 }
611 IA64FAULT vcpu_get_ifs(VCPU * vcpu, u64 * pval)
612 {
613 //PSCB(vcpu,ifs) = PSCB(vcpu)->regs.cr_ifs;
614 //*pval = PSCB(vcpu,regs).cr_ifs;
615 *pval = PSCB(vcpu, ifs);
616 PSCB(vcpu, incomplete_regframe) = 0;
617 return IA64_NO_FAULT;
618 }
620 IA64FAULT vcpu_get_iim(VCPU * vcpu, u64 * pval)
621 {
622 u64 val = PSCB(vcpu, iim);
623 *pval = val;
624 return IA64_NO_FAULT;
625 }
627 IA64FAULT vcpu_get_iha(VCPU * vcpu, u64 * pval)
628 {
629 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_thash);
630 *pval = PSCB(vcpu, iha);
631 return IA64_NO_FAULT;
632 }
634 IA64FAULT vcpu_set_dcr(VCPU * vcpu, u64 val)
635 {
636 // Reads of cr.dcr on SP always have the sign bit set, so
637 // a domain can differentiate whether it is running on SP or not
638 // Thus, writes of DCR should ignore the sign bit
639 //verbose("vcpu_set_dcr: called\n");
640 PSCBX(vcpu, dcr) = val & ~0x8000000000000000L;
641 return IA64_NO_FAULT;
642 }
644 IA64FAULT vcpu_set_iva(VCPU * vcpu, u64 val)
645 {
646 if (VMX_DOMAIN(vcpu))
647 PSCB(vcpu, iva) = val & ~0x7fffL;
648 else
649 PSCBX(vcpu, iva) = val & ~0x7fffL;
651 return IA64_NO_FAULT;
652 }
654 IA64FAULT vcpu_set_pta(VCPU * vcpu, u64 val)
655 {
656 if (val & IA64_PTA_LFMT) {
657 printk("*** No support for VHPT long format yet!!\n");
658 return IA64_ILLOP_FAULT;
659 }
660 if (val & (0x3f << 9)) /* reserved fields */
661 return IA64_RSVDREG_FAULT;
662 if (val & 2) /* reserved fields */
663 return IA64_RSVDREG_FAULT;
664 PSCB(vcpu, pta) = val;
665 return IA64_NO_FAULT;
666 }
668 IA64FAULT vcpu_set_ipsr(VCPU * vcpu, u64 val)
669 {
670 PSCB(vcpu, ipsr) = val;
671 return IA64_NO_FAULT;
672 }
674 IA64FAULT vcpu_set_isr(VCPU * vcpu, u64 val)
675 {
676 PSCB(vcpu, isr) = val;
677 return IA64_NO_FAULT;
678 }
680 IA64FAULT vcpu_set_iip(VCPU * vcpu, u64 val)
681 {
682 PSCB(vcpu, iip) = val;
683 return IA64_NO_FAULT;
684 }
686 IA64FAULT vcpu_increment_iip(VCPU * vcpu)
687 {
688 REGS *regs = vcpu_regs(vcpu);
689 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
690 if (ipsr->ri == 2) {
691 ipsr->ri = 0;
692 regs->cr_iip += 16;
693 } else
694 ipsr->ri++;
695 return IA64_NO_FAULT;
696 }
698 IA64FAULT vcpu_set_ifa(VCPU * vcpu, u64 val)
699 {
700 PSCB(vcpu, ifa) = val;
701 return IA64_NO_FAULT;
702 }
704 IA64FAULT vcpu_set_itir(VCPU * vcpu, u64 val)
705 {
706 PSCB(vcpu, itir) = val;
707 return IA64_NO_FAULT;
708 }
710 IA64FAULT vcpu_set_iipa(VCPU * vcpu, u64 val)
711 {
712 // SP entry code does not save iipa yet nor does it get
713 // properly delivered in the pscb
714 // printk("*** vcpu_set_iipa: cr.iipa not fully implemented yet!!\n");
715 PSCB(vcpu, iipa) = val;
716 return IA64_NO_FAULT;
717 }
719 IA64FAULT vcpu_set_ifs(VCPU * vcpu, u64 val)
720 {
721 //REGS *regs = vcpu_regs(vcpu);
722 PSCB(vcpu, ifs) = val;
723 return IA64_NO_FAULT;
724 }
726 IA64FAULT vcpu_set_iim(VCPU * vcpu, u64 val)
727 {
728 PSCB(vcpu, iim) = val;
729 return IA64_NO_FAULT;
730 }
732 IA64FAULT vcpu_set_iha(VCPU * vcpu, u64 val)
733 {
734 PSCB(vcpu, iha) = val;
735 return IA64_NO_FAULT;
736 }
738 /**************************************************************************
739 VCPU interrupt control register access routines
740 **************************************************************************/
742 void vcpu_pend_unspecified_interrupt(VCPU * vcpu)
743 {
744 PSCB(vcpu, pending_interruption) = 1;
745 }
747 void vcpu_pend_interrupt(VCPU * vcpu, u64 vector)
748 {
749 if (vector & ~0xff) {
750 printk("vcpu_pend_interrupt: bad vector\n");
751 return;
752 }
754 if (vcpu->arch.event_callback_ip) {
755 printk("Deprecated interface. Move to new event based "
756 "solution\n");
757 return;
758 }
760 if (VMX_DOMAIN(vcpu)) {
761 set_bit(vector, VCPU(vcpu, irr));
762 } else {
763 set_bit(vector, PSCBX(vcpu, irr));
764 PSCB(vcpu, pending_interruption) = 1;
765 }
766 }
768 #define IA64_TPR_MMI 0x10000
769 #define IA64_TPR_MIC 0x000f0
771 /* checks to see if a VCPU has any unmasked pending interrupts
772 * if so, returns the highest, else returns SPURIOUS_VECTOR */
773 /* NOTE: Since this gets called from vcpu_get_ivr() and the
774 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
775 * this routine also ignores pscb.interrupt_delivery_enabled
776 * and this must be checked independently; see vcpu_deliverable interrupts() */
777 u64 vcpu_check_pending_interrupts(VCPU * vcpu)
778 {
779 u64 *p, *r, bits, bitnum, mask, i, vector;
781 if (vcpu->arch.event_callback_ip)
782 return SPURIOUS_VECTOR;
784 /* Always check pending event, since guest may just ack the
785 * event injection without handle. Later guest may throw out
786 * the event itself.
787 */
788 check_start:
789 if (event_pending(vcpu) &&
790 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
791 &PSCBX(vcpu, insvc[0])))
792 vcpu_pend_interrupt(vcpu,
793 vcpu->domain->shared_info->arch.
794 evtchn_vector);
796 p = &PSCBX(vcpu, irr[3]);
797 r = &PSCBX(vcpu, insvc[3]);
798 for (i = 3 ;; p--, r--, i--) {
799 bits = *p;
800 if (bits)
801 break; // got a potential interrupt
802 if (*r) {
803 // nothing in this word which is pending+inservice
804 // but there is one inservice which masks lower
805 return SPURIOUS_VECTOR;
806 }
807 if (i == 0) {
808 // checked all bits... nothing pending+inservice
809 return SPURIOUS_VECTOR;
810 }
811 }
812 // have a pending,deliverable interrupt... see if it is masked
813 bitnum = ia64_fls(bits);
814 //printk("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
815 vector = bitnum + (i * 64);
816 mask = 1L << bitnum;
817 /* sanity check for guest timer interrupt */
818 if (vector == (PSCB(vcpu, itv) & 0xff)) {
819 uint64_t now = ia64_get_itc();
820 if (now < PSCBX(vcpu, domain_itm)) {
821 // printk("Ooops, pending guest timer before its due\n");
822 PSCBX(vcpu, irr[i]) &= ~mask;
823 goto check_start;
824 }
825 }
826 //printk("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
827 if (*r >= mask) {
828 // masked by equal inservice
829 //printk("but masked by equal inservice\n");
830 return SPURIOUS_VECTOR;
831 }
832 if (PSCB(vcpu, tpr) & IA64_TPR_MMI) {
833 // tpr.mmi is set
834 //printk("but masked by tpr.mmi\n");
835 return SPURIOUS_VECTOR;
836 }
837 if (((PSCB(vcpu, tpr) & IA64_TPR_MIC) + 15) >= vector) {
838 //tpr.mic masks class
839 //printk("but masked by tpr.mic\n");
840 return SPURIOUS_VECTOR;
841 }
842 //printk("returned to caller\n");
843 return vector;
844 }
846 u64 vcpu_deliverable_interrupts(VCPU * vcpu)
847 {
848 return (vcpu_get_psr_i(vcpu) &&
849 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
850 }
852 u64 vcpu_deliverable_timer(VCPU * vcpu)
853 {
854 return (vcpu_get_psr_i(vcpu) &&
855 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu, itv));
856 }
858 IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval)
859 {
860 /* Use EID=0, ID=vcpu_id. */
861 *pval = vcpu->vcpu_id << 24;
862 return IA64_NO_FAULT;
863 }
865 IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval)
866 {
867 int i;
868 u64 vector, mask;
870 #define HEARTBEAT_FREQ 16 // period in seconds
871 #ifdef HEARTBEAT_FREQ
872 #define N_DOMS 16 // period in seconds
873 #if 0
874 static long count[N_DOMS] = { 0 };
875 #endif
876 static long nonclockcount[N_DOMS] = { 0 };
877 unsigned domid = vcpu->domain->domain_id;
878 #endif
879 #ifdef IRQ_DEBUG
880 static char firstivr = 1;
881 static char firsttime[256];
882 if (firstivr) {
883 int i;
884 for (i = 0; i < 256; i++)
885 firsttime[i] = 1;
886 firstivr = 0;
887 }
888 #endif
890 vector = vcpu_check_pending_interrupts(vcpu);
891 if (vector == SPURIOUS_VECTOR) {
892 PSCB(vcpu, pending_interruption) = 0;
893 *pval = vector;
894 return IA64_NO_FAULT;
895 }
896 #ifdef HEARTBEAT_FREQ
897 if (domid >= N_DOMS)
898 domid = N_DOMS - 1;
899 #if 0
900 if (vector == (PSCB(vcpu, itv) & 0xff)) {
901 if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) {
902 printk("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
903 domid, count[domid], nonclockcount[domid]);
904 //count[domid] = 0;
905 //dump_runq();
906 }
907 }
908 #endif
909 else
910 nonclockcount[domid]++;
911 #endif
912 // now have an unmasked, pending, deliverable vector!
913 // getting ivr has "side effects"
914 #ifdef IRQ_DEBUG
915 if (firsttime[vector]) {
916 printk("*** First get_ivr on vector=%lu,itc=%lx\n",
917 vector, ia64_get_itc());
918 firsttime[vector] = 0;
919 }
920 #endif
921 /* if delivering a timer interrupt, remember domain_itm, which
922 * needs to be done before clearing irr
923 */
924 if (vector == (PSCB(vcpu, itv) & 0xff)) {
925 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
926 }
928 i = vector >> 6;
929 mask = 1L << (vector & 0x3f);
930 //printk("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
931 PSCBX(vcpu, insvc[i]) |= mask;
932 PSCBX(vcpu, irr[i]) &= ~mask;
933 //PSCB(vcpu,pending_interruption)--;
934 *pval = vector;
935 return IA64_NO_FAULT;
936 }
938 IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval)
939 {
940 *pval = PSCB(vcpu, tpr);
941 return IA64_NO_FAULT;
942 }
944 IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval)
945 {
946 *pval = 0L; // reads of eoi always return 0
947 return IA64_NO_FAULT;
948 }
950 IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval)
951 {
952 *pval = PSCBX(vcpu, irr[0]);
953 return IA64_NO_FAULT;
954 }
956 IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval)
957 {
958 *pval = PSCBX(vcpu, irr[1]);
959 return IA64_NO_FAULT;
960 }
962 IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval)
963 {
964 *pval = PSCBX(vcpu, irr[2]);
965 return IA64_NO_FAULT;
966 }
968 IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval)
969 {
970 *pval = PSCBX(vcpu, irr[3]);
971 return IA64_NO_FAULT;
972 }
974 IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval)
975 {
976 *pval = PSCB(vcpu, itv);
977 return IA64_NO_FAULT;
978 }
980 IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval)
981 {
982 *pval = PSCB(vcpu, pmv);
983 return IA64_NO_FAULT;
984 }
986 IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval)
987 {
988 *pval = PSCB(vcpu, cmcv);
989 return IA64_NO_FAULT;
990 }
992 IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval)
993 {
994 // fix this when setting values other than m-bit is supported
995 printk("vcpu_get_lrr0: Unmasked interrupts unsupported\n");
996 *pval = (1L << 16);
997 return IA64_NO_FAULT;
998 }
1000 IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval)
1002 // fix this when setting values other than m-bit is supported
1003 printk("vcpu_get_lrr1: Unmasked interrupts unsupported\n");
1004 *pval = (1L << 16);
1005 return IA64_NO_FAULT;
1008 IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val)
1010 printk("vcpu_set_lid: Setting cr.lid is unsupported\n");
1011 return IA64_ILLOP_FAULT;
1014 IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val)
1016 if (val & 0xff00)
1017 return IA64_RSVDREG_FAULT;
1018 PSCB(vcpu, tpr) = val;
1019 /* This can unmask interrupts. */
1020 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
1021 PSCB(vcpu, pending_interruption) = 1;
1022 return IA64_NO_FAULT;
1025 IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val)
1027 u64 *p, bits, vec, bitnum;
1028 int i;
1030 p = &PSCBX(vcpu, insvc[3]);
1031 for (i = 3; (i >= 0) && !(bits = *p); i--, p--)
1033 if (i < 0) {
1034 printk("Trying to EOI interrupt when none are in-service.\n");
1035 return IA64_NO_FAULT;
1037 bitnum = ia64_fls(bits);
1038 vec = bitnum + (i * 64);
1039 /* clear the correct bit */
1040 bits &= ~(1L << bitnum);
1041 *p = bits;
1042 /* clearing an eoi bit may unmask another pending interrupt... */
1043 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
1044 // worry about this later... Linux only calls eoi
1045 // with interrupts disabled
1046 printk("Trying to EOI interrupt with interrupts enabled\n");
1048 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
1049 PSCB(vcpu, pending_interruption) = 1;
1050 //printk("YYYYY vcpu_set_eoi: Successful\n");
1051 return IA64_NO_FAULT;
1054 IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val)
1056 if (!(val & (1L << 16))) {
1057 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
1058 return IA64_ILLOP_FAULT;
1060 // no place to save this state but nothing to do anyway
1061 return IA64_NO_FAULT;
1064 IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val)
1066 if (!(val & (1L << 16))) {
1067 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
1068 return IA64_ILLOP_FAULT;
1070 // no place to save this state but nothing to do anyway
1071 return IA64_NO_FAULT;
1074 IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val)
1076 /* Check reserved fields. */
1077 if (val & 0xef00)
1078 return IA64_ILLOP_FAULT;
1079 PSCB(vcpu, itv) = val;
1080 if (val & 0x10000) {
1081 /* Disable itm. */
1082 PSCBX(vcpu, domain_itm) = 0;
1083 } else
1084 vcpu_set_next_timer(vcpu);
1085 return IA64_NO_FAULT;
1088 IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val)
1090 if (val & 0xef00) /* reserved fields */
1091 return IA64_RSVDREG_FAULT;
1092 PSCB(vcpu, pmv) = val;
1093 return IA64_NO_FAULT;
1096 IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val)
1098 if (val & 0xef00) /* reserved fields */
1099 return IA64_RSVDREG_FAULT;
1100 PSCB(vcpu, cmcv) = val;
1101 return IA64_NO_FAULT;
1104 /**************************************************************************
1105 VCPU temporary register access routines
1106 **************************************************************************/
1107 u64 vcpu_get_tmp(VCPU * vcpu, u64 index)
1109 if (index > 7)
1110 return 0;
1111 return PSCB(vcpu, tmp[index]);
1114 void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val)
1116 if (index <= 7)
1117 PSCB(vcpu, tmp[index]) = val;
1120 /**************************************************************************
1121 Interval timer routines
1122 **************************************************************************/
1124 BOOLEAN vcpu_timer_disabled(VCPU * vcpu)
1126 u64 itv = PSCB(vcpu, itv);
1127 return (!itv || !!(itv & 0x10000));
1130 BOOLEAN vcpu_timer_inservice(VCPU * vcpu)
1132 u64 itv = PSCB(vcpu, itv);
1133 return test_bit(itv, PSCBX(vcpu, insvc));
1136 BOOLEAN vcpu_timer_expired(VCPU * vcpu)
1138 unsigned long domain_itm = PSCBX(vcpu, domain_itm);
1139 unsigned long now = ia64_get_itc();
1141 if (!domain_itm)
1142 return FALSE;
1143 if (now < domain_itm)
1144 return FALSE;
1145 if (vcpu_timer_disabled(vcpu))
1146 return FALSE;
1147 return TRUE;
1150 void vcpu_safe_set_itm(unsigned long val)
1152 unsigned long epsilon = 100;
1153 unsigned long flags;
1154 u64 now = ia64_get_itc();
1156 local_irq_save(flags);
1157 while (1) {
1158 //printk("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1159 ia64_set_itm(val);
1160 if (val > (now = ia64_get_itc()))
1161 break;
1162 val = now + epsilon;
1163 epsilon <<= 1;
1165 local_irq_restore(flags);
1168 void vcpu_set_next_timer(VCPU * vcpu)
1170 u64 d = PSCBX(vcpu, domain_itm);
1171 //u64 s = PSCBX(vcpu,xen_itm);
1172 u64 s = local_cpu_data->itm_next;
1173 u64 now = ia64_get_itc();
1175 /* gloss over the wraparound problem for now... we know it exists
1176 * but it doesn't matter right now */
1178 if (is_idle_domain(vcpu->domain)) {
1179 // printk("****** vcpu_set_next_timer called during idle!!\n");
1180 vcpu_safe_set_itm(s);
1181 return;
1183 //s = PSCBX(vcpu,xen_itm);
1184 if (d && (d > now) && (d < s)) {
1185 vcpu_safe_set_itm(d);
1186 //using_domain_as_itm++;
1187 } else {
1188 vcpu_safe_set_itm(s);
1189 //using_xen_as_itm++;
1193 IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val)
1195 //UINT now = ia64_get_itc();
1197 //if (val < now) val = now + 1000;
1198 //printk("*** vcpu_set_itm: called with %lx\n",val);
1199 PSCBX(vcpu, domain_itm) = val;
1200 vcpu_set_next_timer(vcpu);
1201 return IA64_NO_FAULT;
1204 IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val)
1206 #define DISALLOW_SETTING_ITC_FOR_NOW
1207 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1208 static int did_print;
1209 if (!did_print) {
1210 printk("vcpu_set_itc: Setting ar.itc is currently disabled "
1211 "(this message is only displayed once)\n");
1212 did_print = 1;
1214 #else
1215 u64 oldnow = ia64_get_itc();
1216 u64 olditm = PSCBX(vcpu, domain_itm);
1217 unsigned long d = olditm - oldnow;
1218 unsigned long x = local_cpu_data->itm_next - oldnow;
1220 u64 newnow = val, min_delta;
1222 local_irq_disable();
1223 if (olditm) {
1224 printk("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val,
1225 newnow + d);
1226 PSCBX(vcpu, domain_itm) = newnow + d;
1228 local_cpu_data->itm_next = newnow + x;
1229 d = PSCBX(vcpu, domain_itm);
1230 x = local_cpu_data->itm_next;
1232 ia64_set_itc(newnow);
1233 if (d && (d > newnow) && (d < x)) {
1234 vcpu_safe_set_itm(d);
1235 //using_domain_as_itm++;
1236 } else {
1237 vcpu_safe_set_itm(x);
1238 //using_xen_as_itm++;
1240 local_irq_enable();
1241 #endif
1242 return IA64_NO_FAULT;
1245 IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval)
1247 //FIXME: Implement this
1248 printk("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1249 return IA64_NO_FAULT;
1250 //return IA64_ILLOP_FAULT;
1253 IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval)
1255 //TODO: Implement this
1256 printk("vcpu_get_itc: Getting ar.itc is unsupported\n");
1257 return IA64_ILLOP_FAULT;
1260 void vcpu_pend_timer(VCPU * vcpu)
1262 u64 itv = PSCB(vcpu, itv) & 0xff;
1264 if (vcpu_timer_disabled(vcpu))
1265 return;
1266 //if (vcpu_timer_inservice(vcpu)) return;
1267 if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) {
1268 // already delivered an interrupt for this so
1269 // don't deliver another
1270 return;
1272 if (vcpu->arch.event_callback_ip) {
1273 /* A small window may occur when injecting vIRQ while related
1274 * handler has not been registered. Don't fire in such case.
1275 */
1276 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1277 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1278 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1280 } else
1281 vcpu_pend_interrupt(vcpu, itv);
1284 // returns true if ready to deliver a timer interrupt too early
1285 u64 vcpu_timer_pending_early(VCPU * vcpu)
1287 u64 now = ia64_get_itc();
1288 u64 itm = PSCBX(vcpu, domain_itm);
1290 if (vcpu_timer_disabled(vcpu))
1291 return 0;
1292 if (!itm)
1293 return 0;
1294 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1297 /**************************************************************************
1298 Privileged operation emulation routines
1299 **************************************************************************/
1301 static void vcpu_force_tlb_miss(VCPU * vcpu, u64 ifa)
1303 PSCB(vcpu, ifa) = ifa;
1304 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1305 vcpu_thash(current, ifa, &PSCB(current, iha));
1308 IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa)
1310 vcpu_force_tlb_miss(vcpu, ifa);
1311 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_INST_TLB_VECTOR :
1312 IA64_ALT_INST_TLB_VECTOR;
1315 IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa)
1317 vcpu_force_tlb_miss(vcpu, ifa);
1318 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_DATA_TLB_VECTOR :
1319 IA64_ALT_DATA_TLB_VECTOR;
1322 IA64FAULT vcpu_rfi(VCPU * vcpu)
1324 // TODO: Only allowed for current vcpu
1325 PSR psr;
1326 u64 int_enable, regspsr = 0;
1327 u64 ifs;
1328 REGS *regs = vcpu_regs(vcpu);
1329 extern void dorfirfi(void);
1331 psr.i64 = PSCB(vcpu, ipsr);
1332 if (psr.ia64_psr.cpl < 3)
1333 psr.ia64_psr.cpl = 2;
1334 int_enable = psr.ia64_psr.i;
1335 if (psr.ia64_psr.ic)
1336 PSCB(vcpu, interrupt_collection_enabled) = 1;
1337 if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it)
1338 vcpu_set_metaphysical_mode(vcpu, FALSE);
1339 else
1340 vcpu_set_metaphysical_mode(vcpu, TRUE);
1341 psr.ia64_psr.ic = 1;
1342 psr.ia64_psr.i = 1;
1343 psr.ia64_psr.dt = 1;
1344 psr.ia64_psr.rt = 1;
1345 psr.ia64_psr.it = 1;
1346 psr.ia64_psr.bn = 1;
1347 //psr.pk = 1; // checking pkeys shouldn't be a problem but seems broken
1348 if (psr.ia64_psr.be) {
1349 printk("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
1350 return IA64_ILLOP_FAULT;
1352 PSCB(vcpu, incomplete_regframe) = 0; // is this necessary?
1353 ifs = PSCB(vcpu, ifs);
1354 //if ((ifs & regs->cr_ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
1355 //if ((ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
1356 if (ifs & regs->cr_ifs & 0x8000000000000000L) {
1357 // TODO: validate PSCB(vcpu,iip)
1358 // TODO: PSCB(vcpu,ipsr) = psr;
1359 PSCB(vcpu, ipsr) = psr.i64;
1360 // now set up the trampoline
1361 regs->cr_iip = *(unsigned long *)dorfirfi; // function pointer!!
1362 __asm__ __volatile("mov %0=psr;;":"=r"(regspsr)::"memory");
1363 regs->cr_ipsr =
1364 regspsr & ~(IA64_PSR_I | IA64_PSR_IC | IA64_PSR_BN);
1365 } else {
1366 regs->cr_ipsr = psr.i64;
1367 regs->cr_iip = PSCB(vcpu, iip);
1369 PSCB(vcpu, interrupt_collection_enabled) = 1;
1370 vcpu_bsw1(vcpu);
1371 vcpu->vcpu_info->evtchn_upcall_mask = !int_enable;
1372 return IA64_NO_FAULT;
1375 IA64FAULT vcpu_cover(VCPU * vcpu)
1377 // TODO: Only allowed for current vcpu
1378 REGS *regs = vcpu_regs(vcpu);
1380 if (!PSCB(vcpu, interrupt_collection_enabled)) {
1381 if (!PSCB(vcpu, incomplete_regframe))
1382 PSCB(vcpu, ifs) = regs->cr_ifs;
1383 else
1384 PSCB(vcpu, incomplete_regframe) = 0;
1386 regs->cr_ifs = 0;
1387 return IA64_NO_FAULT;
1390 IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval)
1392 u64 pta = PSCB(vcpu, pta);
1393 u64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1394 u64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT) - 1);
1395 u64 Mask = (1L << pta_sz) - 1;
1396 u64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1397 u64 compMask_60_15 = ~Mask_60_15;
1398 u64 rr_ps = vcpu_get_rr_ps(vcpu, vadr);
1399 u64 VHPT_offset = (vadr >> rr_ps) << 3;
1400 u64 VHPT_addr1 = vadr & 0xe000000000000000L;
1401 u64 VHPT_addr2a =
1402 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1403 u64 VHPT_addr2b =
1404 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1405 u64 VHPT_addr3 = VHPT_offset & 0x7fff;
1406 u64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1407 VHPT_addr3;
1409 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1410 *pval = VHPT_addr;
1411 return IA64_NO_FAULT;
1414 IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr)
1416 printk("vcpu_ttag: ttag instruction unsupported\n");
1417 return IA64_ILLOP_FAULT;
1420 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1422 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1423 static inline int range_overlap(u64 b1, u64 e1, u64 b2, u64 e2)
1425 return (b1 <= e2) && (e1 >= b2);
1428 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1429 Note: LSBs of base inside page_size are ignored. */
1430 static inline void
1431 check_xen_space_overlap(const char *func, u64 base, u64 page_size)
1433 /* Overlaps can occur only in region 7.
1434 (This is an optimization to bypass all the checks). */
1435 if (REGION_NUMBER(base) != 7)
1436 return;
1438 /* Mask LSBs of base. */
1439 base &= ~(page_size - 1);
1441 /* FIXME: ideally an MCA should be generated... */
1442 if (range_overlap(HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
1443 base, base + page_size)
1444 || range_overlap(current->domain->arch.shared_info_va,
1445 current->domain->arch.shared_info_va
1446 + XSI_SIZE + XMAPPEDREGS_SIZE,
1447 base, base + page_size))
1448 panic_domain(NULL, "%s on Xen virtual space (%lx)\n",
1449 func, base);
1452 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1453 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY * trp, u64 ifa,
1454 u64 rid)
1456 return trp->rid == rid
1457 && ifa >= trp->vadr && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1460 static inline int vcpu_match_tr_entry(TR_ENTRY * trp, u64 ifa, u64 rid)
1462 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1465 static inline int
1466 vcpu_match_tr_entry_range(TR_ENTRY * trp, u64 rid, u64 b, u64 e)
1468 return trp->rid == rid
1469 && trp->pte.p
1470 && range_overlap(b, e, trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1474 static TR_ENTRY *vcpu_tr_lookup(VCPU * vcpu, unsigned long va, u64 rid,
1475 BOOLEAN is_data)
1477 unsigned char *regions;
1478 TR_ENTRY *trp;
1479 int tr_max;
1480 int i;
1482 if (is_data) {
1483 // data
1484 regions = &vcpu->arch.dtr_regions;
1485 trp = vcpu->arch.dtrs;
1486 tr_max = sizeof(vcpu->arch.dtrs) / sizeof(vcpu->arch.dtrs[0]);
1487 } else {
1488 // instruction
1489 regions = &vcpu->arch.itr_regions;
1490 trp = vcpu->arch.itrs;
1491 tr_max = sizeof(vcpu->arch.itrs) / sizeof(vcpu->arch.itrs[0]);
1494 if (!vcpu_quick_region_check(*regions, va)) {
1495 return NULL;
1497 for (i = 0; i < tr_max; i++, trp++) {
1498 if (vcpu_match_tr_entry(trp, va, rid)) {
1499 return trp;
1502 return NULL;
1505 // return value
1506 // 0: failure
1507 // 1: success
1508 int
1509 vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
1510 IA64_BUNDLE * bundle)
1512 u64 gpip; // guest pseudo phyiscal ip
1513 unsigned long vaddr;
1514 struct page_info *page;
1516 again:
1517 #if 0
1518 // Currently xen doesn't track psr.it bits.
1519 // it assumes always psr.it = 1.
1520 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1521 gpip = gip;
1522 } else
1523 #endif
1525 unsigned long region = REGION_NUMBER(gip);
1526 unsigned long rr = PSCB(vcpu, rrs)[region];
1527 unsigned long rid = rr & RR_RID_MASK;
1528 BOOLEAN swap_rr0;
1529 TR_ENTRY *trp;
1531 // vcpu->arch.{i, d}tlb are volatile,
1532 // copy its value to the variable, tr, before use.
1533 TR_ENTRY tr;
1535 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1536 if (trp != NULL) {
1537 tr = *trp;
1538 goto found;
1540 // When it failed to get a bundle, itlb miss is reflected.
1541 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1542 tr = PSCBX(vcpu, itlb);
1543 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1544 //dprintk(XENLOG_WARNING,
1545 // "%s gip 0x%lx gpip 0x%lx\n", __func__,
1546 // gip, gpip);
1547 goto found;
1549 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1550 if (trp != NULL) {
1551 tr = *trp;
1552 goto found;
1554 #if 0
1555 tr = PSCBX(vcpu, dtlb);
1556 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1557 goto found;
1559 #endif
1561 // try to access gip with guest virtual address
1562 // This may cause tlb miss. see vcpu_translate(). Be careful!
1563 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1564 if (swap_rr0) {
1565 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
1567 *bundle = __get_domain_bundle(gip);
1568 if (swap_rr0) {
1569 set_metaphysical_rr0();
1571 if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
1572 dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
1573 return 0;
1575 return 1;
1577 found:
1578 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1579 (gip & ((1 << tr.ps) - 1));
1582 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1583 page = virt_to_page(vaddr);
1584 if (get_page(page, vcpu->domain) == 0) {
1585 if (page_get_owner(page) != vcpu->domain) {
1586 // This page might be a page granted by another
1587 // domain.
1588 panic_domain(regs, "domain tries to execute foreign "
1589 "domain page which might be mapped by "
1590 "grant table.\n");
1592 goto again;
1594 *bundle = *((IA64_BUNDLE *) vaddr);
1595 put_page(page);
1596 return 1;
1599 IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
1600 u64 * pteval, u64 * itir, u64 * iha)
1602 unsigned long region = address >> 61;
1603 unsigned long pta, rid, rr;
1604 union pte_flags pte;
1605 TR_ENTRY *trp;
1607 if (PSCB(vcpu, metaphysical_mode) && !(!is_data && region)) {
1608 // dom0 may generate an uncacheable physical address (msb=1)
1609 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1610 // FIXME: This seems to happen even though it shouldn't. Need to track
1611 // this down, but since it has been apparently harmless, just flag it for now
1612 // panic_domain(vcpu_regs(vcpu),
1614 /*
1615 * Guest may execute itc.d and rfi with psr.dt=0
1616 * When VMM try to fetch opcode, tlb miss may happen,
1617 * At this time PSCB(vcpu,metaphysical_mode)=1,
1618 * region=5,VMM need to handle this tlb miss as if
1619 * PSCB(vcpu,metaphysical_mode)=0
1620 */
1621 printk("vcpu_translate: bad physical address: 0x%lx "
1622 "at %lx\n", address, vcpu_regs(vcpu)->cr_iip);
1624 } else {
1625 *pteval = (address & _PAGE_PPN_MASK) |
1626 __DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX;
1627 *itir = PAGE_SHIFT << 2;
1628 perfc_incrc(phys_translate);
1629 return IA64_NO_FAULT;
1631 } else if (!region && warn_region0_address) {
1632 REGS *regs = vcpu_regs(vcpu);
1633 unsigned long viip = PSCB(vcpu, iip);
1634 unsigned long vipsr = PSCB(vcpu, ipsr);
1635 unsigned long iip = regs->cr_iip;
1636 unsigned long ipsr = regs->cr_ipsr;
1637 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, "
1638 "vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1639 address, viip, vipsr, iip, ipsr);
1642 rr = PSCB(vcpu, rrs)[region];
1643 rid = rr & RR_RID_MASK;
1644 if (is_data) {
1645 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1646 if (trp != NULL) {
1647 *pteval = trp->pte.val;
1648 *itir = trp->itir;
1649 perfc_incrc(tr_translate);
1650 return IA64_NO_FAULT;
1653 // FIXME?: check itr's for data accesses too, else bad things happen?
1654 /* else */ {
1655 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1656 if (trp != NULL) {
1657 *pteval = trp->pte.val;
1658 *itir = trp->itir;
1659 perfc_incrc(tr_translate);
1660 return IA64_NO_FAULT;
1664 /* check 1-entry TLB */
1665 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1666 trp = &vcpu->arch.dtlb;
1667 pte = trp->pte;
1668 if ( /* is_data && */ pte.p
1669 && vcpu_match_tr_entry_no_p(trp, address, rid)) {
1670 *pteval = pte.val;
1671 *itir = trp->itir;
1672 perfc_incrc(dtlb_translate);
1673 return IA64_USE_TLB;
1676 /* check guest VHPT */
1677 pta = PSCB(vcpu, pta);
1678 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1679 panic_domain(vcpu_regs(vcpu), "can't do long format VHPT\n");
1680 //return is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR;
1683 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1684 // note: architecturally, iha is optionally set for alt faults but
1685 // xenlinux depends on it so should document it as part of PV interface
1686 vcpu_thash(vcpu, address, iha);
1687 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE))
1688 return is_data ? IA64_ALT_DATA_TLB_VECTOR :
1689 IA64_ALT_INST_TLB_VECTOR;
1691 /* avoid recursively walking (short format) VHPT */
1692 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1693 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1695 if (!__access_ok(*iha)
1696 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1697 // virtual VHPT walker "missed" in TLB
1698 return IA64_VHPT_FAULT;
1700 /*
1701 * Optimisation: this VHPT walker aborts on not-present pages
1702 * instead of inserting a not-present translation, this allows
1703 * vectoring directly to the miss handler.
1704 */
1705 if (!pte.p)
1706 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1708 /* found mapping in guest VHPT! */
1709 *itir = rr & RR_PS_MASK;
1710 *pteval = pte.val;
1711 perfc_incrc(vhpt_translate);
1712 return IA64_NO_FAULT;
1715 IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr)
1717 u64 pteval, itir, mask, iha;
1718 IA64FAULT fault;
1720 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1721 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
1722 mask = itir_mask(itir);
1723 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1724 return IA64_NO_FAULT;
1726 return vcpu_force_data_miss(vcpu, vadr);
1729 IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
1731 printk("vcpu_tak: tak instruction unsupported\n");
1732 return IA64_ILLOP_FAULT;
1733 // HACK ALERT: tak does a thash for now
1734 //return vcpu_thash(vcpu,vadr,key);
1737 /**************************************************************************
1738 VCPU debug breakpoint register access routines
1739 **************************************************************************/
1741 IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
1743 // TODO: unimplemented DBRs return a reserved register fault
1744 // TODO: Should set Logical CPU state, not just physical
1745 ia64_set_dbr(reg, val);
1746 return IA64_NO_FAULT;
1749 IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
1751 // TODO: unimplemented IBRs return a reserved register fault
1752 // TODO: Should set Logical CPU state, not just physical
1753 ia64_set_ibr(reg, val);
1754 return IA64_NO_FAULT;
1757 IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
1759 // TODO: unimplemented DBRs return a reserved register fault
1760 u64 val = ia64_get_dbr(reg);
1761 *pval = val;
1762 return IA64_NO_FAULT;
1765 IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
1767 // TODO: unimplemented IBRs return a reserved register fault
1768 u64 val = ia64_get_ibr(reg);
1769 *pval = val;
1770 return IA64_NO_FAULT;
1773 /**************************************************************************
1774 VCPU performance monitor register access routines
1775 **************************************************************************/
1777 IA64FAULT vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val)
1779 // TODO: Should set Logical CPU state, not just physical
1780 // NOTE: Writes to unimplemented PMC registers are discarded
1781 #ifdef DEBUG_PFMON
1782 printk("vcpu_set_pmc(%x,%lx)\n", reg, val);
1783 #endif
1784 ia64_set_pmc(reg, val);
1785 return IA64_NO_FAULT;
1788 IA64FAULT vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val)
1790 // TODO: Should set Logical CPU state, not just physical
1791 // NOTE: Writes to unimplemented PMD registers are discarded
1792 #ifdef DEBUG_PFMON
1793 printk("vcpu_set_pmd(%x,%lx)\n", reg, val);
1794 #endif
1795 ia64_set_pmd(reg, val);
1796 return IA64_NO_FAULT;
1799 IA64FAULT vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval)
1801 // NOTE: Reads from unimplemented PMC registers return zero
1802 u64 val = (u64) ia64_get_pmc(reg);
1803 #ifdef DEBUG_PFMON
1804 printk("%lx=vcpu_get_pmc(%x)\n", val, reg);
1805 #endif
1806 *pval = val;
1807 return IA64_NO_FAULT;
1810 IA64FAULT vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval)
1812 // NOTE: Reads from unimplemented PMD registers return zero
1813 u64 val = (u64) ia64_get_pmd(reg);
1814 #ifdef DEBUG_PFMON
1815 printk("%lx=vcpu_get_pmd(%x)\n", val, reg);
1816 #endif
1817 *pval = val;
1818 return IA64_NO_FAULT;
1821 /**************************************************************************
1822 VCPU banked general register access routines
1823 **************************************************************************/
1824 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1825 do{ \
1826 __asm__ __volatile__ ( \
1827 ";;extr.u %0 = %3,%6,16;;\n" \
1828 "dep %1 = %0, %1, 0, 16;;\n" \
1829 "st8 [%4] = %1\n" \
1830 "extr.u %0 = %2, 16, 16;;\n" \
1831 "dep %3 = %0, %3, %6, 16;;\n" \
1832 "st8 [%5] = %3\n" \
1833 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1834 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1835 }while(0)
1837 IA64FAULT vcpu_bsw0(VCPU * vcpu)
1839 // TODO: Only allowed for current vcpu
1840 REGS *regs = vcpu_regs(vcpu);
1841 unsigned long *r = &regs->r16;
1842 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1843 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1844 unsigned long *runat = &regs->eml_unat;
1845 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1846 unsigned long *b1unat = &PSCB(vcpu, vnat);
1848 unsigned long i;
1850 if (VMX_DOMAIN(vcpu)) {
1851 if (VCPU(vcpu, vpsr) & IA64_PSR_BN) {
1852 for (i = 0; i < 16; i++) {
1853 *b1++ = *r;
1854 *r++ = *b0++;
1856 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1857 IA64_PT_REGS_R16_SLOT);
1858 VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
1860 } else {
1861 if (PSCB(vcpu, banknum)) {
1862 for (i = 0; i < 16; i++) {
1863 *b1++ = *r;
1864 *r++ = *b0++;
1866 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1867 IA64_PT_REGS_R16_SLOT);
1868 PSCB(vcpu, banknum) = 0;
1871 return IA64_NO_FAULT;
1874 #define vcpu_bsw1_unat(i, b0unat, b1unat, runat, IA64_PT_REGS_R16_SLOT) \
1875 do { \
1876 __asm__ __volatile__ (";;extr.u %0 = %3,%6,16;;\n" \
1877 "dep %1 = %0, %1, 16, 16;;\n" \
1878 "st8 [%4] = %1\n" \
1879 "extr.u %0 = %2, 0, 16;;\n" \
1880 "dep %3 = %0, %3, %6, 16;;\n" \
1881 "st8 [%5] = %3\n" \
1882 ::"r"(i), "r"(*b0unat), "r"(*b1unat), \
1883 "r"(*runat), "r"(b0unat), "r"(runat), \
1884 "i"(IA64_PT_REGS_R16_SLOT): "memory"); \
1885 } while(0)
1887 IA64FAULT vcpu_bsw1(VCPU * vcpu)
1889 // TODO: Only allowed for current vcpu
1890 REGS *regs = vcpu_regs(vcpu);
1891 unsigned long *r = &regs->r16;
1892 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1893 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1894 unsigned long *runat = &regs->eml_unat;
1895 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1896 unsigned long *b1unat = &PSCB(vcpu, vnat);
1898 unsigned long i;
1900 if (VMX_DOMAIN(vcpu)) {
1901 if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
1902 for (i = 0; i < 16; i++) {
1903 *b0++ = *r;
1904 *r++ = *b1++;
1906 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1907 IA64_PT_REGS_R16_SLOT);
1908 VCPU(vcpu, vpsr) |= IA64_PSR_BN;
1910 } else {
1911 if (!PSCB(vcpu, banknum)) {
1912 for (i = 0; i < 16; i++) {
1913 *b0++ = *r;
1914 *r++ = *b1++;
1916 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1917 IA64_PT_REGS_R16_SLOT);
1918 PSCB(vcpu, banknum) = 1;
1921 return IA64_NO_FAULT;
1924 /**************************************************************************
1925 VCPU cpuid access routines
1926 **************************************************************************/
1928 IA64FAULT vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval)
1930 // FIXME: This could get called as a result of a rsvd-reg fault
1931 // if reg > 3
1932 switch (reg) {
1933 case 0:
1934 memcpy(pval, "Xen/ia64", 8);
1935 break;
1936 case 1:
1937 *pval = 0;
1938 break;
1939 case 2:
1940 *pval = 0;
1941 break;
1942 case 3:
1943 *pval = ia64_get_cpuid(3);
1944 break;
1945 case 4:
1946 *pval = ia64_get_cpuid(4);
1947 break;
1948 default:
1949 if (reg > (ia64_get_cpuid(3) & 0xff))
1950 return IA64_RSVDREG_FAULT;
1951 *pval = ia64_get_cpuid(reg);
1952 break;
1954 return IA64_NO_FAULT;
1957 /**************************************************************************
1958 VCPU region register access routines
1959 **************************************************************************/
1961 unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
1963 ia64_rr rr;
1965 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
1966 return rr.ve;
1969 IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val)
1971 PSCB(vcpu, rrs)[reg >> 61] = val;
1972 // warning: set_one_rr() does it "live"
1973 set_one_rr(reg, val);
1974 return IA64_NO_FAULT;
1977 IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval)
1979 if (VMX_DOMAIN(vcpu))
1980 *pval = VMX(vcpu, vrr[reg >> 61]);
1981 else
1982 *pval = PSCB(vcpu, rrs)[reg >> 61];
1984 return IA64_NO_FAULT;
1987 /**************************************************************************
1988 VCPU protection key register access routines
1989 **************************************************************************/
1991 IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
1993 #ifndef PKR_USE_FIXED
1994 printk("vcpu_get_pkr: called, not implemented yet\n");
1995 return IA64_ILLOP_FAULT;
1996 #else
1997 u64 val = (u64) ia64_get_pkr(reg);
1998 *pval = val;
1999 return IA64_NO_FAULT;
2000 #endif
2003 IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
2005 #ifndef PKR_USE_FIXED
2006 printk("vcpu_set_pkr: called, not implemented yet\n");
2007 return IA64_ILLOP_FAULT;
2008 #else
2009 // if (reg >= NPKRS)
2010 // return IA64_ILLOP_FAULT;
2011 vcpu->pkrs[reg] = val;
2012 ia64_set_pkr(reg, val);
2013 return IA64_NO_FAULT;
2014 #endif
2017 /**************************************************************************
2018 VCPU translation register access routines
2019 **************************************************************************/
2021 static void
2022 vcpu_set_tr_entry_rid(TR_ENTRY * trp, u64 pte,
2023 u64 itir, u64 ifa, u64 rid)
2025 u64 ps;
2026 union pte_flags new_pte;
2028 trp->itir = itir;
2029 trp->rid = rid;
2030 ps = trp->ps;
2031 new_pte.val = pte;
2032 if (new_pte.pl < 2)
2033 new_pte.pl = 2;
2034 trp->vadr = ifa & ~0xfff;
2035 if (ps > 12) { // "ignore" relevant low-order bits
2036 new_pte.ppn &= ~((1UL << (ps - 12)) - 1);
2037 trp->vadr &= ~((1UL << ps) - 1);
2040 /* Atomic write. */
2041 trp->pte.val = new_pte.val;
2044 static inline void
2045 vcpu_set_tr_entry(TR_ENTRY * trp, u64 pte, u64 itir, u64 ifa)
2047 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
2048 VCPU(current, rrs[ifa >> 61]) & RR_RID_MASK);
2051 IA64FAULT vcpu_itr_d(VCPU * vcpu, u64 slot, u64 pte,
2052 u64 itir, u64 ifa)
2054 TR_ENTRY *trp;
2056 if (slot >= NDTRS)
2057 return IA64_RSVDREG_FAULT;
2059 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2061 trp = &PSCBX(vcpu, dtrs[slot]);
2062 //printk("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
2063 vcpu_set_tr_entry(trp, pte, itir, ifa);
2064 vcpu_quick_region_set(PSCBX(vcpu, dtr_regions), ifa);
2066 /*
2067 * FIXME According to spec, vhpt should be purged, but this
2068 * incurs considerable performance loss, since it is safe for
2069 * linux not to purge vhpt, vhpt purge is disabled until a
2070 * feasible way is found.
2072 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2073 */
2075 return IA64_NO_FAULT;
2078 IA64FAULT vcpu_itr_i(VCPU * vcpu, u64 slot, u64 pte,
2079 u64 itir, u64 ifa)
2081 TR_ENTRY *trp;
2083 if (slot >= NITRS)
2084 return IA64_RSVDREG_FAULT;
2086 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2088 trp = &PSCBX(vcpu, itrs[slot]);
2089 //printk("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
2090 vcpu_set_tr_entry(trp, pte, itir, ifa);
2091 vcpu_quick_region_set(PSCBX(vcpu, itr_regions), ifa);
2093 /*
2094 * FIXME According to spec, vhpt should be purged, but this
2095 * incurs considerable performance loss, since it is safe for
2096 * linux not to purge vhpt, vhpt purge is disabled until a
2097 * feasible way is found.
2099 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2100 */
2102 return IA64_NO_FAULT;
2105 IA64FAULT vcpu_set_itr(VCPU * vcpu, u64 slot, u64 pte,
2106 u64 itir, u64 ifa, u64 rid)
2108 TR_ENTRY *trp;
2110 if (slot >= NITRS)
2111 return IA64_RSVDREG_FAULT;
2112 trp = &PSCBX(vcpu, itrs[slot]);
2113 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2115 /* Recompute the itr_region. */
2116 vcpu->arch.itr_regions = 0;
2117 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
2118 if (trp->pte.p)
2119 vcpu_quick_region_set(vcpu->arch.itr_regions,
2120 trp->vadr);
2121 return IA64_NO_FAULT;
2124 IA64FAULT vcpu_set_dtr(VCPU * vcpu, u64 slot, u64 pte,
2125 u64 itir, u64 ifa, u64 rid)
2127 TR_ENTRY *trp;
2129 if (slot >= NDTRS)
2130 return IA64_RSVDREG_FAULT;
2131 trp = &PSCBX(vcpu, dtrs[slot]);
2132 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2134 /* Recompute the dtr_region. */
2135 vcpu->arch.dtr_regions = 0;
2136 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
2137 if (trp->pte.p)
2138 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2139 trp->vadr);
2140 return IA64_NO_FAULT;
2143 /**************************************************************************
2144 VCPU translation cache access routines
2145 **************************************************************************/
2147 void
2148 vcpu_itc_no_srlz(VCPU * vcpu, u64 IorD, u64 vaddr, u64 pte,
2149 u64 mp_pte, u64 logps, struct p2m_entry *entry)
2151 unsigned long psr;
2152 unsigned long ps = (vcpu->domain == dom0) ? logps : PAGE_SHIFT;
2154 check_xen_space_overlap("itc", vaddr, 1UL << logps);
2156 // FIXME, must be inlined or potential for nested fault here!
2157 if ((vcpu->domain == dom0) && (logps < PAGE_SHIFT))
2158 panic_domain(NULL, "vcpu_itc_no_srlz: domain trying to use "
2159 "smaller page size!\n");
2161 BUG_ON(logps > PAGE_SHIFT);
2162 vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry);
2163 psr = ia64_clear_ic();
2164 pte &= ~(_PAGE_RV2 | _PAGE_RV1); // Mask out the reserved bits.
2165 ia64_itc(IorD, vaddr, pte, ps); // FIXME: look for bigger mappings
2166 ia64_set_psr(psr);
2167 // ia64_srlz_i(); // no srls req'd, will rfi later
2168 #ifdef VHPT_GLOBAL
2169 if (vcpu->domain == dom0 && ((vaddr >> 61) == 7)) {
2170 // FIXME: this is dangerous... vhpt_flush_address ensures these
2171 // addresses never get flushed. More work needed if this
2172 // ever happens.
2173 //printk("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2174 if (logps > PAGE_SHIFT)
2175 vhpt_multiple_insert(vaddr, pte, logps);
2176 else
2177 vhpt_insert(vaddr, pte, logps << 2);
2179 // even if domain pagesize is larger than PAGE_SIZE, just put
2180 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2181 else
2182 vhpt_insert(vaddr, pte, PAGE_SHIFT << 2);
2183 #endif
2184 if (IorD & 0x4) /* don't place in 1-entry TLB */
2185 return;
2186 if (IorD & 0x1) {
2187 vcpu_set_tr_entry(&PSCBX(vcpu, itlb), mp_pte, ps << 2, vaddr);
2189 if (IorD & 0x2) {
2190 vcpu_set_tr_entry(&PSCBX(vcpu, dtlb), mp_pte, ps << 2, vaddr);
2194 IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2196 unsigned long pteval, logps = itir_ps(itir);
2197 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2198 struct p2m_entry entry;
2200 if (logps < PAGE_SHIFT)
2201 panic_domain(NULL, "vcpu_itc_d: domain trying to use "
2202 "smaller page size!\n");
2204 again:
2205 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2206 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2207 if (!pteval)
2208 return IA64_ILLOP_FAULT;
2209 if (swap_rr0)
2210 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
2211 vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, logps, &entry);
2212 if (swap_rr0)
2213 set_metaphysical_rr0();
2214 if (p2m_entry_retry(&entry)) {
2215 vcpu_flush_tlb_vhpt_range(ifa, logps);
2216 goto again;
2218 return IA64_NO_FAULT;
2221 IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2223 unsigned long pteval, logps = itir_ps(itir);
2224 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2225 struct p2m_entry entry;
2227 if (logps < PAGE_SHIFT)
2228 panic_domain(NULL, "vcpu_itc_i: domain trying to use "
2229 "smaller page size!\n");
2230 again:
2231 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2232 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2233 if (!pteval)
2234 return IA64_ILLOP_FAULT;
2235 if (swap_rr0)
2236 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
2237 vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, logps, &entry);
2238 if (swap_rr0)
2239 set_metaphysical_rr0();
2240 if (p2m_entry_retry(&entry)) {
2241 vcpu_flush_tlb_vhpt_range(ifa, logps);
2242 goto again;
2244 return IA64_NO_FAULT;
2247 IA64FAULT vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 log_range)
2249 BUG_ON(vcpu != current);
2251 check_xen_space_overlap("ptc_l", vadr, 1UL << log_range);
2253 /* Purge TC */
2254 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2255 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2257 /* Purge all tlb and vhpt */
2258 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2260 return IA64_NO_FAULT;
2263 // At privlvl=0, fc performs no access rights or protection key checks, while
2264 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2265 // read but no protection key check. Thus in order to avoid an unexpected
2266 // access rights fault, we have to translate the virtual address to a
2267 // physical address (possibly via a metaphysical address) and do the fc
2268 // on the physical address, which is guaranteed to flush the same cache line
2269 IA64FAULT vcpu_fc(VCPU * vcpu, u64 vadr)
2271 // TODO: Only allowed for current vcpu
2272 u64 mpaddr, paddr;
2273 IA64FAULT fault;
2275 again:
2276 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2277 if (fault == IA64_NO_FAULT) {
2278 struct p2m_entry entry;
2279 paddr = translate_domain_mpaddr(mpaddr, &entry);
2280 ia64_fc(__va(paddr));
2281 if (p2m_entry_retry(&entry))
2282 goto again;
2284 return fault;
2287 IA64FAULT vcpu_ptc_e(VCPU * vcpu, u64 vadr)
2289 // Note that this only needs to be called once, i.e. the
2290 // architected loop to purge the entire TLB, should use
2291 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2293 vcpu_flush_vtlb_all(current);
2295 return IA64_NO_FAULT;
2298 IA64FAULT vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 addr_range)
2300 printk("vcpu_ptc_g: called, not implemented yet\n");
2301 return IA64_ILLOP_FAULT;
2304 IA64FAULT vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 addr_range)
2306 // FIXME: validate not flushing Xen addresses
2307 // if (Xen address) return(IA64_ILLOP_FAULT);
2308 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2309 //printk("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2311 check_xen_space_overlap("ptc_ga", vadr, addr_range);
2313 domain_flush_vtlb_range(vcpu->domain, vadr, addr_range);
2315 return IA64_NO_FAULT;
2318 IA64FAULT vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 log_range)
2320 unsigned long region = vadr >> 61;
2321 u64 addr_range = 1UL << log_range;
2322 unsigned long rid, rr;
2323 int i;
2324 TR_ENTRY *trp;
2326 BUG_ON(vcpu != current);
2327 check_xen_space_overlap("ptr_d", vadr, 1UL << log_range);
2329 rr = PSCB(vcpu, rrs)[region];
2330 rid = rr & RR_RID_MASK;
2332 /* Purge TC */
2333 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2335 /* Purge tr and recompute dtr_regions. */
2336 vcpu->arch.dtr_regions = 0;
2337 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2338 if (vcpu_match_tr_entry_range
2339 (trp, rid, vadr, vadr + addr_range))
2340 vcpu_purge_tr_entry(trp);
2341 else if (trp->pte.p)
2342 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2343 trp->vadr);
2345 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2347 return IA64_NO_FAULT;
2350 IA64FAULT vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 log_range)
2352 unsigned long region = vadr >> 61;
2353 u64 addr_range = 1UL << log_range;
2354 unsigned long rid, rr;
2355 int i;
2356 TR_ENTRY *trp;
2358 BUG_ON(vcpu != current);
2359 check_xen_space_overlap("ptr_i", vadr, 1UL << log_range);
2361 rr = PSCB(vcpu, rrs)[region];
2362 rid = rr & RR_RID_MASK;
2364 /* Purge TC */
2365 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2367 /* Purge tr and recompute itr_regions. */
2368 vcpu->arch.itr_regions = 0;
2369 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2370 if (vcpu_match_tr_entry_range
2371 (trp, rid, vadr, vadr + addr_range))
2372 vcpu_purge_tr_entry(trp);
2373 else if (trp->pte.p)
2374 vcpu_quick_region_set(vcpu->arch.itr_regions,
2375 trp->vadr);
2377 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2379 return IA64_NO_FAULT;