SPARC patches

HW:
 - Use UNIMP device instead of EMPTY_SLOT
 - Make EMPTY_SLOT similar to UNIMP device
 - Map UART devices unconditionally
 - Pair of fixes for AHB PnP
 - Add trace events to AHB PnP
 
 TCG:
 - Improve exception logging
 
 CI:
 - https://gitlab.com/philmd/qemu/-/pipelines/154231191
 - https://travis-ci.org/github/philmd/qemu/builds/696321130
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAl7fORkACgkQ4+MsLN6t
 wN56ExAAiWB10eKKbqYcsX6yHXXVmihRLbo0E4EbpeB9Vg8H2I3bhL3v4s/WCsKF
 zHL2uazLRFCjQMgy19UvuhDzXPgTZjhGAWvh2GhbB/B21WuXqNOsYj8OHkhUqNbg
 OFK2ZFDWcmK1ddnzJRxa2jG28Ei8TneO6DBRvECiT2r2IEmLuVUvc6Aacpzsqunj
 qZTAg4EnxUKKj1f0kPgaganPRa90ZWJlBNbLkBrbXw+xCZrja1HkKLH46NjRWoap
 5jQznsCgKmKCnlYR1aDO/qGkj3W3VWqI4FPaP3v7p7GFqtOaQ8mu/wytv1uVvJRx
 P7+SkECNmVjIgbrsfG1cWHGvEZ5+iY0Au14/jG0Z/f3el4vgqjjxFBOXQtM4MOoO
 f9ANUQ9ecnlvSq9+P2Rst/CxlZNDEa/E/BANT0n4upYr8pPn9Ya1WrTtPIHYjQdv
 V5hhfNt78tqtGrJD68Z29ywZq8whfg2qwK1rpIZY5I3lyVaY/wfESAQit0HV6Lhf
 KL76nwvmSRxqIC88mChpUW6oGQLPJZW/s9Ug9pO4IzQo/ExoMvf9OOUmsk9Gctaq
 koTRCeoV4Wgcp+BkbCgHANKda9nGGfGanV0uJFBiclZAADfu9nmmdl9nEQoaPCxu
 fwocYIh2aYR9T2DgJvdOlkHLqzVeu9BPZpCKUhjyHE3AmETDsk0=
 =EHrR
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/philmd-gitlab/tags/sparc-next-20200609' into staging

SPARC patches

HW:
- Use UNIMP device instead of EMPTY_SLOT
- Make EMPTY_SLOT similar to UNIMP device
- Map UART devices unconditionally
- Pair of fixes for AHB PnP
- Add trace events to AHB PnP

TCG:
- Improve exception logging

CI:
- https://gitlab.com/philmd/qemu/-/pipelines/154231191
- https://travis-ci.org/github/philmd/qemu/builds/696321130

# gpg: Signature made Tue 09 Jun 2020 08:24:09 BST
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE

* remotes/philmd-gitlab/tags/sparc-next-20200609:
  target/sparc/int32_helper: Extract and use excp_name_str()
  target/sparc/int32_helper: Remove DEBUG_PCALL definition
  hw/timer/grlib_gptimer: Display frequency in decimal
  hw/misc/grlib_ahb_apb_pnp: Add trace events on read accesses
  hw/misc/grlib_ahb_apb_pnp: Fix AHB PnP 8-bit accesses
  hw/misc/grlib_ahb_apb_pnp: Avoid crash when writing to AHB PnP registers
  hw/sparc64/niagara: Remove duplicated NIAGARA_UART_BASE definition
  hw/sparc64/niagara: Map the UART device unconditionally
  hw/sparc/leon3: Map the UART device unconditionally
  hw/misc/empty_slot: Name the slots when created
  hw/misc/empty_slot: Move the 'hw/misc' and cover in MAINTAINERS
  hw/misc/empty_slot: Convert debug printf() to trace event
  hw/misc/empty_slot: Add a 'name' qdev property
  hw/misc/empty_slot: Convert 'size' field as qdev property
  hw/misc/empty_slot: Lower address space priority
  hw/sparc/sun4m: Use UnimplementedDevice for I/O devices

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-06-09 17:29:47 +01:00
commit 31d321c2b3
15 changed files with 124 additions and 70 deletions

View File

@ -1864,6 +1864,13 @@ S: Maintained
F: include/hw/misc/unimp.h
F: hw/misc/unimp.c
Empty slot
M: Artyom Tarasenko <atar4qemu@gmail.com>
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
S: Maintained
F: include/hw/misc/empty_slot.h
F: hw/misc/empty_slot.c
Standard VGA
M: Gerd Hoffmann <kraxel@redhat.com>
S: Maintained

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,6 +5,7 @@ config SUN4M
select CS4231
select ECCMEMCTL
select EMPTY_SLOT
select UNIMP
select ESCC
select ESP
select FDC

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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