Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 95767
b: refs/heads/master
c: a007a75
h: refs/heads/master
i:
  95765: 117e48b
  95763: f69f218
  95759: d871c94
v: v3
  • Loading branch information
Rusty Russell committed May 2, 2008
1 parent 73302dd commit ce67355
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9f3f746741d917fe3c6c544c7d319d533176d90b
refs/heads/master: a007a751d98fe97142e4724a83a4e31ec66b7532
50 changes: 35 additions & 15 deletions trunk/Documentation/lguest/lguest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -925,24 +928,40 @@ 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;

verbose("Resetting device %s\n", dev->name);
/* Clear the status. */
dev->desc->status = 0;
/* This is a reset. */
if (dev->desc->status == 0) {
verbose("Resetting device %s\n", dev->name);

/* Clear any features they've acked. */
memset(get_feature_bits(dev) + dev->desc->feature_len, 0,
dev->desc->feature_len);
/* Clear any features they've acked. */
memset(get_feature_bits(dev) + dev->desc->feature_len, 0,
dev->desc->feature_len);

/* Zero out the virtqueues. */
for (vq = dev->vq; vq; vq = vq->next) {
memset(vq->vring.desc, 0,
vring_size(vq->config.num, getpagesize()));
vq->last_avail_idx = 0;
/* Zero out the virtqueues. */
for (vq = dev->vq; vq; vq = vq->next) {
memset(vq->vring.desc, 0,
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);
}
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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
Expand Down
20 changes: 13 additions & 7 deletions trunk/drivers/lguest/lguest_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/*
Expand Down

0 comments on commit ce67355

Please sign in to comment.