qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Jens Freimann <jfrei@linux.vnet.ibm.com>
To: Christian Borntraeger <borntraeger@de.ibm.com>,
	Alexander Graf <agraf@suse.de>,
	Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: "Eugene (jno) Dvurechenski" <jno@linux.vnet.ibm.com>,
	Jens Freimann <jfrei@linux.vnet.ibm.com>,
	qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 03/10] pc-bios/s390-ccw: handle different sector sizes
Date: Thu, 26 Jun 2014 16:30:02 +0200	[thread overview]
Message-ID: <1403793009-54176-4-git-send-email-jfrei@linux.vnet.ibm.com> (raw)
In-Reply-To: <1403793009-54176-1-git-send-email-jfrei@linux.vnet.ibm.com>

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

Use the virtio device's configuration to figure out the disk geometry
and use a sector size based upon the layout.

Signed-off-by: Eugene (jno) Dvurechenski <jno@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
---
 pc-bios/s390-ccw/bootmap.c  |  3 +-
 pc-bios/s390-ccw/s390-ccw.h |  2 +-
 pc-bios/s390-ccw/virtio.c   | 96 ++++++++++++++++++++++++++++++++++++++++++---
 pc-bios/s390-ccw/virtio.h   | 48 +++++++++++++++++++++++
 4 files changed, 142 insertions(+), 7 deletions(-)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index c216030..79db3c3 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -10,6 +10,7 @@
 
 #include "s390-ccw.h"
 #include "bootmap.h"
+#include "virtio.h"
 
 /* #define DEBUG_FALLBACK */
 
@@ -238,7 +239,7 @@ int zipl_load(void)
         goto fail;
     }
 
-    ns_end = sec + SECTOR_SIZE;
+    ns_end = sec + virtio_get_block_size();
     for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns++) {
         prog_table_entry = (ScsiBlockPtr *)ns;
         if (!prog_table_entry->blockno) {
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index fe1dd22..a2bd042 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -130,6 +130,6 @@ static inline void yield(void)
                   : "memory", "cc");
 }
 
-#define SECTOR_SIZE 512
+#define SECTOR_SIZE 4096
 
 #endif /* S390_CCW_H */
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index c845b14..31b23b0 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -202,7 +202,7 @@ static int vring_wait_reply(struct vring *vr, int timeout)
  *               Virtio block                  *
  ***********************************************/
 
-static int virtio_read_many(ulong sector, void *load_addr, int sec_num)
+int virtio_read_many(ulong sector, void *load_addr, int sec_num)
 {
     struct virtio_blk_outhdr out_hdr;
     u8 status;
@@ -211,12 +211,12 @@ static int virtio_read_many(ulong sector, void *load_addr, int sec_num)
     /* Tell the host we want to read */
     out_hdr.type = VIRTIO_BLK_T_IN;
     out_hdr.ioprio = 99;
-    out_hdr.sector = sector;
+    out_hdr.sector = virtio_sector_adjust(sector);
 
     vring_send_buf(&block, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
 
     /* This is where we want to receive data */
-    vring_send_buf(&block, load_addr, SECTOR_SIZE * sec_num,
+    vring_send_buf(&block, load_addr, virtio_get_block_size() * sec_num,
                    VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
                    VRING_DESC_F_NEXT);
 
@@ -244,7 +244,7 @@ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
     int sec_len = rec_list2 >> 48;
     ulong addr = (ulong)load_addr;
 
-    if (sec_len != SECTOR_SIZE) {
+    if (sec_len != virtio_get_block_size()) {
         return -1;
     }
 
@@ -253,7 +253,7 @@ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
     if (status) {
         virtio_panic("I/O Error");
     }
-    addr += sec_num * SECTOR_SIZE;
+    addr += sec_num * virtio_get_block_size();
 
     return addr;
 }
@@ -263,15 +263,95 @@ int virtio_read(ulong sector, void *load_addr)
     return virtio_read_many(sector, load_addr, 1);
 }
 
+static VirtioBlkConfig blk_cfg = {};
+static bool guessed_disk_nature;
+
+bool virtio_guessed_disk_nature(void)
+{
+    return guessed_disk_nature;
+}
+
+void virtio_assume_scsi(void)
+{
+    guessed_disk_nature = true;
+    blk_cfg.blk_size = 512;
+}
+
+void virtio_assume_eckd(void)
+{
+    guessed_disk_nature = true;
+    blk_cfg.blk_size = 4096;
+
+    /* this must be here to calculate code segment position */
+    blk_cfg.geometry.heads = 15;
+    blk_cfg.geometry.sectors = 12;
+}
+
+bool virtio_disk_is_scsi(void)
+{
+    if (guessed_disk_nature) {
+        return (blk_cfg.blk_size  == 512);
+    }
+    return (blk_cfg.geometry.heads == 255)
+        && (blk_cfg.geometry.sectors == 63)
+        && (blk_cfg.blk_size  == 512);
+}
+
+bool virtio_disk_is_eckd(void)
+{
+    if (guessed_disk_nature) {
+        return (blk_cfg.blk_size  == 4096);
+    }
+    return (blk_cfg.geometry.heads == 15)
+        && (blk_cfg.geometry.sectors == 12)
+        && (blk_cfg.blk_size  == 4096);
+}
+
+bool virtio_ipl_disk_is_valid(void)
+{
+    return blk_cfg.blk_size && (virtio_disk_is_scsi() || virtio_disk_is_eckd());
+}
+
+int virtio_get_block_size(void)
+{
+    return blk_cfg.blk_size;
+}
+
+uint16_t virtio_get_cylinders(void)
+{
+    return blk_cfg.geometry.cylinders;
+}
+
+uint8_t virtio_get_heads(void)
+{
+    return blk_cfg.geometry.heads;
+}
+
+uint8_t virtio_get_sectors(void)
+{
+    return blk_cfg.geometry.sectors;
+}
+
 void virtio_setup_block(struct subchannel_id schid)
 {
     struct vq_info_block info;
     struct vq_config_block config = {};
 
+    blk_cfg.blk_size = 0; /* mark "illegal" - setup started... */
+
     virtio_reset(schid);
 
+    /*
+     * Skipping CCW_CMD_READ_FEAT. We're not doing anything fancy, and
+     * we'll just stop dead anyway if anything does not work like we
+     * expect it.
+     */
+
     config.index = 0;
     if (run_ccw(schid, CCW_CMD_READ_VQ_CONF, &config, sizeof(config))) {
+        virtio_panic("Could not get block device VQ configuration\n");
+    }
+    if (run_ccw(schid, CCW_CMD_READ_CONF, &blk_cfg, sizeof(blk_cfg))) {
         virtio_panic("Could not get block device configuration\n");
     }
     vring_init(&block, config.num, (void *)(100 * 1024 * 1024),
@@ -286,6 +366,12 @@ void virtio_setup_block(struct subchannel_id schid)
     if (!run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info))) {
         virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
     }
+
+    if (!virtio_ipl_disk_is_valid()) {
+        /* make sure all getters but blocksize return 0 for invalid IPL disk */
+        memset(&blk_cfg, 0, sizeof(blk_cfg));
+        virtio_assume_scsi();
+    }
 }
 
 bool virtio_is_blk(struct subchannel_id schid)
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index c2990ea..f1fb1b0 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -161,4 +161,52 @@ struct virtio_blk_outhdr {
         u64 sector;
 };
 
+typedef struct VirtioBlkConfig {
+    u64 capacity; /* in 512-byte sectors */
+    u32 size_max; /* max segment size (if VIRTIO_BLK_F_SIZE_MAX) */
+    u32 seg_max;  /* max number of segments (if VIRTIO_BLK_F_SEG_MAX) */
+
+    struct virtio_blk_geometry {
+        u16 cylinders;
+        u8 heads;
+        u8 sectors;
+    } geometry; /* (if VIRTIO_BLK_F_GEOMETRY) */
+
+    u32 blk_size; /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
+
+    /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY  */
+    u8 physical_block_exp; /* exponent for physical block per logical block */
+    u8 alignment_offset;   /* alignment offset in logical blocks */
+    u16 min_io_size;       /* min I/O size without performance penalty
+                              in logical blocks */
+    u32 opt_io_size;       /* optimal sustained I/O size in logical blocks */
+
+    u8 wce; /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
+} __attribute__((packed)) VirtioBlkConfig;
+
+bool virtio_guessed_disk_nature(void);
+void virtio_assume_scsi(void);
+void virtio_assume_eckd(void);
+
+extern bool virtio_disk_is_scsi(void);
+extern bool virtio_disk_is_eckd(void);
+extern bool virtio_ipl_disk_is_valid(void);
+extern int virtio_get_block_size(void);
+extern uint16_t virtio_get_cylinders(void);
+extern uint8_t virtio_get_heads(void);
+extern uint8_t virtio_get_sectors(void);
+extern int virtio_read_many(ulong sector, void *load_addr, int sec_num);
+
+#define VIRTIO_SECTOR_SIZE 512
+
+static inline ulong virtio_eckd_sector_adjust(ulong sector)
+{
+     return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
+}
+
+static inline ulong virtio_sector_adjust(ulong sector)
+{
+    return virtio_disk_is_eckd() ? virtio_eckd_sector_adjust(sector) : sector;
+}
+
 #endif /* VIRTIO_H */
-- 
1.8.5.5

  parent reply	other threads:[~2014-06-26 14:30 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-26 14:29 [Qemu-devel] [PATCH 00/10] pc-bios/s390-ccw: Add DASD IPL support Jens Freimann
2014-06-26 14:30 ` [Qemu-devel] [PATCH 01/10] pc-bios/s390-ccw: make checkpatch happy Jens Freimann
2014-06-26 14:30 ` [Qemu-devel] [PATCH 02/10] pc-bios/s390-ccw: cleanup and enhance bootmap defintions Jens Freimann
2014-06-26 14:30 ` Jens Freimann [this message]
2014-06-26 14:35   ` [Qemu-devel] [PATCH 03/10] pc-bios/s390-ccw: handle different sector sizes Alexander Graf
2014-06-26 15:08     ` Eugene "jno" Dvurechenski
2014-06-26 15:10       ` Alexander Graf
2014-06-26 14:30 ` [Qemu-devel] [PATCH 04/10] pc-bios/s390-ccw: add some utility code Jens Freimann
2014-06-26 14:30 ` [Qemu-devel] [PATCH 05/10] pc-bios/s390-ccw: Unify error handling Jens Freimann
2014-06-26 14:30 ` [Qemu-devel] [PATCH 06/10] pc-bios/s390-ccw: Add fill_hex_val func to provide better msgs Jens Freimann
2014-06-26 14:30 ` [Qemu-devel] [PATCH 07/10] pc-bios/s390-ccw: factor out ipl code Jens Freimann
2014-06-26 14:30 ` [Qemu-devel] [PATCH 08/10] pc-bios/s390-ccw: IPL from CDL-formatted ECKD DASD Jens Freimann
2014-06-26 14:30 ` [Qemu-devel] [PATCH 09/10] pc-bios/s390-ccw: IPL from LDL/CMS-formatted " Jens Freimann
2014-06-26 14:30 ` [Qemu-devel] [PATCH 10/10] pc-bios/s390-ccw: update binary Jens Freimann
2014-06-26 14:42 ` [Qemu-devel] [PATCH 00/10] pc-bios/s390-ccw: Add DASD IPL support Alexander Graf
2014-06-27  7:53   ` Christian Borntraeger
2014-06-27  9:05     ` Alexander Graf
2014-06-27  9:27       ` Christian Borntraeger
2014-06-27  9:47         ` Cornelia Huck

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=1403793009-54176-4-git-send-email-jfrei@linux.vnet.ibm.com \
    --to=jfrei@linux.vnet.ibm.com \
    --cc=agraf@suse.de \
    --cc=borntraeger@de.ibm.com \
    --cc=cornelia.huck@de.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).