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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [sparc/] [kernel/] [windows.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/* 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
#include <linux/smp.h>
12
#include <linux/smp_lock.h>
13
 
14
#include <asm/uaccess.h>
15
 
16
/* Do save's until all user register windows are out of the cpu. */
17
void flush_user_windows(void)
18
{
19
        register int ctr asm("g5");
20
 
21
        ctr = 0;
22
        __asm__ __volatile__(
23
                "\n1:\n\t"
24
                "ld     [%%g6 + %2], %%g4\n\t"
25
                "orcc   %%g0, %%g4, %%g0\n\t"
26
                "add    %0, 1, %0\n\t"
27
                "bne    1b\n\t"
28
                " save  %%sp, -64, %%sp\n"
29
                "2:\n\t"
30
                "subcc  %0, 1, %0\n\t"
31
                "bne    2b\n\t"
32
                " restore %%g0, %%g0, %%g0\n"
33
        : "=&r" (ctr)
34
        : "0" (ctr),
35
          "i" ((const unsigned long)TI_UWINMASK)
36
        : "g4", "cc");
37
}
38
 
39
static inline void shift_window_buffer(int first_win, int last_win, struct thread_info *tp)
40
{
41
        int i;
42
 
43
        for(i = first_win; i < last_win; i++) {
44
                tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1];
45
                memcpy(&tp->reg_window[i], &tp->reg_window[i+1], sizeof(struct reg_window));
46
        }
47
}
48
 
49
/* Place as many of the user's current register windows
50
 * on the stack that we can.  Even if the %sp is unaligned
51
 * we still copy the window there, the only case that we don't
52
 * succeed is if the %sp points to a bum mapping altogether.
53
 * setup_frame() and do_sigreturn() use this before shifting
54
 * the user stack around.  Future instruction and hardware
55
 * bug workaround routines will need this functionality as
56
 * well.
57
 */
58
void synchronize_user_stack(void)
59
{
60
        struct thread_info *tp = current_thread_info();
61
        int window;
62
 
63
        flush_user_windows();
64
        if(!tp->w_saved)
65
                return;
66
 
67
        /* Ok, there is some dirty work to do. */
68
        for(window = tp->w_saved - 1; window >= 0; window--) {
69
                unsigned long sp = tp->rwbuf_stkptrs[window];
70
 
71
                /* Ok, let it rip. */
72
                if (copy_to_user((char __user *) sp, &tp->reg_window[window],
73
                                 sizeof(struct reg_window)))
74
                        continue;
75
 
76
                shift_window_buffer(window, tp->w_saved - 1, tp);
77
                tp->w_saved--;
78
        }
79
}
80
 
81
#if 0
82
/* An optimization. */
83
static inline void copy_aligned_window(void *dest, const void *src)
84
{
85
        __asm__ __volatile__("ldd [%1], %%g2\n\t"
86
                             "ldd [%1 + 0x8], %%g4\n\t"
87
                             "std %%g2, [%0]\n\t"
88
                             "std %%g4, [%0 + 0x8]\n\t"
89
                             "ldd [%1 + 0x10], %%g2\n\t"
90
                             "ldd [%1 + 0x18], %%g4\n\t"
91
                             "std %%g2, [%0 + 0x10]\n\t"
92
                             "std %%g4, [%0 + 0x18]\n\t"
93
                             "ldd [%1 + 0x20], %%g2\n\t"
94
                             "ldd [%1 + 0x28], %%g4\n\t"
95
                             "std %%g2, [%0 + 0x20]\n\t"
96
                             "std %%g4, [%0 + 0x28]\n\t"
97
                             "ldd [%1 + 0x30], %%g2\n\t"
98
                             "ldd [%1 + 0x38], %%g4\n\t"
99
                             "std %%g2, [%0 + 0x30]\n\t"
100
                             "std %%g4, [%0 + 0x38]\n\t" : :
101
                             "r" (dest), "r" (src) :
102
                             "g2", "g3", "g4", "g5");
103
}
104
#endif
105
 
106
/* Try to push the windows in a threads window buffer to the
107
 * user stack.  Unaligned %sp's are not allowed here.
108
 */
109
 
110
void try_to_clear_window_buffer(struct pt_regs *regs, int who)
111
{
112
        struct thread_info *tp = current_thread_info();
113
        int window;
114
 
115
        lock_kernel();
116
        flush_user_windows();
117
        for(window = 0; window < tp->w_saved; window++) {
118
                unsigned long sp = tp->rwbuf_stkptrs[window];
119
 
120
                if ((sp & 7) ||
121
                    copy_to_user((char __user *) sp, &tp->reg_window[window],
122
                                 sizeof(struct reg_window)))
123
                        do_exit(SIGILL);
124
        }
125
        tp->w_saved = 0;
126
        unlock_kernel();
127
}

powered by: WebSVN 2.1.0

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