Enviar búsqueda
Cargar
4章 Linuxカーネル - 割り込み・例外 5
•
0 recomendaciones
•
1,319 vistas
M
mao999
Seguir
Linuxカーネルの割り込み・例外処理(ソフトウェア寄り) ・IDT ・IDTの初期化 kernel ver 4.9.16
Leer menos
Leer más
Software
Denunciar
Compartir
Denunciar
Compartir
1 de 35
Descargar ahora
Descargar para leer sin conexión
Recomendados
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。
Kazuki Onishi
CVE、JVN番号の取得経験者になろう!
CVE、JVN番号の取得経験者になろう!
kazkiti
ゼロから始める自作 CPU 入門
ゼロから始める自作 CPU 入門
Hirotaka Kawata
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
Fixstars Corporation
2章 Linuxカーネル - メモリ管理1
2章 Linuxカーネル - メモリ管理1
mao999
えっ今日はハッキングしてもいいのか?(CTF Web入門)
えっ今日はハッキングしてもいいのか?(CTF Web入門)
otya mura
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
CODE BLUE
0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと
mao999
Recomendados
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。
Kazuki Onishi
CVE、JVN番号の取得経験者になろう!
CVE、JVN番号の取得経験者になろう!
kazkiti
ゼロから始める自作 CPU 入門
ゼロから始める自作 CPU 入門
Hirotaka Kawata
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
Fixstars Corporation
2章 Linuxカーネル - メモリ管理1
2章 Linuxカーネル - メモリ管理1
mao999
えっ今日はハッキングしてもいいのか?(CTF Web入門)
えっ今日はハッキングしてもいいのか?(CTF Web入門)
otya mura
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
CODE BLUE
0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと
mao999
V8 javascript engine for フロントエンドデベロッパー
V8 javascript engine for フロントエンドデベロッパー
Taketoshi 青野健利
Verilator勉強会 2021/05/29
Verilator勉強会 2021/05/29
ryuz88
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
apkiban
初心者向けCTFのWeb分野の強化法
初心者向けCTFのWeb分野の強化法
kazkiti
AAをつくろう!
AAをつくろう!
Takami Sato
関数型言語ElixirのIoTシステム開発への展開
関数型言語ElixirのIoTシステム開発への展開
Hideki Takase
Research modeで取得した深度(Depth)データを可視化する
Research modeで取得した深度(Depth)データを可視化する
Soichiro Sugimoto
カルマンフィルタ入門
カルマンフィルタ入門
Yasunori Nihei
知っておきたいSpring Batch Tips
知っておきたいSpring Batch Tips
ikeyat
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例
Fixstars Corporation
バグハンターの哀しみ
バグハンターの哀しみ
Masato Kinugawa
ネットワークOS野郎 ~ インフラ野郎Night 20160414
ネットワークOS野郎 ~ インフラ野郎Night 20160414
Kentaro Ebisawa
機械学習工学の進展と課題 2021
機械学習工学の進展と課題 2021
Fuyuki Ishikawa
Map
Map
kikairoya
#logstudy 01 rsyslog入門
#logstudy 01 rsyslog入門
Takashi Takizawa
Integrated Register Allocation introduction
Integrated Register Allocation introduction
Shiva Chen
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
Norishige Fukushima
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
NTT DATA Technology & Innovation
OSS活動の活発さと評価の関係について
OSS活動の活発さと評価の関係について
Takuto Wada
仮想化技術によるマルウェア対策とその問題点
仮想化技術によるマルウェア対策とその問題点
Kuniyasu Suzaki
4章 Linuxカーネル - 割り込み・例外 4
4章 Linuxカーネル - 割り込み・例外 4
mao999
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
Satoshi Mimura
Más contenido relacionado
La actualidad más candente
V8 javascript engine for フロントエンドデベロッパー
V8 javascript engine for フロントエンドデベロッパー
Taketoshi 青野健利
Verilator勉強会 2021/05/29
Verilator勉強会 2021/05/29
ryuz88
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
apkiban
初心者向けCTFのWeb分野の強化法
初心者向けCTFのWeb分野の強化法
kazkiti
AAをつくろう!
AAをつくろう!
Takami Sato
関数型言語ElixirのIoTシステム開発への展開
関数型言語ElixirのIoTシステム開発への展開
Hideki Takase
Research modeで取得した深度(Depth)データを可視化する
Research modeで取得した深度(Depth)データを可視化する
Soichiro Sugimoto
カルマンフィルタ入門
カルマンフィルタ入門
Yasunori Nihei
知っておきたいSpring Batch Tips
知っておきたいSpring Batch Tips
ikeyat
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例
Fixstars Corporation
バグハンターの哀しみ
バグハンターの哀しみ
Masato Kinugawa
ネットワークOS野郎 ~ インフラ野郎Night 20160414
ネットワークOS野郎 ~ インフラ野郎Night 20160414
Kentaro Ebisawa
機械学習工学の進展と課題 2021
機械学習工学の進展と課題 2021
Fuyuki Ishikawa
Map
Map
kikairoya
#logstudy 01 rsyslog入門
#logstudy 01 rsyslog入門
Takashi Takizawa
Integrated Register Allocation introduction
Integrated Register Allocation introduction
Shiva Chen
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
Norishige Fukushima
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
NTT DATA Technology & Innovation
OSS活動の活発さと評価の関係について
OSS活動の活発さと評価の関係について
Takuto Wada
仮想化技術によるマルウェア対策とその問題点
仮想化技術によるマルウェア対策とその問題点
Kuniyasu Suzaki
La actualidad más candente
(20)
V8 javascript engine for フロントエンドデベロッパー
V8 javascript engine for フロントエンドデベロッパー
Verilator勉強会 2021/05/29
Verilator勉強会 2021/05/29
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
初心者向けCTFのWeb分野の強化法
初心者向けCTFのWeb分野の強化法
AAをつくろう!
AAをつくろう!
関数型言語ElixirのIoTシステム開発への展開
関数型言語ElixirのIoTシステム開発への展開
Research modeで取得した深度(Depth)データを可視化する
Research modeで取得した深度(Depth)データを可視化する
カルマンフィルタ入門
カルマンフィルタ入門
知っておきたいSpring Batch Tips
知っておきたいSpring Batch Tips
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例
バグハンターの哀しみ
バグハンターの哀しみ
ネットワークOS野郎 ~ インフラ野郎Night 20160414
ネットワークOS野郎 ~ インフラ野郎Night 20160414
機械学習工学の進展と課題 2021
機械学習工学の進展と課題 2021
Map
Map
#logstudy 01 rsyslog入門
#logstudy 01 rsyslog入門
Integrated Register Allocation introduction
Integrated Register Allocation introduction
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
OSS活動の活発さと評価の関係について
OSS活動の活発さと評価の関係について
仮想化技術によるマルウェア対策とその問題点
仮想化技術によるマルウェア対策とその問題点
Similar a 4章 Linuxカーネル - 割り込み・例外 5
4章 Linuxカーネル - 割り込み・例外 4
4章 Linuxカーネル - 割り込み・例外 4
mao999
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
Satoshi Mimura
NetBSD/i386 割り込みベクタテーブル
NetBSD/i386 割り込みベクタテーブル
kusabanachi
Ext4 filesystem(1)
Ext4 filesystem(1)
Yoshihiro Yunomae
スタート低レイヤー #0
スタート低レイヤー #0
Kiwamu Okabe
initramfsについて
initramfsについて
Kazuhiro Nishiyama
4章 Linuxカーネル - 割り込み・例外 2
4章 Linuxカーネル - 割り込み・例外 2
mao999
core dumpでcode golf
core dumpでcode golf
Nomura Yusuke
SystemV IPC
SystemV IPC
Masami Ichikawa
Gingerbread
Gingerbread
android sola
○○大学の本当にあった怖い話
○○大学の本当にあった怖い話
idkqh7 Nishino
デバドラを書いてみよう!
デバドラを書いてみよう!
Masami Ichikawa
dofilewrite and vn_write
dofilewrite and vn_write
kusabanachi
2011.09.18 v7から始めるunix まとめ
2011.09.18 v7から始めるunix まとめ
Makiko Konoshima
JIT のコードを読んでみた
JIT のコードを読んでみた
y-uti
Interrupts on xv6
Interrupts on xv6
Takuya ASADA
PF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsola
android sola
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
Yasuhiro Ishii
2011.06.11 v7から始めるunix まとめ
2011.06.11 v7から始めるunix まとめ
Makiko Konoshima
PHP AST 徹底解説
PHP AST 徹底解説
do_aki
Similar a 4章 Linuxカーネル - 割り込み・例外 5
(20)
4章 Linuxカーネル - 割り込み・例外 4
4章 Linuxカーネル - 割り込み・例外 4
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
NetBSD/i386 割り込みベクタテーブル
NetBSD/i386 割り込みベクタテーブル
Ext4 filesystem(1)
Ext4 filesystem(1)
スタート低レイヤー #0
スタート低レイヤー #0
initramfsについて
initramfsについて
4章 Linuxカーネル - 割り込み・例外 2
4章 Linuxカーネル - 割り込み・例外 2
core dumpでcode golf
core dumpでcode golf
SystemV IPC
SystemV IPC
Gingerbread
Gingerbread
○○大学の本当にあった怖い話
○○大学の本当にあった怖い話
デバドラを書いてみよう!
デバドラを書いてみよう!
dofilewrite and vn_write
dofilewrite and vn_write
2011.09.18 v7から始めるunix まとめ
2011.09.18 v7から始めるunix まとめ
JIT のコードを読んでみた
JIT のコードを読んでみた
Interrupts on xv6
Interrupts on xv6
PF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsola
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
2011.06.11 v7から始めるunix まとめ
2011.06.11 v7から始めるunix まとめ
PHP AST 徹底解説
PHP AST 徹底解説
4章 Linuxカーネル - 割り込み・例外 5
1.
4 章 Linux
カーネル – 割り込み・例外 5 ・ IDT ・ IDT の初期化 mao Web >https://www.pridact.com Twitter >https://twitter.com/rivarten Mail >official@pridact.com
2.
はじめに 割り込み・例外の話 視点 ・概要 ・ソースコード ソースコードの情報が載っている場合は , 実際にソースコードに目を通しながら資料を見ていっ たほうがいいかもしれません。 今回はソースコードを読み進めていきます。
3.
この資料について ・間違っていたらご指摘をお願い致します。 ・ Linux Kernel
のバージョンは 4.9.16 です。 ・ページタイトルに * 印が付いているページは、 少し踏み込んだ内容になっています。 ざっと全体に目を通したければ、読み飛ばして もらっても構いません。
4.
IDT (1) ・システム初期化時 ,
カーネルが割り込みを許可する前に , ・ idtr レジスタに IDT の先頭アドレスを指定 ・ IDT 内の全エントリを初期化 ・ユーザーモードプロセスが int 命令を使用して 0~255 までの任意ベクタの 割り込みを発行できる為 , 不正な割り込みや例外の発生を防ぐ為に ,IDT の初期化は慎重に行う . Linux における初期化処理 a. 特定の割り込みやトラップのゲートディスクリプタの DPL を 0 に設定し , 不正な割り込み信号には一般保護例外を発生させるようにする . b. ユーザーモードプロセスが特定の例外を直接生成できるようにする為に , 割り込みやトラップゲートのディスクリプタの DPL を 3 に設定し , 例外を発生させることを可能にする .
5.
IDT (2) ・ Intel
が提供している割り込みディスクリプタ ・割り込みゲートディスクリプタ ・トラップゲートディスクリプタ ・タスクゲートディスクリプタ
6.
IDT (3) ・ Linux
が提供している割り込みディスクリプタ ・割り込みゲート Intel の割り込みゲート .DPL=0. 割り込みハンドラはすべて割り込みゲートで実装 . ユーザーモードからアクセス不可 . ・システムトラップゲート ( 旧システムゲート ) Intel のトラップゲート .DPL=3. ベクタ 4,5,128 の例外ハンドラはシステムトラップゲートで実装 . into,bound,int $0x80 アセンブリ命令はユーザーモードでも使用可 . ・システム割り込みゲート Intel の割り込みゲート .DPL=3. ベクタ 3 の例外ハンドラはシステム割り込みゲートで実装 . int3 アセンブリ命令はユーザーモードでも実行可 . ・トラップゲート Intel のトラップゲート .DPL=0. ほとんどの例外ハンドラはトラップゲートで実装 . ユーザーモードからアクセス不可 . ・タスクゲート Intel のタスクゲート .DPL=0. ダブルフォルト例外ハンドラの実装 .
7.
IDT の初期化 (1) ・
IDT へのゲート登録 ・ set_intr_gate(n,addr) ・ set_system_trap_gate(n,addr) ( 旧 set_system_gate) ・ set_system_intr_gate(n,addr) ・ set_trap_gate(n,addr) ・ set_task_gate(n,addr)
8.
IDT の初期化 (2) ・
IDT へのゲート登録 ・ set_intr_gate(n,addr) IDT の n 番目のエントリに割り込みゲートを登録する . ゲート内のセグメントセレクタには ,__KERNEL_CS が設定される . オフセットフィールドには , 割り込みハンドラのアドレス addr を設定 . DPL=0 で設定される . ※ すべての割り込みハンドラをこの関数で登録 . [ver4.9.16 arch/x86/include/asm/desc.h:371] #define set_intr_gate(n, addr) do { set_intr_gate_notrace(n, addr); _trace_set_gate(n, GATE_INTERRUPT, (void*)trace_##addr, 0, 0, __KERNEL_CS); } while (0) [ver4.9.16 arch/x86/include/asm/desc.h:364] #define set_intr_gate_notrace(n, addr) do { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_INTERRUPT, (void *)addr, 0, 0, __KERNEL_CS); } while (0)
9.
IDT の初期化 (3) ・
IDT へのゲート登録 ・ set_system_trap_gate(n,addr) IDT の n 番目のエントリにトラップゲートを登録する . ゲート内のセグメントセレクタには ,__KERNEL_CS が設定される . オフセットフィールドには , 例外ハンドラのアドレス addr を設定 . DPL=3 で設定される . ベクタ 4,5,128 がこのゲート . [ver4.9.16 arch/x86/include/asm/desc.h:408] static inline void set_system_trap_gate(unsigned int n, void *addr) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS); }
10.
IDT の初期化 (4) ・
IDT へのゲート登録 ・ set_system_intr_gate(n,addr) IDT の n 番目のエントリに割り込みゲートを登録する . ゲート内のセグメントセレクタには ,__KERNEL_CS が設定される . オフセットフィールドには , 例外ハンドラのアドレス addr を設定 . DPL=3 で設定される . ベクタ 3 がこのゲート . [ver4.9.16 arch/x86/include/asm/desc.h:402] static inline void set_system_intr_gate(unsigned int n, void *addr) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS); }
11.
IDT の初期化 (5) ・
IDT へのゲート登録 ・ set_trap_gate(n,addr) set_system_trap_gate と同じだが ,DPL=0 で設定する . 殆どの例外ハンドラがこのゲート . [ver4.9.16 arch/x86/include/asm/desc.h:414] static inline void set_trap_gate(unsigned int n, void *addr) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS); }
12.
IDT の初期化 (6) ・
IDT へのゲート登録 ・ set_task_gate(n,addr) IDT の n 番目のエントリにタスクゲートを登録する . ゲート内のセグメントセレクタには , GDT 内の TSS セグメントのインデックスが設定される . この TSS セグメントは , 実行する関数を含んでいるセグメント . オフセットフィールドには ,0 を設定 . DPL=0. ダブルフォルト例外ハンドラがこのゲート . [ver4.9.16 arch/x86/include/asm/desc.h:420] static inline void set_task_gate(unsigned int n, void *addr) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3)); }
13.
IDT の初期化 (7)
* ・ IDT へのゲート登録 ・全ゲート共通 (1) [ver4.9.16 arch/x86/include/asm/desc.h:344] static inline void _set_gate(int gate, unsigned type, void *addr, unsigned dpl, unsigned ist, unsigned seg) { gate_desc s; pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); write_idt_entry(idt_table, gate, &s); write_trace_idt_entry(gate, &s); } [ver4.9.16 arch/x86/include/asm/desc.h:55] CONFIG_X86_64 static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, unsigned dpl, unsigned ist, unsigned seg) { gate->offset_low = PTR_LOW(func); gate->segment = __KERNEL_CS; gate->ist = ist; gate->p = 1; gate->dpl = dpl; gate->zero0 = 0; gate->zero1 = 0; gate->type = type; gate->offset_middle = PTR_MIDDLE(func); gate->offset_high = PTR_HIGH(func); }
14.
IDT の初期化 (8)
* ・ IDT へのゲート登録 ・全ゲート共通 (2) [ver4.9.16 arch/x86/include/asm/desc.h:71] #else (CONFIG_X86_32 static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, unsigned dpl, unsigned ist, unsigned seg) { gate->a = (seg << 16) | (base & 0xffff); gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl << 5)) & 0xff) << 8); } [ver4.9.16 arch/x86/include/asm/desc.h:324] static inline void _trace_set_gate(int gate, unsigned type, void *addr, unsigned dpl, unsigned ist, unsigned seg) { gate_desc s; pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); write_trace_idt_entry(gate, &s); } [ver4.9.16 arch/x86/include/asm/desc.h:106] #define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g) [ver4.9.16 arch/x86/include/asm/desc.h:119] static inline void native_write_idt_entry(gate_desc *idt, int entry, const gate_desc *gate) { memcpy(&idt[entry], gate, sizeof(*gate)); }
15.
IDT の初期化 (9) ・コンピュータの起動直後
, まだリアルモードで動作している時にも , BIOS は IDT を初期化して使用している .(1 度目の初期化 ) ・ Linux が起動すると ,Linux は BIOS ルーチンを使用しない為 , IDT を RAM の別の領域へ移動させ ,2 度目の初期化を行う . ・ idt_table テーブル IDT の 256 エントリのテーブル [ver4.9.16 arch/x86/kernel/traps.c:82] gate_desc idt_table[NR_VECTORS] __page_aligned_bss; ・ gate_desc/desc_struct 構造体 [ver4.9.16 arch/x86/include/asm/desc_defs.h:22] struct desc_struct { union { struct { unsigned int a; unsigned int b; }; struct { u16 limit0; #bit15-0(limit15-0) u16 base0; #bit31-16(base15-0) unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1; #bit39-32(base23-16) #bit43-40(type)/bit44(S) #bit46-45(DPL)/bit47(P) unsigned limit:4, avl: 1, l: 1, d: 1, g: 1, base2: 8; }; #bit51-48(limit19-16) #bit52(AVL)/bit53(L)/bit54(D) #bit55(G)/bit63-56(base31-24) }; } __attribute__((packed)); ※ 参考 2 章 Linux カーネル – メモリ管理 1 アドレス変換機能 x86 におけるセグメンテーション
16.
IDT の初期化 (10) ・
idt_descr 変数 IDT の大きさとアドレス . システム初期化段階で , カーネルが lidt アセンブリ命令で idtr レジスタを設定する時に使用 . [ver4.9.16 arch/x86/kernel/head_32.S:727] .data .globl boot_gdt_descr .globl idt_desc ALIGN … boot_gdt_descr: … idt_descr: .word IDT_ENTRIES*8-1 .long idt_table
17.
IDT の初期化 (11) ・
1 度目の初期化 (1) - ゼロ埋め ブートローダーから起動 --> X+0x200: カーネルセットアップコード (arch/x86/boot/header.S) : _start --> カーネルセットアップコード ヘッダ (arch/x86/boot/compressed/head_32.S:63) : startup_32 --> カーネルセットアップコード メイン (init/main.c) : main() [ver 4.9.16 arch/x86/boot/main.c:135] void main(void){ … go_to_protected_mode() } [ver 4.9.16 arch/x86/boot/pm.c:104] void go_to_protected_mode(void) { readmode_switch_hook(); if (enable_a20()) { die(); } reset_coprocessor(); mask_all_interrupts(); setup_idt(); setup_gdt(); protected_mode_jump(boot_params.hdr.code32_start, (u32)&boot_params + (ds() << 4)); //0x00100000 にジャンプ } [ver4.9.16 arch/x86/boot/pm.c:95] static void setup_idt(void){ staic const struct gdt_ptr null_idt = {0, 0}; asm volatile(“lidtl %0” : : “m” (null_idt)); }
18.
IDT の初期化 (12) ・
1 度目の初期化 (2) - setup_once 関数呼出し前後 カーネルセットアップコードメイン ->init/main.c:main() ->init/main.c:protected_mode_jump(boot_params.hdr.code32_start,(u32)&boot_params + (ds() << 4) ->code32_start= 0x00100000(default for big kernel) = startup_32(arch/x86/kernel/head_32.S) カーネル初期化時に , アセンブリ言語で記述された setup_once 関数を呼び出す . idt_table の 256 エントリ全てを ignore_int() 割り込みハンドラを指すように初期化 . [ver4.9.16 arch/x86/kernel/head_32.S:89] __HEAD ENTRY(startup_32) #BootStrap Processor エントリポイント … jmp default_entry … ENTRY(startup_32_smp) #Secondary Processor エントリポイント … default_entry: …enable_paging へジャンプ enable_paging: … movl setup_once_ref,%eax # 一度呼ばれたら ,setup_once_ref には 0 が代入されている andl %eax,%eax jz 1f #eax が 0 だったら前方の 1 にジャンプ -> set_once 関数を呼ばない call *%eax 1: … jmp *(initial_code) … ENTRY(initial_code) .long i386_start_kernel ENTRY(setup_once_ref) .long setup_once
19.
IDT の初期化 (13) ・
1 度目の初期化 (3) – setup_once 初期例外ハンドラ カーネル初期化時に , アセンブリ言語で記述された setup_once 関数を呼び出す . idt_table の 256 エントリ全てを ignore_int() 割り込みハンドラを指すように初期化 . [ver4.9.16 arch/x86/kernel/head_32.S:611] __INIT setup_once: … # 初期例外ハンドラの設定 movl $idt_tale, %edi #idt_table の先頭ポインタを edi に格納 movl $early_idt_handler_array, %eax #early_idt_handler_array の先頭ポインタを eax に格納 movl $NUM_EXCEPTION_VECTORS, %ecx #NUM_EXCEPTION_VECTORS(=32) を ecx に格納 #loop 命令は ecx をループカウンタとして使用 1: movl %eax, (%edi) #idt_table[ i ].a = early_idt_handler_array[ j ] movl %eax,4(%edi) #idt_table[ i ].b = early_idt_handler_array[ j ] movl $(0x8E000000 + __KERNEL_CS), 2(%edi) #0x8E000000 + __KERNEL_CS = 0x8E000060 #idt_table[ i ].base0 = 0x0060 #idt_table[ i ] .base1=0x00, .type:0xE, .s:0, .dpl:0, .p:1 add $EARLY_IDT_HANDLER_SIZE, %eax #i ++ addl $8, %edi #j ++ loop 1b #ecx = 0 ⇒ ループ終了 …
20.
IDT の初期化 (14) ・
1 度目の初期化 (4) - early_idt_handler_array [ver4.9.16 arch/x86/kernel/head_32.S:610] ENTRY(early_idt_handler_array) i = 0 .rept NUM_EXCEPTION_VECTORS .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1 pushl $0 # Dummy error code, to make stack frame uniform .endif pushl $i #20(%esp) Vector Number jmp early_idt_handler_common i = i + 1 .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - . , 1, 0xcc .endr < コンパイル時 > ・ NUM_EXCEPTION_VECTORS の回数分 ,[.rept] ~ [.endr] ディレクティブ内の処理を機械語として展開 ・ .fill で ,EARLY_IDT_HANDLER_SIZE(=9)byte 領域の残りの部分を 0xCC で埋める < 実行時 > ・ [arch/x86/include/asm/segment.h:211] #define EXCEPTION_ERRCODE_MASK 0x0027d00 例外発生時に制御回路がハードウェアエラーコードを自動的にスタックに積まない例外ベクタの指定 0000 0000 0000 0010 0111 1101 0000 0000 ⇒ ベクタ番号 8, 10, 11, 12, 13, 14, 17 この場合は ,push $0 で 0 をスタックに積む ・ push $i で例外ベクタ番号をスタックに積む ・ early_idt_handler_common にジャンプして , 初期段階の共通割り込みハンドラへの処理へ移るようにする ・ early_idt_handler_common は early_fixup_exception() 関数 [ver4.9.16 arch/x86/mm/extable.c:129] を呼び出す ・ early_fixup_exception() 関数は ,fixup_exception() 関数を呼び出して修復可能ならば例外を修復する .
21.
IDT の初期化 (15) ・
1 度目の初期化 (5) – setup_once 初期割り込みハンドラ … # 初期割り込みハンドラの設定 movl $256 – NUM_EXCEPTION_VECTORS, %ecx #loop 命令のループカウンタとして使用 movl $ignore_int, %edx #edx に ignore_int のアドレスを格納 movl $(__KERNEL_CS << 16), %eax #eax に __KERNEL_CS(0x60) を #16bit 左シフトして格納 (0x00600000) movl %dx, %ax #16bit 版 ignore_int のオフセットを ax に格納 # これにアクセスするときは , #cs に selector=0x10=BOOT_CS を指定 #eax=0x0060[?][?][?][?] movw $0x8E00, %dx #interrupt gate – dpl=0, present #edx=[?][?][?][?]8E00 2: movl %eax, (%edi) #idt_table[ i ].a = early_idt_handler_array[ j ] movl %edx, 4(%edi) #idt_table[ i ].b = ignore_int #idt_table[ i ] .base1=0x00, .type:0xE, .s:0, .dpl:0, .p:1 #idt_table[ i ] .limit:[?], avl: [?], l: [?], d: [?], g: [?], base2: [?]; add $8, %edi #j ++ loop 2b #ifdef CONFIG_CC_STACKPROTECTOR … #endif andl $0,setup_once_ref # 一回設定すると ,setup_once_ref を 0 にする ret # 呼び出し元に戻る
22.
IDT の初期化 (16) ・
1 度目の初期化 (6) - ignore_int アセンブリ言語で記述された何もしない割り込みハンドラ . 1. いくつかのレジスタをスタックに退避 2.printk() 関数を用いて , 「 Unknown interrupt or fault at : … 」 というシステムメッセージ表示 3. スタックに退避しておいたレジスタの値を復帰 . 4.iret 命令を実行して , 割り込まれたプログラムを再開させる . [ver4.9.16 arch/x86/kernel/head_32.S:610] ALIGN ignore_int: cld #ifdef CONFIG_PRINTK …printk 関数を呼び出す #endif iret
23.
IDT の初期化 (17) ・
1 度目の初期化 (7) - 初期 IDT の有効化 startup_32/startup_32_smp -> default_entry -> enable_paging [ver 4.9.16 arch/x86/kernel/head_32.S:414] … call *%eax #setup_once を呼び出す . 一度設定していたら呼び出さない . 1: … i486 かどうかチェック . 最低でも i486 でないといけない is486: movl $0x50022, %ecx #AM, WP, NE, MP をセット movl %cr0, %eax andl $0x80000011, %eax #PG, PE, ET を保存 orl %ecx, %eax movl %eax, %cr0 #cr0 に設定を反映 lgdt early_gdt_descr lidt idt_descr ljmp $(__KERNEL_CS), $1f 1: movl $(__KERNEL_DS), %eax # セグメントレジスタを再読み込み movl %eax, %ss ・ ds,es を __USER_DS で初期化 ・ fs を __KERNEL_PERCPU で初期化 ・ gs を __KERNEL_STACK_CANARY で初期化 ・ LDT をクリア pushl $0 #fake return address for unwinder jmp *(initial_code) #BootStrapProcessor -> i386_start_kernel へジャンプ #ApplicationProcessor -> start_secondary へジャンプ
24.
IDT の初期化 (18) ・
2 度目の初期化 (1) - early_trap_init トラップゲートディスクリプタ初期化 startup_32 -> i386_start_kernel -> start_kernel startup_64 -> x86_64_start_kernel -> start_kernel -> local_irq_disable(), setup_arch()->early_trap_init(), trap_init(), early_irq_init(), init_IRQ(), local_irq_enable() [ver 4.9.16 arch/x86/kernel/traps.c:897] 896 /* Set of traps needed for early debugging. */ 897 void __init early_trap_init(void) 898 { 911 set_intr_gate_notrace(X86_TRAP_DB, debug); 912 /* int3 can be called from all */ 913 set_system_intr_gate(X86_TRAP_BP, &int3); 914 #ifdef CONFIG_X86_32 915 set_intr_gate(X86_TRAP_PF, page_fault); 916 #endif 917 load_idt(&idt_descr); 918 } [ver 4.9.16 arch/x86/include/asm/traps.h:129] X86_TRAP_DB :1 Debug X86_TRAP_BP :3 BreakPoint X86_TRAP_PF :14 PageFault [ver 4.9.16 arch/x86/include/asm/desc.h:93] #define load_idt(dtr) native_load_idt(dtr) [ver 4.9.16 arch/x86/include/asm/desc.h:221] static inline void native_load_idt(const struct desc_ptr *dtr){ asm volatile(“lidt %0”::”m” (*dtr)); }
25.
IDT の初期化 (19) ・
2 度目の初期化 (1) - trap_init 割り込みハンドラ設定 (1) startup_32 -> i386_start_kernel -> start_kernel startup_64 -> x86_64_start_kernel -> start_kernel -> local_irq_disable(), setup_arch()->early_trap_init(), trap_init(), early_irq_init(), init_IRQ(), local_irq_enable() [ver 4.9.16 arch/x86/kernel/traps.c:927] 927 void __init trap_init(void) 928 { 929 int i; 939 set_intr_gate(X86_TRAP_DE, divide_error); 940 set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK); 941 /* int4 can be called from all */ 942 set_system_intr_gate(X86_TRAP_OF, &overflow); 943 set_intr_gate(X86_TRAP_BR, bounds); 944 set_intr_gate(X86_TRAP_UD, invalid_op); 945 set_intr_gate(X86_TRAP_NM, device_not_available); 946 #ifdef CONFIG_X86_32 947 set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS); 948 #else 949 set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK); 950 #endif 951 set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun); 952 set_intr_gate(X86_TRAP_TS, invalid_TSS); 953 set_intr_gate(X86_TRAP_NP, segment_not_present); 954 set_intr_gate(X86_TRAP_SS, stack_segment); 955 set_intr_gate(X86_TRAP_GP, general_protection); 956 set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug); 957 set_intr_gate(X86_TRAP_MF, coprocessor_error); 958 set_intr_gate(X86_TRAP_AC, alignment_check);
26.
IDT の初期化 (19) ・
2 度目の初期化 (1) - trap_init 割り込みハンドラ設定 (2) startup_32 -> i386_start_kernel -> start_kernel startup_64 -> x86_64_start_kernel -> start_kernel -> local_irq_disable(), setup_arch()->early_trap_init(), trap_init(), early_irq_init(), init_IRQ(), local_irq_enable() [ver 4.9.16 arch/x86/kernel/traps.c:927] 959 #ifdef CONFIG_X86_MCE 960 set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK); 961 #endif 962 set_intr_gate(X86_TRAP_XF, simd_coprocessor_error); 963 964 /* Reserve all the builtin and the syscall vector: */ 965 for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) 966 set_bit(i, used_vectors); 967 968 #ifdef CONFIG_IA32_EMULATION 969 set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_compat); 970 set_bit(IA32_SYSCALL_VECTOR, used_vectors); 971 #endif 972 973 #ifdef CONFIG_X86_32 974 set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_32); 975 set_bit(IA32_SYSCALL_VECTOR, used_vectors); 976 #endif 977 978 /* 979 * Set the IDT descriptor to a fixed read-only location, so that the 980 * "sidt" instruction will not leak the location of the kernel, and 981 * to defend the IDT against arbitrary memory write vulnerabilities. 982 * It will be reloaded in cpu_init() */ #F00F バグ対策 983 __set_fixmap(FIX_RO_IDT, __pa_symbol(idt_table), PAGE_KERNEL_RO); 984 idt_descr.address = fix_to_virt(FIX_RO_IDT);
27.
IDT の初期化 -
F00F バグ * ・ Pentium の一部モデル ( 古いモデル ) に F00F バグが存在 . 対策 : 本物の IDT を , 読み出し専用で 固定マップリニアアドレス FIX_RO_IDT にマッピングし , このリニアアドレスを指すように idtr レジスタを初期化 . この領域の物理メモリに直接アクセス出来る様にすることで , 当該モデルでハングアップがなくなる .
28.
IDT の初期化 -
F00F バグ * ・ Pentium の一部モデルでは F00F バグが存在 . Pentium,Pentium MMX,Pentium オーバードライブプロセッサの , ある世代以前のモデルにある設計上の不具合 . Pentium Pro 以降はこのバグの影響はない . ・問題を起こす機械語バイト列「 F0 0F C7 C8 」の先頭 2byte に由来 . ・「ロックされた CMPXCHG8B インストラクションでの不正なオペランド」 と Intel は呼んでいる ・「 F0 0F C7 C8 」のニーモニック lock cmpxchg8b eax ・ cmpxchg8b 命令 オペランドとして指定されたアドレスのメモリ上の 8byte 領域を得る . edx:eax の値とメモリ上の 8byte 値を比較 一致 → Z フラグ =1,ecx:ebx の値を 8byte 領域にストア . 不一致 → Z フラグ =0,8byte データを edx:eax にロード ・ cmpxchg8b のオペランドにレジスタを指定すると「不正命令例外」 → 例外ハンドラが呼ばれる . ・ lock プレフィクスをつけると以後のメモリアクセスが抑制される為 , → 例外ハンドラを実行できず , この段階でハングアップし , 一切の命令を実行せず , 割り込みも受け付けなくなってしまう . ・ Linux ではカーネル 2.0.32/2.1.64 以降で対策が取られている . https://ja.wikipedia.org/wiki/Pentium_F00F_バグ
29.
IDT の初期化 (19) ・
2 度目の初期化 (1) - trap_init 割り込みハンドラ設定 (3) startup_32 -> i386_start_kernel -> start_kernel startup_64 -> x86_64_start_kernel -> start_kernel -> local_irq_disable(), setup_arch()->early_trap_init(), trap_init(), early_irq_init(), init_IRQ(), local_irq_enable() [ver 4.9.16 arch/x86/kernel/traps.c:927] 985 986 /* 987 * Should be a barrier for any external CPU state: 988 */ 989 cpu_init(); 990 991 /* 992 * X86_TRAP_DB and X86_TRAP_BP have been set 993 * in early_trap_init(). However, ITS works only after 994 * cpu_init() loads TSS. See comments in early_trap_init(). 995 */ 996 set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK); 997 /* int3 can be called from all */ 998 set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); 999 1000 x86_init.irqs.trap_init(); #no operation. x86_init_noop() 1001 1002 #ifdef CONFIG_X86_64 1003 memcpy(&debug_idt_table, &idt_table, IDT_ENTRIES * 16); 1004 set_nmi_gate(X86_TRAP_DB, &debug); 1005 set_nmi_gate(X86_TRAP_BP, &int3); 1006 #endif 1007 }
30.
IDT の初期化 (19) ・
2 度目の初期化 (1) - early_irq_init 割り込みゲートディスクリプタ初期化 startup_32 -> i386_start_kernel -> start_kernel startup_64 -> x86_64_start_kernel -> start_kernel start_kernel -> local_irq_disable(), setup_arch(), trap_init(), early_irq_init(), init_IRQ(), local_irq_enable() [ver 4.9.16 kernel/irq/irqdesc.c:504] 504 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { 505 [0 ... NR_IRQS-1] = { 506 .handle_irq = handle_bad_irq, 507 .depth = 1, 508 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), 509 } 510 }; [ver 4.9.16 include/linux/irqdesc.h:51] 割り込みディスクリプタ struct irq_desc の定義 [ver 4.9.16 kernel/irq/irqdesc.c:512] 512 int __init early_irq_init(void) 513 { 514 int count, i, node = first_online_node; 515 struct irq_desc *desc; 517 init_irq_default_affinity(); 519 printk(KERN_INFO "NR_IRQS:%dn", NR_IRQS); 521 desc = irq_desc; 522 count = ARRAY_SIZE(irq_desc); 524 for (i = 0; i < count; i++) { 525 desc[i].kstat_irqs = alloc_percpu(unsigned int); 526 alloc_masks(&desc[i], GFP_KERNEL, node); 527 raw_spin_lock_init(&desc[i].lock); 528 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); 529 desc_set_defaults(i, &desc[i], node, NULL, NULL); 530 } 531 return arch_early_irq_init(); 532 }
31.
IDT の初期化 (20) ・
2 度目の初期化 (2) - init_IRQ BSP のベクタと irq_desc を紐付け start_kernel -> local_irq_disable(), setup_arch(), trap_init(), early_irq_init(), init_IRQ(), local_irq_enable() [ver 4.9.16 arch/x86/kernel/irqinit.c:84] void __init init_IRQ(void) int i; for (i = 0; i < nr_legacy_irqs(); i++) #legacy pic(8259A) の IRQ 数分だけ設定 per_cpu(vector_irq, 0)[ISA_IRQ_VECTOR(i)] = irq_to_desc(i); #BSP のベクタと irq_desc を紐付け x86_init.irqs.intr_init(); } [ver 4.9.16 arch/x86/include/asm/hw_irq.h:180] typedef struct irq_desc* vector_irq_t[NR_VECTORS]; DECLARE_PER_CPU(vector_irq_t, vector_irq); [ver 4.9.16 arch/x86/kernel/irqinit.c:54] DEFINE_PER_CPU(vector_irq_t, vector_irq) = { [0 ... NR_VECTORS – 1] = VECTOR_UNUSED, }; [ver 4.9.16 kernel/irq/irqdesc.c:534] struct irq_desc *irq_to_desc(unsigned int irq) { return (irq < NR_IRQS) ? irq_desc + irq : NULL; } EXPORT_SYMBOL(irq_to_desc);
32.
IDT の初期化 (21) ・
2 度目の初期化 (3) - x86_init.irqs.intr_init start_kernel -> local_irq_disable(), setup_arch(), trap_init(), early_irq_init(), init_IRQ(), local_irq_enable() init_IRQ -> x86_init.irqs.intr_init() = native_init_IRQ() [ver 4.9.16 arch/x86/kernel/irqinit.c:167] 167 void __init native_init_IRQ(void) 168 { 169 int i; 172 x86_init.irqs.pre_vector_init(); # デバイス初期化 174 apic_intr_init(); #APIC のベクタ初期化 181 i = FIRST_EXTERNAL_VECTOR; #0x20(32) 182 #ifndef CONFIG_X86_LOCAL_APIC 183 #define first_system_vector NR_VECTORS 184 #endif # この時点までで設定されていない未使用ベクタのハンドラを設定 ( 通常の割り込みハンドラ設定 ) 185 for_each_clear_bit_from(i, used_vectors, first_system_vector) { #first_system_vector: 256 or 0xef 186 /* IA32_SYSCALL_VECTOR could be used in trap_init already. */ 187 set_intr_gate(i, irq_entries_start + 188 8 * (i - FIRST_EXTERNAL_VECTOR)); 189 } 190 #ifdef CONFIG_X86_LOCAL_APIC 191 for_each_clear_bit_from(i, used_vectors, NR_VECTORS) 192 set_intr_gate(i, spurious_interrupt); # スプリアス割り込みのハンドラを設定 193 #endif 195 if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs()) 196 setup_irq(2, &irq2); # IR2 のハンドラを設定 198 #ifdef CONFIG_X86_32 199 irq_ctx_init(smp_processor_id()); #hardirq と softirq を処理する為の CPU 毎のスタックを確保 200 #endif 201 }
33.
IDT の初期化 (22) ・
2 度目の初期化 (4) - irq_entries_start / common_interrupt start_kernel -> local_irq_disable(), setup_arch(), trap_init(), early_irq_init(), init_IRQ(), local_irq_enable() init_IRQ -> x86_init.irqs.intr_init() = native_init_IRQ() [ver 4.9.16 arch/x86/entry/entry_32.S:603] 603 /* 604 * Build the entry stubs with some assembler magic. 605 * We pack 1 stub into every 8-byte block. 606 */ 607 .align 8 608 ENTRY(irq_entries_start) 609 vector=FIRST_EXTERNAL_VECTOR #0x20 610 .rept (FIRST_SYSTEM_VECTOR - FIRST_EXTERNAL_VECTOR) 611 pushl $(~vector+0x80) /* Note: always in signed byte range */ 612 vector=vector+1 613 jmp common_interrupt 614 .align 8 615 .endr 616 END(irq_entries_start) 617 618 /* 619 * the CPU automatically disables interrupts when executing an IRQ vector, 620 * so IRQ-flags tracing has to follow that: 621 */ 622 .p2align CONFIG_X86_L1_CACHE_SHIFT 623 common_interrupt: 624 ASM_CLAC 625 addl $-0x80, (%esp) /* Adjust vector into the [-256, -1] range */ 626 SAVE_ALL 627 TRACE_IRQS_OFF 628 movl %esp, %eax 629 call do_IRQ 630 jmp ret_from_intr 631 ENDPROC(common_interrupt)
34.
IDT の初期化 (23) ・
2 度目の初期化 (5) - IDT の有効化 start_kernel() [ver 4.9.16 init/main.c:479] BootStrap Processor のみ -> rest_init() [ver 4.9.16 init/main.c:383] -> kernel_init スレッド [ver 4.9.16 init/main.c:939] -> kernel_init_freeable() [ver 4.9.16 init/main.c:986] -> smp_init() [ver 4.9.16 kernel/smp.c:552] 各 CPU 専用の初期化処理 . -> cpu_up(cpu) [ver 4.9.16 kernel/cpu.c:1093] BSP は boot_cpu_init() で CPUHP_ONLINE になる為 ,smp_init 内でのこの関数呼出しは ApplicationProcessor のみ . -> do_cpu_up( 呼出し引数: cpu, CPUHP_ONLINE) [ver 4.9.16 kernel/cpu.c:1063] -> _cpu_up( 呼出し引数: cpu, 0, target) [ver 4.9.16 kernel/cpu.c:1005] -> cpuhp_up_callback( 呼出し引数: cpu, st, CPUHP_BRINGUP_CPU) [ver 4.9.16 kernel/cpu.c:485] st->state が以下の順で変わっていく CPUHP_OFFLINE->CPUHP_CREATE_THREADS->CPUHP_PREF_PREPARE ->CPUHP_WORKQUEUE_PREP->CPUHP_HRTIMERS_PREPARE->CPUHP_SMPCFD_PREPARE ->CPUHP_RELAY_PREPARE->CPUHP_SLAB_PREPARE->CPUHP_RCUTREE_PREP ->CPUHP_NOTIFY_PREPARE->CPUHP_BRINGUP_CPU -> … -> cpuhp_invoke_callback( 呼出し引数: cpu, st->state, true, NULL) [ver 4.9.16 kernel/cpu.c:122] 各 state の startup.single を呼び出す . cb( 呼出し引数: cpu) [ver 4.9.16 kernel/cpu.c:136] = bringup_cpu( 呼出し引数: cpu) [ver 4.9.16 kernel/cpu.c:421] 以降は CPUHP_BRINGUP_CPU の場合 -> __cpu_up( 呼出し引数: cpu, tidle) [ver 4.9.16 arch/x86/include/asm/smp.h:93] -> smp_ops.cpu_up( 呼出し引数: cpu, tidle) [ver 4.9.16 arch/x86/include/asm/smp.h:95] = native_cpu_up( 呼出し引数: cpu, tidle) [ver 4.9.16 arch/x86/kernel/smpboot.c:1070] -> do_boot_cpu( 呼出し引数: apicid, cpu, tidle) [ver 4.9.16 arch/x86/kernel/smpboot.c:949] -> apic->wakeup_secondary_cpu( 呼出し引数: apicid, start_ip) APIC あり wakeup_cpu_via_init_nmi( 呼出し引数: cpu, start_ip, apicid, &cpu0_nmi_registered) APIC なし -> startup_32_smp -> start_secondary() [ver 4.9.16 arch/x86/kernel/smpboot.c:213] Application Processor のみ -> cpu_init() (CONFIG_X86_64) [ver 4.9.16 arch/x86/kernel/cpu/common.c:1470] cpu_init() (CONFIG_X86_32) [ver 4.9.16 arch/x86/kernel/cpu/common.c:1573] -> load_current_idt() [ver 4.9.16 arch/x86/include/asm/desc.h:495] -> switch_to_new_gdt(cpu) [ver 4.9.16 arch/x86/kernel/cpu/common.c:450]
35.
IDT の初期化 (24) ・
2 度目の初期化 (5) - IDT の有効化 -> load_current_idt() [ver 4.9.16 arch/x86/include/asm/desc.h:495] -> load_idt(&idt_descr) [ver 4.9.16 arch/x86/include/asm/desc.h:93] -> switch_to_new_gdt(cpu) [ver 4.9.16 arch/x86/kernel/cpu/common.c:450] -> load_gdt(&gdt_descr) [ver 4.9.16 arch/x86/include/asm/desc.h:92] -> native_load_gdt(dtr) [ver 4.9.16 arch/x86/include/asm/desc.h:216] -> asm volatile(“lgdt %0”::”m” (*dtr));[ver 4.9.16 arch/x86/include/asm/desc.h:218]
Descargar ahora