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

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

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ 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         if (!fixup_exception(regs))
181                 disabled_wait();
182 }
183 
184 static noinline __init void setup_lowcore_early(void)
185 {
186         psw_t psw;
187 
188         psw.addr = (unsigned long)early_pgm_check_handler;
189         psw.mask = PSW_KERNEL_BITS;
190         get_lowcore()->program_new_psw = psw;
191         get_lowcore()->preempt_count = INIT_PREEMPT_COUNT;
192 }
193 
194 static __init void detect_diag9c(void)
195 {
196         unsigned int cpu_address;
197         int rc;
198 
199         cpu_address = stap();
200         diag_stat_inc(DIAG_STAT_X09C);
201         asm volatile(
202                 "       diag    %2,0,0x9c\n"
203                 "0:     la      %0,0\n"
204                 "1:\n"
205                 EX_TABLE(0b,1b)
206                 : "=d" (rc) : "" (-EOPNOTSUPP), "d" (cpu_address) : "cc");
207         if (!rc)
208                 get_lowcore()->machine_flags |= MACHINE_FLAG_DIAG9C;
209 }
210 
211 static __init void detect_machine_facilities(void)
212 {
213         if (test_facility(8)) {
214                 get_lowcore()->machine_flags |= MACHINE_FLAG_EDAT1;
215                 system_ctl_set_bit(0, CR0_EDAT_BIT);
216         }
217         if (test_facility(78))
218                 get_lowcore()->machine_flags |= MACHINE_FLAG_EDAT2;
219         if (test_facility(3))
220                 get_lowcore()->machine_flags |= MACHINE_FLAG_IDTE;
221         if (test_facility(50) && test_facility(73)) {
222                 get_lowcore()->machine_flags |= MACHINE_FLAG_TE;
223                 system_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT);
224         }
225         if (test_facility(51))
226                 get_lowcore()->machine_flags |= MACHINE_FLAG_TLB_LC;
227         if (test_facility(129))
228                 system_ctl_set_bit(0, CR0_VECTOR_BIT);
229         if (test_facility(130))
230                 get_lowcore()->machine_flags |= MACHINE_FLAG_NX;
231         if (test_facility(133))
232                 get_lowcore()->machine_flags |= MACHINE_FLAG_GS;
233         if (test_facility(139) && (tod_clock_base.tod >> 63)) {
234                 /* Enabled signed clock comparator comparisons */
235                 get_lowcore()->machine_flags |= MACHINE_FLAG_SCC;
236                 clock_comparator_max = -1ULL >> 1;
237                 system_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SIGN_BIT);
238         }
239         if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) {
240                 get_lowcore()->machine_flags |= MACHINE_FLAG_PCI_MIO;
241                 /* the control bit is set during PCI initialization */
242         }
243         if (test_facility(194))
244                 get_lowcore()->machine_flags |= MACHINE_FLAG_RDP;
245 }
246 
247 static inline void save_vector_registers(void)
248 {
249 #ifdef CONFIG_CRASH_DUMP
250         if (test_facility(129))
251                 save_vx_regs(boot_cpu_vector_save_area);
252 #endif
253 }
254 
255 static inline void setup_low_address_protection(void)
256 {
257         system_ctl_set_bit(0, CR0_LOW_ADDRESS_PROTECTION_BIT);
258 }
259 
260 static inline void setup_access_registers(void)
261 {
262         unsigned int acrs[NUM_ACRS] = { 0 };
263 
264         restore_access_regs(acrs);
265 }
266 
267 char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
268 static void __init setup_boot_command_line(void)
269 {
270         /* copy arch command line */
271         strscpy(boot_command_line, early_command_line, COMMAND_LINE_SIZE);
272 }
273 
274 static void __init sort_amode31_extable(void)
275 {
276         sort_extable(__start_amode31_ex_table, __stop_amode31_ex_table);
277 }
278 
279 void __init startup_init(void)
280 {
281         kasan_early_init();
282         reset_tod_clock();
283         time_early_init();
284         init_kernel_storage_key();
285         lockdep_off();
286         sort_amode31_extable();
287         setup_lowcore_early();
288         detect_machine_type();
289         setup_arch_string();
290         setup_boot_command_line();
291         detect_diag9c();
292         detect_machine_facilities();
293         save_vector_registers();
294         setup_topology();
295         sclp_early_detect();
296         setup_low_address_protection();
297         setup_access_registers();
298         lockdep_on();
299 }
300 

~ [ 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