Merge remote-tracking branch 'remotes/kraxel/tags/pull-audio-20170111-1' into staging
[qemu/ar7.git] / hw / arm / armv7m.c
blob49d30782c883edf68f047c0b3a4c7cc4fbffbf3f
1 /*
2 * ARMV7M System emulation.
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licensed under the GPL.
8 */
10 #include "qemu/osdep.h"
11 #include "qapi/error.h"
12 #include "qemu-common.h"
13 #include "cpu.h"
14 #include "hw/sysbus.h"
15 #include "hw/arm/arm.h"
16 #include "hw/loader.h"
17 #include "elf.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)
26 uint32_t res;
28 res = *(uint32_t *)opaque;
29 res |= (addr & 0x1ffffff) >> 5;
30 return res;
34 static uint32_t bitband_readb(void *opaque, hwaddr offset)
36 uint8_t v;
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,
42 uint32_t value)
44 uint32_t addr;
45 uint8_t mask;
46 uint8_t v;
47 addr = bitband_addr(opaque, offset);
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);
57 static uint32_t bitband_readw(void *opaque, hwaddr offset)
59 uint32_t addr;
60 uint16_t mask;
61 uint16_t v;
62 addr = bitband_addr(opaque, offset) & ~1;
63 mask = (1 << ((offset >> 2) & 15));
64 mask = tswap16(mask);
65 cpu_physical_memory_read(addr, &v, 2);
66 return (v & mask) != 0;
69 static void bitband_writew(void *opaque, hwaddr offset,
70 uint32_t value)
72 uint32_t addr;
73 uint16_t mask;
74 uint16_t v;
75 addr = bitband_addr(opaque, offset) & ~1;
76 mask = (1 << ((offset >> 2) & 15));
77 mask = tswap16(mask);
78 cpu_physical_memory_read(addr, &v, 2);
79 if (value & 1)
80 v |= mask;
81 else
82 v &= ~mask;
83 cpu_physical_memory_write(addr, &v, 2);
86 static uint32_t bitband_readl(void *opaque, hwaddr offset)
88 uint32_t addr;
89 uint32_t mask;
90 uint32_t v;
91 addr = bitband_addr(opaque, offset) & ~3;
92 mask = (1 << ((offset >> 2) & 31));
93 mask = tswap32(mask);
94 cpu_physical_memory_read(addr, &v, 4);
95 return (v & mask) != 0;
98 static void bitband_writel(void *opaque, hwaddr offset,
99 uint32_t value)
101 uint32_t addr;
102 uint32_t mask;
103 uint32_t v;
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);
108 if (value & 1)
109 v |= mask;
110 else
111 v &= ~mask;
112 cpu_physical_memory_write(addr, &v, 4);
115 static const MemoryRegionOps bitband_ops = {
116 .old_mmio = {
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)
126 typedef struct {
127 /*< private >*/
128 SysBusDevice parent_obj;
129 /*< public >*/
131 MemoryRegion iomem;
132 uint32_t base;
133 } BitBandState;
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)
147 DeviceState *dev;
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);
160 /* Board init. */
162 static void armv7m_reset(void *opaque)
164 ARMCPU *cpu = opaque;
166 cpu_reset(CPU(cpu));
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)
176 ARMCPU *cpu;
177 CPUARMState *env;
178 DeviceState *nvic;
179 int image_size;
180 uint64_t entry;
181 uint64_t lowaddr;
182 int big_endian;
183 MemoryRegion *hack = g_new(MemoryRegion, 1);
185 if (cpu_model == NULL) {
186 cpu_model = "cortex-m3";
188 cpu = cpu_arm_init(cpu_model);
189 if (cpu == NULL) {
190 fprintf(stderr, "Unable to find CPU definition\n");
191 exit(1);
193 env = &cpu->env;
195 armv7m_bitband_init();
197 nvic = qdev_create(NULL, "armv7m_nvic");
198 qdev_prop_set_uint32(nvic, "num-irq", num_irq);
199 env->nvic = nvic;
200 qdev_init_nofail(nvic);
201 sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
202 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
204 #ifdef TARGET_WORDS_BIGENDIAN
205 big_endian = 1;
206 #else
207 big_endian = 0;
208 #endif
210 if (!kernel_filename && !qtest_enabled()) {
211 fprintf(stderr, "Guest image must be specified (using -kernel)\n");
212 exit(1);
215 if (kernel_filename) {
216 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
217 NULL, big_endian, EM_ARM, 1, 0);
218 if (image_size < 0) {
219 image_size = load_image_targphys(kernel_filename, 0, mem_size);
220 lowaddr = 0;
222 if (image_size < 0) {
223 error_report("Could not load kernel '%s'", kernel_filename);
224 exit(1);
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. */
231 memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000, &error_fatal);
232 vmstate_register_ram_global(hack);
233 memory_region_add_subregion(system_memory, 0xfffff000, hack);
235 qemu_register_reset(armv7m_reset, cpu);
236 return nvic;
239 static Property bitband_properties[] = {
240 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
241 DEFINE_PROP_END_OF_LIST(),
244 static void bitband_class_init(ObjectClass *klass, void *data)
246 DeviceClass *dc = DEVICE_CLASS(klass);
248 dc->props = bitband_properties;
251 static const TypeInfo bitband_info = {
252 .name = TYPE_BITBAND,
253 .parent = TYPE_SYS_BUS_DEVICE,
254 .instance_size = sizeof(BitBandState),
255 .instance_init = bitband_init,
256 .class_init = bitband_class_init,
259 static void armv7m_register_types(void)
261 type_register_static(&bitband_info);
264 type_init(armv7m_register_types)