diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm/aspeed.c | 98 | ||||
-rw-r--r-- | hw/arm/aspeed_ast2600.c | 9 | ||||
-rw-r--r-- | hw/misc/aspeed_sbc.c | 141 | ||||
-rw-r--r-- | hw/misc/aspeed_sdmc.c | 2 | ||||
-rw-r--r-- | hw/misc/meson.build | 1 | ||||
-rw-r--r-- | hw/misc/trace-events | 4 | ||||
-rw-r--r-- | hw/openrisc/meson.build | 2 | ||||
-rw-r--r-- | hw/openrisc/openrisc_sim.c | 308 | ||||
-rw-r--r-- | hw/ppc/spapr_rtc.c | 6 | ||||
-rw-r--r-- | hw/rtc/mc146818rtc.c | 5 | ||||
-rw-r--r-- | hw/rtc/meson.build | 2 | ||||
-rw-r--r-- | hw/rtc/pl031.c | 5 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 3 | ||||
-rw-r--r-- | hw/ssi/aspeed_smc.c | 11 |
14 files changed, 494 insertions, 103 deletions
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index d911dc9..11558b3 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -106,17 +106,6 @@ struct AspeedMachineState { SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \ SCU_AST2500_HW_STRAP_RESERVED1) -/* Swift hardware value: 0xF11AD206 */ -#define SWIFT_BMC_HW_STRAP1 ( \ - AST2500_HW_STRAP1_DEFAULTS | \ - SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \ - SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \ - SCU_AST2500_HW_STRAP_UART_DEBUG | \ - SCU_AST2500_HW_STRAP_DDR4_ENABLE | \ - SCU_H_PLL_BYPASS_EN | \ - SCU_AST2500_HW_STRAP_ACPI_ENABLE | \ - SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER)) - #define G220A_BMC_HW_STRAP1 ( \ SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \ SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \ @@ -171,8 +160,8 @@ struct AspeedMachineState { #define TACOMA_BMC_HW_STRAP2 0x00000040 /* Rainier hardware value: (QEMU prototype) */ -#define RAINIER_BMC_HW_STRAP1 0x00000000 -#define RAINIER_BMC_HW_STRAP2 0x00000000 +#define RAINIER_BMC_HW_STRAP1 0x00422016 +#define RAINIER_BMC_HW_STRAP2 0x80000848 /* Fuji hardware value */ #define FUJI_BMC_HW_STRAP1 0x00000000 @@ -544,33 +533,10 @@ static void romulus_bmc_i2c_init(AspeedMachineState *bmc) i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32); } -static void swift_bmc_i2c_init(AspeedMachineState *bmc) +static void create_pca9552(AspeedSoCState *soc, int bus_id, int addr) { - AspeedSoCState *soc = &bmc->soc; - - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "pca9552", 0x60); - - /* The swift board expects a TMP275 but a TMP105 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "tmp105", 0x48); - /* The swift board expects a pca9551 but a pca9552 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x60); - - /* The swift board expects an Epson RX8900 RTC but a ds1338 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "ds1338", 0x32); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x60); - - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c); - /* The swift board expects a pca9539 but a pca9552 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "pca9552", 0x74); - - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c); - /* The swift board expects a pca9539 but a pca9552 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "pca9552", - 0x74); - - /* The swift board expects a TMP275 but a TMP105 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 12), "tmp105", 0x48); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 12), "tmp105", 0x4a); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, bus_id), + TYPE_PCA9552, addr); } static void sonorapass_bmc_i2c_init(AspeedMachineState *bmc) @@ -589,9 +555,9 @@ static void sonorapass_bmc_i2c_init(AspeedMachineState *bmc) smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 4), 0x54, eeprom4_54); /* PCA9539 @ 0x76, but PCA9552 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "pca9552", 0x76); + create_pca9552(soc, 4, 0x76); /* PCA9539 @ 0x77, but PCA9552 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "pca9552", 0x77); + create_pca9552(soc, 4, 0x77); /* bus 6 : */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp105", 0x48); @@ -602,8 +568,8 @@ static void sonorapass_bmc_i2c_init(AspeedMachineState *bmc) uint8_t *eeprom8_56 = g_malloc0(8 * 1024); smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 8), 0x56, eeprom8_56); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x60); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x61); + create_pca9552(soc, 8, 0x60); + create_pca9552(soc, 8, 0x61); /* bus 8 : adc128d818 @ 0x1d */ /* bus 8 : adc128d818 @ 0x1f */ @@ -741,8 +707,7 @@ static void fp5280g2_bmc_i2c_init(AspeedMachineState *bmc) i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "ds1338", 0x68); /* It expects a pca9555 but a pca9552 is compatible */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_PCA9552, - 0x20); + create_pca9552(soc, 8, 0x30); } static void rainier_bmc_i2c_init(AspeedMachineState *bmc) @@ -752,6 +717,8 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 0), 0x51, 32 * KiB); + create_pca9552(soc, 3, 0x61); + /* The rainier expects a TMP275 but a TMP105 is compatible */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105, 0x48); @@ -764,11 +731,14 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 0), 0x50, 64 * KiB); aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x51, 64 * KiB); aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 2), 0x52, 64 * KiB); + create_pca9552(soc, 4, 0x60); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), TYPE_TMP105, 0x48); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), TYPE_TMP105, 0x49); + create_pca9552(soc, 5, 0x60); + create_pca9552(soc, 5, 0x61); i2c_mux = i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), "pca9546", 0x70); aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 0), 0x50, 64 * KiB); @@ -787,8 +757,13 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 2), 0x50, 64 * KiB); aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 3), 0x51, 64 * KiB); + create_pca9552(soc, 7, 0x30); + create_pca9552(soc, 7, 0x31); + create_pca9552(soc, 7, 0x32); + create_pca9552(soc, 7, 0x33); /* Bus 7: TODO max31785@52 */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x61); + create_pca9552(soc, 7, 0x60); + create_pca9552(soc, 7, 0x61); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "dps310", 0x76); /* Bus 7: TODO si7021-a20@20 */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), TYPE_TMP105, @@ -802,7 +777,8 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) 0x4a); aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 8), 0x50, 64 * KiB); aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 64 * KiB); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x61); + create_pca9552(soc, 8, 0x60); + create_pca9552(soc, 8, 0x61); /* Bus 8: ucd90320@11 */ /* Bus 8: ucd90320@b */ /* Bus 8: ucd90320@c */ @@ -823,13 +799,17 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) "pca9546", 0x70); aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 0), 0x50, 64 * KiB); aspeed_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x51, 64 * KiB); + create_pca9552(soc, 11, 0x60); aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 13), 0x50, 64 * KiB); + create_pca9552(soc, 13, 0x60); aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 14), 0x50, 64 * KiB); + create_pca9552(soc, 14, 0x60); aspeed_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 15), 0x50, 64 * KiB); + create_pca9552(soc, 15, 0x60); } static void get_pca9548_channels(I2CBus *bus, uint8_t mux_addr, @@ -1102,26 +1082,6 @@ static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data) aspeed_soc_num_cpus(amc->soc_name); }; -static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); - - mc->desc = "OpenPOWER Swift BMC (ARM1176)"; - amc->soc_name = "ast2500-a1"; - amc->hw_strap1 = SWIFT_BMC_HW_STRAP1; - amc->fmc_model = "mx66l1g45g"; - amc->spi_model = "mx66l1g45g"; - amc->num_cs = 2; - amc->i2c_init = swift_bmc_i2c_init; - mc->default_ram_size = 512 * MiB; - mc->default_cpus = mc->min_cpus = mc->max_cpus = - aspeed_soc_num_cpus(amc->soc_name); - - mc->deprecation_reason = "redundant system. Please use a similar " - "OpenPOWER BMC, Witherspoon or Romulus."; -}; - static void aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1278,10 +1238,6 @@ static const TypeInfo aspeed_machine_types[] = { .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_romulus_class_init, }, { - .name = MACHINE_TYPE_NAME("swift-bmc"), - .parent = TYPE_ASPEED_MACHINE, - .class_init = aspeed_machine_swift_class_init, - }, { .name = MACHINE_TYPE_NAME("sonorapass-bmc"), .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_sonorapass_class_init, diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 12f6edc..21cd334 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -47,6 +47,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_XDMA] = 0x1E6E7000, [ASPEED_DEV_ADC] = 0x1E6E9000, [ASPEED_DEV_DP] = 0x1E6EB000, + [ASPEED_DEV_SBC] = 0x1E6F2000, [ASPEED_DEV_VIDEO] = 0x1E700000, [ASPEED_DEV_SDHCI] = 0x1E740000, [ASPEED_DEV_EMMC] = 0x1E750000, @@ -227,6 +228,8 @@ static void aspeed_soc_ast2600_init(Object *obj) object_initialize_child(obj, "hace", &s->hace, typename); object_initialize_child(obj, "i3c", &s->i3c, TYPE_ASPEED_I3C); + + object_initialize_child(obj, "sbc", &s->sbc, TYPE_ASPEED_SBC); } /* @@ -539,6 +542,12 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) /* The AST2600 I3C controller has one IRQ per bus. */ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i3c.devices[i]), 0, irq); } + + /* Secure Boot Controller */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->sbc), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sbc), 0, sc->memmap[ASPEED_DEV_SBC]); } static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) diff --git a/hw/misc/aspeed_sbc.c b/hw/misc/aspeed_sbc.c new file mode 100644 index 0000000..40f2a8c --- /dev/null +++ b/hw/misc/aspeed_sbc.c @@ -0,0 +1,141 @@ +/* + * ASPEED Secure Boot Controller + * + * Copyright (C) 2021-2022 IBM Corp. + * + * Joel Stanley <joel@jms.id.au> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_sbc.h" +#include "qapi/error.h" +#include "migration/vmstate.h" + +#define R_PROT (0x000 / 4) +#define R_STATUS (0x014 / 4) + +static uint64_t aspeed_sbc_read(void *opaque, hwaddr addr, unsigned int size) +{ + AspeedSBCState *s = ASPEED_SBC(opaque); + + addr >>= 2; + + if (addr >= ASPEED_SBC_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", + __func__, addr << 2); + return 0; + } + + return s->regs[addr]; +} + +static void aspeed_sbc_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) +{ + AspeedSBCState *s = ASPEED_SBC(opaque); + + addr >>= 2; + + if (addr >= ASPEED_SBC_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", + __func__, addr << 2); + return; + } + + switch (addr) { + case R_STATUS: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to read only register 0x%" HWADDR_PRIx "\n", + __func__, addr << 2); + return; + default: + break; + } + + s->regs[addr] = data; +} + +static const MemoryRegionOps aspeed_sbc_ops = { + .read = aspeed_sbc_read, + .write = aspeed_sbc_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static void aspeed_sbc_reset(DeviceState *dev) +{ + struct AspeedSBCState *s = ASPEED_SBC(dev); + + memset(s->regs, 0, sizeof(s->regs)); + + /* Set secure boot enabled, and boot from emmc/spi */ + s->regs[R_STATUS] = 1 << 6 | 1 << 5; +} + +static void aspeed_sbc_realize(DeviceState *dev, Error **errp) +{ + AspeedSBCState *s = ASPEED_SBC(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sbc_ops, s, + TYPE_ASPEED_SBC, 0x1000); + + sysbus_init_mmio(sbd, &s->iomem); +} + +static const VMStateDescription vmstate_aspeed_sbc = { + .name = TYPE_ASPEED_SBC, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, AspeedSBCState, ASPEED_SBC_NR_REGS), + VMSTATE_END_OF_LIST(), + } +}; + +static void aspeed_sbc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = aspeed_sbc_realize; + dc->reset = aspeed_sbc_reset; + dc->vmsd = &vmstate_aspeed_sbc; +} + +static const TypeInfo aspeed_sbc_info = { + .name = TYPE_ASPEED_SBC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedSBCState), + .class_init = aspeed_sbc_class_init, + .class_size = sizeof(AspeedSBCClass) +}; + +static void aspeed_ast2600_sbc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "AST2600 Secure Boot Controller"; +} + +static const TypeInfo aspeed_ast2600_sbc_info = { + .name = TYPE_ASPEED_AST2600_SBC, + .parent = TYPE_ASPEED_SBC, + .class_init = aspeed_ast2600_sbc_class_init, +}; + +static void aspeed_sbc_register_types(void) +{ + type_register_static(&aspeed_ast2600_sbc_info); + type_register_static(&aspeed_sbc_info); +} + +type_init(aspeed_sbc_register_types); diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index 08f856c..d2a3931 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -130,6 +130,7 @@ static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size) return 0; } + trace_aspeed_sdmc_read(addr, s->regs[addr]); return s->regs[addr]; } @@ -148,6 +149,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, return; } + trace_aspeed_sdmc_write(addr, data); asc->write(s, addr, data); } diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 6dcbe04..6455853 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -111,6 +111,7 @@ softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( 'aspeed_i3c.c', 'aspeed_lpc.c', 'aspeed_scu.c', + 'aspeed_sbc.c', 'aspeed_sdmc.c', 'aspeed_xdma.c')) diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 1c373dd..fb5a389 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -205,6 +205,10 @@ aspeed_i3c_write(uint64_t offset, uint64_t data) "I3C write: offset 0x%" PRIx64 aspeed_i3c_device_read(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] read: offset 0x%" PRIx64 " data 0x%" PRIx64 aspeed_i3c_device_write(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] write: offset 0x%" PRIx64 " data 0x%" PRIx64 +# aspeed_sdmc.c +aspeed_sdmc_write(uint64_t reg, uint64_t data) "reg @0x%" PRIx64 " data: 0x%" PRIx64 +aspeed_sdmc_read(uint64_t reg, uint64_t data) "reg @0x%" PRIx64 " data: 0x%" PRIx64 + # bcm2835_property.c bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu" diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build index 947f63e..ec48172 100644 --- a/hw/openrisc/meson.build +++ b/hw/openrisc/meson.build @@ -1,5 +1,5 @@ openrisc_ss = ss.source_set() openrisc_ss.add(files('cputimer.c')) -openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: files('openrisc_sim.c')) +openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), fdt]) hw_arch += {'openrisc': openrisc_ss} diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c index 73fe383..8184caa 100644 --- a/hw/openrisc/openrisc_sim.c +++ b/hw/openrisc/openrisc_sim.c @@ -29,16 +29,61 @@ #include "net/net.h" #include "hw/loader.h" #include "hw/qdev-properties.h" +#include "exec/address-spaces.h" +#include "sysemu/device_tree.h" #include "sysemu/sysemu.h" #include "hw/sysbus.h" #include "sysemu/qtest.h" #include "sysemu/reset.h" #include "hw/core/split-irq.h" +#include <libfdt.h> + #define KERNEL_LOAD_ADDR 0x100 +#define OR1KSIM_CPUS_MAX 4 +#define OR1KSIM_CLK_MHZ 20000000 + +#define TYPE_OR1KSIM_MACHINE MACHINE_TYPE_NAME("or1k-sim") +#define OR1KSIM_MACHINE(obj) \ + OBJECT_CHECK(Or1ksimState, (obj), TYPE_OR1KSIM_MACHINE) + +typedef struct Or1ksimState { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + void *fdt; + int fdt_size; + +} Or1ksimState; + +enum { + OR1KSIM_DRAM, + OR1KSIM_UART, + OR1KSIM_ETHOC, + OR1KSIM_OMPIC, +}; + +enum { + OR1KSIM_OMPIC_IRQ = 1, + OR1KSIM_UART_IRQ = 2, + OR1KSIM_ETHOC_IRQ = 4, +}; + +static const struct MemmapEntry { + hwaddr base; + hwaddr size; +} or1ksim_memmap[] = { + [OR1KSIM_DRAM] = { 0x00000000, 0 }, + [OR1KSIM_UART] = { 0x90000000, 0x100 }, + [OR1KSIM_ETHOC] = { 0x92000000, 0x800 }, + [OR1KSIM_OMPIC] = { 0x98000000, 16 }, +}; + static struct openrisc_boot_info { uint32_t bootstrap_pc; + uint32_t fdt_addr; } boot_info; static void main_cpu_reset(void *opaque) @@ -49,6 +94,7 @@ static void main_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); cpu_set_pc(cs, boot_info.bootstrap_pc); + cpu_set_gpr(&cpu->env, 3, boot_info.fdt_addr); } static qemu_irq get_cpu_irq(OpenRISCCPU *cpus[], int cpunum, int irq_pin) @@ -56,12 +102,77 @@ static qemu_irq get_cpu_irq(OpenRISCCPU *cpus[], int cpunum, int irq_pin) return qdev_get_gpio_in_named(DEVICE(cpus[cpunum]), "IRQ", irq_pin); } -static void openrisc_sim_net_init(hwaddr base, hwaddr descriptors, +static void openrisc_create_fdt(Or1ksimState *state, + const struct MemmapEntry *memmap, + int num_cpus, uint64_t mem_size, + const char *cmdline) +{ + void *fdt; + int cpu; + char *nodename; + int pic_ph; + + fdt = state->fdt = create_device_tree(&state->fdt_size); + if (!fdt) { + error_report("create_device_tree() failed"); + exit(1); + } + + qemu_fdt_setprop_string(fdt, "/", "compatible", "opencores,or1ksim"); + qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x1); + qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x1); + + nodename = g_strdup_printf("/memory@%" HWADDR_PRIx, + memmap[OR1KSIM_DRAM].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cells(fdt, nodename, "reg", + memmap[OR1KSIM_DRAM].base, mem_size); + qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory"); + g_free(nodename); + + qemu_fdt_add_subnode(fdt, "/cpus"); + qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); + qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); + + for (cpu = 0; cpu < num_cpus; cpu++) { + nodename = g_strdup_printf("/cpus/cpu@%d", cpu); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "opencores,or1200-rtlsvn481"); + qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", + OR1KSIM_CLK_MHZ); + g_free(nodename); + } + + nodename = (char *)"/pic"; + qemu_fdt_add_subnode(fdt, nodename); + pic_ph = qemu_fdt_alloc_phandle(fdt); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "opencores,or1k-pic-level"); + qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1); + qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", pic_ph); + + qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", pic_ph); + + qemu_fdt_add_subnode(fdt, "/chosen"); + if (cmdline) { + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); + } + + /* Create aliases node for use by devices. */ + qemu_fdt_add_subnode(fdt, "/aliases"); +} + +static void openrisc_sim_net_init(Or1ksimState *state, hwaddr base, hwaddr size, int num_cpus, OpenRISCCPU *cpus[], int irq_pin, NICInfo *nd) { + void *fdt = state->fdt; DeviceState *dev; SysBusDevice *s; + char *nodename; int i; dev = qdev_new("open_eth"); @@ -81,14 +192,28 @@ static void openrisc_sim_net_init(hwaddr base, hwaddr descriptors, sysbus_connect_irq(s, 0, get_cpu_irq(cpus, 0, irq_pin)); } sysbus_mmio_map(s, 0, base); - sysbus_mmio_map(s, 1, descriptors); + sysbus_mmio_map(s, 1, base + 0x400); + + /* Init device tree node for ethoc. */ + nodename = g_strdup_printf("/ethoc@%" HWADDR_PRIx, base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "opencores,ethoc"); + qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin); + qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0); + + qemu_fdt_setprop_string(fdt, "/aliases", "enet0", nodename); + g_free(nodename); } -static void openrisc_sim_ompic_init(hwaddr base, int num_cpus, +static void openrisc_sim_ompic_init(Or1ksimState *state, hwaddr base, + hwaddr size, int num_cpus, OpenRISCCPU *cpus[], int irq_pin) { + void *fdt = state->fdt; DeviceState *dev; SysBusDevice *s; + char *nodename; int i; dev = qdev_new("or1k-ompic"); @@ -100,28 +225,79 @@ static void openrisc_sim_ompic_init(hwaddr base, int num_cpus, sysbus_connect_irq(s, i, get_cpu_irq(cpus, i, irq_pin)); } sysbus_mmio_map(s, 0, base); + + /* Add device tree node for ompic. */ + nodename = g_strdup_printf("/ompic@%" HWADDR_PRIx, base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "openrisc,ompic"); + qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size); + qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 0); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin); + g_free(nodename); } -static void openrisc_load_kernel(ram_addr_t ram_size, - const char *kernel_filename) +static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base, + hwaddr size, int num_cpus, + OpenRISCCPU *cpus[], int irq_pin) +{ + void *fdt = state->fdt; + char *nodename; + qemu_irq serial_irq; + int i; + + if (num_cpus > 1) { + DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ); + qdev_prop_set_uint32(splitter, "num-lines", num_cpus); + qdev_realize_and_unref(splitter, NULL, &error_fatal); + for (i = 0; i < num_cpus; i++) { + qdev_connect_gpio_out(splitter, i, get_cpu_irq(cpus, i, irq_pin)); + } + serial_irq = qdev_get_gpio_in(splitter, 0); + } else { + serial_irq = get_cpu_irq(cpus, 0, irq_pin); + } + serial_mm_init(get_system_memory(), base, 0, serial_irq, 115200, + serial_hd(0), DEVICE_NATIVE_ENDIAN); + + /* Add device tree node for serial. */ + nodename = g_strdup_printf("/serial@%" HWADDR_PRIx, base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "ns16550a"); + qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", OR1KSIM_CLK_MHZ); + qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0); + + /* The /chosen node is created during fdt creation. */ + qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename); + qemu_fdt_setprop_string(fdt, "/aliases", "uart0", nodename); + g_free(nodename); +} + +static hwaddr openrisc_load_kernel(ram_addr_t ram_size, + const char *kernel_filename) { long kernel_size; uint64_t elf_entry; + uint64_t high_addr; hwaddr entry; if (kernel_filename && !qtest_enabled()) { kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, - &elf_entry, NULL, NULL, NULL, 1, EM_OPENRISC, - 1, 0); + &elf_entry, NULL, &high_addr, NULL, 1, + EM_OPENRISC, 1, 0); entry = elf_entry; if (kernel_size < 0) { kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL, NULL, NULL); + high_addr = entry + kernel_size; } if (kernel_size < 0) { kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR, ram_size - KERNEL_LOAD_ADDR); + high_addr = KERNEL_LOAD_ADDR + kernel_size; } if (entry <= 0) { @@ -133,20 +309,79 @@ static void openrisc_load_kernel(ram_addr_t ram_size, exit(1); } boot_info.bootstrap_pc = entry; + + return high_addr; } + return 0; +} + +static hwaddr openrisc_load_initrd(Or1ksimState *state, const char *filename, + hwaddr load_start, uint64_t mem_size) +{ + void *fdt = state->fdt; + int size; + hwaddr start; + + /* We put the initrd right after the kernel; page aligned. */ + start = TARGET_PAGE_ALIGN(load_start); + + size = load_ramdisk(filename, start, mem_size - start); + if (size < 0) { + size = load_image_targphys(filename, start, mem_size - start); + if (size < 0) { + error_report("could not load ramdisk '%s'", filename); + exit(1); + } + } + + qemu_fdt_setprop_cell(fdt, "/chosen", + "linux,initrd-start", start); + qemu_fdt_setprop_cell(fdt, "/chosen", + "linux,initrd-end", start + size); + + return start + size; +} + +static uint32_t openrisc_load_fdt(Or1ksimState *state, hwaddr load_start, + uint64_t mem_size) +{ + void *fdt = state->fdt; + uint32_t fdt_addr; + int ret; + int fdtsize = fdt_totalsize(fdt); + + if (fdtsize <= 0) { + error_report("invalid device-tree"); + exit(1); + } + + /* We put fdt right after the kernel and/or initrd. */ + fdt_addr = ROUND_UP(load_start, 4); + + ret = fdt_pack(fdt); + /* Should only fail if we've built a corrupted tree */ + g_assert(ret == 0); + /* copy in the device tree */ + qemu_fdt_dumpdtb(fdt, fdtsize); + + rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr, + &address_space_memory); + + return fdt_addr; } static void openrisc_sim_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *kernel_filename = machine->kernel_filename; - OpenRISCCPU *cpus[2] = {}; + OpenRISCCPU *cpus[OR1KSIM_CPUS_MAX] = {}; + Or1ksimState *state = OR1KSIM_MACHINE(machine); MemoryRegion *ram; - qemu_irq serial_irq; + hwaddr load_addr; int n; unsigned int smp_cpus = machine->smp.cpus; - assert(smp_cpus >= 1 && smp_cpus <= 2); + assert(smp_cpus >= 1 && smp_cpus <= OR1KSIM_CPUS_MAX); for (n = 0; n < smp_cpus; n++) { cpus[n] = OPENRISC_CPU(cpu_create(machine->cpu_type)); if (cpus[n] == NULL) { @@ -163,33 +398,58 @@ static void openrisc_sim_init(MachineState *machine) memory_region_init_ram(ram, NULL, "openrisc.ram", ram_size, &error_fatal); memory_region_add_subregion(get_system_memory(), 0, ram); + openrisc_create_fdt(state, or1ksim_memmap, smp_cpus, machine->ram_size, + machine->kernel_cmdline); + if (nd_table[0].used) { - openrisc_sim_net_init(0x92000000, 0x92000400, smp_cpus, - cpus, 4, nd_table); + openrisc_sim_net_init(state, or1ksim_memmap[OR1KSIM_ETHOC].base, + or1ksim_memmap[OR1KSIM_ETHOC].size, + smp_cpus, cpus, + OR1KSIM_ETHOC_IRQ, nd_table); } if (smp_cpus > 1) { - openrisc_sim_ompic_init(0x98000000, smp_cpus, cpus, 1); - - serial_irq = qemu_irq_split(get_cpu_irq(cpus, 0, 2), - get_cpu_irq(cpus, 1, 2)); - } else { - serial_irq = get_cpu_irq(cpus, 0, 2); + openrisc_sim_ompic_init(state, or1ksim_memmap[OR1KSIM_OMPIC].base, + or1ksim_memmap[OR1KSIM_UART].size, + smp_cpus, cpus, OR1KSIM_OMPIC_IRQ); } - serial_mm_init(get_system_memory(), 0x90000000, 0, serial_irq, - 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN); + openrisc_sim_serial_init(state, or1ksim_memmap[OR1KSIM_UART].base, + or1ksim_memmap[OR1KSIM_UART].size, smp_cpus, cpus, + OR1KSIM_UART_IRQ); - openrisc_load_kernel(ram_size, kernel_filename); + load_addr = openrisc_load_kernel(ram_size, kernel_filename); + if (load_addr > 0) { + if (machine->initrd_filename) { + load_addr = openrisc_load_initrd(state, machine->initrd_filename, + load_addr, machine->ram_size); + } + boot_info.fdt_addr = openrisc_load_fdt(state, load_addr, + machine->ram_size); + } } -static void openrisc_sim_machine_init(MachineClass *mc) +static void openrisc_sim_machine_init(ObjectClass *oc, void *data) { + MachineClass *mc = MACHINE_CLASS(oc); + mc->desc = "or1k simulation"; mc->init = openrisc_sim_init; - mc->max_cpus = 2; + mc->max_cpus = OR1KSIM_CPUS_MAX; mc->is_default = true; mc->default_cpu_type = OPENRISC_CPU_TYPE_NAME("or1200"); } -DEFINE_MACHINE("or1k-sim", openrisc_sim_machine_init) +static const TypeInfo or1ksim_machine_typeinfo = { + .name = TYPE_OR1KSIM_MACHINE, + .parent = TYPE_MACHINE, + .class_init = openrisc_sim_machine_init, + .instance_size = sizeof(Or1ksimState), +}; + +static void or1ksim_machine_init_register_types(void) +{ + type_register_static(&or1ksim_machine_typeinfo); +} + +type_init(or1ksim_machine_init_register_types) diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c index 94a5510..d55b4b0 100644 --- a/hw/ppc/spapr_rtc.c +++ b/hw/ppc/spapr_rtc.c @@ -32,7 +32,7 @@ #include "hw/ppc/spapr.h" #include "migration/vmstate.h" #include "qapi/error.h" -#include "qapi/qapi-events-misc-target.h" +#include "qapi/qapi-events-misc.h" #include "qemu/cutils.h" #include "qemu/module.h" @@ -97,6 +97,7 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t nret, target_ulong rets) { SpaprRtcState *rtc = &spapr->rtc; + g_autofree const char *qom_path = NULL; struct tm tm; time_t new_s; int64_t host_ns; @@ -120,7 +121,8 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, SpaprMachineState *spapr, } /* Generate a monitor event for the change */ - qapi_event_send_rtc_change(qemu_timedate_diff(&tm)); + qom_path = object_get_canonical_path(OBJECT(rtc)); + qapi_event_send_rtc_change(qemu_timedate_diff(&tm), qom_path); host_ns = qemu_clock_get_ns(rtc_clock); diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index e61a0cc..ac9a60c 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -40,7 +40,7 @@ #include "hw/rtc/mc146818rtc_regs.h" #include "migration/vmstate.h" #include "qapi/error.h" -#include "qapi/qapi-events-misc-target.h" +#include "qapi/qapi-events-misc.h" #include "qapi/visitor.h" #include "hw/rtc/mc146818rtc_regs.h" @@ -611,12 +611,13 @@ static void rtc_get_time(RTCState *s, struct tm *tm) static void rtc_set_time(RTCState *s) { struct tm tm; + g_autofree const char *qom_path = object_get_canonical_path(OBJECT(s)); rtc_get_time(s, &tm); s->base_rtc = mktimegm(&tm); s->last_update = qemu_clock_get_ns(rtc_clock); - qapi_event_send_rtc_change(qemu_timedate_diff(&tm)); + qapi_event_send_rtc_change(qemu_timedate_diff(&tm), qom_path); } static void rtc_set_cmos(RTCState *s, const struct tm *tm) diff --git a/hw/rtc/meson.build b/hw/rtc/meson.build index 8fd8d8f..7cecdee 100644 --- a/hw/rtc/meson.build +++ b/hw/rtc/meson.build @@ -2,7 +2,7 @@ softmmu_ss.add(when: 'CONFIG_DS1338', if_true: files('ds1338.c')) softmmu_ss.add(when: 'CONFIG_M41T80', if_true: files('m41t80.c')) softmmu_ss.add(when: 'CONFIG_M48T59', if_true: files('m48t59.c')) -specific_ss.add(when: 'CONFIG_PL031', if_true: files('pl031.c')) +softmmu_ss.add(when: 'CONFIG_PL031', if_true: files('pl031.c')) softmmu_ss.add(when: 'CONFIG_TWL92230', if_true: files('twl92230.c')) softmmu_ss.add(when: ['CONFIG_ISA_BUS', 'CONFIG_M48T59'], if_true: files('m48t59-isa.c')) softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-rtc.c')) diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c index 38d9d3c..b01d0e7 100644 --- a/hw/rtc/pl031.c +++ b/hw/rtc/pl031.c @@ -24,7 +24,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include "trace.h" -#include "qapi/qapi-events-misc-target.h" +#include "qapi/qapi-events-misc.h" #define RTC_DR 0x00 /* Data read register */ #define RTC_MR 0x04 /* Match register */ @@ -138,12 +138,13 @@ static void pl031_write(void * opaque, hwaddr offset, switch (offset) { case RTC_LR: { + g_autofree const char *qom_path = object_get_canonical_path(opaque); struct tm tm; s->tick_offset += value - pl031_get_count(s); qemu_get_timedate(&tm, s->tick_offset); - qapi_event_send_rtc_change(qemu_timedate_diff(&tm)); + qapi_event_send_rtc_change(qemu_timedate_diff(&tm), qom_path); pl031_set_alarm(s); break; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 84e3e63..90480e7 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -802,7 +802,10 @@ DEFINE_CCW_MACHINE(7_0, "7.0", true); static void ccw_machine_6_2_instance_options(MachineState *machine) { + static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V6_2 }; + ccw_machine_7_0_instance_options(machine); + s390_set_qemu_cpu_model(0x3906, 14, 2, qemu_cpu_feat); } static void ccw_machine_6_2_class_options(MachineClass *mc) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index ff154eb..d899be1 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -259,6 +259,10 @@ static void aspeed_smc_flash_set_segment_region(AspeedSMCState *s, int cs, memory_region_set_enabled(&fl->mmio, !!seg.size); memory_region_transaction_commit(); + if (asc->segment_addr_mask) { + regval &= asc->segment_addr_mask; + } + s->regs[R_SEG_ADDR0 + cs] = regval; } @@ -1364,6 +1368,7 @@ static void aspeed_2400_fmc_class_init(ObjectClass *klass, void *data) asc->conf_enable_w0 = CONF_ENABLE_W0; asc->max_peripherals = 5; asc->segments = aspeed_2400_fmc_segments; + asc->segment_addr_mask = 0xffff0000; asc->resets = aspeed_2400_fmc_resets; asc->flash_window_base = 0x20000000; asc->flash_window_size = 0x10000000; @@ -1446,6 +1451,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data) asc->conf_enable_w0 = CONF_ENABLE_W0; asc->max_peripherals = 3; asc->segments = aspeed_2500_fmc_segments; + asc->segment_addr_mask = 0xffff0000; asc->resets = aspeed_2500_fmc_resets; asc->flash_window_base = 0x20000000; asc->flash_window_size = 0x10000000; @@ -1483,6 +1489,7 @@ static void aspeed_2500_spi1_class_init(ObjectClass *klass, void *data) asc->conf_enable_w0 = CONF_ENABLE_W0; asc->max_peripherals = 2; asc->segments = aspeed_2500_spi1_segments; + asc->segment_addr_mask = 0xffff0000; asc->flash_window_base = 0x30000000; asc->flash_window_size = 0x8000000; asc->features = 0x0; @@ -1517,6 +1524,7 @@ static void aspeed_2500_spi2_class_init(ObjectClass *klass, void *data) asc->conf_enable_w0 = CONF_ENABLE_W0; asc->max_peripherals = 2; asc->segments = aspeed_2500_spi2_segments; + asc->segment_addr_mask = 0xffff0000; asc->flash_window_base = 0x38000000; asc->flash_window_size = 0x8000000; asc->features = 0x0; @@ -1598,6 +1606,7 @@ static void aspeed_2600_fmc_class_init(ObjectClass *klass, void *data) asc->conf_enable_w0 = CONF_ENABLE_W0; asc->max_peripherals = 3; asc->segments = aspeed_2600_fmc_segments; + asc->segment_addr_mask = 0x0ff00ff0; asc->resets = aspeed_2600_fmc_resets; asc->flash_window_base = 0x20000000; asc->flash_window_size = 0x10000000; @@ -1636,6 +1645,7 @@ static void aspeed_2600_spi1_class_init(ObjectClass *klass, void *data) asc->conf_enable_w0 = CONF_ENABLE_W0; asc->max_peripherals = 2; asc->segments = aspeed_2600_spi1_segments; + asc->segment_addr_mask = 0x0ff00ff0; asc->flash_window_base = 0x30000000; asc->flash_window_size = 0x10000000; asc->features = ASPEED_SMC_FEATURE_DMA | @@ -1674,6 +1684,7 @@ static void aspeed_2600_spi2_class_init(ObjectClass *klass, void *data) asc->conf_enable_w0 = CONF_ENABLE_W0; asc->max_peripherals = 3; asc->segments = aspeed_2600_spi2_segments; + asc->segment_addr_mask = 0x0ff00ff0; asc->flash_window_base = 0x50000000; asc->flash_window_size = 0x10000000; asc->features = ASPEED_SMC_FEATURE_DMA | |