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