mmu_common.c (da5c1d20e9d63575cb358158895a0efa55682c35) mmu_common.c (aa781c102a445e1007a307a972fed24c66b9c24c)
1/*
2 * PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
3 *
4 * Copyright (c) 2003-2007 Jocelyn Mayer
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either

--- 77 unchanged lines hidden (view full) ---

86 nr += env->nb_tlb;
87 }
88
89 return nr;
90}
91
92/* Software driven TLB helpers */
93
1/*
2 * PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
3 *
4 * Copyright (c) 2003-2007 Jocelyn Mayer
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either

--- 77 unchanged lines hidden (view full) ---

86 nr += env->nb_tlb;
87 }
88
89 return nr;
90}
91
92/* Software driven TLB helpers */
93
94static int ppc6xx_tlb_check(CPUPPCState *env,
95 mmu_ctx_t *ctx, target_ulong eaddr,
96 MMUAccessType access_type, target_ulong ptem,
97 bool key, bool nx)
94static int ppc6xx_tlb_check(CPUPPCState *env, hwaddr *raddr, int *prot,
95 target_ulong eaddr, MMUAccessType access_type,
96 target_ulong ptem, bool key, bool nx)
98{
99 ppc6xx_tlb_t *tlb;
100 target_ulong *pte1p;
101 int nr, best, way, ret;
102 bool is_code = (access_type == MMU_INST_FETCH);
103
104 /* Initialize real address with an invalid value */
97{
98 ppc6xx_tlb_t *tlb;
99 target_ulong *pte1p;
100 int nr, best, way, ret;
101 bool is_code = (access_type == MMU_INST_FETCH);
102
103 /* Initialize real address with an invalid value */
105 ctx->raddr = (hwaddr)-1ULL;
104 *raddr = (hwaddr)-1ULL;
106 best = -1;
107 ret = -1; /* No TLB found */
108 for (way = 0; way < env->nb_ways; way++) {
109 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
110 tlb = &env->tlb.tlb6[nr];
111 /* This test "emulates" the PTE index match for hardware TLBs */
112 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
113 qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx

--- 11 unchanged lines hidden (view full) ---

125 access_type == MMU_DATA_STORE ? 'S' : 'L',
126 access_type == MMU_INST_FETCH ? 'I' : 'D');
127 /* Check validity and table match */
128 if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 ||
129 (tlb->pte0 & PTE_PTEM_MASK) != ptem) {
130 continue;
131 }
132 /* all matches should have equal RPN, WIMG & PP */
105 best = -1;
106 ret = -1; /* No TLB found */
107 for (way = 0; way < env->nb_ways; way++) {
108 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
109 tlb = &env->tlb.tlb6[nr];
110 /* This test "emulates" the PTE index match for hardware TLBs */
111 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
112 qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx

--- 11 unchanged lines hidden (view full) ---

124 access_type == MMU_DATA_STORE ? 'S' : 'L',
125 access_type == MMU_INST_FETCH ? 'I' : 'D');
126 /* Check validity and table match */
127 if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 ||
128 (tlb->pte0 & PTE_PTEM_MASK) != ptem) {
129 continue;
130 }
131 /* all matches should have equal RPN, WIMG & PP */
133 if (ctx->raddr != (hwaddr)-1ULL &&
134 (ctx->raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) {
132 if (*raddr != (hwaddr)-1ULL &&
133 (*raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) {
135 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
136 /* TLB inconsistency */
137 continue;
138 }
139 /* Keep the matching PTE information */
140 best = nr;
134 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
135 /* TLB inconsistency */
136 continue;
137 }
138 /* Keep the matching PTE information */
139 best = nr;
141 ctx->raddr = tlb->pte1;
142 ctx->prot = ppc_hash32_prot(key, tlb->pte1 & HPTE32_R_PP, nx);
143 if (check_prot_access_type(ctx->prot, access_type)) {
140 *raddr = tlb->pte1;
141 *prot = ppc_hash32_prot(key, tlb->pte1 & HPTE32_R_PP, nx);
142 if (check_prot_access_type(*prot, access_type)) {
144 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
145 ret = 0;
146 break;
147 } else {
148 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
149 ret = -2;
150 }
151 }
152 if (best != -1) {
153 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
154 " prot=%01x ret=%d\n",
143 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
144 ret = 0;
145 break;
146 } else {
147 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
148 ret = -2;
149 }
150 }
151 if (best != -1) {
152 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
153 " prot=%01x ret=%d\n",
155 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
154 *raddr & TARGET_PAGE_MASK, *prot, ret);
156 /* Update page flags */
157 pte1p = &env->tlb.tlb6[best].pte1;
158 *pte1p |= 0x00000100; /* Update accessed flag */
159 if (!(*pte1p & 0x00000080)) {
160 if (access_type == MMU_DATA_STORE && ret == 0) {
161 /* Update changed flag */
162 *pte1p |= 0x00000080;
163 } else {
164 /* Force page fault for first write access */
155 /* Update page flags */
156 pte1p = &env->tlb.tlb6[best].pte1;
157 *pte1p |= 0x00000100; /* Update accessed flag */
158 if (!(*pte1p & 0x00000080)) {
159 if (access_type == MMU_DATA_STORE && ret == 0) {
160 /* Update changed flag */
161 *pte1p |= 0x00000080;
162 } else {
163 /* Force page fault for first write access */
165 ctx->prot &= ~PAGE_WRITE;
164 *prot &= ~PAGE_WRITE;
166 }
167 }
168 }
169 if (ret == -1) {
170 int r = is_code ? SPR_ICMP : SPR_DCMP;
171 env->spr[r] = ptem;
172 }
173#if defined(DUMP_PAGE_TABLES)

--- 165 unchanged lines hidden (view full) ---

339 }
340 /* Page address translation */
341 qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
342 HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
343 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
344 *hashp = hash;
345
346 /* Software TLB search */
165 }
166 }
167 }
168 if (ret == -1) {
169 int r = is_code ? SPR_ICMP : SPR_DCMP;
170 env->spr[r] = ptem;
171 }
172#if defined(DUMP_PAGE_TABLES)

--- 165 unchanged lines hidden (view full) ---

338 }
339 /* Page address translation */
340 qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
341 HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
342 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
343 *hashp = hash;
344
345 /* Software TLB search */
347 return ppc6xx_tlb_check(env, ctx, eaddr, access_type, ptem, key, nx);
346 return ppc6xx_tlb_check(env, &ctx->raddr, &ctx->prot, eaddr,
347 access_type, ptem, key, nx);
348 }
349
350 /* Direct-store segment : absolutely *BUGGY* for now */
351 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
352 switch (type) {
353 case ACCESS_INT:
354 /* Integer load/store : only access allowed */
355 break;

--- 552 unchanged lines hidden ---
348 }
349
350 /* Direct-store segment : absolutely *BUGGY* for now */
351 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
352 switch (type) {
353 case ACCESS_INT:
354 /* Integer load/store : only access allowed */
355 break;

--- 552 unchanged lines hidden ---