Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/arch/mips/mips/trap.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/arch/mips/mips/trap.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.93.2.6 retrieving revision 1.94 diff -u -p -r1.93.2.6 -r1.94 --- src/sys/arch/mips/mips/trap.c 1998/11/20 15:02:06 1.93.2.6 +++ src/sys/arch/mips/mips/trap.c 1998/10/24 01:36:09 1.94 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.93.2.6 1998/11/20 15:02:06 drochner Exp $ */ +/* $NetBSD: trap.c,v 1.94 1998/10/24 01:36:09 jonathan Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -43,7 +43,7 @@ */ #include /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.93.2.6 1998/11/20 15:02:06 drochner Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.94 1998/10/24 01:36:09 jonathan Exp $"); #include "opt_cputype.h" /* which mips CPU levels do we support? */ #include "opt_inet.h" @@ -123,16 +123,217 @@ __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.9 int astpending; int want_resched; -int (*mips_hardware_intr) __P((unsigned, unsigned, unsigned, unsigned)) = 0; -void (*mips_software_intr) __P((int)) = 0; -int softisr; /* for extensible software interrupt framework */ +int (*mips_hardware_intr) __P((unsigned mask, unsigned pc, unsigned status, + unsigned cause)) = + ( int (*) __P((unsigned, unsigned, unsigned, unsigned)) ) 0; #if defined(MIPS3) && defined(MIPS3_INTERNAL_TIMER_INTERRUPT) +extern u_int32_t mips3_intr_cycle_count; u_int32_t mips3_intr_cycle_count; u_int32_t mips3_timer_delta; #endif -char *trap_type[] = { + +/* + * Exception-handling functions, called via ExceptionTable from locore + */ +#ifdef MIPS1 +extern void mips1_KernGenException __P((void)); +extern void mips1_UserGenException __P((void)); +extern void mips1_SystemCall __P((void)); +extern void mips1_KernIntr __P((void)); +extern void mips1_UserIntr __P((void)); +#if 0 +extern void mips1_TLBModException __P((void)); +#endif +extern void mips1_TLBMissException __P((void)); + +/* marks start/end of vector code */ +extern void mips1_KernGenExceptionEnd __P((void)); +extern void mips1_UserGenExceptionEnd __P((void)); +extern void mips1_SystemCallEnd __P((void)); +extern void mips1_KernIntrEnd __P((void)); +extern void mips1_UserIntrEnd __P((void)); +extern void mips1_exceptionentry_start __P((void)); +extern void mips1_exceptionentry_end __P((void)); +#endif + +#ifdef MIPS3 +extern void mips3_KernGenException __P((void)); +extern void mips3_UserGenException __P((void)); +extern void mips3_SystemCall __P((void)); +extern void mips3_KernIntr __P((void)); +extern void mips3_UserIntr __P((void)); +extern void mips3_TLBInvalidException __P((void)); +extern void mips3_TLBMissException __P((void)); + +extern void mips3_VCED __P((void)); +extern void mips3_VCEI __P((void)); /* XXXX */ + +/* marks start/end of vector code */ +extern void mips3_KernGenExceptionEnd __P((void)); +extern void mips3_UserGenExceptionEnd __P((void)); +extern void mips3_SystemCallEnd __P((void)); +extern void mips3_KernIntrEnd __P((void)); +extern void mips3_UserIntrEnd __P((void)); +extern void mips3_exceptionentry_start __P((void)); +extern void mips3_exceptionentry_end __P((void)); +#endif + + +#ifdef MIPS1 +void (*mips1_ExceptionTable[]) __P((void)) = { +/* + * The kernel exception handlers. + */ + mips1_KernIntr, /* 0 external interrupt */ + mips1_KernGenException, /* 1 TLB modification */ + mips1_TLBMissException, /* 2 TLB miss (load or instr. fetch) */ + mips1_TLBMissException, /* 3 TLB miss (store) */ + mips1_KernGenException, /* 4 address error (load or I-fetch) */ + mips1_KernGenException, /* 5 address error (store) */ + mips1_KernGenException, /* 6 bus error (I-fetch) */ + mips1_KernGenException, /* 7 bus error (load or store) */ + mips1_KernGenException, /* 8 system call */ + mips1_KernGenException, /* 9 breakpoint */ + mips1_KernGenException, /* 10 reserved instruction */ + mips1_KernGenException, /* 11 coprocessor unusable */ + mips1_KernGenException, /* 12 arithmetic overflow */ + mips1_KernGenException, /* 13 r4k trap excpt, r3k reserved */ + mips1_KernGenException, /* 14 r4k virt coherence, r3k reserved */ + mips1_KernGenException, /* 15 r4k FP exception, r3k reserved */ + mips1_KernGenException, /* 16 reserved */ + mips1_KernGenException, /* 17 reserved */ + mips1_KernGenException, /* 18 reserved */ + mips1_KernGenException, /* 19 reserved */ + mips1_KernGenException, /* 20 reserved */ + mips1_KernGenException, /* 21 reserved */ + mips1_KernGenException, /* 22 reserved */ + mips1_KernGenException, /* 23 watch exception */ + mips1_KernGenException, /* 24 reserved */ + mips1_KernGenException, /* 25 reserved */ + mips1_KernGenException, /* 26 reserved */ + mips1_KernGenException, /* 27 reserved */ + mips1_KernGenException, /* 28 reserved */ + mips1_KernGenException, /* 29 reserved */ + mips1_KernGenException, /* 30 reserved */ + mips1_KernGenException, /* 31 virt. coherence exception data */ +/* + * The user exception handlers. + */ + mips1_UserIntr, /* 0 */ + mips1_UserGenException, /* 1 */ + mips1_UserGenException, /* 2 */ + mips1_UserGenException, /* 3 */ + mips1_UserGenException, /* 4 */ + mips1_UserGenException, /* 5 */ + mips1_UserGenException, /* 6 */ + mips1_UserGenException, /* 7 */ + mips1_SystemCall, /* 8 */ + mips1_UserGenException, /* 9 */ + mips1_UserGenException, /* 10 */ + mips1_UserGenException, /* 11 */ + mips1_UserGenException, /* 12 */ + mips1_UserGenException, /* 13 */ + mips1_UserGenException, /* 14 */ + mips1_UserGenException, /* 15 */ + mips1_UserGenException, /* 16 */ + mips1_UserGenException, /* 17 */ + mips1_UserGenException, /* 18 */ + mips1_UserGenException, /* 19 */ + mips1_UserGenException, /* 20 */ + mips1_UserGenException, /* 21 */ + mips1_UserGenException, /* 22 */ + mips1_UserGenException, /* 23 */ + mips1_UserGenException, /* 24 */ + mips1_UserGenException, /* 25 */ + mips1_UserGenException, /* 26 */ + mips1_UserGenException, /* 27 */ + mips1_UserGenException, /* 28 */ + mips1_UserGenException, /* 29 */ + mips1_UserGenException, /* 20 */ + mips1_UserGenException, /* 31 */ +}; +#endif /* MIPS1 */ + +#ifdef MIPS3 /* r4000 family (mips-III cpu) */ + +void (*mips3_ExceptionTable[]) __P((void)) = { +/* + * The kernel exception handlers. + */ + mips3_KernIntr, /* 0 external interrupt */ + mips3_KernGenException, /* 1 TLB modification */ + mips3_TLBInvalidException, /* 2 TLB miss (load or instr. fetch) */ + mips3_TLBInvalidException, /* 3 TLB miss (store) */ + mips3_KernGenException, /* 4 address error (load or I-fetch) */ + mips3_KernGenException, /* 5 address error (store) */ + mips3_KernGenException, /* 6 bus error (I-fetch) */ + mips3_KernGenException, /* 7 bus error (load or store) */ + mips3_KernGenException, /* 8 system call */ + mips3_KernGenException, /* 9 breakpoint */ + mips3_KernGenException, /* 10 reserved instruction */ + mips3_KernGenException, /* 11 coprocessor unusable */ + mips3_KernGenException, /* 12 arithmetic overflow */ + mips3_KernGenException, /* 13 r4k trap excpt, r3k reserved */ + mips3_VCEI, /* 14 r4k virt coherence, r3k reserved */ + mips3_KernGenException, /* 15 r4k FP exception, r3k reserved */ + mips3_KernGenException, /* 16 reserved */ + mips3_KernGenException, /* 17 reserved */ + mips3_KernGenException, /* 18 reserved */ + mips3_KernGenException, /* 19 reserved */ + mips3_KernGenException, /* 20 reserved */ + mips3_KernGenException, /* 21 reserved */ + mips3_KernGenException, /* 22 reserved */ + mips3_KernGenException, /* 23 watch exception */ + mips3_KernGenException, /* 24 reserved */ + mips3_KernGenException, /* 25 reserved */ + mips3_KernGenException, /* 26 reserved */ + mips3_KernGenException, /* 27 reserved */ + mips3_KernGenException, /* 28 reserved */ + mips3_KernGenException, /* 29 reserved */ + mips3_KernGenException, /* 30 reserved */ + mips3_VCED, /* 31 virt. coherence exception data */ +/* + * The user exception handlers. + */ + mips3_UserIntr, /* 0 */ + mips3_UserGenException, /* 1 */ + mips3_UserGenException, /* 2 */ + mips3_UserGenException, /* 3 */ + mips3_UserGenException, /* 4 */ + mips3_UserGenException, /* 5 */ + mips3_UserGenException, /* 6 */ + mips3_UserGenException, /* 7 */ + mips3_SystemCall, /* 8 */ + mips3_UserGenException, /* 9 */ + mips3_UserGenException, /* 10 */ + mips3_UserGenException, /* 11 */ + mips3_UserGenException, /* 12 */ + mips3_UserGenException, /* 13 */ + mips3_VCEI, /* 14 */ + mips3_UserGenException, /* 15 */ + mips3_UserGenException, /* 16 */ + mips3_UserGenException, /* 17 */ + mips3_UserGenException, /* 18 */ + mips3_UserGenException, /* 19 */ + mips3_UserGenException, /* 20 */ + mips3_UserGenException, /* 21 */ + mips3_UserGenException, /* 22 */ + mips3_UserGenException, /* 23 */ + mips3_UserGenException, /* 24 */ + mips3_UserGenException, /* 25 */ + mips3_UserGenException, /* 26 */ + mips3_UserGenException, /* 27 */ + mips3_UserGenException, /* 28 */ + mips3_UserGenException, /* 29 */ + mips3_UserGenException, /* 20 */ + mips3_VCED, /* 31 virt. coherence exception data */ +}; +#endif /* MIPS3 */ + + +char *trap_type[] = { "external interrupt", "TLB modification", "TLB miss (load or instr. fetch)", @@ -167,49 +368,78 @@ char *trap_type[] = { "r4000 virtual coherency data", }; -struct trapframe { - mips_reg_t tf_regs[17]; - mips_reg_t tf_ra; - mips_reg_t tf_sr; - mips_reg_t tf_mullo; - mips_reg_t tf_mulhi; - mips_reg_t tf_epc; -}; +#ifdef DEBUG +#define TRAPSIZE 10 +struct trapdebug { /* trap history buffer for debugging */ + u_int status; + u_int cause; + u_int vadr; + u_int pc; + u_int ra; + u_int sp; + u_int code; +} trapdebug[TRAPSIZE], *trp = trapdebug; -void userret __P((struct proc *, unsigned, u_quad_t)); -void trap __P((unsigned, unsigned, unsigned, unsigned, struct trapframe)); -void syscall __P((unsigned, unsigned, unsigned)); -void interrupt __P((unsigned, unsigned, unsigned)); -void ast __P((unsigned)); -void dealfpu __P((unsigned, unsigned, unsigned)); +void trapDump __P((char * msg)); +#endif /* DEBUG */ -extern void MachEmulateFP __P((unsigned)); -extern void MachFPInterrupt __P((unsigned, unsigned, unsigned, mips_reg_t *)); +/* marks start/end of code */ +extern void splx_end __P((void)); +extern void cpu_switch_end __P((void)); +extern void idle_end __P((void)); +extern void bcopy_end __P((void)); +extern char start[], edata[]; + + +void mips1_dump_tlb __P((int, int, void (*printfn)(const char*, ...))); +void mips3_dump_tlb __P((int, int, void (*printfn)(const char*, ...))); +void mips_dump_tlb __P((int, int)); /* * Other forward declarations. */ -mips_reg_t MachEmulateBranch __P((mips_reg_t *regsPtr, +unsigned MachEmulateBranch __P((unsigned *regsPtr, unsigned instPC, unsigned fpcCSR, int allowNonBranch)); -#ifdef DEBUG -#define TRAPSIZE 10 -struct trapdebug { /* trap history buffer for debugging */ - u_int status; - u_int cause; - mips_reg_t vadr; - mips_reg_t pc; - mips_reg_t ra; - mips_reg_t sp; - u_int code; -} trapdebug[TRAPSIZE], *trp = trapdebug; +struct proc *fpcurproc; +struct pcb *curpcb; -void trapDump __P((char * msg)); -#endif /* DEBUG */ +/* extern functions used but not declared elsewhere */ +extern void clearsoftclock __P((void)); +extern void clearsoftnet __P((void)); +extern void MachFPInterrupt __P((unsigned, unsigned, unsigned, int *)); +extern void switchfpregs __P((struct proc *, struct proc *)); + +/* only called by locore */ +extern void trap __P((u_int status, u_int cause, u_int vaddr, u_int opc, + struct frame frame)); +static void userret __P((struct proc *p, unsigned pc, u_quad_t sticks)); +extern void syscall __P((unsigned status, unsigned cause, unsigned opc, + struct frame *frame)); +extern void child_return __P((struct proc *p)); +extern void interrupt __P((unsigned status, unsigned cause, unsigned pc, + struct frame *frame)); +extern void ast __P((unsigned pc)); + + /* + * stack trace code, also useful to DDB one day + */ +#if defined(DEBUG) || defined(DDB) +extern void stacktrace __P((void)); /*XXX*/ +extern void logstacktrace __P((void)); /*XXX*/ -void +/* extern functions printed by name in stack backtraces */ +extern void idle __P((void)), cpu_switch __P(( struct proc *p)); +extern void MachEmptyWriteBuffer __P((void)); +extern void MachUTLBMiss __P((void)); +extern void setsoftclock __P((void)); +extern int main __P((void*)); +extern void am7990_meminit __P((void*)); /* XXX */ +#endif /* DEBUG || DDB */ + +static void userret(p, pc, sticks) struct proc *p; unsigned pc; @@ -260,13 +490,11 @@ userret(p, pc, sticks) * and the return value (if any) in v0 and possibly v1. */ void -syscall(status, cause, opc) - unsigned status; - unsigned cause; - unsigned opc; +syscall(status, cause, opc, frame) + unsigned status, cause, opc; + struct frame *frame; { struct proc *p = curproc; - struct frame *frame = (struct frame *)p->p_md.md_regs; u_quad_t sticks; int args[8], rval[2], error; size_t code, numsys, nsaved, argsiz; @@ -337,8 +565,8 @@ syscall(status, cause, opc) argsiz = callp->sy_argsize / sizeof(int); if (argsiz > nsaved) { error = copyin( - (void *)((int *)frame->f_regs[SP] + 4), - (void *)(args + nsaved), + (caddr_t)((int *)frame->f_regs[SP] + 4), + (caddr_t)(args + nsaved), (argsiz - nsaved) * sizeof(int)); if (error) goto bad; @@ -393,10 +621,9 @@ syscall(status, cause, opc) * no more FORK_BRAINDAMAGED. */ void -child_return(arg) - void *arg; +child_return(p) + struct proc *p; { - struct proc *p = arg; struct frame *frame = (struct frame *)p->p_md.md_regs; frame->f_regs[V0] = 0; @@ -423,20 +650,18 @@ child_return(arg) */ void trap(status, cause, vaddr, opc, frame) - unsigned status; - unsigned cause; - unsigned vaddr; - unsigned opc; - struct trapframe frame; + u_int status; + u_int cause; + u_int vaddr; + u_int opc; + struct frame frame; { int type, sig; int ucode = 0; u_quad_t sticks = 0; struct proc *p = curproc; vm_prot_t ftype; - extern struct proc *fpcurproc; extern void fswintrberr __P((void)); - extern int ddb_trap __P((int, int *)); #ifdef DEBUG trp->status = status; @@ -474,25 +699,22 @@ trap(status, cause, vaddr, opc, frame) printf(" in %s mode\n", USERMODE(status) ? "user" : "kernel"); printf("status=0x%x, cause=0x%x, pc=0x%x, v=0x%x\n", status, cause, opc, vaddr); - printf("usp=0x%x ksp=%p\n", (int)p->p_md.md_regs[SP], (int*)&frame); + printf("usp=0x%x ksp=%p\n", p->p_md.md_regs[SP], (int*)&frame); if (curproc != NULL) printf("pid=%d cmd=%s\n", p->p_pid, p->p_comm); else printf("curproc == NULL\n"); -#ifdef DDB - ddb_trap(-1, (int *)&frame); -#endif #ifdef DEBUG stacktrace(); trapDump("trap"); -#endif +#endif /* DEBUG */ panic("trap"); /*NOTREACHED*/ case T_TLB_MOD: if (KERNLAND(vaddr)) { pt_entry_t *pte; unsigned entry; - vaddr_t pa; + vm_offset_t pa; pte = kvtopte(vaddr); entry = pte->pt_entry; @@ -509,11 +731,13 @@ trap(status, cause, vaddr, opc, frame) vaddr &= ~PGOFSET; MachTLBUpdate(vaddr, entry); pa = pfn_to_vad(entry); - if (!IS_VM_PHYSADDR(pa)) { - printf("ktlbmod: va %x pa %lx\n", vaddr, pa); +#ifdef ATTR + pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD; +#else + if (!IS_VM_PHYSADDR(pa)) panic("ktlbmod: unmanaged page"); - } - pmap_set_modified(pa); + PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN; +#endif return; /* KERN */ } /*FALLTHROUGH*/ @@ -521,7 +745,7 @@ trap(status, cause, vaddr, opc, frame) { pt_entry_t *pte; unsigned entry; - vaddr_t pa; + vm_offset_t pa; pmap_t pmap; pmap = p->p_vmspace->vm_map.pmap; @@ -543,11 +767,13 @@ trap(status, cause, vaddr, opc, frame) (pmap->pm_tlbpid << MIPS_TLB_PID_SHIFT); MachTLBUpdate(vaddr, entry); pa = pfn_to_vad(entry); - if (!IS_VM_PHYSADDR(pa)) { - printf("utlbmod: va %x pa %lx\n", vaddr, pa); +#ifdef ATTR + pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD; +#else + if (!IS_VM_PHYSADDR(pa)) panic("utlbmod: unmanaged page"); - } - pmap_set_modified(pa); + PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN; +#endif if (type & T_USER) userret(p, opc, sticks); return; /* GEN */ @@ -561,11 +787,11 @@ trap(status, cause, vaddr, opc, frame) * It is an error for the kernel to access user space except * through the copyin/copyout routines. */ - if (p->p_addr->u_pcb.pcb_onfault == NULL) + if (curpcb->pcb_onfault == NULL) goto dopanic; /* check for fuswintr() or suswintr() getting a page fault */ - if (p->p_addr->u_pcb.pcb_onfault == (caddr_t)fswintrberr) { - frame.tf_epc = (int)fswintrberr; + if (curpcb->pcb_onfault == (caddr_t)fswintrberr) { + frame.f_regs[PC] = (int)fswintrberr; return; /* KERN */ } goto pagefault; @@ -576,14 +802,14 @@ trap(status, cause, vaddr, opc, frame) ftype = VM_PROT_WRITE; pagefault: ; { - vaddr_t va; + vm_offset_t va; struct vmspace *vm; vm_map_t map; int rv; vm = p->p_vmspace; map = &vm->vm_map; - va = trunc_page(vaddr); + va = trunc_page((vm_offset_t)vaddr); #if defined(UVM) rv = uvm_fault(map, va, 0, ftype); #ifdef VMFAULT_TRACE @@ -628,13 +854,13 @@ trap(status, cause, vaddr, opc, frame) sig = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; ucode = vaddr; break; /* SIGNAL */ - } + } kernelfault: ; { - vaddr_t va; + vm_offset_t va; int rv; - va = trunc_page(vaddr); + va = trunc_page((vm_offset_t)vaddr); #if defined(UVM) rv = uvm_fault(kernel_map, va, 0, ftype); #else @@ -648,9 +874,9 @@ trap(status, cause, vaddr, opc, frame) case T_ADDR_ERR_ST: /* misaligned access */ case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ copyfault: - if (p->p_addr->u_pcb.pcb_onfault == NULL) + if (curpcb->pcb_onfault == NULL) goto dopanic; - frame.tf_epc = (int)p->p_addr->u_pcb.pcb_onfault; + frame.f_regs[PC] = (int)curpcb->pcb_onfault; return; /* KERN */ case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */ @@ -663,7 +889,7 @@ trap(status, cause, vaddr, opc, frame) case T_BREAK: #ifdef DDB - ddb_trap(type, (int *)&frame); + kdb_trap(type, (struct frame *)&frame.f_regs); return; /* KERN */ #else goto dopanic; @@ -677,7 +903,7 @@ trap(status, cause, vaddr, opc, frame) va = (DELAYBRANCH(cause)) ? opc + sizeof(int) : opc; /* read break instruction */ - instr = fuiword((void *)va); + instr = fuiword((caddr_t)va); #ifdef DEBUG /*XXX*/ printf("break insn 0x%x\n", instr); #endif @@ -686,33 +912,34 @@ trap(status, cause, vaddr, opc, frame) sig = SIGTRAP; break; } - /* + /* * Restore original instruction and clear BP - */ + */ #ifndef NO_PROCFS_SUBR - rv = suiword((void *)va, p->p_md.md_ss_instr); + rv = suiword((caddr_t)va, p->p_md.md_ss_instr); if (rv < 0) { - vaddr_t sa, ea; - sa = trunc_page(va); - ea = round_page(va + sizeof(int) - 1); + vm_offset_t sa, ea; + sa = trunc_page((vm_offset_t)va); + ea = round_page((vm_offset_t)va + sizeof(int) - 1); #if defined(UVM) rv = uvm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_DEFAULT, FALSE); if (rv == KERN_SUCCESS) { - rv = suiword((void *)va, MIPS_BREAK_SSTEP); + rv = suiword((caddr_t)va, MIPS_BREAK_SSTEP); (void)uvm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE); + } } #else rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_DEFAULT, FALSE); if (rv == KERN_SUCCESS) { - rv = suiword((void *)va, MIPS_BREAK_SSTEP); + rv = suiword((caddr_t)va, MIPS_BREAK_SSTEP); (void)vm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE); + } } #endif /* UVM */ - } #else /* NO_PROCFS_SUBR */ { struct uio uio; @@ -737,7 +964,7 @@ trap(status, cause, vaddr, opc, frame) p->p_md.md_ss_addr = 0; sig = SIGTRAP; break; /* SIGNAL */ - } + } case T_RES_INST+T_USER: sig = SIGILL; break; /* SIGNAL */ @@ -745,7 +972,7 @@ trap(status, cause, vaddr, opc, frame) if ((cause & MIPS_CR_COP_ERR) != 0x10000000) { sig = SIGILL; /* only FPU instructions allowed */ break; /* SIGNAL */ - } + } switchfpregs(fpcurproc, p); fpcurproc = p; p->p_md.md_regs[SR] |= MIPS_SR_COP_1_BIT; @@ -759,7 +986,7 @@ trap(status, cause, vaddr, opc, frame) case T_OVFLOW+T_USER: sig = SIGFPE; break; /* SIGNAL */ - } + } p->p_md.md_regs[CAUSE] = cause; p->p_md.md_regs[BADVADDR] = vaddr; trapsignal(p, sig, ucode); @@ -797,22 +1024,24 @@ trap(status, cause, vaddr, opc, frame) /* * Handle an interrupt. - * N.B., curproc might be NULL. + * Called from MachKernIntr() or MachUserIntr() + * Note: curproc might be NULL. */ void -interrupt(status, cause, pc) - unsigned status; - unsigned cause; - unsigned pc; +interrupt(status, cause, pc, frame) + unsigned status, cause, pc; + struct frame *frame; { unsigned mask; extern u_int32_t mips3_cycle_count __P((void)); mask = cause & status; /* pending interrupts & enable mask */ -#if defined(MIPS3) && defined(MIPS_INT_MASK_CLOCK) - if ((mask & MIPS_INT_MASK_CLOCK) && CPUISMIPS3) +#if defined(MIPS3) && defined(MIPS3_INTERNAL_TIMER_INTERRUPT) + if (CPUISMIPS3 && (mask & MIPS_INT_MASK_5)) { mips3_intr_cycle_count = mips3_cycle_count(); + mips3_write_compare(mips3_intr_cycle_count + mips3_timer_delta); + } #endif #ifdef DEBUG @@ -832,63 +1061,60 @@ interrupt(status, cause, pc) #else cnt.v_intr++; #endif - /* real device interrupt */ - if ((mask & INT_MASK_REAL_DEV) && mips_hardware_intr) { + /* Device interrupt */ + if (mips_hardware_intr) splx((*mips_hardware_intr)(mask, pc, status, cause)); - } -#ifdef INT_MASK_FPU_DEAL - if (mask & INT_MASK_FPU_DEAL) { +#ifdef MIPS_INT_MASK_FPU + if (mask & MIPS_INT_MASK_FPU) { intrcnt[FPU_INTR]++; - if (!USERMODE(status)) - panic("kernel used FPU: PC %x, CR %x, SR %x", - pc, cause, status); - /* dealfpu(status, cause, pc); */ - MachFPInterrupt(status, cause, pc, curproc->p_md.md_regs); + if (USERMODE(status)) + MachFPInterrupt(status, cause, pc, frame->f_regs); + else { + printf("FPU interrupt: PC %x CR %x SR %x\n", + pc, cause, status); + } } -#endif +#endif /* MIPS_INT_MASK_FPU */ - /* simulated interrupt */ + /* Network software interrupt */ if ((mask & MIPS_SOFT_INT_MASK_1) - || ((netisr|softisr) && (status & MIPS_SOFT_INT_MASK_1))) { - register int isr, sisr; - isr = netisr; netisr = 0; - sisr = softisr; softisr = 0; + || (netisr && (status & MIPS_SOFT_INT_MASK_1))) { + int isr; + + isr = netisr; + netisr = 0; /* XXX need protect? */ clearsoftnet(); #if defined(UVM) uvmexp.softs++; #else cnt.v_soft++; #endif - if (isr) { - intrcnt[SOFTNET_INTR]++; + intrcnt[SOFTNET_INTR]++; #ifdef INET #if NARP > 0 - if (isr & (1 << NETISR_ARP)) arpintr(); + if (isr & (1 << NETISR_ARP)) arpintr(); #endif - if (isr & (1 << NETISR_IP)) ipintr(); + if (isr & (1 << NETISR_IP)) ipintr(); #endif #ifdef NETATALK - if (isr & (1 << NETISR_ATALK)) atintr(); + if (isr & (1 << NETISR_ATALK)) atintr(); #endif #ifdef NS - if (isr & (1 << NETISR_NS)) nsintr(); + if (isr & (1 << NETISR_NS)) nsintr(); #endif #ifdef ISO - if (isr & (1 << NETISR_ISO)) clnlintr(); + if (isr & (1 << NETISR_ISO)) clnlintr(); #endif #ifdef CCITT - if (isr & (1 << NETISR_CCITT)) ccittintr(); + if (isr & (1 << NETISR_CCITT)) ccittintr(); #endif #if NPPP > 0 - if (isr & (1 << NETISR_PPP)) pppintr(); + if (isr & (1 << NETISR_PPP)) pppintr(); #endif - } - if (sisr && mips_software_intr) - (*mips_software_intr)(sisr); } - /* 'softclock' interrupt */ + /* Software clock interrupt */ if (mask & MIPS_SOFT_INT_MASK_0) { clearsoftclock(); #if defined(UVM) @@ -925,71 +1151,6 @@ ast(pc) userret(p, pc, p->p_sticks); } -/* XXX XXX XXX */ -#define set_cp0sr(x) \ -{ \ - register int _r = (x); \ - __asm __volatile(" \ - .set noreorder ; \ - mtc0 %0, $12 ; \ - nop;nop;nop;nop ; \ - .set reorder" \ - : : "r"(_r)); \ -} - -#define get_fpcsr() \ -({ \ - register int _r; \ - __asm __volatile(" \ - .set noreorder ; \ - cfc1 %0, $31 ; \ - cfc1 %0, $31 ; \ - nop ; \ - .set reorder" \ - : "=r"(_r)); \ - _r; \ -}) - -#define clr_fpcsr() \ - __asm __volatile("ctc1 $0, $31") -/* XXX XXX XXX */ - -void -dealfpu(status, cause, opc) - unsigned status; - unsigned cause; - unsigned opc; -{ - struct frame *f = (struct frame *)curproc->p_md.md_regs; - unsigned v0; - - set_cp0sr(status | MIPS_SR_COP_1_BIT); - v0 = get_fpcsr(); - if ((int)(v0 << (31 - 17)) >= 0) /* ??? */ - goto unimplemented; - if (DELAYBRANCH(cause)) { - f->f_regs[PC] = MachEmulateBranch(f->f_regs, opc, v0, 0); - v0 = *(unsigned *)(opc + sizeof(unsigned)); - } - else { - f->f_regs[PC] = opc + sizeof(unsigned); - v0 = *(unsigned *)opc; - } - if (MIPS_OPCODE_C1 != (v0 >> MIPS_OPCODE_SHIFT)) - goto unimplemented; - - MachEmulateFP(v0); - set_cp0sr(status &~ MIPS_SR_COP_1_BIT); - return; - -unimplemented: - clr_fpcsr(); - f->f_regs[CAUSE] = cause; - f->f_regs[BADVADDR] = 0; - trapsignal(curproc, SIGFPE, v0); - set_cp0sr(status &~ MIPS_SR_COP_1_BIT); - return; -} #ifdef DEBUG void @@ -1017,7 +1178,7 @@ trapDump(msg) printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code); } #ifndef DDB - memset(trapdebug, 0, sizeof(trapdebug)); + bzero(trapdebug, sizeof(trapdebug)); trp = trapdebug; #endif splx(s); @@ -1045,19 +1206,19 @@ GetBranchDest(InstPtr) /* * Return the resulting PC as if the branch was executed. */ -mips_reg_t +unsigned MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch) - mips_reg_t *regsPtr; + unsigned *regsPtr; unsigned instPC; unsigned fpcCSR; int allowNonBranch; { InstFmt inst; - mips_reg_t retAddr; + unsigned retAddr; int condition; inst.word = (instPC < MIPS_KSEG0_START) ? - fuiword((void *)instPC) : *(unsigned*)instPC; + fuiword((caddr_t)instPC) : *(unsigned*)instPC; #if 0 printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC, @@ -1193,32 +1354,32 @@ mips_singlestep(p) struct proc *p; { #ifdef NO_PROCFS_SUBR - struct frame *f = (struct frame *)p->p_md.md_regs; - unsigned va = 0; - int rv; + struct frame *f = (struct frame *)p->p_md.md_regs; + unsigned va = 0; + int rv; - if (p->p_md.md_ss_addr) { + if (p->p_md.md_ss_addr) { printf("SS %s (%d): breakpoint already set at %x (va %x)\n", p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */ - return EFAULT; + return EFAULT; } - if (fuiword((void *)f->f_regs[PC]) != 0) /* not a NOP instruction */ - va = MachEmulateBranch(f->f_regs, f->f_regs[PC], - p->p_addr->u_pcb.pcb_fpregs.r_regs[32], 1); - else - va = f->f_regs[PC] + sizeof(int); + if (fuiword((caddr_t)f->f_regs[PC]) != 0) /* not a NOP instruction */ + va = MachEmulateBranch(f->f_regs, f->f_regs[PC], + p->p_addr->u_pcb.pcb_fpregs.r_regs[32], 1); + else + va = f->f_regs[PC] + sizeof(int); p->p_md.md_ss_addr = va; - p->p_md.md_ss_instr = fuiword((void *)va); - rv = suiword((void *)va, MIPS_BREAK_SSTEP); - if (rv < 0) { - vaddr_t sa, ea; - sa = trunc_page(va); - ea = round_page(va + sizeof(int) - 1); + p->p_md.md_ss_instr = fuiword((caddr_t)va); + rv = suiword((caddr_t)va, MIPS_BREAK_SSTEP); + if (rv < 0) { + vm_offset_t sa, ea; + sa = trunc_page((vm_offset_t)va); + ea = round_page((vm_offset_t)va + sizeof(int) - 1); #if defined(UVM) rv = uvm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_DEFAULT, FALSE); if (rv == KERN_SUCCESS) { - rv = suiword((void *)va, MIPS_BREAK_SSTEP); + rv = suiword((caddr_t)va, MIPS_BREAK_SSTEP); (void)uvm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE); } @@ -1226,54 +1387,54 @@ mips_singlestep(p) rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_DEFAULT, FALSE); if (rv == KERN_SUCCESS) { - rv = suiword((void *)va, MIPS_BREAK_SSTEP); + rv = suiword((caddr_t)va, MIPS_BREAK_SSTEP); (void)vm_map_protect(&p->p_vmspace->vm_map, sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE); } #endif /* UVM */ } #else - struct frame *f = (struct frame *)p->p_md.md_regs; - unsigned pc = f->f_regs[PC]; - unsigned va = 0; - int rv; - int curinstr, bpinstr = MIPS_BREAK_SSTEP; + struct frame *f = (struct frame *)p->p_md.md_regs; + unsigned pc = f->f_regs[PC]; + unsigned va = 0; + int rv; + int curinstr, bpinstr = MIPS_BREAK_SSTEP; struct uio uio; struct iovec iov; #define FETCH_INSTRUCTION(i, va) \ - iov.iov_base = (caddr_t)&(i);\ - iov.iov_len = sizeof(int); \ - uio.uio_iov = &iov;\ - uio.uio_iovcnt = 1;\ - uio.uio_offset = (off_t)(va);\ - uio.uio_resid = sizeof(int);\ - uio.uio_segflg = UIO_SYSSPACE;\ - uio.uio_rw = UIO_READ;\ - uio.uio_procp = curproc;\ - rv = procfs_domem(curproc, p, NULL, &uio) + iov.iov_base = (caddr_t)&(i);\ + iov.iov_len = sizeof(int); \ + uio.uio_iov = &iov;\ + uio.uio_iovcnt = 1;\ + uio.uio_offset = (off_t)(va);\ + uio.uio_resid = sizeof(int);\ + uio.uio_segflg = UIO_SYSSPACE;\ + uio.uio_rw = UIO_READ;\ + uio.uio_procp = curproc;\ + rv = procfs_domem(curproc, p, NULL, &uio) #define STORE_INSTRUCTION(i, va) \ - iov.iov_base = (caddr_t)&(i);\ - iov.iov_len = sizeof(int);\ - uio.uio_iov = &iov;\ - uio.uio_iovcnt = 1;\ - uio.uio_offset = (off_t)(va);\ - uio.uio_resid = sizeof(int);\ - uio.uio_segflg = UIO_SYSSPACE;\ - uio.uio_rw = UIO_WRITE;\ - uio.uio_procp = curproc;\ - rv = procfs_domem(curproc, p, NULL, &uio) + iov.iov_base = (caddr_t)&(i);\ + iov.iov_len = sizeof(int);\ + uio.uio_iov = &iov;\ + uio.uio_iovcnt = 1;\ + uio.uio_offset = (off_t)(va);\ + uio.uio_resid = sizeof(int);\ + uio.uio_segflg = UIO_SYSSPACE;\ + uio.uio_rw = UIO_WRITE;\ + uio.uio_procp = curproc;\ + rv = procfs_domem(curproc, p, NULL, &uio) - /* Fetch what's at the current location. */ - FETCH_INSTRUCTION(curinstr, va); + /* Fetch what's at the current location. */ + FETCH_INSTRUCTION(curinstr, va); /* compute next address after current location */ - if (curinstr != 0) - va = MachEmulateBranch(f->f_regs, pc, - p->p_addr->u_pcb.pcb_fpregs.r_regs[32], 1); - else - va = pc + sizeof(int); + if (curinstr != 0) + va = MachEmulateBranch(f->f_regs, pc, + p->p_addr->u_pcb.pcb_fpregs.r_regs[32], 1); + else + va = pc + sizeof(int); if (p->p_md.md_ss_addr) { printf("SS %s (%d): breakpoint already set at %x (va %x)\n", @@ -1282,32 +1443,28 @@ mips_singlestep(p) } p->p_md.md_ss_addr = va; - /* Fetch what's at the current location. */ - FETCH_INSTRUCTION(p->p_md.md_ss_instr, va); + /* Fetch what's at the current location. */ + FETCH_INSTRUCTION(p->p_md.md_ss_instr, va); - /* Store breakpoint instruction at the "next" location now. */ - STORE_INSTRUCTION(bpinstr, va); + /* Store breakpoint instruction at the "next" location now. */ + STORE_INSTRUCTION(bpinstr, va); MachFlushCache(); /* XXX memory barrier followed by flush icache? */ #endif - if (rv < 0) + if (rv < 0) return (EFAULT); #if 0 printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n", - printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n", + printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n", p->p_comm, p->p_pid, p->p_md.md_ss_addr, - p->p_md.md_ss_instr, pc, fuword((void *)va)); /* XXX */ + p->p_md.md_ss_instr, pc, fuword((caddr_t)va)); /* XXX */ #endif - return 0; + return 0; } #if defined(DEBUG) || defined(DDB) -extern void stacktrace __P((void)); /*XXX*/ -extern void logstacktrace __P((void)); /*XXX*/ - - int kdbpeek(addr) - vaddr_t addr; + vm_offset_t addr; { if (addr & 3) { printf("kdbpeek: unaligned address %lx\n", addr); @@ -1320,31 +1477,6 @@ kdbpeek(addr) #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ -/* marks start/end of code */ -extern char start[], edata[]; -extern char mips1_KernGenException[], mips1_KernGenExceptionEnd[]; -extern char mips1_UserGenException[], mips1_UserGenExceptionEnd[]; -extern char mips1_KernIntr[], mips1_KernIntrEnd[]; -extern char mips1_UserIntr[], mips1_UserIntrEnd[]; -extern char mips1_SystemCall[], mips1_SystemCallEnd[]; -extern char mips1_exceptionentry_start[], mips1_exceptionentry_end[]; -extern char mips3_KernGenException[], mips3_KernGenExceptionEnd[]; -extern char mips3_UserGenException[], mips3_UserGenExceptionEnd[]; -extern char mips3_KernIntr[], mips3_KernIntrEnd[]; -extern char mips3_UserIntr[], mips3_UserIntrEnd[]; -extern char mips3_SystemCall[], mips3_SystemCallEnd[]; -extern char mips3_exceptionentry_start[], mips3_exceptionentry_end[]; -extern int main __P((void*)); -extern void idle __P((void)); -extern void idle_end __P((void)); -extern void cpu_switch __P((struct proc *)); -extern void cpu_switch_end __P((void)); -extern void bcopy_end __P((void)); - -/* - * stack trace code, also useful to DDB one day - */ - /* forward */ char *fn_name(unsigned addr); void stacktrace_subr __P((int a0, int a1, int a2, int a3, @@ -1512,9 +1644,11 @@ specialframe: #endif /* MIPS3 */ - if (pcBetween(cpu_switch, cpu_switch_end)) + if (pcBetween(splx, splx_end)) + subr = (unsigned) splx; + else if (pcBetween(cpu_switch, cpu_switch_end)) subr = (unsigned) cpu_switch; - else if (pcBetween(idle, cpu_switch)) { + else if (pcBetween(idle, idle_end)) { subr = (unsigned) idle; ra = 0; goto done; @@ -1562,7 +1696,7 @@ stackscan: mask = 0; foundframesize = 0; for (va = subr; more; va += sizeof(int), - more = (more == 3) ? 3 : more - 1) { + more = (more == 3) ? 3 : more - 1) { /* stop if hit our current position */ if (va >= pc) break; @@ -1686,6 +1820,9 @@ static struct { void *addr; char *name;} Name(main), Name(interrupt), Name(trap), +#ifdef pmax + Name(am7990_meminit), +#endif #ifdef MIPS1 /* r2000 family (mips-I cpu) */ Name(mips1_KernGenException), @@ -1703,6 +1840,7 @@ static struct { void *addr; char *name;} Name(mips3_UserIntr), #endif /* MIPS3 */ + Name(splx), Name(idle), Name(cpu_switch), {0, 0} @@ -1738,3 +1876,97 @@ fn_name(unsigned addr) } #endif /* DEBUG */ + +#ifdef MIPS3 +/* + * Dump TLB contents on mips3 CPU. + * called by mips3 locore after in-kernel TLB miss. + */ +void +mips3_dump_tlb(first, last, printfn) + int first; + int last; + void (*printfn) __P((const char*, ...)); +{ + int tlbno; + struct tlb tlb; + extern void mips3_TLBRead(int, struct tlb *); + + tlbno = first; + + while(tlbno <= last) { + mips3_TLBRead(tlbno, &tlb); + if (mips_pg_v(tlb.tlb_lo0) || mips_pg_v(tlb.tlb_lo1)) { + (*printfn)("TLB %2d vad 0x%08x ", tlbno, tlb.tlb_hi); + } + else { + (*printfn)("TLB*%2d vad 0x%08x ", tlbno, tlb.tlb_hi); + } + (*printfn)("0=0x%08lx ", pfn_to_vad(tlb.tlb_lo0)); + (*printfn)("%c", tlb.tlb_lo0 & mips_pg_m_bit() ? 'M' : ' '); + (*printfn)("%c", tlb.tlb_lo0 & mips_pg_global_bit() ? 'G' : ' '); + (*printfn)(" atr %x ", (tlb.tlb_lo0 >> 3) & 7); + (*printfn)("1=0x%08lx ", pfn_to_vad(tlb.tlb_lo1)); + (*printfn)("%c", tlb.tlb_lo1 & mips_pg_m_bit() ? 'M' : ' '); + (*printfn)("%c", tlb.tlb_lo1 & mips_pg_global_bit() ? 'G' : ' '); + (*printfn)(" atr %x ", (tlb.tlb_lo1 >> 3) & 7); + (*printfn)(" sz=%x\n", tlb.tlb_mask); + + tlbno++; + } +} +#endif /* MIPS3 */ + +#ifdef MIPS1 +/* + * Dump mips1 TLB contents. + * called by mips3 locore after in-kernel TLB miss. + */ +void +mips1_dump_tlb(first, last, printfn) + int first; + int last; + void (*printfn) __P((const char*, ...)); +{ + int tlbno; + extern u_int tlbhi, tlblo; + extern void mips1_TLBRead(int); + + tlbno = first; + + while(tlbno <= last) { + mips1_TLBRead(tlbno); + if (mips_pg_v(tlblo)) { + (*printfn)("TLB %2d vad 0x%08x ", tlbno, tlbhi); + } + else { + (*printfn)("TLB*%2d vad 0x%08x ", tlbno, tlbhi); + } + (*printfn)("0x%08x ", tlblo & MIPS1_PG_FRAME); + (*printfn)("%c", tlblo & mips_pg_m_bit() ? 'M' : ' '); + (*printfn)("%c", tlblo & mips_pg_global_bit() ? 'G' : ' '); + (*printfn)("%c\n", tlblo & MIPS1_PG_N ? 'N' : ' '); + + tlbno++; + } +} +#endif /* MIPS1 */ + +/* + * Dump TLB after panic. + */ +void +mips_dump_tlb(first, last) + int first; + int last; +{ + if (CPUISMIPS3) { +#ifdef MIPS3 + mips3_dump_tlb(first,last, printf); +#endif + } else { +#ifdef MIPS1 + mips1_dump_tlb(first,last, printf); +#endif + } +}