• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-80  評(píng)論-24  文章-0  trackbacks-0
            上一篇日志主要講解了對(duì)8259A以及中斷向量表的初始化。
            下面的程序主要是時(shí)鐘中斷、硬盤(pán)中斷以及系統(tǒng)調(diào)用入口函數(shù)的實(shí)現(xiàn)。

              1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
              2 ; 每個(gè)進(jìn)程的內(nèi)核態(tài)堆棧頂部棧幀應(yīng)該是這樣的
              3 ; ss
              4 ; esp
              5 ; eflags
              6 ; cs
              7 ; eip
              8 ; eax
              9 ; ecx
             10 ; edx
             11 ; ebx
             12 ; ebp
             13 ; esi
             14 ; edi
             15 ; ds
             16 ; es
             17 ; fs
             18 ; gs
             19 ; 其中ss、esp、eflags、cs、eip是在發(fā)生中斷時(shí)CPU自動(dòng)壓棧的
             20 ; 而其他的是由中斷程序壓棧的,這個(gè)順序不能改變,否則后果自負(fù)
             21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
             22 
             23 CS_OFFSET    equ 0x30
             24 ESP_OFFSET    equ 0x38
             25 SS_OFFSET    equ 0x3c
             26 
             27 ; 一個(gè)宏,因?yàn)樗械膇rq中斷函數(shù)都是先保存現(xiàn)場(chǎng)并將數(shù)據(jù)段等堆棧段
             28 ; 切換到內(nèi)核態(tài),因此,該操作所有的irq中斷入口函數(shù)均相同
             29 ; 故寫(xiě)成宏節(jié)省空間^_!
             30 %macro save_all 0
             31     push eax
             32     push ecx
             33     push edx
             34     push ebx
             35     push ebp
             36     push esi
             37     push edi
             38     push ds
             39     push es
             40     push fs
             41     push gs
             42     mov si, ss
             43     mov ds, si
             44     mov es, si
             45     mov gs, si
             46     mov fs, si
             47 %endmacro
             48 
             49 ; 一個(gè)宏,恢復(fù)現(xiàn)場(chǎng)
             50 %macro recover_all 0
             51     pop gs
             52     pop fs
             53     pop es
             54     pop ds
             55     pop edi
             56     pop esi
             57     pop ebp
             58     pop ebx
             59     pop edx
             60     pop ecx
             61     pop eax
             62 %endmacro
             63 
             64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
             65 ; 時(shí)鐘中斷處理程序
             66 ; 這是整個(gè)系統(tǒng)中最要求“速度快”的程序,因?yàn)闀r(shí)鐘中斷沒(méi)隔1/HZ(s)
             67 ; 就發(fā)生一次,大概它是整個(gè)系統(tǒng)調(diào)用最頻繁的函數(shù),所以需要該函數(shù)
             68 ; 盡量短,沒(méi)有必要的函數(shù)調(diào)用盡量避免。
             69 ; 另外判斷中斷重入minix和linux采取的方法也是不一樣的,minix采用
             70 ; 一個(gè)全局變量,類似于信號(hào)量的概念;而linux的方法則比較簡(jiǎn)單,它
             71 ; 直接獲取存儲(chǔ)在內(nèi)核堆棧中的cs段寄存器的RPL值來(lái)判斷被中斷的程序
             72 ; 是內(nèi)核態(tài)程序的還是用戶態(tài)的進(jìn)程;我們打算采用linux的辦法,雖然
             73 ; minix方法更酷,但是linux的顯然更加簡(jiǎn)單:)
             74 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
             75 int_clock:
             76     save_all
             77     ; 增加心跳數(shù)
             78     inc dword [boot_heartbeat]
             79 
             80     ; 發(fā)送EOI指令結(jié)束本次中斷
             81     mov ax, 0x20
             82     out 0x20, al
             83     sti
             84     
             85     mov eax, [esp + CS_OFFSET]
             86     and eax, 0x03
             87     cmp eax, 0x0 ; 如果CS段寄存器的RPL為0,則說(shuō)明是由內(nèi)核態(tài)進(jìn)入時(shí)鐘中斷,則是中斷重入
             88     je return
             89     call pre_schedule
             90 return:
             91     recover_all
             92     iretd
             93 
             94 int_keyboard:
             95     save_all
             96 
             97     recover_all
             98     iretd
             99 
            100 int_serial_port2:
            101     save_all
            102 
            103     recover_all
            104     iretd
            105 
            106 int_serial_port1:
            107     save_all
            108 
            109     recover_all
            110     iretd
            111 
            112 int_lpt2:
            113     save_all
            114 
            115     recover_all
            116     iretd
            117 
            118 int_floppy:
            119     save_all
            120 
            121     recover_all
            122     iretd
            123 
            124 int_lpt1:
            125     save_all
            126 
            127     recover_all
            128     iretd
            129 
            130 int_rtc:
            131     save_all
            132 
            133     recover_all
            134     iretd
            135 
            136 int_ps_2_mouse:
            137     save_all
            138 
            139     recover_all
            140     iretd
            141 
            142 int_fpu_fault:
            143     save_all
            144 
            145     recover_all
            146     iretd
            147 
            148 ;硬盤(pán)中斷處理程序
            149 int_at_win:
            150     save_all
            151 
            152     mov byte [gs:0xb8006], 'e'; 試驗(yàn)硬盤(pán)中斷是否成功:)
            153 
            154     ; 發(fā)送EOI指令給從8259A結(jié)束本次中斷
            155     mov ax, 0x20
            156     out 0xa0, al
            157     nop
            158     nop
            159     ; 發(fā)送EOI指令給主8259A結(jié)束本次中斷
            160     out 0x20, al
            161     nop
            162     nop
            163 
            164     ; 調(diào)用該函數(shù)使buf_info緩沖區(qū)生效
            165     call validate_buffer
            166 
            167     recover_all
            168     iretd
            169 
            170 ; 默認(rèn)的中斷處理函數(shù),所有的未定義中斷都會(huì)調(diào)用此函數(shù)
            171 int_default:
            172     save_all
            173     recover_all
            174     iretd
            175 
            176 ; 注意從系統(tǒng)調(diào)用返回時(shí)不需要從棧中彈出eax的值,因?yàn)閑ax保存著調(diào)用
            177 ; 對(duì)應(yīng)系統(tǒng)調(diào)用之后的返回值
            178 %macro recover_from_sys_call 0
            179     pop gs
            180     pop fs
            181     pop es
            182     pop ds
            183     pop edi
            184     pop esi
            185     pop ebp
            186     pop ebx
            187     pop edx
            188     pop ecx
            189     add esp, 4 * 1
            190 %endmacro
            191 
            192 ; 系統(tǒng)調(diào)用框架,系統(tǒng)調(diào)用采用0x30號(hào)中斷向量,利用int 0x30指令產(chǎn)
            193 ; 生一個(gè)軟中斷,之后便進(jìn)入sys_call函數(shù),該函數(shù)先調(diào)用save_all框
            194 ; 架保存所有寄存器值,然后調(diào)用對(duì)應(yīng)系統(tǒng)調(diào)用號(hào)的入口函數(shù)完成系統(tǒng)調(diào)用
            195 ; 注意!!!!!系統(tǒng)調(diào)用默認(rèn)有三個(gè)參數(shù),分別利用ebx、ecx、edx來(lái)
            196 ; 傳遞,其中eax保存系統(tǒng)調(diào)用號(hào)
            197 sys_call:
            198     save_all
            199 
            200     sti
            201 
            202     push ebx
            203     push ecx
            204     push edx
            205     call [sys_call_table + eax * 4]
            206     add esp, 4 * 3
            207 
            208     recover_from_sys_call
            209 
            210     cli
            211 
            212     iretd
            213 

            目前不打算對(duì)時(shí)鐘中斷處理函數(shù)、硬盤(pán)中斷處理函數(shù)以及系統(tǒng)調(diào)用入口框架做解釋,因?yàn)楹笮虿糠謱?huì)專門(mén)分章節(jié)進(jìn)行講解。這里只說(shuō)在發(fā)生類似時(shí)鐘中斷、硬盤(pán)中斷以及軟中斷int X的系統(tǒng)調(diào)用時(shí),CPU如何處理的。
            初始情況下假設(shè)CPU正在用戶態(tài)執(zhí)行某一個(gè)進(jìn)程a,此時(shí)的CS、DS、ES、FS、SS均指向用戶態(tài)進(jìn)程a的段基地址。
            當(dāng)時(shí)鐘中斷等中斷抑或int X的系統(tǒng)調(diào)用到來(lái)的時(shí)候,CPU會(huì)自動(dòng)從TSS中尋找用戶態(tài)進(jìn)程a預(yù)先保存的ring0下的SS0和ESP0,然后將SS和ESP寄存器值轉(zhuǎn)換成SS0和ESP0,即切換到核心態(tài)堆棧段(注意,每個(gè)進(jìn)程都可能會(huì)有一個(gè)自己獨(dú)立的ring0堆棧段,這樣可以更好的實(shí)現(xiàn)進(jìn)程切換時(shí)對(duì)內(nèi)核態(tài)的保護(hù),linux對(duì)此的做法是在創(chuàng)建一個(gè)進(jìn)程的時(shí)候在進(jìn)程頁(yè)的末尾申請(qǐng)一塊空間作為該進(jìn)程對(duì)應(yīng)的ring0堆棧段),然后將用戶態(tài)下的SS、ESP、EFLAGS、CS、EIP的值保存在新的SS0:ESP0堆棧段中。注意以上過(guò)程都是CPU自動(dòng)完成的,然后再通過(guò)save_all宏手工將eax、ecx、edx、ebx、ebp、esi、edi、ds、es、fs、gs壓入堆棧,然后再執(zhí)行相應(yīng)的中斷處理程序。完成之后會(huì)通過(guò)recover_all再按序恢復(fù)所有的常規(guī)寄存器。然后調(diào)用iretd命令從堆棧中彈出EIP、CS、EFLAGS、ESP、SS寄存器,然后再重新恢復(fù)進(jìn)程a的運(yùn)行。這一過(guò)程需要對(duì)GDT、IDT、TSS以及保護(hù)模式下的中斷門(mén)、陷阱門(mén)有所了解才可以。
            不過(guò)還有一種情況此處沒(méi)有涉及:當(dāng)發(fā)生進(jìn)程切換的時(shí)候現(xiàn)場(chǎng)保護(hù)與恢復(fù)的過(guò)程如何呢?這一過(guò)程將在后面敘述。

              1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
              2 ; 以下為庫(kù)函數(shù)
              3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
              4 
              5 ; 對(duì)端口進(jìn)行寫(xiě)操作
              6 void out_byte(unsigned short port, unsigned char value);
              7 out_byte:
              8     mov edx, [esp + 4 * 1]
              9     mov al, [esp + 4 * 2]
             10     out dx, al
             11     nop
             12     nop
             13     ret
             14 
             15 ; 對(duì)端口進(jìn)行讀操作
             16 ; uint8 in_byte(unsigned short port);
             17 in_byte:
             18     mov edx, [esp + 4 * 1]
             19     xor eax, eax
             20     in al, dx
             21     nop
             22     nop
             23     ret
             24 
             25 ; 對(duì)從指定端口進(jìn)行讀操作,讀出的n個(gè)字節(jié)數(shù)據(jù)放入buf緩沖區(qū)中
             26 void read_port(uint16 port, void* buf, int n);
             27 read_port:
             28     mov    edx, [esp + 4 * 1]    ; port
             29     mov    edi, [esp + 4 * 2]    ; buf
             30     mov    ecx, [esp + 4 * 3]    ; n
             31     shr    ecx, 1
             32     cld
             33     rep    insw
             34     ret
             35 
             36 ; 對(duì)從指定端口進(jìn)行寫(xiě)操作,數(shù)據(jù)源在buf緩沖區(qū)中,寫(xiě)n個(gè)字節(jié)
             37 void write_port(uint16 port, void* buf, int n);
             38 write_port:
             39     mov    edx, [esp + 4 * 1]    ; port
             40     mov    edi, [esp + 4 * 2]    ; buf
             41     mov    ecx, [esp + 4 * 3]    ; n
             42     shr    ecx, 1
             43     cld
             44     rep    outsw
             45     ret
             46 
             47 ; 安裝指定中斷號(hào)的中斷處理程序
             48 extern int install_int_handler(uint8 INT_IV, void* handler);
             49 install_int_handler:
             50     mov eax, [esp + 4 * 1] ; 中斷向量號(hào)
             51     mov ebx, [esp + 4 * 2] ; 中斷程序入口
             52     cmp eax, 256
             53     jae failed
             54     cmp eax, 0
             55     jbe failed
             56     push PRIVILEGE_KERNEL
             57     push ebx
             58     push INT_GATE_386
             59     push eax
             60     call init_idt
             61     add esp, 4 * 4
             62 failed:
             63     ret
             64     
             65 ; 卸載指定中斷號(hào)的中斷處理程序
             66 extern int uninstall_int_handler(uint8 INT_IV);
             67 uninstall_int_handler:
             68     mov eax, [esp + 4 * 1] ; 中斷向量號(hào)
             69     cmp eax, 256
             70     jae failed
             71     cmp eax, 0
             72     jbe failed
             73     push PRIVILEGE_KERNEL
             74     push int_default
             75     push INT_GATE_386
             76     push eax
             77     call init_idt
             78     add esp, 4 * 4
             79     ret
             80     
             81 ; 安裝指定中斷號(hào)的系統(tǒng)調(diào)用入口
             82 extern int install_sys_call_handler(uint8 INT_IV, void* handler);
             83 install_sys_call_handler:
             84     mov eax, [esp + 4 * 1] ; 中斷向量號(hào)
             85     mov ebx, [esp + 4 * 2] ; 中斷程序入口
             86     cmp eax, 256
             87     jae failed_inst_sys
             88     cmp eax, 0
             89     jbe failed_inst_sys
             90     push PRIVILEGE_USER
             91     push ebx
             92     push INT_TRAP_386
             93     push eax
             94     call init_idt
             95     add esp, 4 * 4
             96 failed_inst_sys:
             97     ret
             98 
             99 ; 打開(kāi)對(duì)應(yīng)向量號(hào)的硬件中斷
            100 ; 注意,這里傳入的參數(shù)是硬件中斷對(duì)應(yīng)的中斷向量號(hào)
            101 ; 需要將該中斷向量號(hào)轉(zhuǎn)化為在8259A上的索引號(hào)
            102 void enable_hwint(uint8 IV);
            103 enable_hwint:
            104     mov ecx, [esp + 4 * 1]
            105     cmp cl, IRQ0_IV
            106     jae master_1
            107     jmp ret_1
            108 master_1:
            109     cmp cl, IRQ8_IV
            110     jae slave_1
            111     push MASTER_CTL_MASK_8259
            112     call in_byte
            113     add esp, 4 * 1
            114     sub cl, IRQ0_IV
            115     mov bl, 1
            116     shl bl, cl
            117     xor bl, 0xff
            118     and al, bl
            119     push eax
            120     push MASTER_CTL_MASK_8259
            121     call out_byte
            122     add esp, 4 * 2
            123     jmp ret_1
            124 slave_1:
            125     cmp cl, IRQ15_IV
            126     ja ret_1
            127     push SLAVE_CTL_MASK_8259
            128     call in_byte
            129     add esp, 4 * 1
            130     sub cl, IRQ8_IV
            131     mov bl, 1
            132     shl bl, cl
            133     xor bl, 0xff
            134     and al, bl
            135     push eax
            136     push SLAVE_CTL_MASK_8259
            137     call out_byte
            138     add esp, 4 * 2
            139 ret_1:
            140     ret
            141 
            142 ; 關(guān)閉對(duì)應(yīng)向量號(hào)的硬件中斷
            143 ; 注意,這里傳入的參數(shù)是硬件中斷對(duì)應(yīng)的中斷向量號(hào)
            144 ; 需要將該中斷向量號(hào)轉(zhuǎn)化為在8259A上的索引號(hào)
            145 void disable_hwint(uint8 IV);
            146 disable_hwint:
            147     mov ecx, [esp + 4 * 1]
            148     cmp cl, IRQ0_IV
            149     jae master_2
            150     jmp ret_2
            151 master_2:
            152     cmp cl, IRQ8_IV
            153     jae slave_2
            154     push MASTER_CTL_MASK_8259
            155     call in_byte
            156     add esp, 4 * 1
            157     sub cl, IRQ0_IV
            158     mov bl, 1
            159     shl bl, cl
            160     or al, bl
            161     push eax
            162     push MASTER_CTL_MASK_8259
            163     call out_byte
            164     add esp, 4 * 2
            165     jmp ret_2
            166 slave_2:
            167     cmp cl, IRQ15_IV
            168     ja ret_2
            169     push SLAVE_CTL_MASK_8259
            170     call in_byte
            171     add esp, 4 * 1
            172     sub cl, IRQ8_IV
            173     mov bl, 1
            174     shl bl, cl
            175     or al, bl
            176     push eax
            177     push SLAVE_CTL_MASK_8259
            178     call out_byte
            179     add esp, 4 * 2
            180 ret_2:
            181     ret
            182 
            183 [SECTION .data]
            184 idt:
            185         ; idt表共可存放256個(gè)中斷門(mén)描述符
            186         times 256 * 8 db 0
            187 
            188 idtr:    dw $ - idt - 1
            189         dd idt
            190 

            上面這段函數(shù)比較簡(jiǎn)單,是一些庫(kù)函數(shù),主要包括對(duì)端口進(jìn)行讀、寫(xiě)操作;以及安裝或者卸載中斷處理程序,方法就是通過(guò)接受中斷號(hào),將IDT中對(duì)應(yīng)的中斷描述符置空或初始化;還有安裝系統(tǒng)調(diào)用,安裝系統(tǒng)調(diào)用和安裝中斷處理程序幾乎相同,唯一的區(qū)別就是門(mén)描述符的類型以及門(mén)描述符的特權(quán)級(jí)不同,中斷處理程序是中斷門(mén),對(duì)應(yīng)的門(mén)描述符DPL為0,系統(tǒng)調(diào)用是陷阱門(mén),對(duì)應(yīng)的DPL為3,這是因?yàn)橹袛嚅T(mén)只需要檢查CPL>=處理程序的DPL,而陷阱門(mén)除了檢查該條件以外還檢查CPL<=陷阱門(mén)描述符的DPL。這樣做的原因是陷阱門(mén)是由程序引起的,諸如系統(tǒng)調(diào)用之類的,需要從程序中跳入;而中斷是硬件引起的。
            再后面函數(shù)就是打開(kāi)或關(guān)閉8259A上的硬件中斷。

            關(guān)于init.s文件的描述就到此為止。之后還會(huì)對(duì)進(jìn)程切換做進(jìn)一步的闡釋。
            posted on 2012-02-14 01:06 myjfm 閱讀(535) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 操作系統(tǒng)
            国产精品美女久久福利网站| 亚洲综合日韩久久成人AV| 亚洲天堂久久精品| 久久久久无码中| 一本一本久久aa综合精品| Xx性欧美肥妇精品久久久久久| 伊人久久成人成综合网222| 久久婷婷国产综合精品| 久久精品夜色噜噜亚洲A∨| 亚洲香蕉网久久综合影视| 99久久精品国产综合一区| 久久福利资源国产精品999| 精品亚洲综合久久中文字幕| 亚洲天堂久久久| 久久精品亚洲精品国产欧美| 麻豆成人久久精品二区三区免费| 久久精品成人免费观看97| 国产精品美女久久久久| 亚洲精品无码久久久久| 一级女性全黄久久生活片免费 | 国产成人久久久精品二区三区| 一本色道久久综合| 久久久久久毛片免费看| 亚洲综合婷婷久久| 久久精品国产影库免费看| 久久久噜噜噜久久熟女AA片| 精品久久久久久久久免费影院| 青青国产成人久久91网| 久久综合精品国产二区无码| 99久久无色码中文字幕人妻| 亚洲欧洲精品成人久久曰影片| 国产福利电影一区二区三区,免费久久久久久久精 | 国产精品无码久久综合| 国内精品九九久久精品| 久久成人小视频| 久久婷婷五月综合国产尤物app| 久久精品综合网| 国产精品禁18久久久夂久| 久久无码av三级| 国产精品美女久久久网AV| 久久精品成人欧美大片|