int main () { /* For each member, set that member to 1, allow gdb to verify that the member (and only that member) is 1, and then reset it back to 0. */ #ifdef usestubs set_debug_traps(); breakpoint(); #endif flags.uc = 1; break1 (); flags.uc = 0; flags.s1 = -1; break1 (); flags.s1 = 0; flags.u1 = 1; break1 (); flags.u1 = 0; flags.s2 = 1; break1 (); flags.s2 = 0; flags.u2 = 1; break1 (); flags.u2 = 0; flags.s3 = 1; break1 (); flags.s3 = 0; flags.u3 = 1; break1 (); flags.u3 = 0; flags.s9 = 1; break1 (); flags.s9 = 0; flags.u9 = 1; break1 (); flags.u9 = 0; flags.sc = 1; break1 (); flags.sc = 0; /* Fill alternating fields with all 1's and verify that none of the bits "bleed over" to the other fields. */ flags.uc = 0xFF; flags.u1 = 0x1; flags.u2 = 0x3; flags.u3 = 0x7; flags.u9 = 0x1FF; break2 (); flags.uc = 0; flags.u1 = 0; flags.u2 = 0; flags.u3 = 0; flags.u9 = 0; flags.s1 = -1; flags.s2 = -1; flags.s3 = -1; flags.s9 = -1; flags.sc = 0xFF; break2 (); flags.s1 = 0; flags.s2 = 0; flags.s3 = 0; flags.s9 = 0; flags.sc = 0; /* Fill the unsigned fields with the maximum positive value and verify that the values are printed correctly. */ /* Maximum positive values */ flags.u1 = 0x1; flags.u2 = 0x3; flags.u3 = 0x7; flags.u9 = 0x1FF; break3 (); flags.u1 = 0; flags.u2 = 0; flags.u3 = 0; flags.u9 = 0; /* Fill the signed fields with the maximum positive value, then the maximally negative value, then -1, and verify in each case that the values are printed correctly. */ /* Maximum positive values */ flags.s1 = 0x0; flags.s2 = 0x1; flags.s3 = 0x3; flags.s9 = 0xFF; break4 (); /* Maximally negative values */ flags.s1 = -0x1; flags.s2 = -0x2; flags.s3 = -0x4; flags.s9 = -0x100; /* Extract bitfield value so that bitfield.exp can check if the target understands signed bitfields. */ i = flags.s9; break4 (); /* -1 */ flags.s1 = -1; flags.s2 = -1; flags.s3 = -1; flags.s9 = -1; break4 (); flags.s1 = 0; flags.s2 = 0; flags.s3 = 0; flags.s9 = 0; /* Bitfields at a non-zero offset in a containing structure. */ container.one.u3 = 5; container.two.u3 = 3; break5 (); return 0; }
void trap(int type, struct trapframe *frame) { struct lwp *l; struct proc *p; struct pcb *pcbp; vaddr_t va; struct vm_map *map; struct vmspace *vm; vm_prot_t vftype; pa_space_t space; u_int opcode; int ret; const char *tts; int type_raw; #ifdef DIAGNOSTIC extern int emergency_stack_start, emergency_stack_end; #endif type_raw = type & ~T_USER; opcode = frame->tf_iir; if (type_raw == T_ITLBMISS || type_raw == T_ITLBMISSNA) { va = frame->tf_iioq_head; space = frame->tf_iisq_head; vftype = VM_PROT_READ; /* XXX VM_PROT_EXECUTE ??? */ } else { va = frame->tf_ior; space = frame->tf_isr; vftype = inst_store(opcode) ? VM_PROT_WRITE : VM_PROT_READ; } if ((l = curlwp) == NULL) l = &lwp0; p = l->l_proc; #ifdef DIAGNOSTIC /* * If we are on the emergency stack, then we either got * a fault on the kernel stack, or we're just handling * a trap for the machine check handler (which also * runs on the emergency stack). * * We *very crudely* differentiate between the two cases * by checking the faulting instruction: if it is the * function prologue instruction that stores the old * frame pointer and updates the stack pointer, we assume * that we faulted on the kernel stack. * * In this case, not completing that instruction will * probably confuse backtraces in kgdb/ddb. Completing * it would be difficult, because we already faulted on * that part of the stack, so instead we fix up the * frame as if the function called has just returned. * This has peculiar knowledge about what values are in * what registers during the "normal gcc -g" prologue. */ if (&type >= &emergency_stack_start && &type < &emergency_stack_end && type != T_IBREAK && STWM_R1_D_SR0_SP(opcode)) { /* Restore the caller's frame pointer. */ frame->tf_r3 = frame->tf_r1; /* Restore the caller's instruction offsets. */ frame->tf_iioq_head = frame->tf_rp; frame->tf_iioq_tail = frame->tf_iioq_head + 4; goto dead_end; } #endif /* DIAGNOSTIC */ #ifdef DEBUG frame_sanity_check(frame, l); #endif /* DEBUG */ /* If this is a trap, not an interrupt, reenable interrupts. */ if (type_raw != T_INTERRUPT) mtctl(frame->tf_eiem, CR_EIEM); if (frame->tf_flags & TFF_LAST) l->l_md.md_regs = frame; if ((type & ~T_USER) > trap_types) tts = "reserved"; else tts = trap_type[type & ~T_USER]; #ifdef TRAPDEBUG if (type_raw != T_INTERRUPT && type_raw != T_IBREAK) printf("trap: %d, %s for %x:%x at %x:%x, fp=%p, rp=%x\n", type, tts, space, (u_int)va, frame->tf_iisq_head, frame->tf_iioq_head, frame, frame->tf_rp); else if (type_raw == T_IBREAK) printf("trap: break instruction %x:%x at %x:%x, fp=%p\n", break5(opcode), break13(opcode), frame->tf_iisq_head, frame->tf_iioq_head, frame); { extern int etext; if (frame < (struct trapframe *)&etext) { printf("trap: bogus frame ptr %p\n", frame); goto dead_end; } } #endif switch (type) { case T_NONEXIST: case T_NONEXIST|T_USER: #if !defined(DDB) && !defined(KGDB) /* we've got screwed up by the central scrutinizer */ panic ("trap: elvis has just left the building!"); break; #else goto dead_end; #endif case T_RECOVERY|T_USER: #ifdef USERTRACE for(;;) { if (frame->tf_iioq_head != rctr_next_iioq) printf("-%08x\nr %08x", rctr_next_iioq - 4, frame->tf_iioq_head); rctr_next_iioq = frame->tf_iioq_head + 4; if (frame->tf_ipsw & PSW_N) { /* Advance the program counter. */ frame->tf_iioq_head = frame->tf_iioq_tail; frame->tf_iioq_tail = frame->tf_iioq_head + 4; /* Clear flags. */ frame->tf_ipsw &= ~(PSW_N|PSW_X|PSW_Y|PSW_Z|PSW_B|PSW_T|PSW_H|PSW_L); /* Simulate another trap. */ continue; } break; } frame->tf_rctr = 0; break; #endif /* USERTRACE */ case T_RECOVERY: #if !defined(DDB) && !defined(KGDB) /* XXX will implement later */ printf ("trap: handicapped"); break; #else goto dead_end; #endif case T_EMULATION | T_USER: #ifdef FPEMUL hppa_fpu_emulate(frame, l); #else /* !FPEMUL */ /* * We don't have FPU emulation, so signal the * process with a SIGFPE. */ hppa_trapsignal_hack(l, SIGFPE, frame->tf_iioq_head); #endif /* !FPEMUL */ break; #ifdef DIAGNOSTIC case T_EXCEPTION: panic("FPU/SFU emulation botch"); /* these just can't happen ever */ case T_PRIV_OP: case T_PRIV_REG: /* these just can't make it to the trap() ever */ case T_HPMC: case T_HPMC | T_USER: case T_EMULATION: #endif case T_IBREAK: case T_DATALIGN: case T_DBREAK: dead_end: if (type & T_USER) { #ifdef DEBUG user_backtrace(frame, l, type); #endif hppa_trapsignal_hack(l, SIGILL, frame->tf_iioq_head); break; } if (trap_kdebug(type, va, frame)) return; else if (type == T_DATALIGN) panic ("trap: %s at 0x%x", tts, (u_int) va); else panic ("trap: no debugger for \"%s\" (%d)", tts, type); break; case T_IBREAK | T_USER: case T_DBREAK | T_USER: /* pass to user debugger */ break; case T_EXCEPTION | T_USER: /* co-proc assist trap */ hppa_trapsignal_hack(l, SIGFPE, va); break; case T_OVERFLOW | T_USER: hppa_trapsignal_hack(l, SIGFPE, va); break; case T_CONDITION | T_USER: break; case T_ILLEGAL | T_USER: #ifdef DEBUG user_backtrace(frame, l, type); #endif hppa_trapsignal_hack(l, SIGILL, va); break; case T_PRIV_OP | T_USER: #ifdef DEBUG user_backtrace(frame, l, type); #endif hppa_trapsignal_hack(l, SIGILL, va); break; case T_PRIV_REG | T_USER: #ifdef DEBUG user_backtrace(frame, l, type); #endif hppa_trapsignal_hack(l, SIGILL, va); break; /* these should never got here */ case T_HIGHERPL | T_USER: case T_LOWERPL | T_USER: hppa_trapsignal_hack(l, SIGSEGV, va); break; case T_IPROT | T_USER: case T_DPROT | T_USER: hppa_trapsignal_hack(l, SIGSEGV, va); break; case T_DATACC: case T_USER | T_DATACC: case T_ITLBMISS: case T_USER | T_ITLBMISS: case T_DTLBMISS: case T_USER | T_DTLBMISS: case T_ITLBMISSNA: case T_USER | T_ITLBMISSNA: case T_DTLBMISSNA: case T_USER | T_DTLBMISSNA: case T_TLB_DIRTY: case T_USER | T_TLB_DIRTY: vm = p->p_vmspace; if (!vm) { #ifdef TRAPDEBUG printf("trap: no vm, p=%p\n", p); #endif goto dead_end; } /* * it could be a kernel map for exec_map faults */ if (!(type & T_USER) && space == HPPA_SID_KERNEL) map = kernel_map; else { map = &vm->vm_map; if (l->l_flag & L_SA) { l->l_savp->savp_faultaddr = va; l->l_flag |= L_SA_PAGEFAULT; } } va = hppa_trunc_page(va); if (map->pmap->pmap_space != space) { #ifdef TRAPDEBUG printf("trap: space missmatch %d != %d\n", space, map->pmap->pmap_space); #endif /* actually dump the user, crap the kernel */ goto dead_end; } /* Never call uvm_fault in interrupt context. */ KASSERT(hppa_intr_depth == 0); ret = uvm_fault(map, va, 0, vftype); #ifdef TRAPDEBUG printf("uvm_fault(%p, %x, %d, %d)=%d\n", map, (u_int)va, 0, vftype, ret); #endif if (map != kernel_map) l->l_flag &= ~L_SA_PAGEFAULT; /* * If this was a stack access we keep track of the maximum * accessed stack size. Also, if uvm_fault gets a protection * failure it is due to accessing the stack region outside * the current limit and we need to reflect that as an access * error. */ if (va >= (vaddr_t)vm->vm_maxsaddr + vm->vm_ssize) { if (ret == 0) { vsize_t nss = btoc(va - USRSTACK + PAGE_SIZE); if (nss > vm->vm_ssize) vm->vm_ssize = nss; } else if (ret == EACCES) ret = EFAULT; } if (ret != 0) { if (type & T_USER) { printf("trapsignal: uvm_fault(%p, %x, %d, %d)=%d\n", map, (u_int)va, 0, vftype, ret); #ifdef DEBUG user_backtrace(frame, l, type); #endif hppa_trapsignal_hack(l, SIGSEGV, frame->tf_ior); } else { if (l && l->l_addr->u_pcb.pcb_onfault) { #ifdef PMAPDEBUG printf("trap: copyin/out %d\n",ret); #endif pcbp = &l->l_addr->u_pcb; frame->tf_iioq_tail = 4 + (frame->tf_iioq_head = pcbp->pcb_onfault); pcbp->pcb_onfault = 0; break; } #if 1 if (trap_kdebug (type, va, frame)) return; #else panic("trap: uvm_fault(%p, %x, %d, %d): %d", map, va, 0, vftype, ret); #endif } } break; case T_DATALIGN | T_USER: #ifdef DEBUG user_backtrace(frame, l, type); #endif hppa_trapsignal_hack(l, SIGBUS, va); break; case T_INTERRUPT: case T_INTERRUPT|T_USER: hppa_intr(frame); mtctl(frame->tf_eiem, CR_EIEM); #if 0 if (trap_kdebug (type, va, frame)) return; #endif break; case T_LOWERPL: case T_DPROT: case T_IPROT: case T_OVERFLOW: case T_CONDITION: case T_ILLEGAL: case T_HIGHERPL: case T_TAKENBR: case T_POWERFAIL: case T_LPMC: case T_PAGEREF: case T_DATAPID: case T_DATAPID | T_USER: if (0 /* T-chip */) { break; } /* FALLTHROUGH to unimplemented */ default: #if 1 if (trap_kdebug (type, va, frame)) return; #endif panic ("trap: unimplemented \'%s\' (%d)", tts, type); } if (type & T_USER) userret(l, l->l_md.md_regs->tf_iioq_head, 0); #ifdef DEBUG frame_sanity_check(frame, l); if (frame->tf_flags & TFF_LAST && curlwp != NULL) frame_sanity_check(curlwp->l_md.md_regs, curlwp); #endif /* DEBUG */ }