diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-07-23 21:43:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-24 15:24:59 -0400 |
commit | 6570c45995a6339597462434a81f358a38941ac4 (patch) | |
tree | e1d963379a71e847f92c447a7ebffeb45bdf1d0f /Documentation/lguest/lguest.c | |
parent | 6ddb23c78aeef40f549c5ad22a3e8dfa1f8297e0 (diff) |
link lguest example launcher non-static
S.Caglar Onur points out that many distributions don't ship a static
zlib. Unfortunately the launcher currently maps virtual device memory
where shared libraries want to go.
The solution is to pre-scan the args to figure out how much memory we
have, then allocate devices above that, rather than down from the top
possible address. This also turns out to be simpler.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'Documentation/lguest/lguest.c')
-rw-r--r-- | Documentation/lguest/lguest.c | 84 |
1 files changed, 34 insertions, 50 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 1432b502a2d9..62a8133393e1 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
@@ -47,12 +47,14 @@ static bool verbose; | |||
47 | #define verbose(args...) \ | 47 | #define verbose(args...) \ |
48 | do { if (verbose) printf(args); } while(0) | 48 | do { if (verbose) printf(args); } while(0) |
49 | static int waker_fd; | 49 | static int waker_fd; |
50 | static u32 top; | ||
50 | 51 | ||
51 | struct device_list | 52 | struct device_list |
52 | { | 53 | { |
53 | fd_set infds; | 54 | fd_set infds; |
54 | int max_infd; | 55 | int max_infd; |
55 | 56 | ||
57 | struct lguest_device_desc *descs; | ||
56 | struct device *dev; | 58 | struct device *dev; |
57 | struct device **lastdev; | 59 | struct device **lastdev; |
58 | }; | 60 | }; |
@@ -324,8 +326,7 @@ static void concat(char *dst, char *args[]) | |||
324 | static int tell_kernel(u32 pgdir, u32 start, u32 page_offset) | 326 | static int tell_kernel(u32 pgdir, u32 start, u32 page_offset) |
325 | { | 327 | { |
326 | u32 args[] = { LHREQ_INITIALIZE, | 328 | u32 args[] = { LHREQ_INITIALIZE, |
327 | LGUEST_GUEST_TOP/getpagesize(), /* Just below us */ | 329 | top/getpagesize(), pgdir, start, page_offset }; |
328 | pgdir, start, page_offset }; | ||
329 | int fd; | 330 | int fd; |
330 | 331 | ||
331 | fd = open_or_die("/dev/lguest", O_RDWR); | 332 | fd = open_or_die("/dev/lguest", O_RDWR); |
@@ -382,7 +383,7 @@ static int setup_waker(int lguest_fd, struct device_list *device_list) | |||
382 | static void *_check_pointer(unsigned long addr, unsigned int size, | 383 | static void *_check_pointer(unsigned long addr, unsigned int size, |
383 | unsigned int line) | 384 | unsigned int line) |
384 | { | 385 | { |
385 | if (addr >= LGUEST_GUEST_TOP || addr + size >= LGUEST_GUEST_TOP) | 386 | if (addr >= top || addr + size >= top) |
386 | errx(1, "%s:%i: Invalid address %li", __FILE__, line, addr); | 387 | errx(1, "%s:%i: Invalid address %li", __FILE__, line, addr); |
387 | return (void *)addr; | 388 | return (void *)addr; |
388 | } | 389 | } |
@@ -629,24 +630,26 @@ static void handle_input(int fd, struct device_list *devices) | |||
629 | } | 630 | } |
630 | } | 631 | } |
631 | 632 | ||
632 | static struct lguest_device_desc *new_dev_desc(u16 type, u16 features, | 633 | static struct lguest_device_desc * |
633 | u16 num_pages) | 634 | new_dev_desc(struct lguest_device_desc *descs, |
635 | u16 type, u16 features, u16 num_pages) | ||
634 | { | 636 | { |
635 | static unsigned long top = LGUEST_GUEST_TOP; | 637 | unsigned int i; |
636 | struct lguest_device_desc *desc; | ||
637 | 638 | ||
638 | desc = malloc(sizeof(*desc)); | 639 | for (i = 0; i < LGUEST_MAX_DEVICES; i++) { |
639 | desc->type = type; | 640 | if (!descs[i].type) { |
640 | desc->num_pages = num_pages; | 641 | descs[i].type = type; |
641 | desc->features = features; | 642 | descs[i].features = features; |
642 | desc->status = 0; | 643 | descs[i].num_pages = num_pages; |
643 | if (num_pages) { | 644 | if (num_pages) { |
644 | top -= num_pages*getpagesize(); | 645 | map_zeroed_pages(top, num_pages); |
645 | map_zeroed_pages(top, num_pages); | 646 | descs[i].pfn = top/getpagesize(); |
646 | desc->pfn = top / getpagesize(); | 647 | top += num_pages*getpagesize(); |
647 | } else | 648 | } |
648 | desc->pfn = 0; | 649 | return &descs[i]; |
649 | return desc; | 650 | } |
651 | } | ||
652 | errx(1, "too many devices"); | ||
650 | } | 653 | } |
651 | 654 | ||
652 | static struct device *new_device(struct device_list *devices, | 655 | static struct device *new_device(struct device_list *devices, |
@@ -669,7 +672,7 @@ static struct device *new_device(struct device_list *devices, | |||
669 | dev->fd = fd; | 672 | dev->fd = fd; |
670 | if (handle_input) | 673 | if (handle_input) |
671 | set_fd(dev->fd, devices); | 674 | set_fd(dev->fd, devices); |
672 | dev->desc = new_dev_desc(type, features, num_pages); | 675 | dev->desc = new_dev_desc(devices->descs, type, features, num_pages); |
673 | dev->mem = (void *)(dev->desc->pfn * getpagesize()); | 676 | dev->mem = (void *)(dev->desc->pfn * getpagesize()); |
674 | dev->handle_input = handle_input; | 677 | dev->handle_input = handle_input; |
675 | dev->watch_key = (unsigned long)dev->mem + watch_off; | 678 | dev->watch_key = (unsigned long)dev->mem + watch_off; |
@@ -866,30 +869,6 @@ static void setup_tun_net(const char *arg, struct device_list *devices) | |||
866 | verbose("attached to bridge: %s\n", br_name); | 869 | verbose("attached to bridge: %s\n", br_name); |
867 | } | 870 | } |
868 | 871 | ||
869 | /* Now we know how much memory we have, we copy in device descriptors */ | ||
870 | static void map_device_descriptors(struct device_list *devs, unsigned long mem) | ||
871 | { | ||
872 | struct device *i; | ||
873 | unsigned int num; | ||
874 | struct lguest_device_desc *descs; | ||
875 | |||
876 | /* Device descriptor array sits just above top of normal memory */ | ||
877 | descs = map_zeroed_pages(mem, 1); | ||
878 | |||
879 | for (i = devs->dev, num = 0; i; i = i->next, num++) { | ||
880 | if (num == LGUEST_MAX_DEVICES) | ||
881 | errx(1, "too many devices"); | ||
882 | verbose("Device %i: %s\n", num, | ||
883 | i->desc->type == LGUEST_DEVICE_T_NET ? "net" | ||
884 | : i->desc->type == LGUEST_DEVICE_T_CONSOLE ? "console" | ||
885 | : i->desc->type == LGUEST_DEVICE_T_BLOCK ? "block" | ||
886 | : "unknown"); | ||
887 | descs[num] = *i->desc; | ||
888 | free(i->desc); | ||
889 | i->desc = &descs[num]; | ||
890 | } | ||
891 | } | ||
892 | |||
893 | static void __attribute__((noreturn)) | 872 | static void __attribute__((noreturn)) |
894 | run_guest(int lguest_fd, struct device_list *device_list) | 873 | run_guest(int lguest_fd, struct device_list *device_list) |
895 | { | 874 | { |
@@ -934,8 +913,8 @@ static void usage(void) | |||
934 | 913 | ||
935 | int main(int argc, char *argv[]) | 914 | int main(int argc, char *argv[]) |
936 | { | 915 | { |
937 | unsigned long mem, pgdir, start, page_offset, initrd_size = 0; | 916 | unsigned long mem = 0, pgdir, start, page_offset, initrd_size = 0; |
938 | int c, lguest_fd; | 917 | int i, c, lguest_fd; |
939 | struct device_list device_list; | 918 | struct device_list device_list; |
940 | void *boot = (void *)0; | 919 | void *boot = (void *)0; |
941 | const char *initrd_name = NULL; | 920 | const char *initrd_name = NULL; |
@@ -945,6 +924,15 @@ int main(int argc, char *argv[]) | |||
945 | device_list.lastdev = &device_list.dev; | 924 | device_list.lastdev = &device_list.dev; |
946 | FD_ZERO(&device_list.infds); | 925 | FD_ZERO(&device_list.infds); |
947 | 926 | ||
927 | /* We need to know how much memory so we can allocate devices. */ | ||
928 | for (i = 1; i < argc; i++) { | ||
929 | if (argv[i][0] != '-') { | ||
930 | mem = top = atoi(argv[i]) * 1024 * 1024; | ||
931 | device_list.descs = map_zeroed_pages(top, 1); | ||
932 | top += getpagesize(); | ||
933 | break; | ||
934 | } | ||
935 | } | ||
948 | while ((c = getopt_long(argc, argv, "v", opts, NULL)) != EOF) { | 936 | while ((c = getopt_long(argc, argv, "v", opts, NULL)) != EOF) { |
949 | switch (c) { | 937 | switch (c) { |
950 | case 'v': | 938 | case 'v': |
@@ -974,16 +962,12 @@ int main(int argc, char *argv[]) | |||
974 | setup_console(&device_list); | 962 | setup_console(&device_list); |
975 | 963 | ||
976 | /* First we map /dev/zero over all of guest-physical memory. */ | 964 | /* First we map /dev/zero over all of guest-physical memory. */ |
977 | mem = atoi(argv[optind]) * 1024 * 1024; | ||
978 | map_zeroed_pages(0, mem / getpagesize()); | 965 | map_zeroed_pages(0, mem / getpagesize()); |
979 | 966 | ||
980 | /* Now we load the kernel */ | 967 | /* Now we load the kernel */ |
981 | start = load_kernel(open_or_die(argv[optind+1], O_RDONLY), | 968 | start = load_kernel(open_or_die(argv[optind+1], O_RDONLY), |
982 | &page_offset); | 969 | &page_offset); |
983 | 970 | ||
984 | /* Write the device descriptors into memory. */ | ||
985 | map_device_descriptors(&device_list, mem); | ||
986 | |||
987 | /* Map the initrd image if requested */ | 971 | /* Map the initrd image if requested */ |
988 | if (initrd_name) { | 972 | if (initrd_name) { |
989 | initrd_size = load_initrd(initrd_name, mem); | 973 | initrd_size = load_initrd(initrd_name, mem); |