📄 cosimulation.html
字号:
<P><B>void bx_dbg_async_pin_ack(unsigned what, bx_bool val)</B><P>In order for the master and slave simulators to accept changes in pinssuch as the A20 line, at the same point, the debugger provides a mechanismfor pending the pin change, until it is acknowledged by the master simulator.The place where the change is ack'd, is recorded by the debugger. Thisinformation is used to run the slave simulator, forcing it to accept thechanges at the same locale as did the master.<P>Initially, the IO devices call a function <I>bx_dbg_async_pin_request()</I>,not listed here, to record the pin change as pending. The pending statusis recorded along with the guard information in <I>bx_guard.async_changes_pending.which</I>.This field contains a binary OR'd set of pending pin changes. Currentlyonly A20 is supported, which is represented by the macro BX_DBG_ASYNC_PENDING_A20.<P>At a time prudent to your CPU simulator, check to see if there areany pending changes, that the CPU should acknowledge. If so, acknowledgethem by calling <I>bx_dbg_async_pin_ack()</I>. The pending value ofthe A20 enable is stored in <I>bx_guard.async_changes_pending.a20</I>.Here is some sample code which performs this task, that you can insertinto the appropriate place in your CPU simulator.<PRE> if (bx_guard.async_changes_pending.which) { if (bx_guard.async_changes_pending.which & BX_DBG_ASYNC_PENDING_A20) bx_dbg_async_pin_ack(BX_DBG_ASYNC_PENDING_A20, bx_guard.async_changes_pending.a20); // ...other checks here when they are supported }</PRE>The <I>bx_dbg_async_pin_ack()</I> function will in turn, invokethe <I>set_A20()</I> callback function in the master simulator, so youdon't have to deal with updating local A20 state in your simulator here,as long as you handle it in <I>set_A20()</I>. Keep in mind, the slavesimulator will never see the code inside this sample code if-construct,since changes are forced in the slave by the debugger at points where the mastersimulator acknowledged them, not as a direct effect of the IO devices.<HR><HR><H3>Guards:</H3>Guards are a mechanism by which the debugger requests each simulatorto stop execution and return control back to the debugger. The debuggerruns each simulator for a particular number of instructions, or untilcertain events occur. Guards are set by the debugger, and it is upto each simulator to examine them upon and during execution of the <I>execute()</I>callback, and return control back to the debugger when the guard criteriaare met.<P>Guard information set by the debugger is stored in global structure<I>bx_guard</I> of type <I>bx_guard_t</I>. For reference, it's declarationis shown here, followed by an explanation of the purpose of each field.Information about the guard encountered by the simulator, and whichcaused control to return to the debugger is stored in the global structure<I>bx_guard_found[]</I> of type <I>bx_guard_found_t</I>. This is actuallyan array of structures, where <I>bx_guard_found[0]</I> is the first simulatorwith ID 0, and <I>bx_guard_found[1]</I> is the second simulator withID 1. This structure is also declared below, and the text explainsthe information which should be returned in this structure based onthe guard encountered.<PRE>typedef struct { unsigned long guard_for; // instruction address breakpoints struct {#if BX_DBG_SUPPORT_VIR_BPOINT unsigned num_virtual; struct { Bit32u cs; // only use 16 bits Bit32u eip; unsigned bpoint_id; } vir[BX_DBG_MAX_VIR_BPOINTS];#endif#if BX_DBG_SUPPORT_LIN_BPOINT unsigned num_linear; struct { Bit32u addr; unsigned bpoint_id; } lin[BX_DBG_MAX_LIN_BPOINTS];#endif#if BX_DBG_SUPPORT_PHY_BPOINT unsigned num_physical; struct { Bit32u addr; unsigned bpoint_id; } phy[BX_DBG_MAX_PHY_BPOINTS];#endif } iaddr; bx_dbg_icount_t icount; // stop after completing this many instructions // user typed Ctrl-C, requesting simulator stop at next convient spot volatile bx_bool interrupt_requested; // booleans to control whether simulator should report events // to debug controller struct { bx_bool irq; bx_bool a20; bx_bool io; bx_bool ucmem; bx_bool dma; } report; struct { bx_bool irq; // should process IRQs asynchronously bx_bool dma; // should process DMAs asynchronously } async;#define BX_DBG_ASYNC_PENDING_A20 0x01#define BX_DBG_ASYNC_PENDING_RESET 0x02#define BX_DBG_ASYNC_PENDING_NMI 0x04 // Asynchronous changes which are pending. These are Q'd by // the debugger, as the master simulator is notified of a pending // async change. At the simulator's next point, where it checks for // such events, it notifies the debugger with acknowlegement. This // field contains a logically or'd list of all events which should // be checked, and ack'd. struct { unsigned which; // logical OR of above constants bx_bool a20; bx_bool reset; bx_bool nmi; } async_changes_pending; } bx_guard_t;typedef struct { unsigned long guard_found; unsigned iaddr_index; bx_dbg_icount_t icount; // number of completed instructions Bit32u cs; // cs:eip and linear addr of instruction at guard point Bit32u eip; Bit32u laddr; bx_bool is_32bit_code; // CS seg size at guard point bx_bool ctrl_c; // simulator stopped due to Ctrl-C request } bx_guard_found_t;extern bx_guard_t bx_guard;extern bx_guard_found_t bx_guard_found[];</PRE><HR><H3>bx_guard_found[]:</H3>It is the task of each simulator to update the <I>bx_guard_found</I>structure.There are some fields which are specific to the type of guard inquestion, and you should update those when a particular guard isencountered. Those fields are explained in more detail in the sectionrelating to the specific guard. There are some fields which areupdated for every case, no matter what the guard is. Below is a listand explanation of the usage of each field.<P><B>unsigned long guard_found;</B> this should be filled in with theparticular guard encountered, for example if an instruction countguard is hit, set this to BX_DBG_GUARD_ICOUNT.<P><B>unsigned iaddr_index;</B>This field is updated, whenever a virtual/linear/physical instructionaddress guard is hit. It is the array index into the bx_guard.iaddr.vir[],bx_guard.iaddr.lin[], or bx_guard.iaddr.phy[] arrays, whichever is appropriate.<P><B>bx_dbg_icount_t icount;</B>This contains the number of instructions which have been completelyexecuted, when the guard was encountered.<P><B>Bit32u cs;</B><BR><B>Bit32u eip;</B><BR><B>Bit32u laddr;</B><BR><B>bx_bool is_32bit_code;</B>These all relate to the same instruction address. From the debugger'spoint of view, instruction addresses can be only at the beginning ofthe instruction. Once an instruction is completed, use the addressof the next instruction.Set <I>cs</I> and <I>eip</I> to the instruction's address (CS:EIP).Set <I>laddr</I> to the instruction's corresponding linear address.Set <I>is_32bit_code</I> to the size (0=16bit, 1=32bit) of the codesegment when the guard is encountered. This is used for disassembly.<P><B>bx_bool ctrl_c;</B>To allow the user to interrupt a simulator from the debug prompt, thedebugger traps Ctrl-C interrupts, and sets <I>bx_guard.interrupt_requested</I>.Your simulator can optionally look for this, provided that theBX_DBG_GUARD_CTRL_C bit is set in <I>bx_guard.guard_for</I> structure.If you chose to do so, you may look for this occurrance whenever isconvenient. Set <I>ctrl_c</I> to 1 to signify this guard has occurred.Here' some sample code to demonstrate this:<PRE> // convenient point to see if user typed Ctrl-C if (bx_guard.interrupt_requested && (bx_guard.guard_for & BX_DBG_GUARD_CTRL_C)) { bx_guard_found[BX_SIM_ID].guard_found = BX_DBG_GUARD_CTRL_C; return; // some mechanism to return control here }</PRE><HR><H3>bx_guard:</H3><P><B>unsigned long guard_for;</B><P>This is a binary OR'd list of guards the debugger is requesting eachsimulator to stop on. Only if the corresponding bit is set in this field,should the simulator examine the rest of the criteria for that guard.Currently, each simulator must be capable of recognizing the followingguards, and returning to the debugger when they occur:<UL><LI>BX_DBG_GUARD_ICOUNT: Instruction count.<LI>BX_DBG_GUARD_CTRL_C: User requested interrupt via Ctrl-C<LI>BX_DBG_GUARD_IADDR_VIR: Stop on this virtual instruction address<LI>BX_DBG_GUARD_IADDR_LIN: Stop on this linear instruction address<LI>BX_DBG_GUARD_IADDR_PHY: Stop on this physical instruction address</UL><P><B>struct { .. } iaddr;</B><P>This structure holds the guard information for instruction addressguards (breakpoints). Depending upon your selections, after editing<I>config.h</I> in the main directory (generated by running ./configure),certain types of instruction address guards are supported. Which ones,are determined by the BX_DBG_SUPPORT_VIR_BPOINT, BX_DBG_SUPPORT_LIN_BPOINT,and BX_DBG_SUPPORT_PHY_BPOINT macros.<P>If the <I>guard_for</I> field contains a set bit represented byBX_DBG_GUARD_IADDR_VIR, then the <I>iaddr.num_virtual</I> field holdsthe number of virtual instruction address guards to examine and compareto the current address. For each, you must examine the CS:EIP valuesstored in <I>iaddr.vir[n]</I>, in the <I>cs</I> and <I>eip</I> subfields.If there is a match, record this in the guard found structure, andreturn control to the debugger:<PRE>bx_guard_found[ID].guard_found = BX_DBG_GUARD_IADDR_VIR;bx_guard_found[ID].iaddr_index = n; // array index in bx_guard.iaddr.vir[]bx_guard_found[ID].icount = .. // number of completed instructionsbx_guard_found[ID].cs = .. // CS selector valuebx_guard_found[ID].eip = .. // EIP valuebx_guard_found[ID].laddr = .. // linear address of CS:EIPbx_guard_found[ID].is_32bit_code = .. // 0=16bit code, 1=32bit code// return control here</PRE><P>If the <I>guard_for</I> field contains a set bit represented byBX_DBG_GUARD_IADDR_LIN, then the <I>iaddr.num_linear</I> field holdsthe number of linear instruction address guards to examine and compareto the current address. For each, you must examine the linear address valuesstored in <I>iaddr.lin[n]</I>, in the <I>addr</I> subfield.If there is a match, record this in the guard found structure, andreturn control to the debugger:<PRE>bx_guard_found[ID].guard_found = BX_DBG_GUARD_IADDR_LIN;bx_guard_found[ID].iaddr_index = n; // array index in bx_guard.iaddr.lin[]bx_guard_found[ID].icount = .. // number of completed instructionsbx_guard_found[ID].cs = .. // CS selector valuebx_guard_found[ID].eip = .. // EIP valuebx_guard_found[ID].laddr = .. // linear address of CS:EIPbx_guard_found[ID].is_32bit_code = .. // 0=16bit code, 1=32bit code// return control here</PRE><P>If the <I>guard_for</I> field contains a set bit represented byBX_DBG_GUARD_IADDR_PHY, then the <I>iaddr.num_physical</I> field holdsthe number of physical instruction address guards to examine and compareto the current address. For each, you must examine the physical address valuesstored in <I>iaddr.phy[n]</I>, in the <I>addr</I> subfield.If there is a match, record this in the guard found structure, andreturn control to the debugger:<PRE>bx_guard_found[ID].guard_found = BX_DBG_GUARD_IADDR_PHY;bx_guard_found[ID].iaddr_index = n; // array index in bx_guard.iaddr.phy[]bx_guard_found[ID].icount = .. // number of completed instructionsbx_guard_found[ID].cs = .. // CS selector valuebx_guard_found[ID].eip = .. // EIP valuebx_guard_found[ID].laddr = .. // linear address of CS:EIPbx_guard_found[ID].is_32bit_code = .. // 0=16bit code, 1=32bit code// return control here</PRE><P><B>volatile bx_bool interrupt_requested;</B><P>If the debugger has turned on the guard for a user interrupt, andthe user has indeed requested one (Ctrl-C), the debugger will setthis field to 1. The simulator should record this in the guard foundinformation, and return control back to the debugger. Look above at theexplanation for the <I>bx_guard.interrupt_requested</I> field for some sample codeon 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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -