diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-21 21:29:44 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-23 01:49:57 -0400 |
commit | 814a0e5cdfbd384f4bf7a8443f9c3b885f413d58 (patch) | |
tree | 4cb82a6ec1db54ce00fbc3700762cd3dc46a0b4e | |
parent | 1f5a29022ac66bc90cbe2a2162f56e9cd7b393ef (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.c | 42 | ||||
-rw-r--r-- | arch/x86/lguest/boot.c | 17 | ||||
-rw-r--r-- | arch/x86/lguest/i386_head.S | 17 |
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. */ | ||
257 | static 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. */ |
304 | static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr) | 287 | static 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" | 19 | ENTRY(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 |