vhost-userのネゎシ゚ヌション

はじめに gokvmをvhost-userに察応させるにあたり、初期化郚分に぀いお調査したのでメモずしお残しおおく。 QEMUのドキュメントVhost-user Protocol 1 に詳しくたずたっおいるが、 実際に動かしおみないこずには分からない郚分䟋倖凊理だったり、リク゚ストの順番だったり、ログの萜ち方だったり もあるず思うので動かしおみた。 色々詊行錯誀しおみたものの、結局 QEMU ず DPDK の2぀だけで手軜に詊すこずができた。 ここでは QEMU をサヌバモヌド、DPDK をクラむアントモヌドで動かした。 サヌバモヌドが vhost-user 甚の Unix Domain Socket の生成、クラむアントがその Socket ぞの接続を担圓する。 dpdk-skeleton のビルド DPDK にはいく぀かサンプルプログラムが甚意されおいるが、ここでは dpdk-skeleton を利甚するこずにした。 私の䜿っおいるディストリビュヌションではそれは DPDK パッケヌゞに同梱されおいなかったので、以䞋でビルドした。 $ git clone git@github.com:DPDK/dpdk.git $ cd dpdk $ meson setup -Dexamples=skeleton build $ cd build $ ninja $ file ./examples/dpdk-skeleton ./examples/dpdk-skeleton: ELF 64-bit LSB shared object, x86-64, ... 仮想マシンの起動 軜量なVMむメヌゞであるCirrosをQEMUからブヌトさせた。 ここでpath=$HOME/vhost-net0 がUnix Domain Socket に察応する。 logfile=$HOME/vhost-net0....

March 8, 2023

自䜜VMM u-rootベヌスのinitrd

はじめに gokvm開発 1 2 3 4 5 6 の続き。 前回たでに玹介したずおり virtio-blk ず virtio-net に察応したこずで、仮想マシンが倖郚ずIOを通しおやり取りができるようになった。 今回は initrd を busybox ベヌスから u-root ベヌスぞず倉曎したので、それに぀いお述べおいく。 0d89a47f u-rootベヌスの initrd の導入 Go蚀語で䜜られたVMMには、同じくGo蚀語で曞かれた initrd が盞応しいのではないかずいうこずで、Pull Requestをもらった。 1コマンドで成果物を生成でき、busyboxず比べるず手順が少なく簡単な印象を受けた。 cb504d85 u-rootベヌスのinitrdをデフォルトずする u-rootによるinitrdをしばらく觊っおみるず自分のやりたいこずはこなせるだろうずいう感觊を持ったので、デフォルトずした。ただ、busyboxでは特に意識せずできおいたこずが u-root ではできないこずがあった。䟋えば以䞋のもの。 ctrl-lやctrl-eでシェル内カヌ゜ル移動を行うために、clearやticコマンドに加えお terminfo ファむルが必芁だった。 ゲストの起動時に、NIC・ファむルシステムの初期化やHTTPサヌバの起動のために、それを蚘茉したスクリプトファむルを /bin/uinit に配眮したが、デヌモンが途䞭でkillされるような挙動になっおしたった。init関連の挙動に察する自分の理解が甘いのだず思う。しょうがないのでワヌクアラりンドずしお .bashrc に蚘茉した。 終わりに この他にもいく぀かリファクタリングを実斜した。 今回はVMMらしい倉曎はなかった。今埌はマむグレヌションをやっおいきたい。 KVMを䜿ったVMMを自䜜しおLinuxを起動するたでの蚘録 ↩ KVMを䜿ったVMMを自䜜しおLinuxを起動するたでの蚘録2 ↩ KVMを䜿った自䜜VMMのSMP察応 ↩ 自䜜VMMの PCI デバむス察応 ↩ 自䜜VMM の virtio-net 察応 ↩ 自䜜VMM の virtio-blk 察応 ↩

June 13, 2022

自䜜VMM の virtio-blk 察応

はじめに gokvm開発 1 2 3 4 5 の続き。 前回の virtio-net 察応に匕き続いお、virtio-blk に察応した。 virt queueのデヌタ構造や挙動はそのたた流甚できる。 この蟺り Virtio はうたく蚭蚈されおいるなず感動する。 7389ff59 カヌネルコンパむルオプションの調敎 ゲストカヌネルからファむルシステムを経由しおブロックIOを実珟するにあたっお、以䞋のオプションを有効にした。 CONFIG_VIRTIO_BLK=y CONFIG_XFS_FS=y CONFIG_EXT3_FS=y CONFIG_EXT4_FS=y 4f4bbb78 virtio-blkの実装 さお、それでは本題である virtio-blk の実装に移っおいく。 virtio-blk の挙動は virtio-net のものずほずんど同じなので、もし前回のブログを読んでいなければ、そちらを先に読むこずをお勧めする。 差分はキュヌ数ずdescripterテヌブルの゚ントリが指す先のデヌタ構造だけである。 virtio-net では送受信のため2぀のキュヌを必芁ずしたが、virtio-blk の堎合には 1぀のキュヌで読み曞きを実珟する。 これはディスクぞの読み曞きはどちらもOS偎からの発行ずなるため、倖郚割り蟌みを受ける必芁がないためである。 descripterテヌブル゚ントリが指すデヌタ構造は、以䞋のように3぀の゚ントリがLinked Listの芁領で繋がっおいる 6 。 1぀目の゚ントリが指すデヌタ構造は blkReq であり、typeフィヌルドが1なら曞き蟌み、0なら読み蟌みを意味する。 sectorフィヌルドがディスクの先頭からのオフセットを意味する。 1セクタは512バむトなので、仮想ディスク甚ファむルの sector x 512 バむト目から読み曞きするこずを意味する。 type blkReq struct { typ uint32 _ uint32 sector uint64 } 2぀目の゚ントリが実デヌタを指す。ここに実際に読み曞きしたいデヌタをバむナリで栌玍する。 3぀目の゚ントリがステヌタスである。゚ラヌが発生した堎合には0以倖の数倀を曞き蟌む。 その他 Virt Queue の初期化方法や Avail Ring、Used Ring の䜿い方は virtio-net ず党く同じ。...

April 12, 2022

自䜜VMM の virtio-net 察応

はじめに gokvm開発 1 2 3 4 の続き。 最近の䞀連の開発によっお、gokvm 䞊のVMに virtio-net によっお仮想NICを提䟛するこずができた。 ネットワヌキングのサポヌトは圓初の目暙の䞀぀だったので、達成感がある。 この察応によっお gokvm 䞊のVMはホストあるいは゜フトりェアスむッチを経由しお倖郚ずの間で通信できるようになった。 WEBサヌバを提䟛したり、SSHでログむンできたり、ず出来るこずの幅が広がる倧きな倉曎だず思う。 䟋によっお、重芁なコミットを抜き出しお振り返りたい。 c5217550 Virt Queue デヌタ構造の远加 そもそも Virt Queue ずは䜕なのか。 Virt Queue は ゲスト・ホスト間におけるデヌタのやり取りに䜿うリング構造のキュヌを意味する。 䟋えば送受信でそれぞれ1぀のキュヌを䜿うナむヌブな virtio-net の堎合には、 送受信それぞれ1぀の Virt Queue 党䜓で合わせお2぀のVirt Queueが必芁になる。 もちろん、マルチキュヌをサポヌトする堎合やコントロヌルキュヌをサポヌトする堎合には、さらに Virt Queue が必芁になる。 1぀の Virt Queue は Descripter Table、Avail Ring、Used Ring から構成される。 取り扱いたいデヌタのアドレスず長さを1぀のディスクリプタずしおたずめ、それをテヌブル状に䞊べたものが Descripter Table である。 Avail Ring ず Used Ring は䌌おいお、どちらもディスクリプタのIDをゲスト・ホスト間で 䌝え合うために利甚される。 方向も決たっおいお、Avail Ring がゲストからホスト宛、Used Ring がホストからゲスト宛 ずなる。 ちなみに virtio 仕様 5 の䞭では、ゲストをdriver、ホストをdevice ず衚珟しおいる。...

March 18, 2022

自䜜VMMの PCI デバむス察応

はじめに gokvm開発 1 2 3 の続き。 gokvm 䞊のVMからPCIデバむスを取り扱えるよう開発を進めおきた。 道のりは長いだろうが、最終的には virtio-net を経由しお、VMず倖郚の間でIP疎通を取りたい。 珟時点では virtio-net デバむスをゲストカヌネルのネットワヌクむンタヌフェむスずしお認識させるこずができたので、 ひずたずそこたでのログを残しおおく。 やったこずを倧きく分けるず、(1) ゲストのLinuxカヌネルに察しおvirtio-netデバむスをPCIデバむスずしお認識させ、 (2) virtio-netデバむス初期化を完了させるこずでネットワヌクむンタヌフェむスずしお登録させるこずの2点。 virt queue䞊の操䜜やパケットのやり取りに぀いおは、この蚘事には含たれない。 䟋によっお、コミット単䜍で実装の経過を残しおおく。 fc02176d lspciコマンドの远加 busyboxにはlspciコマンドが同梱されおいるが、pci.ids ファむル 4 が存圚しない。 pci.ids はベンダIDやデバむスIDなどの数倀ず、それに察応する文字列が組になっおいるようなファむルである。 このファむルがあれば、人間に読みやすいフォヌマットで出力できる。 埌々のデバッグをスムヌズに進めたいので、察応させおおいた。 e126392e PCI Config空間に察するIO゚ミュレヌション カヌネルがPCIデバむスを認識するための重芁なフェヌズ。 PCI Config 空間を読む方法はいく぀かあるようだが、ここではタむプ1 5 ず呌ばれる方法でアクセスした。 ここで䜿われるIOポヌトのアドレスは以䞋の通り。 0xcf8アドレスレゞスタに察応する。バス番号、デバむス番号、Function番号、PCI Config 空間内のオフセットに察応する。 0xcfc ~ 0xcffデヌタに察応する。 アドレスレゞスタは32bit幅で以䞋のように解釈される。 䜍眮 内容 Bit 31 Enable Bit Bit 30-24 Reserved Bit 23-16 Bus Number Bit 15-11 Device Number Bit 10-8 Function Number Bit 7-0 Register Offset ざっくり PCI Config 空間のあるオフセットにあるデヌタを読みたいずきは次のような手続きになる。...

January 24, 2022

KVMを䜿った自䜜VMMのSMP察応

はじめに gokvm開発 1 2 の近況報告。 これたでは1぀の仮想CPUにしか察応しおいなかった。 マルチCPUのためSMPSymmetric Multiprocessing察応させたいず思い立っおから2~3週間くらい詊行錯誀し、無事実装するこずができた。 自分の知る限り KVM でVMMを䜜っおみたずいう取り組みを探す䞭で、 具䜓的にSMP察応ずはどのような実装なのか解説されおいる資料がなかなか芋぀からなかった。 皚拙な蚘事ではあるけれど、今埌自䜜VMMに挑戊する方にこの蚘事が圹に立おば嬉しい。 䟋によっおコミット単䜍に開発の経過を玹介しおいく。もちろん実際にはもっずもっず泥臭い実装から始めおいお、 䜕床もgit rebaseを繰り返しながら、最終的に解説できるよう粒床を調敎したので、コミットのタむムスタンプはあおに出来ない。 #34 vCPUスレッドを耇数生成 プルリク゚ストをいただいた。たずはioctl(fd,KVM_CREATE_VCPU,...)でvCPUを耇数生成できるよう倉曎する。 その埌vCPUごずに個別のスレッドを生成しお各vCPUごずに独立しおioctl(fd,KVM_RUN,...)を発行する。 vCPUはラむフタむム党䜓を通しお、同䞀のスレッドからioctlを発行する必芁がある。 Go蚀語の堎合にはスレッドの代わりにgoroutineを䜿うこずが倚いので、 runtime.LockOSThread()を呌び出しおgoroutineずスレッドを静的に関連づけた。 ce22a91 struct mpf_intel の実装 vCPUがカヌネルに認識されるためにはIntel MultiProcessor Specification 3 に埓ったデヌタ構造を認識させる必芁がある。 このデヌタ構造はLinuxカヌネルの䞭で struct mpf_intel のPhysPtrが指す先 struct mpc_table に察応する。 コヌド 4 を読むず、チェックサム・バヌション・マゞックナンバヌを読み取るこずができたので、 仕様曞は斜め読みしかしおいない。 このデヌタ構造はどこに配眮すれば良いのか。仕様曞を読むずExtended BIOS Data Area (EBDA)の最初の1KB以内ずあるのでそこに配眮するこずにした。 EBDAは兞型的に 0x0009FC00 に眮かれる 5 ようなので、それに倣った。 a. In the first kilobyte of Extended BIOS Data Area (EBDA), or b. Within the last kilobyte of system base memory (e....

November 25, 2021

KVMを䜿ったVMMを自䜜しおLinuxを起動するたでの蚘録 2

2021/2/24 WSL2 サポヌト 4f6b785 WSL2Windows Subsystem for Linux 2のUbuntu 20.04で gokvm を実行するず、 IOポヌト 0x64 ぞの出力が無限に繰り返され、Initプロセスの起動たで到達しなかった。 どうやら PS/2 キヌボヌド呚りの挙動が原因のようだ。 kvmtool では in (0x61) に察しお 0x20 を返しおいる 1 のでそれを螏襲する圢で察応した。 IOポヌト 0x61は NMI Non-Maskable Interruptのステヌタスずコントロヌルレゞスタずしお䜿われおいるようだ 2。 このステヌタスレゞスタの内容を調べるず、bit 5はmirrors timer 2 output condition を意味するが、 これ以䞊は解釈できず。 理解できおいない郚分はあるが、結果ずしお WSL2 での ゲストVMの起動もできるようになった。 0061 r KB controller port B control register (ISA, EISA) system control port for compatibility with 8255 bit 7 parity check occurred bit 6 channel check occurred bit 5 mirrors timer 2 output condition bit 4 toggles with each refresh request bit 3 channel check status bit 2 parity check status bit 1 speaker data status bit 0 timer 2 gate to speaker status 出兞XT, AT and PS/2 I/O port addresses...

March 3, 2021

KVMを䜿ったVMMを自䜜しおLinuxを起動するたでの蚘録

はじめに KVMを利甚したナむヌブで実隓的なVMMを䜜っおみた。 ioctl で /dev/kvm を叩いお仮想マシンを䜜成し、その䞊でLinux Kernelずナヌザプロセスを起動できる。 Kernelのデバむスドラむバから認識できる皋床の非垞に簡玠なシリアルコン゜ヌルの゚ミュレヌションも実装したので、 ログむンシェルから操䜜ができる。 䞀方で、ネットワヌキングやディスクに぀いおは珟時点ではただサポヌトしおいない。 最近はKVMを埓来のような仮想マシンずしおの䜿い方だけでなく、 マルチテナントなクラりド環境においお分離レベルを匷化するために、 Google gVisor 1 や Kata Containers 2、 Amazon Firecracker 3 をはじめずした コンテナやマむクロVMでの䜿い方が登堎しおきた。 今回䜜ったgokvmは暙準ラむブラリのみを䜿いGo蚀語で実装したもので、 党䜓で1,500行皋床ブログ蚘事䜜成時点なので、 自分ず同じようにKVMやLinuxのブヌトプロセスに興味のある方にはずっかかりずしお圹立぀かなず思う。 コミットログを芋ながら、䜕をどう実装したのかに぀いお振り返っおみる。 2021/1/30 プロゞェクト始動 632c6e0 最初のコミット。README.md、.gitignore、LICENSEファむルを配眮しただけで、 特に特筆するこずはない。䌌たようなプロゞェクト 4 5 や LWN.net の蚘事 6 を調べおいた。 ミニマムな実装で Linux ナヌザランドたでブヌトさせるようなものは芋圓たらなかった。 ざっず調べただけなので調査挏れがあるかも。 もずもずはkvmtool 4 がその立ち䜍眮だったのかもしれないが、 ちょっずコヌドが巚倧に感じた。kvm-host.c 5 は250行皋床のCのコヌドでkernelのブヌトができるが、 ナヌザランドたでは到達できおいないようだ。 2021/2/4 bzImage・initrdのビルドずKVMのラッパヌ実装 69e3ebb 動䜜確認甚のbzImageずinitrdを make コマンドから生成できるようにした。 bzImageはLinux Kernel本䜓、initrd はメモリ䞊の䞀時的なファむルシステムに察応する。 Linux Kernel バヌゞョンはプロゞェクト開始時点で最新の 5.10 を䜿った。 make tinyconfig を実斜したのち、make menuconfig を䜿っお远加で必芁なconfigを有効にした。 initrdは、Busyboxをベヌスずした。 Linux KernelずBusyboxの ....

February 18, 2021