18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_S390_MEM_DETECT_H 38c2ecf20Sopenharmony_ci#define _ASM_S390_MEM_DETECT_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/types.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_cienum mem_info_source { 88c2ecf20Sopenharmony_ci MEM_DETECT_NONE = 0, 98c2ecf20Sopenharmony_ci MEM_DETECT_SCLP_STOR_INFO, 108c2ecf20Sopenharmony_ci MEM_DETECT_DIAG260, 118c2ecf20Sopenharmony_ci MEM_DETECT_SCLP_READ_INFO, 128c2ecf20Sopenharmony_ci MEM_DETECT_BIN_SEARCH 138c2ecf20Sopenharmony_ci}; 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistruct mem_detect_block { 168c2ecf20Sopenharmony_ci u64 start; 178c2ecf20Sopenharmony_ci u64 end; 188c2ecf20Sopenharmony_ci}; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci * Storage element id is defined as 1 byte (up to 256 storage elements). 228c2ecf20Sopenharmony_ci * In practise only storage element id 0 and 1 are used). 238c2ecf20Sopenharmony_ci * According to architecture one storage element could have as much as 248c2ecf20Sopenharmony_ci * 1020 subincrements. 255 mem_detect_blocks are embedded in mem_detect_info. 258c2ecf20Sopenharmony_ci * If more mem_detect_blocks are required, a block of memory from already 268c2ecf20Sopenharmony_ci * known mem_detect_block is taken (entries_extended points to it). 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci#define MEM_INLINED_ENTRIES 255 /* (PAGE_SIZE - 16) / 16 */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct mem_detect_info { 318c2ecf20Sopenharmony_ci u32 count; 328c2ecf20Sopenharmony_ci u8 info_source; 338c2ecf20Sopenharmony_ci struct mem_detect_block entries[MEM_INLINED_ENTRIES]; 348c2ecf20Sopenharmony_ci struct mem_detect_block *entries_extended; 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ciextern struct mem_detect_info mem_detect; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_civoid add_mem_detect_block(u64 start, u64 end); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic inline int __get_mem_detect_block(u32 n, unsigned long *start, 418c2ecf20Sopenharmony_ci unsigned long *end) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci if (n >= mem_detect.count) { 448c2ecf20Sopenharmony_ci *start = 0; 458c2ecf20Sopenharmony_ci *end = 0; 468c2ecf20Sopenharmony_ci return -1; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci if (n < MEM_INLINED_ENTRIES) { 508c2ecf20Sopenharmony_ci *start = (unsigned long)mem_detect.entries[n].start; 518c2ecf20Sopenharmony_ci *end = (unsigned long)mem_detect.entries[n].end; 528c2ecf20Sopenharmony_ci } else { 538c2ecf20Sopenharmony_ci *start = (unsigned long)mem_detect.entries_extended[n - MEM_INLINED_ENTRIES].start; 548c2ecf20Sopenharmony_ci *end = (unsigned long)mem_detect.entries_extended[n - MEM_INLINED_ENTRIES].end; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci return 0; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/** 608c2ecf20Sopenharmony_ci * for_each_mem_detect_block - early online memory range iterator 618c2ecf20Sopenharmony_ci * @i: an integer used as loop variable 628c2ecf20Sopenharmony_ci * @p_start: ptr to unsigned long for start address of the range 638c2ecf20Sopenharmony_ci * @p_end: ptr to unsigned long for end address of the range 648c2ecf20Sopenharmony_ci * 658c2ecf20Sopenharmony_ci * Walks over detected online memory ranges. 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ci#define for_each_mem_detect_block(i, p_start, p_end) \ 688c2ecf20Sopenharmony_ci for (i = 0, __get_mem_detect_block(i, p_start, p_end); \ 698c2ecf20Sopenharmony_ci i < mem_detect.count; \ 708c2ecf20Sopenharmony_ci i++, __get_mem_detect_block(i, p_start, p_end)) 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic inline void get_mem_detect_reserved(unsigned long *start, 738c2ecf20Sopenharmony_ci unsigned long *size) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci *start = (unsigned long)mem_detect.entries_extended; 768c2ecf20Sopenharmony_ci if (mem_detect.count > MEM_INLINED_ENTRIES) 778c2ecf20Sopenharmony_ci *size = (mem_detect.count - MEM_INLINED_ENTRIES) * sizeof(struct mem_detect_block); 788c2ecf20Sopenharmony_ci else 798c2ecf20Sopenharmony_ci *size = 0; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic inline unsigned long get_mem_detect_end(void) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci unsigned long start; 858c2ecf20Sopenharmony_ci unsigned long end; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (mem_detect.count) { 888c2ecf20Sopenharmony_ci __get_mem_detect_block(mem_detect.count - 1, &start, &end); 898c2ecf20Sopenharmony_ci return end; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci return 0; 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#endif 95