cdb for xen/ia64.
stolen from kgdb the routine which gets register value.
this includes a bug fix of kgdb/ia64.
Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
diff -r b1068ef4ffb0 -r 0722cc73a7a2 xen/arch/ia64/Makefile
--- a/xen/arch/ia64/Makefile Tue Jan 10 15:51:03 2006 +0900
+++ b/xen/arch/ia64/Makefile Tue Jan 10 15:59:11 2006 +0900
@@ -22,6 +22,10 @@
memset.o strlen.o memcpy_mck.o \
__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
+
+ifeq ($(crash_debug),y)
+OBJS += cdb.o
+endif
# xen stack unwinder
# unwind_decoder.c is included in unwind.c
diff -r b1068ef4ffb0 -r 0722cc73a7a2 xen/arch/ia64/vmx/vmx_process.c
--- a/xen/arch/ia64/vmx/vmx_process.c Tue Jan 10 15:51:03 2006 +0900
+++ b/xen/arch/ia64/vmx/vmx_process.c Tue Jan 10 15:59:11 2006 +0900
@@ -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,13 @@
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)) {
+ 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;
diff -r b1068ef4ffb0 -r 0722cc73a7a2 xen/arch/ia64/xen/hyperprivop.S
--- a/xen/arch/ia64/xen/hyperprivop.S Tue Jan 10 15:51:03 2006 +0900
+++ b/xen/arch/ia64/xen/hyperprivop.S Tue Jan 10 15:59:11 2006 +0900
@@ -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>
diff -r b1068ef4ffb0 -r 0722cc73a7a2 xen/arch/ia64/xen/ivt.S
--- a/xen/arch/ia64/xen/ivt.S Tue Jan 10 15:51:03 2006 +0900
+++ b/xen/arch/ia64/xen/ivt.S Tue Jan 10 15:59:11 2006 +0900
@@ -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
diff -r b1068ef4ffb0 -r 0722cc73a7a2 xen/arch/ia64/xen/process.c
--- a/xen/arch/ia64/xen/process.c Tue Jan 10 15:51:03 2006 +0900
+++ b/xen/arch/ia64/xen/process.c Tue Jan 10 15:59:11 2006 +0900
@@ -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);
@@ -662,7 +663,7 @@
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) {
@@ -673,7 +674,14 @@
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;
diff -r b1068ef4ffb0 -r 0722cc73a7a2 xen/arch/ia64/xen/xenmisc.c
--- a/xen/arch/ia64/xen/xenmisc.c Tue Jan 10 15:51:03 2006 +0900
+++ b/xen/arch/ia64/xen/xenmisc.c Tue Jan 10 15:59:11 2006 +0900
@@ -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);
@@ -357,6 +358,11 @@
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);
diff -r b1068ef4ffb0 -r 0722cc73a7a2 xen/include/asm-ia64/debugger.h
--- a/xen/include/asm-ia64/debugger.h Tue Jan 10 15:51:03 2006 +0900
+++ b/xen/include/asm-ia64/debugger.h Tue Jan 10 15:59:11 2006 +0900
@@ -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/debugger.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_cdb(regs);
+ 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 @@
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__ */
diff -r b1068ef4ffb0 -r 0722cc73a7a2 xen/arch/ia64/xen/cdb.c
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/xen/arch/ia64/xen/cdb.c Tue Jan 10 15:59:11 2006 +0900
@@ -0,0 +1,652 @@
+/*
+ * 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@xxxxxxxxxxx>
+ * Modified for 386 by Jim Kingdon, Cygnus Support.
+ * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe
<dave@xxxxxxxx>
+ *
+ */
+
+
+#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__)
+
+/* Like copy_from_user, but safe to call with interrupts disabled.
+ Trust me, and don't look behind the curtain. */
+unsigned
+xendbg_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;
+}
+
+int
+xendbg_arch_handle_register_read_command(struct cpu_user_regs *regs, struct
xendbg_context *ctx)
+{
+ return xendbg_send_reply("", ctx);
+}
+
+#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]);
+
+
+int
+xendbg_arch_handle_register_get_command(unsigned long regnum, struct
cpu_user_regs *regs, struct xendbg_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 xendbg_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;
+};
+struct reg_to_ptreg_index gr_reg_to_ptreg_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 + 14, ptoff(r14)},
+ {IA64_GR0_REGNUM + 15, ptoff(r15)},
+ {IA64_GR0_REGNUM + 2, ptoff(r2)},
+ {IA64_GR0_REGNUM + 3, ptoff(r3)},
+};
+
+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)},
+};
+
+extern atomic_t cpu_doing_single_step;
+
+#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 pt_fpreg* __freg)
+#endif
+{
+ unsigned long reg, size = 0, *mem = ®
+ char nat;
+#ifndef XEN
+ struct ia64_fpreg freg;
+#else
+ struct pt_fpreg freg;
+#endif
+ 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);
+ } 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[i].reg == regnum) {
+ reg = *((unsigned long *)
+ (((void *)ptregs) +
+ gr_reg_to_ptreg_index[i].ptregoff));
+ 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);
+ 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)
+#ifndef XEN
+ unw_access_fr(info, regnum - IA64_FR0_REGNUM,
+ &freg, 0);
+#else
+ //XXX struct ia64_fpreg and struct pt_fpreg are
same.
+ unw_access_fr(info, regnum - IA64_FR0_REGNUM,
+ (struct ia64_fpreg*)&freg, 0);
+#endif
+ else {
+ freg =
+ *(&ptregs->f6 +
+ (regnum - (IA64_FR0_REGNUM + 6)));
+ }
+ size = sizeof(freg);
+ mem = (unsigned long *)&freg;
+ break;
+ default:
+#ifndef XEN
+ unw_access_fr(info, regnum - IA64_FR0_REGNUM, &freg, 0);
+#else
+ //XXX struct ia64_fpreg and struct pt_fpreg are same.
+ unw_access_fr(info, regnum - IA64_FR0_REGNUM, (struct
ia64_fpreg*)&freg, 0);
+#endif
+ break;
+ } else if (regnum == IA64_IP_REGNUM) {
+ if (!ptregs)
+ unw_get_ip(info, ®);
+ else
+ reg = ptregs->cr_iip;
+ size = sizeof(reg);
+ } else if (regnum == IA64_CFM_REGNUM) {
+ if (!ptregs)
+ unw_get_cfm(info, ®);
+ 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, ®, 0);
+ size = sizeof(reg);
+ } 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;
+ }
+
+#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 xendbg_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
+xendbg_get_reg_callback(struct unw_frame_info* info, void* __arg)
+{
+ struct xendbg_callback_arg* arg = (struct xendbg_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;
+ }
+ if (kgdb_get_reg(arg->regnum, info, arg->regs, arg->reg, arg->freg) <
0) {
+ dbg_printk("%s: kgdb_get_reg failed\n", __func__);
+ arg->error = 1;
+ return;
+ }
+ arg->error = 0;
+ return;
+}
+
+int
+xendbg_arch_handle_register_get_command(unsigned long regnum,
+
struct cpu_user_regs *regs,
+
struct xendbg_context *ctx)
+{
+ struct xendbg_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 = ®
+ arg.freg = &freg;
+ arg.error = 0;
+ unw_init_running(&xendbg_get_reg_callback, (void*)&arg);
+ if (arg.error < 0) {
+ dbg_printk("%s: xendbg_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 xendbg_send_reply(buf, ctx);
+
+out_err:
+ dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum);
+ sprintf(buf, "%s", "E0");
+ goto out;
+}
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--
yamahata
8478:0722cc73a7a2.patch
Description: Text document
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|