1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright IBM Corp. 2013
8 #define KMSG_COMPONENT "sclp_early"
9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11 #include <linux/errno.h>
12 #include <asm/ctl_reg.h>
15 #include "sclp_sdias.h"
18 static struct sclp_ipl_info sclp_ipl_info
;
20 struct sclp_info sclp
;
23 static void __init
sclp_early_facilities_detect(struct read_info_sccb
*sccb
)
25 struct sclp_core_entry
*cpue
;
26 u16 boot_cpu_address
, cpu
;
28 if (sclp_early_get_info(sccb
))
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
& 0x4000);
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
;
55 if (sccb
->hamaxpow
&& sccb
->hamaxpow
< 64)
56 sclp
.hamax
= (1UL << sccb
->hamaxpow
) - 1;
64 sclp
.max_cores
= sccb
->ncpurl
;
66 sclp
.max_cores
= sccb
->hcpua
+ 1;
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
)
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
;
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
);
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;
96 sclp
.hmfai
= sccb
->hmfai
;
97 sclp
.has_dirq
= !!(sccb
->cpudirq
& 0x80);
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.
105 void __init
sclp_early_get_ipl_info(struct sclp_ipl_info
*info
)
107 *info
= sclp_ipl_info
;
110 static struct sclp_core_info sclp_early_core_info __initdata
;
111 static int sclp_early_core_info_valid __initdata
;
113 static void __init
sclp_early_init_core_info(struct read_cpu_info_sccb
*sccb
)
115 if (!SCLP_HAS_CPU_INFO
)
117 memset(sccb
, 0, sizeof(*sccb
));
118 sccb
->header
.length
= sizeof(*sccb
);
119 if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO
, sccb
))
121 if (sccb
->header
.response_code
!= 0x0010)
123 sclp_fill_core_info(&sclp_early_core_info
, sccb
);
124 sclp_early_core_info_valid
= 1;
127 int __init
sclp_early_get_core_info(struct sclp_core_info
*info
)
129 if (!sclp_early_core_info_valid
)
131 *info
= sclp_early_core_info
;
135 static void __init
sclp_early_console_detect(struct init_sccb
*sccb
)
137 if (sccb
->header
.response_code
!= 0x20)
140 if (sclp_early_con_check_vt220(sccb
))
143 if (sclp_early_con_check_linemode(sccb
))
144 sclp
.has_linemode
= 1;
147 void __init
sclp_early_detect(void)
149 void *sccb
= sclp_early_sccb
;
151 sclp_early_facilities_detect(sccb
);
152 sclp_early_init_core_info(sccb
);
155 * Turn off SCLP event notifications. Also save remote masks in the
156 * sccb. These are sufficient to detect sclp console capabilities.
158 sclp_early_set_event_mask(sccb
, 0, 0);
159 sclp_early_console_detect(sccb
);