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