cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

smpboot.c (3886B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * SMP initialisation and IPI support
      4 * Based on arch/arm64/kernel/smp.c
      5 *
      6 * Copyright (C) 2012 ARM Ltd.
      7 * Copyright (C) 2015 Regents of the University of California
      8 * Copyright (C) 2017 SiFive
      9 */
     10
     11#include <linux/arch_topology.h>
     12#include <linux/module.h>
     13#include <linux/init.h>
     14#include <linux/kernel.h>
     15#include <linux/mm.h>
     16#include <linux/sched.h>
     17#include <linux/kernel_stat.h>
     18#include <linux/notifier.h>
     19#include <linux/cpu.h>
     20#include <linux/percpu.h>
     21#include <linux/delay.h>
     22#include <linux/err.h>
     23#include <linux/irq.h>
     24#include <linux/of.h>
     25#include <linux/sched/task_stack.h>
     26#include <linux/sched/mm.h>
     27#include <asm/cpu_ops.h>
     28#include <asm/irq.h>
     29#include <asm/mmu_context.h>
     30#include <asm/numa.h>
     31#include <asm/tlbflush.h>
     32#include <asm/sections.h>
     33#include <asm/sbi.h>
     34#include <asm/smp.h>
     35
     36#include "head.h"
     37
     38static DECLARE_COMPLETION(cpu_running);
     39
     40void __init smp_prepare_boot_cpu(void)
     41{
     42	init_cpu_topology();
     43}
     44
     45void __init smp_prepare_cpus(unsigned int max_cpus)
     46{
     47	int cpuid;
     48	int ret;
     49	unsigned int curr_cpuid;
     50
     51	curr_cpuid = smp_processor_id();
     52	numa_store_cpu_info(curr_cpuid);
     53	numa_add_cpu(curr_cpuid);
     54
     55	/* This covers non-smp usecase mandated by "nosmp" option */
     56	if (max_cpus == 0)
     57		return;
     58
     59	for_each_possible_cpu(cpuid) {
     60		if (cpuid == curr_cpuid)
     61			continue;
     62		if (cpu_ops[cpuid]->cpu_prepare) {
     63			ret = cpu_ops[cpuid]->cpu_prepare(cpuid);
     64			if (ret)
     65				continue;
     66		}
     67		set_cpu_present(cpuid, true);
     68		numa_store_cpu_info(cpuid);
     69	}
     70}
     71
     72void __init setup_smp(void)
     73{
     74	struct device_node *dn;
     75	int hart;
     76	bool found_boot_cpu = false;
     77	int cpuid = 1;
     78
     79	cpu_set_ops(0);
     80
     81	for_each_of_cpu_node(dn) {
     82		hart = riscv_of_processor_hartid(dn);
     83		if (hart < 0)
     84			continue;
     85
     86		if (hart == cpuid_to_hartid_map(0)) {
     87			BUG_ON(found_boot_cpu);
     88			found_boot_cpu = 1;
     89			early_map_cpu_to_node(0, of_node_to_nid(dn));
     90			continue;
     91		}
     92		if (cpuid >= NR_CPUS) {
     93			pr_warn("Invalid cpuid [%d] for hartid [%d]\n",
     94				cpuid, hart);
     95			continue;
     96		}
     97
     98		cpuid_to_hartid_map(cpuid) = hart;
     99		early_map_cpu_to_node(cpuid, of_node_to_nid(dn));
    100		cpuid++;
    101	}
    102
    103	BUG_ON(!found_boot_cpu);
    104
    105	if (cpuid > nr_cpu_ids)
    106		pr_warn("Total number of cpus [%d] is greater than nr_cpus option value [%d]\n",
    107			cpuid, nr_cpu_ids);
    108
    109	for (cpuid = 1; cpuid < nr_cpu_ids; cpuid++) {
    110		if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID) {
    111			cpu_set_ops(cpuid);
    112			set_cpu_possible(cpuid, true);
    113		}
    114	}
    115}
    116
    117static int start_secondary_cpu(int cpu, struct task_struct *tidle)
    118{
    119	if (cpu_ops[cpu]->cpu_start)
    120		return cpu_ops[cpu]->cpu_start(cpu, tidle);
    121
    122	return -EOPNOTSUPP;
    123}
    124
    125int __cpu_up(unsigned int cpu, struct task_struct *tidle)
    126{
    127	int ret = 0;
    128	tidle->thread_info.cpu = cpu;
    129
    130	ret = start_secondary_cpu(cpu, tidle);
    131	if (!ret) {
    132		wait_for_completion_timeout(&cpu_running,
    133					    msecs_to_jiffies(1000));
    134
    135		if (!cpu_online(cpu)) {
    136			pr_crit("CPU%u: failed to come online\n", cpu);
    137			ret = -EIO;
    138		}
    139	} else {
    140		pr_crit("CPU%u: failed to start\n", cpu);
    141	}
    142
    143	return ret;
    144}
    145
    146void __init smp_cpus_done(unsigned int max_cpus)
    147{
    148}
    149
    150/*
    151 * C entry point for a secondary processor.
    152 */
    153asmlinkage __visible void smp_callin(void)
    154{
    155	struct mm_struct *mm = &init_mm;
    156	unsigned int curr_cpuid = smp_processor_id();
    157
    158	riscv_clear_ipi();
    159
    160	/* All kernel threads share the same mm context.  */
    161	mmgrab(mm);
    162	current->active_mm = mm;
    163
    164	notify_cpu_starting(curr_cpuid);
    165	numa_add_cpu(curr_cpuid);
    166	update_siblings_masks(curr_cpuid);
    167	set_cpu_online(curr_cpuid, 1);
    168
    169	/*
    170	 * Remote TLB flushes are ignored while the CPU is offline, so emit
    171	 * a local TLB flush right now just in case.
    172	 */
    173	local_flush_tlb_all();
    174	complete(&cpu_running);
    175	/*
    176	 * Disable preemption before enabling interrupts, so we don't try to
    177	 * schedule a CPU that hasn't actually started yet.
    178	 */
    179	local_irq_enable();
    180	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
    181}