aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/lguest/lguest.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-07-23 21:43:56 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-24 15:24:59 -0400
commit6570c45995a6339597462434a81f358a38941ac4 (patch)
treee1d963379a71e847f92c447a7ebffeb45bdf1d0f /Documentation/lguest/lguest.c
parent6ddb23c78aeef40f549c5ad22a3e8dfa1f8297e0 (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.c84
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)
49static int waker_fd; 49static int waker_fd;
50static u32 top;
50 51
51struct device_list 52struct 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[])
324static int tell_kernel(u32 pgdir, u32 start, u32 page_offset) 326static 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)
382static void *_check_pointer(unsigned long addr, unsigned int size, 383static 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
632static struct lguest_device_desc *new_dev_desc(u16 type, u16 features, 633static struct lguest_device_desc *
633 u16 num_pages) 634new_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
652static struct device *new_device(struct device_list *devices, 655static 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 */
870static 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
893static void __attribute__((noreturn)) 872static void __attribute__((noreturn))
894run_guest(int lguest_fd, struct device_list *device_list) 873run_guest(int lguest_fd, struct device_list *device_list)
895{ 874{
@@ -934,8 +913,8 @@ static void usage(void)
934 913
935int main(int argc, char *argv[]) 914int 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);