On Sun, 3 Dec 2000, James Mastros wrote:
> 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.

I wrote some documentation very very long ago.  Check it out:

http://www.mail-archive.com/plex86%40fastxs.net/msg00181.html

It's probably not up to date but it's a starting point.

> 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.

That's right.

> plugin_t
> --------

You should NEVER TOUCH a plugin_t.  It's used internally by the plex
user program.

However, you will need a pointer to your own plugin_t in order to
communicate with the user program.  Resource allocation requires you
to pass this pointer; it is a sort of "plugin handle".  Save it in
plugin_init().

> 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)?

I think you mean 422?

the correct formula: last=base+range-1.
you allocate range ports.

Explaining line 422:  PORTS is the total amount of ports,
65536.  This means the last available port is PORTS-1 (ports
start at 0).  If the last port in the range is *above*
the last available port, then it doesn't exist and the allocation
should fail.  So:

if (base+range-1 > PORTS-1)
   fail ();

which is the same as

if (base+range > PORTS)
   fail ();
 
> 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.

Correct.
 
> 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?

A software interrupt is an interrupt which is generated by the guest
software by performing an interrupt instruction, such as

   int $0x80

A hardware interrupt is generated (asynchronously) by the hardware.
This is done by the PIC (programmable interrupt controller), which
pulses the processor's INTR line (this is just one of the "legs" on
the x86 chip).  The PIC won't generate another hardware interrupt until
the interrupt has been acknowledged, unless a new interrupt has higher
priority than the previous one.

> 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)

That's not true!!  count is the amount of op_size'd elements in the
array.

You're probably confused by the drop-through structure of
plugin_emulate_outport().  The handler is always called with
the original count value, but remember that at each dropthrough,
the data stream has been split in two --- so if you drop through
from op_size=4 to op_size=2 with count=N, the data stream will
be split up into TWO data streams with count=N, making a total
count of 2N.  total count * op_size remains the same, of course.
 
> Reads/writes may be broken into smaller units on unaligned IO, but smaller
> ones will never be colesed into larger units.

This would not be possible...

> FIXME: Should we fix more exactly the way in which they are split?

Splitting is something internal to the plex86 user program, and not
interesting to plugin writers.  I/O is only split up, if different
parts of the I/O need to go to different plugins!
 
> 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?

Yes.
 
> 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.

Right now, only a quick hack..

> Are the plugin_emulate_* instructions a plugin API or a plex86 one?

They are plex86 internal functions.  Don't touch.

> Is
> there a clear API for reading/writing registers/memory from a plugin?  How
> about executing things in guestspace, ...?

Have a look in user.c.  You will want:

vm_write_physical ()
vm_read_physical ()
vm_get_cpu ()
vm_set_cpu ()

-- Ramon


Reply via email to