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
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
*
|
||||
* 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 <nuttx/spinlock.h>
|
||||
#include <nuttx/signal.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "x86_64_internal.h"
|
||||
#include "intel64_cpu.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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_color_intstack
|
||||
*
|
||||
|
@ -453,6 +451,43 @@ static inline void x86_64_color_intstack(void)
|
|||
# define x86_64_color_intstack()
|
||||
#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
|
||||
****************************************************************************/
|
||||
|
@ -503,6 +538,15 @@ void up_irqinitialize(void)
|
|||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
||||
up_irq_restore(X86_64_RFLAGS_IF);
|
||||
#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 isr_handler
|
||||
.globl irq_xcp_regs
|
||||
.globl g_interrupt_stack
|
||||
.globl g_interrupt_stack_end
|
||||
|
@ -69,7 +68,7 @@ vector_isr\intno:
|
|||
pushq %rdi
|
||||
pushq %rsi
|
||||
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
|
||||
|
||||
/* This macro creates a stub for an ISR which passes it's own
|
||||
|
@ -87,7 +86,7 @@ vector_isr\intno:
|
|||
pushq %rdi
|
||||
pushq %rsi
|
||||
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
|
||||
|
||||
/* This macro creates a stub for an IRQ - the first parameter is
|
||||
|
@ -692,69 +691,6 @@ vector_isr\intno:
|
|||
IRQ 255, IRQ255
|
||||
.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
|
||||
*
|
||||
|
@ -850,7 +786,7 @@ irq_common:
|
|||
add $8, %rsp
|
||||
popq %rdi
|
||||
|
||||
/* The common return point for both isr_handler and irq_handler */
|
||||
/* The common return point for irq_handler */
|
||||
|
||||
.Lreturn:
|
||||
|
||||
|
|
Loading…
Reference in a new issue