Closed18

自作OSで不定期にTriple Faultが発生する原因の調査

ピン留めされたアイテム
junyaUjunyaU

なぜか不定期にこれが発生してQEMUが再起動してしまうので調査

junyaUjunyaU

When a fault occurs, the CPU invokes an exception handler. If a fault occurs while trying to invoke the exception handler, that's called a double fault, which the CPU tries to handle with yet another exception handler. If that invocation results in a fault too, the system reboots with a triple fault.

junyaUjunyaU

Triple Fault時のレジスタの状況

RAX=000000003fb9a000 RBX=0000000000000000 RCX=000000000053b2b0 RDX=00000000000002c0
RSI=000000003c1ecb18 RDI=000000003e1fa850 RBP=000000000080fce0 RSP=000000000080fca0
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=00000000001d6eec RFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 0000000000000000 00000000 00000000
CS =0008 0000000000000000 00000fff 00a09a00 DPL=0 CS64 [-R-]
SS =0000 0000000000000000 00000000 00000000
DS =0000 0000000000000000 00000000 00000000
FS =0000 0000000000000000 00000000 00000000
GS =0000 0000000000000000 00000000 00000000
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0028 000000000053a090 00067fff 00808900 DPL=0 TSS64-avl
GDT=     000000000053a058 00000037
IDT=     000000000053a118 00000fff
CR0=80010033 CR2=000000000053a198 CR3=000000003fb9a000 CR4=00000668
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000050 CCD=000000003e1fa850 CCO=ADDQ
junyaUjunyaU

つまり、0x1d6eecの前の命令がfaultの原因になっていそう?

junyaUjunyaU

context_switchのあたりで起きていそう

junyaUjunyaU
void switch_next_task(bool sleep_current_task)
{
	if (sleep_current_task) {
		CURRENT_TASK->state = TASK_WAITING;
	}

	asm volatile("int %0" : : "i"(interrupt_vector::SWITCH_TASK));
}

このコードを別のものに置換したらfaultが起きなくなったので、ここに問題がありそう

junyaUjunyaU

この実行中に、タイマー割り込みでコンテキストスイッチが発生しておかしくなっている気がしている

junyaUjunyaU

fsが0x3fbf0000になっているのはおかしすぎるな

junyaUjunyaU

この部分でfaultが起きているから原因はfsの値で間違いなさそう。

mov rax, [rdi + 0x30]
mov fs, ax

あとはどこでメモリ破壊されたか

junyaUjunyaU
RAX=000000003eb1f000 RBX=0000000000000000 RCX=000000000000000a RDX=000000000000000a
RSI=8080808080808080 RDI=000000003fbff850 RBP=000000000080fce0 RSP=000000000080fc90
R8 =8080808080808080 R9 =fefefefefefefeff R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=00000000001d4d5c RFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 0000000000000000 00000000 00000000
CS =0008 0000000000000000 00000fff 00a09a00 DPL=0 CS64 [-R-]
SS =0000 0000000000000000 00000000 00000000
DS =0000 0000000000000000 00000000 00000000
FS =0000 0000000000000000 00000000 00000000
GS =0000 0000000000000000 00000000 00000000
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0028 0000000000538090 00067fff 00808900 DPL=0 TSS64-avl
GDT=     0000000000538058 00000037
IDT=     0000000000538100 00000fff

ところどころおかしい値が入ってるなあ

junyaUjunyaU

発生状況の整理

faultが発生しないパターン
何か適当な空コマンドをたたいてからecho xxx を実行するとechoコマンドが正確に実行される
faultが発生するパターン
いきなりecho xxxを実行すると triple fault発生

junyaUjunyaU

fault起こす直前にssの値が0になっているのはなぜだろう

junyaUjunyaU

メモリマネージャーのバグだわこれ
メモリマネージャーがバグると死ぬほど厄介だなこれ...。一見全然関係ないとこでエラーが起きてるように見えてしまう

このスクラップは2024/10/12にクローズされました