aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2014-01-27 10:23:03 -0500
committerRalf Baechle <ralf@linux-mips.org>2014-03-26 18:09:09 -0400
commitff3aa5f296392b4bdc46ce975e6403bc7d27b191 (patch)
tree86cdf26bdf924b2f480106bb67e70792856822b2
parentb2ead528288545859dbd7004e07bc23204cf92a8 (diff)
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 <paul.burton@imgtec.com> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6423/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/signal.c22
-rw-r--r--arch/mips/kernel/signal32.c22
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)
102 int err; 102 int err;
103 while (1) { 103 while (1) {
104 lock_fpu_owner(); 104 lock_fpu_owner();
105 err = own_fpu_inatomic(1); 105 if (is_fpu_owner()) {
106 if (!err) 106 err = save_fp_context(sc);
107 err = save_fp_context(sc); /* this might fail */ 107 unlock_fpu_owner();
108 unlock_fpu_owner(); 108 } else {
109 unlock_fpu_owner();
110 err = copy_fp_to_sigcontext(sc);
111 }
109 if (likely(!err)) 112 if (likely(!err))
110 break; 113 break;
111 /* touch the sigcontext and try again */ 114 /* touch the sigcontext and try again */
@@ -123,10 +126,13 @@ static int protected_restore_fp_context(struct sigcontext __user *sc)
123 int err, tmp __maybe_unused; 126 int err, tmp __maybe_unused;
124 while (1) { 127 while (1) {
125 lock_fpu_owner(); 128 lock_fpu_owner();
126 err = own_fpu_inatomic(0); 129 if (is_fpu_owner()) {
127 if (!err) 130 err = restore_fp_context(sc);
128 err = restore_fp_context(sc); /* this might fail */ 131 unlock_fpu_owner();
129 unlock_fpu_owner(); 132 } else {
133 unlock_fpu_owner();
134 err = copy_fp_from_sigcontext(sc);
135 }
130 if (likely(!err)) 136 if (likely(!err))
131 break; 137 break;
132 /* touch the sigcontext and try again */ 138 /* 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)
118 int err; 118 int err;
119 while (1) { 119 while (1) {
120 lock_fpu_owner(); 120 lock_fpu_owner();
121 err = own_fpu_inatomic(1); 121 if (is_fpu_owner()) {
122 if (!err) 122 err = save_fp_context32(sc);
123 err = save_fp_context32(sc); /* this might fail */ 123 unlock_fpu_owner();
124 unlock_fpu_owner(); 124 } else {
125 unlock_fpu_owner();
126 err = copy_fp_to_sigcontext32(sc);
127 }
125 if (likely(!err)) 128 if (likely(!err))
126 break; 129 break;
127 /* touch the sigcontext and try again */ 130 /* touch the sigcontext and try again */
@@ -139,10 +142,13 @@ static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
139 int err, tmp __maybe_unused; 142 int err, tmp __maybe_unused;
140 while (1) { 143 while (1) {
141 lock_fpu_owner(); 144 lock_fpu_owner();
142 err = own_fpu_inatomic(0); 145 if (is_fpu_owner()) {
143 if (!err) 146 err = restore_fp_context32(sc);
144 err = restore_fp_context32(sc); /* this might fail */ 147 unlock_fpu_owner();
145 unlock_fpu_owner(); 148 } else {
149 unlock_fpu_owner();
150 err = copy_fp_from_sigcontext32(sc);
151 }
146 if (likely(!err)) 152 if (likely(!err))
147 break; 153 break;
148 /* touch the sigcontext and try again */ 154 /* touch the sigcontext and try again */