diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kernel/atags.h | 5 | ||||
-rw-r--r-- | arch/arm/kernel/atags_parse.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/devtree.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 3 | ||||
-rw-r--r-- | arch/arm/kernel/fiq.c | 9 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 21 | ||||
-rw-r--r-- | arch/arm/kernel/module.c | 8 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_cpu.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 21 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 23 | ||||
-rw-r--r-- | arch/arm/kernel/v7m.c | 19 |
14 files changed, 89 insertions, 49 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 86d10dd47dc4..5140df5f23aa 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_ATAGS_PROC) += atags_proc.o obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += atags_compat.o ifeq ($(CONFIG_CPU_V7M),y) -obj-y += entry-v7m.o +obj-y += entry-v7m.o v7m.o else obj-y += entry-armv.o endif diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h index 9edc9692332d..ec4164da6e30 100644 --- a/arch/arm/kernel/atags.h +++ b/arch/arm/kernel/atags.h @@ -7,9 +7,10 @@ static inline void save_atags(struct tag *tags) { } void convert_to_tag_list(struct tag *tags); #ifdef CONFIG_ATAGS -struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr); +const struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer, + unsigned int machine_nr); #else -static inline struct machine_desc * +static inline const struct machine_desc * setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr) { early_print("no ATAGS support: can't continue\n"); diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c index 14512e6931d8..8c14de8180c0 100644 --- a/arch/arm/kernel/atags_parse.c +++ b/arch/arm/kernel/atags_parse.c @@ -178,11 +178,11 @@ static void __init squash_mem_tags(struct tag *tag) tag->hdr.tag = ATAG_NONE; } -struct machine_desc * __init setup_machine_tags(phys_addr_t __atags_pointer, - unsigned int machine_nr) +const struct machine_desc * __init +setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr) { struct tag *tags = (struct tag *)&default_tags; - struct machine_desc *mdesc = NULL, *p; + const struct machine_desc *mdesc = NULL, *p; char *from = default_command_line; default_tags.mem.start = PHYS_OFFSET; diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index 5859c8bc727c..eae1976f859d 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -176,10 +176,10 @@ void __init arm_dt_init_cpu_maps(void) * If a dtb was passed to the kernel in r2, then use it to choose the * correct machine_desc and to setup the system. */ -struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) +const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) { struct boot_param_header *devtree; - struct machine_desc *mdesc, *mdesc_best = NULL; + const struct machine_desc *mdesc, *mdesc_best = NULL; unsigned int score, mdesc_score = ~1; unsigned long dt_root; const char *model; @@ -188,7 +188,7 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) DT_MACHINE_START(GENERIC_DT, "Generic DT based system") MACHINE_END - mdesc_best = (struct machine_desc *)&__mach_desc_GENERIC_DT; + mdesc_best = &__mach_desc_GENERIC_DT; #endif if (!dt_phys) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index d40d0ef389db..9cbe70c8b0ef 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -357,7 +357,8 @@ ENDPROC(__pabt_svc) .endm .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) #ifndef CONFIG_MMU #warning "NPTL on non MMU needs fixing" #else diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 25442f451148..918875d96d5d 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -84,17 +84,14 @@ int show_fiq_list(struct seq_file *p, int prec) void set_fiq_handler(void *start, unsigned int length) { -#if defined(CONFIG_CPU_USE_DOMAINS) - void *base = (void *)0xffff0000; -#else void *base = vectors_page; -#endif unsigned offset = FIQ_OFFSET; memcpy(base + offset, start, length); + if (!cache_is_vipt_nonaliasing()) + flush_icache_range((unsigned long)base + offset, offset + + length); flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); - if (!vectors_high()) - flush_icache_range(offset, offset + length); } int claim_fiq(struct fiq_handler *f) diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 4fb074c446bf..57221e349a7c 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -15,6 +15,7 @@ #include <asm/mmu_context.h> #include <asm/cacheflush.h> #include <asm/mach-types.h> +#include <asm/smp_plat.h> #include <asm/system_misc.h> extern const unsigned char relocate_new_kernel[]; @@ -39,6 +40,14 @@ int machine_kexec_prepare(struct kimage *image) int i, err; /* + * Validate that if the current HW supports SMP, then the SW supports + * and implements CPU hotplug for the current HW. If not, we won't be + * able to kexec reliably, so fail the prepare operation. + */ + if (num_possible_cpus() > 1 && !platform_can_cpu_hotplug()) + return -EINVAL; + + /* * No segment at default ATAGs address. try to locate * a dtb using magic. */ @@ -73,6 +82,7 @@ void machine_crash_nonpanic_core(void *unused) crash_save_cpu(®s, smp_processor_id()); flush_cache_all(); + set_cpu_online(smp_processor_id(), false); atomic_dec(&waiting_for_crash_ipi); while (1) cpu_relax(); @@ -134,10 +144,13 @@ void machine_kexec(struct kimage *image) unsigned long reboot_code_buffer_phys; void *reboot_code_buffer; - if (num_online_cpus() > 1) { - pr_err("kexec: error: multiple CPUs still online\n"); - return; - } + /* + * This can only happen if machine_shutdown() failed to disable some + * CPU, and that can only happen if the checks in + * machine_kexec_prepare() were not correct. If this fails, we can't + * reliably kexec anyway, so BUG_ON is appropriate. + */ + BUG_ON(num_online_cpus() > 1); page_list = image->head & PAGE_MASK; diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 85c3fb6c93c2..084dc8896986 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -292,12 +292,20 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, maps[ARM_SEC_CORE].unw_sec = s; else if (strcmp(".ARM.exidx.exit.text", secname) == 0) maps[ARM_SEC_EXIT].unw_sec = s; + else if (strcmp(".ARM.exidx.text.unlikely", secname) == 0) + maps[ARM_SEC_UNLIKELY].unw_sec = s; + else if (strcmp(".ARM.exidx.text.hot", secname) == 0) + maps[ARM_SEC_HOT].unw_sec = s; else if (strcmp(".init.text", secname) == 0) maps[ARM_SEC_INIT].txt_sec = s; else if (strcmp(".text", secname) == 0) maps[ARM_SEC_CORE].txt_sec = s; else if (strcmp(".exit.text", secname) == 0) maps[ARM_SEC_EXIT].txt_sec = s; + else if (strcmp(".text.unlikely", secname) == 0) + maps[ARM_SEC_UNLIKELY].txt_sec = s; + else if (strcmp(".text.hot", secname) == 0) + maps[ARM_SEC_HOT].txt_sec = s; } for (i = 0; i < ARM_SEC_MAX; i++) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index d9f5cd4e533f..e186ee1e63f6 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -53,7 +53,12 @@ armpmu_map_cache_event(const unsigned (*cache_map) static int armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) { - int mapping = (*event_map)[config]; + int mapping; + + if (config >= PERF_COUNT_HW_MAX) + return -EINVAL; + + mapping = (*event_map)[config]; return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; } @@ -253,6 +258,9 @@ validate_event(struct pmu_hw_events *hw_events, struct arm_pmu *armpmu = to_arm_pmu(event->pmu); struct pmu *leader_pmu = event->group_leader->pmu; + if (is_software_event(event)) + return 1; + if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF) return 1; diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index aebe0e99c153..8d6147b2001f 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c @@ -118,7 +118,8 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler) continue; } - err = request_irq(irq, handler, IRQF_NOBALANCING, "arm-pmu", + err = request_irq(irq, handler, + IRQF_NOBALANCING | IRQF_NO_THREAD, "arm-pmu", cpu_pmu); if (err) { pr_err("unable to request IRQ%d for ARM PMU counters\n", diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 536c85fe72a8..94f6b05f9e24 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -462,7 +462,7 @@ int in_gate_area_no_mm(unsigned long addr) { return in_gate_area(NULL, addr); } -#define is_gate_vma(vma) ((vma) = &gate_vma) +#define is_gate_vma(vma) ((vma) == &gate_vma) #else #define is_gate_vma(vma) 0 #endif diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index afc2489ee13b..0e1e2b3afa45 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -72,10 +72,10 @@ static int __init fpe_setup(char *line) __setup("fpe=", fpe_setup); #endif -extern void paging_init(struct machine_desc *desc); +extern void paging_init(const struct machine_desc *desc); extern void sanity_check_meminfo(void); extern enum reboot_mode reboot_mode; -extern void setup_dma_zone(struct machine_desc *desc); +extern void setup_dma_zone(const struct machine_desc *desc); unsigned int processor_id; EXPORT_SYMBOL(processor_id); @@ -139,7 +139,7 @@ EXPORT_SYMBOL(elf_platform); static const char *cpu_name; static const char *machine_name; static char __initdata cmd_line[COMMAND_LINE_SIZE]; -struct machine_desc *machine_desc __initdata; +const struct machine_desc *machine_desc __initdata; static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; #define ENDIANNESS ((char)endian_test.l) @@ -607,7 +607,7 @@ static void __init setup_processor(void) void __init dump_machine_table(void) { - struct machine_desc *p; + const struct machine_desc *p; early_print("Available machine support:\n\nID (hex)\tNAME\n"); for_each_machine_desc(p) @@ -694,7 +694,7 @@ static int __init early_mem(char *p) } early_param("mem", early_mem); -static void __init request_standard_resources(struct machine_desc *mdesc) +static void __init request_standard_resources(const struct machine_desc *mdesc) { struct memblock_region *region; struct resource *res; @@ -852,7 +852,7 @@ void __init hyp_mode_check(void) void __init setup_arch(char **cmdline_p) { - struct machine_desc *mdesc; + const struct machine_desc *mdesc; setup_processor(); mdesc = setup_machine_fdt(__atags_pointer); @@ -994,15 +994,6 @@ static int c_show(struct seq_file *m, void *v) seq_printf(m, "model name\t: %s rev %d (%s)\n", cpu_name, cpuid & 15, elf_platform); -#if defined(CONFIG_SMP) - seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", - per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), - (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); -#else - seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", - loops_per_jiffy / (500000/HZ), - (loops_per_jiffy / (5000/HZ)) % 100); -#endif /* dump out the processor features */ seq_puts(m, "Features\t: "); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index c2b4f8f0be9a..92d10e503746 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -145,6 +145,16 @@ int boot_secondary(unsigned int cpu, struct task_struct *idle) return -ENOSYS; } +int platform_can_cpu_hotplug(void) +{ +#ifdef CONFIG_HOTPLUG_CPU + if (smp_ops.cpu_kill) + return 1; +#endif + + return 0; +} + #ifdef CONFIG_HOTPLUG_CPU static void percpu_timer_stop(void); @@ -388,17 +398,8 @@ asmlinkage void secondary_start_kernel(void) void __init smp_cpus_done(unsigned int max_cpus) { - int cpu; - unsigned long bogosum = 0; - - for_each_online_cpu(cpu) - bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy; - - printk(KERN_INFO "SMP: Total of %d processors activated " - "(%lu.%02lu BogoMIPS).\n", - num_online_cpus(), - bogosum / (500000/HZ), - (bogosum / (5000/HZ)) % 100); + printk(KERN_INFO "SMP: Total of %d processors activated.\n", + num_online_cpus()); hyp_mode_check(); } diff --git a/arch/arm/kernel/v7m.c b/arch/arm/kernel/v7m.c new file mode 100644 index 000000000000..4d2cba94f5cc --- /dev/null +++ b/arch/arm/kernel/v7m.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2013 Uwe Kleine-Koenig for Pengutronix + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ +#include <linux/io.h> +#include <linux/reboot.h> +#include <asm/barrier.h> +#include <asm/v7m.h> + +void armv7m_restart(enum reboot_mode mode, const char *cmd) +{ + dsb(); + __raw_writel(V7M_SCB_AIRCR_VECTKEY | V7M_SCB_AIRCR_SYSRESETREQ, + BASEADDR_V7M_SCB + V7M_SCB_AIRCR); + dsb(); +} |