~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/kernel/early.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  *    Copyright IBM Corp. 2007, 2009
  4  *    Author(s): Hongjie Yang <hongjie@us.ibm.com>,
  5  */
  6 
  7 #define KMSG_COMPONENT "setup"
  8 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  9 
 10 #include <linux/compiler.h>
 11 #include <linux/init.h>
 12 #include <linux/errno.h>
 13 #include <linux/string.h>
 14 #include <linux/ctype.h>
 15 #include <linux/lockdep.h>
 16 #include <linux/extable.h>
 17 #include <linux/pfn.h>
 18 #include <linux/uaccess.h>
 19 #include <linux/kernel.h>
 20 #include <asm/asm-extable.h>
 21 #include <linux/memblock.h>
 22 #include <asm/access-regs.h>
 23 #include <asm/diag.h>
 24 #include <asm/ebcdic.h>
 25 #include <asm/fpu.h>
 26 #include <asm/ipl.h>
 27 #include <asm/lowcore.h>
 28 #include <asm/processor.h>
 29 #include <asm/sections.h>
 30 #include <asm/setup.h>
 31 #include <asm/sysinfo.h>
 32 #include <asm/cpcmd.h>
 33 #include <asm/sclp.h>
 34 #include <asm/facility.h>
 35 #include <asm/boot_data.h>
 36 #include "entry.h"
 37 
 38 #define decompressor_handled_param(param)                       \
 39 static int __init ignore_decompressor_param_##param(char *s)    \
 40 {                                                               \
 41         return 0;                                               \
 42 }                                                               \
 43 early_param(#param, ignore_decompressor_param_##param)
 44 
 45 decompressor_handled_param(mem);
 46 decompressor_handled_param(vmalloc);
 47 decompressor_handled_param(dfltcc);
 48 decompressor_handled_param(facilities);
 49 decompressor_handled_param(nokaslr);
 50 decompressor_handled_param(cmma);
 51 decompressor_handled_param(relocate_lowcore);
 52 #if IS_ENABLED(CONFIG_KVM)
 53 decompressor_handled_param(prot_virt);
 54 #endif
 55 
 56 static void __init kasan_early_init(void)
 57 {
 58 #ifdef CONFIG_KASAN
 59         init_task.kasan_depth = 0;
 60         sclp_early_printk("KernelAddressSanitizer initialized\n");
 61 #endif
 62 }
 63 
 64 static void __init reset_tod_clock(void)
 65 {
 66         union tod_clock clk;
 67 
 68         if (store_tod_clock_ext_cc(&clk) == 0)
 69                 return;
 70         /* TOD clock not running. Set the clock to Unix Epoch. */
 71         if (set_tod_clock(TOD_UNIX_EPOCH) || store_tod_clock_ext_cc(&clk))
 72                 disabled_wait();
 73 
 74         memset(&tod_clock_base, 0, sizeof(tod_clock_base));
 75         tod_clock_base.tod = TOD_UNIX_EPOCH;
 76         get_lowcore()->last_update_clock = TOD_UNIX_EPOCH;
 77 }
 78 
 79 /*
 80  * Initialize storage key for kernel pages
 81  */
 82 static noinline __init void init_kernel_storage_key(void)
 83 {
 84 #if PAGE_DEFAULT_KEY
 85         unsigned long end_pfn, init_pfn;
 86 
 87         end_pfn = PFN_UP(__pa(_end));
 88 
 89         for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
 90                 page_set_storage_key(init_pfn << PAGE_SHIFT,
 91                                      PAGE_DEFAULT_KEY, 0);
 92 #endif
 93 }
 94 
 95 static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE);
 96 
 97 static noinline __init void detect_machine_type(void)
 98 {
 99         struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page;
100 
101         /* Check current-configuration-level */
102         if (stsi(NULL, 0, 0, 0) <= 2) {
103                 get_lowcore()->machine_flags |= MACHINE_FLAG_LPAR;
104                 return;
105         }
106         /* Get virtual-machine cpu information. */
107         if (stsi(vmms, 3, 2, 2) || !vmms->count)
108                 return;
109 
110         /* Detect known hypervisors */
111         if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3))
112                 get_lowcore()->machine_flags |= MACHINE_FLAG_KVM;
113         else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4))
114                 get_lowcore()->machine_flags |= MACHINE_FLAG_VM;
115 }
116 
117 /* Remove leading, trailing and double whitespace. */
118 static inline void strim_all(char *str)
119 {
120         char *s;
121 
122         s = strim(str);
123         if (s != str)
124                 memmove(str, s, strlen(s));
125         while (*str) {
126                 if (!isspace(*str++))
127                         continue;
128                 if (isspace(*str)) {
129                         s = skip_spaces(str);
130                         memmove(str, s, strlen(s) + 1);
131                 }
132         }
133 }
134 
135 static noinline __init void setup_arch_string(void)
136 {
137         struct sysinfo_1_1_1 *mach = (struct sysinfo_1_1_1 *)&sysinfo_page;
138         struct sysinfo_3_2_2 *vm = (struct sysinfo_3_2_2 *)&sysinfo_page;
139         char mstr[80], hvstr[17];
140 
141         if (stsi(mach, 1, 1, 1))
142                 return;
143         EBCASC(mach->manufacturer, sizeof(mach->manufacturer));
144         EBCASC(mach->type, sizeof(mach->type));
145         EBCASC(mach->model, sizeof(mach->model));
146         EBCASC(mach->model_capacity, sizeof(mach->model_capacity));
147         sprintf(mstr, "%-16.16s %-4.4s %-16.16s %-16.16s",
148                 mach->manufacturer, mach->type,
149                 mach->model, mach->model_capacity);
150         strim_all(mstr);
151         if (stsi(vm, 3, 2, 2) == 0 && vm->count) {
152                 EBCASC(vm->vm[0].cpi, sizeof(vm->vm[0].cpi));
153                 sprintf(hvstr, "%-16.16s", vm->vm[0].cpi);
154                 strim_all(hvstr);
155         } else {
156                 sprintf(hvstr, "%s",
157                         MACHINE_IS_LPAR ? "LPAR" :
158                         MACHINE_IS_VM ? "z/VM" :
159                         MACHINE_IS_KVM ? "KVM" : "unknown");
160         }
161         dump_stack_set_arch_desc("%s (%s)", mstr, hvstr);
162 }
163 
164 static __init void setup_topology(void)
165 {
166         int max_mnest;
167 
168         if (!test_facility(11))
169                 return;
170         get_lowcore()->machine_flags |= MACHINE_FLAG_TOPOLOGY;
171         for (max_mnest = 6; max_mnest > 1; max_mnest--) {
172                 if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0)
173                         break;
174         }
175         topology_max_mnest = max_mnest;
176 }
177 
178 void __do_early_pgm_check(struct pt_regs *regs)
179 {
180         struct lowcore *lc = get_lowcore();
181         unsigned long ip;
182 
183         regs->int_code = lc->pgm_int_code;
184         regs->int_parm_long = lc->trans_exc_code;
185         ip = __rewind_psw(regs->psw, regs->int_code >> 16);
186 
187         /* Monitor Event? Might be a warning */
188         if ((regs->int_code & PGM_INT_CODE_MASK) == 0x40) {
189                 if (report_bug(ip, regs) == BUG_TRAP_TYPE_WARN)
190                         return;
191         }
192         if (fixup_exception(regs))
193                 return;
194         disabled_wait();
195 }
196 
197 static noinline __init void setup_lowcore_early(void)
198 {
199         struct lowcore *lc = get_lowcore();
200         psw_t psw;
201 
202         psw.addr = (unsigned long)early_pgm_check_handler;
203         psw.mask = PSW_KERNEL_BITS;
204         lc->program_new_psw = psw;
205         lc->preempt_count = INIT_PREEMPT_COUNT;
206         lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW);
207         lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW);
208 }
209 
210 static __init void detect_diag9c(void)
211 {
212         unsigned int cpu_address;
213         int rc;
214 
215         cpu_address = stap();
216         diag_stat_inc(DIAG_STAT_X09C);
217         asm volatile(
218                 "       diag    %2,0,0x9c\n"
219                 "0:     la      %0,0\n"
220                 "1:\n"
221                 EX_TABLE(0b,1b)
222                 : "=d" (rc) : "" (-EOPNOTSUPP), "d" (cpu_address) : "cc");
223         if (!rc)
224                 get_lowcore()->machine_flags |= MACHINE_FLAG_DIAG9C;
225 }
226 
227 static __init void detect_machine_facilities(void)
228 {
229         if (test_facility(8)) {
230                 get_lowcore()->machine_flags |= MACHINE_FLAG_EDAT1;
231                 system_ctl_set_bit(0, CR0_EDAT_BIT);
232         }
233         if (test_facility(78))
234                 get_lowcore()->machine_flags |= MACHINE_FLAG_EDAT2;
235         if (test_facility(3))
236                 get_lowcore()->machine_flags |= MACHINE_FLAG_IDTE;
237         if (test_facility(50) && test_facility(73)) {
238                 get_lowcore()->machine_flags |= MACHINE_FLAG_TE;
239                 system_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT);
240         }
241         if (test_facility(51))
242                 get_lowcore()->machine_flags |= MACHINE_FLAG_TLB_LC;
243         if (test_facility(129))
244                 system_ctl_set_bit(0, CR0_VECTOR_BIT);
245         if (test_facility(130))
246                 get_lowcore()->machine_flags |= MACHINE_FLAG_NX;
247         if (test_facility(133))
248                 get_lowcore()->machine_flags |= MACHINE_FLAG_GS;
249         if (test_facility(139) && (tod_clock_base.tod >> 63)) {
250                 /* Enabled signed clock comparator comparisons */
251                 get_lowcore()->machine_flags |= MACHINE_FLAG_SCC;
252                 clock_comparator_max = -1ULL >> 1;
253                 system_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SIGN_BIT);
254         }
255         if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) {
256                 get_lowcore()->machine_flags |= MACHINE_FLAG_PCI_MIO;
257                 /* the control bit is set during PCI initialization */
258         }
259         if (test_facility(194))
260                 get_lowcore()->machine_flags |= MACHINE_FLAG_RDP;
261 }
262 
263 static inline void save_vector_registers(void)
264 {
265 #ifdef CONFIG_CRASH_DUMP
266         if (test_facility(129))
267                 save_vx_regs(boot_cpu_vector_save_area);
268 #endif
269 }
270 
271 static inline void setup_low_address_protection(void)
272 {
273         system_ctl_set_bit(0, CR0_LOW_ADDRESS_PROTECTION_BIT);
274 }
275 
276 static inline void setup_access_registers(void)
277 {
278         unsigned int acrs[NUM_ACRS] = { 0 };
279 
280         restore_access_regs(acrs);
281 }
282 
283 char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
284 static void __init setup_boot_command_line(void)
285 {
286         /* copy arch command line */
287         strscpy(boot_command_line, early_command_line, COMMAND_LINE_SIZE);
288 }
289 
290 static void __init sort_amode31_extable(void)
291 {
292         sort_extable(__start_amode31_ex_table, __stop_amode31_ex_table);
293 }
294 
295 void __init startup_init(void)
296 {
297         kasan_early_init();
298         reset_tod_clock();
299         time_early_init();
300         init_kernel_storage_key();
301         lockdep_off();
302         sort_amode31_extable();
303         setup_lowcore_early();
304         detect_machine_type();
305         setup_arch_string();
306         setup_boot_command_line();
307         detect_diag9c();
308         detect_machine_facilities();
309         save_vector_registers();
310         setup_topology();
311         sclp_early_detect();
312         setup_low_address_protection();
313         setup_access_registers();
314         lockdep_on();
315 }
316 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php