Print this page
restore sparc comments
de-linting of .s files


   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 #if defined(lint)
  29 #include <sys/types.h>
  30 #include <sys/t_lock.h>
  31 #include <sys/promif.h>
  32 #include <sys/prom_isa.h>
  33 #endif  /* lint */
  34 
  35 #include <sys/asm_linkage.h>
  36 #include <sys/intreg.h>
  37 #include <sys/ivintr.h>
  38 #include <sys/mmu.h>
  39 #include <sys/machpcb.h>
  40 #include <sys/machtrap.h>
  41 #include <sys/machlock.h>
  42 #include <sys/fdreg.h>
  43 #include <sys/vis.h>
  44 #include <sys/traptrace.h>
  45 #include <sys/panic.h>
  46 #include <sys/machasi.h>
  47 #include <sys/clock.h>
  48 #include <vm/hat_sfmmu.h>
  49 #if defined(lint)
  50 
  51 #include <sys/thread.h>
  52 #include <sys/time.h>
  53 
  54 #else   /* lint */
  55 
  56 #include "assym.h"
  57 
  58 
  59 !
  60 ! REGOFF must add up to allow double word access to r_tstate.
  61 ! PCB_WBUF must also be aligned.
  62 !
  63 #if (REGOFF & 7) != 0
  64 #error "struct regs not aligned"
  65 #endif
  66 
  67 /*
  68  * Absolute external symbols.
  69  * On the sun4u we put the panic buffer in the third and fourth pages.
  70  * We set things up so that the first 2 pages of KERNELBASE is illegal
  71  * to act as a redzone during copyin/copyout type operations. One of
  72  * the reasons the panic buffer is allocated in low memory to
  73  * prevent being overwritten during booting operations (besides
  74  * the fact that it is small enough to share pages with others).
  75  */


 157  * show in which TRACE_PTR the assertion failure happened.
 158  */
 159         .align  8
 160 trap_freeze_pc:
 161         .nword  0
 162 #endif  /* TRAPTRACE */
 163 
 164         .align 4
 165         .seg    ".text"
 166 
 167 #ifdef  NOPROM
 168         .global availmem
 169 availmem:
 170         .word   0
 171 #endif  /* NOPROM */
 172 
 173         .align  8
 174 _local_p1275cis:
 175         .nword  0
 176 
 177 #endif  /* lint */
 178 
 179 #if defined(lint)
 180 
 181 void
 182 _start(void)
 183 {}
 184 
 185 #else /* lint */
 186 
 187         .seg    ".data"
 188 
 189         .global nwindows, nwin_minus_one, winmask
 190 nwindows:
 191         .word   8
 192 nwin_minus_one:
 193         .word   7
 194 winmask:
 195         .word   8
 196 
 197         .global afsrbuf
 198 afsrbuf:
 199         .word   0,0,0,0
 200 
 201 /*
 202  * System initialization
 203  *
 204  * Our contract with the boot prom specifies that the MMU is on and the
 205  * first 16 meg of memory is mapped with a level-1 pte.  We are called
 206  * with p1275cis ptr in %o0 and kdi_dvec in %o1; we start execution


 339 #endif
 340 
 341         !
 342         ! Now call main.  We will return as process 1 (init).
 343         !
 344         call    main
 345         nop
 346 
 347         !
 348         ! Main should never return.
 349         !
 350         set     .mainretmsg, %o0
 351         call    panic
 352         nop
 353         SET_SIZE(_start)
 354 
 355 .mainretmsg:
 356         .asciz  "main returned"
 357         .align  4
 358 
 359 #endif  /* lint */
 360 
 361 
 362 /*
 363  * Generic system trap handler.
 364  *
 365  * Some kernel trap handlers save themselves from buying a window by
 366  * borrowing some of sys_trap's unused locals. %l0 thru %l3 may be used
 367  * for this purpose, as user_rtt and priv_rtt do not depend on them.
 368  * %l4 thru %l7 should NOT be used this way.
 369  *
 370  * Entry Conditions:
 371  *      %pstate         am:0 priv:1 ie:0
 372  *                      globals are either ag or ig (not mg!)
 373  *
 374  * Register Inputs:
 375  *      %g1             pc of trap handler
 376  *      %g2, %g3        args for handler
 377  *      %g4             desired %pil (-1 means current %pil)
 378  *      %g5, %g6        destroyed
 379  *      %g7             saved
 380  *
 381  * Register Usage:
 382  *      %l0, %l1        temps
 383  *      %l3             saved %g1
 384  *      %l6             curthread for user traps, %pil for priv traps
 385  *      %l7             regs
 386  *
 387  * Called function prototype variants:
 388  *
 389  *      func(struct regs *rp);
 390  *      func(struct regs *rp, uintptr_t arg1 [%g2], uintptr_t arg2 [%g3])
 391  *      func(struct regs *rp, uintptr_t arg1 [%g2],
 392  *          uint32_t arg2 [%g3.l], uint32_t arg3 [%g3.h])
 393  *      func(struct regs *rp, uint32_t arg1 [%g2.l],
 394  *          uint32_t arg2 [%g3.l], uint32_t arg3 [%g3.h], uint32_t [%g2.h])
 395  */
 396 
 397 #if defined(lint)
 398 
 399 void
 400 sys_trap(void)
 401 {}
 402 
 403 #else   /* lint */
 404 
 405         ENTRY_NP(sys_trap)
 406         !
 407         ! force tl=1, update %cwp, branch to correct handler
 408         !
 409         wrpr    %g0, 1, %tl
 410         rdpr    %tstate, %g5
 411         btst    TSTATE_PRIV, %g5
 412         and     %g5, TSTATE_CWP, %g6
 413         bnz,pn  %xcc, priv_trap
 414         wrpr    %g0, %g6, %cwp
 415 
 416         ALTENTRY(user_trap)
 417         !
 418         ! user trap
 419         !
 420         ! make all windows clean for kernel
 421         ! buy a window using the current thread's stack
 422         !
 423         sethi   %hi(nwin_minus_one), %g5
 424         ld      [%g5 + %lo(nwin_minus_one)], %g5


 858         !
 859         wrpr    %g0, 1, %tl
 860         ldn     [%l7 + PC_OFF], %g1
 861         ldn     [%l7 + nPC_OFF], %g2
 862         ldx     [%l7 + TSTATE_OFF], %l0
 863         andn    %l0, TSTATE_CWP, %g7
 864         wrpr    %g1, %tpc
 865         wrpr    %g2, %tnpc
 866         restore
 867         !
 868         ! set %tstate to the correct %cwp
 869         ! retry resumes prom execution
 870         !
 871         rdpr    %cwp, %g1
 872         wrpr    %g1, %g7, %tstate
 873         retry
 874         /* NOTREACHED */
 875         SET_SIZE(priv_rtt)
 876         SET_SIZE(ktl0)
 877 
 878 #endif  /* lint */
 879 
 880 #ifndef lint
 881 
 882 #ifdef DEBUG
 883         .seg    ".data"
 884         .align  4
 885 
 886         .global bad_g4_called
 887 bad_g4_called:
 888         .word   0
 889 
 890 sys_trap_wrong_pil:
 891         .asciz  "sys_trap: %g4(%d) is lower than %pil(%d)"
 892         .align  4
 893         .seg    ".text"
 894 
 895         ENTRY_NP(bad_g4)
 896         mov     %o1, %o0
 897         mov     %o2, %o1
 898         call    panic
 899         mov     %o3, %o2
 900         SET_SIZE(bad_g4)
 901 #endif /* DEBUG */
 902 #endif /* lint */
 903 
 904 /*
 905  * sys_tl1_panic can be called by traps at tl1 which
 906  * really want to panic, but need the rearrangement of
 907  * the args as provided by this wrapper routine.
 908  */
 909 #if defined(lint)
 910 
 911 void
 912 sys_tl1_panic(void)
 913 {}
 914 
 915 #else   /* lint */
 916         ENTRY_NP(sys_tl1_panic)
 917         mov     %o1, %o0
 918         mov     %o2, %o1
 919         call    panic
 920         mov     %o3, %o2
 921         SET_SIZE(sys_tl1_panic)
 922 #endif /* lint */
 923 
 924 /*
 925  * Turn on or off bits in the auxiliary i/o register.
 926  *
 927  * set_auxioreg(bit, flag)
 928  *      int bit;                bit mask in aux i/o reg
 929  *      int flag;               0 = off, otherwise on
 930  *
 931  * This is intrinsicly ugly but is used by the floppy driver.  It is also
 932  * used to turn on/off the led.
 933  */
 934 
 935 #if defined(lint)
 936 
 937 /* ARGSUSED */
 938 void
 939 set_auxioreg(int bit, int flag)
 940 {}
 941 
 942 #else   /* lint */
 943 
 944         .seg    ".data"
 945         .align  4
 946 auxio_panic:
 947         .asciz  "set_auxioreg: interrupts already disabled on entry"
 948         .align  4
 949         .seg    ".text"
 950 
 951         ENTRY_NP(set_auxioreg)
 952         /*
 953          * o0 = bit mask
 954          * o1 = flag: 0 = off, otherwise on
 955          *
 956          * disable interrupts while updating auxioreg
 957          */
 958         rdpr    %pstate, %o2
 959 #ifdef  DEBUG
 960         andcc   %o2, PSTATE_IE, %g0     /* if interrupts already */
 961         bnz,a,pt %icc, 1f               /* disabled, panic */
 962           nop
 963         sethi   %hi(auxio_panic), %o0
 964         call    panic
 965           or    %o0, %lo(auxio_panic), %o0
 966 1:
 967 #endif /* DEBUG */
 968         wrpr    %o2, PSTATE_IE, %pstate         /* disable interrupts */
 969         sethi   %hi(v_auxio_addr), %o3
 970         ldn     [%o3 + %lo(v_auxio_addr)], %o4
 971         ldub    [%o4], %g1                      /* read aux i/o register */
 972         tst     %o1
 973         bnz,a   2f
 974          bset   %o0, %g1                /* on */
 975         bclr    %o0, %g1                /* off */
 976 2:
 977         or      %g1, AUX_MBO, %g1       /* Must Be Ones */
 978         stb     %g1, [%o4]              /* write aux i/o register */
 979         retl
 980          wrpr   %g0, %o2, %pstate       /* enable interrupt */
 981         SET_SIZE(set_auxioreg)
 982 
 983 #endif /* lint */
 984 
 985 /*
 986  * Flush all windows to memory, except for the one we entered in.
 987  * We do this by doing NWINDOW-2 saves then the same number of restores.
 988  * This leaves the WIM immediately before window entered in.
 989  * This is used for context switching.
 990  */
 991 
 992 #if defined(lint)
 993 
 994 void
 995 flush_windows(void)
 996 {}
 997 
 998 #else   /* lint */
 999 
1000         ENTRY_NP(flush_windows)
1001         retl
1002         flushw
1003         SET_SIZE(flush_windows)
1004 
1005 #endif  /* lint */
1006 
1007 #if defined(lint)
1008 
1009 void
1010 debug_flush_windows(void)
1011 {}
1012 
1013 #else   /* lint */
1014 
1015         ENTRY_NP(debug_flush_windows)
1016         set     nwindows, %g1
1017         ld      [%g1], %g1
1018         mov     %g1, %g2
1019 
1020 1:
1021         save    %sp, -WINDOWSIZE, %sp
1022         brnz    %g2, 1b
1023         dec     %g2
1024 
1025         mov     %g1, %g2
1026 2:
1027         restore
1028         brnz    %g2, 2b
1029         dec     %g2
1030 
1031         retl
1032         nop
1033 
1034         SET_SIZE(debug_flush_windows)
1035 
1036 #endif  /* lint */
1037 
1038 /*
1039  * flush user windows to memory.
1040  */
1041 
1042 #if defined(lint)
1043 
1044 void
1045 flush_user_windows(void)
1046 {}
1047 
1048 #else   /* lint */
1049 
1050         ENTRY_NP(flush_user_windows)
1051         rdpr    %otherwin, %g1
1052         brz     %g1, 3f
1053         clr     %g2
1054 1:
1055         save    %sp, -WINDOWSIZE, %sp
1056         rdpr    %otherwin, %g1
1057         brnz    %g1, 1b
1058         add     %g2, 1, %g2
1059 2:
1060         sub     %g2, 1, %g2             ! restore back to orig window
1061         brnz    %g2, 2b
1062         restore
1063 3:
1064         retl
1065         nop
1066         SET_SIZE(flush_user_windows)
1067 
1068 #endif  /* lint */
1069 
1070 /*
1071  * Throw out any user windows in the register file.
1072  * Used by setregs (exec) to clean out old user.
1073  * Used by sigcleanup to remove extraneous windows when returning from a
1074  * signal.
1075  */
1076 
1077 #if defined(lint)
1078 
1079 void
1080 trash_user_windows(void)
1081 {}
1082 
1083 #else   /* lint */
1084 
1085         ENTRY_NP(trash_user_windows)
1086         rdpr    %otherwin, %g1
1087         brz     %g1, 3f                 ! no user windows?
1088         ldn     [THREAD_REG + T_STACK], %g5
1089 
1090         !
1091         ! There are old user windows in the register file. We disable ints
1092         ! and increment cansave so that we don't overflow on these windows.
1093         ! Also, this sets up a nice underflow when first returning to the
1094         ! new user.
1095         !
1096         rdpr    %pstate, %g2
1097         wrpr    %g2, PSTATE_IE, %pstate
1098         rdpr    %cansave, %g3
1099         rdpr    %otherwin, %g1          ! re-read in case of interrupt
1100         add     %g3, %g1, %g3
1101         wrpr    %g0, 0, %otherwin
1102         wrpr    %g0, %g3, %cansave
1103         wrpr    %g0, %g2, %pstate
1104 3:
1105         retl
1106         clr     [%g5 + MPCB_WBCNT]       ! zero window buffer cnt
1107         SET_SIZE(trash_user_windows)
1108 
1109 
1110 #endif  /* lint */
1111 
1112 /*
1113  * Setup g7 via the CPU data structure.
1114  */
1115 #if defined(lint)
1116 
1117 struct scb *
1118 set_tbr(struct scb *s)
1119 { return (s); }
1120 
1121 #else   /* lint */
1122 
1123         ENTRY_NP(set_tbr)
1124         retl
1125         ta      72              ! no tbr, stop simulation
1126         SET_SIZE(set_tbr)
1127 
1128 #endif  /* lint */
1129 
1130 
1131 #if defined(lint)
1132 /*
1133  * These need to be defined somewhere to lint and there is no "hicore.s"...
1134  */
1135 char etext[1], end[1];
1136 #endif  /* lint*/
1137 
1138 #if defined (lint)
1139 
1140 /* ARGSUSED */
1141 void
1142 ptl1_panic(u_int reason)
1143 {}
1144 
1145 #else /* lint */
1146 
1147 #define PTL1_SAVE_WINDOW(RP)                                            \
1148         stxa    %l0, [RP + RW64_LOCAL + (0 * RW64_LOCAL_INCR)] %asi;    \
1149         stxa    %l1, [RP + RW64_LOCAL + (1 * RW64_LOCAL_INCR)] %asi;    \
1150         stxa    %l2, [RP + RW64_LOCAL + (2 * RW64_LOCAL_INCR)] %asi;    \
1151         stxa    %l3, [RP + RW64_LOCAL + (3 * RW64_LOCAL_INCR)] %asi;    \
1152         stxa    %l4, [RP + RW64_LOCAL + (4 * RW64_LOCAL_INCR)] %asi;    \
1153         stxa    %l5, [RP + RW64_LOCAL + (5 * RW64_LOCAL_INCR)] %asi;    \
1154         stxa    %l6, [RP + RW64_LOCAL + (6 * RW64_LOCAL_INCR)] %asi;    \
1155         stxa    %l7, [RP + RW64_LOCAL + (7 * RW64_LOCAL_INCR)] %asi;    \
1156         stxa    %i0, [RP + RW64_IN + (0 * RW64_IN_INCR)] %asi;          \
1157         stxa    %i1, [RP + RW64_IN + (1 * RW64_IN_INCR)] %asi;          \
1158         stxa    %i2, [RP + RW64_IN + (2 * RW64_IN_INCR)] %asi;          \
1159         stxa    %i3, [RP + RW64_IN + (3 * RW64_IN_INCR)] %asi;          \
1160         stxa    %i4, [RP + RW64_IN + (4 * RW64_IN_INCR)] %asi;          \
1161         stxa    %i5, [RP + RW64_IN + (5 * RW64_IN_INCR)] %asi;          \
1162         stxa    %i6, [RP + RW64_IN + (6 * RW64_IN_INCR)] %asi;          \
1163         stxa    %i7, [RP + RW64_IN + (7 * RW64_IN_INCR)] %asi
1164 #define PTL1_NEXT_WINDOW(scr)   \
1165         add     scr, RWIN64SIZE, scr
1166 


1401         CPU_ADDR(%l0, %l1)                      ! %l0 = cpu[cpuid]
1402         add     %l0, CPU_PTL1, %l1              ! %l1 = &CPU->mcpu.ptl1_state
1403         !
1404         ! prepare to call panic()
1405         !
1406         ldn     [%l0 + CPU_THREAD], THREAD_REG  ! restore %g7
1407         ldn     [%l1 + PTL1_STKTOP], %l2        ! %sp = ptl1_stktop
1408         sub     %l2, SA(MINFRAME) + STACK_BIAS, %sp
1409         clr     %fp                             ! no frame below this window
1410         clr     %i7
1411         !
1412         ! enable limited interrupts
1413         !
1414         wrpr    %g0, CLOCK_LEVEL, %pil
1415         wrpr    %g0, PSTATE_KERN, %pstate
1416         !
1417         ba,pt   %xcc, ptl1_panic_handler
1418           mov   %l1, %o0
1419         /*NOTREACHED*/
1420         SET_SIZE(ptl1_panic)
1421 #endif /* lint */
1422 
1423 #ifdef  PTL1_PANIC_DEBUG
1424 #if defined (lint)
1425 /*
1426  * ptl1_recurse() calls itself a number of times to either set up a known
1427  * stack or to cause a kernel stack overflow. It decrements the arguments 
1428  * on each recursion.
1429  * It's called by #ifdef PTL1_PANIC_DEBUG code in startup.c to set the
1430  * registers to a known state to facilitate debugging.
1431  */
1432 
1433 /* ARGSUSED */
1434 void 
1435 ptl1_recurse(int count_threshold, int trap_threshold)
1436 {}
1437 
1438 #else /* lint */
1439 
1440         ENTRY_NP(ptl1_recurse)
1441         save    %sp, -SA(MINFRAME), %sp
1442 
1443         set     ptl1_recurse_call, %o7
1444         cmp     %o7, %i7                        ! if ptl1_recurse is called
1445         be,pt  %icc, 0f                         ! by itself, then skip
1446           nop                                   ! register initialization
1447 
1448         /* 
1449          * Initialize Out Registers to Known Values 
1450          */
1451         set     0x01000, %l0                    ! %i0 is the ...
1452                                                 ! recursion_depth_count
1453         sub     %i0, 1, %o0;
1454         sub     %i1, 1, %o1;
1455         add     %l0, %o0, %o2;
1456         add     %l0, %o2, %o3;
1457         add     %l0, %o3, %o4;
1458         add     %l0, %o4, %o5;
1459         ba,a    1f


1484 
1485         brz,pn %i1, ptl1_recurse_trap           ! if trpp_count == 0) {
1486           nop                                   !    trap to ptl1_panic
1487                                                 !                       
1488         brz,pn %i0, ptl1_recure_exit            ! if(depth_count == 0) {
1489           nop                                   !    skip recursive call
1490                                                 ! }
1491 ptl1_recurse_call:
1492         call    ptl1_recurse
1493           nop
1494 
1495 ptl1_recure_exit:
1496         ret
1497         restore
1498 
1499 ptl1_recurse_trap:
1500         ta      PTL1_DEBUG_TRAP;                ! Trap Always to ptl1_panic()
1501           nop                                   ! NOTREACHED 
1502         SET_SIZE(ptl1_recurse)
1503 
1504 #endif /* lint */
1505 
1506 #if defined (lint)
1507 
1508 /* ARGSUSED */
1509 void
1510 ptl1_panic_xt(int arg1, int arg2)
1511 {}
1512 
1513 #else /* lint */
1514         /*
1515          * Asm function to handle a cross trap to call ptl1_panic()
1516          */
1517         ENTRY_NP(ptl1_panic_xt)
1518         ba      ptl1_panic
1519           mov   PTL1_BAD_DEBUG, %g1
1520         SET_SIZE(ptl1_panic_xt)
1521 
1522 #endif /* lint */
1523 
1524 #endif  /* PTL1_PANIC_DEBUG */
1525 
1526 #ifdef  TRAPTRACE
1527 #if     defined (lint)
1528 
1529 void
1530 trace_ptr_panic(void)
1531 {
1532 }
1533 
1534 #else   /* lint */
1535 
1536         ENTRY_NP(trace_ptr_panic)
1537         !
1538         ! freeze the trap trace to disable the assertions.  Otherwise,
1539         ! ptl1_panic is likely to be repeatedly called from there.
1540         ! %g2 and %g3 are used as scratch registers in ptl1_panic.
1541         !
1542         mov     1, %g3
1543         sethi   %hi(trap_freeze), %g2
1544         st      %g3, [%g2 + %lo(trap_freeze)]
1545         !
1546         ! %g1 contains the %pc address where an assertion was failed.
1547         ! save it in trap_freeze_pc for a debugging hint if there is
1548         ! no value saved in it.
1549         !
1550         set     trap_freeze_pc, %g2
1551         casn    [%g2], %g0, %g1
1552 
1553         ba      ptl1_panic
1554         mov     PTL1_BAD_TRACE_PTR, %g1
1555         SET_SIZE(trace_ptr_panic)
1556 
1557 #endif  /* lint */
1558 #endif  /* TRAPTRACE */
1559         
1560 #if     defined (lint)
1561 /*
1562  * set_kcontextreg() sets PCONTEXT to kctx
1563  * if PCONTEXT==kctx, do nothing
1564  * if N_pgsz0|N_pgsz1 differ, do demap all first
1565  */
1566 
1567 /* ARGSUSED */
1568 void
1569 set_kcontextreg()
1570 {
1571 }
1572 
1573 #else   /* lint */
1574 
1575         ENTRY_NP(set_kcontextreg)
1576         ! SET_KCONTEXTREG(reg0, reg1, reg2, reg3, reg4, label1, label2, label3)
1577         SET_KCONTEXTREG(%o0, %o1, %o2, %o3, %o4, l1, l2, l3)
1578         retl
1579         nop
1580         SET_SIZE(set_kcontextreg)
1581         
1582 #endif /* lint */
1583         
1584 
1585 /*
1586  * The interface for a 32-bit client program that takes over the TBA
1587  * calling the 64-bit romvec OBP.
1588  */
1589 
1590 #if defined(lint)
1591 
1592 /* ARGSUSED */
1593 int
1594 client_handler(void *cif_handler, void *arg_array)
1595 { return 0; }
1596 
1597 #else   /* lint */
1598 
1599         ENTRY(client_handler)
1600         save    %sp, -SA64(MINFRAME64), %sp     ! 32 bit frame, 64 bit sized
1601         sethi   %hi(tba_taken_over), %l2
1602         ld      [%l2+%lo(tba_taken_over)], %l3
1603         brz     %l3, 1f                         ! is the tba_taken_over = 1 ?
1604         rdpr    %wstate, %l5                    ! save %wstate
1605         andn    %l5, WSTATE_MASK, %l6
1606         wrpr    %l6, WSTATE_KMIX, %wstate
1607 
1608         !
1609         ! switch to PCONTEXT=0
1610         !
1611 #ifndef _OPL
1612         mov     MMU_PCONTEXT, %o2
1613         ldxa    [%o2]ASI_DMMU, %o2
1614         srlx    %o2, CTXREG_NEXT_SHIFT, %o2
1615         brz,pt  %o2, 1f                         ! nucleus pgsz is 0, no problem
1616           nop
1617         rdpr    %pstate, %l4                    ! disable interrupts
1618         andn    %l4, PSTATE_IE, %o2


1647         ldx     [%o3 + %lo(kcontextreg)], %o3
1648         brz     %o3, 1f
1649           nop
1650         rdpr    %pstate, %l4                    ! disable interrupts
1651         andn    %l4, PSTATE_IE, %o2
1652         wrpr    %g0, %o2, %pstate
1653         mov     DEMAP_ALL_TYPE, %o2
1654         stxa    %g0, [%o2]ASI_DTLB_DEMAP
1655         stxa    %g0, [%o2]ASI_ITLB_DEMAP
1656         mov     MMU_PCONTEXT, %o2
1657         stxa    %o3, [%o2]ASI_DMMU
1658         membar  #Sync
1659         sethi   %hi(FLUSH_ADDR), %o2
1660         flush   %o2                             ! flush required by immu
1661         wrpr    %g0, %l4, %pstate               ! restore interrupt state
1662 #endif /* _OPL */
1663 
1664 1:      ret                                     ! Return result ...
1665         restore %o0, %g0, %o0                   ! delay; result in %o0
1666         SET_SIZE(client_handler)
1667 
1668 #endif  /* lint */
1669         


   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 









  26 #include <sys/asm_linkage.h>
  27 #include <sys/intreg.h>
  28 #include <sys/ivintr.h>
  29 #include <sys/mmu.h>
  30 #include <sys/machpcb.h>
  31 #include <sys/machtrap.h>
  32 #include <sys/machlock.h>
  33 #include <sys/fdreg.h>
  34 #include <sys/vis.h>
  35 #include <sys/traptrace.h>
  36 #include <sys/panic.h>
  37 #include <sys/machasi.h>
  38 #include <sys/clock.h>
  39 #include <vm/hat_sfmmu.h>

  40 





  41 #include "assym.h"
  42 
  43 
  44 !
  45 ! REGOFF must add up to allow double word access to r_tstate.
  46 ! PCB_WBUF must also be aligned.
  47 !
  48 #if (REGOFF & 7) != 0
  49 #error "struct regs not aligned"
  50 #endif
  51 
  52 /*
  53  * Absolute external symbols.
  54  * On the sun4u we put the panic buffer in the third and fourth pages.
  55  * We set things up so that the first 2 pages of KERNELBASE is illegal
  56  * to act as a redzone during copyin/copyout type operations. One of
  57  * the reasons the panic buffer is allocated in low memory to
  58  * prevent being overwritten during booting operations (besides
  59  * the fact that it is small enough to share pages with others).
  60  */


 142  * show in which TRACE_PTR the assertion failure happened.
 143  */
 144         .align  8
 145 trap_freeze_pc:
 146         .nword  0
 147 #endif  /* TRAPTRACE */
 148 
 149         .align 4
 150         .seg    ".text"
 151 
 152 #ifdef  NOPROM
 153         .global availmem
 154 availmem:
 155         .word   0
 156 #endif  /* NOPROM */
 157 
 158         .align  8
 159 _local_p1275cis:
 160         .nword  0
 161 










 162         .seg    ".data"
 163 
 164         .global nwindows, nwin_minus_one, winmask
 165 nwindows:
 166         .word   8
 167 nwin_minus_one:
 168         .word   7
 169 winmask:
 170         .word   8
 171 
 172         .global afsrbuf
 173 afsrbuf:
 174         .word   0,0,0,0
 175 
 176 /*
 177  * System initialization
 178  *
 179  * Our contract with the boot prom specifies that the MMU is on and the
 180  * first 16 meg of memory is mapped with a level-1 pte.  We are called
 181  * with p1275cis ptr in %o0 and kdi_dvec in %o1; we start execution


 314 #endif
 315 
 316         !
 317         ! Now call main.  We will return as process 1 (init).
 318         !
 319         call    main
 320         nop
 321 
 322         !
 323         ! Main should never return.
 324         !
 325         set     .mainretmsg, %o0
 326         call    panic
 327         nop
 328         SET_SIZE(_start)
 329 
 330 .mainretmsg:
 331         .asciz  "main returned"
 332         .align  4
 333 

 334 

 335 /*
 336  * Generic system trap handler.
 337  *
 338  * Some kernel trap handlers save themselves from buying a window by
 339  * borrowing some of sys_trap's unused locals. %l0 thru %l3 may be used
 340  * for this purpose, as user_rtt and priv_rtt do not depend on them.
 341  * %l4 thru %l7 should NOT be used this way.
 342  *
 343  * Entry Conditions:
 344  *      %pstate         am:0 priv:1 ie:0
 345  *                      globals are either ag or ig (not mg!)
 346  *
 347  * Register Inputs:
 348  *      %g1             pc of trap handler
 349  *      %g2, %g3        args for handler
 350  *      %g4             desired %pil (-1 means current %pil)
 351  *      %g5, %g6        destroyed
 352  *      %g7             saved
 353  *
 354  * Register Usage:
 355  *      %l0, %l1        temps
 356  *      %l3             saved %g1
 357  *      %l6             curthread for user traps, %pil for priv traps
 358  *      %l7             regs
 359  *
 360  * Called function prototype variants:
 361  *
 362  *      func(struct regs *rp);
 363  *      func(struct regs *rp, uintptr_t arg1 [%g2], uintptr_t arg2 [%g3])
 364  *      func(struct regs *rp, uintptr_t arg1 [%g2],
 365  *          uint32_t arg2 [%g3.l], uint32_t arg3 [%g3.h])
 366  *      func(struct regs *rp, uint32_t arg1 [%g2.l],
 367  *          uint32_t arg2 [%g3.l], uint32_t arg3 [%g3.h], uint32_t [%g2.h])
 368  */
 369 








 370         ENTRY_NP(sys_trap)
 371         !
 372         ! force tl=1, update %cwp, branch to correct handler
 373         !
 374         wrpr    %g0, 1, %tl
 375         rdpr    %tstate, %g5
 376         btst    TSTATE_PRIV, %g5
 377         and     %g5, TSTATE_CWP, %g6
 378         bnz,pn  %xcc, priv_trap
 379         wrpr    %g0, %g6, %cwp
 380 
 381         ALTENTRY(user_trap)
 382         !
 383         ! user trap
 384         !
 385         ! make all windows clean for kernel
 386         ! buy a window using the current thread's stack
 387         !
 388         sethi   %hi(nwin_minus_one), %g5
 389         ld      [%g5 + %lo(nwin_minus_one)], %g5


 823         !
 824         wrpr    %g0, 1, %tl
 825         ldn     [%l7 + PC_OFF], %g1
 826         ldn     [%l7 + nPC_OFF], %g2
 827         ldx     [%l7 + TSTATE_OFF], %l0
 828         andn    %l0, TSTATE_CWP, %g7
 829         wrpr    %g1, %tpc
 830         wrpr    %g2, %tnpc
 831         restore
 832         !
 833         ! set %tstate to the correct %cwp
 834         ! retry resumes prom execution
 835         !
 836         rdpr    %cwp, %g1
 837         wrpr    %g1, %g7, %tstate
 838         retry
 839         /* NOTREACHED */
 840         SET_SIZE(priv_rtt)
 841         SET_SIZE(ktl0)
 842 




 843 #ifdef DEBUG
 844         .seg    ".data"
 845         .align  4
 846 
 847         .global bad_g4_called
 848 bad_g4_called:
 849         .word   0
 850 
 851 sys_trap_wrong_pil:
 852         .asciz  "sys_trap: %g4(%d) is lower than %pil(%d)"
 853         .align  4
 854         .seg    ".text"
 855 
 856         ENTRY_NP(bad_g4)
 857         mov     %o1, %o0
 858         mov     %o2, %o1
 859         call    panic
 860         mov     %o3, %o2
 861         SET_SIZE(bad_g4)
 862 #endif /* DEBUG */

 863 
 864 /*
 865  * sys_tl1_panic can be called by traps at tl1 which
 866  * really want to panic, but need the rearrangement of
 867  * the args as provided by this wrapper routine.
 868  */







 869         ENTRY_NP(sys_tl1_panic)
 870         mov     %o1, %o0
 871         mov     %o2, %o1
 872         call    panic
 873         mov     %o3, %o2
 874         SET_SIZE(sys_tl1_panic)

 875 
 876 /*
 877  * Turn on or off bits in the auxiliary i/o register.
 878  *
 879  * set_auxioreg(bit, flag)
 880  *      int bit;                bit mask in aux i/o reg
 881  *      int flag;               0 = off, otherwise on
 882  *
 883  * This is intrinsicly ugly but is used by the floppy driver.  It is also
 884  * used to turn on/off the led.
 885  */
 886 









 887         .seg    ".data"
 888         .align  4
 889 auxio_panic:
 890         .asciz  "set_auxioreg: interrupts already disabled on entry"
 891         .align  4
 892         .seg    ".text"
 893 
 894         ENTRY_NP(set_auxioreg)
 895         /*
 896          * o0 = bit mask
 897          * o1 = flag: 0 = off, otherwise on
 898          *
 899          * disable interrupts while updating auxioreg
 900          */
 901         rdpr    %pstate, %o2
 902 #ifdef  DEBUG
 903         andcc   %o2, PSTATE_IE, %g0     /* if interrupts already */
 904         bnz,a,pt %icc, 1f               /* disabled, panic */
 905           nop
 906         sethi   %hi(auxio_panic), %o0
 907         call    panic
 908           or    %o0, %lo(auxio_panic), %o0
 909 1:
 910 #endif /* DEBUG */
 911         wrpr    %o2, PSTATE_IE, %pstate         /* disable interrupts */
 912         sethi   %hi(v_auxio_addr), %o3
 913         ldn     [%o3 + %lo(v_auxio_addr)], %o4
 914         ldub    [%o4], %g1                      /* read aux i/o register */
 915         tst     %o1
 916         bnz,a   2f
 917          bset   %o0, %g1                /* on */
 918         bclr    %o0, %g1                /* off */
 919 2:
 920         or      %g1, AUX_MBO, %g1       /* Must Be Ones */
 921         stb     %g1, [%o4]              /* write aux i/o register */
 922         retl
 923          wrpr   %g0, %o2, %pstate       /* enable interrupt */
 924         SET_SIZE(set_auxioreg)
 925 


 926 /*
 927  * Flush all windows to memory, except for the one we entered in.
 928  * We do this by doing NWINDOW-2 saves then the same number of restores.
 929  * This leaves the WIM immediately before window entered in.
 930  * This is used for context switching.
 931  */
 932 








 933         ENTRY_NP(flush_windows)
 934         retl
 935         flushw
 936         SET_SIZE(flush_windows)
 937 










 938         ENTRY_NP(debug_flush_windows)
 939         set     nwindows, %g1
 940         ld      [%g1], %g1
 941         mov     %g1, %g2
 942 
 943 1:
 944         save    %sp, -WINDOWSIZE, %sp
 945         brnz    %g2, 1b
 946         dec     %g2
 947 
 948         mov     %g1, %g2
 949 2:
 950         restore
 951         brnz    %g2, 2b
 952         dec     %g2
 953 
 954         retl
 955         nop
 956 
 957         SET_SIZE(debug_flush_windows)
 958 


 959 /*
 960  * flush user windows to memory.
 961  */
 962 








 963         ENTRY_NP(flush_user_windows)
 964         rdpr    %otherwin, %g1
 965         brz     %g1, 3f
 966         clr     %g2
 967 1:
 968         save    %sp, -WINDOWSIZE, %sp
 969         rdpr    %otherwin, %g1
 970         brnz    %g1, 1b
 971         add     %g2, 1, %g2
 972 2:
 973         sub     %g2, 1, %g2             ! restore back to orig window
 974         brnz    %g2, 2b
 975         restore
 976 3:
 977         retl
 978         nop
 979         SET_SIZE(flush_user_windows)
 980 


 981 /*
 982  * Throw out any user windows in the register file.
 983  * Used by setregs (exec) to clean out old user.
 984  * Used by sigcleanup to remove extraneous windows when returning from a
 985  * signal.
 986  */
 987 








 988         ENTRY_NP(trash_user_windows)
 989         rdpr    %otherwin, %g1
 990         brz     %g1, 3f                 ! no user windows?
 991         ldn     [THREAD_REG + T_STACK], %g5
 992 
 993         !
 994         ! There are old user windows in the register file. We disable ints
 995         ! and increment cansave so that we don't overflow on these windows.
 996         ! Also, this sets up a nice underflow when first returning to the
 997         ! new user.
 998         !
 999         rdpr    %pstate, %g2
1000         wrpr    %g2, PSTATE_IE, %pstate
1001         rdpr    %cansave, %g3
1002         rdpr    %otherwin, %g1          ! re-read in case of interrupt
1003         add     %g3, %g1, %g3
1004         wrpr    %g0, 0, %otherwin
1005         wrpr    %g0, %g3, %cansave
1006         wrpr    %g0, %g2, %pstate
1007 3:
1008         retl
1009         clr     [%g5 + MPCB_WBCNT]       ! zero window buffer cnt
1010         SET_SIZE(trash_user_windows)
1011 
1012 


1013 /*
1014  * Setup g7 via the CPU data structure.
1015  */

1016 






1017         ENTRY_NP(set_tbr)
1018         retl
1019         ta      72              ! no tbr, stop simulation
1020         SET_SIZE(set_tbr)
1021 

1022 

















1023 #define PTL1_SAVE_WINDOW(RP)                                            \
1024         stxa    %l0, [RP + RW64_LOCAL + (0 * RW64_LOCAL_INCR)] %asi;    \
1025         stxa    %l1, [RP + RW64_LOCAL + (1 * RW64_LOCAL_INCR)] %asi;    \
1026         stxa    %l2, [RP + RW64_LOCAL + (2 * RW64_LOCAL_INCR)] %asi;    \
1027         stxa    %l3, [RP + RW64_LOCAL + (3 * RW64_LOCAL_INCR)] %asi;    \
1028         stxa    %l4, [RP + RW64_LOCAL + (4 * RW64_LOCAL_INCR)] %asi;    \
1029         stxa    %l5, [RP + RW64_LOCAL + (5 * RW64_LOCAL_INCR)] %asi;    \
1030         stxa    %l6, [RP + RW64_LOCAL + (6 * RW64_LOCAL_INCR)] %asi;    \
1031         stxa    %l7, [RP + RW64_LOCAL + (7 * RW64_LOCAL_INCR)] %asi;    \
1032         stxa    %i0, [RP + RW64_IN + (0 * RW64_IN_INCR)] %asi;          \
1033         stxa    %i1, [RP + RW64_IN + (1 * RW64_IN_INCR)] %asi;          \
1034         stxa    %i2, [RP + RW64_IN + (2 * RW64_IN_INCR)] %asi;          \
1035         stxa    %i3, [RP + RW64_IN + (3 * RW64_IN_INCR)] %asi;          \
1036         stxa    %i4, [RP + RW64_IN + (4 * RW64_IN_INCR)] %asi;          \
1037         stxa    %i5, [RP + RW64_IN + (5 * RW64_IN_INCR)] %asi;          \
1038         stxa    %i6, [RP + RW64_IN + (6 * RW64_IN_INCR)] %asi;          \
1039         stxa    %i7, [RP + RW64_IN + (7 * RW64_IN_INCR)] %asi
1040 #define PTL1_NEXT_WINDOW(scr)   \
1041         add     scr, RWIN64SIZE, scr
1042 


1277         CPU_ADDR(%l0, %l1)                      ! %l0 = cpu[cpuid]
1278         add     %l0, CPU_PTL1, %l1              ! %l1 = &CPU->mcpu.ptl1_state
1279         !
1280         ! prepare to call panic()
1281         !
1282         ldn     [%l0 + CPU_THREAD], THREAD_REG  ! restore %g7
1283         ldn     [%l1 + PTL1_STKTOP], %l2        ! %sp = ptl1_stktop
1284         sub     %l2, SA(MINFRAME) + STACK_BIAS, %sp
1285         clr     %fp                             ! no frame below this window
1286         clr     %i7
1287         !
1288         ! enable limited interrupts
1289         !
1290         wrpr    %g0, CLOCK_LEVEL, %pil
1291         wrpr    %g0, PSTATE_KERN, %pstate
1292         !
1293         ba,pt   %xcc, ptl1_panic_handler
1294           mov   %l1, %o0
1295         /*NOTREACHED*/
1296         SET_SIZE(ptl1_panic)

1297 
1298 #ifdef  PTL1_PANIC_DEBUG
1299 
1300 /*
1301  * ptl1_recurse() calls itself a number of times to either set up a known
1302  * stack or to cause a kernel stack overflow. It decrements the arguments
1303  * on each recursion.
1304  * It's called by #ifdef PTL1_PANIC_DEBUG code in startup.c to set the
1305  * registers to a known state to facilitate debugging.
1306  */








1307         ENTRY_NP(ptl1_recurse)
1308         save    %sp, -SA(MINFRAME), %sp
1309 
1310         set     ptl1_recurse_call, %o7
1311         cmp     %o7, %i7                        ! if ptl1_recurse is called
1312         be,pt  %icc, 0f                         ! by itself, then skip
1313           nop                                   ! register initialization
1314 
1315         /* 
1316          * Initialize Out Registers to Known Values 
1317          */
1318         set     0x01000, %l0                    ! %i0 is the ...
1319                                                 ! recursion_depth_count
1320         sub     %i0, 1, %o0;
1321         sub     %i1, 1, %o1;
1322         add     %l0, %o0, %o2;
1323         add     %l0, %o2, %o3;
1324         add     %l0, %o3, %o4;
1325         add     %l0, %o4, %o5;
1326         ba,a    1f


1351 
1352         brz,pn %i1, ptl1_recurse_trap           ! if trpp_count == 0) {
1353           nop                                   !    trap to ptl1_panic
1354                                                 !                       
1355         brz,pn %i0, ptl1_recure_exit            ! if(depth_count == 0) {
1356           nop                                   !    skip recursive call
1357                                                 ! }
1358 ptl1_recurse_call:
1359         call    ptl1_recurse
1360           nop
1361 
1362 ptl1_recure_exit:
1363         ret
1364         restore
1365 
1366 ptl1_recurse_trap:
1367         ta      PTL1_DEBUG_TRAP;                ! Trap Always to ptl1_panic()
1368           nop                                   ! NOTREACHED 
1369         SET_SIZE(ptl1_recurse)
1370 










1371         /*
1372          * Asm function to handle a cross trap to call ptl1_panic()
1373          */
1374         ENTRY_NP(ptl1_panic_xt)
1375         ba      ptl1_panic
1376           mov   PTL1_BAD_DEBUG, %g1
1377         SET_SIZE(ptl1_panic_xt)
1378 


1379 #endif  /* PTL1_PANIC_DEBUG */
1380 
1381 #ifdef  TRAPTRACE

1382 







1383         ENTRY_NP(trace_ptr_panic)
1384         !
1385         ! freeze the trap trace to disable the assertions.  Otherwise,
1386         ! ptl1_panic is likely to be repeatedly called from there.
1387         ! %g2 and %g3 are used as scratch registers in ptl1_panic.
1388         !
1389         mov     1, %g3
1390         sethi   %hi(trap_freeze), %g2
1391         st      %g3, [%g2 + %lo(trap_freeze)]
1392         !
1393         ! %g1 contains the %pc address where an assertion was failed.
1394         ! save it in trap_freeze_pc for a debugging hint if there is
1395         ! no value saved in it.
1396         !
1397         set     trap_freeze_pc, %g2
1398         casn    [%g2], %g0, %g1
1399 
1400         ba      ptl1_panic
1401         mov     PTL1_BAD_TRACE_PTR, %g1
1402         SET_SIZE(trace_ptr_panic)
1403 

1404 #endif  /* TRAPTRACE */


1405 /*
1406  * set_kcontextreg() sets PCONTEXT to kctx
1407  * if PCONTEXT==kctx, do nothing
1408  * if N_pgsz0|N_pgsz1 differ, do demap all first
1409  */









1410         ENTRY_NP(set_kcontextreg)
1411         ! SET_KCONTEXTREG(reg0, reg1, reg2, reg3, reg4, label1, label2, label3)
1412         SET_KCONTEXTREG(%o0, %o1, %o2, %o3, %o4, l1, l2, l3)
1413         retl
1414         nop
1415         SET_SIZE(set_kcontextreg)
1416 



1417 /*
1418  * The interface for a 32-bit client program that takes over the TBA
1419  * calling the 64-bit romvec OBP.
1420  */
1421 









1422         ENTRY(client_handler)
1423         save    %sp, -SA64(MINFRAME64), %sp     ! 32 bit frame, 64 bit sized
1424         sethi   %hi(tba_taken_over), %l2
1425         ld      [%l2+%lo(tba_taken_over)], %l3
1426         brz     %l3, 1f                         ! is the tba_taken_over = 1 ?
1427         rdpr    %wstate, %l5                    ! save %wstate
1428         andn    %l5, WSTATE_MASK, %l6
1429         wrpr    %l6, WSTATE_KMIX, %wstate
1430 
1431         !
1432         ! switch to PCONTEXT=0
1433         !
1434 #ifndef _OPL
1435         mov     MMU_PCONTEXT, %o2
1436         ldxa    [%o2]ASI_DMMU, %o2
1437         srlx    %o2, CTXREG_NEXT_SHIFT, %o2
1438         brz,pt  %o2, 1f                         ! nucleus pgsz is 0, no problem
1439           nop
1440         rdpr    %pstate, %l4                    ! disable interrupts
1441         andn    %l4, PSTATE_IE, %o2


1470         ldx     [%o3 + %lo(kcontextreg)], %o3
1471         brz     %o3, 1f
1472           nop
1473         rdpr    %pstate, %l4                    ! disable interrupts
1474         andn    %l4, PSTATE_IE, %o2
1475         wrpr    %g0, %o2, %pstate
1476         mov     DEMAP_ALL_TYPE, %o2
1477         stxa    %g0, [%o2]ASI_DTLB_DEMAP
1478         stxa    %g0, [%o2]ASI_ITLB_DEMAP
1479         mov     MMU_PCONTEXT, %o2
1480         stxa    %o3, [%o2]ASI_DMMU
1481         membar  #Sync
1482         sethi   %hi(FLUSH_ADDR), %o2
1483         flush   %o2                             ! flush required by immu
1484         wrpr    %g0, %l4, %pstate               ! restore interrupt state
1485 #endif /* _OPL */
1486 
1487 1:      ret                                     ! Return result ...
1488         restore %o0, %g0, %o0                   ! delay; result in %o0
1489         SET_SIZE(client_handler)


1490