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); | ... | ... |