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

dax_devs.c (2866B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
      4 */
      5#include <linux/device.h>
      6#include <linux/sizes.h>
      7#include <linux/slab.h>
      8#include <linux/mm.h>
      9#include "nd-core.h"
     10#include "pfn.h"
     11#include "nd.h"
     12
     13static void nd_dax_release(struct device *dev)
     14{
     15	struct nd_region *nd_region = to_nd_region(dev->parent);
     16	struct nd_dax *nd_dax = to_nd_dax(dev);
     17	struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
     18
     19	dev_dbg(dev, "trace\n");
     20	nd_detach_ndns(dev, &nd_pfn->ndns);
     21	ida_simple_remove(&nd_region->dax_ida, nd_pfn->id);
     22	kfree(nd_pfn->uuid);
     23	kfree(nd_dax);
     24}
     25
     26struct nd_dax *to_nd_dax(struct device *dev)
     27{
     28	struct nd_dax *nd_dax = container_of(dev, struct nd_dax, nd_pfn.dev);
     29
     30	WARN_ON(!is_nd_dax(dev));
     31	return nd_dax;
     32}
     33EXPORT_SYMBOL(to_nd_dax);
     34
     35static const struct device_type nd_dax_device_type = {
     36	.name = "nd_dax",
     37	.release = nd_dax_release,
     38	.groups = nd_pfn_attribute_groups,
     39};
     40
     41bool is_nd_dax(struct device *dev)
     42{
     43	return dev ? dev->type == &nd_dax_device_type : false;
     44}
     45EXPORT_SYMBOL(is_nd_dax);
     46
     47static struct nd_dax *nd_dax_alloc(struct nd_region *nd_region)
     48{
     49	struct nd_pfn *nd_pfn;
     50	struct nd_dax *nd_dax;
     51	struct device *dev;
     52
     53	nd_dax = kzalloc(sizeof(*nd_dax), GFP_KERNEL);
     54	if (!nd_dax)
     55		return NULL;
     56
     57	nd_pfn = &nd_dax->nd_pfn;
     58	nd_pfn->id = ida_simple_get(&nd_region->dax_ida, 0, 0, GFP_KERNEL);
     59	if (nd_pfn->id < 0) {
     60		kfree(nd_dax);
     61		return NULL;
     62	}
     63
     64	dev = &nd_pfn->dev;
     65	dev_set_name(dev, "dax%d.%d", nd_region->id, nd_pfn->id);
     66	dev->type = &nd_dax_device_type;
     67	dev->parent = &nd_region->dev;
     68
     69	return nd_dax;
     70}
     71
     72struct device *nd_dax_create(struct nd_region *nd_region)
     73{
     74	struct device *dev = NULL;
     75	struct nd_dax *nd_dax;
     76
     77	if (!is_memory(&nd_region->dev))
     78		return NULL;
     79
     80	nd_dax = nd_dax_alloc(nd_region);
     81	if (nd_dax)
     82		dev = nd_pfn_devinit(&nd_dax->nd_pfn, NULL);
     83	nd_device_register(dev);
     84	return dev;
     85}
     86
     87int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns)
     88{
     89	int rc;
     90	struct nd_dax *nd_dax;
     91	struct device *dax_dev;
     92	struct nd_pfn *nd_pfn;
     93	struct nd_pfn_sb *pfn_sb;
     94	struct nd_region *nd_region = to_nd_region(ndns->dev.parent);
     95
     96	if (ndns->force_raw)
     97		return -ENODEV;
     98
     99	switch (ndns->claim_class) {
    100	case NVDIMM_CCLASS_NONE:
    101	case NVDIMM_CCLASS_DAX:
    102		break;
    103	default:
    104		return -ENODEV;
    105	}
    106
    107	nvdimm_bus_lock(&ndns->dev);
    108	nd_dax = nd_dax_alloc(nd_region);
    109	nd_pfn = &nd_dax->nd_pfn;
    110	dax_dev = nd_pfn_devinit(nd_pfn, ndns);
    111	nvdimm_bus_unlock(&ndns->dev);
    112	if (!dax_dev)
    113		return -ENOMEM;
    114	pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
    115	nd_pfn->pfn_sb = pfn_sb;
    116	rc = nd_pfn_validate(nd_pfn, DAX_SIG);
    117	dev_dbg(dev, "dax: %s\n", rc == 0 ? dev_name(dax_dev) : "<none>");
    118	if (rc < 0) {
    119		nd_detach_ndns(dax_dev, &nd_pfn->ndns);
    120		put_device(dax_dev);
    121	} else
    122		nd_device_register(dax_dev);
    123
    124	return rc;
    125}
    126EXPORT_SYMBOL(nd_dax_probe);