Unfortunately, there is no easy way to simply read out the amount of installed memory. We have to probe (via TEST PROTECTION) for installed memory in a given range. Signed-off-by: David Hildenbrand <david@xxxxxxxxxx> --- lib/s390x/asm/arch_def.h | 12 +++++++++++ lib/s390x/io.c | 1 + lib/s390x/sclp.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/s390x/sclp.h | 1 + s390x/Makefile | 1 + 5 files changed, 67 insertions(+) create mode 100644 lib/s390x/sclp.c diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h index 72e5c60..ae27ab2 100644 --- a/lib/s390x/asm/arch_def.h +++ b/lib/s390x/asm/arch_def.h @@ -151,4 +151,16 @@ struct cpuid { uint64_t reserved : 15; }; +static inline int tprot(unsigned long addr) +{ + int cc; + + asm volatile( + " tprot %1,0\n" + " ipm %0\n" + " srl %0,28\n" + : "=d" (cc) : "Q" (addr) : "cc"); + return cc; +} + #endif diff --git a/lib/s390x/io.c b/lib/s390x/io.c index 3121a78..eb4d171 100644 --- a/lib/s390x/io.c +++ b/lib/s390x/io.c @@ -43,6 +43,7 @@ void setup() setup_args_progname(ipl_args); setup_facilities(); sclp_ascii_setup(); + sclp_memory_setup(); } void exit(int code) diff --git a/lib/s390x/sclp.c b/lib/s390x/sclp.c new file mode 100644 index 0000000..ee56820 --- /dev/null +++ b/lib/s390x/sclp.c @@ -0,0 +1,52 @@ +/* + * s390x SCLP driver + * + * Copyright (c) 2017 Red Hat Inc + * + * Authors: + * David Hildenbrand <david@xxxxxxxxxx> + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ + +#include <libcflat.h> +#include <asm/page.h> +#include <asm/arch_def.h> +#include "sclp.h" + +static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); +static uint64_t storage_increment_size; +static uint64_t max_ram_size; +static uint64_t ram_size; + +void sclp_memory_setup(void) +{ + ReadInfo *ri = (void *)_sccb; + uint64_t rnmax, rnsize; + + ri->h.length = SCCB_SIZE; + sclp_service_call(SCLP_CMDW_READ_SCP_INFO_FORCED, ri); + + /* calculate the storage increment size */ + rnsize = ri->rnsize; + if (!rnsize) { + rnsize = ri->rnsize2; + } + storage_increment_size = rnsize << 20; + + /* calculate the maximum memory size */ + rnmax = ri->rnmax; + if (!rnmax) { + rnmax = ri->rnmax2; + } + max_ram_size = rnmax * storage_increment_size; + + /* lowcore is always accessible, so the first increment is accessible */ + ram_size = storage_increment_size; + + /* probe for r/w memory up to max memory size */ + while (ram_size < max_ram_size && + tprot(ram_size + storage_increment_size - 1)) + ram_size += storage_increment_size; +} diff --git a/lib/s390x/sclp.h b/lib/s390x/sclp.h index ec9dcb1..94ff74b 100644 --- a/lib/s390x/sclp.h +++ b/lib/s390x/sclp.h @@ -210,5 +210,6 @@ typedef struct ReadEventData { void sclp_ascii_setup(void); void sclp_print(const char *str); int sclp_service_call(unsigned int command, void *sccb); +void sclp_memory_setup(void); #endif /* SCLP_H */ diff --git a/s390x/Makefile b/s390x/Makefile index f585faf..ce63dd1 100644 --- a/s390x/Makefile +++ b/s390x/Makefile @@ -24,6 +24,7 @@ cflatobjs += lib/util.o cflatobjs += lib/alloc_phys.o cflatobjs += lib/s390x/io.o cflatobjs += lib/s390x/stack.o +cflatobjs += lib/s390x/sclp.o cflatobjs += lib/s390x/sclp-ascii.o cflatobjs += lib/s390x/interrupt.o -- 2.14.3