ia64/xen-unstable

view xen/arch/ia64/xen/vcpu.c @ 10936:3f3388f3e605

[IA64] Virtualize dom0 lid

Because dom0 can't write eid/id into iosapics, lid can be virtualized.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Tue Aug 08 14:40:57 2006 -0600 (2006-08-08)
parents c3e20511c745
children 7c79d49033c6 04e5e80be909
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/arch-ia64.h>
11 #include <asm/ia64_int.h>
12 #include <asm/vcpu.h>
13 #include <asm/regionreg.h>
14 #include <asm/tlb.h>
15 #include <asm/processor.h>
16 #include <asm/delay.h>
17 #include <asm/vmx_vcpu.h>
18 #include <asm/vhpt.h>
19 #include <asm/tlbflush.h>
20 #include <asm/privop.h>
21 #include <xen/event.h>
22 #include <asm/vmx_phy_mode.h>
23 #include <asm/bundle.h>
24 #include <asm/privop_stat.h>
26 /* FIXME: where these declarations should be there ? */
27 extern void getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs);
28 extern void setreg(unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs);
29 extern void getfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs);
31 extern void setfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs);
33 typedef union {
34 struct ia64_psr ia64_psr;
35 unsigned long i64;
36 } PSR;
38 // this def for vcpu_regs won't work if kernel stack is present
39 //#define vcpu_regs(vcpu) ((struct pt_regs *) vcpu->arch.regs
41 #define TRUE 1
42 #define FALSE 0
43 #define IA64_PTA_SZ_BIT 2
44 #define IA64_PTA_VF_BIT 8
45 #define IA64_PTA_BASE_BIT 15
46 #define IA64_PTA_LFMT (1UL << IA64_PTA_VF_BIT)
47 #define IA64_PTA_SZ(x) (x##UL << IA64_PTA_SZ_BIT)
49 unsigned long vcpu_verbose = 0;
51 /**************************************************************************
52 VCPU general register access routines
53 **************************************************************************/
54 #ifdef XEN
55 UINT64
56 vcpu_get_gr(VCPU *vcpu, unsigned long reg)
57 {
58 REGS *regs = vcpu_regs(vcpu);
59 UINT64 val;
61 if (!reg) return 0;
62 getreg(reg,&val,0,regs); // FIXME: handle NATs later
63 return val;
64 }
65 IA64FAULT
66 vcpu_get_gr_nat(VCPU *vcpu, unsigned long reg, UINT64 *val)
67 {
68 REGS *regs = vcpu_regs(vcpu);
69 int nat;
71 getreg(reg,val,&nat,regs); // FIXME: handle NATs later
72 if (nat)
73 return IA64_NAT_CONSUMPTION_VECTOR;
74 return 0;
75 }
77 // returns:
78 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
79 // IA64_NO_FAULT otherwise
80 IA64FAULT
81 vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value, int nat)
82 {
83 REGS *regs = vcpu_regs(vcpu);
84 long sof = (regs->cr_ifs) & 0x7f;
86 if (!reg) return IA64_ILLOP_FAULT;
87 if (reg >= sof + 32) return IA64_ILLOP_FAULT;
88 setreg(reg,value,nat,regs); // FIXME: handle NATs later
89 return IA64_NO_FAULT;
90 }
92 IA64FAULT
93 vcpu_get_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
94 {
95 REGS *regs = vcpu_regs(vcpu);
96 getfpreg(reg,val,regs); // FIXME: handle NATs later
97 return IA64_NO_FAULT;
98 }
100 IA64FAULT
101 vcpu_set_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
102 {
103 REGS *regs = vcpu_regs(vcpu);
104 if(reg > 1)
105 setfpreg(reg,val,regs); // FIXME: handle NATs later
106 return IA64_NO_FAULT;
107 }
109 #else
110 // returns:
111 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
112 // IA64_NO_FAULT otherwise
113 IA64FAULT
114 vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value)
115 {
116 REGS *regs = vcpu_regs(vcpu);
117 long sof = (regs->cr_ifs) & 0x7f;
119 if (!reg) return IA64_ILLOP_FAULT;
120 if (reg >= sof + 32) return IA64_ILLOP_FAULT;
121 setreg(reg,value,0,regs); // FIXME: handle NATs later
122 return IA64_NO_FAULT;
123 }
125 #endif
127 void vcpu_init_regs (struct vcpu *v)
128 {
129 struct pt_regs *regs;
131 regs = vcpu_regs (v);
132 if (VMX_DOMAIN(v)) {
133 /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
134 /* Need to be expanded as macro */
135 regs->cr_ipsr = 0x501008826008;
136 } else {
137 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
138 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
139 regs->cr_ipsr &= ~(IA64_PSR_BITS_TO_CLEAR
140 | IA64_PSR_RI | IA64_PSR_IS);
141 // domain runs at PL2
142 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
143 }
144 regs->cr_ifs = 1UL << 63; /* or clear? */
145 regs->ar_fpsr = FPSR_DEFAULT;
147 if (VMX_DOMAIN(v)) {
148 vmx_init_all_rr(v);
149 /* Virtual processor context setup */
150 VCPU(v, vpsr) = IA64_PSR_BN;
151 VCPU(v, dcr) = 0;
152 } else {
153 init_all_rr(v);
154 regs->ar_rsc |= (2 << 2); /* force PL2/3 */
155 VCPU(v, banknum) = 1;
156 VCPU(v, metaphysical_mode) = 1;
157 VCPU(v, interrupt_mask_addr) =
158 (unsigned char *)v->domain->arch.shared_info_va +
159 INT_ENABLE_OFFSET(v);
160 VCPU(v, itv) = (1 << 16); /* timer vector masked */
161 }
163 v->arch.domain_itm_last = -1L;
164 }
166 /**************************************************************************
167 VCPU privileged application register access routines
168 **************************************************************************/
170 void vcpu_load_kernel_regs(VCPU *vcpu)
171 {
172 ia64_set_kr(0, VCPU(vcpu, krs[0]));
173 ia64_set_kr(1, VCPU(vcpu, krs[1]));
174 ia64_set_kr(2, VCPU(vcpu, krs[2]));
175 ia64_set_kr(3, VCPU(vcpu, krs[3]));
176 ia64_set_kr(4, VCPU(vcpu, krs[4]));
177 ia64_set_kr(5, VCPU(vcpu, krs[5]));
178 ia64_set_kr(6, VCPU(vcpu, krs[6]));
179 ia64_set_kr(7, VCPU(vcpu, krs[7]));
180 }
182 /* GCC 4.0.2 seems not to be able to suppress this call!. */
183 #define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
185 IA64FAULT vcpu_set_ar(VCPU *vcpu, UINT64 reg, UINT64 val)
186 {
187 if (reg == 44) return (vcpu_set_itc(vcpu,val));
188 else if (reg == 27) return (IA64_ILLOP_FAULT);
189 else if (reg == 24)
190 printf("warning: setting ar.eflg is a no-op; no IA-32 support\n");
191 else if (reg > 7) return (IA64_ILLOP_FAULT);
192 else {
193 PSCB(vcpu,krs[reg]) = val;
194 ia64_set_kr(reg,val);
195 }
196 return IA64_NO_FAULT;
197 }
199 IA64FAULT vcpu_get_ar(VCPU *vcpu, UINT64 reg, UINT64 *val)
200 {
201 if (reg == 24)
202 printf("warning: getting ar.eflg is a no-op; no IA-32 support\n");
203 else if (reg > 7) return (IA64_ILLOP_FAULT);
204 else *val = PSCB(vcpu,krs[reg]);
205 return IA64_NO_FAULT;
206 }
208 /**************************************************************************
209 VCPU processor status register access routines
210 **************************************************************************/
212 void vcpu_set_metaphysical_mode(VCPU *vcpu, BOOLEAN newmode)
213 {
214 /* only do something if mode changes */
215 if (!!newmode ^ !!PSCB(vcpu,metaphysical_mode)) {
216 PSCB(vcpu,metaphysical_mode) = newmode;
217 if (newmode) set_metaphysical_rr0();
218 else if (PSCB(vcpu,rrs[0]) != -1)
219 set_one_rr(0, PSCB(vcpu,rrs[0]));
220 }
221 }
223 IA64FAULT vcpu_reset_psr_dt(VCPU *vcpu)
224 {
225 vcpu_set_metaphysical_mode(vcpu,TRUE);
226 return IA64_NO_FAULT;
227 }
229 IA64FAULT vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
230 {
231 struct ia64_psr psr, imm, *ipsr;
232 REGS *regs = vcpu_regs(vcpu);
234 //PRIVOP_COUNT_ADDR(regs,_RSM);
235 // TODO: All of these bits need to be virtualized
236 // TODO: Only allowed for current vcpu
237 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
238 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
239 imm = *(struct ia64_psr *)&imm24;
240 // interrupt flag
241 if (imm.i)
242 vcpu->vcpu_info->evtchn_upcall_mask = 1;
243 if (imm.ic) PSCB(vcpu,interrupt_collection_enabled) = 0;
244 // interrupt collection flag
245 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
246 // just handle psr.up and psr.pp for now
247 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP
248 | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT
249 | IA64_PSR_DFL | IA64_PSR_DFH))
250 return (IA64_ILLOP_FAULT);
251 if (imm.dfh) ipsr->dfh = 0;
252 if (imm.dfl) ipsr->dfl = 0;
253 if (imm.pp) {
254 ipsr->pp = 1;
255 psr.pp = 1; // priv perf ctrs always enabled
256 PSCB(vcpu,vpsr_pp) = 0; // but fool the domain if it gets psr
257 }
258 if (imm.up) { ipsr->up = 0; psr.up = 0; }
259 if (imm.sp) { ipsr->sp = 0; psr.sp = 0; }
260 if (imm.be) ipsr->be = 0;
261 if (imm.dt) vcpu_set_metaphysical_mode(vcpu,TRUE);
262 __asm__ __volatile (";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
263 return IA64_NO_FAULT;
264 }
267 IA64FAULT vcpu_set_psr_dt(VCPU *vcpu)
268 {
269 vcpu_set_metaphysical_mode(vcpu,FALSE);
270 return IA64_NO_FAULT;
271 }
273 IA64FAULT vcpu_set_psr_i(VCPU *vcpu)
274 {
275 vcpu->vcpu_info->evtchn_upcall_mask = 0;
276 PSCB(vcpu,interrupt_collection_enabled) = 1;
277 return IA64_NO_FAULT;
278 }
280 IA64FAULT vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
281 {
282 struct ia64_psr psr, imm, *ipsr;
283 REGS *regs = vcpu_regs(vcpu);
284 UINT64 mask, enabling_interrupts = 0;
286 //PRIVOP_COUNT_ADDR(regs,_SSM);
287 // TODO: All of these bits need to be virtualized
288 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
289 imm = *(struct ia64_psr *)&imm24;
290 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
291 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
292 mask = IA64_PSR_PP|IA64_PSR_SP|IA64_PSR_I|IA64_PSR_IC|IA64_PSR_UM |
293 IA64_PSR_DT|IA64_PSR_DFL|IA64_PSR_DFH;
294 if (imm24 & ~mask) return (IA64_ILLOP_FAULT);
295 if (imm.dfh) ipsr->dfh = 1;
296 if (imm.dfl) ipsr->dfl = 1;
297 if (imm.pp) {
298 ipsr->pp = 1;
299 psr.pp = 1;
300 PSCB(vcpu,vpsr_pp) = 1;
301 }
302 if (imm.sp) { ipsr->sp = 1; psr.sp = 1; }
303 if (imm.i) {
304 if (vcpu->vcpu_info->evtchn_upcall_mask) {
305 //printf("vcpu_set_psr_sm: psr.ic 0->1\n");
306 enabling_interrupts = 1;
307 }
308 vcpu->vcpu_info->evtchn_upcall_mask = 0;
309 }
310 if (imm.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
311 // TODO: do this faster
312 if (imm.mfl) { ipsr->mfl = 1; psr.mfl = 1; }
313 if (imm.mfh) { ipsr->mfh = 1; psr.mfh = 1; }
314 if (imm.ac) { ipsr->ac = 1; psr.ac = 1; }
315 if (imm.up) { ipsr->up = 1; psr.up = 1; }
316 if (imm.be) {
317 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
318 return (IA64_ILLOP_FAULT);
319 }
320 if (imm.dt) vcpu_set_metaphysical_mode(vcpu,FALSE);
321 __asm__ __volatile (";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
322 if (enabling_interrupts &&
323 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
324 PSCB(vcpu,pending_interruption) = 1;
325 return IA64_NO_FAULT;
326 }
328 IA64FAULT vcpu_set_psr_l(VCPU *vcpu, UINT64 val)
329 {
330 struct ia64_psr psr, newpsr, *ipsr;
331 REGS *regs = vcpu_regs(vcpu);
332 UINT64 enabling_interrupts = 0;
334 // TODO: All of these bits need to be virtualized
335 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
336 newpsr = *(struct ia64_psr *)&val;
337 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
338 // just handle psr.up and psr.pp for now
339 //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP)) return (IA64_ILLOP_FAULT);
340 // however trying to set other bits can't be an error as it is in ssm
341 if (newpsr.dfh) ipsr->dfh = 1;
342 if (newpsr.dfl) ipsr->dfl = 1;
343 if (newpsr.pp) {
344 ipsr->pp = 1; psr.pp = 1;
345 PSCB(vcpu,vpsr_pp) = 1;
346 }
347 else {
348 ipsr->pp = 1; psr.pp = 1;
349 PSCB(vcpu,vpsr_pp) = 0;
350 }
351 if (newpsr.up) { ipsr->up = 1; psr.up = 1; }
352 if (newpsr.sp) { ipsr->sp = 1; psr.sp = 1; }
353 if (newpsr.i) {
354 if (vcpu->vcpu_info->evtchn_upcall_mask)
355 enabling_interrupts = 1;
356 vcpu->vcpu_info->evtchn_upcall_mask = 0;
357 }
358 if (newpsr.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
359 if (newpsr.mfl) { ipsr->mfl = 1; psr.mfl = 1; }
360 if (newpsr.mfh) { ipsr->mfh = 1; psr.mfh = 1; }
361 if (newpsr.ac) { ipsr->ac = 1; psr.ac = 1; }
362 if (newpsr.up) { ipsr->up = 1; psr.up = 1; }
363 if (newpsr.dt && newpsr.rt) vcpu_set_metaphysical_mode(vcpu,FALSE);
364 else vcpu_set_metaphysical_mode(vcpu,TRUE);
365 if (newpsr.be) {
366 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
367 return (IA64_ILLOP_FAULT);
368 }
369 if (enabling_interrupts &&
370 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
371 PSCB(vcpu,pending_interruption) = 1;
372 return IA64_NO_FAULT;
373 }
375 IA64FAULT vcpu_get_psr(VCPU *vcpu, UINT64 *pval)
376 {
377 REGS *regs = vcpu_regs(vcpu);
378 struct ia64_psr newpsr;
380 newpsr = *(struct ia64_psr *)&regs->cr_ipsr;
381 if (newpsr.cpl == 2) newpsr.cpl = 0;
382 if (!vcpu->vcpu_info->evtchn_upcall_mask) newpsr.i = 1;
383 else newpsr.i = 0;
384 if (PSCB(vcpu,interrupt_collection_enabled)) newpsr.ic = 1;
385 else newpsr.ic = 0;
386 if (PSCB(vcpu,metaphysical_mode)) newpsr.dt = 0;
387 else newpsr.dt = 1;
388 if (PSCB(vcpu,vpsr_pp)) newpsr.pp = 1;
389 else newpsr.pp = 0;
390 *pval = *(unsigned long *)&newpsr;
391 return IA64_NO_FAULT;
392 }
394 BOOLEAN vcpu_get_psr_ic(VCPU *vcpu)
395 {
396 return !!PSCB(vcpu,interrupt_collection_enabled);
397 }
399 BOOLEAN vcpu_get_psr_i(VCPU *vcpu)
400 {
401 return !vcpu->vcpu_info->evtchn_upcall_mask;
402 }
404 UINT64 vcpu_get_ipsr_int_state(VCPU *vcpu,UINT64 prevpsr)
405 {
406 UINT64 dcr = PSCBX(vcpu,dcr);
407 PSR psr;
409 //printf("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr);
410 psr.i64 = prevpsr;
411 psr.ia64_psr.be = 0; if (dcr & IA64_DCR_BE) psr.ia64_psr.be = 1;
412 psr.ia64_psr.pp = 0; if (dcr & IA64_DCR_PP) psr.ia64_psr.pp = 1;
413 psr.ia64_psr.ic = PSCB(vcpu,interrupt_collection_enabled);
414 psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
415 psr.ia64_psr.bn = PSCB(vcpu,banknum);
416 psr.ia64_psr.dt = 1; psr.ia64_psr.it = 1; psr.ia64_psr.rt = 1;
417 if (psr.ia64_psr.cpl == 2) psr.ia64_psr.cpl = 0; // !!!! fool domain
418 // psr.pk = 1;
419 //printf("returns 0x%016lx...\n",psr.i64);
420 return psr.i64;
421 }
423 /**************************************************************************
424 VCPU control register access routines
425 **************************************************************************/
427 IA64FAULT vcpu_get_dcr(VCPU *vcpu, UINT64 *pval)
428 {
429 //verbose("vcpu_get_dcr: called @%p\n",PSCB(vcpu,iip));
430 // Reads of cr.dcr on Xen always have the sign bit set, so
431 // a domain can differentiate whether it is running on SP or not
432 *pval = PSCBX(vcpu,dcr) | 0x8000000000000000L;
433 return (IA64_NO_FAULT);
434 }
436 IA64FAULT vcpu_get_iva(VCPU *vcpu, UINT64 *pval)
437 {
438 if(VMX_DOMAIN(vcpu)){
439 *pval = PSCB(vcpu,iva) & ~0x7fffL;
440 }else{
441 *pval = PSCBX(vcpu,iva) & ~0x7fffL;
442 }
443 return (IA64_NO_FAULT);
444 }
446 IA64FAULT vcpu_get_pta(VCPU *vcpu, UINT64 *pval)
447 {
448 *pval = PSCB(vcpu,pta);
449 return (IA64_NO_FAULT);
450 }
452 IA64FAULT vcpu_get_ipsr(VCPU *vcpu, UINT64 *pval)
453 {
454 //REGS *regs = vcpu_regs(vcpu);
455 //*pval = regs->cr_ipsr;
456 *pval = PSCB(vcpu,ipsr);
457 return (IA64_NO_FAULT);
458 }
460 IA64FAULT vcpu_get_isr(VCPU *vcpu, UINT64 *pval)
461 {
462 *pval = PSCB(vcpu,isr);
463 return (IA64_NO_FAULT);
464 }
466 IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT64 *pval)
467 {
468 //REGS *regs = vcpu_regs(vcpu);
469 //*pval = regs->cr_iip;
470 *pval = PSCB(vcpu,iip);
471 return (IA64_NO_FAULT);
472 }
474 IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval)
475 {
476 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu),_GET_IFA);
477 *pval = PSCB(vcpu,ifa);
478 return (IA64_NO_FAULT);
479 }
481 unsigned long vcpu_get_rr_ps(VCPU *vcpu,UINT64 vadr)
482 {
483 ia64_rr rr;
485 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
486 return(rr.ps);
487 }
489 unsigned long vcpu_get_rr_rid(VCPU *vcpu,UINT64 vadr)
490 {
491 ia64_rr rr;
493 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
494 return(rr.rid);
495 }
497 unsigned long vcpu_get_itir_on_fault(VCPU *vcpu, UINT64 ifa)
498 {
499 ia64_rr rr;
501 rr.rrval = 0;
502 rr.ps = vcpu_get_rr_ps(vcpu,ifa);
503 rr.rid = vcpu_get_rr_rid(vcpu,ifa);
504 return (rr.rrval);
505 }
508 IA64FAULT vcpu_get_itir(VCPU *vcpu, UINT64 *pval)
509 {
510 UINT64 val = PSCB(vcpu,itir);
511 *pval = val;
512 return (IA64_NO_FAULT);
513 }
515 IA64FAULT vcpu_get_iipa(VCPU *vcpu, UINT64 *pval)
516 {
517 UINT64 val = PSCB(vcpu,iipa);
518 // SP entry code does not save iipa yet nor does it get
519 // properly delivered in the pscb
520 // printf("*** vcpu_get_iipa: cr.iipa not fully implemented yet!!\n");
521 *pval = val;
522 return (IA64_NO_FAULT);
523 }
525 IA64FAULT vcpu_get_ifs(VCPU *vcpu, UINT64 *pval)
526 {
527 //PSCB(vcpu,ifs) = PSCB(vcpu)->regs.cr_ifs;
528 //*pval = PSCB(vcpu,regs).cr_ifs;
529 *pval = PSCB(vcpu,ifs);
530 PSCB(vcpu,incomplete_regframe) = 0;
531 return (IA64_NO_FAULT);
532 }
534 IA64FAULT vcpu_get_iim(VCPU *vcpu, UINT64 *pval)
535 {
536 UINT64 val = PSCB(vcpu,iim);
537 *pval = val;
538 return (IA64_NO_FAULT);
539 }
541 IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval)
542 {
543 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu),_THASH);
544 *pval = PSCB(vcpu,iha);
545 return (IA64_NO_FAULT);
546 }
548 IA64FAULT vcpu_set_dcr(VCPU *vcpu, UINT64 val)
549 {
550 // Reads of cr.dcr on SP always have the sign bit set, so
551 // a domain can differentiate whether it is running on SP or not
552 // Thus, writes of DCR should ignore the sign bit
553 //verbose("vcpu_set_dcr: called\n");
554 PSCBX(vcpu,dcr) = val & ~0x8000000000000000L;
555 return (IA64_NO_FAULT);
556 }
558 IA64FAULT vcpu_set_iva(VCPU *vcpu, UINT64 val)
559 {
560 if(VMX_DOMAIN(vcpu)){
561 PSCB(vcpu,iva) = val & ~0x7fffL;
562 }else{
563 PSCBX(vcpu,iva) = val & ~0x7fffL;
564 }
565 return (IA64_NO_FAULT);
566 }
568 IA64FAULT vcpu_set_pta(VCPU *vcpu, UINT64 val)
569 {
570 if (val & IA64_PTA_LFMT) {
571 printf("*** No support for VHPT long format yet!!\n");
572 return (IA64_ILLOP_FAULT);
573 }
574 if (val & (0x3f<<9)) /* reserved fields */ return IA64_RSVDREG_FAULT;
575 if (val & 2) /* reserved fields */ return IA64_RSVDREG_FAULT;
576 PSCB(vcpu,pta) = val;
577 return IA64_NO_FAULT;
578 }
580 IA64FAULT vcpu_set_ipsr(VCPU *vcpu, UINT64 val)
581 {
582 PSCB(vcpu,ipsr) = val;
583 return IA64_NO_FAULT;
584 }
586 IA64FAULT vcpu_set_isr(VCPU *vcpu, UINT64 val)
587 {
588 PSCB(vcpu,isr) = val;
589 return IA64_NO_FAULT;
590 }
592 IA64FAULT vcpu_set_iip(VCPU *vcpu, UINT64 val)
593 {
594 PSCB(vcpu,iip) = val;
595 return IA64_NO_FAULT;
596 }
598 IA64FAULT vcpu_increment_iip(VCPU *vcpu)
599 {
600 REGS *regs = vcpu_regs(vcpu);
601 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
602 if (ipsr->ri == 2) { ipsr->ri=0; regs->cr_iip += 16; }
603 else ipsr->ri++;
604 return (IA64_NO_FAULT);
605 }
607 IA64FAULT vcpu_set_ifa(VCPU *vcpu, UINT64 val)
608 {
609 PSCB(vcpu,ifa) = val;
610 return IA64_NO_FAULT;
611 }
613 IA64FAULT vcpu_set_itir(VCPU *vcpu, UINT64 val)
614 {
615 PSCB(vcpu,itir) = val;
616 return IA64_NO_FAULT;
617 }
619 IA64FAULT vcpu_set_iipa(VCPU *vcpu, UINT64 val)
620 {
621 // SP entry code does not save iipa yet nor does it get
622 // properly delivered in the pscb
623 // printf("*** vcpu_set_iipa: cr.iipa not fully implemented yet!!\n");
624 PSCB(vcpu,iipa) = val;
625 return IA64_NO_FAULT;
626 }
628 IA64FAULT vcpu_set_ifs(VCPU *vcpu, UINT64 val)
629 {
630 //REGS *regs = vcpu_regs(vcpu);
631 PSCB(vcpu,ifs) = val;
632 return IA64_NO_FAULT;
633 }
635 IA64FAULT vcpu_set_iim(VCPU *vcpu, UINT64 val)
636 {
637 PSCB(vcpu,iim) = val;
638 return IA64_NO_FAULT;
639 }
641 IA64FAULT vcpu_set_iha(VCPU *vcpu, UINT64 val)
642 {
643 PSCB(vcpu,iha) = val;
644 return IA64_NO_FAULT;
645 }
647 /**************************************************************************
648 VCPU interrupt control register access routines
649 **************************************************************************/
651 void vcpu_pend_unspecified_interrupt(VCPU *vcpu)
652 {
653 PSCB(vcpu,pending_interruption) = 1;
654 }
656 void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
657 {
658 if (vector & ~0xff) {
659 printf("vcpu_pend_interrupt: bad vector\n");
660 return;
661 }
663 if (vcpu->arch.event_callback_ip) {
664 printf("Deprecated interface. Move to new event based solution\n");
665 return;
666 }
668 if ( VMX_DOMAIN(vcpu) ) {
669 set_bit(vector,VCPU(vcpu,irr));
670 } else {
671 set_bit(vector,PSCBX(vcpu,irr));
672 PSCB(vcpu,pending_interruption) = 1;
673 }
674 }
676 #define IA64_TPR_MMI 0x10000
677 #define IA64_TPR_MIC 0x000f0
679 /* checks to see if a VCPU has any unmasked pending interrupts
680 * if so, returns the highest, else returns SPURIOUS_VECTOR */
681 /* NOTE: Since this gets called from vcpu_get_ivr() and the
682 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
683 * this routine also ignores pscb.interrupt_delivery_enabled
684 * and this must be checked independently; see vcpu_deliverable interrupts() */
685 UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
686 {
687 UINT64 *p, *r, bits, bitnum, mask, i, vector;
689 if (vcpu->arch.event_callback_ip)
690 return SPURIOUS_VECTOR;
692 /* Always check pending event, since guest may just ack the
693 * event injection without handle. Later guest may throw out
694 * the event itself.
695 */
696 check_start:
697 if (event_pending(vcpu) &&
698 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
699 &PSCBX(vcpu, insvc[0])))
700 vcpu_pend_interrupt(vcpu, vcpu->domain->shared_info->arch.evtchn_vector);
702 p = &PSCBX(vcpu,irr[3]);
703 r = &PSCBX(vcpu,insvc[3]);
704 for (i = 3; ; p--, r--, i--) {
705 bits = *p ;
706 if (bits) break; // got a potential interrupt
707 if (*r) {
708 // nothing in this word which is pending+inservice
709 // but there is one inservice which masks lower
710 return SPURIOUS_VECTOR;
711 }
712 if (i == 0) {
713 // checked all bits... nothing pending+inservice
714 return SPURIOUS_VECTOR;
715 }
716 }
717 // have a pending,deliverable interrupt... see if it is masked
718 bitnum = ia64_fls(bits);
719 //printf("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
720 vector = bitnum+(i*64);
721 mask = 1L << bitnum;
722 /* sanity check for guest timer interrupt */
723 if (vector == (PSCB(vcpu,itv) & 0xff)) {
724 uint64_t now = ia64_get_itc();
725 if (now < PSCBX(vcpu,domain_itm)) {
726 // printk("Ooops, pending guest timer before its due\n");
727 PSCBX(vcpu,irr[i]) &= ~mask;
728 goto check_start;
729 }
730 }
731 //printf("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
732 if (*r >= mask) {
733 // masked by equal inservice
734 //printf("but masked by equal inservice\n");
735 return SPURIOUS_VECTOR;
736 }
737 if (PSCB(vcpu,tpr) & IA64_TPR_MMI) {
738 // tpr.mmi is set
739 //printf("but masked by tpr.mmi\n");
740 return SPURIOUS_VECTOR;
741 }
742 if (((PSCB(vcpu,tpr) & IA64_TPR_MIC) + 15) >= vector) {
743 //tpr.mic masks class
744 //printf("but masked by tpr.mic\n");
745 return SPURIOUS_VECTOR;
746 }
748 //printf("returned to caller\n");
749 return vector;
750 }
752 UINT64 vcpu_deliverable_interrupts(VCPU *vcpu)
753 {
754 return (vcpu_get_psr_i(vcpu) &&
755 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
756 }
758 UINT64 vcpu_deliverable_timer(VCPU *vcpu)
759 {
760 return (vcpu_get_psr_i(vcpu) &&
761 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu,itv));
762 }
764 IA64FAULT vcpu_get_lid(VCPU *vcpu, UINT64 *pval)
765 {
766 /* Use EID=0, ID=vcpu_id. */
767 *pval = vcpu->vcpu_id << 24;
768 return IA64_NO_FAULT;
769 }
771 IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
772 {
773 int i;
774 UINT64 vector, mask;
776 #define HEARTBEAT_FREQ 16 // period in seconds
777 #ifdef HEARTBEAT_FREQ
778 #define N_DOMS 16 // period in seconds
779 #if 0
780 static long count[N_DOMS] = { 0 };
781 #endif
782 static long nonclockcount[N_DOMS] = { 0 };
783 unsigned domid = vcpu->domain->domain_id;
784 #endif
785 #ifdef IRQ_DEBUG
786 static char firstivr = 1;
787 static char firsttime[256];
788 if (firstivr) {
789 int i;
790 for (i=0;i<256;i++) firsttime[i]=1;
791 firstivr=0;
792 }
793 #endif
795 vector = vcpu_check_pending_interrupts(vcpu);
796 if (vector == SPURIOUS_VECTOR) {
797 PSCB(vcpu,pending_interruption) = 0;
798 *pval = vector;
799 return IA64_NO_FAULT;
800 }
801 #ifdef HEARTBEAT_FREQ
802 if (domid >= N_DOMS) domid = N_DOMS-1;
803 #if 0
804 if (vector == (PSCB(vcpu,itv) & 0xff)) {
805 if (!(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) {
806 printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
807 domid, count[domid], nonclockcount[domid]);
808 //count[domid] = 0;
809 //dump_runq();
810 }
811 }
812 #endif
813 else nonclockcount[domid]++;
814 #endif
815 // now have an unmasked, pending, deliverable vector!
816 // getting ivr has "side effects"
817 #ifdef IRQ_DEBUG
818 if (firsttime[vector]) {
819 printf("*** First get_ivr on vector=%lu,itc=%lx\n",
820 vector,ia64_get_itc());
821 firsttime[vector]=0;
822 }
823 #endif
824 /* if delivering a timer interrupt, remember domain_itm, which
825 * needs to be done before clearing irr
826 */
827 if (vector == (PSCB(vcpu,itv) & 0xff)) {
828 PSCBX(vcpu,domain_itm_last) = PSCBX(vcpu,domain_itm);
829 }
831 i = vector >> 6;
832 mask = 1L << (vector & 0x3f);
833 //printf("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
834 PSCBX(vcpu,insvc[i]) |= mask;
835 PSCBX(vcpu,irr[i]) &= ~mask;
836 //PSCB(vcpu,pending_interruption)--;
837 *pval = vector;
838 return IA64_NO_FAULT;
839 }
841 IA64FAULT vcpu_get_tpr(VCPU *vcpu, UINT64 *pval)
842 {
843 *pval = PSCB(vcpu,tpr);
844 return (IA64_NO_FAULT);
845 }
847 IA64FAULT vcpu_get_eoi(VCPU *vcpu, UINT64 *pval)
848 {
849 *pval = 0L; // reads of eoi always return 0
850 return (IA64_NO_FAULT);
851 }
853 IA64FAULT vcpu_get_irr0(VCPU *vcpu, UINT64 *pval)
854 {
855 *pval = PSCBX(vcpu, irr[0]);
856 return (IA64_NO_FAULT);
857 }
859 IA64FAULT vcpu_get_irr1(VCPU *vcpu, UINT64 *pval)
860 {
861 *pval = PSCBX(vcpu, irr[1]);
862 return (IA64_NO_FAULT);
863 }
865 IA64FAULT vcpu_get_irr2(VCPU *vcpu, UINT64 *pval)
866 {
867 *pval = PSCBX(vcpu, irr[2]);
868 return (IA64_NO_FAULT);
869 }
871 IA64FAULT vcpu_get_irr3(VCPU *vcpu, UINT64 *pval)
872 {
873 *pval = PSCBX(vcpu, irr[3]);
874 return (IA64_NO_FAULT);
875 }
877 IA64FAULT vcpu_get_itv(VCPU *vcpu, UINT64 *pval)
878 {
879 *pval = PSCB(vcpu,itv);
880 return (IA64_NO_FAULT);
881 }
883 IA64FAULT vcpu_get_pmv(VCPU *vcpu, UINT64 *pval)
884 {
885 *pval = PSCB(vcpu,pmv);
886 return (IA64_NO_FAULT);
887 }
889 IA64FAULT vcpu_get_cmcv(VCPU *vcpu, UINT64 *pval)
890 {
891 *pval = PSCB(vcpu,cmcv);
892 return (IA64_NO_FAULT);
893 }
895 IA64FAULT vcpu_get_lrr0(VCPU *vcpu, UINT64 *pval)
896 {
897 // fix this when setting values other than m-bit is supported
898 printf("vcpu_get_lrr0: Unmasked interrupts unsupported\n");
899 *pval = (1L << 16);
900 return (IA64_NO_FAULT);
901 }
903 IA64FAULT vcpu_get_lrr1(VCPU *vcpu, UINT64 *pval)
904 {
905 // fix this when setting values other than m-bit is supported
906 printf("vcpu_get_lrr1: Unmasked interrupts unsupported\n");
907 *pval = (1L << 16);
908 return (IA64_NO_FAULT);
909 }
911 IA64FAULT vcpu_set_lid(VCPU *vcpu, UINT64 val)
912 {
913 printf("vcpu_set_lid: Setting cr.lid is unsupported\n");
914 return (IA64_ILLOP_FAULT);
915 }
917 IA64FAULT vcpu_set_tpr(VCPU *vcpu, UINT64 val)
918 {
919 if (val & 0xff00) return IA64_RSVDREG_FAULT;
920 PSCB(vcpu,tpr) = val;
921 /* This can unmask interrupts. */
922 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
923 PSCB(vcpu,pending_interruption) = 1;
924 return (IA64_NO_FAULT);
925 }
927 IA64FAULT vcpu_set_eoi(VCPU *vcpu, UINT64 val)
928 {
929 UINT64 *p, bits, vec, bitnum;
930 int i;
932 p = &PSCBX(vcpu,insvc[3]);
933 for (i = 3; (i >= 0) && !(bits = *p); i--, p--);
934 if (i < 0) {
935 printf("Trying to EOI interrupt when none are in-service.\n");
936 return IA64_NO_FAULT;
937 }
938 bitnum = ia64_fls(bits);
939 vec = bitnum + (i*64);
940 /* clear the correct bit */
941 bits &= ~(1L << bitnum);
942 *p = bits;
943 /* clearing an eoi bit may unmask another pending interrupt... */
944 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
945 // worry about this later... Linux only calls eoi
946 // with interrupts disabled
947 printf("Trying to EOI interrupt with interrupts enabled\n");
948 }
949 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
950 PSCB(vcpu,pending_interruption) = 1;
951 //printf("YYYYY vcpu_set_eoi: Successful\n");
952 return (IA64_NO_FAULT);
953 }
955 IA64FAULT vcpu_set_lrr0(VCPU *vcpu, UINT64 val)
956 {
957 if (!(val & (1L << 16))) {
958 printf("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
959 return (IA64_ILLOP_FAULT);
960 }
961 // no place to save this state but nothing to do anyway
962 return (IA64_NO_FAULT);
963 }
965 IA64FAULT vcpu_set_lrr1(VCPU *vcpu, UINT64 val)
966 {
967 if (!(val & (1L << 16))) {
968 printf("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
969 return (IA64_ILLOP_FAULT);
970 }
971 // no place to save this state but nothing to do anyway
972 return (IA64_NO_FAULT);
973 }
975 IA64FAULT vcpu_set_itv(VCPU *vcpu, UINT64 val)
976 {
977 /* Check reserved fields. */
978 if (val & 0xef00)
979 return (IA64_ILLOP_FAULT);
980 PSCB(vcpu,itv) = val;
981 if (val & 0x10000) {
982 /* Disable itm. */
983 PSCBX(vcpu,domain_itm) = 0;
984 }
985 else vcpu_set_next_timer(vcpu);
986 return (IA64_NO_FAULT);
987 }
989 IA64FAULT vcpu_set_pmv(VCPU *vcpu, UINT64 val)
990 {
991 if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT;
992 PSCB(vcpu,pmv) = val;
993 return (IA64_NO_FAULT);
994 }
996 IA64FAULT vcpu_set_cmcv(VCPU *vcpu, UINT64 val)
997 {
998 if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT;
999 PSCB(vcpu,cmcv) = val;
1000 return (IA64_NO_FAULT);
1003 /**************************************************************************
1004 VCPU temporary register access routines
1005 **************************************************************************/
1006 UINT64 vcpu_get_tmp(VCPU *vcpu, UINT64 index)
1008 if (index > 7) return 0;
1009 return PSCB(vcpu,tmp[index]);
1012 void vcpu_set_tmp(VCPU *vcpu, UINT64 index, UINT64 val)
1014 if (index <= 7) PSCB(vcpu,tmp[index]) = val;
1017 /**************************************************************************
1018 Interval timer routines
1019 **************************************************************************/
1021 BOOLEAN vcpu_timer_disabled(VCPU *vcpu)
1023 UINT64 itv = PSCB(vcpu,itv);
1024 return(!itv || !!(itv & 0x10000));
1027 BOOLEAN vcpu_timer_inservice(VCPU *vcpu)
1029 UINT64 itv = PSCB(vcpu,itv);
1030 return (test_bit(itv, PSCBX(vcpu,insvc)));
1033 BOOLEAN vcpu_timer_expired(VCPU *vcpu)
1035 unsigned long domain_itm = PSCBX(vcpu,domain_itm);
1036 unsigned long now = ia64_get_itc();
1038 if (!domain_itm) return FALSE;
1039 if (now < domain_itm) return FALSE;
1040 if (vcpu_timer_disabled(vcpu)) return FALSE;
1041 return TRUE;
1044 void vcpu_safe_set_itm(unsigned long val)
1046 unsigned long epsilon = 100;
1047 unsigned long flags;
1048 UINT64 now = ia64_get_itc();
1050 local_irq_save(flags);
1051 while (1) {
1052 //printf("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1053 ia64_set_itm(val);
1054 if (val > (now = ia64_get_itc())) break;
1055 val = now + epsilon;
1056 epsilon <<= 1;
1058 local_irq_restore(flags);
1061 void vcpu_set_next_timer(VCPU *vcpu)
1063 UINT64 d = PSCBX(vcpu,domain_itm);
1064 //UINT64 s = PSCBX(vcpu,xen_itm);
1065 UINT64 s = local_cpu_data->itm_next;
1066 UINT64 now = ia64_get_itc();
1068 /* gloss over the wraparound problem for now... we know it exists
1069 * but it doesn't matter right now */
1071 if (is_idle_domain(vcpu->domain)) {
1072 // printf("****** vcpu_set_next_timer called during idle!!\n");
1073 vcpu_safe_set_itm(s);
1074 return;
1076 //s = PSCBX(vcpu,xen_itm);
1077 if (d && (d > now) && (d < s)) {
1078 vcpu_safe_set_itm(d);
1079 //using_domain_as_itm++;
1081 else {
1082 vcpu_safe_set_itm(s);
1083 //using_xen_as_itm++;
1087 IA64FAULT vcpu_set_itm(VCPU *vcpu, UINT64 val)
1089 //UINT now = ia64_get_itc();
1091 //if (val < now) val = now + 1000;
1092 //printf("*** vcpu_set_itm: called with %lx\n",val);
1093 PSCBX(vcpu,domain_itm) = val;
1094 vcpu_set_next_timer(vcpu);
1095 return (IA64_NO_FAULT);
1098 IA64FAULT vcpu_set_itc(VCPU *vcpu, UINT64 val)
1100 #define DISALLOW_SETTING_ITC_FOR_NOW
1101 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1102 static int did_print;
1103 if (!did_print) {
1104 printf("vcpu_set_itc: Setting ar.itc is currently disabled\n");
1105 printf("(this message is only displayed one)\n");
1106 did_print = 1;
1108 #else
1109 UINT64 oldnow = ia64_get_itc();
1110 UINT64 olditm = PSCBX(vcpu,domain_itm);
1111 unsigned long d = olditm - oldnow;
1112 unsigned long x = local_cpu_data->itm_next - oldnow;
1114 UINT64 newnow = val, min_delta;
1116 local_irq_disable();
1117 if (olditm) {
1118 printf("**** vcpu_set_itc(%lx): vitm changed to %lx\n",val,newnow+d);
1119 PSCBX(vcpu,domain_itm) = newnow + d;
1121 local_cpu_data->itm_next = newnow + x;
1122 d = PSCBX(vcpu,domain_itm);
1123 x = local_cpu_data->itm_next;
1125 ia64_set_itc(newnow);
1126 if (d && (d > newnow) && (d < x)) {
1127 vcpu_safe_set_itm(d);
1128 //using_domain_as_itm++;
1130 else {
1131 vcpu_safe_set_itm(x);
1132 //using_xen_as_itm++;
1134 local_irq_enable();
1135 #endif
1136 return (IA64_NO_FAULT);
1139 IA64FAULT vcpu_get_itm(VCPU *vcpu, UINT64 *pval)
1141 //FIXME: Implement this
1142 printf("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1143 return (IA64_NO_FAULT);
1144 //return (IA64_ILLOP_FAULT);
1147 IA64FAULT vcpu_get_itc(VCPU *vcpu, UINT64 *pval)
1149 //TODO: Implement this
1150 printf("vcpu_get_itc: Getting ar.itc is unsupported\n");
1151 return (IA64_ILLOP_FAULT);
1154 void vcpu_pend_timer(VCPU *vcpu)
1156 UINT64 itv = PSCB(vcpu,itv) & 0xff;
1158 if (vcpu_timer_disabled(vcpu)) return;
1159 //if (vcpu_timer_inservice(vcpu)) return;
1160 if (PSCBX(vcpu,domain_itm_last) == PSCBX(vcpu,domain_itm)) {
1161 // already delivered an interrupt for this so
1162 // don't deliver another
1163 return;
1165 if (vcpu->arch.event_callback_ip) {
1166 /* A small window may occur when injecting vIRQ while related
1167 * handler has not been registered. Don't fire in such case.
1168 */
1169 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1170 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1171 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1173 } else
1174 vcpu_pend_interrupt(vcpu, itv);
1177 // returns true if ready to deliver a timer interrupt too early
1178 UINT64 vcpu_timer_pending_early(VCPU *vcpu)
1180 UINT64 now = ia64_get_itc();
1181 UINT64 itm = PSCBX(vcpu,domain_itm);
1183 if (vcpu_timer_disabled(vcpu)) return 0;
1184 if (!itm) return 0;
1185 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1188 /**************************************************************************
1189 Privileged operation emulation routines
1190 **************************************************************************/
1192 static void
1193 vcpu_force_tlb_miss(VCPU* vcpu, UINT64 ifa)
1195 PSCB(vcpu, ifa) = ifa;
1196 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1197 vcpu_thash(current, ifa, &PSCB(current, iha));
1200 IA64FAULT vcpu_force_inst_miss(VCPU *vcpu, UINT64 ifa)
1202 vcpu_force_tlb_miss(vcpu, ifa);
1203 return (vcpu_get_rr_ve(vcpu, ifa)? IA64_INST_TLB_VECTOR: IA64_ALT_INST_TLB_VECTOR);
1206 IA64FAULT vcpu_force_data_miss(VCPU *vcpu, UINT64 ifa)
1208 vcpu_force_tlb_miss(vcpu, ifa);
1209 return (vcpu_get_rr_ve(vcpu, ifa)? IA64_DATA_TLB_VECTOR: IA64_ALT_DATA_TLB_VECTOR);
1212 IA64FAULT vcpu_rfi(VCPU *vcpu)
1214 // TODO: Only allowed for current vcpu
1215 PSR psr;
1216 UINT64 int_enable, regspsr = 0;
1217 UINT64 ifs;
1218 REGS *regs = vcpu_regs(vcpu);
1219 extern void dorfirfi(void);
1221 psr.i64 = PSCB(vcpu,ipsr);
1222 if (psr.ia64_psr.cpl < 3) psr.ia64_psr.cpl = 2;
1223 int_enable = psr.ia64_psr.i;
1224 if (psr.ia64_psr.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
1225 if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it) vcpu_set_metaphysical_mode(vcpu,FALSE);
1226 else vcpu_set_metaphysical_mode(vcpu,TRUE);
1227 psr.ia64_psr.ic = 1; psr.ia64_psr.i = 1;
1228 psr.ia64_psr.dt = 1; psr.ia64_psr.rt = 1; psr.ia64_psr.it = 1;
1229 psr.ia64_psr.bn = 1;
1230 //psr.pk = 1; // checking pkeys shouldn't be a problem but seems broken
1231 if (psr.ia64_psr.be) {
1232 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
1233 return (IA64_ILLOP_FAULT);
1235 PSCB(vcpu,incomplete_regframe) = 0; // is this necessary?
1236 ifs = PSCB(vcpu,ifs);
1237 //if ((ifs & regs->cr_ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
1238 //if ((ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
1239 if (ifs & regs->cr_ifs & 0x8000000000000000L) {
1240 // TODO: validate PSCB(vcpu,iip)
1241 // TODO: PSCB(vcpu,ipsr) = psr;
1242 PSCB(vcpu,ipsr) = psr.i64;
1243 // now set up the trampoline
1244 regs->cr_iip = *(unsigned long *)dorfirfi; // function pointer!!
1245 __asm__ __volatile ("mov %0=psr;;":"=r"(regspsr)::"memory");
1246 regs->cr_ipsr = regspsr & ~(IA64_PSR_I | IA64_PSR_IC | IA64_PSR_BN);
1248 else {
1249 regs->cr_ipsr = psr.i64;
1250 regs->cr_iip = PSCB(vcpu,iip);
1252 PSCB(vcpu,interrupt_collection_enabled) = 1;
1253 vcpu_bsw1(vcpu);
1254 vcpu->vcpu_info->evtchn_upcall_mask = !int_enable;
1255 return (IA64_NO_FAULT);
1258 IA64FAULT vcpu_cover(VCPU *vcpu)
1260 // TODO: Only allowed for current vcpu
1261 REGS *regs = vcpu_regs(vcpu);
1263 if (!PSCB(vcpu,interrupt_collection_enabled)) {
1264 if (!PSCB(vcpu,incomplete_regframe))
1265 PSCB(vcpu,ifs) = regs->cr_ifs;
1266 else PSCB(vcpu,incomplete_regframe) = 0;
1268 regs->cr_ifs = 0;
1269 return (IA64_NO_FAULT);
1272 IA64FAULT vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
1274 UINT64 pta = PSCB(vcpu,pta);
1275 UINT64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1276 UINT64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT)-1);
1277 UINT64 Mask = (1L << pta_sz) - 1;
1278 UINT64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1279 UINT64 compMask_60_15 = ~Mask_60_15;
1280 UINT64 rr_ps = vcpu_get_rr_ps(vcpu,vadr);
1281 UINT64 VHPT_offset = (vadr >> rr_ps) << 3;
1282 UINT64 VHPT_addr1 = vadr & 0xe000000000000000L;
1283 UINT64 VHPT_addr2a =
1284 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1285 UINT64 VHPT_addr2b =
1286 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1287 UINT64 VHPT_addr3 = VHPT_offset & 0x7fff;
1288 UINT64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1289 VHPT_addr3;
1291 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1292 *pval = VHPT_addr;
1293 return (IA64_NO_FAULT);
1296 IA64FAULT vcpu_ttag(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
1298 printf("vcpu_ttag: ttag instruction unsupported\n");
1299 return (IA64_ILLOP_FAULT);
1302 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1304 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1305 static inline int range_overlap (u64 b1, u64 e1, u64 b2, u64 e2)
1307 return (b1 <= e2) && (e1 >= b2);
1310 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1311 Note: LSBs of base inside page_size are ignored. */
1312 static inline void
1313 check_xen_space_overlap (const char *func, u64 base, u64 page_size)
1315 /* Mask LSBs of base. */
1316 base &= ~(page_size - 1);
1318 /* FIXME: ideally an MCA should be generated... */
1319 if (range_overlap (HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
1320 base, base + page_size))
1321 panic_domain (NULL, "%s on Xen virtual space (%lx)\n",
1322 func, base);
1325 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1326 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY *trp, UINT64 ifa, UINT64 rid)
1328 return trp->rid == rid
1329 && ifa >= trp->vadr
1330 && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1333 static inline int vcpu_match_tr_entry(TR_ENTRY *trp, UINT64 ifa, UINT64 rid)
1335 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1338 static inline int
1339 vcpu_match_tr_entry_range(TR_ENTRY *trp, UINT64 rid, u64 b, u64 e)
1341 return trp->rid == rid
1342 && trp->pte.p
1343 && range_overlap (b, e,
1344 trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1348 static TR_ENTRY*
1349 vcpu_tr_lookup(VCPU* vcpu, unsigned long va, UINT64 rid, BOOLEAN is_data)
1351 unsigned char* regions;
1352 TR_ENTRY *trp;
1353 int tr_max;
1354 int i;
1356 if (is_data) {
1357 // data
1358 regions = &vcpu->arch.dtr_regions;
1359 trp = vcpu->arch.dtrs;
1360 tr_max = sizeof(vcpu->arch.dtrs)/sizeof(vcpu->arch.dtrs[0]);
1361 } else {
1362 // instruction
1363 regions = &vcpu->arch.itr_regions;
1364 trp = vcpu->arch.itrs;
1365 tr_max = sizeof(vcpu->arch.itrs)/sizeof(vcpu->arch.itrs[0]);
1368 if (!vcpu_quick_region_check(*regions, va)) {
1369 return NULL;
1371 for (i = 0; i < tr_max; i++, trp++) {
1372 if (vcpu_match_tr_entry(trp, va, rid)) {
1373 return trp;
1376 return NULL;
1379 // return value
1380 // 0: failure
1381 // 1: success
1382 int
1383 vcpu_get_domain_bundle(VCPU* vcpu, REGS* regs, UINT64 gip, IA64_BUNDLE* bundle)
1385 UINT64 gpip;// guest pseudo phyiscal ip
1386 unsigned long vaddr;
1387 struct page_info* page;
1389 again:
1390 #if 0
1391 // Currently xen doesn't track psr.it bits.
1392 // it assumes always psr.it = 1.
1393 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1394 gpip = gip;
1395 } else
1396 #endif
1398 unsigned long region = REGION_NUMBER(gip);
1399 unsigned long rr = PSCB(vcpu, rrs)[region];
1400 unsigned long rid = rr & RR_RID_MASK;
1401 BOOLEAN swap_rr0;
1402 TR_ENTRY* trp;
1404 // vcpu->arch.{i, d}tlb are volatile,
1405 // copy its value to the variable, tr, before use.
1406 TR_ENTRY tr;
1408 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1409 if (trp != NULL) {
1410 tr = *trp;
1411 goto found;
1413 // When it failed to get a bundle, itlb miss is reflected.
1414 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1415 tr = PSCBX(vcpu, itlb);
1416 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1417 //DPRINTK("%s gip 0x%lx gpip 0x%lx\n", __func__, gip, gpip);
1418 goto found;
1420 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1421 if (trp != NULL) {
1422 tr = *trp;
1423 goto found;
1425 #if 0
1426 tr = PSCBX(vcpu, dtlb);
1427 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1428 goto found;
1430 #endif
1432 // try to access gip with guest virtual address
1433 // This may cause tlb miss. see vcpu_translate(). Be careful!
1434 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1435 if (swap_rr0) {
1436 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
1438 *bundle = __get_domain_bundle(gip);
1439 if (swap_rr0) {
1440 set_metaphysical_rr0();
1442 if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
1443 DPRINTK("%s gip 0x%lx\n", __func__, gip);
1444 return 0;
1446 return 1;
1448 found:
1449 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1450 (gip & ((1 << tr.ps) - 1));
1453 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1454 page = virt_to_page(vaddr);
1455 if (get_page(page, vcpu->domain) == 0) {
1456 if (page_get_owner(page) != vcpu->domain) {
1457 // This page might be a page granted by another
1458 // domain.
1459 panic_domain(regs,
1460 "domain tries to execute foreign domain "
1461 "page which might be mapped by grant "
1462 "table.\n");
1464 goto again;
1466 *bundle = *((IA64_BUNDLE*)vaddr);
1467 put_page(page);
1468 return 1;
1471 IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pteval, UINT64 *itir, UINT64 *iha)
1473 unsigned long region = address >> 61;
1474 unsigned long pta, rid, rr;
1475 union pte_flags pte;
1476 TR_ENTRY *trp;
1478 if (PSCB(vcpu,metaphysical_mode) && !(!is_data && region)) {
1479 // dom0 may generate an uncacheable physical address (msb=1)
1480 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1481 // FIXME: This seems to happen even though it shouldn't. Need to track
1482 // this down, but since it has been apparently harmless, just flag it for now
1483 // panic_domain(vcpu_regs(vcpu),
1485 /*
1486 * Guest may execute itc.d and rfi with psr.dt=0
1487 * When VMM try to fetch opcode, tlb miss may happen,
1488 * At this time PSCB(vcpu,metaphysical_mode)=1,
1489 * region=5,VMM need to handle this tlb miss as if
1490 * PSCB(vcpu,metaphysical_mode)=0
1491 */
1492 printk("vcpu_translate: bad physical address: 0x%lx at %lx\n",
1493 address, vcpu_regs (vcpu)->cr_iip);
1495 } else {
1496 *pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS |
1497 _PAGE_PL_2 | _PAGE_AR_RWX;
1498 *itir = PAGE_SHIFT << 2;
1499 perfc_incrc(phys_translate);
1500 return IA64_NO_FAULT;
1503 else if (!region && warn_region0_address) {
1504 REGS *regs = vcpu_regs(vcpu);
1505 unsigned long viip = PSCB(vcpu,iip);
1506 unsigned long vipsr = PSCB(vcpu,ipsr);
1507 unsigned long iip = regs->cr_iip;
1508 unsigned long ipsr = regs->cr_ipsr;
1509 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1510 address, viip, vipsr, iip, ipsr);
1513 rr = PSCB(vcpu,rrs)[region];
1514 rid = rr & RR_RID_MASK;
1515 if (is_data) {
1516 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1517 if (trp != NULL) {
1518 *pteval = trp->pte.val;
1519 *itir = trp->itir;
1520 perfc_incrc(tr_translate);
1521 return IA64_NO_FAULT;
1524 // FIXME?: check itr's for data accesses too, else bad things happen?
1525 /* else */ {
1526 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1527 if (trp != NULL) {
1528 *pteval = trp->pte.val;
1529 *itir = trp->itir;
1530 perfc_incrc(tr_translate);
1531 return IA64_NO_FAULT;
1535 /* check 1-entry TLB */
1536 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1537 trp = &vcpu->arch.dtlb;
1538 pte = trp->pte;
1539 if (/* is_data && */ pte.p
1540 && vcpu_match_tr_entry_no_p(trp,address,rid)) {
1541 *pteval = pte.val;
1542 *itir = trp->itir;
1543 perfc_incrc(dtlb_translate);
1544 return IA64_USE_TLB;
1547 /* check guest VHPT */
1548 pta = PSCB(vcpu,pta);
1549 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1550 panic_domain(vcpu_regs(vcpu),"can't do long format VHPT\n");
1551 //return (is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR);
1554 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1555 // note: architecturally, iha is optionally set for alt faults but
1556 // xenlinux depends on it so should document it as part of PV interface
1557 vcpu_thash(vcpu, address, iha);
1558 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE))
1559 return (is_data ? IA64_ALT_DATA_TLB_VECTOR : IA64_ALT_INST_TLB_VECTOR);
1561 /* avoid recursively walking (short format) VHPT */
1562 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1563 return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
1565 if (!__access_ok (*iha)
1566 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1567 // virtual VHPT walker "missed" in TLB
1568 return IA64_VHPT_FAULT;
1570 /*
1571 * Optimisation: this VHPT walker aborts on not-present pages
1572 * instead of inserting a not-present translation, this allows
1573 * vectoring directly to the miss handler.
1574 */
1575 if (!pte.p)
1576 return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
1578 /* found mapping in guest VHPT! */
1579 *itir = rr & RR_PS_MASK;
1580 *pteval = pte.val;
1581 perfc_incrc(vhpt_translate);
1582 return IA64_NO_FAULT;
1585 IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
1587 UINT64 pteval, itir, mask, iha;
1588 IA64FAULT fault;
1590 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1591 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB)
1593 mask = itir_mask(itir);
1594 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1595 return (IA64_NO_FAULT);
1597 return vcpu_force_data_miss(vcpu,vadr);
1600 IA64FAULT vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key)
1602 printf("vcpu_tak: tak instruction unsupported\n");
1603 return (IA64_ILLOP_FAULT);
1604 // HACK ALERT: tak does a thash for now
1605 //return vcpu_thash(vcpu,vadr,key);
1608 /**************************************************************************
1609 VCPU debug breakpoint register access routines
1610 **************************************************************************/
1612 IA64FAULT vcpu_set_dbr(VCPU *vcpu, UINT64 reg, UINT64 val)
1614 // TODO: unimplemented DBRs return a reserved register fault
1615 // TODO: Should set Logical CPU state, not just physical
1616 ia64_set_dbr(reg,val);
1617 return (IA64_NO_FAULT);
1620 IA64FAULT vcpu_set_ibr(VCPU *vcpu, UINT64 reg, UINT64 val)
1622 // TODO: unimplemented IBRs return a reserved register fault
1623 // TODO: Should set Logical CPU state, not just physical
1624 ia64_set_ibr(reg,val);
1625 return (IA64_NO_FAULT);
1628 IA64FAULT vcpu_get_dbr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1630 // TODO: unimplemented DBRs return a reserved register fault
1631 UINT64 val = ia64_get_dbr(reg);
1632 *pval = val;
1633 return (IA64_NO_FAULT);
1636 IA64FAULT vcpu_get_ibr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1638 // TODO: unimplemented IBRs return a reserved register fault
1639 UINT64 val = ia64_get_ibr(reg);
1640 *pval = val;
1641 return (IA64_NO_FAULT);
1644 /**************************************************************************
1645 VCPU performance monitor register access routines
1646 **************************************************************************/
1648 IA64FAULT vcpu_set_pmc(VCPU *vcpu, UINT64 reg, UINT64 val)
1650 // TODO: Should set Logical CPU state, not just physical
1651 // NOTE: Writes to unimplemented PMC registers are discarded
1652 #ifdef DEBUG_PFMON
1653 printf("vcpu_set_pmc(%x,%lx)\n",reg,val);
1654 #endif
1655 ia64_set_pmc(reg,val);
1656 return (IA64_NO_FAULT);
1659 IA64FAULT vcpu_set_pmd(VCPU *vcpu, UINT64 reg, UINT64 val)
1661 // TODO: Should set Logical CPU state, not just physical
1662 // NOTE: Writes to unimplemented PMD registers are discarded
1663 #ifdef DEBUG_PFMON
1664 printf("vcpu_set_pmd(%x,%lx)\n",reg,val);
1665 #endif
1666 ia64_set_pmd(reg,val);
1667 return (IA64_NO_FAULT);
1670 IA64FAULT vcpu_get_pmc(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1672 // NOTE: Reads from unimplemented PMC registers return zero
1673 UINT64 val = (UINT64)ia64_get_pmc(reg);
1674 #ifdef DEBUG_PFMON
1675 printf("%lx=vcpu_get_pmc(%x)\n",val,reg);
1676 #endif
1677 *pval = val;
1678 return (IA64_NO_FAULT);
1681 IA64FAULT vcpu_get_pmd(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1683 // NOTE: Reads from unimplemented PMD registers return zero
1684 UINT64 val = (UINT64)ia64_get_pmd(reg);
1685 #ifdef DEBUG_PFMON
1686 printf("%lx=vcpu_get_pmd(%x)\n",val,reg);
1687 #endif
1688 *pval = val;
1689 return (IA64_NO_FAULT);
1692 /**************************************************************************
1693 VCPU banked general register access routines
1694 **************************************************************************/
1695 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1696 do{ \
1697 __asm__ __volatile__ ( \
1698 ";;extr.u %0 = %3,%6,16;;\n" \
1699 "dep %1 = %0, %1, 0, 16;;\n" \
1700 "st8 [%4] = %1\n" \
1701 "extr.u %0 = %2, 16, 16;;\n" \
1702 "dep %3 = %0, %3, %6, 16;;\n" \
1703 "st8 [%5] = %3\n" \
1704 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1705 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1706 }while(0)
1708 IA64FAULT vcpu_bsw0(VCPU *vcpu)
1710 // TODO: Only allowed for current vcpu
1711 REGS *regs = vcpu_regs(vcpu);
1712 unsigned long *r = &regs->r16;
1713 unsigned long *b0 = &PSCB(vcpu,bank0_regs[0]);
1714 unsigned long *b1 = &PSCB(vcpu,bank1_regs[0]);
1715 unsigned long *runat = &regs->eml_unat;
1716 unsigned long *b0unat = &PSCB(vcpu,vbnat);
1717 unsigned long *b1unat = &PSCB(vcpu,vnat);
1719 unsigned long i;
1721 if(VMX_DOMAIN(vcpu)){
1722 if(VCPU(vcpu,vpsr)&IA64_PSR_BN){
1723 for (i = 0; i < 16; i++) { *b1++ = *r; *r++ = *b0++; }
1724 vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1725 VCPU(vcpu,vpsr) &= ~IA64_PSR_BN;
1727 }else{
1728 if (PSCB(vcpu,banknum)) {
1729 for (i = 0; i < 16; i++) { *b1++ = *r; *r++ = *b0++; }
1730 vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1731 PSCB(vcpu,banknum) = 0;
1734 return (IA64_NO_FAULT);
1737 #define vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1738 do{ \
1739 __asm__ __volatile__ ( \
1740 ";;extr.u %0 = %3,%6,16;;\n" \
1741 "dep %1 = %0, %1, 16, 16;;\n" \
1742 "st8 [%4] = %1\n" \
1743 "extr.u %0 = %2, 0, 16;;\n" \
1744 "dep %3 = %0, %3, %6, 16;;\n" \
1745 "st8 [%5] = %3\n" \
1746 ::"r"(i),"r"(*b0unat),"r"(*b1unat),"r"(*runat),"r"(b0unat), \
1747 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1748 }while(0)
1750 IA64FAULT vcpu_bsw1(VCPU *vcpu)
1752 // TODO: Only allowed for current vcpu
1753 REGS *regs = vcpu_regs(vcpu);
1754 unsigned long *r = &regs->r16;
1755 unsigned long *b0 = &PSCB(vcpu,bank0_regs[0]);
1756 unsigned long *b1 = &PSCB(vcpu,bank1_regs[0]);
1757 unsigned long *runat = &regs->eml_unat;
1758 unsigned long *b0unat = &PSCB(vcpu,vbnat);
1759 unsigned long *b1unat = &PSCB(vcpu,vnat);
1761 unsigned long i;
1763 if(VMX_DOMAIN(vcpu)){
1764 if(!(VCPU(vcpu,vpsr)&IA64_PSR_BN)){
1765 for (i = 0; i < 16; i++) { *b0++ = *r; *r++ = *b1++; }
1766 vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1767 VCPU(vcpu,vpsr) |= IA64_PSR_BN;
1769 }else{
1770 if (!PSCB(vcpu,banknum)) {
1771 for (i = 0; i < 16; i++) { *b0++ = *r; *r++ = *b1++; }
1772 vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1773 PSCB(vcpu,banknum) = 1;
1776 return (IA64_NO_FAULT);
1779 /**************************************************************************
1780 VCPU cpuid access routines
1781 **************************************************************************/
1784 IA64FAULT vcpu_get_cpuid(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1786 // FIXME: This could get called as a result of a rsvd-reg fault
1787 // if reg > 3
1788 switch(reg) {
1789 case 0:
1790 memcpy(pval,"Xen/ia64",8);
1791 break;
1792 case 1:
1793 *pval = 0;
1794 break;
1795 case 2:
1796 *pval = 0;
1797 break;
1798 case 3:
1799 *pval = ia64_get_cpuid(3);
1800 break;
1801 case 4:
1802 *pval = ia64_get_cpuid(4);
1803 break;
1804 default:
1805 if (reg > (ia64_get_cpuid(3) & 0xff))
1806 return IA64_RSVDREG_FAULT;
1807 *pval = ia64_get_cpuid(reg);
1808 break;
1810 return (IA64_NO_FAULT);
1813 /**************************************************************************
1814 VCPU region register access routines
1815 **************************************************************************/
1817 unsigned long vcpu_get_rr_ve(VCPU *vcpu,UINT64 vadr)
1819 ia64_rr rr;
1821 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
1822 return(rr.ve);
1825 IA64FAULT vcpu_set_rr(VCPU *vcpu, UINT64 reg, UINT64 val)
1827 PSCB(vcpu,rrs)[reg>>61] = val;
1828 // warning: set_one_rr() does it "live"
1829 set_one_rr(reg,val);
1830 return (IA64_NO_FAULT);
1833 IA64FAULT vcpu_get_rr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1835 if(VMX_DOMAIN(vcpu)){
1836 *pval = VMX(vcpu,vrr[reg>>61]);
1837 }else{
1838 *pval = PSCB(vcpu,rrs)[reg>>61];
1840 return (IA64_NO_FAULT);
1843 /**************************************************************************
1844 VCPU protection key register access routines
1845 **************************************************************************/
1847 IA64FAULT vcpu_get_pkr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1849 #ifndef PKR_USE_FIXED
1850 printk("vcpu_get_pkr: called, not implemented yet\n");
1851 return IA64_ILLOP_FAULT;
1852 #else
1853 UINT64 val = (UINT64)ia64_get_pkr(reg);
1854 *pval = val;
1855 return (IA64_NO_FAULT);
1856 #endif
1859 IA64FAULT vcpu_set_pkr(VCPU *vcpu, UINT64 reg, UINT64 val)
1861 #ifndef PKR_USE_FIXED
1862 printk("vcpu_set_pkr: called, not implemented yet\n");
1863 return IA64_ILLOP_FAULT;
1864 #else
1865 // if (reg >= NPKRS) return (IA64_ILLOP_FAULT);
1866 vcpu->pkrs[reg] = val;
1867 ia64_set_pkr(reg,val);
1868 return (IA64_NO_FAULT);
1869 #endif
1872 /**************************************************************************
1873 VCPU translation register access routines
1874 **************************************************************************/
1876 static void
1877 vcpu_set_tr_entry_rid(TR_ENTRY *trp, UINT64 pte,
1878 UINT64 itir, UINT64 ifa, UINT64 rid)
1880 UINT64 ps;
1881 union pte_flags new_pte;
1883 trp->itir = itir;
1884 trp->rid = rid;
1885 ps = trp->ps;
1886 new_pte.val = pte;
1887 if (new_pte.pl < 2) new_pte.pl = 2;
1888 trp->vadr = ifa & ~0xfff;
1889 if (ps > 12) { // "ignore" relevant low-order bits
1890 new_pte.ppn &= ~((1UL<<(ps-12))-1);
1891 trp->vadr &= ~((1UL<<ps)-1);
1894 /* Atomic write. */
1895 trp->pte.val = new_pte.val;
1898 static inline void
1899 vcpu_set_tr_entry(TR_ENTRY *trp, UINT64 pte, UINT64 itir, UINT64 ifa)
1901 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
1902 VCPU(current, rrs[ifa>>61]) & RR_RID_MASK);
1905 IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte,
1906 UINT64 itir, UINT64 ifa)
1908 TR_ENTRY *trp;
1910 if (slot >= NDTRS) return IA64_RSVDREG_FAULT;
1912 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
1914 trp = &PSCBX(vcpu,dtrs[slot]);
1915 //printf("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
1916 vcpu_set_tr_entry(trp,pte,itir,ifa);
1917 vcpu_quick_region_set(PSCBX(vcpu,dtr_regions),ifa);
1919 /*
1920 * FIXME According to spec, vhpt should be purged, but this
1921 * incurs considerable performance loss, since it is safe for
1922 * linux not to purge vhpt, vhpt purge is disabled until a
1923 * feasible way is found.
1925 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
1926 */
1928 return IA64_NO_FAULT;
1931 IA64FAULT vcpu_itr_i(VCPU *vcpu, UINT64 slot, UINT64 pte,
1932 UINT64 itir, UINT64 ifa)
1934 TR_ENTRY *trp;
1936 if (slot >= NITRS) return IA64_RSVDREG_FAULT;
1938 vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
1940 trp = &PSCBX(vcpu,itrs[slot]);
1941 //printf("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
1942 vcpu_set_tr_entry(trp,pte,itir,ifa);
1943 vcpu_quick_region_set(PSCBX(vcpu,itr_regions),ifa);
1945 /*
1946 * FIXME According to spec, vhpt should be purged, but this
1947 * incurs considerable performance loss, since it is safe for
1948 * linux not to purge vhpt, vhpt purge is disabled until a
1949 * feasible way is found.
1951 * vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
1952 */
1954 return IA64_NO_FAULT;
1957 IA64FAULT vcpu_set_itr(VCPU *vcpu, u64 slot, u64 pte,
1958 u64 itir, u64 ifa, u64 rid)
1960 TR_ENTRY *trp;
1962 if (slot >= NITRS)
1963 return IA64_RSVDREG_FAULT;
1964 trp = &PSCBX(vcpu, itrs[slot]);
1965 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
1967 /* Recompute the itr_region. */
1968 vcpu->arch.itr_regions = 0;
1969 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
1970 if (trp->pte.p)
1971 vcpu_quick_region_set(vcpu->arch.itr_regions,
1972 trp->vadr);
1973 return IA64_NO_FAULT;
1976 IA64FAULT vcpu_set_dtr(VCPU *vcpu, u64 slot, u64 pte,
1977 u64 itir, u64 ifa, u64 rid)
1979 TR_ENTRY *trp;
1981 if (slot >= NDTRS)
1982 return IA64_RSVDREG_FAULT;
1983 trp = &PSCBX(vcpu, dtrs[slot]);
1984 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
1986 /* Recompute the dtr_region. */
1987 vcpu->arch.dtr_regions = 0;
1988 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
1989 if (trp->pte.p)
1990 vcpu_quick_region_set(vcpu->arch.dtr_regions,
1991 trp->vadr);
1992 return IA64_NO_FAULT;
1995 /**************************************************************************
1996 VCPU translation cache access routines
1997 **************************************************************************/
1999 void vcpu_itc_no_srlz(VCPU *vcpu, UINT64 IorD, UINT64 vaddr, UINT64 pte, UINT64 mp_pte, UINT64 logps)
2001 unsigned long psr;
2002 unsigned long ps = (vcpu->domain==dom0) ? logps : PAGE_SHIFT;
2004 check_xen_space_overlap ("itc", vaddr, 1UL << logps);
2006 // FIXME, must be inlined or potential for nested fault here!
2007 if ((vcpu->domain==dom0) && (logps < PAGE_SHIFT))
2008 panic_domain (NULL, "vcpu_itc_no_srlz: domain trying to use "
2009 "smaller page size!\n");
2011 BUG_ON(logps > PAGE_SHIFT);
2012 psr = ia64_clear_ic();
2013 ia64_itc(IorD,vaddr,pte,ps); // FIXME: look for bigger mappings
2014 ia64_set_psr(psr);
2015 // ia64_srlz_i(); // no srls req'd, will rfi later
2016 #ifdef VHPT_GLOBAL
2017 if (vcpu->domain==dom0 && ((vaddr >> 61) == 7)) {
2018 // FIXME: this is dangerous... vhpt_flush_address ensures these
2019 // addresses never get flushed. More work needed if this
2020 // ever happens.
2021 //printf("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2022 if (logps > PAGE_SHIFT) vhpt_multiple_insert(vaddr,pte,logps);
2023 else vhpt_insert(vaddr,pte,logps<<2);
2025 // even if domain pagesize is larger than PAGE_SIZE, just put
2026 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2027 else vhpt_insert(vaddr,pte,PAGE_SHIFT<<2);
2028 #endif
2029 if ((mp_pte == -1UL) || (IorD & 0x4)) // don't place in 1-entry TLB
2030 return;
2031 if (IorD & 0x1) {
2032 vcpu_set_tr_entry(&PSCBX(vcpu,itlb),mp_pte,ps<<2,vaddr);
2034 if (IorD & 0x2) {
2035 vcpu_set_tr_entry(&PSCBX(vcpu,dtlb),mp_pte,ps<<2,vaddr);
2039 IA64FAULT vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
2041 unsigned long pteval, logps = itir_ps(itir);
2042 BOOLEAN swap_rr0 = (!(ifa>>61) && PSCB(vcpu,metaphysical_mode));
2043 struct p2m_entry entry;
2045 if (logps < PAGE_SHIFT)
2046 panic_domain (NULL, "vcpu_itc_d: domain trying to use "
2047 "smaller page size!\n");
2049 again:
2050 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2051 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2052 if (!pteval) return IA64_ILLOP_FAULT;
2053 if (swap_rr0) set_one_rr(0x0,PSCB(vcpu,rrs[0]));
2054 vcpu_itc_no_srlz(vcpu,2,ifa,pteval,pte,logps);
2055 if (swap_rr0) set_metaphysical_rr0();
2056 if (p2m_entry_retry(&entry)) {
2057 vcpu_flush_tlb_vhpt_range(ifa, logps);
2058 goto again;
2060 return IA64_NO_FAULT;
2063 IA64FAULT vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
2065 unsigned long pteval, logps = itir_ps(itir);
2066 BOOLEAN swap_rr0 = (!(ifa>>61) && PSCB(vcpu,metaphysical_mode));
2067 struct p2m_entry entry;
2069 if (logps < PAGE_SHIFT)
2070 panic_domain (NULL, "vcpu_itc_i: domain trying to use "
2071 "smaller page size!\n");
2072 again:
2073 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2074 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2075 if (!pteval) return IA64_ILLOP_FAULT;
2076 if (swap_rr0) set_one_rr(0x0,PSCB(vcpu,rrs[0]));
2077 vcpu_itc_no_srlz(vcpu, 1,ifa,pteval,pte,logps);
2078 if (swap_rr0) set_metaphysical_rr0();
2079 if (p2m_entry_retry(&entry)) {
2080 vcpu_flush_tlb_vhpt_range(ifa, logps);
2081 goto again;
2083 return IA64_NO_FAULT;
2086 IA64FAULT vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 log_range)
2088 BUG_ON(vcpu != current);
2090 check_xen_space_overlap ("ptc_l", vadr, 1UL << log_range);
2092 /* Purge TC */
2093 vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb));
2094 vcpu_purge_tr_entry(&PSCBX(vcpu,itlb));
2096 /* Purge all tlb and vhpt */
2097 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2099 return IA64_NO_FAULT;
2102 // At privlvl=0, fc performs no access rights or protection key checks, while
2103 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2104 // read but no protection key check. Thus in order to avoid an unexpected
2105 // access rights fault, we have to translate the virtual address to a
2106 // physical address (possibly via a metaphysical address) and do the fc
2107 // on the physical address, which is guaranteed to flush the same cache line
2108 IA64FAULT vcpu_fc(VCPU *vcpu, UINT64 vadr)
2110 // TODO: Only allowed for current vcpu
2111 UINT64 mpaddr, paddr;
2112 IA64FAULT fault;
2114 again:
2115 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2116 if (fault == IA64_NO_FAULT) {
2117 struct p2m_entry entry;
2118 paddr = translate_domain_mpaddr(mpaddr, &entry);
2119 ia64_fc(__va(paddr));
2120 if (p2m_entry_retry(&entry))
2121 goto again;
2123 return fault;
2126 IA64FAULT vcpu_ptc_e(VCPU *vcpu, UINT64 vadr)
2128 // Note that this only needs to be called once, i.e. the
2129 // architected loop to purge the entire TLB, should use
2130 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2132 vcpu_flush_vtlb_all(current);
2134 return IA64_NO_FAULT;
2137 IA64FAULT vcpu_ptc_g(VCPU *vcpu, UINT64 vadr, UINT64 addr_range)
2139 printk("vcpu_ptc_g: called, not implemented yet\n");
2140 return IA64_ILLOP_FAULT;
2143 IA64FAULT vcpu_ptc_ga(VCPU *vcpu,UINT64 vadr,UINT64 addr_range)
2145 // FIXME: validate not flushing Xen addresses
2146 // if (Xen address) return(IA64_ILLOP_FAULT);
2147 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2148 //printf("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2150 check_xen_space_overlap ("ptc_ga", vadr, addr_range);
2152 domain_flush_vtlb_range (vcpu->domain, vadr, addr_range);
2154 return IA64_NO_FAULT;
2157 IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
2159 unsigned long region = vadr >> 61;
2160 u64 addr_range = 1UL << log_range;
2161 unsigned long rid, rr;
2162 int i;
2163 TR_ENTRY *trp;
2165 BUG_ON(vcpu != current);
2166 check_xen_space_overlap ("ptr_d", vadr, 1UL << log_range);
2168 rr = PSCB(vcpu,rrs)[region];
2169 rid = rr & RR_RID_MASK;
2171 /* Purge TC */
2172 vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb));
2174 /* Purge tr and recompute dtr_regions. */
2175 vcpu->arch.dtr_regions = 0;
2176 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2177 if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range))
2178 vcpu_purge_tr_entry(trp);
2179 else if (trp->pte.p)
2180 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2181 trp->vadr);
2183 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2185 return IA64_NO_FAULT;
2188 IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
2190 unsigned long region = vadr >> 61;
2191 u64 addr_range = 1UL << log_range;
2192 unsigned long rid, rr;
2193 int i;
2194 TR_ENTRY *trp;
2196 BUG_ON(vcpu != current);
2197 check_xen_space_overlap ("ptr_i", vadr, 1UL << log_range);
2199 rr = PSCB(vcpu,rrs)[region];
2200 rid = rr & RR_RID_MASK;
2202 /* Purge TC */
2203 vcpu_purge_tr_entry(&PSCBX(vcpu,itlb));
2205 /* Purge tr and recompute itr_regions. */
2206 vcpu->arch.itr_regions = 0;
2207 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2208 if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range))
2209 vcpu_purge_tr_entry(trp);
2210 else if (trp->pte.p)
2211 vcpu_quick_region_set(vcpu->arch.itr_regions,
2212 trp->vadr);
2214 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2216 return IA64_NO_FAULT;