aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mips-boards
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-04-05 04:45:45 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-04-18 22:14:28 -0400
commit41c594ab65fc89573af296d192aa5235d09717ab (patch)
tree562462512a320f386bdf49eabfbb26bb3ee761fa /arch/mips/mips-boards
parent2600990e640e3bef29ed89d565864cf16ee83833 (diff)
[MIPS] MT: Improved multithreading support.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mips-boards')
-rw-r--r--arch/mips/mips-boards/generic/init.c1
-rw-r--r--arch/mips/mips-boards/generic/time.c68
-rw-r--r--arch/mips/mips-boards/malta/Makefile1
-rw-r--r--arch/mips/mips-boards/malta/malta_int.c11
-rw-r--r--arch/mips/mips-boards/malta/malta_smp.c128
-rw-r--r--arch/mips/mips-boards/sim/cmdline.c59
-rw-r--r--arch/mips/mips-boards/sim/sim_cmdline.c6
-rw-r--r--arch/mips/mips-boards/sim/sim_smp.c14
8 files changed, 203 insertions, 85 deletions
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index eab5a705e989..17dfe6a8cab9 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -220,7 +220,6 @@ void __init kgdb_config (void)
220 generic_putDebugChar (*s++); 220 generic_putDebugChar (*s++);
221 } 221 }
222 222
223 kgdb_enabled = 1;
224 /* Breakpoint is invoked after interrupts are initialised */ 223 /* Breakpoint is invoked after interrupts are initialised */
225 } 224 }
226} 225}
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 93f3bf2c2b22..a9f6124b3a22 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -30,6 +30,7 @@
30#include <linux/mc146818rtc.h> 30#include <linux/mc146818rtc.h>
31 31
32#include <asm/mipsregs.h> 32#include <asm/mipsregs.h>
33#include <asm/mipsmtregs.h>
33#include <asm/ptrace.h> 34#include <asm/ptrace.h>
34#include <asm/hardirq.h> 35#include <asm/hardirq.h>
35#include <asm/irq.h> 36#include <asm/irq.h>
@@ -50,16 +51,23 @@ unsigned long cpu_khz;
50static char display_string[] = " LINUX ON ATLAS "; 51static char display_string[] = " LINUX ON ATLAS ";
51#endif 52#endif
52#if defined(CONFIG_MIPS_MALTA) 53#if defined(CONFIG_MIPS_MALTA)
54#if defined(CONFIG_MIPS_MT_SMTC)
55static char display_string[] = " SMTC LINUX ON MALTA ";
56#else
53static char display_string[] = " LINUX ON MALTA "; 57static char display_string[] = " LINUX ON MALTA ";
58#endif /* CONFIG_MIPS_MT_SMTC */
54#endif 59#endif
55#if defined(CONFIG_MIPS_SEAD) 60#if defined(CONFIG_MIPS_SEAD)
56static char display_string[] = " LINUX ON SEAD "; 61static char display_string[] = " LINUX ON SEAD ";
57#endif 62#endif
58static unsigned int display_count = 0; 63static unsigned int display_count;
59#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) 64#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
60 65
61static unsigned int timer_tick_count=0; 66#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
67
68static unsigned int timer_tick_count;
62static int mips_cpu_timer_irq; 69static int mips_cpu_timer_irq;
70extern void smtc_timer_broadcast(int);
63 71
64static inline void scroll_display_message(void) 72static inline void scroll_display_message(void)
65{ 73{
@@ -75,15 +83,55 @@ static void mips_timer_dispatch (struct pt_regs *regs)
75 do_IRQ (mips_cpu_timer_irq, regs); 83 do_IRQ (mips_cpu_timer_irq, regs);
76} 84}
77 85
86/*
87 * Redeclare until I get around mopping the timer code insanity on MIPS.
88 */
78extern int null_perf_irq(struct pt_regs *regs); 89extern int null_perf_irq(struct pt_regs *regs);
79 90
80extern int (*perf_irq)(struct pt_regs *regs); 91extern int (*perf_irq)(struct pt_regs *regs);
81 92
82irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 93irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
83{ 94{
84 int r2 = cpu_has_mips_r2;
85 int cpu = smp_processor_id(); 95 int cpu = smp_processor_id();
96 int r2 = cpu_has_mips_r2;
97
98#ifdef CONFIG_MIPS_MT_SMTC
99 /*
100 * In an SMTC system, one Count/Compare set exists per VPE.
101 * Which TC within a VPE gets the interrupt is essentially
102 * random - we only know that it shouldn't be one with
103 * IXMT set. Whichever TC gets the interrupt needs to
104 * send special interprocessor interrupts to the other
105 * TCs to make sure that they schedule, etc.
106 *
107 * That code is specific to the SMTC kernel, not to
108 * the a particular platform, so it's invoked from
109 * the general MIPS timer_interrupt routine.
110 */
111
112 /*
113 * DVPE is necessary so long as cross-VPE interrupts
114 * are done via read-modify-write of Cause register.
115 */
116 int vpflags = dvpe();
117 write_c0_compare (read_c0_count() - 1);
118 clear_c0_cause(CPUCTR_IMASKBIT);
119 evpe(vpflags);
120
121 if (cpu_data[cpu].vpe_id == 0) {
122 timer_interrupt(irq, dev_id, regs);
123 scroll_display_message();
124 } else
125 write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
126 smtc_timer_broadcast(cpu_data[cpu].vpe_id);
86 127
128 if (cpu != 0)
129 /*
130 * Other CPUs should do profiling and process accounting
131 */
132 local_timer_interrupt(irq, dev_id, regs);
133
134#else /* CONFIG_MIPS_MT_SMTC */
87 if (cpu == 0) { 135 if (cpu == 0) {
88 /* 136 /*
89 * CPU 0 handles the global timer interrupt job and process 137 * CPU 0 handles the global timer interrupt job and process
@@ -107,12 +155,14 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
107 * More support needs to be added to kernel/time for 155 * More support needs to be added to kernel/time for
108 * counter/timer interrupts on multiple CPU's 156 * counter/timer interrupts on multiple CPU's
109 */ 157 */
110 write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ)); 158 write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
159
111 /* 160 /*
112 * other CPUs should do profiling and process accounting 161 * Other CPUs should do profiling and process accounting
113 */ 162 */
114 local_timer_interrupt (irq, dev_id, regs); 163 local_timer_interrupt(irq, dev_id, regs);
115 } 164 }
165#endif /* CONFIG_MIPS_MT_SMTC */
116 166
117out: 167out:
118 return IRQ_HANDLED; 168 return IRQ_HANDLED;
@@ -126,7 +176,7 @@ static unsigned int __init estimate_cpu_frequency(void)
126 unsigned int prid = read_c0_prid() & 0xffff00; 176 unsigned int prid = read_c0_prid() & 0xffff00;
127 unsigned int count; 177 unsigned int count;
128 178
129#ifdef CONFIG_MIPS_SEAD 179#if defined(CONFIG_MIPS_SEAD) || defined(CONFIG_MIPS_SIM)
130 /* 180 /*
131 * The SEAD board doesn't have a real time clock, so we can't 181 * The SEAD board doesn't have a real time clock, so we can't
132 * really calculate the timer frequency 182 * really calculate the timer frequency
@@ -211,7 +261,11 @@ void __init mips_timer_setup(struct irqaction *irq)
211 261
212 /* we are using the cpu counter for timer interrupts */ 262 /* we are using the cpu counter for timer interrupts */
213 irq->handler = mips_timer_interrupt; /* we use our own handler */ 263 irq->handler = mips_timer_interrupt; /* we use our own handler */
264#ifdef CONFIG_MIPS_MT_SMTC
265 setup_irq_smtc(mips_cpu_timer_irq, irq, CPUCTR_IMASKBIT);
266#else
214 setup_irq(mips_cpu_timer_irq, irq); 267 setup_irq(mips_cpu_timer_irq, irq);
268#endif /* CONFIG_MIPS_MT_SMTC */
215 269
216#ifdef CONFIG_SMP 270#ifdef CONFIG_SMP
217 /* irq_desc(riptor) is a global resource, when the interrupt overlaps 271 /* irq_desc(riptor) is a global resource, when the interrupt overlaps
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index fd4c143c0e2f..77ee5c6d33c1 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -20,3 +20,4 @@
20# 20#
21 21
22obj-y := malta_int.o malta_setup.o 22obj-y := malta_int.o malta_setup.o
23obj-$(CONFIG_SMP) += malta_smp.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index 1da8c18b9c8e..64db07d4dbe5 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -118,8 +118,9 @@ static void malta_hw0_irqdispatch(struct pt_regs *regs)
118 int irq; 118 int irq;
119 119
120 irq = get_int(); 120 irq = get_int();
121 if (irq < 0) 121 if (irq < 0) {
122 return; /* interrupt has already been cleared */ 122 return; /* interrupt has already been cleared */
123 }
123 124
124 do_IRQ(MALTA_INT_BASE+irq, regs); 125 do_IRQ(MALTA_INT_BASE+irq, regs);
125} 126}
@@ -324,9 +325,15 @@ void __init arch_init_irq(void)
324 else if (cpu_has_vint) { 325 else if (cpu_has_vint) {
325 set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); 326 set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
326 set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch); 327 set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch);
327 328#ifdef CONFIG_MIPS_MT_SMTC
329 setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq,
330 (0x100 << MIPSCPU_INT_I8259A));
331 setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI,
332 &corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
333#else /* Not SMTC */
328 setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq); 334 setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
329 setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); 335 setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
336#endif /* CONFIG_MIPS_MT_SMTC */
330 } 337 }
331 else { 338 else {
332 setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq); 339 setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
diff --git a/arch/mips/mips-boards/malta/malta_smp.c b/arch/mips/mips-boards/malta/malta_smp.c
new file mode 100644
index 000000000000..6c6c8eeedbce
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_smp.c
@@ -0,0 +1,128 @@
1/*
2 * Malta Platform-specific hooks for SMP operation
3 */
4
5#include <linux/kernel.h>
6#include <linux/sched.h>
7#include <linux/cpumask.h>
8#include <linux/interrupt.h>
9
10#include <asm/atomic.h>
11#include <asm/cpu.h>
12#include <asm/processor.h>
13#include <asm/system.h>
14#include <asm/hardirq.h>
15#include <asm/mmu_context.h>
16#include <asm/smp.h>
17#ifdef CONFIG_MIPS_MT_SMTC
18#include <asm/smtc_ipi.h>
19#endif /* CONFIG_MIPS_MT_SMTC */
20
21/* VPE/SMP Prototype implements platform interfaces directly */
22#if !defined(CONFIG_MIPS_MT_SMP)
23
24/*
25 * Cause the specified action to be performed on a targeted "CPU"
26 */
27
28void core_send_ipi(int cpu, unsigned int action)
29{
30/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
31#ifdef CONFIG_MIPS_MT_SMTC
32 smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
33#endif /* CONFIG_MIPS_MT_SMTC */
34}
35
36/*
37 * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
38 */
39
40void __init prom_build_cpu_map(void)
41{
42 int nextslot;
43
44 /*
45 * As of November, 2004, MIPSsim only simulates one core
46 * at a time. However, that core may be a MIPS MT core
47 * with multiple virtual processors and thread contexts.
48 */
49
50 if (read_c0_config3() & (1<<2)) {
51 nextslot = mipsmt_build_cpu_map(1);
52 }
53}
54
55/*
56 * Platform "CPU" startup hook
57 */
58
59void prom_boot_secondary(int cpu, struct task_struct *idle)
60{
61#ifdef CONFIG_MIPS_MT_SMTC
62 smtc_boot_secondary(cpu, idle);
63#endif /* CONFIG_MIPS_MT_SMTC */
64}
65
66/*
67 * Post-config but pre-boot cleanup entry point
68 */
69
70void prom_init_secondary(void)
71{
72#ifdef CONFIG_MIPS_MT_SMTC
73 void smtc_init_secondary(void);
74 int myvpe;
75
76 /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
77 myvpe = read_c0_tcbind() & TCBIND_CURVPE;
78 if (myvpe != 0) {
79 /* Ideally, this should be done only once per VPE, but... */
80 clear_c0_status(STATUSF_IP2);
81 set_c0_status(STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP3
82 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6
83 | STATUSF_IP7);
84 }
85
86 smtc_init_secondary();
87#endif /* CONFIG_MIPS_MT_SMTC */
88}
89
90/*
91 * Platform SMP pre-initialization
92 *
93 * As noted above, we can assume a single CPU for now
94 * but it may be multithreaded.
95 */
96
97void plat_smp_setup(void)
98{
99 if (read_c0_config3() & (1<<2))
100 mipsmt_build_cpu_map(0);
101}
102
103void __init plat_prepare_cpus(unsigned int max_cpus)
104{
105 if (read_c0_config3() & (1<<2))
106 mipsmt_prepare_cpus();
107}
108
109/*
110 * SMP initialization finalization entry point
111 */
112
113void prom_smp_finish(void)
114{
115#ifdef CONFIG_MIPS_MT_SMTC
116 smtc_smp_finish();
117#endif /* CONFIG_MIPS_MT_SMTC */
118}
119
120/*
121 * Hook for after all CPUs are online
122 */
123
124void prom_cpus_done(void)
125{
126}
127
128#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mips-boards/sim/cmdline.c b/arch/mips/mips-boards/sim/cmdline.c
deleted file mode 100644
index fef9fbd8e710..000000000000
--- a/arch/mips/mips-boards/sim/cmdline.c
+++ /dev/null
@@ -1,59 +0,0 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Kernel command line creation using the prom monitor (YAMON) argc/argv.
19 */
20#include <linux/init.h>
21#include <linux/string.h>
22
23#include <asm/bootinfo.h>
24
25extern int prom_argc;
26extern int *_prom_argv;
27
28/*
29 * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
30 * This macro take care of sign extension.
31 */
32#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
33
34char arcs_cmdline[CL_SIZE];
35
36char * __init prom_getcmdline(void)
37{
38 return &(arcs_cmdline[0]);
39}
40
41
42void __init prom_init_cmdline(void)
43{
44 char *cp;
45 int actr;
46
47 actr = 1; /* Always ignore argv[0] */
48
49 cp = &(arcs_cmdline[0]);
50 while(actr < prom_argc) {
51 strcpy(cp, prom_argv(actr));
52 cp += strlen(prom_argv(actr));
53 *cp++ = ' ';
54 actr++;
55 }
56 if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
57 --cp;
58 *cp = '\0';
59}
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mips-boards/sim/sim_cmdline.c
index 9df37c6fca36..c63021a5dc6c 100644
--- a/arch/mips/mips-boards/sim/sim_cmdline.c
+++ b/arch/mips/mips-boards/sim/sim_cmdline.c
@@ -26,8 +26,10 @@ char * __init prom_getcmdline(void)
26 return arcs_cmdline; 26 return arcs_cmdline;
27} 27}
28 28
29
30void __init prom_init_cmdline(void) 29void __init prom_init_cmdline(void)
31{ 30{
32 /* nothing to do */ 31 char *cp;
32 cp = arcs_cmdline;
33 /* Get boot line from environment? */
34 *cp = '\0';
33} 35}
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
index a9f0c2bfe4ad..b7084e7c4bf9 100644
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ b/arch/mips/mips-boards/sim/sim_smp.c
@@ -44,8 +44,6 @@
44void core_send_ipi(int cpu, unsigned int action) 44void core_send_ipi(int cpu, unsigned int action)
45{ 45{
46#ifdef CONFIG_MIPS_MT_SMTC 46#ifdef CONFIG_MIPS_MT_SMTC
47 void smtc_send_ipi(int, int, unsigned int);
48
49 smtc_send_ipi(cpu, LINUX_SMP_IPI, action); 47 smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
50#endif /* CONFIG_MIPS_MT_SMTC */ 48#endif /* CONFIG_MIPS_MT_SMTC */
51/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ 49/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
@@ -59,15 +57,8 @@ void core_send_ipi(int cpu, unsigned int action)
59void __init prom_build_cpu_map(void) 57void __init prom_build_cpu_map(void)
60{ 58{
61#ifdef CONFIG_MIPS_MT_SMTC 59#ifdef CONFIG_MIPS_MT_SMTC
62 extern int mipsmt_build_cpu_map(int startslot);
63 int nextslot; 60 int nextslot;
64 61
65 cpus_clear(phys_cpu_present_map);
66
67 /* Register the boot CPU */
68
69 smp_prepare_boot_cpu();
70
71 /* 62 /*
72 * As of November, 2004, MIPSsim only simulates one core 63 * As of November, 2004, MIPSsim only simulates one core
73 * at a time. However, that core may be a MIPS MT core 64 * at a time. However, that core may be a MIPS MT core
@@ -87,8 +78,6 @@ void __init prom_build_cpu_map(void)
87void prom_boot_secondary(int cpu, struct task_struct *idle) 78void prom_boot_secondary(int cpu, struct task_struct *idle)
88{ 79{
89#ifdef CONFIG_MIPS_MT_SMTC 80#ifdef CONFIG_MIPS_MT_SMTC
90 extern void smtc_boot_secondary(int cpu, struct task_struct *t);
91
92 smtc_boot_secondary(cpu, idle); 81 smtc_boot_secondary(cpu, idle);
93#endif /* CONFIG_MIPS_MT_SMTC */ 82#endif /* CONFIG_MIPS_MT_SMTC */
94} 83}
@@ -113,7 +102,6 @@ void prom_init_secondary(void)
113void prom_prepare_cpus(unsigned int max_cpus) 102void prom_prepare_cpus(unsigned int max_cpus)
114{ 103{
115#ifdef CONFIG_MIPS_MT_SMTC 104#ifdef CONFIG_MIPS_MT_SMTC
116 void mipsmt_prepare_cpus(int c);
117 /* 105 /*
118 * As noted above, we can assume a single CPU for now 106 * As noted above, we can assume a single CPU for now
119 * but it may be multithreaded. 107 * but it may be multithreaded.
@@ -132,8 +120,6 @@ void prom_prepare_cpus(unsigned int max_cpus)
132void prom_smp_finish(void) 120void prom_smp_finish(void)
133{ 121{
134#ifdef CONFIG_MIPS_MT_SMTC 122#ifdef CONFIG_MIPS_MT_SMTC
135 void smtc_smp_finish(void);
136
137 smtc_smp_finish(); 123 smtc_smp_finish();
138#endif /* CONFIG_MIPS_MT_SMTC */ 124#endif /* CONFIG_MIPS_MT_SMTC */
139} 125}