We want to be able to mark multiple physical pages as containing
virtualized code. In fact, it's good to leave this marking,
even across multiple CR3 reloads, so that when a task gets
rescheduled our code cache remains useful. That's no
problem.
Though, I need to figure out which strategy to use for handling
accesses to pages which have virtualized code.
For the moment, forget about the physical page holding
currently executing code, and any linear addresses which
map to it. They are handled differently. Assume PTE.P=0
for those. Here are some options for marking the Page
Table Entry (PTE) for any given page which maps to a
vcode page.
(1) PTE.P=1, PTE.RW=0
Reads to vcode pages execute normally, writes fault.
Upon write fault, can either:
A) dump that vcode page and remap PTE.RW as normal data page
B) emulate the instruction
(2) PTE.P=1, PTE.RW=1
Reads and writes to vcode pages execute normally, no faults.
Before executing code in any page, examine the PTE.D bit.
If dirty, then dump vcode page and remap as normal data page.
Option (2) has the benefit of allowing both reads and writes to
occur to vcode pages without generating an exception. The tradeoff
is that we only have the option to dump an entire vcode page
if the page is dirty.
Option (1) incurrs a write exception, but we have the option of
emulating the instruction (and write) so we can possible keep
some or all of the vcode cache for that page intact.
I'm not sure which of these is best yet. Any feedback welcome.
-Kevin