Bochs or me? (Problem resolved!)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Ryu

Bochs or me? (Problem resolved!)

Post by Ryu »

The original thread I created had a lot of long post and haven't made to a second page, which I think led to problems trying to access it. This thread continues Bochs or me? thread.
Brendan wrote: It's a pain in the neck, but the PIC chips can generate a "spurious interrupt", which is normally IRQ7 for PIC1 and IRQ15 for PIC2 (and can't be masked).

The idea is that if the PIC chip's "INTR" line is high then the CPU is meant to wait for the interrupt number to come from a PIC chip. If the PIC chip doesn't know why the INTR line is high then it'll send a spurious interrupt so that the CPU does receive an interrupt number and doesn't get all messed up (i.e. wait forever).

Bochs does emulate this spurious interrupt - see "iodev/pic.cc" around line 807.
Yes! I went and checked 8259A datasheet, and does say along the lines. If IR7 is spurious then you can ignore it and just do iret. But if IR7 is to be used, then you can read PIC.ISR which should be set to the corresponding IR otherwise would be considered spurious. I assume that IR7 is IRQ-15 for slave?

Btw, I am very glad that Bochs emulates this other wise this may lead to very big bugs in the future.
Brendan wrote: Out of curiousity, what would happen if your OS got an IRQ7?
What I also found out was after masking it correctly (which I did fix up and thanks :) ) wasn't enough and GPF still was being generated. I finally went and tried to do a software interrupt to 27h (IRQ-7), and it produced a GPF not a #NP (No segment Present). I guess I was wrong to think that it should have made #NP, and after referring back to the holy bible it doesn't specify on IDTs but only in its error codes, hmm which is confusing.

Here is my routine to handle spurious interrupts:

Code: Select all

SYSTEM_SPURIOUS equ 0FFh

;==========================================================================
___Interrupt27h      PROC SYSCALL
;==========================================================================
;+++++++++++++++STACK+++++++++++++++++++10h++++++++++++++++++++++++++++++++
   @EFLAGS               equ      esp+0Ch
   @CS                  equ      esp+08h
   @RIP               equ      esp+04h
   push   eax         ;   equ      esp+00h
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

   ;;;;; handle spurious NMIs ;;;;;;

   test   BYTE PTR ds:[swSystemFlags], SYSTEM_SPURIOUS   ; guard nesting spurious
   jnz      short @RETURN                           ; interrupt events

   mov      al, 03h            ; PIC.OCW3 set function to read ISR (In Service Register)
   out      23h, al            ; write to PIC.OCW3
   in      al, 20h            ; read ISR

   test   al, 80h            ; if the in-service register does not have IR7 bit set
   jz      short @RETURN      ; this would be a spurious interrupt.

   ;;;; mutex for spurious guard ;;;;

   adc      BYTE PTR ds:[swSystemFlags], 7Fh   ; only first access to handle will pass the
   jp      short @RETURN                  ; the following flags
   jo      short @RETURN                  ; NMIs that made it this far will
   jc      short @RETURN                  ; return as spurious interrupt.

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ;;;;; normal IRQ-7 routine ;;;;;;
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

   mov      al, 20h
   out      20h, al            ; send EOI to master PIC

   mov      BYTE PTR ds:[swSystemFlags], 0      ; release spurious guarding

@RETURN:
   pop      eax
   iretd
___Interrupt27h      ENDP
If you have comments or find anything wrong with it please tell me. I hope it helps other readers overcome sparious interrupts also.

Brendan thanks a ton, because I think I would jumped off a building if it didn't make sense after two more days! I really do appreciate it. :)
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Bochs or me? (Problem resolved!)

Post by Brendan »

Hi,
Ryu wrote:If you have comments or find anything wrong with it please tell me. I hope it helps other readers overcome sparious interrupts also.
There isn't anything wrong there, but you might want to simplify the "mutex for spurious guard". For e.g. something like this will do:

Code: Select all

   ;;;; mutex for spurious guard ;;;;

   bts     BYTE PTR ds:[swSystemFlags], 0 ; only first access to handle will pass
   jc      short @RETURN

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ;;;;; normal IRQ-7 routine ;;;;;;
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

   mov      al, 20h
   out      20h, al            ; send EOI to master PIC

   btr      BYTE PTR ds:[swSystemFlags], 0      ; release spurious guarding
I'm also going to assume you're using an "interrupt gate" rather than a "trap gate" (i.e. that interrupts are disabled while you're reading the ISR from the PIC), even though it won't matter if the "normal IRQ-7 routine" enables IRQs again.

Of course if the "normal IRQ-7 routine" nevr enables interrupts, then you don't need any spurious guarding because the ISR bit in the PIC will do that for you... :)

You might also want to do something similar for "spurious IRQ15":

Code: Select all

;==========================================================================
___Interrupt2Fh      PROC SYSCALL
;==========================================================================
;+++++++++++++++STACK+++++++++++++++++++10h++++++++++++++++++++++++++++++++
   @EFLAGS               equ      esp+0Ch
   @CS                  equ      esp+08h
   @RIP               equ      esp+04h
   push   eax         ;   equ      esp+00h
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

   ;;;;; handle spurious NMIs ;;;;;;

   test   BYTE PTR ds:[swSystemFlags], SYSTEM_SPURIOUS   ; guard nesting spurious
   jnz      short @RETURN                           ; interrupt events

   mov      al, 03h            ; PIC.OCW3 set function to read ISR (In Service Register)
   out      A3h, al            ; write to PIC.OCW3
   in      al, A0h            ; read ISR

   test   al, 80h            ; if the in-service register does not have IR7 bit set
   jz      short @RETURN      ; this would be a spurious interrupt.

   ;;;; mutex for spurious guard ;;;;

   bts     BYTE PTR ds:[swSystemFlags], 1 ; only first access to handle will pass
   jc      short @RETURN

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ;;;;; normal IRQ-15 routine ;;;;;
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

   mov      al, 20h
   out      A0h, al            ; send EOI to slave PIC

   btr      BYTE PTR ds:[swSystemFlags], 1      ; release spurious guarding

@RETURN:
   mov al, 62h            ; NOTE: Specific EOI used for master PIC cascade line!!!!
   out 20h, al            ; send EOI to slave PIC (clear the ISR flag for IRQ15)

   pop      eax
   iretd
___Interrupt2Fh      ENDP
The important part here is sending the EOI to the master PIC without messing up the master PIC's ISR for normal IRQs... ;)


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Ryu

Re:Bochs or me? (Problem resolved!)

Post by Ryu »

Brendan wrote: I'm also going to assume you're using an "interrupt gate" rather than a "trap gate" (i.e. that interrupts are disabled while you're reading the ISR from the PIC), even though it won't matter if the "normal IRQ-7 routine" enables IRQs again.
I use interrupt gates, and only want one interrupt in service at a time. This is because I have only 2KB stack, and if nesting interrupts were allowed then can exceed the stacks limits. But possiblily I will need a trap gate for specific IRQs that the kernel does not use and those trap gates will have to switch stacks. At least this is just my theory approach, I have no real experience with the whole picture of maintaining ISRs in a operating system.
Brendan wrote: Of course if the "normal IRQ-7 routine" nevr enables interrupts, then you don't need any spurious guarding because the ISR bit in the PIC will do that for you... :)
Theres a thing though, heres what is on the 8259A datasheet in page 18:

If IR7 is needed for other purposes a default IR7 can still be detected by reading the ISR. A normal IR7 interrupt will set the corresponding ISR bit, a default won't. If a default IR7 routine occurs during a normal IR7 routine, however, the ISR will remain set. In this case its necessary to keep track wether or not the IR7 routine was previously entered. If another IR7 occurs its default.

What they mean by default and normal is, defaults are the spurious interrupts and the normals is an installed routine. The spurious guard is needed because it can occur during normal IRQ-7 or IRQ-15 and ISR would still have the bit set. This is what I make of it anyways, and I'm just being cautious. Frankly, I'm not even sure if a spurious can happend while handling a spurious interrupt before it gets to return either. If the normal routine service rely on how many occurance of interruption then can lead to corrupt data, specifically IRQ-7 or IRQ-15.

I also think that for my operating system, I may leave IRQ-7 and IRQ-15 to specifically handling the spurious interrupts only. But that would be very wasteful.. or the kernel is only allowed to use it. I donno.

Thankye for this note: "Specific EOI used for master PIC cascade line!!!!
". I would of sent a 20h.. ;D
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Bochs or me? (Problem resolved!)

Post by Brendan »

Hi,
Ryu wrote:What they mean by default and normal is, defaults are the spurious interrupts and the normals is an installed routine. The spurious guard is needed because it can occur during normal IRQ-7 or IRQ-15 and ISR would still have the bit set. This is what I make of it anyways, and I'm just being cautious. Frankly, I'm not even sure if a spurious can happend while handling a spurious interrupt before it gets to return either. If the normal routine service rely on how many occurance of interruption then can lead to corrupt data, specifically IRQ-7 or IRQ-15.
You are correct - if interrupts are enabled within a "normal" IRQ7 then you might get a spurious/default IRQ7 while the ISR bit is still set, however...
Ryu wrote:I use interrupt gates, and only want one interrupt in service at a time.
...in this case, you can't get any IRQ (normal or spurious) while you're handling a normal IRQ7 because the CPU has interrupts disabled. By the time the CPU starts handling the spurious interrupt (i.e. when interrupts are enabled again) the ISR bit from the real IRQ 7 would have been cleared by the EOI.
Ryu wrote:I also think that for my operating system, I may leave IRQ-7 and IRQ-15 to specifically handling the spurious interrupts only. But that would be very wasteful.. or the kernel is only allowed to use it. I donno.
IRQ 7 may be hardwired to the parallel port (and/or sound card or almost anything else), while IRQ15 is used for the secondary ATA/ATAPI controller. You probably shouldn't refuse to support these devices (unless your OS is for your use only).

Alternatively, you could refuse to support the PIC chips so that your OS requires an I/O APIC. This might sound extreme, but most modern computers have an I/O APIC now and by the time you've "finished" writing the OS computers without an I/O APIC will probably be very rare.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Ryu

Re:Bochs or me? (Problem resolved!)

Post by Ryu »

Greetings again,
Brendan wrote: ...in this case, you can't get any IRQ (normal or spurious) while you're handling a normal IRQ7 because the CPU has interrupts disabled. By the time the CPU starts handling the spurious interrupt (i.e. when interrupts are enabled again) the ISR bit from the real IRQ 7 would have been cleared by the EOI.
Hmm I had to think twice with what your saying here, I may get the picture now.. Okay I get it now, it got me confused knowing that spurious interrupts are unmaskable.
Brendan wrote: IRQ 7 may be hardwired to the parallel port (and/or sound card or almost anything else), while IRQ15 is used for the secondary ATA/ATAPI controller. You probably shouldn't refuse to support these devices (unless your OS is for your use only).
I guess this will lead me to make IRQ-7 and IRQ-15 to trap gates and switch stacks for drivers to use. It would then be out of the kernels problem, other then guarding the spurious interrupts. But ofcourse I'm not sure if thats the best way either. Theres only so much I can picture in my brain without having to dig my hands in sand, I can really only know how to deal with it when the time comes.. but thanks for pointing that out. Basically I think the kernel will only reserve the timer IRQ.
Brendan wrote: Alternatively, you could refuse to support the PIC chips so that your OS requires an I/O APIC. This might sound extreme, but most modern computers have an I/O APIC now and by the time you've "finished" writing the OS computers without an I/O APIC will probably be very rare.
I agree.. I think most computers today have I/O APIC but being very clueless about PIC in general I choose to go down with the basics and work my way up. Perhaps I/O APIC is even more simpler, I don't know, but I need to also grasp the basic concept of PICs in the x86 architecture, and hopefully it will mean something when I get into I/O APIC.
mystran

Re:Bochs or me? (Problem resolved!)

Post by mystran »

I do have a perfectly good Duron/800 system, with a perfectly bad VIA KT133(A?) chipset, which does have an IOAPIC, which is buggy enough that you can't use it reliably on any current operating system, including such systems as "Windows" and "Linux".

The same chipset is also known for generating spurious interrupts for no good reason; Linux reports at least one during every boot, and once in a while during normal operation.

That machine would be perfectly usable for me. I do have an AMD64/3000+ as well for more signal processing and gaming power, but I could easily live with the Duron. In fact, I know several people that'd be happy to get such a powerful machine (including one of my sisters, my father, and several friends).

Add the fact that people tend to do OS experimentation with their secondary machines, and suddenly it doesn't seem bad idea at all to support system without (or with unusable) IOAPIC..
Post Reply