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

platsmp.c (8722B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2014-2015 Broadcom Corporation
      4 * Copyright 2014 Linaro Limited
      5 */
      6
      7#include <linux/cpumask.h>
      8#include <linux/delay.h>
      9#include <linux/errno.h>
     10#include <linux/init.h>
     11#include <linux/io.h>
     12#include <linux/irqchip/irq-bcm2836.h>
     13#include <linux/jiffies.h>
     14#include <linux/of.h>
     15#include <linux/of_address.h>
     16#include <linux/sched.h>
     17#include <linux/sched/clock.h>
     18#include <linux/smp.h>
     19
     20#include <asm/cacheflush.h>
     21#include <asm/smp.h>
     22#include <asm/smp_plat.h>
     23#include <asm/smp_scu.h>
     24
     25#include "platsmp.h"
     26
     27/* Size of mapped Cortex A9 SCU address space */
     28#define CORTEX_A9_SCU_SIZE	0x58
     29
     30#define SECONDARY_TIMEOUT_NS	NSEC_PER_MSEC	/* 1 msec (in nanoseconds) */
     31#define BOOT_ADDR_CPUID_MASK	0x3
     32
     33/* Name of device node property defining secondary boot register location */
     34#define OF_SECONDARY_BOOT	"secondary-boot-reg"
     35#define MPIDR_CPUID_BITMASK	0x3
     36
     37/*
     38 * Enable the Cortex A9 Snoop Control Unit
     39 *
     40 * By the time this is called we already know there are multiple
     41 * cores present.  We assume we're running on a Cortex A9 processor,
     42 * so any trouble getting the base address register or getting the
     43 * SCU base is a problem.
     44 *
     45 * Return 0 if successful or an error code otherwise.
     46 */
     47static int __init scu_a9_enable(void)
     48{
     49	unsigned long config_base;
     50	void __iomem *scu_base;
     51
     52	if (!scu_a9_has_base()) {
     53		pr_err("no configuration base address register!\n");
     54		return -ENXIO;
     55	}
     56
     57	/* Config base address register value is zero for uniprocessor */
     58	config_base = scu_a9_get_base();
     59	if (!config_base) {
     60		pr_err("hardware reports only one core\n");
     61		return -ENOENT;
     62	}
     63
     64	scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
     65	if (!scu_base) {
     66		pr_err("failed to remap config base (%lu/%u) for SCU\n",
     67			config_base, CORTEX_A9_SCU_SIZE);
     68		return -ENOMEM;
     69	}
     70
     71	scu_enable(scu_base);
     72
     73	iounmap(scu_base);	/* That's the last we'll need of this */
     74
     75	return 0;
     76}
     77
     78static u32 secondary_boot_addr_for(unsigned int cpu)
     79{
     80	u32 secondary_boot_addr = 0;
     81	struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
     82
     83        if (!cpu_node) {
     84		pr_err("Failed to find device tree node for CPU%u\n", cpu);
     85		return 0;
     86	}
     87
     88	if (of_property_read_u32(cpu_node,
     89				 OF_SECONDARY_BOOT,
     90				 &secondary_boot_addr))
     91		pr_err("required secondary boot register not specified for CPU%u\n",
     92			cpu);
     93
     94	of_node_put(cpu_node);
     95
     96	return secondary_boot_addr;
     97}
     98
     99static int nsp_write_lut(unsigned int cpu)
    100{
    101	void __iomem *sku_rom_lut;
    102	phys_addr_t secondary_startup_phy;
    103	const u32 secondary_boot_addr = secondary_boot_addr_for(cpu);
    104
    105	if (!secondary_boot_addr)
    106		return -EINVAL;
    107
    108	sku_rom_lut = ioremap((phys_addr_t)secondary_boot_addr,
    109				      sizeof(phys_addr_t));
    110	if (!sku_rom_lut) {
    111		pr_warn("unable to ioremap SKU-ROM LUT register for cpu %u\n", cpu);
    112		return -ENOMEM;
    113	}
    114
    115	secondary_startup_phy = __pa_symbol(secondary_startup);
    116	BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX);
    117
    118	writel_relaxed(secondary_startup_phy, sku_rom_lut);
    119
    120	/* Ensure the write is visible to the secondary core */
    121	smp_wmb();
    122
    123	iounmap(sku_rom_lut);
    124
    125	return 0;
    126}
    127
    128static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
    129{
    130	const cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
    131
    132	/* Enable the SCU on Cortex A9 based SoCs */
    133	if (scu_a9_enable()) {
    134		/* Update the CPU present map to reflect uniprocessor mode */
    135		pr_warn("failed to enable A9 SCU - disabling SMP\n");
    136		init_cpu_present(&only_cpu_0);
    137	}
    138}
    139
    140/*
    141 * The ROM code has the secondary cores looping, waiting for an event.
    142 * When an event occurs each core examines the bottom two bits of the
    143 * secondary boot register.  When a core finds those bits contain its
    144 * own core id, it performs initialization, including computing its boot
    145 * address by clearing the boot register value's bottom two bits.  The
    146 * core signals that it is beginning its execution by writing its boot
    147 * address back to the secondary boot register, and finally jumps to
    148 * that address.
    149 *
    150 * So to start a core executing we need to:
    151 * - Encode the (hardware) CPU id with the bottom bits of the secondary
    152 *   start address.
    153 * - Write that value into the secondary boot register.
    154 * - Generate an event to wake up the secondary CPU(s).
    155 * - Wait for the secondary boot register to be re-written, which
    156 *   indicates the secondary core has started.
    157 */
    158static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
    159{
    160	void __iomem *boot_reg;
    161	phys_addr_t boot_func;
    162	u64 start_clock;
    163	u32 cpu_id;
    164	u32 boot_val;
    165	bool timeout = false;
    166	const u32 secondary_boot_addr = secondary_boot_addr_for(cpu);
    167
    168	cpu_id = cpu_logical_map(cpu);
    169	if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
    170		pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK);
    171		return -EINVAL;
    172	}
    173
    174	if (!secondary_boot_addr)
    175		return -EINVAL;
    176
    177	boot_reg = ioremap((phys_addr_t)secondary_boot_addr,
    178				   sizeof(phys_addr_t));
    179	if (!boot_reg) {
    180		pr_err("unable to map boot register for cpu %u\n", cpu_id);
    181		return -ENOMEM;
    182	}
    183
    184	/*
    185	 * Secondary cores will start in secondary_startup(),
    186	 * defined in "arch/arm/kernel/head.S"
    187	 */
    188	boot_func = __pa_symbol(secondary_startup);
    189	BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK);
    190	BUG_ON(boot_func > (phys_addr_t)U32_MAX);
    191
    192	/* The core to start is encoded in the low bits */
    193	boot_val = (u32)boot_func | cpu_id;
    194	writel_relaxed(boot_val, boot_reg);
    195
    196	sev();
    197
    198	/* The low bits will be cleared once the core has started */
    199	start_clock = local_clock();
    200	while (!timeout && readl_relaxed(boot_reg) == boot_val)
    201		timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS;
    202
    203	iounmap(boot_reg);
    204
    205	if (!timeout)
    206		return 0;
    207
    208	pr_err("timeout waiting for cpu %u to start\n", cpu_id);
    209
    210	return -ENXIO;
    211}
    212
    213/* Cluster Dormant Control command to bring CPU into a running state */
    214#define CDC_CMD			6
    215#define CDC_CMD_OFFSET		0
    216#define CDC_CMD_REG(cpu)	(CDC_CMD_OFFSET + 4*(cpu))
    217
    218/*
    219 * BCM23550 has a Cluster Dormant Control block that keeps the core in
    220 * idle state. A command needs to be sent to the block to bring the CPU
    221 * into running state.
    222 */
    223static int bcm23550_boot_secondary(unsigned int cpu, struct task_struct *idle)
    224{
    225	void __iomem *cdc_base;
    226	struct device_node *dn;
    227	char *name;
    228	int ret;
    229
    230	/* Make sure a CDC node exists before booting the
    231	 * secondary core.
    232	 */
    233	name = "brcm,bcm23550-cdc";
    234	dn = of_find_compatible_node(NULL, NULL, name);
    235	if (!dn) {
    236		pr_err("unable to find cdc node\n");
    237		return -ENODEV;
    238	}
    239
    240	cdc_base = of_iomap(dn, 0);
    241	of_node_put(dn);
    242
    243	if (!cdc_base) {
    244		pr_err("unable to remap cdc base register\n");
    245		return -ENOMEM;
    246	}
    247
    248	/* Boot the secondary core */
    249	ret = kona_boot_secondary(cpu, idle);
    250	if (ret)
    251		goto out;
    252
    253	/* Bring this CPU to RUN state so that nIRQ nFIQ
    254	 * signals are unblocked.
    255	 */
    256	writel_relaxed(CDC_CMD, cdc_base + CDC_CMD_REG(cpu));
    257
    258out:
    259	iounmap(cdc_base);
    260
    261	return ret;
    262}
    263
    264static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
    265{
    266	int ret;
    267
    268	/*
    269	 * After wake up, secondary core branches to the startup
    270	 * address programmed at SKU ROM LUT location.
    271	 */
    272	ret = nsp_write_lut(cpu);
    273	if (ret) {
    274		pr_err("unable to write startup addr to SKU ROM LUT\n");
    275		goto out;
    276	}
    277
    278	/* Send a CPU wakeup interrupt to the secondary core */
    279	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
    280
    281out:
    282	return ret;
    283}
    284
    285static int bcm2836_boot_secondary(unsigned int cpu, struct task_struct *idle)
    286{
    287	void __iomem *intc_base;
    288	struct device_node *dn;
    289	char *name;
    290
    291	name = "brcm,bcm2836-l1-intc";
    292	dn = of_find_compatible_node(NULL, NULL, name);
    293	if (!dn) {
    294		pr_err("unable to find intc node\n");
    295		return -ENODEV;
    296	}
    297
    298	intc_base = of_iomap(dn, 0);
    299	of_node_put(dn);
    300
    301	if (!intc_base) {
    302		pr_err("unable to remap intc base register\n");
    303		return -ENOMEM;
    304	}
    305
    306	writel(virt_to_phys(secondary_startup),
    307	       intc_base + LOCAL_MAILBOX3_SET0 + 16 * cpu);
    308
    309	dsb(sy);
    310	sev();
    311
    312	iounmap(intc_base);
    313
    314	return 0;
    315}
    316
    317static const struct smp_operations kona_smp_ops __initconst = {
    318	.smp_prepare_cpus	= bcm_smp_prepare_cpus,
    319	.smp_boot_secondary	= kona_boot_secondary,
    320};
    321CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
    322			&kona_smp_ops);
    323
    324static const struct smp_operations bcm23550_smp_ops __initconst = {
    325	.smp_boot_secondary	= bcm23550_boot_secondary,
    326};
    327CPU_METHOD_OF_DECLARE(bcm_smp_bcm23550, "brcm,bcm23550",
    328			&bcm23550_smp_ops);
    329
    330static const struct smp_operations nsp_smp_ops __initconst = {
    331	.smp_prepare_cpus	= bcm_smp_prepare_cpus,
    332	.smp_boot_secondary	= nsp_boot_secondary,
    333};
    334CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops);
    335
    336const struct smp_operations bcm2836_smp_ops __initconst = {
    337	.smp_boot_secondary	= bcm2836_boot_secondary,
    338};
    339CPU_METHOD_OF_DECLARE(bcm_smp_bcm2836, "brcm,bcm2836-smp", &bcm2836_smp_ops);