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 (2055B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3#define pr_fmt(fmt) "ACPI: " fmt
      4
      5#include <linux/pci.h>
      6#include <linux/acpi.h>
      7#include <acpi/reboot.h>
      8#include <linux/delay.h>
      9
     10#ifdef CONFIG_PCI
     11static void acpi_pci_reboot(struct acpi_generic_address *rr, u8 reset_value)
     12{
     13	unsigned int devfn;
     14	struct pci_bus *bus0;
     15
     16	/* The reset register can only live on bus 0. */
     17	bus0 = pci_find_bus(0, 0);
     18	if (!bus0)
     19		return;
     20	/* Form PCI device/function pair. */
     21	devfn = PCI_DEVFN((rr->address >> 32) & 0xffff,
     22			  (rr->address >> 16) & 0xffff);
     23	pr_debug("Resetting with ACPI PCI RESET_REG.\n");
     24	/* Write the value that resets us. */
     25	pci_bus_write_config_byte(bus0, devfn,
     26			(rr->address & 0xffff), reset_value);
     27}
     28#else
     29static inline void acpi_pci_reboot(struct acpi_generic_address *rr,
     30				   u8 reset_value)
     31{
     32	pr_warn_once("PCI configuration space access is not supported\n");
     33}
     34#endif
     35
     36void acpi_reboot(void)
     37{
     38	struct acpi_generic_address *rr;
     39	u8 reset_value;
     40
     41	if (acpi_disabled)
     42		return;
     43
     44	rr = &acpi_gbl_FADT.reset_register;
     45
     46	/* ACPI reset register was only introduced with v2 of the FADT */
     47
     48	if (acpi_gbl_FADT.header.revision < 2)
     49		return;
     50
     51	/* Is the reset register supported? The spec says we should be
     52	 * checking the bit width and bit offset, but Windows ignores
     53	 * these fields */
     54	if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
     55		return;
     56
     57	reset_value = acpi_gbl_FADT.reset_value;
     58
     59	/* The reset register can only exist in I/O, Memory or PCI config space
     60	 * on a device on bus 0. */
     61	switch (rr->space_id) {
     62	case ACPI_ADR_SPACE_PCI_CONFIG:
     63		acpi_pci_reboot(rr, reset_value);
     64		break;
     65
     66	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
     67	case ACPI_ADR_SPACE_SYSTEM_IO:
     68		pr_debug("ACPI MEMORY or I/O RESET_REG.\n");
     69		acpi_reset();
     70		break;
     71	}
     72
     73	/*
     74	 * Some platforms do not shut down immediately after writing to the
     75	 * ACPI reset register, and this results in racing with the
     76	 * subsequent reboot mechanism.
     77	 *
     78	 * The 15ms delay has been found to be long enough for the system
     79	 * to reboot on the affected platforms.
     80	 */
     81	mdelay(15);
     82}