mem_detect.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  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 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_add_range(&memblock.memory, start, size, 0, 0);
  20. memblock_add_range(&memblock.physmem, start, size, 0, 0);
  21. }
  22. void __init detect_memory_memblock(void)
  23. {
  24. unsigned long memsize, rnmax, rzm, addr, size;
  25. int type;
  26. rzm = sclp.rzm;
  27. rnmax = sclp.rnmax;
  28. memsize = rzm * rnmax;
  29. if (!rzm)
  30. rzm = 1UL << 17;
  31. max_physmem_end = memsize;
  32. addr = 0;
  33. /* keep memblock lists close to the kernel */
  34. memblock_set_bottom_up(true);
  35. do {
  36. size = 0;
  37. type = tprot(addr);
  38. do {
  39. size += rzm;
  40. if (max_physmem_end && addr + size >= max_physmem_end)
  41. break;
  42. } while (type == tprot(addr + size));
  43. if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
  44. if (max_physmem_end && (addr + size > max_physmem_end))
  45. size = max_physmem_end - addr;
  46. memblock_physmem_add(addr, size);
  47. }
  48. addr += size;
  49. } while (addr < max_physmem_end);
  50. memblock_set_bottom_up(false);
  51. if (!max_physmem_end)
  52. max_physmem_end = memblock_end_of_DRAM();
  53. }