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

shmem.c (2882B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * For transport using shared mem structure.
      4 *
      5 * Copyright (C) 2019 ARM Ltd.
      6 */
      7
      8#include <linux/io.h>
      9#include <linux/processor.h>
     10#include <linux/types.h>
     11
     12#include "common.h"
     13
     14/*
     15 * SCMI specification requires all parameters, message headers, return
     16 * arguments or any protocol data to be expressed in little endian
     17 * format only.
     18 */
     19struct scmi_shared_mem {
     20	__le32 reserved;
     21	__le32 channel_status;
     22#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR	BIT(1)
     23#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE	BIT(0)
     24	__le32 reserved1[2];
     25	__le32 flags;
     26#define SCMI_SHMEM_FLAG_INTR_ENABLED	BIT(0)
     27	__le32 length;
     28	__le32 msg_header;
     29	u8 msg_payload[];
     30};
     31
     32void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
     33		      struct scmi_xfer *xfer)
     34{
     35	/*
     36	 * Ideally channel must be free by now unless OS timeout last
     37	 * request and platform continued to process the same, wait
     38	 * until it releases the shared memory, otherwise we may endup
     39	 * overwriting its response with new message payload or vice-versa
     40	 */
     41	spin_until_cond(ioread32(&shmem->channel_status) &
     42			SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
     43	/* Mark channel busy + clear error */
     44	iowrite32(0x0, &shmem->channel_status);
     45	iowrite32(xfer->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED,
     46		  &shmem->flags);
     47	iowrite32(sizeof(shmem->msg_header) + xfer->tx.len, &shmem->length);
     48	iowrite32(pack_scmi_header(&xfer->hdr), &shmem->msg_header);
     49	if (xfer->tx.buf)
     50		memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len);
     51}
     52
     53u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem)
     54{
     55	return ioread32(&shmem->msg_header);
     56}
     57
     58void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
     59			  struct scmi_xfer *xfer)
     60{
     61	xfer->hdr.status = ioread32(shmem->msg_payload);
     62	/* Skip the length of header and status in shmem area i.e 8 bytes */
     63	xfer->rx.len = min_t(size_t, xfer->rx.len,
     64			     ioread32(&shmem->length) - 8);
     65
     66	/* Take a copy to the rx buffer.. */
     67	memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len);
     68}
     69
     70void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem,
     71			      size_t max_len, struct scmi_xfer *xfer)
     72{
     73	/* Skip only the length of header in shmem area i.e 4 bytes */
     74	xfer->rx.len = min_t(size_t, max_len, ioread32(&shmem->length) - 4);
     75
     76	/* Take a copy to the rx buffer.. */
     77	memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len);
     78}
     79
     80void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem)
     81{
     82	iowrite32(SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE, &shmem->channel_status);
     83}
     84
     85bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
     86		     struct scmi_xfer *xfer)
     87{
     88	u16 xfer_id;
     89
     90	xfer_id = MSG_XTRACT_TOKEN(ioread32(&shmem->msg_header));
     91
     92	if (xfer->hdr.seq != xfer_id)
     93		return false;
     94
     95	return ioread32(&shmem->channel_status) &
     96		(SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
     97		 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
     98}