"Self-written operating system sixth chapter" introduced Minix interrupt processing mode

Source: Internet
Author: User
Absrtact: Looking back, we found that our interrupt handlers were not written elegantly enough. The interrupt response requires three conditions: the interrupt token in the eflags is open, the interrupt mask register does not block the corresponding interrupt, and the EOI flag is set.

1. Modify the clock interrupt handler: G/kernel/kernel.asm


174     Inc DWORD [K_reenter]
175     CMP DWORD [K_reenter], 0
176     jne. 1; re-entry. 1
177 
178     mov ESP, stacktop       ; cut to kernel stack
179 	   
	push	. RESTART_V2
	jmp	. 2
. 1:
	push	. Restart_ Reenter_v2
. 2     sti
181 
182     push    0 183 call    Clock_handler
184     Add ESP, 4
185 
186     CLI
	ret, corresponding to the preceding push statement

. RESTART_V2: 
188     mov ESP , [P_proc_ready]; leaving the kernel stack;
189     Lldt    [esp + p_ldt_sel]     eax, [esp + p_stacktop]
191     mov DWORD [TSS + TSS3_S_SP0 ], eax
192 
193. RESTART_REENTER_V2:  if (k_reenter! = 0), it will jump here
194     Dec DWORD [K_reenter]   ; k_reenter--;
195     pop GS  ; ┓
196     pop fs  ┃
197     pop es  ; ┣ Restore original Register value
198     Pop ds  ; ┃
199     popad       ; ┛     add ESP, 4
201 

Note: The above code has also changed logically: The interrupt service is still executed when the interrupt is re-entered, but it will only print ". "is returned; a process switch is performed without an interrupt switch.
Let's take a look at the corresponding interrupt handlers:
-public void Clock_handler (int IRQ),
 {     disp_str ("#");     ticks++;     if (k_reenter! = 0) {         disp_str ("!");         return;     p_proc_ready++;     if (p_proc_ready >= proc_table + nr_tasks) {p_proc_ready         = proc_table;     {
 36}

After we change the code, let's Run the program again:
Think: Whether the above code will cause a stack overflow problem caused by interrupt re-entry.

2. Modify the Restart programRestart is a program that re-runs the Sleep program, which is defined by the assembly in Kernel.asm, called by Tnix_main () in Main.c, and then enters the dead loop:
     k_reenter =-1;     P_proc_ready    = proc_table;     Restart ();     (1) {}

Let's change the code for restart:
353 Restart:
354     mov esp, [p_proc_ready]
355     Lldt    [esp + P_ldt_sel]
356     lea EAX, [ESP + P_ Stacktop]
357     mov DWORD [TSS + tss3_s_sp0], eax
358 restart_reenter:
 Dec DWORD [K_reenter]; Because of this sentence, We need to change the initial value of K_reenter from 1 to 0
359     pop gs
pop     fs
361     pop es
362     pop ds
363     Popad
364     add ESP, 4
365     iretd

Since the latter part of the clock interrupt is the same as the restart, we can omit the coincident part of the clock interrupt.


3 Modifying the interrupt handler--saveCompare the original interrupt handler: Let's summarize the contents of the clock Interrupt program:
1) Protection context
2) Judging interrupt re-entry and stack switching
3) Open interrupt and interrupt processing core program
4) Restore context (already and in the restart process)
Now, we will be 1 and 2) also Independent:
193 Save:
194     Sub ESP, 4
195     Pushad      ; ┓
196     push    ds  ; ┃
197     Push    Es  ; ┣ Save original Register value
198     push    FS  ; ┃
199     push    GS  ; ┛
.     mov dx, ss
201     mov ds, DX
202     mov es, dx
203 
204     mov eax,esp
205 
206     Inc DWORD [K_reenter]
207     CMP DWORD [K_reenter], 0
208     jne. 1
209     with mov esp, Stacktop       ; cut to the kernel stack
211     push    restart
212     jmp. 2
213.1:
214     Push    Restart_reenter
215.2:
216     jmp     [Eax+retadr-p_stackbase]
Partial content of the interrupt handler:
158 hwint00:        ; Interrupt routine for IRQ 0 (the clock).
159     ; Inc    Byte [gs:0]; Change the No. 0 row of the screen, the character of the No. 0 column
161 call     Save
162     mov al, EOI     ; ┓re Enable Master 8259
163 out     Int_m_ctl, Al   ; ┛
Here, we notice a very strange call command--not ending with a ret. Why is it. Think about it, ret pops the return address from the stack to the EIP; but because of this, ESP is changed in the call instruction, so it can't be returned with RET, it needs to use JMP, which is the address of the next instruction to call as the return address of the calling procedure.

4. Modify interrupt Handler--reentrant problem of clock interruptAs we have already analyzed in the first part of this article, the code in this case can still cause a re-entry of the clock interrupt: Therefore, it is necessary to turn off the clock interrupt before reopening the interrupt, and then turn the clock interrupt on after the interrupt is closed.
Look at the code:
     Save
161 162 in  al,int_m_ctlmask
163     or  al,1 164 out     int_m_ Ctlmask,al
165     
166     mov al, EOI     ; ┓reenable Master 8259
167 out     Int_m_ctl, Al   ; ┛
168     
169     STI     171 push    0
call    clock_handler
172     Add ESP, 4
173     
174     CLI
175     in  al,int_m_ctlmask
176 and     Al,0xfe
177 Out     int_m_ctlmask
178 
179     RET

5. Modify interrupt Handlers-code modularity: Unified Interrupt Processing RoutinesIn the above code, we notice that the real clock-related parts are finite, which can easily be extended to other interrupt types. Let's define a macro hwint_master to handle hardware interrupts.
150; Interrupts and exceptions--hardware interrupt
151;---------------------------------
%macro  hwint_master    1
153     Call    Save
154  in AL, Int_m_ctlmask   ; ┓
155     or  al, (1 <<% 1)       ; ┣ Mask Current interrupt
156 out     Int_m_ctlmask, Al   ; ┛
157     mov al, EOI; ┓ EOI bit 158 out     Int_m_ctl, al< c23/>; ┛
159     STI; The CPU automatically shuts down interrupts during the response to the interrupt, which is then allowed to respond to the new interrupt     push    %1          ; ┓
161 call    [irq_table + 4 *%1]    ; ┣ interrupt handler; Obviously, Irq_table is an array of function pointers, which we define in GLOBAL.C
162     pop ecx         ; ┛
163     CLI
164     in  al, Int_m_ctlmask   ; ┓
165     and Al, ~ (1 << 1)      ; ┣ Resume Accept current interrupt
166 Out     Int_m_ctlmask, Al   ; ┛
167     ret
168%endmacro

Related:
Irq_table is defined in the GLOBAL.C:
Public Irq_hander IRQ_TABEL[NR_IRQ];
Declaration: extern Irq_hander irq_table[]; in global.h
Increased definition of Irq_handler in type.h: typedef void (*irq_handler) (int IRQ)
Const.h: #define NR_IRQ 16

Next, let's initialize the irq_table and initialize it to SPURIOUS_IRP first:
In the init_8259a function:
int i; for
(I=0;I<NR_IRQ;I++LL)
	Irq_table[i]=surious_irq;

Now, we need a function to assign a value to Irq_table[0]:
Put_irq_handler public void (int IRQ, T_pf_irq_handler handler)
 {     DISABLE_IRQ (IRQ); This sentence is necessary Before interrupt processing, first off corresponding interrupt     IRQ_TABLE[IRQ] = handler;
 48}

Here, as you can see, we used an interrupt enable function DISABLE_IRQ, and we'll look at it and the structure of another function Enable_irq.

123;                  ======================================================================== 124;
void Disable_irq (int IRQ); 125; ======================================================================== 126;
Disable an interrupt request line by setting a 8259 bit. 127;       Equivalent code for IRQ < 8:128; Out_byte (Int_ctlmask, In_byte (int_ctlmask) |
(1 << IRQ)); 129;
Returns true iff the interrupt is not already disabled.
130; 131 disable_irq:132 mov ecx, [esp + 4]; IRQ 133 PUSHF 134 CLI 135 mov ah, 1 136 rol Ah, cl; Ah = (1 << (IRQ% 8)) 137 CMP cl, 8 138 Jae Disable_8; Disable IRQ >= 8 at the slave 8259 139 disable_0:140 in AL, Int_m_ctlmask 141 test Al, ah 142 jnz Dis_ already;
Already disabled? 143 or Al, ah 144 out Int_m_ctlmask, AL; Set bit at Master 8259 145 Popf 146 mov eax, 1; Disabled by this function 147 RET 148 disable_8:149 in AL, Int_s_ctlmask-Test Al, ah 151 jnz dis_already;
Already disabled? Or AL, ah 153 out Int_s_ctlmask, AL; Set bit at slave 8259 154 Popf 155 mov eax, 1; Disabled by this function 156 RET 157 dis_already:158 Popf 159 xor eax, EAX;  Already disabled RET 161
The corresponding enable code we omit, please read the reader on their own to explain.

6. Application of a unified interrupt processing paradigm
In MAIN.C, the interrupt handler is bound to the pinned pin.
     P_proc_ready    = proc_table;     Put_irq_handler (CLOCK_IRQ, clock_handler);  /* Set Clock Interrupt handler *     /ENABLE_IRQ (CLOCK_IRQ);              /* Allow 8259A to receive clock interrupts
 *     /restart ();
Block all interrupts in init_8259a: Out_byte (INT_M_CTLMASK,0XFF).

To sum up, how we paradigm the interrupt processing process: We extract the register recovery, the stack switch LDT, and so on to the restart part; interrupt processing core: printing related information and process switching is put into the clock interrupt processing handle; Save the context, The judgment interrupt re-entry is put into the save function; In order to prevent clock interrupt re-entry, we add interrupt enable control statement in interrupt processing process; Next, interrupt processing is extended to generalized interrupt processing to encapsulate the interrupt processing process into macro definition Hwint_master. The process is roughly the same, as you can see, it's a process from specialization to generalization, and it's a good way to avoid bloated code and mistakes.

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.