• 38 操作系统-中断处理与特权级转移


    参考

    https://blog.51cto.com/13475106/category6.html及狄泰软件相关课程

    中断处理与特权级转移

    在上节中出现可能出现的问题-8259A在中断特殊完全嵌套方式下(执行中断服务程序期间,可响应本级中断,在时钟中断会出现问题)同一个引脚的新中断是否可以打断旧中断的处理?
    可以从ICW4的设置中(从之前的介绍中得知ICW4的第四位为1时时完全嵌套的方式),但是在时钟中断时没有进行响应本级中断。
    问题展示



    假设:时钟中断请求周期为5MS,对应的中断服务程序执行时间为10MS,那么,中断服务程序是否会被新的时钟中断请求打断?从ICW4的设置来说,这个新的时钟中断会被响应,但是在实际的运行中没有进行响应。

    关于中断优先级

    1.中断优先级由8259A管理-高优先级中断请求优先送往处理器
    2.处理器决定是否响应中断请求-处理器没有中断优先级的概念
    3.在默认情况下-中断服务程序执行时,屏蔽外部中断请求(IF==0),中断服务程序返回后,重新响应外部中断(IF==1)
    验证--在对call EnableTimer处设置断对寄存器进行查看,然后对进入程序TimerHandlerFunc后进行断点设置,对IF寄存器进行查看

    当代操作系统的设计-两种形态用户态与内核态

    1.应用程序(DPL3)执行系统调用时会陷入内核状态(DPL0)-3特权级到0特权级
    2.自定义软中断用于系统调用(int 0x80)(从用户态到内核态)
    3.通过软中断陷入内核一最高特权级(DPL0)执行系统调用
    4.中断服务程序运行与内核态(DPL0)

    中断特权级转移过程(三个步骤)

    1.处理器通过中断向量找到对应的中断描述符
    2.特权级检查-软中断(目标代码DPL<=CPL)[低特权级到高特权级]&&(CPL<=中断描述符);外部中断:CPL>=目标代码段DPL
    3.加载目标代码段选择子到cs,加载偏移地址到ip


    上图为用户态代码段的压栈实现过程-寄存器变化

    中断服务程序返回

    1.iret使得处理器从内核态返回用户态
    2.返回时进行特权级检查-CPL<=目标代码DPL(高特权级>底特权级),对相关段寄存器轻质清零(指向高特权级数据的段寄存器)


    上图为中断结束时的栈恢复

    eflags标志寄存器

    eflags寄存器

    1.IF-系统标志位,决定是否响应外部中断(IF==0,响应外部中断,IF==0,屏蔽外部中断)
    2.IOPL-系统标志位,决定是否允许进行IO操作;CPL<=IOPL才能允许IO端口,当且仅当CPL==0时才能改变IOPL的值
    3.设置IOPL的方法


    在代码中进行设置并查看

     



    从上图可知进行设置之后,IOPL设置为3(在之前中为0)

    目标实验-使用软中断实现系统调用

    1.定义32位核心代码段(中断函数,系统函数)
    2.定义32位任务代码段和数据段(用户程序)
    3.通过软中断转移到内核态调用系统函数-低到高
    4.在任务代码段使用软中断实现函数功能


    .该实验需要注意的是
    1.将IOPL设置位3使得用户态和内核态均可访问IO端口
    2.特权级转移时会发生栈的变化(定义TSS结构,定义不同栈段)
    3.在用户态通过sti指令使得粗略去响应外部中断(必须用户态)

    首先需要定义一个32位的内核代码段,需要将一些代码放置后面执行,实现屏幕打印与时钟中断函数,不同的函数有功能号对应其实现

    代码如下:

    %include "inc.asm"
    
    org 0x9000
    
    jmp ENTRY_SEGMENT
    
    [section .gdt]
    ; GDT definition
    ;                                     段基址,           段界限,       段属性
    GDT_ENTRY       :     Descriptor        0,                0,           0
    CODE32_DESC     :     Descriptor        0,        Code32SegLen - 1,    DA_C + DA_32 + DA_DPL3
    VIDEO_DESC      :     Descriptor     0xB8000,         0x07FFF,         DA_DRWA + DA_32 + DA_DPL3
    DATA32_DESC     :     Descriptor        0,        Data32SegLen - 1,    DA_DRW + DA_32 + DA_DPL3
    STACK32U_DESC   :     Descriptor        0,         TopOfStack32U,      DA_DRW + DA_32 + DA_DPL3
    STACK32K_DESC   :     Descriptor        0,         TopOfStack32K,      DA_DRW + DA_32 + DA_DPL0
    TSS_DESC        :     Descriptor        0,            TSSLen - 1,      DA_386TSS + DA_DPL0
    KERNEL32_DESC   :     Descriptor        0,      Kernel32SegLen - 1,    DA_C + DA_32 + DA_DPL0
    ; GDT end
    
    GdtLen    equ   $ - GDT_ENTRY
    
    GdtPtr:
              dw   GdtLen - 1
              dd   0         
              
    ; GDT Selector
    
    Code32Selector   equ (0x0001 << 3) + SA_TIG + SA_RPL3
    VideoSelector    equ (0x0002 << 3) + SA_TIG + SA_RPL3
    Data32Selector   equ (0x0003 << 3) + SA_TIG + SA_RPL3
    Stack32USelector equ (0x0004 << 3) + SA_TIG + SA_RPL3
    Stack32KSelector equ (0x0005 << 3) + SA_TIG + SA_RPL0
    TSSSelector      equ (0x0006 << 3) + SA_TIG + SA_RPL0
    Kernel32Selector equ (0x0007 << 3) + SA_TIG + SA_RPL0
    ; end of [section .gdt]
    
    [section .idt]
    align 32
    [bits 32]
    IDT_ENTRY:
    ; IDT definition
    ;                        Selector,           Offset,       DCount,    Attribute
    %rep 32
                  Gate    Kernel32Selector,    DefaultHandler,   0,         DA_386IGate + DA_DPL3
    %endrep
    
    Int0x20   :   Gate    Kernel32Selector,    TimerHandler,     0,         DA_386IGate + DA_DPL3
    
    %rep 95
                  Gate    Kernel32Selector,    DefaultHandler,   0,         DA_386IGate + DA_DPL3
    %endrep
    
    Int0x80   :   Gate    Kernel32Selector,    Int0x80Handler,   0,         DA_386IGate + DA_DPL3
    
    %rep 127
                  Gate    Kernel32Selector,    DefaultHandler,   0,         DA_386IGate + DA_DPL3
    %endrep
    
    IdtLen    equ    $ - IDT_ENTRY
    
    IdtPtr:
              dw    IdtLen - 1
              dd    0
    
    ; end of [section .idt]
    
    TopOfStack16    equ 0x7c00
    
    [section .tss]
    [bits 32]
    TSS_SEGMENT:
        dd    0
        dd    TopOfStack32K       ; 0
        dd    Stack32KSelector    ;
        dd    0                   ; 1
        dd    0                   ;
        dd    0                   ; 2
        dd    0                   ;
        times 4 * 18 dd 0
        dw    0
        dw    $ - TSS_SEGMENT + 2
        db    0xFF
        
    TSSLen    equ   $ - TSS_SEGMENT
    
    [section .dat]
    [bits 32]
    DATA32_SEGMENT:
        DTOS               db  "D.T.OS!", 0
        DTOS_OFFSET        equ DTOS - $$
        INT_80H            db  "int 0x80", 0
        INT_80H_OFFSET     equ INT_80H - $$
    
    Data32SegLen equ $ - DATA32_SEGMENT
    
    [section .s16]
    [bits 16]
    ENTRY_SEGMENT:
        mov ax, cs
        mov ds, ax
        mov es, ax
        mov ss, ax
        mov sp, TopOfStack16
        
        ; initialize GDT for 32 bits code segment
        mov esi, CODE32_SEGMENT
        mov edi, CODE32_DESC
        
        call InitDescItem
        
        mov esi, DATA32_SEGMENT
        mov edi, DATA32_DESC
        
        call InitDescItem
        
        mov esi, STACK32U_SEGMENT
        mov edi, STACK32U_DESC
        
        call InitDescItem
        
        mov esi, STACK32K_SEGMENT
        mov edi, STACK32K_DESC
        
        call InitDescItem
        
        mov esi, TSS_SEGMENT
        mov edi, TSS_DESC
        
        call InitDescItem
        
        mov esi, KERNEL32_SEGMENT
        mov edi, KERNEL32_DESC
        
        call InitDescItem
        
        ; initialize GDT pointer struct
        mov eax, 0
        mov ax, ds
        shl eax, 4
        add eax, GDT_ENTRY
        mov dword [GdtPtr + 2], eax
        
        ; initialize IDT pointer struct
        mov eax, 0
        mov ax, ds
        shl eax, 4
        add eax, IDT_ENTRY
        mov dword [IdtPtr + 2], eax
    
        ; 1. load GDT
        lgdt [GdtPtr]
        
        ; 2. close interrupt
        ;    load IDT
        ;    set IOPL to 3
        cli 
        
        lidt [IdtPtr]
        
        pushf
        pop eax
        
        or eax, 0x3000
        
        push eax
        popf
        
        ; 3. open A20
        in al, 0x92
        or al, 00000010b
        out 0x92, al
        
        ; 4. enter protect mode
        mov eax, cr0
        or eax, 0x01
        mov cr0, eax
        
        ; 5. load TSS
        mov ax, TSSSelector
        ltr ax
        
        ; 6. jump to 32 bits code
        ; jmp dword Code32Selector : 0
        push Stack32USelector
        push TopOfStack32U
        push Code32Selector
        push 0
        retf
    
    
    ; esi    --> code segment label
    ; edi    --> descriptor label
    InitDescItem:
        push eax
    
        mov eax, 0
        mov ax, cs
        shl eax, 4
        add eax, esi
        mov word [edi + 2], ax
        shr eax, 16
        mov byte [edi + 4], al
        mov byte [edi + 7], ah
        
        pop eax
        
        ret
    
        
    [section .s32]
    [bits 32]
    CODE32_SEGMENT:   
        mov ax, VideoSelector
        mov gs, ax
        
        mov ax, Stack32USelector
        mov ss, ax
        
        mov eax, TopOfStack32U
        mov esp, eax
        
        mov ax, Data32Selector
        mov ds, ax
        
        
        mov ebp, DTOS_OFFSET
        mov dh, 12
        mov dl, 33
        
        call Printf
        
        call InitDevInt
        
        call EnableTimer
        
        jmp $
    
    ;
    ;
    InitDevInt:
        push ax
        
        mov ax, 0
        
        int 0x80
        
        sti
        
        pop ax
        ret
        
    ; ds:ebp    --> string address
    ; dx        --> dh : row, dl : col  
    Printf:
        push ax
        push bx
        
        mov ax, 1
        mov bx, 0x0C
        
        int 0x80
        
        pop bx
        pop ax
        ret
        
    ;
    ;
    EnableTimer:
        push ax
        
        mov ax, 2
        
        int 0x80
        
        pop ax
        ret
        
    Code32SegLen    equ    $ - CODE32_SEGMENT
    
    [section .knl]
    [bits 32]
    KERNEL32_SEGMENT:         
    ;
    ;
    DefaultHandlerFunc:
        iret
        
    DefaultHandler    equ    DefaultHandlerFunc - $$
        
    ;
    ;
    Int0x80HandlerFunc:
    ax0:
        cmp ax, 0
        jnz ax1
        call InitDevIntFunc
        iret
    ax1:
        cmp ax, 1
        jnz ax2
        call PrintString
        iret
    ax2:
        cmp ax, 2
        jnz ax3
        call EnableTimerFunc
        iret
    ax3:
        iret
        
    Int0x80Handler    equ    Int0x80HandlerFunc - $$
    
    ;
    ;
    TimerHandlerFunc:
        push ax
        push dx
        
        mov ax, [gs:((80 * 14 + 36) * 2)]
        
        cmp al, '9'
        je throtate
        inc al
        jmp thshow
    
    throtate:
        mov al, '0'
        
    thshow:
        mov [gs:((80 * 14 + 36) * 2)], ax
        
        mov dx, MASTER_OCW2_PORT
        call WriteEOI
        
        pop dx
        pop ax
        
        iret
        
    TimerHandler    equ    TimerHandlerFunc - $$
    
    ;
    ;
    Delay:
        %rep 5
        nop
        %endrep
        ret
        
    ;
    ;
    Init8259A:
        push ax
        
        ; master
        ; ICW1
        mov al, 00010001B
        out MASTER_ICW1_PORT, al
        
        call Delay
        
        ; ICW2
        mov al, 0x20
        out MASTER_ICW2_PORT, al
        
        call Delay
        
        ; ICW3
        mov al, 00000100B
        out MASTER_ICW3_PORT, al
        
        call Delay
        
        ; ICW4
        mov al, 00010001B
        out MASTER_ICW4_PORT, al
        
        call Delay
        
        ; slave
        ; ICW1
        mov al, 00010001B
        out SLAVE_ICW1_PORT, al
        
        call Delay
        
        ; ICW2
        mov al, 0x28
        out SLAVE_ICW2_PORT, al
        
        call Delay
        
        ; ICW3
        mov al, 00000010B
        out SLAVE_ICW3_PORT, al
        
        call Delay
        
        ; ICW4
        mov al, 00000001B
        out SLAVE_ICW4_PORT, al
        
        call Delay
        
        pop ax
        
        ret
        
    ; al --> IMR register value
    ; dx --> 8259A port
    WriteIMR:
        out dx, al
        call Delay
        ret
        
    ; dx --> 8259A
    ; return:
    ;     ax --> IMR register value
    ReadIMR:
        in ax, dx
        call Delay
        ret
    
    ;
    ; dx --> 8259A port
    WriteEOI:
        push ax
        
        mov al, 0x20
        out dx, al
        
        call Delay
        
        pop ax
        
        ret
    
    ;
    ;
    EnableTimerFunc:
        push ax
        push dx
        
        mov ah, 0x0C
        mov al, '0'
        mov [gs:((80 * 14 + 36) * 2)], ax
        
        mov dx, MASTER_IMR_PORT
        
        call ReadIMR
        
        and ax, 0xFE
        
        call WriteIMR
        
        pop dx
        pop ax
        
        ret
        
    ;
    ;
    InitDevIntFunc:
        push ax
        push dx
        
        call Init8259A
        
        mov ax, 0xFF
        mov dx, MASTER_IMR_PORT
        
        call WriteIMR
        
        mov ax, 0xFF
        mov dx, SLAVE_IMR_PORT
        
        call WriteIMR
        
        pop dx
        pop ax
        ret
    
    ; ds:ebp    --> string address
    ; bx        --> attribute
    ; dx        --> dh : row, dl : col
    PrintString:
        push ebp
        push eax
        push edi
        push cx
        push dx
        
    print:
        mov cl, [ds:ebp]
        cmp cl, 0
        je end
        mov eax, 80
        mul dh
        add al, dl
        shl eax, 1
        mov edi, eax
        mov ah, bl
        mov al, cl
        mov [gs:edi], ax
        inc ebp
        inc dl
        jmp print
    
    end:
        pop dx
        pop cx
        pop edi
        pop eax
        pop ebp
        
        ret
    
    Kernel32SegLen    equ    $ - KERNEL32_SEGMENT
    
    [section .gsu]
    [bits 32]
    STACK32U_SEGMENT:
        times 1024 * 4 db 0
        
    Stack32USegLen equ $ - STACK32U_SEGMENT
    TopOfStack32U  equ Stack32USegLen - 1
    
    [section .gsk]
    [bits 32]
    STACK32K_SEGMENT:
        times 1024 * 4 db 0
        
    Stack32KSegLen equ $ - STACK32K_SEGMENT
    TopOfStack32K  equ Stack32KSegLen - 1
    

    程序运行结果

    小结

    1.处理器执行中断服务程序期间不再响应新中断(IF==0)
    2.如果需要进行中断嵌套,使用sti设置IF标志位(IF==1)
    3.IOPL决定是否允许进行IO操作CPL<=IOPL才能访问IO端口

      

  • 相关阅读:
    力扣(LeetCode)验证回文串 个人题解(C++)
    力扣(LeetCode)平方数之和 个人题解
    Exclusive Access 2 UVA
    C语言中指针*p[N], (*P)[N]的区别
    2018年蓝桥杯国赛比赛心得
    2018acm/icpc西安邀请赛比赛心得
    [最小割]Cable TV Network UVA
    Tree Reconstruction UVA
    Twenty Questions UVA
    python中的enumerate 函数(编号的实现方式)
  • 原文地址:https://www.cnblogs.com/lh03061238/p/14580326.html
Copyright © 2020-2023  润新知