SlideShare a Scribd company logo
4
Most read
5
Most read
8
Most read
4 章 Linux カーネル – 割り込み・例外 4
・例外ベクタと例外ハンドラ
・割り込みディスクリプタテーブル
・割り込み信号発生からハンドラ実行まで
・ハンドラ実行終了後の処理
・割り込み / 例外処理のネスト
mao
Web >https://www.pridact.com
Twitter >https://twitter.com/rivarten
Mail   >official@pridact.com
はじめに
割り込み・例外の話
視点
・概要
・ハードウェアの動作
・データ構造
・データ構造の操作の仕方
・ソースコード
ソースコードの情報が載っている場合は ,
実際にソースコードに目を通しながら資料を見ていっ
たほうがいいかもしれません。
今回はハードウェアの話が多いかもしれません
この資料について
・間違っていたらご指摘をお願い致します。
・ Linux Kernel のバージョンは 4.9.16 です。
・ページタイトルに * 印が付いているページは、
 少し踏み込んだ内容になっています。
 ざっと全体に目を通したければ、読み飛ばして
 もらっても構いません。
カーネル参考文献
< 参考書 >
 〜基本的に古い情報だが、基本は学べる〜
・詳解 LINUX カーネル 第 3 版 (O’REILLY
・ Linux カーネル 2.6 解読室 (Softbank Creative
・ Linux カーネル解析入門 ( 工学社
・ Modern Operating Systems 3e International
(Pearson, Andrew S. Tanenbaum)
 〜初期化部分を知りたいなら〜
・新装改訂版 Linux のブートプロセスを見る
( アスキー・メディアワークス )
< 参考 Web>
・ Linux Cross Reference[http://lxr.free-electrons.com]
・ Wikipedia
例外ベクタと例外ハンドラ (1)
・例外ベクタ (x86)
ベクタ番号 名前 種類 説明
0 除算エラー (Devide Error) フォルト プログラムが 0 で整数除算すると発生
1
デバッグ例外 (Debug) トラップ ,
フォルト
eflags レジスタの TF=1 で発生 ( デバッガでの
ステップ実行に有用 ). 有効化したデバッグレ
ジスタのアドレス範囲内にある命令を実行し
たり , オペランドへアクセスしたりした時もデ
バッグ例外が発生 .
2
マスク不可割り込み (Non-Maskable
Interrupt) ---
マスク不可割り込み用に予約
(NMI ピンを使用 )
3
ブレークポイント (Breakpoint) トラップ int3( ブレークポイント ) 命令によって発生 .
通常はデバッガがこの命令を埋め込む .
4
オーバーフロー (Overflow) トラップ into( オーバーフローを調べる ) 命令を実行し
た時に ,eflags レジスタの OF(overflow) レジス
タ フラグが設定されている場合に発生
5
Bound 範囲超過 (Bounds check) フォルト bound( アドレス範囲を調べる ) 命令を , アドレ
スの有効範囲外にあるオペランドとともに実
行すると発生 .
6
無効オペコード (Invalid opcode) フォルト CPU が無効なオペコード ( 実行する動作を決
定するマシン語の一部 ) を検出すると発生
7
デバイス使用不可能 (Device not
available)
フォル ESCAPE 命令 ,MMX 命令 ,SSE/SSE2 命令を
実行した時に ,cr0 レジスタの TS フラグが設
定されている場合に発生
例外ベクタと例外ハンドラ (2)
・例外ベクタ (x86)
ベクタ番号 名前 種類 説明
8
ダブルフォルト (Double falult) アボート CPU が例外ハンドラを呼び出す時に別の例
外を検出すると , 通常 2 つの例外は順次処
理されるが , 稀にプロセッサが連続して処理
できない場合があり , その時に発生 .
9
コプロセッサセグメントオーバーラン
(Coprocessor segment overrun)
アボート 外部算術演算コプロセッサで問題が起こると
発生 . 古い 80386 プロセッサの場合にのみ発
生
10
無効 TSS(Invalid TSS) フォルト 無効な TSS を持つプロセスに切り替えようと
した場合に発生
11
セグメント不在 (Segment not present) フォルト メモリ中に存在しない ( セグメントディスクリプ
タの P フラグが設定されていない ) セグメント
を参照した場合に発生
12
スタックセグメントフォルト (Stack
segment fault)
フォルト 命令がスタックセグメントの範囲を越えようと
した場合 , または ss レジスタが指すセグメン
トがメモリ中に存在しない場合に発生 .
13
一般保護 (General protection) フォルト x86 のプロテクトモードの保護規則に違反し
た場合に発生
14
ページフォルト (Page fault) フォルト 参照されたページがメモリ上に存在しない
か , 対応するページテーブルエントリが NULL
か , ページング保護機構に違反した場合に発
生
例外ベクタと例外ハンドラ (3)
・例外ベクタ (x86)
ベクタ番号 名前 種類 説明
15 Intel が予約済み ---
16
浮動小数点エラー (Floating point error) フォルト CPU に組み込まれている浮動小数点回路が
エラーを検出した場合に発生 . 算術オーバー
フローやゼロ除算など .x86 では , 符号付き除
算の結果が符号付き整数にならない場合 (-
2,147,483,648/-1 など ) にも発生 .
17
アラインメントチェック (Alignment check) フォルト オペランドのアドレスが正しくアラインされて
いない場合に発生
18
マシンチェック アボート マシンチェック機構が CPU やバスのエラーを
検出した場合に発生 .
19
SIMD 浮動小数点例外 (SIMD floating
point exception)
フォルト CPU に組み込まれている SSE や SSE2 回路
が浮動小数点演算でエラーを検出した場合
に発生 .
20~31
将来のために Intel が予約
---
例外ベクタと例外ハンドラ (4)
・例外ハンドラ (x86)
ベクタ番号 例外 ハンドラ シグナル
0 除算エラー (Divide Error) divide_error() SIGFPE
1 デバッグ例外 (Debug) debug() SIGTRAP
2
マスク不可割り込み (Non-Maskable
Interrupt)
nmi()
---
3 ブレークポイント (Breakpoint) int3() SIGTRAP
4 オーバーフロー (Overflow) overflow() SIGSEGV
5 Bound 範囲超過 (Bounds check) bounds() SIGSEGV
6 無効オペコード (Invalid opcode) invalid_op() SIGILL
7
デバイス使用不可能 (Device not
available)
device_not_available()
---
8 ダブルフォルト (Double falult) doublefault_fn() ---
9
コプロセッサセグメントオーバーラン
(Coprocessor segment overrun)
coprocessor_segment_ove
rrun()
SIGFPE
10 無効 TSS(Invalid TSS) invalid_TSS() SIGSEGV
11 セグメント不在 (Segment not present) segment_not_present() SIGBUS
12
スタックセグメントフォルト (Stack
segment fault)
stack_segment() SIGBUS
例外ベクタと例外ハンドラ (5)
・例外ハンドラ (x86)
ベクタ番号 例外 ハンドラ シグナル
13 一般保護 (General protection) general_protection() SIGSEGV
14 ページフォルト (Page fault) page_fault() SIGSEGV
15 Intel が予約済み --- ---
16 浮動小数点エラー (Floating point error) coprocessor_error() SIGFPE
17 アラインメントチェック (Alignment check) alignment_check() SIGBUS
18 マシンチェック (Machine check) machine_check() ---
19
SIMD 浮動小数点例外 (SIMD floating
point exception)
simd_coprocessor_error() SIGFPE
割り込みディスクリプタテーブル (1)
・割り込みディスクリプタテーブル IDT
  (Interrupt Descriptor Table)
・割り込みや例外のベクタとハンドラのアドレスの対応を保持 .
・形式は GDT や LDT とほぼ同じ .
・ IDT 最大サイズは 256×8byte=2KB
・ IDT はメモリ上の任意の位置に置くことができる .
・ CPU の idtr レジスタに IDT のベースリニアアドレスとリミットを指定 .
・割り込みを使用する前に lidt アセンブリ命令で初期化する .
・ 40~43bit(type) の内容がディスクリプタの種類を表している .
・ディスクリプタの種類
・タスクゲート
・割り込みゲート
・トラップゲート
Linux では , 割り込み処理に割り込みゲートを使用し ,
例外処理にトラップゲートを使用している .
割り込みディスクリプタテーブル (2)
・タスクゲート
プロセスの TSS セレクタを置く .
割り込み信号が発生した時に実行中のプロセスの TSS と置き換えられる .
ダブルフォルト例外は , カーネルの不正処理を表していて ,
Linux においてタスクゲートを用いる唯一の例外 .
割り込みディスクリプタテーブル (3)
・割り込みゲート
割り込み・例外のハンドラがあるセグメントの
セグメントセレクタとセグメント内でのオフセットを置く .
このセグメントに制御を移す間は ,
プロセッサは eflags.if=0 にしてマスク可能割り込みを禁止する .
割り込みディスクリプタテーブル (4)
・トラップゲート
割り込みゲートと同様だが , 別のセグメントに制御を移す間でも ,
プロセッサが eflags.if フラグを変更しない点で異なる .
割り込み信号発生からハンドラ実行まで (1)
・前提条件
 ・カーネルの初期化が完了し ,CPU がプロテクトモードで動作している .
0. ある 1 つの命令を実行後 ,cs/eip レジスタは次に実行すべき命令のアドレ
 スが入っている . これを実行する前に , 制御回路は前の命令の実行中に
 割り込み・例外が発生していないかを調べる (INTR,NMI を調べる )
 発生していれば , 制御回路は以降の処理を進める .
1. 割り込み・例外に対応するベクタ (0≦i≦255) を取得する .
2.idtr レジスタが指す IDT から i 番目のエントリを読み取る .
  ( 該当エントリには割り込みゲートかトラップゲートが存在する )
3.gdtr レジスタから GDT ベースアドレスを取得し ,
  GDT 内から IDT エントリのセレクタがさすセグメントディスクリプタを取得 .
 このディスクリプタに , 割り込み / 例外ハンドラがあるセグメントのベースア
 ドレスがある .
割り込み信号発生からハンドラ実行まで (2)
4. 割り込み元の正当性の確認 .
・ cs レジスタの CPL と GDT 内のセグメントディスクリプタの DPL を比較 .
  CPL: 割り込みを発生させたプログラムの現行特権レベル
  DPL: セグメントアクセスに必要な特権レベル
・ DPL の特権レベルより CPL の特権レベルの方が低い
  ( 値としては ,CPL>DPL)
 ⇒一般保護例外 .
  割り込みハンドラは , 割り込みを発生させたプログラムより
  低い特権レベルでは動作できない .
・ OK
 ソフトウェア的に生成された割り込み / 例外の場合 (int n,int 3,into
 命令等 ), さらなるセキュリティチェックを行う .
・ CPL と IDT 内のセグメントディスクリプタの DPL を比較
・ DPL の特権レベルより CPL の特権レベルの方が低い
  ( 値としては ,CPL>DPL)
 ⇒一般保護例外 .
   ユーザアプリケーションによるトラップゲートや割り込み
   ゲートへのアクセスを防ぐ .
割り込み信号発生からハンドラ実行まで (3)
5. 特権レベルが変更されているかを調べる .
CPL ≠ セグメントディスクリプタの DPL
⇒ 制御回路は新しい特権レベル用のスタックを用意する .
a. tr レジスタを読み取り , 実行中のプロセスの TSS にアクセス .
b. ss/esp レジスタに ,TSS に置かれている新しい特権レベル用の
 論理アドレスを ss/esp に読み込む .
c. 古い特権レベル用スタックの論理アドレスを表す ss/esp を ,
 新しいスタックに退避 .
6. フォルトが発生した場合 , 例外を発生させた命令の論理アドレスを
  cs/eip に読み込む . これで再実行が可能になる .
7. スタックに eflags,cs,eip レジスタの内容を退避する .
8. 例外がハードウェアエラーコードを持っていれば , スタックに退避する .
9.IDT 内の i 番目のエントリにあるセグメントセレクタとゲートディスクリプタの
 オフセットフィールドを ,cs/eip レジスタに読み込む .
 これが割り込み・例外ハンドラの最初の命令の論理アドレスを表す .
push 順 :[ss,esp] → [eflags,cs,eip] → ( ハードウェアエラーコード )
ハンドラ実行終了後の処理
iret 命令を実行して , 割り込まれたプロセスに制御を移す .
pop 順 :[ss,esp] ← [eflags,cs,eip] ← ( ハードウェアエラーコード )
1. スタックに退避されている cs,eip,eflags レジスタの値を読み込む .
2. ハンドラの CPL が ,cs の CPL と同じかどうか調べる .
  ( 割り込まれたプロセスがハンドラと同じ特権レベルで動作していたか )
 ・同じ⇒ iret は実行を終了
 ・違う⇒次のステップに進む .
3. スタックから ss/esp レジスタを読み込む .
  ( 古い特権レベル用のスタックに戻る )
4.ds,es,fs,gs セグメントレジスタを調べる .
  CPL の特権レベル > DPL の特権レベル ( 値は ,CPL<DPL) となるセグメン
 トディスクリプタを参照するセレクタがあれば ,
 そのセグメントレジスタをクリア .
カーネルルーチンが実行したセグメントを , それより特権レベルが低いプロセスが使用してしまう事を防ぐ .
クリアしなければ , カーネル空間にアクセス可能になってしまう .
割り込み・例外処理のネスト (1)
・割り込み / 例外のカーネル実行パスがネストすることもある .
・カーネル実行パスのネストを許可する条件
 「割り込みハンドラ実行中に絶対にプロセスを切り替えないこと」
カーネル実行パスを再開させる為に必要なデータは ,
カレントプロセスのカーネルスタックに積まれる為 ,
割り込みハンドラ動作中に , 他のプロセスに切り替えられない .
・例外のほとんどはユーザーモードの時だけ発生 .
 ページフォルト例外はカーネルモードでも発生 .
システムコールのカーネル実行パス + ページフォルト例外のカーネル実行パス
・割り込みは , カレントプロセスのデータを参照しない .
・割り込みハンドラは , 別の割り込みハンドラや例外ハンドラに
 割り込むことがある .
・例外ハンドラが割り込みハンドラに割り込むことはない .
・マルチプロセッサにおいて , 例外用のカーネル実行パスは ,
 ある CPU で処理開始された後 , プロセスの切り替えによって ,
 別の CPU に移動することもある .
割り込み・例外処理のネスト (2)
・ Linux がカーネル実行パスのネストを許可する理由
1.PIC やデバイスコントローラのスループット向上 .
PIC やデバイスコントローラは ,
CPU から ACK を受取るまで処理を止めたまま .
カーネル実行パスを切り替えて動作させると , 他の割り込み処理の
実行中であっても , カーネルが ACK を返すことができる .
2. 優先度レベルがない割り込みモデルを実現できる .
割り込みハンドラは , 他の割り込みハンドラの処理を遅延できる為 ,
デバイスに優先順位をあらかじめ与えておく必要がない .
これにより , カーネルコードが単純化でき , 移植性が向上 .

More Related Content

PDF
OSC2011 Tokyo/Fall 濃いバナ(virtio)
PDF
ioMemoryとAtomic Writeによるデータベース高速化
 
PDF
2章 Linuxカーネル - メモリ管理1
PDF
HSM超入門講座
PDF
NGINXセミナー(基本編)~いまさら聞けないNGINXコンフィグなど基本がわかる!
PDF
君にもできる! にゅーとろん君になってみよー!! 「Neutronになって理解するOpenStack Net - OpenStack最新情報セミナー ...
PDF
de:code 2019 Azure IoT Hub クラウド側の最新機能:デモも交えてご紹介
PDF
PostgreSQL Unconference #5 ICU Collation
OSC2011 Tokyo/Fall 濃いバナ(virtio)
ioMemoryとAtomic Writeによるデータベース高速化
 
2章 Linuxカーネル - メモリ管理1
HSM超入門講座
NGINXセミナー(基本編)~いまさら聞けないNGINXコンフィグなど基本がわかる!
君にもできる! にゅーとろん君になってみよー!! 「Neutronになって理解するOpenStack Net - OpenStack最新情報セミナー ...
de:code 2019 Azure IoT Hub クラウド側の最新機能:デモも交えてご紹介
PostgreSQL Unconference #5 ICU Collation

What's hot (20)

PDF
4章 Linuxカーネル - 割り込み・例外 3
PPTX
トランザクションの設計と進化
PDF
こわくない同時実行制御
PDF
TEE (Trusted Execution Environment)は第二の仮想化技術になるか?
PDF
RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)
PDF
Dockerイメージ管理の内部構造
PDF
Kuberneteの運用を支えるGitOps
PDF
Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)
PDF
NEDIA_SNIA_CXL_講演資料.pdf
PDF
Docker管理もHinemosで! ~監視・ジョブ機能を併せ持つ唯一のOSS「Hinemos」のご紹介~
PPTX
Apache Bigtopによるオープンなビッグデータ処理基盤の構築(オープンデベロッパーズカンファレンス 2021 Online 発表資料)
PPTX
コンテナネットワーキング(CNI)最前線
PPTX
BuildKitによる高速でセキュアなイメージビルド
PDF
検証環境をGoBGPで極力仮想化してみた
PDF
コンテナの作り方「Dockerは裏方で何をしているのか?」
PDF
EC2のストレージどう使う? -Instance Storageを理解して高速IOを上手に活用!-
PDF
CRC-32
PDF
Apache Hadoop YARNとマルチテナントにおけるリソース管理
PDF
あなたのクラウドは大丈夫?NRI実務者が教えるセキュリティの傾向と対策 (Oracle Cloudウェビナーシリーズ: 2021年11月24日)
PPTX
Azure DevOps ハンズオン Vo.2 ~Azure DevOps Wiki を用いたドキュメントの作成~
4章 Linuxカーネル - 割り込み・例外 3
トランザクションの設計と進化
こわくない同時実行制御
TEE (Trusted Execution Environment)は第二の仮想化技術になるか?
RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)
Dockerイメージ管理の内部構造
Kuberneteの運用を支えるGitOps
Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)
NEDIA_SNIA_CXL_講演資料.pdf
Docker管理もHinemosで! ~監視・ジョブ機能を併せ持つ唯一のOSS「Hinemos」のご紹介~
Apache Bigtopによるオープンなビッグデータ処理基盤の構築(オープンデベロッパーズカンファレンス 2021 Online 発表資料)
コンテナネットワーキング(CNI)最前線
BuildKitによる高速でセキュアなイメージビルド
検証環境をGoBGPで極力仮想化してみた
コンテナの作り方「Dockerは裏方で何をしているのか?」
EC2のストレージどう使う? -Instance Storageを理解して高速IOを上手に活用!-
CRC-32
Apache Hadoop YARNとマルチテナントにおけるリソース管理
あなたのクラウドは大丈夫?NRI実務者が教えるセキュリティの傾向と対策 (Oracle Cloudウェビナーシリーズ: 2021年11月24日)
Azure DevOps ハンズオン Vo.2 ~Azure DevOps Wiki を用いたドキュメントの作成~
Ad

Similar to 4章 Linuxカーネル - 割り込み・例外 4 (20)

PDF
03 後期勉強会一年の部【川合】
PDF
4章 Linuxカーネル - 割り込み・例外 1
PDF
Exploring the x64
PDF
4章 Linuxカーネル - 割り込み・例外 5
PPTX
Meltdown を正しく理解する
PPTX
Interrupts on xv6
PDF
【学習メモ#7th】12ステップで作る組込みOS自作入門
PDF
Unixカーネルの設計 7 プロセスの制御
PDF
Abusing Interrupts for Reliable Windows Kernel Exploitation (ja)
PDF
StackExchangeで見たシステムプログラミング案件
PDF
本当にわかる Spectre と Meltdown
PDF
x86とコンテキストスイッチ
PDF
SpectreとMeltdown:最近のCPUの深い話
PDF
[CB19] Semzhu-Project – 手で作る組込み向けハイパーバイザと攻撃検知手法の新しい世界 by 朱義文
PDF
【学習メモ#8th】12ステップで作る組込みOS自作入門
PPTX
Survey and Analysis of ICS Vulnerabilities (Japanese)
ODP
Buffer overflow
PDF
Di shen pacsec_jp-final
PDF
システムコールフックを使用した攻撃検出
PDF
[Basic 7] OS の基本 / 割り込み / システム コール / メモリ管理
03 後期勉強会一年の部【川合】
4章 Linuxカーネル - 割り込み・例外 1
Exploring the x64
4章 Linuxカーネル - 割り込み・例外 5
Meltdown を正しく理解する
Interrupts on xv6
【学習メモ#7th】12ステップで作る組込みOS自作入門
Unixカーネルの設計 7 プロセスの制御
Abusing Interrupts for Reliable Windows Kernel Exploitation (ja)
StackExchangeで見たシステムプログラミング案件
本当にわかる Spectre と Meltdown
x86とコンテキストスイッチ
SpectreとMeltdown:最近のCPUの深い話
[CB19] Semzhu-Project – 手で作る組込み向けハイパーバイザと攻撃検知手法の新しい世界 by 朱義文
【学習メモ#8th】12ステップで作る組込みOS自作入門
Survey and Analysis of ICS Vulnerabilities (Japanese)
Buffer overflow
Di shen pacsec_jp-final
システムコールフックを使用した攻撃検出
[Basic 7] OS の基本 / 割り込み / システム コール / メモリ管理
Ad

4章 Linuxカーネル - 割り込み・例外 4

  • 1. 4 章 Linux カーネル – 割り込み・例外 4 ・例外ベクタと例外ハンドラ ・割り込みディスクリプタテーブル ・割り込み信号発生からハンドラ実行まで ・ハンドラ実行終了後の処理 ・割り込み / 例外処理のネスト mao Web >https://www.pridact.com Twitter >https://twitter.com/rivarten Mail   >official@pridact.com
  • 3. この資料について ・間違っていたらご指摘をお願い致します。 ・ Linux Kernel のバージョンは 4.9.16 です。 ・ページタイトルに * 印が付いているページは、  少し踏み込んだ内容になっています。  ざっと全体に目を通したければ、読み飛ばして  もらっても構いません。
  • 4. カーネル参考文献 < 参考書 >  〜基本的に古い情報だが、基本は学べる〜 ・詳解 LINUX カーネル 第 3 版 (O’REILLY ・ Linux カーネル 2.6 解読室 (Softbank Creative ・ Linux カーネル解析入門 ( 工学社 ・ Modern Operating Systems 3e International (Pearson, Andrew S. Tanenbaum)  〜初期化部分を知りたいなら〜 ・新装改訂版 Linux のブートプロセスを見る ( アスキー・メディアワークス ) < 参考 Web> ・ Linux Cross Reference[http://lxr.free-electrons.com] ・ Wikipedia
  • 5. 例外ベクタと例外ハンドラ (1) ・例外ベクタ (x86) ベクタ番号 名前 種類 説明 0 除算エラー (Devide Error) フォルト プログラムが 0 で整数除算すると発生 1 デバッグ例外 (Debug) トラップ , フォルト eflags レジスタの TF=1 で発生 ( デバッガでの ステップ実行に有用 ). 有効化したデバッグレ ジスタのアドレス範囲内にある命令を実行し たり , オペランドへアクセスしたりした時もデ バッグ例外が発生 . 2 マスク不可割り込み (Non-Maskable Interrupt) --- マスク不可割り込み用に予約 (NMI ピンを使用 ) 3 ブレークポイント (Breakpoint) トラップ int3( ブレークポイント ) 命令によって発生 . 通常はデバッガがこの命令を埋め込む . 4 オーバーフロー (Overflow) トラップ into( オーバーフローを調べる ) 命令を実行し た時に ,eflags レジスタの OF(overflow) レジス タ フラグが設定されている場合に発生 5 Bound 範囲超過 (Bounds check) フォルト bound( アドレス範囲を調べる ) 命令を , アドレ スの有効範囲外にあるオペランドとともに実 行すると発生 . 6 無効オペコード (Invalid opcode) フォルト CPU が無効なオペコード ( 実行する動作を決 定するマシン語の一部 ) を検出すると発生 7 デバイス使用不可能 (Device not available) フォル ESCAPE 命令 ,MMX 命令 ,SSE/SSE2 命令を 実行した時に ,cr0 レジスタの TS フラグが設 定されている場合に発生
  • 6. 例外ベクタと例外ハンドラ (2) ・例外ベクタ (x86) ベクタ番号 名前 種類 説明 8 ダブルフォルト (Double falult) アボート CPU が例外ハンドラを呼び出す時に別の例 外を検出すると , 通常 2 つの例外は順次処 理されるが , 稀にプロセッサが連続して処理 できない場合があり , その時に発生 . 9 コプロセッサセグメントオーバーラン (Coprocessor segment overrun) アボート 外部算術演算コプロセッサで問題が起こると 発生 . 古い 80386 プロセッサの場合にのみ発 生 10 無効 TSS(Invalid TSS) フォルト 無効な TSS を持つプロセスに切り替えようと した場合に発生 11 セグメント不在 (Segment not present) フォルト メモリ中に存在しない ( セグメントディスクリプ タの P フラグが設定されていない ) セグメント を参照した場合に発生 12 スタックセグメントフォルト (Stack segment fault) フォルト 命令がスタックセグメントの範囲を越えようと した場合 , または ss レジスタが指すセグメン トがメモリ中に存在しない場合に発生 . 13 一般保護 (General protection) フォルト x86 のプロテクトモードの保護規則に違反し た場合に発生 14 ページフォルト (Page fault) フォルト 参照されたページがメモリ上に存在しない か , 対応するページテーブルエントリが NULL か , ページング保護機構に違反した場合に発 生
  • 7. 例外ベクタと例外ハンドラ (3) ・例外ベクタ (x86) ベクタ番号 名前 種類 説明 15 Intel が予約済み --- 16 浮動小数点エラー (Floating point error) フォルト CPU に組み込まれている浮動小数点回路が エラーを検出した場合に発生 . 算術オーバー フローやゼロ除算など .x86 では , 符号付き除 算の結果が符号付き整数にならない場合 (- 2,147,483,648/-1 など ) にも発生 . 17 アラインメントチェック (Alignment check) フォルト オペランドのアドレスが正しくアラインされて いない場合に発生 18 マシンチェック アボート マシンチェック機構が CPU やバスのエラーを 検出した場合に発生 . 19 SIMD 浮動小数点例外 (SIMD floating point exception) フォルト CPU に組み込まれている SSE や SSE2 回路 が浮動小数点演算でエラーを検出した場合 に発生 . 20~31 将来のために Intel が予約 ---
  • 8. 例外ベクタと例外ハンドラ (4) ・例外ハンドラ (x86) ベクタ番号 例外 ハンドラ シグナル 0 除算エラー (Divide Error) divide_error() SIGFPE 1 デバッグ例外 (Debug) debug() SIGTRAP 2 マスク不可割り込み (Non-Maskable Interrupt) nmi() --- 3 ブレークポイント (Breakpoint) int3() SIGTRAP 4 オーバーフロー (Overflow) overflow() SIGSEGV 5 Bound 範囲超過 (Bounds check) bounds() SIGSEGV 6 無効オペコード (Invalid opcode) invalid_op() SIGILL 7 デバイス使用不可能 (Device not available) device_not_available() --- 8 ダブルフォルト (Double falult) doublefault_fn() --- 9 コプロセッサセグメントオーバーラン (Coprocessor segment overrun) coprocessor_segment_ove rrun() SIGFPE 10 無効 TSS(Invalid TSS) invalid_TSS() SIGSEGV 11 セグメント不在 (Segment not present) segment_not_present() SIGBUS 12 スタックセグメントフォルト (Stack segment fault) stack_segment() SIGBUS
  • 9. 例外ベクタと例外ハンドラ (5) ・例外ハンドラ (x86) ベクタ番号 例外 ハンドラ シグナル 13 一般保護 (General protection) general_protection() SIGSEGV 14 ページフォルト (Page fault) page_fault() SIGSEGV 15 Intel が予約済み --- --- 16 浮動小数点エラー (Floating point error) coprocessor_error() SIGFPE 17 アラインメントチェック (Alignment check) alignment_check() SIGBUS 18 マシンチェック (Machine check) machine_check() --- 19 SIMD 浮動小数点例外 (SIMD floating point exception) simd_coprocessor_error() SIGFPE
  • 10. 割り込みディスクリプタテーブル (1) ・割り込みディスクリプタテーブル IDT   (Interrupt Descriptor Table) ・割り込みや例外のベクタとハンドラのアドレスの対応を保持 . ・形式は GDT や LDT とほぼ同じ . ・ IDT 最大サイズは 256×8byte=2KB ・ IDT はメモリ上の任意の位置に置くことができる . ・ CPU の idtr レジスタに IDT のベースリニアアドレスとリミットを指定 . ・割り込みを使用する前に lidt アセンブリ命令で初期化する . ・ 40~43bit(type) の内容がディスクリプタの種類を表している . ・ディスクリプタの種類 ・タスクゲート ・割り込みゲート ・トラップゲート Linux では , 割り込み処理に割り込みゲートを使用し , 例外処理にトラップゲートを使用している .
  • 11. 割り込みディスクリプタテーブル (2) ・タスクゲート プロセスの TSS セレクタを置く . 割り込み信号が発生した時に実行中のプロセスの TSS と置き換えられる . ダブルフォルト例外は , カーネルの不正処理を表していて , Linux においてタスクゲートを用いる唯一の例外 .
  • 13. 割り込みディスクリプタテーブル (4) ・トラップゲート 割り込みゲートと同様だが , 別のセグメントに制御を移す間でも , プロセッサが eflags.if フラグを変更しない点で異なる .
  • 14. 割り込み信号発生からハンドラ実行まで (1) ・前提条件  ・カーネルの初期化が完了し ,CPU がプロテクトモードで動作している . 0. ある 1 つの命令を実行後 ,cs/eip レジスタは次に実行すべき命令のアドレ  スが入っている . これを実行する前に , 制御回路は前の命令の実行中に  割り込み・例外が発生していないかを調べる (INTR,NMI を調べる )  発生していれば , 制御回路は以降の処理を進める . 1. 割り込み・例外に対応するベクタ (0≦i≦255) を取得する . 2.idtr レジスタが指す IDT から i 番目のエントリを読み取る .   ( 該当エントリには割り込みゲートかトラップゲートが存在する ) 3.gdtr レジスタから GDT ベースアドレスを取得し ,   GDT 内から IDT エントリのセレクタがさすセグメントディスクリプタを取得 .  このディスクリプタに , 割り込み / 例外ハンドラがあるセグメントのベースア  ドレスがある .
  • 15. 割り込み信号発生からハンドラ実行まで (2) 4. 割り込み元の正当性の確認 . ・ cs レジスタの CPL と GDT 内のセグメントディスクリプタの DPL を比較 .   CPL: 割り込みを発生させたプログラムの現行特権レベル   DPL: セグメントアクセスに必要な特権レベル ・ DPL の特権レベルより CPL の特権レベルの方が低い   ( 値としては ,CPL>DPL)  ⇒一般保護例外 .   割り込みハンドラは , 割り込みを発生させたプログラムより   低い特権レベルでは動作できない . ・ OK  ソフトウェア的に生成された割り込み / 例外の場合 (int n,int 3,into  命令等 ), さらなるセキュリティチェックを行う . ・ CPL と IDT 内のセグメントディスクリプタの DPL を比較 ・ DPL の特権レベルより CPL の特権レベルの方が低い   ( 値としては ,CPL>DPL)  ⇒一般保護例外 .    ユーザアプリケーションによるトラップゲートや割り込み    ゲートへのアクセスを防ぐ .
  • 16. 割り込み信号発生からハンドラ実行まで (3) 5. 特権レベルが変更されているかを調べる . CPL ≠ セグメントディスクリプタの DPL ⇒ 制御回路は新しい特権レベル用のスタックを用意する . a. tr レジスタを読み取り , 実行中のプロセスの TSS にアクセス . b. ss/esp レジスタに ,TSS に置かれている新しい特権レベル用の  論理アドレスを ss/esp に読み込む . c. 古い特権レベル用スタックの論理アドレスを表す ss/esp を ,  新しいスタックに退避 . 6. フォルトが発生した場合 , 例外を発生させた命令の論理アドレスを   cs/eip に読み込む . これで再実行が可能になる . 7. スタックに eflags,cs,eip レジスタの内容を退避する . 8. 例外がハードウェアエラーコードを持っていれば , スタックに退避する . 9.IDT 内の i 番目のエントリにあるセグメントセレクタとゲートディスクリプタの  オフセットフィールドを ,cs/eip レジスタに読み込む .  これが割り込み・例外ハンドラの最初の命令の論理アドレスを表す . push 順 :[ss,esp] → [eflags,cs,eip] → ( ハードウェアエラーコード )
  • 17. ハンドラ実行終了後の処理 iret 命令を実行して , 割り込まれたプロセスに制御を移す . pop 順 :[ss,esp] ← [eflags,cs,eip] ← ( ハードウェアエラーコード ) 1. スタックに退避されている cs,eip,eflags レジスタの値を読み込む . 2. ハンドラの CPL が ,cs の CPL と同じかどうか調べる .   ( 割り込まれたプロセスがハンドラと同じ特権レベルで動作していたか )  ・同じ⇒ iret は実行を終了  ・違う⇒次のステップに進む . 3. スタックから ss/esp レジスタを読み込む .   ( 古い特権レベル用のスタックに戻る ) 4.ds,es,fs,gs セグメントレジスタを調べる .   CPL の特権レベル > DPL の特権レベル ( 値は ,CPL<DPL) となるセグメン  トディスクリプタを参照するセレクタがあれば ,  そのセグメントレジスタをクリア . カーネルルーチンが実行したセグメントを , それより特権レベルが低いプロセスが使用してしまう事を防ぐ . クリアしなければ , カーネル空間にアクセス可能になってしまう .
  • 18. 割り込み・例外処理のネスト (1) ・割り込み / 例外のカーネル実行パスがネストすることもある . ・カーネル実行パスのネストを許可する条件  「割り込みハンドラ実行中に絶対にプロセスを切り替えないこと」 カーネル実行パスを再開させる為に必要なデータは , カレントプロセスのカーネルスタックに積まれる為 , 割り込みハンドラ動作中に , 他のプロセスに切り替えられない . ・例外のほとんどはユーザーモードの時だけ発生 .  ページフォルト例外はカーネルモードでも発生 . システムコールのカーネル実行パス + ページフォルト例外のカーネル実行パス ・割り込みは , カレントプロセスのデータを参照しない . ・割り込みハンドラは , 別の割り込みハンドラや例外ハンドラに  割り込むことがある . ・例外ハンドラが割り込みハンドラに割り込むことはない . ・マルチプロセッサにおいて , 例外用のカーネル実行パスは ,  ある CPU で処理開始された後 , プロセスの切り替えによって ,  別の CPU に移動することもある .
  • 19. 割り込み・例外処理のネスト (2) ・ Linux がカーネル実行パスのネストを許可する理由 1.PIC やデバイスコントローラのスループット向上 . PIC やデバイスコントローラは , CPU から ACK を受取るまで処理を止めたまま . カーネル実行パスを切り替えて動作させると , 他の割り込み処理の 実行中であっても , カーネルが ACK を返すことができる . 2. 優先度レベルがない割り込みモデルを実現できる . 割り込みハンドラは , 他の割り込みハンドラの処理を遅延できる為 , デバイスに優先順位をあらかじめ与えておく必要がない . これにより , カーネルコードが単純化でき , 移植性が向上 .