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"
21 #include "exec/address-spaces.h"
23 /* Bitbanded IO. Each word corresponds to a single bit. */
25 /* Get the byte address of the real memory for a bitband access. */
26 static inline uint32_t bitband_addr(void * opaque
, uint32_t addr
)
30 res
= *(uint32_t *)opaque
;
31 res
|= (addr
& 0x1ffffff) >> 5;
36 static uint32_t bitband_readb(void *opaque
, hwaddr offset
)
39 cpu_physical_memory_read(bitband_addr(opaque
, offset
), &v
, 1);
40 return (v
& (1 << ((offset
>> 2) & 7))) != 0;
43 static void bitband_writeb(void *opaque
, hwaddr offset
,
49 addr
= bitband_addr(opaque
, offset
);
50 mask
= (1 << ((offset
>> 2) & 7));
51 cpu_physical_memory_read(addr
, &v
, 1);
56 cpu_physical_memory_write(addr
, &v
, 1);
59 static uint32_t bitband_readw(void *opaque
, hwaddr offset
)
64 addr
= bitband_addr(opaque
, offset
) & ~1;
65 mask
= (1 << ((offset
>> 2) & 15));
67 cpu_physical_memory_read(addr
, &v
, 2);
68 return (v
& mask
) != 0;
71 static void bitband_writew(void *opaque
, hwaddr offset
,
77 addr
= bitband_addr(opaque
, offset
) & ~1;
78 mask
= (1 << ((offset
>> 2) & 15));
80 cpu_physical_memory_read(addr
, &v
, 2);
85 cpu_physical_memory_write(addr
, &v
, 2);
88 static uint32_t bitband_readl(void *opaque
, hwaddr offset
)
93 addr
= bitband_addr(opaque
, offset
) & ~3;
94 mask
= (1 << ((offset
>> 2) & 31));
96 cpu_physical_memory_read(addr
, &v
, 4);
97 return (v
& mask
) != 0;
100 static void bitband_writel(void *opaque
, hwaddr offset
,
106 addr
= bitband_addr(opaque
, offset
) & ~3;
107 mask
= (1 << ((offset
>> 2) & 31));
108 mask
= tswap32(mask
);
109 cpu_physical_memory_read(addr
, &v
, 4);
114 cpu_physical_memory_write(addr
, &v
, 4);
117 static const MemoryRegionOps bitband_ops
= {
119 .read
= { bitband_readb
, bitband_readw
, bitband_readl
, },
120 .write
= { bitband_writeb
, bitband_writew
, bitband_writel
, },
122 .endianness
= DEVICE_NATIVE_ENDIAN
,
125 static void bitband_init(Object
*obj
)
127 BitBandState
*s
= BITBAND(obj
);
128 SysBusDevice
*dev
= SYS_BUS_DEVICE(obj
);
130 memory_region_init_io(&s
->iomem
, obj
, &bitband_ops
, &s
->base
,
131 "bitband", 0x02000000);
132 sysbus_init_mmio(dev
, &s
->iomem
);
137 static const hwaddr bitband_input_addr
[ARMV7M_NUM_BITBANDS
] = {
138 0x20000000, 0x40000000
141 static const hwaddr bitband_output_addr
[ARMV7M_NUM_BITBANDS
] = {
142 0x22000000, 0x42000000
145 static void armv7m_instance_init(Object
*obj
)
147 ARMv7MState
*s
= ARMV7M(obj
);
150 /* Can't init the cpu here, we don't yet know which model to use */
152 object_property_add_link(obj
, "memory",
154 (Object
**)&s
->board_memory
,
155 qdev_prop_allow_set_link_before_realize
,
156 OBJ_PROP_LINK_UNREF_ON_RELEASE
,
158 memory_region_init(&s
->container
, obj
, "armv7m-container", UINT64_MAX
);
160 object_initialize(&s
->nvic
, sizeof(s
->nvic
), "armv7m_nvic");
161 qdev_set_parent_bus(DEVICE(&s
->nvic
), sysbus_get_default());
162 object_property_add_alias(obj
, "num-irq",
163 OBJECT(&s
->nvic
), "num-irq", &error_abort
);
165 for (i
= 0; i
< ARRAY_SIZE(s
->bitband
); i
++) {
166 object_initialize(&s
->bitband
[i
], sizeof(s
->bitband
[i
]), TYPE_BITBAND
);
167 qdev_set_parent_bus(DEVICE(&s
->bitband
[i
]), sysbus_get_default());
171 static void armv7m_realize(DeviceState
*dev
, Error
**errp
)
173 ARMv7MState
*s
= ARMV7M(dev
);
179 const char *typename
;
182 if (!s
->board_memory
) {
183 error_setg(errp
, "memory property was not set");
187 memory_region_add_subregion_overlap(&s
->container
, 0, s
->board_memory
, -1);
189 cpustr
= g_strsplit(s
->cpu_model
, ",", 2);
191 oc
= cpu_class_by_name(TYPE_ARM_CPU
, cpustr
[0]);
193 error_setg(errp
, "Unknown CPU model %s", cpustr
[0]);
199 typename
= object_class_get_name(oc
);
200 cc
->parse_features(typename
, cpustr
[1], &err
);
203 error_propagate(errp
, err
);
207 s
->cpu
= ARM_CPU(object_new(typename
));
209 error_setg(errp
, "Unknown CPU model %s", s
->cpu_model
);
213 object_property_set_link(OBJECT(s
->cpu
), OBJECT(&s
->container
), "memory",
215 object_property_set_bool(OBJECT(s
->cpu
), true, "realized", &err
);
217 error_propagate(errp
, err
);
221 /* Note that we must realize the NVIC after the CPU */
222 object_property_set_bool(OBJECT(&s
->nvic
), true, "realized", &err
);
224 error_propagate(errp
, err
);
228 /* Alias the NVIC's input and output GPIOs as our own so the board
229 * code can wire them up. (We do this in realize because the
230 * NVIC doesn't create the input GPIO array until realize.)
232 qdev_pass_gpios(DEVICE(&s
->nvic
), dev
, NULL
);
233 qdev_pass_gpios(DEVICE(&s
->nvic
), dev
, "SYSRESETREQ");
235 /* Wire the NVIC up to the CPU */
236 sbd
= SYS_BUS_DEVICE(&s
->nvic
);
237 sysbus_connect_irq(sbd
, 0,
238 qdev_get_gpio_in(DEVICE(s
->cpu
), ARM_CPU_IRQ
));
239 s
->cpu
->env
.nvic
= &s
->nvic
;
241 memory_region_add_subregion(&s
->container
, 0xe000e000,
242 sysbus_mmio_get_region(sbd
, 0));
244 for (i
= 0; i
< ARRAY_SIZE(s
->bitband
); i
++) {
245 Object
*obj
= OBJECT(&s
->bitband
[i
]);
246 SysBusDevice
*sbd
= SYS_BUS_DEVICE(&s
->bitband
[i
]);
248 object_property_set_int(obj
, bitband_input_addr
[i
], "base", &err
);
250 error_propagate(errp
, err
);
253 object_property_set_bool(obj
, true, "realized", &err
);
255 error_propagate(errp
, err
);
259 memory_region_add_subregion(&s
->container
, bitband_output_addr
[i
],
260 sysbus_mmio_get_region(sbd
, 0));
264 static Property armv7m_properties
[] = {
265 DEFINE_PROP_STRING("cpu-model", ARMv7MState
, cpu_model
),
266 DEFINE_PROP_END_OF_LIST(),
269 static void armv7m_class_init(ObjectClass
*klass
, void *data
)
271 DeviceClass
*dc
= DEVICE_CLASS(klass
);
273 dc
->realize
= armv7m_realize
;
274 dc
->props
= armv7m_properties
;
277 static const TypeInfo armv7m_info
= {
279 .parent
= TYPE_SYS_BUS_DEVICE
,
280 .instance_size
= sizeof(ARMv7MState
),
281 .instance_init
= armv7m_instance_init
,
282 .class_init
= armv7m_class_init
,
285 static void armv7m_reset(void *opaque
)
287 ARMCPU
*cpu
= opaque
;
292 /* Init CPU and memory for a v7-M based board.
293 mem_size is in bytes.
294 Returns the ARMv7M device. */
296 DeviceState
*armv7m_init(MemoryRegion
*system_memory
, int mem_size
, int num_irq
,
297 const char *kernel_filename
, const char *cpu_model
)
301 if (cpu_model
== NULL
) {
302 cpu_model
= "cortex-m3";
305 armv7m
= qdev_create(NULL
, "armv7m");
306 qdev_prop_set_uint32(armv7m
, "num-irq", num_irq
);
307 qdev_prop_set_string(armv7m
, "cpu-model", cpu_model
);
308 object_property_set_link(OBJECT(armv7m
), OBJECT(get_system_memory()),
309 "memory", &error_abort
);
310 /* This will exit with an error if the user passed us a bad cpu_model */
311 qdev_init_nofail(armv7m
);
313 armv7m_load_kernel(ARM_CPU(first_cpu
), kernel_filename
, mem_size
);
317 void armv7m_load_kernel(ARMCPU
*cpu
, const char *kernel_filename
, int mem_size
)
324 #ifdef TARGET_WORDS_BIGENDIAN
330 if (!kernel_filename
&& !qtest_enabled()) {
331 fprintf(stderr
, "Guest image must be specified (using -kernel)\n");
335 if (kernel_filename
) {
336 image_size
= load_elf(kernel_filename
, NULL
, NULL
, &entry
, &lowaddr
,
337 NULL
, big_endian
, EM_ARM
, 1, 0);
338 if (image_size
< 0) {
339 image_size
= load_image_targphys(kernel_filename
, 0, mem_size
);
342 if (image_size
< 0) {
343 error_report("Could not load kernel '%s'", kernel_filename
);
348 /* CPU objects (unlike devices) are not automatically reset on system
349 * reset, so we must always register a handler to do so. Unlike
350 * A-profile CPUs, we don't need to do anything special in the
351 * handler to arrange that it starts correctly.
352 * This is arguably the wrong place to do this, but it matches the
353 * way A-profile does it. Note that this means that every M profile
354 * board must call this function!
356 qemu_register_reset(armv7m_reset
, cpu
);
359 static Property bitband_properties
[] = {
360 DEFINE_PROP_UINT32("base", BitBandState
, base
, 0),
361 DEFINE_PROP_END_OF_LIST(),
364 static void bitband_class_init(ObjectClass
*klass
, void *data
)
366 DeviceClass
*dc
= DEVICE_CLASS(klass
);
368 dc
->props
= bitband_properties
;
371 static const TypeInfo bitband_info
= {
372 .name
= TYPE_BITBAND
,
373 .parent
= TYPE_SYS_BUS_DEVICE
,
374 .instance_size
= sizeof(BitBandState
),
375 .instance_init
= bitband_init
,
376 .class_init
= bitband_class_init
,
379 static void armv7m_register_types(void)
381 type_register_static(&bitband_info
);
382 type_register_static(&armv7m_info
);
385 type_init(armv7m_register_types
)