diff --git a/Documentation/lguest/Makefile b/Documentation/lguest/Makefile
index 31e794e..60136d8 100644
--- a/Documentation/lguest/Makefile
+++ b/Documentation/lguest/Makefile
@@ -13,7 +13,7 @@ LGUEST_GUEST_TOP := ($(CONFIG_PAGE_OFFSET) - 0x08000000)
CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 -Wl,-T,lguest.lds
LDLIBS:=-lz
-
+LDFLAGS+=-static
all: lguest.lds lguest
# The linker script on x86 is so complex the only way of creating one
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index f791840..bb33ae9 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -15,6 +15,7 @@
#include <stdlib.h>
#include <elf.h>
#include <sys/mman.h>
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -235,15 +236,36 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr,
*
* MAP_PRIVATE means that the page won't be copied until a
* write is done to it. This allows us to share much of the
- * kernel memory between Guests. */
+ * kernel memory between Guests.
+ * Also, another gratuitous use of getpageize :-) as we round
+ * up the section file size.
+ */
addr = mmap((void *)phdr[i].p_paddr,
- phdr[i].p_filesz,
+ roundup(phdr[i].p_filesz, getpagesize()),
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE,
elf_fd, phdr[i].p_offset);
- if (addr != (void *)phdr[i].p_paddr)
- err(1, "Mmaping vmlinux seg %i gave %p not %p",
- i, addr, (void *)phdr[i].p_paddr);
+ /* There is no requirement or guarantee that an ELF file
+ * be appropriately laid out for mmap. In fact, it's
+ * not possible to know for sure beforehand: what if the
+ * file is linked on a machine running with 4K pages and
+ * we end up on a machine with much bigger pages? So we
+ * let the kernel tell us that it can or can not map
+ * the file. If it fails, we read the loader section in and
+ * lose the benefit of the mmap
+ */
+ if (addr != (void *)phdr[i].p_paddr){
+ ssize_t rsize;
+ warn("Mmaping vmlinux seg %i gave %p not %p",
+ i, addr, (void *)phdr[i].p_paddr);
+ addr = (void *) phdr[i].p_paddr;
+ /* read it in ... */
+ if ((rsize = pread(elf_fd, addr, phdr[i].p_filesz,
+ phdr[i].p_offset)) < phdr[i].p_filesz)
+ err(1,
+ "Reading in ELF file gave %i not %d\n", rsize,
+ phdr[i].p_filesz);
+ }
}
return entry_point((void *)start, (void *)end, *page_offset);
diff --git a/drivers/lguest/Kconfig b/drivers/lguest/Kconfig
index 888205c..736e1e3 100644
--- a/drivers/lguest/Kconfig
+++ b/drivers/lguest/Kconfig
@@ -3,6 +3,9 @@ config LGUEST
depends on X86 && PARAVIRT && EXPERIMENTAL && !X86_PAE
select LGUEST_GUEST
select HVC_DRIVER
+ select LGUEST_PLAN9_SYSCALL
+ select LGUEST_NET
+ select LGUEST_BLOCK
---help---
This is a very simple module which allows you to run
multiple instances of the same Linux kernel, using the
@@ -19,6 +22,11 @@ config LGUEST_GUEST
support as a module. The drivers are tiny, so we build them
in too.
+config LGUEST_PLAN9_SYSCALL
+ bool
+ help
+ Support for Plan 9 system calls.
+
config LGUEST_NET
tristate
depends on LGUEST_GUEST && NET
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 49787e9..4f83224 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -222,7 +222,11 @@ static int direct_trap(const struct lguest *lg,
{
/* Hardware interrupts don't go to the Guest at all (except system
* call). */
- if (num >= FIRST_EXTERNAL_VECTOR && num != SYSCALL_VECTOR)
+ if (num >= FIRST_EXTERNAL_VECTOR &&
+#ifdef CONFIG_LGUEST_PLAN9_SYSCALL
+ num != PLAN9_SYSCALL_VECTOR &&
+#endif
+ num != SYSCALL_VECTOR)
return 0;
/* The Host needs to see page faults (for shadow paging and to save the
@@ -351,6 +355,10 @@ void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi)
set_trap(lg, &lg->idt[num], num, lo, hi);
else if (num == SYSCALL_VECTOR)
set_trap(lg, &lg->syscall_idt, num, lo, hi);
+#ifdef CONFIG_LGUEST_PLAN9_SYSCALL
+ else if (num == PLAN9_SYSCALL_VECTOR)
+ set_trap(lg, &lg->syscall_idt, num, lo, hi);
+#endif
}
/* The default entry for each interrupt points into the Switcher routines which
@@ -407,6 +415,13 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
idt[i] = lg->syscall_idt;
else
default_idt_entry(&idt[i], i, def[i]);
+#ifdef CONFIG_LGUEST_PLAN9_SYSCALL
+ i = PLAN9_SYSCALL_VECTOR;
+ if (direct_trap(lg, &lg->syscall_idt, i))
+ idt[i] = lg->syscall_idt;
+ else
+ default_idt_entry(&idt[i], i, def[i]);
+#endif
}
void guest_set_clockevent(struct lguest *lg, unsigned long delta)
diff --git a/include/linux/lguest.h b/include/linux/lguest.h
index 157ad64..08d5474 100644
--- a/include/linux/lguest.h
+++ b/include/linux/lguest.h
@@ -26,6 +26,7 @@
#define LG_CLOCK_MIN_DELTA 100UL
#define LG_CLOCK_MAX_DELTA ULONG_MAX
+#define PLAN9_SYSCALL_VECTOR 0x40
/*G:031 First, how does our Guest contact the Host to ask for privileged
* operations? There are two ways: the direct way is to make a "hypercall",
* to make requests of the Host Itself.
|