xref: /openbsd-src/sys/arch/powerpc/ddb/db_interface.c (revision 3fe80b7fb1a5bd0bd4a7a666724b5696fc175a21)
1*3fe80b7fSnaddy /*	$OpenBSD: db_interface.c,v 1.10 2022/04/14 19:47:11 naddy Exp $	*/
289ca63b3Smpi /*      $NetBSD: db_interface.c,v 1.12 2001/07/22 11:29:46 wiz Exp $ */
389ca63b3Smpi 
489ca63b3Smpi /*
589ca63b3Smpi  * Mach Operating System
689ca63b3Smpi  * Copyright (c) 1991,1990 Carnegie Mellon University
789ca63b3Smpi  * All Rights Reserved.
889ca63b3Smpi  *
989ca63b3Smpi  * Permission to use, copy, modify and distribute this software and its
1089ca63b3Smpi  * documentation is hereby granted, provided that both the copyright
1189ca63b3Smpi  * notice and this permission notice appear in all copies of the
1289ca63b3Smpi  * software, derivative works or modified versions, and any portions
1389ca63b3Smpi  * thereof, and that both notices appear in supporting documentation.
1489ca63b3Smpi  *
1589ca63b3Smpi  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
1689ca63b3Smpi  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1789ca63b3Smpi  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1889ca63b3Smpi  *
1989ca63b3Smpi  * Carnegie Mellon requests users of this software to return to
2089ca63b3Smpi  *
2189ca63b3Smpi  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
2289ca63b3Smpi  *  School of Computer Science
2389ca63b3Smpi  *  Carnegie Mellon University
2489ca63b3Smpi  *  Pittsburgh PA 15213-3890
2589ca63b3Smpi  *
2689ca63b3Smpi  * any improvements or extensions that they make and grant Carnegie the
2789ca63b3Smpi  * rights to redistribute these changes.
2889ca63b3Smpi  *
2989ca63b3Smpi  *      db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
3089ca63b3Smpi  */
3189ca63b3Smpi 
3289ca63b3Smpi #include <sys/param.h>
3389ca63b3Smpi #include <sys/proc.h>
3489ca63b3Smpi #include <sys/systm.h>
359ced64eaSvisa #include <sys/mutex.h>
3689ca63b3Smpi 
3789ca63b3Smpi #include <dev/cons.h>
3889ca63b3Smpi 
3989ca63b3Smpi #include <machine/db_machdep.h>
4089ca63b3Smpi #include <ddb/db_extern.h>
4189ca63b3Smpi #include <ddb/db_interface.h>
4289ca63b3Smpi #include <ddb/db_command.h>
4389ca63b3Smpi #include <ddb/db_output.h>
4489ca63b3Smpi #include <ddb/db_run.h>
4589ca63b3Smpi 
4689ca63b3Smpi #ifdef MULTIPROCESSOR
476c78d705Svisa struct db_mutex ddb_mp_mutex = DB_MUTEX_INITIALIZER;
4889ca63b3Smpi volatile int ddb_state = DDB_STATE_NOT_RUNNING;
4989ca63b3Smpi volatile cpuid_t ddb_active_cpu;
501d47df55Smpi int	        db_switch_cpu;
5189ca63b3Smpi long             db_switch_to_cpu;
5289ca63b3Smpi #endif
5389ca63b3Smpi 
5489ca63b3Smpi extern db_regs_t ddb_regs;
5589ca63b3Smpi 
5689ca63b3Smpi #ifdef MULTIPROCESSOR
5789ca63b3Smpi void db_cpuinfo_cmd(db_expr_t, int, db_expr_t, char *);
5889ca63b3Smpi void db_startproc_cmd(db_expr_t, int, db_expr_t, char *);
5989ca63b3Smpi void db_stopproc_cmd(db_expr_t, int, db_expr_t, char *);
6089ca63b3Smpi void db_ddbproc_cmd(db_expr_t, int, db_expr_t, char *);
6189ca63b3Smpi #endif
6289ca63b3Smpi 
6389ca63b3Smpi int db_trap_glue(struct trapframe *frame); /* called from locore */
6489ca63b3Smpi 
6589ca63b3Smpi void
db_enter()66e97088d6Smpi db_enter()
6789ca63b3Smpi {
6889ca63b3Smpi 	ddb_trap();
6989ca63b3Smpi }
7089ca63b3Smpi 
7189ca63b3Smpi int
db_trap_glue(struct trapframe * frame)7289ca63b3Smpi db_trap_glue(struct trapframe *frame)
7389ca63b3Smpi {
7489ca63b3Smpi 	int s;
7589ca63b3Smpi 
7689ca63b3Smpi 	if (!(frame->srr1 & PSL_PR)
7789ca63b3Smpi 	    && (frame->exc == EXC_TRC
7889ca63b3Smpi 		|| (frame->exc == EXC_PGM && (frame->srr1 & 0x20000))
7989ca63b3Smpi 		|| frame->exc == EXC_BPT)) {
8089ca63b3Smpi 
8189ca63b3Smpi #ifdef MULTIPROCESSOR
826c78d705Svisa 		db_mtx_enter(&ddb_mp_mutex);
8389ca63b3Smpi 		if (ddb_state == DDB_STATE_EXITING)
8489ca63b3Smpi 			ddb_state = DDB_STATE_NOT_RUNNING;
856c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
8689ca63b3Smpi 
8789ca63b3Smpi 		while (db_enter_ddb()) {
8889ca63b3Smpi #endif
892987d5a7Sgkoehler 			ddb_regs = *frame;
9089ca63b3Smpi 
9189ca63b3Smpi 			s = splhigh();
9289ca63b3Smpi 			db_active++;
931d47df55Smpi 			cnpollc(1);
9489ca63b3Smpi 			db_trap(T_BREAKPOINT, 0);
951d47df55Smpi 			cnpollc(0);
9689ca63b3Smpi 			db_active--;
9789ca63b3Smpi 			splx(s);
9889ca63b3Smpi 
992987d5a7Sgkoehler 			*frame = ddb_regs;
10089ca63b3Smpi #ifdef MULTIPROCESSOR
10189ca63b3Smpi 			if (!db_switch_cpu)
10289ca63b3Smpi 				ddb_state = DDB_STATE_EXITING;
10389ca63b3Smpi 		}
10489ca63b3Smpi #endif
10589ca63b3Smpi 		return 1;
10689ca63b3Smpi 	}
10789ca63b3Smpi 	return 0;
10889ca63b3Smpi }
10989ca63b3Smpi 
11089ca63b3Smpi int
db_enter_ddb(void)11189ca63b3Smpi db_enter_ddb(void)
11289ca63b3Smpi {
11389ca63b3Smpi #ifdef MULTIPROCESSOR
11489ca63b3Smpi 	int i;
11589ca63b3Smpi 	struct cpu_info *ci = curcpu();
11689ca63b3Smpi 
1176c78d705Svisa 	db_mtx_enter(&ddb_mp_mutex);
11889ca63b3Smpi 
11989ca63b3Smpi 	/* If we are first in, grab ddb and stop all other CPUs */
12089ca63b3Smpi 	if (ddb_state == DDB_STATE_NOT_RUNNING) {
12189ca63b3Smpi 		ddb_active_cpu = cpu_number();
12289ca63b3Smpi 		ddb_state = DDB_STATE_RUNNING;
12389ca63b3Smpi 		ci->ci_ddb_paused = CI_DDB_INDDB;
1246c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
12589ca63b3Smpi 		for (i = 0; i < ncpus; i++) {
12689ca63b3Smpi 			if (i != cpu_number() &&
12789ca63b3Smpi 			    cpu_info[i].ci_ddb_paused != CI_DDB_STOPPED) {
12889ca63b3Smpi 				cpu_info[i].ci_ddb_paused = CI_DDB_SHOULDSTOP;
12989ca63b3Smpi 				ppc_send_ipi(&cpu_info[i], PPC_IPI_DDB);
13089ca63b3Smpi 			}
13189ca63b3Smpi 		}
1322987d5a7Sgkoehler 		/* ipi is slow.  Try not to db_active++ too early. */
1332987d5a7Sgkoehler 		delay(100);
13489ca63b3Smpi 		return (1);
13589ca63b3Smpi 	}
13689ca63b3Smpi 
13789ca63b3Smpi 	/* Leaving ddb completely.  Start all other CPUs and return 0 */
13889ca63b3Smpi 	if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_EXITING) {
13989ca63b3Smpi 		for (i = 0; i < ncpus; i++) {
14089ca63b3Smpi 			cpu_info[i].ci_ddb_paused = CI_DDB_RUNNING;
14189ca63b3Smpi 		}
1426c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
14389ca63b3Smpi 		return (0);
14489ca63b3Smpi 	}
14589ca63b3Smpi 
14689ca63b3Smpi 	/* We are switching to another CPU. ddb_ddbproc_cmd() has made sure
14789ca63b3Smpi 	 * it is waiting for ddb, we just have to set ddb_active_cpu. */
14889ca63b3Smpi 	if (ddb_active_cpu == cpu_number() && db_switch_cpu) {
14989ca63b3Smpi 		ci->ci_ddb_paused = CI_DDB_SHOULDSTOP;
15089ca63b3Smpi 		db_switch_cpu = 0;
15189ca63b3Smpi 		ddb_active_cpu = db_switch_to_cpu;
15289ca63b3Smpi 		cpu_info[db_switch_to_cpu].ci_ddb_paused = CI_DDB_ENTERDDB;
15389ca63b3Smpi 	}
15489ca63b3Smpi 
15589ca63b3Smpi 	/* Wait until we should enter ddb or resume */
15689ca63b3Smpi 	while (ddb_active_cpu != cpu_number() &&
15789ca63b3Smpi 	    ci->ci_ddb_paused != CI_DDB_RUNNING) {
15889ca63b3Smpi 		if (ci->ci_ddb_paused == CI_DDB_SHOULDSTOP)
15989ca63b3Smpi 			ci->ci_ddb_paused = CI_DDB_STOPPED;
1606c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
16189ca63b3Smpi 
16289ca63b3Smpi 		/* Busy wait without locking, we will confirm with lock later */
16389ca63b3Smpi 		while (ddb_active_cpu != cpu_number() &&
16489ca63b3Smpi 		    ci->ci_ddb_paused != CI_DDB_RUNNING)
16589ca63b3Smpi 			;	/* Do nothing */
16689ca63b3Smpi 
1676c78d705Svisa 		db_mtx_enter(&ddb_mp_mutex);
16889ca63b3Smpi 	}
16989ca63b3Smpi 
17089ca63b3Smpi 	/* Either enter ddb or exit */
17189ca63b3Smpi 	if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_RUNNING) {
17289ca63b3Smpi 		ci->ci_ddb_paused = CI_DDB_INDDB;
1736c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
17489ca63b3Smpi 		return (1);
17589ca63b3Smpi 	} else {
1766c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
17789ca63b3Smpi 		return (0);
17889ca63b3Smpi 	}
17989ca63b3Smpi #else
18089ca63b3Smpi 	return (1);
18189ca63b3Smpi #endif
18289ca63b3Smpi }
18389ca63b3Smpi 
18489ca63b3Smpi #ifdef MULTIPROCESSOR
18589ca63b3Smpi void
ppc_ipi_db(struct cpu_info * ci)18689ca63b3Smpi ppc_ipi_db(struct cpu_info *ci)
18789ca63b3Smpi {
188e97088d6Smpi 	db_enter();
18989ca63b3Smpi }
19089ca63b3Smpi 
19189ca63b3Smpi void
db_cpuinfo_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)19289ca63b3Smpi db_cpuinfo_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
19389ca63b3Smpi {
19489ca63b3Smpi 	int i;
19589ca63b3Smpi 
19689ca63b3Smpi 	for (i = 0; i < ncpus; i++) {
19789ca63b3Smpi 		db_printf("%c%4d: ", (i == cpu_number()) ? '*' : ' ',
19889ca63b3Smpi 		    cpu_info[i].ci_cpuid);
19989ca63b3Smpi 		switch(cpu_info[i].ci_ddb_paused) {
20089ca63b3Smpi 		case CI_DDB_RUNNING:
20189ca63b3Smpi 			db_printf("running\n");
20289ca63b3Smpi 			break;
20389ca63b3Smpi 		case CI_DDB_SHOULDSTOP:
20489ca63b3Smpi 			db_printf("stopping\n");
20589ca63b3Smpi 			break;
20689ca63b3Smpi 		case CI_DDB_STOPPED:
20789ca63b3Smpi 			db_printf("stopped\n");
20889ca63b3Smpi 			break;
20989ca63b3Smpi 		case CI_DDB_ENTERDDB:
21089ca63b3Smpi 			db_printf("entering ddb\n");
21189ca63b3Smpi 			break;
21289ca63b3Smpi 		case CI_DDB_INDDB:
21389ca63b3Smpi 			db_printf("ddb\n");
21489ca63b3Smpi 			break;
21589ca63b3Smpi 		default:
21689ca63b3Smpi 			db_printf("? (%d)\n",
21789ca63b3Smpi 			    cpu_info[i].ci_ddb_paused);
21889ca63b3Smpi 			break;
21989ca63b3Smpi 		}
22089ca63b3Smpi 	}
22189ca63b3Smpi }
22289ca63b3Smpi #endif
22389ca63b3Smpi 
224*3fe80b7fSnaddy const struct db_command db_machine_command_table[] = {
22589ca63b3Smpi #ifdef MULTIPROCESSOR
22689ca63b3Smpi 	{ "cpuinfo",    db_cpuinfo_cmd,         0,      NULL },
22789ca63b3Smpi 	{ "startcpu",   db_startproc_cmd,       0,      NULL },
22889ca63b3Smpi 	{ "stopcpu",    db_stopproc_cmd,        0,      NULL },
22989ca63b3Smpi 	{ "ddbcpu",     db_ddbproc_cmd,         0,      NULL },
23089ca63b3Smpi #endif
23189ca63b3Smpi 	{ (char *)NULL }
23289ca63b3Smpi };
23389ca63b3Smpi 
23489ca63b3Smpi void
db_machine_init(void)23589ca63b3Smpi db_machine_init(void)
23689ca63b3Smpi {
23789ca63b3Smpi #ifdef MULTIPROCESSOR
23889ca63b3Smpi 	int i;
23989ca63b3Smpi 
24089ca63b3Smpi 	for (i = 0; i < ncpus; i++) {
24189ca63b3Smpi 		cpu_info[i].ci_ddb_paused = CI_DDB_RUNNING;
24289ca63b3Smpi 	}
24389ca63b3Smpi #endif
24489ca63b3Smpi }
24589ca63b3Smpi 
24689ca63b3Smpi #ifdef MULTIPROCESSOR
24789ca63b3Smpi void
db_ddbproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)24889ca63b3Smpi db_ddbproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
24989ca63b3Smpi {
25089ca63b3Smpi 	int cpu_n;
25189ca63b3Smpi 
25289ca63b3Smpi 	if (have_addr) {
25389ca63b3Smpi 		cpu_n = addr;
25489ca63b3Smpi 		if (cpu_n >= 0 && cpu_n < ncpus &&
25589ca63b3Smpi 		    cpu_n != cpu_number()) {
25689ca63b3Smpi 			db_switch_to_cpu = cpu_n;
25789ca63b3Smpi 			db_switch_cpu = 1;
25889ca63b3Smpi 			db_cmd_loop_done = 1;
25989ca63b3Smpi 		} else {
26089ca63b3Smpi 			db_printf("Invalid cpu %d\n", (int)addr);
26189ca63b3Smpi 		}
26289ca63b3Smpi 	} else {
26389ca63b3Smpi 		db_printf("CPU not specified\n");
26489ca63b3Smpi 	}
26589ca63b3Smpi }
26689ca63b3Smpi 
26789ca63b3Smpi void
db_startproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)26889ca63b3Smpi db_startproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
26989ca63b3Smpi {
27089ca63b3Smpi 	int cpu_n;
27189ca63b3Smpi 
27289ca63b3Smpi 	if (have_addr) {
27389ca63b3Smpi 		cpu_n = addr;
27489ca63b3Smpi 		if (cpu_n >= 0 && cpu_n < ncpus &&
27589ca63b3Smpi 		    cpu_n != cpu_number())
27689ca63b3Smpi 			db_startcpu(cpu_n);
27789ca63b3Smpi 		else
27889ca63b3Smpi 			db_printf("Invalid cpu %d\n", (int)addr);
27989ca63b3Smpi 	} else {
28089ca63b3Smpi 		for (cpu_n = 0; cpu_n < ncpus; cpu_n++) {
28189ca63b3Smpi 			if (cpu_n != cpu_number()) {
28289ca63b3Smpi 				db_startcpu(cpu_n);
28389ca63b3Smpi 			}
28489ca63b3Smpi 		}
28589ca63b3Smpi 	}
28689ca63b3Smpi }
28789ca63b3Smpi 
28889ca63b3Smpi void
db_stopproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)28989ca63b3Smpi db_stopproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
29089ca63b3Smpi {
29189ca63b3Smpi 	int cpu_n;
29289ca63b3Smpi 
29389ca63b3Smpi 	if (have_addr) {
29489ca63b3Smpi 		cpu_n = addr;
29589ca63b3Smpi 		if (cpu_n >= 0 && cpu_n < ncpus &&
29689ca63b3Smpi 		    cpu_n != cpu_number())
29789ca63b3Smpi 			db_stopcpu(cpu_n);
29889ca63b3Smpi 		else
29989ca63b3Smpi 			db_printf("Invalid cpu %d\n", (int)addr);
30089ca63b3Smpi 	} else {
30189ca63b3Smpi 		for (cpu_n = 0; cpu_n < ncpus; cpu_n++) {
30289ca63b3Smpi 			if (cpu_n != cpu_number()) {
30389ca63b3Smpi 				db_stopcpu(cpu_n);
30489ca63b3Smpi 			}
30589ca63b3Smpi 		}
30689ca63b3Smpi 	}
30789ca63b3Smpi }
30889ca63b3Smpi 
30989ca63b3Smpi void
db_startcpu(int cpu)31089ca63b3Smpi db_startcpu(int cpu)
31189ca63b3Smpi {
31289ca63b3Smpi 	if (cpu != cpu_number() && cpu < ncpus) {
3136c78d705Svisa 		db_mtx_enter(&ddb_mp_mutex);
31489ca63b3Smpi 		cpu_info[cpu].ci_ddb_paused = CI_DDB_RUNNING;
3156c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
31689ca63b3Smpi 	}
31789ca63b3Smpi }
31889ca63b3Smpi 
31989ca63b3Smpi void
db_stopcpu(int cpu)32089ca63b3Smpi db_stopcpu(int cpu)
32189ca63b3Smpi {
3226c78d705Svisa 	db_mtx_enter(&ddb_mp_mutex);
32389ca63b3Smpi 	if (cpu != cpu_number() && cpu < ncpus &&
32489ca63b3Smpi 	    cpu_info[cpu].ci_ddb_paused != CI_DDB_STOPPED) {
32589ca63b3Smpi 		cpu_info[cpu].ci_ddb_paused = CI_DDB_SHOULDSTOP;
3266c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
32789ca63b3Smpi 		ppc_send_ipi(&cpu_info[cpu], PPC_IPI_DDB);
32889ca63b3Smpi 	} else {
3296c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
33089ca63b3Smpi 	}
33189ca63b3Smpi }
33289ca63b3Smpi #endif
333