Hey all.  I'm writing this email because I'm trying to figure out the
plugins API.  I'm going to guess at it, and if I'm wrong, correct me (and
fix the ???s and FIXMEs).  Then I'll try to work this into some
documentation.  Please don't nitpick the spelling at this point; I'll take
care of that in an iteration or two.


For why I'm trying to figure out the API, see the email that I'm probably
going to write shortly after finishing this one.  It probably could use
quite a bit of editing after that.

Plugin init/deinit
------------------
When the plugin is loaded, the following function, which should be exported
by the .so file, is called:
int plugin_init(plugin_t *plugin, int argc, char *argv[]);
It should return 0 unless plex86 should unload the plugin with extreme
prejustice.

During shutdown of the VM (FIXME: What is valid to do here?), the function
void plugin_fini(void) is called.

plugin_t
--------
The plugin_t structure has the following definition: (user/plugin.h)
typedef struct _plugin_t
{
    int  initialized;
    void *handle; /* This is the dlopen handle; it has nothing to do with
                   * event handlers. */
    int  argc;
    char *name, *args, *argv[MAX_ARGC];
    int  (*init)(struct _plugin_t *plugin, int argc, char *argv[]);
    void (*fini)(void);
    struct _plugin_t *next;
} plugin_t;

All fields are filled in by plex86.  Save this somewhere, you'll need it for
most (all?) API functions.
FIXME: Why both *args and *argv[MAX_ARGC]?

IO Port Handler Registration
----------------------------
To register an input port (range), call:
int plugin_alloc_inp(plugin_t *plugin, handler_t handler, int base, int range)
the returned value is -1 if the allocation failed (note that if any of the
ports are taken, the entire range will fail), or 0 for success.

FIXME: Is last=base+range (looks like it from line 442) or last=base+range-1
(looks like it from line 427)?

Output ports are registered with plugin_alloc_outp in a similar fashion.
Note that the two are completely dissepreate: a given port can be registered
for output by one plugin and for input by another.

call void plugin_free_{in,out}p(plugin_t *plugin, int base, int range) to
free io ports.  Note that you can free parts of a range, so be certian to
free all that you meant to.

Interupt Handler Registration
-----------------------------
FIXME: What's the difference between a software interupt (INTR) and a
hardware one (IAC)?  I'll reread my iapx286 manual (best CPU ref I've got)
later today/tonight to see if I just made a fool of myself.
How does the IAC stuff work?


To register a software interupt handler (IE one that gets called on INT n),
call int plugin_alloc_intr(plugin_t *plugin, handler_t handler, int vec)

This will return -1 if registration fails (you've already registered for
this interupt, or ??? (line 694)).  0 is returned for successful
registration.  FIXME: Should we tell the caller where they are on the stack?

Multiple handlers can be registered for each interupt; they are called in
LIFO order (the last one to be registered is called first).

You can deregister for an interupt with plugin_free_intr(plugin_t *plugin,
int vec).

Handlers
--------

When an IO port that you have allocated is read from/written to, the
handler function you registered is called as:
handler(event_t EVT_{IN,OUT}PORT, int port, int op_size, int count, void *loc)
EVT_{IN,OUT}PORT is the type of event: EVT_INPORT for an input port read,
EVT_OUTPORT for an output port write.

port is the base port.

op_size is the size of the port as read/written: 
4 for inl and friends,
2 for inw and friends,
1 for inb and friends.

count is the number of bytes to read/write (bytes, not ports -- it's
independent of op_size)

loc is a pointer to where you should get the data from or write it to.  It's
gaurnteed to be count bytes long.

Reads/writes may be broken into smaller units on unaligned IO, but smaller
ones will never be colesed into larger units.
FIXME: Should we fix more exactly the way in which they are split?

The INTR handler has the same declaration, but a different calling
convention: int handler(event_t event, int vec, int unused1, int unused2,
void *unused3) event is always EVT_INT, vec is the interupt number, and
unused1=unused2=unused3=0.  The return should be true if the interupt should
be reflected onto the host.

In this context, interrupt reflection refers to an interupt percolating from
the guest to the real hardware.  In specific, if any of the intr handlers
return a true value, then after they have all run, and after returning to
the monitor (in the host's kernel space), an INT n matching the one executed
inside the guest is executed.  FIXME: Is this correct?


FIXME: Is there any API for handling regions of memory?  This would be
useful, not only for handling MMIO, but to allow us to write the BIOS
functionality (for example) in userspace instead of guestspace.  If not, can
I suggest this API:

int plugin_register_memory(plugin_t plugin, handler_t handler, long base,
long range)
base/range are linear guest addresses; don't forget to shift if you're
talking in pages or segments.

Callback forms -- would require either sepperate decleartions or change
in others:

READ, WRITE: int handler(event_t event = EVT_{READ,WRITE}MEM, long base, int
op_size, long count, void *loc); -- REP/string instructions might have large
count or multiple calls, but op_size is always the size of the original
instruction. Alternatively, opsize MSB is 1 if rep/string, 2SB is 1 for rep,
0 for string.  Return is number of bytes read/written.  I'm not certian how
much sense the second makes -- it'd make a serial native operation into a
parallel emulated one.

EXECUTE: int handler(event_t event = EVT_EXECMEM, log base, /*rest unused?*/)


Are the plugin_emulate_* instructions a plugin API or a plex86 one?  Is
there a clear API for reading/writing registers/memory from a plugin?  How
about executing things in guestspace, ...?

      -=- James Mastros


-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GU>CS d->-- s-:- a20 C++ UL+++@ P+++>+++++ L++@ E-() N o? K? w@ M-- !V
PS++ PE Y+ PGP(-) t++@ 5+ X+++ R+ tv+ b+++ DI+ D+ G e>++ h! r- y?
------END GEEK CODE BLOCK------

Reply via email to