]> git.proxmox.com Git - mirror_qemu.git/blame - hw/arm/armv7m.c
hw: explicitly include qemu-common.h and cpu.h
[mirror_qemu.git] / hw / arm / armv7m.c
CommitLineData
9ee6e8bb
PB
1/*
2 * ARMV7M System emulation.
3 *
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
6 *
2167f7bc 7 * This code is licensed under the GPL.
9ee6e8bb
PB
8 */
9
12b16722 10#include "qemu/osdep.h"
da34e65c 11#include "qapi/error.h"
4771d756
PB
12#include "qemu-common.h"
13#include "cpu.h"
83c9f4ca 14#include "hw/sysbus.h"
bd2be150 15#include "hw/arm/arm.h"
83c9f4ca 16#include "hw/loader.h"
ca20cf32 17#include "elf.h"
5633b90a
AF
18#include "sysemu/qtest.h"
19#include "qemu/error-report.h"
9ee6e8bb
PB
20
21/* Bitbanded IO. Each word corresponds to a single bit. */
22
2167f7bc 23/* Get the byte address of the real memory for a bitband access. */
8da3ff18 24static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
9ee6e8bb
PB
25{
26 uint32_t res;
27
8da3ff18 28 res = *(uint32_t *)opaque;
9ee6e8bb
PB
29 res |= (addr & 0x1ffffff) >> 5;
30 return res;
31
32}
33
a8170e5e 34static uint32_t bitband_readb(void *opaque, hwaddr offset)
9ee6e8bb
PB
35{
36 uint8_t v;
8da3ff18 37 cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
9ee6e8bb
PB
38 return (v & (1 << ((offset >> 2) & 7))) != 0;
39}
40
a8170e5e 41static void bitband_writeb(void *opaque, hwaddr offset,
9ee6e8bb
PB
42 uint32_t value)
43{
44 uint32_t addr;
45 uint8_t mask;
46 uint8_t v;
8da3ff18 47 addr = bitband_addr(opaque, offset);
9ee6e8bb
PB
48 mask = (1 << ((offset >> 2) & 7));
49 cpu_physical_memory_read(addr, &v, 1);
50 if (value & 1)
51 v |= mask;
52 else
53 v &= ~mask;
54 cpu_physical_memory_write(addr, &v, 1);
55}
56
a8170e5e 57static uint32_t bitband_readw(void *opaque, hwaddr offset)
9ee6e8bb
PB
58{
59 uint32_t addr;
60 uint16_t mask;
61 uint16_t v;
8da3ff18 62 addr = bitband_addr(opaque, offset) & ~1;
9ee6e8bb
PB
63 mask = (1 << ((offset >> 2) & 15));
64 mask = tswap16(mask);
e1fe50dc 65 cpu_physical_memory_read(addr, &v, 2);
9ee6e8bb
PB
66 return (v & mask) != 0;
67}
68
a8170e5e 69static void bitband_writew(void *opaque, hwaddr offset,
9ee6e8bb
PB
70 uint32_t value)
71{
72 uint32_t addr;
73 uint16_t mask;
74 uint16_t v;
8da3ff18 75 addr = bitband_addr(opaque, offset) & ~1;
9ee6e8bb
PB
76 mask = (1 << ((offset >> 2) & 15));
77 mask = tswap16(mask);
e1fe50dc 78 cpu_physical_memory_read(addr, &v, 2);
9ee6e8bb
PB
79 if (value & 1)
80 v |= mask;
81 else
82 v &= ~mask;
e1fe50dc 83 cpu_physical_memory_write(addr, &v, 2);
9ee6e8bb
PB
84}
85
a8170e5e 86static uint32_t bitband_readl(void *opaque, hwaddr offset)
9ee6e8bb
PB
87{
88 uint32_t addr;
89 uint32_t mask;
90 uint32_t v;
8da3ff18 91 addr = bitband_addr(opaque, offset) & ~3;
9ee6e8bb
PB
92 mask = (1 << ((offset >> 2) & 31));
93 mask = tswap32(mask);
e1fe50dc 94 cpu_physical_memory_read(addr, &v, 4);
9ee6e8bb
PB
95 return (v & mask) != 0;
96}
97
a8170e5e 98static void bitband_writel(void *opaque, hwaddr offset,
9ee6e8bb
PB
99 uint32_t value)
100{
101 uint32_t addr;
102 uint32_t mask;
103 uint32_t v;
8da3ff18 104 addr = bitband_addr(opaque, offset) & ~3;
9ee6e8bb
PB
105 mask = (1 << ((offset >> 2) & 31));
106 mask = tswap32(mask);
e1fe50dc 107 cpu_physical_memory_read(addr, &v, 4);
9ee6e8bb
PB
108 if (value & 1)
109 v |= mask;
110 else
111 v &= ~mask;
e1fe50dc 112 cpu_physical_memory_write(addr, &v, 4);
9ee6e8bb
PB
113}
114
f69bf9d4
AK
115static const MemoryRegionOps bitband_ops = {
116 .old_mmio = {
117 .read = { bitband_readb, bitband_readw, bitband_readl, },
118 .write = { bitband_writeb, bitband_writew, bitband_writel, },
119 },
120 .endianness = DEVICE_NATIVE_ENDIAN,
9ee6e8bb
PB
121};
122
936230a7
AF
123#define TYPE_BITBAND "ARM,bitband-memory"
124#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
125
40905a6a 126typedef struct {
936230a7
AF
127 /*< private >*/
128 SysBusDevice parent_obj;
129 /*< public >*/
130
f69bf9d4 131 MemoryRegion iomem;
40905a6a
PB
132 uint32_t base;
133} BitBandState;
134
81a322d4 135static int bitband_init(SysBusDevice *dev)
9ee6e8bb 136{
936230a7 137 BitBandState *s = BITBAND(dev);
9ee6e8bb 138
64bde0f3
PB
139 memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base,
140 "bitband", 0x02000000);
750ecd44 141 sysbus_init_mmio(dev, &s->iomem);
81a322d4 142 return 0;
40905a6a
PB
143}
144
145static void armv7m_bitband_init(void)
146{
147 DeviceState *dev;
148
936230a7 149 dev = qdev_create(NULL, TYPE_BITBAND);
ee6847d1 150 qdev_prop_set_uint32(dev, "base", 0x20000000);
e23a1b33 151 qdev_init_nofail(dev);
1356b98d 152 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
40905a6a 153
936230a7 154 dev = qdev_create(NULL, TYPE_BITBAND);
ee6847d1 155 qdev_prop_set_uint32(dev, "base", 0x40000000);
e23a1b33 156 qdev_init_nofail(dev);
1356b98d 157 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
9ee6e8bb
PB
158}
159
160/* Board init. */
983fe826
PB
161
162static void armv7m_reset(void *opaque)
163{
31363f12
AF
164 ARMCPU *cpu = opaque;
165
166 cpu_reset(CPU(cpu));
983fe826
PB
167}
168
9ee6e8bb 169/* Init CPU and memory for a v7-M based board.
fe6ac447 170 mem_size is in bytes.
9ee6e8bb
PB
171 Returns the NVIC array. */
172
20c59c38 173DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
9ee6e8bb
PB
174 const char *kernel_filename, const char *cpu_model)
175{
0f37c99b 176 ARMCPU *cpu;
5ae93306 177 CPUARMState *env;
fe7e8758 178 DeviceState *nvic;
9ee6e8bb
PB
179 int image_size;
180 uint64_t entry;
181 uint64_t lowaddr;
ca20cf32 182 int big_endian;
7d6f78cf 183 MemoryRegion *hack = g_new(MemoryRegion, 1);
9ee6e8bb 184
0f37c99b 185 if (cpu_model == NULL) {
9ee6e8bb 186 cpu_model = "cortex-m3";
0f37c99b
AF
187 }
188 cpu = cpu_arm_init(cpu_model);
189 if (cpu == NULL) {
9ee6e8bb
PB
190 fprintf(stderr, "Unable to find CPU definition\n");
191 exit(1);
192 }
0f37c99b 193 env = &cpu->env;
9ee6e8bb 194
9ee6e8bb
PB
195 armv7m_bitband_init();
196
fe7e8758 197 nvic = qdev_create(NULL, "armv7m_nvic");
8b47b7da 198 qdev_prop_set_uint32(nvic, "num-irq", num_irq);
983fe826 199 env->nvic = nvic;
e23a1b33 200 qdev_init_nofail(nvic);
de3a658f
PM
201 sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
202 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
9ee6e8bb 203
ca20cf32
BS
204#ifdef TARGET_WORDS_BIGENDIAN
205 big_endian = 1;
206#else
207 big_endian = 0;
208#endif
209
5633b90a 210 if (!kernel_filename && !qtest_enabled()) {
01fd41ab
PC
211 fprintf(stderr, "Guest image must be specified (using -kernel)\n");
212 exit(1);
213 }
214
5633b90a
AF
215 if (kernel_filename) {
216 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
7ef295ea 217 NULL, big_endian, EM_ARM, 1, 0);
5633b90a 218 if (image_size < 0) {
fe6ac447 219 image_size = load_image_targphys(kernel_filename, 0, mem_size);
5633b90a
AF
220 lowaddr = 0;
221 }
222 if (image_size < 0) {
223 error_report("Could not load kernel '%s'", kernel_filename);
224 exit(1);
225 }
9ee6e8bb
PB
226 }
227
9ee6e8bb
PB
228 /* Hack to map an additional page of ram at the top of the address
229 space. This stops qemu complaining about executing code outside RAM
230 when returning from an exception. */
f8ed85ac 231 memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000, &error_fatal);
c5705a77 232 vmstate_register_ram_global(hack);
6e9322de 233 memory_region_add_subregion(system_memory, 0xfffff000, hack);
9ee6e8bb 234
31363f12 235 qemu_register_reset(armv7m_reset, cpu);
20c59c38 236 return nvic;
9ee6e8bb 237}
40905a6a 238
999e12bb
AL
239static Property bitband_properties[] = {
240 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
241 DEFINE_PROP_END_OF_LIST(),
242};
243
244static void bitband_class_init(ObjectClass *klass, void *data)
245{
39bffca2 246 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
247 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
248
249 k->init = bitband_init;
39bffca2 250 dc->props = bitband_properties;
999e12bb
AL
251}
252
8c43a6f0 253static const TypeInfo bitband_info = {
936230a7 254 .name = TYPE_BITBAND,
39bffca2
AL
255 .parent = TYPE_SYS_BUS_DEVICE,
256 .instance_size = sizeof(BitBandState),
257 .class_init = bitband_class_init,
ee6847d1
GH
258};
259
83f7d43a 260static void armv7m_register_types(void)
40905a6a 261{
39bffca2 262 type_register_static(&bitband_info);
40905a6a
PB
263}
264
83f7d43a 265type_init(armv7m_register_types)