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

ndtest.c (23735B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      3
      4#include <linux/platform_device.h>
      5#include <linux/device.h>
      6#include <linux/module.h>
      7#include <linux/genalloc.h>
      8#include <linux/vmalloc.h>
      9#include <linux/dma-mapping.h>
     10#include <linux/list_sort.h>
     11#include <linux/libnvdimm.h>
     12#include <linux/ndctl.h>
     13#include <nd-core.h>
     14#include <linux/printk.h>
     15#include <linux/seq_buf.h>
     16
     17#include "../watermark.h"
     18#include "nfit_test.h"
     19#include "ndtest.h"
     20
     21enum {
     22	DIMM_SIZE = SZ_32M,
     23	LABEL_SIZE = SZ_128K,
     24	NUM_INSTANCES = 2,
     25	NUM_DCR = 4,
     26	NDTEST_MAX_MAPPING = 6,
     27};
     28
     29#define NDTEST_SCM_DIMM_CMD_MASK	   \
     30	((1ul << ND_CMD_GET_CONFIG_SIZE) | \
     31	 (1ul << ND_CMD_GET_CONFIG_DATA) | \
     32	 (1ul << ND_CMD_SET_CONFIG_DATA) | \
     33	 (1ul << ND_CMD_CALL))
     34
     35#define NFIT_DIMM_HANDLE(node, socket, imc, chan, dimm)			\
     36	(((node & 0xfff) << 16) | ((socket & 0xf) << 12)		\
     37	 | ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf))
     38
     39static DEFINE_SPINLOCK(ndtest_lock);
     40static struct ndtest_priv *instances[NUM_INSTANCES];
     41static struct class *ndtest_dimm_class;
     42static struct gen_pool *ndtest_pool;
     43
     44static struct ndtest_dimm dimm_group1[] = {
     45	{
     46		.size = DIMM_SIZE,
     47		.handle = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0),
     48		.uuid_str = "1e5c75d2-b618-11ea-9aa3-507b9ddc0f72",
     49		.physical_id = 0,
     50		.num_formats = 2,
     51	},
     52	{
     53		.size = DIMM_SIZE,
     54		.handle = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1),
     55		.uuid_str = "1c4d43ac-b618-11ea-be80-507b9ddc0f72",
     56		.physical_id = 1,
     57		.num_formats = 2,
     58	},
     59	{
     60		.size = DIMM_SIZE,
     61		.handle = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0),
     62		.uuid_str = "a9f17ffc-b618-11ea-b36d-507b9ddc0f72",
     63		.physical_id = 2,
     64		.num_formats = 2,
     65	},
     66	{
     67		.size = DIMM_SIZE,
     68		.handle = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1),
     69		.uuid_str = "b6b83b22-b618-11ea-8aae-507b9ddc0f72",
     70		.physical_id = 3,
     71		.num_formats = 2,
     72	},
     73	{
     74		.size = DIMM_SIZE,
     75		.handle = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0),
     76		.uuid_str = "bf9baaee-b618-11ea-b181-507b9ddc0f72",
     77		.physical_id = 4,
     78		.num_formats = 2,
     79	},
     80};
     81
     82static struct ndtest_dimm dimm_group2[] = {
     83	{
     84		.size = DIMM_SIZE,
     85		.handle = NFIT_DIMM_HANDLE(1, 0, 0, 0, 0),
     86		.uuid_str = "ca0817e2-b618-11ea-9db3-507b9ddc0f72",
     87		.physical_id = 0,
     88		.num_formats = 1,
     89		.flags = PAPR_PMEM_UNARMED | PAPR_PMEM_EMPTY |
     90			 PAPR_PMEM_SAVE_FAILED | PAPR_PMEM_SHUTDOWN_DIRTY |
     91			 PAPR_PMEM_HEALTH_FATAL,
     92	},
     93};
     94
     95static struct ndtest_mapping region0_mapping[] = {
     96	{
     97		.dimm = 0,
     98		.position = 0,
     99		.start = 0,
    100		.size = SZ_16M,
    101	},
    102	{
    103		.dimm = 1,
    104		.position = 1,
    105		.start = 0,
    106		.size = SZ_16M,
    107	}
    108};
    109
    110static struct ndtest_mapping region1_mapping[] = {
    111	{
    112		.dimm = 0,
    113		.position = 0,
    114		.start = SZ_16M,
    115		.size = SZ_16M,
    116	},
    117	{
    118		.dimm = 1,
    119		.position = 1,
    120		.start = SZ_16M,
    121		.size = SZ_16M,
    122	},
    123	{
    124		.dimm = 2,
    125		.position = 2,
    126		.start = SZ_16M,
    127		.size = SZ_16M,
    128	},
    129	{
    130		.dimm = 3,
    131		.position = 3,
    132		.start = SZ_16M,
    133		.size = SZ_16M,
    134	},
    135};
    136
    137static struct ndtest_mapping region2_mapping[] = {
    138	{
    139		.dimm = 0,
    140		.position = 0,
    141		.start = 0,
    142		.size = DIMM_SIZE,
    143	},
    144};
    145
    146static struct ndtest_mapping region3_mapping[] = {
    147	{
    148		.dimm = 1,
    149		.start = 0,
    150		.size = DIMM_SIZE,
    151	}
    152};
    153
    154static struct ndtest_mapping region4_mapping[] = {
    155	{
    156		.dimm = 2,
    157		.start = 0,
    158		.size = DIMM_SIZE,
    159	}
    160};
    161
    162static struct ndtest_mapping region5_mapping[] = {
    163	{
    164		.dimm = 3,
    165		.start = 0,
    166		.size = DIMM_SIZE,
    167	}
    168};
    169
    170static struct ndtest_region bus0_regions[] = {
    171	{
    172		.type = ND_DEVICE_NAMESPACE_PMEM,
    173		.num_mappings = ARRAY_SIZE(region0_mapping),
    174		.mapping = region0_mapping,
    175		.size = DIMM_SIZE,
    176		.range_index = 1,
    177	},
    178	{
    179		.type = ND_DEVICE_NAMESPACE_PMEM,
    180		.num_mappings = ARRAY_SIZE(region1_mapping),
    181		.mapping = region1_mapping,
    182		.size = DIMM_SIZE * 2,
    183		.range_index = 2,
    184	},
    185	{
    186		.type = ND_DEVICE_NAMESPACE_BLK,
    187		.num_mappings = ARRAY_SIZE(region2_mapping),
    188		.mapping = region2_mapping,
    189		.size = DIMM_SIZE,
    190		.range_index = 3,
    191	},
    192	{
    193		.type = ND_DEVICE_NAMESPACE_BLK,
    194		.num_mappings = ARRAY_SIZE(region3_mapping),
    195		.mapping = region3_mapping,
    196		.size = DIMM_SIZE,
    197		.range_index = 4,
    198	},
    199	{
    200		.type = ND_DEVICE_NAMESPACE_BLK,
    201		.num_mappings = ARRAY_SIZE(region4_mapping),
    202		.mapping = region4_mapping,
    203		.size = DIMM_SIZE,
    204		.range_index = 5,
    205	},
    206	{
    207		.type = ND_DEVICE_NAMESPACE_BLK,
    208		.num_mappings = ARRAY_SIZE(region5_mapping),
    209		.mapping = region5_mapping,
    210		.size = DIMM_SIZE,
    211		.range_index = 6,
    212	},
    213};
    214
    215static struct ndtest_mapping region6_mapping[] = {
    216	{
    217		.dimm = 0,
    218		.position = 0,
    219		.start = 0,
    220		.size = DIMM_SIZE,
    221	},
    222};
    223
    224static struct ndtest_region bus1_regions[] = {
    225	{
    226		.type = ND_DEVICE_NAMESPACE_IO,
    227		.num_mappings = ARRAY_SIZE(region6_mapping),
    228		.mapping = region6_mapping,
    229		.size = DIMM_SIZE,
    230		.range_index = 1,
    231	},
    232};
    233
    234static struct ndtest_config bus_configs[NUM_INSTANCES] = {
    235	/* bus 1 */
    236	{
    237		.dimm_start = 0,
    238		.dimm_count = ARRAY_SIZE(dimm_group1),
    239		.dimms = dimm_group1,
    240		.regions = bus0_regions,
    241		.num_regions = ARRAY_SIZE(bus0_regions),
    242	},
    243	/* bus 2 */
    244	{
    245		.dimm_start = ARRAY_SIZE(dimm_group1),
    246		.dimm_count = ARRAY_SIZE(dimm_group2),
    247		.dimms = dimm_group2,
    248		.regions = bus1_regions,
    249		.num_regions = ARRAY_SIZE(bus1_regions),
    250	},
    251};
    252
    253static inline struct ndtest_priv *to_ndtest_priv(struct device *dev)
    254{
    255	struct platform_device *pdev = to_platform_device(dev);
    256
    257	return container_of(pdev, struct ndtest_priv, pdev);
    258}
    259
    260static int ndtest_config_get(struct ndtest_dimm *p, unsigned int buf_len,
    261			     struct nd_cmd_get_config_data_hdr *hdr)
    262{
    263	unsigned int len;
    264
    265	if ((hdr->in_offset + hdr->in_length) > LABEL_SIZE)
    266		return -EINVAL;
    267
    268	hdr->status = 0;
    269	len = min(hdr->in_length, LABEL_SIZE - hdr->in_offset);
    270	memcpy(hdr->out_buf, p->label_area + hdr->in_offset, len);
    271
    272	return buf_len - len;
    273}
    274
    275static int ndtest_config_set(struct ndtest_dimm *p, unsigned int buf_len,
    276			     struct nd_cmd_set_config_hdr *hdr)
    277{
    278	unsigned int len;
    279
    280	if ((hdr->in_offset + hdr->in_length) > LABEL_SIZE)
    281		return -EINVAL;
    282
    283	len = min(hdr->in_length, LABEL_SIZE - hdr->in_offset);
    284	memcpy(p->label_area + hdr->in_offset, hdr->in_buf, len);
    285
    286	return buf_len - len;
    287}
    288
    289static int ndtest_get_config_size(struct ndtest_dimm *dimm, unsigned int buf_len,
    290				  struct nd_cmd_get_config_size *size)
    291{
    292	size->status = 0;
    293	size->max_xfer = 8;
    294	size->config_size = dimm->config_size;
    295
    296	return 0;
    297}
    298
    299static int ndtest_ctl(struct nvdimm_bus_descriptor *nd_desc,
    300		      struct nvdimm *nvdimm, unsigned int cmd, void *buf,
    301		      unsigned int buf_len, int *cmd_rc)
    302{
    303	struct ndtest_dimm *dimm;
    304	int _cmd_rc;
    305
    306	if (!cmd_rc)
    307		cmd_rc = &_cmd_rc;
    308
    309	*cmd_rc = 0;
    310
    311	if (!nvdimm)
    312		return -EINVAL;
    313
    314	dimm = nvdimm_provider_data(nvdimm);
    315	if (!dimm)
    316		return -EINVAL;
    317
    318	switch (cmd) {
    319	case ND_CMD_GET_CONFIG_SIZE:
    320		*cmd_rc = ndtest_get_config_size(dimm, buf_len, buf);
    321		break;
    322	case ND_CMD_GET_CONFIG_DATA:
    323		*cmd_rc = ndtest_config_get(dimm, buf_len, buf);
    324		break;
    325	case ND_CMD_SET_CONFIG_DATA:
    326		*cmd_rc = ndtest_config_set(dimm, buf_len, buf);
    327		break;
    328	default:
    329		return -EINVAL;
    330	}
    331
    332	/* Failures for a DIMM can be injected using fail_cmd and
    333	 * fail_cmd_code, see the device attributes below
    334	 */
    335	if ((1 << cmd) & dimm->fail_cmd)
    336		return dimm->fail_cmd_code ? dimm->fail_cmd_code : -EIO;
    337
    338	return 0;
    339}
    340
    341static struct nfit_test_resource *ndtest_resource_lookup(resource_size_t addr)
    342{
    343	int i;
    344
    345	for (i = 0; i < NUM_INSTANCES; i++) {
    346		struct nfit_test_resource *n, *nfit_res = NULL;
    347		struct ndtest_priv *t = instances[i];
    348
    349		if (!t)
    350			continue;
    351		spin_lock(&ndtest_lock);
    352		list_for_each_entry(n, &t->resources, list) {
    353			if (addr >= n->res.start && (addr < n->res.start
    354						+ resource_size(&n->res))) {
    355				nfit_res = n;
    356				break;
    357			} else if (addr >= (unsigned long) n->buf
    358					&& (addr < (unsigned long) n->buf
    359						+ resource_size(&n->res))) {
    360				nfit_res = n;
    361				break;
    362			}
    363		}
    364		spin_unlock(&ndtest_lock);
    365		if (nfit_res)
    366			return nfit_res;
    367	}
    368
    369	pr_warn("Failed to get resource\n");
    370
    371	return NULL;
    372}
    373
    374static void ndtest_release_resource(void *data)
    375{
    376	struct nfit_test_resource *res  = data;
    377
    378	spin_lock(&ndtest_lock);
    379	list_del(&res->list);
    380	spin_unlock(&ndtest_lock);
    381
    382	if (resource_size(&res->res) >= DIMM_SIZE)
    383		gen_pool_free(ndtest_pool, res->res.start,
    384				resource_size(&res->res));
    385	vfree(res->buf);
    386	kfree(res);
    387}
    388
    389static void *ndtest_alloc_resource(struct ndtest_priv *p, size_t size,
    390				   dma_addr_t *dma)
    391{
    392	dma_addr_t __dma;
    393	void *buf;
    394	struct nfit_test_resource *res;
    395	struct genpool_data_align data = {
    396		.align = SZ_128M,
    397	};
    398
    399	res = kzalloc(sizeof(*res), GFP_KERNEL);
    400	if (!res)
    401		return NULL;
    402
    403	buf = vmalloc(size);
    404	if (size >= DIMM_SIZE)
    405		__dma = gen_pool_alloc_algo(ndtest_pool, size,
    406					    gen_pool_first_fit_align, &data);
    407	else
    408		__dma = (unsigned long) buf;
    409
    410	if (!__dma)
    411		goto buf_err;
    412
    413	INIT_LIST_HEAD(&res->list);
    414	res->dev = &p->pdev.dev;
    415	res->buf = buf;
    416	res->res.start = __dma;
    417	res->res.end = __dma + size - 1;
    418	res->res.name = "NFIT";
    419	spin_lock_init(&res->lock);
    420	INIT_LIST_HEAD(&res->requests);
    421	spin_lock(&ndtest_lock);
    422	list_add(&res->list, &p->resources);
    423	spin_unlock(&ndtest_lock);
    424
    425	if (dma)
    426		*dma = __dma;
    427
    428	if (!devm_add_action(&p->pdev.dev, ndtest_release_resource, res))
    429		return res->buf;
    430
    431buf_err:
    432	if (__dma && size >= DIMM_SIZE)
    433		gen_pool_free(ndtest_pool, __dma, size);
    434	if (buf)
    435		vfree(buf);
    436	kfree(res);
    437
    438	return NULL;
    439}
    440
    441static ssize_t range_index_show(struct device *dev,
    442		struct device_attribute *attr, char *buf)
    443{
    444	struct nd_region *nd_region = to_nd_region(dev);
    445	struct ndtest_region *region = nd_region_provider_data(nd_region);
    446
    447	return sprintf(buf, "%d\n", region->range_index);
    448}
    449static DEVICE_ATTR_RO(range_index);
    450
    451static struct attribute *ndtest_region_attributes[] = {
    452	&dev_attr_range_index.attr,
    453	NULL,
    454};
    455
    456static const struct attribute_group ndtest_region_attribute_group = {
    457	.name = "papr",
    458	.attrs = ndtest_region_attributes,
    459};
    460
    461static const struct attribute_group *ndtest_region_attribute_groups[] = {
    462	&ndtest_region_attribute_group,
    463	NULL,
    464};
    465
    466static int ndtest_create_region(struct ndtest_priv *p,
    467				struct ndtest_region *region)
    468{
    469	struct nd_mapping_desc mappings[NDTEST_MAX_MAPPING];
    470	struct nd_region_desc *ndr_desc, _ndr_desc;
    471	struct nd_interleave_set *nd_set;
    472	struct resource res;
    473	int i, ndimm = region->mapping[0].dimm;
    474	u64 uuid[2];
    475
    476	memset(&res, 0, sizeof(res));
    477	memset(&mappings, 0, sizeof(mappings));
    478	memset(&_ndr_desc, 0, sizeof(_ndr_desc));
    479	ndr_desc = &_ndr_desc;
    480
    481	if (!ndtest_alloc_resource(p, region->size, &res.start))
    482		return -ENOMEM;
    483
    484	res.end = res.start + region->size - 1;
    485	ndr_desc->mapping = mappings;
    486	ndr_desc->res = &res;
    487	ndr_desc->provider_data = region;
    488	ndr_desc->attr_groups = ndtest_region_attribute_groups;
    489
    490	if (uuid_parse(p->config->dimms[ndimm].uuid_str, (uuid_t *)uuid)) {
    491		pr_err("failed to parse UUID\n");
    492		return -ENXIO;
    493	}
    494
    495	nd_set = devm_kzalloc(&p->pdev.dev, sizeof(*nd_set), GFP_KERNEL);
    496	if (!nd_set)
    497		return -ENOMEM;
    498
    499	nd_set->cookie1 = cpu_to_le64(uuid[0]);
    500	nd_set->cookie2 = cpu_to_le64(uuid[1]);
    501	nd_set->altcookie = nd_set->cookie1;
    502	ndr_desc->nd_set = nd_set;
    503
    504	if (region->type == ND_DEVICE_NAMESPACE_BLK) {
    505		mappings[0].start = 0;
    506		mappings[0].size = DIMM_SIZE;
    507		mappings[0].nvdimm = p->config->dimms[ndimm].nvdimm;
    508
    509		ndr_desc->mapping = &mappings[0];
    510		ndr_desc->num_mappings = 1;
    511		ndr_desc->num_lanes = 1;
    512		ndbr_desc.enable = ndtest_blk_region_enable;
    513		ndbr_desc.do_io = ndtest_blk_do_io;
    514		region->region = nvdimm_blk_region_create(p->bus, ndr_desc);
    515
    516		goto done;
    517	}
    518
    519	for (i = 0; i < region->num_mappings; i++) {
    520		ndimm = region->mapping[i].dimm;
    521		mappings[i].start = region->mapping[i].start;
    522		mappings[i].size = region->mapping[i].size;
    523		mappings[i].position = region->mapping[i].position;
    524		mappings[i].nvdimm = p->config->dimms[ndimm].nvdimm;
    525	}
    526
    527	ndr_desc->num_mappings = region->num_mappings;
    528	region->region = nvdimm_pmem_region_create(p->bus, ndr_desc);
    529
    530done:
    531	if (!region->region) {
    532		dev_err(&p->pdev.dev, "Error registering region %pR\n",
    533			ndr_desc->res);
    534		return -ENXIO;
    535	}
    536
    537	return 0;
    538}
    539
    540static int ndtest_init_regions(struct ndtest_priv *p)
    541{
    542	int i, ret = 0;
    543
    544	for (i = 0; i < p->config->num_regions; i++) {
    545		ret = ndtest_create_region(p, &p->config->regions[i]);
    546		if (ret)
    547			return ret;
    548	}
    549
    550	return 0;
    551}
    552
    553static void put_dimms(void *data)
    554{
    555	struct ndtest_priv *p = data;
    556	int i;
    557
    558	for (i = 0; i < p->config->dimm_count; i++)
    559		if (p->config->dimms[i].dev) {
    560			device_unregister(p->config->dimms[i].dev);
    561			p->config->dimms[i].dev = NULL;
    562		}
    563}
    564
    565static ssize_t handle_show(struct device *dev, struct device_attribute *attr,
    566		char *buf)
    567{
    568	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
    569
    570	return sprintf(buf, "%#x\n", dimm->handle);
    571}
    572static DEVICE_ATTR_RO(handle);
    573
    574static ssize_t fail_cmd_show(struct device *dev, struct device_attribute *attr,
    575		char *buf)
    576{
    577	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
    578
    579	return sprintf(buf, "%#x\n", dimm->fail_cmd);
    580}
    581
    582static ssize_t fail_cmd_store(struct device *dev, struct device_attribute *attr,
    583		const char *buf, size_t size)
    584{
    585	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
    586	unsigned long val;
    587	ssize_t rc;
    588
    589	rc = kstrtol(buf, 0, &val);
    590	if (rc)
    591		return rc;
    592
    593	dimm->fail_cmd = val;
    594
    595	return size;
    596}
    597static DEVICE_ATTR_RW(fail_cmd);
    598
    599static ssize_t fail_cmd_code_show(struct device *dev, struct device_attribute *attr,
    600		char *buf)
    601{
    602	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
    603
    604	return sprintf(buf, "%d\n", dimm->fail_cmd_code);
    605}
    606
    607static ssize_t fail_cmd_code_store(struct device *dev, struct device_attribute *attr,
    608		const char *buf, size_t size)
    609{
    610	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
    611	unsigned long val;
    612	ssize_t rc;
    613
    614	rc = kstrtol(buf, 0, &val);
    615	if (rc)
    616		return rc;
    617
    618	dimm->fail_cmd_code = val;
    619	return size;
    620}
    621static DEVICE_ATTR_RW(fail_cmd_code);
    622
    623static struct attribute *dimm_attributes[] = {
    624	&dev_attr_handle.attr,
    625	&dev_attr_fail_cmd.attr,
    626	&dev_attr_fail_cmd_code.attr,
    627	NULL,
    628};
    629
    630static struct attribute_group dimm_attribute_group = {
    631	.attrs = dimm_attributes,
    632};
    633
    634static const struct attribute_group *dimm_attribute_groups[] = {
    635	&dimm_attribute_group,
    636	NULL,
    637};
    638
    639static ssize_t phys_id_show(struct device *dev,
    640		struct device_attribute *attr, char *buf)
    641{
    642	struct nvdimm *nvdimm = to_nvdimm(dev);
    643	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
    644
    645	return sprintf(buf, "%#x\n", dimm->physical_id);
    646}
    647static DEVICE_ATTR_RO(phys_id);
    648
    649static ssize_t vendor_show(struct device *dev,
    650			   struct device_attribute *attr, char *buf)
    651{
    652	return sprintf(buf, "0x1234567\n");
    653}
    654static DEVICE_ATTR_RO(vendor);
    655
    656static ssize_t id_show(struct device *dev,
    657		       struct device_attribute *attr, char *buf)
    658{
    659	struct nvdimm *nvdimm = to_nvdimm(dev);
    660	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
    661
    662	return sprintf(buf, "%04x-%02x-%04x-%08x", 0xabcd,
    663		       0xa, 2016, ~(dimm->handle));
    664}
    665static DEVICE_ATTR_RO(id);
    666
    667static ssize_t nvdimm_handle_show(struct device *dev,
    668				  struct device_attribute *attr, char *buf)
    669{
    670	struct nvdimm *nvdimm = to_nvdimm(dev);
    671	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
    672
    673	return sprintf(buf, "%#x\n", dimm->handle);
    674}
    675
    676static struct device_attribute dev_attr_nvdimm_show_handle =  {
    677	.attr	= { .name = "handle", .mode = 0444 },
    678	.show	= nvdimm_handle_show,
    679};
    680
    681static ssize_t subsystem_vendor_show(struct device *dev,
    682		struct device_attribute *attr, char *buf)
    683{
    684	return sprintf(buf, "0x%04x\n", 0);
    685}
    686static DEVICE_ATTR_RO(subsystem_vendor);
    687
    688static ssize_t dirty_shutdown_show(struct device *dev,
    689		struct device_attribute *attr, char *buf)
    690{
    691	return sprintf(buf, "%d\n", 42);
    692}
    693static DEVICE_ATTR_RO(dirty_shutdown);
    694
    695static ssize_t formats_show(struct device *dev,
    696		struct device_attribute *attr, char *buf)
    697{
    698	struct nvdimm *nvdimm = to_nvdimm(dev);
    699	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
    700
    701	return sprintf(buf, "%d\n", dimm->num_formats);
    702}
    703static DEVICE_ATTR_RO(formats);
    704
    705static ssize_t format_show(struct device *dev,
    706		struct device_attribute *attr, char *buf)
    707{
    708	struct nvdimm *nvdimm = to_nvdimm(dev);
    709	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
    710
    711	if (dimm->num_formats > 1)
    712		return sprintf(buf, "0x201\n");
    713
    714	return sprintf(buf, "0x101\n");
    715}
    716static DEVICE_ATTR_RO(format);
    717
    718static ssize_t format1_show(struct device *dev, struct device_attribute *attr,
    719			    char *buf)
    720{
    721	return sprintf(buf, "0x301\n");
    722}
    723static DEVICE_ATTR_RO(format1);
    724
    725static umode_t ndtest_nvdimm_attr_visible(struct kobject *kobj,
    726					struct attribute *a, int n)
    727{
    728	struct device *dev = container_of(kobj, struct device, kobj);
    729	struct nvdimm *nvdimm = to_nvdimm(dev);
    730	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
    731
    732	if (a == &dev_attr_format1.attr && dimm->num_formats <= 1)
    733		return 0;
    734
    735	return a->mode;
    736}
    737
    738static ssize_t flags_show(struct device *dev,
    739			  struct device_attribute *attr, char *buf)
    740{
    741	struct nvdimm *nvdimm = to_nvdimm(dev);
    742	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
    743	struct seq_buf s;
    744	u64 flags;
    745
    746	flags = dimm->flags;
    747
    748	seq_buf_init(&s, buf, PAGE_SIZE);
    749	if (flags & PAPR_PMEM_UNARMED_MASK)
    750		seq_buf_printf(&s, "not_armed ");
    751
    752	if (flags & PAPR_PMEM_BAD_SHUTDOWN_MASK)
    753		seq_buf_printf(&s, "flush_fail ");
    754
    755	if (flags & PAPR_PMEM_BAD_RESTORE_MASK)
    756		seq_buf_printf(&s, "restore_fail ");
    757
    758	if (flags & PAPR_PMEM_SAVE_MASK)
    759		seq_buf_printf(&s, "save_fail ");
    760
    761	if (flags & PAPR_PMEM_SMART_EVENT_MASK)
    762		seq_buf_printf(&s, "smart_notify ");
    763
    764
    765	if (seq_buf_used(&s))
    766		seq_buf_printf(&s, "\n");
    767
    768	return seq_buf_used(&s);
    769}
    770static DEVICE_ATTR_RO(flags);
    771
    772static struct attribute *ndtest_nvdimm_attributes[] = {
    773	&dev_attr_nvdimm_show_handle.attr,
    774	&dev_attr_vendor.attr,
    775	&dev_attr_id.attr,
    776	&dev_attr_phys_id.attr,
    777	&dev_attr_subsystem_vendor.attr,
    778	&dev_attr_dirty_shutdown.attr,
    779	&dev_attr_formats.attr,
    780	&dev_attr_format.attr,
    781	&dev_attr_format1.attr,
    782	&dev_attr_flags.attr,
    783	NULL,
    784};
    785
    786static const struct attribute_group ndtest_nvdimm_attribute_group = {
    787	.name = "papr",
    788	.attrs = ndtest_nvdimm_attributes,
    789	.is_visible = ndtest_nvdimm_attr_visible,
    790};
    791
    792static const struct attribute_group *ndtest_nvdimm_attribute_groups[] = {
    793	&ndtest_nvdimm_attribute_group,
    794	NULL,
    795};
    796
    797static int ndtest_dimm_register(struct ndtest_priv *priv,
    798				struct ndtest_dimm *dimm, int id)
    799{
    800	struct device *dev = &priv->pdev.dev;
    801	unsigned long dimm_flags = dimm->flags;
    802
    803	if (dimm->num_formats > 1)
    804		set_bit(NDD_LABELING, &dimm_flags);
    805
    806	if (dimm->flags & PAPR_PMEM_UNARMED_MASK)
    807		set_bit(NDD_UNARMED, &dimm_flags);
    808
    809	dimm->nvdimm = nvdimm_create(priv->bus, dimm,
    810				    ndtest_nvdimm_attribute_groups, dimm_flags,
    811				    NDTEST_SCM_DIMM_CMD_MASK, 0, NULL);
    812	if (!dimm->nvdimm) {
    813		dev_err(dev, "Error creating DIMM object for %pOF\n", priv->dn);
    814		return -ENXIO;
    815	}
    816
    817	dimm->dev = device_create_with_groups(ndtest_dimm_class,
    818					     &priv->pdev.dev,
    819					     0, dimm, dimm_attribute_groups,
    820					     "test_dimm%d", id);
    821	if (!dimm->dev) {
    822		pr_err("Could not create dimm device attributes\n");
    823		return -ENOMEM;
    824	}
    825
    826	return 0;
    827}
    828
    829static int ndtest_nvdimm_init(struct ndtest_priv *p)
    830{
    831	struct ndtest_dimm *d;
    832	void *res;
    833	int i, id;
    834
    835	for (i = 0; i < p->config->dimm_count; i++) {
    836		d = &p->config->dimms[i];
    837		d->id = id = p->config->dimm_start + i;
    838		res = ndtest_alloc_resource(p, LABEL_SIZE, NULL);
    839		if (!res)
    840			return -ENOMEM;
    841
    842		d->label_area = res;
    843		sprintf(d->label_area, "label%d", id);
    844		d->config_size = LABEL_SIZE;
    845
    846		if (!ndtest_alloc_resource(p, d->size,
    847					   &p->dimm_dma[id]))
    848			return -ENOMEM;
    849
    850		if (!ndtest_alloc_resource(p, LABEL_SIZE,
    851					   &p->label_dma[id]))
    852			return -ENOMEM;
    853
    854		if (!ndtest_alloc_resource(p, LABEL_SIZE,
    855					   &p->dcr_dma[id]))
    856			return -ENOMEM;
    857
    858		d->address = p->dimm_dma[id];
    859
    860		ndtest_dimm_register(p, d, id);
    861	}
    862
    863	return 0;
    864}
    865
    866static ssize_t compatible_show(struct device *dev,
    867			       struct device_attribute *attr, char *buf)
    868{
    869	return sprintf(buf, "nvdimm_test");
    870}
    871static DEVICE_ATTR_RO(compatible);
    872
    873static struct attribute *of_node_attributes[] = {
    874	&dev_attr_compatible.attr,
    875	NULL
    876};
    877
    878static const struct attribute_group of_node_attribute_group = {
    879	.name = "of_node",
    880	.attrs = of_node_attributes,
    881};
    882
    883static const struct attribute_group *ndtest_attribute_groups[] = {
    884	&of_node_attribute_group,
    885	NULL,
    886};
    887
    888static int ndtest_bus_register(struct ndtest_priv *p)
    889{
    890	p->config = &bus_configs[p->pdev.id];
    891
    892	p->bus_desc.ndctl = ndtest_ctl;
    893	p->bus_desc.module = THIS_MODULE;
    894	p->bus_desc.provider_name = NULL;
    895	p->bus_desc.attr_groups = ndtest_attribute_groups;
    896
    897	p->bus = nvdimm_bus_register(&p->pdev.dev, &p->bus_desc);
    898	if (!p->bus) {
    899		dev_err(&p->pdev.dev, "Error creating nvdimm bus %pOF\n", p->dn);
    900		return -ENOMEM;
    901	}
    902
    903	return 0;
    904}
    905
    906static int ndtest_remove(struct platform_device *pdev)
    907{
    908	struct ndtest_priv *p = to_ndtest_priv(&pdev->dev);
    909
    910	nvdimm_bus_unregister(p->bus);
    911	return 0;
    912}
    913
    914static int ndtest_probe(struct platform_device *pdev)
    915{
    916	struct ndtest_priv *p;
    917	int rc;
    918
    919	p = to_ndtest_priv(&pdev->dev);
    920	if (ndtest_bus_register(p))
    921		return -ENOMEM;
    922
    923	p->dcr_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
    924				 sizeof(dma_addr_t), GFP_KERNEL);
    925	p->label_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
    926				   sizeof(dma_addr_t), GFP_KERNEL);
    927	p->dimm_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
    928				  sizeof(dma_addr_t), GFP_KERNEL);
    929
    930	rc = ndtest_nvdimm_init(p);
    931	if (rc)
    932		goto err;
    933
    934	rc = ndtest_init_regions(p);
    935	if (rc)
    936		goto err;
    937
    938	rc = devm_add_action_or_reset(&pdev->dev, put_dimms, p);
    939	if (rc)
    940		goto err;
    941
    942	platform_set_drvdata(pdev, p);
    943
    944	return 0;
    945
    946err:
    947	pr_err("%s:%d Failed nvdimm init\n", __func__, __LINE__);
    948	return rc;
    949}
    950
    951static const struct platform_device_id ndtest_id[] = {
    952	{ KBUILD_MODNAME },
    953	{ },
    954};
    955
    956static struct platform_driver ndtest_driver = {
    957	.probe = ndtest_probe,
    958	.remove = ndtest_remove,
    959	.driver = {
    960		.name = KBUILD_MODNAME,
    961	},
    962	.id_table = ndtest_id,
    963};
    964
    965static void ndtest_release(struct device *dev)
    966{
    967	struct ndtest_priv *p = to_ndtest_priv(dev);
    968
    969	kfree(p);
    970}
    971
    972static void cleanup_devices(void)
    973{
    974	int i;
    975
    976	for (i = 0; i < NUM_INSTANCES; i++)
    977		if (instances[i])
    978			platform_device_unregister(&instances[i]->pdev);
    979
    980	nfit_test_teardown();
    981
    982	if (ndtest_pool)
    983		gen_pool_destroy(ndtest_pool);
    984
    985
    986	if (ndtest_dimm_class)
    987		class_destroy(ndtest_dimm_class);
    988}
    989
    990static __init int ndtest_init(void)
    991{
    992	int rc, i;
    993
    994	pmem_test();
    995	libnvdimm_test();
    996	device_dax_test();
    997	dax_pmem_test();
    998
    999	nfit_test_setup(ndtest_resource_lookup, NULL);
   1000
   1001	ndtest_dimm_class = class_create(THIS_MODULE, "nfit_test_dimm");
   1002	if (IS_ERR(ndtest_dimm_class)) {
   1003		rc = PTR_ERR(ndtest_dimm_class);
   1004		goto err_register;
   1005	}
   1006
   1007	ndtest_pool = gen_pool_create(ilog2(SZ_4M), NUMA_NO_NODE);
   1008	if (!ndtest_pool) {
   1009		rc = -ENOMEM;
   1010		goto err_register;
   1011	}
   1012
   1013	if (gen_pool_add(ndtest_pool, SZ_4G, SZ_4G, NUMA_NO_NODE)) {
   1014		rc = -ENOMEM;
   1015		goto err_register;
   1016	}
   1017
   1018	/* Each instance can be taken as a bus, which can have multiple dimms */
   1019	for (i = 0; i < NUM_INSTANCES; i++) {
   1020		struct ndtest_priv *priv;
   1021		struct platform_device *pdev;
   1022
   1023		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
   1024		if (!priv) {
   1025			rc = -ENOMEM;
   1026			goto err_register;
   1027		}
   1028
   1029		INIT_LIST_HEAD(&priv->resources);
   1030		pdev = &priv->pdev;
   1031		pdev->name = KBUILD_MODNAME;
   1032		pdev->id = i;
   1033		pdev->dev.release = ndtest_release;
   1034		rc = platform_device_register(pdev);
   1035		if (rc) {
   1036			put_device(&pdev->dev);
   1037			goto err_register;
   1038		}
   1039		get_device(&pdev->dev);
   1040
   1041		instances[i] = priv;
   1042	}
   1043
   1044	rc = platform_driver_register(&ndtest_driver);
   1045	if (rc)
   1046		goto err_register;
   1047
   1048	return 0;
   1049
   1050err_register:
   1051	pr_err("Error registering platform device\n");
   1052	cleanup_devices();
   1053
   1054	return rc;
   1055}
   1056
   1057static __exit void ndtest_exit(void)
   1058{
   1059	cleanup_devices();
   1060	platform_driver_unregister(&ndtest_driver);
   1061}
   1062
   1063module_init(ndtest_init);
   1064module_exit(ndtest_exit);
   1065MODULE_LICENSE("GPL");
   1066MODULE_AUTHOR("IBM Corporation");