VM0/VM1でFedora 20を起動すると、CPU1以降を認識できない
apic_pass.cのデバッグメッセージを有効にしてみた。
Starting a virtual machine. APIC: handle wait-for-sipi state APIC: handle wait-for-sipi state APIC: handle wait-for-sipi state APIC: Ignore writing to off 0x20 APIC: Ignore writing to off 0x20 APIC: Exit wait-for-sipi state APIC: Exit wait-for-sipi state APIC: Exit wait-for-sipi state APIC: Specified DSH is not supported on fixed int: CPU0 ICR 06000000 000400f6 APIC: Specified DSH is not supported on fixed int: CPU0 ICR 06000000 000400f6 APIC: Specified DSH is not supported on fixed int: CPU0 ICR 06000000 000400f6 APIC: Specified DSH is not supported on fixed int: CPU0 ICR 06000000 000400f6 APIC: Specified DSH is not supported on fixed int: CPU0 ICR 06000000 000400f6
linux 3.12.6のソースコードを読んでみました。
arch/x86/kernel/smpboot.c:do_boot_cpuで、「Stuck ??」というメッセージを出力していました。 AP上でtrampolineコードは実行できたが、何かエラーがあったようです。
if (cpumask_test_cpu(cpu, cpu_callin_mask)) { print_cpu_msr(&cpu_data(cpu)); pr_debug("CPU%d: has booted.\n", cpu); } else { boot_error = 1; if (*trampoline_status == 0xA5A5A5A5) /* trampoline started but...? */ pr_err("CPU%d: Stuck ??\n", cpu); else /* trampoline code not run */ pr_err("CPU%d: Not responding\n", cpu); if (apic->inquire_remote_apic) apic->inquire_remote_apic(apicid); }
arch/x86/realmode/rm/trampoline_64.S:trampoline_startの先頭で、trampoline_stateに0xA5A5A5A5を書き込んでいました。
ENTRY(trampoline_start) cli # We should be safe anyway wbinvd LJMPW_RM(1f) 1: mov %cs, %ax # Code and data in the same place mov %ax, %ds mov %ax, %es mov %ax, %ss movl $0xA5A5A5A5, trampoline_status # write marker for master knows we're running
「APIC: Exit wait-for-sipi state」が一行出力された直後に手動でパニックさせてみました。
SIPIで起床したはずのCPU2は、VMMのtimer_threadがscheduleの中でspinlock待ちでした。
CPU2 panic: Fatal interrupt in VMM: 0x02 NMI CR0: 0x80000039 CR2: 0x00000000 CR3: 0xB4D5C000 CR4: 0x00042668 RSP on interrupt: 0x40397F48 Stack information: +00 Error code / RIP : 0x40126347 +32 RSP / SS : 0x00000058 +08 RIP / CS : 0x00000050 +40 SS / : 0x4012633D +16 CS / RFLAGS : 0x00000002 +48 / : 0x00000000 +24 RFLAGS / RSP : 0x40397F78 +56 / : 0x00000000 RAX: 0x40336400 RCX: 0x40397F58 RDX: 0x40336400 RBX: 0x00000000 RSP: 0x40397EF0 RBP: 0x40397F98 RSI: 0x000F4240 RDI: 0x40397F58 R8: 0x00000000 R9: 0x00000000 R10: 0xC0000000 R11: 0xFFFFFFFFF000 R12: 0x00000000 R13: 0x00000001 R14: 0x40336654 R15: 0x00000000 ES: 0x0058 CS: 0x0050 SS: 0x0058 DS: 0x0058 FS: 0x0058 GS: 0x0080 VMM state of CPU2 ------------------------------ RAX 00000031 RCX 00001181 RDX 40336400 RBX 40397E90 RSP 40397C80 RBP 40397DC0 RSI 00000000 RDI 00000000 R8 00000000 R9 40397B41 R10 00000002 R11 00000000 R12 4014ABD8 R13 40397DD8 R14 00000001 R15 403EA320 CR0 80000039 CR2 00000000 CR3 B4D5C000 CR4 00042668 RFLAGS 00000006 GDTR 40336400+0000FFFF IDTR 401B5B80+0000FFFF backtrace: 0x40397c78: 0x4011a43b 0x40397dc8: 0x4011ac78 0x40397e28: 0x40141ecc 0x40397e48: 0x40114663 0x40397e88: 0x40114818 0x40397fa0: 0x40126ed0 0x40397fe0: 0x40126a49 0x40398000: 0x8f58363419e54f59 ------------------------------------------------ Guest state of CPU2 ---------------------------- RAX 001407F0 RCX 77BAE3DF RDX 06000018 RBX 02100800 RSP 0009C020 RBP 00000000 RSI 00000000 RDI 00000000 R8 00000000 R9 00000000 R10 00000000 R11 00000000 R12 00000000 R13 00000000 R14 00000000 R15 00000000 CR0 00000001 CR2 00000000 CR3 00000000 CR4 001407F0 ACR ES 0000C093 CS 0000C09B SS 0000C093 DS 0000C093 FS 0000C093 GS 0000C093 LIMIT ES FFFFFFFF CS FFFFFFFF SS FFFFFFFF DS FFFFFFFF FS FFFFFFFF GS FFFFFFFF BASE ES 00000000 CS 00000000 SS 00000000 DS 00000000 FS 00000000 GS 00000000 SEL ES 00000018 CS 00000008 SS 00000018 DS 00000018 FS 00000018 GS 00000018 RIP 00098EA8 RFLAGS 00010002 GDTR 00097030+0000001F IDTR 00000000+00000000 EFER 00000000 Exit reason: 0x0 (Exception or NMI) Exit qualification 00098ea8 Exit intr info 80000b0e Exit intr errcode 00000011 VMCS IDTR 00000000+00000000 VMCS RFLAGS 00010002 pe=1 pg=0 sw:en=0x0 es=0x9700 cs=0x9700 ss=0x9700 ds=0x9700 fs=0x0 gs=0x0
(gdb) list *0x40126347 0x40126347 is in schedule (../include/core/spinlock.h:83). 78 : "=abcd" (old), /* output 0 */ 79 #endif 80 "=m" (*lock) /* output 1 */ 81 : "0" ((u8)1) /* input 0 */ 82 ); 83 if (old == 0) { 84 return; 85 } 86 enable_interrupt(); 87 (gdb) list *0x40126ed0 0x40126ed0 is in timer_thread (timer.c:152). 147 } 148 spinlock_unlock (¤tcpu->timer_lock); 149 if (call) 150 callback (p, data); 151 else 152 schedule (); 153 } 154 } 155 156 static void
もう一回やってみると、timer_threadが現在の時刻を取得中でした。
CPU2 panic: Fatal interrupt in VMM: 0x02 NMI CR0: 0x80000039 CR2: 0x00000000 CR3: 0xB4D5C000 CR4: 0x00042668 RSP on interrupt: 0x4038FF18 Stack information: +00 Error code / RIP : 0x40107A3F +32 RSP / SS : 0x00000058 +08 RIP / CS : 0x00000050 +40 SS / : 0x40126C7A +16 CS / RFLAGS : 0x00000046 +48 / : 0x00000005 +24 RFLAGS / RSP : 0x4038FF40 +56 / : 0x0159B9FD RAX: 0x00000000 RCX: 0x4038FF58 RDX: 0x00000000 RBX: 0xBC246850 RSP: 0x4038FEC0 RBP: 0x4038FF98 RSI: 0xBC246850 RDI: 0x4038FF58 R8: 0x00000000 R9: 0x00000000 R10: 0xC0000000 R11: 0xFFFFFFFFF000 R12: 0x00001748 R13: 0x10A6C740BC R14: 0x40336654 R15: 0x40336400 ES: 0x0058 CS: 0x0050 SS: 0x0058 DS: 0x0058 FS: 0x0058 GS: 0x0080 VMM state of CPU2 ------------------------------ RAX 00000031 RCX 00001183 RDX 40336400 RBX 4038FE60 RSP 4038FC50 RBP 4038FD90 RSI 00000000 RDI 00000000 R8 00000000 R9 4038FB11 R10 00000002 R11 00000000 R12 4014ABD8 R13 4038FDA8 R14 00000001 R15 403EA320 CR0 80000039 CR2 00000000 CR3 B4D5C000 CR4 00042668 RFLAGS 00000002 GDTR 40336400+0000FFFF IDTR 401B5B80+0000FFFF backtrace: 0x4038fc48: 0x4011a43b 0x4038fd98: 0x4011ac78 0x4038fdf8: 0x40141ecc 0x4038fe18: 0x40114663 0x4038fe58: 0x40114818 0x4038ffa0: 0x40126e1a 0x4038ffe0: 0x40126a49 0x40390000: 0xdf06deeef67473d9 ------------------------------------------------ Guest state of CPU2 ---------------------------- RAX 001407F0 RCX 77BAE3DF RDX 06000018 RBX 02100800 RSP 0009C020 RBP 00000000 RSI 00000000 RDI 00000000 R8 00000000 R9 00000000 R10 00000000 R11 00000000 R12 00000000 R13 00000000 R14 00000000 R15 00000000 CR0 00000001 CR2 00000000 CR3 00000000 CR4 001407F0 ACR ES 0000C093 CS 0000C09B SS 0000C093 DS 0000C093 FS 0000C093 GS 0000C093 LIMIT ES FFFFFFFF CS FFFFFFFF SS FFFFFFFF DS FFFFFFFF FS FFFFFFFF GS FFFFFFFF BASE ES 00000000 CS 00000000 SS 00000000 DS 00000000 FS 00000000 GS 00000000 SEL ES 00000018 CS 00000008 SS 00000018 DS 00000018 FS 00000018 GS 00000018 RIP 00098EA8 RFLAGS 00010002 GDTR 00097030+0000001F IDTR 00000000+00000000 EFER 00000000 Exit reason: 0x0 (Exception or NMI) Exit qualification 00098ea8 Exit intr info 80000b0e Exit intr errcode 00000011 VMCS IDTR 00000000+00000000 VMCS RFLAGS 00010002 pe=1 pg=0 sw:en=0x0 es=0x9700 cs=0x9700 ss=0x9700 ds=0x9700 fs=0x0 gs=0x0
(gdb) list *0x40107A3F No source file for address 0x40107a3f. (gdb) list *0x40126a49 (gdb) list *0x40126e1a 0x40126e1a is in timer_thread (timer.c:135). 130 VAR_IS_INITIALIZED (data); 131 for (;;) { 132 call = false; 133 spinlock_lock (¤tcpu->timer_lock); 134 time = get_cpu_time (); 135 p = LIST1_POP (currentcpu->timer_on_list); 136 if (p) { 137 ASSERT(p->enable); 138 if ((time - p->settime) >= p->interval) { 139 p->enable = false;
画面に「Stuck ??」と表示されたあとに、panicさせてみると、ゲストソフトウェアの実行中でした。
CPU2 panic: NMI recieved while executing guest software. VMM state of CPU2 ------------------------------ RAX 00000031 RCX 000018A4 RDX 40336400 RBX 00000000 RSP 40367CD0 RBP 40367E10 RSI 00000000 RDI 00000000 R8 00000000 R9 40367B91 R10 00000002 R11 00000000 R12 4014C250 R13 40367E28 R14 00000000 R15 00000000 CR0 80000039 CR2 00000000 CR3 B4D5C000 CR4 00042668 RFLAGS 00000006 GDTR 40336400+0000FFFF IDTR 401B5B80+0000FFFF backtrace: 0x40367cc8: 0x4011a43b 0x40367e18: 0x4011a211 0x40367e78: 0x4012adc5 0x40367ec8: 0x4012b1cc 0x40367fc8: 0x4011530d 0x40367ff8: 0x0 ------------------------------------------------ Guest state of CPU2 ---------------------------- RAX 001407F0 RCX 77BAE3DF RDX 06000018 RBX 02100800 RSP 0009C020 RBP 00000000 RSI 00000000 RDI 00000000 R8 00000000 R9 00000000 R10 00000000 R11 00000000 R12 00000000 R13 00000000 R14 00000000 R15 00000000 CR0 00000001 CR2 00000000 CR3 00000000 CR4 001407F0 ACR ES 0000C093 CS 0000C09B SS 0000C093 DS 0000C093 FS 0000C093 GS 0000C093 LIMIT ES FFFFFFFF CS FFFFFFFF SS FFFFFFFF DS FFFFFFFF FS FFFFFFFF GS FFFFFFFF BASE ES 00000000 CS 00000000 SS 00000000 DS 00000000 FS 00000000 GS 00000000 SEL ES 00000018 CS 00000008 SS 00000018 DS 00000018 FS 00000018 GS 00000018 RIP 00098EA8 RFLAGS 00010002 GDTR 00097030+0000001F IDTR 00000000+00000000 EFER 00000000 Exit reason: 0x0 (Exception or NMI) Exit qualification 00000000 Exit intr info 80000202 Exit intr errcode 000159ec VMCS IDTR 00000000+00000000 VMCS RFLAGS 00010002 pe=1 pg=0 sw:en=0x0 es=0x9700 cs=0x9700 ss=0x9700 ds=0x9700 fs=0x0 gs=0x0 ------------------------------------------------
上記3つのpanicの共通点は、ゲストがプロテクトモードでかつ、ページングがオフで、かつ、RIPが00098EA8であることです。 何かを待っているのかもしれません。
yuichi_xy への返信
上記3つのpanicの共通点は、ゲストがプロテクトモードでかつ、ページングがオフで、かつ、RIPが00098EA8であることです。 何かを待っているのかもしれません。
プロテクトモードでかつ、ページングがオフであることからは、arch/x86/realmode/rm/trampoline_64.Sの以下のコードの実行中の可能性があります。 しかし、ループしているようなコードはありません。
# Enable protected mode movl $X86_CR0_PE, %eax # protected mode (PE) bit movl %eax, %cr0 # into protected mode # flush prefetch and jump to startup_32 ljmpl $__KERNEL32_CS, $pa_startup_32 no_longmode: hlt jmp no_longmode #include "../kernel/verify_cpu.S" .section ".text32","ax" .code32 .balign 4 ENTRY(startup_32) movl %edx, %ss addl $pa_real_mode_base, %esp movl %edx, %ds movl %edx, %es movl %edx, %fs movl %edx, %gs movl pa_tr_cr4, %eax movl %eax, %cr4 # Enable PAE mode # Setup trampoline 4 level pagetables movl $pa_trampoline_pgd, %eax movl %eax, %cr3 # Set up EFER movl pa_tr_efer, %eax movl pa_tr_efer + 4, %edx movl $MSR_EFER, %ecx wrmsr # Enable paging and in turn activate Long Mode movl $(X86_CR0_PG | X86_CR0_WP | X86_CR0_PE), %eax movl %eax, %cr0
Debianのlinux 3.2のソースコードは次のようになっており、違いがあります。
arch/x86/kernel/trampoline_64.S
mov $X86_CR0_PE, %ax # protected mode (PE) bit lmsw %ax # into protected mode # flush prefetch and jump to startup_32 ljmpl *(startup_32_vector - r_base) .code32 .balign 4 startup_32: movl $__KERNEL_DS, %eax # Initialize the %ds segment register movl %eax, %ds movl $X86_CR4_PAE, %eax movl %eax, %cr4 # Enable PAE mode # Setup trampoline 4 level pagetables leal (trampoline_level4_pgt - r_base)(%esi), %eax movl %eax, %cr3 movl $MSR_EFER, %ecx movl $(1 << _EFER_LME), %eax # Enable Long Mode xorl %edx, %edx wrmsr # Enable paging and in turn activate Long Mode # Enable protected mode movl $(X86_CR0_PG | X86_CR0_PE), %eax movl %eax, %cr0
98ea8 の命令を手作業で逆アセンブルしてみましたが、もとのコードに一致せず、逆アセンブルが正しいのか、全然違う場所を実行しているのか分かりませんでした。
debug> dp 98ea0 00098EA0 A1 10 B0 09 00 0F 22 E0-B8 00 A0 09 00 0F 22 D8 ......".......". 00098EB0 A1 08 B0 09 00 8B 15 0C-B0 09 00 B9 80 00 00 C0 ................ 00098EC0 0F 30 B8 01 00 01 80 0F-22 C0 EA 30 8F 09 00 10 .0......"..0.... 00098ED0 00 66 90 66 90 66 90 66-90 66 90 66 90 66 90 90 .f.f.f.f.f.f.f.. 00098EE0 B8 18 00 00 00 8E D8 0F-01 15 30 70 09 00 0F 20 ..........0p... 00098EF0 C0 25 FF FF FF 7F 0F 22-C0 EA 00 8F 09 00 08 00 .%....."........ 00098F00 31 C0 31 D2 B9 80 00 00-C0 0F 30 89 F8 0F 01 1D 1.1.......0..... 00098F10 60 70 09 00 0F 01 15 70-70 09 00 B9 10 00 00 00 `p.....pp....... B8 MOV rAX/r8, Iv I Immediate data v Word, doubleword or quadword (in 64-bit mode), depending on operand-size attribute. mov 00090a00, eax
デバッグログを出力するパッチ(32812_140105.patch)を作成してみました。 hlt命令は実行されていないようです。 やはり、プロテクトモードになっただけで、ページングは有効になっていないようです。
> panicAPIC: Ignore writing to off 0x20 APIC: Ignore writing to off 0x20 APIC: Exit wait-for-sipi state DEBUG: pe_change pe 1 ip 0x103c sw.enable 0 CPU6 panic : Panic requested by user
yuichi_xy への返信
Exit reason: 0x0 (Exception or NMI) Exit qualification 00098ea8 Exit intr info 80000b0e Exit intr errcode 00000011 VMCS IDTR 00000000+00000000 VMCS RFLAGS 00010002
これは、98ea8の命令を実行しようとした時に、page-level protection violationによるページフォールトが発生したことを示しています。 もしかすると、ページフォールトが発生し続けて処理が先に進まないのかもしれません。
yuichi_xy への返信
yuichi_xy への返信
Exit reason: 0x0 (Exception or NMI) Exit qualification 00098ea8 Exit intr info 80000b0e Exit intr errcode 00000011 VMCS IDTR 00000000+00000000 VMCS RFLAGS 00010002
これは、98ea8の命令を実行しようとした時に、page-level protection violationによるページフォールトが発生したことを示しています。 もしかすると、ページフォールトが発生し続けて処理が先に進まないのかもしれません。
CR0 00000001 CR2 00000000 CR3 00000000 CR4 001407F0
CR4のビット20「Enables supervisor-mode execution prevention (SMEP)」が立っていました。 ページング無効の場合、Shadow Page TableのPTEはUSビットが立ちますが(=User Mode)、プロテクトモードの場合、Super Modeになるので、ページフォールトが発生したと考えられます。
次の2つの問題を、r151で修正しました。
yuichi_xy への返信
* 自分宛のIPIの送信にVMMが対応していないため送信に失敗している
yuichi_xy への返信
yuichi_xy への返信
yuichi_xy への返信
Exit reason: 0x0 (Exception or NMI) Exit qualification 00098ea8 Exit intr info 80000b0e Exit intr errcode 00000011 VMCS IDTR 00000000+00000000 VMCS RFLAGS 00010002
これは、98ea8の命令を実行しようとした時に、page-level protection violationによるページフォールトが発生したことを示しています。 もしかすると、ページフォールトが発生し続けて処理が先に進まないのかもしれません。
CR0 00000001 CR2 00000000 CR3 00000000 CR4 001407F0 CR4のビット20「Enables supervisor-mode execution prevention (SMEP)」が立っていました。 ページング無効の場合、Shadow Page TableのPTEはUSビットが立ちますが(=User Mode)、プロテクトモードの場合、Super Modeになるので、ページフォールトが発生したと考えられます。
VM0/VM1でFedora 20を起動すると、CPU1以降を認識できない