diff --git a/SOURCES/kvm-Enable-SGX-RH-Only.patch b/SOURCES/kvm-Enable-SGX-RH-Only.patch
new file mode 100644
index 0000000..63f335b
--- /dev/null
+++ b/SOURCES/kvm-Enable-SGX-RH-Only.patch
@@ -0,0 +1,28 @@
+From f4f7c62a4658a570d3ad694b64463665fa4b80a7 Mon Sep 17 00:00:00 2001
+From: Paul Lai <plai@redhat.com>
+Date: Fri, 21 Jan 2022 13:14:42 -0500
+Subject: [PATCH 04/12] Enable SGX  -- RH Only
+
+RH-Author: Paul Lai <plai@redhat.com>
+RH-MergeRequest: 65: Enable SGX and add SGX Numa support
+RH-Commit: [4/5] 2cd4ee4a429f5e7b1c32e83a10bf488503603795
+RH-Bugzilla: 2033708
+RH-Acked-by: Paolo Bonzini <None>
+RH-Acked-by: Bandan Das <None>
+RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
+---
+ configs/devices/x86_64-softmmu/x86_64-rh-devices.mak | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
+index dc03fbb671..327b1bee62 100644
+--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
++++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
+@@ -101,3 +101,4 @@ CONFIG_TPM=y
+ CONFIG_TPM_CRB=y
+ CONFIG_TPM_TIS_ISA=y
+ CONFIG_TPM_EMULATOR=y
++CONFIG_SGX=y
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch b/SOURCES/kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch
new file mode 100644
index 0000000..6fc7f38
--- /dev/null
+++ b/SOURCES/kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch
@@ -0,0 +1,63 @@
+From 7b973b9cb7b890eaf9a31c99f5c272b513322ac1 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Thu, 3 Feb 2022 15:05:33 +0100
+Subject: [PATCH 1/8] block: Lock AioContext for drain_end in blockdev-reopen
+
+RH-Author: Kevin Wolf <kwolf@redhat.com>
+RH-MergeRequest: 73: block: Lock AioContext for drain_end in blockdev-reopen
+RH-Commit: [1/2] db25e999152b0e4f09decade1ac76b9f56cd9706 (kmwolf/centos-qemu-kvm)
+RH-Bugzilla: 2046659
+RH-Acked-by: Sergio Lopez <None>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+bdrv_subtree_drained_end() requires the caller to hold the AioContext
+lock for the drained node. Not doing this for nodes outside of the main
+AioContext leads to crashes when AIO_WAIT_WHILE() needs to wait and
+tries to temporarily release the lock.
+
+Fixes: 3908b7a8994fa5ef7a89aa58cd5a02fc58141592
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2046659
+Reported-by: Qing Wang <qinwang@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Message-Id: <20220203140534.36522-2-kwolf@redhat.com>
+Reviewed-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit aba8205be0707b9d108e32254e186ba88107a869)
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ blockdev.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/blockdev.c b/blockdev.c
+index b35072644e..565f6a81fd 100644
+--- a/blockdev.c
++++ b/blockdev.c
+@@ -3562,6 +3562,7 @@ void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
+ {
+     BlockReopenQueue *queue = NULL;
+     GSList *drained = NULL;
++    GSList *p;
+ 
+     /* Add each one of the BDS that we want to reopen to the queue */
+     for (; reopen_list != NULL; reopen_list = reopen_list->next) {
+@@ -3611,7 +3612,15 @@ void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
+ 
+ fail:
+     bdrv_reopen_queue_free(queue);
+-    g_slist_free_full(drained, (GDestroyNotify) bdrv_subtree_drained_end);
++    for (p = drained; p; p = p->next) {
++        BlockDriverState *bs = p->data;
++        AioContext *ctx = bdrv_get_aio_context(bs);
++
++        aio_context_acquire(ctx);
++        bdrv_subtree_drained_end(bs);
++        aio_context_release(ctx);
++    }
++    g_slist_free(drained);
+ }
+ 
+ void qmp_blockdev_del(const char *node_name, Error **errp)
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-backend-prevent-dangling-BDS-pointers-across-a.patch b/SOURCES/kvm-block-backend-prevent-dangling-BDS-pointers-across-a.patch
new file mode 100644
index 0000000..8dbf30f
--- /dev/null
+++ b/SOURCES/kvm-block-backend-prevent-dangling-BDS-pointers-across-a.patch
@@ -0,0 +1,129 @@
+From 87f3b10dc600ac12272ee6cdc67571910ea722f6 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Tue, 11 Jan 2022 15:36:12 +0000
+Subject: [PATCH 10/12] block-backend: prevent dangling BDS pointers across
+ aio_poll()
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 71: block-backend: prevent dangling BDS pointers across aio_poll()
+RH-Commit: [1/2] 1b4cab39bf8c933ab910293a29bfceaa9e821068 (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2040123
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+
+The BlockBackend root child can change when aio_poll() is invoked. This
+happens when a temporary filter node is removed upon blockjob
+completion, for example.
+
+Functions in block/block-backend.c must be aware of this when using a
+blk_bs() pointer across aio_poll() because the BlockDriverState refcnt
+may reach 0, resulting in a stale pointer.
+
+One example is scsi_device_purge_requests(), which calls blk_drain() to
+wait for in-flight requests to cancel. If the backup blockjob is active,
+then the BlockBackend root child is a temporary filter BDS owned by the
+blockjob. The blockjob can complete during bdrv_drained_begin() and the
+last reference to the BDS is released when the temporary filter node is
+removed. This results in a use-after-free when blk_drain() calls
+bdrv_drained_end(bs) on the dangling pointer.
+
+Explicitly hold a reference to bs across block APIs that invoke
+aio_poll().
+
+Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2021778
+Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2036178
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Message-Id: <20220111153613.25453-2-stefanha@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 1e3552dbd28359d35967b7c28dc86cde1bc29205)
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ block/block-backend.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/block/block-backend.c b/block/block-backend.c
+index 12ef80ea17..23e727199b 100644
+--- a/block/block-backend.c
++++ b/block/block-backend.c
+@@ -822,16 +822,22 @@ BlockBackend *blk_by_public(BlockBackendPublic *public)
+ void blk_remove_bs(BlockBackend *blk)
+ {
+     ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
+-    BlockDriverState *bs;
+     BdrvChild *root;
+ 
+     notifier_list_notify(&blk->remove_bs_notifiers, blk);
+     if (tgm->throttle_state) {
+-        bs = blk_bs(blk);
++        BlockDriverState *bs = blk_bs(blk);
++
++        /*
++         * Take a ref in case blk_bs() changes across bdrv_drained_begin(), for
++         * example, if a temporary filter node is removed by a blockjob.
++         */
++        bdrv_ref(bs);
+         bdrv_drained_begin(bs);
+         throttle_group_detach_aio_context(tgm);
+         throttle_group_attach_aio_context(tgm, qemu_get_aio_context());
+         bdrv_drained_end(bs);
++        bdrv_unref(bs);
+     }
+ 
+     blk_update_root_state(blk);
+@@ -1705,6 +1711,7 @@ void blk_drain(BlockBackend *blk)
+     BlockDriverState *bs = blk_bs(blk);
+ 
+     if (bs) {
++        bdrv_ref(bs);
+         bdrv_drained_begin(bs);
+     }
+ 
+@@ -1714,6 +1721,7 @@ void blk_drain(BlockBackend *blk)
+ 
+     if (bs) {
+         bdrv_drained_end(bs);
++        bdrv_unref(bs);
+     }
+ }
+ 
+@@ -2044,10 +2052,13 @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
+     int ret;
+ 
+     if (bs) {
++        bdrv_ref(bs);
++
+         if (update_root_node) {
+             ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
+                                                  errp);
+             if (ret < 0) {
++                bdrv_unref(bs);
+                 return ret;
+             }
+         }
+@@ -2057,6 +2068,8 @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
+             throttle_group_attach_aio_context(tgm, new_context);
+             bdrv_drained_end(bs);
+         }
++
++        bdrv_unref(bs);
+     }
+ 
+     blk->ctx = new_context;
+@@ -2326,11 +2339,13 @@ void blk_io_limits_disable(BlockBackend *blk)
+     ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
+     assert(tgm->throttle_state);
+     if (bs) {
++        bdrv_ref(bs);
+         bdrv_drained_begin(bs);
+     }
+     throttle_group_unregister_tgm(tgm);
+     if (bs) {
+         bdrv_drained_end(bs);
++        bdrv_unref(bs);
+     }
+ }
+ 
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-io-Update-BSC-only-if-want_zero-is-true.patch b/SOURCES/kvm-block-io-Update-BSC-only-if-want_zero-is-true.patch
new file mode 100644
index 0000000..5fff268
--- /dev/null
+++ b/SOURCES/kvm-block-io-Update-BSC-only-if-want_zero-is-true.patch
@@ -0,0 +1,56 @@
+From a6b472de71f6ebbe44025e1348c90e6f1f2b2326 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Tue, 18 Jan 2022 17:59:59 +0100
+Subject: [PATCH 06/12] block/io: Update BSC only if want_zero is true
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 69: block/io: Update BSC only if want_zero is true
+RH-Commit: [1/2] ad19ff86c3420cafe5a9e785ee210e482fbc8cd7 (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2041461
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+
+We update the block-status cache whenever we get new information from a
+bdrv_co_block_status() call to the block driver.  However, if we have
+passed want_zero=false to that call, it may flag areas containing zeroes
+as data, and so we would update the block-status cache with wrong
+information.
+
+Therefore, we should not update the cache with want_zero=false.
+
+Reported-by: Nir Soffer <nsoffer@redhat.com>
+Fixes: 0bc329fbb00 ("block: block-status cache for data regions")
+Reviewed-by: Nir Soffer <nsoffer@redhat.com>
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Message-Id: <20220118170000.49423-2-hreitz@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 113b727ce788335cf76f65355d670c9bc130fd75)
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ block/io.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/block/io.c b/block/io.c
+index bb0a254def..4e4cb556c5 100644
+--- a/block/io.c
++++ b/block/io.c
+@@ -2497,8 +2497,12 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
+              * non-protocol nodes, and then it is never used.  However, filling
+              * the cache requires an RCU update, so double check here to avoid
+              * such an update if possible.
++             *
++             * Check want_zero, because we only want to update the cache when we
++             * have accurate information about what is zero and what is data.
+              */
+-            if (ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) &&
++            if (want_zero &&
++                ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) &&
+                 QLIST_EMPTY(&bs->children))
+             {
+                 /*
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-nbd-Assert-there-are-no-timers-when-closed.patch b/SOURCES/kvm-block-nbd-Assert-there-are-no-timers-when-closed.patch
new file mode 100644
index 0000000..24c5b8a
--- /dev/null
+++ b/SOURCES/kvm-block-nbd-Assert-there-are-no-timers-when-closed.patch
@@ -0,0 +1,52 @@
+From 76b03619435d0b2f0125ee7aa5c94f2b889247de Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Fri, 4 Feb 2022 12:10:08 +0100
+Subject: [PATCH 4/8] block/nbd: Assert there are no timers when closed
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 74: block/nbd: Handle AioContext changes
+RH-Commit: [2/6] 56903457ca35d9c596aeb6827a48f80e8eabd66a (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2033626
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Our two timers must not remain armed beyond nbd_clear_bdrvstate(), or
+they will access freed data when they fire.
+
+This patch is separate from the patches that actually fix the issue
+(HEAD^^ and HEAD^) so that you can run the associated regression iotest
+(281) on a configuration that reproducibly exposes the bug.
+
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+(cherry picked from commit 8a39c381e5e407d2fe5500324323f90a8540fa90)
+
+Conflict:
+- block/nbd.c: open_timer was introduced after the 6.2 release (for
+  nbd's @open-timeout parameter), and has not been backported, so drop
+  the assertion that it is NULL
+
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ block/nbd.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/block/nbd.c b/block/nbd.c
+index b8e5a9b4cc..aab20125d8 100644
+--- a/block/nbd.c
++++ b/block/nbd.c
+@@ -108,6 +108,9 @@ static void nbd_clear_bdrvstate(BlockDriverState *bs)
+ 
+     yank_unregister_instance(BLOCKDEV_YANK_INSTANCE(bs->node_name));
+ 
++    /* Must not leave timers behind that would access freed data */
++    assert(!s->reconnect_delay_timer);
++
+     object_unref(OBJECT(s->tlscreds));
+     qapi_free_SocketAddress(s->saddr);
+     s->saddr = NULL;
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-nbd-Delete-reconnect-delay-timer-when-done.patch b/SOURCES/kvm-block-nbd-Delete-reconnect-delay-timer-when-done.patch
new file mode 100644
index 0000000..0cdf622
--- /dev/null
+++ b/SOURCES/kvm-block-nbd-Delete-reconnect-delay-timer-when-done.patch
@@ -0,0 +1,54 @@
+From eeb4683ad8c40a03a4e91463ec1d1b651974b744 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Fri, 4 Feb 2022 12:10:06 +0100
+Subject: [PATCH 3/8] block/nbd: Delete reconnect delay timer when done
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 74: block/nbd: Handle AioContext changes
+RH-Commit: [1/6] 34f92910b6ffd256d781109a2b39737fc6ab449c (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2033626
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+We start the reconnect delay timer to cancel the reconnection attempt
+after a while.  Once nbd_co_do_establish_connection() has returned, this
+attempt is over, and we no longer need the timer.
+
+Delete it before returning from nbd_reconnect_attempt(), so that it does
+not persist beyond the I/O request that was paused for reconnecting; we
+do not want it to fire in a drained section, because all sort of things
+can happen in such a section (e.g. the AioContext might be changed, and
+we do not want the timer to fire in the wrong context; or the BDS might
+even be deleted, and so the timer CB would access already-freed data).
+
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+(cherry picked from commit 3ce1fc16bad9c3f8b7b10b451a224d6d76e5c551)
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ block/nbd.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/block/nbd.c b/block/nbd.c
+index 5ef462db1b..b8e5a9b4cc 100644
+--- a/block/nbd.c
++++ b/block/nbd.c
+@@ -353,6 +353,13 @@ static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s)
+     }
+ 
+     nbd_co_do_establish_connection(s->bs, NULL);
++
++    /*
++     * The reconnect attempt is done (maybe successfully, maybe not), so
++     * we no longer need this timer.  Delete it so it will not outlive
++     * this I/O request (so draining removes all timers).
++     */
++    reconnect_delay_timer_del(s);
+ }
+ 
+ static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t handle)
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-nbd-Move-s-ioc-on-AioContext-change.patch b/SOURCES/kvm-block-nbd-Move-s-ioc-on-AioContext-change.patch
new file mode 100644
index 0000000..1cb29e9
--- /dev/null
+++ b/SOURCES/kvm-block-nbd-Move-s-ioc-on-AioContext-change.patch
@@ -0,0 +1,107 @@
+From 6d9d86cc4e6149d4c0793e8ceb65dab7535a4561 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Fri, 4 Feb 2022 12:10:11 +0100
+Subject: [PATCH 7/8] block/nbd: Move s->ioc on AioContext change
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 74: block/nbd: Handle AioContext changes
+RH-Commit: [5/6] b3c1eb21ac70d64fdac6094468a72cfbe50a30a9 (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2033626
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+s->ioc must always be attached to the NBD node's AioContext.  If that
+context changes, s->ioc must be attached to the new context.
+
+Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2033626
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+(cherry picked from commit e15f3a66c830e3fce99c9d56c493c2f7078a1225)
+
+Conflict:
+- block/nbd.c: open_timer was added after the 6.2 release, so we need
+  not (and cannot) assert it is NULL here.
+
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ block/nbd.c | 41 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+diff --git a/block/nbd.c b/block/nbd.c
+index aab20125d8..a3896c7f5f 100644
+--- a/block/nbd.c
++++ b/block/nbd.c
+@@ -2003,6 +2003,38 @@ static void nbd_cancel_in_flight(BlockDriverState *bs)
+     nbd_co_establish_connection_cancel(s->conn);
+ }
+ 
++static void nbd_attach_aio_context(BlockDriverState *bs,
++                                   AioContext *new_context)
++{
++    BDRVNBDState *s = bs->opaque;
++
++    /*
++     * The reconnect_delay_timer is scheduled in I/O paths when the
++     * connection is lost, to cancel the reconnection attempt after a
++     * given time.  Once this attempt is done (successfully or not),
++     * nbd_reconnect_attempt() ensures the timer is deleted before the
++     * respective I/O request is resumed.
++     * Since the AioContext can only be changed when a node is drained,
++     * the reconnect_delay_timer cannot be active here.
++     */
++    assert(!s->reconnect_delay_timer);
++
++    if (s->ioc) {
++        qio_channel_attach_aio_context(s->ioc, new_context);
++    }
++}
++
++static void nbd_detach_aio_context(BlockDriverState *bs)
++{
++    BDRVNBDState *s = bs->opaque;
++
++    assert(!s->reconnect_delay_timer);
++
++    if (s->ioc) {
++        qio_channel_detach_aio_context(s->ioc);
++    }
++}
++
+ static BlockDriver bdrv_nbd = {
+     .format_name                = "nbd",
+     .protocol_name              = "nbd",
+@@ -2026,6 +2058,9 @@ static BlockDriver bdrv_nbd = {
+     .bdrv_dirname               = nbd_dirname,
+     .strong_runtime_opts        = nbd_strong_runtime_opts,
+     .bdrv_cancel_in_flight      = nbd_cancel_in_flight,
++
++    .bdrv_attach_aio_context    = nbd_attach_aio_context,
++    .bdrv_detach_aio_context    = nbd_detach_aio_context,
+ };
+ 
+ static BlockDriver bdrv_nbd_tcp = {
+@@ -2051,6 +2086,9 @@ static BlockDriver bdrv_nbd_tcp = {
+     .bdrv_dirname               = nbd_dirname,
+     .strong_runtime_opts        = nbd_strong_runtime_opts,
+     .bdrv_cancel_in_flight      = nbd_cancel_in_flight,
++
++    .bdrv_attach_aio_context    = nbd_attach_aio_context,
++    .bdrv_detach_aio_context    = nbd_detach_aio_context,
+ };
+ 
+ static BlockDriver bdrv_nbd_unix = {
+@@ -2076,6 +2114,9 @@ static BlockDriver bdrv_nbd_unix = {
+     .bdrv_dirname               = nbd_dirname,
+     .strong_runtime_opts        = nbd_strong_runtime_opts,
+     .bdrv_cancel_in_flight      = nbd_cancel_in_flight,
++
++    .bdrv_attach_aio_context    = nbd_attach_aio_context,
++    .bdrv_detach_aio_context    = nbd_detach_aio_context,
+ };
+ 
+ static void bdrv_nbd_init(void)
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch b/SOURCES/kvm-block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch
new file mode 100644
index 0000000..bdebdc3
--- /dev/null
+++ b/SOURCES/kvm-block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch
@@ -0,0 +1,71 @@
+From 6989be9d0aa08470f8b287c243dc4bf027d5fbcf Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 8 Dec 2021 15:22:46 +0000
+Subject: [PATCH 1/2] block/nvme: fix infinite loop in nvme_free_req_queue_cb()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
+RH-MergeRequest: 58: block/nvme: fix infinite loop in nvme_free_req_queue_cb()
+RH-Commit: [1/1] 544b3f310d791a20c63b51947de0c6cbb60b0d5b (stefanha/centos-stream-qemu-kvm)
+RH-Bugzilla: 2024544
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+When the request free list is exhausted the coroutine waits on
+q->free_req_queue for the next free request. Whenever a request is
+completed a BH is scheduled to invoke nvme_free_req_queue_cb() and wake
+up waiting coroutines.
+
+1. nvme_get_free_req() waits for a free request:
+
+    while (q->free_req_head == -1) {
+        ...
+            trace_nvme_free_req_queue_wait(q->s, q->index);
+            qemu_co_queue_wait(&q->free_req_queue, &q->lock);
+        ...
+    }
+
+2. nvme_free_req_queue_cb() wakes up the coroutine:
+
+    while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
+       ^--- infinite loop when free_req_head == -1
+    }
+
+nvme_free_req_queue_cb() and the coroutine form an infinite loop when
+q->free_req_head == -1. Fix this by checking q->free_req_head in
+nvme_free_req_queue_cb(). If the free request list is exhausted, don't
+wake waiting coroutines. Eventually an in-flight request will complete
+and the BH will be scheduled again, guaranteeing forward progress.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+Message-id: 20211208152246.244585-1-stefanha@redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit cf4fbc3030c974fff726756a7ceef8386cdf500b)
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ block/nvme.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/block/nvme.c b/block/nvme.c
+index e4f336d79c..fa360b9b3c 100644
+--- a/block/nvme.c
++++ b/block/nvme.c
+@@ -206,8 +206,9 @@ static void nvme_free_req_queue_cb(void *opaque)
+     NVMeQueuePair *q = opaque;
+ 
+     qemu_mutex_lock(&q->lock);
+-    while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
+-        /* Retry all pending requests */
++    while (q->free_req_head != -1 &&
++           qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
++        /* Retry waiting requests */
+     }
+     qemu_mutex_unlock(&q->lock);
+ }
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch b/SOURCES/kvm-block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch
new file mode 100644
index 0000000..39aa96c
--- /dev/null
+++ b/SOURCES/kvm-block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch
@@ -0,0 +1,59 @@
+From d374d5aa4485a0c62d6b48eec64491cae2fd0873 Mon Sep 17 00:00:00 2001
+From: Peter Lieven <pl@kamp.de>
+Date: Thu, 13 Jan 2022 15:44:25 +0100
+Subject: [PATCH 4/5] block/rbd: fix handling of holes in .bdrv_co_block_status
+
+RH-Author: Stefano Garzarella <sgarzare@redhat.com>
+RH-MergeRequest: 68: block/rbd: fix handling of holes in .bdrv_co_block_status
+RH-Commit: [1/2] 8ef178b01885e3c292f7844ccff865b1a8d4faf0 (sgarzarella/qemu-kvm-c-9-s)
+RH-Bugzilla: 2034791
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+the assumption that we can't hit a hole if we do not diff against a snapshot was wrong.
+
+We can see a hole in an image if we diff against base if there exists an older snapshot
+of the image and we have discarded blocks in the image where the snapshot has data.
+
+Fix this by simply handling a hole like an unallocated area. There are no callbacks
+for unallocated areas so just bail out if we hit a hole.
+
+Fixes: 0347a8fd4c3faaedf119be04c197804be40a384b
+Suggested-by: Ilya Dryomov <idryomov@gmail.com>
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Peter Lieven <pl@kamp.de>
+Message-Id: <20220113144426.4036493-2-pl@kamp.de>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 9e302f64bb407a9bb097b626da97228c2654cfee)
+Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
+---
+ block/rbd.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/block/rbd.c b/block/rbd.c
+index def96292e0..20bb896c4a 100644
+--- a/block/rbd.c
++++ b/block/rbd.c
+@@ -1279,11 +1279,11 @@ static int qemu_rbd_diff_iterate_cb(uint64_t offs, size_t len,
+     RBDDiffIterateReq *req = opaque;
+ 
+     assert(req->offs + req->bytes <= offs);
+-    /*
+-     * we do not diff against a snapshot so we should never receive a callback
+-     * for a hole.
+-     */
+-    assert(exists);
++
++    /* treat a hole like an unallocated area and bail out */
++    if (!exists) {
++        return 0;
++    }
+ 
+     if (!req->exists && offs > req->offs) {
+         /*
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-block-rbd-workaround-for-ceph-issue-53784.patch b/SOURCES/kvm-block-rbd-workaround-for-ceph-issue-53784.patch
new file mode 100644
index 0000000..dd3876e
--- /dev/null
+++ b/SOURCES/kvm-block-rbd-workaround-for-ceph-issue-53784.patch
@@ -0,0 +1,103 @@
+From f035b5250529eed8d12e0b93b1b6d6f2c50003f6 Mon Sep 17 00:00:00 2001
+From: Peter Lieven <pl@kamp.de>
+Date: Thu, 13 Jan 2022 15:44:26 +0100
+Subject: [PATCH 5/5] block/rbd: workaround for ceph issue #53784
+
+RH-Author: Stefano Garzarella <sgarzare@redhat.com>
+RH-MergeRequest: 68: block/rbd: fix handling of holes in .bdrv_co_block_status
+RH-Commit: [2/2] 5feaa2e20a77886cc1a84cdf212ade3dcda28289 (sgarzarella/qemu-kvm-c-9-s)
+RH-Bugzilla: 2034791
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+librbd had a bug until early 2022 that affected all versions of ceph that
+supported fast-diff. This bug results in reporting of incorrect offsets
+if the offset parameter to rbd_diff_iterate2 is not object aligned.
+
+This patch works around this bug for pre Quincy versions of librbd.
+
+Fixes: 0347a8fd4c3faaedf119be04c197804be40a384b
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Peter Lieven <pl@kamp.de>
+Message-Id: <20220113144426.4036493-3-pl@kamp.de>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
+Tested-by: Stefano Garzarella <sgarzare@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit fc176116cdea816ceb8dd969080b2b95f58edbc0)
+Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
+---
+ block/rbd.c | 42 ++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 40 insertions(+), 2 deletions(-)
+
+diff --git a/block/rbd.c b/block/rbd.c
+index 20bb896c4a..8f183eba2a 100644
+--- a/block/rbd.c
++++ b/block/rbd.c
+@@ -1320,6 +1320,7 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
+     int status, r;
+     RBDDiffIterateReq req = { .offs = offset };
+     uint64_t features, flags;
++    uint64_t head = 0;
+ 
+     assert(offset + bytes <= s->image_size);
+ 
+@@ -1347,7 +1348,43 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
+         return status;
+     }
+ 
+-    r = rbd_diff_iterate2(s->image, NULL, offset, bytes, true, true,
++#if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 17, 0)
++    /*
++     * librbd had a bug until early 2022 that affected all versions of ceph that
++     * supported fast-diff. This bug results in reporting of incorrect offsets
++     * if the offset parameter to rbd_diff_iterate2 is not object aligned.
++     * Work around this bug by rounding down the offset to object boundaries.
++     * This is OK because we call rbd_diff_iterate2 with whole_object = true.
++     * However, this workaround only works for non cloned images with default
++     * striping.
++     *
++     * See: https://tracker.ceph.com/issues/53784
++     */
++
++    /* check if RBD image has non-default striping enabled */
++    if (features & RBD_FEATURE_STRIPINGV2) {
++        return status;
++    }
++
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
++    /*
++     * check if RBD image is a clone (= has a parent).
++     *
++     * rbd_get_parent_info is deprecated from Nautilus onwards, but the
++     * replacement rbd_get_parent is not present in Luminous and Mimic.
++     */
++    if (rbd_get_parent_info(s->image, NULL, 0, NULL, 0, NULL, 0) != -ENOENT) {
++        return status;
++    }
++#pragma GCC diagnostic pop
++
++    head = req.offs & (s->object_size - 1);
++    req.offs -= head;
++    bytes += head;
++#endif
++
++    r = rbd_diff_iterate2(s->image, NULL, req.offs, bytes, true, true,
+                           qemu_rbd_diff_iterate_cb, &req);
+     if (r < 0 && r != QEMU_RBD_EXIT_DIFF_ITERATE2) {
+         return status;
+@@ -1366,7 +1403,8 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
+         status = BDRV_BLOCK_ZERO | BDRV_BLOCK_OFFSET_VALID;
+     }
+ 
+-    *pnum = req.bytes;
++    assert(req.bytes > head);
++    *pnum = req.bytes - head;
+     return status;
+ }
+ 
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-doc-Add-the-SGX-numa-description.patch b/SOURCES/kvm-doc-Add-the-SGX-numa-description.patch
new file mode 100644
index 0000000..8eac5fa
--- /dev/null
+++ b/SOURCES/kvm-doc-Add-the-SGX-numa-description.patch
@@ -0,0 +1,77 @@
+From eb88a12ab1ecfe77bcc0d0067c96fce27a3bde01 Mon Sep 17 00:00:00 2001
+From: Yang Zhong <yang.zhong@intel.com>
+Date: Mon, 1 Nov 2021 12:20:08 -0400
+Subject: [PATCH 03/12] doc: Add the SGX numa description
+
+RH-Author: Paul Lai <plai@redhat.com>
+RH-MergeRequest: 65: Enable SGX and add SGX Numa support
+RH-Commit: [3/5] c27b3f6976cbe92cc3c0e1dab0191cdd25de596a
+RH-Bugzilla: 2033708
+RH-Acked-by: Paolo Bonzini <None>
+RH-Acked-by: Bandan Das <None>
+RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
+
+Add the SGX numa reference command and how to check if
+SGX numa is support or not with multiple EPC sections.
+
+Signed-off-by: Yang Zhong <yang.zhong@intel.com>
+Message-Id: <20211101162009.62161-5-yang.zhong@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit d1889b36098c79e2e6ac90faf3d0dc5ec0057677)
+Signed-off-by: Paul Lai <plai@redhat.com>
+---
+ docs/system/i386/sgx.rst | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+diff --git a/docs/system/i386/sgx.rst b/docs/system/i386/sgx.rst
+index f8fade5ac2..0f0a73f758 100644
+--- a/docs/system/i386/sgx.rst
++++ b/docs/system/i386/sgx.rst
+@@ -141,8 +141,7 @@ To launch a SGX guest:
+   |qemu_system_x86| \\
+    -cpu host,+sgx-provisionkey \\
+    -object memory-backend-epc,id=mem1,size=64M,prealloc=on \\
+-   -object memory-backend-epc,id=mem2,size=28M \\
+-   -M sgx-epc.0.memdev=mem1,sgx-epc.1.memdev=mem2
++   -M sgx-epc.0.memdev=mem1,sgx-epc.0.node=0
+ 
+ Utilizing SGX in the guest requires a kernel/OS with SGX support.
+ The support can be determined in guest by::
+@@ -152,8 +151,32 @@ The support can be determined in guest by::
+ and SGX epc info by::
+ 
+   $ dmesg | grep sgx
+-  [    1.242142] sgx: EPC section 0x180000000-0x181bfffff
+-  [    1.242319] sgx: EPC section 0x181c00000-0x1837fffff
++  [    0.182807] sgx: EPC section 0x140000000-0x143ffffff
++  [    0.183695] sgx: [Firmware Bug]: Unable to map EPC section to online node. Fallback to the NUMA node 0.
++
++To launch a SGX numa guest:
++
++.. parsed-literal::
++
++  |qemu_system_x86| \\
++   -cpu host,+sgx-provisionkey \\
++   -object memory-backend-ram,size=2G,host-nodes=0,policy=bind,id=node0 \\
++   -object memory-backend-epc,id=mem0,size=64M,prealloc=on,host-nodes=0,policy=bind \\
++   -numa node,nodeid=0,cpus=0-1,memdev=node0 \\
++   -object memory-backend-ram,size=2G,host-nodes=1,policy=bind,id=node1 \\
++   -object memory-backend-epc,id=mem1,size=28M,prealloc=on,host-nodes=1,policy=bind \\
++   -numa node,nodeid=1,cpus=2-3,memdev=node1 \\
++   -M sgx-epc.0.memdev=mem0,sgx-epc.0.node=0,sgx-epc.1.memdev=mem1,sgx-epc.1.node=1
++
++and SGX epc numa info by::
++
++  $ dmesg | grep sgx
++  [    0.369937] sgx: EPC section 0x180000000-0x183ffffff
++  [    0.370259] sgx: EPC section 0x184000000-0x185bfffff
++
++  $ dmesg | grep SRAT
++  [    0.009981] ACPI: SRAT: Node 0 PXM 0 [mem 0x180000000-0x183ffffff]
++  [    0.009982] ACPI: SRAT: Node 1 PXM 1 [mem 0x184000000-0x185bfffff]
+ 
+ References
+ ----------
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-hw-arm-smmuv3-Fix-device-reset.patch b/SOURCES/kvm-hw-arm-smmuv3-Fix-device-reset.patch
new file mode 100644
index 0000000..3b8f307
--- /dev/null
+++ b/SOURCES/kvm-hw-arm-smmuv3-Fix-device-reset.patch
@@ -0,0 +1,61 @@
+From c08c3fbb2bb8494738fd34ec8fc9dc434ce82f4b Mon Sep 17 00:00:00 2001
+From: Eric Auger <eric.auger@redhat.com>
+Date: Wed, 2 Feb 2022 12:16:02 +0100
+Subject: [PATCH 12/12] hw/arm/smmuv3: Fix device reset
+
+RH-Author: Eric Auger <eric.auger@redhat.com>
+RH-MergeRequest: 72: hw/arm/smmuv3: Fix device reset
+RH-Commit: [1/1] 2cfee2f7a03692681224fed96bb4f28406bf460a (eauger1/centos-qemu-kvm)
+RH-Bugzilla: 2042481
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Peter Xu <peterx@redhat.com>
+RH-Acked-by: Andrew Jones <drjones@redhat.com>
+
+branch: c9s
+Brew: 42958737
+Upstream: yes
+
+We currently miss a bunch of register resets in the device reset
+function. This sometimes prevents the guest from rebooting after
+a system_reset (with virtio-blk-pci). For instance, we may get
+the following errors:
+
+invalid STE
+smmuv3-iommu-memory-region-0-0 translation failed for iova=0x13a9d2000(SMMU_EVT_C_BAD_STE)
+Invalid read at addr 0x13A9D2000, size 2, region '(null)', reason: rejected
+invalid STE
+smmuv3-iommu-memory-region-0-0 translation failed for iova=0x13a9d2000(SMMU_EVT_C_BAD_STE)
+Invalid write at addr 0x13A9D2000, size 2, region '(null)', reason: rejected
+invalid STE
+
+Signed-off-by: Eric Auger <eric.auger@redhat.com>
+Message-id: 20220202111602.627429-1-eric.auger@redhat.com
+Fixes: 10a83cb988 ("hw/arm/smmuv3: Skeleton")
+Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
+Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
+(cherry picked from commit 43530095e18fd16dcd51a4b385ad2a22c36f5698)
+Signed-off-by: Eric Auger <eric.auger@redhat.com>
+---
+ hw/arm/smmuv3.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
+index 01b60bee49..1b5640bb98 100644
+--- a/hw/arm/smmuv3.c
++++ b/hw/arm/smmuv3.c
+@@ -276,6 +276,12 @@ static void smmuv3_init_regs(SMMUv3State *s)
+     s->features = 0;
+     s->sid_split = 0;
+     s->aidr = 0x1;
++    s->cr[0] = 0;
++    s->cr0ack = 0;
++    s->irq_ctrl = 0;
++    s->gerror = 0;
++    s->gerrorn = 0;
++    s->statusr = 0;
+ }
+ 
+ static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-iotests-281-Let-NBD-connection-yield-in-iothread.patch b/SOURCES/kvm-iotests-281-Let-NBD-connection-yield-in-iothread.patch
new file mode 100644
index 0000000..20bc3a5
--- /dev/null
+++ b/SOURCES/kvm-iotests-281-Let-NBD-connection-yield-in-iothread.patch
@@ -0,0 +1,108 @@
+From 06583ce33fab2976157461ac4503d6f8eeb59e75 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Fri, 4 Feb 2022 12:10:12 +0100
+Subject: [PATCH 8/8] iotests/281: Let NBD connection yield in iothread
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 74: block/nbd: Handle AioContext changes
+RH-Commit: [6/6] 632b9ef5177a80d1c0c00121e1acc37272076d3e (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2033626
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Put an NBD block device into an I/O thread, and then read data from it,
+hoping that the NBD connection will yield during that read.  When it
+does, the coroutine must be reentered in the block device's I/O thread,
+which will only happen if the NBD block driver attaches the connection's
+QIOChannel to the new AioContext.  It did not do that after 4ddb5d2fde
+("block/nbd: drop connection_co") and prior to "block/nbd: Move s->ioc
+on AioContext change", which would cause an assertion failure.
+
+To improve our chances of yielding, the NBD server is throttled to
+reading 64 kB/s, and the NBD client reads 128 kB, so it should yield at
+some point.
+
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+(cherry picked from commit 8cfbe929e8c26050f0a4580a1606a370a947d4ce)
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ tests/qemu-iotests/281     | 28 +++++++++++++++++++++++++---
+ tests/qemu-iotests/281.out |  4 ++--
+ 2 files changed, 27 insertions(+), 5 deletions(-)
+
+diff --git a/tests/qemu-iotests/281 b/tests/qemu-iotests/281
+index 13c588be75..b2ead7f388 100755
+--- a/tests/qemu-iotests/281
++++ b/tests/qemu-iotests/281
+@@ -253,8 +253,9 @@ class TestYieldingAndTimers(iotests.QMPTestCase):
+         self.create_nbd_export()
+ 
+         # Simple VM with an NBD block device connected to the NBD export
+-        # provided by the QSD
++        # provided by the QSD, and an (initially unused) iothread
+         self.vm = iotests.VM()
++        self.vm.add_object('iothread,id=iothr')
+         self.vm.add_blockdev('nbd,node-name=nbd,server.type=unix,' +
+                              f'server.path={self.sock},export=exp,' +
+                              'reconnect-delay=1')
+@@ -293,19 +294,40 @@ class TestYieldingAndTimers(iotests.QMPTestCase):
+         # thus not see the error, and so the test will pass.)
+         time.sleep(2)
+ 
++    def test_yield_in_iothread(self):
++        # Move the NBD node to the I/O thread; the NBD block driver should
++        # attach the connection's QIOChannel to that thread's AioContext, too
++        result = self.vm.qmp('x-blockdev-set-iothread',
++                             node_name='nbd', iothread='iothr')
++        self.assert_qmp(result, 'return', {})
++
++        # Do some I/O that will be throttled by the QSD, so that the network
++        # connection hopefully will yield here.  When it is resumed, it must
++        # then be resumed in the I/O thread's AioContext.
++        result = self.vm.qmp('human-monitor-command',
++                             command_line='qemu-io nbd "read 0 128K"')
++        self.assert_qmp(result, 'return', '')
++
+     def create_nbd_export(self):
+         assert self.qsd is None
+ 
+-        # Simple NBD export of a null-co BDS
++        # Export a throttled null-co BDS: Reads are throttled (max 64 kB/s),
++        # writes are not.
+         self.qsd = QemuStorageDaemon(
++            '--object',
++            'throttle-group,id=thrgr,x-bps-read=65536,x-bps-read-max=65536',
++
+             '--blockdev',
+             'null-co,node-name=null,read-zeroes=true',
+ 
++            '--blockdev',
++            'throttle,node-name=thr,file=null,throttle-group=thrgr',
++
+             '--nbd-server',
+             f'addr.type=unix,addr.path={self.sock}',
+ 
+             '--export',
+-            'nbd,id=exp,node-name=null,name=exp,writable=true'
++            'nbd,id=exp,node-name=thr,name=exp,writable=true'
+         )
+ 
+     def stop_nbd_export(self):
+diff --git a/tests/qemu-iotests/281.out b/tests/qemu-iotests/281.out
+index 914e3737bd..3f8a935a08 100644
+--- a/tests/qemu-iotests/281.out
++++ b/tests/qemu-iotests/281.out
+@@ -1,5 +1,5 @@
+-.....
++......
+ ----------------------------------------------------------------------
+-Ran 5 tests
++Ran 6 tests
+ 
+ OK
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-iotests-281-Test-lingering-timers.patch b/SOURCES/kvm-iotests-281-Test-lingering-timers.patch
new file mode 100644
index 0000000..7175a31
--- /dev/null
+++ b/SOURCES/kvm-iotests-281-Test-lingering-timers.patch
@@ -0,0 +1,174 @@
+From 3d2d7a46713d362d2ff5137841e689593da976a3 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Fri, 4 Feb 2022 12:10:10 +0100
+Subject: [PATCH 6/8] iotests/281: Test lingering timers
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 74: block/nbd: Handle AioContext changes
+RH-Commit: [4/6] d228ba3fcdfaab2d54dd5b023688a1c055cce2c2 (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2033626
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+Prior to "block/nbd: Delete reconnect delay timer when done" and
+"block/nbd: Delete open timer when done", both of those timers would
+remain scheduled even after successfully (re-)connecting to the server,
+and they would not even be deleted when the BDS is deleted.
+
+This test constructs exactly this situation:
+(1) Configure an @open-timeout, so the open timer is armed, and
+(2) Configure a @reconnect-delay and trigger a reconnect situation
+    (which succeeds immediately), so the reconnect delay timer is armed.
+Then we immediately delete the BDS, and sleep for longer than the
+@open-timeout and @reconnect-delay.  Prior to said patches, this caused
+one (or both) of the timer CBs to access already-freed data.
+
+Accessing freed data may or may not crash, so this test can produce
+false successes, but I do not know how to show the problem in a better
+or more reliable way.  If you run this test on "block/nbd: Assert there
+are no timers when closed" and without the fix patches mentioned above,
+you should reliably see an assertion failure.
+(But all other tests that use the reconnect delay timer (264 and 277)
+will fail in that configuration, too; as will nbd-reconnect-on-open,
+which uses the open timer.)
+
+Remove this test from the quick group because of the two second sleep
+this patch introduces.
+
+(I decided to put this test case into 281, because the main bug this
+series addresses is in the interaction of the NBD block driver and I/O
+threads, which is precisely the scope of 281.  The test case for that
+other bug will also be put into the test class added here.
+
+Also, excuse the test class's name, I couldn't come up with anything
+better.  The "yield" part will make sense two patches from now.)
+
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+(cherry picked from commit eaf1e85d4ddefdbd197f393fa9c5acc7ba8133b0)
+
+Conflict:
+- @open-timeout was introduced after the 6.2 release, and has not been
+  backported.  Consequently, there is no open_timer, and we can (and
+  must) drop the respective parts of the test here.
+
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ tests/qemu-iotests/281     | 73 ++++++++++++++++++++++++++++++++++++--
+ tests/qemu-iotests/281.out |  4 +--
+ 2 files changed, 73 insertions(+), 4 deletions(-)
+
+diff --git a/tests/qemu-iotests/281 b/tests/qemu-iotests/281
+index 956698083f..13c588be75 100755
+--- a/tests/qemu-iotests/281
++++ b/tests/qemu-iotests/281
+@@ -1,5 +1,5 @@
+ #!/usr/bin/env python3
+-# group: rw quick
++# group: rw
+ #
+ # Test cases for blockdev + IOThread interactions
+ #
+@@ -20,8 +20,9 @@
+ #
+ 
+ import os
++import time
+ import iotests
+-from iotests import qemu_img
++from iotests import qemu_img, QemuStorageDaemon
+ 
+ image_len = 64 * 1024 * 1024
+ 
+@@ -243,6 +244,74 @@ class TestBlockdevBackupAbort(iotests.QMPTestCase):
+         # Hangs on failure, we expect this error.
+         self.assert_qmp(result, 'error/class', 'GenericError')
+ 
++# Test for RHBZ#2033626
++class TestYieldingAndTimers(iotests.QMPTestCase):
++    sock = os.path.join(iotests.sock_dir, 'nbd.sock')
++    qsd = None
++
++    def setUp(self):
++        self.create_nbd_export()
++
++        # Simple VM with an NBD block device connected to the NBD export
++        # provided by the QSD
++        self.vm = iotests.VM()
++        self.vm.add_blockdev('nbd,node-name=nbd,server.type=unix,' +
++                             f'server.path={self.sock},export=exp,' +
++                             'reconnect-delay=1')
++
++        self.vm.launch()
++
++    def tearDown(self):
++        self.stop_nbd_export()
++        self.vm.shutdown()
++
++    def test_timers_with_blockdev_del(self):
++        # Stop and restart the NBD server, and do some I/O on the client to
++        # trigger a reconnect and start the reconnect delay timer
++        self.stop_nbd_export()
++        self.create_nbd_export()
++
++        result = self.vm.qmp('human-monitor-command',
++                             command_line='qemu-io nbd "write 0 512"')
++        self.assert_qmp(result, 'return', '')
++
++        # Reconnect is done, so the reconnect delay timer should be gone.
++        # (But there used to be a bug where it remained active, for which this
++        # is a regression test.)
++
++        # Delete the BDS to see whether the timer is gone.  If it is not,
++        # it will remain active, fire later, and then access freed data.
++        # (Or, with "block/nbd: Assert there are no timers when closed"
++        # applied, the assertion added in that patch will fail.)
++        result = self.vm.qmp('blockdev-del', node_name='nbd')
++        self.assert_qmp(result, 'return', {})
++
++        # Give the timer some time to fire (it has a timeout of 1 s).
++        # (Sleeping in an iotest may ring some alarm bells, but note that if
++        # the timing is off here, the test will just always pass.  If we kill
++        # the VM too early, then we just kill the timer before it can fire,
++        # thus not see the error, and so the test will pass.)
++        time.sleep(2)
++
++    def create_nbd_export(self):
++        assert self.qsd is None
++
++        # Simple NBD export of a null-co BDS
++        self.qsd = QemuStorageDaemon(
++            '--blockdev',
++            'null-co,node-name=null,read-zeroes=true',
++
++            '--nbd-server',
++            f'addr.type=unix,addr.path={self.sock}',
++
++            '--export',
++            'nbd,id=exp,node-name=null,name=exp,writable=true'
++        )
++
++    def stop_nbd_export(self):
++        self.qsd.stop()
++        self.qsd = None
++
+ if __name__ == '__main__':
+     iotests.main(supported_fmts=['qcow2'],
+                  supported_protocols=['file'])
+diff --git a/tests/qemu-iotests/281.out b/tests/qemu-iotests/281.out
+index 89968f35d7..914e3737bd 100644
+--- a/tests/qemu-iotests/281.out
++++ b/tests/qemu-iotests/281.out
+@@ -1,5 +1,5 @@
+-....
++.....
+ ----------------------------------------------------------------------
+-Ran 4 tests
++Ran 5 tests
+ 
+ OK
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch b/SOURCES/kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch
new file mode 100644
index 0000000..8616f1c
--- /dev/null
+++ b/SOURCES/kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch
@@ -0,0 +1,106 @@
+From 37593348e7d95580fb2b0009dcb026c07367f1f8 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Thu, 3 Feb 2022 15:05:34 +0100
+Subject: [PATCH 2/8] iotests: Test blockdev-reopen with iothreads and
+ throttling
+
+RH-Author: Kevin Wolf <kwolf@redhat.com>
+RH-MergeRequest: 73: block: Lock AioContext for drain_end in blockdev-reopen
+RH-Commit: [2/2] d19d5fa9efa4813ece75708436891041754ab910 (kmwolf/centos-qemu-kvm)
+RH-Bugzilla: 2046659
+RH-Acked-by: Sergio Lopez <None>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+The 'throttle' block driver implements .bdrv_co_drain_end, so
+blockdev-reopen will have to wait for it to complete in the polling
+loop at the end of qmp_blockdev_reopen(). This makes AIO_WAIT_WHILE()
+release the AioContext lock, which causes a crash if the lock hasn't
+correctly been taken.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Message-Id: <20220203140534.36522-3-kwolf@redhat.com>
+Reviewed-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit ee810602376125ca0e0afd6b7c715e13740978ea)
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ tests/qemu-iotests/245     | 36 +++++++++++++++++++++++++++++++++---
+ tests/qemu-iotests/245.out |  4 ++--
+ 2 files changed, 35 insertions(+), 5 deletions(-)
+
+diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
+index 24ac43f70e..8cbed7821b 100755
+--- a/tests/qemu-iotests/245
++++ b/tests/qemu-iotests/245
+@@ -1138,12 +1138,13 @@ class TestBlockdevReopen(iotests.QMPTestCase):
+         self.assertEqual(self.get_node('hd1'), None)
+         self.assert_qmp(self.get_node('hd2'), 'ro', True)
+ 
+-    def run_test_iothreads(self, iothread_a, iothread_b, errmsg = None):
+-        opts = hd_opts(0)
++    def run_test_iothreads(self, iothread_a, iothread_b, errmsg = None,
++                           opts_a = None, opts_b = None):
++        opts = opts_a or hd_opts(0)
+         result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
+         self.assert_qmp(result, 'return', {})
+ 
+-        opts2 = hd_opts(2)
++        opts2 = opts_b or hd_opts(2)
+         result = self.vm.qmp('blockdev-add', conv_keys = False, **opts2)
+         self.assert_qmp(result, 'return', {})
+ 
+@@ -1194,6 +1195,35 @@ class TestBlockdevReopen(iotests.QMPTestCase):
+     def test_iothreads_switch_overlay(self):
+         self.run_test_iothreads('', 'iothread0')
+ 
++    def test_iothreads_with_throttling(self):
++        # Create a throttle-group object
++        opts = { 'qom-type': 'throttle-group', 'id': 'group0',
++                 'limits': { 'iops-total': 1000 } }
++        result = self.vm.qmp('object-add', conv_keys = False, **opts)
++        self.assert_qmp(result, 'return', {})
++
++        # Options with a throttle filter between format and protocol
++        opts = [
++            {
++                'driver': iotests.imgfmt,
++                'node-name': f'hd{idx}',
++                'file' : {
++                    'node-name': f'hd{idx}-throttle',
++                    'driver': 'throttle',
++                    'throttle-group': 'group0',
++                    'file': {
++                        'driver': 'file',
++                        'node-name': f'hd{idx}-file',
++                        'filename': hd_path[idx],
++                    },
++                },
++            }
++            for idx in (0, 2)
++        ]
++
++        self.run_test_iothreads('iothread0', 'iothread0', None,
++                                opts[0], opts[1])
++
+ if __name__ == '__main__':
+     iotests.activate_logging()
+     iotests.main(supported_fmts=["qcow2"],
+diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
+index 4eced19294..a4e04a3266 100644
+--- a/tests/qemu-iotests/245.out
++++ b/tests/qemu-iotests/245.out
+@@ -17,8 +17,8 @@ read 1/1 bytes at offset 262152
+ read 1/1 bytes at offset 262160
+ 1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ 
+-...............
++................
+ ----------------------------------------------------------------------
+-Ran 25 tests
++Ran 26 tests
+ 
+ OK
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-iotests-Test-qemu-img-convert-of-zeroed-data-cluster.patch b/SOURCES/kvm-iotests-Test-qemu-img-convert-of-zeroed-data-cluster.patch
new file mode 100644
index 0000000..0ab3bcc
--- /dev/null
+++ b/SOURCES/kvm-iotests-Test-qemu-img-convert-of-zeroed-data-cluster.patch
@@ -0,0 +1,81 @@
+From 51f691acd8042351d005873996d7bf4c7b045508 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Fri, 17 Dec 2021 17:46:53 +0100
+Subject: [PATCH 08/12] iotests: Test qemu-img convert of zeroed data cluster
+
+RH-Author: Kevin Wolf <kwolf@redhat.com>
+RH-MergeRequest: 70: qemu-img convert: Fix sparseness of output image
+RH-Commit: [1/2] 0770582c553ac6b0f18c035f9a0238599d4763cc (kmwolf/centos-qemu-kvm)
+RH-Bugzilla: 1882917
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+This demonstrates what happens when the block status changes in
+sub-min_sparse granularity, but all of the parts are zeroed out. The
+alignment logic in is_allocated_sectors() prevents that the target image
+remains fully sparse as expected, but turns it into a data cluster of
+explicit zeros.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Message-Id: <20211217164654.1184218-2-vsementsov@virtuozzo.com>
+Tested-by: Peter Lieven <pl@kamp.de>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 51cd8bddd63540514d44808f7920811439baa253)
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ tests/qemu-iotests/122     |  1 +
+ tests/qemu-iotests/122.out | 10 ++++++++--
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
+index efb260d822..be0f6b79e5 100755
+--- a/tests/qemu-iotests/122
++++ b/tests/qemu-iotests/122
+@@ -251,6 +251,7 @@ $QEMU_IO -c "write -P 0 0 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_test
+ $QEMU_IO -c "write 0 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
+ $QEMU_IO -c "write 8k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
+ $QEMU_IO -c "write 17k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
++$QEMU_IO -c "write -P 0 65k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
+ 
+ for min_sparse in 4k 8k; do
+     echo
+diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
+index 8fbdac2b39..69b8e8b803 100644
+--- a/tests/qemu-iotests/122.out
++++ b/tests/qemu-iotests/122.out
+@@ -192,6 +192,8 @@ wrote 1024/1024 bytes at offset 8192
+ 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ wrote 1024/1024 bytes at offset 17408
+ 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
++wrote 1024/1024 bytes at offset 66560
++1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ 
+ convert -S 4k
+ [{ "start": 0, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+@@ -199,7 +201,9 @@ convert -S 4k
+ { "start": 8192, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+ { "start": 12288, "length": 4096, "depth": 0, "present": false, "zero": true, "data": false},
+ { "start": 16384, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+-{ "start": 20480, "length": 67088384, "depth": 0, "present": false, "zero": true, "data": false}]
++{ "start": 20480, "length": 46080, "depth": 0, "present": false, "zero": true, "data": false},
++{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
++{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
+ 
+ convert -c -S 4k
+ [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
+@@ -211,7 +215,9 @@ convert -c -S 4k
+ 
+ convert -S 8k
+ [{ "start": 0, "length": 24576, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+-{ "start": 24576, "length": 67084288, "depth": 0, "present": false, "zero": true, "data": false}]
++{ "start": 24576, "length": 41984, "depth": 0, "present": false, "zero": true, "data": false},
++{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
++{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
+ 
+ convert -c -S 8k
+ [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-iotests-block-status-cache-New-test.patch b/SOURCES/kvm-iotests-block-status-cache-New-test.patch
new file mode 100644
index 0000000..cd9a198
--- /dev/null
+++ b/SOURCES/kvm-iotests-block-status-cache-New-test.patch
@@ -0,0 +1,197 @@
+From 89fe89491f89a7526ba864a9d94d3de930261d69 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Tue, 18 Jan 2022 18:00:00 +0100
+Subject: [PATCH 07/12] iotests/block-status-cache: New test
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 69: block/io: Update BSC only if want_zero is true
+RH-Commit: [2/2] 3c5a55aca1ac7a71c175a124d63bcf7a4430a022 (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2041461
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+
+Add a new test to verify that want_zero=false block-status calls do not
+pollute the block-status cache for want_zero=true calls.
+
+We check want_zero=true calls and their results using `qemu-img map`
+(over NBD), and want_zero=false calls also using `qemu-img map` over
+NBD, but using the qemu:allocation-depth context.
+
+(This test case cannot be integrated into nbd-qemu-allocation, because
+that is a qcow2 test, and this is a raw test.)
+
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Message-Id: <20220118170000.49423-3-hreitz@redhat.com>
+Reviewed-by: Nir Soffer <nsoffer@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Tested-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 6384dd534d742123d26c008d9794b20bc41359d5)
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ tests/qemu-iotests/tests/block-status-cache   | 139 ++++++++++++++++++
+ .../qemu-iotests/tests/block-status-cache.out |   5 +
+ 2 files changed, 144 insertions(+)
+ create mode 100755 tests/qemu-iotests/tests/block-status-cache
+ create mode 100644 tests/qemu-iotests/tests/block-status-cache.out
+
+diff --git a/tests/qemu-iotests/tests/block-status-cache b/tests/qemu-iotests/tests/block-status-cache
+new file mode 100755
+index 0000000000..6fa10bb8f8
+--- /dev/null
++++ b/tests/qemu-iotests/tests/block-status-cache
+@@ -0,0 +1,139 @@
++#!/usr/bin/env python3
++# group: rw quick
++#
++# Test cases for the block-status cache.
++#
++# Copyright (C) 2022 Red Hat, Inc.
++#
++# 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 <http://www.gnu.org/licenses/>.
++#
++
++import os
++import signal
++import iotests
++from iotests import qemu_img_create, qemu_img_pipe, qemu_nbd
++
++
++image_size = 1 * 1024 * 1024
++test_img = os.path.join(iotests.test_dir, 'test.img')
++
++nbd_pidfile = os.path.join(iotests.test_dir, 'nbd.pid')
++nbd_sock = os.path.join(iotests.sock_dir, 'nbd.sock')
++
++
++class TestBscWithNbd(iotests.QMPTestCase):
++    def setUp(self) -> None:
++        """Just create an empty image with a read-only NBD server on it"""
++        assert qemu_img_create('-f', iotests.imgfmt, test_img,
++                               str(image_size)) == 0
++
++        # Pass --allocation-depth to enable the qemu:allocation-depth context,
++        # which we are going to query to provoke a block-status inquiry with
++        # want_zero=false.
++        assert qemu_nbd(f'--socket={nbd_sock}',
++                        f'--format={iotests.imgfmt}',
++                        '--persistent',
++                        '--allocation-depth',
++                        '--read-only',
++                        f'--pid-file={nbd_pidfile}',
++                        test_img) \
++            == 0
++
++    def tearDown(self) -> None:
++        with open(nbd_pidfile, encoding='utf-8') as f:
++            pid = int(f.read())
++        os.kill(pid, signal.SIGTERM)
++        os.remove(nbd_pidfile)
++        os.remove(test_img)
++
++    def test_with_zero_bug(self) -> None:
++        """
++        Verify that the block-status cache is not corrupted by a
++        want_zero=false call.
++        We can provoke a want_zero=false call with `qemu-img map` over NBD with
++        x-dirty-bitmap=qemu:allocation-depth, so we first run a normal `map`
++        (which results in want_zero=true), then using said
++        qemu:allocation-depth context, and finally another normal `map` to
++        verify that the cache has not been corrupted.
++        """
++
++        nbd_img_opts = f'driver=nbd,server.type=unix,server.path={nbd_sock}'
++        nbd_img_opts_alloc_depth = nbd_img_opts + \
++            ',x-dirty-bitmap=qemu:allocation-depth'
++
++        # Normal map, results in want_zero=true.
++        # This will probably detect an allocated data sector first (qemu likes
++        # to allocate the first sector to facilitate alignment probing), and
++        # then the rest to be zero.  The BSC will thus contain (if anything)
++        # one range covering the first sector.
++        map_pre = qemu_img_pipe('map', '--output=json', '--image-opts',
++                                nbd_img_opts)
++
++        # qemu:allocation-depth maps for want_zero=false.
++        # want_zero=false should (with the file driver, which the server is
++        # using) report everything as data.  While this is sufficient for
++        # want_zero=false, this is nothing that should end up in the
++        # block-status cache.
++        # Due to a bug, this information did end up in the cache, though, and
++        # this would lead to wrong information being returned on subsequent
++        # want_zero=true calls.
++        #
++        # We need to run this map twice: On the first call, we probably still
++        # have the first sector in the cache, and so this will be served from
++        # the cache; and only the subsequent range will be queried from the
++        # block driver.  This subsequent range will then be entered into the
++        # cache.
++        # If we did a want_zero=true call at this point, we would thus get
++        # correct information: The first sector is not covered by the cache, so
++        # we would get fresh block-status information from the driver, which
++        # would return a data range, and this would then go into the cache,
++        # evicting the wrong range from the want_zero=false call before.
++        #
++        # Therefore, we need a second want_zero=false map to reproduce:
++        # Since the first sector is not in the cache, the query for its status
++        # will go to the driver, which will return a result that reports the
++        # whole image to be a single data area.  This result will then go into
++        # the cache, and so the cache will then report the whole image to
++        # contain data.
++        #
++        # Note that once the cache reports the whole image to contain data, any
++        # subsequent map operation will be served from the cache, and so we can
++        # never loop too many times here.
++        for _ in range(2):
++            # (Ignore the result, this is just to contaminate the cache)
++            qemu_img_pipe('map', '--output=json', '--image-opts',
++                          nbd_img_opts_alloc_depth)
++
++        # Now let's see whether the cache reports everything as data, or
++        # whether we get correct information (i.e. the same as we got on our
++        # first attempt).
++        map_post = qemu_img_pipe('map', '--output=json', '--image-opts',
++                                 nbd_img_opts)
++
++        if map_pre != map_post:
++            print('ERROR: Map information differs before and after querying ' +
++                  'qemu:allocation-depth')
++            print('Before:')
++            print(map_pre)
++            print('After:')
++            print(map_post)
++
++            self.fail("Map information differs")
++
++
++if __name__ == '__main__':
++    # The block-status cache only works on the protocol layer, so to test it,
++    # we can only use the raw format
++    iotests.main(supported_fmts=['raw'],
++                 supported_protocols=['file'])
+diff --git a/tests/qemu-iotests/tests/block-status-cache.out b/tests/qemu-iotests/tests/block-status-cache.out
+new file mode 100644
+index 0000000000..ae1213e6f8
+--- /dev/null
++++ b/tests/qemu-iotests/tests/block-status-cache.out
+@@ -0,0 +1,5 @@
++.
++----------------------------------------------------------------------
++Ran 1 tests
++
++OK
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-iotests-stream-error-on-reset-New-test.patch b/SOURCES/kvm-iotests-stream-error-on-reset-New-test.patch
new file mode 100644
index 0000000..cf69e38
--- /dev/null
+++ b/SOURCES/kvm-iotests-stream-error-on-reset-New-test.patch
@@ -0,0 +1,196 @@
+From 300f912d4a5afe4ecca9c68a71429fbc9966ec34 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Tue, 11 Jan 2022 15:36:13 +0000
+Subject: [PATCH 11/12] iotests/stream-error-on-reset: New test
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 71: block-backend: prevent dangling BDS pointers across aio_poll()
+RH-Commit: [2/2] 3167f31b91eb433f338564201f4ef336e39f7f7d (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2040123
+RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
+
+Test the following scenario:
+- Simple stream block in two-layer backing chain (base and top)
+- The job is drained via blk_drain(), then an error occurs while the job
+  settles the ongoing request
+- And so the job completes while in blk_drain()
+
+This was reported as a segfault, but is fixed by "block-backend: prevent
+dangling BDS pointers across aio_poll()".
+
+Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2036178
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Message-Id: <20220111153613.25453-3-stefanha@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 2ca1d5d6b91f8a52a5c651f660b2f58c94bf97ba)
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ .../qemu-iotests/tests/stream-error-on-reset  | 140 ++++++++++++++++++
+ .../tests/stream-error-on-reset.out           |   5 +
+ 2 files changed, 145 insertions(+)
+ create mode 100755 tests/qemu-iotests/tests/stream-error-on-reset
+ create mode 100644 tests/qemu-iotests/tests/stream-error-on-reset.out
+
+diff --git a/tests/qemu-iotests/tests/stream-error-on-reset b/tests/qemu-iotests/tests/stream-error-on-reset
+new file mode 100755
+index 0000000000..7eaedb24d7
+--- /dev/null
++++ b/tests/qemu-iotests/tests/stream-error-on-reset
+@@ -0,0 +1,140 @@
++#!/usr/bin/env python3
++# group: rw quick
++#
++# Test what happens when a stream job completes in a blk_drain().
++#
++# Copyright (C) 2022 Red Hat, Inc.
++#
++# 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 <http://www.gnu.org/licenses/>.
++#
++
++import os
++import iotests
++from iotests import imgfmt, qemu_img_create, qemu_io_silent, QMPTestCase
++
++
++image_size = 1 * 1024 * 1024
++data_size = 64 * 1024
++base = os.path.join(iotests.test_dir, 'base.img')
++top = os.path.join(iotests.test_dir, 'top.img')
++
++
++# We want to test completing a stream job in a blk_drain().
++#
++# The blk_drain() we are going to use is a virtio-scsi device resetting,
++# which we can trigger by resetting the system.
++#
++# In order to have the block job complete on drain, we (1) throttle its
++# base image so we can start the drain after it has begun, but before it
++# completes, and (2) make it encounter an I/O error on the ensuing write.
++# (If it completes regularly, the completion happens after the drain for
++# some reason.)
++
++class TestStreamErrorOnReset(QMPTestCase):
++    def setUp(self) -> None:
++        """
++        Create two images:
++        - base image {base} with {data_size} bytes allocated
++        - top image {top} without any data allocated
++
++        And the following VM configuration:
++        - base image throttled to {data_size}
++        - top image with a blkdebug configuration so the first write access
++          to it will result in an error
++        - top image is attached to a virtio-scsi device
++        """
++        assert qemu_img_create('-f', imgfmt, base, str(image_size)) == 0
++        assert qemu_io_silent('-c', f'write 0 {data_size}', base) == 0
++        assert qemu_img_create('-f', imgfmt, top, str(image_size)) == 0
++
++        self.vm = iotests.VM()
++        self.vm.add_args('-accel', 'tcg') # Make throttling work properly
++        self.vm.add_object(self.vm.qmp_to_opts({
++            'qom-type': 'throttle-group',
++            'id': 'thrgr',
++            'x-bps-total': str(data_size)
++        }))
++        self.vm.add_blockdev(self.vm.qmp_to_opts({
++            'driver': imgfmt,
++            'node-name': 'base',
++            'file': {
++                'driver': 'throttle',
++                'throttle-group': 'thrgr',
++                'file': {
++                    'driver': 'file',
++                    'filename': base
++                }
++            }
++        }))
++        self.vm.add_blockdev(self.vm.qmp_to_opts({
++            'driver': imgfmt,
++            'node-name': 'top',
++            'file': {
++                'driver': 'blkdebug',
++                'node-name': 'top-blkdebug',
++                'inject-error': [{
++                    'event': 'pwritev',
++                    'immediately': 'true',
++                    'once': 'true'
++                }],
++                'image': {
++                    'driver': 'file',
++                    'filename': top
++                }
++            },
++            'backing': 'base'
++        }))
++        self.vm.add_device(self.vm.qmp_to_opts({
++            'driver': 'virtio-scsi',
++            'id': 'vscsi'
++        }))
++        self.vm.add_device(self.vm.qmp_to_opts({
++            'driver': 'scsi-hd',
++            'bus': 'vscsi.0',
++            'drive': 'top'
++        }))
++        self.vm.launch()
++
++    def tearDown(self) -> None:
++        self.vm.shutdown()
++        os.remove(top)
++        os.remove(base)
++
++    def test_stream_error_on_reset(self) -> None:
++        # Launch a stream job, which will take at least a second to
++        # complete, because the base image is throttled (so we can
++        # get in between it having started and it having completed)
++        res = self.vm.qmp('block-stream', job_id='stream', device='top')
++        self.assert_qmp(res, 'return', {})
++
++        while True:
++            ev = self.vm.event_wait('JOB_STATUS_CHANGE')
++            if ev['data']['status'] == 'running':
++                # Once the stream job is running, reset the system, which
++                # forces the virtio-scsi device to be reset, thus draining
++                # the stream job, and making it complete.  Completing
++                # inside of that drain should not result in a segfault.
++                res = self.vm.qmp('system_reset')
++                self.assert_qmp(res, 'return', {})
++            elif ev['data']['status'] == 'null':
++                # The test is done once the job is gone
++                break
++
++
++if __name__ == '__main__':
++    # Passes with any format with backing file support, but qed and
++    # qcow1 do not seem to exercise the used-to-be problematic code
++    # path, so there is no point in having them in this list
++    iotests.main(supported_fmts=['qcow2', 'vmdk'],
++                 supported_protocols=['file'])
+diff --git a/tests/qemu-iotests/tests/stream-error-on-reset.out b/tests/qemu-iotests/tests/stream-error-on-reset.out
+new file mode 100644
+index 0000000000..ae1213e6f8
+--- /dev/null
++++ b/tests/qemu-iotests/tests/stream-error-on-reset.out
+@@ -0,0 +1,5 @@
++.
++----------------------------------------------------------------------
++Ran 1 tests
++
++OK
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-iotests.py-Add-QemuStorageDaemon-class.patch b/SOURCES/kvm-iotests.py-Add-QemuStorageDaemon-class.patch
new file mode 100644
index 0000000..b215d23
--- /dev/null
+++ b/SOURCES/kvm-iotests.py-Add-QemuStorageDaemon-class.patch
@@ -0,0 +1,92 @@
+From c21502a220d107261c9a8627158f357489d86543 Mon Sep 17 00:00:00 2001
+From: Hanna Reitz <hreitz@redhat.com>
+Date: Fri, 4 Feb 2022 12:10:09 +0100
+Subject: [PATCH 5/8] iotests.py: Add QemuStorageDaemon class
+
+RH-Author: Hanna Reitz <hreitz@redhat.com>
+RH-MergeRequest: 74: block/nbd: Handle AioContext changes
+RH-Commit: [3/6] 5da1cda4d025c1bd7029ed8071b4ccf25459a878 (hreitz/qemu-kvm-c-9-s)
+RH-Bugzilla: 2033626
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+
+This is a rather simple class that allows creating a QSD instance
+running in the background and stopping it when no longer needed.
+
+The __del__ handler is a safety net for when something goes so wrong in
+a test that e.g. the tearDown() method is not called (e.g. setUp()
+launches the QSD, but then launching a VM fails).  We do not want the
+QSD to continue running after the test has failed, so __del__() will
+take care to kill it.
+
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+(cherry picked from commit 091dc7b2b5553a529bff9a7bf9ad3bc85bc5bdcd)
+Signed-off-by: Hanna Reitz <hreitz@redhat.com>
+---
+ tests/qemu-iotests/iotests.py | 40 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+
+diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
+index 83bfedb902..a51b5ce8cd 100644
+--- a/tests/qemu-iotests/iotests.py
++++ b/tests/qemu-iotests/iotests.py
+@@ -72,6 +72,8 @@
+ qemu_prog = os.environ.get('QEMU_PROG', 'qemu')
+ qemu_opts = os.environ.get('QEMU_OPTIONS', '').strip().split(' ')
+ 
++qsd_prog = os.environ.get('QSD_PROG', 'qemu-storage-daemon')
++
+ gdb_qemu_env = os.environ.get('GDB_OPTIONS')
+ qemu_gdb = []
+ if gdb_qemu_env:
+@@ -312,6 +314,44 @@ def cmd(self, cmd):
+         return self._read_output()
+ 
+ 
++class QemuStorageDaemon:
++    def __init__(self, *args: str, instance_id: str = 'a'):
++        assert '--pidfile' not in args
++        self.pidfile = os.path.join(test_dir, f'qsd-{instance_id}-pid')
++        all_args = [qsd_prog] + list(args) + ['--pidfile', self.pidfile]
++
++        # Cannot use with here, we want the subprocess to stay around
++        # pylint: disable=consider-using-with
++        self._p = subprocess.Popen(all_args)
++        while not os.path.exists(self.pidfile):
++            if self._p.poll() is not None:
++                cmd = ' '.join(all_args)
++                raise RuntimeError(
++                    'qemu-storage-daemon terminated with exit code ' +
++                    f'{self._p.returncode}: {cmd}')
++
++            time.sleep(0.01)
++
++        with open(self.pidfile, encoding='utf-8') as f:
++            self._pid = int(f.read().strip())
++
++        assert self._pid == self._p.pid
++
++    def stop(self, kill_signal=15):
++        self._p.send_signal(kill_signal)
++        self._p.wait()
++        self._p = None
++
++        try:
++            os.remove(self.pidfile)
++        except OSError:
++            pass
++
++    def __del__(self):
++        if self._p is not None:
++            self.stop(kill_signal=9)
++
++
+ def qemu_nbd(*args):
+     '''Run qemu-nbd in daemon mode and return the parent's exit code'''
+     return subprocess.call(qemu_nbd_args + ['--fork'] + list(args))
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-numa-Enable-numa-for-SGX-EPC-sections.patch b/SOURCES/kvm-numa-Enable-numa-for-SGX-EPC-sections.patch
new file mode 100644
index 0000000..e26bfcf
--- /dev/null
+++ b/SOURCES/kvm-numa-Enable-numa-for-SGX-EPC-sections.patch
@@ -0,0 +1,287 @@
+From 6274a2a09a8931188889467b104bf2e2fc39cb54 Mon Sep 17 00:00:00 2001
+From: Yang Zhong <yang.zhong@intel.com>
+Date: Mon, 1 Nov 2021 12:20:05 -0400
+Subject: [PATCH 01/12] numa: Enable numa for SGX EPC sections
+
+RH-Author: Paul Lai <plai@redhat.com>
+RH-MergeRequest: 65: Enable SGX and add SGX Numa support
+RH-Commit: [1/5] ff69d138c3f5903096388ec7ccf8dc5e6c6c6ffb
+RH-Bugzilla: 2033708
+RH-Acked-by: Paolo Bonzini <None>
+RH-Acked-by: Bandan Das <None>
+RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
+
+The basic SGX did not enable numa for SGX EPC sections, which
+result in all EPC sections located in numa node 0. This patch
+enable SGX numa function in the guest and the EPC section can
+work with RAM as one numa node.
+
+The Guest kernel related log:
+[    0.009981] ACPI: SRAT: Node 0 PXM 0 [mem 0x180000000-0x183ffffff]
+[    0.009982] ACPI: SRAT: Node 1 PXM 1 [mem 0x184000000-0x185bfffff]
+The SRAT table can normally show SGX EPC sections menory info in different
+numa nodes.
+
+The SGX EPC numa related command:
+ ......
+ -m 4G,maxmem=20G \
+ -smp sockets=2,cores=2 \
+ -cpu host,+sgx-provisionkey \
+ -object memory-backend-ram,size=2G,host-nodes=0,policy=bind,id=node0 \
+ -object memory-backend-epc,id=mem0,size=64M,prealloc=on,host-nodes=0,policy=bind \
+ -numa node,nodeid=0,cpus=0-1,memdev=node0 \
+ -object memory-backend-ram,size=2G,host-nodes=1,policy=bind,id=node1 \
+ -object memory-backend-epc,id=mem1,size=28M,prealloc=on,host-nodes=1,policy=bind \
+ -numa node,nodeid=1,cpus=2-3,memdev=node1 \
+ -M sgx-epc.0.memdev=mem0,sgx-epc.0.node=0,sgx-epc.1.memdev=mem1,sgx-epc.1.node=1 \
+ ......
+
+Signed-off-by: Yang Zhong <yang.zhong@intel.com>
+Message-Id: <20211101162009.62161-2-yang.zhong@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 1105812382e1126d86dddc16b3700f8c79dc93d1)
+Signed-off-by: Paul Lai <plai@redhat.com>
+---
+ hw/core/numa.c            |  5 ++---
+ hw/i386/acpi-build.c      |  2 ++
+ hw/i386/sgx-epc.c         |  3 +++
+ hw/i386/sgx-stub.c        |  4 ++++
+ hw/i386/sgx.c             | 44 +++++++++++++++++++++++++++++++++++++++
+ include/hw/i386/sgx-epc.h |  3 +++
+ monitor/hmp-cmds.c        |  1 +
+ qapi/machine.json         | 10 ++++++++-
+ qemu-options.hx           |  4 ++--
+ 9 files changed, 70 insertions(+), 6 deletions(-)
+
+diff --git a/hw/core/numa.c b/hw/core/numa.c
+index e6050b2273..1aa05dcf42 100644
+--- a/hw/core/numa.c
++++ b/hw/core/numa.c
+@@ -784,9 +784,8 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[])
+                 break;
+             case MEMORY_DEVICE_INFO_KIND_SGX_EPC:
+                 se = value->u.sgx_epc.data;
+-                /* TODO: once we support numa, assign to right node */
+-                node_mem[0].node_mem += se->size;
+-                node_mem[0].node_plugged_mem += se->size;
++                node_mem[se->node].node_mem += se->size;
++                node_mem[se->node].node_plugged_mem = 0;
+                 break;
+             default:
+                 g_assert_not_reached();
+diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
+index a99c6e4fe3..8383b83ee3 100644
+--- a/hw/i386/acpi-build.c
++++ b/hw/i386/acpi-build.c
+@@ -2068,6 +2068,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
+         nvdimm_build_srat(table_data);
+     }
+ 
++    sgx_epc_build_srat(table_data);
++
+     /*
+      * TODO: this part is not in ACPI spec and current linux kernel boots fine
+      * without these entries. But I recall there were issues the last time I
+diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c
+index e508827e78..96b2940d75 100644
+--- a/hw/i386/sgx-epc.c
++++ b/hw/i386/sgx-epc.c
+@@ -21,6 +21,7 @@
+ 
+ static Property sgx_epc_properties[] = {
+     DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0),
++    DEFINE_PROP_UINT32(SGX_EPC_NUMA_NODE_PROP, SGXEPCDevice, node, 0),
+     DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem,
+                      TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *),
+     DEFINE_PROP_END_OF_LIST(),
+@@ -139,6 +140,8 @@ static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md,
+     se->memaddr = epc->addr;
+     se->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP,
+                                         NULL);
++    se->node = object_property_get_uint(OBJECT(epc), SGX_EPC_NUMA_NODE_PROP,
++                                        NULL);
+     se->memdev = object_get_canonical_path(OBJECT(epc->hostmem));
+ 
+     info->u.sgx_epc.data = se;
+diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c
+index c9b379e665..26833eb233 100644
+--- a/hw/i386/sgx-stub.c
++++ b/hw/i386/sgx-stub.c
+@@ -6,6 +6,10 @@
+ #include "qapi/error.h"
+ #include "qapi/qapi-commands-misc-target.h"
+ 
++void sgx_epc_build_srat(GArray *table_data)
++{
++}
++
+ SGXInfo *qmp_query_sgx(Error **errp)
+ {
+     error_setg(errp, "SGX support is not compiled in");
+diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
+index 8fef3dd8fa..d04299904a 100644
+--- a/hw/i386/sgx.c
++++ b/hw/i386/sgx.c
+@@ -23,6 +23,7 @@
+ #include "sysemu/hw_accel.h"
+ #include "sysemu/reset.h"
+ #include <sys/ioctl.h>
++#include "hw/acpi/aml-build.h"
+ 
+ #define SGX_MAX_EPC_SECTIONS            8
+ #define SGX_CPUID_EPC_INVALID           0x0
+@@ -36,6 +37,46 @@
+ 
+ #define RETRY_NUM                       2
+ 
++static int sgx_epc_device_list(Object *obj, void *opaque)
++{
++    GSList **list = opaque;
++
++    if (object_dynamic_cast(obj, TYPE_SGX_EPC)) {
++        *list = g_slist_append(*list, DEVICE(obj));
++    }
++
++    object_child_foreach(obj, sgx_epc_device_list, opaque);
++    return 0;
++}
++
++static GSList *sgx_epc_get_device_list(void)
++{
++    GSList *list = NULL;
++
++    object_child_foreach(qdev_get_machine(), sgx_epc_device_list, &list);
++    return list;
++}
++
++void sgx_epc_build_srat(GArray *table_data)
++{
++    GSList *device_list = sgx_epc_get_device_list();
++
++    for (; device_list; device_list = device_list->next) {
++        DeviceState *dev = device_list->data;
++        Object *obj = OBJECT(dev);
++        uint64_t addr, size;
++        int node;
++
++        node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP,
++                                        &error_abort);
++        addr = object_property_get_uint(obj, SGX_EPC_ADDR_PROP, &error_abort);
++        size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP, &error_abort);
++
++        build_srat_memory(table_data, addr, size, node, MEM_AFFINITY_ENABLED);
++    }
++    g_slist_free(device_list);
++}
++
+ static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high)
+ {
+     return (low & MAKE_64BIT_MASK(12, 20)) +
+@@ -226,6 +267,9 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms)
+         /* set the memdev link with memory backend */
+         object_property_parse(obj, SGX_EPC_MEMDEV_PROP, list->value->memdev,
+                               &error_fatal);
++        /* set the numa node property for sgx epc object */
++        object_property_set_uint(obj, SGX_EPC_NUMA_NODE_PROP, list->value->node,
++                             &error_fatal);
+         object_property_set_bool(obj, "realized", true, &error_fatal);
+         object_unref(obj);
+     }
+diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h
+index a6a65be854..581fac389a 100644
+--- a/include/hw/i386/sgx-epc.h
++++ b/include/hw/i386/sgx-epc.h
+@@ -25,6 +25,7 @@
+ #define SGX_EPC_ADDR_PROP "addr"
+ #define SGX_EPC_SIZE_PROP "size"
+ #define SGX_EPC_MEMDEV_PROP "memdev"
++#define SGX_EPC_NUMA_NODE_PROP "node"
+ 
+ /**
+  * SGXEPCDevice:
+@@ -38,6 +39,7 @@ typedef struct SGXEPCDevice {
+ 
+     /* public */
+     uint64_t addr;
++    uint32_t node;
+     HostMemoryBackendEpc *hostmem;
+ } SGXEPCDevice;
+ 
+@@ -56,6 +58,7 @@ typedef struct SGXEPCState {
+ } SGXEPCState;
+ 
+ bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size);
++void sgx_epc_build_srat(GArray *table_data);
+ 
+ static inline uint64_t sgx_epc_above_4g_end(SGXEPCState *sgx_epc)
+ {
+diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
+index 9c91bf93e9..2669156b28 100644
+--- a/monitor/hmp-cmds.c
++++ b/monitor/hmp-cmds.c
+@@ -1810,6 +1810,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
+                                se->id ? se->id : "");
+                 monitor_printf(mon, "  memaddr: 0x%" PRIx64 "\n", se->memaddr);
+                 monitor_printf(mon, "  size: %" PRIu64 "\n", se->size);
++                monitor_printf(mon, "  node: %" PRId64 "\n", se->node);
+                 monitor_printf(mon, "  memdev: %s\n", se->memdev);
+                 break;
+             default:
+diff --git a/qapi/machine.json b/qapi/machine.json
+index 067e3f5378..16e771affc 100644
+--- a/qapi/machine.json
++++ b/qapi/machine.json
+@@ -1207,12 +1207,15 @@
+ #
+ # @memdev: memory backend linked with device
+ #
++# @node: the numa node
++#
+ # Since: 6.2
+ ##
+ { 'struct': 'SgxEPCDeviceInfo',
+   'data': { '*id': 'str',
+             'memaddr': 'size',
+             'size': 'size',
++            'node': 'int',
+             'memdev': 'str'
+           }
+ }
+@@ -1285,10 +1288,15 @@
+ #
+ # @memdev: memory backend linked with device
+ #
++# @node: the numa node
++#
+ # Since: 6.2
+ ##
+ { 'struct': 'SgxEPC',
+-  'data': { 'memdev': 'str' } }
++  'data': { 'memdev': 'str',
++            'node': 'int'
++          }
++}
+ 
+ ##
+ # @SgxEPCProperties:
+diff --git a/qemu-options.hx b/qemu-options.hx
+index 94c4a8dbaf..4b7798088b 100644
+--- a/qemu-options.hx
++++ b/qemu-options.hx
+@@ -127,11 +127,11 @@ SRST
+ ERST
+ 
+ DEF("M", HAS_ARG, QEMU_OPTION_M,
+-    "                sgx-epc.0.memdev=memid\n",
++    "                sgx-epc.0.memdev=memid,sgx-epc.0.node=numaid\n",
+     QEMU_ARCH_ALL)
+ 
+ SRST
+-``sgx-epc.0.memdev=@var{memid}``
++``sgx-epc.0.memdev=@var{memid},sgx-epc.0.node=@var{numaid}``
+     Define an SGX EPC section.
+ ERST
+ 
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch b/SOURCES/kvm-numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch
new file mode 100644
index 0000000..de4c4b1
--- /dev/null
+++ b/SOURCES/kvm-numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch
@@ -0,0 +1,210 @@
+From 0f75501ba348dc9fb3ce0198ceafc8093149457d Mon Sep 17 00:00:00 2001
+From: Yang Zhong <yang.zhong@intel.com>
+Date: Mon, 1 Nov 2021 12:20:07 -0400
+Subject: [PATCH 02/12] numa: Support SGX numa in the monitor and Libvirt
+ interfaces
+
+RH-Author: Paul Lai <plai@redhat.com>
+RH-MergeRequest: 65: Enable SGX and add SGX Numa support
+RH-Commit: [2/5] 8c19cfb1a139fd4dbac771e695a133f16a68437f
+RH-Bugzilla: 2033708
+RH-Acked-by: Paolo Bonzini <None>
+RH-Acked-by: Bandan Das <None>
+RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
+
+Add the SGXEPCSection list into SGXInfo to show the multiple
+SGX EPC sections detailed info, not the total size like before.
+This patch can enable numa support for 'info sgx' command and
+QMP interfaces. The new interfaces show each EPC section info
+in one numa node. Libvirt can use QMP interface to get the
+detailed host SGX EPC capabilities to decide how to allocate
+host EPC sections to guest.
+
+(qemu) info sgx
+ SGX support: enabled
+ SGX1 support: enabled
+ SGX2 support: enabled
+ FLC support: enabled
+ NUMA node #0: size=67108864
+ NUMA node #1: size=29360128
+
+The QMP interface show:
+(QEMU) query-sgx
+{"return": {"sgx": true, "sgx2": true, "sgx1": true, "sections": \
+[{"node": 0, "size": 67108864}, {"node": 1, "size": 29360128}], "flc": true}}
+
+(QEMU) query-sgx-capabilities
+{"return": {"sgx": true, "sgx2": true, "sgx1": true, "sections": \
+[{"node": 0, "size": 17070817280}, {"node": 1, "size": 17079205888}], "flc": true}}
+
+Signed-off-by: Yang Zhong <yang.zhong@intel.com>
+Message-Id: <20211101162009.62161-4-yang.zhong@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 4755927ae12547c2e7cb22c5fa1b39038c6c11b1)
+Signed-off-by: Paul Lai <plai@redhat.com>
+---
+ hw/i386/sgx.c         | 51 +++++++++++++++++++++++++++++++++++--------
+ qapi/misc-target.json | 19 ++++++++++++++--
+ 2 files changed, 59 insertions(+), 11 deletions(-)
+
+diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
+index d04299904a..5de5dd0893 100644
+--- a/hw/i386/sgx.c
++++ b/hw/i386/sgx.c
+@@ -83,11 +83,13 @@ static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high)
+            ((high & MAKE_64BIT_MASK(0, 20)) << 32);
+ }
+ 
+-static uint64_t sgx_calc_host_epc_section_size(void)
++static SGXEPCSectionList *sgx_calc_host_epc_sections(void)
+ {
++    SGXEPCSectionList *head = NULL, **tail = &head;
++    SGXEPCSection *section;
+     uint32_t i, type;
+     uint32_t eax, ebx, ecx, edx;
+-    uint64_t size = 0;
++    uint32_t j = 0;
+ 
+     for (i = 0; i < SGX_MAX_EPC_SECTIONS; i++) {
+         host_cpuid(0x12, i + 2, &eax, &ebx, &ecx, &edx);
+@@ -101,10 +103,13 @@ static uint64_t sgx_calc_host_epc_section_size(void)
+             break;
+         }
+ 
+-        size += sgx_calc_section_metric(ecx, edx);
++        section = g_new0(SGXEPCSection, 1);
++        section->node = j++;
++        section->size = sgx_calc_section_metric(ecx, edx);
++        QAPI_LIST_APPEND(tail, section);
+     }
+ 
+-    return size;
++    return head;
+ }
+ 
+ static void sgx_epc_reset(void *opaque)
+@@ -168,13 +173,35 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp)
+     info->sgx1 = eax & (1U << 0) ? true : false;
+     info->sgx2 = eax & (1U << 1) ? true : false;
+ 
+-    info->section_size = sgx_calc_host_epc_section_size();
++    info->sections = sgx_calc_host_epc_sections();
+ 
+     close(fd);
+ 
+     return info;
+ }
+ 
++static SGXEPCSectionList *sgx_get_epc_sections_list(void)
++{
++    GSList *device_list = sgx_epc_get_device_list();
++    SGXEPCSectionList *head = NULL, **tail = &head;
++    SGXEPCSection *section;
++
++    for (; device_list; device_list = device_list->next) {
++        DeviceState *dev = device_list->data;
++        Object *obj = OBJECT(dev);
++
++        section = g_new0(SGXEPCSection, 1);
++        section->node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP,
++                                                 &error_abort);
++        section->size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP,
++                                                 &error_abort);
++        QAPI_LIST_APPEND(tail, section);
++    }
++    g_slist_free(device_list);
++
++    return head;
++}
++
+ SGXInfo *qmp_query_sgx(Error **errp)
+ {
+     SGXInfo *info = NULL;
+@@ -193,14 +220,13 @@ SGXInfo *qmp_query_sgx(Error **errp)
+         return NULL;
+     }
+ 
+-    SGXEPCState *sgx_epc = &pcms->sgx_epc;
+     info = g_new0(SGXInfo, 1);
+ 
+     info->sgx = true;
+     info->sgx1 = true;
+     info->sgx2 = true;
+     info->flc = true;
+-    info->section_size = sgx_epc->size;
++    info->sections = sgx_get_epc_sections_list();
+ 
+     return info;
+ }
+@@ -208,6 +234,7 @@ SGXInfo *qmp_query_sgx(Error **errp)
+ void hmp_info_sgx(Monitor *mon, const QDict *qdict)
+ {
+     Error *err = NULL;
++    SGXEPCSectionList *section_list, *section;
+     g_autoptr(SGXInfo) info = qmp_query_sgx(&err);
+ 
+     if (err) {
+@@ -222,8 +249,14 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict)
+                    info->sgx2 ? "enabled" : "disabled");
+     monitor_printf(mon, "FLC support: %s\n",
+                    info->flc ? "enabled" : "disabled");
+-    monitor_printf(mon, "size: %" PRIu64 "\n",
+-                   info->section_size);
++
++    section_list = info->sections;
++    for (section = section_list; section; section = section->next) {
++        monitor_printf(mon, "NUMA node #%" PRId64 ": ",
++                       section->value->node);
++        monitor_printf(mon, "size=%" PRIu64 "\n",
++                       section->value->size);
++    }
+ }
+ 
+ bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
+diff --git a/qapi/misc-target.json b/qapi/misc-target.json
+index 5aa2b95b7d..1022aa0184 100644
+--- a/qapi/misc-target.json
++++ b/qapi/misc-target.json
+@@ -337,6 +337,21 @@
+   'if': 'TARGET_ARM' }
+ 
+ 
++##
++# @SGXEPCSection:
++#
++# Information about intel SGX EPC section info
++#
++# @node: the numa node
++#
++# @size: the size of epc section
++#
++# Since: 6.2
++##
++{ 'struct': 'SGXEPCSection',
++  'data': { 'node': 'int',
++            'size': 'uint64'}}
++
+ ##
+ # @SGXInfo:
+ #
+@@ -350,7 +365,7 @@
+ #
+ # @flc: true if FLC is supported
+ #
+-# @section-size: The EPC section size for guest
++# @sections: The EPC sections info for guest
+ #
+ # Since: 6.2
+ ##
+@@ -359,7 +374,7 @@
+             'sgx1': 'bool',
+             'sgx2': 'bool',
+             'flc': 'bool',
+-            'section-size': 'uint64'},
++            'sections': ['SGXEPCSection']},
+    'if': 'TARGET_I386' }
+ 
+ ##
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch b/SOURCES/kvm-qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch
new file mode 100644
index 0000000..9e58f6c
--- /dev/null
+++ b/SOURCES/kvm-qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch
@@ -0,0 +1,213 @@
+From a6a327ae392c02b8e8c75b5d702d929ff8fe408d Mon Sep 17 00:00:00 2001
+From: Yang Zhong <yang.zhong@intel.com>
+Date: Thu, 20 Jan 2022 17:31:04 -0500
+Subject: [PATCH 05/12] qapi: Cleanup SGX related comments and restore
+ @section-size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Paul Lai <plai@redhat.com>
+RH-MergeRequest: 65: Enable SGX and add SGX Numa support
+RH-Commit: [5/5] 0d3b9f37cd3cce202050ba3bd51eef4410ef3d38
+RH-Bugzilla: 2033708
+RH-Acked-by: Paolo Bonzini <None>
+RH-Acked-by: Bandan Das <None>
+RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
+
+The SGX NUMA patches were merged into Qemu 7.0 release, we need
+clarify detailed version history information and also change
+some related comments, which make SGX related comments clearer.
+
+The QMP command schema promises backwards compatibility as standard.
+We temporarily restore "@section-size", which can avoid incompatible
+API breakage. The "@section-size" will be deprecated in 7.2 version.
+
+Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
+Signed-off-by: Yang Zhong <yang.zhong@intel.com>
+Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
+Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
+Message-Id: <20220120223104.437161-1-yang.zhong@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Paul Lai <plai@redhat.com>
+---
+ docs/about/deprecated.rst | 13 +++++++++++++
+ hw/i386/sgx.c             | 11 +++++++++--
+ qapi/machine.json         |  4 ++--
+ qapi/misc-target.json     | 22 +++++++++++++++++-----
+ 4 files changed, 41 insertions(+), 9 deletions(-)
+
+diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
+index ff7488cb63..33925edf45 100644
+--- a/docs/about/deprecated.rst
++++ b/docs/about/deprecated.rst
+@@ -270,6 +270,19 @@ accepted incorrect commands will return an error. Users should make sure that
+ all arguments passed to ``device_add`` are consistent with the documented
+ property types.
+ 
++``query-sgx`` return value member ``section-size`` (since 7.0)
++''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
++
++Member ``section-size`` in return value elements with meta-type ``uint64`` is
++deprecated.  Use ``sections`` instead.
++
++
++``query-sgx-capabilities`` return value member ``section-size`` (since 7.0)
++'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
++
++Member ``section-size`` in return value elements with meta-type ``uint64`` is
++deprecated.  Use ``sections`` instead.
++
+ System accelerators
+ -------------------
+ 
+diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
+index 5de5dd0893..a2b318dd93 100644
+--- a/hw/i386/sgx.c
++++ b/hw/i386/sgx.c
+@@ -83,7 +83,7 @@ static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high)
+            ((high & MAKE_64BIT_MASK(0, 20)) << 32);
+ }
+ 
+-static SGXEPCSectionList *sgx_calc_host_epc_sections(void)
++static SGXEPCSectionList *sgx_calc_host_epc_sections(uint64_t *size)
+ {
+     SGXEPCSectionList *head = NULL, **tail = &head;
+     SGXEPCSection *section;
+@@ -106,6 +106,7 @@ static SGXEPCSectionList *sgx_calc_host_epc_sections(void)
+         section = g_new0(SGXEPCSection, 1);
+         section->node = j++;
+         section->size = sgx_calc_section_metric(ecx, edx);
++        *size += section->size;
+         QAPI_LIST_APPEND(tail, section);
+     }
+ 
+@@ -156,6 +157,7 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp)
+ {
+     SGXInfo *info = NULL;
+     uint32_t eax, ebx, ecx, edx;
++    uint64_t size = 0;
+ 
+     int fd = qemu_open_old("/dev/sgx_vepc", O_RDWR);
+     if (fd < 0) {
+@@ -173,7 +175,8 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp)
+     info->sgx1 = eax & (1U << 0) ? true : false;
+     info->sgx2 = eax & (1U << 1) ? true : false;
+ 
+-    info->sections = sgx_calc_host_epc_sections();
++    info->sections = sgx_calc_host_epc_sections(&size);
++    info->section_size = size;
+ 
+     close(fd);
+ 
+@@ -220,12 +223,14 @@ SGXInfo *qmp_query_sgx(Error **errp)
+         return NULL;
+     }
+ 
++    SGXEPCState *sgx_epc = &pcms->sgx_epc;
+     info = g_new0(SGXInfo, 1);
+ 
+     info->sgx = true;
+     info->sgx1 = true;
+     info->sgx2 = true;
+     info->flc = true;
++    info->section_size = sgx_epc->size;
+     info->sections = sgx_get_epc_sections_list();
+ 
+     return info;
+@@ -249,6 +254,8 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict)
+                    info->sgx2 ? "enabled" : "disabled");
+     monitor_printf(mon, "FLC support: %s\n",
+                    info->flc ? "enabled" : "disabled");
++    monitor_printf(mon, "size: %" PRIu64 "\n",
++                   info->section_size);
+ 
+     section_list = info->sections;
+     for (section = section_list; section; section = section->next) {
+diff --git a/qapi/machine.json b/qapi/machine.json
+index 16e771affc..a9f33d0f27 100644
+--- a/qapi/machine.json
++++ b/qapi/machine.json
+@@ -1207,7 +1207,7 @@
+ #
+ # @memdev: memory backend linked with device
+ #
+-# @node: the numa node
++# @node: the numa node (Since: 7.0)
+ #
+ # Since: 6.2
+ ##
+@@ -1288,7 +1288,7 @@
+ #
+ # @memdev: memory backend linked with device
+ #
+-# @node: the numa node
++# @node: the numa node (Since: 7.0)
+ #
+ # Since: 6.2
+ ##
+diff --git a/qapi/misc-target.json b/qapi/misc-target.json
+index 1022aa0184..4bc45d2474 100644
+--- a/qapi/misc-target.json
++++ b/qapi/misc-target.json
+@@ -344,9 +344,9 @@
+ #
+ # @node: the numa node
+ #
+-# @size: the size of epc section
++# @size: the size of EPC section
+ #
+-# Since: 6.2
++# Since: 7.0
+ ##
+ { 'struct': 'SGXEPCSection',
+   'data': { 'node': 'int',
+@@ -365,7 +365,13 @@
+ #
+ # @flc: true if FLC is supported
+ #
+-# @sections: The EPC sections info for guest
++# @section-size: The EPC section size for guest
++#                Redundant with @sections.  Just for backward compatibility.
++#
++# @sections: The EPC sections info for guest (Since: 7.0)
++#
++# Features:
++# @deprecated: Member @section-size is deprecated.  Use @sections instead.
+ #
+ # Since: 6.2
+ ##
+@@ -374,6 +380,8 @@
+             'sgx1': 'bool',
+             'sgx2': 'bool',
+             'flc': 'bool',
++            'section-size': { 'type': 'uint64',
++                    'features': [ 'deprecated' ] },
+             'sections': ['SGXEPCSection']},
+    'if': 'TARGET_I386' }
+ 
+@@ -390,7 +398,9 @@
+ #
+ # -> { "execute": "query-sgx" }
+ # <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true,
+-#                  "flc": true, "section-size" : 0 } }
++#                  "flc": true,  "section-size" : 96468992,
++#                  "sections": [{"node": 0, "size": 67108864},
++#                  {"node": 1, "size": 29360128}]} }
+ #
+ ##
+ { 'command': 'query-sgx', 'returns': 'SGXInfo', 'if': 'TARGET_I386' }
+@@ -408,7 +418,9 @@
+ #
+ # -> { "execute": "query-sgx-capabilities" }
+ # <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true,
+-#                  "flc": true, "section-size" : 0 } }
++#                  "flc": true, "section-size" : 96468992,
++#                  "section" : [{"node": 0, "size": 67108864},
++#                  {"node": 1, "size": 29360128}]} }
+ #
+ ##
+ { 'command': 'query-sgx-capabilities', 'returns': 'SGXInfo', 'if': 'TARGET_I386' }
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qemu-img-make-is_allocated_sectors-more-efficient.patch b/SOURCES/kvm-qemu-img-make-is_allocated_sectors-more-efficient.patch
new file mode 100644
index 0000000..2d67070
--- /dev/null
+++ b/SOURCES/kvm-qemu-img-make-is_allocated_sectors-more-efficient.patch
@@ -0,0 +1,108 @@
+From a221f5a8ed02690687e6709c49ae0e1e01c5f466 Mon Sep 17 00:00:00 2001
+From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Date: Fri, 17 Dec 2021 17:46:54 +0100
+Subject: [PATCH 09/12] qemu-img: make is_allocated_sectors() more efficient
+
+RH-Author: Kevin Wolf <kwolf@redhat.com>
+RH-MergeRequest: 70: qemu-img convert: Fix sparseness of output image
+RH-Commit: [2/2] cc05aa4ac506b57ff9b430c007618cdf1485a03f (kmwolf/centos-qemu-kvm)
+RH-Bugzilla: 1882917
+RH-Acked-by: Eric Blake <eblake@redhat.com>
+RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+Consider the case when the whole buffer is zero and end is unaligned.
+
+If i <= tail, we return 1 and do one unaligned WRITE, RMW happens.
+
+If i > tail, we do on aligned WRITE_ZERO (or skip if target is zeroed)
+and again one unaligned WRITE, RMW happens.
+
+Let's do better: don't fragment the whole-zero buffer and report it as
+ZERO: in case of zeroed target we just do nothing and avoid RMW. If
+target is not zeroes, one unaligned WRITE_ZERO should not be much worse
+than one unaligned WRITE.
+
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Message-Id: <20211217164654.1184218-3-vsementsov@virtuozzo.com>
+Tested-by: Peter Lieven <pl@kamp.de>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 96054c76ff2db74165385a69f234c57a6bbc941e)
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ qemu-img.c                 | 23 +++++++++++++++++++----
+ tests/qemu-iotests/122.out |  8 ++------
+ 2 files changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/qemu-img.c b/qemu-img.c
+index f036a1d428..d7ddfcc528 100644
+--- a/qemu-img.c
++++ b/qemu-img.c
+@@ -1171,19 +1171,34 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum,
+         }
+     }
+ 
++    if (i == n) {
++        /*
++         * The whole buf is the same.
++         * No reason to split it into chunks, so return now.
++         */
++        *pnum = i;
++        return !is_zero;
++    }
++
+     tail = (sector_num + i) & (alignment - 1);
+     if (tail) {
+         if (is_zero && i <= tail) {
+-            /* treat unallocated areas which only consist
+-             * of a small tail as allocated. */
++            /*
++             * For sure next sector after i is data, and it will rewrite this
++             * tail anyway due to RMW. So, let's just write data now.
++             */
+             is_zero = false;
+         }
+         if (!is_zero) {
+-            /* align up end offset of allocated areas. */
++            /* If possible, align up end offset of allocated areas. */
+             i += alignment - tail;
+             i = MIN(i, n);
+         } else {
+-            /* align down end offset of zero areas. */
++            /*
++             * For sure next sector after i is data, and it will rewrite this
++             * tail anyway due to RMW. Better is avoid RMW and write zeroes up
++             * to aligned bound.
++             */
+             i -= tail;
+         }
+     }
+diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
+index 69b8e8b803..e18766e167 100644
+--- a/tests/qemu-iotests/122.out
++++ b/tests/qemu-iotests/122.out
+@@ -201,9 +201,7 @@ convert -S 4k
+ { "start": 8192, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+ { "start": 12288, "length": 4096, "depth": 0, "present": false, "zero": true, "data": false},
+ { "start": 16384, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+-{ "start": 20480, "length": 46080, "depth": 0, "present": false, "zero": true, "data": false},
+-{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+-{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
++{ "start": 20480, "length": 67088384, "depth": 0, "present": false, "zero": true, "data": false}]
+ 
+ convert -c -S 4k
+ [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
+@@ -215,9 +213,7 @@ convert -c -S 4k
+ 
+ convert -S 8k
+ [{ "start": 0, "length": 24576, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+-{ "start": 24576, "length": 41984, "depth": 0, "present": false, "zero": true, "data": false},
+-{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
+-{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
++{ "start": 24576, "length": 67084288, "depth": 0, "present": false, "zero": true, "data": false}]
+ 
+ convert -c -S 8k
+ [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qemu-storage-daemon-Add-vhost-user-blk-help.patch b/SOURCES/kvm-qemu-storage-daemon-Add-vhost-user-blk-help.patch
new file mode 100644
index 0000000..bc36f5c
--- /dev/null
+++ b/SOURCES/kvm-qemu-storage-daemon-Add-vhost-user-blk-help.patch
@@ -0,0 +1,72 @@
+From 0f4592f79f8c24f84db18a8c39c6056b2a0be524 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
+Date: Fri, 7 Jan 2022 11:54:19 +0100
+Subject: [PATCH 1/5] qemu-storage-daemon: Add vhost-user-blk help
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Kevin Wolf <kwolf@redhat.com>
+RH-MergeRequest: 63: qemu-storage-daemon: Add vhost-user-blk help
+RH-Commit: [1/2] 6b08fec5d6ceea9f8f3810321099310069e08b53 (kmwolf/centos-qemu-kvm)
+RH-Bugzilla: 1962088
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+Add missing vhost-user-blk help:
+
+  $ qemu-storage-daemon -h
+  ...
+    --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,
+             addr.type=unix,addr.path=<socket-path>[,writable=on|off]
+             [,logical-block-size=<block-size>][,num-queues=<num-queues>]
+                           export the specified block node as a
+                           vhosts-user-blk device over UNIX domain socket
+    --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,
+             fd,addr.str=<fd>[,writable=on|off]
+             [,logical-block-size=<block-size>][,num-queues=<num-queues>]
+                           export the specified block node as a
+                           vhosts-user-blk device over file descriptor
+  ...
+
+Fixes: 90fc91d50b7 ("convert vhost-user-blk server to block export API")
+Reported-by: Qing Wang <qinwang@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
+Message-Id: <20220107105420.395011-3-f4bug@amsat.org>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit c8cbc9524269d9583749aaaea8aa244add7e1900)
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ storage-daemon/qemu-storage-daemon.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
+index 52cf17e8ac..9d76d1114d 100644
+--- a/storage-daemon/qemu-storage-daemon.c
++++ b/storage-daemon/qemu-storage-daemon.c
+@@ -104,6 +104,19 @@ static void help(void)
+ "                         export the specified block node over FUSE\n"
+ "\n"
+ #endif /* CONFIG_FUSE */
++#ifdef CONFIG_VHOST_USER_BLK_SERVER
++"  --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,\n"
++"           addr.type=unix,addr.path=<socket-path>[,writable=on|off]\n"
++"           [,logical-block-size=<block-size>][,num-queues=<num-queues>]\n"
++"                         export the specified block node as a\n"
++"                         vhost-user-blk device over UNIX domain socket\n"
++"  --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,\n"
++"           fd,addr.str=<fd>[,writable=on|off]\n"
++"           [,logical-block-size=<block-size>][,num-queues=<num-queues>]\n"
++"                         export the specified block node as a\n"
++"                         vhost-user-blk device over file descriptor\n"
++"\n"
++#endif /* CONFIG_VHOST_USER_BLK_SERVER */
+ "  --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
+ "                         configure a QMP monitor\n"
+ "\n"
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qemu-storage-daemon-Fix-typo-in-vhost-user-blk-help.patch b/SOURCES/kvm-qemu-storage-daemon-Fix-typo-in-vhost-user-blk-help.patch
new file mode 100644
index 0000000..798a27e
--- /dev/null
+++ b/SOURCES/kvm-qemu-storage-daemon-Fix-typo-in-vhost-user-blk-help.patch
@@ -0,0 +1,41 @@
+From 20edf203c8cb314e27409918399aa7cbdc6fdb02 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Tue, 25 Jan 2022 16:15:14 +0100
+Subject: [PATCH 2/5] qemu-storage-daemon: Fix typo in vhost-user-blk help
+
+RH-Author: Kevin Wolf <kwolf@redhat.com>
+RH-MergeRequest: 63: qemu-storage-daemon: Add vhost-user-blk help
+RH-Commit: [2/2] b7afb670c398799b6e49b926e296771453a55fba (kmwolf/centos-qemu-kvm)
+RH-Bugzilla: 1962088
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+
+The syntax of the fd passing case misses the "addr.type=" key. Add it.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Message-Id: <20220125151514.49035-1-kwolf@redhat.com>
+Reviewed-by: Hanna Reitz <hreitz@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit e66e665f15736f5ee1fbd8087926cb0f1e52f61a)
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ storage-daemon/qemu-storage-daemon.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
+index 9d76d1114d..ec9aa79b55 100644
+--- a/storage-daemon/qemu-storage-daemon.c
++++ b/storage-daemon/qemu-storage-daemon.c
+@@ -111,7 +111,7 @@ static void help(void)
+ "                         export the specified block node as a\n"
+ "                         vhost-user-blk device over UNIX domain socket\n"
+ "  --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,\n"
+-"           fd,addr.str=<fd>[,writable=on|off]\n"
++"           addr.type=fd,addr.str=<fd>[,writable=on|off]\n"
+ "           [,logical-block-size=<block-size>][,num-queues=<num-queues>]\n"
+ "                         export the specified block node as a\n"
+ "                         vhost-user-blk device over file descriptor\n"
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-rhel-machine-types-x86-set-prefer_sockets.patch b/SOURCES/kvm-rhel-machine-types-x86-set-prefer_sockets.patch
new file mode 100644
index 0000000..83c912d
--- /dev/null
+++ b/SOURCES/kvm-rhel-machine-types-x86-set-prefer_sockets.patch
@@ -0,0 +1,52 @@
+From ecadfaec992fda7f485522c9ee6e7c9b05614a22 Mon Sep 17 00:00:00 2001
+From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
+Date: Tue, 7 Dec 2021 18:39:47 +0000
+Subject: [PATCH 2/2] rhel machine types/x86: set prefer_sockets
+
+RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-MergeRequest: 59: rhel machine types/x86: set prefer_sockets
+RH-Commit: [1/1] 9bcd9e2c95154e39ef30a8a342ad6c713fa4f1fb (dagrh/c-9-s-qemu-kvm)
+RH-Bugzilla: 2028623
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: quintela1 <quintela@redhat.com>
+RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
+
+When I fixed up the machine types for 8.5 I missed the
+  prefer_sockets = true
+
+add them in; it looks like Power, ARM already have them, and I see them
+in thuth's s390 patch.
+
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+---
+ hw/i386/pc_piix.c | 1 +
+ hw/i386/pc_q35.c  | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
+index 183b5d5464..fccb7f5fc9 100644
+--- a/hw/i386/pc_piix.c
++++ b/hw/i386/pc_piix.c
+@@ -973,6 +973,7 @@ static void pc_machine_rhel7_options(MachineClass *m)
+     compat_props_add(m->compat_props, pc_rhel_compat, pc_rhel_compat_len);
+     m->alias = "pc";
+     m->is_default = 1;
++    m->smp_props.prefer_sockets = true;
+ }
+ 
+ static void pc_init_rhel760(MachineState *machine)
+diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
+index 0e7e885e78..3b748ddd7b 100644
+--- a/hw/i386/pc_q35.c
++++ b/hw/i386/pc_q35.c
+@@ -662,6 +662,7 @@ static void pc_q35_machine_rhel850_options(MachineClass *m)
+                      hw_compat_rhel_8_5_len);
+     compat_props_add(m->compat_props, pc_rhel_8_5_compat,
+                      pc_rhel_8_5_compat_len);
++    m->smp_props.prefer_sockets = true;
+ }
+ 
+ DEFINE_PC_MACHINE(q35_rhel850, "pc-q35-rhel8.5.0", pc_q35_init_rhel850,
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-softmmu-fix-device-deletion-events-with-device-JSON-.patch b/SOURCES/kvm-softmmu-fix-device-deletion-events-with-device-JSON-.patch
new file mode 100644
index 0000000..4ddfbe9
--- /dev/null
+++ b/SOURCES/kvm-softmmu-fix-device-deletion-events-with-device-JSON-.patch
@@ -0,0 +1,130 @@
+From 005339f7deaee639c38d30e5bf2235c292ce3937 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Wed, 5 Jan 2022 12:38:47 +0000
+Subject: [PATCH 3/3] softmmu: fix device deletion events with -device JSON
+ syntax
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Kevin Wolf <kwolf@redhat.com>
+RH-MergeRequest: 62: Fix hot unplug of devices created with -device JSON syntax
+RH-Commit: [1/1] 980e505ba215b5f9324c107481c5bb257ae03f42 (kmwolf/centos-qemu-kvm)
+RH-Bugzilla: 2036669
+RH-Acked-by: Daniel P. Berrangé <berrange@redhat.com>
+RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
+RH-Acked-by: Jano Tomko <None>
+
+The -device JSON syntax impl leaks a reference on the created
+DeviceState instance. As a result when you hot-unplug the
+device, the device_finalize method won't be called and thus
+it will fail to emit the required DEVICE_DELETED event.
+
+A 'json-cli' feature was previously added against the
+'device_add' QMP command QAPI schema to indicated to mgmt
+apps that -device supported JSON syntax. Given the hotplug
+bug that feature flag is not usable for its purpose, so
+we add a new 'json-cli-hotplug' feature to indicate the
+-device supports JSON without breaking hotplug.
+
+Fixes: 5dacda5167560b3af8eadbce5814f60ba44b467e
+Resolves: https://gitlab.com/qemu-project/qemu/-/issues/802
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+Message-Id: <20220105123847.4047954-2-berrange@redhat.com>
+Reviewed-by: Laurent Vivier <lvivier@redhat.com>
+Tested-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Thomas Huth <thuth@redhat.com>
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+(cherry picked from commit 64b4529a432507ee84a924be69a03432639e87ba)
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ qapi/qdev.json                 |  5 ++++-
+ softmmu/vl.c                   |  4 +++-
+ tests/qtest/device-plug-test.c | 19 +++++++++++++++++++
+ 3 files changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/qapi/qdev.json b/qapi/qdev.json
+index 69656b14df..26cd10106b 100644
+--- a/qapi/qdev.json
++++ b/qapi/qdev.json
+@@ -44,6 +44,9 @@
+ # @json-cli: If present, the "-device" command line option supports JSON
+ #            syntax with a structure identical to the arguments of this
+ #            command.
++# @json-cli-hotplug: If present, the "-device" command line option supports JSON
++#                    syntax without the reference counting leak that broke
++#                    hot-unplug
+ #
+ # Notes:
+ #
+@@ -74,7 +77,7 @@
+ { 'command': 'device_add',
+   'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
+   'gen': false, # so we can get the additional arguments
+-  'features': ['json-cli'] }
++  'features': ['json-cli', 'json-cli-hotplug'] }
+ 
+ ##
+ # @device_del:
+diff --git a/softmmu/vl.c b/softmmu/vl.c
+index d46b8fb4ab..b3829e2edd 100644
+--- a/softmmu/vl.c
++++ b/softmmu/vl.c
+@@ -2690,6 +2690,7 @@ static void qemu_create_cli_devices(void)
+     qemu_opts_foreach(qemu_find_opts("device"),
+                       device_init_func, NULL, &error_fatal);
+     QTAILQ_FOREACH(opt, &device_opts, next) {
++        DeviceState *dev;
+         loc_push_restore(&opt->loc);
+         /*
+          * TODO Eventually we should call qmp_device_add() here to make sure it
+@@ -2698,7 +2699,8 @@ static void qemu_create_cli_devices(void)
+          * from the start, so call qdev_device_add_from_qdict() directly for
+          * now.
+          */
+-        qdev_device_add_from_qdict(opt->opts, true, &error_fatal);
++        dev = qdev_device_add_from_qdict(opt->opts, true, &error_fatal);
++        object_unref(OBJECT(dev));
+         loc_pop(&opt->loc);
+     }
+     rom_reset_order_override();
+diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c
+index 559d47727a..ad79bd4c14 100644
+--- a/tests/qtest/device-plug-test.c
++++ b/tests/qtest/device-plug-test.c
+@@ -77,6 +77,23 @@ static void test_pci_unplug_request(void)
+     qtest_quit(qtest);
+ }
+ 
++static void test_pci_unplug_json_request(void)
++{
++    QTestState *qtest = qtest_initf(
++        "-device '{\"driver\": \"virtio-mouse-pci\", \"id\": \"dev0\"}'");
++
++    /*
++     * Request device removal. As the guest is not running, the request won't
++     * be processed. However during system reset, the removal will be
++     * handled, removing the device.
++     */
++    device_del(qtest, "dev0");
++    system_reset(qtest);
++    wait_device_deleted_event(qtest, "dev0");
++
++    qtest_quit(qtest);
++}
++
+ static void test_ccw_unplug(void)
+ {
+     QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0");
+@@ -145,6 +162,8 @@ int main(int argc, char **argv)
+      */
+     qtest_add_func("/device-plug/pci-unplug-request",
+                    test_pci_unplug_request);
++    qtest_add_func("/device-plug/pci-unplug-json-request",
++                   test_pci_unplug_json_request);
+ 
+     if (!strcmp(arch, "s390x")) {
+         qtest_add_func("/device-plug/ccw-unplug",
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-virtiofsd-Drop-membership-of-all-supplementary-group.patch b/SOURCES/kvm-virtiofsd-Drop-membership-of-all-supplementary-group.patch
new file mode 100644
index 0000000..539b8fe
--- /dev/null
+++ b/SOURCES/kvm-virtiofsd-Drop-membership-of-all-supplementary-group.patch
@@ -0,0 +1,110 @@
+From 846192d22a1ddfa87682bb0b67febef5c30c9743 Mon Sep 17 00:00:00 2001
+From: Vivek Goyal <vgoyal@redhat.com>
+Date: Tue, 25 Jan 2022 13:51:14 -0500
+Subject: [PATCH 3/5] virtiofsd: Drop membership of all supplementary groups
+ (CVE-2022-0358)
+
+RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-MergeRequest: 66: c9s:  virtiofsd security fix - drop secondary groups
+RH-Commit: [1/1] cdf3b0405ea3369933e76761890f16b040641036 (redhat/centos-stream/src/qemu-kvm)
+RH-Bugzilla: 2046201
+RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
+RH-Acked-by: Sergio Lopez <None>
+RH-Acked-by: Vivek Goyal <None>
+
+At the start, drop membership of all supplementary groups. This is
+not required.
+
+If we have membership of "root" supplementary group and when we switch
+uid/gid using setresuid/setsgid, we still retain membership of existing
+supplemntary groups. And that can allow some operations which are not
+normally allowed.
+
+For example, if root in guest creates a dir as follows.
+
+$ mkdir -m 03777 test_dir
+
+This sets SGID on dir as well as allows unprivileged users to write into
+this dir.
+
+And now as unprivileged user open file as follows.
+
+$ su test
+$ fd = open("test_dir/priviledge_id", O_RDWR|O_CREAT|O_EXCL, 02755);
+
+This will create SGID set executable in test_dir/.
+
+And that's a problem because now an unpriviliged user can execute it,
+get egid=0 and get access to resources owned by "root" group. This is
+privilege escalation.
+
+Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2044863
+Fixes: CVE-2022-0358
+Reported-by: JIETAO XIAO <shawtao1125@gmail.com>
+Suggested-by: Miklos Szeredi <mszeredi@redhat.com>
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
+Message-Id: <YfBGoriS38eBQrAb@redhat.com>
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+  dgilbert: Fixed missing {}'s style nit
+(cherry picked from commit 449e8171f96a6a944d1f3b7d3627ae059eae21ca)
+---
+ tools/virtiofsd/passthrough_ll.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
+index 64b5b4fbb1..b3d0674f6d 100644
+--- a/tools/virtiofsd/passthrough_ll.c
++++ b/tools/virtiofsd/passthrough_ll.c
+@@ -54,6 +54,7 @@
+ #include <sys/wait.h>
+ #include <sys/xattr.h>
+ #include <syslog.h>
++#include <grp.h>
+ 
+ #include "qemu/cutils.h"
+ #include "passthrough_helpers.h"
+@@ -1161,6 +1162,30 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
+ #define OURSYS_setresuid SYS_setresuid
+ #endif
+ 
++static void drop_supplementary_groups(void)
++{
++    int ret;
++
++    ret = getgroups(0, NULL);
++    if (ret == -1) {
++        fuse_log(FUSE_LOG_ERR, "getgroups() failed with error=%d:%s\n",
++                 errno, strerror(errno));
++        exit(1);
++    }
++
++    if (!ret) {
++        return;
++    }
++
++    /* Drop all supplementary groups. We should not need it */
++    ret = setgroups(0, NULL);
++    if (ret == -1) {
++        fuse_log(FUSE_LOG_ERR, "setgroups() failed with error=%d:%s\n",
++                 errno, strerror(errno));
++        exit(1);
++    }
++}
++
+ /*
+  * Change to uid/gid of caller so that file is created with
+  * ownership of caller.
+@@ -3926,6 +3951,8 @@ int main(int argc, char *argv[])
+ 
+     qemu_init_exec_dir(argv[0]);
+ 
++    drop_supplementary_groups();
++
+     pthread_mutex_init(&lo.mutex, NULL);
+     lo.inodes = g_hash_table_new(lo_key_hash, lo_key_equal);
+     lo.root.fd = -1;
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-x86-Add-q35-RHEL-8.6.0-machine-type.patch b/SOURCES/kvm-x86-Add-q35-RHEL-8.6.0-machine-type.patch
new file mode 100644
index 0000000..eb3273c
--- /dev/null
+++ b/SOURCES/kvm-x86-Add-q35-RHEL-8.6.0-machine-type.patch
@@ -0,0 +1,65 @@
+From 1b8eeb1323fa21c7b26d0396fae5ae4a8cdb1ace Mon Sep 17 00:00:00 2001
+From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
+Date: Tue, 11 Jan 2022 18:29:31 +0000
+Subject: [PATCH 1/3] x86: Add q35 RHEL 8.6.0 machine type
+
+RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-MergeRequest: 61: x86: Add rhel 8.6.0 & 9.0.0 machine types
+RH-Commit: [1/2] 189335cf0e4ad117e3e401f23aa07cddbbac50df (dagrh/c-9-s-qemu-kvm)
+RH-Bugzilla: 1945666
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
+
+Add the new 8.6.0 machine type;  note that while the -AV
+notation has gone in the product naming, just keep the smbios
+definitions the same for consistency.
+
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+---
+ hw/i386/pc_q35.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
+index 3b748ddd7b..0c25305f15 100644
+--- a/hw/i386/pc_q35.c
++++ b/hw/i386/pc_q35.c
+@@ -646,6 +646,24 @@ static void pc_q35_machine_rhel_options(MachineClass *m)
+     compat_props_add(m->compat_props, pc_rhel_compat, pc_rhel_compat_len);
+ }
+ 
++static void pc_q35_init_rhel860(MachineState *machine)
++{
++    pc_q35_init(machine);
++}
++
++static void pc_q35_machine_rhel860_options(MachineClass *m)
++{
++    PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
++    pc_q35_machine_rhel_options(m);
++    m->desc = "RHEL-8.6.0 PC (Q35 + ICH9, 2009)";
++    pcmc->smbios_stream_product = "RHEL-AV";
++    pcmc->smbios_stream_version = "8.6.0";
++}
++
++DEFINE_PC_MACHINE(q35_rhel860, "pc-q35-rhel8.6.0", pc_q35_init_rhel860,
++                  pc_q35_machine_rhel860_options);
++
++
+ static void pc_q35_init_rhel850(MachineState *machine)
+ {
+     pc_q35_init(machine);
+@@ -654,8 +672,9 @@ static void pc_q35_init_rhel850(MachineState *machine)
+ static void pc_q35_machine_rhel850_options(MachineClass *m)
+ {
+     PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+-    pc_q35_machine_rhel_options(m);
++    pc_q35_machine_rhel860_options(m);
+     m->desc = "RHEL-8.5.0 PC (Q35 + ICH9, 2009)";
++    m->alias = NULL;
+     pcmc->smbios_stream_product = "RHEL-AV";
+     pcmc->smbios_stream_version = "8.5.0";
+     compat_props_add(m->compat_props, hw_compat_rhel_8_5,
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-x86-Add-q35-RHEL-9.0.0-machine-type.patch b/SOURCES/kvm-x86-Add-q35-RHEL-9.0.0-machine-type.patch
new file mode 100644
index 0000000..4367495
--- /dev/null
+++ b/SOURCES/kvm-x86-Add-q35-RHEL-9.0.0-machine-type.patch
@@ -0,0 +1,75 @@
+From 3d5024fb9c904a649d07f0def3a90b3d36611215 Mon Sep 17 00:00:00 2001
+From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
+Date: Wed, 12 Jan 2022 13:21:57 +0000
+Subject: [PATCH 2/3] x86: Add q35 RHEL 9.0.0 machine type
+
+RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
+RH-MergeRequest: 61: x86: Add rhel 8.6.0 & 9.0.0 machine types
+RH-Commit: [2/2] 743378502459b978efd632271f97ddb824422203 (dagrh/c-9-s-qemu-kvm)
+RH-Bugzilla: 1945666
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
+
+Add a rhel-9.0.0 q35 machine type; it's currently identical to 8.6.0;
+but having a separate machine type will make life easier in the future
+when the 8.x types go away.
+
+Note: The smbios stream product name has now changed to 'RHEL'
+
+bz: https://bugzilla.redhat.com/show_bug.cgi?id=1945666
+Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
+---
+ hw/i386/pc_q35.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
+index 0c25305f15..bf9ad32f0e 100644
+--- a/hw/i386/pc_q35.c
++++ b/hw/i386/pc_q35.c
+@@ -646,6 +646,23 @@ static void pc_q35_machine_rhel_options(MachineClass *m)
+     compat_props_add(m->compat_props, pc_rhel_compat, pc_rhel_compat_len);
+ }
+ 
++static void pc_q35_init_rhel900(MachineState *machine)
++{
++    pc_q35_init(machine);
++}
++
++static void pc_q35_machine_rhel900_options(MachineClass *m)
++{
++    PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
++    pc_q35_machine_rhel_options(m);
++    m->desc = "RHEL-9.0.0 PC (Q35 + ICH9, 2009)";
++    pcmc->smbios_stream_product = "RHEL";
++    pcmc->smbios_stream_version = "9.0.0";
++}
++
++DEFINE_PC_MACHINE(q35_rhel900, "pc-q35-rhel9.0.0", pc_q35_init_rhel900,
++                  pc_q35_machine_rhel900_options);
++
+ static void pc_q35_init_rhel860(MachineState *machine)
+ {
+     pc_q35_init(machine);
+@@ -654,8 +671,9 @@ static void pc_q35_init_rhel860(MachineState *machine)
+ static void pc_q35_machine_rhel860_options(MachineClass *m)
+ {
+     PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+-    pc_q35_machine_rhel_options(m);
++    pc_q35_machine_rhel900_options(m);
+     m->desc = "RHEL-8.6.0 PC (Q35 + ICH9, 2009)";
++    m->alias = NULL;
+     pcmc->smbios_stream_product = "RHEL-AV";
+     pcmc->smbios_stream_version = "8.6.0";
+ }
+@@ -674,7 +692,6 @@ static void pc_q35_machine_rhel850_options(MachineClass *m)
+     PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+     pc_q35_machine_rhel860_options(m);
+     m->desc = "RHEL-8.5.0 PC (Q35 + ICH9, 2009)";
+-    m->alias = NULL;
+     pcmc->smbios_stream_product = "RHEL-AV";
+     pcmc->smbios_stream_version = "8.5.0";
+     compat_props_add(m->compat_props, hw_compat_rhel_8_5,
+-- 
+2.27.0
+
diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec
index d35d448..c403f49 100644
--- a/SPECS/qemu-kvm.spec
+++ b/SPECS/qemu-kvm.spec
@@ -110,9 +110,23 @@
 %global requires_all_modules                                     \
 %if %{have_opengl}                                               \
 Requires: %{name}-ui-opengl = %{epoch}:%{version}-%{release}     \
+Requires: %{name}-ui-egl-headless = %{epoch}:%{version}-%{release}     \
 %endif                                                           \
+Requires: %{name}-device-display-virtio-gpu = %{epoch}:%{version}-%{release}   \
+Requires: %{name}-device-display-virtio-gpu-gl = %{epoch}:%{version}-%{release}   \
+%ifarch s390x                                                    \
+Requires: %{name}-device-display-virtio-gpu-ccw = %{epoch}:%{version}-%{release}   \
+%else                                                            \
+Requires: %{name}-device-display-virtio-gpu-pci = %{epoch}:%{version}-%{release}   \
+Requires: %{name}-device-display-virtio-gpu-pci-gl = %{epoch}:%{version}-%{release}   \
+%endif                                                           \
+%ifarch x86_64 %{power64}                                        \
+Requires: %{name}-device-display-virtio-vga = %{epoch}:%{version}-%{release}   \
+Requires: %{name}-device-display-virtio-vga-gl = %{epoch}:%{version}-%{release}   \
+%endif                                                           \
+Requires: %{name}-device-usb-host = %{epoch}:%{version}-%{release}   \
 %if %{have_usbredir}                                             \
-Requires: %{name}-hw-usbredir = %{epoch}:%{version}-%{release}   \
+Requires: %{name}-device-usb-redirect = %{epoch}:%{version}-%{release}   \
 %endif                                                           \
 Requires: %{name}-block-rbd = %{epoch}:%{version}-%{release}     \
 Requires: %{name}-audio-pa = %{epoch}:%{version}-%{release}
@@ -130,7 +144,7 @@ Obsoletes: %{name}-block-iscsi <= %{version}                    \
 Summary: QEMU is a machine emulator and virtualizer
 Name: qemu-kvm
 Version: 6.2.0
-Release: 3%{?rcrel}%{?dist}%{?cc_suffix}
+Release: 9%{?rcrel}%{?dist}%{?cc_suffix}
 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
 # Epoch 15 used for RHEL 8
 # Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5)
@@ -193,6 +207,68 @@ Patch31: kvm-hw-arm-virt-Expose-the-RAS-option.patch
 Patch32: kvm-hw-arm-virt-Add-9.0-machine-type-and-remove-8.5-one.patch
 # For bz#2031044 - Add rhel-9.0.0 machine types for RHEL 9.0 [aarch64]
 Patch33: kvm-hw-arm-virt-Check-no_tcg_its-and-minor-style-changes.patch
+# For bz#2024544 - Fio workers hangs when running fio with 32 jobs iodepth 32 and QEMU's userspace NVMe driver
+Patch34: kvm-block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch
+# For bz#2028623 - [9.0] machine types: 6.2: Fix prefer_sockets
+Patch35: kvm-rhel-machine-types-x86-set-prefer_sockets.patch
+# For bz#1945666 - 9.0: x86 machine types
+Patch36: kvm-x86-Add-q35-RHEL-8.6.0-machine-type.patch
+# For bz#1945666 - 9.0: x86 machine types
+Patch37: kvm-x86-Add-q35-RHEL-9.0.0-machine-type.patch
+# For bz#2036669 - DEVICE_DELETED event is not delivered for device frontend if -device is configured via JSON
+Patch38: kvm-softmmu-fix-device-deletion-events-with-device-JSON-.patch
+# For bz#1962088 - [QSD] wrong help message for the fuse
+Patch39: kvm-qemu-storage-daemon-Add-vhost-user-blk-help.patch
+# For bz#1962088 - [QSD] wrong help message for the fuse
+Patch40: kvm-qemu-storage-daemon-Fix-typo-in-vhost-user-blk-help.patch
+# For bz#2046201 - CVE-2022-0358 qemu-kvm: QEMU: virtiofsd: potential privilege escalation via CVE-2018-13405 [rhel-9.0]
+Patch41: kvm-virtiofsd-Drop-membership-of-all-supplementary-group.patch
+# For bz#2034791 - Booting from Local Snapshot Core Dumped Whose Backing File Is Based on RBD
+Patch42: kvm-block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch
+# For bz#2034791 - Booting from Local Snapshot Core Dumped Whose Backing File Is Based on RBD
+Patch43: kvm-block-rbd-workaround-for-ceph-issue-53784.patch
+# For bz#2033708 - [Intel 9.0 Feat] qemu-kvm: SGX 1.5 (SGX1 + Flexible Launch Control) support
+Patch44: kvm-numa-Enable-numa-for-SGX-EPC-sections.patch
+# For bz#2033708 - [Intel 9.0 Feat] qemu-kvm: SGX 1.5 (SGX1 + Flexible Launch Control) support
+Patch45: kvm-numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch
+# For bz#2033708 - [Intel 9.0 Feat] qemu-kvm: SGX 1.5 (SGX1 + Flexible Launch Control) support
+Patch46: kvm-doc-Add-the-SGX-numa-description.patch
+# For bz#2033708 - [Intel 9.0 Feat] qemu-kvm: SGX 1.5 (SGX1 + Flexible Launch Control) support
+Patch47: kvm-Enable-SGX-RH-Only.patch
+# For bz#2033708 - [Intel 9.0 Feat] qemu-kvm: SGX 1.5 (SGX1 + Flexible Launch Control) support
+Patch48: kvm-qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch
+# For bz#2041461 - Inconsistent block status reply in qemu-nbd
+Patch49: kvm-block-io-Update-BSC-only-if-want_zero-is-true.patch
+# For bz#2041461 - Inconsistent block status reply in qemu-nbd
+Patch50: kvm-iotests-block-status-cache-New-test.patch
+# For bz#1882917 - the target image size is incorrect when converting a badly fragmented file
+Patch51: kvm-iotests-Test-qemu-img-convert-of-zeroed-data-cluster.patch
+# For bz#1882917 - the target image size is incorrect when converting a badly fragmented file
+Patch52: kvm-qemu-img-make-is_allocated_sectors-more-efficient.patch
+# For bz#2040123 - Qemu core dumped when do block-stream to a snapshot node on non-enough space storage
+Patch53: kvm-block-backend-prevent-dangling-BDS-pointers-across-a.patch
+# For bz#2040123 - Qemu core dumped when do block-stream to a snapshot node on non-enough space storage
+Patch54: kvm-iotests-stream-error-on-reset-New-test.patch
+# For bz#2042481 - [aarch64] Launch guest with "default-bus-bypass-iommu=off,iommu=smmuv3" and "iommu_platform=on", guest hangs after system_reset
+Patch55: kvm-hw-arm-smmuv3-Fix-device-reset.patch
+# For bz#2046659 - qemu crash after execute blockdev-reopen with  iothread
+Patch56: kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch
+# For bz#2046659 - qemu crash after execute blockdev-reopen with  iothread
+Patch57: kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch
+# For bz#2033626 - Qemu core dump when start guest with nbd node or do block jobs to nbd node
+Patch58: kvm-block-nbd-Delete-reconnect-delay-timer-when-done.patch
+# For bz#2033626 - Qemu core dump when start guest with nbd node or do block jobs to nbd node
+Patch59: kvm-block-nbd-Assert-there-are-no-timers-when-closed.patch
+# For bz#2033626 - Qemu core dump when start guest with nbd node or do block jobs to nbd node
+Patch60: kvm-iotests.py-Add-QemuStorageDaemon-class.patch
+# For bz#2033626 - Qemu core dump when start guest with nbd node or do block jobs to nbd node
+Patch61: kvm-iotests-281-Test-lingering-timers.patch
+# For bz#2033626 - Qemu core dump when start guest with nbd node or do block jobs to nbd node
+Patch62: kvm-block-nbd-Move-s-ioc-on-AioContext-change.patch
+# For bz#2033626 - Qemu core dump when start guest with nbd node or do block jobs to nbd node
+Patch63: kvm-iotests-281-Let-NBD-connection-yield-in-iothread.patch
+
+# Source-git patches
 
 %if %{have_clang}
 BuildRequires: clang
@@ -303,7 +379,15 @@ Requires: libfdt >= %{libfdt_version}
 emulation for the KVM hypervisor. %{name} acts as a virtual
 machine monitor together with the KVM kernel modules, and emulates the
 hardware for a full system such as a PC and its associated peripherals.
-
+This is a minimalistic installation of %{name}. Functionality provided by
+this package is not ensured and it can change in a future version as some
+functionality can be split out to separate package.
+Before updating this package, it is recommended to check the package
+changelog for information on functionality which might have been moved to
+a separate package to prevent issues due to the moved functionality.
+If apps opt-in to minimalist packaging by depending on %{name}-core, they
+explicitly accept that features may disappear from %{name}-core in future
+updates.
 
 %package common
 Summary: QEMU common files needed by all QEMU targets
@@ -439,15 +523,76 @@ Requires: mesa-libEGL
 Requires: mesa-dri-drivers
 %description ui-opengl
 This package provides opengl support.
+
+%package  ui-egl-headless
+Summary: QEMU EGL headless driver
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+Requires: %{name}-ui-opengl%{?_isa} = %{epoch}:%{version}-%{release}
+%description ui-egl-headless
+This package provides the additional egl-headless UI for QEMU.
+%endif
+
+
+%package device-display-virtio-gpu
+Summary: QEMU virtio-gpu display device
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+%description device-display-virtio-gpu
+This package provides the virtio-gpu display device for QEMU.
+
+%package device-display-virtio-gpu-gl
+Summary: QEMU virtio-gpu-gl display device
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+%description device-display-virtio-gpu-gl
+This package provides the virtio-gpu-gl display device for QEMU.
+
+%ifarch s390x
+%package device-display-virtio-gpu-ccw
+Summary: QEMU virtio-gpu-ccw display device
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+%description device-display-virtio-gpu-ccw
+This package provides the virtio-gpu-ccw display device for QEMU.
+%else
+%package device-display-virtio-gpu-pci
+Summary: QEMU virtio-gpu-pci display device
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+%description device-display-virtio-gpu-pci
+This package provides the virtio-gpu-pci display device for QEMU.
+
+%package device-display-virtio-gpu-pci-gl
+Summary: QEMU virtio-gpu-pci-gl display device
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+%description device-display-virtio-gpu-pci-gl
+This package provides the virtio-gpu-pci-gl display device for QEMU.
+%endif
+
+%ifarch x86_64 %{power64}
+%package device-display-virtio-vga
+Summary: QEMU virtio-vga display device
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+%description device-display-virtio-vga
+This package provides the virtio-vga display device for QEMU.
+
+%package device-display-virtio-vga-gl
+Summary: QEMU virtio-vga-gl display device
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+%description device-display-virtio-vga-gl
+This package provides the virtio-vga-gl display device for QEMU.
 %endif
 
+%package device-usb-host
+Summary: QEMU usb host device
+Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
+%description device-usb-host
+This package provides the USB pass through driver for QEMU.
+
 %if %{have_usbredir}
-%package  hw-usbredir
+%package  device-usb-redirect
 Summary: QEMU usbredir support
 Requires: %{name}-common%{?_isa} = %{epoch}:%{version}-%{release}
 Requires: usbredir >= 0.7.1
+Provides: %{name}-hw-usbredir
 
-%description hw-usbredir
+%description device-usb-redirect
 This package provides usbredir support.
 %endif
 
@@ -1105,9 +1250,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
     %{_datadir}/%{name}/s390-ccw.img
     %{_datadir}/%{name}/s390-netboot.img
 %endif
-%ifnarch aarch64 s390x
-    %{_libdir}/%{name}/hw-display-virtio-vga.so
-%endif
 %{_datadir}/icons/*
 %{_datadir}/%{name}/linuxboot_dma.bin
 %if %{have_modules_load}
@@ -1125,25 +1267,33 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
 %{_datadir}/%{name}/systemtap/script.d/qemu_kvm.stp
 %{_datadir}/%{name}/systemtap/conf.d/qemu_kvm.conf
 
+%ifarch x86_64
+    %{_libdir}/%{name}/accel-tcg-%{kvm_target}.so
+%endif
+
+%files device-display-virtio-gpu
 %{_libdir}/%{name}/hw-display-virtio-gpu.so
+%files device-display-virtio-gpu-gl
 %{_libdir}/%{name}/hw-display-virtio-gpu-gl.so
-%ifarch x86_64 %{power64}
-    %{_libdir}/%{name}/hw-display-virtio-vga-gl.so
-%endif
 %ifarch s390x
+%files device-display-virtio-gpu-ccw
     %{_libdir}/%{name}/hw-s390x-virtio-gpu-ccw.so
 %else
+%files device-display-virtio-gpu-pci
     %{_libdir}/%{name}/hw-display-virtio-gpu-pci.so
+%files device-display-virtio-gpu-pci-gl
     %{_libdir}/%{name}/hw-display-virtio-gpu-pci-gl.so
 %endif
-    %{_libdir}/%{name}/accel-qtest-%{kvm_target}.so
-%ifarch x86_64
-    %{_libdir}/%{name}/accel-tcg-%{kvm_target}.so
+%ifarch x86_64 %{power64}
+%files device-display-virtio-vga
+    %{_libdir}/%{name}/hw-display-virtio-vga.so
+%files device-display-virtio-vga-gl
+    %{_libdir}/%{name}/hw-display-virtio-vga-gl.so
 %endif
-%{_libdir}/%{name}/hw-usb-host.so
 
 %files tests
 %{testsdir}
+%{_libdir}/%{name}/accel-qtest-%{kvm_target}.so
 
 %files block-curl
 %{_libdir}/%{name}/block-curl.so
@@ -1158,12 +1308,16 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
 
 %if %{have_opengl}
 %files ui-opengl
-%{_libdir}/%{name}/ui-egl-headless.so
 %{_libdir}/%{name}/ui-opengl.so
+%files ui-egl-headless
+%{_libdir}/%{name}/ui-egl-headless.so
 %endif
 
+%files device-usb-host
+%{_libdir}/%{name}/hw-usb-host.so
+
 %if %{have_usbredir}
-%files hw-usbredir
+%files device-usb-redirect 
     %{_libdir}/%{name}/hw-usb-redirect.so
 %endif
 
@@ -1171,6 +1325,88 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
 %endif
 
 %changelog
+* Thu Feb 17 2022 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-9
+- kvm-block-Lock-AioContext-for-drain_end-in-blockdev-reop.patch [bz#2046659]
+- kvm-iotests-Test-blockdev-reopen-with-iothreads-and-thro.patch [bz#2046659]
+- kvm-block-nbd-Delete-reconnect-delay-timer-when-done.patch [bz#2033626]
+- kvm-block-nbd-Assert-there-are-no-timers-when-closed.patch [bz#2033626]
+- kvm-iotests.py-Add-QemuStorageDaemon-class.patch [bz#2033626]
+- kvm-iotests-281-Test-lingering-timers.patch [bz#2033626]
+- kvm-block-nbd-Move-s-ioc-on-AioContext-change.patch [bz#2033626]
+- kvm-iotests-281-Let-NBD-connection-yield-in-iothread.patch [bz#2033626]
+- Resolves: bz#2046659
+  (qemu crash after execute blockdev-reopen with  iothread)
+- Resolves: bz#2033626
+  (Qemu core dump when start guest with nbd node or do block jobs to nbd node)
+
+* Mon Feb 14 2022 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-8
+- kvm-numa-Enable-numa-for-SGX-EPC-sections.patch [bz#2033708]
+- kvm-numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch [bz#2033708]
+- kvm-doc-Add-the-SGX-numa-description.patch [bz#2033708]
+- kvm-Enable-SGX-RH-Only.patch [bz#2033708]
+- kvm-qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch [bz#2033708]
+- kvm-block-io-Update-BSC-only-if-want_zero-is-true.patch [bz#2041461]
+- kvm-iotests-block-status-cache-New-test.patch [bz#2041461]
+- kvm-iotests-Test-qemu-img-convert-of-zeroed-data-cluster.patch [bz#1882917]
+- kvm-qemu-img-make-is_allocated_sectors-more-efficient.patch [bz#1882917]
+- kvm-block-backend-prevent-dangling-BDS-pointers-across-a.patch [bz#2040123]
+- kvm-iotests-stream-error-on-reset-New-test.patch [bz#2040123]
+- kvm-hw-arm-smmuv3-Fix-device-reset.patch [bz#2042481]
+- Resolves: bz#2033708
+  ([Intel 9.0 Feat] qemu-kvm: SGX 1.5 (SGX1 + Flexible Launch Control) support)
+- Resolves: bz#2041461
+  (Inconsistent block status reply in qemu-nbd)
+- Resolves: bz#1882917
+  (the target image size is incorrect when converting a badly fragmented file)
+- Resolves: bz#2040123
+  (Qemu core dumped when do block-stream to a snapshot node on non-enough space storage)
+- Resolves: bz#2042481
+  ([aarch64] Launch guest with "default-bus-bypass-iommu=off,iommu=smmuv3" and "iommu_platform=on", guest hangs after system_reset)
+
+* Mon Feb 07 2022 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-7
+- kvm-qemu-storage-daemon-Add-vhost-user-blk-help.patch [bz#1962088]
+- kvm-qemu-storage-daemon-Fix-typo-in-vhost-user-blk-help.patch [bz#1962088]
+- kvm-virtiofsd-Drop-membership-of-all-supplementary-group.patch [bz#2046201]
+- kvm-block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch [bz#2034791]
+- kvm-block-rbd-workaround-for-ceph-issue-53784.patch [bz#2034791]
+- Resolves: bz#1962088
+  ([QSD] wrong help message for the fuse)
+- Resolves: bz#2046201
+  (CVE-2022-0358 qemu-kvm: QEMU: virtiofsd: potential privilege escalation via CVE-2018-13405 [rhel-9.0])
+- Resolves: bz#2034791
+  (Booting from Local Snapshot Core Dumped Whose Backing File Is Based on RBD)
+
+* Wed Feb 02 2022 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-6
+- Moving feature support out of qemu-kvm-core to separate packages (can
+  cause loss of functionality when using only qemu-kvm-core - qemu-kvm keeps
+  same feature set).
+- kvm-spec-Rename-qemu-kvm-hw-usbredir-to-qemu-kvm-device-.patch [bz#2022847]
+- kvm-spec-Split-qemu-kvm-ui-opengl.patch [bz#2022847]
+- kvm-spec-Introduce-packages-for-virtio-gpu-modules.patch [bz#2022847]
+- kvm-spec-Introduce-device-display-virtio-vga-packages.patch [bz#2022847]
+- kvm-spec-Move-usb-host-module-to-separate-package.patch [bz#2022847]
+- kvm-spec-Move-qtest-accel-module-to-tests-package.patch [bz#2022847]
+- kvm-spec-Extend-qemu-kvm-core-description.patch [bz#2022847]
+- Resolves: bz#2022847
+  (qemu-kvm: Align package split with Fedora)
+
+* Tue Jan 25 2022 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-5
+- kvm-x86-Add-q35-RHEL-8.6.0-machine-type.patch [bz#1945666]
+- kvm-x86-Add-q35-RHEL-9.0.0-machine-type.patch [bz#1945666]
+- kvm-softmmu-fix-device-deletion-events-with-device-JSON-.patch [bz#2036669]
+- Resolves: bz#1945666
+  (9.0: x86 machine types)
+- Resolves: bz#2036669
+  (DEVICE_DELETED event is not delivered for device frontend if -device is configured via JSON)
+
+* Mon Jan 17 2022 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-4
+- kvm-block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch [bz#2024544]
+- kvm-rhel-machine-types-x86-set-prefer_sockets.patch [bz#2028623]
+- Resolves: bz#2024544
+  (Fio workers hangs when running fio with 32 jobs iodepth 32 and QEMU's userspace NVMe driver)
+- Resolves: bz#2028623
+  ([9.0] machine types: 6.2: Fix prefer_sockets)
+
 * Mon Jan 10 2022 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-3
 - kvm-hw-arm-virt-Register-iommu-as-a-class-property.patch [bz#2031044]
 - kvm-hw-arm-virt-Register-its-as-a-class-property.patch [bz#2031044]