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

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180309' into staging

target-arm queue:
* i.MX: Add i.MX7 SOC implementation and i.MX7 Sabre board
* Report the correct core count in A53 L2CTLR on the ZynqMP board
* linux-user: preliminary SVE support work (signal handling)
* hw/arm/boot: fix memory leak in case of error loading ELF file
* hw/arm/boot: avoid reading off end of buffer if passed very
small image file
* hw/arm: Use more CONFIG switches for the object files
* target/arm: Add "-cpu max" support
* hw/arm/virt: Support -machine gic-version=max
* hw/sd: improve debug tracing
* hw/sd: sdcard: Add the Tuning Command (CMD 19)
* MAINTAINERS: add Philippe as odd-fixes maintainer for SD

# gpg: Signature made Fri 09 Mar 2018 17:24:23 GMT
# gpg: using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg: aka "Peter Maydell <pmaydell@gmail.com>"
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20180309: (25 commits)
MAINTAINERS: Add entries for SD (SDHCI, SDBus, SDCard)
sdhci: Fix a typo in comment
sdcard: Add the Tuning Command (CMD19)
sdcard: Display which protocol is used when tracing (SD or SPI)
sdcard: Display command name when tracing CMD/ACMD
sdcard: Do not trace CMD55, except when we already expect an ACMD
hw/arm/virt: Support -machine gic-version=max
hw/arm/virt: Add "max" to the list of CPU types "virt" supports
target/arm: Make 'any' CPU just an alias for 'max'
target/arm: Add "-cpu max" support
target/arm: Move definition of 'host' cpu type into cpu.c
target/arm: Query host CPU features on-demand at instance init
arm: avoid heap-buffer-overflow in load_aarch64_image
arm: fix load ELF error leak
hw/arm: Use more CONFIG switches for the object files
aarch64-linux-user: Add support for SVE signal frame records
aarch64-linux-user: Add support for EXTRA signal frame records
aarch64-linux-user: Remove struct target_aux_context
aarch64-linux-user: Split out helpers for guest signal handling
linux-user: Implement aarch64 PR_SVE_SET/GET_VL
...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+2579 -194
+8
MAINTAINERS
··· 1100 1100 S: Maintained 1101 1101 F: hw/ssi/xilinx_* 1102 1102 1103 + SD (Secure Card) 1104 + M: Philippe Mathieu-Daudé <f4bug@amsat.org> 1105 + S: Odd Fixes 1106 + F: include/hw/sd/sd* 1107 + F: hw/sd/core.c 1108 + F: hw/sd/sd* 1109 + F: tests/sd* 1110 + 1103 1111 USB 1104 1112 M: Gerd Hoffmann <kraxel@redhat.com> 1105 1113 S: Maintained
+9
default-configs/arm-softmmu.mak
··· 47 47 CONFIG_A15MPCORE=y 48 48 49 49 CONFIG_ARM_V7M=y 50 + CONFIG_NETDUINO2=y 50 51 51 52 CONFIG_ARM_GIC=y 52 53 CONFIG_ARM_GIC_KVM=$(CONFIG_KVM) ··· 109 110 CONFIG_IOTKIT=y 110 111 CONFIG_IOTKIT_SECCTL=y 111 112 113 + CONFIG_VERSATILE=y 112 114 CONFIG_VERSATILE_PCI=y 113 115 CONFIG_VERSATILE_I2C=y 114 116 ··· 117 119 CONFIG_VFIO_AMD_XGBE=y 118 120 119 121 CONFIG_SDHCI=y 122 + CONFIG_INTEGRATOR=y 120 123 CONFIG_INTEGRATOR_DEBUG=y 121 124 122 125 CONFIG_ALLWINNER_A10_PIT=y ··· 126 129 CONFIG_FSL_IMX6=y 127 130 CONFIG_FSL_IMX31=y 128 131 CONFIG_FSL_IMX25=y 132 + CONFIG_FSL_IMX7=y 129 133 130 134 CONFIG_IMX_I2C=y 131 135 ··· 140 144 CONFIG_MSF2=y 141 145 CONFIG_FW_CFG_DMA=y 142 146 CONFIG_XILINX_AXI=y 147 + CONFIG_PCI_DESIGNWARE=y 148 + 149 + CONFIG_STRONGARM=y 150 + CONFIG_HIGHBANK=y 151 + CONFIG_MUSICPAL=y
+22 -9
hw/arm/Makefile.objs
··· 1 - obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o 1 + obj-y += boot.o virt.o sysbus-fdt.o 2 + obj-$(CONFIG_ACPI) += virt-acpi-build.o 2 3 obj-$(CONFIG_DIGIC) += digic_boards.o 3 - obj-y += integratorcp.o mainstone.o musicpal.o nseries.o 4 - obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o 5 - obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o 6 - obj-$(CONFIG_ACPI) += virt-acpi-build.o 7 - obj-y += netduino2.o 8 - obj-y += sysbus-fdt.o 4 + obj-$(CONFIG_EXYNOS4) += exynos4_boards.o 5 + obj-$(CONFIG_HIGHBANK) += highbank.o 6 + obj-$(CONFIG_INTEGRATOR) += integratorcp.o 7 + obj-$(CONFIG_MAINSTONE) += mainstone.o 8 + obj-$(CONFIG_MUSICPAL) += musicpal.o 9 + obj-$(CONFIG_NETDUINO2) += netduino2.o 10 + obj-$(CONFIG_NSERIES) += nseries.o 11 + obj-$(CONFIG_OMAP) += omap_sx1.o palm.o 12 + obj-$(CONFIG_PXA2XX) += gumstix.o spitz.o tosa.o z2.o 13 + obj-$(CONFIG_REALVIEW) += realview.o 14 + obj-$(CONFIG_STELLARIS) += stellaris.o 15 + obj-$(CONFIG_STRONGARM) += collie.o 16 + obj-$(CONFIG_VERSATILE) += vexpress.o versatilepb.o 17 + obj-$(CONFIG_ZYNQ) += xilinx_zynq.o 9 18 10 - obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o 19 + obj-$(CONFIG_ARM_V7M) += armv7m.o 20 + obj-$(CONFIG_EXYNOS4) += exynos4210.o 21 + obj-$(CONFIG_PXA2XX) += pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o 11 22 obj-$(CONFIG_DIGIC) += digic.o 12 - obj-y += omap1.o omap2.o strongarm.o 23 + obj-$(CONFIG_OMAP) += omap1.o omap2.o 24 + obj-$(CONFIG_STRONGARM) += strongarm.o 13 25 obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o 14 26 obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o 15 27 obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o ··· 22 34 obj-$(CONFIG_MPS2) += mps2-tz.o 23 35 obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o 24 36 obj-$(CONFIG_IOTKIT) += iotkit.o 37 + obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
+3 -1
hw/arm/boot.c
··· 829 829 830 830 load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err); 831 831 if (err) { 832 + error_free(err); 832 833 return ret; 833 834 } 834 835 ··· 890 891 } 891 892 892 893 /* check the arm64 magic header value -- very old kernels may not have it */ 893 - if (memcmp(buffer + ARM64_MAGIC_OFFSET, "ARM\x64", 4) == 0) { 894 + if (size > ARM64_MAGIC_OFFSET + 4 && 895 + memcmp(buffer + ARM64_MAGIC_OFFSET, "ARM\x64", 4) == 0) { 894 896 uint64_t hdrvals[2]; 895 897 896 898 /* The arm64 Image header has text_offset and image_size fields at 8 and
+582
hw/arm/fsl-imx7.c
··· 1 + /* 2 + * Copyright (c) 2018, Impinj, Inc. 3 + * 4 + * i.MX7 SoC definitions 5 + * 6 + * Author: Andrey Smirnov <andrew.smirnov@gmail.com> 7 + * 8 + * Based on hw/arm/fsl-imx6.c 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 "qemu-common.h" 24 + #include "hw/arm/fsl-imx7.h" 25 + #include "hw/misc/unimp.h" 26 + #include "sysemu/sysemu.h" 27 + #include "qemu/error-report.h" 28 + 29 + #define NAME_SIZE 20 30 + 31 + static void fsl_imx7_init(Object *obj) 32 + { 33 + BusState *sysbus = sysbus_get_default(); 34 + FslIMX7State *s = FSL_IMX7(obj); 35 + char name[NAME_SIZE]; 36 + int i; 37 + 38 + if (smp_cpus > FSL_IMX7_NUM_CPUS) { 39 + error_report("%s: Only %d CPUs are supported (%d requested)", 40 + TYPE_FSL_IMX7, FSL_IMX7_NUM_CPUS, smp_cpus); 41 + exit(1); 42 + } 43 + 44 + for (i = 0; i < smp_cpus; i++) { 45 + object_initialize(&s->cpu[i], sizeof(s->cpu[i]), 46 + ARM_CPU_TYPE_NAME("cortex-a7")); 47 + snprintf(name, NAME_SIZE, "cpu%d", i); 48 + object_property_add_child(obj, name, OBJECT(&s->cpu[i]), 49 + &error_fatal); 50 + } 51 + 52 + /* 53 + * A7MPCORE 54 + */ 55 + object_initialize(&s->a7mpcore, sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV); 56 + qdev_set_parent_bus(DEVICE(&s->a7mpcore), sysbus); 57 + object_property_add_child(obj, "a7mpcore", 58 + OBJECT(&s->a7mpcore), &error_fatal); 59 + 60 + /* 61 + * GPIOs 1 to 7 62 + */ 63 + for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) { 64 + object_initialize(&s->gpio[i], sizeof(s->gpio[i]), 65 + TYPE_IMX_GPIO); 66 + qdev_set_parent_bus(DEVICE(&s->gpio[i]), sysbus); 67 + snprintf(name, NAME_SIZE, "gpio%d", i); 68 + object_property_add_child(obj, name, 69 + OBJECT(&s->gpio[i]), &error_fatal); 70 + } 71 + 72 + /* 73 + * GPT1, 2, 3, 4 74 + */ 75 + for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) { 76 + object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX7_GPT); 77 + qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus); 78 + snprintf(name, NAME_SIZE, "gpt%d", i); 79 + object_property_add_child(obj, name, OBJECT(&s->gpt[i]), 80 + &error_fatal); 81 + } 82 + 83 + /* 84 + * CCM 85 + */ 86 + object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX7_CCM); 87 + qdev_set_parent_bus(DEVICE(&s->ccm), sysbus); 88 + object_property_add_child(obj, "ccm", OBJECT(&s->ccm), &error_fatal); 89 + 90 + /* 91 + * Analog 92 + */ 93 + object_initialize(&s->analog, sizeof(s->analog), TYPE_IMX7_ANALOG); 94 + qdev_set_parent_bus(DEVICE(&s->analog), sysbus); 95 + object_property_add_child(obj, "analog", OBJECT(&s->analog), &error_fatal); 96 + 97 + /* 98 + * GPCv2 99 + */ 100 + object_initialize(&s->gpcv2, sizeof(s->gpcv2), TYPE_IMX_GPCV2); 101 + qdev_set_parent_bus(DEVICE(&s->gpcv2), sysbus); 102 + object_property_add_child(obj, "gpcv2", OBJECT(&s->gpcv2), &error_fatal); 103 + 104 + for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) { 105 + object_initialize(&s->spi[i], sizeof(s->spi[i]), TYPE_IMX_SPI); 106 + qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default()); 107 + snprintf(name, NAME_SIZE, "spi%d", i + 1); 108 + object_property_add_child(obj, name, OBJECT(&s->spi[i]), NULL); 109 + } 110 + 111 + 112 + for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) { 113 + object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C); 114 + qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default()); 115 + snprintf(name, NAME_SIZE, "i2c%d", i + 1); 116 + object_property_add_child(obj, name, OBJECT(&s->i2c[i]), NULL); 117 + } 118 + 119 + /* 120 + * UART 121 + */ 122 + for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) { 123 + object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL); 124 + qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus); 125 + snprintf(name, NAME_SIZE, "uart%d", i); 126 + object_property_add_child(obj, name, OBJECT(&s->uart[i]), 127 + &error_fatal); 128 + } 129 + 130 + /* 131 + * Ethernet 132 + */ 133 + for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) { 134 + object_initialize(&s->eth[i], sizeof(s->eth[i]), TYPE_IMX_ENET); 135 + qdev_set_parent_bus(DEVICE(&s->eth[i]), sysbus); 136 + snprintf(name, NAME_SIZE, "eth%d", i); 137 + object_property_add_child(obj, name, OBJECT(&s->eth[i]), 138 + &error_fatal); 139 + } 140 + 141 + /* 142 + * SDHCI 143 + */ 144 + for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) { 145 + object_initialize(&s->usdhc[i], sizeof(s->usdhc[i]), 146 + TYPE_IMX_USDHC); 147 + qdev_set_parent_bus(DEVICE(&s->usdhc[i]), sysbus); 148 + snprintf(name, NAME_SIZE, "usdhc%d", i); 149 + object_property_add_child(obj, name, OBJECT(&s->usdhc[i]), 150 + &error_fatal); 151 + } 152 + 153 + /* 154 + * SNVS 155 + */ 156 + object_initialize(&s->snvs, sizeof(s->snvs), TYPE_IMX7_SNVS); 157 + qdev_set_parent_bus(DEVICE(&s->snvs), sysbus); 158 + object_property_add_child(obj, "snvs", OBJECT(&s->snvs), &error_fatal); 159 + 160 + /* 161 + * Watchdog 162 + */ 163 + for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) { 164 + object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_IMX2_WDT); 165 + qdev_set_parent_bus(DEVICE(&s->wdt[i]), sysbus); 166 + snprintf(name, NAME_SIZE, "wdt%d", i); 167 + object_property_add_child(obj, name, OBJECT(&s->wdt[i]), 168 + &error_fatal); 169 + } 170 + 171 + /* 172 + * GPR 173 + */ 174 + object_initialize(&s->gpr, sizeof(s->gpr), TYPE_IMX7_GPR); 175 + qdev_set_parent_bus(DEVICE(&s->gpr), sysbus); 176 + object_property_add_child(obj, "gpr", OBJECT(&s->gpr), &error_fatal); 177 + 178 + object_initialize(&s->pcie, sizeof(s->pcie), TYPE_DESIGNWARE_PCIE_HOST); 179 + qdev_set_parent_bus(DEVICE(&s->pcie), sysbus); 180 + object_property_add_child(obj, "pcie", OBJECT(&s->pcie), &error_fatal); 181 + 182 + for (i = 0; i < FSL_IMX7_NUM_USBS; i++) { 183 + object_initialize(&s->usb[i], 184 + sizeof(s->usb[i]), TYPE_CHIPIDEA); 185 + qdev_set_parent_bus(DEVICE(&s->usb[i]), sysbus); 186 + snprintf(name, NAME_SIZE, "usb%d", i); 187 + object_property_add_child(obj, name, 188 + OBJECT(&s->usb[i]), &error_fatal); 189 + } 190 + } 191 + 192 + static void fsl_imx7_realize(DeviceState *dev, Error **errp) 193 + { 194 + FslIMX7State *s = FSL_IMX7(dev); 195 + Object *o; 196 + int i; 197 + qemu_irq irq; 198 + char name[NAME_SIZE]; 199 + 200 + for (i = 0; i < smp_cpus; i++) { 201 + o = OBJECT(&s->cpu[i]); 202 + 203 + object_property_set_int(o, QEMU_PSCI_CONDUIT_SMC, 204 + "psci-conduit", &error_abort); 205 + 206 + /* On uniprocessor, the CBAR is set to 0 */ 207 + if (smp_cpus > 1) { 208 + object_property_set_int(o, FSL_IMX7_A7MPCORE_ADDR, 209 + "reset-cbar", &error_abort); 210 + } 211 + 212 + if (i) { 213 + /* Secondary CPUs start in PSCI powered-down state */ 214 + object_property_set_bool(o, true, 215 + "start-powered-off", &error_abort); 216 + } 217 + 218 + object_property_set_bool(o, true, "realized", &error_abort); 219 + } 220 + 221 + /* 222 + * A7MPCORE 223 + */ 224 + object_property_set_int(OBJECT(&s->a7mpcore), smp_cpus, "num-cpu", 225 + &error_abort); 226 + object_property_set_int(OBJECT(&s->a7mpcore), 227 + FSL_IMX7_MAX_IRQ + GIC_INTERNAL, 228 + "num-irq", &error_abort); 229 + 230 + object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized", 231 + &error_abort); 232 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX7_A7MPCORE_ADDR); 233 + 234 + for (i = 0; i < smp_cpus; i++) { 235 + SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore); 236 + DeviceState *d = DEVICE(qemu_get_cpu(i)); 237 + 238 + irq = qdev_get_gpio_in(d, ARM_CPU_IRQ); 239 + sysbus_connect_irq(sbd, i, irq); 240 + irq = qdev_get_gpio_in(d, ARM_CPU_FIQ); 241 + sysbus_connect_irq(sbd, i + smp_cpus, irq); 242 + } 243 + 244 + /* 245 + * A7MPCORE DAP 246 + */ 247 + create_unimplemented_device("a7mpcore-dap", FSL_IMX7_A7MPCORE_DAP_ADDR, 248 + 0x100000); 249 + 250 + /* 251 + * GPT1, 2, 3, 4 252 + */ 253 + for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) { 254 + static const hwaddr FSL_IMX7_GPTn_ADDR[FSL_IMX7_NUM_GPTS] = { 255 + FSL_IMX7_GPT1_ADDR, 256 + FSL_IMX7_GPT2_ADDR, 257 + FSL_IMX7_GPT3_ADDR, 258 + FSL_IMX7_GPT4_ADDR, 259 + }; 260 + 261 + s->gpt[i].ccm = IMX_CCM(&s->ccm); 262 + object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", 263 + &error_abort); 264 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, FSL_IMX7_GPTn_ADDR[i]); 265 + } 266 + 267 + for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) { 268 + static const hwaddr FSL_IMX7_GPIOn_ADDR[FSL_IMX7_NUM_GPIOS] = { 269 + FSL_IMX7_GPIO1_ADDR, 270 + FSL_IMX7_GPIO2_ADDR, 271 + FSL_IMX7_GPIO3_ADDR, 272 + FSL_IMX7_GPIO4_ADDR, 273 + FSL_IMX7_GPIO5_ADDR, 274 + FSL_IMX7_GPIO6_ADDR, 275 + FSL_IMX7_GPIO7_ADDR, 276 + }; 277 + 278 + object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", 279 + &error_abort); 280 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, FSL_IMX7_GPIOn_ADDR[i]); 281 + } 282 + 283 + /* 284 + * IOMUXC and IOMUXC_LPSR 285 + */ 286 + for (i = 0; i < FSL_IMX7_NUM_IOMUXCS; i++) { 287 + static const hwaddr FSL_IMX7_IOMUXCn_ADDR[FSL_IMX7_NUM_IOMUXCS] = { 288 + FSL_IMX7_IOMUXC_ADDR, 289 + FSL_IMX7_IOMUXC_LPSR_ADDR, 290 + }; 291 + 292 + snprintf(name, NAME_SIZE, "iomuxc%d", i); 293 + create_unimplemented_device(name, FSL_IMX7_IOMUXCn_ADDR[i], 294 + FSL_IMX7_IOMUXCn_SIZE); 295 + } 296 + 297 + /* 298 + * CCM 299 + */ 300 + object_property_set_bool(OBJECT(&s->ccm), true, "realized", &error_abort); 301 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX7_CCM_ADDR); 302 + 303 + /* 304 + * Analog 305 + */ 306 + object_property_set_bool(OBJECT(&s->analog), true, "realized", 307 + &error_abort); 308 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->analog), 0, FSL_IMX7_ANALOG_ADDR); 309 + 310 + /* 311 + * GPCv2 312 + */ 313 + object_property_set_bool(OBJECT(&s->gpcv2), true, 314 + "realized", &error_abort); 315 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX7_GPC_ADDR); 316 + 317 + /* Initialize all ECSPI */ 318 + for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) { 319 + static const hwaddr FSL_IMX7_SPIn_ADDR[FSL_IMX7_NUM_ECSPIS] = { 320 + FSL_IMX7_ECSPI1_ADDR, 321 + FSL_IMX7_ECSPI2_ADDR, 322 + FSL_IMX7_ECSPI3_ADDR, 323 + FSL_IMX7_ECSPI4_ADDR, 324 + }; 325 + 326 + static const hwaddr FSL_IMX7_SPIn_IRQ[FSL_IMX7_NUM_ECSPIS] = { 327 + FSL_IMX7_ECSPI1_IRQ, 328 + FSL_IMX7_ECSPI2_IRQ, 329 + FSL_IMX7_ECSPI3_IRQ, 330 + FSL_IMX7_ECSPI4_IRQ, 331 + }; 332 + 333 + /* Initialize the SPI */ 334 + object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", 335 + &error_abort); 336 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, 337 + FSL_IMX7_SPIn_ADDR[i]); 338 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0, 339 + qdev_get_gpio_in(DEVICE(&s->a7mpcore), 340 + FSL_IMX7_SPIn_IRQ[i])); 341 + } 342 + 343 + for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) { 344 + static const hwaddr FSL_IMX7_I2Cn_ADDR[FSL_IMX7_NUM_I2CS] = { 345 + FSL_IMX7_I2C1_ADDR, 346 + FSL_IMX7_I2C2_ADDR, 347 + FSL_IMX7_I2C3_ADDR, 348 + FSL_IMX7_I2C4_ADDR, 349 + }; 350 + 351 + static const hwaddr FSL_IMX7_I2Cn_IRQ[FSL_IMX7_NUM_I2CS] = { 352 + FSL_IMX7_I2C1_IRQ, 353 + FSL_IMX7_I2C2_IRQ, 354 + FSL_IMX7_I2C3_IRQ, 355 + FSL_IMX7_I2C4_IRQ, 356 + }; 357 + 358 + object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", 359 + &error_abort); 360 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX7_I2Cn_ADDR[i]); 361 + 362 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0, 363 + qdev_get_gpio_in(DEVICE(&s->a7mpcore), 364 + FSL_IMX7_I2Cn_IRQ[i])); 365 + } 366 + 367 + /* 368 + * UART 369 + */ 370 + for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) { 371 + static const hwaddr FSL_IMX7_UARTn_ADDR[FSL_IMX7_NUM_UARTS] = { 372 + FSL_IMX7_UART1_ADDR, 373 + FSL_IMX7_UART2_ADDR, 374 + FSL_IMX7_UART3_ADDR, 375 + FSL_IMX7_UART4_ADDR, 376 + FSL_IMX7_UART5_ADDR, 377 + FSL_IMX7_UART6_ADDR, 378 + FSL_IMX7_UART7_ADDR, 379 + }; 380 + 381 + static const int FSL_IMX7_UARTn_IRQ[FSL_IMX7_NUM_UARTS] = { 382 + FSL_IMX7_UART1_IRQ, 383 + FSL_IMX7_UART2_IRQ, 384 + FSL_IMX7_UART3_IRQ, 385 + FSL_IMX7_UART4_IRQ, 386 + FSL_IMX7_UART5_IRQ, 387 + FSL_IMX7_UART6_IRQ, 388 + FSL_IMX7_UART7_IRQ, 389 + }; 390 + 391 + 392 + if (i < MAX_SERIAL_PORTS) { 393 + qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hds[i]); 394 + } 395 + 396 + object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", 397 + &error_abort); 398 + 399 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, FSL_IMX7_UARTn_ADDR[i]); 400 + 401 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_UARTn_IRQ[i]); 402 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, irq); 403 + } 404 + 405 + /* 406 + * Ethernet 407 + */ 408 + for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) { 409 + static const hwaddr FSL_IMX7_ENETn_ADDR[FSL_IMX7_NUM_ETHS] = { 410 + FSL_IMX7_ENET1_ADDR, 411 + FSL_IMX7_ENET2_ADDR, 412 + }; 413 + 414 + object_property_set_uint(OBJECT(&s->eth[i]), FSL_IMX7_ETH_NUM_TX_RINGS, 415 + "tx-ring-num", &error_abort); 416 + qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]); 417 + object_property_set_bool(OBJECT(&s->eth[i]), true, "realized", 418 + &error_abort); 419 + 420 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0, FSL_IMX7_ENETn_ADDR[i]); 421 + 422 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_ENET_IRQ(i, 0)); 423 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 0, irq); 424 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_ENET_IRQ(i, 3)); 425 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 1, irq); 426 + } 427 + 428 + /* 429 + * USDHC 430 + */ 431 + for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) { 432 + static const hwaddr FSL_IMX7_USDHCn_ADDR[FSL_IMX7_NUM_USDHCS] = { 433 + FSL_IMX7_USDHC1_ADDR, 434 + FSL_IMX7_USDHC2_ADDR, 435 + FSL_IMX7_USDHC3_ADDR, 436 + }; 437 + 438 + static const int FSL_IMX7_USDHCn_IRQ[FSL_IMX7_NUM_USDHCS] = { 439 + FSL_IMX7_USDHC1_IRQ, 440 + FSL_IMX7_USDHC2_IRQ, 441 + FSL_IMX7_USDHC3_IRQ, 442 + }; 443 + 444 + object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized", 445 + &error_abort); 446 + 447 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0, 448 + FSL_IMX7_USDHCn_ADDR[i]); 449 + 450 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_USDHCn_IRQ[i]); 451 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0, irq); 452 + } 453 + 454 + /* 455 + * SNVS 456 + */ 457 + object_property_set_bool(OBJECT(&s->snvs), true, "realized", &error_abort); 458 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_ADDR); 459 + 460 + /* 461 + * SRC 462 + */ 463 + create_unimplemented_device("sdma", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE); 464 + 465 + /* 466 + * Watchdog 467 + */ 468 + for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) { 469 + static const hwaddr FSL_IMX7_WDOGn_ADDR[FSL_IMX7_NUM_WDTS] = { 470 + FSL_IMX7_WDOG1_ADDR, 471 + FSL_IMX7_WDOG2_ADDR, 472 + FSL_IMX7_WDOG3_ADDR, 473 + FSL_IMX7_WDOG4_ADDR, 474 + }; 475 + 476 + object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", 477 + &error_abort); 478 + 479 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]); 480 + } 481 + 482 + /* 483 + * SDMA 484 + */ 485 + create_unimplemented_device("sdma", FSL_IMX7_SDMA_ADDR, FSL_IMX7_SDMA_SIZE); 486 + 487 + 488 + object_property_set_bool(OBJECT(&s->gpr), true, "realized", 489 + &error_abort); 490 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_GPR_ADDR); 491 + 492 + object_property_set_bool(OBJECT(&s->pcie), true, 493 + "realized", &error_abort); 494 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR); 495 + 496 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTA_IRQ); 497 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq); 498 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTB_IRQ); 499 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq); 500 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTC_IRQ); 501 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq); 502 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ); 503 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq); 504 + 505 + 506 + for (i = 0; i < FSL_IMX7_NUM_USBS; i++) { 507 + static const hwaddr FSL_IMX7_USBMISCn_ADDR[FSL_IMX7_NUM_USBS] = { 508 + FSL_IMX7_USBMISC1_ADDR, 509 + FSL_IMX7_USBMISC2_ADDR, 510 + FSL_IMX7_USBMISC3_ADDR, 511 + }; 512 + 513 + static const hwaddr FSL_IMX7_USBn_ADDR[FSL_IMX7_NUM_USBS] = { 514 + FSL_IMX7_USB1_ADDR, 515 + FSL_IMX7_USB2_ADDR, 516 + FSL_IMX7_USB3_ADDR, 517 + }; 518 + 519 + static const hwaddr FSL_IMX7_USBn_IRQ[FSL_IMX7_NUM_USBS] = { 520 + FSL_IMX7_USB1_IRQ, 521 + FSL_IMX7_USB2_IRQ, 522 + FSL_IMX7_USB3_IRQ, 523 + }; 524 + 525 + object_property_set_bool(OBJECT(&s->usb[i]), true, "realized", 526 + &error_abort); 527 + sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, 528 + FSL_IMX7_USBn_ADDR[i]); 529 + 530 + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_USBn_IRQ[i]); 531 + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0, irq); 532 + 533 + snprintf(name, NAME_SIZE, "usbmisc%d", i); 534 + create_unimplemented_device(name, FSL_IMX7_USBMISCn_ADDR[i], 535 + FSL_IMX7_USBMISCn_SIZE); 536 + } 537 + 538 + /* 539 + * ADCs 540 + */ 541 + for (i = 0; i < FSL_IMX7_NUM_ADCS; i++) { 542 + static const hwaddr FSL_IMX7_ADCn_ADDR[FSL_IMX7_NUM_ADCS] = { 543 + FSL_IMX7_ADC1_ADDR, 544 + FSL_IMX7_ADC2_ADDR, 545 + }; 546 + 547 + snprintf(name, NAME_SIZE, "adc%d", i); 548 + create_unimplemented_device(name, FSL_IMX7_ADCn_ADDR[i], 549 + FSL_IMX7_ADCn_SIZE); 550 + } 551 + 552 + /* 553 + * LCD 554 + */ 555 + create_unimplemented_device("lcdif", FSL_IMX7_LCDIF_ADDR, 556 + FSL_IMX7_LCDIF_SIZE); 557 + } 558 + 559 + static void fsl_imx7_class_init(ObjectClass *oc, void *data) 560 + { 561 + DeviceClass *dc = DEVICE_CLASS(oc); 562 + 563 + dc->realize = fsl_imx7_realize; 564 + 565 + /* Reason: Uses serial_hds and nd_table in realize() directly */ 566 + dc->user_creatable = false; 567 + dc->desc = "i.MX7 SOC"; 568 + } 569 + 570 + static const TypeInfo fsl_imx7_type_info = { 571 + .name = TYPE_FSL_IMX7, 572 + .parent = TYPE_DEVICE, 573 + .instance_size = sizeof(FslIMX7State), 574 + .instance_init = fsl_imx7_init, 575 + .class_init = fsl_imx7_class_init, 576 + }; 577 + 578 + static void fsl_imx7_register_types(void) 579 + { 580 + type_register_static(&fsl_imx7_type_info); 581 + } 582 + type_init(fsl_imx7_register_types)
+90
hw/arm/mcimx7d-sabre.c
··· 1 + /* 2 + * Copyright (c) 2018, Impinj, Inc. 3 + * 4 + * MCIMX7D_SABRE Board System emulation. 5 + * 6 + * Author: Andrey Smirnov <andrew.smirnov@gmail.com> 7 + * 8 + * This code is licensed under the GPL, version 2 or later. 9 + * See the file `COPYING' in the top level directory. 10 + * 11 + * It (partially) emulates a mcimx7d_sabre board, with a Freescale 12 + * i.MX7 SoC 13 + */ 14 + 15 + #include "qemu/osdep.h" 16 + #include "qapi/error.h" 17 + #include "qemu-common.h" 18 + #include "hw/arm/fsl-imx7.h" 19 + #include "hw/boards.h" 20 + #include "sysemu/sysemu.h" 21 + #include "sysemu/device_tree.h" 22 + #include "qemu/error-report.h" 23 + #include "sysemu/qtest.h" 24 + #include "net/net.h" 25 + 26 + typedef struct { 27 + FslIMX7State soc; 28 + MemoryRegion ram; 29 + } MCIMX7Sabre; 30 + 31 + static void mcimx7d_sabre_init(MachineState *machine) 32 + { 33 + static struct arm_boot_info boot_info; 34 + MCIMX7Sabre *s = g_new0(MCIMX7Sabre, 1); 35 + Object *soc; 36 + int i; 37 + 38 + if (machine->ram_size > FSL_IMX7_MMDC_SIZE) { 39 + error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)", 40 + machine->ram_size, FSL_IMX7_MMDC_SIZE); 41 + exit(1); 42 + } 43 + 44 + boot_info = (struct arm_boot_info) { 45 + .loader_start = FSL_IMX7_MMDC_ADDR, 46 + .board_id = -1, 47 + .ram_size = machine->ram_size, 48 + .kernel_filename = machine->kernel_filename, 49 + .kernel_cmdline = machine->kernel_cmdline, 50 + .initrd_filename = machine->initrd_filename, 51 + .nb_cpus = smp_cpus, 52 + }; 53 + 54 + object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX7); 55 + soc = OBJECT(&s->soc); 56 + object_property_add_child(OBJECT(machine), "soc", soc, &error_fatal); 57 + object_property_set_bool(soc, true, "realized", &error_fatal); 58 + 59 + memory_region_allocate_system_memory(&s->ram, NULL, "mcimx7d-sabre.ram", 60 + machine->ram_size); 61 + memory_region_add_subregion(get_system_memory(), 62 + FSL_IMX7_MMDC_ADDR, &s->ram); 63 + 64 + for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) { 65 + BusState *bus; 66 + DeviceState *carddev; 67 + DriveInfo *di; 68 + BlockBackend *blk; 69 + 70 + di = drive_get_next(IF_SD); 71 + blk = di ? blk_by_legacy_dinfo(di) : NULL; 72 + bus = qdev_get_child_bus(DEVICE(&s->soc.usdhc[i]), "sd-bus"); 73 + carddev = qdev_create(bus, TYPE_SD_CARD); 74 + qdev_prop_set_drive(carddev, "drive", blk, &error_fatal); 75 + object_property_set_bool(OBJECT(carddev), true, 76 + "realized", &error_fatal); 77 + } 78 + 79 + if (!qtest_enabled()) { 80 + arm_load_kernel(&s->soc.cpu[0], &boot_info); 81 + } 82 + } 83 + 84 + static void mcimx7d_sabre_machine_init(MachineClass *mc) 85 + { 86 + mc->desc = "Freescale i.MX7 DUAL SABRE (Cortex A7)"; 87 + mc->init = mcimx7d_sabre_init; 88 + mc->max_cpus = FSL_IMX7_NUM_CPUS; 89 + } 90 + DEFINE_MACHINE("mcimx7d-sabre", mcimx7d_sabre_machine_init)
+20 -10
hw/arm/virt.c
··· 169 169 ARM_CPU_TYPE_NAME("cortex-a53"), 170 170 ARM_CPU_TYPE_NAME("cortex-a57"), 171 171 ARM_CPU_TYPE_NAME("host"), 172 + ARM_CPU_TYPE_NAME("max"), 172 173 }; 173 174 174 175 static bool cpu_type_valid(const char *cpu) ··· 1206 1207 /* We can probe only here because during property set 1207 1208 * KVM is not available yet 1208 1209 */ 1209 - if (!vms->gic_version) { 1210 + if (vms->gic_version <= 0) { 1211 + /* "host" or "max" */ 1210 1212 if (!kvm_enabled()) { 1211 - error_report("gic-version=host requires KVM"); 1212 - exit(1); 1213 - } 1214 - 1215 - vms->gic_version = kvm_arm_vgic_probe(); 1216 - if (!vms->gic_version) { 1217 - error_report("Unable to determine GIC version supported by host"); 1218 - exit(1); 1213 + if (vms->gic_version == 0) { 1214 + error_report("gic-version=host requires KVM"); 1215 + exit(1); 1216 + } else { 1217 + /* "max": currently means 3 for TCG */ 1218 + vms->gic_version = 3; 1219 + } 1220 + } else { 1221 + vms->gic_version = kvm_arm_vgic_probe(); 1222 + if (!vms->gic_version) { 1223 + error_report( 1224 + "Unable to determine GIC version supported by host"); 1225 + exit(1); 1226 + } 1219 1227 } 1220 1228 } 1221 1229 ··· 1479 1487 vms->gic_version = 2; 1480 1488 } else if (!strcmp(value, "host")) { 1481 1489 vms->gic_version = 0; /* Will probe later */ 1490 + } else if (!strcmp(value, "max")) { 1491 + vms->gic_version = -1; /* Will probe later */ 1482 1492 } else { 1483 1493 error_setg(errp, "Invalid gic-version value"); 1484 - error_append_hint(errp, "Valid values are 3, 2, host.\n"); 1494 + error_append_hint(errp, "Valid values are 3, 2, host, max.\n"); 1485 1495 } 1486 1496 } 1487 1497
+2
hw/arm/xlnx-zynqmp.c
··· 282 282 s->virt, "has_el2", NULL); 283 283 object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR, 284 284 "reset-cbar", &error_abort); 285 + object_property_set_int(OBJECT(&s->apu_cpu[i]), num_apus, 286 + "core-count", &error_abort); 285 287 object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized", 286 288 &err); 287 289 if (err) {
+2
hw/pci-host/Makefile.objs
··· 17 17 common-obj-$(CONFIG_PCI_Q35) += q35.o 18 18 common-obj-$(CONFIG_PCI_GENERIC) += gpex.o 19 19 common-obj-$(CONFIG_PCI_XILINX) += xilinx-pcie.o 20 + 21 + common-obj-$(CONFIG_PCI_DESIGNWARE) += designware.o
+754
hw/pci-host/designware.c
··· 1 + /* 2 + * Copyright (c) 2018, Impinj, Inc. 3 + * 4 + * Designware PCIe IP block emulation 5 + * 6 + * This library is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU Lesser General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This library 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 GNU 14 + * Lesser General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU Lesser General Public 17 + * License along with this library; if not, see 18 + * <http://www.gnu.org/licenses/>. 19 + */ 20 + 21 + #include "qemu/osdep.h" 22 + #include "qapi/error.h" 23 + #include "hw/pci/msi.h" 24 + #include "hw/pci/pci_bridge.h" 25 + #include "hw/pci/pci_host.h" 26 + #include "hw/pci/pcie_port.h" 27 + #include "hw/pci-host/designware.h" 28 + 29 + #define DESIGNWARE_PCIE_PORT_LINK_CONTROL 0x710 30 + #define DESIGNWARE_PCIE_PHY_DEBUG_R1 0x72C 31 + #define DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP BIT(4) 32 + #define DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C 33 + #define DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE BIT(17) 34 + #define DESIGNWARE_PCIE_MSI_ADDR_LO 0x820 35 + #define DESIGNWARE_PCIE_MSI_ADDR_HI 0x824 36 + #define DESIGNWARE_PCIE_MSI_INTR0_ENABLE 0x828 37 + #define DESIGNWARE_PCIE_MSI_INTR0_MASK 0x82C 38 + #define DESIGNWARE_PCIE_MSI_INTR0_STATUS 0x830 39 + #define DESIGNWARE_PCIE_ATU_VIEWPORT 0x900 40 + #define DESIGNWARE_PCIE_ATU_REGION_INBOUND BIT(31) 41 + #define DESIGNWARE_PCIE_ATU_CR1 0x904 42 + #define DESIGNWARE_PCIE_ATU_TYPE_MEM (0x0 << 0) 43 + #define DESIGNWARE_PCIE_ATU_CR2 0x908 44 + #define DESIGNWARE_PCIE_ATU_ENABLE BIT(31) 45 + #define DESIGNWARE_PCIE_ATU_LOWER_BASE 0x90C 46 + #define DESIGNWARE_PCIE_ATU_UPPER_BASE 0x910 47 + #define DESIGNWARE_PCIE_ATU_LIMIT 0x914 48 + #define DESIGNWARE_PCIE_ATU_LOWER_TARGET 0x918 49 + #define DESIGNWARE_PCIE_ATU_BUS(x) (((x) >> 24) & 0xff) 50 + #define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff) 51 + #define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C 52 + 53 + static DesignwarePCIEHost * 54 + designware_pcie_root_to_host(DesignwarePCIERoot *root) 55 + { 56 + BusState *bus = qdev_get_parent_bus(DEVICE(root)); 57 + return DESIGNWARE_PCIE_HOST(bus->parent); 58 + } 59 + 60 + static void designware_pcie_root_msi_write(void *opaque, hwaddr addr, 61 + uint64_t val, unsigned len) 62 + { 63 + DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(opaque); 64 + DesignwarePCIEHost *host = designware_pcie_root_to_host(root); 65 + 66 + root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable; 67 + 68 + if (root->msi.intr[0].status & ~root->msi.intr[0].mask) { 69 + qemu_set_irq(host->pci.irqs[0], 1); 70 + } 71 + } 72 + 73 + static const MemoryRegionOps designware_pci_host_msi_ops = { 74 + .write = designware_pcie_root_msi_write, 75 + .endianness = DEVICE_LITTLE_ENDIAN, 76 + .valid = { 77 + .min_access_size = 4, 78 + .max_access_size = 4, 79 + }, 80 + }; 81 + 82 + static void designware_pcie_root_update_msi_mapping(DesignwarePCIERoot *root) 83 + 84 + { 85 + MemoryRegion *mem = &root->msi.iomem; 86 + const uint64_t base = root->msi.base; 87 + const bool enable = root->msi.intr[0].enable; 88 + 89 + memory_region_set_address(mem, base); 90 + memory_region_set_enabled(mem, enable); 91 + } 92 + 93 + static DesignwarePCIEViewport * 94 + designware_pcie_root_get_current_viewport(DesignwarePCIERoot *root) 95 + { 96 + const unsigned int idx = root->atu_viewport & 0xF; 97 + const unsigned int dir = 98 + !!(root->atu_viewport & DESIGNWARE_PCIE_ATU_REGION_INBOUND); 99 + return &root->viewports[dir][idx]; 100 + } 101 + 102 + static uint32_t 103 + designware_pcie_root_config_read(PCIDevice *d, uint32_t address, int len) 104 + { 105 + DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d); 106 + DesignwarePCIEViewport *viewport = 107 + designware_pcie_root_get_current_viewport(root); 108 + 109 + uint32_t val; 110 + 111 + switch (address) { 112 + case DESIGNWARE_PCIE_PORT_LINK_CONTROL: 113 + /* 114 + * Linux guest uses this register only to configure number of 115 + * PCIE lane (which in our case is irrelevant) and doesn't 116 + * really care about the value it reads from this register 117 + */ 118 + val = 0xDEADBEEF; 119 + break; 120 + 121 + case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL: 122 + /* 123 + * To make sure that any code in guest waiting for speed 124 + * change does not time out we always report 125 + * PORT_LOGIC_SPEED_CHANGE as set 126 + */ 127 + val = DESIGNWARE_PCIE_PORT_LOGIC_SPEED_CHANGE; 128 + break; 129 + 130 + case DESIGNWARE_PCIE_MSI_ADDR_LO: 131 + val = root->msi.base; 132 + break; 133 + 134 + case DESIGNWARE_PCIE_MSI_ADDR_HI: 135 + val = root->msi.base >> 32; 136 + break; 137 + 138 + case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: 139 + val = root->msi.intr[0].enable; 140 + break; 141 + 142 + case DESIGNWARE_PCIE_MSI_INTR0_MASK: 143 + val = root->msi.intr[0].mask; 144 + break; 145 + 146 + case DESIGNWARE_PCIE_MSI_INTR0_STATUS: 147 + val = root->msi.intr[0].status; 148 + break; 149 + 150 + case DESIGNWARE_PCIE_PHY_DEBUG_R1: 151 + val = DESIGNWARE_PCIE_PHY_DEBUG_R1_XMLH_LINK_UP; 152 + break; 153 + 154 + case DESIGNWARE_PCIE_ATU_VIEWPORT: 155 + val = root->atu_viewport; 156 + break; 157 + 158 + case DESIGNWARE_PCIE_ATU_LOWER_BASE: 159 + val = viewport->base; 160 + break; 161 + 162 + case DESIGNWARE_PCIE_ATU_UPPER_BASE: 163 + val = viewport->base >> 32; 164 + break; 165 + 166 + case DESIGNWARE_PCIE_ATU_LOWER_TARGET: 167 + val = viewport->target; 168 + break; 169 + 170 + case DESIGNWARE_PCIE_ATU_UPPER_TARGET: 171 + val = viewport->target >> 32; 172 + break; 173 + 174 + case DESIGNWARE_PCIE_ATU_LIMIT: 175 + val = viewport->limit; 176 + break; 177 + 178 + case DESIGNWARE_PCIE_ATU_CR1: 179 + case DESIGNWARE_PCIE_ATU_CR2: /* FALLTHROUGH */ 180 + val = viewport->cr[(address - DESIGNWARE_PCIE_ATU_CR1) / 181 + sizeof(uint32_t)]; 182 + break; 183 + 184 + default: 185 + val = pci_default_read_config(d, address, len); 186 + break; 187 + } 188 + 189 + return val; 190 + } 191 + 192 + static uint64_t designware_pcie_root_data_access(void *opaque, hwaddr addr, 193 + uint64_t *val, unsigned len) 194 + { 195 + DesignwarePCIEViewport *viewport = opaque; 196 + DesignwarePCIERoot *root = viewport->root; 197 + 198 + const uint8_t busnum = DESIGNWARE_PCIE_ATU_BUS(viewport->target); 199 + const uint8_t devfn = DESIGNWARE_PCIE_ATU_DEVFN(viewport->target); 200 + PCIBus *pcibus = pci_get_bus(PCI_DEVICE(root)); 201 + PCIDevice *pcidev = pci_find_device(pcibus, busnum, devfn); 202 + 203 + if (pcidev) { 204 + addr &= pci_config_size(pcidev) - 1; 205 + 206 + if (val) { 207 + pci_host_config_write_common(pcidev, addr, 208 + pci_config_size(pcidev), 209 + *val, len); 210 + } else { 211 + return pci_host_config_read_common(pcidev, addr, 212 + pci_config_size(pcidev), 213 + len); 214 + } 215 + } 216 + 217 + return UINT64_MAX; 218 + } 219 + 220 + static uint64_t designware_pcie_root_data_read(void *opaque, hwaddr addr, 221 + unsigned len) 222 + { 223 + return designware_pcie_root_data_access(opaque, addr, NULL, len); 224 + } 225 + 226 + static void designware_pcie_root_data_write(void *opaque, hwaddr addr, 227 + uint64_t val, unsigned len) 228 + { 229 + designware_pcie_root_data_access(opaque, addr, &val, len); 230 + } 231 + 232 + static const MemoryRegionOps designware_pci_host_conf_ops = { 233 + .read = designware_pcie_root_data_read, 234 + .write = designware_pcie_root_data_write, 235 + .endianness = DEVICE_LITTLE_ENDIAN, 236 + .valid = { 237 + .min_access_size = 1, 238 + .max_access_size = 4, 239 + }, 240 + }; 241 + 242 + static void designware_pcie_update_viewport(DesignwarePCIERoot *root, 243 + DesignwarePCIEViewport *viewport) 244 + { 245 + const uint64_t target = viewport->target; 246 + const uint64_t base = viewport->base; 247 + const uint64_t size = (uint64_t)viewport->limit - base + 1; 248 + const bool enabled = viewport->cr[1] & DESIGNWARE_PCIE_ATU_ENABLE; 249 + 250 + MemoryRegion *current, *other; 251 + 252 + if (viewport->cr[0] == DESIGNWARE_PCIE_ATU_TYPE_MEM) { 253 + current = &viewport->mem; 254 + other = &viewport->cfg; 255 + memory_region_set_alias_offset(current, target); 256 + } else { 257 + current = &viewport->cfg; 258 + other = &viewport->mem; 259 + } 260 + 261 + /* 262 + * An outbound viewport can be reconfigure from being MEM to CFG, 263 + * to account for that we disable the "other" memory region that 264 + * becomes unused due to that fact. 265 + */ 266 + memory_region_set_enabled(other, false); 267 + if (enabled) { 268 + memory_region_set_size(current, size); 269 + memory_region_set_address(current, base); 270 + } 271 + memory_region_set_enabled(current, enabled); 272 + } 273 + 274 + static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address, 275 + uint32_t val, int len) 276 + { 277 + DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(d); 278 + DesignwarePCIEHost *host = designware_pcie_root_to_host(root); 279 + DesignwarePCIEViewport *viewport = 280 + designware_pcie_root_get_current_viewport(root); 281 + 282 + switch (address) { 283 + case DESIGNWARE_PCIE_PORT_LINK_CONTROL: 284 + case DESIGNWARE_PCIE_LINK_WIDTH_SPEED_CONTROL: 285 + case DESIGNWARE_PCIE_PHY_DEBUG_R1: 286 + /* No-op */ 287 + break; 288 + 289 + case DESIGNWARE_PCIE_MSI_ADDR_LO: 290 + root->msi.base &= 0xFFFFFFFF00000000ULL; 291 + root->msi.base |= val; 292 + break; 293 + 294 + case DESIGNWARE_PCIE_MSI_ADDR_HI: 295 + root->msi.base &= 0x00000000FFFFFFFFULL; 296 + root->msi.base |= (uint64_t)val << 32; 297 + break; 298 + 299 + case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: { 300 + const bool update_msi_mapping = !root->msi.intr[0].enable ^ !!val; 301 + 302 + root->msi.intr[0].enable = val; 303 + 304 + if (update_msi_mapping) { 305 + designware_pcie_root_update_msi_mapping(root); 306 + } 307 + break; 308 + } 309 + 310 + case DESIGNWARE_PCIE_MSI_INTR0_MASK: 311 + root->msi.intr[0].mask = val; 312 + break; 313 + 314 + case DESIGNWARE_PCIE_MSI_INTR0_STATUS: 315 + root->msi.intr[0].status ^= val; 316 + if (!root->msi.intr[0].status) { 317 + qemu_set_irq(host->pci.irqs[0], 0); 318 + } 319 + break; 320 + 321 + case DESIGNWARE_PCIE_ATU_VIEWPORT: 322 + root->atu_viewport = val; 323 + break; 324 + 325 + case DESIGNWARE_PCIE_ATU_LOWER_BASE: 326 + viewport->base &= 0xFFFFFFFF00000000ULL; 327 + viewport->base |= val; 328 + break; 329 + 330 + case DESIGNWARE_PCIE_ATU_UPPER_BASE: 331 + viewport->base &= 0x00000000FFFFFFFFULL; 332 + viewport->base |= (uint64_t)val << 32; 333 + break; 334 + 335 + case DESIGNWARE_PCIE_ATU_LOWER_TARGET: 336 + viewport->target &= 0xFFFFFFFF00000000ULL; 337 + viewport->target |= val; 338 + break; 339 + 340 + case DESIGNWARE_PCIE_ATU_UPPER_TARGET: 341 + viewport->target &= 0x00000000FFFFFFFFULL; 342 + viewport->target |= val; 343 + break; 344 + 345 + case DESIGNWARE_PCIE_ATU_LIMIT: 346 + viewport->limit = val; 347 + break; 348 + 349 + case DESIGNWARE_PCIE_ATU_CR1: 350 + viewport->cr[0] = val; 351 + break; 352 + case DESIGNWARE_PCIE_ATU_CR2: 353 + viewport->cr[1] = val; 354 + designware_pcie_update_viewport(root, viewport); 355 + break; 356 + 357 + default: 358 + pci_bridge_write_config(d, address, val, len); 359 + break; 360 + } 361 + } 362 + 363 + static char *designware_pcie_viewport_name(const char *direction, 364 + unsigned int i, 365 + const char *type) 366 + { 367 + return g_strdup_printf("PCI %s Viewport %u [%s]", 368 + direction, i, type); 369 + } 370 + 371 + static void designware_pcie_root_realize(PCIDevice *dev, Error **errp) 372 + { 373 + DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(dev); 374 + DesignwarePCIEHost *host = designware_pcie_root_to_host(root); 375 + MemoryRegion *address_space = &host->pci.memory; 376 + PCIBridge *br = PCI_BRIDGE(dev); 377 + DesignwarePCIEViewport *viewport; 378 + /* 379 + * Dummy values used for initial configuration of MemoryRegions 380 + * that belong to a given viewport 381 + */ 382 + const hwaddr dummy_offset = 0; 383 + const uint64_t dummy_size = 4; 384 + size_t i; 385 + 386 + br->bus_name = "dw-pcie"; 387 + 388 + pci_set_word(dev->config + PCI_COMMAND, 389 + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 390 + 391 + pci_config_set_interrupt_pin(dev->config, 1); 392 + pci_bridge_initfn(dev, TYPE_PCIE_BUS); 393 + 394 + pcie_port_init_reg(dev); 395 + 396 + pcie_cap_init(dev, 0x70, PCI_EXP_TYPE_ROOT_PORT, 397 + 0, &error_fatal); 398 + 399 + msi_nonbroken = true; 400 + msi_init(dev, 0x50, 32, true, true, &error_fatal); 401 + 402 + for (i = 0; i < DESIGNWARE_PCIE_NUM_VIEWPORTS; i++) { 403 + MemoryRegion *source, *destination, *mem; 404 + const char *direction; 405 + char *name; 406 + 407 + viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][i]; 408 + viewport->inbound = true; 409 + viewport->base = 0x0000000000000000ULL; 410 + viewport->target = 0x0000000000000000ULL; 411 + viewport->limit = UINT32_MAX; 412 + viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM; 413 + 414 + source = &host->pci.address_space_root; 415 + destination = get_system_memory(); 416 + direction = "Inbound"; 417 + 418 + /* 419 + * Configure MemoryRegion implementing PCI -> CPU memory 420 + * access 421 + */ 422 + mem = &viewport->mem; 423 + name = designware_pcie_viewport_name(direction, i, "MEM"); 424 + memory_region_init_alias(mem, OBJECT(root), name, destination, 425 + dummy_offset, dummy_size); 426 + memory_region_add_subregion_overlap(source, dummy_offset, mem, -1); 427 + memory_region_set_enabled(mem, false); 428 + g_free(name); 429 + 430 + viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_OUTBOUND][i]; 431 + viewport->root = root; 432 + viewport->inbound = false; 433 + viewport->base = 0x0000000000000000ULL; 434 + viewport->target = 0x0000000000000000ULL; 435 + viewport->limit = UINT32_MAX; 436 + viewport->cr[0] = DESIGNWARE_PCIE_ATU_TYPE_MEM; 437 + 438 + destination = &host->pci.memory; 439 + direction = "Outbound"; 440 + source = get_system_memory(); 441 + 442 + /* 443 + * Configure MemoryRegion implementing CPU -> PCI memory 444 + * access 445 + */ 446 + mem = &viewport->mem; 447 + name = designware_pcie_viewport_name(direction, i, "MEM"); 448 + memory_region_init_alias(mem, OBJECT(root), name, destination, 449 + dummy_offset, dummy_size); 450 + memory_region_add_subregion(source, dummy_offset, mem); 451 + memory_region_set_enabled(mem, false); 452 + g_free(name); 453 + 454 + /* 455 + * Configure MemoryRegion implementing access to configuration 456 + * space 457 + */ 458 + mem = &viewport->cfg; 459 + name = designware_pcie_viewport_name(direction, i, "CFG"); 460 + memory_region_init_io(&viewport->cfg, OBJECT(root), 461 + &designware_pci_host_conf_ops, 462 + viewport, name, dummy_size); 463 + memory_region_add_subregion(source, dummy_offset, mem); 464 + memory_region_set_enabled(mem, false); 465 + g_free(name); 466 + } 467 + 468 + /* 469 + * If no inbound iATU windows are configured, HW defaults to 470 + * letting inbound TLPs to pass in. We emulate that by exlicitly 471 + * configuring first inbound window to cover all of target's 472 + * address space. 473 + * 474 + * NOTE: This will not work correctly for the case when first 475 + * configured inbound window is window 0 476 + */ 477 + viewport = &root->viewports[DESIGNWARE_PCIE_VIEWPORT_INBOUND][0]; 478 + viewport->cr[1] = DESIGNWARE_PCIE_ATU_ENABLE; 479 + designware_pcie_update_viewport(root, viewport); 480 + 481 + memory_region_init_io(&root->msi.iomem, OBJECT(root), 482 + &designware_pci_host_msi_ops, 483 + root, "pcie-msi", 0x4); 484 + /* 485 + * We initially place MSI interrupt I/O region a adress 0 and 486 + * disable it. It'll be later moved to correct offset and enabled 487 + * in designware_pcie_root_update_msi_mapping() as a part of 488 + * initialization done by guest OS 489 + */ 490 + memory_region_add_subregion(address_space, dummy_offset, &root->msi.iomem); 491 + memory_region_set_enabled(&root->msi.iomem, false); 492 + } 493 + 494 + static void designware_pcie_set_irq(void *opaque, int irq_num, int level) 495 + { 496 + DesignwarePCIEHost *host = DESIGNWARE_PCIE_HOST(opaque); 497 + 498 + qemu_set_irq(host->pci.irqs[irq_num], level); 499 + } 500 + 501 + static const char * 502 + designware_pcie_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus) 503 + { 504 + return "0000:00"; 505 + } 506 + 507 + static const VMStateDescription vmstate_designware_pcie_msi_bank = { 508 + .name = "designware-pcie-msi-bank", 509 + .version_id = 1, 510 + .minimum_version_id = 1, 511 + .fields = (VMStateField[]) { 512 + VMSTATE_UINT32(enable, DesignwarePCIEMSIBank), 513 + VMSTATE_UINT32(mask, DesignwarePCIEMSIBank), 514 + VMSTATE_UINT32(status, DesignwarePCIEMSIBank), 515 + VMSTATE_END_OF_LIST() 516 + } 517 + }; 518 + 519 + static const VMStateDescription vmstate_designware_pcie_msi = { 520 + .name = "designware-pcie-msi", 521 + .version_id = 1, 522 + .minimum_version_id = 1, 523 + .fields = (VMStateField[]) { 524 + VMSTATE_UINT64(base, DesignwarePCIEMSI), 525 + VMSTATE_STRUCT_ARRAY(intr, 526 + DesignwarePCIEMSI, 527 + DESIGNWARE_PCIE_NUM_MSI_BANKS, 528 + 1, 529 + vmstate_designware_pcie_msi_bank, 530 + DesignwarePCIEMSIBank), 531 + VMSTATE_END_OF_LIST() 532 + } 533 + }; 534 + 535 + static const VMStateDescription vmstate_designware_pcie_viewport = { 536 + .name = "designware-pcie-viewport", 537 + .version_id = 1, 538 + .minimum_version_id = 1, 539 + .fields = (VMStateField[]) { 540 + VMSTATE_UINT64(base, DesignwarePCIEViewport), 541 + VMSTATE_UINT64(target, DesignwarePCIEViewport), 542 + VMSTATE_UINT32(limit, DesignwarePCIEViewport), 543 + VMSTATE_UINT32_ARRAY(cr, DesignwarePCIEViewport, 2), 544 + VMSTATE_END_OF_LIST() 545 + } 546 + }; 547 + 548 + static const VMStateDescription vmstate_designware_pcie_root = { 549 + .name = "designware-pcie-root", 550 + .version_id = 1, 551 + .minimum_version_id = 1, 552 + .fields = (VMStateField[]) { 553 + VMSTATE_PCI_DEVICE(parent_obj, PCIBridge), 554 + VMSTATE_UINT32(atu_viewport, DesignwarePCIERoot), 555 + VMSTATE_STRUCT_2DARRAY(viewports, 556 + DesignwarePCIERoot, 557 + 2, 558 + DESIGNWARE_PCIE_NUM_VIEWPORTS, 559 + 1, 560 + vmstate_designware_pcie_viewport, 561 + DesignwarePCIEViewport), 562 + VMSTATE_STRUCT(msi, 563 + DesignwarePCIERoot, 564 + 1, 565 + vmstate_designware_pcie_msi, 566 + DesignwarePCIEMSI), 567 + VMSTATE_END_OF_LIST() 568 + } 569 + }; 570 + 571 + static void designware_pcie_root_class_init(ObjectClass *klass, void *data) 572 + { 573 + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 574 + DeviceClass *dc = DEVICE_CLASS(klass); 575 + 576 + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 577 + 578 + k->vendor_id = PCI_VENDOR_ID_SYNOPSYS; 579 + k->device_id = 0xABCD; 580 + k->revision = 0; 581 + k->class_id = PCI_CLASS_BRIDGE_PCI; 582 + k->is_bridge = true; 583 + k->exit = pci_bridge_exitfn; 584 + k->realize = designware_pcie_root_realize; 585 + k->config_read = designware_pcie_root_config_read; 586 + k->config_write = designware_pcie_root_config_write; 587 + 588 + dc->reset = pci_bridge_reset; 589 + /* 590 + * PCI-facing part of the host bridge, not usable without the 591 + * host-facing part, which can't be device_add'ed, yet. 592 + */ 593 + dc->user_creatable = false; 594 + dc->vmsd = &vmstate_designware_pcie_root; 595 + } 596 + 597 + static uint64_t designware_pcie_host_mmio_read(void *opaque, hwaddr addr, 598 + unsigned int size) 599 + { 600 + PCIHostState *pci = PCI_HOST_BRIDGE(opaque); 601 + PCIDevice *device = pci_find_device(pci->bus, 0, 0); 602 + 603 + return pci_host_config_read_common(device, 604 + addr, 605 + pci_config_size(device), 606 + size); 607 + } 608 + 609 + static void designware_pcie_host_mmio_write(void *opaque, hwaddr addr, 610 + uint64_t val, unsigned int size) 611 + { 612 + PCIHostState *pci = PCI_HOST_BRIDGE(opaque); 613 + PCIDevice *device = pci_find_device(pci->bus, 0, 0); 614 + 615 + return pci_host_config_write_common(device, 616 + addr, 617 + pci_config_size(device), 618 + val, size); 619 + } 620 + 621 + static const MemoryRegionOps designware_pci_mmio_ops = { 622 + .read = designware_pcie_host_mmio_read, 623 + .write = designware_pcie_host_mmio_write, 624 + .endianness = DEVICE_LITTLE_ENDIAN, 625 + .impl = { 626 + /* 627 + * Our device would not work correctly if the guest was doing 628 + * unaligned access. This might not be a limitation on the real 629 + * device but in practice there is no reason for a guest to access 630 + * this device unaligned. 631 + */ 632 + .min_access_size = 4, 633 + .max_access_size = 4, 634 + .unaligned = false, 635 + }, 636 + }; 637 + 638 + static AddressSpace *designware_pcie_host_set_iommu(PCIBus *bus, void *opaque, 639 + int devfn) 640 + { 641 + DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(opaque); 642 + 643 + return &s->pci.address_space; 644 + } 645 + 646 + static void designware_pcie_host_realize(DeviceState *dev, Error **errp) 647 + { 648 + PCIHostState *pci = PCI_HOST_BRIDGE(dev); 649 + DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(dev); 650 + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 651 + size_t i; 652 + 653 + for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) { 654 + sysbus_init_irq(sbd, &s->pci.irqs[i]); 655 + } 656 + 657 + memory_region_init_io(&s->mmio, 658 + OBJECT(s), 659 + &designware_pci_mmio_ops, 660 + s, 661 + "pcie.reg", 4 * 1024); 662 + sysbus_init_mmio(sbd, &s->mmio); 663 + 664 + memory_region_init(&s->pci.io, OBJECT(s), "pcie-pio", 16); 665 + memory_region_init(&s->pci.memory, OBJECT(s), 666 + "pcie-bus-memory", 667 + UINT64_MAX); 668 + 669 + pci->bus = pci_register_root_bus(dev, "pcie", 670 + designware_pcie_set_irq, 671 + pci_swizzle_map_irq_fn, 672 + s, 673 + &s->pci.memory, 674 + &s->pci.io, 675 + 0, 4, 676 + TYPE_PCIE_BUS); 677 + 678 + memory_region_init(&s->pci.address_space_root, 679 + OBJECT(s), 680 + "pcie-bus-address-space-root", 681 + UINT64_MAX); 682 + memory_region_add_subregion(&s->pci.address_space_root, 683 + 0x0, &s->pci.memory); 684 + address_space_init(&s->pci.address_space, 685 + &s->pci.address_space_root, 686 + "pcie-bus-address-space"); 687 + pci_setup_iommu(pci->bus, designware_pcie_host_set_iommu, s); 688 + 689 + qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus)); 690 + qdev_init_nofail(DEVICE(&s->root)); 691 + } 692 + 693 + static const VMStateDescription vmstate_designware_pcie_host = { 694 + .name = "designware-pcie-host", 695 + .version_id = 1, 696 + .minimum_version_id = 1, 697 + .fields = (VMStateField[]) { 698 + VMSTATE_STRUCT(root, 699 + DesignwarePCIEHost, 700 + 1, 701 + vmstate_designware_pcie_root, 702 + DesignwarePCIERoot), 703 + VMSTATE_END_OF_LIST() 704 + } 705 + }; 706 + 707 + static void designware_pcie_host_class_init(ObjectClass *klass, void *data) 708 + { 709 + DeviceClass *dc = DEVICE_CLASS(klass); 710 + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); 711 + 712 + hc->root_bus_path = designware_pcie_host_root_bus_path; 713 + dc->realize = designware_pcie_host_realize; 714 + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 715 + dc->fw_name = "pci"; 716 + dc->vmsd = &vmstate_designware_pcie_host; 717 + } 718 + 719 + static void designware_pcie_host_init(Object *obj) 720 + { 721 + DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(obj); 722 + DesignwarePCIERoot *root = &s->root; 723 + 724 + object_initialize(root, sizeof(*root), TYPE_DESIGNWARE_PCIE_ROOT); 725 + object_property_add_child(obj, "root", OBJECT(root), NULL); 726 + qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); 727 + qdev_prop_set_bit(DEVICE(root), "multifunction", false); 728 + } 729 + 730 + static const TypeInfo designware_pcie_root_info = { 731 + .name = TYPE_DESIGNWARE_PCIE_ROOT, 732 + .parent = TYPE_PCI_BRIDGE, 733 + .instance_size = sizeof(DesignwarePCIERoot), 734 + .class_init = designware_pcie_root_class_init, 735 + .interfaces = (InterfaceInfo[]) { 736 + { INTERFACE_PCIE_DEVICE }, 737 + { } 738 + }, 739 + }; 740 + 741 + static const TypeInfo designware_pcie_host_info = { 742 + .name = TYPE_DESIGNWARE_PCIE_HOST, 743 + .parent = TYPE_PCI_HOST_BRIDGE, 744 + .instance_size = sizeof(DesignwarePCIEHost), 745 + .instance_init = designware_pcie_host_init, 746 + .class_init = designware_pcie_host_class_init, 747 + }; 748 + 749 + static void designware_pcie_register(void) 750 + { 751 + type_register_static(&designware_pcie_root_info); 752 + type_register_static(&designware_pcie_host_info); 753 + } 754 + type_init(designware_pcie_register)
+1 -1
hw/sd/Makefile.objs
··· 1 1 common-obj-$(CONFIG_PL181) += pl181.o 2 2 common-obj-$(CONFIG_SSI_SD) += ssi-sd.o 3 - common-obj-$(CONFIG_SD) += sd.o core.o 3 + common-obj-$(CONFIG_SD) += sd.o core.o sdmmc-internal.o 4 4 common-obj-$(CONFIG_SDHCI) += sdhci.o 5 5 6 6 obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
+49 -6
hw/sd/sd.c
··· 120 120 qemu_irq readonly_cb; 121 121 qemu_irq inserted_cb; 122 122 QEMUTimer *ocr_power_timer; 123 + const char *proto_name; 123 124 bool enable; 124 125 uint8_t dat_lines; 125 126 bool cmd_line; ··· 866 867 sd->card_status &= ~CARD_IS_LOCKED; 867 868 } 868 869 869 - static sd_rsp_type_t sd_normal_command(SDState *sd, 870 - SDRequest req) 870 + static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) 871 871 { 872 872 uint32_t rca = 0x0000; 873 873 uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : req.arg; 874 874 875 - trace_sdcard_normal_command(req.cmd, req.arg, sd_state_name(sd->state)); 875 + /* CMD55 precedes an ACMD, so we are not interested in tracing it. 876 + * However there is no ACMD55, so we want to trace this particular case. 877 + */ 878 + if (req.cmd != 55 || sd->expecting_acmd) { 879 + trace_sdcard_normal_command(sd->proto_name, 880 + sd_cmd_name(req.cmd), req.cmd, 881 + req.arg, sd_state_name(sd->state)); 882 + } 876 883 877 884 /* Not interpreting this as an app command */ 878 885 sd->card_status &= ~APP_CMD; ··· 1162 1169 } 1163 1170 break; 1164 1171 1172 + case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */ 1173 + if (sd->state == sd_transfer_state) { 1174 + sd->state = sd_sendingdata_state; 1175 + sd->data_offset = 0; 1176 + return sd_r1; 1177 + } 1178 + break; 1179 + 1165 1180 case 23: /* CMD23: SET_BLOCK_COUNT */ 1166 1181 switch (sd->state) { 1167 1182 case sd_transfer_state: ··· 1450 1465 static sd_rsp_type_t sd_app_command(SDState *sd, 1451 1466 SDRequest req) 1452 1467 { 1453 - trace_sdcard_app_command(req.cmd, req.arg); 1468 + trace_sdcard_app_command(sd->proto_name, sd_acmd_name(req.cmd), 1469 + req.cmd, req.arg, sd_state_name(sd->state)); 1454 1470 sd->card_status |= APP_CMD; 1455 1471 switch (req.cmd) { 1456 1472 case 6: /* ACMD6: SET_BUS_WIDTH */ ··· 1765 1781 if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION)) 1766 1782 return; 1767 1783 1768 - trace_sdcard_write_data(sd->current_cmd, value); 1784 + trace_sdcard_write_data(sd->proto_name, 1785 + sd_acmd_name(sd->current_cmd), 1786 + sd->current_cmd, value); 1769 1787 switch (sd->current_cmd) { 1770 1788 case 24: /* CMD24: WRITE_SINGLE_BLOCK */ 1771 1789 sd->data[sd->data_offset ++] = value; ··· 1883 1901 } 1884 1902 } 1885 1903 1904 + #define SD_TUNING_BLOCK_SIZE 64 1905 + 1906 + static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { 1907 + /* See: Physical Layer Simplified Specification Version 3.01, Table 4-2 */ 1908 + 0xff, 0x0f, 0xff, 0x00, 0x0f, 0xfc, 0xc3, 0xcc, 1909 + 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, 1910 + 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, 1911 + 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, 1912 + 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, 1913 + 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, 1914 + 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, 1915 + 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, 1916 + }; 1917 + 1886 1918 uint8_t sd_read_data(SDState *sd) 1887 1919 { 1888 1920 /* TODO: Append CRCs */ ··· 1903 1935 1904 1936 io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len; 1905 1937 1906 - trace_sdcard_read_data(sd->current_cmd, io_len); 1938 + trace_sdcard_read_data(sd->proto_name, 1939 + sd_acmd_name(sd->current_cmd), 1940 + sd->current_cmd, io_len); 1907 1941 switch (sd->current_cmd) { 1908 1942 case 6: /* CMD6: SWITCH_FUNCTION */ 1909 1943 ret = sd->data[sd->data_offset ++]; ··· 1958 1992 } 1959 1993 } 1960 1994 } 1995 + break; 1996 + 1997 + case 19: /* CMD19: SEND_TUNING_BLOCK (SD) */ 1998 + if (sd->data_offset >= SD_TUNING_BLOCK_SIZE - 1) { 1999 + sd->state = sd_transfer_state; 2000 + } 2001 + ret = sd_tuning_block_pattern[sd->data_offset++]; 1961 2002 break; 1962 2003 1963 2004 case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ ··· 2028 2069 { 2029 2070 SDState *sd = SD_CARD(dev); 2030 2071 int ret; 2072 + 2073 + sd->proto_name = sd->spi ? "SPI" : "SD"; 2031 2074 2032 2075 if (sd->blk && blk_is_read_only(sd->blk)) { 2033 2076 error_setg(errp, "Cannot use read-only drive as SD card");
+2 -2
hw/sd/sdhci.c
··· 433 433 for (index = 0; index < blk_size; index++) { 434 434 data = sdbus_read_data(&s->sdbus); 435 435 if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) { 436 - /* Device is not in tunning */ 436 + /* Device is not in tuning */ 437 437 s->fifo_buffer[index] = data; 438 438 } 439 439 } 440 440 441 441 if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) { 442 - /* Device is in tunning */ 442 + /* Device is in tuning */ 443 443 s->hostctl2 &= ~R_SDHC_HOSTCTL2_EXECUTE_TUNING_MASK; 444 444 s->hostctl2 |= R_SDHC_HOSTCTL2_SAMPLING_CLKSEL_MASK; 445 445 s->prnsts &= ~(SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ |
+72
hw/sd/sdmmc-internal.c
··· 1 + /* 2 + * SD/MMC cards common helpers 3 + * 4 + * Copyright (c) 2018 Philippe Mathieu-Daudé <f4bug@amsat.org> 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 + * SPDX-License-Identifier: GPL-2.0-or-later 9 + */ 10 + 11 + #include "qemu/osdep.h" 12 + #include "sdmmc-internal.h" 13 + 14 + const char *sd_cmd_name(uint8_t cmd) 15 + { 16 + static const char *cmd_abbrev[SDMMC_CMD_MAX] = { 17 + [0] = "GO_IDLE_STATE", 18 + [2] = "ALL_SEND_CID", [3] = "SEND_RELATIVE_ADDR", 19 + [4] = "SET_DSR", [5] = "IO_SEND_OP_COND", 20 + [6] = "SWITCH_FUNC", [7] = "SELECT/DESELECT_CARD", 21 + [8] = "SEND_IF_COND", [9] = "SEND_CSD", 22 + [10] = "SEND_CID", [11] = "VOLTAGE_SWITCH", 23 + [12] = "STOP_TRANSMISSION", [13] = "SEND_STATUS", 24 + [15] = "GO_INACTIVE_STATE", 25 + [16] = "SET_BLOCKLEN", [17] = "READ_SINGLE_BLOCK", 26 + [18] = "READ_MULTIPLE_BLOCK", [19] = "SEND_TUNING_BLOCK", 27 + [20] = "SPEED_CLASS_CONTROL", [21] = "DPS_spec", 28 + [23] = "SET_BLOCK_COUNT", 29 + [24] = "WRITE_BLOCK", [25] = "WRITE_MULTIPLE_BLOCK", 30 + [26] = "MANUF_RSVD", [27] = "PROGRAM_CSD", 31 + [28] = "SET_WRITE_PROT", [29] = "CLR_WRITE_PROT", 32 + [30] = "SEND_WRITE_PROT", 33 + [32] = "ERASE_WR_BLK_START", [33] = "ERASE_WR_BLK_END", 34 + [34] = "SW_FUNC_RSVD", [35] = "SW_FUNC_RSVD", 35 + [36] = "SW_FUNC_RSVD", [37] = "SW_FUNC_RSVD", 36 + [38] = "ERASE", 37 + [40] = "DPS_spec", 38 + [42] = "LOCK_UNLOCK", [43] = "Q_MANAGEMENT", 39 + [44] = "Q_TASK_INFO_A", [45] = "Q_TASK_INFO_B", 40 + [46] = "Q_RD_TASK", [47] = "Q_WR_TASK", 41 + [48] = "READ_EXTR_SINGLE", [49] = "WRITE_EXTR_SINGLE", 42 + [50] = "SW_FUNC_RSVD", 43 + [52] = "IO_RW_DIRECT", [53] = "IO_RW_EXTENDED", 44 + [54] = "SDIO_RSVD", [55] = "APP_CMD", 45 + [56] = "GEN_CMD", [57] = "SW_FUNC_RSVD", 46 + [58] = "READ_EXTR_MULTI", [59] = "WRITE_EXTR_MULTI", 47 + [60] = "MANUF_RSVD", [61] = "MANUF_RSVD", 48 + [62] = "MANUF_RSVD", [63] = "MANUF_RSVD", 49 + }; 50 + return cmd_abbrev[cmd] ? cmd_abbrev[cmd] : "UNKNOWN_CMD"; 51 + } 52 + 53 + const char *sd_acmd_name(uint8_t cmd) 54 + { 55 + static const char *acmd_abbrev[SDMMC_CMD_MAX] = { 56 + [6] = "SET_BUS_WIDTH", 57 + [13] = "SD_STATUS", 58 + [14] = "DPS_spec", [15] = "DPS_spec", 59 + [16] = "DPS_spec", 60 + [18] = "SECU_spec", 61 + [22] = "SEND_NUM_WR_BLOCKS", [23] = "SET_WR_BLK_ERASE_COUNT", 62 + [41] = "SD_SEND_OP_COND", 63 + [42] = "SET_CLR_CARD_DETECT", 64 + [51] = "SEND_SCR", 65 + [52] = "SECU_spec", [53] = "SECU_spec", 66 + [54] = "SECU_spec", 67 + [56] = "SECU_spec", [57] = "SECU_spec", 68 + [58] = "SECU_spec", [59] = "SECU_spec", 69 + }; 70 + 71 + return acmd_abbrev[cmd] ? acmd_abbrev[cmd] : "UNKNOWN_ACMD"; 72 + }
+24
hw/sd/sdmmc-internal.h
··· 12 12 13 13 #define SDMMC_CMD_MAX 64 14 14 15 + /** 16 + * sd_cmd_name: 17 + * @cmd: A SD "normal" command, up to SDMMC_CMD_MAX. 18 + * 19 + * Returns a human-readable name describing the command. 20 + * The return value is always a static string which does not need 21 + * to be freed after use. 22 + * 23 + * Returns: The command name of @cmd or "UNKNOWN_CMD". 24 + */ 25 + const char *sd_cmd_name(uint8_t cmd); 26 + 27 + /** 28 + * sd_acmd_name: 29 + * @cmd: A SD "Application-Specific" command, up to SDMMC_CMD_MAX. 30 + * 31 + * Returns a human-readable name describing the application command. 32 + * The return value is always a static string which does not need 33 + * to be freed after use. 34 + * 35 + * Returns: The application command name of @cmd or "UNKNOWN_ACMD". 36 + */ 37 + const char *sd_acmd_name(uint8_t cmd); 38 + 15 39 #endif
+4 -4
hw/sd/trace-events
··· 24 24 sdhci_capareg(const char *desc, uint16_t val) "%s: %u" 25 25 26 26 # hw/sd/sd.c 27 - sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d arg 0x%08x (state %s)" 28 - sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x" 27 + sdcard_normal_command(const char *proto, const char *cmd_desc, uint8_t cmd, uint32_t arg, const char *state) "%s %20s/ CMD%02d arg 0x%08x (state %s)" 28 + sdcard_app_command(const char *proto, const char *acmd_desc, uint8_t acmd, uint32_t arg, const char *state) "%s %23s/ACMD%02d arg 0x%08x (state %s)" 29 29 sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)" 30 30 sdcard_powerup(void) "" 31 31 sdcard_inquiry_cmd41(void) "" ··· 39 39 sdcard_unlock(void) "" 40 40 sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" 41 41 sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x" 42 - sdcard_write_data(uint8_t cmd, uint8_t value) "CMD%02d value 0x%02x" 43 - sdcard_read_data(uint8_t cmd, int length) "CMD%02d len %d" 42 + sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, uint8_t value) "%s %20s/ CMD%02d value 0x%02x" 43 + sdcard_read_data(const char *proto, const char *cmd_desc, uint8_t cmd, int length) "%s %20s/ CMD%02d len %d" 44 44 sdcard_set_voltage(uint16_t millivolts) "%u mV" 45 45 46 46 # hw/sd/milkymist-memcard.c
+222
include/hw/arm/fsl-imx7.h
··· 1 + /* 2 + * Copyright (c) 2018, Impinj, Inc. 3 + * 4 + * i.MX7 SoC definitions 5 + * 6 + * Author: Andrey Smirnov <andrew.smirnov@gmail.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + */ 18 + 19 + #ifndef FSL_IMX7_H 20 + #define FSL_IMX7_H 21 + 22 + #include "hw/arm/arm.h" 23 + #include "hw/cpu/a15mpcore.h" 24 + #include "hw/intc/imx_gpcv2.h" 25 + #include "hw/misc/imx7_ccm.h" 26 + #include "hw/misc/imx7_snvs.h" 27 + #include "hw/misc/imx7_gpr.h" 28 + #include "hw/misc/imx6_src.h" 29 + #include "hw/misc/imx2_wdt.h" 30 + #include "hw/gpio/imx_gpio.h" 31 + #include "hw/char/imx_serial.h" 32 + #include "hw/timer/imx_gpt.h" 33 + #include "hw/timer/imx_epit.h" 34 + #include "hw/i2c/imx_i2c.h" 35 + #include "hw/gpio/imx_gpio.h" 36 + #include "hw/sd/sdhci.h" 37 + #include "hw/ssi/imx_spi.h" 38 + #include "hw/net/imx_fec.h" 39 + #include "hw/pci-host/designware.h" 40 + #include "hw/usb/chipidea.h" 41 + #include "exec/memory.h" 42 + #include "cpu.h" 43 + 44 + #define TYPE_FSL_IMX7 "fsl,imx7" 45 + #define FSL_IMX7(obj) OBJECT_CHECK(FslIMX7State, (obj), TYPE_FSL_IMX7) 46 + 47 + enum FslIMX7Configuration { 48 + FSL_IMX7_NUM_CPUS = 2, 49 + FSL_IMX7_NUM_UARTS = 7, 50 + FSL_IMX7_NUM_ETHS = 2, 51 + FSL_IMX7_ETH_NUM_TX_RINGS = 3, 52 + FSL_IMX7_NUM_USDHCS = 3, 53 + FSL_IMX7_NUM_WDTS = 4, 54 + FSL_IMX7_NUM_GPTS = 4, 55 + FSL_IMX7_NUM_IOMUXCS = 2, 56 + FSL_IMX7_NUM_GPIOS = 7, 57 + FSL_IMX7_NUM_I2CS = 4, 58 + FSL_IMX7_NUM_ECSPIS = 4, 59 + FSL_IMX7_NUM_USBS = 3, 60 + FSL_IMX7_NUM_ADCS = 2, 61 + }; 62 + 63 + typedef struct FslIMX7State { 64 + /*< private >*/ 65 + DeviceState parent_obj; 66 + 67 + /*< public >*/ 68 + ARMCPU cpu[FSL_IMX7_NUM_CPUS]; 69 + A15MPPrivState a7mpcore; 70 + IMXGPTState gpt[FSL_IMX7_NUM_GPTS]; 71 + IMXGPIOState gpio[FSL_IMX7_NUM_GPIOS]; 72 + IMX7CCMState ccm; 73 + IMX7AnalogState analog; 74 + IMX7SNVSState snvs; 75 + IMXGPCv2State gpcv2; 76 + IMXSPIState spi[FSL_IMX7_NUM_ECSPIS]; 77 + IMXI2CState i2c[FSL_IMX7_NUM_I2CS]; 78 + IMXSerialState uart[FSL_IMX7_NUM_UARTS]; 79 + IMXFECState eth[FSL_IMX7_NUM_ETHS]; 80 + SDHCIState usdhc[FSL_IMX7_NUM_USDHCS]; 81 + IMX2WdtState wdt[FSL_IMX7_NUM_WDTS]; 82 + IMX7GPRState gpr; 83 + ChipideaState usb[FSL_IMX7_NUM_USBS]; 84 + DesignwarePCIEHost pcie; 85 + } FslIMX7State; 86 + 87 + enum FslIMX7MemoryMap { 88 + FSL_IMX7_MMDC_ADDR = 0x80000000, 89 + FSL_IMX7_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL, 90 + 91 + FSL_IMX7_GPIO1_ADDR = 0x30200000, 92 + FSL_IMX7_GPIO2_ADDR = 0x30210000, 93 + FSL_IMX7_GPIO3_ADDR = 0x30220000, 94 + FSL_IMX7_GPIO4_ADDR = 0x30230000, 95 + FSL_IMX7_GPIO5_ADDR = 0x30240000, 96 + FSL_IMX7_GPIO6_ADDR = 0x30250000, 97 + FSL_IMX7_GPIO7_ADDR = 0x30260000, 98 + 99 + FSL_IMX7_IOMUXC_LPSR_GPR_ADDR = 0x30270000, 100 + 101 + FSL_IMX7_WDOG1_ADDR = 0x30280000, 102 + FSL_IMX7_WDOG2_ADDR = 0x30290000, 103 + FSL_IMX7_WDOG3_ADDR = 0x302A0000, 104 + FSL_IMX7_WDOG4_ADDR = 0x302B0000, 105 + 106 + FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000, 107 + 108 + FSL_IMX7_GPT1_ADDR = 0x302D0000, 109 + FSL_IMX7_GPT2_ADDR = 0x302E0000, 110 + FSL_IMX7_GPT3_ADDR = 0x302F0000, 111 + FSL_IMX7_GPT4_ADDR = 0x30300000, 112 + 113 + FSL_IMX7_IOMUXC_ADDR = 0x30330000, 114 + FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000, 115 + FSL_IMX7_IOMUXCn_SIZE = 0x1000, 116 + 117 + FSL_IMX7_ANALOG_ADDR = 0x30360000, 118 + FSL_IMX7_SNVS_ADDR = 0x30370000, 119 + FSL_IMX7_CCM_ADDR = 0x30380000, 120 + 121 + FSL_IMX7_SRC_ADDR = 0x30390000, 122 + FSL_IMX7_SRC_SIZE = 0x1000, 123 + 124 + FSL_IMX7_ADC1_ADDR = 0x30610000, 125 + FSL_IMX7_ADC2_ADDR = 0x30620000, 126 + FSL_IMX7_ADCn_SIZE = 0x1000, 127 + 128 + FSL_IMX7_GPC_ADDR = 0x303A0000, 129 + 130 + FSL_IMX7_I2C1_ADDR = 0x30A20000, 131 + FSL_IMX7_I2C2_ADDR = 0x30A30000, 132 + FSL_IMX7_I2C3_ADDR = 0x30A40000, 133 + FSL_IMX7_I2C4_ADDR = 0x30A50000, 134 + 135 + FSL_IMX7_ECSPI1_ADDR = 0x30820000, 136 + FSL_IMX7_ECSPI2_ADDR = 0x30830000, 137 + FSL_IMX7_ECSPI3_ADDR = 0x30840000, 138 + FSL_IMX7_ECSPI4_ADDR = 0x30630000, 139 + 140 + FSL_IMX7_LCDIF_ADDR = 0x30730000, 141 + FSL_IMX7_LCDIF_SIZE = 0x1000, 142 + 143 + FSL_IMX7_UART1_ADDR = 0x30860000, 144 + /* 145 + * Some versions of the reference manual claim that UART2 is @ 146 + * 0x30870000, but experiments with HW + DT files in upstream 147 + * Linux kernel show that not to be true and that block is 148 + * acutally located @ 0x30890000 149 + */ 150 + FSL_IMX7_UART2_ADDR = 0x30890000, 151 + FSL_IMX7_UART3_ADDR = 0x30880000, 152 + FSL_IMX7_UART4_ADDR = 0x30A60000, 153 + FSL_IMX7_UART5_ADDR = 0x30A70000, 154 + FSL_IMX7_UART6_ADDR = 0x30A80000, 155 + FSL_IMX7_UART7_ADDR = 0x30A90000, 156 + 157 + FSL_IMX7_ENET1_ADDR = 0x30BE0000, 158 + FSL_IMX7_ENET2_ADDR = 0x30BF0000, 159 + 160 + FSL_IMX7_USB1_ADDR = 0x30B10000, 161 + FSL_IMX7_USBMISC1_ADDR = 0x30B10200, 162 + FSL_IMX7_USB2_ADDR = 0x30B20000, 163 + FSL_IMX7_USBMISC2_ADDR = 0x30B20200, 164 + FSL_IMX7_USB3_ADDR = 0x30B30000, 165 + FSL_IMX7_USBMISC3_ADDR = 0x30B30200, 166 + FSL_IMX7_USBMISCn_SIZE = 0x200, 167 + 168 + FSL_IMX7_USDHC1_ADDR = 0x30B40000, 169 + FSL_IMX7_USDHC2_ADDR = 0x30B50000, 170 + FSL_IMX7_USDHC3_ADDR = 0x30B60000, 171 + 172 + FSL_IMX7_SDMA_ADDR = 0x30BD0000, 173 + FSL_IMX7_SDMA_SIZE = 0x1000, 174 + 175 + FSL_IMX7_A7MPCORE_ADDR = 0x31000000, 176 + FSL_IMX7_A7MPCORE_DAP_ADDR = 0x30000000, 177 + 178 + FSL_IMX7_PCIE_REG_ADDR = 0x33800000, 179 + FSL_IMX7_PCIE_REG_SIZE = 16 * 1024, 180 + 181 + FSL_IMX7_GPR_ADDR = 0x30340000, 182 + }; 183 + 184 + enum FslIMX7IRQs { 185 + FSL_IMX7_USDHC1_IRQ = 22, 186 + FSL_IMX7_USDHC2_IRQ = 23, 187 + FSL_IMX7_USDHC3_IRQ = 24, 188 + 189 + FSL_IMX7_UART1_IRQ = 26, 190 + FSL_IMX7_UART2_IRQ = 27, 191 + FSL_IMX7_UART3_IRQ = 28, 192 + FSL_IMX7_UART4_IRQ = 29, 193 + FSL_IMX7_UART5_IRQ = 30, 194 + FSL_IMX7_UART6_IRQ = 16, 195 + 196 + FSL_IMX7_ECSPI1_IRQ = 31, 197 + FSL_IMX7_ECSPI2_IRQ = 32, 198 + FSL_IMX7_ECSPI3_IRQ = 33, 199 + FSL_IMX7_ECSPI4_IRQ = 34, 200 + 201 + FSL_IMX7_I2C1_IRQ = 35, 202 + FSL_IMX7_I2C2_IRQ = 36, 203 + FSL_IMX7_I2C3_IRQ = 37, 204 + FSL_IMX7_I2C4_IRQ = 38, 205 + 206 + FSL_IMX7_USB1_IRQ = 43, 207 + FSL_IMX7_USB2_IRQ = 42, 208 + FSL_IMX7_USB3_IRQ = 40, 209 + 210 + FSL_IMX7_PCI_INTA_IRQ = 122, 211 + FSL_IMX7_PCI_INTB_IRQ = 123, 212 + FSL_IMX7_PCI_INTC_IRQ = 124, 213 + FSL_IMX7_PCI_INTD_IRQ = 125, 214 + 215 + FSL_IMX7_UART7_IRQ = 126, 216 + 217 + #define FSL_IMX7_ENET_IRQ(i, n) ((n) + ((i) ? 100 : 118)) 218 + 219 + FSL_IMX7_MAX_IRQ = 128, 220 + }; 221 + 222 + #endif /* FSL_IMX7_H */
+102
include/hw/pci-host/designware.h
··· 1 + /* 2 + * Copyright (c) 2017, Impinj, Inc. 3 + * 4 + * Designware PCIe IP block emulation 5 + * 6 + * This library is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU Lesser General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This library 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 GNU 14 + * Lesser General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU Lesser General Public 17 + * License along with this library; if not, see 18 + * <http://www.gnu.org/licenses/>. 19 + */ 20 + 21 + #ifndef DESIGNWARE_H 22 + #define DESIGNWARE_H 23 + 24 + #include "hw/hw.h" 25 + #include "hw/sysbus.h" 26 + #include "hw/pci/pci.h" 27 + #include "hw/pci/pci_bus.h" 28 + #include "hw/pci/pcie_host.h" 29 + #include "hw/pci/pci_bridge.h" 30 + 31 + #define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host" 32 + #define DESIGNWARE_PCIE_HOST(obj) \ 33 + OBJECT_CHECK(DesignwarePCIEHost, (obj), TYPE_DESIGNWARE_PCIE_HOST) 34 + 35 + #define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root" 36 + #define DESIGNWARE_PCIE_ROOT(obj) \ 37 + OBJECT_CHECK(DesignwarePCIERoot, (obj), TYPE_DESIGNWARE_PCIE_ROOT) 38 + 39 + struct DesignwarePCIERoot; 40 + typedef struct DesignwarePCIERoot DesignwarePCIERoot; 41 + 42 + typedef struct DesignwarePCIEViewport { 43 + DesignwarePCIERoot *root; 44 + 45 + MemoryRegion cfg; 46 + MemoryRegion mem; 47 + 48 + uint64_t base; 49 + uint64_t target; 50 + uint32_t limit; 51 + uint32_t cr[2]; 52 + 53 + bool inbound; 54 + } DesignwarePCIEViewport; 55 + 56 + typedef struct DesignwarePCIEMSIBank { 57 + uint32_t enable; 58 + uint32_t mask; 59 + uint32_t status; 60 + } DesignwarePCIEMSIBank; 61 + 62 + typedef struct DesignwarePCIEMSI { 63 + uint64_t base; 64 + MemoryRegion iomem; 65 + 66 + #define DESIGNWARE_PCIE_NUM_MSI_BANKS 1 67 + 68 + DesignwarePCIEMSIBank intr[DESIGNWARE_PCIE_NUM_MSI_BANKS]; 69 + } DesignwarePCIEMSI; 70 + 71 + struct DesignwarePCIERoot { 72 + PCIBridge parent_obj; 73 + 74 + uint32_t atu_viewport; 75 + 76 + #define DESIGNWARE_PCIE_VIEWPORT_OUTBOUND 0 77 + #define DESIGNWARE_PCIE_VIEWPORT_INBOUND 1 78 + #define DESIGNWARE_PCIE_NUM_VIEWPORTS 4 79 + 80 + DesignwarePCIEViewport viewports[2][DESIGNWARE_PCIE_NUM_VIEWPORTS]; 81 + DesignwarePCIEMSI msi; 82 + }; 83 + 84 + typedef struct DesignwarePCIEHost { 85 + PCIHostState parent_obj; 86 + 87 + DesignwarePCIERoot root; 88 + 89 + struct { 90 + AddressSpace address_space; 91 + MemoryRegion address_space_root; 92 + 93 + MemoryRegion memory; 94 + MemoryRegion io; 95 + 96 + qemu_irq irqs[4]; 97 + } pci; 98 + 99 + MemoryRegion mmio; 100 + } DesignwarePCIEHost; 101 + 102 + #endif /* DESIGNWARE_H */
+2
include/hw/pci/pci_ids.h
··· 269 269 #define PCI_VENDOR_ID_VMWARE 0x15ad 270 270 #define PCI_DEVICE_ID_VMWARE_PVRDMA 0x0820 271 271 272 + #define PCI_VENDOR_ID_SYNOPSYS 0x16C3 273 + 272 274 #endif
+3
linux-user/aarch64/target_syscall.h
··· 19 19 #define TARGET_MLOCKALL_MCL_CURRENT 1 20 20 #define TARGET_MLOCKALL_MCL_FUTURE 2 21 21 22 + #define TARGET_PR_SVE_SET_VL 50 23 + #define TARGET_PR_SVE_GET_VL 51 24 + 22 25 #endif /* AARCH64_TARGET_SYSCALL_H */
+343 -66
linux-user/signal.c
··· 1446 1446 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */ 1447 1447 }; 1448 1448 1449 - /* 1450 - * Auxiliary context saved in the sigcontext.__reserved array. Not exported to 1451 - * user space as it will change with the addition of new context. User space 1452 - * should check the magic/size information. 1453 - */ 1454 - struct target_aux_context { 1455 - struct target_fpsimd_context fpsimd; 1456 - /* additional context to be added before "end" */ 1457 - struct target_aarch64_ctx end; 1449 + #define TARGET_EXTRA_MAGIC 0x45585401 1450 + 1451 + struct target_extra_context { 1452 + struct target_aarch64_ctx head; 1453 + uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */ 1454 + uint32_t size; /* size in bytes of the extra space */ 1455 + uint32_t reserved[3]; 1458 1456 }; 1459 1457 1458 + #define TARGET_SVE_MAGIC 0x53564501 1459 + 1460 + struct target_sve_context { 1461 + struct target_aarch64_ctx head; 1462 + uint16_t vl; 1463 + uint16_t reserved[3]; 1464 + /* The actual SVE data immediately follows. It is layed out 1465 + * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of 1466 + * the original struct pointer. 1467 + */ 1468 + }; 1469 + 1470 + #define TARGET_SVE_VQ_BYTES 16 1471 + 1472 + #define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES) 1473 + #define TARGET_SVE_SIG_PREG_SIZE(VQ) ((VQ) * (TARGET_SVE_VQ_BYTES / 8)) 1474 + 1475 + #define TARGET_SVE_SIG_REGS_OFFSET \ 1476 + QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES) 1477 + #define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \ 1478 + (TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N)) 1479 + #define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \ 1480 + (TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N)) 1481 + #define TARGET_SVE_SIG_FFR_OFFSET(VQ) \ 1482 + (TARGET_SVE_SIG_PREG_OFFSET(VQ, 16)) 1483 + #define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \ 1484 + (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17)) 1485 + 1460 1486 struct target_rt_sigframe { 1461 1487 struct target_siginfo info; 1462 1488 struct target_ucontext uc; 1489 + }; 1490 + 1491 + struct target_rt_frame_record { 1463 1492 uint64_t fp; 1464 1493 uint64_t lr; 1465 1494 uint32_t tramp[2]; 1466 1495 }; 1467 1496 1468 - static int target_setup_sigframe(struct target_rt_sigframe *sf, 1469 - CPUARMState *env, target_sigset_t *set) 1497 + static void target_setup_general_frame(struct target_rt_sigframe *sf, 1498 + CPUARMState *env, target_sigset_t *set) 1470 1499 { 1471 1500 int i; 1472 - struct target_aux_context *aux = 1473 - (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved; 1501 + 1502 + __put_user(0, &sf->uc.tuc_flags); 1503 + __put_user(0, &sf->uc.tuc_link); 1474 1504 1475 - /* set up the stack frame for unwinding */ 1476 - __put_user(env->xregs[29], &sf->fp); 1477 - __put_user(env->xregs[30], &sf->lr); 1505 + __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp); 1506 + __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags); 1507 + __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size); 1478 1508 1479 1509 for (i = 0; i < 31; i++) { 1480 1510 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]); ··· 1488 1518 for (i = 0; i < TARGET_NSIG_WORDS; i++) { 1489 1519 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]); 1490 1520 } 1521 + } 1522 + 1523 + static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd, 1524 + CPUARMState *env) 1525 + { 1526 + int i; 1527 + 1528 + __put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic); 1529 + __put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size); 1530 + __put_user(vfp_get_fpsr(env), &fpsimd->fpsr); 1531 + __put_user(vfp_get_fpcr(env), &fpsimd->fpcr); 1491 1532 1492 1533 for (i = 0; i < 32; i++) { 1493 1534 uint64_t *q = aa64_vfp_qreg(env, i); 1494 1535 #ifdef TARGET_WORDS_BIGENDIAN 1495 - __put_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]); 1496 - __put_user(q[1], &aux->fpsimd.vregs[i * 2]); 1536 + __put_user(q[0], &fpsimd->vregs[i * 2 + 1]); 1537 + __put_user(q[1], &fpsimd->vregs[i * 2]); 1497 1538 #else 1498 - __put_user(q[0], &aux->fpsimd.vregs[i * 2]); 1499 - __put_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]); 1539 + __put_user(q[0], &fpsimd->vregs[i * 2]); 1540 + __put_user(q[1], &fpsimd->vregs[i * 2 + 1]); 1500 1541 #endif 1501 1542 } 1502 - __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr); 1503 - __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr); 1504 - __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic); 1505 - __put_user(sizeof(struct target_fpsimd_context), 1506 - &aux->fpsimd.head.size); 1543 + } 1544 + 1545 + static void target_setup_extra_record(struct target_extra_context *extra, 1546 + uint64_t datap, uint32_t extra_size) 1547 + { 1548 + __put_user(TARGET_EXTRA_MAGIC, &extra->head.magic); 1549 + __put_user(sizeof(struct target_extra_context), &extra->head.size); 1550 + __put_user(datap, &extra->datap); 1551 + __put_user(extra_size, &extra->size); 1552 + } 1553 + 1554 + static void target_setup_end_record(struct target_aarch64_ctx *end) 1555 + { 1556 + __put_user(0, &end->magic); 1557 + __put_user(0, &end->size); 1558 + } 1559 + 1560 + static void target_setup_sve_record(struct target_sve_context *sve, 1561 + CPUARMState *env, int vq, int size) 1562 + { 1563 + int i, j; 1507 1564 1508 - /* set the "end" magic */ 1509 - __put_user(0, &aux->end.magic); 1510 - __put_user(0, &aux->end.size); 1565 + __put_user(TARGET_SVE_MAGIC, &sve->head.magic); 1566 + __put_user(size, &sve->head.size); 1567 + __put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl); 1511 1568 1512 - return 0; 1569 + /* Note that SVE regs are stored as a byte stream, with each byte element 1570 + * at a subsequent address. This corresponds to a little-endian store 1571 + * of our 64-bit hunks. 1572 + */ 1573 + for (i = 0; i < 32; ++i) { 1574 + uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i); 1575 + for (j = 0; j < vq * 2; ++j) { 1576 + __put_user_e(env->vfp.zregs[i].d[j], z + j, le); 1577 + } 1578 + } 1579 + for (i = 0; i <= 16; ++i) { 1580 + uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i); 1581 + for (j = 0; j < vq; ++j) { 1582 + uint64_t r = env->vfp.pregs[i].p[j >> 2]; 1583 + __put_user_e(r >> ((j & 3) * 16), p + j, le); 1584 + } 1585 + } 1513 1586 } 1514 1587 1515 - static int target_restore_sigframe(CPUARMState *env, 1516 - struct target_rt_sigframe *sf) 1588 + static void target_restore_general_frame(CPUARMState *env, 1589 + struct target_rt_sigframe *sf) 1517 1590 { 1518 1591 sigset_t set; 1592 + uint64_t pstate; 1519 1593 int i; 1520 - struct target_aux_context *aux = 1521 - (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved; 1522 - uint32_t magic, size, fpsr, fpcr; 1523 - uint64_t pstate; 1524 1594 1525 1595 target_to_host_sigset(&set, &sf->uc.tuc_sigmask); 1526 1596 set_sigmask(&set); ··· 1533 1603 __get_user(env->pc, &sf->uc.tuc_mcontext.pc); 1534 1604 __get_user(pstate, &sf->uc.tuc_mcontext.pstate); 1535 1605 pstate_write(env, pstate); 1606 + } 1536 1607 1537 - __get_user(magic, &aux->fpsimd.head.magic); 1538 - __get_user(size, &aux->fpsimd.head.size); 1608 + static void target_restore_fpsimd_record(CPUARMState *env, 1609 + struct target_fpsimd_context *fpsimd) 1610 + { 1611 + uint32_t fpsr, fpcr; 1612 + int i; 1539 1613 1540 - if (magic != TARGET_FPSIMD_MAGIC 1541 - || size != sizeof(struct target_fpsimd_context)) { 1542 - return 1; 1543 - } 1614 + __get_user(fpsr, &fpsimd->fpsr); 1615 + vfp_set_fpsr(env, fpsr); 1616 + __get_user(fpcr, &fpsimd->fpcr); 1617 + vfp_set_fpcr(env, fpcr); 1544 1618 1545 1619 for (i = 0; i < 32; i++) { 1546 1620 uint64_t *q = aa64_vfp_qreg(env, i); 1547 1621 #ifdef TARGET_WORDS_BIGENDIAN 1548 - __get_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]); 1549 - __get_user(q[1], &aux->fpsimd.vregs[i * 2]); 1622 + __get_user(q[0], &fpsimd->vregs[i * 2 + 1]); 1623 + __get_user(q[1], &fpsimd->vregs[i * 2]); 1550 1624 #else 1551 - __get_user(q[0], &aux->fpsimd.vregs[i * 2]); 1552 - __get_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]); 1625 + __get_user(q[0], &fpsimd->vregs[i * 2]); 1626 + __get_user(q[1], &fpsimd->vregs[i * 2 + 1]); 1553 1627 #endif 1554 1628 } 1555 - __get_user(fpsr, &aux->fpsimd.fpsr); 1556 - vfp_set_fpsr(env, fpsr); 1557 - __get_user(fpcr, &aux->fpsimd.fpcr); 1558 - vfp_set_fpcr(env, fpcr); 1629 + } 1630 + 1631 + static void target_restore_sve_record(CPUARMState *env, 1632 + struct target_sve_context *sve, int vq) 1633 + { 1634 + int i, j; 1635 + 1636 + /* Note that SVE regs are stored as a byte stream, with each byte element 1637 + * at a subsequent address. This corresponds to a little-endian load 1638 + * of our 64-bit hunks. 1639 + */ 1640 + for (i = 0; i < 32; ++i) { 1641 + uint64_t *z = (void *)sve + TARGET_SVE_SIG_ZREG_OFFSET(vq, i); 1642 + for (j = 0; j < vq * 2; ++j) { 1643 + __get_user_e(env->vfp.zregs[i].d[j], z + j, le); 1644 + } 1645 + } 1646 + for (i = 0; i <= 16; ++i) { 1647 + uint16_t *p = (void *)sve + TARGET_SVE_SIG_PREG_OFFSET(vq, i); 1648 + for (j = 0; j < vq; ++j) { 1649 + uint16_t r; 1650 + __get_user_e(r, p + j, le); 1651 + if (j & 3) { 1652 + env->vfp.pregs[i].p[j >> 2] |= (uint64_t)r << ((j & 3) * 16); 1653 + } else { 1654 + env->vfp.pregs[i].p[j >> 2] = r; 1655 + } 1656 + } 1657 + } 1658 + } 1659 + 1660 + static int target_restore_sigframe(CPUARMState *env, 1661 + struct target_rt_sigframe *sf) 1662 + { 1663 + struct target_aarch64_ctx *ctx, *extra = NULL; 1664 + struct target_fpsimd_context *fpsimd = NULL; 1665 + struct target_sve_context *sve = NULL; 1666 + uint64_t extra_datap = 0; 1667 + bool used_extra = false; 1668 + bool err = false; 1669 + int vq = 0, sve_size = 0; 1670 + 1671 + target_restore_general_frame(env, sf); 1672 + 1673 + ctx = (struct target_aarch64_ctx *)sf->uc.tuc_mcontext.__reserved; 1674 + while (ctx) { 1675 + uint32_t magic, size, extra_size; 1676 + 1677 + __get_user(magic, &ctx->magic); 1678 + __get_user(size, &ctx->size); 1679 + switch (magic) { 1680 + case 0: 1681 + if (size != 0) { 1682 + err = true; 1683 + goto exit; 1684 + } 1685 + if (used_extra) { 1686 + ctx = NULL; 1687 + } else { 1688 + ctx = extra; 1689 + used_extra = true; 1690 + } 1691 + continue; 1692 + 1693 + case TARGET_FPSIMD_MAGIC: 1694 + if (fpsimd || size != sizeof(struct target_fpsimd_context)) { 1695 + err = true; 1696 + goto exit; 1697 + } 1698 + fpsimd = (struct target_fpsimd_context *)ctx; 1699 + break; 1700 + 1701 + case TARGET_SVE_MAGIC: 1702 + if (arm_feature(env, ARM_FEATURE_SVE)) { 1703 + vq = (env->vfp.zcr_el[1] & 0xf) + 1; 1704 + sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16); 1705 + if (!sve && size == sve_size) { 1706 + sve = (struct target_sve_context *)ctx; 1707 + break; 1708 + } 1709 + } 1710 + err = true; 1711 + goto exit; 1559 1712 1560 - return 0; 1713 + case TARGET_EXTRA_MAGIC: 1714 + if (extra || size != sizeof(struct target_extra_context)) { 1715 + err = true; 1716 + goto exit; 1717 + } 1718 + __get_user(extra_datap, 1719 + &((struct target_extra_context *)ctx)->datap); 1720 + __get_user(extra_size, 1721 + &((struct target_extra_context *)ctx)->size); 1722 + extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0); 1723 + break; 1724 + 1725 + default: 1726 + /* Unknown record -- we certainly didn't generate it. 1727 + * Did we in fact get out of sync? 1728 + */ 1729 + err = true; 1730 + goto exit; 1731 + } 1732 + ctx = (void *)ctx + size; 1733 + } 1734 + 1735 + /* Require FPSIMD always. */ 1736 + if (fpsimd) { 1737 + target_restore_fpsimd_record(env, fpsimd); 1738 + } else { 1739 + err = true; 1740 + } 1741 + 1742 + /* SVE data, if present, overwrites FPSIMD data. */ 1743 + if (sve) { 1744 + target_restore_sve_record(env, sve, vq); 1745 + } 1746 + 1747 + exit: 1748 + unlock_user(extra, extra_datap, 0); 1749 + return err; 1561 1750 } 1562 1751 1563 - static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env) 1752 + static abi_ulong get_sigframe(struct target_sigaction *ka, 1753 + CPUARMState *env, int size) 1564 1754 { 1565 1755 abi_ulong sp; 1566 1756 ··· 1573 1763 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; 1574 1764 } 1575 1765 1576 - sp = (sp - sizeof(struct target_rt_sigframe)) & ~15; 1766 + sp = (sp - size) & ~15; 1577 1767 1578 1768 return sp; 1579 1769 } 1580 1770 1771 + typedef struct { 1772 + int total_size; 1773 + int extra_base; 1774 + int extra_size; 1775 + int std_end_ofs; 1776 + int extra_ofs; 1777 + int extra_end_ofs; 1778 + } target_sigframe_layout; 1779 + 1780 + static int alloc_sigframe_space(int this_size, target_sigframe_layout *l) 1781 + { 1782 + /* Make sure there will always be space for the end marker. */ 1783 + const int std_size = sizeof(struct target_rt_sigframe) 1784 + - sizeof(struct target_aarch64_ctx); 1785 + int this_loc = l->total_size; 1786 + 1787 + if (l->extra_base) { 1788 + /* Once we have begun an extra space, all allocations go there. */ 1789 + l->extra_size += this_size; 1790 + } else if (this_size + this_loc > std_size) { 1791 + /* This allocation does not fit in the standard space. */ 1792 + /* Allocate the extra record. */ 1793 + l->extra_ofs = this_loc; 1794 + l->total_size += sizeof(struct target_extra_context); 1795 + 1796 + /* Allocate the standard end record. */ 1797 + l->std_end_ofs = l->total_size; 1798 + l->total_size += sizeof(struct target_aarch64_ctx); 1799 + 1800 + /* Allocate the requested record. */ 1801 + l->extra_base = this_loc = l->total_size; 1802 + l->extra_size = this_size; 1803 + } 1804 + l->total_size += this_size; 1805 + 1806 + return this_loc; 1807 + } 1808 + 1581 1809 static void target_setup_frame(int usig, struct target_sigaction *ka, 1582 1810 target_siginfo_t *info, target_sigset_t *set, 1583 1811 CPUARMState *env) 1584 1812 { 1813 + target_sigframe_layout layout = { 1814 + /* Begin with the size pointing to the reserved space. */ 1815 + .total_size = offsetof(struct target_rt_sigframe, 1816 + uc.tuc_mcontext.__reserved), 1817 + }; 1818 + int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0; 1585 1819 struct target_rt_sigframe *frame; 1820 + struct target_rt_frame_record *fr; 1586 1821 abi_ulong frame_addr, return_addr; 1587 1822 1588 - frame_addr = get_sigframe(ka, env); 1823 + /* FPSIMD record is always in the standard space. */ 1824 + fpsimd_ofs = alloc_sigframe_space(sizeof(struct target_fpsimd_context), 1825 + &layout); 1826 + 1827 + /* SVE state needs saving only if it exists. */ 1828 + if (arm_feature(env, ARM_FEATURE_SVE)) { 1829 + vq = (env->vfp.zcr_el[1] & 0xf) + 1; 1830 + sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16); 1831 + sve_ofs = alloc_sigframe_space(sve_size, &layout); 1832 + } 1833 + 1834 + if (layout.extra_ofs) { 1835 + /* Reserve space for the extra end marker. The standard end marker 1836 + * will have been allocated when we allocated the extra record. 1837 + */ 1838 + layout.extra_end_ofs 1839 + = alloc_sigframe_space(sizeof(struct target_aarch64_ctx), &layout); 1840 + } else { 1841 + /* Reserve space for the standard end marker. 1842 + * Do not use alloc_sigframe_space because we cheat 1843 + * std_size therein to reserve space for this. 1844 + */ 1845 + layout.std_end_ofs = layout.total_size; 1846 + layout.total_size += sizeof(struct target_aarch64_ctx); 1847 + } 1848 + 1849 + /* Reserve space for the return code. On a real system this would 1850 + * be within the VDSO. So, despite the name this is not a "real" 1851 + * record within the frame. 1852 + */ 1853 + fr_ofs = layout.total_size; 1854 + layout.total_size += sizeof(struct target_rt_frame_record); 1855 + 1856 + frame_addr = get_sigframe(ka, env, layout.total_size); 1589 1857 trace_user_setup_frame(env, frame_addr); 1590 1858 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { 1591 1859 goto give_sigsegv; 1592 1860 } 1593 1861 1594 - __put_user(0, &frame->uc.tuc_flags); 1595 - __put_user(0, &frame->uc.tuc_link); 1862 + target_setup_general_frame(frame, env, set); 1863 + target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env); 1864 + target_setup_end_record((void *)frame + layout.std_end_ofs); 1865 + if (layout.extra_ofs) { 1866 + target_setup_extra_record((void *)frame + layout.extra_ofs, 1867 + frame_addr + layout.extra_base, 1868 + layout.extra_size); 1869 + target_setup_end_record((void *)frame + layout.extra_end_ofs); 1870 + } 1871 + if (sve_ofs) { 1872 + target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size); 1873 + } 1874 + 1875 + /* Set up the stack frame for unwinding. */ 1876 + fr = (void *)frame + fr_ofs; 1877 + __put_user(env->xregs[29], &fr->fp); 1878 + __put_user(env->xregs[30], &fr->lr); 1596 1879 1597 - __put_user(target_sigaltstack_used.ss_sp, 1598 - &frame->uc.tuc_stack.ss_sp); 1599 - __put_user(sas_ss_flags(env->xregs[31]), 1600 - &frame->uc.tuc_stack.ss_flags); 1601 - __put_user(target_sigaltstack_used.ss_size, 1602 - &frame->uc.tuc_stack.ss_size); 1603 - target_setup_sigframe(frame, env, set); 1604 1880 if (ka->sa_flags & TARGET_SA_RESTORER) { 1605 1881 return_addr = ka->sa_restorer; 1606 1882 } else { ··· 1609 1885 * Since these are instructions they need to be put as little-endian 1610 1886 * regardless of target default or current CPU endianness. 1611 1887 */ 1612 - __put_user_e(0xd2801168, &frame->tramp[0], le); 1613 - __put_user_e(0xd4000001, &frame->tramp[1], le); 1614 - return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp); 1888 + __put_user_e(0xd2801168, &fr->tramp[0], le); 1889 + __put_user_e(0xd4000001, &fr->tramp[1], le); 1890 + return_addr = frame_addr + fr_ofs 1891 + + offsetof(struct target_rt_frame_record, tramp); 1615 1892 } 1616 1893 env->xregs[0] = usig; 1617 1894 env->xregs[31] = frame_addr; 1618 - env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp); 1895 + env->xregs[29] = frame_addr + fr_ofs; 1619 1896 env->pc = ka->_sa_handler; 1620 1897 env->xregs[30] = return_addr; 1621 1898 if (info) {
+27
linux-user/syscall.c
··· 10672 10672 break; 10673 10673 } 10674 10674 #endif 10675 + #ifdef TARGET_AARCH64 10676 + case TARGET_PR_SVE_SET_VL: 10677 + /* We cannot support either PR_SVE_SET_VL_ONEXEC 10678 + or PR_SVE_VL_INHERIT. Therefore, anything above 10679 + ARM_MAX_VQ results in EINVAL. */ 10680 + ret = -TARGET_EINVAL; 10681 + if (arm_feature(cpu_env, ARM_FEATURE_SVE) 10682 + && arg2 >= 0 && arg2 <= ARM_MAX_VQ * 16 && !(arg2 & 15)) { 10683 + CPUARMState *env = cpu_env; 10684 + int old_vq = (env->vfp.zcr_el[1] & 0xf) + 1; 10685 + int vq = MAX(arg2 / 16, 1); 10686 + 10687 + if (vq < old_vq) { 10688 + aarch64_sve_narrow_vq(env, vq); 10689 + } 10690 + env->vfp.zcr_el[1] = vq - 1; 10691 + ret = vq * 16; 10692 + } 10693 + break; 10694 + case TARGET_PR_SVE_GET_VL: 10695 + ret = -TARGET_EINVAL; 10696 + if (arm_feature(cpu_env, ARM_FEATURE_SVE)) { 10697 + CPUARMState *env = cpu_env; 10698 + ret = ((env->vfp.zcr_el[1] & 0xf) + 1) * 16; 10699 + } 10700 + break; 10701 + #endif /* AARCH64 */ 10675 10702 case PR_GET_SECCOMP: 10676 10703 case PR_SET_SECCOMP: 10677 10704 /* Disable seccomp to prevent the target disabling syscalls we
+2
target/arm/cpu-qom.h
··· 33 33 #define ARM_CPU_GET_CLASS(obj) \ 34 34 OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU) 35 35 36 + #define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU 37 + 36 38 /** 37 39 * ARMCPUClass: 38 40 * @parent_realize: The parent class' realize handler.
+87 -16
target/arm/cpu.c
··· 725 725 int pagebits; 726 726 Error *local_err = NULL; 727 727 728 + /* If we needed to query the host kernel for the CPU features 729 + * then it's possible that might have failed in the initfn, but 730 + * this is the first point where we can report it. 731 + */ 732 + if (cpu->host_cpu_probe_failed) { 733 + if (!kvm_enabled()) { 734 + error_setg(errp, "The 'host' CPU type can only be used with KVM"); 735 + } else { 736 + error_setg(errp, "Failed to retrieve host CPU features"); 737 + } 738 + return; 739 + } 740 + 728 741 cpu_exec_realizefn(cs, &local_err); 729 742 if (local_err != NULL) { 730 743 error_propagate(errp, local_err); ··· 939 952 cs->num_ases = 1; 940 953 } 941 954 cpu_address_space_init(cs, ARMASIdx_NS, "cpu-memory", cs->memory); 955 + 956 + /* No core_count specified, default to smp_cpus. */ 957 + if (cpu->core_count == -1) { 958 + cpu->core_count = smp_cpus; 959 + } 942 960 #endif 943 961 944 962 qemu_init_vcpu(cs); ··· 952 970 ObjectClass *oc; 953 971 char *typename; 954 972 char **cpuname; 973 + const char *cpunamestr; 955 974 956 975 cpuname = g_strsplit(cpu_model, ",", 1); 957 - typename = g_strdup_printf(ARM_CPU_TYPE_NAME("%s"), cpuname[0]); 976 + cpunamestr = cpuname[0]; 977 + #ifdef CONFIG_USER_ONLY 978 + /* For backwards compatibility usermode emulation allows "-cpu any", 979 + * which has the same semantics as "-cpu max". 980 + */ 981 + if (!strcmp(cpunamestr, "any")) { 982 + cpunamestr = "max"; 983 + } 984 + #endif 985 + typename = g_strdup_printf(ARM_CPU_TYPE_NAME("%s"), cpunamestr); 958 986 oc = object_class_by_name(typename); 959 987 g_strfreev(cpuname); 960 988 g_free(typename); ··· 1684 1712 cpu->reset_sctlr = 0x00000078; 1685 1713 } 1686 1714 1687 - #ifdef CONFIG_USER_ONLY 1688 - static void arm_any_initfn(Object *obj) 1715 + #ifndef TARGET_AARCH64 1716 + /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); 1717 + * otherwise, a CPU with as many features enabled as our emulation supports. 1718 + * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c; 1719 + * this only needs to handle 32 bits. 1720 + */ 1721 + static void arm_max_initfn(Object *obj) 1689 1722 { 1690 1723 ARMCPU *cpu = ARM_CPU(obj); 1691 - set_feature(&cpu->env, ARM_FEATURE_V8); 1692 - set_feature(&cpu->env, ARM_FEATURE_VFP4); 1693 - set_feature(&cpu->env, ARM_FEATURE_NEON); 1694 - set_feature(&cpu->env, ARM_FEATURE_THUMB2EE); 1695 - set_feature(&cpu->env, ARM_FEATURE_V8_AES); 1696 - set_feature(&cpu->env, ARM_FEATURE_V8_SHA1); 1697 - set_feature(&cpu->env, ARM_FEATURE_V8_SHA256); 1698 - set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); 1699 - set_feature(&cpu->env, ARM_FEATURE_CRC); 1700 - set_feature(&cpu->env, ARM_FEATURE_V8_RDM); 1701 - set_feature(&cpu->env, ARM_FEATURE_V8_FCMA); 1702 - cpu->midr = 0xffffffff; 1724 + 1725 + if (kvm_enabled()) { 1726 + kvm_arm_set_cpu_features_from_host(cpu); 1727 + } else { 1728 + cortex_a15_initfn(obj); 1729 + #ifdef CONFIG_USER_ONLY 1730 + /* We don't set these in system emulation mode for the moment, 1731 + * since we don't correctly set the ID registers to advertise them, 1732 + */ 1733 + set_feature(&cpu->env, ARM_FEATURE_V8); 1734 + set_feature(&cpu->env, ARM_FEATURE_VFP4); 1735 + set_feature(&cpu->env, ARM_FEATURE_NEON); 1736 + set_feature(&cpu->env, ARM_FEATURE_THUMB2EE); 1737 + set_feature(&cpu->env, ARM_FEATURE_V8_AES); 1738 + set_feature(&cpu->env, ARM_FEATURE_V8_SHA1); 1739 + set_feature(&cpu->env, ARM_FEATURE_V8_SHA256); 1740 + set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); 1741 + set_feature(&cpu->env, ARM_FEATURE_CRC); 1742 + set_feature(&cpu->env, ARM_FEATURE_V8_RDM); 1743 + set_feature(&cpu->env, ARM_FEATURE_V8_FCMA); 1744 + #endif 1745 + } 1703 1746 } 1704 1747 #endif 1705 1748 ··· 1751 1794 { .name = "pxa270-b1", .initfn = pxa270b1_initfn }, 1752 1795 { .name = "pxa270-c0", .initfn = pxa270c0_initfn }, 1753 1796 { .name = "pxa270-c5", .initfn = pxa270c5_initfn }, 1797 + #ifndef TARGET_AARCH64 1798 + { .name = "max", .initfn = arm_max_initfn }, 1799 + #endif 1754 1800 #ifdef CONFIG_USER_ONLY 1755 - { .name = "any", .initfn = arm_any_initfn }, 1801 + { .name = "any", .initfn = arm_max_initfn }, 1756 1802 #endif 1757 1803 #endif 1758 1804 { .name = NULL } ··· 1765 1811 DEFINE_PROP_UINT64("mp-affinity", ARMCPU, 1766 1812 mp_affinity, ARM64_AFFINITY_INVALID), 1767 1813 DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID), 1814 + DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1), 1768 1815 DEFINE_PROP_END_OF_LIST() 1769 1816 }; 1770 1817 ··· 1845 1892 #endif 1846 1893 } 1847 1894 1895 + #ifdef CONFIG_KVM 1896 + static void arm_host_initfn(Object *obj) 1897 + { 1898 + ARMCPU *cpu = ARM_CPU(obj); 1899 + 1900 + kvm_arm_set_cpu_features_from_host(cpu); 1901 + } 1902 + 1903 + static const TypeInfo host_arm_cpu_type_info = { 1904 + .name = TYPE_ARM_HOST_CPU, 1905 + #ifdef TARGET_AARCH64 1906 + .parent = TYPE_AARCH64_CPU, 1907 + #else 1908 + .parent = TYPE_ARM_CPU, 1909 + #endif 1910 + .instance_init = arm_host_initfn, 1911 + }; 1912 + 1913 + #endif 1914 + 1848 1915 static void cpu_register(const ARMCPUInfo *info) 1849 1916 { 1850 1917 TypeInfo type_info = { ··· 1889 1956 cpu_register(info); 1890 1957 info++; 1891 1958 } 1959 + 1960 + #ifdef CONFIG_KVM 1961 + type_register_static(&host_arm_cpu_type_info); 1962 + #endif 1892 1963 } 1893 1964 1894 1965 type_init(arm_cpu_register_types)
+11
target/arm/cpu.h
··· 745 745 /* Uniprocessor system with MP extensions */ 746 746 bool mp_is_up; 747 747 748 + /* True if we tried kvm_arm_host_cpu_features() during CPU instance_init 749 + * and the probe failed (so we need to report the error in realize) 750 + */ 751 + bool host_cpu_probe_failed; 752 + 753 + /* Specify the number of cores in this CPU cluster. Used for the L2CTLR 754 + * register. 755 + */ 756 + int32_t core_count; 757 + 748 758 /* The instance init functions for implementation-specific subclasses 749 759 * set these fields to specify the implementation-dependent values of 750 760 * various constant registers and reset values of non-constant ··· 861 871 #ifdef TARGET_AARCH64 862 872 int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); 863 873 int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); 874 + void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq); 864 875 #endif 865 876 866 877 target_ulong do_arm_semihosting(CPUARMState *env);
+87 -26
target/arm/cpu64.c
··· 28 28 #include "hw/arm/arm.h" 29 29 #include "sysemu/sysemu.h" 30 30 #include "sysemu/kvm.h" 31 + #include "kvm_arm.h" 31 32 32 33 static inline void set_feature(CPUARMState *env, int feature) 33 34 { ··· 42 43 #ifndef CONFIG_USER_ONLY 43 44 static uint64_t a57_a53_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri) 44 45 { 45 - /* Number of processors is in [25:24]; otherwise we RAZ */ 46 - return (smp_cpus - 1) << 24; 46 + ARMCPU *cpu = arm_env_get_cpu(env); 47 + 48 + /* Number of cores is in [25:24]; otherwise we RAZ */ 49 + return (cpu->core_count - 1) << 24; 47 50 } 48 51 #endif 49 52 ··· 212 215 define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo); 213 216 } 214 217 215 - #ifdef CONFIG_USER_ONLY 216 - static void aarch64_any_initfn(Object *obj) 218 + /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); 219 + * otherwise, a CPU with as many features enabled as our emulation supports. 220 + * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; 221 + * this only needs to handle 64 bits. 222 + */ 223 + static void aarch64_max_initfn(Object *obj) 217 224 { 218 225 ARMCPU *cpu = ARM_CPU(obj); 219 226 220 - set_feature(&cpu->env, ARM_FEATURE_V8); 221 - set_feature(&cpu->env, ARM_FEATURE_VFP4); 222 - set_feature(&cpu->env, ARM_FEATURE_NEON); 223 - set_feature(&cpu->env, ARM_FEATURE_AARCH64); 224 - set_feature(&cpu->env, ARM_FEATURE_V8_AES); 225 - set_feature(&cpu->env, ARM_FEATURE_V8_SHA1); 226 - set_feature(&cpu->env, ARM_FEATURE_V8_SHA256); 227 - set_feature(&cpu->env, ARM_FEATURE_V8_SHA512); 228 - set_feature(&cpu->env, ARM_FEATURE_V8_SHA3); 229 - set_feature(&cpu->env, ARM_FEATURE_V8_SM3); 230 - set_feature(&cpu->env, ARM_FEATURE_V8_SM4); 231 - set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); 232 - set_feature(&cpu->env, ARM_FEATURE_CRC); 233 - set_feature(&cpu->env, ARM_FEATURE_V8_RDM); 234 - set_feature(&cpu->env, ARM_FEATURE_V8_FP16); 235 - set_feature(&cpu->env, ARM_FEATURE_V8_FCMA); 236 - cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ 237 - cpu->dcz_blocksize = 7; /* 512 bytes */ 227 + if (kvm_enabled()) { 228 + kvm_arm_set_cpu_features_from_host(cpu); 229 + } else { 230 + aarch64_a57_initfn(obj); 231 + #ifdef CONFIG_USER_ONLY 232 + /* We don't set these in system emulation mode for the moment, 233 + * since we don't correctly set the ID registers to advertise them, 234 + * and in some cases they're only available in AArch64 and not AArch32, 235 + * whereas the architecture requires them to be present in both if 236 + * present in either. 237 + */ 238 + set_feature(&cpu->env, ARM_FEATURE_V8); 239 + set_feature(&cpu->env, ARM_FEATURE_VFP4); 240 + set_feature(&cpu->env, ARM_FEATURE_NEON); 241 + set_feature(&cpu->env, ARM_FEATURE_AARCH64); 242 + set_feature(&cpu->env, ARM_FEATURE_V8_AES); 243 + set_feature(&cpu->env, ARM_FEATURE_V8_SHA1); 244 + set_feature(&cpu->env, ARM_FEATURE_V8_SHA256); 245 + set_feature(&cpu->env, ARM_FEATURE_V8_SHA512); 246 + set_feature(&cpu->env, ARM_FEATURE_V8_SHA3); 247 + set_feature(&cpu->env, ARM_FEATURE_V8_SM3); 248 + set_feature(&cpu->env, ARM_FEATURE_V8_SM4); 249 + set_feature(&cpu->env, ARM_FEATURE_V8_PMULL); 250 + set_feature(&cpu->env, ARM_FEATURE_CRC); 251 + set_feature(&cpu->env, ARM_FEATURE_V8_RDM); 252 + set_feature(&cpu->env, ARM_FEATURE_V8_FP16); 253 + set_feature(&cpu->env, ARM_FEATURE_V8_FCMA); 254 + /* For usermode -cpu max we can use a larger and more efficient DCZ 255 + * blocksize since we don't have to follow what the hardware does. 256 + */ 257 + cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ 258 + cpu->dcz_blocksize = 7; /* 512 bytes */ 259 + #endif 260 + } 238 261 } 239 - #endif 240 262 241 263 typedef struct ARMCPUInfo { 242 264 const char *name; ··· 247 269 static const ARMCPUInfo aarch64_cpus[] = { 248 270 { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, 249 271 { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, 250 - #ifdef CONFIG_USER_ONLY 251 - { .name = "any", .initfn = aarch64_any_initfn }, 252 - #endif 272 + { .name = "max", .initfn = aarch64_max_initfn }, 253 273 { .name = NULL } 254 274 }; 255 275 ··· 366 386 } 367 387 368 388 type_init(aarch64_cpu_register_types) 389 + 390 + /* The manual says that when SVE is enabled and VQ is widened the 391 + * implementation is allowed to zero the previously inaccessible 392 + * portion of the registers. The corollary to that is that when 393 + * SVE is enabled and VQ is narrowed we are also allowed to zero 394 + * the now inaccessible portion of the registers. 395 + * 396 + * The intent of this is that no predicate bit beyond VQ is ever set. 397 + * Which means that some operations on predicate registers themselves 398 + * may operate on full uint64_t or even unrolled across the maximum 399 + * uint64_t[4]. Performing 4 bits of host arithmetic unconditionally 400 + * may well be cheaper than conditionals to restrict the operation 401 + * to the relevant portion of a uint16_t[16]. 402 + * 403 + * TODO: Need to call this for changes to the real system registers 404 + * and EL state changes. 405 + */ 406 + void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) 407 + { 408 + int i, j; 409 + uint64_t pmask; 410 + 411 + assert(vq >= 1 && vq <= ARM_MAX_VQ); 412 + 413 + /* Zap the high bits of the zregs. */ 414 + for (i = 0; i < 32; i++) { 415 + memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq)); 416 + } 417 + 418 + /* Zap the high bits of the pregs and ffr. */ 419 + pmask = 0; 420 + if (vq & 3) { 421 + pmask = ~(-1ULL << (16 * (vq & 3))); 422 + } 423 + for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) { 424 + for (i = 0; i < 17; ++i) { 425 + env->vfp.pregs[i].p[j] &= pmask; 426 + } 427 + pmask = 0; 428 + } 429 + }
+17 -34
target/arm/kvm.c
··· 33 33 34 34 static bool cap_has_mp_state; 35 35 36 + static ARMHostCPUFeatures arm_host_cpu_features; 37 + 36 38 int kvm_arm_vcpu_init(CPUState *cs) 37 39 { 38 40 ARMCPU *cpu = ARM_CPU(cs); ··· 129 131 } 130 132 } 131 133 132 - static void kvm_arm_host_cpu_class_init(ObjectClass *oc, void *data) 134 + void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) 133 135 { 134 - ARMHostCPUClass *ahcc = ARM_HOST_CPU_CLASS(oc); 136 + CPUARMState *env = &cpu->env; 135 137 136 - /* All we really need to set up for the 'host' CPU 137 - * is the feature bits -- we rely on the fact that the 138 - * various ID register values in ARMCPU are only used for 139 - * TCG CPUs. 140 - */ 141 - if (!kvm_arm_get_host_cpu_features(ahcc)) { 142 - fprintf(stderr, "Failed to retrieve host CPU features!\n"); 143 - abort(); 138 + if (!arm_host_cpu_features.dtb_compatible) { 139 + if (!kvm_enabled() || 140 + !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) { 141 + /* We can't report this error yet, so flag that we need to 142 + * in arm_cpu_realizefn(). 143 + */ 144 + cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; 145 + cpu->host_cpu_probe_failed = true; 146 + return; 147 + } 144 148 } 145 - } 146 149 147 - static void kvm_arm_host_cpu_initfn(Object *obj) 148 - { 149 - ARMHostCPUClass *ahcc = ARM_HOST_CPU_GET_CLASS(obj); 150 - ARMCPU *cpu = ARM_CPU(obj); 151 - CPUARMState *env = &cpu->env; 152 - 153 - cpu->kvm_target = ahcc->target; 154 - cpu->dtb_compatible = ahcc->dtb_compatible; 155 - env->features = ahcc->features; 150 + cpu->kvm_target = arm_host_cpu_features.target; 151 + cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible; 152 + env->features = arm_host_cpu_features.features; 156 153 } 157 154 158 - static const TypeInfo host_arm_cpu_type_info = { 159 - .name = TYPE_ARM_HOST_CPU, 160 - #ifdef TARGET_AARCH64 161 - .parent = TYPE_AARCH64_CPU, 162 - #else 163 - .parent = TYPE_ARM_CPU, 164 - #endif 165 - .instance_init = kvm_arm_host_cpu_initfn, 166 - .class_init = kvm_arm_host_cpu_class_init, 167 - .class_size = sizeof(ARMHostCPUClass), 168 - }; 169 - 170 155 int kvm_arch_init(MachineState *ms, KVMState *s) 171 156 { 172 157 /* For ARM interrupt delivery is always asynchronous, ··· 181 166 kvm_halt_in_kernel_allowed = true; 182 167 183 168 cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); 184 - 185 - type_register_static(&host_arm_cpu_type_info); 186 169 187 170 return 0; 188 171 }
+4 -4
target/arm/kvm32.c
··· 28 28 *features |= 1ULL << feature; 29 29 } 30 30 31 - bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc) 31 + bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) 32 32 { 33 33 /* Identify the feature bits corresponding to the host CPU, and 34 34 * fill out the ARMHostCPUClass fields accordingly. To do this ··· 74 74 return false; 75 75 } 76 76 77 - ahcc->target = init.target; 77 + ahcf->target = init.target; 78 78 79 79 /* This is not strictly blessed by the device tree binding docs yet, 80 80 * but in practice the kernel does not care about this string so 81 81 * there is no point maintaining an KVM_ARM_TARGET_* -> string table. 82 82 */ 83 - ahcc->dtb_compatible = "arm,arm-v7"; 83 + ahcf->dtb_compatible = "arm,arm-v7"; 84 84 85 85 for (i = 0; i < ARRAY_SIZE(idregs); i++) { 86 86 ret = ioctl(fdarray[2], KVM_GET_ONE_REG, &idregs[i]); ··· 132 132 set_feature(&features, ARM_FEATURE_VFP4); 133 133 } 134 134 135 - ahcc->features = features; 135 + ahcf->features = features; 136 136 137 137 return true; 138 138 }
+4 -4
target/arm/kvm64.c
··· 443 443 *features &= ~(1ULL << feature); 444 444 } 445 445 446 - bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc) 446 + bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) 447 447 { 448 448 /* Identify the feature bits corresponding to the host CPU, and 449 449 * fill out the ARMHostCPUClass fields accordingly. To do this ··· 471 471 return false; 472 472 } 473 473 474 - ahcc->target = init.target; 475 - ahcc->dtb_compatible = "arm,arm-v8"; 474 + ahcf->target = init.target; 475 + ahcf->dtb_compatible = "arm,arm-v8"; 476 476 477 477 kvm_arm_destroy_scratch_host_vcpu(fdarray); 478 478 ··· 486 486 set_feature(&features, ARM_FEATURE_AARCH64); 487 487 set_feature(&features, ARM_FEATURE_PMU); 488 488 489 - ahcc->features = features; 489 + ahcf->features = features; 490 490 491 491 return true; 492 492 }
+24 -11
target/arm/kvm_arm.h
··· 152 152 void kvm_arm_destroy_scratch_host_vcpu(int *fdarray); 153 153 154 154 #define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU 155 - #define ARM_HOST_CPU_CLASS(klass) \ 156 - OBJECT_CLASS_CHECK(ARMHostCPUClass, (klass), TYPE_ARM_HOST_CPU) 157 - #define ARM_HOST_CPU_GET_CLASS(obj) \ 158 - OBJECT_GET_CLASS(ARMHostCPUClass, (obj), TYPE_ARM_HOST_CPU) 159 - 160 - typedef struct ARMHostCPUClass { 161 - /*< private >*/ 162 - ARMCPUClass parent_class; 163 - /*< public >*/ 164 155 156 + /** 157 + * ARMHostCPUFeatures: information about the host CPU (identified 158 + * by asking the host kernel) 159 + */ 160 + typedef struct ARMHostCPUFeatures { 165 161 uint64_t features; 166 162 uint32_t target; 167 163 const char *dtb_compatible; 168 - } ARMHostCPUClass; 164 + } ARMHostCPUFeatures; 169 165 170 166 /** 171 167 * kvm_arm_get_host_cpu_features: ··· 174 170 * Probe the capabilities of the host kernel's preferred CPU and fill 175 171 * in the ARMHostCPUClass struct accordingly. 176 172 */ 177 - bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc); 173 + bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); 178 174 175 + /** 176 + * kvm_arm_set_cpu_features_from_host: 177 + * @cpu: ARMCPU to set the features for 178 + * 179 + * Set up the ARMCPU struct fields up to match the information probed 180 + * from the host CPU. 181 + */ 182 + void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); 179 183 180 184 /** 181 185 * kvm_arm_sync_mpstate_to_kvm ··· 199 203 void kvm_arm_pmu_init(CPUState *cs); 200 204 201 205 #else 206 + 207 + static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) 208 + { 209 + /* This should never actually be called in the "not KVM" case, 210 + * but set up the fields to indicate an error anyway. 211 + */ 212 + cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; 213 + cpu->host_cpu_probe_failed = true; 214 + } 202 215 203 216 static inline int kvm_arm_vgic_probe(void) 204 217 {