s390/setup: set control program code via diag 318
authorCollin Walling <walling@linux.ibm.com>
Thu, 6 Dec 2018 22:30:04 +0000 (17:30 -0500)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 28 Jan 2019 14:58:53 +0000 (15:58 +0100)
The s390x diagnose 318 instruction sets the control program name code (CPNC)
and control program version code (CPVC) to provide useful information
regarding the OS during debugging. The CPNC is explicitly set to 4 to
indicate a Linux/KVM environment.

The CPVC is a 7-byte value containing:

 - 3-byte Linux version code, currently set to 0
 - 3-byte unique value, currently set to 0
 - 1-byte trailing null

Signed-off-by: Collin Walling <walling@linux.ibm.com>
Acked-by: Janosch Frank <frankja@linux.ibm.com>
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1544135405-22385-2-git-send-email-walling@linux.ibm.com>
[set version code to 0 until the structure is fully defined]
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/diag.h
arch/s390/include/asm/sclp.h
arch/s390/kernel/diag.c
arch/s390/kernel/setup.c
drivers/s390/char/sclp.h
drivers/s390/char/sclp_early.c

index cdbaad50c7c7d46e4e77b7b0dd8b79360a4d1a33..19562be22b7e30c12cfa8c78ada1fb39ebbecd14 100644 (file)
@@ -32,6 +32,7 @@ enum diag_stat_enum {
        DIAG_STAT_X2FC,
        DIAG_STAT_X304,
        DIAG_STAT_X308,
+       DIAG_STAT_X318,
        DIAG_STAT_X500,
        NR_DIAG_STAT
 };
@@ -293,6 +294,17 @@ struct diag26c_mac_resp {
        u8      res[2];
 } __aligned(8);
 
+#define CPNC_LINUX             0x4
+union diag318_info {
+       unsigned long val;
+       struct {
+               unsigned int cpnc : 8;
+               unsigned int cpvc_linux : 24;
+               unsigned char cpvc_distro[3];
+               unsigned char zero;
+       };
+};
+
 int diag204(unsigned long subcode, unsigned long size, void *addr);
 int diag224(void *ptr);
 int diag26c(void *req, void *resp, enum diag26c_sc subcode);
index 0cd4bda85eb1e0d281d3036ca745faa28f992eed..ef4c9dec06a471addcb316f96fb135b79db06ca3 100644 (file)
@@ -78,6 +78,7 @@ struct sclp_info {
        unsigned char has_skey : 1;
        unsigned char has_kss : 1;
        unsigned char has_gisaf : 1;
+       unsigned char has_diag318 : 1;
        unsigned int ibc;
        unsigned int mtid;
        unsigned int mtid_cp;
index 53a5316cc4b7e557b8eb4b71aa78738d2d2ecf11..7edaa733a77fdd9286382f745bdf103253fba26d 100644 (file)
@@ -45,6 +45,7 @@ static const struct diag_desc diag_map[NR_DIAG_STAT] = {
        [DIAG_STAT_X2FC] = { .code = 0x2fc, .name = "Guest Performance Data" },
        [DIAG_STAT_X304] = { .code = 0x304, .name = "Partition-Resource Service" },
        [DIAG_STAT_X308] = { .code = 0x308, .name = "List-Directed IPL" },
+       [DIAG_STAT_X318] = { .code = 0x318, .name = "CP Name and Version Codes" },
        [DIAG_STAT_X500] = { .code = 0x500, .name = "Virtio Service" },
 };
 
index 72dd23ef771b6bf22f77e71df22a40e05fbee2d5..5295e536515b3355add4c72f7bfb435e4763674b 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/memory.h>
 #include <linux/compat.h>
 #include <linux/start_kernel.h>
+#include <linux/version.h>
 
 #include <asm/ipl.h>
 #include <asm/facility.h>
@@ -989,6 +990,25 @@ static void __init setup_task_size(void)
        arch_task_struct_size = task_size;
 }
 
+/*
+ * Issue diagnose 318 to set the control program name and
+ * version codes.
+ */
+static void __init setup_control_program_code(void)
+{
+       union diag318_info diag318_info = {
+               .cpnc = CPNC_LINUX,
+               .cpvc_linux = 0,
+               .cpvc_distro = {0},
+       };
+
+       if (!sclp.has_diag318)
+               return;
+
+       diag_stat_inc(DIAG_STAT_X318);
+       asm volatile("diag %0,0,0x318\n" : : "d" (diag318_info.val));
+}
+
 /*
  * Setup function called from init/main.c just after the banner
  * was printed.
@@ -1031,6 +1051,7 @@ void __init setup_arch(char **cmdline_p)
        os_info_init();
        setup_ipl();
        setup_task_size();
+       setup_control_program_code();
 
        /* Do some memory reservations *before* memory is added to memblock */
        reserve_memory_end();
index b3fcc24b11826eb15a11f0d0f8e457ad192bcd28..367e9d384d852b3140158302e5e713ffa2d43616 100644 (file)
@@ -195,7 +195,9 @@ struct read_info_sccb {
        u16     hcpua;                  /* 120-121 */
        u8      _pad_122[124 - 122];    /* 122-123 */
        u32     hmfai;                  /* 124-127 */
-       u8      _pad_128[4096 - 128];   /* 128-4095 */
+       u8      _pad_128[134 - 128];    /* 128-133 */
+       u8      byte_134;                       /* 134 */
+       u8      _pad_135[4096 - 135];   /* 135-4095 */
 } __packed __aligned(PAGE_SIZE);
 
 struct read_storage_sccb {
index e792cee3b51c5d24089d39b63a88b67bad204fcc..8332788681c402209fb2e7bc202d2a4b9ae8e04a 100644 (file)
@@ -44,6 +44,8 @@ static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
                S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
        if (sccb->fac91 & 0x40)
                S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST;
+       if (sccb->cpuoff > 134)
+               sclp.has_diag318 = !!(sccb->byte_134 & 0x80);
        sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
        sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
        sclp.rzm <<= 20;