From patchwork Thu Jun 26 14:30:02 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Freimann X-Patchwork-Id: 364567 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 993331400F0 for ; Fri, 27 Jun 2014 00:36:04 +1000 (EST) Received: from localhost ([::1]:45017 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X0AmN-0005sG-9l for incoming@patchwork.ozlabs.org; Thu, 26 Jun 2014 10:36:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50168) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X0Ah6-0006YG-At for qemu-devel@nongnu.org; Thu, 26 Jun 2014 10:30:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X0Agw-0001jq-Tf for qemu-devel@nongnu.org; Thu, 26 Jun 2014 10:30:32 -0400 Received: from e06smtp16.uk.ibm.com ([195.75.94.112]:45748) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X0Agw-0001jc-B9 for qemu-devel@nongnu.org; Thu, 26 Jun 2014 10:30:22 -0400 Received: from /spool/local by e06smtp16.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 26 Jun 2014 15:30:21 +0100 Received: from d06dlp02.portsmouth.uk.ibm.com (9.149.20.14) by e06smtp16.uk.ibm.com (192.168.101.146) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 26 Jun 2014 15:30:19 +0100 Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by d06dlp02.portsmouth.uk.ibm.com (Postfix) with ESMTP id D392C2190046 for ; Thu, 26 Jun 2014 15:30:06 +0100 (BST) Received: from d06av04.portsmouth.uk.ibm.com (d06av04.portsmouth.uk.ibm.com [9.149.37.216]) by b06cxnps4074.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s5QEUJ0c34209928 for ; Thu, 26 Jun 2014 14:30:19 GMT Received: from d06av04.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av04.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s5QEUHsY004943 for ; Thu, 26 Jun 2014 08:30:18 -0600 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d06av04.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id s5QEUHuB004932; Thu, 26 Jun 2014 08:30:17 -0600 Received: by tuxmaker.boeblingen.de.ibm.com (Postfix, from userid 1122) id 6CBF01224439; Thu, 26 Jun 2014 16:30:17 +0200 (CEST) From: Jens Freimann To: Christian Borntraeger , Alexander Graf , Cornelia Huck Date: Thu, 26 Jun 2014 16:30:02 +0200 Message-Id: <1403793009-54176-4-git-send-email-jfrei@linux.vnet.ibm.com> X-Mailer: git-send-email 1.8.5.5 In-Reply-To: <1403793009-54176-1-git-send-email-jfrei@linux.vnet.ibm.com> References: <1403793009-54176-1-git-send-email-jfrei@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 14062614-3548-0000-0000-0000004C8400 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.75.94.112 Cc: "Eugene \(jno\) Dvurechenski" , Jens Freimann , qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 03/10] pc-bios/s390-ccw: handle different sector sizes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: "Eugene (jno) Dvurechenski" 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 Signed-off-by: Jens Freimann --- 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 */