?? alpha_palcode.c
字號:
break; case 0x000000AA: /* GENTRAP */ /* REQUIRED */ break; case 0x000000AE: /* CLRFEN */ break; default: break; }}static void pal_unix_call (CPUState *env, uint32_t palcode){ uint64_t palid, val, oldval; if (palcode < 0x00000080) { /* Privileged palcodes */ if (!(env->ps >> 3)) { /* TODO: generate privilege exception */ } } switch (palcode) { case 0x00000000: /* HALT */ /* REQUIRED */ break; case 0x00000001: /* CFLUSH */ break; case 0x00000002: /* DRAINA */ /* REQUIRED */ /* Implemented as no-op */ break; case 0x00000009: /* CSERVE */ /* REQUIRED */ break; case 0x0000000A: /* SWPPAL */ /* REQUIRED */ palid = env->ir[16]; do_swappal(env, palid); break; case 0x0000000D: /* WRIPIR */ val = env->ir[16]; if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1) env->ir[0] = val; break; case 0x00000010: /* RDMCES */ if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0) env->ir[0] = val; break; case 0x00000011: /* WRMCES */ val = env->ir[16]; if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1) env->ir[0] = val; break; case 0x0000002B: /* WRFEN */ val = env->ir[16]; if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1) env->ir[0] = val; break; case 0x0000002D: /* WRVPTPTR */ break; case 0x00000030: /* SWPCTX */ break; case 0x00000031: /* WRVAL */ break; case 0x00000032: /* RDVAL */ break; case 0x00000033: /* TBI */ val = env->ir[16]; if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1) env->ir[0] = val; break; case 0x00000034: /* WRENT */ break; case 0x00000035: /* SWPIPL */ break; case 0x00000036: /* RDPS */ break; case 0x00000037: /* WRKGP */ break; case 0x00000038: /* WRUSP */ val = env->ir[16]; if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1) env->ir[0] = val; break; case 0x00000039: /* WRPERFMON */ val = env->ir[16]; if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1) env->ir[0] = val; break; case 0x0000003A: /* RDUSP */ if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0) env->ir[0] = val; break; case 0x0000003C: /* WHAMI */ if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0) env->ir[0] = val; break; case 0x0000003D: /* RETSYS */ break; case 0x0000003E: /* WTINT */ break; case 0x0000003F: /* RTI */ if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0) env->ir[0] = val; break; case 0x00000080: /* BPT */ /* REQUIRED */ break; case 0x00000081: /* BUGCHK */ /* REQUIRED */ break; case 0x00000083: /* CALLSYS */ break; case 0x00000086: /* IMB */ /* REQUIRED */ /* Implemented as no-op */ break; case 0x00000092: /* URTI */ break; case 0x0000009E: /* RDUNIQUE */ /* REQUIRED */ break; case 0x0000009F: /* WRUNIQUE */ /* REQUIRED */ break; case 0x000000AA: /* GENTRAP */ /* REQUIRED */ break; case 0x000000AE: /* CLRFEN */ break; default: break; }}void call_pal (CPUState *env){ pal_handler_t *pal_handler = env->pal_handler; switch (env->exception_index) { case EXCP_RESET: (*pal_handler->reset)(env); break; case EXCP_MCHK: (*pal_handler->machine_check)(env); break; case EXCP_ARITH: (*pal_handler->arithmetic)(env); break; case EXCP_INTERRUPT: (*pal_handler->interrupt)(env); break; case EXCP_DFAULT: (*pal_handler->dfault)(env); break; case EXCP_DTB_MISS_PAL: (*pal_handler->dtb_miss_pal)(env); break; case EXCP_DTB_MISS_NATIVE: (*pal_handler->dtb_miss_native)(env); break; case EXCP_UNALIGN: (*pal_handler->unalign)(env); break; case EXCP_ITB_MISS: (*pal_handler->itb_miss)(env); break; case EXCP_ITB_ACV: (*pal_handler->itb_acv)(env); break; case EXCP_OPCDEC: (*pal_handler->opcdec)(env); break; case EXCP_FEN: (*pal_handler->fen)(env); break; default: if (env->exception_index >= EXCP_CALL_PAL && env->exception_index < EXCP_CALL_PALP) { /* Unprivileged PAL call */ (*pal_handler->call_pal) (env, (env->exception_index - EXCP_CALL_PAL) >> 6); } else if (env->exception_index >= EXCP_CALL_PALP && env->exception_index < EXCP_CALL_PALE) { /* Privileged PAL call */ (*pal_handler->call_pal) (env, ((env->exception_index - EXCP_CALL_PALP) >> 6) + 0x80); } else { /* Should never happen */ } break; } env->ipr[IPR_EXC_ADDR] &= ~1;}void pal_init (CPUState *env){ do_swappal(env, 0);}#if 0static uint64_t get_ptebase (CPUState *env, uint64_t vaddr){ uint64_t virbnd, ptbr; if ((env->features & FEATURE_VIRBND)) { cpu_alpha_mfpr(env, IPR_VIRBND, &virbnd); if (vaddr >= virbnd) cpu_alpha_mfpr(env, IPR_SYSPTBR, &ptbr); else cpu_alpha_mfpr(env, IPR_PTBR, &ptbr); } else { cpu_alpha_mfpr(env, IPR_PTBR, &ptbr); } return ptbr;}static int get_page_bits (CPUState *env){ /* XXX */ return 13;}static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp, uint64_t ptebase, int page_bits, uint64_t level, int mmu_idx, int rw){ uint64_t pteaddr, pte, pfn; uint8_t gh; int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user; /* XXX: TOFIX */ is_user = mmu_idx == MMU_USER_IDX; pteaddr = (ptebase << page_bits) + (8 * level); pte = ldq_raw(pteaddr); /* Decode all interresting PTE fields */ pfn = pte >> 32; uwe = (pte >> 13) & 1; kwe = (pte >> 12) & 1; ure = (pte >> 9) & 1; kre = (pte >> 8) & 1; gh = (pte >> 5) & 3; foE = (pte >> 3) & 1; foW = (pte >> 2) & 1; foR = (pte >> 1) & 1; v = pte & 1; ret = 0; if (!v) ret = 0x1; /* Check access rights */ ar = 0; if (is_user) { if (ure) ar |= PAGE_READ; if (uwe) ar |= PAGE_WRITE; if (rw == 1 && !uwe) ret |= 0x2; if (rw != 1 && !ure) ret |= 0x2; } else { if (kre) ar |= PAGE_READ; if (kwe) ar |= PAGE_WRITE; if (rw == 1 && !kwe) ret |= 0x2; if (rw != 1 && !kre) ret |= 0x2; } if (rw == 0 && foR) ret |= 0x4; if (rw == 2 && foE) ret |= 0x8; if (rw == 1 && foW) ret |= 0xC; *pfnp = pfn; if (zbitsp != NULL) *zbitsp = page_bits + (3 * gh); if (protp != NULL) *protp = ar; return ret;}static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot, uint64_t ptebase, int page_bits, uint64_t vaddr, int mmu_idx, int rw){ uint64_t pfn, page_mask, lvl_mask, level1, level2, level3; int lvl_bits, ret; page_mask = (1ULL << page_bits) - 1ULL; lvl_bits = page_bits - 3; lvl_mask = (1ULL << lvl_bits) - 1ULL; level3 = (vaddr >> page_bits) & lvl_mask; level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask; level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask; /* Level 1 PTE */ ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0); switch (ret) { case 3: /* Access violation */ return 2; case 2: /* translation not valid */ return 1; default: /* OK */ break; } /* Level 2 PTE */ ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0); switch (ret) { case 3: /* Access violation */ return 2; case 2: /* translation not valid */ return 1; default: /* OK */ break; } /* Level 3 PTE */ ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw); if (ret & 0x1) { /* Translation not valid */ ret = 1; } else if (ret & 2) { /* Access violation */ ret = 2; } else { switch (ret & 0xC) { case 0: /* OK */ ret = 0; break; case 0x4: /* Fault on read */ ret = 3; break; case 0x8: /* Fault on execute */ ret = 4; break; case 0xC: /* Fault on write */ ret = 5; break; } } *paddr = (pfn << page_bits) | (vaddr & page_mask); return 0;}static int virtual_to_physical (CPUState *env, uint64_t *physp, int *zbitsp, int *protp, uint64_t virtual, int mmu_idx, int rw){ uint64_t sva, ptebase; int seg, page_bits, ret; sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS); if (sva != virtual) seg = -1; else seg = sva >> (VA_BITS - 2); virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43)); ptebase = get_ptebase(env, virtual); page_bits = get_page_bits(env); ret = 0; switch (seg) { case 0: /* seg1: 3 levels of PTE */ ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, virtual, mmu_idx, rw); break; case 1: /* seg1: 2 levels of PTE */ ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, virtual, mmu_idx, rw); break; case 2: /* kernel segment */ if (mmu_idx != 0) { ret = 2; } else { *physp = virtual; } break; case 3: /* seg1: TB mapped */ ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, virtual, mmu_idx, rw); break; default: ret = 1; break; } return ret;}/* XXX: code provision */int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, int mmu_idx, int is_softmmu){ uint64_t physical, page_size, end; int prot, zbits, ret; if (env->user_mode_only) { ret = 2; } else { ret = virtual_to_physical(env, &physical, &zbits, &prot, address, mmu_idx, rw); } switch (ret) { case 0: /* No fault */ page_size = 1ULL << zbits; address &= ~(page_size - 1); for (end = physical + page_size; physical < end; physical += 0x1000) { ret = tlb_set_page(env, address, physical, prot, mmu_idx, is_softmmu); address += 0x1000; } break;#if 0 case 1: env->exception_index = EXCP_DFAULT; env->ipr[IPR_EXC_ADDR] = address; ret = 1; break; case 2: env->exception_index = EXCP_ACCESS_VIOLATION; env->ipr[IPR_EXC_ADDR] = address; ret = 1; break; case 3: env->exception_index = EXCP_FAULT_ON_READ; env->ipr[IPR_EXC_ADDR] = address; ret = 1; break; case 4: env->exception_index = EXCP_FAULT_ON_EXECUTE; env->ipr[IPR_EXC_ADDR] = address; ret = 1; case 5: env->exception_index = EXCP_FAULT_ON_WRITE; env->ipr[IPR_EXC_ADDR] = address; ret = 1;#endif default: /* Should never happen */ env->exception_index = EXCP_MCHK; env->ipr[IPR_EXC_ADDR] = address; ret = 1; break; } return ret;}#endif#else /* !defined (CONFIG_USER_ONLY) */void pal_init (CPUState *env){}void call_pal (CPUState *env, int palcode){ target_ulong ret; printf("%s: palcode %02x\n", __func__, palcode); if (logfile != NULL) fprintf(logfile, "%s: palcode %02x\n", __func__, palcode); switch (palcode) { case 0x83: /* CALLSYS */ printf("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]); if (logfile != NULL) fprintf(logfile, "CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]); ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1], env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4], env->ir[IR_A5]); env->ir[IR_A3] = ret; if (ret > (target_ulong)(-515)) { env->ir[IR_V0] = 1; } else { env->ir[IR_V0] = 0; } break; case 0x9E: /* RDUNIQUE */ env->ir[IR_V0] = env->unique; printf("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique); break; case 0x9F: /* WRUNIQUE */ env->unique = env->ir[IR_A0]; printf("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique); break; default: printf("%s: unhandled palcode %02x\n", __func__, palcode); if (logfile != NULL) fprintf(logfile, "%s: unhandled palcode %02x\n", __func__, palcode); exit(1); }}#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -