code:trap - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki
- 陷入处理函数
- 共传入 7 个参数,对应 中断处理的现场保护
2682
2683 /*
2684 * Called from l40.s or l45.s when a processor trap occurs.
2685 * The arguments are the words saved on the system stack
2686 * by the hardware and software during the trap processing.
2687 * Their order is dictated by the hardware and the details
2688 * of C’s calling sequence. They are peculiar in that
2689 * this call is not ’by value’ and changed user registers
2690 * get copied back on return.
2691 * dev is the kind of trap that occurred.
2692 */
2693 trap(dev, sp, r1, nps, r0, pc, ps)
2694 {
2695 register i, a;
2696 register struct sysent *callp;
2697
2698 savfp();
2699 if ((ps&UMODE) == UMODE)
2700 dev =| USER;
2701 u.u_ar0 = &r0;
- 若 陷入前为用户态,向dev追加USER标志
- UMODE 定义在 trap.c
2702 switch(dev) {
- 将 r0 指针 赋予 u.u_ar0
- 方便 使用u.u_ar0的寻址方法 寻址其他参数
2703
2704 /*
2705 * Trap not expected.
2706 * Usually a kernel mode bus error.
2707 * The numbers printed are used to
2708 * find the hardware PS/PC as follows.
2709 * (all numbers in octal 18 bits)
2710 * address_of_saved_ps =
2711 * (ka6*0100) + aps - 0140000;
2712 * address_of_saved_pc =
2713 * address_of_saved_ps - 2;
2714 */
2715 default:
2716 printf("ka6 = %o \n", *ka6);
2717 printf("aps = %o \n", &ps);
2718 printf("trap type %o \n", dev);
2719 panic("trap");
2720
2721 case 0+USER: /* bus error */
2722 i = SIGBUS;
2723 break;
2724
2725 /*
2726 * If illegal instructions are not
2727 * being caught and the offending instruction
2728 * is a SETD, the trap is ignored.
2729 * This is because C produces a SETD at
2730 * the beginning of every program which
2731 * will trap on CPUs without 11/45 FPU.
2732 */
2733 case 1+USER: /* illegal instruction */
2734 if(fuiword(pc-2)==SETD && u.u_signal[SIGINS]==0)
2735 goto out;
2736 i = SIGINS;
- 若 当前指令为 SETD,并且用户不捕捉SIGINS信号,则跳过陷入(原因:参看 2725 - 2732)
2737 break;
2738
2739 case 2+USER: /* bpt or trace */
2740 i = SIGTRC;
2741 break;
2742
2743 case 3+USER: /* iot */
2744 i = SIGIOT;
2745 break;
2746
2747 case 5+USER: /* emt */
2748 i = SIGEMT;
2749 break;
2750
2751 case 6+USER: /* sys call */
2752 u.u_error = 0;
2753 ps =& ~EBIT;
2754 callp = &sysent[fuiword(pc-2)&077];
- 清 错误状态/标志
- EBIT 定义在 trap.c
2755 if (callp == sysent) { /* indirect */
- callp ← 对应的系统调用入口
2756 a = fuiword(pc);
- 若 callp 为0#系统调用入口(间接系统调用) (sysent[0] == sysent),...
- 参看 系统调用#直接/间接系统调用
- 以下代码完成的工作
- 读入 送给系统调用处理函数 的参数
- 2759 - 2760 的说明
- 约定 间接系统调用 的编码形式为 01044XX (SYS 定义在 trap.c)
- 若 违反约定,则将系统调用号 置为 63(实际该系统调用不存在),将会抛出错误
2757 pc =+ 2;
2758 i = fuword(a);
2759 if ((i & ~077) != SYS)
2760 i = 077; /* illegal */
2761 callp = &sysent[i&077];
2762 for(i=0; i<callp-></callp->count; i++)
2763 u.u_arg[i] = fuword(a =+ 2);
2764 } else {
2765 for(i=0; i<callp-></callp->count; i++) {
2766 u.u_arg[i] = fuiword(pc);
2767 pc =+ 2;
2768 }
2769 }
2771 trap1(callp->call);
2772 if(u.u_intflg)
2773 u.u_error = EINTR;
2774 if(u.u_error < 100) {
- 此处构成 系统调用函数 的出错处理,详细参看trap1 2848 的说明
2775 if(u.u_error) {
2776 ps =| EBIT;
2777 r0 = u.u_error;
2778 }
2779 goto out;
2780 }
2774 - 27802781 i = SIGSYS;
2782 break;
2783
2784 /*
2785 * Since the floating exception is an
2786 * imprecise trap, a user generated
2787 * trap may actually come from kernel
2788 * mode. In this case, a signal is sent
2789 * to the current process to be picked
2790 * up later.
2791 */
2792 case 8: /* floating exception */
2793 psignal(u.u_procp, SIGFPT);
2794 return;
2795
2796 case 8+USER:
2797 i = SIGFPT;
2798 break;
2799
2800 /*
2801 * If the user SP is below the stack segment,
2802 * grow the stack automatically.
2803 * This relies on the ability of the hardware
2804 * to restart a half executed instruction.
2805 * On the 11/40 this is not the case and
2806 * the routine backup/l40.s may fail.
2807 * The classic example is on the instruction
2808 * cmp -(sp),-(sp)
2809 */
2810 case 9+USER: /* segmentation exception */
2811 a = sp;
2813 if(grow(a))
2814 goto out;
2815 i = SIGSEG;
2816 break;
2817 }
2819
2820 out:
2821 if(issig())
2822 psig();
2824 }
2825 /* ------------------------- */