Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
mips
kernel
smp-cmp.c
Go to the documentation of this file.
1
/*
2
* This program is free software; you can distribute it and/or modify it
3
* under the terms of the GNU General Public License (Version 2) as
4
* published by the Free Software Foundation.
5
*
6
* This program is distributed in the hope it will be useful, but WITHOUT
7
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9
* for more details.
10
*
11
* You should have received a copy of the GNU General Public License along
12
* with this program; if not, write to the Free Software Foundation, Inc.,
13
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
14
*
15
* Copyright (C) 2007 MIPS Technologies, Inc.
16
* Chris Dearman (
[email protected]
)
17
*/
18
19
#undef DEBUG
20
21
#include <linux/kernel.h>
22
#include <linux/sched.h>
23
#include <
linux/smp.h
>
24
#include <
linux/cpumask.h
>
25
#include <
linux/interrupt.h
>
26
#include <linux/compiler.h>
27
28
#include <
linux/atomic.h
>
29
#include <asm/cacheflush.h>
30
#include <asm/cpu.h>
31
#include <asm/processor.h>
32
#include <asm/hardirq.h>
33
#include <asm/mmu_context.h>
34
#include <asm/smp.h>
35
#include <asm/time.h>
36
#include <
asm/mipsregs.h
>
37
#include <
asm/mipsmtregs.h
>
38
#include <
asm/mips_mt.h
>
39
#include <
asm/amon.h
>
40
#include <
asm/gic.h
>
41
42
static
void
ipi_call_function(
unsigned
int
cpu
)
43
{
44
pr_debug
(
"CPU%d: %s cpu %d status %08x\n"
,
45
smp_processor_id
(), __func__, cpu,
read_c0_status
());
46
47
gic_send_ipi
(
plat_ipi_call_int_xlate
(cpu));
48
}
49
50
51
static
void
ipi_resched(
unsigned
int
cpu)
52
{
53
pr_debug
(
"CPU%d: %s cpu %d status %08x\n"
,
54
smp_processor_id
(), __func__, cpu,
read_c0_status
());
55
56
gic_send_ipi
(
plat_ipi_resched_int_xlate
(cpu));
57
}
58
59
/*
60
* FIXME: This isn't restricted to CMP
61
* The SMVP kernel could use GIC interrupts if available
62
*/
63
void
cmp_send_ipi_single
(
int
cpu,
unsigned
int
action
)
64
{
65
unsigned
long
flags
;
66
67
local_irq_save
(flags);
68
69
switch
(action) {
70
case
SMP_CALL_FUNCTION
:
71
ipi_call_function(cpu);
72
break
;
73
74
case
SMP_RESCHEDULE_YOURSELF
:
75
ipi_resched(cpu);
76
break
;
77
}
78
79
local_irq_restore
(flags);
80
}
81
82
static
void
cmp_send_ipi_mask(
const
struct
cpumask
*
mask
,
unsigned
int
action
)
83
{
84
unsigned
int
i
;
85
86
for_each_cpu
(i, mask)
87
cmp_send_ipi_single
(i, action);
88
}
89
90
static
void
cmp_init_secondary
(
void
)
91
{
92
struct
cpuinfo_mips
*
c
= &
current_cpu_data
;
93
94
/* Assume GIC is present */
95
change_c0_status(
ST0_IM
,
STATUSF_IP3
|
STATUSF_IP4
|
STATUSF_IP6
|
96
STATUSF_IP7
);
97
98
/* Enable per-cpu interrupts: platform specific */
99
100
c->
core
= (
read_c0_ebase
() >> 1) & 0x1ff;
101
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
102
c->vpe_id = (
read_c0_tcbind
() >>
TCBIND_CURVPE_SHIFT
) &
TCBIND_CURVPE
;
103
#endif
104
#ifdef CONFIG_MIPS_MT_SMTC
105
c->tc_id = (
read_c0_tcbind
() &
TCBIND_CURTC
) >>
TCBIND_CURTC_SHIFT
;
106
#endif
107
}
108
109
static
void
cmp_smp_finish
(
void
)
110
{
111
pr_debug
(
"SMPCMP: CPU%d: %s\n"
,
smp_processor_id
(), __func__);
112
113
/* CDFIXME: remove this? */
114
write_c0_compare
(
read_c0_count
() + (8 *
mips_hpt_frequency
/
HZ
));
115
116
#ifdef CONFIG_MIPS_MT_FPAFF
117
/* If we have an FPU, enroll ourselves in the FPU-full mask */
118
if
(
cpu_has_fpu
)
119
cpu_set
(
smp_processor_id
(),
mt_fpu_cpumask
);
120
#endif
/* CONFIG_MIPS_MT_FPAFF */
121
122
local_irq_enable
();
123
}
124
125
static
void
cmp_cpus_done
(
void
)
126
{
127
pr_debug
(
"SMPCMP: CPU%d: %s\n"
,
smp_processor_id
(), __func__);
128
}
129
130
/*
131
* Setup the PC, SP, and GP of a secondary processor and start it running
132
* smp_bootstrap is the place to resume from
133
* __KSTK_TOS(idle) is apparently the stack pointer
134
* (unsigned long)idle->thread_info the gp
135
*/
136
static
void
cmp_boot_secondary
(
int
cpu,
struct
task_struct
*
idle
)
137
{
138
struct
thread_info
*
gp
=
task_thread_info
(idle);
139
unsigned
long
sp
=
__KSTK_TOS
(idle);
140
unsigned
long
pc
= (
unsigned
long
)&
smp_bootstrap
;
141
unsigned
long
a0
= 0;
142
143
pr_debug
(
"SMPCMP: CPU%d: %s cpu %d\n"
,
smp_processor_id
(),
144
__func__, cpu);
145
146
#if 0
147
/* Needed? */
148
flush_icache_range
((
unsigned
long
)gp,
149
(
unsigned
long
)(gp +
sizeof
(
struct
thread_info
)));
150
#endif
151
152
amon_cpu_start
(cpu, pc, sp, (
unsigned
long
)gp, a0);
153
}
154
155
/*
156
* Common setup before any secondaries are started
157
*/
158
void
__init
cmp_smp_setup
(
void
)
159
{
160
int
i
;
161
int
ncpu = 0;
162
163
pr_debug
(
"SMPCMP: CPU%d: %s\n"
,
smp_processor_id
(), __func__);
164
165
#ifdef CONFIG_MIPS_MT_FPAFF
166
/* If we have an FPU, enroll ourselves in the FPU-full mask */
167
if
(
cpu_has_fpu
)
168
cpu_set
(0,
mt_fpu_cpumask
);
169
#endif
/* CONFIG_MIPS_MT_FPAFF */
170
171
for
(i = 1; i <
NR_CPUS
; i++) {
172
if
(
amon_cpu_avail
(i)) {
173
set_cpu_possible
(i,
true
);
174
__cpu_number_map
[
i
] = ++ncpu;
175
__cpu_logical_map
[ncpu] =
i
;
176
}
177
}
178
179
if
(
cpu_has_mipsmt
) {
180
unsigned
int
nvpe, mvpconf0 =
read_c0_mvpconf0
();
181
182
nvpe = ((mvpconf0 &
MVPCONF0_PTC
) >>
MVPCONF0_PTC_SHIFT
) + 1;
183
smp_num_siblings
= nvpe;
184
}
185
pr_info
(
"Detected %i available secondary CPU(s)\n"
, ncpu);
186
}
187
188
void
__init
cmp_prepare_cpus
(
unsigned
int
max_cpus)
189
{
190
pr_debug
(
"SMPCMP: CPU%d: %s max_cpus=%d\n"
,
191
smp_processor_id
(), __func__, max_cpus);
192
193
/*
194
* FIXME: some of these options are per-system, some per-core and
195
* some per-cpu
196
*/
197
mips_mt_set_cpuoptions
();
198
}
199
200
struct
plat_smp_ops
cmp_smp_ops
= {
201
.send_ipi_single =
cmp_send_ipi_single
,
202
.send_ipi_mask = cmp_send_ipi_mask,
203
.init_secondary =
cmp_init_secondary
,
204
.smp_finish =
cmp_smp_finish
,
205
.cpus_done =
cmp_cpus_done
,
206
.boot_secondary =
cmp_boot_secondary
,
207
.smp_setup =
cmp_smp_setup
,
208
.prepare_cpus =
cmp_prepare_cpus
,
209
};
Generated on Thu Jan 10 2013 13:11:24 for Linux Kernel by
1.8.2