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