mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 06:18:40 +08:00
arch/intel64: allow to attach handlers to ISR
arch/intel64: allow to attach handlers to ISR Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
This commit is contained in:
parent
6f4f50e2fe
commit
cfaeb74dd3
3 changed files with 53 additions and 176 deletions
|
@ -135,115 +135,12 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: isr_handler
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This gets called from ISR vector handling logic in broadwell_vectors.S
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
uint64_t *isr_handler(uint64_t *regs, uint64_t irq)
|
|
||||||
{
|
|
||||||
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
|
||||||
struct tcb_s *tcb;
|
|
||||||
|
|
||||||
if (*running_task != NULL)
|
|
||||||
{
|
|
||||||
(*running_task)->xcp.regs = regs;
|
|
||||||
}
|
|
||||||
|
|
||||||
board_autoled_on(LED_INIRQ);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
|
||||||
/* Doesn't return */
|
|
||||||
|
|
||||||
PANIC();
|
|
||||||
|
|
||||||
/* To keep the compiler happy */
|
|
||||||
|
|
||||||
return regs;
|
|
||||||
#else
|
|
||||||
|
|
||||||
DEBUGASSERT(!up_interrupt_context());
|
|
||||||
|
|
||||||
/* Set irq flag */
|
|
||||||
|
|
||||||
up_set_interrupt_context(true);
|
|
||||||
|
|
||||||
switch (irq)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
case 16:
|
|
||||||
__asm__ volatile("fnclex":::"memory");
|
|
||||||
nxsig_kill(this_task()->pid, SIGFPE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* Let's say, all ISR are asserted when REALLY BAD things happened.
|
|
||||||
* Don't even brother to recover, just dump the regs and PANIC.
|
|
||||||
*/
|
|
||||||
|
|
||||||
_alert("PANIC:\n");
|
|
||||||
_alert("Exception %" PRId64 " occurred "
|
|
||||||
"with error code %" PRId64 ":\n",
|
|
||||||
irq, regs[REG_ERRCODE]);
|
|
||||||
|
|
||||||
PANIC_WITH_REGS("panic", regs);
|
|
||||||
|
|
||||||
up_trash_cpu();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tcb = this_task();
|
|
||||||
|
|
||||||
/* Check for a context switch. If a context switch occurred, then
|
|
||||||
* g_current_regs will have a different value than it did on entry. If an
|
|
||||||
* interrupt level context switch has occurred, then the establish the
|
|
||||||
* correct address environment before returning from the interrupt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (*running_task != tcb)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_ARCH_ADDRENV
|
|
||||||
/* Make sure that the address environment for the previously
|
|
||||||
* running task is closed down gracefully (data caches dump,
|
|
||||||
* MMU flushed) and set up the address environment for the new
|
|
||||||
* thread at the head of the ready-to-run list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
addrenv_switch(NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Update scheduler parameters */
|
|
||||||
|
|
||||||
nxsched_suspend_scheduler(*running_task);
|
|
||||||
nxsched_resume_scheduler(tcb);
|
|
||||||
|
|
||||||
/* Record the new "running" task when context switch occurred.
|
|
||||||
* g_running_tasks[] is only used by assertion logic for reporting
|
|
||||||
* crashes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
*running_task = tcb;
|
|
||||||
|
|
||||||
/* Restore the cpu lock */
|
|
||||||
|
|
||||||
restore_critical_section(tcb, this_cpu());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear irq flag */
|
|
||||||
|
|
||||||
up_set_interrupt_context(false);
|
|
||||||
return tcb->xcp.regs;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: irq_handler
|
* Name: irq_handler
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This gets called from IRQ vector handling logic in intel64_vectors.S
|
* This gets called from IRQ or ISR vector handling logic in
|
||||||
|
* intel64_vectors.S
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,9 @@
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
#include <nuttx/spinlock.h>
|
#include <nuttx/spinlock.h>
|
||||||
|
#include <nuttx/signal.h>
|
||||||
|
|
||||||
|
#include "sched/sched.h"
|
||||||
#include "x86_64_internal.h"
|
#include "x86_64_internal.h"
|
||||||
#include "intel64_cpu.h"
|
#include "intel64_cpu.h"
|
||||||
#include "intel64.h"
|
#include "intel64.h"
|
||||||
|
@ -430,10 +432,6 @@ static inline void up_idtinit(void)
|
||||||
setidt(&g_idt_entries, sizeof(struct idt_entry_s) * NR_IRQS - 1);
|
setidt(&g_idt_entries, sizeof(struct idt_entry_s) * NR_IRQS - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: arm_color_intstack
|
* Name: arm_color_intstack
|
||||||
*
|
*
|
||||||
|
@ -453,6 +451,43 @@ static inline void x86_64_color_intstack(void)
|
||||||
# define x86_64_color_intstack()
|
# define x86_64_color_intstack()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: x86_64_fault_panic_isr
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int x86_64_fault_panic_isr(int irq, void *c, void *arg)
|
||||||
|
{
|
||||||
|
uint64_t *regs = (uint64_t *)running_regs();
|
||||||
|
|
||||||
|
/* Let's say, all ISR are asserted when REALLY BAD things happened.
|
||||||
|
* Don't even brother to recover, just dump the regs and PANIC.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_alert("PANIC:\n");
|
||||||
|
_alert("Exception %" PRId32 " occurred "
|
||||||
|
"with error code %" PRId64 ":\n",
|
||||||
|
irq, regs[REG_ERRCODE]);
|
||||||
|
|
||||||
|
PANIC_WITH_REGS("panic", regs);
|
||||||
|
|
||||||
|
up_trash_cpu();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: x86_64_fault_kill_isr
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int x86_64_fault_kill_isr(int irq, void *c, void *arg)
|
||||||
|
{
|
||||||
|
__asm__ volatile("fnclex":::"memory");
|
||||||
|
|
||||||
|
nxsig_kill(running_task()->pid, SIGFPE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -503,6 +538,15 @@ void up_irqinitialize(void)
|
||||||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
||||||
up_irq_restore(X86_64_RFLAGS_IF);
|
up_irq_restore(X86_64_RFLAGS_IF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Attach default handlers for faults */
|
||||||
|
|
||||||
|
irq_attach(ISR0, x86_64_fault_kill_isr, NULL);
|
||||||
|
irq_attach(ISR6, x86_64_fault_panic_isr, NULL);
|
||||||
|
irq_attach(ISR8, x86_64_fault_panic_isr, NULL);
|
||||||
|
irq_attach(ISR13, x86_64_fault_panic_isr, NULL);
|
||||||
|
irq_attach(ISR14, x86_64_fault_panic_isr, NULL);
|
||||||
|
irq_attach(ISR16, x86_64_fault_kill_isr, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
.globl irq_handler
|
.globl irq_handler
|
||||||
.globl isr_handler
|
|
||||||
.globl irq_xcp_regs
|
.globl irq_xcp_regs
|
||||||
.globl g_interrupt_stack
|
.globl g_interrupt_stack
|
||||||
.globl g_interrupt_stack_end
|
.globl g_interrupt_stack_end
|
||||||
|
@ -69,7 +68,7 @@ vector_isr\intno:
|
||||||
pushq %rdi
|
pushq %rdi
|
||||||
pushq %rsi
|
pushq %rsi
|
||||||
movq $\intno, %rsi /* INT Number is saved to 2nd parameter of function call */
|
movq $\intno, %rsi /* INT Number is saved to 2nd parameter of function call */
|
||||||
jmp isr_common /* Go to the common ISR handler code. */
|
jmp irq_common /* Go to the common IRQ handler code. */
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/* This macro creates a stub for an ISR which passes it's own
|
/* This macro creates a stub for an ISR which passes it's own
|
||||||
|
@ -87,7 +86,7 @@ vector_isr\intno:
|
||||||
pushq %rdi
|
pushq %rdi
|
||||||
pushq %rsi
|
pushq %rsi
|
||||||
movq $\intno, %rsi /* INT Number is saved to 2nd parameter of function call */
|
movq $\intno, %rsi /* INT Number is saved to 2nd parameter of function call */
|
||||||
jmp isr_common /* Go to the common ISR handler code. */
|
jmp irq_common /* Go to the common IRQ handler code. */
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/* This macro creates a stub for an IRQ - the first parameter is
|
/* This macro creates a stub for an IRQ - the first parameter is
|
||||||
|
@ -692,69 +691,6 @@ vector_isr\intno:
|
||||||
IRQ 255, IRQ255
|
IRQ 255, IRQ255
|
||||||
.balign 16
|
.balign 16
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: isr_common
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This is the common ISR logic. It saves the processor state, sets up for
|
|
||||||
* kernel mode segments, calls the C-level fault handler, and finally
|
|
||||||
* restores the stack frame.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
isr_common:
|
|
||||||
/* Already swap to the interrupt stack */
|
|
||||||
/* stack is automatically recovered by iretq using task state */
|
|
||||||
|
|
||||||
/* x86_64 don't have pusha, we have to do things manually */
|
|
||||||
/* RDI and RSI are pushed above for handling IRQ no */
|
|
||||||
pushq %rdx
|
|
||||||
pushq %rcx
|
|
||||||
pushq %r8
|
|
||||||
pushq %r9
|
|
||||||
|
|
||||||
pushq %r15
|
|
||||||
pushq %r14
|
|
||||||
pushq %r13
|
|
||||||
pushq %r12
|
|
||||||
pushq %r11
|
|
||||||
pushq %r10
|
|
||||||
pushq %rbp
|
|
||||||
pushq %rbx
|
|
||||||
pushq %rax
|
|
||||||
|
|
||||||
xor %rax, %rax /* Reset rax */
|
|
||||||
mov %ds, %ax /* Lower 16-bits of rax. */
|
|
||||||
pushq %rax /* Save the data segment descriptor */
|
|
||||||
mov %es, %ax /* Lower 16-bits of rax. */
|
|
||||||
pushq %rax /* Save the data segment descriptor */
|
|
||||||
mov %gs, %ax /* Lower 16-bits of rax. */
|
|
||||||
pushq %rax /* Save the data segment descriptor */
|
|
||||||
mov %fs, %ax /* Lower 16-bits of rax. */
|
|
||||||
pushq %rax /* Save the data segment descriptor */
|
|
||||||
|
|
||||||
/* Align to 64-bytes boundary */
|
|
||||||
leaq -(XMMAREA_REG_ALIGN * 8)(%rsp), %rsp
|
|
||||||
|
|
||||||
/* Save xmm registers */
|
|
||||||
leaq -XCPTCONTEXT_XMM_AREA_SIZE(%rsp), %rsp
|
|
||||||
#ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
|
||||||
fxsaveq (%rsp)
|
|
||||||
#else
|
|
||||||
movl $XSAVE_STATE_COMPONENTS, %eax
|
|
||||||
xor %edx, %edx
|
|
||||||
xsave (%rsp)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The current value of the SP points to the beginning of the state save
|
|
||||||
* structure. Save that in RDI as the input parameter to isr_handler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
mov %rsp, %rdi
|
|
||||||
call isr_handler
|
|
||||||
jmp .Lreturn
|
|
||||||
.size isr_common, . - isr_common
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: irq_common
|
* Name: irq_common
|
||||||
*
|
*
|
||||||
|
@ -850,7 +786,7 @@ irq_common:
|
||||||
add $8, %rsp
|
add $8, %rsp
|
||||||
popq %rdi
|
popq %rdi
|
||||||
|
|
||||||
/* The common return point for both isr_handler and irq_handler */
|
/* The common return point for irq_handler */
|
||||||
|
|
||||||
.Lreturn:
|
.Lreturn:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue