📄 machdep.c
字号:
/* $Id: machdep.c,v 1.14 2003/08/10 11:15:24 pefo Exp $ *//* * Copyright (c) 2000 Opsycon AB (http://www.opsycon.se) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by * Opsycon Open System Consulting AB, Sweden. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *//* * Pmon architecture dependent (and possibly cpu type dependent) code. */#include <stdio.h>#include <termio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <errno.h>#ifdef _KERNEL#undef _KERNEL#include <sys/ioctl.h>#define _KERNEL#else#include <sys/ioctl.h>#endif#include <machine/cpu.h>#include <machine/pte.h>#include <machine/frame.h>#include <machine/regnum.h>#include <machine/trap.h>#include <pmon.h>extern int errno;extern u_int8_t end[];extern void CPU_GetTLB(int, struct tlbdata *);/* * CPU type markers. */#define CPU_ALL 0x0003 /* Belongs to mask */#define CPU_7 0x0001 /* RM7000 */#define CPU_5 0x0002 /* R5000 */#define CPU_41 0x0004 /* R4100 */#define F_FMT 0x1000 /* Field uses format */struct RegMap { char width; char bit; short flags; const char * const name; union { const char * const fmt;/* XXX Tell me why i must cast initializers for the next union? */ const char * const *vn; } fe;};int md_tlb(int, char **);static void dsp_rregs __P((int *));static void dsp_fregs __P((int *));static int cputype;/* * Special trap handlers. */register_t on_bus_error;register_t on_acc_error;u_int64_t on_acc_data;/* * Return a ascii version of the processor type. */const char *md_cpuname(){/* XXX make more sophisticated dealing with rev numbers and 52x0 more precisely */ /* Handle the SandCraft SR71000 */ if (((md_cputype() >> 8) & 0xffff) == 0x0504) { cputype = CPU_7; return ("SR71000"); } /* Handle the BCM2150 */ if (((md_cputype() >> 8) & 0xffff) == 0x0401) { cputype = CPU_7; return ("BCM1250"); } switch((md_cputype() >> 8) & 0xff) { case MIPS_E9000: cputype = CPU_7; return("E9000"); case MIPS_RM7000: cputype = CPU_7; return("RM7000"); case MIPS_RM52X0: cputype = CPU_5; return("RM52x0"); default: return("unidentified"); }}/* * Check for any special exception handling. */intmd_check_exception_handler(struct trapframe *frame){ switch((frame->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT) { case T_BUS_ERR_LD_ST: if (on_bus_error != 0) { md_setpc(frame, on_bus_error); on_bus_error = 0; return 1; } case T_TLB_LD_MISS: case T_ADDR_ERR_LD: case T_ADDR_ERR_ST: if (on_acc_error != 0) { md_setpc(frame, on_acc_error); on_acc_error = 0; return 1; } break; default: break; } return 0;}/* * Dump out exception info for an unscheduled exception */voidmd_dumpexc(struct trapframe *tf){ int w = 100; printf("\r\nException Cause=%s, SR=%p, PC=%p\r\n", md_getexcname(tf), (int)md_getsr(tf), md_getpc(tf)); printf("CONTEXT=%llp, XCONTEXT=%llp\r\n", tf->context, tf->xcontext); printf("BADVADDR=%llp, ENTHI=%llp\r\n", tf->badvaddr, tf->enthi); printf("ENTLO0=%llp, ENTLO1=%llp\r\n\r\n", tf->entlo0, tf->entlo1); dsp_rregs(&w); printf("\r\n"); md_do_stacktrace(0, 0, 0, 0);}/* * Set PC to a new value. */voidmd_setpc(struct trapframe *tf, register_t pc){ if (tf == NULL) tf = cpuinfotab[whatcpu]; tf->pc = pc;}/* * This function clears all client registers for launch. */voidmd_clreg(struct trapframe *tf){ if (tf == NULL) tf = cpuinfotab[whatcpu]; md_fpsave(tf);}/* * This function sets the client stack pointer. */voidmd_setsp(struct trapframe *tf, register_t sp){ if (tf == NULL) tf = cpuinfotab[whatcpu]; tf->sp = sp;}/* * This function sets the client sr to the given value. */voidmd_setsr(struct trapframe *tf, register_t sr){ if (tf == NULL) tf = cpuinfotab[whatcpu]; tf->sr = sr;}/* * This function returns the value of the clients sr. */register_tmd_getsr(struct trapframe *tf){ if (tf == NULL) tf = cpuinfotab[whatcpu]; return(tf->sr);}/* * This function sets the client sr to do a trace. */voidmd_settrace(){}/* * This function sets the client sr to do a trace. */voidmd_setlr(struct trapframe *tf, register_t lr){ if (tf == NULL) tf = cpuinfotab[whatcpu]; tf->ra = lr;}/* * This function returns true if the address range given is * invalid for load, eg will overwrite PMON or its working * areas or other protected memory areas or load into * existing memory. */intmd_valid_load_addr(first_addr, last_addr) paddr_t first_addr; paddr_t last_addr;{/* XXX This needs to be reworked!!! */#if 0 first_addr = CACHED_TO_PHYS(first_addr); last_addr = CACHED_TO_PHYS(last_addr); if((first_addr < (paddr_t)CACHED_TO_PHYS(end)) || (last_addr > (paddr_t)memtop)) { return(1); }#endif return(0);} /* * This function sets the SP to the new value given if it's * non zero. The old value of sp is returned. */register_tmd_adjstack(struct trapframe *tf, register_t newsp){ register_t oldsp; if (tf == NULL) tf = cpuinfotab[whatcpu]; oldsp = tf->sp; if(newsp != 0) { tf->sp = newsp; } return(oldsp);}/* * This function sets the arguments to client code so * the client sees the arguments as if it was called * with the arguments. */voidmd_setargs(struct trapframe *tf, register_t a1, register_t a2, register_t a3, register_t a4){ if (tf == NULL) tf = cpuinfotab[whatcpu]; tf->a0 = a1; tf->a1 = a2; tf->a2 = a3; tf->a3 = a4;}voidmd_setentry(struct trapframe *tf, register_t pc){ if (tf == NULL) tf = cpuinfotab[whatcpu]; tf->pc = pc;}/* * This function returns the PC value that is supposed * to be used at restore to client state. Do not confuse * with the value of the exception PC. (Diff on some arches). */void *md_getpc(struct trapframe *tf){ if (tf == NULL) tf = cpuinfotab[whatcpu]; return((void *)(int)tf->pc);}/* * This function is called from exception(). It's purpose * is to decode the exception and return the exception * type to the caller for further processing. */intmd_exc_type(struct trapframe *frame){ switch((frame->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT) { case T_BREAK: case T_TRAP: return(EXC_BPT); case T_IWATCH: case T_DWATCH: return(EXC_WTCH); case T_INT: case T_TLB_MOD: case T_TLB_LD_MISS: case T_TLB_ST_MISS: case T_ADDR_ERR_LD: case T_ADDR_ERR_ST: case T_BUS_ERR_IFETCH: case T_BUS_ERR_LD_ST: case T_SYSCALL: case T_RES_INST: case T_COP_UNUSABLE: case T_OVFLOW: case T_FPE: return(EXC_BAD); case T_VCEI: case T_VCED: return(EXC_BAD); } return(EXC_BAD);}/* * This function returns the value of the RA reg */register_tmd_getlink(struct trapframe *tf){ if (tf == NULL) tf = cpuinfotab[whatcpu]; return(tf->ra);}/* * This function returns a pointer from the value of the * PC reg when an exception have been taken. */void *md_get_excpc(struct trapframe *tf){ if (tf == NULL) tf = cpuinfotab[whatcpu]; return((void *)(int)tf->pc);}const char *md_getexcname(struct trapframe *tf){ switch((tf->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT) { case T_INT: return("interrupt pending");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -