summaryrefslogtreecommitdiff
path: root/debian
diff options
context:
space:
mode:
authorThadeu Lima de Souza Cascardo <cascardo@canonical.com>2018-02-15 11:47:15 -0200
committerThadeu Lima de Souza Cascardo <cascardo@debian.org>2018-03-05 12:43:48 -0300
commit2b8fff460b4c32b8ccd263c829c8b8d9e9027202 (patch)
tree07dfdd32f982527613846aa970166a1dcf9a3942 /debian
parent8f3be3b86fffc6ac9eac564f1dba1753590ef109 (diff)
Add support for SPARSEMEM_EXTREME mem_section as a pointer.
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@debian.org>
Diffstat (limited to 'debian')
-rw-r--r--debian/changelog6
-rw-r--r--debian/patches/0003-sparsemem_extreme.patch239
-rw-r--r--debian/patches/series1
3 files changed, 246 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index f1da216..5a2d846 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+makedumpfile (1:1.6.3-2) UNRELEASED; urgency=medium
+
+ * Add support for SPARSEMEM_EXTREME mem_section as a pointer. (LP: #1750021)
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@debian.org> Mon, 05 Mar 2018 09:28:55 -0300
+
makedumpfile (1:1.6.3-1) unstable; urgency=medium
* New upstream release. Main new feature:
diff --git a/debian/patches/0003-sparsemem_extreme.patch b/debian/patches/0003-sparsemem_extreme.patch
new file mode 100644
index 0000000..3345728
--- /dev/null
+++ b/debian/patches/0003-sparsemem_extreme.patch
@@ -0,0 +1,239 @@
+diff --git a/makedumpfile.c b/makedumpfile.c
+index ed138d3..cd3fa4d 100644
+--- a/makedumpfile.c
++++ b/makedumpfile.c
+@@ -3297,7 +3297,7 @@ get_mm_discontigmem(void)
+ return TRUE;
+ }
+
+-unsigned long
++static unsigned long
+ nr_to_section(unsigned long nr, unsigned long *mem_sec)
+ {
+ unsigned long addr;
+@@ -3311,17 +3311,17 @@ nr_to_section(unsigned long nr, unsigned long *mem_sec)
+ addr = SYMBOL(mem_section) + (nr * SIZE(mem_section));
+ }
+
+- if (!is_kvaddr(addr))
+- return NOT_KV_ADDR;
+-
+ return addr;
+ }
+
+-unsigned long
+-section_mem_map_addr(unsigned long addr)
++static unsigned long
++section_mem_map_addr(unsigned long addr, unsigned long *map_mask)
+ {
+ char *mem_section;
+ unsigned long map;
++ unsigned long mask;
++
++ *map_mask = 0;
+
+ if (!is_kvaddr(addr))
+ return NOT_KV_ADDR;
+@@ -3338,15 +3338,19 @@ section_mem_map_addr(unsigned long addr)
+ }
+ map = ULONG(mem_section + OFFSET(mem_section.section_mem_map));
+ if (info->kernel_version < KERNEL_VERSION(4, 13, 0))
+- map &= SECTION_MAP_MASK_4_12;
++ mask = SECTION_MAP_MASK_4_12;
+ else
+- map &= SECTION_MAP_MASK;
++ mask = SECTION_MAP_MASK;
++ *map_mask = map & ~mask;
++ if (map == 0x0)
++ *map_mask |= SECTION_MARKED_PRESENT;
++ map &= mask;
+ free(mem_section);
+
+ return map;
+ }
+
+-unsigned long
++static unsigned long
+ sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long section_nr)
+ {
+ unsigned long mem_map;
+@@ -3354,17 +3358,110 @@ sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long section_nr)
+ mem_map = coded_mem_map +
+ (SECTION_NR_TO_PFN(section_nr) * SIZE(page));
+
+- if (!is_kvaddr(mem_map))
+- return NOT_KV_ADDR;
+ return mem_map;
+ }
++
++/*
++ * On some kernels, mem_section may be a pointer or an array, when
++ * SPARSEMEM_EXTREME is on.
++ *
++ * We assume that section_mem_map is either 0 or has the present bit set.
++ *
++ */
++
++static int
++validate_mem_section(unsigned long *mem_sec,
++ unsigned long mem_section_ptr, unsigned int mem_section_size,
++ unsigned long *mem_maps, unsigned int num_section)
++{
++ unsigned int section_nr;
++ unsigned long map_mask;
++ unsigned long section, mem_map;
++ if (!readmem(VADDR, mem_section_ptr, mem_sec, mem_section_size)) {
++ ERRMSG("Can't read mem_section array.\n");
++ return FALSE;
++ }
++ for (section_nr = 0; section_nr < num_section; section_nr++) {
++ section = nr_to_section(section_nr, mem_sec);
++ if (section == NOT_KV_ADDR) {
++ mem_map = NOT_MEMMAP_ADDR;
++ } else {
++ mem_map = section_mem_map_addr(section, &map_mask);
++ if (!(map_mask & SECTION_MARKED_PRESENT)) {
++ return FALSE;
++ }
++ if (mem_map == 0) {
++ mem_map = NOT_MEMMAP_ADDR;
++ } else {
++ mem_map = sparse_decode_mem_map(mem_map,
++ section_nr);
++ if (!is_kvaddr(mem_map)) {
++ return FALSE;
++ }
++ }
++ }
++ mem_maps[section_nr] = mem_map;
++ }
++ return TRUE;
++}
++
++static int
++get_mem_section(unsigned int mem_section_size, unsigned long *mem_maps,
++ unsigned int num_section)
++{
++ unsigned long mem_section_ptr;
++ int ret = FALSE;
++ unsigned long *mem_sec = NULL;
++
++ if ((mem_sec = malloc(mem_section_size)) == NULL) {
++ ERRMSG("Can't allocate memory for the mem_section. %s\n",
++ strerror(errno));
++ return FALSE;
++ }
++ ret = validate_mem_section(mem_sec, SYMBOL(mem_section),
++ mem_section_size, mem_maps, num_section);
++
++ if (is_sparsemem_extreme()) {
++ int symbol_valid = ret;
++ int pointer_valid;
++ int mem_maps_size = sizeof(*mem_maps) * num_section;
++ unsigned long *mem_maps_ex = NULL;
++ if (!readmem(VADDR, SYMBOL(mem_section), &mem_section_ptr,
++ sizeof(mem_section_ptr)))
++ goto out;
++
++ if ((mem_maps_ex = malloc(mem_maps_size)) == NULL) {
++ ERRMSG("Can't allocate memory for the mem_maps. %s\n",
++ strerror(errno));
++ goto out;
++ }
++
++ pointer_valid = validate_mem_section(mem_sec,
++ mem_section_ptr,
++ mem_section_size,
++ mem_maps_ex,
++ num_section);
++ if (pointer_valid)
++ memcpy(mem_maps, mem_maps_ex, mem_maps_size);
++ if (mem_maps_ex)
++ free(mem_maps_ex);
++ ret = symbol_valid ^ pointer_valid;
++ if (!ret) {
++ ERRMSG("Could not validate mem_section.\n");
++ }
++ }
++out:
++ if (mem_sec != NULL)
++ free(mem_sec);
++ return ret;
++}
++
+ int
+ get_mm_sparsemem(void)
+ {
+ unsigned int section_nr, mem_section_size, num_section;
+ mdf_pfn_t pfn_start, pfn_end;
+- unsigned long section, mem_map;
+- unsigned long *mem_sec = NULL;
++ unsigned long *mem_maps = NULL;
+
+ int ret = FALSE;
+
+@@ -3379,13 +3476,12 @@ get_mm_sparsemem(void)
+ info->sections_per_root = _SECTIONS_PER_ROOT();
+ mem_section_size = SIZE(mem_section) * NR_SECTION_ROOTS();
+ }
+- if ((mem_sec = malloc(mem_section_size)) == NULL) {
+- ERRMSG("Can't allocate memory for the mem_section. %s\n",
+- strerror(errno));
++ if ((mem_maps = malloc(sizeof(*mem_maps) * num_section)) == NULL) {
++ ERRMSG("Can't allocate memory for the mem_maps. %s\n",
++ strerror(errno));
+ return FALSE;
+ }
+- if (!readmem(VADDR, SYMBOL(mem_section), mem_sec,
+- mem_section_size)) {
++ if (!get_mem_section(mem_section_size, mem_maps, num_section)) {
+ ERRMSG("Can't get the address of mem_section.\n");
+ goto out;
+ }
+@@ -3397,31 +3493,16 @@ get_mm_sparsemem(void)
+ goto out;
+ }
+ for (section_nr = 0; section_nr < num_section; section_nr++) {
+- section = nr_to_section(section_nr, mem_sec);
+- if (section == NOT_KV_ADDR) {
+- mem_map = NOT_MEMMAP_ADDR;
+- } else {
+- mem_map = section_mem_map_addr(section);
+- if (mem_map == 0) {
+- mem_map = NOT_MEMMAP_ADDR;
+- } else {
+- mem_map = sparse_decode_mem_map(mem_map,
+- section_nr);
+- if (!is_kvaddr(mem_map))
+- mem_map = NOT_MEMMAP_ADDR;
+- }
+- }
+ pfn_start = section_nr * PAGES_PER_SECTION();
+ pfn_end = pfn_start + PAGES_PER_SECTION();
+ if (info->max_mapnr < pfn_end)
+ pfn_end = info->max_mapnr;
+- dump_mem_map(pfn_start, pfn_end, mem_map, section_nr);
++ dump_mem_map(pfn_start, pfn_end, mem_maps[section_nr], section_nr);
+ }
+ ret = TRUE;
+ out:
+- if (mem_sec != NULL)
+- free(mem_sec);
+-
++ if (mem_maps != NULL)
++ free(mem_maps);
+ return ret;
+ }
+
+diff --git a/makedumpfile.h b/makedumpfile.h
+index 01eece2..58e1aaa 100644
+--- a/makedumpfile.h
++++ b/makedumpfile.h
+@@ -184,6 +184,7 @@ isAnon(unsigned long mapping)
+ #define SECTIONS_PER_ROOT() (info->sections_per_root)
+ #define SECTION_ROOT_MASK() (SECTIONS_PER_ROOT() - 1)
+ #define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT())
++#define SECTION_MARKED_PRESENT (1UL<<0)
+ #define SECTION_IS_ONLINE (1UL<<2)
+ #define SECTION_MAP_LAST_BIT (1UL<<3)
+ #define SECTION_MAP_MASK_4_12 (~(SECTION_IS_ONLINE-1))
diff --git a/debian/patches/series b/debian/patches/series
index 8d0f986..042bad4 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,3 @@
0001-Remove-libebl-linkage.patch
0002-adapt-makefile-to-debian.patch
+0003-sparsemem_extreme.patch