xref: /openbmc/linux/drivers/s390/char/sclp_early.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2e657d8feSMichael Holzheu /*
3e657d8feSMichael Holzheu  * SCLP early driver
4e657d8feSMichael Holzheu  *
5e657d8feSMichael Holzheu  * Copyright IBM Corp. 2013
6e657d8feSMichael Holzheu  */
7e657d8feSMichael Holzheu 
8e657d8feSMichael Holzheu #define KMSG_COMPONENT "sclp_early"
9e657d8feSMichael Holzheu #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10e657d8feSMichael Holzheu 
11a313bdc5SSebastian Ott #include <linux/errno.h>
1208ab919dSSumanth Korikkar #include <linux/memblock.h>
13acf6a004SMichael Holzheu #include <asm/ctl_reg.h>
14e657d8feSMichael Holzheu #include <asm/sclp.h>
15e657d8feSMichael Holzheu #include <asm/ipl.h>
1608ab919dSSumanth Korikkar #include <asm/setup.h>
17b971cbd0SSumanth Korikkar #include <asm/facility.h>
18e657d8feSMichael Holzheu #include "sclp_sdias.h"
19e657d8feSMichael Holzheu #include "sclp.h"
20e657d8feSMichael Holzheu 
21333cce91SHendrik Brueckner static struct sclp_ipl_info sclp_ipl_info;
22e657d8feSMichael Holzheu 
2337c5f6c8SDavid Hildenbrand struct sclp_info sclp;
2437c5f6c8SDavid Hildenbrand EXPORT_SYMBOL(sclp);
25acf6a004SMichael Holzheu 
sclp_early_facilities_detect(void)26d25d23e1SSumanth Korikkar static void __init sclp_early_facilities_detect(void)
27acf6a004SMichael Holzheu {
28d08d9430SMartin Schwidefsky 	struct sclp_core_entry *cpue;
29d25d23e1SSumanth Korikkar 	struct read_info_sccb *sccb;
30217a4406SHeiko Carstens 	u16 boot_cpu_address, cpu;
31217a4406SHeiko Carstens 
32d25d23e1SSumanth Korikkar 	sccb = sclp_early_get_info();
33d25d23e1SSumanth Korikkar 	if (!sccb)
34acf6a004SMichael Holzheu 		return;
35acf6a004SMichael Holzheu 
3678335a30SDavid Hildenbrand 	sclp.facilities = sccb->facilities;
3737c5f6c8SDavid Hildenbrand 	sclp.has_sprp = !!(sccb->fac84 & 0x02);
38d08d9430SMartin Schwidefsky 	sclp.has_core_type = !!(sccb->fac84 & 0x01);
395236c751SDavid Hildenbrand 	sclp.has_gsls = !!(sccb->fac85 & 0x80);
404013ade3SDavid Hildenbrand 	sclp.has_64bscao = !!(sccb->fac116 & 0x80);
4109be9cb9SDavid Hildenbrand 	sclp.has_cmma = !!(sccb->fac116 & 0x40);
42f7ba1d34SEugene (jno) Dvurechenski 	sclp.has_esca = !!(sccb->fac116 & 0x08);
43a0eb55e6SDavid Hildenbrand 	sclp.has_pfmfi = !!(sccb->fac117 & 0x40);
449c375490SDavid Hildenbrand 	sclp.has_ibs = !!(sccb->fac117 & 0x20);
459e73ea70SMichael Mueller 	sclp.has_gisaf = !!(sccb->fac118 & 0x08);
46f7ba1d34SEugene (jno) Dvurechenski 	sclp.has_hvs = !!(sccb->fac119 & 0x80);
4771cb1bf6SFarhan Ali 	sclp.has_kss = !!(sccb->fac98 & 0x01);
489db153f4SMatthew Rosato 	sclp.has_aisii = !!(sccb->fac118 & 0x40);
49efef0db7SMatthew Rosato 	sclp.has_aeni = !!(sccb->fac118 & 0x20);
50b05a870cSMatthew Rosato 	sclp.has_aisi = !!(sccb->fac118 & 0x10);
51e3d27b62SMatthew Rosato 	sclp.has_zpci_lsi = !!(sccb->fac118 & 0x01);
52acf6a004SMichael Holzheu 	if (sccb->fac85 & 0x02)
53acf6a004SMichael Holzheu 		S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
54118bd31bSMartin Schwidefsky 	if (sccb->fac91 & 0x40)
55118bd31bSMartin Schwidefsky 		S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST;
561b553839SAlexander Egorenkov 	if (sccb->cpuoff > 134) {
574ad78b86SCollin Walling 		sclp.has_diag318 = !!(sccb->byte_134 & 0x80);
58*8cf57d72SAnastasia Eskova 		sclp.has_diag320 = !!(sccb->byte_134 & 0x04);
591b553839SAlexander Egorenkov 		sclp.has_iplcc = !!(sccb->byte_134 & 0x02);
601b553839SAlexander Egorenkov 	}
6187fd22e0SSven Schnelle 	if (sccb->cpuoff > 137) {
62d76b14f3SAlexander Egorenkov 		sclp.has_sipl = !!(sccb->cbl & 0x4000);
6387fd22e0SSven Schnelle 		sclp.has_sipl_eckd = !!(sccb->cbl & 0x2000);
6487fd22e0SSven Schnelle 	}
6537c5f6c8SDavid Hildenbrand 	sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
6637c5f6c8SDavid Hildenbrand 	sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
6737c5f6c8SDavid Hildenbrand 	sclp.rzm <<= 20;
6837c5f6c8SDavid Hildenbrand 	sclp.ibc = sccb->ibc;
69333cce91SHendrik Brueckner 
7032e6b236SGuenther Hutzl 	if (sccb->hamaxpow && sccb->hamaxpow < 64)
7132e6b236SGuenther Hutzl 		sclp.hamax = (1UL << sccb->hamaxpow) - 1;
7232e6b236SGuenther Hutzl 	else
7332e6b236SGuenther Hutzl 		sclp.hamax = U64_MAX;
7432e6b236SGuenther Hutzl 
75cf813db0SHeiko Carstens 	if (!sccb->hcpua) {
76cf813db0SHeiko Carstens 		if (MACHINE_IS_VM)
77d08d9430SMartin Schwidefsky 			sclp.max_cores = 64;
78cf813db0SHeiko Carstens 		else
79d08d9430SMartin Schwidefsky 			sclp.max_cores = sccb->ncpurl;
80cf813db0SHeiko Carstens 	} else {
81d08d9430SMartin Schwidefsky 		sclp.max_cores = sccb->hcpua + 1;
82cf813db0SHeiko Carstens 	}
83cf813db0SHeiko Carstens 
84217a4406SHeiko Carstens 	boot_cpu_address = stap();
85217a4406SHeiko Carstens 	cpue = (void *)sccb + sccb->cpuoff;
86217a4406SHeiko Carstens 	for (cpu = 0; cpu < sccb->ncpurl; cpue++, cpu++) {
8710ad34bcSMartin Schwidefsky 		if (boot_cpu_address != cpue->core_id)
88217a4406SHeiko Carstens 			continue;
8937c5f6c8SDavid Hildenbrand 		sclp.has_siif = cpue->siif;
9037c5f6c8SDavid Hildenbrand 		sclp.has_sigpif = cpue->sigpif;
918dfd523fSDavid Hildenbrand 		sclp.has_sief2 = cpue->sief2;
92b9e28897SDavid Hildenbrand 		sclp.has_gpere = cpue->gpere;
9372cd82b9SDavid Hildenbrand 		sclp.has_ib = cpue->ib;
944a5c3e08SDavid Hildenbrand 		sclp.has_cei = cpue->cei;
9523861451SDavid Hildenbrand 		sclp.has_skey = cpue->skey;
96217a4406SHeiko Carstens 		break;
97217a4406SHeiko Carstens 	}
98217a4406SHeiko Carstens 
99333cce91SHendrik Brueckner 	/* Save IPL information */
100333cce91SHendrik Brueckner 	sclp_ipl_info.is_valid = 1;
101118bd31bSMartin Schwidefsky 	if (sccb->fac91 & 0x2)
102333cce91SHendrik Brueckner 		sclp_ipl_info.has_dump = 1;
103333cce91SHendrik Brueckner 	memcpy(&sclp_ipl_info.loadparm, &sccb->loadparm, LOADPARM_LEN);
10410ad34bcSMartin Schwidefsky 
1053b076dcaSVasily Gorbik 	if (sccb->hsa_size)
1063b076dcaSVasily Gorbik 		sclp.hsa_size = (sccb->hsa_size - 1) * PAGE_SIZE;
10737c5f6c8SDavid Hildenbrand 	sclp.mtid = (sccb->fac42 & 0x80) ? (sccb->fac42 & 31) : 0;
10837c5f6c8SDavid Hildenbrand 	sclp.mtid_cp = (sccb->fac42 & 0x80) ? (sccb->fac43 & 31) : 0;
10937c5f6c8SDavid Hildenbrand 	sclp.mtid_prev = (sccb->fac42 & 0x80) ? (sccb->fac66 & 31) : 0;
110154fa27eSAlexander Yarygin 
111154fa27eSAlexander Yarygin 	sclp.hmfai = sccb->hmfai;
1120a9fddfaSSebastian Ott 	sclp.has_dirq = !!(sccb->cpudirq & 0x80);
113acf6a004SMichael Holzheu }
114acf6a004SMichael Holzheu 
115acf6a004SMichael Holzheu /*
116d5ab7a34SHeiko Carstens  * This function will be called after sclp_early_facilities_detect(), which gets
117d5ab7a34SHeiko Carstens  * called from early.c code. The sclp_early_facilities_detect() function retrieves
118333cce91SHendrik Brueckner  * and saves the IPL information.
119acf6a004SMichael Holzheu  */
sclp_early_get_ipl_info(struct sclp_ipl_info * info)120d5ab7a34SHeiko Carstens void __init sclp_early_get_ipl_info(struct sclp_ipl_info *info)
121acf6a004SMichael Holzheu {
122333cce91SHendrik Brueckner 	*info = sclp_ipl_info;
123acf6a004SMichael Holzheu }
124acf6a004SMichael Holzheu 
sclp_early_get_core_info(struct sclp_core_info * info)125d5ab7a34SHeiko Carstens int __init sclp_early_get_core_info(struct sclp_core_info *info)
126af51160eSHeiko Carstens {
12708ab919dSSumanth Korikkar 	struct read_cpu_info_sccb *sccb;
128b971cbd0SSumanth Korikkar 	int length = test_facility(140) ? EXT_SCCB_READ_CPU : PAGE_SIZE;
12908ab919dSSumanth Korikkar 	int rc = 0;
13008ab919dSSumanth Korikkar 
13108ab919dSSumanth Korikkar 	if (!SCLP_HAS_CPU_INFO)
13208ab919dSSumanth Korikkar 		return -EOPNOTSUPP;
13308ab919dSSumanth Korikkar 
13408ab919dSSumanth Korikkar 	sccb = memblock_alloc_low(length, PAGE_SIZE);
13508ab919dSSumanth Korikkar 	if (!sccb)
13608ab919dSSumanth Korikkar 		return -ENOMEM;
13708ab919dSSumanth Korikkar 
13808ab919dSSumanth Korikkar 	memset(sccb, 0, length);
13908ab919dSSumanth Korikkar 	sccb->header.length = length;
14008ab919dSSumanth Korikkar 	sccb->header.control_mask[2] = 0x80;
14108ab919dSSumanth Korikkar 	if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO, sccb)) {
14208ab919dSSumanth Korikkar 		rc = -EIO;
14308ab919dSSumanth Korikkar 		goto out;
14408ab919dSSumanth Korikkar 	}
14508ab919dSSumanth Korikkar 	if (sccb->header.response_code != 0x0010) {
14608ab919dSSumanth Korikkar 		rc = -EIO;
14708ab919dSSumanth Korikkar 		goto out;
14808ab919dSSumanth Korikkar 	}
14908ab919dSSumanth Korikkar 	sclp_fill_core_info(info, sccb);
15008ab919dSSumanth Korikkar out:
151b6b486ecSHeiko Carstens 	memblock_free(sccb, length);
15208ab919dSSumanth Korikkar 	return rc;
153af51160eSHeiko Carstens }
154af51160eSHeiko Carstens 
sclp_early_console_detect(struct init_sccb * sccb)155d5ab7a34SHeiko Carstens static void __init sclp_early_console_detect(struct init_sccb *sccb)
15652733e01SHendrik Brueckner {
15752733e01SHendrik Brueckner 	if (sccb->header.response_code != 0x20)
15852733e01SHendrik Brueckner 		return;
15952733e01SHendrik Brueckner 
160b8435635SClaudio Imbrenda 	if (sclp_early_con_check_vt220(sccb))
16137c5f6c8SDavid Hildenbrand 		sclp.has_vt220 = 1;
16252733e01SHendrik Brueckner 
163d5ab7a34SHeiko Carstens 	if (sclp_early_con_check_linemode(sccb))
16437c5f6c8SDavid Hildenbrand 		sclp.has_linemode = 1;
16552733e01SHendrik Brueckner }
16652733e01SHendrik Brueckner 
sclp_early_adjust_va(void)167639886b7SAlexander Gordeev void __init __no_sanitize_address sclp_early_adjust_va(void)
168ada1da31SAlexander Gordeev {
169ada1da31SAlexander Gordeev 	sclp_early_sccb = __va((unsigned long)sclp_early_sccb);
170ada1da31SAlexander Gordeev }
171ada1da31SAlexander Gordeev 
sclp_early_detect(void)1727b50da53SMichael Holzheu void __init sclp_early_detect(void)
1737b50da53SMichael Holzheu {
174087c4d74SGerald Schaefer 	void *sccb = sclp_early_sccb;
1755d5de1a0SHendrik Brueckner 
176d25d23e1SSumanth Korikkar 	sclp_early_facilities_detect();
17752733e01SHendrik Brueckner 
178d5ab7a34SHeiko Carstens 	/*
179d5ab7a34SHeiko Carstens 	 * Turn off SCLP event notifications.  Also save remote masks in the
18052733e01SHendrik Brueckner 	 * sccb.  These are sufficient to detect sclp console capabilities.
18152733e01SHendrik Brueckner 	 */
182d5ab7a34SHeiko Carstens 	sclp_early_set_event_mask(sccb, 0, 0);
183d5ab7a34SHeiko Carstens 	sclp_early_console_detect(sccb);
1847b50da53SMichael Holzheu }
185