Bochs/bochs/iodev/iodebug.cc

308 lines
8.3 KiB
C++
Raw Normal View History

/////////////////////////////////////////////////////////////////////////
// $Id: iodebug.cc,v 1.25 2008-02-15 22:05:42 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
#include "bochs.h"
#include "cpu/cpu.h"
#include "iodev.h"
#if BX_SUPPORT_IODEBUG
#define BX_IODEBUG_THIS this->
bx_iodebug_c bx_iodebug;
struct bx_iodebug_s_type {
- Apply patch.replace-Boolean rev 1.3. Every "Boolean" is now changed to a "bx_bool" which is always defined as Bit32u on all platforms. In Carbon specific code, Boolean is still used because the Carbon header files define it to unsigned char. - this fixes bug [ 623152 ] MacOSX: Triple Exception Booting win95. The bug was that some code in Bochs depends on Boolean to be a 32 bit value. (This should be fixed, but I don't know all the places where it needs to be fixed yet.) Because Carbon defined Boolean as an unsigned char, Bochs just followed along and used the unsigned char definition to avoid compile problems. This exposed the dependency on 32 bit Boolean on MacOS X only and led to major simulation problems, that could only be reproduced and debugged on that platform. - On the mailing list we debated whether to make all Booleans into "bool" or our own type. I chose bx_bool for several reasons. 1. Unlike C++'s bool, we can guarantee that bx_bool is the same size on all platforms, which makes it much less likely to have more platform-specific simulation differences in the future. (I spent hours on a borrowed MacOSX machine chasing bug 618388 before discovering that different sized Booleans were the problem, and I don't want to repeat that.) 2. We still have at least one dependency on 32 bit Booleans which must be fixed some time, but I don't want to risk introducing new bugs into the simulation just before the 2.0 release. Modified Files: bochs.h config.h.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h plugin.cc plugin.h bios/rombios.c cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith64.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer16.cc cpu/ctrl_xfer32.cc cpu/ctrl_xfer64.cc cpu/data_xfer16.cc cpu/data_xfer32.cc cpu/data_xfer64.cc cpu/debugstuff.cc cpu/exception.cc cpu/fetchdecode.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io_pro.cc cpu/lazy_flags.cc cpu/lazy_flags.h cpu/mult16.cc cpu/mult32.cc cpu/mult64.cc cpu/mult8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/segment_ctrl_pro.cc cpu/stack_pro.cc cpu/tasking.cc debug/dbg_main.cc debug/debug.h debug/sim2.cc disasm/dis_decode.cc disasm/disasm.h doc/docbook/Makefile docs-html/cosimulation.html fpu/wmFPUemu_glue.cc gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxmain.cc gui/wxmain.h gui/x.cc instrument/example0/instrument.cc instrument/example0/instrument.h instrument/example1/instrument.cc instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/cdrom.cc iodev/cdrom.h iodev/cdrom_osx.cc iodev/cmos.cc iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_arpback.cc iodev/eth_packetmaker.cc iodev/eth_packetmaker.h iodev/floppy.cc iodev/floppy.h iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/ioapic.cc iodev/ioapic.h iodev/iodebug.cc iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.h iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/serial.cc iodev/serial.h iodev/vga.cc iodev/vga.h memory/memory.h memory/misc_mem.cc
2002-10-25 15:44:41 +04:00
bx_bool enabled;
unsigned register_select;
Bit32u registers[2];
Bit32u monitored_mem_areas_start[BX_IODEBUG_MAX_AREAS];
Bit32u monitored_mem_areas_end[BX_IODEBUG_MAX_AREAS];
} bx_iodebug_s;
bx_iodebug_c::bx_iodebug_c()
{
put("IODBG");
settype(IODEBUGLOG);
}
2002-10-26 07:53:22 +04:00
void bx_iodebug_c::init(void)
{
DEV_register_ioread_handler(this, read_handler, 0x8A00,"BOCHS IODEBUG", 2);
DEV_register_iowrite_handler(this, write_handler, 0x8A00,"BOCHS IODEBUG", 2);
DEV_register_iowrite_handler(this, write_handler, 0x8A01,"BOCHS IODEBUG", 2);
bx_iodebug_s.enabled = 0;
bx_iodebug_s.register_select = 0;
for(int i=0;i<BX_IODEBUG_MAX_AREAS;i++) {
bx_iodebug_s.monitored_mem_areas_start[i] = 0;
bx_iodebug_s.monitored_mem_areas_end[i] = 0;
}
}
Bit32u bx_iodebug_c::read_handler(void *this_ptr, Bit32u addr, unsigned io_len)
{
bx_iodebug_c *bx_iodebug_ptr = (bx_iodebug_c *) this_ptr;
return bx_iodebug_ptr->read(addr, io_len);
}
Bit32u bx_iodebug_c::read(Bit32u addr, unsigned io_len)
{
if (bx_iodebug_s.enabled) return 0x8A00;
return(0);
}
void bx_iodebug_c::write_handler(void *this_ptr, Bit32u addr, Bit32u dvalue, unsigned io_len)
{
bx_iodebug_c *bx_iodebug_ptr = (bx_iodebug_c *) this_ptr;
bx_iodebug_ptr->write(addr, dvalue, io_len);
}
void bx_iodebug_c::write(Bit32u addr, Bit32u dvalue, unsigned io_len)
{
// fprintf(stderr, "IODEBUG addr: %4x\tdvalue: %8x\tio_len: %8x\n", (unsigned) addr, (unsigned) dvalue, io_len);
if (addr == 0x8A01)
{
bx_iodebug_s.registers[bx_iodebug_s.register_select] =
(bx_iodebug_s.registers[bx_iodebug_s.register_select] << 16) +
(dvalue & 0xFFFF);
}
if (addr != 0x8A00) return;
if (!bx_iodebug_s.enabled)
{
if(dvalue == 0x8A00)
{
bx_iodebug_s.enabled = 1;
// fprintf(stderr, "IODEBUG enabled\n");
bx_iodebug_s.registers[0] = 0;
bx_iodebug_s.registers[1] = 0;
}
return;
}
switch(dvalue)
{
case 0x8A01:
bx_iodebug_s.register_select = 0;
// fprintf(stderr, "IODEBUG register 0 selected\n");
break;
case 0x8A02:
bx_iodebug_s.register_select = 1;
// fprintf(stderr, "IODEBUG register 1 selected\n");
break;
case 0x8A80:
bx_iodebug_s.register_select = 0;
bx_iodebug_c::add_range(bx_iodebug_s.registers[0],
bx_iodebug_s.registers[1]);
bx_iodebug_s.registers[0] = 0;
bx_iodebug_s.registers[1] = 0;
break;
#if BX_DEBUGGER
case 0x8AE0:
fprintf(stderr, "request return to dbg prompt received, 0x8AE0 command (iodebug)\n");
bx_guard.interrupt_requested=1;
break;
case 0x8AE2:
fprintf(stderr, "request made by the guest os to disable tracing, iodebug port 0x8A00->0x8AE2\n");
BX_CPU(dbg_cpu)->trace = 0;
break;
case 0x8AE3:
fprintf(stderr, "request made by the guest os to enable tracing, iodebug port 0x8A00->0x8AE3\n");
BX_CPU(dbg_cpu)->trace = 1;
break;
case 0x8AE4:
fprintf(stderr, "request made by the guest os to disable register tracing, iodebug port 0x8A00->0x8AE4\n");
BX_CPU(dbg_cpu)->trace_reg = 0;
break;
case 0x8AE5:
fprintf(stderr, "request made by the guest os to enable register tracing, iodebug port 0x8A00->0x8AE5\n");
BX_CPU(dbg_cpu)->trace_reg = 1;
break;
#endif
case 0x8AFF:
bx_iodebug_s.enabled = 0;
// fprintf(stderr, "IODEBUG device deactivated\n");
// break;
// default:
// fprintf(stderr,"IODEBUG unsupported register code\n");
}
}
// Static function
void bx_iodebug_c::mem_write(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
{
if(! bx_iodebug_s.enabled) return;
unsigned area = bx_iodebug_c::range_test(addr, len);
// Device is enabled, testing address ranges
if(area)
{
area--;
#if BX_DEBUGGER
if (cpu != NULL) {
fprintf(stdout, "IODEBUG %s @ eip: " FMT_ADDRX " write at monitored memory location %8X\n",
cpu->name, cpu->get_instruction_pointer(), addr);
}
else {
fprintf(stdout, "IODEBUG write at monitored memory location %8X\n", addr);
}
2005-11-14 22:03:12 +03:00
bx_guard.interrupt_requested=1;
#else
fprintf(stderr, "IODEBUG write to monitored memory area: %2i\t", area);
if (cpu != NULL)
fprintf(stderr, "by EIP:\t\t" FMT_ADDRX "\n\t", cpu->get_instruction_pointer());
else
fprintf(stderr, "(device origin)\t", cpu->get_instruction_pointer());
fprintf(stderr, "range start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t",
bx_iodebug_s.monitored_mem_areas_start[area],
bx_iodebug_s.monitored_mem_areas_end[area],
(unsigned) addr);
switch(len)
{
case 1: {
Bit8u data8 = * ((Bit8u *) data);
fprintf(stderr,"%02X\n", (unsigned) data8);
break;
}
case 2: {
Bit16u data16 = * ((Bit16u *) data);
fprintf(stderr,"%04X\n", (unsigned) data16);
break;
}
case 4: {
Bit32u data32 = * ((Bit32u *) data);
fprintf(stderr,"%08X\n", (unsigned) data32);
break;
}
case 8: {
Bit64u data64 = * ((Bit64u *) data);
fprintf(stderr,"%08X%08x\n",
(unsigned) (data64 >> 32),
(unsigned) (data64 & 0xffffffff));
break;
}
default:
fprintf(stderr, "unsupported write size\n");
}
#endif
}
}
void bx_iodebug_c::mem_read(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
{
if(! bx_iodebug_s.enabled) return;
unsigned area = bx_iodebug_c::range_test(addr, len);
// Device is enabled, testing address ranges
if(area)
{
area--;
#if BX_DEBUGGER
if (cpu != NULL) {
fprintf(stdout, "IODEBUG %s @ eip: " FMT_ADDRX " read at monitored memory location %8X\n",
cpu->name, cpu->get_instruction_pointer(), addr);
}
else {
fprintf(stdout, "IODEBUG read at monitored memory location %8X\n", addr);
}
2005-11-14 22:03:12 +03:00
bx_guard.interrupt_requested=1;
#else
fprintf(stderr, "IODEBUG read at monitored memory area: %2i\t", area);
if (cpu != NULL)
fprintf(stderr, "by EIP:\t\t" FMT_ADDRX "\n\t", cpu->get_instruction_pointer());
else
fprintf(stderr, "(device origin)\t", cpu->get_instruction_pointer());
fprintf(stderr, "range start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t",
bx_iodebug_s.monitored_mem_areas_start[area],
bx_iodebug_s.monitored_mem_areas_end[area],
(unsigned) addr);
switch(len)
{
case 1: {
Bit8u data8 = * ((Bit8u *) data);
fprintf(stderr,"%02X\n", (unsigned) data8);
break;
}
case 2: {
Bit16u data16 = * ((Bit16u *) data);
fprintf(stderr,"%04X\n", (unsigned) data16);
break;
}
case 4: {
Bit32u data32 = * ((Bit32u *) data);
fprintf(stderr,"%08X\n", (unsigned) data32);
break;
}
case 8: {
Bit64u data64 = * ((Bit64u *) data);
fprintf(stderr,"%08X%08x\n",
(unsigned) (data64 >> 32),
(unsigned) (data64 & 0xffffffff));
break;
}
default:
fprintf(stderr, "unsupported read size\n");
}
#endif
}
}
unsigned bx_iodebug_c::range_test(Bit32u addr, unsigned len)
{
for(unsigned i=0;i<BX_IODEBUG_MAX_AREAS;i++)
{
if((bx_iodebug_s.monitored_mem_areas_start[i]!=0) ||
(bx_iodebug_s.monitored_mem_areas_end[i]!=0))
{
if((Bit32u)(addr+len-1) < bx_iodebug_s.monitored_mem_areas_start[i])
continue;
if(addr < bx_iodebug_s.monitored_mem_areas_end[i])
{
return(++i);
}
}
}
return(0);
}
void bx_iodebug_c::add_range(Bit32u addr_start, Bit32u addr_end)
{
for(unsigned i=0;i<BX_IODEBUG_MAX_AREAS;i++)
{
if(!bx_iodebug_s.monitored_mem_areas_start[i] &&
!bx_iodebug_s.monitored_mem_areas_end[i])
{
bx_iodebug_s.monitored_mem_areas_start[i] = addr_start;
bx_iodebug_s.monitored_mem_areas_end[i] = addr_end;
// fprintf(stderr, "IODEBUG added range successfully in slot: %i\n",i);
return;
}
}
// fprintf(stderr, "IODEBUG unable to register memory range, all slots taken\n");
}
#endif /* if BX_SUPPORT_IODEBUG */