diff options
-rw-r--r-- | arch/s390/boot/mem_detect.c | 52 | ||||
-rw-r--r-- | arch/s390/include/asm/mem_detect.h | 1 |
2 files changed, 53 insertions, 0 deletions
diff --git a/arch/s390/boot/mem_detect.c b/arch/s390/boot/mem_detect.c index 8974e3dde1e4..42b0cd23f04a 100644 --- a/arch/s390/boot/mem_detect.c +++ b/arch/s390/boot/mem_detect.c @@ -71,6 +71,53 @@ static unsigned long get_mem_detect_end(void) return 0; } +static int __diag260(unsigned long rx1, unsigned long rx2) +{ + register unsigned long _rx1 asm("2") = rx1; + register unsigned long _rx2 asm("3") = rx2; + register unsigned long _ry asm("4") = 0x10; /* storage configuration */ + int rc = -1; /* fail */ + unsigned long reg1, reg2; + psw_t old = S390_lowcore.program_new_psw; + + asm volatile( + " epsw %0,%1\n" + " st %0,%[psw_pgm]\n" + " st %1,%[psw_pgm]+4\n" + " larl %0,1f\n" + " stg %0,%[psw_pgm]+8\n" + " diag %[rx],%[ry],0x260\n" + " ipm %[rc]\n" + " srl %[rc],28\n" + "1:\n" + : "=&d" (reg1), "=&a" (reg2), + [psw_pgm] "=Q" (S390_lowcore.program_new_psw), + [rc] "+&d" (rc), [ry] "+d" (_ry) + : [rx] "d" (_rx1), "d" (_rx2) + : "cc", "memory"); + S390_lowcore.program_new_psw = old; + return rc == 0 ? _ry : -1; +} + +static int diag260(void) +{ + int rc, i; + + struct { + unsigned long start; + unsigned long end; + } storage_extents[8] __aligned(16); /* VM supports up to 8 extends */ + + memset(storage_extents, 0, sizeof(storage_extents)); + rc = __diag260((unsigned long)storage_extents, sizeof(storage_extents)); + if (rc == -1) + return -1; + + for (i = 0; i < min_t(int, rc, ARRAY_SIZE(storage_extents)); i++) + add_mem_detect_block(storage_extents[i].start, storage_extents[i].end + 1); + return 0; +} + static int tprot(unsigned long addr) { unsigned long pgm_addr; @@ -132,6 +179,11 @@ void detect_memory(void) return; } + if (!diag260()) { + mem_detect.info_source = MEM_DETECT_DIAG260; + return; + } + scan_memory(rzm); mem_detect.info_source = MEM_DETECT_TPROT_LOOP; if (!max_physmem_end) diff --git a/arch/s390/include/asm/mem_detect.h b/arch/s390/include/asm/mem_detect.h index 00426c07f6df..6047a28656f5 100644 --- a/arch/s390/include/asm/mem_detect.h +++ b/arch/s390/include/asm/mem_detect.h @@ -7,6 +7,7 @@ enum mem_info_source { MEM_DETECT_NONE = 0, MEM_DETECT_SCLP_STOR_INFO, + MEM_DETECT_DIAG260, MEM_DETECT_TPROT_LOOP }; |