1 /////////////////////////////////////////////////////////////////////////
2 // $Id: debugstuff.cc 14105 2021-01-30 20:31:03Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2001-2009  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
20 //
21 /////////////////////////////////////////////////////////////////////////
22 
23 #define NEED_CPU_REG_SHORTCUTS 1
24 #include "bochs.h"
25 #include "cpu.h"
26 #define LOG_THIS BX_CPU_THIS_PTR
27 
28 #include "memory/memory-bochs.h"
29 #include "pc_system.h"
30 
debug_disasm_instruction(bx_address offset)31 void BX_CPU_C::debug_disasm_instruction(bx_address offset)
32 {
33 #if BX_DEBUGGER
34   bx_dbg_disassemble_current(BX_CPU_ID, 1); // only one cpu, print time stamp
35 #else
36   bx_phy_address phy_addr;
37   Bit8u  instr_buf[16];
38   char   char_buf[512];
39   size_t i=0;
40 
41   static char letters[] = "0123456789ABCDEF";
42   unsigned remainsInPage = 0x1000 - PAGE_OFFSET(offset);
43 
44   bool valid = dbg_xlate_linear2phy(get_laddr(BX_SEG_REG_CS, offset), &phy_addr);
45   if (valid) {
46     BX_MEM(0)->dbg_fetch_mem(BX_CPU_THIS, phy_addr, 16, instr_buf);
47 
48     bxInstruction_c instr;
49     disasm(instr_buf,
50       BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b,
51       BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64, char_buf+i, &instr,
52       BX_CPU_THIS_PTR get_segment_base(BX_SEG_REG_CS), offset, BX_DISASM_INTEL);
53     unsigned isize = instr.ilen();
54 
55     if (isize <= remainsInPage) {
56       i=strlen(char_buf);
57       char_buf[i++] = ' ';
58       char_buf[i++] = ':';
59       char_buf[i++] = ' ';
60       for (unsigned j=0; j<isize; j++) {
61         char_buf[i++] = letters[(instr_buf[j] >> 4) & 0xf];
62         char_buf[i++] = letters[(instr_buf[j] >> 0) & 0xf];
63       }
64       char_buf[i] = 0;
65       BX_INFO(("0x" FMT_ADDRX ">> %s", offset, char_buf));
66     }
67     else {
68       BX_INFO(("0x" FMT_ADDRX ": (instruction unavailable) page split instruction", offset));
69     }
70   }
71   else {
72     BX_INFO(("0x" FMT_ADDRX ": (instruction unavailable) page not present", offset));
73   }
74 #endif  // #if BX_DEBUGGER
75 }
76 
cpu_mode_string(unsigned cpu_mode)77 const char* cpu_mode_string(unsigned cpu_mode)
78 {
79   static const char *cpu_mode_name[] = {
80      "real mode",
81      "v8086 mode",
82      "protected mode",
83      "compatibility mode",
84      "long mode",
85      "unknown mode"
86   };
87 
88   if(cpu_mode >= 5) cpu_mode = 5;
89   return cpu_mode_name[cpu_mode];
90 }
91 
cpu_state_string(unsigned state)92 const char* cpu_state_string(unsigned state)
93 {
94   static const char *cpu_state_name[] = {
95      "active",
96      "halted",
97      "in shutdown",
98      "waiting for SIPI",
99      "executing mwait",
100      "executing mwait inhibit interrupts",
101      "unknown state"
102   };
103 
104   if(state >= 6) state = 6;
105   return cpu_state_name[state];
106 }
107 
debug(bx_address offset)108 void BX_CPU_C::debug(bx_address offset)
109 {
110 #if BX_SUPPORT_VMX
111   BX_INFO(("CPU is in %s (%s%s)", cpu_mode_string(BX_CPU_THIS_PTR get_cpu_mode()),
112     cpu_state_string(BX_CPU_THIS_PTR activity_state),
113     BX_CPU_THIS_PTR in_vmx_guest ? ", vmx guest" : ""));
114 #else
115   BX_INFO(("CPU is in %s (%s)", cpu_mode_string(BX_CPU_THIS_PTR get_cpu_mode()),
116     cpu_state_string(BX_CPU_THIS_PTR activity_state)));
117 #endif
118   BX_INFO(("CS.mode = %u bit",
119     long64_mode() ? 64 : (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b ? 32 : 16)));
120   BX_INFO(("SS.mode = %u bit",
121     long64_mode() ? 64 : (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b ? 32 : 16)));
122 #if BX_CPU_LEVEL >= 5
123   BX_INFO(("EFER   = 0x%08x", BX_CPU_THIS_PTR efer.get32()));
124 #endif
125 #if BX_SUPPORT_X86_64
126   if (long_mode()) {
127     BX_INFO(("| RAX=" FMT_ADDRX64 "  RBX=" FMT_ADDRX64 "", RAX, RBX));
128     BX_INFO(("| RCX=" FMT_ADDRX64 "  RDX=" FMT_ADDRX64 "", RCX, RDX));
129     BX_INFO(("| RSP=" FMT_ADDRX64 "  RBP=" FMT_ADDRX64 "", RSP, RBP));
130     BX_INFO(("| RSI=" FMT_ADDRX64 "  RDI=" FMT_ADDRX64 "", RSI, RDI));
131     BX_INFO(("|  R8=" FMT_ADDRX64 "   R9=" FMT_ADDRX64 "", R8,  R9));
132     BX_INFO(("| R10=" FMT_ADDRX64 "  R11=" FMT_ADDRX64 "", R10, R11));
133     BX_INFO(("| R12=" FMT_ADDRX64 "  R13=" FMT_ADDRX64 "", R12, R13));
134     BX_INFO(("| R14=" FMT_ADDRX64 "  R15=" FMT_ADDRX64 "", R14, R15));
135   }
136   else
137 #endif
138   {
139     BX_INFO(("| EAX=%08x  EBX=%08x  ECX=%08x  EDX=%08x", EAX, EBX, ECX, EDX));
140     BX_INFO(("| ESP=%08x  EBP=%08x  ESI=%08x  EDI=%08x", ESP, EBP, ESI, EDI));
141   }
142   BX_INFO(("| IOPL=%1u %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
143     BX_CPU_THIS_PTR get_IOPL(),
144     BX_CPU_THIS_PTR get_ID() ? "ID" : "id",
145     BX_CPU_THIS_PTR get_VIP() ? "VIP" : "vip",
146     BX_CPU_THIS_PTR get_VIF() ? "VIF" : "vif",
147     BX_CPU_THIS_PTR get_AC() ? "AC" : "ac",
148     BX_CPU_THIS_PTR get_VM() ? "VM" : "vm",
149     BX_CPU_THIS_PTR get_RF() ? "RF" : "rf",
150     BX_CPU_THIS_PTR get_NT() ? "NT" : "nt",
151     BX_CPU_THIS_PTR get_OF() ? "OF" : "of",
152     BX_CPU_THIS_PTR get_DF() ? "DF" : "df",
153     BX_CPU_THIS_PTR get_IF() ? "IF" : "if",
154     BX_CPU_THIS_PTR get_TF() ? "TF" : "tf",
155     BX_CPU_THIS_PTR get_SF() ? "SF" : "sf",
156     BX_CPU_THIS_PTR get_ZF() ? "ZF" : "zf",
157     BX_CPU_THIS_PTR get_AF() ? "AF" : "af",
158     BX_CPU_THIS_PTR get_PF() ? "PF" : "pf",
159     BX_CPU_THIS_PTR get_CF() ? "CF" : "cf"));
160 
161   BX_INFO(("| SEG sltr(index|ti|rpl)     base    limit G D"));
162   BX_INFO(("|  CS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u",
163     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
164     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index,
165     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti,
166     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl,
167     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base,
168     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled,
169     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g,
170     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b));
171   BX_INFO(("|  DS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u",
172     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value,
173     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.index,
174     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.ti,
175     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.rpl,
176     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.base,
177     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled,
178     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g,
179     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.d_b));
180   BX_INFO(("|  SS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u",
181     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value,
182     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.index,
183     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.ti,
184     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl,
185     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base,
186     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled,
187     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g,
188     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b));
189   BX_INFO(("|  ES:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u",
190     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value,
191     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.index,
192     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.ti,
193     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.rpl,
194     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.base,
195     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit_scaled,
196     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.g,
197     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.d_b));
198   BX_INFO(("|  FS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u",
199     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value,
200     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.index,
201     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.ti,
202     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.rpl,
203     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base,
204     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit_scaled,
205     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.g,
206     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.d_b));
207   BX_INFO(("|  GS:%04x( %04x| %01u|  %1u) %08x %08x %1u %1u",
208     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value,
209     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.index,
210     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.ti,
211     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.rpl,
212     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base,
213     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit_scaled,
214     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.g,
215     (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.d_b));
216 #if BX_SUPPORT_X86_64
217   if (long_mode()) {
218     BX_INFO(("|  MSR_FS_BASE:" FMT_ADDRX64,
219       MSR_FSBASE));
220     BX_INFO(("|  MSR_GS_BASE:" FMT_ADDRX64,
221       MSR_GSBASE));
222 
223     BX_INFO(("| RIP=" FMT_ADDRX64 " (" FMT_ADDRX64 ")",
224       BX_CPU_THIS_PTR gen_reg[BX_64BIT_REG_RIP].rrx,
225       BX_CPU_THIS_PTR prev_rip));
226     BX_INFO(("| CR0=0x%08x CR2=0x" FMT_ADDRX64,
227       (BX_CPU_THIS_PTR cr0.get32()),
228       (BX_CPU_THIS_PTR cr2)));
229     BX_INFO(("| CR3=0x" FMT_ADDRX64 " CR4=0x%08x",
230       BX_CPU_THIS_PTR cr3, BX_CPU_THIS_PTR cr4.get32()));
231   }
232   else
233 #endif // BX_SUPPORT_X86_64
234   {
235     BX_INFO(("| EIP=%08x (%08x)", (unsigned) EIP,
236       (unsigned) BX_CPU_THIS_PTR prev_rip));
237 
238 #if BX_CPU_LEVEL < 5
239     BX_INFO(("| CR0=0x%08x CR2=0x%08x CR3=0x%08x",
240       (unsigned) BX_CPU_THIS_PTR cr0.get32(),
241       (unsigned) BX_CPU_THIS_PTR cr2, (unsigned) BX_CPU_THIS_PTR cr3));
242 #else
243     BX_INFO(("| CR0=0x%08x CR2=0x%08x",
244       BX_CPU_THIS_PTR cr0.get32(), (unsigned) BX_CPU_THIS_PTR cr2));
245     BX_INFO(("| CR3=0x%08x CR4=0x%08x",
246       (unsigned) BX_CPU_THIS_PTR cr3,
247       (unsigned) BX_CPU_THIS_PTR cr4.get32()));
248 #endif
249   }
250 
251   debug_disasm_instruction(offset);
252 }
253 
254 
255 #if BX_DEBUGGER
dbg_set_eip(bx_address val)256 void BX_CPU_C::dbg_set_eip(bx_address val)
257 {
258   RIP = BX_CPU_THIS_PTR prev_rip = val;
259   invalidate_prefetch_q();
260 }
261 
dbg_set_eflags(Bit32u val)262 bool BX_CPU_C::dbg_set_eflags(Bit32u val)
263 {
264   // returns 1=OK, 0=can't change
265 
266   if (val & 0xffff0000) {
267     BX_INFO(("dbg_set_eflags: can't set upper 16 bits of EFLAGS !"));
268     return(0);
269   }
270 
271   // make sure none of the system bits are being changed
272   Bit32u current_sys_bits = ((BX_CPU_THIS_PTR getB_NT()) << 14) |
273                              (BX_CPU_THIS_PTR get_IOPL () << 12) |
274                             ((BX_CPU_THIS_PTR getB_TF()) << 8);
275   if (current_sys_bits != (val & 0x0000f100)) {
276     BX_INFO(("dbg_set_eflags: can't modify NT, IOPL, or TF !"));
277     return(0);
278   }
279 
280   BX_CPU_THIS_PTR set_CF(val & 0x01); val >>= 2;
281   BX_CPU_THIS_PTR set_PF(val & 0x01); val >>= 2;
282   BX_CPU_THIS_PTR set_AF(val & 0x01); val >>= 2;
283   BX_CPU_THIS_PTR set_ZF(val & 0x01); val >>= 1;
284   BX_CPU_THIS_PTR set_SF(val & 0x01); val >>= 2;
285   BX_CPU_THIS_PTR set_DF(val & 0x01); val >>= 1;
286   BX_CPU_THIS_PTR set_OF(val & 0x01);
287   return(1);
288 }
289 
dbg_query_pending(void)290 unsigned BX_CPU_C::dbg_query_pending(void)
291 {
292   unsigned ret = 0;
293 
294   if (BX_HRQ) {  // DMA Hold Request
295     ret |= BX_DBG_PENDING_DMA;
296   }
297 
298   if (is_unmasked_event_pending(BX_EVENT_PENDING_INTR)) {
299     ret |= BX_DBG_PENDING_IRQ;
300   }
301 
302   return ret;
303 }
304 
dbg_get_sreg(bx_dbg_sreg_t * sreg,unsigned sreg_no)305 bool BX_CPU_C::dbg_get_sreg(bx_dbg_sreg_t *sreg, unsigned sreg_no)
306 {
307   if (sreg_no > 5)
308     return(0);
309   sreg->valid = BX_CPU_THIS_PTR sregs[sreg_no].cache.valid;
310   sreg->sel   = BX_CPU_THIS_PTR sregs[sreg_no].selector.value;
311   sreg->des_l = get_descriptor_l(&BX_CPU_THIS_PTR sregs[sreg_no].cache);
312   sreg->des_h = get_descriptor_h(&BX_CPU_THIS_PTR sregs[sreg_no].cache);
313 #if BX_SUPPORT_X86_64
314   sreg->dword3 = BX_CPU_THIS_PTR sregs[sreg_no].cache.u.segment.base >> 32;
315 #endif
316   return(1);
317 }
318 
dbg_set_sreg(unsigned sreg_no,bx_segment_reg_t * sreg)319 bool BX_CPU_C::dbg_set_sreg(unsigned sreg_no, bx_segment_reg_t *sreg)
320 {
321   if (sreg_no < 6) {
322     BX_CPU_THIS_PTR sregs[sreg_no] = *sreg;
323     if (sreg_no == BX_SEG_REG_CS) {
324       handleCpuModeChange();
325 #if BX_CPU_LEVEL >= 4
326       handleAlignmentCheck(/* CPL change */);
327 #endif
328       invalidate_prefetch_q();
329       return 1;
330     }
331   }
332 
333   return 0;
334 }
335 
dbg_get_tr(bx_dbg_sreg_t * sreg)336 void BX_CPU_C::dbg_get_tr(bx_dbg_sreg_t *sreg)
337 {
338   sreg->valid = BX_CPU_THIS_PTR tr.cache.valid;
339   sreg->sel   = BX_CPU_THIS_PTR tr.selector.value;
340   sreg->des_l = get_descriptor_l(&BX_CPU_THIS_PTR tr.cache);
341   sreg->des_h = get_descriptor_h(&BX_CPU_THIS_PTR tr.cache);
342 #if BX_SUPPORT_X86_64
343   sreg->dword3 = BX_CPU_THIS_PTR tr.cache.u.segment.base >> 32;
344 #endif
345 }
346 
dbg_get_ldtr(bx_dbg_sreg_t * sreg)347 void BX_CPU_C::dbg_get_ldtr(bx_dbg_sreg_t *sreg)
348 {
349   sreg->valid = BX_CPU_THIS_PTR ldtr.cache.valid;
350   sreg->sel   = BX_CPU_THIS_PTR ldtr.selector.value;
351   sreg->des_l = get_descriptor_l(&BX_CPU_THIS_PTR ldtr.cache);
352   sreg->des_h = get_descriptor_h(&BX_CPU_THIS_PTR ldtr.cache);
353 #if BX_SUPPORT_X86_64
354   sreg->dword3 = BX_CPU_THIS_PTR ldtr.cache.u.segment.base >> 32;
355 #endif
356 }
357 
dbg_get_gdtr(bx_dbg_global_sreg_t * sreg)358 void BX_CPU_C::dbg_get_gdtr(bx_dbg_global_sreg_t *sreg)
359 {
360   sreg->base  = BX_CPU_THIS_PTR gdtr.base;
361   sreg->limit = BX_CPU_THIS_PTR gdtr.limit;
362 }
363 
dbg_get_idtr(bx_dbg_global_sreg_t * sreg)364 void BX_CPU_C::dbg_get_idtr(bx_dbg_global_sreg_t *sreg)
365 {
366   sreg->base  = BX_CPU_THIS_PTR idtr.base;
367   sreg->limit = BX_CPU_THIS_PTR idtr.limit;
368 }
369 
370 #endif  // #if BX_DEBUGGER
371 
atexit(void)372 void BX_CPU_C::atexit(void)
373 {
374   debug(BX_CPU_THIS_PTR prev_rip);
375 }
376