xref: /qemu/hw/misc/imx_rngc.c (revision abff1abf)
1 /*
2  * Freescale i.MX RNGC emulation
3  *
4  * Copyright (C) 2020 Martin Kaiser <martin@kaiser.cx>
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7  * See the COPYING file in the top-level directory.
8  *
9  * This driver provides the minimum functionality to initialize and seed
10  * an rngc and to read random numbers. The rngb that is found in imx25
11  * chipsets is also supported.
12  */
13 
14 #include "qemu/osdep.h"
15 #include "qemu/main-loop.h"
16 #include "qemu/module.h"
17 #include "qemu/log.h"
18 #include "qemu/guest-random.h"
19 #include "hw/irq.h"
20 #include "hw/misc/imx_rngc.h"
21 #include "migration/vmstate.h"
22 
23 #define RNGC_NAME "i.MX RNGC"
24 
25 #define RNGC_VER_ID  0x00
26 #define RNGC_COMMAND 0x04
27 #define RNGC_CONTROL 0x08
28 #define RNGC_STATUS  0x0C
29 #define RNGC_FIFO    0x14
30 
31 /* These version info are reported by the rngb in an imx258 chip. */
32 #define RNG_TYPE_RNGB 0x1
33 #define V_MAJ 0x2
34 #define V_MIN 0x40
35 
36 #define RNGC_CMD_BIT_SW_RST    0x40
37 #define RNGC_CMD_BIT_CLR_ERR   0x20
38 #define RNGC_CMD_BIT_CLR_INT   0x10
39 #define RNGC_CMD_BIT_SEED      0x02
40 #define RNGC_CMD_BIT_SELF_TEST 0x01
41 
42 #define RNGC_CTRL_BIT_MASK_ERR  0x40
43 #define RNGC_CTRL_BIT_MASK_DONE 0x20
44 #define RNGC_CTRL_BIT_AUTO_SEED 0x10
45 
46 /* the current status for self-test and seed operations */
47 #define OP_IDLE 0
48 #define OP_RUN  1
49 #define OP_DONE 2
50 
51 static uint64_t imx_rngc_read(void *opaque, hwaddr offset, unsigned size)
52 {
53     IMXRNGCState *s = IMX_RNGC(opaque);
54     uint64_t val = 0;
55 
56     switch (offset) {
57     case RNGC_VER_ID:
58         val |= RNG_TYPE_RNGB << 28 | V_MAJ << 8 | V_MIN;
59         break;
60 
61     case RNGC_COMMAND:
62         if (s->op_seed == OP_RUN) {
63             val |= RNGC_CMD_BIT_SEED;
64         }
65         if (s->op_self_test == OP_RUN) {
66             val |= RNGC_CMD_BIT_SELF_TEST;
67         }
68         break;
69 
70     case RNGC_CONTROL:
71         /*
72          * The CTL_ACC and VERIF_MODE bits are not supported yet.
73          * They read as 0.
74          */
75         val |= s->mask;
76         if (s->auto_seed) {
77             val |= RNGC_CTRL_BIT_AUTO_SEED;
78         }
79         /*
80          * We don't have an internal fifo like the real hardware.
81          * There's no need for strategy to handle fifo underflows.
82          * We return the FIFO_UFLOW_RESPONSE bits as 0.
83          */
84         break;
85 
86     case RNGC_STATUS:
87         /*
88          * We never report any statistics test or self-test errors or any
89          * other errors. STAT_TEST_PF, ST_PF and ERROR are always 0.
90          */
91 
92         /*
93          * We don't have an internal fifo, see above. Therefore, we
94          * report back the default fifo size (5 32-bit words) and
95          * indicate that our fifo is always full.
96          */
97         val |= 5 << 12 | 5 << 8;
98 
99         /* We always have a new seed available. */
100         val |= 1 << 6;
101 
102         if (s->op_seed == OP_DONE) {
103             val |= 1 << 5;
104         }
105         if (s->op_self_test == OP_DONE) {
106             val |= 1 << 4;
107         }
108         if (s->op_seed == OP_RUN || s->op_self_test == OP_RUN) {
109             /*
110              * We're busy if self-test is running or if we're
111              * seeding the prng.
112              */
113             val |= 1 << 1;
114         } else {
115             /*
116              * We're ready to provide secure random numbers whenever
117              * we're not busy.
118              */
119             val |= 1;
120         }
121         break;
122 
123     case RNGC_FIFO:
124         qemu_guest_getrandom_nofail(&val, sizeof(val));
125         break;
126     }
127 
128     return val;
129 }
130 
131 static void imx_rngc_do_reset(IMXRNGCState *s)
132 {
133     s->op_self_test = OP_IDLE;
134     s->op_seed = OP_IDLE;
135     s->mask = 0;
136     s->auto_seed = false;
137 }
138 
139 static void imx_rngc_write(void *opaque, hwaddr offset, uint64_t value,
140                            unsigned size)
141 {
142     IMXRNGCState *s = IMX_RNGC(opaque);
143 
144     switch (offset) {
145     case RNGC_COMMAND:
146         if (value & RNGC_CMD_BIT_SW_RST) {
147             imx_rngc_do_reset(s);
148         }
149 
150         /*
151          * For now, both CLR_ERR and CLR_INT clear the interrupt. We
152          * don't report any errors yet.
153          */
154         if (value & (RNGC_CMD_BIT_CLR_ERR | RNGC_CMD_BIT_CLR_INT)) {
155             qemu_irq_lower(s->irq);
156         }
157 
158         if (value & RNGC_CMD_BIT_SEED) {
159             s->op_seed = OP_RUN;
160             qemu_bh_schedule(s->seed_bh);
161         }
162 
163         if (value & RNGC_CMD_BIT_SELF_TEST) {
164             s->op_self_test = OP_RUN;
165             qemu_bh_schedule(s->self_test_bh);
166         }
167         break;
168 
169     case RNGC_CONTROL:
170         /*
171          * The CTL_ACC and VERIF_MODE bits are not supported yet.
172          * We ignore them if they're set by the caller.
173          */
174 
175         if (value & RNGC_CTRL_BIT_MASK_ERR) {
176             s->mask |= RNGC_CTRL_BIT_MASK_ERR;
177         } else {
178             s->mask &= ~RNGC_CTRL_BIT_MASK_ERR;
179         }
180 
181         if (value & RNGC_CTRL_BIT_MASK_DONE) {
182             s->mask |= RNGC_CTRL_BIT_MASK_DONE;
183         } else {
184             s->mask &= ~RNGC_CTRL_BIT_MASK_DONE;
185         }
186 
187         if (value & RNGC_CTRL_BIT_AUTO_SEED) {
188             s->auto_seed = true;
189         } else {
190             s->auto_seed = false;
191         }
192         break;
193     }
194 }
195 
196 static const MemoryRegionOps imx_rngc_ops = {
197     .read  = imx_rngc_read,
198     .write = imx_rngc_write,
199     .endianness = DEVICE_NATIVE_ENDIAN,
200 };
201 
202 static void imx_rngc_self_test(void *opaque)
203 {
204     IMXRNGCState *s = IMX_RNGC(opaque);
205 
206     s->op_self_test = OP_DONE;
207     if (!(s->mask & RNGC_CTRL_BIT_MASK_DONE)) {
208         qemu_irq_raise(s->irq);
209     }
210 }
211 
212 static void imx_rngc_seed(void *opaque)
213 {
214     IMXRNGCState *s = IMX_RNGC(opaque);
215 
216     s->op_seed = OP_DONE;
217     if (!(s->mask & RNGC_CTRL_BIT_MASK_DONE)) {
218         qemu_irq_raise(s->irq);
219     }
220 }
221 
222 static void imx_rngc_realize(DeviceState *dev, Error **errp)
223 {
224     IMXRNGCState *s = IMX_RNGC(dev);
225     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
226 
227     memory_region_init_io(&s->iomem, OBJECT(s), &imx_rngc_ops, s,
228                           TYPE_IMX_RNGC, 0x1000);
229     sysbus_init_mmio(sbd, &s->iomem);
230 
231     sysbus_init_irq(sbd, &s->irq);
232     s->self_test_bh = qemu_bh_new(imx_rngc_self_test, s);
233     s->seed_bh = qemu_bh_new(imx_rngc_seed, s);
234 }
235 
236 static void imx_rngc_reset(DeviceState *dev)
237 {
238     IMXRNGCState *s = IMX_RNGC(dev);
239 
240     imx_rngc_do_reset(s);
241 }
242 
243 static const VMStateDescription vmstate_imx_rngc = {
244     .name = RNGC_NAME,
245     .version_id = 1,
246     .minimum_version_id = 1,
247     .fields = (VMStateField[]) {
248         VMSTATE_UINT8(op_self_test, IMXRNGCState),
249         VMSTATE_UINT8(op_seed, IMXRNGCState),
250         VMSTATE_UINT8(mask, IMXRNGCState),
251         VMSTATE_BOOL(auto_seed, IMXRNGCState),
252         VMSTATE_END_OF_LIST()
253     }
254 };
255 
256 static void imx_rngc_class_init(ObjectClass *klass, void *data)
257 {
258     DeviceClass *dc = DEVICE_CLASS(klass);
259 
260     dc->realize = imx_rngc_realize;
261     dc->reset = imx_rngc_reset;
262     dc->desc = RNGC_NAME,
263     dc->vmsd = &vmstate_imx_rngc;
264 }
265 
266 static const TypeInfo imx_rngc_info = {
267     .name          = TYPE_IMX_RNGC,
268     .parent        = TYPE_SYS_BUS_DEVICE,
269     .instance_size = sizeof(IMXRNGCState),
270     .class_init    = imx_rngc_class_init,
271 };
272 
273 static void imx_rngc_register_types(void)
274 {
275     type_register_static(&imx_rngc_info);
276 }
277 
278 type_init(imx_rngc_register_types)
279