Commit 225d4be7099f0cfdf5c85b4e4be1fa1e5169543c
1 parent
981a2e99
Log invalid accesses (no faults generated yet)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3115 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
30 additions
and
2 deletions
hw/iommu.c
... | ... | @@ -59,6 +59,20 @@ do { printf("IOMMU: " fmt , ##args); } while (0) |
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,6 +232,16 @@ static target_phys_addr_t iommu_translate_pa(IOMMUState *s, |
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,12 +255,16 @@ void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr, |
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); | ... | ... |