Linux 内核软中断子系统 九章编译法,AI直译完成汇编码
九章编程法实战:重构 Linux 内核软中断子系统,千行核心代码压缩到388 行题-CSDN博客
本文是按此C码,严格依照九章编译法,生成汇编码。
# Linux软中断调度器 · 九章空间几何结构直译汇编 # 三元对齐标准:单指令 = 操作码 + 源操作数 + 目的/标志位 # Arch: x86_64 System V ABI, GCC as # 几何常量完全绑定C宏,无硬编码虚化数值 .section .rodata .align 8 # 软中断名字符串(只读几何常量) hi_name: .asciz "hi" timer_name: .asciz "timer" net_tx_name: .asciz "net_tx" net_rx_name: .asciz "net_rx" block_name: .asciz "block" irq_poll_name: .asciz "irq_poll" tasklet_name: .asciz "tasklet" sched_name: .asciz "sched" hrtimer_name: .asciz "hrtimer" rcu_name: .asciz "rcu" # C struct softirq_desc [name, budget, weight, wake_thread_on_full] softirq_table: .quad hi_name, 10, 4, 1 .quad timer_name, 100, 1, 1 .quad net_tx_name, 64, 1, 1 .quad net_rx_name, 64, 1, 1 .quad block_name, 32, 1, 1 .quad irq_poll_name,32, 1, 1 .quad tasklet_name, 0, 1, 1 .quad sched_name, 0, 2, 0 .quad hrtimer_name,0, 1, 1 .quad rcu_name, 0, 2, 0 # 全局几何常量(与C完全同构) NR_SOFTIRQS = 10 MAX_RESTART = 10 MAX_PRESSURE = 10000000000 INT_MAX = 0x7fffffff # per-CPU irq_cpustat_t 几何偏移(严格对齐C结构体布局) PENDING_OFFSET = 0 # u32 __softirq_pending SUM_OFFSET = 4 # u64 softirqs_sum[10] PRESSURE_OFFSET = 84 # u64 softirqs_pressure IRQ_STAT_SIZE = 96 # 全局导出符号 .globl do_softirq .globl raise_softirq .globl raise_softirq_irqoff .globl __raise_softirq_irqoff .globl open_softirq .globl softirq_cpu_dead .globl ksoftirqd_entry .section .bss .align 64 # per-CPU 运行存储几何(最多64CPU,空间精确计算无冗余) per_cpu_irq_stat: .space IRQ_STAT_SIZE * 64 per_cpu_ksoftirqd: .space 8 * 64 # softirq动作向量表 void (*action)(struct softirq_action *) softirq_vec: .space 8 * NR_SOFTIRQS .section .text # ===================== 三元算子:位图操作 纯几何基元 ===================== # si_pend_set(cpu=rdi, nr=esi) 三元:shl(src)|or(op)|内存dst si_pend_set: shlq $4, %rdi lea per_cpu_irq_stat(%rip), %rax addq %rdi, %rax movl $1, %ecx shll %cl, %esi orl %esi, PENDING_OFFSET(%rax) ret # si_pend_clr(cpu=rdi, nr=esi) si_pend_clr: shlq $4, %rdi lea per_cpu_irq_stat(%rip), %rax addq %rdi, %rax movl $1, %ecx shll %cl, %esi notl %esi andl %esi, PENDING_OFFSET(%rax) ret # si_pend_get(cpu=rdi) -> eax 返回pending位图 si_pend_get: shlq $4, %rdi lea per_cpu_irq_stat(%rip), %rax addq %rdi, %rax movl PENDING_OFFSET(%rax), %eax ret # ===================== 三元算子:ksoftirqd线程唤醒 ===================== # si_wake_thread(cpu=rdi) si_wake_thread: pushq %rbx movl %edi, %ebx shlq $3, %rdi lea per_cpu_ksoftirqd(%rip), %rax movq (%rax,%rdi), %rdi testq %rdi, %rdi jz .wake_exit callq task_is_running testl %eax, %eax jnz .wake_exit movq %rdi, %rdi callq wake_up_process .wake_exit: popq %rbx ret # ===================== 三元算子:软中断耗时统计 si_account ===================== # si_account(nr=rdi, start=rsi) si_account: pushq %rbx movq %rsi, %rbx callq smp_processor_id movl %eax, %r8d shlq $4, %rax lea per_cpu_irq_stat(%rip), %rcx addq %rax, %rcx callq sched_clock subq %rbx, %rax # sum += delta movq %rax, %rdx shlq $3, %rdi addq $SUM_OFFSET, %rdi addq %rdx, (%rcx,%rdi) # pressure += delta * weight lea softirq_table(%rip), %rsi shlq $4, %rdi movl 16(%rsi,%rdi), %edi mulq %rdi addq %rax, PRESSURE_OFFSET(%rcx) popq %rbx ret # ===================== 核心调度骨架 do_softirq 完整三元分支直译 ===================== do_softirq: pushq %rbp movq %rsp, %rbp pushq %rbx pushq %r12 pushq %r13 pushq %r14 pushq %r15 # 判定1:中断上下文直接返回 callq in_interrupt testl %eax, %eax jnz .softirq_done # 保存中断标志 local_irq_save pushfq popq %r15 cli callq smp_processor_id movl %eax, %r12d movl %r12d, %edi callq si_pend_get movl %eax, %r13d testl %r13d, %r13d jz .irq_restore movl $MAX_RESTART, %r14d .softirq_loop: # 三元判定1 pending==0 testl %r13d, %r13d jz .irq_restore # 三元判定2 restart <= 0 cmpl $0, %r14d jle .wake_ksoftirqd_jmp # 读取per-cpu压力值 movl %r12d, %edi shlq $4, %rdi lea per_cpu_irq_stat(%rip), %rax addq %rdi, %rax movq PRESSURE_OFFSET(%rax), %rbx # 三元判定3 pressure > MAX_PRESSURE cmpq $MAX_PRESSURE, %rbx ja .wake_ksoftirqd_jmp # 本轮快照mask = pending movl %r13d, %r8d xorl %r9d, %r9d .softirq_inner: cmpl $NR_SOFTIRQS, %r9d jge .round_next testl %r8d, (1<<%r9d) jz .inner_skip # 清除当前软中断pending位 movl %r12d, %edi movl %r9d, %esi callq si_pend_clr # 读取budget lea softirq_table(%rip), %rax shlq $4, %r9 movl 8(%rax,%r9), %ecx testl %ecx, %ecx jnz .budget_ok movl $INT_MAX, %ecx .budget_ok: # 开中断执行action sti lea softirq_vec(%rip), %rax movq (%rax,%r9,8), %rdi callq sched_clock movq %rax, %rsi callq *%rdi movl %r9d, %rdi movq %rsi, %rsi callq si_account cli # mask清除当前位 movl $1, %edx shll %dl, %r9d notl %edx andl %edx, %r8d .inner_skip: incl %r9d jmp .softirq_inner .round_next: # 刷新pending、restart自减 movl %r12d, %edi callq si_pend_get movl %eax, %r13d decl %r14d jmp .softirq_loop .wake_ksoftirqd_jmp: movl %r12d, %edi callq si_wake_thread .irq_restore: # 恢复中断标志 local_irq_restore pushq %r15 popfq .softirq_done: popq %r15 popq %r14 popq %r13 popq %r12 popq %rbx popq %rbp ret # ===================== 对外标准接口直译 ===================== # raise_softirq_irqoff(nr=rdi) raise_softirq_irqoff: pushq %rbx movl %edi, %ebx callq smp_processor_id movl %eax, %edi movl %ebx, %esi callq si_pend_set popq %rbx ret # __raise_softirq_irqoff 别名 __raise_softirq_irqoff: jmp raise_softirq_irqoff # raise_softirq(nr=rdi) 带中断保存恢复 raise_softirq: pushq %rbx pushfq popq %r10 movl %edi, %ebx cli callq smp_processor_id movl %eax, %edi movl %ebx, %esi callq si_pend_set pushq %r10 popfq popq %rbx ret # open_softirq(nr=rdi, action=rsi) 注册软中断回调 open_softirq: lea softirq_vec(%rip), %rax movq %rsi, (%rax,%rdi,8) ret # CPU离线清理 softirq_cpu_dead(cpu=rdi) softirq_cpu_dead: pushq %rbx movl %edi, %ebx xorl %r9d, %r9d .dead_loop: cmpl $NR_SOFTIRQS, %r9d jge .dead_wake movl %ebx, %edi callq si_pend_get testl %eax, (1<<%r9d) jz .dead_skip movl %ebx, %edi movl %r9d, %esi callq si_pend_clr callq smp_processor_id movl %eax, %edi movl %r9d, %esi callq si_pend_set .dead_skip: incl %r9d jmp .dead_loop .dead_wake: callq smp_processor_id movl %eax, %edi callq si_wake_thread popq %rbx ret # ksoftirqd内核线程入口 ksoftirqd_entry(__bind_cpu=rdi) ksoftirqd_entry: pushq %rbx movq %rdi, %rbx .ksoft_loop: callq kthread_should_stop testl %eax, %eax jnz .ksoft_exit callq smp_processor_id movl %eax, %edi callq si_pend_get testl %eax, %eax jnz .run_softirq movq $TASK_INTERRUPTIBLE, %rdi callq set_current_state callq schedule jmp .ksoft_loop .run_softirq: movq $TASK_RUNNING, %rdi callq __set_current_state callq do_softirq movq $TASK_INTERRUPTIBLE, %rdi callq set_current_state jmp .ksoft_loop .ksoft_exit: movq $TASK_RUNNING, %rdi callq __set_current_state xorl %eax, %eax popq %rbx ret