📄 cmds_ppc.c
字号:
/* * cmds_ppc.c: * This file contains monitor commands that are specific to the PowerPC. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#include "cli.h"#include "genlib.h"#include "stddefs.h"#include "arch_ppc.h"#define MTSPR_R3 0x7c6003a6#define MFSPR_R3 0x7c6002a6#define MTDCR_R3 0x7c600386#define MFDCR_R3 0x7c600286#define SYSCALL 0x44000002#define TRAPWORD 0x7fe00008#define SYNC 0x7c0004ac#define ISYNC 0x4c00012c#define BLR 0x4e800020#define SPRREG 1#define DCRREG 2extern void ppc_invalidateIcache();extern void ppc_flushDcache();#if INCLUDE_SPRCMD | INCLUDE_DCRCMD/* mtreg() and mfreg(): * Build the appropriate mf/mt (move from/move to) instruction * right on the stack and execute it. */static voidmtreg(ulong regnum, ulong regval, int type){ ulong tfunc[4]; ulong reg; void (*func)(); reg = (((regnum & 0x1f) << 5) | ((regnum >> 5) & 0x1f)); tfunc[0] = SYNC; tfunc[1] = ISYNC; switch(type) { case SPRREG: tfunc[2] = (MTSPR_R3 | (reg << 11)); break; case DCRREG: tfunc[2] = (MTDCR_R3 | (reg << 11)); break; } tfunc[3] = BLR; ppc_invalidateIcache(tfunc,32); ppc_flushDcache(tfunc,32); func = (void(*)())tfunc; func(regval);}static ulongmfreg(ulong regnum, int type){ ulong tfunc[4]; ulong reg; ulong (*func)(int); reg = (((regnum & 0x1f) << 5) | ((regnum >> 5) & 0x1f)); tfunc[0] = SYNC; tfunc[1] = ISYNC; switch(type) { case SPRREG: tfunc[2] = (MFSPR_R3 | (reg << 11)); /* mfspr r3,SPRNUM */ break; case DCRREG: tfunc[2] = (MFDCR_R3 | (reg << 11)); /* mfdcr r3,DCRNUM */ break; } tfunc[3] = BLR; ppc_invalidateIcache(tfunc,32); ppc_flushDcache(tfunc,32); func = (ulong(*)())tfunc; return(func(regnum));}#endif#if INCLUDE_SPRCMDchar *SprHelp[] = { "Display/modify SPR register", "{sprnum | REGNAME} [sprval]", " where REGNAME = msr", 0,};/* SprCmd: * Command for easy CLI access to PPC SPR registers. * The mtreg() and mfreg() functions build small assy subroutines * right in their own stack space. This is necessary so that the * appropriate SPR index is place in the mtreg/mfreg instruction. * I-cache and D-cache must be invalidated/flushed after the assy routine * is placed in ram. */intSprCmd(int argc,char **argv){ char *arg1, *arg2, *regname; int opt; ulong sprnum, sprval; regname = (char *)0; while((opt=getopt(argc,argv,"n:")) != -1) { switch(opt) { case 'n': regname = optarg; break; default: return(CMD_PARAM_ERROR); } } if ((argc != optind+1) && (argc != optind+2)) return(CMD_PARAM_ERROR); arg1 = argv[optind]; arg2 = argv[optind+1]; sprnum = strtoul(arg1,0,0); sprval = strtoul(arg2,0,0); if (argc == optind+1) { if (!strcmp(arg1,"msr")) { printf("MSR = 0x%lx\n",ppcMfmsr()); } else { if (regname) { printf("%s (spr %ld) = 0x%lx\n",regname,sprnum, mfreg(sprnum,SPRREG)); } else { printf("SPR %ld (0x%lx) = 0x%lx\n",sprnum,sprnum, mfreg(sprnum,SPRREG)); } } } else if (argc == optind+2) { if (!strcmp(arg1,"msr")) { ppcMtmsr(sprval); } else { mtreg(sprnum,sprval,SPRREG); } } return(CMD_SUCCESS);}#endif /* INCLUDE_SPRCMD */#if INCLUDE_DCRCMDchar *DcrHelp[] = { "Display/modify DCR register", "{dcrnum} [dcrval]", 0,};/* DCRCmd: * Command for easy CLI access to PPC DCR registers. * The mtreg() and mfreg() functions build small assy subroutines * right in their own stack space. This is necessary so that the * appropriate DCR index is place in the mtreg/mfreg instruction. * I-cache and D-cache must be invalidated/flushed after the assy routine * is placed in ram. */intDcrCmd(int argc,char **argv){ char *arg1, *arg2, *regname; int opt; ulong dcrnum, dcrval; regname = (char *)0; while((opt=getopt(argc,argv,"n:")) != -1) { switch(opt) { case 'n': regname = optarg; break; default: return(CMD_PARAM_ERROR); } } if ((argc != optind+1) && (argc != optind+2)) return(CMD_PARAM_ERROR); arg1 = argv[optind]; arg2 = argv[optind+1]; dcrnum = strtoul(arg1,0,0); dcrval = strtoul(arg2,0,0); if (argc == optind+1) { if (regname) { printf("%s (spr %ld) = 0x%lx\n",regname,dcrnum, mfreg(dcrnum,DCRREG)); } else { printf("DCR %ld (0x%lx) = 0x%lx\n",dcrnum,dcrnum, mfreg(dcrnum,DCRREG)); } } else if (argc == optind+2) { mtreg(dcrnum,dcrval,DCRREG); } return(CMD_SUCCESS);}#endif /* INCLUDE_DCRCMD */#if INCLUDE_TRAPCMD | INCLUDE_SYSCALLCMD | INCLUDE_IABRCMD | INCLUDE_DABRCMDvoidinstallHandler(char *src, char *dest, int size, int verbose){ if (verbose) { printf("Copying %d-byte handler at 0x%lx to 0x%lx.\n", size,(ulong)src,(ulong)dest); } memcpy(dest,src,size); ppc_flushDcache(dest,size); ppc_invalidateIcache(dest,size);}#endif#if INCLUDE_TRAPCMDchar *TrapHelp[] = { "Use trap instruction for breakpoints", "-[I:iv] {address}", "Options:", " -i install exception handler @ 0x700", " -I{adr}", " install exception handler @ 'adr'", " -v verbose install", 0,};/* TrapCmd(): * Load the monitor's specified vector table entry into * the current vector table. */intTrapCmd(int argc,char **argv){ ulong *addr, handler_at; int opt, install_handler, verbose; extern void program_exception(); if (argc < 2) return(CMD_PARAM_ERROR); verbose = 0; handler_at = 0x700; install_handler = 0; while((opt=getopt(argc,argv,"I:iv")) != -1) { switch(opt) { case 'I': install_handler = 1; handler_at = strtoul(optarg,0,0); break; case 'i': install_handler = 1; break; case 'v': verbose = 1; break; } } /* If -l option is set, then we install the monitor's exception * handler at the PROGRAM_EXCEPTION location. */ if (install_handler) { installHandler((char *)program_exception,(char *)handler_at,256, verbose); if (argc == optind) return(CMD_SUCCESS); } if (argc != (optind + 1)) return(CMD_PARAM_ERROR); addr = (ulong *)strtoul(argv[optind],0,0); *addr = TRAPWORD; ppc_flushDcache(addr,4); ppc_invalidateIcache(addr,4); return(CMD_SUCCESS);}#endif /* INCLUDE_TRAPCMD */#if INCLUDE_SYSCALLCMDchar *SyscallHelp[] = { "Use syscall instruction for breakpoints", "-[I:iv] {address}", "Options:", " -i install exception handler @ 0xc00", " -I{adr}", " install exception handler @ 'adr'", " -v verbose install", 0,};/* SyscallCmd(): * Use SC (system call) instruction to generate a SYSTEM_CALL exception. */intSyscallCmd(int argc,char **argv){ ulong *addr, handler_at; int opt, install_handler, verbose; extern void system_call_exception(); if (argc < 2) return(CMD_PARAM_ERROR); verbose = 0; install_handler = 0; handler_at = 0xc00; while((opt=getopt(argc,argv,"I:iv")) != -1) { switch(opt) { case 'I': install_handler = 1; handler_at = strtoul(optarg,0,0); break; case 'i': install_handler = 1; break; case 'v': verbose = 1; break; } } /* If -i option is set, then we install the monitor's exception * handler at the SYSCALL_EXCEPTION location. */ if (install_handler) { installHandler((char *)system_call_exception,(char *)handler_at,256, verbose); if (argc == optind) return(CMD_SUCCESS); } if (argc != (optind + 1)) return(CMD_PARAM_ERROR); addr = (ulong *)strtoul(argv[optind],0,0); *addr = SYSCALL; ppc_flushDcache(addr,4); ppc_invalidateIcache(addr,4); return(CMD_SUCCESS);}#endif /* INCLUDE_SYSCALLCMD */#if INCLUDE_IABRCMDchar *IabrHelp[] = { "Use IABR (spr 1010) to establish instruction-breakpoint.", "-[dI:itv] [address]", "Options:", " -d disable the exception", " -i install exception handler @ 0x1300", " -I{adr}", " install exception handler @ 'adr'", " -t translation enabled", " -v verbose install", 0,};#define IABR_BE 0x2#define IABR_TE 0x1/* IabrCmd(): * Use IABR register to generate a DSI exception. */intIabrCmd(int argc,char **argv){ ulong addr, mask, handler_at; int opt, install_handler, disable, verbose; extern void instruction_addrbkpt_exception(); if (argc < 2) return(CMD_PARAM_ERROR); handler_at = 0x1300; mask = IABR_BE; install_handler = 0; verbose = disable = 0; while((opt=getopt(argc,argv,"dI:itv")) != -1) { switch(opt) { case 'd': disable = 1; break; case 'I': install_handler = 1; handler_at = strtoul(optarg,0,0); break; case 'i': install_handler = 1; break; case 't': mask = IABR_TE; break; case 'v': verbose = 1; break; } } /* If -d is set, then we disable the DABR's ability to * generate an exception. All other arguments and options * are ignored. */ if (disable) { ppcMtiabr(0); return(CMD_SUCCESS); } /* If -l option is set, then we install the monitor's exception * handler at the DSI_EXCEPTION location. */ if (install_handler) { installHandler((char *)instruction_addrbkpt_exception, (char *)handler_at,256,verbose); if (argc == optind) return(CMD_SUCCESS); } if (argc != (optind + 1)) return(CMD_PARAM_ERROR); addr = strtoul(argv[optind],0,0); addr &= ~3; ppcMtiabr(addr | mask); return(CMD_SUCCESS);}#endif /* INCLUDE_IABRCMD */#if INCLUDE_DABRCMDchar *DabrHelp[] = { "Use DABR (spr 1013) to establish data-breakpoint.", "-[I:irtw] [address]", "Options:", " -d disable the exception", " -i install exception handler @ 0x300", " -I{adr}", " install exception handler @ 'adr'", " -r enable 'read' access exception", " -t translation enabled", " -w enable 'write' access exception", " -v verbose install", 0,};#define DABR_BT 0x4#define DABR_DW 0x2#define DABR_DR 0x1/* DabrCmd(): * Use DABR register to generate a DSI exception. */intDabrCmd(int argc,char **argv){ ulong addr, mask, handler_at; int opt, install_handler, disable, verbose; extern void dsi_exception(); if (argc < 2) return(CMD_PARAM_ERROR); mask = 0; disable = 0; verbose = 0; handler_at = 0x0300; install_handler = 0; while((opt=getopt(argc,argv,"dI:irtvw")) != -1) { switch(opt) { case 'd': disable = 1; break; case 'I': install_handler = 1; handler_at = strtoul(optarg,0,0); break; case 'i': install_handler = 1; break; case 'r': mask |= DABR_DR; /* Enable read-acces to trigger exception */ break; case 't': mask |= DABR_BT; break; case 'w': mask |= DABR_DW; /* Enable write-acces to trigger exception */ break; case 'v': verbose = 1; break; } } /* If -d is set, then we disable the DABR's ability to * generate an exception. All other arguments and options * are ignored. */ if (disable) { ppcMtdabr(0); return(CMD_SUCCESS); } /* If -l option is set, then we install the monitor's exception * handler at the DSI_EXCEPTION location. */ if (install_handler) { installHandler((char *)dsi_exception, (char *)handler_at,256,verbose); if (argc == optind) return(CMD_SUCCESS); } if (argc != (optind + 1)) return(CMD_PARAM_ERROR); if (mask == 0) { printf("Must specify -r and/or -w\n"); return(CMD_FAILURE); } addr = strtoul(argv[optind],0,0) & ~7; ppcMtdabr(addr | mask); return(CMD_SUCCESS);}#endif /* INCLUDE_DABRCMD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -