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

leon3: introduce the plug and play mechanism

This adds the AHB and APB plug and play devices.
They are scanned during the linux boot to discover the various peripheral.

Reviewed-by: Fabien Chouteau <chouteau@adacore.com>
Signed-off-by: KONRAD Frederic <frederic.konrad@adacore.com>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>

authored by

KONRAD Frederic and committed by
Mark Cave-Ayland
162abf1a dbed0d2d

+362 -1
+1 -1
MAINTAINERS
··· 1161 1161 S: Maintained 1162 1162 F: hw/sparc/leon3.c 1163 1163 F: hw/*/grlib* 1164 - F: include/hw/sparc/grlib.h 1164 + F: include/hw/*/grlib* 1165 1165 1166 1166 S390 Machines 1167 1167 -------------
+2
hw/misc/Makefile.objs
··· 77 77 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o 78 78 obj-$(CONFIG_MSF2) += msf2-sysreg.o 79 79 obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o 80 + 81 + obj-$(CONFIG_GRLIB) += grlib_ahb_apb_pnp.o
+269
hw/misc/grlib_ahb_apb_pnp.c
··· 1 + /* 2 + * GRLIB AHB APB PNP 3 + * 4 + * Copyright (C) 2019 AdaCore 5 + * 6 + * Developed by : 7 + * Frederic Konrad <frederic.konrad@adacore.com> 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation, either version 2 of the License, or 12 + * (at your option) any later version. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License along 20 + * with this program; if not, see <http://www.gnu.org/licenses/>. 21 + * 22 + */ 23 + 24 + #include "qemu/osdep.h" 25 + #include "hw/sysbus.h" 26 + #include "hw/misc/grlib_ahb_apb_pnp.h" 27 + 28 + #define GRLIB_PNP_VENDOR_SHIFT (24) 29 + #define GRLIB_PNP_VENDOR_SIZE (8) 30 + #define GRLIB_PNP_DEV_SHIFT (12) 31 + #define GRLIB_PNP_DEV_SIZE (12) 32 + #define GRLIB_PNP_VER_SHIFT (5) 33 + #define GRLIB_PNP_VER_SIZE (5) 34 + #define GRLIB_PNP_IRQ_SHIFT (0) 35 + #define GRLIB_PNP_IRQ_SIZE (5) 36 + #define GRLIB_PNP_ADDR_SHIFT (20) 37 + #define GRLIB_PNP_ADDR_SIZE (12) 38 + #define GRLIB_PNP_MASK_SHIFT (4) 39 + #define GRLIB_PNP_MASK_SIZE (12) 40 + 41 + #define GRLIB_AHB_DEV_ADDR_SHIFT (20) 42 + #define GRLIB_AHB_DEV_ADDR_SIZE (12) 43 + #define GRLIB_AHB_ENTRY_SIZE (0x20) 44 + #define GRLIB_AHB_MAX_DEV (64) 45 + #define GRLIB_AHB_SLAVE_OFFSET (0x800) 46 + 47 + #define GRLIB_APB_DEV_ADDR_SHIFT (8) 48 + #define GRLIB_APB_DEV_ADDR_SIZE (12) 49 + #define GRLIB_APB_ENTRY_SIZE (0x08) 50 + #define GRLIB_APB_MAX_DEV (512) 51 + 52 + #define GRLIB_PNP_MAX_REGS (0x1000) 53 + 54 + typedef struct AHBPnp { 55 + SysBusDevice parent_obj; 56 + MemoryRegion iomem; 57 + 58 + uint32_t regs[GRLIB_PNP_MAX_REGS >> 2]; 59 + uint8_t master_count; 60 + uint8_t slave_count; 61 + } AHBPnp; 62 + 63 + void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask, 64 + uint8_t vendor, uint16_t device, int slave, 65 + int type) 66 + { 67 + unsigned int reg_start; 68 + 69 + /* 70 + * AHB entries look like this: 71 + * 72 + * 31 -------- 23 -------- 11 ----- 9 -------- 4 --- 0 73 + * | VENDOR ID | DEVICE ID | IRQ ? | VERSION | IRQ | 74 + * -------------------------------------------------- 75 + * | USER | 76 + * -------------------------------------------------- 77 + * | USER | 78 + * -------------------------------------------------- 79 + * | USER | 80 + * -------------------------------------------------- 81 + * | USER | 82 + * -------------------------------------------------- 83 + * 31 ----------- 20 --- 15 ----------------- 3 ---- 0 84 + * | ADDR[31..12] | 00PC | MASK | TYPE | 85 + * -------------------------------------------------- 86 + * 31 ----------- 20 --- 15 ----------------- 3 ---- 0 87 + * | ADDR[31..12] | 00PC | MASK | TYPE | 88 + * -------------------------------------------------- 89 + * 31 ----------- 20 --- 15 ----------------- 3 ---- 0 90 + * | ADDR[31..12] | 00PC | MASK | TYPE | 91 + * -------------------------------------------------- 92 + * 31 ----------- 20 --- 15 ----------------- 3 ---- 0 93 + * | ADDR[31..12] | 00PC | MASK | TYPE | 94 + * -------------------------------------------------- 95 + */ 96 + 97 + if (slave) { 98 + assert(dev->slave_count < GRLIB_AHB_MAX_DEV); 99 + reg_start = (GRLIB_AHB_SLAVE_OFFSET 100 + + (dev->slave_count * GRLIB_AHB_ENTRY_SIZE)) >> 2; 101 + dev->slave_count++; 102 + } else { 103 + assert(dev->master_count < GRLIB_AHB_MAX_DEV); 104 + reg_start = (dev->master_count * GRLIB_AHB_ENTRY_SIZE) >> 2; 105 + dev->master_count++; 106 + } 107 + 108 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 109 + GRLIB_PNP_VENDOR_SHIFT, 110 + GRLIB_PNP_VENDOR_SIZE, 111 + vendor); 112 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 113 + GRLIB_PNP_DEV_SHIFT, 114 + GRLIB_PNP_DEV_SIZE, 115 + device); 116 + reg_start += 4; 117 + /* AHB Memory Space */ 118 + dev->regs[reg_start] = type; 119 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 120 + GRLIB_PNP_ADDR_SHIFT, 121 + GRLIB_PNP_ADDR_SIZE, 122 + extract32(address, 123 + GRLIB_AHB_DEV_ADDR_SHIFT, 124 + GRLIB_AHB_DEV_ADDR_SIZE)); 125 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 126 + GRLIB_PNP_MASK_SHIFT, 127 + GRLIB_PNP_MASK_SIZE, 128 + mask); 129 + } 130 + 131 + static uint64_t grlib_ahb_pnp_read(void *opaque, hwaddr offset, unsigned size) 132 + { 133 + AHBPnp *ahb_pnp = GRLIB_AHB_PNP(opaque); 134 + 135 + return ahb_pnp->regs[offset >> 2]; 136 + } 137 + 138 + static const MemoryRegionOps grlib_ahb_pnp_ops = { 139 + .read = grlib_ahb_pnp_read, 140 + .endianness = DEVICE_BIG_ENDIAN, 141 + }; 142 + 143 + static void grlib_ahb_pnp_realize(DeviceState *dev, Error **errp) 144 + { 145 + AHBPnp *ahb_pnp = GRLIB_AHB_PNP(dev); 146 + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 147 + 148 + memory_region_init_io(&ahb_pnp->iomem, OBJECT(dev), &grlib_ahb_pnp_ops, 149 + ahb_pnp, TYPE_GRLIB_AHB_PNP, GRLIB_PNP_MAX_REGS); 150 + sysbus_init_mmio(sbd, &ahb_pnp->iomem); 151 + } 152 + 153 + static void grlib_ahb_pnp_class_init(ObjectClass *klass, void *data) 154 + { 155 + DeviceClass *dc = DEVICE_CLASS(klass); 156 + 157 + dc->realize = grlib_ahb_pnp_realize; 158 + } 159 + 160 + static const TypeInfo grlib_ahb_pnp_info = { 161 + .name = TYPE_GRLIB_AHB_PNP, 162 + .parent = TYPE_SYS_BUS_DEVICE, 163 + .instance_size = sizeof(AHBPnp), 164 + .class_init = grlib_ahb_pnp_class_init, 165 + }; 166 + 167 + /* APBPnp */ 168 + 169 + typedef struct APBPnp { 170 + SysBusDevice parent_obj; 171 + MemoryRegion iomem; 172 + 173 + uint32_t regs[GRLIB_PNP_MAX_REGS >> 2]; 174 + uint32_t entry_count; 175 + } APBPnp; 176 + 177 + void grlib_apb_pnp_add_entry(APBPnp *dev, uint32_t address, uint32_t mask, 178 + uint8_t vendor, uint16_t device, uint8_t version, 179 + uint8_t irq, int type) 180 + { 181 + unsigned int reg_start; 182 + 183 + /* 184 + * APB entries look like this: 185 + * 186 + * 31 -------- 23 -------- 11 ----- 9 ------- 4 --- 0 187 + * | VENDOR ID | DEVICE ID | IRQ ? | VERSION | IRQ | 188 + * 189 + * 31 ---------- 20 --- 15 ----------------- 3 ---- 0 190 + * | ADDR[20..8] | 0000 | MASK | TYPE | 191 + */ 192 + 193 + assert(dev->entry_count < GRLIB_APB_MAX_DEV); 194 + reg_start = (dev->entry_count * GRLIB_APB_ENTRY_SIZE) >> 2; 195 + dev->entry_count++; 196 + 197 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 198 + GRLIB_PNP_VENDOR_SHIFT, 199 + GRLIB_PNP_VENDOR_SIZE, 200 + vendor); 201 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 202 + GRLIB_PNP_DEV_SHIFT, 203 + GRLIB_PNP_DEV_SIZE, 204 + device); 205 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 206 + GRLIB_PNP_VER_SHIFT, 207 + GRLIB_PNP_VER_SIZE, 208 + version); 209 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 210 + GRLIB_PNP_IRQ_SHIFT, 211 + GRLIB_PNP_IRQ_SIZE, 212 + irq); 213 + reg_start += 1; 214 + dev->regs[reg_start] = type; 215 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 216 + GRLIB_PNP_ADDR_SHIFT, 217 + GRLIB_PNP_ADDR_SIZE, 218 + extract32(address, 219 + GRLIB_APB_DEV_ADDR_SHIFT, 220 + GRLIB_APB_DEV_ADDR_SIZE)); 221 + dev->regs[reg_start] = deposit32(dev->regs[reg_start], 222 + GRLIB_PNP_MASK_SHIFT, 223 + GRLIB_PNP_MASK_SIZE, 224 + mask); 225 + } 226 + 227 + static uint64_t grlib_apb_pnp_read(void *opaque, hwaddr offset, unsigned size) 228 + { 229 + APBPnp *apb_pnp = GRLIB_APB_PNP(opaque); 230 + 231 + return apb_pnp->regs[offset >> 2]; 232 + } 233 + 234 + static const MemoryRegionOps grlib_apb_pnp_ops = { 235 + .read = grlib_apb_pnp_read, 236 + .endianness = DEVICE_BIG_ENDIAN, 237 + }; 238 + 239 + static void grlib_apb_pnp_realize(DeviceState *dev, Error **errp) 240 + { 241 + APBPnp *apb_pnp = GRLIB_APB_PNP(dev); 242 + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 243 + 244 + memory_region_init_io(&apb_pnp->iomem, OBJECT(dev), &grlib_apb_pnp_ops, 245 + apb_pnp, TYPE_GRLIB_APB_PNP, GRLIB_PNP_MAX_REGS); 246 + sysbus_init_mmio(sbd, &apb_pnp->iomem); 247 + } 248 + 249 + static void grlib_apb_pnp_class_init(ObjectClass *klass, void *data) 250 + { 251 + DeviceClass *dc = DEVICE_CLASS(klass); 252 + 253 + dc->realize = grlib_apb_pnp_realize; 254 + } 255 + 256 + static const TypeInfo grlib_apb_pnp_info = { 257 + .name = TYPE_GRLIB_APB_PNP, 258 + .parent = TYPE_SYS_BUS_DEVICE, 259 + .instance_size = sizeof(APBPnp), 260 + .class_init = grlib_apb_pnp_class_init, 261 + }; 262 + 263 + static void grlib_ahb_apb_pnp_register_types(void) 264 + { 265 + type_register_static(&grlib_ahb_pnp_info); 266 + type_register_static(&grlib_apb_pnp_info); 267 + } 268 + 269 + type_init(grlib_ahb_apb_pnp_register_types)
+30
hw/sparc/leon3.c
··· 39 39 #include "exec/address-spaces.h" 40 40 41 41 #include "hw/sparc/grlib.h" 42 + #include "hw/misc/grlib_ahb_apb_pnp.h" 42 43 43 44 /* Default system clock. */ 44 45 #define CPU_CLK (40 * 1000 * 1000) ··· 57 58 #define LEON3_TIMER_OFFSET (0x80000300) 58 59 #define LEON3_TIMER_IRQ (6) 59 60 #define LEON3_TIMER_COUNT (2) 61 + 62 + #define LEON3_APB_PNP_OFFSET (0x800FF000) 63 + #define LEON3_AHB_PNP_OFFSET (0xFFFFF000) 60 64 61 65 typedef struct ResetData { 62 66 SPARCCPU *cpu; ··· 187 191 ResetData *reset_info; 188 192 DeviceState *dev; 189 193 int i; 194 + AHBPnp *ahb_pnp; 195 + APBPnp *apb_pnp; 190 196 191 197 /* Init CPU */ 192 198 cpu = SPARC_CPU(cpu_create(machine->cpu_type)); ··· 200 206 reset_info->sp = LEON3_RAM_OFFSET + ram_size; 201 207 qemu_register_reset(main_cpu_reset, reset_info); 202 208 209 + ahb_pnp = GRLIB_AHB_PNP(object_new(TYPE_GRLIB_AHB_PNP)); 210 + object_property_set_bool(OBJECT(ahb_pnp), true, "realized", &error_fatal); 211 + sysbus_mmio_map(SYS_BUS_DEVICE(ahb_pnp), 0, LEON3_AHB_PNP_OFFSET); 212 + grlib_ahb_pnp_add_entry(ahb_pnp, 0, 0, GRLIB_VENDOR_GAISLER, 213 + GRLIB_LEON3_DEV, GRLIB_AHB_MASTER, 214 + GRLIB_CPU_AREA); 215 + 216 + apb_pnp = GRLIB_APB_PNP(object_new(TYPE_GRLIB_APB_PNP)); 217 + object_property_set_bool(OBJECT(apb_pnp), true, "realized", &error_fatal); 218 + sysbus_mmio_map(SYS_BUS_DEVICE(apb_pnp), 0, LEON3_APB_PNP_OFFSET); 219 + grlib_ahb_pnp_add_entry(ahb_pnp, LEON3_APB_PNP_OFFSET, 0xFFF, 220 + GRLIB_VENDOR_GAISLER, GRLIB_APBMST_DEV, 221 + GRLIB_AHB_SLAVE, GRLIB_AHBMEM_AREA); 222 + 203 223 /* Allocate IRQ manager */ 204 224 dev = qdev_create(NULL, TYPE_GRLIB_IRQMP); 205 225 qdev_prop_set_ptr(dev, "set_pil_in", leon3_set_pil_in); ··· 209 229 env->irq_manager = dev; 210 230 env->qemu_irq_ack = leon3_irq_manager; 211 231 cpu_irqs = qemu_allocate_irqs(grlib_irqmp_set_irq, dev, MAX_PILS); 232 + grlib_apb_pnp_add_entry(apb_pnp, LEON3_IRQMP_OFFSET, 0xFFF, 233 + GRLIB_VENDOR_GAISLER, GRLIB_IRQMP_DEV, 234 + 2, 0, GRLIB_APBIO_AREA); 212 235 213 236 /* Allocate RAM */ 214 237 if (ram_size > 1 * GiB) { ··· 303 326 cpu_irqs[LEON3_TIMER_IRQ + i]); 304 327 } 305 328 329 + grlib_apb_pnp_add_entry(apb_pnp, LEON3_TIMER_OFFSET, 0xFFF, 330 + GRLIB_VENDOR_GAISLER, GRLIB_GPTIMER_DEV, 331 + 0, LEON3_TIMER_IRQ, GRLIB_APBIO_AREA); 332 + 306 333 /* Allocate uart */ 307 334 if (serial_hd(0)) { 308 335 dev = qdev_create(NULL, TYPE_GRLIB_APB_UART); ··· 310 337 qdev_init_nofail(dev); 311 338 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_UART_OFFSET); 312 339 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irqs[LEON3_UART_IRQ]); 340 + grlib_apb_pnp_add_entry(apb_pnp, LEON3_UART_OFFSET, 0xFFF, 341 + GRLIB_VENDOR_GAISLER, GRLIB_APBUART_DEV, 1, 342 + LEON3_UART_IRQ, GRLIB_APBIO_AREA); 313 343 } 314 344 } 315 345
+60
include/hw/misc/grlib_ahb_apb_pnp.h
··· 1 + /* 2 + * GRLIB AHB APB PNP 3 + * 4 + * Copyright (C) 2019 AdaCore 5 + * 6 + * Developed by : 7 + * Frederic Konrad <frederic.konrad@adacore.com> 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation, either version 2 of the License, or 12 + * (at your option) any later version. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License along 20 + * with this program; if not, see <http://www.gnu.org/licenses/>. 21 + * 22 + */ 23 + 24 + #ifndef GRLIB_AHB_APB_PNP_H 25 + #define GRLIB_AHB_APB_PNP_H 26 + 27 + #define TYPE_GRLIB_AHB_PNP "grlib,ahbpnp" 28 + #define GRLIB_AHB_PNP(obj) \ 29 + OBJECT_CHECK(AHBPnp, (obj), TYPE_GRLIB_AHB_PNP) 30 + typedef struct AHBPnp AHBPnp; 31 + 32 + #define TYPE_GRLIB_APB_PNP "grlib,apbpnp" 33 + #define GRLIB_APB_PNP(obj) \ 34 + OBJECT_CHECK(APBPnp, (obj), TYPE_GRLIB_APB_PNP) 35 + typedef struct APBPnp APBPnp; 36 + 37 + void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask, 38 + uint8_t vendor, uint16_t device, int slave, 39 + int type); 40 + void grlib_apb_pnp_add_entry(APBPnp *dev, uint32_t address, uint32_t mask, 41 + uint8_t vendor, uint16_t device, uint8_t version, 42 + uint8_t irq, int type); 43 + 44 + /* VENDORS */ 45 + #define GRLIB_VENDOR_GAISLER (0x01) 46 + /* DEVICES */ 47 + #define GRLIB_LEON3_DEV (0x03) 48 + #define GRLIB_APBMST_DEV (0x06) 49 + #define GRLIB_APBUART_DEV (0x0C) 50 + #define GRLIB_IRQMP_DEV (0x0D) 51 + #define GRLIB_GPTIMER_DEV (0x11) 52 + /* TYPE */ 53 + #define GRLIB_CPU_AREA (0x00) 54 + #define GRLIB_APBIO_AREA (0x01) 55 + #define GRLIB_AHBMEM_AREA (0x02) 56 + 57 + #define GRLIB_AHB_MASTER (0x00) 58 + #define GRLIB_AHB_SLAVE (0x01) 59 + 60 + #endif /* GRLIB_AHB_APB_PNP_H */