Loading Documentation/lguest/lguest.c +35 −15 Original line number Diff line number Diff line Loading @@ -131,6 +131,9 @@ struct device /* Any queues attached to this device */ struct virtqueue *vq; /* Handle status being finalized (ie. feature bits stable). */ void (*ready)(struct device *me); /* Device-specific data. */ void *priv; }; Loading Loading @@ -925,14 +928,14 @@ static void enable_fd(int fd, struct virtqueue *vq) write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd)); } /* When the Guest asks us to reset a device, it's is fairly easy. */ static void reset_device(struct device *dev) /* When the Guest tells us they updated the status field, we handle it. */ static void update_device_status(struct device *dev) { struct virtqueue *vq; /* This is a reset. */ if (dev->desc->status == 0) { verbose("Resetting device %s\n", dev->name); /* Clear the status. */ dev->desc->status = 0; /* Clear any features they've acked. */ memset(get_feature_bits(dev) + dev->desc->feature_len, 0, Loading @@ -944,6 +947,22 @@ static void reset_device(struct device *dev) vring_size(vq->config.num, getpagesize())); vq->last_avail_idx = 0; } } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) { warnx("Device %s configuration FAILED", dev->name); } else if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) { unsigned int i; verbose("Device %s OK: offered", dev->name); for (i = 0; i < dev->desc->feature_len; i++) verbose(" %08x", get_feature_bits(dev)[i]); verbose(", accepted"); for (i = 0; i < dev->desc->feature_len; i++) verbose(" %08x", get_feature_bits(dev) [dev->desc->feature_len+i]); if (dev->ready) dev->ready(dev); } } /* This is the generic routine we call when the Guest uses LHCALL_NOTIFY. */ Loading @@ -954,9 +973,9 @@ static void handle_output(int fd, unsigned long addr) /* Check each device and virtqueue. */ for (i = devices.dev; i; i = i->next) { /* Notifications to device descriptors reset the device. */ /* Notifications to device descriptors update device status. */ if (from_guest_phys(addr) == i->desc) { reset_device(i); update_device_status(i); return; } Loading Loading @@ -1170,6 +1189,7 @@ static struct device *new_device(const char *name, u16 type, int fd, dev->handle_input = handle_input; dev->name = name; dev->vq = NULL; dev->ready = NULL; /* Append to device list. Prepending to a single-linked list is * easier, but the user expects the devices to be arranged on the bus Loading drivers/lguest/lguest_device.c +13 −7 Original line number Diff line number Diff line Loading @@ -144,20 +144,26 @@ static u8 lg_get_status(struct virtio_device *vdev) return to_lgdev(vdev)->desc->status; } /* To notify on status updates, we (ab)use the NOTIFY hypercall, with the * descriptor address of the device. A zero status means "reset". */ static void set_status(struct virtio_device *vdev, u8 status) { unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices; /* We set the status. */ to_lgdev(vdev)->desc->status = status; hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0); } static void lg_set_status(struct virtio_device *vdev, u8 status) { BUG_ON(!status); to_lgdev(vdev)->desc->status = status; set_status(vdev, status); } /* To reset the device, we (ab)use the NOTIFY hypercall, with the descriptor * address of the device. The Host will zero the status and all the * features. */ static void lg_reset(struct virtio_device *vdev) { unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices; hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0); set_status(vdev, 0); } /* Loading Loading
Documentation/lguest/lguest.c +35 −15 Original line number Diff line number Diff line Loading @@ -131,6 +131,9 @@ struct device /* Any queues attached to this device */ struct virtqueue *vq; /* Handle status being finalized (ie. feature bits stable). */ void (*ready)(struct device *me); /* Device-specific data. */ void *priv; }; Loading Loading @@ -925,14 +928,14 @@ static void enable_fd(int fd, struct virtqueue *vq) write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd)); } /* When the Guest asks us to reset a device, it's is fairly easy. */ static void reset_device(struct device *dev) /* When the Guest tells us they updated the status field, we handle it. */ static void update_device_status(struct device *dev) { struct virtqueue *vq; /* This is a reset. */ if (dev->desc->status == 0) { verbose("Resetting device %s\n", dev->name); /* Clear the status. */ dev->desc->status = 0; /* Clear any features they've acked. */ memset(get_feature_bits(dev) + dev->desc->feature_len, 0, Loading @@ -944,6 +947,22 @@ static void reset_device(struct device *dev) vring_size(vq->config.num, getpagesize())); vq->last_avail_idx = 0; } } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) { warnx("Device %s configuration FAILED", dev->name); } else if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) { unsigned int i; verbose("Device %s OK: offered", dev->name); for (i = 0; i < dev->desc->feature_len; i++) verbose(" %08x", get_feature_bits(dev)[i]); verbose(", accepted"); for (i = 0; i < dev->desc->feature_len; i++) verbose(" %08x", get_feature_bits(dev) [dev->desc->feature_len+i]); if (dev->ready) dev->ready(dev); } } /* This is the generic routine we call when the Guest uses LHCALL_NOTIFY. */ Loading @@ -954,9 +973,9 @@ static void handle_output(int fd, unsigned long addr) /* Check each device and virtqueue. */ for (i = devices.dev; i; i = i->next) { /* Notifications to device descriptors reset the device. */ /* Notifications to device descriptors update device status. */ if (from_guest_phys(addr) == i->desc) { reset_device(i); update_device_status(i); return; } Loading Loading @@ -1170,6 +1189,7 @@ static struct device *new_device(const char *name, u16 type, int fd, dev->handle_input = handle_input; dev->name = name; dev->vq = NULL; dev->ready = NULL; /* Append to device list. Prepending to a single-linked list is * easier, but the user expects the devices to be arranged on the bus Loading
drivers/lguest/lguest_device.c +13 −7 Original line number Diff line number Diff line Loading @@ -144,20 +144,26 @@ static u8 lg_get_status(struct virtio_device *vdev) return to_lgdev(vdev)->desc->status; } /* To notify on status updates, we (ab)use the NOTIFY hypercall, with the * descriptor address of the device. A zero status means "reset". */ static void set_status(struct virtio_device *vdev, u8 status) { unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices; /* We set the status. */ to_lgdev(vdev)->desc->status = status; hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0); } static void lg_set_status(struct virtio_device *vdev, u8 status) { BUG_ON(!status); to_lgdev(vdev)->desc->status = status; set_status(vdev, status); } /* To reset the device, we (ab)use the NOTIFY hypercall, with the descriptor * address of the device. The Host will zero the status and all the * features. */ static void lg_reset(struct virtio_device *vdev) { unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices; hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0); set_status(vdev, 0); } /* Loading