mem_detect.c 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  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. 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. type = tprot(addr);
  40. do {
  41. size += rzm;
  42. if (max_physmem_end && addr + size >= max_physmem_end)
  43. break;
  44. } while (type == tprot(addr + size));
  45. if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
  46. if (max_physmem_end && (addr + size > max_physmem_end))
  47. size = max_physmem_end - addr;
  48. memblock_physmem_add(addr, size);
  49. }
  50. addr += size;
  51. } while (addr < max_physmem_end);
  52. memblock_set_bottom_up(false);
  53. if (!max_physmem_end)
  54. max_physmem_end = memblock_end_of_DRAM();
  55. }