와치독의 기본 개념

TAEWOO HA·2023년 7월 31일
1

시스템 반도체

목록 보기
2/4
post-custom-banner

와치독

  • 운영체제 커널이 정상적으로 동작하는지 체크하기위한 메커니즘
  • 하드웨어 와치독 타이머 구현 , 타이머를 제어하는 와치독 커널 드라이버 구현

와치독 킥

  • 하드웨어적인 와치독 타이머를 다시 초기화하는 동작.
  • 시스템 소프트웨어 관점에서 정상 동작하고 있는지 체크하는 드라이버

와치독 킥이 수행되지 않았을 경우

  • 엔지니어링 버전에서 와치독 킥이 정상적으로 수행되지 않으면 와치독 리셋이 유발 , 크래쉬 발생

와치독 메커니즘

  • 와치독 킥이 정해진 주기에 따라 수행되면 와치독 타이머가 restart
  • 킥과 리스타트가 반복적으로 발생
  • 와치독 킥이 주어진 주기 안에서 수행되지 않으면 소프트웨어적으로 크게 문제가 있음 ex) 커널 드라이버에 문제가 생기거나 무한루프에 빠지거나 등등 시스템이 리셋을 하게된다

  • 와치독 킥이 제대로 수행되지 않으면 와치독 타이머는 리셋을 하겠다고 판단 , 인터럽트를 통해 시스템을 리셋

멀티 레벨 와치독 리셋

  • 설정된 주기안에 와치독 킥이 수행되지 않으면 리셋을 해야겠다고 판단

    • 와치독 리셋 이슈는 크리티컬한 버그로 관리됨
    • 와치독 킥을 못하는 상황은 대부분 소프트웨어적으로 심각한 오류가 있음.
      • 리커버리 동작보다 크래쉬를 유지시켜서 현상을 디버깅하는게 더 낫다고 판단
  • 와치독 킥을 수행을 못하게 되면 인터럽트를 EL1 커널에 유발 , 인터럽트 핸들러가 호출 , 시스템 리셋을 함

    • 1단계 (Non Secure)
  • 리눅스 커널 드라이버가 인터럽트조차도 받지 못하는 경우 ex) 로컬 인터럽트를 비활성화 => 인터럽트 핸들러가 호출되지 않으면 와치독 리셋이 제대로 발생하지 못함. => 1초나 2초 후에 FIQ를 트러스티드 커널로 보내서 와치독 리셋과 관련된 드라이버를 구현할 수 있다.

    • 2단계 (Secure)

퀄컴 와치독 드라이버 분석

watchdog code and device tree

msm watchdog code
drivers/soc/qcom/watchdog_v2.c
https://android.googlesource.com/kernel/msm.git/+/android-msm-mako-3.4-
jb-mr2/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt
Example:
qcom,wdt@f9017000 {
compatible =
"qcom,msm-watchdog";
reg = <0xf9017000 0x1000>;
interrupts = <0 3 0 0 4 0>;
qcom,bark-time = <11000>; // 킥이 안되면 바크
qcom,pet-time = <10000>; // 와치독 킥을 하는 주기 10초
qcom,ipi-ping = <1>;
};

3가지 컴포넌트

'msm_watchdog'

kernel thread to perform watchdog kick

pet timer

dynamic timer to wakeup 'msm_watchdog' // 깨우기 위한 용도의 타이머

bark IRQ handler

Being triggered when watchdog kick is not performed // 와치독 킥이 정상동작 x일 때 트리거가 되는 인터럽트

msm_watchdog_probe()

§ kernel thread "msm_watchdog" is created 

1014 static int msm_watchdog_probe(struct platform_device *pdev) // 부팅시 프로브 함수 호출
1015 {
...
1033 wdog_dd->watchdog_task = kthread_create(watchdog_kthread, wdog_dd, // 커널 스레드 생성, 첫번째인자는 커널스레드 생성 이후 계속 동작하는 스레드 핸들러 함수의 이름 , 두번째는 스레드 핸들러에 전달되는 매개인자
1034 "msm_watchdog"); // 커널 스레드의 이름 지정
1035 if (IS_ERR(wdog_dd->watchdog_task)) {
1036 ret = PTR_ERR(wdog_dd->watchdog_task);
1037 goto err; // 커널스레드 생성x시 예외처리
1038 }
1039 init_watchdog_data(wdog_dd);

init_watchdog_data()

816 static void init_watchdog_data(struct msm_watchdog_data *wdog_dd)
817 {
...
878 wake_up_process(wdog_dd->watchdog_task);
879 init_timer(&wdog_dd->pet_timer);
880 wdog_dd->pet_timer.data = (unsigned long)wdog_dd; // 타이머 핸들러의 인자로 전달되는 매개인자
881 wdog_dd->pet_timer.function = pet_task_wakeup; // 펫타이머 핸들러 함수
882 wdog_dd->pet_timer.expires = jiffies + delay_time; // 만료시간
883 add_timer(&wdog_dd->pet_timer);


 timer handler function: pet_task_wakeup()
 expires = jiffies + delay_time;

msm workflow

  • 펫 타이머 : 10초 주기로 반복하도록 동작
    • 10초 이후 만료가 되면 펫 타이머의 핸들러 함수(pet task wakeup)이 호출, 와치독 커널 스레드를 깨움
    • 와치독 커널 스레드는 깨어나서 ping other cpus 함수를 호출 : 내부에서 ipi콜을 수행 (다른 arm 코어에게 인터럽트 유발)
    • 그 다음 와치독 킥을 수행 => 펫 타이머 등록 => 커널 스레드는 슬립에 진입

ping other cpu

  • IPI 콜 유발 => 0번째 코어에서 소프트웨어적으로 발생하는 인터럽트를 받아서 처리를 수행 => keep alive response함수 발생
  • 이후 첫번째 코어에 IPI콜 ...
  • smp single을 통해 위의 과정을 진행
  • ipi콜을 유발해서 각각의 cpu코어가 정상동작하는지 체크하는 용도로 ping others cpu가 구현됨
  • 이후 와치독 킥 발생
  • 만약 0번째 cpu에서 stop이 되어 ipi콜을 받지 못하면 와치독 리셋이 발생

pet_watchdog()


385 static void pet_watchdog(struct msm_watchdog_data *wdog_dd)
386 {
387 int slack, count;
…
/* Perform watchdog kick by writing 1 to ‘base + WDT0_RST’
396 __raw_writel(1, wdog_dd->base + WDT0_RST); // 와치독 킥 핵심코드
397 time_ns = sched_clock();
…
/* Key signature to debug watchdog reset
401 wdog_dd->last_pet = time_ns;
402 }

Pet timer (pet_task_wakeup) is not handled

IRQ Storm
local interrupt is not handled properly

  • msm 와치독 커널 스레드에서 와치독 킥을 수행한 다음에 펫 타이머를 등록을 하는 루틴 시행중
  • 펫 테스크 웨이크업에 10초후에 호출이 안되면 와치독 커널 스레드를 깨우지를 못함 => 킥을 못함
  • 이런 경우 와치독 리셋이 발생
    • 인터럽트가 엄청나게 많이 발생할 때 발생가능 (동적 타이머가 처리가 안되는 상태가 발생가능)
    • 다른 커널 드라이버에서 로컬 인터럽트를 비활성화하거나 한 상태에서 다이나믹 타이머 핸들러가 호출 x
      .

'msm_watchdog' is not woken

When two or more real-time processes compete for system resources

- 웨이크업 함수를 호출 하고나서 커널스레드 함수를 깨웠는데 깨지 않을 수도 있다.
 - 대표적으로 2개 or 2개 이상의 프로세스가 경합한 상황 => 일반 우선순위의 커널이나 프로세스가 제대로 정해진 시간내에 깨어나지 못할 수 있다.
 - 깨어나지 않으면 와치독 킥을 못한다

No response after ping_other_cpus is called

Unlimited loops
Busy waiting (spinlock)

  • ping other cpu에서 어떤 cpu에서 ipi콜에 대한 애크가 전달되지 않음 => 와치독 리셋이 유발됨
    • 행이 걸리거나 무한루프에 걸렸을 때 와치독 리셋 유발

와치독 킥

  • 와치독 킥을 수행하지 못하면 와치독 bark irq발생

wdog_bark_handler()

Watchdog reset: code review
637 static irqreturn_t wdog_bark_handler(int irq, void *dev_id)
638 {
639 struct msm_watchdog_data *wdog_dd = (struct msm_watchdog_data *)dev_id;
640 unsigned long nanosec_rem;
641 unsigned long long t = sched_clock();
642
643 nanosec_rem = do_div(t, 1000000000);
644 dev_info(wdog_dd->dev, "Watchdog bark! Now = %lu.%06lu\n",
645 (unsigned long) t, nanosec_rem / 1000);
646
647 print_wdog_data(wdog_dd); // 와치독과 관련된 정보를 커널 코드로 출력
648
649 msm_trigger_wdog_bite(); // 와치독 바크가 제대로 수행하지 않았을 경우 수행 
650 panic("Failed to cause a watchdog bite! - Falling back to kernel panic!"); // panic : 커널 크래시 유발
651 return IRQ_HANDLED;
652 }

How to debug watchdog reset

  • Check stack trace of current processes
  • Review ftrace message
    • sched_switch, sched_wakeup, timer ftrace event
  • Debug all processes registered in the runqueue
post-custom-banner

0개의 댓글