The context introduced by MSA needs to be saved around signals. However, we can't increase the size of struct sigcontext because that will change the offset of the signal mask in struct sigframe or struct ucontext. This patch instead places the new context immediately after the struct sigframe for traditional signals, or similarly after struct ucontext for RT signals. The layout of struct sigframe & struct ucontext is identical from their sigcontext fields onwards, so the offset from the sigcontext to the extended context will always be the same regardless of the type of signal. Userland will be able to search through the extended context by using the magic values to detect which types of context are present. Any unrecognised context can be skipped over using the size field of struct extcontext. Once the magic value END_EXTCONTEXT_MAGIC is seen it is known that there are no further extended context structures to examine. This approach is somewhat similar to that taken by ARM to save VFP & other context at the end of struct ucontext. Userland can determine whether extended context is present by checking for the USED_EXTCONTEXT bit in the sc_used_math field of struct sigcontext. Whilst this could potentially change the historic semantics of sc_used_math if further extended context which does not imply FP context were to be introduced in the future, I have been unable to find any userland code making use of sc_used_math at all. Using one of the fields described as unused in struct sigcontext was considered, but the kernel does not already write to those fields so there would be no guarantee of the field being clear on older kernels. Other alternatives would be to have userland check the kernel version, or to have a HWCAP bit indicating presence of extended context. However there is a desire to have the context & information required to decode it be self contained such that, for example, debuggers could decode the saved context easily. Signed-off-by: Paul Burton <paul.burton@xxxxxxxxxx> --- arch/mips/include/asm/Kbuild | 1 - arch/mips/include/uapi/asm/sigcontext.h | 3 ++ arch/mips/include/uapi/asm/ucontext.h | 65 +++++++++++++++++++++++++++++++++ arch/mips/kernel/signal.c | 13 +++++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 arch/mips/include/uapi/asm/ucontext.h diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index 526539c..18e8b8d 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -16,6 +16,5 @@ generic-y += sections.h generic-y += segment.h generic-y += serial.h generic-y += trace_clock.h -generic-y += ucontext.h generic-y += user.h generic-y += xor.h diff --git a/arch/mips/include/uapi/asm/sigcontext.h b/arch/mips/include/uapi/asm/sigcontext.h index f28facd..80db06c 100644 --- a/arch/mips/include/uapi/asm/sigcontext.h +++ b/arch/mips/include/uapi/asm/sigcontext.h @@ -21,6 +21,9 @@ /* FR=1, but with odd singles in bits 63:32 of preceding even double */ #define USED_HYBRID_FPRS (1 << 2) +/* extended context was used, see struct extcontext for details */ +#define USED_EXTCONTEXT (1 << 3) + #if _MIPS_SIM == _MIPS_SIM_ABI32 struct sigcontext { diff --git a/arch/mips/include/uapi/asm/ucontext.h b/arch/mips/include/uapi/asm/ucontext.h new file mode 100644 index 0000000..2320144 --- /dev/null +++ b/arch/mips/include/uapi/asm/ucontext.h @@ -0,0 +1,65 @@ +#ifndef __MIPS_UAPI_ASM_UCONTEXT_H +#define __MIPS_UAPI_ASM_UCONTEXT_H + +/** + * struct extcontext - extended context header structure + * @magic: magic value identifying the type of extended context + * @size: the size in bytes of the enclosing structure + * + * Extended context structures provide context which does not fit within struct + * sigcontext. They are placed sequentially in memory at the end of struct + * ucontext and struct sigframe, with each extended context structure beginning + * with a header defined by this struct. The type of context represented is + * indicated by the magic field. Userland may check each extended context + * structure against magic values that it recognises. The size field allows any + * unrecognised context to be skipped, allowing for future expansion. The end + * of the extended context data is indicated by the magic value + * END_EXTCONTEXT_MAGIC. + */ +struct extcontext { + unsigned int magic; + unsigned int size; +}; + +/** + * struct msa_extcontext - MSA extended context structure + * @ext: the extended context header, with magic == MSA_EXTCONTEXT_MAGIC + * @wr: the most significant 64 bits of each MSA vector register + * @csr: the value of the MSA control & status register + * + * If MSA context is live for a task at the time a signal is delivered to it, + * this structure will hold the MSA context of the task as it was prior to the + * signal delivery. + */ +struct msa_extcontext { + struct extcontext ext; +#define MSA_EXTCONTEXT_MAGIC 0x784d5341 /* xMSA */ + + unsigned long long wr[32]; + unsigned int csr; +}; + +#define END_EXTCONTEXT_MAGIC 0x78454e44 /* xEND */ + +/** + * struct ucontext - user context structure + * @uc_flags: + * @uc_link: + * @uc_stack: + * @uc_mcontext: holds basic processor state + * @uc_sigmask: + * @uc_extcontext: holds extended processor state + */ +struct ucontext { + /* Historic fields matching asm-generic */ + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; + + /* Extended context structures may follow ucontext */ + unsigned long long uc_extcontext[0]; +}; + +#endif /* __MIPS_UAPI_ASM_UCONTEXT_H */ diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index de0b451..4e626ca 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -47,8 +47,11 @@ static int (*restore_fp_context)(void __user *sc); struct sigframe { u32 sf_ass[4]; /* argument save space for o32 */ u32 sf_pad[2]; /* Was: signal trampoline */ + + /* Matches struct ucontext from its uc_mcontext field onwards */ struct sigcontext sf_sc; sigset_t sf_mask; + unsigned long long sf_extcontext[0]; }; struct rt_sigframe { @@ -686,6 +689,16 @@ static int smp_restore_fp_context(void __user *sc) static int signal_setup(void) { + /* + * The offset from sigcontext to extended context should be the same + * regardless of the type of signal, such that userland can always know + * where to look if it wishes to find the extended context structures. + */ + BUILD_BUG_ON((offsetof(struct sigframe, sf_extcontext) - + offsetof(struct sigframe, sf_sc)) != + (offsetof(struct rt_sigframe, rs_uc.uc_extcontext) - + offsetof(struct rt_sigframe, rs_uc.uc_mcontext))); + #ifdef CONFIG_SMP /* For now just do the cpu_has_fpu check when the functions are invoked */ save_fp_context = smp_save_fp_context; -- 2.4.4