少し趣を変えて、アセンブラのコードをのぞいてみることにしましょう。実割り込みを受け取る本当の入り口の部分の処理です。ハードウェアからの割り込みを受けると、Xenは割り込みハンドラを実行し、引き続いてソフトウェア割り込みハンドラを実行します。リスト2(左アイコンのリンク先)は、そのXenハイパーバイザーの割り込み処理の出入り口のコードです(読みやすくなるようにコードを少し加工しています)。
x86では、割り込み要因ごとに異なる割り込みエントリを持つことができます。リスト2では、例として2つの割り込みエントリを載せました*(B1、B2)。これらの割り込みは、共通のコードを使って前処理を行っています(B3)。この共通コードは、コンテキストの保存(B4)を行った後、前述したdo_IRQ関数(リスト1)を呼び出しており(B5)、do_IRQ関数は割り込み要因に対応した割り込みハンドラを呼び出します。
割り込みハンドラの実行が終了すると、次は遅延処理の実行です。割り込みの復帰先がドメインコンテキストである場合は(B8)、各種遅延処理を行います(B9)。この遅延処理の中では、ソフトウェア割り込み要求が保留されていないか調べ(B12)、もし保留されていれば、ソフトウェア割り込みハンドラを呼び出します*(B13、B15、B16)。
これら各種遅延処理中に、新たな遅延処理要求(ソフトウェア割り込み要求など)が発生することがあります。そのため、それらの遅延処理要求がなくなるまで遅延処理の実行を継続します(B14、B17)。
割り込みの復帰先がハイパーバイザーコードの中である場合は(B8)、各種遅延処理を行わずにコンテキストを割り込み前の状態に戻し、割り込み発生地点に復帰します(B10)。保留になっているソフトウェア割り込み要求は、別のハイパーバイザー呼び出し処理の終了や、ほかのソフトウェア割り込みハンドラの終了を契機として実行されます。
複数CPU間の通信を実現する仕組みとして、「プロセッサ間割り込み」が提供されています。文字どおり「あるCPUからほかのCPUに対し」割り込みを発生させる機構のことです。この割り込みを利用すれば、動作中のCPUに対して非同期的に要求を出すことができます。Xenハイパーバイザーはこの割り込みを利用して、仮想空間の構造変更を通知したり、ドメイン間通信を実現したりしています。
プロセッサ間割り込みも、ハードウェア割り込みと同様の仕組みを利用します。割り込みを受け付けたCPUでは、その割り込み要因に対応する割り込みハンドラを呼び出します。異なる点は、割り込みを生成するのがI/Oコントローラーではなく、CPUであることです。ほかのCPUに通知すべき事象が起きたとき、その事象を通知すべきCPUを指定してこのプロセッサ間割り込みを発生させます。
プロセッサ間割り込み機能の実装は、Linuxの実装をそのまま採用しており、
の2つを用意しています。アーキテクチャごとに実現方法は異なっていますが、基本的な考え方は同じと考えれば良いでしょう*。
関数名 | 説明 |
---|---|
send_IPI_mask() | 指定したCPU群に、プロセッサ間割り込みを送る |
send_IPI_single() | 指定したCPUに、プロセッサ間割り込みを送る |
send_IPI_all() | すべてのCPUに、プロセッサ間割り込みを送る |
send_IPI_allbutself() | 自CPUを除き、すべてのCPUにプロセッサ間割り込みを送る |
smp_send_event_check_mask() | 遅延処理要求のためのプロセッサ間割り込みを送る |
smp_event_check_interrupt() | 遅延処理要求のためのプロセッサ間割り込みハンドラ。このハンドラでは特に何も実行しない |
__flush_tlb_mask() | TLBフラッシュの要求をプロセッサ間割り込みを用いて通知する |
new_tlbflush_clock_period() | - |
smp_invalidate_interrupt | TLBフラッシュ用のプロセッサ間割り込みハンドラ |
smp_call_function() | すべてのCPUにプロセッサ間割り込みを送り、指定した関数を実行させる。また、その実行完了を待ち合わせる |
on_selected_cpus() | 指定したCPUにプロセッサ間割り込みを送り、指定した関数を実行させる。また、その実行完了を待ち合わせる |
smp_call_function_interrupt() | smp_call_function()、またはon_selected_cpus()で送られたプロセッサ間割り込みを受け付けるハンドラ。指定された関数を実行する |
smp_send_stop() | smp_call_function()関数を利用してプロセッサ間割り込みを送り、すべてのプロセッサに停止を要求する |
stop_this_cpu() | プロセッサ間割り込みを受けて、CPUを停止する |
x86用のXenでは、目的別に3種類のプロセッサ間割り込みを利用しています。割り込み要求側CPUでは、どのCPUに対しどの種類の割り込みを発生させるか指定できます。
3の割り込みハンドラはsmp_event_check_interrupt()関数で、表4によると、一見何も実行しないように見えます。しかし、先ほど見た割り込み出口の処理を思い出してください。遅延処理要求が保留されている場合、それらが呼び出されることになります。これは、ほかのCPUに強制的に遅延処理を実行させるために利用するプロセッサ間割り込みです。
次回は、仮想割り込みの仕組みについて説明します。Linuxカーネルのシグナルとよく似ていて*、非同期に発生すること、また明示的に生成できること、発生と受信処理の間にはタイムラグがあること、マスクできることなどの特徴があります。お楽しみに。
実際には、登録可能な割り込み種別分だけエントリがある。
実際にはこの部分で、ソフトウェア割り込みハンドラの呼び出し以外にも各種遅延処理を行うが、ここに載せたコードからは削除してある。
x86アーキテクチャ用のXenでは、APIC(Advanced Programmable Interrupt Controller)があることを前提として実装されている。
もともとシグナルは、割り込みをまねて設計されているので、当然といえば当然だ。
Copyright © ITmedia, Inc. All Rights Reserved.