/* Setup the TSS descriptors and entries */
Ki386InitializeTss(Tss, Idt, Gdt);
在这个Ki386InitializeTss函数里就是进行初始化系统任务的工作,因此要分析这个函数的代码,才可以理解系统任务的工作。
#001 VOID
#002 FASTCALL
#003 Ki386InitializeTss(IN PKTSS Tss,
# 004 IN PKIDTENTRY Idt,
# 005 IN PKGDTENTRY Gdt)
#006 {
#007 PKGDTENTRY TssEntry, TaskGateEntry;
#008
#009 /* Initialize the boot TSS. */
#010 TssEntry = &Gdt[KGDT_TSS / sizeof(KGDTENTRY)];
#011 TssEntry->HighWord.Bits.Type = I386_TSS;
#012 TssEntry->HighWord.Bits.Pres = 1;
#013 TssEntry->HighWord.Bits.Dpl = 0;
这里初始化系统引导任务。第10行代码是根据前面设置的任务选择子来找到入口。
第11行到第13行代码设置引导任务段的属性。
#014 KiInitializeTSS2(Tss, TssEntry);
调用KiInitializeTSS2函数来进行任务段参数设置,并设置I/O位图和中断情况。
#015 KiInitializeTSS(Tss);
调用函数KiInitializeTSS设置I/O位置开始位置,设置中断标志,设置局部描述符和内核堆栈。
#016
#017 /* Load the task register */
#018 Ke386SetTr(KGDT_TSS);
加载内核任务到TR寄存器。
#019
#020 /* Setup the Task Gate for Double Fault Traps */
#021 TaskGateEntry = (PKGDTENTRY)&Idt[8];
#022 TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;
#023 TaskGateEntry->HighWord.Bits.Pres = 1;
#024 TaskGateEntry->HighWord.Bits.Dpl = 0;
#025 ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_DF_TSS;
这里设置中断描述符表里的双重故障处理任务。从INTEL的文档里可以看到它的双重故障的中断号是8,所以这里就是设置第8项的中断描述符。双重故障是怎么样产生的呢?这是INTEL的CPU进入中断处理函数后,紧跟着又发生了一次中断,这样的情况,就叫双重故障。在操作系统里,一般需要把这种情况检查出来,强制地停止这种应用程序的错误,或者恢复系统的资源。比如当调用缺页中断处理后,紧跟着又产生缺页中,这样就会产生双重故障。导致系统无限循环下去,就会死机了。在我新装的电脑里,设置主板与ATI的显示卡不对,就导致操作系统无限循环中断下去,然后系统就死机了。
#026
#027 /* Initialize the TSS used for handling double faults. */
#028 Tss = (PKTSS)KiDoubleFaultTSS;
#029 KiInitializeTSS(Tss);
#030 Tss->CR3 = __readcr3();
#031 Tss->Esp0 = PtrToUlong(KiDoubleFaultStack);
#032 Tss->Eip = PtrToUlong(KiTrap8);
这里双重故障的入口地址。
#033 Tss->Cs = KGDT_R0_CODE;
#034 Tss->Fs = KGDT_R0_PCR;
#035 Tss->Ss = Ke386GetSs();
#036 Tss->Es = KGDT_R3_DATA | RPL_MASK;
#037 Tss->Ds = KGDT_R3_DATA | RPL_MASK;
#038
#039 /* Setup the Double Trap TSS entry in the GDT */
#040 TssEntry = &Gdt[KGDT_DF_TSS / sizeof(KGDTENTRY)];
#041 TssEntry->HighWord.Bits.Type = I386_TSS;
#042 TssEntry->HighWord.Bits.Pres = 1;
#043 TssEntry->HighWord.Bits.Dpl = 0;
#044 TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
#045 TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
#046 TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
#047 TssEntry->LimitLow = KTSS_IO_MAPS;
上面设置双重故障的任务,并设置了GDT里的描述符。
#048
#049 /* Now setup the NMI Task Gate */
#050 TaskGateEntry = (PKGDTENTRY)&Idt[2];
#051 TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;
#052 TaskGateEntry->HighWord.Bits.Pres = 1;
#053 TaskGateEntry->HighWord.Bits.Dpl = 0;
#054 ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_NMI_TSS;
#055
#056 /* Initialize the actual TSS */
#057 Tss = (PKTSS)KiNMITSS;
#058 KiInitializeTSS(Tss);
#059 Tss->CR3 = __readcr3();
#060 Tss->Esp0 = PtrToUlong(KiDoubleFaultStack);
#061 Tss->Eip = PtrToUlong(KiTrap2);
#062 Tss->Cs = KGDT_R0_CODE;
#063 Tss->Fs = KGDT_R0_PCR;
#064 Tss->Ss = Ke386GetSs();
#065 Tss->Es = KGDT_R3_DATA | RPL_MASK;
#066 Tss->Ds = KGDT_R3_DATA | RPL_MASK;
#067
#068 /* And its associated TSS Entry */
#069 TssEntry = &Gdt[KGDT_NMI_TSS / sizeof(KGDTENTRY)];
#070 TssEntry->HighWord.Bits.Type = I386_TSS;
#071 TssEntry->HighWord.Bits.Pres = 1;
#072 TssEntry->HighWord.Bits.Dpl = 0;
#073 TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
#074 TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
#075 TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
#076 TssEntry->LimitLow = KTSS_IO_MAPS;
上面设置不可屏蔽的中断任务。
#077 }