aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/lguest/lguest.c60
-rw-r--r--arch/x86/lguest/i386_head.S15
-rw-r--r--drivers/lguest/lg.h2
-rw-r--r--drivers/lguest/lguest_user.c13
-rw-r--r--drivers/lguest/page_tables.c72
-rw-r--r--include/linux/lguest_launcher.h2
6 files changed, 83 insertions, 81 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index aa2574ca94c7..f2dbbf3bdeab 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -481,51 +481,6 @@ static unsigned long load_initrd(const char *name, unsigned long mem)
481 /* We return the initrd size. */ 481 /* We return the initrd size. */
482 return len; 482 return len;
483} 483}
484
485/* Once we know how much memory we have we can construct simple linear page
486 * tables which set virtual == physical which will get the Guest far enough
487 * into the boot to create its own.
488 *
489 * We lay them out of the way, just below the initrd (which is why we need to
490 * know its size here). */
491static unsigned long setup_pagetables(unsigned long mem,
492 unsigned long initrd_size)
493{
494 unsigned long *pgdir, *linear;
495 unsigned int mapped_pages, i, linear_pages;
496 unsigned int ptes_per_page = getpagesize()/sizeof(void *);
497
498 mapped_pages = mem/getpagesize();
499
500 /* Each PTE page can map ptes_per_page pages: how many do we need? */
501 linear_pages = (mapped_pages + ptes_per_page-1)/ptes_per_page;
502
503 /* We put the toplevel page directory page at the top of memory. */
504 pgdir = from_guest_phys(mem) - initrd_size - getpagesize();
505
506 /* Now we use the next linear_pages pages as pte pages */
507 linear = (void *)pgdir - linear_pages*getpagesize();
508
509 /* Linear mapping is easy: put every page's address into the mapping in
510 * order. PAGE_PRESENT contains the flags Present, Writable and
511 * Executable. */
512 for (i = 0; i < mapped_pages; i++)
513 linear[i] = ((i * getpagesize()) | PAGE_PRESENT);
514
515 /* The top level points to the linear page table pages above. */
516 for (i = 0; i < mapped_pages; i += ptes_per_page) {
517 pgdir[i/ptes_per_page]
518 = ((to_guest_phys(linear) + i*sizeof(void *))
519 | PAGE_PRESENT);
520 }
521
522 verbose("Linear mapping of %u pages in %u pte pages at %#lx\n",
523 mapped_pages, linear_pages, to_guest_phys(linear));
524
525 /* We return the top level (guest-physical) address: the kernel needs
526 * to know where it is. */
527 return to_guest_phys(pgdir);
528}
529/*:*/ 484/*:*/
530 485
531/* Simple routine to roll all the commandline arguments together with spaces 486/* Simple routine to roll all the commandline arguments together with spaces
@@ -548,13 +503,13 @@ static void concat(char *dst, char *args[])
548 503
549/*L:185 This is where we actually tell the kernel to initialize the Guest. We 504/*L:185 This is where we actually tell the kernel to initialize the Guest. We
550 * saw the arguments it expects when we looked at initialize() in lguest_user.c: 505 * saw the arguments it expects when we looked at initialize() in lguest_user.c:
551 * the base of Guest "physical" memory, the top physical page to allow, the 506 * the base of Guest "physical" memory, the top physical page to allow and the
552 * top level pagetable and the entry point for the Guest. */ 507 * entry point for the Guest. */
553static int tell_kernel(unsigned long pgdir, unsigned long start) 508static int tell_kernel(unsigned long start)
554{ 509{
555 unsigned long args[] = { LHREQ_INITIALIZE, 510 unsigned long args[] = { LHREQ_INITIALIZE,
556 (unsigned long)guest_base, 511 (unsigned long)guest_base,
557 guest_limit / getpagesize(), pgdir, start }; 512 guest_limit / getpagesize(), start };
558 int fd; 513 int fd;
559 514
560 verbose("Guest: %p - %p (%#lx)\n", 515 verbose("Guest: %p - %p (%#lx)\n",
@@ -1941,7 +1896,7 @@ int main(int argc, char *argv[])
1941{ 1896{
1942 /* Memory, top-level pagetable, code startpoint and size of the 1897 /* Memory, top-level pagetable, code startpoint and size of the
1943 * (optional) initrd. */ 1898 * (optional) initrd. */
1944 unsigned long mem = 0, pgdir, start, initrd_size = 0; 1899 unsigned long mem = 0, start, initrd_size = 0;
1945 /* Two temporaries and the /dev/lguest file descriptor. */ 1900 /* Two temporaries and the /dev/lguest file descriptor. */
1946 int i, c, lguest_fd; 1901 int i, c, lguest_fd;
1947 /* The boot information for the Guest. */ 1902 /* The boot information for the Guest. */
@@ -2040,9 +1995,6 @@ int main(int argc, char *argv[])
2040 boot->hdr.type_of_loader = 0xFF; 1995 boot->hdr.type_of_loader = 0xFF;
2041 } 1996 }
2042 1997
2043 /* Set up the initial linear pagetables, starting below the initrd. */
2044 pgdir = setup_pagetables(mem, initrd_size);
2045
2046 /* The Linux boot header contains an "E820" memory map: ours is a 1998 /* The Linux boot header contains an "E820" memory map: ours is a
2047 * simple, single region. */ 1999 * simple, single region. */
2048 boot->e820_entries = 1; 2000 boot->e820_entries = 1;
@@ -2064,7 +2016,7 @@ int main(int argc, char *argv[])
2064 2016
2065 /* We tell the kernel to initialize the Guest: this returns the open 2017 /* We tell the kernel to initialize the Guest: this returns the open
2066 * /dev/lguest file descriptor. */ 2018 * /dev/lguest file descriptor. */
2067 lguest_fd = tell_kernel(pgdir, start); 2019 lguest_fd = tell_kernel(start);
2068 2020
2069 /* We clone off a thread, which wakes the Launcher whenever one of the 2021 /* We clone off a thread, which wakes the Launcher whenever one of the
2070 * input file descriptors needs attention. We call this the Waker, and 2022 * input file descriptors needs attention. We call this the Waker, and
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S
index 5c7cef34c9e7..10b9bd35a8ff 100644
--- a/arch/x86/lguest/i386_head.S
+++ b/arch/x86/lguest/i386_head.S
@@ -30,21 +30,6 @@ ENTRY(lguest_entry)
30 movl $lguest_data - __PAGE_OFFSET, %edx 30 movl $lguest_data - __PAGE_OFFSET, %edx
31 int $LGUEST_TRAP_ENTRY 31 int $LGUEST_TRAP_ENTRY
32 32
33 /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl
34 * instruction uses %esi implicitly as the source for the copy we're
35 * about to do. */
36 movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi
37
38 /* Copy first 32 entries of page directory to __PAGE_OFFSET entries.
39 * This means the first 128M of kernel memory will be mapped at
40 * PAGE_OFFSET where the kernel expects to run. This will get it far
41 * enough through boot to switch to its own pagetables. */
42 movl $32, %ecx
43 movl %esi, %edi
44 addl $((__PAGE_OFFSET >> 22) * 4), %edi
45 rep
46 movsl
47
48 /* Set up the initial stack so we can run C code. */ 33 /* Set up the initial stack so we can run C code. */
49 movl $(init_thread_union+THREAD_SIZE),%esp 34 movl $(init_thread_union+THREAD_SIZE),%esp
50 35
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 5faefeaf6790..f2c641e0bdde 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -164,7 +164,7 @@ void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt);
164void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt); 164void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt);
165 165
166/* page_tables.c: */ 166/* page_tables.c: */
167int init_guest_pagetable(struct lguest *lg, unsigned long pgtable); 167int init_guest_pagetable(struct lguest *lg);
168void free_guest_pagetable(struct lguest *lg); 168void free_guest_pagetable(struct lguest *lg);
169void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable); 169void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable);
170void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i); 170void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i);
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index e73a000473cc..34bc017b8b3c 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -146,7 +146,7 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
146 return 0; 146 return 0;
147} 147}
148 148
149/*L:020 The initialization write supplies 4 pointer sized (32 or 64 bit) 149/*L:020 The initialization write supplies 3 pointer sized (32 or 64 bit)
150 * values (in addition to the LHREQ_INITIALIZE value). These are: 150 * values (in addition to the LHREQ_INITIALIZE value). These are:
151 * 151 *
152 * base: The start of the Guest-physical memory inside the Launcher memory. 152 * base: The start of the Guest-physical memory inside the Launcher memory.
@@ -155,9 +155,6 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
155 * allowed to access. The Guest memory lives inside the Launcher, so it sets 155 * allowed to access. The Guest memory lives inside the Launcher, so it sets
156 * this to ensure the Guest can only reach its own memory. 156 * this to ensure the Guest can only reach its own memory.
157 * 157 *
158 * pgdir: The (Guest-physical) address of the top of the initial Guest
159 * pagetables (which are set up by the Launcher).
160 *
161 * start: The first instruction to execute ("eip" in x86-speak). 158 * start: The first instruction to execute ("eip" in x86-speak).
162 */ 159 */
163static int initialize(struct file *file, const unsigned long __user *input) 160static int initialize(struct file *file, const unsigned long __user *input)
@@ -166,7 +163,7 @@ static int initialize(struct file *file, const unsigned long __user *input)
166 * Guest. */ 163 * Guest. */
167 struct lguest *lg; 164 struct lguest *lg;
168 int err; 165 int err;
169 unsigned long args[4]; 166 unsigned long args[3];
170 167
171 /* We grab the Big Lguest lock, which protects against multiple 168 /* We grab the Big Lguest lock, which protects against multiple
172 * simultaneous initializations. */ 169 * simultaneous initializations. */
@@ -192,14 +189,14 @@ static int initialize(struct file *file, const unsigned long __user *input)
192 lg->mem_base = (void __user *)args[0]; 189 lg->mem_base = (void __user *)args[0];
193 lg->pfn_limit = args[1]; 190 lg->pfn_limit = args[1];
194 191
195 /* This is the first cpu (cpu 0) and it will start booting at args[3] */ 192 /* This is the first cpu (cpu 0) and it will start booting at args[2] */
196 err = lg_cpu_start(&lg->cpus[0], 0, args[3]); 193 err = lg_cpu_start(&lg->cpus[0], 0, args[2]);
197 if (err) 194 if (err)
198 goto release_guest; 195 goto release_guest;
199 196
200 /* Initialize the Guest's shadow page tables, using the toplevel 197 /* Initialize the Guest's shadow page tables, using the toplevel
201 * address the Launcher gave us. This allocates memory, so can fail. */ 198 * address the Launcher gave us. This allocates memory, so can fail. */
202 err = init_guest_pagetable(lg, args[2]); 199 err = init_guest_pagetable(lg);
203 if (err) 200 if (err)
204 goto free_regs; 201 goto free_regs;
205 202
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index 81d0c6053447..576a8318221c 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -14,6 +14,7 @@
14#include <linux/percpu.h> 14#include <linux/percpu.h>
15#include <asm/tlbflush.h> 15#include <asm/tlbflush.h>
16#include <asm/uaccess.h> 16#include <asm/uaccess.h>
17#include <asm/bootparam.h>
17#include "lg.h" 18#include "lg.h"
18 19
19/*M:008 We hold reference to pages, which prevents them from being swapped. 20/*M:008 We hold reference to pages, which prevents them from being swapped.
@@ -581,15 +582,82 @@ void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 idx)
581 release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx); 582 release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx);
582} 583}
583 584
585/* Once we know how much memory we have we can construct simple identity
586 * (which set virtual == physical) and linear mappings
587 * which will get the Guest far enough into the boot to create its own.
588 *
589 * We lay them out of the way, just below the initrd (which is why we need to
590 * know its size here). */
591static unsigned long setup_pagetables(struct lguest *lg,
592 unsigned long mem,
593 unsigned long initrd_size)
594{
595 pgd_t __user *pgdir;
596 pte_t __user *linear;
597 unsigned int mapped_pages, i, linear_pages, phys_linear;
598 unsigned long mem_base = (unsigned long)lg->mem_base;
599
600 /* We have mapped_pages frames to map, so we need
601 * linear_pages page tables to map them. */
602 mapped_pages = mem / PAGE_SIZE;
603 linear_pages = (mapped_pages + PTRS_PER_PTE - 1) / PTRS_PER_PTE;
604
605 /* We put the toplevel page directory page at the top of memory. */
606 pgdir = (pgd_t *)(mem + mem_base - initrd_size - PAGE_SIZE);
607
608 /* Now we use the next linear_pages pages as pte pages */
609 linear = (void *)pgdir - linear_pages * PAGE_SIZE;
610
611 /* Linear mapping is easy: put every page's address into the
612 * mapping in order. */
613 for (i = 0; i < mapped_pages; i++) {
614 pte_t pte;
615 pte = pfn_pte(i, __pgprot(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER));
616 if (copy_to_user(&linear[i], &pte, sizeof(pte)) != 0)
617 return -EFAULT;
618 }
619
620 /* The top level points to the linear page table pages above.
621 * We setup the identity and linear mappings here. */
622 phys_linear = (unsigned long)linear - mem_base;
623 for (i = 0; i < mapped_pages; i += PTRS_PER_PTE) {
624 pgd_t pgd;
625 pgd = __pgd((phys_linear + i * sizeof(pte_t)) |
626 (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
627
628 if (copy_to_user(&pgdir[i / PTRS_PER_PTE], &pgd, sizeof(pgd))
629 || copy_to_user(&pgdir[pgd_index(PAGE_OFFSET)
630 + i / PTRS_PER_PTE],
631 &pgd, sizeof(pgd)))
632 return -EFAULT;
633 }
634
635 /* We return the top level (guest-physical) address: remember where
636 * this is. */
637 return (unsigned long)pgdir - mem_base;
638}
639
584/*H:500 (vii) Setting up the page tables initially. 640/*H:500 (vii) Setting up the page tables initially.
585 * 641 *
586 * When a Guest is first created, the Launcher tells us where the toplevel of 642 * When a Guest is first created, the Launcher tells us where the toplevel of
587 * its first page table is. We set some things up here: */ 643 * its first page table is. We set some things up here: */
588int init_guest_pagetable(struct lguest *lg, unsigned long pgtable) 644int init_guest_pagetable(struct lguest *lg)
589{ 645{
646 u64 mem;
647 u32 initrd_size;
648 struct boot_params __user *boot = (struct boot_params *)lg->mem_base;
649
650 /* Get the Guest memory size and the ramdisk size from the boot header
651 * located at lg->mem_base (Guest address 0). */
652 if (copy_from_user(&mem, &boot->e820_map[0].size, sizeof(mem))
653 || get_user(initrd_size, &boot->hdr.ramdisk_size))
654 return -EFAULT;
655
590 /* We start on the first shadow page table, and give it a blank PGD 656 /* We start on the first shadow page table, and give it a blank PGD
591 * page. */ 657 * page. */
592 lg->pgdirs[0].gpgdir = pgtable; 658 lg->pgdirs[0].gpgdir = setup_pagetables(lg, mem, initrd_size);
659 if (IS_ERR_VALUE(lg->pgdirs[0].gpgdir))
660 return lg->pgdirs[0].gpgdir;
593 lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL); 661 lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL);
594 if (!lg->pgdirs[0].pgdir) 662 if (!lg->pgdirs[0].pgdir)
595 return -ENOMEM; 663 return -ENOMEM;
diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h
index bd0eba760522..a53407a4165c 100644
--- a/include/linux/lguest_launcher.h
+++ b/include/linux/lguest_launcher.h
@@ -54,7 +54,7 @@ struct lguest_vqconfig {
54/* Write command first word is a request. */ 54/* Write command first word is a request. */
55enum lguest_req 55enum lguest_req
56{ 56{
57 LHREQ_INITIALIZE, /* + base, pfnlimit, pgdir, start */ 57 LHREQ_INITIALIZE, /* + base, pfnlimit, start */
58 LHREQ_GETDMA, /* No longer used */ 58 LHREQ_GETDMA, /* No longer used */
59 LHREQ_IRQ, /* + irq */ 59 LHREQ_IRQ, /* + irq */
60 LHREQ_BREAK, /* + on/off flag (on blocks until someone does off) */ 60 LHREQ_BREAK, /* + on/off flag (on blocks until someone does off) */