diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2003-03-14 22:05:46 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2003-03-14 22:05:46 +0000 |
commit | f9a803ecd5bb3c006fc0db9606468cc2c4dfcf73 (patch) | |
tree | b806c88c4b3a8f5426a3f551e23c022568dbce2c /sys/arch/i386 | |
parent | 06797afd5c4ef3ff84d99df761a919d73292001b (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.c | 20 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 109 | ||||
-rw-r--r-- | sys/arch/i386/include/specialreg.h | 4 |
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: |