On Mon, May 26, 2025 at 6:40 AM Wang Yugui <wangyugui(a)e16-tech.com> wrote:
>
> Hi,
> Cc: Filipe Manana
>
> I noticed 6.1.140 build failure(fs/btrfs/discard.c:247:5: error: implicit declaration of function 'ASSERT')
>
> fs/btrfs/discard.c: In function 'peek_discard_list':
> fs/btrfs/discard.c:247:5: error: implicit declaration of function 'ASSERT'; did you mean 'IS_ERR'? [-Werror=implicit-function-declaration]
> ASSERT(block_group->discard_index !=
> ^~~~~~
> IS_ERR
>
> It seems realted to the patch(btrfs-fix-discard-worker-infinite-loop-after-disabling-discard.patch).
Yes, it is.
The patch, like most stable backports, was automatically picked by the
stable scripts and added to stable releases.
I assume that before the release was made, it was compile tested by
the stable automatic processes.
I just tried it, and it compiles successfully for me:
fdmanana 11:56:26 ~/git/hub/linux ((v6.12))> git clean -xfd
fdmanana 11:57:27 ~/git/hub/linux ((v6.12))> git co v6.1.140
fdmanana 11:59:53 ~/git/hub/linux ((v6.1.140))> make defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/confdata.o
HOSTCC scripts/kconfig/expr.o
LEX scripts/kconfig/lexer.lex.c
YACC scripts/kconfig/parser.tab.[ch]
HOSTCC scripts/kconfig/lexer.lex.o
HOSTCC scripts/kconfig/menu.o
HOSTCC scripts/kconfig/parser.tab.o
HOSTCC scripts/kconfig/preprocess.o
HOSTCC scripts/kconfig/symbol.o
HOSTCC scripts/kconfig/util.o
HOSTLD scripts/kconfig/conf
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#
# Run make menuconfig to enable btrfs and all its config options
fdmanana 12:01:55 ~/git/hub/linux ((v6.1.140))> make menuconfig
fdmanana 12:02:17 ~/git/hub/linux ((v6.1.140))> grep BTRFS .config
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_BTRFS_FS_CHECK_INTEGRITY=y
CONFIG_BTRFS_FS_RUN_SANITY_TESTS=y
CONFIG_BTRFS_DEBUG=y
CONFIG_BTRFS_ASSERT=y
CONFIG_BTRFS_FS_REF_VERIFY=y
fdmanana 12:06:08 ~/git/hub/linux ((v6.1.140))> make fs/btrfs/btrfs.ko
SYNC include/config/auto.conf
CALL scripts/checksyscalls.sh
DESCEND objtool
CC [M] fs/btrfs/super.o
CC [M] fs/btrfs/ctree.o
CC [M] fs/btrfs/extent-tree.o
CC [M] fs/btrfs/print-tree.o
CC [M] fs/btrfs/root-tree.o
CC [M] fs/btrfs/dir-item.o
CC [M] fs/btrfs/file-item.o
CC [M] fs/btrfs/inode-item.o
CC [M] fs/btrfs/disk-io.o
CC [M] fs/btrfs/transaction.o
CC [M] fs/btrfs/inode.o
CC [M] fs/btrfs/file.o
CC [M] fs/btrfs/tree-defrag.o
CC [M] fs/btrfs/extent_map.o
CC [M] fs/btrfs/sysfs.o
CC [M] fs/btrfs/struct-funcs.o
CC [M] fs/btrfs/xattr.o
CC [M] fs/btrfs/ordered-data.o
CC [M] fs/btrfs/extent_io.o
CC [M] fs/btrfs/volumes.o
CC [M] fs/btrfs/async-thread.o
CC [M] fs/btrfs/ioctl.o
CC [M] fs/btrfs/locking.o
CC [M] fs/btrfs/orphan.o
CC [M] fs/btrfs/export.o
CC [M] fs/btrfs/tree-log.o
CC [M] fs/btrfs/free-space-cache.o
CC [M] fs/btrfs/lzo.o
CC [M] fs/btrfs/zstd.o
CC [M] fs/btrfs/compression.o
CC [M] fs/btrfs/delayed-ref.o
CC [M] fs/btrfs/relocation.o
CC [M] fs/btrfs/delayed-inode.o
CC [M] fs/btrfs/scrub.o
CC [M] fs/btrfs/backref.o
CC [M] fs/btrfs/ulist.o
CC [M] fs/btrfs/qgroup.o
CC [M] fs/btrfs/send.o
CC [M] fs/btrfs/dev-replace.o
CC [M] fs/btrfs/raid56.o
CC [M] fs/btrfs/uuid-tree.o
CC [M] fs/btrfs/props.o
CC [M] fs/btrfs/free-space-tree.o
CC [M] fs/btrfs/tree-checker.o
CC [M] fs/btrfs/space-info.o
CC [M] fs/btrfs/block-rsv.o
CC [M] fs/btrfs/delalloc-space.o
CC [M] fs/btrfs/block-group.o
CC [M] fs/btrfs/discard.o
CC [M] fs/btrfs/reflink.o
CC [M] fs/btrfs/subpage.o
CC [M] fs/btrfs/tree-mod-log.o
CC [M] fs/btrfs/extent-io-tree.o
CC [M] fs/btrfs/acl.o
CC [M] fs/btrfs/check-integrity.o
CC [M] fs/btrfs/ref-verify.o
CC [M] fs/btrfs/tests/free-space-tests.o
CC [M] fs/btrfs/tests/extent-buffer-tests.o
CC [M] fs/btrfs/tests/btrfs-tests.o
CC [M] fs/btrfs/tests/extent-io-tests.o
CC [M] fs/btrfs/tests/inode-tests.o
CC [M] fs/btrfs/tests/qgroup-tests.o
CC [M] fs/btrfs/tests/free-space-tree-tests.o
CC [M] fs/btrfs/tests/extent-map-tests.o
LD [M] fs/btrfs/btrfs.o
make[3]: 'fs/btrfs/btrfs.mod' is up to date.
MODPOST modules-only.symvers
WARNING: vmlinux.o is missing.
Modules may not have dependencies or modversions.
You may get many unresolved symbol warnings.
WARNING: modpost: "bio_associate_blkg" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "zstd_cstream_workspace_bound" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "folio_invalidate" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "__page_file_index" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "strcpy" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "inode_init_owner" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "generic_fillattr" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "is_vmalloc_addr" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "krealloc" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: "vfs_fsync_range" [fs/btrfs/btrfs.ko] undefined!
WARNING: modpost: suppressed 521 unresolved symbol warnings because
there were too many)
LD [M] fs/btrfs/btrfs.ko
fdmanana 12:11:12 ~/git/hub/linux ((v6.1.140))> gcc --version
gcc (Debian 9.3.0-18) 9.3.0
>
> I walked around it with the following patch.
In the future please cc the stable list when you find problems with
stable backports.
>
> diff --git a/fs/btrfs/discard.c b/fs/btrfs/discard.c
> index 98bce18..9ffe5c4 100644
> --- a/fs/btrfs/discard.c
> +++ b/fs/btrfs/discard.c
> @@ -7,6 +7,7 @@
> #include <linux/math64.h>
> #include <linux/sizes.h>
> #include <linux/workqueue.h>
> +#include "messages.h"
> #include "ctree.h"
> #include "block-group.h"
> #include "discard.h"
>
>
> Best Regards
> Wang Yugui (wangyugui(a)e16-tech.com)
> 2025/05/26
>
>
>
Hi,
We’re excited to share exclusive access to the Integrated Systems Europe 2025 Visitor Contact List!
Our database includes 88,351 verified visitor contacts, giving you a powerful resource to connect with key industry professionals.
Each contact includes: Contact Name, Job Title, Company Name, Physical Address, Phone Number, Official Email Address, and more.
Interested in the list? Simply reply with “Send me Pricing” to get full details.
Kind regards,
Garnet Conwell
Sr. Marketing Manager
To opt out of future messages, just reply “Unfollow.”
From: Kairui Song <kasong(a)tencent.com>
On seeing a swap entry PTE, userfaultfd_move does a lockless swap cache
lookup, and try to move the found folio to the faulting vma when.
Currently, it relies on the PTE value check to ensure the moved folio
still belongs to the src swap entry, which turns out is not reliable.
While working and reviewing the swap table series with Barry, following
existing race is observed and reproduced [1]:
( move_pages_pte is moving src_pte to dst_pte, where src_pte is a
swap entry PTE holding swap entry S1, and S1 isn't in the swap cache.)
CPU1 CPU2
userfaultfd_move
move_pages_pte()
entry = pte_to_swp_entry(orig_src_pte);
// Here it got entry = S1
... < Somehow interrupted> ...
<swapin src_pte, alloc and use folio A>
// folio A is just a new allocated folio
// and get installed into src_pte
<frees swap entry S1>
// src_pte now points to folio A, S1
// has swap count == 0, it can be freed
// by folio_swap_swap or swap
// allocator's reclaim.
<try to swap out another folio B>
// folio B is a folio in another VMA.
<put folio B to swap cache using S1 >
// S1 is freed, folio B could use it
// for swap out with no problem.
...
folio = filemap_get_folio(S1)
// Got folio B here !!!
... < Somehow interrupted again> ...
<swapin folio B and free S1>
// Now S1 is free to be used again.
<swapout src_pte & folio A using S1>
// Now src_pte is a swap entry pte
// holding S1 again.
folio_trylock(folio)
move_swap_pte
double_pt_lock
is_pte_pages_stable
// Check passed because src_pte == S1
folio_move_anon_rmap(...)
// Moved invalid folio B here !!!
The race window is very short and requires multiple collisions of
multiple rare events, so it's very unlikely to happen, but with a
deliberately constructed reproducer and increased time window, it can be
reproduced [1].
It's also possible that folio (A) is swapped in, and swapped out again
after the filemap_get_folio lookup, in such case folio (A) may stay in
swap cache so it needs to be moved too. In this case we should also try
again so kernel won't miss a folio move.
Fix this by checking if the folio is the valid swap cache folio after
acquiring the folio lock, and checking the swap cache again after
acquiring the src_pte lock.
SWP_SYNCRHONIZE_IO path does make the problem more complex, but so far
we don't need to worry about that since folios only might get exposed to
swap cache in the swap out path, and it's covered in this patch too by
checking the swap cache again after acquiring src_pte lock.
Fixes: adef440691ba ("userfaultfd: UFFDIO_MOVE uABI")
Closes: https://lore.kernel.org/linux-mm/CAMgjq7B1K=6OOrK2OUZ0-tqCzi+EJt+2_K97TPGoS… [1]
Signed-off-by: Kairui Song <kasong(a)tencent.com>
---
mm/userfaultfd.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index bc473ad21202..a1564d205dfb 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -15,6 +15,7 @@
#include <linux/mmu_notifier.h>
#include <linux/hugetlb.h>
#include <linux/shmem_fs.h>
+#include <linux/delay.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
#include "internal.h"
@@ -1086,6 +1087,8 @@ static int move_swap_pte(struct mm_struct *mm, struct vm_area_struct *dst_vma,
spinlock_t *dst_ptl, spinlock_t *src_ptl,
struct folio *src_folio)
{
+ swp_entry_t entry;
+
double_pt_lock(dst_ptl, src_ptl);
if (!is_pte_pages_stable(dst_pte, src_pte, orig_dst_pte, orig_src_pte,
@@ -1102,6 +1105,19 @@ static int move_swap_pte(struct mm_struct *mm, struct vm_area_struct *dst_vma,
if (src_folio) {
folio_move_anon_rmap(src_folio, dst_vma);
src_folio->index = linear_page_index(dst_vma, dst_addr);
+ } else {
+ /*
+ * Check again after acquiring the src_pte lock. Or we might
+ * miss a new loaded swap cache folio.
+ */
+ entry = pte_to_swp_entry(orig_src_pte);
+ src_folio = filemap_get_folio(swap_address_space(entry),
+ swap_cache_index(entry));
+ if (!IS_ERR_OR_NULL(src_folio)) {
+ double_pt_unlock(dst_ptl, src_ptl);
+ folio_put(src_folio);
+ return -EAGAIN;
+ }
}
orig_src_pte = ptep_get_and_clear(mm, src_addr, src_pte);
@@ -1409,6 +1425,16 @@ static int move_pages_pte(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd,
folio_lock(src_folio);
goto retry;
}
+ /*
+ * Check if the folio still belongs to the target swap entry after
+ * acquiring the lock. Folio can be freed in the swap cache while
+ * not locked.
+ */
+ if (unlikely(!folio_test_swapcache(folio) ||
+ entry.val != folio->swap.val)) {
+ err = -EAGAIN;
+ goto out;
+ }
}
err = move_swap_pte(mm, dst_vma, dst_addr, src_addr, dst_pte, src_pte,
orig_dst_pte, orig_src_pte, dst_pmd, dst_pmdval,
--
2.49.0
The MANA driver's probe registers netdevice via the following call chain:
mana_probe()
register_netdev()
register_netdevice()
register_netdevice() calls notifier callback for netvsc driver,
holding the netdev mutex via netdev_lock_ops().
Further this netvsc notifier callback end up attempting to acquire the
same lock again in dev_xdp_propagate() leading to deadlock.
netvsc_netdev_event()
netvsc_vf_setxdp()
dev_xdp_propagate()
This deadlock was not observed so far because net_shaper_ops was never set,
and thus the lock was effectively a no-op in this case. Fix this by using
netif_xdp_propagate() instead of dev_xdp_propagate() to avoid recursive
locking in this path.
And, since no deadlock is observed on the other path which is via
netvsc_probe, add the lock exclusivly for that path.
Also, clean up the unregistration path by removing the unnecessary call to
netvsc_vf_setxdp(), since unregister_netdevice_many_notify() already
performs this cleanup via dev_xdp_uninstall().
Fixes: 97246d6d21c2 ("net: hold netdev instance lock during ndo_bpf")
Cc: stable(a)vger.kernel.org
Signed-off-by: Saurabh Sengar <ssengar(a)linux.microsoft.com>
Tested-by: Erni Sri Satya Vennela <ernis(a)linux.microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz(a)microsoft.com>
Reviewed-by: Subbaraya Sundeep <sbhatta(a)marvell.com>
---
[V3]
- Add the lock for netvsc probe path
[V2]
- Modified commit message
drivers/net/hyperv/netvsc_bpf.c | 2 +-
drivers/net/hyperv/netvsc_drv.c | 4 ++--
net/core/dev.c | 1 +
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/hyperv/netvsc_bpf.c b/drivers/net/hyperv/netvsc_bpf.c
index e01c5997a551..1dd3755d9e6d 100644
--- a/drivers/net/hyperv/netvsc_bpf.c
+++ b/drivers/net/hyperv/netvsc_bpf.c
@@ -183,7 +183,7 @@ int netvsc_vf_setxdp(struct net_device *vf_netdev, struct bpf_prog *prog)
xdp.command = XDP_SETUP_PROG;
xdp.prog = prog;
- ret = dev_xdp_propagate(vf_netdev, &xdp);
+ ret = netif_xdp_propagate(vf_netdev, &xdp);
if (ret && prog)
bpf_prog_put(prog);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 14a0d04e21ae..c41a025c66f0 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -2462,8 +2462,6 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
- netvsc_vf_setxdp(vf_netdev, NULL);
-
reinit_completion(&net_device_ctx->vf_add);
netdev_rx_handler_unregister(vf_netdev);
netdev_upper_dev_unlink(vf_netdev, ndev);
@@ -2631,7 +2629,9 @@ static int netvsc_probe(struct hv_device *dev,
continue;
netvsc_prepare_bonding(vf_netdev);
+ netdev_lock_ops(vf_netdev);
netvsc_register_vf(vf_netdev, VF_REG_IN_PROBE);
+ netdev_unlock_ops(vf_netdev);
__netvsc_vf_setup(net, vf_netdev);
break;
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 2b514d95c528..a388f459a366 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -9968,6 +9968,7 @@ int netif_xdp_propagate(struct net_device *dev, struct netdev_bpf *bpf)
return dev->netdev_ops->ndo_bpf(dev, bpf);
}
+EXPORT_SYMBOL_GPL(netif_xdp_propagate);
u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode)
{
--
2.43.0
Mask the value read before returning it. The value read over the
parallel bus via the AXI ADC IP block contains both the address and
the data, but callers expect val to only contain the data.
Cc: stable(a)vger.kernel.org
Fixes: 79c47485e438 ("iio: adc: adi-axi-adc: add support for AD7606 register writing")
Signed-off-by: David Lechner <dlechner(a)baylibre.com>
---
drivers/iio/adc/adi-axi-adc.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index cf942c043457ccea49207c3900153ee371b3774f..d4759a98b4062bc25ea088e3868806e82db03e8d 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -457,6 +457,9 @@ static int ad7606_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val)
axi_adc_raw_write(back, addr);
axi_adc_raw_read(back, val);
+ /* Register value is 8 bits. Remove address bits. */
+ *val &= 0xFF;
+
/* Write 0x0 on the bus to get back to ADC mode */
axi_adc_raw_write(back, 0);
---
base-commit: 7cdfbc0113d087348b8e65dd79276d0f57b89a10
change-id: 20250530-iio-adc-adi-axi-adc-fix-ad7606_bus_reg_read-f2bbb503db8b
Best regards,
--
David Lechner <dlechner(a)baylibre.com>
The symlink body (->target) should be freed at the same time as the inode
itself per commit 4fdcfab5b553 ("jffs2: fix use-after-free on symlink
traversal"). It is a filesystem-specific field but there exist several
error paths during generic inode allocation when ->free_inode(), namely
jffs2_free_inode(), is called with still uninitialized private info.
The calltrace looks like:
alloc_inode
inode_init_always // fails
i_callback
free_inode
jffs2_free_inode // touches uninit ->target field
Commit af9a8730ddb6 ("jffs2: Fix potential illegal address access in
jffs2_free_inode") approached the observed problem but fixed it only
partially. Our local Syzkaller instance is still hitting these kinds of
failures.
The thing is that jffs2_i_init_once(), where the initialization of
f->target has been moved, is called once per slab allocation so it won't
be called for the object structure possibly retrieved later from the slab
cache for reuse.
The practice followed by many other filesystems is to initialize
filesystem-private inode contents in the corresponding ->alloc_inode()
callbacks. This also allows to drop initialization from jffs2_iget() and
jffs2_new_inode() as ->alloc_inode() is called in those places.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Fixes: 4fdcfab5b553 ("jffs2: fix use-after-free on symlink traversal")
Cc: stable(a)vger.kernel.org
Signed-off-by: Fedor Pchelkin <pchelkin(a)ispras.ru>
Reviewed-by: Zhihao Cheng <chengzhihao1(a)huawei.com>
---
fs/jffs2/fs.c | 2 --
fs/jffs2/super.c | 3 ++-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index d175cccb7c55..85c4b273918f 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -271,7 +271,6 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
f = JFFS2_INODE_INFO(inode);
c = JFFS2_SB_INFO(inode->i_sb);
- jffs2_init_inode_info(f);
mutex_lock(&f->sem);
ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
@@ -439,7 +438,6 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_r
return ERR_PTR(-ENOMEM);
f = JFFS2_INODE_INFO(inode);
- jffs2_init_inode_info(f);
mutex_lock(&f->sem);
memset(ri, 0, sizeof(*ri));
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 4545f885c41e..b56ff63357f3 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -42,6 +42,8 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb)
f = alloc_inode_sb(sb, jffs2_inode_cachep, GFP_KERNEL);
if (!f)
return NULL;
+
+ jffs2_init_inode_info(f);
return &f->vfs_inode;
}
@@ -58,7 +60,6 @@ static void jffs2_i_init_once(void *foo)
struct jffs2_inode_info *f = foo;
mutex_init(&f->sem);
- f->target = NULL;
inode_init_once(&f->vfs_inode);
}
--
2.49.0
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 7170130e4c72ce0caa0cb42a1627c635cc262821
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '2025052750-fondness-revocable-a23b@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 7170130e4c72ce0caa0cb42a1627c635cc262821 Mon Sep 17 00:00:00 2001
From: Balbir Singh <balbirs(a)nvidia.com>
Date: Tue, 1 Apr 2025 11:07:52 +1100
Subject: [PATCH] x86/mm/init: Handle the special case of device private pages
in add_pages(), to not increase max_pfn and trigger dma_addressing_limited()
bounce buffers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
As Bert Karwatzki reported, the following recent commit causes a
performance regression on AMD iGPU and dGPU systems:
7ffb791423c7 ("x86/kaslr: Reduce KASLR entropy on most x86 systems")
It exposed a bug with nokaslr and zone device interaction.
The root cause of the bug is that, the GPU driver registers a zone
device private memory region. When KASLR is disabled or the above commit
is applied, the direct_map_physmem_end is set to much higher than 10 TiB
typically to the 64TiB address. When zone device private memory is added
to the system via add_pages(), it bumps up the max_pfn to the same
value. This causes dma_addressing_limited() to return true, since the
device cannot address memory all the way up to max_pfn.
This caused a regression for games played on the iGPU, as it resulted in
the DMA32 zone being used for GPU allocations.
Fix this by not bumping up max_pfn on x86 systems, when pgmap is passed
into add_pages(). The presence of pgmap is used to determine if device
private memory is being added via add_pages().
More details:
devm_request_mem_region() and request_free_mem_region() request for
device private memory. iomem_resource is passed as the base resource
with start and end parameters. iomem_resource's end depends on several
factors, including the platform and virtualization. On x86 for example
on bare metal, this value is set to boot_cpu_data.x86_phys_bits.
boot_cpu_data.x86_phys_bits can change depending on support for MKTME.
By default it is set to the same as log2(direct_map_physmem_end) which
is 46 to 52 bits depending on the number of levels in the page table.
The allocation routines used iomem_resource's end and
direct_map_physmem_end to figure out where to allocate the region.
[ arch/powerpc is also impacted by this problem, but this patch does not fix
the issue for PowerPC. ]
Testing:
1. Tested on a virtual machine with test_hmm for zone device inseration
2. A previous version of this patch was tested by Bert, please see:
https://lore.kernel.org/lkml/d87680bab997fdc9fb4e638983132af235d9a03a.camel…
[ mingo: Clarified the comments and the changelog. ]
Reported-by: Bert Karwatzki <spasswolf(a)web.de>
Tested-by: Bert Karwatzki <spasswolf(a)web.de>
Fixes: 7ffb791423c7 ("x86/kaslr: Reduce KASLR entropy on most x86 systems")
Signed-off-by: Balbir Singh <balbirs(a)nvidia.com>
Signed-off-by: Ingo Molnar <mingo(a)kernel.org>
Cc: Brian Gerst <brgerst(a)gmail.com>
Cc: Juergen Gross <jgross(a)suse.com>
Cc: H. Peter Anvin <hpa(a)zytor.com>
Cc: Linus Torvalds <torvalds(a)linux-foundation.org>
Cc: Andrew Morton <akpm(a)linux-foundation.org>
Cc: Christoph Hellwig <hch(a)lst.de>
Cc: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer(a)amd.com>
Cc: Alex Deucher <alexander.deucher(a)amd.com>
Cc: Christian König <christian.koenig(a)amd.com>
Cc: David Airlie <airlied(a)gmail.com>
Cc: Simona Vetter <simona(a)ffwll.ch>
Link: https://lore.kernel.org/r/20250401000752.249348-1-balbirs@nvidia.com
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 519aa53114fa..821a0b53b21c 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -959,9 +959,18 @@ int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
ret = __add_pages(nid, start_pfn, nr_pages, params);
WARN_ON_ONCE(ret);
- /* update max_pfn, max_low_pfn and high_memory */
- update_end_of_memory_vars(start_pfn << PAGE_SHIFT,
- nr_pages << PAGE_SHIFT);
+ /*
+ * Special case: add_pages() is called by memremap_pages() for adding device
+ * private pages. Do not bump up max_pfn in the device private path,
+ * because max_pfn changes affect dma_addressing_limited().
+ *
+ * dma_addressing_limited() returning true when max_pfn is the device's
+ * addressable memory can force device drivers to use bounce buffers
+ * and impact their performance negatively:
+ */
+ if (!params->pgmap)
+ /* update max_pfn, max_low_pfn and high_memory */
+ update_end_of_memory_vars(start_pfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT);
return ret;
}