Jailhouseハイパーバイザ実践

"Jailhouse"は辞書的には拘置所とか刑務所のことで，これをハイパーバイザの名前につけるとはちょっと驚きですが，これはこのハイパーバイザの特徴をとらえた名づけのようです．

JailhouseハイパーバイザはLinux上で動作するオープンソースのハイパーバイザであり，"Jailhouse partitioning hypervisor"とも言われ、有名なQEMU/KVMとは一味違うハイパーバイザです．
Jailhouseハイパーバイザはつい最近version 0.8が公開されたばかりで，version 1.0になるにはまだ少し時間がかかるようですが，ハイパーバイザとしてなかなか興味深く，期待の持てるソフトウェアだと思います．

私は，私がめざすアプリケーションにJailhouseが使えないかと、しばらく前から注目し，ソースコードを読み解くなど個人的に調査していました．今回，目標への第一歩として，比較的容易に入手できるハードウェアプラットフォーム（PC）で，ゲストOSとしてLinuxの動作を確認することができましたので，その情報（これまでの私の理解と知見）を共有したいと思います．


## Jailhouseとは
  Jailhouse partitioning hypervisor
  Jailhouseそのものについては Webページ(https://github.com/siemens/jailhouse) があるので，正確にはそちらをみてください．

### 特徴
-  オープンソースソフトウェア(OSS)である
-  ベアメタルアプリケーションやOSを複数並行して動かすことができる
   複数OSを動かすだけならLinuxには万能のQEMU/KVM がありますが，jailhouseには`partitioning` という形容詞がついており，他のハイパーバイザとの違いはこの点であることです．   
partitioningとは 「分割」ということで，CPUコア，メモリ，デバイスなどシステム資源をゲストOSに占有させます．
-  IntelとARMのマルチコアCPUに対応
    Intel系CPUではVT-xとVT-dが必須ですが，最近ではこれをサポートしたCPUも多く，私のような個人でやっている者は助かります．
-  コアと動作するVM（Jailhouseの用語ではセル）の対応はconfigurationで設定
   + セルにCPUコア（複数可）を割り付け，そこでゲストを動かす
   + たとえば，あるコアで動作するLinuxベースのシステムを，別のコアで動作する小さなベアメタルアプリケーションで監視するなどが考えられます．
   私が特に注目したいのは，準仮想化ハイパーバイザのため，カーネルの一部変更が必要であるものの，複数のLinuxをゲストとして並行して動作させられることです．これによりDSU（Dynamic Software Update）の実現の可能性がみえてきます．
   DSUは連続稼働の必要な組み込みシステムでは必要とされる機能であると思われます．

-  分割することにより，ハイパーバイザの構造と処理が簡単になり，余計なオーバヘッドが減らせる
   + ハイパーバイザのサイズが小さい（堅牢性につながる）
   + 高速（リアルタイム性）
-  セル間通信 IVSHMEM
    基本的には各セルは独立で干渉されないが，セル間通信を行う安全で最低限の機能が用意されている

###  構造
![jailhouse.png](https://qiita-image-store.s3.amazonaws.com/0/226219/a5c87125-bdb8-c6a1-c6f4-0e588ee8a0da.png)


Jailhouse用語

  - セル: Jailhouseによって隔離された空間
    - ルートセル：ホストLinuxが動作するセル
    - ノンルートセル：ゲストソフトウェア（ベアメタルアプリケーションやOS）が動作するセル
- inmate：セルで動作するソフトウェア

### 動作の簡単な説明
- Jailhouseは全体のリソース管理（CPUコア、メモリ、デバイス）を行います．

- Linuxが立ち上がった直後の状態ではJailhouseは動いていません．Jailhouseのenableコマンドにより，Jailhouseがactivateされ，上図のような状態になります．
この状態ではルートセルだけが存在し，ノンルートセルがないので，すべてのコアはルートセル用となります．ルートセルではホストLinuxが動作します．
- JailhouseはホストLinuxから要求されたJailhouse管理コマンドによりノンルートセルの管理を行います．管理コマンドとして、セルの作成/破壊、セルへのソフトウェアのロード、セルのスタートなどがあります．

- Jailhouse createコマンドにより，ノンルートセルが作成される
  ノンルートセルが作成されると，そのconfigurationで指定したコアはそのノンルートセル専用となり，ルートセルからはずされる．また，configurationで指定したリソースはそのセル専用になるため，たとえばデバイスがもしルートセルに属していれば，ルートセルから外されます．つまり，ルートセルからはアクセスできなくなります．
- セルの作成後，そのセルで動作させるソフトウェアのロードを行った後，起動コマンドでソフトウェアをスタートします．

### ハードウェア要件（サポートするCPU)
- マルチコアCPU（2コア以上）
- Intel系64ビットCPU
       VT-xとVT-d(IOMMU)は必須
          身近にあるIntel Core i5やCore i7が使用できる
- 64ビットAMD
        AMD-VとAMD IOMMU
      
- ARM
      仮想化拡張されたARMv7か、ARMv8

### ソフトウェア要件
-    x86-64 Linuxカーネル
-    ARM 詳細はJailhouseのWebページ参照

###  Jailhouseでできること
-  AMP的に複数ゲストを別々のコアで同時に動かす
    -  ベアメタルアプリケーション
    -  Linux（準仮想化なので一部コード変更が必要）
      
  私はこれを利用して，LinuxベースシステムのDSU(Dynamic Software Update)の実現をめざしています．その他にも，Linuxコアの動作を監視するとか，セキュリティ用途でのJailhouse利用が考えられます．
   
###  Jailhouseでできないこと
-  ハードウェアプラットフォームに存在しないデバイスはサポートしない．

## 私の動作環境
  QEMU/KVM上では比較的簡単にJailhouseを動かしてみることができるようですが，私はQEMU/KVMを使用せず，直接ターゲットプラットフォーム（PC）で動かしています.

### 2つの構成 
今回の構成は左図のようなものですが，私の目的の最終的な構成として右図の構成を考えています．
![構成.png](https://qiita-image-store.s3.amazonaws.com/0/226219/05eb1103-e919-15a3-9680-8247d1e4e42e.png)

将来的には

- ２つのLinux間でのDSU（Dynamic Software Update)を行うために，２つのノンルートセルLinux（各セルに1コア）
- オプション的にノンルートセルLinux監視用のセル（1コア）
- それ以外のコアはルートセルに使用（システム管理用）

今回の目標は

-  ひとつのノンルートセルLinux
-  残りのコアはルートセル
-  デバイスの分割
    -  ノンルートセルにアサインしたNICの動作確認(デバイスの分割）
    -  ノンルートLinuxにアサインしたシリアルコンソールの動作確認（当面、デバッグに必要なため）

#### 今回の構成
- セルはルートセルとノンルートセル（Linux）ひとつで，合計２セル
- デバイス
    - NICはノンルートセル(ゲストLinux)が使用
      (ルートセルや複数のセルで使用する場合はそれぞれにNICが必要)
    - シリアルターミナル
       - ttyS0: オンボードシリアル	  ルートセル：ハイパーバイザのデバッグ出力に使用
       - ttyS1: PCIeシリアルボードのポート0   － ゲストLinux用シリアルポート
       - ttyS2: PCIeシリアルボードのポート1  －（今後のもうひとつのLinux用シリアルポート）
   
#####    ハードウェアプラットフォーム(PC)
-    CPU： Intel Core i5 2400 (4コア)
-    メモリ：8GB
-    NIC(オンボード）：ゲスト用
-    HDD：ふつうにLinuxが動作する程度の容量さえあればよい(Linuxがビルドできる程度）
-    増設PCIeシリアルボード（デバッグコンソール用）
     現状のJailhouseには一部サポートしていない機能があるので，選定には注意が必要です．
     私の場合，4種類試した結果、StarTech社 PEX2S952（2ポート）を選定しました．
     また，LinuxのPCIe シリアルドライバは従来のINTxエミュレーション（Jailhouseは未サポート）しかサポートしていないようなので、その対応策として、
              ・Jailhouseに機能追加し，JailhouseでINTxエミュレーションをサポートする
              ・LinuxドライバでMSI(Message Signaled Interrupt)をサポートする
     各方法を検討しましたが、その結果、JailhouseにINTxエミュレーションを機能追加するのは容易ではないようなのであきらめ，今回は応急的にLinuxドライバでMSIをサポートするよう改造しました.

     ボード側のconfiguration(ジャンパースイッチなど）の変更
     デフォールトではボードは割り込みにINTxエミュレーションで使うように設定されている場合が多いようなので，MSIを使用するように設定できるボードを選定する必要があります．

     StarTech社 PEX2S952 の場合はボード上のジャンパースイッチを下図のように設定する必要がありました．

  ![jumper_setting.png](https://qiita-image-store.s3.amazonaws.com/0/226219/9cdd6bc9-121b-982b-6b1d-a22b1a4408bd.png)
   
#####    ソフトウェア
-  Jailhouse version 0.7
-  ホストLinux：Fedora 24 Workstation （Linux-4.9.20）
-  ゲストLinux：ホストLinuxと同一バージョンのLinuxカーネルにする必要はありませんが，Jailhouseは準仮想化ハイパーバイザなのでカーネルに修正が必要．
   どのような修正かはドキュメント化されていませんが，Jailhouse対応済カーネルがJailhouseのWebページからダウンロードできます（私が使用したのはlinux-4.11.0-rc4ベースであった）．
    これとオリジナルLinuxカーネルとの差分をとれば，どのような修正がされているかわかります．実際にdiffで調べてみると若干のソースコード変更と追加で済んでいるようでした．
    ・カーネルの修正
    ・Jailhouse用ソースコード追加
                   
-  ゲストLinuxのルートファイルシステムとしてinitrd使用（メモリベース）
    今回はLinuxの動作を確認できればよいので，`Buildroot`で作成した簡単なものを利用しました．

##  手順

###  準備作業
  
-    BIOS設定
      `VT-x` と`VT-d`をenableにする（もしそうなっていない場合）

-    Jailhouseのビルド
     JailhouseのWebページからJailhouseのソースコード一式をダウンロードし，ビルド

```shell
      make
      make install
      make firmware_install
```

-   configuration
    このハードウェアプラットフォームのconfigurationを作成し，これをベースにターゲット（目的セルのことをここではターゲットと呼ばせてもらう）のconfigurationを作成する．前者にはJailhouseのツールを使用できる（ただし，作成されたファイルの一部変更が必要）が，後者は全くの手作業であり，ハードルが高い．
      ここではその名前をsysconfigとする（ディレクトリはconfigs/) 

    - 必要とするボードを装着（今回の場合PCIeシリアルボード）する．もし，構成を変えた場合はその都度 以下の作業を行う必要がある．
    
    - configurationファイル(configs/sysconfig.c)を作成し、引き続き、作成されたセルのconfiguration(configs/sysconfig.cell)をチェックする．

```shell
        jailhouse config create configs/sysconfig.c
        jailhouse hardware check configs/sysconfig.cell
```

-   ターゲットconfiguration
    - ターゲット用メモリ配置の決定  
      ゲストLinuxの先頭物理メモリアドレス、サイズなど   

    ここで手作業でターゲット用configurationを作成する．ここでは そのファイル名をconfigs/linux-target.cとする．
    以下に示したファイルは今回のものです．
    - ヘッダ部分（cell):configsディレクトリの他のファイルをベースにできますが，`mem_regions`と `pci_devices`と `pci_caps`はターゲットに応じて変える必要がある
    - cpus：このセルが動作するCPUコア（ビットマップで表されている）
    - mem_regions[]：このセルが使用するメモリ領域
    - cache_region[]：sysconfig.cからコピー
    - pio_bitmap[]：このセルが使用するPIOアドレスは慎重に設定する必要がある．
      デバイスが使用するPIOアドレスは
        - `/proc/ioports`
        - `lspci`コマンドで得られる情報
     を参考に設定する
    - pci_devices[]：このセルが使用するPCIデバイス
    - pci_caps[]：このセルが使用するPCIデバイスのcapability情報
      sysconfig.cから，このセルで使用するPCIデバイスについてだけコピーする．`pci_devices`には，この相対indexが記述されるので，pci_devices[]の`cap_start`を変更する必要があります．

    makeを実行すると、バイナリのconfigurationファイル（configs/linux-target.cell)が生成される．

```file:configs/linux-target.c

#include <jailhouse/types.h>
#include <jailhouse/cell-config.h>

#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])

struct {
	struct jailhouse_cell_desc cell;
	__u64 cpus[1];
	struct jailhouse_memory mem_regions[8];    /* このセルが使用するメモリ領域数 */
	struct jailhouse_cache cache_regions[1];
	__u8 pio_bitmap[0x2000];
	struct jailhouse_pci_device pci_devices[4];   /* このセルが使用するPCIデバイス数 */
	struct jailhouse_pci_capability pci_caps[17];  /* PCIデバイスのcapability数 */
} __attribute__((packed)) config = {
	.cell = {
		.signature = JAILHOUSE_CELL_DESC_SIGNATURE,
		.revision = JAILHOUSE_CONFIG_REVISION,
		.name = "linux-target",			/* このセルの名前 */
		.flags = JAILHOUSE_CELL_PASSIVE_COMMREG,

		.cpu_set_size = sizeof(config.cpus),
		.num_memory_regions = ARRAY_SIZE(config.mem_regions),
		.num_cache_regions = ARRAY_SIZE(config.cache_regions),
		.num_irqchips = 0,
		.pio_bitmap_size = ARRAY_SIZE(config.pio_bitmap),
		.num_pci_devices = ARRAY_SIZE(config.pci_devices),
		.num_pci_caps = ARRAY_SIZE(config.pci_caps),
	},

	.cpus = {
		0x8,					/* このセルが動作するCPUコア */
	},

	.mem_regions = {				/* このセルが使用するメモリ領域 */
		/* low RAM */ {
			.phys_start = 0x40200000, 
			.virt_start = 0,
			.size = 0x00100000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA |
				JAILHOUSE_MEM_LOADABLE, 
		},
		/* communication region */ {
			.virt_start = 0x00100000,
			.size = 0x00001000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_COMM_REGION,
		},
		/* high RAM */ {
			.phys_start = 0x40300000,  
			.virt_start = 0x200000, 
			.size = 0x3b00000, 
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA |
				JAILHOUSE_MEM_LOADABLE,
		},
		/* IVSHMEM shared memory region */
		{
			.phys_start = 0x43e00000,
			.virt_start = 0x43e00000,
			.size = 0xff000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_ROOTSHARED,
		},
                /* MemRegion: e0000000-efffffff : 0000:00:02.0 VGA */
                {
                        .phys_start = 0xe0000000,
                        .virt_start = 0xe0000000,
                        .size = 0x10000000,
                        .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_ROOTSHARED,
                },
                /* MemRegion: f0001000-f0003fff : 0000:02:00.0 onboard NIC */
                {
                        .phys_start = 0xf0001000,
                        .virt_start = 0xf0001000,
                        .size = 0x3000,
                        .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE,
                },
                /* MemRegion: f0004000-f0004fff : 0000:02:00.0 onboard NIC */
                {
                        .phys_start = 0xf0004000,
                        .virt_start = 0xf0004000,
                        .size = 0x1000,
                        .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE,
                },
                /* MemRegion: f7800000-f7bfffff : 0000:00:02.0 VGA */
                {
                        .phys_start = 0xf7800000,
                        .virt_start = 0xf7800000,
                        .size = 0x400000,
                        .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_ROOTSHARED,
                },
	},
	.cache_regions = {
		{
			.start = 0,
			.size = 2,
			.type = JAILHOUSE_CACHE_L3,
		},
	},

	.pio_bitmap = {
		[     0/8 ...  0x1ef/8] = -1,
		[ 0x1f0/8 ...  0x1f7/8] = -1, /* IDE0 */
		[ 0x1f8/8 ...  0x2ff/8] = 0,  /* serial (COM4,COM2)  */
		[ 0x300/8 ...  0x3e7/8] = -1,
		[ 0x3e8/8 ...  0x3ef/8] = 0,  /* COM3 */
		[ 0x3f0/8 ...  0x3f7/8] = -1, /* IDE0 (sts) */
		[ 0x3f8/8 ...  0x3ff/8] = 0,  /* COM1 */
		[ 0x400/8 ... 0x0cf7/8] = -1,
		[ 0xcf8/8 ... 0x0cff/8] = 0,
		[ 0xd00/8 ... 0xcfff/8] = -1,
		[0xd000/8 ... 0xdfff/8] = 0,  /* onboard NIC */
		[0xe000/8 ... 0xe107/8] = 0,  /* serial */
		[0xe108/8 ... 0xf03f/8] = -1,
		[0xf040/8 ... 0xffff/8] = -1,
	},
	.pci_devices = {			/* このセルが使用するPCIデバイス */
		{
			.type = JAILHOUSE_PCI_TYPE_IVSHMEM,
			.domain = 0x0,
			.bdf = 0x0e << 3,
			.bar_mask = {
				0xffffff00, 0xffffffff, 0x00000000,
				0x00000000, 0xffffffe0, 0xffffffff,
			},
			.num_msix_vectors = 1,
			.shmem_region = 3,
			.shmem_protocol = JAILHOUSE_SHMEM_PROTO_VETH,
		},
		/* Added for serial */
                /* PCIDevice: 01:00.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
                        .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0x100,
                        .bar_mask = {
                                0xfffffff8, 0x00000000, 0x00000000,
                                0x00000000, 0x00000000, 0x00000000,
                        },
                        .caps_start = 0,
                        .num_caps = 5,
                        .num_msi_vectors = 1,
                        .msi_64bits = 1,
                        .num_msix_vectors = 0,
                        .msix_region_size = 0x0,
                        .msix_address = 0x0,
                },
		/* Added  for serial */
                /* PCIDevice: 01:00.1 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
                        .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0x101,
                        .bar_mask = {
                                0xfffffff8, 0x00000000, 0x00000000,
                                0x00000000, 0x00000000, 0x00000000,
                        },
                        .caps_start = 5,
                        .num_caps = 4,
                        .num_msi_vectors = 1,
                        .msi_64bits = 1,
                        .num_msix_vectors = 0,
                        .msix_region_size = 0x0,
                        .msix_address = 0x0,
                },
		/* Added for onboard NIC */
                /* PCIDevice: 02:00.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
                        .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0x200,
                        .bar_mask = {
                                0xffffff00, 0x00000000, 0xfffff000,
                                0xffffffff, 0xffffc000, 0xffffffff,
                        },
                        .caps_start = 9,
                        .num_caps = 8,
                        .num_msi_vectors = 1,
                        .msi_64bits = 1,
                        .num_msix_vectors = 0,
                        .msix_region_size = 0x0000,
                        .msix_address = 0x00000000,
                },
	},
	.pci_caps = {			/* このセルが使用するPCIデバイスのcapability */
                /* PCIDevice: 01:00.0 */	/* serial */
/* 0 */        {
                        .id = 0x1,
                        .start = 0x40,
                        .len = 8,
                        .flags = JAILHOUSE_PCICAPS_WRITE,
                },
                {
                        .id = 0x5,
                        .start = 0x50,
                        .len = 14,
                        .flags = JAILHOUSE_PCICAPS_WRITE,
                },
                {
                        .id = 0x10,
                        .start = 0x70,
                        .len = 20,
                        .flags = 0,
                },
                {
                        .id = 0x3 | JAILHOUSE_PCI_EXT_CAP,
                        .start = 0x100,
                        .len = 4,
                        .flags = 0,
                },
                {
                        .id = 0x4 | JAILHOUSE_PCI_EXT_CAP,
                        .start = 0x110,
                        .len = 4,
                        .flags = 0,
                },
                /* PCIDevice: 01:00.1 */	/* serial */
/* 5 */        {
                        .id = 0x1,
                        .start = 0x40,
                        .len = 8,
                        .flags = JAILHOUSE_PCICAPS_WRITE,
                },
                {
                        .id = 0x5,
                        .start = 0x50,
                        .len = 14,
                        .flags = JAILHOUSE_PCICAPS_WRITE,
                },
                {
                        .id = 0x10,
                        .start = 0x70,
                        .len = 20,
                        .flags = 0,
                },
                {
                        .id = 0x4 | JAILHOUSE_PCI_EXT_CAP,
                        .start = 0x100,
                        .len = 4,
                        .flags = 0,
                },
                /* PCIDevice: 02:00.0 */	/* onboard NIC */
/* 9 */        {
                        .id = 0x1,
                        .start = 0x40,
                        .len = 8,
                        .flags = JAILHOUSE_PCICAPS_WRITE,
                },
                {
                        .id = 0x5,
                        .start = 0x50,
                        .len = 14,
                        .flags = JAILHOUSE_PCICAPS_WRITE,
                },
                {
                        .id = 0x10,
                        .start = 0x70,
                        .len = 60,
                        .flags = 0,
                },
                {
                        .id = 0x11,
                        .start = 0xb0,
                        .len = 12,
                        .flags = JAILHOUSE_PCICAPS_WRITE,
                },
                {
                        .id = 0x3,
                        .start = 0xd0,
                        .len = 2,
                        .flags = 0,
                },
                {
                        .id = 0x1 | JAILHOUSE_PCI_EXT_CAP,
                        .start = 0x100,
                        .len = 4,
                        .flags = 0,
                },
                {
                        .id = 0x2 | JAILHOUSE_PCI_EXT_CAP,
                        .start = 0x140,
                        .len = 4,
                        .flags = 0,
                },
                {
                        .id = 0x3 | JAILHOUSE_PCI_EXT_CAP,
                        .start = 0x160,
                        .len = 4,
                        .flags = 0,
                },
/* 17 */
	}
};
```

#### ノンルートセルで動作するゲストLinuxの用意
   Linuxカーネルとルートファイルシステムが必要
     ・LinuxカーネルはJailhouseのWebサイトからダウンロードし，ビルド
     ・ルートファイルシステムはとりあえず簡単なものをBuildrootで作成

### ホストLinuxの起動
  カーネル起動コマンドラインに以下を追加し，リブートします．

```shell
   intel_iommu=off memmap=0x4200000\$0x3b000000
```
   これはホストLinux起動時に，物理メモリアドレス0x3b000000から0x4200000バイトの領域（約66MB）をJailhouseハイパーバイザが使用するメモリ領域として予約するという意味です．通常はこの値を変更する必要はありません．

#### Jailhouse本体の起動
-  Jailhouseドライバ(カーネルモジュール）のロード

```shell
     insmod drivers/jailhouse.ko
```
-    jailhouseをactivate（これ以降 ホストLinuxはルートセルで動作する）

```shell	
     jailhouse enable configs/sysconfig.cell
```
#### ノンルートセル（ゲストLinux）起動
   CUIで以下を実行

-   ゲストLinux用のノンルートセルの作成

```shell
     jailhouse cell create configs/linux-target.cell
```

-    作成したノンルートセルにソフトウェアをメモリロード(※）

```shell
     jailhouse cell load linux-target /usr/local/libexec/jailhouse/linux-loader.bin -a 0xf0000 /path/to/bzImage -a 0xffc200 /path/to/initrd -a 0x1ec5000 /path/to/linux-params -a 0xf5000
```
    ※ 実際には jailhouse cell loadコマンドの引数は次のコマンドで得ることができる．

```shell
     jailhouse cell linux /path/to/linux-target.cell /path/to/bzImage \
        -i /path/to/initrd -c "console=ttyS1,115200" -w /path/to/linux-params
```
-    ゲストLinux用（ノンルートセル）の起動

```shell
     jailhouse cell start linux-target
```

### 実行結果
上記のゲストLinux起動操作により，コンソール（ttyS1）に以下のような表示がされ，ログインプロンプトが表示されます．

```shell

Linux version 4.11.0-rc4-328367-g9fd0a81-dirty (root@localhost.localdomain) (gcc
 version 6.3.1 20161221 (Red Hat 6.3.1-1) (GCC) ) #143 Wed Dec 6 12:56:06 JST 2017                                 

Command line: console=ttyS1,115200                                              
x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'         
x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'                        
x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'                        
x86/fpu: xstate_offset[2]:  576, xstate_sizes[2]:  256                          
x86/fpu: Enabled xstate features 0x7, context size is 832 bytes, using 'standard
' format.                                                                       
e820: BIOS-provided physical RAM map: 
  （中略）
Welcome to Buildroot                                                            
jailhouse login: 

```

ここでログインして，たとえばethernetのconfigを行えば，ゲストLinuxと他PCとのEthernet通信が可能です.
（当然，何ができるかはゲストLinux次第です）


## 補足：デバッグ環境（セル毎のコンソール）
  ノンルートセルのデバッグが完了した後、稼働時にはコンソールは必ずしも必要ではありません．しかし，Jailhouse動作で何らかの何か問題があったとき，システム全体がハングすることが多いので，コンソールがないと，全く情報がないことになります（残念ながら，人手でのconfigurationミスが原因でこのような状態に陥ることが少なくない）

  たとえば、コンソールがあれば以下のような情報は出してシステムがハングしますが（これだけでも解析は難しいのですが・・），情報がなければ全くのお手あげになります．したがって，少なくとも初期はコンソールを使用したほうがいいと思います．

```shell
	FATAL: unsupported instruction (0xf3 [0x00] 0x00 0x00)                                                     
       	rip=ffffffff81339dec                                                          
	FATAL: Invalid MMIO/RAM write, addr: 0x000000003b6f0000 size: 0                 
	RIP: 0xffffffff81339dec RSP: 0xffffc9000a107db8 FLAGS: 10246                    
	RAX: 0xffff8801d8766a00 RBX: 0x0000000000000000 RCX: 0x0000000000002000         
	RDX: 0x0000000000000000 RSI: 0x0000000000e1b0d0 RDI: 0xffffc9000a190000         
	CS: 10 BASE: 0x0000000000000000 AR-BYTES: a09b EFER.LMA 1                       
	CR0: 0x0000000080050033 CR3: 0x0000000210990000 CR4: 0x00000000000426f0         
	EFER: 0x0000000000000d01                                                        
	Parking CPU 0 (Cell: "RootCell") 
```

## 感想
現時点でJailhouseは開発途上であり，version 1.0リリースまでに少し時間がかかると思われます．
現Jailhouseは
- 寡黙で実行中の情報が少ない
- ユーザ向け情報が少ない．（特にセルのconfigurationに関して）
という課題もありますが，今後 Jailhouseの特長を生かしたアプリケーションシステム構築に十分利用できると確信しています．


## 今後
   以下の２つの方向がありますが，当面は 1)を進めたいと思っています．
     1)Jailhouse上でLinuxシステムのDSU実現に向けてトライ
     2)他のハードウェアプラットフォームの評価
       特に、組み込みとしては本命のARM ボード

## 参考資料
-  `Jailhouse ホームページ`   https://github.com/siemens/jailhouse
    ここからさまざまページを参照できます
    特に，ノンルートLinuxについては以下の説明が詳しい．
	https://github.com/siemens/jailhouse/blob/master/Documentation/non-root-linux.txt

-  `Understanding the Jailhouse hypervisor`	2014年と少し古いが，Jailhouseを理解するには良い資料
    https://lwn.net/Articles/578295/		part 1
    https://lwn.net/Articles/578852/		part 2

-  `Bootstrapping the Partitioning Hypervisor Jailhouse`	2016年
    https://events.static.linuxfound.org/sites/events/files/slides/ELCE2016-Jailhouse-Tutorial.pdf

-  `Hard Partitioning for Linux: The Jailhouse Hypervisor`	2015年
    https://events.static.linuxfound.org/sites/events/files/slides/LinuxConNA-2015-Jailhouse_0.pdf

-  `IPC for the Partitioning Hypervisor Jailhouse`	2016年
    https://events.static.linuxfound.org/sites/events/files/slides/LinuxConJapan-2016-Jailhouse-IPC.pdf

-  `Real Safe Times in the Jailhouse Hypervisor`	2014年
    https://elinux.org/images/e/e1/Kiszka--real_safe_times_in_the_jailhouse_hypervisor.pdf

-  `Processor SDK Jailhouse Hypervisor`	2016年
    http://processors.wiki.ti.com/index.php/Processor_SDK_Jailhouse_Hypervisor
  
-  `Applying Jailhouse to the Civil Infrastucture System`	2017年
    https://elinux.org/images/f/ff/JapanTechnicalJamboree61_JailhouseR1_eng.pdf