123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- /*
- * ARMV7M System emulation.
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
- #include "qemu/osdep.h"
- #include "hw/arm/armv7m.h"
- #include "qapi/error.h"
- #include "hw/sysbus.h"
- #include "hw/arm/boot.h"
- #include "hw/loader.h"
- #include "hw/qdev-properties.h"
- #include "hw/qdev-clock.h"
- #include "elf.h"
- #include "system/reset.h"
- #include "qemu/error-report.h"
- #include "qemu/module.h"
- #include "qemu/log.h"
- #include "target/arm/idau.h"
- #include "target/arm/cpu.h"
- #include "target/arm/cpu-features.h"
- #include "target/arm/cpu-qom.h"
- #include "migration/vmstate.h"
- /* Bitbanded IO. Each word corresponds to a single bit. */
- /* Get the byte address of the real memory for a bitband access. */
- static inline hwaddr bitband_addr(BitBandState *s, hwaddr offset)
- {
- return s->base | (offset & 0x1ffffff) >> 5;
- }
- static MemTxResult bitband_read(void *opaque, hwaddr offset,
- uint64_t *data, unsigned size, MemTxAttrs attrs)
- {
- BitBandState *s = opaque;
- uint8_t buf[4];
- MemTxResult res;
- int bitpos, bit;
- hwaddr addr;
- assert(size <= 4);
- /* Find address in underlying memory and round down to multiple of size */
- addr = bitband_addr(s, offset) & (-size);
- res = address_space_read(&s->source_as, addr, attrs, buf, size);
- if (res) {
- return res;
- }
- /* Bit position in the N bytes read... */
- bitpos = (offset >> 2) & ((size * 8) - 1);
- /* ...converted to byte in buffer and bit in byte */
- bit = (buf[bitpos >> 3] >> (bitpos & 7)) & 1;
- *data = bit;
- return MEMTX_OK;
- }
- static MemTxResult bitband_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size, MemTxAttrs attrs)
- {
- BitBandState *s = opaque;
- uint8_t buf[4];
- MemTxResult res;
- int bitpos, bit;
- hwaddr addr;
- assert(size <= 4);
- /* Find address in underlying memory and round down to multiple of size */
- addr = bitband_addr(s, offset) & (-size);
- res = address_space_read(&s->source_as, addr, attrs, buf, size);
- if (res) {
- return res;
- }
- /* Bit position in the N bytes read... */
- bitpos = (offset >> 2) & ((size * 8) - 1);
- /* ...converted to byte in buffer and bit in byte */
- bit = 1 << (bitpos & 7);
- if (value & 1) {
- buf[bitpos >> 3] |= bit;
- } else {
- buf[bitpos >> 3] &= ~bit;
- }
- return address_space_write(&s->source_as, addr, attrs, buf, size);
- }
- static const MemoryRegionOps bitband_ops = {
- .read_with_attrs = bitband_read,
- .write_with_attrs = bitband_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .impl.min_access_size = 1,
- .impl.max_access_size = 4,
- .valid.min_access_size = 1,
- .valid.max_access_size = 4,
- };
- static void bitband_init(Object *obj)
- {
- BitBandState *s = BITBAND(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- memory_region_init_io(&s->iomem, obj, &bitband_ops, s,
- "bitband", 0x02000000);
- sysbus_init_mmio(dev, &s->iomem);
- }
- static void bitband_realize(DeviceState *dev, Error **errp)
- {
- BitBandState *s = BITBAND(dev);
- if (!s->source_memory) {
- error_setg(errp, "source-memory property not set");
- return;
- }
- address_space_init(&s->source_as, s->source_memory, "bitband-source");
- }
- /* Board init. */
- static const hwaddr bitband_input_addr[ARMV7M_NUM_BITBANDS] = {
- 0x20000000, 0x40000000
- };
- static const hwaddr bitband_output_addr[ARMV7M_NUM_BITBANDS] = {
- 0x22000000, 0x42000000
- };
- static MemTxResult v7m_sysreg_ns_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size,
- MemTxAttrs attrs)
- {
- MemoryRegion *mr = opaque;
- if (attrs.secure) {
- /* S accesses to the alias act like NS accesses to the real region */
- attrs.secure = 0;
- return memory_region_dispatch_write(mr, addr, value,
- size_memop(size) | MO_LE, attrs);
- } else {
- /* NS attrs are RAZ/WI for privileged, and BusFault for user */
- if (attrs.user) {
- return MEMTX_ERROR;
- }
- return MEMTX_OK;
- }
- }
- static MemTxResult v7m_sysreg_ns_read(void *opaque, hwaddr addr,
- uint64_t *data, unsigned size,
- MemTxAttrs attrs)
- {
- MemoryRegion *mr = opaque;
- if (attrs.secure) {
- /* S accesses to the alias act like NS accesses to the real region */
- attrs.secure = 0;
- return memory_region_dispatch_read(mr, addr, data,
- size_memop(size) | MO_LE, attrs);
- } else {
- /* NS attrs are RAZ/WI for privileged, and BusFault for user */
- if (attrs.user) {
- return MEMTX_ERROR;
- }
- *data = 0;
- return MEMTX_OK;
- }
- }
- static const MemoryRegionOps v7m_sysreg_ns_ops = {
- .read_with_attrs = v7m_sysreg_ns_read,
- .write_with_attrs = v7m_sysreg_ns_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- };
- static MemTxResult v7m_systick_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size,
- MemTxAttrs attrs)
- {
- ARMv7MState *s = opaque;
- MemoryRegion *mr;
- /* Direct the access to the correct systick */
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 0);
- return memory_region_dispatch_write(mr, addr, value,
- size_memop(size) | MO_LE, attrs);
- }
- static MemTxResult v7m_systick_read(void *opaque, hwaddr addr,
- uint64_t *data, unsigned size,
- MemTxAttrs attrs)
- {
- ARMv7MState *s = opaque;
- MemoryRegion *mr;
- /* Direct the access to the correct systick */
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 0);
- return memory_region_dispatch_read(mr, addr, data,
- size_memop(size) | MO_LE, attrs);
- }
- static const MemoryRegionOps v7m_systick_ops = {
- .read_with_attrs = v7m_systick_read,
- .write_with_attrs = v7m_systick_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- };
- /*
- * Unassigned portions of the PPB space are RAZ/WI for privileged
- * accesses, and fault for non-privileged accesses.
- */
- static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
- uint64_t *data, unsigned size,
- MemTxAttrs attrs)
- {
- qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
- (uint32_t)addr);
- if (attrs.user) {
- return MEMTX_ERROR;
- }
- *data = 0;
- return MEMTX_OK;
- }
- static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size,
- MemTxAttrs attrs)
- {
- qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
- (uint32_t)addr);
- if (attrs.user) {
- return MEMTX_ERROR;
- }
- return MEMTX_OK;
- }
- static const MemoryRegionOps ppb_default_ops = {
- .read_with_attrs = ppb_default_read,
- .write_with_attrs = ppb_default_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid.min_access_size = 1,
- .valid.max_access_size = 8,
- };
- static void armv7m_instance_init(Object *obj)
- {
- ARMv7MState *s = ARMV7M(obj);
- int i;
- /* Can't init the cpu here, we don't yet know which model to use */
- memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
- object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
- object_property_add_alias(obj, "num-irq",
- OBJECT(&s->nvic), "num-irq");
- object_property_add_alias(obj, "num-prio-bits",
- OBJECT(&s->nvic), "num-prio-bits");
- object_initialize_child(obj, "systick-reg-ns", &s->systick[M_REG_NS],
- TYPE_SYSTICK);
- /*
- * We can't initialize the secure systick here, as we don't know
- * yet if we need it.
- */
- for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
- object_initialize_child(obj, "bitband[*]", &s->bitband[i],
- TYPE_BITBAND);
- }
- s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
- s->cpuclk = qdev_init_clock_in(DEVICE(obj), "cpuclk", NULL, NULL, 0);
- }
- static void armv7m_realize(DeviceState *dev, Error **errp)
- {
- ARMv7MState *s = ARMV7M(dev);
- SysBusDevice *sbd;
- Error *err = NULL;
- int i;
- if (!s->board_memory) {
- error_setg(errp, "memory property was not set");
- return;
- }
- /* cpuclk must be connected; refclk is optional */
- if (!clock_has_source(s->cpuclk)) {
- error_setg(errp, "armv7m: cpuclk must be connected");
- return;
- }
- memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
- s->cpu = ARM_CPU(object_new_with_props(s->cpu_type, OBJECT(s), "cpu",
- &err, NULL));
- if (err != NULL) {
- error_propagate(errp, err);
- return;
- }
- object_property_set_link(OBJECT(s->cpu), "memory", OBJECT(&s->container),
- &error_abort);
- if (object_property_find(OBJECT(s->cpu), "idau")) {
- object_property_set_link(OBJECT(s->cpu), "idau", s->idau,
- &error_abort);
- }
- if (object_property_find(OBJECT(s->cpu), "init-svtor")) {
- if (!object_property_set_uint(OBJECT(s->cpu), "init-svtor",
- s->init_svtor, errp)) {
- return;
- }
- }
- if (object_property_find(OBJECT(s->cpu), "init-nsvtor")) {
- if (!object_property_set_uint(OBJECT(s->cpu), "init-nsvtor",
- s->init_nsvtor, errp)) {
- return;
- }
- }
- if (object_property_find(OBJECT(s->cpu), "vfp")) {
- if (!object_property_set_bool(OBJECT(s->cpu), "vfp", s->vfp, errp)) {
- return;
- }
- }
- if (object_property_find(OBJECT(s->cpu), "dsp")) {
- if (!object_property_set_bool(OBJECT(s->cpu), "dsp", s->dsp, errp)) {
- return;
- }
- }
- object_property_set_bool(OBJECT(s->cpu), "start-powered-off",
- s->start_powered_off, &error_abort);
- /*
- * Real M-profile hardware can be configured with a different number of
- * MPU regions for Secure vs NonSecure. QEMU's CPU implementation doesn't
- * support that yet, so catch attempts to select that.
- */
- if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) &&
- s->mpu_ns_regions != s->mpu_s_regions) {
- error_setg(errp,
- "mpu-ns-regions and mpu-s-regions properties must have the same value");
- return;
- }
- if (s->mpu_ns_regions != UINT_MAX &&
- object_property_find(OBJECT(s->cpu), "pmsav7-dregion")) {
- if (!object_property_set_uint(OBJECT(s->cpu), "pmsav7-dregion",
- s->mpu_ns_regions, errp)) {
- return;
- }
- }
- /*
- * Tell the CPU where the NVIC is; it will fail realize if it doesn't
- * have one. Similarly, tell the NVIC where its CPU is.
- */
- s->cpu->env.nvic = &s->nvic;
- s->nvic.cpu = s->cpu;
- if (!qdev_realize(DEVICE(s->cpu), NULL, errp)) {
- return;
- }
- /* Note that we must realize the NVIC after the CPU */
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->nvic), errp)) {
- return;
- }
- /* Alias the NVIC's input and output GPIOs as our own so the board
- * code can wire them up. (We do this in realize because the
- * NVIC doesn't create the input GPIO array until realize.)
- */
- qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
- qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
- qdev_pass_gpios(DEVICE(&s->nvic), dev, "NMI");
- /*
- * We map various devices into the container MR at their architected
- * addresses. In particular, we map everything corresponding to the
- * "System PPB" space. This is the range from 0xe0000000 to 0xe00fffff
- * and includes the NVIC, the System Control Space (system registers),
- * the systick timer, and for CPUs with the Security extension an NS
- * banked version of all of these.
- *
- * The default behaviour for unimplemented registers/ranges
- * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
- * is to RAZ/WI for privileged access and BusFault for non-privileged
- * access.
- *
- * The NVIC and System Control Space (SCS) starts at 0xe000e000
- * and looks like this:
- * 0x004 - ICTR
- * 0x010 - 0xff - systick
- * 0x100..0x7ec - NVIC
- * 0x7f0..0xcff - Reserved
- * 0xd00..0xd3c - SCS registers
- * 0xd40..0xeff - Reserved or Not implemented
- * 0xf00 - STIR
- *
- * Some registers within this space are banked between security states.
- * In v8M there is a second range 0xe002e000..0xe002efff which is the
- * NonSecure alias SCS; secure accesses to this behave like NS accesses
- * to the main SCS range, and non-secure accesses (including when
- * the security extension is not implemented) are RAZ/WI.
- * Note that both the main SCS range and the alias range are defined
- * to be exempt from memory attribution (R_BLJT) and so the memory
- * transaction attribute always matches the current CPU security
- * state (attrs.secure == env->v7m.secure). In the v7m_sysreg_ns_ops
- * wrappers we change attrs.secure to indicate the NS access; so
- * generally code determining which banked register to use should
- * use attrs.secure; code determining actual behaviour of the system
- * should use env->v7m.secure.
- *
- * Within the PPB space, some MRs overlap, and the priority
- * of overlapping regions is:
- * - default region (for RAZ/WI and BusFault) : -1
- * - system register regions (provided by the NVIC) : 0
- * - systick : 1
- * This is because the systick device is a small block of registers
- * in the middle of the other system control registers.
- */
- memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
- "nvic-default", 0x100000);
- memory_region_add_subregion_overlap(&s->container, 0xe0000000,
- &s->defaultmem, -1);
- /* Wire the NVIC up to the CPU */
- sbd = SYS_BUS_DEVICE(&s->nvic);
- sysbus_connect_irq(sbd, 0,
- qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
- memory_region_add_subregion(&s->container, 0xe000e000,
- sysbus_mmio_get_region(sbd, 0));
- if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
- /* Create the NS alias region for the NVIC sysregs */
- memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
- &v7m_sysreg_ns_ops,
- sysbus_mmio_get_region(sbd, 0),
- "nvic_sysregs_ns", 0x1000);
- memory_region_add_subregion(&s->container, 0xe002e000,
- &s->sysreg_ns_mem);
- }
- /*
- * Create and map the systick devices. Note that we only connect
- * refclk if it has been connected to us; otherwise the systick
- * device gets the wrong answer for clock_has_source(refclk), because
- * it has an immediate source (the ARMv7M's clock object) but not
- * an ultimate source, and then it won't correctly auto-select the
- * CPU clock as its only possible clock source.
- */
- if (clock_has_source(s->refclk)) {
- qdev_connect_clock_in(DEVICE(&s->systick[M_REG_NS]), "refclk",
- s->refclk);
- }
- qdev_connect_clock_in(DEVICE(&s->systick[M_REG_NS]), "cpuclk", s->cpuclk);
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), errp)) {
- return;
- }
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), 0,
- qdev_get_gpio_in_named(DEVICE(&s->nvic),
- "systick-trigger", M_REG_NS));
- if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY)) {
- /*
- * We couldn't init the secure systick device in instance_init
- * as we didn't know then if the CPU had the security extensions;
- * so we have to do it here.
- */
- object_initialize_child(OBJECT(dev), "systick-reg-s",
- &s->systick[M_REG_S], TYPE_SYSTICK);
- if (clock_has_source(s->refclk)) {
- qdev_connect_clock_in(DEVICE(&s->systick[M_REG_S]), "refclk",
- s->refclk);
- }
- qdev_connect_clock_in(DEVICE(&s->systick[M_REG_S]), "cpuclk",
- s->cpuclk);
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_S]), errp)) {
- return;
- }
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_S]), 0,
- qdev_get_gpio_in_named(DEVICE(&s->nvic),
- "systick-trigger", M_REG_S));
- }
- memory_region_init_io(&s->systickmem, OBJECT(s),
- &v7m_systick_ops, s,
- "v7m_systick", 0xe0);
- memory_region_add_subregion_overlap(&s->container, 0xe000e010,
- &s->systickmem, 1);
- if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
- memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
- &v7m_sysreg_ns_ops, &s->systickmem,
- "v7m_systick_ns", 0xe0);
- memory_region_add_subregion_overlap(&s->container, 0xe002e010,
- &s->systick_ns_mem, 1);
- }
- /* If the CPU has RAS support, create the RAS register block */
- if (cpu_isar_feature(aa32_ras, s->cpu)) {
- object_initialize_child(OBJECT(dev), "armv7m-ras",
- &s->ras, TYPE_ARMV7M_RAS);
- sbd = SYS_BUS_DEVICE(&s->ras);
- if (!sysbus_realize(sbd, errp)) {
- return;
- }
- memory_region_add_subregion_overlap(&s->container, 0xe0005000,
- sysbus_mmio_get_region(sbd, 0), 1);
- }
- for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
- if (s->enable_bitband) {
- Object *obj = OBJECT(&s->bitband[i]);
- sbd = SYS_BUS_DEVICE(&s->bitband[i]);
- if (!object_property_set_int(obj, "base",
- bitband_input_addr[i], errp)) {
- return;
- }
- object_property_set_link(obj, "source-memory",
- OBJECT(s->board_memory), &error_abort);
- if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) {
- return;
- }
- memory_region_add_subregion(&s->container, bitband_output_addr[i],
- sysbus_mmio_get_region(sbd, 0));
- } else {
- object_unparent(OBJECT(&s->bitband[i]));
- }
- }
- }
- static const Property armv7m_properties[] = {
- DEFINE_PROP_STRING("cpu-type", ARMv7MState, cpu_type),
- DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
- MemoryRegion *),
- DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
- DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
- DEFINE_PROP_UINT32("init-nsvtor", ARMv7MState, init_nsvtor, 0),
- DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
- DEFINE_PROP_BOOL("start-powered-off", ARMv7MState, start_powered_off,
- false),
- DEFINE_PROP_BOOL("vfp", ARMv7MState, vfp, true),
- DEFINE_PROP_BOOL("dsp", ARMv7MState, dsp, true),
- DEFINE_PROP_UINT32("mpu-ns-regions", ARMv7MState, mpu_ns_regions, UINT_MAX),
- DEFINE_PROP_UINT32("mpu-s-regions", ARMv7MState, mpu_s_regions, UINT_MAX),
- };
- static const VMStateDescription vmstate_armv7m = {
- .name = "armv7m",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (const VMStateField[]) {
- VMSTATE_CLOCK(refclk, ARMv7MState),
- VMSTATE_CLOCK(cpuclk, ARMv7MState),
- VMSTATE_END_OF_LIST()
- }
- };
- static void armv7m_class_init(ObjectClass *klass, void *data)
- {
- DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = armv7m_realize;
- dc->vmsd = &vmstate_armv7m;
- device_class_set_props(dc, armv7m_properties);
- }
- static const TypeInfo armv7m_info = {
- .name = TYPE_ARMV7M,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(ARMv7MState),
- .instance_init = armv7m_instance_init,
- .class_init = armv7m_class_init,
- };
- static void armv7m_reset(void *opaque)
- {
- ARMCPU *cpu = opaque;
- cpu_reset(CPU(cpu));
- }
- void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename,
- hwaddr mem_base, int mem_size)
- {
- ssize_t image_size;
- uint64_t entry;
- AddressSpace *as;
- int asidx;
- CPUState *cs = CPU(cpu);
- if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
- asidx = ARMASIdx_S;
- } else {
- asidx = ARMASIdx_NS;
- }
- as = cpu_get_address_space(cs, asidx);
- if (kernel_filename) {
- image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
- &entry, NULL, NULL,
- NULL, ELFDATA2LSB, EM_ARM, 1, 0, as);
- if (image_size < 0) {
- image_size = load_image_targphys_as(kernel_filename, mem_base,
- mem_size, as);
- }
- if (image_size < 0) {
- error_report("Could not load kernel '%s'", kernel_filename);
- exit(1);
- }
- }
- /* CPU objects (unlike devices) are not automatically reset on system
- * reset, so we must always register a handler to do so. Unlike
- * A-profile CPUs, we don't need to do anything special in the
- * handler to arrange that it starts correctly.
- * This is arguably the wrong place to do this, but it matches the
- * way A-profile does it. Note that this means that every M profile
- * board must call this function!
- */
- qemu_register_reset(armv7m_reset, cpu);
- }
- static const Property bitband_properties[] = {
- DEFINE_PROP_UINT32("base", BitBandState, base, 0),
- DEFINE_PROP_LINK("source-memory", BitBandState, source_memory,
- TYPE_MEMORY_REGION, MemoryRegion *),
- };
- static void bitband_class_init(ObjectClass *klass, void *data)
- {
- DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = bitband_realize;
- device_class_set_props(dc, bitband_properties);
- }
- static const TypeInfo bitband_info = {
- .name = TYPE_BITBAND,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(BitBandState),
- .instance_init = bitband_init,
- .class_init = bitband_class_init,
- };
- static void armv7m_register_types(void)
- {
- type_register_static(&bitband_info);
- type_register_static(&armv7m_info);
- }
- type_init(armv7m_register_types)
|