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

中断处理与特权级转移

在上节中出现可能出现的问题-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

程序运行结果

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

扫描二维码关注公众号,回复: 11840900 查看本文章

小结

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

猜你喜欢

转载自blog.51cto.com/13475106/2537020