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-devel

[Xen-devel] [PATCH] gdbstub for xen/ia64 (was Re: [Xen-ia64-devel] [PATC

To: xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] gdbstub for xen/ia64 (was Re: [Xen-ia64-devel] [PATCH] cdb for xen/ia64)
From: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Date: Mon, 23 Jan 2006 16:55:51 +0900
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx
Delivery-date: Mon, 23 Jan 2006 08:04:21 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <20060110073813.GH9291@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> <20060110073813.GH9291@xxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.4.2.1i

gdbstub for xen/ia64
catched up recent common gdbstub and kgdb/ia64.

# HG changeset patch
# User yamahata@xxxxxxxxxxxxx
# Node ID aeebe099dae6d13beebd8c879dc011d5a1e4ff78
# Parent  ea582eba5cd2bc3edc3c1dd7416a902c574602d2
ia64 specific part of gdbstub.

Signed-off-by: Isaku Yamahtata <yamahata@xxxxxxxxxxxxx>

diff -r ea582eba5cd2 -r aeebe099dae6 xen/arch/ia64/Makefile
--- a/xen/arch/ia64/Makefile    Mon Jan 23 12:25:55 2006 +0900
+++ b/xen/arch/ia64/Makefile    Mon Jan 23 16:46:19 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 += gdbstub.o
+endif
 
 # xen stack unwinder
 # unwind_decoder.c is included in unwind.c
diff -r ea582eba5cd2 -r aeebe099dae6 xen/arch/ia64/vmx/vmx_process.c
--- a/xen/arch/ia64/vmx/vmx_process.c   Mon Jan 23 12:25:55 2006 +0900
+++ b/xen/arch/ia64/vmx/vmx_process.c   Mon Jan 23 16:46:19 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,14 @@
                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;
diff -r ea582eba5cd2 -r aeebe099dae6 xen/arch/ia64/xen/hyperprivop.S
--- a/xen/arch/ia64/xen/hyperprivop.S   Mon Jan 23 12:25:55 2006 +0900
+++ b/xen/arch/ia64/xen/hyperprivop.S   Mon Jan 23 16:46:19 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>
 
 
@@ -549,7 +550,12 @@
 (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];;
diff -r ea582eba5cd2 -r aeebe099dae6 xen/arch/ia64/xen/ivt.S
--- a/xen/arch/ia64/xen/ivt.S   Mon Jan 23 12:25:55 2006 +0900
+++ b/xen/arch/ia64/xen/ivt.S   Mon Jan 23 16:46:19 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
@@ -841,6 +842,13 @@
        ;;
        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]
diff -r ea582eba5cd2 -r aeebe099dae6 xen/arch/ia64/xen/process.c
--- a/xen/arch/ia64/xen/process.c       Mon Jan 23 12:25:55 2006 +0900
+++ b/xen/arch/ia64/xen/process.c       Mon Jan 23 16:46:19 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);
@@ -652,7 +653,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) {
@@ -663,7 +664,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 ea582eba5cd2 -r aeebe099dae6 xen/arch/ia64/xen/xenmisc.c
--- a/xen/arch/ia64/xen/xenmisc.c       Mon Jan 23 12:25:55 2006 +0900
+++ b/xen/arch/ia64/xen/xenmisc.c       Mon Jan 23 16:46:19 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);
@@ -356,6 +357,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 ea582eba5cd2 -r aeebe099dae6 xen/common/Makefile
--- a/xen/common/Makefile       Mon Jan 23 12:25:55 2006 +0900
+++ b/xen/common/Makefile       Mon Jan 23 16:46:19 2006 +0900
@@ -3,6 +3,9 @@
 
 ifneq ($(perfc),y)
 OBJS := $(subst perfc.o,,$(OBJS))
+endif
+ifneq ($(crash_debug),y)
+OBJS := $(patsubst cdb.o,,$(OBJS))
 endif
 ifneq ($(crash_debug),y)
 OBJS := $(patsubst gdbstub.o,,$(OBJS))
diff -r ea582eba5cd2 -r aeebe099dae6 xen/include/asm-ia64/debugger.h
--- a/xen/include/asm-ia64/debugger.h   Mon Jan 23 12:25:55 2006 +0900
+++ b/xen/include/asm-ia64/debugger.h   Mon Jan 23 16:46:19 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/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 @@
     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 ea582eba5cd2 -r aeebe099dae6 xen/arch/ia64/xen/gdbstub.c
--- /dev/null   Thu Jan  1 00:00:00 1970 +0000
+++ b/xen/arch/ia64/xen/gdbstub.c       Mon Jan 23 16:46:19 2006 +0900
@@ -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@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__)
+
+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:
+ */



-- 
yamahata

Attachment: gdbstub_ia64.patch
Description: Text document

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