memblock.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #include <linux/kernel.h>
  2. #include <linux/types.h>
  3. #include <linux/init.h>
  4. #include <linux/bitops.h>
  5. #include <linux/memblock.h>
  6. #include <linux/bootmem.h>
  7. #include <linux/mm.h>
  8. #include <linux/range.h>
  9. void __init memblock_x86_reserve_range(u64 start, u64 end, char *name)
  10. {
  11. if (start == end)
  12. return;
  13. if (WARN_ONCE(start > end, "memblock_x86_reserve_range: wrong range [%#llx, %#llx)\n", start, end))
  14. return;
  15. memblock_dbg(" memblock_x86_reserve_range: [%#010llx-%#010llx] %16s\n", start, end - 1, name);
  16. memblock_reserve(start, end - start);
  17. }
  18. void __init memblock_x86_free_range(u64 start, u64 end)
  19. {
  20. if (start == end)
  21. return;
  22. if (WARN_ONCE(start > end, "memblock_x86_free_range: wrong range [%#llx, %#llx)\n", start, end))
  23. return;
  24. memblock_dbg(" memblock_x86_free_range: [%#010llx-%#010llx]\n", start, end - 1);
  25. memblock_free(start, end - start);
  26. }
  27. /*
  28. * Finds an active region in the address range from start_pfn to last_pfn and
  29. * returns its range in ei_startpfn and ei_endpfn for the memblock entry.
  30. */
  31. static int __init memblock_x86_find_active_region(const struct memblock_region *ei,
  32. unsigned long start_pfn,
  33. unsigned long last_pfn,
  34. unsigned long *ei_startpfn,
  35. unsigned long *ei_endpfn)
  36. {
  37. u64 align = PAGE_SIZE;
  38. *ei_startpfn = round_up(ei->base, align) >> PAGE_SHIFT;
  39. *ei_endpfn = round_down(ei->base + ei->size, align) >> PAGE_SHIFT;
  40. /* Skip map entries smaller than a page */
  41. if (*ei_startpfn >= *ei_endpfn)
  42. return 0;
  43. /* Skip if map is outside the node */
  44. if (*ei_endpfn <= start_pfn || *ei_startpfn >= last_pfn)
  45. return 0;
  46. /* Check for overlaps */
  47. if (*ei_startpfn < start_pfn)
  48. *ei_startpfn = start_pfn;
  49. if (*ei_endpfn > last_pfn)
  50. *ei_endpfn = last_pfn;
  51. return 1;
  52. }
  53. /*
  54. * Find the hole size (in bytes) in the memory range.
  55. * @start: starting address of the memory range to scan
  56. * @end: ending address of the memory range to scan
  57. */
  58. u64 __init memblock_x86_hole_size(u64 start, u64 end)
  59. {
  60. unsigned long start_pfn = start >> PAGE_SHIFT;
  61. unsigned long last_pfn = end >> PAGE_SHIFT;
  62. unsigned long ei_startpfn, ei_endpfn, ram = 0;
  63. struct memblock_region *r;
  64. for_each_memblock(memory, r)
  65. if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
  66. &ei_startpfn, &ei_endpfn))
  67. ram += ei_endpfn - ei_startpfn;
  68. return end - start - ((u64)ram << PAGE_SHIFT);
  69. }