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

ip30-smp.c (3543B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * ip30-smp.c: SMP on IP30 architecture.
      4 * Based off of the original IP30 SMP code, with inspiration from ip27-smp.c
      5 * and smp-bmips.c.
      6 *
      7 * Copyright (C) 2005-2007 Stanislaw Skowronek <skylark@unaligned.org>
      8 *               2006-2007, 2014-2015 Joshua Kinard <kumba@gentoo.org>
      9 *               2009 Johannes Dickgreber <tanzy@gmx.de>
     10 */
     11
     12#include <linux/init.h>
     13#include <linux/sched.h>
     14#include <linux/sched/task_stack.h>
     15
     16#include <asm/time.h>
     17#include <asm/sgi/heart.h>
     18
     19#include "ip30-common.h"
     20
     21#define MPCONF_MAGIC	0xbaddeed2
     22#define	MPCONF_ADDR	0xa800000000000600L
     23#define MPCONF_SIZE	0x80
     24#define MPCONF(x)	(MPCONF_ADDR + (x) * MPCONF_SIZE)
     25
     26/* HEART can theoretically do 4 CPUs, but only 2 are physically possible */
     27#define MP_NCPU		2
     28
     29struct mpconf {
     30	u32 magic;
     31	u32 prid;
     32	u32 physid;
     33	u32 virtid;
     34	u32 scachesz;
     35	u16 fanloads;
     36	u16 res;
     37	void *launch;
     38	void *rendezvous;
     39	u64 res2[3];
     40	void *stackaddr;
     41	void *lnch_parm;
     42	void *rndv_parm;
     43	u32 idleflag;
     44};
     45
     46static void ip30_smp_send_ipi_single(int cpu, u32 action)
     47{
     48	int irq;
     49
     50	switch (action) {
     51	case SMP_RESCHEDULE_YOURSELF:
     52		irq = HEART_L2_INT_RESCHED_CPU_0;
     53		break;
     54	case SMP_CALL_FUNCTION:
     55		irq = HEART_L2_INT_CALL_CPU_0;
     56		break;
     57	default:
     58		panic("IP30: Unknown action value in %s!\n", __func__);
     59	}
     60
     61	irq += cpu;
     62
     63	/* Poke the other CPU -- it's got mail! */
     64	heart_write(BIT_ULL(irq), &heart_regs->set_isr);
     65}
     66
     67static void ip30_smp_send_ipi_mask(const struct cpumask *mask, u32 action)
     68{
     69	u32 i;
     70
     71	for_each_cpu(i, mask)
     72		ip30_smp_send_ipi_single(i, action);
     73}
     74
     75static void __init ip30_smp_setup(void)
     76{
     77	int i;
     78	int ncpu = 0;
     79	struct mpconf *mpc;
     80
     81	init_cpu_possible(cpumask_of(0));
     82
     83	/* Scan the MPCONF structure and enumerate available CPUs. */
     84	for (i = 0; i < MP_NCPU; i++) {
     85		mpc = (struct mpconf *)MPCONF(i);
     86		if (mpc->magic == MPCONF_MAGIC) {
     87			set_cpu_possible(i, true);
     88			__cpu_number_map[i] = ++ncpu;
     89			__cpu_logical_map[ncpu] = i;
     90			pr_info("IP30: Slot: %d, PrID: %.8x, PhyID: %d, VirtID: %d\n",
     91				i, mpc->prid, mpc->physid, mpc->virtid);
     92		}
     93	}
     94	pr_info("IP30: Detected %d CPU(s) present.\n", ncpu);
     95
     96	/*
     97	 * Set the coherency algorithm to '5' (cacheable coherent
     98	 * exclusive on write).  This is needed on IP30 SMP, especially
     99	 * for R14000 CPUs, otherwise, instruction bus errors will
    100	 * occur upon reaching userland.
    101	 */
    102	change_c0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_COW);
    103}
    104
    105static void __init ip30_smp_prepare_cpus(unsigned int max_cpus)
    106{
    107	/* nothing to do here */
    108}
    109
    110static int __init ip30_smp_boot_secondary(int cpu, struct task_struct *idle)
    111{
    112	struct mpconf *mpc = (struct mpconf *)MPCONF(cpu);
    113
    114	/* Stack pointer (sp). */
    115	mpc->stackaddr = (void *)__KSTK_TOS(idle);
    116
    117	/* Global pointer (gp). */
    118	mpc->lnch_parm = task_thread_info(idle);
    119
    120	mb(); /* make sure stack and lparm are written */
    121
    122	/* Boot CPUx. */
    123	mpc->launch = smp_bootstrap;
    124
    125	/* CPUx now executes smp_bootstrap, then ip30_smp_finish */
    126	return 0;
    127}
    128
    129static void __init ip30_smp_init_cpu(void)
    130{
    131	ip30_per_cpu_init();
    132}
    133
    134static void __init ip30_smp_finish(void)
    135{
    136	enable_percpu_irq(get_c0_compare_int(), IRQ_TYPE_NONE);
    137	local_irq_enable();
    138}
    139
    140struct plat_smp_ops __read_mostly ip30_smp_ops = {
    141	.send_ipi_single	= ip30_smp_send_ipi_single,
    142	.send_ipi_mask		= ip30_smp_send_ipi_mask,
    143	.smp_setup		= ip30_smp_setup,
    144	.prepare_cpus		= ip30_smp_prepare_cpus,
    145	.boot_secondary		= ip30_smp_boot_secondary,
    146	.init_secondary		= ip30_smp_init_cpu,
    147	.smp_finish		= ip30_smp_finish,
    148	.prepare_boot_cpu	= ip30_smp_init_cpu,
    149};