OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [sparc/] [kernel/] [windows.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* windows.c: Routines to deal with register window management
2
 *            at the C-code level.
3
 *
4
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5
 */
6
 
7
#include <linux/kernel.h>
8
#include <linux/sched.h>
9
#include <linux/string.h>
10
#include <linux/mm.h>
11
 
12
/* Do save's until all user register windows are out of the cpu. */
13
void flush_user_windows(void)
14
{
15
        if(current->tss.uwinmask)
16
                flush_user_windows();
17
}
18
 
19
static inline void shift_window_buffer(int first_win, int last_win, struct thread_struct *tp)
20
{
21
        int i;
22
 
23
        for(i = first_win; i < last_win; i++) {
24
                tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1];
25
                memcpy(&tp->reg_window[i], &tp->reg_window[i+1], sizeof(struct reg_window));
26
        }
27
}
28
 
29
/* Place as many of the user's current register windows
30
 * on the stack that we can.  Even if the %sp is unaligned
31
 * we still copy the window there, the only case that we don't
32
 * succeed is if the %sp points to a bum mapping altogether.
33
 * setup_frame() and do_sigreturn() use this before shifting
34
 * the user stack around.  Future instruction and hardware
35
 * bug workaround routines will need this functionality as
36
 * well.
37
 */
38
void synchronize_user_stack(void)
39
{
40
        struct thread_struct *tp = &current->tss;
41
        int window;
42
 
43
        flush_user_windows();
44
 
45
        if(!tp->w_saved)
46
                return;
47
 
48
        /* Ok, there is some dirty work to do. */
49
        for(window = tp->w_saved - 1; window >= 0; window--) {
50
                unsigned long sp = tp->rwbuf_stkptrs[window];
51
 
52
                /* See if %sp is reasonable at all. */
53
                if(verify_area(VERIFY_WRITE, (char *) sp, sizeof(struct reg_window)))
54
                        continue;
55
 
56
                /* Ok, let it rip. */
57
                memcpy((char *) sp, &tp->reg_window[window], sizeof(struct reg_window));
58
                shift_window_buffer(window, tp->w_saved - 1, tp);
59
                tp->w_saved--;
60
        }
61
}
62
 
63
/* An optimization. */
64
static inline void copy_aligned_window(void *dest, const void *src)
65
{
66
        __asm__ __volatile__("ldd [%1], %%g2\n\t"
67
                             "ldd [%1 + 0x8], %%g4\n\t"
68
                             "std %%g2, [%0]\n\t"
69
                             "std %%g4, [%0 + 0x8]\n\t"
70
                             "ldd [%1 + 0x10], %%g2\n\t"
71
                             "ldd [%1 + 0x18], %%g4\n\t"
72
                             "std %%g2, [%0 + 0x10]\n\t"
73
                             "std %%g4, [%0 + 0x18]\n\t"
74
                             "ldd [%1 + 0x20], %%g2\n\t"
75
                             "ldd [%1 + 0x28], %%g4\n\t"
76
                             "std %%g2, [%0 + 0x20]\n\t"
77
                             "std %%g4, [%0 + 0x28]\n\t"
78
                             "ldd [%1 + 0x30], %%g2\n\t"
79
                             "ldd [%1 + 0x38], %%g4\n\t"
80
                             "std %%g2, [%0 + 0x30]\n\t"
81
                             "std %%g4, [%0 + 0x38]\n\t" : :
82
                             "r" (dest), "r" (src) :
83
                             "g2", "g3", "g4", "g5");
84
}
85
 
86
/* Try to push the windows in a threads window buffer to the
87
 * user stack.  Unaligned %sp's are not allowed here.
88
 */
89
 
90
#define stack_is_bad(sp, rw) \
91
  (((sp) & 7) || verify_area(rw, (char *) (sp), sizeof(struct reg_window)))
92
 
93
void try_to_clear_window_buffer(struct pt_regs *regs, int who)
94
{
95
        struct thread_struct *tp = &current->tss;
96
        int window;
97
 
98
        flush_user_windows();
99
        for(window = 0; window < tp->w_saved; window++) {
100
                unsigned long sp = tp->rwbuf_stkptrs[window];
101
 
102
                if(stack_is_bad(sp, VERIFY_WRITE))
103
                        do_exit(SIGILL);
104
                else
105
                        copy_aligned_window((char *) sp, &tp->reg_window[window]);
106
        }
107
        tp->w_saved = 0;
108
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.