Commit 5eb7995e34ebf8cf9a3fc43ed2c7af93149d1b0d

Authored by j_mayer
1 parent 1527c87e

Code provision for PowerPC BookE MMU model support.

Better MSR flags initialisation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3189 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/helper.c
... ... @@ -1013,6 +1013,52 @@ void store_40x_sler (CPUPPCState *env, uint32_t val)
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,9 +1161,9 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
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,7 +1996,7 @@ void do_interrupt (CPUState *env)
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,28 +2492,39 @@ void cpu_dump_rfi (target_ulong RA, target_ulong msr)
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)
... ...
target-ppc/op.c
... ... @@ -2365,6 +2365,54 @@ void OPPROTO op_wrte (void)
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();
... ...
target-ppc/op_helper.c
... ... @@ -2605,4 +2605,151 @@ void do_4xx_tlbwe_lo (void)
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 */
... ...
target-ppc/op_helper.h
... ... @@ -156,6 +156,18 @@ void do_POWER_rfsvc (void);
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);
... ...
target-ppc/translate.c
... ... @@ -4618,9 +4618,10 @@ GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_BOOKE)
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,7 +4649,7 @@ GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
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,7 +4668,7 @@ GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
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,6 +4695,92 @@ GEN_HANDLER(tlbwe, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
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 {
... ...