summaryrefslogtreecommitdiff
path: root/src/core/arm/interpreter/mmu
diff options
context:
space:
mode:
authorGravatar bunnei2014-05-15 22:54:17 -0400
committerGravatar bunnei2014-05-15 22:54:17 -0400
commit3e1eafa244dc2ea6a1d8de6e841370c83c362dda (patch)
treef4fb8778ccb4d71cc73c10a7ad4d0be62acc4533 /src/core/arm/interpreter/mmu
parentMerge pull request #15 from bunnei/hle-services (diff)
downloadyuzu-3e1eafa244dc2ea6a1d8de6e841370c83c362dda.tar.gz
yuzu-3e1eafa244dc2ea6a1d8de6e841370c83c362dda.tar.xz
yuzu-3e1eafa244dc2ea6a1d8de6e841370c83c362dda.zip
- moved mmu to arm/interpreter folder
- added initial VFP code from skyeye
Diffstat (limited to 'src/core/arm/interpreter/mmu')
-rw-r--r--src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp1132
-rw-r--r--src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h37
-rw-r--r--src/core/arm/interpreter/mmu/cache.h168
-rw-r--r--src/core/arm/interpreter/mmu/rb.h55
-rw-r--r--src/core/arm/interpreter/mmu/tlb.h94
-rw-r--r--src/core/arm/interpreter/mmu/wb.h63
6 files changed, 1549 insertions, 0 deletions
diff --git a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
new file mode 100644
index 000000000..a32f076b9
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
@@ -0,0 +1,1132 @@
1/*
2 arm1176jzf_s_mmu.c - ARM920T Memory Management Unit emulation.
3 Copyright (C) 2003 Skyeye Develop Group
4 for help please send mail to <skyeye-developer@lists.gro.clinux.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21#include <assert.h>
22#include <string.h>
23#include <stdint.h>
24
25#include "core/mem_map.h"
26
27#include "core/arm/interpreter/skyeye_defs.h"
28
29#include "core/arm/interpreter/armdefs.h"
30//#include "bank_defs.h"
31#if 0
32#define TLB_SIZE 1024 * 1024
33#define ASID 255
34static uint32_t tlb_entry_array[TLB_SIZE][ASID];
35static inline void invalidate_all_tlb(ARMul_State *state){
36 memset(&tlb_entry_array[0], 0xFF, sizeof(uint32_t) * TLB_SIZE * ASID);
37}
38static inline void invalidate_by_mva(ARMul_State *state, ARMword va){
39 memset(&tlb_entry_array[va >> 12][va & 0xFF], 0xFF, sizeof(uint32_t));
40 return;
41}
42static inline void invalidate_by_asid(ARMul_State *state, ARMword asid){
43 int i;
44 for(i = 0; i < TLB_SIZE; i++)
45 memset(&tlb_entry_array[i][asid & 0xFF], 0xFF, sizeof(uint32_t));
46 return;
47}
48
49static uint32_t get_phys_page(ARMul_State* state, ARMword va){
50 uint32_t phys_page = tlb_entry_array[va >> 12][state->mmu.context_id & 0xFF];
51 //printf("In %s, for va=0x%x, page=0x%x\n", __func__, va, phys_page);
52 return phys_page;
53}
54
55static inline void insert_tlb(ARMul_State* state, ARMword va, ARMword pa){
56 //printf("In %s, insert va=0x%x, pa=0x%x\n", __FUNCTION__, va, pa);
57 //printf("In %s, insert va=0x%x, va>>12=0x%x, pa=0x%x, pa>>12=0x%x\n", __FUNCTION__, va, va >> 12, pa, pa >> 12);
58 tlb_entry_array[va >> 12][state->mmu.context_id & 0xFF] = pa >> 12;
59
60 return;
61}
62#endif
63#define BANK0_START 0x50000000
64static void* mem_ptr = NULL;
65
66static int exclusive_detect(ARMul_State* state, ARMword addr){
67 #if 0
68 for(int i = 0; i < 128; i++){
69 if(state->exclusive_tag_array[i] == addr)
70 return 0;
71 }
72 #endif
73 if(state->exclusive_tag_array[0] == addr)
74 return 0;
75 else
76 return -1;
77}
78
79static void add_exclusive_addr(ARMul_State* state, ARMword addr){
80 #if 0
81 for(int i = 0; i < 128; i++){
82 if(state->exclusive_tag_array[i] == 0xffffffff){
83 state->exclusive_tag_array[i] = addr;
84 //printf("In %s, add addr 0x%x\n", __func__, addr);
85 return;
86 }
87 }
88 printf("In %s ,can not monitor the addr, out of array\n", __FUNCTION__);
89 #endif
90 state->exclusive_tag_array[0] = addr;
91 return;
92}
93
94static void remove_exclusive(ARMul_State* state, ARMword addr){
95 #if 0
96 int i;
97 for(i = 0; i < 128; i++){
98 if(state->exclusive_tag_array[i] == addr){
99 state->exclusive_tag_array[i] = 0xffffffff;
100 //printf("In %s, remove addr 0x%x\n", __func__, addr);
101 return;
102 }
103 }
104 #endif
105 state->exclusive_tag_array[0] = 0xFFFFFFFF;
106}
107
108/* This function encodes table 8-2 Interpreting AP bits,
109 returning non-zero if access is allowed. */
110static int
111check_perms (ARMul_State *state, int ap, int read)
112{
113 int s, r, user;
114
115 s = state->mmu.control & CONTROL_SYSTEM;
116 r = state->mmu.control & CONTROL_ROM;
117 /* chy 2006-02-15 , should consider system mode, don't conside 26bit mode */
118// printf("ap is %x, user is %x, s is %x, read is %x\n", ap, user, s, read);
119// printf("mode is %x\n", state->Mode);
120 user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE);
121
122 switch (ap) {
123 case 0:
124 return read && ((s && !user) || r);
125 case 1:
126 return !user;
127 case 2:
128 return read || !user;
129 case 3:
130 return 1;
131 }
132 return 0;
133}
134
135#if 0
136fault_t
137check_access (ARMul_State *state, ARMword virt_addr, tlb_entry_t *tlb,
138 int read)
139{
140 int access;
141
142 state->mmu.last_domain = tlb->domain;
143 access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3;
144 if ((access == 0) || (access == 2)) {
145 /* It's unclear from the documentation whether this
146 should always raise a section domain fault, or if
147 it should be a page domain fault in the case of an
148 L1 that describes a page table. In the ARM710T
149 datasheets, "Figure 8-9: Sequence for checking faults"
150 seems to indicate the former, while "Table 8-4: Priority
151 encoding of fault status" gives a value for FS[3210] in
152 the event of a domain fault for a page. Hmm. */
153 return SECTION_DOMAIN_FAULT;
154 }
155 if (access == 1) {
156 /* client access - check perms */
157 int subpage, ap;
158#if 0
159 switch (tlb->mapping) {
160 /*ks 2004-05-09
161 * only for XScale
162 * Extend Small Page(ESP) Format
163 * 31-12 bits the base addr of ESP
164 * 11-10 bits SBZ
165 * 9-6 bits TEX
166 * 5-4 bits AP
167 * 3 bit C
168 * 2 bit B
169 * 1-0 bits 11
170 * */
171 case TLB_ESMALLPAGE: /* xj */
172 subpage = 0;
173 /* printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr ); */
174 break;
175
176 case TLB_TINYPAGE:
177 subpage = 0;
178 /* printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr ); */
179 break;
180
181 case TLB_SMALLPAGE:
182 subpage = (virt_addr >> 10) & 3;
183 break;
184 case TLB_LARGEPAGE:
185 subpage = (virt_addr >> 14) & 3;
186 break;
187 case TLB_SECTION:
188 subpage = 3;
189 break;
190 default:
191 assert (0);
192 subpage = 0; /* cleans a warning */
193 }
194 ap = (tlb->perms >> (subpage * 2 + 4)) & 3;
195 if (!check_perms (state, ap, read)) {
196 if (tlb->mapping == TLB_SECTION) {
197 return SECTION_PERMISSION_FAULT;
198 } else {
199 return SUBPAGE_PERMISSION_FAULT;
200 }
201 }
202#endif
203 } else { /* access == 3 */
204 /* manager access - don't check perms */
205 }
206 return NO_FAULT;
207}
208#endif
209
210#if 0
211fault_t
212mmu_translate (ARMul_State *state, ARMword virt_addr, ARMword *phys_addr)
213#endif
214
215/* ap: AP bits value.
216 * sop: section or page description 0:section 1:page
217 */
218fault_t
219mmu_translate (ARMul_State *state, ARMword virt_addr, ARMword *phys_addr, int *ap, int *sop)
220{
221 {
222 /* walk the translation tables */
223 ARMword l1addr, l1desc;
224 if (state->mmu.translation_table_ctrl && virt_addr << state->mmu.translation_table_ctrl >> (32 - state->mmu.translation_table_ctrl - 1)) {
225 l1addr = state->mmu.translation_table_base1;
226 l1addr = (((l1addr >> 14) << 14) | (virt_addr >> 18)) & ~3;
227 } else {
228 l1addr = state->mmu.translation_table_base0;
229 l1addr = (((l1addr >> (14 - state->mmu.translation_table_ctrl)) << (14 - state->mmu.translation_table_ctrl)) | (virt_addr << state->mmu.translation_table_ctrl) >> (18 + state->mmu.translation_table_ctrl)) & ~3;
230 }
231
232 /* l1desc = mem_read_word (state, l1addr); */
233 if (state->space.conf_obj != NULL)
234 state->space.read(state->space.conf_obj, l1addr, &l1desc, 4);
235 else
236 l1desc = Memory::Read32(l1addr); //mem_read_raw(32, l1addr, &l1desc);
237
238 #if 0
239 if (virt_addr == 0xc000d2bc) {
240 printf("mmu_control is %x\n", state->mmu.translation_table_ctrl);
241 printf("mmu_table_0 is %x\n", state->mmu.translation_table_base0);
242 printf("mmu_table_1 is %x\n", state->mmu.translation_table_base1);
243 printf("l1addr is %x l1desc is %x\n", l1addr, l1desc);
244 // exit(-1);
245 }
246 #endif
247 switch (l1desc & 3) {
248 case 0:
249 case 3:
250 /*
251 * according to Figure 3-9 Sequence for checking faults in arm manual,
252 * section translation fault should be returned here.
253 */
254 {
255 return SECTION_TRANSLATION_FAULT;
256 }
257 case 1:
258 /* coarse page table */
259 {
260 ARMword l2addr, l2desc;
261
262
263 l2addr = l1desc & 0xFFFFFC00;
264 l2addr = (l2addr |
265 ((virt_addr & 0x000FF000) >> 10)) &
266 ~3;
267 if(state->space.conf_obj != NULL)
268 state->space.read(state->space.conf_obj, l2addr, &l2desc, 4);
269 else
270 l2desc = Memory::Read32(l2addr); //mem_read_raw(32, l2addr, &l2desc);
271
272 /* chy 2003-09-02 for xscale */
273 *ap = (l2desc >> 4) & 0x3;
274 *sop = 1; /* page */
275
276 switch (l2desc & 3) {
277 case 0:
278 return PAGE_TRANSLATION_FAULT;
279 break;
280 case 1:
281 *phys_addr = (l2desc & 0xFFFF0000) | (virt_addr & 0x0000FFFF);
282 break;
283 case 2:
284 case 3:
285 *phys_addr = (l2desc & 0xFFFFF000) | (virt_addr & 0x00000FFF);
286 break;
287
288 }
289 }
290 break;
291 case 2:
292 /* section */
293
294 *ap = (l1desc >> 10) & 3;
295 *sop = 0; /* section */
296 #if 0
297 if (virt_addr == 0xc000d2bc) {
298 printf("mmu_control is %x\n", state->mmu.translation_table_ctrl);
299 printf("mmu_table_0 is %x\n", state->mmu.translation_table_base0);
300 printf("mmu_table_1 is %x\n", state->mmu.translation_table_base1);
301 printf("l1addr is %x l1desc is %x\n", l1addr, l1desc);
302// printf("l2addr is %x l2desc is %x\n", l2addr, l2desc);
303 printf("ap is %x, sop is %x\n", *ap, *sop);
304 printf("mode is %d\n", state->Mode);
305// exit(-1);
306 }
307 #endif
308
309 if (l1desc & 0x30000)
310 *phys_addr = (l1desc & 0xFF000000) | (virt_addr & 0x00FFFFFF);
311 else
312 *phys_addr = (l1desc & 0xFFF00000) | (virt_addr & 0x000FFFFF);
313 break;
314 }
315 }
316 return NO_FAULT;
317}
318
319
320static fault_t arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va,
321 ARMword data, ARMword datatype);
322static fault_t arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va,
323 ARMword *data, ARMword datatype);
324
325int
326arm1176jzf_s_mmu_init (ARMul_State *state)
327{
328 state->mmu.control = 0x50078;
329 state->mmu.translation_table_base = 0xDEADC0DE;
330 state->mmu.domain_access_control = 0xDEADC0DE;
331 state->mmu.fault_status = 0;
332 state->mmu.fault_address = 0;
333 state->mmu.process_id = 0;
334 state->mmu.context_id = 0;
335 state->mmu.thread_uro_id = 0;
336 //invalidate_all_tlb(state);
337
338 return No_exp;
339}
340
341void
342arm1176jzf_s_mmu_exit (ARMul_State *state)
343{
344}
345
346
347static fault_t
348arm1176jzf_s_mmu_load_instr (ARMul_State *state, ARMword va, ARMword *instr)
349{
350 fault_t fault;
351 int c; /* cache bit */
352 ARMword pa; /* physical addr */
353 ARMword perm; /* physical addr access permissions */
354 int ap, sop;
355
356 static int debug_count = 0; /* used for debug */
357
358 //DEBUG_LOG(ARM11, "va = %x\n", va);
359
360 va = mmu_pid_va_map (va);
361 if (MMU_Enabled) {
362// printf("MMU enabled.\n");
363// sleep(1);
364 /* align check */
365 if ((va & (WORD_SIZE - 1)) && MMU_Aligned) {
366 DEBUG_LOG(ARM11, "align\n");
367 return ALIGNMENT_FAULT;
368 } else
369 va &= ~(WORD_SIZE - 1);
370
371 /* translate tlb */
372 fault = mmu_translate (state, va, &pa, &ap, &sop);
373 if (fault) {
374 DEBUG_LOG(ARM11, "translate\n");
375 printf("va=0x%x, icounter=%lld, fault=%d\n", va, state->NumInstrs, fault);
376 return fault;
377 }
378
379
380 /* no tlb, only check permission */
381 if (!check_perms(state, ap, 1)) {
382 if (sop == 0) {
383 return SECTION_PERMISSION_FAULT;
384 } else {
385 return SUBPAGE_PERMISSION_FAULT;
386 }
387 }
388
389#if 0
390 /*check access */
391 fault = check_access (state, va, tlb, 1);
392 if (fault) {
393 DEBUG_LOG(ARM11, "check_fault\n");
394 return fault;
395 }
396#endif
397 }
398
399 /*if MMU disabled or C flag is set alloc cache */
400 if (MMU_Disabled) {
401// printf("MMU disabled.\n");
402// sleep(1);
403 pa = va;
404 }
405 if(state->space.conf_obj == NULL)
406 state->space.read(state->space.conf_obj, pa, instr, 4);
407 else
408 *instr = Memory::Read32(pa); //mem_read_raw(32, pa, instr);
409
410 return NO_FAULT;
411}
412
413static fault_t
414arm1176jzf_s_mmu_read_byte (ARMul_State *state, ARMword virt_addr, ARMword *data)
415{
416 /* ARMword temp,offset; */
417 fault_t fault;
418 fault = arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
419 return fault;
420}
421
422static fault_t
423arm1176jzf_s_mmu_read_halfword (ARMul_State *state, ARMword virt_addr,
424 ARMword *data)
425{
426 /* ARMword temp,offset; */
427 fault_t fault;
428 fault = arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
429 return fault;
430}
431
432static fault_t
433arm1176jzf_s_mmu_read_word (ARMul_State *state, ARMword virt_addr, ARMword *data)
434{
435 return arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
436}
437
438static fault_t
439arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va, ARMword *data,
440 ARMword datatype)
441{
442 fault_t fault;
443 ARMword pa, real_va, temp, offset;
444 ARMword perm; /* physical addr access permissions */
445 int ap, sop;
446
447 //DEBUG_LOG(ARM11, "va = %x\n", va);
448
449 va = mmu_pid_va_map (va);
450 real_va = va;
451 /* if MMU disabled, memory_read */
452 if (MMU_Disabled) {
453// printf("MMU disabled cpu_id:%x addr:%x.\n", state->mmu.process_id, va);
454// sleep(1);
455
456 /* *data = mem_read_word(state, va); */
457 if (datatype == ARM_BYTE_TYPE)
458 /* *data = mem_read_byte (state, va); */
459 if(state->space.conf_obj != NULL)
460 state->space.read(state->space.conf_obj, va, data, 1);
461 else
462 *data = Memory::Read8(va); //mem_read_raw(8, va, data);
463 else if (datatype == ARM_HALFWORD_TYPE)
464 /* *data = mem_read_halfword (state, va); */
465 if(state->space.conf_obj != NULL)
466 state->space.read(state->space.conf_obj, va, data, 2);
467 else
468 *data = Memory::Read16(va); //mem_read_raw(16, va, data);
469 else if (datatype == ARM_WORD_TYPE)
470 /* *data = mem_read_word (state, va); */
471 if(state->space.conf_obj != NULL)
472 state->space.read(state->space.conf_obj, va, data, 4);
473 else
474 *data = Memory::Read32(va); //mem_read_raw(32, va, data);
475 else {
476 ERROR_LOG(ARM11, "SKYEYE:1 arm1176jzf_s_mmu_read error: unknown data type %d\n", datatype);
477 }
478
479 return NO_FAULT;
480 }
481// printf("MMU enabled.\n");
482// sleep(1);
483
484 /* align check */
485 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
486 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
487 DEBUG_LOG(ARM11, "align\n");
488 return ALIGNMENT_FAULT;
489 }
490
491 /* va &= ~(WORD_SIZE - 1); */
492 #if 0
493 uint32_t page_base;
494 page_base = get_phys_page(state, va);
495 if((page_base & 0xFFF) == 0){
496 pa = (page_base << 12) | (va & 0xFFF);
497 goto skip_translation;
498 }
499 #endif
500 /*translate va to tlb */
501#if 0
502 fault = mmu_translate (state, va, ARM920T_D_TLB (), &tlb);
503#endif
504 fault = mmu_translate (state, va, &pa, &ap, &sop);
505#if 0
506 if(va ==0xbebb1774 || state->Reg[15] == 0x400ff594){
507 //printf("In %s, current=0x%x. mode is %x, pc=0x%x\n", __FUNCTION__, state->CurrInstr, state->Mode, state->Reg[15]);
508 printf("In %s, ap is %d, sop is %d, va=0x%x, pa=0x%x, fault=%d, data=0x%x\n", __FUNCTION__, ap, sop, va, pa, fault, data);
509 int i;
510 for(i = 0; i < 16; i++)
511 printf("Reg[%d]=0x%x\t", i, state->Reg[i]);
512 printf("\n");
513 }
514#endif
515 if (fault) {
516 DEBUG_LOG(ARM11, "translate\n");
517 //printf("mmu read fault at %x\n", va);
518 //printf("fault is %d\n", fault);
519 return fault;
520 }
521// printf("va is %x pa is %x\n", va, pa);
522
523 /* no tlb, only check permission */
524 if (!check_perms(state, ap, 1)) {
525 if (sop == 0) {
526 return SECTION_PERMISSION_FAULT;
527 } else {
528 return SUBPAGE_PERMISSION_FAULT;
529 }
530 }
531#if 0
532 /*check access permission */
533 fault = check_access (state, va, tlb, 1);
534 if (fault)
535 return fault;
536#endif
537
538 //insert_tlb(state, va, pa);
539skip_translation:
540 /* *data = mem_read_word(state, pa); */
541 if (datatype == ARM_BYTE_TYPE) {
542 /* *data = mem_read_byte (state, pa | (real_va & 3)); */
543 if(state->space.conf_obj != NULL)
544 state->space.read(state->space.conf_obj, pa | (real_va & 3), data, 1);
545 else
546 *data = Memory::Read8(pa | (real_va & 3)); //mem_read_raw(8, pa | (real_va & 3), data);
547 /* mem_read_raw(32, pa | (real_va & 3), data); */
548 } else if (datatype == ARM_HALFWORD_TYPE) {
549 /* *data = mem_read_halfword (state, pa | (real_va & 2)); */
550 if(state->space.conf_obj != NULL)
551 state->space.read(state->space.conf_obj, pa | (real_va & 3), data, 2);
552 else
553 *data = Memory::Read16(pa | (real_va & 3)); //mem_read_raw(16, pa | (real_va & 3), data);
554 /* mem_read_raw(32, pa | (real_va & 2), data); */
555 } else if (datatype == ARM_WORD_TYPE)
556 /* *data = mem_read_word (state, pa); */
557 if(state->space.conf_obj != NULL)
558 state->space.read(state->space.conf_obj, pa , data, 4);
559 else
560 *data = Memory::Read32(pa); //mem_read_raw(32, pa, data);
561 else {
562 ERROR_LOG(ARM11, "SKYEYE:2 arm1176jzf_s_mmu_read error: unknown data type %d\n", datatype);
563 }
564 if(0 && (va == 0x2869c)){
565 printf("In %s, pa is %x va=0x%x, value is %x pc %x, instr=0x%x\n", __FUNCTION__, pa, va, *data, state->Reg[15], state->CurrInstr);
566 }
567
568 /* ldrex or ldrexb */
569 if(((state->CurrInstr & 0x0FF000F0) == 0x01900090) ||
570 ((state->CurrInstr & 0x0FF000F0) == 0x01d00090)){
571 int rn = (state->CurrInstr & 0xF0000) >> 16;
572 if(state->Reg[rn] == va){
573 add_exclusive_addr(state, pa | (real_va & 3));
574 state->exclusive_access_state = 1;
575 }
576 }
577#if 0
578 if (state->pc == 0xc011a868) {
579 printf("pa is %x value is %x size is %x\n", pa, data, datatype);
580 printf("icounter is %lld\n", state->NumInstrs);
581// exit(-1);
582 }
583#endif
584
585 return NO_FAULT;
586}
587
588
589static fault_t
590arm1176jzf_s_mmu_write_byte (ARMul_State *state, ARMword virt_addr, ARMword data)
591{
592 return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
593}
594
595static fault_t
596arm1176jzf_s_mmu_write_halfword (ARMul_State *state, ARMword virt_addr,
597 ARMword data)
598{
599 return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
600}
601
602static fault_t
603arm1176jzf_s_mmu_write_word (ARMul_State *state, ARMword virt_addr, ARMword data)
604{
605 return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
606}
607
608
609
610static fault_t
611arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va, ARMword data,
612 ARMword datatype)
613{
614 int b;
615 ARMword pa, real_va;
616 ARMword perm; /* physical addr access permissions */
617 fault_t fault;
618 int ap, sop;
619
620#if 0
621 /8 for sky_printk debugger.*/
622 if (va == 0xffffffff) {
623 putchar((char)data);
624 return 0;
625 }
626 if (va == 0xBfffffff) {
627 putchar((char)data);
628 return 0;
629 }
630#endif
631
632 //DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
633 va = mmu_pid_va_map (va);
634 real_va = va;
635
636 if (MMU_Disabled) {
637 /* mem_write_word(state, va, data); */
638 if (datatype == ARM_BYTE_TYPE)
639 /* mem_write_byte (state, va, data); */
640 if(state->space.conf_obj != NULL)
641 state->space.write(state->space.conf_obj, va, &data, 1);
642 else
643 Memory::Write8(va, data);
644 else if (datatype == ARM_HALFWORD_TYPE)
645 /* mem_write_halfword (state, va, data); */
646 if(state->space.conf_obj != NULL)
647 state->space.write(state->space.conf_obj, va, &data, 2);
648 else
649 Memory::Write16(va, data);
650 else if (datatype == ARM_WORD_TYPE)
651 /* mem_write_word (state, va, data); */
652 if(state->space.conf_obj != NULL)
653 state->space.write(state->space.conf_obj, va, &data, 4);
654 else
655 Memory::Write32(va, data);
656 else {
657 ERROR_LOG (ARM11, "SKYEYE:1 arm1176jzf_s_mmu_write error: unknown data type %d\n", datatype);
658 }
659 goto finished_write;
660 //return 0;
661 }
662 /*align check */
663 /* if ((va & (WORD_SIZE - 1)) && MMU_Aligned){ */
664 if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
665 ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
666 DEBUG_LOG(ARM11, "align\n");
667 return ALIGNMENT_FAULT;
668 }
669 va &= ~(WORD_SIZE - 1);
670 #if 0
671 uint32_t page_base;
672 page_base = get_phys_page(state, va);
673 if((page_base & 0xFFF) == 0){
674 pa = (page_base << 12) | (va & 0xFFF);
675 goto skip_translation;
676 }
677 #endif
678 /*tlb translate */
679 fault = mmu_translate (state, va, &pa, &ap, &sop);
680#if 0
681 if(va ==0xbebb1774 || state->Reg[15] == 0x40102334){
682 //printf("In %s, current=0x%x. mode is %x, pc=0x%x\n", __FUNCTION__, state->CurrInstr, state->Mode, state->Reg[15]);
683 printf("In %s, ap is %d, sop is %d, va=0x%x, pa=0x%x, fault=%d, data=0x%x\n", __FUNCTION__, ap, sop, va, pa, fault, data);
684 int i;
685 for(i = 0; i < 16; i++)
686 printf("Reg[%d]=0x%x\t", i, state->Reg[i]);
687 printf("\n");
688 }
689#endif
690 if (fault) {
691 DEBUG_LOG(ARM11, "translate\n");
692 //printf("mmu write fault at %x\n", va);
693 return fault;
694 }
695// printf("va is %x pa is %x\n", va, pa);
696
697 /* no tlb, only check permission */
698 if (!check_perms(state, ap, 0)) {
699 if (sop == 0) {
700 return SECTION_PERMISSION_FAULT;
701 } else {
702 return SUBPAGE_PERMISSION_FAULT;
703 }
704 }
705
706#if 0
707 /* tlb check access */
708 fault = check_access (state, va, tlb, 0);
709 if (fault) {
710 DEBUG_LOG(ARM11, "check_access\n");
711 return fault;
712 }
713#endif
714#if 0
715 if (pa <= 0x502860ff && (pa + 1 << datatype) > 0x502860ff) {
716 printf("pa is %x value is %x size is %x\n", pa, data, datatype);
717 }
718#endif
719#if 0
720 if (state->pc == 0xc011a878) {
721 printf("write pa is %x value is %x size is %x\n", pa, data, datatype);
722 printf("icounter is %lld\n", state->NumInstrs);
723 exit(-1);
724 }
725#endif
726 //insert_tlb(state, va, pa);
727skip_translation:
728 /* strex */
729 if(((state->CurrInstr & 0x0FF000F0) == 0x01800090) ||
730 ((state->CurrInstr & 0x0FF000F0) == 0x01c00090)){
731 /* failed , the address is monitord now. */
732 int dest_reg = (state->CurrInstr & 0xF000) >> 12;
733 if((exclusive_detect(state, pa | (real_va & 3)) == 0) && (state->exclusive_access_state == 1)){
734 remove_exclusive(state, pa | (real_va & 3));
735 state->Reg[dest_reg] = 0;
736 state->exclusive_access_state = 0;
737 }
738 else{
739 state->Reg[dest_reg] = 1;
740 //printf("In %s, try to strex a monitored address 0x%x\n", __FUNCTION__, pa);
741 return NO_FAULT;
742 }
743 }
744
745 if (datatype == ARM_BYTE_TYPE) {
746 /* mem_write_byte (state,
747 (pa | (real_va & 3)),
748 data);
749 */
750 if(state->space.conf_obj != NULL)
751 state->space.write(state->space.conf_obj, (pa | (real_va & 3)), &data, 1);
752 else
753 Memory::Write8((pa | (real_va & 3)), data);
754
755 } else if (datatype == ARM_HALFWORD_TYPE)
756 /* mem_write_halfword (state,
757 (pa |
758 (real_va & 2)),
759 data);
760 */
761 if(state->space.conf_obj != NULL)
762 state->space.write(state->space.conf_obj, (pa | (real_va & 3)), &data, 2);
763 else
764 Memory::Write16((pa | (real_va & 3)), data);
765 else if (datatype == ARM_WORD_TYPE)
766 /* mem_write_word (state, pa, data); */
767 if(state->space.conf_obj != NULL)
768 state->space.write(state->space.conf_obj, pa, &data, 4);
769 else
770 Memory::Write32(pa, data);
771#if 0
772 if (state->NumInstrs > 236403) {
773 printf("write memory\n");
774 printf("pa is %x value is %x size is %x\n", pa, data, datatype);
775 printf("icounter is %lld\n", state->NumInstrs);
776 }
777#endif
778finished_write:
779#if DIFF_WRITE
780 if(state->icounter > state->debug_icounter){
781 if(state->CurrWrite >= 17 ){
782 printf("Wrong write array, 0x%x", state->CurrWrite);
783 exit(-1);
784 }
785 uint32 record_data = data;
786 if(datatype == ARM_BYTE_TYPE)
787 record_data &= 0xFF;
788 if(datatype == ARM_HALFWORD_TYPE)
789 record_data &= 0xFFFF;
790
791 state->WriteAddr[state->CurrWrite] = pa | (real_va & 3);
792 state->WriteData[state->CurrWrite] = record_data;
793 state->WritePc[state->CurrWrite] = state->Reg[15];
794 state->CurrWrite++;
795 //printf("In %s, pc=0x%x, addr=0x%x, data=0x%x, CFlag=%d\n", __FUNCTION__, state->Reg[15], pa | (real_va & 3), record_data, state->CFlag);
796 }
797#endif
798
799 return NO_FAULT;
800}
801
802ARMword
803arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value)
804{
805 int creg = BITS (16, 19) & 0xf;
806 int OPC_1 = BITS (21, 23) & 0x7;
807 int OPC_2 = BITS (5, 7) & 0x7;
808 ARMword data;
809
810 switch (creg) {
811 case MMU_ID:
812 if (OPC_2 == 0) {
813 data = state->cpu->cpu_val;
814 } else if (OPC_2 == 1) {
815 /* Cache type:
816 * 000 0110 1 000 101 110 0 10 000 101 110 0 10
817 * */
818 data = 0x0D172172;
819 }
820 break;
821 case MMU_CONTROL:
822 /*
823 * 6:3 read as 1
824 * 10 read as 0
825 * 18,16 read as 1
826 * */
827 data = (state->mmu.control | 0x50078) & 0xFFFFFBFF;
828 break;
829 case MMU_TRANSLATION_TABLE_BASE:
830#if 0
831 data = state->mmu.translation_table_base;
832#endif
833 switch (OPC_2) {
834 case 0:
835 data = state->mmu.translation_table_base0;
836 break;
837 case 1:
838 data = state->mmu.translation_table_base1;
839 break;
840 case 2:
841 data = state->mmu.translation_table_ctrl;
842 break;
843 default:
844 printf ("mmu_mrc read UNKNOWN - p15 c2 opcode2 %d\n", OPC_2);
845 break;
846 }
847 break;
848 case MMU_DOMAIN_ACCESS_CONTROL:
849 data = state->mmu.domain_access_control;
850 break;
851 case MMU_FAULT_STATUS:
852 /* OPC_2 = 0: data FSR value
853 * */
854 if (OPC_2 == 0)
855 data = state->mmu.fault_status;
856 if (OPC_2 == 1)
857 data = state->mmu.fault_statusi;
858 break;
859 case MMU_FAULT_ADDRESS:
860 data = state->mmu.fault_address;
861 break;
862 case MMU_PID:
863 //data = state->mmu.process_id;
864 if(OPC_2 == 0)
865 data = state->mmu.process_id;
866 else if(OPC_2 == 1)
867 data = state->mmu.context_id;
868 else if(OPC_2 == 3){
869 data = state->mmu.thread_uro_id;
870 }
871 else{
872 printf ("mmu_mcr read UNKNOWN - reg %d\n", creg);
873 }
874 //printf("SKYEYE In %s, read pid 0x%x, OPC_2 %d, instr=0x%x\n", __FUNCTION__, data, OPC_2, instr);
875 //exit(-1);
876 break;
877 default:
878 printf ("mmu_mrc read UNKNOWN - reg %d\n", creg);
879 data = 0;
880 break;
881 }
882/* printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]); */
883 *value = data;
884 return data;
885}
886
887
888static ARMword
889arm1176jzf_s_mmu_mcr (ARMul_State *state, ARMword instr, ARMword value)
890{
891 int creg = BITS (16, 19) & 0xf;
892 int CRm = BITS (0, 3) & 0xf;
893 int OPC_1 = BITS (21, 23) & 0x7;
894 int OPC_2 = BITS (5, 7) & 0x7;
895 if (!strncmp (state->cpu->cpu_arch_name, "armv6", 5)) {
896 switch (creg) {
897 case MMU_CONTROL:
898 /*
899 * 6:3 read as 1
900 * 10 read as 0
901 * 18,16 read as 1
902 * */
903 if(OPC_2 == 0)
904 state->mmu.control = (value | 0x50078) & 0xFFFFFBFF;
905 else if(OPC_2 == 1)
906 state->mmu.auxiliary_control = value;
907 else if(OPC_2 == 2)
908 state->mmu.coprocessor_access_control = value;
909 else
910 fprintf(stderr, "In %s, wrong OPC_2 %d\n", __FUNCTION__, OPC_2);
911 break;
912 case MMU_TRANSLATION_TABLE_BASE:
913 switch (OPC_2) {
914 /* int i; */
915 case 0:
916#if 0
917 /* TTBR0 */
918 if (state->mmu.translation_table_ctrl & 0x7) {
919 for (i = 0; i <= state->mmu.translation_table_ctrl; i++)
920 state->mmu.translation_table_base0 &= ~(1 << (5 + i));
921 }
922#endif
923 state->mmu.translation_table_base0 = (value);
924 break;
925 case 1:
926#if 0
927 /* TTBR1 */
928 if (state->mmu.translation_table_ctrl & 0x7) {
929 for (i = 0; i <= state->mmu.translation_table_ctrl; i++)
930 state->mmu.translation_table_base1 &= 1 << (5 + i);
931 }
932#endif
933 state->mmu.translation_table_base1 = (value);
934 break;
935 case 2:
936 /* TTBC */
937 state->mmu.translation_table_ctrl = value & 0x7;
938 break;
939 default:
940 printf ("mmu_mcr wrote UNKNOWN - cp15 c2 opcode2 %d\n", OPC_2);
941 break;
942 }
943 //printf("SKYEYE In %s, write TLB_BASE 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr);
944 //invalidate_all_tlb(state);
945 break;
946 case MMU_DOMAIN_ACCESS_CONTROL:
947 /* printf("mmu_mcr wrote DACR "); */
948 state->mmu.domain_access_control = value;
949 break;
950
951 case MMU_FAULT_STATUS:
952 if (OPC_2 == 0)
953 state->mmu.fault_status = value & 0xFF;
954 if (OPC_2 == 1) {
955 printf("set fault status instr\n");
956 }
957 break;
958 case MMU_FAULT_ADDRESS:
959 state->mmu.fault_address = value;
960 break;
961
962 case MMU_CACHE_OPS:
963 break;
964 case MMU_TLB_OPS:
965 {
966 switch(CRm){
967 case 5: /* ITLB */
968 {
969 switch(OPC_2){
970 case 0: /* invalidate all */
971 //invalidate_all_tlb(state);
972 break;
973 case 1: /* invalidate by MVA */
974 //invalidate_by_mva(state, value);
975 break;
976 case 2: /* invalidate by asid */
977 //invalidate_by_asid(state, value);
978 break;
979 default:
980 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
981 break;
982 }
983 break;
984 }
985 case 6: /* DTLB */
986 {
987 switch(OPC_2){
988 case 0: /* invalidate all */
989 //invalidate_all_tlb(state);
990 break;
991 case 1: /* invalidate by MVA */
992 //invalidate_by_mva(state, value);
993 break;
994 case 2: /* invalidate by asid */
995 //invalidate_by_asid(state, value);
996 break;
997 default:
998 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
999 break;
1000 }
1001 break;
1002 }
1003 case 7: /* Unified TLB */
1004 {
1005 switch(OPC_2){
1006 case 0: /* invalidate all */
1007 //invalidate_all_tlb(state);
1008 break;
1009 case 1: /* invalidate by MVA */
1010 //invalidate_by_mva(state, value);
1011 break;
1012 case 2: /* invalidate by asid */
1013 //invalidate_by_asid(state, value);
1014 break;
1015 default:
1016 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
1017 break;
1018 }
1019 break;
1020 }
1021
1022 default:
1023 printf ("mmu_mcr wrote UNKNOWN - reg %d, CRm=%d\n", creg, CRm);
1024 break;
1025 }
1026 //printf("SKYEYE In %s, write TLB 0x%x OPC_1=%d, OPC_2=%d , CRm=%d instr=0x%x\n", __FUNCTION__, value, OPC_1, OPC_2, CRm, instr);
1027 }
1028 break;
1029 case MMU_CACHE_LOCKDOWN:
1030 /*
1031 * FIXME: cache lock down*/
1032 break;
1033 case MMU_TLB_LOCKDOWN:
1034 printf("SKYEYE In %s, write TLB_LOCKDOWN 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr);
1035 /* FIXME:tlb lock down */
1036 break;
1037 case MMU_PID:
1038 //printf("SKYEYE In %s, write pid 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr);
1039 //state->mmu.process_id = value;
1040 /*0:24 should be zero. */
1041 //state->mmu.process_id = value & 0xfe000000;
1042 if(OPC_2 == 0)
1043 state->mmu.process_id = value;
1044 else if(OPC_2 == 1)
1045 state->mmu.context_id = value;
1046 else if(OPC_2 == 3){
1047 state->mmu.thread_uro_id = value;
1048 }
1049 else{
1050 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
1051 }
1052 break;
1053
1054 default:
1055 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
1056 break;
1057 }
1058 }
1059
1060 return No_exp;
1061}
1062
1063///* teawater add for arm2x86 2005.06.19------------------------------------------- */
1064//static int
1065//arm1176jzf_s_mmu_v2p_dbct (ARMul_State *state, ARMword virt_addr,
1066// ARMword *phys_addr)
1067//{
1068// fault_t fault;
1069// int ap, sop;
1070//
1071// ARMword perm; /* physical addr access permissions */
1072// virt_addr = mmu_pid_va_map (virt_addr);
1073// if (MMU_Enabled) {
1074//
1075// /*align check */
1076// if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
1077// DEBUG_LOG(ARM11, "align\n");
1078// return ALIGNMENT_FAULT;
1079// } else
1080// virt_addr &= ~(WORD_SIZE - 1);
1081//
1082// /*translate tlb */
1083// fault = mmu_translate (state, virt_addr, phys_addr, &ap, &sop);
1084// if (fault) {
1085// DEBUG_LOG(ARM11, "translate\n");
1086// return fault;
1087// }
1088//
1089// /* permission check */
1090// if (!check_perms(state, ap, 1)) {
1091// if (sop == 0) {
1092// return SECTION_PERMISSION_FAULT;
1093// } else {
1094// return SUBPAGE_PERMISSION_FAULT;
1095// }
1096// }
1097//#if 0
1098// /*check access */
1099// fault = check_access (state, virt_addr, tlb, 1);
1100// if (fault) {
1101// DEBUG_LOG(ARM11, "check_fault\n");
1102// return fault;
1103// }
1104//#endif
1105// }
1106//
1107// if (MMU_Disabled) {
1108// *phys_addr = virt_addr;
1109// }
1110//
1111// return 0;
1112//}
1113
1114/* AJ2D-------------------------------------------------------------------------- */
1115
1116/*arm1176jzf-s mmu_ops_t*/
1117mmu_ops_t arm1176jzf_s_mmu_ops = {
1118 arm1176jzf_s_mmu_init,
1119 arm1176jzf_s_mmu_exit,
1120 arm1176jzf_s_mmu_read_byte,
1121 arm1176jzf_s_mmu_write_byte,
1122 arm1176jzf_s_mmu_read_halfword,
1123 arm1176jzf_s_mmu_write_halfword,
1124 arm1176jzf_s_mmu_read_word,
1125 arm1176jzf_s_mmu_write_word,
1126 arm1176jzf_s_mmu_load_instr,
1127 arm1176jzf_s_mmu_mcr,
1128 arm1176jzf_s_mmu_mrc
1129/* teawater add for arm2x86 2005.06.19------------------------------------------- */
1130/* arm1176jzf_s_mmu_v2p_dbct, */
1131/* AJ2D-------------------------------------------------------------------------- */
1132};
diff --git a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h
new file mode 100644
index 000000000..299c6b46b
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h
@@ -0,0 +1,37 @@
1/*
2 arm1176JZF-S_mmu.h - ARM1176JZF-S Memory Management Unit emulation.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18
19#ifndef _ARM1176JZF_S_MMU_H_
20#define _ARM1176JZF_S_MMU_H_
21
22#if 0
23typedef struct arm1176jzf-s_mmu_s
24{
25 tlb_t i_tlb;
26 cache_t i_cache;
27
28 tlb_t d_tlb;
29 cache_t d_cache;
30 wb_t wb_t;
31} arm1176jzf-s_mmu_t;
32#endif
33extern mmu_ops_t arm1176jzf_s_mmu_ops;
34
35ARMword
36arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value);
37#endif /*_ARM1176JZF_S_MMU_H_*/
diff --git a/src/core/arm/interpreter/mmu/cache.h b/src/core/arm/interpreter/mmu/cache.h
new file mode 100644
index 000000000..d308d9b87
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/cache.h
@@ -0,0 +1,168 @@
1#ifndef _MMU_CACHE_H_
2#define _MMU_CACHE_H_
3
4typedef struct cache_line_t
5{
6 ARMword tag; /* cache line align address |
7 bit2: last half dirty
8 bit1: first half dirty
9 bit0: cache valid flag
10 */
11 ARMword pa; /*physical address */
12 ARMword *data; /*array of cached data */
13} cache_line_t;
14#define TAG_VALID_FLAG 0x00000001
15#define TAG_FIRST_HALF_DIRTY 0x00000002
16#define TAG_LAST_HALF_DIRTY 0x00000004
17
18/*cache set association*/
19typedef struct cache_set_s
20{
21 cache_line_t *lines;
22 int cycle;
23} cache_set_t;
24
25enum
26{
27 CACHE_WRITE_BACK,
28 CACHE_WRITE_THROUGH,
29};
30
31typedef struct cache_s
32{
33 int width; /*bytes in a line */
34 int way; /*way of set asscociate */
35 int set; /*num of set */
36 int w_mode; /*write back or write through */
37 //int a_mode; /*alloc mode: random or round-bin*/
38 cache_set_t *sets;
39 /**/} cache_s;
40
41typedef struct cache_desc_s
42{
43 int width;
44 int way;
45 int set;
46 int w_mode;
47// int a_mode;
48} cache_desc_t;
49
50
51/*virtual address to cache set index*/
52#define va_cache_set(va, cache_t) \
53 (((va) / (cache_t)->width) & ((cache_t)->set - 1))
54/*virtual address to cahce line aligned*/
55#define va_cache_align(va, cache_t) \
56 ((va) & ~((cache_t)->width - 1))
57/*virtaul address to cache line word index*/
58#define va_cache_index(va, cache_t) \
59 (((va) & ((cache_t)->width - 1)) >> WORD_SHT)
60
61/*see Page 558 in arm manual*/
62/*set/index format value to cache set value*/
63#define index_cache_set(index, cache_t) \
64 (((index) / (cache_t)->width) & ((cache_t)->set - 1))
65
66/*************************cache********************/
67/* mmu cache init
68 *
69 * @cache_t :cache_t to init
70 * @width :cache line width in byte
71 * @way :way of each cache set
72 * @set :cache set num
73 * @w_mode :cache w_mode
74 *
75 * $ -1: error
76 * 0: sucess
77 */
78int
79mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode);
80
81/* free a cache_t's inner data, the ptr self is not freed,
82 * when needed do like below:
83 * mmu_cache_exit(cache);
84 * free(cache_t);
85 *
86 * @cache_t : the cache_t to free
87 */
88void mmu_cache_exit (cache_s * cache_t);
89
90/* mmu cache search
91 *
92 * @state :ARMul_State
93 * @cache_t :cache_t to search
94 * @va :virtual address
95 *
96 * $ NULL: no cache match
97 * cache :cache matched
98 * */
99cache_line_t *mmu_cache_search (ARMul_State * state, cache_s * cache_t,
100 ARMword va);
101
102/* mmu cache search by set/index
103 *
104 * @state :ARMul_State
105 * @cache_t :cache_t to search
106 * @index :set/index value.
107 *
108 * $ NULL: no cache match
109 * cache :cache matched
110 * */
111
112cache_line_t *mmu_cache_search_by_index (ARMul_State * state,
113 cache_s * cache_t, ARMword index);
114
115/* mmu cache alloc
116 *
117 * @state :ARMul_State
118 * @cache_t :cache_t to alloc from
119 * @va :virtual address that require cache alloc, need not cache aligned
120 * @pa :physical address of va
121 *
122 * $ cache_alloced, always alloc OK
123 */
124cache_line_t *mmu_cache_alloc (ARMul_State * state, cache_s * cache_t,
125 ARMword va, ARMword pa);
126
127/* mmu_cache_write_back write cache data to memory
128 *
129 * @state:
130 * @cache_t :cache_t of the cache line
131 * @cache : cache line
132 */
133void
134mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
135 cache_line_t * cache);
136
137/* mmu_cache_clean: clean a cache of va in cache_t
138 *
139 * @state :ARMul_State
140 * @cache_t :cache_t to clean
141 * @va :virtaul address
142 */
143void mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va);
144void
145mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
146 ARMword index);
147
148/* mmu_cache_invalidate : invalidate a cache of va
149 *
150 * @state :ARMul_State
151 * @cache_t :cache_t to invalid
152 * @va :virt_addr to invalid
153 */
154void
155mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va);
156
157void
158mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
159 ARMword index);
160
161void mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t);
162
163void
164mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa);
165
166cache_line_t* mmu_cache_dirty_cache(ARMul_State * state, cache_s * cache_t);
167
168#endif /*_MMU_CACHE_H_*/
diff --git a/src/core/arm/interpreter/mmu/rb.h b/src/core/arm/interpreter/mmu/rb.h
new file mode 100644
index 000000000..7bf0ebb26
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/rb.h
@@ -0,0 +1,55 @@
1#ifndef _MMU_RB_H
2#define _MMU_RB_H
3
4enum rb_type_t
5{
6 RB_INVALID = 0, //invalid
7 RB_1, //1 word
8 RB_4, //4 word
9 RB_8, //8 word
10};
11
12/*bytes of each rb_type*/
13extern ARMword rb_masks[];
14
15#define RB_WORD_NUM 8
16typedef struct rb_entry_s
17{
18 ARMword data[RB_WORD_NUM]; //array to store data
19 ARMword va; //first word va
20 int type; //rb type
21 fault_t fault; //fault set by rb alloc
22} rb_entry_t;
23
24typedef struct rb_s
25{
26 int num;
27 rb_entry_t *entrys;
28} rb_s;
29
30/*mmu_rb_init
31 * @rb_t :rb_t to init
32 * @num :number of entry
33 * */
34int mmu_rb_init (rb_s * rb_t, int num);
35
36/*mmu_rb_exit*/
37void mmu_rb_exit (rb_s * rb_t);
38
39
40/*mmu_rb_search
41 * @rb_t :rb_t to serach
42 * @va :va address to math
43 *
44 * $ NULL :not match
45 * NO-NULL:
46 * */
47rb_entry_t *mmu_rb_search (rb_s * rb_t, ARMword va);
48
49
50void mmu_rb_invalidate_entry (rb_s * rb_t, int i);
51void mmu_rb_invalidate_all (rb_s * rb_t);
52void mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb,
53 int type, ARMword va);
54
55#endif /*_MMU_RB_H_*/
diff --git a/src/core/arm/interpreter/mmu/tlb.h b/src/core/arm/interpreter/mmu/tlb.h
new file mode 100644
index 000000000..938c01786
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/tlb.h
@@ -0,0 +1,94 @@
1#ifndef _MMU_TLB_H_
2#define _MMU_TLB_H_
3
4typedef enum tlb_mapping_t
5{
6 TLB_INVALID = 0,
7 TLB_SMALLPAGE = 1,
8 TLB_LARGEPAGE = 2,
9 TLB_SECTION = 3,
10 TLB_ESMALLPAGE = 4,
11 TLB_TINYPAGE = 5
12} tlb_mapping_t;
13
14extern ARMword tlb_masks[];
15
16/* Permissions bits in a TLB entry:
17 *
18 * 31 12 11 10 9 8 7 6 5 4 3 2 1 0
19 * +-------------+-----+-----+-----+-----+---+---+-------+
20 * Page:| | ap3 | ap2 | ap1 | ap0 | C | B | |
21 * +-------------+-----+-----+-----+-----+---+---+-------+
22 *
23 * 31 12 11 10 9 4 3 2 1 0
24 * +-------------+-----+-----------------+---+---+-------+
25 * Section: | | AP | | C | B | |
26 * +-------------+-----+-----------------+---+---+-------+
27 */
28
29/*
30section:
31 section base address [31:20]
32 AP - table 8-2, page 8-8
33 domain
34 C,B
35
36page:
37 page base address [31:16] or [31:12]
38 ap[3:0]
39 domain (from L1)
40 C,B
41*/
42
43
44typedef struct tlb_entry_t
45{
46 ARMword virt_addr;
47 ARMword phys_addr;
48 ARMword perms;
49 ARMword domain;
50 tlb_mapping_t mapping;
51} tlb_entry_t;
52
53typedef struct tlb_s
54{
55 int num; /*num of tlb entry */
56 int cycle; /*current tlb cycle */
57 tlb_entry_t *entrys;
58} tlb_s;
59
60
61#define tlb_c_flag(tlb) \
62 ((tlb)->perms & 0x8)
63#define tlb_b_flag(tlb) \
64 ((tlb)->perms & 0x4)
65
66#define tlb_va_to_pa(tlb, va) \
67(\
68 {\
69 ARMword mask = tlb_masks[tlb->mapping]; \
70 (tlb->phys_addr & mask) | (va & ~mask);\
71 }\
72)
73
74fault_t
75check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
76 int read);
77
78fault_t
79translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
80 tlb_entry_t ** tlb);
81
82int mmu_tlb_init (tlb_s * tlb_t, int num);
83
84void mmu_tlb_exit (tlb_s * tlb_t);
85
86void mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t);
87
88void
89mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr);
90
91tlb_entry_t *mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t,
92 ARMword virt_addr);
93
94#endif /*_MMU_TLB_H_*/
diff --git a/src/core/arm/interpreter/mmu/wb.h b/src/core/arm/interpreter/mmu/wb.h
new file mode 100644
index 000000000..8fb7de946
--- /dev/null
+++ b/src/core/arm/interpreter/mmu/wb.h
@@ -0,0 +1,63 @@
1#ifndef _MMU_WB_H_
2#define _MMU_WB_H_
3
4typedef struct wb_entry_s
5{
6 ARMword pa; //phy_addr
7 ARMbyte *data; //data
8 int nb; //number byte to write
9} wb_entry_t;
10
11typedef struct wb_s
12{
13 int num; //number of wb_entry
14 int nb; //number of byte of each entry
15 int first; //
16 int last; //
17 int used; //
18 wb_entry_t *entrys;
19} wb_s;
20
21typedef struct wb_desc_s
22{
23 int num;
24 int nb;
25} wb_desc_t;
26
27/* wb_init
28 * @wb_t :wb_t to init
29 * @num :num of entrys
30 * @nw :num of word of each entry
31 *
32 * $ -1:error
33 * 0:ok
34 * */
35int mmu_wb_init (wb_s * wb_t, int num, int nb);
36
37
38/* wb_exit
39 * @wb_t :wb_t to exit
40 * */
41void mmu_wb_exit (wb_s * wb);
42
43
44/* wb_write_bytes :put bytess in Write Buffer
45 * @state: ARMul_State
46 * @wb_t: write buffer
47 * @pa: physical address
48 * @data: data ptr
49 * @n number of byte to write
50 *
51 * Note: write buffer merge is not implemented, can be done late
52 * */
53void
54mmu_wb_write_bytess (ARMul_State * state, wb_s * wb_t, ARMword pa,
55 ARMbyte * data, int n);
56
57
58/* wb_drain_all
59 * @wb_t wb_t to drain
60 * */
61void mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t);
62
63#endif /*_MMU_WB_H_*/