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