/sys/power/state

次の表は /sys/power/state (kernel 内対応関数 state_store()) に書き込む文字列と kernel の挙動です。PC (パソコン) で調査したのでアーキテクチャやプラット・ホームの機能で詳細な挙動に違いがあるかもしれません。関連ドキュメントは /Documentation/power/states.txt です。

書き込む文字列 (kernel 内定数)プロセス稼働CPU稼働主記憶内容電力管理ACPI 相当主要な dev_pm_ops call back[1]
freeze
(PM_SUSPEND_FREEZE)
停止継続 (idle 状態が長くなる)保持周辺 IO デバイス 低消費電力化S0susped - (wake up) - resume
standby
(PM_SUSPEND_STANDBY)
停止boot processor は最小限の内部状態を維持して停止[2]、それ以外の processor は内部状態を失って offline。復帰過程では boot processor が復帰後、その他の processor を online にしている保持周辺 IO デバイス + CPU とその周辺 + 主記憶 低消費電力化S1susped - (wake up) - resume
mem
(PM_SUSPEND_MEM)
停止boot processor は内部状態が待避されて停止[3]、それ以外の processor は内部状態を失って offline
(全停止に至る過程で boot processor 以外を offline にしている。復帰過程も boot processor 復帰後、その他の processor を online にしている)
保持周辺 IO デバイス + CPU とその周辺 + 主記憶 低消費電力化
(standby よりも多くの復帰操作が必要な積極的な低消費電力化)
S3susped - (wake up) - resume
disk
(PM_SUSPEND_MAX)
停止内部状態を失って全停止
(全停止に至る過程で boot processor 以外を offline にして hibernation image 作成、online にして hibernation image を swap 領域へ書き出している)
swap 領域へ待避した後、喪失wakeup に必要な回路以外は電源 offS4freeze - (hibernation image 作成) - thaw - (hibernation image 書き出し) - poweroff - (power_down) - (wake up) - restore

[1] call back のうち prepare, complete, *_early, *_late, *_noirq, runtime_* は省略してあります。

[2] CPU に電源が供給されています。CPU 内部の詳細は公開されていないので推測するしか無いのですが、スタティック動作の回路は状態を維持します。ダイナミック動作の回路は状態を失い、PLL の様な clock 供給・分配系の回路は停止すると考えられます。

[3] 一般的に専用のハードウエアが processor の内部状態を待避復旧しています。このような専用のハードウエアは簡易なプロセッサとプログラムの組み合わせで構成されることもあります。

state ノードに "freeze" を書き込むと単に process が停止し device が suspend するのに対し、kernel 内の dev_pm_ops の freeze メンバ(call back pointer) は "disk" を書き込み hibernate (swap 領域にメモリ内容を書き出し電源 off) する時に呼ばれます。注意が必要です。

suspend - resume が上手くいかない場合

debugfs が /sys/kernel/debug に mount されているならば、# cat /sys/kernel/debug/suspend_stats (kernel 内対応関数 suspend_stats_show(), # cat /sys/kernel/debug/wakeup_sources (kernel 内対応関数 wakeup_sources_stats_show()) で suspend, resume, freeze 周辺の問題の要約を表示できます。/Documentation/power/basic-pm-debugging.txt にテストとデバッグの方法が書かれています。

dev_pm_ops call back が呼ばれるまでの call trace - platform_device の場合

dump_stack() を使って dev_pm_ops メンバが指している call back 関数が呼ばれるまでの call trace を列挙します。i8253_ref ドライバを修正して取得しました。 platform_device 以外の device では途中から call path が変化します。

state = { freeze, standby, mem }

state ノードに "freeze", "standby", "mem" を書き込むと dev_pm_ops メンバの suspend, resume を呼び出します。

suspend

state に "mem" を書き込んだ時に採取されたログです。kernel 内で file system 処理を通過した後、書き込まれた文字列を解釈する関数は state_store() です。"mem" を PM_SUSPEND_MEM に変換する関数が decode_state() です。

[85109.654592] Call Trace:
[85109.654609]  [<ffffffff817d2279>] dump_stack+0x63/0x81
[85109.654618]  [<ffffffffc033d75d>] i8253_ref_suspend+0x4d/0x60 [i8253_ref]
[85109.654627]  [<ffffffff81474ade>] ? acpi_thermal_resume+0xfa/0xfa
[85109.654634]  [<ffffffff8150d829>] platform_pm_suspend+0x29/0x50
[85109.654641]  [<ffffffff815187ae>] dpm_run_callback+0x4e/0x150
[85109.654647]  [<ffffffff81519542>] __device_suspend+0x132/0x3b0
[85109.654651]  [<ffffffff8151b27a>] dpm_suspend+0x13a/0x310
[85109.654654]  [<ffffffff8151b967>] dpm_suspend_start+0x57/0x60
[85109.654660]  [<ffffffff810c8c2f>] suspend_devices_and_enter+0x8f/0x780
[85109.654664]  [<ffffffff810c9416>] pm_suspend+0xf6/0x3b0
[85109.654668]  [<ffffffff810c7d69>] state_store+0x79/0xf0
[85109.654676]  [<ffffffff813b33df>] kobj_attr_store+0xf/0x20
[85109.654681]  [<ffffffff81275bfd>] sysfs_kf_write+0x3d/0x50
[85109.654687]  [<ffffffff812750aa>] kernfs_fop_write+0x12a/0x180
[85109.654692]  [<ffffffff811fa198>] __vfs_write+0x28/0xf0
[85109.654697]  [<ffffffff811fcda9>] ? __sb_start_write+0x49/0xf0
[85109.654705]  [<ffffffff81320373>] ? security_file_permission+0x23/0xa0
[85109.654709]  [<ffffffff811fa889>] vfs_write+0xa9/0x1b0
[85109.654713]  [<ffffffff811fb656>] SyS_write+0x46/0xb0
[85109.654719]  [<ffffffff81218742>] ? __close_fd;+0x82/0xa0
[85109.654725]  [<ffffffff817da0b2>] system_call_fastpath+0x16/0x75
[85109.654743] i8253_ref i8253_ref.0.auto: Suspended.

resume

前の節 suspend の続きです。call trace を見ると suspend_devices_and_enter() までは全く同じ trace になっています。

[85110.121742] Call Trace:
[85110.121761]  [<ffffffff817d2279>] dump_stack+0x63/0x81
[85110.121773]  [<ffffffffc033d8cd>] i8253_ref_resume+0x4d/0x60 [i8253_ref]
[85110.121781]  [<ffffffff8150d87b>] platform_pm_resume+0x2b/0x50
[85110.121789]  [<ffffffff815187ae>] dpm_run_callback+0x4e/0x150
[85110.121794]  [<ffffffff81518d76>] device_resume+0xd6/0x200
[85110.121798]  [<ffffffff8151a479>] dpm_resume+0x129/0x320
[85110.121801]  [<ffffffff8151aa55>] dpm_resume_end+0x15/0x30
[85110.121808]  [<ffffffff810c8cc7>] suspend_devices_and_enter+0x127/0x780
[85110.121812]  [<ffffffff810c9416>] pm_suspend+0xf6/0x3b0
[85110.121816]  [<ffffffff810c7d69>] state_store+0x79/0xf0
[85110.121827]  [<ffffffff813b33df>] kobj_attr_store+0xf/0x20
[85110.121831]  [<ffffffff81275bfd>] sysfs_kf_write+0x3d/0x50
[85110.121839]  [<ffffffff812750aa>] kernfs_fop_write+0x12a/0x180
[85110.121845]  [<ffffffff811fa198>] __vfs_write+0x28/0xf0
[85110.121850]  [<ffffffff811fcda9>] ? __sb_start_write+0x49/0xf0
[85110.121860]  [<ffffffff81320373>] ? security_file_permission+0x23/0xa0
[85110.121864]  [<ffffffff811fa889>] vfs_write+0xa9/0x1b0
[85110.121868]  [<ffffffff811fb656>] SyS_write+0x46/0xb0
[85110.121874]  [<ffffffff81218742>] ? __close_fd+0x82/0xa0
[85110.121881]  [<ffffffff817da0b2>] system_call_fastpath+0x16/0x75
[85110.121984] i8253_ref i8253_ref.0.auto: Resumed. counter=0x02f8

device driver の suspend が完了した後、suspend_devices_and_enter() は続けて suspend_enter() を呼び出します。suspend_enter() ではプラット・ホームの機能により分岐して suspend する関数を呼び分けています。freeze_enter() または suspend_ops->enter() です。freeze_enter() は CPU をなるべく動作しないようにするだけです。suspend_ops->enter() はプラットホームの機能を十分に使いシステム全体を低消費電力状態で停止する処理になります。wake up すると 停止した所から実行が継続します。プラットホーム毎に suspend_ops の内容は変わります。platform_suspend_ops 構造体を実装した場所を追跡してみて下さい。

state = { disk }

state ノードに "disk" を書き込むと dev_pm_ops メンバの freeze, thaw, poweroff, restore が呼び出されます。

freeze

freeze は hibernation image を作成する前に呼び出されます。以降 thaw, poweroff, restore とも hibernation_snapshot() から呼ばれているように crall trace が得られます。

[95474.290649] Call Trace:
[95474.290657]  [<ffffffff817d2279>] dump_stack+0x63/0x81
[95474.290661]  [<ffffffffc033d7bd>] i8253_ref_freeze+0x4d/0x60 [i8253_ref]
[95474.290665]  [<ffffffff81474ade>] ? acpi_thermal_resume+0xfa/0xfa
[95474.290668]  [<ffffffff8150d8c9>] platform_pm_freeze+0x29/0x50
[95474.290671]  [<ffffffff815187ae>] dpm_run_callback+0x4e/0x150
[95474.290673]  [<ffffffff81519542>] __device_suspend+0x132/0x3b0
[95474.290675]  [<ffffffff8151b27a>] dpm_suspend+0x13a/0x310
[95474.290678]  [<ffffffff810c9e14>] hibernation_snapshot+0xb4/0x370
[95474.290679]  [<ffffffff810ca8ce>] hibernate+0x16e/0x220
[95474.290681]  [<ffffffff810c7dd4>] state_store+0xe4/0xf0
[95474.290684]  [<ffffffff813b33df>] kobj_attr_store+0xf/0x20
[95474.290687]  [<ffffffff81275bfd>] sysfs_kf_write+0x3d/0x50
[95474.290689]  [<ffffffff812750aa>] kernfs_fop_write+0x12a/0x180
[95474.290692]  [<ffffffff811fa198>] __vfs_write+0x28/0xf0
[95474.290694]  [<ffffffff811fcda9>] ? __sb_start_write+0x49/0xf0
[95474.290697]  [<ffffffff81320373>] ? security_file_permission+0x23/0xa0
[95474.290699]  [<ffffffff811fa889>] vfs_write+0xa9/0x1b0
[95474.290700]  [<ffffffff811fb656>] SyS_write+0x46/0xb0
[95474.290703]  [<ffffffff81218742>] ? __close_fd+0x82/0xa0
[95474.290706]  [<ffffffff817da0b2>] system_call_fastpath+0x16/0x75
[95474.290725] i8253_ref i8253_ref.0.auto: Freezed.

thaw

thaw は普通 hibernation image を swap 領域に書き込む前に呼び出されます。freeze の後何かのエラーが発生した場合も thaw が呼ばれます。恐らくエラーは領域不足で hibernation image を作れなかったか、swap 領域不足が見込まれる場合が殆どでしょう。

[95474.837030] Call Trace:
[95474.837038]  [<ffffffff817d2279>] dump_stack+0x63/0x81
[95474.837042]  [<ffffffffc033d92d>] i8253_ref_thaw+0x4d/0x60 [i8253_ref]
[95474.837045]  [<ffffffff8150d91b>] platform_pm_thaw+0x2b/0x50
[95474.837049]  [<ffffffff815187ae>] dpm_run_callback+0x4e/0x150
[95474.837051]  [<ffffffff81518d76>] device_resume+0xd6/0x200
[95474.837052]  [<ffffffff8151a479>] dpm_resume+0x129/0x320
[95474.837056]  [<ffffffff810c9f60>] hibernation_snapshot+0x200/0x370
[95474.837057]  [<ffffffff810ca8ce>] hibernate+0x16e/0x220
[95474.837059]  [<ffffffff810c7dd4>] state_store+0xe4/0xf0
[95474.837062]  [<ffffffff813b33df>] kobj_attr_store+0xf/0x20
[95474.837064]  [<ffffffff81275bfd>] sysfs_kf_write+0x3d/0x50
[95474.837067]  [<ffffffff812750aa>] kernfs_fop_write+0x12a/0x180
[95474.837069]  [<ffffffff811fa198>] __vfs_write+0x28/0xf0
[95474.837071]  [<ffffffff811fcda9>] ? __sb_start_write+0x49/0xf0
[95474.837074]  [<ffffffff81320373>] ? security_file_permission+0x23/0xa0
[95474.837076]  [<ffffffff811fa889>] vfs_write+0xa9/0x1b0
[95474.837078]  [<ffffffff811fb656>] SyS_write+0x46/0xb0
[95474.837080]  [<ffffffff81218742>] ? __close_fd+0x82/0xa0
[95474.837083]  [<ffffffff817da0b2>] system_call_fastpath+0x16/0x75
[95474.837117] i8253_ref i8253_ref.0.auto: Thawed. counter=0x1620

poweroff

poweroff は hibernation image を swap 領域に書き込んだ後、電源 off をする前に呼ばれます。

[95488.527795] Call Trace:
[95488.527804]  [<ffffffff817d2279>] dump_stack+0x63/0x81
[95488.527809]  [<ffffffffc033d98d>] i8253_ref_poweroff+0x4d/0x60 [i8253_ref]
[95488.527814]  [<ffffffff81474ade>] ? acpi_thermal_resume+0xfa/0xfa
[95488.527818]  [<ffffffff8150d969>] platform_pm_poweroff+0x29/0x50
[95488.527823]  [<ffffffff815187ae>] dpm_run_callback+0x4e/0x150
[95488.527825]  [<ffffffff81519542>] __device_suspend+0x132/0x3b0
[95488.527827]  [<ffffffff8151b27a>] dpm_suspend+0x13a/0x310
[95488.527829]  [<ffffffff8151b967>] dpm_suspend_start+0x57/0x60
[95488.527833]  [<ffffffff810ca68c>] hibernation_platform_enter+0x3c/0x110
[95488.527835]  [<ffffffff817ce3d8>] power_down+0x1f/0xa1
[95488.527837]  [<ffffffff810ca939>] hibernate+0x1d9/0x220
[95488.527839]  [<ffffffff810c7dd4>] state_store+0xe4/0xf0
[95488.527843]  [<ffffffff813b33df>] kobj_attr_store+0xf/0x20
[95488.527846]  [<ffffffff81275bfd>] sysfs_kf_write+0x3d/0x50
[95488.527849]  [<ffffffff812750aa>] kernfs_fop_write+0x12a/0x180
[95488.527853]  [<ffffffff811fa198>] __vfs_write+0x28/0xf0
[95488.527855]  [<ffffffff811fcda9>] ? __sb_start_write+0x49/0xf0
[95488.527859]  [<ffffffff81320373>] ? security_file_permission+0x23/0xa0
[95488.527862]  [<ffffffff811fa889>] vfs_write+0xa9/0x1b0
[95488.527864]  [<ffffffff811fb656>] SyS_write+0x46/0xb0
[95488.527867]  [<ffffffff81218742>] ? __close_fd+0x82/0xa0
[95488.527870]  [<ffffffff817da0b2>] system_call_fastpath+0x16/0x75
[95488.527907] i8253_ref i8253_ref.0.auto: Poweroffed. counter=0xbcde

restore

restore は kernel が起動した後、swap 領域から hibernation image を読み取り主記憶に展開した後呼ばれます。kernel 起動中の printk 時刻は 0.000000 から始まります。hibernation image の展開が終わった後、printk の時刻は poweroff 前の時刻と整合して続くように修正されます。

[95499.554259] Call Trace:
[95499.554259]  [<ffffffff817d2279>] dump_stack+0x63/0x81
[95499.554259]  [<ffffffffc033d9ed>] i8253_ref_restore+0x4d/0x53 [i8253_ref]
[95499.554259]  [<ffffffff8150d9bb>] platform_pm_restore+0x2b/0x50
[95499.554259]  [<ffffffff815187ae>] dpm_run_callback+0x4e/0x150
[95499.554259]  [<ffffffff81518d76>] device_resume+0xd6/0x200
[95499.554259]  [<ffffffff8151a479>] dpm_resume+0x129/0x320
[95499.554259]  [<ffffffff810c9ecb>] hibernation_snapshot+0x16b/0x370
[95499.554259]  [<ffffffff810ca8ce>] hibernate+0x16e/0x220
[95499.554259]  [<ffffffff810c7dd4>] state_store+0xe4/0xf0
[95499.554259]  [<ffffffff813b33df>] kobj_attr_store+0xf/0x20
[95499.554259]  [<ffffffff81275bfd>] sysfs_kf_write+0x3d/0x50
[95499.554259]  [<ffffffff812750aa>] kernfs_fop_write+0x12a/0x180
[95499.554259]  [<ffffffff811fa198>] __vfs_write+0x28/0xf0
[95499.554259]  [<ffffffff811fcda9>] ? __sb_start_write+0x49/0xf0
[95499.554259]  [<ffffffff81320373>] ? security_file_permission+0x23/0xa0
[95499.554259]  [<ffffffff811fa889>] vfs_write+0xa9/0x1b0
[95499.554259]  [<ffffffff811fb656>] SyS_write+0x46/0xb0
[95499.554259]  [<ffffffff81218742>] ? __close_fd+0x82/0xa0
[95499.554259]  [<ffffffff817da0b2>] system_call_fastpath+0x16/0x75
[95549.131204] i8253_ref i8253_ref.0.auto: Restored. counter=0x10fd

hibernate (state=disk)から復帰するとき kernel は reset 状態から起動します。上の stack dump を見ると state_store() から呼ばれたように見えます。一方で kernel 起動中に何かの process が /sys/power/state に書き込む様なことは起きていません。kernel 内部から /sys/power/state に書き込むこともしていません。hibernation_snapshot() から呼び出している create_image() 内で CPU レジスタを待避する save_processor_state() 関数、hibernate image を読み込んで実行再開するポイントになる swsusp_arch_suspend() 関数、CPU レジスタを復活する restore_processor_state() 関数の呼び出しとグローバル変数 in_suspend (__nosavedata が付いていて、hibernation image に含まれないことに注意する) の巧妙な変化により、hibernate に入るために /sys/power/state に "disk" を書き込んだ処理の続きから再開されます。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2017-09-14 (木) 01:59:26 (2419d)