x86: тройная ошибка при вызове инструкции после переключения каталога страниц - PullRequest
1 голос
/ 06 мая 2020

Я создавал свою версию ОС xv6, но как только я переключаюсь на только что созданный каталог страниц и пытаюсь вызвать функцию, возникает тройная ошибка.

Было много похожих вопросов. спросил, и обычно проблема заключается в том, что ошибка страницы не обрабатывается должным образом либо из-за неправильного сопоставления страниц, либо из-за неправильной IDT.

В моем случае я вручную проверил сопоставление, и оно работает, поэтому меня нет идей что еще можно сломать. Подробности см. Ниже.

Вот где я нахожусь в ядре (просто переключил CR3 на новую таблицу страниц и собираюсь вызвать test_function):

   │0x801017ad <kernel_start+29>    call   0x80101040 <init_kernel_memory_range>
   │0x801017b2 <kernel_start+34>    call   0x801013c0 <init_global_kernel_page_dir>
   │0x801017b7 <kernel_start+39>    call   0x80101390 <switch_to_kernel_page_dir> 
  >│0x801017bc <kernel_start+44>    call   0x80101770 <test_function>

Я могу проверить в gdb что память test_function доступна, поэтому отображение кажется правильным:

(gdb) x/10i test_function

0x80101770 <test_function>:          push   ebp
0x80101771 <test_function+1>:        mov    ebp,esp
0x80101773 <test_function+3>:        sub    esp,0x8
0x80101776 <test_function+6>:        lea    eax,ds:0x80101b00
0x8010177c <test_function+12>:       mov    DWORD PTR [esp],eax
0x8010177f <test_function+15>:       call   0x80101750 <panic>
0x80101784 <test_function+20>:       add    esp,0x8
0x80101787 <test_function+23>:       pop    ebp
0x80101788 <test_function+24>:       ret
0x80101789:  nop

Я также могу проверить, что к стеку можно получить доступ:

(gdb) i r esp
esp            0x8010101c       0x8010101c

(gdb) x/10w 0x8010101c
0x8010101c:     0x80104024      0x80400000      0x00007bf8      0x90669066
0x8010102c:     0x90669066      0x8be58955      0xc35d0845      0x90909090
0x8010103c:     0x90909090      0x83e58955

Сопоставление идентификаторов низких адресов на физические, которые раньше находились в каталоге предыдущей страницы, больше не существует, и это предназначено (0x101770 - физический адрес test_function):

(gdb) x/10i 0x101770
0x101770:    Cannot access memory at address 0x101770

Я также проверил вручную что адреса, которые меня интересуют, правильно переводятся с помощью каталога страниц / таблицы страниц в физические адреса. Тем не менее, когда я наконец call test_function, я получаю это в QEMU:

EAX=003ff000 EBX=00010094 ECX=003ff000 EDX=fe000000
ESI=00010094 EDI=00000000 EBP=80101024 ESP=8010101c
EIP=801017bc EFL=00000096 [--S-AP-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0000 00000000 00000000 00000000
GS =0000 00000000 00000000 00000000
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00007c60 00000017
IDT=     00000000 000003ff
CR0=80010011 CR2=00000040 CR3=003ff000 CR4=00000010
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
EFER=0000000000000000
Triple fault.  Halting for inspection via QEMU monitor.

IDT еще не настроен, но я пока не ожидаю каких-либо ошибок страницы.

Что-нибудь, что мне здесь не хватает? Что еще может вызвать тройную неисправность? Спасибо.

...