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

Subversion Repositories or1k_old

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1624 jcastillo
/*
2
 * MIPS specific syscall handling functions and syscalls
3
 *
4
 * This file is subject to the terms and conditions of the GNU General Public
5
 * License.  See the file "COPYING" in the main directory of this archive
6
 * for more details.
7
 *
8
 * Copyright (C) 1995 by Ralf Baechle
9
 */
10
#include <linux/linkage.h>
11
#include <linux/mm.h>
12
#include <linux/mman.h>
13
#include <linux/sched.h>
14
#include <linux/unistd.h>
15
#include <asm/ptrace.h>
16
#include <asm/segment.h>
17
#include <asm/signal.h>
18
 
19
extern asmlinkage void syscall_trace(void);
20
typedef asmlinkage int (*syscall_t)(void *a0,...);
21
extern asmlinkage int do_syscalls(struct pt_regs *regs, syscall_t fun,
22
                                  int narg);
23
extern syscall_t sys_call_table[];
24
extern unsigned char sys_narg_table[];
25
 
26
asmlinkage int sys_pipe(struct pt_regs *regs)
27
{
28
        int fd[2];
29
        int error;
30
 
31
        error = do_pipe(fd);
32
        if (error)
33
                return error;
34
        regs->reg2 = fd[0];
35
        regs->reg3 = fd[1];
36
        return 0;
37
}
38
 
39
asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
40
                                  int flags, int fd, off_t offset)
41
{
42
        struct file * file = NULL;
43
 
44
        if (flags & MAP_RENAME) {
45
                if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
46
                        return -EBADF;
47
        }
48
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
49
 
50
        return do_mmap(file, addr, len, prot, flags, offset);
51
}
52
 
53
asmlinkage int sys_idle(void)
54
{
55
        if (current->pid != 0)
56
                return -EPERM;
57
 
58
        /* endless idle loop with no priority at all */
59
        current->counter = -100;
60
        for (;;) {
61
                /*
62
                 * R4[26]00 have wait, R4[04]00 don't.
63
                 */
64
                if (wait_available && !need_resched)
65
                        __asm__(".set\tmips3\n\t"
66
                                "wait\n\t"
67
                                ".set\tmips0\n\t");
68
                schedule();
69
        }
70
}
71
 
72
asmlinkage int sys_fork(struct pt_regs *regs)
73
{
74
        return do_fork(SIGCHLD, regs->reg29, regs);
75
}
76
 
77
asmlinkage int sys_clone(struct pt_regs *regs)
78
{
79
        unsigned long clone_flags;
80
        unsigned long newsp;
81
 
82
        clone_flags = regs->reg4;
83
        newsp = regs->reg5;
84
        if (!newsp)
85
                newsp = regs->reg29;
86
        return do_fork(clone_flags, newsp, regs);
87
}
88
 
89
/*
90
 * sys_execve() executes a new program.
91
 */
92
asmlinkage int sys_execve(struct pt_regs *regs)
93
{
94
        int error;
95
        char * filename;
96
 
97
        error = getname((char *) regs->reg4, &filename);
98
        if (error)
99
                return error;
100
        error = do_execve(filename, (char **) regs->reg5,
101
                          (char **) regs->reg6, regs);
102
        putname(filename);
103
        return error;
104
}
105
 
106
/*
107
 * Do the indirect syscall syscall.
108
 */
109
asmlinkage int sys_syscall(unsigned long a0, unsigned long a1, unsigned long a2,
110
                           unsigned long a3, unsigned long a4, unsigned long a5,
111
                           unsigned long a6)
112
{
113
        syscall_t syscall;
114
 
115
        if (a0 > __NR_Linux + __NR_Linux_syscalls)
116
                return -ENOSYS;
117
 
118
        syscall = sys_call_table[a0];
119
        /*
120
         * Prevent stack overflow by recursive
121
         * syscall(__NR_syscall, __NR_syscall,...);
122
         */
123
        if (syscall == (syscall_t) sys_syscall)
124
                return -EINVAL;
125
 
126
        if (syscall == NULL)
127
                return -ENOSYS;
128
 
129
        return syscall((void *)a0, a1, a2, a3, a4, a5, a6);
130
}
131
 
132
void do_sys(struct pt_regs *regs)
133
{
134
        unsigned long syscallnr, usp;
135
        syscall_t syscall;
136
        int errno, narg;
137
 
138
        /*
139
         * Compute the return address;
140
         */
141
        if (regs->cp0_cause & CAUSEF_BD)
142
        {
143
                /*
144
                 * This syscall is in a branch delay slot.  Since we don't do
145
                 * branch delay slot handling we would get a process trying
146
                 * to do syscalls ever and ever again.  So better zap it.
147
                 */
148
                printk("%s: syscall in branch delay slot.\n", current->comm);
149
                current->sig->action[SIGILL-1].sa_handler = NULL;
150
                current->blocked &= ~(1<<(SIGILL-1));
151
                send_sig(SIGILL, current, 1);
152
                return;
153
        }
154
        regs->cp0_epc += 4;
155
 
156
        syscallnr = regs->reg2;
157
        if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
158
                goto illegal_syscall;
159
 
160
        syscall = sys_call_table[syscallnr];
161
        if (syscall == NULL)
162
                goto illegal_syscall;
163
 
164
        narg = sys_narg_table[syscallnr];
165
        if (narg > 4)
166
        {
167
                /*
168
                 * Verify that we can safely get the additional parameters
169
                 * from the user stack.  Of course I could read the params
170
                 * from unaligned addresses ...  Consider this a programming
171
                 * course caliber .45.
172
                 */
173
                usp = regs->reg29;
174
                if (usp & 3)
175
                {
176
                        printk("unaligned usp\n");
177
                        send_sig(SIGSEGV, current, 1);
178
                        regs->reg2 = EFAULT;
179
                        regs->reg7 = 1;
180
                        return;
181
                }
182
                errno = verify_area(VERIFY_READ, (void *) (usp + 16),
183
                                    (narg - 4) * sizeof(unsigned long));
184
                if (errno < 0)
185
                        goto bad_syscall;
186
        }
187
 
188
        if ((current->flags & PF_TRACESYS) == 0)
189
        {
190
                errno = do_syscalls(regs, syscall, narg);
191
                if (errno < 0 || current->errno)
192
                        goto bad_syscall;
193
 
194
                regs->reg2 = errno;
195
                regs->reg7 = 0;
196
        }
197
        else
198
        {
199
                syscall_trace();
200
 
201
                errno = do_syscalls(regs, syscall, narg);
202
                if (errno < 0 || current->errno)
203
                {
204
                        regs->reg2 = -errno;
205
                        regs->reg7 = 1;
206
                }
207
                else
208
                {
209
                        regs->reg2 = errno;
210
                        regs->reg7 = 0;
211
                }
212
 
213
                syscall_trace();
214
        }
215
        return;
216
 
217
bad_syscall:
218
        regs->reg2 = -errno;
219
        regs->reg7 = 1;
220
        return;
221
illegal_syscall:
222
        regs->reg2 = ENOSYS;
223
        regs->reg7 = 1;
224
        return;
225
}

powered by: WebSVN 2.1.0

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