Kevin Lawton wrote:
[snip]
> Approach #2:
> 
> If we wanted to let these 2 instructions execute without
> virtualized intervention, and still yield accurate results
> with respect to the base address returned, then we could
> actually place the GDT and IDT structures at their expected
> linear addresses.  Since we need to page protect the GDT
> and IDT from access by the guest-OS code anyways so
> we can virtualize these structures, we might as well actually
> place them where the guest OS thinks they should be.
> Keep in mind that both the guest-OS and guest-app code
> will be pushed down to ring3, so they will generate
> a page fault upon trying to access the areas of memory
> containing the GDT and IDT, which we of course protected.
> This gives us a chance to do something smart with the
> access.

Can't this present rather serious problems ?

For instance, in my code, I have

    PUBLIC descTable(GDT, NOGDTENTRIES) {
        /* ... */
    } 

NOGDTENTRIES is something like 9, IIRC.  This is just part of
the binary image of the kernel, and takes up a fixed amount of
room in between the rest of the data.  This means we cannot
overrun the GDT size !!!  And we'll probably need extra
segments ourselves for the monitor, so we may get stuck here.

Another thing, you cannot give even read access to the GDT/IDT
to virtualised code, because is the virtualised code modifies
the area of memory that it thinks is the GDT or IDT, it'll also
expect that what they wrote to the memory will actually be
there.  We cannot guarantee that (just think about those IRQ
stubs) so the page would need to be marked non-present.
So the question is, does it really pay to put the IDT/GDT
where the virtualised code thinks it is, even if it is
possible ?  You need to mark a page non-present where it'd
otherwise be read-only --- so, to save effort with two
instructions which'll usually be executed only once, if ever,
in the session lifetime, you cause a bazillion of extra
page faults on a potentially very busy data page.  I'd
go for the scanning method (the first one).

> MAPPING THE ACTUAL MONITOR INTERRUPT HANDLER CODE INTO
> THE GUEST LINEAR SPACE
> ======================================================
> 
> Now that we've discussed placing the GDT and IDT in
> linear memory, we need to map the actual interrupt handler
> code as well.  Since we will be virtualizing the IDT and
> GDT, the guest OS will not see our segment descriptors
> and selectors, so we have some freedom here.  We can
> place this code (by page mapping it) into an unused
> linear address range, again given we have access to the
> guest-OS page tables.
[snip segment placement solution]

Perhaps we should run a few experiments with compiling the
module with -fPIC and look whether the kernel module loader
chokes or not.  If that would work then that'd save us
the effort of figuring out how to fit all those segments
together in the right way.

> This kind of overhead will only occur once per time that
> we find we are no longer living in free memory.  To reduce
> this even further, we could start out at, and use well known
> alternative addresses as part of our relocation strategy.
> The addresses we use, could be ones which are likely not
> to be used by particular guest OSes.

Good idea.

Ramon



Reply via email to