virtio: simplify config mechanism.

Previously we used a type/len pair within the config space, but this
seems overkill.  We now simply define a structure which represents the
layout in the config space: the config space can now only be extended
at the end.

The main driver-visible changes:
1) We indicate what fields are present with an explicit feature bit.
2) Virtqueues are explicitly numbered, and not in the config space.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 6c8a238..4df1804 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -34,6 +34,8 @@
 #include <zlib.h>
 #include <assert.h>
 #include <sched.h>
+#include <limits.h>
+#include <stddef.h>
 #include "linux/lguest_launcher.h"
 #include "linux/virtio_config.h"
 #include "linux/virtio_net.h"
@@ -99,13 +101,11 @@
 	/* The descriptor page for the devices. */
 	u8 *descpage;
 
-	/* The tail of the last descriptor. */
-	unsigned int desc_used;
-
 	/* A single linked list of devices. */
 	struct device *dev;
-	/* ... And an end pointer so we can easily append new devices */
-	struct device **lastdev;
+	/* And a pointer to the last device for easy append and also for
+	 * configuration appending. */
+	struct device *lastdev;
 };
 
 /* The list of Guest devices, based on command line arguments. */
@@ -191,7 +191,7 @@
 #define cpu_to_le64(v64) (v64)
 #define le16_to_cpu(v16) (v16)
 #define le32_to_cpu(v32) (v32)
-#define le64_to_cpu(v32) (v64)
+#define le64_to_cpu(v64) (v64)
 
 /*L:100 The Launcher code itself takes us out into userspace, that scary place
  * where pointers run wild and free!  Unfortunately, like most userspace
@@ -986,54 +986,44 @@
  *
  * All devices need a descriptor so the Guest knows it exists, and a "struct
  * device" so the Launcher can keep track of it.  We have common helper
- * routines to allocate them.
- *
- * This routine allocates a new "struct lguest_device_desc" from descriptor
- * table just above the Guest's normal memory.  It returns a pointer to that
- * descriptor. */
+ * routines to allocate and manage them. */
+
+/* The layout of the device page is a "struct lguest_device_desc" followed by a
+ * number of virtqueue descriptors, then two sets of feature bits, then an
+ * array of configuration bytes.  This routine returns the configuration
+ * pointer. */
+static u8 *device_config(const struct device *dev)
+{
+	return (void *)(dev->desc + 1)
+		+ dev->desc->num_vq * sizeof(struct lguest_vqconfig)
+		+ dev->desc->feature_len * 2;
+}
+
+/* This routine allocates a new "struct lguest_device_desc" from descriptor
+ * table page just above the Guest's normal memory.  It returns a pointer to
+ * that descriptor. */
 static struct lguest_device_desc *new_dev_desc(u16 type)
 {
-	struct lguest_device_desc *d;
+	struct lguest_device_desc d = { .type = type };
+	void *p;
+
+	/* Figure out where the next device config is, based on the last one. */
+	if (devices.lastdev)
+		p = device_config(devices.lastdev)
+			+ devices.lastdev->desc->config_len;
+	else
+		p = devices.descpage;
 
 	/* We only have one page for all the descriptors. */
-	if (devices.desc_used + sizeof(*d) > getpagesize())
+	if (p + sizeof(d) > (void *)devices.descpage + getpagesize())
 		errx(1, "Too many devices");
 
-	/* We don't need to set config_len or status: page is 0 already. */
-	d = (void *)devices.descpage + devices.desc_used;
-	d->type = type;
-	devices.desc_used += sizeof(*d);
-
-	return d;
+	/* p might not be aligned, so we memcpy in. */
+	return memcpy(p, &d, sizeof(d));
 }
 
-/* Each device descriptor is followed by some configuration information.
- * Each configuration field looks like: u8 type, u8 len, [... len bytes...].
- *
- * This routine adds a new field to an existing device's descriptor.  It only
- * works for the last device, but that's OK because that's how we use it. */
-static void add_desc_field(struct device *dev, u8 type, u8 len, const void *c)
-{
-	/* This is the last descriptor, right? */
-	assert(devices.descpage + devices.desc_used
-	       == (u8 *)(dev->desc + 1) + dev->desc->config_len);
-
-	/* We only have one page of device descriptions. */
-	if (devices.desc_used + 2 + len > getpagesize())
-		errx(1, "Too many devices");
-
-	/* Copy in the new config header: type then length. */
-	devices.descpage[devices.desc_used++] = type;
-	devices.descpage[devices.desc_used++] = len;
-	memcpy(devices.descpage + devices.desc_used, c, len);
-	devices.desc_used += len;
-
-	/* Update the device descriptor length: two byte head then data. */
-	dev->desc->config_len += 2 + len;
-}
-
-/* This routine adds a virtqueue to a device.  We specify how many descriptors
- * the virtqueue is to have. */
+/* Each device descriptor is followed by the description of its virtqueues.  We
+ * specify how many descriptors the virtqueue is to have. */
 static void add_virtqueue(struct device *dev, unsigned int num_descs,
 			  void (*handle_output)(int fd, struct virtqueue *me))
 {
@@ -1059,9 +1049,15 @@
 	/* Initialize the vring. */
 	vring_init(&vq->vring, num_descs, p, getpagesize());
 
-	/* Add the configuration information to this device's descriptor. */
-	add_desc_field(dev, VIRTIO_CONFIG_F_VIRTQUEUE,
-		       sizeof(vq->config), &vq->config);
+	/* Append virtqueue to this device's descriptor.  We use
+	 * device_config() to get the end of the device's current virtqueues;
+	 * we check that we haven't added any config or feature information
+	 * yet, otherwise we'd be overwriting them. */
+	assert(dev->desc->config_len == 0 && dev->desc->feature_len == 0);
+	memcpy(device_config(dev), &vq->config, sizeof(vq->config));
+	dev->desc->num_vq++;
+
+	verbose("Virtqueue page %#lx\n", to_guest_phys(p));
 
 	/* Add to tail of list, so dev->vq is first vq, dev->vq->next is
 	 * second.  */
@@ -1077,6 +1073,37 @@
 		vq->vring.used->flags = VRING_USED_F_NO_NOTIFY;
 }
 
+/* The virtqueue descriptors are followed by feature bytes. */
+static void add_feature(struct device *dev, unsigned bit)
+{
+	u8 *features;
+
+	/* We can't extend the feature bits once we've added config bytes */
+	if (dev->desc->feature_len <= bit / CHAR_BIT) {
+		assert(dev->desc->config_len == 0);
+		dev->desc->feature_len = (bit / CHAR_BIT) + 1;
+	}
+
+	features = (u8 *)(dev->desc + 1)
+		+ dev->desc->num_vq * sizeof(struct lguest_vqconfig);
+
+	features[bit / CHAR_BIT] |= (1 << (bit % CHAR_BIT));
+}
+
+/* This routine sets the configuration fields for an existing device's
+ * descriptor.  It only works for the last device, but that's OK because that's
+ * how we use it. */
+static void set_config(struct device *dev, unsigned len, const void *conf)
+{
+	/* Check we haven't overflowed our single page. */
+	if (device_config(dev) + len > devices.descpage + getpagesize())
+		errx(1, "Too many devices");
+
+	/* Copy in the config information, and store the length. */
+	memcpy(device_config(dev), conf, len);
+	dev->desc->config_len = len;
+}
+
 /* This routine does all the creation and setup of a new device, including
  * calling new_dev_desc() to allocate the descriptor and device memory. */
 static struct device *new_device(const char *name, u16 type, int fd,
@@ -1084,14 +1111,6 @@
 {
 	struct device *dev = malloc(sizeof(*dev));
 
-	/* Append to device list.  Prepending to a single-linked list is
-	 * easier, but the user expects the devices to be arranged on the bus
-	 * in command-line order.  The first network device on the command line
-	 * is eth0, the first block device /dev/vda, etc. */
-	*devices.lastdev = dev;
-	dev->next = NULL;
-	devices.lastdev = &dev->next;
-
 	/* Now we populate the fields one at a time. */
 	dev->fd = fd;
 	/* If we have an input handler for this file descriptor, then we add it
@@ -1102,6 +1121,17 @@
 	dev->handle_input = handle_input;
 	dev->name = name;
 	dev->vq = 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
+	 * in command-line order.  The first network device on the command line
+	 * is eth0, the first block device /dev/vda, etc. */
+	if (devices.lastdev)
+		devices.lastdev->next = dev;
+	else
+		devices.dev = dev;
+	devices.lastdev = dev;
+
 	return dev;
 }
 
@@ -1226,7 +1256,7 @@
 	int netfd, ipfd;
 	u32 ip;
 	const char *br_name = NULL;
-	u8 hwaddr[6];
+	struct virtio_net_config conf;
 
 	/* We open the /dev/net/tun device and tell it we want a tap device.  A
 	 * tap device is like a tun device, only somehow different.  To tell
@@ -1265,12 +1295,13 @@
 		ip = str2ip(arg);
 
 	/* Set up the tun device, and get the mac address for the interface. */
-	configure_device(ipfd, ifr.ifr_name, ip, hwaddr);
+	configure_device(ipfd, ifr.ifr_name, ip, conf.mac);
 
 	/* Tell Guest what MAC address to use. */
-	add_desc_field(dev, VIRTIO_CONFIG_NET_MAC_F, sizeof(hwaddr), hwaddr);
+	add_feature(dev, VIRTIO_NET_F_MAC);
+	set_config(dev, sizeof(conf), &conf);
 
-	/* We don't seed the socket any more; setup is done. */
+	/* We don't need the socket any more; setup is done. */
 	close(ipfd);
 
 	verbose("device %u: tun net %u.%u.%u.%u\n",
@@ -1458,8 +1489,7 @@
 	struct device *dev;
 	struct vblk_info *vblk;
 	void *stack;
-	u64 cap;
-	unsigned int val;
+	struct virtio_blk_config conf;
 
 	/* This is the pipe the I/O thread will use to tell us I/O is done. */
 	pipe(p);
@@ -1477,14 +1507,18 @@
 	vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE);
 	vblk->len = lseek64(vblk->fd, 0, SEEK_END);
 
+	/* We support barriers. */
+	add_feature(dev, VIRTIO_BLK_F_BARRIER);
+
 	/* Tell Guest how many sectors this device has. */
-	cap = cpu_to_le64(vblk->len / 512);
-	add_desc_field(dev, VIRTIO_CONFIG_BLK_F_CAPACITY, sizeof(cap), &cap);
+	conf.capacity = cpu_to_le64(vblk->len / 512);
 
 	/* Tell Guest not to put in too many descriptors at once: two are used
 	 * for the in and out elements. */
-	val = cpu_to_le32(VIRTQUEUE_NUM - 2);
-	add_desc_field(dev, VIRTIO_CONFIG_BLK_F_SEG_MAX, sizeof(val), &val);
+	add_feature(dev, VIRTIO_BLK_F_SEG_MAX);
+	conf.seg_max = cpu_to_le32(VIRTQUEUE_NUM - 2);
+
+	set_config(dev, sizeof(conf), &conf);
 
 	/* The I/O thread writes to this end of the pipe when done. */
 	vblk->done_fd = p[1];
@@ -1505,7 +1539,7 @@
 	close(vblk->workpipe[0]);
 
 	verbose("device %u: virtblock %llu sectors\n",
-		devices.device_num, cap);
+		devices.device_num, le64_to_cpu(conf.capacity));
 }
 /* That's the end of device setup. :*/
 
@@ -1610,12 +1644,12 @@
 	/* First we initialize the device list.  Since console and network
 	 * device receive input from a file descriptor, we keep an fdset
 	 * (infds) and the maximum fd number (max_infd) with the head of the
-	 * list.  We also keep a pointer to the last device, for easy appending
-	 * to the list.  Finally, we keep the next interrupt number to hand out
-	 * (1: remember that 0 is used by the timer). */
+	 * list.  We also keep a pointer to the last device.  Finally, we keep
+	 * the next interrupt number to hand out (1: remember that 0 is used by
+	 * the timer). */
 	FD_ZERO(&devices.infds);
 	devices.max_infd = -1;
-	devices.lastdev = &devices.dev;
+	devices.lastdev = NULL;
 	devices.next_irq = 1;
 
 	cpu_id = 0;