Hatena::ブログ(Diary)

かーねる・う゛いえむにっき このページをアンテナに追加 RSSフィード Twitter

2014-03-28

[][]FreeBSD-10 install image for Baytrail-M NUC(DN2820FYKH)

Intel Baytrail-M NUC(DN2820FYKH) causes kernel panic due to its broken ACPI table:

http://www.freebsd.org/cgi/query-pr.cgi?pr=187966

This install image includes patched kernel for the machine, you are able to install FreeBSD-10 on the machine without any kernel rebuilding work.

http://people.freebsd.org/~syuu/dn2820fykh_freebsd10/

2014-03-27

[][]Baytrail-M NUC(DN2820FYKH)でFreeBSDが起動しなかった話・解決編

これの続き。

Linuxでは僕の書いたpatchと同じ感じでreservedが来たらtriggerならlevel、polarityならlowを返すようにしています。

http://lxr.linux.no/linux+v3.13.5/arch/x86/kernel/acpi/boot.c#L1094

ですので、このパッチマージして貰うという事で良いのではないかという気がしてきたので、PRを送ってみました:

amd64/187966: Intel Baytrail-M NUC panics because of buggy ACPI table

その後、それをみたtakawataさんが同等のコードをCURRENTにコミットしてくれました:

Revision 263795

というわけで一件落着。

2014-03-26

[][]Baytrail-M NUC(DN2820FYKH)でFreeBSDが起動しなかった話

bhyve用にこれ買ってみたんですよ、これ。まぁ新しいハードだし地雷だろうなと思ってたんだけど、面白そうにおもっちゃってつい人柱っちゃったんですよ。はい

したらもういきなりドハマリして。

で、どんなpanicを起こしているかを見てみるわけですね。

f:id:syuu1228:20140325223402j:image:w640

こちらは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は相変わらずおかしいようです。

後日談

2014-03-22

[][]RubyTAPを使ったトンネリングプログラムを実装してみる

こちらのサイトシンプルPythonの実装が配布されていたので、Rubyでも実装してみました。

require "socket"
TUNSETIFF = 0x400454ca
IFF_TAP = 0x0002
PEER = "192.168.0.100"
PORT = 9876
tap = open("/dev/net/tun", "r+")
tap.ioctl(TUNSETIFF, ["tap%d", IFF_TAP].pack("a16S"))
sock = UDPSocket.open
sock.bind("0.0.0.0", 9876)
peer = Socket.pack_sockaddr_in(PORT, PEER)
while true
    ret = IO::select([sock, tap])
    ret[0].each do |d|
        if d == tap
            sock.send(tap.read(1500), 0, peer)
        else
            tap.write(sock.recv(65535))
        end
    end
end

RubyでもTAPの読み書きが出来るしselectも使えるしioctlも発行できるよー、っと。

2014-01-25

[][]OSvにマージされたmrubyを試す

$ sudo apt-get install openjdk-7-jdk autotools-dev libltdl-dev libtool autoconf autopoint libboost-all-dev \
genromfs zfs-fuse autoconf ant libffi-dev ruby bison gyp git build-essential qemu-utils qemu-system-x86 \
bridge-utils libvirt0 libvirt-bin
$ git clone git@github.com/cloudius-systems/osv
$ cd osv
$ git submodule update --init
$ cd apps/mruby
$ make module
$ cd -
$ sudo make external all image=mruby
$ sudo ./scripts/run.py
OSv v0.05-72-g4eb7d9c
mruby-eshell

$ ls
[".", "..", "libuutil.so", "libzfs.so", "dev", "tools", "proc", "zfs.so", "tmp", "etc", "zpool.so", "usr"]
$ exit

ただ、これだけだとスクリプトが何も無いので何も実行できない。

スクリプトを足して再ビルドしてみる。

$ cd apps/mruby
$ cat << EOF > tcpsocket.rb
s = TCPSocket.open("www.kame.net", 80)
s.write("GET / HTTP/1.0\r\n\r\n")
puts s.read
s.close
EOF
$ echo "/tcpsocket.rb: \${MODULE_DIR}/tcpsocket.rb" >> usr.manifest
$ cd -
$ sudo make all image=mruby
$ sudo ./scripts/run.py
OSv v0.05-72-g4eb7d9c
mruby-eshell

$ run ./tcpsocket.rb
HTTP/1.1 200 OK
Date: Sat, 25 Jan 2014 00:13:58 GMT
Server: Apache/2.2.26 (FreeBSD) mod_ssl/2.2.26 OpenSSL/0.9.8y DAV/2
Accept-Ranges: bytes
Connection: close
Content-Type: text/html
(後略)
$ exit

ソケット通信のテストが実行出来た。