aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-10-21 21:29:44 -0400
committerRusty Russell <rusty@rustcorp.com.au>2007-10-23 01:49:57 -0400
commit814a0e5cdfbd384f4bf7a8443f9c3b885f413d58 (patch)
tree4cb82a6ec1db54ce00fbc3700762cd3dc46a0b4e
parent1f5a29022ac66bc90cbe2a2162f56e9cd7b393ef (diff)
Revert lguest magic and use hook in head.S
Version 2.07 of the boot protocol uses 0x23C for the hardware_subarch field, that for lguest is "1". This allows us to use the standard boot entry point rather than the "GenuineLguest" string hack. The standard entry point also clears the BSS and copies the boot parameters and commandline for us, saving more code. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--Documentation/lguest/lguest.c42
-rw-r--r--arch/x86/lguest/boot.c17
-rw-r--r--arch/x86/lguest/i386_head.S17
3 files changed, 18 insertions, 58 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index cbf4becd2667..004c5c6aba6a 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -251,23 +251,6 @@ static void *get_pages(unsigned int num)
251 return addr; 251 return addr;
252} 252}
253 253
254/* To find out where to start we look for the magic Guest string, which marks
255 * the code we see in lguest_asm.S. This is a hack which we are currently
256 * plotting to replace with the normal Linux entry point. */
257static unsigned long entry_point(const void *start, const void *end)
258{
259 const void *p;
260
261 /* The scan gives us the physical starting address. We boot with
262 * pagetables set up with virtual and physical the same, so that's
263 * OK. */
264 for (p = start; p < end; p++)
265 if (memcmp(p, "GenuineLguest", strlen("GenuineLguest")) == 0)
266 return to_guest_phys(p + strlen("GenuineLguest"));
267
268 errx(1, "Is this image a genuine lguest?");
269}
270
271/* This routine is used to load the kernel or initrd. It tries mmap, but if 254/* This routine is used to load the kernel or initrd. It tries mmap, but if
272 * that fails (Plan 9's kernel file isn't nicely aligned on page boundaries), 255 * that fails (Plan 9's kernel file isn't nicely aligned on page boundaries),
273 * it falls back to reading the memory in. */ 256 * it falls back to reading the memory in. */
@@ -303,7 +286,6 @@ static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
303 * We return the starting address. */ 286 * We return the starting address. */
304static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr) 287static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
305{ 288{
306 void *start = (void *)-1, *end = NULL;
307 Elf32_Phdr phdr[ehdr->e_phnum]; 289 Elf32_Phdr phdr[ehdr->e_phnum];
308 unsigned int i; 290 unsigned int i;
309 291
@@ -335,19 +317,13 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
335 verbose("Section %i: size %i addr %p\n", 317 verbose("Section %i: size %i addr %p\n",
336 i, phdr[i].p_memsz, (void *)phdr[i].p_paddr); 318 i, phdr[i].p_memsz, (void *)phdr[i].p_paddr);
337 319
338 /* We track the first and last address we mapped, so we can
339 * tell entry_point() where to scan. */
340 if (from_guest_phys(phdr[i].p_paddr) < start)
341 start = from_guest_phys(phdr[i].p_paddr);
342 if (from_guest_phys(phdr[i].p_paddr) + phdr[i].p_filesz > end)
343 end=from_guest_phys(phdr[i].p_paddr)+phdr[i].p_filesz;
344
345 /* We map this section of the file at its physical address. */ 320 /* We map this section of the file at its physical address. */
346 map_at(elf_fd, from_guest_phys(phdr[i].p_paddr), 321 map_at(elf_fd, from_guest_phys(phdr[i].p_paddr),
347 phdr[i].p_offset, phdr[i].p_filesz); 322 phdr[i].p_offset, phdr[i].p_filesz);
348 } 323 }
349 324
350 return entry_point(start, end); 325 /* The entry point is given in the ELF header. */
326 return ehdr->e_entry;
351} 327}
352 328
353/*L:160 Unfortunately the entire ELF image isn't compressed: the segments 329/*L:160 Unfortunately the entire ELF image isn't compressed: the segments
@@ -374,7 +350,8 @@ static unsigned long unpack_bzimage(int fd)
374 350
375 verbose("Unpacked size %i addr %p\n", len, img); 351 verbose("Unpacked size %i addr %p\n", len, img);
376 352
377 return entry_point(img, img + len); 353 /* The entry point for a bzImage is always the first byte */
354 return (unsigned long)img;
378} 355}
379 356
380/*L:150 A bzImage, unlike an ELF file, is not meant to be loaded. You're 357/*L:150 A bzImage, unlike an ELF file, is not meant to be loaded. You're
@@ -1684,8 +1661,15 @@ int main(int argc, char *argv[])
1684 *(u32 *)(boot + 0x228) = 4096; 1661 *(u32 *)(boot + 0x228) = 4096;
1685 concat(boot + 4096, argv+optind+2); 1662 concat(boot + 4096, argv+optind+2);
1686 1663
1687 /* The guest type value of "1" tells the Guest it's under lguest. */ 1664 /* Boot protocol version: 2.07 supports the fields for lguest. */
1688 *(int *)(boot + 0x23c) = 1; 1665 *(u16 *)(boot + 0x206) = 0x207;
1666
1667 /* The hardware_subarch value of "1" tells the Guest it's an lguest. */
1668 *(u32 *)(boot + 0x23c) = 1;
1669
1670 /* Set bit 6 of the loadflags (aka. KEEP_SEGMENTS) so the entry path
1671 * does not try to reload segment registers. */
1672 *(u8 *)(boot + 0x211) |= (1 << 6);
1689 1673
1690 /* We tell the kernel to initialize the Guest: this returns the open 1674 /* We tell the kernel to initialize the Guest: this returns the open
1691 * /dev/lguest file descriptor. */ 1675 * /dev/lguest file descriptor. */
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 495e46a1f111..d2235db4085f 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -928,18 +928,8 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
928/*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops 928/*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops
929 * structures in the kernel provide points for (almost) every routine we have 929 * structures in the kernel provide points for (almost) every routine we have
930 * to override to avoid privileged instructions. */ 930 * to override to avoid privileged instructions. */
931__init void lguest_init(void *boot) 931__init void lguest_init(void)
932{ 932{
933 /* Copy boot parameters first: the Launcher put the physical location
934 * in %esi, and head.S converted that to a virtual address and handed
935 * it to us. We use "__memcpy" because "memcpy" sometimes tries to do
936 * tricky things to go faster, and we're not ready for that. */
937 __memcpy(&boot_params, boot, PARAM_SIZE);
938 /* The boot parameters also tell us where the command-line is: save
939 * that, too. */
940 __memcpy(boot_command_line, __va(boot_params.hdr.cmd_line_ptr),
941 COMMAND_LINE_SIZE);
942
943 /* We're under lguest, paravirt is enabled, and we're running at 933 /* We're under lguest, paravirt is enabled, and we're running at
944 * privilege level 1, not 0 as normal. */ 934 * privilege level 1, not 0 as normal. */
945 pv_info.name = "lguest"; 935 pv_info.name = "lguest";
@@ -1024,11 +1014,6 @@ __init void lguest_init(void *boot)
1024 * the normal data segment to get through booting. */ 1014 * the normal data segment to get through booting. */
1025 asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory"); 1015 asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory");
1026 1016
1027 /* Clear the part of the kernel data which is expected to be zero.
1028 * Normally it will be anyway, but if we're loading from a bzImage with
1029 * CONFIG_RELOCATALE=y, the relocations will be sitting here. */
1030 memset(__bss_start, 0, __bss_stop - __bss_start);
1031
1032 /* The Host uses the top of the Guest's virtual address space for the 1017 /* The Host uses the top of the Guest's virtual address space for the
1033 * Host<->Guest Switcher, and it tells us how much it needs in 1018 * Host<->Guest Switcher, and it tells us how much it needs in
1034 * lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */ 1019 * lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S
index ba4282eba5bf..ebc6ac733899 100644
--- a/arch/x86/lguest/i386_head.S
+++ b/arch/x86/lguest/i386_head.S
@@ -5,11 +5,8 @@
5#include <asm/thread_info.h> 5#include <asm/thread_info.h>
6#include <asm/processor-flags.h> 6#include <asm/processor-flags.h>
7 7
8/*G:020 This is where we begin: we have a magic signature which the launcher 8/*G:020 This is where we begin: head.S notes that the boot header's platform
9 * looks for. The plan is that the Linux boot protocol will be extended with a 9 * type field is "1" (lguest), so calls us here. The boot header is in %esi.
10 * "platform type" field which will guide us here from the normal entry point,
11 * but for the moment this suffices. The normal boot code uses %esi for the
12 * boot header, so we do too.
13 * 10 *
14 * WARNING: be very careful here! We're running at addresses equal to physical 11 * WARNING: be very careful here! We're running at addresses equal to physical
15 * addesses (around 0), not above PAGE_OFFSET as most code expectes 12 * addesses (around 0), not above PAGE_OFFSET as most code expectes
@@ -19,19 +16,14 @@
19 * The .section line puts this code in .init.text so it will be discarded after 16 * The .section line puts this code in .init.text so it will be discarded after
20 * boot. */ 17 * boot. */
21.section .init.text, "ax", @progbits 18.section .init.text, "ax", @progbits
22.ascii "GenuineLguest" 19ENTRY(lguest_entry)
23 /* Make initial hypercall now, so we can set up the pagetables. */ 20 /* Make initial hypercall now, so we can set up the pagetables. */
24 movl $LHCALL_LGUEST_INIT, %eax 21 movl $LHCALL_LGUEST_INIT, %eax
25 movl $lguest_data - __PAGE_OFFSET, %edx 22 movl $lguest_data - __PAGE_OFFSET, %edx
26 int $LGUEST_TRAP_ENTRY 23 int $LGUEST_TRAP_ENTRY
27 24
28 /* Set up boot information pointer to hand to lguest_init(): it wants
29 * a virtual address. */
30 movl %esi, %eax
31 addl $__PAGE_OFFSET, %eax
32
33 /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl 25 /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl
34 * instruction uses %esi, so we needed to save it above. */ 26 * instruction uses %esi implicitly. */
35 movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi 27 movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi
36 28
37 /* Copy first 32 entries of page directory to __PAGE_OFFSET entries. 29 /* Copy first 32 entries of page directory to __PAGE_OFFSET entries.
@@ -47,7 +39,6 @@
47 /* Set up the initial stack so we can run C code. */ 39 /* Set up the initial stack so we can run C code. */
48 movl $(init_thread_union+THREAD_SIZE),%esp 40 movl $(init_thread_union+THREAD_SIZE),%esp
49 41
50
51 /* Jumps are relative, and we're running __PAGE_OFFSET too low at the 42 /* Jumps are relative, and we're running __PAGE_OFFSET too low at the
52 * moment. */ 43 * moment. */
53 jmp lguest_init+__PAGE_OFFSET 44 jmp lguest_init+__PAGE_OFFSET