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#include "qemu/osdep.h"
29#include "hw/sysbus.h"
30#include "hw/register.h"
31#include "qemu/bitops.h"
32#include "sysemu/dma.h"
33#include "qapi/error.h"
34#include "qemu/log.h"
35
36#include "hw/fdt_generic_util.h"
37
38#ifndef XILINX_XPPU_ERR_DEBUG
39#define XILINX_XPPU_ERR_DEBUG 0
40#endif
41
42#define TYPE_XILINX_XPPU "xlnx.xppu"
43
44#define XILINX_XPPU(obj) \
45 OBJECT_CHECK(XPPU, (obj), TYPE_XILINX_XPPU)
46
47REG32(CTRL, 0x0)
48 FIELD(CTRL, APER_PARITY_EN, 1, 2)
49 FIELD(CTRL, MID_PARITY_EN, 1, 1)
50 FIELD(CTRL, ENABLE, 1, 0)
51REG32(ERR_STATUS1, 0x4)
52 FIELD(ERR_STATUS1, AXI_ADDR, 20, 0)
53REG32(ERR_STATUS2, 0x8)
54 FIELD(ERR_STATUS2, AXI_ID, 10, 0)
55REG32(POISON, 0xc)
56 FIELD(POISON, BASE, 20, 0)
57REG32(ISR, 0x10)
58 FIELD(ISR, APER_PARITY, 1, 7)
59 FIELD(ISR, APER_TZ, 1, 6)
60 FIELD(ISR, APER_PERM, 1, 5)
61 FIELD(ISR, MID_PARITY, 1, 3)
62 FIELD(ISR, MID_RO, 1, 2)
63 FIELD(ISR, MID_MISS, 1, 1)
64 FIELD(ISR, INV_APB, 1, 0)
65REG32(IMR, 0x14)
66 FIELD(IMR, APER_PARITY, 1, 7)
67 FIELD(IMR, APER_TZ, 1, 6)
68 FIELD(IMR, APER_PERM, 1, 5)
69 FIELD(IMR, MID_PARITY, 1, 3)
70 FIELD(IMR, MID_RO, 1, 2)
71 FIELD(IMR, MID_MISS, 1, 1)
72 FIELD(IMR, INV_APB, 1, 0)
73REG32(IEN, 0x18)
74 FIELD(IEN, APER_PARITY, 1, 7)
75 FIELD(IEN, APER_TZ, 1, 6)
76 FIELD(IEN, APER_PERM, 1, 5)
77 FIELD(IEN, MID_PARITY, 1, 3)
78 FIELD(IEN, MID_RO, 1, 2)
79 FIELD(IEN, MID_MISS, 1, 1)
80 FIELD(IEN, INV_APB, 1, 0)
81REG32(IDS, 0x1c)
82 FIELD(IDS, APER_PARITY, 1, 7)
83 FIELD(IDS, APER_TZ, 1, 6)
84 FIELD(IDS, APER_PERM, 1, 5)
85 FIELD(IDS, MID_PARITY, 1, 3)
86 FIELD(IDS, MID_RO, 1, 2)
87 FIELD(IDS, MID_MISS, 1, 1)
88 FIELD(IDS, INV_APB, 1, 0)
89REG32(M_MASTER_IDS, 0x3c)
90REG32(M_APERTURE_32B, 0x40)
91REG32(M_APERTURE_64KB, 0x44)
92REG32(M_APERTURE_1MB, 0x48)
93REG32(M_APERTURE_512MB, 0x4c)
94REG32(BASE_32B, 0x50)
95REG32(BASE_64KB, 0x54)
96REG32(BASE_1MB, 0x58)
97REG32(BASE_512MB, 0x5c)
98REG32(ECO, 0xfc)
99REG32(MASTER_ID00, 0x100)
100 FIELD(MASTER_ID00, MIDP, 1, 31)
101 FIELD(MASTER_ID00, MIDR, 1, 30)
102 FIELD(MASTER_ID00, MIDM, 10, 16)
103 FIELD(MASTER_ID00, MID, 10, 0)
104REG32(MASTER_ID01, 0x104)
105 FIELD(MASTER_ID01, MIDP, 1, 31)
106 FIELD(MASTER_ID01, MIDR, 1, 30)
107 FIELD(MASTER_ID01, MIDM, 10, 16)
108 FIELD(MASTER_ID01, MID, 10, 0)
109REG32(MASTER_ID02, 0x108)
110 FIELD(MASTER_ID02, MIDP, 1, 31)
111 FIELD(MASTER_ID02, MIDR, 1, 30)
112 FIELD(MASTER_ID02, MIDM, 10, 16)
113 FIELD(MASTER_ID02, MID, 10, 0)
114REG32(MASTER_ID03, 0x10c)
115 FIELD(MASTER_ID03, MIDP, 1, 31)
116 FIELD(MASTER_ID03, MIDR, 1, 30)
117 FIELD(MASTER_ID03, MIDM, 10, 16)
118 FIELD(MASTER_ID03, MID, 10, 0)
119REG32(MASTER_ID04, 0x110)
120 FIELD(MASTER_ID04, MIDP, 1, 31)
121 FIELD(MASTER_ID04, MIDR, 1, 30)
122 FIELD(MASTER_ID04, MIDM, 10, 16)
123 FIELD(MASTER_ID04, MID, 10, 0)
124REG32(MASTER_ID05, 0x114)
125 FIELD(MASTER_ID05, MIDP, 1, 31)
126 FIELD(MASTER_ID05, MIDR, 1, 30)
127 FIELD(MASTER_ID05, MIDM, 10, 16)
128 FIELD(MASTER_ID05, MID, 10, 0)
129REG32(MASTER_ID06, 0x118)
130 FIELD(MASTER_ID06, MIDP, 1, 31)
131 FIELD(MASTER_ID06, MIDR, 1, 30)
132 FIELD(MASTER_ID06, MIDM, 10, 16)
133 FIELD(MASTER_ID06, MID, 10, 0)
134REG32(MASTER_ID07, 0x11c)
135 FIELD(MASTER_ID07, MIDP, 1, 31)
136 FIELD(MASTER_ID07, MIDR, 1, 30)
137 FIELD(MASTER_ID07, MIDM, 10, 16)
138 FIELD(MASTER_ID07, MID, 10, 0)
139REG32(MASTER_ID08, 0x120)
140 FIELD(MASTER_ID08, MIDP, 1, 31)
141 FIELD(MASTER_ID08, MIDR, 1, 30)
142 FIELD(MASTER_ID08, MIDM, 10, 16)
143 FIELD(MASTER_ID08, MID, 10, 0)
144REG32(MASTER_ID09, 0x124)
145 FIELD(MASTER_ID09, MIDP, 1, 31)
146 FIELD(MASTER_ID09, MIDR, 1, 30)
147 FIELD(MASTER_ID09, MIDM, 10, 16)
148 FIELD(MASTER_ID09, MID, 10, 0)
149REG32(MASTER_ID10, 0x128)
150 FIELD(MASTER_ID10, MIDP, 1, 31)
151 FIELD(MASTER_ID10, MIDR, 1, 30)
152 FIELD(MASTER_ID10, MIDM, 10, 16)
153 FIELD(MASTER_ID10, MID, 10, 0)
154REG32(MASTER_ID11, 0x12c)
155 FIELD(MASTER_ID11, MIDP, 1, 31)
156 FIELD(MASTER_ID11, MIDR, 1, 30)
157 FIELD(MASTER_ID11, MIDM, 10, 16)
158 FIELD(MASTER_ID11, MID, 10, 0)
159REG32(MASTER_ID12, 0x130)
160 FIELD(MASTER_ID12, MIDP, 1, 31)
161 FIELD(MASTER_ID12, MIDR, 1, 30)
162 FIELD(MASTER_ID12, MIDM, 10, 16)
163 FIELD(MASTER_ID12, MID, 10, 0)
164REG32(MASTER_ID13, 0x134)
165 FIELD(MASTER_ID13, MIDP, 1, 31)
166 FIELD(MASTER_ID13, MIDR, 1, 30)
167 FIELD(MASTER_ID13, MIDM, 10, 16)
168 FIELD(MASTER_ID13, MID, 10, 0)
169REG32(MASTER_ID14, 0x138)
170 FIELD(MASTER_ID14, MIDP, 1, 31)
171 FIELD(MASTER_ID14, MIDR, 1, 30)
172 FIELD(MASTER_ID14, MIDM, 10, 16)
173 FIELD(MASTER_ID14, MID, 10, 0)
174REG32(MASTER_ID15, 0x13c)
175 FIELD(MASTER_ID15, MIDP, 1, 31)
176 FIELD(MASTER_ID15, MIDR, 1, 30)
177 FIELD(MASTER_ID15, MIDM, 10, 16)
178 FIELD(MASTER_ID15, MID, 10, 0)
179REG32(MASTER_ID16, 0x140)
180 FIELD(MASTER_ID16, MIDP, 1, 31)
181 FIELD(MASTER_ID16, MIDR, 1, 30)
182 FIELD(MASTER_ID16, MIDM, 10, 16)
183 FIELD(MASTER_ID16, MID, 10, 0)
184REG32(MASTER_ID17, 0x144)
185 FIELD(MASTER_ID17, MIDP, 1, 31)
186 FIELD(MASTER_ID17, MIDR, 1, 30)
187 FIELD(MASTER_ID17, MIDM, 10, 16)
188 FIELD(MASTER_ID17, MID, 10, 0)
189REG32(MASTER_ID18, 0x148)
190 FIELD(MASTER_ID18, MIDP, 1, 31)
191 FIELD(MASTER_ID18, MIDR, 1, 30)
192 FIELD(MASTER_ID18, MIDM, 10, 16)
193 FIELD(MASTER_ID18, MID, 10, 0)
194REG32(MASTER_ID19, 0x14c)
195 FIELD(MASTER_ID19, MIDP, 1, 31)
196 FIELD(MASTER_ID19, MIDR, 1, 30)
197 FIELD(MASTER_ID19, MIDM, 10, 16)
198 FIELD(MASTER_ID19, MID, 10, 0)
199REG32(RAM_ADJ, 0x1fc)
200 FIELD(RAM_ADJ, MESSAGE_EMAS, 1, 13)
201 FIELD(RAM_ADJ, MESSAGE_EMAW, 2, 11)
202 FIELD(RAM_ADJ, MESSAGE_EMA, 3, 8)
203 FIELD(RAM_ADJ, PERMISSION_EMAS, 1, 5)
204 FIELD(RAM_ADJ, PERMISSION_EMAW, 2, 3)
205 FIELD(RAM_ADJ, PERMISSION_EMA, 3, 0)
206
207#define R_MAX (R_RAM_ADJ + 1)
208
209#define NR_MID_ENTRIES 20
210
211#define NR_32B_APL_ENTRIES 128
212#define NR_64K_APL_ENTRIES 256
213#define NR_1M_APL_ENTRIES 16
214#define NR_512M_APL_ENTRIES 1
215#define NR_APL_ENTRIES (NR_32B_APL_ENTRIES + NR_64K_APL_ENTRIES \
216 + NR_1M_APL_ENTRIES + NR_512M_APL_ENTRIES)
217
218typedef enum {
219 GRANULE_32B,
220 GRANULE_64K,
221 GRANULE_1M,
222 GRANULE_512M,
223} XPPUGranule;
224
225typedef struct XPPU XPPU;
226
227typedef struct XPPUAperture {
228 XPPU *parent;
229 MemoryRegion iomem;
230
231 XPPUGranule granule;
232
233 uint64_t base;
234
235 uint64_t extract_mask;
236 uint64_t extract_shift;
237
238 uint32_t ram_base;
239} XPPUAperture;
240
241struct XPPU {
242 SysBusDevice parent_obj;
243 MemoryRegion iomem;
244 qemu_irq irq_isr;
245
246 MemoryRegion *mr;
247 AddressSpace *as;
248
249 XPPUAperture ap[4];
250
251 uint32_t perm_ram[NR_APL_ENTRIES];
252
253 uint32_t regs[R_MAX];
254 RegisterInfo regs_info[R_MAX];
255};
256
257static bool parity32(uint32_t v)
258{
259
260
261
262 v = v ^ (v >> 16);
263 v = v ^ (v >> 8);
264 v = v ^ (v >> 4);
265 v = v ^ (v >> 2);
266 v = v ^ (v >> 1);
267 return v & 1;
268}
269
270static bool check_mid_parity(XPPU *s, uint32_t val32)
271{
272 static const uint32_t rsvd = 0x3c00fc00;
273 bool p_written;
274 bool p_computed;
275
276 if (!AF_EX32(s->regs, CTRL, MID_PARITY_EN)) {
277 return true;
278 }
279
280
281 p_written = val32 & 0x80000000;
282
283
284 val32 &= ~0x80000000;
285
286 val32 &= ~rsvd;
287 p_computed = parity32(val32);
288
289 return p_written == p_computed;
290}
291
292static void check_mid_parities(XPPU *s)
293{
294 unsigned int i;
295
296 for (i = 0; i < NR_MID_ENTRIES; i++) {
297 uint32_t val32;
298
299 val32 = s->regs[R_MASTER_ID00 + i];
300
301
302 if (check_mid_parity(s, val32) == false) {
303 AF_DP32(s->regs, ISR, MID_PARITY, true);
304 continue;
305 }
306 }
307}
308
309static bool check_apl_parity(XPPU *s, uint32_t val32)
310{
311 unsigned int i;
312
313
314
315
316
317 static const uint32_t apl_parities[] = {
318 0x1f,
319 0x1f << 5,
320 0x1f << 10,
321 (0x1f << 15) | 1 << 27,
322 };
323 uint32_t p = 0, p_written;
324 bool ok;
325
326 if (!AF_EX32(s->regs, CTRL, APER_PARITY_EN)) {
327 return true;
328 }
329
330 for (i = 0; i < ARRAY_SIZE(apl_parities); i++) {
331 uint32_t v = val32;
332 bool parity;
333
334
335 v &= apl_parities[i];
336 parity = parity32(v);
337 p |= ((int) parity) << i;
338 }
339
340 p_written = val32 >> 28;
341 ok = p_written == p;
342
343 if (!ok) {
344 qemu_log_mask(LOG_GUEST_ERROR, "Bad APL parity!\n");
345 AF_DP32(s->regs, ISR, APER_PARITY, true);
346 }
347 return ok;
348}
349
350static void isr_update_irq(XPPU *s)
351{
352 bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
353 qemu_set_irq(s->irq_isr, pending);
354}
355
356static void isr_postw(RegisterInfo *reg, uint64_t val64)
357{
358 XPPU *s = XILINX_XPPU(reg->opaque);
359 isr_update_irq(s);
360}
361
362static uint64_t ien_prew(RegisterInfo *reg, uint64_t val64)
363{
364 XPPU *s = XILINX_XPPU(reg->opaque);
365 uint32_t val = val64;
366
367 s->regs[R_IMR] &= ~val;
368 isr_update_irq(s);
369 return 0;
370}
371
372static uint64_t ids_prew(RegisterInfo *reg, uint64_t val64)
373{
374 XPPU *s = XILINX_XPPU(reg->opaque);
375 uint32_t val = val64;
376
377 s->regs[R_IMR] |= val;
378 isr_update_irq(s);
379 return 0;
380}
381
382static void update_mrs(XPPU *s)
383{
384 bool xppu_enabled = AF_EX32(s->regs, CTRL, ENABLE);
385 unsigned int i;
386
387 for (i = 0; i < ARRAY_SIZE(s->ap); i++) {
388 memory_region_set_enabled(&s->ap[i].iomem, xppu_enabled);
389 }
390}
391
392static void ctrl_postw(RegisterInfo *reg, uint64_t val64)
393{
394 XPPU *s = XILINX_XPPU(reg->opaque);
395 update_mrs(s);
396 check_mid_parities(s);
397 isr_update_irq(s);
398}
399
400static void mid_postw(RegisterInfo *reg, uint64_t val64)
401{
402 XPPU *s = XILINX_XPPU(reg->opaque);
403 check_mid_parity(s, val64);
404 isr_update_irq(s);
405}
406
407static RegisterAccessInfo xppu_regs_info[] = {
408 { .name = "CTRL", .decode.addr = A_CTRL,
409 .rsvd = 0xfffffff8,
410 .ro = 0xfffffff8,
411 .post_write = ctrl_postw,
412 },{ .name = "ERR_STATUS1", .decode.addr = A_ERR_STATUS1,
413 .rsvd = 0xfff00000,
414 .ro = 0xffffffff,
415 },{ .name = "ERR_STATUS2", .decode.addr = A_ERR_STATUS2,
416 .rsvd = 0xfffffc00,
417 .ro = 0xffffffff,
418 },{ .name = "POISON", .decode.addr = A_POISON,
419 .reset = 0xff9c0,
420 .rsvd = 0xfff00000,
421 .ro = 0xffffffff,
422 },{ .name = "ISR", .decode.addr = A_ISR,
423 .rsvd = 0xffffff10,
424 .ro = 0xffffff10,
425 .w1c = 0xef,
426 .post_write = isr_postw,
427 },{ .name = "IMR", .decode.addr = A_IMR,
428 .reset = 0xef,
429 .rsvd = 0xffffff10,
430 .ro = 0xffffffff,
431 },{ .name = "IEN", .decode.addr = A_IEN,
432 .rsvd = 0xffffff10,
433 .ro = 0xffffff10,
434 .pre_write = ien_prew,
435 },{ .name = "IDS", .decode.addr = A_IDS,
436 .rsvd = 0xffffff10,
437 .ro = 0xffffff10,
438 .pre_write = ids_prew,
439 },{ .name = "M_MASTER_IDS", .decode.addr = A_M_MASTER_IDS,
440 .reset = 0x14,
441 .ro = 0xffffffff,
442 },{ .name = "M_APERTURE_32B", .decode.addr = A_M_APERTURE_32B,
443 .reset = 0x80,
444 .ro = 0xffffffff,
445 },{ .name = "M_APERTURE_64KB", .decode.addr = A_M_APERTURE_64KB,
446 .reset = 0x100,
447 .ro = 0xffffffff,
448 },{ .name = "M_APERTURE_1MB", .decode.addr = A_M_APERTURE_1MB,
449 .reset = 0x10,
450 .ro = 0xffffffff,
451 },{ .name = "M_APERTURE_512MB", .decode.addr = A_M_APERTURE_512MB,
452 .reset = 0x1,
453 .ro = 0xffffffff,
454 },{ .name = "BASE_32B", .decode.addr = A_BASE_32B,
455 .reset = 0xff990000,
456 .ro = 0xffffffff,
457 },{ .name = "BASE_64KB", .decode.addr = A_BASE_64KB,
458 .reset = 0xff000000,
459 .ro = 0xffffffff,
460 },{ .name = "BASE_1MB", .decode.addr = A_BASE_1MB,
461 .reset = 0xfe000000,
462 .ro = 0xffffffff,
463 },{ .name = "BASE_512MB", .decode.addr = A_BASE_512MB,
464 .reset = 0xc0000000,
465 .ro = 0xffffffff,
466 },{ .name = "ECO", .decode.addr = A_ECO,
467 },{ .name = "MASTER_ID00", .decode.addr = A_MASTER_ID00,
468 .reset = 0x83ff0040,
469 .rsvd = 0x3c00fc00,
470 .ro = 0x3c00fc00,
471 .post_write = mid_postw,
472 },{ .name = "MASTER_ID01", .decode.addr = A_MASTER_ID01,
473 .reset = 0x3f00000,
474 .rsvd = 0x3c00fc00,
475 .ro = 0x3c00fc00,
476 .post_write = mid_postw,
477 },{ .name = "MASTER_ID02", .decode.addr = A_MASTER_ID02,
478 .reset = 0x83f00010,
479 .rsvd = 0x3c00fc00,
480 .ro = 0x3c00fc00,
481 .post_write = mid_postw,
482 },{ .name = "MASTER_ID03", .decode.addr = A_MASTER_ID03,
483 .reset = 0x83c00080,
484 .rsvd = 0x3c00fc00,
485 .ro = 0x3c00fc00,
486 .post_write = mid_postw,
487 },{ .name = "MASTER_ID04", .decode.addr = A_MASTER_ID04,
488 .reset = 0x83c30080,
489 .rsvd = 0x3c00fc00,
490 .ro = 0x3c00fc00,
491 },{ .name = "MASTER_ID05", .decode.addr = A_MASTER_ID05,
492 .reset = 0x3c30081,
493 .rsvd = 0x3c00fc00,
494 .ro = 0x3c00fc00,
495 },{ .name = "MASTER_ID06", .decode.addr = A_MASTER_ID06,
496 .reset = 0x3c30082,
497 .rsvd = 0x3c00fc00,
498 .ro = 0x3c00fc00,
499 },{ .name = "MASTER_ID07", .decode.addr = A_MASTER_ID07,
500 .reset = 0x83c30083,
501 .rsvd = 0x3c00fc00,
502 .ro = 0x3c00fc00,
503 },{ .name = "MASTER_ID08", .decode.addr = A_MASTER_ID08,
504 .rsvd = 0x3c00fc00,
505 .ro = 0x3c00fc00,
506 },{ .name = "MASTER_ID09", .decode.addr = A_MASTER_ID09,
507 .rsvd = 0x3c00fc00,
508 .ro = 0x3c00fc00,
509 },{ .name = "MASTER_ID10", .decode.addr = A_MASTER_ID10,
510 .rsvd = 0x3c00fc00,
511 .ro = 0x3c00fc00,
512 },{ .name = "MASTER_ID11", .decode.addr = A_MASTER_ID11,
513 .rsvd = 0x3c00fc00,
514 .ro = 0x3c00fc00,
515 },{ .name = "MASTER_ID12", .decode.addr = A_MASTER_ID12,
516 .rsvd = 0x3c00fc00,
517 .ro = 0x3c00fc00,
518 },{ .name = "MASTER_ID13", .decode.addr = A_MASTER_ID13,
519 .rsvd = 0x3c00fc00,
520 .ro = 0x3c00fc00,
521 },{ .name = "MASTER_ID14", .decode.addr = A_MASTER_ID14,
522 .rsvd = 0x3c00fc00,
523 .ro = 0x3c00fc00,
524 },{ .name = "MASTER_ID15", .decode.addr = A_MASTER_ID15,
525 .rsvd = 0x3c00fc00,
526 .ro = 0x3c00fc00,
527 },{ .name = "MASTER_ID16", .decode.addr = A_MASTER_ID16,
528 .rsvd = 0x3c00fc00,
529 .ro = 0x3c00fc00,
530 },{ .name = "MASTER_ID17", .decode.addr = A_MASTER_ID17,
531 .rsvd = 0x3c00fc00,
532 .ro = 0x3c00fc00,
533 },{ .name = "MASTER_ID18", .decode.addr = A_MASTER_ID18,
534 .rsvd = 0x3c00fc00,
535 .ro = 0x3c00fc00,
536 },{ .name = "MASTER_ID19", .decode.addr = A_MASTER_ID19,
537 .rsvd = 0x3c00fc00,
538 .ro = 0x3c00fc00,
539 },{ .name = "RAM_ADJ", .decode.addr = A_RAM_ADJ,
540 .reset = 0xb0b,
541 .rsvd = 0xffffc0c0,
542 .ro = 0xffffc0c0,
543 }
544};
545
546static void xppu_reset(DeviceState *dev)
547{
548 XPPU *s = XILINX_XPPU(dev);
549 unsigned int i;
550
551 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
552 register_reset(&s->regs_info[i]);
553 }
554 update_mrs(s);
555 isr_update_irq(s);
556}
557
558static bool xppu_ap_check(XPPU *s, MemoryTransaction *tr, uint32_t apl)
559{
560 unsigned int i;
561 bool mid_match = false;
562 bool tz = extract32(apl, 27, 1);
563 bool ok;
564
565 ok = check_apl_parity(s, apl);
566 if (!ok) {
567 return false;
568 }
569
570
571 for (i = 0; i < NR_MID_ENTRIES; i++) {
572 uint32_t val32, mid, mask;
573 bool readonly;
574
575 if (!extract32(apl, i, 1)) {
576 continue;
577 }
578
579 val32 = s->regs[R_MASTER_ID00 + i];
580 mid = F_EX32(val32, MASTER_ID00, MID);
581 readonly = F_EX32(val32, MASTER_ID00, MIDR);
582 mask = F_EX32(val32, MASTER_ID00, MIDM);
583
584 if ((mid & mask) != (tr->attr.master_id & mask)) {
585 continue;
586 }
587
588 mid_match = true;
589
590
591 if (check_mid_parity(s, val32) == false) {
592 AF_DP32(s->regs, ISR, MID_PARITY, true);
593 continue;
594 }
595
596 if (readonly && tr->rw) {
597 AF_DP32(s->regs, ISR, MID_RO, true);
598 continue;
599 }
600
601 if (!tr->attr.secure && !tz) {
602 AF_DP32(s->regs, ISR, APER_TZ, true);
603 continue;
604 }
605
606 break;
607 }
608
609 if (!mid_match) {
610
611 AF_DP32(s->regs, ISR, MID_MISS, true);
612 }
613
614 return i < NR_MID_ENTRIES;
615}
616
617static void xppu_ap_access(MemoryTransaction *tr)
618{
619 XPPUAperture *ap = tr->opaque;
620 XPPU *s = ap->parent;
621 hwaddr addr = tr->addr;
622 uint32_t ram_offset;
623 uint32_t apl;
624 bool valid;
625 bool isr_free;
626 bool xppu_enabled = AF_EX32(s->regs, CTRL, ENABLE);
627
628 assert(xppu_enabled);
629
630 addr += ap->base;
631
632
633 isr_free = (s->regs[R_ISR] & 0xf6) == 0;
634
635 ram_offset = addr & ap->extract_mask;
636 ram_offset >>= ap->extract_shift;
637
638 ram_offset += ap->ram_base;
639 apl = s->perm_ram[ram_offset];
640 valid = xppu_ap_check(s, tr, apl);
641
642 if (!valid) {
643 if (isr_free) {
644 AF_DP32(s->regs, ISR, APER_PERM, true);
645 AF_DP32(s->regs, ERR_STATUS1, AXI_ADDR, addr >> 12);
646 AF_DP32(s->regs, ERR_STATUS2, AXI_ID, tr->attr.master_id);
647 }
648
649
650
651
652
653
654
655 addr &= (1 << 12) - 1;
656 addr |= AF_EX32(s->regs, POISON, BASE) << 12;
657 isr_update_irq(s);
658 }
659
660
661 tr->data.u64 = cpu_to_le64(tr->data.u64);
662 address_space_rw(s->as, addr, tr->attr, (uint8_t *) &tr->data.u64,
663 tr->size, tr->rw);
664 tr->data.u64 = le64_to_cpu(tr->data.u64);
665}
666
667static const MemoryRegionOps xppu_ap_ops = {
668 .access = xppu_ap_access,
669 .endianness = DEVICE_LITTLE_ENDIAN,
670 .valid = {
671 .min_access_size = 4,
672 .max_access_size = 4,
673 },
674};
675
676static uint64_t xppu_read(void *opaque, hwaddr addr, unsigned size,
677 MemTxAttrs attr)
678{
679 XPPU *s = XILINX_XPPU(opaque);
680 RegisterInfo *r = &s->regs_info[addr / 4];
681
682 if (!attr.secure) {
683
684 return 0;
685 }
686
687 if (addr >= 0x1000 && addr < 0x1644) {
688 unsigned int i = (addr - 0x1000) / 4;
689 assert(i < ARRAY_SIZE(s->perm_ram));
690 return s->perm_ram[i];
691 }
692
693 if (!r->data) {
694 qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
695 object_get_canonical_path(OBJECT(s)),
696 addr);
697 AF_DP32(s->regs, ISR, INV_APB, true);
698 isr_update_irq(s);
699 return 0;
700 }
701 return register_read(r);
702}
703
704static void xppu_write(void *opaque, hwaddr addr, uint64_t value,
705 unsigned size, MemTxAttrs attr)
706{
707 XPPU *s = XILINX_XPPU(opaque);
708 RegisterInfo *r = &s->regs_info[addr / 4];
709
710 if (!attr.secure) {
711 return;
712 }
713
714 if (addr >= 0x1000 && addr < 0x1644) {
715 unsigned int i = (addr - 0x1000) / 4;
716 assert(i < ARRAY_SIZE(s->perm_ram));
717 s->perm_ram[i] = value;
718 return;
719 }
720
721 if (!r->data) {
722 qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
723 object_get_canonical_path(OBJECT(s)),
724 addr, value);
725 AF_DP32(s->regs, ISR, INV_APB, true);
726 isr_update_irq(s);
727 return;
728 }
729 register_write(r, value, ~0);
730}
731
732static void xppu_access(MemoryTransaction *tr)
733{
734 MemTxAttrs attr = tr->attr;
735 void *opaque = tr->opaque;
736 hwaddr addr = tr->addr;
737 unsigned size = tr->size;
738 uint64_t value = tr->data.u64;;
739 bool is_write = tr->rw;
740
741 if (is_write) {
742 xppu_write(opaque, addr, value, size, attr);
743 } else {
744 tr->data.u64 = xppu_read(opaque, addr, size, attr);
745 }
746}
747
748static const MemoryRegionOps xppu_ops = {
749 .access = xppu_access,
750 .endianness = DEVICE_LITTLE_ENDIAN,
751 .valid = {
752 .min_access_size = 4,
753 .max_access_size = 4,
754 },
755};
756
757static void xppu_realize(DeviceState *dev, Error **errp)
758{
759 XPPU *s = XILINX_XPPU(dev);
760 const char *prefix = object_get_canonical_path(OBJECT(dev));
761 unsigned int i;
762
763 for (i = 0; i < ARRAY_SIZE(xppu_regs_info); ++i) {
764 RegisterInfo *r = &s->regs_info[xppu_regs_info[i].decode.addr/4];
765
766 *r = (RegisterInfo) {
767 .data = (uint8_t *)&s->regs[
768 xppu_regs_info[i].decode.addr/4],
769 .data_size = sizeof(uint32_t),
770 .access = &xppu_regs_info[i],
771 .debug = XILINX_XPPU_ERR_DEBUG,
772 .prefix = prefix,
773 .opaque = s,
774 };
775 }
776
777 s->as = s->mr ? address_space_init_shareable(s->mr, NULL)
778 : &address_space_memory;
779}
780
781static void xppu_init(Object *obj)
782{
783 XPPU *s = XILINX_XPPU(obj);
784 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
785
786 sysbus_init_irq(sbd, &s->irq_isr);
787
788 object_property_add_link(obj, "mr", TYPE_MEMORY_REGION,
789 (Object **)&s->mr,
790 qdev_prop_allow_set_link_before_realize,
791 OBJ_PROP_LINK_UNREF_ON_RELEASE,
792 &error_abort);
793}
794
795static bool xppu_parse_reg(FDTGenericMMap *obj, FDTGenericRegPropInfo reg,
796 Error **errp)
797{
798 XPPU *s = XILINX_XPPU(obj);
799 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
800 ObjectClass *klass = object_class_by_name(TYPE_XILINX_XPPU);
801 FDTGenericMMapClass *parent_fmc;
802 unsigned int i;
803
804 parent_fmc = FDT_GENERIC_MMAP_CLASS(object_class_get_parent(klass));
805 memory_region_init_io(&s->iomem, OBJECT(obj), &xppu_ops, s,
806 TYPE_XILINX_XPPU, 0x10000);
807 sysbus_init_mmio(sbd, &s->iomem);
808
809 for (i = 0; i < (reg.n - 1) && i < ARRAY_SIZE(s->ap); i++) {
810 static const XPPUGranule granules[] = {
811 GRANULE_32B,
812 GRANULE_64K,
813 GRANULE_1M,
814 GRANULE_512M
815 };
816 static const uint64_t bases[] = {
817 0xff990000,
818 0xff000000,
819 0xfe000000,
820 0xc0000000,
821 };
822 static const uint64_t masks[] = {
823 0x7f << 5,
824 0xff << 16,
825 0x0f << 20,
826 0,
827 };
828 static const unsigned int shifts[] = {
829 5,
830 16,
831 20,
832 0,
833 };
834 static const uint32_t ram_bases[] = {
835 0x100,
836 0x0,
837 0x180,
838 0x190,
839 };
840 char *name;
841
842 s->ap[i].parent = s;
843 s->ap[i].granule = granules[i];
844 s->ap[i].base = bases[i];
845 s->ap[i].extract_mask = masks[i];
846 s->ap[i].extract_shift = shifts[i];
847 s->ap[i].ram_base = ram_bases[i];
848
849 name = g_strdup_printf("xppu-mr-%d\n", i);
850 memory_region_init_io(&s->ap[i].iomem, OBJECT(obj),
851 &xppu_ap_ops, &s->ap[i],
852 name, reg.s[i + 1]);
853 sysbus_init_mmio(sbd, &s->ap[i].iomem);
854 g_free(name);
855 }
856 return parent_fmc ? parent_fmc->parse_reg(obj, reg, errp) : false;
857}
858
859static const VMStateDescription vmstate_xppu = {
860 .name = TYPE_XILINX_XPPU,
861 .version_id = 1,
862 .minimum_version_id = 1,
863 .minimum_version_id_old = 1,
864 .fields = (VMStateField[]) {
865 VMSTATE_UINT32_ARRAY(regs, XPPU, R_MAX),
866 VMSTATE_END_OF_LIST(),
867 }
868};
869
870static void xppu_class_init(ObjectClass *klass, void *data)
871{
872 DeviceClass *dc = DEVICE_CLASS(klass);
873 FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_CLASS(klass);
874
875 dc->reset = xppu_reset;
876 dc->realize = xppu_realize;
877 dc->vmsd = &vmstate_xppu;
878 fmc->parse_reg = xppu_parse_reg;
879}
880
881static const TypeInfo xppu_info = {
882 .name = TYPE_XILINX_XPPU,
883 .parent = TYPE_SYS_BUS_DEVICE,
884 .instance_size = sizeof(XPPU),
885 .class_init = xppu_class_init,
886 .instance_init = xppu_init,
887 .interfaces = (InterfaceInfo[]) {
888 { TYPE_FDT_GENERIC_MMAP },
889 { },
890 },
891
892};
893
894static void xppu_register_types(void)
895{
896 type_register_static(&xppu_info);
897}
898
899type_init(xppu_register_types)
900