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 if (sccb
->fac85
& 0x02)
44 S390_lowcore
.machine_flags
|= MACHINE_FLAG_ESOP
;
45 if (sccb
->fac91
& 0x40)
46 S390_lowcore
.machine_flags
|= MACHINE_FLAG_TLB_GUEST
;
47 if (sccb
->cpuoff
> 134)
48 sclp
.has_diag318
= !!(sccb
->byte_134
& 0x80);
49 sclp
.rnmax
= sccb
->rnmax
? sccb
->rnmax
: sccb
->rnmax2
;
50 sclp
.rzm
= sccb
->rnsize
? sccb
->rnsize
: sccb
->rnsize2
;
54 if (sccb
->hamaxpow
&& sccb
->hamaxpow
< 64)
55 sclp
.hamax
= (1UL << sccb
->hamaxpow
) - 1;
63 sclp
.max_cores
= sccb
->ncpurl
;
65 sclp
.max_cores
= sccb
->hcpua
+ 1;
68 boot_cpu_address
= stap();
69 cpue
= (void *)sccb
+ sccb
->cpuoff
;
70 for (cpu
= 0; cpu
< sccb
->ncpurl
; cpue
++, cpu
++) {
71 if (boot_cpu_address
!= cpue
->core_id
)
73 sclp
.has_siif
= cpue
->siif
;
74 sclp
.has_sigpif
= cpue
->sigpif
;
75 sclp
.has_sief2
= cpue
->sief2
;
76 sclp
.has_gpere
= cpue
->gpere
;
77 sclp
.has_ib
= cpue
->ib
;
78 sclp
.has_cei
= cpue
->cei
;
79 sclp
.has_skey
= cpue
->skey
;
83 /* Save IPL information */
84 sclp_ipl_info
.is_valid
= 1;
85 if (sccb
->fac91
& 0x2)
86 sclp_ipl_info
.has_dump
= 1;
87 memcpy(&sclp_ipl_info
.loadparm
, &sccb
->loadparm
, LOADPARM_LEN
);
90 sclp
.hsa_size
= (sccb
->hsa_size
- 1) * PAGE_SIZE
;
91 sclp
.mtid
= (sccb
->fac42
& 0x80) ? (sccb
->fac42
& 31) : 0;
92 sclp
.mtid_cp
= (sccb
->fac42
& 0x80) ? (sccb
->fac43
& 31) : 0;
93 sclp
.mtid_prev
= (sccb
->fac42
& 0x80) ? (sccb
->fac66
& 31) : 0;
95 sclp
.hmfai
= sccb
->hmfai
;
99 * This function will be called after sclp_early_facilities_detect(), which gets
100 * called from early.c code. The sclp_early_facilities_detect() function retrieves
101 * and saves the IPL information.
103 void __init
sclp_early_get_ipl_info(struct sclp_ipl_info
*info
)
105 *info
= sclp_ipl_info
;
108 static struct sclp_core_info sclp_early_core_info __initdata
;
109 static int sclp_early_core_info_valid __initdata
;
111 static void __init
sclp_early_init_core_info(struct read_cpu_info_sccb
*sccb
)
113 if (!SCLP_HAS_CPU_INFO
)
115 memset(sccb
, 0, sizeof(*sccb
));
116 sccb
->header
.length
= sizeof(*sccb
);
117 if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO
, sccb
))
119 if (sccb
->header
.response_code
!= 0x0010)
121 sclp_fill_core_info(&sclp_early_core_info
, sccb
);
122 sclp_early_core_info_valid
= 1;
125 int __init
sclp_early_get_core_info(struct sclp_core_info
*info
)
127 if (!sclp_early_core_info_valid
)
129 *info
= sclp_early_core_info
;
133 static void __init
sclp_early_console_detect(struct init_sccb
*sccb
)
135 if (sccb
->header
.response_code
!= 0x20)
138 if (sclp_early_con_check_vt220(sccb
))
141 if (sclp_early_con_check_linemode(sccb
))
142 sclp
.has_linemode
= 1;
145 void __init
sclp_early_detect(void)
147 void *sccb
= &sclp_early_sccb
;
149 sclp_early_facilities_detect(sccb
);
150 sclp_early_init_core_info(sccb
);
153 * Turn off SCLP event notifications. Also save remote masks in the
154 * sccb. These are sufficient to detect sclp console capabilities.
156 sclp_early_set_event_mask(sccb
, 0, 0);
157 sclp_early_console_detect(sccb
);