diff options
| -rw-r--r-- | Documentation/lguest/Makefile | 2 | ||||
| -rw-r--r-- | Documentation/lguest/lguest.c | 2 | ||||
| -rw-r--r-- | arch/x86/lguest/boot.c | 32 |
3 files changed, 22 insertions, 14 deletions
diff --git a/Documentation/lguest/Makefile b/Documentation/lguest/Makefile index bac037eb1cda..725eef81cd48 100644 --- a/Documentation/lguest/Makefile +++ b/Documentation/lguest/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # This creates the demonstration utility "lguest" which runs a Linux guest. | 1 | # This creates the demonstration utility "lguest" which runs a Linux guest. |
| 2 | CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include | 2 | CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include -I../../arch/x86/include |
| 3 | LDLIBS:=-lz | 3 | LDLIBS:=-lz |
| 4 | 4 | ||
| 5 | all: lguest | 5 | all: lguest |
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index da86fd53856a..804520633fcf 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
| @@ -44,7 +44,7 @@ | |||
| 44 | #include "linux/virtio_console.h" | 44 | #include "linux/virtio_console.h" |
| 45 | #include "linux/virtio_rng.h" | 45 | #include "linux/virtio_rng.h" |
| 46 | #include "linux/virtio_ring.h" | 46 | #include "linux/virtio_ring.h" |
| 47 | #include "asm-x86/bootparam.h" | 47 | #include "asm/bootparam.h" |
| 48 | /*L:110 We can ignore the 39 include files we need for this program, but I do | 48 | /*L:110 We can ignore the 39 include files we need for this program, but I do |
| 49 | * want to draw attention to the use of kernel-style types. | 49 | * want to draw attention to the use of kernel-style types. |
| 50 | * | 50 | * |
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 48ee4f9435f4..a5d8e1ace1cf 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
| @@ -367,10 +367,9 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx, | |||
| 367 | * lazily after a task switch, and Linux uses that gratefully, but wouldn't a | 367 | * lazily after a task switch, and Linux uses that gratefully, but wouldn't a |
| 368 | * name like "FPUTRAP bit" be a little less cryptic? | 368 | * name like "FPUTRAP bit" be a little less cryptic? |
| 369 | * | 369 | * |
| 370 | * We store cr0 (and cr3) locally, because the Host never changes it. The | 370 | * We store cr0 locally because the Host never changes it. The Guest sometimes |
| 371 | * Guest sometimes wants to read it and we'd prefer not to bother the Host | 371 | * wants to read it and we'd prefer not to bother the Host unnecessarily. */ |
| 372 | * unnecessarily. */ | 372 | static unsigned long current_cr0; |
| 373 | static unsigned long current_cr0, current_cr3; | ||
| 374 | static void lguest_write_cr0(unsigned long val) | 373 | static void lguest_write_cr0(unsigned long val) |
| 375 | { | 374 | { |
| 376 | lazy_hcall(LHCALL_TS, val & X86_CR0_TS, 0, 0); | 375 | lazy_hcall(LHCALL_TS, val & X86_CR0_TS, 0, 0); |
| @@ -399,17 +398,23 @@ static unsigned long lguest_read_cr2(void) | |||
| 399 | return lguest_data.cr2; | 398 | return lguest_data.cr2; |
| 400 | } | 399 | } |
| 401 | 400 | ||
| 401 | /* See lguest_set_pte() below. */ | ||
| 402 | static bool cr3_changed = false; | ||
| 403 | |||
| 402 | /* cr3 is the current toplevel pagetable page: the principle is the same as | 404 | /* cr3 is the current toplevel pagetable page: the principle is the same as |
| 403 | * cr0. Keep a local copy, and tell the Host when it changes. */ | 405 | * cr0. Keep a local copy, and tell the Host when it changes. The only |
| 406 | * difference is that our local copy is in lguest_data because the Host needs | ||
| 407 | * to set it upon our initial hypercall. */ | ||
| 404 | static void lguest_write_cr3(unsigned long cr3) | 408 | static void lguest_write_cr3(unsigned long cr3) |
| 405 | { | 409 | { |
| 410 | lguest_data.pgdir = cr3; | ||
| 406 | lazy_hcall(LHCALL_NEW_PGTABLE, cr3, 0, 0); | 411 | lazy_hcall(LHCALL_NEW_PGTABLE, cr3, 0, 0); |
| 407 | current_cr3 = cr3; | 412 | cr3_changed = true; |
| 408 | } | 413 | } |
| 409 | 414 | ||
| 410 | static unsigned long lguest_read_cr3(void) | 415 | static unsigned long lguest_read_cr3(void) |
| 411 | { | 416 | { |
| 412 | return current_cr3; | 417 | return lguest_data.pgdir; |
| 413 | } | 418 | } |
| 414 | 419 | ||
| 415 | /* cr4 is used to enable and disable PGE, but we don't care. */ | 420 | /* cr4 is used to enable and disable PGE, but we don't care. */ |
| @@ -498,13 +503,13 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval) | |||
| 498 | * to forget all of them. Fortunately, this is very rare. | 503 | * to forget all of them. Fortunately, this is very rare. |
| 499 | * | 504 | * |
| 500 | * ... except in early boot when the kernel sets up the initial pagetables, | 505 | * ... except in early boot when the kernel sets up the initial pagetables, |
| 501 | * which makes booting astonishingly slow. So we don't even tell the Host | 506 | * which makes booting astonishingly slow: 1.83 seconds! So we don't even tell |
| 502 | * anything changed until we've done the first page table switch. */ | 507 | * the Host anything changed until we've done the first page table switch, |
| 508 | * which brings boot back to 0.25 seconds. */ | ||
| 503 | static void lguest_set_pte(pte_t *ptep, pte_t pteval) | 509 | static void lguest_set_pte(pte_t *ptep, pte_t pteval) |
| 504 | { | 510 | { |
| 505 | *ptep = pteval; | 511 | *ptep = pteval; |
| 506 | /* Don't bother with hypercall before initial setup. */ | 512 | if (cr3_changed) |
| 507 | if (current_cr3) | ||
| 508 | lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0); | 513 | lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0); |
| 509 | } | 514 | } |
| 510 | 515 | ||
| @@ -521,7 +526,7 @@ static void lguest_set_pte(pte_t *ptep, pte_t pteval) | |||
| 521 | static void lguest_flush_tlb_single(unsigned long addr) | 526 | static void lguest_flush_tlb_single(unsigned long addr) |
| 522 | { | 527 | { |
| 523 | /* Simply set it to zero: if it was not, it will fault back in. */ | 528 | /* Simply set it to zero: if it was not, it will fault back in. */ |
| 524 | lazy_hcall(LHCALL_SET_PTE, current_cr3, addr, 0); | 529 | lazy_hcall(LHCALL_SET_PTE, lguest_data.pgdir, addr, 0); |
| 525 | } | 530 | } |
| 526 | 531 | ||
| 527 | /* This is what happens after the Guest has removed a large number of entries. | 532 | /* This is what happens after the Guest has removed a large number of entries. |
| @@ -581,6 +586,9 @@ static void __init lguest_init_IRQ(void) | |||
| 581 | 586 | ||
| 582 | for (i = 0; i < LGUEST_IRQS; i++) { | 587 | for (i = 0; i < LGUEST_IRQS; i++) { |
| 583 | int vector = FIRST_EXTERNAL_VECTOR + i; | 588 | int vector = FIRST_EXTERNAL_VECTOR + i; |
| 589 | /* Some systems map "vectors" to interrupts weirdly. Lguest has | ||
| 590 | * a straightforward 1 to 1 mapping, so force that here. */ | ||
| 591 | __get_cpu_var(vector_irq)[vector] = i; | ||
| 584 | if (vector != SYSCALL_VECTOR) { | 592 | if (vector != SYSCALL_VECTOR) { |
| 585 | set_intr_gate(vector, interrupt[vector]); | 593 | set_intr_gate(vector, interrupt[vector]); |
| 586 | set_irq_chip_and_handler_name(i, &lguest_irq_controller, | 594 | set_irq_chip_and_handler_name(i, &lguest_irq_controller, |
