Date: Mon, 10 Jul 2006 11:44:23 GMT From: Oleksandr Tymoshenko <gonzo@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 101196 for review Message-ID: <200607101144.k6ABiN1H058617@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=101196 Change 101196 by gonzo@gonzo_hq on 2006/07/10 11:44:05 o genassym.s extended with registers offsets in frame struct, VM params etc.. o exception handling added. o fls(3) implementation has been added from libkern. Affected files ... .. //depot/projects/mips2/src/sys/conf/files.mips#11 edit .. //depot/projects/mips2/src/sys/mips/mips/cpu.c#7 edit .. //depot/projects/mips2/src/sys/mips/mips/exception.S#2 edit .. //depot/projects/mips2/src/sys/mips/mips/genassym.c#2 edit .. //depot/projects/mips2/src/sys/mips/mips/intr_machdep.c#2 edit .. //depot/projects/mips2/src/sys/mips/mips/trap.c#3 edit Differences ... ==== //depot/projects/mips2/src/sys/conf/files.mips#11 (text+ko) ==== @@ -33,6 +33,7 @@ libkern/divdi3.c standard libkern/ffs.c standard libkern/ffsl.c standard +libkern/fls.c standard libkern/flsl.c standard libkern/lshrdi3.c standard libkern/moddi3.c standard ==== //depot/projects/mips2/src/sys/mips/mips/cpu.c#7 (text+ko) ==== @@ -92,7 +92,7 @@ * XXMIPS: This makes cooperation with exception handler more handy. Less hand-typing * is needed. Take a look at mips_vector_init() in this file to see a usage. */ -#define VECI(vec, class) mips_vector_install(MIPS_ ## vec ## _EXC_VEC, \ +#define VECI(vec, class) mips_vector_install(vec ## _EXC_VEC, \ class ## Vector, \ class ## VectorEnd) /* @@ -124,10 +124,10 @@ mips_vector_init(void) { - VECI(UTLB_MISS, TLBMiss); - VECI(XTLB_MISS, XTLBMiss); - VECI(CACHE_ERR, Cache); - VECI(GEN, Exception); + VECI(MIPS_UTLB_MISS, TLBMiss); + VECI(MIPS3_XTLB_MISS, XTLBMiss); + VECI(MIPS3_CACHE_ERR, Cache); + VECI(MIPS3_GEN, Exception); mips_wr_status(mips_rd_status() & ~MIPS_SR_BEV); } ==== //depot/projects/mips2/src/sys/mips/mips/exception.S#2 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) [year] [your name] + * Copyright (c) 2003-2004 Juli Mallett <jmallett@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,19 +23,468 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $P4: //depot/projects/mips2/src/sys/mips/mips/exception.S#2 $ */ + +#include "opt_ddb.h" + +#include <machine/asm.h> +#include <machine/cache_r4k.h> +#include <machine/cpuregs.h> +#include <machine/param.h> +#include <machine/pte.h> + #include "assym.s" -#include <machine/asm.h> -#include <machine/asmacros.h> -__FBSDID("$FreeBSD$"); +/* + * Mark the end of a vector. + */ +#define _VEND(x) \ + GLOBAL(x ## End); \ + END(x); + +#define VEND(x) \ + _VEND(x) + +ExceptionHandlerTable: + .dword GenericException /* Int */ + .dword GenericException /* TLBMod */ + .dword TLBMissVector /* TLBL */ + .dword TLBMissVector /* TLBS */ + .dword GenericException /* AdEL */ + .dword GenericException /* AdES */ + .dword GenericException /* IBE */ + .dword GenericException /* DBE */ + .dword GenericException /* Sys */ + .dword GenericException /* Bp */ + .dword GenericException /* RI */ + .dword GenericException /* CpU */ + .dword GenericException /* Ov */ + .dword GenericException /* Tr */ + .dword GenericException /* VCEI */ + .dword GenericException /* FPE */ + .dword GenericException /* Res (16) */ + .dword GenericException /* Res (17) */ + .dword GenericException /* Res (18) */ + .dword GenericException /* Res (19) */ + .dword GenericException /* Res (20) */ + .dword GenericException /* Res (21) */ + .dword GenericException /* Res (22) */ + .dword GenericException /* WATCH */ + .dword GenericException /* Res (24) */ + .dword GenericException /* Res (25) */ + .dword GenericException /* Res (26) */ + .dword GenericException /* Res (27) */ + .dword GenericException /* Res (28) */ + .dword GenericException /* Res (29) */ + .dword GenericException /* Res (30) */ + .dword VCED /* VCED */ + + .text + .set noreorder + +/* + * Exception vector bodies, essentially here to save registers, jump + * to C, restore registers, and return from exception. Some may do + * some fast servicing, where it makes sense to, but in general they + * are meant to be foolproof. Some may jump to assembly herein, not + * to external C routines. + */ +LEAF(ExceptionVector) + .set noat + + mfc0 k0, MIPS_COP_0_CAUSE + and k0, MIPS3_CR_EXC_CODE + srl k0, MIPS_CR_EXC_CODE_SHIFT + sll k0, 3 /* Index 64-bits. */ + la k1, ExceptionHandlerTable + addu k1, k0 + lw k1, 0(k1) + jr k1 + nop + + .set at +VEND(ExceptionVector) + .data +1: .asciiz "ExceptionHandlerTable" + .text + +LEAF(GenericException) + .set noat + + subu sp, sp, TF_SIZE + la k0, 1f + j exception_save_registers + move k1, sp +1: + + /* + * A generic exception may result in DDB being invoked. If we + * are using the kernel debugger, then set up is auxillary + * frame, so it has a full one. + */ +#if DDB + jal save_kdbaux + nop +#endif /* DDB */ + li t0, MIPS_SR_KX + mtc0 t0, MIPS_COP_0_STATUS + + /* + * If this is an interrupt, call cpu_intr() with the arguments: + * trapframe + * + * Otherwise, go to trap(). Trapframe is set to a0 from k1 in the + * BDslot here. + */ + + mfc0 a1, MIPS_COP_0_CAUSE + and k0, a1, MIPS3_CR_EXC_CODE + bnez k0, 1f + move a0, k1 + + jal cpu_intr + nop + + b 2f + nop + + /* + * Call trap() with arguments: + * trapframe, cause, badvaddr. + * + * The trapframe is copied from k1 to a0 in the BDslot above. + * Cause is set up above when computing the code. + */ +1: + mfc0 a1, MIPS_COP_0_CAUSE + mfc0 a2, MIPS_COP_0_BAD_VADDR + + jal trap + nop +2: + + /* + * Make sure interrupts are disabled for the purposes of + * having a clean go at restoring. + */ + mtc0 zero, MIPS_COP_0_CAUSE + li t0, MIPS_SR_KX + mtc0 t0, MIPS_COP_0_STATUS + + move k1, sp + jal exception_restore_registers + nop + + addu sp, sp, TF_SIZE + eret + + .set at +END(GenericException) + .data +3: .asciiz "GenericException" + .text + + +LEAF(CacheVector) + .set noat + la k0, panic + mtc0 k0, MIPS_COP_0_EXC_PC + la a0, 1f + eret + .set at +VEND(CacheVector) + .data +1: .asciiz "Cache Vector" + .text + + +/* + * XXX kernel only. For now that makes sense. + */ +LEAF(TLBMissVector) + .set noat + + mfc0 k0, MIPS_COP_0_BAD_VADDR + /* + * Shift right logical to get a page index, but leaving + * enough bits to index an array of 64 bit values, plus + * align for the even/odd TLB stuff. + */ + + /* VPN2 = (VA >> page_shift) / 2 */ + la k1, VM_MIN_ADDRESS + subu k0, k0, k1 + srl k0, PAGE_SHIFT + 1 + sll k0, 2 + 1 + la k1, kptmap + + + /* + * Find the page table, and index it. + */ + lw k1, 0(k1) + addu k1, k0 + /* + * Write the pair. + */ + lw k0, 0(k1) /* Even PTE. */ + lw k1, 4(k1) /* Odd PTE. */ + /* + * Write TLB entry. + */ + mtc0 k0, MIPS_COP_0_TLB_LO0 + mtc0 k1, MIPS_COP_0_TLB_LO1 + nop + + tlbp + + mfc0 k0, MIPS_COP_0_TLB_INDEX + nop + bltz k0, 1f + nop + + tlbwi + + eret +1: + + tlbwr + eret + + .set at +VEND(TLBMissVector) + .data +2: .asciiz "TLBMissVector" + .text + + + +LEAF(XTLBMissVector) + .set noat + la k0, panic + mtc0 k0, MIPS_COP_0_EXC_PC + la a0, 1f + eret + .set at +VEND(XTLBMissVector) + .data +1: .asciiz "64-bit TLB Miss Vector" + .text + + +LEAF(VCED) + .set noat + la k0, panic + mtc0 k0, MIPS_COP_0_EXC_PC + la a0, 1f + eret + .set at +VEND(VCED) + .data +1: .asciiz "VCED" + .text + +/* + * Handle a data-cache virtual coherency error. + */ +LEAF(VCEDX) + .set noat + mfc0 k0, MIPS_COP_0_BAD_VADDR + srl k0, 3 + sll k0, 3 + cache (CACHE_R4K_SD | CACHEOP_R4K_HIT_WB_INV), 0(k0) + cache (CACHE_R4K_D | CACHEOP_R4K_HIT_INV), 0(k0) + eret + .set at +END(VCEDX) + + +/* + * Restore registers from a trapframe pointed to in k1, returning to ra + * that is passed in, and kept in k0. + */ +LEAF(exception_restore_registers) + move k0, ra + /* + * Load extended registers into some GPRs, and start unrolling + * the trapframe, putting back the extended registers just + * before we need to restore those GPRs. This doesn't do any + * special ordering like the save_registers routine might, + * but it keeps the flow relatively consistent. + */ + + + lw a1, TF_REG_EPC(k1) + lw a0, TF_REG_MULHI(k1) + lw v1, TF_REG_MULLO(k1) +#if 0 + lw v0, TF_REG_SR(k1) +#endif + + lw ra, TF_REG_RA(k1) + lw t9, TF_REG_T9(k1) + lw t8, TF_REG_T8(k1) + lw ta3, TF_REG_TA3(k1) + lw ta2, TF_REG_TA2(k1) + lw ta1, TF_REG_TA1(k1) + lw ta0, TF_REG_TA0(k1) + lw t3, TF_REG_T3(k1) + lw t2, TF_REG_T2(k1) + lw t1, TF_REG_T1(k1) + lw t0, TF_REG_T0(k1) + + /* + * Brief interlude. + */ + mtc0 a1, MIPS_COP_0_EXC_PC + mthi a0 + mtlo v1 +#if 0 + mtc0 v0, MIPS_COP_0_STATUS +#endif + + + + /* + * Now restore the registers we used for scratch, and nearby + * GPRs. + */ + lw a3, TF_REG_A3(k1) + lw a2, TF_REG_A2(k1) + lw a1, TF_REG_A1(k1) + lw a0, TF_REG_A0(k1) + lw v1, TF_REG_V1(k1) + lw v0, TF_REG_V0(k1) + + + + /* + * Restore the stack minus TF_SIZE, to account for sp twiddle. + */ + lw sp, TF_REG_SP(k1) + subu sp, TF_SIZE + + + /* + * We are done with the assembler temporary, restore it, and + * return with it disabled, just in case. + */ + .set noat + lw AT, TF_REG_AST(k1) +#if 1 + /* XXX + * We wait until now so we don't interrupt ourselves. + */ + lw k1, TF_REG_SR(k1) + jr k0 + mtc0 k1, MIPS_COP_0_STATUS +#else + jr k0 + nop +#endif + + .set at +END(exception_restore_registers) + +/* + * Save registers into a trapframe pointed to in k1, returning to k0. + */ +LEAF(exception_save_registers) + /* + * Store the assembler temporary, and make it usable. + */ + .set noat + sw AT, TF_REG_AST(k1) + .set at + /* + * Store registers in order, clobbering the first with values + * we need to have around later, and then storing those at the + * end of the sequence, to avoid any possible issues with the + * time it takes to load from those. + */ + sw v0, TF_REG_V0(k1) + sw v1, TF_REG_V1(k1) + sw a0, TF_REG_A0(k1) + sw a1, TF_REG_A1(k1) + sw a2, TF_REG_A2(k1) + sw a3, TF_REG_A3(k1) + + + + + /* + * Brief interlude. + */ + mfc0 v0, MIPS_COP_0_STATUS + mflo v1 + mfhi a0 + mfc0 a1, MIPS_COP_0_EXC_PC + + sw t0, TF_REG_T0(k1) + sw t1, TF_REG_T1(k1) + sw t2, TF_REG_T2(k1) + sw t3, TF_REG_T3(k1) + sw ta0, TF_REG_TA0(k1) + sw ta1, TF_REG_TA1(k1) + sw ta2, TF_REG_TA2(k1) + sw ta3, TF_REG_TA3(k1) + sw t8, TF_REG_T8(k1) + sw t9, TF_REG_T9(k1) + sw ra, TF_REG_RA(k1) + + /* + * Now save the extended parts of the frame. + */ + sw v0, TF_REG_SR(k1) + sw v1, TF_REG_MULLO(k1) + sw a0, TF_REG_MULHI(k1) + sw a1, TF_REG_EPC(k1) + + /* + * When restore returns, TF_SIZE gets added to the SP for + * return. So in restore, we subtract TF_SIZE, which means + * the value stored herein will be the value returned to. + * To accomodate this, we add TF_SIZE, which makes up for the + * initial subtraction for the trapframe. + */ + addu t0, sp, TF_SIZE + sw t0, TF_REG_SP(k1) + + -ENTRY(reset_entry) -ENTRY(swi_entry) -ENTRY(prefetch_abort_entry) -ENTRY(data_abort_entry) -ENTRY(address_exception_entry) -ENTRY(undefined_entry) -ENTRY(undefinedinstruction_bounce) + /* + * All done. + */ + jr k0 + nop +END(exception_save_registers) + +#if DDB +/* + * Save the kdbaux structure for DDB. + */ +ENTRY(save_kdbaux) + /* + * If we are using the kernel debugger, store registers that + * the compiler normally saves in the place where it expects + * to find them, to form a full frame. + */ + la k0, kdbaux + sw s0, 0x00(k0) + sw s1, 0x08(k0) + sw s2, 0x10(k0) + sw s3, 0x18(k0) + sw s4, 0x20(k0) + sw s5, 0x28(k0) + sw s6, 0x30(k0) + sw s7, 0x38(k0) + sw sp, 0x40(k0) + sw s8, 0x48(k0) + sw gp, 0x50(k0) + + jr ra + nop +END(save_kdbaux) +#endif /* DDB */ ==== //depot/projects/mips2/src/sys/mips/mips/genassym.c#2 (text+ko) ==== @@ -64,4 +64,114 @@ #include <nfsclient/nfs.h> #include <nfsclient/nfsdiskless.h> +#include <machine/locore.h> +#include <machine/pcb.h> +#include <machine/reg.h> + ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace)); +ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); +ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb)); +ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid)); + +ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); +ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); + +ASSYM(TD_FLAGS, offsetof(struct thread, td_flags)); + +ASSYM(TD_FRAME, offsetof(struct thread, td_frame)); +ASSYM(TD_KSTACK, offsetof(struct thread, td_kstack)); +ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); +ASSYM(TD_PROC, offsetof(struct thread, td_proc)); + +ASSYM(TD_MD_REGS, offsetof(struct thread, td_md.md_regs)); + +ASSYM(FRAME_SIZ, sizeof(struct frame)); +ASSYM(FRAME_ZERO, offsetof(struct frame, f_regs[ZERO])); +ASSYM(FRAME_AST, offsetof(struct frame, f_regs[AST])); +ASSYM(FRAME_V0, offsetof(struct frame, f_regs[V0])); +ASSYM(FRAME_V1, offsetof(struct frame, f_regs[V1])); +ASSYM(FRAME_A0, offsetof(struct frame, f_regs[A0])); +ASSYM(FRAME_A1, offsetof(struct frame, f_regs[A1])); +ASSYM(FRAME_A2, offsetof(struct frame, f_regs[A2])); +ASSYM(FRAME_A3, offsetof(struct frame, f_regs[A3])); +ASSYM(FRAME_T0, offsetof(struct frame, f_regs[T0])); +ASSYM(FRAME_T1, offsetof(struct frame, f_regs[T1])); +ASSYM(FRAME_T2, offsetof(struct frame, f_regs[T2])); +ASSYM(FRAME_T3, offsetof(struct frame, f_regs[T3])); + +ASSYM(FRAME_TA0, offsetof(struct frame, f_regs[TA0])); +ASSYM(FRAME_TA1, offsetof(struct frame, f_regs[TA1])); +ASSYM(FRAME_TA2, offsetof(struct frame, f_regs[TA2])); +ASSYM(FRAME_TA3, offsetof(struct frame, f_regs[TA3])); + +ASSYM(FRAME_S0, offsetof(struct frame, f_regs[S0])); +ASSYM(FRAME_S1, offsetof(struct frame, f_regs[S1])); +ASSYM(FRAME_S2, offsetof(struct frame, f_regs[S2])); +ASSYM(FRAME_S3, offsetof(struct frame, f_regs[S3])); +ASSYM(FRAME_S4, offsetof(struct frame, f_regs[S4])); +ASSYM(FRAME_S5, offsetof(struct frame, f_regs[S5])); +ASSYM(FRAME_S6, offsetof(struct frame, f_regs[S6])); +ASSYM(FRAME_S7, offsetof(struct frame, f_regs[S7])); +ASSYM(FRAME_T8, offsetof(struct frame, f_regs[T8])); +ASSYM(FRAME_T9, offsetof(struct frame, f_regs[T9])); +ASSYM(FRAME_K0, offsetof(struct frame, f_regs[K0])); +ASSYM(FRAME_K1, offsetof(struct frame, f_regs[K1])); +ASSYM(FRAME_GP, offsetof(struct frame, f_regs[GP])); +ASSYM(FRAME_SP, offsetof(struct frame, f_regs[SP])); +ASSYM(FRAME_S8, offsetof(struct frame, f_regs[S8])); +ASSYM(FRAME_RA, offsetof(struct frame, f_regs[RA])); +ASSYM(FRAME_SR, offsetof(struct frame, f_regs[SR])); +ASSYM(FRAME_MULLO, offsetof(struct frame, f_regs[MULLO])); +ASSYM(FRAME_MULHI, offsetof(struct frame, f_regs[MULHI])); +ASSYM(FRAME_BADVADDR, offsetof(struct frame, f_regs[BADVADDR])); +ASSYM(FRAME_CAUSE, offsetof(struct frame, f_regs[CAUSE])); +ASSYM(FRAME_EPC, offsetof(struct frame, f_regs[PC])); +ASSYM(FRAME_PPL, offsetof(struct frame, f_ppl)); + +ASSYM(TF_SIZE, sizeof(struct trapframe)); +ASSYM(TF_REG_AST, offsetof(struct trapframe, tf_regs[TF_AST])); +ASSYM(TF_REG_V0, offsetof(struct trapframe, tf_regs[TF_V0])); +ASSYM(TF_REG_V1, offsetof(struct trapframe, tf_regs[TF_V1])); +ASSYM(TF_REG_A0, offsetof(struct trapframe, tf_regs[TF_A0])); +ASSYM(TF_REG_A1, offsetof(struct trapframe, tf_regs[TF_A1])); +ASSYM(TF_REG_A2, offsetof(struct trapframe, tf_regs[TF_A2])); +ASSYM(TF_REG_A3, offsetof(struct trapframe, tf_regs[TF_A3])); +ASSYM(TF_REG_T0, offsetof(struct trapframe, tf_regs[TF_T0])); +ASSYM(TF_REG_T1, offsetof(struct trapframe, tf_regs[TF_T1])); +ASSYM(TF_REG_T2, offsetof(struct trapframe, tf_regs[TF_T2])); +ASSYM(TF_REG_T3, offsetof(struct trapframe, tf_regs[TF_T3])); + +ASSYM(TF_REG_TA0, offsetof(struct trapframe, tf_regs[TF_TA0])); +ASSYM(TF_REG_TA1, offsetof(struct trapframe, tf_regs[TF_TA1])); +ASSYM(TF_REG_TA2, offsetof(struct trapframe, tf_regs[TF_TA2])); +ASSYM(TF_REG_TA3, offsetof(struct trapframe, tf_regs[TF_TA3])); + +ASSYM(TF_REG_T8, offsetof(struct trapframe, tf_regs[TF_T8])); +ASSYM(TF_REG_T9, offsetof(struct trapframe, tf_regs[TF_T9])); +ASSYM(TF_REG_RA, offsetof(struct trapframe, tf_regs[TF_RA])); +ASSYM(TF_REG_SR, offsetof(struct trapframe, tf_regs[TF_SR])); +ASSYM(TF_REG_MULLO, offsetof(struct trapframe, tf_regs[TF_MULLO])); +ASSYM(TF_REG_MULHI, offsetof(struct trapframe, tf_regs[TF_MULHI])); +ASSYM(TF_REG_EPC, offsetof(struct trapframe, tf_regs[TF_EPC])); +ASSYM(TF_REG_SP, offsetof(struct trapframe, tf_regs[TF_SP])); +ASSYM(TF_PPL, offsetof(struct trapframe, tf_ppl)); + +ASSYM(PCB_REG_S0, offsetof(struct pcb, pcb_regs[PCB_REG_S0])); +ASSYM(PCB_REG_S1, offsetof(struct pcb, pcb_regs[PCB_REG_S1])); +ASSYM(PCB_REG_S2, offsetof(struct pcb, pcb_regs[PCB_REG_S2])); +ASSYM(PCB_REG_S3, offsetof(struct pcb, pcb_regs[PCB_REG_S3])); +ASSYM(PCB_REG_S4, offsetof(struct pcb, pcb_regs[PCB_REG_S4])); +ASSYM(PCB_REG_S5, offsetof(struct pcb, pcb_regs[PCB_REG_S5])); +ASSYM(PCB_REG_S6, offsetof(struct pcb, pcb_regs[PCB_REG_S6])); +ASSYM(PCB_REG_S7, offsetof(struct pcb, pcb_regs[PCB_REG_S7])); +ASSYM(PCB_REG_S8, offsetof(struct pcb, pcb_regs[PCB_REG_S8])); +ASSYM(PCB_REG_SP, offsetof(struct pcb, pcb_regs[PCB_REG_SP])); +ASSYM(PCB_REG_SR, offsetof(struct pcb, pcb_regs[PCB_REG_SR])); +ASSYM(PCB_REG_RA, offsetof(struct pcb, pcb_regs[PCB_REG_RA])); + +ASSYM(VM_MIN_ADDRESS, VM_MIN_ADDRESS); +ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS); +ASSYM(VM_MAX_ADDRESS, VM_MAX_ADDRESS); +ASSYM(VM_MIN_KERNEL_ADDRESS, VM_MIN_KERNEL_ADDRESS); +ASSYM(VM_MAX_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS); + ==== //depot/projects/mips2/src/sys/mips/mips/intr_machdep.c#2 (text+ko) ==== @@ -1,5 +1,6 @@ /*- * Copyright (c) 2006 Fill this file and put your name here + * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,3 +28,102 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#include <machine/cpuinfo.h> +#include <machine/cpuregs.h> +#include <machine/frame.h> +#include <machine/intr_machdep.h> +#include <machine/md_var.h> +#include <machine/trap.h> + +struct intrhand { + void (*handler)(void *); + void *arg; +}; +static struct intrhand intrhard[6]; +static struct intrhand intrsoft[2]; + +void +cpu_establish_hardintr(int intr, void (*handler)(void *), void *arg) +{ + struct intrhand *ih; + + if (intr < 0 || intr > 5) + panic("%s called for unknown hard intr %d", __func__, intr); + ih = &intrhard[intr]; + if (ih->handler != NULL && ih->handler != handler) + panic("%s cannot share hard intr %d", __func__, intr); + ih->handler = handler; + ih->arg = arg; + + mips_wr_status(mips_rd_status() | (((1<< intr) << 8) << 2)); +} + +void +cpu_establish_softintr(int intr, void (*handler)(void *), void *arg) +{ + struct intrhand *ih; + + if (intr < 0 || intr > 1) + panic("%s called for unknown soft intr %d", __func__, intr); + ih = &intrsoft[intr]; + if (ih->handler != NULL && ih->handler != handler) + panic("%s cannot share soft intr %d", __func__, intr); + ih->handler = handler; + ih->arg = arg; + + mips_wr_status(mips_rd_status() | ((1 << intr) << 8)); +} + +void +cpu_intr(struct trapframe *tf) +{ + struct intrhand *ih; + register_t cause; + int hard; + int intr; + int i; + + critical_enter(); + + cause = mips_rd_cause(); + intr = (cause & MIPS_INT_MASK) >> 8; + cause &= ~MIPS_INT_MASK; + mips_wr_cause(cause); + + while ((i = fls(intr)) != 0) { + intr &= ~(1 << (i - 1)); + switch (i) { + case 1: case 2: + /* Software interrupt. */ + i--; /* Get a 0-offset interrupt. */ + hard = 0; + ih = &intrsoft[i]; + break; + default: + /* Hardware interrupt. */ + i -= 2; /* Trim software interrupt bits. */ + i--; /* Get a 0-offset interrupt. */ + hard = 1; + ih = &intrhard[i]; + break; + } + if (ih->handler != NULL) { + if (ih->arg == NULL) + (*ih->handler)(tf); + else + (*ih->handler)(ih->arg); + } else + printf("stray %s interrupt %d\n", + hard ? "hard" : "soft", i); + } + KASSERT(i == 0, ("all interrupts handled")); + + critical_exit(); +} ==== //depot/projects/mips2/src/sys/mips/mips/trap.c#3 (text+ko) ==== @@ -107,7 +107,7 @@ tf = retf; bcopy(retf, tf, sizeof *tf); - code = (cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT; + code = (cause & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT; kernelmode = (tf->tf_regs[TF_SR] & MIPS_SR_KSU_USER) == 0; /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607101144.k6ABiN1H058617>