1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include "qemu/osdep.h"
30#include "hw/sysbus.h"
31#include "hw/register.h"
32#include "qemu/bitops.h"
33#include "qapi/error.h"
34#include "qemu/log.h"
35
36#include "sysemu/dma.h"
37#include "exec/address-spaces.h"
38
39#include "hw/fdt_generic_util.h"
40
41#ifndef XILINX_XMPU_ERR_DEBUG
42#define XILINX_XMPU_ERR_DEBUG 0
43#endif
44
45#define TYPE_XILINX_XMPU "xlnx.xmpu"
46
47#define XILINX_XMPU(obj) \
48 OBJECT_CHECK(XMPU, (obj), TYPE_XILINX_XMPU)
49
50REG32(CTRL, 0x0)
51 FIELD(CTRL, ALIGNCFG, 1, 3)
52 FIELD(CTRL, POISONCFG, 1, 2)
53 FIELD(CTRL, DEFWRALLOWED, 1, 1)
54 FIELD(CTRL, DEFRDALLOWED, 1, 0)
55REG32(ERR_STATUS1, 0x4)
56 FIELD(ERR_STATUS1, AXI_ADDR, 20, 0)
57REG32(ERR_STATUS2, 0x8)
58 FIELD(ERR_STATUS2, AXI_ID, 10, 0)
59REG32(POISON, 0xc)
60 FIELD(POISON, ATTRIB, 1, 20)
61 FIELD(POISON, BASE, 20, 0)
62REG32(ISR, 0x10)
63 FIELD(ISR, SECURITYVIO, 1, 3)
64 FIELD(ISR, WRPERMVIO, 1, 2)
65 FIELD(ISR, RDPERMVIO, 1, 1)
66 FIELD(ISR, INV_APB, 1, 0)
67REG32(IMR, 0x14)
68 FIELD(IMR, SECURITYVIO, 1, 3)
69 FIELD(IMR, WRPERMVIO, 1, 2)
70 FIELD(IMR, RDPERMVIO, 1, 1)
71 FIELD(IMR, INV_APB, 1, 0)
72REG32(IEN, 0x18)
73 FIELD(IEN, SECURITYVIO, 1, 3)
74 FIELD(IEN, WRPERMVIO, 1, 2)
75 FIELD(IEN, RDPERMVIO, 1, 1)
76 FIELD(IEN, INV_APB, 1, 0)
77REG32(IDS, 0x1c)
78 FIELD(IDS, SECURITYVIO, 1, 3)
79 FIELD(IDS, WRPERMVIO, 1, 2)
80 FIELD(IDS, RDPERMVIO, 1, 1)
81 FIELD(IDS, INV_APB, 1, 0)
82REG32(LOCK, 0x20)
83 FIELD(LOCK, REGWRDIS, 1, 0)
84REG32(ECO, 0xfc)
85REG32(R00_START, 0x100)
86 FIELD(R00_START, ADDR, 20, 0)
87REG32(R00_END, 0x104)
88 FIELD(R00_END, ADDR, 20, 0)
89REG32(R00_MASTER, 0x108)
90 FIELD(R00_MASTER, MASK, 10, 16)
91 FIELD(R00_MASTER, ID, 10, 0)
92REG32(R00_CONFIG, 0x10c)
93 FIELD(R00_CONFIG, NSCHECKTYPE, 1, 4)
94 FIELD(R00_CONFIG, REGIONNS, 1, 3)
95 FIELD(R00_CONFIG, WRALLOWED, 1, 2)
96 FIELD(R00_CONFIG, RDALLOWED, 1, 1)
97 FIELD(R00_CONFIG, ENABLE, 1, 0)
98REG32(R01_START, 0x110)
99 FIELD(R01_START, ADDR, 20, 0)
100REG32(R01_END, 0x114)
101 FIELD(R01_END, ADDR, 20, 0)
102REG32(R01_MASTER, 0x118)
103 FIELD(R01_MASTER, MASK, 10, 16)
104 FIELD(R01_MASTER, ID, 10, 0)
105REG32(R01_CONFIG, 0x11c)
106 FIELD(R01_CONFIG, NSCHECKTYPE, 1, 4)
107 FIELD(R01_CONFIG, REGIONNS, 1, 3)
108 FIELD(R01_CONFIG, WRALLOWED, 1, 2)
109 FIELD(R01_CONFIG, RDALLOWED, 1, 1)
110 FIELD(R01_CONFIG, ENABLE, 1, 0)
111REG32(R02_START, 0x120)
112 FIELD(R02_START, ADDR, 20, 0)
113REG32(R02_END, 0x124)
114 FIELD(R02_END, ADDR, 20, 0)
115REG32(R02_MASTER, 0x128)
116 FIELD(R02_MASTER, MASK, 10, 16)
117 FIELD(R02_MASTER, ID, 10, 0)
118REG32(R02_CONFIG, 0x12c)
119 FIELD(R02_CONFIG, NSCHECKTYPE, 1, 4)
120 FIELD(R02_CONFIG, REGIONNS, 1, 3)
121 FIELD(R02_CONFIG, WRALLOWED, 1, 2)
122 FIELD(R02_CONFIG, RDALLOWED, 1, 1)
123 FIELD(R02_CONFIG, ENABLE, 1, 0)
124REG32(R03_START, 0x130)
125 FIELD(R03_START, ADDR, 20, 0)
126REG32(R03_END, 0x134)
127 FIELD(R03_END, ADDR, 20, 0)
128REG32(R03_MASTER, 0x138)
129 FIELD(R03_MASTER, MASK, 10, 16)
130 FIELD(R03_MASTER, ID, 10, 0)
131REG32(R03_CONFIG, 0x13c)
132 FIELD(R03_CONFIG, NSCHECKTYPE, 1, 4)
133 FIELD(R03_CONFIG, REGIONNS, 1, 3)
134 FIELD(R03_CONFIG, WRALLOWED, 1, 2)
135 FIELD(R03_CONFIG, RDALLOWED, 1, 1)
136 FIELD(R03_CONFIG, ENABLE, 1, 0)
137REG32(R04_START, 0x140)
138 FIELD(R04_START, ADDR, 20, 0)
139REG32(R04_END, 0x144)
140 FIELD(R04_END, ADDR, 20, 0)
141REG32(R04_MASTER, 0x148)
142 FIELD(R04_MASTER, MASK, 10, 16)
143 FIELD(R04_MASTER, ID, 10, 0)
144REG32(R04_CONFIG, 0x14c)
145 FIELD(R04_CONFIG, NSCHECKTYPE, 1, 4)
146 FIELD(R04_CONFIG, REGIONNS, 1, 3)
147 FIELD(R04_CONFIG, WRALLOWED, 1, 2)
148 FIELD(R04_CONFIG, RDALLOWED, 1, 1)
149 FIELD(R04_CONFIG, ENABLE, 1, 0)
150REG32(R05_START, 0x150)
151 FIELD(R05_START, ADDR, 20, 0)
152REG32(R05_END, 0x154)
153 FIELD(R05_END, ADDR, 20, 0)
154REG32(R05_MASTER, 0x158)
155 FIELD(R05_MASTER, MASK, 10, 16)
156 FIELD(R05_MASTER, ID, 10, 0)
157REG32(R05_CONFIG, 0x15c)
158 FIELD(R05_CONFIG, NSCHECKTYPE, 1, 4)
159 FIELD(R05_CONFIG, REGIONNS, 1, 3)
160 FIELD(R05_CONFIG, WRALLOWED, 1, 2)
161 FIELD(R05_CONFIG, RDALLOWED, 1, 1)
162 FIELD(R05_CONFIG, ENABLE, 1, 0)
163REG32(R06_START, 0x160)
164 FIELD(R06_START, ADDR, 20, 0)
165REG32(R06_END, 0x164)
166 FIELD(R06_END, ADDR, 20, 0)
167REG32(R06_MASTER, 0x168)
168 FIELD(R06_MASTER, MASK, 10, 16)
169 FIELD(R06_MASTER, ID, 10, 0)
170REG32(R06_CONFIG, 0x16c)
171 FIELD(R06_CONFIG, NSCHECKTYPE, 1, 4)
172 FIELD(R06_CONFIG, REGIONNS, 1, 3)
173 FIELD(R06_CONFIG, WRALLOWED, 1, 2)
174 FIELD(R06_CONFIG, RDALLOWED, 1, 1)
175 FIELD(R06_CONFIG, ENABLE, 1, 0)
176REG32(R07_START, 0x170)
177 FIELD(R07_START, ADDR, 20, 0)
178REG32(R07_END, 0x174)
179 FIELD(R07_END, ADDR, 20, 0)
180REG32(R07_MASTER, 0x178)
181 FIELD(R07_MASTER, MASK, 10, 16)
182 FIELD(R07_MASTER, ID, 10, 0)
183REG32(R07_CONFIG, 0x17c)
184 FIELD(R07_CONFIG, NSCHECKTYPE, 1, 4)
185 FIELD(R07_CONFIG, REGIONNS, 1, 3)
186 FIELD(R07_CONFIG, WRALLOWED, 1, 2)
187 FIELD(R07_CONFIG, RDALLOWED, 1, 1)
188 FIELD(R07_CONFIG, ENABLE, 1, 0)
189REG32(R08_START, 0x180)
190 FIELD(R08_START, ADDR, 20, 0)
191REG32(R08_END, 0x184)
192 FIELD(R08_END, ADDR, 20, 0)
193REG32(R08_MASTER, 0x188)
194 FIELD(R08_MASTER, MASK, 10, 16)
195 FIELD(R08_MASTER, ID, 10, 0)
196REG32(R08_CONFIG, 0x18c)
197 FIELD(R08_CONFIG, NSCHECKTYPE, 1, 4)
198 FIELD(R08_CONFIG, REGIONNS, 1, 3)
199 FIELD(R08_CONFIG, WRALLOWED, 1, 2)
200 FIELD(R08_CONFIG, RDALLOWED, 1, 1)
201 FIELD(R08_CONFIG, ENABLE, 1, 0)
202REG32(R09_START, 0x190)
203 FIELD(R09_START, ADDR, 20, 0)
204REG32(R09_END, 0x194)
205 FIELD(R09_END, ADDR, 20, 0)
206REG32(R09_MASTER, 0x198)
207 FIELD(R09_MASTER, MASK, 10, 16)
208 FIELD(R09_MASTER, ID, 10, 0)
209REG32(R09_CONFIG, 0x19c)
210 FIELD(R09_CONFIG, NSCHECKTYPE, 1, 4)
211 FIELD(R09_CONFIG, REGIONNS, 1, 3)
212 FIELD(R09_CONFIG, WRALLOWED, 1, 2)
213 FIELD(R09_CONFIG, RDALLOWED, 1, 1)
214 FIELD(R09_CONFIG, ENABLE, 1, 0)
215REG32(R10_START, 0x1a0)
216 FIELD(R10_START, ADDR, 20, 0)
217REG32(R10_END, 0x1a4)
218 FIELD(R10_END, ADDR, 20, 0)
219REG32(R10_MASTER, 0x1a8)
220 FIELD(R10_MASTER, MASK, 10, 16)
221 FIELD(R10_MASTER, ID, 10, 0)
222REG32(R10_CONFIG, 0x1ac)
223 FIELD(R10_CONFIG, NSCHECKTYPE, 1, 4)
224 FIELD(R10_CONFIG, REGIONNS, 1, 3)
225 FIELD(R10_CONFIG, WRALLOWED, 1, 2)
226 FIELD(R10_CONFIG, RDALLOWED, 1, 1)
227 FIELD(R10_CONFIG, ENABLE, 1, 0)
228REG32(R11_START, 0x1b0)
229 FIELD(R11_START, ADDR, 20, 0)
230REG32(R11_END, 0x1b4)
231 FIELD(R11_END, ADDR, 20, 0)
232REG32(R11_MASTER, 0x1b8)
233 FIELD(R11_MASTER, MASK, 10, 16)
234 FIELD(R11_MASTER, ID, 10, 0)
235REG32(R11_CONFIG, 0x1bc)
236 FIELD(R11_CONFIG, NSCHECKTYPE, 1, 4)
237 FIELD(R11_CONFIG, REGIONNS, 1, 3)
238 FIELD(R11_CONFIG, WRALLOWED, 1, 2)
239 FIELD(R11_CONFIG, RDALLOWED, 1, 1)
240 FIELD(R11_CONFIG, ENABLE, 1, 0)
241REG32(R12_START, 0x1c0)
242 FIELD(R12_START, ADDR, 20, 0)
243REG32(R12_END, 0x1c4)
244 FIELD(R12_END, ADDR, 20, 0)
245REG32(R12_MASTER, 0x1c8)
246 FIELD(R12_MASTER, MASK, 10, 16)
247 FIELD(R12_MASTER, ID, 10, 0)
248REG32(R12_CONFIG, 0x1cc)
249 FIELD(R12_CONFIG, NSCHECKTYPE, 1, 4)
250 FIELD(R12_CONFIG, REGIONNS, 1, 3)
251 FIELD(R12_CONFIG, WRALLOWED, 1, 2)
252 FIELD(R12_CONFIG, RDALLOWED, 1, 1)
253 FIELD(R12_CONFIG, ENABLE, 1, 0)
254REG32(R13_START, 0x1d0)
255 FIELD(R13_START, ADDR, 20, 0)
256REG32(R13_END, 0x1d4)
257 FIELD(R13_END, ADDR, 20, 0)
258REG32(R13_MASTER, 0x1d8)
259 FIELD(R13_MASTER, MASK, 10, 16)
260 FIELD(R13_MASTER, ID, 10, 0)
261REG32(R13_CONFIG, 0x1dc)
262 FIELD(R13_CONFIG, NSCHECKTYPE, 1, 4)
263 FIELD(R13_CONFIG, REGIONNS, 1, 3)
264 FIELD(R13_CONFIG, WRALLOWED, 1, 2)
265 FIELD(R13_CONFIG, RDALLOWED, 1, 1)
266 FIELD(R13_CONFIG, ENABLE, 1, 0)
267REG32(R14_START, 0x1e0)
268 FIELD(R14_START, ADDR, 20, 0)
269REG32(R14_END, 0x1e4)
270 FIELD(R14_END, ADDR, 20, 0)
271REG32(R14_MASTER, 0x1e8)
272 FIELD(R14_MASTER, MASK, 10, 16)
273 FIELD(R14_MASTER, ID, 10, 0)
274REG32(R14_CONFIG, 0x1ec)
275 FIELD(R14_CONFIG, NSCHECKTYPE, 1, 4)
276 FIELD(R14_CONFIG, REGIONNS, 1, 3)
277 FIELD(R14_CONFIG, WRALLOWED, 1, 2)
278 FIELD(R14_CONFIG, RDALLOWED, 1, 1)
279 FIELD(R14_CONFIG, ENABLE, 1, 0)
280REG32(R15_START, 0x1f0)
281 FIELD(R15_START, ADDR, 20, 0)
282REG32(R15_END, 0x1f4)
283 FIELD(R15_END, ADDR, 20, 0)
284REG32(R15_MASTER, 0x1f8)
285 FIELD(R15_MASTER, MASK, 10, 16)
286 FIELD(R15_MASTER, ID, 10, 0)
287REG32(R15_CONFIG, 0x1fc)
288 FIELD(R15_CONFIG, NSCHECKTYPE, 1, 4)
289 FIELD(R15_CONFIG, REGIONNS, 1, 3)
290 FIELD(R15_CONFIG, WRALLOWED, 1, 2)
291 FIELD(R15_CONFIG, RDALLOWED, 1, 1)
292 FIELD(R15_CONFIG, ENABLE, 1, 0)
293
294#define R_MAX (R_R15_CONFIG + 1)
295
296#define NR_XMPU_REGIONS 16
297#define MAX_NR_MASTERS 8
298
299typedef struct XMPU XMPU;
300
301typedef struct XMPUMaster {
302 XMPU *parent;
303
304 AddressSpace *parent_as;
305 MemoryRegion *parent_mr;
306 uint64_t size;
307
308 MemoryRegion mr;
309 MemoryRegion iommu;
310
311 struct {
312 struct {
313 AddressSpace as;
314 MemoryRegion mr;
315 } rw, ro, none;
316 } down;
317
318 struct {
319 MemoryRegion mr[NR_XMPU_REGIONS];
320 } err;
321} XMPUMaster;
322
323struct XMPU {
324 SysBusDevice parent_obj;
325 MemoryRegion iomem;
326
327 MemoryRegion *protected_mr;
328
329
330 XMPUMaster masters[MAX_NR_MASTERS];
331 qemu_irq irq_isr;
332
333 uint64_t addr_mask;
334 uint32_t addr_shift;
335
336 struct {
337 uint32_t nr_masters;
338
339 uint64_t base;
340
341 bool align;
342 bool poison;
343 } cfg;
344
345 uint32_t regs[R_MAX];
346 RegisterInfo regs_info[R_MAX];
347 const char *prefix;
348 bool enabled;
349 qemu_irq enabled_signal;
350};
351
352typedef struct XMPURegion {
353 uint64_t start;
354 uint64_t end;
355 uint64_t size;
356 union {
357 uint32_t u32;
358 struct {
359 uint16_t mask;
360 uint16_t id;
361 };
362 } master;
363 struct {
364 bool nschecktype;
365 bool regionns;
366 bool wrallowed;
367 bool rdallowed;
368 bool enable;
369 } config;
370} XMPURegion;
371
372static void xmpu_decode_region(XMPU *s, XMPURegion *xr, unsigned int region)
373{
374 assert(region < NR_XMPU_REGIONS);
375 uint32_t config;
376 unsigned int offset = region * (R_R01_START - R_R00_START);
377
378 xr->start = s->regs[offset + R_R00_START];
379 xr->end = s->regs[offset + R_R00_END];
380 xr->start <<= 12;
381 xr->end <<= 12;
382
383 xr->size = xr->end - xr->start;
384 xr->master.u32 = s->regs[offset + R_R00_MASTER];
385
386 config = s->regs[offset + R_R00_CONFIG];
387 xr->config.enable = F_EX32(config, R00_CONFIG, ENABLE);
388 xr->config.rdallowed = F_EX32(config, R00_CONFIG, RDALLOWED);
389 xr->config.wrallowed = F_EX32(config, R00_CONFIG, WRALLOWED);
390 xr->config.regionns = F_EX32(config, R00_CONFIG, REGIONNS);
391 xr->config.nschecktype = F_EX32(config, R00_CONFIG, NSCHECKTYPE);
392}
393
394static void isr_update_irq(XMPU *s)
395{
396 bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
397 qemu_set_irq(s->irq_isr, pending);
398}
399
400static void isr_postw(RegisterInfo *reg, uint64_t val64)
401{
402 XMPU *s = XILINX_XMPU(reg->opaque);
403 isr_update_irq(s);
404}
405
406static uint64_t ien_prew(RegisterInfo *reg, uint64_t val64)
407{
408 XMPU *s = XILINX_XMPU(reg->opaque);
409 uint32_t val = val64;
410
411 s->regs[R_IMR] &= ~val;
412 isr_update_irq(s);
413 return 0;
414}
415
416static uint64_t ids_prew(RegisterInfo *reg, uint64_t val64)
417{
418 XMPU *s = XILINX_XMPU(reg->opaque);
419 uint32_t val = val64;
420
421 s->regs[R_IMR] |= val;
422 isr_update_irq(s);
423 return 0;
424}
425
426static void xmpu_update_enabled(XMPU *s)
427{
428 bool regions_enabled = false;
429 bool default_wr = AF_EX32(s->regs, CTRL, DEFWRALLOWED);
430 bool default_rd = AF_EX32(s->regs, CTRL, DEFRDALLOWED);
431 int i;
432
433
434 for (i = NR_XMPU_REGIONS - 1; i >= 0; i--) {
435 XMPURegion xr;
436 xmpu_decode_region(s, &xr, i);
437 if (!xr.config.enable) {
438 continue;
439 }
440 regions_enabled = true;
441 break;
442 }
443
444 s->enabled = true;
445 if (!regions_enabled && default_wr && default_rd) {
446 s->enabled = false;
447 }
448}
449
450static void xmpu_flush(XMPU *s)
451{
452 unsigned int i;
453
454 xmpu_update_enabled(s);
455 qemu_set_irq(s->enabled_signal, s->enabled);
456
457 for (i = 0; i < s->cfg.nr_masters; i++) {
458 IOMMUTLBEntry entry = {
459 .target_as = s->masters[i].parent_as,
460 .iova = 0,
461 .translated_addr = 0,
462 .addr_mask = ~0,
463 .perm = IOMMU_NONE,
464 };
465 memory_region_notify_iommu(&s->masters[i].iommu, entry);
466
467 memory_region_transaction_begin();
468 memory_region_set_readonly(&s->masters[i].iommu, false);
469 memory_region_set_readonly(&s->masters[i].iommu, true);
470 memory_region_set_enabled(&s->masters[i].iommu, s->enabled);
471 memory_region_transaction_commit();
472 }
473}
474
475static void xmpu_setup_postw(RegisterInfo *reg, uint64_t val64)
476{
477 XMPU *s = XILINX_XMPU(reg->opaque);
478 xmpu_flush(s);
479}
480
481static RegisterAccessInfo xmpu_regs_info[] = {
482 { .name = "CTRL", .decode.addr = A_CTRL,
483 .reset = 0x3,
484 .rsvd = 0xfffffff0,
485 .ro = 0xfffffff8,
486 .post_write = xmpu_setup_postw,
487 },{ .name = "ERR_STATUS1", .decode.addr = A_ERR_STATUS1,
488 .rsvd = 0xfff00000,
489 .ro = 0xffffffff,
490 },{ .name = "ERR_STATUS2", .decode.addr = A_ERR_STATUS2,
491 .rsvd = 0xfffffc00,
492 .ro = 0xffffffff,
493 },{ .name = "POISON", .decode.addr = A_POISON,
494 .rsvd = 0xffe00000,
495 .ro = 0xffefffff,
496 .post_write = xmpu_setup_postw,
497 },{ .name = "ISR", .decode.addr = A_ISR,
498 .rsvd = 0xfffffff0,
499 .ro = 0xfffffff0,
500 .w1c = 0xf,
501 .post_write = isr_postw,
502 },{ .name = "IMR", .decode.addr = A_IMR,
503 .reset = 0xf,
504 .rsvd = 0xfffffff0,
505 .ro = 0xffffffff,
506 },{ .name = "IEN", .decode.addr = A_IEN,
507 .rsvd = 0xfffffff0,
508 .ro = 0xfffffff0,
509 .pre_write = ien_prew,
510 },{ .name = "IDS", .decode.addr = A_IDS,
511 .rsvd = 0xfffffff0,
512 .ro = 0xfffffff0,
513 .pre_write = ids_prew,
514 },{ .name = "LOCK", .decode.addr = A_LOCK,
515 },{ .name = "ECO", .decode.addr = A_ECO,
516 },{ .name = "R00_START", .decode.addr = A_R00_START,
517 .rsvd = 0xfff00000,
518 .ro = 0xfff00000,
519 },{ .name = "R00_END", .decode.addr = A_R00_END,
520 .rsvd = 0xfff00000,
521 .ro = 0xfff00000,
522 },{ .name = "R00_MASTER", .decode.addr = A_R00_MASTER,
523 .rsvd = 0xfc00fc00,
524 .ro = 0xfc00fc00,
525 },{ .name = "R00_CONFIG", .decode.addr = A_R00_CONFIG,
526 .reset = 0x8,
527 .rsvd = 0xffffffe0,
528 .ro = 0xffffffe0,
529 },{ .name = "R01_START", .decode.addr = A_R01_START,
530 .rsvd = 0xfff00000,
531 .ro = 0xfff00000,
532 },{ .name = "R01_END", .decode.addr = A_R01_END,
533 .rsvd = 0xfff00000,
534 .ro = 0xfff00000,
535 },{ .name = "R01_MASTER", .decode.addr = A_R01_MASTER,
536 .rsvd = 0xfc00fc00,
537 .ro = 0xfc00fc00,
538 },{ .name = "R01_CONFIG", .decode.addr = A_R01_CONFIG,
539 .reset = 0x8,
540 .rsvd = 0xffffffe0,
541 .ro = 0xffffffe0,
542 },{ .name = "R02_START", .decode.addr = A_R02_START,
543 .rsvd = 0xfff00000,
544 .ro = 0xfff00000,
545 },{ .name = "R02_END", .decode.addr = A_R02_END,
546 .rsvd = 0xfff00000,
547 .ro = 0xfff00000,
548 },{ .name = "R02_MASTER", .decode.addr = A_R02_MASTER,
549 .rsvd = 0xfc00fc00,
550 .ro = 0xfc00fc00,
551 },{ .name = "R02_CONFIG", .decode.addr = A_R02_CONFIG,
552 .reset = 0x8,
553 .rsvd = 0xffffffe0,
554 .ro = 0xffffffe0,
555 },{ .name = "R03_START", .decode.addr = A_R03_START,
556 .rsvd = 0xfff00000,
557 .ro = 0xfff00000,
558 },{ .name = "R03_END", .decode.addr = A_R03_END,
559 .rsvd = 0xfff00000,
560 .ro = 0xfff00000,
561 },{ .name = "R03_MASTER", .decode.addr = A_R03_MASTER,
562 .rsvd = 0xfc00fc00,
563 .ro = 0xfc00fc00,
564 },{ .name = "R03_CONFIG", .decode.addr = A_R03_CONFIG,
565 .reset = 0x8,
566 .rsvd = 0xffffffe0,
567 .ro = 0xffffffe0,
568 },{ .name = "R04_START", .decode.addr = A_R04_START,
569 .rsvd = 0xfff00000,
570 .ro = 0xfff00000,
571 },{ .name = "R04_END", .decode.addr = A_R04_END,
572 .rsvd = 0xfff00000,
573 .ro = 0xfff00000,
574 },{ .name = "R04_MASTER", .decode.addr = A_R04_MASTER,
575 .rsvd = 0xfc00fc00,
576 .ro = 0xfc00fc00,
577 },{ .name = "R04_CONFIG", .decode.addr = A_R04_CONFIG,
578 .reset = 0x8,
579 .rsvd = 0xffffffe0,
580 .ro = 0xffffffe0,
581 },{ .name = "R05_START", .decode.addr = A_R05_START,
582 .rsvd = 0xfff00000,
583 .ro = 0xfff00000,
584 },{ .name = "R05_END", .decode.addr = A_R05_END,
585 .rsvd = 0xfff00000,
586 .ro = 0xfff00000,
587 },{ .name = "R05_MASTER", .decode.addr = A_R05_MASTER,
588 .rsvd = 0xfc00fc00,
589 .ro = 0xfc00fc00,
590 },{ .name = "R05_CONFIG", .decode.addr = A_R05_CONFIG,
591 .reset = 0x8,
592 .rsvd = 0xffffffe0,
593 .ro = 0xffffffe0,
594 },{ .name = "R06_START", .decode.addr = A_R06_START,
595 .rsvd = 0xfff00000,
596 .ro = 0xfff00000,
597 },{ .name = "R06_END", .decode.addr = A_R06_END,
598 .rsvd = 0xfff00000,
599 .ro = 0xfff00000,
600 },{ .name = "R06_MASTER", .decode.addr = A_R06_MASTER,
601 .rsvd = 0xfc00fc00,
602 .ro = 0xfc00fc00,
603 },{ .name = "R06_CONFIG", .decode.addr = A_R06_CONFIG,
604 .reset = 0x8,
605 .rsvd = 0xffffffe0,
606 .ro = 0xffffffe0,
607 },{ .name = "R07_START", .decode.addr = A_R07_START,
608 .rsvd = 0xfff00000,
609 .ro = 0xfff00000,
610 },{ .name = "R07_END", .decode.addr = A_R07_END,
611 .rsvd = 0xfff00000,
612 .ro = 0xfff00000,
613 },{ .name = "R07_MASTER", .decode.addr = A_R07_MASTER,
614 .rsvd = 0xfc00fc00,
615 .ro = 0xfc00fc00,
616 },{ .name = "R07_CONFIG", .decode.addr = A_R07_CONFIG,
617 .reset = 0x8,
618 .rsvd = 0xffffffe0,
619 .ro = 0xffffffe0,
620 },{ .name = "R08_START", .decode.addr = A_R08_START,
621 .rsvd = 0xfff00000,
622 .ro = 0xfff00000,
623 },{ .name = "R08_END", .decode.addr = A_R08_END,
624 .rsvd = 0xfff00000,
625 .ro = 0xfff00000,
626 },{ .name = "R08_MASTER", .decode.addr = A_R08_MASTER,
627 .rsvd = 0xfc00fc00,
628 .ro = 0xfc00fc00,
629 },{ .name = "R08_CONFIG", .decode.addr = A_R08_CONFIG,
630 .reset = 0x8,
631 .rsvd = 0xffffffe0,
632 .ro = 0xffffffe0,
633 },{ .name = "R09_START", .decode.addr = A_R09_START,
634 .rsvd = 0xfff00000,
635 .ro = 0xfff00000,
636 },{ .name = "R09_END", .decode.addr = A_R09_END,
637 .rsvd = 0xfff00000,
638 .ro = 0xfff00000,
639 },{ .name = "R09_MASTER", .decode.addr = A_R09_MASTER,
640 .rsvd = 0xfc00fc00,
641 .ro = 0xfc00fc00,
642 },{ .name = "R09_CONFIG", .decode.addr = A_R09_CONFIG,
643 .reset = 0x8,
644 .rsvd = 0xffffffe0,
645 .ro = 0xffffffe0,
646 },{ .name = "R10_START", .decode.addr = A_R10_START,
647 .rsvd = 0xfff00000,
648 .ro = 0xfff00000,
649 },{ .name = "R10_END", .decode.addr = A_R10_END,
650 .rsvd = 0xfff00000,
651 .ro = 0xfff00000,
652 },{ .name = "R10_MASTER", .decode.addr = A_R10_MASTER,
653 .rsvd = 0xfc00fc00,
654 .ro = 0xfc00fc00,
655 },{ .name = "R10_CONFIG", .decode.addr = A_R10_CONFIG,
656 .reset = 0x8,
657 .rsvd = 0xffffffe0,
658 .ro = 0xffffffe0,
659 },{ .name = "R11_START", .decode.addr = A_R11_START,
660 .rsvd = 0xfff00000,
661 .ro = 0xfff00000,
662 },{ .name = "R11_END", .decode.addr = A_R11_END,
663 .rsvd = 0xfff00000,
664 .ro = 0xfff00000,
665 },{ .name = "R11_MASTER", .decode.addr = A_R11_MASTER,
666 .rsvd = 0xfc00fc00,
667 .ro = 0xfc00fc00,
668 },{ .name = "R11_CONFIG", .decode.addr = A_R11_CONFIG,
669 .reset = 0x8,
670 .rsvd = 0xffffffe0,
671 .ro = 0xffffffe0,
672 },{ .name = "R12_START", .decode.addr = A_R12_START,
673 .rsvd = 0xfff00000,
674 .ro = 0xfff00000,
675 },{ .name = "R12_END", .decode.addr = A_R12_END,
676 .rsvd = 0xfff00000,
677 .ro = 0xfff00000,
678 },{ .name = "R12_MASTER", .decode.addr = A_R12_MASTER,
679 .rsvd = 0xfc00fc00,
680 .ro = 0xfc00fc00,
681 },{ .name = "R12_CONFIG", .decode.addr = A_R12_CONFIG,
682 .reset = 0x8,
683 .rsvd = 0xffffffe0,
684 .ro = 0xffffffe0,
685 },{ .name = "R13_START", .decode.addr = A_R13_START,
686 .rsvd = 0xfff00000,
687 .ro = 0xfff00000,
688 },{ .name = "R13_END", .decode.addr = A_R13_END,
689 .rsvd = 0xfff00000,
690 .ro = 0xfff00000,
691 },{ .name = "R13_MASTER", .decode.addr = A_R13_MASTER,
692 .rsvd = 0xfc00fc00,
693 .ro = 0xfc00fc00,
694 },{ .name = "R13_CONFIG", .decode.addr = A_R13_CONFIG,
695 .reset = 0x8,
696 .rsvd = 0xffffffe0,
697 .ro = 0xffffffe0,
698 },{ .name = "R14_START", .decode.addr = A_R14_START,
699 .rsvd = 0xfff00000,
700 .ro = 0xfff00000,
701 },{ .name = "R14_END", .decode.addr = A_R14_END,
702 .rsvd = 0xfff00000,
703 .ro = 0xfff00000,
704 },{ .name = "R14_MASTER", .decode.addr = A_R14_MASTER,
705 .rsvd = 0xfc00fc00,
706 .ro = 0xfc00fc00,
707 },{ .name = "R14_CONFIG", .decode.addr = A_R14_CONFIG,
708 .reset = 0x8,
709 .rsvd = 0xffffffe0,
710 .ro = 0xffffffe0,
711 },{ .name = "R15_START", .decode.addr = A_R15_START,
712 .rsvd = 0xfff00000,
713 .ro = 0xfff00000,
714 },{ .name = "R15_END", .decode.addr = A_R15_END,
715 .rsvd = 0xfff00000,
716 .ro = 0xfff00000,
717 },{ .name = "R15_MASTER", .decode.addr = A_R15_MASTER,
718 .rsvd = 0xfc00fc00,
719 .ro = 0xfc00fc00,
720 },{ .name = "R15_CONFIG", .decode.addr = A_R15_CONFIG,
721 .reset = 0x8,
722 .rsvd = 0xffffffe0,
723 .ro = 0xffffffe0,
724 }
725};
726
727static void xmpu_reset(DeviceState *dev)
728{
729 XMPU *s = XILINX_XMPU(dev);
730 unsigned int i;
731
732 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
733 register_reset(&s->regs_info[i]);
734 }
735
736 AF_DP32(s->regs, CTRL, ALIGNCFG, s->cfg.align);
737 isr_update_irq(s);
738 xmpu_flush(s);
739}
740
741static uint64_t xmpu_read(void *opaque, hwaddr addr, unsigned size,
742 MemTxAttrs attr)
743{
744 XMPU *s = XILINX_XMPU(opaque);
745 RegisterInfo *r = &s->regs_info[addr / 4];
746
747 if (!attr.secure) {
748
749 return 0;
750 }
751
752 if (!r->data) {
753 qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
754 object_get_canonical_path(OBJECT(s)),
755 addr);
756 AF_DP32(s->regs, ISR, INV_APB, true);
757 return 0;
758 }
759 return register_read(r);
760}
761
762static void xmpu_write(void *opaque, hwaddr addr, uint64_t value,
763 unsigned size, MemTxAttrs attr)
764{
765 XMPU *s = XILINX_XMPU(opaque);
766 RegisterInfo *r = &s->regs_info[addr / 4];
767
768 if (!attr.secure) {
769 return;
770 }
771
772 if (!r->data) {
773 qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
774 object_get_canonical_path(OBJECT(s)),
775 addr, value);
776 AF_DP32(s->regs, ISR, INV_APB, true);
777 return;
778 }
779 register_write(r, value, ~0);
780
781 if (addr > R_R00_MASTER) {
782 xmpu_flush(s);
783 }
784}
785
786static void xmpu_access(MemoryTransaction *tr)
787{
788 MemTxAttrs attr = tr->attr;
789 void *opaque = tr->opaque;
790 XMPU *s = XILINX_XMPU(opaque);
791 hwaddr addr = tr->addr;
792 unsigned size = tr->size;
793 uint64_t value = tr->data.u64;;
794 bool is_write = tr->rw;
795 bool locked;
796
797 locked = AF_EX32(s->regs, LOCK, REGWRDIS);
798 if (locked && (addr < A_ISR || addr >= A_LOCK)) {
799
800 qemu_log_mask(LOG_GUEST_ERROR, "%s: accessing locked register %lx\n",
801 object_get_canonical_path(OBJECT(s)), addr);
802 tr->data.u64 = 0;
803 return;
804 }
805
806 if (is_write) {
807 xmpu_write(opaque, addr, value, size, attr);
808 } else {
809 tr->data.u64 = xmpu_read(opaque, addr, size, attr);
810 }
811}
812
813static const MemoryRegionOps xmpu_ops = {
814 .access = xmpu_access,
815 .endianness = DEVICE_LITTLE_ENDIAN,
816 .valid = {
817 .min_access_size = 1,
818 .max_access_size = 8,
819 },
820};
821
822static IOMMUTLBEntry xmpu_master_translate(XMPUMaster *xm, hwaddr addr,
823 MemTxAttrs *attr,
824 bool *sec_vio)
825{
826 XMPU *s = xm->parent;
827 XMPURegion xr;
828 IOMMUTLBEntry ret = {
829 .iova = addr,
830 .translated_addr = addr,
831 .addr_mask = s->addr_mask,
832 .perm = IOMMU_NONE,
833 };
834 AddressSpace *as_map[] = {
835 [IOMMU_NONE] = &xm->down.none.as,
836 [IOMMU_RO] = &xm->down.ro.as,
837 [IOMMU_WO] = &xm->down.none.as,
838 [IOMMU_RW] = &xm->down.rw.as,
839 };
840 bool default_wr = AF_EX32(s->regs, CTRL, DEFWRALLOWED);
841 bool default_rd = AF_EX32(s->regs, CTRL, DEFRDALLOWED);
842 bool sec = attr->secure;
843 bool sec_access_check;
844 unsigned int nr_matched = 0;
845 int i;
846
847
848 *sec_vio = false;
849
850 if (!s->enabled) {
851 ret.target_as = &xm->down.rw.as;
852 ret.perm = IOMMU_RW;
853 return ret;
854 }
855
856
857 addr += s->cfg.base;
858
859
860 for (i = NR_XMPU_REGIONS - 1; i >= 0; i--) {
861 bool id_match;
862 bool match;
863
864 xmpu_decode_region(s, &xr, i);
865 if (!xr.config.enable) {
866 continue;
867 }
868
869 if (xr.start & s->addr_mask) {
870 qemu_log_mask(LOG_GUEST_ERROR,
871 "%s: Bad region start address %" PRIx64 "\n",
872 s->prefix, xr.start);
873 }
874
875 if (xr.end & s->addr_mask) {
876 qemu_log_mask(LOG_GUEST_ERROR,
877 "%s: Bad region end address %" PRIx64 "\n",
878 s->prefix, xr.end);
879 }
880
881 if (xr.start < s->cfg.base) {
882 qemu_log_mask(LOG_GUEST_ERROR,
883 "%s: Too low region start address %" PRIx64 "\n",
884 s->prefix, xr.end);
885 }
886
887 xr.start &= ~s->addr_mask;
888 xr.end &= ~s->addr_mask;
889
890 id_match = (xr.master.mask & xr.master.id) ==
891 (xr.master.mask & attr->master_id);
892 match = id_match && (addr >= xr.start && addr < xr.end);
893 if (match) {
894 nr_matched++;
895
896
897
898 if (xr.config.nschecktype) {
899
900
901
902 sec_access_check = (sec != xr.config.regionns);
903 } else {
904
905
906
907 sec_access_check = (sec || xr.config.regionns);
908 }
909
910 if (sec_access_check) {
911 if (xr.config.rdallowed) {
912 ret.perm |= IOMMU_RO;
913 }
914 if (xr.config.wrallowed) {
915 ret.perm |= IOMMU_WO;
916 }
917 } else {
918 *sec_vio = true;
919 }
920 break;
921 }
922 }
923
924 if (nr_matched == 0) {
925 if (default_rd) {
926 ret.perm |= IOMMU_RO;
927 }
928 if (default_wr) {
929 ret.perm |= IOMMU_WO;
930 }
931 }
932
933 ret.target_as = as_map[ret.perm];
934 if (ret.perm == IOMMU_RO) {
935 ret.target_as = &xm->down.none.as;
936 }
937#if 0
938 qemu_log("%s: nr_matched=%d AS=%p addr=%lx - > %lx (%lx) perm=%x\n",
939 __func__, nr_matched, ret.target_as, ret.iova,
940 ret.translated_addr, (addr | ret.addr_mask) - addr + 1, ret.perm);
941#endif
942 return ret;
943}
944
945static uint64_t zero_read(void *opaque, hwaddr addr, unsigned size,
946 MemTxAttrs attr)
947{
948 XMPUMaster *xm = opaque;
949 XMPU *s = xm->parent;
950 bool poisoncfg = AF_EX32(s->regs, CTRL, POISONCFG);
951 uint64_t value = 0;
952 bool sec_vio;
953 IOMMUTLBEntry ret = xmpu_master_translate(xm, addr, &attr, &sec_vio);
954
955 if (ret.perm & IOMMU_RO) {
956 dma_memory_read(&xm->down.rw.as, addr, &value, size);
957 } else {
958 if (!(s->regs[R_ISR] & (7 << 1))) {
959 s->regs[R_ERR_STATUS1] = (addr + s->cfg.base) >> 12;
960 }
961 if (poisoncfg) {
962 AddressSpace *as = xm->parent_as;
963 addr = (AF_EX32(s->regs, POISON, BASE) << 12) | (addr & 0xfff);
964 dma_memory_read(as, addr, &value, size);
965 }
966 AF_DP32(s->regs, ERR_STATUS2, AXI_ID, attr.master_id);
967 if (sec_vio) {
968 AF_DP32(s->regs, ISR, SECURITYVIO, true);
969 } else {
970 AF_DP32(s->regs, ISR, RDPERMVIO, true);
971 }
972 isr_update_irq(s);
973 }
974 return value;
975}
976
977static void zero_write(void *opaque, hwaddr addr, uint64_t value,
978 unsigned size, MemTxAttrs attr)
979{
980 XMPUMaster *xm = opaque;
981 XMPU *s = xm->parent;
982 bool poisoncfg = AF_EX32(s->regs, CTRL, POISONCFG);
983 bool sec_vio;
984 IOMMUTLBEntry ret = xmpu_master_translate(xm, addr, &attr, &sec_vio);
985
986 if (ret.perm & IOMMU_WO) {
987 dma_memory_write(&xm->down.rw.as, addr, &value, size);
988 } else {
989 if (!(s->regs[R_ISR] & (7 << 1))) {
990 s->regs[R_ERR_STATUS1] = (addr + s->cfg.base) >> 12;
991 }
992 if (poisoncfg) {
993 AddressSpace *as = xm->parent_as;
994 addr = (AF_EX32(s->regs, POISON, BASE) << 12) | (addr & 0xfff);
995 dma_memory_write(as, addr, &value, size);
996 }
997 AF_DP32(s->regs, ERR_STATUS2, AXI_ID, attr.master_id);
998 if (sec_vio) {
999 AF_DP32(s->regs, ISR, SECURITYVIO, true);
1000 } else {
1001 AF_DP32(s->regs, ISR, WRPERMVIO, true);
1002 }
1003 isr_update_irq(s);
1004 }
1005}
1006
1007static void zero_access(MemoryTransaction *tr)
1008{
1009 MemTxAttrs attr = tr->attr;
1010 void *opaque = tr->opaque;
1011 hwaddr addr = tr->addr;
1012 unsigned size = tr->size;
1013 uint64_t value = tr->data.u64;;
1014 bool is_write = tr->rw;
1015
1016 if (is_write) {
1017 zero_write(opaque, addr, value, size, attr);
1018 } else {
1019 tr->data.u64 = zero_read(opaque, addr, size, attr);
1020 }
1021}
1022
1023static const MemoryRegionOps zero_ops = {
1024 .access = zero_access,
1025 .endianness = DEVICE_LITTLE_ENDIAN,
1026 .valid = {
1027 .min_access_size = 4,
1028 .max_access_size = 4,
1029 },
1030};
1031
1032static IOMMUTLBEntry xmpu_translate(MemoryRegion *mr, hwaddr addr,
1033 bool is_write, MemTxAttrs *attr)
1034{
1035 XMPUMaster *xm;
1036 IOMMUTLBEntry ret;
1037 bool sec_vio;
1038
1039 xm = container_of(mr, XMPUMaster, iommu);
1040 ret = xmpu_master_translate(xm, addr, attr, &sec_vio);
1041#if 0
1042 qemu_log("%s: nr_matched=%d addr=%lx - > %lx (%lx) perm=%x\n",
1043 __func__, nr_matched, ret.iova,
1044 ret.translated_addr, (addr | ret.addr_mask) - addr + 1, ret.perm);
1045#endif
1046 ret.perm = IOMMU_RW;
1047 return ret;
1048}
1049
1050static MemoryRegionIOMMUOps xmpu_iommu_ops = {
1051 .translate_attr = xmpu_translate,
1052};
1053
1054#define MASK_4K (0xfff)
1055#define MASK_1M (0xfffff)
1056static void xmpu_realize(DeviceState *dev, Error **errp)
1057{
1058 XMPU *s = XILINX_XMPU(dev);
1059 unsigned int i;
1060
1061 s->prefix = object_get_canonical_path(OBJECT(dev));
1062
1063 for (i = 0; i < ARRAY_SIZE(xmpu_regs_info); ++i) {
1064 RegisterInfo *r = &s->regs_info[xmpu_regs_info[i].decode.addr/4];
1065
1066 *r = (RegisterInfo) {
1067 .data = (uint8_t *)&s->regs[
1068 xmpu_regs_info[i].decode.addr/4],
1069 .data_size = sizeof(uint32_t),
1070 .access = &xmpu_regs_info[i],
1071 .debug = XILINX_XMPU_ERR_DEBUG,
1072 .prefix = s->prefix,
1073 .opaque = s,
1074 };
1075 }
1076
1077 s->addr_shift = s->cfg.align ? 20 : 12;
1078 s->addr_mask = (1ULL << s->addr_shift) - 1;
1079
1080 s->masters[0].parent = s;
1081}
1082
1083static void xmpu_init(Object *obj)
1084{
1085 XMPU *s = XILINX_XMPU(obj);
1086 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1087
1088 sysbus_init_irq(sbd, &s->irq_isr);
1089
1090 object_property_add_link(obj, "protected-mr", TYPE_MEMORY_REGION,
1091 (Object **)&s->protected_mr,
1092 qdev_prop_allow_set_link_before_realize,
1093 OBJ_PROP_LINK_UNREF_ON_RELEASE,
1094 &error_abort);
1095 object_property_add_link(obj, "mr-0", TYPE_MEMORY_REGION,
1096 (Object **)&s->masters[0].parent_mr,
1097 qdev_prop_allow_set_link_before_realize,
1098 OBJ_PROP_LINK_UNREF_ON_RELEASE,
1099 &error_abort);
1100
1101 qdev_init_gpio_out(DEVICE(sbd), &s->enabled_signal, 1);
1102}
1103
1104static bool xmpu_parse_reg(FDTGenericMMap *obj, FDTGenericRegPropInfo reg,
1105 Error **errp)
1106{
1107 XMPU *s = XILINX_XMPU(obj);
1108 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1109 ObjectClass *klass = object_class_by_name(TYPE_XILINX_XMPU);
1110 FDTGenericMMapClass *parent_fmc;
1111 char *name;
1112 unsigned int i, mid;
1113
1114 parent_fmc = FDT_GENERIC_MMAP_CLASS(object_class_get_parent(klass));
1115 memory_region_init_io(&s->iomem, OBJECT(obj), &xmpu_ops, s,
1116 TYPE_XILINX_XMPU, R_MAX * 4);
1117 sysbus_init_mmio(sbd, &s->iomem);
1118
1119 for (i = 0; i < (reg.n - 1); i++) {
1120 mid = i;
1121
1122
1123 name = g_strdup_printf("xmpu-down-rw-master%d", mid);
1124 memory_region_init_alias(&s->masters[mid].down.rw.mr, OBJECT(s),
1125 name, s->protected_mr,
1126 0, UINT64_MAX);
1127 address_space_init(&s->masters[mid].down.rw.as,
1128 &s->masters[mid].down.rw.mr, name);
1129 g_free(name);
1130
1131
1132 name = g_strdup_printf("xmpu-down-ro-master%d", mid);
1133 memory_region_init_alias(&s->masters[mid].down.ro.mr, OBJECT(s),
1134 name, s->protected_mr,
1135 0, UINT64_MAX);
1136 memory_region_set_readonly(&s->masters[mid].down.ro.mr, true);
1137 address_space_init(&s->masters[mid].down.ro.as,
1138 &s->masters[mid].down.ro.mr, name);
1139 g_free(name);
1140
1141
1142 name = g_strdup_printf("xmpu-down-none-master\n");
1143 memory_region_init_io(&s->masters[mid].down.none.mr, OBJECT(s),
1144 &zero_ops, &s->masters[mid],
1145 name, UINT64_MAX);
1146 address_space_init(&s->masters[mid].down.none.as,
1147 &s->masters[mid].down.none.mr, name);
1148 g_free(name);
1149
1150 name = g_strdup_printf("xmpu-master-%d\n", mid);
1151 s->masters[mid].parent_as = address_space_init_shareable(
1152 s->masters[mid].parent_mr,
1153 NULL);
1154
1155 memory_region_init_iommu(&s->masters[mid].iommu,
1156 OBJECT(s), &xmpu_iommu_ops,
1157 name, reg.s[i + 1]);
1158 g_free(name);
1159
1160 name = g_strdup_printf("xmpu-mr-%d\n", mid);
1161 memory_region_init(&s->masters[mid].mr, OBJECT(s), name, UINT64_MAX);
1162
1163 memory_region_add_subregion_overlap(&s->masters[mid].mr,
1164 0, &s->masters[mid].down.rw.mr, 0);
1165 memory_region_add_subregion_overlap(&s->masters[mid].mr,
1166 0, &s->masters[mid].iommu, 1);
1167 memory_region_set_enabled(&s->masters[mid].iommu, false);
1168 sysbus_init_mmio(sbd, &s->masters[mid].mr);
1169 g_free(name);
1170 }
1171 s->cfg.nr_masters = (i / 2) + 1;
1172
1173 return parent_fmc ? parent_fmc->parse_reg(obj, reg, errp) : false;
1174}
1175
1176static Property xmpu_properties[] = {
1177 DEFINE_PROP_BOOL("align", XMPU, cfg.align, 0),
1178 DEFINE_PROP_BOOL("poison", XMPU, cfg.poison, 0),
1179 DEFINE_PROP_UINT64("protected-base", XMPU, cfg.base, 0),
1180 DEFINE_PROP_END_OF_LIST(),
1181};
1182
1183static const VMStateDescription vmstate_xmpu = {
1184 .name = TYPE_XILINX_XMPU,
1185 .version_id = 1,
1186 .minimum_version_id = 1,
1187 .minimum_version_id_old = 1,
1188 .fields = (VMStateField[]) {
1189 VMSTATE_UINT32_ARRAY(regs, XMPU, R_MAX),
1190 VMSTATE_END_OF_LIST(),
1191 }
1192};
1193
1194static void xmpu_class_init(ObjectClass *klass, void *data)
1195{
1196 DeviceClass *dc = DEVICE_CLASS(klass);
1197 FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_CLASS(klass);
1198
1199 dc->reset = xmpu_reset;
1200 dc->realize = xmpu_realize;
1201 dc->vmsd = &vmstate_xmpu;
1202 dc->props = xmpu_properties;
1203 fmc->parse_reg = xmpu_parse_reg;
1204}
1205
1206static const TypeInfo xmpu_info = {
1207 .name = TYPE_XILINX_XMPU,
1208 .parent = TYPE_SYS_BUS_DEVICE,
1209 .instance_size = sizeof(XMPU),
1210 .class_init = xmpu_class_init,
1211 .instance_init = xmpu_init,
1212 .interfaces = (InterfaceInfo[]) {
1213 { TYPE_FDT_GENERIC_MMAP },
1214 { },
1215 },
1216};
1217
1218static void xmpu_register_types(void)
1219{
1220 type_register_static(&xmpu_info);
1221}
1222
1223type_init(xmpu_register_types)
1224