• <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)
            久久强奷乱码老熟女网站| 色欲综合久久中文字幕网| 国产精品欧美久久久天天影视 | 精品久久久无码21p发布| 久久毛片免费看一区二区三区| 久久福利青草精品资源站| 国产91久久精品一区二区| 久久久久免费看成人影片| 久久国产精品99精品国产| 久久国产精品-久久精品| 麻豆精品久久精品色综合| 久久se精品一区精品二区国产| 久久精品亚洲精品国产欧美| 欧美精品一区二区久久| 精品综合久久久久久98| 久久99亚洲网美利坚合众国| 久久精品一区二区三区不卡| 国产精品女同一区二区久久| 亚洲国产成人精品91久久久 | 伊人久久大香线蕉精品不卡| 7777精品伊人久久久大香线蕉| 久久亚洲AV成人无码软件| 久久影院综合精品| 久久国产精品视频| av色综合久久天堂av色综合在| 婷婷久久综合九色综合98| 久久综合一区二区无码| 久久中文骚妇内射| 手机看片久久高清国产日韩| 日韩精品久久久肉伦网站| 国产精久久一区二区三区| 99精品国产免费久久久久久下载 | 久久精品中文字幕一区| 国产成人精品久久免费动漫| 少妇被又大又粗又爽毛片久久黑人 | 东方aⅴ免费观看久久av| 99久久久久| 国产精品久久久久国产A级| 欧美成a人片免费看久久| 97久久香蕉国产线看观看| 久久久午夜精品|