Linux IPMI 驅動

作者:

Corey Minyard <minyard@mvista.com> / <minyard@acm.org>

智慧平臺管理介面(IPMI)是一種用於控制監控系統的智慧裝置的標準。它提供系統中感測器的動態發現功能,並能監控感測器並在其值改變或超出特定範圍時通知使用者。它還為現場可更換單元(FRU)和看門狗定時器提供了標準化的資料庫。

要使用此功能,您的系統需要一個到 IPMI 控制器(稱為基板管理控制器,或 BMC)的介面,以及能夠使用 IPMI 系統的管理軟體。

本文件描述瞭如何使用 Linux 的 IPMI 驅動。如果您不熟悉 IPMI 本身,請訪問網站 https://www.intel.com/design/servers/ipmi/index.htm。IPMI 是一個很大的主題,我無法在此處全部涵蓋!

配置

Linux IPMI 驅動是模組化的,這意味著您必須根據您的硬體選擇幾項才能使其正常工作。其中大部分可在“字元裝置”選單下的 IPMI 選單中找到。

無論如何,您必須選擇“IPMI 頂層訊息處理程式”才能使用 IPMI。除此之外,您如何操作取決於您的需求和硬體。

訊息處理程式不提供任何使用者級介面。核心程式碼(如看門狗)仍可使用它。如果您需要從使用者空間訪問,並且希望透過裝置驅動訪問,則需要選擇“IPMI 的裝置介面”。

驅動介面取決於您的硬體。如果您的系統正確提供了 IPMI 的 SMBIOS 資訊,驅動將檢測到它並直接工作。如果您的主機板帶有標準介面(通常是“KCS”、“SMIC”或“BT”,請查閱您的硬體手冊),請選擇“IPMI SI 處理程式”選項。此外,還存在一個直接 I2C 訪問 IPMI 管理控制器的驅動。有些主機板支援此功能,但尚不確定它是否適用於所有主機板。為此,請選擇“IPMI SMBus 處理程式”,但如果 SMBIOS/ACPI 資訊不正確或不存在,您可能需要進行一些除錯才能確定它是否適用於您的系統。同時啟用這些功能並讓驅動自動檢測存在的介面是相當安全的。

您通常應在系統上啟用 ACPI,因為帶有 IPMI 的系統可能包含描述它們的 ACPI 表。

如果您有一個標準介面,並且主機板製造商已正確完成其工作,則 IPMI 控制器應自動檢測(透過 ACPI 或 SMBIOS 表)並正常工作。遺憾的是,許多主機板沒有此資訊。驅動會嘗試使用標準預設值,但可能無法工作。如果您遇到這種情況,您需要閱讀下面名為“SI 驅動”或“SMBus 驅動”的部分,瞭解如何手動配置您的系統。

IPMI 定義了一個標準看門狗定時器。您可以透過“IPMI 看門狗定時器”配置選項啟用它。如果您將驅動編譯到核心中,則可以透過核心命令列選項使看門狗定時器在初始化後立即啟動。它還有許多其他選項,請參閱下面的“看門狗”部分了解更多詳細資訊。請注意,如果看門狗被關閉,它也可以繼續執行(預設情況下在關閉時停用)。進入“看門狗卡”選單,啟用“看門狗定時器支援”,並啟用選項“關閉時停用看門狗關機”。

IPMI 系統通常可以使用 IPMI 命令關閉。選擇“IPMI 關機”即可實現此功能。驅動將自動檢測系統是否可以透過 IPMI 關閉。即使您的系統不支援此選項,啟用它也是安全的。這適用於 ATCA 系統、Radisys CPI1 卡以及任何支援標準機箱管理命令的 IPMI 系統。

如果您希望驅動在發生 panic 時將事件寫入事件日誌,請啟用“在 panic 時向所有 BMC 生成 panic 事件”選項。如果您希望將整個 panic 字串使用 OEM 事件寫入事件日誌,請啟用“生成包含 panic 字串的 OEM 事件”選項。您還可以透過將 ipmi_msghandler 模組中名為“panic_op”的模組引數設定為“event”或“string”來動態啟用這些功能。將該引數設定為“none”將停用此功能。

基本設計

Linux IPMI 驅動被設計為高度模組化和靈活,您只需選擇您需要的部分,即可透過多種不同方式使用它。因此,它被分解為許多程式碼塊。這些塊(按模組名稱)是:

ipmi_msghandler - 這是 IPMI 系統的核心軟體。它處理所有訊息、訊息計時和響應。IPMI 使用者連線到此處,IPMI 物理介面(稱為系統管理介面,或 SMI)也連線到此處。這提供了 IPMI 的核心介面,但不提供供應用程式程序使用的介面。

ipmi_devintf - 這為 IPMI 驅動提供了一個使用者空間 IOCTL 介面,此裝置的每個開啟檔案都作為 IPMI 使用者連線到訊息處理程式。

ipmi_si - 用於各種系統介面的驅動。它支援 KCS、SMIC 和 BT 介面。除非您有 SMBus 介面或您自己的自定義介面,否則您可能需要使用它。

ipmi_ssif - 用於訪問 SMBus 上 BMC 的驅動。它使用 I2C 核心驅動的 SMBus 介面透過 SMBus 傳送和接收 IPMI 訊息。

ipmi_powernv - 用於訪問 POWERNV 系統上 BMC 的驅動。

ipmi_watchdog - IPMI 要求系統具有功能強大的看門狗定時器。此驅動在 IPMI 訊息處理程式之上實現了標準 Linux 看門狗定時器介面。

ipmi_poweroff - 某些系統支援透過 IPMI 命令關閉的能力。

bt-bmc - 這不是主驅動的一部分,而是用於訪問 BT 介面的 BMC 側介面的驅動。它用於執行 Linux 的 BMC,以向主機提供介面。

這些都可以透過配置選項單獨選擇。

大部分介面文件都在標頭檔案中。IPMI 標頭檔案是:

linux/ipmi.h - 包含 IPMI 的使用者介面和 IOCTL 介面。

linux/ipmi_smi.h - 包含系統管理介面(與 IPMI 控制器介面的實體)使用的介面。

linux/ipmi_msgdefs.h - 基本 IPMI 訊息的通用定義。

定址

IPMI 定址的工作方式很像 IP 地址,您有一個覆蓋層來處理不同的地址型別。覆蓋層是:

struct ipmi_addr
{
      int   addr_type;
      short channel;
      char  data[IPMI_MAX_ADDR_SIZE];
};

addr_type 決定了地址的實際型別。驅動當前理解兩種不同型別的地址。

“系統介面”地址定義為:

struct ipmi_system_interface_addr
{
      int   addr_type;
      short channel;
};

型別為 IPMI_SYSTEM_INTERFACE_ADDR_TYPE。這用於直接與當前卡上的 BMC 通訊。通道必須是 IPMI_BMC_CHANNEL。

要透過 BMC 在 IPMB 總線上傳送的訊息使用 IPMI_IPMB_ADDR_TYPE 地址型別。格式為:

struct ipmi_ipmb_addr
{
      int           addr_type;
      short         channel;
      unsigned char slave_addr;
      unsigned char lun;
};

這裡的“channel”通常為零,但有些裝置支援多個通道,它對應於 IPMI 規範中定義的通道。

對於傳送方直接位於 IPMB 總線上且無需透過 BMC 的情況,還存在一個 IPMB 直接地址。您可以使用 IPMI_IPMB_DIRECT_ADDR_TYPE 和以下格式向 IPMB 上的特定管理控制器 (MC) 傳送訊息:

struct ipmi_ipmb_direct_addr
{
      int           addr_type;
      short         channel;
      unsigned char slave_addr;
      unsigned char rq_lun;
      unsigned char rs_lun;
};

通道始終為零。您還可以從已註冊處理和響應的其他 MC 接收命令,因此您可以使用此功能在總線上實現管理控制器。

訊息

訊息定義為:

struct ipmi_msg
{
      unsigned char netfn;
      unsigned char lun;
      unsigned char cmd;
      unsigned char *data;
      int           data_len;
};

驅動負責新增/剝離頭部資訊。資料部分只是要傳送的資料(不要在此處放置定址資訊)或響應。請注意,響應的完成程式碼是“資料”中的第一個專案,它不會被剝離,因為所有訊息在規範中都是這樣定義的(因此使偏移量計算更容易 :-)。

當從使用者空間使用 IOCTL 介面時,您必須為“data”提供一個數據塊,填充它,並將 data_len 設定為資料塊的長度,即使在接收訊息時也是如此。否則,驅動將沒有地方放置訊息。

從核心的訊息處理程式上傳的訊息將以以下形式傳入:

struct ipmi_recv_msg
{
      struct list_head link;

      /* The type of message as defined in the "Receive Types"
         defines above. */
      int         recv_type;

      ipmi_user_t      *user;
      struct ipmi_addr addr;
      long             msgid;
      struct ipmi_msg  msg;

      /* Call this when done with the message.  It will presumably free
         the message and do any other necessary cleanup. */
      void (*done)(struct ipmi_recv_msg *msg);

      /* Place-holder for the data, don't make any assumptions about
         the size or existence of this, since it may change. */
      unsigned char   msg_data[IPMI_MAX_MSG_LENGTH];
};

您應該檢視接收型別並適當地處理訊息。

上層介面(訊息處理程式)

介面的上層為使用者提供了 IPMI 介面的一致檢視。它允許定址多個 SMI 介面(因為有些主機板上確實有多個 BMC),使用者無需關心其下是哪種型別的 SMI。

監聽介面

當您的程式碼啟動時,IPMI 驅動可能已檢測到 IPMI 裝置,也可能未檢測到。因此,您可能需要延遲設定直到裝置被檢測到,或者您可以立即進行設定。為了處理這種情況並允許發現,您可以使用 ipmi_smi_watcher_register() 註冊一個 SMI 觀察器,以迭代介面並告知您它們的出現和消失。

建立使用者

要使用訊息處理程式,您必須首先使用 ipmi_create_user 建立一個使用者。介面編號指定您要連線的 SMI,並且您必須提供回撥函式,以便在資料傳入時呼叫。這還允許您傳入一段資料,即 handler_data,它將在所有呼叫中返回給您。

完成後,呼叫 ipmi_destroy_user() 以銷燬使用者。

從使用者空間,開啟裝置會自動建立一個使用者,關閉裝置會自動銷燬使用者。

訊息傳遞

要從核心傳送訊息,ipmi_request_settime() 呼叫幾乎完成了所有訊息處理。大多數引數都是不言自明的。但是,它需要一個“msgid”引數。這不是訊息的序列號。它只是一個長值,當訊息的響應返回時會傳回。您可以隨意使用它。

響應將透過您在 ipmi_create_user() 中傳遞的“handler”的 ipmi_recv_hndl 欄位指向的函式返回。請記住也要檢視接收型別。

從使用者空間,您需要填寫一個 ipmi_req_t 結構體並使用 IPMICTL_SEND_COMMAND ioctl。對於傳入的資料,您可以使用 select() 或 poll() 等待訊息傳入。但是,您不能使用 read() 獲取它們,您必須呼叫 IPMICTL_RECEIVE_MSG 並使用 ipmi_recv_t 結構體才能實際獲取訊息。請記住,您必須在 msg.data 欄位中提供指向資料塊的指標,並且必須使用資料大小填充 msg.data_len 欄位。這為接收方提供了一個實際放置訊息的位置。

如果訊息無法放入您提供的資料中,您將收到 EMSGSIZE 錯誤,並且驅動將把資料留在接收佇列中。如果您想獲取它並截斷訊息,請使用 IPMICTL_RECEIVE_MSG_TRUNC ioctl。

當您在 IPMB 總線上傳送命令(由 IPMI 規範中的 netfn 最低位定義)時,驅動將自動為命令分配序列號並儲存命令。如果在 IPMI 指定的 5 秒內未收到響應,它將自動生成一個響應,表明命令超時。如果收到一個未經請求的響應(例如,如果是在 5 秒之後),該響應將被忽略。

在核心中,收到訊息並處理完畢後,您必須對其呼叫 ipmi_free_recv_msg(),否則會造成訊息洩露。請注意,您絕不應更改訊息的“done”欄位,這是正確清理訊息所必需的。

請注意,在傳送時,有一個 ipmi_request_supply_msgs() 呼叫,允許您提供 SMI 和接收訊息。這對於即使系統緩衝區耗盡也能工作的程式碼片段非常有用(例如,看門狗定時器就使用了它)。您提供自己的緩衝區和自己的釋放例程。不過,由於管理自己的緩衝區很棘手,因此不建議在正常情況下使用。

事件和傳入命令

驅動負責輪詢 IPMI 事件和接收命令(命令不是響應,它們是 IPMB 總線上其他裝置傳送給您的命令)。要接收這些事件和命令,您必須註冊它們,它們不會自動傳送給您。

要接收事件,您必須呼叫 ipmi_set_gets_events() 並將“val”設定為非零。驅動自啟動以來收到的任何事件都將立即傳遞給第一個註冊事件的使用者。之後,如果有多個使用者註冊了事件,他們都將收到所有傳入的事件。

為了接收命令,您必須單獨註冊您要接收的命令。呼叫 ipmi_register_for_cmd() 併為每個要接收的命令提供 netfn 和命令名稱。您還可以指定一個通道的位掩碼,您希望從中接收命令(如果您不關心,則使用 IPMI_CHAN_ALL 接收所有通道)。每個 netfn/cmd/channel 只能註冊一個使用者,但不同的使用者可以註冊不同的命令,或者如果通道位掩碼不重疊,則可以註冊相同的命令。

要響應收到的命令,請在返回的 netfn 中設定響應位,使用從收到的訊息中獲取的地址,並使用與您在收到的訊息中獲得的相同的 msgid。

從使用者空間,提供了等效的 IOCTL 來執行這些功能。

下層(SMI)介面

如前所述,多個 SMI 介面可以註冊到訊息處理程式,每個介面在註冊時都會被分配一個介面編號。它們通常按照註冊順序分配,但是如果一個 SMI 登出後另一個 SMI 註冊,則所有保證都失效。

ipmi_smi.h 定義了管理介面的介面,請參閱該檔案瞭解更多詳細資訊。

SI 驅動

SI 驅動允許在系統中配置 KCS、BT 和 SMIC 介面。它透過多種不同的方法發現介面,具體取決於系統。

您可以在模組載入命令列上指定多達四個介面並控制一些模組引數

modprobe ipmi_si.o type=<type1>,<type2>....
     ports=<port1>,<port2>... addrs=<addr1>,<addr2>...
     irqs=<irq1>,<irq2>...
     regspacings=<sp1>,<sp2>,... regsizes=<size1>,<size2>,...
     regshifts=<shift1>,<shift2>,...
     slave_addrs=<addr1>,<addr2>,...
     force_kipmid=<enable1>,<enable2>,...
     kipmid_max_busy_us=<ustime1>,<ustime2>,...
     unload_when_empty=[0|1]
     trydmi=[0|1] tryacpi=[0|1]
     tryplatform=[0|1] trypci=[0|1]

除 try... 項外,這些都是列表,第一項用於第一個介面,第二項用於第二個介面,依此類推。

si_type 可以是“kcs”、“smic”或“bt”。如果留空,則預設為“kcs”。

如果您為某個介面指定非零的 addrs,則驅動將使用給定記憶體地址作為裝置的地址。這將覆蓋 si_ports。

如果您為某個介面指定非零的 ports,則驅動將使用給定的 I/O 埠作為裝置地址。

如果您為某個介面指定非零的 irqs,則驅動將嘗試使用給定中斷用於裝置。

其他的 try... 項透過其對應的名稱停用發現。這些預設都已啟用,將其設定為零即可停用。tryplatform 停用 openfirmware。

接下來的三個引數與暫存器佈局有關。介面使用的暫存器可能不會出現在連續位置,並且它們可能不在 8 位暫存器中。這些引數允許更精確地指定暫存器中資料的佈局。

regspacings 引數給出連續暫存器起始地址之間的位元組數。例如,如果 regspacing 設定為 4 且起始地址為 0xca2,則第二個暫存器的地址將為 0xca6。這預設為 1。

regsizes 引數給出暫存器的大小(以位元組為單位)。IPMI 使用的資料是 8 位寬的,但它可能位於更大的暫存器中。此引數允許指定讀寫型別。它可以是 1、2、4 或 8。預設值為 1。

由於暫存器大小可能大於 32 位,IPMI 資料可能不在低 8 位中。regshifts 引數給出移位資料以獲取實際 IPMI 資料的量。

slave_addrs 指定本地 BMC 的 IPMI 地址。這通常是 0x20,驅動預設為此,但如果不是,則可以在驅動啟動時指定。

force_ipmid 引數強制啟用(如果設定為 1)或停用(如果設定為 0)核心 IPMI 守護程序。通常這由驅動自動檢測,但中斷損壞的系統可能需要啟用,或者不希望守護程序(不需要效能,不希望 CPU 佔用)的使用者可以停用它。

如果 unload_when_empty 設定為 1,則如果驅動未找到任何介面或所有介面都無法工作,則驅動將被解除安裝。預設值為 1。設定為 0 在熱插拔時有用,但顯然僅適用於模組。

當編譯到核心中時,引數可以在核心命令列中指定為:

ipmi_si.type=<type1>,<type2>...
     ipmi_si.ports=<port1>,<port2>... ipmi_si.addrs=<addr1>,<addr2>...
     ipmi_si.irqs=<irq1>,<irq2>...
     ipmi_si.regspacings=<sp1>,<sp2>,...
     ipmi_si.regsizes=<size1>,<size2>,...
     ipmi_si.regshifts=<shift1>,<shift2>,...
     ipmi_si.slave_addrs=<addr1>,<addr2>,...
     ipmi_si.force_kipmid=<enable1>,<enable2>,...
     ipmi_si.kipmid_max_busy_us=<ustime1>,<ustime2>,...

它的工作方式與同名的模組引數相同。

如果您的 IPMI 介面不支援中斷且是 KCS 或 SMIC 介面,IPMI 驅動將為該介面啟動一個核心執行緒以幫助加速。這是一個低優先順序的核心執行緒,在 IPMI 操作進行時不斷輪詢 IPMI 驅動。force_kipmid 模組引數將允許使用者強制開啟或關閉此執行緒。如果您強制關閉它並且沒有中斷,驅動將執行得非常緩慢。不要怪我,這些介面太糟糕了。

不幸的是,這個執行緒可能會根據介面的效能佔用大量 CPU。這會浪費大量 CPU 並導致檢測空閒 CPU 和增加功耗等各種問題。為了避免這種情況,kipmid_max_busy_us 設定了 kipmid 在休眠一個滴答之前旋轉的最大時間(以微秒為單位)。此值在效能和 CPU 浪費之間設定了一個平衡,需要根據您的需求進行調整。也許有一天會新增自動調整,但這不是一件簡單的事情,即使是自動調整也需要根據使用者所需的效能進行調整。

驅動支援介面的熱插拔。這樣,介面可以在核心啟動並執行後新增或移除。這是透過 /sys/modules/ipmi_si/parameters/hotmod 完成的,它是一個只寫引數。您向此介面寫入一個字串。字串的格式為:

<op1>[:op2[:op3...]]

“op”是:

add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]]

您可以在一行上指定多個介面。“opt”是:

rsp=<regspacing>
rsi=<regsize>
rsh=<regshift>
irq=<irq>
ipmb=<ipmb slave addr>

它們的含義與上面討論的相同。請注意,您也可以在核心命令列中使用此功能,以便以更緊湊的格式指定介面。請注意,在移除介面時,僅使用前三個引數(SI 型別、地址型別和地址)進行比較。移除時,任何選項都將被忽略。

SMBus 驅動 (SSIF)

SMBus 驅動允許在系統中配置多達 4 個 SMBus 裝置。預設情況下,驅動只會註冊它在 DMI 或 ACPI 表中找到的裝置。您可以在模組載入時(對於模組)透過以下方式更改此設定:

modprobe ipmi_ssif.o
      addr=<i2caddr1>[,<i2caddr2>[,...]]
      adapter=<adapter1>[,<adapter2>[...]]
      dbg=<flags1>,<flags2>...
      slave_addrs=<addr1>,<addr2>,...
      tryacpi=[0|1] trydmi=[0|1]
      [dbg_probe=1]
      alerts_broken

地址是正常的 I2C 地址。adapter 是介面卡的字串名稱,如 /sys/bus/i2c/devices/i2c-<n>/name 中所示。它不是 i2c-<n> 本身。此外,比較時會忽略空格,所以如果名稱是“This is an I2C chip”,您可以說 adapter_name=ThisisanI2cchip。這是因為在核心引數中傳遞空格很困難。

除錯標誌是為每個找到的 BMC 設定的位標誌,它們是:IPMI 訊息: 1,驅動狀態: 2,計時: 4,I2C 探測: 8

tryxxx 引數可用於停用從各種來源檢測介面。

將 dbg_probe 設定為 1 將啟用 SMBus 上 BMC 探測和檢測過程的除錯。

slave_addrs 指定本地 BMC 的 IPMI 地址。這通常是 0x20,驅動預設為此,但如果不是,則可以在驅動啟動時指定。

alerts_broken 不啟用 SSIF 的 SMBus 警報。否則,SMBus 警報將在支援的硬體上啟用。

在 SMBus 上發現符合 IPMI 標準的 BMC 可能會導致 I2C 總線上的裝置失效。SMBus 驅動會以塊寫入的方式將“獲取裝置 ID”IPMI 訊息寫入 I2C 匯流排,並等待響應。此操作可能對某些 I2C 裝置有害。強烈建議您將已知的 I2C 地址提供給 smb_addr 引數中的 SMBus 驅動,除非您有 DMI 或 ACPI 資料來告知驅動使用哪個地址。

當編譯到核心中時,地址可以在核心命令列中指定為:

ipmb_ssif.addr=<i2caddr1>[,<i2caddr2>[...]]
      ipmi_ssif.adapter=<adapter1>[,<adapter2>[...]]
      ipmi_ssif.dbg=<flags1>[,<flags2>[...]]
      ipmi_ssif.dbg_probe=1
      ipmi_ssif.slave_addrs=<addr1>[,<addr2>[...]]
      ipmi_ssif.tryacpi=[0|1] ipmi_ssif.trydmi=[0|1]

這些選項與模組命令列上的選項相同。

I2C 驅動不支援非阻塞訪問或輪詢,因此此驅動無法執行 IPMI panic 事件、在 panic 時擴充套件看門狗或其他與 panic 相關的 IPMI 功能,除非進行特殊的核心補丁和驅動修改。您可以在 openipmi 網頁上獲取這些功能。

驅動透過 I2C sysfs 介面支援介面的熱新增和移除。

IPMI IPMB 驅動

此驅動程式用於支援位於 IPMB 總線上的系統;它允許介面看起來像一個正常的 IPMI 介面。向其傳送系統介面定址的訊息將導致訊息傳送到系統上已註冊的 BMC(預設 IPMI 地址為 0x20)。

它還允許您使用 ipmb 直接定址直接定址總線上的其他 MC。您可以從總線上的其他 MC 接收命令,它們將透過上面描述的正常接收命令機制處理。

引數為:

ipmi_ipmb.bmcaddr=<address to use for system interface addresses messages>
      ipmi_ipmb.retry_time_ms=<Time between retries on IPMB>
      ipmi_ipmb.max_retries=<Number of times to retry a message>

除非有裝置樹資訊進行設定,否則載入模組不會自動啟動驅動。如果您想手動例項化其中一個,請執行以下操作:

echo ipmi-ipmb <addr> > /sys/class/i2c-dev/i2c-<n>/device/new_device

請注意,您在此處給出的地址是 I2C 地址,而不是 IPMI 地址。因此,如果您希望您的 MC 地址為 0x60,您在此處放置 0x30。有關更多詳細資訊,請參閱 I2C 驅動資訊。

透過此介面向其他 IPMB 匯流排橋接命令不起作用。接收訊息佇列是按設計未實現的。BMC 上只有一個接收訊息佇列,它 предназначен用於主機驅動,而不是 IPMB 總線上的任何東西。

一個 BMC 可能有多個 IPMB 匯流排,您的裝置位於哪個匯流排取決於系統的接線方式。您可以透過“ipmitool channel info <n>”獲取通道,其中 <n> 是通道,通道範圍為 0-7,並嘗試 IPMB 通道。

其他部分

看門狗

提供了一個看門狗定時器,它實現了 Linux 標準的看門狗定時器介面。它有三個模組引數可以用來控制它:

modprobe ipmi_watchdog timeout=<t> pretimeout=<t> action=<action type>
    preaction=<preaction type> preop=<preop type> start_now=x
    nowayout=x ifnum_to_use=n panic_wdt_timeout=<t>

ifnum_to_use 指定看門狗定時器應使用哪個介面。預設值為 -1,表示選擇第一個註冊的介面。

timeout 是到動作的秒數,pretimeout 是復位前發生預超時 panic 的秒數(如果 pretimeout 為零,則不啟用 pretimeout)。請注意,pretimeout 是最終超時前的時間。因此,如果 timeout 是 50 秒,pretimeout 是 10 秒,那麼 pretimeout 將在 40 秒(超時前 10 秒)發生。panic_wdt_timeout 是在核心 panic 時設定的 timeout 值,以便在 panic 期間執行 kdump 等操作。

action 可以是“reset”、“power_cycle”或“power_off”,指定定時器超時時執行的操作,預設為“reset”。

preaction 可以是“pre_smi”表示透過 SMI 介面指示,“pre_int”表示透過帶中斷的 SMI 指示,以及“pre_nmi”表示在預動作時發生 NMI。這是驅動如何得知預超時的。

preop 可以設定為“preop_none”表示預超時時無操作,“preop_panic”將預操作設定為 panic,或“preop_give_data”以在預超時發生時提供從看門狗裝置讀取的資料。“pre_nmi”設定不能與“preop_give_data”一起使用,因為無法從 NMI 執行資料操作。

當 preop 設定為“preop_give_data”時,預超時發生時,裝置上會有一位元組資料準備好讀取。select 和 fasync 在裝置上也能工作。

如果 start_now 設定為 1,則看門狗定時器將在驅動載入後立即開始執行。

如果 nowayout 設定為 1,則當看門狗裝置關閉時,看門狗定時器不會停止。nowayout 的預設值是:如果 CONFIG_WATCHDOG_NOWAYOUT 選項啟用,則為 true;否則為 false。

當編譯到核心中時,核心命令列可用於配置看門狗:

ipmi_watchdog.timeout=<t> ipmi_watchdog.pretimeout=<t>
      ipmi_watchdog.action=<action type>
      ipmi_watchdog.preaction=<preaction type>
      ipmi_watchdog.preop=<preop type>
      ipmi_watchdog.start_now=x
      ipmi_watchdog.nowayout=x
      ipmi_watchdog.panic_wdt_timeout=<t>

這些選項與模組引數選項相同。

如果看門狗收到預動作,它將恐慌並啟動一個 120 秒的復位超時。在恐慌或重啟期間,如果看門狗正在執行,它將啟動一個 120 秒的計時器,以確保重啟發生。

請注意,如果您對看門狗使用 NMI 預動作,則絕不能使用 NMI 看門狗。沒有合理的方法可以判斷 NMI 是否來自 IPMI 控制器,因此它必須假定如果收到其他未處理的 NMI,它必然來自 IPMI,並且會立即恐慌。

一旦您開啟看門狗定時器,您必須向裝置寫入一個“V”字元才能關閉它,否則定時器將不會停止。這是驅動的新語義,但使其與 Linux 中其他看門狗驅動保持一致。

Panic 超時

OpenIPMI 驅動支援在發生 panic 時將半自定義和自定義事件放入系統事件日誌的功能。如果您啟用“在 panic 時向所有 BMC 生成 panic 事件”選項,您將在 panic 時以標準 IPMI 事件格式獲得一個事件。如果您啟用“生成包含 panic 字串的 OEM 事件”選項,您還將獲得一堆包含 panic 字串的 OEM 事件。

事件的欄位設定是:

  • 生成器 ID:0x21(核心)

  • EvM Rev:0x03(此事件以 IPMI 1.0 格式格式化)

  • 感測器型別:0x20(作業系統關鍵停止感測器)

  • 感測器編號:panic 字串的第一個位元組(如果沒有 panic 字串則為 0)

  • 事件方向 | 事件型別:0x6f(斷言,感測器特定事件資訊)

  • 事件資料 1:0xa1(OEM 位元組 2 和 3 中的執行時停止)

  • 事件資料 2:panic 字串的第二個位元組

  • 事件資料 3:panic 字串的第三個位元組

有關事件佈局的詳細資訊,請參閱 IPMI 規範。此事件總是傳送到本地管理控制器。它將處理將訊息路由到正確位置。

其他 OEM 事件具有以下格式:

  • 記錄 ID(位元組 0-1):由 SEL 設定。

  • 記錄型別(位元組 2):0xf0(OEM 無時間戳)

  • 位元組 3:儲存 panic 的卡的從屬地址

  • 位元組 4:序列號(從零開始)。其餘位元組(11 位元組)是 panic 字串。如果 panic 字串長於 11 位元組,將傳送多個訊息,序列號遞增。

因為您無法使用標準介面傳送 OEM 事件,所以此函式將嘗試查詢 SEL 並將事件新增到其中。它將首先查詢本地管理控制器的功能。如果它有 SEL,那麼事件將儲存在本地管理控制器的 SEL 中。如果本地管理控制器不是事件生成器,將查詢本地管理控制器的事件接收器,並將事件傳送到該裝置上的 SEL。否則,事件將無處可傳送。

關機

如果選擇了關機功能,IPMI 驅動將在標準關機函式指標中安裝一個關機函式。這在 ipmi_poweroff 模組中。當系統請求關機時,它將傳送適當的 IPMI 命令來執行此操作。這在多個平臺上受支援。

有一個名為“poweroff_powercycle”的模組引數,可以為零(執行關機)或非零(執行電源迴圈,關閉系統電源,然後在幾秒鐘內重新開啟)。設定 ipmi_poweroff.poweroff_control=x 將在核心命令列上執行相同的操作。該引數也可透過 /proc/sys/dev/ipmi/poweroff_powercycle 中的 proc 檔案系統獲取。請注意,如果系統不支援電源迴圈,它將始終執行關機操作。

“ifnum_to_use”引數指定關機程式碼應使用哪個介面。預設值為 -1,表示選擇第一個註冊的介面。

請注意,如果啟用了 ACPI,系統將優先使用 ACPI 進行關機。