ia64/xen-unstable

annotate xen/arch/ia64/xen/faults.c @ 10786:86e5d8458c08

[IA64] live migration

Shadow mode and live migration.

Virtualize Dirty bit.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Wed Jul 26 09:36:36 2006 -0600 (2006-07-26)
parents c8bc76d877e0
children 3d6c1af609bf
rev   line source
awilliam@10252 1 /*
awilliam@10252 2 * Miscellaneous process/domain related routines
awilliam@10252 3 *
awilliam@10252 4 * Copyright (C) 2004 Hewlett-Packard Co.
awilliam@10252 5 * Dan Magenheimer (dan.magenheimer@hp.com)
awilliam@10252 6 *
awilliam@10252 7 */
awilliam@10252 8
awilliam@10252 9 #include <xen/config.h>
awilliam@10252 10 #include <xen/lib.h>
awilliam@10252 11 #include <xen/errno.h>
awilliam@10252 12 #include <xen/sched.h>
awilliam@10252 13 #include <xen/smp.h>
awilliam@10252 14 #include <asm/ptrace.h>
awilliam@10252 15 #include <xen/delay.h>
awilliam@10252 16
awilliam@10252 17 #include <asm/system.h>
awilliam@10252 18 #include <asm/processor.h>
awilliam@10252 19 #include <xen/irq.h>
awilliam@10252 20 #include <xen/event.h>
awilliam@10252 21 #include <asm/privop.h>
awilliam@10252 22 #include <asm/vcpu.h>
awilliam@10252 23 #include <asm/ia64_int.h>
awilliam@10252 24 #include <asm/dom_fw.h>
awilliam@10252 25 #include <asm/vhpt.h>
awilliam@10252 26 #include <asm/debugger.h>
awilliam@10252 27 #include <asm/fpswa.h>
awilliam@10561 28 #include <asm/bundle.h>
awilliam@10561 29 #include <asm/privop_stat.h>
awilliam@10517 30 #include <asm/asm-xsi-offsets.h>
awilliam@10786 31 #include <asm/shadow.h>
awilliam@10252 32
awilliam@10252 33 extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
awilliam@10252 34 /* FIXME: where these declarations shold be there ? */
awilliam@10252 35 extern int ia64_hyperprivop(unsigned long, REGS *);
awilliam@10252 36 extern IA64FAULT ia64_hypercall(struct pt_regs *regs);
awilliam@10252 37
awilliam@10252 38 #define IA64_PSR_CPL1 (__IA64_UL(1) << IA64_PSR_CPL1_BIT)
awilliam@10252 39 // note IA64_PSR_PK removed from following, why is this necessary?
awilliam@10252 40 #define DELIVER_PSR_SET (IA64_PSR_IC | IA64_PSR_I | \
awilliam@10252 41 IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_CPL1 | \
awilliam@10252 42 IA64_PSR_IT | IA64_PSR_BN)
awilliam@10252 43
awilliam@10252 44 #define DELIVER_PSR_CLR (IA64_PSR_AC | IA64_PSR_DFL | IA64_PSR_DFH | \
awilliam@10252 45 IA64_PSR_SP | IA64_PSR_DI | IA64_PSR_SI | \
awilliam@10252 46 IA64_PSR_DB | IA64_PSR_LP | IA64_PSR_TB | \
awilliam@10252 47 IA64_PSR_CPL | IA64_PSR_MC | IA64_PSR_IS | \
awilliam@10252 48 IA64_PSR_ID | IA64_PSR_DA | IA64_PSR_DD | \
awilliam@10252 49 IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | IA64_PSR_IA)
awilliam@10252 50
awilliam@10252 51
awilliam@10252 52 extern void do_ssc(unsigned long ssc, struct pt_regs *regs);
awilliam@10252 53
awilliam@10252 54 #define inc_slow_reflect_count(vec) slow_reflect_count[vec>>8]++;
awilliam@10252 55
awilliam@10252 56 // should never panic domain... if it does, stack may have been overrun
awilliam@10252 57 void check_bad_nested_interruption(unsigned long isr, struct pt_regs *regs, unsigned long vector)
awilliam@10252 58 {
awilliam@10252 59 struct vcpu *v = current;
awilliam@10252 60
awilliam@10252 61 if (!(PSCB(v,ipsr) & IA64_PSR_DT)) {
awilliam@10252 62 panic_domain(regs,"psr.dt off, trying to deliver nested dtlb!\n");
awilliam@10252 63 }
awilliam@10252 64 vector &= ~0xf;
awilliam@10252 65 if (vector != IA64_DATA_TLB_VECTOR &&
awilliam@10252 66 vector != IA64_ALT_DATA_TLB_VECTOR &&
awilliam@10252 67 vector != IA64_VHPT_TRANS_VECTOR) {
awilliam@10252 68 panic_domain(regs,"psr.ic off, delivering fault=%lx,ipsr=%lx,iip=%lx,ifa=%lx,isr=%lx,PSCB.iip=%lx\n",
awilliam@10252 69 vector,regs->cr_ipsr,regs->cr_iip,PSCB(v,ifa),isr,PSCB(v,iip));
awilliam@10252 70 }
awilliam@10252 71 }
awilliam@10252 72
awilliam@10252 73 void reflect_interruption(unsigned long isr, struct pt_regs *regs, unsigned long vector)
awilliam@10252 74 {
awilliam@10252 75 struct vcpu *v = current;
awilliam@10252 76
awilliam@10252 77 if (!PSCB(v,interrupt_collection_enabled))
awilliam@10252 78 check_bad_nested_interruption(isr,regs,vector);
awilliam@10252 79 PSCB(v,unat) = regs->ar_unat; // not sure if this is really needed?
awilliam@10252 80 PSCB(v,precover_ifs) = regs->cr_ifs;
awilliam@10252 81 vcpu_bsw0(v);
awilliam@10252 82 PSCB(v,ipsr) = vcpu_get_ipsr_int_state(v,regs->cr_ipsr);
awilliam@10252 83 PSCB(v,isr) = isr;
awilliam@10252 84 PSCB(v,iip) = regs->cr_iip;
awilliam@10252 85 PSCB(v,ifs) = 0;
awilliam@10252 86 PSCB(v,incomplete_regframe) = 0;
awilliam@10252 87
awilliam@10252 88 regs->cr_iip = ((unsigned long) PSCBX(v,iva) + vector) & ~0xffUL;
awilliam@10252 89 regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
awilliam@10444 90 regs->r31 = current->domain->arch.shared_info_va + XSI_IPSR_OFS;
awilliam@10252 91
awilliam@10252 92 v->vcpu_info->evtchn_upcall_mask = 1;
awilliam@10252 93 PSCB(v,interrupt_collection_enabled) = 0;
awilliam@10252 94
awilliam@10252 95 inc_slow_reflect_count(vector);
awilliam@10252 96 }
awilliam@10252 97
awilliam@10252 98 static unsigned long pending_false_positive = 0;
awilliam@10252 99
awilliam@10252 100 void reflect_extint(struct pt_regs *regs)
awilliam@10252 101 {
awilliam@10252 102 unsigned long isr = regs->cr_ipsr & IA64_PSR_RI;
awilliam@10252 103 struct vcpu *v = current;
awilliam@10252 104 static int first_extint = 1;
awilliam@10252 105
awilliam@10252 106 if (first_extint) {
awilliam@10252 107 printf("Delivering first extint to domain: isr=0x%lx, iip=0x%lx\n", isr, regs->cr_iip);
awilliam@10252 108 first_extint = 0;
awilliam@10252 109 }
awilliam@10252 110 if (vcpu_timer_pending_early(v))
awilliam@10252 111 printf("*#*#*#* about to deliver early timer to domain %d!!!\n",v->domain->domain_id);
awilliam@10252 112 PSCB(current,itir) = 0;
awilliam@10252 113 reflect_interruption(isr,regs,IA64_EXTINT_VECTOR);
awilliam@10252 114 }
awilliam@10252 115
awilliam@10252 116 void reflect_event(struct pt_regs *regs)
awilliam@10252 117 {
awilliam@10252 118 unsigned long isr = regs->cr_ipsr & IA64_PSR_RI;
awilliam@10252 119 struct vcpu *v = current;
awilliam@10252 120
awilliam@10252 121 /* Sanity check */
awilliam@10252 122 if (is_idle_vcpu(v) || !user_mode(regs)) {
awilliam@10252 123 //printk("WARN: invocation to reflect_event in nested xen\n");
awilliam@10252 124 return;
awilliam@10252 125 }
awilliam@10252 126
awilliam@10252 127 if (!event_pending(v))
awilliam@10252 128 return;
awilliam@10252 129
awilliam@10252 130 if (!PSCB(v,interrupt_collection_enabled))
awilliam@10252 131 printf("psr.ic off, delivering event, ipsr=%lx,iip=%lx,isr=%lx,viip=0x%lx\n",
awilliam@10252 132 regs->cr_ipsr, regs->cr_iip, isr, PSCB(v, iip));
awilliam@10252 133 PSCB(v,unat) = regs->ar_unat; // not sure if this is really needed?
awilliam@10252 134 PSCB(v,precover_ifs) = regs->cr_ifs;
awilliam@10252 135 vcpu_bsw0(v);
awilliam@10252 136 PSCB(v,ipsr) = vcpu_get_ipsr_int_state(v,regs->cr_ipsr);
awilliam@10252 137 PSCB(v,isr) = isr;
awilliam@10252 138 PSCB(v,iip) = regs->cr_iip;
awilliam@10252 139 PSCB(v,ifs) = 0;
awilliam@10252 140 PSCB(v,incomplete_regframe) = 0;
awilliam@10252 141
awilliam@10252 142 regs->cr_iip = v->arch.event_callback_ip;
awilliam@10252 143 regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
awilliam@10444 144 regs->r31 = current->domain->arch.shared_info_va + XSI_IPSR_OFS;
awilliam@10252 145
awilliam@10252 146 v->vcpu_info->evtchn_upcall_mask = 1;
awilliam@10252 147 PSCB(v,interrupt_collection_enabled) = 0;
awilliam@10252 148 }
awilliam@10252 149
awilliam@10252 150 // ONLY gets called from ia64_leave_kernel
awilliam@10252 151 // ONLY call with interrupts disabled?? (else might miss one?)
awilliam@10252 152 // NEVER successful if already reflecting a trap/fault because psr.i==0
awilliam@10252 153 void deliver_pending_interrupt(struct pt_regs *regs)
awilliam@10252 154 {
awilliam@10252 155 struct domain *d = current->domain;
awilliam@10252 156 struct vcpu *v = current;
awilliam@10252 157 // FIXME: Will this work properly if doing an RFI???
awilliam@10252 158 if (!is_idle_domain(d) && user_mode(regs)) {
awilliam@10252 159 if (vcpu_deliverable_interrupts(v))
awilliam@10252 160 reflect_extint(regs);
awilliam@10252 161 else if (PSCB(v,pending_interruption))
awilliam@10252 162 ++pending_false_positive;
awilliam@10252 163 }
awilliam@10252 164 }
awilliam@10252 165
awilliam@10252 166 static int
awilliam@10252 167 handle_lazy_cover(struct vcpu *v, struct pt_regs *regs)
awilliam@10252 168 {
awilliam@10252 169 if (!PSCB(v,interrupt_collection_enabled)) {
awilliam@10252 170 PSCB(v,ifs) = regs->cr_ifs;
awilliam@10252 171 PSCB(v,incomplete_regframe) = 1;
awilliam@10252 172 regs->cr_ifs = 0;
awilliam@10252 173 lazy_cover_count++;
awilliam@10252 174 return(1); // retry same instruction with cr.ifs off
awilliam@10252 175 }
awilliam@10252 176 return(0);
awilliam@10252 177 }
awilliam@10252 178
awilliam@10252 179 void ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs, unsigned long itir)
awilliam@10252 180 {
awilliam@10252 181 unsigned long iip = regs->cr_iip, iha;
awilliam@10252 182 // FIXME should validate address here
awilliam@10252 183 unsigned long pteval;
awilliam@10252 184 unsigned long is_data = !((isr >> IA64_ISR_X_BIT) & 1UL);
awilliam@10252 185 IA64FAULT fault;
awilliam@10435 186 int is_ptc_l_needed = 0;
awilliam@10435 187 u64 logps;
awilliam@10252 188
awilliam@10252 189 if ((isr & IA64_ISR_SP)
awilliam@10252 190 || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH))
awilliam@10252 191 {
awilliam@10252 192 /*
awilliam@10252 193 * This fault was due to a speculative load or lfetch.fault, set the "ed"
awilliam@10252 194 * bit in the psr to ensure forward progress. (Target register will get a
awilliam@10252 195 * NaT for ld.s, lfetch will be canceled.)
awilliam@10252 196 */
awilliam@10252 197 ia64_psr(regs)->ed = 1;
awilliam@10252 198 return;
awilliam@10252 199 }
awilliam@10252 200
awilliam@10252 201 again:
awilliam@10252 202 fault = vcpu_translate(current,address,is_data,&pteval,&itir,&iha);
awilliam@10252 203 if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
awilliam@10423 204 struct p2m_entry entry;
awilliam@10423 205 pteval = translate_domain_pte(pteval, address, itir, &logps, &entry);
awilliam@10252 206 vcpu_itc_no_srlz(current,is_data?2:1,address,pteval,-1UL,logps);
awilliam@10425 207 if ((fault == IA64_USE_TLB && !current->arch.dtlb.pte.p) ||
awilliam@10425 208 p2m_entry_retry(&entry)) {
awilliam@10425 209 /* dtlb has been purged in-between. This dtlb was
awilliam@10425 210 matching. Undo the work. */
awilliam@10688 211 vcpu_flush_tlb_vhpt_range(address, logps);
awilliam@10435 212
awilliam@10435 213 // the stale entry which we inserted above
awilliam@10435 214 // may remains in tlb cache.
awilliam@10435 215 // we don't purge it now hoping next itc purges it.
awilliam@10435 216 is_ptc_l_needed = 1;
awilliam@10252 217 goto again;
awilliam@10252 218 }
awilliam@10252 219 return;
awilliam@10252 220 }
awilliam@10252 221
awilliam@10435 222 if (is_ptc_l_needed)
awilliam@10435 223 vcpu_ptc_l(current, address, logps);
awilliam@10252 224 if (!user_mode (regs)) {
awilliam@10252 225 /* The fault occurs inside Xen. */
awilliam@10252 226 if (!ia64_done_with_exception(regs)) {
awilliam@10252 227 // should never happen. If it does, region 0 addr may
awilliam@10252 228 // indicate a bad xen pointer
awilliam@10252 229 printk("*** xen_handle_domain_access: exception table"
awilliam@10252 230 " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
awilliam@10252 231 iip, address);
awilliam@10252 232 panic_domain(regs,"*** xen_handle_domain_access: exception table"
awilliam@10252 233 " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
awilliam@10252 234 iip, address);
awilliam@10252 235 }
awilliam@10252 236 return;
awilliam@10252 237 }
awilliam@10450 238
awilliam@10450 239 if ((isr & IA64_ISR_IR) && handle_lazy_cover(current, regs))
awilliam@10450 240 return;
awilliam@10450 241
awilliam@10252 242 if (!PSCB(current,interrupt_collection_enabled)) {
awilliam@10252 243 check_bad_nested_interruption(isr,regs,fault);
awilliam@10252 244 //printf("Delivering NESTED DATA TLB fault\n");
awilliam@10252 245 fault = IA64_DATA_NESTED_TLB_VECTOR;
awilliam@10252 246 regs->cr_iip = ((unsigned long) PSCBX(current,iva) + fault) & ~0xffUL;
awilliam@10252 247 regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
awilliam@10252 248 // NOTE: nested trap must NOT pass PSCB address
awilliam@10252 249 //regs->r31 = (unsigned long) &PSCB(current);
awilliam@10252 250 inc_slow_reflect_count(fault);
awilliam@10252 251 return;
awilliam@10252 252 }
awilliam@10252 253
awilliam@10252 254 PSCB(current,itir) = itir;
awilliam@10252 255 PSCB(current,iha) = iha;
awilliam@10252 256 PSCB(current,ifa) = address;
awilliam@10252 257 reflect_interruption(isr, regs, fault);
awilliam@10252 258 }
awilliam@10252 259
awilliam@10252 260 fpswa_interface_t *fpswa_interface = 0;
awilliam@10252 261
awilliam@10252 262 void trap_init (void)
awilliam@10252 263 {
awilliam@10252 264 if (ia64_boot_param->fpswa)
awilliam@10252 265 /* FPSWA fixup: make the interface pointer a virtual address: */
awilliam@10252 266 fpswa_interface = __va(ia64_boot_param->fpswa);
awilliam@10252 267 else
awilliam@10252 268 printk("No FPSWA supported.\n");
awilliam@10252 269 }
awilliam@10252 270
awilliam@10252 271 static fpswa_ret_t
awilliam@10252 272 fp_emulate (int fp_fault, void *bundle, unsigned long *ipsr,
awilliam@10252 273 unsigned long *fpsr, unsigned long *isr, unsigned long *pr,
awilliam@10252 274 unsigned long *ifs, struct pt_regs *regs)
awilliam@10252 275 {
awilliam@10252 276 fp_state_t fp_state;
awilliam@10252 277 fpswa_ret_t ret;
awilliam@10252 278
awilliam@10252 279 if (!fpswa_interface)
awilliam@10252 280 return ((fpswa_ret_t) {-1, 0, 0, 0});
awilliam@10252 281
awilliam@10252 282 memset(&fp_state, 0, sizeof(fp_state_t));
awilliam@10252 283
awilliam@10252 284 /*
awilliam@10252 285 * compute fp_state. only FP registers f6 - f11 are used by the
awilliam@10252 286 * kernel, so set those bits in the mask and set the low volatile
awilliam@10252 287 * pointer to point to these registers.
awilliam@10252 288 */
awilliam@10252 289 fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */
awilliam@10252 290
awilliam@10252 291 fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;
awilliam@10252 292 /*
awilliam@10252 293 * unsigned long (*EFI_FPSWA) (
awilliam@10252 294 * unsigned long trap_type,
awilliam@10252 295 * void *Bundle,
awilliam@10252 296 * unsigned long *pipsr,
awilliam@10252 297 * unsigned long *pfsr,
awilliam@10252 298 * unsigned long *pisr,
awilliam@10252 299 * unsigned long *ppreds,
awilliam@10252 300 * unsigned long *pifs,
awilliam@10252 301 * void *fp_state);
awilliam@10252 302 */
awilliam@10252 303 ret = (*fpswa_interface->fpswa)(fp_fault, bundle,
awilliam@10252 304 ipsr, fpsr, isr, pr, ifs, &fp_state);
awilliam@10252 305
awilliam@10252 306 return ret;
awilliam@10252 307 }
awilliam@10252 308
awilliam@10252 309 /*
awilliam@10252 310 * Handle floating-point assist faults and traps for domain.
awilliam@10252 311 */
awilliam@10252 312 unsigned long
awilliam@10252 313 handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
awilliam@10252 314 {
awilliam@10252 315 struct vcpu *v = current;
awilliam@10252 316 IA64_BUNDLE bundle;
awilliam@10252 317 unsigned long fault_ip;
awilliam@10252 318 fpswa_ret_t ret;
awilliam@10252 319
awilliam@10252 320 fault_ip = regs->cr_iip;
awilliam@10252 321 /*
awilliam@10252 322 * When the FP trap occurs, the trapping instruction is completed.
awilliam@10252 323 * If ipsr.ri == 0, there is the trapping instruction in previous bundle.
awilliam@10252 324 */
awilliam@10252 325 if (!fp_fault && (ia64_psr(regs)->ri == 0))
awilliam@10252 326 fault_ip -= 16;
awilliam@10704 327
awilliam@10704 328 if (VMX_DOMAIN(current))
awilliam@10704 329 bundle = __vmx_get_domain_bundle(fault_ip);
awilliam@10704 330 else
awilliam@10704 331 bundle = __get_domain_bundle(fault_ip);
awilliam@10704 332
awilliam@10252 333 if (!bundle.i64[0] && !bundle.i64[1]) {
awilliam@10252 334 printk("%s: floating-point bundle at 0x%lx not mapped\n",
awilliam@10252 335 __FUNCTION__, fault_ip);
awilliam@10252 336 return -1;
awilliam@10252 337 }
awilliam@10252 338
awilliam@10252 339 ret = fp_emulate(fp_fault, &bundle, &regs->cr_ipsr, &regs->ar_fpsr,
awilliam@10252 340 &isr, &regs->pr, &regs->cr_ifs, regs);
awilliam@10252 341
awilliam@10252 342 if (ret.status) {
awilliam@10252 343 PSCBX(v, fpswa_ret) = ret;
awilliam@10252 344 printk("%s(%s): fp_emulate() returned %ld\n",
awilliam@10252 345 __FUNCTION__, fp_fault?"fault":"trap", ret.status);
awilliam@10252 346 }
awilliam@10252 347
awilliam@10252 348 return ret.status;
awilliam@10252 349 }
awilliam@10252 350
awilliam@10252 351 void
awilliam@10252 352 ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
awilliam@10252 353 unsigned long iim, unsigned long itir, unsigned long arg5,
awilliam@10252 354 unsigned long arg6, unsigned long arg7, unsigned long stack)
awilliam@10252 355 {
awilliam@10252 356 struct pt_regs *regs = (struct pt_regs *) &stack;
awilliam@10252 357 unsigned long code;
awilliam@10415 358 static const char * const reason[] = {
awilliam@10252 359 "IA-64 Illegal Operation fault",
awilliam@10252 360 "IA-64 Privileged Operation fault",
awilliam@10252 361 "IA-64 Privileged Register fault",
awilliam@10252 362 "IA-64 Reserved Register/Field fault",
awilliam@10252 363 "Disabled Instruction Set Transition fault",
awilliam@10415 364 "Unknown fault 5", "Unknown fault 6",
awilliam@10415 365 "Unknown fault 7", "Illegal Hazard fault",
awilliam@10415 366 "Unknown fault 9", "Unknown fault 10",
awilliam@10415 367 "Unknown fault 11", "Unknown fault 12",
awilliam@10252 368 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
awilliam@10252 369 };
awilliam@10252 370
awilliam@10252 371 printf("ia64_fault, vector=0x%lx, ifa=0x%016lx, iip=0x%016lx, ipsr=0x%016lx, isr=0x%016lx\n",
awilliam@10252 372 vector, ifa, regs->cr_iip, regs->cr_ipsr, isr);
awilliam@10252 373
awilliam@10252 374
awilliam@10252 375 if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) {
awilliam@10252 376 /*
awilliam@10252 377 * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
awilliam@10252 378 * the lfetch.
awilliam@10252 379 */
awilliam@10252 380 ia64_psr(regs)->ed = 1;
awilliam@10252 381 printf("ia64_fault: handled lfetch.fault\n");
awilliam@10252 382 return;
awilliam@10252 383 }
awilliam@10252 384
awilliam@10252 385 switch (vector) {
awilliam@10252 386 case 0:
awilliam@10252 387 printk("VHPT Translation.\n");
awilliam@10252 388 break;
awilliam@10252 389
awilliam@10252 390 case 4:
awilliam@10252 391 printk("Alt DTLB.\n");
awilliam@10252 392 break;
awilliam@10252 393
awilliam@10252 394 case 6:
awilliam@10252 395 printk("Instruction Key Miss.\n");
awilliam@10252 396 break;
awilliam@10252 397
awilliam@10252 398 case 7:
awilliam@10252 399 printk("Data Key Miss.\n");
awilliam@10252 400 break;
awilliam@10252 401
awilliam@10252 402 case 8:
awilliam@10252 403 printk("Dirty-bit.\n");
awilliam@10252 404 break;
awilliam@10252 405
awilliam@10252 406 case 20:
awilliam@10252 407 printk("Page Not Found.\n");
awilliam@10252 408 break;
awilliam@10252 409
awilliam@10252 410 case 21:
awilliam@10252 411 printk("Key Permission.\n");
awilliam@10252 412 break;
awilliam@10252 413
awilliam@10252 414 case 22:
awilliam@10252 415 printk("Instruction Access Rights.\n");
awilliam@10252 416 break;
awilliam@10252 417
awilliam@10252 418 case 24: /* General Exception */
awilliam@10252 419 code = (isr >> 4) & 0xf;
awilliam@10252 420 printk("General Exception: %s%s.\n", reason[code],
awilliam@10252 421 (code == 3) ? ((isr & (1UL << 37)) ? " (RSE access)" :
awilliam@10252 422 " (data access)") : "");
awilliam@10252 423 if (code == 8) {
awilliam@10252 424 # ifdef CONFIG_IA64_PRINT_HAZARDS
awilliam@10252 425 printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
awilliam@10252 426 current->comm, current->pid,
awilliam@10252 427 regs->cr_iip + ia64_psr(regs)->ri,
awilliam@10252 428 regs->pr);
awilliam@10252 429 # endif
awilliam@10252 430 printf("ia64_fault: returning on hazard\n");
awilliam@10252 431 return;
awilliam@10252 432 }
awilliam@10252 433 break;
awilliam@10252 434
awilliam@10252 435 case 25:
awilliam@10252 436 printk("Disabled FP-Register.\n");
awilliam@10252 437 break;
awilliam@10252 438
awilliam@10252 439 case 26:
awilliam@10252 440 printk("NaT consumption.\n");
awilliam@10252 441 break;
awilliam@10252 442
awilliam@10252 443 case 29:
awilliam@10252 444 printk("Debug.\n");
awilliam@10252 445 break;
awilliam@10252 446
awilliam@10252 447 case 30:
awilliam@10252 448 printk("Unaligned Reference.\n");
awilliam@10252 449 break;
awilliam@10252 450
awilliam@10252 451 case 31:
awilliam@10252 452 printk("Unsupported data reference.\n");
awilliam@10252 453 break;
awilliam@10252 454
awilliam@10252 455 case 32:
awilliam@10252 456 printk("Floating-Point Fault.\n");
awilliam@10252 457 break;
awilliam@10252 458
awilliam@10252 459 case 33:
awilliam@10252 460 printk("Floating-Point Trap.\n");
awilliam@10252 461 break;
awilliam@10252 462
awilliam@10252 463 case 34:
awilliam@10252 464 printk("Lower Privilege Transfer Trap.\n");
awilliam@10252 465 break;
awilliam@10252 466
awilliam@10252 467 case 35:
awilliam@10252 468 printk("Taken Branch Trap.\n");
awilliam@10252 469 break;
awilliam@10252 470
awilliam@10252 471 case 36:
awilliam@10252 472 printk("Single Step Trap.\n");
awilliam@10252 473 break;
awilliam@10252 474
awilliam@10252 475 case 45:
awilliam@10252 476 printk("IA-32 Exception.\n");
awilliam@10252 477 break;
awilliam@10252 478
awilliam@10252 479 case 46:
awilliam@10252 480 printk("IA-32 Intercept.\n");
awilliam@10252 481 break;
awilliam@10252 482
awilliam@10252 483 case 47:
awilliam@10252 484 printk("IA-32 Interrupt.\n");
awilliam@10252 485 break;
awilliam@10252 486
awilliam@10252 487 default:
awilliam@10252 488 printk("Fault %lu\n", vector);
awilliam@10252 489 break;
awilliam@10252 490 }
awilliam@10252 491
awilliam@10252 492 show_registers(regs);
awilliam@10252 493 panic("Fault in Xen.\n");
awilliam@10252 494 }
awilliam@10252 495
awilliam@10252 496 unsigned long running_on_sim = 0;
awilliam@10252 497
awilliam@10252 498
awilliam@10252 499 /* Also read in hyperprivop.S */
awilliam@10252 500 int first_break = 0;
awilliam@10252 501
awilliam@10252 502 void
awilliam@10252 503 ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long iim)
awilliam@10252 504 {
awilliam@10252 505 struct domain *d = current->domain;
awilliam@10252 506 struct vcpu *v = current;
awilliam@10252 507 IA64FAULT vector;
awilliam@10252 508
awilliam@10252 509 if (iim == 0x80001 || iim == 0x80002) { //FIXME: don't hardcode constant
awilliam@10252 510 do_ssc(vcpu_get_gr(current,36), regs);
awilliam@10252 511 }
awilliam@10252 512 #ifdef CRASH_DEBUG
awilliam@10252 513 else if ((iim == 0 || iim == CDB_BREAK_NUM) && !user_mode(regs)) {
awilliam@10252 514 if (iim == 0)
awilliam@10252 515 show_registers(regs);
awilliam@10252 516 debugger_trap_fatal(0 /* don't care */, regs);
awilliam@10252 517 }
awilliam@10252 518 #endif
awilliam@10252 519 else if (iim == d->arch.breakimm) {
awilliam@10252 520 /* by default, do not continue */
awilliam@10252 521 v->arch.hypercall_continuation = 0;
awilliam@10252 522
awilliam@10252 523 if ((vector = ia64_hypercall(regs)) == IA64_NO_FAULT) {
awilliam@10252 524 if (!PSCBX(v, hypercall_continuation))
awilliam@10252 525 vcpu_increment_iip(current);
awilliam@10252 526 }
awilliam@10252 527 else reflect_interruption(isr, regs, vector);
awilliam@10252 528 }
awilliam@10252 529 else if (!PSCB(v,interrupt_collection_enabled)) {
awilliam@10252 530 if (ia64_hyperprivop(iim,regs))
awilliam@10252 531 vcpu_increment_iip(current);
awilliam@10252 532 }
awilliam@10252 533 else {
awilliam@10252 534 if (iim == 0)
awilliam@10252 535 die_if_kernel("bug check", regs, iim);
awilliam@10252 536 PSCB(v,iim) = iim;
awilliam@10252 537 reflect_interruption(isr,regs,IA64_BREAK_VECTOR);
awilliam@10252 538 }
awilliam@10252 539 }
awilliam@10252 540
awilliam@10252 541 void
awilliam@10252 542 ia64_handle_privop (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long itir)
awilliam@10252 543 {
awilliam@10252 544 IA64FAULT vector;
awilliam@10252 545
awilliam@10252 546 vector = priv_emulate(current,regs,isr);
awilliam@10252 547 if (vector != IA64_NO_FAULT && vector != IA64_RFI_IN_PROGRESS) {
awilliam@10252 548 // Note: if a path results in a vector to reflect that requires
awilliam@10252 549 // iha/itir (e.g. vcpu_force_data_miss), they must be set there
awilliam@10252 550 reflect_interruption(isr,regs,vector);
awilliam@10252 551 }
awilliam@10252 552 }
awilliam@10252 553
awilliam@10252 554 void
awilliam@10252 555 ia64_handle_reflection (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long iim, unsigned long vector)
awilliam@10252 556 {
awilliam@10252 557 struct vcpu *v = current;
awilliam@10252 558 unsigned long check_lazy_cover = 0;
awilliam@10252 559 unsigned long psr = regs->cr_ipsr;
awilliam@10252 560
awilliam@10252 561 /* Following faults shouldn'g be seen from Xen itself */
awilliam@10415 562 BUG_ON (!(psr & IA64_PSR_CPL));
awilliam@10252 563
awilliam@10252 564 switch(vector) {
awilliam@10252 565 case 8:
awilliam@10252 566 vector = IA64_DIRTY_BIT_VECTOR; break;
awilliam@10252 567 case 9:
awilliam@10252 568 vector = IA64_INST_ACCESS_BIT_VECTOR; break;
awilliam@10252 569 case 10:
awilliam@10252 570 check_lazy_cover = 1;
awilliam@10252 571 vector = IA64_DATA_ACCESS_BIT_VECTOR; break;
awilliam@10252 572 case 20:
awilliam@10252 573 check_lazy_cover = 1;
awilliam@10252 574 vector = IA64_PAGE_NOT_PRESENT_VECTOR; break;
awilliam@10252 575 case 22:
awilliam@10252 576 vector = IA64_INST_ACCESS_RIGHTS_VECTOR; break;
awilliam@10252 577 case 23:
awilliam@10252 578 check_lazy_cover = 1;
awilliam@10252 579 vector = IA64_DATA_ACCESS_RIGHTS_VECTOR; break;
awilliam@10252 580 case 25:
awilliam@10252 581 vector = IA64_DISABLED_FPREG_VECTOR;
awilliam@10252 582 break;
awilliam@10252 583 case 26:
awilliam@10252 584 if (((isr >> 4L) & 0xfL) == 1) {
awilliam@10415 585 /* Fault is due to a register NaT consumption fault. */
awilliam@10252 586 //regs->eml_unat = 0; FIXME: DO WE NEED THIS??
awilliam@10252 587 printf("ia64_handle_reflection: handling regNaT fault\n");
awilliam@10252 588 vector = IA64_NAT_CONSUMPTION_VECTOR; break;
awilliam@10252 589 }
awilliam@10252 590 #if 1
awilliam@10252 591 // pass null pointer dereferences through with no error
awilliam@10252 592 // but retain debug output for non-zero ifa
awilliam@10252 593 if (!ifa) {
awilliam@10252 594 vector = IA64_NAT_CONSUMPTION_VECTOR; break;
awilliam@10252 595 }
awilliam@10252 596 #endif
awilliam@10415 597 #ifdef CONFIG_PRIVIFY
awilliam@10415 598 /* Some privified operations are coded using reg+64 instead
awilliam@10415 599 of reg. */
awilliam@10252 600 printf("*** NaT fault... attempting to handle as privop\n");
awilliam@10252 601 printf("isr=%016lx, ifa=%016lx, iip=%016lx, ipsr=%016lx\n",
awilliam@10252 602 isr, ifa, regs->cr_iip, psr);
awilliam@10252 603 //regs->eml_unat = 0; FIXME: DO WE NEED THIS???
awilliam@10252 604 // certain NaT faults are higher priority than privop faults
awilliam@10252 605 vector = priv_emulate(v,regs,isr);
awilliam@10252 606 if (vector == IA64_NO_FAULT) {
awilliam@10252 607 printf("*** Handled privop masquerading as NaT fault\n");
awilliam@10252 608 return;
awilliam@10252 609 }
awilliam@10415 610 #endif
awilliam@10252 611 vector = IA64_NAT_CONSUMPTION_VECTOR; break;
awilliam@10252 612 case 27:
awilliam@10252 613 //printf("*** Handled speculation vector, itc=%lx!\n",ia64_get_itc());
awilliam@10252 614 PSCB(current,iim) = iim;
awilliam@10252 615 vector = IA64_SPECULATION_VECTOR; break;
awilliam@10252 616 case 30:
awilliam@10252 617 // FIXME: Should we handle unaligned refs in Xen??
awilliam@10252 618 vector = IA64_UNALIGNED_REF_VECTOR; break;
awilliam@10252 619 case 32:
awilliam@10252 620 if (!(handle_fpu_swa(1, regs, isr))) {
awilliam@10252 621 vcpu_increment_iip(v);
awilliam@10252 622 return;
awilliam@10252 623 }
awilliam@10252 624 printf("ia64_handle_reflection: handling FP fault\n");
awilliam@10252 625 vector = IA64_FP_FAULT_VECTOR; break;
awilliam@10252 626 case 33:
awilliam@10252 627 if (!(handle_fpu_swa(0, regs, isr))) return;
awilliam@10252 628 printf("ia64_handle_reflection: handling FP trap\n");
awilliam@10252 629 vector = IA64_FP_TRAP_VECTOR; break;
awilliam@10252 630 case 34:
awilliam@10252 631 printf("ia64_handle_reflection: handling lowerpriv trap\n");
awilliam@10252 632 vector = IA64_LOWERPRIV_TRANSFER_TRAP_VECTOR; break;
awilliam@10252 633 case 35:
awilliam@10252 634 printf("ia64_handle_reflection: handling taken branch trap\n");
awilliam@10252 635 vector = IA64_TAKEN_BRANCH_TRAP_VECTOR; break;
awilliam@10252 636 case 36:
awilliam@10252 637 printf("ia64_handle_reflection: handling single step trap\n");
awilliam@10252 638 vector = IA64_SINGLE_STEP_TRAP_VECTOR; break;
awilliam@10252 639
awilliam@10252 640 default:
awilliam@10252 641 printf("ia64_handle_reflection: unhandled vector=0x%lx\n",vector);
awilliam@10252 642 while(vector);
awilliam@10252 643 return;
awilliam@10252 644 }
awilliam@10252 645 if (check_lazy_cover && (isr & IA64_ISR_IR) && handle_lazy_cover(v, regs)) return;
awilliam@10252 646 PSCB(current,ifa) = ifa;
awilliam@10252 647 PSCB(current,itir) = vcpu_get_itir_on_fault(v,ifa);
awilliam@10252 648 reflect_interruption(isr,regs,vector);
awilliam@10252 649 }
awilliam@10252 650
awilliam@10786 651 void
awilliam@10786 652 ia64_shadow_fault(unsigned long ifa, unsigned long itir,
awilliam@10786 653 unsigned long isr, struct pt_regs *regs)
awilliam@10786 654 {
awilliam@10786 655 struct vcpu *v = current;
awilliam@10786 656 struct domain *d = current->domain;
awilliam@10786 657 unsigned long gpfn;
awilliam@10786 658 unsigned long pte = 0;
awilliam@10786 659 struct vhpt_lf_entry *vlfe;
awilliam@10786 660
awilliam@10786 661 /* There are 2 jobs to do:
awilliam@10786 662 - marking the page as dirty (the metaphysical address must be
awilliam@10786 663 extracted to do that).
awilliam@10786 664 - reflecting or not the fault (the virtual Dirty bit must be
awilliam@10786 665 extracted to decide).
awilliam@10786 666 Unfortunatly these informations are not immediatly available!
awilliam@10786 667 */
awilliam@10786 668
awilliam@10786 669 /* Extract the metaphysical address.
awilliam@10786 670 Try to get it from VHPT and M2P as we need the flags. */
awilliam@10786 671 vlfe = (struct vhpt_lf_entry *)ia64_thash(ifa);
awilliam@10786 672 pte = vlfe->page_flags;
awilliam@10786 673 if (vlfe->ti_tag == ia64_ttag(ifa)) {
awilliam@10786 674 /* The VHPT entry is valid. */
awilliam@10786 675 gpfn = get_gpfn_from_mfn((pte & _PAGE_PPN_MASK) >> PAGE_SHIFT);
awilliam@10786 676 BUG_ON(gpfn == INVALID_M2P_ENTRY);
awilliam@10786 677 }
awilliam@10786 678 else {
awilliam@10786 679 unsigned long itir, iha;
awilliam@10786 680 IA64FAULT fault;
awilliam@10786 681
awilliam@10786 682 /* The VHPT entry is not valid. */
awilliam@10786 683 vlfe = NULL;
awilliam@10786 684
awilliam@10786 685 /* FIXME: gives a chance to tpa, as the TC was valid. */
awilliam@10786 686
awilliam@10786 687 fault = vcpu_translate(v, ifa, 1, &pte, &itir, &iha);
awilliam@10786 688
awilliam@10786 689 /* Try again! */
awilliam@10786 690 if (fault != IA64_NO_FAULT) {
awilliam@10786 691 /* This will trigger a dtlb miss. */
awilliam@10786 692 ia64_ptcl(ifa, PAGE_SHIFT << 2);
awilliam@10786 693 return;
awilliam@10786 694 }
awilliam@10786 695 gpfn = ((pte & _PAGE_PPN_MASK) >> PAGE_SHIFT);
awilliam@10786 696 if (pte & _PAGE_D)
awilliam@10786 697 pte |= _PAGE_VIRT_D;
awilliam@10786 698 }
awilliam@10786 699
awilliam@10786 700 /* Set the dirty bit in the bitmap. */
awilliam@10786 701 shadow_mark_page_dirty (d, gpfn);
awilliam@10786 702
awilliam@10786 703 /* Update the local TC/VHPT and decides wether or not the fault should
awilliam@10786 704 be reflected.
awilliam@10786 705 SMP note: we almost ignore the other processors. The shadow_bitmap
awilliam@10786 706 has been atomically updated. If the dirty fault happen on another
awilliam@10786 707 processor, it will do its job.
awilliam@10786 708 */
awilliam@10786 709
awilliam@10786 710 if (pte != 0) {
awilliam@10786 711 /* We will know how to handle the fault. */
awilliam@10786 712
awilliam@10786 713 if (pte & _PAGE_VIRT_D) {
awilliam@10786 714 /* Rewrite VHPT entry.
awilliam@10786 715 There is no race here because only the
awilliam@10786 716 cpu VHPT owner can write page_flags. */
awilliam@10786 717 if (vlfe)
awilliam@10786 718 vlfe->page_flags = pte | _PAGE_D;
awilliam@10786 719
awilliam@10786 720 /* Purge the TC locally.
awilliam@10786 721 It will be reloaded from the VHPT iff the
awilliam@10786 722 VHPT entry is still valid. */
awilliam@10786 723 ia64_ptcl(ifa, PAGE_SHIFT << 2);
awilliam@10786 724
awilliam@10786 725 atomic64_inc(&d->arch.shadow_fault_count);
awilliam@10786 726 }
awilliam@10786 727 else {
awilliam@10786 728 /* Reflect.
awilliam@10786 729 In this case there is no need to purge. */
awilliam@10786 730 ia64_handle_reflection(ifa, regs, isr, 0, 8);
awilliam@10786 731 }
awilliam@10786 732 }
awilliam@10786 733 else {
awilliam@10786 734 /* We don't know wether or not the fault must be
awilliam@10786 735 reflected. The VHPT entry is not valid. */
awilliam@10786 736 /* FIXME: in metaphysical mode, we could do an ITC now. */
awilliam@10786 737 ia64_ptcl(ifa, PAGE_SHIFT << 2);
awilliam@10786 738 }
awilliam@10786 739 }