diff options
-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 cbf4becd266..004c5c6aba6 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 495e46a1f11..d2235db4085 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 ba4282eba5b..ebc6ac73389 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 |