Statistics
| Branch: | Revision:

root / hw / iommu.c @ 40545f84

History | View | Annotate | Download (5.7 kB)

1
/*
2
 * QEMU SPARC iommu emulation
3
 *
4
 * Copyright (c) 2003-2005 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25

    
26
/* debug iommu */
27
//#define DEBUG_IOMMU
28

    
29
#ifdef DEBUG_IOMMU
30
#define DPRINTF(fmt, args...) \
31
do { printf("IOMMU: " fmt , ##args); } while (0)
32
#else
33
#define DPRINTF(fmt, args...)
34
#endif
35

    
36
#define IOMMU_NREGS (3*4096)
37
#define IOMMU_CTRL_IMPL     0xf0000000 /* Implementation */
38
#define IOMMU_CTRL_VERS     0x0f000000 /* Version */
39
#define IOMMU_CTRL_RNGE     0x0000001c /* Mapping RANGE */
40
#define IOMMU_RNGE_16MB     0x00000000 /* 0xff000000 -> 0xffffffff */
41
#define IOMMU_RNGE_32MB     0x00000004 /* 0xfe000000 -> 0xffffffff */
42
#define IOMMU_RNGE_64MB     0x00000008 /* 0xfc000000 -> 0xffffffff */
43
#define IOMMU_RNGE_128MB    0x0000000c /* 0xf8000000 -> 0xffffffff */
44
#define IOMMU_RNGE_256MB    0x00000010 /* 0xf0000000 -> 0xffffffff */
45
#define IOMMU_RNGE_512MB    0x00000014 /* 0xe0000000 -> 0xffffffff */
46
#define IOMMU_RNGE_1GB      0x00000018 /* 0xc0000000 -> 0xffffffff */
47
#define IOMMU_RNGE_2GB      0x0000001c /* 0x80000000 -> 0xffffffff */
48
#define IOMMU_CTRL_ENAB     0x00000001 /* IOMMU Enable */
49

    
50
/* The format of an iopte in the page tables */
51
#define IOPTE_PAGE          0x07ffff00 /* Physical page number (PA[30:12]) */
52
#define IOPTE_CACHE         0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
53
#define IOPTE_WRITE         0x00000004 /* Writeable */
54
#define IOPTE_VALID         0x00000002 /* IOPTE is valid */
55
#define IOPTE_WAZ           0x00000001 /* Write as zeros */
56

    
57
#define PAGE_SHIFT      12
58
#define PAGE_SIZE       (1 << PAGE_SHIFT)
59
#define PAGE_MASK        (PAGE_SIZE - 1)
60

    
61
typedef struct IOMMUState {
62
    uint32_t addr;
63
    uint32_t regs[IOMMU_NREGS];
64
    uint32_t iostart;
65
} IOMMUState;
66

    
67
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
68
{
69
    IOMMUState *s = opaque;
70
    uint32_t saddr;
71

    
72
    saddr = (addr - s->addr) >> 2;
73
    switch (saddr) {
74
    default:
75
        DPRINTF("read reg[%d] = %x\n", saddr, s->regs[saddr]);
76
        return s->regs[saddr];
77
        break;
78
    }
79
    return 0;
80
}
81

    
82
static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
83
{
84
    IOMMUState *s = opaque;
85
    uint32_t saddr;
86

    
87
    saddr = (addr - s->addr) >> 2;
88
    DPRINTF("write reg[%d] = %x\n", saddr, val);
89
    switch (saddr) {
90
    case 0:
91
        switch (val & IOMMU_CTRL_RNGE) {
92
        case IOMMU_RNGE_16MB:
93
            s->iostart = 0xff000000;
94
            break;
95
        case IOMMU_RNGE_32MB:
96
            s->iostart = 0xfe000000;
97
            break;
98
        case IOMMU_RNGE_64MB:
99
            s->iostart = 0xfc000000;
100
            break;
101
        case IOMMU_RNGE_128MB:
102
            s->iostart = 0xf8000000;
103
            break;
104
        case IOMMU_RNGE_256MB:
105
            s->iostart = 0xf0000000;
106
            break;
107
        case IOMMU_RNGE_512MB:
108
            s->iostart = 0xe0000000;
109
            break;
110
        case IOMMU_RNGE_1GB:
111
            s->iostart = 0xc0000000;
112
            break;
113
        default:
114
        case IOMMU_RNGE_2GB:
115
            s->iostart = 0x80000000;
116
            break;
117
        }
118
        DPRINTF("iostart = %x\n", s->iostart);
119
        /* Fall through */
120
    default:
121
        s->regs[saddr] = val;
122
        break;
123
    }
124
}
125

    
126
static CPUReadMemoryFunc *iommu_mem_read[3] = {
127
    iommu_mem_readw,
128
    iommu_mem_readw,
129
    iommu_mem_readw,
130
};
131

    
132
static CPUWriteMemoryFunc *iommu_mem_write[3] = {
133
    iommu_mem_writew,
134
    iommu_mem_writew,
135
    iommu_mem_writew,
136
};
137

    
138
uint32_t iommu_translate_local(void *opaque, uint32_t addr)
139
{
140
    IOMMUState *s = opaque;
141
    uint32_t iopte, pa, tmppte;
142

    
143
    iopte = s->regs[1] << 4;
144
    addr &= ~s->iostart;
145
    iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
146
    cpu_physical_memory_read(iopte, (void *) &pa, 4);
147
    bswap32s(&pa);
148
    tmppte = pa;
149
    pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
150
    DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, tmppte);
151
    return pa;
152
}
153

    
154
static void iommu_save(QEMUFile *f, void *opaque)
155
{
156
    IOMMUState *s = opaque;
157
    int i;
158
    
159
    qemu_put_be32s(f, &s->addr);
160
    for (i = 0; i < IOMMU_NREGS; i++)
161
        qemu_put_be32s(f, &s->regs[i]);
162
    qemu_put_be32s(f, &s->iostart);
163
}
164

    
165
static int iommu_load(QEMUFile *f, void *opaque, int version_id)
166
{
167
    IOMMUState *s = opaque;
168
    int i;
169
    
170
    if (version_id != 1)
171
        return -EINVAL;
172

    
173
    qemu_get_be32s(f, &s->addr);
174
    for (i = 0; i < IOMMU_NREGS; i++)
175
        qemu_put_be32s(f, &s->regs[i]);
176
    qemu_get_be32s(f, &s->iostart);
177

    
178
    return 0;
179
}
180

    
181
static void iommu_reset(void *opaque)
182
{
183
    IOMMUState *s = opaque;
184

    
185
    memset(s->regs, 0, IOMMU_NREGS * 4);
186
    s->iostart = 0;
187
}
188

    
189
void *iommu_init(uint32_t addr)
190
{
191
    IOMMUState *s;
192
    int iommu_io_memory;
193

    
194
    s = qemu_mallocz(sizeof(IOMMUState));
195
    if (!s)
196
        return NULL;
197

    
198
    s->addr = addr;
199

    
200
    iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
201
    cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory);
202
    
203
    register_savevm("iommu", addr, 1, iommu_save, iommu_load, s);
204
    qemu_register_reset(iommu_reset, s);
205
    return s;
206
}
207