aboutsummaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-07-04 13:06:35 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-07-04 13:06:35 +0100
commitf5666418c449b49917ea24cdb0bed76a602a3c74 (patch)
treea26c728db9e1b08f9a4436f6f5d33341173a158b /target-arm
parentd317091d5ed616328ef5a7b8502167c4e7de8e6b (diff)
target-arm/arm-semi.c: Fix SYS_HEAPINFO for 64-bit guests
SYS_HEAPINFO is one of the few semihosting calls which has to write values back into a parameter block in memory. When we added support for 64-bit semihosting we updated the code which reads from the parameter block to read 64-bit words but forgot to change the code that writes back into the block. Update it to treat the block as a set of words of the appropriate width for the guest. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1466783381-29506-3-git-send-email-peter.maydell@linaro.org
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/arm-semi.c47
1 files changed, 26 insertions, 21 deletions
diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c
index 8be0645eb0..d50726f65d 100644
--- a/target-arm/arm-semi.c
+++ b/target-arm/arm-semi.c
@@ -564,8 +564,10 @@ target_ulong do_arm_semihosting(CPUARMState *env)
}
case TARGET_SYS_HEAPINFO:
{
- uint32_t *ptr;
+ target_ulong retvals[4];
uint32_t limit;
+ int i;
+
GET_ARG(0);
#ifdef CONFIG_USER_ONLY
@@ -587,30 +589,33 @@ target_ulong do_arm_semihosting(CPUARMState *env)
ts->heap_limit = limit;
}
- ptr = lock_user(VERIFY_WRITE, arg0, 16, 0);
- if (!ptr) {
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- }
- ptr[0] = tswap32(ts->heap_base);
- ptr[1] = tswap32(ts->heap_limit);
- ptr[2] = tswap32(ts->stack_base);
- ptr[3] = tswap32(0); /* Stack limit. */
- unlock_user(ptr, arg0, 16);
+ retvals[0] = ts->heap_base;
+ retvals[1] = ts->heap_limit;
+ retvals[2] = ts->stack_base;
+ retvals[3] = 0; /* Stack limit. */
#else
limit = ram_size;
- ptr = lock_user(VERIFY_WRITE, arg0, 16, 0);
- if (!ptr) {
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- }
/* TODO: Make this use the limit of the loaded application. */
- ptr[0] = tswap32(limit / 2);
- ptr[1] = tswap32(limit);
- ptr[2] = tswap32(limit); /* Stack base */
- ptr[3] = tswap32(0); /* Stack limit. */
- unlock_user(ptr, arg0, 16);
+ retvals[0] = limit / 2;
+ retvals[1] = limit;
+ retvals[2] = limit; /* Stack base */
+ retvals[3] = 0; /* Stack limit. */
#endif
+
+ for (i = 0; i < ARRAY_SIZE(retvals); i++) {
+ bool fail;
+
+ if (is_a64(env)) {
+ fail = put_user_u64(retvals[i], arg0 + i * 8);
+ } else {
+ fail = put_user_u32(retvals[i], arg0 + i * 4);
+ }
+
+ if (fail) {
+ /* Couldn't write back to argument block */
+ return -1;
+ }
+ }
return 0;
}
case TARGET_SYS_EXIT: