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

TOMOYO Linux Cross Reference
Linux/arch/arm64/kernel/setup.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Based on arch/arm/kernel/setup.c
  3  *
  4  * Copyright (C) 1995-2001 Russell King
  5  * Copyright (C) 2012 ARM Ltd.
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License version 2 as
  9  * published by the Free Software Foundation.
 10  *
 11  * This program is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 18  */
 19 
 20 #include <linux/export.h>
 21 #include <linux/kernel.h>
 22 #include <linux/stddef.h>
 23 #include <linux/ioport.h>
 24 #include <linux/delay.h>
 25 #include <linux/utsname.h>
 26 #include <linux/initrd.h>
 27 #include <linux/console.h>
 28 #include <linux/bootmem.h>
 29 #include <linux/seq_file.h>
 30 #include <linux/screen_info.h>
 31 #include <linux/init.h>
 32 #include <linux/kexec.h>
 33 #include <linux/crash_dump.h>
 34 #include <linux/root_dev.h>
 35 #include <linux/clk-provider.h>
 36 #include <linux/cpu.h>
 37 #include <linux/interrupt.h>
 38 #include <linux/smp.h>
 39 #include <linux/fs.h>
 40 #include <linux/proc_fs.h>
 41 #include <linux/memblock.h>
 42 #include <linux/of_fdt.h>
 43 #include <linux/of_platform.h>
 44 #include <linux/personality.h>
 45 
 46 #include <asm/cputype.h>
 47 #include <asm/elf.h>
 48 #include <asm/cputable.h>
 49 #include <asm/sections.h>
 50 #include <asm/setup.h>
 51 #include <asm/smp_plat.h>
 52 #include <asm/cacheflush.h>
 53 #include <asm/tlbflush.h>
 54 #include <asm/traps.h>
 55 #include <asm/memblock.h>
 56 #include <asm/psci.h>
 57 
 58 unsigned int processor_id;
 59 EXPORT_SYMBOL(processor_id);
 60 
 61 unsigned int elf_hwcap __read_mostly;
 62 EXPORT_SYMBOL_GPL(elf_hwcap);
 63 
 64 static const char *cpu_name;
 65 static const char *machine_name;
 66 phys_addr_t __fdt_pointer __initdata;
 67 
 68 /*
 69  * Standard memory resources
 70  */
 71 static struct resource mem_res[] = {
 72         {
 73                 .name = "Kernel code",
 74                 .start = 0,
 75                 .end = 0,
 76                 .flags = IORESOURCE_MEM
 77         },
 78         {
 79                 .name = "Kernel data",
 80                 .start = 0,
 81                 .end = 0,
 82                 .flags = IORESOURCE_MEM
 83         }
 84 };
 85 
 86 #define kernel_code mem_res[0]
 87 #define kernel_data mem_res[1]
 88 
 89 void __init early_print(const char *str, ...)
 90 {
 91         char buf[256];
 92         va_list ap;
 93 
 94         va_start(ap, str);
 95         vsnprintf(buf, sizeof(buf), str, ap);
 96         va_end(ap);
 97 
 98         printk("%s", buf);
 99 }
100 
101 struct cpuinfo_arm64 {
102         struct cpu      cpu;
103         u32             reg_midr;
104 };
105 
106 static DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
107 
108 void cpuinfo_store_cpu(void)
109 {
110         struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
111         info->reg_midr = read_cpuid_id();
112 }
113 
114 static void __init setup_processor(void)
115 {
116         struct cpu_info *cpu_info;
117 
118         /*
119          * locate processor in the list of supported processor
120          * types.  The linker builds this table for us from the
121          * entries in arch/arm/mm/proc.S
122          */
123         cpu_info = lookup_processor_type(read_cpuid_id());
124         if (!cpu_info) {
125                 printk("CPU configuration botched (ID %08x), unable to continue.\n",
126                        read_cpuid_id());
127                 while (1);
128         }
129 
130         cpu_name = cpu_info->cpu_name;
131 
132         printk("CPU: %s [%08x] revision %d\n",
133                cpu_name, read_cpuid_id(), read_cpuid_id() & 15);
134 
135         sprintf(init_utsname()->machine, "aarch64");
136         elf_hwcap = 0;
137 }
138 
139 static void __init setup_machine_fdt(phys_addr_t dt_phys)
140 {
141         struct boot_param_header *devtree;
142         unsigned long dt_root;
143 
144         cpuinfo_store_cpu();
145 
146         /* Check we have a non-NULL DT pointer */
147         if (!dt_phys) {
148                 early_print("\n"
149                         "Error: NULL or invalid device tree blob\n"
150                         "The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"
151                         "\nPlease check your bootloader.\n");
152 
153                 while (true)
154                         cpu_relax();
155 
156         }
157 
158         devtree = phys_to_virt(dt_phys);
159 
160         /* Check device tree validity */
161         if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) {
162                 early_print("\n"
163                         "Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n"
164                         "Expected 0x%x, found 0x%x\n"
165                         "\nPlease check your bootloader.\n",
166                         dt_phys, devtree, OF_DT_HEADER,
167                         be32_to_cpu(devtree->magic));
168 
169                 while (true)
170                         cpu_relax();
171         }
172 
173         initial_boot_params = devtree;
174         dt_root = of_get_flat_dt_root();
175 
176         machine_name = of_get_flat_dt_prop(dt_root, "model", NULL);
177         if (!machine_name)
178                 machine_name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
179         if (!machine_name)
180                 machine_name = "<unknown>";
181         pr_info("Machine: %s\n", machine_name);
182 
183         /* Retrieve various information from the /chosen node */
184         of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
185         /* Initialize {size,address}-cells info */
186         of_scan_flat_dt(early_init_dt_scan_root, NULL);
187         /* Setup memory, calling early_init_dt_add_memory_arch */
188         of_scan_flat_dt(early_init_dt_scan_memory, NULL);
189 }
190 
191 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
192 {
193         base &= PAGE_MASK;
194         size &= PAGE_MASK;
195         if (base + size < PHYS_OFFSET) {
196                 pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
197                            base, base + size);
198                 return;
199         }
200         if (base < PHYS_OFFSET) {
201                 pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
202                            base, PHYS_OFFSET);
203                 size -= PHYS_OFFSET - base;
204                 base = PHYS_OFFSET;
205         }
206         memblock_add(base, size);
207 }
208 
209 void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
210 {
211         return __va(memblock_alloc(size, align));
212 }
213 
214 /*
215  * Limit the memory size that was specified via FDT.
216  */
217 static int __init early_mem(char *p)
218 {
219         phys_addr_t limit;
220 
221         if (!p)
222                 return 1;
223 
224         limit = memparse(p, &p) & PAGE_MASK;
225         pr_notice("Memory limited to %lldMB\n", limit >> 20);
226 
227         memblock_enforce_memory_limit(limit);
228 
229         return 0;
230 }
231 early_param("mem", early_mem);
232 
233 static void __init request_standard_resources(void)
234 {
235         struct memblock_region *region;
236         struct resource *res;
237 
238         kernel_code.start   = virt_to_phys(_text);
239         kernel_code.end     = virt_to_phys(_etext - 1);
240         kernel_data.start   = virt_to_phys(_sdata);
241         kernel_data.end     = virt_to_phys(_end - 1);
242 
243         for_each_memblock(memory, region) {
244                 res = alloc_bootmem_low(sizeof(*res));
245                 res->name  = "System RAM";
246                 res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
247                 res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
248                 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
249 
250                 request_resource(&iomem_resource, res);
251 
252                 if (kernel_code.start >= res->start &&
253                     kernel_code.end <= res->end)
254                         request_resource(res, &kernel_code);
255                 if (kernel_data.start >= res->start &&
256                     kernel_data.end <= res->end)
257                         request_resource(res, &kernel_data);
258         }
259 }
260 
261 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
262 
263 void __init setup_arch(char **cmdline_p)
264 {
265         setup_processor();
266 
267         setup_machine_fdt(__fdt_pointer);
268 
269         init_mm.start_code = (unsigned long) _text;
270         init_mm.end_code   = (unsigned long) _etext;
271         init_mm.end_data   = (unsigned long) _edata;
272         init_mm.brk        = (unsigned long) _end;
273 
274         *cmdline_p = boot_command_line;
275 
276         parse_early_param();
277 
278         arm64_memblock_init();
279 
280         paging_init();
281         request_standard_resources();
282 
283         unflatten_device_tree();
284 
285         psci_init();
286 
287         cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
288 #ifdef CONFIG_SMP
289         smp_init_cpus();
290 #endif
291 
292 #ifdef CONFIG_VT
293 #if defined(CONFIG_VGA_CONSOLE)
294         conswitchp = &vga_con;
295 #elif defined(CONFIG_DUMMY_CONSOLE)
296         conswitchp = &dummy_con;
297 #endif
298 #endif
299 }
300 
301 static int __init arm64_device_init(void)
302 {
303         of_clk_init(NULL);
304         of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
305         return 0;
306 }
307 arch_initcall(arm64_device_init);
308 
309 static int __init topology_init(void)
310 {
311         int i;
312 
313         for_each_possible_cpu(i) {
314                 struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
315                 cpu->hotpluggable = 1;
316                 register_cpu(cpu, i);
317         }
318 
319         return 0;
320 }
321 subsys_initcall(topology_init);
322 
323 static const char *hwcap_str[] = {
324         "fp",
325         "asimd",
326         NULL
327 };
328 
329 #ifdef CONFIG_COMPAT
330 static const char *compat_hwcap_str[] = {
331         "swp",
332         "half",
333         "thumb",
334         "26bit",
335         "fastmult",
336         "fpa",
337         "vfp",
338         "edsp",
339         "java",
340         "iwmmxt",
341         "crunch",
342         "thumbee",
343         "neon",
344         "vfpv3",
345         "vfpv3d16",
346         "tls",
347         "vfpv4",
348         "idiva",
349         "idivt",
350         "vfpd32",
351         "lpae",
352         "evtstrm"
353 };
354 #endif /* CONFIG_COMPAT */
355 
356 static int c_show(struct seq_file *m, void *v)
357 {
358         int i, j;
359 
360         for_each_online_cpu(i) {
361                 struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
362                 u32 midr = cpuinfo->reg_midr;
363 
364                 /*
365                  * glibc reads /proc/cpuinfo to determine the number of
366                  * online processors, looking for lines beginning with
367                  * "processor".  Give glibc what it expects.
368                  */
369 #ifdef CONFIG_SMP
370                 seq_printf(m, "processor\t: %d\n", i);
371 #endif
372                 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
373                            loops_per_jiffy / (500000UL/HZ),
374                            loops_per_jiffy / (5000UL/HZ) % 100);
375 
376                 /*
377                  * Dump out the common processor features in a single line.
378                  * Userspace should read the hwcaps with getauxval(AT_HWCAP)
379                  * rather than attempting to parse this, but there's a body of
380                  * software which does already (at least for 32-bit).
381                  */
382                 seq_puts(m, "Features\t:");
383                 if (personality(current->personality) == PER_LINUX32) {
384 #ifdef CONFIG_COMPAT
385                         for (j = 0; compat_hwcap_str[j]; j++)
386                                 if (COMPAT_ELF_HWCAP & (1 << j))
387                                         seq_printf(m, " %s", compat_hwcap_str[j]);
388 #endif /* CONFIG_COMPAT */
389                 } else {
390                         for (j = 0; hwcap_str[j]; j++)
391                                 if (elf_hwcap & (1 << j))
392                                         seq_printf(m, " %s", hwcap_str[j]);
393                 }
394                 seq_puts(m, "\n");
395 
396                 seq_printf(m, "CPU implementer\t: 0x%02x\n", (midr >> 24));
397                 seq_printf(m, "CPU architecture: 8\n");
398                 seq_printf(m, "CPU variant\t: 0x%x\n", ((midr >> 20) & 0xf));
399                 seq_printf(m, "CPU part\t: 0x%03x\n", ((midr >> 4) & 0xfff));
400                 seq_printf(m, "CPU revision\t: %d\n\n", (midr & 0xf));
401         }
402 
403         return 0;
404 }
405 
406 static void *c_start(struct seq_file *m, loff_t *pos)
407 {
408         return *pos < 1 ? (void *)1 : NULL;
409 }
410 
411 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
412 {
413         ++*pos;
414         return NULL;
415 }
416 
417 static void c_stop(struct seq_file *m, void *v)
418 {
419 }
420 
421 const struct seq_operations cpuinfo_op = {
422         .start  = c_start,
423         .next   = c_next,
424         .stop   = c_stop,
425         .show   = c_show
426 };
427 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp