Revision ccc76c24

b/target-sparc/cpu.h
309 309
#define TTE_PGSIZE(tte)     (((tte) >> 61) & 3ULL)
310 310
#define TTE_PA(tte)         ((tte) & 0x1ffffffe000ULL)
311 311

  
312
#define SFSR_NF_BIT         (1ULL << 24)   /* JPS1 NoFault */
313
#define SFSR_TM_BIT         (1ULL << 15)   /* JPS1 TLB Miss */
314
#define SFSR_FT_VA_IMMU_BIT (1ULL << 13)   /* USIIi VA out of range (IMMU) */
315
#define SFSR_FT_VA_DMMU_BIT (1ULL << 12)   /* USIIi VA out of range (DMMU) */
316
#define SFSR_FT_NFO_BIT     (1ULL << 11)   /* NFO page access */
317
#define SFSR_FT_ILL_BIT     (1ULL << 10)   /* illegal LDA/STA ASI */
318
#define SFSR_FT_ATOMIC_BIT  (1ULL <<  9)   /* atomic op on noncacheable area */
319
#define SFSR_FT_NF_E_BIT    (1ULL <<  8)   /* NF access on side effect area */
320
#define SFSR_FT_PRIV_BIT    (1ULL <<  7)   /* privilege violation */
321
#define SFSR_PR_BIT         (1ULL <<  3)   /* privilege mode */
322
#define SFSR_WRITE_BIT      (1ULL <<  2)   /* write access mode */
323
#define SFSR_OW_BIT         (1ULL <<  1)   /* status overwritten */
324
#define SFSR_VALID_BIT      (1ULL <<  0)   /* status valid */
325

  
326
#define SFSR_ASI_SHIFT      16             /* 23:16 ASI value */
327
#define SFSR_ASI_MASK       (0xffULL << SFSR_ASI_SHIFT)
328
#define SFSR_CT_PRIMARY     (0ULL <<  4)   /* 5:4 context type */
329
#define SFSR_CT_SECONDARY   (1ULL <<  4)
330
#define SFSR_CT_NUCLEUS     (2ULL <<  4)
331
#define SFSR_CT_NOTRANS     (3ULL <<  4)
332
#define SFSR_CT_MASK        (3ULL <<  4)
333

  
312 334
typedef struct SparcTLBEntry {
313 335
    uint64_t tag;
314 336
    uint64_t tte;
b/target-sparc/helper.c
413 413
{
414 414
    unsigned int i;
415 415
    uint64_t context;
416
    uint64_t sfsr = 0;
416 417

  
417 418
    int is_user = (mmu_idx == MMU_USER_IDX ||
418 419
                   mmu_idx == MMU_USER_SECONDARY_IDX);
......
427 428
    case MMU_USER_IDX:
428 429
    case MMU_KERNEL_IDX:
429 430
        context = env->dmmu.mmu_primary_context & 0x1fff;
431
        sfsr |= SFSR_CT_PRIMARY;
430 432
        break;
431 433
    case MMU_USER_SECONDARY_IDX:
432 434
    case MMU_KERNEL_SECONDARY_IDX:
433 435
        context = env->dmmu.mmu_secondary_context & 0x1fff;
436
        sfsr |= SFSR_CT_SECONDARY;
434 437
        break;
435 438
    case MMU_NUCLEUS_IDX:
439
        sfsr |= SFSR_CT_NUCLEUS;
440
        /* FALLTHRU */
436 441
    default:
437 442
        context = 0;
438 443
        break;
439 444
    }
440 445

  
446
    if (rw == 1) {
447
        sfsr |= SFSR_WRITE_BIT;
448
    }
449

  
441 450
    for (i = 0; i < 64; i++) {
442 451
        // ctx match, vaddr match, valid?
443 452
        if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
444 453

  
445
            uint8_t fault_type = 0;
446

  
447 454
            // access ok?
448 455
            if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
449
                fault_type |= 1; /* privilege violation */
456
                sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
450 457
                env->exception_index = TT_DFAULT;
451 458

  
452 459
                DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
......
469 476
                return 0;
470 477
            }
471 478

  
472
            if (env->dmmu.sfsr & 1) /* Fault status register */
473
                env->dmmu.sfsr = 2; /* overflow (not read before
474
                                             another fault) */
479
            if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
480
                sfsr |= SFSR_OW_BIT; /* overflow (not read before
481
                                        another fault) */
482
            }
475 483

  
476
            env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
484
            if (env->pstate & PS_PRIV) {
485
                sfsr |= SFSR_PR_BIT;
486
            }
477 487

  
478
            env->dmmu.sfsr |= (fault_type << 7);
488
            /* FIXME: ASI field in SFSR must be set */
489
            env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
479 490

  
480 491
            env->dmmu.sfar = address; /* Fault address register */
481 492

  
......
488 499
    DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
489 500
                address, context);
490 501

  
502
    /*
503
     * On MMU misses:
504
     * - UltraSPARC IIi: SFSR and SFAR unmodified
505
     * - JPS1: SFAR updated and some fields of SFSR updated
506
     */
491 507
    env->dmmu.tag_access = (address & ~0x1fffULL) | context;
492 508
    env->exception_index = TT_DMISS;
493 509
    return 1;
......
524 540
                                 address, context, physical)) {
525 541
            // access ok?
526 542
            if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
527
                if (env->immu.sfsr) /* Fault status register */
528
                    env->immu.sfsr = 2; /* overflow (not read before
529
                                             another fault) */
530
                env->immu.sfsr |= (is_user << 3) | 1;
543
                /* Fault status register */
544
                if (env->immu.sfsr & SFSR_VALID_BIT) {
545
                    env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
546
                                                     another fault) */
547
                } else {
548
                    env->immu.sfsr = 0;
549
                }
550
                if (env->pstate & PS_PRIV) {
551
                    env->immu.sfsr |= SFSR_PR_BIT;
552
                }
553
                if (env->tl > 0) {
554
                    env->immu.sfsr |= SFSR_CT_NUCLEUS;
555
                }
556

  
557
                /* FIXME: ASI field in SFSR must be set */
558
                env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
531 559
                env->exception_index = TT_TFAULT;
532 560

  
533 561
                env->immu.tag_access = (address & ~0x1fffULL) | context;

Also available in: Unified diff