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

raspi: add BCM2835 SOC MPHI emulation

Add BCM2835 SOC MPHI (Message-based Parallel Host Interface)
emulation. It is very basic, only providing the FIQ interrupt
needed to allow the dwc-otg USB host controller driver in the
Raspbian kernel to function.

Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
Acked-by: Philippe Mathieu-Daude <f4bug@amsat.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20200520235349.21215-2-pauldzim@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Paul Zimmerman and committed by
Peter Maydell
3d46938b 7a1e049a

+255
+17
hw/arm/bcm2835_peripherals.c
··· 125 125 OBJECT(&s->sdhci.sdbus)); 126 126 object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost", 127 127 OBJECT(&s->sdhost.sdbus)); 128 + 129 + /* Mphi */ 130 + sysbus_init_child_obj(obj, "mphi", &s->mphi, sizeof(s->mphi), 131 + TYPE_BCM2835_MPHI); 128 132 } 129 133 130 134 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) ··· 359 363 sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); 360 364 361 365 object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus"); 366 + 367 + /* Mphi */ 368 + object_property_set_bool(OBJECT(&s->mphi), true, "realized", &err); 369 + if (err) { 370 + error_propagate(errp, err); 371 + return; 372 + } 373 + 374 + memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET, 375 + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mphi), 0)); 376 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->mphi), 0, 377 + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, 378 + INTERRUPT_HOSTPORT)); 362 379 363 380 create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40); 364 381 create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
+1
hw/misc/Makefile.objs
··· 56 56 common-obj-$(CONFIG_OMAP) += omap_sdrc.o 57 57 common-obj-$(CONFIG_OMAP) += omap_tap.o 58 58 common-obj-$(CONFIG_RASPI) += bcm2835_mbox.o 59 + common-obj-$(CONFIG_RASPI) += bcm2835_mphi.o 59 60 common-obj-$(CONFIG_RASPI) += bcm2835_property.o 60 61 common-obj-$(CONFIG_RASPI) += bcm2835_rng.o 61 62 common-obj-$(CONFIG_RASPI) += bcm2835_thermal.o
+191
hw/misc/bcm2835_mphi.c
··· 1 + /* 2 + * BCM2835 SOC MPHI emulation 3 + * 4 + * Very basic emulation, only providing the FIQ interrupt needed to 5 + * allow the dwc-otg USB host controller driver in the Raspbian kernel 6 + * to function. 7 + * 8 + * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + */ 20 + 21 + #include "qemu/osdep.h" 22 + #include "qapi/error.h" 23 + #include "hw/misc/bcm2835_mphi.h" 24 + #include "migration/vmstate.h" 25 + #include "qemu/error-report.h" 26 + #include "qemu/log.h" 27 + #include "qemu/main-loop.h" 28 + 29 + static inline void mphi_raise_irq(BCM2835MphiState *s) 30 + { 31 + qemu_set_irq(s->irq, 1); 32 + } 33 + 34 + static inline void mphi_lower_irq(BCM2835MphiState *s) 35 + { 36 + qemu_set_irq(s->irq, 0); 37 + } 38 + 39 + static uint64_t mphi_reg_read(void *ptr, hwaddr addr, unsigned size) 40 + { 41 + BCM2835MphiState *s = ptr; 42 + uint32_t val = 0; 43 + 44 + switch (addr) { 45 + case 0x28: /* outdda */ 46 + val = s->outdda; 47 + break; 48 + case 0x2c: /* outddb */ 49 + val = s->outddb; 50 + break; 51 + case 0x4c: /* ctrl */ 52 + val = s->ctrl; 53 + val |= 1 << 17; 54 + break; 55 + case 0x50: /* intstat */ 56 + val = s->intstat; 57 + break; 58 + case 0x1f0: /* swirq_set */ 59 + val = s->swirq; 60 + break; 61 + case 0x1f4: /* swirq_clr */ 62 + val = s->swirq; 63 + break; 64 + default: 65 + qemu_log_mask(LOG_UNIMP, "read from unknown register"); 66 + break; 67 + } 68 + 69 + return val; 70 + } 71 + 72 + static void mphi_reg_write(void *ptr, hwaddr addr, uint64_t val, unsigned size) 73 + { 74 + BCM2835MphiState *s = ptr; 75 + int do_irq = 0; 76 + 77 + switch (addr) { 78 + case 0x28: /* outdda */ 79 + s->outdda = val; 80 + break; 81 + case 0x2c: /* outddb */ 82 + s->outddb = val; 83 + if (val & (1 << 29)) { 84 + do_irq = 1; 85 + } 86 + break; 87 + case 0x4c: /* ctrl */ 88 + s->ctrl = val; 89 + if (val & (1 << 16)) { 90 + do_irq = -1; 91 + } 92 + break; 93 + case 0x50: /* intstat */ 94 + s->intstat = val; 95 + if (val & ((1 << 16) | (1 << 29))) { 96 + do_irq = -1; 97 + } 98 + break; 99 + case 0x1f0: /* swirq_set */ 100 + s->swirq |= val; 101 + do_irq = 1; 102 + break; 103 + case 0x1f4: /* swirq_clr */ 104 + s->swirq &= ~val; 105 + do_irq = -1; 106 + break; 107 + default: 108 + qemu_log_mask(LOG_UNIMP, "write to unknown register"); 109 + return; 110 + } 111 + 112 + if (do_irq > 0) { 113 + mphi_raise_irq(s); 114 + } else if (do_irq < 0) { 115 + mphi_lower_irq(s); 116 + } 117 + } 118 + 119 + static const MemoryRegionOps mphi_mmio_ops = { 120 + .read = mphi_reg_read, 121 + .write = mphi_reg_write, 122 + .impl.min_access_size = 4, 123 + .impl.max_access_size = 4, 124 + .endianness = DEVICE_LITTLE_ENDIAN, 125 + }; 126 + 127 + static void mphi_reset(DeviceState *dev) 128 + { 129 + BCM2835MphiState *s = BCM2835_MPHI(dev); 130 + 131 + s->outdda = 0; 132 + s->outddb = 0; 133 + s->ctrl = 0; 134 + s->intstat = 0; 135 + s->swirq = 0; 136 + } 137 + 138 + static void mphi_realize(DeviceState *dev, Error **errp) 139 + { 140 + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 141 + BCM2835MphiState *s = BCM2835_MPHI(dev); 142 + 143 + sysbus_init_irq(sbd, &s->irq); 144 + } 145 + 146 + static void mphi_init(Object *obj) 147 + { 148 + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 149 + BCM2835MphiState *s = BCM2835_MPHI(obj); 150 + 151 + memory_region_init_io(&s->iomem, obj, &mphi_mmio_ops, s, "mphi", MPHI_MMIO_SIZE); 152 + sysbus_init_mmio(sbd, &s->iomem); 153 + } 154 + 155 + const VMStateDescription vmstate_mphi_state = { 156 + .name = "mphi", 157 + .version_id = 1, 158 + .minimum_version_id = 1, 159 + .fields = (VMStateField[]) { 160 + VMSTATE_UINT32(outdda, BCM2835MphiState), 161 + VMSTATE_UINT32(outddb, BCM2835MphiState), 162 + VMSTATE_UINT32(ctrl, BCM2835MphiState), 163 + VMSTATE_UINT32(intstat, BCM2835MphiState), 164 + VMSTATE_UINT32(swirq, BCM2835MphiState), 165 + VMSTATE_END_OF_LIST() 166 + } 167 + }; 168 + 169 + static void mphi_class_init(ObjectClass *klass, void *data) 170 + { 171 + DeviceClass *dc = DEVICE_CLASS(klass); 172 + 173 + dc->realize = mphi_realize; 174 + dc->reset = mphi_reset; 175 + dc->vmsd = &vmstate_mphi_state; 176 + } 177 + 178 + static const TypeInfo bcm2835_mphi_type_info = { 179 + .name = TYPE_BCM2835_MPHI, 180 + .parent = TYPE_SYS_BUS_DEVICE, 181 + .instance_size = sizeof(BCM2835MphiState), 182 + .instance_init = mphi_init, 183 + .class_init = mphi_class_init, 184 + }; 185 + 186 + static void bcm2835_mphi_register_types(void) 187 + { 188 + type_register_static(&bcm2835_mphi_type_info); 189 + } 190 + 191 + type_init(bcm2835_mphi_register_types)
+2
include/hw/arm/bcm2835_peripherals.h
··· 21 21 #include "hw/misc/bcm2835_property.h" 22 22 #include "hw/misc/bcm2835_rng.h" 23 23 #include "hw/misc/bcm2835_mbox.h" 24 + #include "hw/misc/bcm2835_mphi.h" 24 25 #include "hw/misc/bcm2835_thermal.h" 25 26 #include "hw/sd/sdhci.h" 26 27 #include "hw/sd/bcm2835_sdhost.h" ··· 42 43 qemu_irq irq, fiq; 43 44 44 45 BCM2835SystemTimerState systmr; 46 + BCM2835MphiState mphi; 45 47 UnimplementedDeviceState armtmr; 46 48 UnimplementedDeviceState cprman; 47 49 UnimplementedDeviceState a2w;
+44
include/hw/misc/bcm2835_mphi.h
··· 1 + /* 2 + * BCM2835 SOC MPHI state definitions 3 + * 4 + * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + 17 + #ifndef HW_MISC_BCM2835_MPHI_H 18 + #define HW_MISC_BCM2835_MPHI_H 19 + 20 + #include "hw/irq.h" 21 + #include "hw/sysbus.h" 22 + 23 + #define MPHI_MMIO_SIZE 0x1000 24 + 25 + typedef struct BCM2835MphiState BCM2835MphiState; 26 + 27 + struct BCM2835MphiState { 28 + SysBusDevice parent_obj; 29 + qemu_irq irq; 30 + MemoryRegion iomem; 31 + 32 + uint32_t outdda; 33 + uint32_t outddb; 34 + uint32_t ctrl; 35 + uint32_t intstat; 36 + uint32_t swirq; 37 + }; 38 + 39 + #define TYPE_BCM2835_MPHI "bcm2835-mphi" 40 + 41 + #define BCM2835_MPHI(obj) \ 42 + OBJECT_CHECK(BCM2835MphiState, (obj), TYPE_BCM2835_MPHI) 43 + 44 + #endif