看門狗,又叫 watchdogtimer,是一個定時器電路, 一般有一個輸入,叫喂狗,一個輸出到MCU的RST端,MCU正常工作的時候,每隔一段時間輸出一個信號到喂狗端,給 WDT 清零,如果超過規(guī)定的時間不喂狗,(一般在程序跑飛時),WDT 定時超過,就會給出一個復位信號到MCU,是MCU復位. 防止MCU死機. 看門狗的作用就是防止程序發(fā)生死循環(huán),或者說程序跑飛。
watchdog的操作就是reset,所以跟電源是有聯(lián)系的。
1. 軟硬件watchdog的區(qū)別
通常情況下,watchdog需要硬件支持,但是如果確實沒有相應的硬件,還想使用watchdog功能,則可以使用liunx模擬的watchdog,即軟件watchdog。
硬件watchdog必須有硬件電路支持, 設備節(jié)點/dev/watchdog對應著真實的物理設備, 不同類型的硬件watchdog設備由相應的硬件驅動管理。軟件watchdog由一內核模塊softdog.ko 通過定時器機制實現(xiàn),/dev/watchdog并不對應著真實的物理設備,只是為應用提供了一個與操作硬件watchdog相同的接口。
硬件watchdog比軟件watchdog有更好的可靠性。軟件watchdog基于內核的定時器實現(xiàn),當內核或中斷出現(xiàn)異常時,軟件watchdog將會失效。而硬件watchdog由自身的硬件電路控制, 獨立于內核。無論當前系統(tǒng)狀態(tài)如何,硬件watchdog在設定的時間間隔內沒有被執(zhí)行寫操作,仍會重新啟動系統(tǒng)。
一些硬件watchdog卡如WDT501P 以及一些Berkshire卡還可以監(jiān)測系統(tǒng)溫度,提供了 /dev/temperature接口。
對于應用程序而言, 操作軟件、硬件watchdog的方式基本相同:打開設備/dev/watchdog, 在重啟時間間隔內對/dev/watchdog執(zhí)行寫操作。即軟件、硬件watchdog對應用程序而言基本是透明的。
在任一時刻, 只能有一個watchdog驅動模塊被加載,管理/dev/watchdog 設備節(jié)點。如果系統(tǒng)沒有硬件watchdog電路,則可以加載軟件watchdog驅動softdog.ko。
2. 軟件看門狗
2.1 kernel watchdog
kernel watchdog是用來檢測Lockup 的。所謂lockup,是指某段內核代碼占著CPU不放。Lockup嚴重的情況下會導致整個系統(tǒng)失去響應。Lockup有幾個特點:
首先只有內核代碼才能引起lockup,因為用戶代碼是可以被搶占的,不可能形成lockup(只有一種情況例外,就是SCHED_FIFO優(yōu)先級為99的實時進程即使在用戶態(tài)也可能使[watchdog/x]內核線程搶不到CPU而形成soft lockup)
其次內核代碼必須處于禁止內核搶占的狀態(tài)(preemption disabled),因為Linux是可搶占式的內核,只在某些特定的代碼區(qū)才禁止搶占(例如spinlock),在這些代碼區(qū)才有可能形成lockup。
2.1.1 soft lockup
Lockup分為兩種:soft lockup 和 hard lockup,它們的區(qū)別是 hard lockup 發(fā)生在CPU屏蔽中斷的情況下。而soft lockup則是單個CPU被一直占用的情況(中斷仍然可以響應)。
NMI,即非可屏蔽中斷。即使在內核代碼中設置了屏蔽所有中斷的時候,NMI也是不可以被屏蔽的。
可屏蔽中斷包含時鐘中斷,外設中斷(比如鍵盤中斷,I/O設備中斷,等等),當我們處理中斷處理程序的時候,在中斷處理程序top half時候,在不允許嵌套的情況下,需要關閉中斷。
但NMI就不一樣了,即便在關閉中斷的情況下,他也能被響應。觸發(fā)NMI的條件一般都是ECC error之類的硬件Error。但NMI也給我們提供了一種機制,在系統(tǒng)中斷被誤關閉的情況下,依然能通過中斷處理程序來執(zhí)行一些緊急操作,比如kernel panic。
檢測soft lockup的原理是給每個CPU分配一個定時執(zhí)行的內核線程[watchdog/x],如果該線程在設定的期限內沒有得到執(zhí)行的話就意味著發(fā)生了soft lockup,[watchdog/x]是SCHED_FIFO實時進程,優(yōu)先級為最高的99,擁有優(yōu)先運行的特權。
系統(tǒng)會有一個高精度的計時器hrtimer(一般來源于APIC),該計時器能定期產生時鐘中斷,該中斷對應的中斷處理例程是kernel/watchdog.c: watchdog_timer_fn(),在該例程中:
要遞增計數(shù)器hrtimer_interrupts,這個計數(shù)器同時為hard lockup detector用于判斷CPU是否響應中斷;
還要喚醒[watchdog/x]內核線程,該線程的任務是更新一個時間戳;
soft lock detector檢查時間戳,如果超過soft lockup threshold一直未更新,說明[watchdog/x]未得到運行機會,意味著CPU被霸占,也就是發(fā)生了soft lockup。
linux kernel會自動檢測softlockup,在發(fā)生softlockup情況下,系統(tǒng)默認會打印相關warning信息。如果需要出發(fā)panic的話,可以設置
echo 1 > /proc/sys/kernel/softlockup_panic
可以同時設置 watchdog_thresh參數(shù)來定義發(fā)現(xiàn)softlockup以后系統(tǒng)panic的時間,默認是10s, 也就是說20s后系統(tǒng)panic。最大能設到60s,也就是說,120s后啟動系統(tǒng)panic。
一般來說,在production system上,不建議使用softlockup_panic選項(有可能誤傷)??梢栽谡{試系統(tǒng)上使用。
2.1.1 hard lockup
Hard lockup比soft lockup更加嚴重,CPU不僅無法執(zhí)行其它進程,而且不再響應中斷。檢測hard lockup的原理利用了PMU的NMI perf event,因為NMI中斷是不可屏蔽的,在CPU不再響應中斷的情況下仍然可以得到執(zhí)行,它再去檢查時鐘中斷的計數(shù)器hrtimer_interrupts是否在保持遞增,如果停滯就意味著時鐘中斷未得到響應,也就是發(fā)生了hard lockup
Linux kernel設計了一個檢測lockup的機制,稱為NMI Watchdog,是利用NMI中斷實現(xiàn)的,用NMI是因為lockup有可能發(fā)生在中斷被屏蔽的狀態(tài)下,這時唯一能把CPU搶下來的方法就是通過NMI,因為NMI中斷是不可屏蔽的。
NMI watchdog會利用到之前講到的hrtimer。它的觸發(fā)條件是基于PMU的NMI perf event,當PMU的計數(shù)器溢出時會觸發(fā)NMI中斷,對應的中斷處理例程是 kernel/watchdog.c: watchdog_overflow_callback(),hard lockup detector就在其中,它會檢查上述hrtimer的中斷次數(shù)(hrtimer_interrupts)是否在保持遞增,如果停滯則表明hrtimer中斷未得到響應,也就是發(fā)生了hard lockup。
這里面,被watch的對象是hrtimer,而watchdog則是由PMU設備發(fā)起的NMI中斷處理程序 watchdog_overflow_callback()
hardlockup的檢測需要啟動NMI watchdog??梢酝ㄟ^設置內核參數(shù)實現(xiàn):
echo 1 > /proc/sys/kernel/nmi_watchdog 1 在發(fā)生hardlockup情況下,如果我們需要系統(tǒng)panic,可以設置(默認已設定)
echo 1 > /proc/sys/kernel/hardlockup_panic
2.2 用戶態(tài)watchdog
用戶程序有可能占著臨界資源無法釋放,系統(tǒng)太忙,疲于響應各種中斷,導致無法執(zhí)行調度程序。這都可能導致系統(tǒng)無法正常使用。
在這種情況下,時鐘中斷和NMI中斷仍然能夠被響應,所以內核lockup檢測機制無法檢查出來。但由于系統(tǒng)已經無法正常工作,我們需要一種機制,一種用戶態(tài)的watchdog,來檢測這種系統(tǒng)掛起的狀態(tài),并作出相應的動作。
用戶態(tài)watchdog,自然檢測的對象是用戶態(tài)的程序(是否能被調度)。這里面,基于硬件支持程度不同,我們分為hardware watchdog和software watchdog。后者簡稱softdog。
2.2.1 softdog
使用softdog很簡單,只需要:
安裝 watchdog rpm
啟動softdog服務
-systemctl start softdog.service
默認情況下,watchdog程序會通過softdog.ko創(chuàng)建一個叫做/dev/watchdog1的設備(timer 設備),并且定期往它寫東西(用于更新時間戳)。
位于內核的softdog會模擬timer設備(通過時鐘中斷的方式模擬),并執(zhí)行相應的中斷處理例程,該例程的目的是檢查timer 設備(即/dev/watchdog1)是否timeout。如果timeout,則執(zhí)行相應動作(默認為panic)。
2.2.1 hardware watchdog
通過BMC實現(xiàn)、通過iTCO實現(xiàn)
3. 硬件看門狗
3.1 硬件寄存器介紹
看門狗主要由寄存器、計數(shù)器和狗叫模塊構成,通過寄存器對看門狗進行基本設置,計數(shù)器計算狗叫時間,狗叫模塊決定看門狗超時后發(fā)出的中斷或復位方式。
QOTOM Q300P自帶硬件看門狗,由SuperIO芯片提供,這里簡單實現(xiàn)一下看門狗的復位功能,只需要對看門狗的配置寄存器組和數(shù)據(jù)寄存器組進行操作。
WDTCTRL:Watch Dog Timer Control Register (Index=71h, Default=00h) 控制寄存器,主要是設置中斷,這里不涉及
WDTCONF:Watch Dog Timer Configuration Register (Index=72h, Default=001s0000b) 配置寄存器 Bit6 or Bit4設置為1即可開啟看門狗功能,這里使用Bit6脈沖信號
WDTVALLSB:Watch Dog Timer Time-out Value (LSB) Register (Index=73h, Default=38h) 低位數(shù)據(jù)寄存器WDTVALMSB:Watch Dog Timer Time-out Value (MSB) Register (Index=74h, Default=00h) 高位數(shù)據(jù)寄存器
3.2 喂狗操作
samples/watchdog/watchdog-simple.c中有一個簡單的例子:
int main(void) { int fd = open("/dev/watchdog", O_WRONLY); int ret = 0; if (fd == -1) { perror("watchdog"); exit(EXIT_FAILURE); } while (1) { ret = write(fd, "?", 1); if (ret != 1) { ret = -1; break; } sleep(10); } close(fd); return ret; }
3.3 watchdog硬件驅動編寫
例如:drivers/watchdog/imx_sc_wdt.c中 imx_sc_wdt_probe中會調用devm_watchdog_register_device
#define DEFAULT_TIMEOUT 60 #define MAX_TIMEOUT 128 static int imx_sc_wdt_probe(struct platform_device *pdev) { struct watchdog_device *wdog; struct device *dev = &pdev->dev; int ret; wdog = &imx_sc_wdd->wdd; wdog->info = &imx_sc_wdt_info; wdog->ops = &imx_sc_wdt_ops; wdog->min_timeout = 1; wdog->max_timeout = MAX_TIMEOUT; wdog->parent = dev; wdog->timeout = DEFAULT_TIMEOUT; ret = imx_sc_wdt_set_timeout(wdog, wdog->timeout); if (ret) return ret; return devm_watchdog_register_device(dev, wdog);
imx_sc_wdt_ops的定義為:
static const struct watchdog_ops imx_sc_wdt_ops = { .owner = THIS_MODULE, .start = imx_sc_wdt_start, .stop = imx_sc_wdt_stop, .ping = imx_sc_wdt_ping, .set_timeout = imx_sc_wdt_set_timeout, .set_pretimeout = imx_sc_wdt_set_pretimeout, };
例如imx_sc_wdt_start的實現(xiàn),使用了smc下發(fā)到BL31中處理,為了突出安全性。
static int imx_sc_wdt_start(struct watchdog_device *wdog) { struct arm_smccc_res res; arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_START_WDOG, 0, 0, 0, 0, 0, 0, &res); if (res.a0) return -EACCES; arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_SET_WDOG_ACT, SC_TIMER_WDOG_ACTION_PARTITION, 0, 0, 0, 0, 0, &res); return res.a0 ? -EACCES : 0; }
后記:
對于重要的驅動操作的寄存器,在ARM中需要放入BL31中,也就是說寄存器地址是在安全世界的,不能讓內核直接按地址操作,只暴露了通用的協(xié)議接口,就是一個約束,只能這么用,其他用法不行。暴露API而不是所有寄存器是安全世界和非安全世界的一個重要區(qū)別?!吧抖级稽c,啥都不精通,
-
mcu
+關注
關注
146文章
17162瀏覽量
351346 -
看門狗
+關注
關注
10文章
565瀏覽量
70819 -
電源管理
+關注
關注
115文章
6183瀏覽量
144537 -
定時器
+關注
關注
23文章
3250瀏覽量
114881
原文標題:電源管理入門-14 Watchdog
文章出處:【微信號:OS與AUTOSAR研究,微信公眾號:OS與AUTOSAR研究】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論