From: Alex Benn??e <a...@bennee.com> Commit 9b8c69243 broke the ability to boot the kernel as the value returned by unassigned_mem_read returned non-zero and left the kernel looping forever waiting for it to change (see integrator_led_set in the kernel code).
Relying on a varying implementation detail is incorrect anyway so this introduces a memory region to emulate the debug/led region on the integrator board. It is currently a basic stub as I have no idea what the behaviour of this region should be so for now it simply returns 0's as the old unassigned_mem_read did. --- hw/arm/integratorcp.c | 2 ++ hw/misc/Makefile.objs | 1 + hw/misc/arm_intdbg.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 hw/misc/arm_intdbg.c diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c index 2ef93ed..e5d07c4 100644 --- a/hw/arm/integratorcp.c +++ b/hw/arm/integratorcp.c @@ -446,6 +446,7 @@ static void icp_control_init(hwaddr base) } + /* Board init. */ static struct arm_boot_info integrator_binfo = { @@ -508,6 +509,7 @@ static void integratorcp_init(QEMUMachineInitArgs *args) icp_control_init(0xcb000000); sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]); sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]); + sysbus_create_simple("integrator_dbg", 0x1a000000, 0); sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL); if (nd_table[0].used) smc91c111_init(&nd_table[0], 0xc8000000, pic[27]); diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 2578e29..e2c84a3 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -22,6 +22,7 @@ obj-$(CONFIG_LINUX) += vfio.o endif obj-$(CONFIG_REALVIEW) += arm_sysctl.o +obj-y += arm_intdbg.o obj-$(CONFIG_A9SCU) += a9scu.o obj-$(CONFIG_NSERIES) += cbus.o obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o diff --git a/hw/misc/arm_intdbg.c b/hw/misc/arm_intdbg.c new file mode 100644 index 0000000..1f21447 --- /dev/null +++ b/hw/misc/arm_intdbg.c @@ -0,0 +1,90 @@ +/* + * LED, Switch and Debug control registers for ARM Integrator Boards + * + * This currently is a stub for this functionality written with + * reference to what the Linux kernel looks at. Previously we relied + * on the behaviour of unassigned_mem_read() in the core. + * + * Written by Alex Benn??e + * + * This code is licensed under the GPL. + */ + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "exec/address-spaces.h" + +#define TYPE_ARM_INTDBG "integrator_dbg" +#define ARM_INTDBG(obj) \ + OBJECT_CHECK(arm_intdbg_state, (obj), TYPE_ARM_INTDBG) + +typedef struct { + SysBusDevice parent_obj; + MemoryRegion iomem; + + uint32_t alpha; + uint32_t leds; + uint32_t switches; +} arm_intdbg_state; + +static uint64_t dbg_control_read(void *opaque, hwaddr offset, + unsigned size) +{ + switch (offset >> 2) { + case 0: /* ALPHA */ + return 0; + case 1: /* LEDS */ + return 0; + case 2: /* SWITCHES */ + return 0; + default: + hw_error("dbg_control_read: Bad offset %x\n", (int)offset); + return 0; + } +} + +static void dbg_control_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + switch (offset >> 2) { + case 1: /* ALPHA */ + case 2: /* LEDS */ + case 3: /* SWITCHES */ + /* Nothing interesting implemented yet. */ + break; + default: + hw_error("dbg_control_write: Bad offset %x\n", (int)offset); + } +} + +static const MemoryRegionOps dbg_control_ops = { + .read = dbg_control_read, + .write = dbg_control_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void dbg_control_init(Object *obj) +{ + SysBusDevice *sd = SYS_BUS_DEVICE(obj); + arm_intdbg_state *s = ARM_INTDBG(obj); + memory_region_init_io(&s->iomem, NULL, &dbg_control_ops, NULL, "dbgleds", 0x1000); + sysbus_init_mmio(sd, &s->iomem); +} + +/* + Hardware boilerplate +*/ + +static const TypeInfo arm_intdbg_info = { + .name = TYPE_ARM_INTDBG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(arm_intdbg_state), + .instance_init = dbg_control_init, +}; + +static void arm_intdbg_register_types(void) +{ + type_register_static(&arm_intdbg_info); +} + +type_init(arm_intdbg_register_types) -- 1.8.4