From 870c034da0be2207e1b535cb6897958556fa0380 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 17 Jan 2020 14:09:29 +0000 Subject: [PATCH 01/15] hw/misc: Add the STM32F4xx Sysconfig device Signed-off-by: Alistair Francis Reviewed-by: Peter Maydell Message-id: 49b01423a09cef2ca832ff73a84a996568f1a8fc.1576658572.git.alistair@alistair23.me Signed-off-by: Peter Maydell --- default-configs/arm-softmmu.mak | 1 + hw/arm/Kconfig | 9 ++ hw/misc/Kconfig | 3 + hw/misc/Makefile.objs | 1 + hw/misc/stm32f4xx_syscfg.c | 171 +++++++++++++++++++++++++++++ hw/misc/trace-events | 6 + include/hw/misc/stm32f4xx_syscfg.h | 61 ++++++++++ 7 files changed, 252 insertions(+) create mode 100644 hw/misc/stm32f4xx_syscfg.c create mode 100644 include/hw/misc/stm32f4xx_syscfg.h diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 1f2e0e7fde..645e6201bb 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -30,6 +30,7 @@ CONFIG_Z2=y CONFIG_COLLIE=y CONFIG_ASPEED_SOC=y CONFIG_NETDUINO2=y +CONFIG_NETDUINOPLUS2=y CONFIG_MPS2=y CONFIG_RASPI=y CONFIG_DIGIC=y diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index c6e7782580..4660d14715 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -101,6 +101,10 @@ config NETDUINO2 bool select STM32F205_SOC +config NETDUINOPLUS2 + bool + select STM32F405_SOC + config NSERIES bool select OMAP @@ -307,6 +311,11 @@ config STM32F205_SOC select STM32F2XX_ADC select STM32F2XX_SPI +config STM32F405_SOC + bool + select ARM_V7M + select STM32F4XX_SYSCFG + config XLNX_ZYNQMP_ARM bool select AHCI diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 2164646553..72609650b7 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -82,6 +82,9 @@ config IMX config STM32F2XX_SYSCFG bool +config STM32F4XX_SYSCFG + bool + config MIPS_ITU bool diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index ba898a5781..ea8025e0bb 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -58,6 +58,7 @@ common-obj-$(CONFIG_SLAVIO) += slavio_misc.o common-obj-$(CONFIG_ZYNQ) += zynq_slcr.o common-obj-$(CONFIG_ZYNQ) += zynq-xadc.o common-obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o +common-obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o obj-$(CONFIG_MIPS_CPS) += mips_cpc.o obj-$(CONFIG_MIPS_ITU) += mips_itu.o diff --git a/hw/misc/stm32f4xx_syscfg.c b/hw/misc/stm32f4xx_syscfg.c new file mode 100644 index 0000000000..dbcdca59f8 --- /dev/null +++ b/hw/misc/stm32f4xx_syscfg.c @@ -0,0 +1,171 @@ +/* + * STM32F4xx SYSCFG + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "trace.h" +#include "hw/irq.h" +#include "migration/vmstate.h" +#include "hw/misc/stm32f4xx_syscfg.h" + +static void stm32f4xx_syscfg_reset(DeviceState *dev) +{ + STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(dev); + + s->syscfg_memrmp = 0x00000000; + s->syscfg_pmc = 0x00000000; + s->syscfg_exticr[0] = 0x00000000; + s->syscfg_exticr[1] = 0x00000000; + s->syscfg_exticr[2] = 0x00000000; + s->syscfg_exticr[3] = 0x00000000; + s->syscfg_cmpcr = 0x00000000; +} + +static void stm32f4xx_syscfg_set_irq(void *opaque, int irq, int level) +{ + STM32F4xxSyscfgState *s = opaque; + int icrreg = irq / 4; + int startbit = (irq & 3) * 4; + uint8_t config = config = irq / 16; + + trace_stm32f4xx_syscfg_set_irq(irq / 16, irq % 16, level); + + g_assert(icrreg < SYSCFG_NUM_EXTICR); + + if (extract32(s->syscfg_exticr[icrreg], startbit, 4) == config) { + qemu_set_irq(s->gpio_out[irq], level); + trace_stm32f4xx_pulse_exti(irq); + } +} + +static uint64_t stm32f4xx_syscfg_read(void *opaque, hwaddr addr, + unsigned int size) +{ + STM32F4xxSyscfgState *s = opaque; + + trace_stm32f4xx_syscfg_read(addr); + + switch (addr) { + case SYSCFG_MEMRMP: + return s->syscfg_memrmp; + case SYSCFG_PMC: + return s->syscfg_pmc; + case SYSCFG_EXTICR1...SYSCFG_EXTICR4: + return s->syscfg_exticr[addr / 4 - SYSCFG_EXTICR1 / 4]; + case SYSCFG_CMPCR: + return s->syscfg_cmpcr; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); + return 0; + } +} + +static void stm32f4xx_syscfg_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + STM32F4xxSyscfgState *s = opaque; + uint32_t value = val64; + + trace_stm32f4xx_syscfg_write(value, addr); + + switch (addr) { + case SYSCFG_MEMRMP: + qemu_log_mask(LOG_UNIMP, + "%s: Changing the memory mapping isn't supported " \ + "in QEMU\n", __func__); + return; + case SYSCFG_PMC: + qemu_log_mask(LOG_UNIMP, + "%s: Changing the memory mapping isn't supported " \ + "in QEMU\n", __func__); + return; + case SYSCFG_EXTICR1...SYSCFG_EXTICR4: + s->syscfg_exticr[addr / 4 - SYSCFG_EXTICR1 / 4] = (value & 0xFFFF); + return; + case SYSCFG_CMPCR: + s->syscfg_cmpcr = value; + return; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); + } +} + +static const MemoryRegionOps stm32f4xx_syscfg_ops = { + .read = stm32f4xx_syscfg_read, + .write = stm32f4xx_syscfg_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void stm32f4xx_syscfg_init(Object *obj) +{ + STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(obj); + + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); + + memory_region_init_io(&s->mmio, obj, &stm32f4xx_syscfg_ops, s, + TYPE_STM32F4XX_SYSCFG, 0x400); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + + qdev_init_gpio_in(DEVICE(obj), stm32f4xx_syscfg_set_irq, 16 * 9); + qdev_init_gpio_out(DEVICE(obj), s->gpio_out, 16); +} + +static const VMStateDescription vmstate_stm32f4xx_syscfg = { + .name = TYPE_STM32F4XX_SYSCFG, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(syscfg_memrmp, STM32F4xxSyscfgState), + VMSTATE_UINT32(syscfg_pmc, STM32F4xxSyscfgState), + VMSTATE_UINT32_ARRAY(syscfg_exticr, STM32F4xxSyscfgState, + SYSCFG_NUM_EXTICR), + VMSTATE_UINT32(syscfg_cmpcr, STM32F4xxSyscfgState), + VMSTATE_END_OF_LIST() + } +}; + +static void stm32f4xx_syscfg_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = stm32f4xx_syscfg_reset; + dc->vmsd = &vmstate_stm32f4xx_syscfg; +} + +static const TypeInfo stm32f4xx_syscfg_info = { + .name = TYPE_STM32F4XX_SYSCFG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(STM32F4xxSyscfgState), + .instance_init = stm32f4xx_syscfg_init, + .class_init = stm32f4xx_syscfg_class_init, +}; + +static void stm32f4xx_syscfg_register_types(void) +{ + type_register_static(&stm32f4xx_syscfg_info); +} + +type_init(stm32f4xx_syscfg_register_types) diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 2e0c820834..44b4f72f57 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -84,6 +84,12 @@ mos6522_set_sr_int(void) "set sr_int" mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64 mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x" +# stm32f4xx_syscfg +stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d" +stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d" +stm32f4xx_syscfg_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " " +stm32f4xx_syscfg_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 "" + # tz-mpc.c tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u" tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u" diff --git a/include/hw/misc/stm32f4xx_syscfg.h b/include/hw/misc/stm32f4xx_syscfg.h new file mode 100644 index 0000000000..c62c6629e5 --- /dev/null +++ b/include/hw/misc/stm32f4xx_syscfg.h @@ -0,0 +1,61 @@ +/* + * STM32F4xx SYSCFG + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_STM_SYSCFG_H +#define HW_STM_SYSCFG_H + +#include "hw/sysbus.h" +#include "hw/hw.h" + +#define SYSCFG_MEMRMP 0x00 +#define SYSCFG_PMC 0x04 +#define SYSCFG_EXTICR1 0x08 +#define SYSCFG_EXTICR2 0x0C +#define SYSCFG_EXTICR3 0x10 +#define SYSCFG_EXTICR4 0x14 +#define SYSCFG_CMPCR 0x20 + +#define TYPE_STM32F4XX_SYSCFG "stm32f4xx-syscfg" +#define STM32F4XX_SYSCFG(obj) \ + OBJECT_CHECK(STM32F4xxSyscfgState, (obj), TYPE_STM32F4XX_SYSCFG) + +#define SYSCFG_NUM_EXTICR 4 + +typedef struct { + /* */ + SysBusDevice parent_obj; + + /* */ + MemoryRegion mmio; + + uint32_t syscfg_memrmp; + uint32_t syscfg_pmc; + uint32_t syscfg_exticr[SYSCFG_NUM_EXTICR]; + uint32_t syscfg_cmpcr; + + qemu_irq irq; + qemu_irq gpio_out[16]; +} STM32F4xxSyscfgState; + +#endif From e64d8c83f929d4a0b077b7c460d09c429c6fca57 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 17 Jan 2020 14:09:29 +0000 Subject: [PATCH 02/15] hw/misc: Add the STM32F4xx EXTI device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alistair Francis Reviewed-by: Peter Maydell Message-id: ef941d59fd8658589d34ed432e1d6dfdcf7fb1d0.1576658572.git.alistair@alistair23.me Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- hw/arm/Kconfig | 1 + hw/misc/Kconfig | 3 + hw/misc/Makefile.objs | 1 + hw/misc/stm32f4xx_exti.c | 188 +++++++++++++++++++++++++++++++ hw/misc/trace-events | 5 + include/hw/misc/stm32f4xx_exti.h | 60 ++++++++++ 6 files changed, 258 insertions(+) create mode 100644 hw/misc/stm32f4xx_exti.c create mode 100644 include/hw/misc/stm32f4xx_exti.h diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 4660d14715..3d86691ae0 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -315,6 +315,7 @@ config STM32F405_SOC bool select ARM_V7M select STM32F4XX_SYSCFG + select STM32F4XX_EXTI config XLNX_ZYNQMP_ARM bool diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 72609650b7..bdd77d8020 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -85,6 +85,9 @@ config STM32F2XX_SYSCFG config STM32F4XX_SYSCFG bool +config STM32F4XX_EXTI + bool + config MIPS_ITU bool diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index ea8025e0bb..c6ecbdd7b0 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -59,6 +59,7 @@ common-obj-$(CONFIG_ZYNQ) += zynq_slcr.o common-obj-$(CONFIG_ZYNQ) += zynq-xadc.o common-obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o common-obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o +common-obj-$(CONFIG_STM32F4XX_EXTI) += stm32f4xx_exti.o obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o obj-$(CONFIG_MIPS_CPS) += mips_cpc.o obj-$(CONFIG_MIPS_ITU) += mips_itu.o diff --git a/hw/misc/stm32f4xx_exti.c b/hw/misc/stm32f4xx_exti.c new file mode 100644 index 0000000000..02e7810046 --- /dev/null +++ b/hw/misc/stm32f4xx_exti.c @@ -0,0 +1,188 @@ +/* + * STM32F4XX EXTI + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "trace.h" +#include "hw/irq.h" +#include "migration/vmstate.h" +#include "hw/misc/stm32f4xx_exti.h" + +static void stm32f4xx_exti_reset(DeviceState *dev) +{ + STM32F4xxExtiState *s = STM32F4XX_EXTI(dev); + + s->exti_imr = 0x00000000; + s->exti_emr = 0x00000000; + s->exti_rtsr = 0x00000000; + s->exti_ftsr = 0x00000000; + s->exti_swier = 0x00000000; + s->exti_pr = 0x00000000; +} + +static void stm32f4xx_exti_set_irq(void *opaque, int irq, int level) +{ + STM32F4xxExtiState *s = opaque; + + trace_stm32f4xx_exti_set_irq(irq, level); + + if (((1 << irq) & s->exti_rtsr) && level) { + /* Rising Edge */ + s->exti_pr |= 1 << irq; + } + + if (((1 << irq) & s->exti_ftsr) && !level) { + /* Falling Edge */ + s->exti_pr |= 1 << irq; + } + + if (!((1 << irq) & s->exti_imr)) { + /* Interrupt is masked */ + return; + } + qemu_irq_pulse(s->irq[irq]); +} + +static uint64_t stm32f4xx_exti_read(void *opaque, hwaddr addr, + unsigned int size) +{ + STM32F4xxExtiState *s = opaque; + + trace_stm32f4xx_exti_read(addr); + + switch (addr) { + case EXTI_IMR: + return s->exti_imr; + case EXTI_EMR: + return s->exti_emr; + case EXTI_RTSR: + return s->exti_rtsr; + case EXTI_FTSR: + return s->exti_ftsr; + case EXTI_SWIER: + return s->exti_swier; + case EXTI_PR: + return s->exti_pr; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "STM32F4XX_exti_read: Bad offset %x\n", (int)addr); + return 0; + } + return 0; +} + +static void stm32f4xx_exti_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + STM32F4xxExtiState *s = opaque; + uint32_t value = (uint32_t) val64; + + trace_stm32f4xx_exti_write(addr, value); + + switch (addr) { + case EXTI_IMR: + s->exti_imr = value; + return; + case EXTI_EMR: + s->exti_emr = value; + return; + case EXTI_RTSR: + s->exti_rtsr = value; + return; + case EXTI_FTSR: + s->exti_ftsr = value; + return; + case EXTI_SWIER: + s->exti_swier = value; + return; + case EXTI_PR: + /* This bit is cleared by writing a 1 to it */ + s->exti_pr &= ~value; + return; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "STM32F4XX_exti_write: Bad offset %x\n", (int)addr); + } +} + +static const MemoryRegionOps stm32f4xx_exti_ops = { + .read = stm32f4xx_exti_read, + .write = stm32f4xx_exti_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void stm32f4xx_exti_init(Object *obj) +{ + STM32F4xxExtiState *s = STM32F4XX_EXTI(obj); + int i; + + for (i = 0; i < NUM_INTERRUPT_OUT_LINES; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]); + } + + memory_region_init_io(&s->mmio, obj, &stm32f4xx_exti_ops, s, + TYPE_STM32F4XX_EXTI, 0x400); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + + qdev_init_gpio_in(DEVICE(obj), stm32f4xx_exti_set_irq, + NUM_GPIO_EVENT_IN_LINES); +} + +static const VMStateDescription vmstate_stm32f4xx_exti = { + .name = TYPE_STM32F4XX_EXTI, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(exti_imr, STM32F4xxExtiState), + VMSTATE_UINT32(exti_emr, STM32F4xxExtiState), + VMSTATE_UINT32(exti_rtsr, STM32F4xxExtiState), + VMSTATE_UINT32(exti_ftsr, STM32F4xxExtiState), + VMSTATE_UINT32(exti_swier, STM32F4xxExtiState), + VMSTATE_UINT32(exti_pr, STM32F4xxExtiState), + VMSTATE_END_OF_LIST() + } +}; + +static void stm32f4xx_exti_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = stm32f4xx_exti_reset; + dc->vmsd = &vmstate_stm32f4xx_exti; +} + +static const TypeInfo stm32f4xx_exti_info = { + .name = TYPE_STM32F4XX_EXTI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(STM32F4xxExtiState), + .instance_init = stm32f4xx_exti_init, + .class_init = stm32f4xx_exti_class_init, +}; + +static void stm32f4xx_exti_register_types(void) +{ + type_register_static(&stm32f4xx_exti_info); +} + +type_init(stm32f4xx_exti_register_types) diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 44b4f72f57..7f0f5dff3a 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -90,6 +90,11 @@ stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d" stm32f4xx_syscfg_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " " stm32f4xx_syscfg_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 "" +# stm32f4xx_exti +stm32f4xx_exti_set_irq(int irq, int leve) "Set EXTI: %d to %d" +stm32f4xx_exti_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " " +stm32f4xx_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 "" + # tz-mpc.c tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u" tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u" diff --git a/include/hw/misc/stm32f4xx_exti.h b/include/hw/misc/stm32f4xx_exti.h new file mode 100644 index 0000000000..707036a41b --- /dev/null +++ b/include/hw/misc/stm32f4xx_exti.h @@ -0,0 +1,60 @@ +/* + * STM32F4XX EXTI + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_STM_EXTI_H +#define HW_STM_EXTI_H + +#include "hw/sysbus.h" +#include "hw/hw.h" + +#define EXTI_IMR 0x00 +#define EXTI_EMR 0x04 +#define EXTI_RTSR 0x08 +#define EXTI_FTSR 0x0C +#define EXTI_SWIER 0x10 +#define EXTI_PR 0x14 + +#define TYPE_STM32F4XX_EXTI "stm32f4xx-exti" +#define STM32F4XX_EXTI(obj) \ + OBJECT_CHECK(STM32F4xxExtiState, (obj), TYPE_STM32F4XX_EXTI) + +#define NUM_GPIO_EVENT_IN_LINES 16 +#define NUM_INTERRUPT_OUT_LINES 16 + +typedef struct { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t exti_imr; + uint32_t exti_emr; + uint32_t exti_rtsr; + uint32_t exti_ftsr; + uint32_t exti_swier; + uint32_t exti_pr; + + qemu_irq irq[NUM_INTERRUPT_OUT_LINES]; +} STM32F4xxExtiState; + +#endif From 529fc5fd3e18ace8f739afd02dc0953354f39442 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 17 Jan 2020 14:09:29 +0000 Subject: [PATCH 03/15] hw/arm: Add the STM32F4xx SoC Signed-off-by: Alistair Francis Reviewed-by: Peter Maydell Message-id: 1d145c4c13e5fa140caf131232a6f524c88fcd72.1576658572.git.alistair@alistair23.me Signed-off-by: Peter Maydell --- MAINTAINERS | 8 + hw/arm/Makefile.objs | 1 + hw/arm/stm32f405_soc.c | 302 +++++++++++++++++++++++++++++++++ include/hw/arm/stm32f405_soc.h | 73 ++++++++ 4 files changed, 384 insertions(+) create mode 100644 hw/arm/stm32f405_soc.c create mode 100644 include/hw/arm/stm32f405_soc.h diff --git a/MAINTAINERS b/MAINTAINERS index 4b425d030d..cae53f5c14 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -816,6 +816,14 @@ F: hw/adc/* F: hw/ssi/stm32f2xx_spi.c F: include/hw/*/stm32*.h +STM32F405 +M: Alistair Francis +M: Peter Maydell +S: Maintained +F: hw/arm/stm32f405_soc.c +F: hw/misc/stm32f4xx_syscfg.c +F: hw/misc/stm32f4xx_exti.c + Netduino 2 M: Alistair Francis M: Peter Maydell diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index fe749f65fd..d9d54da7cf 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -36,6 +36,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c new file mode 100644 index 0000000000..f22516fdf7 --- /dev/null +++ b/hw/arm/stm32f405_soc.c @@ -0,0 +1,302 @@ +/* + * STM32F405 SoC + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "exec/address-spaces.h" +#include "sysemu/sysemu.h" +#include "hw/arm/stm32f405_soc.h" +#include "hw/misc/unimp.h" + +#define SYSCFG_ADD 0x40013800 +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800, + 0x40004C00, 0x40005000, 0x40011400, + 0x40007800, 0x40007C00 }; +/* At the moment only Timer 2 to 5 are modelled */ +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400, + 0x40000800, 0x40000C00 }; +#define ADC_ADDR 0x40012000 +static const uint32_t spi_addr[] = { 0x40013000, 0x40003800, 0x40003C00, + 0x40013400, 0x40015000, 0x40015400 }; +#define EXTI_ADDR 0x40013C00 + +#define SYSCFG_IRQ 71 +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 }; +static const int timer_irq[] = { 28, 29, 30, 50 }; +#define ADC_IRQ 18 +static const int spi_irq[] = { 35, 36, 51, 0, 0, 0 }; +static const int exti_irq[] = { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40, + 40, 40, 40, 40, 40} ; + + +static void stm32f405_soc_initfn(Object *obj) +{ + STM32F405State *s = STM32F405_SOC(obj); + int i; + + sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m), + TYPE_ARMV7M); + + sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg), + TYPE_STM32F4XX_SYSCFG); + + for (i = 0; i < STM_NUM_USARTS; i++) { + sysbus_init_child_obj(obj, "usart[*]", &s->usart[i], + sizeof(s->usart[i]), TYPE_STM32F2XX_USART); + } + + for (i = 0; i < STM_NUM_TIMERS; i++) { + sysbus_init_child_obj(obj, "timer[*]", &s->timer[i], + sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER); + } + + for (i = 0; i < STM_NUM_ADCS; i++) { + sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]), + TYPE_STM32F2XX_ADC); + } + + for (i = 0; i < STM_NUM_SPIS; i++) { + sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]), + TYPE_STM32F2XX_SPI); + } + + sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti), + TYPE_STM32F4XX_EXTI); +} + +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) +{ + STM32F405State *s = STM32F405_SOC(dev_soc); + MemoryRegion *system_memory = get_system_memory(); + DeviceState *dev, *armv7m; + SysBusDevice *busdev; + Error *err = NULL; + int i; + + memory_region_init_ram(&s->flash, NULL, "STM32F405.flash", FLASH_SIZE, + &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + memory_region_init_alias(&s->flash_alias, NULL, "STM32F405.flash.alias", + &s->flash, 0, FLASH_SIZE); + + memory_region_set_readonly(&s->flash, true); + memory_region_set_readonly(&s->flash_alias, true); + + memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash); + memory_region_add_subregion(system_memory, 0, &s->flash_alias); + + memory_region_init_ram(&s->sram, NULL, "STM32F405.sram", SRAM_SIZE, + &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram); + + armv7m = DEVICE(&s->armv7m); + qdev_prop_set_uint32(armv7m, "num-irq", 96); + qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type); + qdev_prop_set_bit(armv7m, "enable-bitband", true); + object_property_set_link(OBJECT(&s->armv7m), OBJECT(system_memory), + "memory", &error_abort); + object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + + /* System configuration controller */ + dev = DEVICE(&s->syscfg); + object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, SYSCFG_ADD); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ)); + + /* Attach UART (uses USART registers) and USART controllers */ + for (i = 0; i < STM_NUM_USARTS; i++) { + dev = DEVICE(&(s->usart[i])); + qdev_prop_set_chr(dev, "chardev", serial_hd(i)); + object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, usart_addr[i]); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i])); + } + + /* Timer 2 to 5 */ + for (i = 0; i < STM_NUM_TIMERS; i++) { + dev = DEVICE(&(s->timer[i])); + qdev_prop_set_uint64(dev, "clock-frequency", 1000000000); + object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, timer_addr[i]); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i])); + } + + /* ADC device, the IRQs are ORed together */ + object_initialize_child(OBJECT(s), "adc-orirq", &s->adc_irqs, + sizeof(s->adc_irqs), TYPE_OR_IRQ, + &err, NULL); + if (err != NULL) { + error_propagate(errp, err); + return; + } + object_property_set_int(OBJECT(&s->adc_irqs), STM_NUM_ADCS, + "num-lines", &err); + object_property_set_bool(OBJECT(&s->adc_irqs), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + qdev_connect_gpio_out(DEVICE(&s->adc_irqs), 0, + qdev_get_gpio_in(armv7m, ADC_IRQ)); + + dev = DEVICE(&(s->adc[i])); + object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, ADC_ADDR); + sysbus_connect_irq(busdev, 0, + qdev_get_gpio_in(DEVICE(&s->adc_irqs), i)); + + /* SPI devices */ + for (i = 0; i < STM_NUM_SPIS; i++) { + dev = DEVICE(&(s->spi[i])); + object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, spi_addr[i]); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i])); + } + + /* EXTI device */ + dev = DEVICE(&s->exti); + object_property_set_bool(OBJECT(&s->exti), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, EXTI_ADDR); + for (i = 0; i < 16; i++) { + sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i])); + } + for (i = 0; i < 16; i++) { + qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i)); + } + + create_unimplemented_device("timer[7]", 0x40001400, 0x400); + create_unimplemented_device("timer[12]", 0x40001800, 0x400); + create_unimplemented_device("timer[6]", 0x40001000, 0x400); + create_unimplemented_device("timer[13]", 0x40001C00, 0x400); + create_unimplemented_device("timer[14]", 0x40002000, 0x400); + create_unimplemented_device("RTC and BKP", 0x40002800, 0x400); + create_unimplemented_device("WWDG", 0x40002C00, 0x400); + create_unimplemented_device("IWDG", 0x40003000, 0x400); + create_unimplemented_device("I2S2ext", 0x40003000, 0x400); + create_unimplemented_device("I2S3ext", 0x40004000, 0x400); + create_unimplemented_device("I2C1", 0x40005400, 0x400); + create_unimplemented_device("I2C2", 0x40005800, 0x400); + create_unimplemented_device("I2C3", 0x40005C00, 0x400); + create_unimplemented_device("CAN1", 0x40006400, 0x400); + create_unimplemented_device("CAN2", 0x40006800, 0x400); + create_unimplemented_device("PWR", 0x40007000, 0x400); + create_unimplemented_device("DAC", 0x40007400, 0x400); + create_unimplemented_device("timer[1]", 0x40010000, 0x400); + create_unimplemented_device("timer[8]", 0x40010400, 0x400); + create_unimplemented_device("SDIO", 0x40012C00, 0x400); + create_unimplemented_device("timer[9]", 0x40014000, 0x400); + create_unimplemented_device("timer[10]", 0x40014400, 0x400); + create_unimplemented_device("timer[11]", 0x40014800, 0x400); + create_unimplemented_device("GPIOA", 0x40020000, 0x400); + create_unimplemented_device("GPIOB", 0x40020400, 0x400); + create_unimplemented_device("GPIOC", 0x40020800, 0x400); + create_unimplemented_device("GPIOD", 0x40020C00, 0x400); + create_unimplemented_device("GPIOE", 0x40021000, 0x400); + create_unimplemented_device("GPIOF", 0x40021400, 0x400); + create_unimplemented_device("GPIOG", 0x40021800, 0x400); + create_unimplemented_device("GPIOH", 0x40021C00, 0x400); + create_unimplemented_device("GPIOI", 0x40022000, 0x400); + create_unimplemented_device("CRC", 0x40023000, 0x400); + create_unimplemented_device("RCC", 0x40023800, 0x400); + create_unimplemented_device("Flash Int", 0x40023C00, 0x400); + create_unimplemented_device("BKPSRAM", 0x40024000, 0x400); + create_unimplemented_device("DMA1", 0x40026000, 0x400); + create_unimplemented_device("DMA2", 0x40026400, 0x400); + create_unimplemented_device("Ethernet", 0x40028000, 0x1400); + create_unimplemented_device("USB OTG HS", 0x40040000, 0x30000); + create_unimplemented_device("USB OTG FS", 0x50000000, 0x31000); + create_unimplemented_device("DCMI", 0x50050000, 0x400); + create_unimplemented_device("RNG", 0x50060800, 0x400); +} + +static Property stm32f405_soc_properties[] = { + DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type), + DEFINE_PROP_END_OF_LIST(), +}; + +static void stm32f405_soc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = stm32f405_soc_realize; + dc->props = stm32f405_soc_properties; + /* No vmstate or reset required: device has no internal state */ +} + +static const TypeInfo stm32f405_soc_info = { + .name = TYPE_STM32F405_SOC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(STM32F405State), + .instance_init = stm32f405_soc_initfn, + .class_init = stm32f405_soc_class_init, +}; + +static void stm32f405_soc_types(void) +{ + type_register_static(&stm32f405_soc_info); +} + +type_init(stm32f405_soc_types) diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h new file mode 100644 index 0000000000..1fe97f8c3a --- /dev/null +++ b/include/hw/arm/stm32f405_soc.h @@ -0,0 +1,73 @@ +/* + * STM32F405 SoC + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_ARM_STM32F405_SOC_H +#define HW_ARM_STM32F405_SOC_H + +#include "hw/misc/stm32f4xx_syscfg.h" +#include "hw/timer/stm32f2xx_timer.h" +#include "hw/char/stm32f2xx_usart.h" +#include "hw/adc/stm32f2xx_adc.h" +#include "hw/misc/stm32f4xx_exti.h" +#include "hw/or-irq.h" +#include "hw/ssi/stm32f2xx_spi.h" +#include "hw/arm/armv7m.h" + +#define TYPE_STM32F405_SOC "stm32f405-soc" +#define STM32F405_SOC(obj) \ + OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC) + +#define STM_NUM_USARTS 7 +#define STM_NUM_TIMERS 4 +#define STM_NUM_ADCS 6 +#define STM_NUM_SPIS 6 + +#define FLASH_BASE_ADDRESS 0x08000000 +#define FLASH_SIZE (1024 * 1024) +#define SRAM_BASE_ADDRESS 0x20000000 +#define SRAM_SIZE (192 * 1024) + +typedef struct STM32F405State { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + char *cpu_type; + + ARMv7MState armv7m; + + STM32F4xxSyscfgState syscfg; + STM32F4xxExtiState exti; + STM32F2XXUsartState usart[STM_NUM_USARTS]; + STM32F2XXTimerState timer[STM_NUM_TIMERS]; + qemu_or_irq adc_irqs; + STM32F2XXADCState adc[STM_NUM_ADCS]; + STM32F2XXSPIState spi[STM_NUM_SPIS]; + + MemoryRegion sram; + MemoryRegion flash; + MemoryRegion flash_alias; +} STM32F405State; + +#endif From 60d6c4278a6976ababe351e3de05fcd370158351 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 17 Jan 2020 14:09:29 +0000 Subject: [PATCH 04/15] hw/arm: Add the Netduino Plus 2 Signed-off-by: Alistair Francis Reviewed-by: Peter Maydell Message-id: dad8d8d47f7625913e35e27a1c00f603a6b08f9a.1576658572.git.alistair@alistair23.me Signed-off-by: Peter Maydell --- MAINTAINERS | 6 +++++ hw/arm/Makefile.objs | 1 + hw/arm/netduinoplus2.c | 52 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 hw/arm/netduinoplus2.c diff --git a/MAINTAINERS b/MAINTAINERS index cae53f5c14..55d3642e6c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -830,6 +830,12 @@ M: Peter Maydell S: Maintained F: hw/arm/netduino2.c +Netduino Plus 2 +M: Alistair Francis +M: Peter Maydell +S: Maintained +F: hw/arm/netduinoplus2.c + SmartFusion2 M: Subbaraya Sundeep M: Peter Maydell diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index d9d54da7cf..336f6dd374 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -11,6 +11,7 @@ obj-$(CONFIG_MAINSTONE) += mainstone.o obj-$(CONFIG_MICROBIT) += microbit.o obj-$(CONFIG_MUSICPAL) += musicpal.o obj-$(CONFIG_NETDUINO2) += netduino2.o +obj-$(CONFIG_NETDUINOPLUS2) += netduinoplus2.o obj-$(CONFIG_NSERIES) += nseries.o obj-$(CONFIG_SX1) += omap_sx1.o obj-$(CONFIG_CHEETAH) += palm.o diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c new file mode 100644 index 0000000000..e5e247edbe --- /dev/null +++ b/hw/arm/netduinoplus2.c @@ -0,0 +1,52 @@ +/* + * Netduino Plus 2 Machine Model + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/qdev-properties.h" +#include "qemu/error-report.h" +#include "hw/arm/stm32f405_soc.h" +#include "hw/arm/boot.h" + +static void netduinoplus2_init(MachineState *machine) +{ + DeviceState *dev; + + dev = qdev_create(NULL, TYPE_STM32F405_SOC); + qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4")); + object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal); + + armv7m_load_kernel(ARM_CPU(first_cpu), + machine->kernel_filename, + FLASH_SIZE); +} + +static void netduinoplus2_machine_init(MachineClass *mc) +{ + mc->desc = "Netduino Plus 2 Machine"; + mc->init = netduinoplus2_init; +} + +DEFINE_MACHINE("netduinoplus2", netduinoplus2_machine_init) From c5ce3153f30f3181648b5a6c4efc39505ee201cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Jan 2020 14:09:29 +0000 Subject: [PATCH 05/15] tests/boot_linux_console: Add initrd test for the CubieBoard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This test boots a Linux kernel on a CubieBoard and verify the serial output is working. The kernel image and DeviceTree blob are built by the Armbian project (based on Debian): https://docs.armbian.com/Developer-Guide_Build-Preparation/ The cpio image used comes from the linux-build-test project: https://github.com/groeck/linux-build-test If ARM is a target being built, "make check-acceptance" will automatically include this test by the use of the "arch:arm" tags. Alternatively, this test can be run using: $ avocado --show=console run -t machine:cubieboard tests/acceptance/boot_linux_console.py console: Uncompressing Linux... done, booting the kernel. console: Booting Linux on physical CPU 0x0 console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019 console: CPU: ARMv7 Processor [410fc080] revision 0 (ARMv7), cr=50c5387d console: CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache console: OF: fdt: Machine model: Cubietech Cubieboard [...] console: Boot successful. console: cat /proc/cpuinfo console: / # cat /proc/cpuinfo console: processor : 0 console: model name : ARMv7 Processor rev 0 (v7l) console: BogoMIPS : 832.51 [...] console: Hardware : Allwinner sun4i/sun5i Families console: Revision : 0000 console: Serial : 0000000000000000 console: cat /proc/iomem console: / # cat /proc/iomem console: 01c00000-01c0002f : system-control@1c00000 console: 01c02000-01c02fff : dma-controller@1c02000 console: 01c05000-01c05fff : spi@1c05000 console: 01c0b080-01c0b093 : mdio@1c0b080 console: 01c0c000-01c0cfff : lcd-controller@1c0c000 console: 01c0d000-01c0dfff : lcd-controller@1c0d000 console: 01c0f000-01c0ffff : mmc@1c0f000 [...] PASS (54.35 s) Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Wainer dos Santos Moschetta Tested-by: Wainer dos Santos Moschetta Message-id: 20191230110953.25496-2-f4bug@amsat.org Signed-off-by: Peter Maydell --- tests/acceptance/boot_linux_console.py | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index 9c6aa2040a..4643f60e37 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -400,6 +400,47 @@ class BootLinuxConsole(Test): self.wait_for_console_pattern('Boot successful.') # TODO user command, for now the uart is stuck + def test_arm_cubieboard_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:cubieboard + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') + deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-4.20.7-sunxi') + dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.cpio.gz') + initrd_hash = '2b50f1873e113523967806f4da2afe385462ff9b' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun4i/sun5i') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + 'system-control@1c00000') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + def test_s390x_s390_ccw_virtio(self): """ :avocado: tags=arch:s390x From e33ee3097f705bd7d3ae14a177e12a4b16055970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Jan 2020 14:09:30 +0000 Subject: [PATCH 06/15] tests/boot_linux_console: Add a SD card test for the CubieBoard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel image and DeviceTree blob are built by the Armbian project (based on Debian): https://docs.armbian.com/Developer-Guide_Build-Preparation/ The cpio image used comes from the linux-build-test project: https://github.com/groeck/linux-build-test If ARM is a target being built, "make check-acceptance" will automatically include this test by the use of the "arch:arm" tags. Alternatively, this test can be run using: $ avocado --show=console run -t machine:cubieboard tests/acceptance/boot_linux_console.py console: Uncompressing Linux... done, booting the kernel. console: Booting Linux on physical CPU 0x0 console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019 [...] console: ahci-sunxi 1c18000.sata: Linked as a consumer to regulator.4 console: ahci-sunxi 1c18000.sata: controller can't do 64bit DMA, forcing 32bit console: ahci-sunxi 1c18000.sata: AHCI 0001.0000 32 slots 1 ports 1.5 Gbps 0x1 impl platform mode console: ahci-sunxi 1c18000.sata: flags: ncq only console: scsi host0: ahci-sunxi console: ata1: SATA max UDMA/133 mmio [mem 0x01c18000-0x01c18fff] port 0x100 irq 27 console: of_cfs_init console: of_cfs_init: OK console: vcc3v0: disabling console: vcc5v0: disabling console: usb1-vbus: disabling console: usb2-vbus: disabling console: ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300) console: ata1.00: ATA-7: QEMU HARDDISK, 2.5+, max UDMA/100 console: ata1.00: 40960 sectors, multi 16: LBA48 NCQ (depth 32) console: ata1.00: applying bridge limits console: ata1.00: configured for UDMA/100 console: scsi 0:0:0:0: Direct-Access ATA QEMU HARDDISK 2.5+ PQ: 0 ANSI: 5 console: sd 0:0:0:0: Attached scsi generic sg0 type 0 console: sd 0:0:0:0: [sda] 40960 512-byte logical blocks: (21.0 MB/20.0 MiB) console: sd 0:0:0:0: [sda] Write Protect is off console: sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA console: sd 0:0:0:0: [sda] Attached SCSI disk console: EXT4-fs (sda): mounting ext2 file system using the ext4 subsystem console: EXT4-fs (sda): mounted filesystem without journal. Opts: (null) console: VFS: Mounted root (ext2 filesystem) readonly on device 8:0. [...] console: cat /proc/partitions console: / # cat /proc/partitions console: major minor #blocks name console: 1 0 4096 ram0 console: 1 1 4096 ram1 console: 1 2 4096 ram2 console: 1 3 4096 ram3 console: 8 0 20480 sda console: reboot console: / # reboot [...] console: sd 0:0:0:0: [sda] Synchronizing SCSI cache console: reboot: Restarting system PASS (48.39 s) Signed-off-by: Philippe Mathieu-Daudé Message-id: 20191230110953.25496-3-f4bug@amsat.org Signed-off-by: Peter Maydell --- tests/acceptance/boot_linux_console.py | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index 4643f60e37..e40b84651b 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -441,6 +441,50 @@ class BootLinuxConsole(Test): exec_command_and_wait_for_pattern(self, 'reboot', 'reboot: Restarting system') + def test_arm_cubieboard_sata(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:cubieboard + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') + deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-4.20.7-sunxi') + dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + rootfs_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.ext2.gz') + rootfs_hash = '093e89d2b4d982234bf528bc9fb2f2f17a9d1f93' + rootfs_path_gz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash) + rootfs_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(rootfs_path_gz, rootfs_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'root=/dev/sda ro ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-drive', 'if=none,format=raw,id=disk0,file=' + + rootfs_path, + '-device', 'ide-hd,bus=ide.0,drive=disk0', + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun4i/sun5i') + exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', + 'sda') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + def test_s390x_s390_ccw_virtio(self): """ :avocado: tags=arch:s390x From 7f0ec9893cc8c99e7ee928fdc66bb3046f3e4cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Jan 2020 14:09:30 +0000 Subject: [PATCH 07/15] hw/arm/allwinner-a10: Move SoC definitions out of header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These definitions are specific to the A10 SoC and don't need to be exported to the different Allwinner peripherals. Signed-off-by: Philippe Mathieu-Daudé Message-id: 20191230110953.25496-4-f4bug@amsat.org Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- hw/arm/allwinner-a10.c | 6 ++++++ include/hw/arm/allwinner-a10.h | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c index 118032c8c7..0f1af5a880 100644 --- a/hw/arm/allwinner-a10.c +++ b/hw/arm/allwinner-a10.c @@ -25,6 +25,12 @@ #include "hw/misc/unimp.h" #include "sysemu/sysemu.h" +#define AW_A10_PIC_REG_BASE 0x01c20400 +#define AW_A10_PIT_REG_BASE 0x01c20c00 +#define AW_A10_UART0_REG_BASE 0x01c28000 +#define AW_A10_EMAC_BASE 0x01c0b000 +#define AW_A10_SATA_BASE 0x01c18000 + static void aw_a10_init(Object *obj) { AwA10State *s = AW_A10(obj); diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h index 7d2d215630..941c61e533 100644 --- a/include/hw/arm/allwinner-a10.h +++ b/include/hw/arm/allwinner-a10.h @@ -12,12 +12,6 @@ #include "target/arm/cpu.h" -#define AW_A10_PIC_REG_BASE 0x01c20400 -#define AW_A10_PIT_REG_BASE 0x01c20c00 -#define AW_A10_UART0_REG_BASE 0x01c28000 -#define AW_A10_EMAC_BASE 0x01c0b000 -#define AW_A10_SATA_BASE 0x01c18000 - #define AW_A10_SDRAM_BASE 0x40000000 #define TYPE_AW_A10 "allwinner-a10" From f8a865d36dc1578eb8a4f7c896c4f46f4b82ca45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Jan 2020 14:09:30 +0000 Subject: [PATCH 08/15] hw/arm/allwinner-a10: Simplify by passing IRQs with qdev_pass_gpios() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By calling qdev_pass_gpios() we don't need to hold a copy of the IRQs from the INTC into the SoC state. Instead of filling an array of qemu_irq and passing it around, we can now directly call qdev_get_gpio_in() on the SoC. Signed-off-by: Philippe Mathieu-Daudé Message-id: 20191230110953.25496-5-f4bug@amsat.org Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- hw/arm/allwinner-a10.c | 24 +++++++++++------------- include/hw/arm/allwinner-a10.h | 1 - 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c index 0f1af5a880..966fbd4a6e 100644 --- a/hw/arm/allwinner-a10.c +++ b/hw/arm/allwinner-a10.c @@ -55,7 +55,6 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) { AwA10State *s = AW_A10(dev); SysBusDevice *sysbusdev; - uint8_t i; qemu_irq fiq, irq; Error *err = NULL; @@ -76,9 +75,7 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(sysbusdev, 0, AW_A10_PIC_REG_BASE); sysbus_connect_irq(sysbusdev, 0, irq); sysbus_connect_irq(sysbusdev, 1, fiq); - for (i = 0; i < AW_A10_PIC_INT_NR; i++) { - s->irq[i] = qdev_get_gpio_in(DEVICE(&s->intc), i); - } + qdev_pass_gpios(DEVICE(&s->intc), dev, NULL); object_property_set_bool(OBJECT(&s->timer), true, "realized", &err); if (err != NULL) { @@ -87,12 +84,12 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) } sysbusdev = SYS_BUS_DEVICE(&s->timer); sysbus_mmio_map(sysbusdev, 0, AW_A10_PIT_REG_BASE); - sysbus_connect_irq(sysbusdev, 0, s->irq[22]); - sysbus_connect_irq(sysbusdev, 1, s->irq[23]); - sysbus_connect_irq(sysbusdev, 2, s->irq[24]); - sysbus_connect_irq(sysbusdev, 3, s->irq[25]); - sysbus_connect_irq(sysbusdev, 4, s->irq[67]); - sysbus_connect_irq(sysbusdev, 5, s->irq[68]); + sysbus_connect_irq(sysbusdev, 0, qdev_get_gpio_in(dev, 22)); + sysbus_connect_irq(sysbusdev, 1, qdev_get_gpio_in(dev, 23)); + sysbus_connect_irq(sysbusdev, 2, qdev_get_gpio_in(dev, 24)); + sysbus_connect_irq(sysbusdev, 3, qdev_get_gpio_in(dev, 25)); + sysbus_connect_irq(sysbusdev, 4, qdev_get_gpio_in(dev, 67)); + sysbus_connect_irq(sysbusdev, 5, qdev_get_gpio_in(dev, 68)); memory_region_init_ram(&s->sram_a, OBJECT(dev), "sram A", 48 * KiB, &error_fatal); @@ -111,7 +108,7 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) } sysbusdev = SYS_BUS_DEVICE(&s->emac); sysbus_mmio_map(sysbusdev, 0, AW_A10_EMAC_BASE); - sysbus_connect_irq(sysbusdev, 0, s->irq[55]); + sysbus_connect_irq(sysbusdev, 0, qdev_get_gpio_in(dev, 55)); object_property_set_bool(OBJECT(&s->sata), true, "realized", &err); if (err) { @@ -119,10 +116,11 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, AW_A10_SATA_BASE); - sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, s->irq[56]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, qdev_get_gpio_in(dev, 56)); /* FIXME use a qdev chardev prop instead of serial_hd() */ - serial_mm_init(get_system_memory(), AW_A10_UART0_REG_BASE, 2, s->irq[1], + serial_mm_init(get_system_memory(), AW_A10_UART0_REG_BASE, 2, + qdev_get_gpio_in(dev, 1), 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN); } diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h index 941c61e533..40d0b1d9c0 100644 --- a/include/hw/arm/allwinner-a10.h +++ b/include/hw/arm/allwinner-a10.h @@ -23,7 +23,6 @@ typedef struct AwA10State { /*< public >*/ ARMCPU cpu; - qemu_irq irq[AW_A10_PIC_INT_NR]; AwA10PITState timer; AwA10PICState intc; AwEmacState emac; From af4ba4ed13b2bbfd2d33527741810a5905a11310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Jan 2020 14:09:30 +0000 Subject: [PATCH 09/15] hw/arm/allwinner-a10: Remove local qemu_irq variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We won't reuse the CPU IRQ/FIQ variables. Simplify by calling qdev_get_gpio_in() in place. Signed-off-by: Philippe Mathieu-Daudé Message-id: 20191230110953.25496-6-f4bug@amsat.org Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- hw/arm/allwinner-a10.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c index 966fbd4a6e..1cde165611 100644 --- a/hw/arm/allwinner-a10.c +++ b/hw/arm/allwinner-a10.c @@ -55,7 +55,6 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) { AwA10State *s = AW_A10(dev); SysBusDevice *sysbusdev; - qemu_irq fiq, irq; Error *err = NULL; object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); @@ -63,8 +62,6 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - irq = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ); - fiq = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ); object_property_set_bool(OBJECT(&s->intc), true, "realized", &err); if (err != NULL) { @@ -73,8 +70,10 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) } sysbusdev = SYS_BUS_DEVICE(&s->intc); sysbus_mmio_map(sysbusdev, 0, AW_A10_PIC_REG_BASE); - sysbus_connect_irq(sysbusdev, 0, irq); - sysbus_connect_irq(sysbusdev, 1, fiq); + sysbus_connect_irq(sysbusdev, 0, + qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ)); + sysbus_connect_irq(sysbusdev, 1, + qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); qdev_pass_gpios(DEVICE(&s->intc), dev, NULL); object_property_set_bool(OBJECT(&s->timer), true, "realized", &err); From 21bf9b06cb6d07c6cc437dfd47b47b28c2bb79db Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 17 Jan 2020 14:09:30 +0000 Subject: [PATCH 10/15] target/arm/arm-semi: fix SYS_OPEN to return nonzero filehandle According to the specification "Semihosting for AArch32 and Aarch64", the SYS_OPEN operation should return: - A nonzero handle if the call is successful - -1 if the call is not successful So, it should never return 0. Prior to commit 35e9a0a8ce4b ("target/arm/arm-semi: Make semihosting code hand out its own file descriptors"), the guest fd matched to the host fd. It returned a nonzero handle on success since the fd 0 is already used for stdin. Now that the guest fd is the index of guestfd_array, it starts from 0. I noticed this issue particularly because Trusted Firmware-A built with PLAT=qemu is no longer working. Its io_semihosting driver only handles a positive return value as a valid filehandle. Basically, there are two ways to fix this: - Use (guestfd - 1) as the index of guestfs_arrary. We need to insert increment/decrement to convert the guestfd and the array index back and forth. - Keep using guestfd as the index of guestfs_array. The first entry of guestfs_array is left unused. I thought the latter is simpler. We end up with wasting a small piece of memory for the unused first entry of guestfd_array, but this is probably not a big deal. Fixes: 35e9a0a8ce4b ("target/arm/arm-semi: Make semihosting code hand out its own file descriptors") Cc: qemu-stable@nongnu.org Signed-off-by: Masahiro Yamada Reviewed-by: Richard Henderson Message-id: 20200109041228.10131-1-masahiroy@kernel.org Signed-off-by: Peter Maydell --- target/arm/arm-semi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c index 47d61f6fe1..788fe61b51 100644 --- a/target/arm/arm-semi.c +++ b/target/arm/arm-semi.c @@ -144,7 +144,8 @@ static int alloc_guestfd(void) guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD)); } - for (i = 0; i < guestfd_array->len; i++) { + /* SYS_OPEN should return nonzero handle on success. Start guestfd from 1 */ + for (i = 1; i < guestfd_array->len; i++) { GuestFD *gf = &g_array_index(guestfd_array, GuestFD, i); if (gf->type == GuestFDUnused) { @@ -168,7 +169,7 @@ static GuestFD *do_get_guestfd(int guestfd) return NULL; } - if (guestfd < 0 || guestfd >= guestfd_array->len) { + if (guestfd <= 0 || guestfd >= guestfd_array->len) { return NULL; } From f03965490e4e4223903e79a4ec97139ccdd48e1b Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Fri, 17 Jan 2020 14:09:31 +0000 Subject: [PATCH 11/15] i.MX: add an emulation for RNGC Add an emulation for the RNGC random number generator and the compatible RNGB variant. These peripherals are included (at least) in imx25 and imx35 chipsets. The emulation supports the initial self test, reseeding the prng and reading random numbers. Signed-off-by: Martin Kaiser Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/fsl-imx25.c | 11 ++ hw/misc/Makefile.objs | 1 + hw/misc/imx_rngc.c | 278 +++++++++++++++++++++++++++++++++++++ include/hw/arm/fsl-imx25.h | 5 + include/hw/misc/imx_rngc.h | 35 +++++ 5 files changed, 330 insertions(+) create mode 100644 hw/misc/imx_rngc.c create mode 100644 include/hw/misc/imx_rngc.h diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index 3cb5a8fdfd..da3471b395 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -62,6 +62,9 @@ static void fsl_imx25_init(Object *obj) sysbus_init_child_obj(obj, "fec", &s->fec, sizeof(s->fec), TYPE_IMX_FEC); + sysbus_init_child_obj(obj, "rngc", &s->rngc, sizeof(s->rngc), + TYPE_IMX_RNGC); + for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) { sysbus_init_child_obj(obj, "i2c[*]", &s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C); @@ -188,6 +191,14 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0, qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_FEC_IRQ)); + object_property_set_bool(OBJECT(&s->rngc), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->rngc), 0, FSL_IMX25_RNGC_ADDR); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->rngc), 0, + qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_RNGC_IRQ)); /* Initialize all I2C */ for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) { diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index c6ecbdd7b0..da993f45b7 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -42,6 +42,7 @@ common-obj-$(CONFIG_IMX) += imx7_ccm.o common-obj-$(CONFIG_IMX) += imx2_wdt.o common-obj-$(CONFIG_IMX) += imx7_snvs.o common-obj-$(CONFIG_IMX) += imx7_gpr.o +common-obj-$(CONFIG_IMX) += imx_rngc.o common-obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o common-obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o common-obj-$(CONFIG_MAINSTONE) += mst_fpga.o diff --git a/hw/misc/imx_rngc.c b/hw/misc/imx_rngc.c new file mode 100644 index 0000000000..4c270df2db --- /dev/null +++ b/hw/misc/imx_rngc.c @@ -0,0 +1,278 @@ +/* + * Freescale i.MX RNGC emulation + * + * Copyright (C) 2020 Martin Kaiser + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This driver provides the minimum functionality to initialize and seed + * an rngc and to read random numbers. The rngb that is found in imx25 + * chipsets is also supported. + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "qemu/module.h" +#include "qemu/log.h" +#include "qemu/guest-random.h" +#include "hw/irq.h" +#include "hw/misc/imx_rngc.h" +#include "migration/vmstate.h" + +#define RNGC_NAME "i.MX RNGC" + +#define RNGC_VER_ID 0x00 +#define RNGC_COMMAND 0x04 +#define RNGC_CONTROL 0x08 +#define RNGC_STATUS 0x0C +#define RNGC_FIFO 0x14 + +/* These version info are reported by the rngb in an imx258 chip. */ +#define RNG_TYPE_RNGB 0x1 +#define V_MAJ 0x2 +#define V_MIN 0x40 + +#define RNGC_CMD_BIT_SW_RST 0x40 +#define RNGC_CMD_BIT_CLR_ERR 0x20 +#define RNGC_CMD_BIT_CLR_INT 0x10 +#define RNGC_CMD_BIT_SEED 0x02 +#define RNGC_CMD_BIT_SELF_TEST 0x01 + +#define RNGC_CTRL_BIT_MASK_ERR 0x40 +#define RNGC_CTRL_BIT_MASK_DONE 0x20 +#define RNGC_CTRL_BIT_AUTO_SEED 0x10 + +/* the current status for self-test and seed operations */ +#define OP_IDLE 0 +#define OP_RUN 1 +#define OP_DONE 2 + +static uint64_t imx_rngc_read(void *opaque, hwaddr offset, unsigned size) +{ + IMXRNGCState *s = IMX_RNGC(opaque); + uint64_t val = 0; + + switch (offset) { + case RNGC_VER_ID: + val |= RNG_TYPE_RNGB << 28 | V_MAJ << 8 | V_MIN; + break; + + case RNGC_COMMAND: + if (s->op_seed == OP_RUN) { + val |= RNGC_CMD_BIT_SEED; + } + if (s->op_self_test == OP_RUN) { + val |= RNGC_CMD_BIT_SELF_TEST; + } + break; + + case RNGC_CONTROL: + /* + * The CTL_ACC and VERIF_MODE bits are not supported yet. + * They read as 0. + */ + val |= s->mask; + if (s->auto_seed) { + val |= RNGC_CTRL_BIT_AUTO_SEED; + } + /* + * We don't have an internal fifo like the real hardware. + * There's no need for strategy to handle fifo underflows. + * We return the FIFO_UFLOW_RESPONSE bits as 0. + */ + break; + + case RNGC_STATUS: + /* + * We never report any statistics test or self-test errors or any + * other errors. STAT_TEST_PF, ST_PF and ERROR are always 0. + */ + + /* + * We don't have an internal fifo, see above. Therefore, we + * report back the default fifo size (5 32-bit words) and + * indicate that our fifo is always full. + */ + val |= 5 << 12 | 5 << 8; + + /* We always have a new seed available. */ + val |= 1 << 6; + + if (s->op_seed == OP_DONE) { + val |= 1 << 5; + } + if (s->op_self_test == OP_DONE) { + val |= 1 << 4; + } + if (s->op_seed == OP_RUN || s->op_self_test == OP_RUN) { + /* + * We're busy if self-test is running or if we're + * seeding the prng. + */ + val |= 1 << 1; + } else { + /* + * We're ready to provide secure random numbers whenever + * we're not busy. + */ + val |= 1; + } + break; + + case RNGC_FIFO: + qemu_guest_getrandom_nofail(&val, sizeof(val)); + break; + } + + return val; +} + +static void imx_rngc_do_reset(IMXRNGCState *s) +{ + s->op_self_test = OP_IDLE; + s->op_seed = OP_IDLE; + s->mask = 0; + s->auto_seed = false; +} + +static void imx_rngc_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + IMXRNGCState *s = IMX_RNGC(opaque); + + switch (offset) { + case RNGC_COMMAND: + if (value & RNGC_CMD_BIT_SW_RST) { + imx_rngc_do_reset(s); + } + + /* + * For now, both CLR_ERR and CLR_INT clear the interrupt. We + * don't report any errors yet. + */ + if (value & (RNGC_CMD_BIT_CLR_ERR | RNGC_CMD_BIT_CLR_INT)) { + qemu_irq_lower(s->irq); + } + + if (value & RNGC_CMD_BIT_SEED) { + s->op_seed = OP_RUN; + qemu_bh_schedule(s->seed_bh); + } + + if (value & RNGC_CMD_BIT_SELF_TEST) { + s->op_self_test = OP_RUN; + qemu_bh_schedule(s->self_test_bh); + } + break; + + case RNGC_CONTROL: + /* + * The CTL_ACC and VERIF_MODE bits are not supported yet. + * We ignore them if they're set by the caller. + */ + + if (value & RNGC_CTRL_BIT_MASK_ERR) { + s->mask |= RNGC_CTRL_BIT_MASK_ERR; + } else { + s->mask &= ~RNGC_CTRL_BIT_MASK_ERR; + } + + if (value & RNGC_CTRL_BIT_MASK_DONE) { + s->mask |= RNGC_CTRL_BIT_MASK_DONE; + } else { + s->mask &= ~RNGC_CTRL_BIT_MASK_DONE; + } + + if (value & RNGC_CTRL_BIT_AUTO_SEED) { + s->auto_seed = true; + } else { + s->auto_seed = false; + } + break; + } +} + +static const MemoryRegionOps imx_rngc_ops = { + .read = imx_rngc_read, + .write = imx_rngc_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void imx_rngc_self_test(void *opaque) +{ + IMXRNGCState *s = IMX_RNGC(opaque); + + s->op_self_test = OP_DONE; + if (!(s->mask & RNGC_CTRL_BIT_MASK_DONE)) { + qemu_irq_raise(s->irq); + } +} + +static void imx_rngc_seed(void *opaque) +{ + IMXRNGCState *s = IMX_RNGC(opaque); + + s->op_seed = OP_DONE; + if (!(s->mask & RNGC_CTRL_BIT_MASK_DONE)) { + qemu_irq_raise(s->irq); + } +} + +static void imx_rngc_realize(DeviceState *dev, Error **errp) +{ + IMXRNGCState *s = IMX_RNGC(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init_io(&s->iomem, OBJECT(s), &imx_rngc_ops, s, + TYPE_IMX_RNGC, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + + sysbus_init_irq(sbd, &s->irq); + s->self_test_bh = qemu_bh_new(imx_rngc_self_test, s); + s->seed_bh = qemu_bh_new(imx_rngc_seed, s); +} + +static void imx_rngc_reset(DeviceState *dev) +{ + IMXRNGCState *s = IMX_RNGC(dev); + + imx_rngc_do_reset(s); +} + +static const VMStateDescription vmstate_imx_rngc = { + .name = RNGC_NAME, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(op_self_test, IMXRNGCState), + VMSTATE_UINT8(op_seed, IMXRNGCState), + VMSTATE_UINT8(mask, IMXRNGCState), + VMSTATE_BOOL(auto_seed, IMXRNGCState), + VMSTATE_END_OF_LIST() + } +}; + +static void imx_rngc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = imx_rngc_realize; + dc->reset = imx_rngc_reset; + dc->desc = RNGC_NAME, + dc->vmsd = &vmstate_imx_rngc; +} + +static const TypeInfo imx_rngc_info = { + .name = TYPE_IMX_RNGC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IMXRNGCState), + .class_init = imx_rngc_class_init, +}; + +static void imx_rngc_register_types(void) +{ + type_register_static(&imx_rngc_info); +} + +type_init(imx_rngc_register_types) diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h index 241efb52ae..1c86bb55fb 100644 --- a/include/hw/arm/fsl-imx25.h +++ b/include/hw/arm/fsl-imx25.h @@ -24,6 +24,7 @@ #include "hw/timer/imx_gpt.h" #include "hw/timer/imx_epit.h" #include "hw/net/imx_fec.h" +#include "hw/misc/imx_rngc.h" #include "hw/i2c/imx_i2c.h" #include "hw/gpio/imx_gpio.h" #include "exec/memory.h" @@ -50,6 +51,7 @@ typedef struct FslIMX25State { IMXGPTState gpt[FSL_IMX25_NUM_GPTS]; IMXEPITState epit[FSL_IMX25_NUM_EPITS]; IMXFECState fec; + IMXRNGCState rngc; IMXI2CState i2c[FSL_IMX25_NUM_I2CS]; IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS]; MemoryRegion rom[2]; @@ -211,6 +213,8 @@ typedef struct FslIMX25State { #define FSL_IMX25_GPIO4_SIZE 0x4000 #define FSL_IMX25_GPIO3_ADDR 0x53FA4000 #define FSL_IMX25_GPIO3_SIZE 0x4000 +#define FSL_IMX25_RNGC_ADDR 0x53FB0000 +#define FSL_IMX25_RNGC_SIZE 0x4000 #define FSL_IMX25_GPIO1_ADDR 0x53FCC000 #define FSL_IMX25_GPIO1_SIZE 0x4000 #define FSL_IMX25_GPIO2_ADDR 0x53FD0000 @@ -238,6 +242,7 @@ typedef struct FslIMX25State { #define FSL_IMX25_EPIT1_IRQ 28 #define FSL_IMX25_EPIT2_IRQ 27 #define FSL_IMX25_FEC_IRQ 57 +#define FSL_IMX25_RNGC_IRQ 22 #define FSL_IMX25_I2C1_IRQ 3 #define FSL_IMX25_I2C2_IRQ 4 #define FSL_IMX25_I2C3_IRQ 10 diff --git a/include/hw/misc/imx_rngc.h b/include/hw/misc/imx_rngc.h new file mode 100644 index 0000000000..f0d2b44d4f --- /dev/null +++ b/include/hw/misc/imx_rngc.h @@ -0,0 +1,35 @@ +/* + * Freescale i.MX RNGC emulation + * + * Copyright (C) 2020 Martin Kaiser + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef IMX_RNGC_H +#define IMX_RNGC_H + +#include "hw/sysbus.h" + +#define TYPE_IMX_RNGC "imx.rngc" +#define IMX_RNGC(obj) OBJECT_CHECK(IMXRNGCState, (obj), TYPE_IMX_RNGC) + +typedef struct IMXRNGCState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion iomem; + + uint8_t op_self_test; + uint8_t op_seed; + uint8_t mask; + bool auto_seed; + + QEMUBH *self_test_bh; + QEMUBH *seed_bh; + qemu_irq irq; +} IMXRNGCState; + +#endif /* IMX_RNGC_H */ From 855532912b0e1bf803ae393e5b0c7e80948cd6a4 Mon Sep 17 00:00:00 2001 From: Jeff Kubascik Date: Fri, 17 Jan 2020 14:09:31 +0000 Subject: [PATCH 12/15] target/arm: adjust program counter for wfi exception in AArch32 The wfi instruction can be configured to be trapped by a higher exception level, such as the EL2 hypervisor. When the instruction is trapped, the program counter should contain the address of the wfi instruction that caused the exception. The program counter is adjusted for this in the wfi op helper function. However, this correction is done to env->pc, which only applies to AArch64 mode. For AArch32, the program counter is stored in env->regs[15]. This adds an if-else statement to modify the correct program counter location based on the the current CPU mode. Signed-off-by: Jeff Kubascik Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell --- target/arm/op_helper.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index e5a346cb87..27d16ad9ad 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -295,7 +295,12 @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len) } if (target_el) { - env->pc -= insn_len; + if (env->aarch64) { + env->pc -= insn_len; + } else { + env->regs[15] -= insn_len; + } + raise_exception(env, EXCP_UDEF, syn_wfx(1, 0xe, 0, insn_len == 2), target_el); } From ef1255212a721e3ebc2be4bec9426bda9d2ee308 Mon Sep 17 00:00:00 2001 From: Jeff Kubascik Date: Fri, 17 Jan 2020 14:09:31 +0000 Subject: [PATCH 13/15] arm/gicv3: update virtual irq state after IAR register read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IAR0/IAR1 register is used to acknowledge an interrupt - a read of the register activates the highest priority pending interrupt and provides its interrupt ID. Activating an interrupt can change the CPU's virtual interrupt state - this change makes sure the virtual irq state is updated. Signed-off-by: Jeff Kubascik Reviewed-by: Philippe Mathieu-Daudé Message-id: 20200113154607.97032-1-jeff.kubascik@dornerworks.com Signed-off-by: Peter Maydell --- hw/intc/arm_gicv3_cpuif.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index a254b0ce87..08e000e33c 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -664,6 +664,9 @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri) trace_gicv3_icv_iar_read(ri->crm == 8 ? 0 : 1, gicv3_redist_affid(cs), intid); + + gicv3_cpuif_virt_update(cs); + return intid; } From 30d544839e278dc76017b9a42990c41e84a34377 Mon Sep 17 00:00:00 2001 From: Jeff Kubascik Date: Fri, 17 Jan 2020 14:09:31 +0000 Subject: [PATCH 14/15] target/arm: Return correct IL bit in merge_syn_data_abort The IL bit is set for 32-bit instructions, thus passing false with the is_16bit parameter to syn_data_abort_with_iss() makes a syn mask that always has the IL bit set. Pass is_16bit as true to make the initial syn mask have IL=0, so that the final IL value comes from or'ing template_syn. Cc: qemu-stable@nongnu.org Fixes: aaa1f954d4ca ("target-arm: A64: Create Instruction Syndromes for Data Aborts") Signed-off-by: Jeff Kubascik Signed-off-by: Richard Henderson Message-id: 20200117004618.2742-2-richard.henderson@linaro.org [rth: Extracted this as a self-contained bug fix from a larger patch] Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/tlb_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c index 5feb312941..e63f8bda29 100644 --- a/target/arm/tlb_helper.c +++ b/target/arm/tlb_helper.c @@ -44,7 +44,7 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn, syn = syn_data_abort_with_iss(same_el, 0, 0, 0, 0, 0, ea, 0, s1ptw, is_write, fsc, - false); + true); /* Merge the runtime syndrome with the template syndrome. */ syn |= template_syn; } From 1a1fbc6cbb34c26d43d8360c66c1d21681af14a9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 17 Jan 2020 14:09:31 +0000 Subject: [PATCH 15/15] target/arm: Set ISSIs16Bit in make_issinfo During the conversion to decodetree, the setting of ISSIs16Bit got lost. This causes the guest os to incorrectly adjust trapping memory operations. Cc: qemu-stable@nongnu.org Fixes: 46beb58efbb8a2a32 ("target/arm: Convert T16, load (literal)") Reported-by: Jeff Kubascik Signed-off-by: Richard Henderson Message-id: 20200117004618.2742-3-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/translate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/arm/translate.c b/target/arm/translate.c index 0c8624fb42..2f4aea927f 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -8556,6 +8556,9 @@ static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w) /* ISS not valid if writeback */ if (p && !w) { ret = rd; + if (s->base.pc_next - s->pc_curr == 2) { + ret |= ISSIs16Bit; + } } else { ret = ISSInvalid; }