1 /* 2 * linux/arch/m68k/kernel/sys_m68k.c 3 * 4 * This file contains various random system calls that 5 * have a non-standard calling sequence on the Linux/m68k 6 * platform. 7 */ 8 9 #include <linux/capability.h> 10 #include <linux/errno.h> 11 #include <linux/sched.h> 12 #include <linux/mm.h> 13 #include <linux/smp.h> 14 #include <linux/smp_lock.h> 15 #include <linux/sem.h> 16 #include <linux/msg.h> 17 #include <linux/shm.h> 18 #include <linux/stat.h> 19 #include <linux/syscalls.h> 20 #include <linux/mman.h> 21 #include <linux/file.h> 22 #include <linux/utsname.h> 23 24 #include <asm/setup.h> 25 #include <asm/uaccess.h> 26 #include <asm/cachectl.h> 27 #include <asm/traps.h> 28 #include <asm/ipc.h> 29 #include <asm/page.h> 30 #include <asm/unistd.h> 31 32 /* 33 * sys_pipe() is the normal C calling standard for creating 34 * a pipe. It's not the way unix traditionally does this, though. 35 */ 36 asmlinkage int sys_pipe(unsigned long __user * fildes) 37 { 38 int fd[2]; 39 int error; 40 41 error = do_pipe(fd); 42 if (!error) { 43 if (copy_to_user(fildes, fd, 2*sizeof(int))) 44 error = -EFAULT; 45 } 46 return error; 47 } 48 49 /* common code for old and new mmaps */ 50 static inline long do_mmap2( 51 unsigned long addr, unsigned long len, 52 unsigned long prot, unsigned long flags, 53 unsigned long fd, unsigned long pgoff) 54 { 55 int error = -EBADF; 56 struct file * file = NULL; 57 58 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 59 if (!(flags & MAP_ANONYMOUS)) { 60 file = fget(fd); 61 if (!file) 62 goto out; 63 } 64 65 down_write(¤t->mm->mmap_sem); 66 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 67 up_write(¤t->mm->mmap_sem); 68 69 if (file) 70 fput(file); 71 out: 72 return error; 73 } 74 75 asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, 76 unsigned long prot, unsigned long flags, 77 unsigned long fd, unsigned long pgoff) 78 { 79 return do_mmap2(addr, len, prot, flags, fd, pgoff); 80 } 81 82 /* 83 * Perform the select(nd, in, out, ex, tv) and mmap() system 84 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to 85 * handle more than 4 system call parameters, so these system calls 86 * used a memory block for parameter passing.. 87 */ 88 89 struct mmap_arg_struct { 90 unsigned long addr; 91 unsigned long len; 92 unsigned long prot; 93 unsigned long flags; 94 unsigned long fd; 95 unsigned long offset; 96 }; 97 98 asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) 99 { 100 struct mmap_arg_struct a; 101 int error = -EFAULT; 102 103 if (copy_from_user(&a, arg, sizeof(a))) 104 goto out; 105 106 error = -EINVAL; 107 if (a.offset & ~PAGE_MASK) 108 goto out; 109 110 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 111 112 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 113 out: 114 return error; 115 } 116 117 #if 0 118 struct mmap_arg_struct64 { 119 __u32 addr; 120 __u32 len; 121 __u32 prot; 122 __u32 flags; 123 __u64 offset; /* 64 bits */ 124 __u32 fd; 125 }; 126 127 asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) 128 { 129 int error = -EFAULT; 130 struct file * file = NULL; 131 struct mmap_arg_struct64 a; 132 unsigned long pgoff; 133 134 if (copy_from_user(&a, arg, sizeof(a))) 135 return -EFAULT; 136 137 if ((long)a.offset & ~PAGE_MASK) 138 return -EINVAL; 139 140 pgoff = a.offset >> PAGE_SHIFT; 141 if ((a.offset >> PAGE_SHIFT) != pgoff) 142 return -EINVAL; 143 144 if (!(a.flags & MAP_ANONYMOUS)) { 145 error = -EBADF; 146 file = fget(a.fd); 147 if (!file) 148 goto out; 149 } 150 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 151 152 down_write(¤t->mm->mmap_sem); 153 error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); 154 up_write(¤t->mm->mmap_sem); 155 if (file) 156 fput(file); 157 out: 158 return error; 159 } 160 #endif 161 162 struct sel_arg_struct { 163 unsigned long n; 164 fd_set __user *inp, *outp, *exp; 165 struct timeval __user *tvp; 166 }; 167 168 asmlinkage int old_select(struct sel_arg_struct __user *arg) 169 { 170 struct sel_arg_struct a; 171 172 if (copy_from_user(&a, arg, sizeof(a))) 173 return -EFAULT; 174 /* sys_select() does the appropriate kernel locking */ 175 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); 176 } 177 178 /* 179 * sys_ipc() is the de-multiplexer for the SysV IPC calls.. 180 * 181 * This is really horribly ugly. 182 */ 183 asmlinkage int sys_ipc (uint call, int first, int second, 184 int third, void __user *ptr, long fifth) 185 { 186 int version, ret; 187 188 version = call >> 16; /* hack for backward compatibility */ 189 call &= 0xffff; 190 191 if (call <= SEMCTL) 192 switch (call) { 193 case SEMOP: 194 return sys_semop (first, ptr, second); 195 case SEMGET: 196 return sys_semget (first, second, third); 197 case SEMCTL: { 198 union semun fourth; 199 if (!ptr) 200 return -EINVAL; 201 if (get_user(fourth.__pad, (void __user *__user *) ptr)) 202 return -EFAULT; 203 return sys_semctl (first, second, third, fourth); 204 } 205 default: 206 return -ENOSYS; 207 } 208 if (call <= MSGCTL) 209 switch (call) { 210 case MSGSND: 211 return sys_msgsnd (first, ptr, second, third); 212 case MSGRCV: 213 switch (version) { 214 case 0: { 215 struct ipc_kludge tmp; 216 if (!ptr) 217 return -EINVAL; 218 if (copy_from_user (&tmp, ptr, sizeof (tmp))) 219 return -EFAULT; 220 return sys_msgrcv (first, tmp.msgp, second, 221 tmp.msgtyp, third); 222 } 223 default: 224 return sys_msgrcv (first, ptr, 225 second, fifth, third); 226 } 227 case MSGGET: 228 return sys_msgget ((key_t) first, second); 229 case MSGCTL: 230 return sys_msgctl (first, second, ptr); 231 default: 232 return -ENOSYS; 233 } 234 if (call <= SHMCTL) 235 switch (call) { 236 case SHMAT: 237 switch (version) { 238 default: { 239 ulong raddr; 240 ret = do_shmat (first, ptr, second, &raddr); 241 if (ret) 242 return ret; 243 return put_user (raddr, (ulong __user *) third); 244 } 245 } 246 case SHMDT: 247 return sys_shmdt (ptr); 248 case SHMGET: 249 return sys_shmget (first, second, third); 250 case SHMCTL: 251 return sys_shmctl (first, second, ptr); 252 default: 253 return -ENOSYS; 254 } 255 256 return -EINVAL; 257 } 258 259 /* Convert virtual (user) address VADDR to physical address PADDR */ 260 #define virt_to_phys_040(vaddr) \ 261 ({ \ 262 unsigned long _mmusr, _paddr; \ 263 \ 264 __asm__ __volatile__ (".chip 68040\n\t" \ 265 "ptestr (%1)\n\t" \ 266 "movec %%mmusr,%0\n\t" \ 267 ".chip 68k" \ 268 : "=r" (_mmusr) \ 269 : "a" (vaddr)); \ 270 _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \ 271 _paddr; \ 272 }) 273 274 static inline int 275 cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len) 276 { 277 unsigned long paddr, i; 278 279 switch (scope) 280 { 281 case FLUSH_SCOPE_ALL: 282 switch (cache) 283 { 284 case FLUSH_CACHE_DATA: 285 /* This nop is needed for some broken versions of the 68040. */ 286 __asm__ __volatile__ ("nop\n\t" 287 ".chip 68040\n\t" 288 "cpusha %dc\n\t" 289 ".chip 68k"); 290 break; 291 case FLUSH_CACHE_INSN: 292 __asm__ __volatile__ ("nop\n\t" 293 ".chip 68040\n\t" 294 "cpusha %ic\n\t" 295 ".chip 68k"); 296 break; 297 default: 298 case FLUSH_CACHE_BOTH: 299 __asm__ __volatile__ ("nop\n\t" 300 ".chip 68040\n\t" 301 "cpusha %bc\n\t" 302 ".chip 68k"); 303 break; 304 } 305 break; 306 307 case FLUSH_SCOPE_LINE: 308 /* Find the physical address of the first mapped page in the 309 address range. */ 310 if ((paddr = virt_to_phys_040(addr))) { 311 paddr += addr & ~(PAGE_MASK | 15); 312 len = (len + (addr & 15) + 15) >> 4; 313 } else { 314 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); 315 316 if (len <= tmp) 317 return 0; 318 addr += tmp; 319 len -= tmp; 320 tmp = PAGE_SIZE; 321 for (;;) 322 { 323 if ((paddr = virt_to_phys_040(addr))) 324 break; 325 if (len <= tmp) 326 return 0; 327 addr += tmp; 328 len -= tmp; 329 } 330 len = (len + 15) >> 4; 331 } 332 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; 333 while (len--) 334 { 335 switch (cache) 336 { 337 case FLUSH_CACHE_DATA: 338 __asm__ __volatile__ ("nop\n\t" 339 ".chip 68040\n\t" 340 "cpushl %%dc,(%0)\n\t" 341 ".chip 68k" 342 : : "a" (paddr)); 343 break; 344 case FLUSH_CACHE_INSN: 345 __asm__ __volatile__ ("nop\n\t" 346 ".chip 68040\n\t" 347 "cpushl %%ic,(%0)\n\t" 348 ".chip 68k" 349 : : "a" (paddr)); 350 break; 351 default: 352 case FLUSH_CACHE_BOTH: 353 __asm__ __volatile__ ("nop\n\t" 354 ".chip 68040\n\t" 355 "cpushl %%bc,(%0)\n\t" 356 ".chip 68k" 357 : : "a" (paddr)); 358 break; 359 } 360 if (!--i && len) 361 { 362 /* 363 * No need to page align here since it is done by 364 * virt_to_phys_040(). 365 */ 366 addr += PAGE_SIZE; 367 i = PAGE_SIZE / 16; 368 /* Recompute physical address when crossing a page 369 boundary. */ 370 for (;;) 371 { 372 if ((paddr = virt_to_phys_040(addr))) 373 break; 374 if (len <= i) 375 return 0; 376 len -= i; 377 addr += PAGE_SIZE; 378 } 379 } 380 else 381 paddr += 16; 382 } 383 break; 384 385 default: 386 case FLUSH_SCOPE_PAGE: 387 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); 388 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) 389 { 390 if (!(paddr = virt_to_phys_040(addr))) 391 continue; 392 switch (cache) 393 { 394 case FLUSH_CACHE_DATA: 395 __asm__ __volatile__ ("nop\n\t" 396 ".chip 68040\n\t" 397 "cpushp %%dc,(%0)\n\t" 398 ".chip 68k" 399 : : "a" (paddr)); 400 break; 401 case FLUSH_CACHE_INSN: 402 __asm__ __volatile__ ("nop\n\t" 403 ".chip 68040\n\t" 404 "cpushp %%ic,(%0)\n\t" 405 ".chip 68k" 406 : : "a" (paddr)); 407 break; 408 default: 409 case FLUSH_CACHE_BOTH: 410 __asm__ __volatile__ ("nop\n\t" 411 ".chip 68040\n\t" 412 "cpushp %%bc,(%0)\n\t" 413 ".chip 68k" 414 : : "a" (paddr)); 415 break; 416 } 417 } 418 break; 419 } 420 return 0; 421 } 422 423 #define virt_to_phys_060(vaddr) \ 424 ({ \ 425 unsigned long paddr; \ 426 __asm__ __volatile__ (".chip 68060\n\t" \ 427 "plpar (%0)\n\t" \ 428 ".chip 68k" \ 429 : "=a" (paddr) \ 430 : "0" (vaddr)); \ 431 (paddr); /* XXX */ \ 432 }) 433 434 static inline int 435 cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len) 436 { 437 unsigned long paddr, i; 438 439 /* 440 * 68060 manual says: 441 * cpush %dc : flush DC, remains valid (with our %cacr setup) 442 * cpush %ic : invalidate IC 443 * cpush %bc : flush DC + invalidate IC 444 */ 445 switch (scope) 446 { 447 case FLUSH_SCOPE_ALL: 448 switch (cache) 449 { 450 case FLUSH_CACHE_DATA: 451 __asm__ __volatile__ (".chip 68060\n\t" 452 "cpusha %dc\n\t" 453 ".chip 68k"); 454 break; 455 case FLUSH_CACHE_INSN: 456 __asm__ __volatile__ (".chip 68060\n\t" 457 "cpusha %ic\n\t" 458 ".chip 68k"); 459 break; 460 default: 461 case FLUSH_CACHE_BOTH: 462 __asm__ __volatile__ (".chip 68060\n\t" 463 "cpusha %bc\n\t" 464 ".chip 68k"); 465 break; 466 } 467 break; 468 469 case FLUSH_SCOPE_LINE: 470 /* Find the physical address of the first mapped page in the 471 address range. */ 472 len += addr & 15; 473 addr &= -16; 474 if (!(paddr = virt_to_phys_060(addr))) { 475 unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK); 476 477 if (len <= tmp) 478 return 0; 479 addr += tmp; 480 len -= tmp; 481 tmp = PAGE_SIZE; 482 for (;;) 483 { 484 if ((paddr = virt_to_phys_060(addr))) 485 break; 486 if (len <= tmp) 487 return 0; 488 addr += tmp; 489 len -= tmp; 490 } 491 } 492 len = (len + 15) >> 4; 493 i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4; 494 while (len--) 495 { 496 switch (cache) 497 { 498 case FLUSH_CACHE_DATA: 499 __asm__ __volatile__ (".chip 68060\n\t" 500 "cpushl %%dc,(%0)\n\t" 501 ".chip 68k" 502 : : "a" (paddr)); 503 break; 504 case FLUSH_CACHE_INSN: 505 __asm__ __volatile__ (".chip 68060\n\t" 506 "cpushl %%ic,(%0)\n\t" 507 ".chip 68k" 508 : : "a" (paddr)); 509 break; 510 default: 511 case FLUSH_CACHE_BOTH: 512 __asm__ __volatile__ (".chip 68060\n\t" 513 "cpushl %%bc,(%0)\n\t" 514 ".chip 68k" 515 : : "a" (paddr)); 516 break; 517 } 518 if (!--i && len) 519 { 520 521 /* 522 * We just want to jump to the first cache line 523 * in the next page. 524 */ 525 addr += PAGE_SIZE; 526 addr &= PAGE_MASK; 527 528 i = PAGE_SIZE / 16; 529 /* Recompute physical address when crossing a page 530 boundary. */ 531 for (;;) 532 { 533 if ((paddr = virt_to_phys_060(addr))) 534 break; 535 if (len <= i) 536 return 0; 537 len -= i; 538 addr += PAGE_SIZE; 539 } 540 } 541 else 542 paddr += 16; 543 } 544 break; 545 546 default: 547 case FLUSH_SCOPE_PAGE: 548 len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1); 549 addr &= PAGE_MASK; /* Workaround for bug in some 550 revisions of the 68060 */ 551 for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE) 552 { 553 if (!(paddr = virt_to_phys_060(addr))) 554 continue; 555 switch (cache) 556 { 557 case FLUSH_CACHE_DATA: 558 __asm__ __volatile__ (".chip 68060\n\t" 559 "cpushp %%dc,(%0)\n\t" 560 ".chip 68k" 561 : : "a" (paddr)); 562 break; 563 case FLUSH_CACHE_INSN: 564 __asm__ __volatile__ (".chip 68060\n\t" 565 "cpushp %%ic,(%0)\n\t" 566 ".chip 68k" 567 : : "a" (paddr)); 568 break; 569 default: 570 case FLUSH_CACHE_BOTH: 571 __asm__ __volatile__ (".chip 68060\n\t" 572 "cpushp %%bc,(%0)\n\t" 573 ".chip 68k" 574 : : "a" (paddr)); 575 break; 576 } 577 } 578 break; 579 } 580 return 0; 581 } 582 583 /* sys_cacheflush -- flush (part of) the processor cache. */ 584 asmlinkage int 585 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) 586 { 587 struct vm_area_struct *vma; 588 int ret = -EINVAL; 589 590 lock_kernel(); 591 if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL || 592 cache & ~FLUSH_CACHE_BOTH) 593 goto out; 594 595 if (scope == FLUSH_SCOPE_ALL) { 596 /* Only the superuser may explicitly flush the whole cache. */ 597 ret = -EPERM; 598 if (!capable(CAP_SYS_ADMIN)) 599 goto out; 600 } else { 601 /* 602 * Verify that the specified address region actually belongs 603 * to this process. 604 */ 605 vma = find_vma (current->mm, addr); 606 ret = -EINVAL; 607 /* Check for overflow. */ 608 if (addr + len < addr) 609 goto out; 610 if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) 611 goto out; 612 } 613 614 if (CPU_IS_020_OR_030) { 615 if (scope == FLUSH_SCOPE_LINE && len < 256) { 616 unsigned long cacr; 617 __asm__ ("movec %%cacr, %0" : "=r" (cacr)); 618 if (cache & FLUSH_CACHE_INSN) 619 cacr |= 4; 620 if (cache & FLUSH_CACHE_DATA) 621 cacr |= 0x400; 622 len >>= 2; 623 while (len--) { 624 __asm__ __volatile__ ("movec %1, %%caar\n\t" 625 "movec %0, %%cacr" 626 : /* no outputs */ 627 : "r" (cacr), "r" (addr)); 628 addr += 4; 629 } 630 } else { 631 /* Flush the whole cache, even if page granularity requested. */ 632 unsigned long cacr; 633 __asm__ ("movec %%cacr, %0" : "=r" (cacr)); 634 if (cache & FLUSH_CACHE_INSN) 635 cacr |= 8; 636 if (cache & FLUSH_CACHE_DATA) 637 cacr |= 0x800; 638 __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr)); 639 } 640 ret = 0; 641 goto out; 642 } else { 643 /* 644 * 040 or 060: don't blindly trust 'scope', someone could 645 * try to flush a few megs of memory. 646 */ 647 648 if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE) 649 scope=FLUSH_SCOPE_PAGE; 650 if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL) 651 scope=FLUSH_SCOPE_ALL; 652 if (CPU_IS_040) { 653 ret = cache_flush_040 (addr, scope, cache, len); 654 } else if (CPU_IS_060) { 655 ret = cache_flush_060 (addr, scope, cache, len); 656 } 657 } 658 out: 659 unlock_kernel(); 660 return ret; 661 } 662 663 asmlinkage int sys_getpagesize(void) 664 { 665 return PAGE_SIZE; 666 } 667 668 /* 669 * Do a system call from kernel instead of calling sys_execve so we 670 * end up with proper pt_regs. 671 */ 672 int kernel_execve(const char *filename, char *const argv[], char *const envp[]) 673 { 674 register long __res asm ("%d0") = __NR_execve; 675 register long __a asm ("%d1") = (long)(filename); 676 register long __b asm ("%d2") = (long)(argv); 677 register long __c asm ("%d3") = (long)(envp); 678 asm volatile ("trap #0" : "+d" (__res) 679 : "d" (__a), "d" (__b), "d" (__c)); 680 return __res; 681 } 682