2 * GDB stub system manipultion code.
3 * NetWatch system management mode administration console
5 * Copyright 2009, Google Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
18 * * Neither the name of Google Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from
20 * this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 void send_stop_packet();
47 uint16_t saved_db_entry;
48 uint64_t saved_db_entry_location;
49 enum operating_mode step_start_mode;
50 uint64_t saved_cs_base;
51 uint64_t saved_eflags;
52 uint64_t saved_cs_limit;
53 uint64_t saved_cs_attrib;
54 uint64_t saved_ss_base;
55 uint64_t saved_ss_limit;
56 uint64_t saved_ss_attrib;
58 #define P64(x) (uint32_t)((x)>>32), (uint32_t)(x)
60 static const enum state_reg_t regs32 [] = {
61 STATE_REG_EAX, STATE_REG_ECX, STATE_REG_EDX, STATE_REG_EBX,
62 STATE_REG_ESP, STATE_REG_EBP, STATE_REG_ESI, STATE_REG_EDI,
63 STATE_REG_EIP, STATE_REG_EFLAGS, STATE_REG_CS, STATE_REG_SS,
64 STATE_REG_DS, STATE_REG_ES, STATE_REG_FS, STATE_REG_GS
67 static enum run_mode run_mode;
69 void set_run_mode(enum run_mode mode) {
73 int gdb_post_smi_hook() {
77 enum operating_mode m = get_operating_mode();
82 /* Until we have a better way of handling this - spin in
87 /* First, set RFLAGS.TF */
88 r = state_get_reg(STATE_REG_EFLAGS);
91 /* We also don't want to deal with interrupts. */
93 state_set_reg(STATE_REG_EFLAGS, r);
95 /* Track down the handler for a debug exception */
96 r = state_get_reg(STATE_REG_IDT_LIMIT);
97 r = state_get_reg(STATE_REG_IDT_BASE);
98 if (m == LONG_64BIT || m == LONG_COMPAT) {
99 /* 64-bit. Index up 16 bytes to get to the
100 * debug trap descriptor. */
102 entry = (*ptr) & 0xFFFF;
104 entry |= (*ptr) & 0xFFFF0000;
106 entry |= (uint64_t)(*ptr) << 32;
108 /* Assume 32-bit for now. */
110 entry = (*ptr) & 0xFFFF;
112 entry |= (*ptr) & 0xFFFF0000;
115 outputf("entry is at %08x %08x", (uint32_t)(entry>>32), (uint32_t)entry);
117 saved_db_entry_location = demap_phys(entry);
118 entry_v = p2v(saved_db_entry_location);
119 outputf("entry_v mapped to %08x", entry_v);
121 run_mode = RM_UNENCUMBERED; break;
123 saved_db_entry = *entry_v;
124 *entry_v = 0xB2E6; /* "out %al, $0xb2" */
128 /* Turn off the safety */
129 WRMSR(0xc0010054, 0x8002);
130 outputf("Have fun!");
132 saved_cs_base = state_get_reg(STATE_REG_CS_BASE);
133 saved_cs_limit = state_get_reg(STATE_REG_CS_LIMIT);
134 saved_cs_attrib = state_get_reg(STATE_REG_CS_ATTRIB);
135 saved_ss_base = state_get_reg(STATE_REG_SS_BASE);
136 saved_ss_limit = state_get_reg(STATE_REG_SS_LIMIT);
137 saved_ss_attrib = state_get_reg(STATE_REG_SS_ATTRIB);
142 /* There may be breakpoints. Fall through to
143 * "unencumbered" for now. */
145 case RM_UNENCUMBERED:
156 #define READ_QWORD(pa) ({ uint64_t * p = demap(pa); if (!p) goto fail; outputf("pq %08x %08x", (uint32_t)((*p)>>32), (uint32_t)(*p)); *p; })
157 #define READ_WORD(pa) ({ uint16_t * p = demap(pa); if (!p) goto fail; outputf("p %04x", (*p)); *p; })
159 static void gdb_unmangle_stepped_system() {
163 /* The unexpected breakpoint has caused an interrupt stack to be
164 * built, which we must get rid of. */
166 if (step_start_mode == LONG_64BIT) {
167 r = state_get_reg(STATE_REG_RSP);
168 state_set_reg(STATE_REG_RIP, READ_QWORD(r));
169 state_set_reg(STATE_REG_CS, READ_WORD(r+8));
170 state_set_reg(STATE_REG_RFLAGS, READ_QWORD(r+16));
171 state_set_reg(STATE_REG_RSP, READ_QWORD(r+24));
172 state_set_reg(STATE_REG_SS, READ_WORD(r+32));
173 } else if (step_start_mode == LONG_COMPAT) {
174 r = state_get_reg(STATE_REG_RSP);
175 state_set_reg(STATE_REG_RIP, READ_QWORD(r) & 0xFFFFFFFF);
176 state_set_reg(STATE_REG_CS, READ_WORD(r+8));
177 state_set_reg(STATE_REG_RFLAGS, READ_QWORD(r+16) & 0xFFFFFFFF);
178 state_set_reg(STATE_REG_RSP, READ_QWORD(r+24) & 0xFFFFFFFF);
179 state_set_reg(STATE_REG_SS, READ_WORD(r+32));
181 entry_v = p2v(saved_db_entry_location);
182 *entry_v = saved_db_entry;
184 state_set_reg(STATE_REG_CS_BASE, saved_cs_base);
185 state_set_reg(STATE_REG_CS_LIMIT, saved_cs_limit);
186 state_set_reg(STATE_REG_CS_ATTRIB, saved_cs_attrib);
187 state_set_reg(STATE_REG_SS_BASE, saved_ss_base);
188 state_set_reg(STATE_REG_SS_LIMIT, saved_ss_limit);
189 state_set_reg(STATE_REG_SS_ATTRIB, saved_ss_attrib);
190 state_set_reg(STATE_REG_EFLAGS, saved_eflags);
192 /* Put us back in "stopped" mode, until the GDB server gets around
193 * to handling the step.
196 reset_operating_mode_memo();
197 run_mode = RM_STOPPED;
203 outputf("ERROR: Failed to restore state!");
207 void gdb_pre_smi_hook() {
208 enum operating_mode m = get_operating_mode();
209 uint64_t ip, break_phys;
211 if (run_mode == RM_STEPPING) {
212 /* Oh hey, we are probably stopped on a breakpoint.
216 ? STATE_REG_RIP : STATE_REG_EIP
218 break_phys = demap_phys(ip);
220 if ((break_phys != saved_db_entry_location)
221 && (break_phys != saved_db_entry_location + 2)) {
222 /* Some other event caused us to enter SMM. We'll deal
223 * with the single step when we *actually* get to
228 /* Great. Now we have caused a debug exception.
230 * "Your problems just got worse. Think: what have you done?"
232 * We don't want the running system to know that anything
233 * ever happened, so we manually unwind the stack and undo
234 * everything that happened.
237 gdb_unmangle_stepped_system();
242 void read_registers_32 (char * buf) {
243 int i, r = 0, offset = 0, size = 0;
245 /* Dump registers to buffer. */
247 for (i = 0; i < (sizeof(regs32) / sizeof(enum state_reg_t)); i++) {
248 enum state_reg_t reg = regs32[i];
249 r = state_get_reg(reg);
250 //size = state_reg_size(reg);
252 enhexificate(&r, buf + offset, size);
253 offset += (size * 2);
256 /* XXX: The rest of the buffer "should be" filled with floating point
257 stuff. We'll worry about that later. */
260 void write_registers_32 (char * buf) {
264 uint32_t *ubuf = (uint32_t *)buf;
266 state_set_reg(STATE_REG_EAX, ubuf[0]);
267 state_set_reg(STATE_REG_ECX, ubuf[1]);
268 state_set_reg(STATE_REG_EDX, ubuf[2]);
269 state_set_reg(STATE_REG_EBX, ubuf[3]);
270 state_set_reg(STATE_REG_ESP, ubuf[4]);
271 state_set_reg(STATE_REG_EBP, ubuf[5]);
272 state_set_reg(STATE_REG_ESI, ubuf[6]);
273 state_set_reg(STATE_REG_EDI, ubuf[7]);
275 state_set_reg(STATE_REG_EIP, ubuf[8]);
276 state_set_reg(STATE_REG_EFLAGS, ubuf[9]);
277 state_set_reg(STATE_REG_CS, ubuf[10]);
278 state_set_reg(STATE_REG_SS, ubuf[11]);
279 state_set_reg(STATE_REG_DS, ubuf[12]);
280 state_set_reg(STATE_REG_ES, ubuf[13]);
281 state_set_reg(STATE_REG_FS, ubuf[14]);
282 state_set_reg(STATE_REG_GS, ubuf[15]);
284 /* XXX: Again, need to deal with floating point. */