This patch enables hardware breakpoints and debugging kernel early
before slab is initialized and cpu local data has been established.

Signed-off-by: Bob Picco <[EMAIL PROTECTED]>

 arch/ia64/kernel/entry.S   |    4 +-
 arch/ia64/kernel/ivt.S     |   16 ++++++++
 arch/ia64/kernel/process.c |    6 +++
 arch/ia64/kernel/unwind.c  |   87 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 111 insertions(+), 2 deletions(-)

Index: linux-2.6.17-rc3-kgdb/arch/ia64/kernel/process.c
===================================================================
--- linux-2.6.17-rc3-kgdb.orig/arch/ia64/kernel/process.c       2006-05-01 
13:55:27.000000000 -0400
+++ linux-2.6.17-rc3-kgdb/arch/ia64/kernel/process.c    2006-05-01 
13:56:11.000000000 -0400
@@ -459,6 +459,9 @@ copy_thread (int nr, unsigned long clone
         */
        child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
                                 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | 
IA64_PSR_UP));
+#ifdef CONFIG_KGDB
+       child_ptregs->cr_ipsr |= IA64_PSR_DB;
+#endif
 
        /*
         * NOTE: The calling convention considers all floating point
@@ -687,6 +690,9 @@ kernel_thread (int (*fn)(void *), void *
        regs.pt.r11 = (unsigned long) arg;      /* 2nd argument */
        /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't 
read.  */
        regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
+#ifdef CONFIG_KGDB
+       regs.pt.cr_ipsr |= IA64_PSR_DB;
+#endif
        regs.pt.cr_ifs = 1UL << 63;             /* mark as valid, empty frame */
        regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
        regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
Index: linux-2.6.17-rc3-kgdb/arch/ia64/kernel/unwind.c
===================================================================
--- linux-2.6.17-rc3-kgdb.orig/arch/ia64/kernel/unwind.c        2006-05-01 
13:55:27.000000000 -0400
+++ linux-2.6.17-rc3-kgdb/arch/ia64/kernel/unwind.c     2006-05-01 
13:56:11.000000000 -0400
@@ -72,10 +72,68 @@
 # define STAT(x...)
 #endif
 
+#ifdef CONFIG_KGDB
+#define        KGDB_EARLY_SIZE 100
+static struct unw_reg_state __initdata kgdb_reg_state[KGDB_EARLY_SIZE];
+static struct unw_labeled_state __initdata kgdb_labeled_state[KGDB_EARLY_SIZE];
+void __initdata *kgdb_reg_state_free, __initdata *kgdb_labeled_state_free;
+
+static void __init
+kgdb_malloc_init(void)
+{
+       int i;
+
+       kgdb_reg_state_free = kgdb_reg_state;
+       for (i = 1; i < KGDB_EARLY_SIZE; i++) {
+               *((unsigned long *) &kgdb_reg_state[i]) = (unsigned long) 
kgdb_reg_state_free;
+               kgdb_reg_state_free = &kgdb_reg_state[i];
+       }
+
+       kgdb_labeled_state_free = kgdb_labeled_state;
+       for (i = 1; i < KGDB_EARLY_SIZE; i++) {
+               *((unsigned long *) &kgdb_labeled_state[i]) =
+                       (unsigned long) kgdb_labeled_state_free;
+               kgdb_labeled_state_free = &kgdb_labeled_state[i];
+       }
+
+}
+
+static void * __init
+kgdb_malloc(void **mem)
+{
+       void *p;
+
+       p = *mem;
+       *mem = *((void **) p);
+       return p;
+}
+
+static void __init
+kgdb_free(void **mem, void *p)
+{
+       *((void **)p) = *mem;
+       *mem = p;
+}
+
+#define alloc_reg_state()      (!malloc_sizes[0].cs_cachep ?           \
+               kgdb_malloc(&kgdb_reg_state_free) :                     \
+               kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC))
+#define free_reg_state(usr)    (!malloc_sizes[0].cs_cachep ?           \
+               kgdb_free(&kgdb_reg_state_free, usr) :                  \
+               kfree(usr))
+#define alloc_labeled_state()  (!malloc_sizes[0].cs_cachep ?           \
+               kgdb_malloc(&kgdb_labeled_state_free) :                 \
+               kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC))
+#define free_labeled_state(usr)        (!malloc_sizes[0].cs_cachep ?           
\
+               kgdb_free(&kgdb_labeled_state_free, usr) :              \
+               kfree(usr))
+
+#else
 #define alloc_reg_state()      kmalloc(sizeof(struct unw_reg_state), 
GFP_ATOMIC)
 #define free_reg_state(usr)    kfree(usr)
 #define alloc_labeled_state()  kmalloc(sizeof(struct unw_labeled_state), 
GFP_ATOMIC)
 #define free_labeled_state(usr)        kfree(usr)
+#endif
 
 typedef unsigned long unw_word;
 typedef unsigned char unw_hash_index_t;
@@ -238,6 +296,24 @@ static struct {
 #endif
 };
 
+#ifdef CONFIG_KGDB
+/*
+ * This makes it safe to call breakpoint() very early
+ * in setup_arch providing:
+ *     1) breakpoint isn't called between lines in cpu_init
+ *        where init_mm.mm_count is incremented and ia64_mmu_init
+ *        is called.  Otherwise the test below is invalid.
+ *     2) the memory examined doesn't result in tlbmiss.
+ */
+static unsigned long inline kgdb_unimpl_va_mask(void)
+{
+       if (atomic_read(&init_mm.mm_count) > 1)
+               return local_cpu_data->unimpl_va_mask;
+       else
+               return 0UL;
+}
+#endif
+
 static inline int
 read_only (void *addr)
 {
@@ -1786,7 +1862,11 @@ run_script (struct unw_script *script, s
 
                      case UNW_INSN_LOAD:
 #ifdef UNW_DEBUG
+#ifdef CONFIG_KGDB
+                       if ((s[val] & (kgdb_unimpl_va_mask() | 0x7)) != 0
+#else
                        if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) 
!= 0
+#endif
                            || s[val] < TASK_SIZE)
                        {
                                UNW_DPRINT(0, "unwind.%s: rejecting bad 
psp=0x%lx\n",
@@ -1821,7 +1901,11 @@ find_save_locs (struct unw_frame_info *i
        struct unw_script *scr;
        unsigned long flags = 0;
 
+#ifdef CONFIG_KGDB
+       if ((info->ip & (kgdb_unimpl_va_mask() | 0xf)) || info->ip < TASK_SIZE) 
{
+#else
        if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < 
TASK_SIZE) {
+#endif
                /* don't let obviously bad addresses pollute the cache */
                /* FIXME: should really be level 0 but it occurs too often. KAO 
*/
                UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", 
__FUNCTION__, info->ip);
@@ -2249,6 +2333,9 @@ unw_init (void)
 
        init_unwind_table(&unw.kernel_table, "kernel", KERNEL_START, (unsigned 
long) __gp,
                          __start_unwind, __end_unwind);
+#ifdef CONFIG_KGDB
+       kgdb_malloc_init();
+#endif
 }
 
 /*
Index: linux-2.6.17-rc3-kgdb/arch/ia64/kernel/entry.S
===================================================================
--- linux-2.6.17-rc3-kgdb.orig/arch/ia64/kernel/entry.S 2006-05-01 
13:55:27.000000000 -0400
+++ linux-2.6.17-rc3-kgdb/arch/ia64/kernel/entry.S      2006-05-01 
13:56:11.000000000 -0400
@@ -954,9 +954,9 @@ GLOBAL_ENTRY(ia64_leave_kernel)
        shr.u r18=r19,16        // get byte size of existing "dirty" partition
        ;;
        mov r16=ar.bsp          // get existing backing store pointer
-       addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
+(pUStk)        addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
        ;;
-       ld4 r17=[r17]           // r17 = cpu_data->phys_stacked_size_p8
+(pUStk)        ld4 r17=[r17]           // r17 = cpu_data->phys_stacked_size_p8
 (pKStk)        br.cond.dpnt skip_rbs_switch
 
        /*
Index: linux-2.6.17-rc3-kgdb/arch/ia64/kernel/ivt.S
===================================================================
--- linux-2.6.17-rc3-kgdb.orig/arch/ia64/kernel/ivt.S   2006-05-01 
13:55:27.000000000 -0400
+++ linux-2.6.17-rc3-kgdb/arch/ia64/kernel/ivt.S        2006-05-01 
13:56:11.000000000 -0400
@@ -53,6 +53,14 @@
 #include <asm/unistd.h>
 #include <asm/errno.h>
 
+#ifdef CONFIG_KGDB
+#define KGDB_ENABLE_PSR_DB mov r31=psr;; movl r30=IA64_PSR_DB;;        \
+       or r31=r31,r30;;                                        \
+       mov psr.l=r31;; srlz.i;;
+#else
+#define KGDB_ENABLE_PSR_DB
+#endif
+
 #if 1
 # define PSR_DEFAULT_BITS      psr.ac
 #else
@@ -520,6 +528,7 @@ ENTRY(page_fault)
        movl r14=ia64_leave_kernel
        ;;
        SAVE_REST
+       KGDB_ENABLE_PSR_DB
        mov rp=r14
        ;;
        adds out2=16,r12                        // out2 = pointer to pt_regs
@@ -864,6 +873,7 @@ ENTRY(interrupt)
        srlz.i                  // ensure everybody knows psr.ic is back on
        ;;
        SAVE_REST
+       KGDB_ENABLE_PSR_DB
        ;;
        MCA_RECOVER_RANGE(interrupt)
        alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
@@ -1111,6 +1121,7 @@ ENTRY(non_syscall)
        movl r15=ia64_leave_kernel
        ;;
        SAVE_REST
+       KGDB_ENABLE_PSR_DB
        mov rp=r15
        ;;
        br.call.sptk.many b6=ia64_bad_break     // avoid WAW on CFM and ignore 
return addr
@@ -1144,6 +1155,7 @@ ENTRY(dispatch_unaligned_handler)
        adds r3=8,r2                            // set up second base pointer
        ;;
        SAVE_REST
+       KGDB_ENABLE_PSR_DB
        movl r14=ia64_leave_kernel
        ;;
        mov rp=r14
@@ -1186,6 +1198,10 @@ ENTRY(dispatch_to_fault_handler)
        adds r3=8,r2                            // set up second base pointer 
for SAVE_REST
        ;;
        SAVE_REST
+       cmp.eq p6,p0=29,out0
+(p6)   br.cond.spnt 1f;;                       // debug_vector
+       KGDB_ENABLE_PSR_DB
+1:
        movl r14=ia64_leave_kernel
        ;;
        mov rp=r14


-------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Kgdb-bugreport mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport

Reply via email to