static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, target_ulong eaddr, int rw, int type) { hwaddr hash; target_ulong vsid; int pr, target_page_bits; int ret, ret2; pr = msr_pr; ctx->eaddr = eaddr; ppc_slb_t *slb; target_ulong pageaddr; int segment_bits; LOG_MMU("Check SLBs\n"); slb = slb_lookup(env, eaddr); if (!slb) { return -5; } if (slb->vsid & SLB_VSID_B) { vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T; segment_bits = 40; } else { vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT; segment_bits = 28; } target_page_bits = (slb->vsid & SLB_VSID_L) ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS; ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP) : (slb->vsid & SLB_VSID_KS)); ctx->nx = !!(slb->vsid & SLB_VSID_N); pageaddr = eaddr & ((1ULL << segment_bits) - (1ULL << target_page_bits)); if (slb->vsid & SLB_VSID_B) { hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits); } else { hash = vsid ^ (pageaddr >> target_page_bits); } /* Only 5 bits of the page index are used in the AVPN */ ctx->ptem = (slb->vsid & SLB_VSID_PTEM) | ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80)); LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n", ctx->key, ctx->nx, vsid); ret = -1; /* Check if instruction fetch is allowed, if needed */ if (type != ACCESS_CODE || ctx->nx == 0) { /* Page address translation */ LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx " hash " TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, hash); ctx->hash[0] = hash; ctx->hash[1] = ~hash; /* Initialize real address with an invalid value */ ctx->raddr = (hwaddr)-1ULL; LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ctx->ptem, ctx->hash[0]); /* Primary table lookup */ ret = find_pte64(env, ctx, 0, rw, type, target_page_bits); if (ret < 0) { /* Secondary table lookup */ LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx "\n", env->htab_base, env->htab_mask, vsid, ctx->ptem, ctx->hash[1]); ret2 = find_pte64(env, ctx, 1, rw, type, target_page_bits); if (ret2 != -1) { ret = ret2; } } } else { LOG_MMU("No access allowed\n"); ret = -3; } return ret; }