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
);
134 static void armv7m_bitband_init(void)
138 dev
= qdev_create(NULL
, TYPE_BITBAND
);
139 qdev_prop_set_uint32(dev
, "base", 0x20000000);
140 qdev_init_nofail(dev
);
141 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, 0x22000000);
143 dev
= qdev_create(NULL
, TYPE_BITBAND
);
144 qdev_prop_set_uint32(dev
, "base", 0x40000000);
145 qdev_init_nofail(dev
);
146 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, 0x42000000);
151 static const hwaddr bitband_input_addr
[ARMV7M_NUM_BITBANDS
] = {
152 0x20000000, 0x40000000
155 static const hwaddr bitband_output_addr
[ARMV7M_NUM_BITBANDS
] = {
156 0x22000000, 0x42000000
159 static void armv7m_instance_init(Object
*obj
)
161 ARMv7MState
*s
= ARMV7M(obj
);
164 /* Can't init the cpu here, we don't yet know which model to use */
166 object_initialize(&s
->nvic
, sizeof(s
->nvic
), "armv7m_nvic");
167 qdev_set_parent_bus(DEVICE(&s
->nvic
), sysbus_get_default());
168 object_property_add_alias(obj
, "num-irq",
169 OBJECT(&s
->nvic
), "num-irq", &error_abort
);
171 for (i
= 0; i
< ARRAY_SIZE(s
->bitband
); i
++) {
172 object_initialize(&s
->bitband
[i
], sizeof(s
->bitband
[i
]), TYPE_BITBAND
);
173 qdev_set_parent_bus(DEVICE(&s
->bitband
[i
]), sysbus_get_default());
177 static void armv7m_realize(DeviceState
*dev
, Error
**errp
)
179 ARMv7MState
*s
= ARMV7M(dev
);
184 const char *typename
;
187 cpustr
= g_strsplit(s
->cpu_model
, ",", 2);
189 oc
= cpu_class_by_name(TYPE_ARM_CPU
, cpustr
[0]);
191 error_setg(errp
, "Unknown CPU model %s", cpustr
[0]);
197 typename
= object_class_get_name(oc
);
198 cc
->parse_features(typename
, cpustr
[1], &err
);
201 error_propagate(errp
, err
);
205 s
->cpu
= ARM_CPU(object_new(typename
));
207 error_setg(errp
, "Unknown CPU model %s", s
->cpu_model
);
211 object_property_set_bool(OBJECT(s
->cpu
), true, "realized", &err
);
213 error_propagate(errp
, err
);
217 /* Note that we must realize the NVIC after the CPU */
218 object_property_set_bool(OBJECT(&s
->nvic
), true, "realized", &err
);
220 error_propagate(errp
, err
);
224 /* Alias the NVIC's input and output GPIOs as our own so the board
225 * code can wire them up. (We do this in realize because the
226 * NVIC doesn't create the input GPIO array until realize.)
228 qdev_pass_gpios(DEVICE(&s
->nvic
), dev
, NULL
);
229 qdev_pass_gpios(DEVICE(&s
->nvic
), dev
, "SYSRESETREQ");
231 /* Wire the NVIC up to the CPU */
232 sysbus_connect_irq(SYS_BUS_DEVICE(&s
->nvic
), 0,
233 qdev_get_gpio_in(DEVICE(s
->cpu
), ARM_CPU_IRQ
));
234 s
->cpu
->env
.nvic
= &s
->nvic
;
236 for (i
= 0; i
< ARRAY_SIZE(s
->bitband
); i
++) {
237 Object
*obj
= OBJECT(&s
->bitband
[i
]);
238 SysBusDevice
*sbd
= SYS_BUS_DEVICE(&s
->bitband
[i
]);
240 object_property_set_int(obj
, bitband_input_addr
[i
], "base", &err
);
242 error_propagate(errp
, err
);
245 object_property_set_bool(obj
, true, "realized", &err
);
247 error_propagate(errp
, err
);
251 sysbus_mmio_map(sbd
, 0, bitband_output_addr
[i
]);
255 static Property armv7m_properties
[] = {
256 DEFINE_PROP_STRING("cpu-model", ARMv7MState
, cpu_model
),
257 DEFINE_PROP_END_OF_LIST(),
260 static void armv7m_class_init(ObjectClass
*klass
, void *data
)
262 DeviceClass
*dc
= DEVICE_CLASS(klass
);
264 dc
->realize
= armv7m_realize
;
265 dc
->props
= armv7m_properties
;
268 static const TypeInfo armv7m_info
= {
270 .parent
= TYPE_SYS_BUS_DEVICE
,
271 .instance_size
= sizeof(ARMv7MState
),
272 .instance_init
= armv7m_instance_init
,
273 .class_init
= armv7m_class_init
,
276 static void armv7m_reset(void *opaque
)
278 ARMCPU
*cpu
= opaque
;
283 /* Init CPU and memory for a v7-M based board.
284 mem_size is in bytes.
285 Returns the NVIC array. */
287 DeviceState
*armv7m_init(MemoryRegion
*system_memory
, int mem_size
, int num_irq
,
288 const char *kernel_filename
, const char *cpu_model
)
294 if (cpu_model
== NULL
) {
295 cpu_model
= "cortex-m3";
297 cpu
= cpu_arm_init(cpu_model
);
299 fprintf(stderr
, "Unable to find CPU definition\n");
304 armv7m_bitband_init();
306 nvic
= qdev_create(NULL
, "armv7m_nvic");
307 qdev_prop_set_uint32(nvic
, "num-irq", num_irq
);
309 qdev_init_nofail(nvic
);
310 sysbus_connect_irq(SYS_BUS_DEVICE(nvic
), 0,
311 qdev_get_gpio_in(DEVICE(cpu
), ARM_CPU_IRQ
));
312 armv7m_load_kernel(cpu
, kernel_filename
, mem_size
);
316 void armv7m_load_kernel(ARMCPU
*cpu
, const char *kernel_filename
, int mem_size
)
323 #ifdef TARGET_WORDS_BIGENDIAN
329 if (!kernel_filename
&& !qtest_enabled()) {
330 fprintf(stderr
, "Guest image must be specified (using -kernel)\n");
334 if (kernel_filename
) {
335 image_size
= load_elf(kernel_filename
, NULL
, NULL
, &entry
, &lowaddr
,
336 NULL
, big_endian
, EM_ARM
, 1, 0);
337 if (image_size
< 0) {
338 image_size
= load_image_targphys(kernel_filename
, 0, mem_size
);
341 if (image_size
< 0) {
342 error_report("Could not load kernel '%s'", kernel_filename
);
347 /* CPU objects (unlike devices) are not automatically reset on system
348 * reset, so we must always register a handler to do so. Unlike
349 * A-profile CPUs, we don't need to do anything special in the
350 * handler to arrange that it starts correctly.
351 * This is arguably the wrong place to do this, but it matches the
352 * way A-profile does it. Note that this means that every M profile
353 * board must call this function!
355 qemu_register_reset(armv7m_reset
, cpu
);
358 static Property bitband_properties
[] = {
359 DEFINE_PROP_UINT32("base", BitBandState
, base
, 0),
360 DEFINE_PROP_END_OF_LIST(),
363 static void bitband_class_init(ObjectClass
*klass
, void *data
)
365 DeviceClass
*dc
= DEVICE_CLASS(klass
);
367 dc
->props
= bitband_properties
;
370 static const TypeInfo bitband_info
= {
371 .name
= TYPE_BITBAND
,
372 .parent
= TYPE_SYS_BUS_DEVICE
,
373 .instance_size
= sizeof(BitBandState
),
374 .instance_init
= bitband_init
,
375 .class_init
= bitband_class_init
,
378 static void armv7m_register_types(void)
380 type_register_static(&bitband_info
);
381 type_register_static(&armv7m_info
);
384 type_init(armv7m_register_types
)