ia64/xen-unstable

view xen/arch/ia64/xen/vcpu.c @ 14037:9364bea18bc4

[IA64] First step to support big-endian PV domUs

Signed-off-by: Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>
author awilliam@xenbuild2.aw
date Thu Feb 22 09:42:13 2007 -0700 (2007-02-22)
parents 3fa7489f87bb
children ac28d6c41e6f
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 */
176 }
178 v->arch.domain_itm_last = -1L;
179 }
181 /**************************************************************************
182 VCPU privileged application register access routines
183 **************************************************************************/
185 void vcpu_load_kernel_regs(VCPU * vcpu)
186 {
187 ia64_set_kr(0, VCPU(vcpu, krs[0]));
188 ia64_set_kr(1, VCPU(vcpu, krs[1]));
189 ia64_set_kr(2, VCPU(vcpu, krs[2]));
190 ia64_set_kr(3, VCPU(vcpu, krs[3]));
191 ia64_set_kr(4, VCPU(vcpu, krs[4]));
192 ia64_set_kr(5, VCPU(vcpu, krs[5]));
193 ia64_set_kr(6, VCPU(vcpu, krs[6]));
194 ia64_set_kr(7, VCPU(vcpu, krs[7]));
195 }
197 /* GCC 4.0.2 seems not to be able to suppress this call!. */
198 #define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
200 IA64FAULT vcpu_set_ar(VCPU * vcpu, u64 reg, u64 val)
201 {
202 if (reg == 44)
203 return vcpu_set_itc(vcpu, val);
204 else if (reg == 27)
205 return IA64_ILLOP_FAULT;
206 else if (reg == 24)
207 printk("warning: setting ar.eflg is a no-op; no IA-32 "
208 "support\n");
209 else if (reg > 7)
210 return IA64_ILLOP_FAULT;
211 else {
212 PSCB(vcpu, krs[reg]) = val;
213 ia64_set_kr(reg, val);
214 }
215 return IA64_NO_FAULT;
216 }
218 IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 reg, u64 * val)
219 {
220 if (reg == 24)
221 printk("warning: getting ar.eflg is a no-op; no IA-32 "
222 "support\n");
223 else if (reg > 7)
224 return IA64_ILLOP_FAULT;
225 else
226 *val = PSCB(vcpu, krs[reg]);
227 return IA64_NO_FAULT;
228 }
230 /**************************************************************************
231 VCPU processor status register access routines
232 **************************************************************************/
234 void vcpu_set_metaphysical_mode(VCPU * vcpu, BOOLEAN newmode)
235 {
236 /* only do something if mode changes */
237 if (!!newmode ^ !!PSCB(vcpu, metaphysical_mode)) {
238 PSCB(vcpu, metaphysical_mode) = newmode;
239 if (newmode)
240 set_metaphysical_rr0();
241 else if (PSCB(vcpu, rrs[0]) != -1)
242 set_one_rr(0, PSCB(vcpu, rrs[0]));
243 }
244 }
246 IA64FAULT vcpu_reset_psr_dt(VCPU * vcpu)
247 {
248 vcpu_set_metaphysical_mode(vcpu, TRUE);
249 return IA64_NO_FAULT;
250 }
252 IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24)
253 {
254 struct ia64_psr psr, imm, *ipsr;
255 REGS *regs = vcpu_regs(vcpu);
257 //PRIVOP_COUNT_ADDR(regs,_RSM);
258 // TODO: All of these bits need to be virtualized
259 // TODO: Only allowed for current vcpu
260 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
261 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
262 imm = *(struct ia64_psr *)&imm24;
263 // interrupt flag
264 if (imm.i)
265 vcpu->vcpu_info->evtchn_upcall_mask = 1;
266 if (imm.ic)
267 PSCB(vcpu, interrupt_collection_enabled) = 0;
268 // interrupt collection flag
269 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
270 // just handle psr.up and psr.pp for now
271 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
272 IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
273 IA64_PSR_DFL | IA64_PSR_DFH))
274 return IA64_ILLOP_FAULT;
275 if (imm.dfh) {
276 ipsr->dfh = PSCB(vcpu, hpsr_dfh);
277 PSCB(vcpu, vpsr_dfh) = 0;
278 }
279 if (imm.dfl)
280 ipsr->dfl = 0;
281 if (imm.pp) {
282 ipsr->pp = 1;
283 psr.pp = 1; // priv perf ctrs always enabled
284 PSCB(vcpu, vpsr_pp) = 0; // but fool the domain if it gets psr
285 }
286 if (imm.up) {
287 ipsr->up = 0;
288 psr.up = 0;
289 }
290 if (imm.sp) {
291 ipsr->sp = 0;
292 psr.sp = 0;
293 }
294 if (imm.be)
295 ipsr->be = 0;
296 if (imm.dt)
297 vcpu_set_metaphysical_mode(vcpu, TRUE);
298 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
299 return IA64_NO_FAULT;
300 }
302 IA64FAULT vcpu_set_psr_dt(VCPU * vcpu)
303 {
304 vcpu_set_metaphysical_mode(vcpu, FALSE);
305 return IA64_NO_FAULT;
306 }
308 IA64FAULT vcpu_set_psr_i(VCPU * vcpu)
309 {
310 vcpu->vcpu_info->evtchn_upcall_mask = 0;
311 PSCB(vcpu, interrupt_collection_enabled) = 1;
312 return IA64_NO_FAULT;
313 }
315 IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24)
316 {
317 struct ia64_psr psr, imm, *ipsr;
318 REGS *regs = vcpu_regs(vcpu);
319 u64 mask, enabling_interrupts = 0;
321 //PRIVOP_COUNT_ADDR(regs,_SSM);
322 // TODO: All of these bits need to be virtualized
323 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
324 imm = *(struct ia64_psr *)&imm24;
325 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
326 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
327 mask =
328 IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
329 IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE;
330 if (imm24 & ~mask)
331 return IA64_ILLOP_FAULT;
332 if (imm.dfh) {
333 PSCB(vcpu, vpsr_dfh) = 1;
334 ipsr->dfh = 1;
335 }
336 if (imm.dfl)
337 ipsr->dfl = 1;
338 if (imm.pp) {
339 ipsr->pp = 1;
340 psr.pp = 1;
341 PSCB(vcpu, vpsr_pp) = 1;
342 }
343 if (imm.sp) {
344 ipsr->sp = 1;
345 psr.sp = 1;
346 }
347 if (imm.i) {
348 if (vcpu->vcpu_info->evtchn_upcall_mask) {
349 //printk("vcpu_set_psr_sm: psr.ic 0->1\n");
350 enabling_interrupts = 1;
351 }
352 vcpu->vcpu_info->evtchn_upcall_mask = 0;
353 }
354 if (imm.ic)
355 PSCB(vcpu, interrupt_collection_enabled) = 1;
356 // TODO: do this faster
357 if (imm.mfl) {
358 ipsr->mfl = 1;
359 psr.mfl = 1;
360 }
361 if (imm.mfh) {
362 ipsr->mfh = 1;
363 psr.mfh = 1;
364 }
365 if (imm.ac) {
366 ipsr->ac = 1;
367 psr.ac = 1;
368 }
369 if (imm.up) {
370 ipsr->up = 1;
371 psr.up = 1;
372 }
373 if (imm.be)
374 ipsr->be = 1;
375 if (imm.dt)
376 vcpu_set_metaphysical_mode(vcpu, FALSE);
377 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
378 if (enabling_interrupts &&
379 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
380 PSCB(vcpu, pending_interruption) = 1;
381 return IA64_NO_FAULT;
382 }
384 IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val)
385 {
386 struct ia64_psr psr, newpsr, *ipsr;
387 REGS *regs = vcpu_regs(vcpu);
388 u64 enabling_interrupts = 0;
390 // TODO: All of these bits need to be virtualized
391 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
392 newpsr = *(struct ia64_psr *)&val;
393 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
394 // just handle psr.up and psr.pp for now
395 //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP))
396 // return IA64_ILLOP_FAULT;
397 // however trying to set other bits can't be an error as it is in ssm
398 if (newpsr.dfh) {
399 ipsr->dfh = 1;
400 PSCB(vcpu, vpsr_dfh) = 1;
401 } else {
402 ipsr->dfh = PSCB(vcpu, hpsr_dfh);
403 PSCB(vcpu, vpsr_dfh) = 0;
404 }
405 if (newpsr.dfl)
406 ipsr->dfl = 1;
407 if (newpsr.pp) {
408 ipsr->pp = 1;
409 psr.pp = 1;
410 PSCB(vcpu, vpsr_pp) = 1;
411 } else {
412 ipsr->pp = 1;
413 psr.pp = 1;
414 PSCB(vcpu, vpsr_pp) = 0;
415 }
416 if (newpsr.up) {
417 ipsr->up = 1;
418 psr.up = 1;
419 }
420 if (newpsr.sp) {
421 ipsr->sp = 1;
422 psr.sp = 1;
423 }
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 psr.mfl = 1;
434 }
435 if (newpsr.mfh) {
436 ipsr->mfh = 1;
437 psr.mfh = 1;
438 }
439 if (newpsr.ac) {
440 ipsr->ac = 1;
441 psr.ac = 1;
442 }
443 if (newpsr.up) {
444 ipsr->up = 1;
445 psr.up = 1;
446 }
447 if (newpsr.dt && newpsr.rt)
448 vcpu_set_metaphysical_mode(vcpu, FALSE);
449 else
450 vcpu_set_metaphysical_mode(vcpu, TRUE);
451 if (newpsr.be)
452 ipsr->be = 1;
453 if (enabling_interrupts &&
454 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
455 PSCB(vcpu, pending_interruption) = 1;
456 return IA64_NO_FAULT;
457 }
459 IA64FAULT vcpu_get_psr(VCPU * vcpu, u64 * pval)
460 {
461 REGS *regs = vcpu_regs(vcpu);
462 struct ia64_psr newpsr;
464 newpsr = *(struct ia64_psr *)&regs->cr_ipsr;
465 if (!vcpu->vcpu_info->evtchn_upcall_mask)
466 newpsr.i = 1;
467 else
468 newpsr.i = 0;
469 if (PSCB(vcpu, interrupt_collection_enabled))
470 newpsr.ic = 1;
471 else
472 newpsr.ic = 0;
473 if (PSCB(vcpu, metaphysical_mode))
474 newpsr.dt = 0;
475 else
476 newpsr.dt = 1;
477 if (PSCB(vcpu, vpsr_pp))
478 newpsr.pp = 1;
479 else
480 newpsr.pp = 0;
481 newpsr.dfh = PSCB(vcpu, vpsr_dfh);
483 *pval = *(unsigned long *)&newpsr;
484 *pval &= (MASK(0, 32) | MASK(35, 2));
485 return IA64_NO_FAULT;
486 }
488 BOOLEAN vcpu_get_psr_ic(VCPU * vcpu)
489 {
490 return !!PSCB(vcpu, interrupt_collection_enabled);
491 }
493 BOOLEAN vcpu_get_psr_i(VCPU * vcpu)
494 {
495 return !vcpu->vcpu_info->evtchn_upcall_mask;
496 }
498 u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr)
499 {
500 u64 dcr = PSCB(vcpu, dcr);
501 PSR psr;
503 //printk("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr);
504 psr.i64 = prevpsr;
505 psr.ia64_psr.pp = 0;
506 if (dcr & IA64_DCR_PP)
507 psr.ia64_psr.pp = 1;
508 psr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled);
509 psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
510 psr.ia64_psr.bn = PSCB(vcpu, banknum);
511 psr.ia64_psr.dfh = PSCB(vcpu, vpsr_dfh);
512 psr.ia64_psr.dt = 1;
513 psr.ia64_psr.it = 1;
514 psr.ia64_psr.rt = 1;
515 if (psr.ia64_psr.cpl == 2)
516 psr.ia64_psr.cpl = 0; // !!!! fool domain
517 // psr.pk = 1;
518 //printk("returns 0x%016lx...\n",psr.i64);
519 return psr.i64;
520 }
522 /**************************************************************************
523 VCPU control register access routines
524 **************************************************************************/
526 IA64FAULT vcpu_get_dcr(VCPU * vcpu, u64 * pval)
527 {
528 *pval = PSCB(vcpu, dcr);
529 return IA64_NO_FAULT;
530 }
532 IA64FAULT vcpu_get_iva(VCPU * vcpu, u64 * pval)
533 {
534 if (VMX_DOMAIN(vcpu))
535 *pval = PSCB(vcpu, iva) & ~0x7fffL;
536 else
537 *pval = PSCBX(vcpu, iva) & ~0x7fffL;
539 return IA64_NO_FAULT;
540 }
542 IA64FAULT vcpu_get_pta(VCPU * vcpu, u64 * pval)
543 {
544 *pval = PSCB(vcpu, pta);
545 return IA64_NO_FAULT;
546 }
548 IA64FAULT vcpu_get_ipsr(VCPU * vcpu, u64 * pval)
549 {
550 //REGS *regs = vcpu_regs(vcpu);
551 //*pval = regs->cr_ipsr;
552 *pval = PSCB(vcpu, ipsr);
553 return IA64_NO_FAULT;
554 }
556 IA64FAULT vcpu_get_isr(VCPU * vcpu, u64 * pval)
557 {
558 *pval = PSCB(vcpu, isr);
559 return IA64_NO_FAULT;
560 }
562 IA64FAULT vcpu_get_iip(VCPU * vcpu, u64 * pval)
563 {
564 //REGS *regs = vcpu_regs(vcpu);
565 //*pval = regs->cr_iip;
566 *pval = PSCB(vcpu, iip);
567 return IA64_NO_FAULT;
568 }
570 IA64FAULT vcpu_get_ifa(VCPU * vcpu, u64 * pval)
571 {
572 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_get_ifa);
573 *pval = PSCB(vcpu, ifa);
574 return IA64_NO_FAULT;
575 }
577 unsigned long vcpu_get_rr_ps(VCPU * vcpu, u64 vadr)
578 {
579 ia64_rr rr;
581 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
582 return rr.ps;
583 }
585 unsigned long vcpu_get_rr_rid(VCPU * vcpu, u64 vadr)
586 {
587 ia64_rr rr;
589 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
590 return rr.rid;
591 }
593 unsigned long vcpu_get_itir_on_fault(VCPU * vcpu, u64 ifa)
594 {
595 ia64_rr rr;
597 rr.rrval = 0;
598 rr.ps = vcpu_get_rr_ps(vcpu, ifa);
599 rr.rid = vcpu_get_rr_rid(vcpu, ifa);
600 return rr.rrval;
601 }
603 IA64FAULT vcpu_get_itir(VCPU * vcpu, u64 * pval)
604 {
605 u64 val = PSCB(vcpu, itir);
606 *pval = val;
607 return IA64_NO_FAULT;
608 }
610 IA64FAULT vcpu_get_iipa(VCPU * vcpu, u64 * pval)
611 {
612 u64 val = PSCB(vcpu, iipa);
613 // SP entry code does not save iipa yet nor does it get
614 // properly delivered in the pscb
615 // printk("*** vcpu_get_iipa: cr.iipa not fully implemented yet!!\n");
616 *pval = val;
617 return IA64_NO_FAULT;
618 }
620 IA64FAULT vcpu_get_ifs(VCPU * vcpu, u64 * pval)
621 {
622 //PSCB(vcpu,ifs) = PSCB(vcpu)->regs.cr_ifs;
623 //*pval = PSCB(vcpu,regs).cr_ifs;
624 *pval = PSCB(vcpu, ifs);
625 return IA64_NO_FAULT;
626 }
628 IA64FAULT vcpu_get_iim(VCPU * vcpu, u64 * pval)
629 {
630 u64 val = PSCB(vcpu, iim);
631 *pval = val;
632 return IA64_NO_FAULT;
633 }
635 IA64FAULT vcpu_get_iha(VCPU * vcpu, u64 * pval)
636 {
637 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_thash);
638 *pval = PSCB(vcpu, iha);
639 return IA64_NO_FAULT;
640 }
642 IA64FAULT vcpu_set_dcr(VCPU * vcpu, u64 val)
643 {
644 PSCB(vcpu, dcr) = val;
645 return IA64_NO_FAULT;
646 }
648 IA64FAULT vcpu_set_iva(VCPU * vcpu, u64 val)
649 {
650 if (VMX_DOMAIN(vcpu))
651 PSCB(vcpu, iva) = val & ~0x7fffL;
652 else
653 PSCBX(vcpu, iva) = val & ~0x7fffL;
655 return IA64_NO_FAULT;
656 }
658 IA64FAULT vcpu_set_pta(VCPU * vcpu, u64 val)
659 {
660 if (val & IA64_PTA_LFMT) {
661 printk("*** No support for VHPT long format yet!!\n");
662 return IA64_ILLOP_FAULT;
663 }
664 if (val & (0x3f << 9)) /* reserved fields */
665 return IA64_RSVDREG_FAULT;
666 if (val & 2) /* reserved fields */
667 return IA64_RSVDREG_FAULT;
668 PSCB(vcpu, pta) = val;
669 return IA64_NO_FAULT;
670 }
672 IA64FAULT vcpu_set_ipsr(VCPU * vcpu, u64 val)
673 {
674 PSCB(vcpu, ipsr) = val;
675 return IA64_NO_FAULT;
676 }
678 IA64FAULT vcpu_set_isr(VCPU * vcpu, u64 val)
679 {
680 PSCB(vcpu, isr) = val;
681 return IA64_NO_FAULT;
682 }
684 IA64FAULT vcpu_set_iip(VCPU * vcpu, u64 val)
685 {
686 PSCB(vcpu, iip) = val;
687 return IA64_NO_FAULT;
688 }
690 IA64FAULT vcpu_increment_iip(VCPU * vcpu)
691 {
692 REGS *regs = vcpu_regs(vcpu);
693 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
694 if (ipsr->ri == 2) {
695 ipsr->ri = 0;
696 regs->cr_iip += 16;
697 } else
698 ipsr->ri++;
699 return IA64_NO_FAULT;
700 }
702 IA64FAULT vcpu_decrement_iip(VCPU * vcpu)
703 {
704 REGS *regs = vcpu_regs(vcpu);
705 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
707 if (ipsr->ri == 0) {
708 ipsr->ri = 2;
709 regs->cr_iip -= 16;
710 } else
711 ipsr->ri--;
713 return IA64_NO_FAULT;
714 }
716 IA64FAULT vcpu_set_ifa(VCPU * vcpu, u64 val)
717 {
718 PSCB(vcpu, ifa) = val;
719 return IA64_NO_FAULT;
720 }
722 IA64FAULT vcpu_set_itir(VCPU * vcpu, u64 val)
723 {
724 PSCB(vcpu, itir) = val;
725 return IA64_NO_FAULT;
726 }
728 IA64FAULT vcpu_set_iipa(VCPU * vcpu, u64 val)
729 {
730 // SP entry code does not save iipa yet nor does it get
731 // properly delivered in the pscb
732 // printk("*** vcpu_set_iipa: cr.iipa not fully implemented yet!!\n");
733 PSCB(vcpu, iipa) = val;
734 return IA64_NO_FAULT;
735 }
737 IA64FAULT vcpu_set_ifs(VCPU * vcpu, u64 val)
738 {
739 //REGS *regs = vcpu_regs(vcpu);
740 PSCB(vcpu, ifs) = val;
741 return IA64_NO_FAULT;
742 }
744 IA64FAULT vcpu_set_iim(VCPU * vcpu, u64 val)
745 {
746 PSCB(vcpu, iim) = val;
747 return IA64_NO_FAULT;
748 }
750 IA64FAULT vcpu_set_iha(VCPU * vcpu, u64 val)
751 {
752 PSCB(vcpu, iha) = val;
753 return IA64_NO_FAULT;
754 }
756 /**************************************************************************
757 VCPU interrupt control register access routines
758 **************************************************************************/
760 void vcpu_pend_unspecified_interrupt(VCPU * vcpu)
761 {
762 PSCB(vcpu, pending_interruption) = 1;
763 }
765 void vcpu_pend_interrupt(VCPU * vcpu, u64 vector)
766 {
767 if (vector & ~0xff) {
768 printk("vcpu_pend_interrupt: bad vector\n");
769 return;
770 }
772 if (vcpu->arch.event_callback_ip) {
773 printk("Deprecated interface. Move to new event based "
774 "solution\n");
775 return;
776 }
778 if (VMX_DOMAIN(vcpu)) {
779 set_bit(vector, VCPU(vcpu, irr));
780 } else {
781 set_bit(vector, PSCBX(vcpu, irr));
782 PSCB(vcpu, pending_interruption) = 1;
783 }
784 }
786 #define IA64_TPR_MMI 0x10000
787 #define IA64_TPR_MIC 0x000f0
789 /* checks to see if a VCPU has any unmasked pending interrupts
790 * if so, returns the highest, else returns SPURIOUS_VECTOR */
791 /* NOTE: Since this gets called from vcpu_get_ivr() and the
792 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
793 * this routine also ignores pscb.interrupt_delivery_enabled
794 * and this must be checked independently; see vcpu_deliverable interrupts() */
795 u64 vcpu_check_pending_interrupts(VCPU * vcpu)
796 {
797 u64 *p, *r, bits, bitnum, mask, i, vector;
799 if (vcpu->arch.event_callback_ip)
800 return SPURIOUS_VECTOR;
802 /* Always check pending event, since guest may just ack the
803 * event injection without handle. Later guest may throw out
804 * the event itself.
805 */
806 check_start:
807 if (event_pending(vcpu) &&
808 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
809 &PSCBX(vcpu, insvc[0])))
810 vcpu_pend_interrupt(vcpu,
811 vcpu->domain->shared_info->arch.
812 evtchn_vector);
814 p = &PSCBX(vcpu, irr[3]);
815 r = &PSCBX(vcpu, insvc[3]);
816 for (i = 3 ;; p--, r--, i--) {
817 bits = *p;
818 if (bits)
819 break; // got a potential interrupt
820 if (*r) {
821 // nothing in this word which is pending+inservice
822 // but there is one inservice which masks lower
823 return SPURIOUS_VECTOR;
824 }
825 if (i == 0) {
826 // checked all bits... nothing pending+inservice
827 return SPURIOUS_VECTOR;
828 }
829 }
830 // have a pending,deliverable interrupt... see if it is masked
831 bitnum = ia64_fls(bits);
832 //printk("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
833 vector = bitnum + (i * 64);
834 mask = 1L << bitnum;
835 /* sanity check for guest timer interrupt */
836 if (vector == (PSCB(vcpu, itv) & 0xff)) {
837 uint64_t now = ia64_get_itc();
838 if (now < PSCBX(vcpu, domain_itm)) {
839 // printk("Ooops, pending guest timer before its due\n");
840 PSCBX(vcpu, irr[i]) &= ~mask;
841 goto check_start;
842 }
843 }
844 //printk("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
845 if (*r >= mask) {
846 // masked by equal inservice
847 //printk("but masked by equal inservice\n");
848 return SPURIOUS_VECTOR;
849 }
850 if (PSCB(vcpu, tpr) & IA64_TPR_MMI) {
851 // tpr.mmi is set
852 //printk("but masked by tpr.mmi\n");
853 return SPURIOUS_VECTOR;
854 }
855 if (((PSCB(vcpu, tpr) & IA64_TPR_MIC) + 15) >= vector) {
856 //tpr.mic masks class
857 //printk("but masked by tpr.mic\n");
858 return SPURIOUS_VECTOR;
859 }
860 //printk("returned to caller\n");
861 return vector;
862 }
864 u64 vcpu_deliverable_interrupts(VCPU * vcpu)
865 {
866 return (vcpu_get_psr_i(vcpu) &&
867 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
868 }
870 u64 vcpu_deliverable_timer(VCPU * vcpu)
871 {
872 return (vcpu_get_psr_i(vcpu) &&
873 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu, itv));
874 }
876 IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval)
877 {
878 /* Use EID=0, ID=vcpu_id. */
879 *pval = vcpu->vcpu_id << 24;
880 return IA64_NO_FAULT;
881 }
883 IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval)
884 {
885 int i;
886 u64 vector, mask;
888 #define HEARTBEAT_FREQ 16 // period in seconds
889 #ifdef HEARTBEAT_FREQ
890 #define N_DOMS 16 // period in seconds
891 #if 0
892 static long count[N_DOMS] = { 0 };
893 #endif
894 static long nonclockcount[N_DOMS] = { 0 };
895 unsigned domid = vcpu->domain->domain_id;
896 #endif
897 #ifdef IRQ_DEBUG
898 static char firstivr = 1;
899 static char firsttime[256];
900 if (firstivr) {
901 int i;
902 for (i = 0; i < 256; i++)
903 firsttime[i] = 1;
904 firstivr = 0;
905 }
906 #endif
908 vector = vcpu_check_pending_interrupts(vcpu);
909 if (vector == SPURIOUS_VECTOR) {
910 PSCB(vcpu, pending_interruption) = 0;
911 *pval = vector;
912 return IA64_NO_FAULT;
913 }
914 #ifdef HEARTBEAT_FREQ
915 if (domid >= N_DOMS)
916 domid = N_DOMS - 1;
917 #if 0
918 if (vector == (PSCB(vcpu, itv) & 0xff)) {
919 if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) {
920 printk("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
921 domid, count[domid], nonclockcount[domid]);
922 //count[domid] = 0;
923 //dump_runq();
924 }
925 }
926 #endif
927 else
928 nonclockcount[domid]++;
929 #endif
930 // now have an unmasked, pending, deliverable vector!
931 // getting ivr has "side effects"
932 #ifdef IRQ_DEBUG
933 if (firsttime[vector]) {
934 printk("*** First get_ivr on vector=%lu,itc=%lx\n",
935 vector, ia64_get_itc());
936 firsttime[vector] = 0;
937 }
938 #endif
939 /* if delivering a timer interrupt, remember domain_itm, which
940 * needs to be done before clearing irr
941 */
942 if (vector == (PSCB(vcpu, itv) & 0xff)) {
943 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
944 }
946 i = vector >> 6;
947 mask = 1L << (vector & 0x3f);
948 //printk("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
949 PSCBX(vcpu, insvc[i]) |= mask;
950 PSCBX(vcpu, irr[i]) &= ~mask;
951 //PSCB(vcpu,pending_interruption)--;
952 *pval = vector;
953 return IA64_NO_FAULT;
954 }
956 IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval)
957 {
958 *pval = PSCB(vcpu, tpr);
959 return IA64_NO_FAULT;
960 }
962 IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval)
963 {
964 *pval = 0L; // reads of eoi always return 0
965 return IA64_NO_FAULT;
966 }
968 IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval)
969 {
970 *pval = PSCBX(vcpu, irr[0]);
971 return IA64_NO_FAULT;
972 }
974 IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval)
975 {
976 *pval = PSCBX(vcpu, irr[1]);
977 return IA64_NO_FAULT;
978 }
980 IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval)
981 {
982 *pval = PSCBX(vcpu, irr[2]);
983 return IA64_NO_FAULT;
984 }
986 IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval)
987 {
988 *pval = PSCBX(vcpu, irr[3]);
989 return IA64_NO_FAULT;
990 }
992 IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval)
993 {
994 *pval = PSCB(vcpu, itv);
995 return IA64_NO_FAULT;
996 }
998 IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval)
999 {
1000 *pval = PSCB(vcpu, pmv);
1001 return IA64_NO_FAULT;
1004 IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval)
1006 *pval = PSCB(vcpu, cmcv);
1007 return IA64_NO_FAULT;
1010 IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval)
1012 // fix this when setting values other than m-bit is supported
1013 gdprintk(XENLOG_DEBUG,
1014 "vcpu_get_lrr0: Unmasked interrupts unsupported\n");
1015 *pval = (1L << 16);
1016 return IA64_NO_FAULT;
1019 IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval)
1021 // fix this when setting values other than m-bit is supported
1022 gdprintk(XENLOG_DEBUG,
1023 "vcpu_get_lrr1: Unmasked interrupts unsupported\n");
1024 *pval = (1L << 16);
1025 return IA64_NO_FAULT;
1028 IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val)
1030 printk("vcpu_set_lid: Setting cr.lid is unsupported\n");
1031 return IA64_ILLOP_FAULT;
1034 IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val)
1036 if (val & 0xff00)
1037 return IA64_RSVDREG_FAULT;
1038 PSCB(vcpu, tpr) = val;
1039 /* This can unmask interrupts. */
1040 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
1041 PSCB(vcpu, pending_interruption) = 1;
1042 return IA64_NO_FAULT;
1045 IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val)
1047 u64 *p, bits, vec, bitnum;
1048 int i;
1050 p = &PSCBX(vcpu, insvc[3]);
1051 for (i = 3; (i >= 0) && !(bits = *p); i--, p--)
1053 if (i < 0) {
1054 printk("Trying to EOI interrupt when none are in-service.\n");
1055 return IA64_NO_FAULT;
1057 bitnum = ia64_fls(bits);
1058 vec = bitnum + (i * 64);
1059 /* clear the correct bit */
1060 bits &= ~(1L << bitnum);
1061 *p = bits;
1062 /* clearing an eoi bit may unmask another pending interrupt... */
1063 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
1064 // worry about this later... Linux only calls eoi
1065 // with interrupts disabled
1066 printk("Trying to EOI interrupt with interrupts enabled\n");
1068 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
1069 PSCB(vcpu, pending_interruption) = 1;
1070 //printk("YYYYY vcpu_set_eoi: Successful\n");
1071 return IA64_NO_FAULT;
1074 IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val)
1076 if (!(val & (1L << 16))) {
1077 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
1078 return IA64_ILLOP_FAULT;
1080 // no place to save this state but nothing to do anyway
1081 return IA64_NO_FAULT;
1084 IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val)
1086 if (!(val & (1L << 16))) {
1087 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
1088 return IA64_ILLOP_FAULT;
1090 // no place to save this state but nothing to do anyway
1091 return IA64_NO_FAULT;
1094 IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val)
1096 /* Check reserved fields. */
1097 if (val & 0xef00)
1098 return IA64_ILLOP_FAULT;
1099 PSCB(vcpu, itv) = val;
1100 if (val & 0x10000) {
1101 /* Disable itm. */
1102 PSCBX(vcpu, domain_itm) = 0;
1103 } else
1104 vcpu_set_next_timer(vcpu);
1105 return IA64_NO_FAULT;
1108 IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val)
1110 if (val & 0xef00) /* reserved fields */
1111 return IA64_RSVDREG_FAULT;
1112 PSCB(vcpu, pmv) = val;
1113 return IA64_NO_FAULT;
1116 IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val)
1118 if (val & 0xef00) /* reserved fields */
1119 return IA64_RSVDREG_FAULT;
1120 PSCB(vcpu, cmcv) = val;
1121 return IA64_NO_FAULT;
1124 /**************************************************************************
1125 VCPU temporary register access routines
1126 **************************************************************************/
1127 u64 vcpu_get_tmp(VCPU * vcpu, u64 index)
1129 if (index > 7)
1130 return 0;
1131 return PSCB(vcpu, tmp[index]);
1134 void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val)
1136 if (index <= 7)
1137 PSCB(vcpu, tmp[index]) = val;
1140 /**************************************************************************
1141 Interval timer routines
1142 **************************************************************************/
1144 BOOLEAN vcpu_timer_disabled(VCPU * vcpu)
1146 u64 itv = PSCB(vcpu, itv);
1147 return (!itv || !!(itv & 0x10000));
1150 BOOLEAN vcpu_timer_inservice(VCPU * vcpu)
1152 u64 itv = PSCB(vcpu, itv);
1153 return test_bit(itv, PSCBX(vcpu, insvc));
1156 BOOLEAN vcpu_timer_expired(VCPU * vcpu)
1158 unsigned long domain_itm = PSCBX(vcpu, domain_itm);
1159 unsigned long now = ia64_get_itc();
1161 if (!domain_itm)
1162 return FALSE;
1163 if (now < domain_itm)
1164 return FALSE;
1165 if (vcpu_timer_disabled(vcpu))
1166 return FALSE;
1167 return TRUE;
1170 void vcpu_safe_set_itm(unsigned long val)
1172 unsigned long epsilon = 100;
1173 unsigned long flags;
1174 u64 now = ia64_get_itc();
1176 local_irq_save(flags);
1177 while (1) {
1178 //printk("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1179 ia64_set_itm(val);
1180 if (val > (now = ia64_get_itc()))
1181 break;
1182 val = now + epsilon;
1183 epsilon <<= 1;
1185 local_irq_restore(flags);
1188 void vcpu_set_next_timer(VCPU * vcpu)
1190 u64 d = PSCBX(vcpu, domain_itm);
1191 //u64 s = PSCBX(vcpu,xen_itm);
1192 u64 s = local_cpu_data->itm_next;
1193 u64 now = ia64_get_itc();
1195 /* gloss over the wraparound problem for now... we know it exists
1196 * but it doesn't matter right now */
1198 if (is_idle_domain(vcpu->domain)) {
1199 // printk("****** vcpu_set_next_timer called during idle!!\n");
1200 vcpu_safe_set_itm(s);
1201 return;
1203 //s = PSCBX(vcpu,xen_itm);
1204 if (d && (d > now) && (d < s)) {
1205 vcpu_safe_set_itm(d);
1206 //using_domain_as_itm++;
1207 } else {
1208 vcpu_safe_set_itm(s);
1209 //using_xen_as_itm++;
1213 IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val)
1215 //UINT now = ia64_get_itc();
1217 //if (val < now) val = now + 1000;
1218 //printk("*** vcpu_set_itm: called with %lx\n",val);
1219 PSCBX(vcpu, domain_itm) = val;
1220 vcpu_set_next_timer(vcpu);
1221 return IA64_NO_FAULT;
1224 IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val)
1226 #define DISALLOW_SETTING_ITC_FOR_NOW
1227 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1228 static int did_print;
1229 if (!did_print) {
1230 printk("vcpu_set_itc: Setting ar.itc is currently disabled "
1231 "(this message is only displayed once)\n");
1232 did_print = 1;
1234 #else
1235 u64 oldnow = ia64_get_itc();
1236 u64 olditm = PSCBX(vcpu, domain_itm);
1237 unsigned long d = olditm - oldnow;
1238 unsigned long x = local_cpu_data->itm_next - oldnow;
1240 u64 newnow = val, min_delta;
1242 local_irq_disable();
1243 if (olditm) {
1244 printk("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val,
1245 newnow + d);
1246 PSCBX(vcpu, domain_itm) = newnow + d;
1248 local_cpu_data->itm_next = newnow + x;
1249 d = PSCBX(vcpu, domain_itm);
1250 x = local_cpu_data->itm_next;
1252 ia64_set_itc(newnow);
1253 if (d && (d > newnow) && (d < x)) {
1254 vcpu_safe_set_itm(d);
1255 //using_domain_as_itm++;
1256 } else {
1257 vcpu_safe_set_itm(x);
1258 //using_xen_as_itm++;
1260 local_irq_enable();
1261 #endif
1262 return IA64_NO_FAULT;
1265 IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval)
1267 //FIXME: Implement this
1268 printk("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1269 return IA64_NO_FAULT;
1270 //return IA64_ILLOP_FAULT;
1273 IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval)
1275 //TODO: Implement this
1276 printk("vcpu_get_itc: Getting ar.itc is unsupported\n");
1277 return IA64_ILLOP_FAULT;
1280 void vcpu_pend_timer(VCPU * vcpu)
1282 u64 itv = PSCB(vcpu, itv) & 0xff;
1284 if (vcpu_timer_disabled(vcpu))
1285 return;
1286 //if (vcpu_timer_inservice(vcpu)) return;
1287 if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) {
1288 // already delivered an interrupt for this so
1289 // don't deliver another
1290 return;
1292 if (vcpu->arch.event_callback_ip) {
1293 /* A small window may occur when injecting vIRQ while related
1294 * handler has not been registered. Don't fire in such case.
1295 */
1296 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1297 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1298 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1300 } else
1301 vcpu_pend_interrupt(vcpu, itv);
1304 // returns true if ready to deliver a timer interrupt too early
1305 u64 vcpu_timer_pending_early(VCPU * vcpu)
1307 u64 now = ia64_get_itc();
1308 u64 itm = PSCBX(vcpu, domain_itm);
1310 if (vcpu_timer_disabled(vcpu))
1311 return 0;
1312 if (!itm)
1313 return 0;
1314 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1317 /**************************************************************************
1318 Privileged operation emulation routines
1319 **************************************************************************/
1321 static void vcpu_force_tlb_miss(VCPU * vcpu, u64 ifa)
1323 PSCB(vcpu, ifa) = ifa;
1324 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1325 vcpu_thash(current, ifa, &PSCB(current, iha));
1328 IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa)
1330 vcpu_force_tlb_miss(vcpu, ifa);
1331 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_INST_TLB_VECTOR :
1332 IA64_ALT_INST_TLB_VECTOR;
1335 IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa)
1337 vcpu_force_tlb_miss(vcpu, ifa);
1338 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_DATA_TLB_VECTOR :
1339 IA64_ALT_DATA_TLB_VECTOR;
1342 IA64FAULT vcpu_rfi(VCPU * vcpu)
1344 // TODO: Only allowed for current vcpu
1345 PSR psr;
1346 u64 int_enable, ifs;
1347 REGS *regs = vcpu_regs(vcpu);
1349 psr.i64 = PSCB(vcpu, ipsr);
1350 if (psr.ia64_psr.cpl < 3)
1351 psr.ia64_psr.cpl = 2;
1352 int_enable = psr.ia64_psr.i;
1353 if (psr.ia64_psr.dfh) {
1354 PSCB(vcpu, vpsr_dfh) = 1;
1355 } else {
1356 psr.ia64_psr.dfh = PSCB(vcpu, hpsr_dfh);
1357 PSCB(vcpu, vpsr_dfh) = 0;
1359 if (psr.ia64_psr.ic)
1360 PSCB(vcpu, interrupt_collection_enabled) = 1;
1361 if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it)
1362 vcpu_set_metaphysical_mode(vcpu, FALSE);
1363 else
1364 vcpu_set_metaphysical_mode(vcpu, TRUE);
1365 psr.ia64_psr.ic = 1;
1366 psr.ia64_psr.i = 1;
1367 psr.ia64_psr.dt = 1;
1368 psr.ia64_psr.rt = 1;
1369 psr.ia64_psr.it = 1;
1370 psr.ia64_psr.bn = 1;
1371 //psr.pk = 1; // checking pkeys shouldn't be a problem but seems broken
1373 ifs = PSCB(vcpu, ifs);
1374 if (ifs & 0x8000000000000000UL)
1375 regs->cr_ifs = ifs;
1377 regs->cr_ipsr = psr.i64;
1378 regs->cr_iip = PSCB(vcpu, iip);
1379 PSCB(vcpu, interrupt_collection_enabled) = 1;
1380 vcpu_bsw1(vcpu);
1381 vcpu->vcpu_info->evtchn_upcall_mask = !int_enable;
1382 return IA64_NO_FAULT;
1385 IA64FAULT vcpu_cover(VCPU * vcpu)
1387 // TODO: Only allowed for current vcpu
1388 REGS *regs = vcpu_regs(vcpu);
1390 if (!PSCB(vcpu, interrupt_collection_enabled)) {
1391 PSCB(vcpu, ifs) = regs->cr_ifs;
1393 regs->cr_ifs = 0;
1394 return IA64_NO_FAULT;
1397 IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval)
1399 u64 pta = PSCB(vcpu, pta);
1400 u64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1401 u64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT) - 1);
1402 u64 Mask = (1L << pta_sz) - 1;
1403 u64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1404 u64 compMask_60_15 = ~Mask_60_15;
1405 u64 rr_ps = vcpu_get_rr_ps(vcpu, vadr);
1406 u64 VHPT_offset = (vadr >> rr_ps) << 3;
1407 u64 VHPT_addr1 = vadr & 0xe000000000000000L;
1408 u64 VHPT_addr2a =
1409 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1410 u64 VHPT_addr2b =
1411 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1412 u64 VHPT_addr3 = VHPT_offset & 0x7fff;
1413 u64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1414 VHPT_addr3;
1416 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1417 *pval = VHPT_addr;
1418 return IA64_NO_FAULT;
1421 IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr)
1423 printk("vcpu_ttag: ttag instruction unsupported\n");
1424 return IA64_ILLOP_FAULT;
1427 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1429 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1430 static inline int range_overlap(u64 b1, u64 e1, u64 b2, u64 e2)
1432 return (b1 <= e2) && (e1 >= b2);
1435 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1436 Note: LSBs of base inside page_size are ignored. */
1437 static inline void
1438 check_xen_space_overlap(const char *func, u64 base, u64 page_size)
1440 /* Overlaps can occur only in region 7.
1441 (This is an optimization to bypass all the checks). */
1442 if (REGION_NUMBER(base) != 7)
1443 return;
1445 /* Mask LSBs of base. */
1446 base &= ~(page_size - 1);
1448 /* FIXME: ideally an MCA should be generated... */
1449 if (range_overlap(HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
1450 base, base + page_size)
1451 || range_overlap(current->domain->arch.shared_info_va,
1452 current->domain->arch.shared_info_va
1453 + XSI_SIZE + XMAPPEDREGS_SIZE,
1454 base, base + page_size))
1455 panic_domain(NULL, "%s on Xen virtual space (%lx)\n",
1456 func, base);
1459 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1460 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY * trp, u64 ifa,
1461 u64 rid)
1463 return trp->rid == rid
1464 && ifa >= trp->vadr && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1467 static inline int vcpu_match_tr_entry(TR_ENTRY * trp, u64 ifa, u64 rid)
1469 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1472 static inline int
1473 vcpu_match_tr_entry_range(TR_ENTRY * trp, u64 rid, u64 b, u64 e)
1475 return trp->rid == rid
1476 && trp->pte.p
1477 && range_overlap(b, e, trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1481 static TR_ENTRY *vcpu_tr_lookup(VCPU * vcpu, unsigned long va, u64 rid,
1482 BOOLEAN is_data)
1484 unsigned char *regions;
1485 TR_ENTRY *trp;
1486 int tr_max;
1487 int i;
1489 if (is_data) {
1490 // data
1491 regions = &vcpu->arch.dtr_regions;
1492 trp = vcpu->arch.dtrs;
1493 tr_max = sizeof(vcpu->arch.dtrs) / sizeof(vcpu->arch.dtrs[0]);
1494 } else {
1495 // instruction
1496 regions = &vcpu->arch.itr_regions;
1497 trp = vcpu->arch.itrs;
1498 tr_max = sizeof(vcpu->arch.itrs) / sizeof(vcpu->arch.itrs[0]);
1501 if (!vcpu_quick_region_check(*regions, va)) {
1502 return NULL;
1504 for (i = 0; i < tr_max; i++, trp++) {
1505 if (vcpu_match_tr_entry(trp, va, rid)) {
1506 return trp;
1509 return NULL;
1512 // return value
1513 // 0: failure
1514 // 1: success
1515 int
1516 vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
1517 IA64_BUNDLE * bundle)
1519 u64 gpip; // guest pseudo phyiscal ip
1520 unsigned long vaddr;
1521 struct page_info *page;
1523 again:
1524 #if 0
1525 // Currently xen doesn't track psr.it bits.
1526 // it assumes always psr.it = 1.
1527 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1528 gpip = gip;
1529 } else
1530 #endif
1532 unsigned long region = REGION_NUMBER(gip);
1533 unsigned long rr = PSCB(vcpu, rrs)[region];
1534 unsigned long rid = rr & RR_RID_MASK;
1535 BOOLEAN swap_rr0;
1536 TR_ENTRY *trp;
1538 // vcpu->arch.{i, d}tlb are volatile,
1539 // copy its value to the variable, tr, before use.
1540 TR_ENTRY tr;
1542 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1543 if (trp != NULL) {
1544 tr = *trp;
1545 goto found;
1547 // When it failed to get a bundle, itlb miss is reflected.
1548 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1549 tr = PSCBX(vcpu, itlb);
1550 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1551 //dprintk(XENLOG_WARNING,
1552 // "%s gip 0x%lx gpip 0x%lx\n", __func__,
1553 // gip, gpip);
1554 goto found;
1556 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1557 if (trp != NULL) {
1558 tr = *trp;
1559 goto found;
1561 #if 0
1562 tr = PSCBX(vcpu, dtlb);
1563 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1564 goto found;
1566 #endif
1568 // try to access gip with guest virtual address
1569 // This may cause tlb miss. see vcpu_translate(). Be careful!
1570 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1571 if (swap_rr0) {
1572 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
1574 *bundle = __get_domain_bundle(gip);
1575 if (swap_rr0) {
1576 set_metaphysical_rr0();
1578 if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
1579 dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
1580 return 0;
1582 return 1;
1584 found:
1585 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1586 (gip & ((1 << tr.ps) - 1));
1589 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1590 page = virt_to_page(vaddr);
1591 if (get_page(page, vcpu->domain) == 0) {
1592 if (page_get_owner(page) != vcpu->domain) {
1593 // This page might be a page granted by another
1594 // domain.
1595 panic_domain(regs, "domain tries to execute foreign "
1596 "domain page which might be mapped by "
1597 "grant table.\n");
1599 goto again;
1601 *bundle = *((IA64_BUNDLE *) vaddr);
1602 put_page(page);
1603 return 1;
1606 IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
1607 u64 * pteval, u64 * itir, u64 * iha)
1609 unsigned long region = address >> 61;
1610 unsigned long pta, rid, rr;
1611 union pte_flags pte;
1612 TR_ENTRY *trp;
1614 if (PSCB(vcpu, metaphysical_mode) && !(!is_data && region)) {
1615 // dom0 may generate an uncacheable physical address (msb=1)
1616 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1617 // FIXME: This seems to happen even though it shouldn't. Need to track
1618 // this down, but since it has been apparently harmless, just flag it for now
1619 // panic_domain(vcpu_regs(vcpu),
1621 /*
1622 * Guest may execute itc.d and rfi with psr.dt=0
1623 * When VMM try to fetch opcode, tlb miss may happen,
1624 * At this time PSCB(vcpu,metaphysical_mode)=1,
1625 * region=5,VMM need to handle this tlb miss as if
1626 * PSCB(vcpu,metaphysical_mode)=0
1627 */
1628 printk("vcpu_translate: bad physical address: 0x%lx "
1629 "at %lx\n", address, vcpu_regs(vcpu)->cr_iip);
1631 } else {
1632 *pteval = (address & _PAGE_PPN_MASK) |
1633 __DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX;
1634 *itir = PAGE_SHIFT << 2;
1635 perfc_incrc(phys_translate);
1636 return IA64_NO_FAULT;
1638 } else if (!region && warn_region0_address) {
1639 REGS *regs = vcpu_regs(vcpu);
1640 unsigned long viip = PSCB(vcpu, iip);
1641 unsigned long vipsr = PSCB(vcpu, ipsr);
1642 unsigned long iip = regs->cr_iip;
1643 unsigned long ipsr = regs->cr_ipsr;
1644 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, "
1645 "vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1646 address, viip, vipsr, iip, ipsr);
1649 rr = PSCB(vcpu, rrs)[region];
1650 rid = rr & RR_RID_MASK;
1651 if (is_data) {
1652 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1653 if (trp != NULL) {
1654 *pteval = trp->pte.val;
1655 *itir = trp->itir;
1656 perfc_incrc(tr_translate);
1657 return IA64_NO_FAULT;
1660 // FIXME?: check itr's for data accesses too, else bad things happen?
1661 /* else */ {
1662 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1663 if (trp != NULL) {
1664 *pteval = trp->pte.val;
1665 *itir = trp->itir;
1666 perfc_incrc(tr_translate);
1667 return IA64_NO_FAULT;
1671 /* check 1-entry TLB */
1672 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1673 trp = &vcpu->arch.dtlb;
1674 pte = trp->pte;
1675 if ( /* is_data && */ pte.p
1676 && vcpu_match_tr_entry_no_p(trp, address, rid)) {
1677 *pteval = pte.val;
1678 *itir = trp->itir;
1679 perfc_incrc(dtlb_translate);
1680 return IA64_USE_TLB;
1683 /* check guest VHPT */
1684 pta = PSCB(vcpu, pta);
1685 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1686 panic_domain(vcpu_regs(vcpu), "can't do long format VHPT\n");
1687 //return is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR;
1690 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1691 // note: architecturally, iha is optionally set for alt faults but
1692 // xenlinux depends on it so should document it as part of PV interface
1693 vcpu_thash(vcpu, address, iha);
1694 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE)) {
1695 REGS *regs = vcpu_regs(vcpu);
1696 // NOTE: This is specific code for linux kernel
1697 // We assume region 7 is identity mapped
1698 if (region == 7 && ia64_psr(regs)->cpl == 2) {
1699 pte.val = address & _PAGE_PPN_MASK;
1700 pte.val = pte.val | pgprot_val(PAGE_KERNEL);
1701 goto out;
1703 return is_data ? IA64_ALT_DATA_TLB_VECTOR :
1704 IA64_ALT_INST_TLB_VECTOR;
1707 /* avoid recursively walking (short format) VHPT */
1708 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1709 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1711 if (!__access_ok(*iha)
1712 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1713 // virtual VHPT walker "missed" in TLB
1714 return IA64_VHPT_FAULT;
1716 /*
1717 * Optimisation: this VHPT walker aborts on not-present pages
1718 * instead of inserting a not-present translation, this allows
1719 * vectoring directly to the miss handler.
1720 */
1721 if (!pte.p)
1722 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1724 /* found mapping in guest VHPT! */
1725 out:
1726 *itir = rr & RR_PS_MASK;
1727 *pteval = pte.val;
1728 perfc_incrc(vhpt_translate);
1729 return IA64_NO_FAULT;
1732 IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr)
1734 u64 pteval, itir, mask, iha;
1735 IA64FAULT fault;
1737 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1738 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
1739 mask = itir_mask(itir);
1740 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1741 return IA64_NO_FAULT;
1743 return vcpu_force_data_miss(vcpu, vadr);
1746 IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
1748 printk("vcpu_tak: tak instruction unsupported\n");
1749 return IA64_ILLOP_FAULT;
1750 // HACK ALERT: tak does a thash for now
1751 //return vcpu_thash(vcpu,vadr,key);
1754 /**************************************************************************
1755 VCPU debug breakpoint register access routines
1756 **************************************************************************/
1758 IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
1760 // TODO: unimplemented DBRs return a reserved register fault
1761 // TODO: Should set Logical CPU state, not just physical
1762 ia64_set_dbr(reg, val);
1763 return IA64_NO_FAULT;
1766 IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
1768 // TODO: unimplemented IBRs return a reserved register fault
1769 // TODO: Should set Logical CPU state, not just physical
1770 ia64_set_ibr(reg, val);
1771 return IA64_NO_FAULT;
1774 IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
1776 // TODO: unimplemented DBRs return a reserved register fault
1777 u64 val = ia64_get_dbr(reg);
1778 *pval = val;
1779 return IA64_NO_FAULT;
1782 IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
1784 // TODO: unimplemented IBRs return a reserved register fault
1785 u64 val = ia64_get_ibr(reg);
1786 *pval = val;
1787 return IA64_NO_FAULT;
1790 /**************************************************************************
1791 VCPU performance monitor register access routines
1792 **************************************************************************/
1794 IA64FAULT vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val)
1796 // TODO: Should set Logical CPU state, not just physical
1797 // NOTE: Writes to unimplemented PMC registers are discarded
1798 #ifdef DEBUG_PFMON
1799 printk("vcpu_set_pmc(%x,%lx)\n", reg, val);
1800 #endif
1801 ia64_set_pmc(reg, val);
1802 return IA64_NO_FAULT;
1805 IA64FAULT vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val)
1807 // TODO: Should set Logical CPU state, not just physical
1808 // NOTE: Writes to unimplemented PMD registers are discarded
1809 #ifdef DEBUG_PFMON
1810 printk("vcpu_set_pmd(%x,%lx)\n", reg, val);
1811 #endif
1812 ia64_set_pmd(reg, val);
1813 return IA64_NO_FAULT;
1816 IA64FAULT vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval)
1818 // NOTE: Reads from unimplemented PMC registers return zero
1819 u64 val = (u64) ia64_get_pmc(reg);
1820 #ifdef DEBUG_PFMON
1821 printk("%lx=vcpu_get_pmc(%x)\n", val, reg);
1822 #endif
1823 *pval = val;
1824 return IA64_NO_FAULT;
1827 IA64FAULT vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval)
1829 // NOTE: Reads from unimplemented PMD registers return zero
1830 u64 val = (u64) ia64_get_pmd(reg);
1831 #ifdef DEBUG_PFMON
1832 printk("%lx=vcpu_get_pmd(%x)\n", val, reg);
1833 #endif
1834 *pval = val;
1835 return IA64_NO_FAULT;
1838 /**************************************************************************
1839 VCPU banked general register access routines
1840 **************************************************************************/
1841 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1842 do{ \
1843 __asm__ __volatile__ ( \
1844 ";;extr.u %0 = %3,%6,16;;\n" \
1845 "dep %1 = %0, %1, 0, 16;;\n" \
1846 "st8 [%4] = %1\n" \
1847 "extr.u %0 = %2, 16, 16;;\n" \
1848 "dep %3 = %0, %3, %6, 16;;\n" \
1849 "st8 [%5] = %3\n" \
1850 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1851 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1852 }while(0)
1854 IA64FAULT vcpu_bsw0(VCPU * vcpu)
1856 // TODO: Only allowed for current vcpu
1857 REGS *regs = vcpu_regs(vcpu);
1858 unsigned long *r = &regs->r16;
1859 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1860 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1861 unsigned long *runat = &regs->eml_unat;
1862 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1863 unsigned long *b1unat = &PSCB(vcpu, vnat);
1865 unsigned long i;
1867 if (VMX_DOMAIN(vcpu)) {
1868 if (VCPU(vcpu, vpsr) & IA64_PSR_BN) {
1869 for (i = 0; i < 16; i++) {
1870 *b1++ = *r;
1871 *r++ = *b0++;
1873 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1874 IA64_PT_REGS_R16_SLOT);
1875 VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
1877 } else {
1878 if (PSCB(vcpu, banknum)) {
1879 for (i = 0; i < 16; i++) {
1880 *b1++ = *r;
1881 *r++ = *b0++;
1883 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1884 IA64_PT_REGS_R16_SLOT);
1885 PSCB(vcpu, banknum) = 0;
1888 return IA64_NO_FAULT;
1891 #define vcpu_bsw1_unat(i, b0unat, b1unat, runat, IA64_PT_REGS_R16_SLOT) \
1892 do { \
1893 __asm__ __volatile__ (";;extr.u %0 = %3,%6,16;;\n" \
1894 "dep %1 = %0, %1, 16, 16;;\n" \
1895 "st8 [%4] = %1\n" \
1896 "extr.u %0 = %2, 0, 16;;\n" \
1897 "dep %3 = %0, %3, %6, 16;;\n" \
1898 "st8 [%5] = %3\n" \
1899 ::"r"(i), "r"(*b0unat), "r"(*b1unat), \
1900 "r"(*runat), "r"(b0unat), "r"(runat), \
1901 "i"(IA64_PT_REGS_R16_SLOT): "memory"); \
1902 } while(0)
1904 IA64FAULT vcpu_bsw1(VCPU * vcpu)
1906 // TODO: Only allowed for current vcpu
1907 REGS *regs = vcpu_regs(vcpu);
1908 unsigned long *r = &regs->r16;
1909 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1910 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1911 unsigned long *runat = &regs->eml_unat;
1912 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1913 unsigned long *b1unat = &PSCB(vcpu, vnat);
1915 unsigned long i;
1917 if (VMX_DOMAIN(vcpu)) {
1918 if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
1919 for (i = 0; i < 16; i++) {
1920 *b0++ = *r;
1921 *r++ = *b1++;
1923 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1924 IA64_PT_REGS_R16_SLOT);
1925 VCPU(vcpu, vpsr) |= IA64_PSR_BN;
1927 } else {
1928 if (!PSCB(vcpu, banknum)) {
1929 for (i = 0; i < 16; i++) {
1930 *b0++ = *r;
1931 *r++ = *b1++;
1933 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1934 IA64_PT_REGS_R16_SLOT);
1935 PSCB(vcpu, banknum) = 1;
1938 return IA64_NO_FAULT;
1941 /**************************************************************************
1942 VCPU cpuid access routines
1943 **************************************************************************/
1945 IA64FAULT vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval)
1947 // FIXME: This could get called as a result of a rsvd-reg fault
1948 // if reg > 3
1949 switch (reg) {
1950 case 0:
1951 memcpy(pval, "Xen/ia64", 8);
1952 break;
1953 case 1:
1954 *pval = 0;
1955 break;
1956 case 2:
1957 *pval = 0;
1958 break;
1959 case 3:
1960 *pval = ia64_get_cpuid(3);
1961 break;
1962 case 4:
1963 *pval = ia64_get_cpuid(4);
1964 break;
1965 default:
1966 if (reg > (ia64_get_cpuid(3) & 0xff))
1967 return IA64_RSVDREG_FAULT;
1968 *pval = ia64_get_cpuid(reg);
1969 break;
1971 return IA64_NO_FAULT;
1974 /**************************************************************************
1975 VCPU region register access routines
1976 **************************************************************************/
1978 unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
1980 ia64_rr rr;
1982 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
1983 return rr.ve;
1986 IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val)
1988 PSCB(vcpu, rrs)[reg >> 61] = val;
1989 // warning: set_one_rr() does it "live"
1990 set_one_rr(reg, val);
1991 return IA64_NO_FAULT;
1994 IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval)
1996 if (VMX_DOMAIN(vcpu))
1997 *pval = VMX(vcpu, vrr[reg >> 61]);
1998 else
1999 *pval = PSCB(vcpu, rrs)[reg >> 61];
2001 return IA64_NO_FAULT;
2004 /**************************************************************************
2005 VCPU protection key register access routines
2006 **************************************************************************/
2008 IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
2010 #ifndef PKR_USE_FIXED
2011 printk("vcpu_get_pkr: called, not implemented yet\n");
2012 return IA64_ILLOP_FAULT;
2013 #else
2014 u64 val = (u64) ia64_get_pkr(reg);
2015 *pval = val;
2016 return IA64_NO_FAULT;
2017 #endif
2020 IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
2022 #ifndef PKR_USE_FIXED
2023 printk("vcpu_set_pkr: called, not implemented yet\n");
2024 return IA64_ILLOP_FAULT;
2025 #else
2026 // if (reg >= NPKRS)
2027 // return IA64_ILLOP_FAULT;
2028 vcpu->pkrs[reg] = val;
2029 ia64_set_pkr(reg, val);
2030 return IA64_NO_FAULT;
2031 #endif
2034 /**************************************************************************
2035 VCPU translation register access routines
2036 **************************************************************************/
2038 static void
2039 vcpu_set_tr_entry_rid(TR_ENTRY * trp, u64 pte,
2040 u64 itir, u64 ifa, u64 rid)
2042 u64 ps;
2043 union pte_flags new_pte;
2045 trp->itir = itir;
2046 trp->rid = rid;
2047 ps = trp->ps;
2048 new_pte.val = pte;
2049 if (new_pte.pl < 2)
2050 new_pte.pl = 2;
2051 trp->vadr = ifa & ~0xfff;
2052 if (ps > 12) { // "ignore" relevant low-order bits
2053 new_pte.ppn &= ~((1UL << (ps - 12)) - 1);
2054 trp->vadr &= ~((1UL << ps) - 1);
2057 /* Atomic write. */
2058 trp->pte.val = new_pte.val;
2061 static inline void
2062 vcpu_set_tr_entry(TR_ENTRY * trp, u64 pte, u64 itir, u64 ifa)
2064 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
2065 VCPU(current, rrs[ifa >> 61]) & RR_RID_MASK);
2068 IA64FAULT vcpu_itr_d(VCPU * vcpu, u64 slot, u64 pte,
2069 u64 itir, u64 ifa)
2071 TR_ENTRY *trp;
2073 if (slot >= NDTRS)
2074 return IA64_RSVDREG_FAULT;
2076 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2078 trp = &PSCBX(vcpu, dtrs[slot]);
2079 //printk("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
2080 vcpu_set_tr_entry(trp, pte, itir, ifa);
2081 vcpu_quick_region_set(PSCBX(vcpu, dtr_regions), ifa);
2083 /*
2084 * FIXME According to spec, vhpt should be purged, but this
2085 * incurs considerable performance loss, since it is safe for
2086 * linux not to purge vhpt, vhpt purge is disabled until a
2087 * feasible way is found.
2089 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2090 */
2092 return IA64_NO_FAULT;
2095 IA64FAULT vcpu_itr_i(VCPU * vcpu, u64 slot, u64 pte,
2096 u64 itir, u64 ifa)
2098 TR_ENTRY *trp;
2100 if (slot >= NITRS)
2101 return IA64_RSVDREG_FAULT;
2103 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2105 trp = &PSCBX(vcpu, itrs[slot]);
2106 //printk("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
2107 vcpu_set_tr_entry(trp, pte, itir, ifa);
2108 vcpu_quick_region_set(PSCBX(vcpu, itr_regions), ifa);
2110 /*
2111 * FIXME According to spec, vhpt should be purged, but this
2112 * incurs considerable performance loss, since it is safe for
2113 * linux not to purge vhpt, vhpt purge is disabled until a
2114 * feasible way is found.
2116 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2117 */
2119 return IA64_NO_FAULT;
2122 IA64FAULT vcpu_set_itr(VCPU * vcpu, u64 slot, u64 pte,
2123 u64 itir, u64 ifa, u64 rid)
2125 TR_ENTRY *trp;
2127 if (slot >= NITRS)
2128 return IA64_RSVDREG_FAULT;
2129 trp = &PSCBX(vcpu, itrs[slot]);
2130 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2132 /* Recompute the itr_region. */
2133 vcpu->arch.itr_regions = 0;
2134 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
2135 if (trp->pte.p)
2136 vcpu_quick_region_set(vcpu->arch.itr_regions,
2137 trp->vadr);
2138 return IA64_NO_FAULT;
2141 IA64FAULT vcpu_set_dtr(VCPU * vcpu, u64 slot, u64 pte,
2142 u64 itir, u64 ifa, u64 rid)
2144 TR_ENTRY *trp;
2146 if (slot >= NDTRS)
2147 return IA64_RSVDREG_FAULT;
2148 trp = &PSCBX(vcpu, dtrs[slot]);
2149 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2151 /* Recompute the dtr_region. */
2152 vcpu->arch.dtr_regions = 0;
2153 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
2154 if (trp->pte.p)
2155 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2156 trp->vadr);
2157 return IA64_NO_FAULT;
2160 /**************************************************************************
2161 VCPU translation cache access routines
2162 **************************************************************************/
2164 void
2165 vcpu_itc_no_srlz(VCPU * vcpu, u64 IorD, u64 vaddr, u64 pte,
2166 u64 mp_pte, u64 logps, struct p2m_entry *entry)
2168 unsigned long psr;
2169 unsigned long ps = (vcpu->domain == dom0) ? logps : PAGE_SHIFT;
2171 check_xen_space_overlap("itc", vaddr, 1UL << logps);
2173 // FIXME, must be inlined or potential for nested fault here!
2174 if ((vcpu->domain == dom0) && (logps < PAGE_SHIFT))
2175 panic_domain(NULL, "vcpu_itc_no_srlz: domain trying to use "
2176 "smaller page size!\n");
2178 BUG_ON(logps > PAGE_SHIFT);
2179 vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry);
2180 psr = ia64_clear_ic();
2181 pte &= ~(_PAGE_RV2 | _PAGE_RV1); // Mask out the reserved bits.
2182 ia64_itc(IorD, vaddr, pte, ps); // FIXME: look for bigger mappings
2183 ia64_set_psr(psr);
2184 // ia64_srlz_i(); // no srls req'd, will rfi later
2185 #ifdef VHPT_GLOBAL
2186 if (vcpu->domain == dom0 && ((vaddr >> 61) == 7)) {
2187 // FIXME: this is dangerous... vhpt_flush_address ensures these
2188 // addresses never get flushed. More work needed if this
2189 // ever happens.
2190 //printk("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2191 if (logps > PAGE_SHIFT)
2192 vhpt_multiple_insert(vaddr, pte, logps);
2193 else
2194 vhpt_insert(vaddr, pte, logps << 2);
2196 // even if domain pagesize is larger than PAGE_SIZE, just put
2197 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2198 else
2199 vhpt_insert(vaddr, pte, PAGE_SHIFT << 2);
2200 #endif
2203 IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2205 unsigned long pteval, logps = itir_ps(itir);
2206 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2207 struct p2m_entry entry;
2209 if (logps < PAGE_SHIFT)
2210 panic_domain(NULL, "vcpu_itc_d: domain trying to use "
2211 "smaller page size!\n");
2213 again:
2214 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2215 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2216 if (!pteval)
2217 return IA64_ILLOP_FAULT;
2218 if (swap_rr0)
2219 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
2220 vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, logps, &entry);
2221 if (swap_rr0)
2222 set_metaphysical_rr0();
2223 if (p2m_entry_retry(&entry)) {
2224 vcpu_flush_tlb_vhpt_range(ifa, logps);
2225 goto again;
2227 vcpu_set_tr_entry(&PSCBX(vcpu, dtlb), pte, itir, ifa);
2228 return IA64_NO_FAULT;
2231 IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2233 unsigned long pteval, logps = itir_ps(itir);
2234 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2235 struct p2m_entry entry;
2237 if (logps < PAGE_SHIFT)
2238 panic_domain(NULL, "vcpu_itc_i: domain trying to use "
2239 "smaller page size!\n");
2240 again:
2241 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2242 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2243 if (!pteval)
2244 return IA64_ILLOP_FAULT;
2245 if (swap_rr0)
2246 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
2247 vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, logps, &entry);
2248 if (swap_rr0)
2249 set_metaphysical_rr0();
2250 if (p2m_entry_retry(&entry)) {
2251 vcpu_flush_tlb_vhpt_range(ifa, logps);
2252 goto again;
2254 vcpu_set_tr_entry(&PSCBX(vcpu, itlb), pte, itir, ifa);
2255 return IA64_NO_FAULT;
2258 IA64FAULT vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 log_range)
2260 BUG_ON(vcpu != current);
2262 check_xen_space_overlap("ptc_l", vadr, 1UL << log_range);
2264 /* Purge TC */
2265 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2266 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2268 /* Purge all tlb and vhpt */
2269 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2271 return IA64_NO_FAULT;
2274 // At privlvl=0, fc performs no access rights or protection key checks, while
2275 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2276 // read but no protection key check. Thus in order to avoid an unexpected
2277 // access rights fault, we have to translate the virtual address to a
2278 // physical address (possibly via a metaphysical address) and do the fc
2279 // on the physical address, which is guaranteed to flush the same cache line
2280 IA64FAULT vcpu_fc(VCPU * vcpu, u64 vadr)
2282 // TODO: Only allowed for current vcpu
2283 u64 mpaddr, paddr;
2284 IA64FAULT fault;
2286 again:
2287 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2288 if (fault == IA64_NO_FAULT) {
2289 struct p2m_entry entry;
2290 paddr = translate_domain_mpaddr(mpaddr, &entry);
2291 ia64_fc(__va(paddr));
2292 if (p2m_entry_retry(&entry))
2293 goto again;
2295 return fault;
2298 IA64FAULT vcpu_ptc_e(VCPU * vcpu, u64 vadr)
2300 // Note that this only needs to be called once, i.e. the
2301 // architected loop to purge the entire TLB, should use
2302 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2304 vcpu_flush_vtlb_all(current);
2306 return IA64_NO_FAULT;
2309 IA64FAULT vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 addr_range)
2311 printk("vcpu_ptc_g: called, not implemented yet\n");
2312 return IA64_ILLOP_FAULT;
2315 IA64FAULT vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 addr_range)
2317 // FIXME: validate not flushing Xen addresses
2318 // if (Xen address) return(IA64_ILLOP_FAULT);
2319 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2320 //printk("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2322 check_xen_space_overlap("ptc_ga", vadr, addr_range);
2324 domain_flush_vtlb_range(vcpu->domain, vadr, addr_range);
2326 return IA64_NO_FAULT;
2329 IA64FAULT vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 log_range)
2331 unsigned long region = vadr >> 61;
2332 u64 addr_range = 1UL << log_range;
2333 unsigned long rid, rr;
2334 int i;
2335 TR_ENTRY *trp;
2337 BUG_ON(vcpu != current);
2338 check_xen_space_overlap("ptr_d", vadr, 1UL << log_range);
2340 rr = PSCB(vcpu, rrs)[region];
2341 rid = rr & RR_RID_MASK;
2343 /* Purge TC */
2344 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2346 /* Purge tr and recompute dtr_regions. */
2347 vcpu->arch.dtr_regions = 0;
2348 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2349 if (vcpu_match_tr_entry_range
2350 (trp, rid, vadr, vadr + addr_range))
2351 vcpu_purge_tr_entry(trp);
2352 else if (trp->pte.p)
2353 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2354 trp->vadr);
2356 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2358 return IA64_NO_FAULT;
2361 IA64FAULT vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 log_range)
2363 unsigned long region = vadr >> 61;
2364 u64 addr_range = 1UL << log_range;
2365 unsigned long rid, rr;
2366 int i;
2367 TR_ENTRY *trp;
2369 BUG_ON(vcpu != current);
2370 check_xen_space_overlap("ptr_i", vadr, 1UL << log_range);
2372 rr = PSCB(vcpu, rrs)[region];
2373 rid = rr & RR_RID_MASK;
2375 /* Purge TC */
2376 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2378 /* Purge tr and recompute itr_regions. */
2379 vcpu->arch.itr_regions = 0;
2380 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2381 if (vcpu_match_tr_entry_range
2382 (trp, rid, vadr, vadr + addr_range))
2383 vcpu_purge_tr_entry(trp);
2384 else if (trp->pte.p)
2385 vcpu_quick_region_set(vcpu->arch.itr_regions,
2386 trp->vadr);
2388 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2390 return IA64_NO_FAULT;