ia64/xen-unstable

view tools/ioemu/hw/iommu.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 8e5fc5fe636c
children 0cae0c6436f5
line source
1 /*
2 * QEMU SPARC iommu emulation
3 *
4 * Copyright (c) 2003 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"
26 /* debug iommu */
27 //#define DEBUG_IOMMU
29 /* The IOMMU registers occupy three pages in IO space. */
30 struct iommu_regs {
31 /* First page */
32 volatile unsigned long control; /* IOMMU control */
33 volatile unsigned long base; /* Physical base of iopte page table */
34 volatile unsigned long _unused1[3];
35 volatile unsigned long tlbflush; /* write only */
36 volatile unsigned long pageflush; /* write only */
37 volatile unsigned long _unused2[1017];
38 /* Second page */
39 volatile unsigned long afsr; /* Async-fault status register */
40 volatile unsigned long afar; /* Async-fault physical address */
41 volatile unsigned long _unused3[2];
42 volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */
43 volatile unsigned long sbuscfg1;
44 volatile unsigned long sbuscfg2;
45 volatile unsigned long sbuscfg3;
46 volatile unsigned long mfsr; /* Memory-fault status register */
47 volatile unsigned long mfar; /* Memory-fault physical address */
48 volatile unsigned long _unused4[1014];
49 /* Third page */
50 volatile unsigned long mid; /* IOMMU module-id */
51 };
53 #define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
54 #define IOMMU_CTRL_VERS 0x0f000000 /* Version */
55 #define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
56 #define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
57 #define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
58 #define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
59 #define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
60 #define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
61 #define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
62 #define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
63 #define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
64 #define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
66 #define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
67 #define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */
68 #define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */
69 #define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */
70 #define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
71 #define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
72 #define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */
73 #define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
74 #define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */
75 #define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
77 #define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
78 #define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
79 #define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
80 #define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
81 produced by this device as pure
82 physical. */
84 #define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */
85 #define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */
86 #define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */
87 #define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */
88 #define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred
89 on the even word of the access, low bit
90 indicated odd word caused the parity error */
91 #define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */
92 #define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */
93 #define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */
95 #define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */
96 #define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */
97 #define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */
98 #define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */
99 #define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */
100 #define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */
101 #define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */
103 /* The format of an iopte in the page tables */
104 #define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
105 #define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
106 #define IOPTE_WRITE 0x00000004 /* Writeable */
107 #define IOPTE_VALID 0x00000002 /* IOPTE is valid */
108 #define IOPTE_WAZ 0x00000001 /* Write as zeros */
110 #define PAGE_SHIFT 12
111 #define PAGE_SIZE (1 << PAGE_SHIFT)
112 #define PAGE_MASK (PAGE_SIZE - 1)
114 typedef struct IOMMUState {
115 uint32_t addr;
116 uint32_t regs[sizeof(struct iommu_regs)];
117 uint32_t iostart;
118 } IOMMUState;
120 static IOMMUState *ps;
122 static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
123 {
124 IOMMUState *s = opaque;
125 uint32_t saddr;
127 saddr = (addr - s->addr) >> 2;
128 switch (saddr) {
129 default:
130 return s->regs[saddr];
131 break;
132 }
133 return 0;
134 }
136 static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
137 {
138 IOMMUState *s = opaque;
139 uint32_t saddr;
141 saddr = (addr - s->addr) >> 2;
142 switch (saddr) {
143 case 0:
144 switch (val & IOMMU_CTRL_RNGE) {
145 case IOMMU_RNGE_16MB:
146 s->iostart = 0xff000000;
147 break;
148 case IOMMU_RNGE_32MB:
149 s->iostart = 0xfe000000;
150 break;
151 case IOMMU_RNGE_64MB:
152 s->iostart = 0xfc000000;
153 break;
154 case IOMMU_RNGE_128MB:
155 s->iostart = 0xf8000000;
156 break;
157 case IOMMU_RNGE_256MB:
158 s->iostart = 0xf0000000;
159 break;
160 case IOMMU_RNGE_512MB:
161 s->iostart = 0xe0000000;
162 break;
163 case IOMMU_RNGE_1GB:
164 s->iostart = 0xc0000000;
165 break;
166 default:
167 case IOMMU_RNGE_2GB:
168 s->iostart = 0x80000000;
169 break;
170 }
171 /* Fall through */
172 default:
173 s->regs[saddr] = val;
174 break;
175 }
176 }
178 static CPUReadMemoryFunc *iommu_mem_read[3] = {
179 iommu_mem_readw,
180 iommu_mem_readw,
181 iommu_mem_readw,
182 };
184 static CPUWriteMemoryFunc *iommu_mem_write[3] = {
185 iommu_mem_writew,
186 iommu_mem_writew,
187 iommu_mem_writew,
188 };
190 uint32_t iommu_translate(uint32_t addr)
191 {
192 uint32_t *iopte = (void *)(ps->regs[1] << 4), pa;
194 iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
195 cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
196 bswap32s(&pa);
197 pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
198 return pa + (addr & PAGE_MASK);
199 }
201 void iommu_init(uint32_t addr)
202 {
203 IOMMUState *s;
204 int iommu_io_memory;
206 s = qemu_mallocz(sizeof(IOMMUState));
207 if (!s)
208 return;
210 s->addr = addr;
212 iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
213 cpu_register_physical_memory(addr, sizeof(struct iommu_regs),
214 iommu_io_memory);
216 ps = s;
217 }