diff options
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); |