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