C 使用任务状态段处理环0 int

C 使用任务状态段处理环0 int,c,exception-handling,x86,kernel,low-level,C,Exception Handling,X86,Kernel,Low Level,我已经在easy os内核上工作了一段时间。到目前为止,我已经用一个INT(软件)正确地设置了IDT。 下一步是尝试进入内核的第3环。这是dane,我使用了iret的“技巧”ring switch成功了,因为 段寄存器的状态指示。当我试图使用int$20切换到环0以处理此中断时出现问题。 当然,我已经设置了TSS,以便能够执行此类操作。下面是一些代码: 此函数对描述符进行编码(我将其包含在内,因为我认为这可能是编码的问题) TSS刷新(我的GDT有6个条目(NULL+TSS+4段)): 和中断处

我已经在easy os内核上工作了一段时间。到目前为止,我已经用一个INT(软件)正确地设置了IDT。 下一步是尝试进入内核的第3环。这是dane,我使用了
iret的“技巧”
ring switch成功了,因为 段寄存器的状态指示。当我试图使用
int$20
切换到环0以处理此中断时出现问题。 当然,我已经设置了TSS,以便能够执行此类操作。下面是一些代码: 此函数对描述符进行编码(我将其包含在内,因为我认为这可能是编码的问题)

TSS刷新(我的GDT有6个条目(NULL+TSS+4段)):

和中断处理程序寄存器:

    IDTEntry fillIDTEntry(uint32_t intHandler,
                          uint16_t selector,   
                          uint8_t type_attr)

    {   IDTEntry newEntry;
        newEntry.offset_low = LOW_FUN_ADDR(intHandler); 
        newEntry.selector = selector; 
        newEntry.zero = 0;     
        newEntry.type_attr = type_attr;
        newEntry.offset_up = UP_FUN_ADDR(intHandler);
        return newEntry;
    }

    extern void _lidt(_IDT_PTR* idtPtr);
    void loadIDT()
    {
        zeroIDT();
        _IDT_PTR idtPtr;
        idtPtr.idtSize = sizeof(struct __InteruptDescriptorTableEntry)*256 - 1;
        idtPtr.idtBaseAddr = (uint32_t) &InteruptDescriptorTable;

        IDTEntry printOnScreenInt = fillIDTEntry((uint32_t)interupt_pritnOnScreen, 0x18, 0x8e);
        registerInterupt(printOnScreenInt, 32);
        _lidt(&idtPtr);
    }

    .global _lidt
    _lidt:
        push %ebp
        mov %esp,%ebp

        mov 8(%esp), %eax
        lidt (%eax)
    leave
    ret
最后打印表格Bochs:

    [CPU0  ] interrupt(): soft_int && (gate.dpl < CPL)
    [CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
    [CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
    [CPU0  ] CPU is in protected mode (active)
    [CPU0  ] CS.mode = 32 bit
    [CPU0  ] SS.mode = 32 bit
    [CPU0  ] EFER   = 0x00000000
    [CPU0  ] | EAX=00100d48  EBX=001058b4  ECX=00000720  EDX=001058c2
    [CPU0  ] | ESP=0010589c  EBP=0010589c  ESI=00101000  EDI=00000000
    [CPU0  ] | IOPL=0 ID vip vif ac vm RF nt of df if tf sf zf af PF cf
    [CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
    [CPU0  ] |  CS:000b( 0001| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  DS:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  SS:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  ES:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  FS:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  GS:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] | EIP=001008ed (001008ed)
    [CPU0  ] | CR0=0x60000011 CR2=0x00000000
    [CPU0  ] | CR3=0x00000000 CR4=0x00000000
    [CPU0  ] 0x001008ed>> int 0x20 : CD20
[CPU0]中断():soft_int&&(gate.dpl>内部0x20:CD20

在引入两个特权级别之前,我只想提到这个中断处理程序正在工作。

IDT项的DPL需要大于或等于CPL,才能不出现异常。真的,就是这样吗?:)是的,我仍然对cpl/dpl/rpl机制有点困惑。现在我被困在传递参数以中断:)好的,进行编辑。我们来看看。
    .global flush_tss
    flush_tss:
        mov $0x28, %ax
        ltr %ax
    ret
    IDTEntry fillIDTEntry(uint32_t intHandler,
                          uint16_t selector,   
                          uint8_t type_attr)

    {   IDTEntry newEntry;
        newEntry.offset_low = LOW_FUN_ADDR(intHandler); 
        newEntry.selector = selector; 
        newEntry.zero = 0;     
        newEntry.type_attr = type_attr;
        newEntry.offset_up = UP_FUN_ADDR(intHandler);
        return newEntry;
    }

    extern void _lidt(_IDT_PTR* idtPtr);
    void loadIDT()
    {
        zeroIDT();
        _IDT_PTR idtPtr;
        idtPtr.idtSize = sizeof(struct __InteruptDescriptorTableEntry)*256 - 1;
        idtPtr.idtBaseAddr = (uint32_t) &InteruptDescriptorTable;

        IDTEntry printOnScreenInt = fillIDTEntry((uint32_t)interupt_pritnOnScreen, 0x18, 0x8e);
        registerInterupt(printOnScreenInt, 32);
        _lidt(&idtPtr);
    }

    .global _lidt
    _lidt:
        push %ebp
        mov %esp,%ebp

        mov 8(%esp), %eax
        lidt (%eax)
    leave
    ret
    [CPU0  ] interrupt(): soft_int && (gate.dpl < CPL)
    [CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
    [CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
    [CPU0  ] CPU is in protected mode (active)
    [CPU0  ] CS.mode = 32 bit
    [CPU0  ] SS.mode = 32 bit
    [CPU0  ] EFER   = 0x00000000
    [CPU0  ] | EAX=00100d48  EBX=001058b4  ECX=00000720  EDX=001058c2
    [CPU0  ] | ESP=0010589c  EBP=0010589c  ESI=00101000  EDI=00000000
    [CPU0  ] | IOPL=0 ID vip vif ac vm RF nt of df if tf sf zf af PF cf
    [CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
    [CPU0  ] |  CS:000b( 0001| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  DS:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  SS:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  ES:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  FS:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] |  GS:0013( 0002| 0|  3) 00000000 ffffffff 1 1
    [CPU0  ] | EIP=001008ed (001008ed)
    [CPU0  ] | CR0=0x60000011 CR2=0x00000000
    [CPU0  ] | CR3=0x00000000 CR4=0x00000000
    [CPU0  ] 0x001008ed>> int 0x20 : CD20