diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-02 13:40:50 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-02 13:40:50 -0700 |
commit | bdfc7cbdeef8cadba0e5793079ac0130b8e2220c (patch) | |
tree | 82af0cae4898e259edcc6cbdad639087dc1189a8 /arch/mips/kernel/signal32.c | |
parent | 62d1a3ba5adc5653d43f6cd3a90758bb6ad5d5bd (diff) | |
parent | ade63aada79c61bcd5f51cbd310f237399892268 (diff) |
Merge branch 'mips-for-linux-next' of git://git.linux-mips.org/pub/scm/ralf/upstream-sfr
Pull MIPS updates from Ralf Baechle:
- Support for Imgtec's Aptiv family of MIPS cores.
- Improved detection of BCM47xx configurations.
- Fix hiberation for certain configurations.
- Add support for the Chinese Loongson 3 CPU, a MIPS64 R2 core and
systems.
- Detection and support for the MIPS P5600 core.
- A few more random fixes that didn't make 3.14.
- Support for the EVA Extended Virtual Addressing
- Switch Alchemy to the platform PATA driver
- Complete unification of Alchemy support
- Allow availability of I/O cache coherency to be runtime detected
- Improvments to multiprocessing support for Imgtec platforms
- A few microoptimizations
- Cleanups of FPU support
- Paul Gortmaker's fixes for the init stuff
- Support for seccomp
* 'mips-for-linux-next' of git://git.linux-mips.org/pub/scm/ralf/upstream-sfr: (165 commits)
MIPS: CPC: Use __raw_ memory access functions
MIPS: CM: use __raw_ memory access functions
MIPS: Fix warning when including smp-ops.h with CONFIG_SMP=n
MIPS: Malta: GIC IPIs may be used without MT
MIPS: smp-mt: Use common GIC IPI implementation
MIPS: smp-cmp: Remove incorrect core number probe
MIPS: Fix gigaton of warning building with microMIPS.
MIPS: Fix core number detection for MT cores
MIPS: MT: core_nvpes function to retrieve VPE count
MIPS: Provide empty mips_mt_set_cpuoptions when CONFIG_MIPS_MT=n
MIPS: Lasat: Replace del_timer by del_timer_sync
MIPS: Malta: Setup PM I/O region on boot
MIPS: Loongson: Add a Loongson-3 default config file
MIPS: Loongson 3: Add CPU hotplug support
MIPS: Loongson 3: Add Loongson-3 SMP support
MIPS: Loongson: Add Loongson-3 Kconfig options
MIPS: Loongson: Add swiotlb to support All-Memory DMA
MIPS: Loongson 3: Add serial port support
MIPS: Loongson 3: Add IRQ init and dispatch support
MIPS: Loongson 3: Add HT-linked PCI support
...
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r-- | arch/mips/kernel/signal32.c | 137 |
1 files changed, 117 insertions, 20 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 3d60f7750fa8..299f956e4db3 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -30,6 +30,7 @@ #include <asm/sim.h> #include <asm/ucontext.h> #include <asm/fpu.h> +#include <asm/msa.h> #include <asm/war.h> #include <asm/vdso.h> #include <asm/dsp.h> @@ -42,8 +43,8 @@ static int (*restore_fp_context32)(struct sigcontext32 __user *sc); extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); -extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc); -extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc); +extern asmlinkage int _save_msa_context32(struct sigcontext32 __user *sc); +extern asmlinkage int _restore_msa_context32(struct sigcontext32 __user *sc); /* * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... @@ -78,17 +79,96 @@ struct rt_sigframe32 { }; /* + * Thread saved context copy to/from a signal context presumed to be on the + * user stack, and therefore accessed with appropriate macros from uaccess.h. + */ +static int copy_fp_to_sigcontext32(struct sigcontext32 __user *sc) +{ + int i; + int err = 0; + int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1; + + for (i = 0; i < NUM_FPU_REGS; i += inc) { + err |= + __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0), + &sc->sc_fpregs[i]); + } + err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); + + return err; +} + +static int copy_fp_from_sigcontext32(struct sigcontext32 __user *sc) +{ + int i; + int err = 0; + int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1; + u64 fpr_val; + + for (i = 0; i < NUM_FPU_REGS; i += inc) { + err |= __get_user(fpr_val, &sc->sc_fpregs[i]); + set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val); + } + err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); + + return err; +} + +/* + * These functions will save only the upper 64 bits of the vector registers, + * since the lower 64 bits have already been saved as the scalar FP context. + */ +static int copy_msa_to_sigcontext32(struct sigcontext32 __user *sc) +{ + int i; + int err = 0; + + for (i = 0; i < NUM_FPU_REGS; i++) { + err |= + __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 1), + &sc->sc_msaregs[i]); + } + err |= __put_user(current->thread.fpu.msacsr, &sc->sc_msa_csr); + + return err; +} + +static int copy_msa_from_sigcontext32(struct sigcontext32 __user *sc) +{ + int i; + int err = 0; + u64 val; + + for (i = 0; i < NUM_FPU_REGS; i++) { + err |= __get_user(val, &sc->sc_msaregs[i]); + set_fpr64(¤t->thread.fpu.fpr[i], 1, val); + } + err |= __get_user(current->thread.fpu.msacsr, &sc->sc_msa_csr); + + return err; +} + +/* * sigcontext handlers */ -static int protected_save_fp_context32(struct sigcontext32 __user *sc) +static int protected_save_fp_context32(struct sigcontext32 __user *sc, + unsigned used_math) { int err; + bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA); while (1) { lock_fpu_owner(); - err = own_fpu_inatomic(1); - if (!err) - err = save_fp_context32(sc); /* this might fail */ - unlock_fpu_owner(); + if (is_fpu_owner()) { + err = save_fp_context32(sc); + if (save_msa && !err) + err = _save_msa_context32(sc); + unlock_fpu_owner(); + } else { + unlock_fpu_owner(); + err = copy_fp_to_sigcontext32(sc); + if (save_msa && !err) + err = copy_msa_to_sigcontext32(sc); + } if (likely(!err)) break; /* touch the sigcontext and try again */ @@ -101,15 +181,29 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc) return err; } -static int protected_restore_fp_context32(struct sigcontext32 __user *sc) +static int protected_restore_fp_context32(struct sigcontext32 __user *sc, + unsigned used_math) { int err, tmp __maybe_unused; + bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA); while (1) { lock_fpu_owner(); - err = own_fpu_inatomic(0); - if (!err) - err = restore_fp_context32(sc); /* this might fail */ - unlock_fpu_owner(); + if (is_fpu_owner()) { + err = restore_fp_context32(sc); + if (restore_msa && !err) { + enable_msa(); + err = _restore_msa_context32(sc); + } else { + /* signal handler may have used MSA */ + disable_msa(); + } + unlock_fpu_owner(); + } else { + unlock_fpu_owner(); + err = copy_fp_from_sigcontext32(sc); + if (restore_msa && !err) + err = copy_msa_from_sigcontext32(sc); + } if (likely(!err)) break; /* touch the sigcontext and try again */ @@ -147,7 +241,8 @@ static int setup_sigcontext32(struct pt_regs *regs, err |= __put_user(mflo3(), &sc->sc_lo3); } - used_math = !!used_math(); + used_math = used_math() ? USEDMATH_FP : 0; + used_math |= thread_msa_context_live() ? USEDMATH_MSA : 0; err |= __put_user(used_math, &sc->sc_used_math); if (used_math) { @@ -155,20 +250,21 @@ static int setup_sigcontext32(struct pt_regs *regs, * Save FPU state to signal context. Signal handler * will "inherit" current FPU state. */ - err |= protected_save_fp_context32(sc); + err |= protected_save_fp_context32(sc, used_math); } return err; } static int -check_and_restore_fp_context32(struct sigcontext32 __user *sc) +check_and_restore_fp_context32(struct sigcontext32 __user *sc, + unsigned used_math) { int err, sig; err = sig = fpcsr_pending(&sc->sc_fpc_csr); if (err > 0) err = 0; - err |= protected_restore_fp_context32(sc); + err |= protected_restore_fp_context32(sc, used_math); return err ?: sig; } @@ -205,9 +301,10 @@ static int restore_sigcontext32(struct pt_regs *regs, if (used_math) { /* restore fpu context if we have used it before */ if (!err) - err = check_and_restore_fp_context32(sc); + err = check_and_restore_fp_context32(sc, used_math); } else { - /* signal handler may have used FPU. Give it up. */ + /* signal handler may have used FPU or MSA. Disable them. */ + disable_msa(); lose_fpu(0); } @@ -566,8 +663,8 @@ static int signal32_init(void) save_fp_context32 = _save_fp_context32; restore_fp_context32 = _restore_fp_context32; } else { - save_fp_context32 = fpu_emulator_save_context32; - restore_fp_context32 = fpu_emulator_restore_context32; + save_fp_context32 = copy_fp_to_sigcontext32; + restore_fp_context32 = copy_fp_from_sigcontext32; } return 0; |