* [patch 1/5] Remove existing hw_random implementation
2005-10-19 8:19 [patch 0/5] RNG cleanup & new drivers attempt #1 dsaxena
@ 2005-10-19 8:19 ` dsaxena
2005-10-19 8:19 ` [patch 2/5] Core HW RNG support dsaxena
` (4 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: dsaxena @ 2005-10-19 8:19 UTC (permalink / raw)
To: linux-kernel; +Cc: jgarzik, akpm, tony
[-- Attachment #1: rng/remove_current_rng.patch --]
[-- Type: text/plain, Size: 16432 bytes --]
Remove existing hw_random implementation so that it can be
replaced with a generic cross-architecture RNG codebase.
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
Index: linux-2.6-rng/drivers/char/Kconfig
===================================================================
--- linux-2.6-rng.orig/drivers/char/Kconfig
+++ linux-2.6-rng/drivers/char/Kconfig
@@ -644,21 +644,6 @@ config NWFLASH
If you're not sure, say N.
-config HW_RANDOM
- tristate "Intel/AMD/VIA HW Random Number Generator support"
- depends on (X86 || IA64) && PCI
- ---help---
- This driver provides kernel-side support for the Random Number
- Generator hardware found on Intel i8xx-based motherboards,
- AMD 76x-based motherboards, and Via Nehemiah CPUs.
-
- Provides a character driver, used to read() entropy data.
-
- To compile this driver as a module, choose M here: the
- module will be called hw_random.
-
- If unsure, say N.
-
config NVRAM
tristate "/dev/nvram support"
depends on ATARI || X86 || X86_64 || ARM || GENERIC_NVRAM
Index: linux-2.6-rng/drivers/char/Makefile
===================================================================
--- linux-2.6-rng.orig/drivers/char/Makefile
+++ linux-2.6-rng/drivers/char/Makefile
@@ -73,7 +73,6 @@ endif
obj-$(CONFIG_TOSHIBA) += toshiba.o
obj-$(CONFIG_I8K) += i8k.o
obj-$(CONFIG_DS1620) += ds1620.o
-obj-$(CONFIG_HW_RANDOM) += hw_random.o
obj-$(CONFIG_FTAPE) += ftape/
obj-$(CONFIG_COBALT_LCD) += lcd.o
obj-$(CONFIG_PPDEV) += ppdev.o
Index: linux-2.6-rng/drivers/char/hw_random.c
===================================================================
--- linux-2.6-rng.orig/drivers/char/hw_random.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
- (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
-
- derived from
-
- Hardware driver for the AMD 768 Random Number Generator (RNG)
- (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
-
- derived from
-
- Hardware driver for Intel i810 Random Number Generator (RNG)
- Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
- Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
-
- Please read Documentation/hw_random.txt for details on use.
-
- ----------------------------------------------------------
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
- */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/random.h>
-#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#ifdef __i386__
-#include <asm/msr.h>
-#include <asm/cpufeature.h>
-#endif
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-
-/*
- * core module and version information
- */
-#define RNG_VERSION "1.0.0"
-#define RNG_MODULE_NAME "hw_random"
-#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION
-#define PFX RNG_MODULE_NAME ": "
-
-
-/*
- * debugging macros
- */
-
-/* pr_debug() collapses to a no-op if DEBUG is not defined */
-#define DPRINTK(fmt, args...) pr_debug(PFX "%s: " fmt, __FUNCTION__ , ## args)
-
-
-#undef RNG_NDEBUG /* define to enable lightweight runtime checks */
-#ifdef RNG_NDEBUG
-#define assert(expr) \
- if(!(expr)) { \
- printk(KERN_DEBUG PFX "Assertion failed! %s,%s,%s," \
- "line=%d\n", #expr, __FILE__, __FUNCTION__, __LINE__); \
- }
-#else
-#define assert(expr)
-#endif
-
-#define RNG_MISCDEV_MINOR 183 /* official */
-
-static int rng_dev_open (struct inode *inode, struct file *filp);
-static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
- loff_t * offp);
-
-static int __init intel_init (struct pci_dev *dev);
-static void intel_cleanup(void);
-static unsigned int intel_data_present (void);
-static u32 intel_data_read (void);
-
-static int __init amd_init (struct pci_dev *dev);
-static void amd_cleanup(void);
-static unsigned int amd_data_present (void);
-static u32 amd_data_read (void);
-
-#ifdef __i386__
-static int __init via_init(struct pci_dev *dev);
-static void via_cleanup(void);
-static unsigned int via_data_present (void);
-static u32 via_data_read (void);
-#endif
-
-struct rng_operations {
- int (*init) (struct pci_dev *dev);
- void (*cleanup) (void);
- unsigned int (*data_present) (void);
- u32 (*data_read) (void);
- unsigned int n_bytes; /* number of bytes per ->data_read */
-};
-static struct rng_operations *rng_ops;
-
-static struct file_operations rng_chrdev_ops = {
- .owner = THIS_MODULE,
- .open = rng_dev_open,
- .read = rng_dev_read,
-};
-
-
-static struct miscdevice rng_miscdev = {
- RNG_MISCDEV_MINOR,
- RNG_MODULE_NAME,
- &rng_chrdev_ops,
-};
-
-enum {
- rng_hw_none,
- rng_hw_intel,
- rng_hw_amd,
- rng_hw_via,
-};
-
-static struct rng_operations rng_vendor_ops[] = {
- /* rng_hw_none */
- { },
-
- /* rng_hw_intel */
- { intel_init, intel_cleanup, intel_data_present,
- intel_data_read, 1 },
-
- /* rng_hw_amd */
- { amd_init, amd_cleanup, amd_data_present, amd_data_read, 4 },
-
-#ifdef __i386__
- /* rng_hw_via */
- { via_init, via_cleanup, via_data_present, via_data_read, 1 },
-#endif
-};
-
-/*
- * Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE. We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
- */
-static struct pci_device_id rng_pci_tbl[] = {
- { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
- { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
-
- { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
- { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
- { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
- { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
- { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
-
- { 0, }, /* terminate list */
-};
-MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
-
-
-/***********************************************************************
- *
- * Intel RNG operations
- *
- */
-
-/*
- * RNG registers (offsets from rng_mem)
- */
-#define INTEL_RNG_HW_STATUS 0
-#define INTEL_RNG_PRESENT 0x40
-#define INTEL_RNG_ENABLED 0x01
-#define INTEL_RNG_STATUS 1
-#define INTEL_RNG_DATA_PRESENT 0x01
-#define INTEL_RNG_DATA 2
-
-/*
- * Magic address at which Intel PCI bridges locate the RNG
- */
-#define INTEL_RNG_ADDR 0xFFBC015F
-#define INTEL_RNG_ADDR_LEN 3
-
-/* token to our ioremap'd RNG register area */
-static void __iomem *rng_mem;
-
-static inline u8 intel_hwstatus (void)
-{
- assert (rng_mem != NULL);
- return readb (rng_mem + INTEL_RNG_HW_STATUS);
-}
-
-static inline u8 intel_hwstatus_set (u8 hw_status)
-{
- assert (rng_mem != NULL);
- writeb (hw_status, rng_mem + INTEL_RNG_HW_STATUS);
- return intel_hwstatus ();
-}
-
-static unsigned int intel_data_present(void)
-{
- assert (rng_mem != NULL);
-
- return (readb (rng_mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT) ?
- 1 : 0;
-}
-
-static u32 intel_data_read(void)
-{
- assert (rng_mem != NULL);
-
- return readb (rng_mem + INTEL_RNG_DATA);
-}
-
-static int __init intel_init (struct pci_dev *dev)
-{
- int rc;
- u8 hw_status;
-
- DPRINTK ("ENTER\n");
-
- rng_mem = ioremap (INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
- if (rng_mem == NULL) {
- printk (KERN_ERR PFX "cannot ioremap RNG Memory\n");
- rc = -EBUSY;
- goto err_out;
- }
-
- /* Check for Intel 82802 */
- hw_status = intel_hwstatus ();
- if ((hw_status & INTEL_RNG_PRESENT) == 0) {
- printk (KERN_ERR PFX "RNG not detected\n");
- rc = -ENODEV;
- goto err_out_free_map;
- }
-
- /* turn RNG h/w on, if it's off */
- if ((hw_status & INTEL_RNG_ENABLED) == 0)
- hw_status = intel_hwstatus_set (hw_status | INTEL_RNG_ENABLED);
- if ((hw_status & INTEL_RNG_ENABLED) == 0) {
- printk (KERN_ERR PFX "cannot enable RNG, aborting\n");
- rc = -EIO;
- goto err_out_free_map;
- }
-
- DPRINTK ("EXIT, returning 0\n");
- return 0;
-
-err_out_free_map:
- iounmap (rng_mem);
- rng_mem = NULL;
-err_out:
- DPRINTK ("EXIT, returning %d\n", rc);
- return rc;
-}
-
-static void intel_cleanup(void)
-{
- u8 hw_status;
-
- hw_status = intel_hwstatus ();
- if (hw_status & INTEL_RNG_ENABLED)
- intel_hwstatus_set (hw_status & ~INTEL_RNG_ENABLED);
- else
- printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
- iounmap(rng_mem);
- rng_mem = NULL;
-}
-
-/***********************************************************************
- *
- * AMD RNG operations
- *
- */
-
-static u32 pmbase; /* PMxx I/O base */
-static struct pci_dev *amd_dev;
-
-static unsigned int amd_data_present (void)
-{
- return inl(pmbase + 0xF4) & 1;
-}
-
-
-static u32 amd_data_read (void)
-{
- return inl(pmbase + 0xF0);
-}
-
-static int __init amd_init (struct pci_dev *dev)
-{
- int rc;
- u8 rnen;
-
- DPRINTK ("ENTER\n");
-
- pci_read_config_dword(dev, 0x58, &pmbase);
-
- pmbase &= 0x0000FF00;
-
- if (pmbase == 0)
- {
- printk (KERN_ERR PFX "power management base not set\n");
- rc = -EIO;
- goto err_out;
- }
-
- pci_read_config_byte(dev, 0x40, &rnen);
- rnen |= (1 << 7); /* RNG on */
- pci_write_config_byte(dev, 0x40, rnen);
-
- pci_read_config_byte(dev, 0x41, &rnen);
- rnen |= (1 << 7); /* PMIO enable */
- pci_write_config_byte(dev, 0x41, rnen);
-
- pr_info( PFX "AMD768 system management I/O registers at 0x%X.\n",
- pmbase);
-
- amd_dev = dev;
-
- DPRINTK ("EXIT, returning 0\n");
- return 0;
-
-err_out:
- DPRINTK ("EXIT, returning %d\n", rc);
- return rc;
-}
-
-static void amd_cleanup(void)
-{
- u8 rnen;
-
- pci_read_config_byte(amd_dev, 0x40, &rnen);
- rnen &= ~(1 << 7); /* RNG off */
- pci_write_config_byte(amd_dev, 0x40, rnen);
-
- /* FIXME: twiddle pmio, also? */
-}
-
-#ifdef __i386__
-/***********************************************************************
- *
- * VIA RNG operations
- *
- */
-
-enum {
- VIA_STRFILT_CNT_SHIFT = 16,
- VIA_STRFILT_FAIL = (1 << 15),
- VIA_STRFILT_ENABLE = (1 << 14),
- VIA_RAWBITS_ENABLE = (1 << 13),
- VIA_RNG_ENABLE = (1 << 6),
- VIA_XSTORE_CNT_MASK = 0x0F,
-
- VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */
- VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */
- VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF,
- VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */
- VIA_RNG_CHUNK_2_MASK = 0xFFFF,
- VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */
- VIA_RNG_CHUNK_1_MASK = 0xFF,
-};
-
-static u32 via_rng_datum;
-
-/*
- * Investigate using the 'rep' prefix to obtain 32 bits of random data
- * in one insn. The upside is potentially better performance. The
- * downside is that the instruction becomes no longer atomic. Due to
- * this, just like familiar issues with /dev/random itself, the worst
- * case of a 'rep xstore' could potentially pause a cpu for an
- * unreasonably long time. In practice, this condition would likely
- * only occur when the hardware is failing. (or so we hope :))
- *
- * Another possible performance boost may come from simply buffering
- * until we have 4 bytes, thus returning a u32 at a time,
- * instead of the current u8-at-a-time.
- */
-
-static inline u32 xstore(u32 *addr, u32 edx_in)
-{
- u32 eax_out;
-
- asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
- :"=m"(*addr), "=a"(eax_out)
- :"D"(addr), "d"(edx_in));
-
- return eax_out;
-}
-
-static unsigned int via_data_present(void)
-{
- u32 bytes_out;
-
- /* We choose the recommended 1-byte-per-instruction RNG rate,
- * for greater randomness at the expense of speed. Larger
- * values 2, 4, or 8 bytes-per-instruction yield greater
- * speed at lesser randomness.
- *
- * If you change this to another VIA_CHUNK_n, you must also
- * change the ->n_bytes values in rng_vendor_ops[] tables.
- * VIA_CHUNK_8 requires further code changes.
- *
- * A copy of MSR_VIA_RNG is placed in eax_out when xstore
- * completes.
- */
- via_rng_datum = 0; /* paranoia, not really necessary */
- bytes_out = xstore(&via_rng_datum, VIA_RNG_CHUNK_1) & VIA_XSTORE_CNT_MASK;
- if (bytes_out == 0)
- return 0;
-
- return 1;
-}
-
-static u32 via_data_read(void)
-{
- return via_rng_datum;
-}
-
-static int __init via_init(struct pci_dev *dev)
-{
- u32 lo, hi, old_lo;
-
- /* Control the RNG via MSR. Tread lightly and pay very close
- * close attention to values written, as the reserved fields
- * are documented to be "undefined and unpredictable"; but it
- * does not say to write them as zero, so I make a guess that
- * we restore the values we find in the register.
- */
- rdmsr(MSR_VIA_RNG, lo, hi);
-
- old_lo = lo;
- lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT);
- lo &= ~VIA_XSTORE_CNT_MASK;
- lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
- lo |= VIA_RNG_ENABLE;
-
- if (lo != old_lo)
- wrmsr(MSR_VIA_RNG, lo, hi);
-
- /* perhaps-unnecessary sanity check; remove after testing if
- unneeded */
- rdmsr(MSR_VIA_RNG, lo, hi);
- if ((lo & VIA_RNG_ENABLE) == 0) {
- printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void via_cleanup(void)
-{
- /* do nothing */
-}
-#endif
-
-
-/***********************************************************************
- *
- * /dev/hwrandom character device handling (major 10, minor 183)
- *
- */
-
-static int rng_dev_open (struct inode *inode, struct file *filp)
-{
- /* enforce read-only access to this chrdev */
- if ((filp->f_mode & FMODE_READ) == 0)
- return -EINVAL;
- if (filp->f_mode & FMODE_WRITE)
- return -EINVAL;
-
- return 0;
-}
-
-
-static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
- loff_t * offp)
-{
- static DEFINE_SPINLOCK(rng_lock);
- unsigned int have_data;
- u32 data = 0;
- ssize_t ret = 0;
-
- while (size) {
- spin_lock(&rng_lock);
-
- have_data = 0;
- if (rng_ops->data_present()) {
- data = rng_ops->data_read();
- have_data = rng_ops->n_bytes;
- }
-
- spin_unlock (&rng_lock);
-
- while (have_data && size) {
- if (put_user((u8)data, buf++)) {
- ret = ret ? : -EFAULT;
- break;
- }
- size--;
- ret++;
- have_data--;
- data>>=8;
- }
-
- if (filp->f_flags & O_NONBLOCK)
- return ret ? : -EAGAIN;
-
- if(need_resched())
- schedule_timeout_interruptible(1);
- else
- udelay(200); /* FIXME: We could poll for 250uS ?? */
-
- if (signal_pending (current))
- return ret ? : -ERESTARTSYS;
- }
- return ret;
-}
-
-
-
-/*
- * rng_init_one - look for and attempt to init a single RNG
- */
-static int __init rng_init_one (struct pci_dev *dev)
-{
- int rc;
-
- DPRINTK ("ENTER\n");
-
- assert(rng_ops != NULL);
-
- rc = rng_ops->init(dev);
- if (rc)
- goto err_out;
-
- rc = misc_register (&rng_miscdev);
- if (rc) {
- printk (KERN_ERR PFX "misc device register failed\n");
- goto err_out_cleanup_hw;
- }
-
- DPRINTK ("EXIT, returning 0\n");
- return 0;
-
-err_out_cleanup_hw:
- rng_ops->cleanup();
-err_out:
- DPRINTK ("EXIT, returning %d\n", rc);
- return rc;
-}
-
-
-
-MODULE_AUTHOR("The Linux Kernel team");
-MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
-MODULE_LICENSE("GPL");
-
-
-/*
- * rng_init - initialize RNG module
- */
-static int __init rng_init (void)
-{
- int rc;
- struct pci_dev *pdev = NULL;
- const struct pci_device_id *ent;
-
- DPRINTK ("ENTER\n");
-
- /* Probe for Intel, AMD RNGs */
- for_each_pci_dev(pdev) {
- ent = pci_match_id(rng_pci_tbl, pdev);
- if (ent) {
- rng_ops = &rng_vendor_ops[ent->driver_data];
- goto match;
- }
- }
-
-#ifdef __i386__
- /* Probe for VIA RNG */
- if (cpu_has_xstore) {
- rng_ops = &rng_vendor_ops[rng_hw_via];
- pdev = NULL;
- goto match;
- }
-#endif
-
- DPRINTK ("EXIT, returning -ENODEV\n");
- return -ENODEV;
-
-match:
- rc = rng_init_one (pdev);
- if (rc)
- return rc;
-
- pr_info( RNG_DRIVER_NAME " loaded\n");
-
- DPRINTK ("EXIT, returning 0\n");
- return 0;
-}
-
-
-/*
- * rng_init - shutdown RNG module
- */
-static void __exit rng_cleanup (void)
-{
- DPRINTK ("ENTER\n");
-
- misc_deregister (&rng_miscdev);
-
- if (rng_ops->cleanup)
- rng_ops->cleanup();
-
- DPRINTK ("EXIT\n");
-}
-
-
-module_init (rng_init);
-module_exit (rng_cleanup);
--
Deepak Saxena - dsaxena@plexity.net - http://www.plexity.net
Even a stopped clock gives the right time twice a day.
^ permalink raw reply [flat|nested] 15+ messages in thread* [patch 2/5] Core HW RNG support
2005-10-19 8:19 [patch 0/5] RNG cleanup & new drivers attempt #1 dsaxena
2005-10-19 8:19 ` [patch 1/5] Remove existing hw_random implementation dsaxena
@ 2005-10-19 8:19 ` dsaxena
2005-10-24 10:45 ` Pavel Machek
2005-10-19 8:19 ` [patch 3/5] Intel IXP4xx driver dsaxena
` (3 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: dsaxena @ 2005-10-19 8:19 UTC (permalink / raw)
To: linux-kernel; +Cc: jgarzik, akpm, tony
[-- Attachment #1: rng/add_new_rng_core.patch --]
[-- Type: text/plain, Size: 7620 bytes --]
This patch adds support for the HW RNG core. The core code
simply implements the user space interface and calls HW-specific
function pointers to do the real data gathering. We do this
instead of having each driver re-implement the user space functionality
so we do not end up with a bunch of drivers replicating the exact
same 50 lines of code (see drivers/watchdog).
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
Index: linux-2.6-rng/drivers/char/Makefile
===================================================================
--- linux-2.6-rng.orig/drivers/char/Makefile
+++ linux-2.6-rng/drivers/char/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_AGP) += agp/
obj-$(CONFIG_DRM) += drm/
obj-$(CONFIG_PCMCIA) += pcmcia/
obj-$(CONFIG_IPMI_HANDLER) += ipmi/
+obj-$(CONFIG_RNG) += rng/
obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
obj-$(CONFIG_TCG_TPM) += tpm/
Index: linux-2.6-rng/drivers/char/rng/Makefile
===================================================================
--- /dev/null
+++ linux-2.6-rng/drivers/char/rng/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for HW Random Number Generator (RNG) device drivers.
+#
+
+obj-$(CONFIG_IXP4XX_RNG) += ixp4xx-rng.o core.o
+obj-$(CONFIG_X86_RNG) += x86-rng.o core.o
+obj-$(CONFIG_OMAP_RNG) += omap-rng.o core.o
+
Index: linux-2.6-rng/drivers/char/rng/core.c
===================================================================
--- /dev/null
+++ linux-2.6-rng/drivers/char/rng/core.c
@@ -0,0 +1,141 @@
+/*
+ * drivers/rng/core.c
+ *
+ * Core HW Random Number Generator (RNG) driver
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with parts from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/miscdevice.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+
+#include "rng.h"
+
+#define RNG_MISCDEV_MINOR 183 /* official */
+
+/*
+ * The one and only RNG device.
+ */
+static struct rng_operations *one_rng_to_rule_them_all;
+
+/***********************************************************************
+ *
+ * /dev/hwrandom character device handling (major 10, minor 183)
+ *
+ */
+static int rng_dev_open (struct inode *inode, struct file *filp)
+{
+ /* enforce read-only access to this chrdev */
+ if ((filp->f_mode & FMODE_READ) == 0)
+ return -EINVAL;
+ if (filp->f_mode & FMODE_WRITE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
+ loff_t * offp)
+{
+ static DEFINE_SPINLOCK(rng_lock);
+ unsigned int have_data;
+ u32 data = 0;
+ ssize_t ret = 0;
+
+ while (size) {
+ spin_lock(&rng_lock);
+
+ have_data = 0;
+ if (one_rng_to_rule_them_all->data_present())
+ have_data = one_rng_to_rule_them_all->data_read(&data);
+
+ spin_unlock (&rng_lock);
+
+ while (have_data && size) {
+ if (put_user((u8)data, buf++)) {
+ ret = ret ? : -EFAULT;
+ break;
+ }
+ size--;
+ ret++;
+ have_data--;
+ data>>=8;
+ }
+
+ if (filp->f_flags & O_NONBLOCK)
+ return ret ? : -EAGAIN;
+
+ if(need_resched())
+ schedule_timeout_interruptible(1);
+ else
+ udelay(200); /* FIXME: We could poll for 250uS ?? */
+
+ if (signal_pending (current))
+ return ret ? : -ERESTARTSYS;
+ }
+ return ret;
+}
+
+static struct file_operations rng_chrdev_ops = {
+ .owner = THIS_MODULE,
+ .open = rng_dev_open,
+ .read = rng_dev_read,
+};
+
+static struct miscdevice rng_miscdev = {
+ RNG_MISCDEV_MINOR,
+ "hw_random",
+ &rng_chrdev_ops,
+};
+
+int __init register_rng(struct rng_operations *rng_ops)
+{
+ int retval;
+
+ one_rng_to_rule_them_all = rng_ops;
+
+ retval = misc_register(&rng_miscdev);
+ if (retval)
+ printk(KERN_ERR "misc device register failed\n");
+
+ return retval;
+}
+
+void __exit rng_unregister(struct rng_operations *rng_ops)
+{
+ misc_deregister(&rng_miscdev);
+}
+
Index: linux-2.6-rng/drivers/char/rng/rng.h
===================================================================
--- /dev/null
+++ linux-2.6-rng/drivers/char/rng/rng.h
@@ -0,0 +1,24 @@
+/*
+ * driver/char/rng/rng.h
+ *
+ * RNG definitions shared by drivers
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+struct rng_operations {
+ /* Is there data in the FIFO? */
+ int (*data_present) (void);
+
+ /* Read data and return number of bytes read (up to 4) */
+ int (*data_read) (u32 *buffer);
+};
+
+int register_rng(struct rng_operations *);
+void unregister_rng(struct rng_operations *);
Index: linux-2.6-rng/drivers/char/rng/Kconfig
===================================================================
--- /dev/null
+++ linux-2.6-rng/drivers/char/rng/Kconfig
@@ -0,0 +1,46 @@
+#
+# Hardware Random Number Generator (RNG) configuration
+#
+# We only support one RNG at a time
+#
+
+config X86_RNG
+ tristate "Intel/AMD/VIA HW Random Number Generator support"
+ depends on (X86 || IA64) && PCI
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Intel i8xx-based motherboards,
+ AMD 76x-based motherboards, and Via Nehemiah CPUs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called x86-rng.
+
+ If unsure, say N.
+
+config IXP4XX_RNG
+ tristate "Intel IXP4xx NPU HW Random Number Generator support"
+ depends on ARCH_IXP4XX
+ ---help---
+ This driver provides kernel-side support for the Random
+ Number Generator hardware found on the Intel IXP4xx NPU.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ixp4xx-rng.
+
+config OMAP_RNG
+ tristate "OMAP Random Number Generator support"
+ depends on ARCH_OMAP16XX || ARCH_OMAP24XX
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on OMAP16xx and OMAP24xx multimedia
+ processors.
+
+ To compile this driver as a module, choose M here: the
+ module will be called omap-rng.
+
+ If unsure, say N.
+
+config RNG
+ bool
+ depends on IXP4XX_RNG || X86_RNG || OMAP_RNG
+ default y
Index: linux-2.6-rng/drivers/char/Kconfig
===================================================================
--- linux-2.6-rng.orig/drivers/char/Kconfig
+++ linux-2.6-rng/drivers/char/Kconfig
@@ -644,6 +644,8 @@ config NWFLASH
If you're not sure, say N.
+source "drivers/char/rng/Kconfig"
+
config NVRAM
tristate "/dev/nvram support"
depends on ATARI || X86 || X86_64 || ARM || GENERIC_NVRAM
--
Deepak Saxena - dsaxena@plexity.net - http://www.plexity.net
Even a stopped clock gives the right time twice a day.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [patch 2/5] Core HW RNG support
2005-10-19 8:19 ` [patch 2/5] Core HW RNG support dsaxena
@ 2005-10-24 10:45 ` Pavel Machek
0 siblings, 0 replies; 15+ messages in thread
From: Pavel Machek @ 2005-10-24 10:45 UTC (permalink / raw)
To: dsaxena; +Cc: linux-kernel, jgarzik, akpm, tony
Hi!
> This patch adds support for the HW RNG core. The core code
> simply implements the user space interface and calls HW-specific
> function pointers to do the real data gathering. We do this
> instead of having each driver re-implement the user space functionality
> so we do not end up with a bunch of drivers replicating the exact
> same 50 lines of code (see drivers/watchdog).
>
> Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
>
> Index: linux-2.6-rng/drivers/char/rng/Makefile
> ===================================================================
> --- /dev/null
> +++ linux-2.6-rng/drivers/char/rng/Makefile
Could we have it named drivers/char/random, or perhaps just
drivers/random?
Pavel
--
Thanks, Sharp!
^ permalink raw reply [flat|nested] 15+ messages in thread
* [patch 3/5] Intel IXP4xx driver
2005-10-19 8:19 [patch 0/5] RNG cleanup & new drivers attempt #1 dsaxena
2005-10-19 8:19 ` [patch 1/5] Remove existing hw_random implementation dsaxena
2005-10-19 8:19 ` [patch 2/5] Core HW RNG support dsaxena
@ 2005-10-19 8:19 ` dsaxena
2005-10-19 8:19 ` [patch 4/5] x86 driver dsaxena
` (2 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: dsaxena @ 2005-10-19 8:19 UTC (permalink / raw)
To: linux-kernel; +Cc: jgarzik, akpm, tony
[-- Attachment #1: rng/rng_ixp4xx_driver.patch --]
[-- Type: text/plain, Size: 2415 bytes --]
RNG driver for Intel IXP4xx NPU.
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
---
Tested and works.
Index: linux-2.6-rng/drivers/char/rng/ixp4xx-rng.c
===================================================================
--- /dev/null
+++ linux-2.6-rng/drivers/char/rng/ixp4xx-rng.c
@@ -0,0 +1,66 @@
+/*
+ * drivers/char/rng/ixp4xx-rng.c
+ *
+ * RNG driver for Intel IXP4xx family of NPUs
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include "rng.h"
+
+static u32* __iomem rng_base;
+
+static int ixp4xx_rng_data_present(void)
+{
+ return 1;
+}
+
+static int ixp4xx_rng_data_read(u32 *buffer)
+{
+ *buffer = __raw_readl(rng_base);
+
+ return 4;
+}
+
+struct rng_operations ixp4xx_rng_ops = {
+ .data_present = ixp4xx_rng_data_present,
+ .data_read = ixp4xx_rng_data_read,
+};
+
+static int __init ixp4xx_rng_init(void)
+{
+ rng_base = (u32* __iomem) ioremap(0x70002100, 4);
+ if (!rng_base) return -ENOMEM;
+
+ return register_rng(&ixp4xx_rng_ops);
+}
+
+static void __exit ixp4xx_rng_exit(void)
+{
+ unregister_rng(&ixp4xx_rng_ops);
+ iounmap(rng_base);
+}
+
+subsys_initcall(ixp4xx_rng_init);
+module_exit(ixp4xx_rng_exit);
+
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx");
+MODULE_LICENSE("GPL");
Index: linux-2.6-rng/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
===================================================================
--- linux-2.6-rng.orig/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
+++ linux-2.6-rng/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
@@ -36,6 +36,8 @@
*
* 0x6000000 0x00004000 ioremap'd QMgr
*
+ * 0x7000000 0x00004000 ioremap'd Public-Key Exchange Unit
+ *
* 0xC0000000 0x00001000 0xffbfe000 PCI CFG
*
* 0xC4000000 0x00001000 0xffbfd000 EXP CFG
--
Deepak Saxena - dsaxena@plexity.net - http://www.plexity.net
Even a stopped clock gives the right time twice a day.
^ permalink raw reply [flat|nested] 15+ messages in thread* [patch 4/5] x86 driver
2005-10-19 8:19 [patch 0/5] RNG cleanup & new drivers attempt #1 dsaxena
` (2 preceding siblings ...)
2005-10-19 8:19 ` [patch 3/5] Intel IXP4xx driver dsaxena
@ 2005-10-19 8:19 ` dsaxena
2005-10-19 8:19 ` [patch 5/5] TI OMAP driver dsaxena
2005-10-19 15:01 ` [patch 0/5] RNG cleanup & new drivers attempt #1 Jeff Garzik
5 siblings, 0 replies; 15+ messages in thread
From: dsaxena @ 2005-10-19 8:19 UTC (permalink / raw)
To: linux-kernel; +Cc: jgarzik, akpm, tony
[-- Attachment #1: rng/rng_x86_driver.patch --]
[-- Type: text/plain, Size: 13184 bytes --]
x86 RNG driver. This is basically the existing driver with
the user space interface bits ripped out.
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
---
This builds but I have not tested it yet as I do not have the needed HW.
Index: linux-2.6-rng/drivers/char/rng/x86-rng.c
===================================================================
--- /dev/null
+++ linux-2.6-rng/drivers/char/rng/x86-rng.c
@@ -0,0 +1,528 @@
+/*
+ * drivers/char/rng/x86.c
+ *
+ * RNG driver for Intel/AMD/VIA RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/miscdevice.h>
+#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include <asm/msr.h>
+#include <asm/cpufeature.h>
+
+#include <asm/io.h>
+
+#include "rng.h"
+
+/*
+ * debugging macros
+ */
+
+/* pr_debug() collapses to a no-op if DEBUG is not defined */
+#define DPRINTK(fmt, args...) pr_debug(PFX "%s: " fmt, __FUNCTION__ , ## args)
+
+#define RNG_VERSION "1.1.0"
+#define RNG_MODULE_NAME "x86-rng"
+#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION
+#define PFX RNG_MODULE_NAME ": "
+
+#undef RNG_NDEBUG /* define to enable lightweight runtime checks */
+#ifdef RNG_NDEBUG
+#define assert(expr) \
+ if(!(expr)) { \
+ printk(KERN_DEBUG PFX "Assertion failed! %s,%s,%s," \
+ "line=%d\n", #expr, __FILE__, __FUNCTION__, __LINE__); \
+ }
+#else
+#define assert(expr)
+#endif
+
+
+struct x86_rng_operations {
+ int (*init) (struct pci_dev *dev);
+ void (*cleanup) (void);
+ struct rng_operations rng_ops;
+};
+
+static struct x86_rng_operations *x86_rng_ops;
+
+static int __init intel_init (struct pci_dev *dev);
+static void intel_cleanup(void);
+static int intel_data_present (void);
+static int intel_data_read (u32 *data);
+
+static int __init amd_init (struct pci_dev *dev);
+static void amd_cleanup(void);
+static int amd_data_present (void);
+static int amd_data_read (u32 *data);
+
+#ifdef __i386__
+static int __init via_init(struct pci_dev *dev);
+static void via_cleanup(void);
+static int via_data_present (void);
+static int via_data_read (u32 *date);
+#endif
+
+enum {
+ rng_hw_none,
+ rng_hw_intel,
+ rng_hw_amd,
+ rng_hw_via,
+};
+
+static struct x86_rng_operations rng_vendor_ops[] = {
+ /* rng_hw_none */
+ { },
+
+ /* rng_hw_intel */
+ {
+ .init = intel_init,
+ .cleanup = intel_cleanup,
+ .rng_ops.data_present = intel_data_present,
+ .rng_ops.data_read = intel_data_read
+ },
+
+ /* rng_hw_amd */
+ {
+ .init = amd_init,
+ .cleanup = amd_cleanup,
+ .rng_ops.data_present = amd_data_present,
+ .rng_ops.data_read = amd_data_read
+ },
+
+#ifdef __i386__
+ /* rng_hw_via */
+ {
+ .init = via_init,
+ .cleanup = via_cleanup,
+ .rng_ops.data_present = via_data_present,
+ .rng_ops.data_read = via_data_read
+ }
+#endif
+};
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE. We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id rng_pci_tbl[] = {
+ { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
+ { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
+
+ { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+ { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+ { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+ { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+ { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+
+ { 0, }, /* terminate list */
+};
+MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
+
+/***********************************************************************
+ *
+ * Intel RNG operations
+ *
+ */
+
+/*
+ * RNG registers (offsets from rng_mem)
+ */
+#define INTEL_RNG_HW_STATUS 0
+#define INTEL_RNG_PRESENT 0x40
+#define INTEL_RNG_ENABLED 0x01
+#define INTEL_RNG_STATUS 1
+#define INTEL_RNG_DATA_PRESENT 0x01
+#define INTEL_RNG_DATA 2
+
+/*
+ * Magic address at which Intel PCI bridges locate the RNG
+ */
+#define INTEL_RNG_ADDR 0xFFBC015F
+#define INTEL_RNG_ADDR_LEN 3
+
+/* token to our ioremap'd RNG register area */
+static void __iomem *rng_mem;
+
+static inline u8 intel_hwstatus (void)
+{
+ assert (rng_mem != NULL);
+ return readb (rng_mem + INTEL_RNG_HW_STATUS);
+}
+
+static inline u8 intel_hwstatus_set (u8 hw_status)
+{
+ assert (rng_mem != NULL);
+ writeb (hw_status, rng_mem + INTEL_RNG_HW_STATUS);
+ return intel_hwstatus ();
+}
+
+static int intel_data_present(void)
+{
+ assert (rng_mem != NULL);
+
+ return (readb (rng_mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT) ?
+ 1 : 0;
+}
+
+static int intel_data_read(u32 *data)
+{
+ assert (rng_mem != NULL);
+
+ *data = readb (rng_mem + INTEL_RNG_DATA);
+
+ return 1;
+}
+
+static int __init intel_init (struct pci_dev *dev)
+{
+ int rc;
+ u8 hw_status;
+
+ DPRINTK ("ENTER\n");
+
+ rng_mem = ioremap (INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
+ if (rng_mem == NULL) {
+ printk (KERN_ERR PFX "cannot ioremap RNG Memory\n");
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ /* Check for Intel 82802 */
+ hw_status = intel_hwstatus ();
+ if ((hw_status & INTEL_RNG_PRESENT) == 0) {
+ printk (KERN_ERR PFX "RNG not detected\n");
+ rc = -ENODEV;
+ goto err_out_free_map;
+ }
+
+ /* turn RNG h/w on, if it's off */
+ if ((hw_status & INTEL_RNG_ENABLED) == 0)
+ hw_status = intel_hwstatus_set (hw_status | INTEL_RNG_ENABLED);
+ if ((hw_status & INTEL_RNG_ENABLED) == 0) {
+ printk (KERN_ERR PFX "cannot enable RNG, aborting\n");
+ rc = -EIO;
+ goto err_out_free_map;
+ }
+
+ DPRINTK ("EXIT, returning 0\n");
+ return 0;
+
+err_out_free_map:
+ iounmap (rng_mem);
+ rng_mem = NULL;
+err_out:
+ DPRINTK ("EXIT, returning %d\n", rc);
+ return rc;
+}
+
+static void intel_cleanup(void)
+{
+ u8 hw_status;
+
+ hw_status = intel_hwstatus ();
+ if (hw_status & INTEL_RNG_ENABLED)
+ intel_hwstatus_set (hw_status & ~INTEL_RNG_ENABLED);
+ else
+ printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
+ iounmap(rng_mem);
+ rng_mem = NULL;
+}
+
+/***********************************************************************
+ *
+ * AMD RNG operations
+ *
+ */
+
+static u32 pmbase; /* PMxx I/O base */
+static struct pci_dev *amd_dev;
+
+static int amd_data_present (void)
+{
+ return inl(pmbase + 0xF4) & 1;
+}
+
+
+static int amd_data_read (u32 *data)
+{
+ *data = inl(pmbase + 0xF0);
+
+ return 4;
+}
+
+static int __init amd_init (struct pci_dev *dev)
+{
+ int rc;
+ u8 rnen;
+
+ DPRINTK ("ENTER\n");
+
+ pci_read_config_dword(dev, 0x58, &pmbase);
+
+ pmbase &= 0x0000FF00;
+
+ if (pmbase == 0)
+ {
+ printk (KERN_ERR PFX "power management base not set\n");
+ rc = -EIO;
+ goto err_out;
+ }
+
+ pci_read_config_byte(dev, 0x40, &rnen);
+ rnen |= (1 << 7); /* RNG on */
+ pci_write_config_byte(dev, 0x40, rnen);
+
+ pci_read_config_byte(dev, 0x41, &rnen);
+ rnen |= (1 << 7); /* PMIO enable */
+ pci_write_config_byte(dev, 0x41, rnen);
+
+ pr_info( PFX "AMD768 system management I/O registers at 0x%X.\n",
+ pmbase);
+
+ amd_dev = dev;
+
+ DPRINTK ("EXIT, returning 0\n");
+ return 0;
+
+err_out:
+ DPRINTK ("EXIT, returning %d\n", rc);
+ return rc;
+}
+
+static void amd_cleanup(void)
+{
+ u8 rnen;
+
+ pci_read_config_byte(amd_dev, 0x40, &rnen);
+ rnen &= ~(1 << 7); /* RNG off */
+ pci_write_config_byte(amd_dev, 0x40, rnen);
+
+ /* FIXME: twiddle pmio, also? */
+}
+
+#ifdef __i386__
+/***********************************************************************
+ *
+ * VIA RNG operations
+ *
+ */
+
+enum {
+ VIA_STRFILT_CNT_SHIFT = 16,
+ VIA_STRFILT_FAIL = (1 << 15),
+ VIA_STRFILT_ENABLE = (1 << 14),
+ VIA_RAWBITS_ENABLE = (1 << 13),
+ VIA_RNG_ENABLE = (1 << 6),
+ VIA_XSTORE_CNT_MASK = 0x0F,
+
+ VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */
+ VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */
+ VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF,
+ VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */
+ VIA_RNG_CHUNK_2_MASK = 0xFFFF,
+ VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */
+ VIA_RNG_CHUNK_1_MASK = 0xFF,
+};
+
+static u32 via_rng_datum;
+
+/*
+ * Investigate using the 'rep' prefix to obtain 32 bits of random data
+ * in one insn. The upside is potentially better performance. The
+ * downside is that the instruction becomes no longer atomic. Due to
+ * this, just like familiar issues with /dev/random itself, the worst
+ * case of a 'rep xstore' could potentially pause a cpu for an
+ * unreasonably long time. In practice, this condition would likely
+ * only occur when the hardware is failing. (or so we hope :))
+ *
+ * Another possible performance boost may come from simply buffering
+ * until we have 4 bytes, thus returning a u32 at a time,
+ * instead of the current u8-at-a-time.
+ */
+
+static inline u32 xstore(u32 *addr, u32 edx_in)
+{
+ u32 eax_out;
+
+ asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
+ :"=m"(*addr), "=a"(eax_out)
+ :"D"(addr), "d"(edx_in));
+
+ return eax_out;
+}
+
+static int via_data_present(void)
+{
+ u32 bytes_out;
+
+ /* We choose the recommended 1-byte-per-instruction RNG rate,
+ * for greater randomness at the expense of speed. Larger
+ * values 2, 4, or 8 bytes-per-instruction yield greater
+ * speed at lesser randomness.
+ *
+ * If you change this to another VIA_CHUNK_n, you must also
+ * change the ->n_bytes values in rng_vendor_ops[] tables.
+ * VIA_CHUNK_8 requires further code changes.
+ *
+ * A copy of MSR_VIA_RNG is placed in eax_out when xstore
+ * completes.
+ */
+ via_rng_datum = 0; /* paranoia, not really necessary */
+ bytes_out = xstore(&via_rng_datum, VIA_RNG_CHUNK_1) & VIA_XSTORE_CNT_MASK;
+ if (bytes_out == 0)
+ return 0;
+
+ return 1;
+}
+
+static int via_data_read(u32 *data)
+{
+ *data = via_rng_datum;
+
+ return 1;
+}
+
+static int __init via_init(struct pci_dev *dev)
+{
+ u32 lo, hi, old_lo;
+
+ /* Control the RNG via MSR. Tread lightly and pay very close
+ * close attention to values written, as the reserved fields
+ * are documented to be "undefined and unpredictable"; but it
+ * does not say to write them as zero, so I make a guess that
+ * we restore the values we find in the register.
+ */
+ rdmsr(MSR_VIA_RNG, lo, hi);
+
+ old_lo = lo;
+ lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT);
+ lo &= ~VIA_XSTORE_CNT_MASK;
+ lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
+ lo |= VIA_RNG_ENABLE;
+
+ if (lo != old_lo)
+ wrmsr(MSR_VIA_RNG, lo, hi);
+
+ /* perhaps-unnecessary sanity check; remove after testing if
+ unneeded */
+ rdmsr(MSR_VIA_RNG, lo, hi);
+ if ((lo & VIA_RNG_ENABLE) == 0) {
+ printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void via_cleanup(void)
+{
+ /* do nothing */
+}
+#endif
+
+
+/*
+ * rng_init - initialize RNG module
+ */
+static int __init x86_rng_init(void)
+{
+ int rc;
+ struct pci_dev *pdev = NULL;
+ const struct pci_device_id *ent;
+
+ DPRINTK ("ENTER\n");
+
+ /* Probe for Intel, AMD RNGs */
+ for_each_pci_dev(pdev) {
+ ent = pci_match_id(rng_pci_tbl, pdev);
+ if (ent) {
+ x86_rng_ops = &rng_vendor_ops[ent->driver_data];
+ goto match;
+ }
+ }
+
+ /* Probe for VIA RNG */
+ if (cpu_has_xstore) {
+ x86_rng_ops = &rng_vendor_ops[rng_hw_via];
+ pdev = NULL;
+ goto match;
+ }
+
+ DPRINTK ("EXIT, returning -ENODEV\n");
+ return -ENODEV;
+
+match:
+ rc = x86_rng_ops->init(pdev);
+ if (rc)
+ return rc;
+
+ rc = register_rng(&x86_rng_ops->rng_ops);
+ if (rc) {
+ x86_rng_ops->cleanup();
+ return rc;
+ }
+
+ pr_info( RNG_DRIVER_NAME " loaded\n");
+
+ DPRINTK ("EXIT, returning 0\n");
+ return 0;
+}
+
+/*
+ * rng_init - shutdown RNG module
+ */
+static void __exit x86_rng_exit (void)
+{
+ DPRINTK ("ENTER\n");
+
+ unregister_rng(&x86_rng_ops->rng_ops);
+
+ if (x86_rng_ops->cleanup)
+ x86_rng_ops->cleanup();
+
+ DPRINTK ("EXIT\n");
+}
+
+subsys_initcall(x86_rng_init);
+module_exit(x86_rng_exit);
+
+MODULE_AUTHOR("The Linux Kernel team");
+MODULE_DESCRIPTION("H/W RNG driver for Intel/AMD/VIA chipsets");
+MODULE_LICENSE("GPL");
--
Deepak Saxena - dsaxena@plexity.net - http://www.plexity.net
Even a stopped clock gives the right time twice a day.
^ permalink raw reply [flat|nested] 15+ messages in thread* [patch 5/5] TI OMAP driver
2005-10-19 8:19 [patch 0/5] RNG cleanup & new drivers attempt #1 dsaxena
` (3 preceding siblings ...)
2005-10-19 8:19 ` [patch 4/5] x86 driver dsaxena
@ 2005-10-19 8:19 ` dsaxena
2005-10-19 9:36 ` Eric Piel
2005-10-19 15:01 ` [patch 0/5] RNG cleanup & new drivers attempt #1 Jeff Garzik
5 siblings, 1 reply; 15+ messages in thread
From: dsaxena @ 2005-10-19 8:19 UTC (permalink / raw)
To: linux-kernel; +Cc: jgarzik, akpm, tony
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: rng/rng_omap_driver.patch --]
[-- Type: text/plain, Size: 4964 bytes --]
This patch implements the OMAP RNG driver.
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
---
Builts but untested as I do not hardware.
Index: linux-omap-2.6/drivers/char/rng/omap-rng.c
===================================================================
--- /dev/null
+++ linux-omap-2.6/drivers/char/rng/omap-rng.c
@@ -0,0 +1,208 @@
+/*
+ * driver/char/rng/omap-rng.c
+ *
+ * RNG driver for TI OMAP CPU family
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Mostly based on original driver:
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * TODO:
+ *
+ * - Make status updated be interrupt driven so we don't poll
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/err.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/hardware/clock.h>
+
+#include "rng.h"
+
+#define RNG_OUT_REG 0x00 /* Output register */
+#define RNG_STAT_REG 0x04 /* Status register
+ [0] = STAT_BUSY */
+#define RNG_ALARM_REG 0x24 /* Alarm register
+ [7:0] = ALARM_COUNTER */
+#define RNG_CONFIG_REG 0x28 /* Configuration register
+ [11:6] = RESET_COUNT
+ [5:3] = RING2_DELAY
+ [2:0] = RING1_DELAY */
+#define RNG_REV_REG 0x3c /* Revision register
+ [7:0] = REV_NB */
+#define RNG_MASK_REG 0x40 /* Mask and reset register
+ [2] = IT_EN
+ [1] = SOFTRESET
+ [0] = AUTOIDLE */
+#define RNG_SYSSTATUS 0x44 /* System status
+ [0] = RESETDONE */
+
+static u32 __iomem *rng_base;
+static struct clk *rng_ick;
+static struct device *rng_dev;
+
+static u32 omap_rng_read_reg(int reg)
+{
+ return __raw_readl(rng_base + reg);
+}
+
+static void omap_rng_write_reg(int reg, u32 val)
+{
+ __raw_writel(val, rng_base + reg);
+}
+
+static int omap_rng_data_present(void)
+{
+ return omap_rng_read_reg(RNG_STAT_REG);
+}
+
+static int omap_rng_data_read(u32 *data)
+{
+ *data = omap_rng_read_reg(RNG_OUT_REG);
+
+ return 4;
+}
+
+static struct rng_operations omap_rng_ops = {
+ .data_present = omap_rng_data_present,
+ .data_read = omap_rng_data_read,
+};
+
+static int __init omap_rng_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res, *mem;
+ int ret;
+
+ /*
+ * A bit ugly, and it will never actually happen but there can
+ * be only one RNG and this catches any bork
+ */
+ if (rng_dev)
+ BUG();
+
+ if (cpu_is_omap24xx()) {
+ rng_ick = clk_get(NULL, "rng_ick");
+ if (IS_ERR(rng_ick)) {
+ dev_err(dev, "Could not get rng_ick\n");
+ ret = PTR_ERR(rng_ick);
+ return ret;
+ }
+ else {
+ clk_use(rng_ick);
+ }
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res)
+ return -ENOENT;
+
+ mem = request_mem_region(res->start, res->end - res->start + 1,
+ pdev->name);
+ if (mem == NULL)
+ return -EBUSY;
+
+ dev_set_drvdata(dev, mem);
+ rng_base = (u32 __iomem *)io_p2v(res->start);
+
+ ret = register_rng(&omap_rng_ops);
+ if (ret) {
+ release_resource(mem);
+ rng_base = NULL;
+ return ret;
+ }
+
+ dev_info(dev, "OMAP Random Number Generator ver. %02x\n",
+ omap_rng_read_reg(RNG_REV_REG));
+ omap_rng_write_reg(RNG_MASK_REG, 0x1);
+
+ rng_dev = dev;
+
+ return 0;
+}
+
+static int __exit omap_rng_remove(struct device *dev)
+{
+ struct resource *mem = dev_get_drvdata(dev);
+
+ unregister_rng(&omap_rng_ops);
+
+ omap_rng_write_reg(RNG_MASK_REG, 0x0);
+
+ if (cpu_is_omap24xx()) {
+ clk_unuse(rng_ick);
+ clk_put(rng_ick);
+ }
+
+ release_resource(mem);
+ rng_base = NULL;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
+{
+ omap_rng_write_reg(RNG_MASK_REG, 0x0);
+
+ return 0;
+}
+
+static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
+{
+ omap_rng_write_reg(RNG_MASK_REG, 0x1);
+
+ return 1;
+}
+
+#else
+
+#define omap_rng_suspend NULL
+#define omap_rng_resume NULL
+
+#endif
+
+
+static struct device_driver omap_rng_driver = {
+ .name = "omap_rng",
+ .bus = &platform_bus_type,
+ .probe = omap_rng_probe,
+ .remove = __exit_p(omap_rng_remove),
+ .suspend = omap_rng_suspend,
+ .resume = omap_rng_resume
+};
+
+static int __init omap_rng_init(void)
+{
+ if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
+ return -ENODEV;
+
+ return driver_register(&omap_rng_driver);
+}
+
+static void __exit omap_rng_exit(void)
+{
+ driver_unregister(&omap_rng_driver);
+}
+
+module_init(omap_rng_init);
+module_exit(omap_rng_exit);
+
+MODULE_AUTHOR("Deepak Saxena (and others)");
+MODULE_LICENSE("GPL");
--
Deepak Saxena - dsaxena@plexity.net - http://www.plexity.net
Even a stopped clock gives the right time twice a day.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [patch 5/5] TI OMAP driver
2005-10-19 8:19 ` [patch 5/5] TI OMAP driver dsaxena
@ 2005-10-19 9:36 ` Eric Piel
2005-10-19 9:44 ` Deepak Saxena
0 siblings, 1 reply; 15+ messages in thread
From: Eric Piel @ 2005-10-19 9:36 UTC (permalink / raw)
To: dsaxena; +Cc: linux-kernel, jgarzik, akpm, tony
10/19/2005 10:19 AM, dsaxena@plexity.net wrote/a écrit:
> This patch implements the OMAP RNG driver.
>
> Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
>
> ---
>
> Builts but untested as I do not hardware.
>
> Index: linux-omap-2.6/drivers/char/rng/omap-rng.c
> ===================================================================
> --- /dev/null
> +++ linux-omap-2.6/drivers/char/rng/omap-rng.c
> +#ifdef CONFIG_PM
> +
> +static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
> +{
> + omap_rng_write_reg(RNG_MASK_REG, 0x0);
> +
> + return 0;
> +}
> +
> +static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
> +{
> + omap_rng_write_reg(RNG_MASK_REG, 0x1);
> +
> + return 1;
> +}
Probably one of them should be called omap_rng_resume() ?
Eric
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [patch 5/5] TI OMAP driver
2005-10-19 9:36 ` Eric Piel
@ 2005-10-19 9:44 ` Deepak Saxena
2005-10-21 16:35 ` Tony Lindgren
0 siblings, 1 reply; 15+ messages in thread
From: Deepak Saxena @ 2005-10-19 9:44 UTC (permalink / raw)
To: Eric Piel; +Cc: linux-kernel
On Oct 19 2005, at 11:36, Eric Piel was caught saying:
> >+static int omap_rng_suspend(struct device *dev, pm_message_t message, u32
> >level)
> >+{
> >+ omap_rng_write_reg(RNG_MASK_REG, 0x0);
> >+
> >+ return 0;
> >+}
> >+
> >+static int omap_rng_suspend(struct device *dev, pm_message_t message, u32
> >level)
> >+{
> >+ omap_rng_write_reg(RNG_MASK_REG, 0x1);
> >+
> >+ return 1;
> >+}
> Probably one of them should be called omap_rng_resume() ?
>
> Eric
Tnx!
~Deepak
--
Deepak Saxena - dsaxena@plexity.net - http://www.plexity.net
When law and duty are one, united by religion, you never become fully
conscious, fully aware of yourself. You are always a little less than
an individual. - Frank Herbert
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [patch 5/5] TI OMAP driver
2005-10-19 9:44 ` Deepak Saxena
@ 2005-10-21 16:35 ` Tony Lindgren
2005-10-21 18:00 ` Tony Lindgren
0 siblings, 1 reply; 15+ messages in thread
From: Tony Lindgren @ 2005-10-21 16:35 UTC (permalink / raw)
To: Deepak Saxena; +Cc: Eric Piel, linux-kernel
* Deepak Saxena <dsaxena@plexity.net> [051019 12:45]:
> On Oct 19 2005, at 11:36, Eric Piel was caught saying:
> > >+static int omap_rng_suspend(struct device *dev, pm_message_t message, u32
> > >level)
> > >+{
> > >+ omap_rng_write_reg(RNG_MASK_REG, 0x0);
> > >+
> > >+ return 0;
> > >+}
> > >+
> > >+static int omap_rng_suspend(struct device *dev, pm_message_t message, u32
> > >level)
> > >+{
> > >+ omap_rng_write_reg(RNG_MASK_REG, 0x1);
> > >+
> > >+ return 1;
> > >+}
> > Probably one of them should be called omap_rng_resume() ?
> >
> > Eric
>
> Tnx!
>
> ~Deepak
Cool, works on OMAP OSK after renaming the function above.
Tony
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [patch 5/5] TI OMAP driver
2005-10-21 16:35 ` Tony Lindgren
@ 2005-10-21 18:00 ` Tony Lindgren
2005-10-21 19:10 ` Tony Lindgren
0 siblings, 1 reply; 15+ messages in thread
From: Tony Lindgren @ 2005-10-21 18:00 UTC (permalink / raw)
To: Deepak Saxena; +Cc: Eric Piel, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 382 bytes --]
Hi,
* Tony Lindgren <tony@atomide.com> [051021 19:38]:
>
> Cool, works on OMAP OSK after renaming the function above.
Looks like the following __iomem patch is needed for this to
work on OMAP H4.
At least these two compilers get confused without the following
patch:
arm-xscale-linux-gnu-gcc (GCC) 3.4.4
gcc version 3.4.3 (release) (CodeSourcery ARM Q1B 2005)
Regards,
Tony
[-- Attachment #2: patch-omap-rng-24xx --]
[-- Type: text/plain, Size: 288 bytes --]
--- a/drivers/char/rng/omap-rng.c
+++ b/drivers/char/rng/omap-rng.c
@@ -51,7 +51,7 @@
#define RNG_SYSSTATUS 0x44 /* System status
[0] = RESETDONE */
-static u32 __iomem *rng_base;
+static void __iomem *rng_base;
static struct clk *rng_ick;
static struct device *rng_dev;
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch 5/5] TI OMAP driver
2005-10-21 18:00 ` Tony Lindgren
@ 2005-10-21 19:10 ` Tony Lindgren
2005-10-23 18:12 ` Deepak Saxena
0 siblings, 1 reply; 15+ messages in thread
From: Tony Lindgren @ 2005-10-21 19:10 UTC (permalink / raw)
To: Deepak Saxena; +Cc: Eric Piel, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 659 bytes --]
* Tony Lindgren <tony@atomide.com> [051021 21:03]:
> Hi,
>
> * Tony Lindgren <tony@atomide.com> [051021 19:38]:
> >
> > Cool, works on OMAP OSK after renaming the function above.
>
> Looks like the following __iomem patch is needed for this to
> work on OMAP H4.
>
> At least these two compilers get confused without the following
> patch:
>
> arm-xscale-linux-gnu-gcc (GCC) 3.4.4
> gcc version 3.4.3 (release) (CodeSourcery ARM Q1B 2005)
Here's one more patch on top of my previous patch. Now it's
tested to work on 24xx too in addition to 16xx. The status
bit did not work on 24xx earlier, and looks like the status
bit is always ready on 16xx.
Tony
[-- Attachment #2: patch-omap-rng-24xx-works --]
[-- Type: text/plain, Size: 368 bytes --]
--- a/drivers/char/rng/omap-rng.c
+++ b/drivers/char/rng/omap-rng.c
@@ -65,9 +65,10 @@
__raw_writel(val, rng_base + reg);
}
+/* REVISIT: Does the status bit really work on 16xx? */
static int omap_rng_data_present(void)
{
- return omap_rng_read_reg(RNG_STAT_REG);
+ return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
}
static int omap_rng_data_read(u32 *data)
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [patch 5/5] TI OMAP driver
2005-10-21 19:10 ` Tony Lindgren
@ 2005-10-23 18:12 ` Deepak Saxena
0 siblings, 0 replies; 15+ messages in thread
From: Deepak Saxena @ 2005-10-23 18:12 UTC (permalink / raw)
To: Tony Lindgren; +Cc: Eric Piel, linux-kernel
On Oct 21 2005, at 22:10, Tony Lindgren was caught saying:
> * Tony Lindgren <tony@atomide.com> [051021 21:03]:
>
> Here's one more patch on top of my previous patch. Now it's
> tested to work on 24xx too in addition to 16xx. The status
> bit did not work on 24xx earlier, and looks like the status
> bit is always ready on 16xx.
>
> Tony
Tnx! I'll roll these in next time I post the patches.
~Deepak
--
Deepak Saxena - dsaxena@plexity.net - http://www.plexity.net
When law and duty are one, united by religion, you never become fully
conscious, fully aware of yourself. You are always a little less than
an individual. - Frank Herbert
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch 0/5] RNG cleanup & new drivers attempt #1
2005-10-19 8:19 [patch 0/5] RNG cleanup & new drivers attempt #1 dsaxena
` (4 preceding siblings ...)
2005-10-19 8:19 ` [patch 5/5] TI OMAP driver dsaxena
@ 2005-10-19 15:01 ` Jeff Garzik
2005-10-19 17:25 ` Deepak Saxena
5 siblings, 1 reply; 15+ messages in thread
From: Jeff Garzik @ 2005-10-19 15:01 UTC (permalink / raw)
To: dsaxena; +Cc: linux-kernel, jgarzik, akpm, tony
dsaxena@plexity.net wrote:
> - Allow a fastpath where we don't even have the user space portion
> and the HW drivers just feed the entropy pool directly. While
> this bypasses the FIPS tests and such, there are some applications
> where this is OK or where we really don't want the extra proccess
> context switching. This is specially true on ARM. I'll have to add
> IRQ driven support to the drivers to that, but that's trivial. There
> is also some HW (MPC8xxx for example) that does periodic self-tests
> in HW and lists itself as "FIPs-compliant" and will trigger an error if
> data should no longer be trusted and in that case doing a software
> test might also be undesirable. But...we should let the user decide
> at build time (or runtime?).
Not interesting in pursuing this path. This has been discussed
endlessly, check the archives.
We want the FIPS tests. Hardware (especially cheap hardware) is often
known to go haywire. Trusting hardware to do the FIPS tests is pretty
silly, since you're trusting the piece that might go haywire to tell you
its OK. RNGs have a history of suddenly providing non-random data, for
a variety of reasons (usually poor board wiring).
We also want the userspace daemon because that gives the sysadmin far
more control over how much entropy is added to the system. 99.9% of the
cases in the real world, we don't want the RNG pumping entropy into the
pool at full speed. That will likely pump in more data than a system
needs, chewing CPU. The admin can't even kill the daemon to reclaim his
CPU, if its all in-kernel.
It's not brain surgery, to concoct a method by which an interrupt-driven
device is used from userspace.
Jeff
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [patch 0/5] RNG cleanup & new drivers attempt #1
2005-10-19 15:01 ` [patch 0/5] RNG cleanup & new drivers attempt #1 Jeff Garzik
@ 2005-10-19 17:25 ` Deepak Saxena
0 siblings, 0 replies; 15+ messages in thread
From: Deepak Saxena @ 2005-10-19 17:25 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-kernel, jgarzik, akpm, tony
On Oct 19 2005, at 11:01, Jeff Garzik was caught saying:
> Not interesting in pursuing this path. This has been discussed
> endlessly, check the archives.
>
> We want the FIPS tests. Hardware (especially cheap hardware) is often
> known to go haywire. Trusting hardware to do the FIPS tests is pretty
> silly, since you're trusting the piece that might go haywire to tell you
> its OK. RNGs have a history of suddenly providing non-random data, for
> a variety of reasons (usually poor board wiring).
>
> We also want the userspace daemon because that gives the sysadmin far
> more control over how much entropy is added to the system. 99.9% of the
> cases in the real world, we don't want the RNG pumping entropy into the
> pool at full speed. That will likely pump in more data than a system
> needs, chewing CPU. The admin can't even kill the daemon to reclaim his
> CPU, if its all in-kernel.
OK, understood. But other than the fastpath idea, are you OK with
the direction I took with the code?
~Deepak
--
Deepak Saxena - dsaxena@plexity.net - http://www.plexity.net
When law and duty are one, united by religion, you never become fully
conscious, fully aware of yourself. You are always a little less than
an individual. - Frank Herbert
^ permalink raw reply [flat|nested] 15+ messages in thread