Title: Bochs x86 PC Emulation Software
1Bochs x86 PC Emulation Software
2Bochs x86 System Emulator
- Released under the LGPL
- Detailed emulation of x86 ISA and some devices
- Runs on many different platforms including x86
and Alpha EV5 - Boots old version of RedHat Linux (5.0), PicoBSD,
Windows 95 - Evolved into Plex86/FreeMWare
- Written in C with hacks for speed
3x86 Emulation
- Support for x86 ISA
- Access control
- Arithmetic, bit, multi/div, logical, shift,
strings - Branches (but not prediction)
- Paging, including TLBs
- Exceptions
- Partial support for dynamic execution
- Use of native functions on host platform
- Claims it can give a significant speed up on
supported architectures
4CPU loop
- Loop constructs are apparently the spawn of
Satanuse gotos instead - General idea
- Deal with asynchronous events
- Previous instruction and hardware interrrupts
- External interrupts
- Get an instruction
- Execute
- Update clock
5 BX_CPU_THIS_PTR prev_eip EIP // commit new
EIP BX_CPU_THIS_PTR prev_esp ESP // commit
new ESP main_cpu_loop // ???
BX_CPU_THIS_PTR EXT 0 BX_CPU_THIS_PTR
errorno 0 // First check on events which
occurred for previous instructions // (traps)
and ones which are asynchronous to the CPU //
(hardware interrupts). if (BX_CPU_THIS_PTR
async_event) goto handle_async_event async_e
vents_processed // Now we can handle things
which are synchronous to instruction //
execution. if (BX_CPU_THIS_PTR eflags.rf)
BX_CPU_THIS_PTR eflags.rf 0 // We have
ignored processing of external interrupts and
// debug events on this boundary. Reset the mask
so they // will be processed on the next
boundary. BX_CPU_THIS_PTR inhibit_mask 0
is_32 BX_CPU_THIS_PTR sregsBX_SEG_REG_CS.cache
.u.segment.d_b if (BX_CPU_THIS_PTR bytesleft
0) if (BX_CPU_THIS_PTR bytesleft 0)
prefetch() fetch_ptr BX_CPU_THIS_PTR
fetch_ptr maxisize 16 if
(BX_CPU_THIS_PTR bytesleft lt 16) maxisize
BX_CPU_THIS_PTR bytesleft ret
FetchDecode(fetch_ptr, i, maxisize, is_32)
if (ret) if (i.ResolveModrm)
i.ResolveModrm(i) BX_CPU_THIS_PTR
fetch_ptr i.ilen BX_CPU_THIS_PTR
bytesleft - i.ilen fetch_decode_OK if
(i.rep_used (i.attr BxRepeatable))
repeat_loop if (i.attr BxRepeatableZF)
if (i.as_32) if (ECX ! 0)
i.execute(i) ECX -
1 if ((i.rep_used0xf3)
(get_ZF()0)) goto repeat_done if
((i.rep_used0xf2) (get_ZF()!0)) goto
repeat_done if (ECX 0) goto
repeat_done goto repeat_not_done
else if (CX ! 0)
i.execute(i) CX - 1
if ((i.rep_used0xf3)
(get_ZF()0)) goto repeat_done if
((i.rep_used0xf2) (get_ZF()!0)) goto
repeat_done if (CX 0) goto
repeat_done goto repeat_not_done
else // normal repeat,
no concern for ZF if (i.as_32)
if (ECX ! 0) i.execute(i) ECX
- 1 if (ECX 0) goto
repeat_done goto repeat_not_done
else // 16bit addrsize if (CX ! 0)
i.execute(i) CX -
1 if (CX 0) goto
repeat_done goto repeat_not_done
// shouldn't get here from
above repeat_not_done ifdef REGISTER_IADDR
REGISTER_IADDR(BX_CPU_THIS_PTR eip
BX_CPU_THIS_PTR sregsBX_SREG_CS.cac endif
BX_TICK1() if BX_DEBUGGER 0 if
(BX_CPU_THIS_PTR async_event) endif
invalidate_prefetch_q() goto
debugger_check if BX_DEBUGGER 0
endif goto repeat_loop repeat_done
BX_CPU_THIS_PTR eip i.ilen
else BX_CPU_THIS_PTR eip i.ilen
i.execute(i) BX_CPU_THIS_PTR
prev_eip EIP // commit new EIP
BX_CPU_THIS_PTR prev_esp ESP // commit new
ESP ifdef REGISTER_IADDR REGISTER_IADDR(BX_CP
U_THIS_PTR eip BX_CPU_THIS_PTR
sregsBX_SREG_CS.cache endif BX_TICK1() if
(BX_CPU_THIS_PTR trace)
BX_CPU_THIS_PTR stop_reason STOP_TRACE
return goto main_cpu_loop else
unsigned remain, j static Bit8u
FetchBuffer16 Bit8u temp_ptr //
read all leftover bytes in current page for
(j0 jltBX_CPU_THIS_PTR bytesleft j)
FetchBufferj fetch_ptr //
get remaining bytes for prefetch in next page
// prefetch() needs eip current
BX_CPU_THIS_PTR eip BX_CPU_THIS_PTR
bytesleft remain BX_CPU_THIS_PTR
bytesleft prefetch() if
(BX_CPU_THIS_PTR bytesleft lt 16) // make
sure (bytesleft - remain) below doesn't go
negative bx_panic("fetch_decode
bytesleft0 after prefetch\n")
temp_ptr fetch_ptr BX_CPU_THIS_PTR
fetch_ptr // read leftover bytes in next
page for ( jlt16 j) FetchBufferj
temp_ptr ret
FetchDecode(FetchBuffer, i, 16, is_32) if
(ret0) bx_panic("fetchdecode cross
boundary ret0\n") if (i.ResolveModrm)
i.ResolveModrm(i) remain i.ilen -
remain // note eip has already been
advanced to beginning of page BX_CPU_THIS_PTR
fetch_ptr fetch_ptr remain
BX_CPU_THIS_PTR bytesleft - remain
//BX_CPU_THIS_PTR eip remain
BX_CPU_THIS_PTR eip BX_CPU_THIS_PTR prev_eip
goto fetch_decode_OK
6Device Support
- Completely supported
- CMOS RAM and RTC, DMA, Floppy, hard drive,
keyboard, pci (i440fx), pic, pit (8253/8254),
serial console, vga - Partially supported
- Networking (ne2000 card), mouse, sound blaster
- General structure for handling devices, their
interrupts and timing constraints
7Other details
- Main
- Get system configuration (memory, speed, devices,
etc) - Load OS
- Signal handler
- PC system
- Timers are handled here
- Set interrupts
- Extra support for devices
8Yet more details
- State File
- Checkpointing emulator state
- Memory
- Support for writing and reading physical memory
- Used by the access control and paging functions
- Setup memory
- Load ROM
9Running Bochs
- Currently built on usb
- Optional bios setup
- Boot from a floppy image or disk image
- System configuration
- Command line or .bochsrc options
- But
- Mandrake 7.2, PicoBSD 0.21 and FreeDos failed to
work - Possible floppy driver problems
- Requested cylinder ! current cylinder
10Bochs documentation
11.bochsrc
ROMIMAGE You now need
to load a ROM BIOS into F0000-FFFFF. I've
wiped out most of the BIOS hooks, and replace
them with real BIOS support. Normally, you can
use a precompiled BIOS in the bios/ directory,
named BIOS-bochs-yymmdd. Use the latest one in
there.
MEGS set this to the default number of
Megabytes of memory you want to emulate. You
may also pass the '-megs xyz' option to
bochs
VGAROMIMAGE You now need to load a VGA ROM
BIOS into C0000.
FLOPPYA Point this to pathname
of floppy image file or device This should be
of a bootable floppy(image/device) if you're
booting from 'a'. You can set the initial
status of the media to 'ejected' or 'inserted'.
floppya 2_88path, statusejected
(2.88M 3.5" floppy) floppya 1_44path,
statusinserted (1.44M 3.5" floppy)
floppya 1_2path, statusejected
(1.2M 5.25" floppy) floppya 720kpath,
statusinserted (720K 3.5"
floppy)
FLOPPYB See FLOPPYA above
12.bochsrc
DISKC file, cyl,
heads, spt Point this at a 10M, 20M, or 30M
hard disk image file. Read INSTALL to create
one. Examples diskc file10M.sample,
cyl306, heads4, spt17 diskc
file20M.sample, cyl615, heads4, spt17
diskc file30M.sample, cyl615, heads6,
spt17 diskc file46M.sample, cyl940,
heads6, spt17 diskc file62M.sample,
cyl940, heads8, spt17 diskc
file112M.sample, cyl900, heads15, spt17
diskc file483M.sample, cyl1024, heads15,
spt63
BOOT This defines your boot drive. You
can either boot from 'a' or 'c'. Examples
boot c boot a
LOG Give the path of the
log file you'd like Bochs debug and misc.
verbage to be written to. If you really don't
want it, make it /dev/null. ( Examples
log ./bochs.out log /dev/tty
13.bochsrc
SB16 This defines the
SB16 sound emulation. It can have several of
the following properties. All properties are
in the format sb16 propertyvalue midi The
filename is where the midi data is sent. This can
be a device or just a file if you want to
record the midi data. midimode 0no
data 1output to device (system dependent.
midi denotes the device driver) 2SMF file
output, including headers 3output the
midi data stream to the file (no midi headers and
no delta times, just command and data
bytes) wave This is the device/file where wave
output is stored wavemode 0no data
1output to device (system dependent. wave
denotes the device driver) 2VOC file
output, incl. headers 3output the raw
wave stream to the file log The file to write
the sb16 emulator messages to. loglevel
0no log 1only midi program and bank
changes 2severe errors 3all
errors 4all errors plus all port
accesses 5all errors and port accesses
plus a lot of extra info dmatimer
microseconds per second for a DMA cycle. Make it
smaller to fix non-continous sound.
750000 is usually a good value. This needs a
reasonably correct setting for IPS. For an
example look at the next line
14.bochsrc
VGA_UPDATE_INTERVAL
Video memory is scanned for updates and screen
updated every so many virtual seconds. The
default is 300000, about 3Hz. This is
generally plenty. Keep in mind that you must
tweak the 'ips' directive to be as close to
the number of emulated instructions-per-second
your workstation can do, for this to be
accurate. Examples vga_update_interval
250000
KEYBOARD_SERIAL_DELAY Approximate time
in microseconds that it takes one character to
be transfered from the keyboard to controller
over the serial path. Examples
keyboard_serial_delay 200
FLOPPY_COMMAND_DELAY
Time in microseconds to wait before completing
some floppy commands such as read/write/seek/etc
, which normally have a delay associated. I had
this hardwired to 50,000 before. Examples
floppy_command_delay 50000
15.bochsrc
IPS Emulated
Instructions Per Second. This is the number of
IPS that bochs is capable of running on your
machine. Read the note in config.h on how to
find this. Make sure to recompile after.
Examples machine
Mips _______________________________
_________________________________ 400Mhz
Pentium II with Linux 2.0.36/egcs-1.0.3 1 to
1.8Mips 166Mhz 64bit Sparc with Solaris 2.x
approx 0.75 Mips 200Mhz Pentium with
Linux 2.x approx 0.5
Mips
mouse Not used in any of the GUI specific
modules, but the option
bx_options.mouse_enabled is set to this value.
The idea, is that the GUI code should
not generate mouse events when not
enabled. The hardware emualation itself is not
disabled by this. This is to facilitate
deterministic runs of bochs. Examples
mouse enabled1 mouse enabled0
private_colormap Request that the GUI create and
use it's own non-shared
colormap. This colormap will be used
when in the bochs window. If not
enabled, a shared colormap
scheme may be used. Not implemented
on all GUI's. Examples
private_colormap enabled1 private_colormap
enabled0
16Sample .bochsrc
megs 64boot avgaromimage /tmp_mnt/home/usb/gh
iasi/bochs/bochs-2000_0325a/bios/VGABIOS-elpin-2.2
0 diskc file/tmp_mnt/home/usb/ghiasi/bochs/boch
s-2000_0325a/504M.linux, cyl1024, heads16,
spt63 floppya 1_44/tmp_mnt/home/usb/ghiasi/boc
hs/bochs-2000_0325a/cdrom.img, statusinserted ro
mimage file/tmp_mnt/home/usb/ghiasi/bochs/bochs-
2000_0325a/bios/BIOS-bochs-990925a,
address0xf0000 log /tmp_mnt/home/usb/ghiasi/boc
hs/logs/bochs.outkeyboard_serial_delay
200floppy_command_delay 500vga_update_interval
300000ips 500000000 mouse
enabled0private_colormap enabled0i440fxsuppor
t enabled0newharddrivesupport enabled1
17(No Transcript)
18(No Transcript)
19Bochs log file
0 (0) BX_MEM_Cinit_memory(int) allocating
memory. 0 TTY not used, serial port is not
connected0 (0) get_memory_in_k() 655361982
timer0 period set to 18 hz2019 CMOS write reg
14h value 05h2805 vga io write 3cf reg 05
value 10h2830 vga io write 3da ignoring
feature ctrl vert sync2842 io read 3c5
case 1 sequencer clocking mode2970 vga io
write 3c0 address mode reg162976 vga io write
3c0 address mode reg179443 io read 3c5
case 1 sequencer clocking mode9974 vga io
write 3cf reg 05 value 10h26439 io read
3c5 case 1 sequencer clocking mode 413892
floppy io cylinder request ! current
cylinder418849 floppy io cylinder request !
current cylinder533257776 WBINVD
(ignoring)533257778 devices port92h read
partially supported!!!533257778 devices
returning 02533257780 devices port92h write of
00 partially supported!!!533257780 devices A20
set_enable_a20() called533257780 A20 now
0533274737 floppy DMA and interrupt
capabilities disabled 585090700 ESC3 not
implemented585090701 FWAIT no FPU585090702
ESC7 not implemented777500000 KBD internal
keyboard buffer full, ignoring scancode.(9d)
20Performance Issues
- Bochs claims
- 1.5 MIPS on 400 MHz PII
- SimpleScalar (sim-outorder)
- 50000 IPS on ds20
- Expect additional slowdown when processor model
is incorporated - Instruction window, selection logic, time for
instruction completion - WAG another 50 slowdown
21Potential Problems
- Any full systems simulator
- No processor model
- No caches
- Boots an old version of Linux
- StrongArm full system simulation
- No Arm instructions, MSRs
- Doesnt match Arm memory access model
- Foster full system simulation
- Currently single processor and context support
only - No P4 instructions and MSR names
22What it might do for us?
- Provide a framework for a full system simulator
- Provide device models
- May be possible to swipe new device models from
Plex86 - May be possible to get new versions of OS running
by modifying Plex86 code - Commonality with NSA
- Existing support if someone wants to do x86 stuff
23Bochs PC System structure
- Timers
- Duration, type, function handled by, register,
activate and deactivate - Simulated system clock
- DMA read and write functions
- Input and output operations that call bx_devices
operations - DRQ, DACK, TC, HRQ, HLDA, INTR
- Set Boolean flags and associated state in
bx_devices - void bx_pc_system_craise_HLDA(void)
-
- HLDA 1
- bx_devices.raise_hlda()
- HLDA 0
-
24Bochs PC System structure
Registered timers for devices
Call device specific timers via this
Simulated system clock
pc_system
bx_devices
Input and output operations
Call device input and output via I/O handlers
DRQ, DACK, TC, HRQ, HLDA, INTR
Call bx_devices functions to raise/reset
25Bochs Device structure
- iodev.h
- All supported devices hang off bx_devices_c
- Guest to host translation support
- Register and use I/O read and write handlers
- Register/unregister IRQs
- Input and output operations
- DMA operations
- DRQ, HLDA, etc support
- Timer
26Bochs PC system and Device Interactions
Registered timers for devices
Simulated system clock
pc_system
bx_devices
Input and output operations
DRQ, DACK, TC, HRQ, HLDA, INTR
27Initializing bx_devices
- Set all port addresses to unmapped
- Call initialization routines on each device
included in this bochs build - Register Port 92h System Control I/O handlers
- Register timer(s)
- pic triggers on IRQ0 (timer_delta), IRQ1 and/or
IRQ12 (keyboard) - Set up Bit16u extended memory
28Sample device a floppy
- floppy_t
- Location of floppy image, sectors/track, sectors,
tracks, heads, type - bx_floppy_ctrl_c
- Manipulate a floppy
- DMA read and write
- Media status
- Current state pending requests, status
registers - I/O handlers and timer
29Initializing a floppy device
- Register IRQ6
- Register I/O handlers for address range 0x03F2,
0x03F7 - Initialize floppy based on .bochsrc options
- cmos-gts.reg0x10, cmos-gts.reg0x14
- Register timer
- Tell pc_system which devices (via this)
- How long, type
30Floppy interaction with Bochs
- Floppy initialized
- main.cc main() calls bx_bochs_init() calls
bx_devices.init() - Set number of instructions until interrupt based
on floppy delay parameter - Floppy interrupt is processed when its remaining
time is 0 - pending_command state determines the actions
taken - Can include setting the next interrupt
31Floppy interaction with Bochs
32Timer Details
- pc_system.num_cpu_ticks_remaining
- Time until next scheduled interrupt
- Decremented every cpu cycle
- When time remaining goes to zero
- Check the timers to see which one(s) triggered
- Handle the interrupt(s)
- Update remaining time in all timers
- Set pc_system.num_cpu_ticks_remaining to
minremaining time for each timer
33Timer Details
main_cpu_loop
Identify devices to service
Handle instructions
Service interrupts
Call device specific handlers
Update system clock
Update time til next interrupt for all device
timers
Decrement time until next interrupt
Find new time until next interrupt
Time remaining
false
true
goto main_cpu_loop