lguest: documentation update

Went through the documentation doing typo and content fixes.  This
patch contains only comment and whitespace changes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2007-10-25 15:02:50 +10:00
parent 568a17ffce
commit e1e72965ec
16 changed files with 414 additions and 266 deletions

View File

@ -63,7 +63,7 @@ static struct lguest_pages *lguest_pages(unsigned int cpu)
static DEFINE_PER_CPU(struct lguest *, last_guest);
/*S:010
* We are getting close to the Switcher.
* We approach the Switcher.
*
* Remember that each CPU has two pages which are visible to the Guest when it
* runs on that CPU. This has to contain the state for that Guest: we copy the
@ -134,7 +134,7 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages)
*
* The lcall also pushes the old code segment (KERNEL_CS) onto the
* stack, then the address of this call. This stack layout happens to
* exactly match the stack of an interrupt... */
* exactly match the stack layout created by an interrupt... */
asm volatile("pushf; lcall *lguest_entry"
/* This is how we tell GCC that %eax ("a") and %ebx ("b")
* are changed by this routine. The "=" means output. */
@ -151,40 +151,46 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages)
}
/*:*/
/*M:002 There are hooks in the scheduler which we can register to tell when we
* get kicked off the CPU (preempt_notifier_register()). This would allow us
* to lazily disable SYSENTER which would regain some performance, and should
* also simplify copy_in_guest_info(). Note that we'd still need to restore
* things when we exit to Launcher userspace, but that's fairly easy.
*
* The hooks were designed for KVM, but we can also put them to good use. :*/
/*H:040 This is the i386-specific code to setup and run the Guest. Interrupts
* are disabled: we own the CPU. */
void lguest_arch_run_guest(struct lguest *lg)
{
/* Remember the awfully-named TS bit? If the Guest has asked
* to set it we set it now, so we can trap and pass that trap
* to the Guest if it uses the FPU. */
/* Remember the awfully-named TS bit? If the Guest has asked to set it
* we set it now, so we can trap and pass that trap to the Guest if it
* uses the FPU. */
if (lg->ts)
lguest_set_ts();
/* SYSENTER is an optimized way of doing system calls. We
* can't allow it because it always jumps to privilege level 0.
* A normal Guest won't try it because we don't advertise it in
* CPUID, but a malicious Guest (or malicious Guest userspace
* program) could, so we tell the CPU to disable it before
* running the Guest. */
/* SYSENTER is an optimized way of doing system calls. We can't allow
* it because it always jumps to privilege level 0. A normal Guest
* won't try it because we don't advertise it in CPUID, but a malicious
* Guest (or malicious Guest userspace program) could, so we tell the
* CPU to disable it before running the Guest. */
if (boot_cpu_has(X86_FEATURE_SEP))
wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
/* Now we actually run the Guest. It will pop back out when
* something interesting happens, and we can examine its
* registers to see what it was doing. */
/* Now we actually run the Guest. It will return when something
* interesting happens, and we can examine its registers to see what it
* was doing. */
run_guest_once(lg, lguest_pages(raw_smp_processor_id()));
/* The "regs" pointer contains two extra entries which are not
* really registers: a trap number which says what interrupt or
* trap made the switcher code come back, and an error code
* which some traps set. */
/* Note that the "regs" pointer contains two extra entries which are
* not really registers: a trap number which says what interrupt or
* trap made the switcher code come back, and an error code which some
* traps set. */
/* If the Guest page faulted, then the cr2 register will tell
* us the bad virtual address. We have to grab this now,
* because once we re-enable interrupts an interrupt could
* fault and thus overwrite cr2, or we could even move off to a
* different CPU. */
/* If the Guest page faulted, then the cr2 register will tell us the
* bad virtual address. We have to grab this now, because once we
* re-enable interrupts an interrupt could fault and thus overwrite
* cr2, or we could even move off to a different CPU. */
if (lg->regs->trapnum == 14)
lg->arch.last_pagefault = read_cr2();
/* Similarly, if we took a trap because the Guest used the FPU,
@ -197,14 +203,15 @@ void lguest_arch_run_guest(struct lguest *lg)
wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
}
/*H:130 Our Guest is usually so well behaved; it never tries to do things it
* isn't allowed to. Unfortunately, Linux's paravirtual infrastructure isn't
* quite complete, because it doesn't contain replacements for the Intel I/O
* instructions. As a result, the Guest sometimes fumbles across one during
* the boot process as it probes for various things which are usually attached
* to a PC.
/*H:130 Now we've examined the hypercall code; our Guest can make requests.
* Our Guest is usually so well behaved; it never tries to do things it isn't
* allowed to, and uses hypercalls instead. Unfortunately, Linux's paravirtual
* infrastructure isn't quite complete, because it doesn't contain replacements
* for the Intel I/O instructions. As a result, the Guest sometimes fumbles
* across one during the boot process as it probes for various things which are
* usually attached to a PC.
*
* When the Guest uses one of these instructions, we get trap #13 (General
* When the Guest uses one of these instructions, we get a trap (General
* Protection Fault) and come here. We see if it's one of those troublesome
* instructions and skip over it. We return true if we did. */
static int emulate_insn(struct lguest *lg)
@ -275,43 +282,43 @@ static int emulate_insn(struct lguest *lg)
void lguest_arch_handle_trap(struct lguest *lg)
{
switch (lg->regs->trapnum) {
case 13: /* We've intercepted a GPF. */
/* Check if this was one of those annoying IN or OUT
* instructions which we need to emulate. If so, we
* just go back into the Guest after we've done it. */
case 13: /* We've intercepted a General Protection Fault. */
/* Check if this was one of those annoying IN or OUT
* instructions which we need to emulate. If so, we just go
* back into the Guest after we've done it. */
if (lg->regs->errcode == 0) {
if (emulate_insn(lg))
return;
}
break;
case 14: /* We've intercepted a page fault. */
/* The Guest accessed a virtual address that wasn't
* mapped. This happens a lot: we don't actually set
* up most of the page tables for the Guest at all when
* we start: as it runs it asks for more and more, and
* we set them up as required. In this case, we don't
* even tell the Guest that the fault happened.
*
* The errcode tells whether this was a read or a
* write, and whether kernel or userspace code. */
case 14: /* We've intercepted a Page Fault. */
/* The Guest accessed a virtual address that wasn't mapped.
* This happens a lot: we don't actually set up most of the
* page tables for the Guest at all when we start: as it runs
* it asks for more and more, and we set them up as
* required. In this case, we don't even tell the Guest that
* the fault happened.
*
* The errcode tells whether this was a read or a write, and
* whether kernel or userspace code. */
if (demand_page(lg, lg->arch.last_pagefault, lg->regs->errcode))
return;
/* OK, it's really not there (or not OK): the Guest
* needs to know. We write out the cr2 value so it
* knows where the fault occurred.
*
* Note that if the Guest were really messed up, this
* could happen before it's done the INITIALIZE
* hypercall, so lg->lguest_data will be NULL */
/* OK, it's really not there (or not OK): the Guest needs to
* know. We write out the cr2 value so it knows where the
* fault occurred.
*
* Note that if the Guest were really messed up, this could
* happen before it's done the LHCALL_LGUEST_INIT hypercall, so
* lg->lguest_data could be NULL */
if (lg->lguest_data &&
put_user(lg->arch.last_pagefault, &lg->lguest_data->cr2))
kill_guest(lg, "Writing cr2");
break;
case 7: /* We've intercepted a Device Not Available fault. */
/* If the Guest doesn't want to know, we already
* restored the Floating Point Unit, so we just
* continue without telling it. */
/* If the Guest doesn't want to know, we already restored the
* Floating Point Unit, so we just continue without telling
* it. */
if (!lg->ts)
return;
break;
@ -536,9 +543,6 @@ int lguest_arch_init_hypercalls(struct lguest *lg)
return 0;
}
/* Now we've examined the hypercall code; our Guest can make requests. There
* is one other way we can do things for the Guest, as we see in
* emulate_insn(). :*/
/*L:030 lguest_arch_setup_regs()
*
@ -570,8 +574,8 @@ void lguest_arch_setup_regs(struct lguest *lg, unsigned long start)
/* %esi points to our boot information, at physical address 0, so don't
* touch it. */
/* There are a couple of GDT entries the Guest expects when first
* booting. */
setup_guest_gdt(lg);
}