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

dimm.c (3140B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
      4 */
      5#include <linux/vmalloc.h>
      6#include <linux/module.h>
      7#include <linux/device.h>
      8#include <linux/sizes.h>
      9#include <linux/ndctl.h>
     10#include <linux/slab.h>
     11#include <linux/mm.h>
     12#include <linux/nd.h>
     13#include "label.h"
     14#include "nd.h"
     15
     16static int nvdimm_probe(struct device *dev)
     17{
     18	struct nvdimm_drvdata *ndd;
     19	int rc;
     20
     21	rc = nvdimm_security_setup_events(dev);
     22	if (rc < 0) {
     23		dev_err(dev, "security event setup failed: %d\n", rc);
     24		return rc;
     25	}
     26
     27	rc = nvdimm_check_config_data(dev);
     28	if (rc) {
     29		/* not required for non-aliased nvdimm, ex. NVDIMM-N */
     30		if (rc == -ENOTTY)
     31			rc = 0;
     32		return rc;
     33	}
     34
     35	/*
     36	 * The locked status bit reflects explicit status codes from the
     37	 * label reading commands, revalidate it each time the driver is
     38	 * activated and re-reads the label area.
     39	 */
     40	nvdimm_clear_locked(dev);
     41
     42	ndd = kzalloc(sizeof(*ndd), GFP_KERNEL);
     43	if (!ndd)
     44		return -ENOMEM;
     45
     46	dev_set_drvdata(dev, ndd);
     47	ndd->dpa.name = dev_name(dev);
     48	ndd->ns_current = -1;
     49	ndd->ns_next = -1;
     50	ndd->dpa.start = 0;
     51	ndd->dpa.end = -1;
     52	ndd->dev = dev;
     53	get_device(dev);
     54	kref_init(&ndd->kref);
     55
     56	/*
     57	 * Attempt to unlock, if the DIMM supports security commands,
     58	 * otherwise the locked indication is determined by explicit
     59	 * status codes from the label reading commands.
     60	 */
     61	rc = nvdimm_security_unlock(dev);
     62	if (rc < 0)
     63		dev_dbg(dev, "failed to unlock dimm: %d\n", rc);
     64
     65
     66	/*
     67	 * EACCES failures reading the namespace label-area-properties
     68	 * are interpreted as the DIMM capacity being locked but the
     69	 * namespace labels themselves being accessible.
     70	 */
     71	rc = nvdimm_init_nsarea(ndd);
     72	if (rc == -EACCES) {
     73		/*
     74		 * See nvdimm_namespace_common_probe() where we fail to
     75		 * allow namespaces to probe while the DIMM is locked,
     76		 * but we do allow for namespace enumeration.
     77		 */
     78		nvdimm_set_locked(dev);
     79		rc = 0;
     80	}
     81	if (rc)
     82		goto err;
     83
     84	/*
     85	 * EACCES failures reading the namespace label-data are
     86	 * interpreted as the label area being locked in addition to the
     87	 * DIMM capacity. We fail the dimm probe to prevent regions from
     88	 * attempting to parse the label area.
     89	 */
     90	rc = nd_label_data_init(ndd);
     91	if (rc == -EACCES)
     92		nvdimm_set_locked(dev);
     93	if (rc)
     94		goto err;
     95
     96	dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size);
     97
     98	nvdimm_bus_lock(dev);
     99	if (ndd->ns_current >= 0) {
    100		rc = nd_label_reserve_dpa(ndd);
    101		if (rc == 0)
    102			nvdimm_set_labeling(dev);
    103	}
    104	nvdimm_bus_unlock(dev);
    105
    106	if (rc)
    107		goto err;
    108
    109	return 0;
    110
    111 err:
    112	put_ndd(ndd);
    113	return rc;
    114}
    115
    116static void nvdimm_remove(struct device *dev)
    117{
    118	struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
    119
    120	nvdimm_bus_lock(dev);
    121	dev_set_drvdata(dev, NULL);
    122	nvdimm_bus_unlock(dev);
    123	put_ndd(ndd);
    124}
    125
    126static struct nd_device_driver nvdimm_driver = {
    127	.probe = nvdimm_probe,
    128	.remove = nvdimm_remove,
    129	.drv = {
    130		.name = "nvdimm",
    131	},
    132	.type = ND_DRIVER_DIMM,
    133};
    134
    135int __init nvdimm_init(void)
    136{
    137	return nd_driver_register(&nvdimm_driver);
    138}
    139
    140void nvdimm_exit(void)
    141{
    142	driver_unregister(&nvdimm_driver.drv);
    143}
    144
    145MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DIMM);