reactos操作系统实现(14)

下面来分析一下系统任务是怎么样初始化的,先来看这行代码:

/* 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项的中断描述符。双重故障是怎么样产生的呢?这是INTELCPU进入中断处理函数后,紧跟着又发生了一次中断,这样的情况,就叫双重故障。在操作系统里,一般需要把这种情况检查出来,强制地停止这种应用程序的错误,或者恢复系统的资源。比如当调用缺页中断处理后,紧跟着又产生缺页中,这样就会产生双重故障。导致系统无限循环下去,就会死机了。在我新装的电脑里,设置主板与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  }

你可能感兴趣的:(react)