설정된 주기안에 와치독 킥이 수행되지 않으면 리셋을 해야겠다고 판단
와치독 킥을 수행을 못하게 되면 인터럽트를 EL1 커널에 유발 , 인터럽트 핸들러가 호출 , 시스템 리셋을 함
리눅스 커널 드라이버가 인터럽트조차도 받지 못하는 경우 ex) 로컬 인터럽트를 비활성화 => 인터럽트 핸들러가 호출되지 않으면 와치독 리셋이 제대로 발생하지 못함. => 1초나 2초 후에 FIQ를 트러스티드 커널로 보내서 와치독 리셋과 관련된 드라이버를 구현할 수 있다.
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>;
};
kernel thread to perform watchdog kick
dynamic timer to wakeup 'msm_watchdog' // 깨우기 위한 용도의 타이머
Being triggered when watchdog kick is not performed // 와치독 킥이 정상동작 x일 때 트리거가 되는 인터럽트
§ 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);
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;
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 }
IRQ Storm
local interrupt is not handled properly
When two or more real-time processes compete for system resources
- 웨이크업 함수를 호출 하고나서 커널스레드 함수를 깨웠는데 깨지 않을 수도 있다.
- 대표적으로 2개 or 2개 이상의 프로세스가 경합한 상황 => 일반 우선순위의 커널이나 프로세스가 제대로 정해진 시간내에 깨어나지 못할 수 있다.
- 깨어나지 않으면 와치독 킥을 못한다
Unlimited loops
Busy waiting (spinlock)
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 }