diff options
Diffstat (limited to 'Documentation/lguest')
-rw-r--r-- | Documentation/lguest/lguest.c | 107 |
1 files changed, 57 insertions, 50 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 7418f852e40c..cbf4becd2667 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
@@ -598,15 +598,17 @@ static void wake_parent(int pipefd, int lguest_fd) | |||
598 | select(devices.max_infd+1, &rfds, NULL, NULL, NULL); | 598 | select(devices.max_infd+1, &rfds, NULL, NULL, NULL); |
599 | /* Is it a message from the Launcher? */ | 599 | /* Is it a message from the Launcher? */ |
600 | if (FD_ISSET(pipefd, &rfds)) { | 600 | if (FD_ISSET(pipefd, &rfds)) { |
601 | int ignorefd; | 601 | int fd; |
602 | /* If read() returns 0, it means the Launcher has | 602 | /* If read() returns 0, it means the Launcher has |
603 | * exited. We silently follow. */ | 603 | * exited. We silently follow. */ |
604 | if (read(pipefd, &ignorefd, sizeof(ignorefd)) == 0) | 604 | if (read(pipefd, &fd, sizeof(fd)) == 0) |
605 | exit(0); | 605 | exit(0); |
606 | /* Otherwise it's telling us there's a problem with one | 606 | /* Otherwise it's telling us to change what file |
607 | * of the devices, and we should ignore that file | 607 | * descriptors we're to listen to. */ |
608 | * descriptor from now on. */ | 608 | if (fd >= 0) |
609 | FD_CLR(ignorefd, &devices.infds); | 609 | FD_SET(fd, &devices.infds); |
610 | else | ||
611 | FD_CLR(-fd - 1, &devices.infds); | ||
610 | } else /* Send LHREQ_BREAK command. */ | 612 | } else /* Send LHREQ_BREAK command. */ |
611 | write(lguest_fd, args, sizeof(args)); | 613 | write(lguest_fd, args, sizeof(args)); |
612 | } | 614 | } |
@@ -658,18 +660,6 @@ static void *_check_pointer(unsigned long addr, unsigned int size, | |||
658 | /* A macro which transparently hands the line number to the real function. */ | 660 | /* A macro which transparently hands the line number to the real function. */ |
659 | #define check_pointer(addr,size) _check_pointer(addr, size, __LINE__) | 661 | #define check_pointer(addr,size) _check_pointer(addr, size, __LINE__) |
660 | 662 | ||
661 | /* This simply sets up an iovec array where we can put data to be discarded. | ||
662 | * This happens when the Guest doesn't want or can't handle the input: we have | ||
663 | * to get rid of it somewhere, and if we bury it in the ceiling space it will | ||
664 | * start to smell after a week. */ | ||
665 | static void discard_iovec(struct iovec *iov, unsigned int *num) | ||
666 | { | ||
667 | static char discard_buf[1024]; | ||
668 | *num = 1; | ||
669 | iov->iov_base = discard_buf; | ||
670 | iov->iov_len = sizeof(discard_buf); | ||
671 | } | ||
672 | |||
673 | /* This function returns the next descriptor in the chain, or vq->vring.num. */ | 663 | /* This function returns the next descriptor in the chain, or vq->vring.num. */ |
674 | static unsigned next_desc(struct virtqueue *vq, unsigned int i) | 664 | static unsigned next_desc(struct virtqueue *vq, unsigned int i) |
675 | { | 665 | { |
@@ -812,12 +802,13 @@ static bool handle_console_input(int fd, struct device *dev) | |||
812 | 802 | ||
813 | /* First we need a console buffer from the Guests's input virtqueue. */ | 803 | /* First we need a console buffer from the Guests's input virtqueue. */ |
814 | head = get_vq_desc(dev->vq, iov, &out_num, &in_num); | 804 | head = get_vq_desc(dev->vq, iov, &out_num, &in_num); |
815 | if (head == dev->vq->vring.num) { | 805 | |
816 | /* If they're not ready for input, we warn and set up to | 806 | /* If they're not ready for input, stop listening to this file |
817 | * discard. */ | 807 | * descriptor. We'll start again once they add an input buffer. */ |
818 | warnx("console: no dma buffer!"); | 808 | if (head == dev->vq->vring.num) |
819 | discard_iovec(iov, &in_num); | 809 | return false; |
820 | } else if (out_num) | 810 | |
811 | if (out_num) | ||
821 | errx(1, "Output buffers in console in queue?"); | 812 | errx(1, "Output buffers in console in queue?"); |
822 | 813 | ||
823 | /* This is why we convert to iovecs: the readv() call uses them, and so | 814 | /* This is why we convert to iovecs: the readv() call uses them, and so |
@@ -827,15 +818,16 @@ static bool handle_console_input(int fd, struct device *dev) | |||
827 | /* This implies that the console is closed, is /dev/null, or | 818 | /* This implies that the console is closed, is /dev/null, or |
828 | * something went terribly wrong. */ | 819 | * something went terribly wrong. */ |
829 | warnx("Failed to get console input, ignoring console."); | 820 | warnx("Failed to get console input, ignoring console."); |
830 | /* Put the input terminal back and return failure (meaning, | 821 | /* Put the input terminal back. */ |
831 | * don't call us again). */ | ||
832 | restore_term(); | 822 | restore_term(); |
823 | /* Remove callback from input vq, so it doesn't restart us. */ | ||
824 | dev->vq->handle_output = NULL; | ||
825 | /* Stop listening to this fd: don't call us again. */ | ||
833 | return false; | 826 | return false; |
834 | } | 827 | } |
835 | 828 | ||
836 | /* If we actually read the data into the Guest, tell them about it. */ | 829 | /* Tell the Guest about the new input. */ |
837 | if (head != dev->vq->vring.num) | 830 | add_used_and_trigger(fd, dev->vq, head, len); |
838 | add_used_and_trigger(fd, dev->vq, head, len); | ||
839 | 831 | ||
840 | /* Three ^C within one second? Exit. | 832 | /* Three ^C within one second? Exit. |
841 | * | 833 | * |
@@ -924,7 +916,8 @@ static bool handle_tun_input(int fd, struct device *dev) | |||
924 | /* FIXME: Actually want DRIVER_ACTIVE here. */ | 916 | /* FIXME: Actually want DRIVER_ACTIVE here. */ |
925 | if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) | 917 | if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) |
926 | warn("network: no dma buffer!"); | 918 | warn("network: no dma buffer!"); |
927 | discard_iovec(iov, &in_num); | 919 | /* We'll turn this back on if input buffers are registered. */ |
920 | return false; | ||
928 | } else if (out_num) | 921 | } else if (out_num) |
929 | errx(1, "Output buffers in network recv queue?"); | 922 | errx(1, "Output buffers in network recv queue?"); |
930 | 923 | ||
@@ -938,9 +931,8 @@ static bool handle_tun_input(int fd, struct device *dev) | |||
938 | if (len <= 0) | 931 | if (len <= 0) |
939 | err(1, "reading network"); | 932 | err(1, "reading network"); |
940 | 933 | ||
941 | /* If we actually read the data into the Guest, tell them about it. */ | 934 | /* Tell the Guest about the new packet. */ |
942 | if (head != dev->vq->vring.num) | 935 | add_used_and_trigger(fd, dev->vq, head, sizeof(*hdr) + len); |
943 | add_used_and_trigger(fd, dev->vq, head, sizeof(*hdr) + len); | ||
944 | 936 | ||
945 | verbose("tun input packet len %i [%02x %02x] (%s)\n", len, | 937 | verbose("tun input packet len %i [%02x %02x] (%s)\n", len, |
946 | ((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1], | 938 | ((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1], |
@@ -950,6 +942,15 @@ static bool handle_tun_input(int fd, struct device *dev) | |||
950 | return true; | 942 | return true; |
951 | } | 943 | } |
952 | 944 | ||
945 | /* This callback ensures we try again, in case we stopped console or net | ||
946 | * delivery because Guest didn't have any buffers. */ | ||
947 | static void enable_fd(int fd, struct virtqueue *vq) | ||
948 | { | ||
949 | add_device_fd(vq->dev->fd); | ||
950 | /* Tell waker to listen to it again */ | ||
951 | write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd)); | ||
952 | } | ||
953 | |||
953 | /* This is the generic routine we call when the Guest uses LHCALL_NOTIFY. */ | 954 | /* This is the generic routine we call when the Guest uses LHCALL_NOTIFY. */ |
954 | static void handle_output(int fd, unsigned long addr) | 955 | static void handle_output(int fd, unsigned long addr) |
955 | { | 956 | { |
@@ -996,17 +997,22 @@ static void handle_input(int fd) | |||
996 | * file descriptors and a method of handling them. */ | 997 | * file descriptors and a method of handling them. */ |
997 | for (i = devices.dev; i; i = i->next) { | 998 | for (i = devices.dev; i; i = i->next) { |
998 | if (i->handle_input && FD_ISSET(i->fd, &fds)) { | 999 | if (i->handle_input && FD_ISSET(i->fd, &fds)) { |
1000 | int dev_fd; | ||
1001 | if (i->handle_input(fd, i)) | ||
1002 | continue; | ||
1003 | |||
999 | /* If handle_input() returns false, it means we | 1004 | /* If handle_input() returns false, it means we |
1000 | * should no longer service it. | 1005 | * should no longer service it. Networking and |
1001 | * handle_console_input() does this. */ | 1006 | * console do this when there's no input |
1002 | if (!i->handle_input(fd, i)) { | 1007 | * buffers to deliver into. Console also uses |
1003 | /* Clear it from the set of input file | 1008 | * it when it discovers that stdin is |
1004 | * descriptors kept at the head of the | 1009 | * closed. */ |
1005 | * device list. */ | 1010 | FD_CLR(i->fd, &devices.infds); |
1006 | FD_CLR(i->fd, &devices.infds); | 1011 | /* Tell waker to ignore it too, by sending a |
1007 | /* Tell waker to ignore it too... */ | 1012 | * negative fd number (-1, since 0 is a valid |
1008 | write(waker_fd, &i->fd, sizeof(i->fd)); | 1013 | * FD number). */ |
1009 | } | 1014 | dev_fd = -i->fd - 1; |
1015 | write(waker_fd, &dev_fd, sizeof(dev_fd)); | ||
1010 | } | 1016 | } |
1011 | } | 1017 | } |
1012 | } | 1018 | } |
@@ -1154,11 +1160,11 @@ static void setup_console(void) | |||
1154 | dev->priv = malloc(sizeof(struct console_abort)); | 1160 | dev->priv = malloc(sizeof(struct console_abort)); |
1155 | ((struct console_abort *)dev->priv)->count = 0; | 1161 | ((struct console_abort *)dev->priv)->count = 0; |
1156 | 1162 | ||
1157 | /* The console needs two virtqueues: the input then the output. We | 1163 | /* The console needs two virtqueues: the input then the output. When |
1158 | * don't care when they refill the input queue, since we don't hold | 1164 | * they put something the input queue, we make sure we're listening to |
1159 | * data waiting for them. That's why the input queue's callback is | 1165 | * stdin. When they put something in the output queue, we write it to |
1160 | * NULL. */ | 1166 | * stdout. */ |
1161 | add_virtqueue(dev, VIRTQUEUE_NUM, NULL); | 1167 | add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd); |
1162 | add_virtqueue(dev, VIRTQUEUE_NUM, handle_console_output); | 1168 | add_virtqueue(dev, VIRTQUEUE_NUM, handle_console_output); |
1163 | 1169 | ||
1164 | verbose("device %u: console\n", devices.device_num++); | 1170 | verbose("device %u: console\n", devices.device_num++); |
@@ -1270,8 +1276,9 @@ static void setup_tun_net(const char *arg) | |||
1270 | /* First we create a new network device. */ | 1276 | /* First we create a new network device. */ |
1271 | dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input); | 1277 | dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input); |
1272 | 1278 | ||
1273 | /* Network devices need a receive and a send queue. */ | 1279 | /* Network devices need a receive and a send queue, just like |
1274 | add_virtqueue(dev, VIRTQUEUE_NUM, NULL); | 1280 | * console. */ |
1281 | add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd); | ||
1275 | add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output); | 1282 | add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output); |
1276 | 1283 | ||
1277 | /* We need a socket to perform the magic network ioctls to bring up the | 1284 | /* We need a socket to perform the magic network ioctls to bring up the |