📄 mpcbdm.c
字号:
u_int r0; u_int r1; u_int val; u_int com; r0 = bdm_getreg(0); /*save r0*/ r1 = bdm_getreg(1); /*save r1*/ bdm_setreg(1, addr); /*set addr to r1*/ com = (32 << 26) | (1 << 16); /*lwz r0,0(r1)*/ ser_clkinstr(com, 0); /*load r0 with data from mem*/ val = bdm_getreg(0); /*get data from r0*/ bdm_setreg(0, r0); /*restore data*/ bdm_setreg(1, r1); /*restore data*/ return val;}void ppc_bdm_setword(u_int addr, u_int val){ u_int r0; u_int r1; u_int com; r0 = bdm_getreg(0); /*save r0*/ r1 = bdm_getreg(1); /*save r1*/ bdm_setreg(1, addr); /*put addr in r1*/ bdm_setreg(0, val); /*put data in r0*/ com = (36 << 26) | (1 << 16); /*stw r0,0(r1)*/ ser_clkinstr(com, 0); /*store data into mem*/ bdm_setreg(0, r0); /*restore r0*/ bdm_setreg(1, r1); /*restore r1*/}u_int ppc_bdm_gethalfword(u_int addr){ u_int r0; u_int r1; u_int val; u_int com; r0 = bdm_getreg(0); /*save r0*/ r1 = bdm_getreg(1); /*save r1*/ bdm_setreg(1, addr); /*set addr to r1*/ com = (40 << 26) | (1 << 16); /*lhz r0,0(r1)*/ ser_clkinstr(com, 0); /*load r0 with data from mem*/ val = bdm_getreg(0); /*get data from r0*/ bdm_setreg(0, r0); /*restore data*/ bdm_setreg(1, r1); /*restore data*/ return val;}void ppc_bdm_sethalfword(u_int addr, u_int val){ u_int r0; u_int r1; u_int com; r0 = bdm_getreg(0); /*save r0*/ r1 = bdm_getreg(1); /*save r1*/ bdm_setreg(1, addr); /*put addr in r1*/ bdm_setreg(0, val); /*put data in r0*/ com = (44 << 26) | (1 << 16); /*sth r0,0(r1)*/ ser_clkinstr(com, 0); /*store data into mem*/ bdm_setreg(0, r0); /*restore r0*/ bdm_setreg(1, r1); /*restore r1*/}u_int ppc_bdm_getbyte(u_int addr){ u_int r0; u_int r1; u_int val; u_int com; r0 = bdm_getreg(0); /*save r0*/ r1 = bdm_getreg(1); /*save r1*/ bdm_setreg(1, addr); /*set addr to r1*/ com = (34 << 26) | (1 << 16); /*lbz r0,0(r1)*/ ser_clkinstr(com, 0); /*load r0 with data from mem*/ val = bdm_getreg(0); /*get data from r0*/ bdm_setreg(0, r0); /*restore data*/ bdm_setreg(1, r1); /*restore data*/ return val;}void ppc_bdm_setbyte(u_int addr, u_int val){ u_int r0; u_int r1; u_int com; r0 = bdm_getreg(0); /*save r0*/ r1 = bdm_getreg(1); /*save r1*/ bdm_setreg(1, addr); /*put addr in r1*/ bdm_setreg(0, val); /*put data in r0*/ com = (38 << 26) | (1 << 16); /*stb r0,0(r1)*/ ser_clkinstr(com, 0); /*store data into mem*/ bdm_setreg(0, r0); /*restore r0*/ bdm_setreg(1, r1); /*restore r1*/}u_int ppc_bdm_tablewalk(u_int vAddr){ u_int EPN; u_int TWC; u_int Level1; u_int Level2; u_int Level2Desc; u_int pAddr;/* return value in case of mmu problems : *//* emergency solution for second stage loader */ pAddr = vAddr - mpcbdm_kbase; /* =-0xc0000000 */ EPN = bdm_getspr(SPR_MD_EPN); /* save EPN register */ TWC = bdm_getspr(SPR_MD_TWC); /* save TWC register */ bdm_setspr(SPR_MD_EPN,vAddr); /* set effective addr to virtual addr*/ Level1 = bdm_getspr(SPR_M_TWB); /* do table walk level 1*/ if (Level1 == 0) { if (mpcbdm_verbose&VERBOSE_MMU) { printf("ppc_bdm_tablewalk: invalid level one descriptor for vAddr 0x%08x\n",vAddr); } else { printf("M!"); } return pAddr; } if ((Level1 & 0x0800)&&(mpcbdm_pgdir != 0)) /* kernel function? */ { Level1 = ((mpcbdm_pgdir & 0x3ffff000) | (Level1&0x00000fff)); if (mpcbdm_verbose&VERBOSE_MMU) { printf("ppc_bdm_tablewalk: pgdir -> Level1 = 0x%08x for vAddr 0x%08x\n",Level1,vAddr); } } Level2 = ppc_bdm_getword(Level1); Level2 &= (u_int)0xfffff000; if (Level2 == 0) { if (mpcbdm_verbose&VERBOSE_MMU) { printf("ppc_bdm_tablewalk: invalid level two base for vAddr 0x%08x and level one = 0x%08x\n",vAddr,Level1); } else { printf("M!"); } return pAddr; } Level2 -=mpcbdm_kbase; /* tophys, like table miss does, default=-0xc0000000 */ Level2 |=0x000000001; /* set valid bit in physical L2 page */ bdm_setspr(SPR_MD_TWC,Level2); Level2Desc= bdm_getspr(SPR_MD_TWC); /* perform table walk level 2*/ if (Level2Desc == 0) { if (mpcbdm_verbose&VERBOSE_MMU) { printf("ppc_bdm_tablewalk: invalid level two descriptor for vAddr 0x%08x, level one 0x%08x, level two 0x%08x\n",vAddr,Level1,Level2); } else { printf("M!"); } return pAddr; } pAddr = ppc_bdm_getword(Level2Desc); /*get physical page addr*/ pAddr = (pAddr & (u_int)0xfffff000) | (vAddr & (u_int)0xfff); /*calc physical addr*/ if (mpcbdm_verbose&VERBOSE_MMU) { printf("ppc_bdm_tablewalk: MMU translates virtual 0x%08x to physical 0x%08x\n",vAddr,pAddr); } bdm_setspr(SPR_MD_TWC,TWC); /* restore TWC register */ bdm_setspr(SPR_MD_EPN,EPN); /* restore EPN register */ return pAddr;}void ppc_bdm_read_block(u_int from, char *to, int len){ int n; int val; u_int r0 = bdm_getreg(0); /*save r0*/ u_int r1 = bdm_getreg(1); /*save r1*/ if ((LastMSR & MSR_IR)&&(mpcbdm_mmu)) /*mmu on and option activated*/ { from = ppc_bdm_tablewalk(from); } if (mpcbdm_verbose&VERBOSE_TAR) { printf_filtered("ppc_bdm_read_block: from=0x%08x, len=%d\n",from,len); } if(len > 0) while((from & 3) || len < 4) /*no word aligned start adr?*/ { bdm_setreg(1, (int)from); from += 1; ser_clkinstr(0x88010000, 0); /* lbz r0,0(r1) */ val = bdm_getreg(0); /* read byte*/ *(u_char*)to = val & 0xFF; /* store byte*/ to += 1; if(!--len) break; } if(len > 0 ) bdm_setreg(1, from - 4); for(len; len > 3; len -= 4) /* loop for aligned words*/ { ser_clkinstr(0x84010004, 0); /* lwzu r0,4(r1) */ val = bdm_getreg(0); /* read word*/ val = extract_unsigned_integer(&val, sizeof(val)); memcpy(to, &val, 4); /* store word */ to += 4; from +=4; /* FP: this one was missing ! */ } while(len > 0 && len < 4) /*misaligned bytes to read at end?*/ { bdm_setreg(1, from); from += 1; ser_clkinstr(0x88010000, 0); /* lbz r0,0(r1) */ val = bdm_getreg(0); /*read byte*/ *(u_char*)to = val & 0xFF; /*store byte*/ to += 1; --len; } bdm_setreg(0, r0); /* restore r0*/ bdm_setreg(1, r1); /* restore r1*/}void ppc_bdm_write_block(u_int mem, u_char *ozu, int len){ u_int val; u_int r30 = bdm_getreg(30); u_int r31 = bdm_getreg(31); if ((LastMSR & MSR_IR)&&(mpcbdm_mmu)) /*mmu on and option activated*/ { mem = ppc_bdm_tablewalk(mem); } if (mpcbdm_verbose&VERBOSE_TAR) { printf_filtered("ppc_bdm_write_block: mem=0x%08x, len=%d\n",mem,len); } if(len > 0) while((mem & 3) || len < 4) { bdm_setreg(30, (int)mem); mem += 1; val = *(u_char*)ozu; ozu += 1; bdm_setreg(31, val); ser_clkinstr(0x9BFE0000, 0); /* stb r31,0(r30) */ if(!--len) break; } if(len > 3 ) /*for aligned words use BDM download feature*/ { bdm_setreg(30, mem - 4); ser_clkdpc(DSDI_DPC_START_DOWNLOAD, 0); for(; len > 3; len -= 4) { memcpy(&val, ozu, 4); ozu += 4; val = extract_unsigned_integer(&val, sizeof(val)); ser_clkdata(val, 0); mem += 4; } ser_clkdpc(DSDI_DPC_END_DOWNLOAD, 0); ser_clkdata(val, 0); } while(len > 0) { bdm_setreg(30, (int)mem); mem += 1; val = *(u_char*)ozu; ozu += 1; bdm_setreg(31, val); ser_clkinstr(0x9BFE0000, 0); /* stb r31,0(r30) */ --len; } bdm_setreg(30, r30); bdm_setreg(31, r31);}/**************************************************************** MPCBDM target operations *****************************************************************/static void show_regs(void){ int n; int data; for(n = 0; n < 32; ++n) { data = bdm_getreg(n); printf("R%02d=0x%08X ", n, data); if(!((n + 1) % 4)) printf("\n"); } printf("\n");}void ppc_bdm_stop(void){/* Reset and set DSCK and /DSDI for immediate Debug Mode, asynchronously clocked */ if (mpcbdm_verbose&VERBOSE_TAR) { printf_filtered("ppc_bdm_stop: assert Reset for immediate debug mode, asynchronous clocked\n"); } PP.Write(PP.DSCK); /* set DSCK and /DSDI, implicite wait in Write *//* assert /HRESET and /SRESET, hold DSCK and /DSDI : Debug Mode enable *//* Note: I added HRESET here, because sometimes only SRESET didn't bring the processor in a stable state. So I completely removed ppc_bdm_reset. But I'm not shure I broke something here...*/ PP.Reset(PP.HRESET|PP.SRESET);/* hold reset for some while, since here occured some problems with fast CPUs*/ usleep(mpcbdm_sleep);/* release H&SRESET, hold DSCK, /DSDI: immediate Debug Mode, asynchr. clocked*/ PP.Reset(0x00);/* we have to hold DSDI low for at least eight MPC cycles*/ usleep(mpcbdm_sleep); WaitFreeze(); LastMSR = bdm_getspr(SPR_SRR1); if (mpcbdm_verbose&VERBOSE_SRR1) { printf_filtered("ppc_bdm_stop: "); print_spr_info(SPR_SRR1, LastMSR, 1, 1, 1, 1); printf_filtered("\n"); }}/*FIXME: remove?*/void ppc_bdm_reset(void){ printf("assert HRESET\n"); PP.Write(PP.DSCK); PP.Reset(PP.HRESET); /*FP: assert HRESET with DSCK : Debug Mode enable *//* hold reset for some while, since here occured some problems with fast CPUs*/ usleep(mpcbdm_sleep); PP.Reset(0x00); /* release HRESET with DSCK, /DSDI: immediately debug, asynchr. clocked*/}void ppc_bdm_resume(void){ if (mpcbdm_reattach) { printf("*** Resume without communicating with the MPC (mpcbdm_reattach)\n"); mpcbdm_reattach = 0; ctrlc = 0; return; } printf("*** Resume\n"); ctrlc = 0; bdm_getspr(SPR_ICR); /*read ICR to clear pending interrupts*/ bdm_setspr(SPR_IC_CST, 0x0C000000); /*invalidate instruction cache*/ /*tell PPC to exit from Debug Port Interrupt*/ ser_clkinstr(DSDI_COM_RFI, 0); /*return from interrupt*/}static void ppc_bdm_interrupt (int signo){ signal(signo, ppc_bdm_interrupt); printf("CTRL-C catched - %d\n", ++ctrlc); if(ctrlc >= 5) { printf("\n caught five times CTRL-C: BDM port is not responding.\nQuitting gdb\n"); exit(-1); } ser_clkdpc(DSDI_DPC_ASSERT_NMASK_BREAK,0); /*signal debug port interrupt*/ printf("Sending Debug Port Interrupt Request to PPC...\n");}int ppc_bdm_wait(void){ int icr = 0; void (*ofunc)(); ofunc = signal (SIGINT, ppc_bdm_interrupt); /*install our handler*/ printf("*** wait freeze\n"); WaitFreeze(); /*wait for ppc to come into debug mode*/ /*or interrupt ppc with ctrl-c with our handler*/ signal (SIGINT, ofunc); /*restore old handler*/ icr = bdm_getspr(SPR_ICR); /*interrupt cause register*/ LastICR = icr; /*save interupt cause*//*get srr1, contents of MSR before debug exception*/ LastMSR = bdm_getspr(SPR_SRR1); if (mpcbdm_verbose&VERBOSE_SRR1) { printf_filtered("ppc_bdm_wait: "); print_spr_info(SPR_SRR1, LastMSR, 1, 1, 1, 1); printf_filtered("\n"); } ser_clkdpc(DSDI_DPC_NEGATE_NMASK_BREAK,0); /*negate debug port interrupt request*/// ser_clkinstr(0x7C0004AC, 0); /* sync */// ser_clkinstr(0x4C00012C, 0); /* isync */ if (mpcbdm_dflush) {/* flush all data cache blocks to see valid data, but this is slow*/ mpcbdm_dcache_flush(0,1); } bdm_setspr(SPR_IC_CST, 0x0C000000); /*invalidate instruction cache*/ if(icr & PPC_BIT(17)) icr = 1; /* ICR[SEI] -> INT */ else icr = 0; /* else TRAP */ return icr;}void ppc_bdm_step(void){ if (mpcbdm_reattach) { printf("*** step without communicating with the MPC (mpcbdm_reattach)\n"); } else { printf("*** step\n"); LastDER = bdm_getspr(SPR_DER); /*save previous Debug Enable Register value*/ bdm_setspr(SPR_DER, LastDER | PPC_BIT(14)); /* force TRE for single step*//* set single step trace enable in next MSR */ bdm_setspr(SPR_SRR1, bdm_getspr(SPR_SRR1) | PPC_BIT(21)); } ppc_bdm_resume(); /*execute one step*/}void ppc_bdm_run(void){ if (mpcbdm_reattach) { printf("*** run without communicating with the MPC (mpcbdm_reattach)\n"); } else { printf("*** run\n"); LastDER = bdm_getspr(SPR_DER); /*save previous Debug Enable Register value*//* disable single step trace enable (SE) */ bdm_setspr(SPR_SRR1, bdm_getspr(SPR_SRR1) & ~(PPC_BIT(21))); } ppc_bdm_resume();}void ppc_bdm_init(void){ int i; int n; u_int pvr; u_int partmask; u_int revnum; u_int word; u_int partnum; u_int masknum; if (mpcbdm_reattach) { return; } printf_filtered("*** init\n");/* try to identify processor */ pvr = bdm_getspr(SPR_PVR); /* get processor version register */ partmask = 0x0000ffff & bdm_getspr(SPR_IMMR); /* get IMMR */ partnum = (partmask & 0x0000ff00) >> 8; masknum = partmask & 0x000000ff; word = bdm_getspri(SPRI_REV_NUM); /* get REV_NUM */ revnum = (word & 0xffff0000) >> 16; printf_filtered("Target cpu PVR=0x%08X PARTNUM=0x%02X MASKNUM=0x%02X REV_NUM=0x%04X\n", pvr,partnum,masknum,revnum); for (i=0; CPU[i].name; i++) { if ((pvr == CPU[i].pvr) && (partmask == CPU[i].partmask) && (revnum == CPU[i].revnum)) { printf_filtered("Target cpu is a '%s'\n",CPU[i].name); if (CPU[i].regfile) { printf_filtered("Reading CPU register description file '%s'\n",CPU[i].regfile); } break; } } if (!(CPU[i].name)) { printf_filtered("warning: unknown CPU. Using default register description\n"); }/*initial value for Debug Enable Register*//* SEIE for soft breakpoint recognition (illegal opcode) needed */ bdm_setspr(SPR_DER, 0x7002400F); /*RSTE,CHSTPE,MCIE,TRE,SEIE,LBRKE,IBRKE,EBRKE,DPIE*/ bdm_setspr(SPRI_PLPRCR, bdm_getspr(SPRI_PLPRCR) | PPC_BIT(24)); /*CSE, CheckStopEnable*/ bdm_setsprihw(SPRI_SWSR, 0x556C); /*trigger software watch dog*/ bdm_setsprihw(SPRI_SWSR, 0xAA39); LastMSR = bdm_getspr(SPR_SRR1); if (mpcbdm_verbose&VERBOSE_SRR1) { printf_filtered("ppc_bdm_init: "); print_spr_info(SPR_SRR1, LastMSR, 1, 1, 1, 1); printf_filtered("\n"); } printf("\007BDM initialized\n");}/************************************************************ routines from ocd.c ************************************************************//* Return nonzero if the thread TH is still alive on the remote system. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -