43 |
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw, |
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw, |
44 |
int is_user, int is_softmmu) |
int is_user, int is_softmmu) |
45 |
{ |
{ |
|
env->mmuregs[4] = address; |
|
46 |
if (rw & 2) |
if (rw & 2) |
47 |
env->exception_index = TT_TFAULT; |
env->exception_index = TT_TFAULT; |
48 |
else |
else |
101 |
env = saved_env; |
env = saved_env; |
102 |
} |
} |
103 |
|
|
104 |
|
#ifndef TARGET_SPARC64 |
105 |
static const int access_table[8][8] = { |
static const int access_table[8][8] = { |
106 |
{ 0, 0, 0, 0, 2, 0, 3, 3 }, |
{ 0, 0, 0, 0, 2, 0, 3, 3 }, |
107 |
{ 0, 0, 0, 0, 2, 0, 0, 0 }, |
{ 0, 0, 0, 0, 2, 0, 0, 0 }, |
268 |
return 1; |
return 1; |
269 |
} |
} |
270 |
} |
} |
271 |
|
#else |
272 |
|
static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot, |
273 |
|
int *access_index, target_ulong address, int rw, |
274 |
|
int is_user) |
275 |
|
{ |
276 |
|
target_ulong mask; |
277 |
|
unsigned int i; |
278 |
|
|
279 |
|
if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */ |
280 |
|
*physical = address & 0xffffffff; |
281 |
|
*prot = PAGE_READ | PAGE_WRITE; |
282 |
|
return 0; |
283 |
|
} |
284 |
|
|
285 |
|
for (i = 0; i < 64; i++) { |
286 |
|
if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) { |
287 |
|
switch (env->dtlb_tte[i] >> 60) { |
288 |
|
default: |
289 |
|
case 0x4: // 8k |
290 |
|
mask = 0xffffffffffffe000ULL; |
291 |
|
break; |
292 |
|
case 0x5: // 64k |
293 |
|
mask = 0xffffffffffff0000ULL; |
294 |
|
break; |
295 |
|
case 0x6: // 512k |
296 |
|
mask = 0xfffffffffff80000ULL; |
297 |
|
break; |
298 |
|
case 0x7: // 4M |
299 |
|
mask = 0xffffffffffc00000ULL; |
300 |
|
break; |
301 |
|
} |
302 |
|
// ctx match, vaddr match? |
303 |
|
if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) && |
304 |
|
(address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) { |
305 |
|
// access ok? |
306 |
|
if (((env->dtlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) || |
307 |
|
(!(env->dtlb_tte[i] & 0x2) && (rw == 1))) { |
308 |
|
env->exception_index = TT_DFAULT; |
309 |
|
return 1; |
310 |
|
} |
311 |
|
*physical = env->dtlb_tte[i] & 0xffffe000; |
312 |
|
*prot = PAGE_READ; |
313 |
|
if (env->dtlb_tte[i] & 0x2) |
314 |
|
*prot |= PAGE_WRITE; |
315 |
|
return 0; |
316 |
|
} |
317 |
|
} |
318 |
|
} |
319 |
|
env->exception_index = TT_DFAULT; |
320 |
|
return 1; |
321 |
|
} |
322 |
|
|
323 |
|
static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot, |
324 |
|
int *access_index, target_ulong address, int rw, |
325 |
|
int is_user) |
326 |
|
{ |
327 |
|
target_ulong mask; |
328 |
|
unsigned int i; |
329 |
|
|
330 |
|
if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */ |
331 |
|
*physical = address & 0xffffffff; |
332 |
|
*prot = PAGE_READ; |
333 |
|
return 0; |
334 |
|
} |
335 |
|
for (i = 0; i < 64; i++) { |
336 |
|
if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) { |
337 |
|
switch (env->itlb_tte[i] >> 60) { |
338 |
|
default: |
339 |
|
case 0x4: // 8k |
340 |
|
mask = 0xffffffffffffe000ULL; |
341 |
|
break; |
342 |
|
case 0x5: // 64k |
343 |
|
mask = 0xffffffffffff0000ULL; |
344 |
|
break; |
345 |
|
case 0x6: // 512k |
346 |
|
mask = 0xfffffffffff80000ULL; |
347 |
|
break; |
348 |
|
case 0x7: // 4M |
349 |
|
mask = 0xffffffffffc00000ULL; |
350 |
|
break; |
351 |
|
} |
352 |
|
// ctx match, vaddr match? |
353 |
|
if (env->immuregs[1] == (env->itlb_tag[i] & 0x1fff) && |
354 |
|
(address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) { |
355 |
|
// access ok? |
356 |
|
if ((env->itlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) { |
357 |
|
env->exception_index = TT_TFAULT; |
358 |
|
return 1; |
359 |
|
} |
360 |
|
*physical = env->itlb_tte[i] & 0xffffe000; |
361 |
|
*prot = PAGE_READ; |
362 |
|
return 0; |
363 |
|
} |
364 |
|
} |
365 |
|
} |
366 |
|
env->exception_index = TT_TFAULT; |
367 |
|
return 1; |
368 |
|
} |
369 |
|
|
370 |
|
int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot, |
371 |
|
int *access_index, target_ulong address, int rw, |
372 |
|
int is_user) |
373 |
|
{ |
374 |
|
if (rw == 2) |
375 |
|
return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user); |
376 |
|
else |
377 |
|
return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user); |
378 |
|
} |
379 |
|
|
380 |
|
/* Perform address translation */ |
381 |
|
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
382 |
|
int is_user, int is_softmmu) |
383 |
|
{ |
384 |
|
target_ulong virt_addr; |
385 |
|
target_phys_addr_t paddr; |
386 |
|
unsigned long vaddr; |
387 |
|
int error_code = 0, prot, ret = 0, access_index; |
388 |
|
|
389 |
|
error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user); |
390 |
|
if (error_code == 0) { |
391 |
|
virt_addr = address & TARGET_PAGE_MASK; |
392 |
|
vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1)); |
393 |
|
ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); |
394 |
|
return ret; |
395 |
|
} |
396 |
|
// XXX |
397 |
|
return 1; |
398 |
|
} |
399 |
|
|
400 |
|
#endif |
401 |
#endif |
#endif |
402 |
|
|
403 |
void memcpy32(target_ulong *dst, const target_ulong *src) |
void memcpy32(target_ulong *dst, const target_ulong *src) |
422 |
if (new_cwp == (NWINDOWS - 1)) |
if (new_cwp == (NWINDOWS - 1)) |
423 |
memcpy32(env->regbase + NWINDOWS * 16, env->regbase); |
memcpy32(env->regbase + NWINDOWS * 16, env->regbase); |
424 |
env->regwptr = env->regbase + (new_cwp * 16); |
env->regwptr = env->regbase + (new_cwp * 16); |
425 |
|
REGWPTR = env->regwptr; |
426 |
} |
} |
427 |
|
|
428 |
void cpu_set_cwp(CPUState *env1, int new_cwp) |
void cpu_set_cwp(CPUState *env1, int new_cwp) |
429 |
{ |
{ |
430 |
CPUState *saved_env; |
CPUState *saved_env; |
431 |
|
#ifdef reg_REGWPTR |
432 |
|
target_ulong *saved_regwptr; |
433 |
|
#endif |
434 |
|
|
435 |
saved_env = env; |
saved_env = env; |
436 |
|
#ifdef reg_REGWPTR |
437 |
|
saved_regwptr = REGWPTR; |
438 |
|
#endif |
439 |
env = env1; |
env = env1; |
440 |
set_cwp(new_cwp); |
set_cwp(new_cwp); |
441 |
env = saved_env; |
env = saved_env; |
442 |
|
#ifdef reg_REGWPTR |
443 |
|
REGWPTR = saved_regwptr; |
444 |
|
#endif |
445 |
} |
} |
446 |
|
|
447 |
|
#ifdef TARGET_SPARC64 |
448 |
|
void do_interrupt(int intno) |
449 |
|
{ |
450 |
|
#ifdef DEBUG_PCALL |
451 |
|
if (loglevel & CPU_LOG_INT) { |
452 |
|
static int count; |
453 |
|
fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", |
454 |
|
count, intno, |
455 |
|
env->pc, |
456 |
|
env->npc, env->regwptr[6]); |
457 |
|
cpu_dump_state(env, logfile, fprintf, 0); |
458 |
|
#if 0 |
459 |
|
{ |
460 |
|
int i; |
461 |
|
uint8_t *ptr; |
462 |
|
|
463 |
|
fprintf(logfile, " code="); |
464 |
|
ptr = (uint8_t *)env->pc; |
465 |
|
for(i = 0; i < 16; i++) { |
466 |
|
fprintf(logfile, " %02x", ldub(ptr + i)); |
467 |
|
} |
468 |
|
fprintf(logfile, "\n"); |
469 |
|
} |
470 |
|
#endif |
471 |
|
count++; |
472 |
|
} |
473 |
|
#endif |
474 |
|
#if !defined(CONFIG_USER_ONLY) |
475 |
|
if (env->pstate & PS_IE) { |
476 |
|
cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); |
477 |
|
return; |
478 |
|
} |
479 |
|
#endif |
480 |
|
env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) | |
481 |
|
((env->pstate & 0xfff) << 8) | (env->cwp & 0xff); |
482 |
|
env->tpc[env->tl] = env->pc; |
483 |
|
env->tnpc[env->tl] = env->npc; |
484 |
|
env->tt[env->tl] = intno; |
485 |
|
env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4); |
486 |
|
env->tl++; |
487 |
|
env->pc = env->tbr; |
488 |
|
env->npc = env->pc + 4; |
489 |
|
env->exception_index = 0; |
490 |
|
} |
491 |
|
#else |
492 |
void do_interrupt(int intno) |
void do_interrupt(int intno) |
493 |
{ |
{ |
494 |
int cwp; |
int cwp; |
634 |
printf("MMU dump ends\n"); |
printf("MMU dump ends\n"); |
635 |
} |
} |
636 |
#endif |
#endif |
637 |
|
#endif |