From: Keith Packard Date: Tue, 24 Jan 2023 18:01:15 +0000 (+0000) Subject: semihosting: Write back semihosting data before completion callback X-Git-Tag: v8.0.0-rc0~80^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=978c2bf97b2f8b0938dc6570c46275ed8d8e96f8;p=thirdparty%2Fqemu.git semihosting: Write back semihosting data before completion callback 'lock_user' allocates a host buffer to shadow a target buffer, 'unlock_user' copies that host buffer back to the target and frees the host memory. If the completion function uses the target buffer, it must be called after unlock_user to ensure the data are present. This caused the arm-compatible TARGET_SYS_READC to fail as the completion function, common_semi_readc_cb, pulled data from the target buffer which would not have been gotten the console data. I decided to fix all instances of this pattern instead of just the console_read function to make things consistent and potentially fix bugs in other cases. Signed-off-by: Keith Packard Reviewed-by: Richard Henderson Message-Id: <20221012014822.1242170-1-keithp@keithp.com> Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20230124180127.1881110-24-alex.bennee@linaro.org> --- diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c index 5893c760c5f..ba28194b59a 100644 --- a/semihosting/syscalls.c +++ b/semihosting/syscalls.c @@ -319,11 +319,11 @@ static void host_read(CPUState *cs, gdb_syscall_complete_cb complete, } ret = RETRY_ON_EINTR(read(gf->hostfd, ptr, len)); if (ret == -1) { - complete(cs, -1, errno); unlock_user(ptr, buf, 0); + complete(cs, -1, errno); } else { - complete(cs, ret, 0); unlock_user(ptr, buf, ret); + complete(cs, ret, 0); } } @@ -339,8 +339,8 @@ static void host_write(CPUState *cs, gdb_syscall_complete_cb complete, return; } ret = write(gf->hostfd, ptr, len); - complete(cs, ret, ret == -1 ? errno : 0); unlock_user(ptr, buf, 0); + complete(cs, ret, ret == -1 ? errno : 0); } static void host_lseek(CPUState *cs, gdb_syscall_complete_cb complete, @@ -426,8 +426,8 @@ static void host_stat(CPUState *cs, gdb_syscall_complete_cb complete, ret = -1; } } - complete(cs, ret, err); unlock_user(name, fname, 0); + complete(cs, ret, err); } static void host_remove(CPUState *cs, gdb_syscall_complete_cb complete, @@ -444,8 +444,8 @@ static void host_remove(CPUState *cs, gdb_syscall_complete_cb complete, } ret = remove(p); - complete(cs, ret, ret ? errno : 0); unlock_user(p, fname, 0); + complete(cs, ret, ret ? errno : 0); } static void host_rename(CPUState *cs, gdb_syscall_complete_cb complete, @@ -469,9 +469,9 @@ static void host_rename(CPUState *cs, gdb_syscall_complete_cb complete, } ret = rename(ostr, nstr); - complete(cs, ret, ret ? errno : 0); unlock_user(ostr, oname, 0); unlock_user(nstr, nname, 0); + complete(cs, ret, ret ? errno : 0); } static void host_system(CPUState *cs, gdb_syscall_complete_cb complete, @@ -488,8 +488,8 @@ static void host_system(CPUState *cs, gdb_syscall_complete_cb complete, } ret = system(p); - complete(cs, ret, ret == -1 ? errno : 0); unlock_user(p, cmd, 0); + complete(cs, ret, ret == -1 ? errno : 0); } static void host_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete, @@ -554,8 +554,8 @@ static void staticfile_read(CPUState *cs, gdb_syscall_complete_cb complete, } memcpy(ptr, gf->staticfile.data + gf->staticfile.off, len); gf->staticfile.off += len; - complete(cs, len, 0); unlock_user(ptr, buf, len); + complete(cs, len, 0); } static void staticfile_lseek(CPUState *cs, gdb_syscall_complete_cb complete, @@ -608,8 +608,8 @@ static void console_read(CPUState *cs, gdb_syscall_complete_cb complete, return; } ret = qemu_semihosting_console_read(cs, ptr, len); - complete(cs, ret, 0); unlock_user(ptr, buf, ret); + complete(cs, ret, 0); } static void console_write(CPUState *cs, gdb_syscall_complete_cb complete, @@ -624,8 +624,8 @@ static void console_write(CPUState *cs, gdb_syscall_complete_cb complete, return; } ret = qemu_semihosting_console_write(ptr, len); - complete(cs, ret ? ret : -1, ret ? 0 : EIO); unlock_user(ptr, buf, 0); + complete(cs, ret ? ret : -1, ret ? 0 : EIO); } static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete,