Revision a8dea12f

b/target-ppc/helper.c
549 549
            if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
550 550
                /* Software TLB search */
551 551
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
552
            } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
553
                /* XXX: TODO */
554 552
            } else {
555 553
#if defined (DEBUG_MMU)
556 554
                if (loglevel > 0) {
......
632 630
    return ret;
633 631
}
634 632

  
633
int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
634
                                 uint32_t address, int rw, int access_type)
635
{
636
    ppcemb_tlb_t *tlb;
637
    target_phys_addr_t raddr;
638
    target_ulong mask;
639
    int i, ret, zsel, zpr;
640
            
641
    ret = -6;
642
    for (i = 0; i < env->nb_tlb; i++) {
643
        tlb = &env->tlb[i].tlbe;
644
        /* Check valid flag */
645
        if (!(tlb->prot & PAGE_VALID)) {
646
            if (loglevel)
647
                fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
648
            continue;
649
        }
650
        mask = ~(tlb->size - 1);
651
        if (loglevel) {
652
            fprintf(logfile, "%s: TLB %d address %08x PID %04x <=> "
653
                    "%08x %08x %04x\n",
654
                    __func__, i, address, env->spr[SPR_40x_PID],
655
                    tlb->EPN, mask, tlb->PID);
656
        }
657
        /* Check PID */
658
        if (tlb->PID != 0 && tlb->PID != env->spr[SPR_40x_PID])
659
            continue;
660
        /* Check effective address */
661
        if ((address & mask) != tlb->EPN)
662
            continue;
663
        raddr = (tlb->RPN & mask) | (address & ~mask);
664
        zsel = (tlb->attr >> 4) & 0xF;
665
        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
666
        if (loglevel) {
667
            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
668
                    __func__, i, zsel, zpr, rw, tlb->attr);
669
        }
670
        if (access_type == ACCESS_CODE) {
671
            /* Check execute enable bit */
672
            switch (zpr) {
673
            case 0x0:
674
                if (msr_pr) {
675
                    ret = -3;
676
                    ctx->prot = 0;
677
                    break;
678
                }
679
                /* No break here */
680
            case 0x1:
681
            case 0x2:
682
                /* Check from TLB entry */
683
                if (!(tlb->prot & PAGE_EXEC)) {
684
                    ret = -3;
685
                } else {
686
                    if (tlb->prot & PAGE_WRITE)
687
                        ctx->prot = PAGE_READ | PAGE_WRITE;
688
                    else
689
                        ctx->prot = PAGE_READ;
690
                    ret = 0;
691
                }
692
                break;
693
            case 0x3:
694
                /* All accesses granted */
695
                ret = 0;
696
                ctx->prot = PAGE_READ | PAGE_WRITE;
697
                break;
698
            }
699
        } else {
700
            switch (zpr) {
701
            case 0x0:
702
                if (msr_pr) {
703
                    ret = -2;
704
                    ctx->prot = 0;
705
                    break;
706
                }
707
                /* No break here */
708
            case 0x1:
709
            case 0x2:
710
                /* Check from TLB entry */
711
                /* Check write protection bit */
712
                if (rw && !(tlb->prot & PAGE_WRITE)) {
713
                    ret = -2;
714
                } else {
715
                    ret = 2;
716
                    if (tlb->prot & PAGE_WRITE)
717
                        ctx->prot = PAGE_READ | PAGE_WRITE;
718
                    else
719
                        ctx->prot = PAGE_READ;
720
                }
721
                break;
722
            case 0x3:
723
                /* All accesses granted */
724
                ret = 2;
725
                ctx->prot = PAGE_READ | PAGE_WRITE;
726
                break;
727
            }
728
        }
729
        if (ret >= 0) {
730
            ctx->raddr = raddr;
731
            if (loglevel) {
732
                fprintf(logfile, "%s: access granted " ADDRX " => " REGX
733
                        " %d\n", __func__, address, ctx->raddr, ctx->prot);
734
            }
735
            return i;
736
        }
737
    }
738
    
739
    return ret;
740
}
741

  
635 742
static int check_physical (CPUState *env, mmu_ctx_t *ctx,
636 743
                           target_ulong eaddr, int rw)
637 744
{
......
682 789
        /* No address translation */
683 790
        ret = check_physical(env, ctx, eaddr, rw);
684 791
    } else {
685
        /* Try to find a BAT */
686
        ret = -1;
687
        if (check_BATs)
688
            ret = get_bat(env, ctx, eaddr, rw, access_type);
689
        if (ret < 0) {
690
            /* We didn't match any BAT entry */
691
            ret = get_segment(env, ctx, eaddr, rw, access_type);
792
        switch (PPC_MMU(env)) {
793
        case PPC_FLAGS_MMU_32B:
794
        case PPC_FLAGS_MMU_SOFT_6xx:
795
            /* Try to find a BAT */
796
            ret = -1;
797
            if (check_BATs)
798
                ret = get_bat(env, ctx, eaddr, rw, access_type);
799
            if (ret < 0) {
800
                /* We didn't match any BAT entry */
801
                ret = get_segment(env, ctx, eaddr, rw, access_type);
802
            }
803
            break;
804
        case PPC_FLAGS_MMU_SOFT_4xx:
805
            ret = mmu4xx_get_physical_address(env, ctx, eaddr,
806
                                              rw, access_type);
807
            break;
808
        default:
809
            /* XXX: TODO */
810
            cpu_abort(env, "MMU model not implemented\n");
811
            return -1;
692 812
        }
693 813
    }
694 814
#if 0
......
753 873
                    error_code = 1 << 18;
754 874
                    goto tlb_miss;
755 875
                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
756
                    /* XXX: TODO */
876
                    exception = EXCP_40x_ITLBMISS;
877
                    error_code = 0;
878
                    env->spr[SPR_40x_DEAR] = address;
879
                    env->spr[SPR_40x_ESR] = 0x00000000;
757 880
                } else {
758 881
                    error_code = 0x40000000;
759 882
                }
......
799 922
                    /* Do not alter DAR nor DSISR */
800 923
                    goto out;
801 924
                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
802
                    /* XXX: TODO */
925
                    exception = EXCP_40x_DTLBMISS;
926
                    error_code = 0;
927
                    env->spr[SPR_40x_DEAR] = address;
928
                    if (rw)
929
                        env->spr[SPR_40x_ESR] = 0x00800000;
930
                    else
931
                        env->spr[SPR_40x_ESR] = 0x00000000;
803 932
                } else {
804 933
                    error_code = 0x40000000;
805 934
                }
......
1518 1647
        switch (PPC_EXCP(env)) {
1519 1648
        case PPC_FLAGS_EXCP_40x:
1520 1649
            /* DTLBMISS on 4xx */
1521
            /* XXX: TODO */
1522
            cpu_abort(env,
1523
                      "40x DTLBMISS exception is not implemented yet !\n");
1650
            msr &= ~0xFFFF0000;
1524 1651
            goto store_next;
1525 1652
        case PPC_FLAGS_EXCP_602:
1526 1653
        case PPC_FLAGS_EXCP_603:
......
1538 1665
        switch (PPC_EXCP(env)) {
1539 1666
        case PPC_FLAGS_EXCP_40x:
1540 1667
            /* ITLBMISS on 4xx */
1541
            /* XXX: TODO */
1542
            cpu_abort(env,
1543
                      "40x ITLBMISS exception is not implemented yet !\n");
1668
            msr &= ~0xFFFF0000;
1544 1669
            goto store_next;
1545 1670
        case PPC_FLAGS_EXCP_602:
1546 1671
        case PPC_FLAGS_EXCP_603:
b/target-ppc/op_helper.c
2365 2365
                     way, is_code, CMP, RPN);
2366 2366
}
2367 2367

  
2368
static target_ulong booke_tlb_to_page_size (int size)
2369
{
2370
    return 1024 << (2 * size);
2371
}
2372

  
2373
static int booke_page_size_to_tlb (target_ulong page_size)
2374
{
2375
    int size;
2376

  
2377
    switch (page_size) {
2378
    case 0x00000400UL:
2379
        size = 0x0;
2380
        break;
2381
    case 0x00001000UL:
2382
        size = 0x1;
2383
        break;
2384
    case 0x00004000UL:
2385
        size = 0x2;
2386
        break;
2387
    case 0x00010000UL:
2388
        size = 0x3;
2389
        break;
2390
    case 0x00040000UL:
2391
        size = 0x4;
2392
        break;
2393
    case 0x00100000UL:
2394
        size = 0x5;
2395
        break;
2396
    case 0x00400000UL:
2397
        size = 0x6;
2398
        break;
2399
    case 0x01000000UL:
2400
        size = 0x7;
2401
        break;
2402
    case 0x04000000UL:
2403
        size = 0x8;
2404
        break;
2405
    case 0x10000000UL:
2406
        size = 0x9;
2407
        break;
2408
    case 0x40000000UL:
2409
        size = 0xA;
2410
        break;
2411
#if defined (TARGET_PPC64)
2412
    case 0x000100000000ULL:
2413
        size = 0xB;
2414
        break;
2415
    case 0x000400000000ULL:
2416
        size = 0xC;
2417
        break;
2418
    case 0x001000000000ULL:
2419
        size = 0xD;
2420
        break;
2421
    case 0x004000000000ULL:
2422
        size = 0xE;
2423
        break;
2424
    case 0x010000000000ULL:
2425
        size = 0xF;
2426
        break;
2427
#endif
2428
    default:
2429
        size = -1;
2430
        break;
2431
    }
2432

  
2433
    return size;
2434
}
2435

  
2368 2436
/* Helpers for 4xx TLB management */
2369 2437
void do_4xx_tlbia (void)
2370 2438
{
2371
#if 0
2372
    ppc_tlb_t *tlb;
2373
    target_ulong page, end;
2439
    ppcemb_tlb_t *tlb;
2374 2440
    int i;
2375 2441

  
2376 2442
    for (i = 0; i < 64; i++) {
2377
        tlb = &env->tlb[i];
2443
        tlb = &env->tlb[i].tlbe;
2378 2444
        if (tlb->prot & PAGE_VALID) {
2445
#if 0
2379 2446
            end = tlb->EPN + tlb->size;
2380 2447
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2381 2448
                tlb_flush_page(env, page);
2449
#endif
2382 2450
            tlb->prot &= ~PAGE_VALID;
2383 2451
        }
2384 2452
    }
2385
#endif
2453
    tlb_flush(env, 1);
2386 2454
}
2387 2455

  
2388 2456
void do_4xx_tlbre_lo (void)
2389 2457
{
2390
#if 0
2391
    ppc_tlb_t *tlb;
2458
    ppcemb_tlb_t *tlb;
2459
    int size;
2392 2460

  
2393 2461
    T0 &= 0x3F;
2394
    tlb = &env->tlb[T0];
2395
    T0 = tlb->stor[0];
2396
    env->spr[SPR_40x_PID] = tlb->pid;
2397
#endif
2462
    tlb = &env->tlb[T0].tlbe;
2463
    T0 = tlb->EPN;
2464
    if (tlb->prot & PAGE_VALID)
2465
        T0 |= 0x400;
2466
    size = booke_page_size_to_tlb(tlb->size);
2467
    if (size < 0 || size > 0x7)
2468
        size = 1;
2469
    T0 |= size << 7;
2470
    env->spr[SPR_40x_PID] = tlb->PID;
2398 2471
}
2399 2472

  
2400 2473
void do_4xx_tlbre_hi (void)
2401 2474
{
2402
#if 0
2403
    ppc_tlb_t *tlb;
2475
    ppcemb_tlb_t *tlb;
2404 2476

  
2405 2477
    T0 &= 0x3F;
2406
    tlb = &env->tlb[T0];
2407
    T0 = tlb->stor[1];
2408
#endif
2478
    tlb = &env->tlb[T0].tlbe;
2479
    T0 = tlb->RPN;
2480
    if (tlb->prot & PAGE_EXEC)
2481
        T0 |= 0x200;
2482
    if (tlb->prot & PAGE_WRITE)
2483
        T0 |= 0x100;
2409 2484
}
2410 2485

  
2411 2486
static int tlb_4xx_search (target_ulong virtual)
2412 2487
{
2413
#if 0
2414
    ppc_tlb_t *tlb;
2488
    ppcemb_tlb_t *tlb;
2415 2489
    target_ulong base, mask;
2416 2490
    int i, ret;
2417 2491

  
2418 2492
    /* Default return value is no match */
2419 2493
    ret = -1;
2420 2494
    for (i = 0; i < 64; i++) {
2421
        tlb = &env->tlb[i];
2495
        tlb = &env->tlb[i].tlbe;
2422 2496
        /* Check TLB validity */
2423 2497
        if (!(tlb->prot & PAGE_VALID))
2424 2498
            continue;
2425 2499
        /* Check TLB PID vs current PID */
2426
        if (tlb->pid != 0 && tlb->pid != env->spr[SPR_40x_PID])
2500
        if (tlb->PID != 0 && tlb->PID != env->spr[SPR_40x_PID])
2427 2501
            continue;
2428 2502
        /* Check TLB address vs virtual address */
2429 2503
        base = tlb->EPN;
......
2435 2509
    }
2436 2510

  
2437 2511
    return ret;
2438
#else
2439
    return -1;
2440
#endif
2441 2512
}
2442 2513

  
2443 2514
void do_4xx_tlbsx (void)
......
2457 2528

  
2458 2529
void do_4xx_tlbwe_lo (void)
2459 2530
{
2460
#if 0
2461
    ppc_tlb_t *tlb;
2531
    ppcemb_tlb_t *tlb;
2462 2532
    target_ulong page, end;
2463 2533

  
2464 2534
    T0 &= 0x3F;
2465
    tlb = &env->tlb[T0];
2535
    tlb = &env->tlb[T0].tlbe;
2466 2536
    /* Invalidate previous TLB (if it's valid) */
2467 2537
    if (tlb->prot & PAGE_VALID) {
2468 2538
        end = tlb->EPN + tlb->size;
2469 2539
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2470 2540
            tlb_flush_page(env, page);
2471 2541
    }
2472
    tlb->size = 1024 << (2 * ((T1 >> 7) & 0x7));
2542
    tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
2473 2543
    tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
2474 2544
    if (T1 & 0x400)
2475 2545
        tlb->prot |= PAGE_VALID;
2476 2546
    else
2477 2547
        tlb->prot &= ~PAGE_VALID;
2478
    tlb->pid = env->spr[SPR_BOOKE_PID]; /* PID */
2548
    tlb->PID = env->spr[SPR_BOOKE_PID]; /* PID */
2549
    tlb->attr = T1 & 0xFF;
2479 2550
    /* Invalidate new TLB (if valid) */
2480 2551
    if (tlb->prot & PAGE_VALID) {
2481 2552
        end = tlb->EPN + tlb->size;
2482 2553
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2483 2554
            tlb_flush_page(env, page);
2484 2555
    }
2485
#endif
2486 2556
}
2487 2557

  
2488 2558
void do_4xx_tlbwe_hi (void)
2489 2559
{
2490
#if 0
2491
    ppc_tlb_t *tlb;
2560
    ppcemb_tlb_t *tlb;
2492 2561

  
2493 2562
    T0 &= 0x3F;
2494
    tlb = &env->tlb[T0];
2563
    tlb = &env->tlb[T0].tlbe;
2495 2564
    tlb->RPN = T1 & 0xFFFFFC00;
2496 2565
    tlb->prot = PAGE_READ;
2497 2566
    if (T1 & 0x200)
2498 2567
        tlb->prot |= PAGE_EXEC;
2499 2568
    if (T1 & 0x100)
2500 2569
        tlb->prot |= PAGE_WRITE;
2501
#endif
2502 2570
}
2503 2571
#endif /* !CONFIG_USER_ONLY */

Also available in: Unified diff