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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/arch/or32/kernel/process.c
3
 *
4
 *  or32 version
5
 *    author(s): Matjaz Breskvar (phoenix@opencores.org)
6
 *
7
 *  derived from cris, i386, m68k, ppc, sh ports.
8
 *
9
 *  changes:
10
 *  18. 11. 2003: Matjaz Breskvar (phoenix@opencores.org)
11
 *    initial port to or32 architecture
12
 *
13
 * This file handles the architecture-dependent parts of process handling..
14
 * Based on m86k.
15
 */
16
 
17
#define __KERNEL_SYSCALLS__
18
#include <stdarg.h>
19
 
20
#include <linux/errno.h>
21
#include <linux/sched.h>
22
#include <linux/kernel.h>
23
#include <linux/mm.h>
24
#include <linux/stddef.h>
25
#include <linux/unistd.h>
26
#include <linux/ptrace.h>
27
#include <linux/slab.h>
28
#include <linux/user.h>
29
#include <linux/a.out.h>
30
#include <linux/elfcore.h>
31
#include <linux/interrupt.h>
32
#include <linux/delay.h>
33
 
34
#include <asm/uaccess.h>
35
#include <asm/pgtable.h>
36
#include <asm/system.h>
37
#include <asm/io.h>
38
#include <asm/processor.h>
39
#include <asm/spr_defs.h>
40
#include <asm/or32-hf.h>
41
 
42
#include <linux/smp.h>
43
 
44
/*
45
 * Initial task structure. Make this a per-architecture thing,
46
 * because different architectures tend to have different
47
 * alignment requirements and potentially different initial
48
 * setup.
49
 */
50
 
51
static struct fs_struct init_fs = INIT_FS;
52
static struct files_struct init_files = INIT_FILES;
53
static struct signal_struct init_signals = INIT_SIGNALS;
54
struct mm_struct init_mm = INIT_MM(init_mm);
55
struct task_struct *current_set[NR_CPUS] = {&init_task, };
56
 
57
union task_union  __attribute((aligned(PAGE_SIZE))) init_task_union = {
58
        INIT_TASK(init_task_union.task) };
59
 
60
void show_regs(struct pt_regs *regs)
61
{
62
        extern void show_registers(struct pt_regs *regs);
63
 
64
        show_registers(regs);
65
#if 0
66
        printk("CPU #: %d\n",  smp_processor_id());
67
 
68
        printk("   PC: %08lx    SR: %08lx    SP: %08lx\n",
69
               regs->pc, regs->sr, regs->sp);
70
        printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
71
               0L, regs->sp, regs->gprs[0], regs->gprs[1]);
72
        printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
73
               regs->gprs[2], regs->gprs[3], regs->gprs[4], regs->gprs[5]);
74
        printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
75
               regs->gprs[6], regs->gprs[7], regs->gprs[8], regs->gprs[9]);
76
        printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
77
               regs->gprs[10], regs->gprs[11], regs->gprs[12], regs->gprs[13]);
78
        printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
79
               regs->gprs[14], regs->gprs[15], regs->gprs[16], regs->gprs[17]);
80
        printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
81
               regs->gprs[18], regs->gprs[19], regs->gprs[20], regs->gprs[21]);
82
        printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
83
               regs->gprs[22], regs->gprs[23], regs->gprs[24], regs->gprs[25]);
84
        printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
85
               regs->gprs[26], regs->gprs[27], regs->gprs[28], regs->gprs[29]);
86
        printk("  RES: %08lx oGPR3: %08lx dummy: %08lx\n",
87
               regs->result, regs->orig_gpr3, regs->dummy);
88
 
89
        printk("Process %s (pid: %d, stackpage=%08lx)\n",
90
               current->comm, current->pid, (unsigned long)current);
91
#endif
92
}
93
 
94
/*
95
 * The idle loop on an or32..
96
 */
97
asmlinkage int sys_idle(void)
98
{
99
        if (current->pid != 0)
100
                return -EPERM;
101
 
102
 
103
        /* endless idle loop with no priority at all */
104
        current->counter = -100;
105
        for (;;) {
106
                schedule();
107
        }
108
}
109
 
110
void hard_reset_now(void)
111
{
112
        printk("***HARD_RESET_NOW***\n");
113
        __asm__("l.ori r31,r0,0x100;"
114
                "l.jr  r31         ;"
115
                "l.nop             ;");
116
}
117
 
118
void machine_restart(void)
119
{
120
        hard_reset_now();
121
}
122
 
123
/*
124
 * Similar to machine_power_off, but don't shut off power.  Add code
125
 * here to freeze the system for e.g. post-mortem debug purpose when
126
 * possible.  This halt has nothing to do with the idle halt.
127
 */
128
 
129
void machine_halt(void)
130
{
131
        printk("***MACHINE_HALT***\n");
132
        __asm__("l.nop 1");
133
}
134
 
135
/* If or when software power-off is implemented, add code here.  */
136
 
137
void machine_power_off(void)
138
{
139
        __asm__("l.nop 1");
140
}
141
 
142
/*
143
 * Free current thread data structures etc..
144
 */
145
void exit_thread(void)
146
{
147
}
148
 
149
/*
150
 * When a process does an "exec", machine state like FPU and debug
151
 * registers need to be reset.  This is a hook function for that.
152
 * Currently we don't have any such state to reset, so this is empty.
153
 */
154
void flush_thread(void)
155
{
156
}
157
 
158 1306 phoenix
asmlinkage int sys_fork(int r3, int r4, int r5, int r6, int r7, struct pt_regs *regs)
159 1275 phoenix
{
160
        unsigned long sp;
161
/*
162
 *      __PHX__ :: cleanup
163
 *
164
 *      printk("fork: current 0x%x, ksp 0x%x\n",
165
 *             current, &sp);
166
 */
167
        return do_fork(SIGCHLD, regs->sp, regs, 0);
168
}
169
 
170 1306 phoenix
asmlinkage int sys_clone(int r3, int r4, int r5, int r6, int r7, struct pt_regs *regs)
171 1275 phoenix
{
172 1306 phoenix
        unsigned long clone_flags = (unsigned long)r3;
173 1275 phoenix
        return do_fork(clone_flags, regs->sp, regs, 0);
174
}
175
 
176 1306 phoenix
asmlinkage int sys_vfork(int r3, int r4, int r5, int r6, int r7, struct pt_regs *regs)
177 1275 phoenix
{
178
        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gprs[1], regs, 0);
179
}
180
 
181
 
182
void release_thread(struct task_struct *dead_task)
183
{
184
}
185
 
186
int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
187
                unsigned long unused, struct task_struct *p, struct pt_regs *regs)
188
{
189
        struct pt_regs *childregs, *kregs;
190
        extern void ret_from_fork(void);
191
        unsigned long sp = (unsigned long)p + sizeof(union task_union);
192
        unsigned long childframe;
193
 
194
        /* Copy registers */
195
        sp -= sizeof(struct pt_regs);
196
        childregs = (struct pt_regs *) sp;
197
 
198
        *childregs = *regs;
199
 
200
        if ((childregs->sr & SPR_SR_SM) == 1) {
201
                /* for kernel thread, set `current' and stackptr in new task */
202
                childregs->sp = sp + sizeof(struct pt_regs);
203
                childregs->gprs[0] = (unsigned long) p;
204
                /* __PHX__ :: i think this thread.regs is not needed */
205
                p->thread.regs = NULL;  /* no user register state */
206
        } else
207
                p->thread.regs = childregs;
208
 
209
        childregs->gprs[9] = 0;  /* Result from fork() */
210
//      sp -= STACK_FRAME_OVERHEAD;
211
        childframe = sp;
212
 
213
        /*
214
         * The way this works is that at some point in the future
215
         * some task will call _switch to switch to the new task.
216
         * That will pop off the stack frame created below and start
217
         * the new task running at ret_from_fork.  The new task will
218
         * do some house keeping and then return from the fork or clone
219
         * system call, using the stack frame created above.
220
         */
221
        sp -= sizeof(struct pt_regs);
222
        kregs = (struct pt_regs *) sp;
223
 
224
//      sp -= STACK_FRAME_OVERHEAD;
225
        p->thread.ksp = sp;
226
 
227
        kregs->sr = regs->sr | SPR_SR_SM;
228
        kregs->sp = sp + sizeof(struct pt_regs);
229
        kregs->gprs[0] = p; /* current           */
230
        kregs->gprs[1] = p; /* for schedule_tail */
231
        kregs->pc = (unsigned long)ret_from_fork;
232
        p->thread.last_syscall = -1;
233
        return 0;
234
}
235
 
236
 
237
/*
238
 * Set up a thread for executing a new program
239
 */
240
void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
241
{
242
        phx_warn("NIP: %x, SP: %x", pc, sp);
243
 
244
        set_fs(USER_DS);
245
        memset(regs->gprs, 0, sizeof(regs->gprs));
246
 
247
        regs->pc = pc;
248
        regs->sr = regs->sr & ~ SPR_SR_SM;
249
        regs->sp = sp;
250
}
251
 
252
/* Fill in the fpu structure for a core dump.  */
253
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
254
{
255
        phx_warn("TODO");
256
 
257
        /* __PHX__: __TODO__ for FPU */
258
        return 0;
259
}
260
 
261
void _switch_to(struct task_struct *prev, struct task_struct *new, struct task_struct **last)
262
{
263
        struct thread_struct *new_thread, *old_thread;
264
        long flags;
265
 
266
        save_flags(flags);
267
        cli();
268
        check_stack(NULL, __FILE__, __FUNCTION__, __LINE__);
269
 
270
        /* current_set is an array of saved current pointers
271
         * (one for each cpu). we need them at user->kernel transition,
272
         * while we save them at kernel->user transition
273
         */
274
        new_thread = &new->thread;
275
        old_thread = &current->thread;
276
        current_set[smp_processor_id()] = new;
277
        *last = _switch(old_thread, new_thread);
278
 
279
        check_stack(NULL, __FILE__, __FUNCTION__, __LINE__);
280
        restore_flags(flags);
281
}
282
 
283
/*
284
 * fill in the user structure for a core dump..
285
 */
286
void dump_thread(struct pt_regs *regs, struct user *dump)
287
{
288
 
289
        phx_warn("TODO");
290
 
291
        /* changed the size calculations - should hopefully work better. lbt */
292
        dump->magic = CMAGIC;
293
        dump->start_code = 0;
294
        dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
295
        dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
296
        dump->u_dsize = ((unsigned long) (current->mm->brk +
297
                                          (PAGE_SIZE-1))) >> PAGE_SHIFT;
298
        dump->u_dsize -= dump->u_tsize;
299
        dump->u_ssize = 0;
300
 
301
        /* __PHX__: FIXME !! i've just commented out this for now */
302
//      dump->u_ar0 = (struct pt_regs *)(((int)(&dump->regs)) -((int)(dump)));
303
        dump->regs = *regs;
304
        /* dump floating point stuff */
305
 
306
        /* __PHX__: __TODO__ FPU
307
         * dump->u_fpvalid = dump_fpu (regs, &dump->or32fp);
308
         */
309
}
310 1306 phoenix
 
311 1275 phoenix
/*
312
 * sys_execve() executes a new program.
313
 */
314
asmlinkage int sys_execve(char *name, char **argv, char **envp,
315 1306 phoenix
                          int r6, int r7, struct pt_regs *regs)
316 1275 phoenix
{
317
        int error;
318
        char * filename;
319
 
320
        filename = getname(name);
321
 
322
        error = PTR_ERR(filename);
323
        if (IS_ERR(filename))
324
          goto out;
325
 
326
        error = do_execve(filename, argv, envp, regs);
327
 
328
        if (error == 0) {
329
          current->ptrace &= ~PT_DTRACE;
330
        }
331
 
332
        putname(filename);
333
        out:
334
 
335
        return error;
336
}
337
 
338
unsigned long get_wchan(struct task_struct *p)
339
{
340 1306 phoenix
        /* __PHX__: TODO */
341 1275 phoenix
        phx_warn("TODO");
342
        return 0;
343
}

powered by: WebSVN 2.1.0

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