2008-10-01 15:36:04 +04:00
|
|
|
README-instrumentation
|
|
|
|
|
|
|
|
To use instrumentation features in bochs, you must compile in support for it.
|
|
|
|
You should build a custom instrumentation library in a separate directory in
|
|
|
|
the "instrument/" directory. To tell configure which instrumentation library
|
|
|
|
you want to use, use the "--enable-instrumentation" option. The default
|
|
|
|
library consists of a set of stubs, and the following are equivalent:
|
|
|
|
|
|
|
|
./configure [...] --enable-instrumentation
|
|
|
|
./configure [...] --enable-instrumentation="instrument/stubs"
|
|
|
|
|
|
|
|
You could make a separate directory with your custom library, for example
|
|
|
|
"instrument/myinstrument", copy the contents of the "instrument/stubs"
|
|
|
|
directory to it, then customize it. Use:
|
|
|
|
|
|
|
|
./configure [...] --enable-instrumentation="instrument/myinstrument"
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
BOCHS instrumentation callbacks
|
2008-11-18 23:55:59 +03:00
|
|
|
|
2008-10-01 15:36:04 +04:00
|
|
|
|
|
|
|
void bx_instr_init_env();
|
2008-10-06 10:51:29 +04:00
|
|
|
|
2008-10-01 15:36:04 +04:00
|
|
|
The callback is called when Bochs is initialized, before of reading .bochsrc.
|
|
|
|
It can be used for registration of parameters in siminterface. Then
|
|
|
|
when bx_instr_init() is called it can access configuration parameters defined
|
|
|
|
|
|
|
|
by bx_instr_init_env(), so instrumentalization module can use additional
|
|
|
|
options in .bochsrc.
|
|
|
|
|
2008-11-18 23:55:59 +03:00
|
|
|
|
2008-10-06 10:51:29 +04:00
|
|
|
void bx_instr_exit_env();
|
2008-10-01 15:36:04 +04:00
|
|
|
|
2008-10-06 10:51:29 +04:00
|
|
|
The callback is called each time Bochs exits.
|
2008-10-01 15:36:04 +04:00
|
|
|
|
2008-11-18 23:55:59 +03:00
|
|
|
|
|
|
|
void bx_instr_initialize(unsigned cpu);
|
2008-10-01 15:36:04 +04:00
|
|
|
|
|
|
|
The callback is called each time, when Bochs initializes the CPU object. It
|
|
|
|
can be used for initialization of user's data, dynamic memory allocation and
|
|
|
|
etc.
|
|
|
|
|
2008-11-18 23:55:59 +03:00
|
|
|
|
2008-10-01 15:36:04 +04:00
|
|
|
void bx_instr_exit(unsigned cpu);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs destructs the CPU object. It can
|
|
|
|
be used for destruction of user's data, allocated by bx_instr_init callback.
|
|
|
|
|
|
|
|
|
2008-11-18 23:55:59 +03:00
|
|
|
void bx_instr_reset(unsigned cpu, unsigned type);
|
2008-10-01 15:36:04 +04:00
|
|
|
|
|
|
|
The callback is called each time, when Bochs resets the CPU object. It would
|
|
|
|
be executed once at the start of simulation and each time that user presses
|
|
|
|
RESET BUTTON on the simulator's control panel.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_hlt(unsigned cpu);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs' emulated CPU enters HALT or
|
|
|
|
SHUTDOWN state.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs' emulated CPU enters to the MWAIT
|
|
|
|
state. The callback receives monitored memory range and MWAIT flags as a
|
|
|
|
parameters.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_new_instruction(unsigned cpu);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs completes (commits) already
|
|
|
|
finished instruction and starts a new one.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip);
|
|
|
|
|
|
|
|
The callback is called each time, when currently executed instruction is a
|
|
|
|
conditional near branch and it is taken.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_cnear_branch_not_taken(unsigned cpu);
|
|
|
|
|
|
|
|
The callback is called each time, when currently executed instruction is a
|
|
|
|
conditional near branch and it is not taken.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip);
|
|
|
|
|
|
|
|
The callback is called each time, when currently executed instruction is an
|
|
|
|
unconditional near branch (always taken).
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip);
|
|
|
|
|
|
|
|
The callback is called each time, when currently executed instruction is an
|
|
|
|
unconditional far branch (always taken).
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs starts to decode a new
|
|
|
|
instruction. Through this callback function Bochs could provide an opcode of
|
|
|
|
the instruction, opcode length and an execution mode (16/32/64).
|
|
|
|
|
|
|
|
Currently the callback is not supported when trace-cache optimization feature
|
|
|
|
is enabled.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_interrupt(unsigned cpu, unsigned vector);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator executes an interrupt
|
|
|
|
(software interrupt, hardware interrupt or an exception).
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_exception(unsigned cpu, unsigned vector);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator executes an exception.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator executes a hardware
|
|
|
|
interrupt.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr);
|
|
|
|
|
|
|
|
The callback is called each time the CLFLUSH instruction is executed.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3);
|
|
|
|
void bx_instr_cache_cntrl(unsigned cpu, unsigned what);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator executes a cache/tlb
|
|
|
|
control instruction.
|
|
|
|
|
|
|
|
Possible instruction types, passed through bx_instr_tlb_cntrl:
|
|
|
|
|
|
|
|
#define BX_INSTR_MOV_CR3 10
|
|
|
|
#define BX_INSTR_INVLPG 11
|
|
|
|
#define BX_INSTR_TASKSWITCH 12
|
|
|
|
|
|
|
|
Possible instruction types, passed through bx_instr_cache_cntrl:
|
|
|
|
|
|
|
|
#define BX_INSTR_INVD 20
|
|
|
|
#define BX_INSTR_WBINVD 21
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator executes a PREFETCH
|
|
|
|
instruction.
|
|
|
|
|
|
|
|
Possible PREFETCH types:
|
|
|
|
|
|
|
|
#define BX_INSTR_PREFETCH_NTA 00
|
|
|
|
#define BX_INSTR_PREFETCH_T0 01
|
|
|
|
#define BX_INSTR_PREFETCH_T1 02
|
|
|
|
#define BX_INSTR_PREFETCH_T2 03
|
|
|
|
|
|
|
|
The seg/offset arguments indicate the address of the requested prefetch.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_wrmsr(unsigned cpu, unsigned msr, Bit64u value);
|
|
|
|
|
|
|
|
This callback is called each time when WRMSR instruction is executed.
|
|
|
|
MSR number and written value passed as parameters to the callback function.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator starts a new repeat
|
|
|
|
iteration.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator starts a new
|
|
|
|
instruction execution. In case of repeat instruction the callback will
|
|
|
|
be called only once before the first iteration will be started.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator finishes any
|
|
|
|
instruction execution. In case of repeat instruction the callback will
|
|
|
|
be called only once after all repeat iterations.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator executes a linear
|
|
|
|
memory access. Note that no page split accesses will be generated because
|
|
|
|
Bochs splits page split accesses to two different memory accesses during its
|
|
|
|
execution flow. The callback also will not be generated in case of direct
|
|
|
|
physical memory access like in SMM, VMM or SVM modes.
|
|
|
|
|
|
|
|
Possible access types are: BX_READ, BX_WRITE and BX_RW.
|
|
|
|
|
|
|
|
Currently the callback is not supported when repeat-speedups optimization is
|
|
|
|
enabled.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_mem_data_access(unsigned cpu, unsigned seg, bx_address offset, unsigned len, unsigned rw);
|
|
|
|
|
|
|
|
The callback is called each time, when Bochs simulator executes segment based
|
|
|
|
linear memory access. In contrast to previous callback it will be called even
|
|
|
|
if memory access fails because of any reason (for example segment protection
|
|
|
|
failure or page fault).
|
|
|
|
|
|
|
|
The callback will not be called for system memory accesses like sys desriptor
|
|
|
|
tables reads/writes or new stack pushes during far call or exception.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_phy_read(unsigned cpu, bx_address addr, unsigned len);
|
|
|
|
void bx_instr_phy_write(unsigned cpu, bx_address addr, unsigned len);
|
|
|
|
|
|
|
|
These callback functions are the feedback from external memory system.
|
|
|
|
|
|
|
|
|
|
|
|
void bx_instr_inp(Bit16u addr, unsigned len);
|
|
|
|
void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val);
|
2008-12-29 21:02:01 +03:00
|
|
|
void bx_instr_outp(Bit16u addr, unsigned len, unsigned val);
|
2008-10-01 15:36:04 +04:00
|
|
|
|
|
|
|
These callback functions are a feedback from various system devices.
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
Known problems:
|
|
|
|
|
|
|
|
1. BX_INSTR_LIN_ACCESS doesn't work when repeat-speedups feature is enabled.
|
|
|
|
|
|
|
|
2. BX_INSTR_MEM_DATA doesn't work when repeat-speedups feature is enabled.
|
|
|
|
|
|
|
|
3. BX_INSTR_OPCODE doesn't work with trace cache optimization enabled
|
|
|
|
|
|
|
|
Feature requests:
|
|
|
|
|
|
|
|
1. BX_INSTR_CNEAR_BRANCH_NOT_TAKEN callback should have an additional
|
|
|
|
'not taken' new_EIP parameter.
|
|
|
|
|
|
|
|
2. BX_INSTR_SMI, BX_INSTR_NMI, BX_INSTR_SIPI and other external events
|
|
|
|
callbacks
|
|
|
|
|
|
|
|
3.
|
|
|
|
|
|
|
|
While using Bochs as a reference model for simulations, the simulator needs
|
|
|
|
information about what loads/stores are taking place with each instruction.
|
|
|
|
Presumably, that is what the BX_INSTR_MEM_DATA() instrumentation macros
|
|
|
|
cover (which is the place where our simulator hooks up).
|
|
|
|
|
|
|
|
The RETnear_xxx() functions call access_linear() directly, rather than call
|
|
|
|
read_virtual_xxx() functions. This is a problem for code making use of the
|
|
|
|
BX_INSTR_MEM_DATA() hook because it does not get called for these
|
|
|
|
instructions. Should this be changed along with some other instructions
|
|
|
|
that exhibit this?
|
|
|
|
Brian Slechta
|