Minor format tweaks on config file documentation.
[gem5.git] / arch / alpha / vtophys.cc
1 /*
2 * Copyright (c) 2002-2004 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <string>
30
31 #include "arch/alpha/vtophys.hh"
32 #include "base/trace.hh"
33 #include "cpu/exec_context.hh"
34 #include "mem/functional_mem/physical_memory.hh"
35
36 using namespace std;
37
38 AlphaISA::PageTableEntry
39 kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr)
40 {
41 Addr level1_pte = ptbr + vaddr.level1();
42 AlphaISA::PageTableEntry level1 = pmem->phys_read_qword(level1_pte);
43 if (!level1.valid()) {
44 DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
45 return 0;
46 }
47
48 Addr level2_pte = level1.paddr() + vaddr.level2();
49 AlphaISA::PageTableEntry level2 = pmem->phys_read_qword(level2_pte);
50 if (!level2.valid()) {
51 DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
52 return 0;
53 }
54
55 Addr level3_pte = level2.paddr() + vaddr.level3();
56 AlphaISA::PageTableEntry level3 = pmem->phys_read_qword(level3_pte);
57 if (!level3.valid()) {
58 DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
59 return 0;
60 }
61 return level3;
62 }
63
64 Addr
65 vtophys(PhysicalMemory *xc, Addr vaddr)
66 {
67 Addr paddr = 0;
68 if (AlphaISA::IsUSeg(vaddr))
69 DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
70 else if (AlphaISA::IsK0Seg(vaddr))
71 paddr = AlphaISA::K0Seg2Phys(vaddr);
72 else
73 panic("vtophys: ptbr is not set on virtual lookup");
74
75 DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
76
77 return paddr;
78 }
79
80 Addr
81 vtophys(ExecContext *xc, Addr addr)
82 {
83 AlphaISA::VAddr vaddr = addr;
84 Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20];
85 Addr paddr = 0;
86 //@todo Andrew couldn't remember why he commented some of this code
87 //so I put it back in. Perhaps something to do with gdb debugging?
88 if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) {
89 paddr = vaddr & ~ULL(1);
90 } else {
91 if (AlphaISA::IsK0Seg(vaddr)) {
92 paddr = AlphaISA::K0Seg2Phys(vaddr);
93 } else if (!ptbr) {
94 paddr = vaddr;
95 } else {
96 AlphaISA::PageTableEntry pte =
97 kernel_pte_lookup(xc->physmem, ptbr, vaddr);
98 if (pte.valid())
99 paddr = pte.paddr() | vaddr.offset();
100 }
101 }
102
103
104 DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
105
106 return paddr;
107 }
108
109 uint8_t *
110 ptomem(ExecContext *xc, Addr paddr, size_t len)
111 {
112 return xc->physmem->dma_addr(paddr, len);
113 }
114
115 uint8_t *
116 vtomem(ExecContext *xc, Addr vaddr, size_t len)
117 {
118 Addr paddr = vtophys(xc, vaddr);
119 return xc->physmem->dma_addr(paddr, len);
120 }
121
122 void
123 CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
124 {
125 Addr paddr;
126 char *dmaaddr;
127 char *dst = (char *)dest;
128 int len;
129
130 paddr = vtophys(xc, src);
131 len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
132 (int)cplen);
133 dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
134 assert(dmaaddr);
135
136 memcpy(dst, dmaaddr, len);
137 if (len == cplen)
138 return;
139
140 cplen -= len;
141 dst += len;
142 src += len;
143
144 while (cplen > AlphaISA::PageBytes) {
145 paddr = vtophys(xc, src);
146 dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
147 assert(dmaaddr);
148
149 memcpy(dst, dmaaddr, AlphaISA::PageBytes);
150 cplen -= AlphaISA::PageBytes;
151 dst += AlphaISA::PageBytes;
152 src += AlphaISA::PageBytes;
153 }
154
155 if (cplen > 0) {
156 paddr = vtophys(xc, src);
157 dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
158 assert(dmaaddr);
159
160 memcpy(dst, dmaaddr, cplen);
161 }
162 }
163
164 void
165 CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
166 {
167 Addr paddr;
168 char *dmaaddr;
169 char *src = (char *)source;
170 int len;
171
172 paddr = vtophys(xc, dest);
173 len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
174 (int)cplen);
175 dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
176 assert(dmaaddr);
177
178 memcpy(dmaaddr, src, len);
179 if (len == cplen)
180 return;
181
182 cplen -= len;
183 src += len;
184 dest += len;
185
186 while (cplen > AlphaISA::PageBytes) {
187 paddr = vtophys(xc, dest);
188 dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
189 assert(dmaaddr);
190
191 memcpy(dmaaddr, src, AlphaISA::PageBytes);
192 cplen -= AlphaISA::PageBytes;
193 src += AlphaISA::PageBytes;
194 dest += AlphaISA::PageBytes;
195 }
196
197 if (cplen > 0) {
198 paddr = vtophys(xc, dest);
199 dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
200 assert(dmaaddr);
201
202 memcpy(dmaaddr, src, cplen);
203 }
204 }
205
206 void
207 CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
208 {
209 Addr paddr;
210 char *dmaaddr;
211 int len;
212
213 paddr = vtophys(xc, vaddr);
214 len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
215 (int)maxlen);
216 dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
217 assert(dmaaddr);
218
219 char *term = (char *)memchr(dmaaddr, 0, len);
220 if (term)
221 len = term - dmaaddr + 1;
222
223 memcpy(dst, dmaaddr, len);
224
225 if (term || len == maxlen)
226 return;
227
228 maxlen -= len;
229 dst += len;
230 vaddr += len;
231
232 while (maxlen > AlphaISA::PageBytes) {
233 paddr = vtophys(xc, vaddr);
234 dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
235 assert(dmaaddr);
236
237 char *term = (char *)memchr(dmaaddr, 0, AlphaISA::PageBytes);
238 len = term ? (term - dmaaddr + 1) : AlphaISA::PageBytes;
239
240 memcpy(dst, dmaaddr, len);
241 if (term)
242 return;
243
244 maxlen -= AlphaISA::PageBytes;
245 dst += AlphaISA::PageBytes;
246 vaddr += AlphaISA::PageBytes;
247 }
248
249 if (maxlen > 0) {
250 paddr = vtophys(xc, vaddr);
251 dmaaddr = (char *)xc->physmem->dma_addr(paddr, maxlen);
252 assert(dmaaddr);
253
254 char *term = (char *)memchr(dmaaddr, 0, maxlen);
255 len = term ? (term - dmaaddr + 1) : maxlen;
256
257 memcpy(dst, dmaaddr, len);
258
259 maxlen -= len;
260 }
261
262 if (maxlen == 0)
263 dst[maxlen] = '\0';
264 }