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位的内核代码段,需要将一些代码放置后面执行,实现屏幕打印与时钟中断函数,不同的函数有功能号对应其实现

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
%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端口

  

posted on   lh03061238  阅读(326)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示