simulavr-devel
[Top][All Lists]
Advanced

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

[Simulavr-devel] [bug #45941] [PATCH] Bug in interrupt handling with ins


From: Marcus Holland-Moritz
Subject: [Simulavr-devel] [bug #45941] [PATCH] Bug in interrupt handling with instructions that clear interrupt flag
Date: Sat, 12 Sep 2015 12:48:43 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36

URL:
  <http://savannah.nongnu.org/bugs/?45941>

                 Summary: [PATCH] Bug in interrupt handling with instructions
that clear interrupt flag
                 Project: Simulavr: an AVR simulator
            Submitted by: mhx
            Submitted on: Sat 12 Sep 2015 12:48:42 PM GMT
                Category: Simulation
                Severity: 3 - Normal
              Item Group: None
                  Status: None
                 Privacy: Public
             Assigned to: None
        Originator Email: address@hidden
             Open/Closed: Open
         Discussion Lock: Any
       Component Version: simulavrxx

    _______________________________________________________

Details:

Hi!

I believe I've found a bug in the way simulavr handles interrupts
in the presence of instructions that disable global interrupts.

In a nutshell, when an interrupt is detected and queued to be
executed after the next statement and the next statement is
either CLI or any other instruction that clears the global
interrupt flag (OUT SREG, ...), the interrupt handler will still
be called /after/ global interrupts have been disabled. This
basically means that code that was meant to be uninterruptible
(protected by CLI / SEI) can now be interrupted as the RETI
will jump back to the first instruction after CLI and will even
leave interrupts enabled.

The documentation for CLI clearly states:

  "The interrupts will be immediately disabled. No interrupt
   will be executed after the CLI instruction, even if it
   occurs simultaneously with the CLI instruction."

It isn't quite as clear for when OUT SREG clears the interrupt
flag, but I verified that the behaviour is the same with an
actual ATmega32u4.

I noticed this behaviour when the scheduler for an RTOS I had
written years ago was running amok if left running for long
enough under simulavr. The code had been running for years
without any issues, but failed on simulavr after ~6 seconds
of simulation time.

I've attached some example code to reproduce the problem. From
the trace, you can see that __vector_6 is called after the
execution of CLI (removed wait states for readability):

  clibug.elf 0x009c: main+0xd                       SEI SREG=[I-----Z-] 
  clibug.elf 0x009e: main+0xe                       clibug.elf interrupt on
index 6cleared
  IRQ prepared for addr c
  CLI SREG=[------Z-] 
  clibug.elf 0x00a0: main+0xf                       IRQ DETECTED: VectorAddr:
12clibug.elf IrqSystem: IrqHandlerStarted Vec: 6
  SP=0x45c 0x50 SP=0x45b 0x0 
  clibug.elf 0x0018: ,__vector_default+0xc          JMP 6c __vector_6         
           
  clibug.elf 0x006c: __vector_6                     PUSH R1 SP=0x45a 0x0 
  clibug.elf 0x006e: __vector_6+0x1                 PUSH R0 SP=0x459 0xaa 
  clibug.elf 0x0070: __vector_6+0x2                 IN R0, 0x3f 
  clibug.elf 0x0072: __vector_6+0x3                 PUSH R0 SP=0x458 0x2 
  clibug.elf 0x0074: __vector_6+0x4                 EOR R1, R1 SREG=[------Z-]

  clibug.elf 0x0076: __vector_6+0x5                 NOP 
  clibug.elf 0x0078: __vector_6+0x6                 POP R0 SP=0x459 0x2 
  clibug.elf 0x007a: __vector_6+0x7                 OUT 0x3f, R0 
  clibug.elf 0x007c: __vector_6+0x8                 POP R0 SP=0x45a 0xaa 
  clibug.elf 0x007e: __vector_6+0x9                 POP R1 SP=0x45b 0x0 
  clibug.elf 0x0080: __vector_6+0xa                 RETI SP=0x45c 0x0 SP=0x45d
0x50 clibug.elf IrqSystem: IrqHandler Finished Vec: 6
  clibug.elf 0x00a0: main+0xf                       NOP 

I've also attached a patch that aims to fix the problem by
checking the current instruction before preparing interrupts.
If the instructions will clear the interrupt flag, interrupt
preparation will be skipped. I'm not sure this is the most
elegant way to solve the problem, in particular as there is
now some redundancy with the instruction decoder, but I
couldn't think of a better way while at the same time keeping
the code simple. I'm totally open for suggestions on how to
do things differently :-)

Thanks,
Marcus

PS: The example code was written for atmega16 and I've used the
following commands to test it:

  # avr-gcc -mmcu=atmega16 -gstabs -O2 -std=gnu99 -DF_OSC=1000000 clibug.c -o
clibug.elf
  # simulavr -d atmega16 -t clibug.trace -F 1000000 -m 10000000 -f clibug.elf



    _______________________________________________________

File Attachments:


-------------------------------------------------------
Date: Sat 12 Sep 2015 12:48:42 PM GMT  Name: clibug.c  Size: 380B   By: mhx

<http://savannah.nongnu.org/bugs/download.php?file_id=34862>
-------------------------------------------------------
Date: Sat 12 Sep 2015 12:48:42 PM GMT  Name: fix-cli.patch  Size: 3kB   By:
mhx

<http://savannah.nongnu.org/bugs/download.php?file_id=34863>

    _______________________________________________________

Reply to this item at:

  <http://savannah.nongnu.org/bugs/?45941>

_______________________________________________
  Message sent via/by Savannah
  http://savannah.nongnu.org/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]