patch-1.3.4 linux/arch/sparc/kernel/traps.c

Next file: linux/arch/sparc/mm/Makefile
Previous file: linux/arch/sparc/kernel/setup.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.3/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
@@ -1,7 +1,7 @@
 /*
  * arch/sparc/kernel/traps.c
  *
- * Copyright 1994 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
 /*
@@ -11,37 +11,274 @@
 #include <linux/sched.h>  /* for jiffies */
 #include <linux/kernel.h>
 
-void do_hw_interrupt(unsigned long type, unsigned long vector)
-{
-  if (vector == 14) {
-    jiffies++;
-    return;
-  }
+#include <asm/delay.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/oplib.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mp.h>
+#include <asm/kdebug.h>
 
-  /* Just print garbage for everything else for now. */
+void
+do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
+{
 
-  printk("Unimplemented Sparc TRAP, vector = %lx type = %lx\n", vector, type);
+  printk("Unimplemented Sparc TRAP, type = %02lx psr = %08lx pc = %08lx\n",
+	 type, psr, pc);
+  halt();
 
   return;
 }
 
-extern unsigned long *trapbase;
+void
+do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Illegal instruction at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Privileged instruction at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Unaligned memory access at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Floating Point Disabled trap at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Floating Point Exception at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Tag overflow trap at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Watchpoint detected at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_iacc_error(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Instruction Access Error at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Co-Processor disabled trap at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_bad_flush(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Unimplemented FLUSH Exception at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_dacc_error(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Data Access Error at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Divide By Zero Exception at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_dstore_error(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Data Store Error at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+void
+handle_dacc_mmu_miss(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
+{
+	printk("Data Access MMU-Miss Exception at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
 
-void trap_init(void)
+void
+handle_iacc_mmu_miss(struct pt_regs *regs, unsigned long pc, unsigned long npc,
+		       unsigned long psr)
 {
+	printk("Instruction Access MMU-Miss Exception at PC %08lx NPC %08lx PSR %08lx\n",
+	       pc, npc, psr);
+	halt();
+	return;
+}
+
+/* Since we have our mappings set up, on multiprocessors we can spin them
+ * up here so that timer interrupts work during initialization.
+ */
+
+extern void sparc_cpu_startup(void);
 
-  /* load up the trap table */
+extern int linux_num_cpus;
+extern pgd_t *lnx_root;
 
-#if 0 /* not yet */
-  __asm__("wr %0, 0x0, %%tbr\n\t"
-	  "nop; nop; nop\n\t" : :
-	  "r" (trapbase));
+int linux_smp_still_initting;
+unsigned int thiscpus_tbr;
+int thiscpus_mid;
+
+/* #define SMP_TESTING */
+
+void
+trap_init(void)
+{
+	struct linux_prom_registers ctx_reg;
+	int i;
+
+	if(linux_num_cpus == 1) {
+		printk("trap_init: Uniprocessor detected.\n");
+		return;
+	}
+	if(sparc_cpu_model != sun4m) {
+		printk("trap_init: Multiprocessor on a non-sun4m! Aieee...\n");
+		printk("trap_init: Cannot continue, bailing out.\n");
+		prom_halt();
+	}
+	/* Ok, we are on a sun4m with multiple cpu's */
+	printk("trap_init: Multiprocessor detected, initiating CPU-startup. cpus=%d\n",
+	       linux_num_cpus);
+	linux_smp_still_initting = 1;
+	ctx_reg.which_io = 0x0;  /* real ram */
+	ctx_reg.phys_addr = (char *) (((unsigned long) lnx_root) - PAGE_OFFSET);
+	ctx_reg.reg_size = 0x0;
+	/* This basically takes every cpu, loads up our Linux context table
+	 * into it's context table pointer register, inits it at the low level
+	 * and then makes it spin in an endless loop...
+	 */
+	for(i=0; i<linux_num_cpus; i++) {
+		if((linux_cpus[i].mid & (~8)) != 0x0) {
+			static int cpuid = 0;
+			cpuid = (linux_cpus[i].mid & (~8));
+			percpu_table[cpuid].cpu_is_alive = 0;
+			thiscpus_mid = linux_cpus[i].mid;
+			thiscpus_tbr = (unsigned int)
+				percpu_table[cpuid].trap_table;
+#ifdef SMP_TESTING
+			printk("thiscpus_tbr = %08x\n", thiscpus_tbr);
+			printk("About to fire up cpu %d mid %d cpuid %d\n", i,
+			       linux_cpus[i].mid, cpuid);
 #endif
+			prom_startcpu(linux_cpus[i].prom_node, &ctx_reg, 0x0,
+				      (char *) sparc_cpu_startup);
+			printk("Waiting for cpu %d to start up...\n", i);
+			while(percpu_table[cpuid].cpu_is_alive == 0) {
+				static int counter = 0;
+				counter++;
+				if(counter>200) {
+#ifdef SMP_TESTING
+					printk("UGH, CPU would not start up ;-( \n");
+#endif
+					break;
+				}
+				__delay(200000);
+			}
+		}
+	}
 
-  return;
+	linux_smp_still_initting = 1;
+
+	return;
 }
 
-void die_if_kernel(char * str, struct pt_regs * regs, long err)
+void
+die_if_kernel(char * str, struct pt_regs * regs, long err)
 {
   return;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this