mem_detect.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright IBM Corp. 2008, 2009
  4. *
  5. * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/memblock.h>
  9. #include <linux/init.h>
  10. #include <linux/debugfs.h>
  11. #include <linux/seq_file.h>
  12. #include <asm/ipl.h>
  13. #include <asm/sclp.h>
  14. #include <asm/setup.h>
  15. #define CHUNK_READ_WRITE 0
  16. #define CHUNK_READ_ONLY 1
  17. static inline void memblock_physmem_add(phys_addr_t start, phys_addr_t size)
  18. {
  19. memblock_dbg("memblock_physmem_add: [%#016llx-%#016llx]\n",
  20. start, start + size - 1);
  21. memblock_add_range(&memblock.memory, start, size, 0, 0);
  22. memblock_add_range(&memblock.physmem, start, size, 0, 0);
  23. }
  24. void __init detect_memory_memblock(void)
  25. {
  26. unsigned long memsize, rnmax, rzm, addr, size;
  27. int type;
  28. rzm = sclp.rzm;
  29. rnmax = sclp.rnmax;
  30. memsize = rzm * rnmax;
  31. if (!rzm)
  32. rzm = 1UL << 17;
  33. max_physmem_end = memsize;
  34. addr = 0;
  35. /* keep memblock lists close to the kernel */
  36. memblock_set_bottom_up(true);
  37. do {
  38. size = 0;
  39. /* assume lowcore is writable */
  40. type = addr ? tprot(addr) : CHUNK_READ_WRITE;
  41. do {
  42. size += rzm;
  43. if (max_physmem_end && addr + size >= max_physmem_end)
  44. break;
  45. } while (type == tprot(addr + size));
  46. if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
  47. if (max_physmem_end && (addr + size > max_physmem_end))
  48. size = max_physmem_end - addr;
  49. memblock_physmem_add(addr, size);
  50. }
  51. addr += size;
  52. } while (addr < max_physmem_end);
  53. memblock_set_bottom_up(false);
  54. if (!max_physmem_end)
  55. max_physmem_end = memblock_end_of_DRAM();
  56. memblock_dump_all();
  57. }