Bochs code reading, notes and hacks
NOTE:
- this page uses JavaScript to display the diagrams generated by drawio; Fortunately the embedded js on this page is LibreJs-checked.
- the lincensing of this article inherits whatever Bochs uses; All attributions/credits go to authors of Bochs1 and other references2 3.
- to get the source files of the diagrams, click the diagram, then click the “edit (pen shape)” button to open the diagram in drawio online editor, then you can save/export the source file and/or do whatever you want.
- I use a special patched version Bochs but it won’t hurt.
Table of Content
# black macro magic
cpu/cpu.h
#if BX_USE_CPU_SMF == 0
// normal member functions. This can ONLY be used within BX_CPU_C classes.
// Anyone on the outside should use the BX_CPU macro (defined in bochs.h)
// instead.
# define BX_CPU_THIS_PTR this->
# define BX_CPU_THIS this
# define BX_SMF
# define BX_CPU_C_PREFIX BX_CPU_C::
// with normal member functions, calling a member fn pointer looks like
// object->*(fnptr)(arg, ...);
// Since this is different from when SMF=1, encapsulate it in a macro.
# define BX_CPU_CALL_METHOD(func, args) \
(this->*((BxExecutePtr_tR) (func))) args
# define BX_CPU_CALL_METHODR(func, args) \
(this->*((BxResolvePtr_tR) (func))) args
#else
// static member functions. With SMF, there is only one CPU by definition.
# define BX_CPU_THIS_PTR BX_CPU(0)->
# define BX_CPU_THIS BX_CPU(0)
# define BX_SMF static
# define BX_CPU_C_PREFIX
# define BX_CPU_CALL_METHOD(func, args) \
((BxExecutePtr_tR) (func)) args
# define BX_CPU_CALL_METHODR(func, args) \
((BxResolvePtr_tR) (func)) args
#endif
why: with BX_USE_CPU_SMF == 1
most methods can ba made static because this->
pointer is not needed (since there is only one instance of e.g. CPU).
i.e. with uni-processor configuration the whole CPU object can be made static
(incl. its members and functions). A single CPU object is declared as bx_cpu
.
w/ multiprocessor configuration
bx_cpu_array = new BX_CPU_C_PTR[BX_SMP_PROCESSORS];
HACK | UP | SMP | NOTE |
---|---|---|---|
BX_CPU_C |
bx_cpu_c |
bx_cpu_c |
脱裤子放屁吗? |
CPU object declare | bx_cpu_c bx_cpu |
bx_cpu_c **bx_cpu_array |
|
BX_CPU(x) |
&bx_cpu |
bx_cpu_array[x] |
always return a ponter |
BX_CPU_THIS_PTR |
BX_CPU(0)-> |
this-> |
|
BX_CPU_THIS |
BX_CPU(0) |
this |
debugging: BX_{DEBUG, INFO, ERROR, PANIC}(<fmtstr>)
: each can be switched
on/off at compile time.
BOCHSAPI
: I guess this is only for documentation purposes. (and win32 DLL building? to have__declspec(dllexport)
on variables/functions or classes that the plugins can access.)
Multiple cpu object pointers as array bx_cpu_array[]
. Access through BX_CPU(x)
macro.
# base CPU cycle2
- cpu/instr.h::bxInstruction_c
- stores info of a instruction. dispatch func pointer, opcode, src/dest registers, immediate …
Each instruction is emulated by one or two functions, funcptr in
bxInstruction_c::execute
andbxInstruction_c::execute2
. E.g. LOAD+OP uses two handler functions2
All instructions restartable from the register state +
bxInstruction_c
. Never possible to generate exception /after/ changing the visible state except for RIP (and in some cases RSP) registers CPU loops sets up return point using setjmp(), exception will call longjmp() and appear at the beginning of CPU loop2
# x86_64 long mode Memory access flow
The CPU can access memory through:
- direct host access
access_{read,write}_physical()
Note that the TLB should have
TLB_NoHostPtr
bit set in thelpf[11]
when direct access through host pointer is NOT allowed for the page. A memory operation asking for a direct access through host pointer does not haveTLB_NoHostPtr
bit set in its lpf (which is 4K always aligned) and thus will get TLB miss result when the direct access is not allowed. A memory operation that do not care for a direct access to the memory through host pointer should implicitly clearlpf[11]
bit in the TLB before comparison with memory access lpf 2
-
https://github.com/bochs-emu/Bochs/tree/master?tab=readme-ov-file#authors ↩︎
-
How Bochs Works Under the Hood, 2nd edition, Stanislav Shwartsman and Darek Mihoka ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
-
Darek Mihocka et al., Virtualization without direct execution - designing a portable VM, The 1st Workshop on Architectural and Microarchitectural Support for Binary Translation, ISCA-35 in Beijing, China. https://bochs.sourceforge.io/Virtualization_Without_Hardware_Final.pdf ↩︎
[+] click to leave a comment [+]
>> SEND COMMENT <<