linux/drivers/s390/char/sclp_early.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * SCLP early driver
   4 *
   5 * Copyright IBM Corp. 2013
   6 */
   7
   8#define KMSG_COMPONENT "sclp_early"
   9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  10
  11#include <linux/errno.h>
  12#include <asm/ctl_reg.h>
  13#include <asm/sclp.h>
  14#include <asm/ipl.h>
  15#include "sclp_sdias.h"
  16#include "sclp.h"
  17
  18static struct sclp_ipl_info sclp_ipl_info;
  19
  20struct sclp_info sclp;
  21EXPORT_SYMBOL(sclp);
  22
  23static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
  24{
  25        struct sclp_core_entry *cpue;
  26        u16 boot_cpu_address, cpu;
  27
  28        if (sclp_early_get_info(sccb))
  29                return;
  30
  31        sclp.facilities = sccb->facilities;
  32        sclp.has_sprp = !!(sccb->fac84 & 0x02);
  33        sclp.has_core_type = !!(sccb->fac84 & 0x01);
  34        sclp.has_gsls = !!(sccb->fac85 & 0x80);
  35        sclp.has_64bscao = !!(sccb->fac116 & 0x80);
  36        sclp.has_cmma = !!(sccb->fac116 & 0x40);
  37        sclp.has_esca = !!(sccb->fac116 & 0x08);
  38        sclp.has_pfmfi = !!(sccb->fac117 & 0x40);
  39        sclp.has_ibs = !!(sccb->fac117 & 0x20);
  40        sclp.has_gisaf = !!(sccb->fac118 & 0x08);
  41        sclp.has_hvs = !!(sccb->fac119 & 0x80);
  42        sclp.has_kss = !!(sccb->fac98 & 0x01);
  43        sclp.has_sipl = !!(sccb->cbl & 0x02);
  44        if (sccb->fac85 & 0x02)
  45                S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
  46        if (sccb->fac91 & 0x40)
  47                S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST;
  48        if (sccb->cpuoff > 134)
  49                sclp.has_diag318 = !!(sccb->byte_134 & 0x80);
  50        sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
  51        sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
  52        sclp.rzm <<= 20;
  53        sclp.ibc = sccb->ibc;
  54
  55        if (sccb->hamaxpow && sccb->hamaxpow < 64)
  56                sclp.hamax = (1UL << sccb->hamaxpow) - 1;
  57        else
  58                sclp.hamax = U64_MAX;
  59
  60        if (!sccb->hcpua) {
  61                if (MACHINE_IS_VM)
  62                        sclp.max_cores = 64;
  63                else
  64                        sclp.max_cores = sccb->ncpurl;
  65        } else {
  66                sclp.max_cores = sccb->hcpua + 1;
  67        }
  68
  69        boot_cpu_address = stap();
  70        cpue = (void *)sccb + sccb->cpuoff;
  71        for (cpu = 0; cpu < sccb->ncpurl; cpue++, cpu++) {
  72                if (boot_cpu_address != cpue->core_id)
  73                        continue;
  74                sclp.has_siif = cpue->siif;
  75                sclp.has_sigpif = cpue->sigpif;
  76                sclp.has_sief2 = cpue->sief2;
  77                sclp.has_gpere = cpue->gpere;
  78                sclp.has_ib = cpue->ib;
  79                sclp.has_cei = cpue->cei;
  80                sclp.has_skey = cpue->skey;
  81                break;
  82        }
  83
  84        /* Save IPL information */
  85        sclp_ipl_info.is_valid = 1;
  86        if (sccb->fac91 & 0x2)
  87                sclp_ipl_info.has_dump = 1;
  88        memcpy(&sclp_ipl_info.loadparm, &sccb->loadparm, LOADPARM_LEN);
  89
  90        if (sccb->hsa_size)
  91                sclp.hsa_size = (sccb->hsa_size - 1) * PAGE_SIZE;
  92        sclp.mtid = (sccb->fac42 & 0x80) ? (sccb->fac42 & 31) : 0;
  93        sclp.mtid_cp = (sccb->fac42 & 0x80) ? (sccb->fac43 & 31) : 0;
  94        sclp.mtid_prev = (sccb->fac42 & 0x80) ? (sccb->fac66 & 31) : 0;
  95
  96        sclp.hmfai = sccb->hmfai;
  97        sclp.has_dirq = !!(sccb->cpudirq & 0x80);
  98}
  99
 100/*
 101 * This function will be called after sclp_early_facilities_detect(), which gets
 102 * called from early.c code. The sclp_early_facilities_detect() function retrieves
 103 * and saves the IPL information.
 104 */
 105void __init sclp_early_get_ipl_info(struct sclp_ipl_info *info)
 106{
 107        *info = sclp_ipl_info;
 108}
 109
 110static struct sclp_core_info sclp_early_core_info __initdata;
 111static int sclp_early_core_info_valid __initdata;
 112
 113static void __init sclp_early_init_core_info(struct read_cpu_info_sccb *sccb)
 114{
 115        if (!SCLP_HAS_CPU_INFO)
 116                return;
 117        memset(sccb, 0, sizeof(*sccb));
 118        sccb->header.length = sizeof(*sccb);
 119        if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO, sccb))
 120                return;
 121        if (sccb->header.response_code != 0x0010)
 122                return;
 123        sclp_fill_core_info(&sclp_early_core_info, sccb);
 124        sclp_early_core_info_valid = 1;
 125}
 126
 127int __init sclp_early_get_core_info(struct sclp_core_info *info)
 128{
 129        if (!sclp_early_core_info_valid)
 130                return -EIO;
 131        *info = sclp_early_core_info;
 132        return 0;
 133}
 134
 135static void __init sclp_early_console_detect(struct init_sccb *sccb)
 136{
 137        if (sccb->header.response_code != 0x20)
 138                return;
 139
 140        if (sclp_early_con_check_vt220(sccb))
 141                sclp.has_vt220 = 1;
 142
 143        if (sclp_early_con_check_linemode(sccb))
 144                sclp.has_linemode = 1;
 145}
 146
 147void __init sclp_early_detect(void)
 148{
 149        void *sccb = sclp_early_sccb;
 150
 151        sclp_early_facilities_detect(sccb);
 152        sclp_early_init_core_info(sccb);
 153
 154        /*
 155         * Turn off SCLP event notifications.  Also save remote masks in the
 156         * sccb.  These are sufficient to detect sclp console capabilities.
 157         */
 158        sclp_early_set_event_mask(sccb, 0, 0);
 159        sclp_early_console_detect(sccb);
 160}
 161