diff --git a/MAINTAINERS b/MAINTAINERS index 6e7890ce82..3abe3faa4e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1864,6 +1864,13 @@ S: Maintained F: include/hw/misc/unimp.h F: hw/misc/unimp.c +Empty slot +M: Artyom Tarasenko +R: Philippe Mathieu-Daudé +S: Maintained +F: include/hw/misc/empty_slot.h +F: hw/misc/empty_slot.c + Standard VGA M: Gerd Hoffmann S: Maintained diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 1d540ed6e7..d8fee8effe 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -24,7 +24,6 @@ common-obj-$(CONFIG_SOFTMMU) += numa.o common-obj-$(CONFIG_SOFTMMU) += clock-vmstate.o obj-$(CONFIG_SOFTMMU) += machine-qmp-cmds.o -common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_XILINX_AXI) += stream.o common-obj-$(CONFIG_PTIMER) += ptimer.o common-obj-$(CONFIG_FITLOADER) += loader-fit.o diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 636c95d1fe..62063b2305 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -52,7 +52,7 @@ #include "sysemu/runstate.h" #include "qapi/error.h" #include "qemu/error-report.h" -#include "hw/empty_slot.h" +#include "hw/misc/empty_slot.h" #include "sysemu/kvm.h" #include "hw/semihosting/semihost.h" #include "hw/mips/cps.h" @@ -1241,7 +1241,7 @@ void mips_malta_init(MachineState *machine) * exception when accessing invalid memory. Create an empty slot to * emulate this feature. */ - empty_slot_init(0, 0x20000000); + empty_slot_init("GT64120", 0, 0x20000000); qdev_init_nofail(dev); diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 60a9d80b74..5aaca8a039 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -10,6 +10,7 @@ common-obj-$(CONFIG_EDU) += edu.o common-obj-$(CONFIG_PCA9552) += pca9552.o common-obj-$(CONFIG_UNIMP) += unimp.o +common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_FW_CFG_DMA) += vmcoreinfo.o # ARM devices diff --git a/hw/core/empty_slot.c b/hw/misc/empty_slot.c similarity index 66% rename from hw/core/empty_slot.c rename to hw/misc/empty_slot.c index 3ba450e1ca..b568ae202b 100644 --- a/hw/core/empty_slot.c +++ b/hw/misc/empty_slot.c @@ -11,17 +11,9 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "qemu/module.h" -#include "hw/empty_slot.h" - -//#define DEBUG_EMPTY_SLOT - -#ifdef DEBUG_EMPTY_SLOT -#define DPRINTF(fmt, ...) \ - do { printf("empty_slot: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif +#include "hw/qdev-properties.h" +#include "hw/misc/empty_slot.h" +#include "trace.h" #define TYPE_EMPTY_SLOT "empty_slot" #define EMPTY_SLOT(obj) OBJECT_CHECK(EmptySlot, (obj), TYPE_EMPTY_SLOT) @@ -30,20 +22,26 @@ typedef struct EmptySlot { SysBusDevice parent_obj; MemoryRegion iomem; + char *name; uint64_t size; } EmptySlot; static uint64_t empty_slot_read(void *opaque, hwaddr addr, unsigned size) { - DPRINTF("read from " TARGET_FMT_plx "\n", addr); + EmptySlot *s = EMPTY_SLOT(opaque); + + trace_empty_slot_write(addr, size << 1, 0, size, s->name); + return 0; } static void empty_slot_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", (unsigned)val, addr); + EmptySlot *s = EMPTY_SLOT(opaque); + + trace_empty_slot_write(addr, size << 1, val, size, s->name); } static const MemoryRegionOps empty_slot_ops = { @@ -52,22 +50,18 @@ static const MemoryRegionOps empty_slot_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -void empty_slot_init(hwaddr addr, uint64_t slot_size) +void empty_slot_init(const char *name, hwaddr addr, uint64_t slot_size) { if (slot_size > 0) { /* Only empty slots larger than 0 byte need handling. */ DeviceState *dev; - SysBusDevice *s; - EmptySlot *e; dev = qdev_create(NULL, TYPE_EMPTY_SLOT); - s = SYS_BUS_DEVICE(dev); - e = EMPTY_SLOT(dev); - e->size = slot_size; + qdev_prop_set_uint64(dev, "size", slot_size); qdev_init_nofail(dev); - sysbus_mmio_map(s, 0, addr); + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, addr, -10000); } } @@ -75,16 +69,27 @@ static void empty_slot_realize(DeviceState *dev, Error **errp) { EmptySlot *s = EMPTY_SLOT(dev); + if (s->name == NULL) { + s->name = g_strdup("empty-slot"); + } memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s, - "empty-slot", s->size); + s->name, s->size); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); } +static Property empty_slot_properties[] = { + DEFINE_PROP_UINT64("size", EmptySlot, size, 0), + DEFINE_PROP_STRING("name", EmptySlot, name), + DEFINE_PROP_END_OF_LIST(), +}; + static void empty_slot_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = empty_slot_realize; + device_class_set_props(dc, empty_slot_properties); + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo empty_slot_info = { diff --git a/hw/misc/grlib_ahb_apb_pnp.c b/hw/misc/grlib_ahb_apb_pnp.c index e230e25363..43e001c3c7 100644 --- a/hw/misc/grlib_ahb_apb_pnp.c +++ b/hw/misc/grlib_ahb_apb_pnp.c @@ -25,6 +25,7 @@ #include "qemu/log.h" #include "hw/sysbus.h" #include "hw/misc/grlib_ahb_apb_pnp.h" +#include "trace.h" #define GRLIB_PNP_VENDOR_SHIFT (24) #define GRLIB_PNP_VENDOR_SIZE (8) @@ -132,13 +133,28 @@ void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask, static uint64_t grlib_ahb_pnp_read(void *opaque, hwaddr offset, unsigned size) { AHBPnp *ahb_pnp = GRLIB_AHB_PNP(opaque); + uint32_t val; - return ahb_pnp->regs[offset >> 2]; + val = ahb_pnp->regs[offset >> 2]; + trace_grlib_ahb_pnp_read(offset, val); + + return val; +} + +static void grlib_ahb_pnp_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__); } static const MemoryRegionOps grlib_ahb_pnp_ops = { .read = grlib_ahb_pnp_read, + .write = grlib_ahb_pnp_write, .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, }; static void grlib_ahb_pnp_realize(DeviceState *dev, Error **errp) @@ -228,8 +244,12 @@ void grlib_apb_pnp_add_entry(APBPnp *dev, uint32_t address, uint32_t mask, static uint64_t grlib_apb_pnp_read(void *opaque, hwaddr offset, unsigned size) { APBPnp *apb_pnp = GRLIB_APB_PNP(opaque); + uint32_t val; - return apb_pnp->regs[offset >> 2]; + val = apb_pnp->regs[offset >> 2]; + trace_grlib_apb_pnp_read(offset, val); + + return val; } static void grlib_apb_pnp_write(void *opaque, hwaddr addr, diff --git a/hw/misc/trace-events b/hw/misc/trace-events index a5862b2bed..5561746866 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -39,6 +39,10 @@ ecc_mem_readl_ecr1(uint32_t ret) "Read event count 2 0x%08x" ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = 0x%02x" ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= 0x%02x" +# empty_slot.c +empty_slot_read(uint64_t addr, unsigned width, uint64_t value, unsigned size, const char *name) "rd addr:0x%04"PRIx64" data:0x%0*"PRIx64" size %u [%s]" +empty_slot_write(uint64_t addr, unsigned width, uint64_t value, unsigned size, const char *name) "wr addr:0x%04"PRIx64" data:0x%0*"PRIx64" size %u [%s]" + # slavio_misc.c slavio_misc_update_irq_raise(void) "Raise IRQ" slavio_misc_update_irq_lower(void) "Lower IRQ" @@ -198,3 +202,7 @@ via1_rtc_cmd_pram_read(int addr, int value) "addr=%u value=0x%02x" via1_rtc_cmd_pram_write(int addr, int value) "addr=%u value=0x%02x" via1_rtc_cmd_pram_sect_read(int sector, int offset, int addr, int value) "sector=%u offset=%u addr=%d value=0x%02x" via1_rtc_cmd_pram_sect_write(int sector, int offset, int addr, int value) "sector=%u offset=%u addr=%d value=0x%02x" + +# grlib_ahb_apb_pnp.c +grlib_ahb_pnp_read(uint64_t addr, uint32_t value) "AHB PnP read addr:0x%03"PRIx64" data:0x%08x" +grlib_apb_pnp_read(uint64_t addr, uint32_t value) "APB PnP read addr:0x%03"PRIx64" data:0x%08x" diff --git a/hw/sparc/Kconfig b/hw/sparc/Kconfig index 22aff2f5b7..91805afab6 100644 --- a/hw/sparc/Kconfig +++ b/hw/sparc/Kconfig @@ -5,6 +5,7 @@ config SUN4M select CS4231 select ECCMEMCTL select EMPTY_SLOT + select UNIMP select ESCC select ESP select FDC diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 8f024dab7b..cc55117dec 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -339,16 +339,14 @@ static void leon3_generic_hw_init(MachineState *machine) 0, LEON3_TIMER_IRQ, GRLIB_APBIO_AREA); /* Allocate uart */ - if (serial_hd(0)) { - dev = qdev_create(NULL, TYPE_GRLIB_APB_UART); - qdev_prop_set_chr(dev, "chrdev", serial_hd(0)); - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_UART_OFFSET); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irqs[LEON3_UART_IRQ]); - grlib_apb_pnp_add_entry(apb_pnp, LEON3_UART_OFFSET, 0xFFF, - GRLIB_VENDOR_GAISLER, GRLIB_APBUART_DEV, 1, - LEON3_UART_IRQ, GRLIB_APBIO_AREA); - } + dev = qdev_create(NULL, TYPE_GRLIB_APB_UART); + qdev_prop_set_chr(dev, "chrdev", serial_hd(0)); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_UART_OFFSET); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irqs[LEON3_UART_IRQ]); + grlib_apb_pnp_add_entry(apb_pnp, LEON3_UART_OFFSET, 0xFFF, + GRLIB_VENDOR_GAISLER, GRLIB_APBUART_DEV, 1, + LEON3_UART_IRQ, GRLIB_APBIO_AREA); } static void leon3_generic_machine_init(MachineClass *mc) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 8dda3f7292..249f7ba7ea 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -46,7 +46,8 @@ #include "hw/nvram/chrp_nvram.h" #include "hw/nvram/fw_cfg.h" #include "hw/char/escc.h" -#include "hw/empty_slot.h" +#include "hw/misc/empty_slot.h" +#include "hw/misc/unimp.h" #include "hw/irq.h" #include "hw/loader.h" #include "elf.h" @@ -883,7 +884,8 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, /* models without ECC don't trap when missing ram is accessed */ if (!hwdef->ecc_base) { - empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size); + empty_slot_init("ecc", machine->ram_size, + hwdef->max_mem - machine->ram_size); } prom_init(hwdef->slavio_base, bios_name); @@ -914,7 +916,8 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, Software shouldn't use aliased addresses, neither should it crash when does. Using empty_slot instead of aliasing can help with debugging such accesses */ - empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len); + empty_slot_init("iommu.alias", + hwdef->iommu_pad_base, hwdef->iommu_pad_len); } sparc32_dma_init(hwdef->dma_base, @@ -963,12 +966,14 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, for (i = 0; i < MAX_VSIMMS; i++) { /* vsimm registers probed by OBP */ if (hwdef->vsimm[i].reg_base) { - empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000); + char *name = g_strdup_printf("vsimm[%d]", i); + empty_slot_init(name, hwdef->vsimm[i].reg_base, 0x2000); + g_free(name); } } if (hwdef->sx_base) { - empty_slot_init(hwdef->sx_base, 0x2000); + create_unimplemented_device("SUNW,sx", hwdef->sx_base, 0x2000); } nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8); @@ -1031,14 +1036,16 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, if (hwdef->dbri_base) { /* ISDN chip with attached CS4215 audio codec */ /* prom space */ - empty_slot_init(hwdef->dbri_base+0x1000, 0x30); + create_unimplemented_device("SUNW,DBRI.prom", + hwdef->dbri_base + 0x1000, 0x30); /* reg space */ - empty_slot_init(hwdef->dbri_base+0x10000, 0x100); + create_unimplemented_device("SUNW,DBRI", + hwdef->dbri_base + 0x10000, 0x100); } if (hwdef->bpp_base) { /* parallel port */ - empty_slot_init(hwdef->bpp_base, 0x20); + create_unimplemented_device("SUNW,bpp", hwdef->bpp_base, 0x20); } initrd_size = 0; diff --git a/hw/sparc64/niagara.c b/hw/sparc64/niagara.c index ab5ef8c5b3..a87d55f6bb 100644 --- a/hw/sparc64/niagara.c +++ b/hw/sparc64/niagara.c @@ -68,7 +68,6 @@ typedef struct NiagaraBoardState { #define NIAGARA_VDISK_BASE 0x1f40000000ULL #define NIAGARA_RTC_BASE 0xfff0c1fff8ULL -#define NIAGARA_UART_BASE 0x1f10000000ULL /* Firmware layout * @@ -152,10 +151,8 @@ static void niagara_init(MachineState *machine) exit(1); } } - if (serial_hd(0)) { - serial_mm_init(sysmem, NIAGARA_UART_BASE, 0, NULL, 115200, - serial_hd(0), DEVICE_BIG_ENDIAN); - } + serial_mm_init(sysmem, NIAGARA_UART_BASE, 0, NULL, + 115200, serial_hd(0), DEVICE_BIG_ENDIAN); create_unimplemented_device("sun4v-iob", NIAGARA_IOBBASE, NIAGARA_IOBSIZE); sun4v_rtc_init(NIAGARA_RTC_BASE); } diff --git a/hw/timer/trace-events b/hw/timer/trace-events index 80ea197594..866c9f546a 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -19,7 +19,7 @@ slavio_timer_mem_writel_invalid(uint64_t addr) "invalid write address 0x%"PRIx64 grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run" grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x" grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x" -grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x" +grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq:%uHz" grlib_gptimer_hit(int id) "timer:%d HIT" grlib_gptimer_readl(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" grlib_gptimer_writel(int id, uint64_t addr, uint32_t val) "timer:%d addr 0x%"PRIx64" 0x%x" diff --git a/include/hw/empty_slot.h b/include/hw/empty_slot.h deleted file mode 100644 index cb9a221aa6..0000000000 --- a/include/hw/empty_slot.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef HW_EMPTY_SLOT_H -#define HW_EMPTY_SLOT_H - -#include "exec/hwaddr.h" - -/* empty_slot.c */ -void empty_slot_init(hwaddr addr, uint64_t slot_size); - -#endif diff --git a/include/hw/misc/empty_slot.h b/include/hw/misc/empty_slot.h new file mode 100644 index 0000000000..dec56e56ae --- /dev/null +++ b/include/hw/misc/empty_slot.h @@ -0,0 +1,19 @@ +/* + * QEMU Empty Slot + * + * The empty_slot device emulates known to a bus but not connected devices. + * + * Copyright (c) 2010 Artyom Tarasenko + * + * This code is licensed under the GNU GPL v2 or (at your option) any later + * version. + */ + +#ifndef HW_EMPTY_SLOT_H +#define HW_EMPTY_SLOT_H + +#include "exec/hwaddr.h" + +void empty_slot_init(const char *name, hwaddr addr, uint64_t slot_size); + +#endif diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c index 813b47dbb2..9a71e1abd8 100644 --- a/target/sparc/int32_helper.c +++ b/target/sparc/int32_helper.c @@ -23,9 +23,7 @@ #include "exec/log.h" #include "sysemu/runstate.h" -#define DEBUG_PCALL -#ifdef DEBUG_PCALL static const char * const excp_names[0x80] = { [TT_TFAULT] = "Instruction Access Fault", [TT_ILL_INSN] = "Illegal Instruction", @@ -58,7 +56,14 @@ static const char * const excp_names[0x80] = { [TT_DIV_ZERO] = "Division By Zero", [TT_NCP_INSN] = "Coprocessor Disabled", }; -#endif + +static const char *excp_name_str(int32_t exception_index) +{ + if (exception_index < 0 || exception_index >= ARRAY_SIZE(excp_names)) { + return "Unknown"; + } + return excp_names[exception_index]; +} void sparc_cpu_do_interrupt(CPUState *cs) { @@ -71,7 +76,6 @@ void sparc_cpu_do_interrupt(CPUState *cs) cpu_get_psr(env); } -#ifdef DEBUG_PCALL if (qemu_loglevel_mask(CPU_LOG_INT)) { static int count; const char *name; @@ -81,10 +85,7 @@ void sparc_cpu_do_interrupt(CPUState *cs) } else if (intno >= 0x80) { name = "Trap Instruction"; } else { - name = excp_names[intno]; - if (!name) { - name = "Unknown"; - } + name = excp_name_str(intno); } qemu_log("%6d: %s (v=%02x)\n", count, name, intno); @@ -104,15 +105,15 @@ void sparc_cpu_do_interrupt(CPUState *cs) #endif count++; } -#endif #if !defined(CONFIG_USER_ONLY) if (env->psret == 0) { if (cs->exception_index == 0x80 && env->def.features & CPU_FEATURE_TA0_SHUTDOWN) { qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); } else { - cpu_abort(cs, "Trap 0x%02x while interrupts disabled, Error state", - cs->exception_index); + cpu_abort(cs, "Trap 0x%02x (%s) while interrupts disabled, " + "Error state", + cs->exception_index, excp_name_str(cs->exception_index)); } return; }