aboutsummaryrefslogtreecommitdiff
path: root/linux-user/main.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-05-12 18:47:43 +0100
committerRiku Voipio <riku.voipio@linaro.org>2016-05-27 14:49:50 +0300
commitd7749ab770601258be7ae862b5827c42bb35e44c (patch)
tree9bc9c6149d3be9c77676a83d60cd8ad6cba510d3 /linux-user/main.c
parenta9175169cc55ecff23a158dfee7d9cbb0b75d185 (diff)
linux-user: Set r14 on exit from microblaze syscall
All syscall exits on microblaze result in r14 being equal to the PC we return to, because the kernel syscall exit instruction "rtbd" does this. (This is true even for sigreturn(); note that r14 is not a userspace-usable register as the kernel may clobber it at any point.) Emulate the setting of r14 on exit; this isn't really a guest visible change for valid guest code because r14 isn't reliably observable anyway. However having the code and the comment helps to explain why it's ok for the ERESTARTSYS handling not to undo the changes to r14 that happen on syscall entry. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Diffstat (limited to 'linux-user/main.c')
-rw-r--r--linux-user/main.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 4607e48278..c5da418fa4 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2983,6 +2983,13 @@ void cpu_loop(CPUMBState *env)
env->regs[10],
0, 0);
env->regs[3] = ret;
+ /* All syscall exits result in guest r14 being equal to the
+ * PC we return to, because the kernel syscall exit "rtbd" does
+ * this. (This is true even for sigreturn(); note that r14 is
+ * not a userspace-usable register, as the kernel may clobber it
+ * at any point.)
+ */
+ env->regs[14] = env->sregs[SR_PC];
break;
case EXCP_HW_EXCP:
env->regs[17] = env->sregs[SR_PC] + 4;