⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmds_ppc.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 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 + -