Re: [PATCH v15 00/11] hw/m68k: add Apple Machintosh Quadra 800 machine

2019-10-26 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20191026164546.30020-1-laur...@vivier.eu/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [PATCH v15 00/11] hw/m68k: add Apple Machintosh Quadra 800 machine
Type: series
Message-id: 20191026164546.30020-1-laur...@vivier.eu

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Switched to a new branch 'test'
6a33715 BootLinuxConsoleTest: Test the Quadra 800
00fcb5e hw/m68k: define Macintosh Quadra 800
0fd320a hw/m68k: add a dummy SWIM floppy controller
b2769ed hw/m68k: add Nubus macfb video card
4d4b624 hw/m68k: add Nubus support
0aea0e6 hw/m68k: implement ADB bus support for via
b17ed1f hw/m68k: add VIA support
c7e819f dp8393x: manage big endian bus
6ccaebd esp: add pseudo-DMA as used by Macintosh
01cb492 esp: move get_cmd() post-DMA code to get_cmd_cb()
55e78d9 esp: move handle_ti_cmd() cleanup code to esp_do_dma().

=== OUTPUT BEGIN ===
1/11 Checking commit 55e78d9d9cde (esp: move handle_ti_cmd() cleanup code to 
esp_do_dma().)
2/11 Checking commit 01cb492b0e6b (esp: move get_cmd() post-DMA code to 
get_cmd_cb())
3/11 Checking commit 6ccaebd8eef7 (esp: add pseudo-DMA as used by Macintosh)
4/11 Checking commit c7e819f6f26f (dp8393x: manage big endian bus)
5/11 Checking commit b17ed1faf532 (hw/m68k: add VIA support)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#83: 
new file mode 100644

ERROR: space prohibited after that '&&' (ctx:WxW)
#455: FILE: hw/misc/mac_via.c:368:
+if (!(v1s->last_b & VIA1B_vRTCClk) && (s->b & VIA1B_vRTCClk)) {
^

total: 1 errors, 1 warnings, 912 lines checked

Patch 5/11 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

6/11 Checking commit 0aea0e6cc787 (hw/m68k: implement ADB bus support for via)
7/11 Checking commit 4d4b62485c14 (hw/m68k: add Nubus support)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#64: 
new file mode 100644

total: 0 errors, 1 warnings, 531 lines checked

Patch 7/11 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/11 Checking commit b2769ed8824f (hw/m68k: add Nubus macfb video card)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#75: 
new file mode 100644

total: 0 errors, 1 warnings, 597 lines checked

Patch 8/11 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
9/11 Checking commit 0fd320a0b96e (hw/m68k: add a dummy SWIM floppy controller)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#62: 
new file mode 100644

total: 0 errors, 1 warnings, 593 lines checked

Patch 9/11 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
10/11 Checking commit 00fcb5e66196 (hw/m68k: define Macintosh Quadra 800)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#71: 
new file mode 100644

total: 0 errors, 1 warnings, 537 lines checked

Patch 10/11 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
11/11 Checking commit 6a337153d271 (BootLinuxConsoleTest: Test the Quadra 800)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20191026164546.30020-1-laur...@vivier.eu/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[RFC PATCH v2 20/26] qcow2: Update L2 bitmap in qcow2_alloc_cluster_link_l2()

2019-10-26 Thread Alberto Garcia
The L2 bitmap needs to be updated after each write to indicate what
new subclusters are now allocated.

This needs to happen even if the cluster was already allocated and the
L2 entry was otherwise valid.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index fb6cf8df17..acb7226e03 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -980,6 +980,22 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, 
QCowL2Meta *m)
 
 set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_COPIED |
  (cluster_offset + (i << s->cluster_bits)));
+
+/* Update bitmap with the subclusters that were just written */
+if (has_subclusters(s)) {
+uint64_t written_from = m->cow_start.offset;
+uint64_t written_to = m->cow_end.offset + m->cow_end.nb_bytes;
+uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
+int sc;
+for (sc = 0; sc < s->subclusters_per_cluster; sc++) {
+uint64_t sc_off = i * s->cluster_size + sc * 
s->subcluster_size;
+if (sc_off >= written_from && sc_off < written_to) {
+l2_bitmap |= QCOW_OFLAG_SUB_ALLOC(sc);
+l2_bitmap &= ~QCOW_OFLAG_SUB_ZERO(sc);
+}
+}
+set_l2_bitmap(s, l2_slice, l2_index + i, l2_bitmap);
+}
  }
 
 
-- 
2.20.1




[RFC PATCH v2 04/26] qcow2: Add get_l2_entry() and set_l2_entry()

2019-10-26 Thread Alberto Garcia
The size of an L2 entry is 64 bits, but if we want to have subclusters
we need extended L2 entries. This means that we have to access L2
tables and slices differently depending on whether an image has
extended L2 entries or not.

This patch replaces all l2_slice[] accesses with calls to
get_l2_entry() and set_l2_entry().

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c  | 65 ++
 block/qcow2-refcount.c | 17 +--
 block/qcow2.h  | 12 
 3 files changed, 55 insertions(+), 39 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index ee6b46f917..581fa90ab1 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -379,12 +379,13 @@ fail:
  * cluster which may require a different handling)
  */
 static int count_contiguous_clusters(BlockDriverState *bs, int nb_clusters,
-int cluster_size, uint64_t *l2_slice, uint64_t stop_flags)
+int cluster_size, uint64_t *l2_slice, int l2_index, uint64_t 
stop_flags)
 {
+BDRVQcow2State *s = bs->opaque;
 int i;
 QCow2ClusterType first_cluster_type;
 uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
-uint64_t first_entry = be64_to_cpu(l2_slice[0]);
+uint64_t first_entry = get_l2_entry(s, l2_slice, l2_index);
 uint64_t offset = first_entry & mask;
 
 first_cluster_type = qcow2_get_cluster_type(bs, first_entry);
@@ -397,7 +398,7 @@ static int count_contiguous_clusters(BlockDriverState *bs, 
int nb_clusters,
first_cluster_type == QCOW2_CLUSTER_ZERO_ALLOC);
 
 for (i = 0; i < nb_clusters; i++) {
-uint64_t l2_entry = be64_to_cpu(l2_slice[i]) & mask;
+uint64_t l2_entry = get_l2_entry(s, l2_slice, l2_index + i) & mask;
 if (offset + (uint64_t) i * cluster_size != l2_entry) {
 break;
 }
@@ -413,14 +414,16 @@ static int count_contiguous_clusters(BlockDriverState 
*bs, int nb_clusters,
 static int count_contiguous_clusters_unallocated(BlockDriverState *bs,
  int nb_clusters,
  uint64_t *l2_slice,
+ int l2_index,
  QCow2ClusterType wanted_type)
 {
+BDRVQcow2State *s = bs->opaque;
 int i;
 
 assert(wanted_type == QCOW2_CLUSTER_ZERO_PLAIN ||
wanted_type == QCOW2_CLUSTER_UNALLOCATED);
 for (i = 0; i < nb_clusters; i++) {
-uint64_t entry = be64_to_cpu(l2_slice[i]);
+uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i);
 QCow2ClusterType type = qcow2_get_cluster_type(bs, entry);
 
 if (type != wanted_type) {
@@ -566,7 +569,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t 
offset,
 /* find the cluster offset for the given disk offset */
 
 l2_index = offset_to_l2_slice_index(s, offset);
-*cluster_offset = be64_to_cpu(l2_slice[l2_index]);
+*cluster_offset = get_l2_entry(s, l2_slice, l2_index);
 
 nb_clusters = size_to_clusters(s, bytes_needed);
 /* bytes_needed <= *bytes + offset_in_cluster, both of which are unsigned
@@ -601,14 +604,14 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, 
uint64_t offset,
 case QCOW2_CLUSTER_UNALLOCATED:
 /* how many empty clusters ? */
 c = count_contiguous_clusters_unallocated(bs, nb_clusters,
-  _slice[l2_index], type);
+  l2_slice, l2_index, type);
 *cluster_offset = 0;
 break;
 case QCOW2_CLUSTER_ZERO_ALLOC:
 case QCOW2_CLUSTER_NORMAL:
 /* how many allocated clusters ? */
 c = count_contiguous_clusters(bs, nb_clusters, s->cluster_size,
-  _slice[l2_index], QCOW_OFLAG_ZERO);
+  l2_slice, l2_index, QCOW_OFLAG_ZERO);
 *cluster_offset &= L2E_OFFSET_MASK;
 if (offset_into_cluster(s, *cluster_offset)) {
 qcow2_signal_corruption(bs, true, -1, -1,
@@ -761,7 +764,7 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState 
*bs,
 
 /* Compression can't overwrite anything. Fail if the cluster was already
  * allocated. */
-cluster_offset = be64_to_cpu(l2_slice[l2_index]);
+cluster_offset = get_l2_entry(s, l2_slice, l2_index);
 if (cluster_offset & L2E_OFFSET_MASK) {
 qcow2_cache_put(s->l2_table_cache, (void **) _slice);
 return -EIO;
@@ -786,7 +789,7 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState 
*bs,
 
 BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
 qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
-l2_slice[l2_index] = cpu_to_be64(cluster_offset);
+set_l2_entry(s, l2_slice, l2_index, cluster_offset);
 qcow2_cache_put(s->l2_table_cache, (void **) _slice);
 
 *host_offset = cluster_offset & 

[RFC PATCH v2 23/26] qcow2: Restrict qcow2_co_pwrite_zeroes() to full clusters only

2019-10-26 Thread Alberto Garcia
Ideally it should be possible to zero individual subclusters using
this function, but this is currently not implemented.

Signed-off-by: Alberto Garcia 
---
 block/qcow2.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/block/qcow2.c b/block/qcow2.c
index 01322ca449..537569ce88 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3704,6 +3704,12 @@ static coroutine_fn int 
qcow2_co_pwrite_zeroes(BlockDriverState *bs,
 bytes = s->cluster_size;
 nr = s->cluster_size;
 ret = qcow2_get_cluster_offset(bs, offset, , );
+/* TODO: allow zeroing separate subclusters, we only allow
+ * zeroing full clusters at the moment. */
+if (nr != bytes) {
+qemu_co_mutex_unlock(>lock);
+return -ENOTSUP;
+}
 if (ret != QCOW2_CLUSTER_UNALLOCATED &&
 ret != QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER &&
 ret != QCOW2_CLUSTER_ZERO_PLAIN &&
-- 
2.20.1




[RFC PATCH v2 01/26] qcow2: Add calculate_l2_meta()

2019-10-26 Thread Alberto Garcia
handle_alloc() creates a QCowL2Meta structure in order to update the
image metadata and perform the necessary copy-on-write operations.

This patch moves that code to a separate function so it can be used
from other places.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 76 +--
 1 file changed, 52 insertions(+), 24 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 8982b7b762..6c1dcdc781 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1019,6 +1019,55 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, 
QCowL2Meta *m)
 QCOW2_DISCARD_NEVER);
 }
 
+/*
+ * For a given write request, create a new QCowL2Meta structure and
+ * add it to @m.
+ *
+ * @host_offset points to the beginning of the first cluster.
+ *
+ * @guest_offset and @bytes indicate the offset and length of the
+ * request.
+ *
+ * If @keep_old is true it means that the clusters were already
+ * allocated and will be overwritten. If false then the clusters are
+ * new and we have to decrease the reference count of the old ones.
+ */
+static void calculate_l2_meta(BlockDriverState *bs, uint64_t host_offset,
+  uint64_t guest_offset, uint64_t bytes,
+  QCowL2Meta **m, bool keep_old)
+{
+BDRVQcow2State *s = bs->opaque;
+unsigned cow_start_from = 0;
+unsigned cow_start_to = offset_into_cluster(s, guest_offset);
+unsigned cow_end_from = cow_start_to + bytes;
+unsigned cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
+unsigned nb_clusters = size_to_clusters(s, cow_end_from);
+QCowL2Meta *old_m = *m;
+
+*m = g_malloc0(sizeof(**m));
+**m = (QCowL2Meta) {
+.next   = old_m,
+
+.alloc_offset   = host_offset,
+.offset = start_of_cluster(s, guest_offset),
+.nb_clusters= nb_clusters,
+
+.keep_old_clusters = keep_old,
+
+.cow_start = {
+.offset = cow_start_from,
+.nb_bytes   = cow_start_to - cow_start_from,
+},
+.cow_end = {
+.offset = cow_end_from,
+.nb_bytes   = cow_end_to - cow_end_from,
+},
+};
+
+qemu_co_queue_init(&(*m)->dependent_requests);
+QLIST_INSERT_HEAD(>cluster_allocs, *m, next_in_flight);
+}
+
 /*
  * Returns the number of contiguous clusters that can be used for an allocating
  * write, but require COW to be performed (this includes yet unallocated space,
@@ -1417,35 +1466,14 @@ static int handle_alloc(BlockDriverState *bs, uint64_t 
guest_offset,
 uint64_t requested_bytes = *bytes + offset_into_cluster(s, guest_offset);
 int avail_bytes = nb_clusters << s->cluster_bits;
 int nb_bytes = MIN(requested_bytes, avail_bytes);
-QCowL2Meta *old_m = *m;
-
-*m = g_malloc0(sizeof(**m));
-
-**m = (QCowL2Meta) {
-.next   = old_m,
-
-.alloc_offset   = alloc_cluster_offset,
-.offset = start_of_cluster(s, guest_offset),
-.nb_clusters= nb_clusters,
-
-.keep_old_clusters  = keep_old_clusters,
-
-.cow_start = {
-.offset = 0,
-.nb_bytes   = offset_into_cluster(s, guest_offset),
-},
-.cow_end = {
-.offset = nb_bytes,
-.nb_bytes   = avail_bytes - nb_bytes,
-},
-};
-qemu_co_queue_init(&(*m)->dependent_requests);
-QLIST_INSERT_HEAD(>cluster_allocs, *m, next_in_flight);
 
 *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset);
 *bytes = MIN(*bytes, nb_bytes - offset_into_cluster(s, guest_offset));
 assert(*bytes != 0);
 
+calculate_l2_meta(bs, alloc_cluster_offset, guest_offset, *bytes,
+  m, keep_old_clusters);
+
 return 1;
 
 fail:
-- 
2.20.1




[RFC PATCH v2 10/26] qcow2: Update get/set_l2_entry() and add get/set_l2_bitmap()

2019-10-26 Thread Alberto Garcia
Extended L2 entries are 128-bit wide: 64 bits for the entry itself and
64 bits for the subcluster allocation bitmap.

In order to support them correctly get/set_l2_entry() need to be
updated so they take the entry width into account in order to
calculate the correct offset.

This patch also adds the get/set_l2_bitmap() functions that are used
to access the bitmaps. For convenience, these functions are no-ops
when used in traditional qcow2 images.

Signed-off-by: Alberto Garcia 
---
 block/qcow2.h | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/block/qcow2.h b/block/qcow2.h
index 29a253bfb9..741c41c80f 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -507,15 +507,37 @@ static inline size_t l2_entry_size(BDRVQcow2State *s)
 static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
 int idx)
 {
+idx *= l2_entry_size(s) / sizeof(uint64_t);
 return be64_to_cpu(l2_slice[idx]);
 }
 
+static inline uint64_t get_l2_bitmap(BDRVQcow2State *s, uint64_t *l2_slice,
+ int idx)
+{
+if (has_subclusters(s)) {
+idx *= l2_entry_size(s) / sizeof(uint64_t);
+return be64_to_cpu(l2_slice[idx + 1]);
+} else {
+return 0;
+}
+}
+
 static inline void set_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
 int idx, uint64_t entry)
 {
+idx *= l2_entry_size(s) / sizeof(uint64_t);
 l2_slice[idx] = cpu_to_be64(entry);
 }
 
+static inline void set_l2_bitmap(BDRVQcow2State *s, uint64_t *l2_slice,
+ int idx, uint64_t bitmap)
+{
+if (has_subclusters(s)) {
+idx *= l2_entry_size(s) / sizeof(uint64_t);
+l2_slice[idx + 1] = cpu_to_be64(bitmap);
+}
+}
+
 static inline bool has_data_file(BlockDriverState *bs)
 {
 BDRVQcow2State *s = bs->opaque;
-- 
2.20.1




[RFC PATCH v2 16/26] qcow2: Add subcluster support to discard_in_l2_slice()

2019-10-26 Thread Alberto Garcia
Setting the QCOW_OFLAG_ZERO bit of the L2 entry is forbidden if an
image has subclusters. Instead, the individual 'all zeroes' bits must
be used.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 3e4ba8d448..aa3eb727a5 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1772,7 +1772,11 @@ static int discard_in_l2_slice(BlockDriverState *bs, 
uint64_t offset,
 
 /* First remove L2 entries */
 qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
-if (!full_discard && s->qcow_version >= 3) {
+if (has_subclusters(s)) {
+set_l2_entry(s, l2_slice, l2_index + i, 0);
+set_l2_bitmap(s, l2_slice, l2_index + i,
+  full_discard ? 0 : QCOW_L2_BITMAP_ALL_ZEROES);
+} else if (!full_discard && s->qcow_version >= 3) {
 set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
 } else {
 set_l2_entry(s, l2_slice, l2_index + i, 0);
-- 
2.20.1




[RFC PATCH v2 17/26] qcow2: Add subcluster support to check_refcounts_l2()

2019-10-26 Thread Alberto Garcia
Setting the QCOW_OFLAG_ZERO bit of the L2 entry is forbidden if an
image has subclusters. Instead, the individual 'all zeroes' bits must
be used.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-refcount.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 621318447d..bc73125f70 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1685,8 +1685,13 @@ static int check_refcounts_l2(BlockDriverState *bs, 
BdrvCheckResult *res,
 int ign = active ? QCOW2_OL_ACTIVE_L2 :
QCOW2_OL_INACTIVE_L2;
 
-l2_entry = QCOW_OFLAG_ZERO;
-set_l2_entry(s, l2_table, i, l2_entry);
+if (has_subclusters(s)) {
+set_l2_entry(s, l2_table, i, 0);
+set_l2_bitmap(s, l2_table, i,
+  QCOW_L2_BITMAP_ALL_ZEROES);
+} else {
+set_l2_entry(s, l2_table, i, QCOW_OFLAG_ZERO);
+}
 ret = qcow2_pre_write_overlap_check(bs, ign,
 l2e_offset, l2_entry_size(s), false);
 if (ret < 0) {
-- 
2.20.1




[RFC PATCH v2 19/26] qcow2: Fix offset calculation in handle_dependencies()

2019-10-26 Thread Alberto Garcia
l2meta_cow_start() and l2meta_cow_end() are not necessarily
cluster-aligned if the image has subclusters, so update the
calculation of old_start and old_end to guarantee that no two requests
try to write on the same cluster.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 62f2a9fcc0..fb6cf8df17 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1262,8 +1262,8 @@ static int handle_dependencies(BlockDriverState *bs, 
uint64_t guest_offset,
 
 uint64_t start = guest_offset;
 uint64_t end = start + bytes;
-uint64_t old_start = l2meta_cow_start(old_alloc);
-uint64_t old_end = l2meta_cow_end(old_alloc);
+uint64_t old_start = start_of_cluster(s, l2meta_cow_start(old_alloc));
+uint64_t old_end = ROUND_UP(l2meta_cow_end(old_alloc), 
s->cluster_size);
 
 if (end <= old_start || start >= old_end) {
 /* No intersection */
-- 
2.20.1




[RFC PATCH v2 09/26] qcow2: Add l2_entry_size()

2019-10-26 Thread Alberto Garcia
qcow2 images with subclusters have 128-bit L2 entries. The first 64
bits contain the same information as traditional images and the last
64 bits form a bitmap with the status of each individual subcluster.

Because of that we cannot assume that L2 entries are sizeof(uint64_t)
anymore. This function returns the proper value for the image.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c  | 12 ++--
 block/qcow2-refcount.c | 14 --
 block/qcow2.c  |  6 +++---
 block/qcow2.h  |  5 +
 4 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 581fa90ab1..1f509bda15 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -209,7 +209,7 @@ static int l2_load(BlockDriverState *bs, uint64_t offset,
uint64_t l2_offset, uint64_t **l2_slice)
 {
 BDRVQcow2State *s = bs->opaque;
-int start_of_slice = sizeof(uint64_t) *
+int start_of_slice = l2_entry_size(s) *
 (offset_to_l2_index(s, offset) - offset_to_l2_slice_index(s, offset));
 
 return qcow2_cache_get(bs, s->l2_table_cache, l2_offset + start_of_slice,
@@ -277,7 +277,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
 
 /* allocate a new l2 entry */
 
-l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
+l2_offset = qcow2_alloc_clusters(bs, s->l2_size * l2_entry_size(s));
 if (l2_offset < 0) {
 ret = l2_offset;
 goto fail;
@@ -301,7 +301,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
 
 /* allocate a new entry in the l2 cache */
 
-slice_size2 = s->l2_slice_size * sizeof(uint64_t);
+slice_size2 = s->l2_slice_size * l2_entry_size(s);
 n_slices = s->cluster_size / slice_size2;
 
 trace_qcow2_l2_allocate_get_empty(bs, l1_index);
@@ -365,7 +365,7 @@ fail:
 }
 s->l1_table[l1_index] = old_l2_offset;
 if (l2_offset > 0) {
-qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
+qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s),
 QCOW2_DISCARD_ALWAYS);
 }
 return ret;
@@ -708,7 +708,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t 
offset,
 
 /* Then decrease the refcount of the old table */
 if (l2_offset) {
-qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
+qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s),
 QCOW2_DISCARD_OTHER);
 }
 
@@ -1883,7 +1883,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState 
*bs, uint64_t *l1_table,
 int ret;
 int i, j;
 
-slice_size2 = s->l2_slice_size * sizeof(uint64_t);
+slice_size2 = s->l2_slice_size * l2_entry_size(s);
 n_slices = s->cluster_size / slice_size2;
 
 if (!is_active_l1) {
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 84fe02d388..621318447d 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1253,7 +1253,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
 l2_slice = NULL;
 l1_table = NULL;
 l1_size2 = l1_size * sizeof(uint64_t);
-slice_size2 = s->l2_slice_size * sizeof(uint64_t);
+slice_size2 = s->l2_slice_size * l2_entry_size(s);
 n_slices = s->cluster_size / slice_size2;
 
 s->cache_discards = true;
@@ -1604,7 +1604,7 @@ static int check_refcounts_l2(BlockDriverState *bs, 
BdrvCheckResult *res,
 int i, l2_size, nb_csectors, ret;
 
 /* Read L2 table from disk */
-l2_size = s->l2_size * sizeof(uint64_t);
+l2_size = s->l2_size * l2_entry_size(s);
 l2_table = g_malloc(l2_size);
 
 ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size);
@@ -1679,15 +1679,16 @@ static int check_refcounts_l2(BlockDriverState *bs, 
BdrvCheckResult *res,
 fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
 offset);
 if (fix & BDRV_FIX_ERRORS) {
+int idx = i * (l2_entry_size(s) / sizeof(uint64_t));
 uint64_t l2e_offset =
-l2_offset + (uint64_t)i * sizeof(uint64_t);
+l2_offset + (uint64_t)i * l2_entry_size(s);
 int ign = active ? QCOW2_OL_ACTIVE_L2 :
QCOW2_OL_INACTIVE_L2;
 
 l2_entry = QCOW_OFLAG_ZERO;
 set_l2_entry(s, l2_table, i, l2_entry);
 ret = qcow2_pre_write_overlap_check(bs, ign,
-l2e_offset, sizeof(uint64_t), false);
+l2e_offset, l2_entry_size(s), false);
 if (ret < 0) {
 fprintf(stderr, "ERROR: Overlap check failed\n");
 res->check_errors++;
@@ -1697,7 +1698,8 @@ static int 

[RFC PATCH v2 18/26] qcow2: Add subcluster support to expand_zero_clusters_in_l1()

2019-10-26 Thread Alberto Garcia
Two changes are needed in order to add subcluster support to this
function: deallocated clusters must have their bitmaps cleared, and
expanded clusters must have all the "subcluster allocated" bits set.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index aa3eb727a5..62f2a9fcc0 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -2036,6 +2036,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState 
*bs, uint64_t *l1_table,
 /* not backed; therefore we can simply deallocate the
  * cluster */
 set_l2_entry(s, l2_slice, j, 0);
+set_l2_bitmap(s, l2_slice, j, 0);
 l2_dirty = true;
 continue;
 }
@@ -2102,6 +2103,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState 
*bs, uint64_t *l1_table,
 } else {
 set_l2_entry(s, l2_slice, j, offset);
 }
+set_l2_bitmap(s, l2_slice, j, QCOW_L2_BITMAP_ALL_ALLOC);
 l2_dirty = true;
 }
 
-- 
2.20.1




[RFC PATCH v2 14/26] qcow2: Add subcluster support to qcow2_get_cluster_offset()

2019-10-26 Thread Alberto Garcia
The logic of this function remains pretty much the same, except that
it uses count_contiguous_subclusters(), which combines the logic of
count_contiguous_clusters() / count_contiguous_clusters_unallocated()
and checks individual subclusters.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 111 --
 1 file changed, 52 insertions(+), 59 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 990bc070af..e67559152f 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -372,66 +372,51 @@ fail:
 }
 
 /*
- * Checks how many clusters in a given L2 slice are contiguous in the image
- * file. As soon as one of the flags in the bitmask stop_flags changes compared
- * to the first cluster, the search is stopped and the cluster is not counted
- * as contiguous. (This allows it, for example, to stop at the first compressed
- * cluster which may require a different handling)
+ * Return the number of contiguous subclusters of the exact same type
+ * in a given L2 slice, starting from cluster @l2_index, subcluster
+ * @sc_index. At most @nb_clusters are checked. Allocated clusters are
+ * also required to be contiguous in the image file.
  */
-static int count_contiguous_clusters(BlockDriverState *bs, int nb_clusters,
-int cluster_size, uint64_t *l2_slice, int l2_index, uint64_t 
stop_flags)
+static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters,
+unsigned sc_index, uint64_t *l2_slice,
+int l2_index)
 {
 BDRVQcow2State *s = bs->opaque;
-int i;
-QCow2ClusterType first_cluster_type;
-uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
-uint64_t first_entry = get_l2_entry(s, l2_slice, l2_index);
-uint64_t offset = first_entry & mask;
-
-first_cluster_type = qcow2_get_cluster_type(bs, first_entry);
-if (first_cluster_type == QCOW2_CLUSTER_UNALLOCATED) {
-return 0;
+int i, j, count = 0;
+uint64_t l2_entry = get_l2_entry(s, l2_slice, l2_index);
+uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index);
+uint64_t expected_offset = l2_entry & L2E_OFFSET_MASK;
+bool check_offset = true;
+QCow2ClusterType type =
+qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_index);
+
+assert(type != QCOW2_CLUSTER_INVALID); /* The caller should check this */
+
+if (type == QCOW2_CLUSTER_COMPRESSED) {
+return 1; /* Compressed clusters are always counted one by one */
 }
 
-/* must be allocated */
-assert(first_cluster_type == QCOW2_CLUSTER_NORMAL ||
-   first_cluster_type == QCOW2_CLUSTER_ZERO_ALLOC);
-
-for (i = 0; i < nb_clusters; i++) {
-uint64_t l2_entry = get_l2_entry(s, l2_slice, l2_index + i) & mask;
-if (offset + (uint64_t) i * cluster_size != l2_entry) {
-break;
-}
+if (type == QCOW2_CLUSTER_UNALLOCATED || type == QCOW2_CLUSTER_ZERO_PLAIN) 
{
+check_offset = false;
 }
 
-return i;
-}
-
-/*
- * Checks how many consecutive unallocated clusters in a given L2
- * slice have the same cluster type.
- */
-static int count_contiguous_clusters_unallocated(BlockDriverState *bs,
- int nb_clusters,
- uint64_t *l2_slice,
- int l2_index,
- QCow2ClusterType wanted_type)
-{
-BDRVQcow2State *s = bs->opaque;
-int i;
-
-assert(wanted_type == QCOW2_CLUSTER_ZERO_PLAIN ||
-   wanted_type == QCOW2_CLUSTER_UNALLOCATED);
 for (i = 0; i < nb_clusters; i++) {
-uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i);
-QCow2ClusterType type = qcow2_get_cluster_type(bs, entry);
-
-if (type != wanted_type) {
-break;
+l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
+l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
+if (check_offset && expected_offset != (l2_entry & L2E_OFFSET_MASK)) {
+goto out;
+}
+for (j = (i == 0) ? sc_index : 0; j < s->subclusters_per_cluster; j++) 
{
+if (qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, j) != type) 
{
+goto out;
+}
+count++;
 }
+expected_offset += s->cluster_size;
 }
 
-return i;
+out:
+return count;
 }
 
 static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
@@ -514,8 +499,8 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t 
offset,
  unsigned int *bytes, uint64_t *cluster_offset)
 {
 BDRVQcow2State *s = bs->opaque;
-unsigned int l2_index;
-uint64_t l1_index, l2_offset, *l2_slice;
+unsigned int l2_index, sc_index;
+uint64_t l1_index, l2_offset, *l2_slice, l2_bitmap;
 int c;
 

[RFC PATCH v2 22/26] qcow2: Add subcluster support to handle_alloc_space()

2019-10-26 Thread Alberto Garcia
The bdrv_co_pwrite_zeroes() call here fills complete clusters with
zeroes, but it can happen that some subclusters are not part of the
write request or the copy-on-write. This patch makes sure that only
the affected subclusters are overwritten.

A potential improvement would be to also fill with zeroes the other
subclusters if we can guarantee that we are not overwriting existing
data. However this would waste more disk space, so we should first
evaluate if it's really worth doing.

Signed-off-by: Alberto Garcia 
---
 block/qcow2.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 0261e87709..01322ca449 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2304,6 +2304,9 @@ static int handle_alloc_space(BlockDriverState *bs, 
QCowL2Meta *l2meta)
 
 for (m = l2meta; m != NULL; m = m->next) {
 int ret;
+uint64_t start_offset = m->alloc_offset + m->cow_start.offset;
+uint64_t nb_bytes = m->cow_end.offset + m->cow_end.nb_bytes -
+m->cow_start.offset;
 
 if (!m->cow_start.nb_bytes && !m->cow_end.nb_bytes) {
 continue;
@@ -2318,16 +2321,14 @@ static int handle_alloc_space(BlockDriverState *bs, 
QCowL2Meta *l2meta)
  * efficiently zero out the whole clusters
  */
 
-ret = qcow2_pre_write_overlap_check(bs, 0, m->alloc_offset,
-m->nb_clusters * s->cluster_size,
+ret = qcow2_pre_write_overlap_check(bs, 0, start_offset, nb_bytes,
 true);
 if (ret < 0) {
 return ret;
 }
 
 BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_SPACE);
-ret = bdrv_co_pwrite_zeroes(s->data_file, m->alloc_offset,
-m->nb_clusters * s->cluster_size,
+ret = bdrv_co_pwrite_zeroes(s->data_file, start_offset, nb_bytes,
 BDRV_REQ_NO_FALLBACK);
 if (ret < 0) {
 if (ret != -ENOTSUP && ret != -EAGAIN) {
-- 
2.20.1




[RFC PATCH v2 06/26] qcow2: Add dummy has_subclusters() function

2019-10-26 Thread Alberto Garcia
This function will be used by the qcow2 code to check if an image has
subclusters or not.

At the moment this simply returns false. Once all patches needed for
subcluster support are ready then QEMU will be able to create and
read images with subclusters and this function will return the actual
value.

Signed-off-by: Alberto Garcia 
---
 block/qcow2.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/block/qcow2.h b/block/qcow2.h
index 940cd4c236..b3826b37c1 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -488,6 +488,12 @@ typedef enum QCow2MetadataOverlap {
 
 #define INV_OFFSET (-1ULL)
 
+static inline bool has_subclusters(BDRVQcow2State *s)
+{
+/* FIXME: Return false until this feature is complete */
+return false;
+}
+
 static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
 int idx)
 {
-- 
2.20.1




[RFC PATCH v2 21/26] qcow2: Clear the L2 bitmap when allocating a compressed cluster

2019-10-26 Thread Alberto Garcia
Compressed clusters always have the bitmap part of the extended L2
entry set to 0.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index acb7226e03..3ba8a98073 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -783,6 +783,7 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState 
*bs,
 BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
 qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
 set_l2_entry(s, l2_slice, l2_index, cluster_offset);
+set_l2_bitmap(s, l2_slice, l2_index, 0);
 qcow2_cache_put(s->l2_table_cache, (void **) _slice);
 
 *host_offset = cluster_offset & s->cluster_offset_mask;
-- 
2.20.1




[RFC PATCH v2 13/26] qcow2: Add subcluster support to calculate_l2_meta()

2019-10-26 Thread Alberto Garcia
If an image has subclusters then there are more copy-on-write
scenarios that we need to consider. Let's say we have a write request
from the middle of subcluster #3 until the end of the cluster:

   - If the cluster is new, then subclusters #0 to #3 from the old
 cluster must be copied into the new one.

   - If the cluster is new but the old cluster was unallocated, then
 only subcluster #3 needs copy-on-write. #0 to #2 are marked as
 unallocated in the bitmap of the new L2 entry.

   - If we are overwriting an old cluster and subcluster #3 is
 unallocated or has the all-zeroes bit set then we need
 copy-on-write on subcluster #3.

   - If we are overwriting an old cluster and subcluster #3 was
 allocated then there is no need to copy-on-write.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 136 +-
 1 file changed, 108 insertions(+), 28 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 1f509bda15..990bc070af 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1034,14 +1034,16 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, 
QCowL2Meta *m)
  * If @keep_old is true it means that the clusters were already
  * allocated and will be overwritten. If false then the clusters are
  * new and we have to decrease the reference count of the old ones.
+ *
+ * Returns 1 on success, -errno on failure.
  */
-static void calculate_l2_meta(BlockDriverState *bs, uint64_t host_offset,
-  uint64_t guest_offset, uint64_t bytes,
-  uint64_t *l2_slice, QCowL2Meta **m, bool 
keep_old)
+static int calculate_l2_meta(BlockDriverState *bs, uint64_t host_offset,
+ uint64_t guest_offset, uint64_t bytes,
+ uint64_t *l2_slice, QCowL2Meta **m, bool keep_old)
 {
 BDRVQcow2State *s = bs->opaque;
-int l2_index = offset_to_l2_slice_index(s, guest_offset);
-uint64_t l2_entry;
+int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset);
+uint64_t l2_entry, l2_bitmap;
 unsigned cow_start_from, cow_end_to;
 unsigned cow_start_to = offset_into_cluster(s, guest_offset);
 unsigned cow_end_from = cow_start_to + bytes;
@@ -1049,38 +1051,108 @@ static void calculate_l2_meta(BlockDriverState *bs, 
uint64_t host_offset,
 QCowL2Meta *old_m = *m;
 QCow2ClusterType type;
 
-/* Return if there's no COW (all clusters are normal and we keep them) */
+/* Return if there's no COW (all subclusters are normal and we are
+ * keeping the clusters) */
 if (keep_old) {
+unsigned first_sc = cow_start_to / s->subcluster_size;
+unsigned last_sc = (cow_end_from - 1) / s->subcluster_size;
 int i;
-for (i = 0; i < nb_clusters; i++) {
-l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
-if (qcow2_get_cluster_type(bs, l2_entry) != QCOW2_CLUSTER_NORMAL) {
+for (i = first_sc; i <= last_sc; i++) {
+unsigned c = i / s->subclusters_per_cluster;
+unsigned sc = i % s->subclusters_per_cluster;
+l2_entry = get_l2_entry(s, l2_slice, l2_index + c);
+l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + c);
+type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc);
+if (type == QCOW2_CLUSTER_INVALID) {
+l2_index += c; /* Point to the invalid entry */
+goto fail;
+}
+if (type != QCOW2_CLUSTER_NORMAL) {
 break;
 }
 }
-if (i == nb_clusters) {
-return;
+if (i == last_sc + 1) {
+return 1;
 }
 }
 
 /* Get the L2 entry from the first cluster */
 l2_entry = get_l2_entry(s, l2_slice, l2_index);
-type = qcow2_get_cluster_type(bs, l2_entry);
+l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index);
+sc_index = offset_to_sc_index(s, guest_offset);
+type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_index);
 
-if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
-cow_start_from = cow_start_to;
+if (type == QCOW2_CLUSTER_INVALID) {
+goto fail;
+}
+
+if (!keep_old) {
+switch (type) {
+case QCOW2_CLUSTER_NORMAL:
+case QCOW2_CLUSTER_COMPRESSED:
+case QCOW2_CLUSTER_ZERO_ALLOC:
+case QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER:
+cow_start_from = 0;
+break;
+case QCOW2_CLUSTER_ZERO_PLAIN:
+case QCOW2_CLUSTER_UNALLOCATED:
+cow_start_from = sc_index << s->subcluster_bits;
+break;
+default:
+g_assert_not_reached();
+}
 } else {
-cow_start_from = 0;
+switch (type) {
+case QCOW2_CLUSTER_NORMAL:
+cow_start_from = cow_start_to;
+break;
+case QCOW2_CLUSTER_ZERO_ALLOC:
+case 

[RFC PATCH v2 24/26] qcow2: Add the 'extended_l2' option and the QCOW2_INCOMPAT_EXTL2 bit

2019-10-26 Thread Alberto Garcia
Now that the implementation of subclusters is complete we can finally
add the necessary options to create and read images with this feature,
which we call "extended L2 entries".

Signed-off-by: Alberto Garcia 
---
 block/qcow2.c|  46 ++
 block/qcow2.h|   8 ++-
 include/block/block_int.h|   1 +
 qapi/block-core.json |   6 ++
 tests/qemu-iotests/031.out   |   8 +--
 tests/qemu-iotests/036.out   |   4 +-
 tests/qemu-iotests/049.out   | 102 +++
 tests/qemu-iotests/060.out   |   1 +
 tests/qemu-iotests/061.out   |  20 +++---
 tests/qemu-iotests/065   |  18 --
 tests/qemu-iotests/082.out   |  48 ---
 tests/qemu-iotests/085.out   |  38 ++--
 tests/qemu-iotests/144.out   |   4 +-
 tests/qemu-iotests/182.out   |   2 +-
 tests/qemu-iotests/185.out   |   8 +--
 tests/qemu-iotests/198.out   |   2 +
 tests/qemu-iotests/206.out   |   4 ++
 tests/qemu-iotests/242.out   |   5 ++
 tests/qemu-iotests/255.out   |   8 +--
 tests/qemu-iotests/common.filter |   1 +
 20 files changed, 224 insertions(+), 110 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 537569ce88..b1fa7ab5da 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1347,6 +1347,12 @@ static int coroutine_fn qcow2_do_open(BlockDriverState 
*bs, QDict *options,
 s->subcluster_size = s->cluster_size / s->subclusters_per_cluster;
 s->subcluster_bits = ctz32(s->subcluster_size);
 
+if (s->subcluster_size < (1 << MIN_CLUSTER_BITS)) {
+error_setg(errp, "Unsupported subcluster size: %d", 
s->subcluster_size);
+ret = -EINVAL;
+goto fail;
+}
+
 /* Check support for various header values */
 if (header.refcount_order > 6) {
 error_setg(errp, "Reference count entry width too large; may not "
@@ -2806,6 +2812,11 @@ int qcow2_update_header(BlockDriverState *bs)
 .bit  = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
 .name = "lazy refcounts",
 },
+{
+.type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
+.bit  = QCOW2_INCOMPAT_EXTL2_BITNR,
+.name = "extended L2 entries",
+},
 };
 
 ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,
@@ -3271,6 +3282,27 @@ qcow2_co_create(BlockdevCreateOptions *create_options, 
Error **errp)
 goto out;
 }
 
+if (!qcow2_opts->has_extended_l2) {
+qcow2_opts->extended_l2 = false;
+}
+if (qcow2_opts->extended_l2) {
+unsigned min_cluster_size =
+(1 << MIN_CLUSTER_BITS) * QCOW_MAX_SUBCLUSTERS_PER_CLUSTER;
+if (version < 3) {
+error_setg(errp, "Extended L2 entries are only supported with "
+   "compatibility level 1.1 and above (use version=v3 or "
+   "greater)");
+ret = -EINVAL;
+goto out;
+}
+if (cluster_size < min_cluster_size) {
+error_setg(errp, "Extended L2 entries are only supported with "
+   "cluster sizes of at least %u bytes", min_cluster_size);
+ret = -EINVAL;
+goto out;
+}
+}
+
 if (!qcow2_opts->has_preallocation) {
 qcow2_opts->preallocation = PREALLOC_MODE_OFF;
 }
@@ -3392,6 +3424,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, 
Error **errp)
 cpu_to_be64(QCOW2_AUTOCLEAR_DATA_FILE_RAW);
 }
 
+if (qcow2_opts->extended_l2) {
+header->incompatible_features |=
+cpu_to_be64(QCOW2_INCOMPAT_EXTL2);
+}
+
 ret = blk_pwrite(blk, 0, header, cluster_size, 0);
 g_free(header);
 if (ret < 0) {
@@ -3569,6 +3606,7 @@ static int coroutine_fn qcow2_co_create_opts(const char 
*filename, QemuOpts *opt
 { BLOCK_OPT_BACKING_FMT,"backing-fmt" },
 { BLOCK_OPT_CLUSTER_SIZE,   "cluster-size" },
 { BLOCK_OPT_LAZY_REFCOUNTS, "lazy-refcounts" },
+{ BLOCK_OPT_EXTL2,  "extended-l2" },
 { BLOCK_OPT_REFCOUNT_BITS,  "refcount-bits" },
 { BLOCK_OPT_ENCRYPT,BLOCK_OPT_ENCRYPT_FORMAT },
 { BLOCK_OPT_COMPAT_LEVEL,   "version" },
@@ -4772,6 +4810,8 @@ static ImageInfoSpecific 
*qcow2_get_specific_info(BlockDriverState *bs,
 .corrupt= s->incompatible_features &
   QCOW2_INCOMPAT_CORRUPT,
 .has_corrupt= true,
+.has_extended_l2= true,
+.extended_l2= has_subclusters(s),
 .refcount_bits  = s->refcount_bits,
 .has_bitmaps= !!bitmaps,
 .bitmaps= bitmaps,
@@ -5365,6 +5405,12 @@ static QemuOptsList qcow2_create_opts = {
 .help = "Postpone refcount updates",
 .def_value_str = "off"
 },
+{
+.name = 

[PULL 17/25] libqos: access VIRTIO 1.0 vring in little-endian

2019-10-26 Thread Michael S. Tsirkin
From: Stefan Hajnoczi 

VIRTIO 1.0 uses little-endian for the vring.  Legacy VIRTIO uses guest
endianness.  Adjust the code to handle both.

Note that qvirtio_readq() is not defined because it has no users.  All
the other accessors are really needed.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Thomas Huth 
Message-Id: <20191023100425.12168-10-stefa...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 tests/libqos/virtio-mmio.c |   1 +
 tests/libqos/virtio-pci.c  |   1 +
 tests/libqos/virtio.c  | 131 +++--
 tests/libqos/virtio.h  |   4 +-
 tests/virtio-blk-test.c|   8 +--
 5 files changed, 106 insertions(+), 39 deletions(-)

diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c
index 78066e6e05..4db1f1b8bc 100644
--- a/tests/libqos/virtio-mmio.c
+++ b/tests/libqos/virtio-mmio.c
@@ -157,6 +157,7 @@ static QVirtQueue 
*qvirtio_mmio_virtqueue_setup(QVirtioDevice *d,
 uint64_t addr;
 
 vq = g_malloc0(sizeof(*vq));
+vq->vdev = d;
 qvirtio_mmio_queue_select(d, index);
 qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_ALIGN, 
dev->page_size);
 
diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
index 1b6b760fc6..7ecf5d0a52 100644
--- a/tests/libqos/virtio-pci.c
+++ b/tests/libqos/virtio-pci.c
@@ -217,6 +217,7 @@ static QVirtQueue 
*qvirtio_pci_virtqueue_setup(QVirtioDevice *d,
 feat = qvirtio_pci_get_guest_features(d);
 
 qvirtio_pci_queue_select(d, index);
+vqpci->vq.vdev = d;
 vqpci->vq.index = index;
 vqpci->vq.size = qvirtio_pci_get_queue_size(d);
 vqpci->vq.free_head = 0;
diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c
index fa597c2481..9aa360620c 100644
--- a/tests/libqos/virtio.c
+++ b/tests/libqos/virtio.c
@@ -8,11 +8,68 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/bswap.h"
 #include "libqtest.h"
 #include "libqos/virtio.h"
 #include "standard-headers/linux/virtio_config.h"
 #include "standard-headers/linux/virtio_ring.h"
 
+/*
+ * qtest_readX/writeX() functions transfer host endian from/to guest endian.
+ * This works great for Legacy VIRTIO devices where we need guest endian
+ * accesses.  For VIRTIO 1.0 the vring is little-endian so the automatic guest
+ * endianness conversion is not wanted.
+ *
+ * The following qvirtio_readX/writeX() functions handle Legacy and VIRTIO 1.0
+ * accesses seamlessly.
+ */
+static uint16_t qvirtio_readw(QVirtioDevice *d, QTestState *qts, uint64_t addr)
+{
+uint16_t val = qtest_readw(qts, addr);
+
+if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
+val = bswap16(val);
+}
+return val;
+}
+
+static uint32_t qvirtio_readl(QVirtioDevice *d, QTestState *qts, uint64_t addr)
+{
+uint32_t val = qtest_readl(qts, addr);
+
+if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
+val = bswap32(val);
+}
+return val;
+}
+
+static void qvirtio_writew(QVirtioDevice *d, QTestState *qts,
+   uint64_t addr, uint16_t val)
+{
+if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
+val = bswap16(val);
+}
+qtest_writew(qts, addr, val);
+}
+
+static void qvirtio_writel(QVirtioDevice *d, QTestState *qts,
+   uint64_t addr, uint32_t val)
+{
+if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
+val = bswap32(val);
+}
+qtest_writel(qts, addr, val);
+}
+
+static void qvirtio_writeq(QVirtioDevice *d, QTestState *qts,
+   uint64_t addr, uint64_t val)
+{
+if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
+val = bswap64(val);
+}
+qtest_writeq(qts, addr, val);
+}
+
 uint8_t qvirtio_config_readb(QVirtioDevice *d, uint64_t addr)
 {
 g_assert_true(d->features_negotiated);
@@ -189,23 +246,23 @@ void qvring_init(QTestState *qts, const QGuestAllocator 
*alloc, QVirtQueue *vq,
 
 for (i = 0; i < vq->size - 1; i++) {
 /* vq->desc[i].addr */
-qtest_writeq(qts, vq->desc + (16 * i), 0);
+qvirtio_writeq(vq->vdev, qts, vq->desc + (16 * i), 0);
 /* vq->desc[i].next */
-qtest_writew(qts, vq->desc + (16 * i) + 14, i + 1);
+qvirtio_writew(vq->vdev, qts, vq->desc + (16 * i) + 14, i + 1);
 }
 
 /* vq->avail->flags */
-qtest_writew(qts, vq->avail, 0);
+qvirtio_writew(vq->vdev, qts, vq->avail, 0);
 /* vq->avail->idx */
-qtest_writew(qts, vq->avail + 2, 0);
+qvirtio_writew(vq->vdev, qts, vq->avail + 2, 0);
 /* vq->avail->used_event */
-qtest_writew(qts, vq->avail + 4 + (2 * vq->size), 0);
+qvirtio_writew(vq->vdev, qts, vq->avail + 4 + (2 * vq->size), 0);
 
 /* vq->used->flags */
-qtest_writew(qts, vq->used, 0);
+qvirtio_writew(vq->vdev, qts, vq->used, 0);
 /* vq->used->avail_event */
-qtest_writew(qts, vq->used + 2 + sizeof(struct vring_used_elem) * 

[RFC PATCH v2 26/26] iotests: Add tests for qcow2 images with extended L2 entries

2019-10-26 Thread Alberto Garcia
Signed-off-by: Alberto Garcia 
---
 tests/qemu-iotests/271 | 235 +
 tests/qemu-iotests/271.out | 183 +
 tests/qemu-iotests/group   |   1 +
 3 files changed, 419 insertions(+)
 create mode 100755 tests/qemu-iotests/271
 create mode 100644 tests/qemu-iotests/271.out

diff --git a/tests/qemu-iotests/271 b/tests/qemu-iotests/271
new file mode 100755
index 00..c49433cdc9
--- /dev/null
+++ b/tests/qemu-iotests/271
@@ -0,0 +1,235 @@
+#!/bin/bash
+#
+# Test qcow2 images with extended L2 entries
+#
+# Copyright (C) 2019 Igalia, S.L.
+# Author: Alberto Garcia 
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+#
+
+# creator
+owner=be...@igalia.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1   # failure is the default!
+
+_cleanup()
+{
+   _cleanup_test_img
+rm -f "$TEST_IMG.raw"
+rm -f "$TEST_IMG.backing"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto file nfs
+_supported_os Linux
+
+IMGOPTS="extended_l2=on"
+l2_offset=262144 # 0x4
+
+_verify_img()
+{
+$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.raw" | grep -v 'Images are 
identical'
+$QEMU_IMG check "$TEST_IMG" | _filter_qemu_img_check | \
+grep -v 'No errors were found on the image'
+}
+
+_read_l2_entry()
+{
+entry_no=$1
+nentries=$2
+offset=$(($l2_offset + $entry_no * 16))
+length=$((nentries * 16))
+$QEMU_IO -f raw -c "read -v $offset $length" "$TEST_IMG" | _filter_qemu_io 
| head -n -2
+}
+
+_test_write()
+{
+cmd="$1"
+l2_entry_idx="$2"
+l2_entry_num="$3"
+raw_cmd=`echo $1 | sed s/-c//` # Raw images don't support -c
+echo "$cmd"
+$QEMU_IO -c "$cmd" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "$raw_cmd" -f raw "$TEST_IMG.raw" | _filter_qemu_io
+_verify_img
+if [ -n "$l2_entry_idx" ]; then
+_read_l2_entry "$l2_entry_idx" "$l2_entry_num"
+fi
+}
+
+_reset_img()
+{
+$QEMU_IMG create -f raw "$TEST_IMG.raw" 1M | _filter_img_create
+if [ "$use_backing_file" = "yes" ]; then
+$QEMU_IMG create -f raw "$TEST_IMG.backing" 1M | _filter_img_create
+$QEMU_IO -c 'write -q -P 0xFF 0 1M' -f raw "$TEST_IMG.backing" | 
_filter_qemu_io
+$QEMU_IO -c 'write -q -P 0xFF 0 1M' -f raw "$TEST_IMG.raw" | 
_filter_qemu_io
+_make_test_img -b "$TEST_IMG.backing" 1M
+else
+_make_test_img 1M
+fi
+}
+
+# Test that writing to an image with subclusters produces the expected
+# results, in images with and without backing files
+for use_backing_file in yes no; do
+echo
+echo "### Standard write tests (backing file: $use_backing_file) ###"
+echo
+_reset_img
+### Write subcluster #0 (beginning of subcluster) ###
+_test_write 'write -q -P 1 0 1k' 0 1
+
+### Write subcluster #1 (middle of subcluster) ###
+_test_write 'write -q -P 2 3k 512' 0 1
+
+### Write subcluster #2 (end of subcluster) ###
+_test_write 'write -q -P 3 5k 1k' 0 1
+
+### Write subcluster #3 (full subcluster) ###
+_test_write 'write -q -P 4 6k 2k' 0 1
+
+### Write subclusters #4-6 (full subclusters) ###
+_test_write 'write -q -P 5 8k 6k' 0 1
+
+### Write subclusters #7-9 (partial subclusters) ###
+_test_write 'write -q -P 6 15k 4k' 0 1
+
+### Write subcluster #16 (partial subcluster) ###
+_test_write 'write -q -P 7 32k 1k' 0 2
+
+### Write subcluster #31-#34 (cluster overlap) ###
+_test_write 'write -q -P 8 63k 4k' 0 2
+
+### Zero subcluster #1 (TODO: use the "all zeros" bit)
+_test_write 'write -q -z 2k 2k' 0 1
+
+### Zero cluster #0
+_test_write 'write -q -z 0 64k' 0 1
+
+### Fill cluster #0 with data
+_test_write 'write -q -P 9 0 64k' 0 1
+
+### Zero and unmap half of cluster #0 (this won't unmap it)
+_test_write 'write -q -z -u 0 32k' 0 1
+
+### Zero and unmap cluster #0
+_test_write 'write -q -z -u 0 64k' 0 1
+
+### Write subcluster #2 (middle of subcluster)
+_test_write 'write -q -P 10 3k 512' 0 1
+
+### Fill cluster #0 with data
+_test_write 'write -q -P 11 0 64k' 0 1
+
+### Discard cluster #0
+_test_write 'discard -q 0 64k' 0 1
+
+### Write compressed data to cluster #0
+_test_write 'write -q -c 

Re: [RFC PATCH 00/23] Add subcluster allocation to qcow2

2019-10-26 Thread Alberto Garcia
On Wed 23 Oct 2019 12:39:14 PM CEST, Vladimir Sementsov-Ogievskiy wrote:
> Hi!
>
> This is very interesting! Could you please export a branch to look at,
> as patches can't be applied on master now :(

I just sent a new version with some updates and rebased on top of the
current master.

Berto



[RFC PATCH v2 03/26] qcow2: Process QCOW2_CLUSTER_ZERO_ALLOC clusters in handle_copied()

2019-10-26 Thread Alberto Garcia
When writing to a qcow2 file there are two functions that take a
virtual offset and return a host offset, possibly allocating new
clusters if necessary:

   - handle_copied() looks for normal data clusters that are already
 allocated and have a reference count of 1. In those clusters we
 can simply write the data and there is no need to perform any
 copy-on-write.

   - handle_alloc() looks for clusters that do need copy-on-write,
 either because they haven't been allocated yet, because their
 reference count is != 1 or because they are ZERO_ALLOC clusters.

The ZERO_ALLOC case is a bit special because those are clusters that
are already allocated and they could perfectly be dealt with in
handle_copied() (as long as copy-on-write is performed when required).

In fact, there is extra code specifically for them in handle_alloc()
that tries to reuse the existing allocation if possible and frees them
otherwise.

This patch changes the handling of ZERO_ALLOC clusters so the
semantics of these two functions are now like this:

   - handle_copied() looks for clusters that are already allocated and
 which we can overwrite (NORMAL and ZERO_ALLOC clusters with a
 reference count of 1).

   - handle_alloc() looks for clusters for which we need a new
 allocation (all other cases).

One importante difference after this change is that clusters found in
handle_copied() may now require copy-on-write, but this will be anyway
necessary once we add support for subclusters.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 177 +++---
 1 file changed, 96 insertions(+), 81 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index aa1010a515..ee6b46f917 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1021,7 +1021,8 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, 
QCowL2Meta *m)
 
 /*
  * For a given write request, create a new QCowL2Meta structure and
- * add it to @m.
+ * add it to @m. If the write request does not need copy-on-write or
+ * changes to the L2 metadata then this function does nothing.
  *
  * @host_offset points to the beginning of the first cluster.
  *
@@ -1034,15 +1035,51 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, 
QCowL2Meta *m)
  */
 static void calculate_l2_meta(BlockDriverState *bs, uint64_t host_offset,
   uint64_t guest_offset, uint64_t bytes,
-  QCowL2Meta **m, bool keep_old)
+  uint64_t *l2_slice, QCowL2Meta **m, bool 
keep_old)
 {
 BDRVQcow2State *s = bs->opaque;
-unsigned cow_start_from = 0;
+int l2_index = offset_to_l2_slice_index(s, guest_offset);
+uint64_t l2_entry;
+unsigned cow_start_from, cow_end_to;
 unsigned cow_start_to = offset_into_cluster(s, guest_offset);
 unsigned cow_end_from = cow_start_to + bytes;
-unsigned cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
 unsigned nb_clusters = size_to_clusters(s, cow_end_from);
 QCowL2Meta *old_m = *m;
+QCow2ClusterType type;
+
+/* Return if there's no COW (all clusters are normal and we keep them) */
+if (keep_old) {
+int i;
+for (i = 0; i < nb_clusters; i++) {
+l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
+if (qcow2_get_cluster_type(bs, l2_entry) != QCOW2_CLUSTER_NORMAL) {
+break;
+}
+}
+if (i == nb_clusters) {
+return;
+}
+}
+
+/* Get the L2 entry from the first cluster */
+l2_entry = be64_to_cpu(l2_slice[l2_index]);
+type = qcow2_get_cluster_type(bs, l2_entry);
+
+if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
+cow_start_from = cow_start_to;
+} else {
+cow_start_from = 0;
+}
+
+/* Get the L2 entry from the last cluster */
+l2_entry = be64_to_cpu(l2_slice[l2_index + nb_clusters - 1]);
+type = qcow2_get_cluster_type(bs, l2_entry);
+
+if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
+cow_end_to = cow_end_from;
+} else {
+cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
+}
 
 *m = g_malloc0(sizeof(**m));
 **m = (QCowL2Meta) {
@@ -1068,18 +1105,18 @@ static void calculate_l2_meta(BlockDriverState *bs, 
uint64_t host_offset,
 QLIST_INSERT_HEAD(>cluster_allocs, *m, next_in_flight);
 }
 
-/* Returns true if writing to a cluster requires COW */
+/* Returns true if the cluster is unallocated or has refcount > 1 */
 static bool cluster_needs_cow(BlockDriverState *bs, uint64_t l2_entry)
 {
 switch (qcow2_get_cluster_type(bs, l2_entry)) {
 case QCOW2_CLUSTER_NORMAL:
+case QCOW2_CLUSTER_ZERO_ALLOC:
 if (l2_entry & QCOW_OFLAG_COPIED) {
 return false;
 }
 case QCOW2_CLUSTER_UNALLOCATED:
 case QCOW2_CLUSTER_COMPRESSED:
 case QCOW2_CLUSTER_ZERO_PLAIN:
-case QCOW2_CLUSTER_ZERO_ALLOC:
 return true;
 default:
 

[RFC PATCH v2 02/26] qcow2: Split cluster_needs_cow() out of count_cow_clusters()

2019-10-26 Thread Alberto Garcia
We are going to need it in other places.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 34 +++---
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 6c1dcdc781..aa1010a515 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1068,6 +1068,24 @@ static void calculate_l2_meta(BlockDriverState *bs, 
uint64_t host_offset,
 QLIST_INSERT_HEAD(>cluster_allocs, *m, next_in_flight);
 }
 
+/* Returns true if writing to a cluster requires COW */
+static bool cluster_needs_cow(BlockDriverState *bs, uint64_t l2_entry)
+{
+switch (qcow2_get_cluster_type(bs, l2_entry)) {
+case QCOW2_CLUSTER_NORMAL:
+if (l2_entry & QCOW_OFLAG_COPIED) {
+return false;
+}
+case QCOW2_CLUSTER_UNALLOCATED:
+case QCOW2_CLUSTER_COMPRESSED:
+case QCOW2_CLUSTER_ZERO_PLAIN:
+case QCOW2_CLUSTER_ZERO_ALLOC:
+return true;
+default:
+abort();
+}
+}
+
 /*
  * Returns the number of contiguous clusters that can be used for an allocating
  * write, but require COW to be performed (this includes yet unallocated space,
@@ -1080,25 +1098,11 @@ static int count_cow_clusters(BlockDriverState *bs, int 
nb_clusters,
 
 for (i = 0; i < nb_clusters; i++) {
 uint64_t l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
-QCow2ClusterType cluster_type = qcow2_get_cluster_type(bs, l2_entry);
-
-switch(cluster_type) {
-case QCOW2_CLUSTER_NORMAL:
-if (l2_entry & QCOW_OFLAG_COPIED) {
-goto out;
-}
+if (!cluster_needs_cow(bs, l2_entry)) {
 break;
-case QCOW2_CLUSTER_UNALLOCATED:
-case QCOW2_CLUSTER_COMPRESSED:
-case QCOW2_CLUSTER_ZERO_PLAIN:
-case QCOW2_CLUSTER_ZERO_ALLOC:
-break;
-default:
-abort();
 }
 }
 
-out:
 assert(i <= nb_clusters);
 return i;
 }
-- 
2.20.1




[RFC PATCH v2 11/26] qcow2: Add qcow2_get_subcluster_type()

2019-10-26 Thread Alberto Garcia
This function returns the type of an individual subcluster. If an
image does not have subclusters then this returns the exact same value
as qcow2_get_cluster_type().

The information in standard and extended L2 entries is encoded in a
slightly different way, but all existing QCow2ClusterType values are
also valid for subclusters and have the same meanings (although they
typically only apply to the requested subcluster).

There are two important exceptions to this:

  a) QCOW2_CLUSTER_COMPRESSED means that the whole cluster is
 compressed. We do not support compression at the subcluster
 level.

  b) QCOW2_CLUSTER_UNALLOCATED means that the cluster is unallocated,
 that is, the offset field of the L2 entry does not point to a
 host cluster. All subclusters are obviously unallocated too but
 any of them could be of type QCOW2_CLUSTER_ZERO_PLAIN.

In addition to that, extended L2 entries allow one new scenario where
the cluster is normally allocated but an individual subcluster is not.
This is very different from (b) and because of that this patch adds a
new value called QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER.

As a last thing, this patch adds QCOW2_CLUSTER_INVALID to detect the
cases where an L2 entry has a value that violates the spec. The caller
is responsible for handling these situations.

To prevent compatibility problems with images that have invalid values
but are currently being read by QEMU without causing side effects,
QCOW2_CLUSTER_INVALID is only returned for images with extended L2
entries.

Signed-off-by: Alberto Garcia 
---
 block/qcow2.h | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/block/qcow2.h b/block/qcow2.h
index 741c41c80f..23a2532ff2 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -77,6 +77,15 @@
 
 #define QCOW_MAX_SUBCLUSTERS_PER_CLUSTER 32
 
+/* The subcluster X [0..31] reads as zeroes */
+#define QCOW_OFLAG_SUB_ZERO(X)((1ULL << 63) >> (X))
+/* The subcluster X [0..31] is allocated */
+#define QCOW_OFLAG_SUB_ALLOC(X)   ((1ULL << 31) >> (X))
+/* L2 entry bitmap with all "read as zeroes" bits set */
+#define QCOW_L2_BITMAP_ALL_ZEROES 0xULL
+/* L2 entry bitmap with all allocation bits set */
+#define QCOW_L2_BITMAP_ALL_ALLOC  0xULL
+
 #define MIN_CLUSTER_BITS 9
 #define MAX_CLUSTER_BITS 21
 
@@ -438,10 +447,12 @@ typedef struct QCowL2Meta
 
 typedef enum QCow2ClusterType {
 QCOW2_CLUSTER_UNALLOCATED,
+QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER,
 QCOW2_CLUSTER_ZERO_PLAIN,
 QCOW2_CLUSTER_ZERO_ALLOC,
 QCOW2_CLUSTER_NORMAL,
 QCOW2_CLUSTER_COMPRESSED,
+QCOW2_CLUSTER_INVALID,
 } QCow2ClusterType;
 
 typedef enum QCow2MetadataOverlap {
@@ -621,6 +632,57 @@ static inline QCow2ClusterType 
qcow2_get_cluster_type(BlockDriverState *bs,
 }
 }
 
+/* In an image without subsclusters this returns the same value as
+ * qcow2_get_cluster_type() */
+static inline int qcow2_get_subcluster_type(BlockDriverState *bs,
+uint64_t l2_entry,
+uint64_t l2_bitmap,
+unsigned sc_index)
+{
+BDRVQcow2State *s = bs->opaque;
+QCow2ClusterType type = qcow2_get_cluster_type(bs, l2_entry);
+assert(sc_index < s->subclusters_per_cluster);
+
+if (has_subclusters(s)) {
+bool sc_zero  = l2_bitmap & QCOW_OFLAG_SUB_ZERO(sc_index);
+bool sc_alloc = l2_bitmap & QCOW_OFLAG_SUB_ALLOC(sc_index);
+switch (type) {
+case QCOW2_CLUSTER_COMPRESSED:
+if (l2_bitmap != 0) {
+return QCOW2_CLUSTER_INVALID;
+}
+break;
+case QCOW2_CLUSTER_ZERO_PLAIN:
+case QCOW2_CLUSTER_ZERO_ALLOC:
+return QCOW2_CLUSTER_INVALID;
+case QCOW2_CLUSTER_NORMAL:
+if (!sc_zero && !sc_alloc) {
+return QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER;
+} else if (!sc_zero && sc_alloc) {
+return QCOW2_CLUSTER_NORMAL;
+} else if (sc_zero && !sc_alloc) {
+return QCOW2_CLUSTER_ZERO_ALLOC;
+} else { /* sc_zero && sc_alloc */
+return QCOW2_CLUSTER_INVALID;
+}
+case QCOW2_CLUSTER_UNALLOCATED:
+if (!sc_zero && !sc_alloc) {
+return QCOW2_CLUSTER_UNALLOCATED;
+} else if (!sc_zero && sc_alloc) {
+return QCOW2_CLUSTER_INVALID;
+} else if (sc_zero && !sc_alloc) {
+return QCOW2_CLUSTER_ZERO_PLAIN;
+} else { /* sc_zero && sc_alloc */
+return QCOW2_CLUSTER_INVALID;
+}
+default:
+g_assert_not_reached();
+}
+}
+
+return type;
+}
+
 /* Check whether refcounts are eager or lazy */
 static inline bool qcow2_need_accurate_refcounts(BDRVQcow2State *s)
 {
-- 
2.20.1




[RFC PATCH v2 00/26] Add subcluster allocation to qcow2

2019-10-26 Thread Alberto Garcia
Hi,

here's the new version of the patches to add subcluster allocation
support to qcow2.

Please refer to the cover letter of the first version for a full
description of the patches:

   https://lists.gnu.org/archive/html/qemu-block/2019-10/msg00983.html

This version includes a few tests, but I'm planning to add more for
the next revision.

Berto

v2:
- Patch 12: Update after the changes in 88f468e546.
- Patch 21 (new): Clear the L2 bitmap when allocating a compressed
  cluster. Compressed clusters should have the bitmap all set to 0.
- Patch 24: Document the new fields in the QAPI documentation [Eric].
- Patch 25: Allow qcow2 preallocation with backing files.
- Patch 26: Add some tests for qcow2 images with extended L2 entries.

v1: https://lists.gnu.org/archive/html/qemu-block/2019-10/msg00983.html

Output of git backport-diff against v1:

Key:
[] : patches are identical
[] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/26:[] [-C] 'qcow2: Add calculate_l2_meta()'
002/26:[] [--] 'qcow2: Split cluster_needs_cow() out of 
count_cow_clusters()'
003/26:[] [--] 'qcow2: Process QCOW2_CLUSTER_ZERO_ALLOC clusters in 
handle_copied()'
004/26:[] [--] 'qcow2: Add get_l2_entry() and set_l2_entry()'
005/26:[] [--] 'qcow2: Document the Extended L2 Entries feature'
006/26:[] [--] 'qcow2: Add dummy has_subclusters() function'
007/26:[] [--] 'qcow2: Add subcluster-related fields to BDRVQcow2State'
008/26:[] [--] 'qcow2: Add offset_to_sc_index()'
009/26:[] [--] 'qcow2: Add l2_entry_size()'
010/26:[] [--] 'qcow2: Update get/set_l2_entry() and add 
get/set_l2_bitmap()'
011/26:[] [--] 'qcow2: Add qcow2_get_subcluster_type()'
012/26:[0005] [FC] 'qcow2: Handle QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER'
013/26:[] [--] 'qcow2: Add subcluster support to calculate_l2_meta()'
014/26:[] [--] 'qcow2: Add subcluster support to qcow2_get_cluster_offset()'
015/26:[] [--] 'qcow2: Add subcluster support to zero_in_l2_slice()'
016/26:[] [--] 'qcow2: Add subcluster support to discard_in_l2_slice()'
017/26:[] [--] 'qcow2: Add subcluster support to check_refcounts_l2()'
018/26:[] [--] 'qcow2: Add subcluster support to 
expand_zero_clusters_in_l1()'
019/26:[] [--] 'qcow2: Fix offset calculation in handle_dependencies()'
020/26:[] [--] 'qcow2: Update L2 bitmap in qcow2_alloc_cluster_link_l2()'
021/26:[down] 'qcow2: Clear the L2 bitmap when allocating a compressed cluster'
022/26:[] [--] 'qcow2: Add subcluster support to handle_alloc_space()'
023/26:[] [--] 'qcow2: Restrict qcow2_co_pwrite_zeroes() to full clusters 
only'
024/26:[0007] [FC] 'qcow2: Add the 'extended_l2' option and the 
QCOW2_INCOMPAT_EXTL2 bit'
025/26:[down] 'qcow2: Allow preallocation and backing files if extended_l2 is 
set'
026/26:[down] 'iotests: Add tests for qcow2 images with extended L2 entries'

Alberto Garcia (26):
  qcow2: Add calculate_l2_meta()
  qcow2: Split cluster_needs_cow() out of count_cow_clusters()
  qcow2: Process QCOW2_CLUSTER_ZERO_ALLOC clusters in handle_copied()
  qcow2: Add get_l2_entry() and set_l2_entry()
  qcow2: Document the Extended L2 Entries feature
  qcow2: Add dummy has_subclusters() function
  qcow2: Add subcluster-related fields to BDRVQcow2State
  qcow2: Add offset_to_sc_index()
  qcow2: Add l2_entry_size()
  qcow2: Update get/set_l2_entry() and add get/set_l2_bitmap()
  qcow2: Add qcow2_get_subcluster_type()
  qcow2: Handle QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER
  qcow2: Add subcluster support to calculate_l2_meta()
  qcow2: Add subcluster support to qcow2_get_cluster_offset()
  qcow2: Add subcluster support to zero_in_l2_slice()
  qcow2: Add subcluster support to discard_in_l2_slice()
  qcow2: Add subcluster support to check_refcounts_l2()
  qcow2: Add subcluster support to expand_zero_clusters_in_l1()
  qcow2: Fix offset calculation in handle_dependencies()
  qcow2: Update L2 bitmap in qcow2_alloc_cluster_link_l2()
  qcow2: Clear the L2 bitmap when allocating a compressed cluster
  qcow2: Add subcluster support to handle_alloc_space()
  qcow2: Restrict qcow2_co_pwrite_zeroes() to full clusters only
  qcow2: Add the 'extended_l2' option and the QCOW2_INCOMPAT_EXTL2 bit
  qcow2: Allow preallocation and backing files if extended_l2 is set
  iotests: Add tests for qcow2 images with extended L2 entries

 block/qcow2-cluster.c| 548 ---
 block/qcow2-refcount.c   |  38 ++-
 block/qcow2.c|  92 +-
 block/qcow2.h| 121 ++-
 docs/interop/qcow2.txt   |  68 +++-
 docs/qcow2-cache.txt |  19 +-
 include/block/block_int.h|   1 +
 qapi/block-core.json |   6 +
 tests/qemu-iotests/031.out   |   8 +-
 tests/qemu-iotests/036.out   |   4 +-
 tests/qemu-iotests/049.out   | 102 +++---
 

[RFC PATCH v2 15/26] qcow2: Add subcluster support to zero_in_l2_slice()

2019-10-26 Thread Alberto Garcia
Setting the QCOW_OFLAG_ZERO bit of the L2 entry is forbidden if an
image has subclusters. Instead, the individual 'all zeroes' bits must
be used.

Signed-off-by: Alberto Garcia 
---
 block/qcow2-cluster.c | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index e67559152f..3e4ba8d448 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1852,7 +1852,7 @@ static int zero_in_l2_slice(BlockDriverState *bs, 
uint64_t offset,
 assert(nb_clusters <= INT_MAX);
 
 for (i = 0; i < nb_clusters; i++) {
-uint64_t old_offset;
+uint64_t old_offset, l2_entry = 0;
 QCow2ClusterType cluster_type;
 
 old_offset = get_l2_entry(s, l2_slice, l2_index + i);
@@ -1869,12 +1869,18 @@ static int zero_in_l2_slice(BlockDriverState *bs, 
uint64_t offset,
 
 qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
 if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) {
-set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
 qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
 } else {
-uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i);
-set_l2_entry(s, l2_slice, l2_index + i, entry | QCOW_OFLAG_ZERO);
+l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
 }
+
+if (has_subclusters(s)) {
+set_l2_bitmap(s, l2_slice, l2_index + i, 
QCOW_L2_BITMAP_ALL_ZEROES);
+} else {
+l2_entry |= QCOW_OFLAG_ZERO;
+}
+
+set_l2_entry(s, l2_slice, l2_index + i, l2_entry);
 }
 
 qcow2_cache_put(s->l2_table_cache, (void **) _slice);
-- 
2.20.1




[RFC PATCH v2 07/26] qcow2: Add subcluster-related fields to BDRVQcow2State

2019-10-26 Thread Alberto Garcia
This patch adds the following new fields to BDRVQcow2State:

- subclusters_per_cluster: Number of subclusters in a cluster
- subcluster_size: The size of each subcluster, in bytes
- subcluster_bits: No. of bits so 1 << subcluster_bits = subcluster_size

Images without subclusters are treated as if they had exactly one,
with subcluster_size = cluster_size.

Signed-off-by: Alberto Garcia 
---
 block/qcow2.c | 5 +
 block/qcow2.h | 5 +
 2 files changed, 10 insertions(+)

diff --git a/block/qcow2.c b/block/qcow2.c
index 0bc69e6996..ed8b81c7b7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1342,6 +1342,11 @@ static int coroutine_fn qcow2_do_open(BlockDriverState 
*bs, QDict *options,
 }
 }
 
+s->subclusters_per_cluster =
+has_subclusters(s) ? QCOW_MAX_SUBCLUSTERS_PER_CLUSTER : 1;
+s->subcluster_size = s->cluster_size / s->subclusters_per_cluster;
+s->subcluster_bits = ctz32(s->subcluster_size);
+
 /* Check support for various header values */
 if (header.refcount_order > 6) {
 error_setg(errp, "Reference count entry width too large; may not "
diff --git a/block/qcow2.h b/block/qcow2.h
index b3826b37c1..278ca41314 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -75,6 +75,8 @@
 /* The cluster reads as all zeros */
 #define QCOW_OFLAG_ZERO (1ULL << 0)
 
+#define QCOW_MAX_SUBCLUSTERS_PER_CLUSTER 32
+
 #define MIN_CLUSTER_BITS 9
 #define MAX_CLUSTER_BITS 21
 
@@ -277,6 +279,9 @@ typedef struct BDRVQcow2State {
 int cluster_bits;
 int cluster_size;
 int l2_slice_size;
+int subcluster_bits;
+int subcluster_size;
+int subclusters_per_cluster;
 int l2_bits;
 int l2_size;
 int l1_size;
-- 
2.20.1




[RFC PATCH v2 05/26] qcow2: Document the Extended L2 Entries feature

2019-10-26 Thread Alberto Garcia
Subcluster allocation in qcow2 is implemented by extending the
existing L2 table entries and adding additional information to
indicate the allocation status of each subcluster.

This patch documents the changes to the qcow2 format and how they
affect the calculation of the L2 cache size.

Signed-off-by: Alberto Garcia 
---
 docs/interop/qcow2.txt | 68 --
 docs/qcow2-cache.txt   | 19 +++-
 2 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
index af5711e533..d34261f955 100644
--- a/docs/interop/qcow2.txt
+++ b/docs/interop/qcow2.txt
@@ -39,6 +39,9 @@ The first cluster of a qcow2 image contains the file header:
 as the maximum cluster size and won't be able to open 
images
 with larger cluster sizes.
 
+Note: if the image has Extended L2 Entries then 
cluster_bits
+must be at least 14 (i.e. 16384 byte clusters).
+
  24 - 31:   size
 Virtual disk size in bytes.
 
@@ -109,7 +112,12 @@ in the description of a field.
 An External Data File Name header extension may
 be present if this bit is set.
 
-Bits 3-63:  Reserved (set to 0)
+Bit 3:  Extended L2 Entries.  If this bit is set then
+L2 table entries use an extended format that
+allows subcluster-based allocation. See the
+Extended L2 Entries section for more details.
+
+Bits 4-63:  Reserved (set to 0)
 
  80 -  87:  compatible_features
 Bitmask of compatible features. An implementation can
@@ -437,7 +445,7 @@ cannot be relaxed without an incompatible layout change).
 Given an offset into the virtual disk, the offset into the image file can be
 obtained as follows:
 
-l2_entries = (cluster_size / sizeof(uint64_t))
+l2_entries = (cluster_size / sizeof(uint64_t))[*]
 
 l2_index = (offset / cluster_size) % l2_entries
 l1_index = (offset / cluster_size) / l2_entries
@@ -447,6 +455,8 @@ obtained as follows:
 
 return cluster_offset + (offset % cluster_size)
 
+[*] this changes if Extended L2 Entries are enabled, see next section
+
 L1 table entry:
 
 Bit  0 -  8:Reserved (set to 0)
@@ -487,7 +497,8 @@ Standard Cluster Descriptor:
 nor is data read from the backing file if the cluster is
 unallocated.
 
-With version 2, this is always 0.
+With version 2 or with extended L2 entries (see the next
+section), this is always 0.
 
  1 -  8:Reserved (set to 0)
 
@@ -524,6 +535,57 @@ file (except if bit 0 in the Standard Cluster Descriptor 
is set). If there is
 no backing file or the backing file is smaller than the image, they shall read
 zeros for all parts that are not covered by the backing file.
 
+== Extended L2 Entries ==
+
+An image uses Extended L2 Entries if bit 3 is set on the incompatible_features
+field of the header.
+
+In these images standard data clusters are divided into 32 subclusters of the
+same size. They are contiguous and start from the beginning of the cluster.
+Subclusters can be allocated independently and the L2 entry contains 
information
+indicating the status of each one of them. Compressed data clusters don't have
+subclusters so they are treated like in images without this feature.
+
+The size of an extended L2 entry is 128 bits so the number of entries per table
+is calculated using this formula:
+
+l2_entries = (cluster_size / (2 * sizeof(uint64_t)))
+
+The first 64 bits have the same format as the standard L2 table entry described
+in the previous section, with the exception of bit 0 of the standard cluster
+descriptor.
+
+The last 64 bits contain a subcluster allocation bitmap with this format:
+
+Subcluster Allocation Bitmap (for standard clusters):
+
+Bit  0 -  31:   Allocation status (one bit per subcluster)
+
+1: the subcluster is allocated. In this case the
+   host cluster offset field must contain a valid
+   offset.
+0: the subcluster is not allocated. In this case
+   read requests shall go to the backing file or
+   return zeros if there is no backing file data.
+
+Bits are assigned starting from the most significant one.
+(i.e. bit x is used for subcluster 31 - x)
+
+32 -  63Subcluster reads as zeros (one bit per subcluster)
+
+1: the subcluster reads as zeros. In this case the
+   allocation status bit must be unset. The host
+   cluster offset field may or may not be set.
+   

[RFC PATCH v2 12/26] qcow2: Handle QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER

2019-10-26 Thread Alberto Garcia
In the previous patch we added a new QCow2ClusterType named
QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER. There is a couple of places
where this new value needs to be handled, and that is what this patch
does.

Signed-off-by: Alberto Garcia 
---
 block/qcow2.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index ab40ae36ea..0261e87709 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1938,8 +1938,8 @@ static int coroutine_fn 
qcow2_co_block_status(BlockDriverState *bs,
 
 *pnum = bytes;
 
-if ((ret == QCOW2_CLUSTER_NORMAL || ret == QCOW2_CLUSTER_ZERO_ALLOC) &&
-!s->crypto) {
+if ((ret == QCOW2_CLUSTER_NORMAL || ret == QCOW2_CLUSTER_ZERO_ALLOC ||
+ ret == QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER) && !s->crypto) {
 index_in_cluster = offset & (s->cluster_size - 1);
 *map = cluster_offset | index_in_cluster;
 *file = s->data_file->bs;
@@ -1947,7 +1947,8 @@ static int coroutine_fn 
qcow2_co_block_status(BlockDriverState *bs,
 }
 if (ret == QCOW2_CLUSTER_ZERO_PLAIN || ret == QCOW2_CLUSTER_ZERO_ALLOC) {
 status |= BDRV_BLOCK_ZERO;
-} else if (ret != QCOW2_CLUSTER_UNALLOCATED) {
+} else if (ret != QCOW2_CLUSTER_UNALLOCATED &&
+   ret != QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER) {
 status |= BDRV_BLOCK_DATA;
 }
 if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) &&
@@ -2117,6 +2118,7 @@ static coroutine_fn int 
qcow2_co_preadv_task(BlockDriverState *bs,
 g_assert_not_reached();
 
 case QCOW2_CLUSTER_UNALLOCATED:
+case QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER:
 assert(bs->backing); /* otherwise handled in qcow2_co_preadv_part */
 
 BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
@@ -2187,7 +2189,8 @@ static coroutine_fn int 
qcow2_co_preadv_part(BlockDriverState *bs,
 
 if (ret == QCOW2_CLUSTER_ZERO_PLAIN ||
 ret == QCOW2_CLUSTER_ZERO_ALLOC ||
-(ret == QCOW2_CLUSTER_UNALLOCATED && !bs->backing))
+(ret == QCOW2_CLUSTER_UNALLOCATED && !bs->backing) ||
+(ret == QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER && !bs->backing))
 {
 qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
 } else {
@@ -3701,6 +3704,7 @@ static coroutine_fn int 
qcow2_co_pwrite_zeroes(BlockDriverState *bs,
 nr = s->cluster_size;
 ret = qcow2_get_cluster_offset(bs, offset, , );
 if (ret != QCOW2_CLUSTER_UNALLOCATED &&
+ret != QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER &&
 ret != QCOW2_CLUSTER_ZERO_PLAIN &&
 ret != QCOW2_CLUSTER_ZERO_ALLOC) {
 qemu_co_mutex_unlock(>lock);
@@ -3771,6 +3775,7 @@ qcow2_co_copy_range_from(BlockDriverState *bs,
 
 switch (ret) {
 case QCOW2_CLUSTER_UNALLOCATED:
+case QCOW2_CLUSTER_UNALLOCATED_SUBCLUSTER:
 if (bs->backing && bs->backing->bs) {
 int64_t backing_length = bdrv_getlength(bs->backing->bs);
 if (src_offset >= backing_length) {
-- 
2.20.1




[RFC PATCH v2 25/26] qcow2: Allow preallocation and backing files if extended_l2 is set

2019-10-26 Thread Alberto Garcia
Traditional qcow2 images don't allow preallocation if a backing file
is set. This is because once a cluster is allocated there is no way to
tell that its data should be read from the backing file.

Extended L2 entries have individual allocation bits for each
subcluster, and therefore it is perfectly possible to have an
allocated cluster with all its subclusters unallocated.

Signed-off-by: Alberto Garcia 
---
 block/qcow2.c  | 7 ---
 tests/qemu-iotests/206.out | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index b1fa7ab5da..8cf51c5d64 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3307,10 +3307,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, 
Error **errp)
 qcow2_opts->preallocation = PREALLOC_MODE_OFF;
 }
 if (qcow2_opts->has_backing_file &&
-qcow2_opts->preallocation != PREALLOC_MODE_OFF)
+qcow2_opts->preallocation != PREALLOC_MODE_OFF &&
+!qcow2_opts->extended_l2)
 {
-error_setg(errp, "Backing file and preallocation cannot be used at "
-   "the same time");
+error_setg(errp, "Backing file and preallocation can only be used at "
+   "the same time if extended_l2 is on");
 ret = -EINVAL;
 goto out;
 }
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
index d2efc0394a..cfddfbfaa4 100644
--- a/tests/qemu-iotests/206.out
+++ b/tests/qemu-iotests/206.out
@@ -198,7 +198,7 @@ Job failed: Different refcount widths than 16 bits require 
compatibility level 1
 === Invalid backing file options ===
 {"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": 
{"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", 
"preallocation": "full", "size": 67108864}}}
 {"return": {}}
-Job failed: Backing file and preallocation cannot be used at the same time
+Job failed: Backing file and preallocation can only be used at the same time 
if extended_l2 is on
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
-- 
2.20.1




[RFC PATCH v2 08/26] qcow2: Add offset_to_sc_index()

2019-10-26 Thread Alberto Garcia
For a given offset, return the subcluster number within its cluster
(i.e. with 32 subclusters per cluster it returns a number between 0
and 31).

Signed-off-by: Alberto Garcia 
---
 block/qcow2.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/block/qcow2.h b/block/qcow2.h
index 278ca41314..e25758079c 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -559,6 +559,11 @@ static inline int offset_to_l2_slice_index(BDRVQcow2State 
*s, int64_t offset)
 return (offset >> s->cluster_bits) & (s->l2_slice_size - 1);
 }
 
+static inline int offset_to_sc_index(BDRVQcow2State *s, int64_t offset)
+{
+return (offset >> s->subcluster_bits) & (s->subclusters_per_cluster - 1);
+}
+
 static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s)
 {
 return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
-- 
2.20.1




[PULL 09/25] tests/virtio-blk-test: read config space after feature negotiation

2019-10-26 Thread Michael S. Tsirkin
From: Stefan Hajnoczi 

The VIRTIO Configuration Space cannot be accessed before device feature
bits have been read because a driver doesn't know the endianness until
it has checked VIRTIO_F_VERSION_1.

Fix this problem in preparation for VIRTIO 1.0 support.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Thomas Huth 
Message-Id: <20191023100425.12168-2-stefa...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 tests/virtio-blk-test.c | 33 -
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
index ed13167392..f6674fb233 100644
--- a/tests/virtio-blk-test.c
+++ b/tests/virtio-blk-test.c
@@ -125,10 +125,6 @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator 
*alloc,
 char *data;
 QTestState *qts = global_qtest;
 
-capacity = qvirtio_config_readq(dev, 0);
-
-g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
-
 features = qvirtio_get_features(dev);
 features = features & ~(QVIRTIO_F_BAD_FEATURE |
 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
@@ -136,6 +132,9 @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator 
*alloc,
 (1u << VIRTIO_BLK_F_SCSI));
 qvirtio_set_features(dev, features);
 
+capacity = qvirtio_config_readq(dev, 0);
+g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
+
 qvirtio_set_driver_ok(dev);
 
 /* Write and read with 3 descriptor layout */
@@ -359,9 +358,6 @@ static void indirect(void *obj, void *u_data, 
QGuestAllocator *t_alloc)
 char *data;
 QTestState *qts = global_qtest;
 
-capacity = qvirtio_config_readq(dev, 0);
-g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
-
 features = qvirtio_get_features(dev);
 g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
 features = features & ~(QVIRTIO_F_BAD_FEATURE |
@@ -369,6 +365,9 @@ static void indirect(void *obj, void *u_data, 
QGuestAllocator *t_alloc)
 (1u << VIRTIO_BLK_F_SCSI));
 qvirtio_set_features(dev, features);
 
+capacity = qvirtio_config_readq(dev, 0);
+g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
+
 vq = qvirtqueue_setup(dev, t_alloc, 0);
 qvirtio_set_driver_ok(dev);
 
@@ -434,8 +433,16 @@ static void config(void *obj, void *data, QGuestAllocator 
*t_alloc)
 QVirtioBlk *blk_if = obj;
 QVirtioDevice *dev = blk_if->vdev;
 int n_size = TEST_IMAGE_SIZE / 2;
+uint64_t features;
 uint64_t capacity;
 
+features = qvirtio_get_features(dev);
+features = features & ~(QVIRTIO_F_BAD_FEATURE |
+(1u << VIRTIO_RING_F_INDIRECT_DESC) |
+(1u << VIRTIO_RING_F_EVENT_IDX) |
+(1u << VIRTIO_BLK_F_SCSI));
+qvirtio_set_features(dev, features);
+
 capacity = qvirtio_config_readq(dev, 0);
 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 
@@ -475,9 +482,6 @@ static void msix(void *obj, void *u_data, QGuestAllocator 
*t_alloc)
 qpci_msix_enable(pdev->pdev);
 qvirtio_pci_set_msix_configuration_vector(pdev, t_alloc, 0);
 
-capacity = qvirtio_config_readq(dev, 0);
-g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
-
 features = qvirtio_get_features(dev);
 features = features & ~(QVIRTIO_F_BAD_FEATURE |
 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
@@ -485,6 +489,9 @@ static void msix(void *obj, void *u_data, QGuestAllocator 
*t_alloc)
 (1u << VIRTIO_BLK_F_SCSI));
 qvirtio_set_features(dev, features);
 
+capacity = qvirtio_config_readq(dev, 0);
+g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
+
 vq = qvirtqueue_setup(dev, t_alloc, 0);
 qvirtqueue_pci_msix_setup(pdev, (QVirtQueuePCI *)vq, t_alloc, 1);
 
@@ -584,9 +591,6 @@ static void idx(void *obj, void *u_data, QGuestAllocator 
*t_alloc)
 qpci_msix_enable(pdev->pdev);
 qvirtio_pci_set_msix_configuration_vector(pdev, t_alloc, 0);
 
-capacity = qvirtio_config_readq(dev, 0);
-g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
-
 features = qvirtio_get_features(dev);
 features = features & ~(QVIRTIO_F_BAD_FEATURE |
 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
@@ -594,6 +598,9 @@ static void idx(void *obj, void *u_data, QGuestAllocator 
*t_alloc)
 (1u << VIRTIO_BLK_F_SCSI));
 qvirtio_set_features(dev, features);
 
+capacity = qvirtio_config_readq(dev, 0);
+g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
+
 vq = qvirtqueue_setup(dev, t_alloc, 0);
 qvirtqueue_pci_msix_setup(pdev, (QVirtQueuePCI *)vq, t_alloc, 1);
 
-- 
MST




[PULL 05/25] virtio: basic packed virtqueue support

2019-10-26 Thread Michael S. Tsirkin
From: Jason Wang 

This patch implements basic support for the packed virtqueue. Compare
the split virtqueue which has three rings, packed virtqueue only have
one which is supposed to have better cache utilization and more
hardware friendly.

Please refer virtio specification for more information.

Signed-off-by: Wei Xu 
Signed-off-by: Jason Wang 
Signed-off-by: Eugenio Pérez 
Message-Id: <20191025083527.30803-6-epere...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/block/virtio-blk.c   |   2 +-
 hw/char/virtio-serial-bus.c |   2 +-
 hw/scsi/virtio-scsi.c   |   3 +-
 hw/virtio/virtio.c  | 901 +---
 include/hw/virtio/virtio.h  |  10 +-
 5 files changed, 836 insertions(+), 82 deletions(-)

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index ba846fe9dc..7dbdeaaab9 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1052,7 +1052,7 @@ static void virtio_blk_save_device(VirtIODevice *vdev, 
QEMUFile *f)
 qemu_put_be32(f, virtio_get_queue_index(req->vq));
 }
 
-qemu_put_virtqueue_element(f, >elem);
+qemu_put_virtqueue_element(vdev, f, >elem);
 req = req->next;
 }
 qemu_put_sbyte(f, 0);
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 4e0ed829ae..33259042a9 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -708,7 +708,7 @@ static void virtio_serial_save_device(VirtIODevice *vdev, 
QEMUFile *f)
 if (elem_popped) {
 qemu_put_be32s(f, >iov_idx);
 qemu_put_be64s(f, >iov_offset);
-qemu_put_virtqueue_element(f, port->elem);
+qemu_put_virtqueue_element(vdev, f, port->elem);
 }
 }
 }
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index ee52aa7d17..e8b2b64d09 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -190,11 +190,12 @@ static void virtio_scsi_save_request(QEMUFile *f, 
SCSIRequest *sreq)
 {
 VirtIOSCSIReq *req = sreq->hba_private;
 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev);
+VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
 uint32_t n = virtio_get_queue_index(req->vq) - 2;
 
 assert(n < vs->conf.num_queues);
 qemu_put_be32s(f, );
-qemu_put_virtqueue_element(f, >elem);
+qemu_put_virtqueue_element(vdev, f, >elem);
 }
 
 static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 74cc10fad9..a694b4ab50 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -96,6 +96,7 @@ typedef struct VRingPackedDescEvent {
 struct VirtQueue
 {
 VRing vring;
+VirtQueueElement *used_elems;
 
 /* Next head to pop */
 uint16_t last_avail_idx;
@@ -160,6 +161,7 @@ static void virtio_init_region_cache(VirtIODevice *vdev, 
int n)
 VRingMemoryRegionCaches *new = NULL;
 hwaddr addr, size;
 int64_t len;
+bool packed;
 
 
 addr = vq->vring.desc;
@@ -168,8 +170,10 @@ static void virtio_init_region_cache(VirtIODevice *vdev, 
int n)
 }
 new = g_new0(VRingMemoryRegionCaches, 1);
 size = virtio_queue_get_desc_size(vdev, n);
+packed = virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED) ?
+   true : false;
 len = address_space_cache_init(>desc, vdev->dma_as,
-   addr, size, false);
+   addr, size, packed);
 if (len < size) {
 virtio_error(vdev, "Cannot map desc");
 goto err_desc;
@@ -225,8 +229,8 @@ void virtio_queue_update_rings(VirtIODevice *vdev, int n)
 }
 
 /* Called within rcu_read_lock().  */
-static void vring_desc_read(VirtIODevice *vdev, VRingDesc *desc,
-MemoryRegionCache *cache, int i)
+static void vring_split_desc_read(VirtIODevice *vdev, VRingDesc *desc,
+  MemoryRegionCache *cache, int i)
 {
 address_space_read_cached(cache, i * sizeof(VRingDesc),
   desc, sizeof(VRingDesc));
@@ -236,6 +240,7 @@ static void vring_desc_read(VirtIODevice *vdev, VRingDesc 
*desc,
 virtio_tswap16s(vdev, >next);
 }
 
+/* Called within rcu_read_lock().  */
 static VRingMemoryRegionCaches *vring_get_region_caches(struct VirtQueue *vq)
 {
 VRingMemoryRegionCaches *caches = atomic_rcu_read(>vring.caches);
@@ -370,6 +375,95 @@ int virtio_queue_ready(VirtQueue *vq)
 return vq->vring.avail != 0;
 }
 
+static void vring_packed_desc_read_flags(VirtIODevice *vdev,
+ uint16_t *flags,
+ MemoryRegionCache *cache,
+ int i)
+{
+address_space_read_cached(cache,
+  i * sizeof(VRingPackedDesc) +
+  offsetof(VRingPackedDesc, flags),
+  flags, sizeof(*flags));
+

[PULL 03/25] virtio: Free blk virqueues at unrealize()

2019-10-26 Thread Michael S. Tsirkin
From: Eugenio Pérez 

The function virtio_del_queue was not called at unrealize() callback.

This was detected due to add an allocated element on the vq introduce
in future commits (used_elems) and running address sanitizer memory
leak detector.

Signed-off-by: Eugenio Pérez 
Message-Id: <20191025083527.30803-4-epere...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 hw/block/virtio-blk.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index ed2ddebd2b..ba846fe9dc 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1206,9 +1206,14 @@ static void virtio_blk_device_unrealize(DeviceState 
*dev, Error **errp)
 {
 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 VirtIOBlock *s = VIRTIO_BLK(dev);
+VirtIOBlkConf *conf = >conf;
+unsigned i;
 
 virtio_blk_data_plane_destroy(s->dataplane);
 s->dataplane = NULL;
+for (i = 0; i < conf->num_queues; i++) {
+virtio_del_queue(vdev, i);
+}
 qemu_del_vm_change_state_handler(s->change);
 blockdev_mark_auto_del(s->blk);
 virtio_cleanup(vdev);
-- 
MST




[PULL 11/25] libqos: extend feature bits to 64-bit

2019-10-26 Thread Michael S. Tsirkin
From: Stefan Hajnoczi 

In VIRTIO 1.0 feature bits changed from 32-bit to 64-bit.  (In fact, the
transports allow even more feature bits but nothing uses more than 64
bits today.)

Add 64-bit feature bit support to virtio-mmio and virtio-pci.  This will
be necessary for VIRTIO 1.0 support.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Thomas Huth 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20191023100425.12168-4-stefa...@redhat.com>
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 tests/libqos/virtio-mmio.c | 28 ++--
 tests/libqos/virtio-net.c  |  6 +++---
 tests/libqos/virtio-pci.c  | 12 ++--
 tests/libqos/virtio.c  |  4 ++--
 tests/libqos/virtio.h  | 12 ++--
 tests/virtio-blk-test.c|  8 
 6 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c
index 7154b03c1d..78066e6e05 100644
--- a/tests/libqos/virtio-mmio.c
+++ b/tests/libqos/virtio-mmio.c
@@ -40,22 +40,38 @@ static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, 
uint64_t off)
 return qtest_readq(dev->qts, dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + 
off);
 }
 
-static uint32_t qvirtio_mmio_get_features(QVirtioDevice *d)
+static uint64_t qvirtio_mmio_get_features(QVirtioDevice *d)
 {
 QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev);
+uint64_t lo;
+uint64_t hi = 0;
+
 qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_HOST_FEATURES_SEL, 0);
-return qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_HOST_FEATURES);
+lo = qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_HOST_FEATURES);
+
+if (dev->version >= 2) {
+qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_HOST_FEATURES_SEL, 1);
+hi = qtest_readl(dev->qts, dev->addr + QVIRTIO_MMIO_HOST_FEATURES);
+}
+
+return (hi << 32) | lo;
 }
 
-static void qvirtio_mmio_set_features(QVirtioDevice *d, uint32_t features)
+static void qvirtio_mmio_set_features(QVirtioDevice *d, uint64_t features)
 {
 QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev);
 dev->features = features;
 qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_GUEST_FEATURES_SEL, 0);
 qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_GUEST_FEATURES, features);
+
+if (dev->version >= 2) {
+qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_GUEST_FEATURES_SEL, 1);
+qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_GUEST_FEATURES,
+ features >> 32);
+}
 }
 
-static uint32_t qvirtio_mmio_get_guest_features(QVirtioDevice *d)
+static uint64_t qvirtio_mmio_get_guest_features(QVirtioDevice *d)
 {
 QVirtioMMIODevice *dev = container_of(d, QVirtioMMIODevice, vdev);
 return dev->features;
@@ -149,8 +165,8 @@ static QVirtQueue 
*qvirtio_mmio_virtqueue_setup(QVirtioDevice *d,
 vq->free_head = 0;
 vq->num_free = vq->size;
 vq->align = dev->page_size;
-vq->indirect = (dev->features & (1u << VIRTIO_RING_F_INDIRECT_DESC)) != 0;
-vq->event = (dev->features & (1u << VIRTIO_RING_F_EVENT_IDX)) != 0;
+vq->indirect = dev->features & (1ull << VIRTIO_RING_F_INDIRECT_DESC);
+vq->event = dev->features & (1ull << VIRTIO_RING_F_EVENT_IDX);
 
 qtest_writel(dev->qts, dev->addr + QVIRTIO_MMIO_QUEUE_NUM, vq->size);
 
diff --git a/tests/libqos/virtio-net.c b/tests/libqos/virtio-net.c
index 6567beb553..710d440c3d 100644
--- a/tests/libqos/virtio-net.c
+++ b/tests/libqos/virtio-net.c
@@ -44,11 +44,11 @@ static void virtio_net_setup(QVirtioNet *interface)
 
 features = qvirtio_get_features(vdev);
 features &= ~(QVIRTIO_F_BAD_FEATURE |
-  (1u << VIRTIO_RING_F_INDIRECT_DESC) |
-  (1u << VIRTIO_RING_F_EVENT_IDX));
+  (1ull << VIRTIO_RING_F_INDIRECT_DESC) |
+  (1ull << VIRTIO_RING_F_EVENT_IDX));
 qvirtio_set_features(vdev, features);
 
-if (features & (1u << VIRTIO_NET_F_MQ)) {
+if (features & (1ull << VIRTIO_NET_F_MQ)) {
 interface->n_queues = qvirtio_config_readw(vdev, 8) * 2;
 } else {
 interface->n_queues = 2;
diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
index 50499e75ef..1b6b760fc6 100644
--- a/tests/libqos/virtio-pci.c
+++ b/tests/libqos/virtio-pci.c
@@ -96,19 +96,19 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, 
uint64_t off)
 return val;
 }
 
-static uint32_t qvirtio_pci_get_features(QVirtioDevice *d)
+static uint64_t qvirtio_pci_get_features(QVirtioDevice *d)
 {
 QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev);
 return qpci_io_readl(dev->pdev, dev->bar, VIRTIO_PCI_HOST_FEATURES);
 }
 
-static void qvirtio_pci_set_features(QVirtioDevice *d, uint32_t features)
+static void qvirtio_pci_set_features(QVirtioDevice *d, uint64_t features)
 {
 QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev);
 qpci_io_writel(dev->pdev, dev->bar, VIRTIO_PCI_GUEST_FEATURES, features);
 }
 

Re: [RFC 0/3] block/file-posix: Work around XFS bug

2019-10-26 Thread Vladimir Sementsov-Ogievskiy
26.10.2019 20:37, Nir Soffer wrote:
> On Fri, Oct 25, 2019 at 1:11 PM Max Reitz  wrote:
>>
>> Hi,
>>
>> It seems to me that there is a bug in Linux’s XFS kernel driver, as
>> I’ve explained here:
>>
>> https://lists.nongnu.org/archive/html/qemu-block/2019-10/msg01429.html
>>
>> In combination with our commit c8bb23cbdbe32f, this may lead to guest
>> data corruption when using qcow2 images on XFS with aio=native.
>>
>> We can’t wait until the XFS kernel driver is fixed, we should work
>> around the problem ourselves.
>>
>> This is an RFC for two reasons:
>> (1) I don’t know whether this is the right way to address the issue,
>> (2) Ideally, we should detect whether the XFS kernel driver is fixed and
>>  if so stop applying the workaround.
>>  I don’t know how we would go about this, so this series doesn’t do
>>  it.  (Hence it’s an RFC.)
>> (3) Perhaps it’s a bit of a layering violation to let the file-posix
>>  driver access and modify a BdrvTrackedRequest object.
>>
>> As for how we can address the issue, I see three ways:
>> (1) The one presented in this series: On XFS with aio=native, we extend
>>  tracked requests for post-EOF fallocate() calls (i.e., write-zero
>>  operations) to reach until infinity (INT64_MAX in practice), mark
>>  them serializing and wait for other conflicting requests.
>>
>>  Advantages:
>>  + Limits the impact to very specific cases
>>(And that means it wouldn’t hurt too much to keep this workaround
>>even when the XFS driver has been fixed)
>>  + Works around the bug where it happens, namely in file-posix
>>
>>  Disadvantages:
>>  - A bit complex
>>  - A bit of a layering violation (should file-posix have access to
>>tracked requests?)
>>
>> (2) Always skip qcow2’s handle_alloc_space() on XFS.  The XFS bug only
>>  becomes visible due to that function: I don’t think qcow2 writes
>>  zeroes in any other I/O path, and raw images are fixed in size so
>>  post-EOF writes won’t happen.
>>
>>  Advantages:
>>  + Maybe simpler, depending on how difficult it is to handle the
>>layering violation
>>  + Also fixes the performance problem of handle_alloc_space() being
>>slow on ppc64+XFS.
>>
>>  Disadvantages:
>>  - Huge layering violation because qcow2 would need to know whether
>>the image is stored on XFS or not.
>>  - We’d definitely want to skip this workaround when the XFS driver
>>has been fixed, so we need some method to find out whether it has
>>
>> (3) Drop handle_alloc_space(), i.e. revert c8bb23cbdbe32f.
>>  To my knowledge I’m the only one who has provided any benchmarks for
>>  this commit, and even then I was a bit skeptical because it performs
>>  well in some cases and bad in others.  I concluded that it’s
>>  probably worth it because the “some cases” are more likely to occur.
>>
>>  Now we have this problem of corruption here (granted due to a bug in
>>  the XFS driver), and another report of massively degraded
>>  performance on ppc64
>>  (https://bugzilla.redhat.com/show_bug.cgi?id=1745823 – sorry, a
>>  private BZ; I hate that :-/  The report is about 40 % worse
>>  performance for an in-guest fio write benchmark.)
>>
>>  So I have to ask the question about what the justification for
>>  keeping c8bb23cbdbe32f is.  How much does performance increase with
>>  it actually?  (On non-(ppc64+XFS) machines, obviously)
>>
>>  Advantages:
>>  + Trivial
>>  + No layering violations
>>  + We wouldn’t need to keep track of whether the kernel bug has been
>>fixed or not
>>  + Fixes the ppc64+XFS performance problem
>>
>>  Disadvantages:
>>  - Reverts cluster allocation performance to pre-c8bb23cbdbe32f
>>levels, whatever that means
> 
> Correctness is more important than performance, so this is my
> preference as a user.
> 

Hmm, still, incorrect is XFS, not Qemu. This bug may be triggered by another
software, or may be another scenario in Qemu (not sure).

> 
>> So this is the main reason this is an RFC: What should we do?  Is (1)
>> really the best choice?
>>
>>
>> In any case, I’ve ran the test case I showed in
>> https://lists.nongnu.org/archive/html/qemu-block/2019-10/msg01282.html
>> more than ten times with this series applied and the installation
>> succeeded every time.  (Without this series, it fails like every other
>> time.)
>>
>>
>> Max Reitz (3):
>>block: Make wait/mark serialising requests public
>>block/file-posix: Detect XFS with CONFIG_FALLOCATE
>>block/file-posix: Let post-EOF fallocate serialize
>>
>>   include/block/block_int.h |  3 +++
>>   block/file-posix.c| 46 +--
>>   block/io.c| 24 ++--
>>   3 files changed, 59 insertions(+), 14 deletions(-)
>>
>> --
>> 2.21.0
>>
>>


-- 
Best regards,
Vladimir


Re: [RFC 0/3] block/file-posix: Work around XFS bug

2019-10-26 Thread Nir Soffer
On Fri, Oct 25, 2019 at 1:11 PM Max Reitz  wrote:
>
> Hi,
>
> It seems to me that there is a bug in Linux’s XFS kernel driver, as
> I’ve explained here:
>
> https://lists.nongnu.org/archive/html/qemu-block/2019-10/msg01429.html
>
> In combination with our commit c8bb23cbdbe32f, this may lead to guest
> data corruption when using qcow2 images on XFS with aio=native.
>
> We can’t wait until the XFS kernel driver is fixed, we should work
> around the problem ourselves.
>
> This is an RFC for two reasons:
> (1) I don’t know whether this is the right way to address the issue,
> (2) Ideally, we should detect whether the XFS kernel driver is fixed and
> if so stop applying the workaround.
> I don’t know how we would go about this, so this series doesn’t do
> it.  (Hence it’s an RFC.)
> (3) Perhaps it’s a bit of a layering violation to let the file-posix
> driver access and modify a BdrvTrackedRequest object.
>
> As for how we can address the issue, I see three ways:
> (1) The one presented in this series: On XFS with aio=native, we extend
> tracked requests for post-EOF fallocate() calls (i.e., write-zero
> operations) to reach until infinity (INT64_MAX in practice), mark
> them serializing and wait for other conflicting requests.
>
> Advantages:
> + Limits the impact to very specific cases
>   (And that means it wouldn’t hurt too much to keep this workaround
>   even when the XFS driver has been fixed)
> + Works around the bug where it happens, namely in file-posix
>
> Disadvantages:
> - A bit complex
> - A bit of a layering violation (should file-posix have access to
>   tracked requests?)
>
> (2) Always skip qcow2’s handle_alloc_space() on XFS.  The XFS bug only
> becomes visible due to that function: I don’t think qcow2 writes
> zeroes in any other I/O path, and raw images are fixed in size so
> post-EOF writes won’t happen.
>
> Advantages:
> + Maybe simpler, depending on how difficult it is to handle the
>   layering violation
> + Also fixes the performance problem of handle_alloc_space() being
>   slow on ppc64+XFS.
>
> Disadvantages:
> - Huge layering violation because qcow2 would need to know whether
>   the image is stored on XFS or not.
> - We’d definitely want to skip this workaround when the XFS driver
>   has been fixed, so we need some method to find out whether it has
>
> (3) Drop handle_alloc_space(), i.e. revert c8bb23cbdbe32f.
> To my knowledge I’m the only one who has provided any benchmarks for
> this commit, and even then I was a bit skeptical because it performs
> well in some cases and bad in others.  I concluded that it’s
> probably worth it because the “some cases” are more likely to occur.
>
> Now we have this problem of corruption here (granted due to a bug in
> the XFS driver), and another report of massively degraded
> performance on ppc64
> (https://bugzilla.redhat.com/show_bug.cgi?id=1745823 – sorry, a
> private BZ; I hate that :-/  The report is about 40 % worse
> performance for an in-guest fio write benchmark.)
>
> So I have to ask the question about what the justification for
> keeping c8bb23cbdbe32f is.  How much does performance increase with
> it actually?  (On non-(ppc64+XFS) machines, obviously)
>
> Advantages:
> + Trivial
> + No layering violations
> + We wouldn’t need to keep track of whether the kernel bug has been
>   fixed or not
> + Fixes the ppc64+XFS performance problem
>
> Disadvantages:
> - Reverts cluster allocation performance to pre-c8bb23cbdbe32f
>   levels, whatever that means

Correctness is more important than performance, so this is my
preference as a user.

Nir

> So this is the main reason this is an RFC: What should we do?  Is (1)
> really the best choice?
>
>
> In any case, I’ve ran the test case I showed in
> https://lists.nongnu.org/archive/html/qemu-block/2019-10/msg01282.html
> more than ten times with this series applied and the installation
> succeeded every time.  (Without this series, it fails like every other
> time.)
>
>
> Max Reitz (3):
>   block: Make wait/mark serialising requests public
>   block/file-posix: Detect XFS with CONFIG_FALLOCATE
>   block/file-posix: Let post-EOF fallocate serialize
>
>  include/block/block_int.h |  3 +++
>  block/file-posix.c| 46 +--
>  block/io.c| 24 ++--
>  3 files changed, 59 insertions(+), 14 deletions(-)
>
> --
> 2.21.0
>
>



Re: [RFC 3/3] block/file-posix: Let post-EOF fallocate serialize

2019-10-26 Thread Nir Soffer
On Fri, Oct 25, 2019 at 1:24 PM Max Reitz  wrote:
>
> The XFS kernel driver has a bug that may cause data corruption for qcow2
> images as of qemu commit c8bb23cbdbe32f.  We can work around it by
> treating post-EOF fallocates as serializing up until infinity (INT64_MAX
> in practice).
>
> Signed-off-by: Max Reitz 
> ---
>  block/file-posix.c | 42 ++
>  1 file changed, 42 insertions(+)
>
> diff --git a/block/file-posix.c b/block/file-posix.c
> index 5cd54c8bff..1f5a01df70 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -2713,6 +2713,48 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t 
> offset, int bytes,
>  RawPosixAIOData acb;
>  ThreadPoolFunc *handler;
>
> +#ifdef CONFIG_FALLOCATE
> +if (s->is_xfs && s->use_linux_aio &&

This limit the fix to local xfs filesystem, but the fix may be needed
to remote filesystem such
as gluster over xfs.

> +offset + bytes > bs->total_sectors * BDRV_SECTOR_SIZE)
> +{
> +BdrvTrackedRequest *req;
> +uint64_t end;
> +
> +/*
> + * The Linux XFS driver has a bug where it will discard writes
> + * submitted through the AIO interface if they happen beyond a
> + * concurrently running fallocate() that increases the file
> + * length (i.e., both the write and the fallocate() happen
> + * beyond the EOF).
> + *
> + * To work around it, we look for the tracked request for this
> + * zero write, extend it until INT64_MAX (effectively
> + * infinity), and mark it as serializing.
> + *
> + * TODO: Detect whether this has been fixed in the XFS driver.
> + */
> +
> +QLIST_FOREACH(req, >tracked_requests, list) {
> +if (req->co == qemu_coroutine_self() &&
> +req->type == BDRV_TRACKED_WRITE)
> +{
> +break;
> +}
> +}
> +
> +assert(req);
> +assert(req->offset <= offset);
> +assert(req->offset + req->bytes >= offset + bytes);
> +
> +end = INT64_MAX & -(uint64_t)bs->bl.request_alignment;
> +req->bytes = end - req->offset;
> +req->overlap_bytes = req->bytes;
> +
> +bdrv_mark_request_serialising(req, bs->bl.request_alignment);
> +bdrv_wait_serialising_requests(req);
> +}
> +#endif
> +
>  acb = (RawPosixAIOData) {
>  .bs = bs,
>  .aio_fildes = s->fd,
> --
> 2.21.0
>
>



Re: [RFC 2/3] block/file-posix: Detect XFS with CONFIG_FALLOCATE

2019-10-26 Thread Nir Soffer
On Fri, Oct 25, 2019 at 1:22 PM Max Reitz  wrote:
>
> We will need this for the next patch.
>
> Signed-off-by: Max Reitz 
> ---
>  block/file-posix.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/block/file-posix.c b/block/file-posix.c
> index 695fcf740d..5cd54c8bff 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -149,7 +149,7 @@ typedef struct BDRVRawState {
>  int perm_change_flags;
>  BDRVReopenState *reopen_state;
>
> -#ifdef CONFIG_XFS
> +#if defined(CONFIG_XFS) || defined(CONFIG_FALLOCATE)
>  bool is_xfs:1;
>  #endif
>  bool has_discard:1;
> @@ -667,7 +667,7 @@ static int raw_open_common(BlockDriverState *bs, QDict 
> *options,
>  }
>  #endif
>
> -#ifdef CONFIG_XFS
> +#if defined(CONFIG_XFS) || defined(CONFIG_FALLOCATE)
>  if (platform_test_xfs_fd(s->fd)) {
>  s->is_xfs = true;

What about remote xfs filesystem, e.g. glusterfs over xfs mounted using fuse?
(how oVirt uses glusterfs)

The buggy behavior with concurrent fallocate/pwrite can affect this, and
platform_test_xfs_fd() will probably fail to detect xfs.

Nir

>  }
> --
> 2.21.0
>
>



Re: [PATCH v15 02/11] esp: move get_cmd() post-DMA code to get_cmd_cb()

2019-10-26 Thread Philippe Mathieu-Daudé

On 10/26/19 6:45 PM, Laurent Vivier wrote:

This will be needed to implement pseudo-DMA

Signed-off-by: Laurent Vivier 


:)

Reviewed-by: Philippe Mathieu-Daudé 


---
  hw/scsi/esp.c | 46 +-
  1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 09b28cba17..0230ede21d 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -84,6 +84,34 @@ void esp_request_cancelled(SCSIRequest *req)
  }
  }
  
+static int get_cmd_cb(ESPState *s)

+{
+int target;
+
+target = s->wregs[ESP_WBUSID] & BUSID_DID;
+
+s->ti_size = 0;
+s->ti_rptr = 0;
+s->ti_wptr = 0;
+
+if (s->current_req) {
+/* Started a new command before the old one finished.  Cancel it.  */
+scsi_req_cancel(s->current_req);
+s->async_len = 0;
+}
+
+s->current_dev = scsi_device_find(>bus, 0, target, 0);
+if (!s->current_dev) {
+/* No such drive */
+s->rregs[ESP_RSTAT] = 0;
+s->rregs[ESP_RINTR] = INTR_DC;
+s->rregs[ESP_RSEQ] = SEQ_0;
+esp_raise_irq(s);
+return -1;
+}
+return 0;
+}
+
  static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
  {
  uint32_t dmalen;
@@ -108,23 +136,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t 
buflen)
  }
  trace_esp_get_cmd(dmalen, target);
  
-s->ti_size = 0;

-s->ti_rptr = 0;
-s->ti_wptr = 0;
-
-if (s->current_req) {
-/* Started a new command before the old one finished.  Cancel it.  */
-scsi_req_cancel(s->current_req);
-s->async_len = 0;
-}
-
-s->current_dev = scsi_device_find(>bus, 0, target, 0);
-if (!s->current_dev) {
-// No such drive
-s->rregs[ESP_RSTAT] = 0;
-s->rregs[ESP_RINTR] = INTR_DC;
-s->rregs[ESP_RSEQ] = SEQ_0;
-esp_raise_irq(s);
+if (get_cmd_cb(s) < 0) {
  return 0;
  }
  return dmalen;





[PATCH] MAINTAINERS: add more bitmap-related to Dirty Bitmaps section

2019-10-26 Thread Vladimir Sementsov-Ogievskiy
Let's add bitmaps persistence qcow2 feature and postcopy bitmaps
migration to Dirty Bitmaps section.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 556ce0bfe3..51f31b4011 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1829,6 +1829,8 @@ F: util/hbitmap.c
 F: block/dirty-bitmap.c
 F: include/qemu/hbitmap.h
 F: include/block/dirty-bitmap.h
+F: qcow2-bitmap.c
+F: migration/block-dirty-bitmap.c
 F: tests/test-hbitmap.c
 F: docs/interop/bitmaps.rst
 T: git https://github.com/jnsnow/qemu.git bitmaps
-- 
2.21.0




Re: [PATCH] qemu-iotests/iotests.py: improve assert_qmp message

2019-10-26 Thread Vladimir Sementsov-Ogievskiy
26.10.2019 14:29, Philippe Mathieu-Daudé wrote:
> On 10/26/19 12:12 PM, Vladimir Sementsov-Ogievskiy wrote:
>> Make it obvious, from the two values which is found at path and which
>> is expected.
> 
> Maybe:
> 
> "From the two values compared, make it obvious which is found at path, and 
> which is expected."
> 
> Reviewed-by: Philippe Mathieu-Daudé 

Thanks for review and better wording!

> 
>>
>> Signed-off-by: Vladimir Sementsov-Ogievskiy 
>> ---
>>
>> It's a pain, I can never remember it, and checking each time in source
>> code who is who is boring.
>>
>>   tests/qemu-iotests/iotests.py | 4 ++--
>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
>> index 709def4d5d..e805b9ab14 100644
>> --- a/tests/qemu-iotests/iotests.py
>> +++ b/tests/qemu-iotests/iotests.py
>> @@ -729,8 +729,8 @@ class QMPTestCase(unittest.TestCase):
>>   self.fail('no match for "%s" in %s' % (str(result), 
>> str(value)))
>>   else:
>>   self.assertEqual(result, value,
>> - 'values not equal "%s" and "%s"'
>> - % (str(result), str(value)))
>> + '"%s" is "%s", expected "%s"'
>> + % (path, str(result), str(value)))
>>   def assert_no_active_block_jobs(self):
>>   result = self.vm.qmp('query-block-jobs')
>>


-- 
Best regards,
Vladimir


Re: [PATCH v14 1/9] esp: add pseudo-DMA as used by Macintosh

2019-10-26 Thread Laurent Vivier
Le 25/10/2019 à 16:01, Paolo Bonzini a écrit :
> On 22/10/19 13:17, Laurent Vivier wrote:
>> +if (s->dma_memory_read) {
>> +s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len);
>> +} else {
>> +set_pdma(s, CMD, s->cmdlen, len);
>> +s->pdma_cb = do_dma_pdma_cb;
>> +esp_raise_drq(s);
>> +return;
>> +}
>> +trace_esp_handle_ti_cmd(s->cmdlen);
>> +s->ti_size = 0;
>> +s->cmdlen = 0;
>> +s->do_cmd = 0;
>> +do_cmd(s, s->cmdbuf);
>>  return;
> 
> Can you explain these lines after s->dma_memory_read?  I suppose they
> are related to
> 
>> -}
>> -if (s->do_cmd) {
>> +} else if (s->do_cmd) {
> 
> If so, it would be nice to make those a separate patch.  Otherwise seems
> okay.

Sent a new series with separate patches for ESP.

Could you have a look?

Thanks,
Laurent




[PATCH v15 11/11] BootLinuxConsoleTest: Test the Quadra 800

2019-10-26 Thread Laurent Vivier
From: Philippe Mathieu-Daudé 

This test boots a Linux kernel on a Quadra 800 board
and verify the serial is working.

Example:

  $ avocado --show=app,console run -t machine:q800 
tests/acceptance/boot_linux_console.py
  console: ABCFGHIJK
  console: Linux version 5.2.0-2-m68k (debian-ker...@lists.debian.org) (gcc 
version 8.3.0 (Debian 8.3.0-21)) #1 Debian 5.2.9-2 (2019-08-21)
  console: Detected Macintosh model: 35
  console: Apple Macintosh Quadra 800
  console: Built 1 zonelists, mobility grouping on.  Total pages: 32448
  console: Kernel command line: printk.time=0 console=ttyS0 vga=off
  [...]
  console: Calibrating delay loop... 1236.99 BogoMIPS (lpj=6184960)
  [...]
  console: NuBus: Scanning NuBus slots.
  console: Slot 9: Board resource not found!
  console: SCSI subsystem initialized
  console: clocksource: Switched to clocksource via1
  [...]
  console: macfb: framebuffer at 0xf9001000, mapped to 0x(ptrval), size 468k
  console: macfb: mode is 800x600x8, linelength=800
  console: Console: switching to colour frame buffer device 100x37
  console: fb0: DAFB frame buffer device
  console: pmac_zilog: 0.6 (Benjamin Herrenschmidt )
  console: scc.0: ttyS0 at MMIO 0x50f0c022 (irq = 4, base_baud = 230400) is a 
Z85c30 ESCC - Serial port
  console: scc.1: ttyS1 at MMIO 0x50f0c020 (irq = 4, base_baud = 230400) is a 
Z85c30 ESCC - Serial port
  console: Non-volatile memory driver v1.3
  console: adb: Mac II ADB Driver v1.0 for Unified ADB
  console: mousedev: PS/2 mouse device common for all mice
  console: random: fast init done
  console: Detected ADB keyboard, type .
  console: input: ADB keyboard as /devices/virtual/input/input0
  console: input: ADB mouse as /devices/virtual/input/input1
  console: rtc-generic rtc-generic: registered as rtc0
  console: ledtrig-cpu: registered to indicate activity on CPUs
  [...]
  console: rtc-generic rtc-generic: setting system clock to 2019-09-10T16:20:25 
UTC (1568132425)
  console: List of all partitions:
  console: No filesystem could mount root, tried:
  JOB TIME   : 2.91 s

Signed-off-by: Philippe Mathieu-Daudé 
Reviewed-by: Laurent Vivier 
Tested-by: Cleber Rosa 
Reviewed-by: Cleber Rosa 
Message-Id: <20190910163430.11326-1-f4...@amsat.org>
Signed-off-by: Laurent Vivier 
---
 tests/acceptance/boot_linux_console.py | 24 
 1 file changed, 24 insertions(+)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 8a9a314ab4..df27813c78 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -378,3 +378,27 @@ class BootLinuxConsole(Test):
 self.vm.launch()
 console_pattern = 'Kernel command line: %s' % kernel_command_line
 self.wait_for_console_pattern(console_pattern)
+
+def test_m68k_q800(self):
+"""
+:avocado: tags=arch:m68k
+:avocado: tags=machine:q800
+"""
+deb_url = ('http://ftp.ports.debian.org/debian-ports/pool-m68k/main'
+   '/l/linux/kernel-image-5.2.0-2-m68k-di_5.2.9-2_m68k.udeb')
+deb_hash = '0797e05129595f22f3c0142db5e199769a723bf9'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path,
+'/boot/vmlinux-5.2.0-2-m68k')
+
+self.vm.set_machine('q800')
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'console=ttyS0 vga=off')
+self.vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line)
+self.vm.launch()
+console_pattern = 'Kernel command line: %s' % kernel_command_line
+self.wait_for_console_pattern(console_pattern)
+console_pattern = 'No filesystem could mount root'
+self.wait_for_console_pattern(console_pattern)
-- 
2.21.0




[PATCH v15 07/11] hw/m68k: add Nubus support

2019-10-26 Thread Laurent Vivier
This patch adds basic support for the NuBus bus. This is used by 680x0
Macintosh.

Co-developed-by: Mark Cave-Ayland 
Signed-off-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
Reviewed-by: Thomas Huth 
---
 include/hw/nubus/mac-nubus-bridge.h |  24 
 include/hw/nubus/nubus.h|  69 +
 hw/nubus/mac-nubus-bridge.c |  45 ++
 hw/nubus/nubus-bridge.c |  34 +
 hw/nubus/nubus-bus.c| 111 ++
 hw/nubus/nubus-device.c | 215 
 MAINTAINERS |   2 +
 hw/Kconfig  |   1 +
 hw/Makefile.objs|   1 +
 hw/m68k/Kconfig |   1 +
 hw/nubus/Kconfig|   2 +
 hw/nubus/Makefile.objs  |   4 +
 12 files changed, 509 insertions(+)
 create mode 100644 include/hw/nubus/mac-nubus-bridge.h
 create mode 100644 include/hw/nubus/nubus.h
 create mode 100644 hw/nubus/mac-nubus-bridge.c
 create mode 100644 hw/nubus/nubus-bridge.c
 create mode 100644 hw/nubus/nubus-bus.c
 create mode 100644 hw/nubus/nubus-device.c
 create mode 100644 hw/nubus/Kconfig
 create mode 100644 hw/nubus/Makefile.objs

diff --git a/include/hw/nubus/mac-nubus-bridge.h 
b/include/hw/nubus/mac-nubus-bridge.h
new file mode 100644
index 00..ce9c789d99
--- /dev/null
+++ b/include/hw/nubus/mac-nubus-bridge.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013-2018 Laurent Vivier 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef HW_NUBUS_MAC_H
+#define HW_NUBUS_MAC_H
+
+#include "hw/nubus/nubus.h"
+
+#define TYPE_MAC_NUBUS_BRIDGE "mac-nubus-bridge"
+#define MAC_NUBUS_BRIDGE(obj) OBJECT_CHECK(MacNubusState, (obj), \
+   TYPE_MAC_NUBUS_BRIDGE)
+
+typedef struct MacNubusState {
+SysBusDevice sysbus_dev;
+
+NubusBus *bus;
+} MacNubusState;
+
+#endif
diff --git a/include/hw/nubus/nubus.h b/include/hw/nubus/nubus.h
new file mode 100644
index 00..a8634e54c5
--- /dev/null
+++ b/include/hw/nubus/nubus.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013-2018 Laurent Vivier 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef HW_NUBUS_NUBUS_H
+#define HW_NUBUS_NUBUS_H
+
+#include "hw/qdev-properties.h"
+#include "exec/address-spaces.h"
+
+#define NUBUS_SUPER_SLOT_SIZE 0x1000U
+#define NUBUS_SUPER_SLOT_NB   0x9
+
+#define NUBUS_SLOT_SIZE   0x0100
+#define NUBUS_SLOT_NB 0xF
+
+#define NUBUS_FIRST_SLOT  0x9
+#define NUBUS_LAST_SLOT   0xF
+
+#define TYPE_NUBUS_DEVICE "nubus-device"
+#define NUBUS_DEVICE(obj) \
+ OBJECT_CHECK(NubusDevice, (obj), TYPE_NUBUS_DEVICE)
+
+#define TYPE_NUBUS_BUS "nubus-bus"
+#define NUBUS_BUS(obj) OBJECT_CHECK(NubusBus, (obj), TYPE_NUBUS_BUS)
+
+#define TYPE_NUBUS_BRIDGE "nubus-bridge"
+#define NUBUS_BRIDGE(obj) OBJECT_CHECK(NubusBridge, (obj), TYPE_NUBUS_BRIDGE)
+
+typedef struct NubusBus {
+BusState qbus;
+
+MemoryRegion super_slot_io;
+MemoryRegion slot_io;
+
+int current_slot;
+} NubusBus;
+
+typedef struct NubusDevice {
+DeviceState qdev;
+
+int slot_nb;
+MemoryRegion slot_mem;
+
+/* Format Block */
+
+MemoryRegion fblock_io;
+
+uint32_t rom_length;
+uint32_t rom_crc;
+uint8_t rom_rev;
+uint8_t rom_format;
+uint8_t byte_lanes;
+int32_t directory_offset;
+
+/* ROM */
+
+MemoryRegion rom_io;
+const uint8_t *rom;
+} NubusDevice;
+
+void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t size,
+int revision, int format, uint8_t byte_lanes);
+
+#endif
diff --git a/hw/nubus/mac-nubus-bridge.c b/hw/nubus/mac-nubus-bridge.c
new file mode 100644
index 00..7c329300b8
--- /dev/null
+++ b/hw/nubus/mac-nubus-bridge.c
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (c) 2013-2018 Laurent Vivier 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/nubus/mac-nubus-bridge.h"
+
+
+static void mac_nubus_bridge_init(Object *obj)
+{
+MacNubusState *s = MAC_NUBUS_BRIDGE(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+s->bus = NUBUS_BUS(qbus_create(TYPE_NUBUS_BUS, DEVICE(s), NULL));
+
+sysbus_init_mmio(sbd, >bus->super_slot_io);
+sysbus_init_mmio(sbd, >bus->slot_io);
+}
+
+static void mac_nubus_bridge_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->desc = "Nubus bridge";
+}
+
+static const TypeInfo mac_nubus_bridge_info = {
+.name  = TYPE_MAC_NUBUS_BRIDGE,
+.parent= TYPE_NUBUS_BRIDGE,
+.instance_init = mac_nubus_bridge_init,
+.instance_size = sizeof(MacNubusState),
+.class_init= 

Re: [PATCH] qcow2-bitmap: Fix uint64_t left-shift overflow

2019-10-26 Thread Vladimir Sementsov-Ogievskiy
26.10.2019 12:19, Tuguoyi wrote:
> In check_constraints_on_bitmap(), the sanity check on the
> granularity will cause uint64_t integer left-shift overflow
> when cluster_size is 2M and the granularity is bigger than
> 32K which is even smaller than the default value for a qcow2
> disk with cluster_size set to 64k or bigger. This patch fix
> the issue by right-shift @len instead.
> 
> Signed-off-by: Guoyi Tu 
> ---
>   block/qcow2-bitmap.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
> index 98294a7..2a1d789 100644
> --- a/block/qcow2-bitmap.c
> +++ b/block/qcow2-bitmap.c
> @@ -172,8 +172,8 @@ static int check_constraints_on_bitmap(BlockDriverState 
> *bs,
>   }
> 
>   if ((len > (uint64_t)BME_MAX_PHYS_SIZE << granularity_bits) ||
> -(len > (uint64_t)BME_MAX_TABLE_SIZE * s->cluster_size <<
> -   granularity_bits))

Hmm.
BME_MAX_TABLE_SIZE = 0x800

0x800 * 1024 * 1024 * 2 << 16 = 2 ** 64, so for 64k granularity it 
owerflows..
But for 32k doesn't. Or am I wrong?

Anyway, thanks for fixing!

> +((len >> granularity_bits) > (uint64_t)BME_MAX_TABLE_SIZE *
> +s->cluster_size))

It's a bit incorrect, as len may be unaligned, we need ((len + granularity - 1) 
>> granularity_bits) on the left,
or better DIV_ROUNTD_UP(len, granularity).

>   {
>   error_setg(errp, "Too much space will be occupied by the bitmap. "
>  "Use larger granularity");
> --
> 2.7.4
> -
> 本邮件及其附件含有新华三集团的保密信息,仅限于发送给上面地址中列出
> 的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、
> 或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本
> 邮件!
> This e-mail and its attachments contain confidential information from New 
> H3C, which is
> intended only for the person or entity whose address is listed above. Any use 
> of the
> information contained herein in any way (including, but not limited to, total 
> or partial
> disclosure, reproduction, or dissemination) by persons other than the intended
> recipient(s) is prohibited. If you receive this e-mail in error, please 
> notify the sender
> by phone or email immediately and delete it!
> 

Not sure that this is possible, as it's automatically available here:
https://lists.gnu.org/archive/html/qemu-devel/2019-10/msg07336.html


-- 
Best regards,
Vladimir


[PATCH v15 05/11] hw/m68k: add VIA support

2019-10-26 Thread Laurent Vivier
Inside the 680x0 Macintosh, VIA (Versatile Interface Adapter) is used
to interface the keyboard, Mouse, and real-time clock. It also provides
control line for the floppy disk driver, video interface, sound circuitry
and serial interface.

This implementation is based on the MOS6522 object.

Co-developed-by: Mark Cave-Ayland 
Signed-off-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
Reviewed-by: Hervé Poussineau 
---
 default-configs/m68k-softmmu.mak |   1 +
 include/hw/misc/mac_via.h| 108 +
 hw/misc/mac_via.c| 767 +++
 MAINTAINERS  |   6 +
 hw/m68k/Kconfig  |   4 +
 hw/misc/Kconfig  |   4 +
 hw/misc/Makefile.objs|   1 +
 7 files changed, 891 insertions(+)
 create mode 100644 include/hw/misc/mac_via.h
 create mode 100644 hw/misc/mac_via.c

diff --git a/default-configs/m68k-softmmu.mak b/default-configs/m68k-softmmu.mak
index d67ab8b96d..6629fd2aa3 100644
--- a/default-configs/m68k-softmmu.mak
+++ b/default-configs/m68k-softmmu.mak
@@ -7,3 +7,4 @@ CONFIG_SEMIHOSTING=y
 CONFIG_AN5206=y
 CONFIG_MCF5208=y
 CONFIG_NEXTCUBE=y
+CONFIG_Q800=y
diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
new file mode 100644
index 00..efc8ef3ce3
--- /dev/null
+++ b/include/hw/misc/mac_via.h
@@ -0,0 +1,108 @@
+/*
+ *
+ * Copyright (c) 2011-2018 Laurent Vivier
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_MISC_MAC_VIA_H
+#define HW_MISC_MAC_VIA_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+#include "hw/misc/mos6522.h"
+
+
+/* VIA 1 */
+#define VIA1_IRQ_ONE_SECOND_BIT 0
+#define VIA1_IRQ_VBLANK_BIT 1
+#define VIA1_IRQ_ADB_READY_BIT  2
+#define VIA1_IRQ_ADB_DATA_BIT   3
+#define VIA1_IRQ_ADB_CLOCK_BIT  4
+
+#define VIA1_IRQ_NB 8
+
+#define VIA1_IRQ_ONE_SECOND (1 << VIA1_IRQ_ONE_SECOND_BIT)
+#define VIA1_IRQ_VBLANK (1 << VIA1_IRQ_VBLANK_BIT)
+#define VIA1_IRQ_ADB_READY  (1 << VIA1_IRQ_ADB_READY_BIT)
+#define VIA1_IRQ_ADB_DATA   (1 << VIA1_IRQ_ADB_DATA_BIT)
+#define VIA1_IRQ_ADB_CLOCK  (1 << VIA1_IRQ_ADB_CLOCK_BIT)
+
+
+#define TYPE_MOS6522_Q800_VIA1 "mos6522-q800-via1"
+#define MOS6522_Q800_VIA1(obj)  OBJECT_CHECK(MOS6522Q800VIA1State, (obj), \
+TYPE_MOS6522_Q800_VIA1)
+
+typedef struct MOS6522Q800VIA1State {
+/*< private >*/
+MOS6522State parent_obj;
+
+qemu_irq irqs[VIA1_IRQ_NB];
+uint8_t last_b;
+uint8_t PRAM[256];
+
+/* external timers */
+QEMUTimer *one_second_timer;
+int64_t next_second;
+QEMUTimer *VBL_timer;
+int64_t next_VBL;
+} MOS6522Q800VIA1State;
+
+
+/* VIA 2 */
+#define VIA2_IRQ_SCSI_DATA_BIT  0
+#define VIA2_IRQ_SLOT_BIT   1
+#define VIA2_IRQ_UNUSED_BIT 2
+#define VIA2_IRQ_SCSI_BIT   3
+#define VIA2_IRQ_ASC_BIT4
+
+#define VIA2_IRQ_NB 8
+
+#define VIA2_IRQ_SCSI_DATA  (1 << VIA2_IRQ_SCSI_DATA_BIT)
+#define VIA2_IRQ_SLOT   (1 << VIA2_IRQ_SLOT_BIT)
+#define VIA2_IRQ_UNUSED (1 << VIA2_IRQ_SCSI_BIT)
+#define VIA2_IRQ_SCSI   (1 << VIA2_IRQ_UNUSED_BIT)
+#define VIA2_IRQ_ASC(1 << VIA2_IRQ_ASC_BIT)
+
+#define TYPE_MOS6522_Q800_VIA2 "mos6522-q800-via2"
+#define MOS6522_Q800_VIA2(obj)  OBJECT_CHECK(MOS6522Q800VIA2State, (obj), \
+TYPE_MOS6522_Q800_VIA2)
+
+typedef struct MOS6522Q800VIA2State {
+/*< private >*/
+MOS6522State parent_obj;
+} MOS6522Q800VIA2State;
+
+
+#define TYPE_MAC_VIA "mac_via"
+#define MAC_VIA(obj)   OBJECT_CHECK(MacVIAState, (obj), TYPE_MAC_VIA)
+
+typedef struct MacVIAState {
+SysBusDevice busdev;
+
+/* MMIO */
+MemoryRegion mmio;
+MemoryRegion via1mem;
+MemoryRegion via2mem;
+
+/* VIAs */
+MOS6522Q800VIA1State mos6522_via1;
+MOS6522Q800VIA2State mos6522_via2;
+
+/* RTC */
+uint32_t tick_offset;
+
+uint8_t data_out;
+int data_out_cnt;
+uint8_t data_in;
+uint8_t data_in_cnt;
+uint8_t cmd;
+int wprotect;
+int alt;
+
+/* ADB */
+ADBBusState adb_bus;
+} MacVIAState;
+
+#endif
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
new file mode 100644
index 00..d2da8b8e60
--- /dev/null
+++ b/hw/misc/mac_via.c
@@ -0,0 +1,767 @@
+/*
+ * QEMU m68k Macintosh VIA device support
+ *
+ * Copyright (c) 2011-2018 Laurent Vivier
+ * Copyright (c) 2018 Mark Cave-Ayland
+ *
+ * Some parts from hw/misc/macio/cuda.c
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * some parts from linux-2.6.29, arch/m68k/include/asm/mac_via.h
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "migration/vmstate.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "qemu/timer.h"
+#include "hw/misc/mac_via.h"

[PATCH v15 10/11] hw/m68k: define Macintosh Quadra 800

2019-10-26 Thread Laurent Vivier
If you want to test the machine, it doesn't yet boot a MacROM, but you can
boot a linux kernel from the command line.

You can install your own disk using debian-installer with:

./qemu-system-m68k \
-M q800 \
-serial none -serial mon:stdio \
-m 1000M -drive file=m68k.qcow2,format=qcow2 \
-net nic,model=dp83932,addr=09:00:07:12:34:57 \
-append "console=ttyS0 vga=off" \
-kernel vmlinux-4.15.0-2-m68k \
-initrd initrd.gz \
-drive file=debian-9.0-m68k-NETINST-1.iso \
-drive file=m68k.qcow2,format=qcow2 \
-nographic

If you use a graphic adapter instead of "-nographic", you can use "-g"
to set the size of the display (I use "-g 1600x800x24").

Tested-by: Philippe Mathieu-Daudé 
Co-developed-by: Mark Cave-Ayland 
Signed-off-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
---
 hw/m68k/bootinfo.h| 114 
 hw/m68k/q800.c| 401 ++
 MAINTAINERS   |   2 +
 hw/m68k/Kconfig   |   3 +
 hw/m68k/Makefile.objs |   1 +
 5 files changed, 521 insertions(+)
 create mode 100644 hw/m68k/bootinfo.h
 create mode 100644 hw/m68k/q800.c

diff --git a/hw/m68k/bootinfo.h b/hw/m68k/bootinfo.h
new file mode 100644
index 00..5f8ded2686
--- /dev/null
+++ b/hw/m68k/bootinfo.h
@@ -0,0 +1,114 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ *
+ * Bootinfo tags from linux bootinfo.h and bootinfo-mac.h:
+ * This is an easily parsable and extendable structure containing all
+ * information to be passed from the bootstrap to the kernel
+ *
+ * This structure is copied right after the kernel by the bootstrap
+ * routine.
+ */
+
+#ifndef HW_M68K_BOOTINFO_H
+#define HW_M68K_BOOTINFO_H
+struct bi_record {
+uint16_t tag;/* tag ID */
+uint16_t size;   /* size of record */
+uint32_t data[0];/* data */
+};
+
+/* machine independent tags */
+
+#define BI_LAST 0x /* last record */
+#define BI_MACHTYPE 0x0001 /* machine type (u_long) */
+#define BI_CPUTYPE  0x0002 /* cpu type (u_long) */
+#define BI_FPUTYPE  0x0003 /* fpu type (u_long) */
+#define BI_MMUTYPE  0x0004 /* mmu type (u_long) */
+#define BI_MEMCHUNK 0x0005 /* memory chunk address and size */
+   /* (struct mem_info) */
+#define BI_RAMDISK  0x0006 /* ramdisk address and size */
+   /* (struct mem_info) */
+#define BI_COMMAND_LINE 0x0007 /* kernel command line parameters */
+   /* (string) */
+
+/*  Macintosh-specific tags (all u_long) */
+
+#define BI_MAC_MODEL0x8000  /* Mac Gestalt ID (model type) */
+#define BI_MAC_VADDR0x8001  /* Mac video base address */
+#define BI_MAC_VDEPTH   0x8002  /* Mac video depth */
+#define BI_MAC_VROW 0x8003  /* Mac video rowbytes */
+#define BI_MAC_VDIM 0x8004  /* Mac video dimensions */
+#define BI_MAC_VLOGICAL 0x8005  /* Mac video logical base */
+#define BI_MAC_SCCBASE  0x8006  /* Mac SCC base address */
+#define BI_MAC_BTIME0x8007  /* Mac boot time */
+#define BI_MAC_GMTBIAS  0x8008  /* Mac GMT timezone offset */
+#define BI_MAC_MEMSIZE  0x8009  /* Mac RAM size (sanity check) */
+#define BI_MAC_CPUID0x800a  /* Mac CPU type (sanity check) */
+#define BI_MAC_ROMBASE  0x800b  /* Mac system ROM base address */
+
+/*  Macintosh hardware profile data */
+
+#define BI_MAC_VIA1BASE 0x8010  /* Mac VIA1 base address (always present) */
+#define BI_MAC_VIA2BASE 0x8011  /* Mac VIA2 base address (type varies) */
+#define BI_MAC_VIA2TYPE 0x8012  /* Mac VIA2 type (VIA, RBV, OSS) */
+#define BI_MAC_ADBTYPE  0x8013  /* Mac ADB interface type */
+#define BI_MAC_ASCBASE  0x8014  /* Mac Apple Sound Chip base address */
+#define BI_MAC_SCSI5380 0x8015  /* Mac NCR 5380 SCSI (base address, multi) */
+#define BI_MAC_SCSIDMA  0x8016  /* Mac SCSI DMA (base address) */
+#define BI_MAC_SCSI5396 0x8017  /* Mac NCR 53C96 SCSI (base address, multi) */
+#define BI_MAC_IDETYPE  0x8018  /* Mac IDE interface type */
+#define BI_MAC_IDEBASE  0x8019  /* Mac IDE interface base address */
+#define BI_MAC_NUBUS0x801a  /* Mac Nubus type (none, regular, pseudo) */
+#define BI_MAC_SLOTMASK 0x801b  /* Mac Nubus slots present */
+#define BI_MAC_SCCTYPE  0x801c  /* Mac SCC serial type (normal, IOP) */
+#define BI_MAC_ETHTYPE  0x801d  /* Mac builtin ethernet type (Sonic, MACE */
+#define BI_MAC_ETHBASE  0x801e  /* Mac builtin ethernet base address */
+#define BI_MAC_PMU  0x801f  /* Mac power management / poweroff hardware */
+#define BI_MAC_IOP_SWIM 0x8020  /* Mac SWIM floppy IOP */
+#define BI_MAC_IOP_ADB  0x8021  /* Mac ADB IOP */
+
+#define BOOTINFO0(as, base, id) \
+do { \
+stw_phys(as, base, id); \
+base += 2; \
+stw_phys(as, base, sizeof(struct bi_record)); \
+base += 2; \
+} while (0)
+
+#define BOOTINFO1(as, base, id, value) \
+do { \
+stw_phys(as, base, id); \
+base += 2; \
+stw_phys(as, base, sizeof(struct 

[PATCH v15 03/11] esp: add pseudo-DMA as used by Macintosh

2019-10-26 Thread Laurent Vivier
There is no DMA in Quadra 800, so the CPU reads/writes the data from the
PDMA register (offset 0x100, ESP_PDMA in hw/m68k/q800.c) and copies them
to/from the memory.

There is a nice assembly loop in the kernel to do that, see
linux/drivers/scsi/mac_esp.c:MAC_ESP_PDMA_LOOP().

The start of the transfer is triggered by the DREQ interrupt (see linux
mac_esp_send_pdma_cmd()), the CPU polls on the IRQ flag to start the
transfer after a SCSI command has been sent (in Quadra 800 it goes
through the VIA2, the via2-irq line and the vIFR register)

The Macintosh hardware includes hardware handshaking to prevent the CPU
from reading invalid data or writing data faster than the peripheral
device can accept it.

This is the "blind mode", and from the doc:
"Approximate maximum SCSI transfer rates within a blocks are 1.4 MB per
second for blind transfers in the Macintosh II"

Some references can be found in:
  Apple Macintosh Family Hardware Reference, ISBN 0-201-19255-1
  Guide to the Macintosh Family Hardware, ISBN-0-201-52405-8

Acked-by: Dr. David Alan Gilbert 
Co-developed-by: Mark Cave-Ayland 
Signed-off-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
---
 include/hw/scsi/esp.h |  15 +++
 hw/scsi/esp.c | 278 --
 2 files changed, 284 insertions(+), 9 deletions(-)

diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index adab63d1c9..6ba47dac41 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -14,10 +14,18 @@ typedef void (*ESPDMAMemoryReadWriteFunc)(void *opaque, 
uint8_t *buf, int len);
 
 typedef struct ESPState ESPState;
 
+enum pdma_origin_id {
+PDMA,
+TI,
+CMD,
+ASYNC,
+};
+
 struct ESPState {
 uint8_t rregs[ESP_REGS];
 uint8_t wregs[ESP_REGS];
 qemu_irq irq;
+qemu_irq irq_data;
 uint8_t chip_id;
 bool tchi_written;
 int32_t ti_size;
@@ -48,6 +56,12 @@ struct ESPState {
 ESPDMAMemoryReadWriteFunc dma_memory_write;
 void *dma_opaque;
 void (*dma_cb)(ESPState *s);
+uint8_t pdma_buf[32];
+int pdma_origin;
+uint32_t pdma_len;
+uint32_t pdma_start;
+uint32_t pdma_cur;
+void (*pdma_cb)(ESPState *s);
 };
 
 #define TYPE_ESP "esp"
@@ -59,6 +73,7 @@ typedef struct {
 /*< public >*/
 
 MemoryRegion iomem;
+MemoryRegion pdma;
 uint32_t it_shift;
 ESPState esp;
 } SysBusESPState;
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 0230ede21d..f8fc30cccb 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -38,6 +38,8 @@
  * 
http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
  * and
  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
+ *
+ * On Macintosh Quadra it is a NCR53C96.
  */
 
 static void esp_raise_irq(ESPState *s)
@@ -58,6 +60,16 @@ static void esp_lower_irq(ESPState *s)
 }
 }
 
+static void esp_raise_drq(ESPState *s)
+{
+qemu_irq_raise(s->irq_data);
+}
+
+static void esp_lower_drq(ESPState *s)
+{
+qemu_irq_lower(s->irq_data);
+}
+
 void esp_dma_enable(ESPState *s, int irq, int level)
 {
 if (level) {
@@ -84,6 +96,30 @@ void esp_request_cancelled(SCSIRequest *req)
 }
 }
 
+static void set_pdma(ESPState *s, enum pdma_origin_id origin,
+ uint32_t index, uint32_t len)
+{
+s->pdma_origin = origin;
+s->pdma_start = index;
+s->pdma_cur = index;
+s->pdma_len = len;
+}
+
+static uint8_t *get_pdma_buf(ESPState *s)
+{
+switch (s->pdma_origin) {
+case PDMA:
+return s->pdma_buf;
+case TI:
+return s->ti_buf;
+case CMD:
+return s->cmdbuf;
+case ASYNC:
+return s->async_buf;
+}
+return NULL;
+}
+
 static int get_cmd_cb(ESPState *s)
 {
 int target;
@@ -125,7 +161,14 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t 
buflen)
 if (dmalen > buflen) {
 return 0;
 }
-s->dma_memory_read(s->dma_opaque, buf, dmalen);
+if (s->dma_memory_read) {
+s->dma_memory_read(s->dma_opaque, buf, dmalen);
+} else {
+memcpy(s->pdma_buf, buf, dmalen);
+set_pdma(s, PDMA, 0, dmalen);
+esp_raise_drq(s);
+return 0;
+}
 } else {
 dmalen = s->ti_size;
 if (dmalen > TI_BUFSZ) {
@@ -177,6 +220,16 @@ static void do_cmd(ESPState *s, uint8_t *buf)
 do_busid_cmd(s, [1], busid);
 }
 
+static void satn_pdma_cb(ESPState *s)
+{
+if (get_cmd_cb(s) < 0) {
+return;
+}
+if (s->pdma_cur != s->pdma_start) {
+do_cmd(s, get_pdma_buf(s) + s->pdma_start);
+}
+}
+
 static void handle_satn(ESPState *s)
 {
 uint8_t buf[32];
@@ -186,11 +239,22 @@ static void handle_satn(ESPState *s)
 s->dma_cb = handle_satn;
 return;
 }
+s->pdma_cb = satn_pdma_cb;
 len = get_cmd(s, buf, sizeof(buf));
 if (len)
 do_cmd(s, buf);
 }
 
+static void s_without_satn_pdma_cb(ESPState *s)
+{
+if (get_cmd_cb(s) < 0) {
+return;

[PATCH v15 08/11] hw/m68k: add Nubus macfb video card

2019-10-26 Thread Laurent Vivier
This patch adds support for a graphic framebuffer device.
This device can be added as a sysbus device or as a NuBus device.

It is accessed as a framebuffer but the color palette can be set.

Co-developed-by: Mark Cave-Ayland 
Signed-off-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
Reviewed-by: Hervé Poussineau 
Reviewed-by: Thomas Huth 
---
 include/hw/display/macfb.h |  64 +
 arch_init.c|   4 +
 hw/display/macfb.c | 477 +
 vl.c   |   3 +-
 MAINTAINERS|   2 +
 hw/display/Kconfig |   5 +
 hw/display/Makefile.objs   |   1 +
 hw/m68k/Kconfig|   1 +
 qemu-options.hx|   2 +-
 9 files changed, 557 insertions(+), 2 deletions(-)
 create mode 100644 include/hw/display/macfb.h
 create mode 100644 hw/display/macfb.c

diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h
new file mode 100644
index 00..26367ae2c4
--- /dev/null
+++ b/include/hw/display/macfb.h
@@ -0,0 +1,64 @@
+/*
+ * QEMU Motorola 680x0 Macintosh Video Card Emulation
+ * Copyright (c) 2012-2018 Laurent Vivier
+ *
+ * some parts from QEMU G364 framebuffer Emulator.
+ * Copyright (c) 2007-2011 Herve Poussineau
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef MACFB_H
+#define MACFB_H
+
+#include "qemu/osdep.h"
+#include "exec/memory.h"
+#include "ui/console.h"
+
+typedef struct MacfbState {
+MemoryRegion mem_vram;
+MemoryRegion mem_ctrl;
+QemuConsole *con;
+
+uint8_t *vram;
+uint32_t vram_bit_mask;
+uint32_t palette_current;
+uint8_t color_palette[256 * 3];
+uint32_t width, height; /* in pixels */
+uint8_t depth;
+} MacfbState;
+
+#define TYPE_MACFB "sysbus-macfb"
+#define MACFB(obj) \
+OBJECT_CHECK(MacfbSysBusState, (obj), TYPE_MACFB)
+
+typedef struct {
+SysBusDevice busdev;
+
+MacfbState macfb;
+} MacfbSysBusState;
+
+#define MACFB_NUBUS_DEVICE_CLASS(class) \
+OBJECT_CLASS_CHECK(MacfbNubusDeviceClass, (class), TYPE_NUBUS_MACFB)
+#define MACFB_NUBUS_GET_CLASS(obj) \
+OBJECT_GET_CLASS(MacfbNubusDeviceClass, (obj), TYPE_NUBUS_MACFB)
+
+typedef struct MacfbNubusDeviceClass {
+DeviceClass parent_class;
+
+DeviceRealize parent_realize;
+} MacfbNubusDeviceClass;
+
+#define TYPE_NUBUS_MACFB "nubus-macfb"
+#define NUBUS_MACFB(obj) \
+OBJECT_CHECK(MacfbNubusState, (obj), TYPE_NUBUS_MACFB)
+
+typedef struct {
+NubusDevice busdev;
+
+MacfbState macfb;
+} MacfbNubusState;
+
+#endif
diff --git a/arch_init.c b/arch_init.c
index 0a1531124c..705d0b94ad 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -38,6 +38,10 @@
 int graphic_width = 1024;
 int graphic_height = 768;
 int graphic_depth = 8;
+#elif defined(TARGET_M68K)
+int graphic_width = 800;
+int graphic_height = 600;
+int graphic_depth = 8;
 #else
 int graphic_width = 800;
 int graphic_height = 600;
diff --git a/hw/display/macfb.c b/hw/display/macfb.c
new file mode 100644
index 00..f4fa8e3206
--- /dev/null
+++ b/hw/display/macfb.c
@@ -0,0 +1,477 @@
+/*
+ * QEMU Motorola 680x0 Macintosh Video Card Emulation
+ * Copyright (c) 2012-2018 Laurent Vivier
+ *
+ * some parts from QEMU G364 framebuffer Emulator.
+ * Copyright (c) 2007-2011 Herve Poussineau
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "hw/sysbus.h"
+#include "ui/console.h"
+#include "ui/pixel_ops.h"
+#include "hw/nubus/nubus.h"
+#include "hw/display/macfb.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+
+#define VIDEO_BASE 0x1000
+#define DAFB_BASE  0x0080
+
+#define MACFB_PAGE_SIZE 4096
+#define MACFB_VRAM_SIZE (4 * MiB)
+
+#define DAFB_RESET  0x200
+#define DAFB_LUT0x213
+
+
+typedef void macfb_draw_line_func(MacfbState *s, uint8_t *d, uint32_t addr,
+  int width);
+
+static inline uint8_t macfb_read_byte(MacfbState *s, uint32_t addr)
+{
+return s->vram[addr & s->vram_bit_mask];
+}
+
+/* 1-bit color */
+static void macfb_draw_line1(MacfbState *s, uint8_t *d, uint32_t addr,
+ int width)
+{
+uint8_t r, g, b;
+int x;
+
+for (x = 0; x < width; x++) {
+int bit = x & 7;
+int idx = (macfb_read_byte(s, addr) >> (7 - bit)) & 1;
+r = g = b  = ((1 - idx) << 7);
+addr += (bit == 7);
+
+*(uint32_t *)d = rgb_to_pixel32(r, g, b);
+d += 4;
+}
+}
+
+/* 2-bit color */
+static void macfb_draw_line2(MacfbState *s, uint8_t *d, uint32_t addr,
+ int width)
+{
+uint8_t r, g, b;
+int x;
+
+for (x = 0; x < width; x++) {
+int bit = (x & 3);
+int idx = (macfb_read_byte(s, 

[PATCH v15 04/11] dp8393x: manage big endian bus

2019-10-26 Thread Laurent Vivier
This is needed by Quadra 800, this card can run on little-endian
or big-endian bus.

Signed-off-by: Laurent Vivier 
Tested-by: Hervé Poussineau 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Hervé Poussineau 
---
 hw/net/dp8393x.c | 88 +++-
 1 file changed, 57 insertions(+), 31 deletions(-)

diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index a5678e11fa..693e244ce6 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -153,6 +153,7 @@ typedef struct dp8393xState {
 
 /* Hardware */
 uint8_t it_shift;
+bool big_endian;
 qemu_irq irq;
 #ifdef DEBUG_SONIC
 int irq_level;
@@ -223,6 +224,29 @@ static uint32_t dp8393x_wt(dp8393xState *s)
 return s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
 }
 
+static uint16_t dp8393x_get(dp8393xState *s, int width, uint16_t *base,
+int offset)
+{
+uint16_t val;
+
+if (s->big_endian) {
+val = be16_to_cpu(base[offset * width + width - 1]);
+} else {
+val = le16_to_cpu(base[offset * width]);
+}
+return val;
+}
+
+static void dp8393x_put(dp8393xState *s, int width, uint16_t *base, int offset,
+uint16_t val)
+{
+if (s->big_endian) {
+base[offset * width + width - 1] = cpu_to_be16(val);
+} else {
+base[offset * width] = cpu_to_le16(val);
+}
+}
+
 static void dp8393x_update_irq(dp8393xState *s)
 {
 int level = (s->regs[SONIC_IMR] & s->regs[SONIC_ISR]) ? 1 : 0;
@@ -254,12 +278,12 @@ static void dp8393x_do_load_cam(dp8393xState *s)
 /* Fill current entry */
 address_space_rw(>as, dp8393x_cdp(s),
 MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
-s->cam[index][0] = data[1 * width] & 0xff;
-s->cam[index][1] = data[1 * width] >> 8;
-s->cam[index][2] = data[2 * width] & 0xff;
-s->cam[index][3] = data[2 * width] >> 8;
-s->cam[index][4] = data[3 * width] & 0xff;
-s->cam[index][5] = data[3 * width] >> 8;
+s->cam[index][0] = dp8393x_get(s, width, data, 1) & 0xff;
+s->cam[index][1] = dp8393x_get(s, width, data, 1) >> 8;
+s->cam[index][2] = dp8393x_get(s, width, data, 2) & 0xff;
+s->cam[index][3] = dp8393x_get(s, width, data, 2) >> 8;
+s->cam[index][4] = dp8393x_get(s, width, data, 3) & 0xff;
+s->cam[index][5] = dp8393x_get(s, width, data, 3) >> 8;
 DPRINTF("load cam[%d] with %02x%02x%02x%02x%02x%02x\n", index,
 s->cam[index][0], s->cam[index][1], s->cam[index][2],
 s->cam[index][3], s->cam[index][4], s->cam[index][5]);
@@ -272,7 +296,7 @@ static void dp8393x_do_load_cam(dp8393xState *s)
 /* Read CAM enable */
 address_space_rw(>as, dp8393x_cdp(s),
 MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
-s->regs[SONIC_CE] = data[0 * width];
+s->regs[SONIC_CE] = dp8393x_get(s, width, data, 0);
 DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]);
 
 /* Done */
@@ -293,10 +317,10 @@ static void dp8393x_do_read_rra(dp8393xState *s)
 MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
 
 /* Update SONIC registers */
-s->regs[SONIC_CRBA0] = data[0 * width];
-s->regs[SONIC_CRBA1] = data[1 * width];
-s->regs[SONIC_RBWC0] = data[2 * width];
-s->regs[SONIC_RBWC1] = data[3 * width];
+s->regs[SONIC_CRBA0] = dp8393x_get(s, width, data, 0);
+s->regs[SONIC_CRBA1] = dp8393x_get(s, width, data, 1);
+s->regs[SONIC_RBWC0] = dp8393x_get(s, width, data, 2);
+s->regs[SONIC_RBWC1] = dp8393x_get(s, width, data, 3);
 DPRINTF("CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x\n",
 s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1],
 s->regs[SONIC_RBWC0], s->regs[SONIC_RBWC1]);
@@ -411,12 +435,12 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
 tx_len = 0;
 
 /* Update registers */
-s->regs[SONIC_TCR] = data[0 * width] & 0xf000;
-s->regs[SONIC_TPS] = data[1 * width];
-s->regs[SONIC_TFC] = data[2 * width];
-s->regs[SONIC_TSA0] = data[3 * width];
-s->regs[SONIC_TSA1] = data[4 * width];
-s->regs[SONIC_TFS] = data[5 * width];
+s->regs[SONIC_TCR] = dp8393x_get(s, width, data, 0) & 0xf000;
+s->regs[SONIC_TPS] = dp8393x_get(s, width, data, 1);
+s->regs[SONIC_TFC] = dp8393x_get(s, width, data, 2);
+s->regs[SONIC_TSA0] = dp8393x_get(s, width, data, 3);
+s->regs[SONIC_TSA1] = dp8393x_get(s, width, data, 4);
+s->regs[SONIC_TFS] = dp8393x_get(s, width, data, 5);
 
 /* Handle programmable interrupt */
 if (s->regs[SONIC_TCR] & SONIC_TCR_PINT) {
@@ -442,9 +466,9 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
 address_space_rw(>as,
 dp8393x_ttda(s) + sizeof(uint16_t) * (4 + 3 * i) * width,
 MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
-s->regs[SONIC_TSA0] = 

[PATCH v15 00/11] hw/m68k: add Apple Machintosh Quadra 800 machine

2019-10-26 Thread Laurent Vivier
I'm rebasing some of these patches for seven years now,
too many years...

if you want to test the machine, I'm sorry, it doesn't boot
a MacROM, but you can boot a linux kernel from the command line.

You can install your own disk using debian-installer, with:

...
-M q800 \
-serial none -serial mon:stdio \
-m 1000M \
-net nic,model=dp83932,addr=09:00:07:12:34:57 \
-append "console=ttyS0 vga=off" \
-kernel vmlinux-4.16.0-1-m68k \
-initrd initrd.gz \
-drive file=debian-10.0-m68k-NETINST-1.iso,media=cdrom \
-drive file=m68k.qcow2,format=qcow2 \
-nographic

If you use a graphic adapter instead of "-nographic", you can use "-g" to set 
the
size of the display (I use "-g 1600x800x24").

You can get the ISO from:

https://cdimage.debian.org/cdimage/ports/10.0/m68k/iso-cd/debian-10.0-m68k-NETINST-1.iso

and extract the kernel and initrd.gz:

guestfish --add debian-10.0-m68k-NETINST-1.iso --ro \
  --mount /dev/sda:/ <<_EOF_
copy-out /install/cdrom/initrd.gz .
copy-out /install/kernels/vmlinux-4.16.0-1-m68k .
_EOF_

The mirror to use is: http://ftp.ports.debian.org/debian-ports/
when it fails, continue without boot loader.

In the same way, you can extract the kernel and the initramfs from the qcow2
image to use it with "-kernel" and "-initrd":

guestfish --add m68k.qcow2 --mount /dev/sda2:/ <<_EOF_
copy-out /boot/vmlinux-4.16.0-1-m68k .
copy-out /boot/initrd.img-4.16.0-1-m68k .
_EOF_

and boot with:

   ...
   -append "root=/dev/sda2 rw console=ttyS0 console=tty \
   -kernel vmlinux-4.16.0-1-m68k \
   -initrd initrd.img-4.16.0-1-m68k

NOTE: DHCP doesn't work but you can assign a static IP address.
  We need some patches for dp8393x that are not ready to be merged.
  See http://patchwork.ozlabs.org/patch/927020/
  http://patchwork.ozlabs.org/patch/927030/
  http://patchwork.ozlabs.org/patch/927026/

v15: limit the memory to 1GiB (max RAM address on Q800 is 0x4000)
 (but kernel crashes for values beyond 1015 MiB, I don't know why,
 perhaps because specs of real Q800 say maximum memory is 136 MiB...)
 split ESP patch to ease review, remove one useless change.

v14: rebase
 update VBL and SECOND IFR flags even if the timer is stopped
 updated swim.c header

v13: rebase
 Stop 1-second and VBL timers when the interrupt is disabled
 (fix some performance regressions on PowerMac G5, and 100% CPU
  usage on x86_64)

v12: Merge macfb and nubus macfb patches
 Add some commit messages
 replace DEFINE_MACHINE() by type_init()
 Add BootLinuxConsoleTest from Philippe
 rebase

v11: Add VMState to migrate ESP PDMA

 The new VMState structures cannot be tested because m68k is not
 migratable and then Q800 is not either.
 I've tested the ESP VMState is not broken by the change
 with 'migrate "exec:cat > mig"' with qemu-system-sparc and
 I have compared the result with/without the patch with
 scripts/analyze-migrate.py: files desc.json are identical.

v10: Add SWIM VMState and reset function
 Add MacVIA VMState
 rework Kconfig

v9: Fix comments format
rebase on top of NeXTcube

v8: rebase (new blk_new(), add "qemu-common.h")
update bootinfo information and license
add some braces
Rename Q800IRQState to GLUEState:
it's more like a Logic Unit than an IRQ controller,
and Apple calls it "GLUE" (Mark: I prefer to keep it
like this for the moment, in the future this part
need to be reworked, we have to review the IRQ levels
and to wire NUBUS IRQ. The implementation is really trivial
for the moment and we will move it to QOM in the future)

v7: rebase and port to Kconfig
move IRQ controller back to q800.c (we don't need an object for this)
update log message for ESP changes and add some g_assert()
re-order patches: put esp, escc and dp8393x first

v6: Rebase onto git master (this now includes the m68k EXCP_ILLEGAL fix required
  for this patchset to boot)
Add Hervé's R-B tags
Drop ASC (Apple Sound Chip) device since the Linux driver is broken and
  it is not required for a successful boot
Remove extra esp_raise_irq() from ESP pseudo-DMA patch (Hervé)
Remove "return" from unimplemented write functions and instead add a
  "read only" comment (Hervé)
Rename MAX_FD to SWIM_MAX_FD in SWIM floppy controller patch to prevent
  potential conflicts with other files (Hervé)

v5: Rebase onto git master
Add Philippe's R-B to patch 10
Include the command line to boot a Linux kernel under the q800 machine in 
the
commit message for patch 11 (Philippe)
Fix up comments in hw/misc/mac_via.c (Thomas)
Add asserts to VIA ADB support to prevent potential buffer overflows 
(Thomas)
Move macfb surface/resolution checks to realise and remove hw_error (Thomas)
Move macfb draw_line functions inline and remove macfb-template.h (Mark)
Use guest address rather than source pointer in draw_line 

[PATCH v15 09/11] hw/m68k: add a dummy SWIM floppy controller

2019-10-26 Thread Laurent Vivier
SWIM (Sander-Wozniak Integrated Machine) is the floppy controller of
the 680x0 Macintosh.

This patch introduces only the basic support: it allows to switch from
IWM (Integrated WOZ Machine) mode to the SWIM mode and makes the linux
driver happy.

It cannot read any floppy image.

Co-developed-by: Mark Cave-Ayland 
Signed-off-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
Reviewed-by: Hervé Poussineau 
---
 include/hw/block/swim.h |  76 +++
 hw/block/swim.c | 489 
 MAINTAINERS |   2 +
 hw/block/Kconfig|   3 +
 hw/block/Makefile.objs  |   1 +
 hw/m68k/Kconfig |   1 +
 6 files changed, 572 insertions(+)
 create mode 100644 include/hw/block/swim.h
 create mode 100644 hw/block/swim.c

diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
new file mode 100644
index 00..6add3499d0
--- /dev/null
+++ b/include/hw/block/swim.h
@@ -0,0 +1,76 @@
+/*
+ * QEMU Macintosh floppy disk controller emulator (SWIM)
+ *
+ * Copyright (c) 2014-2018 Laurent Vivier 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef SWIM_H
+#define SWIM_H
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+
+#define SWIM_MAX_FD2
+
+typedef struct SWIMDrive SWIMDrive;
+typedef struct SWIMBus SWIMBus;
+typedef struct SWIMCtrl SWIMCtrl;
+
+#define TYPE_SWIM_DRIVE "swim-drive"
+#define SWIM_DRIVE(obj) OBJECT_CHECK(SWIMDrive, (obj), TYPE_SWIM_DRIVE)
+
+struct SWIMDrive {
+DeviceState qdev;
+int32_t unit;
+BlockConf   conf;
+};
+
+#define TYPE_SWIM_BUS "swim-bus"
+#define SWIM_BUS(obj) OBJECT_CHECK(SWIMBus, (obj), TYPE_SWIM_BUS)
+
+struct SWIMBus {
+BusState bus;
+struct SWIMCtrl *ctrl;
+};
+
+typedef struct FDrive {
+SWIMCtrl *swimctrl;
+BlockBackend *blk;
+BlockConf *conf;
+} FDrive;
+
+struct SWIMCtrl {
+MemoryRegion iomem;
+FDrive drives[SWIM_MAX_FD];
+int mode;
+/* IWM mode */
+int iwm_switch;
+uint16_t regs[8];
+#define IWM_PH0   0
+#define IWM_PH1   1
+#define IWM_PH2   2
+#define IWM_PH3   3
+#define IWM_MTR   4
+#define IWM_DRIVE 5
+#define IWM_Q66
+#define IWM_Q77
+uint8_t iwm_data;
+uint8_t iwm_mode;
+/* SWIM mode */
+uint8_t swim_phase;
+uint8_t swim_mode;
+SWIMBus bus;
+};
+
+#define TYPE_SWIM "swim"
+#define SWIM(obj) OBJECT_CHECK(SWIM, (obj), TYPE_SWIM)
+
+typedef struct SWIM {
+SysBusDevice parent_obj;
+SWIMCtrl ctrl;
+} SWIM;
+#endif
diff --git a/hw/block/swim.c b/hw/block/swim.c
new file mode 100644
index 00..c6d117e89b
--- /dev/null
+++ b/hw/block/swim.c
@@ -0,0 +1,489 @@
+/*
+ * QEMU Macintosh floppy disk controller emulator (SWIM)
+ *
+ * Copyright (c) 2014-2018 Laurent Vivier 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Only the basic support: it allows to switch from IWM (Integrated WOZ
+ * Machine) mode to the SWIM mode and makes the linux driver happy.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "qapi/error.h"
+#include "sysemu/block-backend.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "hw/block/block.h"
+#include "hw/block/swim.h"
+#include "hw/qdev-properties.h"
+
+/* IWM registers */
+
+#define IWM_PH0L0
+#define IWM_PH0H1
+#define IWM_PH1L2
+#define IWM_PH1H3
+#define IWM_PH2L4
+#define IWM_PH2H5
+#define IWM_PH3L6
+#define IWM_PH3H7
+#define IWM_MTROFF  8
+#define IWM_MTRON   9
+#define IWM_INTDRIVE10
+#define IWM_EXTDRIVE11
+#define IWM_Q6L 12
+#define IWM_Q6H 13
+#define IWM_Q7L 14
+#define IWM_Q7H 15
+
+/* SWIM registers */
+
+#define SWIM_WRITE_DATA 0
+#define SWIM_WRITE_MARK 1
+#define SWIM_WRITE_CRC  2
+#define SWIM_WRITE_PARAMETER3
+#define SWIM_WRITE_PHASE4
+#define SWIM_WRITE_SETUP5
+#define SWIM_WRITE_MODE06
+#define SWIM_WRITE_MODE17
+
+#define SWIM_READ_DATA  8
+#define SWIM_READ_MARK  9
+#define SWIM_READ_ERROR 10
+#define SWIM_READ_PARAMETER 11
+#define SWIM_READ_PHASE 12
+#define SWIM_READ_SETUP 13
+#define SWIM_READ_STATUS14
+#define SWIM_READ_HANDSHAKE 15
+
+#define REG_SHIFT   9
+
+#define SWIM_MODE_IWM  0
+#define SWIM_MODE_SWIM 1
+
+/* bits in phase register */
+
+#define SWIM_SEEK_NEGATIVE   0x074
+#define SWIM_STEP0x071
+#define SWIM_MOTOR_ON0x072
+#define SWIM_MOTOR_OFF   0x076
+#define SWIM_INDEX   0x073
+#define SWIM_EJECT   0x077
+#define SWIM_SETMFM  0x171
+#define SWIM_SETGCR  0x175
+#define SWIM_RELAX   0x033

[PATCH v15 02/11] esp: move get_cmd() post-DMA code to get_cmd_cb()

2019-10-26 Thread Laurent Vivier
This will be needed to implement pseudo-DMA

Signed-off-by: Laurent Vivier 
---
 hw/scsi/esp.c | 46 +-
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 09b28cba17..0230ede21d 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -84,6 +84,34 @@ void esp_request_cancelled(SCSIRequest *req)
 }
 }
 
+static int get_cmd_cb(ESPState *s)
+{
+int target;
+
+target = s->wregs[ESP_WBUSID] & BUSID_DID;
+
+s->ti_size = 0;
+s->ti_rptr = 0;
+s->ti_wptr = 0;
+
+if (s->current_req) {
+/* Started a new command before the old one finished.  Cancel it.  */
+scsi_req_cancel(s->current_req);
+s->async_len = 0;
+}
+
+s->current_dev = scsi_device_find(>bus, 0, target, 0);
+if (!s->current_dev) {
+/* No such drive */
+s->rregs[ESP_RSTAT] = 0;
+s->rregs[ESP_RINTR] = INTR_DC;
+s->rregs[ESP_RSEQ] = SEQ_0;
+esp_raise_irq(s);
+return -1;
+}
+return 0;
+}
+
 static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
 {
 uint32_t dmalen;
@@ -108,23 +136,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t 
buflen)
 }
 trace_esp_get_cmd(dmalen, target);
 
-s->ti_size = 0;
-s->ti_rptr = 0;
-s->ti_wptr = 0;
-
-if (s->current_req) {
-/* Started a new command before the old one finished.  Cancel it.  */
-scsi_req_cancel(s->current_req);
-s->async_len = 0;
-}
-
-s->current_dev = scsi_device_find(>bus, 0, target, 0);
-if (!s->current_dev) {
-// No such drive
-s->rregs[ESP_RSTAT] = 0;
-s->rregs[ESP_RINTR] = INTR_DC;
-s->rregs[ESP_RSEQ] = SEQ_0;
-esp_raise_irq(s);
+if (get_cmd_cb(s) < 0) {
 return 0;
 }
 return dmalen;
-- 
2.21.0




[PATCH v15 06/11] hw/m68k: implement ADB bus support for via

2019-10-26 Thread Laurent Vivier
VIA needs to be able to poll the ADB interface and to read/write data
from/to the bus.

This patch adds functions allowing that.

Co-developed-by: Mark Cave-Ayland 
Signed-off-by: Mark Cave-Ayland 
Signed-off-by: Laurent Vivier 
Reviewed-by: Hervé Poussineau 
Reviewed-by: Thomas Huth 
---
 include/hw/misc/mac_via.h |   7 ++
 hw/misc/mac_via.c | 197 ++
 hw/misc/Kconfig   |   1 +
 3 files changed, 205 insertions(+)

diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
index efc8ef3ce3..3f86fcb7e1 100644
--- a/include/hw/misc/mac_via.h
+++ b/include/hw/misc/mac_via.h
@@ -103,6 +103,13 @@ typedef struct MacVIAState {
 
 /* ADB */
 ADBBusState adb_bus;
+QEMUTimer *adb_poll_timer;
+qemu_irq adb_data_ready;
+int adb_data_in_size;
+int adb_data_in_index;
+int adb_data_out_index;
+uint8_t adb_data_in[128];
+uint8_t adb_data_out[16];
 } MacVIAState;
 
 #endif
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index d2da8b8e60..f3f130ad96 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -264,10 +264,16 @@
  * Table 19-10 ADB transaction states
  */
 
+#define ADB_STATE_NEW   0
+#define ADB_STATE_EVEN  1
+#define ADB_STATE_ODD   2
+#define ADB_STATE_IDLE  3
+
 #define VIA1B_vADB_StateMask(VIA1B_vADBS1 | VIA1B_vADBS2)
 #define VIA1B_vADB_StateShift   4
 
 #define VIA_TIMER_FREQ (783360)
+#define VIA_ADB_POLL_FREQ 50 /* XXX: not real */
 
 /* VIA returns time offset from Jan 1, 1904, not 1970 */
 #define RTC_OFFSET 2082844800
@@ -472,6 +478,181 @@ static void via1_rtc_update(MacVIAState *m)
 }
 }
 
+static int adb_via_poll(MacVIAState *s, int state, uint8_t *data)
+{
+if (state != ADB_STATE_IDLE) {
+return 0;
+}
+
+if (s->adb_data_in_size < s->adb_data_in_index) {
+return 0;
+}
+
+if (s->adb_data_out_index != 0) {
+return 0;
+}
+
+s->adb_data_in_index = 0;
+s->adb_data_out_index = 0;
+s->adb_data_in_size = adb_poll(>adb_bus, s->adb_data_in, 0x);
+
+if (s->adb_data_in_size) {
+*data = s->adb_data_in[s->adb_data_in_index++];
+qemu_irq_raise(s->adb_data_ready);
+}
+
+return s->adb_data_in_size;
+}
+
+static int adb_via_send(MacVIAState *s, int state, uint8_t data)
+{
+switch (state) {
+case ADB_STATE_NEW:
+s->adb_data_out_index = 0;
+break;
+case ADB_STATE_EVEN:
+if ((s->adb_data_out_index & 1) == 0) {
+return 0;
+}
+break;
+case ADB_STATE_ODD:
+if (s->adb_data_out_index & 1) {
+return 0;
+}
+break;
+case ADB_STATE_IDLE:
+return 0;
+}
+
+assert(s->adb_data_out_index < sizeof(s->adb_data_out) - 1);
+
+s->adb_data_out[s->adb_data_out_index++] = data;
+qemu_irq_raise(s->adb_data_ready);
+return 1;
+}
+
+static int adb_via_receive(MacVIAState *s, int state, uint8_t *data)
+{
+switch (state) {
+case ADB_STATE_NEW:
+return 0;
+
+case ADB_STATE_EVEN:
+if (s->adb_data_in_size <= 0) {
+qemu_irq_raise(s->adb_data_ready);
+return 0;
+}
+
+if (s->adb_data_in_index >= s->adb_data_in_size) {
+*data = 0;
+qemu_irq_raise(s->adb_data_ready);
+return 1;
+}
+
+if ((s->adb_data_in_index & 1) == 0) {
+return 0;
+}
+
+break;
+
+case ADB_STATE_ODD:
+if (s->adb_data_in_size <= 0) {
+qemu_irq_raise(s->adb_data_ready);
+return 0;
+}
+
+if (s->adb_data_in_index >= s->adb_data_in_size) {
+*data = 0;
+qemu_irq_raise(s->adb_data_ready);
+return 1;
+}
+
+if (s->adb_data_in_index & 1) {
+return 0;
+}
+
+break;
+
+case ADB_STATE_IDLE:
+if (s->adb_data_out_index == 0) {
+return 0;
+}
+
+s->adb_data_in_size = adb_request(>adb_bus, s->adb_data_in,
+  s->adb_data_out,
+  s->adb_data_out_index);
+s->adb_data_out_index = 0;
+s->adb_data_in_index = 0;
+if (s->adb_data_in_size < 0) {
+*data = 0xff;
+qemu_irq_raise(s->adb_data_ready);
+return -1;
+}
+
+if (s->adb_data_in_size == 0) {
+return 0;
+}
+
+break;
+}
+
+assert(s->adb_data_in_index < sizeof(s->adb_data_in) - 1);
+
+*data = s->adb_data_in[s->adb_data_in_index++];
+qemu_irq_raise(s->adb_data_ready);
+if (*data == 0xff || *data == 0) {
+return 0;
+}
+return 1;
+}
+
+static void via1_adb_update(MacVIAState *m)
+{
+MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(>mos6522_via1);
+MOS6522State *s = MOS6522(v1s);
+int state;
+int ret;
+
+state = (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
+
+

[PATCH v15 01/11] esp: move handle_ti_cmd() cleanup code to esp_do_dma().

2019-10-26 Thread Laurent Vivier
To prepare following patches move do_cmd and DMA special case
from handle_ti() to esp_do_dma().

This part of the code must be only executed with real DMA, not with
pseudo-DMA. And PDMA is detected in esp_do_dma(), so move this part
of the code in esp_do_dma(). We keep the code in handle_ti_cmd()
in the case no DMA is done.

Signed-off-by: Laurent Vivier 
---
 hw/scsi/esp.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 841d79b60e..09b28cba17 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -249,10 +249,19 @@ static void esp_do_dma(ESPState *s)
 
 len = s->dma_left;
 if (s->do_cmd) {
+/*
+ * handle_ti_cmd() case: esp_do_dma() is called only from
+ * handle_ti_cmd() with do_cmd != NULL (see the assert())
+ */
 trace_esp_do_dma(s->cmdlen, len);
 assert (s->cmdlen <= sizeof(s->cmdbuf) &&
 len <= sizeof(s->cmdbuf) - s->cmdlen);
 s->dma_memory_read(s->dma_opaque, >cmdbuf[s->cmdlen], len);
+trace_esp_handle_ti_cmd(s->cmdlen);
+s->ti_size = 0;
+s->cmdlen = 0;
+s->do_cmd = 0;
+do_cmd(s, s->cmdbuf);
 return;
 }
 if (s->async_len == 0) {
@@ -373,8 +382,7 @@ static void handle_ti(ESPState *s)
 s->dma_left = minlen;
 s->rregs[ESP_RSTAT] &= ~STAT_TC;
 esp_do_dma(s);
-}
-if (s->do_cmd) {
+} else if (s->do_cmd) {
 trace_esp_handle_ti_cmd(s->cmdlen);
 s->ti_size = 0;
 s->cmdlen = 0;
-- 
2.21.0




Re: [PATCH v14 1/9] esp: add pseudo-DMA as used by Macintosh

2019-10-26 Thread Laurent Vivier
Le 22/10/2019 à 14:21, Philippe Mathieu-Daudé a écrit :
> Hi Laurent,
> 
> On 10/22/19 1:17 PM, Laurent Vivier wrote:
>> There is no DMA in Quadra 800, so the CPU reads/writes the data from the
>> PDMA register (offset 0x100, ESP_PDMA in hw/m68k/q800.c) and copies them
>> to/from the memory.
>>
>> There is a nice assembly loop in the kernel to do that, see
>> linux/drivers/scsi/mac_esp.c:MAC_ESP_PDMA_LOOP().
>>
>> The start of the transfer is triggered by the DREQ interrupt (see linux
>> mac_esp_send_pdma_cmd()), the CPU polls on the IRQ flag to start the
>> transfer after a SCSI command has been sent (in Quadra 800 it goes
>> through the VIA2, the via2-irq line and the vIFR register)
>>
>> The Macintosh hardware includes hardware handshaking to prevent the CPU
>> from reading invalid data or writing data faster than the peripheral
>> device can accept it.
>>
>> This is the "blind mode", and from the doc:
>> "Approximate maximum SCSI transfer rates within a blocks are 1.4 MB per
>> second for blind transfers in the Macintosh II"
>>
>> Some references can be found in:
>>    Apple Macintosh Family Hardware Reference, ISBN 0-201-19255-1
>>    Guide to the Macintosh Family Hardware, ISBN-0-201-52405-8
>>
>> Acked-by: Dr. David Alan Gilbert 
>> Co-developed-by: Mark Cave-Ayland 
>> Signed-off-by: Mark Cave-Ayland 
>> Signed-off-by: Laurent Vivier 
>> ---
>>   include/hw/scsi/esp.h |  15 ++
>>   hw/scsi/esp.c | 338 ++
>>   2 files changed, 324 insertions(+), 29 deletions(-)
>>
>> diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
>> index adab63d1c9..6ba47dac41 100644
>> --- a/include/hw/scsi/esp.h
>> +++ b/include/hw/scsi/esp.h
>> @@ -14,10 +14,18 @@ typedef void (*ESPDMAMemoryReadWriteFunc)(void
>> *opaque, uint8_t *buf, int len);
>>     typedef struct ESPState ESPState;
>>   +enum pdma_origin_id {
>> +    PDMA,
>> +    TI,
>> +    CMD,
>> +    ASYNC,
>> +};
>> +
>>   struct ESPState {
>>   uint8_t rregs[ESP_REGS];
>>   uint8_t wregs[ESP_REGS];
>>   qemu_irq irq;
>> +    qemu_irq irq_data;
>>   uint8_t chip_id;
>>   bool tchi_written;
>>   int32_t ti_size;
>> @@ -48,6 +56,12 @@ struct ESPState {
>>   ESPDMAMemoryReadWriteFunc dma_memory_write;
>>   void *dma_opaque;
>>   void (*dma_cb)(ESPState *s);
>> +    uint8_t pdma_buf[32];
>> +    int pdma_origin;
>> +    uint32_t pdma_len;
>> +    uint32_t pdma_start;
>> +    uint32_t pdma_cur;
>> +    void (*pdma_cb)(ESPState *s);
>>   };
>>     #define TYPE_ESP "esp"
>> @@ -59,6 +73,7 @@ typedef struct {
>>   /*< public >*/
>>     MemoryRegion iomem;
>> +    MemoryRegion pdma;
>>   uint32_t it_shift;
>>   ESPState esp;
>>   } SysBusESPState;
>> diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
>> index 841d79b60e..90b40c4cb5 100644
>> --- a/hw/scsi/esp.c
>> +++ b/hw/scsi/esp.c
>> @@ -38,6 +38,8 @@
>>    *
>> http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
>>
>>    * and
>>    *
>> http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
>>
>> + *
>> + * On Macintosh Quadra it is a NCR53C96.
>>    */
>>     static void esp_raise_irq(ESPState *s)
>> @@ -58,6 +60,16 @@ static void esp_lower_irq(ESPState *s)
>>   }
>>   }
>>   +static void esp_raise_drq(ESPState *s)
>> +{
>> +    qemu_irq_raise(s->irq_data);
>> +}
>> +
>> +static void esp_lower_drq(ESPState *s)
>> +{
>> +    qemu_irq_lower(s->irq_data);
>> +}
>> +
>>   void esp_dma_enable(ESPState *s, int irq, int level)
>>   {
>>   if (level) {
>> @@ -84,29 +96,35 @@ void esp_request_cancelled(SCSIRequest *req)
>>   }
>>   }
>>   -static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
>> +static void set_pdma(ESPState *s, enum pdma_origin_id origin,
>> + uint32_t index, uint32_t len)
>> +{
>> +    s->pdma_origin = origin;
>> +    s->pdma_start = index;
>> +    s->pdma_cur = index;
>> +    s->pdma_len = len;
> 
> Can you pass the pdma_cb to this function, and:
> 
>    s->pdma_cb = pdma_cb;
> 
>> +}
>> +
>> +static uint8_t *get_pdma_buf(ESPState *s)
>> +{
>> +    switch (s->pdma_origin) {
>> +    case PDMA:
>> +    return s->pdma_buf;
>> +    case TI:
>> +    return s->ti_buf;
>> +    case CMD:
>> +    return s->cmdbuf;
>> +    case ASYNC:
>> +    return s->async_buf;
>> +    }
>> +    return NULL;
>> +}
>> +
>> +static int get_cmd_cb(ESPState *s)
>>   {
>> -    uint32_t dmalen;
>>   int target;
>>     target = s->wregs[ESP_WBUSID] & BUSID_DID;
>> -    if (s->dma) {
>> -    dmalen = s->rregs[ESP_TCLO];
>> -    dmalen |= s->rregs[ESP_TCMID] << 8;
>> -    dmalen |= s->rregs[ESP_TCHI] << 16;
>> -    if (dmalen > buflen) {
>> -    return 0;
>> -    }
>> -    s->dma_memory_read(s->dma_opaque, buf, dmalen);
>> -    } else {
>> -    dmalen = s->ti_size;
>> -    if (dmalen > TI_BUFSZ) {
>> -    return 0;
>> -    }
>> -    memcpy(buf, s->ti_buf, dmalen);
>> 

Re: [PATCH 00/20] hw: Clean up hw/i386 headers (and few alpha/hppa)

2019-10-26 Thread Laurent Vivier
Le 26/10/2019 à 14:20, Philippe Mathieu-Daudé a écrit :
> Hi,
> 
> On 10/14/19 4:22 PM, Philippe Mathieu-Daudé wrote:
>> This is a follow-up of Markus's cleanup series:
>> Tame a few "touch this, recompile the world"
>> https://www.mail-archive.com/qemu-devel@nongnu.org/msg635748.html
>>
>> This part is mostly restricted to X86, but since some file from the
>> Alpha/PA-RISC machines include "hw/i386/pc.h" I had to fix them
>> too.
>>
>> Eventually I'll succeed at removing hw/i386/ dependency on non-X86
>> platforms (Quest I started 2 years ago...).
>>
>> Regards,
>>
>> Phil.
>>
>> Philippe Mathieu-Daudé (20):
>>    vl: Add missing "hw/boards.h" include
>>    hw/southbridge/ich9: Removed unused headers
>>    hw/input/pckbd: Remove unused "hw/i386/pc.h" header
>>    hw/i386/ioapic_internal: Remove unused "hw/i386/ioapic.h" header
>>    hw/timer: Remove unused "ui/console.h" header
>>    hw/usb/dev-storage: Remove unused "ui/console.h" header
>>    hw/i386/intel_iommu: Remove unused includes
>>    hw/xen/xen_pt_load_rom: Remove unused includes
>>    hw/alpha/alpha_sys: Remove unused "hw/ide.h" header
>>    hw/alpha/dp264: Include "net/net.h"
>>    hw/hppa/machine: Include "net/net.h"
>>    hw/acpi/cpu_hotplug: Include "hw/pci/pci.h"
>>    hw/timer/hpet: Include "exec/address-spaces.h"
>>    hw/pci-host/q35: Include "qemu/range.h"
>>    hw/i2c/smbus_ich9: Include "qemu/range.h"
>>    hw/pci-host/piix: Include "qemu/range.h"
>>    hw/acpi: Include "hw/mem/nvdimm.h"
>>    hw/i386: Include "hw/mem/nvdimm.h"
>>    hw/pci-host/q35: Remove unused includes
>>    hw/i386/pc: Clean up includes
> Laurent, since this series is fully reviewed, can it go via
> your qemu-trivial tree?

I'll try but I'm not sure to have the time to do that before the softfreeze.

Thanks,
Laurent



Re: [PATCH 00/20] hw: Clean up hw/i386 headers (and few alpha/hppa)

2019-10-26 Thread Philippe Mathieu-Daudé

Hi,

On 10/14/19 4:22 PM, Philippe Mathieu-Daudé wrote:

This is a follow-up of Markus's cleanup series:
Tame a few "touch this, recompile the world"
https://www.mail-archive.com/qemu-devel@nongnu.org/msg635748.html

This part is mostly restricted to X86, but since some file from the
Alpha/PA-RISC machines include "hw/i386/pc.h" I had to fix them
too.

Eventually I'll succeed at removing hw/i386/ dependency on non-X86
platforms (Quest I started 2 years ago...).

Regards,

Phil.

Philippe Mathieu-Daudé (20):
   vl: Add missing "hw/boards.h" include
   hw/southbridge/ich9: Removed unused headers
   hw/input/pckbd: Remove unused "hw/i386/pc.h" header
   hw/i386/ioapic_internal: Remove unused "hw/i386/ioapic.h" header
   hw/timer: Remove unused "ui/console.h" header
   hw/usb/dev-storage: Remove unused "ui/console.h" header
   hw/i386/intel_iommu: Remove unused includes
   hw/xen/xen_pt_load_rom: Remove unused includes
   hw/alpha/alpha_sys: Remove unused "hw/ide.h" header
   hw/alpha/dp264: Include "net/net.h"
   hw/hppa/machine: Include "net/net.h"
   hw/acpi/cpu_hotplug: Include "hw/pci/pci.h"
   hw/timer/hpet: Include "exec/address-spaces.h"
   hw/pci-host/q35: Include "qemu/range.h"
   hw/i2c/smbus_ich9: Include "qemu/range.h"
   hw/pci-host/piix: Include "qemu/range.h"
   hw/acpi: Include "hw/mem/nvdimm.h"
   hw/i386: Include "hw/mem/nvdimm.h"
   hw/pci-host/q35: Remove unused includes
   hw/i386/pc: Clean up includes

Laurent, since this series is fully reviewed, can it go via
your qemu-trivial tree?

Thanks,

Phil.



Re: [PATCH] qemu-iotests/iotests.py: improve assert_qmp message

2019-10-26 Thread Philippe Mathieu-Daudé

On 10/26/19 12:12 PM, Vladimir Sementsov-Ogievskiy wrote:

Make it obvious, from the two values which is found at path and which
is expected.


Maybe:

"From the two values compared, make it obvious which is found at path, 
and which is expected."


Reviewed-by: Philippe Mathieu-Daudé 



Signed-off-by: Vladimir Sementsov-Ogievskiy 
---

It's a pain, I can never remember it, and checking each time in source
code who is who is boring.

  tests/qemu-iotests/iotests.py | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 709def4d5d..e805b9ab14 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -729,8 +729,8 @@ class QMPTestCase(unittest.TestCase):
  self.fail('no match for "%s" in %s' % (str(result), str(value)))
  else:
  self.assertEqual(result, value,
- 'values not equal "%s" and "%s"'
- % (str(result), str(value)))
+ '"%s" is "%s", expected "%s"'
+ % (path, str(result), str(value)))
  
  def assert_no_active_block_jobs(self):

  result = self.vm.qmp('query-block-jobs')





[PATCH] qemu-iotests/iotests.py: improve assert_qmp message

2019-10-26 Thread Vladimir Sementsov-Ogievskiy
Make it obvious, from the two values which is found at path and which
is expected.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---

It's a pain, I can never remember it, and checking each time in source
code who is who is boring.

 tests/qemu-iotests/iotests.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 709def4d5d..e805b9ab14 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -729,8 +729,8 @@ class QMPTestCase(unittest.TestCase):
 self.fail('no match for "%s" in %s' % (str(result), str(value)))
 else:
 self.assertEqual(result, value,
- 'values not equal "%s" and "%s"'
- % (str(result), str(value)))
+ '"%s" is "%s", expected "%s"'
+ % (path, str(result), str(value)))
 
 def assert_no_active_block_jobs(self):
 result = self.vm.qmp('query-block-jobs')
-- 
2.21.0




[PATCH] qcow2-bitmap: Fix uint64_t left-shift overflow

2019-10-26 Thread Tuguoyi
In check_constraints_on_bitmap(), the sanity check on the
granularity will cause uint64_t integer left-shift overflow
when cluster_size is 2M and the granularity is bigger than
32K which is even smaller than the default value for a qcow2
disk with cluster_size set to 64k or bigger. This patch fix
the issue by right-shift @len instead.

Signed-off-by: Guoyi Tu 
---
 block/qcow2-bitmap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 98294a7..2a1d789 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -172,8 +172,8 @@ static int check_constraints_on_bitmap(BlockDriverState *bs,
 }

 if ((len > (uint64_t)BME_MAX_PHYS_SIZE << granularity_bits) ||
-(len > (uint64_t)BME_MAX_TABLE_SIZE * s->cluster_size <<
-   granularity_bits))
+((len >> granularity_bits) > (uint64_t)BME_MAX_TABLE_SIZE *
+s->cluster_size))
 {
 error_setg(errp, "Too much space will be occupied by the bitmap. "
"Use larger granularity");
--
2.7.4
-
本邮件及其附件含有新华三集团的保密信息,仅限于发送给上面地址中列出
的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、
或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本
邮件!
This e-mail and its attachments contain confidential information from New H3C, 
which is
intended only for the person or entity whose address is listed above. Any use 
of the
information contained herein in any way (including, but not limited to, total 
or partial
disclosure, reproduction, or dissemination) by persons other than the intended
recipient(s) is prohibited. If you receive this e-mail in error, please notify 
the sender
by phone or email immediately and delete it!


Re: [PULL 0/2] Block patches

2019-10-26 Thread Peter Maydell
On Fri, 25 Oct 2019 at 20:18, Stefan Hajnoczi  wrote:
>
> The following changes since commit 58560ad254fbda71d4daa6622d71683190070ee2:
>
>   Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.2-20191024' 
> into staging (2019-10-24 16:22:58 +0100)
>
> are available in the Git repository at:
>
>   https://github.com/stefanha/qemu.git tags/block-pull-request
>
> for you to fetch changes up to d154ef37ff885918fa3e512fd7a8e42870291667:
>
>   yield_until_fd_readable: make it work with any AioContect (2019-10-25 
> 14:38:29 +0200)
>
> 
> Pull request
>
> 
>
> Dietmar Maurer (1):
>   yield_until_fd_readable: make it work with any AioContect
>
> Julia Suvorova (1):
>   virtio-blk: Add blk_drain() to virtio_blk_device_unrealize()


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/4.2
for any user-visible changes.

-- PMM