From 5744c62443507a88d280c9f2369254c27216b6c0 Mon Sep 17 00:00:00 2001 From: ligd Date: Tue, 13 Dec 2022 21:39:22 +0800 Subject: [PATCH] sim: set timer irq as real timer Signed-off-by: ligd --- arch/sim/include/irq.h | 1 + arch/sim/include/setjmp.h | 17 +++++++++++++---- arch/sim/src/sim/posix/sim_hostirq.c | 17 +++++++++++++++++ arch/sim/src/sim/sim_doirq.c | 9 ++------- arch/sim/src/sim/sim_exit.c | 3 ++- arch/sim/src/sim/sim_internal.h | 23 +++++++++++++++++++++++ arch/sim/src/sim/sim_switchcontext.c | 9 ++++----- 7 files changed, 62 insertions(+), 17 deletions(-) diff --git a/arch/sim/include/irq.h b/arch/sim/include/irq.h index 5d1b343f81..93397018d6 100644 --- a/arch/sim/include/irq.h +++ b/arch/sim/include/irq.h @@ -115,6 +115,7 @@ int up_cpu_index(void); * leave_critical section(), are probably what you really want. */ +irqstate_t up_irq_flags(void); irqstate_t up_irq_save(void); void up_irq_restore(irqstate_t flags); diff --git a/arch/sim/include/setjmp.h b/arch/sim/include/setjmp.h index 20f8bdfbfe..7e510ef005 100644 --- a/arch/sim/include/setjmp.h +++ b/arch/sim/include/setjmp.h @@ -37,7 +37,7 @@ #if defined(CONFIG_HOST_X86_64) && !defined(CONFIG_SIM_M32) /* Storage order: %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, %rip */ -# define XCPTCONTEXT_REGS 8 +# define XCPTCONTEXT_REGS 9 # define XCPTCONTEXT_SIZE (8 * XCPTCONTEXT_REGS) # ifdef __ASSEMBLY__ @@ -50,6 +50,7 @@ # define JB_R14 (5*8) # define JB_R15 (6*8) # define JB_RSI (7*8) +# define JB_FLAG (8*8) # else @@ -61,6 +62,7 @@ # define JB_R14 (5) # define JB_R15 (6) # define JB_RSI (7) +# define JB_FLAG (8) # endif /* __ASSEMBLY__ */ @@ -73,7 +75,7 @@ #elif defined(CONFIG_HOST_X86) || defined(CONFIG_SIM_M32) /* Storage order: %ebx, %esi, %edi, %ebp, sp, and return PC */ -# define XCPTCONTEXT_REGS 6 +# define XCPTCONTEXT_REGS (8) # define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) # ifdef __ASSEMBLY__ @@ -84,6 +86,8 @@ # define JB_EBP (3*4) # define JB_SP (4*4) # define JB_PC (5*4) +# define JB_FLAG (6*4) +# define JB_FLAG1 (7*4) # else @@ -93,6 +97,8 @@ # define JB_EBP (3) # define JB_SP (4) # define JB_PC (5) +# define JB_FLAG (6) +# define JB_FLAG1 (7) # endif /* __ASSEMBLY__ */ @@ -102,16 +108,18 @@ #elif defined(CONFIG_HOST_ARM) -# define XCPTCONTEXT_REGS 16 +# define XCPTCONTEXT_REGS 18 # define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) # define JB_FP 7 # define JB_SP 8 # define JB_PC 9 +# define JB_FLAG 16 +# define JB_FLAG1 17 #elif defined(CONFIG_HOST_ARM64) -# define XCPTCONTEXT_REGS 32 +# define XCPTCONTEXT_REGS 33 # define XCPTCONTEXT_SIZE (8 * XCPTCONTEXT_REGS) # ifdef __ASSEMBLY__ @@ -134,6 +142,7 @@ # define JB_PC (11) # define JB_FP (12) # define JB_SP (13) +# define JB_FLAG (32) # endif /* __ASSEMBLY__ */ diff --git a/arch/sim/src/sim/posix/sim_hostirq.c b/arch/sim/src/sim/posix/sim_hostirq.c index 1426b0e3a0..8b6086c3cd 100644 --- a/arch/sim/src/sim/posix/sim_hostirq.c +++ b/arch/sim/src/sim/posix/sim_hostirq.c @@ -62,6 +62,23 @@ static void up_handle_irq(int irq, siginfo_t *info, void *context) * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_irq_flags + * + * Description: + * Get the current irq flags + * + ****************************************************************************/ + +uint64_t up_irq_flags(void) +{ + union sigset_u omask; + + pthread_sigmask(SIG_SETMASK, NULL, &omask.sigset); + + return omask.flags; +} + /**************************************************************************** * Name: up_irq_save * diff --git a/arch/sim/src/sim/sim_doirq.c b/arch/sim/src/sim/sim_doirq.c index 2c23be0182..a55b984e61 100644 --- a/arch/sim/src/sim/sim_doirq.c +++ b/arch/sim/src/sim/sim_doirq.c @@ -48,11 +48,8 @@ void *sim_doirq(int irq, void *context) * CURRENT_REGS is also used to manage interrupt level context switches. */ -#ifdef CONFIG_SMP - if (setjmp(regs) == 0) + if (sim_saveusercontext(regs) == 0) { -#endif - CURRENT_REGS = regs; /* Deliver the IRQ */ @@ -74,12 +71,10 @@ void *sim_doirq(int irq, void *context) CURRENT_REGS = NULL; -#ifdef CONFIG_SMP /* Then switch contexts */ - longjmp(regs, 1); + sim_fullcontextrestore(regs); } -#endif return regs; } diff --git a/arch/sim/src/sim/sim_exit.c b/arch/sim/src/sim/sim_exit.c index 255e0b3d4e..fe4be9fa14 100644 --- a/arch/sim/src/sim/sim_exit.c +++ b/arch/sim/src/sim/sim_exit.c @@ -31,6 +31,7 @@ #include "task/task.h" #include "sched/sched.h" +#include "sim_internal.h" /**************************************************************************** * Public Functions @@ -82,7 +83,7 @@ void up_exit(int status) /* Then switch contexts */ - longjmp(tcb->xcp.regs, 1); + sim_fullcontextrestore(tcb->xcp.regs); /* The function does not return */ diff --git a/arch/sim/src/sim/sim_internal.h b/arch/sim/src/sim/sim_internal.h index 037bc27300..3805b5770c 100644 --- a/arch/sim/src/sim/sim_internal.h +++ b/arch/sim/src/sim/sim_internal.h @@ -85,6 +85,29 @@ #define sim_savestate(regs) sim_copyfullstate(regs, (xcpt_reg_t *)CURRENT_REGS) #define sim_restorestate(regs) (CURRENT_REGS = regs) +#define sim_saveusercontext(saveregs) \ + ({ \ + irqstate_t flags = up_irq_flags(); \ + uint32_t *env = (uint32_t *)saveregs + JB_FLAG; \ + int ret; \ + \ + env[0] = flags & UINT32_MAX; \ + env[1] = (flags >> 32) & UINT32_MAX; \ + \ + ret = setjmp(saveregs); \ + ret; \ + }) +#define sim_fullcontextrestore(restoreregs) \ + do \ + { \ + xcpt_reg_t *env = restoreregs; \ + uint32_t *flags = (uint32_t *)&env[JB_FLAG]; \ + \ + up_irq_restore(((uint64_t)flags[1] << 32) | flags[0]); \ + longjmp(env, 1); \ + } \ + while (0) + /* File System Definitions **************************************************/ /* These definitions characterize the compressed filesystem image */ diff --git a/arch/sim/src/sim/sim_switchcontext.c b/arch/sim/src/sim/sim_switchcontext.c index a3dee9c937..3ecb284d71 100644 --- a/arch/sim/src/sim/sim_switchcontext.c +++ b/arch/sim/src/sim/sim_switchcontext.c @@ -31,7 +31,6 @@ #include #include "clock/clock.h" -#include "sched/sched.h" #include "sim_internal.h" /**************************************************************************** @@ -84,11 +83,11 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb) } /* Copy the exception context into the TCB of the task that was - * previously active. if setjmp returns a non-zero value, then - * this is really the previously running task restarting! + * previously active. if sim_saveusercontext returns a non-zero value, + * then this is really the previously running task restarting! */ - else if (!setjmp(rtcb->xcp.regs)) + else if (!sim_saveusercontext(rtcb->xcp.regs)) { sinfo("New Active Task TCB=%p\n", tcb); @@ -102,7 +101,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb) /* Then switch contexts */ - longjmp(tcb->xcp.regs, 1); + sim_fullcontextrestore(tcb->xcp.regs); } else {