天天看點

crash linux主要指令,crash分析

Machine Check Exception (MCE) 是CPU發現硬體錯誤時觸發的異常(exception),中斷号是18,異常的類型是abort:

crash linux主要指令,crash分析

導緻MCE的原因主要有:總線故障、記憶體ECC校驗錯、cache錯誤、TLB錯誤、内部時鐘錯誤,等等。不僅硬體故障會引起MCE,不恰當的BIOS配置、firmware bug、軟體bug也有可能引起MCE。

在 Linux 系統上,如果發生的MCE錯誤屬于可以自動糾正的類型,那麼系統保持繼續運作,MCE錯誤日志會記錄在一個ring buffer中(這個ring buffer通過裝置檔案/dev/mcelog來通路),用 mcelog(8) 指令可以讀取MCE日志,系統通常會通過cron任務或者mcelog.service把ring buffer中的MCE日志寫入/var/log/mcelog檔案中。如果發生的MCE錯誤屬于無法恢複的類型,那麼系統會panic,錯誤資訊會輸出在終端上和message buffer裡。

分析MCE需要參考Intel手冊第3卷,15章Machine-Check Architecture和16章Interpreting Machine-Check Error Codes。由于MCE在不同型号的CPU上有差異,解讀的方法也有不同,第16章是專門解釋在不同的CPU型号上如何解讀MCE錯誤碼。

每個CPU上有一組寄存器稱為 Machine-Check MSR (Model-Specific Register),用于Machine-Check的控制與記錄,分為全局寄存器和若幹Bank寄存器(CPU的硬體單元分成若幹組,每一組稱為一個Bank)。當發生MCE時,錯誤資訊記錄在全局狀态寄存器 MCG_STATUS MSR 和Bank寄存器 MCi_STATUS MSR 中,如下圖黃色框所示:

crash linux主要指令,crash分析

分析MCE的方法,就是根據Intel手冊解讀上述寄存器中記錄的錯誤資訊。Linux核心把MCE的資訊儲存在下面的結構體中:

/arch/x86/include/asm/mce.h :

0067 struct mce {

0068 __u64 status;

0069 __u64 misc;

0070 __u64 addr;

0071 __u64 mcgstatus;

0072 __u64 ip;

0073 __u64 tsc;

0074 __u64 time;

0075 __u8 cpuvendor;

0076 __u8 inject_flags;

0077 __u16 pad;

0078 __u32 cpuid;

0079 __u8 cs;

0080 __u8 bank;

0081 __u8 cpu;

0082 __u8 finished;

0083 __u32 extcpu;

0084 __u32 socketid;

0085 __u32 apicid;

0086 __u64 mcgcap;

0087 };

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

/arch/x86/include/asm/mce.h:

0067structmce{

0068__u64status;

0069__u64misc;

0070__u64addr;

0071__u64mcgstatus;

0072__u64ip;

0073__u64tsc;

0074__u64time;

0075__u8cpuvendor;

0076__u8inject_flags;

0077__u16pad;

0078__u32cpuid;

0079__u8cs;

0080__u8bank;

0081__u8cpu;

0082__u8finished;

0083__u32extcpu;

0084__u32socketid;

0085__u32apicid;

0086__u64mcgcap;

0087};

下面的MCE錯誤資訊截取自一台因MCE而crash的機器,我們以此為例來解讀一下MCE資訊。

注:産生以下資訊的核心函數是:

static void print_mce(struct mce *m)

源程式:arch/x86/kernel/cpu/mcheck/mce.c

如果需要的話,閱讀源程式可以了解輸出的資訊與原始資料的對應關系。

[Hardware Error]: CPU 3: Machine Check Exception: 4 Bank 5: be00000000800400

[Hardware Error]: TSC 128727f47a97 ADDR 3f628bd69349 MISC 1

[Hardware Error]: PROCESSOR 0:106a5 TIME 1450279905 SOCKET 1 APIC 14

[Hardware Error]: Machine check: Processor context corrupt

Kernel panic - not syncing: Fatal Machine check

1

2

3

4

5

[HardwareError]:CPU3:MachineCheckException:4Bank5:be00000000800400

[HardwareError]:TSC128727f47a97ADDR3f628bd69349MISC1

[HardwareError]:PROCESSOR0:106a5TIME1450279905SOCKET1APIC14

[HardwareError]:Machinecheck:Processorcontextcorrupt

Kernelpanic-notsyncing:FatalMachinecheck

其中CPU和Bank是MCE的接收者:

CPU 3 – 表示檢測到MCE錯誤的是3号CPU,對應struct mce的extcpu字段;

Bank 5 – 一組硬體單元稱為一個bank,每個bank對應一組machine-check寄存器;

MCE的錯誤代碼包括兩部分:

Machine Check Exception: 4 – 表示 IA32_MCG_STATUS MSR寄存器的狀态碼是4(含義見後文),對應 mcgstatus字段;

be00000000800400 – 表示 IA32_MCi_STATUS MSR寄存器中的錯誤碼(含義見後文),對應status字段。

Machine Check Excheption: 4 的含義

它來自全局狀态寄存器 IA32_MCG_STATUS MSR,(對應struct mce的 mcgstatus字段),隻用到三個bit,如下所示。4表示machine-check in progress。

crash linux主要指令,crash分析

Bit 0: Restart IP Valid. 表示程式的執行是否可以在被異常中斷的指令處重新開始。

Bit 1: Error IP Valid. 表示被中斷的指令是否與MCE錯誤直接相關。

Bit 2: Machine Check In Progress. 表示 machine check 正在進行中。

be00000000800400 的含義

它來自bank寄存器IA32_MCi_STATUS MSR,(對應struct mce的status字段)。

crash linux主要指令,crash分析

be00000000800400 的二進制位如下:

Bit 63: VAL. 表示本寄存器中包含有效的錯誤碼

Bit 61: UC. 表示是無法糾正的MCE

Bit 60: EN. 表示處于允許報告錯誤的狀态

Bit 59: MISCV. 表示MCi_MISC寄存器中含有對該錯誤的補充資訊

Bit 58: ADDRV. 表示MCi_ADDR寄存器含有發生錯誤的記憶體位址

Bit 57: PCC. 表示該CPU的上下文狀态已被該錯誤破壞,無法恢複軟體代碼的運作

Bits [16:31] 包含特定CPU型号相關的擴充錯誤碼. 本例中是0x0080.

Bits [0:15] 包含MCE錯誤碼,該錯誤碼是所有CPU型号通用的,分為兩類:simple error codes(簡單錯誤碼) 和 compound error codes(複合錯誤碼),本例中0x0400表示Internal timer error:

– Simple Error Codes:

0000 0000 0000 0000 – 沒有錯誤.

0000 0000 0000 0001 – Unclassified. 未分類的錯誤類型.

0000 0000 0000 0010 – ROM微碼校驗錯

0000 0000 0000 0011 – MCE是由于别的CPU的BINT# 引起的.

0000 0000 0000 0100 – Functional redundancy check (FRC) master/slave error.

0000 0000 0000 0101 – Internal parity error.

0000 0100 0000 0000 – Internal timer error.

0000 01xx xxxx xxxx – Internal unclassified error. 至少有一個x等于1

– Compound Error Codes:

000F 0000 0000 11LL – Generic cache hierarchy errors.

000F 0000 0001 TTLL – TLB errors.

000F 0000 1MMM CCCC – Memory controller errors (Intel-only).

000F 0001 RRRR TTLL – Memory errors in the cache hierarchy.

000F 1PPT RRRR IILL – Bus and interconnect errors.

下一步,由于Bits [16:31] 是非零值0x0080,包含的是特定CPU型号相關的擴充錯誤碼,我們要參考Intel手冊第三卷第16章。首先确定CPU型号,我們需要的是CPU faimily和model,從/proc/cpuinfo中可以找到:

# less /proc/cpuinfo

...

processor : 3

vendor_id : GenuineIntel

cpu family : 6

model : 26

model name : Intel(R) Xeon(R) CPU L5520 @ 2.27GHz

stepping : 5

cpu MHz : 2266.700

cache size : 8192 KB

physical id : 1

siblings : 8

core id : 2

cpu cores : 4

apicid : 20

...

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

# less /proc/cpuinfo

...

processor:3

vendor_id:GenuineIntel

cpufamily:6

model:26

modelname:Intel(R)Xeon(R)[email protected]

stepping:5

cpuMHz:2266.700

cachesize:8192KB

physicalid:1

siblings:8

coreid:2

cpucores:4

apicid:20

...

根據cpu family/model,即06_1AH,找到Intel手冊中對應的章節,但是沒找到比對Internal timer error和0x0080的條目。是以隻能到此為止了。

總結我們的發現:

CPU 3 發現了無法糾正的MCE,是Internal timer error,被中斷的指令與MCE不相關,被中斷的程式指令不能恢複運作,CPU的上下文已被MCE破壞。

怎樣禁用MCE

可以在 /boot/grub/grub.conf 中加入以下内容:mce=off。

還有其它的MCE選項,比如禁用CMCI(Corrected Machine Check Interrupt),或者禁用MCE日志,等等,例如:

mce=off  — Disable machine check

mce=no_cmci  — Disable CMCI(Corrected Machine Check Interrupt)

參見文檔:Documentation/x86/x86_64/boot-options.txt

每個 CPU 都有一個sysfs接口:

/sys/devices/system/machinecheck/machinecheckN

注:(N = CPU number)

其中包含的可調參數參見:Documentation/x86/x86_64/machinecheck