direct-io.hg

view xen/arch/ia64/xen/vcpu.c @ 15104:4b4db1f10147

[IA64] Clear pending event when vcpu boots

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Mon May 07 13:14:27 2007 -0600 (2007-05-07)
parents f8aede89c706
children b4cc3fbcdf25
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 /* lazy fp */
145 FP_PSR(v) = IA64_PSR_DFH;
146 regs->cr_ipsr |= IA64_PSR_DFH;
147 } else {
148 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
149 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
150 regs->cr_ipsr &= ~(IA64_PSR_BITS_TO_CLEAR
151 | IA64_PSR_RI | IA64_PSR_IS);
152 // domain runs at PL2
153 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
154 // lazy fp
155 PSCB(v, hpsr_dfh) = 1;
156 PSCB(v, hpsr_mfh) = 0;
157 regs->cr_ipsr |= IA64_PSR_DFH;
158 }
159 regs->cr_ifs = 1UL << 63; /* or clear? */
160 regs->ar_fpsr = FPSR_DEFAULT;
162 if (VMX_DOMAIN(v)) {
163 vmx_init_all_rr(v);
164 /* Virtual processor context setup */
165 VCPU(v, vpsr) = IA64_PSR_BN;
166 VCPU(v, dcr) = 0;
167 } else {
168 init_all_rr(v);
169 regs->ar_rsc |= (2 << 2); /* force PL2/3 */
170 VCPU(v, banknum) = 1;
171 VCPU(v, metaphysical_mode) = 1;
172 VCPU(v, interrupt_mask_addr) =
173 (unsigned char *)v->domain->arch.shared_info_va +
174 INT_ENABLE_OFFSET(v);
175 VCPU(v, itv) = (1 << 16); /* timer vector masked */
177 /* SAL specification 3.2.4 */
178 VCPU(v, vpsr) = IA64_PSR_AC | IA64_PSR_IC | IA64_PSR_BN;
179 v->vcpu_info->evtchn_upcall_pending = 0;
180 v->vcpu_info->evtchn_upcall_mask = -1;
181 }
183 /* pta.size must not be 0. The minimum is 15 (32k) */
184 VCPU(v, pta) = 15 << 2;
186 v->arch.domain_itm_last = -1L;
187 }
189 /**************************************************************************
190 VCPU privileged application register access routines
191 **************************************************************************/
193 void vcpu_load_kernel_regs(VCPU * vcpu)
194 {
195 ia64_set_kr(0, VCPU(vcpu, krs[0]));
196 ia64_set_kr(1, VCPU(vcpu, krs[1]));
197 ia64_set_kr(2, VCPU(vcpu, krs[2]));
198 ia64_set_kr(3, VCPU(vcpu, krs[3]));
199 ia64_set_kr(4, VCPU(vcpu, krs[4]));
200 ia64_set_kr(5, VCPU(vcpu, krs[5]));
201 ia64_set_kr(6, VCPU(vcpu, krs[6]));
202 ia64_set_kr(7, VCPU(vcpu, krs[7]));
203 }
205 /* GCC 4.0.2 seems not to be able to suppress this call!. */
206 #define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
208 IA64FAULT vcpu_set_ar(VCPU * vcpu, u64 reg, u64 val)
209 {
210 if (reg == 44)
211 return vcpu_set_itc(vcpu, val);
212 else if (reg == 27)
213 return IA64_ILLOP_FAULT;
214 else if (reg == 24)
215 printk("warning: setting ar.eflg is a no-op; no IA-32 "
216 "support\n");
217 else if (reg > 7)
218 return IA64_ILLOP_FAULT;
219 else {
220 PSCB(vcpu, krs[reg]) = val;
221 ia64_set_kr(reg, val);
222 }
223 return IA64_NO_FAULT;
224 }
226 IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 reg, u64 * val)
227 {
228 if (reg == 24)
229 printk("warning: getting ar.eflg is a no-op; no IA-32 "
230 "support\n");
231 else if (reg > 7)
232 return IA64_ILLOP_FAULT;
233 else
234 *val = PSCB(vcpu, krs[reg]);
235 return IA64_NO_FAULT;
236 }
238 /**************************************************************************
239 VCPU processor status register access routines
240 **************************************************************************/
242 void vcpu_set_metaphysical_mode(VCPU * vcpu, BOOLEAN newmode)
243 {
244 /* only do something if mode changes */
245 if (!!newmode ^ !!PSCB(vcpu, metaphysical_mode)) {
246 PSCB(vcpu, metaphysical_mode) = newmode;
247 if (newmode)
248 set_metaphysical_rr0();
249 else if (PSCB(vcpu, rrs[0]) != -1)
250 set_one_rr(0, PSCB(vcpu, rrs[0]));
251 }
252 }
254 IA64FAULT vcpu_reset_psr_dt(VCPU * vcpu)
255 {
256 vcpu_set_metaphysical_mode(vcpu, TRUE);
257 return IA64_NO_FAULT;
258 }
260 IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24)
261 {
262 struct ia64_psr psr, imm, *ipsr;
263 REGS *regs = vcpu_regs(vcpu);
265 //PRIVOP_COUNT_ADDR(regs,_RSM);
266 // TODO: All of these bits need to be virtualized
267 // TODO: Only allowed for current vcpu
268 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
269 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
270 imm = *(struct ia64_psr *)&imm24;
271 // interrupt flag
272 if (imm.i)
273 vcpu->vcpu_info->evtchn_upcall_mask = 1;
274 if (imm.ic)
275 PSCB(vcpu, interrupt_collection_enabled) = 0;
276 // interrupt collection flag
277 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
278 // just handle psr.up and psr.pp for now
279 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
280 IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
281 IA64_PSR_DFL | IA64_PSR_DFH))
282 return IA64_ILLOP_FAULT;
283 if (imm.dfh) {
284 ipsr->dfh = PSCB(vcpu, hpsr_dfh);
285 PSCB(vcpu, vpsr_dfh) = 0;
286 }
287 if (imm.dfl)
288 ipsr->dfl = 0;
289 if (imm.pp) {
290 ipsr->pp = 1;
291 psr.pp = 1; // priv perf ctrs always enabled
292 PSCB(vcpu, vpsr_pp) = 0; // but fool the domain if it gets psr
293 }
294 if (imm.up) {
295 ipsr->up = 0;
296 psr.up = 0;
297 }
298 if (imm.sp) {
299 ipsr->sp = 0;
300 psr.sp = 0;
301 }
302 if (imm.be)
303 ipsr->be = 0;
304 if (imm.dt)
305 vcpu_set_metaphysical_mode(vcpu, TRUE);
306 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
307 return IA64_NO_FAULT;
308 }
310 IA64FAULT vcpu_set_psr_dt(VCPU * vcpu)
311 {
312 vcpu_set_metaphysical_mode(vcpu, FALSE);
313 return IA64_NO_FAULT;
314 }
316 IA64FAULT vcpu_set_psr_i(VCPU * vcpu)
317 {
318 vcpu->vcpu_info->evtchn_upcall_mask = 0;
319 PSCB(vcpu, interrupt_collection_enabled) = 1;
320 return IA64_NO_FAULT;
321 }
323 IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24)
324 {
325 struct ia64_psr psr, imm, *ipsr;
326 REGS *regs = vcpu_regs(vcpu);
327 u64 mask, enabling_interrupts = 0;
329 //PRIVOP_COUNT_ADDR(regs,_SSM);
330 // TODO: All of these bits need to be virtualized
331 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
332 imm = *(struct ia64_psr *)&imm24;
333 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
334 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
335 mask =
336 IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
337 IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE;
338 if (imm24 & ~mask)
339 return IA64_ILLOP_FAULT;
340 if (imm.dfh) {
341 PSCB(vcpu, vpsr_dfh) = 1;
342 ipsr->dfh = 1;
343 }
344 if (imm.dfl)
345 ipsr->dfl = 1;
346 if (imm.pp) {
347 ipsr->pp = 1;
348 psr.pp = 1;
349 PSCB(vcpu, vpsr_pp) = 1;
350 }
351 if (imm.sp) {
352 ipsr->sp = 1;
353 psr.sp = 1;
354 }
355 if (imm.i) {
356 if (vcpu->vcpu_info->evtchn_upcall_mask) {
357 //printk("vcpu_set_psr_sm: psr.ic 0->1\n");
358 enabling_interrupts = 1;
359 }
360 vcpu->vcpu_info->evtchn_upcall_mask = 0;
361 }
362 if (imm.ic)
363 PSCB(vcpu, interrupt_collection_enabled) = 1;
364 // TODO: do this faster
365 if (imm.mfl) {
366 ipsr->mfl = 1;
367 psr.mfl = 1;
368 }
369 if (imm.mfh) {
370 ipsr->mfh = 1;
371 psr.mfh = 1;
372 }
373 if (imm.ac) {
374 ipsr->ac = 1;
375 psr.ac = 1;
376 }
377 if (imm.up) {
378 ipsr->up = 1;
379 psr.up = 1;
380 }
381 if (imm.be)
382 ipsr->be = 1;
383 if (imm.dt)
384 vcpu_set_metaphysical_mode(vcpu, FALSE);
385 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
386 if (enabling_interrupts &&
387 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
388 PSCB(vcpu, pending_interruption) = 1;
389 return IA64_NO_FAULT;
390 }
392 IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val)
393 {
394 struct ia64_psr newpsr, *ipsr;
395 REGS *regs = vcpu_regs(vcpu);
396 u64 enabling_interrupts = 0;
398 newpsr = *(struct ia64_psr *)&val;
399 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
400 // just handle psr.up and psr.pp for now
401 //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP))
402 // return IA64_ILLOP_FAULT;
403 // however trying to set other bits can't be an error as it is in ssm
404 if (newpsr.dfh) {
405 ipsr->dfh = 1;
406 PSCB(vcpu, vpsr_dfh) = 1;
407 } else {
408 ipsr->dfh = PSCB(vcpu, hpsr_dfh);
409 PSCB(vcpu, vpsr_dfh) = 0;
410 }
411 if (newpsr.dfl)
412 ipsr->dfl = 1;
413 if (newpsr.pp) {
414 ipsr->pp = 1;
415 PSCB(vcpu, vpsr_pp) = 1;
416 } else {
417 ipsr->pp = 1;
418 PSCB(vcpu, vpsr_pp) = 0;
419 }
420 if (newpsr.up)
421 ipsr->up = 1;
422 if (newpsr.sp)
423 ipsr->sp = 1;
424 if (newpsr.i) {
425 if (vcpu->vcpu_info->evtchn_upcall_mask)
426 enabling_interrupts = 1;
427 vcpu->vcpu_info->evtchn_upcall_mask = 0;
428 }
429 if (newpsr.ic)
430 PSCB(vcpu, interrupt_collection_enabled) = 1;
431 if (newpsr.mfl)
432 ipsr->mfl = 1;
433 if (newpsr.mfh)
434 ipsr->mfh = 1;
435 if (newpsr.ac)
436 ipsr->ac = 1;
437 if (newpsr.up)
438 ipsr->up = 1;
439 if (newpsr.dt && newpsr.rt)
440 vcpu_set_metaphysical_mode(vcpu, FALSE);
441 else
442 vcpu_set_metaphysical_mode(vcpu, TRUE);
443 if (newpsr.be)
444 ipsr->be = 1;
445 if (enabling_interrupts &&
446 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
447 PSCB(vcpu, pending_interruption) = 1;
448 return IA64_NO_FAULT;
449 }
451 IA64FAULT vcpu_get_psr(VCPU * vcpu, u64 * pval)
452 {
453 REGS *regs = vcpu_regs(vcpu);
454 struct ia64_psr newpsr;
456 newpsr = *(struct ia64_psr *)&regs->cr_ipsr;
457 if (!vcpu->vcpu_info->evtchn_upcall_mask)
458 newpsr.i = 1;
459 else
460 newpsr.i = 0;
461 if (PSCB(vcpu, interrupt_collection_enabled))
462 newpsr.ic = 1;
463 else
464 newpsr.ic = 0;
465 if (PSCB(vcpu, metaphysical_mode))
466 newpsr.dt = 0;
467 else
468 newpsr.dt = 1;
469 if (PSCB(vcpu, vpsr_pp))
470 newpsr.pp = 1;
471 else
472 newpsr.pp = 0;
473 newpsr.dfh = PSCB(vcpu, vpsr_dfh);
475 *pval = *(unsigned long *)&newpsr;
476 *pval &= (MASK(0, 32) | MASK(35, 2));
477 return IA64_NO_FAULT;
478 }
480 BOOLEAN vcpu_get_psr_ic(VCPU * vcpu)
481 {
482 return !!PSCB(vcpu, interrupt_collection_enabled);
483 }
485 BOOLEAN vcpu_get_psr_i(VCPU * vcpu)
486 {
487 return !vcpu->vcpu_info->evtchn_upcall_mask;
488 }
490 u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr)
491 {
492 u64 dcr = PSCB(vcpu, dcr);
493 PSR psr;
495 //printk("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr);
496 psr.i64 = prevpsr;
497 psr.ia64_psr.pp = 0;
498 if (dcr & IA64_DCR_PP)
499 psr.ia64_psr.pp = 1;
500 psr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled);
501 psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
502 psr.ia64_psr.bn = PSCB(vcpu, banknum);
503 psr.ia64_psr.dfh = PSCB(vcpu, vpsr_dfh);
504 psr.ia64_psr.dt = 1;
505 psr.ia64_psr.it = 1;
506 psr.ia64_psr.rt = 1;
507 if (psr.ia64_psr.cpl == 2)
508 psr.ia64_psr.cpl = 0; // !!!! fool domain
509 // psr.pk = 1;
510 //printk("returns 0x%016lx...\n",psr.i64);
511 return psr.i64;
512 }
514 /**************************************************************************
515 VCPU control register access routines
516 **************************************************************************/
518 IA64FAULT vcpu_get_dcr(VCPU * vcpu, u64 * pval)
519 {
520 *pval = PSCB(vcpu, dcr);
521 return IA64_NO_FAULT;
522 }
524 IA64FAULT vcpu_get_iva(VCPU * vcpu, u64 * pval)
525 {
526 if (VMX_DOMAIN(vcpu))
527 *pval = PSCB(vcpu, iva) & ~0x7fffL;
528 else
529 *pval = PSCBX(vcpu, iva) & ~0x7fffL;
531 return IA64_NO_FAULT;
532 }
534 IA64FAULT vcpu_get_pta(VCPU * vcpu, u64 * pval)
535 {
536 *pval = PSCB(vcpu, pta);
537 return IA64_NO_FAULT;
538 }
540 IA64FAULT vcpu_get_ipsr(VCPU * vcpu, u64 * pval)
541 {
542 //REGS *regs = vcpu_regs(vcpu);
543 //*pval = regs->cr_ipsr;
544 *pval = PSCB(vcpu, ipsr);
545 return IA64_NO_FAULT;
546 }
548 IA64FAULT vcpu_get_isr(VCPU * vcpu, u64 * pval)
549 {
550 *pval = PSCB(vcpu, isr);
551 return IA64_NO_FAULT;
552 }
554 IA64FAULT vcpu_get_iip(VCPU * vcpu, u64 * pval)
555 {
556 //REGS *regs = vcpu_regs(vcpu);
557 //*pval = regs->cr_iip;
558 *pval = PSCB(vcpu, iip);
559 return IA64_NO_FAULT;
560 }
562 IA64FAULT vcpu_get_ifa(VCPU * vcpu, u64 * pval)
563 {
564 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_get_ifa);
565 *pval = PSCB(vcpu, ifa);
566 return IA64_NO_FAULT;
567 }
569 unsigned long vcpu_get_rr_ps(VCPU * vcpu, u64 vadr)
570 {
571 ia64_rr rr;
573 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
574 return rr.ps;
575 }
577 unsigned long vcpu_get_rr_rid(VCPU * vcpu, u64 vadr)
578 {
579 ia64_rr rr;
581 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
582 return rr.rid;
583 }
585 unsigned long vcpu_get_itir_on_fault(VCPU * vcpu, u64 ifa)
586 {
587 ia64_rr rr;
589 rr.rrval = 0;
590 rr.ps = vcpu_get_rr_ps(vcpu, ifa);
591 rr.rid = vcpu_get_rr_rid(vcpu, ifa);
592 return rr.rrval;
593 }
595 IA64FAULT vcpu_get_itir(VCPU * vcpu, u64 * pval)
596 {
597 u64 val = PSCB(vcpu, itir);
598 *pval = val;
599 return IA64_NO_FAULT;
600 }
602 IA64FAULT vcpu_get_iipa(VCPU * vcpu, u64 * pval)
603 {
604 u64 val = PSCB(vcpu, iipa);
605 // SP entry code does not save iipa yet nor does it get
606 // properly delivered in the pscb
607 // printk("*** vcpu_get_iipa: cr.iipa not fully implemented yet!!\n");
608 *pval = val;
609 return IA64_NO_FAULT;
610 }
612 IA64FAULT vcpu_get_ifs(VCPU * vcpu, u64 * pval)
613 {
614 //PSCB(vcpu,ifs) = PSCB(vcpu)->regs.cr_ifs;
615 //*pval = PSCB(vcpu,regs).cr_ifs;
616 *pval = PSCB(vcpu, ifs);
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 PSCB(vcpu, dcr) = val;
637 return IA64_NO_FAULT;
638 }
640 IA64FAULT vcpu_set_iva(VCPU * vcpu, u64 val)
641 {
642 if (VMX_DOMAIN(vcpu))
643 PSCB(vcpu, iva) = val & ~0x7fffL;
644 else
645 PSCBX(vcpu, iva) = val & ~0x7fffL;
647 return IA64_NO_FAULT;
648 }
650 IA64FAULT vcpu_set_pta(VCPU * vcpu, u64 val)
651 {
652 if (val & IA64_PTA_LFMT) {
653 printk("*** No support for VHPT long format yet!!\n");
654 return IA64_ILLOP_FAULT;
655 }
656 if (val & (0x3f << 9)) /* reserved fields */
657 return IA64_RSVDREG_FAULT;
658 if (val & 2) /* reserved fields */
659 return IA64_RSVDREG_FAULT;
660 PSCB(vcpu, pta) = val;
661 return IA64_NO_FAULT;
662 }
664 IA64FAULT vcpu_set_ipsr(VCPU * vcpu, u64 val)
665 {
666 PSCB(vcpu, ipsr) = val;
667 return IA64_NO_FAULT;
668 }
670 IA64FAULT vcpu_set_isr(VCPU * vcpu, u64 val)
671 {
672 PSCB(vcpu, isr) = val;
673 return IA64_NO_FAULT;
674 }
676 IA64FAULT vcpu_set_iip(VCPU * vcpu, u64 val)
677 {
678 PSCB(vcpu, iip) = val;
679 return IA64_NO_FAULT;
680 }
682 IA64FAULT vcpu_increment_iip(VCPU * vcpu)
683 {
684 REGS *regs = vcpu_regs(vcpu);
685 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
686 if (ipsr->ri == 2) {
687 ipsr->ri = 0;
688 regs->cr_iip += 16;
689 } else
690 ipsr->ri++;
691 return IA64_NO_FAULT;
692 }
694 IA64FAULT vcpu_decrement_iip(VCPU * vcpu)
695 {
696 REGS *regs = vcpu_regs(vcpu);
697 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
699 if (ipsr->ri == 0) {
700 ipsr->ri = 2;
701 regs->cr_iip -= 16;
702 } else
703 ipsr->ri--;
705 return IA64_NO_FAULT;
706 }
708 IA64FAULT vcpu_set_ifa(VCPU * vcpu, u64 val)
709 {
710 PSCB(vcpu, ifa) = val;
711 return IA64_NO_FAULT;
712 }
714 IA64FAULT vcpu_set_itir(VCPU * vcpu, u64 val)
715 {
716 PSCB(vcpu, itir) = val;
717 return IA64_NO_FAULT;
718 }
720 IA64FAULT vcpu_set_iipa(VCPU * vcpu, u64 val)
721 {
722 // SP entry code does not save iipa yet nor does it get
723 // properly delivered in the pscb
724 // printk("*** vcpu_set_iipa: cr.iipa not fully implemented yet!!\n");
725 PSCB(vcpu, iipa) = val;
726 return IA64_NO_FAULT;
727 }
729 IA64FAULT vcpu_set_ifs(VCPU * vcpu, u64 val)
730 {
731 //REGS *regs = vcpu_regs(vcpu);
732 PSCB(vcpu, ifs) = val;
733 return IA64_NO_FAULT;
734 }
736 IA64FAULT vcpu_set_iim(VCPU * vcpu, u64 val)
737 {
738 PSCB(vcpu, iim) = val;
739 return IA64_NO_FAULT;
740 }
742 IA64FAULT vcpu_set_iha(VCPU * vcpu, u64 val)
743 {
744 PSCB(vcpu, iha) = val;
745 return IA64_NO_FAULT;
746 }
748 /**************************************************************************
749 VCPU interrupt control register access routines
750 **************************************************************************/
752 void vcpu_pend_unspecified_interrupt(VCPU * vcpu)
753 {
754 PSCB(vcpu, pending_interruption) = 1;
755 }
757 void vcpu_pend_interrupt(VCPU * vcpu, u64 vector)
758 {
759 if (vector & ~0xff) {
760 printk("vcpu_pend_interrupt: bad vector\n");
761 return;
762 }
764 if (vcpu->arch.event_callback_ip) {
765 printk("Deprecated interface. Move to new event based "
766 "solution\n");
767 return;
768 }
770 if (VMX_DOMAIN(vcpu)) {
771 set_bit(vector, VCPU(vcpu, irr));
772 } else {
773 set_bit(vector, PSCBX(vcpu, irr));
774 PSCB(vcpu, pending_interruption) = 1;
775 }
776 }
778 #define IA64_TPR_MMI 0x10000
779 #define IA64_TPR_MIC 0x000f0
781 /* checks to see if a VCPU has any unmasked pending interrupts
782 * if so, returns the highest, else returns SPURIOUS_VECTOR */
783 /* NOTE: Since this gets called from vcpu_get_ivr() and the
784 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
785 * this routine also ignores pscb.interrupt_delivery_enabled
786 * and this must be checked independently; see vcpu_deliverable interrupts() */
787 u64 vcpu_check_pending_interrupts(VCPU * vcpu)
788 {
789 u64 *p, *r, bits, bitnum, mask, i, vector;
791 if (vcpu->arch.event_callback_ip)
792 return SPURIOUS_VECTOR;
794 /* Always check pending event, since guest may just ack the
795 * event injection without handle. Later guest may throw out
796 * the event itself.
797 */
798 check_start:
799 if (event_pending(vcpu) &&
800 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
801 &PSCBX(vcpu, insvc[0])))
802 vcpu_pend_interrupt(vcpu,
803 vcpu->domain->shared_info->arch.
804 evtchn_vector);
806 p = &PSCBX(vcpu, irr[3]);
807 r = &PSCBX(vcpu, insvc[3]);
808 for (i = 3 ;; p--, r--, i--) {
809 bits = *p;
810 if (bits)
811 break; // got a potential interrupt
812 if (*r) {
813 // nothing in this word which is pending+inservice
814 // but there is one inservice which masks lower
815 return SPURIOUS_VECTOR;
816 }
817 if (i == 0) {
818 // checked all bits... nothing pending+inservice
819 return SPURIOUS_VECTOR;
820 }
821 }
822 // have a pending,deliverable interrupt... see if it is masked
823 bitnum = ia64_fls(bits);
824 //printk("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
825 vector = bitnum + (i * 64);
826 mask = 1L << bitnum;
827 /* sanity check for guest timer interrupt */
828 if (vector == (PSCB(vcpu, itv) & 0xff)) {
829 uint64_t now = ia64_get_itc();
830 if (now < PSCBX(vcpu, domain_itm)) {
831 // printk("Ooops, pending guest timer before its due\n");
832 PSCBX(vcpu, irr[i]) &= ~mask;
833 goto check_start;
834 }
835 }
836 //printk("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
837 if (*r >= mask) {
838 // masked by equal inservice
839 //printk("but masked by equal inservice\n");
840 return SPURIOUS_VECTOR;
841 }
842 if (PSCB(vcpu, tpr) & IA64_TPR_MMI) {
843 // tpr.mmi is set
844 //printk("but masked by tpr.mmi\n");
845 return SPURIOUS_VECTOR;
846 }
847 if (((PSCB(vcpu, tpr) & IA64_TPR_MIC) + 15) >= vector) {
848 //tpr.mic masks class
849 //printk("but masked by tpr.mic\n");
850 return SPURIOUS_VECTOR;
851 }
852 //printk("returned to caller\n");
853 return vector;
854 }
856 u64 vcpu_deliverable_interrupts(VCPU * vcpu)
857 {
858 return (vcpu_get_psr_i(vcpu) &&
859 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
860 }
862 u64 vcpu_deliverable_timer(VCPU * vcpu)
863 {
864 return (vcpu_get_psr_i(vcpu) &&
865 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu, itv));
866 }
868 IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval)
869 {
870 /* Use EID=0, ID=vcpu_id. */
871 *pval = vcpu->vcpu_id << 24;
872 return IA64_NO_FAULT;
873 }
875 IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval)
876 {
877 int i;
878 u64 vector, mask;
880 #define HEARTBEAT_FREQ 16 // period in seconds
881 #ifdef HEARTBEAT_FREQ
882 #define N_DOMS 16 // period in seconds
883 #if 0
884 static long count[N_DOMS] = { 0 };
885 #endif
886 static long nonclockcount[N_DOMS] = { 0 };
887 unsigned domid = vcpu->domain->domain_id;
888 #endif
889 #ifdef IRQ_DEBUG
890 static char firstivr = 1;
891 static char firsttime[256];
892 if (firstivr) {
893 int i;
894 for (i = 0; i < 256; i++)
895 firsttime[i] = 1;
896 firstivr = 0;
897 }
898 #endif
900 vector = vcpu_check_pending_interrupts(vcpu);
901 if (vector == SPURIOUS_VECTOR) {
902 PSCB(vcpu, pending_interruption) = 0;
903 *pval = vector;
904 return IA64_NO_FAULT;
905 }
906 #ifdef HEARTBEAT_FREQ
907 if (domid >= N_DOMS)
908 domid = N_DOMS - 1;
909 #if 0
910 if (vector == (PSCB(vcpu, itv) & 0xff)) {
911 if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) {
912 printk("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
913 domid, count[domid], nonclockcount[domid]);
914 //count[domid] = 0;
915 //dump_runq();
916 }
917 }
918 #endif
919 else
920 nonclockcount[domid]++;
921 #endif
922 // now have an unmasked, pending, deliverable vector!
923 // getting ivr has "side effects"
924 #ifdef IRQ_DEBUG
925 if (firsttime[vector]) {
926 printk("*** First get_ivr on vector=%lu,itc=%lx\n",
927 vector, ia64_get_itc());
928 firsttime[vector] = 0;
929 }
930 #endif
931 /* if delivering a timer interrupt, remember domain_itm, which
932 * needs to be done before clearing irr
933 */
934 if (vector == (PSCB(vcpu, itv) & 0xff)) {
935 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
936 }
938 i = vector >> 6;
939 mask = 1L << (vector & 0x3f);
940 //printk("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
941 PSCBX(vcpu, insvc[i]) |= mask;
942 PSCBX(vcpu, irr[i]) &= ~mask;
943 //PSCB(vcpu,pending_interruption)--;
944 *pval = vector;
945 return IA64_NO_FAULT;
946 }
948 IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval)
949 {
950 *pval = PSCB(vcpu, tpr);
951 return IA64_NO_FAULT;
952 }
954 IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval)
955 {
956 *pval = 0L; // reads of eoi always return 0
957 return IA64_NO_FAULT;
958 }
960 IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval)
961 {
962 *pval = PSCBX(vcpu, irr[0]);
963 return IA64_NO_FAULT;
964 }
966 IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval)
967 {
968 *pval = PSCBX(vcpu, irr[1]);
969 return IA64_NO_FAULT;
970 }
972 IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval)
973 {
974 *pval = PSCBX(vcpu, irr[2]);
975 return IA64_NO_FAULT;
976 }
978 IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval)
979 {
980 *pval = PSCBX(vcpu, irr[3]);
981 return IA64_NO_FAULT;
982 }
984 IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval)
985 {
986 *pval = PSCB(vcpu, itv);
987 return IA64_NO_FAULT;
988 }
990 IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval)
991 {
992 *pval = PSCB(vcpu, pmv);
993 return IA64_NO_FAULT;
994 }
996 IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval)
997 {
998 *pval = PSCB(vcpu, cmcv);
999 return IA64_NO_FAULT;
1002 IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval)
1004 // fix this when setting values other than m-bit is supported
1005 gdprintk(XENLOG_DEBUG,
1006 "vcpu_get_lrr0: Unmasked interrupts unsupported\n");
1007 *pval = (1L << 16);
1008 return IA64_NO_FAULT;
1011 IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval)
1013 // fix this when setting values other than m-bit is supported
1014 gdprintk(XENLOG_DEBUG,
1015 "vcpu_get_lrr1: Unmasked interrupts unsupported\n");
1016 *pval = (1L << 16);
1017 return IA64_NO_FAULT;
1020 IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val)
1022 printk("vcpu_set_lid: Setting cr.lid is unsupported\n");
1023 return IA64_ILLOP_FAULT;
1026 IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val)
1028 if (val & 0xff00)
1029 return IA64_RSVDREG_FAULT;
1030 PSCB(vcpu, tpr) = val;
1031 /* This can unmask interrupts. */
1032 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
1033 PSCB(vcpu, pending_interruption) = 1;
1034 return IA64_NO_FAULT;
1037 IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val)
1039 u64 *p, bits, vec, bitnum;
1040 int i;
1042 p = &PSCBX(vcpu, insvc[3]);
1043 for (i = 3; (i >= 0) && !(bits = *p); i--, p--)
1045 if (i < 0) {
1046 printk("Trying to EOI interrupt when none are in-service.\n");
1047 return IA64_NO_FAULT;
1049 bitnum = ia64_fls(bits);
1050 vec = bitnum + (i * 64);
1051 /* clear the correct bit */
1052 bits &= ~(1L << bitnum);
1053 *p = bits;
1054 /* clearing an eoi bit may unmask another pending interrupt... */
1055 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
1056 // worry about this later... Linux only calls eoi
1057 // with interrupts disabled
1058 printk("Trying to EOI interrupt with interrupts enabled\n");
1060 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
1061 PSCB(vcpu, pending_interruption) = 1;
1062 //printk("YYYYY vcpu_set_eoi: Successful\n");
1063 return IA64_NO_FAULT;
1066 IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val)
1068 if (!(val & (1L << 16))) {
1069 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
1070 return IA64_ILLOP_FAULT;
1072 // no place to save this state but nothing to do anyway
1073 return IA64_NO_FAULT;
1076 IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val)
1078 if (!(val & (1L << 16))) {
1079 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
1080 return IA64_ILLOP_FAULT;
1082 // no place to save this state but nothing to do anyway
1083 return IA64_NO_FAULT;
1086 IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val)
1088 /* Check reserved fields. */
1089 if (val & 0xef00)
1090 return IA64_ILLOP_FAULT;
1091 PSCB(vcpu, itv) = val;
1092 if (val & 0x10000) {
1093 /* Disable itm. */
1094 PSCBX(vcpu, domain_itm) = 0;
1095 } else
1096 vcpu_set_next_timer(vcpu);
1097 return IA64_NO_FAULT;
1100 IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val)
1102 if (val & 0xef00) /* reserved fields */
1103 return IA64_RSVDREG_FAULT;
1104 PSCB(vcpu, pmv) = val;
1105 return IA64_NO_FAULT;
1108 IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val)
1110 if (val & 0xef00) /* reserved fields */
1111 return IA64_RSVDREG_FAULT;
1112 PSCB(vcpu, cmcv) = val;
1113 return IA64_NO_FAULT;
1116 /**************************************************************************
1117 VCPU temporary register access routines
1118 **************************************************************************/
1119 u64 vcpu_get_tmp(VCPU * vcpu, u64 index)
1121 if (index > 7)
1122 return 0;
1123 return PSCB(vcpu, tmp[index]);
1126 void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val)
1128 if (index <= 7)
1129 PSCB(vcpu, tmp[index]) = val;
1132 /**************************************************************************
1133 Interval timer routines
1134 **************************************************************************/
1136 BOOLEAN vcpu_timer_disabled(VCPU * vcpu)
1138 u64 itv = PSCB(vcpu, itv);
1139 return (!itv || !!(itv & 0x10000));
1142 BOOLEAN vcpu_timer_inservice(VCPU * vcpu)
1144 u64 itv = PSCB(vcpu, itv);
1145 return test_bit(itv, PSCBX(vcpu, insvc));
1148 BOOLEAN vcpu_timer_expired(VCPU * vcpu)
1150 unsigned long domain_itm = PSCBX(vcpu, domain_itm);
1151 unsigned long now = ia64_get_itc();
1153 if (!domain_itm)
1154 return FALSE;
1155 if (now < domain_itm)
1156 return FALSE;
1157 if (vcpu_timer_disabled(vcpu))
1158 return FALSE;
1159 return TRUE;
1162 void vcpu_safe_set_itm(unsigned long val)
1164 unsigned long epsilon = 100;
1165 unsigned long flags;
1166 u64 now = ia64_get_itc();
1168 local_irq_save(flags);
1169 while (1) {
1170 //printk("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1171 ia64_set_itm(val);
1172 if (val > (now = ia64_get_itc()))
1173 break;
1174 val = now + epsilon;
1175 epsilon <<= 1;
1177 local_irq_restore(flags);
1180 void vcpu_set_next_timer(VCPU * vcpu)
1182 u64 d = PSCBX(vcpu, domain_itm);
1183 //u64 s = PSCBX(vcpu,xen_itm);
1184 u64 s = local_cpu_data->itm_next;
1185 u64 now = ia64_get_itc();
1187 /* gloss over the wraparound problem for now... we know it exists
1188 * but it doesn't matter right now */
1190 if (is_idle_domain(vcpu->domain)) {
1191 // printk("****** vcpu_set_next_timer called during idle!!\n");
1192 vcpu_safe_set_itm(s);
1193 return;
1195 //s = PSCBX(vcpu,xen_itm);
1196 if (d && (d > now) && (d < s)) {
1197 vcpu_safe_set_itm(d);
1198 //using_domain_as_itm++;
1199 } else {
1200 vcpu_safe_set_itm(s);
1201 //using_xen_as_itm++;
1205 IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val)
1207 //UINT now = ia64_get_itc();
1209 //if (val < now) val = now + 1000;
1210 //printk("*** vcpu_set_itm: called with %lx\n",val);
1211 PSCBX(vcpu, domain_itm) = val;
1212 vcpu_set_next_timer(vcpu);
1213 return IA64_NO_FAULT;
1216 IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val)
1218 #define DISALLOW_SETTING_ITC_FOR_NOW
1219 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1220 static int did_print;
1221 if (!did_print) {
1222 printk("vcpu_set_itc: Setting ar.itc is currently disabled "
1223 "(this message is only displayed once)\n");
1224 did_print = 1;
1226 #else
1227 u64 oldnow = ia64_get_itc();
1228 u64 olditm = PSCBX(vcpu, domain_itm);
1229 unsigned long d = olditm - oldnow;
1230 unsigned long x = local_cpu_data->itm_next - oldnow;
1232 u64 newnow = val, min_delta;
1234 local_irq_disable();
1235 if (olditm) {
1236 printk("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val,
1237 newnow + d);
1238 PSCBX(vcpu, domain_itm) = newnow + d;
1240 local_cpu_data->itm_next = newnow + x;
1241 d = PSCBX(vcpu, domain_itm);
1242 x = local_cpu_data->itm_next;
1244 ia64_set_itc(newnow);
1245 if (d && (d > newnow) && (d < x)) {
1246 vcpu_safe_set_itm(d);
1247 //using_domain_as_itm++;
1248 } else {
1249 vcpu_safe_set_itm(x);
1250 //using_xen_as_itm++;
1252 local_irq_enable();
1253 #endif
1254 return IA64_NO_FAULT;
1257 IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval)
1259 //FIXME: Implement this
1260 printk("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1261 return IA64_NO_FAULT;
1262 //return IA64_ILLOP_FAULT;
1265 IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval)
1267 //TODO: Implement this
1268 printk("vcpu_get_itc: Getting ar.itc is unsupported\n");
1269 return IA64_ILLOP_FAULT;
1272 void vcpu_pend_timer(VCPU * vcpu)
1274 u64 itv = PSCB(vcpu, itv) & 0xff;
1276 if (vcpu_timer_disabled(vcpu))
1277 return;
1278 //if (vcpu_timer_inservice(vcpu)) return;
1279 if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) {
1280 // already delivered an interrupt for this so
1281 // don't deliver another
1282 return;
1284 if (vcpu->arch.event_callback_ip) {
1285 /* A small window may occur when injecting vIRQ while related
1286 * handler has not been registered. Don't fire in such case.
1287 */
1288 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1289 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1290 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1292 } else
1293 vcpu_pend_interrupt(vcpu, itv);
1296 // returns true if ready to deliver a timer interrupt too early
1297 u64 vcpu_timer_pending_early(VCPU * vcpu)
1299 u64 now = ia64_get_itc();
1300 u64 itm = PSCBX(vcpu, domain_itm);
1302 if (vcpu_timer_disabled(vcpu))
1303 return 0;
1304 if (!itm)
1305 return 0;
1306 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1309 /**************************************************************************
1310 Privileged operation emulation routines
1311 **************************************************************************/
1313 static void vcpu_force_tlb_miss(VCPU * vcpu, u64 ifa)
1315 PSCB(vcpu, ifa) = ifa;
1316 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1317 vcpu_thash(current, ifa, &PSCB(current, iha));
1320 IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa)
1322 vcpu_force_tlb_miss(vcpu, ifa);
1323 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_INST_TLB_VECTOR :
1324 IA64_ALT_INST_TLB_VECTOR;
1327 IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa)
1329 vcpu_force_tlb_miss(vcpu, ifa);
1330 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_DATA_TLB_VECTOR :
1331 IA64_ALT_DATA_TLB_VECTOR;
1334 IA64FAULT vcpu_rfi(VCPU * vcpu)
1336 // TODO: Only allowed for current vcpu
1337 PSR psr;
1338 u64 int_enable, ifs;
1339 REGS *regs = vcpu_regs(vcpu);
1341 psr.i64 = PSCB(vcpu, ipsr);
1342 if (psr.ia64_psr.cpl < 3)
1343 psr.ia64_psr.cpl = 2;
1344 int_enable = psr.ia64_psr.i;
1345 if (psr.ia64_psr.dfh) {
1346 PSCB(vcpu, vpsr_dfh) = 1;
1347 } else {
1348 psr.ia64_psr.dfh = PSCB(vcpu, hpsr_dfh);
1349 PSCB(vcpu, vpsr_dfh) = 0;
1351 if (psr.ia64_psr.ic)
1352 PSCB(vcpu, interrupt_collection_enabled) = 1;
1353 if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it)
1354 vcpu_set_metaphysical_mode(vcpu, FALSE);
1355 else
1356 vcpu_set_metaphysical_mode(vcpu, TRUE);
1357 psr.ia64_psr.ic = 1;
1358 psr.ia64_psr.i = 1;
1359 psr.ia64_psr.dt = 1;
1360 psr.ia64_psr.rt = 1;
1361 psr.ia64_psr.it = 1;
1362 psr.ia64_psr.bn = 1;
1363 //psr.pk = 1; // checking pkeys shouldn't be a problem but seems broken
1365 ifs = PSCB(vcpu, ifs);
1366 if (ifs & 0x8000000000000000UL)
1367 regs->cr_ifs = ifs;
1369 regs->cr_ipsr = psr.i64;
1370 regs->cr_iip = PSCB(vcpu, iip);
1371 PSCB(vcpu, interrupt_collection_enabled) = 1;
1372 vcpu_bsw1(vcpu);
1373 vcpu->vcpu_info->evtchn_upcall_mask = !int_enable;
1374 return IA64_NO_FAULT;
1377 IA64FAULT vcpu_cover(VCPU * vcpu)
1379 // TODO: Only allowed for current vcpu
1380 REGS *regs = vcpu_regs(vcpu);
1382 if (!PSCB(vcpu, interrupt_collection_enabled)) {
1383 PSCB(vcpu, ifs) = regs->cr_ifs;
1385 regs->cr_ifs = 0;
1386 return IA64_NO_FAULT;
1389 IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval)
1391 u64 pta = PSCB(vcpu, pta);
1392 u64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1393 u64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT) - 1);
1394 u64 Mask = (1L << pta_sz) - 1;
1395 u64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1396 u64 compMask_60_15 = ~Mask_60_15;
1397 u64 rr_ps = vcpu_get_rr_ps(vcpu, vadr);
1398 u64 VHPT_offset = (vadr >> rr_ps) << 3;
1399 u64 VHPT_addr1 = vadr & 0xe000000000000000L;
1400 u64 VHPT_addr2a =
1401 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1402 u64 VHPT_addr2b =
1403 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1404 u64 VHPT_addr3 = VHPT_offset & 0x7fff;
1405 u64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1406 VHPT_addr3;
1408 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1409 *pval = VHPT_addr;
1410 return IA64_NO_FAULT;
1413 IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr)
1415 printk("vcpu_ttag: ttag instruction unsupported\n");
1416 return IA64_ILLOP_FAULT;
1419 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1421 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1422 static inline int range_overlap(u64 b1, u64 e1, u64 b2, u64 e2)
1424 return (b1 <= e2) && (e1 >= b2);
1427 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1428 Note: LSBs of base inside page_size are ignored. */
1429 static inline void
1430 check_xen_space_overlap(const char *func, u64 base, u64 page_size)
1432 /* Overlaps can occur only in region 7.
1433 (This is an optimization to bypass all the checks). */
1434 if (REGION_NUMBER(base) != 7)
1435 return;
1437 /* Mask LSBs of base. */
1438 base &= ~(page_size - 1);
1440 /* FIXME: ideally an MCA should be generated... */
1441 if (range_overlap(HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
1442 base, base + page_size)
1443 || range_overlap(current->domain->arch.shared_info_va,
1444 current->domain->arch.shared_info_va
1445 + XSI_SIZE + XMAPPEDREGS_SIZE,
1446 base, base + page_size))
1447 panic_domain(NULL, "%s on Xen virtual space (%lx)\n",
1448 func, base);
1451 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1452 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY * trp, u64 ifa,
1453 u64 rid)
1455 return trp->rid == rid
1456 && ifa >= trp->vadr && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1459 static inline int vcpu_match_tr_entry(TR_ENTRY * trp, u64 ifa, u64 rid)
1461 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1464 static inline int
1465 vcpu_match_tr_entry_range(TR_ENTRY * trp, u64 rid, u64 b, u64 e)
1467 return trp->rid == rid
1468 && trp->pte.p
1469 && range_overlap(b, e, trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1473 static TR_ENTRY *vcpu_tr_lookup(VCPU * vcpu, unsigned long va, u64 rid,
1474 BOOLEAN is_data)
1476 unsigned char *regions;
1477 TR_ENTRY *trp;
1478 int tr_max;
1479 int i;
1481 if (is_data) {
1482 // data
1483 regions = &vcpu->arch.dtr_regions;
1484 trp = vcpu->arch.dtrs;
1485 tr_max = sizeof(vcpu->arch.dtrs) / sizeof(vcpu->arch.dtrs[0]);
1486 } else {
1487 // instruction
1488 regions = &vcpu->arch.itr_regions;
1489 trp = vcpu->arch.itrs;
1490 tr_max = sizeof(vcpu->arch.itrs) / sizeof(vcpu->arch.itrs[0]);
1493 if (!vcpu_quick_region_check(*regions, va)) {
1494 return NULL;
1496 for (i = 0; i < tr_max; i++, trp++) {
1497 if (vcpu_match_tr_entry(trp, va, rid)) {
1498 return trp;
1501 return NULL;
1504 // return value
1505 // 0: failure
1506 // 1: success
1507 int
1508 vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
1509 IA64_BUNDLE * bundle)
1511 u64 gpip; // guest pseudo phyiscal ip
1512 unsigned long vaddr;
1513 struct page_info *page;
1515 again:
1516 #if 0
1517 // Currently xen doesn't track psr.it bits.
1518 // it assumes always psr.it = 1.
1519 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1520 gpip = gip;
1521 } else
1522 #endif
1524 unsigned long region = REGION_NUMBER(gip);
1525 unsigned long rr = PSCB(vcpu, rrs)[region];
1526 unsigned long rid = rr & RR_RID_MASK;
1527 BOOLEAN swap_rr0;
1528 TR_ENTRY *trp;
1530 // vcpu->arch.{i, d}tlb are volatile,
1531 // copy its value to the variable, tr, before use.
1532 TR_ENTRY tr;
1534 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1535 if (trp != NULL) {
1536 tr = *trp;
1537 goto found;
1539 // When it failed to get a bundle, itlb miss is reflected.
1540 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1541 tr = PSCBX(vcpu, itlb);
1542 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1543 //dprintk(XENLOG_WARNING,
1544 // "%s gip 0x%lx gpip 0x%lx\n", __func__,
1545 // gip, gpip);
1546 goto found;
1548 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1549 if (trp != NULL) {
1550 tr = *trp;
1551 goto found;
1553 #if 0
1554 tr = PSCBX(vcpu, dtlb);
1555 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1556 goto found;
1558 #endif
1560 // try to access gip with guest virtual address
1561 // This may cause tlb miss. see vcpu_translate(). Be careful!
1562 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1563 if (swap_rr0) {
1564 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
1566 *bundle = __get_domain_bundle(gip);
1567 if (swap_rr0) {
1568 set_metaphysical_rr0();
1570 if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
1571 dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
1572 return 0;
1574 return 1;
1576 found:
1577 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1578 (gip & ((1 << tr.ps) - 1));
1581 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1582 page = virt_to_page(vaddr);
1583 if (get_page(page, vcpu->domain) == 0) {
1584 if (page_get_owner(page) != vcpu->domain) {
1585 // This page might be a page granted by another
1586 // domain.
1587 panic_domain(regs, "domain tries to execute foreign "
1588 "domain page which might be mapped by "
1589 "grant table.\n");
1591 goto again;
1593 *bundle = *((IA64_BUNDLE *) vaddr);
1594 put_page(page);
1595 return 1;
1598 IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
1599 u64 * pteval, u64 * itir, u64 * iha)
1601 unsigned long region = address >> 61;
1602 unsigned long pta, rid, rr;
1603 union pte_flags pte;
1604 TR_ENTRY *trp;
1606 if (PSCB(vcpu, metaphysical_mode) && !(!is_data && region)) {
1607 // dom0 may generate an uncacheable physical address (msb=1)
1608 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1609 // FIXME: This seems to happen even though it shouldn't. Need to track
1610 // this down, but since it has been apparently harmless, just flag it for now
1611 // panic_domain(vcpu_regs(vcpu),
1613 /*
1614 * Guest may execute itc.d and rfi with psr.dt=0
1615 * When VMM try to fetch opcode, tlb miss may happen,
1616 * At this time PSCB(vcpu,metaphysical_mode)=1,
1617 * region=5,VMM need to handle this tlb miss as if
1618 * PSCB(vcpu,metaphysical_mode)=0
1619 */
1620 printk("vcpu_translate: bad physical address: 0x%lx "
1621 "at %lx\n", address, vcpu_regs(vcpu)->cr_iip);
1623 } else {
1624 *pteval = (address & _PAGE_PPN_MASK) |
1625 __DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX;
1626 *itir = PAGE_SHIFT << 2;
1627 perfc_incr(phys_translate);
1628 return IA64_NO_FAULT;
1630 } else if (!region && warn_region0_address) {
1631 REGS *regs = vcpu_regs(vcpu);
1632 unsigned long viip = PSCB(vcpu, iip);
1633 unsigned long vipsr = PSCB(vcpu, ipsr);
1634 unsigned long iip = regs->cr_iip;
1635 unsigned long ipsr = regs->cr_ipsr;
1636 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, "
1637 "vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1638 address, viip, vipsr, iip, ipsr);
1641 rr = PSCB(vcpu, rrs)[region];
1642 rid = rr & RR_RID_MASK;
1643 if (is_data) {
1644 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1645 if (trp != NULL) {
1646 *pteval = trp->pte.val;
1647 *itir = trp->itir;
1648 perfc_incr(tr_translate);
1649 return IA64_NO_FAULT;
1652 // FIXME?: check itr's for data accesses too, else bad things happen?
1653 /* else */ {
1654 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1655 if (trp != NULL) {
1656 *pteval = trp->pte.val;
1657 *itir = trp->itir;
1658 perfc_incr(tr_translate);
1659 return IA64_NO_FAULT;
1663 /* check 1-entry TLB */
1664 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1665 trp = &vcpu->arch.dtlb;
1666 pte = trp->pte;
1667 if ( /* is_data && */ pte.p
1668 && vcpu_match_tr_entry_no_p(trp, address, rid)) {
1669 *pteval = pte.val;
1670 *itir = trp->itir;
1671 perfc_incr(dtlb_translate);
1672 return IA64_USE_TLB;
1675 /* check guest VHPT */
1676 pta = PSCB(vcpu, pta);
1677 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1678 panic_domain(vcpu_regs(vcpu), "can't do long format VHPT\n");
1679 //return is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR;
1682 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1683 // note: architecturally, iha is optionally set for alt faults but
1684 // xenlinux depends on it so should document it as part of PV interface
1685 vcpu_thash(vcpu, address, iha);
1686 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE)) {
1687 REGS *regs = vcpu_regs(vcpu);
1688 // NOTE: This is specific code for linux kernel
1689 // We assume region 7 is identity mapped
1690 if (region == 7 && ia64_psr(regs)->cpl == 2) {
1691 pte.val = address & _PAGE_PPN_MASK;
1692 pte.val = pte.val | pgprot_val(PAGE_KERNEL);
1693 goto out;
1695 return is_data ? IA64_ALT_DATA_TLB_VECTOR :
1696 IA64_ALT_INST_TLB_VECTOR;
1699 /* avoid recursively walking (short format) VHPT */
1700 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1701 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1703 if (!__access_ok(*iha)
1704 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1705 // virtual VHPT walker "missed" in TLB
1706 return IA64_VHPT_FAULT;
1708 /*
1709 * Optimisation: this VHPT walker aborts on not-present pages
1710 * instead of inserting a not-present translation, this allows
1711 * vectoring directly to the miss handler.
1712 */
1713 if (!pte.p)
1714 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1716 /* found mapping in guest VHPT! */
1717 out:
1718 *itir = rr & RR_PS_MASK;
1719 *pteval = pte.val;
1720 perfc_incr(vhpt_translate);
1721 return IA64_NO_FAULT;
1724 IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr)
1726 u64 pteval, itir, mask, iha;
1727 IA64FAULT fault;
1729 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1730 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
1731 mask = itir_mask(itir);
1732 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1733 return IA64_NO_FAULT;
1735 return vcpu_force_data_miss(vcpu, vadr);
1738 IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
1740 printk("vcpu_tak: tak instruction unsupported\n");
1741 return IA64_ILLOP_FAULT;
1742 // HACK ALERT: tak does a thash for now
1743 //return vcpu_thash(vcpu,vadr,key);
1746 /**************************************************************************
1747 VCPU debug breakpoint register access routines
1748 **************************************************************************/
1750 IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
1752 // TODO: unimplemented DBRs return a reserved register fault
1753 // TODO: Should set Logical CPU state, not just physical
1754 ia64_set_dbr(reg, val);
1755 return IA64_NO_FAULT;
1758 IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
1760 // TODO: unimplemented IBRs return a reserved register fault
1761 // TODO: Should set Logical CPU state, not just physical
1762 ia64_set_ibr(reg, val);
1763 return IA64_NO_FAULT;
1766 IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
1768 // TODO: unimplemented DBRs return a reserved register fault
1769 u64 val = ia64_get_dbr(reg);
1770 *pval = val;
1771 return IA64_NO_FAULT;
1774 IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
1776 // TODO: unimplemented IBRs return a reserved register fault
1777 u64 val = ia64_get_ibr(reg);
1778 *pval = val;
1779 return IA64_NO_FAULT;
1782 /**************************************************************************
1783 VCPU performance monitor register access routines
1784 **************************************************************************/
1786 IA64FAULT vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val)
1788 // TODO: Should set Logical CPU state, not just physical
1789 // NOTE: Writes to unimplemented PMC registers are discarded
1790 #ifdef DEBUG_PFMON
1791 printk("vcpu_set_pmc(%x,%lx)\n", reg, val);
1792 #endif
1793 ia64_set_pmc(reg, val);
1794 return IA64_NO_FAULT;
1797 IA64FAULT vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val)
1799 // TODO: Should set Logical CPU state, not just physical
1800 // NOTE: Writes to unimplemented PMD registers are discarded
1801 #ifdef DEBUG_PFMON
1802 printk("vcpu_set_pmd(%x,%lx)\n", reg, val);
1803 #endif
1804 ia64_set_pmd(reg, val);
1805 return IA64_NO_FAULT;
1808 IA64FAULT vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval)
1810 // NOTE: Reads from unimplemented PMC registers return zero
1811 u64 val = (u64) ia64_get_pmc(reg);
1812 #ifdef DEBUG_PFMON
1813 printk("%lx=vcpu_get_pmc(%x)\n", val, reg);
1814 #endif
1815 *pval = val;
1816 return IA64_NO_FAULT;
1819 IA64FAULT vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval)
1821 // NOTE: Reads from unimplemented PMD registers return zero
1822 u64 val = (u64) ia64_get_pmd(reg);
1823 #ifdef DEBUG_PFMON
1824 printk("%lx=vcpu_get_pmd(%x)\n", val, reg);
1825 #endif
1826 *pval = val;
1827 return IA64_NO_FAULT;
1830 /**************************************************************************
1831 VCPU banked general register access routines
1832 **************************************************************************/
1833 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1834 do{ \
1835 __asm__ __volatile__ ( \
1836 ";;extr.u %0 = %3,%6,16;;\n" \
1837 "dep %1 = %0, %1, 0, 16;;\n" \
1838 "st8 [%4] = %1\n" \
1839 "extr.u %0 = %2, 16, 16;;\n" \
1840 "dep %3 = %0, %3, %6, 16;;\n" \
1841 "st8 [%5] = %3\n" \
1842 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1843 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1844 }while(0)
1846 IA64FAULT vcpu_bsw0(VCPU * vcpu)
1848 // TODO: Only allowed for current vcpu
1849 REGS *regs = vcpu_regs(vcpu);
1850 unsigned long *r = &regs->r16;
1851 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1852 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1853 unsigned long *runat = &regs->eml_unat;
1854 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1855 unsigned long *b1unat = &PSCB(vcpu, vnat);
1857 unsigned long i;
1859 if (VMX_DOMAIN(vcpu)) {
1860 if (VCPU(vcpu, vpsr) & IA64_PSR_BN) {
1861 for (i = 0; i < 16; i++) {
1862 *b1++ = *r;
1863 *r++ = *b0++;
1865 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1866 IA64_PT_REGS_R16_SLOT);
1867 VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
1869 } else {
1870 if (PSCB(vcpu, banknum)) {
1871 for (i = 0; i < 16; i++) {
1872 *b1++ = *r;
1873 *r++ = *b0++;
1875 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1876 IA64_PT_REGS_R16_SLOT);
1877 PSCB(vcpu, banknum) = 0;
1880 return IA64_NO_FAULT;
1883 #define vcpu_bsw1_unat(i, b0unat, b1unat, runat, IA64_PT_REGS_R16_SLOT) \
1884 do { \
1885 __asm__ __volatile__ (";;extr.u %0 = %3,%6,16;;\n" \
1886 "dep %1 = %0, %1, 16, 16;;\n" \
1887 "st8 [%4] = %1\n" \
1888 "extr.u %0 = %2, 0, 16;;\n" \
1889 "dep %3 = %0, %3, %6, 16;;\n" \
1890 "st8 [%5] = %3\n" \
1891 ::"r"(i), "r"(*b0unat), "r"(*b1unat), \
1892 "r"(*runat), "r"(b0unat), "r"(runat), \
1893 "i"(IA64_PT_REGS_R16_SLOT): "memory"); \
1894 } while(0)
1896 IA64FAULT vcpu_bsw1(VCPU * vcpu)
1898 // TODO: Only allowed for current vcpu
1899 REGS *regs = vcpu_regs(vcpu);
1900 unsigned long *r = &regs->r16;
1901 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1902 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1903 unsigned long *runat = &regs->eml_unat;
1904 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1905 unsigned long *b1unat = &PSCB(vcpu, vnat);
1907 unsigned long i;
1909 if (VMX_DOMAIN(vcpu)) {
1910 if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
1911 for (i = 0; i < 16; i++) {
1912 *b0++ = *r;
1913 *r++ = *b1++;
1915 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1916 IA64_PT_REGS_R16_SLOT);
1917 VCPU(vcpu, vpsr) |= IA64_PSR_BN;
1919 } else {
1920 if (!PSCB(vcpu, banknum)) {
1921 for (i = 0; i < 16; i++) {
1922 *b0++ = *r;
1923 *r++ = *b1++;
1925 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1926 IA64_PT_REGS_R16_SLOT);
1927 PSCB(vcpu, banknum) = 1;
1930 return IA64_NO_FAULT;
1933 /**************************************************************************
1934 VCPU cpuid access routines
1935 **************************************************************************/
1937 IA64FAULT vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval)
1939 // FIXME: This could get called as a result of a rsvd-reg fault
1940 // if reg > 3
1941 switch (reg) {
1942 case 0:
1943 memcpy(pval, "Xen/ia64", 8);
1944 break;
1945 case 1:
1946 *pval = 0;
1947 break;
1948 case 2:
1949 *pval = 0;
1950 break;
1951 case 3:
1952 *pval = ia64_get_cpuid(3);
1953 break;
1954 case 4:
1955 *pval = ia64_get_cpuid(4);
1956 break;
1957 default:
1958 if (reg > (ia64_get_cpuid(3) & 0xff))
1959 return IA64_RSVDREG_FAULT;
1960 *pval = ia64_get_cpuid(reg);
1961 break;
1963 return IA64_NO_FAULT;
1966 /**************************************************************************
1967 VCPU region register access routines
1968 **************************************************************************/
1970 unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
1972 ia64_rr rr;
1974 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
1975 return rr.ve;
1978 IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val)
1980 PSCB(vcpu, rrs)[reg >> 61] = val;
1981 // warning: set_one_rr() does it "live"
1982 set_one_rr(reg, val);
1983 return IA64_NO_FAULT;
1986 IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval)
1988 if (VMX_DOMAIN(vcpu))
1989 *pval = VMX(vcpu, vrr[reg >> 61]);
1990 else
1991 *pval = PSCB(vcpu, rrs)[reg >> 61];
1993 return IA64_NO_FAULT;
1996 /**************************************************************************
1997 VCPU protection key register access routines
1998 **************************************************************************/
2000 IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
2002 #ifndef PKR_USE_FIXED
2003 printk("vcpu_get_pkr: called, not implemented yet\n");
2004 return IA64_ILLOP_FAULT;
2005 #else
2006 u64 val = (u64) ia64_get_pkr(reg);
2007 *pval = val;
2008 return IA64_NO_FAULT;
2009 #endif
2012 IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
2014 #ifndef PKR_USE_FIXED
2015 printk("vcpu_set_pkr: called, not implemented yet\n");
2016 return IA64_ILLOP_FAULT;
2017 #else
2018 // if (reg >= NPKRS)
2019 // return IA64_ILLOP_FAULT;
2020 vcpu->pkrs[reg] = val;
2021 ia64_set_pkr(reg, val);
2022 return IA64_NO_FAULT;
2023 #endif
2026 /**************************************************************************
2027 VCPU translation register access routines
2028 **************************************************************************/
2030 static void
2031 vcpu_set_tr_entry_rid(TR_ENTRY * trp, u64 pte,
2032 u64 itir, u64 ifa, u64 rid)
2034 u64 ps;
2035 union pte_flags new_pte;
2037 trp->itir = itir;
2038 trp->rid = rid;
2039 ps = trp->ps;
2040 new_pte.val = pte;
2041 if (new_pte.pl < 2)
2042 new_pte.pl = 2;
2043 trp->vadr = ifa & ~0xfff;
2044 if (ps > 12) { // "ignore" relevant low-order bits
2045 new_pte.ppn &= ~((1UL << (ps - 12)) - 1);
2046 trp->vadr &= ~((1UL << ps) - 1);
2049 /* Atomic write. */
2050 trp->pte.val = new_pte.val;
2053 static inline void
2054 vcpu_set_tr_entry(TR_ENTRY * trp, u64 pte, u64 itir, u64 ifa)
2056 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
2057 VCPU(current, rrs[ifa >> 61]) & RR_RID_MASK);
2060 IA64FAULT vcpu_itr_d(VCPU * vcpu, u64 slot, u64 pte,
2061 u64 itir, u64 ifa)
2063 TR_ENTRY *trp;
2065 if (slot >= NDTRS)
2066 return IA64_RSVDREG_FAULT;
2068 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2070 trp = &PSCBX(vcpu, dtrs[slot]);
2071 //printk("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
2072 vcpu_set_tr_entry(trp, pte, itir, ifa);
2073 vcpu_quick_region_set(PSCBX(vcpu, dtr_regions), ifa);
2075 /*
2076 * FIXME According to spec, vhpt should be purged, but this
2077 * incurs considerable performance loss, since it is safe for
2078 * linux not to purge vhpt, vhpt purge is disabled until a
2079 * feasible way is found.
2081 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2082 */
2084 return IA64_NO_FAULT;
2087 IA64FAULT vcpu_itr_i(VCPU * vcpu, u64 slot, u64 pte,
2088 u64 itir, u64 ifa)
2090 TR_ENTRY *trp;
2092 if (slot >= NITRS)
2093 return IA64_RSVDREG_FAULT;
2095 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2097 trp = &PSCBX(vcpu, itrs[slot]);
2098 //printk("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
2099 vcpu_set_tr_entry(trp, pte, itir, ifa);
2100 vcpu_quick_region_set(PSCBX(vcpu, itr_regions), ifa);
2102 /*
2103 * FIXME According to spec, vhpt should be purged, but this
2104 * incurs considerable performance loss, since it is safe for
2105 * linux not to purge vhpt, vhpt purge is disabled until a
2106 * feasible way is found.
2108 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2109 */
2111 return IA64_NO_FAULT;
2114 IA64FAULT vcpu_set_itr(VCPU * vcpu, u64 slot, u64 pte,
2115 u64 itir, u64 ifa, u64 rid)
2117 TR_ENTRY *trp;
2119 if (slot >= NITRS)
2120 return IA64_RSVDREG_FAULT;
2121 trp = &PSCBX(vcpu, itrs[slot]);
2122 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2124 /* Recompute the itr_region. */
2125 vcpu->arch.itr_regions = 0;
2126 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
2127 if (trp->pte.p)
2128 vcpu_quick_region_set(vcpu->arch.itr_regions,
2129 trp->vadr);
2130 return IA64_NO_FAULT;
2133 IA64FAULT vcpu_set_dtr(VCPU * vcpu, u64 slot, u64 pte,
2134 u64 itir, u64 ifa, u64 rid)
2136 TR_ENTRY *trp;
2138 if (slot >= NDTRS)
2139 return IA64_RSVDREG_FAULT;
2140 trp = &PSCBX(vcpu, dtrs[slot]);
2141 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2143 /* Recompute the dtr_region. */
2144 vcpu->arch.dtr_regions = 0;
2145 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
2146 if (trp->pte.p)
2147 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2148 trp->vadr);
2149 return IA64_NO_FAULT;
2152 /**************************************************************************
2153 VCPU translation cache access routines
2154 **************************************************************************/
2156 void
2157 vcpu_itc_no_srlz(VCPU * vcpu, u64 IorD, u64 vaddr, u64 pte,
2158 u64 mp_pte, u64 logps, struct p2m_entry *entry)
2160 unsigned long psr;
2161 unsigned long ps = (vcpu->domain == dom0) ? logps : PAGE_SHIFT;
2163 check_xen_space_overlap("itc", vaddr, 1UL << logps);
2165 // FIXME, must be inlined or potential for nested fault here!
2166 if ((vcpu->domain == dom0) && (logps < PAGE_SHIFT))
2167 panic_domain(NULL, "vcpu_itc_no_srlz: domain trying to use "
2168 "smaller page size!\n");
2170 BUG_ON(logps > PAGE_SHIFT);
2171 vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry);
2172 psr = ia64_clear_ic();
2173 pte &= ~(_PAGE_RV2 | _PAGE_RV1); // Mask out the reserved bits.
2174 ia64_itc(IorD, vaddr, pte, ps); // FIXME: look for bigger mappings
2175 ia64_set_psr(psr);
2176 // ia64_srlz_i(); // no srls req'd, will rfi later
2177 #ifdef VHPT_GLOBAL
2178 if (vcpu->domain == dom0 && ((vaddr >> 61) == 7)) {
2179 // FIXME: this is dangerous... vhpt_flush_address ensures these
2180 // addresses never get flushed. More work needed if this
2181 // ever happens.
2182 //printk("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2183 if (logps > PAGE_SHIFT)
2184 vhpt_multiple_insert(vaddr, pte, logps);
2185 else
2186 vhpt_insert(vaddr, pte, logps << 2);
2188 // even if domain pagesize is larger than PAGE_SIZE, just put
2189 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2190 else
2191 vhpt_insert(vaddr, pte, PAGE_SHIFT << 2);
2192 #endif
2195 IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2197 unsigned long pteval, logps = itir_ps(itir);
2198 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2199 struct p2m_entry entry;
2201 if (logps < PAGE_SHIFT)
2202 panic_domain(NULL, "vcpu_itc_d: domain trying to use "
2203 "smaller page size!\n");
2205 again:
2206 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2207 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2208 if (!pteval)
2209 return IA64_ILLOP_FAULT;
2210 if (swap_rr0)
2211 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
2212 vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, logps, &entry);
2213 if (swap_rr0)
2214 set_metaphysical_rr0();
2215 if (p2m_entry_retry(&entry)) {
2216 vcpu_flush_tlb_vhpt_range(ifa, logps);
2217 goto again;
2219 vcpu_set_tr_entry(&PSCBX(vcpu, dtlb), pte, itir, ifa);
2220 return IA64_NO_FAULT;
2223 IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2225 unsigned long pteval, logps = itir_ps(itir);
2226 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2227 struct p2m_entry entry;
2229 if (logps < PAGE_SHIFT)
2230 panic_domain(NULL, "vcpu_itc_i: domain trying to use "
2231 "smaller page size!\n");
2232 again:
2233 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2234 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2235 if (!pteval)
2236 return IA64_ILLOP_FAULT;
2237 if (swap_rr0)
2238 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
2239 vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, logps, &entry);
2240 if (swap_rr0)
2241 set_metaphysical_rr0();
2242 if (p2m_entry_retry(&entry)) {
2243 vcpu_flush_tlb_vhpt_range(ifa, logps);
2244 goto again;
2246 vcpu_set_tr_entry(&PSCBX(vcpu, itlb), pte, itir, ifa);
2247 return IA64_NO_FAULT;
2250 IA64FAULT vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 log_range)
2252 BUG_ON(vcpu != current);
2254 check_xen_space_overlap("ptc_l", vadr, 1UL << log_range);
2256 /* Purge TC */
2257 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2258 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2260 /* Purge all tlb and vhpt */
2261 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2263 return IA64_NO_FAULT;
2266 // At privlvl=0, fc performs no access rights or protection key checks, while
2267 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2268 // read but no protection key check. Thus in order to avoid an unexpected
2269 // access rights fault, we have to translate the virtual address to a
2270 // physical address (possibly via a metaphysical address) and do the fc
2271 // on the physical address, which is guaranteed to flush the same cache line
2272 IA64FAULT vcpu_fc(VCPU * vcpu, u64 vadr)
2274 // TODO: Only allowed for current vcpu
2275 u64 mpaddr, paddr;
2276 IA64FAULT fault;
2278 again:
2279 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2280 if (fault == IA64_NO_FAULT) {
2281 struct p2m_entry entry;
2282 paddr = translate_domain_mpaddr(mpaddr, &entry);
2283 ia64_fc(__va(paddr));
2284 if (p2m_entry_retry(&entry))
2285 goto again;
2287 return fault;
2290 IA64FAULT vcpu_ptc_e(VCPU * vcpu, u64 vadr)
2292 // Note that this only needs to be called once, i.e. the
2293 // architected loop to purge the entire TLB, should use
2294 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2296 vcpu_flush_vtlb_all(current);
2298 return IA64_NO_FAULT;
2301 IA64FAULT vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 addr_range)
2303 printk("vcpu_ptc_g: called, not implemented yet\n");
2304 return IA64_ILLOP_FAULT;
2307 IA64FAULT vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 addr_range)
2309 // FIXME: validate not flushing Xen addresses
2310 // if (Xen address) return(IA64_ILLOP_FAULT);
2311 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2312 //printk("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2314 check_xen_space_overlap("ptc_ga", vadr, addr_range);
2316 domain_flush_vtlb_range(vcpu->domain, vadr, addr_range);
2318 return IA64_NO_FAULT;
2321 IA64FAULT vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 log_range)
2323 unsigned long region = vadr >> 61;
2324 u64 addr_range = 1UL << log_range;
2325 unsigned long rid, rr;
2326 int i;
2327 TR_ENTRY *trp;
2329 BUG_ON(vcpu != current);
2330 check_xen_space_overlap("ptr_d", vadr, 1UL << log_range);
2332 rr = PSCB(vcpu, rrs)[region];
2333 rid = rr & RR_RID_MASK;
2335 /* Purge TC */
2336 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2338 /* Purge tr and recompute dtr_regions. */
2339 vcpu->arch.dtr_regions = 0;
2340 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2341 if (vcpu_match_tr_entry_range
2342 (trp, rid, vadr, vadr + addr_range))
2343 vcpu_purge_tr_entry(trp);
2344 else if (trp->pte.p)
2345 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2346 trp->vadr);
2348 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2350 return IA64_NO_FAULT;
2353 IA64FAULT vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 log_range)
2355 unsigned long region = vadr >> 61;
2356 u64 addr_range = 1UL << log_range;
2357 unsigned long rid, rr;
2358 int i;
2359 TR_ENTRY *trp;
2361 BUG_ON(vcpu != current);
2362 check_xen_space_overlap("ptr_i", vadr, 1UL << log_range);
2364 rr = PSCB(vcpu, rrs)[region];
2365 rid = rr & RR_RID_MASK;
2367 /* Purge TC */
2368 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2370 /* Purge tr and recompute itr_regions. */
2371 vcpu->arch.itr_regions = 0;
2372 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2373 if (vcpu_match_tr_entry_range
2374 (trp, rid, vadr, vadr + addr_range))
2375 vcpu_purge_tr_entry(trp);
2376 else if (trp->pte.p)
2377 vcpu_quick_region_set(vcpu->arch.itr_regions,
2378 trp->vadr);
2380 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2382 return IA64_NO_FAULT;