SOFTIRQ_MASK 분석하기
SOFTIRQ_MASK 가 어떤 값인지 알아보기 위해 이 플래그의 선언부를 확인해봤습니다.
다음은 SOFTIRQ_MASK의 선언부입니다.
https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/preempt.h
#define SOFTIRQ_MASK (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
보시다시피 SOFTIRQ_MASK 매크로는 __IRQ_MASK, SOFTIRQ_BITS, SOFTIRQ_SHIFT와 같이 생소한 매크로로 구성돼 있어 바로 어떤 값인지 확인하기 어렵습니다.
그래서 각각의 매크로의 선언부를 따라 가다 보면 시간이 오래 걸리는 경우가 많습니다.
SOFTIRQ_MASK 매크로를 확인하기 위한 패치 코드
그래서 SOFTIRQ_MASK 매크로의 정체를 빨리 확인하기 위해 다음과 같은 패치 코드를 생성해봤습니다.
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 6f58486..acde648 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -246,6 +246,15 @@ static inline bool lockdep_softirq_start(void) { return false; }
static inline void lockdep_softirq_end(bool in_hardirq) { }
#endif
+int __find_softirq_mask(int param)
+{
+ int result = 0;
+
+ result = param & SOFTIRQ_MASK;
+
+ return result;
+}
+
asmlinkage __visible void __softirq_entry __do_softirq(void)
{
unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
@@ -256,6 +265,9 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
__u32 pending;
int softirq_bit;
+ if (__find_softirq_mask(max_restart))
+ return;
+
/*
* Mask out PF_MEMALLOC s current task context is borrowed for the
* softirq. A softirq handled such as network RX might set PF_MEMALLOC
여기서 주의 사항은 소스를 빌드한 후 리눅스 시스템에는 절대 설치하면 안됩니다.
SOFTIRQ_MASK 매크로를 전처리 코드에서 확인하기
위에서 보이는 패치를 반영한 후 커널을 빌드해서 전처리 파일을 확인해 봤습니다.
다음 코드를 같이 볼까요?
out/kernel/.tmp_softirq.i
int __find_softirq_mask(int param)
{
int result = 0;
result = param & (((1UL << (8))-1) << (0 + 8));
return result;
}
위 코드에서 보이듯 SOFTIRQ_MASK의 정체는 '(((1UL << (8))-1) << (0 + 8))' 임을 알 수 있습니다.
(((1UL << (8))-1) << (0 + 8)) 구문을 계산하려고 하니 짜증이 나는군요.
SOFTIRQ_MASK 매크로를 어셈블리 코드로 확인하기
이번에는 __find_softirq_mask() 함수를 어셈블리 코드로 분석해보겠습니다. 다음 코드를 같이 보겠습니다.
______addr/line|code______|label_________________|mnemonic________________|comment
01 NSR:801244AC|E1A0C00D __find_softirq_mask: cpy r12,r13
02 NSR:801244B0|E92DD800 push {r11-r12,r14,pc}
03 NSR:801244B4|E24CB004 sub r11,r12,#0x4 ; r11,r12,#4
04 NSR:801244B8|E52DE004 push {r14}
05 NSR:801244BC|EBFFAE15 bl 0x8010FD18 ; __gnu_mcount_nc
06 NSR:801244C0|E2000CFF and r0,r0,#0xFF00 ; r0,r0,#65280
07 NSR:801244C4|E89DA800 ldm r13,{r11,r13,pc}
06번째 줄을 보면 'and r0,r0,#0xFF00' 구문이 보입니다. 즉, SOFTIRQ_MASK의 정체는 0xFF00입니다.
'param & SOFTIRQ_MASK' 구문은 어셈블리 코드 포멧으로 'and r0,r0,#0xFF00' 명령어이기 때문입니다.
결론
C 포멧의 소스 코드보다 어셈블리 코드를 분석할 때 매크로의 정체를 빨리 파악할 수 있습니다.
이처럼 어셈블리 코드를 읽으면 더 빨리 코드를 읽을 때도 있습니다.
태그 : softirq, SOFTIRQ_MASK
최근 덧글