- added instructions how to update the online documentation
[bochs-mirror.git] / README-plugins
blob8853bbe20459804601843daebfb3f7731bc21895
1 README-plugins
3 This is the README file that came from the CVS branch called BRANCH_PLUGINS.
4 It's not intended to be user documentation for plugins.  It's more like a
5 bunch of to-do lists that the developers used to coordinate their efforts
6 while working on plugins.  At the bottom are some miscellaneous notes by the
7 plugin developers and some references to useful usenet articles.
9 -------------------------------------------------------------------------
10 BRANCH_PLUGINS
12 The branch is called BRANCH_PLUGINS.  There is a normal tag called
13 BRANCH_PLUGINS_BASE that marks the point where the branch began.  The
14 base marker will help at merge time.
16 This branch is a place to experiment with Bochs plugins.  Bryce created
17 the branch on October 4, 2002, and he and Christophe began working on
18 Bochs plugins.
20 We started from Bryce's patch.plugins3, which was a patch from December 2001
21 that copied in some of the plugin architecture from plex86.  Here are the
22 comments from that patch:
24 > Patch name: patch.plugins3
25 > Author: Bryce Denney
26 > Date: Wed Dec 12 17:56:11 EST 2001
28 > This patch replaces the Bochs keyboard with a slightly modified version
29 > of the plex86 keyboard device, which is implemented as a plugin.  This
30 > is sort of a proof of concept, rather than anything that I'm about to
31 > check in.  It uses GNU libtool to compile the plex86 keyboard code into
32 > a shared library, and installs that shared library in
33 > /tmp/bochslib/libplex-keyboard.so.  Then the new code in plugin.cc (which
34 > is adapted from the plex86 plugin code) loads the libplex-keyboard library
35 > during initialization and installs the plex86 keyboard instead of the
36 > bochs keyboard.
38 > I chose the keyboard because it takes about 2 seconds to test that it's
39 > basically working, and because the bochs and plex86 implementations hadn't
40 > changed very much since they split.
42 > If you look at plex-keyboard.cc and plex-keyboard.h, it is fundamentally the
43 > same as the current plex86 code.  I have changed lots of names from bx_* to
44 > plex_* just to reduce confusion and mayhem when I was compiling with both
45 > kbd implementations.  I didn't change anything except to get it to compile.
47 Christophe had made a plugins5 patch, so he checked it in, with these
48 changes:
49  - plex86 keyboard device was marged with Bochs keyboard, as a plugin
50  - plugin.cc was cleaned up
51  - a device registration mechanism was set up
52  - the biosdev and unmapped devices were plugin-ized
54 TO DO:
55 - (LATER) some plugins, such as the GUI, PIT, SB, and NE2000, have several different
56   possible implementations.  In this case, all implementations should be
57   children of a single stub class.  The stub's methods produce errors or
58   panics if they are called, depending on the importance of the device.
59   There is always one instance of the stub class lying around, which will be
60   used if none of the implementation plugins is loaded.  Either an optional
61   plugin or a user plugin can fill in these slots.
63 - platform specific issues
64   - (LATER) make sure LTDL works on VC++.  It doesn't and won't without
65     significant work.  Maybe it's easier to support VC++ with ifdefs in
66     plugin.cc rather than using ltdl at all.  This will have to wait.
67   - (DONE) nmake build: we must use lib.exe, not $(LIBTOOL) $(CXX) stuff
69 - configure script work
70   - LTDL has a feature called dlpreload which sort of emulates dlopen
71     by linking all the modules statically and then emulating dlopen calls.
72     I don't see any value in this for plugins.  If the platform cannot
73     support dlopen or some equivalent, let the configure script crash and
74     tell the user to configure without plugins instead.
75   - (DONE) to support plugins on MacOSX, the user must install dlcompat.
76     Otherwise libtool's configure script will discover that no dlopen() or
77     equivalent function is found, and it will not be able to build/load
78     plugins.  The configure script should bomb in this case, with an error
79     that says where to find dlcompat.  dlcompat IS installed on SF compile
80     farm in /sw/include and /sw/lib.
82 - Understand/resolve simulation differences between CVS head and
83   BRANCH_PLUGINS.  Simulation is slightly different.
84   - compare four versions
85     - BRANCH_PLUGINS with --enable-plugins
86     - BRANCH_PLUGINS without --enable-plugins
87     - BRANCH_PLUGINS_BASE
88     - CVS head
89   - these differences seem to be explained by a few things:
90     1. devices are initialized in a different order, so they are assigned
91        different timer id.  For any events that occur at the same tick, the
92        timer handlers would get called in a different order.  I believe I
93        have fixed the order of timer registration so that it matches, and
94        that cleaned up some simulation differences.
95     2. bx_gui->handle_events is now called from iodev/devices.cc instead of
96        from iodev/keyboard.cc.
97     3. bx_keyb_c::periodic() used to be called directly from devices.cc
98        but now the keyboard registers its own timer
99   - I have never seen any problems caused by the sim differences, but they
100     make me nervous. -Bryce
102 - (LATER) convert remaining devices
104 - (LATER) maybe the implementation class for each plugin device should go into
105   the .cc file instead of the header file.  If all their methods are called
106   through the stub class virtual functions, and no external file has access to
107   the real non-stub class, then maybe there is no point in letting anybody
108   else see the real class at all?  (If you do use the class you will get
109   undefined symbols when you compile for plugins anyway.)  For the hard drive,
110   we could put bx_hard_drive_stub_c in harddrv.h, and any constants or types
111   that external files might need, and then put the real class, bx_hard_drive_c,
112   at the top of harddrv.cc.
115 - (LATER) eventually we need to clarify the connection between plugins and
116   devices.  At the moment, each plugin creates exactly one device, but it does
117   not have to work that way.
118   - it would be more correct to mark the devices as core, optional, etc. than
119     to use a type field in the plugin struct.  The reason that the type
120     (core,optional,user) is currently passed into the PLUG_load_plugin macro
121     and placed in the plugin struct instead of letting the device code decide
122     is: devices.cc is responsible for initting and resetting devices, so I
123     wanted devices.cc to decide whether the device would be managed by the
124     plugin infrastructure (init_all, reset_all) or not.  This is not that
125     important yet, but when Volker wants to write a plugin with multiple
126     devices, we will need to sort it out.
128 - (LATER) make a way for users to replace a core plugin with one of their
129   choice.
131 - (LATER) implement user plugins.  These are plugins that Bochs does not know
132   anything about at compile time.  The user asks Bochs to load a plugin using
133   just its filename.  It loads the plugin and registers any bx_params that
134   the user can configure, and either the text config interface or the
135   wxWindows interface can display this param list as a menu or dialog.
136   Then at simulation start time, we call init() on the user device and
137   it can be used like any other device.
139 - (LATER) make plugin CPU???
141 DONE:
142 - applied patch.plugins5
143 - updated makefile dependencies now that plugin.h is in there
144 - all guis converted to plugins
145 - 8 I/O devices are converted to plugins
146 - make the Makefile use libtool to build dynamic libraries
147 - use libtool's ltdl library to open and read dynamic libraries, since it
148   has cross platform support
149 - the Boolean/bx_bool thing will be resolved in the main branch.  I have
150   made patch.replace-Boolean.gz which I will apply later, after the
151   plugins branch has been merged.  This become more urgent because it
152   caused bug #623152 MacOSX: Triple Exception Booting win95
153 - take a look at the code generated by calls to virtual functions, to
154   check if there's huge overhead that I don't know about.
155   Answer: I don't believe there is that much extra overhead.  If you call
156   a nonvirtual function, it must push all the args onto the stack, then
157   push the THIS pointer, then call the method using a known constant address.
158   With a virtual function, you push all the args onto the stack, then push
159   the THIS pointer, then do one extra memory reference to THIS+constant to read
160   the pointer to the virtual method, and call it.  This is just what I
161   expected to find--no strange and magicial code was inserted by the
162   compiler in this case.
163 - wxWindows configuration interface and display works fine as a plugin now
164 - selection of config interface is controlled by the bochsrc line
165   "config_interface: NAME" and the parameter bx_options.Osel_config.
166 - selection of display library is controlled by the bochsrc line
167   "display_library: NAME" and the parameter bx_options.Osel_displaylib.
168 - renamed vga_library to display_library (Christophe's suggestion)
169 - add --with-all-libs option, which attempts to detect all the display
170   libraries that Bochs can compile with.  You can use this with or without
171   plugins, compile with multiple guis in the same binary, and select between
172   them at runtime.  If the detection fails, you can always write a bunch
173   of --with-PACKAGE options yourself.
174 - load plugins as they are needed, in main.cc and iodev/devices.cc.
175   - plugins are loaded using a macro PLUG_load_plugin(plugin_name, plugin_type).
176     When plugins are enabled, this macro calls bx_load_plugin() in plugin.cc,
177     which loads the plugin with lt_dlopen and calls its plugin_init method.
178     When plugins are disabled, the code is already linked into the binary so
179     the macro calls the plugin_init method directly.
180   - The plugin_init method for plugin ABC is called libABC_LTX_plugin_init()
181     and the same prefix is added before the plugin_fini method.  This "name
182     mangling" makes the symbols unique so that they can all be linked
183     statically into the binary when plugins are turned off.  This turned out
184     to be a very useful thing!
185   - The choice of lib*_LTX_* is not random...  The libtool LTDL library
186     automatically searches for symbols of the form lib<module>_LTX_<symbol>
187     before looking for <symbol>.  Libtool recommends making global symbols in
188     every plugin unique in some way, and in fact on MacOSX the dynamic linker
189     will not allow two libs to be linked in that both have plugin_init symbols,
190     so this sort of mangling is required.
191 - how do we know what plugins should be available when we start Bochs?
192   - we have core plugins, optional plugins, and user plugins.
193     - (V2.0) core plugin: These are so fundamental that Bochs won't even
194       initialize without them, for example the CMOS.  The user can substitute
195       his own equivalent plugin to replace the CMOS, but he cannot say "Don't
196       load the CMOS at all."  Core plugin devices are initialized and reset
197       explictly by code in iodev/devices.cc, since the initialization order for
198       some of them is critical.  They are currently NOT added to the device
199       list in pluginRegisterDevice and pluginRegisterDeviceDevmodel, so that
200       the plugin system does not call init() and reset().  If a core plugin
201       cannot be found, Bochs will panic.
202       In the bochsrc we can provide a way for the user to REPLACE a core plugin
203       with a different plugin that implements the same C++ interface, but there
204       is no way to ask bochs to NOT load a core plugin.  I'm not sure how to
205       configure the replacement plugin--this may have to be added later.
206       Bochsrc line:
207         replace_core_plugin: old=pic, new=mypic
208     - (V2.0) optional plugin: These can be loaded or not without affecting
209       Bochs's ability to start up and simulate.  Initialization and reset for
210       all optional plugins are handled by bx_init_plugins() and
211       bx_reset_plugins(), which are now called from bx_devices_c::init() and
212       bx_devices_c::reset().  Bochs knows how to configure optional plugins at
213       compile time, and they are loaded only if the configuration settings
214       enables the device.  Examples: serial, parallel, ne2k.  See the call to
215       is_serial_enabled() in iodev/devices.cc.  There are some plugins that you
216       wouldn't ever want to leave out, like vga.  Maybe the term "optional" is
217       not clear and I need to think of a better name.  Bochs will panic if an
218       optional plugin cannot be found.  If the plugin was compiled, then
219       it should be available at runtime too!
220     - (NOT DONE) user plugin: These are plugins that Bochs does not know
221       anything about at compile time.  The user asks Bochs to load a plugin
222       using just its filename.  It loads the plugin and (somehow) gets
223       information about what settings the user can configure.  The settings are
224       adjusted by either bochsrc lines or the user interface, and then the
225       device can be used.  I'm missing some details here because I haven't
226       thought through it all the way.  User plugins may not be supported until
227       after v2.0.
228   - list of plugins sorted into categories
229     - core plugins: unmapped, biosdev, cmos, dma, pic, vga
230     - optional: floppy, harddrv, keyboard, serial, parallel
231     - user: none yet
232 - clarify relationship of plugin and device
233   - a plugin is a shared object that you load that has a plugin_init() and
234     plugin_fini() function inside.  The plugin_init() can create any number of
235     "devices" and register them.  Devices are added to a global list so that we
236     can do operations on every registered device.
237   - There is (now) a pointer from each device to the plugin that created it.
238   - Devices created by core plugins are called core devices.  These will not be
239     added to the device list because they are managed by existing code in
240     devices.cc and elsewhere.  Instead of referring to them by their device_t
241     structure, we will use a global pointer to them, similar to the
242     bx_devices.pluginKeyboard pointer.  (Alternative: maybe we should add
243     them to device list anyway, but exclude them in init_all and reset_all
244     functions.)
245   - MACOSX PLUGINS WORK!  to support plugins on MacOSX, we must ensure that no
246     plugins have any global symbol names in common, including plugin_init!  An
247     easy solution to this is to say that all plugin functions which can be
248     looked up with dlsym must follow a pattern like "%s_BXPLUG_%s", where the
249     first %s is the module name and the second is the plain symbol name, e.g.
250     pic_BXPLUG_plugin_init.  Symbols that are used internally can be declared
251     static (file scope only).
252   - SOLARIS PLUGINS WORK!  to support plugins on Solaris, we must not rely on
253     the use of global object constructors.  In fact every global variable in a
254     module MUST BE set to a compile-time constant.  We must declare object
255     pointers as globals, not actual objects.
256   - WIN32 PLUGINS WORK!  to support plugins on win32, I added the
257     BOCHSAPI macro which expands to __declspec(dllexport) in the nonplugin
258     code and __declspec(dllimport) in the plugin code.  Some makefile hacks
259     were required too.  A few differences between win32 and other platforms:
260     - use semicolon to separate path names in LTDL_LIBRARY_PATH
261     - every path name in LTDL_LIBRARY_PATH should start with a drive letter,
262       for example: c:/cygwin/home/bryce/plugins.
263 - how do we locate plugins on the disk?
264   - make install copies the plugins into ${prefix}/lib
265   - if people install into a standard location, no action may be needed (?)
266   - we can tell people to set the LTDL_LIBRARY_PATH variable.
267   - if necessary we can implement a bochsrc command like
268       plugin_search_directory: /path/to/libs
269     which would call lt_dlsetsearchpath() to add the path to LTDL's list of
270     directories it will search.
271 - change log for BRANCH_PLUGINS is in patches/patch.plugins.  It is
272   pretty complete now.
279 -----------------------------------------------
280 random notes:
282 class heirarchy:
283  logfunctions
284  - bx_devmodel_c
285    - bx_keyb_stub_c
286      - bx_keyb_c
288 bx_devmodel_c is an abstract class that defines standard functions that all
289 devices should define, like init and reset.  Each method is defined as empty
290 in bx_devmodel_c so that child classes can choose to implement them or not.
292 bx_keyb_stub_c declares the methods that code outside the keyboard would need
293 to call, such as mouse_motion, gen_scancode, etc.  It declares these methods
294 virtual, and provides a minimal definition for each that just does a panic.   A
295 global variable pluginKeyboard initially points to an instance of
296 bx_keyb_stub_c so that if you forget/fail to load the load the keyboard plugin,
297 you will see these panics when the methods are called.
299 bx_keyb_c is the real keyboard code.  In its constructor, it changes
300 pluginKeyboard to point to "this".  This is equivalent to installing all
301 the plugin callbacks associated with the keyboard.  It also works in
302 nonplugin code, which is a plus.
305 hard drive read_handler.  Right now the read_handler
306 is a static method so it must get its object pointer from somewhere.
307   1) It can get it from global variable bx_hard_drive
308   2) The hard drive object can be passed in to it
309 We've always used #2, so every device has methods that look like this:
311   static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
312   static void   write_handler(void *this_ptr, Bit32u address, Bit32u value, unsi
314 If/when we switch over to using virtual methods, there will no longer be
315 any problem finding the this pointer.  If we go that route, the this_ptr
316 can be eliminated.  For now, we must use the this_ptr.  Otherwise we could
317 never support more than one device of a given type.
321 ------------------------------------------
322 References
324 From: Tero Pulkkinen (p150650@zori.cs.tut.fi)
325  Subject: Re: undefined reference to `pm virtual table'
326  Newsgroups: gnu.g++.help
327  Date: 1996/11/15
330 > The compile goes off OK, but I get this error at link time:
331 >   pm.o(.text+0xa8): undefined reference to `pm virtual table'
333 This error comes from that the compiler didnt make virtual function
334 table for object even though there's implemented functions that use
335 objects of that type(constructor for example). Probably your pm-class
336 has all implemented member functions *inline* and you still have
337 (pure) virtual functions inside the class.
339 The creation point of virtual function table usually (dunno if g++ does that)
340 is at position of first seen noninline function body of that class.
341 Now if every of your function is inline, there's no place where compiler
342 could make virtual function table.
344 Fix is to move body of for example constructor(any member is fine) to the .cc
345 file instead of keeping it in .h-file and linking that .o file to your
346 executable.
348 Other sollution is to remove *all* implementations of functions from header
349 file. If all functions of a class are pure virtual, there's no need for
350 virtual function table. (Constructor must set pointer to virtual function
351 table to the object, so, if you have constructor, you'll need virtual
352 function table too, even in abstract classes...)
354 > Can someone help me?  Thanks in advance.
356 Hope this helps....