systemdにはコンテナやハイパーバイザの検出用関数detect_virtualizationが存在する。v230現在では、まずコンテナを判別するdetect_containerを実行して、判別できなければ仮想化環境を判別するdetect_vmを実行する。
detect_container
OpenVZ, LXC, LXC (libvirt), Docker, RKT, systemd nspawnを判別できる。
- OpenVZ
- 
/proc/vzが存在して、/proc/bcが存在しない- ルートコンテキストには両方存在する
 
 
 - 
 - それ以外
- 自分がPID=1であれば、
containerという環境変数を調べる - PID!=1であれば、
/run/systemd/containerの中を調べる- PID=1のsystemdプロセスが当該ファイルを生成する
 
 - それもなければ、PID=1のプロセスの
container環境変数を調べる 
 - 自分がPID=1であれば、
 
detect_vm
KVM, QEMU, Bochs, Xen, UML, VMware, VirtualBox, Microsoft Azure, IBM z/VM, Parallels Desktopを判別できる。
systemdは仮想化環境を判別する方法をいくつか持っており、それらを順次実行していく。
detect_vm_dmi
DMIはDesktop Management Interfaceのことで、シリアル番号やBIOSのリビジョンといったハードウェア情報を取得するためのインタフェースである。Linuxでは、sysfsで以下のような情報が手に入る。
$ ls /sys/class/dmi/id/
bios_date     board_asset_tag  board_vendor       chassis_serial  chassis_version  product_name    product_version  uevent
bios_vendor   board_name       board_version      chassis_type    modalias         product_serial  subsystem
bios_version  board_serial     chassis_asset_tag  chassis_vendor  power            product_uuid    sys_vendor
systemdは以下のDMIを順番に調べる。
/sys/class/dmi/id/product_name/sys/class/dmi/id/sys_vendor/sys/class/dmi/id/board_vendor/sys/class/dmi/id/bios_vendor
最近のVMMだと、これらのファイルのいずれかに識別のための文字列が入っている。
- KVM
 - QEMU
 - VMware, VMW
 - innotek GmbH (VirtualBox)
 - Xen
 - Bochs
 - Parallels
 
detect_vm_cpuid
CPUIDの調べ方は後述するが、これもDMIと同様に設定されている文字列を元に仮想化環境を判別する。
- XenVMMXenVMM
 - KVMKVMKVM
 - VMwareVMware
 - Microsoft Hv
 
detect_vm_xen
/proc/xen/capabilitiesが存在しているかチェックする。とりあえず、ここでXenであると判別するが、後でDom0のチェックを行なう(後述)。
detect_vm_hypervisor
/sys/hypervisor/typeを調べてxenと書かれていればXenと判別する。
detect_vm_device_tree
ARM, AArch64, PPC, PPC64の場合はデバイスツリーを調べる。
- 
/proc/device-tree/hypervisor/compatibleが存在する場合- 
linux,kvmと書かれていればKVMと判別する - 
xenと書かれていればXenと判別する 
 - 
 - 存在しない場合
- 
/proc/device-treeのディレクトリを調べて、fw-cfgというファイルが存在すればQEMUと判別する 
 - 
 
detect_vm_uml
/proc/cpuinfoに\nvendor_id\t: User Mode Linux\nという文字列が含まれていればUMLと判別する。
detect_vm_zvm
s390の場合、/proc/sysinfoのVM00 Control Programというエントリを調べる。
- 
z/VMと書かれていればz/VMと判別する - そうでなければKVMと判別する
 
detect_vm_xen_dom0
もしこの段階でXenと判別されていた場合Dom0か否かを調べる。
/proc/xen/capabilitiesの機能リストにcontrol_dが存在していれば、Dom0だと判断し、仮想化環境ではないと判別する。
CPUIDの調べ方
ハイパーバイザ用のCPUIDについては、CPUID usage for interaction between Hypervisors and Linux. [LWN.net]に詳しい説明が書かれている。CPUID命令は、EAXレジスタに欲しい情報のIDを入れてCPUID命令を呼び出すと、情報毎に決められた特定のレジスタに情報が設定される (CPUID - Wikipedia, the free encyclopedia)。EAX=1がプロセッサ情報に対応し、EAXにプロセッサモデルやファミリ、EDXとECXにプロセッサの個々の機能が設定される。ECXの31ビット目はハイパーバイザ向けに予約されており、ハイパーバイザは1にセットして返すことになっている。ハイパーバイザが存在することがわかると、今度はEAX=0x40000000を入れてCPUID命令を呼ぶことで、ハイパーバイザ用ベンダIDを取得することができる。