The third step: initial establishment of interrupt exception handling mechanism

Source: Internet
Author: User
Tags error code exception handling reserved

To set up the interrupt exception handling mechanism is to initialize the 8259A and set up the Interrupt descriptor table. The amount of code is huge because of the processing of 10 or so defined exceptions, plus the processing of 16 external interrupts.

Because a time can not think of a better solution, so the copy of the "self-write operating system" in the set of methods used first ...

The specific initialization process is:

Kernel-Init_prot ()

In the Init_prot () call init_8259a (), the 8259A is initialized, the same as the previous code, just replaced by the C form.

After calling init_8259a (), the repeating Init_idt_desc () function initializes the IDE table, the first 10 are exception handling, the last 16 are external interrupt processing, and finally the custom interrupt

It is important to note that a function table is established for the external interrupt handler so that the final processing function of the interrupt can be modified after a flexible setting.

Once the interrupt exception handling mechanism is established (albeit the simplest), it can be easily tested.

In the main function of KERNEL.C, uncomment the following three exception test items separately, and you can see that the exception information is displayed on the screen.

Test exception
int 3//Test Debug Breakpoint exception
JMP 0x40:0//Testing General Protection Error exceptions
UD2//test Invalid opcode exception

Tests for external interrupts:

Test external interrupts
ENABLE_IRQ (KEYBOARD_IRQ); Open Keyboard Interrupt
ENABLE_IRQ (CLOCK_IRQ); Open Clock Interrupt

Note: Because a lot of code was added at once, beyond the initial setting to load 4 sector size kernel-to-memory limits in boot.c, you need to increase the number of sectors loaded ...

CODE:KERNEL.C (change)

 //file: kernel.c//function: Kernel program, currently functions for testing several output functions in the PRINT.C//run: Run.exe automatically compiles boot.c with the build IMG and calls Bochs to run the program. Author: Miao//Time: 2010-5-17 #define YCBIT 32//Tell the compiler to compile the program in 32-bit format #define ycorg 0x0//This value will generate address base offset for variable functions such as at compile time, simple, set to 0 # Include "Global.h" #include "kernel.h" #include "print.h" #include "klib.h" #include "i8259.h" void init (); Kernel entry point ASM void Main () {LGDT cs:gdtptr//Load new GDTR mov eax, selectorvideo mov gs, AX//Video Segment Selector (purpose) mov eax, SelectorData32 Make 32-bit code snippet variable (printplace) can read and write MOV ds, ax call init//Initialize function//test exception//int 3//Test Debug Breakpoint Exception//jmp 0x40:0//test General Protection Error Exception//UD2//test None Effective opcode exception STI//Open interrupt jmp kernel_main} void init () {disp_str ("================ init start =================/n"); Disp_str ("I NIT IDT--------------------------------"); Init_prot (); Initialize IDT disp_str ("ok/n"); Disp_str ("================ init end ===================/n"); } int Kernel_main () {//Test external Interrupt//enable_irq (KEYBOARD_IRQ);//Open keyboard interrupt//enable_irq (CLOCK_IRQ);//Open Clock Interrupt while (1); return 0;} #include "print.c" #include "KLIB.C" #include "I8259.c"

Code:klib.h (New)

File: Klib.h//function: Klib header file, declaration of public function required by the kernel, etc.//Author: Miao//Time: 2010-5-16//write data to the specified port asm void Out_byte (T_port port, t_8 value); Reads data from the specified port ASM t_8 in_byte (t_port port);

CODE:KLIB.C (New)

File: KLIB.C//function: Define common functions required by the kernel//Author: Miao//Time: 2010-5-16//write data to the specified port asm void Out_byte (T_port port, T_8 value) {mov edx, [ ESP + 4]//port mov al, [esp + 4 + 4]//value out DX, Al NOP//one point delay NOP ret}//Read data from the specified port ASM t_8 in_byte (t_port port) {m OV edx, [ESP + 4]//port xor eax, eax in al, DX NOP//One point delay NOP ret}

Code:i8259.h (New)

File: I8259.h//function: i8259 header file, placing initialization 8259A, and setting the required macros for interrupt, data structure definition, global variables and function declaration etc.//Author: Miao//Time: 2010-5-16//8259a interrupt Control Port # Define INT_M_CTL 0x20//Primary: Interrupt Controller input/output port #define INT_M_CTLMASK 0x21//Primary: Disables the specified interrupt number through this port #define INT_S_CTL 0xA0//From: Secondary interrupt controller input and output Port #define Int_s_ctlmask 0XA1//From: Disables the specified interrupt number//interrupt (Exception) vector number from 0 to 255 in 256, preceded by 0~13 defined, 20~31intel reserved unused, 32~255 user custom # Define Int_vector_divide 0x0//Division error #define INT_VECTOR_DEBUG 0x1/debug Exception #define INT_VECTOR_NMI 0x2//unshielded interrupt #define Int_vect Or_breakpoint 0x3//debug Breakpoint #define Int_vector_overflow 0x4//Overflow #define INT_VECTOR_BOUNDS 0x5//cross-border #define Int_vector_inval_ OP 0x6//Invalid opcode #define Int_vector_coproc_not 0x7//device unavailable #define INT_VECTOR_DOUBLE_FAULT 0x8//Double error #define INT_VECTOR_COP Roc_seg 0x9//coprocessor segment out of bounds #define INT_VECTOR_INVAL_TSS 0xA//Invalid TSS #define Int_vector_seg_not 0xB//segment does not exist #define Int_vector_st Ack_fault 0xC//Stack segment error #define Int_vector_protection 0xD//General Protection Error #define INT_VECTOR_PAGE_FAULT 0xE//Page Error//0xF//intel reserved #define INT_VECTOR_COPROC_ERR 0x10//floating-point error//0x14~0x1f//intel reserved unused//0x20~0x2f as 16 external interrupts for 8259A #define INT_VECTOR_IRQ0 0x20//Master: 0x20~0x27 #define Int_vector_irq8 0x28//From: 0x28~0x2f//0X30~0XFF//temporarily not with//hardware interrupt vector (used when opening or disabling an external interrupt) #define CLOCK_IRQ 0 #define KEYBOARD_IRQ 1//386 Interrupt Type value #de Fine da_386igate 0x8E//Interrupt (Exception) has permissions #define PRIVILEGE_KRNL 0 #define PRIVILEGE_USER 3//8259a, main 8, 8, total 16 hardware interrupts #define NR_IRQ typedef void (*t_pf_irq_handler) (int IRQ); Defines the interrupt Request handler function type typedef void (*t_pf_int_handler) (); Define the hardware interrupt handler type//Create a function pointer table for 16 hardware interrupts, and call the corresponding handler function when each hardware interrupt occurs t_pf_irq_handler IRQ_TABLE[NR_IRQ]; Gate descriptor struct Gate {t_16 offset_low;//offset low t_16 selector;//selector t_8 DCount;//The field is valid only in the calling door descriptor. If you invoke a subroutine with a call gate to cause a privilege-level conversion and a stack change,//You need to copy the parameters from the outer stack to the inner stack. The double-digit field is the number of double-character parameters to be copied when this happens. T_8 attr; P (1) DPL (2) DT (1) TYPE (4) t_16 Offset_high;//offset High}; #define IDT_SIZE GATE idt[idt_size];//Interrupt descriptor, up to 256 can be defined, currently apply for 64 T_8 idt_ptr[6]; Total 6 bytes 0~15:limit,16~47:base Displays the corresponding exception error message when used as a parameter//exception for Sidt and Lidt. Char err_description[][64] = {"#DE Divide Error", "#DB RESERVED", "-nmi Interrupt", "#BP Breakpoint", "#OF Overflow", "#BR BOUND Range exceeded", "#UD Invalid Opcode (Undefined Opcode)", "#NM Device not Available (No Math coprocessor)", "#DF Double Fault", "coprocess or Segment overrun (reserved), "#TS Invalid TSS", "#NP Segment not Present", "#SS stack-segment Fault", "#GP General Prot Ection "," #PF page Fault ","-(Intel reserved. Do no use.) "," #MF x87 FPU floating-point Error (Math Fault), "#AC Alignment check", "#MC Machine Check", "#XF SIMD Floa Ting-point Exception "}; void Init_prot (); Initializes the IDT function asm void Disable_irq (int IRQ); Turn off the specific interrupt asm void Enable_irq (int IRQ); Open a specific interrupt void Put_irq_handler (int IRQ, T_pf_irq_handler handler);//Register the handler function with a specific interrupt

CODE:I8259.C (New)

SPURIOUS_IRQ: "); Disp_int (IRQ); DISP_STR ("/n"); } void init_8259a () {out_byte (int_m_ctl, 0x11);//Master 8259, ICW1 out_byte (Int_s_ctl, 0x11);//from 8259, ICW1 out_byte (int_m _ctlmask, int_vector_irq0); Main 8259,ICW2. Set the interrupt entry address for ' main 8259 ' to 0x20 out_byte (Int_s_ctlmask, Int_vector_irq8); From 8259,ICW2. Set the interrupt entry address for ' from 8259 ' to 0x28 out_byte (Int_m_ctlmask, 0x4); Lord 8259, ICW3. IR2 corresponds to ' from 8259 ' Out_byte (Int_s_ctlmask, 0x2); From 8259, ICW3. Corresponds to ' main 8259 ' of the IR2 out_byte (Int_m_ctlmask, 0x1); Main 8259, ICW4 out_byte (Int_s_ctlmask, 0x1); From 8259, ICW4//The default starts by masking all external interrupt out_byte (Int_m_ctlmask, 0xFF); Main 8259, OCW1 out_byte (Int_s_ctlmask, 0xFF); From 8259, OCW1 int i; for (i=0;i<nr_irq;i++) irq_table[i] = SPURIOUS_IRQ; Initialize a default calling function for 16 hardware interrupt handler function pointer table}//Initialize 386 break gate void Init_idt_desc (unsigned char vector, t_8 desc_type, T_pf_int_handler Handler, unsigned char privilege) {GATE *p_gate = &idt[vecTor]; T_32 base = (t_32) handler; P_gate->offset_low = base & 0xFFFF; P_gate->selector = SelectorCode32; P_gate->dcount = 0; p_gate->attr = Desc_type | (Privilege << 5); P_gate->offset_high = (base >>) & 0xFFFF; }//exception handler, display error message void Exception_handler (int vec_no, int err_code, int EIP, int cs, int eflags) {int i; int text_color = 0xA0; Disp_pos = 0; Displays the error message starting from shelf disp_color_str ("exception! --", text_color); Disp_color_str (Err_description[vec_no], text_color); Disp_color_str ("/neflags:", Text_color); Disp_int (EFlags); Disp_color_str ("CS:", Text_color); Disp_int (CS); Disp_color_str ("EIP:", Text_color); Disp_int (EIP); if (err_code! = 0xFFFFFFFF) {disp_color_str ("Error Code:", Text_color); Disp_int (Err_code); }} ASM void exception () {Call Exception_handler//Display error message Add ESP, 4*2//Let the top of the stack point to the EIP, from top to bottom in the stack: EIP, CS, EFlags hlt}//Interrupts and exceptions --Exception, setting error code and interrupt number ASM void Divide_error () {Push 0xFFFFFFFF//No error code push 0//vector_no = 0 jmp exception} ASM voidSingle_step_exception () {Push 0xFFFFFFFF//No error code push 1//vector_no = 1 jmp exception} ASM void Nmi () {Push 0xFFFFFFFF No error code push 2//vector_no = 2 jmp exception} ASM void Breakpoint_exception () {Push 0xFFFFFFFF//No error code push 3//vecto R_no = 3 JMP exception} ASM void overflow () {Push 0xFFFFFFFF//No error code push 4//vector_no = 4 JMP exception} asm void Bo Unds_check () {Push 0xFFFFFFFF//No error code push 5//vector_no = 5 JMP exception} ASM void Inval_opcode () {Push 0xFFFFFFFF/ /No error code push 6//vector_no = 6 JMP exception} ASM void Copr_not_available () {Push 0xFFFFFFFF//No error code push 7//vector_no = 7 JMP Exception} ASM void Double_fault () {Push 8//vector_no = 8 JMP exception} ASM void Copr_seg_overrun () {Push 0 XFFFFFFFF//No error code push 9//vector_no = 9 jmp exception} ASM void Inval_tss () {Push//vector_no = a JMP exception} a SM void Segment_not_present () {push one//vector_no = B jmp exception} asm void Stack_exception () {push]//vector_no = C JMP Exception} ASM VOID General_protection () {Push//vector_no = D jmp exception} asm void Page_fault () {Push//vector_no = E jmp exc Eption} asm void Copr_error () {Push 0xFFFFFFFF//No error code push//VECTOR_NO = 10h jmp Exception} #define EOI 0x20//interrupts and Exception--Hardware interrupt #define HWINT_MASTER (IRQ_NO)/in AL, Int_m_ctlmask/*┓*//or Al, (1 << irq_no)/*┣ Shield Current Interrupt */out I Nt_m_ctlmask, Al/*┛*//mov al, EOI/*┓ EOI bit */out Int_m_ctl, al/*┛*//STI/* CPU will automatically turn off interrupts during response to interrupts, this sentence will allow response to new interrupts * //Push Irq_no/*┓*//Call DWORD [&irq_table + 4 * irq_no]/*┣ Interrupt Handler *//pop ecx/*┛*//cli/in al, Int_m_c Tlmask/*┓*//And Al, ~ (1 << irq_no)/*┣ Resume Accept current Interrupt */out Int_m_ctlmask, al/*┛*//iretd/ret/#pragma ali GN (0) ASM void hwint00 ()//interrupt routine for IRQ (the clock). {hwint_master (0)} #pragma align (+) ASM void hwint01 ()//interrupt routine for IRQ 1 (keyboard) {Hwint_master (1)} #pra GMA Align (+) ASM void hwint02 ()//interrupt routine for IRQ 2 (cascade!) {hWint_master (2)} #pragma align (+) ASM void hwint03 ()//interrupt routine for IRQ 3 (second serial) {Hwint_master (3)} #p Ragma align (+) ASM void hwint04 ()//interrupt routine for IRQ 4 (first serial) {Hwint_master (4)} #pragma align (+) ASM void hwint05 ()//interrupt routine for IRQ 5 (XT Winchester) {Hwint_master (5)} #pragma align (+) ASM void hwint06 ()//in Terrupt routine for IRQ 6 (floppy) {Hwint_master (6)} #pragma align (+) ASM void hwint07 ()//interrupt routine for IRQ 7 (printer) {Hwint_master (7)} #define HWINT_SLAVE (irq_no)/push Irq_no/call spurious_irq/add ESP, 4/hlt/#pragma align (+) a SM void hwint08 ()//interrupt routine for IRQ 8 (realtime clock). {Hwint_slave (8)} #pragma align (+) ASM void hwint09 ()//interrupt routine for IRQ 9 (IRQ 2 redirected) {Hwint_slave (9) } #pragma align (+) ASM void hwint10 ()//interrupt routine for IRQ ten {Hwint_slave (Ten)} #pragma align (+) ASM void Hwint One ()//interrupt routine for IRQ {Hwint_slave (one)} #pragma align (() ASM void hwint12 ()//interrupt routine for IRQ-{hwint_slave ()} #pragma align (+) ASM void hwint13 ()//interrupt Routine for IRQ (FPU exception) {Hwint_slave (1)} #pragma align (+) ASM void hwint14 ()//interrupt routine for IRQ 4 (at Winchester) {Hwint_slave} #pragma align (+) ASM void hwint15 ()//interrupt routine for IRQ {Hwint_slave (15 )}//Initialize IDT void Init_prot () {init_8259a ();//Initialize All to interrupt gate (no trap gate)//Interrupt vector interrupt class value handler function permissions//exception Init_idt_desc (int_vector_div IDE, Da_386igate, Divide_error, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_debug, Da_386igate, SINGLE_STEP_EXCEPTION,PRIVILEGE_KRNL); Init_idt_desc (Int_vector_nmi, Da_386igate, NMI, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_breakpoint, Da_386igate, Breakpoint_exception, Privilege_user); Init_idt_desc (Int_vector_overflow, Da_386igate, OVERFLOW, Privilege_user); Init_idt_desc (Int_vector_bounds, Da_386igate, Bounds_check, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_inval_op, Da_386igate, Inval_opcode, Privilege_kRNL); Init_idt_desc (Int_vector_coproc_not, Da_386igate, copr_not_available, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_double_fault,da_386igate, Double_fault, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_coproc_seg, Da_386igate, Copr_seg_overrun, PRIVILEGE_KRNL); Init_idt_desc (INT_VECTOR_INVAL_TSS, Da_386igate, INVAL_TSS, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_seg_not, Da_386igate, Segment_not_present, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_stack_fault, Da_386igate, Stack_exception, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_protection, Da_386igate, General_protection, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_page_fault, Da_386igate, Page_fault, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_coproc_err, Da_386igate, Copr_error, PRIVILEGE_KRNL); External interrupt Init_idt_desc (int_vector_irq0 + 0, da_386igate, hwint00, PRIVILEGE_KRNL); Init_idt_desc (int_vector_irq0 + 1, da_386igate, hwint01, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq0 + 2, da_386igate, hwint02, PRIVILEGE_KRNL); Init_idt_desc (INt_vector_irq0 + 3, da_386igate, hwint03, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq0 + 4, da_386igate, hwint04, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq0 + 5, da_386igate, hwint05, PRIVILEGE_KRNL); Init_idt_desc (int_vector_irq0 + 6, da_386igate, hwint06, PRIVILEGE_KRNL); Init_idt_desc (int_vector_irq0 + 7, da_386igate, hwint07, PRIVILEGE_KRNL); Init_idt_desc (int_vector_irq8 + 0, da_386igate, hwint08, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq8 + 1, da_386igate, hwint09, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq8 + 2, da_386igate, hwint10, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq8 + 3, da_386igate, hwint11, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq8 + 4, da_386igate, hwint12, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq8 + 5, da_386igate, hwint13, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq8 + 6, da_386igate, hwint14, PRIVILEGE_KRNL); Init_idt_desc (Int_vector_irq8 + 7, da_386igate, hwint15, PRIVILEGE_KRNL); Custom Interrupt//init_idt_desc (int_vEctor_sys_call, Da_386igate, Sys_call, Privilege_user); * (t_16*) (&idt_ptr[0]) = idt_size * sizeof (GATE); * (t_32*) (&idt_ptr[2]) = (t_32) &idt + protecaddr; Asm{lidt Idt_ptr}//Load IDT}//Close specific interrupt asm void Disable_irq (int IRQ) {mov ecx, [ESP + 4]//IRQ PUSHF CLI mov ah, 1 rol Ah, CL//ah = (1 << (IRQ% 8)) CMP cl, 8 Jae Disable_8//disable IRQ >= 8 at the slave 8259 Disable_0:in al, Int_m_ Ctlmask Test Al, ah jnz dis_already//already disabled? Or AL, ah out Int_m_ctlmask, al//set bit in master 8259 Popf mov eax, 1//disabled by this function ret Disable_8:in al, Int_s_ctlmask Test Al, ah jnz dis_already//already disabled? Or AL, ah out Int_s_ctlmask, al//set bit @ slave 8259 Popf mov eax, 1//disabled by this function ret Dis_already:popf xor eax, eax//already disabled ret}//Open specific interrupt asm void Enable_irq (int IRQ) {mov ecx, [esp + 4]; IRQ PUSHF CLI mov ah, To Rol ah, cl//ah = ~ (1 << (IRQ% 8)) CMP cl, 8 Jae Enable_8//enable IRQ >= 8 at the slave 8259 Enable_0:in Al, Int_m_ctlmask and Al, ah out Int_m_ctlmask, Al//clear bits at Master 8259 Popf ret enable_8:in al, INT _s_ctlmask and Al, ah out Int_s_ctlmask, al//clear bit at slave 8259 Popf ret}//to a specific interrupt registration handler void Put_irq_handler (INT i RQ, T_pf_irq_handler handler) {DISABLE_IRQ (IRQ); IRQ_TABLE[IRQ] = handler;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.