Revision b769d8fe
b/exec-all.h | ||
---|---|---|
592 | 592 |
#endif |
593 | 593 |
if (__builtin_expect(env->tlb_read[is_user][index].address != |
594 | 594 |
(addr & TARGET_PAGE_MASK), 0)) { |
595 |
#if defined (TARGET_PPC) |
|
596 |
env->access_type = ACCESS_CODE; |
|
597 |
ldub_code((void *)addr); |
|
598 |
env->access_type = ACCESS_INT; |
|
599 |
#else |
|
600 | 595 |
ldub_code((void *)addr); |
601 |
#endif |
|
602 | 596 |
} |
603 | 597 |
return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base; |
604 | 598 |
} |
b/exec.c | ||
---|---|---|
2115 | 2115 |
#define MMUSUFFIX _cmmu |
2116 | 2116 |
#define GETPC() NULL |
2117 | 2117 |
#define env cpu_single_env |
2118 |
#define SOFTMMU_CODE_ACCESS |
|
2118 | 2119 |
|
2119 | 2120 |
#define SHIFT 0 |
2120 | 2121 |
#include "softmmu_template.h" |
b/softmmu_template.h | ||
---|---|---|
39 | 39 |
#error unsupported data size |
40 | 40 |
#endif |
41 | 41 |
|
42 |
#ifdef SOFTMMU_CODE_ACCESS |
|
43 |
#define READ_ACCESS_TYPE 2 |
|
44 |
#else |
|
45 |
#define READ_ACCESS_TYPE 0 |
|
46 |
#endif |
|
47 |
|
|
42 | 48 |
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(unsigned long addr, |
43 | 49 |
int is_user, |
44 | 50 |
void *retaddr); |
45 |
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(unsigned long addr, |
|
46 |
DATA_TYPE val, |
|
47 |
int is_user, |
|
48 |
void *retaddr); |
|
49 |
|
|
50 | 51 |
static inline DATA_TYPE glue(io_read, SUFFIX)(unsigned long physaddr, |
51 | 52 |
unsigned long tlb_addr) |
52 | 53 |
{ |
... | ... | |
68 | 69 |
return res; |
69 | 70 |
} |
70 | 71 |
|
71 |
static inline void glue(io_write, SUFFIX)(unsigned long physaddr, |
|
72 |
DATA_TYPE val, |
|
73 |
unsigned long tlb_addr, |
|
74 |
void *retaddr) |
|
75 |
{ |
|
76 |
int index; |
|
77 |
|
|
78 |
index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); |
|
79 |
env->mem_write_vaddr = tlb_addr; |
|
80 |
env->mem_write_pc = (unsigned long)retaddr; |
|
81 |
#if SHIFT <= 2 |
|
82 |
io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val); |
|
83 |
#else |
|
84 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
85 |
io_mem_write[index][2](io_mem_opaque[index], physaddr, val >> 32); |
|
86 |
io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val); |
|
87 |
#else |
|
88 |
io_mem_write[index][2](io_mem_opaque[index], physaddr, val); |
|
89 |
io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val >> 32); |
|
90 |
#endif |
|
91 |
#endif /* SHIFT > 2 */ |
|
92 |
} |
|
93 |
|
|
94 | 72 |
/* handle all cases except unaligned access which span two pages */ |
95 | 73 |
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(unsigned long addr, |
96 | 74 |
int is_user) |
... | ... | |
125 | 103 |
} else { |
126 | 104 |
/* the page is not in the TLB : fill it */ |
127 | 105 |
retaddr = GETPC(); |
128 |
tlb_fill(addr, 0, is_user, retaddr);
|
|
106 |
tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr);
|
|
129 | 107 |
goto redo; |
130 | 108 |
} |
131 | 109 |
return res; |
... | ... | |
172 | 150 |
} |
173 | 151 |
} else { |
174 | 152 |
/* the page is not in the TLB : fill it */ |
175 |
tlb_fill(addr, 0, is_user, retaddr);
|
|
153 |
tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr);
|
|
176 | 154 |
goto redo; |
177 | 155 |
} |
178 | 156 |
return res; |
179 | 157 |
} |
180 | 158 |
|
159 |
#ifndef SOFTMMU_CODE_ACCESS |
|
160 |
|
|
161 |
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(unsigned long addr, |
|
162 |
DATA_TYPE val, |
|
163 |
int is_user, |
|
164 |
void *retaddr); |
|
165 |
|
|
166 |
static inline void glue(io_write, SUFFIX)(unsigned long physaddr, |
|
167 |
DATA_TYPE val, |
|
168 |
unsigned long tlb_addr, |
|
169 |
void *retaddr) |
|
170 |
{ |
|
171 |
int index; |
|
172 |
|
|
173 |
index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); |
|
174 |
env->mem_write_vaddr = tlb_addr; |
|
175 |
env->mem_write_pc = (unsigned long)retaddr; |
|
176 |
#if SHIFT <= 2 |
|
177 |
io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val); |
|
178 |
#else |
|
179 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
180 |
io_mem_write[index][2](io_mem_opaque[index], physaddr, val >> 32); |
|
181 |
io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val); |
|
182 |
#else |
|
183 |
io_mem_write[index][2](io_mem_opaque[index], physaddr, val); |
|
184 |
io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val >> 32); |
|
185 |
#endif |
|
186 |
#endif /* SHIFT > 2 */ |
|
187 |
} |
|
181 | 188 |
|
182 | 189 |
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(unsigned long addr, |
183 | 190 |
DATA_TYPE val, |
... | ... | |
257 | 264 |
} |
258 | 265 |
} |
259 | 266 |
|
267 |
#endif /* !defined(SOFTMMU_CODE_ACCESS) */ |
|
268 |
|
|
269 |
#undef READ_ACCESS_TYPE |
|
260 | 270 |
#undef SHIFT |
261 | 271 |
#undef DATA_TYPE |
262 | 272 |
#undef SUFFIX |
b/target-i386/helper2.c | ||
---|---|---|
331 | 331 |
printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", |
332 | 332 |
addr, is_write, is_user, env->eip); |
333 | 333 |
#endif |
334 |
|
|
334 |
is_write &= 1; |
|
335 |
|
|
335 | 336 |
if (env->user_mode_only) { |
336 | 337 |
/* user mode only emulation */ |
337 | 338 |
error_code = 0; |
b/target-ppc/helper.c | ||
---|---|---|
432 | 432 |
generated code */ |
433 | 433 |
saved_env = env; |
434 | 434 |
env = cpu_single_env; |
435 |
#if 0 |
|
435 | 436 |
{ |
436 | 437 |
unsigned long tlb_addrr, tlb_addrw; |
437 | 438 |
int index; |
438 | 439 |
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
439 | 440 |
tlb_addrr = env->tlb_read[is_user][index].address; |
440 | 441 |
tlb_addrw = env->tlb_write[is_user][index].address; |
441 |
#if 0 |
|
442 | 442 |
if (loglevel) { |
443 | 443 |
fprintf(logfile, |
444 | 444 |
"%s 1 %p %p idx=%d addr=0x%08lx tbl_addr=0x%08lx 0x%08lx " |
... | ... | |
447 | 447 |
tlb_addrr, tlb_addrw, addr & TARGET_PAGE_MASK, |
448 | 448 |
tlb_addrr & (TARGET_PAGE_MASK | TLB_INVALID_MASK)); |
449 | 449 |
} |
450 |
#endif |
|
451 | 450 |
} |
451 |
#endif |
|
452 | 452 |
ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1); |
453 | 453 |
if (ret) { |
454 | 454 |
if (retaddr) { |
... | ... | |
463 | 463 |
} |
464 | 464 |
do_raise_exception_err(env->exception_index, env->error_code); |
465 | 465 |
} |
466 |
#if 0 |
|
466 | 467 |
{ |
467 | 468 |
unsigned long tlb_addrr, tlb_addrw; |
468 | 469 |
int index; |
469 | 470 |
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
470 | 471 |
tlb_addrr = env->tlb_read[is_user][index].address; |
471 | 472 |
tlb_addrw = env->tlb_write[is_user][index].address; |
472 |
#if 0 |
|
473 | 473 |
printf("%s 2 %p %p idx=%d addr=0x%08lx tbl_addr=0x%08lx 0x%08lx " |
474 | 474 |
"(0x%08lx 0x%08lx)\n", __func__, env, |
475 | 475 |
&env->tlb_read[is_user][index], index, addr, |
476 | 476 |
tlb_addrr, tlb_addrw, addr & TARGET_PAGE_MASK, |
477 | 477 |
tlb_addrr & (TARGET_PAGE_MASK | TLB_INVALID_MASK)); |
478 |
#endif |
|
479 | 478 |
} |
479 |
#endif |
|
480 | 480 |
env = saved_env; |
481 | 481 |
} |
482 | 482 |
|
... | ... | |
496 | 496 |
int access_type; |
497 | 497 |
int ret = 0; |
498 | 498 |
|
499 |
// printf("%s 0\n", __func__); |
|
500 |
access_type = env->access_type; |
|
499 |
if (rw == 2) { |
|
500 |
/* code access */ |
|
501 |
rw = 0; |
|
502 |
access_type = ACCESS_CODE; |
|
503 |
} else { |
|
504 |
/* data access */ |
|
505 |
/* XXX: put correct access by using cpu_restore_state() |
|
506 |
correctly */ |
|
507 |
access_type = ACCESS_INT; |
|
508 |
// access_type = env->access_type; |
|
509 |
} |
|
501 | 510 |
if (env->user_mode_only) { |
502 | 511 |
/* user mode only emulation */ |
503 | 512 |
ret = -2; |
504 | 513 |
goto do_fault; |
505 | 514 |
} |
506 |
/* NASTY BUG workaround */ |
|
507 |
if (access_type == ACCESS_CODE && rw) { |
|
508 |
printf("%s: ERROR WRITE CODE ACCESS\n", __func__); |
|
509 |
access_type = ACCESS_INT; |
|
510 |
} |
|
511 | 515 |
ret = get_physical_address(env, &physical, &prot, |
512 | 516 |
address, rw, access_type); |
513 | 517 |
if (ret == 0) { |
... | ... | |
590 | 594 |
env->error_code = error_code; |
591 | 595 |
ret = 1; |
592 | 596 |
} |
593 |
|
|
594 | 597 |
return ret; |
595 | 598 |
} |
596 | 599 |
|
... | ... | |
671 | 674 |
if (loglevel > 0) { |
672 | 675 |
fprintf(logfile, "Raise exception at 0x%08x => 0x%08x (%02x)\n", |
673 | 676 |
env->nip, excp << 8, env->error_code); |
674 |
} |
|
677 |
}
|
|
675 | 678 |
if (loglevel > 0) |
676 | 679 |
cpu_ppc_dump_state(env, logfile, 0); |
677 | 680 |
} |
678 | 681 |
#endif |
682 |
if (loglevel & CPU_LOG_INT) { |
|
683 |
fprintf(logfile, "Raise exception at 0x%08x => 0x%08x (%02x)\n", |
|
684 |
env->nip, excp << 8, env->error_code); |
|
685 |
} |
|
679 | 686 |
/* Generate informations in save/restore registers */ |
680 | 687 |
switch (excp) { |
681 | 688 |
case EXCP_OFCALL: |
... | ... | |
824 | 831 |
} |
825 | 832 |
goto store_next; |
826 | 833 |
case EXCP_SYSCALL: |
827 |
#if defined (DEBUG_EXCEPTIONS) |
|
828 |
if (msr_pr) { |
|
829 |
if (loglevel) { |
|
830 |
fprintf(logfile, "syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", |
|
831 |
env->gpr[0], env->gpr[3], env->gpr[4], |
|
832 |
env->gpr[5], env->gpr[6]); |
|
833 |
} else { |
|
834 |
printf("syscall %d from 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", |
|
835 |
env->gpr[0], env->nip, env->gpr[3], env->gpr[4], |
|
836 |
env->gpr[5], env->gpr[6]); |
|
837 |
} |
|
838 |
} |
|
839 |
#endif |
|
834 |
if (loglevel & CPU_LOG_INT) { |
|
835 |
fprintf(logfile, "syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", |
|
836 |
env->gpr[0], env->gpr[3], env->gpr[4], |
|
837 |
env->gpr[5], env->gpr[6]); |
|
838 |
if (env->gpr[0] == 4 && env->gpr[3] == 1) { |
|
839 |
int len, addr, i; |
|
840 |
uint8_t c; |
|
841 |
|
|
842 |
fprintf(logfile, "write: "); |
|
843 |
addr = env->gpr[4]; |
|
844 |
len = env->gpr[5]; |
|
845 |
if (len > 64) |
|
846 |
len = 64; |
|
847 |
for(i = 0; i < len; i++) { |
|
848 |
c = 0; |
|
849 |
cpu_memory_rw_debug(env, addr + i, &c, 1, 0); |
|
850 |
if (c < 32 || c > 126) |
|
851 |
c = '.'; |
|
852 |
fprintf(logfile, "%c", c); |
|
853 |
} |
|
854 |
fprintf(logfile, "\n"); |
|
855 |
} |
|
856 |
} |
|
840 | 857 |
goto store_next; |
841 | 858 |
case EXCP_TRACE: |
842 | 859 |
goto store_next; |
b/target-ppc/translate.c | ||
---|---|---|
3002 | 3002 |
#else |
3003 | 3003 |
env->nip = 0xFFFFFFFC; |
3004 | 3004 |
#endif |
3005 |
env->access_type = ACCESS_INT; |
|
3006 | 3005 |
cpu_single_env = env; |
3007 | 3006 |
return env; |
3008 | 3007 |
} |
... | ... | |
3050 | 3049 |
/* Single step trace mode */ |
3051 | 3050 |
msr_se = 1; |
3052 | 3051 |
#endif |
3053 |
env->access_type = ACCESS_CODE; |
|
3054 | 3052 |
/* Set env in case of segfault during code fetch */ |
3055 | 3053 |
while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) { |
3056 | 3054 |
if (search_pc) { |
3057 |
if (loglevel > 0) |
|
3058 |
fprintf(logfile, "Search PC...\n"); |
|
3059 | 3055 |
j = gen_opc_ptr - gen_opc_buf; |
3060 | 3056 |
if (lj < j) { |
3061 | 3057 |
lj++; |
... | ... | |
3187 | 3183 |
fprintf(logfile, "\n"); |
3188 | 3184 |
} |
3189 | 3185 |
#endif |
3190 |
env->access_type = ACCESS_INT; |
|
3191 |
|
|
3192 | 3186 |
return 0; |
3193 | 3187 |
} |
3194 | 3188 |
|
b/target-sparc/cpu.h | ||
---|---|---|
86 | 86 |
#define PG_MODIFIED_MASK (1 << PG_MODIFIED_BIT) |
87 | 87 |
#define PG_CACHE_MASK (1 << PG_CACHE_BIT) |
88 | 88 |
|
89 |
#define ACCESS_DATA 0 |
|
90 |
#define ACCESS_CODE 1 |
|
91 |
#define ACCESS_MMU 2 |
|
92 |
|
|
93 | 89 |
#define NWINDOWS 32 |
94 | 90 |
|
95 | 91 |
typedef struct CPUSPARCState { |
... | ... | |
131 | 127 |
CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; |
132 | 128 |
CPUTLBEntry tlb_write[2][CPU_TLB_SIZE]; |
133 | 129 |
int error_code; |
134 |
int access_type; |
|
135 | 130 |
/* MMU regs */ |
136 | 131 |
uint32_t mmuregs[16]; |
137 | 132 |
/* temporary float registers */ |
b/target-sparc/helper.c | ||
---|---|---|
132 | 132 |
int is_user, int is_softmmu) |
133 | 133 |
{ |
134 | 134 |
int exception = 0; |
135 |
int access_type, access_perms = 0, access_index = 0;
|
|
135 |
int access_perms = 0, access_index = 0; |
|
136 | 136 |
uint8_t *pde_ptr; |
137 | 137 |
uint32_t pde, virt_addr; |
138 | 138 |
int error_code = 0, is_dirty, prot, ret = 0; |
139 | 139 |
unsigned long paddr, vaddr, page_offset; |
140 | 140 |
|
141 |
access_type = env->access_type; |
|
142 | 141 |
if (env->user_mode_only) { |
143 | 142 |
/* user mode only emulation */ |
144 | 143 |
ret = -2; |
... | ... | |
156 | 155 |
/* SPARC reference MMU table walk: Context table->L1->L2->PTE */ |
157 | 156 |
/* Context base + context number */ |
158 | 157 |
pde_ptr = phys_ram_base + (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4); |
159 |
env->access_type = ACCESS_MMU; |
|
160 | 158 |
pde = ldl_raw(pde_ptr); |
161 | 159 |
|
162 | 160 |
/* Ctx pde */ |
... | ... | |
219 | 217 |
} |
220 | 218 |
|
221 | 219 |
/* update page modified and dirty bits */ |
222 |
is_dirty = rw && !(pde & PG_MODIFIED_MASK);
|
|
220 |
is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
|
|
223 | 221 |
if (!(pde & PG_ACCESSED_MASK) || is_dirty) { |
224 | 222 |
pde |= PG_ACCESSED_MASK; |
225 | 223 |
if (is_dirty) |
... | ... | |
228 | 226 |
} |
229 | 227 |
|
230 | 228 |
/* check access */ |
231 |
access_index = (rw << 2) | ((access_type == ACCESS_CODE)? 2 : 0) | (is_user? 0 : 1);
|
|
229 |
access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
|
|
232 | 230 |
access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT; |
233 | 231 |
error_code = access_table[access_index][access_perms]; |
234 | 232 |
if (error_code) |
... | ... | |
249 | 247 |
paddr = ((pde & PTE_ADDR_MASK) << 4) + page_offset; |
250 | 248 |
|
251 | 249 |
do_mapping: |
252 |
env->access_type = access_type; |
|
253 | 250 |
vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1)); |
254 | 251 |
|
255 | 252 |
ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); |
256 | 253 |
return ret; |
257 | 254 |
|
258 | 255 |
do_fault: |
259 |
env->access_type = access_type; |
|
260 | 256 |
if (env->mmuregs[3]) /* Fault status register */ |
261 | 257 |
env->mmuregs[3] = 1; /* overflow (not read before another fault) */ |
262 | 258 |
env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2; |
b/target-sparc/translate.c | ||
---|---|---|
1278 | 1278 |
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
1279 | 1279 |
gen_opparam_ptr = gen_opparam_buf; |
1280 | 1280 |
|
1281 |
env->access_type = ACCESS_CODE; |
|
1282 |
|
|
1283 | 1281 |
do { |
1284 | 1282 |
if (env->nb_breakpoints > 0) { |
1285 | 1283 |
for(j = 0; j < env->nb_breakpoints; j++) { |
... | ... | |
1352 | 1350 |
} |
1353 | 1351 |
} |
1354 | 1352 |
#endif |
1355 |
|
|
1356 |
env->access_type = ACCESS_DATA; |
|
1357 | 1353 |
return 0; |
1358 | 1354 |
} |
1359 | 1355 |
|
... | ... | |
1379 | 1375 |
env->cwp = 0; |
1380 | 1376 |
env->wim = 1; |
1381 | 1377 |
env->regwptr = env->regbase + (env->cwp * 16); |
1382 |
env->access_type = ACCESS_DATA; |
|
1383 | 1378 |
#if defined(CONFIG_USER_ONLY) |
1384 | 1379 |
env->user_mode_only = 1; |
1385 | 1380 |
#else |
Also available in: Unified diff