[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/
- [Simulavr-devel] [bug #45941] [PATCH] Bug in interrupt handling with instructions that clear interrupt flag,
Marcus Holland-Moritz <=