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_pcc.c (3371B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Author: Sudeep Holla <sudeep.holla@arm.com>
      4 * Copyright 2021 Arm Limited
      5 *
      6 * The PCC Address Space also referred as PCC Operation Region pertains to the
      7 * region of PCC subspace that succeeds the PCC signature. The PCC Operation
      8 * Region works in conjunction with the PCC Table(Platform Communications
      9 * Channel Table). PCC subspaces that are marked for use as PCC Operation
     10 * Regions must not be used as PCC subspaces for the standard ACPI features
     11 * such as CPPC, RASF, PDTT and MPST. These standard features must always use
     12 * the PCC Table instead.
     13 *
     14 * This driver sets up the PCC Address Space and installs an handler to enable
     15 * handling of PCC OpRegion in the firmware.
     16 *
     17 */
     18#include <linux/kernel.h>
     19#include <linux/acpi.h>
     20#include <linux/completion.h>
     21#include <linux/idr.h>
     22#include <linux/io.h>
     23
     24#include <acpi/pcc.h>
     25
     26struct pcc_data {
     27	struct pcc_mbox_chan *pcc_chan;
     28	void __iomem *pcc_comm_addr;
     29	struct completion done;
     30	struct mbox_client cl;
     31	struct acpi_pcc_info ctx;
     32};
     33
     34static struct acpi_pcc_info pcc_ctx;
     35
     36static void pcc_rx_callback(struct mbox_client *cl, void *m)
     37{
     38	struct pcc_data *data = container_of(cl, struct pcc_data, cl);
     39
     40	complete(&data->done);
     41}
     42
     43static acpi_status
     44acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
     45			     void *handler_context,  void **region_context)
     46{
     47	struct pcc_data *data;
     48	struct acpi_pcc_info *ctx = handler_context;
     49	struct pcc_mbox_chan *pcc_chan;
     50
     51	data = kzalloc(sizeof(*data), GFP_KERNEL);
     52	if (!data)
     53		return AE_NO_MEMORY;
     54
     55	data->cl.rx_callback = pcc_rx_callback;
     56	data->cl.knows_txdone = true;
     57	data->ctx.length = ctx->length;
     58	data->ctx.subspace_id = ctx->subspace_id;
     59	data->ctx.internal_buffer = ctx->internal_buffer;
     60
     61	init_completion(&data->done);
     62	data->pcc_chan = pcc_mbox_request_channel(&data->cl, ctx->subspace_id);
     63	if (IS_ERR(data->pcc_chan)) {
     64		pr_err("Failed to find PCC channel for subspace %d\n",
     65		       ctx->subspace_id);
     66		return AE_NOT_FOUND;
     67	}
     68
     69	pcc_chan = data->pcc_chan;
     70	data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr,
     71					      pcc_chan->shmem_size);
     72	if (!data->pcc_comm_addr) {
     73		pr_err("Failed to ioremap PCC comm region mem for %d\n",
     74		       ctx->subspace_id);
     75		return AE_NO_MEMORY;
     76	}
     77
     78	*region_context = data;
     79	return AE_OK;
     80}
     81
     82static acpi_status
     83acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
     84			       u32 bits, acpi_integer *value,
     85			       void *handler_context, void *region_context)
     86{
     87	int ret;
     88	struct pcc_data *data = region_context;
     89
     90	reinit_completion(&data->done);
     91
     92	/* Write to Shared Memory */
     93	memcpy_toio(data->pcc_comm_addr, (void *)value, data->ctx.length);
     94
     95	ret = mbox_send_message(data->pcc_chan->mchan, NULL);
     96	if (ret < 0)
     97		return AE_ERROR;
     98
     99	if (data->pcc_chan->mchan->mbox->txdone_irq)
    100		wait_for_completion(&data->done);
    101
    102	mbox_client_txdone(data->pcc_chan->mchan, ret);
    103
    104	memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length);
    105
    106	return AE_OK;
    107}
    108
    109void __init acpi_init_pcc(void)
    110{
    111	acpi_status status;
    112
    113	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
    114						    ACPI_ADR_SPACE_PLATFORM_COMM,
    115						    &acpi_pcc_address_space_handler,
    116						    &acpi_pcc_address_space_setup,
    117						    &pcc_ctx);
    118	if (ACPI_FAILURE(status))
    119		pr_alert("OperationRegion handler could not be installed\n");
    120}