[RFC V2 04/37] dmem: let pat recognize dmem

From: yulei . kernel
Date: Mon Dec 07 2020 - 06:34:26 EST


From: Yulei Zhang <yuleixzhang@xxxxxxxxxxx>

x86 pat uses 'struct page' by only checking if it's system ram,
however it is not true if dmem is used, let's teach pat to
recognize this case if it is ram but it is !pfn_valid()

We always use WB for dmem and any attempt to change this
behavior will be rejected and WARN_ON is triggered

Signed-off-by: Xiao Guangrong <gloryxiao@xxxxxxxxxxx>
Signed-off-by: Yulei Zhang <yuleixzhang@xxxxxxxxxxx>
---
arch/x86/mm/pat/memtype.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/arch/x86/mm/pat/memtype.c b/arch/x86/mm/pat/memtype.c
index 8f665c3..fd8a298 100644
--- a/arch/x86/mm/pat/memtype.c
+++ b/arch/x86/mm/pat/memtype.c
@@ -511,6 +511,13 @@ static int reserve_ram_pages_type(u64 start, u64 end,
for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
enum page_cache_mode type;

+ /*
+ * it's dmem if it's ram but not 'struct page' backend,
+ * we always use WB
+ */
+ if (WARN_ON(!pfn_valid(pfn)))
+ return -EBUSY;
+
page = pfn_to_page(pfn);
type = get_page_memtype(page);
if (type != _PAGE_CACHE_MODE_WB) {
@@ -539,6 +546,13 @@ static int free_ram_pages_type(u64 start, u64 end)
u64 pfn;

for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
+ /*
+ * it's dmem, see the comments in
+ * reserve_ram_pages_type()
+ */
+ if (WARN_ON(!pfn_valid(pfn)))
+ continue;
+
page = pfn_to_page(pfn);
set_page_memtype(page, _PAGE_CACHE_MODE_WB);
}
@@ -714,6 +728,13 @@ static enum page_cache_mode lookup_memtype(u64 paddr)
if (pat_pagerange_is_ram(paddr, paddr + PAGE_SIZE)) {
struct page *page;

+ /*
+ * dmem always uses WB, see the comments in
+ * reserve_ram_pages_type()
+ */
+ if (!pfn_valid(paddr >> PAGE_SHIFT))
+ return rettype;
+
page = pfn_to_page(paddr >> PAGE_SHIFT);
return get_page_memtype(page);
}
--
1.8.3.1