OpenBSDで実際のC-stateを確認する(MWAIT)
Determining C-states using MWAIT on OpenBSD
ファイアウォールサーバのOSをOpenBSDに変えました。以前のFreeBSDをそのまま使っても良かったのですが、PFのみ使用・QATも/dev/randomのみとなっていたので土日を使ってインストール・設定し直しました。
今回はそのOpenBSDでC-stateを確認する方法という記事になっております。
はじめに
OpenBSDはCPUの省電力管理について、FreeBSDの hw.acpi.cpu.cx_lowest のようなユーザーが手動でいじるsysctl 項目は存在せず、カーネル(acpicpu)がACPIテーブルから情報を取得して自動的に管理するようになっています。
今回、低消費電力サーバーを構築する際に、このCPUが本当にC-stateに入っているのか?が個人的に気になっていました。今回はAtom C3558(Denverton)を搭載したボードを例に、OpenBSDが認識しているC-stateの実態をMWAIT命令から確認していきたいと思います。
実行した環境
OS: OpenBSD 7.8 amd64
MB: Quanmax Inc. MITX-DNV
CPU: Atom C3558 (4コア) @ 2.200GHz
OpenBSDのC-state認識
OpenBSDでは、起動時の dmesg で acpicpu ドライバの認識状況を確認できます。
acpicpu0 at acpi0: C2(10@50 mwait.1@0x21), C1(1000@1 mwait.1@0x1), PSS
acpicpu1 at acpi0: C2(10@50 mwait.1@0x21), C1(1000@1 mwait.1@0x1), PSS
...ここで見るべきは C2(10@50 mwait.1@0x21) という表記です。
ACPI上の名称はC2ですが、かっこ内の mwait.1@0x21こそが、CPUに対して「どの程度深く眠るか」を指示する物理的な命令値(MWAITサブステート)となっています。
MWAITサブステートを読み解く
Intelプロセッサにおいて、MWAIT命令に渡す引数(ヒント値)の上位ニブル(4ビット)は、概ね以下の状態に対応しています。
| ヒント値(上位) | 対応するIntel実装のC-state |
| 0x0x | C1-state |
| 0x1x | C3-state |
| 0x2x | C6-state |
| 0x3x | C7-state |
今回の環境で表示されているのは 0x21 です。つまり、OS上の表記は「C2」であっても、ハードウェアに対しては 「C6系のサブステート1」 を要求していることがわかります。また、C1がC3に相当することも見て取れます。
Denverton (Atom C3558) の場合
Linuxカーネルの intel_idle ドライバ等の実装を確認すると、Denverton世代のC-stateマップは以下のようになっています。
MWAIT 0x00: C1
MWAIT 0x01: C1E
MWAIT 0x20: C6
MWAIT 0x21: C6 ←本環境の場合このプロセッサは最大でC6までしか対応していないため、この 0x21 が出ている時点で、OpenBSDはハードウェアが持つ最大の省電力状態を正しく活用できていると判断できます。
MWAIT値の読み方の注意点
MWAITヒントの読み方についての補足ですが、Intelのマニュアルによれば、「MWAIT拡張で定義されたC-stateはプロセッサ固有のものであり、ACPI C-stateとは直接一致しない」とされています。
また、Linuxカーネルのドキュメントでも、ヒント値の意味はプラットフォームに依存する場合があると注意書きがあります。(Linux Kernel Documentation)
現実的には、多くのCore系・Xeon系プロセッサでは上記の上位ニブル規則が適用されていますが、最新のAtom系(Sierra Forest等)では例外も出始めています。
厳密な確認が必要な場合は、各CPU世代のデータシートや、Linuxの intel_idle.c のソースコードにあるテーブルと照らし合わせるのが最も確実です。
まとめ
OpenBSDでCPUは実際どれくらいのC-stateをしているんだろうと思ったときは、 dmesg の mwait 値を確認すれば大半が判断可能です。
上位ニブルが 0x2 や 0x3 なら、十分に深いところまで落ちており、逆に!プレフィックスなどが付いている場合はBiosなどでスキップされている状態だということです。
また、OpenBSD 7.6以降では、suspend-to-idle時にも可能な限り深いC-stateを選択するよう改善が進んでおり、ユーザーが意識せずとも最適な省電力が得られるようになっています。設定項目が少ないのは、それだけOS側が賢く処理している証拠だと思いました。
おわり
参考URL
- Intel® 64 and IA-32 Architectures Software Developer’s Manual (Volume 2B: MWAIT instruction)
- github: Linux Kernel Source: intel_idle.c (Denverton C-states definition)
- Linux Kernel Documentation: CPU Idle Time Management
- OpenBSD 7.6 Release Notes (Improved C-state selection for acpicpu)