diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /arch/arc/kernel | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz |
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r-- | arch/arc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arc/kernel/ctx_sw.c | 13 | ||||
-rw-r--r-- | arch/arc/kernel/ctx_sw_asm.S | 11 | ||||
-rw-r--r-- | arch/arc/kernel/devtree.c | 97 | ||||
-rw-r--r-- | arch/arc/kernel/entry.S | 24 | ||||
-rw-r--r-- | arch/arc/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/arc/kernel/irq.c | 12 | ||||
-rw-r--r-- | arch/arc/kernel/kgdb.c | 12 | ||||
-rw-r--r-- | arch/arc/kernel/kprobes.c | 8 | ||||
-rw-r--r-- | arch/arc/kernel/perf_event.c | 326 | ||||
-rw-r--r-- | arch/arc/kernel/reset.c | 1 | ||||
-rw-r--r-- | arch/arc/kernel/setup.c | 17 | ||||
-rw-r--r-- | arch/arc/kernel/smp.c | 10 | ||||
-rw-r--r-- | arch/arc/kernel/stacktrace.c | 5 | ||||
-rw-r--r-- | arch/arc/kernel/time.c | 11 | ||||
-rw-r--r-- | arch/arc/kernel/traps.c | 3 |
16 files changed, 123 insertions, 430 deletions
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index 8004b4f..c242ef0 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_ARC_MISALIGN_ACCESS) += unaligned.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_ARC_METAWARE_HLINK) += arc_hostlink.o -obj-$(CONFIG_PERF_EVENTS) += perf_event.o obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o CFLAGS_fpu.o += -mdpfp diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c index c14a5be..34410eb 100644 --- a/arch/arc/kernel/ctx_sw.c +++ b/arch/arc/kernel/ctx_sw.c @@ -17,8 +17,6 @@ #include <asm/asm-offsets.h> #include <linux/sched.h> -#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) - struct task_struct *__sched __switch_to(struct task_struct *prev_task, struct task_struct *next_task) { @@ -47,16 +45,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) #endif /* set ksp of outgoing task in tsk->thread.ksp */ -#if KSP_WORD_OFF <= 255 "st.as sp, [%3, %1] \n\t" -#else - /* - * Workaround for NR_CPUS=4k - * %1 is bigger than 255 (S9 offset for st.as) - */ - "add2 r24, %3, %1 \n\t" - "st sp, [r24] \n\t" -#endif "sync \n\t" @@ -108,7 +97,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) /* FP/BLINK restore generated by gcc (standard func epilogue */ : "=r"(tmp) - : "n"(KSP_WORD_OFF), "r"(next), "r"(prev) + : "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev) : "blink" ); diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S index 65690e7..d897234 100644 --- a/arch/arc/kernel/ctx_sw_asm.S +++ b/arch/arc/kernel/ctx_sw_asm.S @@ -14,8 +14,6 @@ #include <asm/asm-offsets.h> #include <asm/linkage.h> -#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) - ;################### Low Level Context Switch ########################## .section .sched.text,"ax",@progbits @@ -30,13 +28,8 @@ __switch_to: SAVE_CALLEE_SAVED_KERNEL /* Save the now KSP in task->thread.ksp */ -#if KSP_WORD_OFF <= 255 - st.as sp, [r0, KSP_WORD_OFF] -#else - /* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */ - add2 r24, r0, KSP_WORD_OFF - st sp, [r24] -#endif + st.as sp, [r0, (TASK_THREAD + THREAD_KSP)/4] + /* * Return last task in r0 (return reg) * On ARC, Return reg = First Arg reg = r0. diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index b6dc4e2..2340af0 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -14,22 +14,10 @@ #include <linux/memblock.h> #include <linux/of.h> #include <linux/of_fdt.h> +#include <asm/prom.h> #include <asm/clk.h> #include <asm/mach_desc.h> -static const void * __init arch_get_next_mach(const char *const **match) -{ - static const struct machine_desc *mdesc = __arch_info_begin; - const struct machine_desc *m = mdesc; - - if (m >= __arch_info_end) - return NULL; - - mdesc++; - *match = m->dt_compat; - return m; -} - /** * setup_machine_fdt - Machine setup when an dtb was passed to the kernel * @dt: virtual address pointer to dt blob @@ -37,24 +25,93 @@ static const void * __init arch_get_next_mach(const char *const **match) * If a dtb was passed to the kernel, then use it to choose the correct * machine_desc and to setup the system. */ -const struct machine_desc * __init setup_machine_fdt(void *dt) +struct machine_desc * __init setup_machine_fdt(void *dt) { - const struct machine_desc *mdesc; + struct boot_param_header *devtree = dt; + struct machine_desc *mdesc = NULL, *mdesc_best = NULL; + unsigned int score, mdesc_score = ~1; unsigned long dt_root; + const char *model, *compat; void *clk; + char manufacturer[16]; unsigned long len; - if (!early_init_dt_scan(dt)) + /* check device tree validity */ + if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) return NULL; - mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach); - if (!mdesc) + initial_boot_params = devtree; + dt_root = of_get_flat_dt_root(); + + /* + * The kernel could be multi-platform enabled, thus could have many + * "baked-in" machine descriptors. Search thru all for the best + * "compatible" string match. + */ + for_each_machine_desc(mdesc) { + score = of_flat_dt_match(dt_root, mdesc->dt_compat); + if (score > 0 && score < mdesc_score) { + mdesc_best = mdesc; + mdesc_score = score; + } + } + if (!mdesc_best) { + const char *prop; + long size; + + pr_err("\n unrecognized device tree list:\n[ "); + + prop = of_get_flat_dt_prop(dt_root, "compatible", &size); + if (prop) { + while (size > 0) { + printk("'%s' ", prop); + size -= strlen(prop) + 1; + prop += strlen(prop) + 1; + } + } + printk("]\n\n"); + machine_halt(); + } + + /* compat = "<manufacturer>,<model>" */ + compat = mdesc_best->dt_compat[0]; + + model = strchr(compat, ','); + if (model) + model++; + + strlcpy(manufacturer, compat, model ? model - compat : strlen(compat)); + + pr_info("Board \"%s\" from %s (Manufacturer)\n", model, manufacturer); + + /* Retrieve various information from the /chosen node */ + of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); + + /* Initialize {size,address}-cells info */ + of_scan_flat_dt(early_init_dt_scan_root, NULL); + + /* Setup memory, calling early_init_dt_add_memory_arch */ + of_scan_flat_dt(early_init_dt_scan_memory, NULL); - dt_root = of_get_flat_dt_root(); clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len); if (clk) arc_set_core_freq(of_read_ulong(clk, len/4)); - return mdesc; + return mdesc_best; +} + +/* + * Copy the flattened DT out of .init since unflattening doesn't copy strings + * and the normal DT APIs refs them from orig flat DT + */ +void __init copy_devtree(void) +{ + void *alloc = early_init_dt_alloc_memory_arch( + be32_to_cpu(initial_boot_params->totalsize), 64); + if (alloc) { + memcpy(alloc, initial_boot_params, + be32_to_cpu(initial_boot_params->totalsize)); + initial_boot_params = alloc; + } } diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 47d09d0..b908dde 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -250,14 +250,6 @@ ARC_ENTRY handle_interrupt_level1 lr r0, [icause1] and r0, r0, 0x1f -#ifdef CONFIG_TRACE_IRQFLAGS - ; icause1 needs to be read early, before calling tracing, which - ; can clobber scratch regs, hence use of stack to stash it - push r0 - TRACE_ASM_IRQ_DISABLE - pop r0 -#endif - bl.d @arch_do_IRQ mov r1, sp @@ -345,9 +337,9 @@ ARC_ENTRY EV_TLBProtV ; vineetg: Mar 6th: Random Seg Fault issue #1 ; ecr and efa were not saved in case an Intr sneaks in ; after fake rtie - + ; lr r2, [ecr] - lr r0, [efa] ; Faulting Data address + lr r1, [efa] ; Faulting Data address ; --------(4) Return from CPU Exception Mode --------- ; Fake a rtie, but rtie to next label @@ -356,8 +348,6 @@ ARC_ENTRY EV_TLBProtV FAKE_RET_FROM_EXCPN r9 - mov r1, sp - ;------ (5) Type of Protection Violation? ---------- ; ; ProtV Hardware Exception is triggered for Access Faults of 2 types @@ -368,12 +358,16 @@ ARC_ENTRY EV_TLBProtV bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f ;========= (6a) Access Violation Processing ======== + mov r0, sp ; pt_regs bl do_page_fault b ret_from_exception ;========== (6b) Non aligned access ============ 4: + mov r0, r1 + mov r1, sp ; pt_regs +#ifdef CONFIG_ARC_MISALIGN_ACCESS SAVE_CALLEE_SAVED_USER mov r2, sp ; callee_regs @@ -382,6 +376,9 @@ ARC_ENTRY EV_TLBProtV ; TBD: optimize - do this only if a callee reg was involved ; either a dst of emulated LD/ST or src with address-writeback RESTORE_CALLEE_SAVED_USER +#else + bl do_misaligned_error +#endif b ret_from_exception @@ -578,7 +575,6 @@ resume_user_mode_begin: ; --- (Slow Path #2) pending signal --- mov r0, sp ; pt_regs for arg to do_signal()/do_notify_resume() - GET_CURR_THR_INFO_FLAGS r9 bbit0 r9, TIF_SIGPENDING, .Lchk_notify_resume ; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs @@ -644,8 +640,6 @@ resume_kernel_mode: restore_regs : - TRACE_ASM_IRQ_ENABLE - lr r10, [status32] ; Restore REG File. In case multiple Events outstanding, diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S index 2c878e9..0f944f0 100644 --- a/arch/arc/kernel/head.S +++ b/arch/arc/kernel/head.S @@ -95,7 +95,7 @@ stext: ;---------------------------------------------------------------- ; First lines of code run by secondary before jumping to 'C' ;---------------------------------------------------------------- - .section .text, "ax",@progbits + .section .init.text, "ax",@progbits .type first_lines_of_secondary, @function .globl first_lines_of_secondary diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index a4b141e..5fc9245 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -39,14 +39,10 @@ void arc_init_IRQ(void) level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5; level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6; - /* - * Write to register, even if no LV2 IRQs configured to reset it - * in case bootloader had mucked with it - */ - write_aux_reg(AUX_IRQ_LEV, level_mask); - - if (level_mask) + if (level_mask) { pr_info("Level-2 interrupts bitset %x\n", level_mask); + write_aux_reg(AUX_IRQ_LEV, level_mask); + } } /* @@ -150,7 +146,7 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs) set_irq_regs(old_regs); } -int get_hw_config_num_irq(void) +int __init get_hw_config_num_irq(void) { uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR); diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c index a2ff5c5..a7698fb 100644 --- a/arch/arc/kernel/kgdb.c +++ b/arch/arc/kernel/kgdb.c @@ -196,18 +196,6 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) instruction_pointer(regs) = ip; } -static void kgdb_call_nmi_hook(void *ignored) -{ - kgdb_nmicallback(raw_smp_processor_id(), NULL); -} - -void kgdb_roundup_cpus(unsigned long flags) -{ - local_irq_enable(); - smp_call_function(kgdb_call_nmi_hook, NULL, 0); - local_irq_disable(); -} - struct kgdb_arch arch_kgdb_ops = { /* breakpoint instruction: TRAP_S 0x3 */ #ifdef CONFIG_CPU_BIG_ENDIAN diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c index 42b0504..72f9782 100644 --- a/arch/arc/kernel/kprobes.c +++ b/arch/arc/kernel/kprobes.c @@ -87,13 +87,13 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; kcb->kprobe_status = kcb->prev_kprobe.status; } static inline void __kprobes set_current_kprobe(struct kprobe *p) { - __this_cpu_write(current_kprobe, p); + __get_cpu_var(current_kprobe) = p; } static void __kprobes resume_execution(struct kprobe *p, unsigned long addr, @@ -237,7 +237,7 @@ int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs) return 1; } else if (kprobe_running()) { - p = __this_cpu_read(current_kprobe); + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { setup_singlestep(p, regs); kcb->kprobe_status = KPROBE_HIT_SS; @@ -327,7 +327,7 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned long trapnr) */ /* We increment the nmissed count for accounting, - * we can also use npre/npostfault count for accounting + * we can also use npre/npostfault count for accouting * these specific fault cases. */ kprobes_inc_nmissed_count(cur); diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c deleted file mode 100644 index e46d81f..0000000 --- a/arch/arc/kernel/perf_event.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Linux performance counter support for ARC700 series - * - * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) - * - * This code is inspired by the perf support of various other architectures. - * - * 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/errno.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/perf_event.h> -#include <linux/platform_device.h> -#include <asm/arcregs.h> - -struct arc_pmu { - struct pmu pmu; - int counter_size; /* in bits */ - int n_counters; - unsigned long used_mask[BITS_TO_LONGS(ARC_PMU_MAX_HWEVENTS)]; - int ev_hw_idx[PERF_COUNT_ARC_HW_MAX]; -}; - -/* read counter #idx; note that counter# != event# on ARC! */ -static uint64_t arc_pmu_read_counter(int idx) -{ - uint32_t tmp; - uint64_t result; - - /* - * ARC supports making 'snapshots' of the counters, so we don't - * need to care about counters wrapping to 0 underneath our feet - */ - write_aux_reg(ARC_REG_PCT_INDEX, idx); - tmp = read_aux_reg(ARC_REG_PCT_CONTROL); - write_aux_reg(ARC_REG_PCT_CONTROL, tmp | ARC_REG_PCT_CONTROL_SN); - result = (uint64_t) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32; - result |= read_aux_reg(ARC_REG_PCT_SNAPL); - - return result; -} - -static void arc_perf_event_update(struct perf_event *event, - struct hw_perf_event *hwc, int idx) -{ - struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu); - uint64_t prev_raw_count, new_raw_count; - int64_t delta; - - do { - prev_raw_count = local64_read(&hwc->prev_count); - new_raw_count = arc_pmu_read_counter(idx); - } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count, - new_raw_count) != prev_raw_count); - - delta = (new_raw_count - prev_raw_count) & - ((1ULL << arc_pmu->counter_size) - 1ULL); - - local64_add(delta, &event->count); - local64_sub(delta, &hwc->period_left); -} - -static void arc_pmu_read(struct perf_event *event) -{ - arc_perf_event_update(event, &event->hw, event->hw.idx); -} - -static int arc_pmu_cache_event(u64 config) -{ - unsigned int cache_type, cache_op, cache_result; - int ret; - - cache_type = (config >> 0) & 0xff; - cache_op = (config >> 8) & 0xff; - cache_result = (config >> 16) & 0xff; - if (cache_type >= PERF_COUNT_HW_CACHE_MAX) - return -EINVAL; - if (cache_type >= PERF_COUNT_HW_CACHE_OP_MAX) - return -EINVAL; - if (cache_type >= PERF_COUNT_HW_CACHE_RESULT_MAX) - return -EINVAL; - - ret = arc_pmu_cache_map[cache_type][cache_op][cache_result]; - - if (ret == CACHE_OP_UNSUPPORTED) - return -ENOENT; - - return ret; -} - -/* initializes hw_perf_event structure if event is supported */ -static int arc_pmu_event_init(struct perf_event *event) -{ - struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu); - struct hw_perf_event *hwc = &event->hw; - int ret; - - /* ARC 700 PMU does not support sampling events */ - if (is_sampling_event(event)) - return -ENOENT; - - switch (event->attr.type) { - case PERF_TYPE_HARDWARE: - if (event->attr.config >= PERF_COUNT_HW_MAX) - return -ENOENT; - if (arc_pmu->ev_hw_idx[event->attr.config] < 0) - return -ENOENT; - hwc->config = arc_pmu->ev_hw_idx[event->attr.config]; - pr_debug("initializing event %d with cfg %d\n", - (int) event->attr.config, (int) hwc->config); - return 0; - case PERF_TYPE_HW_CACHE: - ret = arc_pmu_cache_event(event->attr.config); - if (ret < 0) - return ret; - hwc->config = arc_pmu->ev_hw_idx[ret]; - return 0; - default: - return -ENOENT; - } -} - -/* starts all counters */ -static void arc_pmu_enable(struct pmu *pmu) -{ - uint32_t tmp; - tmp = read_aux_reg(ARC_REG_PCT_CONTROL); - write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x1); -} - -/* stops all counters */ -static void arc_pmu_disable(struct pmu *pmu) -{ - uint32_t tmp; - tmp = read_aux_reg(ARC_REG_PCT_CONTROL); - write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0); -} - -/* - * Assigns hardware counter to hardware condition. - * Note that there is no separate start/stop mechanism; - * stopping is achieved by assigning the 'never' condition - */ -static void arc_pmu_start(struct perf_event *event, int flags) -{ - struct hw_perf_event *hwc = &event->hw; - int idx = hwc->idx; - - if (WARN_ON_ONCE(idx == -1)) - return; - - if (flags & PERF_EF_RELOAD) - WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); - - event->hw.state = 0; - - /* enable ARC pmu here */ - write_aux_reg(ARC_REG_PCT_INDEX, idx); - write_aux_reg(ARC_REG_PCT_CONFIG, hwc->config); -} - -static void arc_pmu_stop(struct perf_event *event, int flags) -{ - struct hw_perf_event *hwc = &event->hw; - int idx = hwc->idx; - - if (!(event->hw.state & PERF_HES_STOPPED)) { - /* stop ARC pmu here */ - write_aux_reg(ARC_REG_PCT_INDEX, idx); - - /* condition code #0 is always "never" */ - write_aux_reg(ARC_REG_PCT_CONFIG, 0); - - event->hw.state |= PERF_HES_STOPPED; - } - - if ((flags & PERF_EF_UPDATE) && - !(event->hw.state & PERF_HES_UPTODATE)) { - arc_perf_event_update(event, &event->hw, idx); - event->hw.state |= PERF_HES_UPTODATE; - } -} - -static void arc_pmu_del(struct perf_event *event, int flags) -{ - struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu); - - arc_pmu_stop(event, PERF_EF_UPDATE); - __clear_bit(event->hw.idx, arc_pmu->used_mask); - - perf_event_update_userpage(event); -} - -/* allocate hardware counter and optionally start counting */ -static int arc_pmu_add(struct perf_event *event, int flags) -{ - struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu); - struct hw_perf_event *hwc = &event->hw; - int idx = hwc->idx; - - if (__test_and_set_bit(idx, arc_pmu->used_mask)) { - idx = find_first_zero_bit(arc_pmu->used_mask, - arc_pmu->n_counters); - if (idx == arc_pmu->n_counters) - return -EAGAIN; - - __set_bit(idx, arc_pmu->used_mask); - hwc->idx = idx; - } - - write_aux_reg(ARC_REG_PCT_INDEX, idx); - write_aux_reg(ARC_REG_PCT_CONFIG, 0); - write_aux_reg(ARC_REG_PCT_COUNTL, 0); - write_aux_reg(ARC_REG_PCT_COUNTH, 0); - local64_set(&hwc->prev_count, 0); - - hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED; - if (flags & PERF_EF_START) - arc_pmu_start(event, PERF_EF_RELOAD); - - perf_event_update_userpage(event); - - return 0; -} - -static int arc_pmu_device_probe(struct platform_device *pdev) -{ - struct arc_pmu *arc_pmu; - struct arc_reg_pct_build pct_bcr; - struct arc_reg_cc_build cc_bcr; - int i, j, ret; - - union cc_name { - struct { - uint32_t word0, word1; - char sentinel; - } indiv; - char str[9]; - } cc_name; - - - READ_BCR(ARC_REG_PCT_BUILD, pct_bcr); - if (!pct_bcr.v) { - pr_err("This core does not have performance counters!\n"); - return -ENODEV; - } - - arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), - GFP_KERNEL); - if (!arc_pmu) - return -ENOMEM; - - arc_pmu->n_counters = pct_bcr.c; - BUG_ON(arc_pmu->n_counters > ARC_PMU_MAX_HWEVENTS); - - arc_pmu->counter_size = 32 + (pct_bcr.s << 4); - pr_info("ARC PMU found with %d counters of size %d bits\n", - arc_pmu->n_counters, arc_pmu->counter_size); - - READ_BCR(ARC_REG_CC_BUILD, cc_bcr); - - if (!cc_bcr.v) - pr_err("Strange! Performance counters exist, but no countable conditions?\n"); - - pr_info("ARC PMU has %d countable conditions\n", cc_bcr.c); - - cc_name.str[8] = 0; - for (i = 0; i < PERF_COUNT_HW_MAX; i++) - arc_pmu->ev_hw_idx[i] = -1; - - for (j = 0; j < cc_bcr.c; j++) { - write_aux_reg(ARC_REG_CC_INDEX, j); - cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0); - cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1); - for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) { - if (arc_pmu_ev_hw_map[i] && - !strcmp(arc_pmu_ev_hw_map[i], cc_name.str) && - strlen(arc_pmu_ev_hw_map[i])) { - pr_debug("mapping %d to idx %d with name %s\n", - i, j, cc_name.str); - arc_pmu->ev_hw_idx[i] = j; - } - } - } - - arc_pmu->pmu = (struct pmu) { - .pmu_enable = arc_pmu_enable, - .pmu_disable = arc_pmu_disable, - .event_init = arc_pmu_event_init, - .add = arc_pmu_add, - .del = arc_pmu_del, - .start = arc_pmu_start, - .stop = arc_pmu_stop, - .read = arc_pmu_read, - }; - - ret = perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW); - - return ret; -} - -#ifdef CONFIG_OF -static const struct of_device_id arc_pmu_match[] = { - { .compatible = "snps,arc700-pmu" }, - {}, -}; -MODULE_DEVICE_TABLE(of, arc_pmu_match); -#endif - -static struct platform_driver arc_pmu_driver = { - .driver = { - .name = "arc700-pmu", - .of_match_table = of_match_ptr(arc_pmu_match), - }, - .probe = arc_pmu_device_probe, -}; - -module_platform_driver(arc_pmu_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mischa Jonker <mjonker@synopsys.com>"); -MODULE_DESCRIPTION("ARC PMU driver"); diff --git a/arch/arc/kernel/reset.c b/arch/arc/kernel/reset.c index 2768fa1..e227a2b 100644 --- a/arch/arc/kernel/reset.c +++ b/arch/arc/kernel/reset.c @@ -31,4 +31,3 @@ void machine_power_off(void) } void (*pm_power_off) (void) = NULL; -EXPORT_SYMBOL(pm_power_off); diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 643eae4..2c68bc7e 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -21,6 +21,7 @@ #include <asm/setup.h> #include <asm/page.h> #include <asm/irq.h> +#include <asm/prom.h> #include <asm/unwind.h> #include <asm/clk.h> #include <asm/mach_desc.h> @@ -30,13 +31,14 @@ int running_on_hw = 1; /* vs. on ISS */ char __initdata command_line[COMMAND_LINE_SIZE]; -const struct machine_desc *machine_desc; +struct machine_desc *machine_desc; struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; -static void read_arc_build_cfg_regs(void) + +void read_arc_build_cfg_regs(void) { struct bcr_perip uncached_space; struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; @@ -104,7 +106,7 @@ static const struct cpuinfo_data arc_cpu_tbl[] = { { {0x00, NULL } } }; -static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) +char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) { int n = 0; struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; @@ -169,7 +171,7 @@ static const struct id_to_str mac_mul_nm[] = { {0x6, "Dual 16x16 and 32x16"} }; -static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) +char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) { int n = 0; struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; @@ -232,7 +234,7 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) return buf; } -static void arc_chk_ccms(void) +void arc_chk_ccms(void) { #if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM) struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; @@ -267,7 +269,7 @@ static void arc_chk_ccms(void) * hardware has dedicated regs which need to be saved/restored on ctx-sw * (Single Precision uses core regs), thus kernel is kind of oblivious to it */ -static void arc_chk_fpu(void) +void arc_chk_fpu(void) { struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; @@ -344,7 +346,8 @@ void __init setup_arch(char **cmdline_p) setup_arch_memory(); /* copy flat DT out of .init and then unflatten it */ - unflatten_and_copy_device_tree(); + copy_devtree(); + unflatten_device_tree(); /* Can be issue if someone passes cmd line arg "ro" * But that is unlikely so keeping it as it is diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index c2f9ebb..bca3052 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -95,7 +95,7 @@ void __init smp_cpus_done(unsigned int max_cpus) * If it turns out to be elaborate, it's better to code it in assembly * */ -void __weak arc_platform_smp_wait_to_boot(int cpu) +void __attribute__((weak)) arc_platform_smp_wait_to_boot(int cpu) { /* * As a hack for debugging - since debugger will single-step over the @@ -128,7 +128,6 @@ void start_kernel_secondary(void) atomic_inc(&mm->mm_users); atomic_inc(&mm->mm_count); current->active_mm = mm; - cpumask_set_cpu(cpu, mm_cpumask(mm)); notify_cpu_starting(cpu); set_cpu_online(cpu, true); @@ -211,6 +210,7 @@ enum ipi_msg_type { IPI_NOP = 0, IPI_RESCHEDULE = 1, IPI_CALL_FUNC, + IPI_CALL_FUNC_SINGLE, IPI_CPU_STOP }; @@ -254,7 +254,7 @@ void smp_send_stop(void) void arch_send_call_function_single_ipi(int cpu) { - ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC); + ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); } void arch_send_call_function_ipi_mask(const struct cpumask *mask) @@ -286,6 +286,10 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi, int cpu) generic_smp_call_function_interrupt(); break; + case IPI_CALL_FUNC_SINGLE: + generic_smp_call_function_single_interrupt(); + break; + case IPI_CPU_STOP: ipi_cpu_stop(cpu); break; diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c index 9ce47cf..f8b7d88 100644 --- a/arch/arc/kernel/stacktrace.c +++ b/arch/arc/kernel/stacktrace.c @@ -237,14 +237,11 @@ unsigned int get_wchan(struct task_struct *tsk) */ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { - /* Assumes @tsk is sleeping so unwinds from __switch_to */ arc_unwind_core(tsk, NULL, __collect_all_but_sched, trace); } void save_stack_trace(struct stack_trace *trace) { - /* Pass NULL for task so it unwinds the current call frame */ - arc_unwind_core(NULL, NULL, __collect_all, trace); + arc_unwind_core(current, NULL, __collect_all, trace); } -EXPORT_SYMBOL_GPL(save_stack_trace); #endif diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index e5f3a83..3fde7de 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -63,10 +63,9 @@ int arc_counter_setup(void) { - /* - * For SMP this needs to be 0. However Kconfig glue doesn't - * enable this option for SMP configs - */ + /* RTSC insn taps into cpu clk, needs no setup */ + + /* For SMP, only allowed if cross-core-sync, hence usable as cs */ return 1; } @@ -207,7 +206,7 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = { static irqreturn_t timer_irq_handler(int irq, void *dev_id) { - struct clock_event_device *clk = this_cpu_ptr(&arc_clockevent_device); + struct clock_event_device *clk = &__get_cpu_var(arc_clockevent_device); arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC); clk->event_handler(clk); @@ -224,7 +223,7 @@ static struct irqaction arc_timer_irq = { * Setup the local event timer for @cpu * N.B. weak so that some exotic ARC SoCs can completely override it */ -void __weak arc_local_timer_setup(unsigned int cpu) +void __attribute__((weak)) arc_local_timer_setup(unsigned int cpu) { struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu); diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index 3eadfda..e21692d 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -84,18 +84,19 @@ DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", do_memory_error, BUS_ADRERR) DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT) DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) +#ifdef CONFIG_ARC_MISALIGN_ACCESS /* * Entry Point for Misaligned Data access Exception, for emulating in software */ int do_misaligned_access(unsigned long address, struct pt_regs *regs, struct callee_regs *cregs) { - /* If emulation not enabled, or failed, kill the task */ if (misaligned_fixup(address, regs, cregs) != 0) return do_misaligned_error(address, regs); return 0; } +#endif /* * Entry point for miscll errors such as Nested Exceptions |