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

vfio_platform_bcmflexrm.c (2472B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2017 Broadcom
      4 */
      5
      6/*
      7 * This driver provides reset support for Broadcom FlexRM ring manager
      8 * to VFIO platform.
      9 */
     10
     11#include <linux/delay.h>
     12#include <linux/device.h>
     13#include <linux/init.h>
     14#include <linux/io.h>
     15#include <linux/kernel.h>
     16#include <linux/module.h>
     17
     18#include "../vfio_platform_private.h"
     19
     20/* FlexRM configuration */
     21#define RING_REGS_SIZE					0x10000
     22#define RING_VER_MAGIC					0x76303031
     23
     24/* Per-Ring register offsets */
     25#define RING_VER					0x000
     26#define RING_CONTROL					0x034
     27#define RING_FLUSH_DONE					0x038
     28
     29/* Register RING_CONTROL fields */
     30#define CONTROL_FLUSH_SHIFT				5
     31
     32/* Register RING_FLUSH_DONE fields */
     33#define FLUSH_DONE_MASK					0x1
     34
     35static int vfio_platform_bcmflexrm_shutdown(void __iomem *ring)
     36{
     37	unsigned int timeout;
     38
     39	/* Disable/inactivate ring */
     40	writel_relaxed(0x0, ring + RING_CONTROL);
     41
     42	/* Set ring flush state */
     43	timeout = 1000; /* timeout of 1s */
     44	writel_relaxed(BIT(CONTROL_FLUSH_SHIFT), ring + RING_CONTROL);
     45	do {
     46		if (readl_relaxed(ring + RING_FLUSH_DONE) &
     47		    FLUSH_DONE_MASK)
     48			break;
     49		mdelay(1);
     50	} while (--timeout);
     51	if (!timeout)
     52		return -ETIMEDOUT;
     53
     54	/* Clear ring flush state */
     55	timeout = 1000; /* timeout of 1s */
     56	writel_relaxed(0x0, ring + RING_CONTROL);
     57	do {
     58		if (!(readl_relaxed(ring + RING_FLUSH_DONE) &
     59		      FLUSH_DONE_MASK))
     60			break;
     61		mdelay(1);
     62	} while (--timeout);
     63	if (!timeout)
     64		return -ETIMEDOUT;
     65
     66	return 0;
     67}
     68
     69static int vfio_platform_bcmflexrm_reset(struct vfio_platform_device *vdev)
     70{
     71	void __iomem *ring;
     72	int rc = 0, ret = 0, ring_num = 0;
     73	struct vfio_platform_region *reg = &vdev->regions[0];
     74
     75	/* Map FlexRM ring registers if not mapped */
     76	if (!reg->ioaddr) {
     77		reg->ioaddr = ioremap(reg->addr, reg->size);
     78		if (!reg->ioaddr)
     79			return -ENOMEM;
     80	}
     81
     82	/* Discover and shutdown each FlexRM ring */
     83	for (ring = reg->ioaddr;
     84	     ring < (reg->ioaddr + reg->size); ring += RING_REGS_SIZE) {
     85		if (readl_relaxed(ring + RING_VER) == RING_VER_MAGIC) {
     86			rc = vfio_platform_bcmflexrm_shutdown(ring);
     87			if (rc) {
     88				dev_warn(vdev->device,
     89					 "FlexRM ring%d shutdown error %d\n",
     90					 ring_num, rc);
     91				ret |= rc;
     92			}
     93			ring_num++;
     94		}
     95	}
     96
     97	return ret;
     98}
     99
    100module_vfio_reset_handler("brcm,iproc-flexrm-mbox",
    101			  vfio_platform_bcmflexrm_reset);
    102
    103MODULE_LICENSE("GPL v2");
    104MODULE_AUTHOR("Anup Patel <anup.patel@broadcom.com>");
    105MODULE_DESCRIPTION("Reset support for Broadcom FlexRM VFIO platform device");