Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _ASM_S390_MEM_DETECT_H
0003 #define _ASM_S390_MEM_DETECT_H
0004 
0005 #include <linux/types.h>
0006 
0007 enum mem_info_source {
0008     MEM_DETECT_NONE = 0,
0009     MEM_DETECT_SCLP_STOR_INFO,
0010     MEM_DETECT_DIAG260,
0011     MEM_DETECT_SCLP_READ_INFO,
0012     MEM_DETECT_BIN_SEARCH
0013 };
0014 
0015 struct mem_detect_block {
0016     u64 start;
0017     u64 end;
0018 };
0019 
0020 /*
0021  * Storage element id is defined as 1 byte (up to 256 storage elements).
0022  * In practise only storage element id 0 and 1 are used).
0023  * According to architecture one storage element could have as much as
0024  * 1020 subincrements. 255 mem_detect_blocks are embedded in mem_detect_info.
0025  * If more mem_detect_blocks are required, a block of memory from already
0026  * known mem_detect_block is taken (entries_extended points to it).
0027  */
0028 #define MEM_INLINED_ENTRIES 255 /* (PAGE_SIZE - 16) / 16 */
0029 
0030 struct mem_detect_info {
0031     u32 count;
0032     u8 info_source;
0033     struct mem_detect_block entries[MEM_INLINED_ENTRIES];
0034     struct mem_detect_block *entries_extended;
0035 };
0036 extern struct mem_detect_info mem_detect;
0037 
0038 void add_mem_detect_block(u64 start, u64 end);
0039 
0040 static inline int __get_mem_detect_block(u32 n, unsigned long *start,
0041                      unsigned long *end)
0042 {
0043     if (n >= mem_detect.count) {
0044         *start = 0;
0045         *end = 0;
0046         return -1;
0047     }
0048 
0049     if (n < MEM_INLINED_ENTRIES) {
0050         *start = (unsigned long)mem_detect.entries[n].start;
0051         *end = (unsigned long)mem_detect.entries[n].end;
0052     } else {
0053         *start = (unsigned long)mem_detect.entries_extended[n - MEM_INLINED_ENTRIES].start;
0054         *end = (unsigned long)mem_detect.entries_extended[n - MEM_INLINED_ENTRIES].end;
0055     }
0056     return 0;
0057 }
0058 
0059 /**
0060  * for_each_mem_detect_block - early online memory range iterator
0061  * @i: an integer used as loop variable
0062  * @p_start: ptr to unsigned long for start address of the range
0063  * @p_end: ptr to unsigned long for end address of the range
0064  *
0065  * Walks over detected online memory ranges.
0066  */
0067 #define for_each_mem_detect_block(i, p_start, p_end)            \
0068     for (i = 0, __get_mem_detect_block(i, p_start, p_end);      \
0069          i < mem_detect.count;                  \
0070          i++, __get_mem_detect_block(i, p_start, p_end))
0071 
0072 static inline void get_mem_detect_reserved(unsigned long *start,
0073                        unsigned long *size)
0074 {
0075     *start = (unsigned long)mem_detect.entries_extended;
0076     if (mem_detect.count > MEM_INLINED_ENTRIES)
0077         *size = (mem_detect.count - MEM_INLINED_ENTRIES) * sizeof(struct mem_detect_block);
0078     else
0079         *size = 0;
0080 }
0081 
0082 static inline unsigned long get_mem_detect_end(void)
0083 {
0084     unsigned long start;
0085     unsigned long end;
0086 
0087     if (mem_detect.count) {
0088         __get_mem_detect_block(mem_detect.count - 1, &start, &end);
0089         return end;
0090     }
0091     return 0;
0092 }
0093 
0094 #endif