]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] s390: improve memory detection logic
authorAndrew Morton <akpm@osdl.org>
Sat, 12 Jun 2004 23:43:29 +0000 (16:43 -0700)
committerLinus Torvalds <torvalds@evo.osdl.org>
Sat, 12 Jun 2004 23:43:29 +0000 (16:43 -0700)
From: Martin Schwidefsky <schwidefsky@de.ibm.com>

From: Guillaume Morin <guillaume@morinfr.org>

This patch improves the memory detection logic.  It detects any amount of
holes in the memory layout up to MEMORY_CHUNK blocks of available memory.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/s390/kernel/head.S
arch/s390/kernel/head64.S
arch/s390/kernel/setup.c
arch/s390/mm/extmem.c
include/asm-s390/setup.h

index 229f4aff8aecd4bcfb1d838fdd9342fac029402d..068653a5e77e9f5fd206d6975104bfd4a66dc659 100644 (file)
@@ -478,9 +478,80 @@ startup:basr  %r13,0                     # get base
         mvcle %r2,%r4,0                 # clear mem
         jo    .-4                       # branch back, if not finish
 
+       l     %r2,.Lrcp-.LPG1(%r13)     # Read SCP forced command word
+.Lservicecall:
+       stosm .Lpmask-.LPG1(%r13),0x01  # authorize ext interrupts
+
+       stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0
+       la    %r1,0x200                 # set bit 22
+       o     %r1,.Lcr-.LPG1(%r13)      # or old cr0 with r1
+       st    %r1,.Lcr-.LPG1(%r13)
+       lctl  %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0
+
+       mvc   __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
+       la    %r1, .Lsclph-.LPG1(%r13)
+       a     %r1,__LC_EXT_NEW_PSW+4    # set handler
+       st    %r1,__LC_EXT_NEW_PSW+4
+
+       la    %r4,_pstart-.LPG1(%r13)   # %r4 is our index for sccb stuff
+       la    %r1, .Lsccb-PARMAREA(%r4) # our sccb
+       .insn rre,0xb2200000,%r2,%r1    # service call
+       ipm   %r1
+       srl   %r1,28                    # get cc code
+       xr    %r3, %r3
+       chi   %r1,3
+       be    .Lfchunk-.LPG1(%r13)      # leave
+       chi   %r1,2
+       be    .Lservicecall-.LPG1(%r13)
+       lpsw  .Lwaitsclp-.LPG1(%r13)
+.Lsclph:
+       lh    %r1,.Lsccbr-PARMAREA(%r4)
+       chi   %r1,0x10                  # 0x0010 is the sucess code
+       je    .Lprocsccb                # let's process the sccb
+       chi   %r1,0x1f0
+       bne   .Lfchunk-.LPG1(%r13)      # unhandled error code
+       c     %r2, .Lrcp-.LPG1(%r13)    # Did we try Read SCP forced
+       bne   .Lfchunk-.LPG1(%r13)      # if no, give up
+       l     %r2, .Lrcp2-.LPG1(%r13)   # try with Read SCP
+       b     .Lservicecall-.LPG1(%r13)
+.Lprocsccb:
+       lh    %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+       chi   %r1,0x00
+       jne   .Lscnd
+       l     %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
+.Lscnd:
+       xr    %r3,%r3                   # same logic
+       ic    %r3,.Lscpa1-PARMAREA(%r4)
+       chi   %r3,0x00
+       jne   .Lcompmem
+       l     %r3,.Lscpa2-PARMAREA(%r13)
+.Lcompmem:
+       mr    %r2,%r1                   # mem in MB on 128-bit
+       l     %r1,.Lonemb-.LPG1(%r13)
+       mr    %r2,%r1                   # mem size in bytes in %r3
+       b     .Lfchunk-.LPG1(%r13)
+
+.Lpmask:
+       .byte 0
+.align 8
+.Lpcext:.long  0x00080000,0x80000000
+.Lcr:
+       .long 0x00                      # place holder for cr0
+.Lwaitsclp:
+       .long 0x020A0000
+       .long .Lsclph
+.Lrcp:
+       .int 0x00120001                 # Read SCP forced code
+.Lrcp2:
+       .int 0x00020001                 # Read SCP code
+.Lonemb:
+       .int 0x100000
+.Lfchunk:
+
 #
 # find memory chunks.
 #
+       lr    %r9,%r3                    # end of mem
        mvc   __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
        la    %r1,1                      # test in increments of 128KB
        sll   %r1,17
@@ -488,38 +559,46 @@ startup:basr  %r13,0                     # get base
        slr   %r4,%r4                    # set start of chunk to zero
        slr   %r5,%r5                    # set end of chunk to zero
        slr   %r6,%r6                    # set access code to zero
+       la    %r10, MEMORY_CHUNKS        # number of chunks
 .Lloop:
        tprot 0(%r5),0                   # test protection of first byte
        ipm   %r7
        srl   %r7,28
        clr   %r6,%r7                    # compare cc with last access code
        be    .Lsame-.LPG1(%r13)
-       clr   %r4,%r5                    # chunk size > 0?
-       be    .Lsize0-.LPG1(%r13)
-       st    %r4,0(%r3)                 # store start address of chunk
-       lr    %r0,%r5
-       slr   %r0,%r4
-       st    %r0,4(%r3)                 # store size of chunk
-       st    %r6,8(%r3)                 # store type of chunk
-       la    %r3,12(%r3)
-       lr    %r4,%r5                    # set start to end
-.Lsize0:
-       lr    %r6,%r7                    # set access code to last cc
+       b     .Lchkmem-.LPG1(%r13)
 .Lsame:
        ar    %r5,%r1                    # add 128KB to end of chunk
        bno   .Lloop-.LPG1(%r13)         # r1 < 0x80000000 -> loop
 .Lchkmem:                               # > 2GB or tprot got a program check
        clr   %r4,%r5                    # chunk size > 0?
-       be    .Ldonemem-.LPG1(%r13)
+       be    .Lchkloop-.LPG1(%r13)
        st    %r4,0(%r3)                 # store start address of chunk
        lr    %r0,%r5
        slr   %r0,%r4
        st    %r0,4(%r3)                 # store size of chunk
        st    %r6,8(%r3)                 # store type of chunk
+       la    %r3,12(%r3)
+       l     %r4,.Lmemsize-.LPG1(%r13)  # address of variable memory_size
+       st    %r5,0(%r4)                 # store last end to memory size
+       ahi   %r10,-1                    # update chunk number
+.Lchkloop:
+       lr    %r6,%r7                    # set access code to last cc
+       # we got an exception or we're starting a new
+       # chunk , we must check if we should
+       # still try to find valid memory (if we detected
+       # the amount of available storage), and if we
+       # have chunks left
+       xr    %r0,%r0
+       clr   %r0,%r9                    # did we detect memory?
+       je    .Ldonemem                  # if not, leave
+       chi   %r10,0                     # do we have chunks left?
+       je    .Ldonemem
+       alr   %r5,%r1                    # add 128KB to end of chunk
+       lr    %r4,%r5                    # potential new chunk
+       clr    %r5,%r9                   # should we go on?
+       jl     .Lloop
 .Ldonemem:             
-        l     %r1,.Lmemsize-.LPG1(%r13)  # address of variable memory_size
-       st    %r5,0(%r1)                 # store last end to memory size
-       
         l      %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
 #
 # find out if we are running under VM
@@ -631,6 +710,23 @@ _pstart:
        .byte  "root=/dev/ram0 ro"
         .byte  0
        .org   0x11000
+.Lsccb:
+       .hword 0x1000                   # length, one page
+       .byte 0x00,0x00,0x00
+       .byte 0x80                      # variable response bit set
+.Lsccbr:
+       .hword 0x00                     # response code
+.Lscpincr1:
+       .hword 0x00
+.Lscpa1:
+       .byte 0x00
+       .fill 89,1,0
+.Lscpa2:
+       .int 0x00
+.Lscpincr2:
+       .quad 0x00
+       .fill 3984,1,0
+       .org 0x12000
        .global _pend
 _pend: 
 
index c380e2b9cc8ec50b620d27293317cda10842d017..26caebd7d676f6488f56d3b348df57b98711eee8 100644 (file)
@@ -480,12 +480,81 @@ startup:basr  %r13,0                     # get base
         mvcle %r2,%r4,0                 # clear mem
         jo    .-4                       # branch back, if not finish
 
+       l     %r2,.Lrcp-.LPG1(%r13)     # Read SCP forced command word
+.Lservicecall:
+       stosm .Lpmask-.LPG1(%r13),0x01  # authorize ext interrupts
+
+       stctg %r0,%r0,.Lcr-.LPG1(%r13)  # get cr0
+       la    %r1,0x200                 # set bit 22
+       og    %r1,.Lcr-.LPG1(%r13)      # or old cr0 with r1
+       stg   %r1,.Lcr-.LPG1(%r13)
+       lctlg %r0,%r0,.Lcr-.LPG1(%r13)  # load modified cr0
+
+       mvc   __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
+       larl  %r1,.Lsclph
+       stg   %r1,__LC_EXT_NEW_PSW+8    # set handler
+
+       larl  %r4,_pstart               # %r4 is our index for sccb stuff
+       la    %r1,.Lsccb-PARMAREA(%r4)  # our sccb
+       .insn rre,0xb2200000,%r2,%r1    # service call
+       ipm   %r1
+       srl   %r1,28                    # get cc code
+       xr    %r3,%r3
+       chi   %r1,3
+       be    .Lfchunk-.LPG1(%r13)      # leave
+       chi   %r1,2
+       be    .Lservicecall-.LPG1(%r13)
+       lpsw  .Lwaitsclp-.LPG1(%r13)
+.Lsclph:
+       lh    %r1,.Lsccbr-PARMAREA(%r4)
+       chi   %r1,0x10                  # 0x0010 is the sucess code
+       je    .Lprocsccb                # let's process the sccb
+       chi   %r1,0x1f0
+       bne   .Lfchunk-.LPG1(%r13)      # unhandled error code
+       c     %r2,.Lrcp-.LPG1(%r13)     # Did we try Read SCP forced
+       bne   .Lfchunk-.LPG1(%r13)      # if no, give up
+       l     %r2,.Lrcp2-.LPG1(%r13)    # try with Read SCP
+       b     .Lservicecall-.LPG1(%r13)
+.Lprocsccb:
+       lh    %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+       chi   %r1,0x00
+       jne   .Lscnd
+       lg    %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
+.Lscnd:
+       xr    %r3,%r3                   # same logic
+       ic    %r3,.Lscpa1-PARMAREA(%r4)
+       chi   %r3,0x00
+       jne   .Lcompmem
+       l     %r3,.Lscpa2-PARMAREA(%r13)
+.Lcompmem:
+       mlgr  %r2,%r1                   # mem in MB on 128-bit
+       l     %r1,.Lonemb-.LPG1(%r13)
+       mlgr  %r2,%r1                   # mem size in bytes in %r3
+       b     .Lfchunk-.LPG1(%r13)
+
+.Lpmask:
+       .byte 0
+       .align 8
+.Lcr:
+       .quad 0x00  # place holder for cr0
+.Lwaitsclp:
+       .long 0x020A0000
+       .quad .Lsclph
+.Lrcp:
+       .int 0x00120001 # Read SCP forced code
+.Lrcp2:
+       .int 0x00020001 # Read SCP code
+.Lonemb:
+       .int 0x100000
+
+.Lfchunk:
                                         # set program check new psw mask
        mvc   __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
 
 #
 # find memory chunks.
 #
+       lgr   %r9,%r3                    # end of mem
        larl  %r1,.Lchkmem               # set program check address
        stg   %r1,__LC_PGM_NEW_PSW+8
        la    %r1,1                      # test in increments of 128KB
@@ -494,51 +563,51 @@ startup:basr  %r13,0                     # get base
        slgr  %r4,%r4                    # set start of chunk to zero
        slgr  %r5,%r5                    # set end of chunk to zero
        slr  %r6,%r6                     # set access code to zero
+       la    %r10,MEMORY_CHUNKS         # number of chunks
 .Lloop:
        tprot 0(%r5),0                   # test protection of first byte
        ipm   %r7
        srl   %r7,28
        clr   %r6,%r7                    # compare cc with last access code
        je    .Lsame
-       clgr  %r4,%r5                    # chunk size > 0?
-       je    .Lsize0
-       stg   %r4,0(%r3)                 # store start address of chunk
-       lgr   %r0,%r5
-       slgr  %r0,%r4
-       stg   %r0,8(%r3)                 # store size of chunk
-       st    %r6,20(%r3)                # store type of chunk
-       la    %r3,24(%r3)
-       lgr   %r4,%r5                    # set start to end
-       larl  %r8,memory_size
-       stg   %r5,0(%r8)                 # store memory size
-.Lsize0:
-       lr    %r6,%r7                    # set access code to last cc
+       j     .Lchkmem
 .Lsame:
        algr  %r5,%r1                    # add 128KB to end of chunk
-       brc   12,.Lloop
+                                        # no need to check here,
+       brc   12,.Lloop                  # this is the same chunk
 .Lchkmem:                               # > 16EB or tprot got a program check
        clgr  %r4,%r5                    # chunk size > 0?
-       je    .Ldonemem
+       je    .Lchkloop
        stg   %r4,0(%r3)                 # store start address of chunk
        lgr   %r0,%r5
        slgr  %r0,%r4
        stg   %r0,8(%r3)                 # store size of chunk
        st    %r6,20(%r3)                # store type of chunk
        la    %r3,24(%r3)
-       lgr   %r4,%r5
        larl  %r8,memory_size
        stg   %r5,0(%r8)                 # store memory size
-#
-# Running native the HSA is located at 2GB and we will get an
-# addressing exception trying to access it. We have to restart
-# the scan at 2GB to find out if the machine has more than 2GB.
-#
+       ahi   %r10,-1                    # update chunk number
+.Lchkloop:
+       lr    %r6,%r7                    # set access code to last cc
+       # we got an exception or we're starting a new
+       # chunk , we must check if we should
+       # still try to find valid memory (if we detected
+       # the amount of available storage), and if we
+       # have chunks left
        lghi  %r4,1
        sllg  %r4,%r4,31
        clgr  %r5,%r4
-       jhe   .Ldonemem
-       lgr   %r5,%r4
-       j     .Lloop
+       je    .Lhsaskip
+       xr    %r0, %r0
+       clgr  %r0, %r9                   # did we detect memory?
+       je    .Ldonemem                  # if not, leave
+       chi   %r10, 0                    # do we have chunks left?
+       je    .Ldonemem
+.Lhsaskip:
+       algr  %r5,%r1                    # add 128KB to end of chunk
+       lgr   %r4,%r5                    # potential new chunk
+       clgr  %r5,%r9                    # should we go on?
+       jl    .Lloop
 .Ldonemem:             
 
        larl  %r12,machine_flags
@@ -640,6 +709,23 @@ _pstart:
        .byte  "root=/dev/ram0 ro"
         .byte  0
        .org   0x11000
+.Lsccb:
+       .hword 0x1000                   # length, one page
+       .byte 0x00,0x00,0x00
+       .byte 0x80                      # variable response bit set
+.Lsccbr:
+       .hword 0x00                     # response code
+.Lscpincr1:
+       .hword 0x00
+.Lscpa1:
+       .byte 0x00
+       .fill 89,1,0
+.Lscpa2:
+       .int 0x00
+.Lscpincr2:
+       .quad 0x00
+       .fill 3984,1,0
+       .org 0x12000
        .global _pend
 _pend: 
 
index 7ca8a8706cca777fc11129383c499ab7d8a7354f..d549ad5c2724d858474d02fd2f8e3a814440bbe6 100644 (file)
@@ -53,7 +53,9 @@ unsigned int console_device = -1;
 unsigned int console_irq = -1;
 unsigned long memory_size = 0;
 unsigned long machine_flags = 0;
-struct { unsigned long addr, size, type; } memory_chunk[16] = { { 0 } };
+struct {
+       unsigned long addr, size, type;
+} memory_chunk[MEMORY_CHUNKS] = { { 0 } };
 #define CHUNK_READ_WRITE 0
 #define CHUNK_READ_ONLY 1
 int cpus_initialized = 0;
index ea3db122dda67e9d7ef9ed22e5269e6ff9f9e01c..b0b2714eac2880b60321837a17afd6053d644f00 100644 (file)
@@ -55,7 +55,9 @@ struct dcss_segment {
 
 static spinlock_t dcss_lock = SPIN_LOCK_UNLOCKED;
 static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list);
-extern struct {unsigned long addr, size, type;} memory_chunk[16];
+extern struct {
+       unsigned long addr, size, type;
+} memory_chunk[MEMORY_CHUNKS];
 
 /*
  * Create the 8 bytes, ebcdic VM segment name from
@@ -258,16 +260,16 @@ int segment_load(char *name, int segtype, unsigned long *addr,
                    shared segment */
                 dcss_diag_query(dcss_name, &rwattr, &shattr, &segstart, &segend);
                /* does segment collide with main memory? */
-               for (i=0; i<16; i++) {
-                                       if (memory_chunk[i].type != 0)
-                                               continue;
-                                       if (memory_chunk[i].addr > segend)
-                                               continue;
-                                       if (memory_chunk[i].addr + memory_chunk[i].size <= segstart)
-                                               continue;
-                                       spin_unlock(&dcss_lock);
-                                       return -ENOENT;
-                               }
+               for (i=0; i < MEMORY_CHUNKS; i++) {
+                       if (memory_chunk[i].type != 0)
+                               continue;
+                       if (memory_chunk[i].addr > segend)
+                               continue;
+                       if (memory_chunk[i].addr + memory_chunk[i].size <= segstart)
+                               continue;
+                       spin_unlock(&dcss_lock);
+                       return -ENOENT;
+               }
                /* or does it collide with other (loaded) segments? */
                list_for_each(l, &dcss_list) {
                        tmp = list_entry(l, struct dcss_segment, list);
index c5b19f08c363f731787bbff3b465cdcb6660f594..ba3b3510e9a7daec328750fadd69627425f6d273 100644 (file)
@@ -12,6 +12,7 @@
 #define COMMAND_LINE_SIZE      896
 #define RAMDISK_ORIGIN         0x800000
 #define RAMDISK_SIZE           0x800000
+#define MEMORY_CHUNKS          16      /* max 0x7fff */
 
 #ifndef __ASSEMBLY__