2 * arch/ppc/kernel/misc.S
6 * This file contains miscellaneous low-level functions.
7 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
9 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
11 * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
12 * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
21 #include <linux/config.h>
22 #include <linux/sys.h>
23 #include <asm/unistd.h>
24 #include <asm/errno.h>
25 #include <asm/processor.h>
27 #include <asm/cache.h>
33 * Returns (address we're running at) - (address we were linked at)
34 * for use before the text and data are mapped to KERNELBASE.
66 #ifdef CONFIG_PPC_ISERIES
67 /* unsigned long __no_use_save_flags(void) */
68 _GLOBAL(__no_use_save_flags)
70 lbz r3,PACAPROCENABLED(r4)
73 /* void __no_use_restore_flags(unsigned long flags) */
74 _GLOBAL(__no_use_restore_flags)
76 * Just set/clear the MSR_EE bit through restore/flags but do not
77 * change anything else. This is needed by the RT system and makes
82 lbz r5,PACAPROCENABLED(r6)
83 /* Check if things are setup the way we want _already_. */
86 /* are we enabling interrupts? */
88 stb r3,PACAPROCENABLED(r6)
90 /* Check pending interrupts */
95 * Handle pending interrupts in interrupt context
101 _GLOBAL(__no_use_cli)
103 lbz r3,PACAPROCENABLED(r5)
105 stb r4,PACAPROCENABLED(r5)
108 _GLOBAL(__no_use_sti)
111 stb r3,PACAPROCENABLED(r6)
113 /* Check for pending interrupts
114 * A decrementer, IPI or PMC interrupt may have occurred
115 * while we were in the hypervisor (which enables)
121 * Handle pending interrupts in interrupt context
128 * Flush instruction cache.
130 _GLOBAL(flush_instruction_cache)
133 * This is called by kgdb code
134 * and should probably go away
135 * to be replaced by invalidating
136 * the cache lines that are actually
139 /* use invalidate-all bit in HID0
140 * - is this consistent across all 64-bit cpus? -- paulus */
149 * Write any modified data cache blocks out to memory
150 * and invalidate the corresponding instruction cache blocks.
152 * flush_icache_range(unsigned long start, unsigned long stop)
154 * flush all bytes from start through stop-1 inclusive
157 _GLOBAL(flush_icache_range)
160 * Flush the data cache to memory
162 * Different systems have different cache line sizes
163 * and in some cases i-cache and d-cache line sizes differ from
166 LOADADDR(r10,naca) /* Get Naca address */
168 LOADADDR(r11,systemcfg) /* Get systemcfg address */
170 lwz r7,DCACHEL1LINESIZE(r11) /* Get cache line size */
172 andc r6,r3,r5 /* round low to line bdy */
173 subf r8,r6,r4 /* compute length */
174 add r8,r8,r5 /* ensure we get enough */
175 lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */
176 srw. r8,r8,r9 /* compute line count */
177 beqlr /* nothing to do? */
184 /* Now invalidate the instruction cache */
186 lwz r7,ICACHEL1LINESIZE(r11) /* Get Icache line size */
188 andc r6,r3,r5 /* round low to line bdy */
189 subf r8,r6,r4 /* compute length */
191 lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */
192 srw. r8,r8,r9 /* compute line count */
193 beqlr /* nothing to do? */
202 * Like above, but only do the D-cache.
204 * flush_dcache_range(unsigned long start, unsigned long stop)
206 * flush all bytes from start to stop-1 inclusive
208 _GLOBAL(flush_dcache_range)
211 * Flush the data cache to memory
213 * Different systems have different cache line sizes
215 LOADADDR(r10,naca) /* Get Naca address */
217 LOADADDR(r11,systemcfg) /* Get systemcfg address */
219 lwz r7,DCACHEL1LINESIZE(r11) /* Get dcache line size */
221 andc r6,r3,r5 /* round low to line bdy */
222 subf r8,r6,r4 /* compute length */
223 add r8,r8,r5 /* ensure we get enough */
224 lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */
225 srw. r8,r8,r9 /* compute line count */
226 beqlr /* nothing to do? */
235 * Flush a particular page from the data cache to RAM.
236 * Note: this is necessary because the instruction cache does *not*
237 * snoop from the data cache.
239 * void __flush_dcache_icache(void *page)
241 _GLOBAL(__flush_dcache_icache)
243 * Flush the data cache to memory
245 * Different systems have different cache line sizes
248 /* Flush the dcache */
251 LOADADDR(r8,systemcfg) /* Get systemcfg address */
253 clrrdi r3,r3,12 /* Page align */
254 lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */
255 lwz r5,DCACHEL1LINESIZE(r8) /* Get dcache line size */
263 /* Now invalidate the icache */
265 lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */
266 lwz r5,ICACHEL1LINESIZE(r8) /* Get icache line size */
275 * I/O string operations
277 * insb(port, buf, len)
278 * outsb(port, buf, len)
279 * insw(port, buf, len)
280 * outsw(port, buf, len)
281 * insl(port, buf, len)
282 * outsl(port, buf, len)
283 * insw_ns(port, buf, len)
284 * outsw_ns(port, buf, len)
285 * insl_ns(port, buf, len)
286 * outsl_ns(port, buf, len)
288 * The *_ns versions don't do byte-swapping.
403 * Extended precision shifts
405 * R3/R4 has 64 bit value
409 * ashrdi3: XXXYYY/ZZZAAA -> SSSXXX/YYYZZZ
410 * ashldi3: XXXYYY/ZZZAAA -> YYYZZZ/AAA000
411 * lshrdi3: XXXYYY/ZZZAAA -> 000XXX/YYYZZZ
413 /* MIKEC: These may no longer be needed...what does gcc expect ? */
418 slw r7,r3,r6 /* isolate YYY */
419 srw r4,r4,r5 /* isolate ZZZ */
420 or r4,r4,r7 /* YYYZZZ */
421 sraw r3,r3,r5 /* SSSXXX */
427 srw r7,r4,r6 /* isolate ZZZ */
428 slw r4,r4,r5 /* AAA000 */
429 slw r3,r3,r5 /* YYY--- */
430 or r3,r3,r7 /* YYYZZZ */
436 slw r7,r3,r6 /* isolate YYY */
437 srw r4,r4,r5 /* isolate ZZZ */
438 or r4,r4,r7 /* YYYZZZ */
439 srw r3,r3,r5 /* 000XXX */
449 mr r3,r1 /* Close enough */
465 lfd 0,0(r5) /* load up fpscr value */
469 mffs 0 /* save new fpscr value */
474 lfd 0,0(r5) /* load up fpscr value */
478 mffs 0 /* save new fpscr value */
483 * Create a kernel thread
484 * kernel_thread(fn, arg, flags)
486 _GLOBAL(kernel_thread)
487 mr r6,r3 /* function */
488 ori r3,r5,CLONE_VM /* flags */
491 cmpi 0,r3,0 /* parent or child? */
492 bnelr /* return if parent */
494 li r0,0 /* clear out p->thread.regs */
495 std r0,THREAD+PT_REGS(r13) /* since we don't have user ctx */
496 li r0,RUN_FLAG /* Run light on */
497 std r0,THREAD+THREAD_FLAGS(r13)
501 mtlr r6 /* fn addr in lr */
502 mr r3,r4 /* load arg and call fn */
504 li r0,__NR_exit /* exit after child exits */
508 #ifdef CONFIG_BINFMT_ELF32
509 /* Why isn't this a) automatic, b) written in 'C'? */
511 _GLOBAL(sys_call_table32)
512 .llong .sys_ni_syscall /* 0 - old "setup()" system call */
517 .llong .sys32_open /* 5 */
519 .llong .sys32_waitpid
522 .llong .sys_unlink /* 10 */
527 .llong .sys_chmod /* 15 */
529 .llong .sys_ni_syscall /* old break syscall holder */
532 .llong .sys_getpid /* 20 */
534 .llong .sys_oldumount
537 .llong .ppc64_sys32_stime /* 25 */
542 .llong .sys32_utime /* 30 */
543 .llong .sys_ni_syscall /* old stty syscall holder */
544 .llong .sys_ni_syscall /* old gtty syscall holder */
547 .llong .sys_ni_syscall /* 35 */ /* old ftime syscall holder */
552 .llong .sys_rmdir /* 40 */
556 .llong .sys_ni_syscall /* old prof syscall holder */
557 .llong .sys_brk /* 45 */
562 .llong .sys_getegid /* 50 */
564 .llong .sys32_umount /* recycled never used phys() */
565 .llong .sys_ni_syscall /* old lock syscall holder */
567 .llong .sys32_fcntl /* 55 */
568 .llong .sys_ni_syscall /* old mpx syscall holder */
569 .llong .sys32_setpgid
570 .llong .sys_ni_syscall /* old ulimit syscall holder */
572 .llong .sys32_umask /* 60 */
577 .llong .sys_getpgrp /* 65 */
579 .llong .sys32_sigaction
581 .llong .sys32_ssetmask
582 .llong .sys_setreuid /* 70 */
584 .llong .sys_sigsuspend
585 .llong .sys32_sigpending
586 .llong .sys32_sethostname
587 .llong .sys32_setrlimit /* 75 */
588 .llong .sys32_old_getrlimit
589 .llong .sys32_getrusage
590 .llong .sys32_gettimeofday
591 .llong .sys32_settimeofday
592 .llong .sys32_getgroups /* 80 */
593 .llong .sys32_setgroups
594 .llong .sys_ni_syscall /* old select syscall */
597 .llong .sys32_readlink /* 85 */
601 .llong .old32_readdir
602 .llong .sys32_mmap /* 90 */
605 .llong .sys_ftruncate
607 .llong .sys_fchown /* 95 */
608 .llong .sys32_getpriority
609 .llong .sys32_setpriority
610 .llong .sys_ni_syscall /* old profil syscall holder */
612 .llong .sys32_fstatfs /* 100 */
614 .llong .sys32_socketcall
616 .llong .sys32_setitimer
617 .llong .sys32_getitimer /* 105 */
618 .llong .sys32_newstat
619 .llong .sys32_newlstat
620 .llong .sys32_newfstat
622 .llong .sys_ni_syscall /* 110 old iopl syscall */
624 .llong .sys_ni_syscall /* old 'idle' syscall */
625 .llong .sys_ni_syscall /* old vm86 syscall */
627 .llong .sys_swapoff /* 115 */
628 .llong .sys32_sysinfo
631 .llong .ppc32_sigreturn
632 .llong .sys32_clone /* 120 */
633 .llong .sys32_setdomainname
634 .llong .ppc64_newuname
635 .llong .sys_ni_syscall /* old modify_ldt syscall */
636 .llong .sys32_adjtimex
637 .llong .sys_mprotect /* 125 */
638 .llong .sys32_sigprocmask
639 .llong .sys32_create_module
640 .llong .sys32_init_module
641 .llong .sys32_delete_module
642 .llong .sys32_get_kernel_syms /* 130 */
643 .llong .sys32_quotactl
644 .llong .sys32_getpgid
646 .llong .sys32_bdflush
647 .llong .sys32_sysfs /* 135 */
648 .llong .sys32_personality
649 .llong .sys_ni_syscall /* for afs_syscall */
652 .llong .sys_llseek /* 140 */
653 .llong .sys32_getdents
657 .llong .sys32_readv /* 145 */
660 .llong .sys_fdatasync
662 .llong .sys_mlock /* 150 */
664 .llong .sys32_mlockall
665 .llong .sys_munlockall
666 .llong .sys32_sched_setparam
667 .llong .sys32_sched_getparam /* 155 */
668 .llong .sys32_sched_setscheduler
669 .llong .sys32_sched_getscheduler
670 .llong .sys_sched_yield
671 .llong .sys32_sched_get_priority_max
672 .llong .sys32_sched_get_priority_min /* 160 */
673 .llong .sys32_sched_rr_get_interval
674 .llong .sys32_nanosleep
676 .llong .sys_setresuid
677 .llong .sys_getresuid /* 165 */
678 .llong .sys32_query_module
680 .llong .sys32_nfsservctl
681 .llong .sys_setresgid
682 .llong .sys_getresgid /* 170 */
684 .llong .ppc32_rt_sigreturn
685 .llong .sys32_rt_sigaction
686 .llong .sys32_rt_sigprocmask
687 .llong .sys32_rt_sigpending /* 175 */
688 .llong .sys32_rt_sigtimedwait
689 .llong .sys32_rt_sigqueueinfo
690 .llong .sys32_rt_sigsuspend
692 .llong .sys32_pwrite /* 180 */
697 .llong .sys32_sigaltstack /* 185 */
698 .llong .sys32_sendfile
699 .llong .sys_ni_syscall /* streams1 */
700 .llong .sys_ni_syscall /* streams2 */
702 .llong .sys32_getrlimit /* 190 */
703 .llong .sys32_readahead
705 .llong .sys32_truncate64 /* 193 - truncate64 */
706 .llong .sys32_ftruncate64 /* 194 - ftruncate64 */
707 .llong .sys_stat64 /* 195 - stat64 */
708 .llong .sys_lstat64 /* 196 - lstat64 */
709 .llong .sys_fstat64 /* 197 - fstat64 */
710 .llong .sys32_pciconfig_read /* 198 */
711 .llong .sys32_pciconfig_write /* 199 */
712 .llong .sys_pciconfig_iobase /* 200 */
713 .llong .sys_ni_syscall /* 201 - reserved - MacOnLinux - new */
714 .llong .sys_getdents64 /* 202 */
715 .llong .sys_pivot_root /* 203 */
716 .llong .sys32_fcntl64 /* 204 */
717 .llong .sys_madvise /* 205 */
718 .llong .sys_mincore /* 206 */
719 .llong .sys_gettid /* 207 */
720 #if 0 /* Reserved syscalls */
721 .llong .sys_tkill /* 208 */
723 .llong .sys_lsetxattr /* 210 */
724 .llong .sys_fsetxattr
726 .llong .sys_lgetxattr
727 .llong .sys_fgetxattr
728 .llong .sys_listxattr /* 215 */
729 .llong .sys_llistxattr
730 .llong .sys_flistxattr
731 .llong .sys_removexattr
732 .llong .sys_lremovexattr
733 .llong .sys_fremovexattr /* 220 */
736 .llong .sys_perfmonctl /* Put this here for now ... */
737 .rept NR_syscalls-222
738 .llong .sys_ni_syscall
742 _GLOBAL(sys_call_table)
743 .llong .sys_ni_syscall /* 0 - old "setup()" system call */
748 .llong .sys_open /* 5 */
753 .llong .sys_unlink /* 10 */
758 .llong .sys_chmod /* 15 */
760 .llong .sys_ni_syscall /* old break syscall holder */
763 .llong .sys_getpid /* 20 */
765 .llong .sys_ni_syscall /* old umount syscall */
768 .llong .ppc64_sys_stime /* 25 */
773 .llong .sys_utime /* 30 */
774 .llong .sys_ni_syscall /* old stty syscall holder */
775 .llong .sys_ni_syscall /* old gtty syscall holder */
778 .llong .sys_ni_syscall /* 35 */ /* old ftime syscall holder */
783 .llong .sys_rmdir /* 40 */
787 .llong .sys_ni_syscall /* old prof syscall holder */
788 .llong .sys_brk /* 45 */
793 .llong .sys_getegid /* 50 */
795 .llong .sys_umount /* recycled never used phys() */
796 .llong .sys_ni_syscall /* old lock syscall holder */
798 .llong .sys_fcntl /* 55 */
799 .llong .sys_ni_syscall /* old mpx syscall holder */
801 .llong .sys_ni_syscall /* old ulimit syscall holder */
802 .llong .sys_ni_syscall /* old uname syscall */
803 .llong .sys_umask /* 60 */
808 .llong .sys_getpgrp /* 65 */
810 .llong .sys_sigaction
813 .llong .sys_setreuid /* 70 */
815 .llong .sys_sigsuspend
816 .llong .sys_sigpending
817 .llong .sys_sethostname
818 .llong .sys_setrlimit /* 75 */
819 .llong .sys_ni_syscall /* old getrlimit syscall */
820 .llong .sys_getrusage
821 .llong .sys_gettimeofday
822 .llong .sys_settimeofday
823 .llong .sys_getgroups /* 80 */
824 .llong .sys_setgroups
825 .llong .sys_ni_syscall /* old select syscall */
828 .llong .sys_readlink /* 85 */
832 .llong .sys_ni_syscall /* old readdir syscall */
833 .llong .sys_mmap /* 90 */
836 .llong .sys_ftruncate
838 .llong .sys_fchown /* 95 */
839 .llong .sys_getpriority
840 .llong .sys_setpriority
841 .llong .sys_ni_syscall /* old profil syscall holder */
843 .llong .sys_fstatfs /* 100 */
845 .llong .sys_socketcall
847 .llong .sys_setitimer
848 .llong .sys_getitimer /* 105 */
853 .llong .sys_ni_syscall /* 110 old iopl syscall */
855 .llong .sys_ni_syscall /* old 'idle' syscall */
856 .llong .sys_ni_syscall /* old vm86 syscall */
858 .llong .sys_swapoff /* 115 */
862 .llong .ppc64_sigreturn
863 .llong .sys_clone /* 120 */
864 .llong .sys_setdomainname
865 .llong .ppc64_newuname
866 .llong .sys_ni_syscall /* old modify_ldt syscall */
868 .llong .sys_mprotect /* 125 */
869 .llong .sys_sigprocmask
870 .llong .sys_create_module
871 .llong .sys_init_module
872 .llong .sys_delete_module
873 .llong .sys_get_kernel_syms /* 130 */
878 .llong .sys_sysfs /* 135 */
879 .llong .sys_personality
880 .llong .sys_ni_syscall /* for afs_syscall */
883 .llong .sys_llseek /* 140 */
888 .llong .sys_readv /* 145 */
891 .llong .sys_fdatasync
893 .llong .sys_mlock /* 150 */
896 .llong .sys_munlockall
897 .llong .sys_sched_setparam
898 .llong .sys_sched_getparam /* 155 */
899 .llong .sys_sched_setscheduler
900 .llong .sys_sched_getscheduler
901 .llong .sys_sched_yield
902 .llong .sys_sched_get_priority_max
903 .llong .sys_sched_get_priority_min /* 160 */
904 .llong .sys_sched_rr_get_interval
905 .llong .sys_nanosleep
907 .llong .sys_setresuid
908 .llong .sys_getresuid /* 165 */
909 .llong .sys_query_module
911 .llong .sys_nfsservctl
912 .llong .sys_setresgid
913 .llong .sys_getresgid /* 170 */
915 .llong .ppc64_rt_sigreturn
916 .llong .sys_rt_sigaction
917 .llong .sys_rt_sigprocmask
918 .llong .sys_rt_sigpending /* 175 */
919 .llong .sys_rt_sigtimedwait
920 .llong .sys_rt_sigqueueinfo
921 .llong .sys_rt_sigsuspend
923 .llong .sys_pwrite /* 180 */
928 .llong .sys_sigaltstack /* 185 */
930 .llong .sys_ni_syscall /* streams1 */
931 .llong .sys_ni_syscall /* streams2 */
933 .llong .sys_getrlimit /* 190 */
934 .llong .sys_readahead
935 .llong .sys_ni_syscall /* 192 - reserved - mmap2 */
936 .llong .sys_ni_syscall /* 193 - reserved - truncate64 */
937 .llong .sys_ni_syscall /* 194 - reserved - ftruncate64 */
938 .llong .sys_ni_syscall /* 195 - reserved - stat64 */
939 .llong .sys_ni_syscall /* 196 - reserved - lstat64 */
940 .llong .sys_ni_syscall /* 197 - reserved - fstat64 */
941 .llong .sys_pciconfig_read /* 198 */
942 .llong .sys_pciconfig_write /* 199 */
943 .llong .sys_pciconfig_iobase /* 200 */
944 .llong .sys_ni_syscall /* 201 - reserved - MacOnLinux - new */
945 .llong .sys_getdents64 /* 202 */
946 .llong .sys_pivot_root /* 203 */
947 .llong .sys_ni_syscall /* 204 */
948 .llong .sys_madvise /* 205 */
949 .llong .sys_mincore /* 206 */
950 .llong .sys_gettid /* 207 */
951 #if 0 /* Reserved syscalls */
952 .llong .sys_tkill /* 208 */
954 .llong .sys_lsetxattr /* 210 */
955 .llong .sys_fsetxattr
957 .llong .sys_lgetxattr
958 .llong .sys_fgetxattr
959 .llong .sys_listxattr /* 215 */
960 .llong .sys_llistxattr
961 .llong .sys_flistxattr
962 .llong .sys_removexattr
963 .llong .sys_lremovexattr
964 .llong .sys_fremovexattr /* 220 */
967 .llong .sys_perfmonctl /* Put this here for now ... */
968 .rept NR_syscalls-222
969 .llong .sys_ni_syscall