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 "qapi/error.h"
12 #include "qemu-common.h"
14 #include "hw/sysbus.h"
15 #include "hw/arm/arm.h"
16 #include "hw/loader.h"
18 #include "sysemu/qtest.h"
19 #include "qemu/error-report.h"
21 /* Bitbanded IO. Each word corresponds to a single bit. */
23 /* Get the byte address of the real memory for a bitband access. */
24 static inline uint32_t bitband_addr(void * opaque
, uint32_t addr
)
28 res
= *(uint32_t *)opaque
;
29 res
|= (addr
& 0x1ffffff) >> 5;
34 static uint32_t bitband_readb(void *opaque
, hwaddr offset
)
37 cpu_physical_memory_read(bitband_addr(opaque
, offset
), &v
, 1);
38 return (v
& (1 << ((offset
>> 2) & 7))) != 0;
41 static void bitband_writeb(void *opaque
, hwaddr offset
,
47 addr
= bitband_addr(opaque
, offset
);
48 mask
= (1 << ((offset
>> 2) & 7));
49 cpu_physical_memory_read(addr
, &v
, 1);
54 cpu_physical_memory_write(addr
, &v
, 1);
57 static uint32_t bitband_readw(void *opaque
, hwaddr offset
)
62 addr
= bitband_addr(opaque
, offset
) & ~1;
63 mask
= (1 << ((offset
>> 2) & 15));
65 cpu_physical_memory_read(addr
, &v
, 2);
66 return (v
& mask
) != 0;
69 static void bitband_writew(void *opaque
, hwaddr offset
,
75 addr
= bitband_addr(opaque
, offset
) & ~1;
76 mask
= (1 << ((offset
>> 2) & 15));
78 cpu_physical_memory_read(addr
, &v
, 2);
83 cpu_physical_memory_write(addr
, &v
, 2);
86 static uint32_t bitband_readl(void *opaque
, hwaddr offset
)
91 addr
= bitband_addr(opaque
, offset
) & ~3;
92 mask
= (1 << ((offset
>> 2) & 31));
94 cpu_physical_memory_read(addr
, &v
, 4);
95 return (v
& mask
) != 0;
98 static void bitband_writel(void *opaque
, hwaddr offset
,
104 addr
= bitband_addr(opaque
, offset
) & ~3;
105 mask
= (1 << ((offset
>> 2) & 31));
106 mask
= tswap32(mask
);
107 cpu_physical_memory_read(addr
, &v
, 4);
112 cpu_physical_memory_write(addr
, &v
, 4);
115 static const MemoryRegionOps bitband_ops
= {
117 .read
= { bitband_readb
, bitband_readw
, bitband_readl
, },
118 .write
= { bitband_writeb
, bitband_writew
, bitband_writel
, },
120 .endianness
= DEVICE_NATIVE_ENDIAN
,
123 #define TYPE_BITBAND "ARM,bitband-memory"
124 #define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
128 SysBusDevice parent_obj
;
135 static void bitband_init(Object
*obj
)
137 BitBandState
*s
= BITBAND(obj
);
138 SysBusDevice
*dev
= SYS_BUS_DEVICE(obj
);
140 memory_region_init_io(&s
->iomem
, obj
, &bitband_ops
, &s
->base
,
141 "bitband", 0x02000000);
142 sysbus_init_mmio(dev
, &s
->iomem
);
145 static void armv7m_bitband_init(void)
149 dev
= qdev_create(NULL
, TYPE_BITBAND
);
150 qdev_prop_set_uint32(dev
, "base", 0x20000000);
151 qdev_init_nofail(dev
);
152 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, 0x22000000);
154 dev
= qdev_create(NULL
, TYPE_BITBAND
);
155 qdev_prop_set_uint32(dev
, "base", 0x40000000);
156 qdev_init_nofail(dev
);
157 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, 0x42000000);
162 static void armv7m_reset(void *opaque
)
164 ARMCPU
*cpu
= opaque
;
169 /* Init CPU and memory for a v7-M based board.
170 mem_size is in bytes.
171 Returns the NVIC array. */
173 DeviceState
*armv7m_init(MemoryRegion
*system_memory
, int mem_size
, int num_irq
,
174 const char *kernel_filename
, const char *cpu_model
)
184 if (cpu_model
== NULL
) {
185 cpu_model
= "cortex-m3";
187 cpu
= cpu_arm_init(cpu_model
);
189 fprintf(stderr
, "Unable to find CPU definition\n");
194 armv7m_bitband_init();
196 nvic
= qdev_create(NULL
, "armv7m_nvic");
197 qdev_prop_set_uint32(nvic
, "num-irq", num_irq
);
199 qdev_init_nofail(nvic
);
200 sysbus_connect_irq(SYS_BUS_DEVICE(nvic
), 0,
201 qdev_get_gpio_in(DEVICE(cpu
), ARM_CPU_IRQ
));
203 #ifdef TARGET_WORDS_BIGENDIAN
209 if (!kernel_filename
&& !qtest_enabled()) {
210 fprintf(stderr
, "Guest image must be specified (using -kernel)\n");
214 if (kernel_filename
) {
215 image_size
= load_elf(kernel_filename
, NULL
, NULL
, &entry
, &lowaddr
,
216 NULL
, big_endian
, EM_ARM
, 1, 0);
217 if (image_size
< 0) {
218 image_size
= load_image_targphys(kernel_filename
, 0, mem_size
);
221 if (image_size
< 0) {
222 error_report("Could not load kernel '%s'", kernel_filename
);
227 qemu_register_reset(armv7m_reset
, cpu
);
231 static Property bitband_properties
[] = {
232 DEFINE_PROP_UINT32("base", BitBandState
, base
, 0),
233 DEFINE_PROP_END_OF_LIST(),
236 static void bitband_class_init(ObjectClass
*klass
, void *data
)
238 DeviceClass
*dc
= DEVICE_CLASS(klass
);
240 dc
->props
= bitband_properties
;
243 static const TypeInfo bitband_info
= {
244 .name
= TYPE_BITBAND
,
245 .parent
= TYPE_SYS_BUS_DEVICE
,
246 .instance_size
= sizeof(BitBandState
),
247 .instance_init
= bitband_init
,
248 .class_init
= bitband_class_init
,
251 static void armv7m_register_types(void)
253 type_register_static(&bitband_info
);
256 type_init(armv7m_register_types
)