|
[PATCH] ia64 fixes and clean up: msg#00102linux.kernel.debugging.kgdb.bugs
This patch fixes various register fetch/put methods and does a general code clean up and restructuring for fetch/put. The patch is based on work I did last fall; anticipating the arrival of a libunwind replacing the current unwind code. The code was tested on a two processor rx2600. Signed-off-by: Bob Picco <bob.picco@xxxxxx> arch/ia64/kernel/kgdb.c | 578 ++++++++++++++++++++++++++---------------------- 1 file changed, 315 insertions(+), 263 deletions(-) Index: linux-2.6.15-kgdb/arch/ia64/kernel/kgdb.c =================================================================== --- linux-2.6.15-kgdb.orig/arch/ia64/kernel/kgdb.c 2006-01-11 13:45:23.000000000 -0500 +++ linux-2.6.15-kgdb/arch/ia64/kernel/kgdb.c 2006-01-11 14:21:56.000000000 -0500 @@ -14,6 +14,8 @@ /* * Copyright (C) 2000-2001 VERITAS Software Corporation. + * (c) Copyright 2005 Hewlett-Packard Development Company, L.P. + * Bob Picco <bob.picco@xxxxxx> */ /* * Contributor: Lake Stevens Instrument Division$ @@ -40,9 +42,11 @@ #define NUM_REGS 590 #define REGISTER_BYTES (NUM_REGS*8+128*8) -#define REGISTER_BYTE(N) (((N) * 8) \ - + ((N) <= IA64_FR0_REGNUM ? 0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM))) -#define REGISTER_SIZE(N) (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8) +#define REGISTER_BYTE(N) (((N) * 8) \ + + ((N) <= IA64_FR0_REGNUM ? \ + 0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM))) +#define REGISTER_SIZE(N) \ + (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8) #define IA64_GR0_REGNUM 0 #define IA64_FR0_REGNUM 128 #define IA64_FR127_REGNUM (IA64_FR0_REGNUM+127) @@ -77,136 +81,308 @@ #define IA64_LC_REGNUM (IA64_AR0_REGNUM+65) #define IA64_EC_REGNUM (IA64_AR0_REGNUM+66) -#define REGISTER_INDEX(N) (REGISTER_BYTE(N) / sizeof (unsigned long)) +#define REGISTER_INDEX(N) (REGISTER_BYTE(N) / sizeof (unsigned long)) -#define ptoff(V) ((unsigned int) &((struct pt_regs *)0x0)->V) +#define ptoff(V) ((unsigned int) &((struct pt_regs *)0x0)->V) struct reg_to_ptreg_index { unsigned int reg; unsigned int ptregoff; }; -struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = { + +static struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = { + {IA64_GR0_REGNUM + 1, ptoff(r1)}, + {IA64_GR0_REGNUM + 2, ptoff(r2)}, + {IA64_GR0_REGNUM + 3, ptoff(r3)}, {IA64_GR0_REGNUM + 8, ptoff(r8)}, {IA64_GR0_REGNUM + 9, ptoff(r9)}, {IA64_GR0_REGNUM + 10, ptoff(r10)}, {IA64_GR0_REGNUM + 11, ptoff(r11)}, - {IA64_GR0_REGNUM + 1, ptoff(r1)}, {IA64_GR0_REGNUM + 12, ptoff(r12)}, {IA64_GR0_REGNUM + 13, ptoff(r13)}, {IA64_GR0_REGNUM + 14, ptoff(r14)}, {IA64_GR0_REGNUM + 15, ptoff(r15)}, + {IA64_GR0_REGNUM + 16, ptoff(r16)}, + {IA64_GR0_REGNUM + 17, ptoff(r17)}, + {IA64_GR0_REGNUM + 18, ptoff(r18)}, + {IA64_GR0_REGNUM + 19, ptoff(r19)}, + {IA64_GR0_REGNUM + 20, ptoff(r20)}, + {IA64_GR0_REGNUM + 21, ptoff(r21)}, + {IA64_GR0_REGNUM + 22, ptoff(r22)}, + {IA64_GR0_REGNUM + 23, ptoff(r23)}, + {IA64_GR0_REGNUM + 24, ptoff(r24)}, + {IA64_GR0_REGNUM + 25, ptoff(r25)}, + {IA64_GR0_REGNUM + 26, ptoff(r26)}, + {IA64_GR0_REGNUM + 27, ptoff(r27)}, + {IA64_GR0_REGNUM + 28, ptoff(r28)}, + {IA64_GR0_REGNUM + 29, ptoff(r29)}, + {IA64_GR0_REGNUM + 30, ptoff(r30)}, + {IA64_GR0_REGNUM + 31, ptoff(r31)}, }; -struct reg_to_ptreg_index br_reg_to_ptreg_index[] = { +static struct reg_to_ptreg_index br_reg_to_ptreg_index[] = { {IA64_BR0_REGNUM, ptoff(b0)}, {IA64_BR0_REGNUM + 6, ptoff(b6)}, {IA64_BR0_REGNUM + 7, ptoff(b7)}, }; +static struct reg_to_ptreg_index ar_reg_to_ptreg_index[] = { + {IA64_PFS_REGNUM, ptoff(ar_pfs)}, + {IA64_UNAT_REGNUM, ptoff(ar_unat)}, + {IA64_RNAT_REGNUM, ptoff(ar_rnat)}, + {IA64_BSPSTORE_REGNUM, ptoff(ar_bspstore)}, + {IA64_RSC_REGNUM, ptoff(ar_rsc)}, + {IA64_CSD_REGNUM, ptoff(ar_csd)}, + {IA64_SSD_REGNUM, ptoff(ar_ssd)}, + {IA64_FPSR_REGNUM, ptoff(ar_fpsr)}, + {IA64_CCV_REGNUM, ptoff(ar_ccv)}, +}; + extern atomic_t cpu_doing_single_step; -void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info, - struct pt_regs *ptregs) +static int kgdb_gr_reg(int regnum, struct unw_frame_info *info, + unsigned long *reg, int rw) { - unsigned long reg, size = 0, *mem = ® char nat; - struct ia64_fpreg freg; - int i; if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) || - (regnum >= (IA64_GR0_REGNUM + 4) && regnum <= (IA64_GR0_REGNUM + 7)) - || (regnum >= (IA64_GR0_REGNUM + 16) - && regnum <= (IA64_GR0_REGNUM + 31))) { - unw_access_gr(info, regnum - IA64_GR0_REGNUM, ®, &nat, 0); - size = sizeof(reg); + (regnum >= (IA64_GR0_REGNUM + 4) && + regnum <= (IA64_GR0_REGNUM + 7))) + return !unw_access_gr(info, regnum - IA64_GR0_REGNUM, + reg, &nat, rw); + else + return 0; +} + +static int kgdb_gr_ptreg(int regnum, struct pt_regs * ptregs, + struct unw_frame_info *info, unsigned long *reg, int rw) +{ + int i, result = 1; + char nat; + + if (!((regnum >= (IA64_GR0_REGNUM + 2) && + regnum <= (IA64_GR0_REGNUM + 3)) || + (regnum >= (IA64_GR0_REGNUM + 8) && + regnum <= (IA64_GR0_REGNUM + 15)) || + (regnum >= (IA64_GR0_REGNUM + 16) && + regnum <= (IA64_GR0_REGNUM + 31)))) + return 0; + else if (rw && ptregs) { + for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++) + if (gr_reg_to_ptreg_index[i].reg == regnum) { + *((unsigned long *)(((void *)ptregs) + + gr_reg_to_ptreg_index[i].ptregoff)) = *reg; + break; + } + } else if (!rw && ptregs) { + for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++) + if (gr_reg_to_ptreg_index[i].reg == regnum) { + *reg = *((unsigned long *) + (((void *)ptregs) + + gr_reg_to_ptreg_index[i].ptregoff)); + break; + } } else - if ((regnum >= (IA64_GR0_REGNUM + 2) - && regnum <= (IA64_GR0_REGNUM + 3)) - || (regnum >= (IA64_GR0_REGNUM + 8) - && regnum <= (IA64_GR0_REGNUM + 15))) { - if (ptregs) { - for (i = 0; i < (sizeof(gr_reg_to_ptreg_index) / - sizeof(gr_reg_to_ptreg_index[0])); i++) - if (gr_reg_to_ptreg_index[0].reg == regnum) { - reg = *((unsigned long *) - (((void *)ptregs) + - gr_reg_to_ptreg_index[i].ptregoff)); + result = !unw_access_gr(info, regnum - IA64_GR0_REGNUM, + reg, &nat, rw); + return result; +} + +static int kgdb_br_reg(int regnum, struct pt_regs * ptregs, + struct unw_frame_info *info, unsigned long *reg, int rw) +{ + int i, result = 1; + + if (!(regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7))) + return 0; + + switch (regnum) { + case IA64_BR0_REGNUM: + case IA64_BR0_REGNUM + 6: + case IA64_BR0_REGNUM + 7: + if (rw) { + for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++) + if (br_reg_to_ptreg_index[i].reg == regnum) { + *((unsigned long *) + (((void *)ptregs) + + br_reg_to_ptreg_index[i].ptregoff)) = + *reg; break; } } else - unw_access_gr(info, regnum - IA64_GR0_REGNUM, ®, - &nat, 0); - size = sizeof(reg); - } else if (regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7)) - switch (regnum) { - case IA64_BR0_REGNUM: - case IA64_BR0_REGNUM + 6: - case IA64_BR0_REGNUM + 7: - if (ptregs) { - for (i = 0; i < (sizeof(br_reg_to_ptreg_index) / - sizeof(br_reg_to_ptreg_index - [0])); i++) - if (br_reg_to_ptreg_index[i].reg == - regnum) { - reg = *((unsigned long *) - (((void *)ptregs) + - br_reg_to_ptreg_index - [i].ptregoff)); - break; - } - } else - unw_access_br(info, regnum - IA64_BR0_REGNUM, - ®, 0); - size = sizeof(reg); - break; - case IA64_BR0_REGNUM + 1: - case IA64_BR0_REGNUM + 2: - case IA64_BR0_REGNUM + 3: - case IA64_BR0_REGNUM + 4: - case IA64_BR0_REGNUM + 5: - unw_access_br(info, regnum - IA64_BR0_REGNUM, ®, 0); - size = sizeof(reg); + for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++) + if (br_reg_to_ptreg_index[i].reg == regnum) { + *reg = *((unsigned long *) + (((void *)ptregs) + + br_reg_to_ptreg_index[i]. + ptregoff)); + break; + } + break; + case IA64_BR0_REGNUM + 1: + case IA64_BR0_REGNUM + 2: + case IA64_BR0_REGNUM + 3: + case IA64_BR0_REGNUM + 4: + case IA64_BR0_REGNUM + 5: + result = !unw_access_br(info, regnum - IA64_BR0_REGNUM, + reg, rw); + break; + } + + return result; +} + +static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs, + struct unw_frame_info *info, unsigned long *reg, + struct ia64_fpreg *freg, int rw) +{ + int result = 1; + + if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127))) + return 0; + + switch (regnum) { + case IA64_FR0_REGNUM + 6: + case IA64_FR0_REGNUM + 7: + case IA64_FR0_REGNUM + 8: + case IA64_FR0_REGNUM + 9: + case IA64_FR0_REGNUM + 10: + case IA64_FR0_REGNUM + 11: + case IA64_FR0_REGNUM + 12: + if (rw) { + char *ptr = inbuffer; + + freg->u.bits[0] = *reg; + kgdb_hex2long(&ptr, &freg->u.bits[1]); + *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) = + *freg; break; - } else if (regnum >= IA64_FR0_REGNUM - && regnum <= (IA64_FR0_REGNUM + 127)) - switch (regnum) { - case IA64_FR0_REGNUM + 6: - case IA64_FR0_REGNUM + 7: - case IA64_FR0_REGNUM + 8: - case IA64_FR0_REGNUM + 9: - case IA64_FR0_REGNUM + 10: - case IA64_FR0_REGNUM + 11: - case IA64_FR0_REGNUM + 12: - if (!ptregs) - unw_access_fr(info, regnum - IA64_FR0_REGNUM, - &freg, 0); - else { - freg = - *(&ptregs->f6 + - (regnum - (IA64_FR0_REGNUM + 6))); + } else if (!ptregs) + result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM, + freg, rw); + else + *freg = + *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))); + break; + default: + if (!rw) + result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM, + freg, rw); + else + result = 0; + break; + } + + return result; +} + +static int kgdb_ar_reg(int regnum, struct pt_regs * ptregs, + struct unw_frame_info *info, unsigned long *reg, int rw) +{ + int result = 0, i; + + if (!(regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM)) + return 0; + + if (rw && ptregs) { + for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++) + if (ar_reg_to_ptreg_index[i].reg == regnum) { + *((unsigned long *) (((void *)ptregs) + + ar_reg_to_ptreg_index[i].ptregoff)) = + *reg; + result = 1; + break; } - size = sizeof(freg); - mem = (unsigned long *)&freg; - break; - default: - unw_access_fr(info, regnum - IA64_FR0_REGNUM, &freg, 0); - break; + } else if (ptregs) { + for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++) + if (ar_reg_to_ptreg_index[i].reg == regnum) { + *reg = *((unsigned long *) (((void *)ptregs) + + ar_reg_to_ptreg_index[i].ptregoff)); + result = 1; + break; + } + } + + if (result) + return result; + + result = 1; + + switch (regnum) { + case IA64_CSD_REGNUM: + result = !unw_access_ar(info, UNW_AR_CSD, reg, rw); + break; + case IA64_SSD_REGNUM: + result = !unw_access_ar(info, UNW_AR_SSD, reg, rw); + break; + case IA64_UNAT_REGNUM: + result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); + break; + case IA64_RNAT_REGNUM: + result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); + break; + case IA64_BSPSTORE_REGNUM: + result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); + break; + case IA64_PFS_REGNUM: + result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); + break; + case IA64_LC_REGNUM: + result = !unw_access_ar(info, UNW_AR_LC, reg, rw); + break; + case IA64_EC_REGNUM: + result = !unw_access_ar(info, UNW_AR_EC, reg, rw); + break; + case IA64_FPSR_REGNUM: + result = !unw_access_ar(info, UNW_AR_FPSR, reg, rw); + break; + case IA64_RSC_REGNUM: + result = !unw_access_ar(info, UNW_AR_RSC, reg, rw); + break; + case IA64_CCV_REGNUM: + result = !unw_access_ar(info, UNW_AR_CCV, reg, rw); + break; + default: + result = 0; + } + + return result; +} + +void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info, + struct pt_regs *ptregs) +{ + unsigned long reg, size = 0, *mem = ® + struct ia64_fpreg freg; + + if (kgdb_gr_reg(regnum, info, ®, 0) || + kgdb_gr_ptreg(regnum, ptregs, info, ®, 0) || + kgdb_br_reg(regnum, ptregs, info, ®, 0) || + kgdb_ar_reg(regnum, ptregs, info, ®, 0)) + size = sizeof(reg); + else if (kgdb_fr_reg(regnum, NULL, ptregs, info, ®, &freg, 0)) { + size = sizeof(freg); + mem = (unsigned long *)&freg; } else if (regnum == IA64_IP_REGNUM) { - if (!ptregs) + if (!ptregs) { unw_get_ip(info, ®); - else + size = sizeof(reg); + } else { reg = ptregs->cr_iip; - size = sizeof(reg); + size = sizeof(reg); + } } else if (regnum == IA64_CFM_REGNUM) { - if (!ptregs) + if (!ptregs) { unw_get_cfm(info, ®); - else + size = sizeof(reg); + } else { reg = ptregs->cr_ifs; - size = sizeof(reg); + size = sizeof(reg); + } } else if (regnum == IA64_PSR_REGNUM) { if (!ptregs && kgdb_usethread) ptregs = (struct pt_regs *) - ((unsigned long)kgdb_usethread + IA64_STK_OFFSET) - - 1; + ((unsigned long)kgdb_usethread + + IA64_STK_OFFSET) - 1; if (ptregs) reg = ptregs->cr_ipsr; size = sizeof(reg); @@ -219,151 +395,33 @@ void kgdb_get_reg(char *outbuffer, int r } else if (regnum == IA64_BSP_REGNUM) { unw_get_bsp(info, ®); size = sizeof(reg); - } else if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM) - switch (regnum) { - case IA64_CSD_REGNUM: - if (ptregs) - reg = ptregs->ar_csd; - else - unw_access_ar(info, UNW_AR_CSD, ®, 0); - size = sizeof(reg); - break; - case IA64_SSD_REGNUM: - if (ptregs) - reg = ptregs->ar_ssd; - else - unw_access_ar(info, UNW_AR_SSD, ®, 0); - size = sizeof(reg); - break; - case IA64_UNAT_REGNUM: - if (ptregs) - reg = ptregs->ar_unat; - else - unw_access_ar(info, UNW_AR_UNAT, ®, 0); - size = sizeof(reg); - break; - case IA64_RNAT_REGNUM: - unw_access_ar(info, UNW_AR_RNAT, ®, 0); - size = sizeof(reg); - break; - case IA64_BSPSTORE_REGNUM: - unw_access_ar(info, UNW_AR_BSPSTORE, ®, 0); - size = sizeof(reg); - break; - case IA64_PFS_REGNUM: - unw_access_ar(info, UNW_AR_PFS, ®, 0); - size = sizeof(reg); - break; - case IA64_LC_REGNUM: - unw_access_ar(info, UNW_AR_LC, ®, 0); - size = sizeof(reg); - break; - case IA64_EC_REGNUM: - unw_access_ar(info, UNW_AR_EC, ®, 0); - size = sizeof(reg); - break; - case IA64_FPSR_REGNUM: - if (ptregs) - reg = ptregs->ar_fpsr; - else - unw_access_ar(info, UNW_AR_FPSR, ®, 0); - size = sizeof(reg); - break; - case IA64_RSC_REGNUM: - if (ptregs) - reg = ptregs->ar_rsc; - else - unw_access_ar(info, UNW_AR_RNAT, ®, 0); - size = sizeof(reg); - break; - case IA64_CCV_REGNUM: - unw_access_ar(info, UNW_AR_CCV, ®, 0); - size = sizeof(reg); - break; - } + } if (size) { - kgdb_mem2hex((char *)mem, outbuffer, size); - outbuffer[size * 2] = 0; - } else + kgdb_mem2hex((char *) mem, outbuffer, size); + outbuffer[size*2] = 0; + } + else strcpy(outbuffer, "E0"); - return; } void kgdb_put_reg(char *inbuffer, char *outbuffer, int regnum, - struct unw_frame_info *info, struct pt_regs *ptregs) + struct unw_frame_info *info, struct pt_regs *ptregs) { unsigned long reg; - char nat = 0; struct ia64_fpreg freg; - int i; - char *ptr; + char *ptr = inbuffer; - ptr = inbuffer; kgdb_hex2long(&ptr, ®); strcpy(outbuffer, "OK"); - if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) || - (regnum >= (IA64_GR0_REGNUM + 4) && regnum <= (IA64_GR0_REGNUM + 7)) - || (regnum >= (IA64_GR0_REGNUM + 16) - && regnum <= (IA64_GR0_REGNUM + 31))) { - unw_access_gr(info, regnum - IA64_GR0_REGNUM, ®, &nat, 1); - } else - if ((regnum >= (IA64_GR0_REGNUM + 2) - && regnum <= (IA64_GR0_REGNUM + 3)) - || (regnum >= (IA64_GR0_REGNUM + 8) - && regnum <= (IA64_GR0_REGNUM + 15))) { - for (i = 0; - i < - (sizeof(gr_reg_to_ptreg_index) / - sizeof(gr_reg_to_ptreg_index[0])); i++) - if (gr_reg_to_ptreg_index[0].reg == regnum) { - *((unsigned long *) - (((void *)ptregs) + - gr_reg_to_ptreg_index[i].ptregoff)) = reg; - break; - } - } else if (regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7)) - switch (regnum) { - case IA64_BR0_REGNUM: - case IA64_BR0_REGNUM + 6: - case IA64_BR0_REGNUM + 7: - for (i = 0; i < (sizeof(br_reg_to_ptreg_index) / - sizeof(br_reg_to_ptreg_index[0])); i++) - if (br_reg_to_ptreg_index[i].reg == regnum) { - *((unsigned long *) - (((void *)ptregs) + - br_reg_to_ptreg_index[i].ptregoff)) = - reg; - break; - } - break; - case IA64_BR0_REGNUM + 1: - case IA64_BR0_REGNUM + 2: - case IA64_BR0_REGNUM + 3: - case IA64_BR0_REGNUM + 4: - case IA64_BR0_REGNUM + 5: - unw_access_br(info, regnum - IA64_BR0_REGNUM, ®, 1); - break; - } else if (regnum >= IA64_FR0_REGNUM - && regnum <= (IA64_FR0_REGNUM + 127)) - switch (regnum) { - case IA64_FR0_REGNUM + 6: - case IA64_FR0_REGNUM + 7: - case IA64_FR0_REGNUM + 8: - case IA64_FR0_REGNUM + 9: - case IA64_FR0_REGNUM + 10: - case IA64_FR0_REGNUM + 11: - case IA64_FR0_REGNUM + 12: - freg.u.bits[0] = reg; - kgdb_hex2long(&ptr, &freg.u.bits[1]); - *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) = - freg; - break; - default: - break; - } else if (regnum == IA64_IP_REGNUM) + if (kgdb_gr_reg(regnum, info, ®, 1) || + kgdb_gr_ptreg(regnum, ptregs, info, ®, 1) || + kgdb_br_reg(regnum, ptregs, info, ®, 1) || + kgdb_fr_reg(regnum, inbuffer, ptregs, info, ®, &freg, 1) || + kgdb_ar_reg(regnum, ptregs, info, ®, 1)) ; + else if (regnum == IA64_IP_REGNUM) ptregs->cr_iip = reg; else if (regnum == IA64_CFM_REGNUM) ptregs->cr_ifs = reg; @@ -371,40 +429,7 @@ void kgdb_put_reg(char *inbuffer, char * ptregs->cr_ipsr = reg; else if (regnum == IA64_PR_REGNUM) ptregs->pr = reg; - else if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM) - switch (regnum) { - case IA64_CSD_REGNUM: - ptregs->ar_csd = reg; - break; - case IA64_SSD_REGNUM: - ptregs->ar_ssd = reg; - case IA64_UNAT_REGNUM: - ptregs->ar_unat = reg; - case IA64_RNAT_REGNUM: - unw_access_ar(info, UNW_AR_RNAT, ®, 1); - break; - case IA64_BSPSTORE_REGNUM: - unw_access_ar(info, UNW_AR_BSPSTORE, ®, 1); - break; - case IA64_PFS_REGNUM: - unw_access_ar(info, UNW_AR_PFS, ®, 1); - break; - case IA64_LC_REGNUM: - unw_access_ar(info, UNW_AR_LC, ®, 1); - break; - case IA64_EC_REGNUM: - unw_access_ar(info, UNW_AR_EC, ®, 1); - break; - case IA64_FPSR_REGNUM: - ptregs->ar_fpsr = reg; - break; - case IA64_RSC_REGNUM: - ptregs->ar_rsc = reg; - break; - case IA64_CCV_REGNUM: - unw_access_ar(info, UNW_AR_CCV, ®, 1); - break; - } else + else strcpy(outbuffer, "E01"); return; @@ -765,7 +790,6 @@ static void inline kgdb_wait(struct pt_r if (hw_breakpoint_status & IA64_PSR_DB) ia64_setreg(_IA64_REG_PSR_L, hw_breakpoint_status); - touch_softlockup_watchdog(); return; } @@ -955,6 +979,35 @@ int kgdb_arch_handle_exception(int e_vec return info.ret; } +/* + * This is done because I evidently made an incorrect 'p' encoding + * when my patch for gdb was committed. It was later corrected. This + * check supports both my wrong encoding of the register number and + * the correct encoding. Eventually this should be eliminated and + * kgdb_hex2long should be demarshalling the regnum. + */ +static inline int check_packet(unsigned int regnum, char *packet) +{ + static int check_done, swap; + unsigned long reglong; + + if (likely(check_done)) { + if (swap) { + kgdb_hex2long(&packet, ®long); + regnum = (int) reglong; + } + + } else { + if (regnum > NUM_REGS) { + kgdb_hex2long(&packet, ®long); + regnum = (int) reglong; + swap = 1; + } + check_done = 1; + } + return regnum; +} + static void do_kgdb_handle_exception(struct unw_frame_info *unw_info, void *data) { @@ -982,10 +1035,11 @@ static void do_kgdb_handle_exception(str switch (remcom_in_buffer[0]) { case 'p': { - int regnum; + unsigned int regnum; kgdb_hex2mem(&remcom_in_buffer[1], (char *)®num, sizeof(regnum)); + regnum = check_packet(regnum, &remcom_in_buffer[1]); if (regnum >= NUM_REGS) { remcom_out_buffer[0] = 'E'; remcom_out_buffer[1] = 0; @@ -996,7 +1050,7 @@ static void do_kgdb_handle_exception(str } case 'P': { - int regno; + unsigned int regno; long v; char *ptr; @@ -1004,7 +1058,7 @@ static void do_kgdb_handle_exception(str if ((!kgdb_usethread || kgdb_usethread == current) && kgdb_hex2long(&ptr, &v) && *ptr++ == '=' && (v >= 0)) { - regno = (int)v; + regno = (unsigned int)v; regno = (regno >= NUM_REGS ? 0 : regno); kgdb_put_reg(ptr, remcom_out_buffer, regno, unw_info, linux_regs); @@ -1053,8 +1107,6 @@ static void do_kgdb_handle_exception(str linux_regs->cr_ipsr &= ~IA64_PSR_DB; } - if (atomic_read(&init_mm.mm_count) > 1) - touch_softlockup_watchdog(); info->ret = 0; break; default: ------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Do you grep through log files for problems? Stop! Download the new AJAX search engine that makes searching your log files as easy as surfing the web. DOWNLOAD SPLUNK! http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Re: kgdb on arm for 2.6: 00102, Lance Spaulding |
|---|---|
| Next by Date: | Re: SMP KGDB on ppc64?: 00102, Tom Rini |
| Previous by Thread: | Removed context.patch.i: 00102, Jitendra Pawar |
| Next by Thread: | [PATCH] align break instruction address in kgdb_set_sw_break: 00102, Bob Picco |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |