All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cornelia Huck <cornelia.huck@de.ibm.com>
To: qemu-devel@nongnu.org
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>,
	borntraeger@de.ibm.com, jfrei@linux.vnet.ibm.com, agraf@suse.de,
	"Eugene (jno) Dvurechenski" <jno@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH for-2.6 05/14] pc-bios/s390-ccw: update virtio implementation to allow up to 3 vrings
Date: Fri, 18 Mar 2016 15:21:26 +0100	[thread overview]
Message-ID: <1458310895-29044-6-git-send-email-cornelia.huck@de.ibm.com> (raw)
In-Reply-To: <1458310895-29044-1-git-send-email-cornelia.huck@de.ibm.com>

From: "Eugene (jno) Dvurechenski" <jno@linux.vnet.ibm.com>

Add ability to work with up to 3 vrings, which is required for
virtio-scsi implementation.
Implement the optional cookie to speed up processing of virtio
notifications.

Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Eugene (jno) Dvurechenski <jno@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 pc-bios/s390-ccw/main.c     |   1 -
 pc-bios/s390-ccw/s390-ccw.h |   1 -
 pc-bios/s390-ccw/virtio.c   | 140 +++++++++++++++++++++++++++-----------------
 pc-bios/s390-ccw/virtio.h   |   4 ++
 4 files changed, 90 insertions(+), 56 deletions(-)

diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 7f192f3..6bf44a7 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -12,7 +12,6 @@
 #include "virtio.h"
 
 char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
-char ring_area[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
 uint64_t boot_value;
 static SubChannelId blk_schid = { .one = 1 };
 
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index a5c0684..3e00d42 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -61,7 +61,6 @@ void consume_sclp_int(void);
 void panic(const char *string);
 void write_subsystem_identification(void);
 extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
-extern char ring_area[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
 extern uint64_t boot_value;
 
 /* sclp-ascii.c */
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 64c6e07..d366aa3 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -11,29 +11,35 @@
 #include "s390-ccw.h"
 #include "virtio.h"
 
-static VRing block;
+static VRing block[VIRTIO_MAX_VQS];
+static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS]
+                     __attribute__((__aligned__(PAGE_SIZE)));
+static int nr_vqs = 1;
 
 static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
 
+/* virtio spec v1.0 para 4.3.3.2 */
 static long kvm_hypercall(unsigned long nr, unsigned long param1,
-                          unsigned long param2)
+                          unsigned long param2, unsigned long param3)
 {
     register ulong r_nr asm("1") = nr;
     register ulong r_param1 asm("2") = param1;
     register ulong r_param2 asm("3") = param2;
+    register ulong r_param3 asm("4") = param3;
     register long retval asm("2");
 
     asm volatile ("diag 2,4,0x500"
                   : "=d" (retval)
-                  : "d" (r_nr), "0" (r_param1), "r"(r_param2)
+                  : "d" (r_nr), "0" (r_param1), "r"(r_param2), "d"(r_param3)
                   : "memory", "cc");
 
     return retval;
 }
 
-static void virtio_notify(SubChannelId schid)
+static long virtio_notify(SubChannelId schid, int vq_idx, long cookie)
 {
-    kvm_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, *(u32 *)&schid, 0);
+    return kvm_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, *(u32 *)&schid,
+                         vq_idx, cookie);
 }
 
 /***********************************************
@@ -106,15 +112,17 @@ static void virtio_reset(SubChannelId schid)
     run_ccw(schid, CCW_CMD_VDEV_RESET, NULL, 0);
 }
 
-static void vring_init(VRing *vr, unsigned int num, void *p,
-                       unsigned long align)
+static void vring_init(VRing *vr, VqInfo *info)
 {
+    void *p = (void *) info->queue;
+
     debug_print_addr("init p", p);
-    vr->num = num;
+    vr->id = info->index;
+    vr->num = info->num;
     vr->desc = p;
-    vr->avail = p + num * sizeof(VRingDesc);
-    vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1)
-                & ~(align - 1));
+    vr->avail = p + info->num * sizeof(VRingDesc);
+    vr->used = (void *)(((unsigned long)&vr->avail->ring[info->num]
+               + info->align - 1) & ~(info->align - 1));
 
     /* Zero out all relevant field */
     vr->avail->flags = 0;
@@ -125,13 +133,15 @@ static void vring_init(VRing *vr, unsigned int num, void *p,
     vr->used->idx = 0;
     vr->used_idx = 0;
     vr->next_idx = 0;
+    vr->cookie = 0;
 
     debug_print_addr("init vr", vr);
 }
 
-static void vring_notify(SubChannelId schid)
+static bool vring_notify(VRing *vr)
 {
-    virtio_notify(schid);
+    vr->cookie = virtio_notify(vr->schid, vr->id, vr->cookie);
+    return vr->cookie >= 0;
 }
 
 static void vring_send_buf(VRing *vr, void *p, int len, int flags)
@@ -167,6 +177,21 @@ ulong get_second(void)
     return (get_clock() >> 12) / 1000000;
 }
 
+static int vr_poll(VRing *vr)
+{
+    if (vr->used->idx == vr->used_idx) {
+        vring_notify(vr);
+        yield();
+        return 0;
+    }
+
+    vr->used_idx = vr->used->idx;
+    vr->next_idx = 0;
+    vr->desc[0].len = 0;
+    vr->desc[0].flags = 0;
+    return 1; /* vr has been updated */
+}
+
 /*
  * Wait for the host to reply.
  *
@@ -174,28 +199,24 @@ ulong get_second(void)
  *
  * Returns 0 on success, 1 on timeout.
  */
-static int vring_wait_reply(VRing *vr, int timeout)
+static int vring_wait_reply(int timeout)
 {
     ulong target_second = get_second() + timeout;
-    SubChannelId schid = vr->schid;
-    int r = 0;
 
-    /* Wait until the used index has moved. */
-    while (vr->used->idx == vr->used_idx) {
-        vring_notify(schid);
-        if (timeout && (get_second() >= target_second)) {
-            r = 1;
-            break;
+    /* Wait for any queue to be updated by the host */
+    do {
+        int i, r = 0;
+
+        for (i = 0; i < nr_vqs; i++) {
+            r += vr_poll(&block[i]);
         }
         yield();
-    }
-
-    vr->used_idx = vr->used->idx;
-    vr->next_idx = 0;
-    vr->desc[0].len = 0;
-    vr->desc[0].flags = 0;
+        if (r) {
+            return 0;
+        }
+    } while (!timeout || (get_second() < target_second));
 
-    return r;
+    return 1;
 }
 
 /***********************************************
@@ -213,21 +234,21 @@ int virtio_read_many(ulong sector, void *load_addr, int sec_num)
     out_hdr.ioprio = 99;
     out_hdr.sector = virtio_sector_adjust(sector);
 
-    vring_send_buf(&block, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
+    vring_send_buf(&block[0], &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
 
     /* This is where we want to receive data */
-    vring_send_buf(&block, load_addr, virtio_get_block_size() * sec_num,
+    vring_send_buf(&block[0], load_addr, virtio_get_block_size() * sec_num,
                    VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
                    VRING_DESC_F_NEXT);
 
     /* status field */
-    vring_send_buf(&block, &status, sizeof(u8), VRING_DESC_F_WRITE |
+    vring_send_buf(&block[0], &status, sizeof(u8), VRING_DESC_F_WRITE |
                    VRING_HIDDEN_IS_CHAIN);
 
     /* Now we can tell the host to read */
-    vring_wait_reply(&block, 0);
+    vring_wait_reply(0);
 
-    r = drain_irqs(block.schid);
+    r = drain_irqs(block[0].schid);
     if (r) {
         /* Well, whatever status is supposed to contain... */
         status = 1;
@@ -363,15 +384,18 @@ uint64_t virtio_get_blocks(void)
            (virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
 }
 
-void virtio_setup_block(SubChannelId schid)
+static void virtio_setup_ccw(SubChannelId schid,
+                             int nvr, void *cfg, int cfg_size)
 {
-    VqInfo info;
-    VqConfig config = {};
+    int i;
 
     blk_cfg.blk_size = 0; /* mark "illegal" - setup started... */
+    nr_vqs = nvr;
     guessed_disk_nature = false;
 
     virtio_reset(schid);
+    IPL_assert(run_ccw(schid, CCW_CMD_READ_CONF, cfg, cfg_size) == 0,
+               "Could not get block device configuration");
 
     /*
      * Skipping CCW_CMD_READ_FEAT. We're not doing anything fancy, and
@@ -379,25 +403,33 @@ void virtio_setup_block(SubChannelId schid)
      * expect it.
      */
 
-    config.index = 0;
-    if (run_ccw(schid, CCW_CMD_READ_VQ_CONF, &config, sizeof(config))) {
-        panic("Could not get block device VQ configuration\n");
-    }
-    if (run_ccw(schid, CCW_CMD_READ_CONF, &blk_cfg, sizeof(blk_cfg))) {
-        panic("Could not get block device configuration\n");
+    for (i = 0; i < nr_vqs; i++) {
+        VqInfo info = {
+            .queue = (unsigned long long) ring_area + (i * VIRTIO_RING_SIZE),
+            .align = KVM_S390_VIRTIO_RING_ALIGN,
+            .index = i,
+            .num = 0,
+        };
+        VqConfig config = {
+            .index = i,
+            .num = 0,
+        };
+
+        IPL_assert(
+            run_ccw(schid, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0,
+            "Could not get block device VQ configuration");
+        info.num = config.num;
+        vring_init(&block[i], &info);
+        block[i].schid = schid;
+        IPL_assert(run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0,
+                   "Cannot set VQ info");
     }
-    vring_init(&block, config.num, ring_area,
-               KVM_S390_VIRTIO_RING_ALIGN);
-
-    info.queue = (unsigned long long) ring_area;
-    info.align = KVM_S390_VIRTIO_RING_ALIGN;
-    info.index = 0;
-    info.num = config.num;
-    block.schid = schid;
+    virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
+}
 
-    if (!run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info))) {
-        virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
-    }
+void virtio_setup_block(SubChannelId schid)
+{
+    virtio_setup_ccw(schid, 1, &blk_cfg, sizeof(blk_cfg));
 
     if (!virtio_ipl_disk_is_valid()) {
         /* make sure all getters but blocksize return 0 for invalid IPL disk */
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index af6e142..d17b135 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -72,6 +72,8 @@ struct VirtioDev {
 };
 typedef struct VirtioDev VirtioDev;
 
+#define VIRTIO_RING_SIZE            (PAGE_SIZE * 8)
+#define VIRTIO_MAX_VQS              3
 #define KVM_S390_VIRTIO_RING_ALIGN  4096
 
 #define VRING_USED_F_NO_NOTIFY  1
@@ -130,6 +132,8 @@ struct VRing {
     VRingAvail *avail;
     VRingUsed *used;
     SubChannelId schid;
+    long cookie;
+    int id;
 };
 typedef struct VRing VRing;
 
-- 
2.7.4

  parent reply	other threads:[~2016-03-18 14:21 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-18 14:21 [Qemu-devel] [PATCH for-2.6 00/14] s390-ccw bios patches Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 01/14] pc-bios/s390-ccw: add more disk layout checks Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 02/14] pc-bios/s390-ccw: virtio_panic -> panic Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 03/14] pc-bios/s390-ccw: add utility functions and "export" some others Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 04/14] pc-bios/s390-ccw: qemuize types Cornelia Huck
2016-03-18 14:21 ` Cornelia Huck [this message]
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 06/14] pc-bios/s390-ccw: add vdev object to store all device details Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 07/14] pc-bios/s390-ccw: make provisions for different backends Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 08/14] pc-bios/s390-ccw: add simplified virtio call Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 09/14] pc-bios/s390-ccw: add scsi definitions Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 10/14] pc-bios/s390-ccw: add virtio-scsi implementation Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 11/14] pc-bios/s390-ccw: enable virtio-scsi Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 12/14] pc-bios/s390-ccw: enhance bootmap detection Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 13/14] pc-bios/s390-ccw: disambiguation of "No zIPL magic" message Cornelia Huck
2016-03-18 14:21 ` [Qemu-devel] [PATCH for-2.6 14/14] s390-ccw.img: rebuild image Cornelia Huck
2016-03-23  9:07 ` [Qemu-devel] [PATCH for-2.6 00/14] s390-ccw bios patches Christian Borntraeger

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=1458310895-29044-6-git-send-email-cornelia.huck@de.ibm.com \
    --to=cornelia.huck@de.ibm.com \
    --cc=agraf@suse.de \
    --cc=borntraeger@de.ibm.com \
    --cc=jfrei@linux.vnet.ibm.com \
    --cc=jno@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /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.