| 137 |
return 0; |
return 0; |
| 138 |
} |
} |
| 139 |
|
|
| 140 |
|
*access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1); |
| 141 |
|
|
| 142 |
/* SPARC reference MMU table walk: Context table->L1->L2->PTE */ |
/* SPARC reference MMU table walk: Context table->L1->L2->PTE */ |
| 143 |
/* Context base + context number */ |
/* Context base + context number */ |
| 144 |
pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4); |
pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4); |
| 148 |
switch (pde & PTE_ENTRYTYPE_MASK) { |
switch (pde & PTE_ENTRYTYPE_MASK) { |
| 149 |
default: |
default: |
| 150 |
case 0: /* Invalid */ |
case 0: /* Invalid */ |
| 151 |
return 1; |
return 1 << 2; |
| 152 |
case 2: /* L0 PTE, maybe should not happen? */ |
case 2: /* L0 PTE, maybe should not happen? */ |
| 153 |
case 3: /* Reserved */ |
case 3: /* Reserved */ |
| 154 |
return 4; |
return 4 << 2; |
| 155 |
case 1: /* L0 PDE */ |
case 1: /* L0 PDE */ |
| 156 |
pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4); |
pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4); |
| 157 |
pde = ldl_phys(pde_ptr); |
pde = ldl_phys(pde_ptr); |
| 159 |
switch (pde & PTE_ENTRYTYPE_MASK) { |
switch (pde & PTE_ENTRYTYPE_MASK) { |
| 160 |
default: |
default: |
| 161 |
case 0: /* Invalid */ |
case 0: /* Invalid */ |
| 162 |
return 1; |
return (1 << 8) | (1 << 2); |
| 163 |
case 3: /* Reserved */ |
case 3: /* Reserved */ |
| 164 |
return 4; |
return (1 << 8) | (4 << 2); |
| 165 |
case 1: /* L1 PDE */ |
case 1: /* L1 PDE */ |
| 166 |
pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4); |
pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4); |
| 167 |
pde = ldl_phys(pde_ptr); |
pde = ldl_phys(pde_ptr); |
| 169 |
switch (pde & PTE_ENTRYTYPE_MASK) { |
switch (pde & PTE_ENTRYTYPE_MASK) { |
| 170 |
default: |
default: |
| 171 |
case 0: /* Invalid */ |
case 0: /* Invalid */ |
| 172 |
return 1; |
return (2 << 8) | (1 << 2); |
| 173 |
case 3: /* Reserved */ |
case 3: /* Reserved */ |
| 174 |
return 4; |
return (2 << 8) | (4 << 2); |
| 175 |
case 1: /* L2 PDE */ |
case 1: /* L2 PDE */ |
| 176 |
pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4); |
pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4); |
| 177 |
pde = ldl_phys(pde_ptr); |
pde = ldl_phys(pde_ptr); |
| 179 |
switch (pde & PTE_ENTRYTYPE_MASK) { |
switch (pde & PTE_ENTRYTYPE_MASK) { |
| 180 |
default: |
default: |
| 181 |
case 0: /* Invalid */ |
case 0: /* Invalid */ |
| 182 |
return 1; |
return (3 << 8) | (1 << 2); |
| 183 |
case 1: /* PDE, should not happen */ |
case 1: /* PDE, should not happen */ |
| 184 |
case 3: /* Reserved */ |
case 3: /* Reserved */ |
| 185 |
return 4; |
return (3 << 8) | (4 << 2); |
| 186 |
case 2: /* L3 PTE */ |
case 2: /* L3 PTE */ |
| 187 |
virt_addr = address & TARGET_PAGE_MASK; |
virt_addr = address & TARGET_PAGE_MASK; |
| 188 |
page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1); |
page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1); |
| 208 |
stl_phys_notdirty(pde_ptr, pde); |
stl_phys_notdirty(pde_ptr, pde); |
| 209 |
} |
} |
| 210 |
/* check access */ |
/* check access */ |
|
*access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1); |
|
| 211 |
access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT; |
access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT; |
| 212 |
error_code = access_table[*access_index][access_perms]; |
error_code = access_table[*access_index][access_perms]; |
| 213 |
if (error_code) |
if (error_code) |
| 247 |
|
|
| 248 |
if (env->mmuregs[3]) /* Fault status register */ |
if (env->mmuregs[3]) /* Fault status register */ |
| 249 |
env->mmuregs[3] = 1; /* overflow (not read before another fault) */ |
env->mmuregs[3] = 1; /* overflow (not read before another fault) */ |
| 250 |
env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2; |
env->mmuregs[3] |= (access_index << 5) | error_code | 2; |
| 251 |
env->mmuregs[4] = address; /* Fault address register */ |
env->mmuregs[4] = address; /* Fault address register */ |
| 252 |
|
|
| 253 |
if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) { |
if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) { |
| 254 |
|
#if 0 |
| 255 |
// No fault |
// No fault |
| 256 |
cpu_abort(env, "Unsupported MMU no fault case"); |
vaddr = address & TARGET_PAGE_MASK; |
| 257 |
|
paddr = 0xfffff000; |
| 258 |
|
prot = PAGE_READ | PAGE_WRITE; |
| 259 |
|
ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); |
| 260 |
|
return ret; |
| 261 |
|
#else |
| 262 |
|
cpu_abort(env, "MMU no fault case no handled"); |
| 263 |
|
return 0; |
| 264 |
|
#endif |
| 265 |
|
} else { |
| 266 |
|
if (rw & 2) |
| 267 |
|
env->exception_index = TT_TFAULT; |
| 268 |
|
else |
| 269 |
|
env->exception_index = TT_DFAULT; |
| 270 |
|
return 1; |
| 271 |
} |
} |
|
if (rw & 2) |
|
|
env->exception_index = TT_TFAULT; |
|
|
else |
|
|
env->exception_index = TT_DFAULT; |
|
|
return 1; |
|
| 272 |
} |
} |
| 273 |
#endif |
#endif |
| 274 |
|
|