cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sclp_early.c (4491B)


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