Home | History | Annotate | Line # | Download | only in sparc64
      1  1.15     rmind /*	$NetBSD: kgdb_machdep.c,v 1.15 2011/05/23 18:38:51 rmind Exp $ */
      2   1.1    martin /*-
      3   1.1    martin  * Copyright (c) 1997 The NetBSD Foundation, Inc.
      4   1.1    martin  * All rights reserved.
      5   1.1    martin  *
      6   1.1    martin  * This code is derived from software contributed to The NetBSD Foundation
      7   1.1    martin  * by Paul Kranenburg.
      8   1.1    martin  *
      9   1.1    martin  * Redistribution and use in source and binary forms, with or without
     10   1.1    martin  * modification, are permitted provided that the following conditions
     11   1.1    martin  * are met:
     12   1.1    martin  * 1. Redistributions of source code must retain the above copyright
     13   1.1    martin  *    notice, this list of conditions and the following disclaimer.
     14   1.1    martin  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1    martin  *    notice, this list of conditions and the following disclaimer in the
     16   1.1    martin  *    documentation and/or other materials provided with the distribution.
     17   1.1    martin  *
     18   1.1    martin  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     19   1.1    martin  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     20   1.1    martin  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     21   1.1    martin  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     22   1.1    martin  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23   1.1    martin  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24   1.1    martin  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25   1.1    martin  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26   1.1    martin  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27   1.1    martin  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28   1.1    martin  * POSSIBILITY OF SUCH DAMAGE.
     29   1.1    martin  */
     30   1.1    martin 
     31   1.1    martin /*
     32   1.1    martin  * Copyright (c) 1992, 1993
     33   1.1    martin  *	The Regents of the University of California.  All rights reserved.
     34   1.4       agc  *
     35   1.4       agc  * This software was developed by the Computer Systems Engineering group
     36   1.4       agc  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     37   1.4       agc  * contributed to Berkeley.
     38   1.4       agc  *
     39   1.4       agc  * All advertising materials mentioning features or use of this software
     40   1.4       agc  * must display the following acknowledgements:
     41   1.4       agc  *	This product includes software developed by the University of
     42   1.4       agc  *	California, Lawrence Berkeley Laboratory.
     43   1.4       agc  *
     44   1.4       agc  * 	This product includes software developed by Harvard University.
     45   1.4       agc  *
     46   1.4       agc  * Redistribution and use in source and binary forms, with or without
     47   1.4       agc  * modification, are permitted provided that the following conditions
     48   1.4       agc  * are met:
     49   1.4       agc  * 1. Redistributions of source code must retain the above copyright
     50   1.4       agc  *    notice, this list of conditions and the following disclaimer.
     51   1.4       agc  * 2. Redistributions in binary form must reproduce the above copyright
     52   1.4       agc  *    notice, this list of conditions and the following disclaimer in the
     53   1.4       agc  *    documentation and/or other materials provided with the distribution.
     54   1.4       agc  * 3. Neither the name of the University nor the names of its contributors
     55   1.4       agc  *    may be used to endorse or promote products derived from this software
     56   1.4       agc  *    without specific prior written permission.
     57   1.4       agc  *
     58   1.4       agc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     59   1.4       agc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     60   1.4       agc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     61   1.4       agc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     62   1.4       agc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     63   1.4       agc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     64   1.4       agc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     65   1.4       agc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     66   1.4       agc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     67   1.4       agc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     68   1.4       agc  * SUCH DAMAGE.
     69   1.4       agc  *
     70   1.4       agc  *	@(#)kgdb_stub.c	8.1 (Berkeley) 6/11/93
     71   1.4       agc  */
     72   1.4       agc 
     73   1.4       agc /*
     74   1.1    martin  * Copyright (c) 1995
     75   1.1    martin  * 	The President and Fellows of Harvard College. All rights reserved.
     76   1.1    martin  *
     77   1.1    martin  * This software was developed by the Computer Systems Engineering group
     78   1.1    martin  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     79   1.1    martin  * contributed to Berkeley.
     80   1.1    martin  *
     81   1.1    martin  * All advertising materials mentioning features or use of this software
     82   1.1    martin  * must display the following acknowledgements:
     83   1.1    martin  *	This product includes software developed by the University of
     84   1.1    martin  *	California, Lawrence Berkeley Laboratory.
     85   1.1    martin  *
     86   1.1    martin  * 	This product includes software developed by Harvard University.
     87   1.1    martin  *
     88   1.1    martin  * Redistribution and use in source and binary forms, with or without
     89   1.1    martin  * modification, are permitted provided that the following conditions
     90   1.1    martin  * are met:
     91   1.1    martin  * 1. Redistributions of source code must retain the above copyright
     92   1.1    martin  *    notice, this list of conditions and the following disclaimer.
     93   1.1    martin  * 2. Redistributions in binary form must reproduce the above copyright
     94   1.1    martin  *    notice, this list of conditions and the following disclaimer in the
     95   1.1    martin  *    documentation and/or other materials provided with the distribution.
     96   1.1    martin  * 3. All advertising materials mentioning features or use of this software
     97   1.1    martin  *    must display the following acknowledgement:
     98   1.1    martin  *	This product includes software developed by the University of
     99   1.1    martin  *	California, Berkeley and its contributors.
    100   1.1    martin  * 4. Neither the name of the University nor the names of its contributors
    101   1.1    martin  *    may be used to endorse or promote products derived from this software
    102   1.1    martin  *    without specific prior written permission.
    103   1.1    martin  *
    104   1.1    martin  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    105   1.1    martin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    106   1.1    martin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    107   1.1    martin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    108   1.1    martin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    109   1.1    martin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    110   1.1    martin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    111   1.1    martin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    112   1.1    martin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    113   1.1    martin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    114   1.1    martin  * SUCH DAMAGE.
    115   1.1    martin  *
    116   1.1    martin  *	@(#)kgdb_stub.c	8.1 (Berkeley) 6/11/93
    117   1.1    martin  */
    118   1.1    martin 
    119   1.1    martin /*
    120   1.1    martin  * Machine dependent routines needed by kern/kgdb_stub.c
    121   1.1    martin  */
    122   1.3     lukem 
    123   1.3     lukem #include <sys/cdefs.h>
    124  1.15     rmind __KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.15 2011/05/23 18:38:51 rmind Exp $");
    125   1.1    martin 
    126   1.1    martin #include "opt_kgdb.h"
    127   1.1    martin #include "opt_multiprocessor.h"
    128   1.1    martin #include "opt_sparc_arch.h"
    129   1.1    martin 
    130   1.1    martin #ifdef KGDB
    131   1.1    martin 
    132   1.1    martin #include <sys/param.h>
    133   1.1    martin #include <sys/systm.h>
    134   1.1    martin #include <sys/buf.h>
    135   1.1    martin #include <sys/kgdb.h>
    136   1.1    martin 
    137   1.1    martin #include <machine/ctlreg.h>
    138   1.1    martin #include <machine/psl.h>
    139   1.1    martin #include <machine/reg.h>
    140   1.1    martin #include <machine/trap.h>
    141   1.1    martin #include <machine/cpu.h>
    142   1.1    martin 
    143   1.1    martin #include <sparc/sparc/asm.h>
    144   1.1    martin 
    145   1.7       cdi extern int64_t pseg_get(struct pmap *, vaddr_t);
    146   1.1    martin 
    147   1.7       cdi static inline void kgdb_copy(register char *, register char *, register int);
    148   1.7       cdi static inline void kgdb_zero(register char *, register int);
    149   1.1    martin 
    150   1.1    martin /*
    151   1.1    martin  * This little routine exists simply so that bcopy() can be debugged.
    152   1.1    martin  */
    153   1.6     perry static inline void
    154   1.7       cdi kgdb_copy(register char *src, register char *dst, register int len)
    155   1.1    martin {
    156   1.1    martin 
    157   1.1    martin 	while (--len >= 0)
    158   1.1    martin 		*dst++ = *src++;
    159   1.1    martin }
    160   1.1    martin 
    161   1.1    martin /* ditto for bzero */
    162   1.6     perry static inline void
    163   1.7       cdi kgdb_zero(register char *ptr, register int len)
    164   1.1    martin {
    165   1.1    martin 	while (--len >= 0)
    166   1.1    martin 		*ptr++ = (char) 0;
    167   1.1    martin }
    168   1.1    martin 
    169   1.1    martin /*
    170   1.1    martin  * Deal with KGDB in a MP environment. XXX need to have "mach cpu" equiv.
    171   1.1    martin  */
    172   1.1    martin #ifdef MULTIPROCESSOR
    173   1.1    martin 
    174   1.1    martin #define NOCPU -1
    175   1.1    martin 
    176   1.1    martin static int kgdb_suspend_others(void);
    177   1.1    martin static void kgdb_resume_others(void);
    178   1.1    martin static void kgdb_suspend(void);
    179   1.1    martin 
    180   1.1    martin __cpu_simple_lock_t kgdb_lock;
    181   1.1    martin int kgdb_cpu = NOCPU;
    182   1.1    martin 
    183   1.1    martin static int
    184   1.1    martin kgdb_suspend_others(void)
    185   1.1    martin {
    186   1.1    martin 	int cpu_me = cpu_number();
    187   1.1    martin 	int win;
    188   1.1    martin 
    189   1.1    martin 	if (cpus == NULL)
    190   1.1    martin 		return 1;
    191   1.1    martin 
    192   1.1    martin 	__cpu_simple_lock(&kgdb_lock);
    193   1.1    martin 	if (kgdb_cpu == NOCPU)
    194   1.1    martin 		kgdb_cpu = cpu_me;
    195   1.1    martin 	win = (kgdb_cpu == cpu_me);
    196   1.1    martin 	__cpu_simple_unlock(&kgdb_lock);
    197   1.1    martin 
    198   1.1    martin 	if (win)
    199   1.1    martin 		mp_pause_cpus();
    200   1.1    martin 
    201   1.1    martin 	return win;
    202   1.1    martin }
    203   1.1    martin 
    204   1.1    martin static void
    205   1.1    martin kgdb_resume_others(void)
    206   1.1    martin {
    207   1.1    martin 
    208   1.1    martin 	mp_resume_cpus();
    209   1.1    martin 
    210   1.1    martin 	__cpu_simple_lock(&kgdb_lock);
    211   1.1    martin 	kgdb_cpu = NOCPU;
    212   1.1    martin 	__cpu_simple_unlock(&kgdb_lock);
    213   1.1    martin }
    214   1.1    martin 
    215   1.1    martin static void
    216  1.14    cegger kgdb_suspend(void)
    217   1.1    martin {
    218   1.1    martin 
    219   1.9       rjs 	sparc64_ipi_pause_thiscpu(NULL);
    220   1.1    martin }
    221   1.8       mrg #endif	/* MULTIPROCESSOR */
    222   1.1    martin 
    223   1.1    martin /*
    224   1.1    martin  * Trap into kgdb to wait for debugger to connect,
    225   1.1    martin  * noting on the console why nothing else is going on.
    226   1.1    martin  */
    227   1.1    martin void
    228  1.12    cegger kgdb_connect(int verbose)
    229   1.1    martin {
    230   1.1    martin 
    231  1.12    cegger 	if (kgdb_dev == NODEV)
    232   1.1    martin 		return;
    233   1.1    martin #if NFB > 0
    234   1.1    martin 	fb_unblank();
    235   1.1    martin #endif
    236   1.1    martin #ifdef MULTIPROCESSOR
    237   1.1    martin 	/* While we're in the debugger, pause all other CPUs */
    238   1.1    martin 	if (!kgdb_suspend_others()) {
    239   1.1    martin 		kgdb_suspend();
    240   1.1    martin 	} else {
    241   1.8       mrg #endif	/* MULTIPROCESSOR */
    242   1.1    martin 		if (verbose)
    243   1.1    martin 			printf("kgdb waiting...");
    244   1.1    martin 		__asm("ta %0" :: "n" (T_KGDB_EXEC));	/* trap into kgdb */
    245   1.1    martin 
    246   1.1    martin 		kgdb_debug_panic = 1;
    247   1.1    martin 
    248   1.1    martin #ifdef MULTIPROCESSOR
    249   1.1    martin 		/* Other CPUs can continue now */
    250   1.1    martin 		kgdb_resume_others();
    251   1.1    martin 	}
    252   1.8       mrg #endif	/* MULTIPROCESSOR */
    253   1.1    martin }
    254   1.1    martin 
    255   1.1    martin /*
    256   1.1    martin  * Decide what to do on panic.
    257   1.1    martin  */
    258   1.1    martin void
    259  1.12    cegger kgdb_panic(void)
    260   1.1    martin {
    261   1.1    martin 
    262  1.12    cegger 	if (kgdb_dev != NODEV && kgdb_debug_panic)
    263   1.1    martin 		kgdb_connect(kgdb_active == 0);
    264   1.1    martin }
    265   1.1    martin 
    266   1.1    martin /*
    267   1.1    martin  * Translate a trap number into a unix compatible signal value.
    268   1.1    martin  * (gdb only understands unix signal numbers).
    269   1.1    martin  * XXX should this be done at the other end?
    270   1.1    martin  */
    271   1.1    martin int
    272  1.13       dsl kgdb_signal(int type)
    273   1.1    martin {
    274   1.1    martin 	int sigval;
    275   1.1    martin 
    276   1.1    martin 	switch (type) {
    277   1.1    martin 
    278   1.1    martin 	case T_AST:
    279   1.1    martin 		sigval = SIGINT;
    280   1.1    martin 		break;
    281   1.1    martin 
    282   1.1    martin 	case T_TEXTFAULT:
    283   1.1    martin 	case T_DATAFAULT:
    284   1.1    martin 		sigval = SIGSEGV;
    285   1.1    martin 		break;
    286   1.1    martin 
    287   1.1    martin 	case T_ALIGN:
    288   1.1    martin 		sigval = SIGBUS;
    289   1.1    martin 		break;
    290   1.1    martin 
    291   1.1    martin 	case T_ILLINST:
    292   1.1    martin 	case T_PRIVINST:
    293   1.1    martin 	case T_DIV0:
    294   1.1    martin 		sigval = SIGILL;
    295   1.1    martin 		break;
    296   1.1    martin 
    297   1.1    martin 	case T_FP_IEEE_754:
    298   1.1    martin 	case T_FP_OTHER:
    299   1.1    martin 		sigval = SIGFPE;
    300   1.1    martin 		break;
    301   1.1    martin 
    302   1.1    martin 	case T_BREAKPOINT:
    303   1.1    martin 		sigval = SIGTRAP;
    304   1.1    martin 		break;
    305   1.1    martin 
    306   1.1    martin 	case T_KGDB_EXEC:
    307   1.1    martin 		sigval = SIGIOT;
    308   1.1    martin 		break;
    309   1.1    martin 
    310   1.1    martin 	default:
    311   1.1    martin 		sigval = SIGEMT;
    312   1.1    martin 		break;
    313   1.1    martin 	}
    314   1.1    martin 	return (sigval);
    315   1.1    martin }
    316   1.1    martin 
    317   1.1    martin /*
    318   1.1    martin  * Definitions exported from gdb (& then made prettier).
    319   1.1    martin  * (see gnu/dist/toolchain/gdb/config/sparc/tm-sp64.h)
    320   1.1    martin  */
    321   1.1    martin #define	GDB_G0		0
    322   1.1    martin #define	GDB_O0		8
    323   1.1    martin #define	GDB_L0		16
    324   1.1    martin #define	GDB_I0		24
    325   1.1    martin #define	GDB_FP0		32
    326   1.1    martin #define GDB_PC		80
    327   1.1    martin #define GDB_NPC		81
    328   1.1    martin #define GDB_CCR		82
    329   1.1    martin #define	GDB_FSR		83
    330   1.1    martin #define	GDB_FPRS	84
    331   1.1    martin #define	GDB_Y		85
    332   1.1    martin #define	GDB_ASI		86
    333   1.1    martin 
    334   1.1    martin #define REGISTER_BYTES		(KGDB_NUMREGS * 8)
    335   1.1    martin #define REGISTER_BYTE(n)	((n) * 8)
    336   1.1    martin 
    337   1.1    martin /*
    338   1.1    martin  * Translate the values stored in the kernel regs struct to the format
    339   1.1    martin  * understood by gdb.
    340   1.1    martin  */
    341   1.1    martin void
    342  1.13       dsl kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
    343   1.1    martin {
    344   1.8       mrg 	struct trapframe64 *tf = &regs->db_tf;
    345   1.1    martin 
    346   1.1    martin 	/* %g0..%g7 and %o0..%o7: from trapframe */
    347   1.1    martin 	gdb_regs[0] = 0;
    348  1.10  christos 	kgdb_copy((void *)&tf->tf_global[1], (void *)&gdb_regs[1], 15 * 8);
    349   1.1    martin 
    350   1.1    martin 	/* %l0..%l7 and %i0..%i7: from stack */
    351  1.10  christos 	kgdb_copy((void *)(long)tf->tf_out[6], (void *)&gdb_regs[GDB_L0], 16 * 8);
    352   1.1    martin 
    353   1.1    martin 	/* %f0..%f31 -- fake, kernel does not use FP */
    354  1.10  christos 	kgdb_zero((void *)&gdb_regs[GDB_FP0], 32 * 8);
    355   1.1    martin 
    356   1.1    martin 	/* %y, %psr, %wim, %tbr, %pc, %npc, %fsr, %csr */
    357   1.1    martin 	gdb_regs[GDB_PC] = tf->tf_pc;
    358   1.1    martin 	gdb_regs[GDB_NPC] = tf->tf_npc;
    359   1.1    martin }
    360   1.1    martin 
    361   1.1    martin /*
    362   1.1    martin  * Reverse the above.
    363   1.1    martin  */
    364   1.1    martin void
    365  1.13       dsl kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
    366   1.1    martin {
    367   1.8       mrg 	struct trapframe64 *tf = &regs->db_tf;
    368   1.1    martin 
    369  1.10  christos 	kgdb_copy((void *)&gdb_regs[1], (void *)&tf->tf_global[1], 15 * 8);
    370  1.10  christos 	kgdb_copy((void *)&gdb_regs[GDB_L0], (void *)(long)tf->tf_out[6], 16 * 8);
    371   1.1    martin 	tf->tf_pc = gdb_regs[GDB_PC];
    372   1.1    martin 	tf->tf_npc = gdb_regs[GDB_NPC];
    373   1.1    martin }
    374   1.1    martin 
    375   1.1    martin /*
    376   1.1    martin  * Determine if memory at [va..(va+len)] is valid.
    377   1.1    martin  */
    378   1.1    martin int
    379  1.13       dsl kgdb_acc(vaddr_t va, size_t len)
    380   1.1    martin {
    381   1.1    martin 	int64_t data;
    382   1.1    martin 	vaddr_t eva;
    383   1.1    martin 	struct pmap *pm = &kernel_pmap_;
    384   1.1    martin 
    385   1.1    martin 	eva = round_page(va + len);
    386   1.1    martin 	va = trunc_page(va);
    387   1.1    martin 
    388  1.15     rmind 	mutex_enter(&pm->pm_lock);
    389   1.1    martin 	for (; va < eva; va += PAGE_SIZE) {
    390   1.1    martin 		data = pseg_get(pm, va);
    391   1.1    martin 		if ((data & TLB_V) == 0) {
    392  1.15     rmind 			mutex_exit(&pm->pm_lock);
    393   1.1    martin 			return 0;
    394   1.1    martin 		}
    395   1.1    martin 	}
    396  1.15     rmind 	mutex_exit(&pm->pm_lock);
    397   1.1    martin 
    398   1.1    martin 	return (1);
    399   1.1    martin }
    400   1.1    martin #endif
    401