CVSROOT: /home/cvs
Module name: malta
Changes by: chris@ftp.linux-mips.org 05/07/28 18:26:20
Modified files:
linux/arch/mips: Tag: MaltaRef_2_6 Kconfig Makefile
linux/arch/mips/kernel: Tag: MaltaRef_2_6 Makefile genex.S
irq_cpu.c traps.c
linux/arch/mips/mips-boards/generic: Tag: MaltaRef_2_6 time.c
Log message:
* arch/mips/mips-boards/generic/time.c (mips_timer_interrupt): SMP
timer support.
* arch/mips/kernel/traps.c (do_mt): MT exception handler.
(mips_srs_alloc): Corrected spinlock usage.
(mips_srs_free): Corrected spinlock usage.
(per_cpu_trap_init): Disable VPE operation before changing cause
register (not strictly necessary because 2nd VPE shouldn't be
running...)
(trap_init): Install MT exception handler.
* arch/mips/kernel/irq_cpu.c: Check cpu_has_mipsmt before using
dvpe/evpe.
* arch/mips/kernel/genex.S: Added MT exception.
* arch/mips/kernel/Makefile: Added smp_mt.c.
* arch/mips/Makefile: Added CONFIG_MIPS_MIPSSIM support.
* arch/mips/Kconfig: Added MIPS_MIPSSIM and MIPS_MT_SMP. Make SMP
dependent on MIPS_MT_SMP.
diff -urN malta/linux/arch/mips/Kconfig malta/linux/arch/mips/Kconfig
--- malta/linux/arch/mips/Kconfig 2005/07/27 14:17:17 1.73.1000.8
+++ malta/linux/arch/mips/Kconfig 2005/07/28 17:26:18 1.73.1000.9
@@ -289,6 +289,12 @@
This enables support for the MIPS Technologies SEAD evaluation
board.
+config MIPS_MIPSSIM
+ bool 'Support for MIPS simulator (MIPSsim)'
+ select IRQ_CPU
+ help
+ This enables support for the MIPS Technologies MIPSsim simulator.
+
config MOMENCO_JAGUAR_ATX
bool "Support for Momentum Jaguar board"
select BOOT_ELF32
@@ -1150,6 +1156,14 @@
config MIPS_MT
bool "Enable MIPS MT"
+choice
+ prompt "MIPS MT options"
+ depends on MIPS_MT
+
+config MIPS_MT_SMP
+ bool "Use 1 TC on each available VPE for SMP"
+ select SMP
+
config MIPS_VPE_LOADER
bool "VPE loader support."
depends on MIPS_MT
@@ -1158,6 +1172,8 @@
Includes a loader for loading an elf relocatable object
onto another VPE and running it.
+endchoice
+
config MIPS_VPE_LOADER_TOM
bool "Load VPE program into memory hidden from linux"
depends on MIPS_VPE_LOADER
@@ -1291,7 +1307,7 @@
config SMP
bool "Multi-Processing support"
- depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) ||
SGI_IP27
+ depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) ||
SGI_IP27 || MIPS_MT_SMP
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
diff -urN malta/linux/arch/mips/Makefile malta/linux/arch/mips/Makefile
--- malta/linux/arch/mips/Makefile 2005/06/21 13:23:40 1.167.1000.5
+++ malta/linux/arch/mips/Makefile 2005/07/28 17:26:18 1.167.1000.6
@@ -423,6 +423,13 @@
load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000
#
+# MIPS simulator (MIPSsim)
+#
+core-$(CONFIG_MIPS_MIPSSIM) += arch/mips/mips-boards/sim/
+cflags-$(CONFIG_MIPS_MIPSSIM) += -Iinclude/asm-mips/mach-sim
+load-$(CONFIG_MIPS_MIPSSIM) += 0xffffffff80100000
+
+#
# Momentum Ocelot board
#
# The Ocelot setup.o must be linked early - it does the ioremap() for the
diff -urN malta/linux/arch/mips/kernel/Makefile
malta/linux/arch/mips/kernel/Makefile
--- malta/linux/arch/mips/kernel/Makefile 2005/07/27 13:37:54
1.80.1000.5
+++ malta/linux/arch/mips/kernel/Makefile 2005/07/28 17:26:19
1.80.1000.6
@@ -34,6 +34,8 @@
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_MIPS_MT_SMP) += smp_mt.o
+
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o
diff -urN malta/linux/arch/mips/kernel/genex.S
malta/linux/arch/mips/kernel/genex.S
--- malta/linux/arch/mips/kernel/genex.S 2005/06/21 13:24:02
1.7.1000.2
+++ malta/linux/arch/mips/kernel/genex.S 2005/07/28 17:26:19
1.7.1000.3
@@ -323,6 +323,7 @@
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
BUILD_HANDLER watch watch sti verbose /* #23 */
BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
+ BUILD_HANDLER mt mt sti verbose /* #25 */
BUILD_HANDLER dsp dsp sti silent /* #26 */
BUILD_HANDLER reserved reserved sti verbose /* others */
diff -urN malta/linux/arch/mips/kernel/irq_cpu.c
malta/linux/arch/mips/kernel/irq_cpu.c
--- malta/linux/arch/mips/kernel/irq_cpu.c 2005/07/22 13:21:43
1.8.1000.3
+++ malta/linux/arch/mips/kernel/irq_cpu.c 2005/07/28 17:26:19
1.8.1000.4
@@ -47,11 +47,12 @@
* to stop other VPEs whenever the local VPE does
* anything similar.
*/
- unsigned int vpflags = dvpe();
+ unsigned int vpflags = cpu_has_mipsmt ? dvpe() : 0;
#endif /* CONFIG_MIPS_MT */
clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
#ifdef CONFIG_MIPS_MT
- evpe(vpflags);
+ if (cpu_has_mipsmt)
+ evpe(vpflags);
#endif /* CONFIG_MIPS_MT */
set_c0_status(0x100 << (irq - mips_cpu_irq_base));
irq_enable_hazard();
@@ -97,14 +98,15 @@
static void mips_cpu_irq_ack(unsigned int irq)
{
#ifdef CONFIG_MIPS_MT
- unsigned int vpflags = dvpe();
+ unsigned int vpflags = cpu_has_mipsmt ? dvpe() : 0;
#endif /* CONFIG_MIPS_MT */
/* Only necessary for soft interrupts */
clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
#ifdef CONFIG_MIPS_MT
- evpe(vpflags);
+ if (cpu_has_mipsmt)
+ evpe(vpflags);
#endif /* CONFIG_MIPS_MT */
mask_mips_irq(irq);
}
diff -urN malta/linux/arch/mips/kernel/traps.c
malta/linux/arch/mips/kernel/traps.c
--- malta/linux/arch/mips/kernel/traps.c 2005/07/12 16:23:40
1.193.1000.6
+++ malta/linux/arch/mips/kernel/traps.c 2005/07/28 17:26:19
1.193.1000.7
@@ -56,6 +56,7 @@
extern asmlinkage void handle_fpe(void);
extern asmlinkage void handle_mdmx(void);
extern asmlinkage void handle_watch(void);
+extern asmlinkage void handle_mt(void);
extern asmlinkage void handle_dsp(void);
extern asmlinkage void handle_mcheck(void);
extern asmlinkage void handle_reserved(void);
@@ -801,6 +802,44 @@
(regs->cp0_status & ST0_TS) ? "" : "not ");
}
+asmlinkage void do_mt(struct pt_regs *regs)
+{
+ int subcode;
+
+ die_if_kernel("MIPS MT Thread exception in kernel", regs);
+
+ if (cpu_has_mipsmt) {
+ subcode = (read_vpe_c0_vpecontrol() & VPECONTROL_EXCPT)
+ >> VPECONTROL_EXCPT_SHIFT;
+ switch(subcode) {
+ case 0:
+ printk("Thread Underflow\n");
+ break;
+ case 1:
+ printk("Thread Overflow\n");
+ break;
+ case 2:
+ printk("Invalid YIELD Qualifier\n");
+ break;
+ case 3:
+ printk("Gating Storage Exception\n");
+ break;
+ case 4:
+ printk("YIELD Scheduler Exception\n");
+ break;
+ case 5:
+ printk("Gating Storage Schedulier Exception\n");
+ break;
+ default:
+ printk("*** UNKNOWN THREAD EXCEPTION %d ***\n",
+ subcode);
+ break;
+ }
+ }
+ force_sig(SIGILL, current);
+}
+
+
asmlinkage void do_dsp(struct pt_regs *regs)
{
if (cpu_has_dsp)
@@ -996,18 +1035,18 @@
int set;
long flags;
- spin_lock_irqsave(sr->sr_lock, flags);
+ spin_lock_irqsave(&sr->sr_lock, flags);
for (set = 0; set < sr->sr_supported; set++) {
if ((sr->sr_allocated & (1 << set)) == 0) {
sr->sr_allocated |= 1 << set;
- spin_unlock_irqrestore(sr->sr_lock, flags);
+ spin_unlock_irqrestore(&sr->sr_lock, flags);
return set;
}
}
/* None available */
- spin_unlock_irqrestore(sr->sr_lock, flags);
+ spin_unlock_irqrestore(&sr->sr_lock, flags);
return -1;
}
@@ -1016,9 +1055,9 @@
struct shadow_registers *sr = &shadow_registers;
long flags;
- spin_lock_irqsave(sr->sr_lock, flags);
+ spin_lock_irqsave(&sr->sr_lock, flags);
sr->sr_allocated &= ~(1 << set);
- spin_unlock_irqrestore(sr->sr_lock, flags);
+ spin_unlock_irqrestore(&sr->sr_lock, flags);
}
void *set_vi_srs_handler (int n, void *addr, int srs)
@@ -1189,8 +1228,17 @@
/* Setting vector spacing enables EI/VI mode */
change_c0_intctl (0x3e0, VECTORSPACING);
}
- if (cpu_has_divec)
+ if (cpu_has_divec) {
+#ifdef CONFIG_MIPS_MT
+ unsigned int vpflags;
+ vpflags = cpu_has_mipsmt ? dvpe() : 0;
+#endif
set_c0_cause(CAUSEF_IV);
+#ifdef CONFIG_MIPS_MT
+ if (cpu_has_mipsmt)
+ evpe(vpflags);
+#endif
+ }
cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
TLBMISS_HANDLER_SETUP();
@@ -1331,6 +1379,9 @@
if (cpu_has_mcheck)
set_except_vector(24, handle_mcheck);
+ if (cpu_has_mipsmt)
+ set_except_vector(25, handle_mt);
+
if (cpu_has_dsp)
set_except_vector(26, handle_dsp);
diff -urN malta/linux/arch/mips/mips-boards/generic/time.c
malta/linux/arch/mips/mips-boards/generic/time.c
--- malta/linux/arch/mips/mips-boards/generic/time.c 2005/06/21 13:24:12
1.23.1000.3
+++ malta/linux/arch/mips/mips-boards/generic/time.c 2005/07/28 17:26:20
1.23.1000.4
@@ -61,6 +61,15 @@
static unsigned int timer_tick_count=0;
static int mips_cpu_timer_irq;
+static inline void scroll_display_message(void)
+{
+ if ((timer_tick_count++ % HZ) == 0) {
+ mips_display_message(&display_string[display_count++]);
+ if (display_count == MAX_DISPLAY_COUNT)
+ display_count = 0;
+ }
+}
+
static void mips_timer_dispatch (struct pt_regs *regs)
{
do_IRQ (mips_cpu_timer_irq, regs);
@@ -68,17 +77,42 @@
irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
+#ifdef CONFIG_SMP
+ int cpu = smp_processor_id();
+
+ if (cpu == 0) {
+ /*
+ * CPU 0 handles the global timer interrupt job and process
accounting
+ * resets count/compare registers to trigger next timer int.
+ */
+ (void) timer_interrupt(irq, dev_id, regs);
+ scroll_display_message();
+ }
+ else {
+ /* Everyone else needs to reset the timer int here as
+ ll_local_timer_interrupt doesn't */
+ /*
+ * FIXME: need to cope with counter underflow.
+ * More support needs to be added to kernel/time for
+ * counter/timer interrupts on multiple CPU's
+ */
+ write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ));
+ /*
+ * other CPUs should do profiling and process accounting
+ */
+ local_timer_interrupt (irq, dev_id, regs);
+ }
+
+ return IRQ_HANDLED;
+#else
irqreturn_t r;
r = timer_interrupt(irq, dev_id, regs);
- if ((timer_tick_count++ % HZ) == 0) {
- mips_display_message(&display_string[display_count++]);
- if (display_count == MAX_DISPLAY_COUNT)
- display_count = 0;
- }
+ scroll_display_message();
return r;
+#endif
}
/*
@@ -89,7 +123,7 @@
unsigned int prid = read_c0_prid() & 0xffff00;
unsigned int count;
-#ifdef CONFIG_MIPS_SEAD
+#if defined(CONFIG_MIPS_SEAD) || defined(CONFIG_MIPS_MIPSSIM)
/*
* The SEAD board doesn't have a real time clock, so we can't
* really calculate the timer frequency
@@ -176,6 +210,13 @@
irq->handler = mips_timer_interrupt; /* we use our own handler */
setup_irq(mips_cpu_timer_irq, irq);
+#ifdef CONFIG_SMP
+ /* irq_desc(riptor) is a global resource, when the interrupt overlaps
+ on seperate cpu's the first one tries to handle the second interrupt.
+ The effect is that the int remains disabled on the second cpu.
+ Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
+ irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
+#endif
/* to generate the first timer interrupt */
write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
|