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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [i960/] [kernel/] [process.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*
2
 *  linux/arch/i960/kernel/process.c
3
 *
4
 *  Copyright (C) 1999  Keith Adams     <kma@cse.ogi.edu>
5
 *                      Oregon Graduate Institute
6
 *
7
 *  Based on:
8
 *
9
 *  linux/arch/m68k/kernel/process.c
10
 *
11
 *  Copyright (C) 1995  Hamish Macdonald
12
 *
13
 */
14
 
15
/*
16
 * This file handles the architecture-dependent parts of process handling..
17
 */
18
 
19
#include <linux/errno.h>
20
#include <linux/sched.h>
21
#include <linux/kernel.h>
22
#include <linux/mm.h>
23
#include <linux/stddef.h>
24
#include <linux/unistd.h>
25
#include <linux/ptrace.h>
26
#include <linux/malloc.h>
27
#include <linux/user.h>
28
#include <linux/a.out.h>
29
 
30
#include <asm/segment.h>
31
#include <asm/system.h>
32
#include <asm/traps.h>
33
#include <asm/machdep.h>
34
#include <asm/setup.h>
35
#include <asm/dprintk.h>
36
 
37
extern void stack_trace(void);
38
extern void stack_trace_from(unsigned long sp);
39
 
40
asmlinkage void ret_from_exception(void);
41
 
42
/*
43
 * The idle loop on an i960
44
 */
45
asmlinkage int sys_idle(void)
46
{
47
        if (current->pid != 0)
48
                return -EPERM;
49
 
50
        sti();
51
        /* endless idle loop with no priority at all */
52
        current->counter = -100;
53
        for (;;) {
54
                __asm__ ("halt 2");
55
                schedule();
56
        }
57
}
58
 
59
static unsigned long
60
stack_align(unsigned long sp)
61
{
62
#define STACK_ALIGN     16      /* must be power of 2 */
63
        if ((unsigned long) sp & (STACK_ALIGN-1)) {
64
                (unsigned long) sp += STACK_ALIGN;
65
                (unsigned long) sp &= ~(STACK_ALIGN-1);
66
        }
67
#undef STACK_ALIGN
68
        return sp;
69
}
70
 
71
#ifdef CONFIG_MON960
72
#include <asm/mon960.h>
73
#endif
74
 
75
void hard_reset_now(void)
76
{
77
#ifdef CONFIG_MON960
78
        cli();
79
        mon960_exit(0);
80
#else
81
        printk("ermm, I don't know how to reset. Sorry.\n");
82
#endif
83
}
84
 
85
void show_regs(struct pt_regs * regs)
86
{
87
        int ii;
88
        printk("\n");
89
        printk("PC:\t%08lx\tAC:\t%08lx\n",
90
               regs->pc, regs->ac);
91
        printk("pfp:\t%08lx\tg0:\t%08lx\n",
92
               regs->lregs[0], regs->gregs[0]);
93
        printk("sp:\t%08lx\tg1:\t%08lx\n",
94
               regs->lregs[1], regs->gregs[1]);
95
        printk("rip:\t%08lx\tg2:\t%08lx\n",
96
               regs->lregs[2], regs->gregs[2]);
97
        for (ii=3; ii < 16; ii++)
98
                printk("r%d:\t%08lx\tg%d\t%08lx\n", ii,
99
                       regs->lregs[ii], ii, regs->gregs[ii]);
100
}
101
 
102
void hex_dump(unsigned long start, int len)
103
{
104
        char* c = (char*) start;
105
        int     ii;
106
 
107
#define CHARS_IN_LINE 16
108
        for (ii=0; ii < len; ii++) {
109
                if (! (ii & (CHARS_IN_LINE-1))) {
110
                        printk("\n%8x: ", start + ii);
111
                }
112
                printk("%2x ", c[ii]);
113
        }
114
        printk("\n");
115
}
116
 
117
/*
118
 * Free current thread data structures etc..
119
 */
120
void exit_thread(void)
121
{
122
}
123
 
124
void flush_thread(void)
125
{
126
}
127
 
128
void release_thread(struct task_struct *dead_task)
129
{
130
}
131
 
132
void switch_to(struct task_struct* prev, struct task_struct* next)
133
{
134
        if (next == prev)
135
                return;
136
 
137
#if 0
138
        dprintk("*** switch_to: new pfp: 0x%8x\n", next->tss.pfp);
139
        dprintk("*** switch_to: old stack:\n");
140
        stack_trace();
141
        dprintk("*** switch_to: new stack:\n");
142
        stack_trace_from(next->tss.pfp);
143
#endif
144
        current_set[smp_processor_id()] = next;
145
        __asm__ __volatile__
146
                ("st    pfp, (%1)\n\t"          /* save current pfp */
147
                 "flushreg\n\t"
148
                 "mov   %2, pfp\n\t"
149
                 "flushreg\n\t"
150
                 : "=m" (prev->tss.pfp)
151
                 :"r" (&prev->tss.pfp), "r" (next->tss.pfp));
152
}
153
 
154
/*
155
 * Called from the vfork path. We need to copy enough of the caller's kernel and
156
 * user stacks to get the child out of the kernel, and back to the level where
157
 * vfork was called. This is, I admit, somewhat heinous, and probably a longer
158
 * code path than one would like.
159
 */
160
void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
161
                 struct task_struct * p, struct pt_regs * regs)
162
{
163
        struct pt_regs          *childregs;
164
        extern void             syscall_return(void);
165
        unsigned long           new_ustack;
166
 
167
        if (!regs)
168
                return;         /* kernel_thread hack */
169
 
170
        asm("flushreg");
171
        /*
172
         * Setting up child's ustack: allocate it just below caller's ustack,
173
         * copy in caller's ustack, and relocate sp's. When returning to the
174
         * child, we skip the syscall_frame and go straight back to the caller
175
         * frame.
176
         *
177
         * low addresses
178
         *       _______________
179
         *      | caller_frame  |
180
         *      |_______________|
181
         *      | syscall_frame |
182
         *      |_______________|
183
         *      | child_caller_frame
184
         *      |_______________|
185
         *      ...
186
         *       _______________
187
         *      | regs          |  (top o' kernel stack)
188
         *      ...
189
         *
190
         * high addresses
191
         */
192
        {
193
                struct i960_frame       *syscall_frame, *caller_frame;
194
                struct i960_frame       *child_caller_frame;
195
                unsigned long           frame_len, offset;
196
 
197
                syscall_frame = (struct i960_frame*)
198
                        (regs->lregs[PT_PFP] & ~0xf);
199
                caller_frame = (struct i960_frame*)syscall_frame->pfp;
200
                dprintk("new_ustack: 0x%8x\n", syscall_frame->sp);
201
                new_ustack = stack_align(syscall_frame->sp);
202
                dprintk("new_ustack: 0x%8x\n", new_ustack);
203
                child_caller_frame = (struct i960_frame*) new_ustack;
204
                frame_len = caller_frame->sp - (unsigned long)(caller_frame);
205
                dprintk("frame len: 0x%8x\n", frame_len);
206
                memcpy((void*)new_ustack, caller_frame, frame_len);
207
 
208
                offset = new_ustack - (unsigned long)caller_frame;
209
                child_caller_frame->sp += offset;
210
                /*
211
                 * XXX: you should never return from the function that called
212
                 * vfork; right now, you'll just walk off with a bad stack,
213
                 * but eventually we might want to catch this case and force
214
                 * an exit.
215
                 */
216
                child_caller_frame->pfp = 0;
217
        }
218
 
219
        /*
220
         * We build a near-copy of the top frame of the caller's syscall stack
221
         * in the child's kstack; the child's sp points to the child stack. Its
222
         * pfp heads to the frame in the child's ustack that we created above.
223
         */
224
 
225
        childregs = (struct pt_regs*)p->kernel_stack_page;
226
        *childregs = *regs;             /* bitwise copy */
227
 
228
        childregs->lregs[PT_PFP] = new_ustack | 2;      /* return to user */
229
        childregs->lregs[PT_SP] = (unsigned long)(childregs + 1);
230
        childregs->gregs[0] = 0;  /* Child gets a retval of zero */
231
        childregs->gregs[15] = (unsigned long) &childregs->lregs[0];
232
 
233
        /* we reload the pfp from the thread struct in switch_to */
234
        p->tss.pfp = (unsigned long)&childregs->lregs;
235
#ifdef DEBUG
236
        dprintk("child stack:\n");
237
        stack_trace_from(p->tss.pfp);
238
#endif
239
}
240
 
241
/* Fill in the fpu structure for a core dump.  */
242
 
243
int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
244
{
245
  return 0;
246
}
247
 
248
/*
249
 * fill in the user structure for a core dump..
250
 */
251
void dump_thread(struct pt_regs * regs, struct user * dump)
252
{
253
        /* XXX: write this */
254
}
255
 
256
/*
257
 * start a thread
258
 */
259
void start_thread(struct pt_regs * regs, unsigned long ip, unsigned long sp)
260
{
261
        struct i960_frame* frame;
262
 
263
        /* align the stack */
264
        sp = stack_align(sp);
265
 
266
        /*
267
         * build a little stack frame at sp; start running
268
         */
269
        frame = (struct i960_frame*) sp;
270
        frame->sp = ((unsigned long)sp) + 16*4;
271
        frame->rip = ip;
272
        frame->pfp = 0;
273
#ifdef DEBUG
274
        dprintk("before:\n");
275
        stack_trace();
276
#endif
277
        regs->lregs[PT_PFP] = (sp | 0x7);       /* returning from interrupt */
278
        regs->pc = (1<<13);             /* bit 13: interrupted mode */
279
        regs->ac = (1<<15) | (1<<12);   /* bits 15 and 12: precise faults, no overflow interrupts */
280
 
281
        /*
282
         * g12 contains the "data" bias. the code expects text and data to
283
         * be allocated contiguously, and g12 points to code. Since data/bss
284
         * might be allocated separately from text, we point g12 at
285
         * data_start - text_len
286
         */
287
        regs->gregs[12] = current->mm->start_data -
288
                (current->mm->end_code - current->mm->start_code);
289
        regs->gregs[13] = current->mm->env_start - 12;
290
        regs->gregs[14] = 0;
291
        dprintk("set first arg: 0x%8x\n", regs->gregs[0]);
292
        /* make memory coherent; the stack cache flush might be gratuitous */
293
        asm("flushreg
294
            dcctl       3, g0, g0
295
            icctl       2, g0, g0");
296
#ifdef DEBUG
297
        dprintk("set data seg to: 0x%8x\n", regs->gregs[12]);
298
        dprintk("set start to %p\n", ip);
299
        stack_trace();
300
#endif
301
}
302
 

powered by: WebSVN 2.1.0

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