Linux 内核显示 "WARNING: at arch/x86/mm/pageattr.c:962 change_page_attr_set_clr" 没有解释

Linux kernel shows "WARNING: at arch/x86/mm/pageattr.c:962 change_page_attr_set_clr" without explanation

我正在编写一个针对 Linux v3-v4 的 x86_64 内核模块,它在内核符号的地址上使用 set_memory_rw()。虽然通话有效,但我收到了一条没有任何解释的警告:

[  596.183643] ------------[ cut here ]------------
[  596.183667] WARNING: at arch/x86/mm/pageattr.c:962 change_page_attr_set_clr+0x2ca/0x450()

以前我使用的是另一种方法,先调用 virt_to_page(),然后再调用 set_pages_rw()。然而,正如内核源代码所述,这是一个已弃用的 API,它建议使用 set_memory_rw() 而不是

These APIs should be considered deprecated and are likely going to be removed in the future. [...] Specifically, many users of the old APIs had a virtual address, called virt_to_page() or vmalloc_to_page() on that address to get a struct page* that the old API required. To convert these cases, use set_memory_*() on the original virtual address, do not use these functions.

谁能解释一下这是什么问题?
我想我正在绊倒 this check,这表明我可以添加 *addr &= PAGE_MASK;,但我不想盲目地这样做。

I think I'm tripping this check, which suggests I can just add *addr &= PAGE_MASK; but I don't want to do it blindly.

我觉得不错(这极有可能是“地址未与页面边界对齐”的问题;而且极有可能不想盲目这样做是个好主意)。

可能的情况是您有一个您关心的地址范围(而不是一个页面范围);这就是你如何解决这个问题的。这意味着:

a) 计算 numpages 时要小心(例如,原始范围可能类似于“4 个字节,一页末尾有 2 个字节,下一页开头有 2 个字节页”)。正确的做法是将“起始地址”向下取整(pg = start_address & PAGE_MASK;),将“结束地址”向上取整(end_page = ((start_address + size_in_bytes - 1) | ~PAGE_MASK) + 1;),然后计算页数(numpages = end_page - pg)。

b) 在同一 page/s 中可能还有其他您不想使用新页面属性的内容。如果是这样,那么你就有了一个基本的设计问题。