diff mbox series

[PATCHv6,10/15] x86/mm: Report unaccepted memory in /proc/meminfo

Message ID 20220517153444.11195-11-kirill.shutemov@linux.intel.com
State New
Headers show
Series mm, x86/cc: Implement support for unaccepted memory | expand

Commit Message

Kirill A. Shutemov May 17, 2022, 3:34 p.m. UTC
Track amount of unaccepted memory and report it in /proc/meminfo.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
 arch/x86/include/asm/set_memory.h        |  2 ++
 arch/x86/include/asm/unaccepted_memory.h |  9 ++++++
 arch/x86/mm/init.c                       |  8 ++++++
 arch/x86/mm/pat/set_memory.c             |  2 +-
 arch/x86/mm/unaccepted_memory.c          | 36 +++++++++++++++++++++++-
 5 files changed, 55 insertions(+), 2 deletions(-)

Comments

David Hildenbrand June 2, 2022, 8:39 a.m. UTC | #1
On 17.05.22 17:34, Kirill A. Shutemov wrote:
> Track amount of unaccepted memory and report it in /proc/meminfo.

I feel like instead of doing this arch specific tracking here, we should
simply report the total number of unaccepted (base) pages in the buddy.

When the system boots up, the number will rise as unaccepted memory gets
exposed to the buddy. But especially once user space is up and running,
that number should only go down.

Once it hits zero, there is no unaccepted memory left in the buddy and
there won't be any performance surprises anymote -- and AFAIKT, that's
what we really care about.
diff mbox series

Patch

diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index 78ca53512486..e467f3941d22 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -86,6 +86,8 @@  bool kernel_page_present(struct page *page);
 
 extern int kernel_set_to_readonly;
 
+void direct_map_meminfo(struct seq_file *m);
+
 #ifdef CONFIG_X86_64
 /*
  * Prevent speculative access to the page by either unmapping
diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h
index 89fc91c61560..d8622d952212 100644
--- a/arch/x86/include/asm/unaccepted_memory.h
+++ b/arch/x86/include/asm/unaccepted_memory.h
@@ -3,7 +3,10 @@ 
 #ifndef _ASM_X86_UNACCEPTED_MEMORY_H
 #define _ASM_X86_UNACCEPTED_MEMORY_H
 
+#include <linux/types.h>
+
 struct boot_params;
+struct seq_file;
 
 void process_unaccepted_memory(struct boot_params *params, u64 start, u64 num);
 
@@ -12,5 +15,11 @@  void process_unaccepted_memory(struct boot_params *params, u64 start, u64 num);
 void accept_memory(phys_addr_t start, phys_addr_t end);
 bool range_contains_unaccepted_memory(phys_addr_t start, phys_addr_t end);
 
+void unaccepted_meminfo(struct seq_file *m);
+
+#else
+
+static inline void unaccepted_meminfo(struct seq_file *m) {}
+
 #endif
 #endif
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index d8cfce221275..7e92a9d93994 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -1065,3 +1065,11 @@  unsigned long max_swapfile_size(void)
 	return pages;
 }
 #endif
+
+#ifdef CONFIG_PROC_FS
+void arch_report_meminfo(struct seq_file *m)
+{
+	direct_map_meminfo(m);
+	unaccepted_meminfo(m);
+}
+#endif
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index 0656db33574d..f08881c4b8ee 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -105,7 +105,7 @@  static void split_page_count(int level)
 	direct_pages_count[level - 1] += PTRS_PER_PTE;
 }
 
-void arch_report_meminfo(struct seq_file *m)
+void direct_map_meminfo(struct seq_file *m)
 {
 	seq_printf(m, "DirectMap4k:    %8lu kB\n",
 			direct_pages_count[PG_LEVEL_4K] << 2);
diff --git a/arch/x86/mm/unaccepted_memory.c b/arch/x86/mm/unaccepted_memory.c
index 33bf70592a46..1ca71eb98c24 100644
--- a/arch/x86/mm/unaccepted_memory.c
+++ b/arch/x86/mm/unaccepted_memory.c
@@ -2,14 +2,17 @@ 
 #include <linux/memblock.h>
 #include <linux/mm.h>
 #include <linux/pfn.h>
+#include <linux/seq_file.h>
 #include <linux/spinlock.h>
 
+#include <asm/e820/api.h>
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/unaccepted_memory.h>
 
-/* Protects unaccepted memory bitmap */
+/* Protects unaccepted memory bitmap and nr_unaccepted */
 static DEFINE_SPINLOCK(unaccepted_memory_lock);
+static unsigned long nr_unaccepted;
 
 void accept_memory(phys_addr_t start, phys_addr_t end)
 {
@@ -63,6 +66,12 @@  void accept_memory(phys_addr_t start, phys_addr_t end)
 		/* Platform-specific memory-acceptance call goes here */
 		panic("Cannot accept memory: unknown platform\n");
 		bitmap_clear(bitmap, range_start, len);
+
+		/* In early boot nr_unaccepted is not yet initialized */
+		if (nr_unaccepted) {
+			WARN_ON(nr_unaccepted < len);
+			nr_unaccepted -= len;
+		}
 	}
 	spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
 }
@@ -90,3 +99,28 @@  bool range_contains_unaccepted_memory(phys_addr_t start, phys_addr_t end)
 
 	return ret;
 }
+
+void unaccepted_meminfo(struct seq_file *m)
+{
+	seq_printf(m, "UnacceptedMem:  %8lu kB\n",
+		   (READ_ONCE(nr_unaccepted) * PMD_SIZE) >> 10);
+}
+
+static int __init unaccepted_init(void)
+{
+	unsigned long *unaccepted_memory;
+	unsigned long flags, bitmap_size;
+
+	if (!boot_params.unaccepted_memory)
+		return 0;
+
+	bitmap_size = e820__end_of_ram_pfn() * PAGE_SIZE / PMD_SIZE;
+	unaccepted_memory = __va(boot_params.unaccepted_memory);
+
+	spin_lock_irqsave(&unaccepted_memory_lock, flags);
+	nr_unaccepted = bitmap_weight(unaccepted_memory, bitmap_size);
+	spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
+
+	return 0;
+}
+fs_initcall(unaccepted_init);