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

reboot.c (4032B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  Copyright (C) 1996-2000 Russell King - Converted to ARM.
      4 *  Original Copyright (C) 1995  Linus Torvalds
      5 */
      6#include <linux/cpu.h>
      7#include <linux/delay.h>
      8#include <linux/reboot.h>
      9
     10#include <asm/cacheflush.h>
     11#include <asm/idmap.h>
     12#include <asm/virt.h>
     13
     14#include "reboot.h"
     15
     16typedef void (*phys_reset_t)(unsigned long, bool);
     17
     18/*
     19 * Function pointers to optional machine specific functions
     20 */
     21void (*pm_power_off)(void);
     22EXPORT_SYMBOL(pm_power_off);
     23
     24/*
     25 * A temporary stack to use for CPU reset. This is static so that we
     26 * don't clobber it with the identity mapping. When running with this
     27 * stack, any references to the current task *will not work* so you
     28 * should really do as little as possible before jumping to your reset
     29 * code.
     30 */
     31static u64 soft_restart_stack[16];
     32
     33static void __soft_restart(void *addr)
     34{
     35	phys_reset_t phys_reset;
     36
     37	/* Take out a flat memory mapping. */
     38	setup_mm_for_reboot();
     39
     40	/* Clean and invalidate caches */
     41	flush_cache_all();
     42
     43	/* Turn off caching */
     44	cpu_proc_fin();
     45
     46	/* Push out any further dirty data, and ensure cache is empty */
     47	flush_cache_all();
     48
     49	/* Switch to the identity mapping. */
     50	phys_reset = (phys_reset_t)virt_to_idmap(cpu_reset);
     51
     52	/* original stub should be restored by kvm */
     53	phys_reset((unsigned long)addr, is_hyp_mode_available());
     54
     55	/* Should never get here. */
     56	BUG();
     57}
     58
     59void _soft_restart(unsigned long addr, bool disable_l2)
     60{
     61	u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);
     62
     63	/* Disable interrupts first */
     64	raw_local_irq_disable();
     65	local_fiq_disable();
     66
     67	/* Disable the L2 if we're the last man standing. */
     68	if (disable_l2)
     69		outer_disable();
     70
     71	/* Change to the new stack and continue with the reset. */
     72	call_with_stack(__soft_restart, (void *)addr, (void *)stack);
     73
     74	/* Should never get here. */
     75	BUG();
     76}
     77
     78void soft_restart(unsigned long addr)
     79{
     80	_soft_restart(addr, num_online_cpus() == 1);
     81}
     82
     83/*
     84 * Called by kexec, immediately prior to machine_kexec().
     85 *
     86 * This must completely disable all secondary CPUs; simply causing those CPUs
     87 * to execute e.g. a RAM-based pin loop is not sufficient. This allows the
     88 * kexec'd kernel to use any and all RAM as it sees fit, without having to
     89 * avoid any code or data used by any SW CPU pin loop. The CPU hotplug
     90 * functionality embodied in smp_shutdown_nonboot_cpus() to achieve this.
     91 */
     92void machine_shutdown(void)
     93{
     94	smp_shutdown_nonboot_cpus(reboot_cpu);
     95}
     96
     97/*
     98 * Halting simply requires that the secondary CPUs stop performing any
     99 * activity (executing tasks, handling interrupts). smp_send_stop()
    100 * achieves this.
    101 */
    102void machine_halt(void)
    103{
    104	local_irq_disable();
    105	smp_send_stop();
    106	while (1);
    107}
    108
    109/*
    110 * Power-off simply requires that the secondary CPUs stop performing any
    111 * activity (executing tasks, handling interrupts). smp_send_stop()
    112 * achieves this. When the system power is turned off, it will take all CPUs
    113 * with it.
    114 */
    115void machine_power_off(void)
    116{
    117	local_irq_disable();
    118	smp_send_stop();
    119	do_kernel_power_off();
    120}
    121
    122/*
    123 * Restart requires that the secondary CPUs stop performing any activity
    124 * while the primary CPU resets the system. Systems with a single CPU can
    125 * use soft_restart() as their machine descriptor's .restart hook, since that
    126 * will cause the only available CPU to reset. Systems with multiple CPUs must
    127 * provide a HW restart implementation, to ensure that all CPUs reset at once.
    128 * This is required so that any code running after reset on the primary CPU
    129 * doesn't have to co-ordinate with other CPUs to ensure they aren't still
    130 * executing pre-reset code, and using RAM that the primary CPU's code wishes
    131 * to use. Implementing such co-ordination would be essentially impossible.
    132 */
    133void machine_restart(char *cmd)
    134{
    135	local_irq_disable();
    136	smp_send_stop();
    137
    138	do_kernel_restart(cmd);
    139
    140	/* Give a grace period for failure to restart of 1s */
    141	mdelay(1000);
    142
    143	/* Whoops - the platform was unable to reboot. Tell the user! */
    144	printk("Reboot failed -- System halted\n");
    145	while (1);
    146}