Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/mem_detect: replace tprot loop with binary search

In a situation when other memory detection methods are not available
(no SCLP and no z/VM diag260), continuous online memory is assumed.
Replacing tprot loop with faster binary search, as only online memory
end has to be found.

Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Vasily Gorbik and committed by
Martin Schwidefsky
54c57795 cd45c995

+18 -34
+15 -30
arch/s390/boot/mem_detect.c
··· 3 3 #include <asm/sclp.h> 4 4 #include <asm/sections.h> 5 5 #include <asm/mem_detect.h> 6 + #include <asm/sparsemem.h> 6 7 #include "compressed/decompressor.h" 7 8 #include "boot.h" 8 - 9 - #define CHUNK_READ_WRITE 0 10 - #define CHUNK_READ_ONLY 1 11 9 12 10 unsigned long __bootdata(max_physmem_end); 13 11 struct mem_detect_info __bootdata(mem_detect); ··· 139 141 return rc; 140 142 } 141 143 142 - static void scan_memory(unsigned long rzm) 144 + static void search_mem_end(void) 143 145 { 144 - unsigned long addr, size; 145 - int type; 146 + unsigned long range = 1 << (MAX_PHYSMEM_BITS - 20); /* in 1MB blocks */ 147 + unsigned long offset = 0; 148 + unsigned long pivot; 146 149 147 - if (!rzm) 148 - rzm = 1UL << 20; 150 + while (range > 1) { 151 + range >>= 1; 152 + pivot = offset + range; 153 + if (!tprot(pivot << 20)) 154 + offset = pivot; 155 + } 149 156 150 - addr = 0; 151 - do { 152 - size = 0; 153 - /* assume lowcore is writable */ 154 - type = addr ? tprot(addr) : CHUNK_READ_WRITE; 155 - do { 156 - size += rzm; 157 - if (max_physmem_end && addr + size >= max_physmem_end) 158 - break; 159 - } while (type == tprot(addr + size)); 160 - if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) { 161 - if (max_physmem_end && (addr + size > max_physmem_end)) 162 - size = max_physmem_end - addr; 163 - add_mem_detect_block(addr, addr + size); 164 - } 165 - addr += size; 166 - } while (addr < max_physmem_end); 157 + add_mem_detect_block(0, (offset + 1) << 20); 167 158 } 168 159 169 160 void detect_memory(void) 170 161 { 171 - unsigned long rzm; 172 - 173 - sclp_early_get_meminfo(&max_physmem_end, &rzm); 162 + sclp_early_get_memsize(&max_physmem_end); 174 163 175 164 if (!sclp_early_read_storage_info()) { 176 165 mem_detect.info_source = MEM_DETECT_SCLP_STOR_INFO; ··· 175 190 return; 176 191 } 177 192 178 - scan_memory(rzm); 179 - mem_detect.info_source = MEM_DETECT_TPROT_LOOP; 193 + search_mem_end(); 194 + mem_detect.info_source = MEM_DETECT_BIN_SEARCH; 180 195 max_physmem_end = get_mem_detect_end(); 181 196 }
+1 -1
arch/s390/include/asm/mem_detect.h
··· 9 9 MEM_DETECT_SCLP_STOR_INFO, 10 10 MEM_DETECT_DIAG260, 11 11 MEM_DETECT_SCLP_READ_INFO, 12 - MEM_DETECT_TPROT_LOOP 12 + MEM_DETECT_BIN_SEARCH 13 13 }; 14 14 15 15 struct mem_detect_block {
+1 -1
arch/s390/include/asm/sclp.h
··· 114 114 void sclp_early_printk_force(const char *s); 115 115 void __sclp_early_printk(const char *s, unsigned int len, unsigned int force); 116 116 117 - int sclp_early_get_meminfo(unsigned long *mem, unsigned long *rzm); 117 + int sclp_early_get_memsize(unsigned long *mem); 118 118 int _sclp_get_core_info(struct sclp_core_info *info); 119 119 int sclp_core_configure(u8 core); 120 120 int sclp_core_deconfigure(u8 core);
+1 -2
drivers/s390/char/sclp_early_core.c
··· 272 272 return 0; 273 273 } 274 274 275 - int __init sclp_early_get_meminfo(unsigned long *mem, unsigned long *rzm) 275 + int __init sclp_early_get_memsize(unsigned long *mem) 276 276 { 277 277 unsigned long rnmax; 278 278 unsigned long rnsize; ··· 285 285 rnsize = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; 286 286 rnsize <<= 20; 287 287 *mem = rnsize * rnmax; 288 - *rzm = rnsize; 289 288 return 0; 290 289 } 291 290