aboutsummaryrefslogtreecommitdiff
path: root/arch/arc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r--arch/arc/kernel/asm-offsets.c2
-rw-r--r--arch/arc/kernel/clk.c2
-rw-r--r--arch/arc/kernel/disasm.c4
-rw-r--r--arch/arc/kernel/entry.S8
-rw-r--r--arch/arc/kernel/irq.c25
-rw-r--r--arch/arc/kernel/kprobes.c1
-rw-r--r--arch/arc/kernel/module.c4
-rw-r--r--arch/arc/kernel/process.c27
-rw-r--r--arch/arc/kernel/setup.c36
-rw-r--r--arch/arc/kernel/smp.c2
-rw-r--r--arch/arc/kernel/stacktrace.c7
-rw-r--r--arch/arc/kernel/time.c1
-rw-r--r--arch/arc/kernel/traps.c24
-rw-r--r--arch/arc/kernel/troubleshoot.c53
14 files changed, 86 insertions, 110 deletions
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c
index 0dc148ebce7..7dcda702524 100644
--- a/arch/arc/kernel/asm-offsets.c
+++ b/arch/arc/kernel/asm-offsets.c
@@ -11,9 +11,9 @@
#include <linux/interrupt.h>
#include <linux/thread_info.h>
#include <linux/kbuild.h>
+#include <linux/ptrace.h>
#include <asm/hardirq.h>
#include <asm/page.h>
-#include <asm/ptrace.h>
int main(void)
{
diff --git a/arch/arc/kernel/clk.c b/arch/arc/kernel/clk.c
index 66ce0dc917f..10c7b0b5a07 100644
--- a/arch/arc/kernel/clk.c
+++ b/arch/arc/kernel/clk.c
@@ -8,7 +8,7 @@
#include <asm/clk.h>
-unsigned long core_freq = 800000000;
+unsigned long core_freq = 80000000;
/*
* As of now we default to device-tree provided clock
diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c
index 2f390289a79..b8a549c4f54 100644
--- a/arch/arc/kernel/disasm.c
+++ b/arch/arc/kernel/disasm.c
@@ -12,8 +12,8 @@
#include <linux/types.h>
#include <linux/kprobes.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
#include <asm/disasm.h>
-#include <asm/uaccess.h>
#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
defined(CONFIG_KPROBES)
@@ -535,4 +535,4 @@ int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
return instr.is_branch;
}
-#endif /* CONFIG_KGDB || CONFIG_MISALIGN_ACCESS || CONFIG_KPROBES */
+#endif /* CONFIG_KGDB || CONFIG_ARC_MISALIGN_ACCESS || CONFIG_KPROBES */
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 91eeab81f52..0c6d664d4a8 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -393,12 +393,14 @@ ARC_ENTRY EV_TLBProtV
#ifdef CONFIG_ARC_MISALIGN_ACCESS
SAVE_CALLEE_SAVED_USER
mov r3, sp ; callee_regs
-#endif
bl do_misaligned_access
-#ifdef CONFIG_ARC_MISALIGN_ACCESS
- DISCARD_CALLEE_SAVED_USER
+ ; 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
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 551c10dff48..8115fa53157 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -11,6 +11,8 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include "../../drivers/irqchip/irqchip.h"
#include <asm/sections.h>
#include <asm/irq.h>
#include <asm/mach_desc.h>
@@ -26,7 +28,7 @@
* -Disable all IRQs (on CPU side)
* -Optionally, setup the High priority Interrupts as Level 2 IRQs
*/
-void __init arc_init_IRQ(void)
+void __cpuinit arc_init_IRQ(void)
{
int level_mask = 0;
@@ -97,15 +99,13 @@ static const struct irq_domain_ops arc_intc_domain_ops = {
static struct irq_domain *root_domain;
-void __init init_onchip_IRQ(void)
+static int __init
+init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
{
- struct device_node *intc = NULL;
+ if (parent)
+ panic("DeviceTree incore intc not a root irq controller\n");
- intc = of_find_compatible_node(NULL, NULL, "snps,arc700-intc");
- if(!intc)
- panic("DeviceTree Missing incore intc\n");
-
- root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
+ root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0,
&arc_intc_domain_ops, NULL);
if (!root_domain)
@@ -113,8 +113,12 @@ void __init init_onchip_IRQ(void)
/* with this we don't need to export root_domain */
irq_set_default_host(root_domain);
+
+ return 0;
}
+IRQCHIP_DECLARE(arc_intc, "snps,arc700-intc", init_onchip_IRQ);
+
/*
* Late Interrupt system init called from start_kernel for Boot CPU only
*
@@ -123,12 +127,13 @@ void __init init_onchip_IRQ(void)
*/
void __init init_IRQ(void)
{
- init_onchip_IRQ();
-
/* Any external intc can be setup here */
if (machine_desc->init_irq)
machine_desc->init_irq();
+ /* process the entire interrupt tree in one go */
+ irqchip_init();
+
#ifdef CONFIG_SMP
/* Master CPU can initialize it's side of IPI */
if (machine_desc->init_smp)
diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c
index 3bfeacb674d..5a7b80e2d88 100644
--- a/arch/arc/kernel/kprobes.c
+++ b/arch/arc/kernel/kprobes.c
@@ -10,7 +10,6 @@
#include <linux/kprobes.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/kprobes.h>
#include <linux/kdebug.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
diff --git a/arch/arc/kernel/module.c b/arch/arc/kernel/module.c
index cdd359352c0..376e0462296 100644
--- a/arch/arc/kernel/module.c
+++ b/arch/arc/kernel/module.c
@@ -47,7 +47,7 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
}
}
#endif
- return 0;
+ return 0;
}
void module_arch_cleanup(struct module *mod)
@@ -141,5 +141,5 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
mod->arch.unw_info = unw;
}
#endif
- return 0;
+ return 0;
}
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
index 0a7531d9929..cad66851e0c 100644
--- a/arch/arc/kernel/process.c
+++ b/arch/arc/kernel/process.c
@@ -41,37 +41,12 @@ SYSCALL_DEFINE0(arc_gettls)
return task_thread_info(current)->thr_ptr;
}
-static inline void arch_idle(void)
+void arch_cpu_idle(void)
{
/* sleep, but enable all interrupts before committing */
__asm__("sleep 0x3");
}
-void cpu_idle(void)
-{
- /* Since we SLEEP in idle loop, TIF_POLLING_NRFLAG can't be set */
-
- /* endless idle loop with no priority at all */
- while (1) {
- tick_nohz_idle_enter();
- rcu_idle_enter();
-
-doze:
- local_irq_disable();
- if (!need_resched()) {
- arch_idle();
- goto doze;
- } else {
- local_irq_enable();
- }
-
- rcu_idle_exit();
- tick_nohz_idle_exit();
-
- schedule_preempt_disabled();
- }
-}
-
asmlinkage void ret_from_fork(void);
/* Layout of Child kernel mode stack as setup at the end of this function is
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 2d95ac07df7..b2b3731dd1e 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -14,14 +14,13 @@
#include <linux/module.h>
#include <linux/cpu.h>
#include <linux/of_fdt.h>
+#include <linux/cache.h>
#include <asm/sections.h>
#include <asm/arcregs.h>
#include <asm/tlb.h>
-#include <asm/cache.h>
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/irq.h>
-#include <asm/arcregs.h>
#include <asm/prom.h>
#include <asm/unwind.h>
#include <asm/clk.h>
@@ -32,14 +31,14 @@
int running_on_hw = 1; /* vs. on ISS */
char __initdata command_line[COMMAND_LINE_SIZE];
-struct machine_desc *machine_desc __initdata;
+struct machine_desc *machine_desc __cpuinitdata;
struct task_struct *_current_task[NR_CPUS]; /* For stack switching */
struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
-void __init read_arc_build_cfg_regs(void)
+void __cpuinit read_arc_build_cfg_regs(void)
{
struct bcr_perip uncached_space;
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
@@ -238,7 +237,7 @@ char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
return buf;
}
-void __init arc_chk_ccms(void)
+void __cpuinit arc_chk_ccms(void)
{
#if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
@@ -273,7 +272,7 @@ void __init 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
*/
-void __init arc_chk_fpu(void)
+void __cpuinit arc_chk_fpu(void)
{
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
@@ -294,7 +293,7 @@ void __init arc_chk_fpu(void)
* such as only for boot CPU etc
*/
-void __init setup_processor(void)
+void __cpuinit setup_processor(void)
{
char str[512];
int cpu_id = smp_processor_id();
@@ -319,23 +318,20 @@ void __init setup_processor(void)
void __init setup_arch(char **cmdline_p)
{
+ /* This also populates @boot_command_line from /bootargs */
+ machine_desc = setup_machine_fdt(__dtb_start);
+ if (!machine_desc)
+ panic("Embedded DT invalid\n");
+
+ /* Append any u-boot provided cmdline */
#ifdef CONFIG_CMDLINE_UBOOT
- /* Make sure that a whitespace is inserted before */
- strlcat(command_line, " ", sizeof(command_line));
+ /* Add a whitespace seperator between the 2 cmdlines */
+ strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+ strlcat(boot_command_line, command_line, COMMAND_LINE_SIZE);
#endif
- /*
- * Append .config cmdline to base command line, which might already
- * contain u-boot "bootargs" (handled by head.S, if so configured)
- */
- strlcat(command_line, CONFIG_CMDLINE, sizeof(command_line));
/* Save unparsed command line copy for /proc/cmdline */
- strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
- *cmdline_p = command_line;
-
- machine_desc = setup_machine_fdt(__dtb_start);
- if (!machine_desc)
- panic("Embedded DT invalid\n");
+ *cmdline_p = boot_command_line;
/* To force early parsing of things like mem=xxx */
parse_early_param();
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index 3af3e06dcf0..5c7fd603d21 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -141,7 +141,7 @@ void __cpuinit start_kernel_secondary(void)
local_irq_enable();
preempt_disable();
- cpu_idle();
+ cpu_startup_entry(CPUHP_ONLINE);
}
/*
diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c
index a63ff842564..ca0207b9d5b 100644
--- a/arch/arc/kernel/stacktrace.c
+++ b/arch/arc/kernel/stacktrace.c
@@ -220,13 +220,6 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
show_stacktrace(tsk, NULL);
}
-/* Expected by Rest of kernel code */
-void dump_stack(void)
-{
- show_stacktrace(NULL, NULL);
-}
-EXPORT_SYMBOL(dump_stack);
-
/* Another API expected by schedular, shows up in "ps" as Wait Channel
* Ofcourse just returning schedule( ) would be pointless so unwind until
* the function is not in schedular code
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index f13f72807aa..09f4309aa2c 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
-#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/init.h>
#include <linux/timex.h>
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c
index 7496995371e..0471d9c9dd5 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -16,11 +16,12 @@
#include <linux/sched.h>
#include <linux/kdebug.h>
#include <linux/uaccess.h>
-#include <asm/ptrace.h>
+#include <linux/ptrace.h>
+#include <linux/kprobes.h>
+#include <linux/kgdb.h>
#include <asm/setup.h>
-#include <asm/kprobes.h>
#include <asm/unaligned.h>
-#include <asm/kgdb.h>
+#include <asm/kprobes.h>
void __init trap_init(void)
{
@@ -83,6 +84,7 @@ DO_ERROR_INFO(SIGILL, "Invalid Extn Insn", do_extension_fault, ILL_ILLOPC)
DO_ERROR_INFO(SIGILL, "Illegal Insn (or Seq)", insterror_is_error, ILL_ILLOPC)
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
/*
@@ -91,21 +93,11 @@ DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
int do_misaligned_access(unsigned long cause, unsigned long address,
struct pt_regs *regs, struct callee_regs *cregs)
{
- if (misaligned_fixup(address, regs, cause, cregs) != 0) {
- siginfo_t info;
-
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_ADRALN;
- info.si_addr = (void __user *)address;
- return handle_exception(cause, "Misaligned Access", regs,
- &info);
- }
+ if (misaligned_fixup(address, regs, cause, cregs) != 0)
+ return do_misaligned_error(cause, address, regs);
+
return 0;
}
-
-#else
-DO_ERROR_INFO(SIGSEGV, "Misaligned Access", do_misaligned_access, SEGV_ACCERR)
#endif
/*
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 7c10873c311..11c301b81c9 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -26,7 +26,6 @@ static noinline void print_reg_file(long *reg_rev, int start_num)
char buf[512];
int n = 0, len = sizeof(buf);
- /* weird loop because pt_regs regs rev r12..r0, r25..r13 */
for (i = start_num; i < start_num + 13; i++) {
n += scnprintf(buf + n, len - n, "r%02u: 0x%08lx\t",
i, (unsigned long)*reg_rev);
@@ -34,13 +33,18 @@ static noinline void print_reg_file(long *reg_rev, int start_num)
if (((i + 1) % 3) == 0)
n += scnprintf(buf + n, len - n, "\n");
+ /* because pt_regs has regs reversed: r12..r0, r25..r13 */
reg_rev--;
}
if (start_num != 0)
n += scnprintf(buf + n, len - n, "\n\n");
- pr_info("%s", buf);
+ /* To continue printing callee regs on same line as scratch regs */
+ if (start_num == 0)
+ pr_info("%s", buf);
+ else
+ pr_cont("%s\n", buf);
}
static void show_callee_regs(struct callee_regs *cregs)
@@ -71,7 +75,7 @@ void print_task_path_n_nm(struct task_struct *tsk, char *buf)
}
done:
- pr_info("%s, TGID %u\n", path_nm, tsk->tgid);
+ pr_info("Path: %s\n", path_nm);
}
EXPORT_SYMBOL(print_task_path_n_nm);
@@ -83,6 +87,10 @@ static void show_faulting_vma(unsigned long address, char *buf)
dev_t dev = 0;
char *nm = buf;
+ /* can't use print_vma_addr() yet as it doesn't check for
+ * non-inclusive vma
+ */
+
vma = find_vma(current->active_mm, address);
/* check against the find_vma( ) behaviour which returns the next VMA
@@ -98,10 +106,13 @@ static void show_faulting_vma(unsigned long address, char *buf)
ino = inode->i_ino;
}
pr_info(" @off 0x%lx in [%s]\n"
- " VMA: 0x%08lx to 0x%08lx\n\n",
- address - vma->vm_start, nm, vma->vm_start, vma->vm_end);
- } else
+ " VMA: 0x%08lx to 0x%08lx\n",
+ vma->vm_start < TASK_UNMAPPED_BASE ?
+ address : address - vma->vm_start,
+ nm, vma->vm_start, vma->vm_end);
+ } else {
pr_info(" @No matching VMA found\n");
+ }
}
static void show_ecr_verbose(struct pt_regs *regs)
@@ -110,7 +121,7 @@ static void show_ecr_verbose(struct pt_regs *regs)
unsigned long address;
cause_reg = current->thread.cause_code;
- pr_info("\n[ECR]: 0x%08x => ", cause_reg);
+ pr_info("\n[ECR ]: 0x%08x => ", cause_reg);
/* For Data fault, this is data address not instruction addr */
address = current->thread.fault_address;
@@ -120,7 +131,7 @@ static void show_ecr_verbose(struct pt_regs *regs)
/* For DTLB Miss or ProtV, display the memory involved too */
if (vec == ECR_V_DTLB_MISS) {
- pr_cont("Invalid (%s) @ 0x%08lx by insn @ 0x%08lx\n",
+ pr_cont("Invalid %s 0x%08lx by insn @ 0x%08lx\n",
(cause_code == 0x01) ? "Read From" :
((cause_code == 0x02) ? "Write to" : "EX"),
address, regs->ret);
@@ -163,24 +174,28 @@ void show_regs(struct pt_regs *regs)
return;
print_task_path_n_nm(tsk, buf);
+ show_regs_print_info(KERN_INFO);
if (current->thread.cause_code)
show_ecr_verbose(regs);
- pr_info("[EFA]: 0x%08lx\n", current->thread.fault_address);
- pr_info("[ERET]: 0x%08lx (PC of Faulting Instr)\n", regs->ret);
+ pr_info("[EFA ]: 0x%08lx\n[BLINK ]: %pS\n[ERET ]: %pS\n",
+ current->thread.fault_address,
+ (void *)regs->blink, (void *)regs->ret);
- show_faulting_vma(regs->ret, buf); /* faulting code, not data */
+ if (user_mode(regs))
+ show_faulting_vma(regs->ret, buf); /* faulting code, not data */
- /* can't use print_vma_addr() yet as it doesn't check for
- * non-inclusive vma
- */
+ pr_info("[STAT32]: 0x%08lx", regs->status32);
+
+#define STS_BIT(r, bit) r->status32 & STATUS_##bit##_MASK ? #bit : ""
+ if (!user_mode(regs))
+ pr_cont(" : %2s %2s %2s %2s %2s\n",
+ STS_BIT(regs, AE), STS_BIT(regs, A2), STS_BIT(regs, A1),
+ STS_BIT(regs, E2), STS_BIT(regs, E1));
- /* print special regs */
- pr_info("status32: 0x%08lx\n", regs->status32);
- pr_info(" SP: 0x%08lx\tFP: 0x%08lx\n", regs->sp, regs->fp);
- pr_info("BTA: 0x%08lx\tBLINK: 0x%08lx\n",
- regs->bta, regs->blink);
+ pr_info("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n",
+ regs->bta, regs->sp, regs->fp);
pr_info("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n",
regs->lp_start, regs->lp_end, regs->lp_count);