qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

i.MX: add an emulation for RNGC

Add an emulation for the RNGC random number generator and the compatible
RNGB variant. These peripherals are included (at least) in imx25 and
imx35 chipsets.

The emulation supports the initial self test, reseeding the prng and
reading random numbers.

Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Martin Kaiser and committed by
Peter Maydell
f0396549 21bf9b06

+330
+11
hw/arm/fsl-imx25.c
··· 62 62 63 63 sysbus_init_child_obj(obj, "fec", &s->fec, sizeof(s->fec), TYPE_IMX_FEC); 64 64 65 + sysbus_init_child_obj(obj, "rngc", &s->rngc, sizeof(s->rngc), 66 + TYPE_IMX_RNGC); 67 + 65 68 for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) { 66 69 sysbus_init_child_obj(obj, "i2c[*]", &s->i2c[i], sizeof(s->i2c[i]), 67 70 TYPE_IMX_I2C); ··· 188 191 sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0, 189 192 qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_FEC_IRQ)); 190 193 194 + object_property_set_bool(OBJECT(&s->rngc), true, "realized", &err); 195 + if (err) { 196 + error_propagate(errp, err); 197 + return; 198 + } 199 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->rngc), 0, FSL_IMX25_RNGC_ADDR); 200 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->rngc), 0, 201 + qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_RNGC_IRQ)); 191 202 192 203 /* Initialize all I2C */ 193 204 for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
+1
hw/misc/Makefile.objs
··· 42 42 common-obj-$(CONFIG_IMX) += imx2_wdt.o 43 43 common-obj-$(CONFIG_IMX) += imx7_snvs.o 44 44 common-obj-$(CONFIG_IMX) += imx7_gpr.o 45 + common-obj-$(CONFIG_IMX) += imx_rngc.o 45 46 common-obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o 46 47 common-obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o 47 48 common-obj-$(CONFIG_MAINSTONE) += mst_fpga.o
+278
hw/misc/imx_rngc.c
··· 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)
+5
include/hw/arm/fsl-imx25.h
··· 24 24 #include "hw/timer/imx_gpt.h" 25 25 #include "hw/timer/imx_epit.h" 26 26 #include "hw/net/imx_fec.h" 27 + #include "hw/misc/imx_rngc.h" 27 28 #include "hw/i2c/imx_i2c.h" 28 29 #include "hw/gpio/imx_gpio.h" 29 30 #include "exec/memory.h" ··· 50 51 IMXGPTState gpt[FSL_IMX25_NUM_GPTS]; 51 52 IMXEPITState epit[FSL_IMX25_NUM_EPITS]; 52 53 IMXFECState fec; 54 + IMXRNGCState rngc; 53 55 IMXI2CState i2c[FSL_IMX25_NUM_I2CS]; 54 56 IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS]; 55 57 MemoryRegion rom[2]; ··· 211 213 #define FSL_IMX25_GPIO4_SIZE 0x4000 212 214 #define FSL_IMX25_GPIO3_ADDR 0x53FA4000 213 215 #define FSL_IMX25_GPIO3_SIZE 0x4000 216 + #define FSL_IMX25_RNGC_ADDR 0x53FB0000 217 + #define FSL_IMX25_RNGC_SIZE 0x4000 214 218 #define FSL_IMX25_GPIO1_ADDR 0x53FCC000 215 219 #define FSL_IMX25_GPIO1_SIZE 0x4000 216 220 #define FSL_IMX25_GPIO2_ADDR 0x53FD0000 ··· 238 242 #define FSL_IMX25_EPIT1_IRQ 28 239 243 #define FSL_IMX25_EPIT2_IRQ 27 240 244 #define FSL_IMX25_FEC_IRQ 57 245 + #define FSL_IMX25_RNGC_IRQ 22 241 246 #define FSL_IMX25_I2C1_IRQ 3 242 247 #define FSL_IMX25_I2C2_IRQ 4 243 248 #define FSL_IMX25_I2C3_IRQ 10
+35
include/hw/misc/imx_rngc.h
··· 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 + 10 + #ifndef IMX_RNGC_H 11 + #define IMX_RNGC_H 12 + 13 + #include "hw/sysbus.h" 14 + 15 + #define TYPE_IMX_RNGC "imx.rngc" 16 + #define IMX_RNGC(obj) OBJECT_CHECK(IMXRNGCState, (obj), TYPE_IMX_RNGC) 17 + 18 + typedef struct IMXRNGCState { 19 + /*< private >*/ 20 + SysBusDevice parent_obj; 21 + 22 + /*< public >*/ 23 + MemoryRegion iomem; 24 + 25 + uint8_t op_self_test; 26 + uint8_t op_seed; 27 + uint8_t mask; 28 + bool auto_seed; 29 + 30 + QEMUBH *self_test_bh; 31 + QEMUBH *seed_bh; 32 + qemu_irq irq; 33 + } IMXRNGCState; 34 + 35 + #endif /* IMX_RNGC_H */