s390/sclp: use only one sclp early buffer to send commands
authorAlexander Egorenkov <egorenar@linux.ibm.com>
Sat, 10 Oct 2020 01:34:25 +0000 (03:34 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Tue, 27 Jul 2021 07:39:13 +0000 (09:39 +0200)
A buffer that can be used for communication with SCLP is required
to lie below 2GB memory address. Therefore, both sclp_info_sccb
and sclp_early_sccb must fulfill this requirement if passed directly
to the sclp_early_cmd() function. Instead, use only sclp_early_sccb
for communication with SCLP. This allows the buffer sclp_info_sccb
to be placed anywhere in the memory address space and, therefore,
simplifies the process of making the decompressor relocatable later on,
one thing less to relocate. And make sure that the length of the new unified
early SCLP buffer is no less than the length of the removed sclp_info_sccb
buffer which might be larger than the length of the sclp_early_sccb buffer.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Reviewed-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/boot/head.S
arch/s390/include/asm/sclp.h
arch/s390/include/asm/setup.h
drivers/s390/char/sclp_early_core.c

index cafe454..0cfa76f 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
+#include <asm/sclp.h>
 
 #define ARCH_OFFSET    4
 
@@ -410,6 +411,6 @@ SYM_DATA_START(parmarea)
 SYM_DATA_END(parmarea)
 
        .org    EARLY_SCCB_OFFSET
-       .fill   4096
+       .fill   EXT_SCCB_READ_SCP
 
        .org    HEAD_END
index 5763769..3adbb41 100644 (file)
@@ -8,8 +8,6 @@
 #define _ASM_S390_SCLP_H
 
 #include <linux/types.h>
-#include <asm/chpid.h>
-#include <asm/cpu.h>
 
 #define SCLP_CHP_INFO_MASK_SIZE                32
 #define EARLY_SCCB_SIZE                PAGE_SIZE
 /* 24 + 16 * SCLP_MAX_CORES */
 #define EXT_SCCB_READ_CPU      (3 * PAGE_SIZE)
 
+#ifndef __ASSEMBLY__
+#include <asm/chpid.h>
+#include <asm/cpu.h>
+
 struct sclp_chp_info {
        u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
        u8 standby[SCLP_CHP_INFO_MASK_SIZE];
@@ -147,4 +149,5 @@ static inline int sclp_get_core_info(struct sclp_core_info *info, int early)
        return _sclp_get_core_info(info);
 }
 
+#endif /* __ASSEMBLY__ */
 #endif /* _ASM_S390_SCLP_H */
index 3a77aa9..cf285f5 100644 (file)
@@ -7,6 +7,7 @@
 #define _ASM_S390_SETUP_H
 
 #include <linux/bits.h>
+#include <asm/sclp.h>
 #include <uapi/asm/setup.h>
 #include <linux/build_bug.h>
 
@@ -14,7 +15,7 @@
 #define EP_STRING              "S390EP"
 #define PARMAREA               0x10400
 #define EARLY_SCCB_OFFSET      0x11000
-#define HEAD_END               0x12000
+#define HEAD_END               (EARLY_SCCB_OFFSET + EXT_SCCB_READ_SCP)
 
 /*
  * Machine features detected in early.c
index b7329af..80ba652 100644 (file)
@@ -235,11 +235,20 @@ void sclp_early_printk(const char *str)
        __sclp_early_printk(str, strlen(str));
 }
 
+/*
+ * We can't pass sclp_info_sccb to sclp_early_cmd() here directly,
+ * because it might not fulfil the requiremets for a SCLP communication buffer:
+ *   - lie below 2G in memory
+ *   - be page-aligned
+ * Therefore, we use the buffer sclp_early_sccb (which fulfils all those
+ * requirements) temporarily for communication and copy a received response
+ * back into the buffer sclp_info_sccb upon successful completion.
+ */
 int __init sclp_early_read_info(void)
 {
        int i;
        int length = test_facility(140) ? EXT_SCCB_READ_SCP : PAGE_SIZE;
-       struct read_info_sccb *sccb = &sclp_info_sccb;
+       struct read_info_sccb *sccb = (struct read_info_sccb *)sclp_early_sccb;
        sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
                                  SCLP_CMDW_READ_SCP_INFO};
 
@@ -251,6 +260,7 @@ int __init sclp_early_read_info(void)
                if (sclp_early_cmd(commands[i], sccb))
                        break;
                if (sccb->header.response_code == 0x10) {
+                       memcpy(&sclp_info_sccb, sccb, length);
                        sclp_info_sccb_valid = 1;
                        return 0;
                }