diff options
| author | Thomas Huth | 2016-04-14 17:14:53 +0200 |
|---|---|---|
| committer | David Gibson | 2016-04-18 07:14:38 +0200 |
| commit | 537d3e8e6beea9a0fbd6469eb38450e718244dad (patch) | |
| tree | 89b8bd2b951197ebc8d5500168518422f41cb6ae /target-ppc | |
| parent | ppc: Fix the range check in the LSWI instruction (diff) | |
| download | qemu-537d3e8e6beea9a0fbd6469eb38450e718244dad.tar.gz qemu-537d3e8e6beea9a0fbd6469eb38450e718244dad.tar.xz qemu-537d3e8e6beea9a0fbd6469eb38450e718244dad.zip | |
ppc: Fix the bad exception NIP value and the range check in LSWX
The range checks in the LSWX instruction are completely insufficient:
They do not take the wrap-around case into account, and the check
"reg < rx" should be "reg <= rx" instead. Fix it by using the new
lsw_reg_in_range() helper function that is already used for LSWI, too.
Then there is a second problem: In case the INVAL exception is generated,
the NIP value is wrong, it currently points to the instruction before
the LSWX instruction. This is because gen_lswx() already decreases the
NIP value by 4 (to be prepared for page fault exceptions), and
powerpc_excp() later decreases it again by 4 while handling the program
exception. So to get this right, we've got to undo the "- 4" from
gen_lswx() here before calling helper_raise_exception_err().
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target-ppc')
| -rw-r--r-- | target-ppc/mem_helper.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c index 581d9faa23..6d584c9126 100644 --- a/target-ppc/mem_helper.c +++ b/target-ppc/mem_helper.c @@ -102,8 +102,9 @@ void helper_lswx(CPUPPCState *env, target_ulong addr, uint32_t reg, { if (likely(xer_bc != 0)) { int num_used_regs = (xer_bc + 3) / 4; - if (unlikely((ra != 0 && reg < ra && (reg + num_used_regs) > ra) || - (reg < rb && (reg + num_used_regs) > rb))) { + if (unlikely((ra != 0 && lsw_reg_in_range(reg, num_used_regs, ra)) || + lsw_reg_in_range(reg, num_used_regs, rb))) { + env->nip += 4; /* Compensate the "nip - 4" from gen_lswx() */ helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX); |
