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

mpc86xx_smp.c (2465B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Author: Xianghua Xiao <x.xiao@freescale.com>
      4 *         Zhang Wei <wei.zhang@freescale.com>
      5 *
      6 * Copyright 2006 Freescale Semiconductor Inc.
      7 */
      8
      9#include <linux/stddef.h>
     10#include <linux/kernel.h>
     11#include <linux/init.h>
     12#include <linux/delay.h>
     13#include <linux/pgtable.h>
     14
     15#include <asm/code-patching.h>
     16#include <asm/page.h>
     17#include <asm/pci-bridge.h>
     18#include <asm/mpic.h>
     19#include <asm/cacheflush.h>
     20#include <asm/inst.h>
     21
     22#include <sysdev/fsl_soc.h>
     23
     24#include "mpc86xx.h"
     25
     26extern void __secondary_start_mpc86xx(void);
     27
     28#define MCM_PORT_CONFIG_OFFSET	0x10
     29
     30/* Offset from CCSRBAR */
     31#define MPC86xx_MCM_OFFSET      (0x1000)
     32#define MPC86xx_MCM_SIZE        (0x1000)
     33
     34static void __init
     35smp_86xx_release_core(int nr)
     36{
     37	__be32 __iomem *mcm_vaddr;
     38	unsigned long pcr;
     39
     40	if (nr < 0 || nr >= NR_CPUS)
     41		return;
     42
     43	/*
     44	 * Startup Core #nr.
     45	 */
     46	mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET,
     47			    MPC86xx_MCM_SIZE);
     48	pcr = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2));
     49	pcr |= 1 << (nr + 24);
     50	out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr);
     51
     52	iounmap(mcm_vaddr);
     53}
     54
     55
     56static int __init
     57smp_86xx_kick_cpu(int nr)
     58{
     59	unsigned int save_vector;
     60	unsigned long target, flags;
     61	int n = 0;
     62	unsigned int *vector = (unsigned int *)(KERNELBASE + 0x100);
     63
     64	if (nr < 0 || nr >= NR_CPUS)
     65		return -ENOENT;
     66
     67	pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr);
     68
     69	local_irq_save(flags);
     70
     71	/* Save reset vector */
     72	save_vector = *vector;
     73
     74	/* Setup fake reset vector to call __secondary_start_mpc86xx. */
     75	target = (unsigned long) __secondary_start_mpc86xx;
     76	patch_branch(vector, target, BRANCH_SET_LINK);
     77
     78	/* Kick that CPU */
     79	smp_86xx_release_core(nr);
     80
     81	/* Wait a bit for the CPU to take the exception. */
     82	while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000))
     83		mdelay(1);
     84
     85	/* Restore the exception vector */
     86	patch_instruction(vector, ppc_inst(save_vector));
     87
     88	local_irq_restore(flags);
     89
     90	pr_debug("wait CPU #%d for %d msecs.\n", nr, n);
     91
     92	return 0;
     93}
     94
     95
     96static void __init
     97smp_86xx_setup_cpu(int cpu_nr)
     98{
     99	mpic_setup_this_cpu();
    100}
    101
    102
    103struct smp_ops_t smp_86xx_ops = {
    104	.cause_nmi_ipi = NULL,
    105	.message_pass = smp_mpic_message_pass,
    106	.probe = smp_mpic_probe,
    107	.kick_cpu = smp_86xx_kick_cpu,
    108	.setup_cpu = smp_86xx_setup_cpu,
    109	.take_timebase = smp_generic_take_timebase,
    110	.give_timebase = smp_generic_give_timebase,
    111};
    112
    113
    114void __init
    115mpc86xx_smp_init(void)
    116{
    117	smp_ops = &smp_86xx_ops;
    118}