Revision 225d4be7 hw/iommu.c
b/hw/iommu.c | ||
---|---|---|
59 | 59 |
#define IOMMU_PGFLUSH (0x0018 >> 2) |
60 | 60 |
#define IOMMU_PGFLUSH_MASK 0xffffffff |
61 | 61 |
|
62 |
#define IOMMU_AFSR (0x1000 >> 2) |
|
63 |
#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */ |
|
64 |
#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */ |
|
65 |
#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */ |
|
66 |
#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */ |
|
67 |
#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */ |
|
68 |
#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */ |
|
69 |
#define IOMMU_AFSR_RESV 0x00f00000 /* Reserved, forced to 0x8 by hardware */ |
|
70 |
#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */ |
|
71 |
#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */ |
|
72 |
#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */ |
|
73 |
|
|
74 |
#define IOMMU_AFAR (0x1004 >> 2) |
|
75 |
|
|
62 | 76 |
#define IOMMU_SBCFG0 (0x1010 >> 2) /* SBUS configration per-slot */ |
63 | 77 |
#define IOMMU_SBCFG1 (0x1014 >> 2) /* SBUS configration per-slot */ |
64 | 78 |
#define IOMMU_SBCFG2 (0x1018 >> 2) /* SBUS configration per-slot */ |
... | ... | |
218 | 232 |
return pa; |
219 | 233 |
} |
220 | 234 |
|
235 |
static void iommu_bad_addr(IOMMUState *s, target_phys_addr_t addr, int is_write) |
|
236 |
{ |
|
237 |
DPRINTF("bad addr " TARGET_FMT_plx "\n", addr); |
|
238 |
s->regs[IOMMU_AFSR] = IOMMU_AFSR_ERR | IOMMU_AFSR_LE | (8 << 20) | |
|
239 |
IOMMU_AFSR_FAV; |
|
240 |
if (!is_write) |
|
241 |
s->regs[IOMMU_AFSR] |= IOMMU_AFSR_RD; |
|
242 |
s->regs[IOMMU_AFAR] = addr; |
|
243 |
} |
|
244 |
|
|
221 | 245 |
void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr, |
222 | 246 |
uint8_t *buf, int len, int is_write) |
223 | 247 |
{ |
... | ... | |
231 | 255 |
if (l > len) |
232 | 256 |
l = len; |
233 | 257 |
flags = iommu_page_get_flags(opaque, page); |
234 |
if (!(flags & IOPTE_VALID)) |
|
258 |
if (!(flags & IOPTE_VALID)) { |
|
259 |
iommu_bad_addr(opaque, page, is_write); |
|
235 | 260 |
return; |
261 |
} |
|
236 | 262 |
phys_addr = iommu_translate_pa(opaque, addr, flags); |
237 | 263 |
if (is_write) { |
238 |
if (!(flags & IOPTE_WRITE)) |
|
264 |
if (!(flags & IOPTE_WRITE)) { |
|
265 |
iommu_bad_addr(opaque, page, is_write); |
|
239 | 266 |
return; |
267 |
} |
|
240 | 268 |
cpu_physical_memory_write(phys_addr, buf, len); |
241 | 269 |
} else { |
242 | 270 |
cpu_physical_memory_read(phys_addr, buf, len); |
Also available in: Unified diff