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

random.c (2572B)


      1/* Copyright (C) 2005 - 2008 Jeff Dike <jdike@{linux.intel,addtoit}.com> */
      2
      3/* Much of this ripped from drivers/char/hw_random.c, see there for other
      4 * copyright.
      5 *
      6 * This software may be used and distributed according to the terms
      7 * of the GNU General Public License, incorporated herein by reference.
      8 */
      9#include <linux/sched/signal.h>
     10#include <linux/module.h>
     11#include <linux/fs.h>
     12#include <linux/interrupt.h>
     13#include <linux/miscdevice.h>
     14#include <linux/hw_random.h>
     15#include <linux/delay.h>
     16#include <linux/uaccess.h>
     17#include <init.h>
     18#include <irq_kern.h>
     19#include <os.h>
     20
     21/*
     22 * core module information
     23 */
     24#define RNG_MODULE_NAME "hw_random"
     25
     26/* Changed at init time, in the non-modular case, and at module load
     27 * time, in the module case.  Presumably, the module subsystem
     28 * protects against a module being loaded twice at the same time.
     29 */
     30static int random_fd = -1;
     31static struct hwrng hwrng = { 0, };
     32static DECLARE_COMPLETION(have_data);
     33
     34static int rng_dev_read(struct hwrng *rng, void *buf, size_t max, bool block)
     35{
     36	int ret;
     37
     38	for (;;) {
     39		ret = os_read_file(random_fd, buf, max);
     40		if (block && ret == -EAGAIN) {
     41			add_sigio_fd(random_fd);
     42
     43			ret = wait_for_completion_killable(&have_data);
     44
     45			ignore_sigio_fd(random_fd);
     46			deactivate_fd(random_fd, RANDOM_IRQ);
     47
     48			if (ret < 0)
     49				break;
     50		} else {
     51			break;
     52		}
     53	}
     54
     55	return ret != -EAGAIN ? ret : 0;
     56}
     57
     58static irqreturn_t random_interrupt(int irq, void *data)
     59{
     60	complete(&have_data);
     61
     62	return IRQ_HANDLED;
     63}
     64
     65/*
     66 * rng_init - initialize RNG module
     67 */
     68static int __init rng_init (void)
     69{
     70	int err;
     71
     72	err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
     73	if (err < 0)
     74		goto out;
     75
     76	random_fd = err;
     77	err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
     78			     0, "random", NULL);
     79	if (err < 0)
     80		goto err_out_cleanup_hw;
     81
     82	sigio_broken(random_fd);
     83	hwrng.name = RNG_MODULE_NAME;
     84	hwrng.read = rng_dev_read;
     85	hwrng.quality = 1024;
     86
     87	err = hwrng_register(&hwrng);
     88	if (err) {
     89		pr_err(RNG_MODULE_NAME " registering failed (%d)\n", err);
     90		goto err_out_cleanup_hw;
     91	}
     92out:
     93	return err;
     94
     95err_out_cleanup_hw:
     96	os_close_file(random_fd);
     97	random_fd = -1;
     98	goto out;
     99}
    100
    101/*
    102 * rng_cleanup - shutdown RNG module
    103 */
    104
    105static void cleanup(void)
    106{
    107	free_irq_by_fd(random_fd);
    108	os_close_file(random_fd);
    109}
    110
    111static void __exit rng_cleanup(void)
    112{
    113	hwrng_unregister(&hwrng);
    114	os_close_file(random_fd);
    115}
    116
    117module_init (rng_init);
    118module_exit (rng_cleanup);
    119__uml_exitcall(cleanup);
    120
    121MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");
    122MODULE_LICENSE("GPL");