mce 패닉 @4.18 커널이 @5.15 커널을 통과하는 이유는 무엇입니까?

mce 패닉 @4.18 커널이 @5.15 커널을 통과하는 이유는 무엇입니까?

수정되지 않은 오류를 삽입할 때 CentOS 커널 4.18에서 테스트가 충돌하지만 업스트림 커널 5.15에서는 통과합니다.

이 문제는 다음과 관련될 수 있습니다.

수정되지 않은 오류를 삽입한 후 시스템을 재부팅합니다.

Panic_on_warn==0일 때 커널 패닉이 발생하는 이유는 무엇입니까?

호출 추적을 요약하려면 다음을 수행하십시오.

[   242.337362] kernel BUG at arch/x86/kernel/cpu/mce/core.c:1364!

이 커널(CentOS 8.5.2111 커널)을 확인했는데 1364행은 다음과 같습니다.

1363 out_ist:
1364    nmi_exit();

PS CentOS 커널의 코드는 업스트림 커널과 매우 다르게 보입니다.

그런 다음 BUG_ON(!in_nmi());(내 이해로는) 트리거

#define nmi_exit()                      \
    do {                            \
        lockdep_hardirq_exit();             \
        rcu_nmi_exit();                 \
        BUG_ON(!in_nmi());              \
        __preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET);   \
        ftrace_nmi_exit();              \
        lockdep_on();                   \
        printk_nmi_exit();              \
        arch_nmi_exit();                \
    } while (0)

CentOS 4.18 커널 다운로드는 다음과 같습니다.

https://vault.centos.org/8.5.2111/BaseOS/Source/SPackages/kernel-4.18.0-348.el8.src.rpm

전체 로그:

[root@localhost GreenTea]# ./einj_mem_uc -f 'single'

0: single   vaddr = xxxxxxxx paddr = xxxxx[   242.248140] core: Uncorrected hardware memory error in user-access at xxxxxxxx
[   242.248410] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 0
[   242.257296] BUG: scheduling while atomic: einj_mem_uc/9237/0x00110000
a400
[   242.258700] Memory failure: xxxx: Killing einj_mem_uc:9237 due to hardware memory corruption
[   242.267021] {1}[Hardware Error]: event severity: recoverable
[   242.267022] {1}[Hardware Error]:  Error 0, type: recoverable
[   242.267023] {1}[Hardware Error]:  fru_text: Card01, ChnG, DIMM0
[   242.267023] {1}[Hardware Error]:   section_type: memory error
[   242.267024] {1}[Hardware Error]:   error_status: 0x0000000000000400
[   242.267024] {1}[Hardware Error]:   physical_address: 0x00000004805da400
[   242.267026] {1}[Hardware Error]:   node: 0 card: 6 module: 0 rank: 0 bank: 16 device: 0 row: 8835 column: 16 
[   242.267026] {1}[Hardware Error]:   error_type: 4, single-symbol chipkill ECC
[   242.267027] {1}[Hardware Error]:   DIMM location: _Node0_Channel6_Dimm0 CPU0_G0 
[   242.267053] Memory failure: xxxxx: already hardware poisoned
[   242.274392] Memory failure: xxxxx: recovery action for dirty LRU page: Recovered
[   242.285519] EDAC skx MC3: HANDLING MCE MEMORY ERROR
[   242.318662] ------------[ cut here ]------------
[   242.326171] EDAC skx MC3: CPU 0: Machine Check Event: 0x0 Bank 255: 0xb40000000000009f
[   242.337362] kernel BUG at arch/x86/kernel/cpu/mce/core.c:1364!
[   242.337366] invalid opcode: 0000 [#1] SMP NOPTI
[   242.337367] CPU: 139 PID: 9237 Comm: einj_mem_uc Kdump: loaded Tainted: G   M    W        --------- -  - 4.18.0-348.el8.x86_64 #1
[   242.337368] Hardware name: Foo Inc. Foo  BIOS 4C012 01/21/2022
[   242.345383] EDAC skx MC3: TSC 0x0 
[   242.345383] EDAC skx MC3: ADDR 0x4805da400 
[   242.353765] RIP: 0010:do_machine_check+0xb10/0xc70
[   242.353766] Code: 42 bf f4 01 00 00 e8 df 92 92 00 8b 05 b9 cb e2 01 41 39 c7 7e 2d 4c 89 ee 4c 89 e7 e8 09 ec ff ff 85 c0 74 dc e9 17 fe ff ff <0f> 0b 0f 0b 8b 35 1a 6c 7e 01 e9 05 fb ff ff c7 05 87 cb e2 01 01
[   242.353766] RSP: 0018:ff2f652d53383e58 EFLAGS: 00010046
[   242.353767] RAX: 0000000080000000 RBX: 00000000004805da RCX: 3ffffffffffffffe
[   242.353768] RDX: ff121aa3ffbeaf40 RSI: 0000000000000001 RDI: ff121a69005db000
[   242.360497] EDAC skx MC3: MISC 0x0 
[   242.360498] EDAC skx MC3: PROCESSOR 0:0x806f6 TIME 1529665988 SOCKET 0 APIC 0x0
[   242.369175] RBP: ff121a65a70f3c80 R08: ff121a6480000010 R09: 0000000000000000
[   242.369176] R10: 0000000000000002 R11: 0000000000000003 R12: 0000000000000000
[   242.369176] R13: 0000000000000000 R14: ff121aa3ffb95ce0 R15: 0000000000000014
[   242.369177] FS:  00007fe1bde23640(0000) GS:ff121aa3ffbc0000(0000) knlGS:0000000000000000
[   242.369177] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   242.369177] CR2: 00007f50808270cc CR3: 00000001d0118001 CR4: 0000000000771ee0
[   242.369178] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   242.369178] DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400
[   242.369179] PKRU: 55555554
[   242.369179] Call Trace:
[   242.369182]  ? machine_check+0x25/0x40
[   242.374751] EDAC MC3: 1 UE memory read error on CPU_SrcID#0_MC#3_Chan#0_DIMM#0 (channel:0 slot:0 page:0x4805da offset:0x400 grain:32 -  err_code:0x0000:0x009f  SystemAddress:0x4805da400 ProcessorSocketId:0x0 MemoryControllerId:0x3 ChannelAddress:0x800bb400 ChannelId:0x0 RankAddress:0x2002ed00 PhysicalRankId:0x0 DimmSlotId:0x0 DimmRankId:0x0 Row:0x2283 Column:0x10 Bank:0x0 BankGroup:0x4 ChipSelect:0x0)
[   242.380013]  machine_check+0x2f/0x40
[   242.380015] RIP: 0033:0x403f5b
[   242.380015] Code: 89 05 cd 37 20 00 8b 05 c7 37 20 00 c3 53 48 8b 1d 92 37 20 00 e8 2b d5 ff ff 48 8d 84 1b 76 14 40 00 48 f7 db 48 21 d8 5b c3 <0f> be 07 c3 0f be 07 0f be 57 01 01 d0 c3 48 8b 47 ff c3 c6 07 61
[   242.380016] RSP: 002b:00007ffcfb9e6098 EFLAGS: 00010206
[   242.380016] RAX: 0000000000607280 RBX: 0000000000607280 RCX: 0000000001b7b010
[   242.380017] RDX: 0000000000000000 RSI: 0000000000000001 RDI: 00007fe1bde21400
[   242.380017] RBP: 00007fe1bde21400 R08: 0000000001b7b04a R09: 0000000000000000
[   242.380017] R10: 0000000000000000 R11: 0000000000000206 R12: 0000000000000001
[   242.380018] R13: 00007ffcfb9e6410 R14: 0000000000000000 R15: 0000000000000000
[   242.380018] Modules linked in: einj xt_CHECKSUM ipt_MASQUERADE xt_conntrack ipt_REJECT nft_compat nf_nat_tftp nft_objref nf_conntrack_tftp nft_counter tun bridge stp llc nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nf_tables_set nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip_set nf_tables nfnetlink sunrpc vfat fat sd_mod sg intel_rapl_msr intel_rapl_common i10nm_edac nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel iTCO_wdt intel_pmt_telemetry intel_pmt_crashlog iTCO_vendor_support intel_pmt_class kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcspkr rapl intel_th_gth ipmi_ssif uas intel_th_pci isst_if_mbox_pci isst_if_mmio idxd usb_storage joydev intel_pmt intel_th i2c_i801 isst_if_common i2c_ismt wmi acpi_ipmi ipmi_si ipmi_devintf ipmi_msghandler acpi_pad acpi_power_meter xfs libcrc32c ast i2c_algo_bit drm_vram_helper drm_kms_helper syscopyarea sysfillrect
[   242.380033]  sysimgblt fb_sys_fops drm_ttm_helper ttm crc32c_intel nvme ahci drm nvme_core libahci libata t10_pi pinctrl_emmitsburg dm_mirror dm_region_hash dm_log dm_mod fuse
[    0.000000] Linux version 4.18.0-348.el8.x86_64 ([email protected]) (gcc version 8.5.0 20210514 (Red Hat 8.5.0-3) (GCC)) #1 SMP Mon Oct 4 12:17:22 EDT 2021

이게 패닉을 일으키는 것 같은데(?) nmi_exit();왜 opcode가 0000인가요?

이 로그의 근본 원인은 무엇 kernel BUG at arch/x86/kernel/cpu/mce/core.c:1364!이며 호출 추적 중에 커널이 다시 시작되는 이유는 무엇입니까?

20220908 업데이트:

#define nmi_enter()                     \
    do {                            \
        arch_nmi_enter();               \
        printk_nmi_enter();             \
        lockdep_off();                  \
        ftrace_nmi_enter();             \
        BUG_ON(in_nmi() == NMI_MASK);           \
        __preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET);   \
        rcu_nmi_enter();                \
        lockdep_hardirq_enter();            \
    } while (0)

#define nmi_exit()                      \
    do {                            \
        lockdep_hardirq_exit();             \
        rcu_nmi_exit();                 \
        BUG_ON(!in_nmi());              \
        __preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET);   \
        ftrace_nmi_exit();              \
        lockdep_on();                   \
        printk_nmi_exit();              \
        arch_nmi_exit();                \
    } while (0)

제가 이해한 바로는 두 번째 항목이 발생하더라도 트리거가 do_machine_check()발생해서는 안 됩니다 .BUG_ON(!in_nmi())

전임자:

__preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET);
__preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET);
BUG_ON(!in_nmi());

__preempt_count_add"OR" 연산이 아닙니다.

static inline void __preempt_count_add(int val)
{
    u32 pc = READ_ONCE(current_thread_info()->preempt.count);
    pc += val;
    WRITE_ONCE(current_thread_info()->preempt.count, pc);
}

기타:

이 줄은 PASS(업스트림 커널 5.15) 로그에 없습니다.

[   242.257296] BUG: scheduling while atomic: einj_mem_uc/9237/0x00110000

답변1

아래에 나열된 몇 가지 사실을 바탕으로 내 작업 이론은 수정되지 않은 하드웨어 메모리 오류(UHME)가 발생하여 NMI가 발생했다는 것입니다. NMI 처리 중 페이지 폴트가 발생했습니다. 선점 수를 늘리면 작업 순서 문제가 발생하거나 nmi_handler 내에서 페이지 오류를 허용하는 버그가 있을 수 있습니다.

  • CentOS 4.18.0.348의 코드는 메인라인 Linux 4.18.0 코드 베이스와 크게 다릅니다. 5.x 버전의 많은 기능이 CentOS 4.18.0.x로 백포트되었습니다. 이 코드는 RedHat에서만 검토되었으므로 오류가 발생할 가능성이 더 높습니다.

내 연구 의견은 다이어그램이 사건의 흐름을 보여준다는 것입니다.

  1. 사용자 모드 einj_mem_uc.
  2. nmi_enter()를 시작합니다. in_nmi()는 preempt_count_add()가 true로 설정될 때까지 false입니다.
  3. nmi 핸들러는 내부적으로 NMI 인터럽트 처리를 시작합니다.
  4. 페이지 폴트가 발생하고 페이지 폴트 핸들러로 점프합니다.
  5. 페이지 폴트 핸들러는 in_nmi()를 true로 유지하고 iret으로 종료됩니다.
  6. Intel iret 결함으로 인해 in_nmi() 값이 false로 지워집니다.
  7. 핸들러 내부의 in_nmi()가 false인 hmi 핸들러를 반환합니다.
  8. nmi 핸들러는 BUG_ON(!in_nmi()) 검사를 트리거하는 nmi_exit를 반환합니다.
  9. 이로 인해 패닉이 발생하고 중지되거나 다시 시작됩니다.

차트

나는 메인라인 4.18.1이 5.15 커널처럼 작동할 것이라고 생각합니다.

처음에는 다른 소스 코드 작업을 완료했습니다.질문.

답변2

댓글과 답변을 하다가 의심했던 대로첫 번째 관련 질문일반적으로 이중 오류가 발생합니다. 여기에 추가합니다. 트리플이 있을 수 있습니다. (4.18에서 감소)

4.18의 경우에만(이 커널 옵션은 5.7에서만 사용 가능하므로) 커널 .config 파일에서 설정을 확인하는 것이 좋습니다.CONFIG_이중 오류이렇게 하면 이중 오류 예외 처리기가 활성화됩니다.
(주석 참고: 이 옵션을 비활성화하면... 흰머리가 더 많아질 수 있습니다. ;-) ) 설정하지 않으면 커널이 상황을 처리할 수 없으며 자동으로 재부팅됩니다.
설정했다면 실제로 4.18에서 삼중 실패에 직면하게 됩니다. (적어도 두 번째 추적 덤프가 시작될 것으로 예상했기 때문에 이것이 가능성이 없다고 생각합니다.) => CONFIG_DOUBLEFAULT가 4.18 구성에 설정되지 않은 것 같습니다.


5.15에서는 왜 이런 일이 발생하지 않습니까?:

5.8부터 x32 아키텍처가 이중 오류를 처리하는 이전 방식을 유지하는 경우 x86_64 아키텍처는 다음 기능의 이점을 누릴 수 있습니다(i386에서는 사용할 수 없음).인터럽트 스택 테이블. 이를 통해 이중 오류 또는 NMI와 같은 지정된 이벤트에 대해 새 스택으로 자동 전환할 수 있습니다.
초기 메모리 오류는 스택(원자적 컨텍스트에서 예약됨)과 관련되므로 추적 덤프에서는 이중 오류가 발생하고 백트레이스 덤프에서는 삼중 오류가 발생합니다.
x86_64의 5.8부터 메모리 오류 없이 새로운 스택으로 전환할 수 있는 가능성은 이중 오류를 원활하게 처리하는 데 도움이 됩니다.

답변3

커널과 아무 관련이 없으며 이전 커널 대신 최신 커널로 해당 메모리 주소에 도달하는 하드웨어 메모리 버그일 뿐이라고 생각합니다. 기억력 테스트를 해본 적이 있나요?

답변4

BUG_ON(true)커널 BUG를 유발하는 것 같습니다 .invalid opcode 0000

이런 경우라면,

BUG_ON(!in_nmi());

이 덤프를 트리거하십시오.

관련 정보