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:
p-szafonimateusz 2024-11-13 12:25:35 +01:00 committed by Xiang Xiao
parent 6f4f50e2fe
commit cfaeb74dd3
3 changed files with 53 additions and 176 deletions

View file

@ -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
*
****************************************************************************/

View file

@ -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);
}
/****************************************************************************

View file

@ -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: