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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [mips64/] [kernel/] [process.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * This file is subject to the terms and conditions of the GNU General Public
3
 * License.  See the file "COPYING" in the main directory of this archive
4
 * for more details.
5
 *
6
 * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others.
7
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8
 */
9
#include <linux/errno.h>
10
#include <linux/sched.h>
11
#include <linux/kernel.h>
12
#include <linux/mm.h>
13
#include <linux/stddef.h>
14
#include <linux/unistd.h>
15
#include <linux/ptrace.h>
16
#include <linux/slab.h>
17
#include <linux/mman.h>
18
#include <linux/personality.h>
19
#include <linux/sys.h>
20
#include <linux/user.h>
21
#include <linux/a.out.h>
22
#include <linux/init.h>
23
#include <linux/completion.h>
24
 
25
#include <asm/bootinfo.h>
26
#include <asm/pgtable.h>
27
#include <asm/system.h>
28
#include <asm/mipsregs.h>
29
#include <asm/processor.h>
30
#include <asm/stackframe.h>
31
#include <asm/uaccess.h>
32
#include <asm/io.h>
33
#include <asm/elf.h>
34
#include <asm/cpu.h>
35
#include <asm/fpu.h>
36
#include <asm/inst.h>
37
 
38
ATTRIB_NORET void cpu_idle(void)
39
{
40
        /* endless idle loop with no priority at all */
41
        init_idle();
42
        current->nice = 20;
43
        current->counter = -100;
44
        while (1) {
45
                while (!current->need_resched)
46
                        if (cpu_wait)
47
                                (*cpu_wait)();
48
                schedule();
49
                check_pgt_cache();
50
        }
51
}
52
 
53
asmlinkage void ret_from_fork(void);
54
 
55
void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
56
{
57
        unsigned long status;
58
 
59
        /* New thread loses kernel privileges. */
60
        status = regs->cp0_status & ~(ST0_CU0|ST0_FR|ST0_KSU);
61
        status |= KSU_USER;
62
        status |= (current->thread.mflags & MF_32BIT_REGS) ? 0 : ST0_FR;
63
        regs->cp0_status = status;
64
        current->used_math = 0;
65
        lose_fpu();
66
        regs->cp0_epc = pc;
67
        regs->regs[29] = sp;
68
        current->thread.current_ds = USER_DS;
69
}
70
 
71
void exit_thread(void)
72
{
73
}
74
 
75
void flush_thread(void)
76
{
77
}
78
 
79
int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
80
                unsigned long unused, struct task_struct *p,
81
                struct pt_regs *regs)
82
{
83
        struct pt_regs *childregs;
84
        long childksp;
85
 
86
        childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32;
87
 
88
        if (is_fpu_owner()) {
89
                save_fp(p);
90
        }
91
 
92
        /* set up new TSS. */
93
        childregs = (struct pt_regs *) childksp - 1;
94
        *childregs = *regs;
95
        childregs->regs[7] = 0;  /* Clear error flag */
96
        childregs->regs[2] = 0;  /* Child gets zero as return value */
97
        regs->regs[2] = p->pid;
98
 
99
        if (childregs->cp0_status & ST0_CU0) {
100
                childregs->regs[28] = (unsigned long) p;
101
                childregs->regs[29] = childksp;
102
                p->thread.current_ds = KERNEL_DS;
103
        } else {
104
                childregs->regs[29] = usp;
105
                p->thread.current_ds = USER_DS;
106
        }
107
        p->thread.reg29 = (unsigned long) childregs;
108
        p->thread.reg31 = (unsigned long) ret_from_fork;
109
 
110
        /*
111
         * New tasks lose permission to use the fpu. This accelerates context
112
         * switching for most programs since they don't use the fpu.  Most
113
         * MIPS IV CPUs use ST0_CU3 as ST0_XX flag so we leave it unchanged.
114
         */
115
        p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1|ST0_KSU);
116
        childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
117
 
118
        return 0;
119
}
120
 
121
/* Fill in the fpu structure for a core dump.. */
122
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
123
{
124
        memcpy(r, &current->thread.fpu, sizeof(current->thread.fpu));
125
        return 1;
126
}
127
 
128
/*
129
 * Create a kernel thread
130
 */
131
int arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
132
{
133
        int retval;
134
 
135
        __asm__ __volatile__(
136
                "       move    $6, $sp         \n"
137
                "       move    $4, %5          \n"
138
                "       li      $2, %1          \n"
139
                "       syscall                 \n"
140
                "       beq     $6, $sp, 1f     \n"
141
                "       move    $4, %3          \n"
142
                "       jalr    %4              \n"
143
                "       move    $4, $2          \n"
144
                "       li      $2, %2          \n"
145
                "       syscall                 \n"
146
                "1:     move    %0, $2          \n"
147
                : "=r" (retval)
148
                : "i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn),
149
                  "r" (flags | CLONE_VM)
150
                 /*
151
                  * The called subroutine might have destroyed any of the
152
                  * at, result, argument or temporary registers ...
153
                 */
154
                : "$2", "$3", "$4", "$5", "$6", "$7", "$8",
155
                  "$9","$10","$11","$12","$13","$14","$15","$24","$25","$31");
156
 
157
        return retval;
158
}
159
 
160
/*
161
 * These bracket the sleeping functions..
162
 */
163
extern void scheduling_functions_start_here(void);
164
extern void scheduling_functions_end_here(void);
165
#define first_sched     ((unsigned long) scheduling_functions_start_here)
166
#define last_sched      ((unsigned long) scheduling_functions_end_here)
167
 
168
struct mips_frame_info schedule_frame;
169
static struct mips_frame_info schedule_timeout_frame;
170
static struct mips_frame_info sleep_on_frame;
171
static struct mips_frame_info sleep_on_timeout_frame;
172
static struct mips_frame_info wait_for_completion_frame;
173
static int mips_frame_info_initialized;
174
static int __init get_frame_info(struct mips_frame_info *info, void *func)
175
{
176
        int i;
177
        union mips_instruction *ip = (union mips_instruction *)func;
178
        info->pc_offset = -1;
179
        info->frame_offset = -1;
180
        for (i = 0; i < 128; i++, ip++) {
181
                /* if jal, jalr, jr, stop. */
182
                if (ip->j_format.opcode == jal_op ||
183
                    (ip->r_format.opcode == spec_op &&
184
                     (ip->r_format.func == jalr_op ||
185
                      ip->r_format.func == jr_op)))
186
                        break;
187
                if (ip->i_format.opcode == sd_op &&
188
                    ip->i_format.rs == 29) {
189
                        /* sd $ra, offset($sp) */
190
                        if (ip->i_format.rt == 31) {
191
                                if (info->pc_offset != -1)
192
                                        break;
193
                                info->pc_offset =
194
                                        ip->i_format.simmediate / sizeof(long);
195
                        }
196
                        /* sd $s8, offset($sp) */
197
                        if (ip->i_format.rt == 30) {
198
                                if (info->frame_offset != -1)
199
                                        break;
200
                                info->frame_offset =
201
                                        ip->i_format.simmediate / sizeof(long);
202
                        }
203
                }
204
        }
205
        if (info->pc_offset == -1 || info->frame_offset == -1) {
206
                printk("Can't analyze prologue code at %p\n", func);
207
                info->pc_offset = -1;
208
                info->frame_offset = -1;
209
                return -1;
210
        }
211
 
212
        return 0;
213
}
214
void __init frame_info_init(void)
215
{
216
        mips_frame_info_initialized =
217
                !get_frame_info(&schedule_frame, schedule) &&
218
                !get_frame_info(&schedule_timeout_frame, schedule_timeout) &&
219
                !get_frame_info(&sleep_on_frame, sleep_on) &&
220
                !get_frame_info(&sleep_on_timeout_frame, sleep_on_timeout) &&
221
                !get_frame_info(&wait_for_completion_frame, wait_for_completion);
222
}
223
 
224
/* get_wchan - a maintenance nightmare ...  */
225
unsigned long get_wchan(struct task_struct *p)
226
{
227
        unsigned long frame, pc;
228
 
229
        if (!p || p == current || p->state == TASK_RUNNING)
230
                return 0;
231
 
232
        if (!mips_frame_info_initialized)
233
                return 0;
234
        pc = thread_saved_pc(&p->thread);
235
        if (pc < first_sched || pc >= last_sched)
236
                goto out;
237
 
238
        if (pc >= (unsigned long) sleep_on_timeout)
239
                goto schedule_timeout_caller;
240
        if (pc >= (unsigned long) sleep_on)
241
                goto schedule_caller;
242
        if (pc >= (unsigned long) interruptible_sleep_on_timeout)
243
                goto schedule_timeout_caller;
244
        if (pc >= (unsigned long)interruptible_sleep_on)
245
                goto schedule_caller;
246
        if (pc >= (unsigned long)wait_for_completion)
247
                goto schedule_caller;
248
        goto schedule_timeout_caller;
249
 
250
schedule_caller:
251
        frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset];
252
        if (pc >= (unsigned long) sleep_on)
253
                pc = ((unsigned long *)frame)[sleep_on_frame.pc_offset];
254
        else
255
                pc = ((unsigned long *)frame)[wait_for_completion_frame.pc_offset];
256
        goto out;
257
 
258
schedule_timeout_caller:
259
        /* Must be schedule_timeout ...  */
260
        frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset];
261
 
262
        /* The schedule_timeout frame ...  */
263
        pc    = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
264
 
265
        if (pc >= first_sched && pc < last_sched) {
266
                /* schedule_timeout called by [interruptible_]sleep_on_timeout */
267
                frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset];
268
                pc    = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset];
269
        }
270
 
271
out:
272
        if (current->thread.mflags & MF_32BIT_ADDR) /* Kludge for 32-bit ps  */
273
                pc &= 0xffffffff;
274
 
275
        return pc;
276
}

powered by: WebSVN 2.1.0

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