Revision 5eb7995e

b/target-ppc/helper.c
1013 1013
    env->spr[SPR_405_SLER] = val;
1014 1014
}
1015 1015

  
1016
int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1017
                                   target_ulong address, int rw,
1018
                                   int access_type)
1019
{
1020
    ppcemb_tlb_t *tlb;
1021
    target_phys_addr_t raddr;
1022
    int i, prot, ret;
1023

  
1024
    ret = -1;
1025
    raddr = -1;
1026
    for (i = 0; i < env->nb_tlb; i++) {
1027
        tlb = &env->tlb[i].tlbe;
1028
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1029
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1030
            continue;
1031
        if (msr_pr)
1032
            prot = tlb->prot & 0xF;
1033
        else
1034
            prot = (tlb->prot >> 4) & 0xF;
1035
        /* Check the address space */
1036
        if (access_type == ACCESS_CODE) {
1037
            if (msr_is != (tlb->attr & 1))
1038
                continue;
1039
            ctx->prot = prot;
1040
            if (prot & PAGE_EXEC) {
1041
                ret = 0;
1042
                break;
1043
            }
1044
            ret = -3;
1045
        } else {
1046
            if (msr_ds != (tlb->attr & 1))
1047
                continue;
1048
            ctx->prot = prot;
1049
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1050
                ret = 0;
1051
                break;
1052
            }
1053
            ret = -2;
1054
        }
1055
    }
1056
    if (ret >= 0)
1057
        ctx->raddr = raddr;
1058

  
1059
    return ret;
1060
}
1061

  
1016 1062
static int check_physical (CPUState *env, mmu_ctx_t *ctx,
1017 1063
                           target_ulong eaddr, int rw)
1018 1064
{
......
1115 1161
            cpu_abort(env, "601 MMU model not implemented\n");
1116 1162
            return -1;
1117 1163
        case PPC_FLAGS_MMU_BOOKE:
1118
            /* XXX: TODO */
1119
            cpu_abort(env, "BookeE MMU model not implemented\n");
1120
            return -1;
1164
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1165
                                                rw, access_type);
1166
            break;
1121 1167
        case PPC_FLAGS_MMU_BOOKE_FSL:
1122 1168
            /* XXX: TODO */
1123 1169
            cpu_abort(env, "BookE FSL MMU model not implemented\n");
......
1950 1996
        cpu_abort(env, "Floating point assist exception "
1951 1997
                  "is not implemented yet !\n");
1952 1998
        goto store_next;
1953
        /* 64 bits PowerPC exceptions */
1999
    /* 64 bits PowerPC exceptions */
1954 2000
    case EXCP_DSEG: /* 0x0380 */
1955 2001
        /* XXX: TODO */
1956 2002
        cpu_abort(env, "Data segment exception is not implemented yet !\n");
......
2446 2492
void cpu_ppc_reset (void *opaque)
2447 2493
{
2448 2494
    CPUPPCState *env;
2495
    int i;
2449 2496

  
2450 2497
    env = opaque;
2498
    /* XXX: some of those flags initialisation values could depend
2499
     *      on the actual PowerPC implementation
2500
     */
2501
    for (i = 0; i < 63; i++)
2502
        env->msr[i] = 0;
2503
#if defined(TARGET_PPC64)
2504
    msr_hv = 0; /* Should be 1... */
2505
#endif
2506
    msr_ap = 0; /* TO BE CHECKED */
2507
    msr_sa = 0; /* TO BE CHECKED */
2508
    msr_ip = 0; /* TO BE CHECKED */
2451 2509
#if defined (DO_SINGLE_STEP) && 0
2452 2510
    /* Single step trace mode */
2453 2511
    msr_se = 1;
2454 2512
    msr_be = 1;
2455 2513
#endif
2456
    msr_fp = 1; /* Allow floating point exceptions */
2457
    msr_me = 1; /* Allow machine check exceptions  */
2458
#if defined(TARGET_PPC64)
2459
    msr_sf = 0; /* Boot in 32 bits mode */
2460
    msr_cm = 0;
2461
#endif
2462 2514
#if defined(CONFIG_USER_ONLY)
2515
    msr_fp = 1; /* Allow floating point exceptions */
2463 2516
    msr_pr = 1;
2464
    tlb_flush(env, 1);
2465 2517
#else
2466 2518
    env->nip = 0xFFFFFFFC;
2467 2519
    ppc_tlb_invalidate_all(env);
2468 2520
#endif
2469 2521
    do_compute_hflags(env);
2470 2522
    env->reserve = -1;
2523
    /* Be sure no exception or interrupt is pending */
2524
    env->pending_interrupts = 0;
2525
    env->exception_index = EXCP_NONE;
2526
    /* Flush all TLBs */
2527
    tlb_flush(env, 1);
2471 2528
}
2472 2529

  
2473 2530
CPUPPCState *cpu_ppc_init (void)
b/target-ppc/op.c
2365 2365
    RETURN();
2366 2366
}
2367 2367

  
2368
void OPPROTO op_booke_tlbre0 (void)
2369
{
2370
    do_booke_tlbre0();
2371
    RETURN();
2372
}
2373

  
2374
void OPPROTO op_booke_tlbre1 (void)
2375
{
2376
    do_booke_tlbre1();
2377
    RETURN();
2378
}
2379

  
2380
void OPPROTO op_booke_tlbre2 (void)
2381
{
2382
    do_booke_tlbre2();
2383
    RETURN();
2384
}
2385

  
2386
void OPPROTO op_booke_tlbsx (void)
2387
{
2388
    do_booke_tlbsx();
2389
    RETURN();
2390
}
2391

  
2392
void OPPROTO op_booke_tlbsx_ (void)
2393
{
2394
    do_booke_tlbsx_();
2395
    RETURN();
2396
}
2397

  
2398
void OPPROTO op_booke_tlbwe0 (void)
2399
{
2400
    do_booke_tlbwe0();
2401
    RETURN();
2402
}
2403

  
2404
void OPPROTO op_booke_tlbwe1 (void)
2405
{
2406
    do_booke_tlbwe1();
2407
    RETURN();
2408
}
2409

  
2410
void OPPROTO op_booke_tlbwe2 (void)
2411
{
2412
    do_booke_tlbwe2();
2413
    RETURN();
2414
}
2415

  
2368 2416
void OPPROTO op_4xx_tlbre_lo (void)
2369 2417
{
2370 2418
    do_4xx_tlbre_lo();
b/target-ppc/op_helper.c
2605 2605
    }
2606 2606
#endif
2607 2607
}
2608

  
2609
/* BookE TLB management */
2610
void do_booke_tlbwe0 (void)
2611
{
2612
    ppcemb_tlb_t *tlb;
2613
    target_ulong EPN, size;
2614
    int do_flush_tlbs;
2615

  
2616
#if defined (DEBUG_SOFTWARE_TLB)
2617
    if (loglevel != 0) {
2618
        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2619
    }
2620
#endif
2621
    do_flush_tlbs = 0;
2622
    T0 &= 0x3F;
2623
    tlb = &env->tlb[T0].tlbe;
2624
    EPN = T1 & 0xFFFFFC00;
2625
    if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2626
        do_flush_tlbs = 1;
2627
    tlb->EPN = EPN;
2628
    size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
2629
    if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2630
        do_flush_tlbs = 1;
2631
    tlb->size = size;
2632
    tlb->attr &= ~0x1;
2633
    tlb->attr |= (T1 >> 8) & 1;
2634
    if (T1 & 0x200) {
2635
        tlb->prot |= PAGE_VALID;
2636
    } else {
2637
        if (tlb->prot & PAGE_VALID) {
2638
            tlb->prot &= ~PAGE_VALID;
2639
            do_flush_tlbs = 1;
2640
        }
2641
    }
2642
    tlb->PID = env->spr[SPR_BOOKE_PID];
2643
    if (do_flush_tlbs)
2644
        tlb_flush(env, 1);
2645
}
2646

  
2647
void do_booke_tlbwe1 (void)
2648
{
2649
    ppcemb_tlb_t *tlb;
2650
    target_phys_addr_t RPN;
2651

  
2652
#if defined (DEBUG_SOFTWARE_TLB)
2653
    if (loglevel != 0) {
2654
        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2655
    }
2656
#endif
2657
    T0 &= 0x3F;
2658
    tlb = &env->tlb[T0].tlbe;
2659
    RPN = T1 & 0xFFFFFC0F;
2660
    if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
2661
        tlb_flush(env, 1);
2662
    tlb->RPN = RPN;
2663
}
2664

  
2665
void do_booke_tlbwe2 (void)
2666
{
2667
    ppcemb_tlb_t *tlb;
2668

  
2669
#if defined (DEBUG_SOFTWARE_TLB)
2670
    if (loglevel != 0) {
2671
        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2672
    }
2673
#endif
2674
    T0 &= 0x3F;
2675
    tlb = &env->tlb[T0].tlbe;
2676
    tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
2677
    tlb->prot = tlb->prot & PAGE_VALID;
2678
    if (T1 & 0x1)
2679
        tlb->prot |= PAGE_READ << 4;
2680
    if (T1 & 0x2)
2681
        tlb->prot |= PAGE_WRITE << 4;
2682
    if (T1 & 0x4)
2683
        tlb->prot |= PAGE_EXEC << 4;
2684
    if (T1 & 0x8)
2685
        tlb->prot |= PAGE_READ;
2686
    if (T1 & 0x10)
2687
        tlb->prot |= PAGE_WRITE;
2688
    if (T1 & 0x20)
2689
        tlb->prot |= PAGE_EXEC;
2690
}
2691

  
2692
void do_booke_tlbsx (void)
2693
{
2694
    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
2695
}
2696

  
2697
void do_booke_tlbsx_ (void)
2698
{
2699
    int tmp = xer_so;
2700

  
2701
    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
2702
    if (T0 != -1)
2703
        tmp |= 0x02;
2704
    env->crf[0] = tmp;
2705
}
2706

  
2707
void do_booke_tlbre0 (void)
2708
{
2709
    ppcemb_tlb_t *tlb;
2710
    int size;
2711

  
2712
    T0 &= 0x3F;
2713
    tlb = &env->tlb[T0].tlbe;
2714
    T0 = tlb->EPN;
2715
    size = booke_page_size_to_tlb(tlb->size);
2716
    if (size < 0 || size > 0xF)
2717
        size = 1;
2718
    T0 |= size << 4;
2719
    if (tlb->attr & 0x1)
2720
        T0 |= 0x100;
2721
    if (tlb->prot & PAGE_VALID)
2722
        T0 |= 0x200;
2723
    env->spr[SPR_BOOKE_PID] = tlb->PID;
2724
}
2725

  
2726
void do_booke_tlbre1 (void)
2727
{
2728
    ppcemb_tlb_t *tlb;
2729

  
2730
    T0 &= 0x3F;
2731
    tlb = &env->tlb[T0].tlbe;
2732
    T0 = tlb->RPN;
2733
}
2734

  
2735
void do_booke_tlbre2 (void)
2736
{
2737
    ppcemb_tlb_t *tlb;
2738

  
2739
    T0 &= 0x3F;
2740
    tlb = &env->tlb[T0].tlbe;
2741
    T0 = tlb->attr & ~0x1;
2742
    if (tlb->prot & (PAGE_READ << 4))
2743
        T0 |= 0x1;
2744
    if (tlb->prot & (PAGE_WRITE << 4))
2745
        T0 |= 0x2;
2746
    if (tlb->prot & (PAGE_EXEC << 4))
2747
        T0 |= 0x4;
2748
    if (tlb->prot & PAGE_READ)
2749
        T0 |= 0x8;
2750
    if (tlb->prot & PAGE_WRITE)
2751
        T0 |= 0x10;
2752
    if (tlb->prot & PAGE_EXEC)
2753
        T0 |= 0x20;
2754
}
2608 2755
#endif /* !CONFIG_USER_ONLY */
b/target-ppc/op_helper.h
156 156
void do_op_602_mfrom (void);
157 157
#endif
158 158

  
159
/* PowerPC BookE specific helpers */
160
#if !defined(CONFIG_USER_ONLY)
161
void do_booke_tlbre0 (void);
162
void do_booke_tlbre1 (void);
163
void do_booke_tlbre2 (void);
164
void do_booke_tlbsx (void);
165
void do_booke_tlbsx_ (void);
166
void do_booke_tlbwe0 (void);
167
void do_booke_tlbwe1 (void);
168
void do_booke_tlbwe2 (void);
169
#endif
170

  
159 171
/* PowerPC 4xx specific helpers */
160 172
void do_405_check_ov (void);
161 173
void do_405_check_sat (void);
b/target-ppc/translate.c
4618 4618
    RET_CHG_FLOW(ctx);
4619 4619
#endif
4620 4620
}
4621

  
4621 4622
/* TLB management - PowerPC 405 implementation */
4622 4623
/* tlbre */
4623
GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
4624
GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
4624 4625
{
4625 4626
#if defined(CONFIG_USER_ONLY)
4626 4627
    RET_PRIVOPC(ctx);
......
4648 4649
}
4649 4650

  
4650 4651
/* tlbsx - tlbsx. */
4651
GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
4652
GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
4652 4653
{
4653 4654
#if defined(CONFIG_USER_ONLY)
4654 4655
    RET_PRIVOPC(ctx);
......
4667 4668
}
4668 4669

  
4669 4670
/* tlbwe */
4670
GEN_HANDLER(tlbwe, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
4671
GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
4671 4672
{
4672 4673
#if defined(CONFIG_USER_ONLY)
4673 4674
    RET_PRIVOPC(ctx);
......
4694 4695
#endif
4695 4696
}
4696 4697

  
4698
/* TLB management - PowerPC BookE implementation */
4699
/* tlbre */
4700
GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
4701
{
4702
#if defined(CONFIG_USER_ONLY)
4703
    RET_PRIVOPC(ctx);
4704
#else
4705
    if (unlikely(!ctx->supervisor)) {
4706
        RET_PRIVOPC(ctx);
4707
        return;
4708
    }
4709
    switch (rB(ctx->opcode)) {
4710
    case 0:
4711
        gen_op_load_gpr_T0(rA(ctx->opcode));
4712
        gen_op_booke_tlbre0();
4713
        gen_op_store_T0_gpr(rD(ctx->opcode));
4714
        break;
4715
    case 1:
4716
        gen_op_load_gpr_T0(rA(ctx->opcode));
4717
        gen_op_booke_tlbre1();
4718
        gen_op_store_T0_gpr(rD(ctx->opcode));
4719
        break;
4720
    case 2:
4721
        gen_op_load_gpr_T0(rA(ctx->opcode));
4722
        gen_op_booke_tlbre2();
4723
        gen_op_store_T0_gpr(rD(ctx->opcode));
4724
        break;
4725
    default:
4726
        RET_INVAL(ctx);
4727
        break;
4728
    }
4729
#endif
4730
}
4731

  
4732
/* tlbsx - tlbsx. */
4733
GEN_HANDLER(tlbsx_booke, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
4734
{
4735
#if defined(CONFIG_USER_ONLY)
4736
    RET_PRIVOPC(ctx);
4737
#else
4738
    if (unlikely(!ctx->supervisor)) {
4739
        RET_PRIVOPC(ctx);
4740
        return;
4741
    }
4742
    gen_addr_reg_index(ctx);
4743
    if (Rc(ctx->opcode))
4744
        gen_op_booke_tlbsx_();
4745
    else
4746
        gen_op_booke_tlbsx();
4747
    gen_op_store_T0_gpr(rD(ctx->opcode));
4748
#endif
4749
}
4750

  
4751
/* tlbwe */
4752
GEN_HANDLER(tlbwe_booke, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
4753
{
4754
#if defined(CONFIG_USER_ONLY)
4755
    RET_PRIVOPC(ctx);
4756
#else
4757
    if (unlikely(!ctx->supervisor)) {
4758
        RET_PRIVOPC(ctx);
4759
        return;
4760
    }
4761
    switch (rB(ctx->opcode)) {
4762
    case 0:
4763
        gen_op_load_gpr_T0(rA(ctx->opcode));
4764
        gen_op_load_gpr_T1(rS(ctx->opcode));
4765
        gen_op_booke_tlbwe0();
4766
        break;
4767
    case 1:
4768
        gen_op_load_gpr_T0(rA(ctx->opcode));
4769
        gen_op_load_gpr_T1(rS(ctx->opcode));
4770
        gen_op_booke_tlbwe1();
4771
        break;
4772
    case 2:
4773
        gen_op_load_gpr_T0(rA(ctx->opcode));
4774
        gen_op_load_gpr_T1(rS(ctx->opcode));
4775
        gen_op_booke_tlbwe2();
4776
        break;
4777
    default:
4778
        RET_INVAL(ctx);
4779
        break;
4780
    }
4781
#endif
4782
}
4783

  
4697 4784
/* wrtee */
4698 4785
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
4699 4786
{

Also available in: Unified diff