virtualizing nonvirtualizable CPUs
Kragen
kragen-discuss@kragen.dnaco.net
Mon, 7 Dec 1998 17:22:39 -0500 (EST)
virtualizing nonvirtualizable CPUs
I'm told Windows9x can't run as an inferior process under any OS, because it
checks the processor status word (an unprivileged operation), determines that
it is an inferior process, and refuses to run.
There's a simple solution to this, and problems like these. (Another such
problem: some CPUs include real-time clocks accessible by unprivileged
instructions. How to replay a process deterministically (for example, to
rerun it to see how an erroneous value got computed) on such a machine?)
This method makes it possible to flawlessly simulate a process having total
control of the machine, with what should be relatively minor speed costs most
of the time.
It requires an MMU that has separate permissions for reading, writing, and
execution.
Originally mark all the code pages as not executable, but readable and writable.
Whenever you get a page fault indicating that the program has tried to execute
a code page, validate the code page as described below, then mark it as
executable and readable, but not writable, and return control to the program,
so it can execute the code you just validated. If you invisibly modified the
code page, mark the page as executable, but neither readable nor writable.
Whenever you get a page fault indicating that the program is trying to read
a validated and invisibly modified code page, return the data the program
should have gotten, so the program can't see the invisible modification. This
is what makes the modification "invisible".
Whenever you get a page fault indicating that the program is trying to write
a validated code page, mark that page as readable and writable, but not
executable. Then the program can modify it to its heart's content, but as
soon as it tries to execute the modified code, that code will have to be
validated (as explained above).
Validating
==========
To "validate" a page of code is to verify that a program executing it cannot
execute any instructions you've defined as "privileged". An example might be
the read-PSW instruction for the Pentium, or a read-clock instruction on a
processor that provides an unprivileged read-clock instruction. The key point
is that you, not the CPU manufacturer, can decide which instructions are
"privileged".
Instructions that are defined as privileged by the CPU manufacturer you
don't have to worry about, because those instructions will cause a trap
anyway -- you don't have to do any extra work to trap them. (You do,
of course, have to do extra work to simulate them.)
For "easy" CPUs -- CPUs that have fixed-length instructions that must be aligned
on word boundaries -- this is as simple as checking each instruction and
replacing any "privileged" ones with traps.
For "hard" CPUs -- like ones with variable-length instructions, or
instructions that are fixed-length but need not be aligned -- it
requires examining every possible interpretation of the given memory
area for possibly "privileged" instructions. So you disassemble an
instruction starting at every byte boundary.
Either way, any "privileged" instructions get replaced by instructions
that will cause a trap. ("Invalid opcode" trap is an easy one.)
Ideally, you'd like to use a one-byte instruction on machines with
variable-length instructions, since you might want to insert
consecutive "trap" instructions.
You may also have to replace some other instructions with traps, if you
screwed up later parts of them by sticking those traps in there. (This
can only happen on "hard" CPUs.) This can possibly trickle backwards
quite a ways.
All of these modifications must be made "invisible" -- see above for how you
keep your modifications invisible.
(I looked into this. You'd think Quarterdeck would have a patent on
this if anyone did, but they don't.)
--
<kragen@pobox.com> Kragen Sitaker <http://www.pobox.com/~kragen/>
This radically anti-cynical approach to life is not just a shared
disposition but also an act of conscious dissent. -- Alan Bershaw, on the
attitude of Jewel fans ("everyday angels")