우선 콜스택부터 점검을 해보면, "kswapd0" 프로세스에서 slab cache를 scanning 하는 도중 커널 크래시가 발생하였음을 알 수 있습니다. 메모리가 부족한 상태로 보입니다. ("kswapd0" 프로세스는 page memory가 부족할 때 실행됩니다.)
-000|do_DataAbort(addr = 3244789312, fsr = 3245415784, regs = 0xC1678E40)
-001|__dabt_svc(asm)
 -->|exception
-002|test_and_set_bit(asm)  // <<**** kernel panic
-003|bit_spin_lock(inline)
-003|hlist_bl_lock(inline)
-003|mb_cache_shrink_scan(?, ?)
-004|shrink_slab_node(shrinkctl = 0xED1C9F08, shrinker = 0xC1721FF0, ?, ?)
-005|shrink_slab(shrinkctl = 0xED1C9F08, nr_pages_scanned = 871, lru_pages = 392
-006|kswapd_shrink_zone(inline)
-006|balance_pgdat(inline)
-006|kswapd(p = 0xC1830580)
-007|kthread(_create = 0xED18ED80)
-008|ret_from_fork(asm)
-009|ret_fast_syscall(asm)
 
커널 패닉이 발생한 주소는 0xC037B07C인데, r12가 0x2이라서 "strneb r1,[r12] " 명령어 실행 도중 data abort가 trigger되었습니다.
   NSR:C037B078|E211C003  _test_and_set_bit:      ands    r12,r1,#0x3      ; r12,r1,#3
___NSR:C037B07C|15CC1000                          strneb  r1,[r12]   <<-- kernel panic
 
그럼 r12가 왜 0x2가 되었는지. 그리고 어떤 데이터 structure였는지 코드 리뷰를 해보면,
bit_spin_lock() 함수에서 _test_and_set_bit() 함수 호출 시 r9(0xE9C25A4E)에서 r1으로 copy를 하고,
______addr/line|code_____|label__________________|mnemonic________________|comment
   NSR:C0256018|E3A00000                          mov     r0,#0x0          ; r0,#0
   NSR:C025601C|E1A01009                          cpy     r1,r9
   NSR:C0256020|EB049414                          bl      0xC037B078       ; _test_and_set_bit
 
_test_and_set_bit() 함수 첫 instruction에서 "ands r12,r1,#0x3" 동작으로 r12가 0x2가 되었습니다.
   NSR:C037B078|E211C003  _test_and_set_bit:      ands    r12,r1,#0x3      ; r12,r1,#3  // <<-- r1: 0xE9C25A4E
___NSR:C037B07C|15CC1000                          strneb  r1,[r12]   <<-- kernel panic
 
그럼, bit_spin_lock() 함수에서 _test_and_set_bit() 함수 호출 시 쓰이는 r9의 출처는 어디 일까요?
@C0255FF8 주소에서 "ldr r9,r4,#0x34" 인스트럭션으로 r9가 0xE9C25A4E로 업데이트됩니다.
   NSR:C0255FF8|E5949034                          ldr     r9,[r4,#0x34]
   NSR:C0255FFC|E3C3303F                          bic     r3,r3,#0x3F      ; r3,r3,#63
   NSR:C0256000|E5932004                          ldr     r2,[r3,#0x4]
   NSR:C0256004|E2822001                          add     r2,r2,#0x1       ; r2,r2,#1
   NSR:C0256008|E5832004                          str     r2,[r3,#0x4]
   NSR:C025600C|E1A0300D                          cpy     r3,r13
   NSR:C0256010|E3C35D7F                          bic     r5,r3,#0x1FC0    ; r5,r3,#8128
   NSR:C0256014|E3C5A03F                          bic     r10,r5,#0x3F     ; r10,r5,#63
   NSR:C0256018|E3A00000                          mov     r0,#0x0          ; r0,#0
   NSR:C025601C|E1A01009                          cpy     r1,r9
   NSR:C0256020|EB049414                          bl      0xC037B078       ; _test_and_set_bit
 
아래 offset 명령어로 R4: 0xDAC71BC0 = struct mb_cache_entry 임을 알 수 있습니다.
 
offsetof(struct mb_cache_entry,e_block_hash_p) = 0x34
 
  (struct mb_cache_entry*)0xDAC71BC0 // <<-- R4
    e_lru_list = (next = 0xDAC71BC0, prev = 0xDAC71BC0),
    e_cache = 0xE698B000,
    e_used = 0x0,
    e_queued = 0x0,
    e_refcnt = (counter = 0x0),
    e_bdev = 0xEDC4CC00,
    e_block = 0x8313,
    e_block_list = (next = 0x0, pprev = 0xE9C25A4C),
    e_index = (o_list = (next = 0x0, pprev = 0xE9C26808), o_key = 0x396FB86C),
    e_block_hash_p = 0xE9C25A4E // <<--R9
      first = 0xDAC7 -> (
        next = 0x0,  // <<--?
        pprev = 0x0)), // <<--?
    e_index_hash_p = 0xE9C26808)
 
그런데 논리적으로 문제가 될만한 디버깅 정보는 찾기 어렵습니다.
 
#커널 크래시 디버깅 및 TroubleShooting

+ Recent posts