Blame view

kernel/debug/kdb/kdb_debugger.c 4.31 KB
5d5314d67   Jason Wessel   kdb: core for kgd...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * Created by: Jason Wessel <jason.wessel@windriver.com>
   *
   * Copyright (c) 2009 Wind River Systems, Inc.  All Rights Reserved.
   *
   * This file is licensed under the terms of the GNU General Public
   * License version 2. This program is licensed "as is" without any
   * warranty of any kind, whether express or implied.
   */
  
  #include <linux/kgdb.h>
  #include <linux/kdb.h>
  #include <linux/kdebug.h>
6e5fdeedc   Paul Gortmaker   kernel: Fix files...
14
  #include <linux/export.h>
b10d22d6e   Anton Vorontsov   kernel/debug: Mak...
15
  #include <linux/hardirq.h>
5d5314d67   Jason Wessel   kdb: core for kgd...
16
17
18
19
20
21
22
23
24
  #include "kdb_private.h"
  #include "../debug_core.h"
  
  /*
   * KDB interface to KGDB internals
   */
  get_char_func kdb_poll_funcs[] = {
  	dbg_io_get_char,
  	NULL,
f5316b4ae   Jason Wessel   kgdb,8250,pl011: ...
25
26
27
28
  	NULL,
  	NULL,
  	NULL,
  	NULL,
5d5314d67   Jason Wessel   kdb: core for kgd...
29
  };
f5316b4ae   Jason Wessel   kgdb,8250,pl011: ...
30
31
32
33
  EXPORT_SYMBOL_GPL(kdb_poll_funcs);
  
  int kdb_poll_idx = 1;
  EXPORT_SYMBOL_GPL(kdb_poll_idx);
5d5314d67   Jason Wessel   kdb: core for kgd...
34

f679c4985   Jason Wessel   kdb,kgdb: Impleme...
35
  static struct kgdb_state *kdb_ks;
5d5314d67   Jason Wessel   kdb: core for kgd...
36
37
38
39
40
41
42
43
  int kdb_stub(struct kgdb_state *ks)
  {
  	int error = 0;
  	kdb_bp_t *bp;
  	unsigned long addr = kgdb_arch_pc(ks->ex_vector, ks->linux_regs);
  	kdb_reason_t reason = KDB_REASON_OOPS;
  	kdb_dbtrap_t db_result = KDB_DB_NOBPT;
  	int i;
f679c4985   Jason Wessel   kdb,kgdb: Impleme...
44
  	kdb_ks = ks;
5d5314d67   Jason Wessel   kdb: core for kgd...
45
46
47
48
49
50
51
52
  	if (KDB_STATE(REENTRY)) {
  		reason = KDB_REASON_SWITCH;
  		KDB_STATE_CLEAR(REENTRY);
  		addr = instruction_pointer(ks->linux_regs);
  	}
  	ks->pass_exception = 0;
  	if (atomic_read(&kgdb_setting_breakpoint))
  		reason = KDB_REASON_KEYBOARD;
b10d22d6e   Anton Vorontsov   kernel/debug: Mak...
53
54
  	if (in_nmi())
  		reason = KDB_REASON_NMI;
5d5314d67   Jason Wessel   kdb: core for kgd...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  	for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) {
  		if ((bp->bp_enabled) && (bp->bp_addr == addr)) {
  			reason = KDB_REASON_BREAK;
  			db_result = KDB_DB_BPT;
  			if (addr != instruction_pointer(ks->linux_regs))
  				kgdb_arch_set_pc(ks->linux_regs, addr);
  			break;
  		}
  	}
  	if (reason == KDB_REASON_BREAK || reason == KDB_REASON_SWITCH) {
  		for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) {
  			if (bp->bp_free)
  				continue;
  			if (bp->bp_addr == addr) {
  				bp->bp_delay = 1;
  				bp->bp_delayed = 1;
  	/*
  	 * SSBPT is set when the kernel debugger must single step a
  	 * task in order to re-establish an instruction breakpoint
  	 * which uses the instruction replacement mechanism.  It is
  	 * cleared by any action that removes the need to single-step
  	 * the breakpoint.
  	 */
  				reason = KDB_REASON_BREAK;
  				db_result = KDB_DB_BPT;
  				KDB_STATE_SET(SSBPT);
  				break;
  			}
  		}
  	}
  
  	if (reason != KDB_REASON_BREAK && ks->ex_vector == 0 &&
  		ks->signo == SIGTRAP) {
  		reason = KDB_REASON_SSTEP;
  		db_result = KDB_DB_BPT;
  	}
  	/* Set initial kdb state variables */
  	KDB_STATE_CLEAR(KGDB_TRANS);
495363d38   Jason Wessel   kdb,debug_core: a...
93
  	kdb_initial_cpu = atomic_read(&kgdb_active);
5d5314d67   Jason Wessel   kdb: core for kgd...
94
95
96
97
98
99
  	kdb_current_task = kgdb_info[ks->cpu].task;
  	kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
  	/* Remove any breakpoints as needed by kdb and clear single step */
  	kdb_bp_remove();
  	KDB_STATE_CLEAR(DOING_SS);
  	KDB_STATE_CLEAR(DOING_SSB);
f5316b4ae   Jason Wessel   kgdb,8250,pl011: ...
100
  	KDB_STATE_SET(PAGER);
5d5314d67   Jason Wessel   kdb: core for kgd...
101
102
103
104
105
106
107
108
109
110
111
  	/* zero out any offline cpu data */
  	for_each_present_cpu(i) {
  		if (!cpu_online(i)) {
  			kgdb_info[i].debuggerinfo = NULL;
  			kgdb_info[i].task = NULL;
  		}
  	}
  	if (ks->err_code == DIE_OOPS || reason == KDB_REASON_OOPS) {
  		ks->pass_exception = 1;
  		KDB_FLAG_SET(CATASTROPHIC);
  	}
5d5314d67   Jason Wessel   kdb: core for kgd...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  	if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) {
  		KDB_STATE_CLEAR(SSBPT);
  		KDB_STATE_CLEAR(DOING_SS);
  	} else {
  		/* Start kdb main loop */
  		error = kdb_main_loop(KDB_REASON_ENTER, reason,
  				      ks->err_code, db_result, ks->linux_regs);
  	}
  	/*
  	 * Upon exit from the kdb main loop setup break points and restart
  	 * the system based on the requested continue state
  	 */
  	kdb_initial_cpu = -1;
  	kdb_current_task = NULL;
  	kdb_current_regs = NULL;
f5316b4ae   Jason Wessel   kgdb,8250,pl011: ...
127
  	KDB_STATE_CLEAR(PAGER);
5d5314d67   Jason Wessel   kdb: core for kgd...
128
129
  	kdbnearsym_cleanup();
  	if (error == KDB_CMD_KGDB) {
d613d828e   Jason Wessel   kdb: Remove all r...
130
  		if (KDB_STATE(DOING_KGDB))
5d5314d67   Jason Wessel   kdb: core for kgd...
131
  			KDB_STATE_CLEAR(DOING_KGDB);
5d5314d67   Jason Wessel   kdb: core for kgd...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  		return DBG_PASS_EVENT;
  	}
  	kdb_bp_install(ks->linux_regs);
  	dbg_activate_sw_breakpoints();
  	/* Set the exit state to a single step or a continue */
  	if (KDB_STATE(DOING_SS))
  		gdbstub_state(ks, "s");
  	else
  		gdbstub_state(ks, "c");
  
  	KDB_FLAG_CLEAR(CATASTROPHIC);
  
  	/* Invoke arch specific exception handling prior to system resume */
  	kgdb_info[ks->cpu].ret_state = gdbstub_state(ks, "e");
  	if (ks->pass_exception)
  		kgdb_info[ks->cpu].ret_state = 1;
  	if (error == KDB_CMD_CPU) {
  		KDB_STATE_SET(REENTRY);
  		/*
  		 * Force clear the single step bit because kdb emulates this
  		 * differently vs the gdbstub
  		 */
  		kgdb_single_step = 0;
  		dbg_deactivate_sw_breakpoints();
  		return DBG_SWITCH_CPU_EVENT;
  	}
  	return kgdb_info[ks->cpu].ret_state;
  }
f679c4985   Jason Wessel   kdb,kgdb: Impleme...
160
161
162
163
  void kdb_gdb_state_pass(char *buf)
  {
  	gdbstub_state(kdb_ks, buf);
  }