diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 17:47:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 17:47:13 -0500 |
commit | 2dc10ad81fc017837037e60439662e1b16bdffb9 (patch) | |
tree | fc2f77874339b2f79499e3b34dc5ecb496b68dfc /arch/arm64/kernel/setup.c | |
parent | e627078a0cbdc0c391efeb5a2c4eb287328fd633 (diff) | |
parent | f8f8bdc48851da979c6e0e4808b6031122e4af47 (diff) |
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 updates from Catalin Marinas:
- "genirq: Introduce generic irq migration for cpu hotunplugged" patch
merged from tip/irq/for-arm to allow the arm64-specific part to be
upstreamed via the arm64 tree
- CPU feature detection reworked to cope with heterogeneous systems
where CPUs may not have exactly the same features. The features
reported by the kernel via internal data structures or ELF_HWCAP are
delayed until all the CPUs are up (and before user space starts)
- Support for 16KB pages, with the additional bonus of a 36-bit VA
space, though the latter only depending on EXPERT
- Implement native {relaxed, acquire, release} atomics for arm64
- New ASID allocation algorithm which avoids IPI on roll-over, together
with TLB invalidation optimisations (using local vs global where
feasible)
- KASan support for arm64
- EFI_STUB clean-up and isolation for the kernel proper (required by
KASan)
- copy_{to,from,in}_user optimisations (sharing the memcpy template)
- perf: moving arm64 to the arm32/64 shared PMU framework
- L1_CACHE_BYTES increased to 128 to accommodate Cavium hardware
- Support for the contiguous PTE hint on kernel mapping (16 consecutive
entries may be able to use a single TLB entry)
- Generic CONFIG_HZ now used on arm64
- defconfig updates
* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (91 commits)
arm64/efi: fix libstub build under CONFIG_MODVERSIONS
ARM64: Enable multi-core scheduler support by default
arm64/efi: move arm64 specific stub C code to libstub
arm64: page-align sections for DEBUG_RODATA
arm64: Fix build with CONFIG_ZONE_DMA=n
arm64: Fix compat register mappings
arm64: Increase the max granular size
arm64: remove bogus TASK_SIZE_64 check
arm64: make Timer Interrupt Frequency selectable
arm64/mm: use PAGE_ALIGNED instead of IS_ALIGNED
arm64: cachetype: fix definitions of ICACHEF_* flags
arm64: cpufeature: declare enable_cpu_capabilities as static
genirq: Make the cpuhotplug migration code less noisy
arm64: Constify hwcap name string arrays
arm64/kvm: Make use of the system wide safe values
arm64/debug: Make use of the system wide safe value
arm64: Move FP/ASIMD hwcap handling to common code
arm64/HWCAP: Use system wide safe values
arm64/capabilities: Make use of system wide safe value
arm64: Delay cpu feature capability checks
...
Diffstat (limited to 'arch/arm64/kernel/setup.c')
-rw-r--r-- | arch/arm64/kernel/setup.c | 245 |
1 files changed, 6 insertions, 239 deletions
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 232247945b1c..8119479147db 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/cache.h> | 29 | #include <linux/cache.h> |
30 | #include <linux/bootmem.h> | 30 | #include <linux/bootmem.h> |
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/screen_info.h> | 31 | #include <linux/screen_info.h> |
33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
34 | #include <linux/kexec.h> | 33 | #include <linux/kexec.h> |
@@ -44,7 +43,6 @@ | |||
44 | #include <linux/of_fdt.h> | 43 | #include <linux/of_fdt.h> |
45 | #include <linux/of_platform.h> | 44 | #include <linux/of_platform.h> |
46 | #include <linux/efi.h> | 45 | #include <linux/efi.h> |
47 | #include <linux/personality.h> | ||
48 | #include <linux/psci.h> | 46 | #include <linux/psci.h> |
49 | 47 | ||
50 | #include <asm/acpi.h> | 48 | #include <asm/acpi.h> |
@@ -54,6 +52,7 @@ | |||
54 | #include <asm/elf.h> | 52 | #include <asm/elf.h> |
55 | #include <asm/cpufeature.h> | 53 | #include <asm/cpufeature.h> |
56 | #include <asm/cpu_ops.h> | 54 | #include <asm/cpu_ops.h> |
55 | #include <asm/kasan.h> | ||
57 | #include <asm/sections.h> | 56 | #include <asm/sections.h> |
58 | #include <asm/setup.h> | 57 | #include <asm/setup.h> |
59 | #include <asm/smp_plat.h> | 58 | #include <asm/smp_plat.h> |
@@ -64,23 +63,6 @@ | |||
64 | #include <asm/efi.h> | 63 | #include <asm/efi.h> |
65 | #include <asm/xen/hypervisor.h> | 64 | #include <asm/xen/hypervisor.h> |
66 | 65 | ||
67 | unsigned long elf_hwcap __read_mostly; | ||
68 | EXPORT_SYMBOL_GPL(elf_hwcap); | ||
69 | |||
70 | #ifdef CONFIG_COMPAT | ||
71 | #define COMPAT_ELF_HWCAP_DEFAULT \ | ||
72 | (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\ | ||
73 | COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ | ||
74 | COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\ | ||
75 | COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ | ||
76 | COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\ | ||
77 | COMPAT_HWCAP_LPAE) | ||
78 | unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; | ||
79 | unsigned int compat_elf_hwcap2 __read_mostly; | ||
80 | #endif | ||
81 | |||
82 | DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); | ||
83 | |||
84 | phys_addr_t __fdt_pointer __initdata; | 66 | phys_addr_t __fdt_pointer __initdata; |
85 | 67 | ||
86 | /* | 68 | /* |
@@ -195,104 +177,6 @@ static void __init smp_build_mpidr_hash(void) | |||
195 | __flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash)); | 177 | __flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash)); |
196 | } | 178 | } |
197 | 179 | ||
198 | static void __init setup_processor(void) | ||
199 | { | ||
200 | u64 features; | ||
201 | s64 block; | ||
202 | u32 cwg; | ||
203 | int cls; | ||
204 | |||
205 | printk("CPU: AArch64 Processor [%08x] revision %d\n", | ||
206 | read_cpuid_id(), read_cpuid_id() & 15); | ||
207 | |||
208 | sprintf(init_utsname()->machine, ELF_PLATFORM); | ||
209 | elf_hwcap = 0; | ||
210 | |||
211 | cpuinfo_store_boot_cpu(); | ||
212 | |||
213 | /* | ||
214 | * Check for sane CTR_EL0.CWG value. | ||
215 | */ | ||
216 | cwg = cache_type_cwg(); | ||
217 | cls = cache_line_size(); | ||
218 | if (!cwg) | ||
219 | pr_warn("No Cache Writeback Granule information, assuming cache line size %d\n", | ||
220 | cls); | ||
221 | if (L1_CACHE_BYTES < cls) | ||
222 | pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n", | ||
223 | L1_CACHE_BYTES, cls); | ||
224 | |||
225 | /* | ||
226 | * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks. | ||
227 | * The blocks we test below represent incremental functionality | ||
228 | * for non-negative values. Negative values are reserved. | ||
229 | */ | ||
230 | features = read_cpuid(ID_AA64ISAR0_EL1); | ||
231 | block = cpuid_feature_extract_field(features, 4); | ||
232 | if (block > 0) { | ||
233 | switch (block) { | ||
234 | default: | ||
235 | case 2: | ||
236 | elf_hwcap |= HWCAP_PMULL; | ||
237 | case 1: | ||
238 | elf_hwcap |= HWCAP_AES; | ||
239 | case 0: | ||
240 | break; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | if (cpuid_feature_extract_field(features, 8) > 0) | ||
245 | elf_hwcap |= HWCAP_SHA1; | ||
246 | |||
247 | if (cpuid_feature_extract_field(features, 12) > 0) | ||
248 | elf_hwcap |= HWCAP_SHA2; | ||
249 | |||
250 | if (cpuid_feature_extract_field(features, 16) > 0) | ||
251 | elf_hwcap |= HWCAP_CRC32; | ||
252 | |||
253 | block = cpuid_feature_extract_field(features, 20); | ||
254 | if (block > 0) { | ||
255 | switch (block) { | ||
256 | default: | ||
257 | case 2: | ||
258 | elf_hwcap |= HWCAP_ATOMICS; | ||
259 | case 1: | ||
260 | /* RESERVED */ | ||
261 | case 0: | ||
262 | break; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | #ifdef CONFIG_COMPAT | ||
267 | /* | ||
268 | * ID_ISAR5_EL1 carries similar information as above, but pertaining to | ||
269 | * the AArch32 32-bit execution state. | ||
270 | */ | ||
271 | features = read_cpuid(ID_ISAR5_EL1); | ||
272 | block = cpuid_feature_extract_field(features, 4); | ||
273 | if (block > 0) { | ||
274 | switch (block) { | ||
275 | default: | ||
276 | case 2: | ||
277 | compat_elf_hwcap2 |= COMPAT_HWCAP2_PMULL; | ||
278 | case 1: | ||
279 | compat_elf_hwcap2 |= COMPAT_HWCAP2_AES; | ||
280 | case 0: | ||
281 | break; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | if (cpuid_feature_extract_field(features, 8) > 0) | ||
286 | compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1; | ||
287 | |||
288 | if (cpuid_feature_extract_field(features, 12) > 0) | ||
289 | compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2; | ||
290 | |||
291 | if (cpuid_feature_extract_field(features, 16) > 0) | ||
292 | compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32; | ||
293 | #endif | ||
294 | } | ||
295 | |||
296 | static void __init setup_machine_fdt(phys_addr_t dt_phys) | 180 | static void __init setup_machine_fdt(phys_addr_t dt_phys) |
297 | { | 181 | { |
298 | void *dt_virt = fixmap_remap_fdt(dt_phys); | 182 | void *dt_virt = fixmap_remap_fdt(dt_phys); |
@@ -406,8 +290,9 @@ u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; | |||
406 | 290 | ||
407 | void __init setup_arch(char **cmdline_p) | 291 | void __init setup_arch(char **cmdline_p) |
408 | { | 292 | { |
409 | setup_processor(); | 293 | pr_info("Boot CPU: AArch64 Processor [%08x]\n", read_cpuid_id()); |
410 | 294 | ||
295 | sprintf(init_utsname()->machine, ELF_PLATFORM); | ||
411 | init_mm.start_code = (unsigned long) _text; | 296 | init_mm.start_code = (unsigned long) _text; |
412 | init_mm.end_code = (unsigned long) _etext; | 297 | init_mm.end_code = (unsigned long) _etext; |
413 | init_mm.end_data = (unsigned long) _edata; | 298 | init_mm.end_data = (unsigned long) _edata; |
@@ -436,6 +321,9 @@ void __init setup_arch(char **cmdline_p) | |||
436 | 321 | ||
437 | paging_init(); | 322 | paging_init(); |
438 | relocate_initrd(); | 323 | relocate_initrd(); |
324 | |||
325 | kasan_init(); | ||
326 | |||
439 | request_standard_resources(); | 327 | request_standard_resources(); |
440 | 328 | ||
441 | early_ioremap_reset(); | 329 | early_ioremap_reset(); |
@@ -493,124 +381,3 @@ static int __init topology_init(void) | |||
493 | return 0; | 381 | return 0; |
494 | } | 382 | } |
495 | subsys_initcall(topology_init); | 383 | subsys_initcall(topology_init); |
496 | |||
497 | static const char *hwcap_str[] = { | ||
498 | "fp", | ||
499 | "asimd", | ||
500 | "evtstrm", | ||
501 | "aes", | ||
502 | "pmull", | ||
503 | "sha1", | ||
504 | "sha2", | ||
505 | "crc32", | ||
506 | "atomics", | ||
507 | NULL | ||
508 | }; | ||
509 | |||
510 | #ifdef CONFIG_COMPAT | ||
511 | static const char *compat_hwcap_str[] = { | ||
512 | "swp", | ||
513 | "half", | ||
514 | "thumb", | ||
515 | "26bit", | ||
516 | "fastmult", | ||
517 | "fpa", | ||
518 | "vfp", | ||
519 | "edsp", | ||
520 | "java", | ||
521 | "iwmmxt", | ||
522 | "crunch", | ||
523 | "thumbee", | ||
524 | "neon", | ||
525 | "vfpv3", | ||
526 | "vfpv3d16", | ||
527 | "tls", | ||
528 | "vfpv4", | ||
529 | "idiva", | ||
530 | "idivt", | ||
531 | "vfpd32", | ||
532 | "lpae", | ||
533 | "evtstrm" | ||
534 | }; | ||
535 | |||
536 | static const char *compat_hwcap2_str[] = { | ||
537 | "aes", | ||
538 | "pmull", | ||
539 | "sha1", | ||
540 | "sha2", | ||
541 | "crc32", | ||
542 | NULL | ||
543 | }; | ||
544 | #endif /* CONFIG_COMPAT */ | ||
545 | |||
546 | static int c_show(struct seq_file *m, void *v) | ||
547 | { | ||
548 | int i, j; | ||
549 | |||
550 | for_each_online_cpu(i) { | ||
551 | struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i); | ||
552 | u32 midr = cpuinfo->reg_midr; | ||
553 | |||
554 | /* | ||
555 | * glibc reads /proc/cpuinfo to determine the number of | ||
556 | * online processors, looking for lines beginning with | ||
557 | * "processor". Give glibc what it expects. | ||
558 | */ | ||
559 | seq_printf(m, "processor\t: %d\n", i); | ||
560 | |||
561 | /* | ||
562 | * Dump out the common processor features in a single line. | ||
563 | * Userspace should read the hwcaps with getauxval(AT_HWCAP) | ||
564 | * rather than attempting to parse this, but there's a body of | ||
565 | * software which does already (at least for 32-bit). | ||
566 | */ | ||
567 | seq_puts(m, "Features\t:"); | ||
568 | if (personality(current->personality) == PER_LINUX32) { | ||
569 | #ifdef CONFIG_COMPAT | ||
570 | for (j = 0; compat_hwcap_str[j]; j++) | ||
571 | if (compat_elf_hwcap & (1 << j)) | ||
572 | seq_printf(m, " %s", compat_hwcap_str[j]); | ||
573 | |||
574 | for (j = 0; compat_hwcap2_str[j]; j++) | ||
575 | if (compat_elf_hwcap2 & (1 << j)) | ||
576 | seq_printf(m, " %s", compat_hwcap2_str[j]); | ||
577 | #endif /* CONFIG_COMPAT */ | ||
578 | } else { | ||
579 | for (j = 0; hwcap_str[j]; j++) | ||
580 | if (elf_hwcap & (1 << j)) | ||
581 | seq_printf(m, " %s", hwcap_str[j]); | ||
582 | } | ||
583 | seq_puts(m, "\n"); | ||
584 | |||
585 | seq_printf(m, "CPU implementer\t: 0x%02x\n", | ||
586 | MIDR_IMPLEMENTOR(midr)); | ||
587 | seq_printf(m, "CPU architecture: 8\n"); | ||
588 | seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr)); | ||
589 | seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr)); | ||
590 | seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr)); | ||
591 | } | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
597 | { | ||
598 | return *pos < 1 ? (void *)1 : NULL; | ||
599 | } | ||
600 | |||
601 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
602 | { | ||
603 | ++*pos; | ||
604 | return NULL; | ||
605 | } | ||
606 | |||
607 | static void c_stop(struct seq_file *m, void *v) | ||
608 | { | ||
609 | } | ||
610 | |||
611 | const struct seq_operations cpuinfo_op = { | ||
612 | .start = c_start, | ||
613 | .next = c_next, | ||
614 | .stop = c_stop, | ||
615 | .show = c_show | ||
616 | }; | ||