patch-2.1.9 linux/arch/sparc/kernel/windows.c
Next file: linux/arch/sparc/kernel/wof.S
Previous file: linux/arch/sparc/kernel/unaligned.c
Back to the patch index
Back to the overall index
- Lines: 101
- Date:
Sat Nov 9 10:11:53 1996
- Orig file:
v2.1.8/linux/arch/sparc/kernel/windows.c
- Orig date:
Mon Mar 4 08:49:57 1996
diff -u --recursive --new-file v2.1.8/linux/arch/sparc/kernel/windows.c linux/arch/sparc/kernel/windows.c
@@ -9,11 +9,29 @@
#include <linux/string.h>
#include <linux/mm.h>
+#include <asm/uaccess.h>
+
/* Do save's until all user register windows are out of the cpu. */
void flush_user_windows(void)
{
- if(current->tss.uwinmask)
- flush_user_windows();
+ register int ctr asm("g5");
+
+ ctr = 0;
+ __asm__ __volatile__("
+1:
+ ld [%%g6 + %2], %%g4
+ orcc %%g0, %%g4, %%g0
+ add %0, 1, %0
+ bne 1b
+ save %%sp, -64, %%sp
+2:
+ subcc %0, 1, %0
+ bne 2b
+ restore %%g0, %%g0, %%g0"
+ : "=&r" (ctr)
+ : "0" (ctr),
+ "i" ((const unsigned long)(&(((struct task_struct *)0)->tss.uwinmask)))
+ : "g4");
}
static inline void shift_window_buffer(int first_win, int last_win, struct thread_struct *tp)
@@ -37,11 +55,11 @@
*/
void synchronize_user_stack(void)
{
- struct thread_struct *tp = ¤t->tss;
+ struct thread_struct *tp;
int window;
flush_user_windows();
-
+ tp = ¤t->tss;
if(!tp->w_saved)
return;
@@ -49,17 +67,17 @@
for(window = tp->w_saved - 1; window >= 0; window--) {
unsigned long sp = tp->rwbuf_stkptrs[window];
- /* See if %sp is reasonable at all. */
- if(verify_area(VERIFY_WRITE, (char *) sp, sizeof(struct reg_window)))
+ /* Ok, let it rip. */
+ if(copy_to_user((char *) sp, &tp->reg_window[window],
+ sizeof(struct reg_window)))
continue;
- /* Ok, let it rip. */
- memcpy((char *) sp, &tp->reg_window[window], sizeof(struct reg_window));
shift_window_buffer(window, tp->w_saved - 1, tp);
tp->w_saved--;
}
}
+#if 0
/* An optimization. */
static inline void copy_aligned_window(void *dest, const void *src)
{
@@ -82,27 +100,25 @@
"r" (dest), "r" (src) :
"g2", "g3", "g4", "g5");
}
+#endif
/* Try to push the windows in a threads window buffer to the
* user stack. Unaligned %sp's are not allowed here.
*/
-#define stack_is_bad(sp, rw) \
- (((sp) & 7) || verify_area(rw, (char *) (sp), sizeof(struct reg_window)))
-
void try_to_clear_window_buffer(struct pt_regs *regs, int who)
{
- struct thread_struct *tp = ¤t->tss;
+ struct thread_struct *tp;
int window;
flush_user_windows();
+ tp = ¤t->tss;
for(window = 0; window < tp->w_saved; window++) {
unsigned long sp = tp->rwbuf_stkptrs[window];
- if(stack_is_bad(sp, VERIFY_WRITE))
+ if((sp & 7) ||
+ copy_to_user((char *) sp, &tp->reg_window[window], REGWIN_SZ))
do_exit(SIGILL);
- else
- copy_aligned_window((char *) sp, &tp->reg_window[window]);
}
tp->w_saved = 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov