mem_detect.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_S390_MEM_DETECT_H
  3. #define _ASM_S390_MEM_DETECT_H
  4. #include <linux/types.h>
  5. enum mem_info_source {
  6. MEM_DETECT_NONE = 0,
  7. MEM_DETECT_SCLP_STOR_INFO,
  8. MEM_DETECT_DIAG260,
  9. MEM_DETECT_SCLP_READ_INFO,
  10. MEM_DETECT_BIN_SEARCH
  11. };
  12. struct mem_detect_block {
  13. u64 start;
  14. u64 end;
  15. };
  16. /*
  17. * Storage element id is defined as 1 byte (up to 256 storage elements).
  18. * In practise only storage element id 0 and 1 are used).
  19. * According to architecture one storage element could have as much as
  20. * 1020 subincrements. 255 mem_detect_blocks are embedded in mem_detect_info.
  21. * If more mem_detect_blocks are required, a block of memory from already
  22. * known mem_detect_block is taken (entries_extended points to it).
  23. */
  24. #define MEM_INLINED_ENTRIES 255 /* (PAGE_SIZE - 16) / 16 */
  25. struct mem_detect_info {
  26. u32 count;
  27. u8 info_source;
  28. struct mem_detect_block entries[MEM_INLINED_ENTRIES];
  29. struct mem_detect_block *entries_extended;
  30. };
  31. extern struct mem_detect_info mem_detect;
  32. void add_mem_detect_block(u64 start, u64 end);
  33. static inline int __get_mem_detect_block(u32 n, unsigned long *start,
  34. unsigned long *end)
  35. {
  36. if (n >= mem_detect.count) {
  37. *start = 0;
  38. *end = 0;
  39. return -1;
  40. }
  41. if (n < MEM_INLINED_ENTRIES) {
  42. *start = (unsigned long)mem_detect.entries[n].start;
  43. *end = (unsigned long)mem_detect.entries[n].end;
  44. } else {
  45. *start = (unsigned long)mem_detect.entries_extended[n - MEM_INLINED_ENTRIES].start;
  46. *end = (unsigned long)mem_detect.entries_extended[n - MEM_INLINED_ENTRIES].end;
  47. }
  48. return 0;
  49. }
  50. /**
  51. * for_each_mem_detect_block - early online memory range iterator
  52. * @i: an integer used as loop variable
  53. * @p_start: ptr to unsigned long for start address of the range
  54. * @p_end: ptr to unsigned long for end address of the range
  55. *
  56. * Walks over detected online memory ranges.
  57. */
  58. #define for_each_mem_detect_block(i, p_start, p_end) \
  59. for (i = 0, __get_mem_detect_block(i, p_start, p_end); \
  60. i < mem_detect.count; \
  61. i++, __get_mem_detect_block(i, p_start, p_end))
  62. static inline void get_mem_detect_reserved(unsigned long *start,
  63. unsigned long *size)
  64. {
  65. *start = (unsigned long)mem_detect.entries_extended;
  66. if (mem_detect.count > MEM_INLINED_ENTRIES)
  67. *size = (mem_detect.count - MEM_INLINED_ENTRIES) * sizeof(struct mem_detect_block);
  68. else
  69. *size = 0;
  70. }
  71. static inline unsigned long get_mem_detect_end(void)
  72. {
  73. unsigned long start;
  74. unsigned long end;
  75. if (mem_detect.count) {
  76. __get_mem_detect_block(mem_detect.count - 1, &start, &end);
  77. return end;
  78. }
  79. return 0;
  80. }
  81. #endif