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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: sys_sparc.c,v 1.1.1.1 2004-04-15 01:34:06 phoenix Exp $
2
 * linux/arch/sparc64/kernel/sys_sparc.c
3
 *
4
 * This file contains various random system calls that
5
 * have a non-standard calling sequence on the Linux/sparc
6
 * platform.
7
 */
8
 
9
#include <linux/config.h>
10
#include <linux/errno.h>
11
#include <linux/types.h>
12
#include <linux/sched.h>
13
#include <linux/fs.h>
14
#include <linux/file.h>
15
#include <linux/mm.h>
16
#include <linux/sem.h>
17
#include <linux/msg.h>
18
#include <linux/shm.h>
19
#include <linux/stat.h>
20
#include <linux/mman.h>
21
#include <linux/utsname.h>
22
#include <linux/smp.h>
23
#include <linux/smp_lock.h>
24
#include <linux/slab.h>
25
#include <linux/ipc.h>
26
#include <linux/personality.h>
27
 
28
#include <asm/uaccess.h>
29
#include <asm/ipc.h>
30
#include <asm/utrap.h>
31
#include <asm/perfctr.h>
32
 
33
/* #define DEBUG_UNIMP_SYSCALL */
34
 
35
/* XXX Make this per-binary type, this way we can detect the type of
36
 * XXX a binary.  Every Sparc executable calls this very early on.
37
 */
38
asmlinkage unsigned long sys_getpagesize(void)
39
{
40
        return PAGE_SIZE;
41
}
42
 
43
#define COLOUR_ALIGN(addr,pgoff)                \
44
        ((((addr)+SHMLBA-1)&~(SHMLBA-1)) +      \
45
         (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
46
 
47
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
48
{
49
        struct vm_area_struct * vmm;
50
        unsigned long task_size = TASK_SIZE;
51
        int do_color_align;
52
 
53
        if (flags & MAP_FIXED) {
54
                /* We do not accept a shared mapping if it would violate
55
                 * cache aliasing constraints.
56
                 */
57
                if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
58
                        return -EINVAL;
59
                return addr;
60
        }
61
 
62
        if (current->thread.flags & SPARC_FLAG_32BIT)
63
                task_size = 0xf0000000UL;
64
        if (len > task_size || len > -PAGE_OFFSET)
65
                return -ENOMEM;
66
        if (!addr)
67
                addr = TASK_UNMAPPED_BASE;
68
 
69
        do_color_align = 0;
70
        if (filp || (flags & MAP_SHARED))
71
                do_color_align = 1;
72
 
73
        if (do_color_align)
74
                addr = COLOUR_ALIGN(addr, pgoff);
75
        else
76
                addr = PAGE_ALIGN(addr);
77
        task_size -= len;
78
 
79
        for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
80
                /* At this point:  (!vmm || addr < vmm->vm_end). */
81
                if (addr < PAGE_OFFSET && -PAGE_OFFSET - len < addr) {
82
                        addr = PAGE_OFFSET;
83
                        vmm = find_vma(current->mm, PAGE_OFFSET);
84
                }
85
                if (task_size < addr)
86
                        return -ENOMEM;
87
                if (!vmm || addr + len <= vmm->vm_start)
88
                        return addr;
89
                addr = vmm->vm_end;
90
                if (do_color_align)
91
                        addr = COLOUR_ALIGN(addr, pgoff);
92
        }
93
}
94
 
95
/* Try to align mapping such that we align it as much as possible. */
96
unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags)
97
{
98
        unsigned long align_goal, addr = -ENOMEM;
99
 
100
        if (flags & MAP_FIXED) {
101
                /* Ok, don't mess with it. */
102
                return get_unmapped_area(NULL, addr, len, pgoff, flags);
103
        }
104
        flags &= ~MAP_SHARED;
105
 
106
        align_goal = PAGE_SIZE;
107
        if (len >= (4UL * 1024 * 1024))
108
                align_goal = (4UL * 1024 * 1024);
109
        else if (len >= (512UL * 1024))
110
                align_goal = (512UL * 1024);
111
        else if (len >= (64UL * 1024))
112
                align_goal = (64UL * 1024);
113
 
114
        do {
115
                addr = get_unmapped_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags);
116
                if (!(addr & ~PAGE_MASK)) {
117
                        addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL);
118
                        break;
119
                }
120
 
121
                if (align_goal == (4UL * 1024 * 1024))
122
                        align_goal = (512UL * 1024);
123
                else if (align_goal == (512UL * 1024))
124
                        align_goal = (64UL * 1024);
125
                else
126
                        align_goal = PAGE_SIZE;
127
        } while ((addr & ~PAGE_MASK) && align_goal > PAGE_SIZE);
128
 
129
        /* Mapping is smaller than 64K or larger areas could not
130
         * be obtained.
131
         */
132
        if (addr & ~PAGE_MASK)
133
                addr = get_unmapped_area(NULL, orig_addr, len, pgoff, flags);
134
 
135
        return addr;
136
}
137
 
138
extern asmlinkage unsigned long sys_brk(unsigned long brk);
139
 
140
asmlinkage unsigned long sparc_brk(unsigned long brk)
141
{
142
        /* People could try to be nasty and use ta 0x6d in 32bit programs */
143
        if ((current->thread.flags & SPARC_FLAG_32BIT) &&
144
            brk >= 0xf0000000UL)
145
                return current->mm->brk;
146
 
147
        if ((current->mm->brk & PAGE_OFFSET) != (brk & PAGE_OFFSET))
148
                return current->mm->brk;
149
        return sys_brk(brk);
150
}
151
 
152
/*
153
 * sys_pipe() is the normal C calling standard for creating
154
 * a pipe. It's not the way unix traditionally does this, though.
155
 */
156
asmlinkage int sparc_pipe(struct pt_regs *regs)
157
{
158
        int fd[2];
159
        int error;
160
 
161
        error = do_pipe(fd);
162
        if (error)
163
                goto out;
164
        regs->u_regs[UREG_I1] = fd[1];
165
        error = fd[0];
166
out:
167
        return error;
168
}
169
 
170
/*
171
 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
172
 *
173
 * This is really horribly ugly.
174
 */
175
 
176
asmlinkage int sys_ipc (unsigned call, int first, int second, unsigned long third, void *ptr, long fifth)
177
{
178
        int err;
179
 
180
        /* No need for backward compatibility. We can start fresh... */
181
 
182
        if (call <= SEMCTL)
183
                switch (call) {
184
                case SEMOP:
185
                        err = sys_semtimedop (first, (struct sembuf *)ptr, second, NULL);
186
                        goto out;
187
                case SEMTIMEDOP:
188
                        err = sys_semtimedop (first, (struct sembuf *)ptr, second, (const struct timespec *) fifth);
189
                        goto out;
190
                case SEMGET:
191
                        err = sys_semget (first, second, (int)third);
192
                        goto out;
193
                case SEMCTL: {
194
                        union semun fourth;
195
                        err = -EINVAL;
196
                        if (!ptr)
197
                                goto out;
198
                        err = -EFAULT;
199
                        if(get_user(fourth.__pad, (void **)ptr))
200
                                goto out;
201
                        err = sys_semctl (first, second | IPC_64, (int)third, fourth);
202
                        goto out;
203
                        }
204
                default:
205
                        err = -ENOSYS;
206
                        goto out;
207
                }
208
        if (call <= MSGCTL)
209
                switch (call) {
210
                case MSGSND:
211
                        err = sys_msgsnd (first, (struct msgbuf *) ptr,
212
                                          second, (int)third);
213
                        goto out;
214
                case MSGRCV:
215
                        err = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, (int)third);
216
                        goto out;
217
                case MSGGET:
218
                        err = sys_msgget ((key_t) first, second);
219
                        goto out;
220
                case MSGCTL:
221
                        err = sys_msgctl (first, second | IPC_64, (struct msqid_ds *) ptr);
222
                        goto out;
223
                default:
224
                        err = -ENOSYS;
225
                        goto out;
226
                }
227
        if (call <= SHMCTL)
228
                switch (call) {
229
                case SHMAT: {
230
                        ulong raddr;
231
                        err = sys_shmat (first, (char *) ptr, second, &raddr);
232
                        if (!err) {
233
                                if (put_user(raddr, (ulong *) third))
234
                                        err = -EFAULT;
235
                        }
236
                        goto out;
237
                }
238
                case SHMDT:
239
                        err = sys_shmdt ((char *)ptr);
240
                        goto out;
241
                case SHMGET:
242
                        err = sys_shmget (first, second, (int)third);
243
                        goto out;
244
                case SHMCTL:
245
                        err = sys_shmctl (first, second | IPC_64, (struct shmid_ds *) ptr);
246
                        goto out;
247
                default:
248
                        err = -ENOSYS;
249
                        goto out;
250
                }
251
        else
252
                err = -ENOSYS;
253
out:
254
        return err;
255
}
256
 
257
extern asmlinkage int sys_newuname(struct new_utsname * name);
258
 
259
asmlinkage int sparc64_newuname(struct new_utsname * name)
260
{
261
        int ret = sys_newuname(name);
262
 
263
        if (current->personality == PER_LINUX32 && !ret) {
264
                ret = copy_to_user(name->machine, "sparc\0\0", 8);
265
        }
266
        return ret;
267
}
268
 
269
extern asmlinkage long sys_personality(unsigned long);
270
 
271
asmlinkage int sparc64_personality(unsigned long personality)
272
{
273
        int ret;
274
 
275
        if (current->personality == PER_LINUX32 && personality == PER_LINUX)
276
                personality = PER_LINUX32;
277
        ret = sys_personality(personality);
278
        if (ret == PER_LINUX32)
279
                ret = PER_LINUX;
280
 
281
        return ret;
282
}
283
 
284
/* Linux version of mmap */
285
asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
286
        unsigned long prot, unsigned long flags, unsigned long fd,
287
        unsigned long off)
288
{
289
        struct file * file = NULL;
290
        unsigned long retval = -EBADF;
291
 
292
        if (!(flags & MAP_ANONYMOUS)) {
293
                file = fget(fd);
294
                if (!file)
295
                        goto out;
296
        }
297
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
298
        len = PAGE_ALIGN(len);
299
        retval = -EINVAL;
300
 
301
        if (current->thread.flags & SPARC_FLAG_32BIT) {
302
                if (len > 0xf0000000UL ||
303
                    ((flags & MAP_FIXED) && addr > 0xf0000000UL - len))
304
                        goto out_putf;
305
        } else {
306
                if (len > -PAGE_OFFSET ||
307
                    ((flags & MAP_FIXED) &&
308
                     addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET))
309
                        goto out_putf;
310
        }
311
 
312
        down_write(&current->mm->mmap_sem);
313
        retval = do_mmap(file, addr, len, prot, flags, off);
314
        up_write(&current->mm->mmap_sem);
315
 
316
out_putf:
317
        if (file)
318
                fput(file);
319
out:
320
        return retval;
321
}
322
 
323
asmlinkage long sys64_munmap(unsigned long addr, size_t len)
324
{
325
        long ret;
326
 
327
        if (len > -PAGE_OFFSET ||
328
            (addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET))
329
                return -EINVAL;
330
        down_write(&current->mm->mmap_sem);
331
        ret = do_munmap(current->mm, addr, len);
332
        up_write(&current->mm->mmap_sem);
333
        return ret;
334
}
335
 
336
extern unsigned long do_mremap(unsigned long addr,
337
        unsigned long old_len, unsigned long new_len,
338
        unsigned long flags, unsigned long new_addr);
339
 
340
asmlinkage unsigned long sys64_mremap(unsigned long addr,
341
        unsigned long old_len, unsigned long new_len,
342
        unsigned long flags, unsigned long new_addr)
343
{
344
        struct vm_area_struct *vma;
345
        unsigned long ret = -EINVAL;
346
        if (current->thread.flags & SPARC_FLAG_32BIT)
347
                goto out;
348
        if (old_len > -PAGE_OFFSET || new_len > -PAGE_OFFSET)
349
                goto out;
350
        if (addr < PAGE_OFFSET && addr + old_len > -PAGE_OFFSET)
351
                goto out;
352
        down_write(&current->mm->mmap_sem);
353
        if (flags & MREMAP_FIXED) {
354
                if (new_addr < PAGE_OFFSET &&
355
                    new_addr + new_len > -PAGE_OFFSET)
356
                        goto out_sem;
357
        } else if (addr < PAGE_OFFSET && addr + new_len > -PAGE_OFFSET) {
358
                unsigned long map_flags = 0;
359
                struct file *file = NULL;
360
 
361
                ret = -ENOMEM;
362
                if (!(flags & MREMAP_MAYMOVE))
363
                        goto out_sem;
364
 
365
                vma = find_vma(current->mm, addr);
366
                if (vma) {
367
                        if (vma->vm_flags & VM_SHARED)
368
                                map_flags |= MAP_SHARED;
369
                        file = vma->vm_file;
370
                }
371
 
372
                /* MREMAP_FIXED checked above. */
373
                new_addr = get_unmapped_area(file, addr, new_len,
374
                                    vma ? vma->vm_pgoff : 0,
375
                                    map_flags);
376
                ret = new_addr;
377
                if (new_addr & ~PAGE_MASK)
378
                        goto out_sem;
379
                flags |= MREMAP_FIXED;
380
        }
381
        ret = do_mremap(addr, old_len, new_len, flags, new_addr);
382
out_sem:
383
        up_write(&current->mm->mmap_sem);
384
out:
385
        return ret;
386
}
387
 
388
/* we come to here via sys_nis_syscall so it can setup the regs argument */
389
asmlinkage unsigned long
390
c_sys_nis_syscall (struct pt_regs *regs)
391
{
392
        static int count;
393
 
394
        /* Don't make the system unusable, if someone goes stuck */
395
        if (count++ > 5)
396
                return -ENOSYS;
397
 
398
        printk ("Unimplemented SPARC system call %ld\n",regs->u_regs[1]);
399
#ifdef DEBUG_UNIMP_SYSCALL      
400
        show_regs (regs);
401
#endif
402
 
403
        return -ENOSYS;
404
}
405
 
406
/* #define DEBUG_SPARC_BREAKPOINT */
407
 
408
asmlinkage void
409
sparc_breakpoint (struct pt_regs *regs)
410
{
411
        siginfo_t info;
412
 
413
        if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
414
                regs->tpc &= 0xffffffff;
415
                regs->tnpc &= 0xffffffff;
416
        }
417
#ifdef DEBUG_SPARC_BREAKPOINT
418
        printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc);
419
#endif
420
        info.si_signo = SIGTRAP;
421
        info.si_errno = 0;
422
        info.si_code = TRAP_BRKPT;
423
        info.si_addr = (void *)regs->tpc;
424
        info.si_trapno = 0;
425
        force_sig_info(SIGTRAP, &info, current);
426
#ifdef DEBUG_SPARC_BREAKPOINT
427
        printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc);
428
#endif
429
}
430
 
431
extern void check_pending(int signum);
432
 
433
asmlinkage int sys_getdomainname(char *name, int len)
434
{
435
        int nlen;
436
        int err = -EFAULT;
437
 
438
        down_read(&uts_sem);
439
 
440
        nlen = strlen(system_utsname.domainname) + 1;
441
 
442
        if (nlen < len)
443
                len = nlen;
444
        if(len > __NEW_UTS_LEN)
445
                goto done;
446
        if(copy_to_user(name, system_utsname.domainname, len))
447
                goto done;
448
        err = 0;
449
done:
450
        up_read(&uts_sem);
451
        return err;
452
}
453
 
454
/* only AP+ systems have sys_aplib */
455
asmlinkage int sys_aplib(void)
456
{
457
        return -ENOSYS;
458
}
459
 
460
asmlinkage int solaris_syscall(struct pt_regs *regs)
461
{
462
        static int count;
463
 
464
        regs->tpc = regs->tnpc;
465
        regs->tnpc += 4;
466
        if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
467
                regs->tpc &= 0xffffffff;
468
                regs->tnpc &= 0xffffffff;
469
        }
470
        if(++count <= 5) {
471
                printk ("For Solaris binary emulation you need solaris module loaded\n");
472
                show_regs (regs);
473
        }
474
        send_sig(SIGSEGV, current, 1);
475
 
476
        return -ENOSYS;
477
}
478
 
479
#ifndef CONFIG_SUNOS_EMUL
480
asmlinkage int sunos_syscall(struct pt_regs *regs)
481
{
482
        static int count;
483
 
484
        regs->tpc = regs->tnpc;
485
        regs->tnpc += 4;
486
        if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
487
                regs->tpc &= 0xffffffff;
488
                regs->tnpc &= 0xffffffff;
489
        }
490
        if(++count <= 20)
491
                printk ("SunOS binary emulation not compiled in\n");
492
        force_sig(SIGSEGV, current);
493
 
494
        return -ENOSYS;
495
}
496
#endif
497
 
498
asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p,
499
                                 utrap_handler_t new_d,
500
                                 utrap_handler_t *old_p, utrap_handler_t *old_d)
501
{
502
        if (type < UT_INSTRUCTION_EXCEPTION || type > UT_TRAP_INSTRUCTION_31)
503
                return -EINVAL;
504
        if (new_p == (utrap_handler_t)(long)UTH_NOCHANGE) {
505
                if (old_p) {
506
                        if (!current->thread.utraps) {
507
                                if (put_user(NULL, old_p))
508
                                        return -EFAULT;
509
                        } else {
510
                                if (put_user((utrap_handler_t)(current->thread.utraps[type]), old_p))
511
                                        return -EFAULT;
512
                        }
513
                }
514
                if (old_d) {
515
                        if (put_user(NULL, old_d))
516
                                return -EFAULT;
517
                }
518
                return 0;
519
        }
520
        if (!current->thread.utraps) {
521
                current->thread.utraps =
522
                        kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL);
523
                if (!current->thread.utraps) return -ENOMEM;
524
                current->thread.utraps[0] = 1;
525
                memset(current->thread.utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long));
526
        } else {
527
                if ((utrap_handler_t)current->thread.utraps[type] != new_p &&
528
                    current->thread.utraps[0] > 1) {
529
                        long *p = current->thread.utraps;
530
 
531
                        current->thread.utraps =
532
                                kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long),
533
                                        GFP_KERNEL);
534
                        if (!current->thread.utraps) {
535
                                current->thread.utraps = p;
536
                                return -ENOMEM;
537
                        }
538
                        p[0]--;
539
                        current->thread.utraps[0] = 1;
540
                        memcpy(current->thread.utraps+1, p+1,
541
                               UT_TRAP_INSTRUCTION_31*sizeof(long));
542
                }
543
        }
544
        if (old_p) {
545
                if (put_user((utrap_handler_t)(current->thread.utraps[type]), old_p))
546
                        return -EFAULT;
547
        }
548
        if (old_d) {
549
                if (put_user(NULL, old_d))
550
                        return -EFAULT;
551
        }
552
        current->thread.utraps[type] = (long)new_p;
553
 
554
        return 0;
555
}
556
 
557
long sparc_memory_ordering(unsigned long model, struct pt_regs *regs)
558
{
559
        if (model >= 3)
560
                return -EINVAL;
561
        regs->tstate = (regs->tstate & ~TSTATE_MM) | (model << 14);
562
        return 0;
563
}
564
 
565
asmlinkage int
566
sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,
567
                 void *restorer, size_t sigsetsize)
568
{
569
        struct k_sigaction new_ka, old_ka;
570
        int ret;
571
 
572
        /* XXX: Don't preclude handling different sized sigset_t's.  */
573
        if (sigsetsize != sizeof(sigset_t))
574
                return -EINVAL;
575
 
576
        if (act) {
577
                new_ka.ka_restorer = restorer;
578
                if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
579
                        return -EFAULT;
580
        }
581
 
582
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
583
 
584
        if (!ret && oact) {
585
                if (copy_to_user(oact, &old_ka.sa, sizeof(*oact)))
586
                        return -EFAULT;
587
        }
588
 
589
        return ret;
590
}
591
 
592
/* Invoked by rtrap code to update performance counters in
593
 * user space.
594
 */
595
asmlinkage void
596
update_perfctrs(void)
597
{
598
        unsigned long pic, tmp;
599
 
600
        read_pic(pic);
601
        tmp = (current->thread.kernel_cntd0 += (unsigned int)pic);
602
        __put_user(tmp, current->thread.user_cntd0);
603
        tmp = (current->thread.kernel_cntd1 += (pic >> 32));
604
        __put_user(tmp, current->thread.user_cntd1);
605
        reset_pic();
606
}
607
 
608
asmlinkage int
609
sys_perfctr(int opcode, unsigned long arg0, unsigned long arg1, unsigned long arg2)
610
{
611
        int err = 0;
612
 
613
        switch(opcode) {
614
        case PERFCTR_ON:
615
                current->thread.pcr_reg = arg2;
616
                current->thread.user_cntd0 = (u64 *) arg0;
617
                current->thread.user_cntd1 = (u64 *) arg1;
618
                current->thread.kernel_cntd0 =
619
                        current->thread.kernel_cntd1 = 0;
620
                write_pcr(arg2);
621
                reset_pic();
622
                current->thread.flags |= SPARC_FLAG_PERFCTR;
623
                break;
624
 
625
        case PERFCTR_OFF:
626
                err = -EINVAL;
627
                if ((current->thread.flags & SPARC_FLAG_PERFCTR) != 0) {
628
                        current->thread.user_cntd0 =
629
                                current->thread.user_cntd1 = NULL;
630
                        current->thread.pcr_reg = 0;
631
                        write_pcr(0);
632
                        current->thread.flags &= ~(SPARC_FLAG_PERFCTR);
633
                        err = 0;
634
                }
635
                break;
636
 
637
        case PERFCTR_READ: {
638
                unsigned long pic, tmp;
639
 
640
                if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
641
                        err = -EINVAL;
642
                        break;
643
                }
644
                read_pic(pic);
645
                tmp = (current->thread.kernel_cntd0 += (unsigned int)pic);
646
                err |= __put_user(tmp, current->thread.user_cntd0);
647
                tmp = (current->thread.kernel_cntd1 += (pic >> 32));
648
                err |= __put_user(tmp, current->thread.user_cntd1);
649
                reset_pic();
650
                break;
651
        }
652
 
653
        case PERFCTR_CLRPIC:
654
                if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
655
                        err = -EINVAL;
656
                        break;
657
                }
658
                current->thread.kernel_cntd0 =
659
                        current->thread.kernel_cntd1 = 0;
660
                reset_pic();
661
                break;
662
 
663
        case PERFCTR_SETPCR: {
664
                u64 *user_pcr = (u64 *)arg0;
665
                if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
666
                        err = -EINVAL;
667
                        break;
668
                }
669
                err |= __get_user(current->thread.pcr_reg, user_pcr);
670
                write_pcr(current->thread.pcr_reg);
671
                current->thread.kernel_cntd0 =
672
                        current->thread.kernel_cntd1 = 0;
673
                reset_pic();
674
                break;
675
        }
676
 
677
        case PERFCTR_GETPCR: {
678
                u64 *user_pcr = (u64 *)arg0;
679
                if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
680
                        err = -EINVAL;
681
                        break;
682
                }
683
                err |= __put_user(current->thread.pcr_reg, user_pcr);
684
                break;
685
        }
686
 
687
        default:
688
                err = -EINVAL;
689
                break;
690
        };
691
        return err;
692
}

powered by: WebSVN 2.1.0

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