Fix QEMU timer interrupt handler

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3389 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-03-17 22:33:49 +00:00
parent c4a13281a2
commit 663ea6d478
8 changed files with 230 additions and 65 deletions

View File

@ -56,55 +56,55 @@
/* ISR and IRQ numbers */
#define ISR0 0
#define ISR1 1
#define ISR2 2
#define ISR3 3
#define ISR4 4
#define ISR5 5
#define ISR6 6
#define ISR7 7
#define ISR8 8
#define ISR9 9
#define ISR10 10
#define ISR11 11
#define ISR12 12
#define ISR13 13
#define ISR14 14
#define ISR15 15
#define ISR16 16
#define ISR17 17
#define ISR18 18
#define ISR19 19
#define ISR20 20
#define ISR21 21
#define ISR22 22
#define ISR23 23
#define ISR24 24
#define ISR25 25
#define ISR26 26
#define ISR27 27
#define ISR28 28
#define ISR29 29
#define ISR30 30
#define ISR31 31
#define ISR0 0 /* Division by zero exception */
#define ISR1 1 /* Debug exception */
#define ISR2 2 /* Non maskable interrupt */
#define ISR3 3 /* Breakpoint exception */
#define ISR4 4 /* 'Into detected overflow' */
#define ISR5 5 /* Out of bounds exception */
#define ISR6 6 /* Invalid opcode exception */
#define ISR7 7 /* No coprocessor exception */
#define ISR8 8 /* Double fault (pushes an error code) */
#define ISR9 9 /* Coprocessor segment overrun */
#define ISR10 10 /* Bad TSS (pushes an error code) */
#define ISR11 11 /* Segment not present (pushes an error code) */
#define ISR12 12 /* Stack fault (pushes an error code) */
#define ISR13 13 /* General protection fault (pushes an error code) */
#define ISR14 14 /* Page fault (pushes an error code) */
#define ISR15 15 /* Unknown interrupt exception */
#define ISR16 16 /* Coprocessor fault */
#define ISR17 17 /* Alignment check exception */
#define ISR18 18 /* Machine check exception */
#define ISR19 19 /* Reserved */
#define ISR20 20 /* Reserved */
#define ISR21 21 /* Reserved */
#define ISR22 22 /* Reserved */
#define ISR23 23 /* Reserved */
#define ISR24 24 /* Reserved */
#define ISR25 25 /* Reserved */
#define ISR26 26 /* Reserved */
#define ISR27 27 /* Reserved */
#define ISR28 28 /* Reserved */
#define ISR29 29 /* Reserved */
#define ISR30 30 /* Reserved */
#define ISR31 31 /* Reserved */
#define IRQ0 32
#define IRQ1 33
#define IRQ2 34
#define IRQ3 35
#define IRQ4 36
#define IRQ5 37
#define IRQ6 38
#define IRQ7 39
#define IRQ8 40
#define IRQ9 41
#define IRQ10 42
#define IRQ11 43
#define IRQ12 44
#define IRQ13 45
#define IRQ14 46
#define IRQ15 47
#define IRQ0 32 /* System timer (cannot be changed) */
#define IRQ1 33 /* Keyboard controller (cannot be changed) */
#define IRQ2 34 /* Cascaded signals from IRQs 815 */
#define IRQ3 35 /* Serial port controller for COM2/4 */
#define IRQ4 36 /* serial port controller for COM1/3 */
#define IRQ5 37 /* LPT port 2 or sound card */
#define IRQ6 38 /* Floppy disk controller */
#define IRQ7 39 /* LPT port 1 or sound card */
#define IRQ8 40 /* Real time clock (RTC) */
#define IRQ9 41 /* Open interrupt/available or SCSI host adapter */
#define IRQ10 42 /* Open interrupt/available or SCSI or NIC */
#define IRQ11 43 /* Open interrupt/available or SCSI or NIC */
#define IRQ12 44 /* Mouse on PS/2 connector */
#define IRQ13 45 /* Math coprocessor */
#define IRQ14 46 /* Primary ATA channel */
#define IRQ15 47 /* Secondary ATA channel */
#define NR_IRQS 48
@ -138,6 +138,25 @@
#define XCPTCONTEXT_REGS (16)
#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
/* Some special landmarks in the stack frame:
*
* TOP_PUSHA - The offset (in 32-bit words) from the beginning of the
* save area on the stack to the value that should be in REG_ESP.
* BOTTOM_PUSHA - The offset (in 32-bit words) from the stack position before
* the interrupt occurred to the value that should be in REG_ESP.
* save area on the stack to the value that should be in REG_ESP.
* OFFSET_PRIO - The offset from the value of REG_ESP to the value of the
* stack pointer before the interrupt occurred (assuming that a priority
* change occurred.
* OFFSET_PRIO - The offset from the value of REG_ESP to the value of the
* stack pointer before the interrupt occurred (assuming that NO priority
* change occurred.
*/
#define TOP_PUSHA REG_IRQNO
#define BOTTOM_PRIO (XCPTCONTEXT_REGS-REG_IRQNO)
#define BOTTOM_NOPRIO (REG_SP-REG_IRQNO)
/****************************************************************************
* Public Types
****************************************************************************/

View File

@ -80,7 +80,6 @@
* referenced is passed to get the state from the TCB.
*/
#define up_savestate(regs) up_copystate(regs, current_regs)
#define up_restorestate(regs) (current_regs = regs)
/****************************************************************************
@ -150,6 +149,7 @@ extern uint32_t _ebss; /* End+1 of .bss */
extern void up_boot(void);
extern void up_copystate(uint32_t *dest, uint32_t *src);
extern void up_savestate(uint32_t *regs);
extern void up_decodeirq(uint32_t *regs);
extern void up_irqinitialize(void);
#ifdef CONFIG_ARCH_DMA

View File

@ -85,7 +85,10 @@ void up_initial_state(_TCB *tcb)
memset(xcp, 0, sizeof(struct xcptcontext));
/* Save the initial stack pointer */
/* Save the initial stack pointer... the value of the stackpointer before
* the "interrupt occurs." We don't know the value of REG_ESP yet..
* that depends on if a priority change is required or not.
*/
xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr;

View File

@ -0,0 +1,113 @@
/****************************************************************************
* arch/x86/src/i486/up_savestate.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <debug.h>
#include <arch/arch.h>
#include <arch/irq.h>
#include "up_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_savestate
*
* Description:
* This function saves the interrupt level context information in the
* TCB. This would just be a up_copystate but we have to handle one
* special case. In the case where the privilige level changes, the
* value of sp and ss will not be saved on stack by the interrupt handler.
* So, in that case, we will have to fudge those values here.
*
****************************************************************************/
void up_savestate(uint32_t *regs)
{
uint8_t cpl;
uint8_t rpl;
/* First, just copy all of the registers */
up_copystate(regs, current_regs);
/* The RES_SP and REG_SS values will not be saved by the interrupt handling
* logic if there is no change in privilege level. In that case, we will
* have to "fudge" those values here. For now, just overwrite the REG_SP
* and REG_SS values with what we believe to be correct. Obviously, this
* will have to change in the future to support multi-segment operation.
*
* Check for a change in privilege level.
*/
rpl = regs[REG_CS] & 3;
cpl = up_getcs() & 3;
DEBUGASSERT(rpl >= cpl);
if (rpl == cpl)
{
/* No priority change, SP and SS are not present in the stack frame.
*
* The value saved in the REG_ESP will be the stackpointer value prior to
* the execution of the PUSHA. It will point at REG_IRQNO.
*/
regs[REG_SP] = current_regs[REG_ESP] + 4*BOTTOM_NOPRIO;
regs[REG_SS] = up_getss();
}
else
{
DEBUGASSERT(regs[REG_SP] == current_regs[REG_ESP] + 4*BOTTOM_PRIO);
}
}

View File

@ -45,7 +45,7 @@ CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c \
up_initialize.c up_initialstate.c up_interruptcontext.c up_irq.c \
up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c up_regdump.c \
up_releasepending.c up_releasestack.c up_reprioritizertr.c \
up_sigdeliver.c up_schedulesigaction.c up_unblocktask.c \
up_savestate.c up_sigdeliver.c up_schedulesigaction.c up_unblocktask.c \
up_usestack.c
# Required QEMU files

View File

@ -106,26 +106,43 @@ up_fullcontextrestore:
cli
/* We now have everything we need from the old stack. Now get the new
* stack pointer.
/* Get the value of the stack pointer as it was when the pusha was
* executed the interrupt handler.
*/
movl (4*REG_SP)(%eax), %esp
/* Create an interrupt stack frame for the final iret.
*
* SP Before ->
* SS
* ESP
* EFLAGS
* CS
* SP After -> EIP
*
* IRET STACK
* PRIO CHANGE No PRIO CHANGE
* --------------- -----------------
* SP Before ->
* SS EFLAGS
* ESP CS
* EFLAGS -> EIP
* CS ...
* SP After -> EIP
*
* So, first check for a priority change.
*/
movl (4*REG_CS)(%eax), %edx
andl $3, %edx
mov %cs, %ebx
andl $3, %ebx
cmpb %bl, %dl
je .Lnopriochange
/* The priority will change... put SS and ESP on the stack */
mov (4*REG_SS)(%eax), %ebx
push %ebx
movl (4*REG_SP)(%eax), %ebx
push %ebx
.Lnopriochange:
movl (4*REG_EFLAGS)(%eax), %ebx
push %ebx
mov (4*REG_CS)(%eax), %ebx
@ -162,4 +179,3 @@ up_fullcontextrestore:
iret
.size up_fullcontextrestore, . - up_fullcontextrestore
.end

View File

@ -126,11 +126,26 @@ up_saveusercontext:
mov %cs, (4*REG_CS)(%eax)
mov %ds, (4*REG_DS)(%eax)
/* Save the value of SP as will be after we return (don't bother to save
* REG_ESP).
/* Save the value of SP as will be at the time of the IRET that will
* appear to be the return from this function.
*
*
* CURRENT STACK IRET STACK
* PRIO CHANGE No PRIO CHANGE
* --------------- --------------- -----------------
* EIP
* CS ...
* EFLAGS EIP
* -> ESP CS
* ESP->Return address SS EFLAGS
* Argument Argument Argument
*
* NOTE: We don't yet know the value for REG_ESP! That depends upon
* if a priority change occurs or not.
*/
leal 4(%esp), %ecx
leal -4(%esp), %ecx
movl %ecx, (4*REG_SP)(%eax)
/* Fetch the PC from the stack and save it in the save block */

View File

@ -266,7 +266,6 @@ irq_common:
popa /* Pops edi,esi,ebp... */
add $8, %esp /* Cleans up the pushed error code and pushed ISR number */
sti
iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
iret /* Pops 3-5 things at once: CS, EIP, EFLAGS (and maybe SS and ESP) */
.size irq_common, . - irq_common
.end