1
2
3
4
5
6
7
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
18
19
20static 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
30static 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
37static 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
53static 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
65static 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
82static 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
94static 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
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,
117};
118
119#define TYPE_BITBAND "ARM,bitband-memory"
120#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
121
122typedef struct {
123
124 SysBusDevice parent_obj;
125
126
127 MemoryRegion iomem;
128 uint32_t base;
129} BitBandState;
130
131static 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
141static 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
157
158static void armv7m_reset(void *opaque)
159{
160 ARMCPU *cpu = opaque;
161
162 cpu_reset(CPU(cpu));
163}
164
165
166
167
168
169DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
170 const char *kernel_filename, const char *cpu_model)
171{
172 ARMCPU *cpu;
173 CPUARMState *env;
174 DeviceState *nvic;
175 int image_size;
176 uint64_t entry;
177 uint64_t lowaddr;
178 int big_endian;
179 MemoryRegion *hack = g_new(MemoryRegion, 1);
180
181 if (cpu_model == NULL) {
182 cpu_model = "cortex-m3";
183 }
184 cpu = cpu_arm_init(cpu_model);
185 if (cpu == NULL) {
186 fprintf(stderr, "Unable to find CPU definition\n");
187 exit(1);
188 }
189 env = &cpu->env;
190
191 armv7m_bitband_init();
192
193 nvic = qdev_create(NULL, "armv7m_nvic");
194 qdev_prop_set_uint32(nvic, "num-irq", num_irq);
195 env->nvic = nvic;
196 qdev_init_nofail(nvic);
197 sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
198 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
199
200#ifdef TARGET_WORDS_BIGENDIAN
201 big_endian = 1;
202#else
203 big_endian = 0;
204#endif
205
206 if (!kernel_filename && !qtest_enabled()) {
207 fprintf(stderr, "Guest image must be specified (using -kernel)\n");
208 exit(1);
209 }
210
211 if (kernel_filename) {
212 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
213 NULL, big_endian, EM_ARM, 1);
214 if (image_size < 0) {
215 image_size = load_image_targphys(kernel_filename, 0, mem_size);
216 lowaddr = 0;
217 }
218 if (image_size < 0) {
219 error_report("Could not load kernel '%s'", kernel_filename);
220 exit(1);
221 }
222 }
223
224
225
226
227 memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000, &error_fatal);
228 vmstate_register_ram_global(hack);
229 memory_region_add_subregion(system_memory, 0xfffff000, hack);
230
231 qemu_register_reset(armv7m_reset, cpu);
232 return nvic;
233}
234
235static Property bitband_properties[] = {
236 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
237 DEFINE_PROP_END_OF_LIST(),
238};
239
240static void bitband_class_init(ObjectClass *klass, void *data)
241{
242 DeviceClass *dc = DEVICE_CLASS(klass);
243 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
244
245 k->init = bitband_init;
246 dc->props = bitband_properties;
247}
248
249static const TypeInfo bitband_info = {
250 .name = TYPE_BITBAND,
251 .parent = TYPE_SYS_BUS_DEVICE,
252 .instance_size = sizeof(BitBandState),
253 .class_init = bitband_class_init,
254};
255
256static void armv7m_register_types(void)
257{
258 type_register_static(&bitband_info);
259}
260
261type_init(armv7m_register_types)
262