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