aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/Kconfig1
-rw-r--r--hw/Makefile.objs1
-rw-r--r--hw/alpha/dp264.c2
-rw-r--r--hw/arm/aspeed.c23
-rw-r--r--hw/arm/bcm2835_peripherals.c30
-rw-r--r--hw/arm/bcm2836.c44
-rw-r--r--hw/arm/collie.c8
-rw-r--r--hw/arm/digic_boards.c9
-rw-r--r--hw/arm/exynos4210.c2
-rw-r--r--hw/arm/highbank.c3
-rw-r--r--hw/arm/mps2-tz.c3
-rw-r--r--hw/arm/mps2.c3
-rw-r--r--hw/arm/musca.c2
-rw-r--r--hw/arm/nseries.c10
-rw-r--r--hw/arm/omap1.c12
-rw-r--r--hw/arm/omap2.c13
-rw-r--r--hw/arm/omap_sx1.c8
-rw-r--r--hw/arm/palm.c8
-rw-r--r--hw/arm/raspi.c14
-rw-r--r--hw/arm/strongarm.c7
-rw-r--r--hw/arm/strongarm.h4
-rw-r--r--hw/arm/xilinx_zynq.c3
-rw-r--r--hw/block/virtio-blk.c1
-rw-r--r--hw/dma/xilinx_axidma.c9
-rw-r--r--hw/gpio/aspeed_gpio.c8
-rw-r--r--hw/hppa/machine.c7
-rw-r--r--hw/i386/acpi-build.c2
-rw-r--r--hw/i386/microvm.c2
-rw-r--r--hw/i386/pc.c2
-rw-r--r--hw/i386/pc_q35.c2
-rw-r--r--hw/intc/armv7m_nvic.c22
-rw-r--r--hw/intc/pnv_xive.c20
-rw-r--r--hw/intc/spapr_xive.c324
-rw-r--r--hw/intc/spapr_xive_kvm.c22
-rw-r--r--hw/intc/xics.c18
-rw-r--r--hw/intc/xics_kvm.c9
-rw-r--r--hw/intc/xics_spapr.c117
-rw-r--r--hw/intc/xive.c31
-rw-r--r--hw/m68k/mcf5206.c15
-rw-r--r--hw/m68k/mcf5208.c9
-rw-r--r--hw/mips/mips_fulong2e.c2
-rw-r--r--hw/mips/mips_jazz.c2
-rw-r--r--hw/mips/mips_malta.c2
-rw-r--r--hw/mips/mips_r4k.c2
-rw-r--r--hw/misc/Makefile.objs1
-rw-r--r--hw/misc/bcm2835_thermal.c135
-rw-r--r--hw/net/fsl_etsec/etsec.c9
-rw-r--r--hw/net/fsl_etsec/etsec.h1
-rw-r--r--hw/pci/pci_bridge.c2
-rw-r--r--hw/ppc/pnv.c20
-rw-r--r--hw/ppc/pnv_core.c31
-rw-r--r--hw/ppc/pnv_psi.c15
-rw-r--r--hw/ppc/ppc405_boards.c2
-rw-r--r--hw/ppc/prep.c4
-rw-r--r--hw/ppc/rs6000_mc.c15
-rw-r--r--hw/ppc/spapr.c26
-rw-r--r--hw/ppc/spapr_cpu_core.c47
-rw-r--r--hw/ppc/spapr_irq.c611
-rw-r--r--hw/ppc/spapr_pci.c7
-rw-r--r--hw/rtc/Kconfig23
-rw-r--r--hw/rtc/Makefile.objs13
-rw-r--r--hw/rtc/aspeed_rtc.c (renamed from hw/timer/aspeed_rtc.c)2
-rw-r--r--hw/rtc/ds1338.c (renamed from hw/timer/ds1338.c)0
-rw-r--r--hw/rtc/exynos4210_rtc.c (renamed from hw/timer/exynos4210_rtc.c)0
-rw-r--r--hw/rtc/m41t80.c (renamed from hw/timer/m41t80.c)0
-rw-r--r--hw/rtc/m48t59-internal.h (renamed from hw/timer/m48t59-internal.h)0
-rw-r--r--hw/rtc/m48t59-isa.c (renamed from hw/timer/m48t59-isa.c)4
-rw-r--r--hw/rtc/m48t59.c (renamed from hw/timer/m48t59.c)2
-rw-r--r--hw/rtc/mc146818rtc.c (renamed from hw/timer/mc146818rtc.c)5
-rw-r--r--hw/rtc/pl031.c (renamed from hw/timer/pl031.c)2
-rw-r--r--hw/rtc/sun4v-rtc.c (renamed from hw/timer/sun4v-rtc.c)2
-rw-r--r--hw/rtc/trace-events19
-rw-r--r--hw/rtc/twl92230.c (renamed from hw/timer/twl92230.c)0
-rw-r--r--hw/rtc/xlnx-zynqmp-rtc.c (renamed from hw/timer/xlnx-zynqmp-rtc.c)3
-rw-r--r--hw/sd/sdhci.c68
-rw-r--r--hw/sparc/sun4m.c2
-rw-r--r--hw/sparc64/niagara.c27
-rw-r--r--hw/sparc64/sun4u.c2
-rw-r--r--hw/timer/Kconfig24
-rw-r--r--hw/timer/Makefile.objs36
-rw-r--r--hw/timer/altera_timer.c13
-rw-r--r--hw/timer/arm_mptimer.c4
-rw-r--r--hw/timer/bcm2835_systmr.c163
-rw-r--r--hw/timer/etraxfs_timer.c23
-rw-r--r--hw/timer/exynos4210_mct.c2
-rw-r--r--hw/timer/grlib_gptimer.c28
-rw-r--r--hw/timer/hpet.c3
-rw-r--r--hw/timer/lm32_timer.c13
-rw-r--r--hw/timer/milkymist-sysctl.c25
-rw-r--r--hw/timer/puv3_ost.c9
-rw-r--r--hw/timer/sh_timer.c13
-rw-r--r--hw/timer/slavio_timer.c32
-rw-r--r--hw/timer/trace-events21
-rw-r--r--hw/timer/xilinx_timer.c13
-rw-r--r--hw/xtensa/Kconfig6
-rw-r--r--hw/xtensa/Makefile.objs1
-rw-r--r--hw/xtensa/sim.c41
-rw-r--r--hw/xtensa/virt.c135
-rw-r--r--hw/xtensa/xtensa_sim.h34
99 files changed, 1699 insertions, 878 deletions
diff --git a/hw/Kconfig b/hw/Kconfig
index b45db3c813..4b53fee4d0 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -27,6 +27,7 @@ source pci-host/Kconfig
source pcmcia/Kconfig
source pci/Kconfig
source rdma/Kconfig
+source rtc/Kconfig
source scsi/Kconfig
source sd/Kconfig
source semihosting/Kconfig
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index ece6cc3755..fd9750e5f2 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -26,6 +26,7 @@ devices-dirs-y += nvram/
devices-dirs-y += pci/
devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/
devices-dirs-y += pcmcia/
+devices-dirs-y += rtc/
devices-dirs-$(CONFIG_SCSI) += scsi/
devices-dirs-y += sd/
devices-dirs-y += ssi/
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 51feee8558..51b3cf7a61 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -14,7 +14,7 @@
#include "alpha_sys.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/ide.h"
#include "hw/timer/i8254.h"
#include "hw/isa/superio.h"
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 52993f84b4..028191ff36 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -88,6 +88,10 @@ struct AspeedBoardState {
/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
+/* AST2600 evb hardware value */
+#define AST2600_EVB_HW_STRAP1 0x000000C0
+#define AST2600_EVB_HW_STRAP2 0x00000003
+
/*
* The max ram region is for firmwares that scan the address space
* with load/store to guess how much RAM the SoC has.
@@ -187,6 +191,8 @@ static void aspeed_board_init(MachineState *machine,
&error_abort);
object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
&error_abort);
+ object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap2, "hw-strap2",
+ &error_abort);
object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
&error_abort);
object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus",
@@ -308,6 +314,12 @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
}
+static void ast2600_evb_i2c_init(AspeedBoardState *bmc)
+{
+ /* Start with some devices on our I2C busses */
+ ast2500_evb_i2c_init(bmc);
+}
+
static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
{
AspeedSoCState *soc = &bmc->soc;
@@ -455,6 +467,17 @@ static const AspeedBoardConfig aspeed_boards[] = {
.num_cs = 2,
.i2c_init = witherspoon_bmc_i2c_init,
.ram = 512 * MiB,
+ }, {
+ .name = MACHINE_TYPE_NAME("ast2600-evb"),
+ .desc = "Aspeed AST2600 EVB (Cortex A7)",
+ .soc_name = "ast2600-a0",
+ .hw_strap1 = AST2600_EVB_HW_STRAP1,
+ .hw_strap2 = AST2600_EVB_HW_STRAP2,
+ .fmc_model = "w25q512jv",
+ .spi_model = "mx66u51235f",
+ .num_cs = 1,
+ .i2c_init = ast2600_evb_i2c_init,
+ .ram = 1 * GiB,
},
};
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index fdcf616c56..17207ae07e 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -58,6 +58,10 @@ static void bcm2835_peripherals_init(Object *obj)
/* Interrupt Controller */
sysbus_init_child_obj(obj, "ic", &s->ic, sizeof(s->ic), TYPE_BCM2835_IC);
+ /* SYS Timer */
+ sysbus_init_child_obj(obj, "systimer", &s->systmr, sizeof(s->systmr),
+ TYPE_BCM2835_SYSTIMER);
+
/* UART0 */
sysbus_init_child_obj(obj, "uart0", &s->uart0, sizeof(s->uart0),
TYPE_PL011);
@@ -111,6 +115,10 @@ static void bcm2835_peripherals_init(Object *obj)
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
OBJECT(&s->gpu_bus_mr), &error_abort);
+ /* Thermal */
+ sysbus_init_child_obj(obj, "thermal", &s->thermal, sizeof(s->thermal),
+ TYPE_BCM2835_THERMAL);
+
/* GPIO */
sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
TYPE_BCM2835_GPIO);
@@ -167,6 +175,18 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
+ /* Sys Timer */
+ object_property_set_bool(OBJECT(&s->systmr), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
+ INTERRUPT_ARM_TIMER));
+
/* UART0 */
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
object_property_set_bool(OBJECT(&s->uart0), true, "realized", &err);
@@ -321,6 +341,15 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
INTERRUPT_DMA0 + n));
}
+ /* THERMAL */
+ object_property_set_bool(OBJECT(&s->thermal), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ memory_region_add_subregion(&s->peri_mr, THERMAL_OFFSET,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->thermal), 0));
+
/* GPIO */
object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
if (err) {
@@ -339,7 +368,6 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
}
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
- create_unimp(s, &s->systmr, "bcm2835-systimer", ST_OFFSET, 0x20);
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 723aef6bf5..221ff06895 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -16,15 +16,11 @@
#include "hw/arm/raspi_platform.h"
#include "hw/sysbus.h"
-/* Peripheral base address seen by the CPU */
-#define BCM2836_PERI_BASE 0x3F000000
-
-/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
-#define BCM2836_CONTROL_BASE 0x40000000
-
struct BCM283XInfo {
const char *name;
const char *cpu_type;
+ hwaddr peri_base; /* Peripheral base address seen by the CPU */
+ hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
int clusterid;
};
@@ -32,12 +28,16 @@ static const BCM283XInfo bcm283x_socs[] = {
{
.name = TYPE_BCM2836,
.cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"),
+ .peri_base = 0x3f000000,
+ .ctrl_base = 0x40000000,
.clusterid = 0xf,
},
#ifdef TARGET_AARCH64
{
.name = TYPE_BCM2837,
.cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
+ .peri_base = 0x3f000000,
+ .ctrl_base = 0x40000000,
.clusterid = 0x0,
},
#endif
@@ -51,8 +51,9 @@ static void bcm2836_init(Object *obj)
int n;
for (n = 0; n < BCM283X_NCPUS; n++) {
- object_initialize_child(obj, "cpu[*]", &s->cpus[n], sizeof(s->cpus[n]),
- info->cpu_type, &error_abort, NULL);
+ object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
+ sizeof(s->cpu[n].core), info->cpu_type,
+ &error_abort, NULL);
}
sysbus_init_child_obj(obj, "control", &s->control, sizeof(s->control),
@@ -104,7 +105,7 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
}
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
- BCM2836_PERI_BASE, 1);
+ info->peri_base, 1);
/* bcm2836 interrupt controller (and mailboxes, etc.) */
object_property_set_bool(OBJECT(&s->control), true, "realized", &err);
@@ -113,7 +114,7 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
return;
}
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, BCM2836_CONTROL_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, info->ctrl_base);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0));
@@ -122,11 +123,11 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
for (n = 0; n < BCM283X_NCPUS; n++) {
/* TODO: this should be converted to a property of ARM_CPU */
- s->cpus[n].mp_affinity = (info->clusterid << 8) | n;
+ s->cpu[n].core.mp_affinity = (info->clusterid << 8) | n;
/* set periphbase/CBAR value for CPU-local registers */
- object_property_set_int(OBJECT(&s->cpus[n]),
- BCM2836_PERI_BASE + MSYNC_OFFSET,
+ object_property_set_int(OBJECT(&s->cpu[n].core),
+ info->peri_base,
"reset-cbar", &err);
if (err) {
error_propagate(errp, err);
@@ -134,14 +135,15 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
}
/* start powered off if not enabled */
- object_property_set_bool(OBJECT(&s->cpus[n]), n >= s->enabled_cpus,
+ object_property_set_bool(OBJECT(&s->cpu[n].core), n >= s->enabled_cpus,
"start-powered-off", &err);
if (err) {
error_propagate(errp, err);
return;
}
- object_property_set_bool(OBJECT(&s->cpus[n]), true, "realized", &err);
+ object_property_set_bool(OBJECT(&s->cpu[n].core), true,
+ "realized", &err);
if (err) {
error_propagate(errp, err);
return;
@@ -149,18 +151,18 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
/* Connect irq/fiq outputs from the interrupt controller. */
qdev_connect_gpio_out_named(DEVICE(&s->control), "irq", n,
- qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_IRQ));
+ qdev_get_gpio_in(DEVICE(&s->cpu[n].core), ARM_CPU_IRQ));
qdev_connect_gpio_out_named(DEVICE(&s->control), "fiq", n,
- qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_FIQ));
+ qdev_get_gpio_in(DEVICE(&s->cpu[n].core), ARM_CPU_FIQ));
/* Connect timers from the CPU to the interrupt controller */
- qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_PHYS,
+ qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_PHYS,
qdev_get_gpio_in_named(DEVICE(&s->control), "cntpnsirq", n));
- qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_VIRT,
+ qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_VIRT,
qdev_get_gpio_in_named(DEVICE(&s->control), "cntvirq", n));
- qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_HYP,
+ qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_HYP,
qdev_get_gpio_in_named(DEVICE(&s->control), "cnthpirq", n));
- qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_SEC,
+ qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_SEC,
qdev_get_gpio_in_named(DEVICE(&s->control), "cntpsirq", n));
}
}
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
index b1288ccea8..970a4405cc 100644
--- a/hw/arm/collie.c
+++ b/hw/arm/collie.c
@@ -27,9 +27,13 @@ static void collie_init(MachineState *machine)
{
StrongARMState *s;
DriveInfo *dinfo;
- MemoryRegion *sysmem = get_system_memory();
+ MemoryRegion *sdram = g_new(MemoryRegion, 1);
- s = sa1110_init(sysmem, collie_binfo.ram_size, machine->cpu_type);
+ s = sa1110_init(machine->cpu_type);
+
+ memory_region_allocate_system_memory(sdram, NULL, "strongarm.sdram",
+ collie_binfo.ram_size);
+ memory_region_add_subregion(get_system_memory(), SA_SDCS0, sdram);
dinfo = drive_get(IF_PFLASH, 0, 0);
pflash_cfi01_register(SA_CS0, "collie.fl1", 0x02000000,
diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c
index 304e4d1a29..ef3fc2b6a5 100644
--- a/hw/arm/digic_boards.c
+++ b/hw/arm/digic_boards.c
@@ -53,12 +53,6 @@ typedef struct DigicBoard {
const char *rom1_def_filename;
} DigicBoard;
-static void digic4_board_setup_ram(DigicBoardState *s, hwaddr ram_size)
-{
- memory_region_allocate_system_memory(&s->ram, NULL, "ram", ram_size);
- memory_region_add_subregion(get_system_memory(), 0, &s->ram);
-}
-
static void digic4_board_init(DigicBoard *board)
{
Error *err = NULL;
@@ -72,7 +66,8 @@ static void digic4_board_init(DigicBoard *board)
exit(1);
}
- digic4_board_setup_ram(s, board->ram_size);
+ memory_region_allocate_system_memory(&s->ram, NULL, "ram", board->ram_size);
+ memory_region_add_subregion(get_system_memory(), 0, &s->ram);
if (board->add_rom0) {
board->add_rom0(s, DIGIC4_ROM0_BASE, board->rom0_def_filename);
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index a9f8a5c868..77fbe1baab 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -405,7 +405,7 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
* public datasheet which is very similar (implementing
* MMC Specification Version 4.0 being the only difference noted)
*/
- dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
+ dev = qdev_create(NULL, TYPE_S3C_SDHCI);
qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
qdev_init_nofail(dev);
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index f1724d6929..518d935fdf 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -78,7 +78,8 @@ static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
smpboot[n] = tswap32(smpboot[n]);
}
- rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
+ rom_add_blob_fixed_as("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR,
+ arm_boot_address_space(cpu, info));
}
static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 6b24aaacde..f8b620bcc6 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -38,6 +38,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/units.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/arm/boot.h"
@@ -458,7 +459,7 @@ static void mps2tz_common_init(MachineState *machine)
* call the 16MB our "system memory", as it's the largest lump.
*/
memory_region_allocate_system_memory(&mms->psram,
- NULL, "mps.ram", 0x01000000);
+ NULL, "mps.ram", 16 * MiB);
memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
/* The overflow IRQs for all UARTs are ORed together.
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
index 10efff36b2..d002b126d3 100644
--- a/hw/arm/mps2.c
+++ b/hw/arm/mps2.c
@@ -23,6 +23,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/units.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/arm/boot.h"
@@ -146,7 +147,7 @@ static void mps2_common_init(MachineState *machine)
* zbt_boot_ctrl is always zero).
*/
memory_region_allocate_system_memory(&mms->psram,
- NULL, "mps.ram", 0x1000000);
+ NULL, "mps.ram", 16 * MiB);
memory_region_add_subregion(system_memory, 0x21000000, &mms->psram);
switch (mmc->fpga_type) {
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
index 68db4b5b38..ba99dd1941 100644
--- a/hw/arm/musca.c
+++ b/hw/arm/musca.c
@@ -32,7 +32,7 @@
#include "hw/misc/tz-mpc.h"
#include "hw/misc/tz-ppc.h"
#include "hw/misc/unimp.h"
-#include "hw/timer/pl031.h"
+#include "hw/rtc/pl031.h"
#define MUSCA_NUMIRQ_MAX 96
#define MUSCA_PPC_MAX 3
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index a36971d39a..7e361936a9 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -47,6 +47,7 @@
/* Nokia N8x0 support */
struct n800_s {
+ MemoryRegion sdram;
struct omap_mpu_state_s *mpu;
struct rfbi_chip_s blizzard;
@@ -1311,11 +1312,14 @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p)
static void n8x0_init(MachineState *machine,
struct arm_boot_info *binfo, int model)
{
- MemoryRegion *sysmem = get_system_memory();
struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
- int sdram_size = binfo->ram_size;
+ uint64_t sdram_size = binfo->ram_size;
- s->mpu = omap2420_mpu_init(sysmem, sdram_size, machine->cpu_type);
+ memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram",
+ sdram_size);
+ memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE, &s->sdram);
+
+ s->mpu = omap2420_mpu_init(&s->sdram, machine->cpu_type);
/* Setup peripherals
*
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index 0400593805..6ce038a453 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -23,6 +23,7 @@
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
+#include "exec/address-spaces.h"
#include "hw/boards.h"
#include "hw/hw.h"
#include "hw/irq.h"
@@ -3858,8 +3859,7 @@ static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr);
}
-struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
- unsigned long sdram_size,
+struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram,
const char *cpu_type)
{
int i;
@@ -3867,11 +3867,12 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
qemu_irq dma_irqs[6];
DriveInfo *dinfo;
SysBusDevice *busdev;
+ MemoryRegion *system_memory = get_system_memory();
/* Core */
s->mpu_model = omap310;
s->cpu = ARM_CPU(cpu_create(cpu_type));
- s->sdram_size = sdram_size;
+ s->sdram_size = memory_region_size(dram);
s->sram_size = OMAP15XX_SRAM_SIZE;
s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
@@ -3880,9 +3881,6 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
omap_clk_init(s);
/* Memory-mapped stuff */
- memory_region_allocate_system_memory(&s->emiff_ram, NULL, "omap1.dram",
- s->sdram_size);
- memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
memory_region_init_ram(&s->imif_ram, NULL, "omap1.sram", s->sram_size,
&error_fatal);
memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
@@ -3925,7 +3923,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
/* Register SDRAM and SRAM DMA ports for fast transfers. */
- soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->emiff_ram),
+ soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(dram),
OMAP_EMIFF_BASE, s->sdram_size);
soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram),
OMAP_IMIF_BASE, s->sram_size);
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index bd7ddff983..457f152bac 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -22,6 +22,7 @@
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "cpu.h"
+#include "exec/address-spaces.h"
#include "sysemu/blockdev.h"
#include "sysemu/qtest.h"
#include "sysemu/reset.h"
@@ -2276,8 +2277,7 @@ static const struct dma_irq_map omap2_dma_irq_map[] = {
{ 0, OMAP_INT_24XX_SDMA_IRQ3 },
};
-struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
- unsigned long sdram_size,
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram,
const char *cpu_type)
{
struct omap_mpu_state_s *s = g_new0(struct omap_mpu_state_s, 1);
@@ -2286,11 +2286,11 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
int i;
SysBusDevice *busdev;
struct omap_target_agent_s *ta;
+ MemoryRegion *sysmem = get_system_memory();
/* Core */
s->mpu_model = omap2420;
s->cpu = ARM_CPU(cpu_create(cpu_type));
- s->sdram_size = sdram_size;
s->sram_size = OMAP242X_SRAM_SIZE;
s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
@@ -2299,9 +2299,6 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
omap_clk_init(s);
/* Memory-mapped stuff */
- memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram",
- s->sdram_size);
- memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size,
&error_fatal);
memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
@@ -2338,8 +2335,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
s->port->addr_valid = omap2_validate_addr;
/* Register SDRAM and SRAM ports for fast DMA transfers. */
- soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
- OMAP2_Q2_BASE, s->sdram_size);
+ soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(sdram),
+ OMAP2_Q2_BASE, memory_region_size(sdram));
soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
OMAP2_SRAM_BASE, s->sram_size);
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
index c071197be7..be245714db 100644
--- a/hw/arm/omap_sx1.c
+++ b/hw/arm/omap_sx1.c
@@ -103,6 +103,7 @@ static void sx1_init(MachineState *machine, const int version)
{
struct omap_mpu_state_s *mpu;
MemoryRegion *address_space = get_system_memory();
+ MemoryRegion *dram = g_new(MemoryRegion, 1);
MemoryRegion *flash = g_new(MemoryRegion, 1);
MemoryRegion *cs = g_new(MemoryRegion, 4);
static uint32_t cs0val = 0x00213090;
@@ -118,8 +119,11 @@ static void sx1_init(MachineState *machine, const int version)
flash_size = flash2_size;
}
- mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size,
- machine->cpu_type);
+ memory_region_allocate_system_memory(dram, NULL, "omap1.dram",
+ sx1_binfo.ram_size);
+ memory_region_add_subregion(address_space, OMAP_EMIFF_BASE, dram);
+
+ mpu = omap310_mpu_init(dram, machine->cpu_type);
/* External Flash (EMIFS) */
memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size,
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
index 02a3a82b9b..72eca8cc55 100644
--- a/hw/arm/palm.c
+++ b/hw/arm/palm.c
@@ -190,16 +190,20 @@ static void palmte_init(MachineState *machine)
MemoryRegion *address_space_mem = get_system_memory();
struct omap_mpu_state_s *mpu;
int flash_size = 0x00800000;
- int sdram_size = palmte_binfo.ram_size;
static uint32_t cs0val = 0xffffffff;
static uint32_t cs1val = 0x0000e1a0;
static uint32_t cs2val = 0x0000e1a0;
static uint32_t cs3val = 0xe1a0e1a0;
int rom_size, rom_loaded = 0;
+ MemoryRegion *dram = g_new(MemoryRegion, 1);
MemoryRegion *flash = g_new(MemoryRegion, 1);
MemoryRegion *cs = g_new(MemoryRegion, 4);
- mpu = omap310_mpu_init(address_space_mem, sdram_size, machine->cpu_type);
+ memory_region_allocate_system_memory(dram, NULL, "omap1.dram",
+ palmte_binfo.ram_size);
+ memory_region_add_subregion(address_space_mem, OMAP_EMIFF_BASE, dram);
+
+ mpu = omap310_mpu_init(dram, machine->cpu_type);
/* External Flash (EMIFS) */
memory_region_init_ram(flash, NULL, "palmte.flash", flash_size,
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 615d755879..6a510aafc1 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -60,12 +60,14 @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
QEMU_BUILD_BUG_ON((BOARDSETUP_ADDR & 0xf) != 0
|| (BOARDSETUP_ADDR >> 4) >= 0x100);
- rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
- info->smp_loader_start);
+ rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
+ info->smp_loader_start,
+ arm_boot_address_space(cpu, info));
}
static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
{
+ AddressSpace *as = arm_boot_address_space(cpu, info);
/* Unlike the AArch32 version we don't need to call the board setup hook.
* The mechanism for doing the spin-table is also entirely different.
* We must have four 64-bit fields at absolute addresses
@@ -92,10 +94,10 @@ static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
0, 0, 0, 0
};
- rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
- info->smp_loader_start);
- rom_add_blob_fixed("raspi_spintables", spintables, sizeof(spintables),
- SPINTABLE_ADDR);
+ rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
+ info->smp_loader_start, as);
+ rom_add_blob_fixed_as("raspi_spintables", spintables, sizeof(spintables),
+ SPINTABLE_ADDR, as);
}
static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info)
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index dc65d88a65..6bee034914 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -1586,8 +1586,7 @@ static const TypeInfo strongarm_ssp_info = {
};
/* Main CPU functions */
-StrongARMState *sa1110_init(MemoryRegion *sysmem,
- unsigned int sdram_size, const char *cpu_type)
+StrongARMState *sa1110_init(const char *cpu_type)
{
StrongARMState *s;
int i;
@@ -1601,10 +1600,6 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
s->cpu = ARM_CPU(cpu_create(cpu_type));
- memory_region_allocate_system_memory(&s->sdram, NULL, "strongarm.sdram",
- sdram_size);
- memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
-
s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ),
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ),
diff --git a/hw/arm/strongarm.h b/hw/arm/strongarm.h
index e98840b461..192821f6aa 100644
--- a/hw/arm/strongarm.h
+++ b/hw/arm/strongarm.h
@@ -55,7 +55,6 @@ enum {
typedef struct {
ARMCPU *cpu;
- MemoryRegion sdram;
DeviceState *pic;
DeviceState *gpio;
DeviceState *ppc;
@@ -63,7 +62,6 @@ typedef struct {
SSIBus *ssp_bus;
} StrongARMState;
-StrongARMState *sa1110_init(MemoryRegion *sysmem,
- unsigned int sdram_size, const char *rev);
+StrongARMState *sa1110_init(const char *cpu_type);
#endif
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index c14774e542..3a0fa5b23f 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -16,6 +16,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/units.h"
#include "qapi/error.h"
#include "cpu.h"
#include "hw/sysbus.h"
@@ -194,7 +195,7 @@ static void zynq_init(MachineState *machine)
memory_region_add_subregion(address_space_mem, 0, ext_ram);
/* 256K of on-chip memory */
- memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10,
+ memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 * KiB,
&error_fatal);
memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index ed2ddebd2b..14e9f85b8b 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1207,6 +1207,7 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOBlock *s = VIRTIO_BLK(dev);
+ blk_drain(s->blk);
virtio_blk_data_plane_destroy(s->dataplane);
s->dataplane = NULL;
qemu_del_vm_change_state_handler(s->change);
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index e035d1f750..fb3a978e28 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -31,7 +31,6 @@
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
#include "qemu/log.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "hw/stream.h"
@@ -104,7 +103,6 @@ enum {
};
struct Stream {
- QEMUBH *bh;
ptimer_state *ptimer;
qemu_irq irq;
@@ -242,6 +240,7 @@ static void stream_complete(struct Stream *s)
unsigned int comp_delay;
/* Start the delayed timer. */
+ ptimer_transaction_begin(s->ptimer);
comp_delay = s->regs[R_DMACR] >> 24;
if (comp_delay) {
ptimer_stop(s->ptimer);
@@ -255,6 +254,7 @@ static void stream_complete(struct Stream *s)
s->regs[R_DMASR] |= DMASR_IOC_IRQ;
stream_reload_complete_cnt(s);
}
+ ptimer_transaction_commit(s->ptimer);
}
static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
@@ -551,9 +551,10 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
struct Stream *st = &s->streams[i];
st->nr = i;
- st->bh = qemu_bh_new(timer_hit, st);
- st->ptimer = ptimer_init_with_bh(st->bh, PTIMER_POLICY_DEFAULT);
+ st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(st->ptimer);
ptimer_set_freq(st->ptimer, s->freqhz);
+ ptimer_transaction_commit(st->ptimer);
}
return;
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
index 196e47c262..7acc5fa8e2 100644
--- a/hw/gpio/aspeed_gpio.c
+++ b/hw/gpio/aspeed_gpio.c
@@ -733,13 +733,13 @@ static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name,
{
int pin = 0xfff;
bool level = true;
- char group[3];
+ char group[4];
AspeedGPIOState *s = ASPEED_GPIO(obj);
int set_idx, group_idx = 0;
if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
/* 1.8V gpio */
- if (sscanf(name, "gpio%3s%1d", group, &pin) != 2) {
+ if (sscanf(name, "gpio%3[18A-E]%1d", group, &pin) != 2) {
error_setg(errp, "%s: error reading %s", __func__, name);
return;
}
@@ -760,7 +760,7 @@ static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
Error *local_err = NULL;
bool level;
int pin = 0xfff;
- char group[3];
+ char group[4];
AspeedGPIOState *s = ASPEED_GPIO(obj);
int set_idx, group_idx = 0;
@@ -771,7 +771,7 @@ static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
}
if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
/* 1.8V gpio */
- if (sscanf(name, "gpio%3s%1d", group, &pin) != 2) {
+ if (sscanf(name, "gpio%3[18A-E]%1d", group, &pin) != 2) {
error_setg(errp, "%s: error reading %s", __func__, name);
return;
}
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 7e23675429..b30aba6d54 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -12,7 +12,7 @@
#include "qemu/error-report.h"
#include "sysemu/reset.h"
#include "sysemu/sysemu.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/ide.h"
#include "hw/timer/i8254.h"
#include "hw/char/serial.h"
@@ -161,9 +161,8 @@ static void machine_hppa_init(MachineState *machine)
g_free(firmware_filename);
rom_region = g_new(MemoryRegion, 1);
- memory_region_allocate_system_memory(rom_region, OBJECT(machine),
- "firmware",
- (FIRMWARE_END - FIRMWARE_START));
+ memory_region_init_ram(rom_region, NULL, "firmware",
+ (FIRMWARE_END - FIRMWARE_START), &error_fatal);
memory_region_add_subregion(addr_space, FIRMWARE_START, rom_region);
/* Load kernel */
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index bc0256e1e0..9dd3dbb16c 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -45,7 +45,7 @@
#include "hw/acpi/vmgenid.h"
#include "hw/boards.h"
#include "sysemu/tpm_backend.h"
-#include "hw/timer/mc146818rtc_regs.h"
+#include "hw/rtc/mc146818rtc_regs.h"
#include "migration/vmstate.h"
#include "hw/mem/memory-device.h"
#include "sysemu/numa.h"
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 20d2189ea8..8aacd6c8d1 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -35,7 +35,7 @@
#include "hw/i386/pc.h"
#include "target/i386/cpu.h"
#include "hw/timer/i8254.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/char/serial.h"
#include "hw/i386/topology.h"
#include "hw/i386/e820_memory_layout.h"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 5fce60c856..b8f02c6f3f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -43,7 +43,7 @@
#include "elf.h"
#include "migration/vmstate.h"
#include "multiboot.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/dma/i8257.h"
#include "hw/timer/i8254.h"
#include "hw/input/i8042.h"
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index def3bc2d7b..d8b4c48021 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -33,7 +33,7 @@
#include "hw/loader.h"
#include "sysemu/arch_init.h"
#include "hw/i2c/smbus_eeprom.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/xen/xen.h"
#include "sysemu/kvm.h"
#include "hw/kvm/clock.h"
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 8e93e51e81..e8c74f9eba 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -2251,7 +2251,7 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
}
}
nvic_irq_update(s);
- return MEMTX_OK;
+ goto exit_ok;
case 0x200 ... 0x23f: /* NVIC Set pend */
/* the special logic in armv7m_nvic_set_pending()
* is not needed since IRQs are never escalated
@@ -2269,9 +2269,9 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
}
}
nvic_irq_update(s);
- return MEMTX_OK;
+ goto exit_ok;
case 0x300 ... 0x33f: /* NVIC Active */
- return MEMTX_OK; /* R/O */
+ goto exit_ok; /* R/O */
case 0x400 ... 0x5ef: /* NVIC Priority */
startvec = (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
@@ -2281,10 +2281,10 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
}
}
nvic_irq_update(s);
- return MEMTX_OK;
+ goto exit_ok;
case 0xd18 ... 0xd1b: /* System Handler Priority (SHPR1) */
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
- return MEMTX_OK;
+ goto exit_ok;
}
/* fall through */
case 0xd1c ... 0xd23: /* System Handler Priority (SHPR2, SHPR3) */
@@ -2299,10 +2299,10 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
set_prio(s, hdlidx, sbank, newprio);
}
nvic_irq_update(s);
- return MEMTX_OK;
+ goto exit_ok;
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
- return MEMTX_OK;
+ goto exit_ok;
}
/* All bits are W1C, so construct 32 bit value with 0s in
* the parts not written by the access size
@@ -2322,15 +2322,19 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
*/
s->cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK);
}
- return MEMTX_OK;
+ goto exit_ok;
}
if (size == 4) {
nvic_writel(s, offset, value, attrs);
- return MEMTX_OK;
+ goto exit_ok;
}
qemu_log_mask(LOG_GUEST_ERROR,
"NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
/* This is UNPREDICTABLE; treat as RAZ/WI */
+
+ exit_ok:
+ /* Ensure any changes made are reflected in the cached hflags. */
+ arm_rebuild_hflags(&s->cpu->env);
return MEMTX_OK;
}
diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
index ed6e9d71bb..348f2fdd26 100644
--- a/hw/intc/pnv_xive.c
+++ b/hw/intc/pnv_xive.c
@@ -385,7 +385,7 @@ static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
PnvXive *xive = PNV_XIVE(xrtr);
if (pnv_xive_get_ic(blk) != xive) {
- xive_error(xive, "VST: EAS %x is remote !?", XIVE_SRCNO(blk, idx));
+ xive_error(xive, "VST: EAS %x is remote !?", XIVE_EAS(blk, idx));
return -1;
}
@@ -431,7 +431,7 @@ static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno)
PnvXive *xive = PNV_XIVE(xn);
uint8_t blk = xive->chip->chip_id;
- xive_router_notify(xn, XIVE_SRCNO(blk, srcno));
+ xive_router_notify(xn, XIVE_EAS(blk, srcno));
}
/*
@@ -1225,12 +1225,24 @@ static const MemoryRegionOps pnv_xive_ic_reg_ops = {
static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val)
{
+ uint8_t blk;
+ uint32_t idx;
+
+ if (val & XIVE_TRIGGER_END) {
+ xive_error(xive, "IC: END trigger at @0x%"HWADDR_PRIx" data 0x%"PRIx64,
+ addr, val);
+ return;
+ }
+
/*
* Forward the source event notification directly to the Router.
* The source interrupt number should already be correctly encoded
* with the chip block id by the sending device (PHB, PSI).
*/
- xive_router_notify(XIVE_NOTIFIER(xive), val);
+ blk = XIVE_EAS_BLOCK(val);
+ idx = XIVE_EAS_INDEX(val);
+
+ xive_router_notify(XIVE_NOTIFIER(xive), XIVE_EAS(blk, idx));
}
static void pnv_xive_ic_notify_write(void *opaque, hwaddr addr, uint64_t val,
@@ -1566,7 +1578,7 @@ void pnv_xive_pic_print_info(PnvXive *xive, Monitor *mon)
{
XiveRouter *xrtr = XIVE_ROUTER(xive);
uint8_t blk = xive->chip->chip_id;
- uint32_t srcno0 = XIVE_SRCNO(blk, 0);
+ uint32_t srcno0 = XIVE_EAS(blk, 0);
uint32_t nr_ipis = pnv_xive_nr_ipis(xive);
uint32_t nr_ends = pnv_xive_nr_ends(xive);
XiveEAS eas;
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 04879abf2e..d8e1291905 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -205,23 +205,6 @@ void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable)
memory_region_set_enabled(&xive->end_source.esb_mmio, false);
}
-/*
- * When a Virtual Processor is scheduled to run on a HW thread, the
- * hypervisor pushes its identifier in the OS CAM line. Emulate the
- * same behavior under QEMU.
- */
-void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx)
-{
- uint8_t nvt_blk;
- uint32_t nvt_idx;
- uint32_t nvt_cam;
-
- spapr_xive_cpu_to_nvt(POWERPC_CPU(tctx->cs), &nvt_blk, &nvt_idx);
-
- nvt_cam = cpu_to_be32(TM_QW1W2_VO | xive_nvt_cam_line(nvt_blk, nvt_idx));
- memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &nvt_cam, 4);
-}
-
static void spapr_xive_end_reset(XiveEND *end)
{
memset(end, 0, sizeof(*end));
@@ -462,10 +445,10 @@ static int vmstate_spapr_xive_pre_save(void *opaque)
* Called by the sPAPR IRQ backend 'post_load' method at the machine
* level.
*/
-int spapr_xive_post_load(SpaprXive *xive, int version_id)
+static int spapr_xive_post_load(SpaprInterruptController *intc, int version_id)
{
if (kvm_irqchip_in_kernel()) {
- return kvmppc_xive_post_load(xive, version_id);
+ return kvmppc_xive_post_load(SPAPR_XIVE(intc), version_id);
}
return 0;
@@ -487,6 +470,42 @@ static const VMStateDescription vmstate_spapr_xive = {
},
};
+static int spapr_xive_claim_irq(SpaprInterruptController *intc, int lisn,
+ bool lsi, Error **errp)
+{
+ SpaprXive *xive = SPAPR_XIVE(intc);
+ XiveSource *xsrc = &xive->source;
+
+ assert(lisn < xive->nr_irqs);
+
+ if (xive_eas_is_valid(&xive->eat[lisn])) {
+ error_setg(errp, "IRQ %d is not free", lisn);
+ return -EBUSY;
+ }
+
+ /*
+ * Set default values when allocating an IRQ number
+ */
+ xive->eat[lisn].w |= cpu_to_be64(EAS_VALID | EAS_MASKED);
+ if (lsi) {
+ xive_source_irq_set_lsi(xsrc, lisn);
+ }
+
+ if (kvm_irqchip_in_kernel()) {
+ return kvmppc_xive_source_reset_one(xsrc, lisn, errp);
+ }
+
+ return 0;
+}
+
+static void spapr_xive_free_irq(SpaprInterruptController *intc, int lisn)
+{
+ SpaprXive *xive = SPAPR_XIVE(intc);
+ assert(lisn < xive->nr_irqs);
+
+ xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID);
+}
+
static Property spapr_xive_properties[] = {
DEFINE_PROP_UINT32("nr-irqs", SpaprXive, nr_irqs, 0),
DEFINE_PROP_UINT32("nr-ends", SpaprXive, nr_ends, 0),
@@ -495,10 +514,167 @@ static Property spapr_xive_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static int spapr_xive_cpu_intc_create(SpaprInterruptController *intc,
+ PowerPCCPU *cpu, Error **errp)
+{
+ SpaprXive *xive = SPAPR_XIVE(intc);
+ Object *obj;
+ SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
+
+ obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(xive), errp);
+ if (!obj) {
+ return -1;
+ }
+
+ spapr_cpu->tctx = XIVE_TCTX(obj);
+ return 0;
+}
+
+static void xive_tctx_set_os_cam(XiveTCTX *tctx, uint32_t os_cam)
+{
+ uint32_t qw1w2 = cpu_to_be32(TM_QW1W2_VO | os_cam);
+ memcpy(&tctx->regs[TM_QW1_OS + TM_WORD2], &qw1w2, 4);
+}
+
+static void spapr_xive_cpu_intc_reset(SpaprInterruptController *intc,
+ PowerPCCPU *cpu)
+{
+ XiveTCTX *tctx = spapr_cpu_state(cpu)->tctx;
+ uint8_t nvt_blk;
+ uint32_t nvt_idx;
+
+ xive_tctx_reset(tctx);
+
+ /*
+ * When a Virtual Processor is scheduled to run on a HW thread,
+ * the hypervisor pushes its identifier in the OS CAM line.
+ * Emulate the same behavior under QEMU.
+ */
+ spapr_xive_cpu_to_nvt(cpu, &nvt_blk, &nvt_idx);
+
+ xive_tctx_set_os_cam(tctx, xive_nvt_cam_line(nvt_blk, nvt_idx));
+}
+
+static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val)
+{
+ SpaprXive *xive = SPAPR_XIVE(intc);
+
+ if (kvm_irqchip_in_kernel()) {
+ kvmppc_xive_source_set_irq(&xive->source, irq, val);
+ } else {
+ xive_source_set_irq(&xive->source, irq, val);
+ }
+}
+
+static void spapr_xive_print_info(SpaprInterruptController *intc, Monitor *mon)
+{
+ SpaprXive *xive = SPAPR_XIVE(intc);
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ xive_tctx_pic_print_info(spapr_cpu_state(cpu)->tctx, mon);
+ }
+
+ spapr_xive_pic_print_info(xive, mon);
+}
+
+static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers,
+ void *fdt, uint32_t phandle)
+{
+ SpaprXive *xive = SPAPR_XIVE(intc);
+ int node;
+ uint64_t timas[2 * 2];
+ /* Interrupt number ranges for the IPIs */
+ uint32_t lisn_ranges[] = {
+ cpu_to_be32(0),
+ cpu_to_be32(nr_servers),
+ };
+ /*
+ * EQ size - the sizes of pages supported by the system 4K, 64K,
+ * 2M, 16M. We only advertise 64K for the moment.
+ */
+ uint32_t eq_sizes[] = {
+ cpu_to_be32(16), /* 64K */
+ };
+ /*
+ * The following array is in sync with the reserved priorities
+ * defined by the 'spapr_xive_priority_is_reserved' routine.
+ */
+ uint32_t plat_res_int_priorities[] = {
+ cpu_to_be32(7), /* start */
+ cpu_to_be32(0xf8), /* count */
+ };
+
+ /* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */
+ timas[0] = cpu_to_be64(xive->tm_base +
+ XIVE_TM_USER_PAGE * (1ull << TM_SHIFT));
+ timas[1] = cpu_to_be64(1ull << TM_SHIFT);
+ timas[2] = cpu_to_be64(xive->tm_base +
+ XIVE_TM_OS_PAGE * (1ull << TM_SHIFT));
+ timas[3] = cpu_to_be64(1ull << TM_SHIFT);
+
+ _FDT(node = fdt_add_subnode(fdt, 0, xive->nodename));
+
+ _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe"));
+ _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas)));
+
+ _FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe"));
+ _FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes,
+ sizeof(eq_sizes)));
+ _FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges,
+ sizeof(lisn_ranges)));
+
+ /* For Linux to link the LSIs to the interrupt controller. */
+ _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0));
+ _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2));
+
+ /* For SLOF */
+ _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
+ _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
+
+ /*
+ * The "ibm,plat-res-int-priorities" property defines the priority
+ * ranges reserved by the hypervisor
+ */
+ _FDT(fdt_setprop(fdt, 0, "ibm,plat-res-int-priorities",
+ plat_res_int_priorities, sizeof(plat_res_int_priorities)));
+}
+
+static int spapr_xive_activate(SpaprInterruptController *intc, Error **errp)
+{
+ SpaprXive *xive = SPAPR_XIVE(intc);
+
+ if (kvm_enabled()) {
+ int rc = spapr_irq_init_kvm(kvmppc_xive_connect, intc, errp);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+
+ /* Activate the XIVE MMIOs */
+ spapr_xive_mmio_set_enabled(xive, true);
+
+ return 0;
+}
+
+static void spapr_xive_deactivate(SpaprInterruptController *intc)
+{
+ SpaprXive *xive = SPAPR_XIVE(intc);
+
+ spapr_xive_mmio_set_enabled(xive, false);
+
+ if (kvm_irqchip_in_kernel()) {
+ kvmppc_xive_disconnect(intc);
+ }
+}
+
static void spapr_xive_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
+ SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
dc->desc = "sPAPR XIVE Interrupt Controller";
dc->props = spapr_xive_properties;
@@ -511,6 +687,17 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
xrc->get_nvt = spapr_xive_get_nvt;
xrc->write_nvt = spapr_xive_write_nvt;
xrc->get_tctx = spapr_xive_get_tctx;
+
+ sicc->activate = spapr_xive_activate;
+ sicc->deactivate = spapr_xive_deactivate;
+ sicc->cpu_intc_create = spapr_xive_cpu_intc_create;
+ sicc->cpu_intc_reset = spapr_xive_cpu_intc_reset;
+ sicc->claim_irq = spapr_xive_claim_irq;
+ sicc->free_irq = spapr_xive_free_irq;
+ sicc->set_irq = spapr_xive_set_irq;
+ sicc->print_info = spapr_xive_print_info;
+ sicc->dt = spapr_xive_dt;
+ sicc->post_load = spapr_xive_post_load;
}
static const TypeInfo spapr_xive_info = {
@@ -519,6 +706,10 @@ static const TypeInfo spapr_xive_info = {
.instance_init = spapr_xive_instance_init,
.instance_size = sizeof(SpaprXive),
.class_init = spapr_xive_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_SPAPR_INTC },
+ { }
+ },
};
static void spapr_xive_register_types(void)
@@ -528,39 +719,6 @@ static void spapr_xive_register_types(void)
type_init(spapr_xive_register_types)
-int spapr_xive_irq_claim(SpaprXive *xive, int lisn, bool lsi, Error **errp)
-{
- XiveSource *xsrc = &xive->source;
-
- assert(lisn < xive->nr_irqs);
-
- if (xive_eas_is_valid(&xive->eat[lisn])) {
- error_setg(errp, "IRQ %d is not free", lisn);
- return -EBUSY;
- }
-
- /*
- * Set default values when allocating an IRQ number
- */
- xive->eat[lisn].w |= cpu_to_be64(EAS_VALID | EAS_MASKED);
- if (lsi) {
- xive_source_irq_set_lsi(xsrc, lisn);
- }
-
- if (kvm_irqchip_in_kernel()) {
- return kvmppc_xive_source_reset_one(xsrc, lisn, errp);
- }
-
- return 0;
-}
-
-void spapr_xive_irq_free(SpaprXive *xive, int lisn)
-{
- assert(lisn < xive->nr_irqs);
-
- xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID);
-}
-
/*
* XIVE hcalls
*
@@ -1540,65 +1698,3 @@ void spapr_xive_hcall_init(SpaprMachineState *spapr)
spapr_register_hypercall(H_INT_SYNC, h_int_sync);
spapr_register_hypercall(H_INT_RESET, h_int_reset);
}
-
-void spapr_dt_xive(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
- uint32_t phandle)
-{
- SpaprXive *xive = spapr->xive;
- int node;
- uint64_t timas[2 * 2];
- /* Interrupt number ranges for the IPIs */
- uint32_t lisn_ranges[] = {
- cpu_to_be32(0),
- cpu_to_be32(nr_servers),
- };
- /*
- * EQ size - the sizes of pages supported by the system 4K, 64K,
- * 2M, 16M. We only advertise 64K for the moment.
- */
- uint32_t eq_sizes[] = {
- cpu_to_be32(16), /* 64K */
- };
- /*
- * The following array is in sync with the reserved priorities
- * defined by the 'spapr_xive_priority_is_reserved' routine.
- */
- uint32_t plat_res_int_priorities[] = {
- cpu_to_be32(7), /* start */
- cpu_to_be32(0xf8), /* count */
- };
-
- /* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */
- timas[0] = cpu_to_be64(xive->tm_base +
- XIVE_TM_USER_PAGE * (1ull << TM_SHIFT));
- timas[1] = cpu_to_be64(1ull << TM_SHIFT);
- timas[2] = cpu_to_be64(xive->tm_base +
- XIVE_TM_OS_PAGE * (1ull << TM_SHIFT));
- timas[3] = cpu_to_be64(1ull << TM_SHIFT);
-
- _FDT(node = fdt_add_subnode(fdt, 0, xive->nodename));
-
- _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe"));
- _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas)));
-
- _FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe"));
- _FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes,
- sizeof(eq_sizes)));
- _FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges,
- sizeof(lisn_ranges)));
-
- /* For Linux to link the LSIs to the interrupt controller. */
- _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0));
- _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2));
-
- /* For SLOF */
- _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
- _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
-
- /*
- * The "ibm,plat-res-int-priorities" property defines the priority
- * ranges reserved by the hypervisor
- */
- _FDT(fdt_setprop(fdt, 0, "ibm,plat-res-int-priorities",
- plat_res_int_priorities, sizeof(plat_res_int_priorities)));
-}
diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c
index 51b334b676..08012ac7cd 100644
--- a/hw/intc/spapr_xive_kvm.c
+++ b/hw/intc/spapr_xive_kvm.c
@@ -740,8 +740,9 @@ static void *kvmppc_xive_mmap(SpaprXive *xive, int pgoff, size_t len,
* All the XIVE memory regions are now backed by mappings from the KVM
* XIVE device.
*/
-void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
+int kvmppc_xive_connect(SpaprInterruptController *intc, Error **errp)
{
+ SpaprXive *xive = SPAPR_XIVE(intc);
XiveSource *xsrc = &xive->source;
Error *local_err = NULL;
size_t esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
@@ -753,19 +754,19 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
* rebooting under the XIVE-only interrupt mode.
*/
if (xive->fd != -1) {
- return;
+ return 0;
}
if (!kvmppc_has_cap_xive()) {
error_setg(errp, "IRQ_XIVE capability must be present for KVM");
- return;
+ return -1;
}
/* First, create the KVM XIVE device */
xive->fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_XIVE, false);
if (xive->fd < 0) {
error_setg_errno(errp, -xive->fd, "XIVE: error creating KVM device");
- return;
+ return -1;
}
/*
@@ -821,15 +822,17 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp)
kvm_kernel_irqchip = true;
kvm_msi_via_irqfd_allowed = true;
kvm_gsi_direct_mapping = true;
- return;
+ return 0;
fail:
error_propagate(errp, local_err);
- kvmppc_xive_disconnect(xive, NULL);
+ kvmppc_xive_disconnect(intc);
+ return -1;
}
-void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
+void kvmppc_xive_disconnect(SpaprInterruptController *intc)
{
+ SpaprXive *xive = SPAPR_XIVE(intc);
XiveSource *xsrc;
size_t esb_len;
@@ -838,11 +841,6 @@ void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp)
return;
}
- if (!kvmppc_has_cap_xive()) {
- error_setg(errp, "IRQ_XIVE capability must be present for KVM");
- return;
- }
-
/* Clear the KVM mapping */
xsrc = &xive->source;
esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index dfe7dbd254..6da05763f9 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -274,10 +274,8 @@ static const VMStateDescription vmstate_icp_server = {
},
};
-static void icp_reset_handler(void *dev)
+void icp_reset(ICPState *icp)
{
- ICPState *icp = ICP(dev);
-
icp->xirr = 0;
icp->pending_priority = 0xff;
icp->mfrr = 0xff;
@@ -288,7 +286,7 @@ static void icp_reset_handler(void *dev)
if (kvm_irqchip_in_kernel()) {
Error *local_err = NULL;
- icp_set_kvm_state(ICP(dev), &local_err);
+ icp_set_kvm_state(icp, &local_err);
if (local_err) {
error_report_err(local_err);
}
@@ -351,7 +349,6 @@ static void icp_realize(DeviceState *dev, Error **errp)
}
}
- qemu_register_reset(icp_reset_handler, dev);
vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
}
@@ -360,7 +357,6 @@ static void icp_unrealize(DeviceState *dev, Error **errp)
ICPState *icp = ICP(dev);
vmstate_unregister(NULL, &vmstate_icp_server, icp);
- qemu_unregister_reset(icp_reset_handler, dev);
}
static void icp_class_init(ObjectClass *klass, void *data)
@@ -369,6 +365,11 @@ static void icp_class_init(ObjectClass *klass, void *data)
dc->realize = icp_realize;
dc->unrealize = icp_unrealize;
+ /*
+ * Reason: part of XICS interrupt controller, needs to be wired up
+ * by icp_create().
+ */
+ dc->user_creatable = false;
}
static const TypeInfo icp_info = {
@@ -689,6 +690,11 @@ static void ics_class_init(ObjectClass *klass, void *data)
dc->props = ics_properties;
dc->reset = ics_reset;
dc->vmsd = &vmstate_ics;
+ /*
+ * Reason: part of XICS interrupt controller, needs to be wired up,
+ * e.g. by spapr_irq_init().
+ */
+ dc->user_creatable = false;
}
static const TypeInfo ics_info = {
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index ba90d6dc96..954c424b36 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -342,8 +342,9 @@ void ics_kvm_set_irq(ICSState *ics, int srcno, int val)
}
}
-int xics_kvm_connect(SpaprMachineState *spapr, Error **errp)
+int xics_kvm_connect(SpaprInterruptController *intc, Error **errp)
{
+ ICSState *ics = ICS_SPAPR(intc);
int rc;
CPUState *cs;
Error *local_err = NULL;
@@ -413,7 +414,7 @@ int xics_kvm_connect(SpaprMachineState *spapr, Error **errp)
}
/* Update the KVM sources */
- ics_set_kvm_state(spapr->ics, &local_err);
+ ics_set_kvm_state(ics, &local_err);
if (local_err) {
goto fail;
}
@@ -431,11 +432,11 @@ int xics_kvm_connect(SpaprMachineState *spapr, Error **errp)
fail:
error_propagate(errp, local_err);
- xics_kvm_disconnect(spapr, NULL);
+ xics_kvm_disconnect(intc);
return -1;
}
-void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp)
+void xics_kvm_disconnect(SpaprInterruptController *intc)
{
/*
* Only on P9 using the XICS-on XIVE KVM device:
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 6e5eb24b3c..7418fb9f37 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -308,8 +308,8 @@ static void ics_spapr_realize(DeviceState *dev, Error **errp)
spapr_register_hypercall(H_IPOLL, h_ipoll);
}
-void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
- uint32_t phandle)
+static void xics_spapr_dt(SpaprInterruptController *intc, uint32_t nr_servers,
+ void *fdt, uint32_t phandle)
{
uint32_t interrupt_server_ranges_prop[] = {
0, cpu_to_be32(nr_servers),
@@ -330,19 +330,132 @@ void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
_FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
}
+static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
+ PowerPCCPU *cpu, Error **errp)
+{
+ ICSState *ics = ICS_SPAPR(intc);
+ Object *obj;
+ SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
+
+ obj = icp_create(OBJECT(cpu), TYPE_ICP, ics->xics, errp);
+ if (!obj) {
+ return -1;
+ }
+
+ spapr_cpu->icp = ICP(obj);
+ return 0;
+}
+
+static void xics_spapr_cpu_intc_reset(SpaprInterruptController *intc,
+ PowerPCCPU *cpu)
+{
+ icp_reset(spapr_cpu_state(cpu)->icp);
+}
+
+static int xics_spapr_claim_irq(SpaprInterruptController *intc, int irq,
+ bool lsi, Error **errp)
+{
+ ICSState *ics = ICS_SPAPR(intc);
+
+ assert(ics);
+ assert(ics_valid_irq(ics, irq));
+
+ if (!ics_irq_free(ics, irq - ics->offset)) {
+ error_setg(errp, "IRQ %d is not free", irq);
+ return -EBUSY;
+ }
+
+ ics_set_irq_type(ics, irq - ics->offset, lsi);
+ return 0;
+}
+
+static void xics_spapr_free_irq(SpaprInterruptController *intc, int irq)
+{
+ ICSState *ics = ICS_SPAPR(intc);
+ uint32_t srcno = irq - ics->offset;
+
+ assert(ics_valid_irq(ics, irq));
+
+ memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
+}
+
+static void xics_spapr_set_irq(SpaprInterruptController *intc, int irq, int val)
+{
+ ICSState *ics = ICS_SPAPR(intc);
+ uint32_t srcno = irq - ics->offset;
+
+ ics_set_irq(ics, srcno, val);
+}
+
+static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
+{
+ ICSState *ics = ICS_SPAPR(intc);
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
+ }
+
+ ics_pic_print_info(ics, mon);
+}
+
+static int xics_spapr_post_load(SpaprInterruptController *intc, int version_id)
+{
+ if (!kvm_irqchip_in_kernel()) {
+ CPUState *cs;
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ icp_resend(spapr_cpu_state(cpu)->icp);
+ }
+ }
+ return 0;
+}
+
+static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp)
+{
+ if (kvm_enabled()) {
+ return spapr_irq_init_kvm(xics_kvm_connect, intc, errp);
+ }
+ return 0;
+}
+
+static void xics_spapr_deactivate(SpaprInterruptController *intc)
+{
+ if (kvm_irqchip_in_kernel()) {
+ xics_kvm_disconnect(intc);
+ }
+}
+
static void ics_spapr_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ICSStateClass *isc = ICS_CLASS(klass);
+ SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
device_class_set_parent_realize(dc, ics_spapr_realize,
&isc->parent_realize);
+ sicc->activate = xics_spapr_activate;
+ sicc->deactivate = xics_spapr_deactivate;
+ sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
+ sicc->cpu_intc_reset = xics_spapr_cpu_intc_reset;
+ sicc->claim_irq = xics_spapr_claim_irq;
+ sicc->free_irq = xics_spapr_free_irq;
+ sicc->set_irq = xics_spapr_set_irq;
+ sicc->print_info = xics_spapr_print_info;
+ sicc->dt = xics_spapr_dt;
+ sicc->post_load = xics_spapr_post_load;
}
static const TypeInfo ics_spapr_info = {
.name = TYPE_ICS_SPAPR,
.parent = TYPE_ICS,
.class_init = ics_spapr_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_SPAPR_INTC },
+ { }
+ },
};
static void xics_spapr_register_types(void)
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 29df06df11..f066be5eb5 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -547,10 +547,8 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon)
}
}
-static void xive_tctx_reset(void *dev)
+void xive_tctx_reset(XiveTCTX *tctx)
{
- XiveTCTX *tctx = XIVE_TCTX(dev);
-
memset(tctx->regs, 0, sizeof(tctx->regs));
/* Set some defaults */
@@ -607,13 +605,6 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
return;
}
}
-
- qemu_register_reset(xive_tctx_reset, dev);
-}
-
-static void xive_tctx_unrealize(DeviceState *dev, Error **errp)
-{
- qemu_unregister_reset(xive_tctx_reset, dev);
}
static int vmstate_xive_tctx_pre_save(void *opaque)
@@ -668,8 +659,12 @@ static void xive_tctx_class_init(ObjectClass *klass, void *data)
dc->desc = "XIVE Interrupt Thread Context";
dc->realize = xive_tctx_realize;
- dc->unrealize = xive_tctx_unrealize;
dc->vmsd = &vmstate_xive_tctx;
+ /*
+ * Reason: part of XIVE interrupt controller, needs to be wired up
+ * by xive_tctx_create().
+ */
+ dc->user_creatable = false;
}
static const TypeInfo xive_tctx_info = {
@@ -1118,6 +1113,11 @@ static void xive_source_class_init(ObjectClass *klass, void *data)
dc->props = xive_source_properties;
dc->realize = xive_source_realize;
dc->vmsd = &vmstate_xive_source;
+ /*
+ * Reason: part of XIVE interrupt controller, needs to be wired up,
+ * e.g. by spapr_xive_instance_init().
+ */
+ dc->user_creatable = false;
}
static const TypeInfo xive_source_info = {
@@ -1648,8 +1648,8 @@ do_escalation:
void xive_router_notify(XiveNotifier *xn, uint32_t lisn)
{
XiveRouter *xrtr = XIVE_ROUTER(xn);
- uint8_t eas_blk = XIVE_SRCNO_BLOCK(lisn);
- uint32_t eas_idx = XIVE_SRCNO_INDEX(lisn);
+ uint8_t eas_blk = XIVE_EAS_BLOCK(lisn);
+ uint32_t eas_idx = XIVE_EAS_INDEX(lisn);
XiveEAS eas;
/* EAS cache lookup */
@@ -1853,6 +1853,11 @@ static void xive_end_source_class_init(ObjectClass *klass, void *data)
dc->desc = "XIVE END Source";
dc->props = xive_end_source_properties;
dc->realize = xive_end_source_realize;
+ /*
+ * Reason: part of XIVE interrupt controller, needs to be wired up,
+ * e.g. by spapr_xive_instance_init().
+ */
+ dc->user_creatable = false;
}
static const TypeInfo xive_end_source_info = {
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
index a49096367c..b155dd8170 100644
--- a/hw/m68k/mcf5206.c
+++ b/hw/m68k/mcf5206.c
@@ -8,7 +8,6 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/irq.h"
@@ -57,10 +56,12 @@ static void m5206_timer_recalibrate(m5206_timer_state *s)
int prescale;
int mode;
+ ptimer_transaction_begin(s->timer);
ptimer_stop(s->timer);
- if ((s->tmr & TMR_RST) == 0)
- return;
+ if ((s->tmr & TMR_RST) == 0) {
+ goto exit;
+ }
prescale = (s->tmr >> 8) + 1;
mode = (s->tmr >> 1) & 3;
@@ -78,6 +79,8 @@ static void m5206_timer_recalibrate(m5206_timer_state *s)
ptimer_set_limit(s->timer, s->trr, 0);
ptimer_run(s->timer, 0);
+exit:
+ ptimer_transaction_commit(s->timer);
}
static void m5206_timer_trigger(void *opaque)
@@ -123,7 +126,9 @@ static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
s->tcr = val;
break;
case 0xc:
+ ptimer_transaction_begin(s->timer);
ptimer_set_count(s->timer, val);
+ ptimer_transaction_commit(s->timer);
break;
case 0x11:
s->ter &= ~val;
@@ -137,11 +142,9 @@ static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
static m5206_timer_state *m5206_timer_init(qemu_irq irq)
{
m5206_timer_state *s;
- QEMUBH *bh;
s = g_new0(m5206_timer_state, 1);
- bh = qemu_bh_new(m5206_timer_trigger, s);
- s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+ s->timer = ptimer_init(m5206_timer_trigger, s, PTIMER_POLICY_DEFAULT);
s->irq = irq;
m5206_timer_reset(s);
return s;
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 34d34eba17..158c5e4be7 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -9,7 +9,6 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
@@ -79,6 +78,7 @@ static void m5208_timer_write(void *opaque, hwaddr offset,
return;
}
+ ptimer_transaction_begin(s->timer);
if (s->pcsr & PCSR_EN)
ptimer_stop(s->timer);
@@ -94,8 +94,10 @@ static void m5208_timer_write(void *opaque, hwaddr offset,
if (s->pcsr & PCSR_EN)
ptimer_run(s->timer, 0);
+ ptimer_transaction_commit(s->timer);
break;
case 2:
+ ptimer_transaction_begin(s->timer);
s->pmr = value;
s->pcsr &= ~PCSR_PIF;
if ((s->pcsr & PCSR_RLD) == 0) {
@@ -104,6 +106,7 @@ static void m5208_timer_write(void *opaque, hwaddr offset,
} else {
ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
}
+ ptimer_transaction_commit(s->timer);
break;
case 4:
break;
@@ -182,7 +185,6 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
{
MemoryRegion *iomem = g_new(MemoryRegion, 1);
m5208_timer_state *s;
- QEMUBH *bh;
int i;
/* SDRAMC. */
@@ -191,8 +193,7 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
/* Timers. */
for (i = 0; i < 2; i++) {
s = g_new0(m5208_timer_state, 1);
- bh = qemu_bh_new(m5208_timer_trigger, s);
- s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+ s->timer = ptimer_init(m5208_timer_trigger, s, PTIMER_POLICY_DEFAULT);
memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s,
"m5208-timer", 0x00004000);
memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index cf537dd7e6..03a27e1767 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -39,7 +39,7 @@
#include "hw/ide.h"
#include "elf.h"
#include "hw/isa/vt82c686.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/timer/i8254.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 8d010a0b6e..d978bb64a0 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -39,7 +39,7 @@
#include "hw/scsi/esp.h"
#include "hw/mips/bios.h"
#include "hw/loader.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/timer/i8254.h"
#include "hw/display/vga.h"
#include "hw/audio/pcspk.h"
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 4d9c64b36a..c1c8810e71 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -45,7 +45,7 @@
#include "hw/irq.h"
#include "hw/loader.h"
#include "elf.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/timer/i8254.h"
#include "exec/address-spaces.h"
#include "hw/sysbus.h" /* SysBusDevice */
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index bc0be26544..70024235ae 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -28,7 +28,7 @@
#include "hw/ide.h"
#include "hw/loader.h"
#include "elf.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/input/i8042.h"
#include "hw/timer/i8254.h"
#include "exec/address-spaces.h"
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index a150680966..c89f3816a5 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -53,6 +53,7 @@ common-obj-$(CONFIG_OMAP) += omap_tap.o
common-obj-$(CONFIG_RASPI) += bcm2835_mbox.o
common-obj-$(CONFIG_RASPI) += bcm2835_property.o
common-obj-$(CONFIG_RASPI) += bcm2835_rng.o
+common-obj-$(CONFIG_RASPI) += bcm2835_thermal.o
common-obj-$(CONFIG_SLAVIO) += slavio_misc.o
common-obj-$(CONFIG_ZYNQ) += zynq_slcr.o
common-obj-$(CONFIG_ZYNQ) += zynq-xadc.o
diff --git a/hw/misc/bcm2835_thermal.c b/hw/misc/bcm2835_thermal.c
new file mode 100644
index 0000000000..c6f3b1ad60
--- /dev/null
+++ b/hw/misc/bcm2835_thermal.c
@@ -0,0 +1,135 @@
+/*
+ * BCM2835 dummy thermal sensor
+ *
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/misc/bcm2835_thermal.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+
+REG32(CTL, 0)
+FIELD(CTL, POWER_DOWN, 0, 1)
+FIELD(CTL, RESET, 1, 1)
+FIELD(CTL, BANDGAP_CTRL, 2, 3)
+FIELD(CTL, INTERRUPT_ENABLE, 5, 1)
+FIELD(CTL, DIRECT, 6, 1)
+FIELD(CTL, INTERRUPT_CLEAR, 7, 1)
+FIELD(CTL, HOLD, 8, 10)
+FIELD(CTL, RESET_DELAY, 18, 8)
+FIELD(CTL, REGULATOR_ENABLE, 26, 1)
+
+REG32(STAT, 4)
+FIELD(STAT, DATA, 0, 10)
+FIELD(STAT, VALID, 10, 1)
+FIELD(STAT, INTERRUPT, 11, 1)
+
+#define THERMAL_OFFSET_C 412
+#define THERMAL_COEFF (-0.538f)
+
+static uint16_t bcm2835_thermal_temp2adc(int temp_C)
+{
+ return (temp_C - THERMAL_OFFSET_C) / THERMAL_COEFF;
+}
+
+static uint64_t bcm2835_thermal_read(void *opaque, hwaddr addr, unsigned size)
+{
+ Bcm2835ThermalState *s = BCM2835_THERMAL(opaque);
+ uint32_t val = 0;
+
+ switch (addr) {
+ case A_CTL:
+ val = s->ctl;
+ break;
+ case A_STAT:
+ /* Temperature is constantly 25°C. */
+ val = FIELD_DP32(bcm2835_thermal_temp2adc(25), STAT, VALID, true);
+ break;
+ default:
+ /* MemoryRegionOps are aligned, so this can not happen. */
+ g_assert_not_reached();
+ }
+ return val;
+}
+
+static void bcm2835_thermal_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
+{
+ Bcm2835ThermalState *s = BCM2835_THERMAL(opaque);
+
+ switch (addr) {
+ case A_CTL:
+ s->ctl = value;
+ break;
+ case A_STAT:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write 0x%" PRIx64
+ " to 0x%" HWADDR_PRIx "\n",
+ __func__, value, addr);
+ break;
+ default:
+ /* MemoryRegionOps are aligned, so this can not happen. */
+ g_assert_not_reached();
+ }
+}
+
+static const MemoryRegionOps bcm2835_thermal_ops = {
+ .read = bcm2835_thermal_read,
+ .write = bcm2835_thermal_write,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 4,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void bcm2835_thermal_reset(DeviceState *dev)
+{
+ Bcm2835ThermalState *s = BCM2835_THERMAL(dev);
+
+ s->ctl = 0;
+}
+
+static void bcm2835_thermal_realize(DeviceState *dev, Error **errp)
+{
+ Bcm2835ThermalState *s = BCM2835_THERMAL(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_thermal_ops,
+ s, TYPE_BCM2835_THERMAL, 8);
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+}
+
+static const VMStateDescription bcm2835_thermal_vmstate = {
+ .name = "bcm2835_thermal",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(ctl, Bcm2835ThermalState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void bcm2835_thermal_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = bcm2835_thermal_realize;
+ dc->reset = bcm2835_thermal_reset;
+ dc->vmsd = &bcm2835_thermal_vmstate;
+}
+
+static const TypeInfo bcm2835_thermal_info = {
+ .name = TYPE_BCM2835_THERMAL,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(Bcm2835ThermalState),
+ .class_init = bcm2835_thermal_class_init,
+};
+
+static void bcm2835_thermal_register_types(void)
+{
+ type_register_static(&bcm2835_thermal_info);
+}
+
+type_init(bcm2835_thermal_register_types)
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index d9b3e8c691..717de76569 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -34,7 +34,6 @@
#include "etsec.h"
#include "registers.h"
#include "qemu/log.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
/* #define HEX_DUMP */
@@ -195,9 +194,11 @@ static void write_dmactrl(eTSEC *etsec,
if (!(value & DMACTRL_WOP)) {
/* Start polling */
+ ptimer_transaction_begin(etsec->ptimer);
ptimer_stop(etsec->ptimer);
ptimer_set_count(etsec->ptimer, 1);
ptimer_run(etsec->ptimer, 1);
+ ptimer_transaction_commit(etsec->ptimer);
}
}
@@ -391,10 +392,10 @@ static void etsec_realize(DeviceState *dev, Error **errp)
object_get_typename(OBJECT(dev)), dev->id, etsec);
qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a);
-
- etsec->bh = qemu_bh_new(etsec_timer_hit, etsec);
- etsec->ptimer = ptimer_init_with_bh(etsec->bh, PTIMER_POLICY_DEFAULT);
+ etsec->ptimer = ptimer_init(etsec_timer_hit, etsec, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(etsec->ptimer);
ptimer_set_freq(etsec->ptimer, 100);
+ ptimer_transaction_commit(etsec->ptimer);
}
static void etsec_instance_init(Object *obj)
diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h
index 09d05c2133..7951c3ad65 100644
--- a/hw/net/fsl_etsec/etsec.h
+++ b/hw/net/fsl_etsec/etsec.h
@@ -141,7 +141,6 @@ typedef struct eTSEC {
uint16_t phy_control;
/* Polling */
- QEMUBH *bh;
struct ptimer_state *ptimer;
/* Whether we should flush the rx queue when buffer becomes available. */
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 715b9a4fe6..97967d12eb 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -311,7 +311,7 @@ void pci_bridge_reset(DeviceState *qdev)
/*
* the default values for base/limit registers aren't specified
- * in the PCI-to-PCI-bridge spec. So we don't thouch them here.
+ * in the PCI-to-PCI-bridge spec. So we don't touch them here.
* Each implementation can override it.
* typical implementation does
* zero base/limit registers or
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 7cf64b6d25..60632720ef 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -48,7 +48,7 @@
#include "hw/isa/isa.h"
#include "hw/boards.h"
#include "hw/char/serial.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include <libfdt.h>
@@ -778,6 +778,13 @@ static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
pnv_cpu->intc = obj;
}
+static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
+{
+ PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
+
+ icp_reset(ICP(pnv_cpu->intc));
+}
+
/*
* 0:48 Reserved - Read as zeroes
* 49:52 Node ID
@@ -815,6 +822,13 @@ static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
pnv_cpu->intc = obj;
}
+static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
+{
+ PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
+
+ xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
+}
+
/*
* Allowed core identifiers on a POWER8 Processor Chip :
*
@@ -984,6 +998,7 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
k->cores_mask = POWER8E_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
+ k->intc_reset = pnv_chip_power8_intc_reset;
k->isa_create = pnv_chip_power8_isa_create;
k->dt_populate = pnv_chip_power8_dt_populate;
k->pic_print_info = pnv_chip_power8_pic_print_info;
@@ -1003,6 +1018,7 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
k->cores_mask = POWER8_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
+ k->intc_reset = pnv_chip_power8_intc_reset;
k->isa_create = pnv_chip_power8_isa_create;
k->dt_populate = pnv_chip_power8_dt_populate;
k->pic_print_info = pnv_chip_power8_pic_print_info;
@@ -1022,6 +1038,7 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
k->cores_mask = POWER8_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
+ k->intc_reset = pnv_chip_power8_intc_reset;
k->isa_create = pnv_chip_power8nvl_isa_create;
k->dt_populate = pnv_chip_power8_dt_populate;
k->pic_print_info = pnv_chip_power8_pic_print_info;
@@ -1191,6 +1208,7 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
k->cores_mask = POWER9_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p9;
k->intc_create = pnv_chip_power9_intc_create;
+ k->intc_reset = pnv_chip_power9_intc_reset;
k->isa_create = pnv_chip_power9_isa_create;
k->dt_populate = pnv_chip_power9_dt_populate;
k->pic_print_info = pnv_chip_power9_pic_print_info;
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index b1a7489e7a..e81cd3a3e0 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -40,11 +40,11 @@ static const char *pnv_core_cpu_typename(PnvCore *pc)
return cpu_type;
}
-static void pnv_cpu_reset(void *opaque)
+static void pnv_core_cpu_reset(PowerPCCPU *cpu, PnvChip *chip)
{
- PowerPCCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
cpu_reset(cs);
@@ -55,6 +55,8 @@ static void pnv_cpu_reset(void *opaque)
env->gpr[3] = PNV_FDT_ADDR;
env->nip = 0x10;
env->msr |= MSR_HVB; /* Hypervisor mode */
+
+ pcc->intc_reset(chip, cpu);
}
/*
@@ -160,7 +162,7 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};
-static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp)
+static void pnv_core_cpu_realize(PowerPCCPU *cpu, PnvChip *chip, Error **errp)
{
CPUPPCState *env = &cpu->env;
int core_pir;
@@ -192,8 +194,17 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp)
/* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
+}
+
+static void pnv_core_reset(void *dev)
+{
+ CPUCore *cc = CPU_CORE(dev);
+ PnvCore *pc = PNV_CORE(dev);
+ int i;
- qemu_register_reset(pnv_cpu_reset, cpu);
+ for (i = 0; i < cc->nr_threads; i++) {
+ pnv_core_cpu_reset(pc->threads[i], pc->chip);
+ }
}
static void pnv_core_realize(DeviceState *dev, Error **errp)
@@ -214,6 +225,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
"required link 'chip' not found: ");
return;
}
+ pc->chip = PNV_CHIP(chip);
pc->threads = g_new(PowerPCCPU *, cc->nr_threads);
for (i = 0; i < cc->nr_threads; i++) {
@@ -235,7 +247,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
}
for (j = 0; j < cc->nr_threads; j++) {
- pnv_realize_vcpu(pc->threads[j], PNV_CHIP(chip), &local_err);
+ pnv_core_cpu_realize(pc->threads[j], pc->chip, &local_err);
if (local_err) {
goto err;
}
@@ -244,6 +256,8 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id);
pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops,
pc, name, PNV_XSCOM_EX_SIZE);
+
+ qemu_register_reset(pnv_core_reset, pc);
return;
err:
@@ -255,11 +269,10 @@ err:
error_propagate(errp, local_err);
}
-static void pnv_unrealize_vcpu(PowerPCCPU *cpu)
+static void pnv_core_cpu_unrealize(PowerPCCPU *cpu)
{
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
- qemu_unregister_reset(pnv_cpu_reset, cpu);
object_unparent(OBJECT(pnv_cpu_state(cpu)->intc));
cpu_remove_sync(CPU(cpu));
cpu->machine_data = NULL;
@@ -273,8 +286,10 @@ static void pnv_core_unrealize(DeviceState *dev, Error **errp)
CPUCore *cc = CPU_CORE(dev);
int i;
+ qemu_unregister_reset(pnv_core_reset, pc);
+
for (i = 0; i < cc->nr_threads; i++) {
- pnv_unrealize_vcpu(pc->threads[i]);
+ pnv_core_cpu_unrealize(pc->threads[i]);
}
g_free(pc->threads);
}
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index a997f16bb4..68d0dfacfe 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -660,10 +660,19 @@ static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno)
uint32_t offset =
(psi->regs[PSIHB_REG(PSIHB9_IVT_OFFSET)] >> PSIHB9_IVT_OFF_SHIFT);
- uint64_t lisn = cpu_to_be64(offset + srcno);
+ uint64_t data = XIVE_TRIGGER_PQ | offset | srcno;
+ MemTxResult result;
- if (valid) {
- cpu_physical_memory_write(notify_addr, &lisn, sizeof(lisn));
+ if (!valid) {
+ return;
+ }
+
+ address_space_stq_be(&address_space_memory, notify_addr, data,
+ MEMTXATTRS_UNSPECIFIED, &result);
+ if (result != MEMTX_OK) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: trigger failed @%"
+ HWADDR_PRIx "\n", __func__, notif_port);
+ return;
}
}
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 388cae0b43..1f721feed6 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -29,7 +29,7 @@
#include "cpu.h"
#include "hw/ppc/ppc.h"
#include "ppc405.h"
-#include "hw/timer/m48t59.h"
+#include "hw/rtc/m48t59.h"
#include "hw/block/flash.h"
#include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 4f3c6bf190..862345c2ac 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -25,7 +25,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
-#include "hw/timer/m48t59.h"
+#include "hw/rtc/m48t59.h"
#include "hw/char/serial.h"
#include "hw/block/fdc.h"
#include "net/net.h"
@@ -40,7 +40,7 @@
#include "hw/ide.h"
#include "hw/irq.h"
#include "hw/loader.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
#include "hw/isa/pc87312.h"
#include "hw/net/ne2000-isa.h"
#include "sysemu/arch_init.h"
diff --git a/hw/ppc/rs6000_mc.c b/hw/ppc/rs6000_mc.c
index df7c0006fc..66b14db5fa 100644
--- a/hw/ppc/rs6000_mc.c
+++ b/hw/ppc/rs6000_mc.c
@@ -144,6 +144,7 @@ static void rs6000mc_realize(DeviceState *dev, Error **errp)
RS6000MCState *s = RS6000MC_DEVICE(dev);
int socket = 0;
unsigned int ram_size = s->ram_size / MiB;
+ Error *local_err = NULL;
while (socket < 6) {
if (ram_size >= 64) {
@@ -165,19 +166,21 @@ static void rs6000mc_realize(DeviceState *dev, Error **errp)
if (s->simm_size[socket]) {
char name[] = "simm.?";
name[5] = socket + '0';
- memory_region_allocate_system_memory(&s->simm[socket], OBJECT(dev),
- name,
- s->simm_size[socket] * MiB);
+ memory_region_init_ram(&s->simm[socket], OBJECT(dev), name,
+ s->simm_size[socket] * MiB, &local_err);
+ if (local_err) {
+ goto out;
+ }
memory_region_add_subregion_overlap(get_system_memory(), 0,
&s->simm[socket], socket);
}
}
if (ram_size) {
/* unable to push all requested RAM in SIMMs */
- error_setg(errp, "RAM size incompatible with this board. "
+ error_setg(&local_err, "RAM size incompatible with this board. "
"Try again with something else, like %" PRId64 " MB",
s->ram_size / MiB - ram_size);
- return;
+ goto out;
}
if (s->autoconfigure) {
@@ -193,6 +196,8 @@ static void rs6000mc_realize(DeviceState *dev, Error **errp)
isa_register_portio_list(ISA_DEVICE(dev), &s->portio, 0x0,
rs6000mc_port_list, s, "rs6000mc");
+out:
+ error_propagate(errp, local_err);
}
static const VMStateDescription vmstate_rs6000mc = {
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 4eb97d3a9b..94f9d27096 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1247,8 +1247,7 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
_FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
/* /interrupt controller */
- spapr->irq->dt_populate(spapr, spapr_max_server_number(spapr), fdt,
- PHANDLE_INTC);
+ spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC);
ret = spapr_populate_memory(spapr, fdt);
if (ret < 0) {
@@ -1268,7 +1267,7 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
}
QLIST_FOREACH(phb, &spapr->phbs, list) {
- ret = spapr_dt_phb(phb, PHANDLE_INTC, fdt, spapr->irq->nr_msis, NULL);
+ ret = spapr_dt_phb(spapr, phb, PHANDLE_INTC, fdt, NULL);
if (ret < 0) {
error_report("couldn't setup PCI devices in fdt");
exit(1);
@@ -2496,6 +2495,7 @@ static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
{
MachineState *ms = MACHINE(spapr);
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
Error *local_err = NULL;
bool vsmt_user = !!spapr->vsmt;
int kvm_smt = kvmppc_smt_threads();
@@ -2522,7 +2522,7 @@ static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
goto out;
}
/* In this case, spapr->vsmt has been set by the command line */
- } else {
+ } else if (!smc->smp_threads_vsmt) {
/*
* Default VSMT value is tricky, because we need it to be as
* consistent as possible (for migration), but this requires
@@ -2531,6 +2531,8 @@ static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
* overwhelmingly common case in production systems.
*/
spapr->vsmt = MAX(8, smp_threads);
+ } else {
+ spapr->vsmt = smp_threads;
}
/* KVM: If necessary, set the SMT mode: */
@@ -3739,9 +3741,10 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
spapr_vcpu_id(spapr, cc->core_id));
g_assert(drc);
- spapr_drc_detach(drc);
-
- spapr_hotplug_req_remove_by_index(drc);
+ if (!spapr_drc_unplug_requested(drc)) {
+ spapr_drc_detach(drc);
+ spapr_hotplug_req_remove_by_index(drc);
+ }
}
int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
@@ -3903,8 +3906,7 @@ int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
return -1;
}
- if (spapr_dt_phb(sphb, intc_phandle, fdt, spapr->irq->nr_msis,
- fdt_start_offset)) {
+ if (spapr_dt_phb(spapr, sphb, intc_phandle, fdt, fdt_start_offset)) {
error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
return -1;
}
@@ -4263,7 +4265,7 @@ static void spapr_pic_print_info(InterruptStatsProvider *obj,
{
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
- spapr->irq->print_info(spapr, mon);
+ spapr_irq_print_info(spapr, mon);
monitor_printf(mon, "irqchip: %s\n",
kvm_irqchip_in_kernel() ? "in-kernel" : "emulated");
}
@@ -4438,6 +4440,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
smc->irq = &spapr_irq_dual;
smc->dr_phb_enabled = true;
smc->linux_pci_probe = true;
+ smc->smp_threads_vsmt = true;
+ smc->nr_xirqs = SPAPR_NR_XIRQS;
}
static const TypeInfo spapr_machine_info = {
@@ -4505,6 +4509,7 @@ static void spapr_machine_4_1_class_options(MachineClass *mc)
spapr_machine_4_2_class_options(mc);
smc->linux_pci_probe = false;
+ smc->smp_threads_vsmt = false;
compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
}
@@ -4573,6 +4578,7 @@ static void spapr_machine_3_0_class_options(MachineClass *mc)
compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
smc->legacy_irq_allocation = true;
+ smc->nr_xirqs = 0x400;
smc->irq = &spapr_irq_xics_legacy;
}
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 1d93de8161..ef7b27a66d 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -25,14 +25,14 @@
#include "sysemu/hw_accel.h"
#include "qemu/error-report.h"
-static void spapr_cpu_reset(void *opaque)
+static void spapr_reset_vcpu(PowerPCCPU *cpu)
{
- PowerPCCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
target_ulong lpcr;
+ SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
cpu_reset(cs);
@@ -77,9 +77,11 @@ static void spapr_cpu_reset(void *opaque)
spapr_cpu->dtl_addr = 0;
spapr_cpu->dtl_size = 0;
- spapr_caps_cpu_apply(SPAPR_MACHINE(qdev_get_machine()), cpu);
+ spapr_caps_cpu_apply(spapr, cpu);
kvm_check_mmu(cpu, &error_fatal);
+
+ spapr_irq_cpu_intc_reset(spapr, cpu);
}
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3)
@@ -193,7 +195,6 @@ static void spapr_unrealize_vcpu(PowerPCCPU *cpu, SpaprCpuCore *sc)
if (!sc->pre_3_0_migration) {
vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
}
- qemu_unregister_reset(spapr_cpu_reset, cpu);
if (spapr_cpu_state(cpu)->icp) {
object_unparent(OBJECT(spapr_cpu_state(cpu)->icp));
}
@@ -204,12 +205,36 @@ static void spapr_unrealize_vcpu(PowerPCCPU *cpu, SpaprCpuCore *sc)
object_unparent(OBJECT(cpu));
}
+/*
+ * Called when CPUs are hot-plugged.
+ */
+static void spapr_cpu_core_reset(DeviceState *dev)
+{
+ CPUCore *cc = CPU_CORE(dev);
+ SpaprCpuCore *sc = SPAPR_CPU_CORE(dev);
+ int i;
+
+ for (i = 0; i < cc->nr_threads; i++) {
+ spapr_reset_vcpu(sc->threads[i]);
+ }
+}
+
+/*
+ * Called by the machine reset.
+ */
+static void spapr_cpu_core_reset_handler(void *opaque)
+{
+ spapr_cpu_core_reset(opaque);
+}
+
static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp)
{
SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(dev);
int i;
+ qemu_unregister_reset(spapr_cpu_core_reset_handler, sc);
+
for (i = 0; i < cc->nr_threads; i++) {
spapr_unrealize_vcpu(sc->threads[i], sc);
}
@@ -234,12 +259,8 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
cpu_ppc_set_vhyp(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
kvmppc_set_papr(cpu);
- qemu_register_reset(spapr_cpu_reset, cpu);
- spapr_cpu_reset(cpu);
-
- spapr->irq->cpu_intc_create(spapr, cpu, &local_err);
- if (local_err) {
- goto error_unregister;
+ if (spapr_irq_cpu_intc_create(spapr, cpu, &local_err) < 0) {
+ goto error_intc_create;
}
if (!sc->pre_3_0_migration) {
@@ -249,8 +270,7 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
return;
-error_unregister:
- qemu_unregister_reset(spapr_cpu_reset, cpu);
+error_intc_create:
cpu_remove_sync(CPU(cpu));
error:
error_propagate(errp, local_err);
@@ -337,6 +357,8 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
goto err_unrealize;
}
}
+
+ qemu_register_reset(spapr_cpu_core_reset_handler, sc);
return;
err_unrealize:
@@ -365,6 +387,7 @@ static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
dc->realize = spapr_cpu_core_realize;
dc->unrealize = spapr_cpu_core_unrealize;
+ dc->reset = spapr_cpu_core_reset;
dc->props = spapr_cpu_core_properties;
scc->cpu_type = data;
}
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 457eabe24c..b941608b69 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -23,9 +23,20 @@
#include "trace.h"
-void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis)
+static const TypeInfo spapr_intc_info = {
+ .name = TYPE_SPAPR_INTC,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(SpaprInterruptControllerClass),
+};
+
+static void spapr_irq_msi_init(SpaprMachineState *spapr)
{
- spapr->irq_map_nr = nr_msis;
+ if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+ /* Legacy mode doesn't use this allocator */
+ return;
+ }
+
+ spapr->irq_map_nr = spapr_irq_nr_msis(spapr);
spapr->irq_map = bitmap_new(spapr->irq_map_nr);
}
@@ -59,262 +70,53 @@ void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num)
bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
}
-static void spapr_irq_init_kvm(SpaprMachineState *spapr,
- SpaprIrq *irq, Error **errp)
+int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
+ SpaprInterruptController *intc,
+ Error **errp)
{
- MachineState *machine = MACHINE(spapr);
+ MachineState *machine = MACHINE(qdev_get_machine());
Error *local_err = NULL;
if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
- irq->init_kvm(spapr, &local_err);
- if (local_err && machine_kernel_irqchip_required(machine)) {
- error_prepend(&local_err,
- "kernel_irqchip requested but unavailable: ");
- error_propagate(errp, local_err);
- return;
- }
+ if (fn(intc, &local_err) < 0) {
+ if (machine_kernel_irqchip_required(machine)) {
+ error_prepend(&local_err,
+ "kernel_irqchip requested but unavailable: ");
+ error_propagate(errp, local_err);
+ return -1;
+ }
- if (!local_err) {
- return;
+ /*
+ * We failed to initialize the KVM device, fallback to
+ * emulated mode
+ */
+ error_prepend(&local_err,
+ "kernel_irqchip allowed but unavailable: ");
+ error_append_hint(&local_err,
+ "Falling back to kernel-irqchip=off\n");
+ warn_report_err(local_err);
}
-
- /*
- * We failed to initialize the KVM device, fallback to
- * emulated mode
- */
- error_prepend(&local_err, "kernel_irqchip allowed but unavailable: ");
- error_append_hint(&local_err, "Falling back to kernel-irqchip=off\n");
- warn_report_err(local_err);
}
+
+ return 0;
}
/*
* XICS IRQ backend.
*/
-static int spapr_irq_claim_xics(SpaprMachineState *spapr, int irq, bool lsi,
- Error **errp)
-{
- ICSState *ics = spapr->ics;
-
- assert(ics);
- assert(ics_valid_irq(ics, irq));
-
- if (!ics_irq_free(ics, irq - ics->offset)) {
- error_setg(errp, "IRQ %d is not free", irq);
- return -1;
- }
-
- ics_set_irq_type(ics, irq - ics->offset, lsi);
- return 0;
-}
-
-static void spapr_irq_free_xics(SpaprMachineState *spapr, int irq)
-{
- ICSState *ics = spapr->ics;
- uint32_t srcno = irq - ics->offset;
-
- assert(ics_valid_irq(ics, irq));
-
- memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
-}
-
-static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
-{
- CPUState *cs;
-
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
- }
-
- ics_pic_print_info(spapr->ics, mon);
-}
-
-static void spapr_irq_cpu_intc_create_xics(SpaprMachineState *spapr,
- PowerPCCPU *cpu, Error **errp)
-{
- Error *local_err = NULL;
- Object *obj;
- SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
-
- obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- spapr_cpu->icp = ICP(obj);
-}
-
-static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
-{
- if (!kvm_irqchip_in_kernel()) {
- CPUState *cs;
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- icp_resend(spapr_cpu_state(cpu)->icp);
- }
- }
- return 0;
-}
-
-static void spapr_irq_set_irq_xics(void *opaque, int irq, int val)
-{
- SpaprMachineState *spapr = opaque;
- uint32_t srcno = irq - spapr->ics->offset;
-
- ics_set_irq(spapr->ics, srcno, val);
-}
-
-static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
-{
- Error *local_err = NULL;
-
- spapr_irq_init_kvm(spapr, &spapr_irq_xics, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-}
-
-static void spapr_irq_init_kvm_xics(SpaprMachineState *spapr, Error **errp)
-{
- if (kvm_enabled()) {
- xics_kvm_connect(spapr, errp);
- }
-}
-
SpaprIrq spapr_irq_xics = {
- .nr_xirqs = SPAPR_NR_XIRQS,
- .nr_msis = SPAPR_NR_MSIS,
.xics = true,
.xive = false,
-
- .claim = spapr_irq_claim_xics,
- .free = spapr_irq_free_xics,
- .print_info = spapr_irq_print_info_xics,
- .dt_populate = spapr_dt_xics,
- .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
- .post_load = spapr_irq_post_load_xics,
- .reset = spapr_irq_reset_xics,
- .set_irq = spapr_irq_set_irq_xics,
- .init_kvm = spapr_irq_init_kvm_xics,
};
/*
* XIVE IRQ backend.
*/
-static int spapr_irq_claim_xive(SpaprMachineState *spapr, int irq, bool lsi,
- Error **errp)
-{
- return spapr_xive_irq_claim(spapr->xive, irq, lsi, errp);
-}
-
-static void spapr_irq_free_xive(SpaprMachineState *spapr, int irq)
-{
- spapr_xive_irq_free(spapr->xive, irq);
-}
-
-static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
- Monitor *mon)
-{
- CPUState *cs;
-
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- xive_tctx_pic_print_info(spapr_cpu_state(cpu)->tctx, mon);
- }
-
- spapr_xive_pic_print_info(spapr->xive, mon);
-}
-
-static void spapr_irq_cpu_intc_create_xive(SpaprMachineState *spapr,
- PowerPCCPU *cpu, Error **errp)
-{
- Error *local_err = NULL;
- Object *obj;
- SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
-
- obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- spapr_cpu->tctx = XIVE_TCTX(obj);
-
- /*
- * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
- * don't beneficiate from the reset of the XIVE IRQ backend
- */
- spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
-}
-
-static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
-{
- return spapr_xive_post_load(spapr->xive, version_id);
-}
-
-static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
-{
- CPUState *cs;
- Error *local_err = NULL;
-
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- /* (TCG) Set the OS CAM line of the thread interrupt context. */
- spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx);
- }
-
- spapr_irq_init_kvm(spapr, &spapr_irq_xive, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- /* Activate the XIVE MMIOs */
- spapr_xive_mmio_set_enabled(spapr->xive, true);
-}
-
-static void spapr_irq_set_irq_xive(void *opaque, int irq, int val)
-{
- SpaprMachineState *spapr = opaque;
-
- if (kvm_irqchip_in_kernel()) {
- kvmppc_xive_source_set_irq(&spapr->xive->source, irq, val);
- } else {
- xive_source_set_irq(&spapr->xive->source, irq, val);
- }
-}
-
-static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp)
-{
- if (kvm_enabled()) {
- kvmppc_xive_connect(spapr->xive, errp);
- }
-}
-
SpaprIrq spapr_irq_xive = {
- .nr_xirqs = SPAPR_NR_XIRQS,
- .nr_msis = SPAPR_NR_MSIS,
.xics = false,
.xive = true,
-
- .claim = spapr_irq_claim_xive,
- .free = spapr_irq_free_xive,
- .print_info = spapr_irq_print_info_xive,
- .dt_populate = spapr_dt_xive,
- .cpu_intc_create = spapr_irq_cpu_intc_create_xive,
- .post_load = spapr_irq_post_load_xive,
- .reset = spapr_irq_reset_xive,
- .set_irq = spapr_irq_set_irq_xive,
- .init_kvm = spapr_irq_init_kvm_xive,
};
/*
@@ -327,138 +129,11 @@ SpaprIrq spapr_irq_xive = {
*/
/*
- * Returns the sPAPR IRQ backend negotiated by CAS. XICS is the
- * default.
- */
-static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
-{
- return spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ?
- &spapr_irq_xive : &spapr_irq_xics;
-}
-
-static int spapr_irq_claim_dual(SpaprMachineState *spapr, int irq, bool lsi,
- Error **errp)
-{
- Error *local_err = NULL;
- int ret;
-
- ret = spapr_irq_xics.claim(spapr, irq, lsi, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return ret;
- }
-
- ret = spapr_irq_xive.claim(spapr, irq, lsi, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return ret;
- }
-
- return ret;
-}
-
-static void spapr_irq_free_dual(SpaprMachineState *spapr, int irq)
-{
- spapr_irq_xics.free(spapr, irq);
- spapr_irq_xive.free(spapr, irq);
-}
-
-static void spapr_irq_print_info_dual(SpaprMachineState *spapr, Monitor *mon)
-{
- spapr_irq_current(spapr)->print_info(spapr, mon);
-}
-
-static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
- uint32_t nr_servers, void *fdt,
- uint32_t phandle)
-{
- spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
-}
-
-static void spapr_irq_cpu_intc_create_dual(SpaprMachineState *spapr,
- PowerPCCPU *cpu, Error **errp)
-{
- Error *local_err = NULL;
-
- spapr_irq_xive.cpu_intc_create(spapr, cpu, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- spapr_irq_xics.cpu_intc_create(spapr, cpu, errp);
-}
-
-static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
-{
- /*
- * Force a reset of the XIVE backend after migration. The machine
- * defaults to XICS at startup.
- */
- if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
- if (kvm_irqchip_in_kernel()) {
- xics_kvm_disconnect(spapr, &error_fatal);
- }
- spapr_irq_xive.reset(spapr, &error_fatal);
- }
-
- return spapr_irq_current(spapr)->post_load(spapr, version_id);
-}
-
-static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
-{
- Error *local_err = NULL;
-
- /*
- * Deactivate the XIVE MMIOs. The XIVE backend will reenable them
- * if selected.
- */
- spapr_xive_mmio_set_enabled(spapr->xive, false);
-
- /* Destroy all KVM devices */
- if (kvm_irqchip_in_kernel()) {
- xics_kvm_disconnect(spapr, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- error_prepend(errp, "KVM XICS disconnect failed: ");
- return;
- }
- kvmppc_xive_disconnect(spapr->xive, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- error_prepend(errp, "KVM XIVE disconnect failed: ");
- return;
- }
- }
-
- spapr_irq_current(spapr)->reset(spapr, errp);
-}
-
-static void spapr_irq_set_irq_dual(void *opaque, int irq, int val)
-{
- SpaprMachineState *spapr = opaque;
-
- spapr_irq_current(spapr)->set_irq(spapr, irq, val);
-}
-
-/*
* Define values in sync with the XIVE and XICS backend
*/
SpaprIrq spapr_irq_dual = {
- .nr_xirqs = SPAPR_NR_XIRQS,
- .nr_msis = SPAPR_NR_MSIS,
.xics = true,
.xive = true,
-
- .claim = spapr_irq_claim_dual,
- .free = spapr_irq_free_dual,
- .print_info = spapr_irq_print_info_dual,
- .dt_populate = spapr_irq_dt_populate_dual,
- .cpu_intc_create = spapr_irq_cpu_intc_create_dual,
- .post_load = spapr_irq_post_load_dual,
- .reset = spapr_irq_reset_dual,
- .set_irq = spapr_irq_set_irq_dual,
- .init_kvm = NULL, /* should not be used */
};
@@ -521,9 +196,85 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
/*
* sPAPR IRQ frontend routines for devices
*/
+#define ALL_INTCS(spapr_) \
+ { SPAPR_INTC((spapr_)->ics), SPAPR_INTC((spapr_)->xive), }
+
+int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
+ PowerPCCPU *cpu, Error **errp)
+{
+ SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+ int i;
+ int rc;
+
+ for (i = 0; i < ARRAY_SIZE(intcs); i++) {
+ SpaprInterruptController *intc = intcs[i];
+ if (intc) {
+ SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+ rc = sicc->cpu_intc_create(intc, cpu, errp);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void spapr_irq_cpu_intc_reset(SpaprMachineState *spapr, PowerPCCPU *cpu)
+{
+ SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(intcs); i++) {
+ SpaprInterruptController *intc = intcs[i];
+ if (intc) {
+ SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+ sicc->cpu_intc_reset(intc, cpu);
+ }
+ }
+}
+
+static void spapr_set_irq(void *opaque, int irq, int level)
+{
+ SpaprMachineState *spapr = SPAPR_MACHINE(opaque);
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+ sicc->set_irq(spapr->active_intc, irq, level);
+}
+
+void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon)
+{
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+ sicc->print_info(spapr->active_intc, mon);
+}
+
+void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
+ void *fdt, uint32_t phandle)
+{
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+ sicc->dt(spapr->active_intc, nr_servers, fdt, phandle);
+}
+
+uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
+{
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
+ if (smc->legacy_irq_allocation) {
+ return smc->nr_xirqs;
+ } else {
+ return SPAPR_XIRQ_BASE + smc->nr_xirqs - SPAPR_IRQ_MSI;
+ }
+}
+
void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
{
MachineState *machine = MACHINE(spapr);
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
if (machine_kernel_irqchip_split(machine)) {
error_setg(errp, "kernel_irqchip split mode not supported on pseries");
@@ -541,9 +292,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
}
/* Initialize the MSI IRQ allocator. */
- if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
- spapr_irq_msi_init(spapr, spapr->irq->nr_msis);
- }
+ spapr_irq_msi_init(spapr);
if (spapr->irq->xics) {
Error *local_err = NULL;
@@ -563,8 +312,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
return;
}
- object_property_set_int(obj, spapr->irq->nr_xirqs, "nr-irqs",
- &local_err);
+ object_property_set_int(obj, smc->nr_xirqs, "nr-irqs", &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -585,8 +333,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
int i;
dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
- qdev_prop_set_uint32(dev, "nr-irqs",
- spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
+ qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_XIRQ_BASE);
/*
* 8 XIVE END structures per CPU. One for each available
* priority
@@ -598,8 +345,11 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
/* Enable the CPU IPIs */
for (i = 0; i < nr_servers; ++i) {
- if (spapr_xive_irq_claim(spapr->xive, SPAPR_IRQ_IPI + i,
- false, errp) < 0) {
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(spapr->xive);
+
+ if (sicc->claim_irq(SPAPR_INTC(spapr->xive), SPAPR_IRQ_IPI + i,
+ false, errp) < 0) {
return;
}
}
@@ -607,32 +357,60 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
spapr_xive_hcall_init(spapr);
}
- spapr->qirqs = qemu_allocate_irqs(spapr->irq->set_irq, spapr,
- spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
+ spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
+ smc->nr_xirqs + SPAPR_XIRQ_BASE);
}
int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
{
+ SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+ int i;
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ int rc;
+
assert(irq >= SPAPR_XIRQ_BASE);
- assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
+
+ for (i = 0; i < ARRAY_SIZE(intcs); i++) {
+ SpaprInterruptController *intc = intcs[i];
+ if (intc) {
+ SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+ rc = sicc->claim_irq(intc, irq, lsi, errp);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+ }
- return spapr->irq->claim(spapr, irq, lsi, errp);
+ return 0;
}
void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
{
- int i;
+ SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+ int i, j;
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
assert(irq >= SPAPR_XIRQ_BASE);
- assert((irq + num) <= (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert((irq + num) <= (smc->nr_xirqs + SPAPR_XIRQ_BASE));
for (i = irq; i < (irq + num); i++) {
- spapr->irq->free(spapr, i);
+ for (j = 0; j < ARRAY_SIZE(intcs); j++) {
+ SpaprInterruptController *intc = intcs[j];
+
+ if (intc) {
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(intc);
+ sicc->free_irq(intc, i);
+ }
+ }
}
}
qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
{
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
/*
* This interface is basically for VIO and PHB devices to find the
* right qemu_irq to manipulate, so we only allow access to the
@@ -641,7 +419,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
* interfaces, we can change this if we need to in future.
*/
assert(irq >= SPAPR_XIRQ_BASE);
- assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
if (spapr->ics) {
assert(ics_valid_irq(spapr->ics, irq));
@@ -656,16 +434,18 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
int spapr_irq_post_load(SpaprMachineState *spapr, int version_id)
{
- return spapr->irq->post_load(spapr, version_id);
+ SpaprInterruptControllerClass *sicc;
+
+ spapr_irq_update_active_intc(spapr);
+ sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+ return sicc->post_load(spapr->active_intc, version_id);
}
void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
{
assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
- if (spapr->irq->reset) {
- spapr->irq->reset(spapr, errp);
- }
+ spapr_irq_update_active_intc(spapr);
}
int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
@@ -689,6 +469,54 @@ int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
return phandle;
}
+static void set_active_intc(SpaprMachineState *spapr,
+ SpaprInterruptController *new_intc)
+{
+ SpaprInterruptControllerClass *sicc;
+
+ assert(new_intc);
+
+ if (new_intc == spapr->active_intc) {
+ /* Nothing to do */
+ return;
+ }
+
+ if (spapr->active_intc) {
+ sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+ if (sicc->deactivate) {
+ sicc->deactivate(spapr->active_intc);
+ }
+ }
+
+ sicc = SPAPR_INTC_GET_CLASS(new_intc);
+ if (sicc->activate) {
+ sicc->activate(new_intc, &error_fatal);
+ }
+
+ spapr->active_intc = new_intc;
+}
+
+void spapr_irq_update_active_intc(SpaprMachineState *spapr)
+{
+ SpaprInterruptController *new_intc;
+
+ if (!spapr->ics) {
+ /*
+ * XXX before we run CAS, ov5_cas is initialized empty, which
+ * indicates XICS, even if we have ic-mode=xive. TODO: clean
+ * up the CAS path so that we have a clearer way of handling
+ * this.
+ */
+ new_intc = SPAPR_INTC(spapr->xive);
+ } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
+ new_intc = SPAPR_INTC(spapr->xive);
+ } else {
+ new_intc = SPAPR_INTC(spapr->ics);
+ }
+
+ set_active_intc(spapr, new_intc);
+}
+
/*
* XICS legacy routines - to deprecate one day
*/
@@ -744,21 +572,14 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
return first + ics->offset;
}
-#define SPAPR_IRQ_XICS_LEGACY_NR_XIRQS 0x400
-
SpaprIrq spapr_irq_xics_legacy = {
- .nr_xirqs = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
- .nr_msis = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
.xics = true,
.xive = false,
-
- .claim = spapr_irq_claim_xics,
- .free = spapr_irq_free_xics,
- .print_info = spapr_irq_print_info_xics,
- .dt_populate = spapr_dt_xics,
- .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
- .post_load = spapr_irq_post_load_xics,
- .reset = spapr_irq_reset_xics,
- .set_irq = spapr_irq_set_irq_xics,
- .init_kvm = spapr_irq_init_kvm_xics,
};
+
+static void spapr_irq_register_types(void)
+{
+ type_register_static(&spapr_intc_info);
+}
+
+type_init(spapr_irq_register_types)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 01ff41d4c4..cc0e7829b6 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -2277,8 +2277,8 @@ static void spapr_phb_pci_enumerate(SpaprPhbState *phb)
}
-int spapr_dt_phb(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
- uint32_t nr_msis, int *node_offset)
+int spapr_dt_phb(SpaprMachineState *spapr, SpaprPhbState *phb,
+ uint32_t intc_phandle, void *fdt, int *node_offset)
{
int bus_off, i, j, ret;
uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
@@ -2343,7 +2343,8 @@ int spapr_dt_phb(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
_FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges));
_FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
- _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", nr_msis));
+ _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi",
+ spapr_irq_nr_msis(spapr)));
/* Dynamic DMA window */
if (phb->ddw_enabled) {
diff --git a/hw/rtc/Kconfig b/hw/rtc/Kconfig
new file mode 100644
index 0000000000..45daa8d655
--- /dev/null
+++ b/hw/rtc/Kconfig
@@ -0,0 +1,23 @@
+config DS1338
+ bool
+ depends on I2C
+
+config M41T80
+ bool
+ depends on I2C
+
+config M48T59
+ bool
+
+config PL031
+ bool
+
+config TWL92230
+ bool
+ depends on I2C
+
+config MC146818RTC
+ bool
+
+config SUN4V_RTC
+ bool
diff --git a/hw/rtc/Makefile.objs b/hw/rtc/Makefile.objs
new file mode 100644
index 0000000000..8dc9fcd3a9
--- /dev/null
+++ b/hw/rtc/Makefile.objs
@@ -0,0 +1,13 @@
+common-obj-$(CONFIG_DS1338) += ds1338.o
+common-obj-$(CONFIG_M41T80) += m41t80.o
+common-obj-$(CONFIG_M48T59) += m48t59.o
+ifeq ($(CONFIG_ISA_BUS),y)
+common-obj-$(CONFIG_M48T59) += m48t59-isa.o
+endif
+common-obj-$(CONFIG_PL031) += pl031.o
+common-obj-$(CONFIG_TWL92230) += twl92230.o
+common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
+common-obj-$(CONFIG_EXYNOS4) += exynos4210_rtc.o
+obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
+common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
+common-obj-$(CONFIG_ASPEED_SOC) += aspeed_rtc.o
diff --git a/hw/timer/aspeed_rtc.c b/hw/rtc/aspeed_rtc.c
index 5313017353..3ca1183558 100644
--- a/hw/timer/aspeed_rtc.c
+++ b/hw/rtc/aspeed_rtc.c
@@ -8,7 +8,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
-#include "hw/timer/aspeed_rtc.h"
+#include "hw/rtc/aspeed_rtc.h"
#include "migration/vmstate.h"
#include "qemu/log.h"
#include "qemu/timer.h"
diff --git a/hw/timer/ds1338.c b/hw/rtc/ds1338.c
index 588a9ba9be..588a9ba9be 100644
--- a/hw/timer/ds1338.c
+++ b/hw/rtc/ds1338.c
diff --git a/hw/timer/exynos4210_rtc.c b/hw/rtc/exynos4210_rtc.c
index f85483a07f..f85483a07f 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/rtc/exynos4210_rtc.c
diff --git a/hw/timer/m41t80.c b/hw/rtc/m41t80.c
index 914ecac8f4..914ecac8f4 100644
--- a/hw/timer/m41t80.c
+++ b/hw/rtc/m41t80.c
diff --git a/hw/timer/m48t59-internal.h b/hw/rtc/m48t59-internal.h
index 4d4f2a6fed..4d4f2a6fed 100644
--- a/hw/timer/m48t59-internal.h
+++ b/hw/rtc/m48t59-internal.h
diff --git a/hw/timer/m48t59-isa.c b/hw/rtc/m48t59-isa.c
index 5e5432abfd..7fde854c0f 100644
--- a/hw/timer/m48t59-isa.c
+++ b/hw/rtc/m48t59-isa.c
@@ -1,5 +1,5 @@
/*
- * QEMU M48T59 and M48T08 NVRAM emulation (ISA bus interface
+ * QEMU M48T59 and M48T08 NVRAM emulation (ISA bus interface)
*
* Copyright (c) 2003-2005, 2007 Jocelyn Mayer
* Copyright (c) 2013 Hervé Poussineau
@@ -26,7 +26,7 @@
#include "qemu/osdep.h"
#include "hw/isa/isa.h"
#include "hw/qdev-properties.h"
-#include "hw/timer/m48t59.h"
+#include "hw/rtc/m48t59.h"
#include "m48t59-internal.h"
#include "qemu/module.h"
diff --git a/hw/timer/m48t59.c b/hw/rtc/m48t59.c
index a9fc2f981a..fc592b9fb1 100644
--- a/hw/timer/m48t59.c
+++ b/hw/rtc/m48t59.c
@@ -27,7 +27,7 @@
#include "qemu-common.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
-#include "hw/timer/m48t59.h"
+#include "hw/rtc/m48t59.h"
#include "qemu/timer.h"
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
diff --git a/hw/timer/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index 0d7784b104..ee6bf82b40 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -34,13 +34,14 @@
#include "sysemu/replay.h"
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc_regs.h"
#include "migration/vmstate.h"
#include "qapi/error.h"
#include "qapi/qapi-events-misc-target.h"
#include "qapi/visitor.h"
#include "exec/address-spaces.h"
-#include "hw/timer/mc146818rtc_regs.h"
+#include "hw/rtc/mc146818rtc_regs.h"
#ifdef TARGET_I386
#include "qapi/qapi-commands-misc-target.h"
diff --git a/hw/timer/pl031.c b/hw/rtc/pl031.c
index 2b3e261006..3a982752a2 100644
--- a/hw/timer/pl031.c
+++ b/hw/rtc/pl031.c
@@ -13,7 +13,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
-#include "hw/timer/pl031.h"
+#include "hw/rtc/pl031.h"
#include "migration/vmstate.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
diff --git a/hw/timer/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
index 54272a822f..ada01b5774 100644
--- a/hw/timer/sun4v-rtc.c
+++ b/hw/rtc/sun4v-rtc.c
@@ -13,7 +13,7 @@
#include "hw/sysbus.h"
#include "qemu/module.h"
#include "qemu/timer.h"
-#include "hw/timer/sun4v-rtc.h"
+#include "hw/rtc/sun4v-rtc.h"
#include "trace.h"
diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events
new file mode 100644
index 0000000000..d6749f4616
--- /dev/null
+++ b/hw/rtc/trace-events
@@ -0,0 +1,19 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# sun4v-rtc.c
+sun4v_rtc_read(uint64_t addr, uint64_t value) "read: addr 0x%" PRIx64 " value 0x%" PRIx64
+sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value 0x%" PRIx64
+
+# xlnx-zynqmp-rtc.c
+xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
+
+# pl031.c
+pl031_irq_state(int level) "irq state %d"
+pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+pl031_alarm_raised(void) "alarm raised"
+pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
+
+# aspeed-rtc.c
+aspeed_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
+aspeed_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
diff --git a/hw/timer/twl92230.c b/hw/rtc/twl92230.c
index 63bd13d2ca..63bd13d2ca 100644
--- a/hw/timer/twl92230.c
+++ b/hw/rtc/twl92230.c
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/rtc/xlnx-zynqmp-rtc.c
index 5692db98c2..2bcd14d779 100644
--- a/hw/timer/xlnx-zynqmp-rtc.c
+++ b/hw/rtc/xlnx-zynqmp-rtc.c
@@ -32,11 +32,10 @@
#include "qemu/log.h"
#include "qemu/module.h"
#include "hw/irq.h"
-#include "hw/ptimer.h"
#include "qemu/cutils.h"
#include "sysemu/sysemu.h"
#include "trace.h"
-#include "hw/timer/xlnx-zynqmp-rtc.h"
+#include "hw/rtc/xlnx-zynqmp-rtc.h"
#include "migration/vmstate.h"
#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index e08ec3e398..88404d0e9d 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1532,6 +1532,8 @@ static const TypeInfo sdhci_bus_info = {
.class_init = sdhci_bus_class_init,
};
+/* --- qdev i.MX eSDHC --- */
+
static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
{
SDHCIState *s = SYSBUS_SDHCI(opaque);
@@ -1734,7 +1736,6 @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
}
}
-
static const MemoryRegionOps usdhc_mmio_ops = {
.read = usdhc_read,
.write = usdhc_write,
@@ -1760,11 +1761,76 @@ static const TypeInfo imx_usdhc_info = {
.instance_init = imx_usdhc_init,
};
+/* --- qdev Samsung s3c --- */
+
+#define S3C_SDHCI_CONTROL2 0x80
+#define S3C_SDHCI_CONTROL3 0x84
+#define S3C_SDHCI_CONTROL4 0x8c
+
+static uint64_t sdhci_s3c_read(void *opaque, hwaddr offset, unsigned size)
+{
+ uint64_t ret;
+
+ switch (offset) {
+ case S3C_SDHCI_CONTROL2:
+ case S3C_SDHCI_CONTROL3:
+ case S3C_SDHCI_CONTROL4:
+ /* ignore */
+ ret = 0;
+ break;
+ default:
+ ret = sdhci_read(opaque, offset, size);
+ break;
+ }
+
+ return ret;
+}
+
+static void sdhci_s3c_write(void *opaque, hwaddr offset, uint64_t val,
+ unsigned size)
+{
+ switch (offset) {
+ case S3C_SDHCI_CONTROL2:
+ case S3C_SDHCI_CONTROL3:
+ case S3C_SDHCI_CONTROL4:
+ /* ignore */
+ break;
+ default:
+ sdhci_write(opaque, offset, val, size);
+ break;
+ }
+}
+
+static const MemoryRegionOps sdhci_s3c_mmio_ops = {
+ .read = sdhci_s3c_read,
+ .write = sdhci_s3c_write,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ .unaligned = false
+ },
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void sdhci_s3c_init(Object *obj)
+{
+ SDHCIState *s = SYSBUS_SDHCI(obj);
+
+ s->io_ops = &sdhci_s3c_mmio_ops;
+}
+
+static const TypeInfo sdhci_s3c_info = {
+ .name = TYPE_S3C_SDHCI ,
+ .parent = TYPE_SYSBUS_SDHCI,
+ .instance_init = sdhci_s3c_init,
+};
+
static void sdhci_register_types(void)
{
type_register_static(&sdhci_sysbus_info);
type_register_static(&sdhci_bus_info);
type_register_static(&imx_usdhc_info);
+ type_register_static(&sdhci_s3c_info);
}
type_init(sdhci_register_types)
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 6c5a17a020..2aaa5bf1ae 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -31,7 +31,7 @@
#include "qemu/error-report.h"
#include "qemu/timer.h"
#include "hw/sparc/sun4m_iommu.h"
-#include "hw/timer/m48t59.h"
+#include "hw/rtc/m48t59.h"
#include "migration/vmstate.h"
#include "hw/sparc/sparc32_dma.h"
#include "hw/block/fdc.h"
diff --git a/hw/sparc64/niagara.c b/hw/sparc64/niagara.c
index 167143bffe..5eb2d097b9 100644
--- a/hw/sparc64/niagara.c
+++ b/hw/sparc64/niagara.c
@@ -30,12 +30,13 @@
#include "hw/misc/unimp.h"
#include "hw/loader.h"
#include "hw/sparc/sparc64.h"
-#include "hw/timer/sun4v-rtc.h"
+#include "hw/rtc/sun4v-rtc.h"
#include "exec/address-spaces.h"
#include "sysemu/block-backend.h"
#include "qemu/error-report.h"
#include "sysemu/qtest.h"
#include "sysemu/sysemu.h"
+#include "qapi/error.h"
typedef struct NiagaraBoardState {
MemoryRegion hv_ram;
@@ -106,8 +107,8 @@ static void niagara_init(MachineState *machine)
/* init CPUs */
sparc64_cpu_devinit(machine->cpu_type, NIAGARA_PROM_BASE);
/* set up devices */
- memory_region_allocate_system_memory(&s->hv_ram, NULL, "sun4v-hv.ram",
- NIAGARA_HV_RAM_SIZE);
+ memory_region_init_ram(&s->hv_ram, NULL, "sun4v-hv.ram",
+ NIAGARA_HV_RAM_SIZE, &error_fatal);
memory_region_add_subregion(sysmem, NIAGARA_HV_RAM_BASE, &s->hv_ram);
memory_region_allocate_system_memory(&s->partition_ram, NULL,
@@ -116,17 +117,17 @@ static void niagara_init(MachineState *machine)
memory_region_add_subregion(sysmem, NIAGARA_PARTITION_RAM_BASE,
&s->partition_ram);
- memory_region_allocate_system_memory(&s->nvram, NULL,
- "sun4v.nvram", NIAGARA_NVRAM_SIZE);
+ memory_region_init_ram(&s->nvram, NULL, "sun4v.nvram", NIAGARA_NVRAM_SIZE,
+ &error_fatal);
memory_region_add_subregion(sysmem, NIAGARA_NVRAM_BASE, &s->nvram);
- memory_region_allocate_system_memory(&s->md_rom, NULL,
- "sun4v-md.rom", NIAGARA_MD_ROM_SIZE);
+ memory_region_init_ram(&s->md_rom, NULL, "sun4v-md.rom",
+ NIAGARA_MD_ROM_SIZE, &error_fatal);
memory_region_add_subregion(sysmem, NIAGARA_MD_ROM_BASE, &s->md_rom);
- memory_region_allocate_system_memory(&s->hv_rom, NULL,
- "sun4v-hv.rom", NIAGARA_HV_ROM_SIZE);
+ memory_region_init_ram(&s->hv_rom, NULL, "sun4v-hv.rom",
+ NIAGARA_HV_ROM_SIZE, &error_fatal);
memory_region_add_subregion(sysmem, NIAGARA_HV_ROM_BASE, &s->hv_rom);
- memory_region_allocate_system_memory(&s->prom, NULL,
- "sun4v.prom", PROM_SIZE_MAX);
+ memory_region_init_ram(&s->prom, NULL, "sun4v.prom", PROM_SIZE_MAX,
+ &error_fatal);
memory_region_add_subregion(sysmem, NIAGARA_PROM_BASE, &s->prom);
add_rom_or_fail("nvram1", NIAGARA_NVRAM_BASE);
@@ -143,8 +144,8 @@ static void niagara_init(MachineState *machine)
BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
int size = blk_getlength(blk);
if (size > 0) {
- memory_region_allocate_system_memory(&s->vdisk_ram, NULL,
- "sun4v_vdisk.ram", size);
+ memory_region_init_ram(&s->vdisk_ram, NULL, "sun4v_vdisk.ram", size,
+ &error_fatal);
memory_region_add_subregion(get_system_memory(),
NIAGARA_VDISK_BASE, &s->vdisk_ram);
dinfo->is_default = 1;
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 1ded2a4c9a..955082773b 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -36,7 +36,7 @@
#include "hw/pci-host/sabre.h"
#include "hw/char/serial.h"
#include "hw/char/parallel.h"
-#include "hw/timer/m48t59.h"
+#include "hw/rtc/m48t59.h"
#include "migration/vmstate.h"
#include "hw/input/i8042.h"
#include "hw/block/fdc.h"
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
index eefc95f35e..a990f9fe35 100644
--- a/hw/timer/Kconfig
+++ b/hw/timer/Kconfig
@@ -9,10 +9,6 @@ config ARM_MPTIMER
config A9_GTIMER
bool
-config DS1338
- bool
- depends on I2C
-
config HPET
bool
default y if PC
@@ -20,27 +16,10 @@ config HPET
config I8254
bool
-config M41T80
- bool
- depends on I2C
-
-config M48T59
- bool
-
-config PL031
- bool
-
-config TWL92230
- bool
- depends on I2C
-
config ALTERA_TIMER
bool
select PTIMER
-config MC146818RTC
- bool
-
config ALLWINNER_A10_PIT
bool
select PTIMER
@@ -48,9 +27,6 @@ config ALLWINNER_A10_PIT
config STM32F2XX_TIMER
bool
-config SUN4V_RTC
- bool
-
config CMSDK_APB_TIMER
bool
select PTIMER
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index 123d92c969..dece235fd7 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -3,17 +3,9 @@ common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o
common-obj-$(CONFIG_ARM_V7M) += armv7m_systick.o
common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o
common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
-common-obj-$(CONFIG_DS1338) += ds1338.o
common-obj-$(CONFIG_HPET) += hpet.o
common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
-common-obj-$(CONFIG_M41T80) += m41t80.o
-common-obj-$(CONFIG_M48T59) += m48t59.o
-ifeq ($(CONFIG_ISA_BUS),y)
-common-obj-$(CONFIG_M48T59) += m48t59-isa.o
-endif
-common-obj-$(CONFIG_PL031) += pl031.o
common-obj-$(CONFIG_PUV3) += puv3_ost.o
-common-obj-$(CONFIG_TWL92230) += twl92230.o
common-obj-$(CONFIG_XILINX) += xilinx_timer.o
common-obj-$(CONFIG_SLAVIO) += slavio_timer.o
common-obj-$(CONFIG_ETRAXFS) += etraxfs_timer.o
@@ -22,28 +14,24 @@ common-obj-$(CONFIG_IMX) += imx_epit.o
common-obj-$(CONFIG_IMX) += imx_gpt.o
common-obj-$(CONFIG_LM32) += lm32_timer.o
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
-common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
common-obj-$(CONFIG_NRF51_SOC) += nrf51_timer.o
-obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
-obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
-obj-$(CONFIG_EXYNOS4) += exynos4210_pwm.o
-obj-$(CONFIG_EXYNOS4) += exynos4210_rtc.o
-obj-$(CONFIG_OMAP) += omap_gptimer.o
-obj-$(CONFIG_OMAP) += omap_synctimer.o
-obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o
-obj-$(CONFIG_SH4) += sh_timer.o
-obj-$(CONFIG_DIGIC) += digic-timer.o
-obj-$(CONFIG_MIPS_CPS) += mips_gictimer.o
+common-obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
+common-obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
+common-obj-$(CONFIG_EXYNOS4) += exynos4210_pwm.o
+common-obj-$(CONFIG_OMAP) += omap_gptimer.o
+common-obj-$(CONFIG_OMAP) += omap_synctimer.o
+common-obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o
+common-obj-$(CONFIG_SH4) += sh_timer.o
+common-obj-$(CONFIG_DIGIC) += digic-timer.o
+common-obj-$(CONFIG_MIPS_CPS) += mips_gictimer.o
-obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
-
-obj-$(CONFIG_ALLWINNER_A10_PIT) += allwinner-a10-pit.o
+common-obj-$(CONFIG_ALLWINNER_A10_PIT) += allwinner-a10-pit.o
common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o
-common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o aspeed_rtc.o
+common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
-common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
common-obj-$(CONFIG_CMSDK_APB_DUALTIMER) += cmsdk-apb-dualtimer.o
common-obj-$(CONFIG_MSF2) += mss-timer.o
+common-obj-$(CONFIG_RASPI) += bcm2835_systmr.o
diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c
index ee32e0ec1f..79fc381252 100644
--- a/hw/timer/altera_timer.c
+++ b/hw/timer/altera_timer.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qapi/error.h"
@@ -53,7 +52,6 @@ typedef struct AlteraTimer {
MemoryRegion mmio;
qemu_irq irq;
uint32_t freq_hz;
- QEMUBH *bh;
ptimer_state *ptimer;
uint32_t regs[R_MAX];
} AlteraTimer;
@@ -105,6 +103,7 @@ static void timer_write(void *opaque, hwaddr addr,
break;
case R_CONTROL:
+ ptimer_transaction_begin(t->ptimer);
t->regs[R_CONTROL] = value & (CONTROL_ITO | CONTROL_CONT);
if ((value & CONTROL_START) &&
!(t->regs[R_STATUS] & STATUS_RUN)) {
@@ -115,10 +114,12 @@ static void timer_write(void *opaque, hwaddr addr,
ptimer_stop(t->ptimer);
t->regs[R_STATUS] &= ~STATUS_RUN;
}
+ ptimer_transaction_commit(t->ptimer);
break;
case R_PERIODL:
case R_PERIODH:
+ ptimer_transaction_begin(t->ptimer);
t->regs[addr] = value & 0xFFFF;
if (t->regs[R_STATUS] & STATUS_RUN) {
ptimer_stop(t->ptimer);
@@ -126,6 +127,7 @@ static void timer_write(void *opaque, hwaddr addr,
}
tvalue = (t->regs[R_PERIODH] << 16) | t->regs[R_PERIODL];
ptimer_set_limit(t->ptimer, tvalue + 1, 1);
+ ptimer_transaction_commit(t->ptimer);
break;
case R_SNAPL:
@@ -183,9 +185,10 @@ static void altera_timer_realize(DeviceState *dev, Error **errp)
return;
}
- t->bh = qemu_bh_new(timer_hit, t);
- t->ptimer = ptimer_init_with_bh(t->bh, PTIMER_POLICY_DEFAULT);
+ t->ptimer = ptimer_init(timer_hit, t, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(t->ptimer);
ptimer_set_freq(t->ptimer, t->freq_hz);
+ ptimer_transaction_commit(t->ptimer);
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
TYPE_ALTERA_TIMER, R_MAX * sizeof(uint32_t));
@@ -204,8 +207,10 @@ static void altera_timer_reset(DeviceState *dev)
{
AlteraTimer *t = ALTERA_TIMER(dev);
+ ptimer_transaction_begin(t->ptimer);
ptimer_stop(t->ptimer);
ptimer_set_limit(t->ptimer, 0xffffffff, 1);
+ ptimer_transaction_commit(t->ptimer);
memset(t->regs, 0, sizeof(t->regs));
}
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index fdf97d1800..2bf11f788c 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -237,7 +237,7 @@ static void arm_mptimer_reset(DeviceState *dev)
}
}
-static void arm_mptimer_init_with_bh(Object *obj)
+static void arm_mptimer_init(Object *obj)
{
ARMMPTimerState *s = ARM_MPTIMER(obj);
@@ -319,7 +319,7 @@ static const TypeInfo arm_mptimer_info = {
.name = TYPE_ARM_MPTIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARMMPTimerState),
- .instance_init = arm_mptimer_init_with_bh,
+ .instance_init = arm_mptimer_init,
.class_init = arm_mptimer_class_init,
};
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
new file mode 100644
index 0000000000..3387a6214a
--- /dev/null
+++ b/hw/timer/bcm2835_systmr.c
@@ -0,0 +1,163 @@
+/*
+ * BCM2835 SYS timer emulation
+ *
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Datasheet: BCM2835 ARM Peripherals (C6357-M-1398)
+ * https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
+ *
+ * Only the free running 64-bit counter is implemented.
+ * The 4 COMPARE registers and the interruption are not implemented.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "hw/timer/bcm2835_systmr.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+REG32(CTRL_STATUS, 0x00)
+REG32(COUNTER_LOW, 0x04)
+REG32(COUNTER_HIGH, 0x08)
+REG32(COMPARE0, 0x0c)
+REG32(COMPARE1, 0x10)
+REG32(COMPARE2, 0x14)
+REG32(COMPARE3, 0x18)
+
+static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
+{
+ bool enable = !!s->reg.status;
+
+ trace_bcm2835_systmr_irq(enable);
+ qemu_set_irq(s->irq, enable);
+}
+
+static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
+ unsigned timer_index)
+{
+ /* TODO fow now, since neither Linux nor U-boot use these timers. */
+ qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
+ timer_index);
+}
+
+static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
+ uint64_t r = 0;
+
+ switch (offset) {
+ case A_CTRL_STATUS:
+ r = s->reg.status;
+ break;
+ case A_COMPARE0 ... A_COMPARE3:
+ r = s->reg.compare[(offset - A_COMPARE0) >> 2];
+ break;
+ case A_COUNTER_LOW:
+ case A_COUNTER_HIGH:
+ /* Free running counter at 1MHz */
+ r = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
+ r >>= 8 * (offset - A_COUNTER_LOW);
+ r &= UINT32_MAX;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ }
+ trace_bcm2835_systmr_read(offset, r);
+
+ return r;
+}
+
+static void bcm2835_systmr_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
+
+ trace_bcm2835_systmr_write(offset, value);
+ switch (offset) {
+ case A_CTRL_STATUS:
+ s->reg.status &= ~value; /* Ack */
+ bcm2835_systmr_update_irq(s);
+ break;
+ case A_COMPARE0 ... A_COMPARE3:
+ s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
+ bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
+ break;
+ case A_COUNTER_LOW:
+ case A_COUNTER_HIGH:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only ofs 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ }
+}
+
+static const MemoryRegionOps bcm2835_systmr_ops = {
+ .read = bcm2835_systmr_read,
+ .write = bcm2835_systmr_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static void bcm2835_systmr_reset(DeviceState *dev)
+{
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(dev);
+
+ memset(&s->reg, 0, sizeof(s->reg));
+}
+
+static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
+ s, "bcm2835-sys-timer", 0x20);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
+}
+
+static const VMStateDescription bcm2835_systmr_vmstate = {
+ .name = "bcm2835_sys_timer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void bcm2835_systmr_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = bcm2835_systmr_realize;
+ dc->reset = bcm2835_systmr_reset;
+ dc->vmsd = &bcm2835_systmr_vmstate;
+}
+
+static const TypeInfo bcm2835_systmr_info = {
+ .name = TYPE_BCM2835_SYSTIMER,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835SystemTimerState),
+ .class_init = bcm2835_systmr_class_init,
+};
+
+static void bcm2835_systmr_register_types(void)
+{
+ type_register_static(&bcm2835_systmr_info);
+}
+
+type_init(bcm2835_systmr_register_types);
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index ab27fe1895..afe3d30a8e 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -26,7 +26,6 @@
#include "hw/sysbus.h"
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "hw/irq.h"
@@ -59,9 +58,6 @@ typedef struct ETRAXTimerState {
qemu_irq irq;
qemu_irq nmi;
- QEMUBH *bh_t0;
- QEMUBH *bh_t1;
- QEMUBH *bh_wd;
ptimer_state *ptimer_t0;
ptimer_state *ptimer_t1;
ptimer_state *ptimer_wd;
@@ -155,6 +151,7 @@ static void update_ctrl(ETRAXTimerState *t, int tnum)
}
D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
+ ptimer_transaction_begin(timer);
ptimer_set_freq(timer, freq_hz);
ptimer_set_limit(timer, div, 0);
@@ -176,6 +173,7 @@ static void update_ctrl(ETRAXTimerState *t, int tnum)
abort();
break;
}
+ ptimer_transaction_commit(timer);
}
static void timer_update_irq(ETRAXTimerState *t)
@@ -240,6 +238,7 @@ static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value)
t->wd_hits = 0;
+ ptimer_transaction_begin(t->ptimer_wd);
ptimer_set_freq(t->ptimer_wd, 760);
if (wd_cnt == 0)
wd_cnt = 256;
@@ -250,6 +249,7 @@ static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value)
ptimer_stop(t->ptimer_wd);
t->rw_wd_ctrl = value;
+ ptimer_transaction_commit(t->ptimer_wd);
}
static void
@@ -311,9 +311,15 @@ static void etraxfs_timer_reset(void *opaque)
{
ETRAXTimerState *t = opaque;
+ ptimer_transaction_begin(t->ptimer_t0);
ptimer_stop(t->ptimer_t0);
+ ptimer_transaction_commit(t->ptimer_t0);
+ ptimer_transaction_begin(t->ptimer_t1);
ptimer_stop(t->ptimer_t1);
+ ptimer_transaction_commit(t->ptimer_t1);
+ ptimer_transaction_begin(t->ptimer_wd);
ptimer_stop(t->ptimer_wd);
+ ptimer_transaction_commit(t->ptimer_wd);
t->rw_wd_ctrl = 0;
t->r_intr = 0;
t->rw_intr_mask = 0;
@@ -325,12 +331,9 @@ static void etraxfs_timer_realize(DeviceState *dev, Error **errp)
ETRAXTimerState *t = ETRAX_TIMER(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- t->bh_t0 = qemu_bh_new(timer0_hit, t);
- t->bh_t1 = qemu_bh_new(timer1_hit, t);
- t->bh_wd = qemu_bh_new(watchdog_hit, t);
- t->ptimer_t0 = ptimer_init_with_bh(t->bh_t0, PTIMER_POLICY_DEFAULT);
- t->ptimer_t1 = ptimer_init_with_bh(t->bh_t1, PTIMER_POLICY_DEFAULT);
- t->ptimer_wd = ptimer_init_with_bh(t->bh_wd, PTIMER_POLICY_DEFAULT);
+ t->ptimer_t0 = ptimer_init(timer0_hit, t, PTIMER_POLICY_DEFAULT);
+ t->ptimer_t1 = ptimer_init(timer1_hit, t, PTIMER_POLICY_DEFAULT);
+ t->ptimer_wd = ptimer_init(watchdog_hit, t, PTIMER_POLICY_DEFAULT);
sysbus_init_irq(sbd, &t->irq);
sysbus_init_irq(sbd, &t->nmi);
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 7225758414..944120aea5 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -1254,7 +1254,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
/* Start FRC if transition from disabled to enabled */
if ((value & G_TCON_TIMER_ENABLE) > (old_val &
G_TCON_TIMER_ENABLE)) {
- exynos4210_gfrc_start(&s->g_timer);
+ exynos4210_gfrc_restart(s);
}
if ((value & G_TCON_TIMER_ENABLE) < (old_val &
G_TCON_TIMER_ENABLE)) {
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index bb09268ea1..7a9371c0e3 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -29,7 +29,6 @@
#include "hw/irq.h"
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "trace.h"
@@ -63,7 +62,6 @@ typedef struct GPTimer GPTimer;
typedef struct GPTimerUnit GPTimerUnit;
struct GPTimer {
- QEMUBH *bh;
struct ptimer_state *ptimer;
qemu_irq irq;
@@ -93,6 +91,17 @@ struct GPTimerUnit {
uint32_t config;
};
+static void grlib_gptimer_tx_begin(GPTimer *timer)
+{
+ ptimer_transaction_begin(timer->ptimer);
+}
+
+static void grlib_gptimer_tx_commit(GPTimer *timer)
+{
+ ptimer_transaction_commit(timer->ptimer);
+}
+
+/* Must be called within grlib_gptimer_tx_begin/commit block */
static void grlib_gptimer_enable(GPTimer *timer)
{
assert(timer != NULL);
@@ -115,6 +124,7 @@ static void grlib_gptimer_enable(GPTimer *timer)
ptimer_run(timer->ptimer, 1);
}
+/* Must be called within grlib_gptimer_tx_begin/commit block */
static void grlib_gptimer_restart(GPTimer *timer)
{
assert(timer != NULL);
@@ -141,7 +151,9 @@ static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler)
trace_grlib_gptimer_set_scaler(scaler, value);
for (i = 0; i < unit->nr_timers; i++) {
+ ptimer_transaction_begin(unit->timers[i].ptimer);
ptimer_set_freq(unit->timers[i].ptimer, value);
+ ptimer_transaction_commit(unit->timers[i].ptimer);
}
}
@@ -266,8 +278,10 @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
switch (timer_addr) {
case COUNTER_OFFSET:
trace_grlib_gptimer_writel(id, addr, value);
+ grlib_gptimer_tx_begin(&unit->timers[id]);
unit->timers[id].counter = value;
grlib_gptimer_enable(&unit->timers[id]);
+ grlib_gptimer_tx_commit(&unit->timers[id]);
return;
case COUNTER_RELOAD_OFFSET:
@@ -291,6 +305,7 @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
/* gptimer_restart calls gptimer_enable, so if "enable" and "load"
bits are present, we just have to call restart. */
+ grlib_gptimer_tx_begin(&unit->timers[id]);
if (value & GPTIMER_LOAD) {
grlib_gptimer_restart(&unit->timers[id]);
} else if (value & GPTIMER_ENABLE) {
@@ -301,6 +316,7 @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT);
unit->timers[id].config = value;
+ grlib_gptimer_tx_commit(&unit->timers[id]);
return;
default:
@@ -344,9 +360,11 @@ static void grlib_gptimer_reset(DeviceState *d)
timer->counter = 0;
timer->reload = 0;
timer->config = 0;
+ ptimer_transaction_begin(timer->ptimer);
ptimer_stop(timer->ptimer);
ptimer_set_count(timer->ptimer, 0);
ptimer_set_freq(timer->ptimer, unit->freq_hz);
+ ptimer_transaction_commit(timer->ptimer);
}
}
@@ -365,14 +383,16 @@ static void grlib_gptimer_realize(DeviceState *dev, Error **errp)
GPTimer *timer = &unit->timers[i];
timer->unit = unit;
- timer->bh = qemu_bh_new(grlib_gptimer_hit, timer);
- timer->ptimer = ptimer_init_with_bh(timer->bh, PTIMER_POLICY_DEFAULT);
+ timer->ptimer = ptimer_init(grlib_gptimer_hit, timer,
+ PTIMER_POLICY_DEFAULT);
timer->id = i;
/* One IRQ line for each timer */
sysbus_init_irq(sbd, &timer->irq);
+ ptimer_transaction_begin(timer->ptimer);
ptimer_set_freq(timer->ptimer, unit->freq_hz);
+ ptimer_transaction_commit(timer->ptimer);
}
memory_region_init_io(&unit->iomem, OBJECT(unit), &grlib_gptimer_ops,
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 1ddae4e7d7..9f17aaa278 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -33,7 +33,8 @@
#include "qemu/timer.h"
#include "hw/timer/hpet.h"
#include "hw/sysbus.h"
-#include "hw/timer/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "hw/rtc/mc146818rtc_regs.h"
#include "migration/vmstate.h"
#include "hw/timer/i8254.h"
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index fabde760b2..3fdecd09fe 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -30,7 +30,6 @@
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#define DEFAULT_FREQUENCY (50*1000000)
@@ -63,7 +62,6 @@ struct LM32TimerState {
MemoryRegion iomem;
- QEMUBH *bh;
ptimer_state *ptimer;
qemu_irq irq;
@@ -119,6 +117,7 @@ static void timer_write(void *opaque, hwaddr addr,
s->regs[R_SR] &= ~SR_TO;
break;
case R_CR:
+ ptimer_transaction_begin(s->ptimer);
s->regs[R_CR] = value;
if (s->regs[R_CR] & CR_START) {
ptimer_run(s->ptimer, 1);
@@ -126,10 +125,13 @@ static void timer_write(void *opaque, hwaddr addr,
if (s->regs[R_CR] & CR_STOP) {
ptimer_stop(s->ptimer);
}
+ ptimer_transaction_commit(s->ptimer);
break;
case R_PERIOD:
s->regs[R_PERIOD] = value;
+ ptimer_transaction_begin(s->ptimer);
ptimer_set_count(s->ptimer, value);
+ ptimer_transaction_commit(s->ptimer);
break;
case R_SNAPSHOT:
error_report("lm32_timer: write access to read only register 0x"
@@ -176,7 +178,9 @@ static void timer_reset(DeviceState *d)
for (i = 0; i < R_MAX; i++) {
s->regs[i] = 0;
}
+ ptimer_transaction_begin(s->ptimer);
ptimer_stop(s->ptimer);
+ ptimer_transaction_commit(s->ptimer);
}
static void lm32_timer_init(Object *obj)
@@ -195,10 +199,11 @@ static void lm32_timer_realize(DeviceState *dev, Error **errp)
{
LM32TimerState *s = LM32_TIMER(dev);
- s->bh = qemu_bh_new(timer_hit, s);
- s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT);
+ s->ptimer = ptimer_init(timer_hit, s, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(s->ptimer);
ptimer_set_freq(s->ptimer, s->freq_hz);
+ ptimer_transaction_commit(s->ptimer);
}
static const VMStateDescription vmstate_lm32_timer = {
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 5193c03850..7a62e212c3 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -31,7 +31,6 @@
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
enum {
@@ -71,8 +70,6 @@ struct MilkymistSysctlState {
MemoryRegion regs_region;
- QEMUBH *bh0;
- QEMUBH *bh1;
ptimer_state *ptimer0;
ptimer_state *ptimer1;
@@ -161,14 +158,19 @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
s->regs[addr] = value;
break;
case R_TIMER0_COMPARE:
+ ptimer_transaction_begin(s->ptimer0);
ptimer_set_limit(s->ptimer0, value, 0);
s->regs[addr] = value;
+ ptimer_transaction_commit(s->ptimer0);
break;
case R_TIMER1_COMPARE:
+ ptimer_transaction_begin(s->ptimer1);
ptimer_set_limit(s->ptimer1, value, 0);
s->regs[addr] = value;
+ ptimer_transaction_commit(s->ptimer1);
break;
case R_TIMER0_CONTROL:
+ ptimer_transaction_begin(s->ptimer0);
s->regs[addr] = value;
if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
trace_milkymist_sysctl_start_timer0();
@@ -179,8 +181,10 @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
trace_milkymist_sysctl_stop_timer0();
ptimer_stop(s->ptimer0);
}
+ ptimer_transaction_commit(s->ptimer0);
break;
case R_TIMER1_CONTROL:
+ ptimer_transaction_begin(s->ptimer1);
s->regs[addr] = value;
if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
trace_milkymist_sysctl_start_timer1();
@@ -191,6 +195,7 @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
trace_milkymist_sysctl_stop_timer1();
ptimer_stop(s->ptimer1);
}
+ ptimer_transaction_commit(s->ptimer1);
break;
case R_ICAP:
sysctl_icap_write(s, value);
@@ -263,8 +268,12 @@ static void milkymist_sysctl_reset(DeviceState *d)
s->regs[i] = 0;
}
+ ptimer_transaction_begin(s->ptimer0);
ptimer_stop(s->ptimer0);
+ ptimer_transaction_commit(s->ptimer0);
+ ptimer_transaction_begin(s->ptimer1);
ptimer_stop(s->ptimer1);
+ ptimer_transaction_commit(s->ptimer1);
/* defaults */
s->regs[R_ICAP] = ICAP_READY;
@@ -292,13 +301,15 @@ static void milkymist_sysctl_realize(DeviceState *dev, Error **errp)
{
MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev);
- s->bh0 = qemu_bh_new(timer0_hit, s);
- s->bh1 = qemu_bh_new(timer1_hit, s);
- s->ptimer0 = ptimer_init_with_bh(s->bh0, PTIMER_POLICY_DEFAULT);
- s->ptimer1 = ptimer_init_with_bh(s->bh1, PTIMER_POLICY_DEFAULT);
+ s->ptimer0 = ptimer_init(timer0_hit, s, PTIMER_POLICY_DEFAULT);
+ s->ptimer1 = ptimer_init(timer1_hit, s, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(s->ptimer0);
ptimer_set_freq(s->ptimer0, s->freq_hz);
+ ptimer_transaction_commit(s->ptimer0);
+ ptimer_transaction_begin(s->ptimer1);
ptimer_set_freq(s->ptimer1, s->freq_hz);
+ ptimer_transaction_commit(s->ptimer1);
}
static const VMStateDescription vmstate_milkymist_sysctl = {
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
index 0898da5ce9..697519593b 100644
--- a/hw/timer/puv3_ost.c
+++ b/hw/timer/puv3_ost.c
@@ -13,7 +13,6 @@
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/ptimer.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#undef DEBUG_PUV3
@@ -27,7 +26,6 @@ typedef struct PUV3OSTState {
SysBusDevice parent_obj;
MemoryRegion iomem;
- QEMUBH *bh;
qemu_irq irq;
ptimer_state *ptimer;
@@ -68,6 +66,7 @@ static void puv3_ost_write(void *opaque, hwaddr offset,
DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
switch (offset) {
case 0x00: /* Match Register 0 */
+ ptimer_transaction_begin(s->ptimer);
s->reg_OSMR0 = value;
if (s->reg_OSMR0 > s->reg_OSCR) {
ptimer_set_count(s->ptimer, s->reg_OSMR0 - s->reg_OSCR);
@@ -76,6 +75,7 @@ static void puv3_ost_write(void *opaque, hwaddr offset,
(0xffffffff - s->reg_OSCR));
}
ptimer_run(s->ptimer, 2);
+ ptimer_transaction_commit(s->ptimer);
break;
case 0x14: /* Status Register */
assert(value == 0);
@@ -128,9 +128,10 @@ static void puv3_ost_realize(DeviceState *dev, Error **errp)
sysbus_init_irq(sbd, &s->irq);
- s->bh = qemu_bh_new(puv3_ost_tick, s);
- s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT);
+ s->ptimer = ptimer_init(puv3_ost_tick, s, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(s->ptimer);
ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
+ ptimer_transaction_commit(s->ptimer);
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
PUV3_REGS_OFFSET);
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index 48a81b4dc7..13c4051808 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -13,7 +13,6 @@
#include "hw/irq.h"
#include "hw/sh4/sh.h"
#include "qemu/timer.h"
-#include "qemu/main-loop.h"
#include "hw/ptimer.h"
//#define DEBUG_TIMER
@@ -91,13 +90,18 @@ static void sh_timer_write(void *opaque, hwaddr offset,
switch (offset >> 2) {
case OFFSET_TCOR:
s->tcor = value;
+ ptimer_transaction_begin(s->timer);
ptimer_set_limit(s->timer, s->tcor, 0);
+ ptimer_transaction_commit(s->timer);
break;
case OFFSET_TCNT:
s->tcnt = value;
+ ptimer_transaction_begin(s->timer);
ptimer_set_count(s->timer, s->tcnt);
+ ptimer_transaction_commit(s->timer);
break;
case OFFSET_TCR:
+ ptimer_transaction_begin(s->timer);
if (s->enabled) {
/* Pause the timer if it is running. This may cause some
inaccuracy dure to rounding, but avoids a whole lot of other
@@ -148,6 +152,7 @@ static void sh_timer_write(void *opaque, hwaddr offset,
/* Restart the timer if still enabled. */
ptimer_run(s->timer, 0);
}
+ ptimer_transaction_commit(s->timer);
break;
case OFFSET_TCPR:
if (s->feat & TIMER_FEAT_CAPT) {
@@ -168,12 +173,14 @@ static void sh_timer_start_stop(void *opaque, int enable)
printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
#endif
+ ptimer_transaction_begin(s->timer);
if (s->enabled && !enable) {
ptimer_stop(s->timer);
}
if (!s->enabled && enable) {
ptimer_run(s->timer, 0);
}
+ ptimer_transaction_commit(s->timer);
s->enabled = !!enable;
#ifdef DEBUG_TIMER
@@ -191,7 +198,6 @@ static void sh_timer_tick(void *opaque)
static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
{
sh_timer_state *s;
- QEMUBH *bh;
s = (sh_timer_state *)g_malloc0(sizeof(sh_timer_state));
s->freq = freq;
@@ -203,8 +209,7 @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
s->enabled = 0;
s->irq = irq;
- bh = qemu_bh_new(sh_timer_tick, s);
- s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+ s->timer = ptimer_init(sh_timer_tick, s, PTIMER_POLICY_DEFAULT);
sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor);
sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt);
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 692d213897..c55e8d0bf4 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -30,7 +30,6 @@
#include "hw/sysbus.h"
#include "migration/vmstate.h"
#include "trace.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
/*
@@ -213,6 +212,7 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
saddr = addr >> 2;
switch (saddr) {
case TIMER_LIMIT:
+ ptimer_transaction_begin(t->timer);
if (slavio_timer_is_user(tc)) {
uint64_t count;
@@ -227,15 +227,14 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
// set limit, reset counter
qemu_irq_lower(t->irq);
t->limit = val & TIMER_MAX_COUNT32;
- if (t->timer) {
- if (t->limit == 0) { /* free-run */
- ptimer_set_limit(t->timer,
- LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
- } else {
- ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
- }
+ if (t->limit == 0) { /* free-run */
+ ptimer_set_limit(t->timer,
+ LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
+ } else {
+ ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
}
}
+ ptimer_transaction_commit(t->timer);
break;
case TIMER_COUNTER:
if (slavio_timer_is_user(tc)) {
@@ -247,7 +246,9 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
t->reached = 0;
count = ((uint64_t)t->counthigh) << 32 | t->count;
trace_slavio_timer_mem_writel_limit(timer_index, count);
+ ptimer_transaction_begin(t->timer);
ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
+ ptimer_transaction_commit(t->timer);
} else {
trace_slavio_timer_mem_writel_counter_invalid();
}
@@ -255,13 +256,16 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
case TIMER_COUNTER_NORST:
// set limit without resetting counter
t->limit = val & TIMER_MAX_COUNT32;
+ ptimer_transaction_begin(t->timer);
if (t->limit == 0) { /* free-run */
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
} else {
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
}
+ ptimer_transaction_commit(t->timer);
break;
case TIMER_STATUS:
+ ptimer_transaction_begin(t->timer);
if (slavio_timer_is_user(tc)) {
// start/stop user counter
if (val & 1) {
@@ -273,6 +277,7 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
}
}
t->run = val & 1;
+ ptimer_transaction_commit(t->timer);
break;
case TIMER_MODE:
if (timer_index == 0) {
@@ -282,6 +287,7 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
unsigned int processor = 1 << i;
CPUTimerState *curr_timer = &s->cputimer[i + 1];
+ ptimer_transaction_begin(curr_timer->timer);
// check for a change in timer mode for this processor
if ((val & processor) != (s->cputimer_mode & processor)) {
if (val & processor) { // counter -> user timer
@@ -308,6 +314,7 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
trace_slavio_timer_mem_writel_mode_counter(timer_index);
}
}
+ ptimer_transaction_commit(curr_timer->timer);
}
} else {
trace_slavio_timer_mem_writel_mode_invalid();
@@ -367,10 +374,12 @@ static void slavio_timer_reset(DeviceState *d)
curr_timer->count = 0;
curr_timer->reached = 0;
if (i <= s->num_cpus) {
+ ptimer_transaction_begin(curr_timer->timer);
ptimer_set_limit(curr_timer->timer,
LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
ptimer_run(curr_timer->timer, 0);
curr_timer->run = 1;
+ ptimer_transaction_commit(curr_timer->timer);
}
}
s->cputimer_mode = 0;
@@ -380,7 +389,6 @@ static void slavio_timer_init(Object *obj)
{
SLAVIO_TIMERState *s = SLAVIO_TIMER(obj);
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- QEMUBH *bh;
unsigned int i;
TimerContext *tc;
@@ -392,9 +400,11 @@ static void slavio_timer_init(Object *obj)
tc->s = s;
tc->timer_index = i;
- bh = qemu_bh_new(slavio_timer_irq, tc);
- s->cputimer[i].timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+ s->cputimer[i].timer = ptimer_init(slavio_timer_irq, tc,
+ PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(s->cputimer[i].timer);
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
+ ptimer_transaction_commit(s->cputimer[i].timer);
size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index db02a9142c..29fda7870e 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -66,24 +66,11 @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A
cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
-# hw/timer/aspeed-rtc.c
-aspeed_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
-aspeed_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
-
-# sun4v-rtc.c
-sun4v_rtc_read(uint64_t addr, uint64_t value) "read: addr 0x%" PRIx64 " value 0x%" PRIx64
-sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value 0x%" PRIx64
-
-# xlnx-zynqmp-rtc.c
-xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
-
# nrf51_timer.c
nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
-# pl031.c
-pl031_irq_state(int level) "irq state %d"
-pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
-pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
-pl031_alarm_raised(void) "alarm raised"
-pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
+# bcm2835_systmr.c
+bcm2835_systmr_irq(bool enable) "timer irq state %u"
+bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
+bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 92dbff304d..7191ea54f5 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -28,7 +28,6 @@
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
#include "qemu/log.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#define D(x)
@@ -52,7 +51,6 @@
struct xlx_timer
{
- QEMUBH *bh;
ptimer_state *ptimer;
void *parent;
int nr; /* for debug. */
@@ -134,6 +132,7 @@ timer_read(void *opaque, hwaddr addr, unsigned int size)
return r;
}
+/* Must be called inside ptimer transaction block */
static void timer_enable(struct xlx_timer *xt)
{
uint64_t count;
@@ -174,8 +173,11 @@ timer_write(void *opaque, hwaddr addr,
value &= ~TCSR_TINT;
xt->regs[addr] = value & 0x7ff;
- if (value & TCSR_ENT)
+ if (value & TCSR_ENT) {
+ ptimer_transaction_begin(xt->ptimer);
timer_enable(xt);
+ ptimer_transaction_commit(xt->ptimer);
+ }
break;
default:
@@ -220,9 +222,10 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
xt->parent = t;
xt->nr = i;
- xt->bh = qemu_bh_new(timer_hit, xt);
- xt->ptimer = ptimer_init_with_bh(xt->bh, PTIMER_POLICY_DEFAULT);
+ xt->ptimer = ptimer_init(timer_hit, xt, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(xt->ptimer);
ptimer_set_freq(xt->ptimer, t->freq_hz);
+ ptimer_transaction_commit(xt->ptimer);
}
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
diff --git a/hw/xtensa/Kconfig b/hw/xtensa/Kconfig
index d72817d012..0740657ea5 100644
--- a/hw/xtensa/Kconfig
+++ b/hw/xtensa/Kconfig
@@ -1,6 +1,12 @@
config XTENSA_SIM
bool
+config XTENSA_VIRT
+ bool
+ select XTENSA_SIM
+ select PCI_EXPRESS_GENERIC_BRIDGE
+ select PCI_DEVICES
+
config XTENSA_XTFPGA
bool
select OPENCORES_ETH
diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs
index 0bbfccd6de..2b40e1b60a 100644
--- a/hw/xtensa/Makefile.objs
+++ b/hw/xtensa/Makefile.objs
@@ -2,4 +2,5 @@ obj-y += mx_pic.o
obj-y += pic_cpu.o
obj-y += xtensa_memory.o
obj-$(CONFIG_XTENSA_SIM) += sim.o
+obj-$(CONFIG_XTENSA_VIRT) += virt.o
obj-$(CONFIG_XTENSA_XTFPGA) += xtfpga.o
diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c
index 981dbb7bbe..a22743a3d6 100644
--- a/hw/xtensa/sim.c
+++ b/hw/xtensa/sim.c
@@ -37,6 +37,7 @@
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
#include "xtensa_memory.h"
+#include "xtensa_sim.h"
static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
{
@@ -52,12 +53,11 @@ static void sim_reset(void *opaque)
cpu_reset(CPU(cpu));
}
-static void xtensa_sim_init(MachineState *machine)
+XtensaCPU *xtensa_sim_common_init(MachineState *machine)
{
XtensaCPU *cpu = NULL;
CPUXtensaState *env = NULL;
ram_addr_t ram_size = machine->ram_size;
- const char *kernel_filename = machine->kernel_filename;
int n;
for (n = 0; n < machine->smp.cpus; n++) {
@@ -89,30 +89,41 @@ static void xtensa_sim_init(MachineState *machine)
xtensa_create_memory_regions(&sysram, "xtensa.sysram",
get_system_memory());
}
-
if (serial_hd(0)) {
xtensa_sim_open_console(serial_hd(0));
}
- if (kernel_filename) {
- uint64_t elf_entry;
- uint64_t elf_lowaddr;
+ return cpu;
+}
+
+void xtensa_sim_load_kernel(XtensaCPU *cpu, MachineState *machine)
+{
+ const char *kernel_filename = machine->kernel_filename;
#ifdef TARGET_WORDS_BIGENDIAN
- int success = load_elf(kernel_filename, NULL,
- translate_phys_addr, cpu,
- &elf_entry, &elf_lowaddr,
- NULL, 1, EM_XTENSA, 0, 0);
+ int big_endian = true;
#else
- int success = load_elf(kernel_filename, NULL,
- translate_phys_addr, cpu,
- &elf_entry, &elf_lowaddr,
- NULL, 0, EM_XTENSA, 0, 0);
+ int big_endian = false;
#endif
+
+ if (kernel_filename) {
+ uint64_t elf_entry;
+ uint64_t elf_lowaddr;
+ int success = load_elf(kernel_filename, NULL, translate_phys_addr, cpu,
+ &elf_entry, &elf_lowaddr, NULL, big_endian,
+ EM_XTENSA, 0, 0);
+
if (success > 0) {
- env->pc = elf_entry;
+ cpu->env.pc = elf_entry;
}
}
}
+static void xtensa_sim_init(MachineState *machine)
+{
+ XtensaCPU *cpu = xtensa_sim_common_init(machine);
+
+ xtensa_sim_load_kernel(cpu, machine);
+}
+
static void xtensa_sim_machine_init(MachineClass *mc)
{
mc->desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")";
diff --git a/hw/xtensa/virt.c b/hw/xtensa/virt.c
new file mode 100644
index 0000000000..b22dcf938a
--- /dev/null
+++ b/hw/xtensa/virt.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2019, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "sysemu/reset.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/pci-host/gpex.h"
+#include "net/net.h"
+#include "elf.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h"
+#include "xtensa_memory.h"
+#include "xtensa_sim.h"
+
+static void create_pcie(CPUXtensaState *env, int irq_base, hwaddr addr_base)
+{
+ hwaddr base_ecam = addr_base + 0x00100000;
+ hwaddr size_ecam = 0x03f00000;
+ hwaddr base_pio = addr_base + 0x00000000;
+ hwaddr size_pio = 0x00010000;
+ hwaddr base_mmio = addr_base + 0x04000000;
+ hwaddr size_mmio = 0x08000000;
+
+ MemoryRegion *ecam_alias;
+ MemoryRegion *ecam_reg;
+ MemoryRegion *pio_alias;
+ MemoryRegion *pio_reg;
+ MemoryRegion *mmio_alias;
+ MemoryRegion *mmio_reg;
+
+ DeviceState *dev;
+ PCIHostState *pci;
+ qemu_irq *extints;
+ int i;
+
+ dev = qdev_create(NULL, TYPE_GPEX_HOST);
+ qdev_init_nofail(dev);
+
+ /* Map only the first size_ecam bytes of ECAM space. */
+ ecam_alias = g_new0(MemoryRegion, 1);
+ ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+ memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
+ ecam_reg, 0, size_ecam);
+ memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias);
+
+ /*
+ * Map the MMIO window into system address space so as to expose
+ * the section of PCI MMIO space which starts at the same base address
+ * (ie 1:1 mapping for that part of PCI MMIO space visible through
+ * the window).
+ */
+ mmio_alias = g_new0(MemoryRegion, 1);
+ mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
+ memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
+ mmio_reg, base_mmio, size_mmio);
+ memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias);
+
+ /* Map IO port space. */
+ pio_alias = g_new0(MemoryRegion, 1);
+ pio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 2);
+ memory_region_init_alias(pio_alias, OBJECT(dev), "pcie-pio",
+ pio_reg, 0, size_pio);
+ memory_region_add_subregion(get_system_memory(), base_pio, pio_alias);
+
+ /* Connect IRQ lines. */
+ extints = xtensa_get_extints(env);
+
+ for (i = 0; i < GPEX_NUM_IRQS; i++) {
+ void *q = extints[irq_base + i];
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, q);
+ gpex_set_irq_num(GPEX_HOST(dev), i, irq_base + i);
+ }
+
+ pci = PCI_HOST_BRIDGE(dev);
+ if (pci->bus) {
+ for (i = 0; i < nb_nics; i++) {
+ NICInfo *nd = &nd_table[i];
+
+ if (!nd->model) {
+ nd->model = g_strdup("virtio");
+ }
+
+ pci_nic_init_nofail(nd, pci->bus, nd->model, NULL);
+ }
+ }
+}
+
+static void xtensa_virt_init(MachineState *machine)
+{
+ XtensaCPU *cpu = xtensa_sim_common_init(machine);
+ CPUXtensaState *env = &cpu->env;
+
+ create_pcie(env, 0, 0xf0000000);
+ xtensa_sim_load_kernel(cpu, machine);
+}
+
+static void xtensa_virt_machine_init(MachineClass *mc)
+{
+ mc->desc = "virt machine (" XTENSA_DEFAULT_CPU_MODEL ")";
+ mc->init = xtensa_virt_init;
+ mc->max_cpus = 32;
+ mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
+}
+
+DEFINE_MACHINE("virt", xtensa_virt_machine_init)
diff --git a/hw/xtensa/xtensa_sim.h b/hw/xtensa/xtensa_sim.h
new file mode 100644
index 0000000000..bdc92f3d2c
--- /dev/null
+++ b/hw/xtensa/xtensa_sim.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef XTENSA_SIM_H
+#define XTENSA_SIM_H
+
+XtensaCPU *xtensa_sim_common_init(MachineState *machine);
+void xtensa_sim_load_kernel(XtensaCPU *cpu, MachineState *machine);
+
+#endif