Convert the entropy pool framework from pseudo-callout-driven to soft interrupt driven operation. Add a polling mode of operation -- now we can ask hardware random number generators to top us up just when we need it (bcm2835_rng and amdpm converted as examples). Fix a stall noticed with repeated reads from /dev/random while testing.diff -r1.3 -r1.4 src/sys/arch/arm/broadcom/bcm2835_rng.c
(tls)
--- src/sys/arch/arm/broadcom/bcm2835_rng.c 2013/02/01 16:10:16 1.3
+++ src/sys/arch/arm/broadcom/bcm2835_rng.c 2013/06/13 00:55:01 1.4
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: bcm2835_rng.c,v 1.3 2013/02/01 16:10:16 skrll Exp $ */ | 1 | /* $NetBSD: bcm2835_rng.c,v 1.4 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jared D. McNeill | 8 | * by Jared D. McNeill | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,65 +20,66 @@ | @@ -20,65 +20,66 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: bcm2835_rng.c,v 1.3 2013/02/01 16:10:16 skrll Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: bcm2835_rng.c,v 1.4 2013/06/13 00:55:01 tls Exp $"); | |
34 | 34 | |||
35 | #include <sys/param.h> | 35 | #include <sys/param.h> | |
36 | #include <sys/systm.h> | 36 | #include <sys/systm.h> | |
37 | #include <sys/device.h> | 37 | #include <sys/device.h> | |
38 | #include <sys/kernel.h> | 38 | #include <sys/kernel.h> | |
39 | #include <sys/bus.h> | 39 | #include <sys/bus.h> | |
40 | #include <sys/rnd.h> | 40 | #include <sys/rnd.h> | |
41 | #include <sys/atomic.h> | |||
41 | 42 | |||
42 | #include <arm/broadcom/bcm_amba.h> | 43 | #include <arm/broadcom/bcm_amba.h> | |
43 | #include <arm/broadcom/bcm2835reg.h> | 44 | #include <arm/broadcom/bcm2835reg.h> | |
44 | #include <arm/broadcom/bcm2835_intr.h> | 45 | #include <arm/broadcom/bcm2835_intr.h> | |
45 | 46 | |||
46 | #define RNG_CTRL 0x00 | 47 | #define RNG_CTRL 0x00 | |
47 | #define RNG_CTRL_EN __BIT(0) | 48 | #define RNG_CTRL_EN __BIT(0) | |
48 | #define RNG_STATUS 0x04 | 49 | #define RNG_STATUS 0x04 | |
49 | #define RNG_STATUS_CNT_MASK __BITS(31,24) | 50 | #define RNG_STATUS_CNT_MASK __BITS(31,24) | |
50 | #define RNG_STATUS_CNT_SHIFT 24 | 51 | #define RNG_STATUS_CNT_SHIFT 24 | |
51 | #define RNG_DATA 0x08 | 52 | #define RNG_DATA 0x08 | |
52 | 53 | |||
53 | #define RNG_DATA_MAX 256 | 54 | #define RNG_DATA_MAX 256 | |
54 | 55 | |||
55 | struct bcm2835rng_softc { | 56 | struct bcm2835rng_softc { | |
56 | device_t sc_dev; | 57 | device_t sc_dev; | |
57 | 58 | |||
58 | bus_space_tag_t sc_iot; | 59 | bus_space_tag_t sc_iot; | |
59 | bus_space_handle_t sc_ioh; | 60 | bus_space_handle_t sc_ioh; | |
60 | 61 | |||
61 | krndsource_t sc_rnd; | 62 | krndsource_t sc_rnd; | |
62 | callout_t sc_tick; | 63 | ||
64 | kmutex_t sc_mutex; | |||
63 | 65 | |||
64 | uint32_t sc_data[RNG_DATA_MAX]; | 66 | uint32_t sc_data[RNG_DATA_MAX]; | |
65 | }; | 67 | }; | |
66 | 68 | |||
69 | static void bcmrng_get(size_t, void *); | |||
67 | static int bcmrng_match(device_t, cfdata_t, void *); | 70 | static int bcmrng_match(device_t, cfdata_t, void *); | |
68 | static void bcmrng_attach(device_t, device_t, void *); | 71 | static void bcmrng_attach(device_t, device_t, void *); | |
69 | 72 | |||
70 | static void bcmrng_tick(void *); | |||
71 | ||||
72 | CFATTACH_DECL_NEW(bcmrng_amba, sizeof(struct bcm2835rng_softc), | 73 | CFATTACH_DECL_NEW(bcmrng_amba, sizeof(struct bcm2835rng_softc), | |
73 | bcmrng_match, bcmrng_attach, NULL, NULL); | 74 | bcmrng_match, bcmrng_attach, NULL, NULL); | |
74 | 75 | |||
75 | /* ARGSUSED */ | 76 | /* ARGSUSED */ | |
76 | static int | 77 | static int | |
77 | bcmrng_match(device_t parent, cfdata_t match, void *aux) | 78 | bcmrng_match(device_t parent, cfdata_t match, void *aux) | |
78 | { | 79 | { | |
79 | struct amba_attach_args *aaa = aux; | 80 | struct amba_attach_args *aaa = aux; | |
80 | 81 | |||
81 | if (strcmp(aaa->aaa_name, "bcmrng") != 0) | 82 | if (strcmp(aaa->aaa_name, "bcmrng") != 0) | |
82 | return 0; | 83 | return 0; | |
83 | 84 | |||
84 | return 1; | 85 | return 1; | |
@@ -93,49 +94,57 @@ bcmrng_attach(device_t parent, device_t | @@ -93,49 +94,57 @@ bcmrng_attach(device_t parent, device_t | |||
93 | 94 | |||
94 | aprint_naive("\n"); | 95 | aprint_naive("\n"); | |
95 | aprint_normal(": RNG\n"); | 96 | aprint_normal(": RNG\n"); | |
96 | 97 | |||
97 | sc->sc_dev = self; | 98 | sc->sc_dev = self; | |
98 | sc->sc_iot = aaa->aaa_iot; | 99 | sc->sc_iot = aaa->aaa_iot; | |
99 | 100 | |||
100 | if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, BCM2835_RNG_SIZE, 0, | 101 | if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, BCM2835_RNG_SIZE, 0, | |
101 | &sc->sc_ioh)) { | 102 | &sc->sc_ioh)) { | |
102 | aprint_error_dev(sc->sc_dev, "unable to map device\n"); | 103 | aprint_error_dev(sc->sc_dev, "unable to map device\n"); | |
103 | return; | 104 | return; | |
104 | } | 105 | } | |
105 | 106 | |||
106 | rnd_attach_source(&sc->sc_rnd, device_xname(self), RND_TYPE_RNG, | 107 | mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM); | |
107 | RND_FLAG_NO_ESTIMATE); | |||
108 | 108 | |||
109 | callout_init(&sc->sc_tick, CALLOUT_MPSAFE); | 109 | rndsource_setcb(&sc->sc_rnd, bcmrng_get, sc); | |
110 | callout_setfunc(&sc->sc_tick, bcmrng_tick, sc); | 110 | rnd_attach_source(&sc->sc_rnd, device_xname(self), RND_TYPE_RNG, | |
111 | RND_FLAG_NO_ESTIMATE|RND_FLAG_HASCB); | |||
111 | 112 | |||
112 | /* discard initial numbers, broadcom says they are "less random" */ | 113 | /* discard initial numbers, broadcom says they are "less random" */ | |
113 | bus_space_write_4(sc->sc_iot, sc->sc_ioh, RNG_STATUS, 0x40000); | 114 | bus_space_write_4(sc->sc_iot, sc->sc_ioh, RNG_STATUS, 0x40000); | |
114 | 115 | |||
115 | /* enable rng */ | 116 | /* enable rng */ | |
116 | ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, RNG_CTRL); | 117 | ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, RNG_CTRL); | |
117 | ctrl |= RNG_CTRL_EN; | 118 | ctrl |= RNG_CTRL_EN; | |
118 | bus_space_write_4(sc->sc_iot, sc->sc_ioh, RNG_CTRL, ctrl); | 119 | bus_space_write_4(sc->sc_iot, sc->sc_ioh, RNG_CTRL, ctrl); | |
119 | ||||
120 | /* start timer */ | |||
121 | bcmrng_tick(sc); | |||
122 | } | 120 | } | |
123 | 121 | |||
124 | static void | 122 | static void | |
125 | bcmrng_tick(void *priv) | 123 | bcmrng_get(size_t bytes, void *priv) | |
126 | { | 124 | { | |
127 | struct bcm2835rng_softc *sc = priv; | 125 | struct bcm2835rng_softc *sc = priv; | |
128 | uint32_t status; | 126 | uint32_t status; | |
129 | int cnt; | 127 | int need = bytes, cnt; | |
130 | 128 | |||
131 | status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, RNG_STATUS); | 129 | mutex_spin_enter(&sc->sc_mutex); | |
132 | cnt = (status & RNG_STATUS_CNT_MASK) >> RNG_STATUS_CNT_SHIFT; | 130 | ||
133 | if (cnt > 0) { | 131 | printf("bcmrng: asked for %d bytes", (int)bytes); | |
134 | bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh, RNG_DATA, | 132 | ||
135 | sc->sc_data, cnt); | 133 | if (__predict_false(need < 1)) { | |
136 | rnd_add_data(&sc->sc_rnd, sc->sc_data, | 134 | return; | |
137 | cnt * 4, cnt * 4 * NBBY); | |||
138 | } | 135 | } | |
139 | 136 | |||
140 | callout_schedule(&sc->sc_tick, 1); | 137 | while (need > 0) { | |
138 | status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, RNG_STATUS); | |||
139 | cnt = (status & RNG_STATUS_CNT_MASK) >> RNG_STATUS_CNT_SHIFT; | |||
140 | if (cnt > 0) { | |||
141 | bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh, | |||
142 | RNG_DATA, sc->sc_data, cnt); | |||
143 | rnd_add_data(&sc->sc_rnd, sc->sc_data, | |||
144 | cnt * 4, cnt * 4 * NBBY); | |||
145 | } | |||
146 | ||||
147 | need -= cnt * 4; | |||
148 | } | |||
149 | mutex_spin_exit(&sc->sc_mutex); | |||
141 | } | 150 | } |
--- src/sys/dev/Attic/rndpseudo.c 2012/11/25 15:29:24 1.11
+++ src/sys/dev/Attic/rndpseudo.c 2013/06/13 00:55:01 1.12
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rndpseudo.c,v 1.11 2012/11/25 15:29:24 christos Exp $ */ | 1 | /* $NetBSD: rndpseudo.c,v 1.12 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. | 8 | * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,27 +20,27 @@ | @@ -20,27 +20,27 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.11 2012/11/25 15:29:24 christos Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.12 2013/06/13 00:55:01 tls Exp $"); | |
34 | 34 | |||
35 | #if defined(_KERNEL_OPT) | 35 | #if defined(_KERNEL_OPT) | |
36 | #include "opt_compat_netbsd.h" | 36 | #include "opt_compat_netbsd.h" | |
37 | #endif | 37 | #endif | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/ioctl.h> | 40 | #include <sys/ioctl.h> | |
41 | #include <sys/fcntl.h> | 41 | #include <sys/fcntl.h> | |
42 | #include <sys/file.h> | 42 | #include <sys/file.h> | |
43 | #include <sys/filedesc.h> | 43 | #include <sys/filedesc.h> | |
44 | #include <sys/select.h> | 44 | #include <sys/select.h> | |
45 | #include <sys/poll.h> | 45 | #include <sys/poll.h> | |
46 | #include <sys/kmem.h> | 46 | #include <sys/kmem.h> | |
@@ -209,26 +209,27 @@ rndopen(dev_t dev, int flag, int ifmt, | @@ -209,26 +209,27 @@ rndopen(dev_t dev, int flag, int ifmt, | |||
209 | case RND_DEV_RANDOM: | 209 | case RND_DEV_RANDOM: | |
210 | hard = 1; | 210 | hard = 1; | |
211 | break; | 211 | break; | |
212 | default: | 212 | default: | |
213 | return ENXIO; | 213 | return ENXIO; | |
214 | } | 214 | } | |
215 | ctx = pool_cache_get(rp_cpc, PR_WAITOK); | 215 | ctx = pool_cache_get(rp_cpc, PR_WAITOK); | |
216 | if ((error = fd_allocfile(&fp, &fd)) != 0) { | 216 | if ((error = fd_allocfile(&fp, &fd)) != 0) { | |
217 | pool_cache_put(rp_cpc, ctx); | 217 | pool_cache_put(rp_cpc, ctx); | |
218 | return error; | 218 | return error; | |
219 | } | 219 | } | |
220 | ctx->cprng = NULL; | 220 | ctx->cprng = NULL; | |
221 | ctx->hard = hard; | 221 | ctx->hard = hard; | |
222 | ctx->bytesonkey = 0; | |||
222 | mutex_init(&ctx->interlock, MUTEX_DEFAULT, IPL_NONE); | 223 | mutex_init(&ctx->interlock, MUTEX_DEFAULT, IPL_NONE); | |
223 | 224 | |||
224 | return fd_clone(fp, fd, flag, &rnd_fileops, ctx); | 225 | return fd_clone(fp, fd, flag, &rnd_fileops, ctx); | |
225 | } | 226 | } | |
226 | 227 | |||
227 | static void | 228 | static void | |
228 | rnd_alloc_cprng(rp_ctx_t *ctx) | 229 | rnd_alloc_cprng(rp_ctx_t *ctx) | |
229 | { | 230 | { | |
230 | char personalization_buf[64]; | 231 | char personalization_buf[64]; | |
231 | struct lwp *l = curlwp; | 232 | struct lwp *l = curlwp; | |
232 | int cflags = ctx->hard ? CPRNG_USE_CV : | 233 | int cflags = ctx->hard ? CPRNG_USE_CV : | |
233 | CPRNG_INIT_ANY|CPRNG_REKEY_ANY; | 234 | CPRNG_INIT_ANY|CPRNG_REKEY_ANY; | |
234 | 235 | |||
@@ -288,42 +289,57 @@ rnd_read(struct file * fp, off_t *offp, | @@ -288,42 +289,57 @@ rnd_read(struct file * fp, off_t *offp, | |||
288 | return EIO; | 289 | return EIO; | |
289 | } | 290 | } | |
290 | 291 | |||
291 | strength = cprng_strong_strength(cprng); | 292 | strength = cprng_strong_strength(cprng); | |
292 | ret = 0; | 293 | ret = 0; | |
293 | bf = pool_cache_get(rp_pc, PR_WAITOK); | 294 | bf = pool_cache_get(rp_pc, PR_WAITOK); | |
294 | while (uio->uio_resid > 0) { | 295 | while (uio->uio_resid > 0) { | |
295 | int n, nread, want; | 296 | int n, nread, want; | |
296 | 297 | |||
297 | want = MIN(RND_TEMP_BUFFER_SIZE, uio->uio_resid); | 298 | want = MIN(RND_TEMP_BUFFER_SIZE, uio->uio_resid); | |
298 | 299 | |||
299 | /* XXX is this _really_ what's wanted? */ | 300 | /* XXX is this _really_ what's wanted? */ | |
300 | if (ctx->hard) { | 301 | if (ctx->hard) { | |
302 | #ifdef RND_VERBOSE | |||
303 | printf("rnd: hard, want = %d, strength = %d, " | |||
304 | "bytesonkey = %d\n", (int)want, (int)strength, | |||
305 | (int)ctx->bytesonkey); | |||
306 | #endif | |||
301 | n = MIN(want, strength - ctx->bytesonkey); | 307 | n = MIN(want, strength - ctx->bytesonkey); | |
302 | if (n < 1) { | 308 | if (n < 1) { | |
303 | cprng_strong_deplete(cprng); | 309 | #ifdef RND_VERBOSE | |
304 | n = MIN(want, strength); | 310 | printf("rnd: BAD BAD BAD: n = %d, want = %d, " | |
305 | ctx->bytesonkey = 0; | 311 | "strength = %d, bytesonkey = %d\n", n, | |
306 | membar_producer(); | 312 | (int)want, (int)strength, | |
313 | (int)ctx->bytesonkey); | |||
314 | #endif | |||
307 | } | 315 | } | |
308 | } else { | 316 | } else { | |
309 | n = want; | 317 | n = want; | |
310 | } | 318 | } | |
311 | 319 | |||
312 | nread = cprng_strong(cprng, bf, n, | 320 | nread = cprng_strong(cprng, bf, n, | |
313 | (fp->f_flag & FNONBLOCK) ? FNONBLOCK : 0); | 321 | (fp->f_flag & FNONBLOCK) ? FNONBLOCK : 0); | |
314 | 322 | |||
315 | if (ctx->hard && nread > 0) { | 323 | if (ctx->hard && nread > 0) { | |
316 | atomic_add_int(&ctx->bytesonkey, nread); | 324 | if (atomic_add_int_nv(&ctx->bytesonkey, nread) >= | |
325 | strength) { | |||
326 | cprng_strong_deplete(cprng); | |||
327 | ctx->bytesonkey = 0; | |||
328 | membar_producer(); | |||
329 | } | |||
330 | #ifdef RND_VERBOSE | |||
331 | printf("rnd: new bytesonkey %d\n", ctx->bytesonkey); | |||
332 | #endif | |||
317 | } | 333 | } | |
318 | if (nread < 1) { | 334 | if (nread < 1) { | |
319 | if (fp->f_flag & FNONBLOCK) { | 335 | if (fp->f_flag & FNONBLOCK) { | |
320 | ret = EWOULDBLOCK; | 336 | ret = EWOULDBLOCK; | |
321 | } else { | 337 | } else { | |
322 | ret = EINTR; | 338 | ret = EINTR; | |
323 | } | 339 | } | |
324 | goto out; | 340 | goto out; | |
325 | } | 341 | } | |
326 | 342 | |||
327 | ret = uiomove((void *)bf, nread, uio); | 343 | ret = uiomove((void *)bf, nread, uio); | |
328 | if (ret != 0 || n < want) { | 344 | if (ret != 0 || n < want) { | |
329 | goto out; | 345 | goto out; |
--- src/sys/dev/pci/amdpm.c 2012/10/27 17:18:28 1.36
+++ src/sys/dev/pci/amdpm.c 2013/06/13 00:55:01 1.37
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: amdpm.c,v 1.36 2012/10/27 17:18:28 chs Exp $ */ | 1 | /* $NetBSD: amdpm.c,v 1.37 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Enami Tsugutomo. | 8 | * by Enami Tsugutomo. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,51 +20,53 @@ | @@ -20,51 +20,53 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: amdpm.c,v 1.36 2012/10/27 17:18:28 chs Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: amdpm.c,v 1.37 2013/06/13 00:55:01 tls Exp $"); | |
34 | 34 | |||
35 | #include "opt_amdpm.h" | 35 | #include "opt_amdpm.h" | |
36 | 36 | |||
37 | #include <sys/param.h> | 37 | #include <sys/param.h> | |
38 | #include <sys/systm.h> | 38 | #include <sys/systm.h> | |
39 | #include <sys/kernel.h> | 39 | #include <sys/kernel.h> | |
40 | #include <sys/device.h> | 40 | #include <sys/device.h> | |
41 | #include <sys/callout.h> | 41 | #include <sys/callout.h> | |
42 | #include <sys/rnd.h> | 42 | #include <sys/rnd.h> | |
43 | #include <sys/mutex.h> | |||
43 | 44 | |||
44 | #include <sys/bus.h> | 45 | #include <sys/bus.h> | |
45 | #include <dev/ic/acpipmtimer.h> | 46 | #include <dev/ic/acpipmtimer.h> | |
46 | 47 | |||
47 | #include <dev/i2c/i2cvar.h> | 48 | #include <dev/i2c/i2cvar.h> | |
48 | 49 | |||
49 | #include <dev/pci/pcivar.h> | 50 | #include <dev/pci/pcivar.h> | |
50 | #include <dev/pci/pcireg.h> | 51 | #include <dev/pci/pcireg.h> | |
51 | #include <dev/pci/pcidevs.h> | 52 | #include <dev/pci/pcidevs.h> | |
52 | 53 | |||
53 | #include <dev/pci/amdpmreg.h> | 54 | #include <dev/pci/amdpmreg.h> | |
54 | #include <dev/pci/amdpmvar.h> | 55 | #include <dev/pci/amdpmvar.h> | |
55 | #include <dev/pci/amdpm_smbusreg.h> | 56 | #include <dev/pci/amdpm_smbusreg.h> | |
56 | 57 | |||
57 | static void amdpm_rnd_callout(void *); | 58 | static void amdpm_rnd_callout(void *); | |
59 | static void amdpm_rnd_callout_locked(void *); | |||
58 | 60 | |||
59 | #ifdef AMDPM_RND_COUNTERS | 61 | #ifdef AMDPM_RND_COUNTERS | |
60 | #define AMDPM_RNDCNT_INCR(ev) (ev)->ev_count++ | 62 | #define AMDPM_RNDCNT_INCR(ev) (ev)->ev_count++ | |
61 | #endif | 63 | #endif | |
62 | 64 | |||
63 | static int | 65 | static int | |
64 | amdpm_match(device_t parent, cfdata_t match, void *aux) | 66 | amdpm_match(device_t parent, cfdata_t match, void *aux) | |
65 | { | 67 | { | |
66 | struct pci_attach_args *pa = aux; | 68 | struct pci_attach_args *pa = aux; | |
67 | 69 | |||
68 | if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD) { | 70 | if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD) { | |
69 | switch (PCI_PRODUCT(pa->pa_id)) { | 71 | switch (PCI_PRODUCT(pa->pa_id)) { | |
70 | case PCI_PRODUCT_AMD_PBC768_PMC: | 72 | case PCI_PRODUCT_AMD_PBC768_PMC: | |
@@ -73,26 +75,37 @@ amdpm_match(device_t parent, cfdata_t ma | @@ -73,26 +75,37 @@ amdpm_match(device_t parent, cfdata_t ma | |||
73 | } | 75 | } | |
74 | } | 76 | } | |
75 | if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA) { | 77 | if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA) { | |
76 | switch (PCI_PRODUCT(pa->pa_id)) { | 78 | switch (PCI_PRODUCT(pa->pa_id)) { | |
77 | case PCI_PRODUCT_NVIDIA_XBOX_SMBUS: | 79 | case PCI_PRODUCT_NVIDIA_XBOX_SMBUS: | |
78 | return (1); | 80 | return (1); | |
79 | } | 81 | } | |
80 | } | 82 | } | |
81 | 83 | |||
82 | return (0); | 84 | return (0); | |
83 | } | 85 | } | |
84 | 86 | |||
85 | static void | 87 | static void | |
88 | amdpm_rnd_get(size_t bytes, void *priv) | |||
89 | { | |||
90 | struct amdpm_softc *sc = priv; | |||
91 | ||||
92 | mutex_enter(&sc->sc_mutex); | |||
93 | sc->sc_rnd_need = bytes; | |||
94 | amdpm_rnd_callout_locked(sc); | |||
95 | mutex_exit(&sc->sc_mutex); | |||
96 | } | |||
97 | ||||
98 | static void | |||
86 | amdpm_attach(device_t parent, device_t self, void *aux) | 99 | amdpm_attach(device_t parent, device_t self, void *aux) | |
87 | { | 100 | { | |
88 | struct amdpm_softc *sc = device_private(self); | 101 | struct amdpm_softc *sc = device_private(self); | |
89 | struct pci_attach_args *pa = aux; | 102 | struct pci_attach_args *pa = aux; | |
90 | pcireg_t confreg, pmptrreg; | 103 | pcireg_t confreg, pmptrreg; | |
91 | u_int32_t pmreg; | 104 | u_int32_t pmreg; | |
92 | int i; | 105 | int i; | |
93 | 106 | |||
94 | pci_aprint_devinfo(pa, NULL); | 107 | pci_aprint_devinfo(pa, NULL); | |
95 | 108 | |||
96 | sc->sc_dev = self; | 109 | sc->sc_dev = self; | |
97 | 110 | |||
98 | if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NVIDIA_XBOX_SMBUS) | 111 | if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NVIDIA_XBOX_SMBUS) | |
@@ -141,96 +154,120 @@ amdpm_attach(device_t parent, device_t s | @@ -141,96 +154,120 @@ amdpm_attach(device_t parent, device_t s | |||
141 | AMDPM_PMSIZE, 0, &sc->sc_ioh)) { | 154 | AMDPM_PMSIZE, 0, &sc->sc_ioh)) { | |
142 | aprint_error_dev(self, "failed to map PMxx space\n"); | 155 | aprint_error_dev(self, "failed to map PMxx space\n"); | |
143 | return; | 156 | return; | |
144 | } | 157 | } | |
145 | } | 158 | } | |
146 | 159 | |||
147 | /* don't attach a timecounter on nforce boards */ | 160 | /* don't attach a timecounter on nforce boards */ | |
148 | if ((confreg & AMDPM_TMRRST) == 0 && (confreg & AMDPM_STOPTMR) == 0 && | 161 | if ((confreg & AMDPM_TMRRST) == 0 && (confreg & AMDPM_STOPTMR) == 0 && | |
149 | !sc->sc_nforce) { | 162 | !sc->sc_nforce) { | |
150 | acpipmtimer_attach(self, sc->sc_iot, sc->sc_ioh, | 163 | acpipmtimer_attach(self, sc->sc_iot, sc->sc_ioh, | |
151 | AMDPM_TMR, ((confreg & AMDPM_TMR32) ? ACPIPMT_32BIT : 0)); | 164 | AMDPM_TMR, ((confreg & AMDPM_TMR32) ? ACPIPMT_32BIT : 0)); | |
152 | } | 165 | } | |
153 | 166 | |||
167 | /* XXX this mutex is IPL_VM because it can be taken by rnd_getmore() */ | |||
168 | mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM); | |||
169 | ||||
154 | /* try to attach devices on the smbus */ | 170 | /* try to attach devices on the smbus */ | |
155 | if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC8111_ACPI || | 171 | if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC8111_ACPI || | |
156 | PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC768_PMC || | 172 | PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC768_PMC || | |
157 | sc->sc_nforce) { | 173 | sc->sc_nforce) { | |
158 | amdpm_smbus_attach(sc); | 174 | amdpm_smbus_attach(sc); | |
159 | } | 175 | } | |
160 | 176 | |||
161 | if (confreg & AMDPM_RNGEN) { | 177 | if (confreg & AMDPM_RNGEN) { | |
162 | /* Check to see if we can read data from the RNG. */ | 178 | /* Check to see if we can read data from the RNG. */ | |
163 | (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, | 179 | (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, | |
164 | AMDPM_RNGDATA); | 180 | AMDPM_RNGDATA); | |
165 | for (i = 0; i < 1000; i++) { | 181 | for (i = 0; i < 1000; i++) { | |
166 | pmreg = bus_space_read_4(sc->sc_iot, | 182 | pmreg = bus_space_read_4(sc->sc_iot, | |
167 | sc->sc_ioh, AMDPM_RNGSTAT); | 183 | sc->sc_ioh, AMDPM_RNGSTAT); | |
168 | if (pmreg & AMDPM_RNGDONE) | 184 | if (pmreg & AMDPM_RNGDONE) | |
169 | break; | 185 | break; | |
170 | delay(1); | 186 | delay(1); | |
171 | } | 187 | } | |
172 | if ((pmreg & AMDPM_RNGDONE) != 0) { | 188 | if ((pmreg & AMDPM_RNGDONE) != 0) { | |
173 | aprint_normal_dev(self, "" | 189 | aprint_normal_dev(self, "" | |
174 | "random number generator enabled (apprx. %dms)\n", | 190 | "random number generator enabled (apprx. %dms)\n", | |
175 | i); | 191 | i); | |
176 | callout_init(&sc->sc_rnd_ch, 0); | 192 | callout_init(&sc->sc_rnd_ch, CALLOUT_MPSAFE); | |
193 | rndsource_setcb(&sc->sc_rnd_source, | |||
194 | amdpm_rnd_get, sc); | |||
177 | rnd_attach_source(&sc->sc_rnd_source, | 195 | rnd_attach_source(&sc->sc_rnd_source, | |
178 | device_xname(self), RND_TYPE_RNG, | 196 | device_xname(self), RND_TYPE_RNG, | |
179 | /* | 197 | /* | |
180 | * XXX Careful! The use of RND_FLAG_NO_ESTIMATE | 198 | * XXX Careful! The use of RND_FLAG_NO_ESTIMATE | |
181 | * XXX here is unobvious: we later feed raw bits | 199 | * XXX here is unobvious: we later feed raw bits | |
182 | * XXX into the "entropy pool" with rnd_add_data, | 200 | * XXX into the "entropy pool" with rnd_add_data, | |
183 | * XXX explicitly supplying an entropy estimate. | 201 | * XXX explicitly supplying an entropy estimate. | |
184 | * XXX In this context, NO_ESTIMATE serves only | 202 | * XXX In this context, NO_ESTIMATE serves only | |
185 | * XXX to prevent rnd_add_data from trying to | 203 | * XXX to prevent rnd_add_data from trying to | |
186 | * XXX use the *time at which we added the data* | 204 | * XXX use the *time at which we added the data* | |
187 | * XXX as entropy, which is not a good idea since | 205 | * XXX as entropy, which is not a good idea since | |
188 | * XXX we add data periodically from a callout. | 206 | * XXX we add data periodically from a callout. | |
189 | */ | 207 | */ | |
190 | RND_FLAG_NO_ESTIMATE); | 208 | RND_FLAG_NO_ESTIMATE|RND_FLAG_HASCB); | |
191 | #ifdef AMDPM_RND_COUNTERS | 209 | #ifdef AMDPM_RND_COUNTERS | |
192 | evcnt_attach_dynamic(&sc->sc_rnd_hits, EVCNT_TYPE_MISC, | 210 | evcnt_attach_dynamic(&sc->sc_rnd_hits, EVCNT_TYPE_MISC, | |
193 | NULL, device_xname(self), "rnd hits"); | 211 | NULL, device_xname(self), "rnd hits"); | |
194 | evcnt_attach_dynamic(&sc->sc_rnd_miss, EVCNT_TYPE_MISC, | 212 | evcnt_attach_dynamic(&sc->sc_rnd_miss, EVCNT_TYPE_MISC, | |
195 | NULL, device_xname(self), "rnd miss"); | 213 | NULL, device_xname(self), "rnd miss"); | |
196 | for (i = 0; i < 256; i++) { | 214 | for (i = 0; i < 256; i++) { | |
197 | evcnt_attach_dynamic(&sc->sc_rnd_data[i], | 215 | evcnt_attach_dynamic(&sc->sc_rnd_data[i], | |
198 | EVCNT_TYPE_MISC, NULL, device_xname(self), | 216 | EVCNT_TYPE_MISC, NULL, device_xname(self), | |
199 | "rnd data"); | 217 | "rnd data"); | |
200 | } | 218 | } | |
201 | #endif | 219 | #endif | |
220 | sc->sc_rnd_need = RND_POOLBITS / NBBY; | |||
202 | amdpm_rnd_callout(sc); | 221 | amdpm_rnd_callout(sc); | |
203 | } | 222 | } | |
204 | } | 223 | } | |
205 | } | 224 | } | |
206 | 225 | |||
207 | CFATTACH_DECL_NEW(amdpm, sizeof(struct amdpm_softc), | 226 | CFATTACH_DECL_NEW(amdpm, sizeof(struct amdpm_softc), | |
208 | amdpm_match, amdpm_attach, NULL, NULL); | 227 | amdpm_match, amdpm_attach, NULL, NULL); | |
209 | 228 | |||
210 | static void | 229 | static void | |
211 | amdpm_rnd_callout(void *v) | 230 | amdpm_rnd_callout_locked(void *v) | |
212 | { | 231 | { | |
213 | struct amdpm_softc *sc = v; | 232 | struct amdpm_softc *sc = v; | |
214 | u_int32_t rngreg; | 233 | u_int32_t rngreg; | |
215 | #ifdef AMDPM_RND_COUNTERS | 234 | #ifdef AMDPM_RND_COUNTERS | |
216 | int i; | 235 | int i; | |
217 | #endif | 236 | #endif | |
218 | 237 | |||
238 | if (sc->sc_rnd_need < 1) { | |||
239 | callout_stop(&sc->sc_rnd_ch); | |||
240 | return; | |||
241 | } | |||
242 | ||||
219 | if ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGSTAT) & | 243 | if ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGSTAT) & | |
220 | AMDPM_RNGDONE) != 0) { | 244 | AMDPM_RNGDONE) != 0) { | |
221 | rngreg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, | 245 | rngreg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, | |
222 | AMDPM_RNGDATA); | 246 | AMDPM_RNGDATA); | |
223 | rnd_add_data(&sc->sc_rnd_source, &rngreg, | 247 | rnd_add_data(&sc->sc_rnd_source, &rngreg, | |
224 | sizeof(rngreg), sizeof(rngreg) * NBBY); | 248 | sizeof(rngreg), sizeof(rngreg) * NBBY); | |
249 | sc->sc_rnd_need -= sizeof(rngreg); | |||
225 | #ifdef AMDPM_RND_COUNTERS | 250 | #ifdef AMDPM_RND_COUNTERS | |
226 | AMDPM_RNDCNT_INCR(&sc->sc_rnd_hits); | 251 | AMDPM_RNDCNT_INCR(&sc->sc_rnd_hits); | |
227 | for (i = 0; i < sizeof(rngreg); i++, rngreg >>= NBBY) | 252 | for (i = 0; i < sizeof(rngreg); i++, rngreg >>= NBBY) | |
228 | AMDPM_RNDCNT_INCR(&sc->sc_rnd_data[rngreg & 0xff]); | 253 | AMDPM_RNDCNT_INCR(&sc->sc_rnd_data[rngreg & 0xff]); | |
229 | #endif | 254 | #endif | |
230 | } | 255 | } | |
231 | #ifdef AMDPM_RND_COUNTERS | 256 | #ifdef AMDPM_RND_COUNTERS | |
232 | else | 257 | else | |
233 | AMDPM_RNDCNT_INCR(&sc->sc_rnd_miss); | 258 | AMDPM_RNDCNT_INCR(&sc->sc_rnd_miss); | |
234 | #endif | 259 | #endif | |
235 | callout_reset(&sc->sc_rnd_ch, 1, amdpm_rnd_callout, sc); | 260 | if (sc->sc_rnd_need > 0) { | |
261 | callout_reset(&sc->sc_rnd_ch, 1, amdpm_rnd_callout, sc); | |||
262 | } | |||
263 | } | |||
264 | ||||
265 | static void | |||
266 | amdpm_rnd_callout(void *v) | |||
267 | { | |||
268 | struct amdpm_softc *sc = v; | |||
269 | ||||
270 | mutex_enter(&sc->sc_mutex); | |||
271 | amdpm_rnd_callout_locked(v); | |||
272 | mutex_exit(&sc->sc_mutex); | |||
236 | } | 273 | } |
--- src/sys/dev/pci/amdpm_smbus.c 2012/10/27 17:18:28 1.19
+++ src/sys/dev/pci/amdpm_smbus.c 2013/06/13 00:55:01 1.20
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: amdpm_smbus.c,v 1.19 2012/10/27 17:18:28 chs Exp $ */ | 1 | /* $NetBSD: amdpm_smbus.c,v 1.20 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2005 Anil Gopinath (anil_public@yahoo.com) | 4 | * Copyright (c) 2005 Anil Gopinath (anil_public@yahoo.com) | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -22,27 +22,27 @@ | @@ -22,27 +22,27 @@ | |||
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
23 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 23 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
25 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 25 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
28 | * SUCH DAMAGE. | 28 | * SUCH DAMAGE. | |
29 | */ | 29 | */ | |
30 | 30 | |||
31 | /* driver for SMBUS 1.0 host controller found in the | 31 | /* driver for SMBUS 1.0 host controller found in the | |
32 | * AMD-8111 HyperTransport I/O Hub | 32 | * AMD-8111 HyperTransport I/O Hub | |
33 | */ | 33 | */ | |
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | __KERNEL_RCSID(0, "$NetBSD: amdpm_smbus.c,v 1.19 2012/10/27 17:18:28 chs Exp $"); | 35 | __KERNEL_RCSID(0, "$NetBSD: amdpm_smbus.c,v 1.20 2013/06/13 00:55:01 tls Exp $"); | |
36 | 36 | |||
37 | #include <sys/param.h> | 37 | #include <sys/param.h> | |
38 | #include <sys/systm.h> | 38 | #include <sys/systm.h> | |
39 | #include <sys/kernel.h> | 39 | #include <sys/kernel.h> | |
40 | #include <sys/device.h> | 40 | #include <sys/device.h> | |
41 | #include <sys/rnd.h> | 41 | #include <sys/rnd.h> | |
42 | #include <sys/mutex.h> | 42 | #include <sys/mutex.h> | |
43 | 43 | |||
44 | #include <dev/pci/pcireg.h> | 44 | #include <dev/pci/pcireg.h> | |
45 | #include <dev/pci/pcivar.h> | 45 | #include <dev/pci/pcivar.h> | |
46 | #include <dev/pci/pcidevs.h> | 46 | #include <dev/pci/pcidevs.h> | |
47 | 47 | |||
48 | #include <dev/i2c/i2cvar.h> | 48 | #include <dev/i2c/i2cvar.h> | |
@@ -73,28 +73,26 @@ amdpm_smbus_attach(struct amdpm_softc *s | @@ -73,28 +73,26 @@ amdpm_smbus_attach(struct amdpm_softc *s | |||
73 | struct i2cbus_attach_args iba; | 73 | struct i2cbus_attach_args iba; | |
74 | 74 | |||
75 | /* register with iic */ | 75 | /* register with iic */ | |
76 | sc->sc_i2c.ic_cookie = sc; | 76 | sc->sc_i2c.ic_cookie = sc; | |
77 | sc->sc_i2c.ic_acquire_bus = amdpm_smbus_acquire_bus; | 77 | sc->sc_i2c.ic_acquire_bus = amdpm_smbus_acquire_bus; | |
78 | sc->sc_i2c.ic_release_bus = amdpm_smbus_release_bus; | 78 | sc->sc_i2c.ic_release_bus = amdpm_smbus_release_bus; | |
79 | sc->sc_i2c.ic_send_start = NULL; | 79 | sc->sc_i2c.ic_send_start = NULL; | |
80 | sc->sc_i2c.ic_send_stop = NULL; | 80 | sc->sc_i2c.ic_send_stop = NULL; | |
81 | sc->sc_i2c.ic_initiate_xfer = NULL; | 81 | sc->sc_i2c.ic_initiate_xfer = NULL; | |
82 | sc->sc_i2c.ic_read_byte = NULL; | 82 | sc->sc_i2c.ic_read_byte = NULL; | |
83 | sc->sc_i2c.ic_write_byte = NULL; | 83 | sc->sc_i2c.ic_write_byte = NULL; | |
84 | sc->sc_i2c.ic_exec = amdpm_smbus_exec; | 84 | sc->sc_i2c.ic_exec = amdpm_smbus_exec; | |
85 | 85 | |||
86 | mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); | |||
87 | ||||
88 | iba.iba_tag = &sc->sc_i2c; | 86 | iba.iba_tag = &sc->sc_i2c; | |
89 | (void)config_found_ia(sc->sc_dev, "i2cbus", &iba, iicbus_print); | 87 | (void)config_found_ia(sc->sc_dev, "i2cbus", &iba, iicbus_print); | |
90 | } | 88 | } | |
91 | 89 | |||
92 | static int | 90 | static int | |
93 | amdpm_smbus_acquire_bus(void *cookie, int flags) | 91 | amdpm_smbus_acquire_bus(void *cookie, int flags) | |
94 | { | 92 | { | |
95 | struct amdpm_softc *sc = cookie; | 93 | struct amdpm_softc *sc = cookie; | |
96 | 94 | |||
97 | mutex_enter(&sc->sc_mutex); | 95 | mutex_enter(&sc->sc_mutex); | |
98 | return 0; | 96 | return 0; | |
99 | } | 97 | } | |
100 | 98 |
--- src/sys/dev/pci/amdpmvar.h 2012/10/27 17:18:28 1.9
+++ src/sys/dev/pci/amdpmvar.h 2013/06/13 00:55:01 1.10
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: amdpmvar.h,v 1.9 2012/10/27 17:18:28 chs Exp $ */ | 1 | /* $NetBSD: amdpmvar.h,v 1.10 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Enami Tsugutomo. | 8 | * by Enami Tsugutomo. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -43,23 +43,24 @@ struct amdpm_softc { | @@ -43,23 +43,24 @@ struct amdpm_softc { | |||
43 | 43 | |||
44 | bus_space_tag_t sc_iot; | 44 | bus_space_tag_t sc_iot; | |
45 | bus_space_handle_t sc_ioh; /* PMxx space */ | 45 | bus_space_handle_t sc_ioh; /* PMxx space */ | |
46 | bus_space_handle_t sc_sm_ioh; /* SM space */ | 46 | bus_space_handle_t sc_sm_ioh; /* SM space */ | |
47 | 47 | |||
48 | i2c_addr_t sc_smbus_slaveaddr; /* address of smbus slave */ | 48 | i2c_addr_t sc_smbus_slaveaddr; /* address of smbus slave */ | |
49 | struct i2c_controller sc_i2c; /* i2c controller info */ | 49 | struct i2c_controller sc_i2c; /* i2c controller info */ | |
50 | kmutex_t sc_mutex; | 50 | kmutex_t sc_mutex; | |
51 | 51 | |||
52 | void *sc_ih; | 52 | void *sc_ih; | |
53 | 53 | |||
54 | struct callout sc_rnd_ch; | 54 | struct callout sc_rnd_ch; | |
55 | krndsource_t sc_rnd_source; | 55 | krndsource_t sc_rnd_source; | |
56 | int sc_rnd_need; | |||
56 | #ifdef AMDPM_RND_COUNTERS | 57 | #ifdef AMDPM_RND_COUNTERS | |
57 | struct evcnt sc_rnd_hits; | 58 | struct evcnt sc_rnd_hits; | |
58 | struct evcnt sc_rnd_miss; | 59 | struct evcnt sc_rnd_miss; | |
59 | struct evcnt sc_rnd_data[256]; | 60 | struct evcnt sc_rnd_data[256]; | |
60 | #endif | 61 | #endif | |
61 | 62 | |||
62 | char sc_nforce; | 63 | char sc_nforce; | |
63 | }; | 64 | }; | |
64 | 65 | |||
65 | #endif /* _DEV_PCI_AMDPMVAR_H_ */ | 66 | #endif /* _DEV_PCI_AMDPMVAR_H_ */ |
--- src/sys/dev/pci/hifn7751var.h 2012/10/27 17:18:32 1.9
+++ src/sys/dev/pci/hifn7751var.h 2013/06/13 00:55:01 1.10
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: hifn7751var.h,v 1.9 2012/10/27 17:18:32 chs Exp $ */ | 1 | /* $NetBSD: hifn7751var.h,v 1.10 2013/06/13 00:55:01 tls Exp $ */ | |
2 | /* $OpenBSD: hifn7751var.h,v 1.18 2000/06/02 22:36:45 deraadt Exp $ */ | 2 | /* $OpenBSD: hifn7751var.h,v 1.18 2000/06/02 22:36:45 deraadt Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Invertex AEON / Hifn 7751 driver | 5 | * Invertex AEON / Hifn 7751 driver | |
6 | * Copyright (c) 1999 Invertex Inc. All rights reserved. | 6 | * Copyright (c) 1999 Invertex Inc. All rights reserved. | |
7 | * Copyright (c) 1999 Theo de Raadt | 7 | * Copyright (c) 1999 Theo de Raadt | |
8 | * Copyright (c) 2000-2001 Network Security Technologies, Inc. | 8 | * Copyright (c) 2000-2001 Network Security Technologies, Inc. | |
9 | * http://www.netsec.net | 9 | * http://www.netsec.net | |
10 | * | 10 | * | |
11 | * Please send any comments, feedback, bug-fixes, or feature requests to | 11 | * Please send any comments, feedback, bug-fixes, or feature requests to | |
12 | * software@invertex.com. | 12 | * software@invertex.com. | |
13 | * | 13 | * | |
14 | * Redistribution and use in source and binary forms, with or without | 14 | * Redistribution and use in source and binary forms, with or without | |
@@ -159,41 +159,42 @@ struct hifn_softc { | @@ -159,41 +159,42 @@ struct hifn_softc { | |||
159 | #define HIFN_HAS_AES 0x04 /* includes AES support */ | 159 | #define HIFN_HAS_AES 0x04 /* includes AES support */ | |
160 | #define HIFN_IS_7811 0x08 /* Hifn 7811 part */ | 160 | #define HIFN_IS_7811 0x08 /* Hifn 7811 part */ | |
161 | #define HIFN_IS_7956 0x10 /* Hifn 7956/7955 don't have SDRAM */ | 161 | #define HIFN_IS_7956 0x10 /* Hifn 7956/7955 don't have SDRAM */ | |
162 | #define HIFN_NO_BURSTWRITE 0x20 | 162 | #define HIFN_NO_BURSTWRITE 0x20 | |
163 | #define HIFN_HAS_LEDS 0x40 | 163 | #define HIFN_HAS_LEDS 0x40 | |
164 | 164 | |||
165 | #define HIFN_RNG_BITSPER 17 /* From Hifn 6500 paper: 0.06 bits | 165 | #define HIFN_RNG_BITSPER 17 /* From Hifn 6500 paper: 0.06 bits | |
166 | of entropy per RNG register bit | 166 | of entropy per RNG register bit | |
167 | worst-case */ | 167 | worst-case */ | |
168 | 168 | |||
169 | struct callout sc_rngto; /* rng timeout */ | 169 | struct callout sc_rngto; /* rng timeout */ | |
170 | struct callout sc_tickto; /* led-clear timeout */ | 170 | struct callout sc_tickto; /* led-clear timeout */ | |
171 | krndsource_t sc_rnd_source; | 171 | krndsource_t sc_rnd_source; | |
172 | int sc_rngfirst; | |||
173 | int sc_rnghz; | 172 | int sc_rnghz; | |
173 | int sc_rng_need; /* how many bytes wanted */ | |||
174 | int sc_c_busy; /* command ring busy */ | 174 | int sc_c_busy; /* command ring busy */ | |
175 | int sc_s_busy; /* source data ring busy */ | 175 | int sc_s_busy; /* source data ring busy */ | |
176 | int sc_d_busy; /* destination data ring busy */ | 176 | int sc_d_busy; /* destination data ring busy */ | |
177 | int sc_r_busy; /* result ring busy */ | 177 | int sc_r_busy; /* result ring busy */ | |
178 | int sc_active; /* for initial countdown */ | 178 | int sc_active; /* for initial countdown */ | |
179 | int sc_needwakeup; /* ops q'd wating on resources */ | 179 | int sc_needwakeup; /* ops q'd wating on resources */ | |
180 | int sc_curbatch; /* # ops submitted w/o int */ | 180 | int sc_curbatch; /* # ops submitted w/o int */ | |
181 | int sc_suspended; | 181 | int sc_suspended; | |
182 | struct hifn_session sc_sessions[2048]; | 182 | struct hifn_session sc_sessions[2048]; | |
183 | pci_chipset_tag_t sc_pci_pc; | 183 | pci_chipset_tag_t sc_pci_pc; | |
184 | pcitag_t sc_pci_tag; | 184 | pcitag_t sc_pci_tag; | |
185 | bus_size_t sc_waw_lastreg; | 185 | bus_size_t sc_waw_lastreg; | |
186 | int sc_waw_lastgroup; | 186 | int sc_waw_lastgroup; | |
187 | kmutex_t sc_mtx; | |||
187 | }; | 188 | }; | |
188 | 189 | |||
189 | #define WRITE_REG_0(sc,reg,val) hifn_write_4((sc), 0, (reg), (val)) | 190 | #define WRITE_REG_0(sc,reg,val) hifn_write_4((sc), 0, (reg), (val)) | |
190 | #define WRITE_REG_1(sc,reg,val) hifn_write_4((sc), 1, (reg), (val)) | 191 | #define WRITE_REG_1(sc,reg,val) hifn_write_4((sc), 1, (reg), (val)) | |
191 | #define READ_REG_0(sc,reg) hifn_read_4((sc), 0, (reg)) | 192 | #define READ_REG_0(sc,reg) hifn_read_4((sc), 0, (reg)) | |
192 | #define READ_REG_1(sc,reg) hifn_read_4((sc), 1, (reg)) | 193 | #define READ_REG_1(sc,reg) hifn_read_4((sc), 1, (reg)) | |
193 | 194 | |||
194 | #define SET_LED(sc,v) \ | 195 | #define SET_LED(sc,v) \ | |
195 | if (sc->sc_flags & HIFN_HAS_LEDS) \ | 196 | if (sc->sc_flags & HIFN_HAS_LEDS) \ | |
196 | WRITE_REG_1(sc, HIFN_1_7811_MIPSRST, \ | 197 | WRITE_REG_1(sc, HIFN_1_7811_MIPSRST, \ | |
197 | READ_REG_1(sc, HIFN_1_7811_MIPSRST) | (v)) | 198 | READ_REG_1(sc, HIFN_1_7811_MIPSRST) | (v)) | |
198 | #define CLR_LED(sc,v) \ | 199 | #define CLR_LED(sc,v) \ | |
199 | if (sc->sc_flags & HIFN_HAS_LEDS) \ | 200 | if (sc->sc_flags & HIFN_HAS_LEDS) \ |
--- src/sys/dev/pci/hifn7751.c 2012/10/27 17:18:32 1.51
+++ src/sys/dev/pci/hifn7751.c 2013/06/13 00:55:01 1.52
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: hifn7751.c,v 1.51 2012/10/27 17:18:32 chs Exp $ */ | 1 | /* $NetBSD: hifn7751.c,v 1.52 2013/06/13 00:55:01 tls Exp $ */ | |
2 | /* $FreeBSD: hifn7751.c,v 1.5.2.7 2003/10/08 23:52:00 sam Exp $ */ | 2 | /* $FreeBSD: hifn7751.c,v 1.5.2.7 2003/10/08 23:52:00 sam Exp $ */ | |
3 | /* $OpenBSD: hifn7751.c,v 1.140 2003/08/01 17:55:54 deraadt Exp $ */ | 3 | /* $OpenBSD: hifn7751.c,v 1.140 2003/08/01 17:55:54 deraadt Exp $ */ | |
4 | 4 | |||
5 | /* | 5 | /* | |
6 | * Invertex AEON / Hifn 7751 driver | 6 | * Invertex AEON / Hifn 7751 driver | |
7 | * Copyright (c) 1999 Invertex Inc. All rights reserved. | 7 | * Copyright (c) 1999 Invertex Inc. All rights reserved. | |
8 | * Copyright (c) 1999 Theo de Raadt | 8 | * Copyright (c) 1999 Theo de Raadt | |
9 | * Copyright (c) 2000-2001 Network Security Technologies, Inc. | 9 | * Copyright (c) 2000-2001 Network Security Technologies, Inc. | |
10 | * http://www.netsec.net | 10 | * http://www.netsec.net | |
11 | * Copyright (c) 2003 Hifn Inc. | 11 | * Copyright (c) 2003 Hifn Inc. | |
12 | * | 12 | * | |
13 | * This driver is based on a previous driver by Invertex, for which they | 13 | * This driver is based on a previous driver by Invertex, for which they | |
14 | * requested: Please send any comments, feedback, bug-fixes, or feature | 14 | * requested: Please send any comments, feedback, bug-fixes, or feature | |
@@ -38,30 +38,31 @@ | @@ -38,30 +38,31 @@ | |||
38 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 38 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
39 | * | 39 | * | |
40 | * Effort sponsored in part by the Defense Advanced Research Projects | 40 | * Effort sponsored in part by the Defense Advanced Research Projects | |
41 | * Agency (DARPA) and Air Force Research Laboratory, Air Force | 41 | * Agency (DARPA) and Air Force Research Laboratory, Air Force | |
42 | * Materiel Command, USAF, under agreement number F30602-01-2-0537. | 42 | * Materiel Command, USAF, under agreement number F30602-01-2-0537. | |
43 | * | 43 | * | |
44 | */ | 44 | */ | |
45 | 45 | |||
46 | /* | 46 | /* | |
47 | * Driver for various Hifn pre-HIPP encryption processors. | 47 | * Driver for various Hifn pre-HIPP encryption processors. | |
48 | */ | 48 | */ | |
49 | 49 | |||
50 | #include <sys/cdefs.h> | 50 | #include <sys/cdefs.h> | |
51 | __KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.51 2012/10/27 17:18:32 chs Exp $"); | 51 | __KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.52 2013/06/13 00:55:01 tls Exp $"); | |
52 | 52 | |||
53 | #include <sys/param.h> | 53 | #include <sys/param.h> | |
54 | #include <sys/systm.h> | 54 | #include <sys/systm.h> | |
55 | #include <sys/mutex.h> | |||
55 | #include <sys/proc.h> | 56 | #include <sys/proc.h> | |
56 | #include <sys/errno.h> | 57 | #include <sys/errno.h> | |
57 | #include <sys/malloc.h> | 58 | #include <sys/malloc.h> | |
58 | #include <sys/kernel.h> | 59 | #include <sys/kernel.h> | |
59 | #include <sys/mbuf.h> | 60 | #include <sys/mbuf.h> | |
60 | #include <sys/device.h> | 61 | #include <sys/device.h> | |
61 | 62 | |||
62 | #ifdef __OpenBSD__ | 63 | #ifdef __OpenBSD__ | |
63 | #include <crypto/crypto.h> | 64 | #include <crypto/crypto.h> | |
64 | #include <dev/rndvar.h> | 65 | #include <dev/rndvar.h> | |
65 | #else | 66 | #else | |
66 | #include <opencrypto/cryptodev.h> | 67 | #include <opencrypto/cryptodev.h> | |
67 | #include <sys/cprng.h> | 68 | #include <sys/cprng.h> | |
@@ -130,42 +131,42 @@ static int hifn_process(void*, struct cr | @@ -130,42 +131,42 @@ static int hifn_process(void*, struct cr | |||
130 | static void hifn_callback(struct hifn_softc *, struct hifn_command *, | 131 | static void hifn_callback(struct hifn_softc *, struct hifn_command *, | |
131 | u_int8_t *); | 132 | u_int8_t *); | |
132 | static int hifn_crypto(struct hifn_softc *, struct hifn_command *, | 133 | static int hifn_crypto(struct hifn_softc *, struct hifn_command *, | |
133 | struct cryptop*, int); | 134 | struct cryptop*, int); | |
134 | static int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *); | 135 | static int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *); | |
135 | static int hifn_writeramaddr(struct hifn_softc *, int, u_int8_t *); | 136 | static int hifn_writeramaddr(struct hifn_softc *, int, u_int8_t *); | |
136 | static int hifn_dmamap_aligned(bus_dmamap_t); | 137 | static int hifn_dmamap_aligned(bus_dmamap_t); | |
137 | static int hifn_dmamap_load_src(struct hifn_softc *, | 138 | static int hifn_dmamap_load_src(struct hifn_softc *, | |
138 | struct hifn_command *); | 139 | struct hifn_command *); | |
139 | static int hifn_dmamap_load_dst(struct hifn_softc *, | 140 | static int hifn_dmamap_load_dst(struct hifn_softc *, | |
140 | struct hifn_command *); | 141 | struct hifn_command *); | |
141 | static int hifn_init_pubrng(struct hifn_softc *); | 142 | static int hifn_init_pubrng(struct hifn_softc *); | |
142 | static void hifn_rng(void *); | 143 | static void hifn_rng(void *); | |
144 | static void hifn_rng_locked(void *); | |||
143 | static void hifn_tick(void *); | 145 | static void hifn_tick(void *); | |
144 | static void hifn_abort(struct hifn_softc *); | 146 | static void hifn_abort(struct hifn_softc *); | |
145 | static void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, | 147 | static void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, | |
146 | int *); | 148 | int *); | |
147 | static void hifn_write_4(struct hifn_softc *, int, bus_size_t, u_int32_t); | 149 | static void hifn_write_4(struct hifn_softc *, int, bus_size_t, u_int32_t); | |
148 | static u_int32_t hifn_read_4(struct hifn_softc *, int, bus_size_t); | 150 | static u_int32_t hifn_read_4(struct hifn_softc *, int, bus_size_t); | |
149 | #ifdef HAVE_CRYPTO_LZS | 151 | #ifdef HAVE_CRYPTO_LZS | |
150 | static int hifn_compression(struct hifn_softc *, struct cryptop *, | 152 | static int hifn_compression(struct hifn_softc *, struct cryptop *, | |
151 | struct hifn_command *); | 153 | struct hifn_command *); | |
152 | static struct mbuf *hifn_mkmbuf_chain(int, struct mbuf *); | 154 | static struct mbuf *hifn_mkmbuf_chain(int, struct mbuf *); | |
153 | static int hifn_compress_enter(struct hifn_softc *, struct hifn_command *); | 155 | static int hifn_compress_enter(struct hifn_softc *, struct hifn_command *); | |
154 | static void hifn_callback_comp(struct hifn_softc *, struct hifn_command *, | 156 | static void hifn_callback_comp(struct hifn_softc *, struct hifn_command *, | |
155 | u_int8_t *); | 157 | u_int8_t *); | |
156 | #endif /* HAVE_CRYPTO_LZS */ | 158 | #endif /* HAVE_CRYPTO_LZS */ | |
157 | 159 | |||
158 | ||||
159 | struct hifn_stats hifnstats; | 160 | struct hifn_stats hifnstats; | |
160 | 161 | |||
161 | static const struct hifn_product { | 162 | static const struct hifn_product { | |
162 | pci_vendor_id_t hifn_vendor; | 163 | pci_vendor_id_t hifn_vendor; | |
163 | pci_product_id_t hifn_product; | 164 | pci_product_id_t hifn_product; | |
164 | int hifn_flags; | 165 | int hifn_flags; | |
165 | const char *hifn_name; | 166 | const char *hifn_name; | |
166 | } hifn_products[] = { | 167 | } hifn_products[] = { | |
167 | { PCI_VENDOR_INVERTEX, PCI_PRODUCT_INVERTEX_AEON, | 168 | { PCI_VENDOR_INVERTEX, PCI_PRODUCT_INVERTEX_AEON, | |
168 | 0, | 169 | 0, | |
169 | "Invertex AEON", | 170 | "Invertex AEON", | |
170 | }, | 171 | }, | |
171 | 172 | |||
@@ -408,56 +409,72 @@ hifn_attach(device_t parent, device_t se | @@ -408,56 +409,72 @@ hifn_attach(device_t parent, device_t se | |||
408 | crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC_96, 0, 0, | 409 | crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC_96, 0, 0, | |
409 | hifn_newsession, hifn_freesession, hifn_process, sc); | 410 | hifn_newsession, hifn_freesession, hifn_process, sc); | |
410 | crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC_96, 0, 0, | 411 | crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC_96, 0, 0, | |
411 | hifn_newsession, hifn_freesession, hifn_process, sc); | 412 | hifn_newsession, hifn_freesession, hifn_process, sc); | |
412 | crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0, | 413 | crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0, | |
413 | hifn_newsession, hifn_freesession, hifn_process, sc); | 414 | hifn_newsession, hifn_freesession, hifn_process, sc); | |
414 | break; | 415 | break; | |
415 | } | 416 | } | |
416 | 417 | |||
417 | bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, | 418 | bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, | |
418 | sc->sc_dmamap->dm_mapsize, | 419 | sc->sc_dmamap->dm_mapsize, | |
419 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | 420 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | |
420 | 421 | |||
421 | if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG)) | 422 | if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG)) { | |
422 | hifn_init_pubrng(sc); | 423 | hifn_init_pubrng(sc); | |
424 | sc->sc_rng_need = RND_POOLBITS / NBBY; | |||
425 | } | |||
426 | ||||
427 | mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM); | |||
423 | 428 | |||
424 | #ifdef __OpenBSD__ | 429 | #ifdef __OpenBSD__ | |
425 | timeout_set(&sc->sc_tickto, hifn_tick, sc); | 430 | timeout_set(&sc->sc_tickto, hifn_tick, sc); | |
426 | timeout_add(&sc->sc_tickto, hz); | 431 | timeout_add(&sc->sc_tickto, hz); | |
427 | #else | 432 | #else | |
428 | callout_init(&sc->sc_tickto, 0); | 433 | callout_init(&sc->sc_tickto, CALLOUT_MPSAFE); | |
429 | callout_reset(&sc->sc_tickto, hz, hifn_tick, sc); | 434 | callout_reset(&sc->sc_tickto, hz, hifn_tick, sc); | |
430 | #endif | 435 | #endif | |
431 | return; | 436 | return; | |
432 | 437 | |||
433 | fail_intr: | 438 | fail_intr: | |
434 | pci_intr_disestablish(pc, sc->sc_ih); | 439 | pci_intr_disestablish(pc, sc->sc_ih); | |
435 | fail_mem: | 440 | fail_mem: | |
436 | bus_dmamap_unload(sc->sc_dmat, dmamap); | 441 | bus_dmamap_unload(sc->sc_dmat, dmamap); | |
437 | bus_dmamap_destroy(sc->sc_dmat, dmamap); | 442 | bus_dmamap_destroy(sc->sc_dmat, dmamap); | |
438 | bus_dmamem_unmap(sc->sc_dmat, kva, sizeof(*sc->sc_dma)); | 443 | bus_dmamem_unmap(sc->sc_dmat, kva, sizeof(*sc->sc_dma)); | |
439 | bus_dmamem_free(sc->sc_dmat, &seg, rseg); | 444 | bus_dmamem_free(sc->sc_dmat, &seg, rseg); | |
440 | 445 | |||
441 | /* Turn off DMA polling */ | 446 | /* Turn off DMA polling */ | |
442 | WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET | | 447 | WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET | | |
443 | HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE); | 448 | HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE); | |
444 | 449 | |||
445 | fail_io1: | 450 | fail_io1: | |
446 | bus_space_unmap(sc->sc_st1, sc->sc_sh1, iosize1); | 451 | bus_space_unmap(sc->sc_st1, sc->sc_sh1, iosize1); | |
447 | fail_io0: | 452 | fail_io0: | |
448 | bus_space_unmap(sc->sc_st0, sc->sc_sh0, iosize0); | 453 | bus_space_unmap(sc->sc_st0, sc->sc_sh0, iosize0); | |
449 | } | 454 | } | |
450 | 455 | |||
456 | static void | |||
457 | hifn_rng_get(size_t bytes, void *priv) | |||
458 | { | |||
459 | struct hifn_softc *sc = priv; | |||
460 | ||||
461 | mutex_enter(&sc->sc_mtx); | |||
462 | sc->sc_rng_need = bytes; | |||
463 | ||||
464 | hifn_rng_locked(sc); | |||
465 | mutex_exit(&sc->sc_mtx); | |||
466 | } | |||
467 | ||||
451 | static int | 468 | static int | |
452 | hifn_init_pubrng(struct hifn_softc *sc) | 469 | hifn_init_pubrng(struct hifn_softc *sc) | |
453 | { | 470 | { | |
454 | u_int32_t r; | 471 | u_int32_t r; | |
455 | int i; | 472 | int i; | |
456 | 473 | |||
457 | if ((sc->sc_flags & HIFN_IS_7811) == 0) { | 474 | if ((sc->sc_flags & HIFN_IS_7811) == 0) { | |
458 | /* Reset 7951 public key/rng engine */ | 475 | /* Reset 7951 public key/rng engine */ | |
459 | WRITE_REG_1(sc, HIFN_1_PUB_RESET, | 476 | WRITE_REG_1(sc, HIFN_1_PUB_RESET, | |
460 | READ_REG_1(sc, HIFN_1_PUB_RESET) | HIFN_PUBRST_RESET); | 477 | READ_REG_1(sc, HIFN_1_PUB_RESET) | HIFN_PUBRST_RESET); | |
461 | 478 | |||
462 | for (i = 0; i < 100; i++) { | 479 | for (i = 0; i < 100; i++) { | |
463 | DELAY(1000); | 480 | DELAY(1000); | |
@@ -490,182 +507,196 @@ hifn_init_pubrng(struct hifn_softc *sc) | @@ -490,182 +507,196 @@ hifn_init_pubrng(struct hifn_softc *sc) | |||
490 | READ_REG_1(sc, HIFN_1_RNG_CONFIG) | | 507 | READ_REG_1(sc, HIFN_1_RNG_CONFIG) | | |
491 | HIFN_RNGCFG_ENA); | 508 | HIFN_RNGCFG_ENA); | |
492 | 509 | |||
493 | /* | 510 | /* | |
494 | * The Hifn RNG documentation states that at their | 511 | * The Hifn RNG documentation states that at their | |
495 | * recommended "conservative" RNG config values, | 512 | * recommended "conservative" RNG config values, | |
496 | * the RNG must warm up for 0.4s before providing | 513 | * the RNG must warm up for 0.4s before providing | |
497 | * data that meet their worst-case estimate of 0.06 | 514 | * data that meet their worst-case estimate of 0.06 | |
498 | * bits of random data per output register bit. | 515 | * bits of random data per output register bit. | |
499 | */ | 516 | */ | |
500 | DELAY(4000); | 517 | DELAY(4000); | |
501 | 518 | |||
502 | #ifdef __NetBSD__ | 519 | #ifdef __NetBSD__ | |
520 | rndsource_setcb(&sc->sc_rnd_source, hifn_rng_get, sc); | |||
503 | /* | 521 | /* | |
504 | * XXX Careful! The use of RND_FLAG_NO_ESTIMATE | 522 | * XXX Careful! The use of RND_FLAG_NO_ESTIMATE | |
505 | * XXX here is unobvious: we later feed raw bits | 523 | * XXX here is unobvious: we later feed raw bits | |
506 | * XXX into the "entropy pool" with rnd_add_data, | 524 | * XXX into the "entropy pool" with rnd_add_data, | |
507 | * XXX explicitly supplying an entropy estimate. | 525 | * XXX explicitly supplying an entropy estimate. | |
508 | * XXX In this context, NO_ESTIMATE serves only | 526 | * XXX In this context, NO_ESTIMATE serves only | |
509 | * XXX to prevent rnd_add_data from trying to | 527 | * XXX to prevent rnd_add_data from trying to | |
510 | * XXX use the *time at which we added the data* | 528 | * XXX use the *time at which we added the data* | |
511 | * XXX as entropy, which is not a good idea since | 529 | * XXX as entropy, which is not a good idea since | |
512 | * XXX we add data periodically from a callout. | 530 | * XXX we add data periodically from a callout. | |
513 | */ | 531 | */ | |
514 | rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dv), | 532 | rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dv), | |
515 | RND_TYPE_RNG, RND_FLAG_NO_ESTIMATE); | 533 | RND_TYPE_RNG, | |
534 | RND_FLAG_NO_ESTIMATE|RND_FLAG_HASCB); | |||
516 | #endif | 535 | #endif | |
517 | 536 | |||
518 | sc->sc_rngfirst = 1; | |||
519 | if (hz >= 100) | 537 | if (hz >= 100) | |
520 | sc->sc_rnghz = hz / 100; | 538 | sc->sc_rnghz = hz / 100; | |
521 | else | 539 | else | |
522 | sc->sc_rnghz = 1; | 540 | sc->sc_rnghz = 1; | |
523 | #ifdef __OpenBSD__ | 541 | #ifdef __OpenBSD__ | |
524 | timeout_set(&sc->sc_rngto, hifn_rng, sc); | 542 | timeout_set(&sc->sc_rngto, hifn_rng, sc); | |
525 | #else /* !__OpenBSD__ */ | 543 | #else /* !__OpenBSD__ */ | |
526 | callout_init(&sc->sc_rngto, 0); | 544 | callout_init(&sc->sc_rngto, CALLOUT_MPSAFE); | |
527 | #endif /* !__OpenBSD__ */ | 545 | #endif /* !__OpenBSD__ */ | |
528 | } | 546 | } | |
529 | 547 | |||
530 | /* Enable public key engine, if available */ | 548 | /* Enable public key engine, if available */ | |
531 | if (sc->sc_flags & HIFN_HAS_PUBLIC) { | 549 | if (sc->sc_flags & HIFN_HAS_PUBLIC) { | |
532 | WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE); | 550 | WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE); | |
533 | sc->sc_dmaier |= HIFN_DMAIER_PUBDONE; | 551 | sc->sc_dmaier |= HIFN_DMAIER_PUBDONE; | |
534 | WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); | 552 | WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); | |
535 | } | 553 | } | |
536 | 554 | |||
537 | /* Call directly into the RNG once to prime the pool. */ | 555 | /* Call directly into the RNG once to prime the pool. */ | |
538 | hifn_rng(sc); /* Sets callout/timeout at end */ | 556 | hifn_rng(sc); /* Sets callout/timeout at end */ | |
539 | 557 | |||
540 | return (0); | 558 | return (0); | |
541 | } | 559 | } | |
542 | 560 | |||
543 | static void | 561 | static void | |
544 | hifn_rng(void *vsc) | 562 | hifn_rng_locked(void *vsc) | |
545 | { | 563 | { | |
546 | struct hifn_softc *sc = vsc; | 564 | struct hifn_softc *sc = vsc; | |
547 | #ifdef __NetBSD__ | 565 | #ifdef __NetBSD__ | |
548 | uint32_t num[64]; | 566 | uint32_t num[64]; | |
549 | #else | 567 | #else | |
550 | uint32_t num[2]; | 568 | uint32_t num[2]; | |
551 | #endif | 569 | #endif | |
552 | uint32_t sts; | 570 | uint32_t sts; | |
553 | int i; | 571 | int i; | |
572 | size_t got, gotent; | |||
573 | ||||
574 | if (sc->sc_rng_need < 1) { | |||
575 | callout_stop(&sc->sc_rngto); | |||
576 | return; | |||
577 | } | |||
554 | 578 | |||
555 | if (sc->sc_flags & HIFN_IS_7811) { | 579 | if (sc->sc_flags & HIFN_IS_7811) { | |
556 | for (i = 0; i < 5; i++) { /* XXX why 5? */ | 580 | for (i = 0; i < 5; i++) { /* XXX why 5? */ | |
557 | sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS); | 581 | sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS); | |
558 | if (sts & HIFN_7811_RNGSTS_UFL) { | 582 | if (sts & HIFN_7811_RNGSTS_UFL) { | |
559 | printf("%s: RNG underflow: disabling\n", | 583 | printf("%s: RNG underflow: disabling\n", | |
560 | device_xname(sc->sc_dv)); | 584 | device_xname(sc->sc_dv)); | |
561 | return; | 585 | return; | |
562 | } | 586 | } | |
563 | if ((sts & HIFN_7811_RNGSTS_RDY) == 0) | 587 | if ((sts & HIFN_7811_RNGSTS_RDY) == 0) | |
564 | break; | 588 | break; | |
565 | 589 | |||
566 | /* | 590 | /* | |
567 | * There are at least two words in the RNG FIFO | 591 | * There are at least two words in the RNG FIFO | |
568 | * at this point. | 592 | * at this point. | |
569 | */ | 593 | */ | |
570 | num[0] = READ_REG_1(sc, HIFN_1_7811_RNGDAT); | 594 | num[0] = READ_REG_1(sc, HIFN_1_7811_RNGDAT); | |
571 | num[1] = READ_REG_1(sc, HIFN_1_7811_RNGDAT); | 595 | num[1] = READ_REG_1(sc, HIFN_1_7811_RNGDAT); | |
596 | got = 2 * sizeof(num[0]); | |||
597 | gotent = (got * NBBY) / HIFN_RNG_BITSPER; | |||
572 | 598 | |||
573 | if (sc->sc_rngfirst) | |||
574 | sc->sc_rngfirst = 0; | |||
575 | #ifdef __NetBSD__ | 599 | #ifdef __NetBSD__ | |
576 | rnd_add_data(&sc->sc_rnd_source, num, | 600 | rnd_add_data(&sc->sc_rnd_source, num, got, gotent); | |
577 | 2 * sizeof(num[0]), | 601 | sc->sc_rng_need -= gotent; | |
578 | (2 * sizeof(num[0]) * NBBY) / | |||
579 | HIFN_RNG_BITSPER); | |||
580 | #else | 602 | #else | |
581 | /* | 603 | /* | |
582 | * XXX This is a really bad idea. | 604 | * XXX This is a really bad idea. | |
583 | * XXX Hifn estimate as little as 0.06 | 605 | * XXX Hifn estimate as little as 0.06 | |
584 | * XXX actual bits of entropy per output | 606 | * XXX actual bits of entropy per output | |
585 | * XXX register bit. How can we tell the | 607 | * XXX register bit. How can we tell the | |
586 | * XXX kernel RNG subsystem we're handing | 608 | * XXX kernel RNG subsystem we're handing | |
587 | * XXX it 64 "true" random bits, for any | 609 | * XXX it 64 "true" random bits, for any | |
588 | * XXX sane value of "true"? | 610 | * XXX sane value of "true"? | |
589 | * XXX | 611 | * XXX | |
590 | * XXX The right thing to do here, if we | 612 | * XXX The right thing to do here, if we | |
591 | * XXX cannot supply an estimate ourselves, | 613 | * XXX cannot supply an estimate ourselves, | |
592 | * XXX would be to hash the bits locally. | 614 | * XXX would be to hash the bits locally. | |
593 | */ | 615 | */ | |
594 | add_true_randomness(num[0]); | 616 | add_true_randomness(num[0]); | |
595 | add_true_randomness(num[1]); | 617 | add_true_randomness(num[1]); | |
596 | #endif | 618 | #endif | |
597 | 619 | |||
598 | } | 620 | } | |
599 | } else { | 621 | } else { | |
600 | #ifdef __NetBSD__ | 622 | int nwords = 0; | |
601 | /* First time through, try to help fill the pool. */ | 623 | ||
602 | int nwords = sc->sc_rngfirst ? | 624 | if (sc->sc_rng_need) { | |
603 | sizeof(num) / sizeof(num[0]) : 4; | 625 | nwords = (sc->sc_rng_need * NBBY) / HIFN_RNG_BITSPER; | |
604 | #else | 626 | } | |
605 | int nwords = 2; | 627 | ||
606 | #endif | 628 | if (nwords < 2) { | |
629 | nwords = 2; | |||
630 | } | |||
631 | ||||
607 | /* | 632 | /* | |
608 | * We must be *extremely* careful here. The Hifn | 633 | * We must be *extremely* careful here. The Hifn | |
609 | * 795x differ from the published 6500 RNG design | 634 | * 795x differ from the published 6500 RNG design | |
610 | * in more ways than the obvious lack of the output | 635 | * in more ways than the obvious lack of the output | |
611 | * FIFO and LFSR control registers. In fact, there | 636 | * FIFO and LFSR control registers. In fact, there | |
612 | * is only one LFSR, instead of the 6500's two, and | 637 | * is only one LFSR, instead of the 6500's two, and | |
613 | * it's 32 bits, not 31. | 638 | * it's 32 bits, not 31. | |
614 | * | 639 | * | |
615 | * Further, a block diagram obtained from Hifn shows | 640 | * Further, a block diagram obtained from Hifn shows | |
616 | * a very curious latching of this register: the LFSR | 641 | * a very curious latching of this register: the LFSR | |
617 | * rotates at a frequency of RNG_Clk / 8, but the | 642 | * rotates at a frequency of RNG_Clk / 8, but the | |
618 | * RNG_Data register is latched at a frequency of | 643 | * RNG_Data register is latched at a frequency of | |
619 | * RNG_Clk, which means that it is possible for | 644 | * RNG_Clk, which means that it is possible for | |
620 | * consecutive reads of the RNG_Data register to read | 645 | * consecutive reads of the RNG_Data register to read | |
621 | * identical state from the LFSR. The simplest | 646 | * identical state from the LFSR. The simplest | |
622 | * workaround seems to be to read eight samples from | 647 | * workaround seems to be to read eight samples from | |
623 | * the register for each one that we use. Since each | 648 | * the register for each one that we use. Since each | |
624 | * read must require at least one PCI cycle, and | 649 | * read must require at least one PCI cycle, and | |
625 | * RNG_Clk is at least PCI_Clk, this is safe. | 650 | * RNG_Clk is at least PCI_Clk, this is safe. | |
626 | */ | 651 | */ | |
627 | ||||
628 | ||||
629 | if (sc->sc_rngfirst) { | |||
630 | sc->sc_rngfirst = 0; | |||
631 | } | |||
632 | ||||
633 | ||||
634 | for(i = 0 ; i < nwords * 8; i++) | 652 | for(i = 0 ; i < nwords * 8; i++) | |
635 | { | 653 | { | |
636 | volatile u_int32_t regtmp; | 654 | volatile u_int32_t regtmp; | |
637 | regtmp = READ_REG_1(sc, HIFN_1_RNG_DATA); | 655 | regtmp = READ_REG_1(sc, HIFN_1_RNG_DATA); | |
638 | num[i / 8] = regtmp; | 656 | num[i / 8] = regtmp; | |
639 | } | 657 | } | |
658 | ||||
659 | got = nwords * sizeof(num[0]); | |||
660 | gotent = (got * NBBY) / HIFN_RNG_BITSPER; | |||
640 | #ifdef __NetBSD__ | 661 | #ifdef __NetBSD__ | |
641 | rnd_add_data(&sc->sc_rnd_source, num, | 662 | rnd_add_data(&sc->sc_rnd_source, num, got, gotent); | |
642 | nwords * sizeof(num[0]), | 663 | sc->sc_rng_need -= gotent; | |
643 | (nwords * sizeof(num[0]) * NBBY) / | |||
644 | HIFN_RNG_BITSPER); | |||
645 | #else | 664 | #else | |
646 | /* XXX a bad idea; see 7811 block above */ | 665 | /* XXX a bad idea; see 7811 block above */ | |
647 | add_true_randomness(num[0]); | 666 | add_true_randomness(num[0]); | |
648 | #endif | 667 | #endif | |
649 | } | 668 | } | |
650 | 669 | |||
651 | #ifdef __OpenBSD__ | 670 | #ifdef __OpenBSD__ | |
652 | timeout_add(&sc->sc_rngto, sc->sc_rnghz); | 671 | timeout_add(&sc->sc_rngto, sc->sc_rnghz); | |
653 | #else | 672 | #else | |
654 | callout_reset(&sc->sc_rngto, sc->sc_rnghz, hifn_rng, sc); | 673 | if (sc->sc_rng_need > 0) { | |
674 | callout_reset(&sc->sc_rngto, sc->sc_rnghz, hifn_rng, sc); | |||
675 | } | |||
655 | #endif | 676 | #endif | |
656 | } | 677 | } | |
657 | 678 | |||
658 | static void | 679 | static void | |
680 | hifn_rng(void *vsc) | |||
681 | { | |||
682 | struct hifn_softc *sc = vsc; | |||
683 | ||||
684 | mutex_spin_enter(&sc->sc_mtx); | |||
685 | hifn_rng_locked(vsc); | |||
686 | mutex_spin_exit(&sc->sc_mtx); | |||
687 | } | |||
688 | ||||
689 | static void | |||
659 | hifn_puc_wait(struct hifn_softc *sc) | 690 | hifn_puc_wait(struct hifn_softc *sc) | |
660 | { | 691 | { | |
661 | int i; | 692 | int i; | |
662 | 693 | |||
663 | for (i = 5000; i > 0; i--) { | 694 | for (i = 5000; i > 0; i--) { | |
664 | DELAY(1); | 695 | DELAY(1); | |
665 | if (!(READ_REG_0(sc, HIFN_0_PUCTRL) & HIFN_PUCTRL_RESET)) | 696 | if (!(READ_REG_0(sc, HIFN_0_PUCTRL) & HIFN_PUCTRL_RESET)) | |
666 | break; | 697 | break; | |
667 | } | 698 | } | |
668 | if (!i) | 699 | if (!i) | |
669 | printf("%s: proc unit did not reset\n", device_xname(sc->sc_dv)); | 700 | printf("%s: proc unit did not reset\n", device_xname(sc->sc_dv)); | |
670 | } | 701 | } | |
671 | 702 | |||
@@ -1580,27 +1611,27 @@ hifn_dmamap_load_src(struct hifn_softc * | @@ -1580,27 +1611,27 @@ hifn_dmamap_load_src(struct hifn_softc * | |||
1580 | } | 1611 | } | |
1581 | } | 1612 | } | |
1582 | dma->srci = idx; | 1613 | dma->srci = idx; | |
1583 | dma->srcu += map->dm_nsegs; | 1614 | dma->srcu += map->dm_nsegs; | |
1584 | return (idx); | 1615 | return (idx); | |
1585 | } | 1616 | } | |
1586 | 1617 | |||
1587 | static int | 1618 | static int | |
1588 | hifn_crypto(struct hifn_softc *sc, struct hifn_command *cmd, | 1619 | hifn_crypto(struct hifn_softc *sc, struct hifn_command *cmd, | |
1589 | struct cryptop *crp, int hint) | 1620 | struct cryptop *crp, int hint) | |
1590 | { | 1621 | { | |
1591 | struct hifn_dma *dma = sc->sc_dma; | 1622 | struct hifn_dma *dma = sc->sc_dma; | |
1592 | u_int32_t cmdlen; | 1623 | u_int32_t cmdlen; | |
1593 | int cmdi, resi, s, err = 0; | 1624 | int cmdi, resi, err = 0; | |
1594 | 1625 | |||
1595 | if (bus_dmamap_create(sc->sc_dmat, HIFN_MAX_DMALEN, MAX_SCATTER, | 1626 | if (bus_dmamap_create(sc->sc_dmat, HIFN_MAX_DMALEN, MAX_SCATTER, | |
1596 | HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->src_map)) | 1627 | HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->src_map)) | |
1597 | return (ENOMEM); | 1628 | return (ENOMEM); | |
1598 | 1629 | |||
1599 | if (crp->crp_flags & CRYPTO_F_IMBUF) { | 1630 | if (crp->crp_flags & CRYPTO_F_IMBUF) { | |
1600 | if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->src_map, | 1631 | if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->src_map, | |
1601 | cmd->srcu.src_m, BUS_DMA_NOWAIT)) { | 1632 | cmd->srcu.src_m, BUS_DMA_NOWAIT)) { | |
1602 | err = ENOMEM; | 1633 | err = ENOMEM; | |
1603 | goto err_srcmap1; | 1634 | goto err_srcmap1; | |
1604 | } | 1635 | } | |
1605 | } else if (crp->crp_flags & CRYPTO_F_IOV) { | 1636 | } else if (crp->crp_flags & CRYPTO_F_IOV) { | |
1606 | if (bus_dmamap_load_uio(sc->sc_dmat, cmd->src_map, | 1637 | if (bus_dmamap_load_uio(sc->sc_dmat, cmd->src_map, | |
@@ -1710,41 +1741,37 @@ hifn_crypto(struct hifn_softc *sc, struc | @@ -1710,41 +1741,37 @@ hifn_crypto(struct hifn_softc *sc, struc | |||
1710 | #endif | 1741 | #endif | |
1711 | 1742 | |||
1712 | if (cmd->src_map == cmd->dst_map) | 1743 | if (cmd->src_map == cmd->dst_map) | |
1713 | bus_dmamap_sync(sc->sc_dmat, cmd->src_map, | 1744 | bus_dmamap_sync(sc->sc_dmat, cmd->src_map, | |
1714 | 0, cmd->src_map->dm_mapsize, | 1745 | 0, cmd->src_map->dm_mapsize, | |
1715 | BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); | 1746 | BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); | |
1716 | else { | 1747 | else { | |
1717 | bus_dmamap_sync(sc->sc_dmat, cmd->src_map, | 1748 | bus_dmamap_sync(sc->sc_dmat, cmd->src_map, | |
1718 | 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 1749 | 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
1719 | bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, | 1750 | bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, | |
1720 | 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); | 1751 | 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); | |
1721 | } | 1752 | } | |
1722 | 1753 | |||
1723 | s = splnet(); | |||
1724 | ||||
1725 | /* | 1754 | /* | |
1726 | * need 1 cmd, and 1 res | 1755 | * need 1 cmd, and 1 res | |
1727 | * need N src, and N dst | 1756 | * need N src, and N dst | |
1728 | */ | 1757 | */ | |
1729 | if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE || | 1758 | if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE || | |
1730 | (dma->resu + 1) > HIFN_D_RES_RSIZE) { | 1759 | (dma->resu + 1) > HIFN_D_RES_RSIZE) { | |
1731 | splx(s); | |||
1732 | err = ENOMEM; | 1760 | err = ENOMEM; | |
1733 | goto err_dstmap; | 1761 | goto err_dstmap; | |
1734 | } | 1762 | } | |
1735 | if ((dma->srcu + cmd->src_map->dm_nsegs) > HIFN_D_SRC_RSIZE || | 1763 | if ((dma->srcu + cmd->src_map->dm_nsegs) > HIFN_D_SRC_RSIZE || | |
1736 | (dma->dstu + cmd->dst_map->dm_nsegs + 1) > HIFN_D_DST_RSIZE) { | 1764 | (dma->dstu + cmd->dst_map->dm_nsegs + 1) > HIFN_D_DST_RSIZE) { | |
1737 | splx(s); | |||
1738 | err = ENOMEM; | 1765 | err = ENOMEM; | |
1739 | goto err_dstmap; | 1766 | goto err_dstmap; | |
1740 | } | 1767 | } | |
1741 | 1768 | |||
1742 | if (dma->cmdi == HIFN_D_CMD_RSIZE) { | 1769 | if (dma->cmdi == HIFN_D_CMD_RSIZE) { | |
1743 | dma->cmdi = 0; | 1770 | dma->cmdi = 0; | |
1744 | dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_VALID | | 1771 | dma->cmdr[HIFN_D_CMD_RSIZE].l = htole32(HIFN_D_VALID | | |
1745 | HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); | 1772 | HIFN_D_JUMP | HIFN_D_MASKDONEIRQ); | |
1746 | HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE, | 1773 | HIFN_CMDR_SYNC(sc, HIFN_D_CMD_RSIZE, | |
1747 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 1774 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
1748 | } | 1775 | } | |
1749 | cmdi = dma->cmdi++; | 1776 | cmdi = dma->cmdi++; | |
1750 | cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]); | 1777 | cmdlen = hifn_write_command(cmd, dma->command_bufs[cmdi]); | |
@@ -1827,52 +1854,50 @@ hifn_crypto(struct hifn_softc *sc, struc | @@ -1827,52 +1854,50 @@ hifn_crypto(struct hifn_softc *sc, struc | |||
1827 | if (sc->sc_d_busy == 0) { | 1854 | if (sc->sc_d_busy == 0) { | |
1828 | WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA); | 1855 | WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA); | |
1829 | sc->sc_d_busy = 1; | 1856 | sc->sc_d_busy = 1; | |
1830 | } | 1857 | } | |
1831 | 1858 | |||
1832 | #ifdef HIFN_DEBUG | 1859 | #ifdef HIFN_DEBUG | |
1833 | if (hifn_debug) | 1860 | if (hifn_debug) | |
1834 | printf("%s: command: stat %8x ier %8x\n", | 1861 | printf("%s: command: stat %8x ier %8x\n", | |
1835 | device_xname(sc->sc_dv), | 1862 | device_xname(sc->sc_dv), | |
1836 | READ_REG_1(sc, HIFN_1_DMA_CSR), READ_REG_1(sc, HIFN_1_DMA_IER)); | 1863 | READ_REG_1(sc, HIFN_1_DMA_CSR), READ_REG_1(sc, HIFN_1_DMA_IER)); | |
1837 | #endif | 1864 | #endif | |
1838 | 1865 | |||
1839 | sc->sc_active = 5; | 1866 | sc->sc_active = 5; | |
1840 | splx(s); | |||
1841 | return (err); /* success */ | 1867 | return (err); /* success */ | |
1842 | 1868 | |||
1843 | err_dstmap: | 1869 | err_dstmap: | |
1844 | if (cmd->src_map != cmd->dst_map) | 1870 | if (cmd->src_map != cmd->dst_map) | |
1845 | bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); | 1871 | bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); | |
1846 | err_dstmap1: | 1872 | err_dstmap1: | |
1847 | if (cmd->src_map != cmd->dst_map) | 1873 | if (cmd->src_map != cmd->dst_map) | |
1848 | bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); | 1874 | bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); | |
1849 | err_srcmap: | 1875 | err_srcmap: | |
1850 | if (crp->crp_flags & CRYPTO_F_IMBUF && | 1876 | if (crp->crp_flags & CRYPTO_F_IMBUF && | |
1851 | cmd->srcu.src_m != cmd->dstu.dst_m) | 1877 | cmd->srcu.src_m != cmd->dstu.dst_m) | |
1852 | m_freem(cmd->dstu.dst_m); | 1878 | m_freem(cmd->dstu.dst_m); | |
1853 | bus_dmamap_unload(sc->sc_dmat, cmd->src_map); | 1879 | bus_dmamap_unload(sc->sc_dmat, cmd->src_map); | |
1854 | err_srcmap1: | 1880 | err_srcmap1: | |
1855 | bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); | 1881 | bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); | |
1856 | return (err); | 1882 | return (err); | |
1857 | } | 1883 | } | |
1858 | 1884 | |||
1859 | static void | 1885 | static void | |
1860 | hifn_tick(void *vsc) | 1886 | hifn_tick(void *vsc) | |
1861 | { | 1887 | { | |
1862 | struct hifn_softc *sc = vsc; | 1888 | struct hifn_softc *sc = vsc; | |
1863 | int s; | |||
1864 | 1889 | |||
1865 | s = splnet(); | 1890 | mutex_spin_enter(&sc->sc_mtx); | |
1866 | if (sc->sc_active == 0) { | 1891 | if (sc->sc_active == 0) { | |
1867 | struct hifn_dma *dma = sc->sc_dma; | 1892 | struct hifn_dma *dma = sc->sc_dma; | |
1868 | u_int32_t r = 0; | 1893 | u_int32_t r = 0; | |
1869 | 1894 | |||
1870 | if (dma->cmdu == 0 && sc->sc_c_busy) { | 1895 | if (dma->cmdu == 0 && sc->sc_c_busy) { | |
1871 | sc->sc_c_busy = 0; | 1896 | sc->sc_c_busy = 0; | |
1872 | r |= HIFN_DMACSR_C_CTRL_DIS; | 1897 | r |= HIFN_DMACSR_C_CTRL_DIS; | |
1873 | CLR_LED(sc, HIFN_MIPSRST_LED0); | 1898 | CLR_LED(sc, HIFN_MIPSRST_LED0); | |
1874 | } | 1899 | } | |
1875 | if (dma->srcu == 0 && sc->sc_s_busy) { | 1900 | if (dma->srcu == 0 && sc->sc_s_busy) { | |
1876 | sc->sc_s_busy = 0; | 1901 | sc->sc_s_busy = 0; | |
1877 | r |= HIFN_DMACSR_S_CTRL_DIS; | 1902 | r |= HIFN_DMACSR_S_CTRL_DIS; | |
1878 | CLR_LED(sc, HIFN_MIPSRST_LED1); | 1903 | CLR_LED(sc, HIFN_MIPSRST_LED1); | |
@@ -1881,55 +1906,59 @@ hifn_tick(void *vsc) | @@ -1881,55 +1906,59 @@ hifn_tick(void *vsc) | |||
1881 | sc->sc_d_busy = 0; | 1906 | sc->sc_d_busy = 0; | |
1882 | r |= HIFN_DMACSR_D_CTRL_DIS; | 1907 | r |= HIFN_DMACSR_D_CTRL_DIS; | |
1883 | } | 1908 | } | |
1884 | if (dma->resu == 0 && sc->sc_r_busy) { | 1909 | if (dma->resu == 0 && sc->sc_r_busy) { | |
1885 | sc->sc_r_busy = 0; | 1910 | sc->sc_r_busy = 0; | |
1886 | r |= HIFN_DMACSR_R_CTRL_DIS; | 1911 | r |= HIFN_DMACSR_R_CTRL_DIS; | |
1887 | CLR_LED(sc, HIFN_MIPSRST_LED2); | 1912 | CLR_LED(sc, HIFN_MIPSRST_LED2); | |
1888 | } | 1913 | } | |
1889 | if (r) | 1914 | if (r) | |
1890 | WRITE_REG_1(sc, HIFN_1_DMA_CSR, r); | 1915 | WRITE_REG_1(sc, HIFN_1_DMA_CSR, r); | |
1891 | } | 1916 | } | |
1892 | else | 1917 | else | |
1893 | sc->sc_active--; | 1918 | sc->sc_active--; | |
1894 | splx(s); | |||
1895 | #ifdef __OpenBSD__ | 1919 | #ifdef __OpenBSD__ | |
1896 | timeout_add(&sc->sc_tickto, hz); | 1920 | timeout_add(&sc->sc_tickto, hz); | |
1897 | #else | 1921 | #else | |
1898 | callout_reset(&sc->sc_tickto, hz, hifn_tick, sc); | 1922 | callout_reset(&sc->sc_tickto, hz, hifn_tick, sc); | |
1899 | #endif | 1923 | #endif | |
1924 | mutex_spin_exit(&sc->sc_mtx); | |||
1900 | } | 1925 | } | |
1901 | 1926 | |||
1902 | static int | 1927 | static int | |
1903 | hifn_intr(void *arg) | 1928 | hifn_intr(void *arg) | |
1904 | { | 1929 | { | |
1905 | struct hifn_softc *sc = arg; | 1930 | struct hifn_softc *sc = arg; | |
1906 | struct hifn_dma *dma = sc->sc_dma; | 1931 | struct hifn_dma *dma = sc->sc_dma; | |
1907 | u_int32_t dmacsr, restart; | 1932 | u_int32_t dmacsr, restart; | |
1908 | int i, u; | 1933 | int i, u; | |
1909 | 1934 | |||
1910 | dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR); | 1935 | dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR); | |
1911 | 1936 | |||
1912 | #ifdef HIFN_DEBUG | 1937 | #ifdef HIFN_DEBUG | |
1913 | if (hifn_debug) | 1938 | if (hifn_debug) | |
1914 | printf("%s: irq: stat %08x ien %08x u %d/%d/%d/%d\n", | 1939 | printf("%s: irq: stat %08x ien %08x u %d/%d/%d/%d\n", | |
1915 | device_xname(sc->sc_dv), | 1940 | device_xname(sc->sc_dv), | |
1916 | dmacsr, READ_REG_1(sc, HIFN_1_DMA_IER), | 1941 | dmacsr, READ_REG_1(sc, HIFN_1_DMA_IER), | |
1917 | dma->cmdu, dma->srcu, dma->dstu, dma->resu); | 1942 | dma->cmdu, dma->srcu, dma->dstu, dma->resu); | |
1918 | #endif | 1943 | #endif | |
1919 | 1944 | |||
1945 | mutex_spin_enter(&sc->sc_mtx); | |||
1946 | ||||
1920 | /* Nothing in the DMA unit interrupted */ | 1947 | /* Nothing in the DMA unit interrupted */ | |
1921 | if ((dmacsr & sc->sc_dmaier) == 0) | 1948 | if ((dmacsr & sc->sc_dmaier) == 0) { | |
1949 | mutex_spin_exit(&sc->sc_mtx); | |||
1922 | return (0); | 1950 | return (0); | |
1951 | } | |||
1923 | 1952 | |||
1924 | WRITE_REG_1(sc, HIFN_1_DMA_CSR, dmacsr & sc->sc_dmaier); | 1953 | WRITE_REG_1(sc, HIFN_1_DMA_CSR, dmacsr & sc->sc_dmaier); | |
1925 | 1954 | |||
1926 | if (dmacsr & HIFN_DMACSR_ENGINE) | 1955 | if (dmacsr & HIFN_DMACSR_ENGINE) | |
1927 | WRITE_REG_0(sc, HIFN_0_PUISR, READ_REG_0(sc, HIFN_0_PUISR)); | 1956 | WRITE_REG_0(sc, HIFN_0_PUISR, READ_REG_0(sc, HIFN_0_PUISR)); | |
1928 | 1957 | |||
1929 | if ((sc->sc_flags & HIFN_HAS_PUBLIC) && | 1958 | if ((sc->sc_flags & HIFN_HAS_PUBLIC) && | |
1930 | (dmacsr & HIFN_DMACSR_PUBDONE)) | 1959 | (dmacsr & HIFN_DMACSR_PUBDONE)) | |
1931 | WRITE_REG_1(sc, HIFN_1_PUB_STATUS, | 1960 | WRITE_REG_1(sc, HIFN_1_PUB_STATUS, | |
1932 | READ_REG_1(sc, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE); | 1961 | READ_REG_1(sc, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE); | |
1933 | 1962 | |||
1934 | restart = dmacsr & (HIFN_DMACSR_R_OVER | HIFN_DMACSR_D_OVER); | 1963 | restart = dmacsr & (HIFN_DMACSR_R_OVER | HIFN_DMACSR_D_OVER); | |
1935 | if (restart) | 1964 | if (restart) | |
@@ -1938,27 +1967,27 @@ hifn_intr(void *arg) | @@ -1938,27 +1967,27 @@ hifn_intr(void *arg) | |||
1938 | if (sc->sc_flags & HIFN_IS_7811) { | 1967 | if (sc->sc_flags & HIFN_IS_7811) { | |
1939 | if (dmacsr & HIFN_DMACSR_ILLR) | 1968 | if (dmacsr & HIFN_DMACSR_ILLR) | |
1940 | printf("%s: illegal read\n", device_xname(sc->sc_dv)); | 1969 | printf("%s: illegal read\n", device_xname(sc->sc_dv)); | |
1941 | if (dmacsr & HIFN_DMACSR_ILLW) | 1970 | if (dmacsr & HIFN_DMACSR_ILLW) | |
1942 | printf("%s: illegal write\n", device_xname(sc->sc_dv)); | 1971 | printf("%s: illegal write\n", device_xname(sc->sc_dv)); | |
1943 | } | 1972 | } | |
1944 | 1973 | |||
1945 | restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT | | 1974 | restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT | | |
1946 | HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT); | 1975 | HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT); | |
1947 | if (restart) { | 1976 | if (restart) { | |
1948 | printf("%s: abort, resetting.\n", device_xname(sc->sc_dv)); | 1977 | printf("%s: abort, resetting.\n", device_xname(sc->sc_dv)); | |
1949 | hifnstats.hst_abort++; | 1978 | hifnstats.hst_abort++; | |
1950 | hifn_abort(sc); | 1979 | hifn_abort(sc); | |
1951 | return (1); | 1980 | goto out; | |
1952 | } | 1981 | } | |
1953 | 1982 | |||
1954 | if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->resu == 0)) { | 1983 | if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->resu == 0)) { | |
1955 | /* | 1984 | /* | |
1956 | * If no slots to process and we receive a "waiting on | 1985 | * If no slots to process and we receive a "waiting on | |
1957 | * command" interrupt, we disable the "waiting on command" | 1986 | * command" interrupt, we disable the "waiting on command" | |
1958 | * (by clearing it). | 1987 | * (by clearing it). | |
1959 | */ | 1988 | */ | |
1960 | sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT; | 1989 | sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT; | |
1961 | WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); | 1990 | WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier); | |
1962 | } | 1991 | } | |
1963 | 1992 | |||
1964 | /* clear the rings */ | 1993 | /* clear the rings */ | |
@@ -2016,149 +2045,169 @@ hifn_intr(void *arg) | @@ -2016,149 +2045,169 @@ hifn_intr(void *arg) | |||
2016 | HIFN_CMDR_SYNC(sc, i, | 2045 | HIFN_CMDR_SYNC(sc, i, | |
2017 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | 2046 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | |
2018 | break; | 2047 | break; | |
2019 | } | 2048 | } | |
2020 | if (i != HIFN_D_CMD_RSIZE) { | 2049 | if (i != HIFN_D_CMD_RSIZE) { | |
2021 | u--; | 2050 | u--; | |
2022 | HIFN_CMD_SYNC(sc, i, BUS_DMASYNC_POSTWRITE); | 2051 | HIFN_CMD_SYNC(sc, i, BUS_DMASYNC_POSTWRITE); | |
2023 | } | 2052 | } | |
2024 | if (++i == (HIFN_D_CMD_RSIZE + 1)) | 2053 | if (++i == (HIFN_D_CMD_RSIZE + 1)) | |
2025 | i = 0; | 2054 | i = 0; | |
2026 | } | 2055 | } | |
2027 | dma->cmdk = i; dma->cmdu = u; | 2056 | dma->cmdk = i; dma->cmdu = u; | |
2028 | 2057 | |||
2058 | out: | |||
2059 | mutex_spin_exit(&sc->sc_mtx); | |||
2029 | return (1); | 2060 | return (1); | |
2030 | } | 2061 | } | |
2031 | 2062 | |||
2032 | /* | 2063 | /* | |
2033 | * Allocate a new 'session' and return an encoded session id. 'sidp' | 2064 | * Allocate a new 'session' and return an encoded session id. 'sidp' | |
2034 | * contains our registration id, and should contain an encoded session | 2065 | * contains our registration id, and should contain an encoded session | |
2035 | * id on successful allocation. | 2066 | * id on successful allocation. | |
2036 | */ | 2067 | */ | |
2037 | static int | 2068 | static int | |
2038 | hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri) | 2069 | hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri) | |
2039 | { | 2070 | { | |
2040 | struct cryptoini *c; | 2071 | struct cryptoini *c; | |
2041 | struct hifn_softc *sc = arg; | 2072 | struct hifn_softc *sc = arg; | |
2042 | int i, mac = 0, cry = 0, comp = 0; | 2073 | int i, mac = 0, cry = 0, comp = 0, retval = EINVAL; | |
2043 | 2074 | |||
2044 | KASSERT(sc != NULL /*, ("hifn_newsession: null softc")*/); | 2075 | KASSERT(sc != NULL /*, ("hifn_newsession: null softc")*/); | |
2045 | if (sidp == NULL || cri == NULL || sc == NULL) | 2076 | if (sidp == NULL || cri == NULL || sc == NULL) | |
2046 | return (EINVAL); | 2077 | return retval; | |
2078 | ||||
2079 | mutex_spin_enter(&sc->sc_mtx); | |||
2047 | 2080 | |||
2048 | for (i = 0; i < sc->sc_maxses; i++) | 2081 | for (i = 0; i < sc->sc_maxses; i++) | |
2049 | if (sc->sc_sessions[i].hs_state == HS_STATE_FREE) | 2082 | if (sc->sc_sessions[i].hs_state == HS_STATE_FREE) | |
2050 | break; | 2083 | break; | |
2051 | if (i == sc->sc_maxses) | 2084 | if (i == sc->sc_maxses) { | |
2052 | return (ENOMEM); | 2085 | retval = ENOMEM; | |
2086 | goto out; | |||
2087 | } | |||
2053 | 2088 | |||
2054 | for (c = cri; c != NULL; c = c->cri_next) { | 2089 | for (c = cri; c != NULL; c = c->cri_next) { | |
2055 | switch (c->cri_alg) { | 2090 | switch (c->cri_alg) { | |
2056 | case CRYPTO_MD5: | 2091 | case CRYPTO_MD5: | |
2057 | case CRYPTO_SHA1: | 2092 | case CRYPTO_SHA1: | |
2058 | case CRYPTO_MD5_HMAC_96: | 2093 | case CRYPTO_MD5_HMAC_96: | |
2059 | case CRYPTO_SHA1_HMAC_96: | 2094 | case CRYPTO_SHA1_HMAC_96: | |
2060 | if (mac) | 2095 | if (mac) { | |
2061 | return (EINVAL); | 2096 | goto out; | |
2097 | } | |||
2062 | mac = 1; | 2098 | mac = 1; | |
2063 | break; | 2099 | break; | |
2064 | case CRYPTO_DES_CBC: | 2100 | case CRYPTO_DES_CBC: | |
2065 | case CRYPTO_3DES_CBC: | 2101 | case CRYPTO_3DES_CBC: | |
2066 | case CRYPTO_AES_CBC: | 2102 | case CRYPTO_AES_CBC: | |
2067 | /* Note that this is an initialization | 2103 | /* Note that this is an initialization | |
2068 | vector, not a cipher key; any function | 2104 | vector, not a cipher key; any function | |
2069 | giving sufficient Hamming distance | 2105 | giving sufficient Hamming distance | |
2070 | between outputs is fine. Use of RC4 | 2106 | between outputs is fine. Use of RC4 | |
2071 | to generate IVs has been FIPS140-2 | 2107 | to generate IVs has been FIPS140-2 | |
2072 | certified by several labs. */ | 2108 | certified by several labs. */ | |
2073 | #ifdef __NetBSD__ | 2109 | #ifdef __NetBSD__ | |
2074 | cprng_fast(sc->sc_sessions[i].hs_iv, | 2110 | cprng_fast(sc->sc_sessions[i].hs_iv, | |
2075 | c->cri_alg == CRYPTO_AES_CBC ? | 2111 | c->cri_alg == CRYPTO_AES_CBC ? | |
2076 | HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); | 2112 | HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); | |
2077 | #else /* FreeBSD and OpenBSD have get_random_bytes */ | 2113 | #else /* FreeBSD and OpenBSD have get_random_bytes */ | |
2078 | /* XXX this may read fewer, does it matter? */ | 2114 | /* XXX this may read fewer, does it matter? */ | |
2079 | get_random_bytes(sc->sc_sessions[i].hs_iv, | 2115 | get_random_bytes(sc->sc_sessions[i].hs_iv, | |
2080 | c->cri_alg == CRYPTO_AES_CBC ? | 2116 | c->cri_alg == CRYPTO_AES_CBC ? | |
2081 | HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); | 2117 | HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH); | |
2082 | #endif | 2118 | #endif | |
2083 | /*FALLTHROUGH*/ | 2119 | /*FALLTHROUGH*/ | |
2084 | case CRYPTO_ARC4: | 2120 | case CRYPTO_ARC4: | |
2085 | if (cry) | 2121 | if (cry) { | |
2086 | return (EINVAL); | 2122 | goto out; | |
2123 | } | |||
2087 | cry = 1; | 2124 | cry = 1; | |
2088 | break; | 2125 | break; | |
2089 | #ifdef HAVE_CRYPTO_LZS | 2126 | #ifdef HAVE_CRYPTO_LZS | |
2090 | case CRYPTO_LZS_COMP: | 2127 | case CRYPTO_LZS_COMP: | |
2091 | if (comp) | 2128 | if (comp) { | |
2092 | return (EINVAL); | 2129 | goto out; | |
2130 | } | |||
2093 | comp = 1; | 2131 | comp = 1; | |
2094 | break; | 2132 | break; | |
2095 | #endif | 2133 | #endif | |
2096 | default: | 2134 | default: | |
2097 | return (EINVAL); | 2135 | goto out; | |
2098 | } | 2136 | } | |
2099 | } | 2137 | } | |
2100 | if (mac == 0 && cry == 0 && comp == 0) | 2138 | if (mac == 0 && cry == 0 && comp == 0) { | |
2101 | return (EINVAL); | 2139 | goto out; | |
2140 | } | |||
2102 | 2141 | |||
2103 | /* | 2142 | /* | |
2104 | * XXX only want to support compression without chaining to | 2143 | * XXX only want to support compression without chaining to | |
2105 | * MAC/crypt engine right now | 2144 | * MAC/crypt engine right now | |
2106 | */ | 2145 | */ | |
2107 | if ((comp && mac) || (comp && cry)) | 2146 | if ((comp && mac) || (comp && cry)) { | |
2108 | return (EINVAL); | 2147 | goto out; | |
2148 | } | |||
2109 | 2149 | |||
2110 | *sidp = HIFN_SID(device_unit(sc->sc_dv), i); | 2150 | *sidp = HIFN_SID(device_unit(sc->sc_dv), i); | |
2111 | sc->sc_sessions[i].hs_state = HS_STATE_USED; | 2151 | sc->sc_sessions[i].hs_state = HS_STATE_USED; | |
2112 | 2152 | |||
2113 | return (0); | 2153 | retval = 0; | |
2154 | out: | |||
2155 | mutex_spin_exit(&sc->sc_mtx); | |||
2156 | return retval; | |||
2114 | } | 2157 | } | |
2115 | 2158 | |||
2116 | /* | 2159 | /* | |
2117 | * Deallocate a session. | 2160 | * Deallocate a session. | |
2118 | * XXX this routine should run a zero'd mac/encrypt key into context ram. | 2161 | * XXX this routine should run a zero'd mac/encrypt key into context ram. | |
2119 | * XXX to blow away any keys already stored there. | 2162 | * XXX to blow away any keys already stored there. | |
2120 | */ | 2163 | */ | |
2121 | static int | 2164 | static int | |
2122 | hifn_freesession(void *arg, u_int64_t tid) | 2165 | hifn_freesession(void *arg, u_int64_t tid) | |
2123 | { | 2166 | { | |
2124 | struct hifn_softc *sc = arg; | 2167 | struct hifn_softc *sc = arg; | |
2125 | int session; | 2168 | int session; | |
2126 | u_int32_t sid = ((u_int32_t) tid) & 0xffffffff; | 2169 | u_int32_t sid = ((u_int32_t) tid) & 0xffffffff; | |
2127 | 2170 | |||
2128 | KASSERT(sc != NULL /*, ("hifn_freesession: null softc")*/); | 2171 | KASSERT(sc != NULL /*, ("hifn_freesession: null softc")*/); | |
2129 | if (sc == NULL) | 2172 | if (sc == NULL) | |
2130 | return (EINVAL); | 2173 | return (EINVAL); | |
2131 | 2174 | |||
2175 | mutex_spin_enter(&sc->sc_mtx); | |||
2132 | session = HIFN_SESSION(sid); | 2176 | session = HIFN_SESSION(sid); | |
2133 | if (session >= sc->sc_maxses) | 2177 | if (session >= sc->sc_maxses) { | |
2178 | mutex_spin_exit(&sc->sc_mtx); | |||
2134 | return (EINVAL); | 2179 | return (EINVAL); | |
2180 | } | |||
2135 | 2181 | |||
2136 | memset(&sc->sc_sessions[session], 0, sizeof(sc->sc_sessions[session])); | 2182 | memset(&sc->sc_sessions[session], 0, sizeof(sc->sc_sessions[session])); | |
2183 | mutex_spin_exit(&sc->sc_mtx); | |||
2137 | return (0); | 2184 | return (0); | |
2138 | } | 2185 | } | |
2139 | 2186 | |||
2140 | static int | 2187 | static int | |
2141 | hifn_process(void *arg, struct cryptop *crp, int hint) | 2188 | hifn_process(void *arg, struct cryptop *crp, int hint) | |
2142 | { | 2189 | { | |
2143 | struct hifn_softc *sc = arg; | 2190 | struct hifn_softc *sc = arg; | |
2144 | struct hifn_command *cmd = NULL; | 2191 | struct hifn_command *cmd = NULL; | |
2145 | int session, err, ivlen; | 2192 | int session, err, ivlen; | |
2146 | struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; | 2193 | struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; | |
2147 | 2194 | |||
2148 | if (crp == NULL || crp->crp_callback == NULL) { | 2195 | if (crp == NULL || crp->crp_callback == NULL) { | |
2149 | hifnstats.hst_invalid++; | 2196 | hifnstats.hst_invalid++; | |
2150 | return (EINVAL); | 2197 | return (EINVAL); | |
2151 | } | 2198 | } | |
2199 | ||||
2200 | mutex_spin_enter(&sc->sc_mtx); | |||
2152 | session = HIFN_SESSION(crp->crp_sid); | 2201 | session = HIFN_SESSION(crp->crp_sid); | |
2153 | 2202 | |||
2154 | if (sc == NULL || session >= sc->sc_maxses) { | 2203 | if (sc == NULL || session >= sc->sc_maxses) { | |
2155 | err = EINVAL; | 2204 | err = EINVAL; | |
2156 | goto errout; | 2205 | goto errout; | |
2157 | } | 2206 | } | |
2158 | 2207 | |||
2159 | cmd = (struct hifn_command *)malloc(sizeof(struct hifn_command), | 2208 | cmd = (struct hifn_command *)malloc(sizeof(struct hifn_command), | |
2160 | M_DEVBUF, M_NOWAIT|M_ZERO); | 2209 | M_DEVBUF, M_NOWAIT|M_ZERO); | |
2161 | if (cmd == NULL) { | 2210 | if (cmd == NULL) { | |
2162 | hifnstats.hst_nomem++; | 2211 | hifnstats.hst_nomem++; | |
2163 | err = ENOMEM; | 2212 | err = ENOMEM; | |
2164 | goto errout; | 2213 | goto errout; | |
@@ -2367,50 +2416,53 @@ hifn_process(void *arg, struct cryptop * | @@ -2367,50 +2416,53 @@ hifn_process(void *arg, struct cryptop * | |||
2367 | } | 2416 | } | |
2368 | 2417 | |||
2369 | cmd->crp = crp; | 2418 | cmd->crp = crp; | |
2370 | cmd->session_num = session; | 2419 | cmd->session_num = session; | |
2371 | cmd->softc = sc; | 2420 | cmd->softc = sc; | |
2372 | 2421 | |||
2373 | err = hifn_crypto(sc, cmd, crp, hint); | 2422 | err = hifn_crypto(sc, cmd, crp, hint); | |
2374 | if (err == 0) { | 2423 | if (err == 0) { | |
2375 | if (enccrd) | 2424 | if (enccrd) | |
2376 | sc->sc_sessions[session].hs_prev_op = | 2425 | sc->sc_sessions[session].hs_prev_op = | |
2377 | enccrd->crd_flags & CRD_F_ENCRYPT; | 2426 | enccrd->crd_flags & CRD_F_ENCRYPT; | |
2378 | if (sc->sc_sessions[session].hs_state == HS_STATE_USED) | 2427 | if (sc->sc_sessions[session].hs_state == HS_STATE_USED) | |
2379 | sc->sc_sessions[session].hs_state = HS_STATE_KEY; | 2428 | sc->sc_sessions[session].hs_state = HS_STATE_KEY; | |
2429 | mutex_spin_exit(&sc->sc_mtx); | |||
2380 | return 0; | 2430 | return 0; | |
2381 | } else if (err == ERESTART) { | 2431 | } else if (err == ERESTART) { | |
2382 | /* | 2432 | /* | |
2383 | * There weren't enough resources to dispatch the request | 2433 | * There weren't enough resources to dispatch the request | |
2384 | * to the part. Notify the caller so they'll requeue this | 2434 | * to the part. Notify the caller so they'll requeue this | |
2385 | * request and resubmit it again soon. | 2435 | * request and resubmit it again soon. | |
2386 | */ | 2436 | */ | |
2387 | #ifdef HIFN_DEBUG | 2437 | #ifdef HIFN_DEBUG | |
2388 | if (hifn_debug) | 2438 | if (hifn_debug) | |
2389 | printf("%s: requeue request\n", device_xname(sc->sc_dv)); | 2439 | printf("%s: requeue request\n", device_xname(sc->sc_dv)); | |
2390 | #endif | 2440 | #endif | |
2391 | free(cmd, M_DEVBUF); | 2441 | free(cmd, M_DEVBUF); | |
2392 | sc->sc_needwakeup |= CRYPTO_SYMQ; | 2442 | sc->sc_needwakeup |= CRYPTO_SYMQ; | |
2443 | mutex_spin_exit(&sc->sc_mtx); | |||
2393 | return (err); | 2444 | return (err); | |
2394 | } | 2445 | } | |
2395 | 2446 | |||
2396 | errout: | 2447 | errout: | |
2397 | if (cmd != NULL) | 2448 | if (cmd != NULL) | |
2398 | free(cmd, M_DEVBUF); | 2449 | free(cmd, M_DEVBUF); | |
2399 | if (err == EINVAL) | 2450 | if (err == EINVAL) | |
2400 | hifnstats.hst_invalid++; | 2451 | hifnstats.hst_invalid++; | |
2401 | else | 2452 | else | |
2402 | hifnstats.hst_nomem++; | 2453 | hifnstats.hst_nomem++; | |
2403 | crp->crp_etype = err; | 2454 | crp->crp_etype = err; | |
2455 | mutex_spin_exit(&sc->sc_mtx); | |||
2404 | crypto_done(crp); | 2456 | crypto_done(crp); | |
2405 | return (0); | 2457 | return (0); | |
2406 | } | 2458 | } | |
2407 | 2459 | |||
2408 | static void | 2460 | static void | |
2409 | hifn_abort(struct hifn_softc *sc) | 2461 | hifn_abort(struct hifn_softc *sc) | |
2410 | { | 2462 | { | |
2411 | struct hifn_dma *dma = sc->sc_dma; | 2463 | struct hifn_dma *dma = sc->sc_dma; | |
2412 | struct hifn_command *cmd; | 2464 | struct hifn_command *cmd; | |
2413 | struct cryptop *crp; | 2465 | struct cryptop *crp; | |
2414 | int i, u; | 2466 | int i, u; | |
2415 | 2467 | |||
2416 | i = dma->resk; u = dma->resu; | 2468 | i = dma->resk; u = dma->resu; | |
@@ -2706,58 +2758,53 @@ hifn_compression(struct hifn_softc *sc, | @@ -2706,58 +2758,53 @@ hifn_compression(struct hifn_softc *sc, | |||
2706 | bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, | 2758 | bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, | |
2707 | 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); | 2759 | 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); | |
2708 | } | 2760 | } | |
2709 | 2761 | |||
2710 | cmd->crp = crp; | 2762 | cmd->crp = crp; | |
2711 | /* | 2763 | /* | |
2712 | * Always use session 0. The modes of compression we use are | 2764 | * Always use session 0. The modes of compression we use are | |
2713 | * stateless and there is always at least one compression | 2765 | * stateless and there is always at least one compression | |
2714 | * context, zero. | 2766 | * context, zero. | |
2715 | */ | 2767 | */ | |
2716 | cmd->session_num = 0; | 2768 | cmd->session_num = 0; | |
2717 | cmd->softc = sc; | 2769 | cmd->softc = sc; | |
2718 | 2770 | |||
2719 | s = splnet(); | |||
2720 | err = hifn_compress_enter(sc, cmd); | 2771 | err = hifn_compress_enter(sc, cmd); | |
2721 | splx(s); | |||
2722 | 2772 | |||
2723 | if (err != 0) | 2773 | if (err != 0) | |
2724 | goto fail; | 2774 | goto fail; | |
2725 | return (0); | 2775 | return (0); | |
2726 | 2776 | |||
2727 | fail: | 2777 | fail: | |
2728 | if (cmd->dst_map != NULL) { | 2778 | if (cmd->dst_map != NULL) { | |
2729 | if (cmd->dst_map->dm_nsegs > 0) | 2779 | if (cmd->dst_map->dm_nsegs > 0) | |
2730 | bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); | 2780 | bus_dmamap_unload(sc->sc_dmat, cmd->dst_map); | |
2731 | bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); | 2781 | bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map); | |
2732 | } | 2782 | } | |
2733 | if (cmd->src_map != NULL) { | 2783 | if (cmd->src_map != NULL) { | |
2734 | if (cmd->src_map->dm_nsegs > 0) | 2784 | if (cmd->src_map->dm_nsegs > 0) | |
2735 | bus_dmamap_unload(sc->sc_dmat, cmd->src_map); | 2785 | bus_dmamap_unload(sc->sc_dmat, cmd->src_map); | |
2736 | bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); | 2786 | bus_dmamap_destroy(sc->sc_dmat, cmd->src_map); | |
2737 | } | 2787 | } | |
2738 | free(cmd, M_DEVBUF); | 2788 | free(cmd, M_DEVBUF); | |
2739 | if (err == EINVAL) | 2789 | if (err == EINVAL) | |
2740 | hifnstats.hst_invalid++; | 2790 | hifnstats.hst_invalid++; | |
2741 | else | 2791 | else | |
2742 | hifnstats.hst_nomem++; | 2792 | hifnstats.hst_nomem++; | |
2743 | crp->crp_etype = err; | 2793 | crp->crp_etype = err; | |
2744 | crypto_done(crp); | 2794 | crypto_done(crp); | |
2745 | return (0); | 2795 | return (0); | |
2746 | } | 2796 | } | |
2747 | 2797 | |||
2748 | /* | |||
2749 | * must be called at splnet() | |||
2750 | */ | |||
2751 | static int | 2798 | static int | |
2752 | hifn_compress_enter(struct hifn_softc *sc, struct hifn_command *cmd) | 2799 | hifn_compress_enter(struct hifn_softc *sc, struct hifn_command *cmd) | |
2753 | { | 2800 | { | |
2754 | struct hifn_dma *dma = sc->sc_dma; | 2801 | struct hifn_dma *dma = sc->sc_dma; | |
2755 | int cmdi, resi; | 2802 | int cmdi, resi; | |
2756 | u_int32_t cmdlen; | 2803 | u_int32_t cmdlen; | |
2757 | 2804 | |||
2758 | if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE || | 2805 | if ((dma->cmdu + 1) > HIFN_D_CMD_RSIZE || | |
2759 | (dma->resu + 1) > HIFN_D_CMD_RSIZE) | 2806 | (dma->resu + 1) > HIFN_D_CMD_RSIZE) | |
2760 | return (ENOMEM); | 2807 | return (ENOMEM); | |
2761 | 2808 | |||
2762 | if ((dma->srcu + cmd->src_map->dm_nsegs) > HIFN_D_SRC_RSIZE || | 2809 | if ((dma->srcu + cmd->src_map->dm_nsegs) > HIFN_D_SRC_RSIZE || | |
2763 | (dma->dstu + cmd->dst_map->dm_nsegs) > HIFN_D_DST_RSIZE) | 2810 | (dma->dstu + cmd->dst_map->dm_nsegs) > HIFN_D_DST_RSIZE) | |
@@ -2911,27 +2958,26 @@ hifn_callback_comp(struct hifn_softc *sc | @@ -2911,27 +2958,26 @@ hifn_callback_comp(struct hifn_softc *sc | |||
2911 | goto out; | 2958 | goto out; | |
2912 | } | 2959 | } | |
2913 | if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->dst_map, | 2960 | if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->dst_map, | |
2914 | cmd->dstu.dst_m, BUS_DMA_NOWAIT)) { | 2961 | cmd->dstu.dst_m, BUS_DMA_NOWAIT)) { | |
2915 | err = ENOMEM; | 2962 | err = ENOMEM; | |
2916 | goto out; | 2963 | goto out; | |
2917 | } | 2964 | } | |
2918 | 2965 | |||
2919 | bus_dmamap_sync(sc->sc_dmat, cmd->src_map, | 2966 | bus_dmamap_sync(sc->sc_dmat, cmd->src_map, | |
2920 | 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 2967 | 0, cmd->src_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
2921 | bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, | 2968 | bus_dmamap_sync(sc->sc_dmat, cmd->dst_map, | |
2922 | 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); | 2969 | 0, cmd->dst_map->dm_mapsize, BUS_DMASYNC_PREREAD); | |
2923 | 2970 | |||
2924 | /* already at splnet... */ | |||
2925 | err = hifn_compress_enter(sc, cmd); | 2971 | err = hifn_compress_enter(sc, cmd); | |
2926 | if (err != 0) | 2972 | if (err != 0) | |
2927 | goto out; | 2973 | goto out; | |
2928 | return; | 2974 | return; | |
2929 | } | 2975 | } | |
2930 | 2976 | |||
2931 | olen = dstsize - (letoh16(baseres.dst_cnt) | | 2977 | olen = dstsize - (letoh16(baseres.dst_cnt) | | |
2932 | (((letoh16(baseres.session) & HIFN_BASE_RES_DSTLEN_M) >> | 2978 | (((letoh16(baseres.session) & HIFN_BASE_RES_DSTLEN_M) >> | |
2933 | HIFN_BASE_RES_DSTLEN_S) << 16)); | 2979 | HIFN_BASE_RES_DSTLEN_S) << 16)); | |
2934 | 2980 | |||
2935 | crp->crp_olen = olen - cmd->compcrd->crd_skip; | 2981 | crp->crp_olen = olen - cmd->compcrd->crd_skip; | |
2936 | 2982 | |||
2937 | bus_dmamap_unload(sc->sc_dmat, cmd->src_map); | 2983 | bus_dmamap_unload(sc->sc_dmat, cmd->src_map); |
--- src/sys/dev/pci/ubsec.c 2012/10/27 17:18:35 1.28
+++ src/sys/dev/pci/ubsec.c 2013/06/13 00:55:01 1.29
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ubsec.c,v 1.28 2012/10/27 17:18:35 chs Exp $ */ | 1 | /* $NetBSD: ubsec.c,v 1.29 2013/06/13 00:55:01 tls Exp $ */ | |
2 | /* $FreeBSD: src/sys/dev/ubsec/ubsec.c,v 1.6.2.6 2003/01/23 21:06:43 sam Exp $ */ | 2 | /* $FreeBSD: src/sys/dev/ubsec/ubsec.c,v 1.6.2.6 2003/01/23 21:06:43 sam Exp $ */ | |
3 | /* $OpenBSD: ubsec.c,v 1.127 2003/06/04 14:04:58 jason Exp $ */ | 3 | /* $OpenBSD: ubsec.c,v 1.127 2003/06/04 14:04:58 jason Exp $ */ | |
4 | 4 | |||
5 | /* | 5 | /* | |
6 | * Copyright (c) 2000 Jason L. Wright (jason@thought.net) | 6 | * Copyright (c) 2000 Jason L. Wright (jason@thought.net) | |
7 | * Copyright (c) 2000 Theo de Raadt (deraadt@openbsd.org) | 7 | * Copyright (c) 2000 Theo de Raadt (deraadt@openbsd.org) | |
8 | * Copyright (c) 2001 Patrik Lindergren (patrik@ipunplugged.com) | 8 | * Copyright (c) 2001 Patrik Lindergren (patrik@ipunplugged.com) | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -25,42 +25,42 @@ | @@ -25,42 +25,42 @@ | |||
25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
27 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | 27 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | * | 30 | * | |
31 | * Effort sponsored in part by the Defense Advanced Research Projects | 31 | * Effort sponsored in part by the Defense Advanced Research Projects | |
32 | * Agency (DARPA) and Air Force Research Laboratory, Air Force | 32 | * Agency (DARPA) and Air Force Research Laboratory, Air Force | |
33 | * Materiel Command, USAF, under agreement number F30602-01-2-0537. | 33 | * Materiel Command, USAF, under agreement number F30602-01-2-0537. | |
34 | * | 34 | * | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __KERNEL_RCSID(0, "$NetBSD: ubsec.c,v 1.28 2012/10/27 17:18:35 chs Exp $"); | 38 | __KERNEL_RCSID(0, "$NetBSD: ubsec.c,v 1.29 2013/06/13 00:55:01 tls Exp $"); | |
39 | 39 | |||
40 | #undef UBSEC_DEBUG | 40 | #undef UBSEC_DEBUG | |
41 | 41 | |||
42 | /* | 42 | /* | |
43 | * uBsec 5[56]01, bcm580xx, bcm582x hardware crypto accelerator | 43 | * uBsec 5[56]01, bcm580xx, bcm582x hardware crypto accelerator | |
44 | */ | 44 | */ | |
45 | 45 | |||
46 | #include <sys/param.h> | 46 | #include <sys/param.h> | |
47 | #include <sys/systm.h> | 47 | #include <sys/systm.h> | |
48 | #include <sys/proc.h> | 48 | #include <sys/proc.h> | |
49 | #include <sys/endian.h> | 49 | #include <sys/endian.h> | |
50 | #ifdef __NetBSD__ | 50 | #ifdef __NetBSD__ | |
51 | #define UBSEC_NO_RNG /* hangs on attach */ | |||
51 | #define letoh16 htole16 | 52 | #define letoh16 htole16 | |
52 | #define letoh32 htole32 | 53 | #define letoh32 htole32 | |
53 | #define UBSEC_NO_RNG /* until statistically tested */ | |||
54 | #endif | 54 | #endif | |
55 | #include <sys/errno.h> | 55 | #include <sys/errno.h> | |
56 | #include <sys/malloc.h> | 56 | #include <sys/malloc.h> | |
57 | #include <sys/kernel.h> | 57 | #include <sys/kernel.h> | |
58 | #include <sys/mbuf.h> | 58 | #include <sys/mbuf.h> | |
59 | #include <sys/device.h> | 59 | #include <sys/device.h> | |
60 | #include <sys/queue.h> | 60 | #include <sys/queue.h> | |
61 | 61 | |||
62 | #include <opencrypto/cryptodev.h> | 62 | #include <opencrypto/cryptodev.h> | |
63 | #include <opencrypto/xform.h> | 63 | #include <opencrypto/xform.h> | |
64 | #ifdef __OpenBSD__ | 64 | #ifdef __OpenBSD__ | |
65 | #include <dev/rndvar.h> | 65 | #include <dev/rndvar.h> | |
66 | #include <sys/md5k.h> | 66 | #include <sys/md5k.h> | |
@@ -109,27 +109,29 @@ extern int ubsec_debug; | @@ -109,27 +109,29 @@ extern int ubsec_debug; | |||
109 | int ubsec_debug=1; | 109 | int ubsec_debug=1; | |
110 | #endif | 110 | #endif | |
111 | 111 | |||
112 | static int ubsec_intr(void *); | 112 | static int ubsec_intr(void *); | |
113 | static int ubsec_newsession(void*, u_int32_t *, struct cryptoini *); | 113 | static int ubsec_newsession(void*, u_int32_t *, struct cryptoini *); | |
114 | static int ubsec_freesession(void*, u_int64_t); | 114 | static int ubsec_freesession(void*, u_int64_t); | |
115 | static int ubsec_process(void*, struct cryptop *, int hint); | 115 | static int ubsec_process(void*, struct cryptop *, int hint); | |
116 | static void ubsec_callback(struct ubsec_softc *, struct ubsec_q *); | 116 | static void ubsec_callback(struct ubsec_softc *, struct ubsec_q *); | |
117 | static void ubsec_feed(struct ubsec_softc *); | 117 | static void ubsec_feed(struct ubsec_softc *); | |
118 | static void ubsec_mcopy(struct mbuf *, struct mbuf *, int, int); | 118 | static void ubsec_mcopy(struct mbuf *, struct mbuf *, int, int); | |
119 | static void ubsec_callback2(struct ubsec_softc *, struct ubsec_q2 *); | 119 | static void ubsec_callback2(struct ubsec_softc *, struct ubsec_q2 *); | |
120 | static void ubsec_feed2(struct ubsec_softc *); | 120 | static void ubsec_feed2(struct ubsec_softc *); | |
121 | #ifndef UBSEC_NO_RNG | 121 | #ifndef UBSEC_NO_RNG | |
122 | static void ubsec_rng(void *); | 122 | static void ubsec_rng(void *); | |
123 | static void ubsec_rng_locked(void *); | |||
124 | static void ubsec_rng_get(size_t, void *); | |||
123 | #endif /* UBSEC_NO_RNG */ | 125 | #endif /* UBSEC_NO_RNG */ | |
124 | static int ubsec_dma_malloc(struct ubsec_softc *, bus_size_t, | 126 | static int ubsec_dma_malloc(struct ubsec_softc *, bus_size_t, | |
125 | struct ubsec_dma_alloc *, int); | 127 | struct ubsec_dma_alloc *, int); | |
126 | static void ubsec_dma_free(struct ubsec_softc *, struct ubsec_dma_alloc *); | 128 | static void ubsec_dma_free(struct ubsec_softc *, struct ubsec_dma_alloc *); | |
127 | static int ubsec_dmamap_aligned(bus_dmamap_t); | 129 | static int ubsec_dmamap_aligned(bus_dmamap_t); | |
128 | 130 | |||
129 | static int ubsec_kprocess(void*, struct cryptkop *, int); | 131 | static int ubsec_kprocess(void*, struct cryptkop *, int); | |
130 | static int ubsec_kprocess_modexp_sw(struct ubsec_softc *, | 132 | static int ubsec_kprocess_modexp_sw(struct ubsec_softc *, | |
131 | struct cryptkop *, int); | 133 | struct cryptkop *, int); | |
132 | static int ubsec_kprocess_modexp_hw(struct ubsec_softc *, | 134 | static int ubsec_kprocess_modexp_hw(struct ubsec_softc *, | |
133 | struct cryptkop *, int); | 135 | struct cryptkop *, int); | |
134 | static int ubsec_kprocess_rsapriv(struct ubsec_softc *, | 136 | static int ubsec_kprocess_rsapriv(struct ubsec_softc *, | |
135 | struct cryptkop *, int); | 137 | struct cryptkop *, int); | |
@@ -349,26 +351,29 @@ ubsec_attach(device_t parent, device_t s | @@ -349,26 +351,29 @@ ubsec_attach(device_t parent, device_t s | |||
349 | aprint_error(" at %s", intrstr); | 351 | aprint_error(" at %s", intrstr); | |
350 | aprint_error("\n"); | 352 | aprint_error("\n"); | |
351 | return; | 353 | return; | |
352 | } | 354 | } | |
353 | aprint_normal_dev(self, "interrupting at %s\n", intrstr); | 355 | aprint_normal_dev(self, "interrupting at %s\n", intrstr); | |
354 | 356 | |||
355 | sc->sc_cid = crypto_get_driverid(0); | 357 | sc->sc_cid = crypto_get_driverid(0); | |
356 | if (sc->sc_cid < 0) { | 358 | if (sc->sc_cid < 0) { | |
357 | aprint_error_dev(self, "couldn't get crypto driver id\n"); | 359 | aprint_error_dev(self, "couldn't get crypto driver id\n"); | |
358 | pci_intr_disestablish(pc, sc->sc_ih); | 360 | pci_intr_disestablish(pc, sc->sc_ih); | |
359 | return; | 361 | return; | |
360 | } | 362 | } | |
361 | 363 | |||
364 | sc->sc_rng_need = RND_POOLBITS / NBBY; | |||
365 | mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM); | |||
366 | ||||
362 | SIMPLEQ_INIT(&sc->sc_freequeue); | 367 | SIMPLEQ_INIT(&sc->sc_freequeue); | |
363 | dmap = sc->sc_dmaa; | 368 | dmap = sc->sc_dmaa; | |
364 | for (i = 0; i < UBS_MAX_NQUEUE; i++, dmap++) { | 369 | for (i = 0; i < UBS_MAX_NQUEUE; i++, dmap++) { | |
365 | struct ubsec_q *q; | 370 | struct ubsec_q *q; | |
366 | 371 | |||
367 | q = (struct ubsec_q *)malloc(sizeof(struct ubsec_q), | 372 | q = (struct ubsec_q *)malloc(sizeof(struct ubsec_q), | |
368 | M_DEVBUF, M_NOWAIT); | 373 | M_DEVBUF, M_NOWAIT); | |
369 | if (q == NULL) { | 374 | if (q == NULL) { | |
370 | aprint_error_dev(self, "can't allocate queue buffers\n"); | 375 | aprint_error_dev(self, "can't allocate queue buffers\n"); | |
371 | break; | 376 | break; | |
372 | } | 377 | } | |
373 | 378 | |||
374 | if (ubsec_dma_malloc(sc, sizeof(struct ubsec_dmachunk), | 379 | if (ubsec_dma_malloc(sc, sizeof(struct ubsec_dmachunk), | |
@@ -420,26 +425,30 @@ ubsec_attach(device_t parent, device_t s | @@ -420,26 +425,30 @@ ubsec_attach(device_t parent, device_t s | |||
420 | if (ubsec_dma_malloc(sc, sizeof(struct ubsec_ctx_rngbypass), | 425 | if (ubsec_dma_malloc(sc, sizeof(struct ubsec_ctx_rngbypass), | |
421 | &sc->sc_rng.rng_q.q_ctx, 0)) { | 426 | &sc->sc_rng.rng_q.q_ctx, 0)) { | |
422 | ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_mcr); | 427 | ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_mcr); | |
423 | goto skip_rng; | 428 | goto skip_rng; | |
424 | } | 429 | } | |
425 | 430 | |||
426 | if (ubsec_dma_malloc(sc, sizeof(u_int32_t) * | 431 | if (ubsec_dma_malloc(sc, sizeof(u_int32_t) * | |
427 | UBSEC_RNG_BUFSIZ, &sc->sc_rng.rng_buf, 0)) { | 432 | UBSEC_RNG_BUFSIZ, &sc->sc_rng.rng_buf, 0)) { | |
428 | ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_ctx); | 433 | ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_ctx); | |
429 | ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_mcr); | 434 | ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_mcr); | |
430 | goto skip_rng; | 435 | goto skip_rng; | |
431 | } | 436 | } | |
432 | 437 | |||
438 | rndsource_setcb(&sc->sc_rnd_source, ubsec_rng_get, sc); | |||
439 | rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev), | |||
440 | RND_TYPE_RNG, | |||
441 | RND_FLAG_NO_ESTIMATE|RND_FLAG_HASCB); | |||
433 | if (hz >= 100) | 442 | if (hz >= 100) | |
434 | sc->sc_rnghz = hz / 100; | 443 | sc->sc_rnghz = hz / 100; | |
435 | else | 444 | else | |
436 | sc->sc_rnghz = 1; | 445 | sc->sc_rnghz = 1; | |
437 | #ifdef __OpenBSD__ | 446 | #ifdef __OpenBSD__ | |
438 | timeout_set(&sc->sc_rngto, ubsec_rng, sc); | 447 | timeout_set(&sc->sc_rngto, ubsec_rng, sc); | |
439 | timeout_add(&sc->sc_rngto, sc->sc_rnghz); | 448 | timeout_add(&sc->sc_rngto, sc->sc_rnghz); | |
440 | #else | 449 | #else | |
441 | callout_init(&sc->sc_rngto, 0); | 450 | callout_init(&sc->sc_rngto, 0); | |
442 | callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc); | 451 | callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc); | |
443 | #endif | 452 | #endif | |
444 | skip_rng: | 453 | skip_rng: | |
445 | if (sc->sc_rnghz) | 454 | if (sc->sc_rnghz) | |
@@ -464,29 +473,31 @@ ubsec_attach(device_t parent, device_t s | @@ -464,29 +473,31 @@ ubsec_attach(device_t parent, device_t s | |||
464 | 473 | |||
465 | /* | 474 | /* | |
466 | * UBSEC Interrupt routine | 475 | * UBSEC Interrupt routine | |
467 | */ | 476 | */ | |
468 | static int | 477 | static int | |
469 | ubsec_intr(void *arg) | 478 | ubsec_intr(void *arg) | |
470 | { | 479 | { | |
471 | struct ubsec_softc *sc = arg; | 480 | struct ubsec_softc *sc = arg; | |
472 | volatile u_int32_t stat; | 481 | volatile u_int32_t stat; | |
473 | struct ubsec_q *q; | 482 | struct ubsec_q *q; | |
474 | struct ubsec_dma *dmap; | 483 | struct ubsec_dma *dmap; | |
475 | int npkts = 0, i; | 484 | int npkts = 0, i; | |
476 | 485 | |||
486 | mutex_spin_enter(&sc->sc_mtx); | |||
477 | stat = READ_REG(sc, BS_STAT); | 487 | stat = READ_REG(sc, BS_STAT); | |
478 | stat &= sc->sc_statmask; | 488 | stat &= sc->sc_statmask; | |
479 | if (stat == 0) { | 489 | if (stat == 0) { | |
490 | mutex_spin_exit(&sc->sc_mtx); | |||
480 | return (0); | 491 | return (0); | |
481 | } | 492 | } | |
482 | 493 | |||
483 | WRITE_REG(sc, BS_STAT, stat); /* IACK */ | 494 | WRITE_REG(sc, BS_STAT, stat); /* IACK */ | |
484 | 495 | |||
485 | /* | 496 | /* | |
486 | * Check to see if we have any packets waiting for us | 497 | * Check to see if we have any packets waiting for us | |
487 | */ | 498 | */ | |
488 | if ((stat & BS_STAT_MCR1_DONE)) { | 499 | if ((stat & BS_STAT_MCR1_DONE)) { | |
489 | while (!SIMPLEQ_EMPTY(&sc->sc_qchip)) { | 500 | while (!SIMPLEQ_EMPTY(&sc->sc_qchip)) { | |
490 | q = SIMPLEQ_FIRST(&sc->sc_qchip); | 501 | q = SIMPLEQ_FIRST(&sc->sc_qchip); | |
491 | dmap = q->q_dma; | 502 | dmap = q->q_dma; | |
492 | 503 | |||
@@ -573,26 +584,27 @@ ubsec_intr(void *arg) | @@ -573,26 +584,27 @@ ubsec_intr(void *arg) | |||
573 | ubsec_feed(sc); | 584 | ubsec_feed(sc); | |
574 | } | 585 | } | |
575 | 586 | |||
576 | if (sc->sc_needwakeup) { /* XXX check high watermark */ | 587 | if (sc->sc_needwakeup) { /* XXX check high watermark */ | |
577 | int wkeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ); | 588 | int wkeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ); | |
578 | #ifdef UBSEC_DEBUG | 589 | #ifdef UBSEC_DEBUG | |
579 | if (ubsec_debug) | 590 | if (ubsec_debug) | |
580 | printf("%s: wakeup crypto (%x)\n", device_xname(sc->sc_dev), | 591 | printf("%s: wakeup crypto (%x)\n", device_xname(sc->sc_dev), | |
581 | sc->sc_needwakeup); | 592 | sc->sc_needwakeup); | |
582 | #endif /* UBSEC_DEBUG */ | 593 | #endif /* UBSEC_DEBUG */ | |
583 | sc->sc_needwakeup &= ~wkeup; | 594 | sc->sc_needwakeup &= ~wkeup; | |
584 | crypto_unblock(sc->sc_cid, wkeup); | 595 | crypto_unblock(sc->sc_cid, wkeup); | |
585 | } | 596 | } | |
597 | mutex_spin_exit(&sc->sc_mtx); | |||
586 | return (1); | 598 | return (1); | |
587 | } | 599 | } | |
588 | 600 | |||
589 | /* | 601 | /* | |
590 | * ubsec_feed() - aggregate and post requests to chip | 602 | * ubsec_feed() - aggregate and post requests to chip | |
591 | * OpenBSD comments: | 603 | * OpenBSD comments: | |
592 | * It is assumed that the caller set splnet() | 604 | * It is assumed that the caller set splnet() | |
593 | */ | 605 | */ | |
594 | static void | 606 | static void | |
595 | ubsec_feed(struct ubsec_softc *sc) | 607 | ubsec_feed(struct ubsec_softc *sc) | |
596 | { | 608 | { | |
597 | struct ubsec_q *q, *q2; | 609 | struct ubsec_q *q, *q2; | |
598 | int npkts, i; | 610 | int npkts, i; | |
@@ -916,60 +928,60 @@ ubsec_op_cb(void *arg, bus_dma_segment_t | @@ -916,60 +928,60 @@ ubsec_op_cb(void *arg, bus_dma_segment_t | |||
916 | op->mapsize = mapsize; | 928 | op->mapsize = mapsize; | |
917 | op->nsegs = nsegs; | 929 | op->nsegs = nsegs; | |
918 | memcpy(op->segs, seg, nsegs * sizeof (seg[0])); | 930 | memcpy(op->segs, seg, nsegs * sizeof (seg[0])); | |
919 | } | 931 | } | |
920 | #endif | 932 | #endif | |
921 | 933 | |||
922 | static int | 934 | static int | |
923 | ubsec_process(void *arg, struct cryptop *crp, int hint) | 935 | ubsec_process(void *arg, struct cryptop *crp, int hint) | |
924 | { | 936 | { | |
925 | struct ubsec_q *q = NULL; | 937 | struct ubsec_q *q = NULL; | |
926 | #ifdef __OpenBSD__ | 938 | #ifdef __OpenBSD__ | |
927 | int card; | 939 | int card; | |
928 | #endif | 940 | #endif | |
929 | int err = 0, i, j, s, nicealign; | 941 | int err = 0, i, j, nicealign; | |
930 | struct ubsec_softc *sc; | 942 | struct ubsec_softc *sc; | |
931 | struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; | 943 | struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; | |
932 | int encoffset = 0, macoffset = 0, cpskip, cpoffset; | 944 | int encoffset = 0, macoffset = 0, cpskip, cpoffset; | |
933 | int sskip, dskip, stheend, dtheend; | 945 | int sskip, dskip, stheend, dtheend; | |
934 | int16_t coffset; | 946 | int16_t coffset; | |
935 | struct ubsec_session *ses; | 947 | struct ubsec_session *ses; | |
936 | struct ubsec_pktctx ctx; | 948 | struct ubsec_pktctx ctx; | |
937 | struct ubsec_dma *dmap = NULL; | 949 | struct ubsec_dma *dmap = NULL; | |
938 | 950 | |||
939 | sc = arg; | 951 | sc = arg; | |
940 | KASSERT(sc != NULL /*, ("ubsec_process: null softc")*/); | 952 | KASSERT(sc != NULL /*, ("ubsec_process: null softc")*/); | |
941 | 953 | |||
942 | if (crp == NULL || crp->crp_callback == NULL || sc == NULL) { | 954 | if (crp == NULL || crp->crp_callback == NULL || sc == NULL) { | |
943 | ubsecstats.hst_invalid++; | 955 | ubsecstats.hst_invalid++; | |
944 | return (EINVAL); | 956 | return (EINVAL); | |
945 | } | 957 | } | |
946 | if (UBSEC_SESSION(crp->crp_sid) >= sc->sc_nsessions) { | 958 | if (UBSEC_SESSION(crp->crp_sid) >= sc->sc_nsessions) { | |
947 | ubsecstats.hst_badsession++; | 959 | ubsecstats.hst_badsession++; | |
948 | return (EINVAL); | 960 | return (EINVAL); | |
949 | } | 961 | } | |
950 | 962 | |||
951 | s = splnet(); | 963 | mutex_spin_enter(&sc->sc_mtx); | |
952 | 964 | |||
953 | if (SIMPLEQ_EMPTY(&sc->sc_freequeue)) { | 965 | if (SIMPLEQ_EMPTY(&sc->sc_freequeue)) { | |
954 | ubsecstats.hst_queuefull++; | 966 | ubsecstats.hst_queuefull++; | |
955 | sc->sc_needwakeup |= CRYPTO_SYMQ; | 967 | sc->sc_needwakeup |= CRYPTO_SYMQ; | |
956 | splx(s); | 968 | mutex_spin_exit(&sc->sc_mtx); | |
957 | return(ERESTART); | 969 | return(ERESTART); | |
958 | } | 970 | } | |
959 | 971 | |||
960 | q = SIMPLEQ_FIRST(&sc->sc_freequeue); | 972 | q = SIMPLEQ_FIRST(&sc->sc_freequeue); | |
961 | SIMPLEQ_REMOVE_HEAD(&sc->sc_freequeue, /*q,*/ q_next); | 973 | SIMPLEQ_REMOVE_HEAD(&sc->sc_freequeue, /*q,*/ q_next); | |
962 | splx(s); | 974 | mutex_spin_exit(&sc->sc_mtx); | |
963 | 975 | |||
964 | dmap = q->q_dma; /* Save dma pointer */ | 976 | dmap = q->q_dma; /* Save dma pointer */ | |
965 | memset(q, 0, sizeof(struct ubsec_q)); | 977 | memset(q, 0, sizeof(struct ubsec_q)); | |
966 | memset(&ctx, 0, sizeof(ctx)); | 978 | memset(&ctx, 0, sizeof(ctx)); | |
967 | 979 | |||
968 | q->q_sesn = UBSEC_SESSION(crp->crp_sid); | 980 | q->q_sesn = UBSEC_SESSION(crp->crp_sid); | |
969 | q->q_dma = dmap; | 981 | q->q_dma = dmap; | |
970 | ses = &sc->sc_sessions[q->q_sesn]; | 982 | ses = &sc->sc_sessions[q->q_sesn]; | |
971 | 983 | |||
972 | if (crp->crp_flags & CRYPTO_F_IMBUF) { | 984 | if (crp->crp_flags & CRYPTO_F_IMBUF) { | |
973 | q->q_src_m = (struct mbuf *)crp->crp_buf; | 985 | q->q_src_m = (struct mbuf *)crp->crp_buf; | |
974 | q->q_dst_m = (struct mbuf *)crp->crp_buf; | 986 | q->q_dst_m = (struct mbuf *)crp->crp_buf; | |
975 | } else if (crp->crp_flags & CRYPTO_F_IOV) { | 987 | } else if (crp->crp_flags & CRYPTO_F_IOV) { | |
@@ -1426,53 +1438,53 @@ ubsec_process(void *arg, struct cryptop | @@ -1426,53 +1438,53 @@ ubsec_process(void *arg, struct cryptop | |||
1426 | for (i = 0; i < 6; i++) | 1438 | for (i = 0; i < 6; i++) | |
1427 | ctxl->pc_deskey[i] = ctx.pc_deskey[i]; | 1439 | ctxl->pc_deskey[i] = ctx.pc_deskey[i]; | |
1428 | for (i = 0; i < 5; i++) | 1440 | for (i = 0; i < 5; i++) | |
1429 | ctxl->pc_hminner[i] = ctx.pc_hminner[i]; | 1441 | ctxl->pc_hminner[i] = ctx.pc_hminner[i]; | |
1430 | for (i = 0; i < 5; i++) | 1442 | for (i = 0; i < 5; i++) | |
1431 | ctxl->pc_hmouter[i] = ctx.pc_hmouter[i]; | 1443 | ctxl->pc_hmouter[i] = ctx.pc_hmouter[i]; | |
1432 | ctxl->pc_iv[0] = ctx.pc_iv[0]; | 1444 | ctxl->pc_iv[0] = ctx.pc_iv[0]; | |
1433 | ctxl->pc_iv[1] = ctx.pc_iv[1]; | 1445 | ctxl->pc_iv[1] = ctx.pc_iv[1]; | |
1434 | } else | 1446 | } else | |
1435 | memcpy((char *)dmap->d_alloc.dma_vaddr + | 1447 | memcpy((char *)dmap->d_alloc.dma_vaddr + | |
1436 | offsetof(struct ubsec_dmachunk, d_ctx), &ctx, | 1448 | offsetof(struct ubsec_dmachunk, d_ctx), &ctx, | |
1437 | sizeof(struct ubsec_pktctx)); | 1449 | sizeof(struct ubsec_pktctx)); | |
1438 | 1450 | |||
1439 | s = splnet(); | 1451 | mutex_spin_enter(&sc->sc_mtx); | |
1440 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next); | 1452 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next); | |
1441 | sc->sc_nqueue++; | 1453 | sc->sc_nqueue++; | |
1442 | ubsecstats.hst_ipackets++; | 1454 | ubsecstats.hst_ipackets++; | |
1443 | ubsecstats.hst_ibytes += dmap->d_alloc.dma_map->dm_mapsize; | 1455 | ubsecstats.hst_ibytes += dmap->d_alloc.dma_map->dm_mapsize; | |
1444 | if ((hint & CRYPTO_HINT_MORE) == 0 || sc->sc_nqueue >= ubsec_maxbatch) | 1456 | if ((hint & CRYPTO_HINT_MORE) == 0 || sc->sc_nqueue >= ubsec_maxbatch) | |
1445 | ubsec_feed(sc); | 1457 | ubsec_feed(sc); | |
1446 | splx(s); | 1458 | mutex_spin_exit(&sc->sc_mtx); | |
1447 | return (0); | 1459 | return (0); | |
1448 | 1460 | |||
1449 | errout: | 1461 | errout: | |
1450 | if (q != NULL) { | 1462 | if (q != NULL) { | |
1451 | if ((q->q_dst_m != NULL) && (q->q_src_m != q->q_dst_m)) | 1463 | if ((q->q_dst_m != NULL) && (q->q_src_m != q->q_dst_m)) | |
1452 | m_freem(q->q_dst_m); | 1464 | m_freem(q->q_dst_m); | |
1453 | 1465 | |||
1454 | if (q->q_dst_map != NULL && q->q_dst_map != q->q_src_map) { | 1466 | if (q->q_dst_map != NULL && q->q_dst_map != q->q_src_map) { | |
1455 | bus_dmamap_unload(sc->sc_dmat, q->q_dst_map); | 1467 | bus_dmamap_unload(sc->sc_dmat, q->q_dst_map); | |
1456 | bus_dmamap_destroy(sc->sc_dmat, q->q_dst_map); | 1468 | bus_dmamap_destroy(sc->sc_dmat, q->q_dst_map); | |
1457 | } | 1469 | } | |
1458 | if (q->q_src_map != NULL) { | 1470 | if (q->q_src_map != NULL) { | |
1459 | bus_dmamap_unload(sc->sc_dmat, q->q_src_map); | 1471 | bus_dmamap_unload(sc->sc_dmat, q->q_src_map); | |
1460 | bus_dmamap_destroy(sc->sc_dmat, q->q_src_map); | 1472 | bus_dmamap_destroy(sc->sc_dmat, q->q_src_map); | |
1461 | } | 1473 | } | |
1462 | 1474 | |||
1463 | s = splnet(); | 1475 | mutex_spin_enter(&sc->sc_mtx); | |
1464 | SIMPLEQ_INSERT_TAIL(&sc->sc_freequeue, q, q_next); | 1476 | SIMPLEQ_INSERT_TAIL(&sc->sc_freequeue, q, q_next); | |
1465 | splx(s); | 1477 | mutex_spin_exit(&sc->sc_mtx); | |
1466 | } | 1478 | } | |
1467 | #if 0 /* jonathan says: this openbsd code seems to be subsumed elsewhere */ | 1479 | #if 0 /* jonathan says: this openbsd code seems to be subsumed elsewhere */ | |
1468 | if (err == EINVAL) | 1480 | if (err == EINVAL) | |
1469 | ubsecstats.hst_invalid++; | 1481 | ubsecstats.hst_invalid++; | |
1470 | else | 1482 | else | |
1471 | ubsecstats.hst_nomem++; | 1483 | ubsecstats.hst_nomem++; | |
1472 | #endif | 1484 | #endif | |
1473 | if (err != ERESTART) { | 1485 | if (err != ERESTART) { | |
1474 | crp->crp_etype = err; | 1486 | crp->crp_etype = err; | |
1475 | crypto_done(crp); | 1487 | crypto_done(crp); | |
1476 | } else { | 1488 | } else { | |
1477 | sc->sc_needwakeup |= CRYPTO_SYMQ; | 1489 | sc->sc_needwakeup |= CRYPTO_SYMQ; | |
1478 | } | 1490 | } | |
@@ -1628,33 +1640,38 @@ ubsec_callback2(struct ubsec_softc *sc, | @@ -1628,33 +1640,38 @@ ubsec_callback2(struct ubsec_softc *sc, | |||
1628 | case UBS_CTXOP_RNGBYPASS: { | 1640 | case UBS_CTXOP_RNGBYPASS: { | |
1629 | struct ubsec_q2_rng *rng = (struct ubsec_q2_rng *)q; | 1641 | struct ubsec_q2_rng *rng = (struct ubsec_q2_rng *)q; | |
1630 | u_int32_t *p; | 1642 | u_int32_t *p; | |
1631 | int i; | 1643 | int i; | |
1632 | 1644 | |||
1633 | bus_dmamap_sync(sc->sc_dmat, rng->rng_buf.dma_map, 0, | 1645 | bus_dmamap_sync(sc->sc_dmat, rng->rng_buf.dma_map, 0, | |
1634 | rng->rng_buf.dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD); | 1646 | rng->rng_buf.dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD); | |
1635 | p = (u_int32_t *)rng->rng_buf.dma_vaddr; | 1647 | p = (u_int32_t *)rng->rng_buf.dma_vaddr; | |
1636 | #ifndef __NetBSD__ | 1648 | #ifndef __NetBSD__ | |
1637 | for (i = 0; i < UBSEC_RNG_BUFSIZ; p++, i++) | 1649 | for (i = 0; i < UBSEC_RNG_BUFSIZ; p++, i++) | |
1638 | add_true_randomness(letoh32(*p)); | 1650 | add_true_randomness(letoh32(*p)); | |
1639 | rng->rng_used = 0; | 1651 | rng->rng_used = 0; | |
1640 | #else | 1652 | #else | |
1641 | /* XXX NetBSD rnd subsystem too weak */ | 1653 | i = UBSEC_RNG_BUFSIZ * sizeof(u_int32_t); | |
1642 | i = 0; (void)i; /* shut off gcc warnings */ | 1654 | rnd_add_data(&sc->sc_rnd_source, (char *)p, i, i * NBBY); | |
1655 | sc->sc_rng_need -= i; | |||
1656 | rng->rng_used = 0; | |||
1643 | #endif | 1657 | #endif | |
1644 | #ifdef __OpenBSD__ | 1658 | #ifdef __OpenBSD__ | |
1645 | timeout_add(&sc->sc_rngto, sc->sc_rnghz); | 1659 | timeout_add(&sc->sc_rngto, sc->sc_rnghz); | |
1646 | #else | 1660 | #else | |
1647 | callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc); | 1661 | if (sc->sc_rng_need > 0) { | |
1662 | callout_reset(&sc->sc_rngto, sc->sc_rnghz, | |||
1663 | ubsec_rng, sc); | |||
1664 | } | |||
1648 | #endif | 1665 | #endif | |
1649 | break; | 1666 | break; | |
1650 | } | 1667 | } | |
1651 | #endif | 1668 | #endif | |
1652 | case UBS_CTXOP_MODEXP: { | 1669 | case UBS_CTXOP_MODEXP: { | |
1653 | struct ubsec_q2_modexp *me = (struct ubsec_q2_modexp *)q; | 1670 | struct ubsec_q2_modexp *me = (struct ubsec_q2_modexp *)q; | |
1654 | u_int rlen, clen; | 1671 | u_int rlen, clen; | |
1655 | 1672 | |||
1656 | krp = me->me_krp; | 1673 | krp = me->me_krp; | |
1657 | rlen = (me->me_modbits + 7) / 8; | 1674 | rlen = (me->me_modbits + 7) / 8; | |
1658 | clen = (krp->krp_param[krp->krp_iparams].crp_nbits + 7) / 8; | 1675 | clen = (krp->krp_param[krp->krp_iparams].crp_nbits + 7) / 8; | |
1659 | 1676 | |||
1660 | bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map, | 1677 | bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map, | |
@@ -1717,40 +1734,68 @@ ubsec_callback2(struct ubsec_softc *sc, | @@ -1717,40 +1734,68 @@ ubsec_callback2(struct ubsec_softc *sc, | |||
1717 | 1734 | |||
1718 | /* Can't free here, so put us on the free list. */ | 1735 | /* Can't free here, so put us on the free list. */ | |
1719 | SIMPLEQ_INSERT_TAIL(&sc->sc_q2free, &rp->rpr_q, q_next); | 1736 | SIMPLEQ_INSERT_TAIL(&sc->sc_q2free, &rp->rpr_q, q_next); | |
1720 | break; | 1737 | break; | |
1721 | } | 1738 | } | |
1722 | default: | 1739 | default: | |
1723 | printf("%s: unknown ctx op: %x\n", device_xname(sc->sc_dev), | 1740 | printf("%s: unknown ctx op: %x\n", device_xname(sc->sc_dev), | |
1724 | letoh16(ctx->ctx_op)); | 1741 | letoh16(ctx->ctx_op)); | |
1725 | break; | 1742 | break; | |
1726 | } | 1743 | } | |
1727 | } | 1744 | } | |
1728 | 1745 | |||
1729 | #ifndef UBSEC_NO_RNG | 1746 | #ifndef UBSEC_NO_RNG | |
1747 | ||||
1748 | static void | |||
1749 | ubsec_rng_get(size_t bytes, void *vsc) | |||
1750 | { | |||
1751 | struct ubsec_softc *sc = vsc; | |||
1752 | ||||
1753 | mutex_spin_enter(&sc->sc_mtx); | |||
1754 | sc->sc_rng_need = bytes; | |||
1755 | ubsec_rng_locked(sc); | |||
1756 | mutex_spin_exit(&sc->sc_mtx); | |||
1757 | ||||
1758 | } | |||
1759 | ||||
1730 | static void | 1760 | static void | |
1731 | ubsec_rng(void *vsc) | 1761 | ubsec_rng(void *vsc) | |
1732 | { | 1762 | { | |
1733 | struct ubsec_softc *sc = vsc; | 1763 | struct ubsec_softc *sc = vsc; | |
1764 | mutex_spin_enter(&sc->sc_mtx); | |||
1765 | ubsec_rng_locked(sc); | |||
1766 | mutex_spin_exit(&sc->sc_mtx); | |||
1767 | } | |||
1768 | ||||
1769 | static void | |||
1770 | ubsec_rng_locked(void *vsc) | |||
1771 | { | |||
1772 | struct ubsec_softc *sc = vsc; | |||
1734 | struct ubsec_q2_rng *rng = &sc->sc_rng; | 1773 | struct ubsec_q2_rng *rng = &sc->sc_rng; | |
1735 | struct ubsec_mcr *mcr; | 1774 | struct ubsec_mcr *mcr; | |
1736 | struct ubsec_ctx_rngbypass *ctx; | 1775 | struct ubsec_ctx_rngbypass *ctx; | |
1737 | int s; | |||
1738 | 1776 | |||
1739 | s = splnet(); | 1777 | mutex_spin_enter(&sc->sc_mtx); | |
1740 | if (rng->rng_used) { | 1778 | if (rng->rng_used) { | |
1741 | splx(s); | 1779 | mutex_spin_exit(&sc->sc_mtx); | |
1742 | return; | 1780 | return; | |
1743 | } | 1781 | } | |
1782 | ||||
1783 | if (sc->sc_rng_need < 1) { | |||
1784 | callout_stop(&sc->sc_rngto); | |||
1785 | mutex_spin_exit(&sc->sc_mtx); | |||
1786 | return; | |||
1787 | } | |||
1788 | ||||
1744 | sc->sc_nqueue2++; | 1789 | sc->sc_nqueue2++; | |
1745 | if (sc->sc_nqueue2 >= UBS_MAX_NQUEUE) | 1790 | if (sc->sc_nqueue2 >= UBS_MAX_NQUEUE) | |
1746 | goto out; | 1791 | goto out; | |
1747 | 1792 | |||
1748 | mcr = (struct ubsec_mcr *)rng->rng_q.q_mcr.dma_vaddr; | 1793 | mcr = (struct ubsec_mcr *)rng->rng_q.q_mcr.dma_vaddr; | |
1749 | ctx = (struct ubsec_ctx_rngbypass *)rng->rng_q.q_ctx.dma_vaddr; | 1794 | ctx = (struct ubsec_ctx_rngbypass *)rng->rng_q.q_ctx.dma_vaddr; | |
1750 | 1795 | |||
1751 | mcr->mcr_pkts = htole16(1); | 1796 | mcr->mcr_pkts = htole16(1); | |
1752 | mcr->mcr_flags = 0; | 1797 | mcr->mcr_flags = 0; | |
1753 | mcr->mcr_cmdctxp = htole32(rng->rng_q.q_ctx.dma_paddr); | 1798 | mcr->mcr_cmdctxp = htole32(rng->rng_q.q_ctx.dma_paddr); | |
1754 | mcr->mcr_ipktbuf.pb_addr = mcr->mcr_ipktbuf.pb_next = 0; | 1799 | mcr->mcr_ipktbuf.pb_addr = mcr->mcr_ipktbuf.pb_next = 0; | |
1755 | mcr->mcr_ipktbuf.pb_len = 0; | 1800 | mcr->mcr_ipktbuf.pb_len = 0; | |
1756 | mcr->mcr_reserved = mcr->mcr_pktlen = 0; | 1801 | mcr->mcr_reserved = mcr->mcr_pktlen = 0; | |
@@ -1760,36 +1805,36 @@ ubsec_rng(void *vsc) | @@ -1760,36 +1805,36 @@ ubsec_rng(void *vsc) | |||
1760 | mcr->mcr_opktbuf.pb_next = 0; | 1805 | mcr->mcr_opktbuf.pb_next = 0; | |
1761 | 1806 | |||
1762 | ctx->rbp_len = htole16(sizeof(struct ubsec_ctx_rngbypass)); | 1807 | ctx->rbp_len = htole16(sizeof(struct ubsec_ctx_rngbypass)); | |
1763 | ctx->rbp_op = htole16(UBS_CTXOP_RNGSHA1); | 1808 | ctx->rbp_op = htole16(UBS_CTXOP_RNGSHA1); | |
1764 | rng->rng_q.q_type = UBS_CTXOP_RNGSHA1; | 1809 | rng->rng_q.q_type = UBS_CTXOP_RNGSHA1; | |
1765 | 1810 | |||
1766 | bus_dmamap_sync(sc->sc_dmat, rng->rng_buf.dma_map, 0, | 1811 | bus_dmamap_sync(sc->sc_dmat, rng->rng_buf.dma_map, 0, | |
1767 | rng->rng_buf.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); | 1812 | rng->rng_buf.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); | |
1768 | 1813 | |||
1769 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &rng->rng_q, q_next); | 1814 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &rng->rng_q, q_next); | |
1770 | rng->rng_used = 1; | 1815 | rng->rng_used = 1; | |
1771 | ubsec_feed2(sc); | 1816 | ubsec_feed2(sc); | |
1772 | ubsecstats.hst_rng++; | 1817 | ubsecstats.hst_rng++; | |
1773 | splx(s); | 1818 | mutex_spin_exit(&sc->sc_mtx); | |
1774 | 1819 | |||
1775 | return; | 1820 | return; | |
1776 | 1821 | |||
1777 | out: | 1822 | out: | |
1778 | /* | 1823 | /* | |
1779 | * Something weird happened, generate our own call back. | 1824 | * Something weird happened, generate our own call back. | |
1780 | */ | 1825 | */ | |
1781 | sc->sc_nqueue2--; | 1826 | sc->sc_nqueue2--; | |
1782 | splx(s); | 1827 | mutex_spin_exit(&sc->sc_mtx); | |
1783 | #ifdef __OpenBSD__ | 1828 | #ifdef __OpenBSD__ | |
1784 | timeout_add(&sc->sc_rngto, sc->sc_rnghz); | 1829 | timeout_add(&sc->sc_rngto, sc->sc_rnghz); | |
1785 | #else | 1830 | #else | |
1786 | callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc); | 1831 | callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc); | |
1787 | #endif | 1832 | #endif | |
1788 | } | 1833 | } | |
1789 | #endif /* UBSEC_NO_RNG */ | 1834 | #endif /* UBSEC_NO_RNG */ | |
1790 | 1835 | |||
1791 | static int | 1836 | static int | |
1792 | ubsec_dma_malloc(struct ubsec_softc *sc, bus_size_t size, | 1837 | ubsec_dma_malloc(struct ubsec_softc *sc, bus_size_t size, | |
1793 | struct ubsec_dma_alloc *dma,int mapflags) | 1838 | struct ubsec_dma_alloc *dma,int mapflags) | |
1794 | { | 1839 | { | |
1795 | int r; | 1840 | int r; | |
@@ -2087,27 +2132,27 @@ ubsec_kprocess(void *arg, struct cryptko | @@ -2087,27 +2132,27 @@ ubsec_kprocess(void *arg, struct cryptko | |||
2087 | } | 2132 | } | |
2088 | 2133 | |||
2089 | /* | 2134 | /* | |
2090 | * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] (sw normalization) | 2135 | * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] (sw normalization) | |
2091 | */ | 2136 | */ | |
2092 | static int | 2137 | static int | |
2093 | ubsec_kprocess_modexp_sw(struct ubsec_softc *sc, struct cryptkop *krp, | 2138 | ubsec_kprocess_modexp_sw(struct ubsec_softc *sc, struct cryptkop *krp, | |
2094 | int hint) | 2139 | int hint) | |
2095 | { | 2140 | { | |
2096 | struct ubsec_q2_modexp *me; | 2141 | struct ubsec_q2_modexp *me; | |
2097 | struct ubsec_mcr *mcr; | 2142 | struct ubsec_mcr *mcr; | |
2098 | struct ubsec_ctx_modexp *ctx; | 2143 | struct ubsec_ctx_modexp *ctx; | |
2099 | struct ubsec_pktbuf *epb; | 2144 | struct ubsec_pktbuf *epb; | |
2100 | int s, err = 0; | 2145 | int err = 0; | |
2101 | u_int nbits, normbits, mbits, shiftbits, ebits; | 2146 | u_int nbits, normbits, mbits, shiftbits, ebits; | |
2102 | 2147 | |||
2103 | me = (struct ubsec_q2_modexp *)malloc(sizeof *me, M_DEVBUF, M_NOWAIT); | 2148 | me = (struct ubsec_q2_modexp *)malloc(sizeof *me, M_DEVBUF, M_NOWAIT); | |
2104 | if (me == NULL) { | 2149 | if (me == NULL) { | |
2105 | err = ENOMEM; | 2150 | err = ENOMEM; | |
2106 | goto errout; | 2151 | goto errout; | |
2107 | } | 2152 | } | |
2108 | memset(me, 0, sizeof *me); | 2153 | memset(me, 0, sizeof *me); | |
2109 | me->me_krp = krp; | 2154 | me->me_krp = krp; | |
2110 | me->me_q.q_type = UBS_CTXOP_MODEXP; | 2155 | me->me_q.q_type = UBS_CTXOP_MODEXP; | |
2111 | 2156 | |||
2112 | nbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_N]); | 2157 | nbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_N]); | |
2113 | if (nbits <= 512) | 2158 | if (nbits <= 512) | |
@@ -2244,31 +2289,31 @@ ubsec_kprocess_modexp_sw(struct ubsec_so | @@ -2244,31 +2289,31 @@ ubsec_kprocess_modexp_sw(struct ubsec_so | |||
2244 | * ubsec_feed2 will sync mcr and ctx, we just need to sync | 2289 | * ubsec_feed2 will sync mcr and ctx, we just need to sync | |
2245 | * everything else. | 2290 | * everything else. | |
2246 | */ | 2291 | */ | |
2247 | bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map, | 2292 | bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map, | |
2248 | 0, me->me_M.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 2293 | 0, me->me_M.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
2249 | bus_dmamap_sync(sc->sc_dmat, me->me_E.dma_map, | 2294 | bus_dmamap_sync(sc->sc_dmat, me->me_E.dma_map, | |
2250 | 0, me->me_E.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 2295 | 0, me->me_E.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
2251 | bus_dmamap_sync(sc->sc_dmat, me->me_C.dma_map, | 2296 | bus_dmamap_sync(sc->sc_dmat, me->me_C.dma_map, | |
2252 | 0, me->me_C.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); | 2297 | 0, me->me_C.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); | |
2253 | bus_dmamap_sync(sc->sc_dmat, me->me_epb.dma_map, | 2298 | bus_dmamap_sync(sc->sc_dmat, me->me_epb.dma_map, | |
2254 | 0, me->me_epb.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 2299 | 0, me->me_epb.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
2255 | 2300 | |||
2256 | /* Enqueue and we're done... */ | 2301 | /* Enqueue and we're done... */ | |
2257 | s = splnet(); | 2302 | mutex_spin_enter(&sc->sc_mtx); | |
2258 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &me->me_q, q_next); | 2303 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &me->me_q, q_next); | |
2259 | ubsec_feed2(sc); | 2304 | ubsec_feed2(sc); | |
2260 | ubsecstats.hst_modexp++; | 2305 | ubsecstats.hst_modexp++; | |
2261 | splx(s); | 2306 | mutex_spin_exit(&sc->sc_mtx); | |
2262 | 2307 | |||
2263 | return (0); | 2308 | return (0); | |
2264 | 2309 | |||
2265 | errout: | 2310 | errout: | |
2266 | if (me != NULL) { | 2311 | if (me != NULL) { | |
2267 | if (me->me_q.q_mcr.dma_map != NULL) | 2312 | if (me->me_q.q_mcr.dma_map != NULL) | |
2268 | ubsec_dma_free(sc, &me->me_q.q_mcr); | 2313 | ubsec_dma_free(sc, &me->me_q.q_mcr); | |
2269 | if (me->me_q.q_ctx.dma_map != NULL) { | 2314 | if (me->me_q.q_ctx.dma_map != NULL) { | |
2270 | memset(me->me_q.q_ctx.dma_vaddr, 0, me->me_q.q_ctx.dma_size); | 2315 | memset(me->me_q.q_ctx.dma_vaddr, 0, me->me_q.q_ctx.dma_size); | |
2271 | ubsec_dma_free(sc, &me->me_q.q_ctx); | 2316 | ubsec_dma_free(sc, &me->me_q.q_ctx); | |
2272 | } | 2317 | } | |
2273 | if (me->me_M.dma_map != NULL) { | 2318 | if (me->me_M.dma_map != NULL) { | |
2274 | memset(me->me_M.dma_vaddr, 0, me->me_M.dma_size); | 2319 | memset(me->me_M.dma_vaddr, 0, me->me_M.dma_size); | |
@@ -2292,27 +2337,27 @@ errout: | @@ -2292,27 +2337,27 @@ errout: | |||
2292 | } | 2337 | } | |
2293 | 2338 | |||
2294 | /* | 2339 | /* | |
2295 | * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] (hw normalization) | 2340 | * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] (hw normalization) | |
2296 | */ | 2341 | */ | |
2297 | static int | 2342 | static int | |
2298 | ubsec_kprocess_modexp_hw(struct ubsec_softc *sc, struct cryptkop *krp, | 2343 | ubsec_kprocess_modexp_hw(struct ubsec_softc *sc, struct cryptkop *krp, | |
2299 | int hint) | 2344 | int hint) | |
2300 | { | 2345 | { | |
2301 | struct ubsec_q2_modexp *me; | 2346 | struct ubsec_q2_modexp *me; | |
2302 | struct ubsec_mcr *mcr; | 2347 | struct ubsec_mcr *mcr; | |
2303 | struct ubsec_ctx_modexp *ctx; | 2348 | struct ubsec_ctx_modexp *ctx; | |
2304 | struct ubsec_pktbuf *epb; | 2349 | struct ubsec_pktbuf *epb; | |
2305 | int s, err = 0; | 2350 | int err = 0; | |
2306 | u_int nbits, normbits, mbits, shiftbits, ebits; | 2351 | u_int nbits, normbits, mbits, shiftbits, ebits; | |
2307 | 2352 | |||
2308 | me = (struct ubsec_q2_modexp *)malloc(sizeof *me, M_DEVBUF, M_NOWAIT); | 2353 | me = (struct ubsec_q2_modexp *)malloc(sizeof *me, M_DEVBUF, M_NOWAIT); | |
2309 | if (me == NULL) { | 2354 | if (me == NULL) { | |
2310 | err = ENOMEM; | 2355 | err = ENOMEM; | |
2311 | goto errout; | 2356 | goto errout; | |
2312 | } | 2357 | } | |
2313 | memset(me, 0, sizeof *me); | 2358 | memset(me, 0, sizeof *me); | |
2314 | me->me_krp = krp; | 2359 | me->me_krp = krp; | |
2315 | me->me_q.q_type = UBS_CTXOP_MODEXP; | 2360 | me->me_q.q_type = UBS_CTXOP_MODEXP; | |
2316 | 2361 | |||
2317 | nbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_N]); | 2362 | nbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_N]); | |
2318 | if (nbits <= 512) | 2363 | if (nbits <= 512) | |
@@ -2449,30 +2494,30 @@ ubsec_kprocess_modexp_hw(struct ubsec_so | @@ -2449,30 +2494,30 @@ ubsec_kprocess_modexp_hw(struct ubsec_so | |||
2449 | * ubsec_feed2 will sync mcr and ctx, we just need to sync | 2494 | * ubsec_feed2 will sync mcr and ctx, we just need to sync | |
2450 | * everything else. | 2495 | * everything else. | |
2451 | */ | 2496 | */ | |
2452 | bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map, | 2497 | bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map, | |
2453 | 0, me->me_M.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 2498 | 0, me->me_M.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
2454 | bus_dmamap_sync(sc->sc_dmat, me->me_E.dma_map, | 2499 | bus_dmamap_sync(sc->sc_dmat, me->me_E.dma_map, | |
2455 | 0, me->me_E.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 2500 | 0, me->me_E.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
2456 | bus_dmamap_sync(sc->sc_dmat, me->me_C.dma_map, | 2501 | bus_dmamap_sync(sc->sc_dmat, me->me_C.dma_map, | |
2457 | 0, me->me_C.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); | 2502 | 0, me->me_C.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); | |
2458 | bus_dmamap_sync(sc->sc_dmat, me->me_epb.dma_map, | 2503 | bus_dmamap_sync(sc->sc_dmat, me->me_epb.dma_map, | |
2459 | 0, me->me_epb.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 2504 | 0, me->me_epb.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
2460 | 2505 | |||
2461 | /* Enqueue and we're done... */ | 2506 | /* Enqueue and we're done... */ | |
2462 | s = splnet(); | 2507 | mutex_spin_enter(&sc->sc_mtx); | |
2463 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &me->me_q, q_next); | 2508 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &me->me_q, q_next); | |
2464 | ubsec_feed2(sc); | 2509 | ubsec_feed2(sc); | |
2465 | splx(s); | 2510 | mutex_spin_exit(&sc->sc_mtx); | |
2466 | 2511 | |||
2467 | return (0); | 2512 | return (0); | |
2468 | 2513 | |||
2469 | errout: | 2514 | errout: | |
2470 | if (me != NULL) { | 2515 | if (me != NULL) { | |
2471 | if (me->me_q.q_mcr.dma_map != NULL) | 2516 | if (me->me_q.q_mcr.dma_map != NULL) | |
2472 | ubsec_dma_free(sc, &me->me_q.q_mcr); | 2517 | ubsec_dma_free(sc, &me->me_q.q_mcr); | |
2473 | if (me->me_q.q_ctx.dma_map != NULL) { | 2518 | if (me->me_q.q_ctx.dma_map != NULL) { | |
2474 | memset(me->me_q.q_ctx.dma_vaddr, 0, me->me_q.q_ctx.dma_size); | 2519 | memset(me->me_q.q_ctx.dma_vaddr, 0, me->me_q.q_ctx.dma_size); | |
2475 | ubsec_dma_free(sc, &me->me_q.q_ctx); | 2520 | ubsec_dma_free(sc, &me->me_q.q_ctx); | |
2476 | } | 2521 | } | |
2477 | if (me->me_M.dma_map != NULL) { | 2522 | if (me->me_M.dma_map != NULL) { | |
2478 | memset(me->me_M.dma_vaddr, 0, me->me_M.dma_size); | 2523 | memset(me->me_M.dma_vaddr, 0, me->me_M.dma_size); | |
@@ -2492,27 +2537,27 @@ errout: | @@ -2492,27 +2537,27 @@ errout: | |||
2492 | } | 2537 | } | |
2493 | krp->krp_status = err; | 2538 | krp->krp_status = err; | |
2494 | crypto_kdone(krp); | 2539 | crypto_kdone(krp); | |
2495 | return (0); | 2540 | return (0); | |
2496 | } | 2541 | } | |
2497 | 2542 | |||
2498 | static int | 2543 | static int | |
2499 | ubsec_kprocess_rsapriv(struct ubsec_softc *sc, struct cryptkop *krp, | 2544 | ubsec_kprocess_rsapriv(struct ubsec_softc *sc, struct cryptkop *krp, | |
2500 | int hint) | 2545 | int hint) | |
2501 | { | 2546 | { | |
2502 | struct ubsec_q2_rsapriv *rp = NULL; | 2547 | struct ubsec_q2_rsapriv *rp = NULL; | |
2503 | struct ubsec_mcr *mcr; | 2548 | struct ubsec_mcr *mcr; | |
2504 | struct ubsec_ctx_rsapriv *ctx; | 2549 | struct ubsec_ctx_rsapriv *ctx; | |
2505 | int s, err = 0; | 2550 | int err = 0; | |
2506 | u_int padlen, msglen; | 2551 | u_int padlen, msglen; | |
2507 | 2552 | |||
2508 | msglen = ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_P]); | 2553 | msglen = ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_P]); | |
2509 | padlen = ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_Q]); | 2554 | padlen = ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_Q]); | |
2510 | if (msglen > padlen) | 2555 | if (msglen > padlen) | |
2511 | padlen = msglen; | 2556 | padlen = msglen; | |
2512 | 2557 | |||
2513 | if (padlen <= 256) | 2558 | if (padlen <= 256) | |
2514 | padlen = 256; | 2559 | padlen = 256; | |
2515 | else if (padlen <= 384) | 2560 | else if (padlen <= 384) | |
2516 | padlen = 384; | 2561 | padlen = 384; | |
2517 | else if (padlen <= 512) | 2562 | else if (padlen <= 512) | |
2518 | padlen = 512; | 2563 | padlen = 512; | |
@@ -2645,31 +2690,31 @@ ubsec_kprocess_rsapriv(struct ubsec_soft | @@ -2645,31 +2690,31 @@ ubsec_kprocess_rsapriv(struct ubsec_soft | |||
2645 | ctx->rpr_q_len = htole16(padlen); | 2690 | ctx->rpr_q_len = htole16(padlen); | |
2646 | ctx->rpr_p_len = htole16(padlen); | 2691 | ctx->rpr_p_len = htole16(padlen); | |
2647 | 2692 | |||
2648 | /* | 2693 | /* | |
2649 | * ubsec_feed2 will sync mcr and ctx, we just need to sync | 2694 | * ubsec_feed2 will sync mcr and ctx, we just need to sync | |
2650 | * everything else. | 2695 | * everything else. | |
2651 | */ | 2696 | */ | |
2652 | bus_dmamap_sync(sc->sc_dmat, rp->rpr_msgin.dma_map, | 2697 | bus_dmamap_sync(sc->sc_dmat, rp->rpr_msgin.dma_map, | |
2653 | 0, rp->rpr_msgin.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | 2698 | 0, rp->rpr_msgin.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); | |
2654 | bus_dmamap_sync(sc->sc_dmat, rp->rpr_msgout.dma_map, | 2699 | bus_dmamap_sync(sc->sc_dmat, rp->rpr_msgout.dma_map, | |
2655 | 0, rp->rpr_msgout.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); | 2700 | 0, rp->rpr_msgout.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); | |
2656 | 2701 | |||
2657 | /* Enqueue and we're done... */ | 2702 | /* Enqueue and we're done... */ | |
2658 | s = splnet(); | 2703 | mutex_spin_enter(&sc->sc_mtx); | |
2659 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &rp->rpr_q, q_next); | 2704 | SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &rp->rpr_q, q_next); | |
2660 | ubsec_feed2(sc); | 2705 | ubsec_feed2(sc); | |
2661 | ubsecstats.hst_modexpcrt++; | 2706 | ubsecstats.hst_modexpcrt++; | |
2662 | splx(s); | 2707 | mutex_spin_exit(&sc->sc_mtx); | |
2663 | return (0); | 2708 | return (0); | |
2664 | 2709 | |||
2665 | errout: | 2710 | errout: | |
2666 | if (rp != NULL) { | 2711 | if (rp != NULL) { | |
2667 | if (rp->rpr_q.q_mcr.dma_map != NULL) | 2712 | if (rp->rpr_q.q_mcr.dma_map != NULL) | |
2668 | ubsec_dma_free(sc, &rp->rpr_q.q_mcr); | 2713 | ubsec_dma_free(sc, &rp->rpr_q.q_mcr); | |
2669 | if (rp->rpr_msgin.dma_map != NULL) { | 2714 | if (rp->rpr_msgin.dma_map != NULL) { | |
2670 | memset(rp->rpr_msgin.dma_vaddr, 0, rp->rpr_msgin.dma_size); | 2715 | memset(rp->rpr_msgin.dma_vaddr, 0, rp->rpr_msgin.dma_size); | |
2671 | ubsec_dma_free(sc, &rp->rpr_msgin); | 2716 | ubsec_dma_free(sc, &rp->rpr_msgin); | |
2672 | } | 2717 | } | |
2673 | if (rp->rpr_msgout.dma_map != NULL) { | 2718 | if (rp->rpr_msgout.dma_map != NULL) { | |
2674 | memset(rp->rpr_msgout.dma_vaddr, 0, rp->rpr_msgout.dma_size); | 2719 | memset(rp->rpr_msgout.dma_vaddr, 0, rp->rpr_msgout.dma_size); | |
2675 | ubsec_dma_free(sc, &rp->rpr_msgout); | 2720 | ubsec_dma_free(sc, &rp->rpr_msgout); |
--- src/sys/dev/pci/ubsecvar.h 2012/10/27 17:18:35 1.4
+++ src/sys/dev/pci/ubsecvar.h 2013/06/13 00:55:01 1.5
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ubsecvar.h,v 1.4 2012/10/27 17:18:35 chs Exp $ */ | 1 | /* $NetBSD: ubsecvar.h,v 1.5 2013/06/13 00:55:01 tls Exp $ */ | |
2 | /* $OpenBSD: ubsecvar.h,v 1.36 2003/06/04 16:02:41 jason Exp $ */ | 2 | /* $OpenBSD: ubsecvar.h,v 1.36 2003/06/04 16:02:41 jason Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 2000 Theo de Raadt | 5 | * Copyright (c) 2000 Theo de Raadt | |
6 | * Copyright (c) 2001 Patrik Lindergren (patrik@ipunplugged.com) | 6 | * Copyright (c) 2001 Patrik Lindergren (patrik@ipunplugged.com) | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * | 11 | * | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
@@ -139,47 +139,50 @@ struct ubsec_q { | @@ -139,47 +139,50 @@ struct ubsec_q { | |||
139 | struct mbuf *q_src_m, *q_dst_m; | 139 | struct mbuf *q_src_m, *q_dst_m; | |
140 | struct uio *q_src_io, *q_dst_io; | 140 | struct uio *q_src_io, *q_dst_io; | |
141 | 141 | |||
142 | bus_dmamap_t q_src_map; | 142 | bus_dmamap_t q_src_map; | |
143 | bus_dmamap_t q_dst_map; | 143 | bus_dmamap_t q_dst_map; | |
144 | 144 | |||
145 | int q_sesn; | 145 | int q_sesn; | |
146 | int q_flags; | 146 | int q_flags; | |
147 | }; | 147 | }; | |
148 | 148 | |||
149 | struct ubsec_softc { | 149 | struct ubsec_softc { | |
150 | device_t sc_dev; /* generic device */ | 150 | device_t sc_dev; /* generic device */ | |
151 | void *sc_ih; /* interrupt handler cookie */ | 151 | void *sc_ih; /* interrupt handler cookie */ | |
152 | kmutex_t sc_mtx; | |||
152 | bus_space_handle_t sc_sh; /* memory handle */ | 153 | bus_space_handle_t sc_sh; /* memory handle */ | |
153 | bus_space_tag_t sc_st; /* memory tag */ | 154 | bus_space_tag_t sc_st; /* memory tag */ | |
154 | bus_dma_tag_t sc_dmat; /* dma tag */ | 155 | bus_dma_tag_t sc_dmat; /* dma tag */ | |
155 | int sc_flags; /* device specific flags */ | 156 | int sc_flags; /* device specific flags */ | |
156 | int sc_suspended; | 157 | int sc_suspended; | |
157 | int sc_needwakeup; /* notify crypto layer */ | 158 | int sc_needwakeup; /* notify crypto layer */ | |
158 | u_int32_t sc_statmask; /* interrupt status mask */ | 159 | u_int32_t sc_statmask; /* interrupt status mask */ | |
159 | int32_t sc_cid; /* crypto tag */ | 160 | int32_t sc_cid; /* crypto tag */ | |
160 | SIMPLEQ_HEAD(,ubsec_q) sc_queue; /* packet queue, mcr1 */ | 161 | SIMPLEQ_HEAD(,ubsec_q) sc_queue; /* packet queue, mcr1 */ | |
161 | int sc_nqueue; /* count enqueued, mcr1 */ | 162 | int sc_nqueue; /* count enqueued, mcr1 */ | |
162 | SIMPLEQ_HEAD(,ubsec_q) sc_qchip; /* on chip, mcr1 */ | 163 | SIMPLEQ_HEAD(,ubsec_q) sc_qchip; /* on chip, mcr1 */ | |
163 | int sc_nqchip; /* count on chip, mcr1 */ | 164 | int sc_nqchip; /* count on chip, mcr1 */ | |
164 | SIMPLEQ_HEAD(,ubsec_q) sc_freequeue; /* list of free queue elements */ | 165 | SIMPLEQ_HEAD(,ubsec_q) sc_freequeue; /* list of free queue elements */ | |
165 | SIMPLEQ_HEAD(,ubsec_q2) sc_queue2; /* packet queue, mcr2 */ | 166 | SIMPLEQ_HEAD(,ubsec_q2) sc_queue2; /* packet queue, mcr2 */ | |
166 | int sc_nqueue2; /* count enqueued, mcr2 */ | 167 | int sc_nqueue2; /* count enqueued, mcr2 */ | |
167 | SIMPLEQ_HEAD(,ubsec_q2) sc_qchip2; /* on chip, mcr2 */ | 168 | SIMPLEQ_HEAD(,ubsec_q2) sc_qchip2; /* on chip, mcr2 */ | |
168 | int sc_nsessions; /* # of sessions */ | 169 | int sc_nsessions; /* # of sessions */ | |
169 | struct ubsec_session *sc_sessions; /* sessions */ | 170 | struct ubsec_session *sc_sessions; /* sessions */ | |
170 | struct callout sc_rngto; /* rng timeout */ | 171 | struct callout sc_rngto; /* rng timeout */ | |
171 | int sc_rnghz; /* rng poll time */ | 172 | int sc_rnghz; /* rng poll time */ | |
172 | struct ubsec_q2_rng sc_rng; | 173 | struct ubsec_q2_rng sc_rng; | |
174 | krndsource_t sc_rnd_source; | |||
175 | int sc_rng_need; /* how many bytes wanted */ | |||
173 | struct ubsec_dma sc_dmaa[UBS_MAX_NQUEUE]; | 176 | struct ubsec_dma sc_dmaa[UBS_MAX_NQUEUE]; | |
174 | struct ubsec_q *sc_queuea[UBS_MAX_NQUEUE]; | 177 | struct ubsec_q *sc_queuea[UBS_MAX_NQUEUE]; | |
175 | SIMPLEQ_HEAD(,ubsec_q2) sc_q2free; /* free list */ | 178 | SIMPLEQ_HEAD(,ubsec_q2) sc_q2free; /* free list */ | |
176 | }; | 179 | }; | |
177 | 180 | |||
178 | #define UBSEC_QFLAGS_COPYOUTIV 0x1 | 181 | #define UBSEC_QFLAGS_COPYOUTIV 0x1 | |
179 | 182 | |||
180 | struct ubsec_session { | 183 | struct ubsec_session { | |
181 | u_int32_t ses_used; | 184 | u_int32_t ses_used; | |
182 | u_int32_t ses_deskey[6]; /* 3DES key */ | 185 | u_int32_t ses_deskey[6]; /* 3DES key */ | |
183 | u_int32_t ses_hminner[5]; /* hmac inner state */ | 186 | u_int32_t ses_hminner[5]; /* hmac inner state */ | |
184 | u_int32_t ses_hmouter[5]; /* hmac outer state */ | 187 | u_int32_t ses_hmouter[5]; /* hmac outer state */ | |
185 | u_int32_t ses_iv[2]; /* [3]DES iv */ | 188 | u_int32_t ses_iv[2]; /* [3]DES iv */ |
--- src/sys/dev/scsipi/sd.c 2013/05/29 00:47:49 1.300
+++ src/sys/dev/scsipi/sd.c 2013/06/13 00:55:01 1.301
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: sd.c,v 1.300 2013/05/29 00:47:49 christos Exp $ */ | 1 | /* $NetBSD: sd.c,v 1.301 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Charles M. Hannum. | 8 | * by Charles M. Hannum. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -37,27 +37,27 @@ | @@ -37,27 +37,27 @@ | |||
37 | * Mellon University, makes this software available to CMU to distribute | 37 | * Mellon University, makes this software available to CMU to distribute | |
38 | * or use in any manner that they see fit as long as this message is kept with | 38 | * or use in any manner that they see fit as long as this message is kept with | |
39 | * the software. For this reason TFS also grants any other persons or | 39 | * the software. For this reason TFS also grants any other persons or | |
40 | * organisations permission to use or modify this software. | 40 | * organisations permission to use or modify this software. | |
41 | * | 41 | * | |
42 | * TFS supplies this software to be publicly redistributed | 42 | * TFS supplies this software to be publicly redistributed | |
43 | * on the understanding that TFS is not responsible for the correct | 43 | * on the understanding that TFS is not responsible for the correct | |
44 | * functioning of this software in any circumstances. | 44 | * functioning of this software in any circumstances. | |
45 | * | 45 | * | |
46 | * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992 | 46 | * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992 | |
47 | */ | 47 | */ | |
48 | 48 | |||
49 | #include <sys/cdefs.h> | 49 | #include <sys/cdefs.h> | |
50 | __KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.300 2013/05/29 00:47:49 christos Exp $"); | 50 | __KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.301 2013/06/13 00:55:01 tls Exp $"); | |
51 | 51 | |||
52 | #include "opt_scsi.h" | 52 | #include "opt_scsi.h" | |
53 | 53 | |||
54 | #include <sys/param.h> | 54 | #include <sys/param.h> | |
55 | #include <sys/systm.h> | 55 | #include <sys/systm.h> | |
56 | #include <sys/kernel.h> | 56 | #include <sys/kernel.h> | |
57 | #include <sys/file.h> | 57 | #include <sys/file.h> | |
58 | #include <sys/stat.h> | 58 | #include <sys/stat.h> | |
59 | #include <sys/ioctl.h> | 59 | #include <sys/ioctl.h> | |
60 | #include <sys/scsiio.h> | 60 | #include <sys/scsiio.h> | |
61 | #include <sys/buf.h> | 61 | #include <sys/buf.h> | |
62 | #include <sys/bufq.h> | 62 | #include <sys/bufq.h> | |
63 | #include <sys/uio.h> | 63 | #include <sys/uio.h> | |
@@ -205,27 +205,27 @@ sdmatch(device_t parent, cfdata_t match, | @@ -205,27 +205,27 @@ sdmatch(device_t parent, cfdata_t match, | |||
205 | 205 | |||
206 | return (priority); | 206 | return (priority); | |
207 | } | 207 | } | |
208 | 208 | |||
209 | /* | 209 | /* | |
210 | * Attach routine common to atapi & scsi. | 210 | * Attach routine common to atapi & scsi. | |
211 | */ | 211 | */ | |
212 | static void | 212 | static void | |
213 | sdattach(device_t parent, device_t self, void *aux) | 213 | sdattach(device_t parent, device_t self, void *aux) | |
214 | { | 214 | { | |
215 | struct sd_softc *sd = device_private(self); | 215 | struct sd_softc *sd = device_private(self); | |
216 | struct scsipibus_attach_args *sa = aux; | 216 | struct scsipibus_attach_args *sa = aux; | |
217 | struct scsipi_periph *periph = sa->sa_periph; | 217 | struct scsipi_periph *periph = sa->sa_periph; | |
218 | int error, result, rndval = cprng_strong32(); | 218 | int error, result; | |
219 | struct disk_parms *dp = &sd->params; | 219 | struct disk_parms *dp = &sd->params; | |
220 | char pbuf[9]; | 220 | char pbuf[9]; | |
221 | 221 | |||
222 | SC_DEBUG(periph, SCSIPI_DB2, ("sdattach: ")); | 222 | SC_DEBUG(periph, SCSIPI_DB2, ("sdattach: ")); | |
223 | 223 | |||
224 | sd->sc_dev = self; | 224 | sd->sc_dev = self; | |
225 | sd->type = (sa->sa_inqbuf.type & SID_TYPE); | 225 | sd->type = (sa->sa_inqbuf.type & SID_TYPE); | |
226 | strncpy(sd->name, sa->sa_inqbuf.product, sizeof(sd->name)); | 226 | strncpy(sd->name, sa->sa_inqbuf.product, sizeof(sd->name)); | |
227 | if (sd->type == T_SIMPLE_DIRECT) | 227 | if (sd->type == T_SIMPLE_DIRECT) | |
228 | periph->periph_quirks |= PQUIRK_ONLYBIG | PQUIRK_NOBIGMODESENSE; | 228 | periph->periph_quirks |= PQUIRK_ONLYBIG | PQUIRK_NOBIGMODESENSE; | |
229 | 229 | |||
230 | if (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sa->sa_periph)) == | 230 | if (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sa->sa_periph)) == | |
231 | SCSIPI_BUSTYPE_SCSI && periph->periph_version == 0) | 231 | SCSIPI_BUSTYPE_SCSI && periph->periph_version == 0) | |
@@ -318,36 +318,36 @@ sdattach(device_t parent, device_t self, | @@ -318,36 +318,36 @@ sdattach(device_t parent, device_t self, | |||
318 | */ | 318 | */ | |
319 | rnd_attach_source(&sd->rnd_source, device_xname(sd->sc_dev), | 319 | rnd_attach_source(&sd->rnd_source, device_xname(sd->sc_dev), | |
320 | RND_TYPE_DISK, 0); | 320 | RND_TYPE_DISK, 0); | |
321 | 321 | |||
322 | /* Discover wedges on this disk. */ | 322 | /* Discover wedges on this disk. */ | |
323 | dkwedge_discover(&sd->sc_dk); | 323 | dkwedge_discover(&sd->sc_dk); | |
324 | 324 | |||
325 | /* | 325 | /* | |
326 | * Disk insertion and removal times can be a useful source | 326 | * Disk insertion and removal times can be a useful source | |
327 | * of entropy, though the estimator should never _count_ | 327 | * of entropy, though the estimator should never _count_ | |
328 | * these bits, on insertion, because the deltas to the | 328 | * these bits, on insertion, because the deltas to the | |
329 | * nonexistent) previous event should never allow it. | 329 | * nonexistent) previous event should never allow it. | |
330 | */ | 330 | */ | |
331 | rnd_add_uint32(&sd->rnd_source, rndval); | 331 | rnd_add_uint32(&sd->rnd_source, 0); | |
332 | } | 332 | } | |
333 | 333 | |||
334 | static int | 334 | static int | |
335 | sddetach(device_t self, int flags) | 335 | sddetach(device_t self, int flags) | |
336 | { | 336 | { | |
337 | struct sd_softc *sd = device_private(self); | 337 | struct sd_softc *sd = device_private(self); | |
338 | int s, bmaj, cmaj, i, mn, rc, rndval = cprng_strong32(); | 338 | int s, bmaj, cmaj, i, mn, rc; | |
339 | 339 | |||
340 | rnd_add_uint32(&sd->rnd_source, rndval); | 340 | rnd_add_uint32(&sd->rnd_source, 0); | |
341 | 341 | |||
342 | if ((rc = disk_begindetach(&sd->sc_dk, sdlastclose, self, flags)) != 0) | 342 | if ((rc = disk_begindetach(&sd->sc_dk, sdlastclose, self, flags)) != 0) | |
343 | return rc; | 343 | return rc; | |
344 | 344 | |||
345 | /* locate the major number */ | 345 | /* locate the major number */ | |
346 | bmaj = bdevsw_lookup_major(&sd_bdevsw); | 346 | bmaj = bdevsw_lookup_major(&sd_bdevsw); | |
347 | cmaj = cdevsw_lookup_major(&sd_cdevsw); | 347 | cmaj = cdevsw_lookup_major(&sd_cdevsw); | |
348 | 348 | |||
349 | /* Nuke the vnodes for any open instances */ | 349 | /* Nuke the vnodes for any open instances */ | |
350 | for (i = 0; i < MAXPARTITIONS; i++) { | 350 | for (i = 0; i < MAXPARTITIONS; i++) { | |
351 | mn = SDMINOR(device_unit(self), i); | 351 | mn = SDMINOR(device_unit(self), i); | |
352 | vdevgone(bmaj, mn, mn, VBLK); | 352 | vdevgone(bmaj, mn, mn, VBLK); | |
353 | vdevgone(cmaj, mn, mn, VCHR); | 353 | vdevgone(cmaj, mn, mn, VCHR); |
--- src/sys/kern/Attic/kern_rndpool.c 2012/04/17 02:50:38 1.2
+++ src/sys/kern/Attic/kern_rndpool.c 2013/06/13 00:55:01 1.3
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: kern_rndpool.c,v 1.2 2012/04/17 02:50:38 tls Exp $ */ | 1 | /* $NetBSD: kern_rndpool.c,v 1.3 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Michael Graff <explorer@flame.org>. This code uses ideas and | 8 | * by Michael Graff <explorer@flame.org>. This code uses ideas and | |
9 | * algorithms from the Linux driver written by Ted Ts'o. | 9 | * algorithms from the Linux driver written by Ted Ts'o. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -21,49 +21,52 @@ | @@ -21,49 +21,52 @@ | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: kern_rndpool.c,v 1.2 2012/04/17 02:50:38 tls Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: kern_rndpool.c,v 1.3 2013/06/13 00:55:01 tls Exp $"); | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | #include <sys/systm.h> | 37 | #include <sys/systm.h> | |
38 | #include <sys/sha1.h> | 38 | #include <sys/sha1.h> | |
39 | 39 | |||
40 | #include <sys/rnd.h> | 40 | #include <sys/rnd.h> | |
41 | #include <dev/rnd_private.h> | 41 | #include <dev/rnd_private.h> | |
42 | 42 | |||
43 | /* | 43 | /* | |
44 | * The random pool "taps" | 44 | * The random pool "taps" | |
45 | */ | 45 | */ | |
46 | #define TAP1 99 | 46 | #define TAP1 99 | |
47 | #define TAP2 59 | 47 | #define TAP2 59 | |
48 | #define TAP3 31 | 48 | #define TAP3 31 | |
49 | #define TAP4 9 | 49 | #define TAP4 9 | |
50 | #define TAP5 7 | 50 | #define TAP5 7 | |
51 | 51 | |||
52 | /* | 52 | /* | |
53 | * Let others know: the pool is full. | 53 | * Let others know: the pool is full. | |
54 | * | |||
55 | * XXX these should be per-pool if we really mean to allow multiple pools. | |||
54 | */ | 56 | */ | |
55 | int rnd_full = 0; /* Flag: is the pool full? */ | 57 | int rnd_full = 0; /* Flag: is the pool full? */ | |
56 | int rnd_filled = 0; /* Count: how many times filled? */ | 58 | int rnd_filled = 0; /* Count: how many times filled? */ | |
59 | int rnd_empty = 1; /* Flag: is the pool empty? */ | |||
57 | 60 | |||
58 | static inline void rndpool_add_one_word(rndpool_t *, u_int32_t); | 61 | static inline void rndpool_add_one_word(rndpool_t *, u_int32_t); | |
59 | 62 | |||
60 | void | 63 | void | |
61 | rndpool_init(rndpool_t *rp) | 64 | rndpool_init(rndpool_t *rp) | |
62 | { | 65 | { | |
63 | 66 | |||
64 | rp->cursor = 0; | 67 | rp->cursor = 0; | |
65 | rp->rotate = 1; | 68 | rp->rotate = 1; | |
66 | 69 | |||
67 | memset(&rp->stats, 0, sizeof(rp->stats)); | 70 | memset(&rp->stats, 0, sizeof(rp->stats)); | |
68 | 71 | |||
69 | rp->stats.curentropy = 0; | 72 | rp->stats.curentropy = 0; |
--- src/sys/kern/Attic/kern_rndq.c 2013/01/26 22:22:07 1.10
+++ src/sys/kern/Attic/kern_rndq.c 2013/06/13 00:55:01 1.11
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: kern_rndq.c,v 1.10 2013/01/26 22:22:07 tls Exp $ */ | 1 | /* $NetBSD: kern_rndq.c,v 1.11 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997-2013 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997-2013 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. | 8 | * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. | |
9 | * This code uses ideas and algorithms from the Linux driver written by | 9 | * This code uses ideas and algorithms from the Linux driver written by | |
10 | * Ted Ts'o. | 10 | * Ted Ts'o. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -22,40 +22,41 @@ | @@ -22,40 +22,41 @@ | |||
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | __KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.10 2013/01/26 22:22:07 tls Exp $"); | 35 | __KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.11 2013/06/13 00:55:01 tls Exp $"); | |
36 | 36 | |||
37 | #include <sys/param.h> | 37 | #include <sys/param.h> | |
38 | #include <sys/ioctl.h> | 38 | #include <sys/ioctl.h> | |
39 | #include <sys/fcntl.h> | 39 | #include <sys/fcntl.h> | |
40 | #include <sys/select.h> | 40 | #include <sys/select.h> | |
41 | #include <sys/poll.h> | 41 | #include <sys/poll.h> | |
42 | #include <sys/kmem.h> | 42 | #include <sys/kmem.h> | |
43 | #include <sys/mutex.h> | 43 | #include <sys/mutex.h> | |
44 | #include <sys/proc.h> | 44 | #include <sys/proc.h> | |
45 | #include <sys/kernel.h> | 45 | #include <sys/kernel.h> | |
46 | #include <sys/conf.h> | 46 | #include <sys/conf.h> | |
47 | #include <sys/systm.h> | 47 | #include <sys/systm.h> | |
48 | #include <sys/callout.h> | 48 | #include <sys/callout.h> | |
49 | #include <sys/intr.h> | |||
49 | #include <sys/rnd.h> | 50 | #include <sys/rnd.h> | |
50 | #include <sys/vnode.h> | 51 | #include <sys/vnode.h> | |
51 | #include <sys/pool.h> | 52 | #include <sys/pool.h> | |
52 | #include <sys/kauth.h> | 53 | #include <sys/kauth.h> | |
53 | #include <sys/once.h> | 54 | #include <sys/once.h> | |
54 | #include <sys/rngtest.h> | 55 | #include <sys/rngtest.h> | |
55 | #include <sys/cpu.h> /* XXX temporary, see rnd_detach_source */ | 56 | #include <sys/cpu.h> /* XXX temporary, see rnd_detach_source */ | |
56 | 57 | |||
57 | #include <dev/rnd_private.h> | 58 | #include <dev/rnd_private.h> | |
58 | 59 | |||
59 | #if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */ | 60 | #if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */ | |
60 | #include <machine/cpu_counter.h> | 61 | #include <machine/cpu_counter.h> | |
61 | #endif | 62 | #endif | |
@@ -89,30 +90,33 @@ int rnd_debug = 0; | @@ -89,30 +90,33 @@ int rnd_debug = 0; | |||
89 | typedef struct _rnd_sample_t { | 90 | typedef struct _rnd_sample_t { | |
90 | SIMPLEQ_ENTRY(_rnd_sample_t) next; | 91 | SIMPLEQ_ENTRY(_rnd_sample_t) next; | |
91 | krndsource_t *source; | 92 | krndsource_t *source; | |
92 | int cursor; | 93 | int cursor; | |
93 | int entropy; | 94 | int entropy; | |
94 | u_int32_t ts[RND_SAMPLE_COUNT]; | 95 | u_int32_t ts[RND_SAMPLE_COUNT]; | |
95 | u_int32_t values[RND_SAMPLE_COUNT]; | 96 | u_int32_t values[RND_SAMPLE_COUNT]; | |
96 | } rnd_sample_t; | 97 | } rnd_sample_t; | |
97 | 98 | |||
98 | /* | 99 | /* | |
99 | * The event queue. Fields are altered at an interrupt level. | 100 | * The event queue. Fields are altered at an interrupt level. | |
100 | * All accesses must be protected with the mutex. | 101 | * All accesses must be protected with the mutex. | |
101 | */ | 102 | */ | |
102 | volatile int rnd_timeout_pending; | |||
103 | SIMPLEQ_HEAD(, _rnd_sample_t) rnd_samples; | 103 | SIMPLEQ_HEAD(, _rnd_sample_t) rnd_samples; | |
104 | kmutex_t rnd_mtx; | 104 | kmutex_t rnd_mtx; | |
105 | 105 | |||
106 | /* | |||
107 | * This lock protects dispatch of our soft interrupts. | |||
108 | */ | |||
109 | kmutex_t rndsoft_mtx; | |||
106 | 110 | |||
107 | /* | 111 | /* | |
108 | * Entropy sinks: usually other generators waiting to be rekeyed. | 112 | * Entropy sinks: usually other generators waiting to be rekeyed. | |
109 | * | 113 | * | |
110 | * A sink's callback MUST NOT re-add the sink to the list, or | 114 | * A sink's callback MUST NOT re-add the sink to the list, or | |
111 | * list corruption will occur. The list is protected by the | 115 | * list corruption will occur. The list is protected by the | |
112 | * rndsink_mtx, which must be released before calling any sink's | 116 | * rndsink_mtx, which must be released before calling any sink's | |
113 | * callback. | 117 | * callback. | |
114 | */ | 118 | */ | |
115 | TAILQ_HEAD(, rndsink) rnd_sinks; | 119 | TAILQ_HEAD(, rndsink) rnd_sinks; | |
116 | kmutex_t rndsink_mtx; | 120 | kmutex_t rndsink_mtx; | |
117 | 121 | |||
118 | /* | 122 | /* | |
@@ -139,34 +143,35 @@ kcondvar_t rndpool_cv; | @@ -139,34 +143,35 @@ kcondvar_t rndpool_cv; | |||
139 | static krndsource_t rnd_source_no_collect = { | 143 | static krndsource_t rnd_source_no_collect = { | |
140 | /* LIST_ENTRY list */ | 144 | /* LIST_ENTRY list */ | |
141 | .name = { 'N', 'o', 'C', 'o', 'l', 'l', 'e', 'c', 't', | 145 | .name = { 'N', 'o', 'C', 'o', 'l', 'l', 'e', 'c', 't', | |
142 | 0, 0, 0, 0, 0, 0, 0 }, | 146 | 0, 0, 0, 0, 0, 0, 0 }, | |
143 | .last_time = 0, .last_delta = 0, .last_delta2 = 0, .total = 0, | 147 | .last_time = 0, .last_delta = 0, .last_delta2 = 0, .total = 0, | |
144 | .type = RND_TYPE_UNKNOWN, | 148 | .type = RND_TYPE_UNKNOWN, | |
145 | .flags = (RND_FLAG_NO_COLLECT | | 149 | .flags = (RND_FLAG_NO_COLLECT | | |
146 | RND_FLAG_NO_ESTIMATE | | 150 | RND_FLAG_NO_ESTIMATE | | |
147 | RND_TYPE_UNKNOWN), | 151 | RND_TYPE_UNKNOWN), | |
148 | .state = NULL, | 152 | .state = NULL, | |
149 | .test_cnt = 0, | 153 | .test_cnt = 0, | |
150 | .test = NULL | 154 | .test = NULL | |
151 | }; | 155 | }; | |
152 | 156 | void *rnd_process, *rnd_wakeup; | ||
153 | struct callout rnd_callout, skew_callout; | 157 | struct callout skew_callout; | |
154 | 158 | |||
155 | void rnd_wakeup_readers(void); | 159 | void rnd_wakeup_readers(void); | |
156 | static inline u_int32_t rnd_estimate_entropy(krndsource_t *, u_int32_t); | 160 | static inline u_int32_t rnd_estimate_entropy(krndsource_t *, u_int32_t); | |
157 | static inline u_int32_t rnd_counter(void); | 161 | static inline u_int32_t rnd_counter(void); | |
158 | static void rnd_timeout(void *); | 162 | static void rnd_intr(void *); | |
159 | static void rnd_process_events(void *); | 163 | static void rnd_wake(void *); | |
164 | static void rnd_process_events(void); | |||
160 | u_int32_t rnd_extract_data_locked(void *, u_int32_t, u_int32_t); /* XXX */ | 165 | u_int32_t rnd_extract_data_locked(void *, u_int32_t, u_int32_t); /* XXX */ | |
161 | static void rnd_add_data_ts(krndsource_t *, const void *const, | 166 | static void rnd_add_data_ts(krndsource_t *, const void *const, | |
162 | uint32_t, uint32_t, uint32_t); | 167 | uint32_t, uint32_t, uint32_t); | |
163 | 168 | |||
164 | int rnd_ready = 0; | 169 | int rnd_ready = 0; | |
165 | int rnd_initial_entropy = 0; | 170 | int rnd_initial_entropy = 0; | |
166 | 171 | |||
167 | #ifdef DIAGNOSTIC | 172 | #ifdef DIAGNOSTIC | |
168 | static int rnd_tested = 0; | 173 | static int rnd_tested = 0; | |
169 | static rngtest_t rnd_rt; | 174 | static rngtest_t rnd_rt; | |
170 | static uint8_t rnd_testbits[sizeof(rnd_rt.rt_b)]; | 175 | static uint8_t rnd_testbits[sizeof(rnd_rt.rt_b)]; | |
171 | #endif | 176 | #endif | |
172 | 177 | |||
@@ -186,91 +191,161 @@ rnd_counter(void) | @@ -186,91 +191,161 @@ rnd_counter(void) | |||
186 | #if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */ | 191 | #if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */ | |
187 | if (cpu_hascounter()) | 192 | if (cpu_hascounter()) | |
188 | return (cpu_counter32()); | 193 | return (cpu_counter32()); | |
189 | #endif | 194 | #endif | |
190 | if (rnd_ready) { | 195 | if (rnd_ready) { | |
191 | microtime(&tv); | 196 | microtime(&tv); | |
192 | return (tv.tv_sec * 1000000 + tv.tv_usec); | 197 | return (tv.tv_sec * 1000000 + tv.tv_usec); | |
193 | } | 198 | } | |
194 | /* when called from rnd_init, its too early to call microtime safely */ | 199 | /* when called from rnd_init, its too early to call microtime safely */ | |
195 | return (0); | 200 | return (0); | |
196 | } | 201 | } | |
197 | 202 | |||
198 | /* | 203 | /* | |
204 | * We may be called from low IPL -- protect our softint. | |||
205 | */ | |||
206 | ||||
207 | static inline void | |||
208 | rnd_schedule_softint(void *softint) | |||
209 | { | |||
210 | mutex_spin_enter(&rndsoft_mtx); | |||
211 | softint_schedule(softint); | |||
212 | mutex_spin_exit(&rndsoft_mtx); | |||
213 | } | |||
214 | ||||
215 | /* | |||
216 | * XXX repulsive: we can't initialize our softints in rnd_init | |||
217 | * XXX (too early) so we wrap the points where we'd schedule them, thus. | |||
218 | */ | |||
219 | static inline void | |||
220 | rnd_schedule_process(void) | |||
221 | { | |||
222 | if (__predict_true(rnd_process)) { | |||
223 | rnd_schedule_softint(rnd_process); | |||
224 | return; | |||
225 | } | |||
226 | if (!cold) { | |||
227 | rnd_process = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE, | |||
228 | rnd_intr, NULL); | |||
229 | } | |||
230 | rnd_process_events(); | |||
231 | } | |||
232 | ||||
233 | static inline void | |||
234 | rnd_schedule_wakeup(void) | |||
235 | { | |||
236 | if (__predict_true(rnd_wakeup)) { | |||
237 | rnd_schedule_softint(rnd_wakeup); | |||
238 | return; | |||
239 | } | |||
240 | if (!cold) { | |||
241 | rnd_wakeup = softint_establish(SOFTINT_CLOCK|SOFTINT_MPSAFE, | |||
242 | rnd_wake, NULL); | |||
243 | } | |||
244 | rnd_wakeup_readers(); | |||
245 | } | |||
246 | ||||
247 | /* | |||
248 | * Tell any sources with "feed me" callbacks that we are hungry. | |||
249 | */ | |||
250 | static void | |||
251 | rnd_getmore(size_t byteswanted) | |||
252 | { | |||
253 | krndsource_t *rs; | |||
254 | ||||
255 | KASSERT(mutex_owned(&rndpool_mtx)); | |||
256 | ||||
257 | LIST_FOREACH(rs, &rnd_sources, list) { | |||
258 | if (rs->flags & RND_FLAG_HASCB) { | |||
259 | KASSERT(rs->get != NULL); | |||
260 | KASSERT(rs->getarg != NULL); | |||
261 | rs->get((size_t)byteswanted, rs->getarg); | |||
262 | #ifdef RND_VERBOSE | |||
263 | printf("rnd: asking source %s for %d bytes\n", | |||
264 | rs->name, (int)byteswanted); | |||
265 | #endif | |||
266 | } | |||
267 | } | |||
268 | } | |||
269 | ||||
270 | /* | |||
199 | * Check to see if there are readers waiting on us. If so, kick them. | 271 | * Check to see if there are readers waiting on us. If so, kick them. | |
200 | */ | 272 | */ | |
201 | void | 273 | void | |
202 | rnd_wakeup_readers(void) | 274 | rnd_wakeup_readers(void) | |
203 | { | 275 | { | |
204 | rndsink_t *sink, *tsink; | 276 | rndsink_t *sink, *tsink; | |
277 | size_t entropy_count; | |||
205 | TAILQ_HEAD(, rndsink) sunk = TAILQ_HEAD_INITIALIZER(sunk); | 278 | TAILQ_HEAD(, rndsink) sunk = TAILQ_HEAD_INITIALIZER(sunk); | |
206 | 279 | |||
207 | mutex_spin_enter(&rndpool_mtx); | 280 | mutex_spin_enter(&rndpool_mtx); | |
208 | if (rndpool_get_entropy_count(&rnd_pool) < RND_ENTROPY_THRESHOLD * 8) { | 281 | entropy_count = rndpool_get_entropy_count(&rnd_pool); | |
282 | if (entropy_count < RND_ENTROPY_THRESHOLD * 8) { | |||
283 | rnd_empty = 1; | |||
209 | mutex_spin_exit(&rndpool_mtx); | 284 | mutex_spin_exit(&rndpool_mtx); | |
210 | return; | 285 | return; | |
286 | } else { | |||
287 | #ifdef RND_VERBOSE | |||
288 | if (__predict_false(!rnd_initial_entropy)) { | |||
289 | printf("rnd: have initial entropy (%u)\n", | |||
290 | (unsigned int)entropy_count); | |||
291 | } | |||
292 | #endif | |||
293 | rnd_empty = 0; | |||
294 | rnd_initial_entropy = 1; | |||
211 | } | 295 | } | |
212 | 296 | |||
213 | /* | 297 | /* | |
214 | * First, take care of in-kernel consumers needing rekeying. | 298 | * First, take care of consumers needing rekeying. | |
215 | */ | 299 | */ | |
216 | mutex_spin_enter(&rndsink_mtx); | 300 | mutex_spin_enter(&rndsink_mtx); | |
217 | TAILQ_FOREACH_SAFE(sink, &rnd_sinks, tailq, tsink) { | 301 | TAILQ_FOREACH_SAFE(sink, &rnd_sinks, tailq, tsink) { | |
218 | if (!mutex_tryenter(&sink->mtx)) { | 302 | if (!mutex_tryenter(&sink->mtx)) { | |
219 | #ifdef RND_VERBOSE | 303 | #ifdef RND_VERBOSE | |
220 | printf("rnd_wakeup_readers: " | 304 | printf("rnd_wakeup_readers: " | |
221 | "skipping busy rndsink\n"); | 305 | "skipping busy rndsink\n"); | |
222 | #endif | 306 | #endif | |
223 | continue; | 307 | continue; | |
224 | } | 308 | } | |
225 | 309 | |||
226 | KASSERT(RSTATE_PENDING == sink->state); | 310 | KASSERT(RSTATE_PENDING == sink->state); | |
227 | 311 | |||
228 | if ((sink->len + RND_ENTROPY_THRESHOLD) * 8 < | 312 | if (sink->len * 8 < rndpool_get_entropy_count(&rnd_pool)) { | |
229 | rndpool_get_entropy_count(&rnd_pool)) { | |||
230 | /* We have enough entropy to sink some here. */ | 313 | /* We have enough entropy to sink some here. */ | |
231 | if (rndpool_extract_data(&rnd_pool, sink->data, | 314 | if (rndpool_extract_data(&rnd_pool, sink->data, | |
232 | sink->len, RND_EXTRACT_GOOD) | 315 | sink->len, RND_EXTRACT_GOOD) | |
233 | != sink->len) { | 316 | != sink->len) { | |
234 | panic("could not extract estimated " | 317 | panic("could not extract estimated " | |
235 | "entropy from pool"); | 318 | "entropy from pool"); | |
236 | } | 319 | } | |
237 | sink->state = RSTATE_HASBITS; | 320 | sink->state = RSTATE_HASBITS; | |
238 | /* Move this sink to the list of pending callbacks */ | 321 | /* Move this sink to the list of pending callbacks */ | |
239 | TAILQ_REMOVE(&rnd_sinks, sink, tailq); | 322 | TAILQ_REMOVE(&rnd_sinks, sink, tailq); | |
240 | TAILQ_INSERT_HEAD(&sunk, sink, tailq); | 323 | TAILQ_INSERT_HEAD(&sunk, sink, tailq); | |
241 | } else { | 324 | } else { | |
242 | mutex_exit(&sink->mtx); | |||
243 | } | |||
244 | } | |||
245 | mutex_spin_exit(&rndsink_mtx); | |||
246 | ||||
247 | /* | |||
248 | * If we still have enough new bits to do something, feed userspace. | |||
249 | */ | |||
250 | if (rndpool_get_entropy_count(&rnd_pool) > RND_ENTROPY_THRESHOLD * 8) { | |||
251 | #ifdef RND_VERBOSE | 325 | #ifdef RND_VERBOSE | |
252 | if (!rnd_initial_entropy) | 326 | printf("sink wants %d, we have %d, asking for more\n", | |
253 | printf("rnd: have initial entropy (%u)\n", | 327 | (int)sink->len * 8, | |
254 | rndpool_get_entropy_count(&rnd_pool)); | 328 | (int)rndpool_get_entropy_count(&rnd_pool)); | |
255 | #endif | 329 | #endif | |
256 | rnd_initial_entropy = 1; | 330 | mutex_spin_exit(&sink->mtx); | |
257 | mutex_spin_exit(&rndpool_mtx); | 331 | rnd_getmore(sink->len * 8); | |
258 | } else { | 332 | } | |
259 | mutex_spin_exit(&rndpool_mtx); | |||
260 | } | 333 | } | |
334 | mutex_spin_exit(&rndsink_mtx); | |||
335 | mutex_spin_exit(&rndpool_mtx); | |||
261 | 336 | |||
262 | /* | 337 | /* | |
263 | * Now that we have dropped the mutex, we can run sinks' callbacks. | 338 | * Now that we have dropped the mutexes, we can run sinks' callbacks. | |
264 | * Since we have reused the "tailq" member of the sink structure for | 339 | * Since we have reused the "tailq" member of the sink structure for | |
265 | * this temporary on-stack queue, the callback must NEVER re-add | 340 | * this temporary on-stack queue, the callback must NEVER re-add | |
266 | * the sink to the main queue, or our on-stack queue will become | 341 | * the sink to the main queue, or our on-stack queue will become | |
267 | * corrupt. | 342 | * corrupt. | |
268 | */ | 343 | */ | |
269 | while ((sink = TAILQ_FIRST(&sunk))) { | 344 | while ((sink = TAILQ_FIRST(&sunk))) { | |
270 | #ifdef RND_VERBOSE | 345 | #ifdef RND_VERBOSE | |
271 | printf("supplying %d bytes to entropy sink \"%s\"" | 346 | printf("supplying %d bytes to entropy sink \"%s\"" | |
272 | " (cb %p, arg %p).\n", | 347 | " (cb %p, arg %p).\n", | |
273 | (int)sink->len, sink->name, sink->cb, sink->arg); | 348 | (int)sink->len, sink->name, sink->cb, sink->arg); | |
274 | #endif | 349 | #endif | |
275 | sink->state = RSTATE_HASBITS; | 350 | sink->state = RSTATE_HASBITS; | |
276 | sink->cb(sink->arg); | 351 | sink->cb(sink->arg); | |
@@ -368,29 +443,27 @@ rnd_skew(void *arg) | @@ -368,29 +443,27 @@ rnd_skew(void *arg) | |||
368 | * rnd_init() must be called very early on in the boot process, so | 443 | * rnd_init() must be called very early on in the boot process, so | |
369 | * the pool is ready for other devices to attach as sources. | 444 | * the pool is ready for other devices to attach as sources. | |
370 | */ | 445 | */ | |
371 | void | 446 | void | |
372 | rnd_init(void) | 447 | rnd_init(void) | |
373 | { | 448 | { | |
374 | u_int32_t c; | 449 | u_int32_t c; | |
375 | 450 | |||
376 | if (rnd_ready) | 451 | if (rnd_ready) | |
377 | return; | 452 | return; | |
378 | 453 | |||
379 | mutex_init(&rnd_mtx, MUTEX_DEFAULT, IPL_VM); | 454 | mutex_init(&rnd_mtx, MUTEX_DEFAULT, IPL_VM); | |
380 | mutex_init(&rndsink_mtx, MUTEX_DEFAULT, IPL_VM); | 455 | mutex_init(&rndsink_mtx, MUTEX_DEFAULT, IPL_VM); | |
381 | 456 | mutex_init(&rndsoft_mtx, MUTEX_DEFAULT, IPL_VM); | ||
382 | callout_init(&rnd_callout, CALLOUT_MPSAFE); | |||
383 | callout_setfunc(&rnd_callout, rnd_timeout, NULL); | |||
384 | 457 | |||
385 | /* | 458 | /* | |
386 | * take a counter early, hoping that there's some variance in | 459 | * take a counter early, hoping that there's some variance in | |
387 | * the following operations | 460 | * the following operations | |
388 | */ | 461 | */ | |
389 | c = rnd_counter(); | 462 | c = rnd_counter(); | |
390 | 463 | |||
391 | LIST_INIT(&rnd_sources); | 464 | LIST_INIT(&rnd_sources); | |
392 | SIMPLEQ_INIT(&rnd_samples); | 465 | SIMPLEQ_INIT(&rnd_samples); | |
393 | TAILQ_INIT(&rnd_sinks); | 466 | TAILQ_INIT(&rnd_sinks); | |
394 | 467 | |||
395 | rndpool_init(&rnd_pool); | 468 | rndpool_init(&rnd_pool); | |
396 | mutex_init(&rndpool_mtx, MUTEX_DEFAULT, IPL_VM); | 469 | mutex_init(&rndpool_mtx, MUTEX_DEFAULT, IPL_VM); | |
@@ -747,46 +820,30 @@ rnd_add_data_ts(krndsource_t *rs, const | @@ -747,46 +820,30 @@ rnd_add_data_ts(krndsource_t *rs, const | |||
747 | 820 | |||
748 | /* | 821 | /* | |
749 | * If we didn't finish any sample buffers, we're done. | 822 | * If we didn't finish any sample buffers, we're done. | |
750 | */ | 823 | */ | |
751 | if (!filled) { | 824 | if (!filled) { | |
752 | return; | 825 | return; | |
753 | } | 826 | } | |
754 | 827 | |||
755 | mutex_spin_enter(&rnd_mtx); | 828 | mutex_spin_enter(&rnd_mtx); | |
756 | while ((state = SIMPLEQ_FIRST(&tmp_samples))) { | 829 | while ((state = SIMPLEQ_FIRST(&tmp_samples))) { | |
757 | SIMPLEQ_REMOVE_HEAD(&tmp_samples, next); | 830 | SIMPLEQ_REMOVE_HEAD(&tmp_samples, next); | |
758 | SIMPLEQ_INSERT_HEAD(&rnd_samples, state, next); | 831 | SIMPLEQ_INSERT_HEAD(&rnd_samples, state, next); | |
759 | } | 832 | } | |
760 | ||||
761 | /* | |||
762 | * If we are still starting up, cause immediate processing of | |||
763 | * the queued samples. Otherwise, if the timeout isn't | |||
764 | * pending, have it run in the near future. | |||
765 | */ | |||
766 | if (__predict_false(cold)) { | |||
767 | #ifdef RND_VERBOSE | |||
768 | printf("rnd: directly processing boot-time events.\n"); | |||
769 | #endif | |||
770 | rnd_process_events(NULL); /* Drops lock! */ | |||
771 | return; | |||
772 | } | |||
773 | if (rnd_timeout_pending == 0) { | |||
774 | rnd_timeout_pending = 1; | |||
775 | mutex_spin_exit(&rnd_mtx); | |||
776 | callout_schedule(&rnd_callout, 1); | |||
777 | return; | |||
778 | } | |||
779 | mutex_spin_exit(&rnd_mtx); | 833 | mutex_spin_exit(&rnd_mtx); | |
834 | ||||
835 | /* Cause processing of queued samples */ | |||
836 | rnd_schedule_process(); | |||
780 | } | 837 | } | |
781 | 838 | |||
782 | static int | 839 | static int | |
783 | rnd_hwrng_test(rnd_sample_t *sample) | 840 | rnd_hwrng_test(rnd_sample_t *sample) | |
784 | { | 841 | { | |
785 | krndsource_t *source = sample->source; | 842 | krndsource_t *source = sample->source; | |
786 | size_t cmplen; | 843 | size_t cmplen; | |
787 | uint8_t *v1, *v2; | 844 | uint8_t *v1, *v2; | |
788 | size_t resid, totest; | 845 | size_t resid, totest; | |
789 | 846 | |||
790 | KASSERT(source->type == RND_TYPE_RNG); | 847 | KASSERT(source->type == RND_TYPE_RNG); | |
791 | 848 | |||
792 | /* | 849 | /* | |
@@ -827,69 +884,97 @@ rnd_hwrng_test(rnd_sample_t *sample) | @@ -827,69 +884,97 @@ rnd_hwrng_test(rnd_sample_t *sample) | |||
827 | return 1; | 884 | return 1; | |
828 | } | 885 | } | |
829 | source->test_cnt = -1; | 886 | source->test_cnt = -1; | |
830 | memset(source->test, 0, sizeof(*source->test)); | 887 | memset(source->test, 0, sizeof(*source->test)); | |
831 | } | 888 | } | |
832 | return 0; | 889 | return 0; | |
833 | } | 890 | } | |
834 | 891 | |||
835 | /* | 892 | /* | |
836 | * Process the events in the ring buffer. Called by rnd_timeout or | 893 | * Process the events in the ring buffer. Called by rnd_timeout or | |
837 | * by the add routines directly if the callout has never fired (that | 894 | * by the add routines directly if the callout has never fired (that | |
838 | * is, if we are "cold" -- just booted). | 895 | * is, if we are "cold" -- just booted). | |
839 | * | 896 | * | |
840 | * Call with rnd_mtx held -- WILL RELEASE IT. | |||
841 | */ | 897 | */ | |
842 | static void | 898 | static void | |
843 | rnd_process_events(void *arg) | 899 | rnd_process_events(void) | |
844 | { | 900 | { | |
845 | rnd_sample_t *sample; | 901 | rnd_sample_t *sample = NULL; | |
846 | krndsource_t *source, *badsource = NULL; | 902 | krndsource_t *source, *badsource = NULL; | |
903 | static krndsource_t *last_source; | |||
847 | u_int32_t entropy; | 904 | u_int32_t entropy; | |
905 | size_t pool_entropy; | |||
906 | int found = 0, wake = 0; | |||
848 | SIMPLEQ_HEAD(, _rnd_sample_t) dq_samples = | 907 | SIMPLEQ_HEAD(, _rnd_sample_t) dq_samples = | |
849 | SIMPLEQ_HEAD_INITIALIZER(dq_samples); | 908 | SIMPLEQ_HEAD_INITIALIZER(dq_samples); | |
850 | SIMPLEQ_HEAD(, _rnd_sample_t) df_samples = | 909 | SIMPLEQ_HEAD(, _rnd_sample_t) df_samples = | |
851 | SIMPLEQ_HEAD_INITIALIZER(df_samples); | 910 | SIMPLEQ_HEAD_INITIALIZER(df_samples); | |
852 | TAILQ_HEAD(, rndsink) sunk = TAILQ_HEAD_INITIALIZER(sunk); | 911 | TAILQ_HEAD(, rndsink) sunk = TAILQ_HEAD_INITIALIZER(sunk); | |
853 | 912 | |||
854 | /* | 913 | /* | |
855 | * Sample queue is protected by rnd_mtx, drain to onstack queue | 914 | * Sample queue is protected by rnd_mtx, drain to onstack queue | |
856 | * and drop lock. | 915 | * and drop lock. | |
857 | */ | 916 | */ | |
858 | 917 | |||
918 | mutex_spin_enter(&rnd_mtx); | |||
859 | while ((sample = SIMPLEQ_FIRST(&rnd_samples))) { | 919 | while ((sample = SIMPLEQ_FIRST(&rnd_samples))) { | |
920 | found++; | |||
860 | SIMPLEQ_REMOVE_HEAD(&rnd_samples, next); | 921 | SIMPLEQ_REMOVE_HEAD(&rnd_samples, next); | |
861 | /* | 922 | /* | |
862 | * We repeat this check here, since it is possible | 923 | * We repeat this check here, since it is possible | |
863 | * the source was disabled before we were called, but | 924 | * the source was disabled before we were called, but | |
864 | * after the entry was queued. | 925 | * after the entry was queued. | |
865 | */ | 926 | */ | |
866 | if (__predict_false(sample->source->flags | 927 | if (__predict_false(sample->source->flags | |
867 | & RND_FLAG_NO_COLLECT)) { | 928 | & RND_FLAG_NO_COLLECT)) { | |
868 | SIMPLEQ_INSERT_TAIL(&df_samples, sample, next); | 929 | SIMPLEQ_INSERT_TAIL(&df_samples, sample, next); | |
869 | } else { | 930 | } else { | |
870 | SIMPLEQ_INSERT_TAIL(&dq_samples, sample, next); | 931 | SIMPLEQ_INSERT_TAIL(&dq_samples, sample, next); | |
871 | } | 932 | } | |
872 | } | 933 | } | |
873 | mutex_spin_exit(&rnd_mtx); | 934 | mutex_spin_exit(&rnd_mtx); | |
874 | 935 | |||
875 | /* Don't thrash the rndpool mtx either. Hold, add all samples. */ | 936 | /* Don't thrash the rndpool mtx either. Hold, add all samples. */ | |
876 | mutex_spin_enter(&rndpool_mtx); | 937 | mutex_spin_enter(&rndpool_mtx); | |
938 | ||||
939 | pool_entropy = rndpool_get_entropy_count(&rnd_pool); | |||
940 | if (pool_entropy > RND_ENTROPY_THRESHOLD * 8) { | |||
941 | wake++; | |||
942 | } else { | |||
943 | rnd_empty = 1; | |||
944 | rnd_getmore((RND_POOLBITS - pool_entropy) / 8); | |||
945 | #ifdef RND_VERBOSE | |||
946 | printf("rnd: empty, asking for %d bits\n", | |||
947 | (int)((RND_POOLBITS - pool_entropy) / 8)); | |||
948 | #endif | |||
949 | } | |||
950 | ||||
877 | while ((sample = SIMPLEQ_FIRST(&dq_samples))) { | 951 | while ((sample = SIMPLEQ_FIRST(&dq_samples))) { | |
878 | SIMPLEQ_REMOVE_HEAD(&dq_samples, next); | 952 | SIMPLEQ_REMOVE_HEAD(&dq_samples, next); | |
879 | source = sample->source; | 953 | source = sample->source; | |
880 | entropy = sample->entropy; | 954 | entropy = sample->entropy; | |
881 | 955 | |||
882 | /* | 956 | /* | |
957 | * Don't provide a side channel for timing attacks on | |||
958 | * low-rate sources: require mixing with some other | |||
959 | * source before we schedule a wakeup. | |||
960 | */ | |||
961 | if (!wake && | |||
962 | (source != last_source || source->flags & RND_FLAG_FAST)) { | |||
963 | wake++; | |||
964 | } | |||
965 | last_source = source; | |||
966 | ||||
967 | /* | |||
883 | * Hardware generators are great but sometimes they | 968 | * Hardware generators are great but sometimes they | |
884 | * have...hardware issues. Don't use any data from | 969 | * have...hardware issues. Don't use any data from | |
885 | * them unless it passes some tests. | 970 | * them unless it passes some tests. | |
886 | */ | 971 | */ | |
887 | if (source->type == RND_TYPE_RNG) { | 972 | if (source->type == RND_TYPE_RNG) { | |
888 | if (__predict_false(rnd_hwrng_test(sample))) { | 973 | if (__predict_false(rnd_hwrng_test(sample))) { | |
889 | /* | 974 | /* | |
890 | * Detach the bad source. See below. | 975 | * Detach the bad source. See below. | |
891 | */ | 976 | */ | |
892 | badsource = source; | 977 | badsource = source; | |
893 | printf("rnd: detaching source \"%s\".", | 978 | printf("rnd: detaching source \"%s\".", | |
894 | badsource->name); | 979 | badsource->name); | |
895 | break; | 980 | break; | |
@@ -915,72 +1000,75 @@ rnd_process_events(void *arg) | @@ -915,72 +1000,75 @@ rnd_process_events(void *arg) | |||
915 | * point at which we detected a problem onwards. | 1000 | * point at which we detected a problem onwards. | |
916 | */ | 1001 | */ | |
917 | rnd_detach_source(badsource); | 1002 | rnd_detach_source(badsource); | |
918 | while ((sample = SIMPLEQ_FIRST(&dq_samples))) { | 1003 | while ((sample = SIMPLEQ_FIRST(&dq_samples))) { | |
919 | SIMPLEQ_REMOVE_HEAD(&dq_samples, next); | 1004 | SIMPLEQ_REMOVE_HEAD(&dq_samples, next); | |
920 | rnd_sample_free(sample); | 1005 | rnd_sample_free(sample); | |
921 | } | 1006 | } | |
922 | } | 1007 | } | |
923 | while ((sample = SIMPLEQ_FIRST(&df_samples))) { | 1008 | while ((sample = SIMPLEQ_FIRST(&df_samples))) { | |
924 | SIMPLEQ_REMOVE_HEAD(&df_samples, next); | 1009 | SIMPLEQ_REMOVE_HEAD(&df_samples, next); | |
925 | rnd_sample_free(sample); | 1010 | rnd_sample_free(sample); | |
926 | } | 1011 | } | |
927 | 1012 | |||
1013 | ||||
928 | /* | 1014 | /* | |
929 | * Wake up any potential readers waiting. | 1015 | * Wake up any potential readers waiting. | |
930 | */ | 1016 | */ | |
931 | rnd_wakeup_readers(); | 1017 | if (wake) { | |
1018 | rnd_schedule_wakeup(); | |||
1019 | } | |||
932 | } | 1020 | } | |
933 | 1021 | |||
934 | /* | |||
935 | * Timeout, run to process the events in the ring buffer. | |||
936 | */ | |||
937 | static void | 1022 | static void | |
938 | rnd_timeout(void *arg) | 1023 | rnd_intr(void *arg) | |
939 | { | 1024 | { | |
940 | mutex_spin_enter(&rnd_mtx); | 1025 | rnd_process_events(); | |
941 | rnd_timeout_pending = 0; | 1026 | } | |
942 | rnd_process_events(arg); | 1027 | ||
1028 | static void | |||
1029 | rnd_wake(void *arg) | |||
1030 | { | |||
1031 | rnd_wakeup_readers(); | |||
943 | } | 1032 | } | |
944 | 1033 | |||
945 | u_int32_t | 1034 | u_int32_t | |
946 | rnd_extract_data_locked(void *p, u_int32_t len, u_int32_t flags) | 1035 | rnd_extract_data_locked(void *p, u_int32_t len, u_int32_t flags) | |
947 | { | 1036 | { | |
948 | static int timed_in; | 1037 | static int timed_in; | |
1038 | int entropy_count; | |||
949 | 1039 | |||
950 | KASSERT(mutex_owned(&rndpool_mtx)); | 1040 | KASSERT(mutex_owned(&rndpool_mtx)); | |
951 | if (__predict_false(!timed_in)) { | 1041 | if (__predict_false(!timed_in)) { | |
952 | if (boottime.tv_sec) { | 1042 | if (boottime.tv_sec) { | |
953 | rndpool_add_data(&rnd_pool, &boottime, | 1043 | rndpool_add_data(&rnd_pool, &boottime, | |
954 | sizeof(boottime), 0); | 1044 | sizeof(boottime), 0); | |
955 | } | 1045 | } | |
956 | timed_in++; | 1046 | timed_in++; | |
957 | } | 1047 | } | |
958 | if (__predict_false(!rnd_initial_entropy)) { | 1048 | if (__predict_false(!rnd_initial_entropy)) { | |
959 | u_int32_t c; | 1049 | u_int32_t c; | |
960 | 1050 | |||
961 | #ifdef RND_VERBOSE | 1051 | #ifdef RND_VERBOSE | |
962 | printf("rnd: WARNING! initial entropy low (%u).\n", | 1052 | printf("rnd: WARNING! initial entropy low (%u).\n", | |
963 | rndpool_get_entropy_count(&rnd_pool)); | 1053 | rndpool_get_entropy_count(&rnd_pool)); | |
964 | #endif | 1054 | #endif | |
965 | /* Try once again to put something in the pool */ | 1055 | /* Try once again to put something in the pool */ | |
966 | c = rnd_counter(); | 1056 | c = rnd_counter(); | |
967 | rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1); | 1057 | rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1); | |
968 | } | 1058 | } | |
969 | 1059 | |||
970 | #ifdef DIAGNOSTIC | 1060 | #ifdef DIAGNOSTIC | |
971 | while (!rnd_tested) { | 1061 | while (!rnd_tested) { | |
972 | int entropy_count; | |||
973 | ||||
974 | entropy_count = rndpool_get_entropy_count(&rnd_pool); | 1062 | entropy_count = rndpool_get_entropy_count(&rnd_pool); | |
975 | #ifdef RND_VERBOSE | 1063 | #ifdef RND_VERBOSE | |
976 | printf("rnd: starting statistical RNG test, entropy = %d.\n", | 1064 | printf("rnd: starting statistical RNG test, entropy = %d.\n", | |
977 | entropy_count); | 1065 | entropy_count); | |
978 | #endif | 1066 | #endif | |
979 | if (rndpool_extract_data(&rnd_pool, rnd_rt.rt_b, | 1067 | if (rndpool_extract_data(&rnd_pool, rnd_rt.rt_b, | |
980 | sizeof(rnd_rt.rt_b), RND_EXTRACT_ANY) | 1068 | sizeof(rnd_rt.rt_b), RND_EXTRACT_ANY) | |
981 | != sizeof(rnd_rt.rt_b)) { | 1069 | != sizeof(rnd_rt.rt_b)) { | |
982 | panic("rnd: could not get bits for statistical test"); | 1070 | panic("rnd: could not get bits for statistical test"); | |
983 | } | 1071 | } | |
984 | /* | 1072 | /* | |
985 | * Stash the tested bits so we can put them back in the | 1073 | * Stash the tested bits so we can put them back in the | |
986 | * pool, restoring the entropy count. DO NOT rely on | 1074 | * pool, restoring the entropy count. DO NOT rely on | |
@@ -1002,26 +1090,30 @@ rnd_extract_data_locked(void *p, u_int32 | @@ -1002,26 +1090,30 @@ rnd_extract_data_locked(void *p, u_int32 | |||
1002 | continue; | 1090 | continue; | |
1003 | } | 1091 | } | |
1004 | memset(&rnd_rt, 0, sizeof(rnd_rt)); | 1092 | memset(&rnd_rt, 0, sizeof(rnd_rt)); | |
1005 | rndpool_add_data(&rnd_pool, rnd_testbits, sizeof(rnd_testbits), | 1093 | rndpool_add_data(&rnd_pool, rnd_testbits, sizeof(rnd_testbits), | |
1006 | entropy_count); | 1094 | entropy_count); | |
1007 | memset(rnd_testbits, 0, sizeof(rnd_testbits)); | 1095 | memset(rnd_testbits, 0, sizeof(rnd_testbits)); | |
1008 | #ifdef RND_VERBOSE | 1096 | #ifdef RND_VERBOSE | |
1009 | printf("rnd: statistical RNG test done, entropy = %d.\n", | 1097 | printf("rnd: statistical RNG test done, entropy = %d.\n", | |
1010 | rndpool_get_entropy_count(&rnd_pool)); | 1098 | rndpool_get_entropy_count(&rnd_pool)); | |
1011 | #endif | 1099 | #endif | |
1012 | rnd_tested++; | 1100 | rnd_tested++; | |
1013 | } | 1101 | } | |
1014 | #endif | 1102 | #endif | |
1103 | entropy_count = rndpool_get_entropy_count(&rnd_pool); | |||
1104 | if (entropy_count < (RND_ENTROPY_THRESHOLD * 2 + len) * 8) { | |||
1105 | rnd_getmore(RND_POOLBITS - entropy_count * 8); | |||
1106 | } | |||
1015 | return rndpool_extract_data(&rnd_pool, p, len, flags); | 1107 | return rndpool_extract_data(&rnd_pool, p, len, flags); | |
1016 | } | 1108 | } | |
1017 | 1109 | |||
1018 | u_int32_t | 1110 | u_int32_t | |
1019 | rnd_extract_data(void *p, u_int32_t len, u_int32_t flags) | 1111 | rnd_extract_data(void *p, u_int32_t len, u_int32_t flags) | |
1020 | { | 1112 | { | |
1021 | uint32_t retval; | 1113 | uint32_t retval; | |
1022 | 1114 | |||
1023 | mutex_spin_enter(&rndpool_mtx); | 1115 | mutex_spin_enter(&rndpool_mtx); | |
1024 | retval = rnd_extract_data_locked(p, len, flags); | 1116 | retval = rnd_extract_data_locked(p, len, flags); | |
1025 | mutex_spin_exit(&rndpool_mtx); | 1117 | mutex_spin_exit(&rndpool_mtx); | |
1026 | return retval; | 1118 | return retval; | |
1027 | } | 1119 | } | |
@@ -1031,33 +1123,27 @@ rndsink_attach(rndsink_t *rs) | @@ -1031,33 +1123,27 @@ rndsink_attach(rndsink_t *rs) | |||
1031 | { | 1123 | { | |
1032 | #ifdef RND_VERBOSE | 1124 | #ifdef RND_VERBOSE | |
1033 | printf("rnd: entropy sink \"%s\" wants %d bytes of data.\n", | 1125 | printf("rnd: entropy sink \"%s\" wants %d bytes of data.\n", | |
1034 | rs->name, (int)rs->len); | 1126 | rs->name, (int)rs->len); | |
1035 | #endif | 1127 | #endif | |
1036 | 1128 | |||
1037 | KASSERT(mutex_owned(&rs->mtx)); | 1129 | KASSERT(mutex_owned(&rs->mtx)); | |
1038 | KASSERT(rs->state = RSTATE_PENDING); | 1130 | KASSERT(rs->state = RSTATE_PENDING); | |
1039 | 1131 | |||
1040 | mutex_spin_enter(&rndsink_mtx); | 1132 | mutex_spin_enter(&rndsink_mtx); | |
1041 | TAILQ_INSERT_TAIL(&rnd_sinks, rs, tailq); | 1133 | TAILQ_INSERT_TAIL(&rnd_sinks, rs, tailq); | |
1042 | mutex_spin_exit(&rndsink_mtx); | 1134 | mutex_spin_exit(&rndsink_mtx); | |
1043 | 1135 | |||
1044 | mutex_spin_enter(&rnd_mtx); | 1136 | rnd_schedule_process(); | |
1045 | if (rnd_timeout_pending == 0) { | |||
1046 | rnd_timeout_pending = 1; | |||
1047 | callout_schedule(&rnd_callout, 1); | |||
1048 | } | |||
1049 | mutex_spin_exit(&rnd_mtx); | |||
1050 | ||||
1051 | } | 1137 | } | |
1052 | 1138 | |||
1053 | void | 1139 | void | |
1054 | rndsink_detach(rndsink_t *rs) | 1140 | rndsink_detach(rndsink_t *rs) | |
1055 | { | 1141 | { | |
1056 | rndsink_t *sink, *tsink; | 1142 | rndsink_t *sink, *tsink; | |
1057 | #ifdef RND_VERBOSE | 1143 | #ifdef RND_VERBOSE | |
1058 | printf("rnd: entropy sink \"%s\" no longer wants data.\n", rs->name); | 1144 | printf("rnd: entropy sink \"%s\" no longer wants data.\n", rs->name); | |
1059 | #endif | 1145 | #endif | |
1060 | KASSERT(mutex_owned(&rs->mtx)); | 1146 | KASSERT(mutex_owned(&rs->mtx)); | |
1061 | 1147 | |||
1062 | mutex_spin_enter(&rndsink_mtx); | 1148 | mutex_spin_enter(&rndsink_mtx); | |
1063 | TAILQ_FOREACH_SAFE(sink, &rnd_sinks, tailq, tsink) { | 1149 | TAILQ_FOREACH_SAFE(sink, &rnd_sinks, tailq, tsink) { |
--- src/sys/kern/subr_cprng.c 2013/03/28 18:06:48 1.16
+++ src/sys/kern/subr_cprng.c 2013/06/13 00:55:01 1.17
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: subr_cprng.c,v 1.16 2013/03/28 18:06:48 tls Exp $ */ | 1 | /* $NetBSD: subr_cprng.c,v 1.17 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Thor Lancelot Simon. | 8 | * by Thor Lancelot Simon. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -36,27 +36,27 @@ | @@ -36,27 +36,27 @@ | |||
36 | #include <sys/systm.h> | 36 | #include <sys/systm.h> | |
37 | #include <sys/kmem.h> | 37 | #include <sys/kmem.h> | |
38 | #include <sys/mutex.h> | 38 | #include <sys/mutex.h> | |
39 | #include <sys/rngtest.h> | 39 | #include <sys/rngtest.h> | |
40 | #include <sys/rnd.h> | 40 | #include <sys/rnd.h> | |
41 | #include <dev/rnd_private.h> | 41 | #include <dev/rnd_private.h> | |
42 | 42 | |||
43 | #if defined(__HAVE_CPU_COUNTER) | 43 | #if defined(__HAVE_CPU_COUNTER) | |
44 | #include <machine/cpu_counter.h> | 44 | #include <machine/cpu_counter.h> | |
45 | #endif | 45 | #endif | |
46 | 46 | |||
47 | #include <sys/cprng.h> | 47 | #include <sys/cprng.h> | |
48 | 48 | |||
49 | __KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.16 2013/03/28 18:06:48 tls Exp $"); | 49 | __KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.17 2013/06/13 00:55:01 tls Exp $"); | |
50 | 50 | |||
51 | void | 51 | void | |
52 | cprng_init(void) | 52 | cprng_init(void) | |
53 | { | 53 | { | |
54 | nist_ctr_initialize(); | 54 | nist_ctr_initialize(); | |
55 | } | 55 | } | |
56 | 56 | |||
57 | static inline uint32_t | 57 | static inline uint32_t | |
58 | cprng_counter(void) | 58 | cprng_counter(void) | |
59 | { | 59 | { | |
60 | struct timeval tv; | 60 | struct timeval tv; | |
61 | 61 | |||
62 | #if defined(__HAVE_CPU_COUNTER) | 62 | #if defined(__HAVE_CPU_COUNTER) | |
@@ -190,28 +190,37 @@ cprng_strong_create(const char *const na | @@ -190,28 +190,37 @@ cprng_strong_create(const char *const na | |||
190 | 190 | |||
191 | mutex_init(&c->mtx, MUTEX_DEFAULT, ipl); | 191 | mutex_init(&c->mtx, MUTEX_DEFAULT, ipl); | |
192 | 192 | |||
193 | if (c->flags & CPRNG_USE_CV) { | 193 | if (c->flags & CPRNG_USE_CV) { | |
194 | cv_init(&c->cv, (const char *)c->name); | 194 | cv_init(&c->cv, (const char *)c->name); | |
195 | } | 195 | } | |
196 | 196 | |||
197 | selinit(&c->selq); | 197 | selinit(&c->selq); | |
198 | 198 | |||
199 | r = cprng_entropy_try(key, sizeof(key)); | 199 | r = cprng_entropy_try(key, sizeof(key)); | |
200 | if (r != sizeof(key)) { | 200 | if (r != sizeof(key)) { | |
201 | if (c->flags & CPRNG_INIT_ANY) { | 201 | if (c->flags & CPRNG_INIT_ANY) { | |
202 | #ifdef DEBUG | 202 | #ifdef DEBUG | |
203 | printf("cprng %s: WARNING insufficient " | 203 | /* | |
204 | "entropy at creation.\n", name); | 204 | * If we have ever crossed the pool's | |
205 | * minimum-entropy threshold, then we are | |||
206 | * providing cryptographically strong | |||
207 | * random output -- if not information- | |||
208 | * theoretically strong. Warn elsewise. | |||
209 | */ | |||
210 | if (!rnd_initial_entropy) { | |||
211 | printf("cprng %s: WARNING insufficient " | |||
212 | "entropy at creation.\n", name); | |||
213 | } | |||
205 | #endif | 214 | #endif | |
206 | } else { | 215 | } else { | |
207 | hard++; | 216 | hard++; | |
208 | } | 217 | } | |
209 | getmore++; | 218 | getmore++; | |
210 | } | 219 | } | |
211 | 220 | |||
212 | if (nist_ctr_drbg_instantiate(&c->drbg, key, sizeof(key), | 221 | if (nist_ctr_drbg_instantiate(&c->drbg, key, sizeof(key), | |
213 | &cc, sizeof(cc), name, strlen(name))) { | 222 | &cc, sizeof(cc), name, strlen(name))) { | |
214 | panic("cprng %s: instantiation failed.", name); | 223 | panic("cprng %s: instantiation failed.", name); | |
215 | } | 224 | } | |
216 | 225 | |||
217 | if (getmore) { | 226 | if (getmore) { |
--- src/sys/sys/rnd.h 2013/01/26 19:05:11 1.35
+++ src/sys/sys/rnd.h 2013/06/13 00:55:01 1.36
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rnd.h,v 1.35 2013/01/26 19:05:11 tls Exp $ */ | 1 | /* $NetBSD: rnd.h,v 1.36 2013/06/13 00:55:01 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Michael Graff <explorer@flame.org>. This code uses ideas and | 8 | * by Michael Graff <explorer@flame.org>. This code uses ideas and | |
9 | * algorithms from the Linux driver written by Ted Ts'o. | 9 | * algorithms from the Linux driver written by Ted Ts'o. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -82,26 +82,27 @@ typedef struct | @@ -82,26 +82,27 @@ typedef struct | |||
82 | typedef struct { | 82 | typedef struct { | |
83 | char name[16]; /* device name */ | 83 | char name[16]; /* device name */ | |
84 | uint32_t total; /* entropy from this source */ | 84 | uint32_t total; /* entropy from this source */ | |
85 | uint32_t type; /* type */ | 85 | uint32_t type; /* type */ | |
86 | uint32_t flags; /* flags */ | 86 | uint32_t flags; /* flags */ | |
87 | } rndsource_t; | 87 | } rndsource_t; | |
88 | 88 | |||
89 | /* | 89 | /* | |
90 | * Flags to control the source. Low byte is type, upper bits are flags. | 90 | * Flags to control the source. Low byte is type, upper bits are flags. | |
91 | */ | 91 | */ | |
92 | #define RND_FLAG_NO_ESTIMATE 0x00000100 /* don't estimate entropy */ | 92 | #define RND_FLAG_NO_ESTIMATE 0x00000100 /* don't estimate entropy */ | |
93 | #define RND_FLAG_NO_COLLECT 0x00000200 /* don't collect entropy */ | 93 | #define RND_FLAG_NO_COLLECT 0x00000200 /* don't collect entropy */ | |
94 | #define RND_FLAG_FAST 0x00000400 /* process samples in bulk */ | 94 | #define RND_FLAG_FAST 0x00000400 /* process samples in bulk */ | |
95 | #define RND_FLAG_HASCB 0x00000800 /* has get callback */ | |||
95 | 96 | |||
96 | #define RND_TYPE_UNKNOWN 0 /* unknown source */ | 97 | #define RND_TYPE_UNKNOWN 0 /* unknown source */ | |
97 | #define RND_TYPE_DISK 1 /* source is physical disk */ | 98 | #define RND_TYPE_DISK 1 /* source is physical disk */ | |
98 | #define RND_TYPE_NET 2 /* source is a network device */ | 99 | #define RND_TYPE_NET 2 /* source is a network device */ | |
99 | #define RND_TYPE_TAPE 3 /* source is a tape drive */ | 100 | #define RND_TYPE_TAPE 3 /* source is a tape drive */ | |
100 | #define RND_TYPE_TTY 4 /* source is a tty device */ | 101 | #define RND_TYPE_TTY 4 /* source is a tty device */ | |
101 | #define RND_TYPE_RNG 5 /* source is a hardware RNG */ | 102 | #define RND_TYPE_RNG 5 /* source is a hardware RNG */ | |
102 | #define RND_TYPE_SKEW 6 /* source is skew between clocks */ | 103 | #define RND_TYPE_SKEW 6 /* source is skew between clocks */ | |
103 | #define RND_TYPE_ENV 7 /* source is temp or fan sensor */ | 104 | #define RND_TYPE_ENV 7 /* source is temp or fan sensor */ | |
104 | #define RND_TYPE_VM 8 /* source is VM system events */ | 105 | #define RND_TYPE_VM 8 /* source is VM system events */ | |
105 | #define RND_TYPE_POWER 9 /* source is power events */ | 106 | #define RND_TYPE_POWER 9 /* source is power events */ | |
106 | #define RND_TYPE_MAX 9 /* last type id used */ | 107 | #define RND_TYPE_MAX 9 /* last type id used */ | |
107 | 108 | |||
@@ -117,28 +118,37 @@ typedef struct { | @@ -117,28 +118,37 @@ typedef struct { | |||
117 | 118 | |||
118 | typedef struct krndsource { | 119 | typedef struct krndsource { | |
119 | LIST_ENTRY(krndsource) list; /* the linked list */ | 120 | LIST_ENTRY(krndsource) list; /* the linked list */ | |
120 | char name[16]; /* device name */ | 121 | char name[16]; /* device name */ | |
121 | uint32_t last_time; /* last time recorded */ | 122 | uint32_t last_time; /* last time recorded */ | |
122 | uint32_t last_delta; /* last delta value */ | 123 | uint32_t last_delta; /* last delta value */ | |
123 | uint32_t last_delta2; /* last delta2 value */ | 124 | uint32_t last_delta2; /* last delta2 value */ | |
124 | uint32_t total; /* entropy from this source */ | 125 | uint32_t total; /* entropy from this source */ | |
125 | uint32_t type; /* type */ | 126 | uint32_t type; /* type */ | |
126 | uint32_t flags; /* flags */ | 127 | uint32_t flags; /* flags */ | |
127 | void *state; /* state information */ | 128 | void *state; /* state information */ | |
128 | size_t test_cnt; /* how much test data accumulated? */ | 129 | size_t test_cnt; /* how much test data accumulated? */ | |
129 | rngtest_t *test; /* test data for RNG type sources */ | 130 | rngtest_t *test; /* test data for RNG type sources */ | |
131 | void (*get)(size_t, void *); /* pool wants N bytes (badly) */ | |||
132 | void *getarg; /* argument to get-function */ | |||
130 | } krndsource_t; | 133 | } krndsource_t; | |
131 | 134 | |||
135 | static inline void | |||
136 | rndsource_setcb(struct krndsource *const rs, void *const cb, void *const arg) | |||
137 | { | |||
138 | rs->get = cb; | |||
139 | rs->getarg = arg; | |||
140 | } | |||
141 | ||||
132 | enum rsink_st { | 142 | enum rsink_st { | |
133 | RSTATE_IDLE = 0, | 143 | RSTATE_IDLE = 0, | |
134 | RSTATE_PENDING, | 144 | RSTATE_PENDING, | |
135 | RSTATE_HASBITS | 145 | RSTATE_HASBITS | |
136 | }; | 146 | }; | |
137 | 147 | |||
138 | typedef struct rndsink { | 148 | typedef struct rndsink { | |
139 | TAILQ_ENTRY(rndsink) tailq; /* the queue */ | 149 | TAILQ_ENTRY(rndsink) tailq; /* the queue */ | |
140 | kmutex_t mtx; /* lock to seed or unregister */ | 150 | kmutex_t mtx; /* lock to seed or unregister */ | |
141 | enum rsink_st state; /* in-use? filled? */ | 151 | enum rsink_st state; /* in-use? filled? */ | |
142 | void (*cb)(void *); /* callback function when ready */ | 152 | void (*cb)(void *); /* callback function when ready */ | |
143 | void *arg; /* callback function argument */ | 153 | void *arg; /* callback function argument */ | |
144 | char name[16]; /* sink name */ | 154 | char name[16]; /* sink name */ | |
@@ -176,26 +186,27 @@ void rnd_detach_source(krndsource_t *); | @@ -176,26 +186,27 @@ void rnd_detach_source(krndsource_t *); | |||
176 | void rndsink_attach(rndsink_t *); | 186 | void rndsink_attach(rndsink_t *); | |
177 | void rndsink_detach(rndsink_t *); | 187 | void rndsink_detach(rndsink_t *); | |
178 | 188 | |||
179 | void rnd_seed(void *, size_t); | 189 | void rnd_seed(void *, size_t); | |
180 | 190 | |||
181 | static inline void | 191 | static inline void | |
182 | rnd_add_uint32(krndsource_t *kr, uint32_t val) | 192 | rnd_add_uint32(krndsource_t *kr, uint32_t val) | |
183 | { | 193 | { | |
184 | if (RND_ENABLED(kr)) { | 194 | if (RND_ENABLED(kr)) { | |
185 | _rnd_add_uint32(kr, val); | 195 | _rnd_add_uint32(kr, val); | |
186 | } | 196 | } | |
187 | } | 197 | } | |
188 | 198 | |||
199 | extern int rnd_empty; | |||
189 | extern int rnd_full; | 200 | extern int rnd_full; | |
190 | extern int rnd_filled; | 201 | extern int rnd_filled; | |
191 | extern int rnd_initial_entropy; | 202 | extern int rnd_initial_entropy; | |
192 | 203 | |||
193 | #endif /* _KERNEL */ | 204 | #endif /* _KERNEL */ | |
194 | 205 | |||
195 | #define RND_MAXSTATCOUNT 10 /* 10 sources at once max */ | 206 | #define RND_MAXSTATCOUNT 10 /* 10 sources at once max */ | |
196 | 207 | |||
197 | /* | 208 | /* | |
198 | * return "count" random entries, starting at "start" | 209 | * return "count" random entries, starting at "start" | |
199 | */ | 210 | */ | |
200 | typedef struct { | 211 | typedef struct { | |
201 | uint32_t start; | 212 | uint32_t start; |