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

acpi_parking_protocol.c (3628B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ARM64 ACPI Parking Protocol implementation
      4 *
      5 * Authors: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
      6 *	    Mark Salter <msalter@redhat.com>
      7 */
      8#include <linux/acpi.h>
      9#include <linux/mm.h>
     10#include <linux/types.h>
     11
     12#include <asm/cpu_ops.h>
     13
     14struct parking_protocol_mailbox {
     15	__le32 cpu_id;
     16	__le32 reserved;
     17	__le64 entry_point;
     18};
     19
     20struct cpu_mailbox_entry {
     21	struct parking_protocol_mailbox __iomem *mailbox;
     22	phys_addr_t mailbox_addr;
     23	u8 version;
     24	u8 gic_cpu_id;
     25};
     26
     27static struct cpu_mailbox_entry cpu_mailbox_entries[NR_CPUS];
     28
     29void __init acpi_set_mailbox_entry(int cpu,
     30				   struct acpi_madt_generic_interrupt *p)
     31{
     32	struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu];
     33
     34	cpu_entry->mailbox_addr = p->parked_address;
     35	cpu_entry->version = p->parking_version;
     36	cpu_entry->gic_cpu_id = p->cpu_interface_number;
     37}
     38
     39bool acpi_parking_protocol_valid(int cpu)
     40{
     41	struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu];
     42
     43	return cpu_entry->mailbox_addr && cpu_entry->version;
     44}
     45
     46static int acpi_parking_protocol_cpu_init(unsigned int cpu)
     47{
     48	pr_debug("%s: ACPI parked addr=%llx\n", __func__,
     49		  cpu_mailbox_entries[cpu].mailbox_addr);
     50
     51	return 0;
     52}
     53
     54static int acpi_parking_protocol_cpu_prepare(unsigned int cpu)
     55{
     56	return 0;
     57}
     58
     59static int acpi_parking_protocol_cpu_boot(unsigned int cpu)
     60{
     61	struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu];
     62	struct parking_protocol_mailbox __iomem *mailbox;
     63	u32 cpu_id;
     64
     65	/*
     66	 * Map mailbox memory with attribute device nGnRE (ie ioremap -
     67	 * this deviates from the parking protocol specifications since
     68	 * the mailboxes are required to be mapped nGnRnE; the attribute
     69	 * discrepancy is harmless insofar as the protocol specification
     70	 * is concerned).
     71	 * If the mailbox is mistakenly allocated in the linear mapping
     72	 * by FW ioremap will fail since the mapping will be prevented
     73	 * by the kernel (it clashes with the linear mapping attributes
     74	 * specifications).
     75	 */
     76	mailbox = ioremap(cpu_entry->mailbox_addr, sizeof(*mailbox));
     77	if (!mailbox)
     78		return -EIO;
     79
     80	cpu_id = readl_relaxed(&mailbox->cpu_id);
     81	/*
     82	 * Check if firmware has set-up the mailbox entry properly
     83	 * before kickstarting the respective cpu.
     84	 */
     85	if (cpu_id != ~0U) {
     86		iounmap(mailbox);
     87		return -ENXIO;
     88	}
     89
     90	/*
     91	 * stash the mailbox address mapping to use it for further FW
     92	 * checks in the postboot method
     93	 */
     94	cpu_entry->mailbox = mailbox;
     95
     96	/*
     97	 * We write the entry point and cpu id as LE regardless of the
     98	 * native endianness of the kernel. Therefore, any boot-loaders
     99	 * that read this address need to convert this address to the
    100	 * Boot-Loader's endianness before jumping.
    101	 */
    102	writeq_relaxed(__pa_symbol(function_nocfi(secondary_entry)),
    103		       &mailbox->entry_point);
    104	writel_relaxed(cpu_entry->gic_cpu_id, &mailbox->cpu_id);
    105
    106	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
    107
    108	return 0;
    109}
    110
    111static void acpi_parking_protocol_cpu_postboot(void)
    112{
    113	int cpu = smp_processor_id();
    114	struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu];
    115	struct parking_protocol_mailbox __iomem *mailbox = cpu_entry->mailbox;
    116	u64 entry_point;
    117
    118	entry_point = readq_relaxed(&mailbox->entry_point);
    119	/*
    120	 * Check if firmware has cleared the entry_point as expected
    121	 * by the protocol specification.
    122	 */
    123	WARN_ON(entry_point);
    124}
    125
    126const struct cpu_operations acpi_parking_protocol_ops = {
    127	.name		= "parking-protocol",
    128	.cpu_init	= acpi_parking_protocol_cpu_init,
    129	.cpu_prepare	= acpi_parking_protocol_cpu_prepare,
    130	.cpu_boot	= acpi_parking_protocol_cpu_boot,
    131	.cpu_postboot	= acpi_parking_protocol_cpu_postboot
    132};