120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. From: Tobias Wolf <dev-NTEO@vplace.de>
  2. Subject: mm: Fix alloc_node_mem_map with ARCH_PFN_OFFSET calculation
  3. An rt288x (ralink) based router (Belkin F5D8235 v1) does not boot with any
  4. kernel beyond version 4.3 resulting in:
  5. BUG: Bad page state in process swapper pfn:086ac
  6. bisect resulted in:
  7. a1c34a3bf00af2cede839879502e12dc68491ad5 is the first bad commit
  8. commit a1c34a3bf00af2cede839879502e12dc68491ad5
  9. Author: Laura Abbott <laura@labbott.name>
  10. Date: Thu Nov 5 18:48:46 2015 -0800
  11. mm: Don't offset memmap for flatmem
  12. Srinivas Kandagatla reported bad page messages when trying to remove the
  13. bottom 2MB on an ARM based IFC6410 board
  14. BUG: Bad page state in process swapper pfn:fffa8
  15. page:ef7fb500 count:0 mapcount:0 mapping: (null) index:0x0
  16. flags: 0x96640253(locked|error|dirty|active|arch_1|reclaim|mlocked)
  17. page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
  18. bad because of flags:
  19. flags: 0x200041(locked|active|mlocked)
  20. Modules linked in:
  21. CPU: 0 PID: 0 Comm: swapper Not tainted 3.19.0-rc3-00007-g412f9ba-dirty
  22. #816
  23. Hardware name: Qualcomm (Flattened Device Tree)
  24. unwind_backtrace
  25. show_stack
  26. dump_stack
  27. bad_page
  28. free_pages_prepare
  29. free_hot_cold_page
  30. __free_pages
  31. free_highmem_page
  32. mem_init
  33. start_kernel
  34. Disabling lock debugging due to kernel taint
  35. [...]
  36. :040000 040000 2de013c372345fd471cd58f0553c9b38b0ef1cc4
  37. 0a8156f848733dfa21e16c196dfb6c0a76290709 M mm
  38. This fix for ARM does not account ARCH_PFN_OFFSET for mem_map as later used by
  39. page_to_pfn anymore.
  40. The following output was generated with two hacked in printk statements:
  41. printk("before %p vs. %p or %p\n", mem_map, mem_map - offset, mem_map -
  42. (pgdat->node_start_pfn - ARCH_PFN_OFFSET));
  43. if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
  44. mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET);
  45. printk("after %p\n", mem_map);
  46. Output:
  47. [ 0.000000] before 8861b280 vs. 8861b280 or 8851b280
  48. [ 0.000000] after 8851b280
  49. As seen in the first line mem_map with subtraction of offset does not equal the
  50. mem_map after subtraction of ARCH_PFN_OFFSET.
  51. After adding the offset of ARCH_PFN_OFFSET as well to mem_map as the
  52. previously calculated offset is zero for the named platform it is able to boot
  53. 4.4 and 4.9-rc7 again.
  54. Signed-off-by: Tobias Wolf <dev-NTEO@vplace.de>
  55. ---
  56. --- a/mm/page_alloc.c
  57. +++ b/mm/page_alloc.c
  58. @@ -6213,7 +6213,7 @@ static void __ref alloc_node_mem_map(str
  59. mem_map = NODE_DATA(0)->node_mem_map;
  60. #if defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) || defined(CONFIG_FLATMEM)
  61. if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
  62. - mem_map -= offset;
  63. + mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET);
  64. #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
  65. }
  66. #endif