From 49cffbc6079c27432b4635d5d03ce14a249d86e2 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Wed, 11 Nov 2015 09:59:26 +0800 Subject: [PATCH 01/10] virtio-blk: trivial code optimization 1. avoid possible superflous checking 2. make code more robustness ["make code more robustness" refers to avoiding integer underflows/overflows. --Stefan] Signed-off-by: Gonglei Message-id: 1447207166-12612-1-git-send-email-arei.gonglei@huawei.com Signed-off-by: Stefan Hajnoczi --- hw/block/virtio-blk.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index b88b726be1..f72d4b6069 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -407,24 +407,16 @@ void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb) for (i = 0; i < mrb->num_reqs; i++) { VirtIOBlockReq *req = mrb->reqs[i]; if (num_reqs > 0) { - bool merge = true; - - /* merge would exceed maximum number of IOVs */ - if (niov + req->qiov.niov > IOV_MAX) { - merge = false; - } - - /* merge would exceed maximum transfer length of backend device */ - if (req->qiov.size / BDRV_SECTOR_SIZE + nb_sectors > max_xfer_len) { - merge = false; - } - - /* requests are not sequential */ - if (sector_num + nb_sectors != req->sector_num) { - merge = false; - } - - if (!merge) { + /* + * NOTE: We cannot merge the requests in below situations: + * 1. requests are not sequential + * 2. merge would exceed maximum number of IOVs + * 3. merge would exceed maximum transfer length of backend device + */ + if (sector_num + nb_sectors != req->sector_num || + niov > IOV_MAX - req->qiov.niov || + req->qiov.size / BDRV_SECTOR_SIZE > max_xfer_len || + nb_sectors > max_xfer_len - req->qiov.size / BDRV_SECTOR_SIZE) { submit_requests(blk, mrb, start, num_reqs, niov); num_reqs = 0; } From bd44feb754bdb1354f9813ca5dfe883f3d058193 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 9 Jul 2015 10:56:44 +0100 Subject: [PATCH 02/10] block: add BlockLimits.max_iov field The maximum number of struct iovec elements depends on the BlockDriverState. The raw-posix and iSCSI protocols have a maximum of IOV_MAX but others could have different values. Cc: Peter Lieven Suggested-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- block/io.c | 7 +++++++ include/block/block_int.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/block/io.c b/block/io.c index 841f5b503f..42050a0598 100644 --- a/block/io.c +++ b/block/io.c @@ -166,9 +166,13 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.max_transfer_length = bs->file->bs->bl.max_transfer_length; bs->bl.min_mem_alignment = bs->file->bs->bl.min_mem_alignment; bs->bl.opt_mem_alignment = bs->file->bs->bl.opt_mem_alignment; + bs->bl.max_iov = bs->file->bs->bl.max_iov; } else { bs->bl.min_mem_alignment = 512; bs->bl.opt_mem_alignment = getpagesize(); + + /* Safe default since most protocols use readv()/writev()/etc */ + bs->bl.max_iov = IOV_MAX; } if (bs->backing) { @@ -189,6 +193,9 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.min_mem_alignment = MAX(bs->bl.min_mem_alignment, bs->backing->bs->bl.min_mem_alignment); + bs->bl.max_iov = + MIN(bs->bl.max_iov, + bs->backing->bs->bl.max_iov); } /* Then let the driver override it */ diff --git a/include/block/block_int.h b/include/block/block_int.h index 9a1c466c84..256609dd3d 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -330,6 +330,9 @@ typedef struct BlockLimits { /* memory alignment for bounce buffer */ size_t opt_mem_alignment; + + /* maximum number of iovec elements */ + int max_iov; } BlockLimits; typedef struct BdrvOpBlocker BdrvOpBlocker; From 648296e067e617e140032c0ab329fb89ffb92aaa Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 9 Jul 2015 10:56:45 +0100 Subject: [PATCH 03/10] block-backend: add blk_get_max_iov() Add a function to query BlockLimits.max_iov. Signed-off-by: Stefan Hajnoczi --- block/block-backend.c | 5 +++++ include/sysemu/block-backend.h | 1 + 2 files changed, 6 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c index 36ccc9e616..f41d326b3c 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1023,6 +1023,11 @@ int blk_get_max_transfer_length(BlockBackend *blk) } } +int blk_get_max_iov(BlockBackend *blk) +{ + return blk->bs->bl.max_iov; +} + void blk_set_guest_block_size(BlockBackend *blk, int align) { blk->guest_block_size = align; diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index fb068ea47b..dc244760a1 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -146,6 +146,7 @@ void blk_lock_medium(BlockBackend *blk, bool locked); void blk_eject(BlockBackend *blk, bool eject_flag); int blk_get_flags(BlockBackend *blk); int blk_get_max_transfer_length(BlockBackend *blk); +int blk_get_max_iov(BlockBackend *blk); void blk_set_guest_block_size(BlockBackend *blk, int align); void *blk_blockalign(BlockBackend *blk, size_t size); bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp); From 222565f65c3fba6825912c2561de7831e514ef3c Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 9 Jul 2015 10:56:46 +0100 Subject: [PATCH 04/10] block: replace IOV_MAX with BlockLimits.max_iov Request merging must not result in a huge request that exceeds the maximum number of iovec elements. Use BlockLimits.max_iov instead of hardcoding IOV_MAX. Signed-off-by: Stefan Hajnoczi --- block/io.c | 3 ++- hw/block/virtio-blk.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/block/io.c b/block/io.c index 42050a0598..63e3678036 100644 --- a/block/io.c +++ b/block/io.c @@ -1889,7 +1889,8 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs, merge = 1; } - if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) { + if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > + bs->bl.max_iov) { merge = 0; } diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index f72d4b6069..51f867b513 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -414,7 +414,7 @@ void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb) * 3. merge would exceed maximum transfer length of backend device */ if (sector_num + nb_sectors != req->sector_num || - niov > IOV_MAX - req->qiov.niov || + niov > blk_get_max_iov(blk) - req->qiov.niov || req->qiov.size / BDRV_SECTOR_SIZE > max_xfer_len || nb_sectors > max_xfer_len - req->qiov.size / BDRV_SECTOR_SIZE) { submit_requests(blk, mrb, start, num_reqs, niov); From 3515727f31a2377ec94d0adb450cc175f33138f7 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 9 Jul 2015 10:56:47 +0100 Subject: [PATCH 05/10] block/mirror: replace IOV_MAX with blk_get_max_iov() Use blk_get_max_iov() instead of hardcoding IOV_MAX, which may not apply to all BlockDrivers. Signed-off-by: Stefan Hajnoczi --- block/mirror.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index fc34a9c491..f201f2b18a 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -161,13 +161,15 @@ static void mirror_read_complete(void *opaque, int ret) static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) { BlockDriverState *source = s->common.bs; - int nb_sectors, sectors_per_chunk, nb_chunks; + int nb_sectors, sectors_per_chunk, nb_chunks, max_iov; int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector; uint64_t delay_ns = 0; MirrorOp *op; int pnum; int64_t ret; + max_iov = MIN(source->bl.max_iov, s->target->bl.max_iov); + s->sector_num = hbitmap_iter_next(&s->hbi); if (s->sector_num < 0) { bdrv_dirty_iter_init(s->dirty_bitmap, &s->hbi); @@ -248,7 +250,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) trace_mirror_break_buf_busy(s, nb_chunks, s->in_flight); break; } - if (IOV_MAX < nb_chunks + added_chunks) { + if (max_iov < nb_chunks + added_chunks) { trace_mirror_break_iov_max(s, nb_chunks, added_chunks); break; } From b4a9e25b7b8f258f0692d273e59e3e20347cdf28 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Fri, 27 Nov 2015 15:20:06 +0300 Subject: [PATCH 06/10] parallels: add format spec This specifies Parallels image format as implemented in Parallels Cloud Server 6.10 Signed-off-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Denis V. Lunev Message-id: 1448626806-17591-1-git-send-email-den@openvz.org CC: Eric Blake CC: John Snow CC: Stefan Hajnoczi Signed-off-by: Stefan Hajnoczi --- MAINTAINERS | 1 + docs/specs/parallels.txt | 228 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 docs/specs/parallels.txt diff --git a/MAINTAINERS b/MAINTAINERS index 55a0fd8ae5..46bba68990 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1490,6 +1490,7 @@ M: Denis V. Lunev L: qemu-block@nongnu.org S: Supported F: block/parallels.c +F: docs/specs/parallels.txt qed M: Stefan Hajnoczi diff --git a/docs/specs/parallels.txt b/docs/specs/parallels.txt new file mode 100644 index 0000000000..b4fe2295fb --- /dev/null +++ b/docs/specs/parallels.txt @@ -0,0 +1,228 @@ += License = + +Copyright (c) 2015 Denis Lunev +Copyright (c) 2015 Vladimir Sementsov-Ogievskiy + +This work is licensed under the terms of the GNU GPL, version 2 or later. +See the COPYING file in the top-level directory. + += Parallels Expandable Image File Format = + +A Parallels expandable image file consists of three consecutive parts: + * header + * BAT + * data area + +All numbers in a Parallels expandable image are stored in little-endian byte +order. + + +== Definitions == + + Sector A 512-byte data chunk. + + Cluster A data chunk of the size specified in the image header. + Currently, the default size is 1MiB (2048 sectors). In previous + versions, cluster sizes of 63 sectors, 256 and 252 kilobytes were + used. + + BAT Block Allocation Table, an entity that contains information for + guest-to-host I/O data address translation. + + +== Header == + +The header is placed at the start of an image and contains the following +fields: + +Bytes: + 0 - 15: magic + Must contain "WithoutFreeSpace" or "WithouFreSpacExt". + + 16 - 19: version + Must be 2. + + 20 - 23: heads + Disk geometry parameter for guest. + + 24 - 27: cylinders + Disk geometry parameter for guest. + + 28 - 31: tracks + Cluster size, in sectors. + + 32 - 35: nb_bat_entries + Disk size, in clusters (BAT size). + + 36 - 43: nb_sectors + Disk size, in sectors. + + For "WithoutFreeSpace" images: + Only the lowest 4 bytes are used. The highest 4 bytes must be + cleared in this case. + + For "WithouFreSpacExt" images, there are no such + restrictions. + + 44 - 47: in_use + Set to 0x746F6E59 when the image is opened by software in R/W + mode; set to 0x312e3276 when the image is closed. + + A zero in this field means that the image was opened by an old + version of the software that doesn't support Format Extension + (see below). + + Other values are not allowed. + + 48 - 51: data_off + An offset, in sectors, from the start of the file to the start of + the data area. + + For "WithoutFreeSpace" images: + - If data_off is zero, the offset is calculated as the end of BAT + table plus some padding to ensure sector size alignment. + - If data_off is non-zero, the offset should be aligned to sector + size. However it is recommended to align it to cluster size for + newly created images. + + For "WithouFreSpacExt" images: + data_off must be non-zero and aligned to cluster size. + + 52 - 55: flags + Miscellaneous flags. + + Bit 0: Empty Image bit. If set, the image should be + considered clear. + + Bits 2-31: Unused. + + 56 - 63: ext_off + Format Extension offset, an offset, in sectors, from the start of + the file to the start of the Format Extension Cluster. + + ext_off must meet the same requirements as cluster offsets + defined by BAT entries (see below). + + +== BAT == + +BAT is placed immediately after the image header. In the file, BAT is a +contiguous array of 32-bit unsigned little-endian integers with +(bat_entries * 4) bytes size. + +Each BAT entry contains an offset from the start of the file to the +corresponding cluster. The offset set in clusters for "WithouFreSpacExt" images +and in sectors for "WithoutFreeSpace" images. + +If a BAT entry is zero, the corresponding cluster is not allocated and should +be considered as filled with zeroes. + +Cluster offsets specified by BAT entries must meet the following requirements: + - the value must not be lower than data offset (provided by header.data_off + or calculated as specified above), + - the value must be lower than the desired file size, + - the value must be unique among all BAT entries, + - the result of (cluster offset - data offset) must be aligned to cluster + size. + + +== Data Area == + +The data area is an area from the data offset (provided by header.data_off or +calculated as specified above) to the end of the file. It represents a +contiguous array of clusters. Most of them are allocated by the BAT, some may +be allocated by the ext_off field in the header while other may be allocated by +extensions. All clusters allocated by ext_off and extensions should meet the +same requirements as clusters specified by BAT entries. + + +== Format Extension == + +The Format Extension is an area 1 cluster in size that provides additional +format features. This cluster is addressed by the ext_off field in the header. +The format of the Format Extension area is the following: + + 0 - 7: magic + Must be 0xAB234CEF23DCEA87 + + 8 - 23: m_CheckSum + The MD5 checksum of the entire Header Extension cluster except + the first 24 bytes. + + The above are followed by feature sections or "extensions". The last + extension must be "End of features" (see below). + +Each feature section has the following format: + + 0 - 7: magic + The identifier of the feature: + 0x0000000000000000 - End of features + 0x20385FAE252CB34A - Dirty bitmap + + 8 - 15: flags + External flags for extension: + + Bit 0: NECESSARY + If the software cannot load the extension (due to an + unknown magic number or error), the file should not be + changed. If this flag is unset and there is an error on + loading the extension, said extension should be dropped. + + Bit 1: TRANSIT + If there is an unknown extension with this flag set, + said extension should be left as is. + + If neither NECESSARY nor TRANSIT are set, the extension should be + dropped. + + 16 - 19: data_size + The size of the following feature data, in bytes. + + 20 - 23: unused32 + Align header to 8 bytes boundary. + + variable: data (data_size bytes) + + The above is followed by padding to the next 8 bytes boundary, then the + next extension starts. + + The last extension must be "End of features" with all the fields set to 0. + + +=== Dirty bitmaps feature === + +This feature provides a way of storing dirty bitmaps in the image. The fields +of its data area are: + + 0 - 7: size + The bitmap size, should be equal to disk size in sectors. + + 8 - 23: id + An identifier for backup consistency checking. + + 24 - 27: granularity + Bitmap granularity, in sectors. I.e., the number of sectors + corresponding to one bit of the bitmap. Granularity must be + a power of 2. + + 28 - 31: l1_size + The number of entries in the L1 table of the bitmap. + + variable: l1 (64 * l1_size bytes) + L1 offset table (in bytes) + +A dirty bitmap is stored using a one-level structure for the mapping to host +clusters - an L1 table. + +Given an offset in bytes into the bitmap data, the offset in bytes into the +image file can be obtained as follows: + + offset = l1_table[offset / cluster_size] + (offset % cluster_size) + +If an L1 table entry is 0, the corresponding cluster of the bitmap is assumed +to be zero. + +If an L1 table entry is 1, the corresponding cluster of the bitmap is assumed +to have all bits set. + +If an L1 table entry is not 0 or 1, it allocates a cluster from the data area. From d6b6913276535bc0bc0d519d94ba0c908d8cfed8 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Sat, 5 Dec 2015 19:52:20 +0800 Subject: [PATCH 07/10] scripts/gdb: Fix a python exception in mtree.py The following exception is threw: Python Exception name 'long' is not defined: Error occurred in Python command: name 'long' is not defined Python 2.4+, int()/long() have been unified, so replace long with int. Signed-off-by: Yang Wei Message-id: 1449316340-4030-1-git-send-email-w90p710@gmail.com Signed-off-by: Stefan Hajnoczi --- scripts/qemugdb/mtree.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/qemugdb/mtree.py b/scripts/qemugdb/mtree.py index 06011c30cc..cc8131c2e7 100644 --- a/scripts/qemugdb/mtree.py +++ b/scripts/qemugdb/mtree.py @@ -21,7 +21,7 @@ def isnull(ptr): return ptr == gdb.Value(0).cast(ptr.type) def int128(p): - return long(p['lo']) + (long(p['hi']) << 64) + return int(p['lo']) + (int(p['hi']) << 64) class MtreeCommand(gdb.Command): '''Display the memory tree hierarchy''' @@ -40,11 +40,11 @@ class MtreeCommand(gdb.Command): def process_queue(self): while self.queue: ptr = self.queue.pop(0) - if long(ptr) in self.seen: + if int(ptr) in self.seen: continue self.print_item(ptr) def print_item(self, ptr, offset = gdb.Value(0), level = 0): - self.seen.add(long(ptr)) + self.seen.add(int(ptr)) addr = ptr['addr'] addr += offset size = int128(ptr['size']) @@ -58,8 +58,8 @@ class MtreeCommand(gdb.Command): klass = ' (RAM)' gdb.write('%s%016x-%016x %s%s (@ %s)\n' % (' ' * level, - long(addr), - long(addr + (size - 1)), + int(addr), + int(addr + (size - 1)), ptr['name'].string(), klass, ptr, From 6890a695d954f33c8a9c4efd3037fdb707fe28ec Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 21 Dec 2015 14:47:47 -0800 Subject: [PATCH 08/10] sd: sdhci: Delete over-zealous power check This check was conditionalising SD card operation on the card being powered by the SDHCI host controller. It is however possible (particularly in embedded systems) for the power control of the SD card to be managed outside of SDHCI. This can be as trivial as hard-wiring the SD slot VCC to a constant power-rail. This means the guest SDHCI can validly opt-out of the SDHCI power control feature while still using the card. So delete this check to allow operation of the card with SDHCI power control. This is needed for at least Xilinx Zynq and Raspberry Pi, and also makes Freescale i.MX25 work for me. The digilent Zybo board has a public schematic which shows SD VCC hardwiring: http://digilentinc.com/Data/Products/ZYBO/ZYBO_sch_VB.3.pdf bottom of page 3. Signed-off-by: Peter Crosthwaite Reviewed-by: Sai Pavan Boddu Signed-off-by: Andrew Baumann Message-id: 1450738069-18664-2-git-send-email-Andrew.Baumann@microsoft.com [AB: Add Pi to list of devices fixed in commit message] Signed-off-by: Andrew Baumann Signed-off-by: Stefan Hajnoczi --- hw/sd/sdhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 861276065f..bc39d48ac4 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -831,7 +831,7 @@ static void sdhci_data_transfer(void *opaque) static bool sdhci_can_issue_command(SDHCIState *s) { - if (!SDHC_CLOCK_IS_ON(s->clkcon) || !(s->pwrcon & SDHC_POWER_ON) || + if (!SDHC_CLOCK_IS_ON(s->clkcon) || (((s->prnsts & SDHC_DATA_INHIBIT) || s->stopped_state) && ((s->cmdreg & SDHC_CMD_DATA_PRESENT) || ((s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY && From 62d32ec817f985ce1c38868d279d449c80975ff2 Mon Sep 17 00:00:00 2001 From: Andrew Baumann Date: Mon, 21 Dec 2015 14:47:48 -0800 Subject: [PATCH 09/10] sdhci: don't raise a command index error for an unexpected response This deletes a block of code that raised a command index error if a command returned response data, but the guest did not set the appropriate bits in the response register to handle such a response. I cannot find any documentation that suggests the controller should behave in this way, the error code doesn't make sense (command index error is defined for the case where the index in a response does not match that of the issued command), and in at least one case (CMD23 issued by UEFI on Raspberry Pi 2), actual hardware does not do this. Signed-off-by: Andrew Baumann Reviewed-by: Peter Crosthwaite Message-id: 1450738069-18664-3-git-send-email-Andrew.Baumann@microsoft.com Signed-off-by: Stefan Hajnoczi --- hw/sd/sdhci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index bc39d48ac4..dd83e89d52 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -243,9 +243,6 @@ static void sdhci_send_command(SDHCIState *s) (s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) { s->norintsts |= SDHC_NIS_TRSCMP; } - } else if (rlen != 0 && (s->errintstsen & SDHC_EISEN_CMDIDX)) { - s->errintsts |= SDHC_EIS_CMDIDX; - s->norintsts |= SDHC_NIS_ERR; } if (s->norintstsen & SDHC_NISEN_CMDCMP) { From 723697551a7e926abe7d3c7f2966012b8075143d Mon Sep 17 00:00:00 2001 From: Andrew Baumann Date: Mon, 21 Dec 2015 14:47:49 -0800 Subject: [PATCH 10/10] sdhci: add optional quirk property to disable card insertion/removal interrupts This is needed for a quirk of the Raspberry Pi (bcm2835/6) MMC controller, where the card insert bit is documented as unimplemented (always reads zero, doesn't generate interrupts) but is in fact observed on hardware as set at power on, but is cleared (and remains clear) on subsequent controller resets. Signed-off-by: Andrew Baumann Reviewed-by: Peter Crosthwaite Message-id: 1450738069-18664-4-git-send-email-Andrew.Baumann@microsoft.com Signed-off-by: Stefan Hajnoczi --- hw/sd/sdhci.c | 5 ++++- include/hw/sd/sdhci.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index dd83e89d52..7acb4d7928 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -193,7 +193,9 @@ static void sdhci_reset(SDHCIState *s) * initialization */ memset(&s->sdmasysad, 0, (uintptr_t)&s->capareg - (uintptr_t)&s->sdmasysad); - sd_set_cb(s->card, s->ro_cb, s->eject_cb); + if (!s->noeject_quirk) { + sd_set_cb(s->card, s->ro_cb, s->eject_cb); + } s->data_count = 0; s->stopped_state = sdhc_not_stopped; } @@ -1276,6 +1278,7 @@ static Property sdhci_sysbus_properties[] = { DEFINE_PROP_UINT32("capareg", SDHCIState, capareg, SDHC_CAPAB_REG_DEFAULT), DEFINE_PROP_UINT32("maxcurr", SDHCIState, maxcurr, 0), + DEFINE_PROP_BOOL("noeject-quirk", SDHCIState, noeject_quirk, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h index e78d938570..ffd1f80891 100644 --- a/include/hw/sd/sdhci.h +++ b/include/hw/sd/sdhci.h @@ -77,6 +77,7 @@ typedef struct SDHCIState { uint32_t buf_maxsz; uint16_t data_count; /* current element in FIFO buffer */ uint8_t stopped_state;/* Current SDHC state */ + bool noeject_quirk;/* Quirk to disable card insert/remove interrupts */ /* Buffer Data Port Register - virtual access point to R and W buffers */ /* Software Reset Register - always reads as 0 */ /* Force Event Auto CMD12 Error Interrupt Reg - write only */