WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ia64-devel

[Xen-devel] [PATCH] cdb for xen/ia64

To: xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] cdb for xen/ia64
From: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Date: Tue, 10 Jan 2006 16:38:13 +0900
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx
Delivery-date: Tue, 10 Jan 2006 07:44:32 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <20060110073119.GG9291@xxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <20060110073119.GG9291@xxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.4.2.1i
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 = &reg;
+       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, &reg, &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, &reg,
+                                     &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,
+                                             &reg, 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, &reg, 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, &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);
+       } 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, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_SSD_REGNUM:
+                       if (ptregs)
+                               reg = ptregs->ar_ssd;
+                       else
+                               unw_access_ar(info, UNW_AR_SSD, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_UNAT_REGNUM:
+                       if (ptregs)
+                               reg = ptregs->ar_unat;
+                       else
+                               unw_access_ar(info, UNW_AR_UNAT, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_RNAT_REGNUM:
+                       unw_access_ar(info, UNW_AR_RNAT, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_BSPSTORE_REGNUM:
+                       unw_access_ar(info, UNW_AR_BSPSTORE, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_PFS_REGNUM:
+                       unw_access_ar(info, UNW_AR_PFS, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_LC_REGNUM:
+                       unw_access_ar(info, UNW_AR_LC, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_EC_REGNUM:
+                       unw_access_ar(info, UNW_AR_EC, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_FPSR_REGNUM:
+                       if (ptregs)
+                               reg = ptregs->ar_fpsr;
+                       else
+                               unw_access_ar(info, UNW_AR_FPSR, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_RSC_REGNUM:
+                       if (ptregs)
+                               reg = ptregs->ar_rsc;
+                       else
+                               unw_access_ar(info, UNW_AR_RNAT, &reg, 0);
+                       size = sizeof(reg);
+                       break;
+               case IA64_CCV_REGNUM:
+                       unw_access_ar(info, UNW_AR_CCV, &reg, 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 = &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

Attachment: 8478:0722cc73a7a2.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel