summaryrefslogtreecommitdiff
path: root/sys/arch/i386/pci
diff options
context:
space:
mode:
authorTom Cosgrove <tom@cvs.openbsd.org>2006-10-26 08:37:15 +0000
committerTom Cosgrove <tom@cvs.openbsd.org>2006-10-26 08:37:15 +0000
commitab1eba7ede322f6bbea366ce24d7ea103d703d23 (patch)
tree4d2dfbf5921c9d2b22b9d657e94f5bf932cdbf49 /sys/arch/i386/pci
parent6cd44b05b739b43cf54f14cbd77d1b935a9157b1 (diff)
Driver for the AMD Geode LX series processor security block.
Currently just uses the RNG; AES support to be added later. ok deraadt@
Diffstat (limited to 'sys/arch/i386/pci')
-rw-r--r--sys/arch/i386/pci/glxsb.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/sys/arch/i386/pci/glxsb.c b/sys/arch/i386/pci/glxsb.c
new file mode 100644
index 00000000000..077eec4b6dc
--- /dev/null
+++ b/sys/arch/i386/pci/glxsb.c
@@ -0,0 +1,184 @@
+/* $OpenBSD: glxsb.c,v 1.1 2006/10/26 08:37:14 tom Exp $ */
+
+/*
+ * Copyright (c) 2006 Tom Cosgrove <tom@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for the security block on the AMD Geode LX processors
+ * http://www.amd.com/files/connectivitysolutions/geode/geode_lx/33234d_lx_ds.pdf
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/types.h>
+#include <sys/timeout.h>
+
+#include <machine/bus.h>
+#include <machine/pctr.h>
+
+#include <dev/rndvar.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#define SB_GLD_MSR_CAP 0x58002000 /* RO - Capabilities */
+#define SB_GLD_MSR_CONFIG 0x58002001 /* RW - Master Config */
+#define SB_GLD_MSR_SMI 0x58002002 /* RW - SMI */
+#define SB_GLD_MSR_ERROR 0x58002003 /* RW - Error */
+#define SB_GLD_MSR_PM 0x58002004 /* RW - Power Mgmt */
+#define SB_GLD_MSR_DIAG 0x58002005 /* RW - Diagnostic */
+#define SB_GLD_MSR_CTRL 0x58002006 /* RW - Security Block Cntrl */
+
+ /* For GLD_MSR_CTRL: */
+#define SB_GMC_DIV0 0x0000 /* AES update divisor values */
+#define SB_GMC_DIV1 0x0001
+#define SB_GMC_DIV2 0x0002
+#define SB_GMC_DIV3 0x0003
+#define SB_GMC_DIV_MASK 0x0003
+#define SB_GMC_SBI 0x0004 /* AES swap bits */
+#define SB_GMC_SBY 0x0008 /* AES swap bytes */
+#define SB_GMC_TW 0x0010 /* Time write (EEPROM) */
+#define SB_GMC_T_SEL0 0x0000 /* RNG post-proc: none */
+#define SB_GMC_T_SEL1 0x0100 /* RNG post-proc: LFSR */
+#define SB_GMC_T_SEL2 0x0200 /* RNG post-proc: whitener */
+#define SB_GMC_T_SEL3 0x0300 /* RNG LFSR+whitener */
+#define SB_GMC_T_SEL_MASK 0x0300
+#define SB_GMC_T_NE 0x0400 /* Noise (generator) Enable */
+#define SB_GMC_T_TM 0x0800 /* RNG test mode */
+ /* (deterministic) */
+
+/* Security Block configuration/control registers (offsets from base) */
+
+#define SB_CTL_A 0x0000 /* RW - SB Control A */
+#define SB_CTL_B 0x0004 /* RW - SB Control B */
+#define SB_AES_INT 0x0008 /* RW - SB AES Interrupt */
+#define SB_SOURCE_A 0x0010 /* RW - Source A */
+#define SB_DEST_A 0x0014 /* RW - Destination A */
+#define SB_LENGTH_A 0x0018 /* RW - Length A */
+#define SB_SOURCE_B 0x0020 /* RW - Source B */
+#define SB_DEST_B 0x0024 /* RW - Destination B */
+#define SB_LENGTH_B 0x0028 /* RW - Length B */
+#define SB_WKEY_0 0x0030 /* WO - Writable Key 0 */
+#define SB_WKEY_1 0x0034 /* WO - Writable Key 1 */
+#define SB_WKEY_2 0x0038 /* WO - Writable Key 2 */
+#define SB_WKEY_3 0x003C /* WO - Writable Key 3 */
+#define SB_CBC_IV_0 0x0040 /* RW - CBC IV 0 */
+#define SB_CBC_IV_1 0x0044 /* RW - CBC IV 1 */
+#define SB_CBC_IV_2 0x0048 /* RW - CBC IV 2 */
+#define SB_CBC_IV_3 0x004C /* RW - CBC IV 3 */
+#define SB_RANDOM_NUM 0x0050 /* RW - Random Number */
+#define SB_RANDOM_NUM_STATUS 0x0054 /* RW - Random Number Status */
+#define SB_EEPROM_COMM 0x0800 /* RW - EEPROM Command */
+#define SB_EEPROM_ADDR 0x0804 /* RW - EEPROM Address */
+#define SB_EEPROM_DATA 0x0808 /* RW - EEPROM Data */
+#define SB_EEPROM_SEC_STATE 0x080C /* RW - EEPROM Security State */
+
+#define SB_RNS_TRNG_VALID 0x0001 /* in SB_RANDOM_NUM_STATUS */
+
+#define SB_MEM_SIZE 0x0810 /* Size of memory block */
+
+struct glxsb_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ struct timeout sc_to;
+};
+
+int glxsb_match(struct device *, void *, void *);
+void glxsb_attach(struct device *, struct device *, void *);
+void glxsb_rnd(void *);
+
+struct cfattach glxsb_ca = {
+ sizeof(struct glxsb_softc), glxsb_match, glxsb_attach
+};
+
+struct cfdriver glxsb_cd = {
+ NULL, "glxsb", DV_DULL
+};
+
+
+int
+glxsb_match(struct device *parent, void *match, void *aux)
+{
+ struct pci_attach_args *pa = aux;
+
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_GEODE_LX_CRYPTO)
+ return (1);
+
+ return (0);
+}
+
+void
+glxsb_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct glxsb_softc *sc = (void *) self;
+ struct pci_attach_args *pa = aux;
+ bus_addr_t membase;
+ bus_size_t memsize;
+ uint64_t msr;
+
+ msr = rdmsr(SB_GLD_MSR_CAP);
+ if ((msr & 0xFFFF00) != 0x130400) {
+ printf(": unknown ID 0x%x\n", (int) ((msr & 0xFFFF00) >> 16));
+ return;
+ }
+
+ /* printf(": revision %d", (int) (msr & 0xFF)); */
+
+ /* Map in the security block configuration/control registers */
+ if (pci_mapreg_map(pa, PCI_MAPREG_START,
+ PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_iot,
+ &sc->sc_ioh, &membase, &memsize, SB_MEM_SIZE)) {
+ printf(": can't find mem space\n");
+ return;
+ }
+
+ /*
+ * Configure the Security Block.
+ *
+ * We want to enable the noise generator (T_NE), and enable the
+ * linear feedback shift register and whitener post-processing
+ * (T_SEL = 3). Also ensure that test mode (deterministic values)
+ * is disabled.
+ */
+ msr = rdmsr(SB_GLD_MSR_CTRL);
+ msr &= ~(SB_GMC_T_TM | SB_GMC_T_SEL_MASK);
+ msr |= SB_GMC_T_NE | SB_GMC_T_SEL3;
+ wrmsr(SB_GLD_MSR_CTRL, msr);
+
+ /* Install a periodic collector for the "true" (AMD's word) RNG */
+ timeout_set(&sc->sc_to, glxsb_rnd, sc);
+ glxsb_rnd(sc);
+ printf(": RNG\n");
+}
+
+void
+glxsb_rnd(void *v)
+{
+ struct glxsb_softc *sc = v;
+ uint32_t status, value;
+ extern int hz;
+
+ status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SB_RANDOM_NUM_STATUS);
+ if (status & SB_RNS_TRNG_VALID) {
+ value = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SB_RANDOM_NUM);
+ add_true_randomness(value);
+ }
+
+ timeout_add(&sc->sc_to, (hz > 100) ? (hz / 100) : 1);
+}