s390/mem_detect: introduce z/VM specific diag260 call
authorVasily Gorbik <gor@linux.ibm.com>
Wed, 11 Apr 2018 16:48:20 +0000 (18:48 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 9 Oct 2018 09:21:10 +0000 (11:21 +0200)
In the case when z/VM memory is defined with "define storage config"
command, SCLP storage info is not available. Utilize diag260 "storage
configuration" call, to get information about z/VM specific guest memory
definitions with potential memory holes.

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>
arch/s390/boot/mem_detect.c
arch/s390/include/asm/mem_detect.h

index 8974e3dde1e4b94e3fe356938cbcc5978f924764..42b0cd23f04aea3e78decad33279ee407ac913a9 100644 (file)
@@ -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)
index 00426c07f6df46ed84c348c002de248a2f62c0f4..6047a28656f5a360761e9273a8721c67cc7765d7 100644 (file)
@@ -7,6 +7,7 @@
 enum mem_info_source {
        MEM_DETECT_NONE = 0,
        MEM_DETECT_SCLP_STOR_INFO,
+       MEM_DETECT_DIAG260,
        MEM_DETECT_TPROT_LOOP
 };