target-arm queue:
* Update copyright dates to 2022 * hw/armv7m: Fix broken VMStateDescription * hw/char/exynos4210_uart: Fix crash on trying to load VM state * rtc: Move RTC function prototypes to their own header * xlnx-versal-virt: Support PMC SLCR * xlnx-versal-virt: Support OSPI flash memory controller * scripts: Explain the difference between linux-headers and standard-headers * target/arm: Log CPU index in 'Taking exception' log * arm_gicv3_its: Various bugfixes and cleanups * arm_gicv3_its: Implement the missing MOVI and MOVALL commands * ast2600: Fix address mapping of second SPI controller * target/arm: Use correct entrypoint for SVC taken from Hyp to Hyp -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmH0C+AZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3gG4D/9biXPVdkOd7lIslRX0ihRg AZkZrMNk6VF/MW6xJNVWWd+44cyjLopFqF5dS+Vjebt7pEtZvxY0K5mYmzClk6lg 2U89gWuLEDJDKNVfKAmsmj24Os4xRj4sJPq/Mee8lsBdOAwEQ3C36p0RnWGBcTJN 9VfzRMSGvdjQFJjGAaro078zrA1Q11msA4BbLht+YGTE1aeyryyfF/qGSRlrlTn8 +r0ZWBD4ttz8IsqSLtnpQvT6EbL79w0jBywVauVzCOGQGpti3HdHJNYR7cKgTMja Hffx6f6iv/O4SAUUGS0WMWdfW/MEVxOFxJ7Zc2twGqDMuVWlFiLT0X1MZuHi0FpG CjbhTsvJIrKom1Ib+LPkWscrlHHEf0cvME0WokErLOJDXvbqKj04oOkpQmqUIv0+ 5j7o4mlQFuLXIyzcrBZxmwT/Ekg8KZA8aUR0ddUd0vBmGMdO2En/c4Qr/x4H2gXH HL/18oPRaSV6mP08mxcda+hJ9m5MC+7l0+KKoDfaPM9d4hl5StI0zTlH+5ffbK+m UWthMnrrZw2ZU8AzGPZxOAW5K5S3XOso5Z9credkRGuSDriaGuNY0s5gSvNawZGe ioIrUl50t+5/o2+tba7FA2ePiGeC9/zS671zHG9Rdpe86JpJXCzWO7OYiVulV3Yu dmQYrhgnUqNjh3SAiXUFVA== =m7N5 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20220128' into staging target-arm queue: * Update copyright dates to 2022 * hw/armv7m: Fix broken VMStateDescription * hw/char/exynos4210_uart: Fix crash on trying to load VM state * rtc: Move RTC function prototypes to their own header * xlnx-versal-virt: Support PMC SLCR * xlnx-versal-virt: Support OSPI flash memory controller * scripts: Explain the difference between linux-headers and standard-headers * target/arm: Log CPU index in 'Taking exception' log * arm_gicv3_its: Various bugfixes and cleanups * arm_gicv3_its: Implement the missing MOVI and MOVALL commands * ast2600: Fix address mapping of second SPI controller * target/arm: Use correct entrypoint for SVC taken from Hyp to Hyp # gpg: Signature made Fri 28 Jan 2022 15:29:36 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20220128: (32 commits) target/arm: Use correct entrypoint for SVC taken from Hyp to Hyp hw/arm: ast2600: Fix address mapping of second SPI controller hw/intc/arm_gicv3_its: Implement MOVI hw/intc/arm_gicv3_its: Implement MOVALL hw/intc/arm_gicv3_its: Check table bounds against correct limit hw/intc/arm_gicv3_its: Make GITS_BASER<n> RAZ/WI for unimplemented registers hw/intc/arm_gicv3_its: Provide read accessor for translation_ops hw/intc/arm_gicv3: Set GICR_CTLR.CES if LPIs are supported hw/intc/arm_gicv3_redist: Remove unnecessary zero checks hw/intc/arm_gicv3_its: Sort ITS command list into numeric order hw/intc/arm_gicv3: Honour GICD_CTLR.EnableGrp1NS for LPIs hw/intc/arm_gicv3_its: Don't clear GITS_CWRITER on writes to GITS_CBASER hw/intc/arm_gicv3_its: Don't clear GITS_CREADR when GITS_CTLR.ENABLED is set hw/intc/arm_gicv3: Initialise dma_as in GIC, not ITS hw/intc/arm_gicv3_its: Add tracepoints target/arm: Log CPU index in 'Taking exception' log scripts: Explain the difference between linux-headers and standard-headers MAINTAINERS: Remove myself (for raspi). MAINTAINERS: Add an entry for Xilinx Versal OSPI hw/arm/xlnx-versal-virt: Connect mt35xu01g flashes to the OSPI ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						95a6af2a00
					
				| @ -818,7 +818,6 @@ F: docs/system/arm/palm.rst | ||||
| 
 | ||||
| Raspberry Pi | ||||
| M: Peter Maydell <peter.maydell@linaro.org> | ||||
| R: Andrew Baumann <Andrew.Baumann@microsoft.com> | ||||
| R: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||||
| L: qemu-arm@nongnu.org | ||||
| S: Odd Fixes | ||||
| @ -958,6 +957,12 @@ F: hw/display/dpcd.c | ||||
| F: include/hw/display/dpcd.h | ||||
| F: docs/system/arm/xlnx-versal-virt.rst | ||||
| 
 | ||||
| Xilinx Versal OSPI | ||||
| M: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||||
| S: Maintained | ||||
| F: hw/ssi/xlnx-versal-ospi.c | ||||
| F: include/hw/ssi/xlnx-versal-ospi.h | ||||
| 
 | ||||
| ARM ACPI Subsystem | ||||
| M: Shannon Zhao <shannon.zhaosl@gmail.com> | ||||
| L: qemu-arm@nongnu.org | ||||
|  | ||||
| @ -98,7 +98,7 @@ default_role = 'any' | ||||
| 
 | ||||
| # General information about the project. | ||||
| project = u'QEMU' | ||||
| copyright = u'2021, The QEMU Project Developers' | ||||
| copyright = u'2022, The QEMU Project Developers' | ||||
| author = u'The QEMU Project Developers' | ||||
| 
 | ||||
| # The version info for the project you're documenting, acts as replacement for | ||||
|  | ||||
| @ -520,8 +520,8 @@ static const VMStateDescription vmstate_armv7m = { | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_CLOCK(refclk, SysTickState), | ||||
|         VMSTATE_CLOCK(cpuclk, SysTickState), | ||||
|         VMSTATE_CLOCK(refclk, ARMv7MState), | ||||
|         VMSTATE_CLOCK(cpuclk, ARMv7MState), | ||||
|         VMSTATE_END_OF_LIST() | ||||
|     } | ||||
| }; | ||||
|  | ||||
| @ -29,7 +29,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { | ||||
|     [ASPEED_DEV_PWM]       = 0x1E610000, | ||||
|     [ASPEED_DEV_FMC]       = 0x1E620000, | ||||
|     [ASPEED_DEV_SPI1]      = 0x1E630000, | ||||
|     [ASPEED_DEV_SPI2]      = 0x1E641000, | ||||
|     [ASPEED_DEV_SPI2]      = 0x1E631000, | ||||
|     [ASPEED_DEV_EHCI1]     = 0x1E6A1000, | ||||
|     [ASPEED_DEV_EHCI2]     = 0x1E6A3000, | ||||
|     [ASPEED_DEV_MII1]      = 0x1E650000, | ||||
|  | ||||
| @ -21,7 +21,6 @@ | ||||
| #include "qemu/error-report.h" | ||||
| #include "qemu/main-loop.h" | ||||
| #include "qapi/error.h" | ||||
| #include "qemu-common.h" | ||||
| #include "cpu.h" | ||||
| #include "exec/address-spaces.h" | ||||
| #include "hw/hw.h" | ||||
| @ -35,6 +34,7 @@ | ||||
| #include "sysemu/qtest.h" | ||||
| #include "sysemu/reset.h" | ||||
| #include "sysemu/runstate.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "qemu/range.h" | ||||
| #include "hw/sysbus.h" | ||||
| #include "qemu/cutils.h" | ||||
|  | ||||
| @ -8,7 +8,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "qemu/error-report.h" | ||||
| #include "qemu/module.h" | ||||
| #include "qapi/error.h" | ||||
| @ -27,6 +26,7 @@ | ||||
| #include "chardev/char-fe.h" | ||||
| #include "sysemu/blockdev.h" | ||||
| #include "sysemu/qtest.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "qemu/log.h" | ||||
| #include "qom/object.h" | ||||
|  | ||||
| @ -28,7 +28,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "cpu.h" | ||||
| #include "hw/irq.h" | ||||
| #include "hw/qdev-properties.h" | ||||
| @ -41,6 +40,7 @@ | ||||
| #include "chardev/char-fe.h" | ||||
| #include "chardev/char-serial.h" | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "hw/ssi/ssi.h" | ||||
| #include "qapi/error.h" | ||||
| #include "qemu/cutils.h" | ||||
|  | ||||
| @ -25,6 +25,8 @@ | ||||
| #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt") | ||||
| OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE) | ||||
| 
 | ||||
| #define XLNX_VERSAL_NUM_OSPI_FLASH 4 | ||||
| 
 | ||||
| struct VersalVirt { | ||||
|     MachineState parent_obj; | ||||
| 
 | ||||
| @ -365,7 +367,7 @@ static void fdt_add_bbram_node(VersalVirt *s) | ||||
|     qemu_fdt_add_subnode(s->fdt, name); | ||||
| 
 | ||||
|     qemu_fdt_setprop_cells(s->fdt, name, "interrupts", | ||||
|                            GIC_FDT_IRQ_TYPE_SPI, VERSAL_BBRAM_APB_IRQ_0, | ||||
|                            GIC_FDT_IRQ_TYPE_SPI, VERSAL_PMC_APB_IRQ, | ||||
|                            GIC_FDT_IRQ_FLAGS_LEVEL_HI); | ||||
|     qemu_fdt_setprop(s->fdt, name, "interrupt-names", | ||||
|                      interrupt_names, sizeof(interrupt_names)); | ||||
| @ -691,6 +693,27 @@ static void versal_virt_init(MachineState *machine) | ||||
|             exit(EXIT_FAILURE); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) { | ||||
|         BusState *spi_bus; | ||||
|         DeviceState *flash_dev; | ||||
|         qemu_irq cs_line; | ||||
|         DriveInfo *dinfo = drive_get(IF_MTD, 0, i); | ||||
| 
 | ||||
|         spi_bus = qdev_get_child_bus(DEVICE(&s->soc.pmc.iou.ospi), "spi0"); | ||||
| 
 | ||||
|         flash_dev = qdev_new("mt35xu01g"); | ||||
|         if (dinfo) { | ||||
|             qdev_prop_set_drive_err(flash_dev, "drive", | ||||
|                                     blk_by_legacy_dinfo(dinfo), &error_fatal); | ||||
|         } | ||||
|         qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal); | ||||
| 
 | ||||
|         cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); | ||||
| 
 | ||||
|         sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.pmc.iou.ospi), | ||||
|                            i + 1, cs_line); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void versal_virt_machine_instance_init(Object *obj) | ||||
|  | ||||
| @ -21,10 +21,15 @@ | ||||
| #include "kvm_arm.h" | ||||
| #include "hw/misc/unimp.h" | ||||
| #include "hw/arm/xlnx-versal.h" | ||||
| #include "qemu/log.h" | ||||
| #include "hw/sysbus.h" | ||||
| 
 | ||||
| #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72") | ||||
| #define GEM_REVISION        0x40070106 | ||||
| 
 | ||||
| #define VERSAL_NUM_PMC_APB_IRQS 3 | ||||
| #define NUM_OSPI_IRQ_LINES 3 | ||||
| 
 | ||||
| static void versal_create_apu_cpus(Versal *s) | ||||
| { | ||||
|     int i; | ||||
| @ -260,6 +265,26 @@ static void versal_create_sds(Versal *s, qemu_irq *pic) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic) | ||||
| { | ||||
|     DeviceState *orgate; | ||||
| 
 | ||||
|     /*
 | ||||
|      * The VERSAL_PMC_APB_IRQ is an 'or' of the interrupts from the following | ||||
|      * models: | ||||
|      *  - RTC | ||||
|      *  - BBRAM | ||||
|      *  - PMC SLCR | ||||
|      */ | ||||
|     object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate", | ||||
|                             &s->pmc.apb_irq_orgate, TYPE_OR_IRQ); | ||||
|     orgate = DEVICE(&s->pmc.apb_irq_orgate); | ||||
|     object_property_set_int(OBJECT(orgate), | ||||
|                             "num-lines", VERSAL_NUM_PMC_APB_IRQS, &error_fatal); | ||||
|     qdev_realize(orgate, NULL, &error_fatal); | ||||
|     qdev_connect_gpio_out(orgate, 0, pic[VERSAL_PMC_APB_IRQ]); | ||||
| } | ||||
| 
 | ||||
| static void versal_create_rtc(Versal *s, qemu_irq *pic) | ||||
| { | ||||
|     SysBusDevice *sbd; | ||||
| @ -277,7 +302,8 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) | ||||
|      * TODO: Connect the ALARM and SECONDS interrupts once our RTC model | ||||
|      * supports them. | ||||
|      */ | ||||
|     sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]); | ||||
|     sysbus_connect_irq(sbd, 1, | ||||
|                        qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0)); | ||||
| } | ||||
| 
 | ||||
| static void versal_create_xrams(Versal *s, qemu_irq *pic) | ||||
| @ -328,7 +354,8 @@ static void versal_create_bbram(Versal *s, qemu_irq *pic) | ||||
|     sysbus_realize(sbd, &error_fatal); | ||||
|     memory_region_add_subregion(&s->mr_ps, MM_PMC_BBRAM_CTRL, | ||||
|                                 sysbus_mmio_get_region(sbd, 0)); | ||||
|     sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]); | ||||
|     sysbus_connect_irq(sbd, 0, | ||||
|                        qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 1)); | ||||
| } | ||||
| 
 | ||||
| static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base) | ||||
| @ -369,6 +396,114 @@ static void versal_create_efuse(Versal *s, qemu_irq *pic) | ||||
|     sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]); | ||||
| } | ||||
| 
 | ||||
| static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic) | ||||
| { | ||||
|     SysBusDevice *sbd; | ||||
| 
 | ||||
|     object_initialize_child(OBJECT(s), "versal-pmc-iou-slcr", &s->pmc.iou.slcr, | ||||
|                             TYPE_XILINX_VERSAL_PMC_IOU_SLCR); | ||||
| 
 | ||||
|     sbd = SYS_BUS_DEVICE(&s->pmc.iou.slcr); | ||||
|     sysbus_realize(sbd, &error_fatal); | ||||
| 
 | ||||
|     memory_region_add_subregion(&s->mr_ps, MM_PMC_PMC_IOU_SLCR, | ||||
|                                 sysbus_mmio_get_region(sbd, 0)); | ||||
| 
 | ||||
|     sysbus_connect_irq(sbd, 0, | ||||
|                        qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2)); | ||||
| } | ||||
| 
 | ||||
| static void versal_create_ospi(Versal *s, qemu_irq *pic) | ||||
| { | ||||
|     SysBusDevice *sbd; | ||||
|     MemoryRegion *mr_dac; | ||||
|     qemu_irq ospi_mux_sel; | ||||
|     DeviceState *orgate; | ||||
| 
 | ||||
|     memory_region_init(&s->pmc.iou.ospi.linear_mr, OBJECT(s), | ||||
|                        "versal-ospi-linear-mr" , MM_PMC_OSPI_DAC_SIZE); | ||||
| 
 | ||||
|     object_initialize_child(OBJECT(s), "versal-ospi", &s->pmc.iou.ospi.ospi, | ||||
|                             TYPE_XILINX_VERSAL_OSPI); | ||||
| 
 | ||||
|     mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 1); | ||||
|     memory_region_add_subregion(&s->pmc.iou.ospi.linear_mr, 0x0, mr_dac); | ||||
| 
 | ||||
|     /* Create the OSPI destination DMA */ | ||||
|     object_initialize_child(OBJECT(s), "versal-ospi-dma-dst", | ||||
|                             &s->pmc.iou.ospi.dma_dst, | ||||
|                             TYPE_XLNX_CSU_DMA); | ||||
| 
 | ||||
|     object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_dst), | ||||
|                             "dma", OBJECT(get_system_memory()), | ||||
|                              &error_abort); | ||||
| 
 | ||||
|     sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst); | ||||
|     sysbus_realize(sbd, &error_fatal); | ||||
| 
 | ||||
|     memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_DST, | ||||
|                                 sysbus_mmio_get_region(sbd, 0)); | ||||
| 
 | ||||
|     /* Create the OSPI source DMA */ | ||||
|     object_initialize_child(OBJECT(s), "versal-ospi-dma-src", | ||||
|                             &s->pmc.iou.ospi.dma_src, | ||||
|                             TYPE_XLNX_CSU_DMA); | ||||
| 
 | ||||
|     object_property_set_bool(OBJECT(&s->pmc.iou.ospi.dma_src), "is-dst", | ||||
|                              false, &error_abort); | ||||
| 
 | ||||
|     object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src), | ||||
|                             "dma", OBJECT(mr_dac), &error_abort); | ||||
| 
 | ||||
|     object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src), | ||||
|                             "stream-connected-dma", | ||||
|                              OBJECT(&s->pmc.iou.ospi.dma_dst), | ||||
|                              &error_abort); | ||||
| 
 | ||||
|     sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src); | ||||
|     sysbus_realize(sbd, &error_fatal); | ||||
| 
 | ||||
|     memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_SRC, | ||||
|                                 sysbus_mmio_get_region(sbd, 0)); | ||||
| 
 | ||||
|     /* Realize the OSPI */ | ||||
|     object_property_set_link(OBJECT(&s->pmc.iou.ospi.ospi), "dma-src", | ||||
|                              OBJECT(&s->pmc.iou.ospi.dma_src), &error_abort); | ||||
| 
 | ||||
|     sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi); | ||||
|     sysbus_realize(sbd, &error_fatal); | ||||
| 
 | ||||
|     memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI, | ||||
|                                 sysbus_mmio_get_region(sbd, 0)); | ||||
| 
 | ||||
|     memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DAC, | ||||
|                                 &s->pmc.iou.ospi.linear_mr); | ||||
| 
 | ||||
|     /* ospi_mux_sel */ | ||||
|     ospi_mux_sel = qdev_get_gpio_in_named(DEVICE(&s->pmc.iou.ospi.ospi), | ||||
|                                           "ospi-mux-sel", 0); | ||||
|     qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "ospi-mux-sel", 0, | ||||
|                                 ospi_mux_sel); | ||||
| 
 | ||||
|     /* OSPI irq */ | ||||
|     object_initialize_child(OBJECT(s), "ospi-irq-orgate", | ||||
|                             &s->pmc.iou.ospi.irq_orgate, TYPE_OR_IRQ); | ||||
|     object_property_set_int(OBJECT(&s->pmc.iou.ospi.irq_orgate), | ||||
|                             "num-lines", NUM_OSPI_IRQ_LINES, &error_fatal); | ||||
| 
 | ||||
|     orgate = DEVICE(&s->pmc.iou.ospi.irq_orgate); | ||||
|     qdev_realize(orgate, NULL, &error_fatal); | ||||
| 
 | ||||
|     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 0, | ||||
|                        qdev_get_gpio_in(orgate, 0)); | ||||
|     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src), 0, | ||||
|                        qdev_get_gpio_in(orgate, 1)); | ||||
|     sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst), 0, | ||||
|                        qdev_get_gpio_in(orgate, 2)); | ||||
| 
 | ||||
|     qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]); | ||||
| } | ||||
| 
 | ||||
| /* This takes the board allocated linear DDR memory and creates aliases
 | ||||
|  * for each split DDR range/aperture on the Versal address map. | ||||
|  */ | ||||
| @ -425,8 +560,31 @@ static void versal_unimp_area(Versal *s, const char *name, | ||||
|     memory_region_add_subregion(mr, base, mr_dev); | ||||
| } | ||||
| 
 | ||||
| static void versal_unimp_sd_emmc_sel(void *opaque, int n, int level) | ||||
| { | ||||
|     qemu_log_mask(LOG_UNIMP, | ||||
|                   "Selecting between enabling SD mode or eMMC mode on " | ||||
|                   "controller %d is not yet implemented\n", n); | ||||
| } | ||||
| 
 | ||||
| static void versal_unimp_qspi_ospi_mux_sel(void *opaque, int n, int level) | ||||
| { | ||||
|     qemu_log_mask(LOG_UNIMP, | ||||
|                   "Selecting between enabling the QSPI or OSPI linear address " | ||||
|                   "region is not yet implemented\n"); | ||||
| } | ||||
| 
 | ||||
| static void versal_unimp_irq_parity_imr(void *opaque, int n, int level) | ||||
| { | ||||
|     qemu_log_mask(LOG_UNIMP, | ||||
|                   "PMC SLCR parity interrupt behaviour " | ||||
|                   "is not yet implemented\n"); | ||||
| } | ||||
| 
 | ||||
| static void versal_unimp(Versal *s) | ||||
| { | ||||
|     qemu_irq gpio_in; | ||||
| 
 | ||||
|     versal_unimp_area(s, "psm", &s->mr_ps, | ||||
|                         MM_PSM_START, MM_PSM_END - MM_PSM_START); | ||||
|     versal_unimp_area(s, "crl", &s->mr_ps, | ||||
| @ -441,6 +599,31 @@ static void versal_unimp(Versal *s) | ||||
|                         MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE); | ||||
|     versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps, | ||||
|                         MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE); | ||||
| 
 | ||||
|     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_sd_emmc_sel, | ||||
|                             "sd-emmc-sel-dummy", 2); | ||||
|     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel, | ||||
|                             "qspi-ospi-mux-sel-dummy", 1); | ||||
|     qdev_init_gpio_in_named(DEVICE(s), versal_unimp_irq_parity_imr, | ||||
|                             "irq-parity-imr-dummy", 1); | ||||
| 
 | ||||
|     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 0); | ||||
|     qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 0, | ||||
|                                 gpio_in); | ||||
| 
 | ||||
|     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 1); | ||||
|     qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 1, | ||||
|                                 gpio_in); | ||||
| 
 | ||||
|     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "qspi-ospi-mux-sel-dummy", 0); | ||||
|     qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), | ||||
|                                 "qspi-ospi-mux-sel", 0, | ||||
|                                 gpio_in); | ||||
| 
 | ||||
|     gpio_in = qdev_get_gpio_in_named(DEVICE(s), "irq-parity-imr-dummy", 0); | ||||
|     qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), | ||||
|                                 SYSBUS_DEVICE_GPIO_IRQ, 0, | ||||
|                                 gpio_in); | ||||
| } | ||||
| 
 | ||||
| static void versal_realize(DeviceState *dev, Error **errp) | ||||
| @ -455,10 +638,13 @@ static void versal_realize(DeviceState *dev, Error **errp) | ||||
|     versal_create_gems(s, pic); | ||||
|     versal_create_admas(s, pic); | ||||
|     versal_create_sds(s, pic); | ||||
|     versal_create_pmc_apb_irq_orgate(s, pic); | ||||
|     versal_create_rtc(s, pic); | ||||
|     versal_create_xrams(s, pic); | ||||
|     versal_create_bbram(s, pic); | ||||
|     versal_create_efuse(s, pic); | ||||
|     versal_create_pmc_iou_slcr(s, pic); | ||||
|     versal_create_ospi(s, pic); | ||||
|     versal_map_ddr(s); | ||||
|     versal_unimp(s); | ||||
| 
 | ||||
|  | ||||
| @ -255,6 +255,8 @@ static const FlashPartInfo known_devices[] = { | ||||
|     { INFO("n25q512a",    0x20ba20,      0,  64 << 10, 1024, ER_4K) }, | ||||
|     { INFO("n25q512ax3",  0x20ba20,  0x1000,  64 << 10, 1024, ER_4K) }, | ||||
|     { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) }, | ||||
|     { INFO_STACKED("mt35xu01g", 0x2c5b1b, 0x104100, 128 << 10, 1024, | ||||
|                    ER_4K | ER_32K, 2) }, | ||||
|     { INFO_STACKED("n25q00",    0x20ba21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, | ||||
|     { INFO_STACKED("n25q00a",   0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, | ||||
|     { INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, | ||||
|  | ||||
| @ -628,7 +628,6 @@ static const VMStateDescription vmstate_exynos4210_uart_fifo = { | ||||
|     .name = "exynos4210.uart.fifo", | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .post_load = exynos4210_uart_post_load, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_UINT32(sp, Exynos4210UartFIFO), | ||||
|         VMSTATE_UINT32(rp, Exynos4210UartFIFO), | ||||
| @ -641,6 +640,7 @@ static const VMStateDescription vmstate_exynos4210_uart = { | ||||
|     .name = "exynos4210.uart", | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .post_load = exynos4210_uart_post_load, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_STRUCT(rx, Exynos4210UartState, 1, | ||||
|                        vmstate_exynos4210_uart_fifo, Exynos4210UartFIFO), | ||||
|  | ||||
| @ -472,6 +472,20 @@ static uint64_t addr_msb_pre_write(RegisterInfo *reg, uint64_t val) | ||||
|     return val & R_ADDR_MSB_ADDR_MSB_MASK; | ||||
| } | ||||
| 
 | ||||
| static MemTxResult xlnx_csu_dma_class_read(XlnxCSUDMA *s, hwaddr addr, | ||||
|                                            uint32_t len) | ||||
| { | ||||
|     RegisterInfo *reg = &s->regs_info[R_SIZE]; | ||||
|     uint64_t we = MAKE_64BIT_MASK(0, 4 * 8); | ||||
| 
 | ||||
|     s->regs[R_ADDR] = addr; | ||||
|     s->regs[R_ADDR_MSB] = (uint64_t)addr >> 32; | ||||
| 
 | ||||
|     register_write(reg, len, we, object_get_typename(OBJECT(s)), false); | ||||
| 
 | ||||
|     return (s->regs[R_SIZE] == 0) ? MEMTX_OK : MEMTX_ERROR; | ||||
| } | ||||
| 
 | ||||
| static const RegisterAccessInfo *xlnx_csu_dma_regs_info[] = { | ||||
| #define DMACH_REGINFO(NAME, snd)                                              \ | ||||
|     (const RegisterAccessInfo []) {                                           \ | ||||
| @ -696,6 +710,7 @@ static void xlnx_csu_dma_class_init(ObjectClass *klass, void *data) | ||||
| { | ||||
|     DeviceClass *dc = DEVICE_CLASS(klass); | ||||
|     StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); | ||||
|     XlnxCSUDMAClass *xcdc = XLNX_CSU_DMA_CLASS(klass); | ||||
| 
 | ||||
|     dc->reset = xlnx_csu_dma_reset; | ||||
|     dc->realize = xlnx_csu_dma_realize; | ||||
| @ -704,6 +719,8 @@ static void xlnx_csu_dma_class_init(ObjectClass *klass, void *data) | ||||
| 
 | ||||
|     ssc->push = xlnx_csu_dma_stream_push; | ||||
|     ssc->can_push = xlnx_csu_dma_stream_can_push; | ||||
| 
 | ||||
|     xcdc->read = xlnx_csu_dma_class_read; | ||||
| } | ||||
| 
 | ||||
| static void xlnx_csu_dma_init(Object *obj) | ||||
|  | ||||
| @ -166,6 +166,7 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs) | ||||
|     } | ||||
| 
 | ||||
|     if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable && | ||||
|         (cs->gic->gicd_ctlr & GICD_CTLR_EN_GRP1NS) && | ||||
|         (cs->hpplpi.prio != 0xff)) { | ||||
|         if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) { | ||||
|             cs->hppi.irq = cs->hpplpi.irq; | ||||
|  | ||||
| @ -357,6 +357,11 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (s->lpi_enable) { | ||||
|         address_space_init(&s->dma_as, s->dma, | ||||
|                            "gicv3-its-sysmem"); | ||||
|     } | ||||
| 
 | ||||
|     s->cpu = g_new0(GICv3CPUState, s->num_cpu); | ||||
| 
 | ||||
|     for (i = 0; i < s->num_cpu; i++) { | ||||
| @ -424,6 +429,10 @@ static void arm_gicv3_common_reset(DeviceState *dev) | ||||
| 
 | ||||
|         cs->level = 0; | ||||
|         cs->gicr_ctlr = 0; | ||||
|         if (s->lpi_enable) { | ||||
|             /* Our implementation supports clearing GICR_CTLR.EnableLPIs */ | ||||
|             cs->gicr_ctlr |= GICR_CTLR_CES; | ||||
|         } | ||||
|         cs->gicr_statusr[GICV3_S] = 0; | ||||
|         cs->gicr_statusr[GICV3_NS] = 0; | ||||
|         cs->gicr_waker = GICR_WAKER_ProcessorSleep | GICR_WAKER_ChildrenAsleep; | ||||
|  | ||||
| @ -13,6 +13,7 @@ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu/log.h" | ||||
| #include "trace.h" | ||||
| #include "hw/qdev-properties.h" | ||||
| #include "hw/intc/arm_gicv3_its_common.h" | ||||
| #include "gicv3_internal.h" | ||||
| @ -255,10 +256,10 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, | ||||
| 
 | ||||
|     eventid = (value & EVENTID_MASK); | ||||
| 
 | ||||
|     if (devid >= s->dt.num_ids) { | ||||
|     if (devid >= s->dt.num_entries) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: devid %d>=%d", | ||||
|                       __func__, devid, s->dt.num_ids); | ||||
|                       __func__, devid, s->dt.num_entries); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
| @ -299,7 +300,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     if (icid >= s->ct.num_ids) { | ||||
|     if (icid >= s->ct.num_entries) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid ICID 0x%x in ITE (table corrupted?)\n", | ||||
|                       __func__, icid); | ||||
| @ -383,10 +384,10 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, | ||||
| 
 | ||||
|     icid = value & ICID_MASK; | ||||
| 
 | ||||
|     if (devid >= s->dt.num_ids) { | ||||
|     if (devid >= s->dt.num_entries) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: devid %d>=%d", | ||||
|                       __func__, devid, s->dt.num_ids); | ||||
|                       __func__, devid, s->dt.num_entries); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
| @ -399,7 +400,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, | ||||
|     num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); | ||||
|     num_intids = 1ULL << (GICD_TYPER_IDBITS + 1); | ||||
| 
 | ||||
|     if ((icid >= s->ct.num_ids) | ||||
|     if ((icid >= s->ct.num_entries) | ||||
|             || !dte_valid || (eventid >= num_eventids) || | ||||
|             (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) && | ||||
|              (pIntid != INTID_SPURIOUS))) { | ||||
| @ -484,7 +485,7 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset) | ||||
| 
 | ||||
|     valid = (value & CMD_FIELD_VALID_MASK); | ||||
| 
 | ||||
|     if ((icid >= s->ct.num_ids) || (rdbase >= s->gicv3->num_cpu)) { | ||||
|     if ((icid >= s->ct.num_entries) || (rdbase >= s->gicv3->num_cpu)) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "ITS MAPC: invalid collection table attributes " | ||||
|                       "icid %d rdbase %" PRIu64 "\n",  icid, rdbase); | ||||
| @ -565,7 +566,7 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, | ||||
| 
 | ||||
|     valid = (value & CMD_FIELD_VALID_MASK); | ||||
| 
 | ||||
|     if ((devid >= s->dt.num_ids) || | ||||
|     if ((devid >= s->dt.num_entries) || | ||||
|         (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "ITS MAPD: invalid device table attributes " | ||||
| @ -581,6 +582,201 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, | ||||
|     return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL; | ||||
| } | ||||
| 
 | ||||
| static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value, | ||||
|                                    uint32_t offset) | ||||
| { | ||||
|     AddressSpace *as = &s->gicv3->dma_as; | ||||
|     MemTxResult res = MEMTX_OK; | ||||
|     uint64_t rd1, rd2; | ||||
| 
 | ||||
|     /* No fields in dwords 0 or 1 */ | ||||
|     offset += NUM_BYTES_IN_DW; | ||||
|     offset += NUM_BYTES_IN_DW; | ||||
|     value = address_space_ldq_le(as, s->cq.base_addr + offset, | ||||
|                                  MEMTXATTRS_UNSPECIFIED, &res); | ||||
|     if (res != MEMTX_OK) { | ||||
|         return CMD_STALL; | ||||
|     } | ||||
| 
 | ||||
|     rd1 = FIELD_EX64(value, MOVALL_2, RDBASE1); | ||||
|     if (rd1 >= s->gicv3->num_cpu) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: RDBASE1 %" PRId64 | ||||
|                       " out of range (must be less than %d)\n", | ||||
|                       __func__, rd1, s->gicv3->num_cpu); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     offset += NUM_BYTES_IN_DW; | ||||
|     value = address_space_ldq_le(as, s->cq.base_addr + offset, | ||||
|                                  MEMTXATTRS_UNSPECIFIED, &res); | ||||
|     if (res != MEMTX_OK) { | ||||
|         return CMD_STALL; | ||||
|     } | ||||
| 
 | ||||
|     rd2 = FIELD_EX64(value, MOVALL_3, RDBASE2); | ||||
|     if (rd2 >= s->gicv3->num_cpu) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: RDBASE2 %" PRId64 | ||||
|                       " out of range (must be less than %d)\n", | ||||
|                       __func__, rd2, s->gicv3->num_cpu); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     if (rd1 == rd2) { | ||||
|         /* Move to same target must succeed as a no-op */ | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     /* Move all pending LPIs from redistributor 1 to redistributor 2 */ | ||||
|     gicv3_redist_movall_lpis(&s->gicv3->cpu[rd1], &s->gicv3->cpu[rd2]); | ||||
| 
 | ||||
|     return CMD_CONTINUE; | ||||
| } | ||||
| 
 | ||||
| static ItsCmdResult process_movi(GICv3ITSState *s, uint64_t value, | ||||
|                                  uint32_t offset) | ||||
| { | ||||
|     AddressSpace *as = &s->gicv3->dma_as; | ||||
|     MemTxResult res = MEMTX_OK; | ||||
|     uint32_t devid, eventid, intid; | ||||
|     uint16_t old_icid, new_icid; | ||||
|     uint64_t old_cte, new_cte; | ||||
|     uint64_t old_rdbase, new_rdbase; | ||||
|     uint64_t dte; | ||||
|     bool dte_valid, ite_valid, cte_valid; | ||||
|     uint64_t num_eventids; | ||||
|     IteEntry ite = {}; | ||||
| 
 | ||||
|     devid = FIELD_EX64(value, MOVI_0, DEVICEID); | ||||
| 
 | ||||
|     offset += NUM_BYTES_IN_DW; | ||||
|     value = address_space_ldq_le(as, s->cq.base_addr + offset, | ||||
|                                  MEMTXATTRS_UNSPECIFIED, &res); | ||||
|     if (res != MEMTX_OK) { | ||||
|         return CMD_STALL; | ||||
|     } | ||||
|     eventid = FIELD_EX64(value, MOVI_1, EVENTID); | ||||
| 
 | ||||
|     offset += NUM_BYTES_IN_DW; | ||||
|     value = address_space_ldq_le(as, s->cq.base_addr + offset, | ||||
|                                  MEMTXATTRS_UNSPECIFIED, &res); | ||||
|     if (res != MEMTX_OK) { | ||||
|         return CMD_STALL; | ||||
|     } | ||||
|     new_icid = FIELD_EX64(value, MOVI_2, ICID); | ||||
| 
 | ||||
|     if (devid >= s->dt.num_entries) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: devid %d>=%d", | ||||
|                       __func__, devid, s->dt.num_entries); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
|     dte = get_dte(s, devid, &res); | ||||
|     if (res != MEMTX_OK) { | ||||
|         return CMD_STALL; | ||||
|     } | ||||
| 
 | ||||
|     dte_valid = FIELD_EX64(dte, DTE, VALID); | ||||
|     if (!dte_valid) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: " | ||||
|                       "invalid dte: %"PRIx64" for %d\n", | ||||
|                       __func__, dte, devid); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); | ||||
|     if (eventid >= num_eventids) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: eventid %d >= %" | ||||
|                       PRId64 "\n", | ||||
|                       __func__, eventid, num_eventids); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     ite_valid = get_ite(s, eventid, dte, &old_icid, &intid, &res); | ||||
|     if (res != MEMTX_OK) { | ||||
|         return CMD_STALL; | ||||
|     } | ||||
| 
 | ||||
|     if (!ite_valid) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: invalid ITE\n", | ||||
|                       __func__); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     if (old_icid >= s->ct.num_entries) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid ICID 0x%x in ITE (table corrupted?)\n", | ||||
|                       __func__, old_icid); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     if (new_icid >= s->ct.num_entries) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: ICID 0x%x\n", | ||||
|                       __func__, new_icid); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     cte_valid = get_cte(s, old_icid, &old_cte, &res); | ||||
|     if (res != MEMTX_OK) { | ||||
|         return CMD_STALL; | ||||
|     } | ||||
|     if (!cte_valid) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: " | ||||
|                       "invalid cte: %"PRIx64"\n", | ||||
|                       __func__, old_cte); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     cte_valid = get_cte(s, new_icid, &new_cte, &res); | ||||
|     if (res != MEMTX_OK) { | ||||
|         return CMD_STALL; | ||||
|     } | ||||
|     if (!cte_valid) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid command attributes: " | ||||
|                       "invalid cte: %"PRIx64"\n", | ||||
|                       __func__, new_cte); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     old_rdbase = FIELD_EX64(old_cte, CTE, RDBASE); | ||||
|     if (old_rdbase >= s->gicv3->num_cpu) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: CTE has invalid rdbase 0x%"PRIx64"\n", | ||||
|                       __func__, old_rdbase); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     new_rdbase = FIELD_EX64(new_cte, CTE, RDBASE); | ||||
|     if (new_rdbase >= s->gicv3->num_cpu) { | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: CTE has invalid rdbase 0x%"PRIx64"\n", | ||||
|                       __func__, new_rdbase); | ||||
|         return CMD_CONTINUE; | ||||
|     } | ||||
| 
 | ||||
|     if (old_rdbase != new_rdbase) { | ||||
|         /* Move the LPI from the old redistributor to the new one */ | ||||
|         gicv3_redist_mov_lpi(&s->gicv3->cpu[old_rdbase], | ||||
|                              &s->gicv3->cpu[new_rdbase], | ||||
|                              intid); | ||||
|     } | ||||
| 
 | ||||
|     /* Update the ICID field in the interrupt translation table entry */ | ||||
|     ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1); | ||||
|     ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL); | ||||
|     ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid); | ||||
|     ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); | ||||
|     ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, new_icid); | ||||
|     return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Current implementation blocks until all | ||||
|  * commands are processed | ||||
| @ -634,6 +830,8 @@ static void process_cmdq(GICv3ITSState *s) | ||||
| 
 | ||||
|         cmd = (data & CMD_MASK); | ||||
| 
 | ||||
|         trace_gicv3_its_process_command(rd_offset, cmd); | ||||
| 
 | ||||
|         switch (cmd) { | ||||
|         case GITS_CMD_INT: | ||||
|             result = process_its_cmd(s, data, cq_offset, INTERRUPT); | ||||
| @ -676,6 +874,12 @@ static void process_cmdq(GICv3ITSState *s) | ||||
|                 gicv3_redist_update_lpi(&s->gicv3->cpu[i]); | ||||
|             } | ||||
|             break; | ||||
|         case GITS_CMD_MOVI: | ||||
|             result = process_movi(s, data, cq_offset); | ||||
|             break; | ||||
|         case GITS_CMD_MOVALL: | ||||
|             result = process_movall(s, data, cq_offset); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @ -788,7 +992,7 @@ static void extract_table_params(GICv3ITSState *s) | ||||
|                                   L1TABLE_ENTRY_SIZE) * | ||||
|                                  (page_sz / td->entry_sz)); | ||||
|         } | ||||
|         td->num_ids = 1ULL << idbits; | ||||
|         td->num_entries = MIN(td->num_entries, 1ULL << idbits); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -810,6 +1014,18 @@ static void extract_cmdq_params(GICv3ITSState *s) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static MemTxResult gicv3_its_translation_read(void *opaque, hwaddr offset, | ||||
|                                               uint64_t *data, unsigned size, | ||||
|                                               MemTxAttrs attrs) | ||||
| { | ||||
|     /*
 | ||||
|      * GITS_TRANSLATER is write-only, and all other addresses | ||||
|      * in the interrupt translation space frame are RES0. | ||||
|      */ | ||||
|     *data = 0; | ||||
|     return MEMTX_OK; | ||||
| } | ||||
| 
 | ||||
| static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset, | ||||
|                                                uint64_t data, unsigned size, | ||||
|                                                MemTxAttrs attrs) | ||||
| @ -818,6 +1034,8 @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset, | ||||
|     bool result = true; | ||||
|     uint32_t devid = 0; | ||||
| 
 | ||||
|     trace_gicv3_its_translation_write(offset, data, size, attrs.requester_id); | ||||
| 
 | ||||
|     switch (offset) { | ||||
|     case GITS_TRANSLATER: | ||||
|         if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) { | ||||
| @ -848,7 +1066,6 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||||
|             s->ctlr |= R_GITS_CTLR_ENABLED_MASK; | ||||
|             extract_table_params(s); | ||||
|             extract_cmdq_params(s); | ||||
|             s->creadr = 0; | ||||
|             process_cmdq(s); | ||||
|         } else { | ||||
|             s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK; | ||||
| @ -862,7 +1079,6 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||||
|         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||||
|             s->cbaser = deposit64(s->cbaser, 0, 32, value); | ||||
|             s->creadr = 0; | ||||
|             s->cwriter = s->creadr; | ||||
|         } | ||||
|         break; | ||||
|     case GITS_CBASER + 4: | ||||
| @ -873,7 +1089,6 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||||
|         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||||
|             s->cbaser = deposit64(s->cbaser, 32, 32, value); | ||||
|             s->creadr = 0; | ||||
|             s->cwriter = s->creadr; | ||||
|         } | ||||
|         break; | ||||
|     case GITS_CWRITER: | ||||
| @ -915,6 +1130,10 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||||
|         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||||
|             index = (offset - GITS_BASER) / 8; | ||||
| 
 | ||||
|             if (s->baser[index] == 0) { | ||||
|                 /* Unimplemented GITS_BASERn: RAZ/WI */ | ||||
|                 break; | ||||
|             } | ||||
|             if (offset & 7) { | ||||
|                 value <<= 32; | ||||
|                 value &= ~GITS_BASER_RO_MASK; | ||||
| @ -1011,6 +1230,10 @@ static bool its_writell(GICv3ITSState *s, hwaddr offset, | ||||
|          */ | ||||
|         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||||
|             index = (offset - GITS_BASER) / 8; | ||||
|             if (s->baser[index] == 0) { | ||||
|                 /* Unimplemented GITS_BASERn: RAZ/WI */ | ||||
|                 break; | ||||
|             } | ||||
|             s->baser[index] &= GITS_BASER_RO_MASK; | ||||
|             s->baser[index] |= (value & ~GITS_BASER_RO_MASK); | ||||
|         } | ||||
| @ -1023,7 +1246,6 @@ static bool its_writell(GICv3ITSState *s, hwaddr offset, | ||||
|         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||||
|             s->cbaser = value; | ||||
|             s->creadr = 0; | ||||
|             s->cwriter = s->creadr; | ||||
|         } | ||||
|         break; | ||||
|     case GITS_CWRITER: | ||||
| @ -1107,6 +1329,7 @@ static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data, | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid guest read at offset " TARGET_FMT_plx | ||||
|                       "size %u\n", __func__, offset, size); | ||||
|         trace_gicv3_its_badread(offset, size); | ||||
|         /*
 | ||||
|          * The spec requires that reserved registers are RAZ/WI; | ||||
|          * so use false returns from leaf functions as a way to | ||||
| @ -1114,6 +1337,8 @@ static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data, | ||||
|          * the caller, or we'll cause a spurious guest data abort. | ||||
|          */ | ||||
|         *data = 0; | ||||
|     } else { | ||||
|         trace_gicv3_its_read(offset, *data, size); | ||||
|     } | ||||
|     return MEMTX_OK; | ||||
| } | ||||
| @ -1140,12 +1365,15 @@ static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data, | ||||
|         qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                       "%s: invalid guest write at offset " TARGET_FMT_plx | ||||
|                       "size %u\n", __func__, offset, size); | ||||
|         trace_gicv3_its_badwrite(offset, data, size); | ||||
|         /*
 | ||||
|          * The spec requires that reserved registers are RAZ/WI; | ||||
|          * so use false returns from leaf functions as a way to | ||||
|          * trigger the guest-error logging but don't return it to | ||||
|          * the caller, or we'll cause a spurious guest data abort. | ||||
|          */ | ||||
|     } else { | ||||
|         trace_gicv3_its_write(offset, data, size); | ||||
|     } | ||||
|     return MEMTX_OK; | ||||
| } | ||||
| @ -1161,6 +1389,7 @@ static const MemoryRegionOps gicv3_its_control_ops = { | ||||
| }; | ||||
| 
 | ||||
| static const MemoryRegionOps gicv3_its_translation_ops = { | ||||
|     .read_with_attrs = gicv3_its_translation_read, | ||||
|     .write_with_attrs = gicv3_its_translation_write, | ||||
|     .valid.min_access_size = 2, | ||||
|     .valid.max_access_size = 4, | ||||
| @ -1183,9 +1412,6 @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp) | ||||
| 
 | ||||
|     gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops); | ||||
| 
 | ||||
|     address_space_init(&s->gicv3->dma_as, s->gicv3->dma, | ||||
|                        "gicv3-its-sysmem"); | ||||
| 
 | ||||
|     /* set the ITS default features supported */ | ||||
|     s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1); | ||||
|     s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE, | ||||
|  | ||||
| @ -591,8 +591,7 @@ void gicv3_redist_update_lpi_only(GICv3CPUState *cs) | ||||
|     idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||||
|                  GICD_TYPER_IDBITS); | ||||
| 
 | ||||
|     if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser || | ||||
|         !cs->gicr_pendbaser) { | ||||
|     if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| @ -673,9 +672,8 @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level) | ||||
|     idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||||
|                  GICD_TYPER_IDBITS); | ||||
| 
 | ||||
|     if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser || | ||||
|          !cs->gicr_pendbaser || (irq > (1ULL << (idbits + 1)) - 1) || | ||||
|          irq < GICV3_LPI_INTID_START) { | ||||
|     if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || | ||||
|         (irq > (1ULL << (idbits + 1)) - 1) || irq < GICV3_LPI_INTID_START) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| @ -683,6 +681,113 @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level) | ||||
|     gicv3_redist_lpi_pending(cs, irq, level); | ||||
| } | ||||
| 
 | ||||
| void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq) | ||||
| { | ||||
|     /*
 | ||||
|      * Move the specified LPI's pending state from the source redistributor | ||||
|      * to the destination. | ||||
|      * | ||||
|      * If LPIs are disabled on dest this is CONSTRAINED UNPREDICTABLE: | ||||
|      * we choose to NOP. If LPIs are disabled on source there's nothing | ||||
|      * to be transferred anyway. | ||||
|      */ | ||||
|     AddressSpace *as = &src->gic->dma_as; | ||||
|     uint64_t idbits; | ||||
|     uint32_t pendt_size; | ||||
|     uint64_t src_baddr; | ||||
|     uint8_t src_pend; | ||||
| 
 | ||||
|     if (!(src->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || | ||||
|         !(dest->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     idbits = MIN(FIELD_EX64(src->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||||
|                  GICD_TYPER_IDBITS); | ||||
|     idbits = MIN(FIELD_EX64(dest->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||||
|                  idbits); | ||||
| 
 | ||||
|     pendt_size = 1ULL << (idbits + 1); | ||||
|     if ((irq / 8) >= pendt_size) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     src_baddr = src->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; | ||||
| 
 | ||||
|     address_space_read(as, src_baddr + (irq / 8), | ||||
|                        MEMTXATTRS_UNSPECIFIED, &src_pend, sizeof(src_pend)); | ||||
|     if (!extract32(src_pend, irq % 8, 1)) { | ||||
|         /* Not pending on source, nothing to do */ | ||||
|         return; | ||||
|     } | ||||
|     src_pend &= ~(1 << (irq % 8)); | ||||
|     address_space_write(as, src_baddr + (irq / 8), | ||||
|                         MEMTXATTRS_UNSPECIFIED, &src_pend, sizeof(src_pend)); | ||||
|     if (irq == src->hpplpi.irq) { | ||||
|         /*
 | ||||
|          * We just made this LPI not-pending so only need to update | ||||
|          * if it was previously the highest priority pending LPI | ||||
|          */ | ||||
|         gicv3_redist_update_lpi(src); | ||||
|     } | ||||
|     /* Mark it pending on the destination */ | ||||
|     gicv3_redist_lpi_pending(dest, irq, 1); | ||||
| } | ||||
| 
 | ||||
| void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest) | ||||
| { | ||||
|     /*
 | ||||
|      * We must move all pending LPIs from the source redistributor | ||||
|      * to the destination. That is, for every pending LPI X on | ||||
|      * src, we must set it not-pending on src and pending on dest. | ||||
|      * LPIs that are already pending on dest are not cleared. | ||||
|      * | ||||
|      * If LPIs are disabled on dest this is CONSTRAINED UNPREDICTABLE: | ||||
|      * we choose to NOP. If LPIs are disabled on source there's nothing | ||||
|      * to be transferred anyway. | ||||
|      */ | ||||
|     AddressSpace *as = &src->gic->dma_as; | ||||
|     uint64_t idbits; | ||||
|     uint32_t pendt_size; | ||||
|     uint64_t src_baddr, dest_baddr; | ||||
|     int i; | ||||
| 
 | ||||
|     if (!(src->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || | ||||
|         !(dest->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     idbits = MIN(FIELD_EX64(src->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||||
|                  GICD_TYPER_IDBITS); | ||||
|     idbits = MIN(FIELD_EX64(dest->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||||
|                  idbits); | ||||
| 
 | ||||
|     pendt_size = 1ULL << (idbits + 1); | ||||
|     src_baddr = src->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; | ||||
|     dest_baddr = dest->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; | ||||
| 
 | ||||
|     for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) { | ||||
|         uint8_t src_pend, dest_pend; | ||||
| 
 | ||||
|         address_space_read(as, src_baddr + i, MEMTXATTRS_UNSPECIFIED, | ||||
|                            &src_pend, sizeof(src_pend)); | ||||
|         if (!src_pend) { | ||||
|             continue; | ||||
|         } | ||||
|         address_space_read(as, dest_baddr + i, MEMTXATTRS_UNSPECIFIED, | ||||
|                            &dest_pend, sizeof(dest_pend)); | ||||
|         dest_pend |= src_pend; | ||||
|         src_pend = 0; | ||||
|         address_space_write(as, src_baddr + i, MEMTXATTRS_UNSPECIFIED, | ||||
|                             &src_pend, sizeof(src_pend)); | ||||
|         address_space_write(as, dest_baddr + i, MEMTXATTRS_UNSPECIFIED, | ||||
|                             &dest_pend, sizeof(dest_pend)); | ||||
|     } | ||||
| 
 | ||||
|     gicv3_redist_update_lpi(src); | ||||
|     gicv3_redist_update_lpi(dest); | ||||
| } | ||||
| 
 | ||||
| void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level) | ||||
| { | ||||
|     /* Update redistributor state for a change in an external PPI input line */ | ||||
|  | ||||
| @ -110,6 +110,7 @@ | ||||
| #define GICR_NSACR            (GICR_SGI_OFFSET + 0x0E00) | ||||
| 
 | ||||
| #define GICR_CTLR_ENABLE_LPIS        (1U << 0) | ||||
| #define GICR_CTLR_CES                (1U << 1) | ||||
| #define GICR_CTLR_RWP                (1U << 3) | ||||
| #define GICR_CTLR_DPG0               (1U << 24) | ||||
| #define GICR_CTLR_DPG1NS             (1U << 25) | ||||
| @ -314,16 +315,18 @@ FIELD(GITS_TYPER, CIL, 36, 1) | ||||
| #define CMD_MASK                  0xff | ||||
| 
 | ||||
| /* ITS Commands */ | ||||
| #define GITS_CMD_CLEAR            0x04 | ||||
| #define GITS_CMD_DISCARD          0x0F | ||||
| #define GITS_CMD_MOVI             0x01 | ||||
| #define GITS_CMD_INT              0x03 | ||||
| #define GITS_CMD_MAPC             0x09 | ||||
| #define GITS_CMD_CLEAR            0x04 | ||||
| #define GITS_CMD_SYNC             0x05 | ||||
| #define GITS_CMD_MAPD             0x08 | ||||
| #define GITS_CMD_MAPI             0x0B | ||||
| #define GITS_CMD_MAPC             0x09 | ||||
| #define GITS_CMD_MAPTI            0x0A | ||||
| #define GITS_CMD_MAPI             0x0B | ||||
| #define GITS_CMD_INV              0x0C | ||||
| #define GITS_CMD_INVALL           0x0D | ||||
| #define GITS_CMD_SYNC             0x05 | ||||
| #define GITS_CMD_MOVALL           0x0E | ||||
| #define GITS_CMD_DISCARD          0x0F | ||||
| 
 | ||||
| /* MAPC command fields */ | ||||
| #define ICID_LENGTH                  16 | ||||
| @ -354,6 +357,15 @@ FIELD(MAPC, RDBASE, 16, 32) | ||||
| #define L2_TABLE_VALID_MASK       CMD_FIELD_VALID_MASK | ||||
| #define TABLE_ENTRY_VALID_MASK    (1ULL << 0) | ||||
| 
 | ||||
| /* MOVALL command fields */ | ||||
| FIELD(MOVALL_2, RDBASE1, 16, 36) | ||||
| FIELD(MOVALL_3, RDBASE2, 16, 36) | ||||
| 
 | ||||
| /* MOVI command fields */ | ||||
| FIELD(MOVI_0, DEVICEID, 32, 32) | ||||
| FIELD(MOVI_1, EVENTID, 0, 32) | ||||
| FIELD(MOVI_2, ICID, 0, 16) | ||||
| 
 | ||||
| /*
 | ||||
|  * 12 bytes Interrupt translation Table Entry size | ||||
|  * as per Table 5.3 in GICv3 spec | ||||
| @ -496,6 +508,27 @@ void gicv3_redist_update_lpi(GICv3CPUState *cs); | ||||
|  * an incoming migration has loaded new state. | ||||
|  */ | ||||
| void gicv3_redist_update_lpi_only(GICv3CPUState *cs); | ||||
| /**
 | ||||
|  * gicv3_redist_mov_lpi: | ||||
|  * @src: source redistributor | ||||
|  * @dest: destination redistributor | ||||
|  * @irq: LPI to update | ||||
|  * | ||||
|  * Move the pending state of the specified LPI from @src to @dest, | ||||
|  * as required by the ITS MOVI command. | ||||
|  */ | ||||
| void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq); | ||||
| /**
 | ||||
|  * gicv3_redist_movall_lpis: | ||||
|  * @src: source redistributor | ||||
|  * @dest: destination redistributor | ||||
|  * | ||||
|  * Scan the LPI pending table for @src, and for each pending LPI there | ||||
|  * mark it as not-pending for @src and pending for @dest, as required | ||||
|  * by the ITS MOVALL command. | ||||
|  */ | ||||
| void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest); | ||||
| 
 | ||||
| void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); | ||||
| void gicv3_init_cpuif(GICv3State *s); | ||||
| 
 | ||||
|  | ||||
| @ -169,6 +169,14 @@ gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned siz | ||||
| gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor 0x%x interrupt %d level changed to %d" | ||||
| gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor 0x%x pending SGI %d" | ||||
| 
 | ||||
| # arm_gicv3_its.c | ||||
| gicv3_its_read(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" | ||||
| gicv3_its_badread(uint64_t offset, unsigned size) "GICv3 ITS read: offset 0x%" PRIx64 " size %u: error" | ||||
| gicv3_its_write(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" | ||||
| gicv3_its_badwrite(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u: error" | ||||
| gicv3_its_translation_write(uint64_t offset, uint64_t data, unsigned size, uint32_t requester_id) "GICv3 ITS TRANSLATER write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u requester_id 0x%x" | ||||
| gicv3_its_process_command(uint32_t rd_offset, uint8_t cmd) "GICv3 ITS: processing command at offset 0x%x: 0x%x" | ||||
| 
 | ||||
| # armv7m_nvic.c | ||||
| nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d" | ||||
| nvic_recompute_state_secure(int vectpending, bool vectpending_is_s_banked, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d is_s_banked %d vectpending_prio %d exception_prio %d" | ||||
|  | ||||
| @ -16,7 +16,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "migration/vmstate.h" | ||||
| #include "hw/sysbus.h" | ||||
| #include "hw/irq.h" | ||||
| @ -30,6 +29,7 @@ | ||||
| #include "hw/qdev-properties.h" | ||||
| #include "hw/qdev-properties-system.h" | ||||
| #include "sysemu/block-backend.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "trace.h" | ||||
| #include "qemu/log.h" | ||||
| 
 | ||||
|  | ||||
| @ -24,7 +24,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/ppc/mac.h" | ||||
| #include "hw/qdev-properties.h" | ||||
| #include "migration/vmstate.h" | ||||
| @ -34,6 +33,7 @@ | ||||
| #include "qapi/error.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "sysemu/runstate.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "qapi/error.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "qemu/log.h" | ||||
|  | ||||
| @ -29,7 +29,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/ppc/mac.h" | ||||
| #include "hw/qdev-properties.h" | ||||
| #include "migration/vmstate.h" | ||||
| @ -41,6 +40,7 @@ | ||||
| #include "qapi/error.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "sysemu/runstate.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "qapi/error.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "qemu/log.h" | ||||
|  | ||||
| @ -84,7 +84,10 @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files( | ||||
| )) | ||||
| softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-xramc.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( | ||||
|   'xlnx-versal-xramc.c', | ||||
|   'xlnx-versal-pmc-iou-slcr.c', | ||||
| )) | ||||
| softmmu_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) | ||||
|  | ||||
							
								
								
									
										1446
									
								
								hw/misc/xlnx-versal-pmc-iou-slcr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1446
									
								
								hw/misc/xlnx-versal-pmc-iou-slcr.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -26,9 +26,9 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "hw/ppc/spapr.h" | ||||
| #include "migration/vmstate.h" | ||||
| #include "qapi/error.h" | ||||
|  | ||||
| @ -23,9 +23,9 @@ | ||||
| #include "migration/vmstate.h" | ||||
| #include "qemu/log.h" | ||||
| #include "qemu/module.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/qdev-properties.h" | ||||
| #include "hw/rtc/allwinner-rtc.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "trace.h" | ||||
| 
 | ||||
| /* RTC registers */ | ||||
|  | ||||
| @ -7,11 +7,11 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/rtc/aspeed_rtc.h" | ||||
| #include "migration/vmstate.h" | ||||
| #include "qemu/log.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "sysemu/rtc.h" | ||||
| 
 | ||||
| #include "trace.h" | ||||
| 
 | ||||
|  | ||||
| @ -11,12 +11,12 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/i2c/i2c.h" | ||||
| #include "migration/vmstate.h" | ||||
| #include "qemu/bcd.h" | ||||
| #include "qemu/module.h" | ||||
| #include "qom/object.h" | ||||
| #include "sysemu/rtc.h" | ||||
| 
 | ||||
| /* Size of NVRAM including both the user-accessible area and the
 | ||||
|  * secondary register area. | ||||
|  | ||||
| @ -26,7 +26,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "qemu/log.h" | ||||
| #include "qemu/module.h" | ||||
| #include "hw/sysbus.h" | ||||
| @ -39,6 +38,7 @@ | ||||
| 
 | ||||
| #include "hw/arm/exynos4210.h" | ||||
| #include "qom/object.h" | ||||
| #include "sysemu/rtc.h" | ||||
| 
 | ||||
| #define DEBUG_RTC 0 | ||||
| 
 | ||||
|  | ||||
| @ -20,7 +20,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/rtc/goldfish_rtc.h" | ||||
| #include "migration/vmstate.h" | ||||
| #include "hw/irq.h" | ||||
| @ -29,6 +28,7 @@ | ||||
| #include "qemu/bitops.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "qemu/log.h" | ||||
| 
 | ||||
|  | ||||
| @ -8,13 +8,13 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "qemu/log.h" | ||||
| #include "qemu/module.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "qemu/bcd.h" | ||||
| #include "hw/i2c/i2c.h" | ||||
| #include "qom/object.h" | ||||
| #include "sysemu/rtc.h" | ||||
| 
 | ||||
| #define TYPE_M41T80 "m41t80" | ||||
| OBJECT_DECLARE_SIMPLE_TYPE(M41t80State, M41T80) | ||||
|  | ||||
| @ -24,12 +24,12 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/irq.h" | ||||
| #include "hw/qdev-properties.h" | ||||
| #include "hw/rtc/m48t59.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "sysemu/runstate.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "hw/sysbus.h" | ||||
| #include "qapi/error.h" | ||||
|  | ||||
| @ -23,7 +23,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "qemu/module.h" | ||||
| #include "qemu/bcd.h" | ||||
| @ -36,6 +35,7 @@ | ||||
| #include "sysemu/replay.h" | ||||
| #include "sysemu/reset.h" | ||||
| #include "sysemu/runstate.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "hw/rtc/mc146818rtc.h" | ||||
| #include "hw/rtc/mc146818rtc_regs.h" | ||||
| #include "migration/vmstate.h" | ||||
|  | ||||
| @ -12,7 +12,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/rtc/pl031.h" | ||||
| #include "migration/vmstate.h" | ||||
| #include "hw/irq.h" | ||||
| @ -20,6 +19,7 @@ | ||||
| #include "hw/sysbus.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "qemu/log.h" | ||||
| #include "qemu/module.h" | ||||
|  | ||||
| @ -20,13 +20,13 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "hw/i2c/i2c.h" | ||||
| #include "hw/irq.h" | ||||
| #include "migration/qemu-file-types.h" | ||||
| #include "migration/vmstate.h" | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "qemu/bcd.h" | ||||
| #include "qemu/module.h" | ||||
| #include "qom/object.h" | ||||
|  | ||||
| @ -25,7 +25,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/sysbus.h" | ||||
| #include "hw/register.h" | ||||
| #include "qemu/bitops.h" | ||||
| @ -34,6 +33,7 @@ | ||||
| #include "hw/irq.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "trace.h" | ||||
| #include "hw/rtc/xlnx-zynqmp-rtc.h" | ||||
| #include "migration/vmstate.h" | ||||
|  | ||||
| @ -9,7 +9,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "qapi/error.h" | ||||
| #include "hw/s390x/tod.h" | ||||
| #include "qemu/timer.h" | ||||
| @ -17,6 +16,7 @@ | ||||
| #include "qemu/module.h" | ||||
| #include "cpu.h" | ||||
| #include "tcg/tcg_s390x.h" | ||||
| #include "sysemu/rtc.h" | ||||
| 
 | ||||
| static void qemu_s390_tod_get(const S390TODState *td, S390TOD *tod, | ||||
|                               Error **errp) | ||||
|  | ||||
| @ -19,11 +19,11 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "hw/pci/pci.h" | ||||
| #include "hw/qdev-properties.h" | ||||
| #include "sysemu/dma.h" | ||||
| #include "sysemu/block-backend.h" | ||||
| #include "sysemu/rtc.h" | ||||
| #include "hw/pci/msi.h" | ||||
| #include "hw/pci/msix.h" | ||||
| #include "qemu/iov.h" | ||||
|  | ||||
| @ -7,5 +7,6 @@ softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_XILINX_SPI', if_true: files('xilinx_spi.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_XILINX_SPIPS', if_true: files('xilinx_spips.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-ospi.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_spi.c')) | ||||
| softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_spi.c')) | ||||
|  | ||||
							
								
								
									
										1853
									
								
								hw/ssi/xlnx-versal-ospi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1853
									
								
								hw/ssi/xlnx-versal-ospi.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -26,6 +26,9 @@ | ||||
| #include "hw/misc/xlnx-versal-xramc.h" | ||||
| #include "hw/nvram/xlnx-bbram.h" | ||||
| #include "hw/nvram/xlnx-versal-efuse.h" | ||||
| #include "hw/ssi/xlnx-versal-ospi.h" | ||||
| #include "hw/dma/xlnx_csu_dma.h" | ||||
| #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" | ||||
| 
 | ||||
| #define TYPE_XLNX_VERSAL "xlnx-versal" | ||||
| OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) | ||||
| @ -78,6 +81,15 @@ struct Versal { | ||||
|     struct { | ||||
|         struct { | ||||
|             SDHCIState sd[XLNX_VERSAL_NR_SDS]; | ||||
|             XlnxVersalPmcIouSlcr slcr; | ||||
| 
 | ||||
|             struct { | ||||
|                 XlnxVersalOspi ospi; | ||||
|                 XlnxCSUDMA dma_src; | ||||
|                 XlnxCSUDMA dma_dst; | ||||
|                 MemoryRegion linear_mr; | ||||
|                 qemu_or_irq irq_orgate; | ||||
|             } ospi; | ||||
|         } iou; | ||||
| 
 | ||||
|         XlnxZynqMPRTC rtc; | ||||
| @ -85,6 +97,8 @@ struct Versal { | ||||
|         XlnxEFuse efuse; | ||||
|         XlnxVersalEFuseCtrl efuse_ctrl; | ||||
|         XlnxVersalEFuseCache efuse_cache; | ||||
| 
 | ||||
|         qemu_or_irq apb_irq_orgate; | ||||
|     } pmc; | ||||
| 
 | ||||
|     struct { | ||||
| @ -111,8 +125,8 @@ struct Versal { | ||||
| #define VERSAL_GEM1_WAKE_IRQ_0     59 | ||||
| #define VERSAL_ADMA_IRQ_0          60 | ||||
| #define VERSAL_XRAM_IRQ_0          79 | ||||
| #define VERSAL_BBRAM_APB_IRQ_0     121 | ||||
| #define VERSAL_RTC_APB_ERR_IRQ     121 | ||||
| #define VERSAL_PMC_APB_IRQ         121 | ||||
| #define VERSAL_OSPI_IRQ            124 | ||||
| #define VERSAL_SD0_IRQ_0           126 | ||||
| #define VERSAL_EFUSE_IRQ           139 | ||||
| #define VERSAL_RTC_ALARM_IRQ       142 | ||||
| @ -178,6 +192,18 @@ struct Versal { | ||||
| #define MM_FPD_FPD_APU              0xfd5c0000 | ||||
| #define MM_FPD_FPD_APU_SIZE         0x100 | ||||
| 
 | ||||
| #define MM_PMC_PMC_IOU_SLCR         0xf1060000 | ||||
| #define MM_PMC_PMC_IOU_SLCR_SIZE    0x10000 | ||||
| 
 | ||||
| #define MM_PMC_OSPI                 0xf1010000 | ||||
| #define MM_PMC_OSPI_SIZE            0x10000 | ||||
| 
 | ||||
| #define MM_PMC_OSPI_DAC             0xc0000000 | ||||
| #define MM_PMC_OSPI_DAC_SIZE        0x20000000 | ||||
| 
 | ||||
| #define MM_PMC_OSPI_DMA_DST         0xf1011800 | ||||
| #define MM_PMC_OSPI_DMA_SRC         0xf1011000 | ||||
| 
 | ||||
| #define MM_PMC_SD0                  0xf1040000U | ||||
| #define MM_PMC_SD0_SIZE             0x10000 | ||||
| #define MM_PMC_BBRAM_CTRL           0xf11f0000 | ||||
|  | ||||
| @ -21,6 +21,11 @@ | ||||
| #ifndef XLNX_CSU_DMA_H | ||||
| #define XLNX_CSU_DMA_H | ||||
| 
 | ||||
| #include "hw/sysbus.h" | ||||
| #include "hw/register.h" | ||||
| #include "hw/ptimer.h" | ||||
| #include "hw/stream.h" | ||||
| 
 | ||||
| #define TYPE_XLNX_CSU_DMA "xlnx.csu_dma" | ||||
| 
 | ||||
| #define XLNX_CSU_DMA_R_MAX (0x2c / 4) | ||||
| @ -46,7 +51,22 @@ typedef struct XlnxCSUDMA { | ||||
|     RegisterInfo regs_info[XLNX_CSU_DMA_R_MAX]; | ||||
| } XlnxCSUDMA; | ||||
| 
 | ||||
| #define XLNX_CSU_DMA(obj) \ | ||||
|     OBJECT_CHECK(XlnxCSUDMA, (obj), TYPE_XLNX_CSU_DMA) | ||||
| OBJECT_DECLARE_TYPE(XlnxCSUDMA, XlnxCSUDMAClass, XLNX_CSU_DMA) | ||||
| 
 | ||||
| struct XlnxCSUDMAClass { | ||||
|     SysBusDeviceClass parent_class; | ||||
| 
 | ||||
|     /*
 | ||||
|      * read: Start a read transfer on a Xilinx CSU DMA engine | ||||
|      * | ||||
|      * @s: the Xilinx CSU DMA engine to start the transfer on | ||||
|      * @addr: the address to read | ||||
|      * @len: the number of bytes to read at 'addr' | ||||
|      * | ||||
|      * @return a MemTxResult indicating whether the operation succeeded ('len' | ||||
|      * bytes were read) or failed. | ||||
|      */ | ||||
|     MemTxResult (*read)(XlnxCSUDMA *s, hwaddr addr, uint32_t len); | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -47,7 +47,6 @@ typedef struct { | ||||
|     uint16_t entry_sz; | ||||
|     uint32_t page_sz; | ||||
|     uint32_t num_entries; | ||||
|     uint32_t num_ids; | ||||
|     uint64_t base_addr; | ||||
| } TableDesc; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										78
									
								
								include/hw/misc/xlnx-versal-pmc-iou-slcr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								include/hw/misc/xlnx-versal-pmc-iou-slcr.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| /*
 | ||||
|  * Header file for the Xilinx Versal's PMC IOU SLCR | ||||
|  * | ||||
|  * Copyright (C) 2021 Xilinx Inc | ||||
|  * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * This is a model of Xilinx Versal's PMC I/O Peripheral Control and Status | ||||
|  * module documented in Versal's Technical Reference manual [1] and the Versal | ||||
|  * ACAP Register reference [2]. | ||||
|  * | ||||
|  * References: | ||||
|  * | ||||
|  * [1] Versal ACAP Technical Reference Manual, | ||||
|  *     https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
 | ||||
|  * | ||||
|  * [2] Versal ACAP Register Reference, | ||||
|  *     https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___pmc_iop_slcr.html
 | ||||
|  * | ||||
|  * QEMU interface: | ||||
|  * + sysbus MMIO region 0: MemoryRegion for the device's registers | ||||
|  * + sysbus IRQ 0: PMC (AXI and APB) parity error interrupt detected by the PMC | ||||
|  *   I/O peripherals. | ||||
|  * + sysbus IRQ 1: Device interrupt. | ||||
|  * + Named GPIO output "sd-emmc-sel[0]": Enables 0: SD mode or 1: eMMC mode on | ||||
|  *   SD/eMMC controller 0. | ||||
|  * + Named GPIO output "sd-emmc-sel[1]": Enables 0: SD mode or 1: eMMC mode on | ||||
|  *   SD/eMMC controller 1. | ||||
|  * + Named GPIO output "qspi-ospi-mux-sel": Selects 0: QSPI linear region or 1: | ||||
|  *   OSPI linear region. | ||||
|  * + Named GPIO output "ospi-mux-sel": Selects 0: OSPI Indirect access mode or | ||||
|  *   1: OSPI direct access mode. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef XILINX_VERSAL_PMC_IOU_SLCR_H | ||||
| #define XILINX_VERSAL_PMC_IOU_SLCR_H | ||||
| 
 | ||||
| #include "hw/register.h" | ||||
| 
 | ||||
| #define TYPE_XILINX_VERSAL_PMC_IOU_SLCR "xlnx.versal-pmc-iou-slcr" | ||||
| 
 | ||||
| OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalPmcIouSlcr, XILINX_VERSAL_PMC_IOU_SLCR) | ||||
| 
 | ||||
| #define XILINX_VERSAL_PMC_IOU_SLCR_R_MAX (0x828 / 4 + 1) | ||||
| 
 | ||||
| struct XlnxVersalPmcIouSlcr { | ||||
|     SysBusDevice parent_obj; | ||||
|     MemoryRegion iomem; | ||||
|     qemu_irq irq_parity_imr; | ||||
|     qemu_irq irq_imr; | ||||
|     qemu_irq sd_emmc_sel[2]; | ||||
|     qemu_irq qspi_ospi_mux_sel; | ||||
|     qemu_irq ospi_mux_sel; | ||||
| 
 | ||||
|     uint32_t regs[XILINX_VERSAL_PMC_IOU_SLCR_R_MAX]; | ||||
|     RegisterInfo regs_info[XILINX_VERSAL_PMC_IOU_SLCR_R_MAX]; | ||||
| }; | ||||
| 
 | ||||
| #endif /* XILINX_VERSAL_PMC_IOU_SLCR_H */ | ||||
							
								
								
									
										111
									
								
								include/hw/ssi/xlnx-versal-ospi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								include/hw/ssi/xlnx-versal-ospi.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| /*
 | ||||
|  * Header file for the Xilinx Versal's OSPI controller | ||||
|  * | ||||
|  * Copyright (C) 2021 Xilinx Inc | ||||
|  * Written by Francisco Iglesias <francisco.iglesias@xilinx.com> | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * This is a model of Xilinx Versal's Octal SPI flash memory controller | ||||
|  * documented in Versal's Technical Reference manual [1] and the Versal ACAP | ||||
|  * Register reference [2]. | ||||
|  * | ||||
|  * References: | ||||
|  * | ||||
|  * [1] Versal ACAP Technical Reference Manual, | ||||
|  *     https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
 | ||||
|  * | ||||
|  * [2] Versal ACAP Register Reference, | ||||
|  *     https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___ospi.html
 | ||||
|  * | ||||
|  * | ||||
|  * QEMU interface: | ||||
|  * + sysbus MMIO region 0: MemoryRegion for the device's registers | ||||
|  * + sysbus MMIO region 1: MemoryRegion for flash memory linear address space | ||||
|  *   (data transfer). | ||||
|  * + sysbus IRQ 0: Device interrupt. | ||||
|  * + Named GPIO input "ospi-mux-sel": 0: enables indirect access mode | ||||
|  *   and 1: enables direct access mode. | ||||
|  * + Property "dac-with-indac": Allow both direct accesses and indirect | ||||
|  *   accesses simultaneously. | ||||
|  * + Property "indac-write-disabled": Disable indirect access writes. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef XILINX_VERSAL_OSPI_H | ||||
| #define XILINX_VERSAL_OSPI_H | ||||
| 
 | ||||
| #include "hw/register.h" | ||||
| #include "hw/ssi/ssi.h" | ||||
| #include "qemu/fifo8.h" | ||||
| #include "hw/dma/xlnx_csu_dma.h" | ||||
| 
 | ||||
| #define TYPE_XILINX_VERSAL_OSPI "xlnx.versal-ospi" | ||||
| 
 | ||||
| OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalOspi, XILINX_VERSAL_OSPI) | ||||
| 
 | ||||
| #define XILINX_VERSAL_OSPI_R_MAX (0xfc / 4 + 1) | ||||
| 
 | ||||
| /*
 | ||||
|  * Indirect operations | ||||
|  */ | ||||
| typedef struct IndOp { | ||||
|     uint32_t flash_addr; | ||||
|     uint32_t num_bytes; | ||||
|     uint32_t done_bytes; | ||||
|     bool completed; | ||||
| } IndOp; | ||||
| 
 | ||||
| struct XlnxVersalOspi { | ||||
|     SysBusDevice parent_obj; | ||||
| 
 | ||||
|     MemoryRegion iomem; | ||||
|     MemoryRegion iomem_dac; | ||||
| 
 | ||||
|     uint8_t num_cs; | ||||
|     qemu_irq *cs_lines; | ||||
| 
 | ||||
|     SSIBus *spi; | ||||
| 
 | ||||
|     Fifo8 rx_fifo; | ||||
|     Fifo8 tx_fifo; | ||||
| 
 | ||||
|     Fifo8 rx_sram; | ||||
|     Fifo8 tx_sram; | ||||
| 
 | ||||
|     qemu_irq irq; | ||||
| 
 | ||||
|     XlnxCSUDMA *dma_src; | ||||
|     bool ind_write_disabled; | ||||
|     bool dac_with_indac; | ||||
|     bool dac_enable; | ||||
|     bool src_dma_inprog; | ||||
| 
 | ||||
|     IndOp rd_ind_op[2]; | ||||
|     IndOp wr_ind_op[2]; | ||||
| 
 | ||||
|     uint32_t regs[XILINX_VERSAL_OSPI_R_MAX]; | ||||
|     RegisterInfo regs_info[XILINX_VERSAL_OSPI_R_MAX]; | ||||
| 
 | ||||
|     /* Maximum inferred membank size is 512 bytes */ | ||||
|     uint8_t stig_membank[512]; | ||||
| }; | ||||
| 
 | ||||
| #endif /* XILINX_VERSAL_OSPI_H */ | ||||
| @ -13,7 +13,7 @@ | ||||
| #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) | ||||
| 
 | ||||
| /* Copyright string for -version arguments, About dialogs, etc */ | ||||
| #define QEMU_COPYRIGHT "Copyright (c) 2003-2021 " \ | ||||
| #define QEMU_COPYRIGHT "Copyright (c) 2003-2022 " \ | ||||
|     "Fabrice Bellard and the QEMU Project developers" | ||||
| 
 | ||||
| /* Bug reporting information for --help arguments, About dialogs, etc */ | ||||
| @ -26,9 +26,6 @@ | ||||
| int qemu_main(int argc, char **argv, char **envp); | ||||
| #endif | ||||
| 
 | ||||
| void qemu_get_timedate(struct tm *tm, int offset); | ||||
| int qemu_timedate_diff(struct tm *tm); | ||||
| 
 | ||||
| void *qemu_oom_check(void *ptr); | ||||
| 
 | ||||
| ssize_t qemu_write_full(int fd, const void *buf, size_t count) | ||||
|  | ||||
							
								
								
									
										58
									
								
								include/sysemu/rtc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								include/sysemu/rtc.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| /*
 | ||||
|  * RTC configuration and clock read | ||||
|  * | ||||
|  * Copyright (c) 2003-2021 QEMU contributors | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef SYSEMU_RTC_H | ||||
| #define SYSEMU_RTC_H | ||||
| 
 | ||||
| /**
 | ||||
|  * qemu_get_timedate: Get the current RTC time | ||||
|  * @tm: struct tm to fill in with RTC time | ||||
|  * @offset: offset in seconds to adjust the RTC time by before | ||||
|  *          converting to struct tm format. | ||||
|  * | ||||
|  * This function fills in @tm with the current RTC time, as adjusted | ||||
|  * by @offset (for example, if @offset is 3600 then the returned time/date | ||||
|  * will be one hour further ahead than the current RTC time). | ||||
|  * | ||||
|  * The usual use is by RTC device models, which should call this function | ||||
|  * to find the time/date value that they should return to the guest | ||||
|  * when it reads the RTC registers. | ||||
|  * | ||||
|  * The behaviour of the clock whose value this function returns will | ||||
|  * depend on the -rtc command line option passed by the user. | ||||
|  */ | ||||
| void qemu_get_timedate(struct tm *tm, int offset); | ||||
| 
 | ||||
| /**
 | ||||
|  * qemu_timedate_diff: Return difference between a struct tm and the RTC | ||||
|  * @tm: struct tm containing the date/time to compare against | ||||
|  * | ||||
|  * Returns the difference in seconds between the RTC clock time | ||||
|  * and the date/time specified in @tm. For example, if @tm specifies | ||||
|  * a timestamp one hour further ahead than the current RTC time | ||||
|  * then this function will return 3600. | ||||
|  */ | ||||
| int qemu_timedate_diff(struct tm *tm); | ||||
| 
 | ||||
| #endif | ||||
| @ -23,7 +23,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "clients.h" | ||||
| #include "qapi/error.h" | ||||
| #include "qemu/error-report.h" | ||||
| @ -33,6 +32,7 @@ | ||||
| #include "qapi/visitor.h" | ||||
| #include "net/filter.h" | ||||
| #include "qom/object.h" | ||||
| #include "sysemu/rtc.h" | ||||
| 
 | ||||
| typedef struct DumpState { | ||||
|     int64_t start_ts; | ||||
|  | ||||
| @ -9,6 +9,22 @@ | ||||
| # | ||||
| # This work is licensed under the terms of the GNU GPL version 2. | ||||
| # See the COPYING file in the top-level directory. | ||||
| # | ||||
| # The script will copy the headers into two target folders: | ||||
| # | ||||
| # - linux-headers/ for files that are required for compiling for a | ||||
| #   Linux host.  Generally we have these so we can use kernel structs | ||||
| #   and defines that are more recent than the headers that might be | ||||
| #   installed on the host system.  Usually this script can do simple | ||||
| #   file copies for these headers. | ||||
| # | ||||
| # - include/standard-headers/ for files that are used for guest | ||||
| #   device emulation and are required on all hosts.  For instance, we | ||||
| #   get our definitions of the virtio structures from the Linux | ||||
| #   kernel headers, but we need those definitions regardless of which | ||||
| #   host OS we are building for.  This script has to be careful to | ||||
| #   sanitize the headers to remove any use of Linux-specifics such as | ||||
| #   types like "__u64".  This work is done in the cp_portable function. | ||||
| 
 | ||||
| tmpdir=$(mktemp -d) | ||||
| linux="$1" | ||||
|  | ||||
| @ -23,7 +23,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu-common.h" | ||||
| #include "qemu/cutils.h" | ||||
| #include "qapi/error.h" | ||||
| #include "qapi/qmp/qerror.h" | ||||
| @ -33,6 +32,7 @@ | ||||
| #include "qom/object.h" | ||||
| #include "sysemu/replay.h" | ||||
| #include "sysemu/sysemu.h" | ||||
| #include "sysemu/rtc.h" | ||||
| 
 | ||||
| static enum { | ||||
|     RTC_BASE_UTC, | ||||
|  | ||||
| @ -9317,8 +9317,10 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, | ||||
|     return target_el; | ||||
| } | ||||
| 
 | ||||
| void arm_log_exception(int idx) | ||||
| void arm_log_exception(CPUState *cs) | ||||
| { | ||||
|     int idx = cs->exception_index; | ||||
| 
 | ||||
|     if (qemu_loglevel_mask(CPU_LOG_INT)) { | ||||
|         const char *exc = NULL; | ||||
|         static const char * const excnames[] = { | ||||
| @ -9352,7 +9354,8 @@ void arm_log_exception(int idx) | ||||
|         if (!exc) { | ||||
|             exc = "unknown"; | ||||
|         } | ||||
|         qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc); | ||||
|         qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s] on CPU %d\n", | ||||
|                       idx, exc, cs->cpu_index); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -9655,7 +9658,7 @@ static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs) | ||||
|      * separately here. | ||||
|      * | ||||
|      * The vector table entry used is always the 0x14 Hyp mode entry point, | ||||
|      * unless this is an UNDEF/HVC/abort taken from Hyp to Hyp. | ||||
|      * unless this is an UNDEF/SVC/HVC/abort taken from Hyp to Hyp. | ||||
|      * The offset applied to the preferred return address is always zero | ||||
|      * (see DDI0487C.a section G1.12.3). | ||||
|      * PSTATE A/I/F masks are set based only on the SCR.EA/IRQ/FIQ values. | ||||
| @ -9669,7 +9672,7 @@ static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs) | ||||
|         addr = 0x04; | ||||
|         break; | ||||
|     case EXCP_SWI: | ||||
|         addr = 0x14; | ||||
|         addr = 0x08; | ||||
|         break; | ||||
|     case EXCP_BKPT: | ||||
|         /* Fall through to prefetch abort.  */ | ||||
| @ -10185,7 +10188,7 @@ void arm_cpu_do_interrupt(CPUState *cs) | ||||
| 
 | ||||
|     assert(!arm_feature(env, ARM_FEATURE_M)); | ||||
| 
 | ||||
|     arm_log_exception(cs->exception_index); | ||||
|     arm_log_exception(cs); | ||||
|     qemu_log_mask(CPU_LOG_INT, "...from EL%d to EL%d\n", arm_current_el(env), | ||||
|                   new_el); | ||||
|     if (qemu_loglevel_mask(CPU_LOG_INT) | ||||
|  | ||||
| @ -1130,7 +1130,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, | ||||
|                    ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) | ||||
|     __attribute__((nonnull)); | ||||
| 
 | ||||
| void arm_log_exception(int idx); | ||||
| void arm_log_exception(CPUState *cs); | ||||
| 
 | ||||
| #endif /* !CONFIG_USER_ONLY */ | ||||
| 
 | ||||
|  | ||||
| @ -2206,7 +2206,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) | ||||
|     uint32_t lr; | ||||
|     bool ignore_stackfaults; | ||||
| 
 | ||||
|     arm_log_exception(cs->exception_index); | ||||
|     arm_log_exception(cs); | ||||
| 
 | ||||
|     /*
 | ||||
|      * For exceptions we just mark as pending on the NVIC, and let that | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Peter Maydell
						Peter Maydell