1 /* $Id: sys_sparc.c,v 1.25 1998/10/21 03:21:15 davem Exp $ 2 * linux/arch/sparc64/kernel/sys_sparc.c 4 * This file contains various random system calls that 5 * have a non-standard calling sequence on the Linux/sparc 9 #include <linux/errno.h> 10 #include <linux/types.h> 11 #include <linux/sched.h> 13 #include <linux/file.h> 15 #include <linux/sem.h> 16 #include <linux/msg.h> 17 #include <linux/shm.h> 18 #include <linux/stat.h> 19 #include <linux/mman.h> 20 #include <linux/utsname.h> 21 #include <linux/smp.h> 22 #include <linux/smp_lock.h> 23 #include <linux/malloc.h> 25 #include <asm/uaccess.h> 27 #include <asm/utrap.h> 28 #include <asm/perfctr.h> 30 /* XXX Make this per-binary type, this way we can detect the type of 31 * XXX a binary. Every Sparc executable calls this very early on. 33 asmlinkage
unsigned longsys_getpagesize(void) 38 extern asmlinkage
unsigned longsys_brk(unsigned long brk
); 40 asmlinkage
unsigned longsparc_brk(unsigned long brk
) 42 if(brk
>=0x80000000000UL
)/* VM hole */ 43 return current
->mm
->brk
; 48 * sys_pipe() is the normal C calling standard for creating 49 * a pipe. It's not the way unix traditionally does this, though. 51 asmlinkage
intsparc_pipe(struct pt_regs
*regs
) 60 regs
->u_regs
[UREG_I1
] = fd
[1]; 68 * sys_ipc() is the de-multiplexer for the SysV IPC calls.. 70 * This is really horribly ugly. 73 asmlinkage
intsys_ipc(unsigned call
,int first
,int second
,unsigned long third
,void*ptr
,long fifth
) 78 /* No need for backward compatibility. We can start fresh... */ 83 err
=sys_semop(first
, (struct sembuf
*)ptr
, second
); 86 err
=sys_semget(first
, second
, (int)third
); 94 if(get_user(fourth
.__pad
, (void**)ptr
)) 96 err
=sys_semctl(first
, second
, (int)third
, fourth
); 106 err
=sys_msgsnd(first
, (struct msgbuf
*) ptr
, 110 err
=sys_msgrcv(first
, (struct msgbuf
*) ptr
, second
, fifth
, (int)third
); 113 err
=sys_msgget((key_t
) first
, second
); 116 err
=sys_msgctl(first
, second
, (struct msqid_ds
*) ptr
); 125 err
=sys_shmat(first
, (char*) ptr
, second
, (ulong
*) third
); 128 err
=sys_shmdt((char*)ptr
); 131 err
=sys_shmget(first
, second
, (int)third
); 134 err
=sys_shmctl(first
, second
, (struct shmid_ds
*) ptr
); 147 /* Linux version of mmap */ 148 asmlinkage
unsigned longsys_mmap(unsigned long addr
,unsigned long len
, 149 unsigned long prot
,unsigned long flags
,unsigned long fd
, 152 struct file
* file
= NULL
; 153 unsigned long retval
= -EBADF
; 155 down(¤t
->mm
->mmap_sem
); 157 if(!(flags
& MAP_ANONYMOUS
)) { 163 len
=PAGE_ALIGN(len
); 164 if(!(flags
& MAP_FIXED
) && !addr
) { 165 addr
=get_unmapped_area(addr
, len
); 171 if(current
->tss
.flags
& SPARC_FLAG_32BIT
) { 172 if(len
>0xf0000000UL
|| addr
>0xf0000000UL
- len
) 175 if(len
>=0x80000000000UL
|| 176 (addr
<0x80000000000UL
&& 177 addr
>0x80000000000UL
-len
)) 179 if(addr
>=0x80000000000ULL
&& addr
<0xfffff80000000000UL
) { 181 retval
= current
->mm
->brk
; 186 flags
&= ~(MAP_EXECUTABLE
| MAP_DENYWRITE
); 187 retval
=do_mmap(file
, addr
, len
, prot
, flags
, off
); 194 up(¤t
->mm
->mmap_sem
); 198 /* we come to here via sys_nis_syscall so it can setup the regs argument */ 199 asmlinkage
unsigned long 200 c_sys_nis_syscall(struct pt_regs
*regs
) 204 if(++count
<=20) {/* Don't make the system unusable, if someone goes stuck */ 205 printk("Unimplemented SPARC system call %ld\n",regs
->u_regs
[1]); 212 /* #define DEBUG_SPARC_BREAKPOINT */ 215 sparc_breakpoint(struct pt_regs
*regs
) 218 #ifdef DEBUG_SPARC_BREAKPOINT 219 printk("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs
->tpc
, regs
->tnpc
); 221 force_sig(SIGTRAP
, current
); 222 #ifdef DEBUG_SPARC_BREAKPOINT 223 printk("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs
->tpc
, regs
->tnpc
); 228 externvoidcheck_pending(int signum
); 230 asmlinkage
intsys_getdomainname(char*name
,int len
) 237 nlen
=strlen(system_utsname
.domainname
) +1; 241 if(len
> __NEW_UTS_LEN
) 243 if(copy_to_user(name
, system_utsname
.domainname
, len
)) 251 /* only AP+ systems have sys_aplib */ 252 asmlinkage
intsys_aplib(void) 257 asmlinkage
intsolaris_syscall(struct pt_regs
*regs
) 261 regs
->tpc
= regs
->tnpc
; 264 printk("For Solaris binary emulation you need solaris module loaded\n"); 266 send_sig(SIGSEGV
, current
,1); 271 asmlinkage
intsys_utrap_install(utrap_entry_t type
, utrap_handler_t new_p
, 272 utrap_handler_t new_d
, 273 utrap_handler_t
*old_p
, utrap_handler_t
*old_d
) 275 if(type
< UT_INSTRUCTION_EXCEPTION
|| type
> UT_TRAP_INSTRUCTION_31
) 277 if(new_p
== (utrap_handler_t
)(long)UTH_NOCHANGE
) { 279 if(!current
->tss
.utraps
) 280 put_user_ret(NULL
, old_p
, -EFAULT
); 282 put_user_ret((utrap_handler_t
)(current
->tss
.utraps
[type
]), old_p
, -EFAULT
); 285 put_user_ret(NULL
, old_d
, -EFAULT
); 289 if(!current
->tss
.utraps
) { 290 current
->tss
.utraps
=kmalloc((UT_TRAP_INSTRUCTION_31
+1)*sizeof(long), GFP_KERNEL
); 291 if(!current
->tss
.utraps
)return-ENOMEM
; 292 current
->tss
.utraps
[0] =1; 293 memset(current
->tss
.utraps
+1,0, UT_TRAP_INSTRUCTION_31
*sizeof(long)); 295 if((utrap_handler_t
)current
->tss
.utraps
[type
] != new_p
&& current
->tss
.utraps
[0] >1) { 296 long*p
= current
->tss
.utraps
; 298 current
->tss
.utraps
=kmalloc((UT_TRAP_INSTRUCTION_31
+1)*sizeof(long), GFP_KERNEL
); 299 if(!current
->tss
.utraps
) { 300 current
->tss
.utraps
= p
; 304 current
->tss
.utraps
[0] =1; 305 memcpy(current
->tss
.utraps
+1, p
+1, UT_TRAP_INSTRUCTION_31
*sizeof(long)); 309 put_user_ret((utrap_handler_t
)(current
->tss
.utraps
[type
]), old_p
, -EFAULT
); 311 put_user_ret(NULL
, old_d
, -EFAULT
); 312 current
->tss
.utraps
[type
] = (long)new_p
; 317 longsparc_memory_ordering(unsigned long model
,struct pt_regs
*regs
) 321 regs
->tstate
= (regs
->tstate
& ~TSTATE_MM
) | (model
<<14); 326 sys_sigaction(int sig
,const struct old_sigaction
*act
, 327 struct old_sigaction
*oact
) 329 struct k_sigaction new_ka
, old_ka
; 334 if(verify_area(VERIFY_READ
, act
,sizeof(*act
)) || 335 __get_user(new_ka
.sa
.sa_handler
, &act
->sa_handler
) || 336 __get_user(new_ka
.sa
.sa_restorer
, &act
->sa_restorer
)) 338 __get_user(new_ka
.sa
.sa_flags
, &act
->sa_flags
); 339 __get_user(mask
, &act
->sa_mask
); 340 siginitset(&new_ka
.sa
.sa_mask
, mask
); 341 new_ka
.ka_restorer
= NULL
; 344 ret
=do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
); 347 if(verify_area(VERIFY_WRITE
, oact
,sizeof(*oact
)) || 348 __put_user(old_ka
.sa
.sa_handler
, &oact
->sa_handler
) || 349 __put_user(old_ka
.sa
.sa_restorer
, &oact
->sa_restorer
)) 351 __put_user(old_ka
.sa
.sa_flags
, &oact
->sa_flags
); 352 __put_user(old_ka
.sa
.sa_mask
.sig
[0], &oact
->sa_mask
); 359 sys_rt_sigaction(int sig
,const struct sigaction
*act
,struct sigaction
*oact
, 360 void*restorer
,size_t sigsetsize
) 362 struct k_sigaction new_ka
, old_ka
; 365 /* XXX: Don't preclude handling different sized sigset_t's. */ 366 if(sigsetsize
!=sizeof(sigset_t
)) 370 new_ka
.ka_restorer
= restorer
; 371 if(copy_from_user(&new_ka
.sa
, act
,sizeof(*act
))) 375 ret
=do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
); 378 if(copy_to_user(oact
, &old_ka
.sa
,sizeof(*oact
))) 385 /* Invoked by rtrap code to update performance counters in 389 update_perfctrs(void) 391 unsigned long pic
, tmp
; 394 tmp
= (current
->tss
.kernel_cntd0
+= (unsigned int)pic
); 395 __put_user(tmp
, current
->tss
.user_cntd0
); 396 tmp
= (current
->tss
.kernel_cntd1
+= (pic
>>32)); 397 __put_user(tmp
, current
->tss
.user_cntd1
); 402 sys_perfctr(int opcode
,unsigned long arg0
,unsigned long arg1
,unsigned long arg2
) 408 current
->tss
.pcr_reg
= arg2
; 409 current
->tss
.user_cntd0
= (u64
*) arg0
; 410 current
->tss
.user_cntd1
= (u64
*) arg1
; 411 current
->tss
.kernel_cntd0
= 412 current
->tss
.kernel_cntd1
=0; 415 current
->tss
.flags
|= SPARC_FLAG_PERFCTR
; 420 if((current
->tss
.flags
& SPARC_FLAG_PERFCTR
) !=0) { 421 current
->tss
.user_cntd0
= 422 current
->tss
.user_cntd1
= NULL
; 423 current
->tss
.pcr_reg
=0; 425 current
->tss
.flags
&= ~(SPARC_FLAG_PERFCTR
); 431 unsigned long pic
, tmp
; 433 if(!(current
->tss
.flags
& SPARC_FLAG_PERFCTR
)) { 438 tmp
= (current
->tss
.kernel_cntd0
+= (unsigned int)pic
); 439 err
|=__put_user(tmp
, current
->tss
.user_cntd0
); 440 tmp
= (current
->tss
.kernel_cntd1
+= (pic
>>32)); 441 err
|=__put_user(tmp
, current
->tss
.user_cntd1
); 447 if(!(current
->tss
.flags
& SPARC_FLAG_PERFCTR
)) { 451 current
->tss
.kernel_cntd0
= 452 current
->tss
.kernel_cntd1
=0; 456 case PERFCTR_SETPCR
: { 457 u64
*user_pcr
= (u64
*)arg0
; 458 if(!(current
->tss
.flags
& SPARC_FLAG_PERFCTR
)) { 462 err
|=__get_user(current
->tss
.pcr_reg
, user_pcr
); 463 write_pcr(current
->tss
.pcr_reg
); 464 current
->tss
.kernel_cntd0
= 465 current
->tss
.kernel_cntd1
=0; 470 case PERFCTR_GETPCR
: { 471 u64
*user_pcr
= (u64
*)arg0
; 472 if(!(current
->tss
.flags
& SPARC_FLAG_PERFCTR
)) { 476 err
|=__put_user(current
->tss
.pcr_reg
, user_pcr
);