From ff3aa5f296392b4bdc46ce975e6403bc7d27b191 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 27 Jan 2014 15:23:03 +0000 Subject: [PATCH] MIPS: Don't require FPU on sigcontext setup/restore When a task which has used the FPU at some point in its past takes a signal the kernel would previously always require the task to take ownership of the FPU whilst setting up or restoring from the sigcontext. That means that if the task has not used the FPU within this timeslice then the kernel would enable the FPU, restore the task's FP context into FPU registers and then save them into the sigcontext. This seems inefficient, and if the signal handler doesn't use FP then enabling the FPU & the extra memory accesses are entirely wasted work. This patch modifies the sigcontext setup & restore code to copy directly between the tasks saved FP context & the sigcontext for any tasks which have used FP in the past but are not currently the FPU owner (ie. have not used FP in this timeslice). Signed-off-by: Paul Burton Reviewed-by: Qais Yousef Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6423/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/signal.c | 22 ++++++++++++++-------- arch/mips/kernel/signal32.c | 22 ++++++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index b7e4614d41b5..e0178e117f68 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -102,10 +102,13 @@ static int protected_save_fp_context(struct sigcontext __user *sc) int err; while (1) { lock_fpu_owner(); - err = own_fpu_inatomic(1); - if (!err) - err = save_fp_context(sc); /* this might fail */ - unlock_fpu_owner(); + if (is_fpu_owner()) { + err = save_fp_context(sc); + unlock_fpu_owner(); + } else { + unlock_fpu_owner(); + err = copy_fp_to_sigcontext(sc); + } if (likely(!err)) break; /* touch the sigcontext and try again */ @@ -123,10 +126,13 @@ static int protected_restore_fp_context(struct sigcontext __user *sc) int err, tmp __maybe_unused; while (1) { lock_fpu_owner(); - err = own_fpu_inatomic(0); - if (!err) - err = restore_fp_context(sc); /* this might fail */ - unlock_fpu_owner(); + if (is_fpu_owner()) { + err = restore_fp_context(sc); + unlock_fpu_owner(); + } else { + unlock_fpu_owner(); + err = copy_fp_from_sigcontext(sc); + } if (likely(!err)) break; /* touch the sigcontext and try again */ diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index dc09206d8c7b..aec58211faaa 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -118,10 +118,13 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc) int err; 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); + unlock_fpu_owner(); + } else { + unlock_fpu_owner(); + err = copy_fp_to_sigcontext32(sc); + } if (likely(!err)) break; /* touch the sigcontext and try again */ @@ -139,10 +142,13 @@ static int protected_restore_fp_context32(struct sigcontext32 __user *sc) int err, tmp __maybe_unused; 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); + unlock_fpu_owner(); + } else { + unlock_fpu_owner(); + err = copy_fp_from_sigcontext32(sc); + } if (likely(!err)) break; /* touch the sigcontext and try again */ -- 2.20.1