mmu-hash32: Split out handling of direct store segments

At present a large chunk of ppc_hash32_translate() is taken up with an
ugly if selecting between direct store segments (hardly ever used) and
normal paged segments.  This patch clarifies the flow of code by
handling direct store segments immediately then returning, leaving the
straight line code to describe the normal MMU path.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
David Gibson 2013-03-12 00:31:24 +00:00 committed by Alexander Graf
parent 65d61643d0
commit 4b9605a5b1
1 changed files with 78 additions and 78 deletions

View File

@ -381,7 +381,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
{
hwaddr hash;
target_ulong vsid;
int ds, pr, target_page_bits;
int pr, target_page_bits;
int ret, ret2;
target_ulong sr, pgidx;
@ -401,12 +401,69 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
}
}
pr = msr_pr;
/* 3. Look up the Segment Register */
sr = env->sr[eaddr >> 28];
pr = msr_pr;
ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
ds = !!(sr & SR32_T);
/* 4. Handle direct store segments */
if (sr & SR32_T) {
LOG_MMU("direct store...\n");
/* Direct-store segment : absolutely *BUGGY* for now */
/* Direct-store implies a 32-bit MMU.
* Check the Segment Register's bus unit ID (BUID).
*/
if ((sr & 0x1FF00000) >> 20 == 0x07f) {
/* Memory-forced I/O controller interface access */
/* If T=1 and BUID=x'07F', the 601 performs a memory access
* to SR[28-31] LA[4-31], bypassing all protection mechanisms.
*/
ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return 0;
}
if (rwx == 2) {
/* No code fetch is allowed in direct-store areas */
return -4;
}
switch (env->access_type) {
case ACCESS_INT:
/* Integer load/store : only access allowed */
break;
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:
qemu_log("ERROR: instruction should not need "
"address translation\n");
return -4;
}
if ((rwx == 1 || ctx->key != 1) && (rwx == 0 || ctx->key != 0)) {
ctx->raddr = eaddr;
return 2;
} else {
return -2;
}
}
ctx->nx = !!(sr & SR32_NX);
vsid = sr & SR32_VSID;
target_page_bits = TARGET_PAGE_BITS;
@ -419,10 +476,10 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
hash = vsid ^ pgidx;
ctx->ptem = (vsid << 7) | (pgidx >> 10);
LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
ctx->key, ds, ctx->nx, vsid);
LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
ctx->key, ctx->nx, vsid);
ret = -1;
if (!ds) {
/* Check if instruction fetch is allowed, if needed */
if (rwx != 2 || ctx->nx == 0) {
/* Page address translation */
@ -476,63 +533,6 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
LOG_MMU("No access allowed\n");
ret = -3;
}
} else {
target_ulong sr;
LOG_MMU("direct store...\n");
/* Direct-store segment : absolutely *BUGGY* for now */
/* Direct-store implies a 32-bit MMU.
* Check the Segment Register's bus unit ID (BUID).
*/
sr = env->sr[eaddr >> 28];
if ((sr & 0x1FF00000) >> 20 == 0x07f) {
/* Memory-forced I/O controller interface access */
/* If T=1 and BUID=x'07F', the 601 performs a memory access
* to SR[28-31] LA[4-31], bypassing all protection mechanisms.
*/
ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return 0;
}
if (rwx == 2) {
/* No code fetch is allowed in direct-store areas */
return -4;
}
switch (env->access_type) {
case ACCESS_INT:
/* Integer load/store : only access allowed */
break;
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:
qemu_log("ERROR: instruction should not need "
"address translation\n");
return -4;
}
if ((rwx == 1 || ctx->key != 1) && (rwx == 0 || ctx->key != 0)) {
ctx->raddr = eaddr;
ret = 2;
} else {
ret = -2;
}
}
return ret;
}