/[gxemul]/upstream/0.3.7/src/cpus/memory_arm.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.7/src/cpus/memory_arm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 21 - (show annotations)
Mon Oct 8 16:19:28 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 7973 byte(s)
0.3.7
1 /*
2 * Copyright (C) 2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. 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 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: memory_arm.c,v 1.30 2005/11/05 17:56:46 debug Exp $
29 *
30 *
31 * TODO/NOTE: The B and/or C bits could also cause the return value to
32 * be MEMORY_NOT_FULL_PAGE, to make sure it doesn't get entered into the
33 * translation arrays. TODO: Find out if this is a good thing to do.
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "cpu.h"
41 #include "memory.h"
42 #include "misc.h"
43
44 #include "armreg.h"
45
46 extern int quiet_mode;
47
48
49 /*
50 * arm_translate_address():
51 *
52 * Address translation with the MMU disabled.
53 */
54 int arm_translate_address(struct cpu *cpu, uint64_t vaddr64,
55 uint64_t *return_addr, int flags)
56 {
57 *return_addr = vaddr64 & 0xffffffff;
58 return 2;
59 }
60
61
62 /*
63 * arm_check_access():
64 *
65 * Helper function. Returns 0 for no access, 1 for read-only, and 2 for
66 * read/write.
67 */
68 static int arm_check_access(struct cpu *cpu, int ap, int dav, int user)
69 {
70 int s, r;
71
72 switch (dav) {
73 case 0: /* No access at all. */
74 return 0;
75 case 1: /* Normal access check. */
76 break;
77 case 2: fatal("arm_check_access(): 1 shouldn't be used\n");
78 exit(1);
79 case 3: /* Anything is allowed. */
80 return 2;
81 }
82
83 switch (ap) {
84 case 0: s = (cpu->cd.arm.control & ARM_CONTROL_S)? 1 : 0;
85 r = (cpu->cd.arm.control & ARM_CONTROL_R)? 2 : 0;
86 switch (s + r) {
87 case 0: return 0;
88 case 1: return user? 0 : 1;
89 case 2: return 1;
90 }
91 fatal("arm_check_access: UNPREDICTABLE s+r value!\n");
92 return 0;
93 case 1: return user? 0 : 2;
94 case 2: return user? 1 : 2;
95 }
96
97 /* "case 3": */
98 return 2;
99 }
100
101
102 /*
103 * arm_translate_address_mmu():
104 *
105 * Don't call this function is userland_emul is non-NULL, or cpu is NULL.
106 *
107 * Return values:
108 * 0 Failure
109 * 1 Success, the page is readable only
110 * 2 Success, the page is read/write
111 *
112 * If this is a 1KB page access, then the return value is ORed with
113 * MEMORY_NOT_FULL_PAGE.
114 */
115 int arm_translate_address_mmu(struct cpu *cpu, uint64_t vaddr64,
116 uint64_t *return_addr, int flags)
117 {
118 unsigned char *q;
119 uint32_t addr, d=0, d2 = (uint32_t)(int32_t)-1, ptba, vaddr = vaddr64;
120 int instr = flags & FLAG_INSTR;
121 int writeflag = (flags & FLAG_WRITEFLAG)? 1 : 0;
122 int useraccess = flags & MEMORY_USER_ACCESS;
123 int no_exceptions = flags & FLAG_NOEXCEPTIONS;
124 int user = (cpu->cd.arm.cpsr & ARM_FLAG_MODE) == ARM_MODE_USR32;
125 int domain, dav, ap0,ap1,ap2,ap3, ap = 0, access = 0;
126 int fs = 2; /* fault status (2 = terminal exception) */
127 int subpage = 0;
128
129 if (useraccess)
130 user = 1;
131
132 addr = ((vaddr & 0xfff00000ULL) >> 18);
133
134 if (cpu->cd.arm.translation_table == NULL ||
135 cpu->cd.arm.ttb != cpu->cd.arm.last_ttb) {
136 uint32_t ofs;
137 cpu->cd.arm.translation_table = memory_paddr_to_hostaddr(
138 cpu->mem, cpu->cd.arm.ttb & 0x0fffffff, 0);
139 if (cpu->cd.arm.translation_table != NULL) {
140 ofs = cpu->cd.arm.ttb & ((1 << BITS_PER_MEMBLOCK) - 1);
141 cpu->cd.arm.translation_table += ofs;
142 }
143 cpu->cd.arm.last_ttb = cpu->cd.arm.ttb;
144 }
145
146 if (cpu->cd.arm.translation_table != NULL) {
147 d = *(uint32_t *)(cpu->cd.arm.translation_table + addr);
148 #ifdef HOST_LITTLE_ENDIAN
149 if (cpu->byte_order == EMUL_BIG_ENDIAN)
150 #else
151 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
152 #endif
153 d = ((d & 0xff) << 24) | ((d & 0xff00) << 8) |
154 ((d & 0xff0000) >> 8) | ((d & 0xff000000) >> 24);
155 }
156
157 /* Get the domain from the descriptor, and the Domain Access Value: */
158 domain = (d >> 5) & 15;
159 dav = (cpu->cd.arm.dacr >> (domain * 2)) & 3;
160
161 switch (d & 3) {
162
163 case 0: domain = 0;
164 fs = FAULT_TRANS_S;
165 goto exception_return;
166
167 case 1: /* Course Pagetable: */
168 if (dav == 0) {
169 fs = FAULT_DOMAIN_P;
170 goto exception_return;
171 }
172 ptba = d & 0xfffffc00;
173 addr = ptba + ((vaddr & 0x000ff000) >> 10);
174
175 q = memory_paddr_to_hostaddr(cpu->mem, addr & 0x0fffffff, 0);
176 if (q == NULL) {
177 printf("arm memory blah blah adfh asfg asdgasdg\n");
178 exit(1);
179 }
180 d2 = *(uint32_t *)(q + (addr & ((1 << BITS_PER_MEMBLOCK) - 1)));
181 #ifdef HOST_LITTLE_ENDIAN
182 if (cpu->byte_order == EMUL_BIG_ENDIAN)
183 #else
184 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
185 #endif
186 d2 = ((d2 & 0xff) << 24) | ((d2 & 0xff00) << 8) |
187 ((d2 & 0xff0000) >> 8) | ((d2 & 0xff000000) >> 24);
188
189 switch (d2 & 3) {
190 case 0: fs = FAULT_TRANS_P;
191 goto exception_return;
192 case 1: /* 16KB page: */
193 ap = (d2 >> 4) & 255;
194 switch (vaddr & 0x0000c000) {
195 case 0x4000: ap >>= 2; break;
196 case 0x8000: ap >>= 4; break;
197 case 0xc000: ap >>= 6; break;
198 }
199 ap &= 3;
200 *return_addr = (d2 & 0xffff0000) | (vaddr & 0x0000ffff);
201 break;
202 case 3: {
203 static int first = 1;
204 if (first) {
205 fatal("[ WARNING! ARM course second "
206 "level page table seems to contain"
207 " tiny pages; treating as 4K ]\n");
208 first = 0;
209 }
210 }
211 subpage = 1;
212 case 2: /* 4KB page: */
213 ap3 = (d2 >> 10) & 3;
214 ap2 = (d2 >> 8) & 3;
215 ap1 = (d2 >> 6) & 3;
216 ap0 = (d2 >> 4) & 3;
217 switch (vaddr & 0x00000c00) {
218 case 0x000: ap = ap0; break;
219 case 0x400: ap = ap1; break;
220 case 0x800: ap = ap2; break;
221 default: ap = ap3;
222 }
223 /* Ugly hack: (TODO) */
224 if ((d2 & 3) == 3)
225 ap = ap0;
226 if (ap0 != ap1 || ap0 != ap2 || ap0 != ap3)
227 subpage = 1;
228 *return_addr = (d2 & 0xfffff000) | (vaddr & 0x00000fff);
229 break;
230 #if 0
231 case 3: /* 1KB page: */
232 subpage = 1;
233 ap = (d2 >> 4) & 3;
234 *return_addr = (d2 & 0xfffffc00) | (vaddr & 0x000003ff);
235 break;
236 #endif
237 }
238 access = arm_check_access(cpu, ap, dav, user);
239 if (access > writeflag)
240 return access | (subpage? MEMORY_NOT_FULL_PAGE : 0);
241 fs = FAULT_PERM_P;
242 goto exception_return;
243
244 case 2: /* Section descriptor: */
245 if (dav == 0) {
246 fs = FAULT_DOMAIN_S;
247 goto exception_return;
248 }
249 *return_addr = (d & 0xfff00000) | (vaddr & 0x000fffff);
250 ap = (d >> 10) & 3;
251 access = arm_check_access(cpu, ap, dav, user);
252 if (access > writeflag)
253 return access;
254 fs = FAULT_PERM_S;
255 goto exception_return;
256
257 default:fatal("TODO: descriptor for vaddr 0x%08x: 0x%08x ("
258 "unimplemented type %i)\n", vaddr, d, d&3);
259 exit(1);
260 }
261
262 exception_return:
263 if (no_exceptions)
264 return 0;
265
266 if (!quiet_mode) {
267 fatal("{ arm memory fault: vaddr=0x%08x domain=%i dav=%i ap=%i "
268 "access=%i user=%i", (int)vaddr, domain, dav, ap,
269 access, user);
270 fatal(" d=0x%08x d2=0x%08x }\n", d, d2);
271 }
272
273 if (instr)
274 arm_exception(cpu, ARM_EXCEPTION_PREF_ABT);
275 else {
276 cpu->cd.arm.far = vaddr;
277 cpu->cd.arm.fsr = (domain << 4) | fs;
278 arm_exception(cpu, ARM_EXCEPTION_DATA_ABT);
279 }
280
281 return 0;
282 }
283

  ViewVC Help
Powered by ViewVC 1.1.26