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:
parent
c4a13281a2
commit
663ea6d478
|
@ -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 8–15 */
|
||||
#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
|
||||
****************************************************************************/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue