⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 helper.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr){    target_phys_addr_t sr_base;    target_ulong rt;    uint64_t tmp64;    uint32_t tmp;    sr_base = env->spr[SPR_ASR];    sr_base += 12 * slb_nr;    tmp64 = ldq_phys(sr_base);    tmp = ldl_phys(sr_base + 8);    if (tmp64 & 0x0000000008000000ULL) {        /* SLB entry is valid */        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */        rt = tmp >> 8;             /* 65:88 => 40:63 */        rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */        rt |= ((tmp >> 4) & 0xF) << 27;    } else {        rt = 0;    }#if defined(DEBUG_SLB)    if (loglevel != 0) {        fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "                ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);    }#endif    return rt;}void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs){    target_phys_addr_t sr_base;    uint64_t tmp64;    uint32_t tmp;    sr_base = env->spr[SPR_ASR];    sr_base += 12 * slb_nr;    /* Copy Rs bits 37:63 to SLB 62:88 */    tmp = rs << 8;    tmp64 = (rs >> 24) & 0x7;    /* Copy Rs bits 33:36 to SLB 89:92 */    tmp |= ((rs >> 27) & 0xF) << 4;    /* Set the valid bit */    tmp64 |= 1 << 27;    /* Set ESID */    tmp64 |= (uint32_t)slb_nr << 28;#if defined(DEBUG_SLB)    if (loglevel != 0) {        fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64                " %08" PRIx32 "\n", __func__,                slb_nr, rs, sr_base, tmp64, tmp);    }#endif    /* Write SLB entry to memory */    stq_phys(sr_base, tmp64);    stl_phys(sr_base + 8, tmp);}#endif /* defined(TARGET_PPC64) *//* Perform segment based translation */static always_inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,                                                    int sdr_sh,                                                    target_phys_addr_t hash,                                                    target_phys_addr_t mask){    return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);}static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,                                      target_ulong eaddr, int rw, int type){    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;#if defined(TARGET_PPC64)    int attr;#endif    int ds, vsid_sh, sdr_sh, pr;    int ret, ret2;    pr = msr_pr;#if defined(TARGET_PPC64)    if (env->mmu_model & POWERPC_MMU_64) {#if defined (DEBUG_MMU)        if (loglevel != 0) {            fprintf(logfile, "Check SLBs\n");        }#endif        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);        if (ret < 0)            return ret;        ctx->key = ((attr & 0x40) && (pr != 0)) ||            ((attr & 0x80) && (pr == 0)) ? 1 : 0;        ds = 0;        ctx->nx = attr & 0x20 ? 1 : 0;        vsid_mask = 0x00003FFFFFFFFF80ULL;        vsid_sh = 7;        sdr_sh = 18;        sdr_mask = 0x3FF80;    } else#endif /* defined(TARGET_PPC64) */    {        sr = env->sr[eaddr >> 28];        page_mask = 0x0FFFFFFF;        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;        ds = sr & 0x80000000 ? 1 : 0;        ctx->nx = sr & 0x10000000 ? 1 : 0;        vsid = sr & 0x00FFFFFF;        vsid_mask = 0x01FFFFC0;        vsid_sh = 6;        sdr_sh = 16;        sdr_mask = 0xFFC0;#if defined (DEBUG_MMU)        if (loglevel != 0) {            fprintf(logfile, "Check segment v=" ADDRX " %d " ADDRX                    " nip=" ADDRX " lr=" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",                    eaddr, (int)(eaddr >> 28), sr, env->nip,                    env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0,                    rw, type);        }#endif    }#if defined (DEBUG_MMU)    if (loglevel != 0) {        fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n",                ctx->key, ds, ctx->nx, vsid);    }#endif    ret = -1;    if (!ds) {        /* Check if instruction fetch is allowed, if needed */        if (type != ACCESS_CODE || ctx->nx == 0) {            /* Page address translation */            /* Primary table address */            sdr = env->sdr1;            pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;#if defined(TARGET_PPC64)            if (env->mmu_model & POWERPC_MMU_64) {                htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));                /* XXX: this is false for 1 TB segments */                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;            } else#endif            {                htab_mask = sdr & 0x000001FF;                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;            }            mask = (htab_mask << sdr_sh) | sdr_mask;#if defined (DEBUG_MMU)            if (loglevel != 0) {                fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX                        " mask " PADDRX " " ADDRX "\n",                        sdr, sdr_sh, hash, mask, page_mask);            }#endif            ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);            /* Secondary table address */            hash = (~hash) & vsid_mask;#if defined (DEBUG_MMU)            if (loglevel != 0) {                fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX                        " mask " PADDRX "\n",                        sdr, sdr_sh, hash, mask);            }#endif            ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);#if defined(TARGET_PPC64)            if (env->mmu_model & POWERPC_MMU_64) {                /* Only 5 bits of the page index are used in the AVPN */                ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);            } else#endif            {                ctx->ptem = (vsid << 7) | (pgidx >> 10);            }            /* Initialize real address with an invalid value */            ctx->raddr = (target_phys_addr_t)-1ULL;            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {                /* Software TLB search */                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);            } else {#if defined (DEBUG_MMU)                if (loglevel != 0) {                    fprintf(logfile, "0 sdr1=" PADDRX " vsid=" ADDRX " "                            "api=" ADDRX " hash=" PADDRX                            " pg_addr=" PADDRX "\n",                            sdr, vsid, pgidx, hash, ctx->pg_addr[0]);                }#endif                /* Primary table lookup */                ret = find_pte(env, ctx, 0, rw, type);                if (ret < 0) {                    /* Secondary table lookup */#if defined (DEBUG_MMU)                    if (eaddr != 0xEFFFFFFF && loglevel != 0) {                        fprintf(logfile, "1 sdr1=" PADDRX " vsid=" ADDRX " "                                "api=" ADDRX " hash=" PADDRX                                " pg_addr=" PADDRX "\n",                                sdr, vsid, pgidx, hash, ctx->pg_addr[1]);                    }#endif                    ret2 = find_pte(env, ctx, 1, rw, type);                    if (ret2 != -1)                        ret = ret2;                }            }#if defined (DUMP_PAGE_TABLES)            if (loglevel != 0) {                target_phys_addr_t curaddr;                uint32_t a0, a1, a2, a3;                fprintf(logfile, "Page table: " PADDRX " len " PADDRX "\n",                        sdr, mask + 0x80);                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);                     curaddr += 16) {                    a0 = ldl_phys(curaddr);                    a1 = ldl_phys(curaddr + 4);                    a2 = ldl_phys(curaddr + 8);                    a3 = ldl_phys(curaddr + 12);                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {                        fprintf(logfile, PADDRX ": %08x %08x %08x %08x\n",                                curaddr, a0, a1, a2, a3);                    }                }            }#endif        } else {#if defined (DEBUG_MMU)            if (loglevel != 0)                fprintf(logfile, "No access allowed\n");#endif            ret = -3;        }    } else {#if defined (DEBUG_MMU)        if (loglevel != 0)            fprintf(logfile, "direct store...\n");#endif        /* Direct-store segment : absolutely *BUGGY* for now */        switch (type) {        case ACCESS_INT:            /* Integer load/store : only access allowed */            break;        case ACCESS_CODE:            /* No code fetch is allowed in direct-store areas */            return -4;        case ACCESS_FLOAT:            /* Floating point load/store */            return -4;        case ACCESS_RES:            /* lwarx, ldarx or srwcx. */            return -4;        case ACCESS_CACHE:            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */            /* Should make the instruction do no-op.             * As it already do no-op, it's quite easy :-)             */            ctx->raddr = eaddr;            return 0;        case ACCESS_EXT:            /* eciwx or ecowx */            return -4;        default:            if (logfile) {                fprintf(logfile, "ERROR: instruction should not need "                        "address translation\n");            }            return -4;        }        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {            ctx->raddr = eaddr;            ret = 2;        } else {            ret = -2;        }    }    return ret;}/* Generic TLB check function for embedded PowerPC implementations */static always_inline int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,                                           target_phys_addr_t *raddrp,                                           target_ulong address,                                           uint32_t pid, int ext, int i){    target_ulong mask;    /* Check valid flag */    if (!(tlb->prot & PAGE_VALID)) {        if (loglevel != 0)            fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);        return -1;    }    mask = ~(tlb->size - 1);#if defined (DEBUG_SOFTWARE_TLB)    if (loglevel != 0) {        fprintf(logfile, "%s: TLB %d address " ADDRX " PID %u <=> " ADDRX                " " ADDRX " %u\n",                __func__, i, address, pid, tlb->EPN, mask, (uint32_t)tlb->PID);    }#endif    /* Check PID */    if (tlb->PID != 0 && tlb->PID != pid)        return -1;    /* Check effective address */    if ((address & mask) != tlb->EPN)        return -1;    *raddrp = (tlb->RPN & mask) | (address & ~mask);#if (TARGET_PHYS_ADDR_BITS >= 36)    if (ext) {        /* Extend the physical address to 36 bits */        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;    }#endif    return 0;}/* Generic TLB search function for PowerPC embedded implementations */int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid){    ppcemb_tlb_t *tlb;    target_phys_addr_t raddr;    int i, ret;    /* Default return value is no match */    ret = -1;    for (i = 0; i < env->nb_tlb; i++) {        tlb = &env->tlb[i].tlbe;        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {            ret = i;            break;        }    }    return ret;}/* Helpers specific to PowerPC 40x implementations */static always_inline void ppc4xx_tlb_invalidate_all (CPUState *env){    ppcemb_tlb_t *tlb;    int i;    for (i = 0; i < env->nb_tlb; i++) {        tlb = &env->tlb[i].tlbe;        tlb->prot &= ~PAGE_VALID;    }    tlb_flush(env, 1);}static always_inline void ppc4xx_tlb_invalidate_virt (CPUState *env,                                                      target_ulong eaddr,                                                      uint32_t pid){#if !defined(FLUSH_ALL_TLBS)    ppcemb_tlb_t *tlb;    target_phys_addr_t raddr;    target_ulong page, end;    int i;    for (i = 0; i < env->nb_tlb; i++) {        tlb = &env->tlb[i].tlbe;        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {            end = tlb->EPN + tlb->size;            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)                tlb_flush_page(env, page);            tlb->prot &= ~PAGE_VALID;            break;        }    }#else    ppc4xx_tlb_invalidate_all(env);#endif}int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,                                 target_ulong address, int rw, int access_type){    ppcemb_tlb_t *tlb;    target_phys_addr_t raddr;    int i, ret, zsel, zpr, pr;	printf("mmu40x_get_physical_address\n");//debugger    ret = -1;    raddr = (target_phys_addr_t)-1ULL;    pr = msr_pr;    for (i = 0; i < env->nb_tlb; i++) {        tlb = &env->tlb[i].tlbe;        if (ppcemb_tlb_check(env, tlb, &raddr, address,                             env->spr[SPR_40x_PID], 0, i) < 0)            continue;        zsel = (tlb->attr >> 4) & 0xF;        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;#if defined (DEBUG_SOFTWARE_TLB)        if (loglevel != 0) {            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",                    __func__, i, zsel, zpr, rw, tlb->attr);        }#endif        /* Check execute enable bit */        switch (zpr) {        case 0x2:            if (pr != 0)                goto check_perms;            /* No break here */        case 0x3:            /* All accesses granted */            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -