Message ID | 20211220214135.189157-4-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | linux-user: prctl improvements | expand |
On 12/20/21 22:41, Richard Henderson wrote: > This requires extra work for each target, but adds the > common syscall code, and the necessary flag in CPUState. > > Reviewed-by: Warner Losh <imp@bsdimp.com> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > include/hw/core/cpu.h | 3 +++ > linux-user/generic/target_prctl_unalign.h | 27 +++++++++++++++++++++++ > cpu.c | 20 ++++++++++++----- > linux-user/syscall.c | 13 +++++++++-- > 4 files changed, 56 insertions(+), 7 deletions(-) > create mode 100644 linux-user/generic/target_prctl_unalign.h > > diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h > index e948e81f1a..76ab3b851c 100644 > --- a/include/hw/core/cpu.h > +++ b/include/hw/core/cpu.h > @@ -413,6 +413,9 @@ struct CPUState { > > bool ignore_memory_transaction_failures; > > + /* Used for user-only emulation of prctl(PR_SET_UNALIGN). */ > + bool prctl_unalign_sigbus; Could we forward-declare a UserEmuCPUState structure in this file, use it here: struct UserEmuCPUState *user_cpu; and declare it in include/hw/core/useremu-cpu.h (or better name) restricted to user emulation? I'd rather not mix sys/user emu specific fields in CPUState. Can be done later of course, so: Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Le 20/12/2021 à 22:41, Richard Henderson a écrit : > This requires extra work for each target, but adds the > common syscall code, and the necessary flag in CPUState. > > Reviewed-by: Warner Losh <imp@bsdimp.com> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > include/hw/core/cpu.h | 3 +++ > linux-user/generic/target_prctl_unalign.h | 27 +++++++++++++++++++++++ > cpu.c | 20 ++++++++++++----- > linux-user/syscall.c | 13 +++++++++-- > 4 files changed, 56 insertions(+), 7 deletions(-) > create mode 100644 linux-user/generic/target_prctl_unalign.h > Reviewed-by: Laurent Vivier <laurent@vivier.eu>
On 12/20/21 2:31 PM, Philippe Mathieu-Daudé wrote: >> + /* Used for user-only emulation of prctl(PR_SET_UNALIGN). */ >> + bool prctl_unalign_sigbus; > > Could we forward-declare a UserEmuCPUState structure in this file, > use it here: > > struct UserEmuCPUState *user_cpu; > > and declare it in include/hw/core/useremu-cpu.h (or better name) > restricted to user emulation? Eh. I suppose we could, but at the moment it's one byte in an existing padding hole. > I'd rather not mix sys/user emu specific fields in CPUState. There are *lots* of system specific fields in CPUState. r~
Hi Richard, (revisiting this old patch.) On 20/12/21 22:41, Richard Henderson wrote: > This requires extra work for each target, but adds the > common syscall code, and the necessary flag in CPUState. > > Reviewed-by: Warner Losh <imp@bsdimp.com> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > include/hw/core/cpu.h | 3 +++ > linux-user/generic/target_prctl_unalign.h | 27 +++++++++++++++++++++++ > cpu.c | 20 ++++++++++++----- > linux-user/syscall.c | 13 +++++++++-- > 4 files changed, 56 insertions(+), 7 deletions(-) > create mode 100644 linux-user/generic/target_prctl_unalign.h > > diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h > index e948e81f1a..76ab3b851c 100644 > --- a/include/hw/core/cpu.h > +++ b/include/hw/core/cpu.h > @@ -413,6 +413,9 @@ struct CPUState { > > bool ignore_memory_transaction_failures; > > + /* Used for user-only emulation of prctl(PR_SET_UNALIGN). */ > + bool prctl_unalign_sigbus; > + > struct hax_vcpu_state *hax_vcpu; > > struct hvf_vcpu_state *hvf; > diff --git a/linux-user/generic/target_prctl_unalign.h b/linux-user/generic/target_prctl_unalign.h > new file mode 100644 > index 0000000000..bc3b83af2a > --- /dev/null > +++ b/linux-user/generic/target_prctl_unalign.h > @@ -0,0 +1,27 @@ > +/* > + * Generic prctl unalign functions for linux-user > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > +#ifndef GENERIC_TARGET_PRCTL_UNALIGN_H > +#define GENERIC_TARGET_PRCTL_UNALIGN_H > + > +static abi_long do_prctl_get_unalign(CPUArchState *env, target_long arg2) > +{ > + CPUState *cs = env_cpu(env); > + uint32_t res = PR_UNALIGN_NOPRINT; > + if (cs->prctl_unalign_sigbus) { > + res |= PR_UNALIGN_SIGBUS; > + } > + return put_user_u32(res, arg2); > +} > +#define do_prctl_get_unalign do_prctl_get_unalign > + > +static abi_long do_prctl_set_unalign(CPUArchState *env, target_long arg2) > +{ > + env_cpu(env)->prctl_unalign_sigbus = arg2 & PR_UNALIGN_SIGBUS; > + return 0; > +} > +#define do_prctl_set_unalign do_prctl_set_unalign > + > +#endif /* GENERIC_TARGET_PRCTL_UNALIGN_H */ > diff --git a/cpu.c b/cpu.c > index 945dd3dded..016bf06a1a 100644 > --- a/cpu.c > +++ b/cpu.c > @@ -174,13 +174,23 @@ void cpu_exec_unrealizefn(CPUState *cpu) > cpu_list_remove(cpu); > } > > +/* > + * This can't go in hw/core/cpu.c because that file is compiled only > + * once for both user-mode and system builds. > + */ > static Property cpu_common_props[] = { > -#ifndef CONFIG_USER_ONLY > +#ifdef CONFIG_USER_ONLY > /* > - * Create a memory property for softmmu CPU object, > - * so users can wire up its memory. (This can't go in hw/core/cpu.c > - * because that file is compiled only once for both user-mode > - * and system builds.) The default if no link is set up is to use > + * Create a property for the user-only object, so users can > + * adjust prctl(PR_SET_UNALIGN) from the command-line. How can I test this per-thread property? Shouldn't this be an accel (TCG/user) property, for all threads? > + * Has no effect if the target does not support the feature. > + */ > + DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState, > + prctl_unalign_sigbus, false), > +#else > + /* > + * Create a memory property for softmmu CPU object, so users can > + * wire up its memory. The default if no link is set up is to use > * the system address space. > */ > DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION, > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index ef7a955dbb..3f481eb5b2 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -6377,6 +6377,12 @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2) > #ifndef do_prctl_get_tagged_addr_ctrl > #define do_prctl_get_tagged_addr_ctrl do_prctl_inval0 > #endif > +#ifndef do_prctl_get_unalign > +#define do_prctl_get_unalign do_prctl_inval1 > +#endif > +#ifndef do_prctl_set_unalign > +#define do_prctl_set_unalign do_prctl_inval1 > +#endif > > static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, > abi_long arg3, abi_long arg4, abi_long arg5) > @@ -6440,6 +6446,11 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, > } > return do_prctl_get_tagged_addr_ctrl(env); > > + case PR_GET_UNALIGN: > + return do_prctl_get_unalign(env, arg2); > + case PR_SET_UNALIGN: > + return do_prctl_set_unalign(env, arg2); > + > case PR_GET_DUMPABLE: > case PR_SET_DUMPABLE: > case PR_GET_KEEPCAPS: > @@ -6482,8 +6493,6 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, > case PR_SET_THP_DISABLE: > case PR_GET_TSC: > case PR_SET_TSC: > - case PR_GET_UNALIGN: > - case PR_SET_UNALIGN: > default: > /* Disable to prevent the target disabling stuff we need. */ > return -TARGET_EINVAL;
On 1/9/24 04:15, Philippe Mathieu-Daudé wrote: >> +/* >> + * This can't go in hw/core/cpu.c because that file is compiled only >> + * once for both user-mode and system builds. >> + */ >> static Property cpu_common_props[] = { >> -#ifndef CONFIG_USER_ONLY >> +#ifdef CONFIG_USER_ONLY >> /* >> - * Create a memory property for softmmu CPU object, >> - * so users can wire up its memory. (This can't go in hw/core/cpu.c >> - * because that file is compiled only once for both user-mode >> - * and system builds.) The default if no link is set up is to use >> + * Create a property for the user-only object, so users can >> + * adjust prctl(PR_SET_UNALIGN) from the command-line. > > How can I test this per-thread property? -cpu foo,prctl-unalign-sigbus=true > Shouldn't this be an accel (TCG/user) property, for all threads? There is always one cpu at user-only startup, and it is copied on clone. Logically it would be a kernel property, since it's something the kernel does, not the cpu. But cpu vs accel makes no difference to me; it was just easy here. IIRC, this is simply a proxy for not really being able to inherit this bit across fork+exec like you can with the real kernel. r~
On 8/1/24 22:13, Richard Henderson wrote: > On 1/9/24 04:15, Philippe Mathieu-Daudé wrote: >>> +/* >>> + * This can't go in hw/core/cpu.c because that file is compiled only >>> + * once for both user-mode and system builds. >>> + */ >>> static Property cpu_common_props[] = { >>> -#ifndef CONFIG_USER_ONLY >>> +#ifdef CONFIG_USER_ONLY >>> /* >>> - * Create a memory property for softmmu CPU object, >>> - * so users can wire up its memory. (This can't go in hw/core/cpu.c >>> - * because that file is compiled only once for both user-mode >>> - * and system builds.) The default if no link is set up is to use >>> + * Create a property for the user-only object, so users can >>> + * adjust prctl(PR_SET_UNALIGN) from the command-line. >> >> How can I test this per-thread property? > > -cpu foo,prctl-unalign-sigbus=true > > >> Shouldn't this be an accel (TCG/user) property, for all threads? > > There is always one cpu at user-only startup, and it is copied on clone. > > Logically it would be a kernel property, since it's something the kernel > does, not the cpu. But cpu vs accel makes no difference to me; it was > just easy here. Can a process started with prctl(PR_SET_UNALIGN) unset it before forking? "kernel property" as "accel property" works for me. > IIRC, this is simply a proxy for not really being able to inherit this > bit across fork+exec like you can with the real kernel. > > > r~
On 1/9/24 10:21, Philippe Mathieu-Daudé wrote: > On 8/1/24 22:13, Richard Henderson wrote: >> On 1/9/24 04:15, Philippe Mathieu-Daudé wrote: >>>> +/* >>>> + * This can't go in hw/core/cpu.c because that file is compiled only >>>> + * once for both user-mode and system builds. >>>> + */ >>>> static Property cpu_common_props[] = { >>>> -#ifndef CONFIG_USER_ONLY >>>> +#ifdef CONFIG_USER_ONLY >>>> /* >>>> - * Create a memory property for softmmu CPU object, >>>> - * so users can wire up its memory. (This can't go in hw/core/cpu.c >>>> - * because that file is compiled only once for both user-mode >>>> - * and system builds.) The default if no link is set up is to use >>>> + * Create a property for the user-only object, so users can >>>> + * adjust prctl(PR_SET_UNALIGN) from the command-line. >>> >>> How can I test this per-thread property? >> >> -cpu foo,prctl-unalign-sigbus=true >> >> >>> Shouldn't this be an accel (TCG/user) property, for all threads? >> >> There is always one cpu at user-only startup, and it is copied on clone. >> >> Logically it would be a kernel property, since it's something the kernel does, not the >> cpu. But cpu vs accel makes no difference to me; it was just easy here. > > Can a process started with prctl(PR_SET_UNALIGN) unset it before > forking? Yes. > "kernel property" as "accel property" works for me. Does it really matter though, especially now that the cpu property has been present for two years now. r~
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index e948e81f1a..76ab3b851c 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -413,6 +413,9 @@ struct CPUState { bool ignore_memory_transaction_failures; + /* Used for user-only emulation of prctl(PR_SET_UNALIGN). */ + bool prctl_unalign_sigbus; + struct hax_vcpu_state *hax_vcpu; struct hvf_vcpu_state *hvf; diff --git a/linux-user/generic/target_prctl_unalign.h b/linux-user/generic/target_prctl_unalign.h new file mode 100644 index 0000000000..bc3b83af2a --- /dev/null +++ b/linux-user/generic/target_prctl_unalign.h @@ -0,0 +1,27 @@ +/* + * Generic prctl unalign functions for linux-user + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef GENERIC_TARGET_PRCTL_UNALIGN_H +#define GENERIC_TARGET_PRCTL_UNALIGN_H + +static abi_long do_prctl_get_unalign(CPUArchState *env, target_long arg2) +{ + CPUState *cs = env_cpu(env); + uint32_t res = PR_UNALIGN_NOPRINT; + if (cs->prctl_unalign_sigbus) { + res |= PR_UNALIGN_SIGBUS; + } + return put_user_u32(res, arg2); +} +#define do_prctl_get_unalign do_prctl_get_unalign + +static abi_long do_prctl_set_unalign(CPUArchState *env, target_long arg2) +{ + env_cpu(env)->prctl_unalign_sigbus = arg2 & PR_UNALIGN_SIGBUS; + return 0; +} +#define do_prctl_set_unalign do_prctl_set_unalign + +#endif /* GENERIC_TARGET_PRCTL_UNALIGN_H */ diff --git a/cpu.c b/cpu.c index 945dd3dded..016bf06a1a 100644 --- a/cpu.c +++ b/cpu.c @@ -174,13 +174,23 @@ void cpu_exec_unrealizefn(CPUState *cpu) cpu_list_remove(cpu); } +/* + * This can't go in hw/core/cpu.c because that file is compiled only + * once for both user-mode and system builds. + */ static Property cpu_common_props[] = { -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_USER_ONLY /* - * Create a memory property for softmmu CPU object, - * so users can wire up its memory. (This can't go in hw/core/cpu.c - * because that file is compiled only once for both user-mode - * and system builds.) The default if no link is set up is to use + * Create a property for the user-only object, so users can + * adjust prctl(PR_SET_UNALIGN) from the command-line. + * Has no effect if the target does not support the feature. + */ + DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState, + prctl_unalign_sigbus, false), +#else + /* + * Create a memory property for softmmu CPU object, so users can + * wire up its memory. The default if no link is set up is to use * the system address space. */ DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION, diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ef7a955dbb..3f481eb5b2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6377,6 +6377,12 @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2) #ifndef do_prctl_get_tagged_addr_ctrl #define do_prctl_get_tagged_addr_ctrl do_prctl_inval0 #endif +#ifndef do_prctl_get_unalign +#define do_prctl_get_unalign do_prctl_inval1 +#endif +#ifndef do_prctl_set_unalign +#define do_prctl_set_unalign do_prctl_inval1 +#endif static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) @@ -6440,6 +6446,11 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, } return do_prctl_get_tagged_addr_ctrl(env); + case PR_GET_UNALIGN: + return do_prctl_get_unalign(env, arg2); + case PR_SET_UNALIGN: + return do_prctl_set_unalign(env, arg2); + case PR_GET_DUMPABLE: case PR_SET_DUMPABLE: case PR_GET_KEEPCAPS: @@ -6482,8 +6493,6 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, case PR_SET_THP_DISABLE: case PR_GET_TSC: case PR_SET_TSC: - case PR_GET_UNALIGN: - case PR_SET_UNALIGN: default: /* Disable to prevent the target disabling stuff we need. */ return -TARGET_EINVAL;