2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2013 Cavium, Inc.
9 #include <linux/interrupt.h>
10 #include <linux/cpumask.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/sched/task_stack.h>
15 #include <asm/mipsregs.h>
16 #include <asm/setup.h>
21 * Writing the sp releases the CPU, so writes must be ordered, gp
24 unsigned long paravirt_smp_sp
[NR_CPUS
];
25 unsigned long paravirt_smp_gp
[NR_CPUS
];
27 static int numcpus
= 1;
29 static int __init
set_numcpus(char *str
)
33 if (get_option(&str
, &newval
)) {
34 if (newval
< 1 || newval
>= NR_CPUS
)
42 early_param("numcpus", set_numcpus
);
45 static void paravirt_smp_setup(void)
48 unsigned int cpunum
= get_ebase_cpunum();
50 if (WARN_ON(cpunum
>= NR_CPUS
))
53 /* The present CPUs are initially just the boot cpu (CPU 0). */
54 for (id
= 0; id
< NR_CPUS
; id
++) {
55 set_cpu_possible(id
, id
== 0);
56 set_cpu_present(id
, id
== 0);
58 __cpu_number_map
[cpunum
] = 0;
59 __cpu_logical_map
[0] = cpunum
;
61 for (id
= 0; id
< numcpus
; id
++) {
62 set_cpu_possible(id
, true);
63 set_cpu_present(id
, true);
64 __cpu_number_map
[id
] = id
;
65 __cpu_logical_map
[id
] = id
;
69 void irq_mbox_ipi(int cpu
, unsigned int actions
);
70 static void paravirt_send_ipi_single(int cpu
, unsigned int action
)
72 irq_mbox_ipi(cpu
, action
);
75 static void paravirt_send_ipi_mask(const struct cpumask
*mask
, unsigned int action
)
79 for_each_cpu(cpu
, mask
)
80 paravirt_send_ipi_single(cpu
, action
);
83 static void paravirt_init_secondary(void)
87 sr
= set_c0_status(ST0_BEV
);
88 write_c0_ebase((u32
)ebase
);
90 sr
|= STATUSF_IP2
; /* Interrupt controller on IP2 */
96 static void paravirt_smp_finish(void)
98 /* to generate the first CPU timer interrupt */
99 write_c0_compare(read_c0_count() + mips_hpt_frequency
/ HZ
);
103 static int paravirt_boot_secondary(int cpu
, struct task_struct
*idle
)
105 paravirt_smp_gp
[cpu
] = (unsigned long)task_thread_info(idle
);
107 paravirt_smp_sp
[cpu
] = __KSTK_TOS(idle
);
111 static irqreturn_t
paravirt_reched_interrupt(int irq
, void *dev_id
)
117 static irqreturn_t
paravirt_function_interrupt(int irq
, void *dev_id
)
119 generic_smp_call_function_interrupt();
123 static void paravirt_prepare_cpus(unsigned int max_cpus
)
125 if (request_irq(MIPS_IRQ_MBOX0
, paravirt_reched_interrupt
,
126 IRQF_PERCPU
| IRQF_NO_THREAD
, "Scheduler",
127 paravirt_reched_interrupt
)) {
128 panic("Cannot request_irq for SchedulerIPI");
130 if (request_irq(MIPS_IRQ_MBOX1
, paravirt_function_interrupt
,
131 IRQF_PERCPU
| IRQF_NO_THREAD
, "SMP-Call",
132 paravirt_function_interrupt
)) {
133 panic("Cannot request_irq for SMP-Call");
137 const struct plat_smp_ops paravirt_smp_ops
= {
138 .send_ipi_single
= paravirt_send_ipi_single
,
139 .send_ipi_mask
= paravirt_send_ipi_mask
,
140 .init_secondary
= paravirt_init_secondary
,
141 .smp_finish
= paravirt_smp_finish
,
142 .boot_secondary
= paravirt_boot_secondary
,
143 .smp_setup
= paravirt_smp_setup
,
144 .prepare_cpus
= paravirt_prepare_cpus
,