All of lore.kernel.org
 help / color / mirror / Atom feed
From: john cooper <john.cooper@redhat.com>
To: KVM list <kvm@vger.kernel.org>, qemu-devel@nongnu.org
Cc: Rusty Russell <rusty@rustcorp.com.au>,
	Christoph Hellwig <hch@lst.de>,
	john.cooper@redhat.com
Subject: Re: [PATCH 1/2] Add serial number support for virtio_blk, V4a
Date: Wed, 03 Jun 2009 17:07:04 -0400	[thread overview]
Message-ID: <4A26E5F8.1040803@redhat.com> (raw)
In-Reply-To: <4A1F6130.9070705@redhat.com>

This patch implements the missing qemu logic to
interpret a '-drive .. serial=XYZ ..' flag for
a virtio_blk device.

The serial number string is contained in a
skeletal IDENTIFY DEVICE data structure and
this structure is made available to the guest
virtio_blk driver via pci i/o region 0.

Signed-off-by: john cooper <john.cooper@redhat.com>
---

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 8dd3c7a..0b7ebe9 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -25,6 +25,7 @@ typedef struct VirtIOBlock
     BlockDriverState *bs;
     VirtQueue *vq;
     void *rq;
+    char serial_str[BLOCK_SERIAL_STRLEN + 1];
 } VirtIOBlock;
 
 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
@@ -285,6 +286,50 @@ static void virtio_blk_reset(VirtIODevice *vdev)
     qemu_aio_flush();
 }
 
+/* store identify data in little endian format
+ */
+static inline void put_le16(uint16_t *p, unsigned int v)
+{
+    *p = cpu_to_le16(v);
+}
+
+/* copy to *dst from *src, nul pad dst tail as needed to len bytes
+ */
+static inline void padstr(char *dst, const char *src, int len)
+{
+    while (len--)
+        *dst++ = *src ? *src++ : '\0';
+}
+
+/* setup simulated identify data as appropriate for virtio block device
+ *
+ * ref: AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
+ */
+static inline void virtio_identify_template(struct virtio_blk_config *bc)
+{
+    uint16_t *p = &bc->identify[0];
+    uint64_t lba_sectors = bc->capacity;
+
+    memset(p, 0, sizeof(bc->identify));
+    put_le16(p + 0, 0x0);                            /* ATA device */
+    padstr((char *)(p + 23), QEMU_VERSION, 8);       /* firmware revision */
+    padstr((char *)(p + 27), "QEMU VIRT_BLK", 40);   /* model# */
+    put_le16(p + 47, 0x80ff);                        /* max xfer 255 sectors */
+    put_le16(p + 49, 0x0b00);                        /* support IORDY/LBA/DMA */
+    put_le16(p + 59, 0x1ff);                         /* cur xfer 255 sectors */
+    put_le16(p + 80, 0x1f0);                         /* support ATA8/7/6/5/4 */
+    put_le16(p + 81, 0x16);
+    put_le16(p + 82, 0x400);
+    put_le16(p + 83, 0x400);
+    put_le16(p + 100, lba_sectors);
+    put_le16(p + 101, lba_sectors >> 16);
+    put_le16(p + 102, lba_sectors >> 32);
+    put_le16(p + 103, lba_sectors >> 48);
+}
+
+/* coalesce internal state, copy to pci i/o region 0
+ */
+
 static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 {
     VirtIOBlock *s = to_virtio_blk(vdev);
@@ -299,11 +344,15 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     stw_raw(&blkcfg.cylinders, cylinders);
     blkcfg.heads = heads;
     blkcfg.sectors = secs;
+    virtio_identify_template(&blkcfg);
+    memcpy(&blkcfg.identify[VIRTIO_BLK_ID_SN], s->serial_str,
+        VIRTIO_BLK_ID_SN_BYTES);
     memcpy(config, &blkcfg, sizeof(blkcfg));
 }
 
 static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
 {
+    VirtIOBlock *s = to_virtio_blk(vdev);
     uint32_t features = 0;
 
     features |= (1 << VIRTIO_BLK_F_SEG_MAX);
@@ -311,6 +360,8 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
 #ifdef __linux__
     features |= (1 << VIRTIO_BLK_F_SCSI);
 #endif
+    if (strcmp(s->serial_str, "0"))
+        features |= 1 << VIRTIO_BLK_F_IDENTIFY;
 
     return features;
 }
@@ -354,6 +405,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev)
     int cylinders, heads, secs;
     static int virtio_blk_id;
     BlockDriverState *bs;
+    char *ps;
 
     s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
                                           sizeof(struct virtio_blk_config),
@@ -365,6 +417,10 @@ VirtIODevice *virtio_blk_init(DeviceState *dev)
     s->vdev.reset = virtio_blk_reset;
     s->bs = bs;
     s->rq = NULL;
+    if (strlen(ps = (char *)drive_get_serial(bs)))
+        strncpy(s->serial_str, ps, sizeof(s->serial_str));
+    else
+        snprintf(s->serial_str, sizeof(s->serial_str), "0");
     bs->private = dev;
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
     bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index dff3e0c..1be4342 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -30,6 +30,11 @@
 #define VIRTIO_BLK_F_RO         5       /* Disk is read-only */
 #define VIRTIO_BLK_F_BLK_SIZE   6       /* Block size of disk is available*/
 #define VIRTIO_BLK_F_SCSI       7       /* Supports scsi command passthru */
+#define VIRTIO_BLK_F_IDENTIFY   8       /* ATA IDENTIFY supported */
+
+#define VIRTIO_BLK_ID_LEN       256     /* length of identify u16 array */
+#define VIRTIO_BLK_ID_SN        10      /* start of char * serial# */
+#define VIRTIO_BLK_ID_SN_BYTES  20      /* length in bytes of serial# */
 
 struct virtio_blk_config
 {
@@ -39,6 +44,8 @@ struct virtio_blk_config
     uint16_t cylinders;
     uint8_t heads;
     uint8_t sectors;
+    uint32_t _blk_size;    /* structure pad, currently unused */
+    uint16_t identify[VIRTIO_BLK_ID_LEN];
 } __attribute__((packed));
 
 /* These two define direction. */
diff --git a/sysemu.h b/sysemu.h
index 47d001e..d3df19f 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -152,6 +152,8 @@ typedef enum {
     BLOCK_ERR_STOP_ANY
 } BlockInterfaceErrorAction;
 
+#define BLOCK_SERIAL_STRLEN 20
+
 typedef struct DriveInfo {
     BlockDriverState *bdrv;
     BlockInterfaceType type;
@@ -160,7 +162,7 @@ typedef struct DriveInfo {
     int used;
     int drive_opt_idx;
     BlockInterfaceErrorAction onerror;
-    char serial[21];
+    char serial[BLOCK_SERIAL_STRLEN + 1];
 } DriveInfo;
 
 #define MAX_IDE_DEVS	2

-- 
john.cooper@redhat.com


WARNING: multiple messages have this Message-ID (diff)
From: john cooper <john.cooper@redhat.com>
To: KVM list <kvm@vger.kernel.org>, qemu-devel@nongnu.org
Cc: john.cooper@redhat.com, Rusty Russell <rusty@rustcorp.com.au>,
	Christoph Hellwig <hch@lst.de>
Subject: [Qemu-devel] Re: [PATCH 1/2] Add serial number support for virtio_blk, V4a
Date: Wed, 03 Jun 2009 17:07:04 -0400	[thread overview]
Message-ID: <4A26E5F8.1040803@redhat.com> (raw)
In-Reply-To: <4A1F6130.9070705@redhat.com>

This patch implements the missing qemu logic to
interpret a '-drive .. serial=XYZ ..' flag for
a virtio_blk device.

The serial number string is contained in a
skeletal IDENTIFY DEVICE data structure and
this structure is made available to the guest
virtio_blk driver via pci i/o region 0.

Signed-off-by: john cooper <john.cooper@redhat.com>
---

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 8dd3c7a..0b7ebe9 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -25,6 +25,7 @@ typedef struct VirtIOBlock
     BlockDriverState *bs;
     VirtQueue *vq;
     void *rq;
+    char serial_str[BLOCK_SERIAL_STRLEN + 1];
 } VirtIOBlock;
 
 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
@@ -285,6 +286,50 @@ static void virtio_blk_reset(VirtIODevice *vdev)
     qemu_aio_flush();
 }
 
+/* store identify data in little endian format
+ */
+static inline void put_le16(uint16_t *p, unsigned int v)
+{
+    *p = cpu_to_le16(v);
+}
+
+/* copy to *dst from *src, nul pad dst tail as needed to len bytes
+ */
+static inline void padstr(char *dst, const char *src, int len)
+{
+    while (len--)
+        *dst++ = *src ? *src++ : '\0';
+}
+
+/* setup simulated identify data as appropriate for virtio block device
+ *
+ * ref: AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
+ */
+static inline void virtio_identify_template(struct virtio_blk_config *bc)
+{
+    uint16_t *p = &bc->identify[0];
+    uint64_t lba_sectors = bc->capacity;
+
+    memset(p, 0, sizeof(bc->identify));
+    put_le16(p + 0, 0x0);                            /* ATA device */
+    padstr((char *)(p + 23), QEMU_VERSION, 8);       /* firmware revision */
+    padstr((char *)(p + 27), "QEMU VIRT_BLK", 40);   /* model# */
+    put_le16(p + 47, 0x80ff);                        /* max xfer 255 sectors */
+    put_le16(p + 49, 0x0b00);                        /* support IORDY/LBA/DMA */
+    put_le16(p + 59, 0x1ff);                         /* cur xfer 255 sectors */
+    put_le16(p + 80, 0x1f0);                         /* support ATA8/7/6/5/4 */
+    put_le16(p + 81, 0x16);
+    put_le16(p + 82, 0x400);
+    put_le16(p + 83, 0x400);
+    put_le16(p + 100, lba_sectors);
+    put_le16(p + 101, lba_sectors >> 16);
+    put_le16(p + 102, lba_sectors >> 32);
+    put_le16(p + 103, lba_sectors >> 48);
+}
+
+/* coalesce internal state, copy to pci i/o region 0
+ */
+
 static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 {
     VirtIOBlock *s = to_virtio_blk(vdev);
@@ -299,11 +344,15 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     stw_raw(&blkcfg.cylinders, cylinders);
     blkcfg.heads = heads;
     blkcfg.sectors = secs;
+    virtio_identify_template(&blkcfg);
+    memcpy(&blkcfg.identify[VIRTIO_BLK_ID_SN], s->serial_str,
+        VIRTIO_BLK_ID_SN_BYTES);
     memcpy(config, &blkcfg, sizeof(blkcfg));
 }
 
 static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
 {
+    VirtIOBlock *s = to_virtio_blk(vdev);
     uint32_t features = 0;
 
     features |= (1 << VIRTIO_BLK_F_SEG_MAX);
@@ -311,6 +360,8 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
 #ifdef __linux__
     features |= (1 << VIRTIO_BLK_F_SCSI);
 #endif
+    if (strcmp(s->serial_str, "0"))
+        features |= 1 << VIRTIO_BLK_F_IDENTIFY;
 
     return features;
 }
@@ -354,6 +405,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev)
     int cylinders, heads, secs;
     static int virtio_blk_id;
     BlockDriverState *bs;
+    char *ps;
 
     s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
                                           sizeof(struct virtio_blk_config),
@@ -365,6 +417,10 @@ VirtIODevice *virtio_blk_init(DeviceState *dev)
     s->vdev.reset = virtio_blk_reset;
     s->bs = bs;
     s->rq = NULL;
+    if (strlen(ps = (char *)drive_get_serial(bs)))
+        strncpy(s->serial_str, ps, sizeof(s->serial_str));
+    else
+        snprintf(s->serial_str, sizeof(s->serial_str), "0");
     bs->private = dev;
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
     bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index dff3e0c..1be4342 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -30,6 +30,11 @@
 #define VIRTIO_BLK_F_RO         5       /* Disk is read-only */
 #define VIRTIO_BLK_F_BLK_SIZE   6       /* Block size of disk is available*/
 #define VIRTIO_BLK_F_SCSI       7       /* Supports scsi command passthru */
+#define VIRTIO_BLK_F_IDENTIFY   8       /* ATA IDENTIFY supported */
+
+#define VIRTIO_BLK_ID_LEN       256     /* length of identify u16 array */
+#define VIRTIO_BLK_ID_SN        10      /* start of char * serial# */
+#define VIRTIO_BLK_ID_SN_BYTES  20      /* length in bytes of serial# */
 
 struct virtio_blk_config
 {
@@ -39,6 +44,8 @@ struct virtio_blk_config
     uint16_t cylinders;
     uint8_t heads;
     uint8_t sectors;
+    uint32_t _blk_size;    /* structure pad, currently unused */
+    uint16_t identify[VIRTIO_BLK_ID_LEN];
 } __attribute__((packed));
 
 /* These two define direction. */
diff --git a/sysemu.h b/sysemu.h
index 47d001e..d3df19f 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -152,6 +152,8 @@ typedef enum {
     BLOCK_ERR_STOP_ANY
 } BlockInterfaceErrorAction;
 
+#define BLOCK_SERIAL_STRLEN 20
+
 typedef struct DriveInfo {
     BlockDriverState *bdrv;
     BlockInterfaceType type;
@@ -160,7 +162,7 @@ typedef struct DriveInfo {
     int used;
     int drive_opt_idx;
     BlockInterfaceErrorAction onerror;
-    char serial[21];
+    char serial[BLOCK_SERIAL_STRLEN + 1];
 } DriveInfo;
 
 #define MAX_IDE_DEVS	2

-- 
john.cooper@redhat.com

  parent reply	other threads:[~2009-06-03 21:11 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-29  4:14 [PATCH 0/2] Add serial number support for virtio_blk, V4 john cooper
2009-05-29  4:14 ` [Qemu-devel] " john cooper
2009-06-03 21:06 ` [PATCH 0/2] Add serial number support for virtio_blk, V4a john cooper
2009-06-03 21:06   ` [Qemu-devel] " john cooper
2009-06-03 21:07 ` john cooper [this message]
2009-06-03 21:07   ` [Qemu-devel] Re: [PATCH 1/2] " john cooper
2009-06-03 21:07 ` [PATCH 2/2] " john cooper
2009-06-03 21:07   ` [Qemu-devel] " john cooper
2009-06-04  6:31   ` Rusty Russell
2009-06-04  6:31     ` [Qemu-devel] " Rusty Russell
2009-06-09 12:19   ` [PATCH] " Rusty Russell
2009-06-09 12:19     ` [Qemu-devel] " Rusty Russell
2009-06-09 12:42     ` Jens Axboe
2009-06-09 12:42       ` [Qemu-devel] " Jens Axboe
2009-06-09 12:21   ` [PATCH 2/2] " Rusty Russell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A26E5F8.1040803@redhat.com \
    --to=john.cooper@redhat.com \
    --cc=hch@lst.de \
    --cc=kvm@vger.kernel.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rusty@rustcorp.com.au \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.