diff options
Diffstat (limited to 'arch/sparc/kernel/entry.S')
-rw-r--r-- | arch/sparc/kernel/entry.S | 432 |
1 files changed, 71 insertions, 361 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index f445e98463e6..2dbe1806e530 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) | 7 | * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/linkage.h> | ||
10 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
11 | 12 | ||
12 | #include <asm/head.h> | 13 | #include <asm/head.h> |
@@ -17,10 +18,8 @@ | |||
17 | #include <asm/asm-offsets.h> | 18 | #include <asm/asm-offsets.h> |
18 | #include <asm/psr.h> | 19 | #include <asm/psr.h> |
19 | #include <asm/vaddrs.h> | 20 | #include <asm/vaddrs.h> |
20 | #include <asm/memreg.h> | ||
21 | #include <asm/page.h> | 21 | #include <asm/page.h> |
22 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
23 | #include <asm/pgtsun4c.h> | ||
24 | #include <asm/winmacro.h> | 23 | #include <asm/winmacro.h> |
25 | #include <asm/signal.h> | 24 | #include <asm/signal.h> |
26 | #include <asm/obio.h> | 25 | #include <asm/obio.h> |
@@ -125,22 +124,11 @@ floppy_tdone: | |||
125 | set auxio_register, %l7 | 124 | set auxio_register, %l7 |
126 | ld [%l7], %l7 | 125 | ld [%l7], %l7 |
127 | 126 | ||
128 | set sparc_cpu_model, %l5 | 127 | ldub [%l7], %l5 |
129 | ld [%l5], %l5 | ||
130 | subcc %l5, 1, %g0 /* enum { sun4c = 1 }; */ | ||
131 | be 1f | ||
132 | ldub [%l7], %l5 | ||
133 | 128 | ||
134 | or %l5, 0xc2, %l5 | 129 | or %l5, 0xc2, %l5 |
135 | stb %l5, [%l7] | 130 | stb %l5, [%l7] |
136 | andn %l5, 0x02, %l5 | 131 | andn %l5, 0x02, %l5 |
137 | b 2f | ||
138 | nop | ||
139 | |||
140 | 1: | ||
141 | or %l5, 0xf4, %l5 | ||
142 | stb %l5, [%l7] | ||
143 | andn %l5, 0x04, %l5 | ||
144 | 132 | ||
145 | 2: | 133 | 2: |
146 | /* Kill some time so the bits set */ | 134 | /* Kill some time so the bits set */ |
@@ -266,6 +254,11 @@ smp4m_ticker: | |||
266 | WRITE_PAUSE | 254 | WRITE_PAUSE |
267 | RESTORE_ALL | 255 | RESTORE_ALL |
268 | 256 | ||
257 | #define GET_PROCESSOR4M_ID(reg) \ | ||
258 | rd %tbr, %reg; \ | ||
259 | srl %reg, 12, %reg; \ | ||
260 | and %reg, 3, %reg; | ||
261 | |||
269 | /* Here is where we check for possible SMP IPI passed to us | 262 | /* Here is where we check for possible SMP IPI passed to us |
270 | * on some level other than 15 which is the NMI and only used | 263 | * on some level other than 15 which is the NMI and only used |
271 | * for cross calls. That has a separate entry point below. | 264 | * for cross calls. That has a separate entry point below. |
@@ -328,7 +321,7 @@ linux_trap_ipi15_sun4m: | |||
328 | ld [%o5 + %o0], %o5 | 321 | ld [%o5 + %o0], %o5 |
329 | ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending | 322 | ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending |
330 | andcc %o3, %o2, %g0 | 323 | andcc %o3, %o2, %g0 |
331 | be 1f ! Must be an NMI async memory error | 324 | be sun4m_nmi_error ! Must be an NMI async memory error |
332 | st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 | 325 | st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 |
333 | WRITE_PAUSE | 326 | WRITE_PAUSE |
334 | ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending | 327 | ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending |
@@ -342,27 +335,6 @@ linux_trap_ipi15_sun4m: | |||
342 | nop | 335 | nop |
343 | b ret_trap_lockless_ipi | 336 | b ret_trap_lockless_ipi |
344 | clr %l6 | 337 | clr %l6 |
345 | 1: | ||
346 | /* NMI async memory error handling. */ | ||
347 | sethi %hi(0x80000000), %l4 | ||
348 | sethi %hi(sun4m_irq_global), %o5 | ||
349 | ld [%o5 + %lo(sun4m_irq_global)], %l5 | ||
350 | st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000 | ||
351 | WRITE_PAUSE | ||
352 | ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending | ||
353 | WRITE_PAUSE | ||
354 | or %l0, PSR_PIL, %l4 | ||
355 | wr %l4, 0x0, %psr | ||
356 | WRITE_PAUSE | ||
357 | wr %l4, PSR_ET, %psr | ||
358 | WRITE_PAUSE | ||
359 | call sun4m_nmi | ||
360 | nop | ||
361 | st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000 | ||
362 | WRITE_PAUSE | ||
363 | ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending | ||
364 | WRITE_PAUSE | ||
365 | RESTORE_ALL | ||
366 | 338 | ||
367 | .globl smp4d_ticker | 339 | .globl smp4d_ticker |
368 | /* SMP per-cpu ticker interrupts are handled specially. */ | 340 | /* SMP per-cpu ticker interrupts are handled specially. */ |
@@ -760,326 +732,37 @@ setcc_trap_handler: | |||
760 | jmp %l2 ! advance over trap instruction | 732 | jmp %l2 ! advance over trap instruction |
761 | rett %l2 + 0x4 ! like this... | 733 | rett %l2 + 0x4 ! like this... |
762 | 734 | ||
763 | .align 4 | 735 | sun4m_nmi_error: |
764 | .globl linux_trap_nmi_sun4c | 736 | /* NMI async memory error handling. */ |
765 | linux_trap_nmi_sun4c: | 737 | sethi %hi(0x80000000), %l4 |
766 | SAVE_ALL | 738 | sethi %hi(sun4m_irq_global), %o5 |
767 | 739 | ld [%o5 + %lo(sun4m_irq_global)], %l5 | |
768 | /* Ugh, we need to clear the IRQ line. This is now | 740 | st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000 |
769 | * a very sun4c specific trap handler... | ||
770 | */ | ||
771 | sethi %hi(interrupt_enable), %l5 | ||
772 | ld [%l5 + %lo(interrupt_enable)], %l5 | ||
773 | ldub [%l5], %l6 | ||
774 | andn %l6, INTS_ENAB, %l6 | ||
775 | stb %l6, [%l5] | ||
776 | |||
777 | /* Now it is safe to re-enable traps without recursion. */ | ||
778 | or %l0, PSR_PIL, %l0 | ||
779 | wr %l0, PSR_ET, %psr | ||
780 | WRITE_PAUSE | 741 | WRITE_PAUSE |
781 | 742 | ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending | |
782 | /* Now call the c-code with the pt_regs frame ptr and the | ||
783 | * memory error registers as arguments. The ordering chosen | ||
784 | * here is due to unlatching semantics. | ||
785 | */ | ||
786 | sethi %hi(AC_SYNC_ERR), %o0 | ||
787 | add %o0, 0x4, %o0 | ||
788 | lda [%o0] ASI_CONTROL, %o2 ! sync vaddr | ||
789 | sub %o0, 0x4, %o0 | ||
790 | lda [%o0] ASI_CONTROL, %o1 ! sync error | ||
791 | add %o0, 0xc, %o0 | ||
792 | lda [%o0] ASI_CONTROL, %o4 ! async vaddr | ||
793 | sub %o0, 0x4, %o0 | ||
794 | lda [%o0] ASI_CONTROL, %o3 ! async error | ||
795 | call sparc_lvl15_nmi | ||
796 | add %sp, STACKFRAME_SZ, %o0 | ||
797 | |||
798 | RESTORE_ALL | ||
799 | |||
800 | .align 4 | ||
801 | .globl invalid_segment_patch1_ff | ||
802 | .globl invalid_segment_patch2_ff | ||
803 | invalid_segment_patch1_ff: cmp %l4, 0xff | ||
804 | invalid_segment_patch2_ff: mov 0xff, %l3 | ||
805 | |||
806 | .align 4 | ||
807 | .globl invalid_segment_patch1_1ff | ||
808 | .globl invalid_segment_patch2_1ff | ||
809 | invalid_segment_patch1_1ff: cmp %l4, 0x1ff | ||
810 | invalid_segment_patch2_1ff: mov 0x1ff, %l3 | ||
811 | |||
812 | .align 4 | ||
813 | .globl num_context_patch1_16, num_context_patch2_16 | ||
814 | num_context_patch1_16: mov 0x10, %l7 | ||
815 | num_context_patch2_16: mov 0x10, %l7 | ||
816 | |||
817 | .align 4 | ||
818 | .globl vac_linesize_patch_32 | ||
819 | vac_linesize_patch_32: subcc %l7, 32, %l7 | ||
820 | |||
821 | .align 4 | ||
822 | .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on | ||
823 | |||
824 | /* | ||
825 | * Ugly, but we can't use hardware flushing on the sun4 and we'd require | ||
826 | * two instructions (Anton) | ||
827 | */ | ||
828 | vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 | ||
829 | |||
830 | vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG | ||
831 | |||
832 | .globl invalid_segment_patch1, invalid_segment_patch2 | ||
833 | .globl num_context_patch1 | ||
834 | .globl vac_linesize_patch, vac_hwflush_patch1 | ||
835 | .globl vac_hwflush_patch2 | ||
836 | |||
837 | .align 4 | ||
838 | .globl sun4c_fault | ||
839 | |||
840 | ! %l0 = %psr | ||
841 | ! %l1 = %pc | ||
842 | ! %l2 = %npc | ||
843 | ! %l3 = %wim | ||
844 | ! %l7 = 1 for textfault | ||
845 | ! We want error in %l5, vaddr in %l6 | ||
846 | sun4c_fault: | ||
847 | sethi %hi(AC_SYNC_ERR), %l4 | ||
848 | add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6 | ||
849 | lda [%l6] ASI_CONTROL, %l5 ! Address | ||
850 | lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit | ||
851 | |||
852 | andn %l5, 0xfff, %l5 ! Encode all info into l7 | ||
853 | srl %l6, 14, %l4 | ||
854 | |||
855 | and %l4, 2, %l4 | ||
856 | or %l5, %l4, %l4 | ||
857 | |||
858 | or %l4, %l7, %l7 ! l7 = [addr,write,txtfault] | ||
859 | |||
860 | andcc %l0, PSR_PS, %g0 | ||
861 | be sun4c_fault_fromuser | ||
862 | andcc %l7, 1, %g0 ! Text fault? | ||
863 | |||
864 | be 1f | ||
865 | sethi %hi(KERNBASE), %l4 | ||
866 | |||
867 | mov %l1, %l5 ! PC | ||
868 | |||
869 | 1: | ||
870 | cmp %l5, %l4 | ||
871 | blu sun4c_fault_fromuser | ||
872 | sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4 | ||
873 | |||
874 | /* If the kernel references a bum kernel pointer, or a pte which | ||
875 | * points to a non existent page in ram, we will run this code | ||
876 | * _forever_ and lock up the machine!!!!! So we must check for | ||
877 | * this condition, the AC_SYNC_ERR bits are what we must examine. | ||
878 | * Also a parity error would make this happen as well. So we just | ||
879 | * check that we are in fact servicing a tlb miss and not some | ||
880 | * other type of fault for the kernel. | ||
881 | */ | ||
882 | andcc %l6, 0x80, %g0 | ||
883 | be sun4c_fault_fromuser | ||
884 | and %l5, %l4, %l5 | ||
885 | |||
886 | /* Test for NULL pte_t * in vmalloc area. */ | ||
887 | sethi %hi(VMALLOC_START), %l4 | ||
888 | cmp %l5, %l4 | ||
889 | blu,a invalid_segment_patch1 | ||
890 | lduXa [%l5] ASI_SEGMAP, %l4 | ||
891 | |||
892 | sethi %hi(swapper_pg_dir), %l4 | ||
893 | srl %l5, SUN4C_PGDIR_SHIFT, %l6 | ||
894 | or %l4, %lo(swapper_pg_dir), %l4 | ||
895 | sll %l6, 2, %l6 | ||
896 | ld [%l4 + %l6], %l4 | ||
897 | andcc %l4, PAGE_MASK, %g0 | ||
898 | be sun4c_fault_fromuser | ||
899 | lduXa [%l5] ASI_SEGMAP, %l4 | ||
900 | |||
901 | invalid_segment_patch1: | ||
902 | cmp %l4, 0x7f | ||
903 | bne 1f | ||
904 | sethi %hi(sun4c_kfree_ring), %l4 | ||
905 | or %l4, %lo(sun4c_kfree_ring), %l4 | ||
906 | ld [%l4 + 0x18], %l3 | ||
907 | deccc %l3 ! do we have a free entry? | ||
908 | bcs,a 2f ! no, unmap one. | ||
909 | sethi %hi(sun4c_kernel_ring), %l4 | ||
910 | |||
911 | st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries-- | ||
912 | |||
913 | ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next | ||
914 | st %l5, [%l6 + 0x08] ! entry->vaddr = address | ||
915 | |||
916 | ld [%l6 + 0x00], %l3 ! next = entry->next | ||
917 | ld [%l6 + 0x04], %l7 ! entry->prev | ||
918 | |||
919 | st %l7, [%l3 + 0x04] ! next->prev = entry->prev | ||
920 | st %l3, [%l7 + 0x00] ! entry->prev->next = next | ||
921 | |||
922 | sethi %hi(sun4c_kernel_ring), %l4 | ||
923 | or %l4, %lo(sun4c_kernel_ring), %l4 | ||
924 | ! head = &sun4c_kernel_ring.ringhd | ||
925 | |||
926 | ld [%l4 + 0x00], %l7 ! head->next | ||
927 | |||
928 | st %l4, [%l6 + 0x04] ! entry->prev = head | ||
929 | st %l7, [%l6 + 0x00] ! entry->next = head->next | ||
930 | st %l6, [%l7 + 0x04] ! head->next->prev = entry | ||
931 | |||
932 | st %l6, [%l4 + 0x00] ! head->next = entry | ||
933 | |||
934 | ld [%l4 + 0x18], %l3 | ||
935 | inc %l3 ! sun4c_kernel_ring.num_entries++ | ||
936 | st %l3, [%l4 + 0x18] | ||
937 | b 4f | ||
938 | ld [%l6 + 0x08], %l5 | ||
939 | |||
940 | 2: | ||
941 | or %l4, %lo(sun4c_kernel_ring), %l4 | ||
942 | ! head = &sun4c_kernel_ring.ringhd | ||
943 | |||
944 | ld [%l4 + 0x04], %l6 ! entry = head->prev | ||
945 | |||
946 | ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr | ||
947 | |||
948 | ! Flush segment from the cache. | ||
949 | sethi %hi((64 * 1024)), %l7 | ||
950 | 9: | ||
951 | vac_hwflush_patch1: | ||
952 | vac_linesize_patch: | ||
953 | subcc %l7, 16, %l7 | ||
954 | bne 9b | ||
955 | vac_hwflush_patch2: | ||
956 | sta %g0, [%l3 + %l7] ASI_FLUSHSEG | ||
957 | |||
958 | st %l5, [%l6 + 0x08] ! entry->vaddr = address | ||
959 | |||
960 | ld [%l6 + 0x00], %l5 ! next = entry->next | ||
961 | ld [%l6 + 0x04], %l7 ! entry->prev | ||
962 | |||
963 | st %l7, [%l5 + 0x04] ! next->prev = entry->prev | ||
964 | st %l5, [%l7 + 0x00] ! entry->prev->next = next | ||
965 | st %l4, [%l6 + 0x04] ! entry->prev = head | ||
966 | |||
967 | ld [%l4 + 0x00], %l7 ! head->next | ||
968 | |||
969 | st %l7, [%l6 + 0x00] ! entry->next = head->next | ||
970 | st %l6, [%l7 + 0x04] ! head->next->prev = entry | ||
971 | st %l6, [%l4 + 0x00] ! head->next = entry | ||
972 | |||
973 | mov %l3, %l5 ! address = tmp | ||
974 | |||
975 | 4: | ||
976 | num_context_patch1: | ||
977 | mov 0x08, %l7 | ||
978 | |||
979 | ld [%l6 + 0x08], %l4 | ||
980 | ldub [%l6 + 0x0c], %l3 | ||
981 | or %l4, %l3, %l4 ! encode new vaddr/pseg into l4 | ||
982 | |||
983 | sethi %hi(AC_CONTEXT), %l3 | ||
984 | lduba [%l3] ASI_CONTROL, %l6 | ||
985 | |||
986 | /* Invalidate old mapping, instantiate new mapping, | ||
987 | * for each context. Registers l6/l7 are live across | ||
988 | * this loop. | ||
989 | */ | ||
990 | 3: deccc %l7 | ||
991 | sethi %hi(AC_CONTEXT), %l3 | ||
992 | stba %l7, [%l3] ASI_CONTROL | ||
993 | invalid_segment_patch2: | ||
994 | mov 0x7f, %l3 | ||
995 | stXa %l3, [%l5] ASI_SEGMAP | ||
996 | andn %l4, 0x1ff, %l3 | ||
997 | bne 3b | ||
998 | stXa %l4, [%l3] ASI_SEGMAP | ||
999 | |||
1000 | sethi %hi(AC_CONTEXT), %l3 | ||
1001 | stba %l6, [%l3] ASI_CONTROL | ||
1002 | |||
1003 | andn %l4, 0x1ff, %l5 | ||
1004 | |||
1005 | 1: | ||
1006 | sethi %hi(VMALLOC_START), %l4 | ||
1007 | cmp %l5, %l4 | ||
1008 | |||
1009 | bgeu 1f | ||
1010 | mov 1 << (SUN4C_REAL_PGDIR_SHIFT - PAGE_SHIFT), %l7 | ||
1011 | |||
1012 | sethi %hi(KERNBASE), %l6 | ||
1013 | |||
1014 | sub %l5, %l6, %l4 | ||
1015 | srl %l4, PAGE_SHIFT, %l4 | ||
1016 | sethi %hi((SUN4C_PAGE_KERNEL & 0xf4000000)), %l3 | ||
1017 | or %l3, %l4, %l3 | ||
1018 | |||
1019 | sethi %hi(PAGE_SIZE), %l4 | ||
1020 | |||
1021 | 2: | ||
1022 | sta %l3, [%l5] ASI_PTE | ||
1023 | deccc %l7 | ||
1024 | inc %l3 | ||
1025 | bne 2b | ||
1026 | add %l5, %l4, %l5 | ||
1027 | |||
1028 | b 7f | ||
1029 | sethi %hi(sun4c_kernel_faults), %l4 | ||
1030 | |||
1031 | 1: | ||
1032 | srl %l5, SUN4C_PGDIR_SHIFT, %l3 | ||
1033 | sethi %hi(swapper_pg_dir), %l4 | ||
1034 | or %l4, %lo(swapper_pg_dir), %l4 | ||
1035 | sll %l3, 2, %l3 | ||
1036 | ld [%l4 + %l3], %l4 | ||
1037 | and %l4, PAGE_MASK, %l4 | ||
1038 | |||
1039 | srl %l5, (PAGE_SHIFT - 2), %l6 | ||
1040 | and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6 | ||
1041 | add %l6, %l4, %l6 | ||
1042 | |||
1043 | sethi %hi(PAGE_SIZE), %l4 | ||
1044 | |||
1045 | 2: | ||
1046 | ld [%l6], %l3 | ||
1047 | deccc %l7 | ||
1048 | sta %l3, [%l5] ASI_PTE | ||
1049 | add %l6, 0x4, %l6 | ||
1050 | bne 2b | ||
1051 | add %l5, %l4, %l5 | ||
1052 | |||
1053 | sethi %hi(sun4c_kernel_faults), %l4 | ||
1054 | 7: | ||
1055 | ld [%l4 + %lo(sun4c_kernel_faults)], %l3 | ||
1056 | inc %l3 | ||
1057 | st %l3, [%l4 + %lo(sun4c_kernel_faults)] | ||
1058 | |||
1059 | /* Restore condition codes */ | ||
1060 | wr %l0, 0x0, %psr | ||
1061 | WRITE_PAUSE | 743 | WRITE_PAUSE |
1062 | jmp %l1 | 744 | or %l0, PSR_PIL, %l4 |
1063 | rett %l2 | 745 | wr %l4, 0x0, %psr |
1064 | 746 | WRITE_PAUSE | |
1065 | sun4c_fault_fromuser: | 747 | wr %l4, PSR_ET, %psr |
1066 | SAVE_ALL | 748 | WRITE_PAUSE |
749 | call sun4m_nmi | ||
1067 | nop | 750 | nop |
1068 | 751 | st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000 | |
1069 | mov %l7, %o1 ! Decode the info from %l7 | ||
1070 | mov %l7, %o2 | ||
1071 | and %o1, 1, %o1 ! arg2 = text_faultp | ||
1072 | mov %l7, %o3 | ||
1073 | and %o2, 2, %o2 ! arg3 = writep | ||
1074 | andn %o3, 0xfff, %o3 ! arg4 = faulting address | ||
1075 | |||
1076 | wr %l0, PSR_ET, %psr | ||
1077 | WRITE_PAUSE | 752 | WRITE_PAUSE |
753 | ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending | ||
754 | WRITE_PAUSE | ||
755 | RESTORE_ALL | ||
1078 | 756 | ||
1079 | call do_sun4c_fault | 757 | #ifndef CONFIG_SMP |
1080 | add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr | 758 | .align 4 |
759 | .globl linux_trap_ipi15_sun4m | ||
760 | linux_trap_ipi15_sun4m: | ||
761 | SAVE_ALL | ||
1081 | 762 | ||
1082 | RESTORE_ALL | 763 | ba sun4m_nmi_error |
764 | nop | ||
765 | #endif /* CONFIG_SMP */ | ||
1083 | 766 | ||
1084 | .align 4 | 767 | .align 4 |
1085 | .globl srmmu_fault | 768 | .globl srmmu_fault |
@@ -1483,11 +1166,13 @@ fpload: | |||
1483 | .globl __ndelay | 1166 | .globl __ndelay |
1484 | __ndelay: | 1167 | __ndelay: |
1485 | save %sp, -STACKFRAME_SZ, %sp | 1168 | save %sp, -STACKFRAME_SZ, %sp |
1486 | mov %i0, %o0 | 1169 | mov %i0, %o0 ! round multiplier up so large ns ok |
1487 | call .umul ! round multiplier up so large ns ok | 1170 | mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ) |
1488 | mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ) | 1171 | umul %o0, %o1, %o0 |
1489 | call .umul | 1172 | rd %y, %o1 |
1490 | mov %i1, %o1 ! udelay_val | 1173 | mov %i1, %o1 ! udelay_val |
1174 | umul %o0, %o1, %o0 | ||
1175 | rd %y, %o1 | ||
1491 | ba delay_continue | 1176 | ba delay_continue |
1492 | mov %o1, %o0 ! >>32 later for better resolution | 1177 | mov %o1, %o0 ! >>32 later for better resolution |
1493 | 1178 | ||
@@ -1496,18 +1181,21 @@ __udelay: | |||
1496 | save %sp, -STACKFRAME_SZ, %sp | 1181 | save %sp, -STACKFRAME_SZ, %sp |
1497 | mov %i0, %o0 | 1182 | mov %i0, %o0 |
1498 | sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok | 1183 | sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok |
1499 | call .umul | 1184 | or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000 |
1500 | or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000 | 1185 | umul %o0, %o1, %o0 |
1501 | call .umul | 1186 | rd %y, %o1 |
1502 | mov %i1, %o1 ! udelay_val | 1187 | mov %i1, %o1 ! udelay_val |
1188 | umul %o0, %o1, %o0 | ||
1189 | rd %y, %o1 | ||
1503 | sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32, | 1190 | sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32, |
1504 | or %g0, %lo(0x028f4b62), %l0 | 1191 | or %g0, %lo(0x028f4b62), %l0 |
1505 | addcc %o0, %l0, %o0 ! 2**32 * 0.009 999 | 1192 | addcc %o0, %l0, %o0 ! 2**32 * 0.009 999 |
1506 | bcs,a 3f | 1193 | bcs,a 3f |
1507 | add %o1, 0x01, %o1 | 1194 | add %o1, 0x01, %o1 |
1508 | 3: | 1195 | 3: |
1509 | call .umul | 1196 | mov HZ, %o0 ! >>32 earlier for wider range |
1510 | mov HZ, %o0 ! >>32 earlier for wider range | 1197 | umul %o0, %o1, %o0 |
1198 | rd %y, %o1 | ||
1511 | 1199 | ||
1512 | delay_continue: | 1200 | delay_continue: |
1513 | cmp %o0, 0x0 | 1201 | cmp %o0, 0x0 |
@@ -1670,4 +1358,26 @@ flushw_all: | |||
1670 | ret | 1358 | ret |
1671 | restore | 1359 | restore |
1672 | 1360 | ||
1361 | #ifdef CONFIG_SMP | ||
1362 | ENTRY(hard_smp_processor_id) | ||
1363 | 661: rd %tbr, %g1 | ||
1364 | srl %g1, 12, %o0 | ||
1365 | and %o0, 3, %o0 | ||
1366 | .section .cpuid_patch, "ax" | ||
1367 | /* Instruction location. */ | ||
1368 | .word 661b | ||
1369 | /* SUN4D implementation. */ | ||
1370 | lda [%g0] ASI_M_VIKING_TMP1, %o0 | ||
1371 | nop | ||
1372 | nop | ||
1373 | /* LEON implementation. */ | ||
1374 | rd %asr17, %o0 | ||
1375 | srl %o0, 0x1c, %o0 | ||
1376 | nop | ||
1377 | .previous | ||
1378 | retl | ||
1379 | nop | ||
1380 | ENDPROC(hard_smp_processor_id) | ||
1381 | #endif | ||
1382 | |||
1673 | /* End of entry.S */ | 1383 | /* End of entry.S */ |