Baytrail-M NUC(DN2820FYKH)でFreeBSDが起動しなかった話
bhyve用にこれ買ってみたんですよ、これ。まぁ新しいハードだし地雷だろうなと思ってたんだけど、面白そうにおもっちゃってつい人柱っちゃったんですよ。はい。
したらもういきなりドハマリして。
- FreeBSDが入っている2.5インチHDDを繋いでもレガシーブートモードでブートセクタが認識されている様子が無い
- USBメモリやUSB CD-ROMを認識する気配も無い
- ふと何となくHDDを抜いてUSBメモリを刺したらUbuntuがあっさり起動
- …それ、電源容量足りてないのでは?
- HDDをSSDに差し替えてみたらUSBメモリとSSD両方認識
- でもUEFIの設定画面でブートデバイスのリスト空になったりするし、ブートセレクタでUSBメモリでてこないし
- UEFIの設定画面のメモリ容量0GBだし
- UEFIの設定画面からネット経由のファームアップを選んだらエラーメッセージ
- UEFIの設定画面からUSBメモリ経由のファームアップを実行したらフリーズ
- もうなんか全然うまくいかないので別のマシンでSSDにFreeBSDをインストールしてきてから、NUCに刺してみる
- かーねるぱにっく!
- インストールするFreeBSDのバージョンを変えたり試行錯誤してみたら、動く組み合わせを発見
- 無事起動!
- でもよくみると、USBコントローラがdmesgにエラーを吐きまくって発狂してて動いてない。CPUコアは2つのはずだが1つしか見えてない。
- これ、ACPIのテーブルがちゃんと読めてないか壊れてたりするのでは?
- dmesgみると「ACPI BIOS Warning (bug): Incorrect checksum in table [DSDT] - 0x8E, should be 0x51 (20130823/tbprint-233」とか出てる
- ACPIのテーブル、ちゃんと読めてないか壊れてるとしか思えない
- USBメモリでブートしてACPIテーブルのダンプを取る→再コンパイル→エラー無し。FreeBSDでだけおかしいのだろうか?
- BIOSリカバリモードでなら無事ファームアップできるらしいと教えて貰ったので試してみる
- FreeBSDがまたカーネルパニックするようになった!←イマココ
で、どんなpanicを起こしているかを見てみるわけですね。
こちらはverbose modeで起動時のpanic画面で、「Bogus Interrupt Trigger Mode」で止まってます。
static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source) { switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { case ACPI_MADT_TRIGGER_CONFORMS: if (Source == AcpiGbl_FADT.SciInterrupt) return (INTR_TRIGGER_LEVEL); else return (INTR_TRIGGER_EDGE); case ACPI_MADT_TRIGGER_EDGE: return (INTR_TRIGGER_EDGE); case ACPI_MADT_TRIGGER_LEVEL: return (INTR_TRIGGER_LEVEL); default: panic("Bogus Interrupt Trigger Mode"); } }
何らかのデバイスの割り込み設定をパースしている所に見えます。
で、取り敢えず先に進みたいと思ったので、panicをコメントアウトして、PCIデバイスの割り込みで通常使われているINTR_TRIGGER_LEVELをreturnするようにコードを適当に書き換えてみます。
すると、今度は「Bogus Interrupt Polarity」でpanicしました。
コードではこの辺ですね。
static enum intr_polarity interrupt_polarity(UINT16 IntiFlags, UINT8 Source) { switch (IntiFlags & ACPI_MADT_POLARITY_MASK) { case ACPI_MADT_POLARITY_CONFORMS: if (Source == AcpiGbl_FADT.SciInterrupt) return (INTR_POLARITY_LOW); else return (INTR_POLARITY_HIGH); case ACPI_MADT_POLARITY_ACTIVE_HIGH: return (INTR_POLARITY_HIGH); case ACPI_MADT_POLARITY_ACTIVE_LOW: return (INTR_POLARITY_LOW); default: panic("Bogus Interrupt Polarity"); } }
で、今度もpanicをコメントアウトして、取り敢えず適当にINTR_POLARITY_LOWを返すように書き換えてみます。
…すると、問題なく動作するようになりました。
でも、このエラーは何だったのでしょう。dmesgやソースコードを眺めた感じでは、MADTというテーブルのパース中に、あるデバイスの割り込み設定を取りに行ったら範囲外の値を受け取ってカーネルの実行を止めたというように読み取れます。
ではどんな値が来てるのかdmesgに表示してみましょう。
こんなprintfを入れてみました:
diff --git a/sys/x86/acpica/madt.c b/sys/x86/acpica/madt.c index 9dfb77f..fdc86c0 100644 --- a/sys/x86/acpica/madt.c +++ b/sys/x86/acpica/madt.c @@ -308,14 +308,15 @@ interrupt_polarity(UINT16 IntiFlags, UINT8 Source) case ACPI_MADT_POLARITY_ACTIVE_LOW: return (INTR_POLARITY_LOW); default: - panic("Bogus Interrupt Polarity"); + printf("Bogus Interrupt Polarity %x, set to low\n", + IntiFlags & ACPI_MADT_POLARITY_MASK); + return (INTR_POLARITY_LOW); } } static enum intr_trigger interrupt_trigger(UINT16 IntiFlags, UINT8 Source) { - switch (IntiFlags & ACPI_MADT_TRIGGER_MASK) { case ACPI_MADT_TRIGGER_CONFORMS: if (Source == AcpiGbl_FADT.SciInterrupt) @@ -327,7 +328,9 @@ interrupt_trigger(UINT16 IntiFlags, UINT8 Source) case ACPI_MADT_TRIGGER_LEVEL: return (INTR_TRIGGER_LEVEL); default: - panic("Bogus Interrupt Trigger Mode"); + printf("Bogus Interrupt Trigger Mode %x, set to level\n", + IntiFlags & ACPI_MADT_TRIGGER_MASK); + return (INTR_TRIGGER_LEVEL); } }
すると、以下のような出力が得られます(一部抜粋)
MADT: Found IO APIC ID 1, Interrupt 0 at 0xfec00000 ioapic0: Routing external 8259A's -> intpin 0 lapic0: Routing NMI -> LINT1 Bogus Interrupt Trigger Mode 8, set to level lapic0: LINT1 trigger: level lapic0: LINT1 polarity: high lapic2: Routing NMI -> LINT1 lapic2: LINT1 trigger: level Bogus Interrupt Polarity 2, set to low lapic2: LINT1 polarity: low MADT: Interrupt override: source 0, irq 2 ioapic0: Routing IRQ 0 -> intpin 2 MADT: Interrupt override: source 9, irq 9 ioapic0: intpin 9 trigger: level ioapic0 <Version 2.0> irqs 0-86 on motherboard lapic0: Forcing LINT1 to edge trigger
つまり、Interrupt Trigger Modeに0x8が、Interrupt Polarityに0x2が届いているらしい、という事がわかります。
この値はなんだろう、ここには実装されていないけど新しいモードでもあるのかな?と思ってACPI Specificationを眺めてみます。
…すると、どちらもreservedな値らしいという事がわかりました。なんか変ですね…。
dmesgを見る限りでは2つのコアの割り込みコントローラ(lapic0, lapic2)からそれぞれ接続されている、レガシ割り込み1番(LINT1と書いてある)の設定でしょうか…。
これ以上はMADTを眺めない限り分からなそうです。
というわけでMADTをダンプしてみます:
$ sudo acpidump -t MADT /* RSD PTR: OEM=INTEL, ACPI_Rev=2.0x (2) XSDT=0xb9549078, length=36, cksum=199 */ /* XSDT: Length=116, Revision=1, Checksum=141, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x1072009, Creator ID=AMI, Creator Revision=0x10013 Entries={ 0xb9550848, 0xb9550958, 0xb95509c0, 0xb9550a08, 0xb9550a48, 0xb9550b50, 0xb9550b88, 0xb95512f0, 0xb9551580, 0xb9551700 } */ /* FACP: Length=268, Revision=5, Checksum=89, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x1072009, Creator ID=AMI, Creator Revision=0x10013 FACS=0xb96eef80, DSDT=0xb9549180 INT_MODEL=APIC Preferred_PM_Profile=Desktop (1) SCI_INT=9 SMI_CMD=0xb2, ACPI_ENABLE=0xa0, ACPI_DISABLE=0xa1, S4BIOS_REQ=0x0 PSTATE_CNT=0x80 PM1a_EVT_BLK=0x400-0x403 PM1a_CNT_BLK=0x404-0x405 PM2_CNT_BLK=0x450-0x450 PM_TMR_BLK=0x408-0x40b GPE0_BLK=0x420-0x42f CST_CNT=0x85 P_LVL2_LAT=101 us, P_LVL3_LAT=1001 us FLUSH_SIZE=1024, FLUSH_STRIDE=16 DUTY_OFFSET=1, DUTY_WIDTH=3 DAY_ALRM=13, MON_ALRM=0, CENTURY=50 IAPC_BOOT_ARCH={NO_VGA} Flags={WBINVD,SLEEP_BUTTON,S4_RTC_WAKE,RESET_REGISTER,PLATFORM_CLOCK,S4_RTC_VALID,REMOTE_POWER_ON} RESET_REG=0xcf9:0[8] (IO), RESET_VALUE=0x6 */ /* FACS: Length=64, HwSig=0x0000004f, Firm_Wake_Vec=0x00000000 Global_Lock= Flags= Version=2 */ /* DSDT: Length=30405, Revision=2, Checksum=79, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x1072009, Creator ID=INTL, Creator Revision=0x20120913 */ /* APIC: Length=104, Revision=3, Checksum=174, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x1072009, Creator ID=AMI, Creator Revision=0x10013 Local APIC ADDR=0xfee00000 Flags={PC-AT} Type=Local APIC ACPI CPU=1 Flags={ENABLED} APIC ID=0 Type=Local APIC NMI ACPI CPU=1 LINT Pin=60 Flags={Polarity=active-hi, Trigger=0x2} Type=Local APIC ACPI CPU=2 Flags={ENABLED} APIC ID=2 Type=Local APIC NMI ACPI CPU=2 LINT Pin=61 Flags={Polarity=0x2, Trigger=level} Type=IO APIC APIC ID=1 INT BASE=0 ADDR=0x00000000fec00000 Type=INT Override BUS=0 IRQ=0 INTR=2 Flags={Polarity=conforming, Trigger=conforming} Type=INT Override BUS=0 IRQ=9 INTR=9 Flags={Polarity=active-hi, Trigger=level} */ /* FPDT: Length=68, Revision=1, Checksum=181, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x1072009, Creator ID=AMI, Creator Revision=0x10013 */ /* MCFG: Length=60, Revision=1, Checksum=76, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x1072009, Creator ID=MSFT, Creator Revision=0x97 Base Address=0x00000000e0000000 Segment Group=0x0000 Start Bus=0 End Bus=255 */ /* LPIT: Length=260, Revision=1, Checksum=63, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x3, Creator ID=VLV2, Creator Revision=0x100000d */ /* HPET: Length=56, Revision=1, Checksum=171, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x1072009, Creator ID=AMI., Creator Revision=0x5 HPET Number=0 ADDR=0xfed00000:0[64] (Memory) HW Rev=0x1 Comparators=2 Counter Size=1 Legacy IRQ routing capable={TRUE} PCI Vendor ID=0x8086 Minimal Tick=128 Flags=0x00 */ /* SSDT: Length=1891, Revision=1, Checksum=193, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x3000, Creator ID=INTL, Creator Revision=0x20061109 */ /* SSDT: Length=656, Revision=1, Checksum=10, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x3000, Creator ID=INTL, Creator Revision=0x20061109 */ /* SSDT: Length=378, Revision=1, Checksum=186, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x3000, Creator ID=INTL, Creator Revision=0x20061109 */ /* UEFI: Length=66, Revision=1, Checksum=147, OEMID=INTEL, OEM Table ID=DN2820FY, OEM Revision=0x0, Creator ID=, Creator Revision=0x0 */
よくわかりませんが、多分
Type=Local APIC NMI ACPI CPU=1 LINT Pin=60 Flags={Polarity=active-hi, Trigger=0x2}
と
Type=Local APIC NMI ACPI CPU=2 LINT Pin=61 Flags={Polarity=0x2, Trigger=level}
でしょうか。
Trigger=0x2はおそらくビットシフト後の0x8だと思われます。
間違ってるっぽいのは分かったけど、それでどうしたらいいんだろうか…。
まぁ、取り敢えず上述のパッチでpanicを起こさないようにすると動くには動くんですが。
ちなみに、新しいファームウェアではこのパッチを当てないと起動出来ないですが、CPU数はちゃんと2に増えました。
USBは相変わらずおかしいようです。