2 * ARMV7M System emulation.
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licensed under the GPL.
10 #include "qemu/osdep.h"
11 #include "hw/arm/armv7m.h"
12 #include "qapi/error.h"
13 #include "qemu-common.h"
15 #include "hw/sysbus.h"
16 #include "hw/arm/arm.h"
17 #include "hw/loader.h"
19 #include "sysemu/qtest.h"
20 #include "qemu/error-report.h"
22 /* Bitbanded IO. Each word corresponds to a single bit. */
24 /* Get the byte address of the real memory for a bitband access. */
25 static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
29 res = *(uint32_t *)opaque;
30 res |= (addr & 0x1ffffff) >> 5;
35 static uint32_t bitband_readb(void *opaque, hwaddr offset)
38 cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
39 return (v & (1 << ((offset >> 2) & 7))) != 0;
42 static void bitband_writeb(void *opaque, hwaddr offset,
48 addr = bitband_addr(opaque, offset);
49 mask = (1 << ((offset >> 2) & 7));
50 cpu_physical_memory_read(addr, &v, 1);
55 cpu_physical_memory_write(addr, &v, 1);
58 static uint32_t bitband_readw(void *opaque, hwaddr offset)
63 addr = bitband_addr(opaque, offset) & ~1;
64 mask = (1 << ((offset >> 2) & 15));
66 cpu_physical_memory_read(addr, &v, 2);
67 return (v & mask) != 0;
70 static void bitband_writew(void *opaque, hwaddr offset,
76 addr = bitband_addr(opaque, offset) & ~1;
77 mask = (1 << ((offset >> 2) & 15));
79 cpu_physical_memory_read(addr, &v, 2);
84 cpu_physical_memory_write(addr, &v, 2);
87 static uint32_t bitband_readl(void *opaque, hwaddr offset)
92 addr = bitband_addr(opaque, offset) & ~3;
93 mask = (1 << ((offset >> 2) & 31));
95 cpu_physical_memory_read(addr, &v, 4);
96 return (v & mask) != 0;
99 static void bitband_writel(void *opaque, hwaddr offset,
105 addr = bitband_addr(opaque, offset) & ~3;
106 mask = (1 << ((offset >> 2) & 31));
107 mask = tswap32(mask);
108 cpu_physical_memory_read(addr, &v, 4);
113 cpu_physical_memory_write(addr, &v, 4);
116 static const MemoryRegionOps bitband_ops = {
118 .read = { bitband_readb, bitband_readw, bitband_readl, },
119 .write = { bitband_writeb, bitband_writew, bitband_writel, },
121 .endianness = DEVICE_NATIVE_ENDIAN,
124 static void bitband_init(Object *obj)
126 BitBandState *s = BITBAND(obj);
127 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
129 memory_region_init_io(&s->iomem, obj, &bitband_ops, &s->base,
130 "bitband", 0x02000000);
131 sysbus_init_mmio(dev, &s->iomem);
136 static const hwaddr bitband_input_addr[ARMV7M_NUM_BITBANDS] = {
137 0x20000000, 0x40000000
140 static const hwaddr bitband_output_addr[ARMV7M_NUM_BITBANDS] = {
141 0x22000000, 0x42000000
144 static void armv7m_instance_init(Object *obj)
146 ARMv7MState *s = ARMV7M(obj);
149 /* Can't init the cpu here, we don't yet know which model to use */
151 object_initialize(&s->nvic, sizeof(s->nvic), "armv7m_nvic");
152 qdev_set_parent_bus(DEVICE(&s->nvic), sysbus_get_default());
153 object_property_add_alias(obj, "num-irq",
154 OBJECT(&s->nvic), "num-irq", &error_abort);
156 for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
157 object_initialize(&s->bitband[i], sizeof(s->bitband[i]), TYPE_BITBAND);
158 qdev_set_parent_bus(DEVICE(&s->bitband[i]), sysbus_get_default());
162 static void armv7m_realize(DeviceState *dev, Error **errp)
164 ARMv7MState *s = ARMV7M(dev);
169 const char *typename;
172 cpustr = g_strsplit(s->cpu_model, ",", 2);
174 oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
176 error_setg(errp, "Unknown CPU model %s", cpustr[0]);
182 typename = object_class_get_name(oc);
183 cc->parse_features(typename, cpustr[1], &err);
186 error_propagate(errp, err);
190 s->cpu = ARM_CPU(object_new(typename));
192 error_setg(errp, "Unknown CPU model %s", s->cpu_model);
196 object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
198 error_propagate(errp, err);
202 /* Note that we must realize the NVIC after the CPU */
203 object_property_set_bool(OBJECT(&s->nvic), true, "realized", &err);
205 error_propagate(errp, err);
209 /* Alias the NVIC's input and output GPIOs as our own so the board
210 * code can wire them up. (We do this in realize because the
211 * NVIC doesn't create the input GPIO array until realize.)
213 qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
214 qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
216 /* Wire the NVIC up to the CPU */
217 sysbus_connect_irq(SYS_BUS_DEVICE(&s->nvic), 0,
218 qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
219 s->cpu->env.nvic = &s->nvic;
221 for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
222 Object *obj = OBJECT(&s->bitband[i]);
223 SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]);
225 object_property_set_int(obj, bitband_input_addr[i], "base", &err);
227 error_propagate(errp, err);
230 object_property_set_bool(obj, true, "realized", &err);
232 error_propagate(errp, err);
236 sysbus_mmio_map(sbd, 0, bitband_output_addr[i]);
240 static Property armv7m_properties[] = {
241 DEFINE_PROP_STRING("cpu-model", ARMv7MState, cpu_model),
242 DEFINE_PROP_END_OF_LIST(),
245 static void armv7m_class_init(ObjectClass *klass, void *data)
247 DeviceClass *dc = DEVICE_CLASS(klass);
249 dc->realize = armv7m_realize;
250 dc->props = armv7m_properties;
253 static const TypeInfo armv7m_info = {
255 .parent = TYPE_SYS_BUS_DEVICE,
256 .instance_size = sizeof(ARMv7MState),
257 .instance_init = armv7m_instance_init,
258 .class_init = armv7m_class_init,
261 static void armv7m_reset(void *opaque)
263 ARMCPU *cpu = opaque;
268 /* Init CPU and memory for a v7-M based board.
269 mem_size is in bytes.
270 Returns the ARMv7M device. */
272 DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
273 const char *kernel_filename, const char *cpu_model)
277 if (cpu_model == NULL) {
278 cpu_model = "cortex-m3";
281 armv7m = qdev_create(NULL, "armv7m");
282 qdev_prop_set_uint32(armv7m, "num-irq", num_irq);
283 qdev_prop_set_string(armv7m, "cpu-model", cpu_model);
284 /* This will exit with an error if the user passed us a bad cpu_model */
285 qdev_init_nofail(armv7m);
287 armv7m_load_kernel(ARM_CPU(first_cpu), kernel_filename, mem_size);
291 void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
298 #ifdef TARGET_WORDS_BIGENDIAN
304 if (!kernel_filename && !qtest_enabled()) {
305 fprintf(stderr, "Guest image must be specified (using -kernel)\n");
309 if (kernel_filename) {
310 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
311 NULL, big_endian, EM_ARM, 1, 0);
312 if (image_size < 0) {
313 image_size = load_image_targphys(kernel_filename, 0, mem_size);
316 if (image_size < 0) {
317 error_report("Could not load kernel '%s'", kernel_filename);
322 /* CPU objects (unlike devices) are not automatically reset on system
323 * reset, so we must always register a handler to do so. Unlike
324 * A-profile CPUs, we don't need to do anything special in the
325 * handler to arrange that it starts correctly.
326 * This is arguably the wrong place to do this, but it matches the
327 * way A-profile does it. Note that this means that every M profile
328 * board must call this function!
330 qemu_register_reset(armv7m_reset, cpu);
333 static Property bitband_properties[] = {
334 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
335 DEFINE_PROP_END_OF_LIST(),
338 static void bitband_class_init(ObjectClass *klass, void *data)
340 DeviceClass *dc = DEVICE_CLASS(klass);
342 dc->props = bitband_properties;
345 static const TypeInfo bitband_info = {
346 .name = TYPE_BITBAND,
347 .parent = TYPE_SYS_BUS_DEVICE,
348 .instance_size = sizeof(BitBandState),
349 .instance_init = bitband_init,
350 .class_init = bitband_class_init,
353 static void armv7m_register_types(void)
355 type_register_static(&bitband_info);
356 type_register_static(&armv7m_info);
359 type_init(armv7m_register_types)