読者です 読者をやめる 読者になる 読者になる

Linuxカーネルを新しいCPUに移植する

この記事はLinuxアドベントカレンダー2015 21日目に大遅刻した記事です。ごめんなさい

皆さん、ご家庭に「作ってみたはいいけれど、動くOSがなくて困ってる!」っていうCPUはありませんか?もしそんなCPUがあればLinuxを移植してみてはどうでしょう??
この記事ではLinuxを新しいCPUへ移植する話をします。

前書き

なぜLinuxを新CPUに移植する話をしているかというと、学科の同期数名で、FPGAで作ったCPUにLinuxを移植するということを5月ごろから細々と進めているからです。(もっとも院試やら卒論やらで本格的に作業できるのは実際には来年の2月以降です。。)これは以前自作CPUにxv6を移植したやつの第2段階ですね。

まだ新CPUのもろもろが出来上がっていませんので、現在は本番の移植のための勉強としてx86アーキテクチャのミニマムな再実装をやっているところです。本記事は今までの知見をもとに書かれています。まだ移植を完成させたわけではないので、記述に不完全/誤ったところがあるはずです。見つけた場合はご指摘くださいませ。

移植関連資料

さて、Linuxを新CPUに移植するのは簡単なタスクではありません。やることはそれなりにありますしLinuxカーネルの理解ももちろん必要です。そして何よりまとまった資料が少ないことが問題になりました。以下に参考になりそうな資料をいくつか挙げておきます。

Embedded Linux Conferenceでの発表資料です。移植の全体的な流れが俯瞰できると思います。

K1というプロセッサーにLinuxを移植した際の話が載っています。実際に移植する際の具体的な雰囲気が感じ取れます。

Linuxカーネルを移植するための正しい方法」についてのLWNの記事なんですが、要約すると「x86からコピペすんなカス」という記事です。詳しい移植の流れなどについては特に触れられていませんが、今では不可欠な存在になったasm-genericが紹介されています。

で、僕らが作業を始めた頃はこれくらいしか資料がなく大変だなーと思っていたのですが、実は最近次の記事がLWNに上がったようです。

移植にあたって書かなければいけないことが、簡単にではありますが、網羅的にまとまっています。これからLinuxを移植しようと思ったらまず第一に参照すべき資料になると思います。*1

Linuxカーネルそのものの情報については、定番ですが

詳解 Linuxカーネル 第3版

詳解 Linuxカーネル 第3版

が参考になると思います。

ただ、ご存じの通り詳解Linuxカーネルは扱うカーネルのバージョンがだいぶ古く、現在の状況と食い違うことがしばしばあります。最近は0xAXさんによる Linux Inside - GitBook が、最新の4.x系列のカーネルに沿った解説をしていてかなり参考になります。現在進行形で内容がどんどん充実してきているのでぜひブクマしておきましょう。

ツールチェインの移植 - clangも使えるけど・・・

Linuxを移植するにはLinuxコンパイルできるコンパイラアセンブラ、リンカが必要になります。なので先にこれを移植しなければなりません。

まず絶対にGNU binutilsは必要です。asやldですね。Linuxをビルドしたいなら他の選択肢はないはずです。次にコンパイラですが、移植するのはgccとclangどちらでも一応大丈夫です。「あれ、Linuxってclangでビルドできたっけ?」となると思うんですが、実はアーキテクチャ非依存部はclangでもビルド可能になっています。x86のビルドが現時点ではこけてしまうので実感がないと思うのですが、後々紹介するスタブアーキテクチャはclangでもばっちりビルドできます。clangでのLinuxのビルドの状況は別記事にでもまとめたいですね。

ただ現状ではclangのビルドは不安定です。3.6系でtypeof演算子のバグを踏んでカーネルのビルドが落ちていたなどclang側でも時々問題が発生しますし、カーネル側もarch/x86を見ればわかる通りclang未対応の機能を気兼ねなくぶち込んできます。お互いにお互いをあまり慮っていないように見えるので、clangを選ぶ際はそこらへんを考慮した方がいいでしょうね。Linuxをclangでビルドできることが当たり前になる時代はそう遠くないと体感的には感じているんですが・・・。

gccbinutilsの移植に関しては今回はこれ以上触れません。 詳しくは、Open Computer Design Projectの 新アーキテクチャに GCC を移植 [Open Design Computer Project] がとても参考になると思います。

archディレクトリ

ここからが本題になりますね。Linuxカーネルアーキテクチャ依存部を書く話です。

まずLinuxソースコードの構成をざっと俯瞰すると、だいたい以下のような感じになっています。

├ Documentation/     
├ arch/     
├ block/    
├ certs/    
├ crypto/   
├ drivers/  
├ firmware/     
├ fs/   
├ include/  
├ init/     
├ ipc/  
├ kernel/   
├ lib/  
├ mm/   
├ net/  
├ samples/  
├ scripts/  
├ security/     
├ sound/    
├ tools/    
└ usr/virt/  

kernelにはカーネルのコアになる機能、fsにはファイルシステム、mmにはメモリ管理周りといった風に、目的に応じてソースコードが分類されて詰められています。ドライバーなどは別にすれば、移植に当たって触らなければいけないのは、上から2番目のarchディレクトリだけです。この中にさらにアーキテクチャごとにディレクトリが作られ、例えばx86やらmipsやらopenriscやらといったものがこの中にすでに並んでいます。ここに新しいディレクトリを作り、アーキテクチャ依存部として必要なソースコードを追加していくのが具体的なLinuxの移植作業になります。

例えばnew_cpuというアーキテクチャを追加したければ、arch/new_cpuなるディレクトリを作ればいいことになります。加えてちょこちょことMakefileなどを追加すれば、

make ARCH="new_cpu"

とかするとカーネルがnew_cpuディレクトリを認識してくれてビルドを始めることができます。便利ですね。
といっても何も書いていない空ディレクトリではもちろん普通にビルドに失敗します。移植の第一歩はひとまずビルドができるように、各種ファイルやスタブ実装のコードを用意することになります。

ビルドシステムの理解

arch/new_cpu以下に必要なのはソースコードだけではありません。arch依存のMakefileも必要ですし、menuconfig用のconfigなどなども必要になります。ここらへんを何の頼りもなしに用意するのは不可能ですから、ほかのアーキテクチャを参考にしてarch/new_cpu以下に何を配置すべきなのか参考にしましょう。ただしこのとき、間違ってもx86などの奇天烈なアーキテクチャを参考にしてはいけません。おすすめなのは先ほど上げた資料中でも紹介されていたscoreというアーキテクチャで、とてもファイル数が少なく全体を読み通すことができます。僕らのx86再実装もscoreを参考にしつつ進めています。

scoreを参考にしてarch/score以下にどのようなファイルがあるか見てみましょう。

 ├ boot/  
 │    vmlinuxの作成に必要なMakefileなど  
 ├ configs/  
 │    アーキテクチャのデフォルトのmenuconfigなど  
 ├ include/    
 │    ├ asm  
 │    │   アーキテクチャ依存ヘッダファイル
 │    └ uapi  
 │         そのうち、ユーザー空間にエクスポートされるもの  
 ├ kernel/  
 │   ├ *.c      
 │   │   アーキテクチャ依存の関数などを記述します  
 │   └ vmlinux.ld.S  
 │        カーネルのリンカスクリプトを記述します  
 ├ lib/  
 │    文字列関数やビット演算など補助ライブラリ  
 └ mm/  
       アーキテクチャ依存関数のうち、メモリ管理周り  

x86などの巨大なアーキテクチャでない限り、だいたいこれと同じ構成になります。例えばopenriscなんかは全く同じディレクトリ構成です。(もっともscoreがopenriscを参考にしたのかもしれませんが。)
scoreの具体的なソースコードは、Linux/arch/score/ - Linux Cross Reference - Free Electronsなどでご覧ください。kernelやmmを覗くと、移植に必要なファイル数は思ったよりも少ないかも?って感想を抱くかもしれません。

ご覧の通り、ビルドのために各種Makefileやconfigファイルが必要です。先ほど書いた通り、各アーキテクチャの実装も参考にするのでが、大本の参考資料としてkernel.orgのDocumentationにあるKbuildのマニュアルは必読です。これらはおそらくオンラインで手に入るLinuxMakefileやconfigの最も詳細な解説になります。arch開発者向けの資料も用意されています。

リンカスクリプトであるvmlinux.ld.Sも書く必要があります。リンカスクリプトは資料がほとんどないため書くのに苦労すると思います。基本的にはGNU ldのあまりまとまりのよろしくないマニュアルを読んで理解するしかありません。VMAとLMAがきちんと設定できているか気を付けながら書きましょう。具体的なカーネルリンカスクリプトの例の一部がinclude/asm-generic/vmlinux.lds.hの冒頭のコメントにあって参考になります。また、後に紹介する僕らのアーキテクチャstub nullpo-head/Linux-Architecture-Stub · GitHub がこれをもとに完全なvmlinux.ld.Sを書いていますので参考になるかと思います。

スタブを作る

ビルドシステムに必要なファイルを準備できたら、次はリンクを成功させるためにスタブコードを用意しなければなりません。

一番最初に紹介した資料Porting Linuxのように、基本的には「他のアーキテクチャをコピペしてはいけない」です。ので、Makefileやvmlinux.ld.Sだけ他のアーキテクチャを参考に書き、ひとまずビルドが走るようになったらエラーメッセージを頼りにスタブを増やしていく・・・というのが理想の流れとされているようです。Porting Linux to a new processor architecture, part 1: The basics [LWN.net]でも、エラーメッセージを頼りに何の関数が必要か推測すると書いてあります。これは、すでにあるアーキテクチャをコピーすると不要なものまで実装してしまいやすいからだとThe right way...では説明されています。

とはいえこの作業は大変ですし、最低限のスタブはわりとHW非依存になるはずなのに各自で書くことに若干不毛さも感じてしまいます。これを解消するためにThe right way...では、「ブートまでできるexampleアーキテクチャを用意してそこからブランチできるようにするぜ!」と宣言していて実装も進んでいたそうなんですが、コメント欄いわく「gitインフラ移行のゴタゴタで消えちゃったわ」だそうです。合掌。

さて、前言をひっくり返すようですが、僕らはx86最小実装ではあえてscoreのコピーから始め、最低限の定義以外をガリガリ削ってスタブを作ることにしました。繰り返すように、既存のアーキテクチャをコピーして始めることのデメリットはとにもかくにも無駄な機能もよく分からないままコピーしてしまうことです。しかし、scoreはとても小さい実装なのですべての行に目を通すことができ、なおかつPorting Linuxで紹介されているようにとてもきれいで読みやすいです。なのでx86やarmなどの巨大なアーキテクチャと違い、目を通さないまま丸々コピペする心配があまりありません。この方法で始めると最初からビルドが通るので、作業中に誤りを埋め込んでもすぐに発見できてとても楽になりました。

先ほどのブートまでできるexampleアークテクチャには及びませんが、x86再実装とは別にscoreをもとにしたstubアーキテクチャ

github.com

にて作成中です。もし新しく移植を始める際にはお役に立つかもしれません。まだまだscore依存のコードが(特にヘッダファイルに)残っていますが、x86再実装の進行とともに洗練させていくつもりです。

make ARCH=stubs tinyconfig
make ARCH=stubs -j4

にてビルド可能です。出来上がるELFはx86用になっています。

ところでツールチェインの節で紹介したようにこれはclangでもビルド可能です。その場合、

make ARCH=stubs CC="clang -no-integrated-as"

となります。-no-integrated-asって何やねんというとclangの統合インラインアセンブリによる最適化を無効にするオプションです。clangのバグと機能不足によるもので、現時点ではこれを付けるのがLinuxビルドのデファクトになっています。

中身を書く

スタブができたら後はひたすら中身を実際に実装していく作業になります。スタブを理解してほかのアーキテクチャを流し読みしていると、だいたいやるべきことが分かってきます。流れとしてはだいたい以下のようになります。

  1. head.Sにブートシークエンスを書いてstart_kernelまで走らせる

  2. メモリ初期化や割り込み初期化など初期化処理を書いてstart_kernelを完遂させる

  3. 割り込みハンドラやswitch_toなど、カーネルの動作に必要なarch依存部を書いてinitを起動させる

なお、これらはkernel/*.cだけを埋めていけばいいというわけではなく、動作に必要なヘッダファイルも並行して埋めていくことになります。例えばメモリのレイアウトに関する定数など。またLinuxはヘッダファイルにも.cファイル並みに関数の実装を書くので、それも書いていく必要があります。書かなければいけない主要な関数などは、

Porting Linux to a new processor architecture, part 2: The early code [LWN.net]

にまとまっているので雰囲気を知りたい方はぜひ参考にしてください。

x86再実装においては、僕らはまだまだ2の途中の段階です。1のブートシークエンスはmulti boot headerを書いてgrubqemuにハードウェアの初期化を任せ簡潔に済ませました。

実際にコードを書いていく作業は当たり前なんですが大変です。数としては書くべき.cは意外と多くないのですが、カーネルの理解が必要とされるので、カーネルの勉強を並行しての作業だとあまり速くは書けません。また、include/以下の.hの方は多いと100個ほど書かなければならないそうです。もっとも現在はasm-genericをincludeするだけで大半のものが済ませてしまいます。感謝感謝。

自分もまだまだ作業中なので、この部分に関して簡潔にまとめることは残念ながらまだまだできません。実際に作業をしての雑感としては、コードを書いている時間よりもカーネルのコアのコードや資料を読んでいる時間の方が何十倍もあるね!という感じです。(カーネルnewbieなので当然ですね。)新年ではカーネルの移植を完了しての雑感を書きたいところです。

まとめ

Linuxを新しいCPUへ移植する作業は、ツールチェインを移植したのち、archディレクトリ以下をほかのアーキテクチャを参考にしつつ実装していく作業でした。最近はPorting Linux to a new processor architecture, part 1: The basics [LWN.net]などのいい感じの資料も出てきて作業がしやすくなっています。カーネルの勉強にももしかしたらちょうどいいかもしれません[要出典]

Linuxを移植したいけど余った新しいCPUがない?そんな場合は学科の後輩たちが書いている CPU実験 Advent Calendar 2015 - Adventar にいい感じのCPUの作り方の記事があるかもしれませんし、ないかもしれません。(雑な宣伝)

ところで文中何度も出てきたx86のミニマムな再実装ですが、レポジトリこちらになります。ただし本格的な作業がまだなので、今はどなたかの参考になる段階にはないと思います。。後々の成長を見守ってくださいませ。

それでは皆様、メリークリスマス! & よいお年を!

*1:移植が終わったらこういう資料を作ろうと思っていた僕たちからすると少し複雑

ビルドしたLinuxカーネルをブートできる最低限の環境を用意する(with Busybox & qemu)

最近Linuxカーネル周りを触り始めています。Linuxカーネル周りを触り始めたといってもそもそもLinux歴が浅く、menuconfigを本格的にいじりながらビルドするのは今回が初めてだったりしてブートするだけでも大変でした。そこらへんをまとめます。

カスタムビルドしたLinuxカーネルをブートできる環境を簡単に用意する

今更何だという感じですが、Linuxとは正確にはカーネルの部分だけのことを指していて、ユーザーランドを含みません。巷でよく言われるアレですね。(もしあなたが十分に信心深いなら、Linuxシステム全体をLIGNUXと呼んでもよいです。)
なのでkernel.orgから引っ張ってきたカーネルソースをビルドしても、すぐには起動して試すことができません。ubuntuなどのディストリのカーネルを入れ替える形でブートさせてもいいのですが、 カーネルソース自体をいじっていてテストをしたいときなど、あまりデカいディストリを振り回したくない状況もあるでしょう。本記事ではBusyBoxで簡単なユーザーランドを作ってqemu上でカーネルをブートし、カーネルの動作を確認できるように基本的なコマンドを使える環境を構築する方法を紹介します。

注意

この記事は、特にARMをターゲットとしていないことと一般的なカーネルビルドの方法もまとめて書いてあることを除いては Busybox for ARM on QEMU | Freedom Embedded に書いてあること以上のことは何も書いていません。BusyBoxを用いてファイルシステムを構築する方法を手早く知りたければこちらを参照することをオススメします。

カーネルをビルドする

まず一般的なカーネルのビルド方法をメモ書きしておきます。

とにもかくにもカーネルのソースが必要です。kernel.orgからほしいバージョンのソースを入手しましょう。適当にアーカイブを展開し、展開したディレクトリに移動すれば

$ make menuconfig

を叩くことによってカーネルの各種オプションを設定できます。なおこの記事ではinitramfsを使ってブートするので、General Optionsの中のinitramfsをサポートするオプションは無効化しないでください。
ちなみにこれは、GUIバージョンもあり、

$ make xconfig

および

$ make gconfig

を使うことができます。それぞれKDEGNOMEを使うGUIです。
また、色々いじった設定を元に戻したければ、

$ make defconfig

すればオーケーです。

次にやることは本番のビルドです。

$ make -j4

とすればオーケー。普通ですね。もちろん-j4の部分のスレッド数は適宜あなたのコア数などに合わせて置き換えてください。だいたい10分くらいビルドに時間がかかるように思います。

さて、ubuntuなどのディストリのカーネルを入れ替える場合は普通この後make installとかするわけですが、今回はこのカスタムカーネルをとりあえずブートしてテストしたいだけなのでやりません。ユーザーランドをBusyBoxで作っていきます。

BusyBoxでユーザーランドを作る

次にBusyBoxを使ってinitramfsを作っていきます。なお、今回qemu上で動かすLinuxは、RAMのみのディスクなし、ユーザーランドもBusyBoxのコマンド群のみという構成になります。またアーキテクチャは、特に指定していない場合ホストのマシンと一致されます。

カーネルの時と同じく、まずBusyBoxのソースを用意しましょう。適当に展開した後は、そのディレクトリにて

$ make menuconfig

を叩くと、BusyBoxの設定のコンフィグ画面が表示されるので、ライブラリを静的にリンクするようにしてください。
その後、

$ make install

を実行してください。make installではありますが、ホスト上のマシンに何かがインストールされるわけではなく、単に_installというディレクトリができるだけです。sudoはつけないようにしましょう。
次に、起動後ルートファイルシステムとなることになるファイルを作ります。

$ cd _install
$ find . | cpio -o --format=newc > ../rootfs.img

もし容量を小さくしたい場合は、さらに先ほどの参考サイトに従って圧縮をかけてもいいです。

qemuカーネルをブートする

qemuは-kernelというオプションがあり、カーネルのelfバイナリを読んで直接メモリ上に配置してくれます。これによって特にブートローダを用意せずともカーネルをブートすることができます。さらにinitrdオプションを使って先ほど作ったrootfs.imgを渡します。
以下のコマンド

$ qemu-system-x86_64 -kernel bzImage -initrd rootfs.img -append "root=/dev/ram rdinit=/bin/sh"

を走らせることで、BusyBoxによるシェルが起動します。あとは普通にlsやらcatやらが使用できると思います。お疲れ様でした。

オプション:/procや/sysを機能させる

参考サイトにもあるフォローアップをこの記事でも書いておきます。
上までの手順では、/procや/sysが必要になる機能、たとえばpsコマンドが動きません。なのでこれらを機能させたければきちんとマウントする必要があります。

# mkdir /proc
# mount -t proc none /proc
# mkdir /sys
# mount -t sysfs none /sys
# mdev -s

これらを毎回行いたければ、proc, sysディレクトリおよびetc/init.d/rcSスクリプトをrootfs.imgの中に追加し、qemuのappendに書くブートパラメータのrdinitを/bin/shではなく/sbin/initに変更しましょう。
rcSの内容はだいたい以下のようになります。

#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s

ざーっと要点だけ書いてしまっていますので、詳しくは元ネタのBusybox for ARM on QEMU | Freedom Embeddedの方を参照してください。

CPU実験で自作CPUにUNIXライクOS (xv6) を移植した話

今年のCPU実験では、有志からなる我らがX班が、おそらくCPU実験史上初である自作CPUへのOS (xv6) 移植に成功しました。コア係とコンパイラ係の面々がそれぞれまとめ記事を書いていたので、OS係から見たOS移植のまとめも書こうかなと思います。こんなことしてましたってことが伝わればいいなと思います。

この記事を読む後輩やらなんやらがいたら、ぜひ僕らがやったようなことはさっさとクリアしちゃって、さらにさらに面白いことをする踏み台にしていってほしいですね。

どなたが読んでもある程度概要が伝わるよう、まずCPU実験とは何かということをさらっと書いた後、実際にxv6を移植するにあたってやったことをまとめたいと思います。

CPU実験とは

CPU実験は僕の学科(理学部情報科学科)で3年冬に行われる、半年間にわたる学科名物演習です。

最初の週で4~5人程度の班に分けられた後、それぞれの班でオリジナルのCPUアーキテクチャを考案しそれをFPGA上に実装、加えてそのCPU用のocamlサブセットコンパイラを作り、作ったCPU上で課題のレイトレプログラムを走らせる、というものです。当然この命令セットが動く仮想マシンなんてものはこの世に存在しないので、自分たちの手でシミュレータを作る必要があります。またコンパイラの下で動くアセンブラも必要ですし、課題のプログラムがレイトレなのでCPUにはFPUも載せる必要があります。まぁこれがなかなか大変な演習で、過去には失踪者が出た例もあるとかないとか・・・。

ちなみにこのCPU、VHDLというハードウェア記述言語で作らされるのですが、大学でVHDLの書き方を習ったことは1ミリもありません。心温まるお話ですね。*1

自分たちで作ったCPUでOSを動かそう

さて、CPU実験の概要はそんな感じです。お気づきの方もいるかと思いますが、上の説明にはOSの話なんて全く出てきません。ちょっと説明を加えます。

実験の流れとして、ふつうはまずどんなに遅くてもいいから課題のプログラムが確実に動くCPUを一つ完成させます。これはよく1stアーキテクチャとか呼ばれます。で、実際に動くCPUを一つ作りさえすれば単位が確定するので、早めに完成した班はあとは割と自由な時間となるのです。ここから高速化を目指すのが正統派の班の行動なんですが、中にはゲームを作ったりスピーカーで音楽を奏で始めたりとお遊びに力を入れる班もでてきます。僕がコア係として所属していた6班は余興大好きの方の班で、CPU実験開始当初からOSを動かそうという話になっていました。この話に他班も興味を示した結果、晴れて8人くらいからなる合同班、X班が結成され、「自分たちのCPUでOSを動かすぞー!」という運びになったわけです。

xv6

移植するOSは、MITが教育用に作成した、Unix v6インスパイアなシンプルなOSであるxv6にしました。xv6はUnix v6と違ってANSI Cで書かれていて、x86上で動作します。教育用なだけあって、ユーザーランド周りやプロセス周りが少し貧弱ですが、シンプルかつUnixライクなOSとして割と十分な機能を持っています。詳しい情報はwikipedia公式サイトででも。

大変!

xv6移植する移植すると言っても、なんでもかんでもゼロから作ろうってわけですからソフトウェア側だけでも障害がいくつもあります。

  1. コンパイラどうすんねん
    CPU実験では普通mlコンパイラを作ります。当然Cなんてコンパイルできません。

  2. リンカも割とリッチなやつが必要っぽい
    xv6ではリンカスクリプトを活用してバイナリファイルをくっつけたりディスクイメージをくっつけたりします。CPU実験で作ったツールチェインにはリンカなんて高級なものはなく、だいたいアセンブラ複数ファイルをぶん投げたら一つのバイナリを吐くような作りになってしまっています。

  3. デバッグ用のシミュレーターどうすんねん
    CPU実験で作ったシミュレータはありますが、1命令1命令ずつ実行するシンプルなもので、割り込みとかありませんし仮想アドレス変換なんかもありません。

  4. というかそもそもCPUの機能には何がいるねん
    リングプロテクション?仮想アドレス?割り込み?そもそも何がいるのか不明瞭です。ここが決まらないと2のシミュレータも作れません。

  5. ハードウェア資源は足りるの?
    僕らのFPGA基盤に乗っているもので使えるメモリはだいたい4MBのSRAMだけ*2だし、通信手段はシリアルポートだけ*3です。SDカードやIDEディスクをくっつけてる余裕はなさそう。

  6. xv6、x86にべったり依存して書かれすぎ
    ブートの最初の方で4MBページ拡張使うわ、char 1byte, int 4byteであることを前提にハードコーディングするわ、スタックいじくりまくったトランポリンするわで移植性皆無です。まあxv6という名前がx86Unix "v6"から来てそうだし仕方ない。

まあこんな感じで不安点はいくらでもあったんですがX班OS移植プロジェクトは12月くらいにスタートしました。

ここからはだいたい時系列順でやったことを書いていこうかと思うのですが、かなり長いので先に動いてるOSの話を読みたい!みたいな方は3月の話以降を。

11月終わり~12月初頭

まず1個目の「コンパイラどうすんねん」が解決します。なんと「C89コンパイラフルスクラッチ」です。正直これでいくと思ってませんでした。インド人もびっくり。最初はid:wasabizgccllvmでもやるかーって話してた記憶があるんですが、うどんくん(id:kw_udon)が突然「Cコンパイラ書いてきた」と言って簡単なパーサとエミッタを積んだコンパイラを持ってきました。楽しそうだったので最速完動した3班由来のメンバーであるwasabizと@b-inaryが加わって、この3人がコンパイラ係としてフルスクラッチコンパイラを書き始めます。これが後のuccとなります。ucc開発についてはうどんくんの下の記事が詳しいです。

kw-udon.hatenablog.com

5個目の「ハードウェア資源は足りるの?」も解決します。このころはまだOSが決まっていなかったのですが、xv6が標準でシリアルで外部と通信し、しかもメモリは1MBも食わない、memfsも簡単に使えるのでディスクもいらないなどなど、我らがFPGA基盤にぴったりだということが判明し、xv6で行くことになります。コードがコンパクトなのもとてもgood。

12月中旬

OS係が動き始めます。また、12月8日に僕が作ったCPU実験本筋のCPUとシミュレーションのレイトレ結果の数ビットのdiffがようやくなくなり、6班(僕らの班)が完動します。原因は、ISE(VHDLから回路を合成してくれるすごいやつだよ)が吐くFPUの回路の挙動が、実際に書いたVHDLの挙動と食い違っていたせいでした。すごいやつって書いたけどあいつ絶対許さない。VHDL文のwhile文は合成できても使っちゃダメですよ絶対。班公式の仕事としての完動は3番目だったように思います。

ここらで6班メンバーがX班のOS係やらMMU係やらになります。OS係のメンバーが最終的なものと同じ、僕(@nullpo_head)、warelle@mhの3人に固まります。

12月終わり~1月中旬

4個目の大変ポイント、「というかそもそもCPUの機能には何がいるねん」が解決し始めます。

OS班のメンバーが固まったので、週1で輪読でxv6のソースコードリーディングを始めます。xv6にはMIT謹製の教科書があるんですが、結局これはあんまり読みませんでした。今からxv6を読みたいという人、OSの基礎的な概念を理解しているなら特に読む必要はなさそうです。このころ同時に僕はxv6をMIPSに移植し始めました。MIPS移植がなさそうだったので(ARMはある)。一週間くらいでスケジューラが動き始めるくらいまで移植が完了します。(外部周辺機器の割り込み周りの制御とユーザープログラムの起動はまだうまくいかない)ここで書き換えのためにMIPSについて、xv6の動作を理解するためにx86についてそれぞれ調べまくったので、割り込み周りの概念とMMUの概念を理解します。CPUに必要なものが見えてきます。

自作アーキテクチャシミュレータ上のxv6でも、色々コメントアウトして頑張った結果、ブートシークェンスの最初の文字

xv6...
cpu0: starting...

が表示されます。つまり、このころにはもうuccがxv6の大部分をコンパイルできるほど成長しています。uccすごい。

ここで大学のテストが挟まって、2月くらいまで一旦作業が鈍化します。

2月

テストが終わりました。OS係に本腰が入ります。全体のタスクがだいたい把握できたので4週間ほどでOS移植が完了する線表を引きました。

1日にはMIPS移植もPICあたりの初期化が完成し(マジ大変だった)、割り込みハンドラのひとまずの書き換えも完了してユーザープログラムが起動する直前まで移植されます。ここでの経験を基に自作CPUの割り込みの仕様と仮想アドレス変換の仕様を決めました。「というかそもそもCPUの機能には何がいるねん」が解決します。xv6は割り込みと仮想アドレス変換さえあれば動く!!周辺機器はタイマーとシリアルしかないので大がかりな割り込みコントローラはいらないし、デマンドページングがないのでリングプロテクションもいりません! なお、仮想アドレス変換はx86のページング部分と同じ方式にしました。一見CPUの実装が大変になるように見えますが、速さを犠牲にしてTLBが毎回ミスするような挙動にすれば実装が簡単なのではという話になっていました。(まあ最終的には優秀なコアができあがったので、TLBにあたるものもきちんと乗りました。) ちなみにOS移植が本格的に動き始めたので、MIPS移植は以降手がつけられなくなります。残念。

あとは怒涛の進捗が始まるので週区切りで記します。。。。

1週目

コメントアウトだらけのなんちゃってブートシークエンスではなく、mhにより初期化処理がきちんと移植され始めます。warelleがx86アセンブリを自作アーキテクチャのものに書き換えます。僕は、策定した仕様を基にCPU実験用のシンプルなシミュレータに割り込みシミュレーション機能をつけ、仮想アドレス変換の対応も完全にしました。シミュレータにOSを動かすのに十分な機能が付きます。またMakefileを自作アーキテクチャ用のものに書き換えました。全体として色々と開発の下地が整っていきました。

2週目

僕は大変ポイントその2、「リンカも割とリッチなやつが必要っぽい」に対応します。アセンブラ作者のb-inary先生に.setディレクティブの追加と、ファイルのアセンブル時の先頭アドレスを変更できる機能の追加をお願いします。xv6では主にカーネルの終端アドレスであるend, バイナリイメージであるfs.imgとinitcodeの先頭アドレスやサイズを得るためにldのbinary blobsを使うのですが、追加してもらった.setディレクティブさえあれば、
1. まずend, _binary_initcode_startなどには0xdeadbeefなどの適当なダミー値を.setで与えてアセンブル、ひとまずカーネルのサイズを得る
2. そのカーネルのサイズからそれぞれのシンボルの値を計算、.setディレクティブで無理やり追加
3. 計算しなおしたその値でもう一度アセンブル
4. できあがったカーネルにfs.imgやinitcodeをcatでくっつける
5. こうしてできあがったカーネルのヘッダを再計算してごにょごにょ書き換え、完成
という手順で同等のことを達成、原始的なリンカっぽいことができるようになります。ステキ。rubyスクリプトMakefileでこれらをやってやります。 先頭アドレスの変更は、もちろんカーネルのbaseアドレスやユーザープログラムのベースアドレスをそれぞれ0x80000000や0x0に返るためのものです。
warelleは割り込み周りを書き換えます。割り込み周りは理解が難しい、流れを把握するのが難しい、デバッグが難しいで難しい揃いです。僕がMIPSを移植したときにはgdbという神器があるのでまだ楽でしたが、独自シミュレータにはデバッグ機能など皆無だったのでデバッグがかなり難しかったのではないかと思います。(このときだったかどうかちょっと記憶が怪しいのですが)デバッグのしづらさに耐えかねたのかwarelleはシミュレータにディスアセンブラデバッグダンプ機能を付けてきました。これを皮切りにシミュレータのデバッグ機能はOSチームによりどんどん高機能化され、最終的には下図みたいな感じに成長します。

f:id:nullpo_head:20150324100129p:plain

このころmhはファイルシステム担当として、ファイルシステム周りを教科書を読みつつ理解していました。

3週目~

山あり谷ありで書き換えが進んだxv6、なんだかんだ言って動きません。特にuccの、charもintもともに32bitであるという仕様が響きました。実はCの仕様ではsizeof(char) <= sizeof(int)なことしか要求されてないので、これは仕様的には合法ですし僕らのアーキテクチャ上では実際問題ありませんでした。しかしxv6はx86を前提として書かれているので、sizeof(int) == 4なことを前提にポインタの値に定数をガンガン加算したりしてくるので、色々と不整合が起きてしまいます。これが生むバグが分かりづらい上に量も多かったので、結局uccの方にcharを8bitにしてくれるようお願いすることになります。このchar 32bit問題をuccチームに任せた後は、僕は最初のentry段階のページ初期化を書いたり割り込み周りがきちんと動くよう修正トライ&エラーを繰り返したりしました。要は大変ポイントその6、「xv6、x86にべったり依存して書かれすぎ」を地道につぶす作業です。

27,28日

slackを見返すとやたらこの日に進捗が生まれてます。多分悔いを残して2/29日に突入しないためだと思います。ucc班が爆速でchar 8bit対応を終わらせてくれた後なんやかんやで頑張り、ついに、初めてのユーザープログラムinitが起動します。そしてそのあと怒涛の進捗をだし、ついにシェルまで起動します。その後、MIPS移植ではたどり着かなったユーザープロセス周りの移植をどんどん進めました。
再現しづらいバグやら割り込み仕様の不備やらが発覚、潰しは発生、潰しは発生しますが、なんやかんやでなんとか乗り越えます。なんやかんやはなんやかんやです。

3月

1日、そしてxv6の移植が完了します。シミュレータ上でxv6が動きました・・・!

f:id:nullpo_head:20150324091208p:plain

線表上では3/4が完成目標だったので、結構余裕ができました。ちなみに最終発表の日数は3/17です。

余興かくあるべし

ここからはもともとお遊びだったOS移植のお遊びがさらに加速します。

まずmhの手によって4時間くらいでミニcursesが作られ、シミュレータ上でslが走ります。(遊びとなると進捗ってめっちゃ速くでるんだなあ・・・)

f:id:nullpo_head:20150324091346p:plain

warelleはなんだかマインスイーパーがしたくなりました。

f:id:nullpo_head:20150324091509p:plain

また、ここらへんで僕の趣味でディレクトリ構造をきれいにして、ヘッダファイル類をモダンなunixの構造っぽく変更、またuccチーム 謹製のlibcを移植しました。たとえば今まで

#include "types.h"
#include "stat.h"
#include "user.h"

char buf[512];

void
cat(int fd)
{
  int n;

  while((n = read(fd, buf, sizeof(buf))) > 0)
    write(1, buf, n);
  if(n < 0){
    printf(1, "cat: read error\n");
    exit();
  }
}

みたいな感じで独自仕様感がたっぷりだったcatは、

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char buf[512];

void
cat(int fd)
{
  int n;

  while((n = read(fd, buf, sizeof(buf))) > 0)
  write(1, buf, n);
  if(n < 0){
    printf("cat: read error\n");
    exit(1);
  }
}

こうなりました。しかもwasabizの手によりX班コアGAIAも完成*4、シミュレータよりはるかに速く動くので遊びやすいし開発しやすい。満を持して、今回屈指の完成度を誇る2048が作られます。

f:id:nullpo_head:20150324091905p:plain

この2048、本当に完成度が高く、コア係のwasabizは実機上でずっとこの2048で遊んでました。
ちなみに2048では非ラインバッファリングな入力が使われていますが、xv6にはもともとこの機能はなく、read, writeに加えてioctlをdevswのアクションとして追加し、ICANONやechoを制御するtermios関連の機能を新たに追加しました。なのでこんなに完成度の高い2048が遊べるxv6はGAIA上のものだけです。
(なお、V6インスパイアなxv6としてはgtty, sttyシステムコールを追加するほうがそれっぽいとは思うんですが、xv6にはttyの概念がないのでこれを追加するのは変だなと思ったのと、ioctlがUnix V7からの登場と意外と古株だったのでioctlを採用しました)

さて、少しかっこいいお遊びとして、xv6-gaiaには小さなアセンブリが載っています。うどんくん製です。また、warelleがまさかの1日で作ってきたミニviも載っています。この二つを使うとできることが、

f:id:nullpo_head:20150324092118p:plain f:id:nullpo_head:20150324092125p:plain

こんな感じのFPGA上での動的なプログラミングです。CPU実験としてはかなりレベルが高い余興なんじゃないでしょうか。

最後の余興

CPU実験のもともとのお題は、「自作CPU上でレイトレを動かせ」でした。せっかくOSが動いたんですから、やることは決まっています。「自作CPU上"のOS上"でレイトレ」です。うどんくんとb-inaryさんが課題のmlプログラム、min-rtをCに移植してくれました。完成したのは最終発表当日ギリギリです。
が、ここで予期はしていたが目を背けていた問題が発生。完成したバイナリファイルがでかすぎ問題です。実はxv6のファイルシステム上では80kbくらいを越えるファイルが作れないのです。
まあでも予期はしていただけに解決策は用意していました。この完成したmin-rtをconsoleのようなデバイスファイルとして作ることです。consoleデバイスがreadアクションでユーザー入力を返すように、デバイスとして実装したmin-rtのreadアクションで_binary_min_rt_startから読み込んだ値を返せば、アドホックな分岐などのあまりトリッキーなことをせずに綺麗にリンクできます。ちょっとバグも埋め込んだりはしましたが、なんとか最終発表の1時間前には完成しました。

f:id:nullpo_head:20150324092158j:plain

多分どの代でも1回は冗談で言っていたであろう、「OSを作ってそのうえでレイトレ完動」が実現してしまいました。。
次はなんだろう、多分どの代でも一回は出るであろう冗談は「raytraceという1命令だけ作ってハードウェアレイトレする」ですかね。。割と対極にあるしCPUなんて作り飽きたぜ!って後輩がいれば挑戦してみるのはいいかもしれませんね。

書き残し、およびもっと技術的なことについて

GAIA版xv6には、上では書ききれてない変更がまだたくさんあります。たとえばb-inaryさんによってシェルのreadlineが強くなってたり、僕もpwdコマンド追加してたりmhによってhaltシステムコールが増えてたり。ともかくユーザーランドは割と魔改造されてるので気になる方はソースを直接見ていただければと思います。
そして上では割と軽いノリで「だいたい何をしたか」を記述するのに注力したので、OS移植の詳細は割と省いています。書ききれていない難しい箇所 or 興味深い箇所がまだまだたくさんあったりします。*5 GAIAやMIPSカーネル予約レジスタのk0, k1レジスタが必要な理由とか、興味深いことやハマりどころがまだいくつかあるので、いつかまとめられたらなーと思います。特にMIPS移植の際のMIPSに関する情報、ノウハウについてはどこかにまとめる必要性を感じています。。

感想

FPGA上へのOS移植は、やはり楽しかったです。OSの仕組みとx86MIPSについてかなり勉強になりました。CPU実験本筋でCPUも作ったしアセンブラも作ったしX班でOSも移植したしでかなり色々経験しました。 ただ振り返ってみればCPU実験にしてはこじんまりとしたことしかしなかったなという反省もあります。xv6移植に関しては、(もちろん簡単ではないことなのだけど)○○くらいのタスク量でやれそうだなという予想で始まって実際にその通りに達成して、「自分の想定内で想定通りの働きをしただけ」、という少し寂しい感想がないでもないです。実際作った線表から2日以上ずれたことなかったし。ここまで大きくなるのか!と驚かされたuccや、CPU実験であるにも関わらず割り込みもMMUも実装したGAIAコアのような、「本当にできるのか?」という感じの挑戦をしたかったかな、と少し思います。Linuxに初めから、とは言わずも、ucLinuxくらいには挑戦していればよかったかもしれない。
もっともX班の活動はこれで終わりではなく、今はうどんくんが「OS移植班全体の野望」という所のLinuxを動かすための算段を、wasabizと考えています。こっちは文句なしで難しいし実現できるか正直わからないので、頑張りたいなと思っている次第であります。
あと全然違う話ですがMIPS移植完成させねば。昨日久しぶりにMIPS版xv6を触り、TLB周りの処理を修正してinitcodeまで起動させました。初ユーザープログラムです。追試やら課題やらを回避しつつ4月初頭には完成させたいですね。

...

以上でCPU実験まとめ終わりです。後輩の方、興味を持った方、ぜひぜひCPUを作ったりOSを移植したりしてみてくださいませー

最後にX班のメンバーをまとめておきます。

...

*1:僕らの学科はほかにも心温まる話が溢れている。たとえば1回目の講義で緩くHaskellに入門したと思ったら次の週には初めて名前を聞くモナドを駆使した超ヘビーな課題を解かされ、3回目にはつい先日入門したはずのHaskellで言語処理系を書かされる

*2:本当は数百MBのDRAMがついてるのだが動かした人はいない。DRAM遅いし。

*3:USBもあるが制御が大変になる

*4:詳細がwasabiz.hatenablog.comにあります。

*5:たとえば割り込みのtrapasm.Sの先頭。割り込みが発生してトラップフレームをスタックに積む際、必ずsp以降ではなくsp - 4以降から格納します。最初はspから積んでいたのですがそれではごく稀にバグが出てしまっていました。これはspより先を使わない規約にしているつもりだったのに、callの際にどうしても1命令幅分だけspより先の領域を使うことがあり、そこで割り込みが発生した時にその領域をつぶしてしまっていたからというものでした。他にもGAIAではブートステージでx86のように4MBページ拡張を使って初期ページディレクトリーを確保することができないため、現在のpcが0x0000hogeでも0x080000hogeでも動くように作ったPICのようなCコードで初期ページディレクトリーを作ったり、少し面白い実装になっています。

モバイル環境では外部アダプタを使わない方がいい|Surface Pro2 あるいはモバイルノートwindows8にオススメなHyper-Vネットワーク構成

このブログSurfaceのことばっか書いてるなと思い始めたnullpo_headです。今回の話題は「Surface Pro またはwindows8が入ったモバイルノートにオススメなHyper-Vのネットワーク構成」です。まぁほとんどタイトルとおんなじですね。人生なんてそんなもんです。

 

今回の話の核は

1. Hyper-Vのネットワークスイッチは、普通外部アダプタを作成してそれを仮想マシンにつなげるよう解説されるが、これは回線が安定しているサーバー機を前提とした構成なのでモバイル環境とめっちゃ相性が悪い。無線回線が切り替わるたびにアダプタが死んだりする。

2. なので内部ネットワークアダプタを作って、それをWindowsのICS機能でインターネットにつないでお手軽ネットワーク構成を作りましょう

 

という2点です。あ、1に関連する現象として、移動してWifi環境が切り替わるときにネットワークアダプタがしばしば死んでしまうというものがありますので、今回の記事は「SurfaceやノートPCでHyper-Vをオンにするとネットワークアダプタが時々死んでしまう現象を解決する」とも言えます。こっちの方がこの問題に悩まされている人々がググるときに役に立つかもしれません。(あと、hyper-vの外部アダプタを作っている状態だとau wi-fiがつながらないとかいう問題もあったらしいですね)

以下詳細です。

 

まずHyper-Vの通常推奨されるネットワーク構成がモバイル環境には向かないという話を書くんですが、そのために一応Hyper-Vのネットワークについてさらっとふれておきます。

Hyper-Vは名前の通りハイパーバイザ型に分類される仮想化環境で、OSよりも上位(レイヤ的には下位)で動くというのはよく聞く話ですね。

f:id:nullpo_head:20131126015143p:plain

VirtualBoxなどのホストOS型はあくまでOSの上で動くアプリケーションですが、ハイパーバイザ型は一味違い、OSよりもハードウェア側に位置することでゲストOSの高速化を図ります。

それでネットワークの構成も、VMware playerやVirtual BoxのようなホストOS型とは少し違ってきます。
f:id:nullpo_head:20131126015147p:plain

ホストOS型の時はただのアプリケーションだったので、普通にアプリケーションとしてインターネットと通信していればよかったのですが、Hyper-VはホストOSよりも偉いために、逆にホストOSやゲストOSにネットワークアダプタを割り当ててあげることになります。Hyper-VはホストOSから物理NICを奪い取り、ホストOSとゲストOSのそれぞれに仮想的なアダプタを作って、そこへ実際のNICへ通信を流してあげるのです。

これがHyper-Vにおける基本的なネットワーク構成です。

 

で、ここからが本題です。この基本的な構成が実はモバイルPCには向かないという話です。この構成を作るために必要な、「ホストOSから物理NICの権限を奪い取り、ホストOSのアダプタを仮想アダプタにすげかえる」という処理、それなりに大変なんですね。

この構成を実際にHyper-Vで作る操作を行うためには、Hyper-Vマネージャより仮想スイッチを作成し、「外部ネットワークアダプタ」を作成します。この手順はいたるところで解説されている一般的な手順です。

が、「このとき、物理ネットワークインターフェイスに以前割り当てられていたTCP/IPのパラメータは、一時的にネットワーク接続が停止したあと、仮想ネット ワークに複製される。しかし、どういうわけかパラメータの複製に失敗することがある。そうすると、仮想ネットワークはDHCPクライアントとなり、以前の IPアドレスは失われてしまう。この結果、ネットワークにDHCPサーバがいなければIPアドレスは割り当てられず、いっさいの通信ができなくなるのだ。 データセンターに配置した物理サーバをリモート管理している場合は、管理もできなくなる。」

 とAscii.jpさんの連載記事の中の一記事、

「遠隔操作時に失敗すると悲惨なことに? Hyper-Vのインストールはネットワークに注意しよう!」(http://ascii.jp/elem/000/000/553/553016/)

でも紹介されているように、操作時に時々ネットワークの接続を失うことがあります。運悪くこの状態になってしまうと、適当にアダプタのオンとオフを切り替えたりして復旧させねばなりません。

Hyper-Vはもともとサーバーにインストールされることが前提とされた製品ですから、セットアップ時に一回遭遇するくらいなら大した問題ではありません。しかし運が悪いことに、モバイル環境ではWifiなどネットワーク環境が切り替わるたびにこの不幸な状態に似た症状に陥ることがあるっぽいのです。

実際僕は大学を行き来しているうちに、2日に一回はネットワークアダプタが死んでました。。。(ずばりこのセットアップ時のものと同じ現象なのかどうかは寡聞にして知りませんが)

 

そこでこのある意味大がかりなネットワーク構成はすぱっとあきらめ、モバイル環境に適切な構成に切り替えましょう。

 

1. 内部ネットワークアダプタを作る

f:id:nullpo_head:20131126022834p:plain

Hyper-Vマネージャを起動し、右側メニューにある仮想スイッチマネージャから図のように内部スイッチを選択し、作成します。そしてお目当ての仮想マシンのネットワークアダプタにこれを割り当てておきましょう。

この内部ネットワークアダプタというものは、仮想マシンとホストOSの間だけをつなぐもので、インターネットにはつながりません。ですのでHyper-Vが物理マシンのNICを横取りする必要がなく、先ほど説明したような大掛かりな構成が作られません。作られた接続は、コントロールパネルのネットワーク接続一覧にひょこっと現れます。これを作っただけでは仮想マシンはホストOSとネットワーク的に接続されただけで、まだインターネットにはつながっていないのでこれをインターネットにつなげます。

 

2. ネットワーク接続の共有を使って、作成した内部ネットワークアダプタをインターネットにつなぐ

コントロールパネルの「コントロール パネル\ネットワークとインターネット\ネットワーク接続」を開くと、元からあるWi-Fiなどと並んで先ほど作成した内部ネットワークアダプタが表示されていると思います。

f:id:nullpo_head:20131126023954p:plain

あとは図のようにWi-Fiなど普段使っている回線のプロパティを表示し、共有タブから接続の共有をオンにしましょう。これで仮想マシンもインターネットにつながるようになると思います。オテガル!

 

この構成ならばホストOSのネットワーク構成が変わらないので、ハイパーバイザ型の仮想化でもライトに使うことができると思います。多分。ちょっとネットワークいじらなきゃなってときでも共有を解除するだけですべて元通りです。

ちなみにこれはSurfaceを例にしてるために有線LANアダプタがないんですが、普段から有線も無線も使うよ!って人はブリッジ接続などを作ればいいと思います。なんにせよネットワーク環境が変わるたびにアダプタが死なないよう祈る必要はなくなるのでいい感じなんじゃないでしょうか。また、仮想マシンを外部に公開したいときは、ポートの開放も設定から普通にできますので特に問題ないと思われます。

 

以上で今回の話は終わりです。モバイルノートPCでもHyper-Vをがんがん動かしましょう!!

 

そういえば:買ってまだ数か月のSurface Pro初代もメモリ8gb欲しいぞ~~~~~~~~~~(;´Д`)

 

 

参考文献:

Hyper-Vのネットワークを理解する -外部ネットワーク- | WindowsServer管理者への道

http://ebi.dyndns.biz/windowsadmin/2013/04/18/hyper-v%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B-%E5%A4%96%E9%83%A8%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF/

・ASCII.jp:Hyper-Vのインストールはネットワークに注意しよう! (1/2)|Windows Serverで学ぶサーバOS入門

http://ascii.jp/elem/000/000/553/553016/

Hyper-V - Wikipedia

http://ja.wikipedia.org/wiki/Hyper-V

Surface Proで(あるいはもしかするとwin8のモバイルノートPCでも)休止状態から復帰できなくなったことへの応急処置

ちょっと前から自分のSurface Pro(初代)が長時間スリープさせた後の復帰で、復帰前の状態を復元できずにただの再起動となってしまうことが起きてました。最初はちょくちょくだったのですがだんだんと頻度が上がっていき、最近はもう100%です。めっちゃ困ります。

結論から言うとこれはwindows8.1にアップデートしてから生じている現象(ログの日付によれば)のようで、多分winのバグです、そのうち治るんじゃないでしょうか。でも不便なまま過ごすわけにもいかないので、とりあえずの応急処置として

・コンパネの「コントロール パネル\ハードウェアとサウンド\電源オプション\システム設定」から行けるところで高速スタートアップを無効に設定する

ことでこの現象は抑えられます。副作用として、まぁ当たり前ですけど起動が前より若干遅く感じられます。あと休止状態からの復帰も若干遅くなります(デフォルトだとスリープのまま2時間たつと休止状態に移行しているようです)

早く改善されるといいですね。

 

以下問題の切り分けの経緯について

これの解決にあたってwindowsのエラーを扱う方法を少し身に着けたのでその経緯をば。

f:id:nullpo_head:20131124023015p:plainまずwindowsのログの見方です。winではログはイベントビューアというものから見れ、win8系ならwin+xキーでメニューを出せば、その中にイベントビューアというものがもうあるとおもいます。これをクリックすればさまざまなログが見れるイベントビューアなるものが起動します。GUIなので使い方に困ることは特にないでしょう。

そして、これのwindowsログの中に「システム」というものがあります。ここに今回欲しいログが吐かれるわけです。

 

 あとはこのエラーの中からめぼしいものを探せば

「システムは正常にシャットダウンする前に再起動しました。このエラーは、システムの応答の停止、クラッシュ、または予期しない電源の遮断により発生する可能性があります。」というログと、「Windows はエラー ステータス 0xC0000411 の休止状態から再開できませんでした。」というログが得られます。あとはこれを手がかりにしてググればなんとかなりますね。

まとめると、「イベントビューアでログを見て、ググる。以上」という感じです。いえい。

 

 

参考文献

1.Cannot resume from hibernate on Surface Pro 2

同じエラーで苦しむ人々。ただし僕と違ってSurface Pro2です。おのれMSめ、日本の初代発売から3ヵ月くらいで2を投下しおって。。。PowerCoverでたらくれ。。。

http://social.technet.microsoft.com/Forums/windows/en-US/bb19d1bb-2dbb-4748-8d85-e5be49689953/cannot-resume-from-hibernate-on-surface-pro-2?forum=w8itprogeneral

2.Windows 8 Pro (64bit) Failing to resume from Sleep (/Hibernate?) - Error ID 41 (Kernel-Power)

こちらはSuface Proではない一般のwindowsPCでの同様の現象の報告です。タイトルにあるいは~を入れたのはこれによります。Surface以外でも起きているかもしれませんので。今回の応急処置はここで見つけたもので、自分で試したところ有効でしたので紹介しました。

http://social.technet.microsoft.com/Forums/de-DE/4828857c-1f53-45bc-9d48-5ca8b34b416a/windows-8-pro-64bit-failing-to-resume-from-sleep-hibernate-error-id-41-kernelpower

 

Windows 8.1 or server 2012 R2 からLinuxクライアントもHyper-Vの動的メモリでhot add memoryを使えるようになった

 

windows8.1にアップデートしたら動的メモリが完璧に動くようになったぞ!!!!!!!

 

f:id:nullpo_head:20131018050751p:plain

まぁ言いたいことは記事タイトルの一行ですべて終わりなんですけど、あまりにも嬉しくて書きました。というかこの記事のためにこのブログを作った。

 

そこかしこで3.8くらいからLinuxHyper-Vの動的メモリに対応していて需要に合わせてメモリを増減できるみたいな記述がされてますが、実はそんなことはなくwindows8およびそれ以前までHyper-VLinuxクライアントの動的メモリ対応が不完全でした。使われていないメモリの縮小には対応していましたが、メモリ要求が増えた時に起動メモリ以上のメモリへ伸長することができなかったんです。しかし8.1に乗っているHyper-Vからはこれが可能になります。上スクショの「割り当てられたメモリ」が「起動メモリ」より多いことに注目。

なおこの機能を使うにはLinux側で適切なフラグが必要なので、カーネルのバージョンを確認しておきましょう。

 

僕は今、

「・Hyper-V上でarch linuxを動かし

・そのarch上ではGUIは一切動かさず待機

・windowsでCygwin/Xを使ってarch上のlxterminalとかを持ってくる

・その他双方向ファイル共有とかでwindowsとlinuxの融合を目指す」

という構成にしていまして、これは「確かに仮想マシンは動いてるけどGnomeみたいなデスクトップ環境も何も動いてないので100MBくらいしか余計なメモリを消費しない」という利点があります。あとはLinux上で動かすアプリケーション分だけのメモリが消費されるだけです。(またWindows8による快適なタッチ操作が行えます。SurfaceいいよSurface。)ところが、固定メモリ消費だと結局あらかじめメモリを割り当てておく必要があったのでこのメリットが半減だったんですよ。。だから今回のhot-add-memoryはめっちゃうれしいわけです。これで普段の生活がより快適になりそうです!!

 

 

参考文献

・New Hyper-V features in Windows Server 2012 R2

http://www.tudy.ro/2013/06/04/new-hyper-v-features-in-windows-server-2012-r2/

Windows 8 Hyper-Vで自宅鯖

http://engawa.2ch.net/test/read.cgi/mysv/1352818048/ (38 - 46)

ID一致

昔はTwitterIDとは違うID取得してたけどTwitterと統一した。

きらきら輝く入力を得たのち、その輝きをできるだけ保ったまま出力できるマッシーーンになれるよう再び頑張ります