summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2003-03-14 22:05:46 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2003-03-14 22:05:46 +0000
commitf9a803ecd5bb3c006fc0db9606468cc2c4dfcf73 (patch)
treeb806c88c4b3a8f5426a3f551e23c022568dbce2c /sys/arch/i386
parent06797afd5c4ef3ff84d99df761a919d73292001b (diff)
Support for the VIA C3 Nehemiah on-cpu random number generator. This chip
will be shipping soon (we have nice prototypes). Written by toby.
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/i386/autoconf.c20
-rw-r--r--sys/arch/i386/i386/machdep.c109
-rw-r--r--sys/arch/i386/include/specialreg.h4
3 files changed, 130 insertions, 3 deletions
diff --git a/sys/arch/i386/i386/autoconf.c b/sys/arch/i386/i386/autoconf.c
index 0f4d7b4d28f..f8b7b94b095 100644
--- a/sys/arch/i386/i386/autoconf.c
+++ b/sys/arch/i386/i386/autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.c,v 1.45 2002/06/08 08:08:28 niklas Exp $ */
+/* $OpenBSD: autoconf.c,v 1.46 2003/03/14 22:05:43 deraadt Exp $ */
/* $NetBSD: autoconf.c,v 1.20 1996/05/03 19:41:56 christos Exp $ */
/*-
@@ -80,6 +80,13 @@ void diskconf(void);
*/
dev_t bootdev = 0; /* bootdevice, initialized in locore.s */
+/* Support for VIA C3 RNG */
+#ifdef I686_CPU
+extern struct timeout viac3_rnd_tmo;
+extern int viac3_rnd_present;
+void viac3_rnd(void *);
+#endif
+
/*
* Determine i/o configuration for a machine.
*/
@@ -112,6 +119,17 @@ cpu_configure()
/* Set up proc0's TSS and LDT (after the FPU is configured). */
i386_proc0_tss_ldt_init();
+
+#ifdef I686_CPU
+ /*
+ * At this point the RNG is running, and if FSXR is set we can
+ * use it. Here we setup a periodic timeout to collect the data.
+ */
+ if (viac3_rnd_present) {
+ timeout_set(&viac3_rnd_tmo, viac3_rnd, &viac3_rnd_tmo);
+ viac3_rnd(&viac3_rnd_tmo);
+ }
+#endif
}
/*
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 7971432b25a..d5948c4a099 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.221 2003/03/07 19:23:37 wilfried Exp $ */
+/* $OpenBSD: machdep.c,v 1.222 2003/03/14 22:05:43 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -129,6 +129,7 @@
#include <machine/specialreg.h>
#include <machine/biosvar.h>
+#include <dev/rndvar.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
#include <dev/ic/i8042reg.h>
@@ -314,6 +315,7 @@ void intel586_cpu_setup(const char *, int, int);
void intel686_cpu_setup(const char *, int, int);
char * intel686_cpu_name(int);
char * cyrix3_cpu_name(int, int);
+void viac3_rnd(void *);
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
static __inline u_char
@@ -993,6 +995,69 @@ winchip_cpu_setup(cpu_device, model, step)
#endif
}
+#if defined(I686_CPU)
+/*
+ * Note, the VIA C3 Nehemia provides 4 internal 8-byte buffers, which
+ * store random data, and can be accessed a lot quicker than waiting
+ * for new data to be generated. As we are using every 8th bit only
+ * due to whitening, we only pull off 4 bytes worth of data here, to
+ * help prevent stalling, and allow the RNG to generate new data in
+ * parallel with anything else going on.
+ *
+ * Note, due to some weirdness in the RNG, we need at last 7 bytes
+ * extra on the end of our buffer. Also, there is an outside chance
+ * that the VIA RNG can "wedge", as the generated bit-rate is variable.
+ * Since the RNG generates in excess of 21KB/s at it's worst, this is
+ * still significantly faster than the rate at which we are collecting
+ * from it. We could do all sorts of startup testing and things, but
+ * frankly, I don't really see the point.
+ *
+ * Adding to the whole confusion, in order to access the RNG, we need
+ * to have FXSR support enabled, and the correct FPU enable bits must
+ * be there to enable the FPU. It would be nice if all this mumbo-
+ * jumbo was not needed in order to use the RNG. Oh well, life does
+ * go on...
+ */
+#define VIAC3_RNG_BUFSIZ 16 /* 32bit words */
+struct timeout viac3_rnd_tmo;
+int viac3_rnd_present = 0;
+
+void
+viac3_rnd(void *v)
+{
+ struct timeout *tmo = v;
+ unsigned int *p, i, rv, creg0, creg4, len = VIAC3_RNG_BUFSIZ;
+ static int buffer[VIAC3_RNG_BUFSIZ + 2];
+ int s;
+
+ s = splhigh();
+ /* XXX - should not be needed, but we need FXSR & FPU set to access RNG */
+ creg0 = rcr0();
+ lcr0(creg0 & ~(CR0_EM|CR0_TS));
+ creg4 = rcr4();
+ lcr4(creg4 | CR4_OSFXSR);
+
+ /*
+ * Here we collect the random data from the VIA C3 RNG. We make
+ * sure that we turn on maximum whitening (%edx[0,1] == "11"), so
+ * that we get the best random data possible.
+ */
+ __asm __volatile ("rep;.byte 0x0F,0xA7,0xC0"
+ : "=a" (rv) : "d" (3), "D" (buffer), "c" (len*sizeof(int))
+ : "memory", "cc");
+
+ /* XXX - should not be needed */
+ lcr0(creg0);
+ lcr4(creg4);
+
+ for (i = 0, p = buffer; i < VIAC3_RNG_BUFSIZ; i++, p++)
+ add_true_randomness(*p);
+
+ timeout_add(tmo, (hz>100)?(hz/100):1);
+ splx(s);
+}
+#endif
+
void
cyrix3_cpu_setup(cpu_device, model, step)
const char *cpu_device;
@@ -1014,6 +1079,45 @@ cyrix3_cpu_setup(cpu_device, model, step)
cpu_feature &= ~CPUID_3DNOW;
}
break;
+
+ case 9:
+ if (step < 3)
+ break;
+
+ /*
+ * C3 Nehemia:
+ * First we check for extended feature flags, and then
+ * (if present) retrieve the ones at 0xC0000001. In this
+ * bit 2 tells us if the RNG is present. Bit 3 tells us
+ * if the RNG has been enabled. In order to use the RNG
+ * we need 3 things: We need an RNG, we need the FXSR bit
+ * enabled in cr4 (SSE/SSE2 stuff), and we need to have
+ * Bit 6 of MSR 0x110B set to 1 (the default), which will
+ * show up as bit 3 set here.
+ */
+ __asm __volatile("cpuid" /* Check for RNG */
+ : "=a" (val) : "a" (0xC0000000) : "cc");
+ if (val >= 0xC0000001) {
+ __asm __volatile("cpuid"
+ : "=d" (val) : "a" (0xC0000001) : "cc");
+ }
+
+ /* Stop here if no RNG */
+ if (!(val & 0x4))
+ break;
+
+ /* Enable RNG if disabled */
+ if (!(val & 0x8)) {
+ u_int64_t msreg;
+
+ msreg = rdmsr(0x110B);
+ msreg |= 0x40;
+ wrmsr(0x110B, msreg);
+ printf("Screwed with MSR 0x110B!\n");
+ }
+ viac3_rnd_present = 1;
+ printf("%s: RNG activated\n", cpu_device);
+ break;
}
#endif
}
@@ -1172,6 +1276,9 @@ cyrix3_cpu_name(model, step)
if (step < 8)
name = "C3 Ezra-T";
break;
+ case 9:
+ name = "C3 Nehemia";
+ break;
}
return name;
}
diff --git a/sys/arch/i386/include/specialreg.h b/sys/arch/i386/include/specialreg.h
index ceb6219f88d..a03e77360ef 100644
--- a/sys/arch/i386/include/specialreg.h
+++ b/sys/arch/i386/include/specialreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: specialreg.h,v 1.11 2001/12/04 17:47:24 mickey Exp $ */
+/* $OpenBSD: specialreg.h,v 1.12 2003/03/14 22:05:45 deraadt Exp $ */
/* $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $ */
/*-
@@ -85,6 +85,8 @@
#define CR4_MCE 0x00000040 /* machine check enable */
#define CR4_PGE 0x00000080 /* page global enable */
#define CR4_PCE 0x00000100 /* enable RDPMC instruction for all cpls */
+#define CR4_OSFXSR 0x00000200 /* enable SSE instructions (P6 & later) */
+#define CR4_OSXMMEXCPT 0x00000400 /* enable SSE instructions (P6 & later) */
/*
* CPUID "features" (and "extended features") bits: