Bugs in irqtab.c and patches

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

    I found 3 bugs in file arch/i86/kernel/irqtab.c:

    1. Interrupt #15 was considered a trap and the corresponding EOI
not sent, rendering this
        interrupt useless after servicing the first interrupt.

    2. Interrupts in the slave controller are masked after servicing
the first interrupt, rendering
        these interrupts useless.

    3. In interrupt #0, the bios service routine is invoked once every
5 interrupts. When this
        happens, both ELKS and BIOS interrupts service routines send
EOI to the interrupt
        controller, probably disrupting its internal operation.

    In addition to fixing the above bugs, the following patch reduces
the code size in at least
50 bytes. After applying the patch, the kernel Image was built and the
a test machine booted the modified kernel.

greetings,

Juan

diff -Nurb elks.orig/arch/i86/kernel/irqtab.c elks/arch/i86/kernel/irqtab.c
--- elks.orig/arch/i86/kernel/irqtab.c	2002-10-31 19:04:25.000000000 -0600
+++ elks/arch/i86/kernel/irqtab.c	2012-01-30 18:52:15.000000000 -0600
@@ -36,6 +36,11 @@
    #define bios_call_cnt    cseg_bios_call_cnt
 #endif

+#ifdef CONFIG_ROMCODE
+ #define SEG_IRQ_DATA es
+#else
+ #define SEG_IRQ_DATA cs
+#endif

 #ifndef S_SPLINT_S
 #asm
@@ -105,34 +110,32 @@
         mov dx,ds      ;the original value
         cli            ;just here

-        xor ax,ax
-        mov es,ax      ;intr table
-
 #ifdef CONFIG_ROMCODE
         mov ax,#CONFIG_ROM_IRQ_DATA
-#else
-        mov ax,cs
+        mov es,ax
 #endif
-        mov ds,ax
-
+        seg SEG_IRQ_DATA
 	mov stashed_ds,dx

+        xor ax,ax
+        mov es,ax      ;intr table
+
 	seg es                     ;insert new timer intr
 	mov bx,[32]
-	mov off_stashed_irq0, bx   ; the old one
-	lea ax,_irq0
+	mov off_stashed_irq0_l, bx	; the old one
+	mov ax,#_irq0
 	seg es
 	mov [32],ax
 	seg es
 	mov bx,[34]
-	mov seg_stashed_irq0, bx
+	mov seg_stashed_irq0_l, bx
 	mov ax,cs
 	seg es
 	mov [34],ax
-
+	mov [bios_call_cnt_l],#5	; init bios timer int. call counter

 #ifndef CONFIG_CONSOLE_BIOS
-	lea ax,_irq1      ;keyboard
+	mov ax,#_irq1      ;keyboard
 	seg es
 	mov [36],ax
 	mov ax,cs
@@ -141,7 +144,7 @@
 #endif

 #if 0
-	lea ax,_irq2
+	mov ax,#_irq2
 	seg es
 	mov [40],ax
 	mov ax,cs
@@ -149,14 +152,14 @@
 	mov [42],ax
 #endif

-	lea ax,_irq3      ;com2
+	mov ax,#_irq3      ;com2
 	seg es
 	mov [44],ax
 	mov ax,cs
 	seg es
 	mov [46],ax

-	lea ax,_irq4     ;com1
+	mov ax,#_irq4     ;com1
 	seg es
 	mov [48],ax
 	mov ax,cs
@@ -165,7 +168,7 @@


 ! Setup INT 0x80 (for syscall)
-	lea ax,_syscall_int
+	mov ax,#_syscall_int
 	seg es
 	mov [512],ax
 	mov ax,cs
@@ -223,65 +226,65 @@
 	mov	ax,#1
 	br	_irqit
 #if 0
-_irq2:
+_irq2:                   ;XT: EGA vert retrace; AT: cascade
 	push	ax
 	mov	ax,#2
 	br	_irqit
 #endif
-_irq3:                   ;com2
+_irq3:                   ;com2 & com4
 	push	ax
 	mov	ax,#3
 	br	_irqit
-_irq4:                   ;com1
+_irq4:                   ;com1 & com3
 	push	ax
 	mov	ax,#4
 	br	_irqit

 #if 0
-_irq5:
+_irq5:                   ;XT: fixed disk controller; AT: lpt2
 	push	ax
 	mov	ax,#5
 	br	_irqit
-_irq6:
+_irq6:                   ;floppy disk controller
 	push	ax
 	mov	ax,#6
 	br	_irqit
-_irq7:
+_irq7:                   ;lpt1 printer controller
 	push	ax
 	mov	ax,#7
 	br	_irqit
 !
 !	AT interrupts
 !
-_irq8:
+_irq8:                   ;real time clock
 	push	ax
 	mov	ax,#8
 	br	_irqit
-_irq9:
+_irq9:                   ;redirect cascade
 	push	ax
 	mov	ax,#9
 	br	_irqit
-_irq10:
+_irq10:                   ;
 	push	ax
 	mov	ax,#10
 	br	_irqit
-_irq11:
+_irq11:                   ;
 	push	ax
 	mov	ax,#11
 	jmp	_irqit
-_irq12:
+_irq12:                   ;ps2 mouse
 	push	ax
 	mov	ax,#12
 	jmp	_irqit
-_irq13:
+_irq13:                   ;math coprocessor
 	push	ax
 	mov	ax,#13
 	jmp	_irqit
-_irq14:
+_irq14:                   ;fixed disk controller 1
 	push	ax
 	mov	ax,#14
 	jmp	_irqit
-_irq15:
+_irq15:                   ;fixed disk controller 2
 	push	ax
 	mov	ax,#15
 	jmp	_irqit
@@ -445,27 +448,25 @@
 !
 #ifdef CONFIG_ROMCODE
         mov bx,#CONFIG_ROM_IRQ_DATA
-#else
-        mov bx,cs
+        mov es,bx
 #endif
+!
+!	Switch segments
+!
+        seg SEG_IRQ_DATA
+	mov	bx,stashed_ds		! Recover the data segment
         mov ds,bx

-	mov	stashed_irq,ax	! Save IRQ number
+	mov	stashed_irq_l,ax	! Save IRQ number
 	mov	ax,ss		! Get current SS
 	mov	bx,ax		! Save for later
-	mov	stashed_ss, ax	! Save SS:SP
-	mov	ax,sp
-	mov	stashed_sp, ax
-!
-!	Switch segments
-!
-	mov	ax,stashed_ds   ! Recover the data segment
-	mov	ds,ax
-	mov	es,ax
+	mov	stashed_ss_l,ax		! Save SS:SP
+	mov	stashed_sp_l,sp
+	movb	cl,bios_call_cnt_l
 !
 !	Set up task switch controller
 !
-	xor	ch,ch		! Assume we are not allowed to switch
+	xorb	ch,ch		! Assume we are not allowed to switch
 !
 !	See where we were (BX holds the SS on entry)
 !
@@ -482,7 +483,6 @@
 !	Bios etc - switch to interrupt stack
 !
 	mov	sp,#_intstack
-!	lea	sp, _intstack
 	j	switched
 !
 !	User task. Extract kernel SP. (BX already holds current)
@@ -491,8 +491,6 @@
 	mov	ax,[bx]		! kernel stack ptr
 	mov	sp,ax		! switch to kernel stack
 	inc	ch		! Switch allowable
-	j	switched
-ktask:
 !
 !	In ktask state we have a suitable stack. It might be
 !	better to use the intstack..
@@ -500,25 +498,15 @@
 switched:
 	mov	ax,ds
 	mov	ss,ax		! /* Set SS: right */
+	mov	es,ax		! /* Set ES: right */
+ktask:
 ! /*
 !	Put the old SS;SP on the top of the stack. We can't
 !	leave them in stashed_ss/sp as we could re-enter the
 !	routine on a reschedule.
 ! */
-#ifdef CONFIG_ROMCODE
-        mov ax,#CONFIG_ROM_IRQ_DATA
-        mov es,ax
-        seg es
-	push	stashed_sp
-	seg es
-	push	stashed_ss
-
-#else
-	seg 	cs
-	push	stashed_sp
-	seg	cs
-	push	stashed_ss
-#endif
+	push	stashed_sp_l
+	push	stashed_ss_l
 !
 !	We are on a suitable stack and cx says whether we can
 !	switch afterwards. The C code will want to eat CX so
@@ -530,19 +518,12 @@
 	mov	bp,sp
 	mov	_can_tswitch, ch
 	push	cx		! Save ch
-#ifdef CONFIG_ROMCODE
-        seg	es
-#else
-	seg	cs		! Recover the IRQ we saved
-#endif
-	mov	ax,stashed_irq
+	mov	ax,stashed_irq_l ! Recover the IRQ we saved
 	push	ax		! IRQ for later
 	push	bp		! Register base
 	push	ax		! IRQ number
-#ifdef CONFIG_ROMCODE
         mov ax,ds
-        mov es,ax        ;es back to dataseg
-#endif
+        mov	es,ax		! es back to dataseg
 !
 !	Call the C code
 !
@@ -557,52 +538,30 @@
 !
 !	Restore any chips
 !
-	cmp	ax,#15
+	cmp	ax,#16
 	jge	was_trap	! Traps need no reset
-	cmp	ax,#8
-	jge	sec_8259	! IRQ on low chip
-!
-!	Reset primary 8259
-!
+	or	ax,ax		! Is int #0?
+	jnz	a4
+	dec	cl		! Will call bios int?
+	je	was_trap
+a4:
 	mov	cl,al		! Save the IRQ number
-	inb	al,0x21		! The chip line state
-	jmp	a7
-a7:	jmp	a8
-a8:
-!	movb	al,#1
-!	shl	al,cl		! Shift the irq (saved in cl) to a mask
-!	orb	al,_cache_21
-!	movb	_cache_21, al
-	movb	al,_cache_21	! Extract the IRQ mask register
-	outb	0x21,al		! Now ack the IRQ
-	jmp	a9
-a9:	jmp	a10
-a10:	movb	al,#0x20	! EOI
-	outb	0x20,al
-	jmp	was_trap
-
+	movb	al,#0x20	! EOI
+	cmp	cl,#8
+	jb	pri_8259	! IRQ on low chip
 !
 !	Reset secondary 8259 if we have taken an AT rather
 !	than XT irq. We also have to prod the primay
 !	controller EOI..
 !
-sec_8259:
-	mov	cl,al		! Save the IRQ for making masks
-	inb	al,0xA1
-	jmp	a1
-a1:	jmp	a2
-a2:	movb	al,#1
-	shl	al,cl
-	orb	al,_cache_A1
-	movb	_cache_A1, al
-	outb	0xA1,al		! Now ack the IRQ
-	jmp	a3
-a3:	jmp	a4
-a4:	movb	al,#0x20
 	outb	0xA0,al
 	jmp	a5
-a5:	jmp	a6
-a6:	outb	0x20,al		! Ack on primary controller
+a5:	jmp	pri_8259
+!
+!	Reset primary 8259
+!
+pri_8259:
+	outb	0x20,al		! Ack on primary controller

 !
 !	And a trap does no hardware work
@@ -655,83 +614,44 @@
 	pop	cx
 	pop	bx
 	pop	es
-#ifdef CONFIG_ROMCODE
-	mov	ax,#CONFIG_ROM_IRQ_DATA
-	mov	ds,ax
-#else
-	seg	cs
-#endif
-	mov	ax, stashed_irq
-	or 	ax,ax
-	jz	irq0_bios
-	pop	ds
-	pop	ax
-!
-!	Iret restores CS:IP and F (thus including the interrupt bit)
-!
-	iret
+	cmp	stashed_irq_l,#0
+	jnz	no_bios_call
 !
 !	IRQ 0 (timer) has to go on to the bios for some systems
 !
-!	FIXME: should call the bios only every fifth event.
-!
 irq0_bios:
-    pop     ds
-	pop	ax           ;now the stack empty
-
-;------------------------------------------------
-;Build new Stack
-;
-;  SP    ->  RET seg
-;            RET offs
-;  SP-4  ->  BP
-;  SP-4  ->  BX
-;            DS
-;  SP-8  ->  free                     ;sp

-label1:
-
-	sub sp,#4                     ;space for retf
-	push bp
-	mov bp,sp
-
-	push	bx
-	push    ds
-#ifdef CONFIG_ROMCODE
-	mov bx,#CONFIG_ROM_IRQ_DATA
-#else
-	mov bx,cs
-#endif
-	mov ds,bx
-	mov	bx,bios_call_cnt
-	inc	bx
-	cmp	bx,#5
+	dec	[bios_call_cnt_l]
 	jne	no_bios_call
-
-	xor	bx,bx
-	mov	bios_call_cnt,bx
-	mov bx, seg_stashed_irq0
-	mov	[bp+4], bx
-	mov bx, off_stashed_irq0
-	mov [bp+2], bx
-
+	mov	[bios_call_cnt_l],#5
+	pushf
+	callf	[off_stashed_irq0_l]
+no_bios_call:
 	pop ds
-	pop	bx
-	pop bp
-	retf
-
-no_bios_call:                          ;sp-8
-	mov	bios_call_cnt,bx
-	pop	ds
-	pop	bx                     ;sp-4
-	pop bp
-	add sp,#4
+	pop	ax           ;now the stack empty
+!
+!	Iret restores CS:IP and F (thus including the interrupt bit)
+!
 	iret

 	.data
 .globl	_can_tswitch
 _can_tswitch:
 	.byte 0
+
+off_stashed_irq0_l:
+	.word	0
+seg_stashed_irq0_l:
+	.word	0
+stashed_sp_l:
+	.word 	0
+stashed_ss_l:
+	.word 	0
+stashed_irq_l:
+	.word	0
+bios_call_cnt_l:
+	.word	0
+
 	.zerow	256		! (was) 128 byte interrupt stack
 _intstack:
--
To unsubscribe from this list: send the line "unsubscribe linux-8086" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Kernel]     [Linux ia64]     [DCCP]     [Linux for ARM]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux