1
0
Fork 0
alistair23-linux/arch/mips/paravirt/paravirt-smp.c

146 lines
3.3 KiB
C
Raw Normal View History

/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2013 Cavium, Inc.
*/
#include <linux/interrupt.h>
#include <linux/cpumask.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <asm/mipsregs.h>
#include <asm/setup.h>
#include <asm/time.h>
#include <asm/smp.h>
/*
* Writing the sp releases the CPU, so writes must be ordered, gp
* first, then sp.
*/
unsigned long paravirt_smp_sp[NR_CPUS];
unsigned long paravirt_smp_gp[NR_CPUS];
static int numcpus = 1;
static int __init set_numcpus(char *str)
{
int newval;
if (get_option(&str, &newval)) {
if (newval < 1 || newval >= NR_CPUS)
goto bad;
numcpus = newval;
return 0;
}
bad:
return -EINVAL;
}
early_param("numcpus", set_numcpus);
static void paravirt_smp_setup(void)
{
int id;
unsigned int cpunum = get_ebase_cpunum();
if (WARN_ON(cpunum >= NR_CPUS))
return;
/* The present CPUs are initially just the boot cpu (CPU 0). */
for (id = 0; id < NR_CPUS; id++) {
set_cpu_possible(id, id == 0);
set_cpu_present(id, id == 0);
}
__cpu_number_map[cpunum] = 0;
__cpu_logical_map[0] = cpunum;
for (id = 0; id < numcpus; id++) {
set_cpu_possible(id, true);
set_cpu_present(id, true);
__cpu_number_map[id] = id;
__cpu_logical_map[id] = id;
}
}
void irq_mbox_ipi(int cpu, unsigned int actions);
static void paravirt_send_ipi_single(int cpu, unsigned int action)
{
irq_mbox_ipi(cpu, action);
}
static void paravirt_send_ipi_mask(const struct cpumask *mask, unsigned int action)
{
unsigned int cpu;
for_each_cpu(cpu, mask)
paravirt_send_ipi_single(cpu, action);
}
static void paravirt_init_secondary(void)
{
unsigned int sr;
sr = set_c0_status(ST0_BEV);
write_c0_ebase((u32)ebase);
sr |= STATUSF_IP2; /* Interrupt controller on IP2 */
write_c0_status(sr);
irq_cpu_online();
}
static void paravirt_smp_finish(void)
{
/* to generate the first CPU timer interrupt */
write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
local_irq_enable();
}
static int paravirt_boot_secondary(int cpu, struct task_struct *idle)
{
paravirt_smp_gp[cpu] = (unsigned long)task_thread_info(idle);
smp_wmb();
paravirt_smp_sp[cpu] = __KSTK_TOS(idle);
return 0;
}
static irqreturn_t paravirt_reched_interrupt(int irq, void *dev_id)
{
scheduler_ipi();
return IRQ_HANDLED;
}
static irqreturn_t paravirt_function_interrupt(int irq, void *dev_id)
{
generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
static void paravirt_prepare_cpus(unsigned int max_cpus)
{
if (request_irq(MIPS_IRQ_MBOX0, paravirt_reched_interrupt,
IRQF_PERCPU | IRQF_NO_THREAD, "Scheduler",
paravirt_reched_interrupt)) {
panic("Cannot request_irq for SchedulerIPI");
}
if (request_irq(MIPS_IRQ_MBOX1, paravirt_function_interrupt,
IRQF_PERCPU | IRQF_NO_THREAD, "SMP-Call",
paravirt_function_interrupt)) {
panic("Cannot request_irq for SMP-Call");
}
}
MIPS: SMP: Constify smp ops smp_ops providers do not modify their ops structures, so they should be made const for robustness. Since currently the MIPS kernel is not mapped with memory protection, this does not in itself provide any security benefit, but it still makes sense to make this change. There are also slight code size efficincies from the structure being made read-only, saving 128 bytes of kernel text on a pistachio_defconfig. Before: text data bss dec hex filename 7187239 1772752 470224 9430215 8fe4c7 vmlinux After: text data bss dec hex filename 7187111 1772752 470224 9430087 8fe447 vmlinux Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Marcin Nowakowski <marcin.nowakowski@imgtec.com> Cc: Bart Van Assche <bart.vanassche@sandisk.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com> Cc: Huacai Chen <chenhc@lemote.com> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: Kevin Cernekee <cernekee@gmail.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Doug Ledford <dledford@redhat.com> Cc: James Hogan <james.hogan@imgtec.com> Cc: Joe Perches <joe@perches.com> Cc: Florian Fainelli <f.fainelli@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Steven J. Hill <steven.hill@cavium.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/16784/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2017-07-19 02:21:03 -06:00
const struct plat_smp_ops paravirt_smp_ops = {
.send_ipi_single = paravirt_send_ipi_single,
.send_ipi_mask = paravirt_send_ipi_mask,
.init_secondary = paravirt_init_secondary,
.smp_finish = paravirt_smp_finish,
.boot_secondary = paravirt_boot_secondary,
.smp_setup = paravirt_smp_setup,
.prepare_cpus = paravirt_prepare_cpus,
};