ia64/xen-unstable

view xen/arch/ia64/xen/vcpu.c @ 10692:306d7857928c

[IA64] Save & restore.

xc_ia64_linux_save.c and xc_ia64_linux_restore.c added.
vcpu context has more registers and states (eg: tr registers).
Per cpu irqs are deallocated when cpu is switched off.
#if/#endif added in reboot.c for ia64.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Tue Jul 11 12:51:18 2006 -0600 (2006-07-11)
parents bdc0258e162a
children 000789c36d28
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 extern void panic_domain(struct pt_regs *, const char *, ...);
34 extern IA64_BUNDLE __get_domain_bundle(UINT64);
36 typedef union {
37 struct ia64_psr ia64_psr;
38 unsigned long i64;
39 } PSR;
41 // this def for vcpu_regs won't work if kernel stack is present
42 //#define vcpu_regs(vcpu) ((struct pt_regs *) vcpu->arch.regs
44 #define TRUE 1
45 #define FALSE 0
46 #define IA64_PTA_SZ_BIT 2
47 #define IA64_PTA_VF_BIT 8
48 #define IA64_PTA_BASE_BIT 15
49 #define IA64_PTA_LFMT (1UL << IA64_PTA_VF_BIT)
50 #define IA64_PTA_SZ(x) (x##UL << IA64_PTA_SZ_BIT)
52 unsigned long vcpu_verbose = 0;
54 /**************************************************************************
55 VCPU general register access routines
56 **************************************************************************/
57 #ifdef XEN
58 UINT64
59 vcpu_get_gr(VCPU *vcpu, unsigned long reg)
60 {
61 REGS *regs = vcpu_regs(vcpu);
62 UINT64 val;
64 if (!reg) return 0;
65 getreg(reg,&val,0,regs); // FIXME: handle NATs later
66 return val;
67 }
68 IA64FAULT
69 vcpu_get_gr_nat(VCPU *vcpu, unsigned long reg, UINT64 *val)
70 {
71 REGS *regs = vcpu_regs(vcpu);
72 int nat;
74 getreg(reg,val,&nat,regs); // FIXME: handle NATs later
75 if (nat)
76 return IA64_NAT_CONSUMPTION_VECTOR;
77 return 0;
78 }
80 // returns:
81 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
82 // IA64_NO_FAULT otherwise
83 IA64FAULT
84 vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value, int nat)
85 {
86 REGS *regs = vcpu_regs(vcpu);
87 long sof = (regs->cr_ifs) & 0x7f;
89 if (!reg) return IA64_ILLOP_FAULT;
90 if (reg >= sof + 32) return IA64_ILLOP_FAULT;
91 setreg(reg,value,nat,regs); // FIXME: handle NATs later
92 return IA64_NO_FAULT;
93 }
95 IA64FAULT
96 vcpu_get_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
97 {
98 REGS *regs = vcpu_regs(vcpu);
99 getfpreg(reg,val,regs); // FIXME: handle NATs later
100 return IA64_NO_FAULT;
101 }
103 IA64FAULT
104 vcpu_set_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
105 {
106 REGS *regs = vcpu_regs(vcpu);
107 if(reg > 1)
108 setfpreg(reg,val,regs); // FIXME: handle NATs later
109 return IA64_NO_FAULT;
110 }
112 #else
113 // returns:
114 // IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
115 // IA64_NO_FAULT otherwise
116 IA64FAULT
117 vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value)
118 {
119 REGS *regs = vcpu_regs(vcpu);
120 long sof = (regs->cr_ifs) & 0x7f;
122 if (!reg) return IA64_ILLOP_FAULT;
123 if (reg >= sof + 32) return IA64_ILLOP_FAULT;
124 setreg(reg,value,0,regs); // FIXME: handle NATs later
125 return IA64_NO_FAULT;
126 }
128 #endif
130 void vcpu_init_regs (struct vcpu *v)
131 {
132 struct pt_regs *regs;
134 regs = vcpu_regs (v);
135 if (VMX_DOMAIN(v)) {
136 /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
137 /* Need to be expanded as macro */
138 regs->cr_ipsr = 0x501008826008;
139 } else {
140 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
141 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
142 regs->cr_ipsr &= ~(IA64_PSR_BITS_TO_CLEAR
143 | IA64_PSR_RI | IA64_PSR_IS);
144 // domain runs at PL2
145 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
146 }
147 regs->cr_ifs = 1UL << 63; /* or clear? */
148 regs->ar_fpsr = FPSR_DEFAULT;
150 if (VMX_DOMAIN(v)) {
151 vmx_init_all_rr(v);
152 /* Virtual processor context setup */
153 VCPU(v, vpsr) = IA64_PSR_BN;
154 VCPU(v, dcr) = 0;
155 } else {
156 init_all_rr(v);
157 regs->ar_rsc |= (2 << 2); /* force PL2/3 */
158 VCPU(v, banknum) = 1;
159 VCPU(v, metaphysical_mode) = 1;
160 VCPU(v, interrupt_mask_addr) =
161 (unsigned char *)v->domain->arch.shared_info_va +
162 INT_ENABLE_OFFSET(v);
163 VCPU(v, itv) = (1 << 16); /* timer vector masked */
164 }
166 v->arch.domain_itm_last = -1L;
167 }
169 /**************************************************************************
170 VCPU privileged application register access routines
171 **************************************************************************/
173 void vcpu_load_kernel_regs(VCPU *vcpu)
174 {
175 ia64_set_kr(0, VCPU(vcpu, krs[0]));
176 ia64_set_kr(1, VCPU(vcpu, krs[1]));
177 ia64_set_kr(2, VCPU(vcpu, krs[2]));
178 ia64_set_kr(3, VCPU(vcpu, krs[3]));
179 ia64_set_kr(4, VCPU(vcpu, krs[4]));
180 ia64_set_kr(5, VCPU(vcpu, krs[5]));
181 ia64_set_kr(6, VCPU(vcpu, krs[6]));
182 ia64_set_kr(7, VCPU(vcpu, krs[7]));
183 }
185 /* GCC 4.0.2 seems not to be able to suppress this call!. */
186 #define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
188 IA64FAULT vcpu_set_ar(VCPU *vcpu, UINT64 reg, UINT64 val)
189 {
190 if (reg == 44) return (vcpu_set_itc(vcpu,val));
191 else if (reg == 27) return (IA64_ILLOP_FAULT);
192 else if (reg == 24)
193 printf("warning: setting ar.eflg is a no-op; no IA-32 support\n");
194 else if (reg > 7) return (IA64_ILLOP_FAULT);
195 else {
196 PSCB(vcpu,krs[reg]) = val;
197 ia64_set_kr(reg,val);
198 }
199 return IA64_NO_FAULT;
200 }
202 IA64FAULT vcpu_get_ar(VCPU *vcpu, UINT64 reg, UINT64 *val)
203 {
204 if (reg == 24)
205 printf("warning: getting ar.eflg is a no-op; no IA-32 support\n");
206 else if (reg > 7) return (IA64_ILLOP_FAULT);
207 else *val = PSCB(vcpu,krs[reg]);
208 return IA64_NO_FAULT;
209 }
211 /**************************************************************************
212 VCPU processor status register access routines
213 **************************************************************************/
215 void vcpu_set_metaphysical_mode(VCPU *vcpu, BOOLEAN newmode)
216 {
217 /* only do something if mode changes */
218 if (!!newmode ^ !!PSCB(vcpu,metaphysical_mode)) {
219 PSCB(vcpu,metaphysical_mode) = newmode;
220 if (newmode) set_metaphysical_rr0();
221 else if (PSCB(vcpu,rrs[0]) != -1)
222 set_one_rr(0, PSCB(vcpu,rrs[0]));
223 }
224 }
226 IA64FAULT vcpu_reset_psr_dt(VCPU *vcpu)
227 {
228 vcpu_set_metaphysical_mode(vcpu,TRUE);
229 return IA64_NO_FAULT;
230 }
232 IA64FAULT vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
233 {
234 struct ia64_psr psr, imm, *ipsr;
235 REGS *regs = vcpu_regs(vcpu);
237 //PRIVOP_COUNT_ADDR(regs,_RSM);
238 // TODO: All of these bits need to be virtualized
239 // TODO: Only allowed for current vcpu
240 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
241 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
242 imm = *(struct ia64_psr *)&imm24;
243 // interrupt flag
244 if (imm.i)
245 vcpu->vcpu_info->evtchn_upcall_mask = 1;
246 if (imm.ic) PSCB(vcpu,interrupt_collection_enabled) = 0;
247 // interrupt collection flag
248 //if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
249 // just handle psr.up and psr.pp for now
250 if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP
251 | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT
252 | IA64_PSR_DFL | IA64_PSR_DFH))
253 return (IA64_ILLOP_FAULT);
254 if (imm.dfh) ipsr->dfh = 0;
255 if (imm.dfl) ipsr->dfl = 0;
256 if (imm.pp) {
257 ipsr->pp = 1;
258 psr.pp = 1; // priv perf ctrs always enabled
259 PSCB(vcpu,vpsr_pp) = 0; // but fool the domain if it gets psr
260 }
261 if (imm.up) { ipsr->up = 0; psr.up = 0; }
262 if (imm.sp) { ipsr->sp = 0; psr.sp = 0; }
263 if (imm.be) ipsr->be = 0;
264 if (imm.dt) vcpu_set_metaphysical_mode(vcpu,TRUE);
265 __asm__ __volatile (";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
266 return IA64_NO_FAULT;
267 }
270 IA64FAULT vcpu_set_psr_dt(VCPU *vcpu)
271 {
272 vcpu_set_metaphysical_mode(vcpu,FALSE);
273 return IA64_NO_FAULT;
274 }
276 IA64FAULT vcpu_set_psr_i(VCPU *vcpu)
277 {
278 vcpu->vcpu_info->evtchn_upcall_mask = 0;
279 PSCB(vcpu,interrupt_collection_enabled) = 1;
280 return IA64_NO_FAULT;
281 }
283 IA64FAULT vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
284 {
285 struct ia64_psr psr, imm, *ipsr;
286 REGS *regs = vcpu_regs(vcpu);
287 UINT64 mask, enabling_interrupts = 0;
289 //PRIVOP_COUNT_ADDR(regs,_SSM);
290 // TODO: All of these bits need to be virtualized
291 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
292 imm = *(struct ia64_psr *)&imm24;
293 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
294 // just handle psr.sp,pp and psr.i,ic (and user mask) for now
295 mask = IA64_PSR_PP|IA64_PSR_SP|IA64_PSR_I|IA64_PSR_IC|IA64_PSR_UM |
296 IA64_PSR_DT|IA64_PSR_DFL|IA64_PSR_DFH;
297 if (imm24 & ~mask) return (IA64_ILLOP_FAULT);
298 if (imm.dfh) ipsr->dfh = 1;
299 if (imm.dfl) ipsr->dfl = 1;
300 if (imm.pp) {
301 ipsr->pp = 1;
302 psr.pp = 1;
303 PSCB(vcpu,vpsr_pp) = 1;
304 }
305 if (imm.sp) { ipsr->sp = 1; psr.sp = 1; }
306 if (imm.i) {
307 if (vcpu->vcpu_info->evtchn_upcall_mask) {
308 //printf("vcpu_set_psr_sm: psr.ic 0->1\n");
309 enabling_interrupts = 1;
310 }
311 vcpu->vcpu_info->evtchn_upcall_mask = 0;
312 }
313 if (imm.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
314 // TODO: do this faster
315 if (imm.mfl) { ipsr->mfl = 1; psr.mfl = 1; }
316 if (imm.mfh) { ipsr->mfh = 1; psr.mfh = 1; }
317 if (imm.ac) { ipsr->ac = 1; psr.ac = 1; }
318 if (imm.up) { ipsr->up = 1; psr.up = 1; }
319 if (imm.be) {
320 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
321 return (IA64_ILLOP_FAULT);
322 }
323 if (imm.dt) vcpu_set_metaphysical_mode(vcpu,FALSE);
324 __asm__ __volatile (";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
325 if (enabling_interrupts &&
326 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
327 PSCB(vcpu,pending_interruption) = 1;
328 return IA64_NO_FAULT;
329 }
331 IA64FAULT vcpu_set_psr_l(VCPU *vcpu, UINT64 val)
332 {
333 struct ia64_psr psr, newpsr, *ipsr;
334 REGS *regs = vcpu_regs(vcpu);
335 UINT64 enabling_interrupts = 0;
337 // TODO: All of these bits need to be virtualized
338 __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
339 newpsr = *(struct ia64_psr *)&val;
340 ipsr = (struct ia64_psr *)&regs->cr_ipsr;
341 // just handle psr.up and psr.pp for now
342 //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP)) return (IA64_ILLOP_FAULT);
343 // however trying to set other bits can't be an error as it is in ssm
344 if (newpsr.dfh) ipsr->dfh = 1;
345 if (newpsr.dfl) ipsr->dfl = 1;
346 if (newpsr.pp) {
347 ipsr->pp = 1; psr.pp = 1;
348 PSCB(vcpu,vpsr_pp) = 1;
349 }
350 else {
351 ipsr->pp = 1; psr.pp = 1;
352 PSCB(vcpu,vpsr_pp) = 0;
353 }
354 if (newpsr.up) { ipsr->up = 1; psr.up = 1; }
355 if (newpsr.sp) { ipsr->sp = 1; psr.sp = 1; }
356 if (newpsr.i) {
357 if (vcpu->vcpu_info->evtchn_upcall_mask)
358 enabling_interrupts = 1;
359 vcpu->vcpu_info->evtchn_upcall_mask = 0;
360 }
361 if (newpsr.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
362 if (newpsr.mfl) { ipsr->mfl = 1; psr.mfl = 1; }
363 if (newpsr.mfh) { ipsr->mfh = 1; psr.mfh = 1; }
364 if (newpsr.ac) { ipsr->ac = 1; psr.ac = 1; }
365 if (newpsr.up) { ipsr->up = 1; psr.up = 1; }
366 if (newpsr.dt && newpsr.rt) vcpu_set_metaphysical_mode(vcpu,FALSE);
367 else vcpu_set_metaphysical_mode(vcpu,TRUE);
368 if (newpsr.be) {
369 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
370 return (IA64_ILLOP_FAULT);
371 }
372 if (enabling_interrupts &&
373 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
374 PSCB(vcpu,pending_interruption) = 1;
375 return IA64_NO_FAULT;
376 }
378 IA64FAULT vcpu_get_psr(VCPU *vcpu, UINT64 *pval)
379 {
380 REGS *regs = vcpu_regs(vcpu);
381 struct ia64_psr newpsr;
383 newpsr = *(struct ia64_psr *)&regs->cr_ipsr;
384 if (newpsr.cpl == 2) newpsr.cpl = 0;
385 if (!vcpu->vcpu_info->evtchn_upcall_mask) newpsr.i = 1;
386 else newpsr.i = 0;
387 if (PSCB(vcpu,interrupt_collection_enabled)) newpsr.ic = 1;
388 else newpsr.ic = 0;
389 if (PSCB(vcpu,metaphysical_mode)) newpsr.dt = 0;
390 else newpsr.dt = 1;
391 if (PSCB(vcpu,vpsr_pp)) newpsr.pp = 1;
392 else newpsr.pp = 0;
393 *pval = *(unsigned long *)&newpsr;
394 return IA64_NO_FAULT;
395 }
397 BOOLEAN vcpu_get_psr_ic(VCPU *vcpu)
398 {
399 return !!PSCB(vcpu,interrupt_collection_enabled);
400 }
402 BOOLEAN vcpu_get_psr_i(VCPU *vcpu)
403 {
404 return !vcpu->vcpu_info->evtchn_upcall_mask;
405 }
407 UINT64 vcpu_get_ipsr_int_state(VCPU *vcpu,UINT64 prevpsr)
408 {
409 UINT64 dcr = PSCBX(vcpu,dcr);
410 PSR psr;
412 //printf("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr);
413 psr.i64 = prevpsr;
414 psr.ia64_psr.be = 0; if (dcr & IA64_DCR_BE) psr.ia64_psr.be = 1;
415 psr.ia64_psr.pp = 0; if (dcr & IA64_DCR_PP) psr.ia64_psr.pp = 1;
416 psr.ia64_psr.ic = PSCB(vcpu,interrupt_collection_enabled);
417 psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
418 psr.ia64_psr.bn = PSCB(vcpu,banknum);
419 psr.ia64_psr.dt = 1; psr.ia64_psr.it = 1; psr.ia64_psr.rt = 1;
420 if (psr.ia64_psr.cpl == 2) psr.ia64_psr.cpl = 0; // !!!! fool domain
421 // psr.pk = 1;
422 //printf("returns 0x%016lx...\n",psr.i64);
423 return psr.i64;
424 }
426 /**************************************************************************
427 VCPU control register access routines
428 **************************************************************************/
430 IA64FAULT vcpu_get_dcr(VCPU *vcpu, UINT64 *pval)
431 {
432 //verbose("vcpu_get_dcr: called @%p\n",PSCB(vcpu,iip));
433 // Reads of cr.dcr on Xen always have the sign bit set, so
434 // a domain can differentiate whether it is running on SP or not
435 *pval = PSCBX(vcpu,dcr) | 0x8000000000000000L;
436 return (IA64_NO_FAULT);
437 }
439 IA64FAULT vcpu_get_iva(VCPU *vcpu, UINT64 *pval)
440 {
441 if(VMX_DOMAIN(vcpu)){
442 *pval = PSCB(vcpu,iva) & ~0x7fffL;
443 }else{
444 *pval = PSCBX(vcpu,iva) & ~0x7fffL;
445 }
446 return (IA64_NO_FAULT);
447 }
449 IA64FAULT vcpu_get_pta(VCPU *vcpu, UINT64 *pval)
450 {
451 *pval = PSCB(vcpu,pta);
452 return (IA64_NO_FAULT);
453 }
455 IA64FAULT vcpu_get_ipsr(VCPU *vcpu, UINT64 *pval)
456 {
457 //REGS *regs = vcpu_regs(vcpu);
458 //*pval = regs->cr_ipsr;
459 *pval = PSCB(vcpu,ipsr);
460 return (IA64_NO_FAULT);
461 }
463 IA64FAULT vcpu_get_isr(VCPU *vcpu, UINT64 *pval)
464 {
465 *pval = PSCB(vcpu,isr);
466 return (IA64_NO_FAULT);
467 }
469 IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT64 *pval)
470 {
471 //REGS *regs = vcpu_regs(vcpu);
472 //*pval = regs->cr_iip;
473 *pval = PSCB(vcpu,iip);
474 return (IA64_NO_FAULT);
475 }
477 IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval)
478 {
479 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu),_GET_IFA);
480 *pval = PSCB(vcpu,ifa);
481 return (IA64_NO_FAULT);
482 }
484 unsigned long vcpu_get_rr_ps(VCPU *vcpu,UINT64 vadr)
485 {
486 ia64_rr rr;
488 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
489 return(rr.ps);
490 }
492 unsigned long vcpu_get_rr_rid(VCPU *vcpu,UINT64 vadr)
493 {
494 ia64_rr rr;
496 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
497 return(rr.rid);
498 }
500 unsigned long vcpu_get_itir_on_fault(VCPU *vcpu, UINT64 ifa)
501 {
502 ia64_rr rr;
504 rr.rrval = 0;
505 rr.ps = vcpu_get_rr_ps(vcpu,ifa);
506 rr.rid = vcpu_get_rr_rid(vcpu,ifa);
507 return (rr.rrval);
508 }
511 IA64FAULT vcpu_get_itir(VCPU *vcpu, UINT64 *pval)
512 {
513 UINT64 val = PSCB(vcpu,itir);
514 *pval = val;
515 return (IA64_NO_FAULT);
516 }
518 IA64FAULT vcpu_get_iipa(VCPU *vcpu, UINT64 *pval)
519 {
520 UINT64 val = PSCB(vcpu,iipa);
521 // SP entry code does not save iipa yet nor does it get
522 // properly delivered in the pscb
523 // printf("*** vcpu_get_iipa: cr.iipa not fully implemented yet!!\n");
524 *pval = val;
525 return (IA64_NO_FAULT);
526 }
528 IA64FAULT vcpu_get_ifs(VCPU *vcpu, UINT64 *pval)
529 {
530 //PSCB(vcpu,ifs) = PSCB(vcpu)->regs.cr_ifs;
531 //*pval = PSCB(vcpu,regs).cr_ifs;
532 *pval = PSCB(vcpu,ifs);
533 PSCB(vcpu,incomplete_regframe) = 0;
534 return (IA64_NO_FAULT);
535 }
537 IA64FAULT vcpu_get_iim(VCPU *vcpu, UINT64 *pval)
538 {
539 UINT64 val = PSCB(vcpu,iim);
540 *pval = val;
541 return (IA64_NO_FAULT);
542 }
544 IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval)
545 {
546 PRIVOP_COUNT_ADDR(vcpu_regs(vcpu),_THASH);
547 *pval = PSCB(vcpu,iha);
548 return (IA64_NO_FAULT);
549 }
551 IA64FAULT vcpu_set_dcr(VCPU *vcpu, UINT64 val)
552 {
553 // Reads of cr.dcr on SP always have the sign bit set, so
554 // a domain can differentiate whether it is running on SP or not
555 // Thus, writes of DCR should ignore the sign bit
556 //verbose("vcpu_set_dcr: called\n");
557 PSCBX(vcpu,dcr) = val & ~0x8000000000000000L;
558 return (IA64_NO_FAULT);
559 }
561 IA64FAULT vcpu_set_iva(VCPU *vcpu, UINT64 val)
562 {
563 if(VMX_DOMAIN(vcpu)){
564 PSCB(vcpu,iva) = val & ~0x7fffL;
565 }else{
566 PSCBX(vcpu,iva) = val & ~0x7fffL;
567 }
568 return (IA64_NO_FAULT);
569 }
571 IA64FAULT vcpu_set_pta(VCPU *vcpu, UINT64 val)
572 {
573 if (val & IA64_PTA_LFMT) {
574 printf("*** No support for VHPT long format yet!!\n");
575 return (IA64_ILLOP_FAULT);
576 }
577 if (val & (0x3f<<9)) /* reserved fields */ return IA64_RSVDREG_FAULT;
578 if (val & 2) /* reserved fields */ return IA64_RSVDREG_FAULT;
579 PSCB(vcpu,pta) = val;
580 return IA64_NO_FAULT;
581 }
583 IA64FAULT vcpu_set_ipsr(VCPU *vcpu, UINT64 val)
584 {
585 PSCB(vcpu,ipsr) = val;
586 return IA64_NO_FAULT;
587 }
589 IA64FAULT vcpu_set_isr(VCPU *vcpu, UINT64 val)
590 {
591 PSCB(vcpu,isr) = val;
592 return IA64_NO_FAULT;
593 }
595 IA64FAULT vcpu_set_iip(VCPU *vcpu, UINT64 val)
596 {
597 PSCB(vcpu,iip) = val;
598 return IA64_NO_FAULT;
599 }
601 IA64FAULT vcpu_increment_iip(VCPU *vcpu)
602 {
603 REGS *regs = vcpu_regs(vcpu);
604 struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
605 if (ipsr->ri == 2) { ipsr->ri=0; regs->cr_iip += 16; }
606 else ipsr->ri++;
607 return (IA64_NO_FAULT);
608 }
610 IA64FAULT vcpu_set_ifa(VCPU *vcpu, UINT64 val)
611 {
612 PSCB(vcpu,ifa) = val;
613 return IA64_NO_FAULT;
614 }
616 IA64FAULT vcpu_set_itir(VCPU *vcpu, UINT64 val)
617 {
618 PSCB(vcpu,itir) = val;
619 return IA64_NO_FAULT;
620 }
622 IA64FAULT vcpu_set_iipa(VCPU *vcpu, UINT64 val)
623 {
624 // SP entry code does not save iipa yet nor does it get
625 // properly delivered in the pscb
626 // printf("*** vcpu_set_iipa: cr.iipa not fully implemented yet!!\n");
627 PSCB(vcpu,iipa) = val;
628 return IA64_NO_FAULT;
629 }
631 IA64FAULT vcpu_set_ifs(VCPU *vcpu, UINT64 val)
632 {
633 //REGS *regs = vcpu_regs(vcpu);
634 PSCB(vcpu,ifs) = val;
635 return IA64_NO_FAULT;
636 }
638 IA64FAULT vcpu_set_iim(VCPU *vcpu, UINT64 val)
639 {
640 PSCB(vcpu,iim) = val;
641 return IA64_NO_FAULT;
642 }
644 IA64FAULT vcpu_set_iha(VCPU *vcpu, UINT64 val)
645 {
646 PSCB(vcpu,iha) = val;
647 return IA64_NO_FAULT;
648 }
650 /**************************************************************************
651 VCPU interrupt control register access routines
652 **************************************************************************/
654 void vcpu_pend_unspecified_interrupt(VCPU *vcpu)
655 {
656 PSCB(vcpu,pending_interruption) = 1;
657 }
659 void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
660 {
661 if (vector & ~0xff) {
662 printf("vcpu_pend_interrupt: bad vector\n");
663 return;
664 }
666 if (vcpu->arch.event_callback_ip) {
667 printf("Deprecated interface. Move to new event based solution\n");
668 return;
669 }
671 if ( VMX_DOMAIN(vcpu) ) {
672 set_bit(vector,VCPU(vcpu,irr));
673 } else {
674 set_bit(vector,PSCBX(vcpu,irr));
675 PSCB(vcpu,pending_interruption) = 1;
676 }
677 }
679 #define IA64_TPR_MMI 0x10000
680 #define IA64_TPR_MIC 0x000f0
682 /* checks to see if a VCPU has any unmasked pending interrupts
683 * if so, returns the highest, else returns SPURIOUS_VECTOR */
684 /* NOTE: Since this gets called from vcpu_get_ivr() and the
685 * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
686 * this routine also ignores pscb.interrupt_delivery_enabled
687 * and this must be checked independently; see vcpu_deliverable interrupts() */
688 UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
689 {
690 UINT64 *p, *r, bits, bitnum, mask, i, vector;
692 if (vcpu->arch.event_callback_ip)
693 return SPURIOUS_VECTOR;
695 /* Always check pending event, since guest may just ack the
696 * event injection without handle. Later guest may throw out
697 * the event itself.
698 */
699 check_start:
700 if (event_pending(vcpu) &&
701 !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
702 &PSCBX(vcpu, insvc[0])))
703 vcpu_pend_interrupt(vcpu, vcpu->domain->shared_info->arch.evtchn_vector);
705 p = &PSCBX(vcpu,irr[3]);
706 r = &PSCBX(vcpu,insvc[3]);
707 for (i = 3; ; p--, r--, i--) {
708 bits = *p ;
709 if (bits) break; // got a potential interrupt
710 if (*r) {
711 // nothing in this word which is pending+inservice
712 // but there is one inservice which masks lower
713 return SPURIOUS_VECTOR;
714 }
715 if (i == 0) {
716 // checked all bits... nothing pending+inservice
717 return SPURIOUS_VECTOR;
718 }
719 }
720 // have a pending,deliverable interrupt... see if it is masked
721 bitnum = ia64_fls(bits);
722 //printf("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
723 vector = bitnum+(i*64);
724 mask = 1L << bitnum;
725 /* sanity check for guest timer interrupt */
726 if (vector == (PSCB(vcpu,itv) & 0xff)) {
727 uint64_t now = ia64_get_itc();
728 if (now < PSCBX(vcpu,domain_itm)) {
729 // printk("Ooops, pending guest timer before its due\n");
730 PSCBX(vcpu,irr[i]) &= ~mask;
731 goto check_start;
732 }
733 }
734 //printf("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);
735 if (*r >= mask) {
736 // masked by equal inservice
737 //printf("but masked by equal inservice\n");
738 return SPURIOUS_VECTOR;
739 }
740 if (PSCB(vcpu,tpr) & IA64_TPR_MMI) {
741 // tpr.mmi is set
742 //printf("but masked by tpr.mmi\n");
743 return SPURIOUS_VECTOR;
744 }
745 if (((PSCB(vcpu,tpr) & IA64_TPR_MIC) + 15) >= vector) {
746 //tpr.mic masks class
747 //printf("but masked by tpr.mic\n");
748 return SPURIOUS_VECTOR;
749 }
751 //printf("returned to caller\n");
752 return vector;
753 }
755 UINT64 vcpu_deliverable_interrupts(VCPU *vcpu)
756 {
757 return (vcpu_get_psr_i(vcpu) &&
758 vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
759 }
761 UINT64 vcpu_deliverable_timer(VCPU *vcpu)
762 {
763 return (vcpu_get_psr_i(vcpu) &&
764 vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu,itv));
765 }
767 IA64FAULT vcpu_get_lid(VCPU *vcpu, UINT64 *pval)
768 {
769 /* Use real LID for domain0 until vIOSAPIC is present.
770 Use EID=0, ID=vcpu_id for domU. */
771 if (vcpu->domain == dom0)
772 *pval = ia64_getreg(_IA64_REG_CR_LID);
773 else
774 *pval = vcpu->vcpu_id << 24;
775 return IA64_NO_FAULT;
776 }
778 IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
779 {
780 int i;
781 UINT64 vector, mask;
783 #define HEARTBEAT_FREQ 16 // period in seconds
784 #ifdef HEARTBEAT_FREQ
785 #define N_DOMS 16 // period in seconds
786 #if 0
787 static long count[N_DOMS] = { 0 };
788 #endif
789 static long nonclockcount[N_DOMS] = { 0 };
790 unsigned domid = vcpu->domain->domain_id;
791 #endif
792 #ifdef IRQ_DEBUG
793 static char firstivr = 1;
794 static char firsttime[256];
795 if (firstivr) {
796 int i;
797 for (i=0;i<256;i++) firsttime[i]=1;
798 firstivr=0;
799 }
800 #endif
802 vector = vcpu_check_pending_interrupts(vcpu);
803 if (vector == SPURIOUS_VECTOR) {
804 PSCB(vcpu,pending_interruption) = 0;
805 *pval = vector;
806 return IA64_NO_FAULT;
807 }
808 #ifdef HEARTBEAT_FREQ
809 if (domid >= N_DOMS) domid = N_DOMS-1;
810 #if 0
811 if (vector == (PSCB(vcpu,itv) & 0xff)) {
812 if (!(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) {
813 printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
814 domid, count[domid], nonclockcount[domid]);
815 //count[domid] = 0;
816 //dump_runq();
817 }
818 }
819 #endif
820 else nonclockcount[domid]++;
821 #endif
822 // now have an unmasked, pending, deliverable vector!
823 // getting ivr has "side effects"
824 #ifdef IRQ_DEBUG
825 if (firsttime[vector]) {
826 printf("*** First get_ivr on vector=%lu,itc=%lx\n",
827 vector,ia64_get_itc());
828 firsttime[vector]=0;
829 }
830 #endif
831 /* if delivering a timer interrupt, remember domain_itm, which
832 * needs to be done before clearing irr
833 */
834 if (vector == (PSCB(vcpu,itv) & 0xff)) {
835 PSCBX(vcpu,domain_itm_last) = PSCBX(vcpu,domain_itm);
836 }
838 i = vector >> 6;
839 mask = 1L << (vector & 0x3f);
840 //printf("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
841 PSCBX(vcpu,insvc[i]) |= mask;
842 PSCBX(vcpu,irr[i]) &= ~mask;
843 //PSCB(vcpu,pending_interruption)--;
844 *pval = vector;
845 return IA64_NO_FAULT;
846 }
848 IA64FAULT vcpu_get_tpr(VCPU *vcpu, UINT64 *pval)
849 {
850 *pval = PSCB(vcpu,tpr);
851 return (IA64_NO_FAULT);
852 }
854 IA64FAULT vcpu_get_eoi(VCPU *vcpu, UINT64 *pval)
855 {
856 *pval = 0L; // reads of eoi always return 0
857 return (IA64_NO_FAULT);
858 }
860 IA64FAULT vcpu_get_irr0(VCPU *vcpu, UINT64 *pval)
861 {
862 *pval = PSCBX(vcpu, irr[0]);
863 return (IA64_NO_FAULT);
864 }
866 IA64FAULT vcpu_get_irr1(VCPU *vcpu, UINT64 *pval)
867 {
868 *pval = PSCBX(vcpu, irr[1]);
869 return (IA64_NO_FAULT);
870 }
872 IA64FAULT vcpu_get_irr2(VCPU *vcpu, UINT64 *pval)
873 {
874 *pval = PSCBX(vcpu, irr[2]);
875 return (IA64_NO_FAULT);
876 }
878 IA64FAULT vcpu_get_irr3(VCPU *vcpu, UINT64 *pval)
879 {
880 *pval = PSCBX(vcpu, irr[3]);
881 return (IA64_NO_FAULT);
882 }
884 IA64FAULT vcpu_get_itv(VCPU *vcpu, UINT64 *pval)
885 {
886 *pval = PSCB(vcpu,itv);
887 return (IA64_NO_FAULT);
888 }
890 IA64FAULT vcpu_get_pmv(VCPU *vcpu, UINT64 *pval)
891 {
892 *pval = PSCB(vcpu,pmv);
893 return (IA64_NO_FAULT);
894 }
896 IA64FAULT vcpu_get_cmcv(VCPU *vcpu, UINT64 *pval)
897 {
898 *pval = PSCB(vcpu,cmcv);
899 return (IA64_NO_FAULT);
900 }
902 IA64FAULT vcpu_get_lrr0(VCPU *vcpu, UINT64 *pval)
903 {
904 // fix this when setting values other than m-bit is supported
905 printf("vcpu_get_lrr0: Unmasked interrupts unsupported\n");
906 *pval = (1L << 16);
907 return (IA64_NO_FAULT);
908 }
910 IA64FAULT vcpu_get_lrr1(VCPU *vcpu, UINT64 *pval)
911 {
912 // fix this when setting values other than m-bit is supported
913 printf("vcpu_get_lrr1: Unmasked interrupts unsupported\n");
914 *pval = (1L << 16);
915 return (IA64_NO_FAULT);
916 }
918 IA64FAULT vcpu_set_lid(VCPU *vcpu, UINT64 val)
919 {
920 printf("vcpu_set_lid: Setting cr.lid is unsupported\n");
921 return (IA64_ILLOP_FAULT);
922 }
924 IA64FAULT vcpu_set_tpr(VCPU *vcpu, UINT64 val)
925 {
926 if (val & 0xff00) return IA64_RSVDREG_FAULT;
927 PSCB(vcpu,tpr) = val;
928 /* This can unmask interrupts. */
929 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
930 PSCB(vcpu,pending_interruption) = 1;
931 return (IA64_NO_FAULT);
932 }
934 IA64FAULT vcpu_set_eoi(VCPU *vcpu, UINT64 val)
935 {
936 UINT64 *p, bits, vec, bitnum;
937 int i;
939 p = &PSCBX(vcpu,insvc[3]);
940 for (i = 3; (i >= 0) && !(bits = *p); i--, p--);
941 if (i < 0) {
942 printf("Trying to EOI interrupt when none are in-service.\n");
943 return IA64_NO_FAULT;
944 }
945 bitnum = ia64_fls(bits);
946 vec = bitnum + (i*64);
947 /* clear the correct bit */
948 bits &= ~(1L << bitnum);
949 *p = bits;
950 /* clearing an eoi bit may unmask another pending interrupt... */
951 if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
952 // worry about this later... Linux only calls eoi
953 // with interrupts disabled
954 printf("Trying to EOI interrupt with interrupts enabled\n");
955 }
956 if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
957 PSCB(vcpu,pending_interruption) = 1;
958 //printf("YYYYY vcpu_set_eoi: Successful\n");
959 return (IA64_NO_FAULT);
960 }
962 IA64FAULT vcpu_set_lrr0(VCPU *vcpu, UINT64 val)
963 {
964 if (!(val & (1L << 16))) {
965 printf("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
966 return (IA64_ILLOP_FAULT);
967 }
968 // no place to save this state but nothing to do anyway
969 return (IA64_NO_FAULT);
970 }
972 IA64FAULT vcpu_set_lrr1(VCPU *vcpu, UINT64 val)
973 {
974 if (!(val & (1L << 16))) {
975 printf("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
976 return (IA64_ILLOP_FAULT);
977 }
978 // no place to save this state but nothing to do anyway
979 return (IA64_NO_FAULT);
980 }
982 IA64FAULT vcpu_set_itv(VCPU *vcpu, UINT64 val)
983 {
984 /* Check reserved fields. */
985 if (val & 0xef00)
986 return (IA64_ILLOP_FAULT);
987 PSCB(vcpu,itv) = val;
988 if (val & 0x10000) {
989 /* Disable itm. */
990 PSCBX(vcpu,domain_itm) = 0;
991 }
992 else vcpu_set_next_timer(vcpu);
993 return (IA64_NO_FAULT);
994 }
996 IA64FAULT vcpu_set_pmv(VCPU *vcpu, UINT64 val)
997 {
998 if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT;
999 PSCB(vcpu,pmv) = val;
1000 return (IA64_NO_FAULT);
1003 IA64FAULT vcpu_set_cmcv(VCPU *vcpu, UINT64 val)
1005 if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT;
1006 PSCB(vcpu,cmcv) = val;
1007 return (IA64_NO_FAULT);
1010 /**************************************************************************
1011 VCPU temporary register access routines
1012 **************************************************************************/
1013 UINT64 vcpu_get_tmp(VCPU *vcpu, UINT64 index)
1015 if (index > 7) return 0;
1016 return PSCB(vcpu,tmp[index]);
1019 void vcpu_set_tmp(VCPU *vcpu, UINT64 index, UINT64 val)
1021 if (index <= 7) PSCB(vcpu,tmp[index]) = val;
1024 /**************************************************************************
1025 Interval timer routines
1026 **************************************************************************/
1028 BOOLEAN vcpu_timer_disabled(VCPU *vcpu)
1030 UINT64 itv = PSCB(vcpu,itv);
1031 return(!itv || !!(itv & 0x10000));
1034 BOOLEAN vcpu_timer_inservice(VCPU *vcpu)
1036 UINT64 itv = PSCB(vcpu,itv);
1037 return (test_bit(itv, PSCBX(vcpu,insvc)));
1040 BOOLEAN vcpu_timer_expired(VCPU *vcpu)
1042 unsigned long domain_itm = PSCBX(vcpu,domain_itm);
1043 unsigned long now = ia64_get_itc();
1045 if (!domain_itm) return FALSE;
1046 if (now < domain_itm) return FALSE;
1047 if (vcpu_timer_disabled(vcpu)) return FALSE;
1048 return TRUE;
1051 void vcpu_safe_set_itm(unsigned long val)
1053 unsigned long epsilon = 100;
1054 unsigned long flags;
1055 UINT64 now = ia64_get_itc();
1057 local_irq_save(flags);
1058 while (1) {
1059 //printf("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
1060 ia64_set_itm(val);
1061 if (val > (now = ia64_get_itc())) break;
1062 val = now + epsilon;
1063 epsilon <<= 1;
1065 local_irq_restore(flags);
1068 void vcpu_set_next_timer(VCPU *vcpu)
1070 UINT64 d = PSCBX(vcpu,domain_itm);
1071 //UINT64 s = PSCBX(vcpu,xen_itm);
1072 UINT64 s = local_cpu_data->itm_next;
1073 UINT64 now = ia64_get_itc();
1075 /* gloss over the wraparound problem for now... we know it exists
1076 * but it doesn't matter right now */
1078 if (is_idle_domain(vcpu->domain)) {
1079 // printf("****** vcpu_set_next_timer called during idle!!\n");
1080 vcpu_safe_set_itm(s);
1081 return;
1083 //s = PSCBX(vcpu,xen_itm);
1084 if (d && (d > now) && (d < s)) {
1085 vcpu_safe_set_itm(d);
1086 //using_domain_as_itm++;
1088 else {
1089 vcpu_safe_set_itm(s);
1090 //using_xen_as_itm++;
1094 IA64FAULT vcpu_set_itm(VCPU *vcpu, UINT64 val)
1096 //UINT now = ia64_get_itc();
1098 //if (val < now) val = now + 1000;
1099 //printf("*** vcpu_set_itm: called with %lx\n",val);
1100 PSCBX(vcpu,domain_itm) = val;
1101 vcpu_set_next_timer(vcpu);
1102 return (IA64_NO_FAULT);
1105 IA64FAULT vcpu_set_itc(VCPU *vcpu, UINT64 val)
1107 #define DISALLOW_SETTING_ITC_FOR_NOW
1108 #ifdef DISALLOW_SETTING_ITC_FOR_NOW
1109 static int did_print;
1110 if (!did_print) {
1111 printf("vcpu_set_itc: Setting ar.itc is currently disabled\n");
1112 printf("(this message is only displayed one)\n");
1113 did_print = 1;
1115 #else
1116 UINT64 oldnow = ia64_get_itc();
1117 UINT64 olditm = PSCBX(vcpu,domain_itm);
1118 unsigned long d = olditm - oldnow;
1119 unsigned long x = local_cpu_data->itm_next - oldnow;
1121 UINT64 newnow = val, min_delta;
1123 local_irq_disable();
1124 if (olditm) {
1125 printf("**** vcpu_set_itc(%lx): vitm changed to %lx\n",val,newnow+d);
1126 PSCBX(vcpu,domain_itm) = newnow + d;
1128 local_cpu_data->itm_next = newnow + x;
1129 d = PSCBX(vcpu,domain_itm);
1130 x = local_cpu_data->itm_next;
1132 ia64_set_itc(newnow);
1133 if (d && (d > newnow) && (d < x)) {
1134 vcpu_safe_set_itm(d);
1135 //using_domain_as_itm++;
1137 else {
1138 vcpu_safe_set_itm(x);
1139 //using_xen_as_itm++;
1141 local_irq_enable();
1142 #endif
1143 return (IA64_NO_FAULT);
1146 IA64FAULT vcpu_get_itm(VCPU *vcpu, UINT64 *pval)
1148 //FIXME: Implement this
1149 printf("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
1150 return (IA64_NO_FAULT);
1151 //return (IA64_ILLOP_FAULT);
1154 IA64FAULT vcpu_get_itc(VCPU *vcpu, UINT64 *pval)
1156 //TODO: Implement this
1157 printf("vcpu_get_itc: Getting ar.itc is unsupported\n");
1158 return (IA64_ILLOP_FAULT);
1161 void vcpu_pend_timer(VCPU *vcpu)
1163 UINT64 itv = PSCB(vcpu,itv) & 0xff;
1165 if (vcpu_timer_disabled(vcpu)) return;
1166 //if (vcpu_timer_inservice(vcpu)) return;
1167 if (PSCBX(vcpu,domain_itm_last) == PSCBX(vcpu,domain_itm)) {
1168 // already delivered an interrupt for this so
1169 // don't deliver another
1170 return;
1172 if (vcpu->arch.event_callback_ip) {
1173 /* A small window may occur when injecting vIRQ while related
1174 * handler has not been registered. Don't fire in such case.
1175 */
1176 if (vcpu->virq_to_evtchn[VIRQ_ITC]) {
1177 send_guest_vcpu_virq(vcpu, VIRQ_ITC);
1178 PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
1180 } else
1181 vcpu_pend_interrupt(vcpu, itv);
1184 // returns true if ready to deliver a timer interrupt too early
1185 UINT64 vcpu_timer_pending_early(VCPU *vcpu)
1187 UINT64 now = ia64_get_itc();
1188 UINT64 itm = PSCBX(vcpu,domain_itm);
1190 if (vcpu_timer_disabled(vcpu)) return 0;
1191 if (!itm) return 0;
1192 return (vcpu_deliverable_timer(vcpu) && (now < itm));
1195 /**************************************************************************
1196 Privileged operation emulation routines
1197 **************************************************************************/
1199 static void
1200 vcpu_force_tlb_miss(VCPU* vcpu, UINT64 ifa)
1202 PSCB(vcpu, ifa) = ifa;
1203 PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
1204 vcpu_thash(current, ifa, &PSCB(current, iha));
1207 IA64FAULT vcpu_force_inst_miss(VCPU *vcpu, UINT64 ifa)
1209 vcpu_force_tlb_miss(vcpu, ifa);
1210 return (vcpu_get_rr_ve(vcpu, ifa)? IA64_INST_TLB_VECTOR: IA64_ALT_INST_TLB_VECTOR);
1213 IA64FAULT vcpu_force_data_miss(VCPU *vcpu, UINT64 ifa)
1215 vcpu_force_tlb_miss(vcpu, ifa);
1216 return (vcpu_get_rr_ve(vcpu, ifa)? IA64_DATA_TLB_VECTOR: IA64_ALT_DATA_TLB_VECTOR);
1219 IA64FAULT vcpu_rfi(VCPU *vcpu)
1221 // TODO: Only allowed for current vcpu
1222 PSR psr;
1223 UINT64 int_enable, regspsr = 0;
1224 UINT64 ifs;
1225 REGS *regs = vcpu_regs(vcpu);
1226 extern void dorfirfi(void);
1228 psr.i64 = PSCB(vcpu,ipsr);
1229 if (psr.ia64_psr.cpl < 3) psr.ia64_psr.cpl = 2;
1230 int_enable = psr.ia64_psr.i;
1231 if (psr.ia64_psr.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
1232 if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it) vcpu_set_metaphysical_mode(vcpu,FALSE);
1233 else vcpu_set_metaphysical_mode(vcpu,TRUE);
1234 psr.ia64_psr.ic = 1; psr.ia64_psr.i = 1;
1235 psr.ia64_psr.dt = 1; psr.ia64_psr.rt = 1; psr.ia64_psr.it = 1;
1236 psr.ia64_psr.bn = 1;
1237 //psr.pk = 1; // checking pkeys shouldn't be a problem but seems broken
1238 if (psr.ia64_psr.be) {
1239 printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
1240 return (IA64_ILLOP_FAULT);
1242 PSCB(vcpu,incomplete_regframe) = 0; // is this necessary?
1243 ifs = PSCB(vcpu,ifs);
1244 //if ((ifs & regs->cr_ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
1245 //if ((ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
1246 if (ifs & regs->cr_ifs & 0x8000000000000000L) {
1247 // TODO: validate PSCB(vcpu,iip)
1248 // TODO: PSCB(vcpu,ipsr) = psr;
1249 PSCB(vcpu,ipsr) = psr.i64;
1250 // now set up the trampoline
1251 regs->cr_iip = *(unsigned long *)dorfirfi; // function pointer!!
1252 __asm__ __volatile ("mov %0=psr;;":"=r"(regspsr)::"memory");
1253 regs->cr_ipsr = regspsr & ~(IA64_PSR_I | IA64_PSR_IC | IA64_PSR_BN);
1255 else {
1256 regs->cr_ipsr = psr.i64;
1257 regs->cr_iip = PSCB(vcpu,iip);
1259 PSCB(vcpu,interrupt_collection_enabled) = 1;
1260 vcpu_bsw1(vcpu);
1261 vcpu->vcpu_info->evtchn_upcall_mask = !int_enable;
1262 return (IA64_NO_FAULT);
1265 IA64FAULT vcpu_cover(VCPU *vcpu)
1267 // TODO: Only allowed for current vcpu
1268 REGS *regs = vcpu_regs(vcpu);
1270 if (!PSCB(vcpu,interrupt_collection_enabled)) {
1271 if (!PSCB(vcpu,incomplete_regframe))
1272 PSCB(vcpu,ifs) = regs->cr_ifs;
1273 else PSCB(vcpu,incomplete_regframe) = 0;
1275 regs->cr_ifs = 0;
1276 return (IA64_NO_FAULT);
1279 IA64FAULT vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
1281 UINT64 pta = PSCB(vcpu,pta);
1282 UINT64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
1283 UINT64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT)-1);
1284 UINT64 Mask = (1L << pta_sz) - 1;
1285 UINT64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
1286 UINT64 compMask_60_15 = ~Mask_60_15;
1287 UINT64 rr_ps = vcpu_get_rr_ps(vcpu,vadr);
1288 UINT64 VHPT_offset = (vadr >> rr_ps) << 3;
1289 UINT64 VHPT_addr1 = vadr & 0xe000000000000000L;
1290 UINT64 VHPT_addr2a =
1291 ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
1292 UINT64 VHPT_addr2b =
1293 ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
1294 UINT64 VHPT_addr3 = VHPT_offset & 0x7fff;
1295 UINT64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
1296 VHPT_addr3;
1298 //verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
1299 *pval = VHPT_addr;
1300 return (IA64_NO_FAULT);
1303 IA64FAULT vcpu_ttag(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
1305 printf("vcpu_ttag: ttag instruction unsupported\n");
1306 return (IA64_ILLOP_FAULT);
1309 int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
1311 /* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
1312 static inline int range_overlap (u64 b1, u64 e1, u64 b2, u64 e2)
1314 return (b1 <= e2) && (e1 >= b2);
1317 /* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
1318 Note: LSBs of base inside page_size are ignored. */
1319 static inline void
1320 check_xen_space_overlap (const char *func, u64 base, u64 page_size)
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 panic_domain (NULL, "%s on Xen virtual space (%lx)\n",
1329 func, base);
1332 // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
1333 static inline int vcpu_match_tr_entry_no_p(TR_ENTRY *trp, UINT64 ifa, UINT64 rid)
1335 return trp->rid == rid
1336 && ifa >= trp->vadr
1337 && ifa <= (trp->vadr + (1L << trp->ps) - 1);
1340 static inline int vcpu_match_tr_entry(TR_ENTRY *trp, UINT64 ifa, UINT64 rid)
1342 return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
1345 static inline int
1346 vcpu_match_tr_entry_range(TR_ENTRY *trp, UINT64 rid, u64 b, u64 e)
1348 return trp->rid == rid
1349 && trp->pte.p
1350 && range_overlap (b, e,
1351 trp->vadr, trp->vadr + (1L << trp->ps) - 1);
1355 static TR_ENTRY*
1356 vcpu_tr_lookup(VCPU* vcpu, unsigned long va, UINT64 rid, BOOLEAN is_data)
1358 unsigned char* regions;
1359 TR_ENTRY *trp;
1360 int tr_max;
1361 int i;
1363 if (is_data) {
1364 // data
1365 regions = &vcpu->arch.dtr_regions;
1366 trp = vcpu->arch.dtrs;
1367 tr_max = sizeof(vcpu->arch.dtrs)/sizeof(vcpu->arch.dtrs[0]);
1368 } else {
1369 // instruction
1370 regions = &vcpu->arch.itr_regions;
1371 trp = vcpu->arch.itrs;
1372 tr_max = sizeof(vcpu->arch.itrs)/sizeof(vcpu->arch.itrs[0]);
1375 if (!vcpu_quick_region_check(*regions, va)) {
1376 return NULL;
1378 for (i = 0; i < tr_max; i++, trp++) {
1379 if (vcpu_match_tr_entry(trp, va, rid)) {
1380 return trp;
1383 return NULL;
1386 // return value
1387 // 0: failure
1388 // 1: success
1389 int
1390 vcpu_get_domain_bundle(VCPU* vcpu, REGS* regs, UINT64 gip, IA64_BUNDLE* bundle)
1392 UINT64 gpip;// guest pseudo phyiscal ip
1393 unsigned long vaddr;
1394 struct page_info* page;
1396 again:
1397 #if 0
1398 // Currently xen doesn't track psr.it bits.
1399 // it assumes always psr.it = 1.
1400 if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
1401 gpip = gip;
1402 } else
1403 #endif
1405 unsigned long region = REGION_NUMBER(gip);
1406 unsigned long rr = PSCB(vcpu, rrs)[region];
1407 unsigned long rid = rr & RR_RID_MASK;
1408 BOOLEAN swap_rr0;
1409 TR_ENTRY* trp;
1411 // vcpu->arch.{i, d}tlb are volatile,
1412 // copy its value to the variable, tr, before use.
1413 TR_ENTRY tr;
1415 trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
1416 if (trp != NULL) {
1417 tr = *trp;
1418 goto found;
1420 // When it failed to get a bundle, itlb miss is reflected.
1421 // Last itc.i value is cached to PSCBX(vcpu, itlb).
1422 tr = PSCBX(vcpu, itlb);
1423 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1424 //DPRINTK("%s gip 0x%lx gpip 0x%lx\n", __func__, gip, gpip);
1425 goto found;
1427 trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
1428 if (trp != NULL) {
1429 tr = *trp;
1430 goto found;
1432 #if 0
1433 tr = PSCBX(vcpu, dtlb);
1434 if (vcpu_match_tr_entry(&tr, gip, rid)) {
1435 goto found;
1437 #endif
1439 // try to access gip with guest virtual address
1440 // This may cause tlb miss. see vcpu_translate(). Be careful!
1441 swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
1442 if (swap_rr0) {
1443 set_one_rr(0x0, PSCB(vcpu, rrs[0]));
1445 *bundle = __get_domain_bundle(gip);
1446 if (swap_rr0) {
1447 set_metaphysical_rr0();
1449 if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
1450 DPRINTK("%s gip 0x%lx\n", __func__, gip);
1451 return 0;
1453 return 1;
1455 found:
1456 gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
1457 (gip & ((1 << tr.ps) - 1));
1460 vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
1461 page = virt_to_page(vaddr);
1462 if (get_page(page, vcpu->domain) == 0) {
1463 if (page_get_owner(page) != vcpu->domain) {
1464 // This page might be a page granted by another
1465 // domain.
1466 panic_domain(regs,
1467 "domain tries to execute foreign domain "
1468 "page which might be mapped by grant "
1469 "table.\n");
1471 goto again;
1473 *bundle = *((IA64_BUNDLE*)vaddr);
1474 put_page(page);
1475 return 1;
1478 IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pteval, UINT64 *itir, UINT64 *iha)
1480 unsigned long region = address >> 61;
1481 unsigned long pta, rid, rr;
1482 union pte_flags pte;
1483 TR_ENTRY *trp;
1485 if (PSCB(vcpu,metaphysical_mode) && !(!is_data && region)) {
1486 // dom0 may generate an uncacheable physical address (msb=1)
1487 if (region && ((region != 4) || (vcpu->domain != dom0))) {
1488 // FIXME: This seems to happen even though it shouldn't. Need to track
1489 // this down, but since it has been apparently harmless, just flag it for now
1490 // panic_domain(vcpu_regs(vcpu),
1492 /*
1493 * Guest may execute itc.d and rfi with psr.dt=0
1494 * When VMM try to fetch opcode, tlb miss may happen,
1495 * At this time PSCB(vcpu,metaphysical_mode)=1,
1496 * region=5,VMM need to handle this tlb miss as if
1497 * PSCB(vcpu,metaphysical_mode)=0
1498 */
1499 printk("vcpu_translate: bad physical address: 0x%lx at %lx\n",
1500 address, vcpu_regs (vcpu)->cr_iip);
1502 } else {
1503 *pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS |
1504 _PAGE_PL_2 | _PAGE_AR_RWX;
1505 *itir = PAGE_SHIFT << 2;
1506 phys_translate_count++;
1507 return IA64_NO_FAULT;
1510 else if (!region && warn_region0_address) {
1511 REGS *regs = vcpu_regs(vcpu);
1512 unsigned long viip = PSCB(vcpu,iip);
1513 unsigned long vipsr = PSCB(vcpu,ipsr);
1514 unsigned long iip = regs->cr_iip;
1515 unsigned long ipsr = regs->cr_ipsr;
1516 printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
1517 address, viip, vipsr, iip, ipsr);
1520 rr = PSCB(vcpu,rrs)[region];
1521 rid = rr & RR_RID_MASK;
1522 if (is_data) {
1523 trp = vcpu_tr_lookup(vcpu, address, rid, 1);
1524 if (trp != NULL) {
1525 *pteval = trp->pte.val;
1526 *itir = trp->itir;
1527 tr_translate_count++;
1528 return IA64_NO_FAULT;
1531 // FIXME?: check itr's for data accesses too, else bad things happen?
1532 /* else */ {
1533 trp = vcpu_tr_lookup(vcpu, address, rid, 0);
1534 if (trp != NULL) {
1535 *pteval = trp->pte.val;
1536 *itir = trp->itir;
1537 tr_translate_count++;
1538 return IA64_NO_FAULT;
1542 /* check 1-entry TLB */
1543 // FIXME?: check dtlb for inst accesses too, else bad things happen?
1544 trp = &vcpu->arch.dtlb;
1545 pte = trp->pte;
1546 if (/* is_data && */ pte.p
1547 && vcpu_match_tr_entry_no_p(trp,address,rid)) {
1548 *pteval = pte.val;
1549 *itir = trp->itir;
1550 dtlb_translate_count++;
1551 return IA64_USE_TLB;
1554 /* check guest VHPT */
1555 pta = PSCB(vcpu,pta);
1556 if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
1557 panic_domain(vcpu_regs(vcpu),"can't do long format VHPT\n");
1558 //return (is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR);
1561 *itir = rr & (RR_RID_MASK | RR_PS_MASK);
1562 // note: architecturally, iha is optionally set for alt faults but
1563 // xenlinux depends on it so should document it as part of PV interface
1564 vcpu_thash(vcpu, address, iha);
1565 if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE))
1566 return (is_data ? IA64_ALT_DATA_TLB_VECTOR : IA64_ALT_INST_TLB_VECTOR);
1568 /* avoid recursively walking (short format) VHPT */
1569 if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
1570 return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
1572 if (!__access_ok (*iha)
1573 || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
1574 // virtual VHPT walker "missed" in TLB
1575 return IA64_VHPT_FAULT;
1577 /*
1578 * Optimisation: this VHPT walker aborts on not-present pages
1579 * instead of inserting a not-present translation, this allows
1580 * vectoring directly to the miss handler.
1581 */
1582 if (!pte.p)
1583 return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
1585 /* found mapping in guest VHPT! */
1586 *itir = rr & RR_PS_MASK;
1587 *pteval = pte.val;
1588 vhpt_translate_count++;
1589 return IA64_NO_FAULT;
1592 IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
1594 UINT64 pteval, itir, mask, iha;
1595 IA64FAULT fault;
1597 fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
1598 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB)
1600 mask = itir_mask(itir);
1601 *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
1602 return (IA64_NO_FAULT);
1604 return vcpu_force_data_miss(vcpu,vadr);
1607 IA64FAULT vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key)
1609 printf("vcpu_tak: tak instruction unsupported\n");
1610 return (IA64_ILLOP_FAULT);
1611 // HACK ALERT: tak does a thash for now
1612 //return vcpu_thash(vcpu,vadr,key);
1615 /**************************************************************************
1616 VCPU debug breakpoint register access routines
1617 **************************************************************************/
1619 IA64FAULT vcpu_set_dbr(VCPU *vcpu, UINT64 reg, UINT64 val)
1621 // TODO: unimplemented DBRs return a reserved register fault
1622 // TODO: Should set Logical CPU state, not just physical
1623 ia64_set_dbr(reg,val);
1624 return (IA64_NO_FAULT);
1627 IA64FAULT vcpu_set_ibr(VCPU *vcpu, UINT64 reg, UINT64 val)
1629 // TODO: unimplemented IBRs return a reserved register fault
1630 // TODO: Should set Logical CPU state, not just physical
1631 ia64_set_ibr(reg,val);
1632 return (IA64_NO_FAULT);
1635 IA64FAULT vcpu_get_dbr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1637 // TODO: unimplemented DBRs return a reserved register fault
1638 UINT64 val = ia64_get_dbr(reg);
1639 *pval = val;
1640 return (IA64_NO_FAULT);
1643 IA64FAULT vcpu_get_ibr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1645 // TODO: unimplemented IBRs return a reserved register fault
1646 UINT64 val = ia64_get_ibr(reg);
1647 *pval = val;
1648 return (IA64_NO_FAULT);
1651 /**************************************************************************
1652 VCPU performance monitor register access routines
1653 **************************************************************************/
1655 IA64FAULT vcpu_set_pmc(VCPU *vcpu, UINT64 reg, UINT64 val)
1657 // TODO: Should set Logical CPU state, not just physical
1658 // NOTE: Writes to unimplemented PMC registers are discarded
1659 #ifdef DEBUG_PFMON
1660 printf("vcpu_set_pmc(%x,%lx)\n",reg,val);
1661 #endif
1662 ia64_set_pmc(reg,val);
1663 return (IA64_NO_FAULT);
1666 IA64FAULT vcpu_set_pmd(VCPU *vcpu, UINT64 reg, UINT64 val)
1668 // TODO: Should set Logical CPU state, not just physical
1669 // NOTE: Writes to unimplemented PMD registers are discarded
1670 #ifdef DEBUG_PFMON
1671 printf("vcpu_set_pmd(%x,%lx)\n",reg,val);
1672 #endif
1673 ia64_set_pmd(reg,val);
1674 return (IA64_NO_FAULT);
1677 IA64FAULT vcpu_get_pmc(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1679 // NOTE: Reads from unimplemented PMC registers return zero
1680 UINT64 val = (UINT64)ia64_get_pmc(reg);
1681 #ifdef DEBUG_PFMON
1682 printf("%lx=vcpu_get_pmc(%x)\n",val,reg);
1683 #endif
1684 *pval = val;
1685 return (IA64_NO_FAULT);
1688 IA64FAULT vcpu_get_pmd(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1690 // NOTE: Reads from unimplemented PMD registers return zero
1691 UINT64 val = (UINT64)ia64_get_pmd(reg);
1692 #ifdef DEBUG_PFMON
1693 printf("%lx=vcpu_get_pmd(%x)\n",val,reg);
1694 #endif
1695 *pval = val;
1696 return (IA64_NO_FAULT);
1699 /**************************************************************************
1700 VCPU banked general register access routines
1701 **************************************************************************/
1702 #define vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1703 do{ \
1704 __asm__ __volatile__ ( \
1705 ";;extr.u %0 = %3,%6,16;;\n" \
1706 "dep %1 = %0, %1, 0, 16;;\n" \
1707 "st8 [%4] = %1\n" \
1708 "extr.u %0 = %2, 16, 16;;\n" \
1709 "dep %3 = %0, %3, %6, 16;;\n" \
1710 "st8 [%5] = %3\n" \
1711 ::"r"(i),"r"(*b1unat),"r"(*b0unat),"r"(*runat),"r"(b1unat), \
1712 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1713 }while(0)
1715 IA64FAULT vcpu_bsw0(VCPU *vcpu)
1717 // TODO: Only allowed for current vcpu
1718 REGS *regs = vcpu_regs(vcpu);
1719 unsigned long *r = &regs->r16;
1720 unsigned long *b0 = &PSCB(vcpu,bank0_regs[0]);
1721 unsigned long *b1 = &PSCB(vcpu,bank1_regs[0]);
1722 unsigned long *runat = &regs->eml_unat;
1723 unsigned long *b0unat = &PSCB(vcpu,vbnat);
1724 unsigned long *b1unat = &PSCB(vcpu,vnat);
1726 unsigned long i;
1728 if(VMX_DOMAIN(vcpu)){
1729 if(VCPU(vcpu,vpsr)&IA64_PSR_BN){
1730 for (i = 0; i < 16; i++) { *b1++ = *r; *r++ = *b0++; }
1731 vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1732 VCPU(vcpu,vpsr) &= ~IA64_PSR_BN;
1734 }else{
1735 if (PSCB(vcpu,banknum)) {
1736 for (i = 0; i < 16; i++) { *b1++ = *r; *r++ = *b0++; }
1737 vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1738 PSCB(vcpu,banknum) = 0;
1741 return (IA64_NO_FAULT);
1744 #define vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
1745 do{ \
1746 __asm__ __volatile__ ( \
1747 ";;extr.u %0 = %3,%6,16;;\n" \
1748 "dep %1 = %0, %1, 16, 16;;\n" \
1749 "st8 [%4] = %1\n" \
1750 "extr.u %0 = %2, 0, 16;;\n" \
1751 "dep %3 = %0, %3, %6, 16;;\n" \
1752 "st8 [%5] = %3\n" \
1753 ::"r"(i),"r"(*b0unat),"r"(*b1unat),"r"(*runat),"r"(b0unat), \
1754 "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
1755 }while(0)
1757 IA64FAULT vcpu_bsw1(VCPU *vcpu)
1759 // TODO: Only allowed for current vcpu
1760 REGS *regs = vcpu_regs(vcpu);
1761 unsigned long *r = &regs->r16;
1762 unsigned long *b0 = &PSCB(vcpu,bank0_regs[0]);
1763 unsigned long *b1 = &PSCB(vcpu,bank1_regs[0]);
1764 unsigned long *runat = &regs->eml_unat;
1765 unsigned long *b0unat = &PSCB(vcpu,vbnat);
1766 unsigned long *b1unat = &PSCB(vcpu,vnat);
1768 unsigned long i;
1770 if(VMX_DOMAIN(vcpu)){
1771 if(!(VCPU(vcpu,vpsr)&IA64_PSR_BN)){
1772 for (i = 0; i < 16; i++) { *b0++ = *r; *r++ = *b1++; }
1773 vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1774 VCPU(vcpu,vpsr) |= IA64_PSR_BN;
1776 }else{
1777 if (!PSCB(vcpu,banknum)) {
1778 for (i = 0; i < 16; i++) { *b0++ = *r; *r++ = *b1++; }
1779 vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
1780 PSCB(vcpu,banknum) = 1;
1783 return (IA64_NO_FAULT);
1786 /**************************************************************************
1787 VCPU cpuid access routines
1788 **************************************************************************/
1791 IA64FAULT vcpu_get_cpuid(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1793 // FIXME: This could get called as a result of a rsvd-reg fault
1794 // if reg > 3
1795 switch(reg) {
1796 case 0:
1797 memcpy(pval,"Xen/ia64",8);
1798 break;
1799 case 1:
1800 *pval = 0;
1801 break;
1802 case 2:
1803 *pval = 0;
1804 break;
1805 case 3:
1806 *pval = ia64_get_cpuid(3);
1807 break;
1808 case 4:
1809 *pval = ia64_get_cpuid(4);
1810 break;
1811 default:
1812 if (reg > (ia64_get_cpuid(3) & 0xff))
1813 return IA64_RSVDREG_FAULT;
1814 *pval = ia64_get_cpuid(reg);
1815 break;
1817 return (IA64_NO_FAULT);
1820 /**************************************************************************
1821 VCPU region register access routines
1822 **************************************************************************/
1824 unsigned long vcpu_get_rr_ve(VCPU *vcpu,UINT64 vadr)
1826 ia64_rr rr;
1828 rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
1829 return(rr.ve);
1832 IA64FAULT vcpu_set_rr(VCPU *vcpu, UINT64 reg, UINT64 val)
1834 PSCB(vcpu,rrs)[reg>>61] = val;
1835 // warning: set_one_rr() does it "live"
1836 set_one_rr(reg,val);
1837 return (IA64_NO_FAULT);
1840 IA64FAULT vcpu_get_rr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1842 if(VMX_DOMAIN(vcpu)){
1843 *pval = VMX(vcpu,vrr[reg>>61]);
1844 }else{
1845 *pval = PSCB(vcpu,rrs)[reg>>61];
1847 return (IA64_NO_FAULT);
1850 /**************************************************************************
1851 VCPU protection key register access routines
1852 **************************************************************************/
1854 IA64FAULT vcpu_get_pkr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
1856 #ifndef PKR_USE_FIXED
1857 printk("vcpu_get_pkr: called, not implemented yet\n");
1858 return IA64_ILLOP_FAULT;
1859 #else
1860 UINT64 val = (UINT64)ia64_get_pkr(reg);
1861 *pval = val;
1862 return (IA64_NO_FAULT);
1863 #endif
1866 IA64FAULT vcpu_set_pkr(VCPU *vcpu, UINT64 reg, UINT64 val)
1868 #ifndef PKR_USE_FIXED
1869 printk("vcpu_set_pkr: called, not implemented yet\n");
1870 return IA64_ILLOP_FAULT;
1871 #else
1872 // if (reg >= NPKRS) return (IA64_ILLOP_FAULT);
1873 vcpu->pkrs[reg] = val;
1874 ia64_set_pkr(reg,val);
1875 return (IA64_NO_FAULT);
1876 #endif
1879 /**************************************************************************
1880 VCPU translation register access routines
1881 **************************************************************************/
1883 static void
1884 vcpu_set_tr_entry_rid(TR_ENTRY *trp, UINT64 pte,
1885 UINT64 itir, UINT64 ifa, UINT64 rid)
1887 UINT64 ps;
1888 union pte_flags new_pte;
1890 trp->itir = itir;
1891 trp->rid = rid;
1892 ps = trp->ps;
1893 new_pte.val = pte;
1894 if (new_pte.pl < 2) new_pte.pl = 2;
1895 trp->vadr = ifa & ~0xfff;
1896 if (ps > 12) { // "ignore" relevant low-order bits
1897 new_pte.ppn &= ~((1UL<<(ps-12))-1);
1898 trp->vadr &= ~((1UL<<ps)-1);
1901 /* Atomic write. */
1902 trp->pte.val = new_pte.val;
1905 static inline void
1906 vcpu_set_tr_entry(TR_ENTRY *trp, UINT64 pte, UINT64 itir, UINT64 ifa)
1908 vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
1909 VCPU(current, rrs[ifa>>61]) & RR_RID_MASK);
1912 IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte,
1913 UINT64 itir, UINT64 ifa)
1915 TR_ENTRY *trp;
1917 if (slot >= NDTRS) return IA64_RSVDREG_FAULT;
1919 vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
1921 trp = &PSCBX(vcpu,dtrs[slot]);
1922 //printf("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
1923 vcpu_set_tr_entry(trp,pte,itir,ifa);
1924 vcpu_quick_region_set(PSCBX(vcpu,dtr_regions),ifa);
1926 vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
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 vcpu_flush_tlb_vhpt_range(ifa & itir_mask(itir), itir_ps(itir));
1947 return IA64_NO_FAULT;
1950 IA64FAULT vcpu_set_itr(VCPU *vcpu, u64 slot, u64 pte,
1951 u64 itir, u64 ifa, u64 rid)
1953 TR_ENTRY *trp;
1955 if (slot >= NITRS)
1956 return IA64_RSVDREG_FAULT;
1957 trp = &PSCBX(vcpu, itrs[slot]);
1958 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
1960 /* Recompute the itr_region. */
1961 vcpu->arch.itr_regions = 0;
1962 for (trp = vcpu->arch.itrs; trp < &vcpu->arch.itrs[NITRS]; trp++)
1963 if (trp->pte.p)
1964 vcpu_quick_region_set(vcpu->arch.itr_regions,
1965 trp->vadr);
1966 return IA64_NO_FAULT;
1969 IA64FAULT vcpu_set_dtr(VCPU *vcpu, u64 slot, u64 pte,
1970 u64 itir, u64 ifa, u64 rid)
1972 TR_ENTRY *trp;
1974 if (slot >= NDTRS)
1975 return IA64_RSVDREG_FAULT;
1976 trp = &PSCBX(vcpu, dtrs[slot]);
1977 vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
1979 /* Recompute the dtr_region. */
1980 vcpu->arch.dtr_regions = 0;
1981 for (trp = vcpu->arch.dtrs; trp < &vcpu->arch.dtrs[NDTRS]; trp++)
1982 if (trp->pte.p)
1983 vcpu_quick_region_set(vcpu->arch.dtr_regions,
1984 trp->vadr);
1985 return IA64_NO_FAULT;
1988 /**************************************************************************
1989 VCPU translation cache access routines
1990 **************************************************************************/
1992 void vcpu_itc_no_srlz(VCPU *vcpu, UINT64 IorD, UINT64 vaddr, UINT64 pte, UINT64 mp_pte, UINT64 logps)
1994 unsigned long psr;
1995 unsigned long ps = (vcpu->domain==dom0) ? logps : PAGE_SHIFT;
1997 check_xen_space_overlap ("itc", vaddr, 1UL << logps);
1999 // FIXME, must be inlined or potential for nested fault here!
2000 if ((vcpu->domain==dom0) && (logps < PAGE_SHIFT))
2001 panic_domain (NULL, "vcpu_itc_no_srlz: domain trying to use "
2002 "smaller page size!\n");
2004 #ifdef CONFIG_XEN_IA64_DOM0_VP
2005 BUG_ON(logps > PAGE_SHIFT);
2006 #endif
2007 psr = ia64_clear_ic();
2008 ia64_itc(IorD,vaddr,pte,ps); // FIXME: look for bigger mappings
2009 ia64_set_psr(psr);
2010 // ia64_srlz_i(); // no srls req'd, will rfi later
2011 #ifdef VHPT_GLOBAL
2012 if (vcpu->domain==dom0 && ((vaddr >> 61) == 7)) {
2013 // FIXME: this is dangerous... vhpt_flush_address ensures these
2014 // addresses never get flushed. More work needed if this
2015 // ever happens.
2016 //printf("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
2017 if (logps > PAGE_SHIFT) vhpt_multiple_insert(vaddr,pte,logps);
2018 else vhpt_insert(vaddr,pte,logps<<2);
2020 // even if domain pagesize is larger than PAGE_SIZE, just put
2021 // PAGE_SIZE mapping in the vhpt for now, else purging is complicated
2022 else vhpt_insert(vaddr,pte,PAGE_SHIFT<<2);
2023 #endif
2024 if ((mp_pte == -1UL) || (IorD & 0x4)) // don't place in 1-entry TLB
2025 return;
2026 if (IorD & 0x1) {
2027 vcpu_set_tr_entry(&PSCBX(vcpu,itlb),mp_pte,ps<<2,vaddr);
2029 if (IorD & 0x2) {
2030 vcpu_set_tr_entry(&PSCBX(vcpu,dtlb),mp_pte,ps<<2,vaddr);
2034 IA64FAULT vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
2036 unsigned long pteval, logps = itir_ps(itir);
2037 BOOLEAN swap_rr0 = (!(ifa>>61) && PSCB(vcpu,metaphysical_mode));
2038 struct p2m_entry entry;
2040 if (logps < PAGE_SHIFT)
2041 panic_domain (NULL, "vcpu_itc_d: domain trying to use "
2042 "smaller page size!\n");
2044 again:
2045 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2046 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2047 if (!pteval) return IA64_ILLOP_FAULT;
2048 if (swap_rr0) set_one_rr(0x0,PSCB(vcpu,rrs[0]));
2049 vcpu_itc_no_srlz(vcpu,2,ifa,pteval,pte,logps);
2050 if (swap_rr0) set_metaphysical_rr0();
2051 if (p2m_entry_retry(&entry)) {
2052 vcpu_flush_tlb_vhpt_range(ifa, logps);
2053 goto again;
2055 return IA64_NO_FAULT;
2058 IA64FAULT vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
2060 unsigned long pteval, logps = itir_ps(itir);
2061 BOOLEAN swap_rr0 = (!(ifa>>61) && PSCB(vcpu,metaphysical_mode));
2062 struct p2m_entry entry;
2064 if (logps < PAGE_SHIFT)
2065 panic_domain (NULL, "vcpu_itc_i: domain trying to use "
2066 "smaller page size!\n");
2067 again:
2068 //itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
2069 pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
2070 if (!pteval) return IA64_ILLOP_FAULT;
2071 if (swap_rr0) set_one_rr(0x0,PSCB(vcpu,rrs[0]));
2072 vcpu_itc_no_srlz(vcpu, 1,ifa,pteval,pte,logps);
2073 if (swap_rr0) set_metaphysical_rr0();
2074 if (p2m_entry_retry(&entry)) {
2075 vcpu_flush_tlb_vhpt_range(ifa, logps);
2076 goto again;
2078 return IA64_NO_FAULT;
2081 IA64FAULT vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 log_range)
2083 BUG_ON(vcpu != current);
2085 check_xen_space_overlap ("ptc_l", vadr, 1UL << log_range);
2087 /* Purge TC */
2088 vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb));
2089 vcpu_purge_tr_entry(&PSCBX(vcpu,itlb));
2091 /* Purge all tlb and vhpt */
2092 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2094 return IA64_NO_FAULT;
2097 // At privlvl=0, fc performs no access rights or protection key checks, while
2098 // at privlvl!=0, fc performs access rights checks as if it were a 1-byte
2099 // read but no protection key check. Thus in order to avoid an unexpected
2100 // access rights fault, we have to translate the virtual address to a
2101 // physical address (possibly via a metaphysical address) and do the fc
2102 // on the physical address, which is guaranteed to flush the same cache line
2103 IA64FAULT vcpu_fc(VCPU *vcpu, UINT64 vadr)
2105 // TODO: Only allowed for current vcpu
2106 UINT64 mpaddr, paddr;
2107 IA64FAULT fault;
2109 again:
2110 fault = vcpu_tpa(vcpu, vadr, &mpaddr);
2111 if (fault == IA64_NO_FAULT) {
2112 struct p2m_entry entry;
2113 paddr = translate_domain_mpaddr(mpaddr, &entry);
2114 ia64_fc(__va(paddr));
2115 if (p2m_entry_retry(&entry))
2116 goto again;
2118 return fault;
2121 IA64FAULT vcpu_ptc_e(VCPU *vcpu, UINT64 vadr)
2123 // Note that this only needs to be called once, i.e. the
2124 // architected loop to purge the entire TLB, should use
2125 // base = stride1 = stride2 = 0, count0 = count 1 = 1
2127 vcpu_flush_vtlb_all(current);
2129 return IA64_NO_FAULT;
2132 IA64FAULT vcpu_ptc_g(VCPU *vcpu, UINT64 vadr, UINT64 addr_range)
2134 printk("vcpu_ptc_g: called, not implemented yet\n");
2135 return IA64_ILLOP_FAULT;
2138 IA64FAULT vcpu_ptc_ga(VCPU *vcpu,UINT64 vadr,UINT64 addr_range)
2140 // FIXME: validate not flushing Xen addresses
2141 // if (Xen address) return(IA64_ILLOP_FAULT);
2142 // FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
2143 //printf("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
2145 check_xen_space_overlap ("ptc_ga", vadr, addr_range);
2147 domain_flush_vtlb_range (vcpu->domain, vadr, addr_range);
2149 return IA64_NO_FAULT;
2152 IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
2154 unsigned long region = vadr >> 61;
2155 u64 addr_range = 1UL << log_range;
2156 unsigned long rid, rr;
2157 int i;
2158 TR_ENTRY *trp;
2160 BUG_ON(vcpu != current);
2161 check_xen_space_overlap ("ptr_d", vadr, 1UL << log_range);
2163 rr = PSCB(vcpu,rrs)[region];
2164 rid = rr & RR_RID_MASK;
2166 /* Purge TC */
2167 vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb));
2169 /* Purge tr and recompute dtr_regions. */
2170 vcpu->arch.dtr_regions = 0;
2171 for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
2172 if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range))
2173 vcpu_purge_tr_entry(trp);
2174 else if (trp->pte.p)
2175 vcpu_quick_region_set(vcpu->arch.dtr_regions,
2176 trp->vadr);
2178 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2180 return IA64_NO_FAULT;
2183 IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
2185 unsigned long region = vadr >> 61;
2186 u64 addr_range = 1UL << log_range;
2187 unsigned long rid, rr;
2188 int i;
2189 TR_ENTRY *trp;
2191 BUG_ON(vcpu != current);
2192 check_xen_space_overlap ("ptr_i", vadr, 1UL << log_range);
2194 rr = PSCB(vcpu,rrs)[region];
2195 rid = rr & RR_RID_MASK;
2197 /* Purge TC */
2198 vcpu_purge_tr_entry(&PSCBX(vcpu,itlb));
2200 /* Purge tr and recompute itr_regions. */
2201 vcpu->arch.itr_regions = 0;
2202 for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
2203 if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range))
2204 vcpu_purge_tr_entry(trp);
2205 else if (trp->pte.p)
2206 vcpu_quick_region_set(vcpu->arch.itr_regions,
2207 trp->vadr);
2209 vcpu_flush_tlb_vhpt_range (vadr, log_range);
2211 return IA64_NO_FAULT;