ia64/xen-unstable

view xen/arch/ia64/xen/vcpu.c @ 15660:32825349924d

[IA64] Clean up unused pkrs[] handling.

Signed-off-by: Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>
author Alex Williamson <alex.williamson@hp.com>
date Mon Jul 30 16:01:05 2007 -0600 (2007-07-30)
parents 87b0b6a08dbd
children 85c2f2d754ef
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 #define IA64_PSR_NON_VIRT_BITS \
56 (IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | \
57 IA64_PSR_MFL| IA64_PSR_MFH| IA64_PSR_PK | \
58 IA64_PSR_DFL| IA64_PSR_SP | IA64_PSR_DB | \
59 IA64_PSR_LP | IA64_PSR_TB | IA64_PSR_ID | \
60 IA64_PSR_DA | IA64_PSR_DD | IA64_PSR_SS | \
61 IA64_PSR_RI | IA64_PSR_ED | IA64_PSR_IA)
63 unsigned long vcpu_verbose = 0;
65 /**************************************************************************
66 VCPU general register access routines
67 **************************************************************************/
68 #ifdef XEN
69 u64 vcpu_get_gr(VCPU * vcpu, unsigned long reg)
70 {
71 REGS *regs = vcpu_regs(vcpu);
72 u64 val;
74 if (!reg)
75 return 0;
76 getreg(reg, &val, 0, regs); // FIXME: handle NATs later
77 return val;
78 }
80 IA64FAULT vcpu_get_gr_nat(VCPU * vcpu, unsigned long reg, u64 * val)
81 {
82 REGS *regs = vcpu_regs(vcpu);
83 int nat;
85 getreg(reg, val, &nat, regs); // FIXME: handle NATs later
86 if (nat)
87 return IA64_NAT_CONSUMPTION_VECTOR;
88 return 0;
89 }
91 // returns:
92 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
93 // IA64_NO_FAULT otherwise
94 IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value, int nat)
95 {
96 REGS *regs = vcpu_regs(vcpu);
97 long sof = (regs->cr_ifs) & 0x7f;
99 if (!reg)
100 return IA64_ILLOP_FAULT;
101 if (reg >= sof + 32)
102 return IA64_ILLOP_FAULT;
103 setreg(reg, value, nat, regs); // FIXME: handle NATs later
104 return IA64_NO_FAULT;
105 }
107 IA64FAULT
108 vcpu_get_fpreg(VCPU * vcpu, unsigned long reg, struct ia64_fpreg * val)
109 {
110 REGS *regs = vcpu_regs(vcpu);
111 getfpreg(reg, val, regs); // FIXME: handle NATs later
112 return IA64_NO_FAULT;
113 }
115 IA64FAULT
116 vcpu_set_fpreg(VCPU * vcpu, unsigned long reg, struct ia64_fpreg * val)
117 {
118 REGS *regs = vcpu_regs(vcpu);
119 if (reg > 1)
120 setfpreg(reg, val, regs); // FIXME: handle NATs later
121 return IA64_NO_FAULT;
122 }
124 #else
125 // returns:
126 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
127 // IA64_NO_FAULT otherwise
128 IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value)
129 {
130 REGS *regs = vcpu_regs(vcpu);
131 long sof = (regs->cr_ifs) & 0x7f;
133 if (!reg)
134 return IA64_ILLOP_FAULT;
135 if (reg >= sof + 32)
136 return IA64_ILLOP_FAULT;
137 setreg(reg, value, 0, regs); // FIXME: handle NATs later
138 return IA64_NO_FAULT;
139 }
141 #endif
143 void vcpu_init_regs(struct vcpu *v)
144 {
145 struct pt_regs *regs;
147 regs = vcpu_regs(v);
148 if (VMX_DOMAIN(v)) {
149 /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
150 /* Need to be expanded as macro */
151 regs->cr_ipsr = 0x501008826008;
152 /* lazy fp */
153 FP_PSR(v) = IA64_PSR_DFH;
154 regs->cr_ipsr |= IA64_PSR_DFH;
155 } else {
156 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
157 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
158 regs->cr_ipsr &= ~(IA64_PSR_BITS_TO_CLEAR
159 | IA64_PSR_RI | IA64_PSR_IS);
160 // domain runs at PL2
161 regs->cr_ipsr = vcpu_pl_adjust(regs->cr_ipsr,IA64_PSR_CPL0_BIT);
162 // lazy fp
163 PSCB(v, hpsr_dfh) = 1;
164 PSCB(v, hpsr_mfh) = 0;
165 regs->cr_ipsr |= IA64_PSR_DFH;
166 }
167 regs->cr_ifs = 1UL << 63; /* or clear? */
168 regs->ar_fpsr = FPSR_DEFAULT;
170 if (VMX_DOMAIN(v)) {
171 vmx_init_all_rr(v);
172 /* Virtual processor context setup */
173 VCPU(v, vpsr) = IA64_PSR_BN;
174 VCPU(v, dcr) = 0;
175 } else {
176 init_all_rr(v);
177 regs->ar_rsc = vcpu_pl_adjust(regs->ar_rsc, 2);
178 VCPU(v, banknum) = 1;
179 VCPU(v, metaphysical_mode) = 1;
180 VCPU(v, interrupt_mask_addr) =
181 (unsigned char *)v->domain->arch.shared_info_va +
182 INT_ENABLE_OFFSET(v);
183 VCPU(v, itv) = (1 << 16); /* timer vector masked */
185 v->vcpu_info->evtchn_upcall_pending = 0;
186 v->vcpu_info->evtchn_upcall_mask = -1;
187 }
189 /* pta.size must not be 0. The minimum is 15 (32k) */
190 VCPU(v, pta) = 15 << 2;
192 v->arch.domain_itm_last = -1L;
193 }
195 /**************************************************************************
196 VCPU privileged application register access routines
197 **************************************************************************/
199 void vcpu_load_kernel_regs(VCPU * vcpu)
200 {
201 ia64_set_kr(0, VCPU(vcpu, krs[0]));
202 ia64_set_kr(1, VCPU(vcpu, krs[1]));
203 ia64_set_kr(2, VCPU(vcpu, krs[2]));
204 ia64_set_kr(3, VCPU(vcpu, krs[3]));
205 ia64_set_kr(4, VCPU(vcpu, krs[4]));
206 ia64_set_kr(5, VCPU(vcpu, krs[5]));
207 ia64_set_kr(6, VCPU(vcpu, krs[6]));
208 ia64_set_kr(7, VCPU(vcpu, krs[7]));
209 }
211 /* GCC 4.0.2 seems not to be able to suppress this call!. */
212 #define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
214 IA64FAULT vcpu_set_ar(VCPU * vcpu, u64 reg, u64 val)
215 {
216 if (reg == 44)
217 return vcpu_set_itc(vcpu, val);
218 else if (reg == 27)
219 return IA64_ILLOP_FAULT;
220 else if (reg == 24)
221 printk("warning: setting ar.eflg is a no-op; no IA-32 "
222 "support\n");
223 else if (reg > 7)
224 return IA64_ILLOP_FAULT;
225 else {
226 PSCB(vcpu, krs[reg]) = val;
227 ia64_set_kr(reg, val);
228 }
229 return IA64_NO_FAULT;
230 }
232 IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 reg, u64 * val)
233 {
234 if (reg == 24)
235 printk("warning: getting ar.eflg is a no-op; no IA-32 "
236 "support\n");
237 else if (reg > 7)
238 return IA64_ILLOP_FAULT;
239 else
240 *val = PSCB(vcpu, krs[reg]);
241 return IA64_NO_FAULT;
242 }
244 /**************************************************************************
245 VCPU processor status register access routines
246 **************************************************************************/
248 void vcpu_set_metaphysical_mode(VCPU * vcpu, BOOLEAN newmode)
249 {
250 /* only do something if mode changes */
251 if (!!newmode ^ !!PSCB(vcpu, metaphysical_mode)) {
252 PSCB(vcpu, metaphysical_mode) = newmode;
253 if (newmode)
254 set_metaphysical_rr0();
255 else if (PSCB(vcpu, rrs[0]) != -1)
256 set_one_rr(0, PSCB(vcpu, rrs[0]));
257 }
258 }
260 IA64FAULT vcpu_reset_psr_dt(VCPU * vcpu)
261 {
262 vcpu_set_metaphysical_mode(vcpu, TRUE);
263 return IA64_NO_FAULT;
264 }
266 IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24)
267 {
268 struct ia64_psr psr, imm, *ipsr;
269 REGS *regs = vcpu_regs(vcpu);
271 //PRIVOP_COUNT_ADDR(regs,_RSM);
272 // TODO: All of these bits need to be virtualized
273 // TODO: Only allowed for current vcpu
274 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
275 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
276 imm = *(struct ia64_psr *)&imm24;
277 // interrupt flag
278 if (imm.i)
279 vcpu->vcpu_info->evtchn_upcall_mask = 1;
280 if (imm.ic)
281 PSCB(vcpu, interrupt_collection_enabled) = 0;
282 // interrupt collection flag
283 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
284 // just handle psr.up and psr.pp for now
285 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
286 IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
287 IA64_PSR_DFL | IA64_PSR_DFH))
288 return IA64_ILLOP_FAULT;
289 if (imm.dfh) {
290 ipsr->dfh = PSCB(vcpu, hpsr_dfh);
291 PSCB(vcpu, vpsr_dfh) = 0;
292 }
293 if (imm.dfl)
294 ipsr->dfl = 0;
295 if (imm.pp) {
296 ipsr->pp = 1;
297 psr.pp = 1; // priv perf ctrs always enabled
298 PSCB(vcpu, vpsr_pp) = 0; // but fool the domain if it gets psr
299 }
300 if (imm.up) {
301 ipsr->up = 0;
302 psr.up = 0;
303 }
304 if (imm.sp) {
305 ipsr->sp = 0;
306 psr.sp = 0;
307 }
308 if (imm.be)
309 ipsr->be = 0;
310 if (imm.dt)
311 vcpu_set_metaphysical_mode(vcpu, TRUE);
312 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
313 return IA64_NO_FAULT;
314 }
316 IA64FAULT vcpu_set_psr_dt(VCPU * vcpu)
317 {
318 vcpu_set_metaphysical_mode(vcpu, FALSE);
319 return IA64_NO_FAULT;
320 }
322 IA64FAULT vcpu_set_psr_i(VCPU * vcpu)
323 {
324 vcpu->vcpu_info->evtchn_upcall_mask = 0;
325 PSCB(vcpu, interrupt_collection_enabled) = 1;
326 return IA64_NO_FAULT;
327 }
329 IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24)
330 {
331 struct ia64_psr psr, imm, *ipsr;
332 REGS *regs = vcpu_regs(vcpu);
333 u64 mask, enabling_interrupts = 0;
335 //PRIVOP_COUNT_ADDR(regs,_SSM);
336 // TODO: All of these bits need to be virtualized
337 __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
338 imm = *(struct ia64_psr *)&imm24;
339 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
340 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
341 mask =
342 IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
343 IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH | IA64_PSR_BE;
344 if (imm24 & ~mask)
345 return IA64_ILLOP_FAULT;
346 if (imm.dfh) {
347 PSCB(vcpu, vpsr_dfh) = 1;
348 ipsr->dfh = 1;
349 }
350 if (imm.dfl)
351 ipsr->dfl = 1;
352 if (imm.pp) {
353 ipsr->pp = 1;
354 psr.pp = 1;
355 PSCB(vcpu, vpsr_pp) = 1;
356 }
357 if (imm.sp) {
358 ipsr->sp = 1;
359 psr.sp = 1;
360 }
361 if (imm.i) {
362 if (vcpu->vcpu_info->evtchn_upcall_mask) {
363 //printk("vcpu_set_psr_sm: psr.ic 0->1\n");
364 enabling_interrupts = 1;
365 }
366 vcpu->vcpu_info->evtchn_upcall_mask = 0;
367 }
368 if (imm.ic)
369 PSCB(vcpu, interrupt_collection_enabled) = 1;
370 // TODO: do this faster
371 if (imm.mfl) {
372 ipsr->mfl = 1;
373 psr.mfl = 1;
374 }
375 if (imm.mfh) {
376 ipsr->mfh = 1;
377 psr.mfh = 1;
378 }
379 if (imm.ac) {
380 ipsr->ac = 1;
381 psr.ac = 1;
382 }
383 if (imm.up) {
384 ipsr->up = 1;
385 psr.up = 1;
386 }
387 if (imm.be)
388 ipsr->be = 1;
389 if (imm.dt)
390 vcpu_set_metaphysical_mode(vcpu, FALSE);
391 __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
392 if (enabling_interrupts &&
393 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
394 PSCB(vcpu, pending_interruption) = 1;
395 return IA64_NO_FAULT;
396 }
398 IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val)
399 {
400 struct ia64_psr newpsr, *ipsr;
401 REGS *regs = vcpu_regs(vcpu);
402 u64 enabling_interrupts = 0;
404 newpsr = *(struct ia64_psr *)&val;
405 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
406 // just handle psr.up and psr.pp for now
407 //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP))
408 // return IA64_ILLOP_FAULT;
409 // however trying to set other bits can't be an error as it is in ssm
410 if (newpsr.dfh) {
411 ipsr->dfh = 1;
412 PSCB(vcpu, vpsr_dfh) = 1;
413 } else {
414 ipsr->dfh = PSCB(vcpu, hpsr_dfh);
415 PSCB(vcpu, vpsr_dfh) = 0;
416 }
417 if (newpsr.dfl)
418 ipsr->dfl = 1;
419 if (newpsr.pp) {
420 ipsr->pp = 1;
421 PSCB(vcpu, vpsr_pp) = 1;
422 } else {
423 ipsr->pp = 1;
424 PSCB(vcpu, vpsr_pp) = 0;
425 }
426 if (newpsr.up)
427 ipsr->up = 1;
428 if (newpsr.sp)
429 ipsr->sp = 1;
430 if (newpsr.i) {
431 if (vcpu->vcpu_info->evtchn_upcall_mask)
432 enabling_interrupts = 1;
433 vcpu->vcpu_info->evtchn_upcall_mask = 0;
434 }
435 if (newpsr.ic)
436 PSCB(vcpu, interrupt_collection_enabled) = 1;
437 if (newpsr.mfl)
438 ipsr->mfl = 1;
439 if (newpsr.mfh)
440 ipsr->mfh = 1;
441 if (newpsr.ac)
442 ipsr->ac = 1;
443 if (newpsr.up)
444 ipsr->up = 1;
445 if (newpsr.dt && newpsr.rt)
446 vcpu_set_metaphysical_mode(vcpu, FALSE);
447 else
448 vcpu_set_metaphysical_mode(vcpu, TRUE);
449 if (newpsr.be)
450 ipsr->be = 1;
451 if (enabling_interrupts &&
452 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
453 PSCB(vcpu, pending_interruption) = 1;
454 return IA64_NO_FAULT;
455 }
457 IA64FAULT vcpu_set_psr(VCPU * vcpu, u64 val)
458 {
459 IA64_PSR newpsr, vpsr;
460 REGS *regs = vcpu_regs(vcpu);
461 u64 enabling_interrupts = 0;
463 /* Copy non-virtualized bits. */
464 newpsr.val = val & IA64_PSR_NON_VIRT_BITS;
466 /* Bits forced to 1 (psr.si, psr.is and psr.mc are forced to 0) */
467 newpsr.val |= IA64_PSR_DI;
469 newpsr.val |= IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT |
470 IA64_PSR_IT | IA64_PSR_BN | IA64_PSR_DI | IA64_PSR_PP;
472 vpsr.val = val;
474 if (val & IA64_PSR_DFH) {
475 newpsr.dfh = 1;
476 PSCB(vcpu, vpsr_dfh) = 1;
477 } else {
478 newpsr.dfh = PSCB(vcpu, hpsr_dfh);
479 PSCB(vcpu, vpsr_dfh) = 0;
480 }
482 PSCB(vcpu, vpsr_pp) = vpsr.pp;
484 if (vpsr.i) {
485 if (vcpu->vcpu_info->evtchn_upcall_mask)
486 enabling_interrupts = 1;
488 vcpu->vcpu_info->evtchn_upcall_mask = 0;
490 if (enabling_interrupts &&
491 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
492 PSCB(vcpu, pending_interruption) = 1;
493 } else
494 vcpu->vcpu_info->evtchn_upcall_mask = 1;
496 PSCB(vcpu, interrupt_collection_enabled) = vpsr.ic;
497 vcpu_set_metaphysical_mode(vcpu, !(vpsr.dt && vpsr.rt && vpsr.it));
499 newpsr.cpl |= max_t(u64, vpsr.cpl, CONFIG_CPL0_EMUL);
501 if (PSCB(vcpu, banknum) != vpsr.bn) {
502 if (vpsr.bn)
503 vcpu_bsw1(vcpu);
504 else
505 vcpu_bsw0(vcpu);
506 }
508 regs->cr_ipsr = newpsr.val;
510 return IA64_NO_FAULT;
511 }
513 u64 vcpu_get_psr(VCPU * vcpu)
514 {
515 REGS *regs = vcpu_regs(vcpu);
516 PSR newpsr;
517 PSR ipsr;
519 ipsr.i64 = regs->cr_ipsr;
521 /* Copy non-virtualized bits. */
522 newpsr.i64 = ipsr.i64 & IA64_PSR_NON_VIRT_BITS;
524 /* Bits forced to 1 (psr.si and psr.is are forced to 0) */
525 newpsr.i64 |= IA64_PSR_DI;
527 /* System mask. */
528 newpsr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled);
529 newpsr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
531 if (!PSCB(vcpu, metaphysical_mode))
532 newpsr.i64 |= IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_IT;
534 newpsr.ia64_psr.dfh = PSCB(vcpu, vpsr_dfh);
535 newpsr.ia64_psr.pp = PSCB(vcpu, vpsr_pp);
537 /* Fool cpl. */
538 if (ipsr.ia64_psr.cpl <= CONFIG_CPL0_EMUL)
539 newpsr.ia64_psr.cpl = 0;
540 else
541 newpsr.ia64_psr.cpl = ipsr.ia64_psr.cpl;
543 newpsr.ia64_psr.bn = PSCB(vcpu, banknum);
545 return newpsr.i64;
546 }
548 IA64FAULT vcpu_get_psr_masked(VCPU * vcpu, u64 * pval)
549 {
550 u64 psr = vcpu_get_psr(vcpu);
551 *pval = psr & (MASK(0, 32) | MASK(35, 2));
552 return IA64_NO_FAULT;
553 }
555 BOOLEAN vcpu_get_psr_ic(VCPU * vcpu)
556 {
557 return !!PSCB(vcpu, interrupt_collection_enabled);
558 }
560 BOOLEAN vcpu_get_psr_i(VCPU * vcpu)
561 {
562 return !vcpu->vcpu_info->evtchn_upcall_mask;
563 }
565 /**************************************************************************
566 VCPU control register access routines
567 **************************************************************************/
569 IA64FAULT vcpu_get_dcr(VCPU * vcpu, u64 * pval)
570 {
571 *pval = PSCB(vcpu, dcr);
572 return IA64_NO_FAULT;
573 }
575 IA64FAULT vcpu_get_iva(VCPU * vcpu, u64 * pval)
576 {
577 if (VMX_DOMAIN(vcpu))
578 *pval = PSCB(vcpu, iva) & ~0x7fffL;
579 else
580 *pval = PSCBX(vcpu, iva) & ~0x7fffL;
582 return IA64_NO_FAULT;
583 }
585 IA64FAULT vcpu_get_pta(VCPU * vcpu, u64 * pval)
586 {
587 *pval = PSCB(vcpu, pta);
588 return IA64_NO_FAULT;
589 }
591 IA64FAULT vcpu_get_ipsr(VCPU * vcpu, u64 * pval)
592 {
593 //REGS *regs = vcpu_regs(vcpu);
594 //*pval = regs->cr_ipsr;
595 *pval = PSCB(vcpu, ipsr);
596 return IA64_NO_FAULT;
597 }
599 IA64FAULT vcpu_get_isr(VCPU * vcpu, u64 * pval)
600 {
601 *pval = PSCB(vcpu, isr);
602 return IA64_NO_FAULT;
603 }
605 IA64FAULT vcpu_get_iip(VCPU * vcpu, u64 * pval)
606 {
607 //REGS *regs = vcpu_regs(vcpu);
608 //*pval = regs->cr_iip;
609 *pval = PSCB(vcpu, iip);
610 return IA64_NO_FAULT;
611 }
613 IA64FAULT vcpu_get_ifa(VCPU * vcpu, u64 * pval)
614 {
615 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_get_ifa);
616 *pval = PSCB(vcpu, ifa);
617 return IA64_NO_FAULT;
618 }
620 unsigned long vcpu_get_rr_ps(VCPU * vcpu, u64 vadr)
621 {
622 ia64_rr rr;
624 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
625 return rr.ps;
626 }
628 unsigned long vcpu_get_rr_rid(VCPU * vcpu, u64 vadr)
629 {
630 ia64_rr rr;
632 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
633 return rr.rid;
634 }
636 unsigned long vcpu_get_itir_on_fault(VCPU * vcpu, u64 ifa)
637 {
638 ia64_rr rr;
640 rr.rrval = 0;
641 rr.ps = vcpu_get_rr_ps(vcpu, ifa);
642 rr.rid = vcpu_get_rr_rid(vcpu, ifa);
643 return rr.rrval;
644 }
646 IA64FAULT vcpu_get_itir(VCPU * vcpu, u64 * pval)
647 {
648 u64 val = PSCB(vcpu, itir);
649 *pval = val;
650 return IA64_NO_FAULT;
651 }
653 IA64FAULT vcpu_get_iipa(VCPU * vcpu, u64 * pval)
654 {
655 u64 val = PSCB(vcpu, iipa);
656 // SP entry code does not save iipa yet nor does it get
657 // properly delivered in the pscb
658 // printk("*** vcpu_get_iipa: cr.iipa not fully implemented yet!!\n");
659 *pval = val;
660 return IA64_NO_FAULT;
661 }
663 IA64FAULT vcpu_get_ifs(VCPU * vcpu, u64 * pval)
664 {
665 //PSCB(vcpu,ifs) = PSCB(vcpu)->regs.cr_ifs;
666 //*pval = PSCB(vcpu,regs).cr_ifs;
667 *pval = PSCB(vcpu, ifs);
668 return IA64_NO_FAULT;
669 }
671 IA64FAULT vcpu_get_iim(VCPU * vcpu, u64 * pval)
672 {
673 u64 val = PSCB(vcpu, iim);
674 *pval = val;
675 return IA64_NO_FAULT;
676 }
678 IA64FAULT vcpu_get_iha(VCPU * vcpu, u64 * pval)
679 {
680 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_thash);
681 *pval = PSCB(vcpu, iha);
682 return IA64_NO_FAULT;
683 }
685 IA64FAULT vcpu_set_dcr(VCPU * vcpu, u64 val)
686 {
687 PSCB(vcpu, dcr) = val;
688 return IA64_NO_FAULT;
689 }
691 IA64FAULT vcpu_set_iva(VCPU * vcpu, u64 val)
692 {
693 if (VMX_DOMAIN(vcpu))
694 PSCB(vcpu, iva) = val & ~0x7fffL;
695 else
696 PSCBX(vcpu, iva) = val & ~0x7fffL;
698 return IA64_NO_FAULT;
699 }
701 IA64FAULT vcpu_set_pta(VCPU * vcpu, u64 val)
702 {
703 if (val & IA64_PTA_LFMT) {
704 printk("*** No support for VHPT long format yet!!\n");
705 return IA64_ILLOP_FAULT;
706 }
707 if (val & (0x3f << 9)) /* reserved fields */
708 return IA64_RSVDREG_FAULT;
709 if (val & 2) /* reserved fields */
710 return IA64_RSVDREG_FAULT;
711 PSCB(vcpu, pta) = val;
712 return IA64_NO_FAULT;
713 }
715 IA64FAULT vcpu_set_ipsr(VCPU * vcpu, u64 val)
716 {
717 PSCB(vcpu, ipsr) = val;
718 return IA64_NO_FAULT;
719 }
721 IA64FAULT vcpu_set_isr(VCPU * vcpu, u64 val)
722 {
723 PSCB(vcpu, isr) = val;
724 return IA64_NO_FAULT;
725 }
727 IA64FAULT vcpu_set_iip(VCPU * vcpu, u64 val)
728 {
729 PSCB(vcpu, iip) = val;
730 return IA64_NO_FAULT;
731 }
733 IA64FAULT vcpu_increment_iip(VCPU * vcpu)
734 {
735 REGS *regs = vcpu_regs(vcpu);
736 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
737 if (ipsr->ri == 2) {
738 ipsr->ri = 0;
739 regs->cr_iip += 16;
740 } else
741 ipsr->ri++;
742 return IA64_NO_FAULT;
743 }
745 IA64FAULT vcpu_decrement_iip(VCPU * vcpu)
746 {
747 REGS *regs = vcpu_regs(vcpu);
748 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
750 if (ipsr->ri == 0) {
751 ipsr->ri = 2;
752 regs->cr_iip -= 16;
753 } else
754 ipsr->ri--;
756 return IA64_NO_FAULT;
757 }
759 IA64FAULT vcpu_set_ifa(VCPU * vcpu, u64 val)
760 {
761 PSCB(vcpu, ifa) = val;
762 return IA64_NO_FAULT;
763 }
765 IA64FAULT vcpu_set_itir(VCPU * vcpu, u64 val)
766 {
767 PSCB(vcpu, itir) = val;
768 return IA64_NO_FAULT;
769 }
771 IA64FAULT vcpu_set_iipa(VCPU * vcpu, u64 val)
772 {
773 // SP entry code does not save iipa yet nor does it get
774 // properly delivered in the pscb
775 // printk("*** vcpu_set_iipa: cr.iipa not fully implemented yet!!\n");
776 PSCB(vcpu, iipa) = val;
777 return IA64_NO_FAULT;
778 }
780 IA64FAULT vcpu_set_ifs(VCPU * vcpu, u64 val)
781 {
782 //REGS *regs = vcpu_regs(vcpu);
783 PSCB(vcpu, ifs) = val;
784 return IA64_NO_FAULT;
785 }
787 IA64FAULT vcpu_set_iim(VCPU * vcpu, u64 val)
788 {
789 PSCB(vcpu, iim) = val;
790 return IA64_NO_FAULT;
791 }
793 IA64FAULT vcpu_set_iha(VCPU * vcpu, u64 val)
794 {
795 PSCB(vcpu, iha) = val;
796 return IA64_NO_FAULT;
797 }
799 /**************************************************************************
800 VCPU interrupt control register access routines
801 **************************************************************************/
803 void vcpu_pend_unspecified_interrupt(VCPU * vcpu)
804 {
805 PSCB(vcpu, pending_interruption) = 1;
806 }
808 void vcpu_pend_interrupt(VCPU * vcpu, u64 vector)
809 {
810 if (vector & ~0xff) {
811 printk("vcpu_pend_interrupt: bad vector\n");
812 return;
813 }
815 if (vcpu->arch.event_callback_ip) {
816 printk("Deprecated interface. Move to new event based "
817 "solution\n");
818 return;
819 }
821 if (VMX_DOMAIN(vcpu)) {
822 set_bit(vector, VCPU(vcpu, irr));
823 } else {
824 set_bit(vector, PSCBX(vcpu, irr));
825 PSCB(vcpu, pending_interruption) = 1;
826 }
827 }
829 #define IA64_TPR_MMI 0x10000
830 #define IA64_TPR_MIC 0x000f0
832 /* checks to see if a VCPU has any unmasked pending interrupts
833 * if so, returns the highest, else returns SPURIOUS_VECTOR */
834 /* NOTE: Since this gets called from vcpu_get_ivr() and the
835 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
836 * this routine also ignores pscb.interrupt_delivery_enabled
837 * and this must be checked independently; see vcpu_deliverable interrupts() */
838 u64 vcpu_check_pending_interrupts(VCPU * vcpu)
839 {
840 u64 *p, *r, bits, bitnum, mask, i, vector;
842 if (vcpu->arch.event_callback_ip)
843 return SPURIOUS_VECTOR;
845 /* Always check pending event, since guest may just ack the
846 * event injection without handle. Later guest may throw out
847 * the event itself.
848 */
849 check_start:
850 if (event_pending(vcpu) &&
851 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
852 &PSCBX(vcpu, insvc[0])))
853 vcpu_pend_interrupt(vcpu,
854 vcpu->domain->shared_info->arch.
855 evtchn_vector);
857 p = &PSCBX(vcpu, irr[3]);
858 r = &PSCBX(vcpu, insvc[3]);
859 for (i = 3 ;; p--, r--, i--) {
860 bits = *p;
861 if (bits)
862 break; // got a potential interrupt
863 if (*r) {
864 // nothing in this word which is pending+inservice
865 // but there is one inservice which masks lower
866 return SPURIOUS_VECTOR;
867 }
868 if (i == 0) {
869 // checked all bits... nothing pending+inservice
870 return SPURIOUS_VECTOR;
871 }
872 }
873 // have a pending,deliverable interrupt... see if it is masked
874 bitnum = ia64_fls(bits);
875 //printk("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
876 vector = bitnum + (i * 64);
877 mask = 1L << bitnum;
878 /* sanity check for guest timer interrupt */
879 if (vector == (PSCB(vcpu, itv) & 0xff)) {
880 uint64_t now = ia64_get_itc();
881 if (now < PSCBX(vcpu, domain_itm)) {
882 // printk("Ooops, pending guest timer before its due\n");
883 PSCBX(vcpu, irr[i]) &= ~mask;
884 goto check_start;
885 }
886 }
887 //printk("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
888 if (*r >= mask) {
889 // masked by equal inservice
890 //printk("but masked by equal inservice\n");
891 return SPURIOUS_VECTOR;
892 }
893 if (PSCB(vcpu, tpr) & IA64_TPR_MMI) {
894 // tpr.mmi is set
895 //printk("but masked by tpr.mmi\n");
896 return SPURIOUS_VECTOR;
897 }
898 if (((PSCB(vcpu, tpr) & IA64_TPR_MIC) + 15) >= vector) {
899 //tpr.mic masks class
900 //printk("but masked by tpr.mic\n");
901 return SPURIOUS_VECTOR;
902 }
903 //printk("returned to caller\n");
904 return vector;
905 }
907 u64 vcpu_deliverable_interrupts(VCPU * vcpu)
908 {
909 return (vcpu_get_psr_i(vcpu) &&
910 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
911 }
913 u64 vcpu_deliverable_timer(VCPU * vcpu)
914 {
915 return (vcpu_get_psr_i(vcpu) &&
916 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu, itv));
917 }
919 IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval)
920 {
921 /* Use EID=0, ID=vcpu_id. */
922 *pval = vcpu->vcpu_id << 24;
923 return IA64_NO_FAULT;
924 }
926 IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval)
927 {
928 int i;
929 u64 vector, mask;
931 #define HEARTBEAT_FREQ 16 // period in seconds
932 #ifdef HEARTBEAT_FREQ
933 #define N_DOMS 16 // period in seconds
934 #if 0
935 static long count[N_DOMS] = { 0 };
936 #endif
937 static long nonclockcount[N_DOMS] = { 0 };
938 unsigned domid = vcpu->domain->domain_id;
939 #endif
940 #ifdef IRQ_DEBUG
941 static char firstivr = 1;
942 static char firsttime[256];
943 if (firstivr) {
944 int i;
945 for (i = 0; i < 256; i++)
946 firsttime[i] = 1;
947 firstivr = 0;
948 }
949 #endif
951 vector = vcpu_check_pending_interrupts(vcpu);
952 if (vector == SPURIOUS_VECTOR) {
953 PSCB(vcpu, pending_interruption) = 0;
954 *pval = vector;
955 return IA64_NO_FAULT;
956 }
957 #ifdef HEARTBEAT_FREQ
958 if (domid >= N_DOMS)
959 domid = N_DOMS - 1;
960 #if 0
961 if (vector == (PSCB(vcpu, itv) & 0xff)) {
962 if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) {
963 printk("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
964 domid, count[domid], nonclockcount[domid]);
965 //count[domid] = 0;
966 //dump_runq();
967 }
968 }
969 #endif
970 else
971 nonclockcount[domid]++;
972 #endif
973 // now have an unmasked, pending, deliverable vector!
974 // getting ivr has "side effects"
975 #ifdef IRQ_DEBUG
976 if (firsttime[vector]) {
977 printk("*** First get_ivr on vector=%lu,itc=%lx\n",
978 vector, ia64_get_itc());
979 firsttime[vector] = 0;
980 }
981 #endif
982 /* if delivering a timer interrupt, remember domain_itm, which
983 * needs to be done before clearing irr
984 */
985 if (vector == (PSCB(vcpu, itv) & 0xff)) {
986 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
987 }
989 i = vector >> 6;
990 mask = 1L << (vector & 0x3f);
991 //printk("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
992 PSCBX(vcpu, insvc[i]) |= mask;
993 PSCBX(vcpu, irr[i]) &= ~mask;
994 //PSCB(vcpu,pending_interruption)--;
995 *pval = vector;
996 return IA64_NO_FAULT;
997 }
999 IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval)
1001 *pval = PSCB(vcpu, tpr);
1002 return IA64_NO_FAULT;
1005 IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval)
1007 *pval = 0L; // reads of eoi always return 0
1008 return IA64_NO_FAULT;
1011 IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval)
1013 *pval = PSCBX(vcpu, irr[0]);
1014 return IA64_NO_FAULT;
1017 IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval)
1019 *pval = PSCBX(vcpu, irr[1]);
1020 return IA64_NO_FAULT;
1023 IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval)
1025 *pval = PSCBX(vcpu, irr[2]);
1026 return IA64_NO_FAULT;
1029 IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval)
1031 *pval = PSCBX(vcpu, irr[3]);
1032 return IA64_NO_FAULT;
1035 IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval)
1037 *pval = PSCB(vcpu, itv);
1038 return IA64_NO_FAULT;
1041 IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval)
1043 *pval = PSCB(vcpu, pmv);
1044 return IA64_NO_FAULT;
1047 IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval)
1049 *pval = PSCB(vcpu, cmcv);
1050 return IA64_NO_FAULT;
1053 IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval)
1055 // fix this when setting values other than m-bit is supported
1056 gdprintk(XENLOG_DEBUG,
1057 "vcpu_get_lrr0: Unmasked interrupts unsupported\n");
1058 *pval = (1L << 16);
1059 return IA64_NO_FAULT;
1062 IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval)
1064 // fix this when setting values other than m-bit is supported
1065 gdprintk(XENLOG_DEBUG,
1066 "vcpu_get_lrr1: Unmasked interrupts unsupported\n");
1067 *pval = (1L << 16);
1068 return IA64_NO_FAULT;
1071 IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val)
1073 printk("vcpu_set_lid: Setting cr.lid is unsupported\n");
1074 return IA64_ILLOP_FAULT;
1077 IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val)
1079 if (val & 0xff00)
1080 return IA64_RSVDREG_FAULT;
1081 PSCB(vcpu, tpr) = val;
1082 /* This can unmask interrupts. */
1083 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
1084 PSCB(vcpu, pending_interruption) = 1;
1085 return IA64_NO_FAULT;
1088 IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val)
1090 u64 *p, bits, vec, bitnum;
1091 int i;
1093 p = &PSCBX(vcpu, insvc[3]);
1094 for (i = 3; (i >= 0) && !(bits = *p); i--, p--)
1096 if (i < 0) {
1097 printk("Trying to EOI interrupt when none are in-service.\n");
1098 return IA64_NO_FAULT;
1100 bitnum = ia64_fls(bits);
1101 vec = bitnum + (i * 64);
1102 /* clear the correct bit */
1103 bits &= ~(1L << bitnum);
1104 *p = bits;
1105 /* clearing an eoi bit may unmask another pending interrupt... */
1106 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
1107 // worry about this later... Linux only calls eoi
1108 // with interrupts disabled
1109 printk("Trying to EOI interrupt with interrupts enabled\n");
1111 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
1112 PSCB(vcpu, pending_interruption) = 1;
1113 //printk("YYYYY vcpu_set_eoi: Successful\n");
1114 return IA64_NO_FAULT;
1117 IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val)
1119 if (!(val & (1L << 16))) {
1120 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
1121 return IA64_ILLOP_FAULT;
1123 // no place to save this state but nothing to do anyway
1124 return IA64_NO_FAULT;
1127 IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val)
1129 if (!(val & (1L << 16))) {
1130 printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
1131 return IA64_ILLOP_FAULT;
1133 // no place to save this state but nothing to do anyway
1134 return IA64_NO_FAULT;
1137 IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val)
1139 /* Check reserved fields. */
1140 if (val & 0xef00)
1141 return IA64_ILLOP_FAULT;
1142 PSCB(vcpu, itv) = val;
1143 if (val & 0x10000) {
1144 /* Disable itm. */
1145 PSCBX(vcpu, domain_itm) = 0;
1146 } else
1147 vcpu_set_next_timer(vcpu);
1148 return IA64_NO_FAULT;
1151 IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val)
1153 if (val & 0xef00) /* reserved fields */
1154 return IA64_RSVDREG_FAULT;
1155 PSCB(vcpu, pmv) = val;
1156 return IA64_NO_FAULT;
1159 IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val)
1161 if (val & 0xef00) /* reserved fields */
1162 return IA64_RSVDREG_FAULT;
1163 PSCB(vcpu, cmcv) = val;
1164 return IA64_NO_FAULT;
1167 /**************************************************************************
1168 VCPU temporary register access routines
1169 **************************************************************************/
1170 u64 vcpu_get_tmp(VCPU * vcpu, u64 index)
1172 if (index > 7)
1173 return 0;
1174 return PSCB(vcpu, tmp[index]);
1177 void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val)
1179 if (index <= 7)
1180 PSCB(vcpu, tmp[index]) = val;
1183 /**************************************************************************
1184 Interval timer routines
1185 **************************************************************************/
1187 BOOLEAN vcpu_timer_disabled(VCPU * vcpu)
1189 u64 itv = PSCB(vcpu, itv);
1190 return (!itv || !!(itv & 0x10000));
1193 BOOLEAN vcpu_timer_inservice(VCPU * vcpu)
1195 u64 itv = PSCB(vcpu, itv);
1196 return test_bit(itv, PSCBX(vcpu, insvc));
1199 BOOLEAN vcpu_timer_expired(VCPU * vcpu)
1201 unsigned long domain_itm = PSCBX(vcpu, domain_itm);
1202 unsigned long now = ia64_get_itc();
1204 if (!domain_itm)
1205 return FALSE;
1206 if (now < domain_itm)
1207 return FALSE;
1208 if (vcpu_timer_disabled(vcpu))
1209 return FALSE;
1210 return TRUE;
1213 void vcpu_safe_set_itm(unsigned long val)
1215 unsigned long epsilon = 100;
1216 unsigned long flags;
1217 u64 now = ia64_get_itc();
1219 local_irq_save(flags);
1220 while (1) {
1221 //printk("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1222 ia64_set_itm(val);
1223 if (val > (now = ia64_get_itc()))
1224 break;
1225 val = now + epsilon;
1226 epsilon <<= 1;
1228 local_irq_restore(flags);
1231 void vcpu_set_next_timer(VCPU * vcpu)
1233 u64 d = PSCBX(vcpu, domain_itm);
1234 //u64 s = PSCBX(vcpu,xen_itm);
1235 u64 s = local_cpu_data->itm_next;
1236 u64 now = ia64_get_itc();
1238 /* gloss over the wraparound problem for now... we know it exists
1239 * but it doesn't matter right now */
1241 if (is_idle_domain(vcpu->domain)) {
1242 // printk("****** vcpu_set_next_timer called during idle!!\n");
1243 vcpu_safe_set_itm(s);
1244 return;
1246 //s = PSCBX(vcpu,xen_itm);
1247 if (d && (d > now) && (d < s)) {
1248 vcpu_safe_set_itm(d);
1249 //using_domain_as_itm++;
1250 } else {
1251 vcpu_safe_set_itm(s);
1252 //using_xen_as_itm++;
1256 IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val)
1258 //UINT now = ia64_get_itc();
1260 //if (val < now) val = now + 1000;
1261 //printk("*** vcpu_set_itm: called with %lx\n",val);
1262 PSCBX(vcpu, domain_itm) = val;
1263 vcpu_set_next_timer(vcpu);
1264 return IA64_NO_FAULT;
1267 IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val)
1269 #define DISALLOW_SETTING_ITC_FOR_NOW
1270 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1271 static int did_print;
1272 if (!did_print) {
1273 printk("vcpu_set_itc: Setting ar.itc is currently disabled "
1274 "(this message is only displayed once)\n");
1275 did_print = 1;
1277 #else
1278 u64 oldnow = ia64_get_itc();
1279 u64 olditm = PSCBX(vcpu, domain_itm);
1280 unsigned long d = olditm - oldnow;
1281 unsigned long x = local_cpu_data->itm_next - oldnow;
1283 u64 newnow = val, min_delta;
1285 local_irq_disable();
1286 if (olditm) {
1287 printk("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val,
1288 newnow + d);
1289 PSCBX(vcpu, domain_itm) = newnow + d;
1291 local_cpu_data->itm_next = newnow + x;
1292 d = PSCBX(vcpu, domain_itm);
1293 x = local_cpu_data->itm_next;
1295 ia64_set_itc(newnow);
1296 if (d && (d > newnow) && (d < x)) {
1297 vcpu_safe_set_itm(d);
1298 //using_domain_as_itm++;
1299 } else {
1300 vcpu_safe_set_itm(x);
1301 //using_xen_as_itm++;
1303 local_irq_enable();
1304 #endif
1305 return IA64_NO_FAULT;
1308 IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval)
1310 //FIXME: Implement this
1311 printk("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1312 return IA64_NO_FAULT;
1313 //return IA64_ILLOP_FAULT;
1316 IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval)
1318 //TODO: Implement this
1319 printk("vcpu_get_itc: Getting ar.itc is unsupported\n");
1320 return IA64_ILLOP_FAULT;
1323 void vcpu_pend_timer(VCPU * vcpu)
1325 u64 itv = PSCB(vcpu, itv) & 0xff;
1327 if (vcpu_timer_disabled(vcpu))
1328 return;
1329 //if (vcpu_timer_inservice(vcpu)) return;
1330 if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) {
1331 // already delivered an interrupt for this so
1332 // don't deliver another
1333 return;
1335 if (vcpu->arch.event_callback_ip) {
1336 /* A small window may occur when injecting vIRQ while related
1337 * handler has not been registered. Don't fire in such case.
1338 */
1339 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1340 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1341 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1343 } else
1344 vcpu_pend_interrupt(vcpu, itv);
1347 // returns true if ready to deliver a timer interrupt too early
1348 u64 vcpu_timer_pending_early(VCPU * vcpu)
1350 u64 now = ia64_get_itc();
1351 u64 itm = PSCBX(vcpu, domain_itm);
1353 if (vcpu_timer_disabled(vcpu))
1354 return 0;
1355 if (!itm)
1356 return 0;
1357 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1360 /**************************************************************************
1361 Privileged operation emulation routines
1362 **************************************************************************/
1364 static void vcpu_force_tlb_miss(VCPU * vcpu, u64 ifa)
1366 PSCB(vcpu, ifa) = ifa;
1367 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1368 vcpu_thash(current, ifa, &PSCB(current, iha));
1371 IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa)
1373 vcpu_force_tlb_miss(vcpu, ifa);
1374 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_INST_TLB_VECTOR :
1375 IA64_ALT_INST_TLB_VECTOR;
1378 IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa)
1380 vcpu_force_tlb_miss(vcpu, ifa);
1381 return vcpu_get_rr_ve(vcpu, ifa) ? IA64_DATA_TLB_VECTOR :
1382 IA64_ALT_DATA_TLB_VECTOR;
1385 IA64FAULT vcpu_rfi(VCPU * vcpu)
1387 u64 ifs;
1388 REGS *regs = vcpu_regs(vcpu);
1390 vcpu_set_psr(vcpu, PSCB(vcpu, ipsr));
1392 ifs = PSCB(vcpu, ifs);
1393 if (ifs & 0x8000000000000000UL)
1394 regs->cr_ifs = ifs;
1396 regs->cr_iip = PSCB(vcpu, iip);
1398 return IA64_NO_FAULT;
1401 IA64FAULT vcpu_cover(VCPU * vcpu)
1403 // TODO: Only allowed for current vcpu
1404 REGS *regs = vcpu_regs(vcpu);
1406 if (!PSCB(vcpu, interrupt_collection_enabled)) {
1407 PSCB(vcpu, ifs) = regs->cr_ifs;
1409 regs->cr_ifs = 0;
1410 return IA64_NO_FAULT;
1413 IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval)
1415 u64 pta = PSCB(vcpu, pta);
1416 u64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1417 u64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT) - 1);
1418 u64 Mask = (1L << pta_sz) - 1;
1419 u64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1420 u64 compMask_60_15 = ~Mask_60_15;
1421 u64 rr_ps = vcpu_get_rr_ps(vcpu, vadr);
1422 u64 VHPT_offset = (vadr >> rr_ps) << 3;
1423 u64 VHPT_addr1 = vadr & 0xe000000000000000L;
1424 u64 VHPT_addr2a =
1425 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1426 u64 VHPT_addr2b =
1427 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1428 u64 VHPT_addr3 = VHPT_offset & 0x7fff;
1429 u64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1430 VHPT_addr3;
1432 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1433 *pval = VHPT_addr;
1434 return IA64_NO_FAULT;
1437 IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr)
1439 printk("vcpu_ttag: ttag instruction unsupported\n");
1440 return IA64_ILLOP_FAULT;
1443 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1445 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1446 static inline int range_overlap(u64 b1, u64 e1, u64 b2, u64 e2)
1448 return (b1 <= e2) && (e1 >= b2);
1451 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1452 Note: LSBs of base inside page_size are ignored. */
1453 static inline void
1454 check_xen_space_overlap(const char *func, u64 base, u64 page_size)
1456 /* Overlaps can occur only in region 7.
1457 (This is an optimization to bypass all the checks). */
1458 if (REGION_NUMBER(base) != 7)
1459 return;
1461 /* Mask LSBs of base. */
1462 base &= ~(page_size - 1);
1464 /* FIXME: ideally an MCA should be generated... */
1465 if (range_overlap(HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
1466 base, base + page_size)
1467 || range_overlap(current->domain->arch.shared_info_va,
1468 current->domain->arch.shared_info_va
1469 + XSI_SIZE + XMAPPEDREGS_SIZE,
1470 base, base + page_size))
1471 panic_domain(NULL, "%s on Xen virtual space (%lx)\n",
1472 func, base);
1475 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1476 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY * trp, u64 ifa,
1477 u64 rid)
1479 return trp->rid == rid
1480 && ifa >= trp->vadr && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1483 static inline int vcpu_match_tr_entry(TR_ENTRY * trp, u64 ifa, u64 rid)
1485 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1488 static inline int
1489 vcpu_match_tr_entry_range(TR_ENTRY * trp, u64 rid, u64 b, u64 e)
1491 return trp->rid == rid
1492 && trp->pte.p
1493 && range_overlap(b, e, trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1497 static TR_ENTRY *vcpu_tr_lookup(VCPU * vcpu, unsigned long va, u64 rid,
1498 BOOLEAN is_data)
1500 unsigned char *regions;
1501 TR_ENTRY *trp;
1502 int tr_max;
1503 int i;
1505 if (is_data) {
1506 // data
1507 regions = &vcpu->arch.dtr_regions;
1508 trp = vcpu->arch.dtrs;
1509 tr_max = sizeof(vcpu->arch.dtrs) / sizeof(vcpu->arch.dtrs[0]);
1510 } else {
1511 // instruction
1512 regions = &vcpu->arch.itr_regions;
1513 trp = vcpu->arch.itrs;
1514 tr_max = sizeof(vcpu->arch.itrs) / sizeof(vcpu->arch.itrs[0]);
1517 if (!vcpu_quick_region_check(*regions, va)) {
1518 return NULL;
1520 for (i = 0; i < tr_max; i++, trp++) {
1521 if (vcpu_match_tr_entry(trp, va, rid)) {
1522 return trp;
1525 return NULL;
1528 // return value
1529 // 0: failure
1530 // 1: success
1531 int
1532 vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
1533 IA64_BUNDLE * bundle)
1535 u64 gpip; // guest pseudo phyiscal ip
1536 unsigned long vaddr;
1537 struct page_info *page;
1539 again:
1540 #if 0
1541 // Currently xen doesn't track psr.it bits.
1542 // it assumes always psr.it = 1.
1543 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1544 gpip = gip;
1545 } else
1546 #endif
1548 unsigned long region = REGION_NUMBER(gip);
1549 unsigned long rr = PSCB(vcpu, rrs)[region];
1550 unsigned long rid = rr & RR_RID_MASK;
1551 BOOLEAN swap_rr0;
1552 TR_ENTRY *trp;
1554 // vcpu->arch.{i, d}tlb are volatile,
1555 // copy its value to the variable, tr, before use.
1556 TR_ENTRY tr;
1558 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1559 if (trp != NULL) {
1560 tr = *trp;
1561 goto found;
1563 // When it failed to get a bundle, itlb miss is reflected.
1564 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1565 tr = PSCBX(vcpu, itlb);
1566 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1567 //dprintk(XENLOG_WARNING,
1568 // "%s gip 0x%lx gpip 0x%lx\n", __func__,
1569 // gip, gpip);
1570 goto found;
1572 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1573 if (trp != NULL) {
1574 tr = *trp;
1575 goto found;
1577 #if 0
1578 tr = PSCBX(vcpu, dtlb);
1579 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1580 goto found;
1582 #endif
1584 // try to access gip with guest virtual address
1585 // This may cause tlb miss. see vcpu_translate(). Be careful!
1586 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1587 if (swap_rr0) {
1588 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
1590 *bundle = __get_domain_bundle(gip);
1591 if (swap_rr0) {
1592 set_metaphysical_rr0();
1594 if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
1595 dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
1596 return 0;
1598 return 1;
1600 found:
1601 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1602 (gip & ((1 << tr.ps) - 1));
1605 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1606 page = virt_to_page(vaddr);
1607 if (get_page(page, vcpu->domain) == 0) {
1608 if (page_get_owner(page) != vcpu->domain) {
1609 // This page might be a page granted by another
1610 // domain.
1611 panic_domain(regs, "domain tries to execute foreign "
1612 "domain page which might be mapped by "
1613 "grant table.\n");
1615 goto again;
1617 *bundle = *((IA64_BUNDLE *) vaddr);
1618 put_page(page);
1619 return 1;
1622 IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
1623 u64 * pteval, u64 * itir, u64 * iha)
1625 unsigned long region = address >> 61;
1626 unsigned long pta, rid, rr;
1627 union pte_flags pte;
1628 TR_ENTRY *trp;
1630 if (PSCB(vcpu, metaphysical_mode) && !(!is_data && region)) {
1631 // dom0 may generate an uncacheable physical address (msb=1)
1632 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1633 // FIXME: This seems to happen even though it shouldn't. Need to track
1634 // this down, but since it has been apparently harmless, just flag it for now
1635 // panic_domain(vcpu_regs(vcpu),
1637 /*
1638 * Guest may execute itc.d and rfi with psr.dt=0
1639 * When VMM try to fetch opcode, tlb miss may happen,
1640 * At this time PSCB(vcpu,metaphysical_mode)=1,
1641 * region=5,VMM need to handle this tlb miss as if
1642 * PSCB(vcpu,metaphysical_mode)=0
1643 */
1644 printk("vcpu_translate: bad physical address: 0x%lx "
1645 "at %lx\n", address, vcpu_regs(vcpu)->cr_iip);
1647 } else {
1648 *pteval = (address & _PAGE_PPN_MASK) |
1649 __DIRTY_BITS | _PAGE_PL_PRIV | _PAGE_AR_RWX;
1650 *itir = PAGE_SHIFT << 2;
1651 perfc_incr(phys_translate);
1652 return IA64_NO_FAULT;
1654 } else if (!region && warn_region0_address) {
1655 REGS *regs = vcpu_regs(vcpu);
1656 unsigned long viip = PSCB(vcpu, iip);
1657 unsigned long vipsr = PSCB(vcpu, ipsr);
1658 unsigned long iip = regs->cr_iip;
1659 unsigned long ipsr = regs->cr_ipsr;
1660 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, "
1661 "vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1662 address, viip, vipsr, iip, ipsr);
1665 rr = PSCB(vcpu, rrs)[region];
1666 rid = rr & RR_RID_MASK;
1667 if (is_data) {
1668 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1669 if (trp != NULL) {
1670 *pteval = trp->pte.val;
1671 *itir = trp->itir;
1672 perfc_incr(tr_translate);
1673 return IA64_NO_FAULT;
1676 // FIXME?: check itr's for data accesses too, else bad things happen?
1677 /* else */ {
1678 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1679 if (trp != NULL) {
1680 *pteval = trp->pte.val;
1681 *itir = trp->itir;
1682 perfc_incr(tr_translate);
1683 return IA64_NO_FAULT;
1687 /* check 1-entry TLB */
1688 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1689 trp = &vcpu->arch.dtlb;
1690 pte = trp->pte;
1691 if ( /* is_data && */ pte.p
1692 && vcpu_match_tr_entry_no_p(trp, address, rid)) {
1693 *pteval = pte.val;
1694 *itir = trp->itir;
1695 perfc_incr(dtlb_translate);
1696 return IA64_USE_TLB;
1699 /* check guest VHPT */
1700 pta = PSCB(vcpu, pta);
1701 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1702 panic_domain(vcpu_regs(vcpu), "can't do long format VHPT\n");
1703 //return is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR;
1706 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1707 // note: architecturally, iha is optionally set for alt faults but
1708 // xenlinux depends on it so should document it as part of PV interface
1709 vcpu_thash(vcpu, address, iha);
1710 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE)) {
1711 REGS *regs = vcpu_regs(vcpu);
1712 struct opt_feature* optf = &(vcpu->domain->arch.opt_feature);
1714 /* Optimization for identity mapped region 7 OS (linux) */
1715 if (optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG7 &&
1716 region == 7 && ia64_psr(regs)->cpl == CONFIG_CPL0_EMUL) {
1717 pte.val = address & _PAGE_PPN_MASK;
1718 pte.val = pte.val | optf->im_reg7.pgprot;
1719 goto out;
1721 return is_data ? IA64_ALT_DATA_TLB_VECTOR :
1722 IA64_ALT_INST_TLB_VECTOR;
1725 /* avoid recursively walking (short format) VHPT */
1726 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1727 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1729 if (!__access_ok(*iha)
1730 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1731 // virtual VHPT walker "missed" in TLB
1732 return IA64_VHPT_FAULT;
1734 /*
1735 * Optimisation: this VHPT walker aborts on not-present pages
1736 * instead of inserting a not-present translation, this allows
1737 * vectoring directly to the miss handler.
1738 */
1739 if (!pte.p)
1740 return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
1742 /* found mapping in guest VHPT! */
1743 out:
1744 *itir = rr & RR_PS_MASK;
1745 *pteval = pte.val;
1746 perfc_incr(vhpt_translate);
1747 return IA64_NO_FAULT;
1750 IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr)
1752 u64 pteval, itir, mask, iha;
1753 IA64FAULT fault;
1755 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1756 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
1757 mask = itir_mask(itir);
1758 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1759 return IA64_NO_FAULT;
1761 return vcpu_force_data_miss(vcpu, vadr);
1764 IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
1766 printk("vcpu_tak: tak instruction unsupported\n");
1767 return IA64_ILLOP_FAULT;
1768 // HACK ALERT: tak does a thash for now
1769 //return vcpu_thash(vcpu,vadr,key);
1772 /**************************************************************************
1773 VCPU debug breakpoint register access routines
1774 **************************************************************************/
1776 IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
1778 if (reg >= IA64_NUM_DBG_REGS)
1779 return IA64_RSVDREG_FAULT;
1780 if ((reg & 1) == 0) {
1781 /* Validate address. */
1782 if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END)
1783 return IA64_ILLOP_FAULT;
1784 } else {
1785 if (!VMX_DOMAIN(vcpu)) {
1786 /* Mask PL0. */
1787 val &= ~(1UL << 56);
1790 if (val != 0)
1791 vcpu->arch.dbg_used |= (1 << reg);
1792 else
1793 vcpu->arch.dbg_used &= ~(1 << reg);
1794 vcpu->arch.dbr[reg] = val;
1795 if (vcpu == current)
1796 ia64_set_dbr(reg, val);
1797 return IA64_NO_FAULT;
1800 IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
1802 if (reg >= IA64_NUM_DBG_REGS)
1803 return IA64_RSVDREG_FAULT;
1804 if ((reg & 1) == 0) {
1805 /* Validate address. */
1806 if (val >= HYPERVISOR_VIRT_START && val <= HYPERVISOR_VIRT_END)
1807 return IA64_ILLOP_FAULT;
1808 } else {
1809 if (!VMX_DOMAIN(vcpu)) {
1810 /* Mask PL0. */
1811 val &= ~(1UL << 56);
1814 if (val != 0)
1815 vcpu->arch.dbg_used |= (1 << (reg + IA64_NUM_DBG_REGS));
1816 else
1817 vcpu->arch.dbg_used &= ~(1 << (reg + IA64_NUM_DBG_REGS));
1818 vcpu->arch.ibr[reg] = val;
1819 if (vcpu == current)
1820 ia64_set_ibr(reg, val);
1821 return IA64_NO_FAULT;
1824 IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
1826 if (reg >= IA64_NUM_DBG_REGS)
1827 return IA64_RSVDREG_FAULT;
1828 *pval = vcpu->arch.dbr[reg];
1829 return IA64_NO_FAULT;
1832 IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
1834 if (reg >= IA64_NUM_DBG_REGS)
1835 return IA64_RSVDREG_FAULT;
1836 *pval = vcpu->arch.ibr[reg];
1837 return IA64_NO_FAULT;
1840 /**************************************************************************
1841 VCPU performance monitor register access routines
1842 **************************************************************************/
1844 IA64FAULT vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val)
1846 // TODO: Should set Logical CPU state, not just physical
1847 // NOTE: Writes to unimplemented PMC registers are discarded
1848 #ifdef DEBUG_PFMON
1849 printk("vcpu_set_pmc(%x,%lx)\n", reg, val);
1850 #endif
1851 ia64_set_pmc(reg, val);
1852 return IA64_NO_FAULT;
1855 IA64FAULT vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val)
1857 // TODO: Should set Logical CPU state, not just physical
1858 // NOTE: Writes to unimplemented PMD registers are discarded
1859 #ifdef DEBUG_PFMON
1860 printk("vcpu_set_pmd(%x,%lx)\n", reg, val);
1861 #endif
1862 ia64_set_pmd(reg, val);
1863 return IA64_NO_FAULT;
1866 IA64FAULT vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval)
1868 // NOTE: Reads from unimplemented PMC registers return zero
1869 u64 val = (u64) ia64_get_pmc(reg);
1870 #ifdef DEBUG_PFMON
1871 printk("%lx=vcpu_get_pmc(%x)\n", val, reg);
1872 #endif
1873 *pval = val;
1874 return IA64_NO_FAULT;
1877 IA64FAULT vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval)
1879 // NOTE: Reads from unimplemented PMD registers return zero
1880 u64 val = (u64) ia64_get_pmd(reg);
1881 #ifdef DEBUG_PFMON
1882 printk("%lx=vcpu_get_pmd(%x)\n", val, reg);
1883 #endif
1884 *pval = val;
1885 return IA64_NO_FAULT;
1888 /**************************************************************************
1889 VCPU banked general register access routines
1890 **************************************************************************/
1891 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1892 do{ \
1893 __asm__ __volatile__ ( \
1894 ";;extr.u %0 = %3,%6,16;;\n" \
1895 "dep %1 = %0, %1, 0, 16;;\n" \
1896 "st8 [%4] = %1\n" \
1897 "extr.u %0 = %2, 16, 16;;\n" \
1898 "dep %3 = %0, %3, %6, 16;;\n" \
1899 "st8 [%5] = %3\n" \
1900 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1901 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1902 }while(0)
1904 IA64FAULT vcpu_bsw0(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 *b1++ = *r;
1921 *r++ = *b0++;
1923 vcpu_bsw0_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 *b1++ = *r;
1931 *r++ = *b0++;
1933 vcpu_bsw0_unat(i, b0unat, b1unat, runat,
1934 IA64_PT_REGS_R16_SLOT);
1935 PSCB(vcpu, banknum) = 0;
1938 return IA64_NO_FAULT;
1941 #define vcpu_bsw1_unat(i, b0unat, b1unat, runat, IA64_PT_REGS_R16_SLOT) \
1942 do { \
1943 __asm__ __volatile__ (";;extr.u %0 = %3,%6,16;;\n" \
1944 "dep %1 = %0, %1, 16, 16;;\n" \
1945 "st8 [%4] = %1\n" \
1946 "extr.u %0 = %2, 0, 16;;\n" \
1947 "dep %3 = %0, %3, %6, 16;;\n" \
1948 "st8 [%5] = %3\n" \
1949 ::"r"(i), "r"(*b0unat), "r"(*b1unat), \
1950 "r"(*runat), "r"(b0unat), "r"(runat), \
1951 "i"(IA64_PT_REGS_R16_SLOT): "memory"); \
1952 } while(0)
1954 IA64FAULT vcpu_bsw1(VCPU * vcpu)
1956 // TODO: Only allowed for current vcpu
1957 REGS *regs = vcpu_regs(vcpu);
1958 unsigned long *r = &regs->r16;
1959 unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
1960 unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
1961 unsigned long *runat = &regs->eml_unat;
1962 unsigned long *b0unat = &PSCB(vcpu, vbnat);
1963 unsigned long *b1unat = &PSCB(vcpu, vnat);
1965 unsigned long i;
1967 if (VMX_DOMAIN(vcpu)) {
1968 if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
1969 for (i = 0; i < 16; i++) {
1970 *b0++ = *r;
1971 *r++ = *b1++;
1973 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1974 IA64_PT_REGS_R16_SLOT);
1975 VCPU(vcpu, vpsr) |= IA64_PSR_BN;
1977 } else {
1978 if (!PSCB(vcpu, banknum)) {
1979 for (i = 0; i < 16; i++) {
1980 *b0++ = *r;
1981 *r++ = *b1++;
1983 vcpu_bsw1_unat(i, b0unat, b1unat, runat,
1984 IA64_PT_REGS_R16_SLOT);
1985 PSCB(vcpu, banknum) = 1;
1988 return IA64_NO_FAULT;
1991 /**************************************************************************
1992 VCPU cpuid access routines
1993 **************************************************************************/
1995 IA64FAULT vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval)
1997 // FIXME: This could get called as a result of a rsvd-reg fault
1998 // if reg > 3
1999 switch (reg) {
2000 case 0:
2001 memcpy(pval, "Xen/ia64", 8);
2002 break;
2003 case 1:
2004 *pval = 0;
2005 break;
2006 case 2:
2007 *pval = 0;
2008 break;
2009 case 3:
2010 *pval = ia64_get_cpuid(3);
2011 break;
2012 case 4:
2013 *pval = ia64_get_cpuid(4);
2014 break;
2015 default:
2016 if (reg > (ia64_get_cpuid(3) & 0xff))
2017 return IA64_RSVDREG_FAULT;
2018 *pval = ia64_get_cpuid(reg);
2019 break;
2021 return IA64_NO_FAULT;
2024 /**************************************************************************
2025 VCPU region register access routines
2026 **************************************************************************/
2028 unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
2030 ia64_rr rr;
2032 rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
2033 return rr.ve;
2036 IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val)
2038 PSCB(vcpu, rrs)[reg >> 61] = val;
2039 if (vcpu == current)
2040 set_one_rr(reg, val);
2041 return IA64_NO_FAULT;
2044 IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval)
2046 if (VMX_DOMAIN(vcpu))
2047 *pval = VMX(vcpu, vrr[reg >> 61]);
2048 else
2049 *pval = PSCB(vcpu, rrs)[reg >> 61];
2051 return IA64_NO_FAULT;
2054 /**************************************************************************
2055 VCPU protection key register access routines
2056 **************************************************************************/
2058 IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
2060 printk("vcpu_get_pkr: called, not implemented yet\n");
2061 return IA64_ILLOP_FAULT;
2064 IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
2066 printk("vcpu_set_pkr: called, not implemented yet\n");
2067 return IA64_ILLOP_FAULT;
2070 /**************************************************************************
2071 VCPU translation register access routines
2072 **************************************************************************/
2074 static void
2075 vcpu_set_tr_entry_rid(TR_ENTRY * trp, u64 pte,
2076 u64 itir, u64 ifa, u64 rid)
2078 u64 ps;
2079 union pte_flags new_pte;
2081 trp->itir = itir;
2082 trp->rid = rid;
2083 ps = trp->ps;
2084 new_pte.val = pte;
2085 if (new_pte.pl < CONFIG_CPL0_EMUL)
2086 new_pte.pl = CONFIG_CPL0_EMUL;
2087 trp->vadr = ifa & ~0xfff;
2088 if (ps > 12) { // "ignore" relevant low-order bits
2089 new_pte.ppn &= ~((1UL << (ps - 12)) - 1);
2090 trp->vadr &= ~((1UL << ps) - 1);
2093 /* Atomic write. */
2094 trp->pte.val = new_pte.val;
2097 static inline void
2098 vcpu_set_tr_entry(TR_ENTRY * trp, u64 pte, u64 itir, u64 ifa)
2100 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
2101 VCPU(current, rrs[ifa >> 61]) & RR_RID_MASK);
2104 IA64FAULT vcpu_itr_d(VCPU * vcpu, u64 slot, u64 pte,
2105 u64 itir, u64 ifa)
2107 TR_ENTRY *trp;
2109 if (slot >= NDTRS)
2110 return IA64_RSVDREG_FAULT;
2112 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2114 trp = &PSCBX(vcpu, dtrs[slot]);
2115 //printk("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
2116 vcpu_set_tr_entry(trp, pte, itir, ifa);
2117 vcpu_quick_region_set(PSCBX(vcpu, dtr_regions), ifa);
2119 /*
2120 * FIXME According to spec, vhpt should be purged, but this
2121 * incurs considerable performance loss, since it is safe for
2122 * linux not to purge vhpt, vhpt purge is disabled until a
2123 * feasible way is found.
2125 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2126 */
2128 return IA64_NO_FAULT;
2131 IA64FAULT vcpu_itr_i(VCPU * vcpu, u64 slot, u64 pte,
2132 u64 itir, u64 ifa)
2134 TR_ENTRY *trp;
2136 if (slot >= NITRS)
2137 return IA64_RSVDREG_FAULT;
2139 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2141 trp = &PSCBX(vcpu, itrs[slot]);
2142 //printk("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
2143 vcpu_set_tr_entry(trp, pte, itir, ifa);
2144 vcpu_quick_region_set(PSCBX(vcpu, itr_regions), ifa);
2146 /*
2147 * FIXME According to spec, vhpt should be purged, but this
2148 * incurs considerable performance loss, since it is safe for
2149 * linux not to purge vhpt, vhpt purge is disabled until a
2150 * feasible way is found.
2152 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
2153 */
2155 return IA64_NO_FAULT;
2158 IA64FAULT vcpu_set_itr(VCPU * vcpu, u64 slot, u64 pte,
2159 u64 itir, u64 ifa, u64 rid)
2161 TR_ENTRY *trp;
2163 if (slot >= NITRS)
2164 return IA64_RSVDREG_FAULT;
2165 trp = &PSCBX(vcpu, itrs[slot]);
2166 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2168 /* Recompute the itr_region. */
2169 vcpu->arch.itr_regions = 0;
2170 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
2171 if (trp->pte.p)
2172 vcpu_quick_region_set(vcpu->arch.itr_regions,
2173 trp->vadr);
2174 return IA64_NO_FAULT;
2177 IA64FAULT vcpu_set_dtr(VCPU * vcpu, u64 slot, u64 pte,
2178 u64 itir, u64 ifa, u64 rid)
2180 TR_ENTRY *trp;
2182 if (slot >= NDTRS)
2183 return IA64_RSVDREG_FAULT;
2184 trp = &PSCBX(vcpu, dtrs[slot]);
2185 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
2187 /* Recompute the dtr_region. */
2188 vcpu->arch.dtr_regions = 0;
2189 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
2190 if (trp->pte.p)
2191 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2192 trp->vadr);
2193 return IA64_NO_FAULT;
2196 /**************************************************************************
2197 VCPU translation cache access routines
2198 **************************************************************************/
2200 void
2201 vcpu_itc_no_srlz(VCPU * vcpu, u64 IorD, u64 vaddr, u64 pte,
2202 u64 mp_pte, u64 logps, struct p2m_entry *entry)
2204 unsigned long psr;
2205 unsigned long ps = (vcpu->domain == dom0) ? logps : PAGE_SHIFT;
2207 check_xen_space_overlap("itc", vaddr, 1UL << logps);
2209 // FIXME, must be inlined or potential for nested fault here!
2210 if ((vcpu->domain == dom0) && (logps < PAGE_SHIFT))
2211 panic_domain(NULL, "vcpu_itc_no_srlz: domain trying to use "
2212 "smaller page size!\n");
2214 BUG_ON(logps > PAGE_SHIFT);
2215 vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry);
2216 psr = ia64_clear_ic();
2217 pte &= ~(_PAGE_RV2 | _PAGE_RV1); // Mask out the reserved bits.
2218 ia64_itc(IorD, vaddr, pte, ps); // FIXME: look for bigger mappings
2219 ia64_set_psr(psr);
2220 // ia64_srlz_i(); // no srls req'd, will rfi later
2221 if (vcpu->domain == dom0 && ((vaddr >> 61) == 7)) {
2222 // FIXME: this is dangerous... vhpt_flush_address ensures these
2223 // addresses never get flushed. More work needed if this
2224 // ever happens.
2225 //printk("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2226 if (logps > PAGE_SHIFT)
2227 vhpt_multiple_insert(vaddr, pte, logps);
2228 else
2229 vhpt_insert(vaddr, pte, logps << 2);
2231 // even if domain pagesize is larger than PAGE_SIZE, just put
2232 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2233 else
2234 vhpt_insert(vaddr, pte, PAGE_SHIFT << 2);
2237 IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2239 unsigned long pteval, logps = itir_ps(itir);
2240 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2241 struct p2m_entry entry;
2243 if (logps < PAGE_SHIFT)
2244 panic_domain(NULL, "vcpu_itc_d: domain trying to use "
2245 "smaller page size!\n");
2247 again:
2248 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2249 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2250 if (!pteval)
2251 return IA64_ILLOP_FAULT;
2252 if (swap_rr0)
2253 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
2254 vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, logps, &entry);
2255 if (swap_rr0)
2256 set_metaphysical_rr0();
2257 if (p2m_entry_retry(&entry)) {
2258 vcpu_flush_tlb_vhpt_range(ifa, logps);
2259 goto again;
2261 vcpu_set_tr_entry(&PSCBX(vcpu, dtlb), pte, itir, ifa);
2262 return IA64_NO_FAULT;
2265 IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
2267 unsigned long pteval, logps = itir_ps(itir);
2268 BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
2269 struct p2m_entry entry;
2271 if (logps < PAGE_SHIFT)
2272 panic_domain(NULL, "vcpu_itc_i: domain trying to use "
2273 "smaller page size!\n");
2274 again:
2275 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2276 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2277 if (!pteval)
2278 return IA64_ILLOP_FAULT;
2279 if (swap_rr0)
2280 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
2281 vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, logps, &entry);
2282 if (swap_rr0)
2283 set_metaphysical_rr0();
2284 if (p2m_entry_retry(&entry)) {
2285 vcpu_flush_tlb_vhpt_range(ifa, logps);
2286 goto again;
2288 vcpu_set_tr_entry(&PSCBX(vcpu, itlb), pte, itir, ifa);
2289 return IA64_NO_FAULT;
2292 IA64FAULT vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 log_range)
2294 BUG_ON(vcpu != current);
2296 check_xen_space_overlap("ptc_l", vadr, 1UL << log_range);
2298 /* Purge TC */
2299 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2300 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2302 /* Purge all tlb and vhpt */
2303 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2305 return IA64_NO_FAULT;
2308 // At privlvl=0, fc performs no access rights or protection key checks, while
2309 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2310 // read but no protection key check. Thus in order to avoid an unexpected
2311 // access rights fault, we have to translate the virtual address to a
2312 // physical address (possibly via a metaphysical address) and do the fc
2313 // on the physical address, which is guaranteed to flush the same cache line
2314 IA64FAULT vcpu_fc(VCPU * vcpu, u64 vadr)
2316 // TODO: Only allowed for current vcpu
2317 u64 mpaddr, paddr;
2318 IA64FAULT fault;
2320 again:
2321 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2322 if (fault == IA64_NO_FAULT) {
2323 struct p2m_entry entry;
2324 paddr = translate_domain_mpaddr(mpaddr, &entry);
2325 ia64_fc(__va(paddr));
2326 if (p2m_entry_retry(&entry))
2327 goto again;
2329 return fault;
2332 IA64FAULT vcpu_ptc_e(VCPU * vcpu, u64 vadr)
2334 // Note that this only needs to be called once, i.e. the
2335 // architected loop to purge the entire TLB, should use
2336 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2338 vcpu_flush_vtlb_all(current);
2340 return IA64_NO_FAULT;
2343 IA64FAULT vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 addr_range)
2345 printk("vcpu_ptc_g: called, not implemented yet\n");
2346 return IA64_ILLOP_FAULT;
2349 IA64FAULT vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 addr_range)
2351 // FIXME: validate not flushing Xen addresses
2352 // if (Xen address) return(IA64_ILLOP_FAULT);
2353 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2354 //printk("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2356 check_xen_space_overlap("ptc_ga", vadr, addr_range);
2358 domain_flush_vtlb_range(vcpu->domain, vadr, addr_range);
2360 return IA64_NO_FAULT;
2363 IA64FAULT vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 log_range)
2365 unsigned long region = vadr >> 61;
2366 u64 addr_range = 1UL << log_range;
2367 unsigned long rid, rr;
2368 int i;
2369 TR_ENTRY *trp;
2371 BUG_ON(vcpu != current);
2372 check_xen_space_overlap("ptr_d", vadr, 1UL << log_range);
2374 rr = PSCB(vcpu, rrs)[region];
2375 rid = rr & RR_RID_MASK;
2377 /* Purge TC */
2378 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
2380 /* Purge tr and recompute dtr_regions. */
2381 vcpu->arch.dtr_regions = 0;
2382 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2383 if (vcpu_match_tr_entry_range
2384 (trp, rid, vadr, vadr + addr_range))
2385 vcpu_purge_tr_entry(trp);
2386 else if (trp->pte.p)
2387 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2388 trp->vadr);
2390 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2392 return IA64_NO_FAULT;
2395 IA64FAULT vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 log_range)
2397 unsigned long region = vadr >> 61;
2398 u64 addr_range = 1UL << log_range;
2399 unsigned long rid, rr;
2400 int i;
2401 TR_ENTRY *trp;
2403 BUG_ON(vcpu != current);
2404 check_xen_space_overlap("ptr_i", vadr, 1UL << log_range);
2406 rr = PSCB(vcpu, rrs)[region];
2407 rid = rr & RR_RID_MASK;
2409 /* Purge TC */
2410 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
2412 /* Purge tr and recompute itr_regions. */
2413 vcpu->arch.itr_regions = 0;
2414 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2415 if (vcpu_match_tr_entry_range
2416 (trp, rid, vadr, vadr + addr_range))
2417 vcpu_purge_tr_entry(trp);
2418 else if (trp->pte.p)
2419 vcpu_quick_region_set(vcpu->arch.itr_regions,
2420 trp->vadr);
2422 vcpu_flush_tlb_vhpt_range(vadr, log_range);
2424 return IA64_NO_FAULT;