5.3.5 ipipe_flags之TIP_USERINTRET

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-优快云博客

原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

5.3.5 ipipe_flags之TIP_USERINTRET

Xenomai实时任务可能会因为使用Linux系统调用而切换到root domain即Linux中运行,在这个过程中,会给ipipe_flags置位TIP_USERINTRET。

pipeline_leave_oob_prepare

->ipipe_enable_user_intret_notifier

当Xenomai实时任务运行在root domain中时,如果被el0_irq中断,在返回用户空间时,会出现如下图的复杂情况。

771be036b966435aa7b5fa2e6efe2822.png

第1步,在el0_irq通过b ret_to_user_nocheck跳转到此处,关闭daif共4个中断屏蔽标识。在此之前da_f都是打开状态,而__i_是屏蔽状态。

第2步,检查TSK_TI_FLAGS中是否设置了_TIF_WORK_MASK标记。TSK_TI_FLAGS定义在arch/arm64/kernel/asm-offsets.c:

DEFINE(TSK_TI_FLAGS,        offsetof(struct task_struct, thread_info.flags));

_TIF_WORK_MASK定义在arch/arm64/include/asm/thread_info.h:

#define _TIF_WORK_MASK         (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \

                             _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \

                             _TIF_UPROBE | _TIF_FSCHECK)

如果TSK_TI_FLAGS与_TIF_WORK_MASK按位与运算位0,则直接跳转到第5步。否则跳转到第3步。

第3步,执行do_notify_resume函数,该函数通过判断TSK_TI_FLAGS来执行具体逻辑。最值得一提的是,如果匹配了_TIF_NEED_RESCHED,则调用schedule()执行任务切换。

第4步,在第3步中,可能将第2步中的x1寄存器重新赋值,所以需要对x1寄存器按照第2步进行初始化,为进入第5步做准备。

第5步,调用enable_step_ts,检查TSK_TI_FLAGS中是否设置了TIF_SINGLESTEP标记。如果是,则置位MDSCR.SS。此处和kernel_entry中调用disable_step_tsk是相对的。因为在第1步中已经关闭了debug中断,所以此时置位MDSCR.SS并不会真正使能Single Step。

TSK_TI_FLAGS定义在arch/arm64/kernel/asm-offsets.c:

DEFINE(TSK_TI_FLAGS,        offsetof(struct task_struct, thread_info.flags));

enable_step_tsk定义在arch/arm64/include/asm/assembler.h:

       .macro    enable_step_tsk, flgs, tmp

       tbz  \flgs, #TIF_SINGLESTEP, 9990f

       mrs \tmp, mdscr_el1

       orr   \tmp, \tmp, #DBG_MDSCR_SS

       msr mdscr_el1, \tmp

9990:

       .endm

第6步,检查TSK_TI_IPIPE中是否设置了_TIP_USERINTRET标记。TSK_TI_IPIPE定义在arch/arm64/kernel/asm-offsets.c:

DEFINE(TSK_TI_IPIPE,           offsetof(struct task_struct, thread_info.ipipe_flags));

_TIP_USERINTRET定义在arch/arm64/include/asm/thread_info.h。根据注释,它用于在异常返回用户空间之前,通知实时内核Xenomai。

#define TIP_USERINTRET     3     /* Notify on IRQ/trap return to root userspace */

#define _TIP_USERINTRET   (1 << TIP_USERINTRET)

如果仅仅打上了I-pipe Patch,那么ipipe_kevent_hook不会对_TIP_USERINTRET做任何处理,调用关系如下:

__ipipe_notify_user_intreturn [kernel/ipipe/core.c]

->__ipipe_notify_kevent

-> ipipe_kevent_hook [kernel/ipipe/core.c]

->return 0

如果安装了Xenomai,则定义新的ipipe_kevent_hook函数,调用关系如下,且是同步调用:

__ipipe_notify_user_intreturn [kernel/ipipe/core.c]

->__ipipe_notify_kevent

    -> ipipe_kevent_hook [kernel/xenomai/pipeline/kevents.c]

->handle_user_return

->ipipe_disable_user_intret_notifier()

->cobalt_handle_user_return

    -> xnthread_harden

在cobalt_handle_user_return的主体部分,依赖于对XNCONTHI的检查,来决定是否调用xnthread_harden。Xenomai中调用xnthread_set_info(curr, XNCONTHI)来设置XNCONTHI标记的地方,均有debuging(单步或ptrace)相关。

#define XNCONTHI  0x00000200 /**< Continue in primary mode after debugging */

       因此,Xenomai使用_TIP_USERINTRET只用于处理处于debugging过程中的任务。如果任务处于debugging状态,Xenomai认为此种情况下不需在乎实时性,无需自己处理,会将任务切换到root域交给Linux处理。

最终从__ipipe_notify_user_intreturn返回时,通过return !ipipe_root_p来检查当前是root域还是head域,核心部分在xnthread_harden中。

xnthread_harden在tsk_linux_root切换到head域之前,调用signal_pending检查TIF_SIGPENDING。如果检查到了TIF_SIGPENDING,说明任务中有singal信号待处理,那么xnthread_harden直接返回,任务依然在root域。

xnthread_harden在tsk_linux_root切换到head域之后,再次调用signal_pending检查TIF_SIGPENDING。如果没有检查到TIF_SIGPENDING,直接返回,此时切换到了root域。如果检查到了TIF_SIGPENDING,说明任务中有singal信号待处理,那么xnthread_harden调用xnthread_relax切换任务回到root域。

signal_pending函数定义在include/linux/sched/signal.h:

static inline int signal_pending(struct task_struct *p)

{

    return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING));

}

从xnthread_harden返回后,如果切换到了head域,则__ipipe_notify_user_intreturn的返回值return !ipipe_root_p为0,跳转到第7步,执行kernel_exit 0,返回用户层。

从xnthread_harden返回后,如果依然在root域,说明任务中有singal信号待处理,依次跳转到2->3->4->5->6->7(如图中虚线所示),最终执行kernel_exit 0,返回用户层。第2步中,因为TSK_TI_FLAGS 中必然有TIF_SIGPENDING,所以一定会跳转到第3步。第6步中,因为之前在第8步中已经关闭了TIP_USERINTRET,所以一定会跳转到第7步。

关闭TIP_USERINTRET的过程:__ipipe_notify_user_intreturn->__ipipe_notify_kevent-> ipipe_kevent_hook -> handle_user_return->ipipe_disable_user_intret_notifier()

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-优快云博客

原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值