ia64/xen-unstable

view xen/arch/ia64/xen/vcpu.c @ 11706:64290e7622d2

[IA64] Prevent domains to itc/ptd in shared_info_va.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Mon Oct 02 21:30:51 2006 -0600 (2006-10-02)
parents 79afceca9065
children 3f3a818d56f5
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>
28 /* FIXME: where these declarations should be there ? */
29 extern void getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs);
30 extern void setreg(unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs);
31 extern void getfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs);
33 extern void setfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs);
35 typedef union {
36 struct ia64_psr ia64_psr;
37 unsigned long i64;
38 } PSR;
40 // this def for vcpu_regs won't work if kernel stack is present
41 //#define vcpu_regs(vcpu) ((struct pt_regs *) vcpu->arch.regs
43 #define TRUE 1
44 #define FALSE 0
45 #define IA64_PTA_SZ_BIT 2
46 #define IA64_PTA_VF_BIT 8
47 #define IA64_PTA_BASE_BIT 15
48 #define IA64_PTA_LFMT (1UL << IA64_PTA_VF_BIT)
49 #define IA64_PTA_SZ(x) (x##UL << IA64_PTA_SZ_BIT)
51 unsigned long vcpu_verbose = 0;
53 /**************************************************************************
54 VCPU general register access routines
55 **************************************************************************/
56 #ifdef XEN
57 UINT64
58 vcpu_get_gr(VCPU *vcpu, unsigned long reg)
59 {
60 REGS *regs = vcpu_regs(vcpu);
61 UINT64 val;
63 if (!reg) return 0;
64 getreg(reg,&val,0,regs); // FIXME: handle NATs later
65 return val;
66 }
67 IA64FAULT
68 vcpu_get_gr_nat(VCPU *vcpu, unsigned long reg, UINT64 *val)
69 {
70 REGS *regs = vcpu_regs(vcpu);
71 int nat;
73 getreg(reg,val,&nat,regs); // FIXME: handle NATs later
74 if (nat)
75 return IA64_NAT_CONSUMPTION_VECTOR;
76 return 0;
77 }
79 // returns:
80 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
81 // IA64_NO_FAULT otherwise
82 IA64FAULT
83 vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value, int nat)
84 {
85 REGS *regs = vcpu_regs(vcpu);
86 long sof = (regs->cr_ifs) & 0x7f;
88 if (!reg) return IA64_ILLOP_FAULT;
89 if (reg >= sof + 32) return IA64_ILLOP_FAULT;
90 setreg(reg,value,nat,regs); // FIXME: handle NATs later
91 return IA64_NO_FAULT;
92 }
94 IA64FAULT
95 vcpu_get_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
96 {
97 REGS *regs = vcpu_regs(vcpu);
98 getfpreg(reg,val,regs); // FIXME: handle NATs later
99 return IA64_NO_FAULT;
100 }
102 IA64FAULT
103 vcpu_set_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
104 {
105 REGS *regs = vcpu_regs(vcpu);
106 if(reg > 1)
107 setfpreg(reg,val,regs); // FIXME: handle NATs later
108 return IA64_NO_FAULT;
109 }
111 #else
112 // returns:
113 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
114 // IA64_NO_FAULT otherwise
115 IA64FAULT
116 vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value)
117 {
118 REGS *regs = vcpu_regs(vcpu);
119 long sof = (regs->cr_ifs) & 0x7f;
121 if (!reg) return IA64_ILLOP_FAULT;
122 if (reg >= sof + 32) return IA64_ILLOP_FAULT;
123 setreg(reg,value,0,regs); // FIXME: handle NATs later
124 return IA64_NO_FAULT;
125 }
127 #endif
129 void vcpu_init_regs (struct vcpu *v)
130 {
131 struct pt_regs *regs;
133 regs = vcpu_regs (v);
134 if (VMX_DOMAIN(v)) {
135 /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
136 /* Need to be expanded as macro */
137 regs->cr_ipsr = 0x501008826008;
138 } else {
139 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
140 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
141 regs->cr_ipsr &= ~(IA64_PSR_BITS_TO_CLEAR
142 | IA64_PSR_RI | IA64_PSR_IS);
143 // domain runs at PL2
144 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
145 }
146 regs->cr_ifs = 1UL << 63; /* or clear? */
147 regs->ar_fpsr = FPSR_DEFAULT;
149 if (VMX_DOMAIN(v)) {
150 vmx_init_all_rr(v);
151 /* Virtual processor context setup */
152 VCPU(v, vpsr) = IA64_PSR_BN;
153 VCPU(v, dcr) = 0;
154 } else {
155 init_all_rr(v);
156 regs->ar_rsc |= (2 << 2); /* force PL2/3 */
157 VCPU(v, banknum) = 1;
158 VCPU(v, metaphysical_mode) = 1;
159 VCPU(v, interrupt_mask_addr) =
160 (unsigned char *)v->domain->arch.shared_info_va +
161 INT_ENABLE_OFFSET(v);
162 VCPU(v, itv) = (1 << 16); /* timer vector masked */
163 }
165 v->arch.domain_itm_last = -1L;
166 }
168 /**************************************************************************
169 VCPU privileged application register access routines
170 **************************************************************************/
172 void vcpu_load_kernel_regs(VCPU *vcpu)
173 {
174 ia64_set_kr(0, VCPU(vcpu, krs[0]));
175 ia64_set_kr(1, VCPU(vcpu, krs[1]));
176 ia64_set_kr(2, VCPU(vcpu, krs[2]));
177 ia64_set_kr(3, VCPU(vcpu, krs[3]));
178 ia64_set_kr(4, VCPU(vcpu, krs[4]));
179 ia64_set_kr(5, VCPU(vcpu, krs[5]));
180 ia64_set_kr(6, VCPU(vcpu, krs[6]));
181 ia64_set_kr(7, VCPU(vcpu, krs[7]));
182 }
184 /* GCC 4.0.2 seems not to be able to suppress this call!. */
185 #define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
187 IA64FAULT vcpu_set_ar(VCPU *vcpu, UINT64 reg, UINT64 val)
188 {
189 if (reg == 44) return (vcpu_set_itc(vcpu,val));
190 else if (reg == 27) return (IA64_ILLOP_FAULT);
191 else if (reg == 24)
192 printf("warning: setting ar.eflg is a no-op; no IA-32 support\n");
193 else if (reg > 7) return (IA64_ILLOP_FAULT);
194 else {
195 PSCB(vcpu,krs[reg]) = val;
196 ia64_set_kr(reg,val);
197 }
198 return IA64_NO_FAULT;
199 }
201 IA64FAULT vcpu_get_ar(VCPU *vcpu, UINT64 reg, UINT64 *val)
202 {
203 if (reg == 24)
204 printf("warning: getting ar.eflg is a no-op; no IA-32 support\n");
205 else if (reg > 7) return (IA64_ILLOP_FAULT);
206 else *val = PSCB(vcpu,krs[reg]);
207 return IA64_NO_FAULT;
208 }
210 /**************************************************************************
211 VCPU processor status register access routines
212 **************************************************************************/
214 void vcpu_set_metaphysical_mode(VCPU *vcpu, BOOLEAN newmode)
215 {
216 /* only do something if mode changes */
217 if (!!newmode ^ !!PSCB(vcpu,metaphysical_mode)) {
218 PSCB(vcpu,metaphysical_mode) = newmode;
219 if (newmode) set_metaphysical_rr0();
220 else if (PSCB(vcpu,rrs[0]) != -1)
221 set_one_rr(0, PSCB(vcpu,rrs[0]));
222 }
223 }
225 IA64FAULT vcpu_reset_psr_dt(VCPU *vcpu)
226 {
227 vcpu_set_metaphysical_mode(vcpu,TRUE);
228 return IA64_NO_FAULT;
229 }
231 IA64FAULT vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
232 {
233 struct ia64_psr psr, imm, *ipsr;
234 REGS *regs = vcpu_regs(vcpu);
236 //PRIVOP_COUNT_ADDR(regs,_RSM);
237 // TODO: All of these bits need to be virtualized
238 // TODO: Only allowed for current vcpu
239 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
240 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
241 imm = *(struct ia64_psr *)&imm24;
242 // interrupt flag
243 if (imm.i)
244 vcpu->vcpu_info->evtchn_upcall_mask = 1;
245 if (imm.ic) PSCB(vcpu,interrupt_collection_enabled) = 0;
246 // interrupt collection flag
247 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
248 // just handle psr.up and psr.pp for now
249 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP
250 | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT
251 | IA64_PSR_DFL | IA64_PSR_DFH))
252 return (IA64_ILLOP_FAULT);
253 if (imm.dfh) ipsr->dfh = 0;
254 if (imm.dfl) ipsr->dfl = 0;
255 if (imm.pp) {
256 ipsr->pp = 1;
257 psr.pp = 1; // priv perf ctrs always enabled
258 PSCB(vcpu,vpsr_pp) = 0; // but fool the domain if it gets psr
259 }
260 if (imm.up) { ipsr->up = 0; psr.up = 0; }
261 if (imm.sp) { ipsr->sp = 0; psr.sp = 0; }
262 if (imm.be) ipsr->be = 0;
263 if (imm.dt) vcpu_set_metaphysical_mode(vcpu,TRUE);
264 __asm__ __volatile (";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
265 return IA64_NO_FAULT;
266 }
269 IA64FAULT vcpu_set_psr_dt(VCPU *vcpu)
270 {
271 vcpu_set_metaphysical_mode(vcpu,FALSE);
272 return IA64_NO_FAULT;
273 }
275 IA64FAULT vcpu_set_psr_i(VCPU *vcpu)
276 {
277 vcpu->vcpu_info->evtchn_upcall_mask = 0;
278 PSCB(vcpu,interrupt_collection_enabled) = 1;
279 return IA64_NO_FAULT;
280 }
282 IA64FAULT vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
283 {
284 struct ia64_psr psr, imm, *ipsr;
285 REGS *regs = vcpu_regs(vcpu);
286 UINT64 mask, enabling_interrupts = 0;
288 //PRIVOP_COUNT_ADDR(regs,_SSM);
289 // TODO: All of these bits need to be virtualized
290 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
291 imm = *(struct ia64_psr *)&imm24;
292 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
293 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
294 mask = IA64_PSR_PP|IA64_PSR_SP|IA64_PSR_I|IA64_PSR_IC|IA64_PSR_UM |
295 IA64_PSR_DT|IA64_PSR_DFL|IA64_PSR_DFH;
296 if (imm24 & ~mask) return (IA64_ILLOP_FAULT);
297 if (imm.dfh) ipsr->dfh = 1;
298 if (imm.dfl) ipsr->dfl = 1;
299 if (imm.pp) {
300 ipsr->pp = 1;
301 psr.pp = 1;
302 PSCB(vcpu,vpsr_pp) = 1;
303 }
304 if (imm.sp) { ipsr->sp = 1; psr.sp = 1; }
305 if (imm.i) {
306 if (vcpu->vcpu_info->evtchn_upcall_mask) {
307 //printf("vcpu_set_psr_sm: psr.ic 0->1\n");
308 enabling_interrupts = 1;
309 }
310 vcpu->vcpu_info->evtchn_upcall_mask = 0;
311 }
312 if (imm.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
313 // TODO: do this faster
314 if (imm.mfl) { ipsr->mfl = 1; psr.mfl = 1; }
315 if (imm.mfh) { ipsr->mfh = 1; psr.mfh = 1; }
316 if (imm.ac) { ipsr->ac = 1; psr.ac = 1; }
317 if (imm.up) { ipsr->up = 1; psr.up = 1; }
318 if (imm.be) {
319 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
320 return (IA64_ILLOP_FAULT);
321 }
322 if (imm.dt) vcpu_set_metaphysical_mode(vcpu,FALSE);
323 __asm__ __volatile (";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
324 if (enabling_interrupts &&
325 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
326 PSCB(vcpu,pending_interruption) = 1;
327 return IA64_NO_FAULT;
328 }
330 IA64FAULT vcpu_set_psr_l(VCPU *vcpu, UINT64 val)
331 {
332 struct ia64_psr psr, newpsr, *ipsr;
333 REGS *regs = vcpu_regs(vcpu);
334 UINT64 enabling_interrupts = 0;
336 // TODO: All of these bits need to be virtualized
337 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
338 newpsr = *(struct ia64_psr *)&val;
339 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
340 // just handle psr.up and psr.pp for now
341 //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP)) return (IA64_ILLOP_FAULT);
342 // however trying to set other bits can't be an error as it is in ssm
343 if (newpsr.dfh) ipsr->dfh = 1;
344 if (newpsr.dfl) ipsr->dfl = 1;
345 if (newpsr.pp) {
346 ipsr->pp = 1; psr.pp = 1;
347 PSCB(vcpu,vpsr_pp) = 1;
348 }
349 else {
350 ipsr->pp = 1; psr.pp = 1;
351 PSCB(vcpu,vpsr_pp) = 0;
352 }
353 if (newpsr.up) { ipsr->up = 1; psr.up = 1; }
354 if (newpsr.sp) { ipsr->sp = 1; psr.sp = 1; }
355 if (newpsr.i) {
356 if (vcpu->vcpu_info->evtchn_upcall_mask)
357 enabling_interrupts = 1;
358 vcpu->vcpu_info->evtchn_upcall_mask = 0;
359 }
360 if (newpsr.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
361 if (newpsr.mfl) { ipsr->mfl = 1; psr.mfl = 1; }
362 if (newpsr.mfh) { ipsr->mfh = 1; psr.mfh = 1; }
363 if (newpsr.ac) { ipsr->ac = 1; psr.ac = 1; }
364 if (newpsr.up) { ipsr->up = 1; psr.up = 1; }
365 if (newpsr.dt && newpsr.rt) vcpu_set_metaphysical_mode(vcpu,FALSE);
366 else vcpu_set_metaphysical_mode(vcpu,TRUE);
367 if (newpsr.be) {
368 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
369 return (IA64_ILLOP_FAULT);
370 }
371 if (enabling_interrupts &&
372 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
373 PSCB(vcpu,pending_interruption) = 1;
374 return IA64_NO_FAULT;
375 }
377 IA64FAULT vcpu_get_psr(VCPU *vcpu, UINT64 *pval)
378 {
379 REGS *regs = vcpu_regs(vcpu);
380 struct ia64_psr newpsr;
382 newpsr = *(struct ia64_psr *)&regs->cr_ipsr;
383 if (newpsr.cpl == 2) newpsr.cpl = 0;
384 if (!vcpu->vcpu_info->evtchn_upcall_mask) newpsr.i = 1;
385 else newpsr.i = 0;
386 if (PSCB(vcpu,interrupt_collection_enabled)) newpsr.ic = 1;
387 else newpsr.ic = 0;
388 if (PSCB(vcpu,metaphysical_mode)) newpsr.dt = 0;
389 else newpsr.dt = 1;
390 if (PSCB(vcpu,vpsr_pp)) newpsr.pp = 1;
391 else newpsr.pp = 0;
392 *pval = *(unsigned long *)&newpsr;
393 return IA64_NO_FAULT;
394 }
396 BOOLEAN vcpu_get_psr_ic(VCPU *vcpu)
397 {
398 return !!PSCB(vcpu,interrupt_collection_enabled);
399 }
401 BOOLEAN vcpu_get_psr_i(VCPU *vcpu)
402 {
403 return !vcpu->vcpu_info->evtchn_upcall_mask;
404 }
406 UINT64 vcpu_get_ipsr_int_state(VCPU *vcpu,UINT64 prevpsr)
407 {
408 UINT64 dcr = PSCBX(vcpu,dcr);
409 PSR psr;
411 //printf("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr);
412 psr.i64 = prevpsr;
413 psr.ia64_psr.be = 0; if (dcr & IA64_DCR_BE) psr.ia64_psr.be = 1;
414 psr.ia64_psr.pp = 0; if (dcr & IA64_DCR_PP) psr.ia64_psr.pp = 1;
415 psr.ia64_psr.ic = PSCB(vcpu,interrupt_collection_enabled);
416 psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
417 psr.ia64_psr.bn = PSCB(vcpu,banknum);
418 psr.ia64_psr.dt = 1; psr.ia64_psr.it = 1; psr.ia64_psr.rt = 1;
419 if (psr.ia64_psr.cpl == 2) psr.ia64_psr.cpl = 0; // !!!! fool domain
420 // psr.pk = 1;
421 //printf("returns 0x%016lx...\n",psr.i64);
422 return psr.i64;
423 }
425 /**************************************************************************
426 VCPU control register access routines
427 **************************************************************************/
429 IA64FAULT vcpu_get_dcr(VCPU *vcpu, UINT64 *pval)
430 {
431 //verbose("vcpu_get_dcr: called @%p\n",PSCB(vcpu,iip));
432 // Reads of cr.dcr on Xen always have the sign bit set, so
433 // a domain can differentiate whether it is running on SP or not
434 *pval = PSCBX(vcpu,dcr) | 0x8000000000000000L;
435 return (IA64_NO_FAULT);
436 }
438 IA64FAULT vcpu_get_iva(VCPU *vcpu, UINT64 *pval)
439 {
440 if(VMX_DOMAIN(vcpu)){
441 *pval = PSCB(vcpu,iva) & ~0x7fffL;
442 }else{
443 *pval = PSCBX(vcpu,iva) & ~0x7fffL;
444 }
445 return (IA64_NO_FAULT);
446 }
448 IA64FAULT vcpu_get_pta(VCPU *vcpu, UINT64 *pval)
449 {
450 *pval = PSCB(vcpu,pta);
451 return (IA64_NO_FAULT);
452 }
454 IA64FAULT vcpu_get_ipsr(VCPU *vcpu, UINT64 *pval)
455 {
456 //REGS *regs = vcpu_regs(vcpu);
457 //*pval = regs->cr_ipsr;
458 *pval = PSCB(vcpu,ipsr);
459 return (IA64_NO_FAULT);
460 }
462 IA64FAULT vcpu_get_isr(VCPU *vcpu, UINT64 *pval)
463 {
464 *pval = PSCB(vcpu,isr);
465 return (IA64_NO_FAULT);
466 }
468 IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT64 *pval)
469 {
470 //REGS *regs = vcpu_regs(vcpu);
471 //*pval = regs->cr_iip;
472 *pval = PSCB(vcpu,iip);
473 return (IA64_NO_FAULT);
474 }
476 IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval)
477 {
478 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_get_ifa);
479 *pval = PSCB(vcpu,ifa);
480 return (IA64_NO_FAULT);
481 }
483 unsigned long vcpu_get_rr_ps(VCPU *vcpu,UINT64 vadr)
484 {
485 ia64_rr rr;
487 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
488 return(rr.ps);
489 }
491 unsigned long vcpu_get_rr_rid(VCPU *vcpu,UINT64 vadr)
492 {
493 ia64_rr rr;
495 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
496 return(rr.rid);
497 }
499 unsigned long vcpu_get_itir_on_fault(VCPU *vcpu, UINT64 ifa)
500 {
501 ia64_rr rr;
503 rr.rrval = 0;
504 rr.ps = vcpu_get_rr_ps(vcpu,ifa);
505 rr.rid = vcpu_get_rr_rid(vcpu,ifa);
506 return (rr.rrval);
507 }
510 IA64FAULT vcpu_get_itir(VCPU *vcpu, UINT64 *pval)
511 {
512 UINT64 val = PSCB(vcpu,itir);
513 *pval = val;
514 return (IA64_NO_FAULT);
515 }
517 IA64FAULT vcpu_get_iipa(VCPU *vcpu, UINT64 *pval)
518 {
519 UINT64 val = PSCB(vcpu,iipa);
520 // SP entry code does not save iipa yet nor does it get
521 // properly delivered in the pscb
522 // printf("*** vcpu_get_iipa: cr.iipa not fully implemented yet!!\n");
523 *pval = val;
524 return (IA64_NO_FAULT);
525 }
527 IA64FAULT vcpu_get_ifs(VCPU *vcpu, UINT64 *pval)
528 {
529 //PSCB(vcpu,ifs) = PSCB(vcpu)->regs.cr_ifs;
530 //*pval = PSCB(vcpu,regs).cr_ifs;
531 *pval = PSCB(vcpu,ifs);
532 PSCB(vcpu,incomplete_regframe) = 0;
533 return (IA64_NO_FAULT);
534 }
536 IA64FAULT vcpu_get_iim(VCPU *vcpu, UINT64 *pval)
537 {
538 UINT64 val = PSCB(vcpu,iim);
539 *pval = val;
540 return (IA64_NO_FAULT);
541 }
543 IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval)
544 {
545 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_thash);
546 *pval = PSCB(vcpu,iha);
547 return (IA64_NO_FAULT);
548 }
550 IA64FAULT vcpu_set_dcr(VCPU *vcpu, UINT64 val)
551 {
552 // Reads of cr.dcr on SP always have the sign bit set, so
553 // a domain can differentiate whether it is running on SP or not
554 // Thus, writes of DCR should ignore the sign bit
555 //verbose("vcpu_set_dcr: called\n");
556 PSCBX(vcpu,dcr) = val & ~0x8000000000000000L;
557 return (IA64_NO_FAULT);
558 }
560 IA64FAULT vcpu_set_iva(VCPU *vcpu, UINT64 val)
561 {
562 if(VMX_DOMAIN(vcpu)){
563 PSCB(vcpu,iva) = val & ~0x7fffL;
564 }else{
565 PSCBX(vcpu,iva) = val & ~0x7fffL;
566 }
567 return (IA64_NO_FAULT);
568 }
570 IA64FAULT vcpu_set_pta(VCPU *vcpu, UINT64 val)
571 {
572 if (val & IA64_PTA_LFMT) {
573 printf("*** No support for VHPT long format yet!!\n");
574 return (IA64_ILLOP_FAULT);
575 }
576 if (val & (0x3f<<9)) /* reserved fields */ return IA64_RSVDREG_FAULT;
577 if (val & 2) /* reserved fields */ return IA64_RSVDREG_FAULT;
578 PSCB(vcpu,pta) = val;
579 return IA64_NO_FAULT;
580 }
582 IA64FAULT vcpu_set_ipsr(VCPU *vcpu, UINT64 val)
583 {
584 PSCB(vcpu,ipsr) = val;
585 return IA64_NO_FAULT;
586 }
588 IA64FAULT vcpu_set_isr(VCPU *vcpu, UINT64 val)
589 {
590 PSCB(vcpu,isr) = val;
591 return IA64_NO_FAULT;
592 }
594 IA64FAULT vcpu_set_iip(VCPU *vcpu, UINT64 val)
595 {
596 PSCB(vcpu,iip) = val;
597 return IA64_NO_FAULT;
598 }
600 IA64FAULT vcpu_increment_iip(VCPU *vcpu)
601 {
602 REGS *regs = vcpu_regs(vcpu);
603 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
604 if (ipsr->ri == 2) { ipsr->ri=0; regs->cr_iip += 16; }
605 else ipsr->ri++;
606 return (IA64_NO_FAULT);
607 }
609 IA64FAULT vcpu_set_ifa(VCPU *vcpu, UINT64 val)
610 {
611 PSCB(vcpu,ifa) = val;
612 return IA64_NO_FAULT;
613 }
615 IA64FAULT vcpu_set_itir(VCPU *vcpu, UINT64 val)
616 {
617 PSCB(vcpu,itir) = val;
618 return IA64_NO_FAULT;
619 }
621 IA64FAULT vcpu_set_iipa(VCPU *vcpu, UINT64 val)
622 {
623 // SP entry code does not save iipa yet nor does it get
624 // properly delivered in the pscb
625 // printf("*** vcpu_set_iipa: cr.iipa not fully implemented yet!!\n");
626 PSCB(vcpu,iipa) = val;
627 return IA64_NO_FAULT;
628 }
630 IA64FAULT vcpu_set_ifs(VCPU *vcpu, UINT64 val)
631 {
632 //REGS *regs = vcpu_regs(vcpu);
633 PSCB(vcpu,ifs) = val;
634 return IA64_NO_FAULT;
635 }
637 IA64FAULT vcpu_set_iim(VCPU *vcpu, UINT64 val)
638 {
639 PSCB(vcpu,iim) = val;
640 return IA64_NO_FAULT;
641 }
643 IA64FAULT vcpu_set_iha(VCPU *vcpu, UINT64 val)
644 {
645 PSCB(vcpu,iha) = val;
646 return IA64_NO_FAULT;
647 }
649 /**************************************************************************
650 VCPU interrupt control register access routines
651 **************************************************************************/
653 void vcpu_pend_unspecified_interrupt(VCPU *vcpu)
654 {
655 PSCB(vcpu,pending_interruption) = 1;
656 }
658 void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
659 {
660 if (vector & ~0xff) {
661 printf("vcpu_pend_interrupt: bad vector\n");
662 return;
663 }
665 if (vcpu->arch.event_callback_ip) {
666 printf("Deprecated interface. Move to new event based solution\n");
667 return;
668 }
670 if ( VMX_DOMAIN(vcpu) ) {
671 set_bit(vector,VCPU(vcpu,irr));
672 } else {
673 set_bit(vector,PSCBX(vcpu,irr));
674 PSCB(vcpu,pending_interruption) = 1;
675 }
676 }
678 #define IA64_TPR_MMI 0x10000
679 #define IA64_TPR_MIC 0x000f0
681 /* checks to see if a VCPU has any unmasked pending interrupts
682 * if so, returns the highest, else returns SPURIOUS_VECTOR */
683 /* NOTE: Since this gets called from vcpu_get_ivr() and the
684 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
685 * this routine also ignores pscb.interrupt_delivery_enabled
686 * and this must be checked independently; see vcpu_deliverable interrupts() */
687 UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
688 {
689 UINT64 *p, *r, bits, bitnum, mask, i, vector;
691 if (vcpu->arch.event_callback_ip)
692 return SPURIOUS_VECTOR;
694 /* Always check pending event, since guest may just ack the
695 * event injection without handle. Later guest may throw out
696 * the event itself.
697 */
698 check_start:
699 if (event_pending(vcpu) &&
700 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
701 &PSCBX(vcpu, insvc[0])))
702 vcpu_pend_interrupt(vcpu, vcpu->domain->shared_info->arch.evtchn_vector);
704 p = &PSCBX(vcpu,irr[3]);
705 r = &PSCBX(vcpu,insvc[3]);
706 for (i = 3; ; p--, r--, i--) {
707 bits = *p ;
708 if (bits) break; // got a potential interrupt
709 if (*r) {
710 // nothing in this word which is pending+inservice
711 // but there is one inservice which masks lower
712 return SPURIOUS_VECTOR;
713 }
714 if (i == 0) {
715 // checked all bits... nothing pending+inservice
716 return SPURIOUS_VECTOR;
717 }
718 }
719 // have a pending,deliverable interrupt... see if it is masked
720 bitnum = ia64_fls(bits);
721 //printf("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
722 vector = bitnum+(i*64);
723 mask = 1L << bitnum;
724 /* sanity check for guest timer interrupt */
725 if (vector == (PSCB(vcpu,itv) & 0xff)) {
726 uint64_t now = ia64_get_itc();
727 if (now < PSCBX(vcpu,domain_itm)) {
728 // printk("Ooops, pending guest timer before its due\n");
729 PSCBX(vcpu,irr[i]) &= ~mask;
730 goto check_start;
731 }
732 }
733 //printf("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
734 if (*r >= mask) {
735 // masked by equal inservice
736 //printf("but masked by equal inservice\n");
737 return SPURIOUS_VECTOR;
738 }
739 if (PSCB(vcpu,tpr) & IA64_TPR_MMI) {
740 // tpr.mmi is set
741 //printf("but masked by tpr.mmi\n");
742 return SPURIOUS_VECTOR;
743 }
744 if (((PSCB(vcpu,tpr) & IA64_TPR_MIC) + 15) >= vector) {
745 //tpr.mic masks class
746 //printf("but masked by tpr.mic\n");
747 return SPURIOUS_VECTOR;
748 }
750 //printf("returned to caller\n");
751 return vector;
752 }
754 UINT64 vcpu_deliverable_interrupts(VCPU *vcpu)
755 {
756 return (vcpu_get_psr_i(vcpu) &&
757 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
758 }
760 UINT64 vcpu_deliverable_timer(VCPU *vcpu)
761 {
762 return (vcpu_get_psr_i(vcpu) &&
763 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu,itv));
764 }
766 IA64FAULT vcpu_get_lid(VCPU *vcpu, UINT64 *pval)
767 {
768 /* Use EID=0, ID=vcpu_id. */
769 *pval = vcpu->vcpu_id << 24;
770 return IA64_NO_FAULT;
771 }
773 IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
774 {
775 int i;
776 UINT64 vector, mask;
778 #define HEARTBEAT_FREQ 16 // period in seconds
779 #ifdef HEARTBEAT_FREQ
780 #define N_DOMS 16 // period in seconds
781 #if 0
782 static long count[N_DOMS] = { 0 };
783 #endif
784 static long nonclockcount[N_DOMS] = { 0 };
785 unsigned domid = vcpu->domain->domain_id;
786 #endif
787 #ifdef IRQ_DEBUG
788 static char firstivr = 1;
789 static char firsttime[256];
790 if (firstivr) {
791 int i;
792 for (i=0;i<256;i++) firsttime[i]=1;
793 firstivr=0;
794 }
795 #endif
797 vector = vcpu_check_pending_interrupts(vcpu);
798 if (vector == SPURIOUS_VECTOR) {
799 PSCB(vcpu,pending_interruption) = 0;
800 *pval = vector;
801 return IA64_NO_FAULT;
802 }
803 #ifdef HEARTBEAT_FREQ
804 if (domid >= N_DOMS) domid = N_DOMS-1;
805 #if 0
806 if (vector == (PSCB(vcpu,itv) & 0xff)) {
807 if (!(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) {
808 printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
809 domid, count[domid], nonclockcount[domid]);
810 //count[domid] = 0;
811 //dump_runq();
812 }
813 }
814 #endif
815 else nonclockcount[domid]++;
816 #endif
817 // now have an unmasked, pending, deliverable vector!
818 // getting ivr has "side effects"
819 #ifdef IRQ_DEBUG
820 if (firsttime[vector]) {
821 printf("*** First get_ivr on vector=%lu,itc=%lx\n",
822 vector,ia64_get_itc());
823 firsttime[vector]=0;
824 }
825 #endif
826 /* if delivering a timer interrupt, remember domain_itm, which
827 * needs to be done before clearing irr
828 */
829 if (vector == (PSCB(vcpu,itv) & 0xff)) {
830 PSCBX(vcpu,domain_itm_last) = PSCBX(vcpu,domain_itm);
831 }
833 i = vector >> 6;
834 mask = 1L << (vector & 0x3f);
835 //printf("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
836 PSCBX(vcpu,insvc[i]) |= mask;
837 PSCBX(vcpu,irr[i]) &= ~mask;
838 //PSCB(vcpu,pending_interruption)--;
839 *pval = vector;
840 return IA64_NO_FAULT;
841 }
843 IA64FAULT vcpu_get_tpr(VCPU *vcpu, UINT64 *pval)
844 {
845 *pval = PSCB(vcpu,tpr);
846 return (IA64_NO_FAULT);
847 }
849 IA64FAULT vcpu_get_eoi(VCPU *vcpu, UINT64 *pval)
850 {
851 *pval = 0L; // reads of eoi always return 0
852 return (IA64_NO_FAULT);
853 }
855 IA64FAULT vcpu_get_irr0(VCPU *vcpu, UINT64 *pval)
856 {
857 *pval = PSCBX(vcpu, irr[0]);
858 return (IA64_NO_FAULT);
859 }
861 IA64FAULT vcpu_get_irr1(VCPU *vcpu, UINT64 *pval)
862 {
863 *pval = PSCBX(vcpu, irr[1]);
864 return (IA64_NO_FAULT);
865 }
867 IA64FAULT vcpu_get_irr2(VCPU *vcpu, UINT64 *pval)
868 {
869 *pval = PSCBX(vcpu, irr[2]);
870 return (IA64_NO_FAULT);
871 }
873 IA64FAULT vcpu_get_irr3(VCPU *vcpu, UINT64 *pval)
874 {
875 *pval = PSCBX(vcpu, irr[3]);
876 return (IA64_NO_FAULT);
877 }
879 IA64FAULT vcpu_get_itv(VCPU *vcpu, UINT64 *pval)
880 {
881 *pval = PSCB(vcpu,itv);
882 return (IA64_NO_FAULT);
883 }
885 IA64FAULT vcpu_get_pmv(VCPU *vcpu, UINT64 *pval)
886 {
887 *pval = PSCB(vcpu,pmv);
888 return (IA64_NO_FAULT);
889 }
891 IA64FAULT vcpu_get_cmcv(VCPU *vcpu, UINT64 *pval)
892 {
893 *pval = PSCB(vcpu,cmcv);
894 return (IA64_NO_FAULT);
895 }
897 IA64FAULT vcpu_get_lrr0(VCPU *vcpu, UINT64 *pval)
898 {
899 // fix this when setting values other than m-bit is supported
900 printf("vcpu_get_lrr0: Unmasked interrupts unsupported\n");
901 *pval = (1L << 16);
902 return (IA64_NO_FAULT);
903 }
905 IA64FAULT vcpu_get_lrr1(VCPU *vcpu, UINT64 *pval)
906 {
907 // fix this when setting values other than m-bit is supported
908 printf("vcpu_get_lrr1: Unmasked interrupts unsupported\n");
909 *pval = (1L << 16);
910 return (IA64_NO_FAULT);
911 }
913 IA64FAULT vcpu_set_lid(VCPU *vcpu, UINT64 val)
914 {
915 printf("vcpu_set_lid: Setting cr.lid is unsupported\n");
916 return (IA64_ILLOP_FAULT);
917 }
919 IA64FAULT vcpu_set_tpr(VCPU *vcpu, UINT64 val)
920 {
921 if (val & 0xff00) return IA64_RSVDREG_FAULT;
922 PSCB(vcpu,tpr) = val;
923 /* This can unmask interrupts. */
924 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
925 PSCB(vcpu,pending_interruption) = 1;
926 return (IA64_NO_FAULT);
927 }
929 IA64FAULT vcpu_set_eoi(VCPU *vcpu, UINT64 val)
930 {
931 UINT64 *p, bits, vec, bitnum;
932 int i;
934 p = &PSCBX(vcpu,insvc[3]);
935 for (i = 3; (i >= 0) && !(bits = *p); i--, p--);
936 if (i < 0) {
937 printf("Trying to EOI interrupt when none are in-service.\n");
938 return IA64_NO_FAULT;
939 }
940 bitnum = ia64_fls(bits);
941 vec = bitnum + (i*64);
942 /* clear the correct bit */
943 bits &= ~(1L << bitnum);
944 *p = bits;
945 /* clearing an eoi bit may unmask another pending interrupt... */
946 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
947 // worry about this later... Linux only calls eoi
948 // with interrupts disabled
949 printf("Trying to EOI interrupt with interrupts enabled\n");
950 }
951 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
952 PSCB(vcpu,pending_interruption) = 1;
953 //printf("YYYYY vcpu_set_eoi: Successful\n");
954 return (IA64_NO_FAULT);
955 }
957 IA64FAULT vcpu_set_lrr0(VCPU *vcpu, UINT64 val)
958 {
959 if (!(val & (1L << 16))) {
960 printf("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
961 return (IA64_ILLOP_FAULT);
962 }
963 // no place to save this state but nothing to do anyway
964 return (IA64_NO_FAULT);
965 }
967 IA64FAULT vcpu_set_lrr1(VCPU *vcpu, UINT64 val)
968 {
969 if (!(val & (1L << 16))) {
970 printf("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
971 return (IA64_ILLOP_FAULT);
972 }
973 // no place to save this state but nothing to do anyway
974 return (IA64_NO_FAULT);
975 }
977 IA64FAULT vcpu_set_itv(VCPU *vcpu, UINT64 val)
978 {
979 /* Check reserved fields. */
980 if (val & 0xef00)
981 return (IA64_ILLOP_FAULT);
982 PSCB(vcpu,itv) = val;
983 if (val & 0x10000) {
984 /* Disable itm. */
985 PSCBX(vcpu,domain_itm) = 0;
986 }
987 else vcpu_set_next_timer(vcpu);
988 return (IA64_NO_FAULT);
989 }
991 IA64FAULT vcpu_set_pmv(VCPU *vcpu, UINT64 val)
992 {
993 if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT;
994 PSCB(vcpu,pmv) = val;
995 return (IA64_NO_FAULT);
996 }
998 IA64FAULT vcpu_set_cmcv(VCPU *vcpu, UINT64 val)
999 {
1000 if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT;
1001 PSCB(vcpu,cmcv) = val;
1002 return (IA64_NO_FAULT);
1005 /**************************************************************************
1006 VCPU temporary register access routines
1007 **************************************************************************/
1008 UINT64 vcpu_get_tmp(VCPU *vcpu, UINT64 index)
1010 if (index > 7) return 0;
1011 return PSCB(vcpu,tmp[index]);
1014 void vcpu_set_tmp(VCPU *vcpu, UINT64 index, UINT64 val)
1016 if (index <= 7) PSCB(vcpu,tmp[index]) = val;
1019 /**************************************************************************
1020 Interval timer routines
1021 **************************************************************************/
1023 BOOLEAN vcpu_timer_disabled(VCPU *vcpu)
1025 UINT64 itv = PSCB(vcpu,itv);
1026 return(!itv || !!(itv & 0x10000));
1029 BOOLEAN vcpu_timer_inservice(VCPU *vcpu)
1031 UINT64 itv = PSCB(vcpu,itv);
1032 return (test_bit(itv, PSCBX(vcpu,insvc)));
1035 BOOLEAN vcpu_timer_expired(VCPU *vcpu)
1037 unsigned long domain_itm = PSCBX(vcpu,domain_itm);
1038 unsigned long now = ia64_get_itc();
1040 if (!domain_itm) return FALSE;
1041 if (now < domain_itm) return FALSE;
1042 if (vcpu_timer_disabled(vcpu)) return FALSE;
1043 return TRUE;
1046 void vcpu_safe_set_itm(unsigned long val)
1048 unsigned long epsilon = 100;
1049 unsigned long flags;
1050 UINT64 now = ia64_get_itc();
1052 local_irq_save(flags);
1053 while (1) {
1054 //printf("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1055 ia64_set_itm(val);
1056 if (val > (now = ia64_get_itc())) break;
1057 val = now + epsilon;
1058 epsilon <<= 1;
1060 local_irq_restore(flags);
1063 void vcpu_set_next_timer(VCPU *vcpu)
1065 UINT64 d = PSCBX(vcpu,domain_itm);
1066 //UINT64 s = PSCBX(vcpu,xen_itm);
1067 UINT64 s = local_cpu_data->itm_next;
1068 UINT64 now = ia64_get_itc();
1070 /* gloss over the wraparound problem for now... we know it exists
1071 * but it doesn't matter right now */
1073 if (is_idle_domain(vcpu->domain)) {
1074 // printf("****** vcpu_set_next_timer called during idle!!\n");
1075 vcpu_safe_set_itm(s);
1076 return;
1078 //s = PSCBX(vcpu,xen_itm);
1079 if (d && (d > now) && (d < s)) {
1080 vcpu_safe_set_itm(d);
1081 //using_domain_as_itm++;
1083 else {
1084 vcpu_safe_set_itm(s);
1085 //using_xen_as_itm++;
1089 IA64FAULT vcpu_set_itm(VCPU *vcpu, UINT64 val)
1091 //UINT now = ia64_get_itc();
1093 //if (val < now) val = now + 1000;
1094 //printf("*** vcpu_set_itm: called with %lx\n",val);
1095 PSCBX(vcpu,domain_itm) = val;
1096 vcpu_set_next_timer(vcpu);
1097 return (IA64_NO_FAULT);
1100 IA64FAULT vcpu_set_itc(VCPU *vcpu, UINT64 val)
1102 #define DISALLOW_SETTING_ITC_FOR_NOW
1103 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1104 static int did_print;
1105 if (!did_print) {
1106 printf("vcpu_set_itc: Setting ar.itc is currently disabled\n");
1107 printf("(this message is only displayed one)\n");
1108 did_print = 1;
1110 #else
1111 UINT64 oldnow = ia64_get_itc();
1112 UINT64 olditm = PSCBX(vcpu,domain_itm);
1113 unsigned long d = olditm - oldnow;
1114 unsigned long x = local_cpu_data->itm_next - oldnow;
1116 UINT64 newnow = val, min_delta;
1118 local_irq_disable();
1119 if (olditm) {
1120 printf("**** vcpu_set_itc(%lx): vitm changed to %lx\n",val,newnow+d);
1121 PSCBX(vcpu,domain_itm) = newnow + d;
1123 local_cpu_data->itm_next = newnow + x;
1124 d = PSCBX(vcpu,domain_itm);
1125 x = local_cpu_data->itm_next;
1127 ia64_set_itc(newnow);
1128 if (d && (d > newnow) && (d < x)) {
1129 vcpu_safe_set_itm(d);
1130 //using_domain_as_itm++;
1132 else {
1133 vcpu_safe_set_itm(x);
1134 //using_xen_as_itm++;
1136 local_irq_enable();
1137 #endif
1138 return (IA64_NO_FAULT);
1141 IA64FAULT vcpu_get_itm(VCPU *vcpu, UINT64 *pval)
1143 //FIXME: Implement this
1144 printf("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1145 return (IA64_NO_FAULT);
1146 //return (IA64_ILLOP_FAULT);
1149 IA64FAULT vcpu_get_itc(VCPU *vcpu, UINT64 *pval)
1151 //TODO: Implement this
1152 printf("vcpu_get_itc: Getting ar.itc is unsupported\n");
1153 return (IA64_ILLOP_FAULT);
1156 void vcpu_pend_timer(VCPU *vcpu)
1158 UINT64 itv = PSCB(vcpu,itv) & 0xff;
1160 if (vcpu_timer_disabled(vcpu)) return;
1161 //if (vcpu_timer_inservice(vcpu)) return;
1162 if (PSCBX(vcpu,domain_itm_last) == PSCBX(vcpu,domain_itm)) {
1163 // already delivered an interrupt for this so
1164 // don't deliver another
1165 return;
1167 if (vcpu->arch.event_callback_ip) {
1168 /* A small window may occur when injecting vIRQ while related
1169 * handler has not been registered. Don't fire in such case.
1170 */
1171 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1172 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1173 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1175 } else
1176 vcpu_pend_interrupt(vcpu, itv);
1179 // returns true if ready to deliver a timer interrupt too early
1180 UINT64 vcpu_timer_pending_early(VCPU *vcpu)
1182 UINT64 now = ia64_get_itc();
1183 UINT64 itm = PSCBX(vcpu,domain_itm);
1185 if (vcpu_timer_disabled(vcpu)) return 0;
1186 if (!itm) return 0;
1187 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1190 /**************************************************************************
1191 Privileged operation emulation routines
1192 **************************************************************************/
1194 static void
1195 vcpu_force_tlb_miss(VCPU* vcpu, UINT64 ifa)
1197 PSCB(vcpu, ifa) = ifa;
1198 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1199 vcpu_thash(current, ifa, &PSCB(current, iha));
1202 IA64FAULT vcpu_force_inst_miss(VCPU *vcpu, UINT64 ifa)
1204 vcpu_force_tlb_miss(vcpu, ifa);
1205 return (vcpu_get_rr_ve(vcpu, ifa)? IA64_INST_TLB_VECTOR: IA64_ALT_INST_TLB_VECTOR);
1208 IA64FAULT vcpu_force_data_miss(VCPU *vcpu, UINT64 ifa)
1210 vcpu_force_tlb_miss(vcpu, ifa);
1211 return (vcpu_get_rr_ve(vcpu, ifa)? IA64_DATA_TLB_VECTOR: IA64_ALT_DATA_TLB_VECTOR);
1214 IA64FAULT vcpu_rfi(VCPU *vcpu)
1216 // TODO: Only allowed for current vcpu
1217 PSR psr;
1218 UINT64 int_enable, regspsr = 0;
1219 UINT64 ifs;
1220 REGS *regs = vcpu_regs(vcpu);
1221 extern void dorfirfi(void);
1223 psr.i64 = PSCB(vcpu,ipsr);
1224 if (psr.ia64_psr.cpl < 3) psr.ia64_psr.cpl = 2;
1225 int_enable = psr.ia64_psr.i;
1226 if (psr.ia64_psr.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
1227 if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it) vcpu_set_metaphysical_mode(vcpu,FALSE);
1228 else vcpu_set_metaphysical_mode(vcpu,TRUE);
1229 psr.ia64_psr.ic = 1; psr.ia64_psr.i = 1;
1230 psr.ia64_psr.dt = 1; psr.ia64_psr.rt = 1; psr.ia64_psr.it = 1;
1231 psr.ia64_psr.bn = 1;
1232 //psr.pk = 1; // checking pkeys shouldn't be a problem but seems broken
1233 if (psr.ia64_psr.be) {
1234 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
1235 return (IA64_ILLOP_FAULT);
1237 PSCB(vcpu,incomplete_regframe) = 0; // is this necessary?
1238 ifs = PSCB(vcpu,ifs);
1239 //if ((ifs & regs->cr_ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
1240 //if ((ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
1241 if (ifs & regs->cr_ifs & 0x8000000000000000L) {
1242 // TODO: validate PSCB(vcpu,iip)
1243 // TODO: PSCB(vcpu,ipsr) = psr;
1244 PSCB(vcpu,ipsr) = psr.i64;
1245 // now set up the trampoline
1246 regs->cr_iip = *(unsigned long *)dorfirfi; // function pointer!!
1247 __asm__ __volatile ("mov %0=psr;;":"=r"(regspsr)::"memory");
1248 regs->cr_ipsr = regspsr & ~(IA64_PSR_I | IA64_PSR_IC | IA64_PSR_BN);
1250 else {
1251 regs->cr_ipsr = psr.i64;
1252 regs->cr_iip = PSCB(vcpu,iip);
1254 PSCB(vcpu,interrupt_collection_enabled) = 1;
1255 vcpu_bsw1(vcpu);
1256 vcpu->vcpu_info->evtchn_upcall_mask = !int_enable;
1257 return (IA64_NO_FAULT);
1260 IA64FAULT vcpu_cover(VCPU *vcpu)
1262 // TODO: Only allowed for current vcpu
1263 REGS *regs = vcpu_regs(vcpu);
1265 if (!PSCB(vcpu,interrupt_collection_enabled)) {
1266 if (!PSCB(vcpu,incomplete_regframe))
1267 PSCB(vcpu,ifs) = regs->cr_ifs;
1268 else PSCB(vcpu,incomplete_regframe) = 0;
1270 regs->cr_ifs = 0;
1271 return (IA64_NO_FAULT);
1274 IA64FAULT vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
1276 UINT64 pta = PSCB(vcpu,pta);
1277 UINT64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1278 UINT64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT)-1);
1279 UINT64 Mask = (1L << pta_sz) - 1;
1280 UINT64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1281 UINT64 compMask_60_15 = ~Mask_60_15;
1282 UINT64 rr_ps = vcpu_get_rr_ps(vcpu,vadr);
1283 UINT64 VHPT_offset = (vadr >> rr_ps) << 3;
1284 UINT64 VHPT_addr1 = vadr & 0xe000000000000000L;
1285 UINT64 VHPT_addr2a =
1286 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1287 UINT64 VHPT_addr2b =
1288 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1289 UINT64 VHPT_addr3 = VHPT_offset & 0x7fff;
1290 UINT64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1291 VHPT_addr3;
1293 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1294 *pval = VHPT_addr;
1295 return (IA64_NO_FAULT);
1298 IA64FAULT vcpu_ttag(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
1300 printf("vcpu_ttag: ttag instruction unsupported\n");
1301 return (IA64_ILLOP_FAULT);
1304 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1306 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1307 static inline int range_overlap (u64 b1, u64 e1, u64 b2, u64 e2)
1309 return (b1 <= e2) && (e1 >= b2);
1312 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1313 Note: LSBs of base inside page_size are ignored. */
1314 static inline void
1315 check_xen_space_overlap (const char *func, u64 base, u64 page_size)
1317 /* Overlaps can occur only in region 7.
1318 (This is an optimization to bypass all the checks). */
1319 if (REGION_NUMBER(base) != 7)
1320 return;
1322 /* Mask LSBs of base. */
1323 base &= ~(page_size - 1);
1325 /* FIXME: ideally an MCA should be generated... */
1326 if (range_overlap (HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
1327 base, base + page_size)
1328 || range_overlap(current->domain->arch.shared_info_va,
1329 current->domain->arch.shared_info_va
1330 + XSI_SIZE + XMAPPEDREGS_SIZE,
1331 base, base + page_size))
1332 panic_domain (NULL, "%s on Xen virtual space (%lx)\n",
1333 func, base);
1336 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1337 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY *trp, UINT64 ifa, UINT64 rid)
1339 return trp->rid == rid
1340 && ifa >= trp->vadr
1341 && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1344 static inline int vcpu_match_tr_entry(TR_ENTRY *trp, UINT64 ifa, UINT64 rid)
1346 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1349 static inline int
1350 vcpu_match_tr_entry_range(TR_ENTRY *trp, UINT64 rid, u64 b, u64 e)
1352 return trp->rid == rid
1353 && trp->pte.p
1354 && range_overlap (b, e,
1355 trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1359 static TR_ENTRY*
1360 vcpu_tr_lookup(VCPU* vcpu, unsigned long va, UINT64 rid, BOOLEAN is_data)
1362 unsigned char* regions;
1363 TR_ENTRY *trp;
1364 int tr_max;
1365 int i;
1367 if (is_data) {
1368 // data
1369 regions = &vcpu->arch.dtr_regions;
1370 trp = vcpu->arch.dtrs;
1371 tr_max = sizeof(vcpu->arch.dtrs)/sizeof(vcpu->arch.dtrs[0]);
1372 } else {
1373 // instruction
1374 regions = &vcpu->arch.itr_regions;
1375 trp = vcpu->arch.itrs;
1376 tr_max = sizeof(vcpu->arch.itrs)/sizeof(vcpu->arch.itrs[0]);
1379 if (!vcpu_quick_region_check(*regions, va)) {
1380 return NULL;
1382 for (i = 0; i < tr_max; i++, trp++) {
1383 if (vcpu_match_tr_entry(trp, va, rid)) {
1384 return trp;
1387 return NULL;
1390 // return value
1391 // 0: failure
1392 // 1: success
1393 int
1394 vcpu_get_domain_bundle(VCPU* vcpu, REGS* regs, UINT64 gip, IA64_BUNDLE* bundle)
1396 UINT64 gpip;// guest pseudo phyiscal ip
1397 unsigned long vaddr;
1398 struct page_info* page;
1400 again:
1401 #if 0
1402 // Currently xen doesn't track psr.it bits.
1403 // it assumes always psr.it = 1.
1404 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1405 gpip = gip;
1406 } else
1407 #endif
1409 unsigned long region = REGION_NUMBER(gip);
1410 unsigned long rr = PSCB(vcpu, rrs)[region];
1411 unsigned long rid = rr & RR_RID_MASK;
1412 BOOLEAN swap_rr0;
1413 TR_ENTRY* trp;
1415 // vcpu->arch.{i, d}tlb are volatile,
1416 // copy its value to the variable, tr, before use.
1417 TR_ENTRY tr;
1419 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1420 if (trp != NULL) {
1421 tr = *trp;
1422 goto found;
1424 // When it failed to get a bundle, itlb miss is reflected.
1425 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1426 tr = PSCBX(vcpu, itlb);
1427 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1428 //DPRINTK("%s gip 0x%lx gpip 0x%lx\n", __func__, gip, gpip);
1429 goto found;
1431 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1432 if (trp != NULL) {
1433 tr = *trp;
1434 goto found;
1436 #if 0
1437 tr = PSCBX(vcpu, dtlb);
1438 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1439 goto found;
1441 #endif
1443 // try to access gip with guest virtual address
1444 // This may cause tlb miss. see vcpu_translate(). Be careful!
1445 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1446 if (swap_rr0) {
1447 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
1449 *bundle = __get_domain_bundle(gip);
1450 if (swap_rr0) {
1451 set_metaphysical_rr0();
1453 if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
1454 DPRINTK("%s gip 0x%lx\n", __func__, gip);
1455 return 0;
1457 return 1;
1459 found:
1460 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1461 (gip & ((1 << tr.ps) - 1));
1464 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1465 page = virt_to_page(vaddr);
1466 if (get_page(page, vcpu->domain) == 0) {
1467 if (page_get_owner(page) != vcpu->domain) {
1468 // This page might be a page granted by another
1469 // domain.
1470 panic_domain(regs,
1471 "domain tries to execute foreign domain "
1472 "page which might be mapped by grant "
1473 "table.\n");
1475 goto again;
1477 *bundle = *((IA64_BUNDLE*)vaddr);
1478 put_page(page);
1479 return 1;
1482 IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pteval, UINT64 *itir, UINT64 *iha)
1484 unsigned long region = address >> 61;
1485 unsigned long pta, rid, rr;
1486 union pte_flags pte;
1487 TR_ENTRY *trp;
1489 if (PSCB(vcpu,metaphysical_mode) && !(!is_data && region)) {
1490 // dom0 may generate an uncacheable physical address (msb=1)
1491 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1492 // FIXME: This seems to happen even though it shouldn't. Need to track
1493 // this down, but since it has been apparently harmless, just flag it for now
1494 // panic_domain(vcpu_regs(vcpu),
1496 /*
1497 * Guest may execute itc.d and rfi with psr.dt=0
1498 * When VMM try to fetch opcode, tlb miss may happen,
1499 * At this time PSCB(vcpu,metaphysical_mode)=1,
1500 * region=5,VMM need to handle this tlb miss as if
1501 * PSCB(vcpu,metaphysical_mode)=0
1502 */
1503 printk("vcpu_translate: bad physical address: 0x%lx at %lx\n",
1504 address, vcpu_regs (vcpu)->cr_iip);
1506 } else {
1507 *pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS |
1508 _PAGE_PL_2 | _PAGE_AR_RWX;
1509 *itir = PAGE_SHIFT << 2;
1510 perfc_incrc(phys_translate);
1511 return IA64_NO_FAULT;
1514 else if (!region && warn_region0_address) {
1515 REGS *regs = vcpu_regs(vcpu);
1516 unsigned long viip = PSCB(vcpu,iip);
1517 unsigned long vipsr = PSCB(vcpu,ipsr);
1518 unsigned long iip = regs->cr_iip;
1519 unsigned long ipsr = regs->cr_ipsr;
1520 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1521 address, viip, vipsr, iip, ipsr);
1524 rr = PSCB(vcpu,rrs)[region];
1525 rid = rr & RR_RID_MASK;
1526 if (is_data) {
1527 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1528 if (trp != NULL) {
1529 *pteval = trp->pte.val;
1530 *itir = trp->itir;
1531 perfc_incrc(tr_translate);
1532 return IA64_NO_FAULT;
1535 // FIXME?: check itr's for data accesses too, else bad things happen?
1536 /* else */ {
1537 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1538 if (trp != NULL) {
1539 *pteval = trp->pte.val;
1540 *itir = trp->itir;
1541 perfc_incrc(tr_translate);
1542 return IA64_NO_FAULT;
1546 /* check 1-entry TLB */
1547 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1548 trp = &vcpu->arch.dtlb;
1549 pte = trp->pte;
1550 if (/* is_data && */ pte.p
1551 && vcpu_match_tr_entry_no_p(trp,address,rid)) {
1552 *pteval = pte.val;
1553 *itir = trp->itir;
1554 perfc_incrc(dtlb_translate);
1555 return IA64_USE_TLB;
1558 /* check guest VHPT */
1559 pta = PSCB(vcpu,pta);
1560 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1561 panic_domain(vcpu_regs(vcpu),"can't do long format VHPT\n");
1562 //return (is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR);
1565 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1566 // note: architecturally, iha is optionally set for alt faults but
1567 // xenlinux depends on it so should document it as part of PV interface
1568 vcpu_thash(vcpu, address, iha);
1569 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE))
1570 return (is_data ? IA64_ALT_DATA_TLB_VECTOR : IA64_ALT_INST_TLB_VECTOR);
1572 /* avoid recursively walking (short format) VHPT */
1573 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1574 return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
1576 if (!__access_ok (*iha)
1577 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1578 // virtual VHPT walker "missed" in TLB
1579 return IA64_VHPT_FAULT;
1581 /*
1582 * Optimisation: this VHPT walker aborts on not-present pages
1583 * instead of inserting a not-present translation, this allows
1584 * vectoring directly to the miss handler.
1585 */
1586 if (!pte.p)
1587 return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
1589 /* found mapping in guest VHPT! */
1590 *itir = rr & RR_PS_MASK;
1591 *pteval = pte.val;
1592 perfc_incrc(vhpt_translate);
1593 return IA64_NO_FAULT;
1596 IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
1598 UINT64 pteval, itir, mask, iha;
1599 IA64FAULT fault;
1601 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1602 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB)
1604 mask = itir_mask(itir);
1605 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1606 return (IA64_NO_FAULT);
1608 return vcpu_force_data_miss(vcpu,vadr);
1611 IA64FAULT vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key)
1613 printf("vcpu_tak: tak instruction unsupported\n");
1614 return (IA64_ILLOP_FAULT);
1615 // HACK ALERT: tak does a thash for now
1616 //return vcpu_thash(vcpu,vadr,key);
1619 /**************************************************************************
1620 VCPU debug breakpoint register access routines
1621 **************************************************************************/
1623 IA64FAULT vcpu_set_dbr(VCPU *vcpu, UINT64 reg, UINT64 val)
1625 // TODO: unimplemented DBRs return a reserved register fault
1626 // TODO: Should set Logical CPU state, not just physical
1627 ia64_set_dbr(reg,val);
1628 return (IA64_NO_FAULT);
1631 IA64FAULT vcpu_set_ibr(VCPU *vcpu, UINT64 reg, UINT64 val)
1633 // TODO: unimplemented IBRs return a reserved register fault
1634 // TODO: Should set Logical CPU state, not just physical
1635 ia64_set_ibr(reg,val);
1636 return (IA64_NO_FAULT);
1639 IA64FAULT vcpu_get_dbr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1641 // TODO: unimplemented DBRs return a reserved register fault
1642 UINT64 val = ia64_get_dbr(reg);
1643 *pval = val;
1644 return (IA64_NO_FAULT);
1647 IA64FAULT vcpu_get_ibr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1649 // TODO: unimplemented IBRs return a reserved register fault
1650 UINT64 val = ia64_get_ibr(reg);
1651 *pval = val;
1652 return (IA64_NO_FAULT);
1655 /**************************************************************************
1656 VCPU performance monitor register access routines
1657 **************************************************************************/
1659 IA64FAULT vcpu_set_pmc(VCPU *vcpu, UINT64 reg, UINT64 val)
1661 // TODO: Should set Logical CPU state, not just physical
1662 // NOTE: Writes to unimplemented PMC registers are discarded
1663 #ifdef DEBUG_PFMON
1664 printf("vcpu_set_pmc(%x,%lx)\n",reg,val);
1665 #endif
1666 ia64_set_pmc(reg,val);
1667 return (IA64_NO_FAULT);
1670 IA64FAULT vcpu_set_pmd(VCPU *vcpu, UINT64 reg, UINT64 val)
1672 // TODO: Should set Logical CPU state, not just physical
1673 // NOTE: Writes to unimplemented PMD registers are discarded
1674 #ifdef DEBUG_PFMON
1675 printf("vcpu_set_pmd(%x,%lx)\n",reg,val);
1676 #endif
1677 ia64_set_pmd(reg,val);
1678 return (IA64_NO_FAULT);
1681 IA64FAULT vcpu_get_pmc(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1683 // NOTE: Reads from unimplemented PMC registers return zero
1684 UINT64 val = (UINT64)ia64_get_pmc(reg);
1685 #ifdef DEBUG_PFMON
1686 printf("%lx=vcpu_get_pmc(%x)\n",val,reg);
1687 #endif
1688 *pval = val;
1689 return (IA64_NO_FAULT);
1692 IA64FAULT vcpu_get_pmd(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1694 // NOTE: Reads from unimplemented PMD registers return zero
1695 UINT64 val = (UINT64)ia64_get_pmd(reg);
1696 #ifdef DEBUG_PFMON
1697 printf("%lx=vcpu_get_pmd(%x)\n",val,reg);
1698 #endif
1699 *pval = val;
1700 return (IA64_NO_FAULT);
1703 /**************************************************************************
1704 VCPU banked general register access routines
1705 **************************************************************************/
1706 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1707 do{ \
1708 __asm__ __volatile__ ( \
1709 ";;extr.u %0 = %3,%6,16;;\n" \
1710 "dep %1 = %0, %1, 0, 16;;\n" \
1711 "st8 [%4] = %1\n" \
1712 "extr.u %0 = %2, 16, 16;;\n" \
1713 "dep %3 = %0, %3, %6, 16;;\n" \
1714 "st8 [%5] = %3\n" \
1715 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1716 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1717 }while(0)
1719 IA64FAULT vcpu_bsw0(VCPU *vcpu)
1721 // TODO: Only allowed for current vcpu
1722 REGS *regs = vcpu_regs(vcpu);
1723 unsigned long *r = &regs->r16;
1724 unsigned long *b0 = &PSCB(vcpu,bank0_regs[0]);
1725 unsigned long *b1 = &PSCB(vcpu,bank1_regs[0]);
1726 unsigned long *runat = &regs->eml_unat;
1727 unsigned long *b0unat = &PSCB(vcpu,vbnat);
1728 unsigned long *b1unat = &PSCB(vcpu,vnat);
1730 unsigned long i;
1732 if(VMX_DOMAIN(vcpu)){
1733 if(VCPU(vcpu,vpsr)&IA64_PSR_BN){
1734 for (i = 0; i < 16; i++) { *b1++ = *r; *r++ = *b0++; }
1735 vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1736 VCPU(vcpu,vpsr) &= ~IA64_PSR_BN;
1738 }else{
1739 if (PSCB(vcpu,banknum)) {
1740 for (i = 0; i < 16; i++) { *b1++ = *r; *r++ = *b0++; }
1741 vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1742 PSCB(vcpu,banknum) = 0;
1745 return (IA64_NO_FAULT);
1748 #define vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1749 do{ \
1750 __asm__ __volatile__ ( \
1751 ";;extr.u %0 = %3,%6,16;;\n" \
1752 "dep %1 = %0, %1, 16, 16;;\n" \
1753 "st8 [%4] = %1\n" \
1754 "extr.u %0 = %2, 0, 16;;\n" \
1755 "dep %3 = %0, %3, %6, 16;;\n" \
1756 "st8 [%5] = %3\n" \
1757 ::"r"(i),"r"(*b0unat),"r"(*b1unat),"r"(*runat),"r"(b0unat), \
1758 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1759 }while(0)
1761 IA64FAULT vcpu_bsw1(VCPU *vcpu)
1763 // TODO: Only allowed for current vcpu
1764 REGS *regs = vcpu_regs(vcpu);
1765 unsigned long *r = &regs->r16;
1766 unsigned long *b0 = &PSCB(vcpu,bank0_regs[0]);
1767 unsigned long *b1 = &PSCB(vcpu,bank1_regs[0]);
1768 unsigned long *runat = &regs->eml_unat;
1769 unsigned long *b0unat = &PSCB(vcpu,vbnat);
1770 unsigned long *b1unat = &PSCB(vcpu,vnat);
1772 unsigned long i;
1774 if(VMX_DOMAIN(vcpu)){
1775 if(!(VCPU(vcpu,vpsr)&IA64_PSR_BN)){
1776 for (i = 0; i < 16; i++) { *b0++ = *r; *r++ = *b1++; }
1777 vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1778 VCPU(vcpu,vpsr) |= IA64_PSR_BN;
1780 }else{
1781 if (!PSCB(vcpu,banknum)) {
1782 for (i = 0; i < 16; i++) { *b0++ = *r; *r++ = *b1++; }
1783 vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1784 PSCB(vcpu,banknum) = 1;
1787 return (IA64_NO_FAULT);
1790 /**************************************************************************
1791 VCPU cpuid access routines
1792 **************************************************************************/
1795 IA64FAULT vcpu_get_cpuid(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1797 // FIXME: This could get called as a result of a rsvd-reg fault
1798 // if reg > 3
1799 switch(reg) {
1800 case 0:
1801 memcpy(pval,"Xen/ia64",8);
1802 break;
1803 case 1:
1804 *pval = 0;
1805 break;
1806 case 2:
1807 *pval = 0;
1808 break;
1809 case 3:
1810 *pval = ia64_get_cpuid(3);
1811 break;
1812 case 4:
1813 *pval = ia64_get_cpuid(4);
1814 break;
1815 default:
1816 if (reg > (ia64_get_cpuid(3) & 0xff))
1817 return IA64_RSVDREG_FAULT;
1818 *pval = ia64_get_cpuid(reg);
1819 break;
1821 return (IA64_NO_FAULT);
1824 /**************************************************************************
1825 VCPU region register access routines
1826 **************************************************************************/
1828 unsigned long vcpu_get_rr_ve(VCPU *vcpu,UINT64 vadr)
1830 ia64_rr rr;
1832 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
1833 return(rr.ve);
1836 IA64FAULT vcpu_set_rr(VCPU *vcpu, UINT64 reg, UINT64 val)
1838 PSCB(vcpu,rrs)[reg>>61] = val;
1839 // warning: set_one_rr() does it "live"
1840 set_one_rr(reg,val);
1841 return (IA64_NO_FAULT);
1844 IA64FAULT vcpu_get_rr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1846 if(VMX_DOMAIN(vcpu)){
1847 *pval = VMX(vcpu,vrr[reg>>61]);
1848 }else{
1849 *pval = PSCB(vcpu,rrs)[reg>>61];
1851 return (IA64_NO_FAULT);
1854 /**************************************************************************
1855 VCPU protection key register access routines
1856 **************************************************************************/
1858 IA64FAULT vcpu_get_pkr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1860 #ifndef PKR_USE_FIXED
1861 printk("vcpu_get_pkr: called, not implemented yet\n");
1862 return IA64_ILLOP_FAULT;
1863 #else
1864 UINT64 val = (UINT64)ia64_get_pkr(reg);
1865 *pval = val;
1866 return (IA64_NO_FAULT);
1867 #endif
1870 IA64FAULT vcpu_set_pkr(VCPU *vcpu, UINT64 reg, UINT64 val)
1872 #ifndef PKR_USE_FIXED
1873 printk("vcpu_set_pkr: called, not implemented yet\n");
1874 return IA64_ILLOP_FAULT;
1875 #else
1876 // if (reg >= NPKRS) return (IA64_ILLOP_FAULT);
1877 vcpu->pkrs[reg] = val;
1878 ia64_set_pkr(reg,val);
1879 return (IA64_NO_FAULT);
1880 #endif
1883 /**************************************************************************
1884 VCPU translation register access routines
1885 **************************************************************************/
1887 static void
1888 vcpu_set_tr_entry_rid(TR_ENTRY *trp, UINT64 pte,
1889 UINT64 itir, UINT64 ifa, UINT64 rid)
1891 UINT64 ps;
1892 union pte_flags new_pte;
1894 trp->itir = itir;
1895 trp->rid = rid;
1896 ps = trp->ps;
1897 new_pte.val = pte;
1898 if (new_pte.pl < 2) new_pte.pl = 2;
1899 trp->vadr = ifa & ~0xfff;
1900 if (ps > 12) { // "ignore" relevant low-order bits
1901 new_pte.ppn &= ~((1UL<<(ps-12))-1);
1902 trp->vadr &= ~((1UL<<ps)-1);
1905 /* Atomic write. */
1906 trp->pte.val = new_pte.val;
1909 static inline void
1910 vcpu_set_tr_entry(TR_ENTRY *trp, UINT64 pte, UINT64 itir, UINT64 ifa)
1912 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
1913 VCPU(current, rrs[ifa>>61]) & RR_RID_MASK);
1916 IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte,
1917 UINT64 itir, UINT64 ifa)
1919 TR_ENTRY *trp;
1921 if (slot >= NDTRS) return IA64_RSVDREG_FAULT;
1923 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
1925 trp = &PSCBX(vcpu,dtrs[slot]);
1926 //printf("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
1927 vcpu_set_tr_entry(trp,pte,itir,ifa);
1928 vcpu_quick_region_set(PSCBX(vcpu,dtr_regions),ifa);
1930 /*
1931 * FIXME According to spec, vhpt should be purged, but this
1932 * incurs considerable performance loss, since it is safe for
1933 * linux not to purge vhpt, vhpt purge is disabled until a
1934 * feasible way is found.
1936 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
1937 */
1939 return IA64_NO_FAULT;
1942 IA64FAULT vcpu_itr_i(VCPU *vcpu, UINT64 slot, UINT64 pte,
1943 UINT64 itir, UINT64 ifa)
1945 TR_ENTRY *trp;
1947 if (slot >= NITRS) return IA64_RSVDREG_FAULT;
1949 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
1951 trp = &PSCBX(vcpu,itrs[slot]);
1952 //printf("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
1953 vcpu_set_tr_entry(trp,pte,itir,ifa);
1954 vcpu_quick_region_set(PSCBX(vcpu,itr_regions),ifa);
1956 /*
1957 * FIXME According to spec, vhpt should be purged, but this
1958 * incurs considerable performance loss, since it is safe for
1959 * linux not to purge vhpt, vhpt purge is disabled until a
1960 * feasible way is found.
1962 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
1963 */
1965 return IA64_NO_FAULT;
1968 IA64FAULT vcpu_set_itr(VCPU *vcpu, u64 slot, u64 pte,
1969 u64 itir, u64 ifa, u64 rid)
1971 TR_ENTRY *trp;
1973 if (slot >= NITRS)
1974 return IA64_RSVDREG_FAULT;
1975 trp = &PSCBX(vcpu, itrs[slot]);
1976 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
1978 /* Recompute the itr_region. */
1979 vcpu->arch.itr_regions = 0;
1980 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
1981 if (trp->pte.p)
1982 vcpu_quick_region_set(vcpu->arch.itr_regions,
1983 trp->vadr);
1984 return IA64_NO_FAULT;
1987 IA64FAULT vcpu_set_dtr(VCPU *vcpu, u64 slot, u64 pte,
1988 u64 itir, u64 ifa, u64 rid)
1990 TR_ENTRY *trp;
1992 if (slot >= NDTRS)
1993 return IA64_RSVDREG_FAULT;
1994 trp = &PSCBX(vcpu, dtrs[slot]);
1995 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
1997 /* Recompute the dtr_region. */
1998 vcpu->arch.dtr_regions = 0;
1999 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
2000 if (trp->pte.p)
2001 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2002 trp->vadr);
2003 return IA64_NO_FAULT;
2006 /**************************************************************************
2007 VCPU translation cache access routines
2008 **************************************************************************/
2010 void vcpu_itc_no_srlz(VCPU *vcpu, UINT64 IorD, UINT64 vaddr, UINT64 pte, UINT64 mp_pte, UINT64 logps)
2012 unsigned long psr;
2013 unsigned long ps = (vcpu->domain==dom0) ? logps : PAGE_SHIFT;
2015 check_xen_space_overlap ("itc", vaddr, 1UL << logps);
2017 // FIXME, must be inlined or potential for nested fault here!
2018 if ((vcpu->domain==dom0) && (logps < PAGE_SHIFT))
2019 panic_domain (NULL, "vcpu_itc_no_srlz: domain trying to use "
2020 "smaller page size!\n");
2022 BUG_ON(logps > PAGE_SHIFT);
2023 psr = ia64_clear_ic();
2024 ia64_itc(IorD,vaddr,pte,ps); // FIXME: look for bigger mappings
2025 ia64_set_psr(psr);
2026 // ia64_srlz_i(); // no srls req'd, will rfi later
2027 #ifdef VHPT_GLOBAL
2028 if (vcpu->domain==dom0 && ((vaddr >> 61) == 7)) {
2029 // FIXME: this is dangerous... vhpt_flush_address ensures these
2030 // addresses never get flushed. More work needed if this
2031 // ever happens.
2032 //printf("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2033 if (logps > PAGE_SHIFT) vhpt_multiple_insert(vaddr,pte,logps);
2034 else vhpt_insert(vaddr,pte,logps<<2);
2036 // even if domain pagesize is larger than PAGE_SIZE, just put
2037 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2038 else vhpt_insert(vaddr,pte,PAGE_SHIFT<<2);
2039 #endif
2040 if ((mp_pte == -1UL) || (IorD & 0x4)) // don't place in 1-entry TLB
2041 return;
2042 if (IorD & 0x1) {
2043 vcpu_set_tr_entry(&PSCBX(vcpu,itlb),mp_pte,ps<<2,vaddr);
2045 if (IorD & 0x2) {
2046 vcpu_set_tr_entry(&PSCBX(vcpu,dtlb),mp_pte,ps<<2,vaddr);
2050 IA64FAULT vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
2052 unsigned long pteval, logps = itir_ps(itir);
2053 BOOLEAN swap_rr0 = (!(ifa>>61) && PSCB(vcpu,metaphysical_mode));
2054 struct p2m_entry entry;
2056 if (logps < PAGE_SHIFT)
2057 panic_domain (NULL, "vcpu_itc_d: domain trying to use "
2058 "smaller page size!\n");
2060 again:
2061 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2062 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2063 if (!pteval) return IA64_ILLOP_FAULT;
2064 if (swap_rr0) set_one_rr(0x0,PSCB(vcpu,rrs[0]));
2065 vcpu_itc_no_srlz(vcpu,2,ifa,pteval,pte,logps);
2066 if (swap_rr0) set_metaphysical_rr0();
2067 if (p2m_entry_retry(&entry)) {
2068 vcpu_flush_tlb_vhpt_range(ifa, logps);
2069 goto again;
2071 return IA64_NO_FAULT;
2074 IA64FAULT vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
2076 unsigned long pteval, logps = itir_ps(itir);
2077 BOOLEAN swap_rr0 = (!(ifa>>61) && PSCB(vcpu,metaphysical_mode));
2078 struct p2m_entry entry;
2080 if (logps < PAGE_SHIFT)
2081 panic_domain (NULL, "vcpu_itc_i: domain trying to use "
2082 "smaller page size!\n");
2083 again:
2084 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2085 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2086 if (!pteval) return IA64_ILLOP_FAULT;
2087 if (swap_rr0) set_one_rr(0x0,PSCB(vcpu,rrs[0]));
2088 vcpu_itc_no_srlz(vcpu, 1,ifa,pteval,pte,logps);
2089 if (swap_rr0) set_metaphysical_rr0();
2090 if (p2m_entry_retry(&entry)) {
2091 vcpu_flush_tlb_vhpt_range(ifa, logps);
2092 goto again;
2094 return IA64_NO_FAULT;
2097 IA64FAULT vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 log_range)
2099 BUG_ON(vcpu != current);
2101 check_xen_space_overlap ("ptc_l", vadr, 1UL << log_range);
2103 /* Purge TC */
2104 vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb));
2105 vcpu_purge_tr_entry(&PSCBX(vcpu,itlb));
2107 /* Purge all tlb and vhpt */
2108 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2110 return IA64_NO_FAULT;
2113 // At privlvl=0, fc performs no access rights or protection key checks, while
2114 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2115 // read but no protection key check. Thus in order to avoid an unexpected
2116 // access rights fault, we have to translate the virtual address to a
2117 // physical address (possibly via a metaphysical address) and do the fc
2118 // on the physical address, which is guaranteed to flush the same cache line
2119 IA64FAULT vcpu_fc(VCPU *vcpu, UINT64 vadr)
2121 // TODO: Only allowed for current vcpu
2122 UINT64 mpaddr, paddr;
2123 IA64FAULT fault;
2125 again:
2126 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2127 if (fault == IA64_NO_FAULT) {
2128 struct p2m_entry entry;
2129 paddr = translate_domain_mpaddr(mpaddr, &entry);
2130 ia64_fc(__va(paddr));
2131 if (p2m_entry_retry(&entry))
2132 goto again;
2134 return fault;
2137 IA64FAULT vcpu_ptc_e(VCPU *vcpu, UINT64 vadr)
2139 // Note that this only needs to be called once, i.e. the
2140 // architected loop to purge the entire TLB, should use
2141 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2143 vcpu_flush_vtlb_all(current);
2145 return IA64_NO_FAULT;
2148 IA64FAULT vcpu_ptc_g(VCPU *vcpu, UINT64 vadr, UINT64 addr_range)
2150 printk("vcpu_ptc_g: called, not implemented yet\n");
2151 return IA64_ILLOP_FAULT;
2154 IA64FAULT vcpu_ptc_ga(VCPU *vcpu,UINT64 vadr,UINT64 addr_range)
2156 // FIXME: validate not flushing Xen addresses
2157 // if (Xen address) return(IA64_ILLOP_FAULT);
2158 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2159 //printf("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2161 check_xen_space_overlap ("ptc_ga", vadr, addr_range);
2163 domain_flush_vtlb_range (vcpu->domain, vadr, addr_range);
2165 return IA64_NO_FAULT;
2168 IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
2170 unsigned long region = vadr >> 61;
2171 u64 addr_range = 1UL << log_range;
2172 unsigned long rid, rr;
2173 int i;
2174 TR_ENTRY *trp;
2176 BUG_ON(vcpu != current);
2177 check_xen_space_overlap ("ptr_d", vadr, 1UL << log_range);
2179 rr = PSCB(vcpu,rrs)[region];
2180 rid = rr & RR_RID_MASK;
2182 /* Purge TC */
2183 vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb));
2185 /* Purge tr and recompute dtr_regions. */
2186 vcpu->arch.dtr_regions = 0;
2187 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2188 if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range))
2189 vcpu_purge_tr_entry(trp);
2190 else if (trp->pte.p)
2191 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2192 trp->vadr);
2194 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2196 return IA64_NO_FAULT;
2199 IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
2201 unsigned long region = vadr >> 61;
2202 u64 addr_range = 1UL << log_range;
2203 unsigned long rid, rr;
2204 int i;
2205 TR_ENTRY *trp;
2207 BUG_ON(vcpu != current);
2208 check_xen_space_overlap ("ptr_i", vadr, 1UL << log_range);
2210 rr = PSCB(vcpu,rrs)[region];
2211 rid = rr & RR_RID_MASK;
2213 /* Purge TC */
2214 vcpu_purge_tr_entry(&PSCBX(vcpu,itlb));
2216 /* Purge tr and recompute itr_regions. */
2217 vcpu->arch.itr_regions = 0;
2218 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2219 if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range))
2220 vcpu_purge_tr_entry(trp);
2221 else if (trp->pte.p)
2222 vcpu_quick_region_set(vcpu->arch.itr_regions,
2223 trp->vadr);
2225 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2227 return IA64_NO_FAULT;
2230 int ia64_map_hypercall_param(void)
2232 struct vcpu *v = current;
2233 struct domain *d = current->domain;
2234 u64 vaddr = v->arch.hypercall_param.va & PAGE_MASK;
2235 volatile pte_t* pte;
2237 if (v->arch.hypercall_param.va == 0)
2238 return FALSE;
2239 pte = lookup_noalloc_domain_pte(d, v->arch.hypercall_param.pa1);
2240 if (!pte || !pte_present(*pte))
2241 return FALSE;
2242 vcpu_itc_no_srlz(v, 2, vaddr, pte_val(*pte), -1UL, PAGE_SHIFT);
2243 if (v->arch.hypercall_param.pa2) {
2244 vaddr += PAGE_SIZE;
2245 pte = lookup_noalloc_domain_pte(d, v->arch.hypercall_param.pa2);
2246 if (pte && pte_present(*pte)) {
2247 vcpu_itc_no_srlz(v, 2, vaddr, pte_val(*pte),
2248 -1UL, PAGE_SHIFT);
2251 ia64_srlz_d();
2252 return TRUE;