Author: Bryce Denney
Date: Wed Nov 20 19:26:24 EST 2002
For any software interrupt, hardware interrupt, or exception, Bochs
calls the instrumentation macro BX_INSTR_INTERRUPT(). For each call
to BX_INSTR_INTERRUPT(), this patch adds instrumentation code that
looks up each interrupt in the Ralf Brown x86 interrupt list and
prints the name of the interrupt in English. This output can be very
useful in telling what a user space program is doing.
For a whole lot of configure options, I put #if...#endif around code that
is specific to the option, even in files which are normally only compiled
when the option is on. This allows me to create a MS Visual C++ 6.0
workspace that supports many of these options. The workspace will basically
compile every file all the time, but the code for disabled options will
be commented out by the #if...#endif.
This may one day lead to simplification of the Makefiles and configure
scripts, but for the moment I'm leaving them alone.
More details inside the file itself.
- add new keyboard init code from Adam Sulmicki
- changed last cli() to #asm cli #endasm
- remove unused cli() function
- don't panic on shutdown status 0x09. just do the normal post
cvs upd -p -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz > patch.gz
Then gunzip it and read it!
If all you are looking for is the change log, I will save you the trouble
and paste it in right here...
----------------------------------------------------------------------
Patch name: patch.plugins
Date: Thu Oct 24 16:19:04 EDT 2002
Authors:
Bryce Denney
Christophe Bothamy
Kevin Lawton (we grabbed a lot of plugin code from plex86)
Testing help from:
Volker Ruppert
Don Becker (Psyon)
Jeremy Parsons (Br'fin)
GENERAL NOTES
- All the work on this patch was done in a CVS branch called BRANCH_PLUGINS.
It was made into a patch mostly for documentation purposes. You can find
more details on many things mentioned here in the CVS logs for
BRANCH_PLUGINS.
- Generally, this patch touches so many files and so many important variables
that any file that has NOT been test-compiled might not compile anymore.
We have tried to test every file, but there are some that we just can't
test without help from others because we don't have every platform avaiable.
During the bugfix/release process for 2.0 I hope we can get somebody to
compile every file so that we don't release a broken 2.0.
- WARNING: I didn't diff the configure script, since it will almost always be
rejected. You must run autoconf after applying this patch.
USING PLUGINS
- add new configure option --enable-plugins, which turns on plugin support
- added 2 new bochsrc options that let you select which configuration
interface and which display library you want to use:
config_interface: control
display_library: sdl
There is one restriction though: if you want to use wxWindows at all,
then it must be selected as both the config_interface and the
display_library. These two are not separable. There could be
strange interactions between other combinations of libraries that we
haven't discovered yet.
- now you can configure with several different --with-* options at once,
and select between them at runtime. This works with or without plugins
enabled. Example: configure --with-x11 --with-sdl --with-term.
To choose between them use "display_library: name" in the bochsrc
- add new configure options --with-all-libs which tries to detect all the
display libraries that can be compiled on your machine, and enables them
all. If the detection fails, you can always write a bunch of
--with-PACKAGE options yourself.
- when you run Bochs, it needs to know where to find its plugins. For now
if the plugins are not stored in a default system library path, you need to
set the LTDL_LIBRARY_PATH environment to a colon-separated list of
directories to search in to find the plugins. When you first build
Bochs, all the plugins are in gui/* and iodev/*. So this command would
work (sh syntax):
LTDL_LIBRARY_PATH=`pwd`/gui:`pwd`/iodev; export LTDL_LIBRARY_PATH
There is a slight variation for win32: use a semicolon instead of a
colon to separate the directories in the list, and the directories should
start with a drive letter and colon. Example
d:/bochs/plugins;d:/bochs-2.0/plugins
PLATFORMS
- on Win32 platforms, plugins currently work in Cygwin/MinGW but some more
work is needed to support VC++. The makefiles build .DLL files for
the plugins using gcc and a program called dlltool. Remember to
use semicolons to separate dir names in LTDL_LIBRARY_PATH, and to
list absolute directories starting with a drive letter.
- on MacOS X, plugins will only work correctly if you install the
"dlcompat" library. Dlcompat is part of the OpenDarwin project.
- Bochs plugins work on Linux and Solaris without any extra work.
CONFIGURE AND MAKE
- makefiles in gui and iodev directories have some new options and targets
for building plugins. First the object files are sorted into two groups,
pluggable and non-pluggable. When you are compiling with plugins, each of
the pluggable object files is added to the list to compile as plugins.
If plugins are disabled, all objects are put into a list to compile
normally.
- remove MDEFINES from top level makefile
- add LDFLAGS to the @LINK@ variable that is set by configure
- add several plugin-related make targets in toplevel, gui, and iodev
makefiles
- use libtool to build libraries: both static and shared. Except on win32,
libtool doesn't do the job so we just use gcc directly with help from
a program called dlltool.
- use libtool's tiny LTDL library to provide a cross-platform interface
to the functions that load shared libraries. The LTDL sources are included
in the Bochs source code now (ltdl.h and ltdl.c), and also the configure
script generates ltdlconf.h. Bryce has done some minor-to-medium intensity
hacking on LTDL to make it work at all. To see the changes, do cvs diff
-r1.1.2.1 -r1.1.2.2 ltdl.c or look at the CVS logs of
bochs-testing/plugin-test/libltdl/ltdl.c for details.
- add "BOCHSAPI" to every variable, function, and class that any plugin
will need, for building win32 DLLs. The BOCHSAPI macro is used
for DLL building on win32 platforms. In config.h it is defined as
__declspec(dllexport), or __declspec(dllimport), or empty. Config.h
knows if it should be importing or exporting symbols by the BX_PLUGGABLE
macro which is defined in all plugin files.
PLUGIN CONFIGURATION INTERFACES AND DISPLAY LIBRARIES
- a configuration interface is a set of menus that lets you change Bochs's
settings. You can choose between two configuration interfaces:
the text mode menus, and the wxWindows graphical interface.
- A display library is the code that shows text and graphics on the
virtual Bochs screen. There are many different display libraries
to choose from, for example X11, win32, BeOS, Carbon(MacOSX), SDL, etc.
Except for wxWindows, all display libraries look pretty similar. They
create a window with a toolbar full of buttons at the top.
- The wxWindows port is BOTH a configuration interface and a display library.
It has menus and dialog boxes (the config interface) and also a toolbar and
virtual Bochs screen.
- now the standard main() is used ALL the time, even for wxWindows which
used to define its own main in the IMPLEMENT_APP macro. Now we always
start in main(), and wxWindows uses the IMPLEMENT_APP_NO_MAIN macro. It
parses the command line and possibly the configuration file, then according
to the setting of the param BXP_SEL_CONFIG_INTERFACE it starts the text
config interface (control) or the wxWindows config interface (loading a
plugin if necessary). Now the config interface is responsible for
starting the simulation at the appropriate time (by calling
SIM->begin_simulation()), instead of returning and letting main start the
simulation. See cvs log for main.cc 1.156.2.14 for more details.
- wxmain.cc's MyApp::OnInit function is called later in the startup
process than it used to be. Now main() does the first few steps, such
as calling bx_init_main(), and starts up the configuration interface
when it's ready. This means that the config interface does not get
to control the messages that appear during command line parsing or
loading of the .bochsrc. It may have to change in the future.
- configuration interfaces now must define an initialization function that
calls SIM->register_configuration_interface with a callback function.
The callback function is called whenever Bochs needs a simulation
interface. This allows us to easily select between them, even when
support for multiple config interfaces is compiled in. wxWindows
has been made into a plugin, but so far control.cc (the text config
interface) has not due to some difficulties linking bochs without it.
- Bryce intends to rename control.cc to textconfig.cc or something more
appropriate when the branch merge is done. When it was created, it was
called a "control panel" but now that term has been replaced by a
"configuration interface".
- Each display library file (gui/win32.cc, gui/x.cc, etc.) defines a C++ class
that descends from bx_gui_c. bx_gui_c declares some of its methods virtual
so that the child class can redefine the methods. The virtual methods are:
specific_init, text_update, graphics_tile_update, handle_events, flush,
clear_screen, palette_change, dimension_update, create_bitmap,
headerbar_bitmap, replace_bitmap, show_headerbar, get_clipboard_text,
set_clipboard_text, mouse_enabled_changed_specific, and exit. Also,
each file needed a plugin_init, which creates an object of the right
type and sets the global "bx_gui" to it, and a plugin_fini which
(theoretically) cleans up afterward. These turned out to be so similar
that they are defined in a macro called IMPLEMENT_GUI_PLUGIN_CODE(gui_name).
(As usual, wxWindows is different and needs its own plugin_init and fini
since it provides both a configuration interface and a display. It
registers a config interface and calls MyPanel::OnPluginInit, which is
in wx.cc, to create a bx_wx_gui_c and set the bx_gui pointer.)
- removed the first argument of bx_gui::specific_init method because it
is no longer static. In a virtual method, you always know who "this" is.
- bx_gui::get_sighandler_mask() and bx_gui::sighandler() are always present,
defined as virtual methods that do nothing. In term.cc only, they are
redefined to do whatever term needs to do with them. This solves problems
with undefined symbols when you enable term support.
- The various display libraries used to all redefine bx_gui methods instead
of virtual methods of their own subclass. This made it impossible to
compile multiple guis at once. Because they are all child classes with
different names, any number can be linked into a binary at once. This was
important for plugins, but even without plugins it allows us to compile
in support for many display libraries and select them at runtime.
- in siminterface, added register_configuration_interface and
configuration_interface. The register method is called by the
init function of a configuration interface (control.cc or wxmain.cc)
to tell siminterface what function to call when someone wants to start
the config interface. To start it, you call configuration_interface(),
which calls the callback function set up by that init function.
- in siminterface, is_sim_thread, set_sim_thread_func. These replace the
global isSimThread function. I had to make something that was
1) available if wxWindows was compiled in, compiled as a plugin and
either loaded, or not., and 2) did not have any link time references
to wxWindows files. As with other things, when wxWindows initializes
it calls SIM->set_sim_thread_func() with a callback function. When
anyone calls SIM->is_sim_thread() it calls the callback function, or if
it hasn't been installed yet it always returns true.
PLUGIN DEVICES
- Plugin devices are not as uniform as plugin display libraries. There
are many of them that interact, some provide special functions that other
devices can call like bx_pic::raise_irq(), and some have to be initialized
before or after others. Our implementation of plugin devices works like
this:
- each device provides a plugin_init method and a plugin_fini method
- the plugin_init method can initialize any number of devices and they
should be "registered" by calling BX_REGISTER_DEVICE_DEVMODEL().
- all plugin devices descend from a class called bx_devmodel_c. The devmodel
class is made up of virtual functions which tell the operations that we
should be able to do on ANY device. The real implementation of a device,
in a child class, will override these methods to implement the real
behavior of that device. As an example, the C++ class heirarchy for the
keyboard device looks like this:
logfunctions
|
+-- bx_devmodel_c
|
+-- bx_keyb_stub_c
|
+-- bx_keyboard_c
Logfunctions provides logging capabilities. bx_devmodel_c provides a
uniform interface for dealing with any device without even knowing which
one it is. bx_keyb_stub_c defines the interfaces that all external
functions and objects can use, but the implementation of those interfaces
just does a panic saying that you forgot to load the keyboard plugin.
Finally, bx_keyboard_c implements all of the missing methods.
- for devices that provide special functions that other devices can call, we
make a "stub" class in iodev/iodev.h which has virtual functions that just
print a panic or warning message. The real device will create a subclass
of the stub, which redefines the virtual methods with the actual
implementation. This means that we can install an instance of the stub if
the plugin is not loaded to catch any calls to the device (it's that
or a segfault). When the plugin is loaded, we replace the stub with a
pointer to the real class. Virtual functions are equivalent in performance
to setting up function pointers, but the syntax is cleaner and the compiler
helps to enforce correct usage.
- because of limitations of shared libraries on some systems such as
Solaris, it is not safe to rely on global variable constructors being
called. So if you write "bx_my_device device;" as a global variable,
on Solaris the constructor(s) for bx_my_device will not ever be called.
That's why in the plugin_init function we explictly create the object
with the "new" operator.
- every file that can be compiled as a plugin should define BX_PLUGGABLE
before including config.h. This is used when building win32 DLLs.
- in plugin.h, define macros for basically every inter-device function,
for example DEV_dma_register_8bit_channel, BX_MEM_READ_PHYSICAL,
DEV_hd_read_handler, etc. The macros are used everywhere instead
of the direct call to the device, because the macros are designed to
do the right thing even if the plugin is not loaded. This is necessary
even for devices that will always be loaded, but we want to make them
into a plugin. Otherwise we can't link bochs because of references to
undefined symbols.
- in iodev/devices.cc, device plugins are loaded if they are needed. At
the moment we still load almost all of them all the time, but it doesn't have
to be that way. Serial and Parallel devices are loaded only if they
are enabled in the bochsrc/config interface. Devices that can be compiled
as plugins are called plugin*. Devices that have not been converted to
plugins still have their old names like sb16, pit, ne2k. At the end
of the bx_devices::init() function we call bx_init_plugins() which
calls the init function of devices created in plugins. (Not every
device, see core plugins vs. optional plugins.) At the end of
bx_devices::reset() we call bx_reset_plugins() which calls the reset
function of devices created in plugins.
- core plugins vs. optional plugins vs. user plugins
- core plugin: These are so fundamental that Bochs can't even initialize
without them, for example the CMOS. The user can substitute his own
equivalent plugin to replace the CMOS, but he cannot say "Don't load the
CMOS at all." Core plugin devices are initialized and reset explictly by
code in iodev/devices.cc, since the initialization order for some of them
is critical. They are currently NOT added to the device list in
pluginRegisterDevice and pluginRegisterDeviceDevmodel, so that the plugin
system does not call init() and reset(). If a core plugin cannot be found,
Bochs will panic.
(NOT DONE) In the bochsrc we could easily provide a way for the user to
replace a core plugin with a different plugin that implements the same C++
interface. This is not implemented yet. Example bochsrc line:
replace_core_plugin: old=pic, new=mypic
- optional plugin: These can be loaded or not, without affecting Bochs's
ability to start up and simulate. Initialization and reset for all
optional plugins are handled by bx_init_plugins() and bx_reset_plugins(),
which are now called from bx_devices_c::init() and bx_devices_c::reset().
Bochs knows how to configure optional plugins at compile time, and they are
loaded only if the configuration settings enables the device. Examples:
serial, parallel. See the call to is_serial_enabled() in iodev/devices.cc.
There are some "optional" plugins that you might not ever want to leave
out, like vga. Maybe the term optional is not clear and we need to think
of a better name. Bochs will panic if an optional plugin cannot be found.
If the plugin was compiled, then it should be available at runtime too!
- (NOT DONE) user plugin: These are plugins that Bochs does not know
anything about at compile time. The user asks Bochs to load a plugin
using just its filename. It loads the plugin and (somehow) gets
information about what settings the user can configure. The settings are
adjusted by either bochsrc lines or the user interface, and then the
device can be used. User plugins will probably not be supported until
after v2.0.
- These categories might change over time, and more may be added. We have
to start somewhere.
- the keyboard timer handler used to control all sorts of things that had very
little to do with the keyboard! For example, it would call SIM->periodic()
and bx_gui->handle_events() to make the gui update when it was supposed to.
This has been moved into iodev/devices.cc instead. It didn't really belong
in the keyboard model, and what if you wanted to simulate with no keyboard
one day?
- in devices.cc, added the concept of a default I/O handler. Before, the
"unmapped" device was initialized first and it would register every single
I/O port in the whole 64k address space, then other devices would claim the
ones that they needed. Now it works differently. Now, the unmapped device
registers the default I/O read handler and the default I/O write handler,
which are represented by BX_DEFAULT_IO_DEVICE. This is from an email
conversation with Christophe
> Sooner or later, we will need to unregister some ioport handler, because
> some ports can be moved around the io architecture (for example the PCI
> IDE Bus Master ioports). Bochs can not do this at the moment.
> ...
> When another device claims the io address, we change the handler
> number to the one of the new function. This behaviour is compatible with
> the old one.
> But when we'll need to unregister an io address handler, we will just
> reset the handler number to BX_DEFAULT_IO_HANDLER so unmapped is called
> again when the io port is accessed.
> This way, we can have Bochs devices register/unregister/re-register
> their handlers.
- device init() methods no longer have an argument. We used to pass in
a pointer to the global variable bx_devices, which each device would
(usually) dutifully store and use instead of using the global symbol,
but it wasn't helping much. If we start to simulate more than one
PC at once (who knows? it might happen) then maybe we'll add it back.
BUG FIXES THAT ENDED UP IN THE PLUGIN BRANCH
(maybe should be checked in separately?)
- gdbstub should not call bx_parse_cmdline anymore
- check SIM->get_init_done before calling DEV_kbd_paste_delay_changed.
- in all makefiles move $(BX_INCDIRS) to the front. Otherwise you can
accidently get config.h or other important includes from libraries
when they put -Ipath into CFLAGS.
- add semicolon to the end of a BX_INFO for XADD_EdGd in arith32.cc
- make control.cc ignore BX_ASYNC_EVT_REFRESH and BX_ASYNC_EVT_DBG_MSG
instead of sending them to default: which prints a warning.
- remove memset(&s, 0, sizeof(s)) in bx_keyb_c constructor. This memset
was wiping out some of the fields of the parent class (logfunctions).
Patch was created with:
cvs diff -u
Apply patch to what version:
cvs checked out on DATE, release version VER
Instructions:
To patch, go to main bochs directory.
Type "patch -p0 < THIS_PATCH_FILE".
----------------------------------------------------------------------
and a very detailed description of what was changed. These changes will
be checked into the CVS trunk momentarily.
Then I will remove the patch, but it will stay around in CVS history
forever as documentation of what we have done.
There was a POTENTIAL RISK for your HARDDISKS with the previous
patch because it updated the concat_image_t object (BX_SPLIT_HD is on
by default). The behaviour of BX_SPLIT_HD is to open all filenames
incrementing the last letter. Guess what follows /dev/hda ?
You may now access block devices from within bochs, only
if --disable-split-hd is configured.
It has only been tested on linux and a WinNT guest.
There are issues with the current bios CHS translating scheme and
the guest OS translating scheme. For example my compaq system translates
a physical 38792/16/63 20GiB harddrive to
a logical 2586/240/63, which does not follow the bitshift algorithm.
I had to find a different PCHS that would translate in a compatible LCHS
I still have to investigate further, but I'm afraid everything I can do
will break some systems or the others.
Those issues should be explained in the documentation.
created in the first rev. When you're talking to Carbon libraries,
of course you should use Boolean instead of bx_bool. My global
search and replace missed such subtleties.
This avoids naming conflicts, since no other library is likely to
use bx_bool.
- I will apply this before release 2.0, but not until the feature freeze
has begun, because it will break almost every patch.
This card has 2 ata channels, so this would be better
than the promise DC2300. It also has drivers for win95,
available on tekram website.
Many thanks to Volker for fixing the interrupt bug!
It solved the problem I had with this patch...
which adds a help command to the debugger
- modified: debug/dbg_main.cc debug/debug.h debug/lexer.c debug/lexer.l
debug/parser.c debug/parser.h debug/parser.y docs-html/debugger.html
- removed the patch file now that the changes are committed
integrate it, if it looks good. Putting here for the CVS trail.
"This patch adds extra inline asm statements for the most important
instructions I found to be still resorting to lazy flags execution.
I counted the instructions that "hit" and "missed" when an eflag
value was needed - if there was a miss, the flag was not known and
had to be calculated with lazy_flags.cc. The culprit instruction
which last executed to affect the eflags was tallied."
parameter so we know which source modules are requesting
timers. Also added a SpewPeriodicTimerInfo #define in
case somebody is still having guest OS hang problems. If
enabled, this macro will force a brief dump of the active timers
list to the bochsout.txt file, every 5Million ticks.
If the lowest timer's period is extremely low, that would be
suspect.
testing. Please try these out if you want to help test
them or if your guest OS appears to be hanging with
no apparent activity. The old bochs internal timer
framework is broken in several areas.
I put these in the patches directory for now. After
a 'make all-clean', you can do something like:
mv pc_system.cc pc_system.cc-old
mv pc_system.h pc_system.h-old
cp patches/pc_system.cc-kpl .
cp patches/pc_system.h-kpl .
make
And let me know if A) they work for you and B) if they help
the hanging problem.
- moved cpu_online_map into the BX_CPU_C structure as a static member
(there is only one per bochs, not one per CPU)
- reduced the diffs in several places to make it more clear what had changed
- removed lots of whitespace diffs
From sf patch page :
This patch adds remote GDB stub capability to Bochs.
It's an updated version of the patched bochs 1.3pre1 in
found in this URL:
http://www.rtmk.org/bochs-gdb.html
more details in the same site. thanks Johan Rydberg
I'm keeping a separate patch in case Christophe wants to make revisions
to his patch without my changes getting in the way.
I have just been working on the configuration interface part, for
example making it so that when you disable the ata[0123] channel, all the
devices controlled by that channel will be disabled as well. I haven't
gotten around to the wxWindows part, but these changes will make the
wxWindows work much easier. I will update this patch as my work progresses.
to diff configure...you'll have to run autoconf yourself.
- in config.h.in set BX_SUPPORT_MMX to 0, not 1. The configure script
will replace it with a 1 if appropriate. That's the way all other
options are done.
- you need to use patch -p1 for this
of bochs' broken paging code, and made an option to compile in
support of 4Meg pages, with the default being disabled, because
it is not well supported yet.
Some devices already had one. Some I had to add an empty one.
I did a little cleaning of init() methods to make them more uniform
but generally I left them alone.
- I also put these exact diffs into a patch "patch.iodev-add-reset"
in case I want to revert these changes for some reason, for example
if they break an old patch. It should be deleted after a while.
Port 0x8901 is used. Two time values can be set and
read, along with the difference of the two.
Please look in the patch file for instructions on usage.
to describe the format of the log prefix. This option can be any string
with special tokens being replaced at run time :
# %t : 11 decimal digits timer tick
# %i : 8 hexadecimal digits of cpu0 current eip
# %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror)
# %d : 5 characters string of the device, between brackets
the default is "%t%i%d", so the logprefix is the same as before.
New tokens can be easily added or changed if needed.
Modified Files:
.bochsrc bochs.h logio.cc main.cc gui/control.cc
gui/siminterface.h gui/siminterface.cc
patches/patch.logfilefmteip
in a multiprocessor simulation. Imagine that! Without the patch, there is
just one FPU for all the processors, which is clearly wrong.
See bug [ 461762 ] multiple processors but only one FPU
not required to use a patched wxWindows library, but it allows us to
do much better key mapping. Bryce sent this patch to the wxWindows
developers, and wxWindows 2.3.3 will include these changes.
60 bytes. It may be simpler to just put the padding code into
ne2k.cc instead. As Peter says:
> I don't think it really matters, but for correctness, the eth_*.cc modules
> should probably all be patched as they are simulating what appears on the
> wire (which is wrong). The ne2k.cc module takes what's on the wire and
> assembles it into packets. By doing it that way, the bug is fixed for all
> NIC drivers in the future.
. ports 0x0400 0x0401 and 0xfff0 : rombios
. ports 0x0500 0x0501 and 0x0502 : vgabios
The rombios log output was previously handled by the unmmapped device
boot of linux 2.2.17 to freeze forever. I don't understand what's being
done in this rev, so I'll ask Dave to check over it and see he can find
anything suspicious.
An INIT interrupt with Trigger mode=Level and Level=Deassert tells
all the APICs to set their arbitration ID. It does NOT do a normal
init, as bochs was doing before.
invalid. This fixes the misleading panic message:
bx_local_apic_c::match_logical_addr: cluster model addressing not
implemented, which was printed even if the OS did not request cluster
addressing.