ia64 specific part of gdbstub.

Signed-off-by: Isaku Yamahtata <yamahata@valinux.co.jp>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2006-01-23 15:47:00 +01:00
1 parent 5a132f7674
commit e3f67392ec
8 files changed
+921 -4

No files matched your search

+4
View File
@@ -23,6 +23,10 @@ OBJS += bitop.o clear_page.o flush.o copy_page_mck.o \
__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
ifeq ($(crash_debug),y)
OBJS += gdbstub.o
endif
# xen stack unwinder
# unwind_decoder.c is included in unwind.c
OBJS += unwind.o
+9
View File
@@ -41,6 +41,7 @@
#include <asm/regionreg.h>
#include <asm/privop.h>
#include <asm/ia64_int.h>
#include <asm/debugger.h>
//#include <asm/hpsim_ssc.h>
#include <asm/dom_fw.h>
#include <asm/vmx_vcpu.h>
@@ -107,6 +108,14 @@ vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long is
if (running_on_sim) do_ssc(vcpu_get_gr_nat(current,36), regs);
else do_ssc(vcpu_get_gr_nat(current,36), regs);
}
#endif
#ifdef CRASH_DEBUG
if ((iim == 0 || iim == CDB_BREAK_NUM) && !user_mode(regs) &&
IS_VMM_ADDRESS(regs->cr_iip)) {
if (iim == 0)
show_registers(regs);
debugger_trap_fatal(0 /* don't care */, regs);
} else
#endif
if (iim == d->arch.breakimm) {
struct ia64_pal_retval y;
+811
View File
@@ -0,0 +1,811 @@
/*
* ia64-specific cdb routines
* cdb xen/ia64 by Isaku Yamahta <yamahata at valinux co jp>
* VA Linux Systems Japan K.K.
* some routines are stolen from kgdb/ia64.
*/
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
/*
* Copyright (C) 2000-2001 VERITAS Software Corporation.
*/
/*
* Contributor: Lake Stevens Instrument Division$
* Written by: Glenn Engel $
* Updated by: Amit Kale<akale@veritas.com>
* Modified for 386 by Jim Kingdon, Cygnus Support.
* Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
*
*/
#include <xen/lib.h>
#include <asm/byteorder.h>
#include <asm/debugger.h>
#include <asm/uaccess.h>
#define USE_UNWIND
#ifdef USE_UNWIND
#include <asm/unwind.h>
#endif
/* Printk isn't particularly safe just after we've trapped to the
debugger. so avoid it. */
#define dbg_printk(...)
//#define dbg_printk(...) printk(__VA_ARGS__)
u16
gdb_arch_signal_num(struct cpu_user_regs *regs, unsigned long cookie)
{
/* XXX */
return 1;
}
void
gdb_arch_read_reg_array(struct cpu_user_regs *regs, struct gdb_context *ctx)
{
gdb_send_reply("", ctx);
}
void
gdb_arch_write_reg_array(struct cpu_user_regs *regs, const char* buf,
struct gdb_context *ctx)
{
/* XXX TODO */
gdb_send_reply("E02", ctx);
}
/* Like copy_from_user, but safe to call with interrupts disabled.
Trust me, and don't look behind the curtain. */
unsigned
gdb_arch_copy_from_user(void *dest, const void *src, unsigned len)
{
int val;
__asm__ __volatile__(
"cmp4.eq p6, p0 = r0, %1\n"
"(p6) br.cond.dptk 2f\n"
"[1:]\n"
".xdata4 \"__ex_table\", 99f-., 2f-.;\n"
"[99:] ld1 %0 = [%3], 1\n"
";;\n"
".xdata4 \"__ex_table\", 99f-., 2f-.;\n"
"[99:] st1 [%2] = %0, 1\n"
"adds %1 = -1, %1\n"
";;\n"
"cmp4.eq p0, p6 = r0, %1\n"
"(p6) br.cond.dptk 1b\n"
"[2:]\n"
: "=r"(val), "=r"(len), "=r"(dest), "=r"(src)
: "1"(len), "2"(dest), "3"(src)
: "memory", "p6");
return len;
}
unsigned int
gdb_arch_copy_to_user(void *dest, const void *src, unsigned len)
{
/* XXX */
return len;
}
#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 IA64_GR0_REGNUM 0
#define IA64_FR0_REGNUM 128
#define IA64_FR127_REGNUM (IA64_FR0_REGNUM+127)
#define IA64_PR0_REGNUM 256
#define IA64_BR0_REGNUM 320
#define IA64_VFP_REGNUM 328
#define IA64_PR_REGNUM 330
#define IA64_IP_REGNUM 331
#define IA64_PSR_REGNUM 332
#define IA64_CFM_REGNUM 333
#define IA64_AR0_REGNUM 334
#define IA64_NAT0_REGNUM 462
#define IA64_NAT31_REGNUM (IA64_NAT0_REGNUM+31)
#define IA64_NAT32_REGNUM (IA64_NAT0_REGNUM+32)
#define IA64_RSC_REGNUM (IA64_AR0_REGNUM+16)
#define IA64_BSP_REGNUM (IA64_AR0_REGNUM+17)
#define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM+18)
#define IA64_RNAT_REGNUM (IA64_AR0_REGNUM+19)
#define IA64_FCR_REGNUM (IA64_AR0_REGNUM+21)
#define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM+24)
#define IA64_CSD_REGNUM (IA64_AR0_REGNUM+25)
#define IA64_SSD_REGNUM (IA64_AR0_REGNUM+26)
#define IA64_CFLG_REGNUM (IA64_AR0_REGNUM+27)
#define IA64_FSR_REGNUM (IA64_AR0_REGNUM+28)
#define IA64_FIR_REGNUM (IA64_AR0_REGNUM+29)
#define IA64_FDR_REGNUM (IA64_AR0_REGNUM+30)
#define IA64_CCV_REGNUM (IA64_AR0_REGNUM+32)
#define IA64_UNAT_REGNUM (IA64_AR0_REGNUM+36)
#define IA64_FPSR_REGNUM (IA64_AR0_REGNUM+40)
#define IA64_ITC_REGNUM (IA64_AR0_REGNUM+44)
#define IA64_PFS_REGNUM (IA64_AR0_REGNUM+64)
#define IA64_LC_REGNUM (IA64_AR0_REGNUM+65)
#define IA64_EC_REGNUM (IA64_AR0_REGNUM+66)
#ifndef USE_UNWIND
struct regs_to_cpu_user_resgs_index {
unsigned int reg;
unsigned int ptregoff;
};
#define ptoff(V) ((unsigned int)&((struct cpu_user_regs*)0x0)->V)
// gr
static const struct regs_to_cpu_user_resgs_index
gr_reg_to_cpu_user_regs_index[] = {
{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 + 15, ptoff(r15)},
{IA64_GR0_REGNUM + 14, ptoff(r14)},
{IA64_GR0_REGNUM + 2, ptoff(r2)},
{IA64_GR0_REGNUM + 3, ptoff(r3)},
{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)},
{IA64_GR0_REGNUM + 4, ptoff(r4)},
{IA64_GR0_REGNUM + 5, ptoff(r5)},
{IA64_GR0_REGNUM + 6, ptoff(r6)},
{IA64_GR0_REGNUM + 7, ptoff(r7)},
};
static const int gr_reg_to_cpu_user_regs_index_max =
sizeof(gr_reg_to_cpu_user_regs_index) /
sizeof(gr_reg_to_cpu_user_regs_index[0]);
// br
static const struct regs_to_cpu_user_resgs_index
br_reg_to_cpu_user_regs_index[] = {
{IA64_BR0_REGNUM + 0, ptoff(b0)},
{IA64_BR0_REGNUM + 6, ptoff(b6)},
{IA64_BR0_REGNUM + 7, ptoff(b7)},
};
static const int br_reg_to_cpu_user_regs_index_max =
sizeof(br_reg_to_cpu_user_regs_index) /
sizeof(br_reg_to_cpu_user_regs_index[0]);
// f
static const struct regs_to_cpu_user_resgs_index
fr_reg_to_cpu_user_regs_index[] = {
{IA64_FR0_REGNUM + 6, ptoff(f6)},
{IA64_FR0_REGNUM + 7, ptoff(f7)},
{IA64_FR0_REGNUM + 8, ptoff(f8)},
{IA64_FR0_REGNUM + 9, ptoff(f9)},
{IA64_FR0_REGNUM + 10, ptoff(f10)},
{IA64_FR0_REGNUM + 11, ptoff(f11)},
};
static const int fr_reg_to_cpu_user_regs_index_max =
sizeof(fr_reg_to_cpu_user_regs_index) /
sizeof(fr_reg_to_cpu_user_regs_index[0]);
void
gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs,
struct gdb_context *ctx)
{
unsigned long reg = IA64_IP_REGNUM;
char buf[9];
int i;
dbg_printk("Register read regnum = 0x%lx\n", regnum);
if (IA64_GR0_REGNUM <= regnum && regnum <= IA64_GR0_REGNUM + 31) {
for (i = 0; i < gr_reg_to_cpu_user_regs_index_max; i++) {
if (gr_reg_to_cpu_user_regs_index[i].reg == regnum) {
reg = *(unsigned long*)(((char*)regs) + gr_reg_to_cpu_user_regs_index[i].ptregoff);
break;
}
}
if (i == gr_reg_to_cpu_user_regs_index_max) {
goto out_err;
}
} else if (IA64_BR0_REGNUM <= regnum && regnum <= IA64_BR0_REGNUM + 7) {
for (i = 0; i < br_reg_to_cpu_user_regs_index_max; i++) {
if (br_reg_to_cpu_user_regs_index[i].reg == regnum) {
reg = *(unsigned long*)(((char*)regs) + br_reg_to_cpu_user_regs_index[i].ptregoff);
break;
}
}
if (i == br_reg_to_cpu_user_regs_index_max) {
goto out_err;
}
} else if (IA64_FR0_REGNUM + 6 <= regnum && regnum <= IA64_FR0_REGNUM + 11) {
for (i = 0; i < fr_reg_to_cpu_user_regs_index_max; i++) {
if (fr_reg_to_cpu_user_regs_index[i].reg == regnum) {
reg = *(unsigned long*)(((char*)regs) + fr_reg_to_cpu_user_regs_index[i].ptregoff);
break;
}
}
if (i == fr_reg_to_cpu_user_regs_index_max) {
goto out_err;
}
} else if (regnum == IA64_CSD_REGNUM) {
reg = regs->ar_csd;
} else if (regnum == IA64_SSD_REGNUM) {
reg = regs->ar_ssd;
} else if (regnum == IA64_PSR_REGNUM) {
reg = regs->cr_ipsr;
} else if (regnum == IA64_IP_REGNUM) {
reg = regs->cr_iip;
} else if (regnum == IA64_CFM_REGNUM) {
reg = regs->cr_ifs;
} else if (regnum == IA64_UNAT_REGNUM) {
reg = regs->ar_unat;
} else if (regnum == IA64_PFS_REGNUM) {
reg = regs->ar_pfs;
} else if (regnum == IA64_RSC_REGNUM) {
reg = regs->ar_rsc;
} else if (regnum == IA64_RNAT_REGNUM) {
reg = regs->ar_rnat;
} else if (regnum == IA64_BSPSTORE_REGNUM) {
reg = regs->ar_bspstore;
} else if (regnum == IA64_PR_REGNUM) {
reg = regs->pr;
} else if (regnum == IA64_FPSR_REGNUM) {
reg = regs->ar_fpsr;
} else if (regnum == IA64_CCV_REGNUM) {
reg = regs->ar_ccv;
} else {
// emul_unat, rfi_pfs
goto out_err;
}
dbg_printk("Register read regnum = 0x%lx, val = 0x%lx\n", regnum, reg);
sprintf(buf, "%.08lx", swab64(reg));
out:
return gdb_send_reply(buf, ctx);
out_err:
dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum);
sprintf(buf, "%s", "x");
goto out;
}
#else
#define ptoff(V) ((unsigned int) &((struct pt_regs *)0x0)->V)
struct reg_to_ptreg_index {
unsigned int reg;
unsigned int ptregoff;
};
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 + 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)},
};
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)},
};
#ifndef XEN
extern atomic_t cpu_doing_single_step;
#endif
static int kgdb_gr_reg(int regnum, struct unw_frame_info *info,
unsigned long *reg, int rw)
{
char nat;
if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) ||
(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
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
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) {
#ifndef XEN
char *ptr = inbuffer;
freg->u.bits[0] = *reg;
kgdb_hex2long(&ptr, &freg->u.bits[1]);
*(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) =
*freg;
#else
printk("%s: %d: writing to fpreg is not supported.\n",
__func__, __LINE__);
#endif
break;
} else if (!ptregs)
result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
freg, rw);
else
#ifndef XEN
*freg =
*(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6)));
#else
//XXX struct ia64_fpreg and struct pt_fpreg are same.
*freg = *((struct ia64_fpreg*)(&ptregs->f6 +
(regnum - (IA64_FR0_REGNUM + 6))));
#endif
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;
}
} 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;
}
#ifndef XEN
void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info,
struct pt_regs *ptregs)
#else
static int
kgdb_get_reg(int regnum, struct unw_frame_info *info,
struct cpu_user_regs* ptregs,
unsigned long* __reg, struct ia64_fpreg* __freg)
#endif
{
unsigned long reg, size = 0, *mem = &reg;
struct ia64_fpreg freg;
if (kgdb_gr_reg(regnum, info, &reg, 0) ||
kgdb_gr_ptreg(regnum, ptregs, info, &reg, 0) ||
kgdb_br_reg(regnum, ptregs, info, &reg, 0) ||
kgdb_ar_reg(regnum, ptregs, info, &reg, 0))
size = sizeof(reg);
else if (kgdb_fr_reg(regnum, NULL, ptregs, info, &reg, &freg, 0)) {
size = sizeof(freg);
mem = (unsigned long *)&freg;
} else if (regnum == IA64_IP_REGNUM) {
if (!ptregs) {
unw_get_ip(info, &reg);
size = sizeof(reg);
} else {
reg = ptregs->cr_iip;
size = sizeof(reg);
}
} else if (regnum == IA64_CFM_REGNUM) {
if (!ptregs)
unw_get_cfm(info, &reg);
else
reg = ptregs->cr_ifs;
size = sizeof(reg);
} else if (regnum == IA64_PSR_REGNUM) {
#ifndef XEN
if (!ptregs && kgdb_usethread)
ptregs = (struct pt_regs *)
((unsigned long)kgdb_usethread +
IA64_STK_OFFSET) - 1;
#endif
if (ptregs)
reg = ptregs->cr_ipsr;
size = sizeof(reg);
} else if (regnum == IA64_PR_REGNUM) {
if (ptregs)
reg = ptregs->pr;
else
unw_access_pr(info, &reg, 0);
size = sizeof(reg);
} else if (regnum == IA64_BSP_REGNUM) {
unw_get_bsp(info, &reg);
size = sizeof(reg);
}
#ifndef XEN
if (size) {
kgdb_mem2hex((char *) mem, outbuffer, size);
outbuffer[size*2] = 0;
}
else
strcpy(outbuffer, "E0");
return;
#else
if (size) {
if (size == sizeof(reg)) {
*__reg = reg;
} else {
BUG_ON(size != sizeof(freg));
*__freg = freg;
}
return 0;
}
return -1;
#endif
}
#ifndef XEN
static int inline kgdb_get_blocked_state(struct task_struct *p,
struct unw_frame_info *unw)
#else
static int
kgdb_get_blocked_state(struct vcpu *p,
struct cpu_user_regs *regs,
struct unw_frame_info *unw)
#endif
{
unsigned long ip;
int count = 0;
#ifndef XEN
unw_init_from_blocked_task(unw, p);
#endif
ip = 0UL;
do {
if (unw_unwind(unw) < 0)
return -1;
unw_get_ip(unw, &ip);
#ifndef XEN
if (!in_sched_functions(ip))
break;
#else
dbg_printk("ip 0x%lx cr_iip 0x%lx\n", ip, regs->cr_iip);
if (ip == regs->cr_iip)
break;
#endif
} while (count++ < 16);
if (!ip)
return -1;
else
return 0;
}
struct gdb_callback_arg
{
struct cpu_user_regs* regs;
unsigned long regnum;
unsigned long* reg;
struct pt_fpreg* freg;
int error;
// 1: not supported
// 0: success
// -1: failure
};
static void
gdb_get_reg_callback(struct unw_frame_info* info, void* __arg)
{
struct gdb_callback_arg* arg = (struct gdb_callback_arg*)__arg;
if (kgdb_get_blocked_state(current, arg->regs, info) < 0) {
dbg_printk("%s: kgdb_get_blocked_state failed\n", __func__);
arg->error = -1;
return;
}
//XXX struct ia64_fpreg and struct pt_fpreg are same.
if (kgdb_get_reg(arg->regnum, info, arg->regs, arg->reg,
(struct ia64_fpreg*)arg->freg) < 0) {
dbg_printk("%s: kgdb_get_reg failed\n", __func__);
arg->error = 1;
return;
}
arg->error = 0;
return;
}
void
gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs,
struct gdb_context *ctx)
{
struct gdb_callback_arg arg;
unsigned long reg;
struct pt_fpreg freg;
char buf[16 * 2 + 1];
if (regnum >= NUM_REGS) {
dbg_printk("%s: regnum %ld\n", __func__, regnum);
goto out_err;
}
arg.regs = regs;
arg.regnum = regnum;
arg.reg = &reg;
arg.freg = &freg;
arg.error = 0;
unw_init_running(&gdb_get_reg_callback, (void*)&arg);
if (arg.error < 0) {
dbg_printk("%s: gdb_get_reg_callback failed\n", __func__);
goto out_err;
}
if (arg.error > 0) {
// notify gdb that this register is not supported.
// see fetch_register_using_p() in gdb/remote.c.
sprintf(buf, "%s", "x");
} else if (IA64_FR0_REGNUM <= regnum && regnum <= IA64_FR0_REGNUM + 127) {
sprintf(buf, "%.016lx", swab64(freg.u.bits[0]));
sprintf(buf + 16, "%.016lx", swab64(freg.u.bits[1]));
} else {
sprintf(buf, "%.016lx", swab64(reg));
}
out:
return gdb_send_reply(buf, ctx);
out_err:
dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum);
sprintf(buf, "%s", "E0");
goto out;
}
#endif
void
gdb_arch_resume(struct cpu_user_regs *regs,
unsigned long addr, unsigned long type,
struct gdb_context *ctx)
{
/* XXX */
if (type == GDB_STEP) {
gdb_send_reply("S01", ctx);
}
}
void
gdb_arch_print_state(struct cpu_user_regs *regs)
{
/* XXX */
}
void
gdb_arch_enter(struct cpu_user_regs *regs)
{
/* nothing */
}
void
gdb_arch_exit(struct cpu_user_regs *regs)
{
/* nothing */
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* End:
*/
+7 -1
View File
@@ -12,6 +12,7 @@
#include <asm/offsets.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/debugger.h>
#include <public/arch-ia64.h>
@@ -549,7 +550,12 @@ GLOBAL_ENTRY(fast_break_reflect)
(p7) br.spnt.many 1f ;;
cmp.eq p7,p0=r17,r0
(p7) br.spnt.few dispatch_break_fault ;;
1:
#ifdef CRASH_DEBUG
movl r21=CDB_BREAK_NUM ;;
cmp.eq p7,p0=r17,r21
(p7) br.spnt.few dispatch_break_fault ;;
#endif
1:
#if 1 /* special handling in case running on simulator */
movl r20=first_break;;
ld4 r23=[r20];;
+8
View File
@@ -15,6 +15,7 @@
#define sys_call_table 0
#define sys_ni_syscall 0
#include <asm/vhpt.h>
#include <asm/debugger.h>
#endif
/*
* arch/ia64/kernel/ivt.S
@@ -841,6 +842,13 @@ ENTRY(break_fault)
;;
cmp.eq p7,p0=r17,r0
(p7) br.spnt.few dispatch_break_fault ;;
#ifdef CRASH_DEBUG
// panic can occur before domain0 is created.
// in such case referencing XSI_PSR_IC causes nested_dtlb_miss
movl r18=CDB_BREAK_NUM ;;
cmp.eq p7,p0=r17,r18 ;;
(p7) br.spnt.few dispatch_break_fault ;;
#endif
movl r18=XSI_PSR_IC
;;
ld8 r19=[r18]
+10 -2
View File
@@ -31,6 +31,7 @@
#include <asm/dom_fw.h>
#include "hpsim_ssc.h"
#include <xen/multicall.h>
#include <asm/debugger.h>
extern unsigned long vcpu_get_itir_on_fault(struct vcpu *, UINT64);
extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
@@ -652,7 +653,7 @@ void
ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long iim)
{
struct domain *d = (struct domain *) current->domain;
struct vcpu *v = (struct domain *) current;
struct vcpu *v = current;
extern unsigned long running_on_sim;
if (first_break) {
@@ -663,7 +664,14 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, u
if (iim == 0x80001 || iim == 0x80002) { //FIXME: don't hardcode constant
if (running_on_sim) do_ssc(vcpu_get_gr(current,36), regs);
else do_ssc(vcpu_get_gr(current,36), regs);
}
}
#ifdef CRASH_DEBUG
else if ((iim == 0 || iim == CDB_BREAK_NUM) && !user_mode(regs)) {
if (iim == 0)
show_registers(regs);
debugger_trap_fatal(0 /* don't care */, regs);
}
#endif
else if (iim == d->arch.breakimm) {
/* by default, do not continue */
v->arch.hypercall_continuation = 0;
+6
View File
@@ -18,6 +18,7 @@
#include <xen/softirq.h>
#include <public/sched.h>
#include <asm/vhpt.h>
#include <asm/debugger.h>
efi_memory_desc_t ia64_efi_io_md;
EXPORT_SYMBOL(ia64_efi_io_md);
@@ -356,6 +357,11 @@ loop:
va_end(args);
printf(buf);
if (regs) show_registers(regs);
if (regs) {
debugger_trap_fatal(0 /* don't care */, regs);
} else {
debugger_trap_immediate();
}
domain_pause_by_systemcontroller(current->domain);
v->domain->shutdown_code = SHUTDOWN_crash;
set_bit(_DOMF_shutdown, v->domain->domain_flags);
+66 -1
View File
@@ -24,6 +24,54 @@
#include <xen/softirq.h>
// this number is an arbitary number which is not used for any other purpose
// __builtin_trap(), FORCE_CRASH() 0x0
// ski 0x80001, 0x80002
// kdb 0x80100, 0x80101
// kprobe 0x80200, jprobe 0x80300
// kgdb 0x6665
// gdb 0x99998 (#define IA64_BREAKPOINT 0x00003333300LL)
// cdb should handle 0 and CDB_BREAK_NUM.
#define CDB_BREAK_NUM 0x80800
#ifndef __ASSEMBLY__
#include <xen/gdbstub.h>
// NOTE: on xen struct pt_regs = struct cpu_user_regs
// see include/asm-ia64/linux-xen/asm/ptrace.h
#ifdef CRASH_DEBUG
// crash_debug=y
/* The main trap handlers use these helper macros which include early bail. */
static inline int debugger_trap_entry(
unsigned int vector, struct cpu_user_regs *regs)
{
return 0;
}
extern int __trap_to_cdb(struct cpu_user_regs *r);
static inline int debugger_trap_fatal(
unsigned int vector, struct cpu_user_regs *regs)
{
(void)__trap_to_gdb(regs, vector);
return 0;
}
#define ____debugger_trap_immediate(b) __asm__ __volatile__ ("break.m "#b"\n")
#define __debugger_trap_immediate(b) ____debugger_trap_immediate(b)
#define debugger_trap_immediate() __debugger_trap_immediate(CDB_BREAK_NUM)
//XXX temporal work around
#ifndef CONFIG_SMP
#define smp_send_stop() /* nothing */
#endif
#elif defined DOMU_DEBUG
// domu_debug=y
#warning "domu_debug is not implemented yet."
/* The main trap handlers use these helper macros which include early bail. */
static inline int debugger_trap_entry(
unsigned int vector, struct cpu_user_regs *regs)
@@ -37,6 +85,23 @@ static inline int debugger_trap_fatal(
return 0;
}
#define debugger_trap_immediate() do {} while(0)
#define debugger_trap_immediate() ((void)0)
#else
/* The main trap handlers use these helper macros which include early bail. */
static inline int debugger_trap_entry(
unsigned int vector, struct cpu_user_regs *regs)
{
return 0;
}
static inline int debugger_trap_fatal(
unsigned int vector, struct cpu_user_regs *regs)
{
return 0;
}
#define debugger_trap_immediate() ((void)0)
#endif
#endif // __ASSEMBLLY__
#endif /* __ASM_DEBUGGER_H__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.