xics: report errors with the QEMU Error API
[qemu/cris-port.git] / hw / arm / armv7m.c
blobf3973f721a4280125eb9bdb0898c998e6ea046fc
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 "hw/sysbus.h"
12 #include "hw/arm/arm.h"
13 #include "hw/loader.h"
14 #include "elf.h"
15 #include "sysemu/qtest.h"
16 #include "qemu/error-report.h"
18 /* Bitbanded IO. Each word corresponds to a single bit. */
20 /* Get the byte address of the real memory for a bitband access. */
21 static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
23 uint32_t res;
25 res = *(uint32_t *)opaque;
26 res |= (addr & 0x1ffffff) >> 5;
27 return res;
31 static uint32_t bitband_readb(void *opaque, hwaddr offset)
33 uint8_t v;
34 cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
35 return (v & (1 << ((offset >> 2) & 7))) != 0;
38 static void bitband_writeb(void *opaque, hwaddr offset,
39 uint32_t value)
41 uint32_t addr;
42 uint8_t mask;
43 uint8_t v;
44 addr = bitband_addr(opaque, offset);
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);
54 static uint32_t bitband_readw(void *opaque, hwaddr offset)
56 uint32_t addr;
57 uint16_t mask;
58 uint16_t v;
59 addr = bitband_addr(opaque, offset) & ~1;
60 mask = (1 << ((offset >> 2) & 15));
61 mask = tswap16(mask);
62 cpu_physical_memory_read(addr, &v, 2);
63 return (v & mask) != 0;
66 static void bitband_writew(void *opaque, hwaddr offset,
67 uint32_t value)
69 uint32_t addr;
70 uint16_t mask;
71 uint16_t v;
72 addr = bitband_addr(opaque, offset) & ~1;
73 mask = (1 << ((offset >> 2) & 15));
74 mask = tswap16(mask);
75 cpu_physical_memory_read(addr, &v, 2);
76 if (value & 1)
77 v |= mask;
78 else
79 v &= ~mask;
80 cpu_physical_memory_write(addr, &v, 2);
83 static uint32_t bitband_readl(void *opaque, hwaddr offset)
85 uint32_t addr;
86 uint32_t mask;
87 uint32_t v;
88 addr = bitband_addr(opaque, offset) & ~3;
89 mask = (1 << ((offset >> 2) & 31));
90 mask = tswap32(mask);
91 cpu_physical_memory_read(addr, &v, 4);
92 return (v & mask) != 0;
95 static void bitband_writel(void *opaque, hwaddr offset,
96 uint32_t value)
98 uint32_t addr;
99 uint32_t mask;
100 uint32_t v;
101 addr = bitband_addr(opaque, offset) & ~3;
102 mask = (1 << ((offset >> 2) & 31));
103 mask = tswap32(mask);
104 cpu_physical_memory_read(addr, &v, 4);
105 if (value & 1)
106 v |= mask;
107 else
108 v &= ~mask;
109 cpu_physical_memory_write(addr, &v, 4);
112 static const MemoryRegionOps bitband_ops = {
113 .old_mmio = {
114 .read = { bitband_readb, bitband_readw, bitband_readl, },
115 .write = { bitband_writeb, bitband_writew, bitband_writel, },
117 .endianness = DEVICE_NATIVE_ENDIAN,
120 #define TYPE_BITBAND "ARM,bitband-memory"
121 #define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
123 typedef struct {
124 /*< private >*/
125 SysBusDevice parent_obj;
126 /*< public >*/
128 MemoryRegion iomem;
129 uint32_t base;
130 } BitBandState;
132 static int bitband_init(SysBusDevice *dev)
134 BitBandState *s = BITBAND(dev);
136 memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base,
137 "bitband", 0x02000000);
138 sysbus_init_mmio(dev, &s->iomem);
139 return 0;
142 static void armv7m_bitband_init(void)
144 DeviceState *dev;
146 dev = qdev_create(NULL, TYPE_BITBAND);
147 qdev_prop_set_uint32(dev, "base", 0x20000000);
148 qdev_init_nofail(dev);
149 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
151 dev = qdev_create(NULL, TYPE_BITBAND);
152 qdev_prop_set_uint32(dev, "base", 0x40000000);
153 qdev_init_nofail(dev);
154 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
157 /* Board init. */
159 static void armv7m_reset(void *opaque)
161 ARMCPU *cpu = opaque;
163 cpu_reset(CPU(cpu));
166 /* Init CPU and memory for a v7-M based board.
167 mem_size is in bytes.
168 Returns the NVIC array. */
170 DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
171 const char *kernel_filename, const char *cpu_model)
173 ARMCPU *cpu;
174 CPUARMState *env;
175 DeviceState *nvic;
176 int image_size;
177 uint64_t entry;
178 uint64_t lowaddr;
179 int big_endian;
180 MemoryRegion *hack = g_new(MemoryRegion, 1);
182 if (cpu_model == NULL) {
183 cpu_model = "cortex-m3";
185 cpu = cpu_arm_init(cpu_model);
186 if (cpu == NULL) {
187 fprintf(stderr, "Unable to find CPU definition\n");
188 exit(1);
190 env = &cpu->env;
192 armv7m_bitband_init();
194 nvic = qdev_create(NULL, "armv7m_nvic");
195 qdev_prop_set_uint32(nvic, "num-irq", num_irq);
196 env->nvic = nvic;
197 qdev_init_nofail(nvic);
198 sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
199 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
201 #ifdef TARGET_WORDS_BIGENDIAN
202 big_endian = 1;
203 #else
204 big_endian = 0;
205 #endif
207 if (!kernel_filename && !qtest_enabled()) {
208 fprintf(stderr, "Guest image must be specified (using -kernel)\n");
209 exit(1);
212 if (kernel_filename) {
213 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
214 NULL, big_endian, EM_ARM, 1);
215 if (image_size < 0) {
216 image_size = load_image_targphys(kernel_filename, 0, mem_size);
217 lowaddr = 0;
219 if (image_size < 0) {
220 error_report("Could not load kernel '%s'", kernel_filename);
221 exit(1);
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. */
228 memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000, &error_fatal);
229 vmstate_register_ram_global(hack);
230 memory_region_add_subregion(system_memory, 0xfffff000, hack);
232 qemu_register_reset(armv7m_reset, cpu);
233 return nvic;
236 static Property bitband_properties[] = {
237 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
238 DEFINE_PROP_END_OF_LIST(),
241 static void bitband_class_init(ObjectClass *klass, void *data)
243 DeviceClass *dc = DEVICE_CLASS(klass);
244 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
246 k->init = bitband_init;
247 dc->props = bitband_properties;
250 static const TypeInfo bitband_info = {
251 .name = TYPE_BITBAND,
252 .parent = TYPE_SYS_BUS_DEVICE,
253 .instance_size = sizeof(BitBandState),
254 .class_init = bitband_class_init,
257 static void armv7m_register_types(void)
259 type_register_static(&bitband_info);
262 type_init(armv7m_register_types)