mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] s390: improve memory detection logic.
@ 2004-06-11 17:31 Martin Schwidefsky
  0 siblings, 0 replies; only message in thread
From: Martin Schwidefsky @ 2004-06-11 17:31 UTC (permalink / raw)
  To: akpm, linux-kernel

[PATCH] s390: improve memory detection logic.

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>

diffstat:
 arch/s390/kernel/head.S   |  126 ++++++++++++++++++++++++++++++++++++++-----
 arch/s390/kernel/head64.S |  134 +++++++++++++++++++++++++++++++++++++---------
 arch/s390/kernel/setup.c  |    4 +
 arch/s390/mm/extmem.c     |   24 ++++----
 include/asm-s390/setup.h  |    1 
 5 files changed, 238 insertions(+), 51 deletions(-)

diff -urN linux-2.6/arch/s390/kernel/head.S linux-2.6-s390/arch/s390/kernel/head.S
--- linux-2.6/arch/s390/kernel/head.S	Mon May 10 04:32:26 2004
+++ linux-2.6-s390/arch/s390/kernel/head.S	Fri Jun 11 19:09:49 2004
@@ -478,9 +478,80 @@
         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 @@
 	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 @@
     	.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:	
 
diff -urN linux-2.6/arch/s390/kernel/head64.S linux-2.6-s390/arch/s390/kernel/head64.S
--- linux-2.6/arch/s390/kernel/head64.S	Mon May 10 04:32:27 2004
+++ linux-2.6-s390/arch/s390/kernel/head64.S	Fri Jun 11 19:09:49 2004
@@ -480,12 +480,81 @@
         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 @@
 	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 @@
     	.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:	
 
diff -urN linux-2.6/arch/s390/kernel/setup.c linux-2.6-s390/arch/s390/kernel/setup.c
--- linux-2.6/arch/s390/kernel/setup.c	Mon May 10 04:32:00 2004
+++ linux-2.6-s390/arch/s390/kernel/setup.c	Fri Jun 11 19:09:49 2004
@@ -53,7 +53,9 @@
 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;
diff -urN linux-2.6/arch/s390/mm/extmem.c linux-2.6-s390/arch/s390/mm/extmem.c
--- linux-2.6/arch/s390/mm/extmem.c	Mon May 10 04:32:54 2004
+++ linux-2.6-s390/arch/s390/mm/extmem.c	Fri Jun 11 19:09:49 2004
@@ -55,7 +55,9 @@
 
 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 @@
                    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);
diff -urN linux-2.6/include/asm-s390/setup.h linux-2.6-s390/include/asm-s390/setup.h
--- linux-2.6/include/asm-s390/setup.h	Mon May 10 04:33:19 2004
+++ linux-2.6-s390/include/asm-s390/setup.h	Fri Jun 11 19:09:49 2004
@@ -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__
 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-06-11 17:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-06-11 17:31 [PATCH] s390: improve memory detection logic Martin Schwidefsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®