The crashed kernel passes usable RAM info through pt_loads[], but the
current code ignore this, and parse all sections below info->max_mapnr.
Refer to code in get_mm_sparsemem()
  num_section = divideup(info->max_mapnr, PAGES_PER_SECTION());

These ranges can include unwanted memory e.g. reserved-memory for crash
kernel, PMEM for fs-dax. Excluding them by setting mem_maps[section_nr]=NULL.

Signed-off-by: Pingfan Liu <[email protected]>
---
 elf_info.c     | 12 ++++++++++++
 elf_info.h     |  1 +
 makedumpfile.c |  5 +++++
 3 files changed, 18 insertions(+)

diff --git a/elf_info.c b/elf_info.c
index 7d72742..297c3e4 100644
--- a/elf_info.c
+++ b/elf_info.c
@@ -1302,3 +1302,15 @@ get_max_file_offset(void)
 {
        return max_file_offset;
 }
+
+int phyaddr_in_pt_loads(unsigned long long phys_start)
+{
+        struct pt_load_segment *pls;
+
+       for (int i = 0; i < num_pt_loads; i++) {
+               pls = &pt_loads[i];
+               if (phys_start >= pls->phys_start && phys_start < pls->phys_end)
+                       return TRUE;
+       }
+       return FALSE;
+}
diff --git a/elf_info.h b/elf_info.h
index 934b608..f5bb07c 100644
--- a/elf_info.h
+++ b/elf_info.h
@@ -90,6 +90,7 @@ void get_eraseinfo(off_t *offset, unsigned long *size);
 void set_eraseinfo(off_t offset, unsigned long size);
 
 off_t get_max_file_offset(void);
+int phyaddr_in_pt_loads(unsigned long long phys_start);
 
 #endif  /* ELF_INFO_H */
 
diff --git a/makedumpfile.c b/makedumpfile.c
index f5860a1..c0fa075 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -3556,8 +3556,13 @@ get_mm_sparsemem(void)
                goto out;
        }
        for (section_nr = 0; section_nr < num_section; section_nr++) {
+               unsigned long phys_start;
+
                pfn_start = section_nr * PAGES_PER_SECTION();
                pfn_end   = pfn_start + PAGES_PER_SECTION();
+               phys_start = pfn_start << PAGESHIFT();
+               if (!phyaddr_in_pt_loads(phys_start))
+                       mem_maps[section_nr] = (unsigned long)NULL;
                if (info->max_mapnr < pfn_end)
                        pfn_end = info->max_mapnr;
                dump_mem_map(pfn_start, pfn_end, mem_maps[section_nr], 
section_nr);
-- 
2.7.5


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to