cleanup and rename old doc abou cosimulation
This commit is contained in:
parent
ea7d5e74ee
commit
77f025b9b0
@ -1,278 +1,12 @@
|
||||
<HTML>
|
||||
|
||||
<HEAD>
|
||||
<META NAME="copyright" CONTENT="Copyright 2001 by MandrakeSoft S.A.">
|
||||
<META NAME="Author" CONTENT="Kevin Lawton">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
|
||||
<TITLE>Cosimulating: Using Bochs debugger to drive 2 simulators</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY TEXT="#000000" BGCOLOR="#ececec" LINK="#3333cc" VLINK="#666666">
|
||||
|
||||
<CENTER><H1><I>Welcome to the Bochs x86 PC Emulation Software Home Page!</I></H1></CENTER>
|
||||
|
||||
<CENTER><H1>Cosimulating: using Bochs debugger to drive 2 simulators</H1></CENTER>
|
||||
|
||||
<HR SIZE=5 NOSHADE>
|
||||
<H2>What is Cosimulation?</H2>
|
||||
|
||||
<IMG SRC="../doc/docbook/images/undercon.png" ALT="Under Construction">
|
||||
I'll add a discussion of cosimulation here soon.
|
||||
|
||||
<HR SIZE=5 NOSHADE>
|
||||
<H2>Cosimulation Programmatic Interface</H2>
|
||||
<IMG SRC="../doc/docbook/images/undercon.png" ALT="Under Construction">
|
||||
This documentation is not yet complete, and this interface is
|
||||
subject to change.
|
||||
|
||||
<HR>
|
||||
<HR>
|
||||
<H3>Callback Structure:</H3>
|
||||
|
||||
<P>Upon startup, the cosimulation controller (debugger) will initialize each
|
||||
simulator (or emulator) by calling an init routine. There are 2
|
||||
macro's in config.h (generated from config.h.in), which determine
|
||||
the names of the initialization routines, one for each simulator.
|
||||
These macro's are BX_SIM1_INIT and BX_SIM2_INIT. The first one
|
||||
likely can be kept as is. You will need to edit the second
|
||||
one, to be a routine in the second simulator which will receive
|
||||
a few parameters, and fill in a callback structure. This is the
|
||||
only routine in each simulator environment which is needed directly,
|
||||
as the callback routines which are filled in, are used subsequently.
|
||||
It should be of the type:
|
||||
|
||||
<PRE>
|
||||
void some_name_here(bx_dbg_callback_t *, int argc, char *argv[]);
|
||||
</PRE>
|
||||
|
||||
The <I>argc</I> and <I>argv</I> parameters are as you might expect.
|
||||
They consist of any simulator specific command line options passed to
|
||||
the bochs executable at program invocation time. Since there can be
|
||||
more than one simulator, command line options are delimited by
|
||||
<I>-sim1</I> and <I>-sim2</I> as in:
|
||||
|
||||
<PRE>
|
||||
Usage: bochs [-rc path] [-sim1 ... ] [-sim2 ...]
|
||||
</PRE>
|
||||
|
||||
The first parameter is the address of a callback structure, whose type
|
||||
<I>bx_dbg_callback_t</I> is defined in bx_debug/debug.h. Most fields
|
||||
are function pointers, though some are not. Below, is a description
|
||||
of each field in the callback structure.
|
||||
|
||||
<P>
|
||||
<PRE>
|
||||
typedef struct {
|
||||
bx_bool (*setphymem)(Bit32u addr, unsigned len, Bit8u *buf);
|
||||
bx_bool (*getphymem)(Bit32u addr, unsigned len, Bit8u *buf);
|
||||
void (*xlate_linear2phy)(Bit32u linear, Bit32u *phy, bx_bool *valid);
|
||||
bx_bool (*set_reg)(unsigned reg, Bit32u val);
|
||||
Bit32u (*get_reg)(unsigned reg);
|
||||
bx_bool (*set_cpu)(bx_dbg_cpu_t *cpu);
|
||||
bx_bool (*get_cpu)(bx_dbg_cpu_t *cpu);
|
||||
unsigned dirty_page_tbl_size;
|
||||
unsigned char *dirty_page_tbl;
|
||||
void (*atexit)(void);
|
||||
unsigned (*query_pending)(void);
|
||||
void (*execute)(void);
|
||||
void (*take_irq)(void);
|
||||
void (*take_dma)(void);
|
||||
void (*reset_cpu)(unsigned source);
|
||||
void (*init_mem)(int size_in_bytes);
|
||||
void (*load_ROM)(const char *path, Bit32u romaddress);
|
||||
|
||||
void (*set_A20)(unsigned val);
|
||||
void (*set_NMI)(unsigned val);
|
||||
void (*set_RESET)(unsigned val);
|
||||
void (*set_INTR)(unsigned val);
|
||||
void (*force_interrupt)(unsigned vector);
|
||||
|
||||
#if BX_INSTRUMENTATION
|
||||
void (*instr_start)(void);
|
||||
void (*instr_stop)(void);
|
||||
void (*instr_reset)(void);
|
||||
void (*instr_print)(void);
|
||||
#endif
|
||||
#if BX_USE_LOADER
|
||||
void (*loader)(char *path);
|
||||
#endif
|
||||
} bx_dbg_callback_t;
|
||||
</PRE>
|
||||
|
||||
<P><B>bx_bool (*setphymem)(Bit32u addr, unsigned len, Bit8u *buf);</B>
|
||||
<P>Set (write to) physical memory of simulator at address <I>addr</I> from the
|
||||
<I>len</I> bytes in <I>buf</I>. The bytes in <I>buf</I> should be copied to the simulator's
|
||||
physical memory byte-at-a-time with no concern for endian-ness. Return 1
|
||||
if the write is OK, 0 if an error occurs.
|
||||
|
||||
<P><B>bx_bool (*getphymem)(Bit32u addr, unsigned len, Bit8u *buf);</B>
|
||||
<P>Get (read from) physical memory of simulator at address <I>addr</I> to the
|
||||
<I>len</I> bytes in <I>buf</I>. The bytes in <I>buf</I> should be copied from the simulator's
|
||||
physical memory byte-at-a-time with no concern for endian-ness. Return 1
|
||||
if the read is OK, 0 if an error occurs.
|
||||
|
||||
<P><B>void (*xlate_linear2phy)(Bit32u linear, Bit32u *phy, bx_bool *valid);</B>
|
||||
<P>Translate a linear to a physical address, without generating an exception
|
||||
or updating the paging tables. The debugger passes the simulator the
|
||||
<I>linear</I> address. The simulator is expected to set <I>phy</I> to
|
||||
the corresponding physical address if available, and update <I>valid</I>,
|
||||
which should be set to 1 if the physical address was available, and 0
|
||||
if not. It is possible, the address is not in the paging tables, and
|
||||
thus not available.
|
||||
|
||||
<P><B>bx_bool (*set_reg)(unsigned reg, Bit32u val);</B>
|
||||
<P>Set a specific CPU register as determined by <I>reg</I> in the
|
||||
simulator to <I>val</I>. The value of <I>reg</I> will be one of the
|
||||
defines, such as BX_DBG_REG_EAX defined in <I>bx_debug/debug.h</I>. The
|
||||
segment registers can only be set by this method in real mode. This
|
||||
function should return a 1 if the operation is successful, and 0 if not.
|
||||
|
||||
<P><B>Bit32u (*get_reg)(unsigned reg);</B>
|
||||
<P>Return the value of a specific CPU register in the simulator as
|
||||
determined by <I>reg</I>, whose value is of the same range
|
||||
as those passed into <I>set_reg()</I>
|
||||
|
||||
<P><B>bx_bool (*set_cpu)(bx_dbg_cpu_t *cpu);</B>
|
||||
<P>Set all the registers in the CPU simulator to those in the structure
|
||||
<I>cpu</I>. The <I>bx_dbg_cpu_t</I> structure is defined in bx_debug/debug.h.
|
||||
|
||||
<P><B>bx_bool (*get_cpu)(bx_dbg_cpu_t *cpu);</B>
|
||||
<P>Get values for all the registers in the CPU simulator, and place them in
|
||||
the structure <I>cpu</I>. The <I>bx_dbg_cpu_t</I> structure is defined in bx_debug/debug.h.
|
||||
|
||||
<P><B>unsigned dirty_page_tbl_size;</B>
|
||||
<BR><B>unsigned char *dirty_page_tbl;</B>
|
||||
<P>To keep track of what areas of memory have been written to, and allow
|
||||
the debugger to efficiently compare regions of memory in each simulator,
|
||||
each simulator should provide a dirty page table. It is expected that
|
||||
each byte in the array represents one 4K page of physical memory. A value
|
||||
of 1 represents that the page has been written to, since the last time it
|
||||
was cleared by the debugger, and a value of 0 represents that no write
|
||||
has occurred within that physical page.
|
||||
<P>You should fill in the field <I>dirty_page_tbl</I> with a pointer
|
||||
to an array of bytes. And <I>dirty_page_tbl_size</I> should be set
|
||||
to the size of the array in bytes. If possible, make the array big
|
||||
enough to span the largest amount of physical memory you might request.
|
||||
I chose to not make this size dynamic with the user's requested memory size,
|
||||
to eliminate an extra access via a pointer.
|
||||
|
||||
<P><B>void (*atexit)(void);</B>
|
||||
<P>Called when the debugger needs to terminate execution. This function
|
||||
should close files and do all necessary shutdown of the simulator.
|
||||
<B>NOTE:</B> Do not call exit() directly from
|
||||
the simulator, but instead call <I>bx_dbg_exit()</I>. As there may be multiple
|
||||
simulators, <I>bx_dbg_exit()</I> will handle invoking the <I>atexit</I> callback in
|
||||
each simulator first, and then it will call exit().
|
||||
|
||||
<P><B>void (*execute)(void);</B>
|
||||
<P>The debugger calls <I>execute()</I> in either slave or master simulator,
|
||||
commanding either to execute instructions until a guard is reached, in which
|
||||
case control should be returned back to the debugger.
|
||||
|
||||
<P><B>void (*reset_cpu)(unsigned source);</B>
|
||||
<P>This function is called once by the debugger to initialize the simulator's
|
||||
CPU upon program startup. <I>Source</I> will be either
|
||||
BX_RESET_HARDWARE or BX_RESET_SOFTWARE.
|
||||
|
||||
<P><B>void (*init_mem)(int size_in_bytes);</B>
|
||||
<P>This function is called once by the debugger to initialize the simulator's
|
||||
memory upon program startup. <I>Size_in_bytes</I> denotes
|
||||
the size of physical memory the user has requested, so that both simulators
|
||||
can use the same physical memory size. This would be an appropriate
|
||||
time to allocate memory for the simulator.
|
||||
|
||||
<P><B>void (*load_ROM)(const char *path, Bit32u romaddress);</B>
|
||||
<P>Commands the simulator to load a ROM image stored in the filename
|
||||
<I>path</I> into physical memory at address <I>romaddress</I>.
|
||||
|
||||
<P><B>void (*set_A20)(unsigned val);</B>
|
||||
<P>This function is called by the cosim controller to command either master
|
||||
or slave simulator to change it's A20 setting. If the value of <I>val</I> passed
|
||||
is 1, then the A20 address line is passed through and used. This will give
|
||||
normal addressing of the entire 32bit address space. If the value is 0,
|
||||
then A20 is masked out, and addressing at the 1Meg boundary will wrap, modeling
|
||||
8086 addressing.
|
||||
<P>The cosim controller also commands the <I>bx_pc_system</I> class to
|
||||
maintain the same A20 state as passed in this function, so you may alternatively
|
||||
use values directly from that class, rather than keep your own A20 state.
|
||||
If so, set the value of <I>set_A20</I> to NULL, and use the following
|
||||
members from <I>bx_pc_system</I>. In this case, <I>set_A20</I> won't be
|
||||
called.
|
||||
<UL>
|
||||
<LI><B>bx_pc_system.enable_a20:</B> Same value as passed to <I>set_A20</I>.
|
||||
<LI><B>bx_pc_system.a20_mask:</B> Logical AND this with a physical address to obtain the
|
||||
address after application of the A20 gate.
|
||||
</UL>
|
||||
|
||||
<P><B>void (*set_NMI)(unsigned val);</B>
|
||||
<P>Not supported yet. Will tell the simulator that the value of
|
||||
the NMI pin, is currently <I>val</I>. Use an empty stub function
|
||||
for this for now.
|
||||
|
||||
<P><B>void (*set_RESET)(unsigned val);</B>
|
||||
<P>Not supported yet. Will tell the simulator that the value of
|
||||
the RESET pin, is currently <I>val</I>. Use an empty stub function
|
||||
for this for now.
|
||||
|
||||
<P><B>void (*set_INTR)(unsigned val);</B>
|
||||
<P>The INTR pin is driven by the device models. When the INTR pin is
|
||||
raised due to an interrupt request by the PIC, or lowered after the
|
||||
interrupt is acknowledged, this function is called to notify the
|
||||
simulator of the new status. Only the master simulator will receive
|
||||
notification, as INTR is always 0 for the slave simulator. Interrupts
|
||||
are forced in the slave simulator, synchronizing it to the execution
|
||||
path of the master, using <I>force_interrupt()</I> described below.
|
||||
A value in <I>val</I> of 0 indicates no interrupt is requested. A value
|
||||
of 1 indicates an interrupt request.
|
||||
|
||||
<P><B>void (*force_interrupt)(unsigned vector);</B>
|
||||
<P>In order for the debugger to force the slave simulator to take an
|
||||
interrupt at the same point as the master simulator, the interrupt vector
|
||||
is recorded when taken by the master simulator. The debugger commands
|
||||
the slave to the same point, and calls this routine, forcing the slave
|
||||
to take the given interrupt, <I>vector</I>.
|
||||
|
||||
<P><B>void (*instr_start)(void);</B> (Only defined if macro BX_INSTRUMENTATION is 1)
|
||||
<P>Called when the user types in "<I>instrument start</I>" at the debug prompt.
|
||||
The instrumentation package can use this function to do whatever is
|
||||
necessary to initialize the instrumentation package and/or command
|
||||
it to begin collecting data.
|
||||
|
||||
<P><B>void (*instr_stop)(void);</B> (Only defined if macro BX_INSTRUMENTATION is 1)
|
||||
<P>Called when the user types in "<I>instrument stop</I>" at the debug prompt.
|
||||
The instrumentation package can use this function to do whatever is
|
||||
necessary to temporarily or permanently stop the instrumentation package
|
||||
from collecting data.
|
||||
|
||||
<P><B>void (*instr_reset)(void);</B> (Only defined if macro BX_INSTRUMENTATION is 1)
|
||||
<P>Called when the user types in "<I>instrument reset</I>" at the debug prompt.
|
||||
The instrumentation package can use this function to command the instrumentation
|
||||
package to reset it's data collection mechanisms.
|
||||
|
||||
<P><B>void (*instr_print)(void);</B> (Only defined if macro BX_INSTRUMENTATION is 1)
|
||||
<P>Called when the user types in "<I>instrument print</I>" at the debug prompt.
|
||||
The instrumentation package can use this function to output it's collected
|
||||
data.
|
||||
|
||||
<P><B>void (*loader)(char *path);</B> (Only defined if macro BX_USE_LOADER is 1)
|
||||
<P>Called when the user types in "<I>loader pathname</I>" at the debug prompt.
|
||||
The idea is to allow a loader routine to read in a program which is specific
|
||||
to the OS you are running within the emulator, from a file on your native
|
||||
workstation, load it properly into simulator memory and run it on the
|
||||
simulator. This loader must be specific to the OS you are running within the
|
||||
simulator, and I do not provide one with bochs.
|
||||
|
||||
<P><B>void (*take_irq)(void);</B>
|
||||
<BR><B>void (*take_dma)(void);</B>
|
||||
<BR><B>unsigned (*query_pending)(void);</B>
|
||||
<P>These are vestiges of a past interface. They correspond to the
|
||||
"take irq", "take dma", and "query pending" commands, which you
|
||||
shouldn't use. They will be removed. Set these fields to NULL,
|
||||
or to empty stub functions.
|
||||
|
||||
<HR>
|
||||
<HR>
|
||||
<H3>Debugger (Cosimulation Controller) Functions:</H3>
|
||||
<H3>Debugger Functions:</H3>
|
||||
|
||||
<P><B>void bx_dbg_exit(int code)</B>
|
||||
<P>When there is a situation in the simulator, where you need to terminate
|
||||
@ -593,14 +327,8 @@ on how to do this.
|
||||
<P><B>struct { .. } async;</B>
|
||||
<P><B>struct { .. } async_changes_pending;</B>
|
||||
|
||||
|
||||
<HR SIZE=5 NOSHADE>
|
||||
<P>
|
||||
Related Links:
|
||||
<UL>
|
||||
<LI><A HREF="debugger.html">Debugger</A>
|
||||
<LI><A HREF="instrumentation.html">Instrumentation</A>
|
||||
</UL>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
Loading…
x
Reference in New Issue
Block a user