aboutsummaryrefslogtreecommitdiff
path: root/arch/cris/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/cris/kernel')
-rw-r--r--arch/cris/kernel/Makefile3
-rw-r--r--arch/cris/kernel/crisksyms.c21
-rw-r--r--arch/cris/kernel/irq.c263
-rw-r--r--arch/cris/kernel/module.c39
-rw-r--r--arch/cris/kernel/process.c31
-rw-r--r--arch/cris/kernel/profile.c73
-rw-r--r--arch/cris/kernel/ptrace.c37
-rw-r--r--arch/cris/kernel/setup.c26
-rw-r--r--arch/cris/kernel/time.c18
-rw-r--r--arch/cris/kernel/traps.c64
10 files changed, 249 insertions, 326 deletions
diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
index 1546a0e7404..c8e8ea57098 100644
--- a/arch/cris/kernel/Makefile
+++ b/arch/cris/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.10 2004/05/14 10:18:12 starvik Exp $
+# $Id: Makefile,v 1.12 2004/10/19 13:07:43 starvik Exp $
#
# Makefile for the linux kernel.
#
@@ -10,6 +10,7 @@ obj-y := process.o traps.o irq.o ptrace.o setup.o \
obj-$(CONFIG_MODULES) += crisksyms.o
obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_SYSTEM_PROFILER) += profile.o
clean:
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index 7141bbecd7e..85833d704eb 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -27,13 +27,13 @@ extern void __Udiv(void);
extern void __Umod(void);
extern void __Div(void);
extern void __Mod(void);
+extern void __ashldi3(void);
extern void __ashrdi3(void);
-extern void iounmap(void *addr);
+extern void __lshrdi3(void);
+extern void iounmap(volatile void * __iomem);
/* Platform dependent support */
EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(get_cmos_time);
EXPORT_SYMBOL(loops_per_usec);
@@ -57,7 +57,9 @@ EXPORT_SYMBOL(__Udiv);
EXPORT_SYMBOL(__Umod);
EXPORT_SYMBOL(__Div);
EXPORT_SYMBOL(__Mod);
+EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshrdi3);
/* Memory functions */
EXPORT_SYMBOL(__ioremap);
@@ -69,23 +71,10 @@ EXPORT_SYMBOL(__down);
EXPORT_SYMBOL(__down_interruptible);
EXPORT_SYMBOL(__down_trylock);
-/* Export shadow registers for the CPU I/O pins */
-EXPORT_SYMBOL(genconfig_shadow);
-EXPORT_SYMBOL(port_pa_data_shadow);
-EXPORT_SYMBOL(port_pa_dir_shadow);
-EXPORT_SYMBOL(port_pb_data_shadow);
-EXPORT_SYMBOL(port_pb_dir_shadow);
-EXPORT_SYMBOL(port_pb_config_shadow);
-EXPORT_SYMBOL(port_g_data_shadow);
-
/* Userspace access functions */
EXPORT_SYMBOL(__copy_user_zeroing);
EXPORT_SYMBOL(__copy_user);
-/* Cache flush functions */
-EXPORT_SYMBOL(flush_etrax_cache);
-EXPORT_SYMBOL(prepare_rx_descriptor);
-
#undef memcpy
#undef memset
extern void * memset(void *, int, __kernel_size_t);
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
index d848b940745..30deaf1b728 100644
--- a/arch/cris/kernel/irq.c
+++ b/arch/cris/kernel/irq.c
@@ -12,8 +12,6 @@
* shouldn't result in any weird surprises, and installing new handlers
* should be easier.
*
- * Notice Linux/CRIS: these routines do not care about SMP
- *
*/
/*
@@ -24,6 +22,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/ptrace.h>
+#include <linux/irq.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
@@ -36,84 +35,56 @@
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/errno.h>
-#include <linux/bitops.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
-/* Defined in arch specific irq.c */
-extern void arch_setup_irq(int irq);
-extern void arch_free_irq(int irq);
-
-void
-disable_irq(unsigned int irq_nr)
-{
- unsigned long flags;
-
- local_save_flags(flags);
- local_irq_disable();
- mask_irq(irq_nr);
- local_irq_restore(flags);
-}
-
-void
-enable_irq(unsigned int irq_nr)
+void ack_bad_irq(unsigned int irq)
{
- unsigned long flags;
- local_save_flags(flags);
- local_irq_disable();
- unmask_irq(irq_nr);
- local_irq_restore(flags);
+ printk("unexpected IRQ trap at vector %02x\n", irq);
}
-unsigned long
-probe_irq_on()
-{
- return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-int
-probe_irq_off(unsigned long x)
-{
- return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-/*
- * Initial irq handlers.
- */
-
-static struct irqaction *irq_action[NR_IRQS];
-
int show_interrupts(struct seq_file *p, void *v)
{
- int i = *(loff_t *) v;
+ int i = *(loff_t *) v, j;
struct irqaction * action;
unsigned long flags;
+ if (i == 0) {
+ seq_printf(p, " ");
+ for (j=0; j<NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
+ }
+
if (i < NR_IRQS) {
- local_irq_save(flags);
- action = irq_action[i];
- if (!action)
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
goto skip;
- seq_printf(p, "%2d: %10u %c %s",
- i, kstat_this_cpu.irqs[i],
- (action->flags & SA_INTERRUPT) ? '+' : ' ',
- action->name);
- for (action = action->next; action; action = action->next) {
- seq_printf(p, ",%s %s",
- (action->flags & SA_INTERRUPT) ? " +" : "",
- action->name);
- }
+ seq_printf(p, "%3d: ",i);
+#ifndef CONFIG_SMP
+ seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %s", action->name);
+
+ for (action=action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+
seq_putc(p, '\n');
skip:
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
return 0;
}
+
/* called by the assembler IRQ entry functions defined in irq.h
* to dispatch the interrupts to registred handlers
* interrupts are disabled upon entry - depending on if the
@@ -123,164 +94,17 @@ skip:
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
- struct irqaction *action;
- int do_random, cpu;
- int ret, retval = 0;
-
- cpu = smp_processor_id();
- irq_enter();
- kstat_cpu(cpu).irqs[irq - FIRST_IRQ]++;
- action = irq_action[irq - FIRST_IRQ];
-
- if (action) {
- if (!(action->flags & SA_INTERRUPT))
- local_irq_enable();
- do_random = 0;
- do {
- ret = action->handler(irq, action->dev_id, regs);
- if (ret == IRQ_HANDLED)
- do_random |= action->flags;
- retval |= ret;
- action = action->next;
- } while (action);
-
- if (retval != 1) {
- if (retval) {
- printk("irq event %d: bogus retval mask %x\n",
- irq, retval);
- } else {
- printk("irq %d: nobody cared\n", irq);
- }
- }
-
- if (do_random & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
- local_irq_disable();
- }
- irq_exit();
-}
-
-/* this function links in a handler into the chain of handlers for the
- given irq, and if the irq has never been registred, the appropriate
- handler is entered into the interrupt vector
-*/
-
-int setup_irq(int irq, struct irqaction * new)
-{
- int shared = 0;
- struct irqaction *old, **p;
- unsigned long flags;
-
- p = irq_action + irq - FIRST_IRQ;
- if ((old = *p) != NULL) {
- /* Can't share interrupts unless both agree to */
- if (!(old->flags & new->flags & SA_SHIRQ))
- return -EBUSY;
-
- /* Can't share interrupts unless both are same type */
- if ((old->flags ^ new->flags) & SA_INTERRUPT)
- return -EBUSY;
-
- /* add new interrupt at end of irq queue */
- do {
- p = &old->next;
- old = *p;
- } while (old);
- shared = 1;
- }
-
- if (new->flags & SA_SAMPLE_RANDOM)
- rand_initialize_irq(irq);
-
- local_save_flags(flags);
- local_irq_disable();
- *p = new;
-
- if (!shared) {
- /* if the irq wasn't registred before, enter it into the vector table
- and unmask it physically
- */
- arch_setup_irq(irq);
- unmask_irq(irq);
- }
-
- local_irq_restore(flags);
- return 0;
-}
-
-/* this function is called by a driver to register an irq handler
- Valid flags:
- SA_INTERRUPT -> it's a fast interrupt, handler called with irq disabled and
- no signal checking etc is performed upon exit
- SA_SHIRQ -> the interrupt can be shared between different handlers, the handler
- is required to check if the irq was "aimed" at it explicitely
- SA_RANDOM -> the interrupt will add to the random generators entropy
-*/
-
-int request_irq(unsigned int irq,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags,
- const char * devname,
- void *dev_id)
-{
- int retval;
- struct irqaction * action;
-
- if(!handler)
- return -EINVAL;
-
- /* allocate and fill in a handler structure and setup the irq */
-
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action)
- return -ENOMEM;
-
- action->handler = handler;
- action->flags = irqflags;
- cpus_clear(action->mask);
- action->name = devname;
- action->next = NULL;
- action->dev_id = dev_id;
-
- retval = setup_irq(irq, action);
-
- if (retval)
- kfree(action);
- return retval;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
- struct irqaction * action, **p;
- unsigned long flags;
-
- if (irq >= NR_IRQS) {
- printk("Trying to free IRQ%d\n",irq);
- return;
+ unsigned long sp;
+ irq_enter();
+ sp = rdsp();
+ if (unlikely((sp & (PAGE_SIZE - 1)) < (PAGE_SIZE/8))) {
+ printk("do_IRQ: stack overflow: %lX\n", sp);
+ show_stack(NULL, (unsigned long *)sp);
}
- for (p = irq - FIRST_IRQ + irq_action; (action = *p) != NULL; p = &action->next) {
- if (action->dev_id != dev_id)
- continue;
-
- /* Found it - now free it */
- local_save_flags(flags);
- local_irq_disable();
- *p = action->next;
- if (!irq_action[irq - FIRST_IRQ]) {
- mask_irq(irq);
- arch_free_irq(irq);
- }
- local_irq_restore(flags);
- kfree(action);
- return;
- }
- printk("Trying to free free IRQ%d\n",irq);
+ __do_IRQ(irq, regs);
+ irq_exit();
}
-EXPORT_SYMBOL(free_irq);
-
void weird_irq(void)
{
local_irq_disable();
@@ -288,10 +112,3 @@ void weird_irq(void)
while(1);
}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-/* Used by other archs to show/control IRQ steering during SMP */
-void __init
-init_irq_proc(void)
-{
-}
-#endif
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c
index f1d3e784f30..11b867df861 100644
--- a/arch/cris/kernel/module.c
+++ b/arch/cris/kernel/module.c
@@ -32,7 +32,7 @@ void *module_alloc(unsigned long size)
{
if (size == 0)
return NULL;
- return vmalloc(size);
+ return vmalloc_exec(size);
}
@@ -59,26 +59,8 @@ int apply_relocate(Elf32_Shdr *sechdrs,
unsigned int relsec,
struct module *me)
{
- unsigned int i;
- Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
- Elf32_Sym *sym;
- uint32_t *location;
-
- DEBUGP("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
- /* This is where to make the change */
- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
- + rel[i].r_offset;
- /* This is the symbol it is referring to. Note that all
- undefined symbols have been resolved. */
- sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
- + ELF32_R_SYM(rel[i].r_info);
-
- /* We add the value into the location given */
- *location += sym->st_value;
- }
- return 0;
+ printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
+ return -ENOEXEC;
}
int apply_relocate_add(Elf32_Shdr *sechdrs,
@@ -90,7 +72,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
unsigned int i;
Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
- DEBUGP ("Applying relocate section %u to %u\n", relsec,
+ DEBUGP ("Applying add relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) {
@@ -103,7 +85,18 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
Elf32_Sym *sym
= ((Elf32_Sym *)sechdrs[symindex].sh_addr
+ ELF32_R_SYM (rela[i].r_info));
- *loc = sym->st_value + rela[i].r_addend;
+ switch (ELF32_R_TYPE(rela[i].r_info)) {
+ case R_CRIS_32:
+ *loc = sym->st_value + rela[i].r_addend;
+ break;
+ case R_CRIS_32_PCREL:
+ *loc = sym->st_value - (unsigned)loc + rela[i].r_addend - 4;
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rela[i].r_info));
+ return -ENOEXEC;
+ }
}
return 0;
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index a5ad2b67585..949a0e40e03 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.17 2004/04/05 13:53:48 starvik Exp $
+/* $Id: process.c,v 1.21 2005/03/04 08:16:17 starvik Exp $
*
* linux/arch/cris/kernel/process.c
*
@@ -8,6 +8,18 @@
* Authors: Bjorn Wesen (bjornw@axis.com)
*
* $Log: process.c,v $
+ * Revision 1.21 2005/03/04 08:16:17 starvik
+ * Merge of Linux 2.6.11.
+ *
+ * Revision 1.20 2005/01/18 05:57:22 starvik
+ * Renamed hlt_counter to cris_hlt_counter and made it global.
+ *
+ * Revision 1.19 2004/10/19 13:07:43 starvik
+ * Merge of Linux 2.6.9
+ *
+ * Revision 1.18 2004/08/16 12:37:23 starvik
+ * Merge of Linux 2.6.8
+ *
* Revision 1.17 2004/04/05 13:53:48 starvik
* Merge of Linux 2.6.5
*
@@ -161,18 +173,18 @@ EXPORT_SYMBOL(init_task);
* region by enable_hlt/disable_hlt.
*/
-static int hlt_counter=0;
+int cris_hlt_counter=0;
void disable_hlt(void)
{
- hlt_counter++;
+ cris_hlt_counter++;
}
EXPORT_SYMBOL(disable_hlt);
void enable_hlt(void)
{
- hlt_counter--;
+ cris_hlt_counter--;
}
EXPORT_SYMBOL(enable_hlt);
@@ -195,16 +207,19 @@ void cpu_idle (void)
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
- void (*idle)(void) = pm_idle;
-
+ void (*idle)(void);
+ /*
+ * Mark this as an RCU critical section so that
+ * synchronize_kernel() in the unload path waits
+ * for our completion.
+ */
+ idle = pm_idle;
if (!idle)
idle = default_idle;
-
idle();
}
schedule();
}
-
}
void hard_reset_now (void);
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
new file mode 100644
index 00000000000..69c52189f04
--- /dev/null
+++ b/arch/cris/kernel/profile.c
@@ -0,0 +1,73 @@
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/types.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+#define SAMPLE_BUFFER_SIZE 8192
+
+static char* sample_buffer;
+static char* sample_buffer_pos;
+static int prof_running = 0;
+
+void
+cris_profile_sample(struct pt_regs* regs)
+{
+ if (!prof_running)
+ return;
+ if (user_mode(regs))
+ *(unsigned int*)sample_buffer_pos = current->pid;
+ else
+ *(unsigned int*)sample_buffer_pos = 0;
+ *(unsigned int*)(sample_buffer_pos + 4) = instruction_pointer(regs);
+ sample_buffer_pos += 8;
+ if (sample_buffer_pos == sample_buffer + SAMPLE_BUFFER_SIZE)
+ sample_buffer_pos = sample_buffer;
+}
+
+static ssize_t
+read_cris_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ if (p > SAMPLE_BUFFER_SIZE)
+ return 0;
+ if (p + count > SAMPLE_BUFFER_SIZE)
+ count = SAMPLE_BUFFER_SIZE - p;
+ if (copy_to_user(buf, sample_buffer + p,count))
+ return -EFAULT;
+ memset(sample_buffer + p, 0, count);
+ *ppos += count;
+ return count;
+}
+
+static ssize_t
+write_cris_profile(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ sample_buffer_pos = sample_buffer;
+ memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE);
+}
+
+static struct file_operations cris_proc_profile_operations = {
+ .read = read_cris_profile,
+ .write = write_cris_profile,
+};
+
+static int
+__init init_cris_profile(void)
+{
+ struct proc_dir_entry *entry;
+ sample_buffer = (char*)kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
+ sample_buffer_pos = sample_buffer;
+ entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL);
+ if (entry) {
+ entry->proc_fops = &cris_proc_profile_operations;
+ entry->size = SAMPLE_BUFFER_SIZE;
+ }
+ prof_running = 1;
+ return 0;
+}
+
+__initcall(init_cris_profile);
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
index e85a2fdd9ac..2b6363cbe98 100644
--- a/arch/cris/kernel/ptrace.c
+++ b/arch/cris/kernel/ptrace.c
@@ -8,6 +8,12 @@
* Authors: Bjorn Wesen
*
* $Log: ptrace.c,v $
+ * Revision 1.10 2004/09/22 11:50:01 orjanf
+ * * Moved get_reg/put_reg to arch-specific files.
+ * * Added functions to access debug registers (CRISv32).
+ * * Added support for PTRACE_SINGLESTEP (CRISv32).
+ * * Added S flag to CCS_MASK (CRISv32).
+ *
* Revision 1.9 2003/07/04 12:56:11 tobiasa
* Moved arch-specific code to arch-specific files.
*
@@ -72,37 +78,6 @@
#include <asm/system.h>
#include <asm/processor.h>
-/*
- * Get contents of register REGNO in task TASK.
- */
-inline long get_reg(struct task_struct *task, unsigned int regno)
-{
- /* USP is a special case, it's not in the pt_regs struct but
- * in the tasks thread struct
- */
-
- if (regno == PT_USP)
- return task->thread.usp;
- else if (regno < PT_MAX)
- return ((unsigned long *)user_regs(task->thread_info))[regno];
- else
- return 0;
-}
-
-/*
- * Write contents of register REGNO in task TASK.
- */
-inline int put_reg(struct task_struct *task, unsigned int regno,
- unsigned long data)
-{
- if (regno == PT_USP)
- task->thread.usp = data;
- else if (regno < PT_MAX)
- ((unsigned long *)user_regs(task->thread_info))[regno] = data;
- else
- return -1;
- return 0;
-}
/* notification of userspace execution resumption
* - triggered by current->work.notify_resume
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index 6ec2671078b..d11206e467a 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -17,6 +17,7 @@
#include <asm/pgtable.h>
#include <linux/seq_file.h>
#include <linux/tty.h>
+#include <linux/utsname.h>
#include <asm/setup.h>
@@ -29,7 +30,7 @@ struct screen_info screen_info;
extern int root_mountflags;
extern char _etext, _edata, _end;
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+char cris_command_line[COMMAND_LINE_SIZE] = { 0, };
extern const unsigned long text_start, edata; /* set by the linker script */
extern unsigned long dram_start, dram_end;
@@ -147,34 +148,35 @@ setup_arch(char **cmdline_p)
paging_init();
- /* We don't use a command line yet, so just re-initialize it without
- saving anything that might be there. */
-
- *cmdline_p = command_line;
+ *cmdline_p = cris_command_line;
#ifdef CONFIG_ETRAX_CMDLINE
- strlcpy(command_line, CONFIG_ETRAX_CMDLINE, COMMAND_LINE_SIZE);
- command_line[COMMAND_LINE_SIZE - 1] = '\0';
+ if (!strcmp(cris_command_line, "")) {
+ strlcpy(cris_command_line, CONFIG_ETRAX_CMDLINE, COMMAND_LINE_SIZE);
+ cris_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+ }
+#endif
/* Save command line for future references. */
- memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+ memcpy(saved_command_line, cris_command_line, COMMAND_LINE_SIZE);
saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
-#endif
/* give credit for the CRIS port */
show_etrax_copyright();
+
+ /* Setup utsname */
+ strcpy(system_utsname.machine, cris_machine_name);
}
static void *c_start(struct seq_file *m, loff_t *pos)
{
- /* We only got one CPU... */
- return *pos < 1 ? (void *)1 : NULL;
+ return *pos < NR_CPUS ? (void *)(int)(*pos + 1): NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
++*pos;
- return NULL;
+ return c_start(m, pos);
}
static void c_stop(struct seq_file *m, void *v)
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index 6c28b0e7f7b..fa2d4323da2 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.14 2004/06/01 05:38:11 starvik Exp $
+/* $Id: time.c,v 1.18 2005/03/04 08:16:17 starvik Exp $
*
* linux/arch/cris/kernel/time.c
*
@@ -30,6 +30,7 @@
#include <linux/bcd.h>
#include <linux/timex.h>
#include <linux/init.h>
+#include <linux/profile.h>
u64 jiffies_64 = INITIAL_JIFFIES;
@@ -214,6 +215,21 @@ update_xtime_from_cmos(void)
}
}
+extern void cris_profile_sample(struct pt_regs* regs);
+
+void
+cris_do_profile(struct pt_regs* regs)
+{
+
+#if CONFIG_SYSTEM_PROFILER
+ cris_profile_sample(regs);
+#endif
+
+#if CONFIG_PROFILING
+ profile_tick(CPU_PROFILING, regs);
+#endif
+}
+
/*
* Scheduler clock - returns current time in nanosec units.
*/
diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c
index d4dfa050e3a..520d92205fe 100644
--- a/arch/cris/kernel/traps.c
+++ b/arch/cris/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.9 2004/05/11 12:28:26 starvik Exp $
+/* $Id: traps.c,v 1.11 2005/01/24 16:03:19 orjanf Exp $
*
* linux/arch/cris/traps.c
*
@@ -20,13 +20,15 @@
static int kstack_depth_to_print = 24;
+extern int raw_printk(const char *fmt, ...);
+
void show_trace(unsigned long * stack)
{
unsigned long addr, module_start, module_end;
extern char _stext, _etext;
int i;
- printk("\nCall Trace: ");
+ raw_printk("\nCall Trace: ");
i = 1;
module_start = VMALLOC_START;
@@ -37,7 +39,7 @@ void show_trace(unsigned long * stack)
/* This message matches "failing address" marked
s390 in ksymoops, so lines containing it will
not be filtered out by ksymoops. */
- printk ("Failing address 0x%lx\n", (unsigned long)stack);
+ raw_printk ("Failing address 0x%lx\n", (unsigned long)stack);
break;
}
stack++;
@@ -54,8 +56,8 @@ void show_trace(unsigned long * stack)
(addr <= (unsigned long) &_etext)) ||
((addr >= module_start) && (addr <= module_end))) {
if (i && ((i % 8) == 0))
- printk("\n ");
- printk("[<%08lx>] ", addr);
+ raw_printk("\n ");
+ raw_printk("[<%08lx>] ", addr);
i++;
}
}
@@ -96,25 +98,59 @@ show_stack(struct task_struct *task, unsigned long *sp)
stack = sp;
- printk("\nStack from %08lx:\n ", (unsigned long)stack);
+ raw_printk("\nStack from %08lx:\n ", (unsigned long)stack);
for(i = 0; i < kstack_depth_to_print; i++) {
if (((long) stack & (THREAD_SIZE-1)) == 0)
break;
if (i && ((i % 8) == 0))
- printk("\n ");
+ raw_printk("\n ");
if (__get_user (addr, stack)) {
/* This message matches "failing address" marked
s390 in ksymoops, so lines containing it will
not be filtered out by ksymoops. */
- printk ("Failing address 0x%lx\n", (unsigned long)stack);
+ raw_printk ("Failing address 0x%lx\n", (unsigned long)stack);
break;
}
stack++;
- printk("%08lx ", addr);
+ raw_printk("%08lx ", addr);
}
show_trace(sp);
}
+static void (*nmi_handler)(struct pt_regs*);
+extern void arch_enable_nmi(void);
+
+void set_nmi_handler(void (*handler)(struct pt_regs*))
+{
+ nmi_handler = handler;
+ arch_enable_nmi();
+}
+
+void handle_nmi(struct pt_regs* regs)
+{
+ if (nmi_handler)
+ nmi_handler(regs);
+}
+
+#ifdef CONFIG_DEBUG_NMI_OOPS
+void oops_nmi_handler(struct pt_regs* regs)
+{
+ stop_watchdog();
+ raw_printk("NMI!\n");
+ show_registers(regs);
+}
+
+static int
+__init oops_nmi_register(void)
+{
+ set_nmi_handler(oops_nmi_handler);
+ return 0;
+}
+
+__initcall(oops_nmi_register);
+
+#endif
+
#if 0
/* displays a short stack trace */
@@ -123,9 +159,9 @@ show_stack()
{
unsigned long *sp = (unsigned long *)rdusp();
int i;
- printk("Stack dump [0x%08lx]:\n", (unsigned long)sp);
+ raw_printk("Stack dump [0x%08lx]:\n", (unsigned long)sp);
for(i = 0; i < 16; i++)
- printk("sp + %d: 0x%08lx\n", i*4, sp[i]);
+ raw_printk("sp + %d: 0x%08lx\n", i*4, sp[i]);
return 0;
}
#endif
@@ -142,3 +178,9 @@ trap_init(void)
{
/* Nothing needs to be done */
}
+
+void spinning_cpu(void* addr)
+{
+ raw_printk("CPU %d spinning on %X\n", smp_processor_id(), addr);
+ dump_stack();
+}