[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] ia64 specific part of gdbstub.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 34f2b388beb0c89b4f2edb04239d2fac41d760f5
# Parent  d270db8a909266d2dd37b98708f92352b8ed7b4e
ia64 specific part of gdbstub.

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

diff -r d270db8a9092 -r 34f2b388beb0 xen/arch/ia64/Makefile
--- a/xen/arch/ia64/Makefile    Mon Jan 23 14:17:14 2006
+++ b/xen/arch/ia64/Makefile    Mon Jan 23 14:47:00 2006
@@ -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 d270db8a9092 -r 34f2b388beb0 xen/arch/ia64/vmx/vmx_process.c
--- a/xen/arch/ia64/vmx/vmx_process.c   Mon Jan 23 14:17:14 2006
+++ b/xen/arch/ia64/vmx/vmx_process.c   Mon Jan 23 14:47:00 2006
@@ -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 d270db8a9092 -r 34f2b388beb0 xen/arch/ia64/xen/hyperprivop.S
--- a/xen/arch/ia64/xen/hyperprivop.S   Mon Jan 23 14:17:14 2006
+++ b/xen/arch/ia64/xen/hyperprivop.S   Mon Jan 23 14:47:00 2006
@@ -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 d270db8a9092 -r 34f2b388beb0 xen/arch/ia64/xen/ivt.S
--- a/xen/arch/ia64/xen/ivt.S   Mon Jan 23 14:17:14 2006
+++ b/xen/arch/ia64/xen/ivt.S   Mon Jan 23 14:47:00 2006
@@ -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 d270db8a9092 -r 34f2b388beb0 xen/arch/ia64/xen/process.c
--- a/xen/arch/ia64/xen/process.c       Mon Jan 23 14:17:14 2006
+++ b/xen/arch/ia64/xen/process.c       Mon Jan 23 14:47:00 2006
@@ -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 d270db8a9092 -r 34f2b388beb0 xen/arch/ia64/xen/xenmisc.c
--- a/xen/arch/ia64/xen/xenmisc.c       Mon Jan 23 14:17:14 2006
+++ b/xen/arch/ia64/xen/xenmisc.c       Mon Jan 23 14:47:00 2006
@@ -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 d270db8a9092 -r 34f2b388beb0 xen/include/asm-ia64/debugger.h
--- a/xen/include/asm-ia64/debugger.h   Mon Jan 23 14:17:14 2006
+++ b/xen/include/asm-ia64/debugger.h   Mon Jan 23 14:47:00 2006
@@ -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 d270db8a9092 -r 34f2b388beb0 xen/arch/ia64/xen/gdbstub.c
--- /dev/null   Mon Jan 23 14:17:14 2006
+++ b/xen/arch/ia64/xen/gdbstub.c       Mon Jan 23 14:47:00 2006
@@ -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:
+ */

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.