diff --git a/articles/20220907-riscv-irq-analysis-part5-generic-entry-backgroud-and-status.md b/articles/20220907-riscv-irq-analysis-part5-generic-entry-backgroud-and-status.md
new file mode 100644
index 0000000000000000000000000000000000000000..19e466780ef2ee1b431bb4ffec7d8cff94a7ae2c
--- /dev/null
+++ b/articles/20220907-riscv-irq-analysis-part5-generic-entry-backgroud-and-status.md
@@ -0,0 +1,440 @@
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.1-rc2 - [autocorrect]
+> Author: 牛工 - 通天塔 985400330@qq.com
+> Date: 2022/09/07
+> Revisor: Falcon ; iOSDevLog
+> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
+> Proposal: [【老师提案】Linux IRQ 子系统分析 · Issue #I5E5EP · 泰晓科技/RISCV-Linux - Gitee.com](https://gitee.com/tinylab/riscv-linux/issues/I5E5EP)
+> Sponsor: PLCT Lab, ISCAS
+
+# Generic entry RISC-V 补丁分析
+
+## 前言
+
+郭老师在 RISC-V 社区中的新补丁 [[PATCH V3 0/7] riscv: Add GENERIC_ENTRY, irq stack support (kernel.org)][005]
+
+补丁描述如下:
+
+> The patches convert RISC-V to use the generic entry infrastructure from kernel/entry/\*.Add independent irq stacks (IRQ_STACKS) for percpu to prevent kernel stack overflows. Add the HAVE_SOFTIRQ_ON_OWN_STACK feature for the IRQ_STACKS config.
+
+补丁将 RISC-V 转换为使用 `kernel/entry/*` 的结构体。为每个 CPU 添加独立的 irq 堆栈(IRQ_STACKS),以防止内核堆栈溢出。为 IRQ_STACKS 配置添加 HAVE_SOFTIRQ_ON_OWN_STACK 特性。
+
+RISC-V 引入了新的特性 Generic entry,本篇文章将对该特性的背景、好处、各架构的支持情况、RISC-V 的迁移情况进行讲述。
+
+## 背景
+
+在引入该补丁之前,RISC-V 的关于中断的处理很多都是自定义实现了,没有使用内核提供的一些好的中断处理接口,导致代码比较冗余。
+
+还有对于 syscall 的处理函数也不够简洁可读,郭老师对于此处的代码进行了优化。
+
+补丁 `[PATCH V3 4/7] riscv: convert to generic entry` 是进行 generic entry 接口转换的一个关键补丁。
+
+补丁中的描述:
+
+```
+ - More clear entry.S with handle_exception and ret_from_exception
+ - Get rid of complex custom signal implementation
+ - More readable syscall procedure
+ - Little modification on ret_from_fork & ret_from_kernel_thread
+ - Wrap with irqentry_enter/exit and syscall_enter/exit_from_user_mode
+ - Use the standard preemption code instead of custom
+```
+
+- 使 `handle_exception` 和 `ret_from_exception` 在 entry.S 中更清晰
+- 摆脱复杂的自定义信号实现
+- 更可读的 syscall 过程
+- 对 `ret_from_fork` 和 `ret_from_kernel_thread` 进行了一些修改
+- 新增 `irqentry_enter/exit` 和 `syscall_enter/exit_from_user_mode` 调用
+- 使用标准抢占代码,不使用自定义抢占代码
+
+## 好处
+
+基于之前的代码对本次新增的补丁的好处进行深入分析。
+
+```
+ arch/riscv/Kconfig | 1 +
+ arch/riscv/include/asm/csr.h | 1 -
+ arch/riscv/include/asm/entry-common.h | 8 +
+ arch/riscv/include/asm/ptrace.h | 10 +-
+ arch/riscv/include/asm/stacktrace.h | 5 +
+ arch/riscv/include/asm/syscall.h | 6 +
+ arch/riscv/include/asm/thread_info.h | 13 +-
+ arch/riscv/kernel/entry.S | 228 +++-----------------------
+ arch/riscv/kernel/irq.c | 15 ++
+ arch/riscv/kernel/ptrace.c | 40 -----
+ arch/riscv/kernel/signal.c | 21 +--
+ arch/riscv/kernel/sys_riscv.c | 27 +++
+ arch/riscv/kernel/traps.c | 11 ++
+ arch/riscv/mm/fault.c | 12 +-
+ 14 files changed, 117 insertions(+), 281 deletions(-)
+ create mode 100644 arch/riscv/include/asm/entry-common.h
+```
+
+通过补丁可以看到本次删除掉了很多的代码,使代码更加简洁了。
+
+本次改动主要涉及 4 个部分:抢占式中断处理流程、上下文保存、do_riscv_irq 函数的实现、syscall 处理函数的实现。
+
+之前我有篇文章是写的中断的处理流程,[RISC-V 中断子系统分析——CPU 中断处理][002] 文章写了关于 `handle_exception` 的分析。该函数是产生异常时的跳转地址,主要用于中断处理、异常处理、syscall 处理、保护现场、恢复现场。
+
+### 抢占式中断处理流程改动
+
+此处就是对于 **标准抢占代码** 替代 **自定义抢占代码** 的相关处理。
+
+当前的修改后:
+
+```assembly
+@@ -14,10 +14,6 @@
+ #include
+ #include
+/* 当未设置抢占时,定义 resume_kernel 函数为 restore_all */
+-#if !IS_ENABLED(CONFIG_PREEMPTION)
+-.set resume_kernel, restore_all
+-#endif
+-
+ ENTRY(handle_exception)
+```
+
+此处删除了如果未使能抢占的一个配置。
+
+#### 自定义的抢占代码
+
+当定义了抢占宏 `CONFIG_PREEMPTION` 时
+
+```assembly
+/* arch/riscv/kernel/entry.S */
+/* version:Linux 6.0-rc4 */
+ret_from_exception:
+ REG_L s0, PT_STATUS(sp)
+ csrc CSR_STATUS, SR_IE
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call __trace_hardirqs_off
+#endif
+#ifdef CONFIG_RISCV_M_MODE
+ /* the MPP value is too large to be used as an immediate arg for addi */
+ li t0, SR_MPP
+ and s0, s0, t0
+#else
+ andi s0, s0, SR_SPP
+#endif
+ bnez s0, resume_kernel
+```
+
+当使能了抢占之后,执行的是以下代码。
+
+```assembly
+/* arch/riscv/kernel/entry.S */
+/* version:Linux 6.0-rc4 */
+#if IS_ENABLED(CONFIG_PREEMPTION)
+resume_kernel:
+/* 判断此处是否需要进行抢占式的中断处理 */
+ REG_L s0, TASK_TI_PREEMPT_COUNT(tp)
+ bnez s0, restore_all
+ REG_L s0, TASK_TI_FLAGS(tp)
+ andi s0, s0, _TIF_NEED_RESCHED
+ beqz s0, restore_all
+ call preempt_schedule_irq /*符合抢占要求,call 抢占调度函数 */
+ j restore_all
+#endif
+```
+
+#### 标准抢占代码
+
+上一小节描述了自定义抢占代码的实现,改动之后,在 entry.S 中的抢占相关的判断等代码被删除,不再对抢占进行处理。
+
+标准的抢占代码如下代码:
+
+```c
+// arch\riscv\kernel\irq.c
+//version:https://github.com/guoren83/linux/tree/generic_entry_v3
+asmlinkage void noinstr do_riscv_irq(struct pt_regs *regs)
+{
+...
+ irqentry_exit(regs, state);
+}
+```
+
+```c
+// kernel\entry\common.c
+//version:https://github.com/guoren83/linux/tree/generic_entry_v3
+noinstr void irqentry_exit(struct pt_regs *regs, irqentry_state_t state)
+{
+...
+ if (IS_ENABLED(CONFIG_PREEMPTION))
+ irqentry_exit_cond_resched();
+...
+}
+```
+
+```c
+// kernel\entry\common.c
+//version:https://github.com/guoren83/linux/tree/generic_entry_v3
+void raw_irqentry_exit_cond_resched(void)
+{
+ if (!preempt_count()) {
+ ...
+ preempt_schedule_irq();
+ }
+}
+```
+
+之前的抢占相关的代码是在汇编文件 `arch/riscv/kernel/entry.S` 中进行实现的,未使用内核现有的接口。
+
+新增了 `do_riscv_irq` 之后,调用了公共函数 `irqentry_exit`,完成了抢占检测和调度的工作。
+
+充分利用了内核现有接口,使得 RISC-V 代码更加整洁。
+
+### 上下文保存改动
+
+```assembly
+@@ -106,19 +102,8 @@ _save_context:
+ .option norelax
+ la gp, __global_pointer$
+ .option pop
+-
+-#ifdef CONFIG_TRACE_IRQFLAGS
+- call __trace_hardirqs_off
+-#endif
+-
+-#ifdef CONFIG_CONTEXT_TRACKING_USER
+- /* If previous state is in user mode, call user_exit_callable(). */
+- li a0, SR_PP
+- and a0, s1, a0
+- bnez a0, skip_context_tracking
+- call user_exit_callable
+-skip_context_tracking: /* 删除了跳过上下文切换追踪的函数标签 */
+-#endif
++ move a0, sp /* pt_regs */
++ la ra, ret_from_exception
+
+ /*
+ * MSB of cause differentiates between
+```
+
+删除了关于 `CONFIG_TRACE_IRQFLAGS` 和 `CONFIG_CONTEXT_TRACKING_USER` 的相关调用,用于中断的调试。新增代码设置返回地址 `ret_from_exception`。
+
+```assembly
+@@ -126,134 +111,26 @@ skip_context_tracking:
+ */
+ bge s4, zero, 1f
+
+- la ra, ret_from_exception /*代码上移,删除了跳过上下文追踪标签 */
+-
+ /* Handle interrupts */
+- move a0, sp /* pt_regs */
+- la a1, generic_handle_arch_irq
+- jr a1
++ tail do_riscv_irq/*更换了中断处理函数 */
+
+/* 以下关于异常的代码被删除 */
+ 1:
+- /*
+- * Exceptions run with interrupts enabled or disabled depending on the
+- * state of SR_PIE in m/sstatus.
+- */
+- andi t0, s1, SR_PIE
+- beqz t0, 1f
+- /* kprobes, entered via ebreak, must have interrupts disabled. */
+- li t0, EXC_BREAKPOINT
+- beq s4, t0, 1f
+-#ifdef CONFIG_TRACE_IRQFLAGS
+- call __trace_hardirqs_on
+-#endif
+- csrs CSR_STATUS, SR_IE
+-
+-1:
+- la ra, ret_from_exception
+- /* Handle syscalls */
+- li t0, EXC_SYSCALL
+- beq s4, t0, handle_syscall
+-
+/* 以上关于处理异常的代码被删除 */
+
+/* 处理一些其他的异常 */
+ /* Handle other exceptions */
+ slli t0, s4, RISCV_LGPTR
+ la t1, excp_vect_table
+ la t2, excp_vect_table_end
+- move a0, sp /* pt_regs */
+ add t0, t1, t0
+ /* Check if exception code lies within bounds */
+- bgeu t0, t2, 1f
++ bgeu t0, t2, 2f/*修改 t0>t2 之后的 PC 指针偏移,此处不明白为什么从 1f->2f */
+ REG_L t0, 0(t0)
+ jr t0 /*跳转到异常代码处理地址 */
+-1:
++2:
+ tail do_trap_unknown
++END(handle_exception)
+/* 再往下则删除了 syscall 的相关处理代码 */
+```
+
+以上修改了中断的处理流程,改变了中断处理函数,删除了异常处理代码,修改了出现异常代码时的 PC 指针地址,删除了 syscall 的相关处理代码。
+
+删除了汇编部分的 syscall 相关代码,放到了以下位置进行处理,`do_sys_ecall_u` 函数在 `arch/riscv/kernel/sys_riscv.c` 代码中进行了实现,提高了代码可读性。
+
+```assembly
+@@ -582,7 +398,7 @@ ENTRY(excp_vect_table)
+ RISCV_PTR do_trap_load_fault
+ RISCV_PTR do_trap_store_misaligned
+ RISCV_PTR do_trap_store_fault
+- RISCV_PTR do_trap_ecall_u /* system call, gets intercepted */
++ RISCV_PTR do_sys_ecall_u /* system call */
+ RISCV_PTR do_trap_ecall_s
+ RISCV_PTR do_trap_unknown
+ RISCV_PTR do_trap_ecall_m
+```
+
+### do_riscv_irq 函数实现
+
+之前在 [RISC-V 中断子系统分析——PLIC 中断处理][003] 这篇文章中,对中断处理的流程进行了分析。
+
+```
+[nfk test] goldfish_rtc_interrupt
+CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.17.0-dirty #85
+Hardware name: riscv-virtio,qemu (DT)
+Call Trace:
+[] dump_backtrace+0x1c/0x24
+[] show_stack+0x2c/0x38
+[] dump_stack_lvl+0x40/0x58
+[] dump_stack+0x14/0x1c
+[] goldfish_rtc_interrupt+0x22/0x74
+[] __handle_irq_event_percpu+0x52/0xe0
+[] handle_irq_event_percpu+0x12/0x4e
+[] handle_irq_event+0x5e/0x94
+[] handle_fasteoi_irq+0xac/0x18e
+[] generic_handle_domain_irq+0x28/0x3a
+[] plic_handle_irq+0x8a/0xec
+[] generic_handle_domain_irq+0x28/0x3a
+[] riscv_intc_irq+0x34/0x5c
+[] generic_handle_arch_irq+0x4a/0x74
+[] ret_from_exception+0x0/0xc
+[] rcu_idle_enter+0x10/0x18
+```
+
+以上是之前的中断处理流程,当前补丁修改了 `generic_handle_domain_irq` 为 `do_riscv_irq`。
+
+```c
+/*
+ * generic_handle_arch_irq - root irq handler for architectures which do no
+ * entry accounting themselves
+ * @regs: Register file coming from the low-level handling code
+ */
+```
+
+根据 `generic_handle_domain_irq` 的注释可知,该函数是架构没有自己的中断处理入口的时候才会使用的一个接口。现在 RISC-V 已经有了自己的中断处理接口 `do_riscv_irq`。
+
+`````c
+diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
+index 7207fa08d78f..24c2e1bd756a 100644
+--- a/arch/riscv/kernel/irq.c
++++ b/arch/riscv/kernel/irq.c
+@@ -5,6 +5,7 @@
+
+ * Copyright (C) 2018 Christoph Hellwig
+ */
+
++#include
+ #include
+ #include
+ #include
+@@ -22,3 +23,17 @@ void __init init_IRQ(void)
+ if (!handle_arch_irq)
+ panic("No interrupt controller found.");
+ }
++
++asmlinkage void noinstr do_riscv_irq(struct pt_regs *regs)
++{
+// 该函数在 [PATCH V3 5/7] riscv: Support HAVE_IRQ_EXIT_ON_IRQ_STACK 又进行了修改
++ struct pt_regs *old_regs;
++ irqentry_state_t state = irqentry_enter(regs); // 新增入口状态获取
++
++ irq_enter_rcu(); // 接口
++ old_regs = set_irq_regs(regs); // 与 generic_handle_arch_irq 一致
++ handle_arch_irq(regs); // 与 generic_handle_arch_irq 一致
++ set_irq_regs(old_regs); // 与 generic_handle_arch_irq 一致
++ irq_exit_rcu();
+ +
++ irqentry_exit(regs, state); // 新增状态+推出
+ +}
+`````
+
+[Entry/exit handling for exceptions, interrupts, syscalls and KVM — The Linux Kernel documentation][001] 中描述了关于 `irqentry_exit` 和 `irqentry_enter` 的作用。
+
+### syscall 修改
+
+补丁删除了 `arch/riscv/kernel/ptrace.c` 中 syscall 相关的代码,在 `arch/riscv/kernel/sys_riscv.c` 中新增了 `do_sys_ecall_u` 函数,用于处理 syscall,**这使 syscall 的调用过程更加的可读。**
+
+在 `arch/riscv/kernel/traps.c` 和 `arch/riscv/mm/fault.c` 中新增了关于 `irqentry_exit` 和 `irqentry_enter` 的调用。
+
+## 各架构的支持
+
+各架构对于 Generic entry 的支持情况主要看对于 `kernel\entry\common.c` 的使用情况。
+
+
+
+当前使用 `irqentry_exit` 函数的架构主要有:loongarch、RISC-V、s390、x86;
+
+arm64 架构实现了自己的 entry-common.c,与公共接口不同。
+
+该接口是在 2020 年第一次引入内核,目前在各个架构上的支持还不完善,需要大家共同完成。
+
+```
+commit 142781e108b13b2b0e8f035cfb5bfbbc8f14d887
+Author: Thomas Gleixner
+Date: Wed Jul 22 23:59:56 2020 +0200
+
+ entry: Provide generic syscall entry functionality
+
+ On syscall entry certain work needs to be done:
+
+ - Establish state (lockdep, context tracking, tracing)
+ - Conditional work (ptrace, seccomp, audit...)
+
+ This code is needlessly duplicated and different in all
+ architectures.
+
+ Provide a generic version based on the x86 implementation which has all the
+ RCU and instrumentation bits right.
+
+ As interrupt/exception entry from user space needs parts of the same
+ functionality, provide a function for this as well.
+
+ syscall_enter_from_user_mode() and irqentry_enter_from_user_mode() must be
+ called right after the low level ASM entry. The calling code must be
+ non-instrumentable. After the functions returns state is correct and the
+ subsequent functions can be instrumented.
+
+ Signed-off-by: Thomas Gleixner
+ Acked-by: Kees Cook
+ Link: https://lkml.kernel.org/r/20200722220519.513463269@linutronix.de
+
+ kernel/entry/common.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 88 insertions(+)
+```
+
+## 迁移情况
+
+[[PATCH V5 00/11\] riscv: Add GENERIC_ENTRY support and related features - guoren (kernel.org)][004]
+
+当前郭老师已经升级补丁至 V5,还在持续进行中。
+
+## 小结
+
+本文分析了郭老师在 V3 版本上的补丁提交,对 generic entry 的背景、好处、各架构的支持情况进行了讲述,希望大家能根据本文加深对中断处理的理解,后续我会继续跟进郭老师的补丁提交情况,向大佬学习!
+
+## 参考资料
+
+[[PATCH V3 0/7] riscv: Add GENERIC_ENTRY, irq stack support (kernel.org)][005]
+
+[[PATCH V5 00/11] riscv: Add GENERIC_ENTRY support and related features - guoren (kernel.org)][004]
+
+[Entry/exit handling for exceptions, interrupts, syscalls and KVM — The Linux Kernel documentation][001]
+
+[RISC-V 中断子系统分析——CPU 中断处理][002]
+
+[RISC-V 中断子系统分析——CPU 中断处理][002]
+
+[001]: https://docs.kernel.org/core-api/entry.html
+[002]: https://gitee.com/tinylab/riscv-linux/blob/master/articles/20220712-riscv-irq-analysis-part3-Interrupt-handling-cpu.md
+[003]: https://gitee.com/tinylab/riscv-linux/blob/master/articles/20220919-riscv-irq-analysis-part2-interrupt-handling-plic.md
+[004]: https://lore.kernel.org/all/20220918155246.1203293-1-guoren@kernel.org/
+[005]: https://lore.kernel.org/linux-riscv/CAJF2gTS0Oe7AHcNf1+uGHX=S0bZoKHX2nS-+O72tjjrjq4wScA@mail.gmail.com/T/#t
diff --git a/articles/images/riscv-irq-analysis/image-20220921233758928.png b/articles/images/riscv-irq-analysis/image-20220921233758928.png
new file mode 100644
index 0000000000000000000000000000000000000000..5729235f0e5bfbf1407e53b70143717eb4856a90
Binary files /dev/null and b/articles/images/riscv-irq-analysis/image-20220921233758928.png differ