aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/lguest/lguest.c
diff options
context:
space:
mode:
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);