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 |
|
|