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

rmem.c (2406B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (C) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
      4 */
      5
      6#include <linux/io.h>
      7#include <linux/module.h>
      8#include <linux/nvmem-provider.h>
      9#include <linux/of_reserved_mem.h>
     10#include <linux/platform_device.h>
     11
     12struct rmem {
     13	struct device *dev;
     14	struct nvmem_device *nvmem;
     15	struct reserved_mem *mem;
     16
     17	phys_addr_t size;
     18};
     19
     20static int rmem_read(void *context, unsigned int offset,
     21		     void *val, size_t bytes)
     22{
     23	struct rmem *priv = context;
     24	size_t available = priv->mem->size;
     25	loff_t off = offset;
     26	void *addr;
     27	int count;
     28
     29	/*
     30	 * Only map the reserved memory at this point to avoid potential rogue
     31	 * kernel threads inadvertently modifying it. Based on the current
     32	 * uses-cases for this driver, the performance hit isn't a concern.
     33	 * Nor is likely to be, given the nature of the subsystem. Most nvmem
     34	 * devices operate over slow buses to begin with.
     35	 *
     36	 * An alternative would be setting the memory as RO, set_memory_ro(),
     37	 * but as of Dec 2020 this isn't possible on arm64.
     38	 */
     39	addr = memremap(priv->mem->base, available, MEMREMAP_WB);
     40	if (IS_ERR(addr)) {
     41		dev_err(priv->dev, "Failed to remap memory region\n");
     42		return PTR_ERR(addr);
     43	}
     44
     45	count = memory_read_from_buffer(val, bytes, &off, addr, available);
     46
     47	memunmap(addr);
     48
     49	return count;
     50}
     51
     52static int rmem_probe(struct platform_device *pdev)
     53{
     54	struct nvmem_config config = { };
     55	struct device *dev = &pdev->dev;
     56	struct reserved_mem *mem;
     57	struct rmem *priv;
     58
     59	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
     60	if (!priv)
     61		return -ENOMEM;
     62	priv->dev = dev;
     63
     64	mem = of_reserved_mem_lookup(dev->of_node);
     65	if (!mem) {
     66		dev_err(dev, "Failed to lookup reserved memory\n");
     67		return -EINVAL;
     68	}
     69	priv->mem = mem;
     70
     71	config.dev = dev;
     72	config.priv = priv;
     73	config.name = "rmem";
     74	config.size = mem->size;
     75	config.reg_read = rmem_read;
     76
     77	return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config));
     78}
     79
     80static const struct of_device_id rmem_match[] = {
     81	{ .compatible = "nvmem-rmem", },
     82	{ /* sentinel */ },
     83};
     84MODULE_DEVICE_TABLE(of, rmem_match);
     85
     86static struct platform_driver rmem_driver = {
     87	.probe = rmem_probe,
     88	.driver = {
     89		.name = "rmem",
     90		.of_match_table = rmem_match,
     91	},
     92};
     93module_platform_driver(rmem_driver);
     94
     95MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
     96MODULE_DESCRIPTION("Reserved Memory Based nvmem Driver");
     97MODULE_LICENSE("GPL");