NetBSD/amd64-currentをAmazon Web Service EC2 c5インスタンスで動かしてみる

この記事は、 NetBSD Advent Calendar 2018の23日目の記事です。

はじめに

もう1年以上前の話だと思うのですが、Amazon Web Service (AWS) EC2にc5という Linux KVMをAmazonが独自拡張したと言うインスタンスのタイプが追加されました。 その後、同じような仕組みのm5インスタンスと言うもの追加されているようです。 c5インスタンスでは、Elastic Network Adapter (ENA)と言うEthernetアダプター を利用できることが必須になっているようです。 NetBSD/aarch64では、a1インスタンスでena(4)がFreeBSDから移植されていて 無事に動いていますが、 c5インスタンスでのNetBSD/amd64の動作確認結果は聞いたことはありませんでした。

そもそもc5インスタンスで起動できるAMIの作り方も良く分かりませんでした。 今回は、カーネルパニックでena(4)は動かせるまで至りませんでしたが、 c5インスタンス用のAMIの作成をまとめておくことは意味があるかもしれません。

AMIファイルの作り方を調べてみる

AWS EC2のAMIは、直接ダウンロードしてみることはできないようです。 裏にはスナップショットと言うものがあるようですが、Amazonが公開している Amazon LinuxのAMI用のスナップショットを見ることはできないようです。

今回は、FreeBSD/amd64 12のAMIからc5インスタンスを作成し、そのディスクの 構造を見てみました。それを見ると、NetBSDで言うと、GPTパーティションからの BIOSブート(UEFIブートではない)であることが分かりました。 かつて、UEFIブートができないことにGPTを使っていたやり方を思い出せば良さそうです。

ここで、カーネルは、

ena*    at pci? dev ? function ?        # Amazon Elastic Network Adapter
の行をGENERIC設定ファイルに追加した追加したGENERIC_ENA設定ファイルでビルドします。
; 3GBのディスクイメージファイルを作成します
$ dd if=/dev/zero of=./netbsd-c5-gpt-bios-boot.img bs=1g count=3
; vnd(4)を使ってブロックデバイスとして扱えるようにします。
# vndconfig vnd0 netbsd-c5-gpt-bios-boot.img
; GPTパーティションを作る準備をします
# gpt create vnd0
; 2GBのルートパーティションを作成します。私の場合には/dev/dk5として扱えるようになります。
# gpt add -s 2g -t ffs -l AWSROOT vnd0
; 1GBのスワップパーティションを作成します。私の場合には/dev/dk6として扱えるようになります。
# gpt add -t swap -l AWSSWAP vnd0
; ルートパーティションからBIOSブートするように設定します。
# gpt biosboot -A -i 1 vnd0
; ルートパーティションをFFSv2でフォーマットします。
# newfs -O2 /dev/rdk5
; FFSv2で起動できるようにブートローダーを配置します。
# installboot -v /dev/rdk5 /usr/mdec/bootxx_ffsv2
; ユーザーランドをインストールするために/mntにマウントします。
# mount /dev/dk5 /mnt
# cd /usr/src ; 以下でユーザーランドをビルドします。
# ./build.sh -U -O /usr/world/8.99/amd64/obj -T /usr/world/8.99/amd64/tools -D /usr/world/8.99/amd64/destdir -R /usr/world/8.99/amd64/release -u -j 8 -m amd64 tools
# ./build.sh -U -O /usr/world/8.99/amd64/obj -T /usr/world/8.99/amd64/tools -D /usr/world/8.99/amd64/destdir -R /usr/world/8.99/amd64/release -u -j 8 -m amd64 kernel=GENERIC_ENA
# ./build.sh -U -O /usr/world/8.99/amd64/obj -T /usr/world/8.99/amd64/tools -D /usr/world/8.99/amd64/destdir -R /usr/world/8.99/amd64/release -u -j 8 -m amd64 distribution
; ユーザーランドを/mntをルートにしてインストールします。
# ./build.sh -U -O /usr/world/8.99/amd64/obj -T /usr/world/8.99/amd64/tools -D /usr/world/8.99/amd64/destdir -R /usr/world/8.99/amd64/release -u -j 8 -m amd64 -V INSTALLSETS="base comp etc games man misc modules tests text" install=/mnt
; ブートローダーをインストールします。
# cp /usr/mdec/boot /mnt
; カーネルをインストールします (ena(4)が有効になっているカーネルをインストールします)
# cp /usr/world/8.99/amd64/obj/sys/arch/amd64/compile/GENERIC_ENA/netbsd /mnt
; AWS EC2の公開鍵の配置のためのスクリプトを追加します。
# vi /mnt/etc/rc.d/ec2_init
/etc/rc.d/ec2_initは、NetBSD Wikiの Build-up your own NetBSD AMIのウェブページにある以下のような内容です。
#!/bin/sh
#
# PROVIDE: ec2_init
# REQUIRE: NETWORKING
# BEFORE:  LOGIN

$_rc_subr_loaded . /etc/rc.subr

name="ec2_init"
rcvar=${name}
start_cmd="ec2_init"
stop_cmd=":"

METADATA_URL="http://169.254.169.254/latest/meta-data/"
SSH_KEY_URL="public-keys/0/openssh-key"
HOSTNAME_URL="hostname"

SSH_KEY_FILE="/root/.ssh/authorized_keys"

ec2_init()
{
        (
        umask 022
        # fetch the key pair from Amazon Web Services
        EC2_SSH_KEY=$(ftp -o - "${METADATA_URL}${SSH_KEY_URL}")

        if [ -n "$EC2_SSH_KEY" ]; then
                # A key pair is associated with this instance, add it
                # to root 'authorized_keys' file
                mkdir -p $(dirname "$SSH_KEY_FILE")
                touch "$SSH_KEY_FILE"
                cd $(dirname "$SSH_KEY_FILE")

                grep -q "$EC2_SSH_KEY" "$SSH_KEY_FILE"
                if [ $? -ne 0 ]; then
                        echo "Setting EC2 SSH key pair: ${EC2_SSH_KEY##* }"
                        echo "$EC2_SSH_KEY" >> "$SSH_KEY_FILE"
                fi
        fi

        # set hostname
        HOSTNAME=$(ftp -o - "${METADATA_URL}${HOSTNAME_URL}")
        echo "Setting EC2 hostname: ${HOSTNAME}"
        echo "$HOSTNAME" > /etc/myname
        hostname "$HOSTNAME"
        )
}

load_rc_config $name
run_rc_command "$1"
; 実行可能に設定します。
# chmod 555 /mnt/etc/rc.d/ec2_init
; 起動時の設定をします。
# vi /mnt/etc/rc.conf
rc_configured=YES
ec2_init=YES
sshd=YES # for remote shell access to instance
; rootユーザーでログインできるようにします。
# vi /mnt/etc/ssh/sshd_config
PermitRootLogin without-password
; 以下でファイルシステムの設定をします。
# mkdir /mnt/proc /mnt/kern
# vi /mnt/etc/ifconfig.ena0
dhcp
# vi /mnt/etc/fstab
NAME=AWSROOT    /               ffs     rw,log  1 1
NAME=AWSSWAP    none            swap    sw,dp   0 0
kernfs          /kern           kernfs  rw
ptyfs           /dev/pts        ptyfs   rw
procfs          /proc           procfs  rw
tmpfs           /var/shm        tmpfs   rw,-m1777,-sram%25
; /dev以下のノードを作成します。
# cd /mnt/dev
# ./MAKEDEV all
; vnd0を開放します。
# cd ~
# umount /mnt
# vndconfig -u vnd0
これで、ディスクイメージファイルは完成です。 以下で、AMIファイルを作成して行きます。

AMIファイルの作成は、Elastic Block Store (EBS)でディスクを割り当てし、 そのディスクにローカルで作成したディスクイメージを書き込み、 そのスナップショットをとってAMIを作成します。 操作は、Pythonで書かれたawsコマンドを使います。

; pkgsrcからawsコマンドをインストールします。
# cd /usr/pkgsrc/net/py-awscli
# make install

; AWSの認証のための情報と、使用するリージョンの情報、実行結果の表示方法を設定します、
$ aws configure
AWS Access Key ID [None]: XXX
AWS Secret Access Key [None]: XXX
Default region name [None]: us-east-1
Default output format [None]: text

; 既にあるsshの鍵ペアを使って、Amazon Linux 2のHVMのAMIを使ってc5.largeインスタンスを起動させます、
$ aws ec2 run-instances --image-id ami-009d6802948d06e52 --instance-type c5.large --key-name c5-20181220
619017845909    r-0dab8fafc6dbc2a6c
INSTANCES       0       x86_64          False   xen     ami-009d6802948d06e52  i-01dfee86f4d0d109d      c5.large        c5-20181220     2018-12-21T13:41:14.000Z
        ip-172-31-38-245.ec2.internal   172.31.38.245           /dev/xvda      ebs      True            subnet-73de462f hvm     vpc-d459f1ae
CPUOPTIONS      1       2
MONITORING      disabled
NETWORKINTERFACES               0e:de:7c:89:d3:a2       eni-0a38d352461629255  619017845909     ip-172-31-38-245.ec2.internal   172.31.38.245   True    in-use subnet-73de462f  vpc-d459f1ae
ATTACHMENT      2018-12-21T13:41:14.000Z        eni-attach-09acc70fb71f4bd95   True     0       attaching
GROUPS  sg-1d45925e     default
PRIVATEIPADDRESSES      True    ip-172-31-38-245.ec2.internal   172.31.38.245
PLACEMENT       us-east-1d              default
SECURITYGROUPS  sg-1d45925e     default
STATE   0       pending
STATEREASON     pending pending
; これで、i-01dfee86f4d0d109dというインスタンスIDのc5.largeインスタンスが起動されました、

; 起動完了してrunningステータスになっているか確認します。
$ aws ec2 describe-instances --instance-ids i-01dfee86f4d0d109d
ESERVATIONS    619017845909    r-0dab8fafc6dbc2a6c
INSTANCES       0       x86_64          False   True    xen     ami-009d6802948d06e52   i-01dfee86f4d0d109d     c5.large        c5-20181220     2018-12-21T13:41:14.000Z        ip-172-31-38-245.ec2.internal   172.31.38.245   ec2-34-229-210-170.compute-1.amazonaws.com      34.229.210.170  /dev/xvda       ebs     True   subnet-73de462f  hvm     vpc-d459f1ae
BLOCKDEVICEMAPPINGS     /dev/xvda
EBS     2018-12-21T13:41:15.000Z        True    attached        vol-029d14d5198ee2174
CPUOPTIONS      1       2
HIBERNATIONOPTIONS      False
MONITORING      disabled
NETWORKINTERFACES               0e:de:7c:89:d3:a2       eni-0a38d352461629255  619017845909     ip-172-31-38-245.ec2.internal   172.31.38.245   True    in-use subnet-73de462f  vpc-d459f1ae
ASSOCIATION     amazon  ec2-34-229-210-170.compute-1.amazonaws.com      34.229.210.170
ATTACHMENT      2018-12-21T13:41:14.000Z        eni-attach-09acc70fb71f4bd95   True     0       attached
GROUPS  sg-1d45925e     default
PRIVATEIPADDRESSES      True    ip-172-31-38-245.ec2.internal   172.31.38.245
ASSOCIATION     amazon  ec2-34-229-210-170.compute-1.amazonaws.com      34.229.210.170
PLACEMENT       us-east-1d              default
SECURITYGROUPS  sg-1d45925e     default
STATE   16      running
; runningステータスになっていることを確認して次に進みます。

; 3GBのstandardタイプ(磁気ハードディスクドライブ)のEBSボリュームを作成します、
$ aws ec2 create-volume --availability-zone us-east-1d --volume-type standard --size 3

; 作成したEBSボリュームの内容を確認します、
$ aws ec2 describe-volumes --volume-ids vol-076f8c399f56e6753
VOLUMES us-east-1d      2018-12-21T13:44:05.665Z        False   3              available        vol-076f8c399f56e6753   standard

; Amazon Linux 2のインスタンスに作成したEBSボリュームを接続します。
$ aws ec2 attach-volume --instance-id i-01dfee86f4d0d109d --volume-id vol-076f8c399f56e6753 --device "/dev/sdf"
2018-12-21T13:46:15.709Z        /dev/sdf        i-01dfee86f4d0d109d     attaching       vol-076f8c399f56e6753

; 接続できたことを確認します。
$ aws ec2 describe-volumes --volume-ids vol-076f8c399f56e6753
VOLUMES us-east-1d      2018-12-21T13:44:05.665Z        False   3              in-use   vol-076f8c399f56e6753   standard
ATTACHMENTS     2018-12-21T13:46:15.000Z        False   /dev/sdf        i-01dfee86f4d0d109d     attached        vol-076f8c399f56e6753

; もし、送信側セキュリティー設定(ポートごとの通過できる通信の設定)を実施します。
$ aws ec2 authorize-security-group-egress --group-id sg-1d45925e --port 22 --protocol all

; 受信側のセキュリティー設定を実施します。
$ aws ec2 authorize-security-group-ingress --group-id sg-1d45925e --port 22 --protocol all --cidr 0.0.0.0/0

; Amazon Linux 2のディスク領域にディスクイメージファイルを転送します。
$ scp -i c5-20181220.pem netbsd-c5-gpt-bios-boot.img ec2-user@ec2-34-229-210-170.compute-1.amazonaws.com:~/

; sshでAmazon Linux 2にログインします。
$ ssh -i c5-20181220.pem ec2-user@ec2-34-229-210-170.compute-1.amazonaws.com

; 接続したEBSボリュームにディスクイメージファイルを書き込みます。これがスナップショットになり、AMIになります。
[ec2-user@ip-172-31-38-245 ~]$ sudo dd if=netbsd-c5-gpt-bios-boot.img of=/dev/sdf bs=64k

; /dev/sdfに接続したEBSボリュームを取り外します。
$ aws ec2 detach-volume --volume-id vol-076f8c399f56e6753
2018-12-21T13:46:15.000Z        /dev/sdf        i-01dfee86f4d0d109d     detaching       vol-076f8c399f56e6753

; 取り外したEBSボリュームのスナップショットを取得します。これにはしばらく時間がかかります。
$ aws ec2 create-snapshot --volume-id vol-076f8c399f56e6753
        False   619017845909            snap-04eb837b14f764a00  2018-12-21T14:06:20.000Z        pending vol-076f8c399f56e6753   3

; Amazon Linux 2のインスタンスを消します。
$ aws ec2 terminate-instances --instance-ids i-01dfee86f4d0d109d
TERMINATINGINSTANCES    i-01dfee86f4d0d109d
CURRENTSTATE    32      shutting-down
PREVIOUSSTATE   16      running

; スナップショットを使ってAMIを作成します。
$ aws ec2 register-image --architecture x86_64 --name "NetBSD/amd64 8.99.28 with ena" --ena-support --virtualization-type hvm --block-device-mappings 'DeviceName=/dev/sda1,Ebs={SnapshotId=snap-04eb837b14f764a00}' --root-device-name "/dev/sda1"
ami-088a6d6fc2dccd87b
; これで、ami-088a6d6fc2dccd87bというIDのAMIが作成されました。ENAが有効で、c5.largeインスタンスに使えるように仮想化タイプもhvmにしました。
このAMIを使ってc5.largeインスタンスを起動させてみます。

NetBSD/amd64-currentの起動

ami-088a6d6fc2dccd87bを使って、c5.largeインスタンスを作成することで、 NetBSD/amd64-currentを起動させることができます。 起動したら、AWS ConsoleからInstanceを選び、起動させたインスタンスのInstance Settings よりGet Instance Screenshotを選びます。 残念ながらMSI-X割り込みの関係でエラーになってカーネルパニックしてしまっています。

AWS EC2は、sshでログインできないと何もできませんので、 ディスクイメージファイルのカーネルファイル/netbsdを差し替えて アップロードしてEBSボリュームに書き込むのを繰り返してデバッグするしかなさそうです。

NetBSD/amd64でChisel HDLからVerilogを生成してシミュレーションしてみる

この記事は、 NetBSD Advent Calendar 2018の20日目の記事です。

はじめに

MIPSの 命令セットアーキテクチャーと実装が オープンソースになるような時代が来るとは思っていませんでした。 これもRISC-Vへの期待に影響があるのかもしれません。

Chiselと言うハードウェア記述言語は、そのRISC-Vの代表的な実装である Rocket chip の多くの部分を書くのに使われているものです。

今回は、Rocket chipは大規模過ぎるので、Chiselのチュートリアルである Chisel TutorialsのChiselコードをVerilogに変換して、 verilatorでのシミュレーション実行もしてみたいと思います。

私はこれからChiselで書いてみたい回路があるのですが、 NetBSDで生活して良くあるのは、そもそも環境が整わない、整ったと思ったら誤作動している と行ったことなので、既存の正しく動くことの分かっているものが、同じように動くことを 確認するのは大切です。

Chiselの環境の準備

Chiselは、ScalaというJava Virtual Machine (JVM)で動く処理系で書かれています。 Chisel自体が、Scala言語のドメイン固有言語(DSL)になっています。

Chiselの処理系は、sbt (pkgsrc/lang/scala-sbt)を使って各環境ごとに それぞれ用意します。 ですので、/usr/local以下にインストールしておくといったことは 一般的ではないようです。

まずは、pkgsrc.lang/scala-sbtのインストールですが、 NetBSD/amd64のネイティブなOpenJDK 8ではうまく動きません。 Java Native Access (JNA)がサポートされていないのが いけませんし、他にも理由はありそうです。 pkgsrc/lang/openjdk8をちゃんと直さないといけません…。 ですが、ここでは先を急いでpkgsrc/lang/oracle-jdk8を 使うことにしてしまいます。 java.sun.com からLinux/x86_64用のJREとJDKの配布物をダウンロードして$DISTDIR に配置した上で、以下のように実行すれば良いでしょう。

# cd /usr/pkgsrc/lang/scala-sbt
# make ACCEPTABLE_LICENSES=oracle-binary-code-license install
これで、Oracle JDKを追加でインストールしてsbtはそれを使うようにできます。 pkgsrc/lang/openjdk8と共存できるので、 アンインストールは不要です。

Chisel Tutorialsから試してみます。chisel-tutorialの Gitリポジトリーをクローンし、まずはFIRRTLでシミュレーションをしてみます。 Chisel Tutorialsの課題の加算器の解答例をシミュレーションしてみます。 初回は、Chisel自体のインストールも実行されます。

$ git clone git@github.com:ucb-bar/chisel-tutorial.git
$ cd  chisel-tutorial
$ sbt -v "test:runMain solutions.Launcher Adder"
(snip)
[info] Loading settings from build.sbt ...
[info] Set current project to chisel-tutorial (in build file:/home/ryoon/chisel/chisel-tutorial/)
[warn] Multiple main classes detected.  Run 'show discoveredMainClasses' to see the list
[info] Running solutions.Launcher Adder
Starting tutorial Adder
[info] [0.002] Elaborating design...
[info] [1.010] Done elaborating.
Total FIRRTL Compile Time: 508.3 ms
Total FIRRTL Compile Time: 82.5 ms
file loaded in 0.149673865 seconds, 6 symbols, 2 statements
[info] [0.001] SEED 1545137294717
test Adder Success: 10 tests passed in 15 cycles in 0.020284 seconds 739.49 Hz
[info] [0.007] RAN 10 CYCLES PASSED
Tutorials passing: 1
[success] Total time: 4 s, completed 2018/12/18 21:48:16
どうやら、テストまで成功したようです。

次には、Verilogのコードを生成し、Verilatorによるシミュレーションも実施してみます。 ですが、そうやらChiselは、GNU makeがmakeと言う名前でPATH にあることを前提にしているようです。 Chiselをbuildし直したら良いのでしょうが、ここでは簡便に/usr/pkg/bin/gmakemakeとしてシンボリックリンクを作成してしまいます。

# cd /usr/pkgsrc/cad/verilator
# make install
$ ln -s /usr/pkg/bin/gmake make
$ PATH=./:$PATH sbt -v "test:runMain solutions.Launcher Adder --backend-name verilator
      Archiving VAdder__ALL.a ...
ar r VAdder__ALL.a VAdder__ALLcls.o VAdder__ALLsup.o
ranlib VAdder__ALL.a
c++    Adder-harness.o verilated.o verilated_vcd_c.o VAdder__ALL.a    -o VAdder -lm -lstdc++
make: Leaving directory '/home/ryoon/chisel/chisel-tutorial/test_run_dir/solutions/Adder'
sim start on brownie at Tue Dec 18 21:56:19 2018
inChannelName: 00029411.in
outChannelName: 00029411.out
cmdChannelName: 00029411.cmd
STARTING test_run_dir/solutions/Adder/VAdder
[info] [0.001] SEED 1545137775286
Enabling waves..
Exit Code: 0
[info] [0.022] RAN 10 CYCLES PASSED
Tutorials passing: 1
[success] Total time: 6 s, completed 2018/12/18 21:56:19
テストまで完了し成功したようです。 ここで、Verilogのソースコードはtest_run_dir/solutions/Adder/Adder.vに 生成されます。 これをVerilatorでシミュレーションした際の波形ファイルは、test_run_dir/solutions/Adder/Adder.vcdに 生成されます。 pkgsrc/cad/gtkwaveで波形を見ることができます。
# cd /usr/pkgsrc/cad/gtkwave
# make install
$ gtkwave test_run_dir/solutions/Adder/Adder.vcd
ですが、今の私には波形が正しいかを判断することはできません…。

Chiselでの回路の記述と確認は、どうにかNetBSD/amd64上でも実施できそうです。

NetBSD/amd64-current上でIntel Quick Sync Videoを使ってみる

この記事は、 NetBSD Advent Calendar 2018の10日目の記事です。

はじめに

IntelのCPUに内蔵されているGPUには、Intel Quick Sync Video (QSV)というビデオのデコードとエンコードをする仕組みが入っています。 今回は、KabylakeなIntel Core i7なチップの搭載されているHP Spectre x360 ae019TUで、NetBSD/amd64 8.99.27上で、 H.264のビデオのデコードとエンコードをQSVでさせてみました。 エンコードには、pkgsrc/multimedia/ffmpeg4を使い、 デコードには、pkgsrc/multimedia/mpvを使います。 比較のためにfmpeg4でCPUを使ってH.264を利用しますが、 これには本来はライセンスが必要なはずです。 CPUを使ってH.264のデコード/エンコードをしてはいけないと思います。

Intel QSVを使用する準備

NetBSDでIntel QSVを使うためには、pkgsrc/multimedia/libva (VA API)を使うのが一番良いようです。 Intel Media SDKはもしNetBSDで使えたとしても相当苦労するのが明らかですし、 VDPAUは、2015年以降のコミットは2018年11月の2件のみです。

NetBSD/amd64 8.99.27で必要なものをpkgsrcからインストールします。 pkgsrc/multimedia/ffmpeg4pkgsrc/multimedia/mpvもNetBSD/amd64 8.99.27ではpkgsrc/multimedia/libva に依存するのが既定値になっています。 本当に自分の環境でlibvaサポートが有効になるかを確認したい場合にが、 make show-optionsの出力にvaapiが含まれているかを確認すれば良いでしょう。 libvaからIntel QSVを使うには、pkgsrc/multimedia/intel-vaapi-driverが必要です。 また、libvaの動作確認をするには、pkgsrc/multimedia/libva-utilsがあると良いです。

# cd /usr/pkgsrc/multimedia/ffmpeg4
# make install
# cd /usr/pkgsrc/multimedia/mpv
# make install
# cd /usr/pkgsrc/multimedia/intel-vaapi-driver
# make install
# cd /usr/pkgsrc/multimedia/libva-utils
# make install
これで必要なソフトウェアは準備できました。

本当にIntel QSVが使えるか確認する

mpvffmpeg4を使ってみる前に、libva-utilsパッケージに含まれるvainfoコマンドで、 サポートされているIntel QSVの機能を確認してみます。

$ vainfo
vainfo: VA-API version: 1.3 (libva 2.3.0)
vainfo: Driver version: Intel i965 driver for Intel(R) Kaby Lake - 2.2.0
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Simple            : VAEntrypointEncSlice
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointEncSliceLP
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointEncSliceLP
      VAProfileH264MultiviewHigh      : VAEntrypointVLD
      VAProfileH264MultiviewHigh      : VAEntrypointEncSlice
      VAProfileH264StereoHigh         : VAEntrypointVLD
      VAProfileH264StereoHigh         : VAEntrypointEncSlice
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointEncPicture
      VAProfileVP8Version0_3          : VAEntrypointVLD
      VAProfileVP8Version0_3          : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileHEVCMain10             : VAEntrypointVLD
      VAProfileHEVCMain10             : VAEntrypointEncSlice
      VAProfileVP9Profile0            : VAEntrypointVLD
      VAProfileVP9Profile0            : VAEntrypointEncSlice
      VAProfileVP9Profile2            : VAEntrypointVLD
私の環境ではH.264のサポートはデコードもエンコードも有効なようです。

より古いIntel製CPUの場合には、提供されない機能もあるようです。 ですので、全ての環境で同じ結果が表示されるとは限りません。

テスト用のビデオファイルを用意する

良く考えると、私は全くビデオファイルを持っていませんでした。 自由に使えるビデオファイルと言えば、Blender FoundationのBig Buck Bunnyの3Dアニメーションビデオです。 https://download.blender.org/peach/bigbuckbunny_movies/から、 big_buck_bunny_1080p_stereo.aviのファイルをダウンロードしておきます。 これは、MS MPEG4というcodecでエンコードされたファイルのようです。

H.264にエンコードしてみる

ffmpeg4を使ってH.264にエンコードしてみます。 ちょっとマシンの都合が悪く、実際の結果を示せませんが、おおむね以下のような性能でエンコードされました。 大変期待外れな内容です。

エンコーダー CPU (libx264) QSV (h264_vaapi)
実時間に対する倍数 1.7倍程度 1.0倍程度
それぞれの実行時のコマンドは以下のようです。
; CPUエンコードの場合
$ ffmpeg4 -c:a copy -c:v h264 -level 40 -qp 23 -i big_buck_bunny_1080p_stereo.avi software.mp4
; QSVエンコードの場合
$ ffmpeg4 -vaapi_device /dev/dri/card0 -hwaccel_output_format vaapi -c:v h264_vaapi -level 50 -qp 23 -c:a copy -i big_buck_bunny_1080p_stereo.avi hardware.mp4
QSVエンコードの場合、load averageは2程度で推移しています。 もしかしたらMS MPEG4のデコードが律速になっているのかもしれません。

big_buck_bunny_1080p_stereo.aviのファイルをH.264エンコードのファイルに変換したファイルを変換元ファイルにして 再度挑戦してみます。

エンコーダー CPU (libx264) QSV (h264_vaapi)
実時間に対する倍数 0.3倍程度 0.7倍程度
それぞれの実行時のコマンドは以下のようです。
; CPUエンコードの場合
$ ffmpeg4 -c:a copy -c:v h264 -level 40 -qp 23 -i big_buck_bunny_1080p_stereo.mp4 software.mp4
; QSVエンコードの場合
$ ffmpeg4 -vaapi_device /dev/dri/card0 -hwaccel_output_format vaapi -c:v h264_vaapi -level 50 -qp 23 -c:a copy -i big_buck_bunny_1080p_stereo.mp4 hardware.mp4
余計に悪くなってしまいました。

次にQSVの場合のH.264のデコードも有効にしてみます。

エンコーダー CPU (libx264) QSV (h264_vaapi)
実時間に対する倍数 0.3倍程度 9.3倍程度
それぞれの実行時のコマンドは以下のようです。
; CPUエンコードの場合
$ ffmpeg4 -c:a copy -c:v h264 -level 40 -qp 23 -i big_buck_bunny_1080p_stereo.mp4 software.mp4
; QSVエンコードの場合
$ ffmpeg4 -vaapi_device /dev/dri/card0 -hwaccel vaapi -hwaccel_output_format vaapi -c:v h264_vaapi -level 50 -qp 23 -c:a copy -i big_buck_bunny_1080p_stereo.mp4 hardware.mp4
これくらい差があれば、ありがたさを実感できます。

mpvでのデコード

pkgsrc/multimedia/mpvでIntel QSVでデコードして視聴する場合には、以下のようにします。

$ mpv --hwdec=vaapi --vo=vaapi big_buck_bunny_1080p_stereo.mp4
これで視聴すると、load averageは上がらないようですし、H.264のライセンスのことも気にしなくて良いのかもしれません。

実際には、VP9等のcodecもIntel QSVはサポートしています。そちらの方が有用かもしれません。

明日は、furandon_pigさんが記事を書いてくれます。

Amazon Web Service EC2のa1インスタンスでNetBSD/aarch64を動かしてみる

この記事は、 NetBSD Advent Calendar 2018の9日目の記事です。

はじめに

port-armメーリングリストに、 jmcneill@さんが、 NetBSD on AWS EC2 ARM instances と言う投稿をされました。 AmazonがAmazon Web Service (AWS) EC2にa1インスタンスという64ビットARM (aarch64)を追加していますが、 その上でNetBSD/evbarm64が動くという話です。

今回は、jmcneill@さんが、用意してくれたAMIを使って、a1.middleインスタンス を作り、pkgsrcを使ってみました。

AWS EC2 a1とは

AWS EC2 a1は、Amazonの独自に開発した64ビットARM CPUである AWS Gravitation Processorで動くインスタンスのようです。 jmcneill@さんが、 us-east-1(N. Virginia)にAMIを用意してくれていますので、 us-east-1であれば何の苦もなくインスタンスを用意できるはずです。

今回は、a1.middleインスタンスを使ってみますが、これはCPU: 1基、RAM: 2GiBの インスタンスです。最大構成のa1.4xlargeですと、CPU: 16基、RAM: 32 GiBです。

a1.middleインスタンスを用意する

a1インスタンスだからと言って、特に特別なことはありません。 普通にAWSのインスタンスを作成していきます。 まずは、Community版のAMIで、ami-0c7624c662581e8faを検索して 選択します。ログイン用のssh鍵も生成し、ダウンロードしておきます。

次には、EBSディスクを割り当ててインスタンスを起動させます。

a1.middleインスタンスへログインする

ログインについては、NetBSD Wikiの記事に書かれている通りです。 生成したssh鍵の秘密鍵をダウンロードしてあると思います。それを使って、以下のようにログインします。

$ chmod 600 a1-privatekey.pem
$ ssh -i a1-privatekey.pem root@aws-hostname-address

a1.middleインスタンスの初期設定をする

ログインはできましたが、あまりセキュリティー的に気持ちの良い状態ではありません。 ちょっと試すだけだとしても、以下のような設定はしておいた方が良いでしょう。

# useradd -m ryoon
# passwd ryoon
# su ryoon
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
(手元の端末からssh公開鍵を転送し、~/.ssh/authorized_keysを用意する)
# vi /etc/group
wheel:*:0:root,ryoon
(snip)
operator:*:5:root,ryoon
(snip)
# vi /etc/ssh/sshd_config
(snip)
PasswordAuthentication no
(snip)
UsePam no
# /etc/rc.d/ec2_init stop
# vi /etc/rc.conf
(snip)
ec2_init=NO
(snip)
ここまで設定したら、別ターミナルから自分のユーザーID (ここではryoon)で ログインしてみて、suコマンドでrootユーザーになれる ことまで確認します。成功したら、下のターミナルではログアウトして良いです。

a1.middleインスタンスを使ってみる

ここまでやれば、とりあえずは大きな不安はなく状況を確認できます。 最初にunameの結果を確認しておきます。

$ uname -ap
NetBSD ec2-34-228-210-40.compute-1.amazonaws.com 8.99.26 NetBSD 8.99.26 (GENERIC64) #3: Fri Nov 30 14:40:13 AST 2018  jmcneill@toki.invisible.ca:/home/jmcneill/netbsd/cvs-src/sys/arch/evbarm/compile/obj/GENERIC64 evbarm aarch64

dmesgは以下のようです。

------------------------------------------
kern_vtopdiff         = 0xffffffbf85800000
physical_start        = 0x0000000040000000
kernel_start_phys     = 0x000000007a800000
kernel_end_phys       = 0x000000007b42e000
msgbuf                = 0x000000007c22c000
physical_end          = 0x000000043b000000
VM_MIN_KERNEL_ADDRESS = 0xffffffc000000000
kernel_start_l2       = 0xffffffc000000000
kernel_start          = 0xffffffc000000000
kernel_end            = 0xffffffc000c2e000
pagetables            = 0xffffffc000c2e000
pagetables_end        = 0xffffffc000c39000
kernel_end_l2         = 0xffffffc000e00000
module_start          = 0xffffffc000e00000
module_end            = 0xffffffc002e00000
(kernel va area)
(devmap va area)      = 0xfffffffff0000000
VM_MAX_KERNEL_ADDRESS = 0xffffffffffe00000
------------------------------------------
mpstart
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
2018 The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California.  All rights reserved.

NetBSD 8.99.26 (GENERIC64) #3: Fri Nov 30 14:40:13 AST 2018
 jmcneill@toki.invisible.ca:/home/jmcneill/netbsd/cvs-src/sys/arch/evbarm/compile/obj/GENERIC64
total memory = 1952 MB
avail memory = 1889 MB
timecounter: Timecounters tick every 10.000 msec
armfdt0 (root)
simplebus0 at armfdt0: ACPI
simplebus1 at simplebus0
acpifdt0 at simplebus0
acpifdt0: using EFI runtime services for RTC
ACPI: RSDP 0x000000007C2D0014 000024 (v02 AMAZON)
ACPI: XSDT 0x000000007C2C00E8 000064 (v01 AMAZON AMZNFACP 00000001      01000013)
ACPI: FACP 0x000000007C2A0000 000114 (v06 AMAZON AMZNFACP 00000001 AMZN 00000001)
ACPI: DSDT 0x000000007C230000 00154F (v03 AMAZON AMZNDSDT 00000001 INTL 20160108)
CPI: APIC 0x000000007C2B0000 0000B8 (v03 AMAZON AMZNAPIC 00000001 AMZN 00000001)
ACPI: SPCR 0x000000007C290000 000050 (v02 AMAZON AMZNSPCR 00000001 AMZN 00000001)
ACPI: GTDT 0x000000007C280000 000060 (v02 AMAZON AMZNGTDT 00000001 AMZN 00000001)
ACPI: MCFG 0x000000007C270000 00003C (v02 AMAZON AMZNMCFG 00000001 AMZN 00000001)
ACPI: SLIT 0x000000007C260000 00002D (v01 AMAZON AMZNSLIT 00000001 AMZN 00000001)
ACPI: IORT 0x000000007C250000 000078 (v01 AMAZON AMZNIORT 00000001 AMZN 00000001)
ACPI: PPTT 0x000000007C240000 0000A0 (v01 AMAZON AMZNPPTT 00000001 AMZN 00000001)
ACPI: 1 ACPI AML tables successfully acquired and loaded
acpi0 at acpifdt0: Intel ACPICA 20180810
acpi0: X/RSDT: OemId , AslId <    ,01000013>
acpi0: MCFG: segment 0, bus 0-255, address 0x0000000020000000
cpu0 at acpi0: Cortex-A72 r0p3 (Cortex V8-A core)
cpu0: package 0, core 0, smt 0
cpu0: IC enabled, DC enabled, EL0/EL1 stack Alignment check enabled
cpu0: Cache Writeback Granule 16B, Exclusives Reservation Granule 16B
cpu0: Dcache line 64, Icache line 64
cpu0: L1 48KB/64B 3-way read-allocate PIPT Instruction cache
cpu0: L1 32KB/64B 2-way write-back read-allocate write-allocate PIPT Data cache
cpu0: L2 2048KB/64B 16-way write-back read-allocate write-allocate PIPT Unified cache
cpu0: revID=0x0, PMCv3, 4k table, 64k table, 16bit ASID
cpu0: auxID=0x11120, GICv3, FP, CRC32, SHA1, SHA256, AES+PMULL, NEON, rounding, NaN propagation, denormals, 32x64bitRegs, Fused Multiply-Add
gicvthree0 at acpi0: GICv3
gicvthree0: ITS #0 at 0x10080000
gicvthree0: ITS TT0 type 0x1 size 0x80000
gicvthree0: ITS TT1 type 0x4 size 0x10000
gtmr0 at acpi0: irq 27
armgtmr0 at gtmr0: ARM Generic Timer (83333 kHz)
timecounter: Timecounter "armgtmr0" frequency 83333333 Hz quality 500
qemufwcfg0 at acpi0 (FWCF, QEMU0002): mem 0x9020000-0x9020017
qemufwcfg0: <U>
acpipchb0 at acpi0 (PCI0, PNP0A08-PCI0): PCI Express Host Bridge
pci0 at acpipchb0 bus 0
pci0: i/o space, memory space enabled, rd/line, rd/mult, wr/inv ok
vendor 1d0f product 0200 (host bridge) at pci0 dev 0 function 0 not configured
puc0 at pci0 dev 1 function 0: Amazon.com EC2 Serial (com)
com0 at puc0 port 0 (16650-compatible): polling
com0: ns16550a, working fifo
com0: console
nvme0 at pci0 dev 4 function 0: vendor 1d0f product 8061 (rev. 0x00)
nvme0: NVMe 1.0
nvme0: for admin queue interrupting at irq 8192 (MSI-X vec 0)
nvme0: Amazon Elastic Block Store, firmware 1.0, serial vol0b45b29e22629dbda
nvme0: for io queue 1 interrupting at irq 8193 (MSI-X vec 1) affinity to cpu0
ld4 at nvme0 nsid 1
ld4: 30720 MB, 7801 cyl, 128 head, 63 sec, 512 bytes/sect x 62914560 sectors
ena0 at pci0 dev 5 function 0: vendor 1d0f product ec20 (rev. 0x00)
pci0: Elastic Network Adapter (ENA)ena vDRV_MODULE_VER_MAJOR.DRV_MODULE_VER_MINOR.DRV_MODULE_VER_SUBMINOR
ena0: initalize 1 io queues
ena0: for MGMNT interrupting at irq 8194 (MSI-X vec 0)
RES0 (PNP0C02) at acpi0 not configured
plgpio0 at acpi0 (GPO0, ARMH0061-0): mem 0x9030000-0x9030fff irq 39
gpio0 at plgpio0: 8 pins
acpibut0 at acpi0 (PWRB, PNP0C0C-0): ACPI Power Button
acpiged0 at acpi0 (GED1, ACPI0013-0): irq 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79
ena0: link is UP
ena0: link state UP (was UNKNOWN)
timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
cpu_boot_secondary_processors: writing mbox with 0
cpu_boot_secondary_processors: secondary processors hatched
IPsec: Initialized Security Association Processing.
boot device: ld4
root on ld4a dumps on ld4b
mountroot: trying ext2fs...
mountroot: trying ffs...
root file system type: ffs
kern.module.path=/stand/evbarm/8.99.26/modules
init: copying out path `/sbin/init' 11
ena0: device is going UP
ena0: for IO queue 0 interrupting at irq 8195 (MSI-X vec 1)
Kernel RNG "kernel" runs test FAILURE: too many runs of 1 0s (2686 >= 2685)
cprng kernel: failed statistical RNG test
Kernel RNG "kernel" runs test FAILURE: too many runs of 4 1s (393 >= 384)
cprng kernel: failed statistical RNG test
Kernel RNG "kernel" long run test FAILURE: Run of 26 1s found
cprng kernel: failed statistical RNG test
64ビットARMでのUEFIやACPI、ena(4)など、最近の変更のおかげで 使えていることが良く分かります。

ena(4)がどのように使えているのかも確認してみます。

$ ifconfig
ena0: flags=0x8843 mtu 1500
 capabilities=80200
 enabled=0
 ec_capabilities=4
 ec_enabled=0
 address: 0e:52:89:d3:32:4e
 media: Ethernet autoselect (10Gbase-T full-duplex)
 status: active
 inet6 fe80::af2d:2c6:5f60:bd02%ena0/64 flags 0x0 scopeid 0x1
 inet 172.31.34.124/20 broadcast 172.31.47.255 flags 0x0
lo0: flags=0x8049 mtu 33624
 inet6 ::1/128 flags 0x20
 inet6 fe80::1%lo0/64 flags 0x0 scopeid 0x2
 inet 127.0.0.1/8 flags 0x0
10Gbit Ethernetとして認識されていることが分かります。ですが、ネットワーク速度は実測 できていません。

pkgsrcanoncvs.NetBSD.orgからcheckout して、pkgsrc/multimedia/ffmpeg4をビルドしてみましたが、 体感的には、Intel Core SoloなNetBSD/i386のマシンが思い出されました。 思ったより速いです。

明日は、Intel CPUなマシン上で動くNetBSD/amd64でIntel Quick Sync Videoの機能を 使って、ビデオの再生やエンコードを高速化したいと思います。

pkgsrcでのクロスコンパイル方法 2018年版

この記事は、 NetBSD Advent Calendar 2018の8日目の記事です。

はじめに

pkgsrcには、今目の前にあるマシンとは違うアーキテクチャーの マシンで動くNetBSDのためのバイナリーパッケージを作る仕組みがあります。

基本的には、 pkgsrc/doc/HOWTO-use-crosscompile にあるようにすれば良い訳ですが、実際にやってみた経験のある方は 多くはないかもしれません。

今回はNetBSD/amd64 8.99.25で、 NetBSD/evbearmv7hf-el用 8.99.25のバイナリーパッケージを作成してみます。

クロスツールチェインを用意する

NetBSDはクロスビルドをするためのツールチェインを簡単に作ることができます。 具体的には、以下のようにします。

$ cd /usr/src
$ ./build.sh -U -T /usr/world/9/earmv7hf-el/tools -O /usr/world/9/earmv7hf-el/obj -D /usr/world/9/earmv7hf-el/destdir tools
$ ./build.sh -U -T /usr/world/9/earmv7hf-el/tools -O /usr/world/9/earmv7hf-el/obj -D /usr/world/9/earmv7hf-el/destdir build
これで、/usr/world/9/earmv7hf-el/tools以下にクロスコンパイラーなどが、 /usr/world/9/earmv7hf-el/destdir以下にユーザーランドが用意されます。

このクロスコンパイラーなどを使い、このユーザーランドにパッケージをインストールしつつ パッケージをビルドしていくことになります。

/etc/mk.confの設定

pkgsrcの設定は、NetBSDがホストのであって別段bootstrap pkgsrcを 実行していない場合は、/etc/mk.confに設定を書くことになります。

ここでは、以下のように実行した場合にevbearmv7hf-el用に クロスビルドするようにしてみます。

$ cd /usr/pkgsrc/www/http-parser
$ make USE_CROSS_COMPILE=YES install
/etc/mk.confに以下のように追加します。
USE_CROSS_COMPILE?=no
.if !empty(USE_CROSS_COMPILE:M[yY][eE][sS])
USE_CWRAPPERS=no
#ABI=32
CROSSBASE=${LOCALBASE}/cross
MACHINE_ARCH=earmv7hf
TOOLDIR=/usr/world/8.99/evbearmv7hf-el/tools
CROSS_DESTDIR=/usr/world/8.99/evbearmv7hf-el/destdir
PACKAGES=/usr/pkgbin/earmv7hf
WRKOBJDIR=/usr/tmp/pkgsrc/evbearmv7hf-el
.endif
最近のpkgsrcでは、ビルドを高速化するために pkgsrc/pkgtools/cwrappersというツールを使うようになっています。 ですが、このcwrappersは、クロスビルドには対応できていないようです。 USE_CWRAPPERS=noを指定しておく必要があります。

後はビルドするだけと言いたい所ですが、クロスビルド用のlibtool コマンドをネイティブ環境にインストールしておく必要があります。 クロスビルドしたearmv7hf用のバイナリーパッケージをNetBSD/amd64のユーザーランドに インストールします。 以下のように実行して準備しておきます。

# cd /usr/pkgsrc/cross/cross-libtool-base
# make USE_CROSS_COMPILE=YES package
# pkg_add -m earmv7hf /usr/pkgbin/earmv7hf/All/cross-libtool-base-earmv7hf-2.4.6nb4.tgz

後は、前述のようにコマンドを実行して待つだけです。

$ cd /usr/pkgsrc/www/http-parser
$ make USE_CROSS_COMPILE=YES install
(snip)
$ ll /usr/pkgbin/earmv7hf/All/http-parser-2.8.1.tgz
-rw-r--r--  1 ryoon  wheel  34029 Sep 28 02:08 /usr/pkgbin/earmv7hf/All/http-parser-2.8.1.tgz

ビルド結果の確認

ビルドできたパッケージを確認してみましょう。以下のようにearmv7hf用のバイナリーができている ことが分かります。

$ file libhttp_parser.so.2.0.7
libhttp_parser.so.2.0.7: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, for NetBSD 8.99.25, compiled for: earmv7hf, not stripped

全てのパッケージがクロスビルド可能な訳ではありません。私はpkgsrc/lang/rust のブートストラップキットを作成するために必要なパッケージしか試せていません。 まずはcwrappersでクロスビルドができるようにしたいと思っています。 その次にはPythonがビルドできるようになれば役立ちそうです。

明日は、最近のNetBSD/aarch64でできるようになったと言うAmazon Web Service (AWS) EC2 でのa1インスタンスでのNetBSDの動作を体験してみたいと思います。

pkgsrcでGo言語で書かれたソフトウェアをパッケージにする方法

この記事は、NetBSD Advent Calendar 2018の7日目の記事です。

はじめに

pkgsrcのパッケージは、オフラインでビルドできることが求められています。 ですので、ビルドの準備段階や最中に依存するソースコードをダウンロードするのは 避けなくてはいけません。

今日はGo言語で書かれたソフトウエアであるHugo と言うスタティックサイトジェネレーターを例にして、Go言語で書かれたソフトウエアの場合の buildlinkの仕組みを体験してみたいと思います。

依存するソフトウエアの準備方法

pkgsrcでは、configureステージ(典型的には GNU autoconfのconfigureスクリプトを実行する段階で、ビルドの1つ前の段階)の前に WRKSRC(デフォルトではそのパッケージのディレクトリー内にwork ディレクトリー)以下に、依存するパッケージのヘッダーファイルやライブラリファイルを用意して おきます。 このような処理をする場合には、例えば以下のように パッケージのMakefileから buildlink3.mkファイルをインクルードしておきます。

(snip)
.include "../../devel/go-locker/buildlink3.mk"
.include "../../www/go-toml-burntsushi/buildlink3.mk"
.include "../../www/go-urlesc/buildlink3.mk"
.include "../../devel/go-purell/buildlink3.mk"
.include "../../textproc/go-chroma/buildlink3.mk"
(snip)

ヘッダーファイルやライブラリーファイルをWRKSRC以下に配置すると 書きましたが、Go言語の場合には、ちょっと事情が異なり、ソースコードとスタティックライブラリーが 配置されます)。 実際に依存先のソースコードとスタティックライブラリーが格納されるのは、 work/.buildlink/gopkgディレクトリー以下です。 pkgsrc/www/hugoの場合の中身を少し確認してみます。
$ find work/.buildlink/gopkg
(snip)
work/.buildlink/gopkg/src/github.com/disintegration/imaging/utils.go
work/.buildlink/gopkg/src/github.com/disintegration/imaging/utils_test.go
work/.buildlink/gopkg/src/github.com/dlclark
work/.buildlink/gopkg/src/github.com/dlclark/regexp2
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/ATTRIB
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/LICENSE
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/README.md
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/match.go
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/regexp.go
(snip)
以上のように/usr/pkg/gopkgの以下の必要なパッケージの分だけが配置 されています。

パッケージング手順

Hugoの場合には、依存するソフトウエアの情報がREADME.mdに記載されています。 最初のステップは、そこに記載されているソフトウエアがpkgsrcに 収録されているかどうかを確認することから始めます。 Go言語で書かれたソフトウエアは、GitHubやgolang.org、gopkg.inといった ウェブサイトでホスティングされている例が多く、URIがソフトウエアを識別する 名前空間になっているようです。それは、MakefileGO_SRCPATHに指定されていますので、pkgsrcの ツリー内を検索すれば、目的のソフトウエアが既にpkgsrcに 収録されているか分かると思います。

通常、pkgsrcのパッケージを作る際には、 pkgsrc/pkgtools/url2pkgパッケージで提供される url2pkgコマンドを使うの便利ですが、Go言語で書かれたソフトウエアの 場合には、利用してもあまり利点はありません。 既存のGo言語で書かれたソフトウエアのパッケージのディレクトリーをコピーして それを元に作成するのが良いと思います。

ここでは、pkgsrc/www/go-aceパッケージのMakefilelbuildlink3.mkを例に注意点を説明してみます。

# $NetBSD: Makefile,v 1.6 2018/11/04 18:38:08 bsiegert Exp $ # CVSタグは変更は不要です。適切に書き変わります、

DISTNAME= ace-0.0.4b # ウェブブラウザーでダウンロードしてみてファイル名を確認して、それを使用します。
PKGNAME= go-${DISTNAME} # パッケージの名前です。通常はこのままで良いです。
PKGREVISION= 4 # 初回作成時には、PKGREVISIONは含めません。
MASTER_SITES= ${MASTER_SITE_GITHUB:=yosssi/} # GitHubでホスティングされている場合には、MASTER_SITE_GITHUBを使います。ここでは、https://github.com/yosssi/ と展開されます。
CATEGORIES= www # カテゴリーを選択して設定します。
GITHUB_TAG= 71afeb714739f9d5f7e1849bcd4a0a5938e1a70d # リリースもされておらず、タグも打たれていない場合にはハッシュ値を設定します。
GITHUB_PROJECT= ${PKGBASE:S/^go-//} # GitHubのプロジェクト名です。通常はこのままで良いです。

MAINTAINER= pkgsrc-users@NetBSD.org # 自分の電子メールアドレスを設定します。
HOMEPAGE= https://github.com/yosssi/ace # プロジェクトのウェブサイトを設定します。
COMMENT= HTML template engine for Go # パッケージの説明を1行で書きます。
LICENSE= mit # pkgsrc/licenses以下のファイル名でライセンスを指定します。

GO_DIST_BASE= ${GITHUB_PROJECT}-${GITHUB_TAG} # 通常はこのまま良いです。
GO_SRCPATH= github.com/yosssi/ace # GitHubのURIから作成します。

# Avoid a circular dependency on ace-proxy
# 以下の部分は、www/go-ace特有の処理なので、通常は必要ありません。
post-patch:
 ${RUN} ${RM} -rf ${WRKSRC}/examples/cache_options

.include "../../www/go-gohtml/buildlink3.mk" # go-aceの依存するパッケージを指定します。
.include "../../lang/go/go-package.mk" # GO言語で書かれたパッケージ用の定型句です。
.include "../../mk/bsd.pkg.mk" # pkgsrcのパッケージ用の定型句です。
実際には、pkgsrc/pkgtools/pkglintを使って、以下のようにチェックし、 「Looks fine.」となるようにします。
$ cd /usr/pkgsrc/www/go-ace
$ pkglint -Wall -Call

ビルドしてみる

Hugoの場合には、README.mdに依存するパッケージが書かれていましたが、 書かれているパッケージが依存するパッケージまでは書かれていません。 また、こんなに丁寧なではないこともあります。 Go言語のパッケージの場合には、実際にビルドしてみれば簡単に不足するパッケージが 分かります。

ここでは、pkgsrc/www/hugoから

.include "../../devel/go-locker/buildlink3.mk"
の行を削除して、ビルドしてみます。 以下のようにビルドに失敗しました。
===> Building for go-hugo-0.52
/usr/tmp/pkgsrc/www/hugo/work/src/github.com/gohugoio/hugo/cache/filecache/filecache.go:30:2: cannot find package "github.com/BurntSushi/locker" in any of:
        /usr/pkg/go111/src/github.com/BurntSushi/locker (from $GOROOT)
        /usr/tmp/pkgsrc/www/hugo/work/src/github.com/BurntSushi/locker (from $GOPATH)
        /usr/tmp/pkgsrc/www/hugo/work/.buildlink/gopkg/src/github.com/BurntSushi/locker
*** Error code 1

Stop.
make[1]: stopped in /usr/pkgsrc/www/hugo
*** Error code 1

Stop.
make: stopped in /usr/pkgsrc/www/hugo
https://github.com/BurntSushi/lockerがないことが分かりました。 これが既にpkgsrc内にあればbuildlinkすれば良いですし、 なければpkgsrc/www/go-aceの例のようにパッケージを 作成した上でbuildlinkします。 パッケージの依存関係は数珠つなぎになっていますから、 パッケージを作る作業は再帰的に続いてなかなか終わらない場合もあります。 ですが、依存しなくなったパッケージを依存関係から削除するのよりはずっと簡単です。

Go言語のパッケージは、まだまだ充実しているとは言えないと思いますので、 面白いソフトウエアがあれば教えてもらえればと思います。

明日は、pkgsrcでのクロスコンパイルの方法について書こうと思います。

NetBSD/amd64-current on HP Spectre x360 ae019TU (デスクトップ環境構築編)

この記事は、NetBSD Advent Calendar 2018の6日目の記事です。

前回の補足

前回のインストール編で 書き忘れていた点が2点ありました。

  • 最近のNetBSD/amd64-currentだと、acpibat(4)の認識のところで止まってしまいます。ですので、boot -cで起動させて、disable acpibatを入力してやるか、事前に/boot.cfgファイルを書き換えて、userconf disable acpibatを足しておく必要があります。
  • 附属の可視光/赤外線用のビデオカメラの認識の際にカーネルパニックします。PR kern/53734が正しいかは分かりませんが、uvideo(4)を無効にするか、このPRのパッチを当てておく必要があります。

はじめに

前回インストールしたNetBSD/amd64 8.99.26では、以下の機能が使えます。

  • オーディオ出力
  • Synaptics製タッチパッド
  • microSDカードリーダー
  • 無線LAN
  • NVMe SSDストレージ
  • Intel製内蔵GPUによるアクセラレーション
  • USB Aコネクター経由でのUSB 3デバイスの利用
以下の機能は、パッチを当てれば使えます。
  • タッチスクリーンのペンによる操作
以下の機能は使えません。
  • 内蔵の可視光/赤外線のウェブカメラ
  • タッチスクリーンの指による操作
  • 指紋認証
  • USB Type-Cコネクター経由でのUSB 3デバイスの利用
  • ディスプレイの輝度調整
  • ACPIで電源を切る(shutdown -p nowが働かない)
  • ACPIで内蔵バッテリーのステータスを取得する
  • ハードウェアボタンによるオーディオ音量調整
細かい所は不便ですが、生活するのに困るほどではありません。

ここでは、快適にFirefoxウェブブラウザー(pkgsrc/www/firefox)で ウェブブラウジングができるようにする、Blender(pkgsrc/graphics/blender)で3Dモデリングができるまでを説明して行きます。

必要なパッケージのインストール

快適なX Window Systemの環境を容用意するには、残念ながらxsrcから 生成されたXでは不十分なことは前回も触れました。 ここでは、pkgsrcでも不十分ですので、lpkgsrc-wip も利用します。 pkgsrc-wipは、pkgsrcに収録されていない 作業中のパッケージを収録しているリポジトリーです。 pkgsrc-wipは、Git等のバージョン管理システムの リポジトリーからパッケージをビルドする仕組みが充実しているので、 リリースされていないソフトウエアは、pkgsrc-wipに置かれたままに なっていることもあるようです。

pkgsrcのディレクトリーの下に以下のようにpkgsrc-wipの リポジトリーを展開します。

$ cd /usr/pkgsrc
$ git clone git://wip.pkgsrc.org/pkgsrc-wip.git wip
これにより、pkgsrc-wipのリポジトリーが/usr/pkgsrc/wip ディレクトリーに配置できました。

今回使うのは、/usr/pkgsrc/wip/xf86-video-intel-gitパッケージです。 また、/usr/pkgsrc/x11/modular-xorg-serverについては、 /usr/pkgsrc/graphics/MesaLib18を利用する必要があります。 となると、以下のような順序でパッケージをインストールすることになります。

# cd /usr/pkgsrc/graphics/MesaLib18
# make install
# cd /usr/pkgsrc/wip/xf86-video-intel-git
# make install
ここで、/usr/pkgsrc/x11/modular-xorg-serverは、 /usr/pkgsrc/wip/xf86-video-intel-git の依存パッケージとしてインストールされるので、明示的にmake install を実行する必要はありません。

他には、生活に必要なパッケージを入れて行きます。 今回は、FirefoxとBlenderを使えるようにするのが目的でしたが、 Xのモジュールやターミナルエミュレーター、ウィンドウマネージャー、日本語インプットメソッド、フォントなども必要です。

# /usr/pkgsrc/x11/xf86-input-mouse
# make install
# /usr/pkgsrc/x11/xf86-input-keyboard
# make install
# /usr/pkgsrc/fonts/noto-ttf
# make install
# /usr/pkgsrc/meta-pkgs/modular-xorg-apps
# make install
# /usr/pkgsrc/meta-pkgs/modular-xorg-fonts
# make install
# /usr/pkgsrc/meta-pkgs/modular-xorg-utils
# make install
# /usr/pkgsrc/www/firefox
# make install
# /usr/pkgsrc/graphics/blender
# make install
# /usr/pkgsrc/wm/jwm
# make install
# /usr/pkgsrc/x11/mlterm
# make install
# /usr/pkgsrc/inputmethod/fcitx-skk
# make install
それぞれの設定については、省略します。

この組み合わせであれば、FirefoxでWebGLなウェブページを楽しんだり、 快適にBlenderで3Dモデリングを楽しんだりすることができます。 ここでは、FirefoxでWebGLでアクアリウムを表示するサンプルを表示させたスクリーンショットを 掲載しておきます。 もし描画が乱れる場合には、 アクセラレーションメソッドをSNAではなくUXAにして みてください。

本当は、xsrcからインストールしたX Window Systemで以上のような ことができれば良いのですが、現状ではうまく行きません。

明日は、Go言語で書かれたソフトウエアをpkgsrcのパッケージにする例を紹介したいと思います。

NetBSD/amd64-current on HP Spectre x360 ae019TU (インストール編)

この記事は、 NetBSD Advent Calendar 2018の5日目の記事です。

はじめに

2018年7月のJapan NetBSD Users' GroupのBoFの際には、いろいろ動かないものばかり だったのだが、2018年12月現在では、HP Spectre x360 13-inch ae019TUも多くの 機能がちゃんと動くようになっている。 今日から2日間は、HP Spectre x360 13-inch ae019TUで、快適にNetBSDデスクトップを 使用する方法について書いていきたい。 ちなみにこの記事は、おおしまさんのU-EFI bootで起動するNetBSD USBメモリを作ってみるの記事を 読んだ方にはほぼ不要だと思います。

NetBSDのインストール

このマシンには、当然のようにDVDドライブなどは内蔵されていない。 それにUEFIな環境で使用したい。 と言うことで、今日の時点で最新なNetBSD-8.99.26-amd64-uefi-install.img.gznycdn.NetBSD.orgから ディスクイメージをダウンロードして USBスティックに書き込み、インストールに使用することにする。 NetBSDの環境があれば、そこでddコマンドで書き込むのが良いのだが、 今回は、Windows 10 Proの環境で書き込んでみた。rawrite32.exeを使う。 rawrite32.exeは、a href="https://www.netbsd.org/~martin/rawrite32/"> lNetBSD.orgにあるmartin@のウェブページからダウンロードすることができる。 ちなみに、既にGPTなパーティショニングがされていると、rawrite32.exeでは どうやってもエラーになってディスクイメージを書き込めないことがある。 どうにかしたいのだが、何も行動できていない。

実際のインストールは、インストーラーであるsysinstは使用しなかった。 おそらくsysinstは、GPTパーティショニングな環境へのインストールに まだ対応していないのではないかと思う。これについても何もできていない。 今回は、sysinstが起動したら、すぐにCtrl-Cを押して シェルに移行し、そこでインストールを行なった。 このマシンのストレージはNVMeなSSDであり、ld0として認識される。 容量は1 TBである。 以下のようにしてパーティションを設定する。

# gpt create ld0
# gpt add -s 128m -t efi -l EFI ld0
# gpt add -s 50G -t ffs -l ROOT ld0
# gpt add -s 32G -t swap -l SWAP ld0
# gpt add -s 250G -t ffs -l USR  ld0
# gpt -t ffs -l HOME ld0
以下のようにそれぞれのパーティションをnewfsする。 ここで、ld0に作成した各GPTパーティションはdk2移行に 割り振られているものとする。今のdk2が実際に使用する際には dk0となる。
# newfs_msdos /dev/rdk2
# newfs -O2 /dev/rdk3
# newfs -O2 /dev/rdk4
# newfs -O2 /dev/rdk5
# newfs -O2 /dev/rdk6
# gpt set -a bootme -i 2 ld0
ここで注意すべき点があるとすれば、gpt biosbootコマンドを使ってはいけない ということである。 これを実行してしまうと、このマシンではUEFIでもCSMでも起動しなくなる (そもそも純粋なUEFIモードというのが、このマシンのBIOS設定では不可能なようであるが)。 以下のようにUEFIブートローダーを配置する。
# mkdir /efiboot
# mount_msdos /dev/dk2 /efiboot
# mkdir -p /efiboot/EFI/boot
# cp /usr/mdec/boot*.efi /efiboot/EFI/boot
# umount /efiboot
これにより、bootia32.efibootx64.efiが配置され、 bootx64.efiが使用されることとなる。 あとは、パーティションを実際の使用時と同じ構造で/mnt以下に にmountして例えば以下のように配布物を展開しておく。
# tar zxvfp base.tgz -C /mnt
# tar zxvfp etc.tgz -C /mnt
ここで、他の配布物も展開しておいて良いが、X Window Systemに関しては、 xsrcからビルドしたものでは快適なデスクトップ環境は実現できないので、 X Window System関連のものは展開しない。 忘れてはいけないのが、/dev以下のノードの作成である。 このタイミングでちゃんとやっておかないとtmpfsが使われてしまい。 直すのが面倒である。 他にも必要なものを準備しておく。
# cp / mnt/usr/mdec/boot /mnt
# mkdir /mnt/kern
# mkdir /mnt/proc
# cd /mnt/dev
# ./MAKEDEV all
後は設定ファイル類を準備すれば良い。
# vi /etc/fstab
NAME=ROOT /  ffs rw,log 1 1
NAME=SWAP none  swap sw,dp 0 0
NAME=USR /usr  ffs rw,log 1 1
NAME=HOME /home  ffs rw,log 1 1
kernfs  /kern  kernfs rw
ptyfs  /dev/pts ptyfs rw
procfs  /proc  procfs rw
tmpfs  /var/shm tmpfs rw,-m1777,-sram%25

# vi /etc/rc.conf
(snip)
rc_configured=YES
(snip)

ここまで来れば、後はいつものNetBSD環境である。 dmesgは、dmesgdに投稿してある。 一つ残念なこととして、USB Type-CポートがUSB 3のデバイスを認識しないというのがある。 どうにか直したいのだが…。

明日は、pkgsrcpkgsrc-wipを使って(私的に)快適なデスクトップ環境を構築する話を書きます。

pkgsrc/security/acmeshでLet's EncryptのTLS/SSL証明書を使う

この記事は、NetBSD Advent Calendar 2018の4日目の記事です。

自分のウェブサイトをLet's EncryptでTLS/SSL化したいと思っていて、 過去にはpkgsrc/security/py-certbotを試すために pkgsrc/sysutils/py-psutilのNetBSDへの移植に 取り組んだこともあったのだが、なかなか継続的に利用し続けるのは大変だった。

NetBSD blogの Using acme.sh for Let's Encrypt certificates on pkgsrc.org servers を読んで、acme.sh を試したいと思ったのだが、そもそもpkgsrcには収録されていないし、DNSによる認証は ちょっと遠慮したいので、そのまま適用はできないでいた。 やっと重い腰を上げてpkgsrcに追加して設定した話を書きたい。 ちなみに、ワイルドカード証明書が発行できるようになっているが、今回はワイルドカード証明書 は発行を受けない。

インストール

インストールは、pkgsrc/security/acmeshを使えば良い。

# cd /usr/pkgsrc/security/acmesh
# make install
以上のように実行すれば良い。このようにインストールすると、 ▽usおそらくHTTPでの認証で ウェブサーバーをインストールしないでもTLS/SSL証明書を発行できるように pkgsrc/net/socatもインストールされる。 今回はsocatは使わないがインストールされてしまう。

TLS/SSL証明書の発行を受ける

TLS/SSL証明書の発行を受けようというサーバーのホスト名はwww.example.com であることにしよう。 このFQDNでアクセスできるようにDNSを設定しておくのが必要なのは言うまでもない。

私は、このサーバーでpkgsrc/www/nginx-develをhttpdとして 使用する予定なので、TLS/SSL証明書の発行を受ける際にも、これを使用することにする。 以下のようにインストールし、設定しておく。

# cd /usr/pkgsrc/www/nginx-devel
# make install
# vi /usr/pkg/etc/nginx/nginx.conf
http {
(snip)
    server {
        listen       80;
        server_name  www.example.com;
(snip)
        location / {
            root   /usr/htdocs;
            index  index.html index.htm;
        }
(snip)
# cp /usr/pkg/share/examples/rc.d/nginx /etc/rc.d
# vi /etc/rc.conf
(snip)
nginx=YES
(snip)
# /etc/rc.d/nginx start
次に、HTTPでの認証用のファイルの作成などをacme.shコマンドを使って行なう。
# sudo nginx
$ /usr/pkg/sbin/acme.sh --issue -w /usr/htdocs -d www.example.com
これによって、例えば
/usr/htdocs/.well-known/acme-challenge/q-h2-aGCzrWmEurHUYgG_KZU1hVroXgi9n6nzNH0odc
のようなファイル名のファイルが生成され、2分間(?)程度待つとTLS/SSL証明書が発行される。 場所は、nginxユーザーのホームディレクトリーである/var/db/nginx 以下である。 使用する2つのファイルを/usr/pkg/etc/nginx内にシンボリックリンクしておく。
# cd /usr/pkg/etc/nginx
# ln -s /var/db/nginx/.acme.sh/www.example.com/fullchain.cer www.example.com.cer
# ln -s /var/db/nginx/.acme.sh/www.example.com/www.example.com.key www.example.com.key

これらを、それぞれ/usr/pkg/etc/nginx.confに以下のように設定する。

# vi /usr/pkg/etc/nginx.conf
(snip)
http {
    server {
        listen       443 http2 ssl;
        server_name  www.example.com;

        ssl_certificate      www.example.com.cer;
        ssl_certificate_key  www.example.com.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
(snip)

TLS/SSL証明書を更新する

このように発行されたLet's EncryptのTLS/SSL証明書は、3カ月しか有効ではない。 毎回手作業では大変なのでcronで自動的に更新したい。 今回は以下のように、TLS/SSL証明書を再取得してnginxを再起動する ように設定した。しかし、まだ初回の更新の機会がめぐって来ていないので、 実際のところはうまく動くかは分からない。

# cd /usr/pkgsrc/security/sudo
# make install
# visudo
(snip)
nginx ALL=(root) NOPASSWD: /etc/rc.d/nginx reload
# sudo nginx
$ crontab -e
3 1 * * * /usr/pkg/sbin/acme.sh --cron --home /var/db/nginx/.acme.sh --reloadcmd "/usr/pkg/bin/sudo /etc/rc.d/nginx reload" && /usr/pkg/sbin/acme.sh --cron --home /var/db/nginx/.acme.sh  --installcert -d www.example.com --reloadcmd "/usr/pkg/bin/sudo /etc/rc.d/nginx reload"
crontabの内容について、実際に動くのを確認できた内容に書き換えました。

明日は、NetBSDデスクトップ環境として常用しているHP Spectre x360 13-inch ae019TUについて、 NetBSD/amd64-currentをインストールする話を書こうと思います。

plgarc/wip/llama.cppでpkgsrcのBLASサポートを探る

この記事は、 NetBSD Advent Calendar 2024 の13日目の記事です。 llama.cppを使ってみる 以前に、 NetBSD/amd64でllama.cppを使ってみる という記事で llama.cpp を使ってみていました。 あれか...