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>
staging
Peter Maydell 2022-01-28 16:59:56 +00:00
commit 95a6af2a00
52 changed files with 4300 additions and 74 deletions

View File

@ -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

View File

@ -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

View File

@ -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()
}
};

View File

@ -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,

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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)

View File

@ -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);

View File

@ -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) },

View File

@ -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),

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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 */

View File

@ -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);

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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'))

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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 */

View File

@ -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"

View File

@ -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.

View File

@ -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

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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'))

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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;

View 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 */

View 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 */

View File

@ -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)

View 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

View File

@ -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;

View File

@ -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"

View File

@ -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,

View File

@ -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)

View File

@ -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 */

View File

@ -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