mem_detect.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /*
  2. * Copyright IBM Corp. 2008, 2009
  3. *
  4. * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/module.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 ADDR2G (1ULL << 31)
  16. #define CHUNK_READ_WRITE 0
  17. #define CHUNK_READ_ONLY 1
  18. static inline void memblock_physmem_add(phys_addr_t start, phys_addr_t size)
  19. {
  20. memblock_add_range(&memblock.memory, start, size, 0, 0);
  21. memblock_add_range(&memblock.physmem, start, size, 0, 0);
  22. }
  23. void __init detect_memory_memblock(void)
  24. {
  25. unsigned long long memsize, rnmax, rzm;
  26. unsigned long addr, size;
  27. int type;
  28. rzm = sclp_get_rzm();
  29. rnmax = sclp_get_rnmax();
  30. memsize = rzm * rnmax;
  31. if (!rzm)
  32. rzm = 1ULL << 17;
  33. if (IS_ENABLED(CONFIG_32BIT)) {
  34. rzm = min(ADDR2G, rzm);
  35. memsize = min(ADDR2G, memsize);
  36. }
  37. max_physmem_end = memsize;
  38. addr = 0;
  39. /* keep memblock lists close to the kernel */
  40. memblock_set_bottom_up(true);
  41. do {
  42. size = 0;
  43. type = tprot(addr);
  44. do {
  45. size += rzm;
  46. if (max_physmem_end && addr + size >= max_physmem_end)
  47. break;
  48. } while (type == tprot(addr + size));
  49. if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
  50. if (max_physmem_end && (addr + size > max_physmem_end))
  51. size = max_physmem_end - addr;
  52. memblock_physmem_add(addr, size);
  53. }
  54. addr += size;
  55. } while (addr < max_physmem_end);
  56. memblock_set_bottom_up(false);
  57. if (!max_physmem_end)
  58. max_physmem_end = memblock_end_of_DRAM();
  59. }