Home | History | Annotate | Line # | Download | only in powerpc
      1 /*	$NetBSD: kgdb_machdep.c,v 1.26 2024/09/08 10:02:49 andvar Exp $	*/
      2 
      3 /*
      4  * Copyright 2001 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Allen Briggs for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *      This product includes software developed for the NetBSD Project by
     20  *      Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 #include <sys/cdefs.h>
     39 __KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.26 2024/09/08 10:02:49 andvar Exp $");
     40 
     41 #ifdef _KERNEL_OPT
     42 #include "opt_ppcarch.h"
     43 #endif
     44 
     45 /*
     46  * Machine-dependent functions for remote KGDB.
     47  */
     48 
     49 #include <sys/param.h>
     50 #include <sys/kgdb.h>
     51 #include <sys/systm.h>
     52 
     53 #include <uvm/uvm_extern.h>
     54 
     55 #include <machine/reg.h>
     56 #include <machine/trap.h>
     57 #include <machine/pmap.h>
     58 #include <machine/psl.h>
     59 
     60 #include <powerpc/spr.h>
     61 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE)
     62 #include <powerpc/oea/spr.h>
     63 #include <powerpc/oea/bat.h>
     64 
     65 #elif defined (PPC_OEA64)
     66 #include <powerpc/oea/spr.h>
     67 
     68 #elif defined (PPC_IBM4XX)
     69 #include <powerpc/booke/spr.h>
     70 
     71 #elif defined (PPC_BOOKE)
     72 #include <powerpc/booke/spr.h>
     73 
     74 #else
     75 #error unknown architecture
     76 #endif
     77 
     78 /*
     79  * Determine if the memory at va..(va+len) is valid.
     80  */
     81 int
     82 kgdb_acc(vaddr_t va, size_t len)
     83 {
     84 	vaddr_t   last_va;
     85 	paddr_t   pa;
     86 	u_int msr;
     87 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE)
     88 	u_int batu;
     89 #ifdef PPC_OEA601
     90 	u_int batl;
     91 #endif
     92 #endif
     93 
     94 	/* If translation is off, everything is fair game */
     95 	__asm volatile ("mfmsr %0" : "=r"(msr));
     96 	if ((msr & PSL_DR) == 0) {
     97 		return 1;
     98 	}
     99 
    100 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE)
    101 	/* Now check battable registers */
    102 #ifdef PPC_OEA601
    103 	if ((mfpvr() >> 16) == MPC601) {
    104 		__asm volatile ("mfibatl %0,0" : "=r"(batl));
    105 		__asm volatile ("mfibatu %0,0" : "=r"(batu));
    106 		if (BAT601_VALID_P(batl) &&
    107 				BAT601_VA_MATCH_P(batu,batl,va))
    108 			return 1;
    109 		__asm volatile ("mfibatl %0,1" : "=r"(batl));
    110 		__asm volatile ("mfibatu %0,1" : "=r"(batu));
    111 		if (BAT601_VALID_P(batl) &&
    112 				BAT601_VA_MATCH_P(batu,batl,va))
    113 			return 1;
    114 		__asm volatile ("mfibatl %0,2" : "=r"(batl));
    115 		__asm volatile ("mfibatu %0,2" : "=r"(batu));
    116 		if (BAT601_VALID_P(batl) &&
    117 				BAT601_VA_MATCH_P(batu,batl,va))
    118 			return 1;
    119 		__asm volatile ("mfibatl %0,3" : "=r"(batl));
    120 		__asm volatile ("mfibatu %0,3" : "=r"(batu));
    121 		if (BAT601_VALID_P(batl) &&
    122 				BAT601_VA_MATCH_P(batu,batl,va))
    123 			return 1;
    124 	} else {
    125 #endif /* PPC_OEA601 */
    126 		__asm volatile ("mfdbatu %0,0" : "=r"(batu));
    127 		if (BAT_VALID_P(batu,msr) &&
    128 				BAT_VA_MATCH_P(batu,va) &&
    129 				(batu & BAT_PP) != BAT_PP_NONE) {
    130 			return 1;
    131 		}
    132 		__asm volatile ("mfdbatu %0,1" : "=r"(batu));
    133 		if (BAT_VALID_P(batu,msr) &&
    134 				BAT_VA_MATCH_P(batu,va) &&
    135 				(batu & BAT_PP) != BAT_PP_NONE) {
    136 			return 1;
    137 		}
    138 		__asm volatile ("mfdbatu %0,2" : "=r"(batu));
    139 		if (BAT_VALID_P(batu,msr) &&
    140 				BAT_VA_MATCH_P(batu,va) &&
    141 				(batu & BAT_PP) != BAT_PP_NONE) {
    142 			return 1;
    143 		}
    144 		__asm volatile ("mfdbatu %0,3" : "=r"(batu));
    145 		if (BAT_VALID_P(batu,msr) &&
    146 				BAT_VA_MATCH_P(batu,va) &&
    147 				(batu & BAT_PP) != BAT_PP_NONE) {
    148 			return 1;
    149 #ifdef PPC_OEA601
    150 		}
    151 #endif
    152 	}
    153 #endif /* PPC_OEA || PPC_OEA601 || PPC_OEA64_BRIDGE */
    154 
    155 #if defined(PPC_IBM4XX)
    156 	/* Is it (supposed to be) TLB-reserved mapping? */
    157 	if (va < VM_MIN_KERNEL_ADDRESS || va > VM_MAX_KERNEL_ADDRESS)
    158 		return (1);
    159 #endif
    160 
    161 	last_va = va + len;
    162 	va  &= ~PGOFSET;
    163 	last_va &= ~PGOFSET;
    164 
    165 	do {
    166 		/*
    167 		 * I think this should be able to handle
    168 		 * non-pmap_kernel() va's, too.
    169 		 */
    170 		if (!pmap_extract(pmap_kernel(), va, &pa))
    171 			return 0;
    172 		va += PAGE_SIZE;
    173 	} while (va <= last_va);
    174 
    175 	return (1);
    176 }
    177 
    178 /*
    179  * Translate a trap number into a unix compatible signal value.
    180  * (gdb only understands unix signal numbers).  Some of these are bogus
    181  * and should be reviewed.
    182  */
    183 int
    184 kgdb_signal(int type)
    185 {
    186 	switch (type) {
    187 #if defined (PPC_IBM4XX) || defined (PPC_BOOKE)
    188 	case EXC_PIT:		/* 40x - Programmable interval timer */
    189 	case EXC_FIT:		/* 40x - Fixed interval timer */
    190 		return SIGALRM;
    191 
    192 	case EXC_CII:		/* 40x - Critical input interrupt */
    193 	case EXC_WDOG:		/* 40x - Watchdog timer */
    194 	case EXC_DEBUG:		/* 40x - Debug trap */
    195 		return SIGTRAP;
    196 
    197 	case EXC_DTMISS:	/* 40x - Instruction TLB miss */
    198 	case EXC_ITMISS:	/* 40x - Data TLB miss */
    199 		return SIGSEGV;
    200 #endif
    201 
    202 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE)
    203 	case EXC_PERF:		/* 604/750/7400 - Performance monitoring */
    204 	case EXC_BPT:		/* 604/750/7400 - Instruction breakpoint */
    205 	case EXC_SMI:		/* 604/750/7400 - System management interrupt */
    206 	case EXC_THRM:		/* 750/7400 - Thermal management interrupt */
    207 		return SIGTRAP;
    208 
    209 	case EXC_IMISS:		/* 603 - Instruction translation miss */
    210 	case EXC_DLMISS:	/* 603 - Data load translation miss */
    211 	case EXC_DSMISS:	/* 603 - Data store translation miss */
    212 		return SIGSEGV;
    213 
    214 	case EXC_RST:		/* All but IBM 4xx - Reset */
    215 		return SIGURG;
    216 
    217 	case EXC_VEC:		/* 7400 - Altivec unavailable */
    218 	case EXC_VECAST:	/* 7400 - Altivec assist */
    219 		return SIGFPE;
    220 #endif
    221 
    222 	case EXC_DECR:		/* Decrementer interrupt */
    223 		return SIGALRM;
    224 
    225 	case EXC_EXI:		/* External interrupt */
    226 		return SIGINT;
    227 
    228 	case EXC_PGM:		/* Program interrupt */
    229 	case EXC_ALI:		/* Alignment */
    230 		return SIGILL;
    231 
    232   case T_BREAKPOINT:
    233 	case EXC_MCHK:		/* Machine check */
    234 	case EXC_TRC:		/* Trace */
    235 		return SIGTRAP;
    236 
    237 	case EXC_ISI:		/* Instruction storage interrupt */
    238 	case EXC_DSI:		/* Data storage interrupt */
    239 		return SIGSEGV;
    240 
    241 	case EXC_FPU:		/* Floating point unavailable */
    242 	case EXC_FPA:		/* Floating-point assist */
    243 		return SIGFPE;
    244 
    245 	case EXC_SC:		/* System call */
    246 		return SIGURG;
    247 
    248 	case EXC_RSVD:		/* Reserved */
    249 	case EXC_AST:		/* Floating point unavailable */
    250 	default:
    251 		return SIGEMT;
    252 	}
    253 }
    254 
    255 /*
    256  * Translate the values stored in the kernel regs struct to the format
    257  * understood by gdb.
    258  */
    259 void
    260 kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
    261 {
    262 	memcpy(gdb_regs, regs, 32 * sizeof(unsigned long));
    263 	gdb_regs[KGDB_PPC_PC_REG]  = regs->iar;
    264 	gdb_regs[KGDB_PPC_MSR_REG] = regs->msr;
    265 	gdb_regs[KGDB_PPC_CR_REG]  = regs->cr;
    266 	gdb_regs[KGDB_PPC_LR_REG]  = regs->lr;
    267 	gdb_regs[KGDB_PPC_CTR_REG] = regs->ctr;
    268 	gdb_regs[KGDB_PPC_XER_REG] = regs->xer;
    269 }
    270 
    271 /*
    272  * Reverse the above.
    273  */
    274 void
    275 kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
    276 {
    277 	regs->xer = gdb_regs[KGDB_PPC_XER_REG];
    278 	regs->ctr = gdb_regs[KGDB_PPC_CTR_REG];
    279 	regs->lr  = gdb_regs[KGDB_PPC_LR_REG];
    280 	regs->cr  = gdb_regs[KGDB_PPC_CR_REG];
    281 	regs->msr = gdb_regs[KGDB_PPC_MSR_REG];
    282 	regs->iar = gdb_regs[KGDB_PPC_PC_REG];
    283 	memcpy(regs, gdb_regs, 32 * sizeof(unsigned long));
    284 }
    285 
    286 /*
    287  * Trap into kgdb to wait for debugger to connect,
    288  * noting on the console why nothing else is going on.
    289  */
    290 void
    291 kgdb_connect(int verbose)
    292 {
    293 	if (kgdb_dev == NODEV)
    294 		return;
    295 
    296 	if (verbose)
    297 		printf("kgdb waiting...");
    298 
    299 	__asm volatile(BKPT_ASM);
    300 
    301 	if (verbose && kgdb_active) {
    302 		printf("kgdb connected.\n");
    303 	}
    304 
    305 	kgdb_debug_panic = 1;
    306 }
    307 
    308 /*
    309  * Decide what to do on panic.
    310  * (This is called by panic, like Debugger())
    311  */
    312 void
    313 kgdb_panic(void)
    314 {
    315 	if (kgdb_dev != NODEV && kgdb_debug_panic) {
    316 		printf("entering kgdb\n");
    317 		kgdb_connect(kgdb_active == 0);
    318 	}
    319 }
    320