| 75 |
{ 2, 2, 2, 0, 2, 2, 2, 0 } |
{ 2, 2, 2, 0, 2, 2, 2, 0 } |
| 76 |
}; |
}; |
| 77 |
|
|
| 78 |
/* 1 = write OK */ |
static const int perm_table[2][8] = { |
| 79 |
static const int rw_table[2][8] = { |
{ |
| 80 |
{ 0, 1, 0, 1, 0, 1, 0, 1 }, |
PAGE_READ, |
| 81 |
{ 0, 1, 0, 1, 0, 0, 0, 0 } |
PAGE_READ | PAGE_WRITE, |
| 82 |
|
PAGE_READ | PAGE_EXEC, |
| 83 |
|
PAGE_READ | PAGE_WRITE | PAGE_EXEC, |
| 84 |
|
PAGE_EXEC, |
| 85 |
|
PAGE_READ | PAGE_WRITE, |
| 86 |
|
PAGE_READ | PAGE_EXEC, |
| 87 |
|
PAGE_READ | PAGE_WRITE | PAGE_EXEC |
| 88 |
|
}, |
| 89 |
|
{ |
| 90 |
|
PAGE_READ, |
| 91 |
|
PAGE_READ | PAGE_WRITE, |
| 92 |
|
PAGE_READ | PAGE_EXEC, |
| 93 |
|
PAGE_READ | PAGE_WRITE | PAGE_EXEC, |
| 94 |
|
PAGE_EXEC, |
| 95 |
|
PAGE_READ, |
| 96 |
|
0, |
| 97 |
|
0, |
| 98 |
|
} |
| 99 |
}; |
}; |
| 100 |
|
|
| 101 |
int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot, |
int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot, |
| 112 |
virt_addr = address & TARGET_PAGE_MASK; |
virt_addr = address & TARGET_PAGE_MASK; |
| 113 |
if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */ |
if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */ |
| 114 |
*physical = address; |
*physical = address; |
| 115 |
*prot = PAGE_READ | PAGE_WRITE; |
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
| 116 |
return 0; |
return 0; |
| 117 |
} |
} |
| 118 |
|
|
| 194 |
return error_code; |
return error_code; |
| 195 |
|
|
| 196 |
/* the page can be put in the TLB */ |
/* the page can be put in the TLB */ |
| 197 |
*prot = PAGE_READ; |
*prot = perm_table[is_user][access_perms]; |
| 198 |
if (pde & PG_MODIFIED_MASK) { |
if (!(pde & PG_MODIFIED_MASK)) { |
| 199 |
/* only set write access if already dirty... otherwise wait |
/* only set write access if already dirty... otherwise wait |
| 200 |
for dirty access */ |
for dirty access */ |
| 201 |
if (rw_table[is_user][access_perms]) |
*prot &= ~PAGE_WRITE; |
|
*prot |= PAGE_WRITE; |
|
| 202 |
} |
} |
| 203 |
|
|
| 204 |
/* Even if large ptes, we map only one 4KB page in the cache to |
/* Even if large ptes, we map only one 4KB page in the cache to |
| 222 |
#ifdef DEBUG_MMU |
#ifdef DEBUG_MMU |
| 223 |
printf("Translate at 0x%lx -> 0x%lx, vaddr 0x%lx\n", (long)address, (long)paddr, (long)vaddr); |
printf("Translate at 0x%lx -> 0x%lx, vaddr 0x%lx\n", (long)address, (long)paddr, (long)vaddr); |
| 224 |
#endif |
#endif |
| 225 |
ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); |
ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); |
| 226 |
return ret; |
return ret; |
| 227 |
} |
} |
| 228 |
|
|
| 237 |
// neverland. Fake/overridden mappings will be flushed when |
// neverland. Fake/overridden mappings will be flushed when |
| 238 |
// switching to normal mode. |
// switching to normal mode. |
| 239 |
vaddr = address & TARGET_PAGE_MASK; |
vaddr = address & TARGET_PAGE_MASK; |
| 240 |
prot = PAGE_READ | PAGE_WRITE; |
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
| 241 |
ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); |
ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); |
| 242 |
return ret; |
return ret; |
| 243 |
} else { |
} else { |
| 244 |
if (rw & 2) |
if (rw & 2) |
| 421 |
|
|
| 422 |
if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */ |
if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */ |
| 423 |
*physical = address; |
*physical = address; |
| 424 |
*prot = PAGE_READ; |
*prot = PAGE_EXEC; |
| 425 |
return 0; |
return 0; |
| 426 |
} |
} |
| 427 |
|
|
| 457 |
return 1; |
return 1; |
| 458 |
} |
} |
| 459 |
*physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL); |
*physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL); |
| 460 |
*prot = PAGE_READ; |
*prot = PAGE_EXEC; |
| 461 |
return 0; |
return 0; |
| 462 |
} |
} |
| 463 |
} |
} |
| 493 |
#ifdef DEBUG_MMU |
#ifdef DEBUG_MMU |
| 494 |
printf("Translate at 0x%llx -> 0x%llx, vaddr 0x%llx\n", address, paddr, vaddr); |
printf("Translate at 0x%llx -> 0x%llx, vaddr 0x%llx\n", address, paddr, vaddr); |
| 495 |
#endif |
#endif |
| 496 |
ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); |
ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); |
| 497 |
return ret; |
return ret; |
| 498 |
} |
} |
| 499 |
// XXX |
// XXX |