~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/iommu.c

Tags: upstream-0.9.0+20070816
ImportĀ upstreamĀ versionĀ 0.9.0+20070816

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 */
87
101
#define PAGE_MASK       (PAGE_SIZE - 1)
88
102
 
89
103
typedef struct IOMMUState {
90
 
    uint32_t addr;
 
104
    target_phys_addr_t addr;
91
105
    uint32_t regs[IOMMU_NREGS];
92
 
    uint32_t iostart;
 
106
    target_phys_addr_t iostart;
93
107
} IOMMUState;
94
108
 
95
109
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
96
110
{
97
111
    IOMMUState *s = opaque;
98
 
    uint32_t saddr;
 
112
    target_phys_addr_t saddr;
99
113
 
100
114
    saddr = (addr - s->addr) >> 2;
101
115
    switch (saddr) {
102
116
    default:
103
 
        DPRINTF("read reg[%d] = %x\n", saddr, s->regs[saddr]);
 
117
        DPRINTF("read reg[%d] = %x\n", (int)saddr, s->regs[saddr]);
104
118
        return s->regs[saddr];
105
119
        break;
106
120
    }
110
124
static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
111
125
{
112
126
    IOMMUState *s = opaque;
113
 
    uint32_t saddr;
 
127
    target_phys_addr_t saddr;
114
128
 
115
129
    saddr = (addr - s->addr) >> 2;
116
 
    DPRINTF("write reg[%d] = %x\n", saddr, val);
 
130
    DPRINTF("write reg[%d] = %x\n", (int)saddr, val);
117
131
    switch (saddr) {
118
132
    case IOMMU_CTRL:
119
133
        switch (val & IOMMU_CTRL_RNGE) {
120
134
        case IOMMU_RNGE_16MB:
121
 
            s->iostart = 0xff000000;
 
135
            s->iostart = 0xffffffffff000000ULL;
122
136
            break;
123
137
        case IOMMU_RNGE_32MB:
124
 
            s->iostart = 0xfe000000;
 
138
            s->iostart = 0xfffffffffe000000ULL;
125
139
            break;
126
140
        case IOMMU_RNGE_64MB:
127
 
            s->iostart = 0xfc000000;
 
141
            s->iostart = 0xfffffffffc000000ULL;
128
142
            break;
129
143
        case IOMMU_RNGE_128MB:
130
 
            s->iostart = 0xf8000000;
 
144
            s->iostart = 0xfffffffff8000000ULL;
131
145
            break;
132
146
        case IOMMU_RNGE_256MB:
133
 
            s->iostart = 0xf0000000;
 
147
            s->iostart = 0xfffffffff0000000ULL;
134
148
            break;
135
149
        case IOMMU_RNGE_512MB:
136
 
            s->iostart = 0xe0000000;
 
150
            s->iostart = 0xffffffffe0000000ULL;
137
151
            break;
138
152
        case IOMMU_RNGE_1GB:
139
 
            s->iostart = 0xc0000000;
 
153
            s->iostart = 0xffffffffc0000000ULL;
140
154
            break;
141
155
        default:
142
156
        case IOMMU_RNGE_2GB:
143
 
            s->iostart = 0x80000000;
 
157
            s->iostart = 0xffffffff80000000ULL;
144
158
            break;
145
159
        }
146
 
        DPRINTF("iostart = %x\n", s->iostart);
 
160
        DPRINTF("iostart = " TARGET_FMT_plx "\n", s->iostart);
147
161
        s->regs[saddr] = ((val & IOMMU_CTRL_MASK) | IOMMU_VERSION);
148
162
        break;
149
163
    case IOMMU_BASE:
186
200
    iommu_mem_writew,
187
201
};
188
202
 
189
 
static uint32_t iommu_page_get_flags(IOMMUState *s, uint32_t addr)
 
203
static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr)
190
204
{
191
 
    uint32_t iopte;
 
205
    uint32_t iopte, ret;
 
206
#ifdef DEBUG_IOMMU
 
207
    target_phys_addr_t pa = addr;
 
208
#endif
192
209
 
193
 
    iopte = s->regs[1] << 4;
 
210
    iopte = s->regs[IOMMU_BASE] << 4;
194
211
    addr &= ~s->iostart;
195
212
    iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
196
 
    return ldl_phys(iopte);
 
213
    ret = ldl_phys(iopte);
 
214
    DPRINTF("get flags addr " TARGET_FMT_plx " => pte %x, *ptes = %x\n", pa,
 
215
            iopte, ret);
 
216
 
 
217
    return ret;
197
218
}
198
219
 
199
 
static uint32_t iommu_translate_pa(IOMMUState *s, uint32_t addr, uint32_t pa)
 
220
static target_phys_addr_t iommu_translate_pa(IOMMUState *s,
 
221
                                             target_phys_addr_t addr,
 
222
                                             uint32_t pte)
200
223
{
201
224
    uint32_t tmppte;
202
 
 
203
 
    tmppte = pa;
204
 
    pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
205
 
    DPRINTF("xlate dva %x => pa %x (iopte = %x)\n", addr, pa, tmppte);
 
225
    target_phys_addr_t pa;
 
226
 
 
227
    tmppte = pte;
 
228
    pa = ((pte & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
 
229
    DPRINTF("xlate dva " TARGET_FMT_plx " => pa " TARGET_FMT_plx
 
230
            " (iopte = %x)\n", addr, pa, tmppte);
 
231
 
206
232
    return pa;
207
233
}
208
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
 
209
245
void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr,
210
246
                           uint8_t *buf, int len, int is_write)
211
247
{
212
 
    int l, flags;
213
 
    target_ulong page, phys_addr;
 
248
    int l;
 
249
    uint32_t flags;
 
250
    target_phys_addr_t page, phys_addr;
214
251
 
215
252
    while (len > 0) {
216
253
        page = addr & TARGET_PAGE_MASK;
218
255
        if (l > len)
219
256
            l = len;
220
257
        flags = iommu_page_get_flags(opaque, page);
221
 
        if (!(flags & IOPTE_VALID))
 
258
        if (!(flags & IOPTE_VALID)) {
 
259
            iommu_bad_addr(opaque, page, is_write);
222
260
            return;
 
261
        }
223
262
        phys_addr = iommu_translate_pa(opaque, addr, flags);
224
263
        if (is_write) {
225
 
            if (!(flags & IOPTE_WRITE))
 
264
            if (!(flags & IOPTE_WRITE)) {
 
265
                iommu_bad_addr(opaque, page, is_write);
226
266
                return;
 
267
            }
227
268
            cpu_physical_memory_write(phys_addr, buf, len);
228
269
        } else {
229
270
            cpu_physical_memory_read(phys_addr, buf, len);
239
280
    IOMMUState *s = opaque;
240
281
    int i;
241
282
    
242
 
    qemu_put_be32s(f, &s->addr);
243
283
    for (i = 0; i < IOMMU_NREGS; i++)
244
284
        qemu_put_be32s(f, &s->regs[i]);
245
 
    qemu_put_be32s(f, &s->iostart);
 
285
    qemu_put_be64s(f, &s->iostart);
246
286
}
247
287
 
248
288
static int iommu_load(QEMUFile *f, void *opaque, int version_id)
250
290
    IOMMUState *s = opaque;
251
291
    int i;
252
292
    
253
 
    if (version_id != 1)
 
293
    if (version_id != 2)
254
294
        return -EINVAL;
255
295
 
256
 
    qemu_get_be32s(f, &s->addr);
257
296
    for (i = 0; i < IOMMU_NREGS; i++)
258
 
        qemu_put_be32s(f, &s->regs[i]);
259
 
    qemu_get_be32s(f, &s->iostart);
 
297
        qemu_get_be32s(f, &s->regs[i]);
 
298
    qemu_get_be64s(f, &s->iostart);
260
299
 
261
300
    return 0;
262
301
}
267
306
 
268
307
    memset(s->regs, 0, IOMMU_NREGS * 4);
269
308
    s->iostart = 0;
270
 
    s->regs[0] = IOMMU_VERSION;
 
309
    s->regs[IOMMU_CTRL] = IOMMU_VERSION;
271
310
}
272
311
 
273
 
void *iommu_init(uint32_t addr)
 
312
void *iommu_init(target_phys_addr_t addr)
274
313
{
275
314
    IOMMUState *s;
276
315
    int iommu_io_memory;
284
323
    iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
285
324
    cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory);
286
325
    
287
 
    register_savevm("iommu", addr, 1, iommu_save, iommu_load, s);
 
326
    register_savevm("iommu", addr, 2, iommu_save, iommu_load, s);
288
327
    qemu_register_reset(iommu_reset, s);
289
328
    return s;
290
329
}