]> Git Repo - qemu.git/blob - hw/arm/armv7m.c
memory: add parameter errp to memory_region_init_ram
[qemu.git] / hw / arm / armv7m.c
1 /*
2  * ARMV7M System emulation.
3  *
4  * Copyright (c) 2006-2007 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licensed under the GPL.
8  */
9
10 #include "hw/sysbus.h"
11 #include "hw/arm/arm.h"
12 #include "hw/loader.h"
13 #include "elf.h"
14 #include "sysemu/qtest.h"
15 #include "qemu/error-report.h"
16
17 /* Bitbanded IO.  Each word corresponds to a single bit.  */
18
19 /* Get the byte address of the real memory for a bitband access.  */
20 static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
21 {
22     uint32_t res;
23
24     res = *(uint32_t *)opaque;
25     res |= (addr & 0x1ffffff) >> 5;
26     return res;
27
28 }
29
30 static uint32_t bitband_readb(void *opaque, hwaddr offset)
31 {
32     uint8_t v;
33     cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
34     return (v & (1 << ((offset >> 2) & 7))) != 0;
35 }
36
37 static void bitband_writeb(void *opaque, hwaddr offset,
38                            uint32_t value)
39 {
40     uint32_t addr;
41     uint8_t mask;
42     uint8_t v;
43     addr = bitband_addr(opaque, offset);
44     mask = (1 << ((offset >> 2) & 7));
45     cpu_physical_memory_read(addr, &v, 1);
46     if (value & 1)
47         v |= mask;
48     else
49         v &= ~mask;
50     cpu_physical_memory_write(addr, &v, 1);
51 }
52
53 static uint32_t bitband_readw(void *opaque, hwaddr offset)
54 {
55     uint32_t addr;
56     uint16_t mask;
57     uint16_t v;
58     addr = bitband_addr(opaque, offset) & ~1;
59     mask = (1 << ((offset >> 2) & 15));
60     mask = tswap16(mask);
61     cpu_physical_memory_read(addr, &v, 2);
62     return (v & mask) != 0;
63 }
64
65 static void bitband_writew(void *opaque, hwaddr offset,
66                            uint32_t value)
67 {
68     uint32_t addr;
69     uint16_t mask;
70     uint16_t v;
71     addr = bitband_addr(opaque, offset) & ~1;
72     mask = (1 << ((offset >> 2) & 15));
73     mask = tswap16(mask);
74     cpu_physical_memory_read(addr, &v, 2);
75     if (value & 1)
76         v |= mask;
77     else
78         v &= ~mask;
79     cpu_physical_memory_write(addr, &v, 2);
80 }
81
82 static uint32_t bitband_readl(void *opaque, hwaddr offset)
83 {
84     uint32_t addr;
85     uint32_t mask;
86     uint32_t v;
87     addr = bitband_addr(opaque, offset) & ~3;
88     mask = (1 << ((offset >> 2) & 31));
89     mask = tswap32(mask);
90     cpu_physical_memory_read(addr, &v, 4);
91     return (v & mask) != 0;
92 }
93
94 static void bitband_writel(void *opaque, hwaddr offset,
95                            uint32_t value)
96 {
97     uint32_t addr;
98     uint32_t mask;
99     uint32_t v;
100     addr = bitband_addr(opaque, offset) & ~3;
101     mask = (1 << ((offset >> 2) & 31));
102     mask = tswap32(mask);
103     cpu_physical_memory_read(addr, &v, 4);
104     if (value & 1)
105         v |= mask;
106     else
107         v &= ~mask;
108     cpu_physical_memory_write(addr, &v, 4);
109 }
110
111 static const MemoryRegionOps bitband_ops = {
112     .old_mmio = {
113         .read = { bitband_readb, bitband_readw, bitband_readl, },
114         .write = { bitband_writeb, bitband_writew, bitband_writel, },
115     },
116     .endianness = DEVICE_NATIVE_ENDIAN,
117 };
118
119 #define TYPE_BITBAND "ARM,bitband-memory"
120 #define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
121
122 typedef struct {
123     /*< private >*/
124     SysBusDevice parent_obj;
125     /*< public >*/
126
127     MemoryRegion iomem;
128     uint32_t base;
129 } BitBandState;
130
131 static int bitband_init(SysBusDevice *dev)
132 {
133     BitBandState *s = BITBAND(dev);
134
135     memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base,
136                           "bitband", 0x02000000);
137     sysbus_init_mmio(dev, &s->iomem);
138     return 0;
139 }
140
141 static void armv7m_bitband_init(void)
142 {
143     DeviceState *dev;
144
145     dev = qdev_create(NULL, TYPE_BITBAND);
146     qdev_prop_set_uint32(dev, "base", 0x20000000);
147     qdev_init_nofail(dev);
148     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
149
150     dev = qdev_create(NULL, TYPE_BITBAND);
151     qdev_prop_set_uint32(dev, "base", 0x40000000);
152     qdev_init_nofail(dev);
153     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
154 }
155
156 /* Board init.  */
157
158 static void armv7m_reset(void *opaque)
159 {
160     ARMCPU *cpu = opaque;
161
162     cpu_reset(CPU(cpu));
163 }
164
165 /* Init CPU and memory for a v7-M based board.
166    flash_size and sram_size are in kb.
167    Returns the NVIC array.  */
168
169 qemu_irq *armv7m_init(MemoryRegion *system_memory,
170                       int flash_size, int sram_size,
171                       const char *kernel_filename, const char *cpu_model)
172 {
173     ARMCPU *cpu;
174     CPUARMState *env;
175     DeviceState *nvic;
176     /* FIXME: make this local state.  */
177     static qemu_irq pic[64];
178     int image_size;
179     uint64_t entry;
180     uint64_t lowaddr;
181     int i;
182     int big_endian;
183     MemoryRegion *sram = g_new(MemoryRegion, 1);
184     MemoryRegion *flash = g_new(MemoryRegion, 1);
185     MemoryRegion *hack = g_new(MemoryRegion, 1);
186
187     flash_size *= 1024;
188     sram_size *= 1024;
189
190     if (cpu_model == NULL) {
191         cpu_model = "cortex-m3";
192     }
193     cpu = cpu_arm_init(cpu_model);
194     if (cpu == NULL) {
195         fprintf(stderr, "Unable to find CPU definition\n");
196         exit(1);
197     }
198     env = &cpu->env;
199
200 #if 0
201     /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
202        We don't have proper commandline options, so allocate half of memory
203        as SRAM, up to a maximum of 32Mb, and the rest as code.  */
204     if (ram_size > (512 + 32) * 1024 * 1024)
205         ram_size = (512 + 32) * 1024 * 1024;
206     sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
207     if (sram_size > 32 * 1024 * 1024)
208         sram_size = 32 * 1024 * 1024;
209     code_size = ram_size - sram_size;
210 #endif
211
212     /* Flash programming is done via the SCU, so pretend it is ROM.  */
213     memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size,
214                            &error_abort);
215     vmstate_register_ram_global(flash);
216     memory_region_set_readonly(flash, true);
217     memory_region_add_subregion(system_memory, 0, flash);
218     memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size, &error_abort);
219     vmstate_register_ram_global(sram);
220     memory_region_add_subregion(system_memory, 0x20000000, sram);
221     armv7m_bitband_init();
222
223     nvic = qdev_create(NULL, "armv7m_nvic");
224     env->nvic = nvic;
225     qdev_init_nofail(nvic);
226     sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
227                        qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
228     for (i = 0; i < 64; i++) {
229         pic[i] = qdev_get_gpio_in(nvic, i);
230     }
231
232 #ifdef TARGET_WORDS_BIGENDIAN
233     big_endian = 1;
234 #else
235     big_endian = 0;
236 #endif
237
238     if (!kernel_filename && !qtest_enabled()) {
239         fprintf(stderr, "Guest image must be specified (using -kernel)\n");
240         exit(1);
241     }
242
243     if (kernel_filename) {
244         image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
245                               NULL, big_endian, ELF_MACHINE, 1);
246         if (image_size < 0) {
247             image_size = load_image_targphys(kernel_filename, 0, flash_size);
248             lowaddr = 0;
249         }
250         if (image_size < 0) {
251             error_report("Could not load kernel '%s'", kernel_filename);
252             exit(1);
253         }
254     }
255
256     /* Hack to map an additional page of ram at the top of the address
257        space.  This stops qemu complaining about executing code outside RAM
258        when returning from an exception.  */
259     memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000, &error_abort);
260     vmstate_register_ram_global(hack);
261     memory_region_add_subregion(system_memory, 0xfffff000, hack);
262
263     qemu_register_reset(armv7m_reset, cpu);
264     return pic;
265 }
266
267 static Property bitband_properties[] = {
268     DEFINE_PROP_UINT32("base", BitBandState, base, 0),
269     DEFINE_PROP_END_OF_LIST(),
270 };
271
272 static void bitband_class_init(ObjectClass *klass, void *data)
273 {
274     DeviceClass *dc = DEVICE_CLASS(klass);
275     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
276
277     k->init = bitband_init;
278     dc->props = bitband_properties;
279 }
280
281 static const TypeInfo bitband_info = {
282     .name          = TYPE_BITBAND,
283     .parent        = TYPE_SYS_BUS_DEVICE,
284     .instance_size = sizeof(BitBandState),
285     .class_init    = bitband_class_init,
286 };
287
288 static void armv7m_register_types(void)
289 {
290     type_register_static(&bitband_info);
291 }
292
293 type_init(armv7m_register_types)
This page took 0.040739 seconds and 4 git commands to generate.