/[gxemul]/trunk/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 /trunk/src/cpus/memory_arm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 7856 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


1 /*
2 * Copyright (C) 2005-2006 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.36 2006/07/14 16:33:28 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 "arm_cpu_types.h"
41 #include "cpu.h"
42 #include "memory.h"
43 #include "misc.h"
44
45 #include "armreg.h"
46
47 extern int quiet_mode;
48
49
50 /*
51 * arm_translate_v2p():
52 *
53 * Address translation with the MMU disabled. (Just treat the virtual address
54 * as a physical address.)
55 */
56 int arm_translate_v2p(struct cpu *cpu, uint64_t vaddr64,
57 uint64_t *return_paddr, int flags)
58 {
59 *return_paddr = vaddr64 & 0xffffffff;
60
61 return 2;
62 }
63
64
65 /*
66 * arm_check_access():
67 *
68 * Helper function. Returns 0 for no access, 1 for read-only, and 2 for
69 * read/write.
70 */
71 static int arm_check_access(struct cpu *cpu, int ap, int dav, int user)
72 {
73 int s, r;
74
75 switch (dav) {
76 case 0: /* No access at all. */
77 return 0;
78 case 1: /* Normal access check. */
79 break;
80 case 2: fatal("arm_check_access(): 1 shouldn't be used\n");
81 exit(1);
82 case 3: /* Anything is allowed. */
83 return 2;
84 }
85
86 switch (ap) {
87 case 0: s = (cpu->cd.arm.control & ARM_CONTROL_S)? 1 : 0;
88 r = (cpu->cd.arm.control & ARM_CONTROL_R)? 2 : 0;
89 switch (s + r) {
90 case 0: return 0;
91 case 1: return user? 0 : 1;
92 case 2: return 1;
93 }
94 fatal("arm_check_access: UNPREDICTABLE s+r value!\n");
95 return 0;
96 case 1: return user? 0 : 2;
97 case 2: return user? 1 : 2;
98 }
99
100 /* "case 3": */
101 return 2;
102 }
103
104
105 /*
106 * arm_translate_v2p_mmu():
107 *
108 * Don't call this function is userland_emul is non-NULL, or cpu is NULL.
109 *
110 * Return values:
111 * 0 Failure
112 * 1 Success, the page is readable only
113 * 2 Success, the page is read/write
114 *
115 * If this is a 1KB page access, then the return value is ORed with
116 * MEMORY_NOT_FULL_PAGE.
117 */
118 int arm_translate_v2p_mmu(struct cpu *cpu, uint64_t vaddr64,
119 uint64_t *return_paddr, int flags)
120 {
121 unsigned char *q;
122 uint32_t addr, d=0, d2 = (uint32_t)(int32_t)-1, ptba, vaddr = vaddr64;
123 int instr = flags & FLAG_INSTR;
124 int writeflag = (flags & FLAG_WRITEFLAG)? 1 : 0;
125 int useraccess = flags & MEMORY_USER_ACCESS;
126 int no_exceptions = flags & FLAG_NOEXCEPTIONS;
127 int user = (cpu->cd.arm.cpsr & ARM_FLAG_MODE) == ARM_MODE_USR32;
128 int domain, dav, ap0,ap1,ap2,ap3, ap = 0, access = 0;
129 int fs = 2; /* fault status (2 = terminal exception) */
130 int subpage = 0;
131
132 if (useraccess)
133 user = 1;
134
135 addr = ((vaddr & 0xfff00000ULL) >> 18);
136
137 if (cpu->cd.arm.translation_table == NULL ||
138 cpu->cd.arm.ttb != cpu->cd.arm.last_ttb) {
139 cpu->cd.arm.translation_table = memory_paddr_to_hostaddr(
140 cpu->mem, cpu->cd.arm.ttb & 0x0fffffff, 0);
141 cpu->cd.arm.last_ttb = cpu->cd.arm.ttb;
142 }
143
144 if (cpu->cd.arm.translation_table != NULL) {
145 d = *(uint32_t *)(cpu->cd.arm.translation_table + addr);
146 #ifdef HOST_LITTLE_ENDIAN
147 if (cpu->byte_order == EMUL_BIG_ENDIAN)
148 #else
149 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
150 #endif
151 d = ((d & 0xff) << 24) | ((d & 0xff00) << 8) |
152 ((d & 0xff0000) >> 8) | ((d & 0xff000000) >> 24);
153 }
154
155 /* Get the domain from the descriptor, and the Domain Access Value: */
156 domain = (d >> 5) & 15;
157 dav = (cpu->cd.arm.dacr >> (domain * 2)) & 3;
158
159 switch (d & 3) {
160
161 case 0: domain = 0;
162 fs = FAULT_TRANS_S;
163 goto exception_return;
164
165 case 1: /* Course Pagetable: */
166 if (dav == 0) {
167 fs = FAULT_DOMAIN_P;
168 goto exception_return;
169 }
170 ptba = d & 0xfffffc00;
171 addr = ptba + ((vaddr & 0x000ff000) >> 10);
172
173 q = memory_paddr_to_hostaddr(cpu->mem, addr & 0x0fffffff, 0);
174 if (q == NULL) {
175 printf("arm memory blah blah adfh asfg asdgasdg\n");
176 exit(1);
177 }
178 d2 = *(uint32_t *)(q);
179 #ifdef HOST_LITTLE_ENDIAN
180 if (cpu->byte_order == EMUL_BIG_ENDIAN)
181 #else
182 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
183 #endif
184 d2 = ((d2 & 0xff) << 24) | ((d2 & 0xff00) << 8) |
185 ((d2 & 0xff0000) >> 8) | ((d2 & 0xff000000) >> 24);
186
187 switch (d2 & 3) {
188 case 0: fs = FAULT_TRANS_P;
189 goto exception_return;
190 case 1: /* 16KB page: */
191 ap = (d2 >> 4) & 255;
192 switch (vaddr & 0x0000c000) {
193 case 0x4000: ap >>= 2; break;
194 case 0x8000: ap >>= 4; break;
195 case 0xc000: ap >>= 6; break;
196 }
197 ap &= 3;
198 *return_paddr = (d2 & 0xffff0000)|(vaddr & 0x0000ffff);
199 break;
200 case 3: if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE) {
201 /* 4KB page (Xscale) */
202 subpage = 0;
203 } else {
204 /* 1KB page */
205 subpage = 1;
206 ap = (d2 >> 4) & 3;
207 *return_paddr = (d2 & 0xfffffc00) |
208 (vaddr & 0x000003ff);
209 break;
210 }
211 /* NOTE: Fall-through for XScale! */
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 /* NOTE: Ugly hack for XScale: */
224 if ((d2 & 3) == 3) {
225 /* Treated as 4KB page: */
226 ap = ap0;
227 } else {
228 if (ap0 != ap1 || ap0 != ap2 || ap0 != ap3)
229 subpage = 1;
230 }
231 *return_paddr = (d2 & 0xfffff000)|(vaddr & 0x00000fff);
232 break;
233 }
234 access = arm_check_access(cpu, ap, dav, user);
235 if (access > writeflag)
236 return access | (subpage? MEMORY_NOT_FULL_PAGE : 0);
237 fs = FAULT_PERM_P;
238 goto exception_return;
239
240 case 2: /* Section descriptor: */
241 if (dav == 0) {
242 fs = FAULT_DOMAIN_S;
243 goto exception_return;
244 }
245 *return_paddr = (d & 0xfff00000) | (vaddr & 0x000fffff);
246 ap = (d >> 10) & 3;
247 access = arm_check_access(cpu, ap, dav, user);
248 if (access > writeflag)
249 return access;
250 fs = FAULT_PERM_S;
251 goto exception_return;
252
253 default:fatal("TODO: descriptor for vaddr 0x%08x: 0x%08x ("
254 "unimplemented type %i)\n", vaddr, d, d&3);
255 exit(1);
256 }
257
258 exception_return:
259 if (no_exceptions)
260 return 0;
261
262 if (!quiet_mode) {
263 fatal("{ arm memory fault: vaddr=0x%08x domain=%i dav=%i ap=%i "
264 "access=%i user=%i", (int)vaddr, domain, dav, ap,
265 access, user);
266 fatal(" d=0x%08x d2=0x%08x pc=0x%08x }\n", d, d2, (int)cpu->pc);
267 }
268
269 if (instr)
270 arm_exception(cpu, ARM_EXCEPTION_PREF_ABT);
271 else {
272 cpu->cd.arm.far = vaddr;
273 cpu->cd.arm.fsr = (domain << 4) | fs;
274 arm_exception(cpu, ARM_EXCEPTION_DATA_ABT);
275 }
276
277 return 0;
278 }
279

  ViewVC Help
Powered by ViewVC 1.1.26