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

test_async_driver_probe.c (7786B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2014 Google, Inc.
      4 */
      5
      6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      7
      8#include <linux/delay.h>
      9#include <linux/init.h>
     10#include <linux/hrtimer.h>
     11#include <linux/module.h>
     12#include <linux/platform_device.h>
     13#include <linux/time.h>
     14#include <linux/numa.h>
     15#include <linux/nodemask.h>
     16#include <linux/topology.h>
     17
     18#define TEST_PROBE_DELAY	(5 * 1000)	/* 5 sec */
     19#define TEST_PROBE_THRESHOLD	(TEST_PROBE_DELAY / 2)
     20
     21static atomic_t warnings, errors, timeout, async_completed;
     22
     23static int test_probe(struct platform_device *pdev)
     24{
     25	struct device *dev = &pdev->dev;
     26
     27	/*
     28	 * Determine if we have hit the "timeout" limit for the test if we
     29	 * have then report it as an error, otherwise we wil sleep for the
     30	 * required amount of time and then report completion.
     31	 */
     32	if (atomic_read(&timeout)) {
     33		dev_err(dev, "async probe took too long\n");
     34		atomic_inc(&errors);
     35	} else {
     36		dev_dbg(&pdev->dev, "sleeping for %d msecs in probe\n",
     37			 TEST_PROBE_DELAY);
     38		msleep(TEST_PROBE_DELAY);
     39		dev_dbg(&pdev->dev, "done sleeping\n");
     40	}
     41
     42	/*
     43	 * Report NUMA mismatch if device node is set and we are not
     44	 * performing an async init on that node.
     45	 */
     46	if (dev->driver->probe_type == PROBE_PREFER_ASYNCHRONOUS) {
     47		if (IS_ENABLED(CONFIG_NUMA) &&
     48		    dev_to_node(dev) != numa_node_id()) {
     49			dev_warn(dev, "NUMA node mismatch %d != %d\n",
     50				 dev_to_node(dev), numa_node_id());
     51			atomic_inc(&warnings);
     52		}
     53
     54		atomic_inc(&async_completed);
     55	}
     56
     57	return 0;
     58}
     59
     60static struct platform_driver async_driver = {
     61	.driver = {
     62		.name = "test_async_driver",
     63		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
     64	},
     65	.probe = test_probe,
     66};
     67
     68static struct platform_driver sync_driver = {
     69	.driver = {
     70		.name = "test_sync_driver",
     71		.probe_type = PROBE_FORCE_SYNCHRONOUS,
     72	},
     73	.probe = test_probe,
     74};
     75
     76static struct platform_device *async_dev[NR_CPUS * 2];
     77static struct platform_device *sync_dev[2];
     78
     79static struct platform_device *
     80test_platform_device_register_node(char *name, int id, int nid)
     81{
     82	struct platform_device *pdev;
     83	int ret;
     84
     85	pdev = platform_device_alloc(name, id);
     86	if (!pdev)
     87		return NULL;
     88
     89	if (nid != NUMA_NO_NODE)
     90		set_dev_node(&pdev->dev, nid);
     91
     92	ret = platform_device_add(pdev);
     93	if (ret) {
     94		platform_device_put(pdev);
     95		return ERR_PTR(ret);
     96	}
     97
     98	return pdev;
     99
    100}
    101
    102static int __init test_async_probe_init(void)
    103{
    104	struct platform_device **pdev = NULL;
    105	int async_id = 0, sync_id = 0;
    106	unsigned long long duration;
    107	ktime_t calltime;
    108	int err, nid, cpu;
    109
    110	pr_info("registering first set of asynchronous devices...\n");
    111
    112	for_each_online_cpu(cpu) {
    113		nid = cpu_to_node(cpu);
    114		pdev = &async_dev[async_id];
    115		*pdev =	test_platform_device_register_node("test_async_driver",
    116							   async_id,
    117							   nid);
    118		if (IS_ERR(*pdev)) {
    119			err = PTR_ERR(*pdev);
    120			*pdev = NULL;
    121			pr_err("failed to create async_dev: %d\n", err);
    122			goto err_unregister_async_devs;
    123		}
    124
    125		async_id++;
    126	}
    127
    128	pr_info("registering asynchronous driver...\n");
    129	calltime = ktime_get();
    130	err = platform_driver_register(&async_driver);
    131	if (err) {
    132		pr_err("Failed to register async_driver: %d\n", err);
    133		goto err_unregister_async_devs;
    134	}
    135
    136	duration = (unsigned long long)ktime_ms_delta(ktime_get(), calltime);
    137	pr_info("registration took %lld msecs\n", duration);
    138	if (duration > TEST_PROBE_THRESHOLD) {
    139		pr_err("test failed: probe took too long\n");
    140		err = -ETIMEDOUT;
    141		goto err_unregister_async_driver;
    142	}
    143
    144	pr_info("registering second set of asynchronous devices...\n");
    145	calltime = ktime_get();
    146	for_each_online_cpu(cpu) {
    147		nid = cpu_to_node(cpu);
    148		pdev = &sync_dev[sync_id];
    149
    150		*pdev = test_platform_device_register_node("test_async_driver",
    151							   async_id,
    152							   nid);
    153		if (IS_ERR(*pdev)) {
    154			err = PTR_ERR(*pdev);
    155			*pdev = NULL;
    156			pr_err("failed to create async_dev: %d\n", err);
    157			goto err_unregister_async_driver;
    158		}
    159
    160		async_id++;
    161	}
    162
    163	duration = (unsigned long long)ktime_ms_delta(ktime_get(), calltime);
    164	dev_info(&(*pdev)->dev,
    165		 "registration took %lld msecs\n", duration);
    166	if (duration > TEST_PROBE_THRESHOLD) {
    167		dev_err(&(*pdev)->dev,
    168			"test failed: probe took too long\n");
    169		err = -ETIMEDOUT;
    170		goto err_unregister_async_driver;
    171	}
    172
    173
    174	pr_info("registering first synchronous device...\n");
    175	nid = cpu_to_node(cpu);
    176	pdev = &sync_dev[sync_id];
    177
    178	*pdev = test_platform_device_register_node("test_sync_driver",
    179						   sync_id,
    180						   NUMA_NO_NODE);
    181	if (IS_ERR(*pdev)) {
    182		err = PTR_ERR(*pdev);
    183		*pdev = NULL;
    184		pr_err("failed to create sync_dev: %d\n", err);
    185		goto err_unregister_async_driver;
    186	}
    187
    188	sync_id++;
    189
    190	pr_info("registering synchronous driver...\n");
    191	calltime = ktime_get();
    192	err = platform_driver_register(&sync_driver);
    193	if (err) {
    194		pr_err("Failed to register async_driver: %d\n", err);
    195		goto err_unregister_sync_devs;
    196	}
    197
    198	duration = (unsigned long long)ktime_ms_delta(ktime_get(), calltime);
    199	pr_info("registration took %lld msecs\n", duration);
    200	if (duration < TEST_PROBE_THRESHOLD) {
    201		dev_err(&(*pdev)->dev,
    202			"test failed: probe was too quick\n");
    203		err = -ETIMEDOUT;
    204		goto err_unregister_sync_driver;
    205	}
    206
    207	pr_info("registering second synchronous device...\n");
    208	pdev = &sync_dev[sync_id];
    209	calltime = ktime_get();
    210
    211	*pdev = test_platform_device_register_node("test_sync_driver",
    212						   sync_id,
    213						   NUMA_NO_NODE);
    214	if (IS_ERR(*pdev)) {
    215		err = PTR_ERR(*pdev);
    216		*pdev = NULL;
    217		pr_err("failed to create sync_dev: %d\n", err);
    218		goto err_unregister_sync_driver;
    219	}
    220
    221	sync_id++;
    222
    223	duration = (unsigned long long)ktime_ms_delta(ktime_get(), calltime);
    224	dev_info(&(*pdev)->dev,
    225		 "registration took %lld msecs\n", duration);
    226	if (duration < TEST_PROBE_THRESHOLD) {
    227		dev_err(&(*pdev)->dev,
    228			"test failed: probe was too quick\n");
    229		err = -ETIMEDOUT;
    230		goto err_unregister_sync_driver;
    231	}
    232
    233	/*
    234	 * The async events should have completed while we were taking care
    235	 * of the synchronous events. We will now terminate any outstanding
    236	 * asynchronous probe calls remaining by forcing timeout and remove
    237	 * the driver before we return which should force the flush of the
    238	 * pending asynchronous probe calls.
    239	 *
    240	 * Otherwise if they completed without errors or warnings then
    241	 * report successful completion.
    242	 */
    243	if (atomic_read(&async_completed) != async_id) {
    244		pr_err("async events still pending, forcing timeout\n");
    245		atomic_inc(&timeout);
    246		err = -ETIMEDOUT;
    247	} else if (!atomic_read(&errors) && !atomic_read(&warnings)) {
    248		pr_info("completed successfully\n");
    249		return 0;
    250	}
    251
    252err_unregister_sync_driver:
    253	platform_driver_unregister(&sync_driver);
    254err_unregister_sync_devs:
    255	while (sync_id--)
    256		platform_device_unregister(sync_dev[sync_id]);
    257err_unregister_async_driver:
    258	platform_driver_unregister(&async_driver);
    259err_unregister_async_devs:
    260	while (async_id--)
    261		platform_device_unregister(async_dev[async_id]);
    262
    263	/*
    264	 * If err is already set then count that as an additional error for
    265	 * the test. Otherwise we will report an invalid argument error and
    266	 * not count that as we should have reached here as a result of
    267	 * errors or warnings being reported by the probe routine.
    268	 */
    269	if (err)
    270		atomic_inc(&errors);
    271	else
    272		err = -EINVAL;
    273
    274	pr_err("Test failed with %d errors and %d warnings\n",
    275	       atomic_read(&errors), atomic_read(&warnings));
    276
    277	return err;
    278}
    279module_init(test_async_probe_init);
    280
    281static void __exit test_async_probe_exit(void)
    282{
    283	int id = 2;
    284
    285	platform_driver_unregister(&async_driver);
    286	platform_driver_unregister(&sync_driver);
    287
    288	while (id--)
    289		platform_device_unregister(sync_dev[id]);
    290
    291	id = NR_CPUS * 2;
    292	while (id--)
    293		platform_device_unregister(async_dev[id]);
    294}
    295module_exit(test_async_probe_exit);
    296
    297MODULE_DESCRIPTION("Test module for asynchronous driver probing");
    298MODULE_AUTHOR("Dmitry Torokhov <dtor@chromium.org>");
    299MODULE_LICENSE("GPL");