--- /dev/null
+From ae70dcb9d9ecaf7d9836d3e1b5bef654d7ef5680 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Mon, 24 Jul 2023 05:25:30 +0200
+Subject: net: dsa: qca8k: fix broken search_and_del
+
+From: Christian Marangi <ansuelsmth@gmail.com>
+
+commit ae70dcb9d9ecaf7d9836d3e1b5bef654d7ef5680 upstream.
+
+On deleting an MDB entry for a port, fdb_search_and_del is used.
+An FDB entry can't be modified so it needs to be deleted and readded
+again with the new portmap (and the port deleted as requested)
+
+We use the SEARCH operator to search the entry to edit by vid and mac
+address and then we check the aging if we actually found an entry.
+
+Currently the code suffer from a bug where the searched fdb entry is
+never read again with the found values (if found) resulting in the code
+always returning -EINVAL as aging was always 0.
+
+Fix this by correctly read the fdb entry after it was searched.
+
+Fixes: ba8f870dfa63 ("net: dsa: qca8k: add support for mdb_add/del")
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/dsa/qca/qca8k-common.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/net/dsa/qca/qca8k-common.c
++++ b/drivers/net/dsa/qca/qca8k-common.c
+@@ -330,6 +330,10 @@ static int qca8k_fdb_search_and_del(stru
+ if (ret < 0)
+ goto exit;
+
++ ret = qca8k_fdb_read(priv, &fdb);
++ if (ret < 0)
++ goto exit;
++
+ /* Rule doesn't exist. Why delete? */
+ if (!fdb.aging) {
+ ret = -EINVAL;
--- /dev/null
+From dfd739f182b00b02bd7470ed94d112684cc04fa2 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Mon, 24 Jul 2023 05:25:31 +0200
+Subject: net: dsa: qca8k: fix mdb add/del case with 0 VID
+
+From: Christian Marangi <ansuelsmth@gmail.com>
+
+commit dfd739f182b00b02bd7470ed94d112684cc04fa2 upstream.
+
+The qca8k switch doesn't support using 0 as VID and require a default
+VID to be always set. MDB add/del function doesn't currently handle
+this and are currently setting the default VID.
+
+Fix this by correctly handling this corner case and internally use the
+default VID for VID 0 case.
+
+Fixes: ba8f870dfa63 ("net: dsa: qca8k: add support for mdb_add/del")
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/dsa/qca/qca8k-common.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/dsa/qca/qca8k-common.c
++++ b/drivers/net/dsa/qca/qca8k-common.c
+@@ -853,6 +853,9 @@ int qca8k_port_mdb_add(struct dsa_switch
+ const u8 *addr = mdb->addr;
+ u16 vid = mdb->vid;
+
++ if (!vid)
++ vid = QCA8K_PORT_VID_DEF;
++
+ return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid,
+ QCA8K_ATU_STATUS_STATIC);
+ }
+@@ -865,6 +868,9 @@ int qca8k_port_mdb_del(struct dsa_switch
+ const u8 *addr = mdb->addr;
+ u16 vid = mdb->vid;
+
++ if (!vid)
++ vid = QCA8K_PORT_VID_DEF;
++
+ return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
+ }
+
--- /dev/null
+From 80248d4160894d7e40b04111bdbaa4ff93fc4bd7 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Mon, 24 Jul 2023 05:25:29 +0200
+Subject: net: dsa: qca8k: fix search_and_insert wrong handling of new rule
+
+From: Christian Marangi <ansuelsmth@gmail.com>
+
+commit 80248d4160894d7e40b04111bdbaa4ff93fc4bd7 upstream.
+
+On inserting a mdb entry, fdb_search_and_insert is used to add a port to
+the qca8k target entry in the FDB db.
+
+A FDB entry can't be modified so it needs to be removed and insert again
+with the new values.
+
+To detect if an entry already exist, the SEARCH operation is used and we
+check the aging of the entry. If the entry is not 0, the entry exist and
+we proceed to delete it.
+
+Current code have 2 main problem:
+- The condition to check if the FDB entry exist is wrong and should be
+ the opposite.
+- When a FDB entry doesn't exist, aging was never actually set to the
+ STATIC value resulting in allocating an invalid entry.
+
+Fix both problem by adding aging support to the function, calling the
+function with STATIC as aging by default and finally by correct the
+condition to check if the entry actually exist.
+
+Fixes: ba8f870dfa63 ("net: dsa: qca8k: add support for mdb_add/del")
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/dsa/qca/qca8k-common.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/dsa/qca/qca8k-common.c
++++ b/drivers/net/dsa/qca/qca8k-common.c
+@@ -281,7 +281,7 @@ void qca8k_fdb_flush(struct qca8k_priv *
+ }
+
+ static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
+- const u8 *mac, u16 vid)
++ const u8 *mac, u16 vid, u8 aging)
+ {
+ struct qca8k_fdb fdb = { 0 };
+ int ret;
+@@ -298,10 +298,12 @@ static int qca8k_fdb_search_and_insert(s
+ goto exit;
+
+ /* Rule exist. Delete first */
+- if (!fdb.aging) {
++ if (fdb.aging) {
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
+ if (ret)
+ goto exit;
++ } else {
++ fdb.aging = aging;
+ }
+
+ /* Add port to fdb portmask */
+@@ -847,7 +849,8 @@ int qca8k_port_mdb_add(struct dsa_switch
+ const u8 *addr = mdb->addr;
+ u16 vid = mdb->vid;
+
+- return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
++ return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid,
++ QCA8K_ATU_STATUS_STATIC);
+ }
+
+ int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
--- /dev/null
+From 641db40f3afe7998011bfabc726dba3e698f8196 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@linaro.org>
+Date: Tue, 25 Jul 2023 20:03:16 +0300
+Subject: proc/vmcore: fix signedness bug in read_from_oldmem()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+commit 641db40f3afe7998011bfabc726dba3e698f8196 upstream.
+
+The bug is the error handling:
+
+ if (tmp < nr_bytes) {
+
+"tmp" can hold negative error codes but because "nr_bytes" is type size_t
+the negative error codes are treated as very high positive values
+(success). Fix this by changing "nr_bytes" to type ssize_t. The
+"nr_bytes" variable is used to store values between 1 and PAGE_SIZE and
+they can fit in ssize_t without any issue.
+
+Link: https://lkml.kernel.org/r/b55f7eed-1c65-4adc-95d1-6c7c65a54a6e@moroto.mountain
+Fixes: 5d8de293c224 ("vmcore: convert copy_oldmem_page() to take an iov_iter")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Acked-by: Baoquan He <bhe@redhat.com>
+Cc: Dave Young <dyoung@redhat.com>
+Cc: Vivek Goyal <vgoyal@redhat.com>
+Cc: Alexey Dobriyan <adobriyan@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/proc/vmcore.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/proc/vmcore.c
++++ b/fs/proc/vmcore.c
+@@ -132,7 +132,7 @@ ssize_t read_from_oldmem(struct iov_iter
+ u64 *ppos, bool encrypted)
+ {
+ unsigned long pfn, offset;
+- size_t nr_bytes;
++ ssize_t nr_bytes;
+ ssize_t read = 0, tmp;
+ int idx;
+
irq-bcm6345-l1-do-not-assume-a-fixed-block-to-cpu-ma.patch
irqchip-gic-v4.1-properly-lock-vpes-when-doing-a-dir.patch
locking-rtmutex-fix-task-pi_waiters-integrity.patch
+proc-vmcore-fix-signedness-bug-in-read_from_oldmem.patch
+xen-speed-up-grant-table-reclaim.patch
+virtio-net-fix-race-between-set-queues-and-probe.patch
+net-dsa-qca8k-fix-search_and_insert-wrong-handling-of-new-rule.patch
+net-dsa-qca8k-fix-broken-search_and_del.patch
+net-dsa-qca8k-fix-mdb-add-del-case-with-0-vid.patch
--- /dev/null
+From 25266128fe16d5632d43ada34c847d7b8daba539 Mon Sep 17 00:00:00 2001
+From: Jason Wang <jasowang@redhat.com>
+Date: Tue, 25 Jul 2023 03:20:49 -0400
+Subject: virtio-net: fix race between set queues and probe
+
+From: Jason Wang <jasowang@redhat.com>
+
+commit 25266128fe16d5632d43ada34c847d7b8daba539 upstream.
+
+A race were found where set_channels could be called after registering
+but before virtnet_set_queues() in virtnet_probe(). Fixing this by
+moving the virtnet_set_queues() before netdevice registering. While at
+it, use _virtnet_set_queues() to avoid holding rtnl as the device is
+not even registered at that time.
+
+Cc: stable@vger.kernel.org
+Fixes: a220871be66f ("virtio-net: correctly enable multiqueue")
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Link: https://lore.kernel.org/r/20230725072049.617289-1-jasowang@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/virtio_net.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3940,6 +3940,8 @@ static int virtnet_probe(struct virtio_d
+ if (vi->has_rss || vi->has_rss_hash_report)
+ virtnet_init_default_rss(vi);
+
++ _virtnet_set_queues(vi, vi->curr_queue_pairs);
++
+ /* serialize netdev register + virtio_device_ready() with ndo_open() */
+ rtnl_lock();
+
+@@ -3960,8 +3962,6 @@ static int virtnet_probe(struct virtio_d
+ goto free_unregister_netdev;
+ }
+
+- virtnet_set_queues(vi, vi->curr_queue_pairs);
+-
+ /* Assume link up if device can't report link status,
+ otherwise get link status from config. */
+ netif_carrier_off(dev);
--- /dev/null
+From c04e9894846c663f3278a414f34416e6e45bbe68 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Wed, 26 Jul 2023 12:52:41 -0400
+Subject: xen: speed up grant-table reclaim
+
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+
+commit c04e9894846c663f3278a414f34416e6e45bbe68 upstream.
+
+When a grant entry is still in use by the remote domain, Linux must put
+it on a deferred list. Normally, this list is very short, because
+the PV network and block protocols expect the backend to unmap the grant
+first. However, Qubes OS's GUI protocol is subject to the constraints
+of the X Window System, and as such winds up with the frontend unmapping
+the window first. As a result, the list can grow very large, resulting
+in a massive memory leak and eventual VM freeze.
+
+To partially solve this problem, make the number of entries that the VM
+will attempt to free at each iteration tunable. The default is still
+10, but it can be overridden via a module parameter.
+
+This is Cc: stable because (when combined with appropriate userspace
+changes) it fixes a severe performance and stability problem for Qubes
+OS users.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Demi Marie Obenour <demi@invisiblethingslab.com>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Link: https://lore.kernel.org/r/20230726165354.1252-1-demi@invisiblethingslab.com
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/ABI/testing/sysfs-module | 11 +++++++++
+ drivers/xen/grant-table.c | 40 +++++++++++++++++++++++----------
+ 2 files changed, 40 insertions(+), 11 deletions(-)
+
+--- a/Documentation/ABI/testing/sysfs-module
++++ b/Documentation/ABI/testing/sysfs-module
+@@ -60,3 +60,14 @@ Description: Module taint flags:
+ C staging driver module
+ E unsigned module
+ == =====================
++
++What: /sys/module/grant_table/parameters/free_per_iteration
++Date: July 2023
++KernelVersion: 6.5 but backported to all supported stable branches
++Contact: Xen developer discussion <xen-devel@lists.xenproject.org>
++Description: Read and write number of grant entries to attempt to free per iteration.
++
++ Note: Future versions of Xen and Linux may provide a better
++ interface for controlling the rate of deferred grant reclaim
++ or may not need it at all.
++Users: Qubes OS (https://www.qubes-os.org)
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -498,14 +498,21 @@ static LIST_HEAD(deferred_list);
+ static void gnttab_handle_deferred(struct timer_list *);
+ static DEFINE_TIMER(deferred_timer, gnttab_handle_deferred);
+
++static atomic64_t deferred_count;
++static atomic64_t leaked_count;
++static unsigned int free_per_iteration = 10;
++module_param(free_per_iteration, uint, 0600);
++
+ static void gnttab_handle_deferred(struct timer_list *unused)
+ {
+- unsigned int nr = 10;
++ unsigned int nr = READ_ONCE(free_per_iteration);
++ const bool ignore_limit = nr == 0;
+ struct deferred_entry *first = NULL;
+ unsigned long flags;
++ size_t freed = 0;
+
+ spin_lock_irqsave(&gnttab_list_lock, flags);
+- while (nr--) {
++ while ((ignore_limit || nr--) && !list_empty(&deferred_list)) {
+ struct deferred_entry *entry
+ = list_first_entry(&deferred_list,
+ struct deferred_entry, list);
+@@ -515,10 +522,14 @@ static void gnttab_handle_deferred(struc
+ list_del(&entry->list);
+ spin_unlock_irqrestore(&gnttab_list_lock, flags);
+ if (_gnttab_end_foreign_access_ref(entry->ref)) {
++ uint64_t ret = atomic64_dec_return(&deferred_count);
++
+ put_free_entry(entry->ref);
+- pr_debug("freeing g.e. %#x (pfn %#lx)\n",
+- entry->ref, page_to_pfn(entry->page));
++ pr_debug("freeing g.e. %#x (pfn %#lx), %llu remaining\n",
++ entry->ref, page_to_pfn(entry->page),
++ (unsigned long long)ret);
+ put_page(entry->page);
++ freed++;
+ kfree(entry);
+ entry = NULL;
+ } else {
+@@ -530,21 +541,22 @@ static void gnttab_handle_deferred(struc
+ spin_lock_irqsave(&gnttab_list_lock, flags);
+ if (entry)
+ list_add_tail(&entry->list, &deferred_list);
+- else if (list_empty(&deferred_list))
+- break;
+ }
+- if (!list_empty(&deferred_list) && !timer_pending(&deferred_timer)) {
++ if (list_empty(&deferred_list))
++ WARN_ON(atomic64_read(&deferred_count));
++ else if (!timer_pending(&deferred_timer)) {
+ deferred_timer.expires = jiffies + HZ;
+ add_timer(&deferred_timer);
+ }
+ spin_unlock_irqrestore(&gnttab_list_lock, flags);
++ pr_debug("Freed %zu references", freed);
+ }
+
+ static void gnttab_add_deferred(grant_ref_t ref, struct page *page)
+ {
+ struct deferred_entry *entry;
+ gfp_t gfp = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
+- const char *what = KERN_WARNING "leaking";
++ uint64_t leaked, deferred;
+
+ entry = kmalloc(sizeof(*entry), gfp);
+ if (!page) {
+@@ -567,10 +579,16 @@ static void gnttab_add_deferred(grant_re
+ add_timer(&deferred_timer);
+ }
+ spin_unlock_irqrestore(&gnttab_list_lock, flags);
+- what = KERN_DEBUG "deferring";
++ deferred = atomic64_inc_return(&deferred_count);
++ leaked = atomic64_read(&leaked_count);
++ pr_debug("deferring g.e. %#x (pfn %#lx) (total deferred %llu, total leaked %llu)\n",
++ ref, page ? page_to_pfn(page) : -1, deferred, leaked);
++ } else {
++ deferred = atomic64_read(&deferred_count);
++ leaked = atomic64_inc_return(&leaked_count);
++ pr_warn("leaking g.e. %#x (pfn %#lx) (total deferred %llu, total leaked %llu)\n",
++ ref, page ? page_to_pfn(page) : -1, deferred, leaked);
+ }
+- printk("%s g.e. %#x (pfn %#lx)\n",
+- what, ref, page ? page_to_pfn(page) : -1);
+ }
+
+ int gnttab_try_end_foreign_access(grant_ref_t ref)