Я занимаюсь разработкой операционной системы и вот моя цель. Я включил подкачку и хочу удалить отображение идентификаторов. Ранее у меня было два сопоставления: карта идентификации 0-4M и ядро с виртуальным адресом 0xC0000000, сопоставленное с физическим адресом 1M. Мой загрузчик делает это до перехода к ядру, и ядро несет ответственность за удаление карты идентификации. Мой указатель стека теперь имеет значение 0x90000. Моя стратегия такова:
После входа в ядро я использую рекурсивные таблицы страниц для доступа (я получаю их виртуальные адреса: Что происходит, когда вы теряете виртуальный адрес каталога страниц? ) в мой каталог страниц и все остальные таблицы страниц. Рекурсивные таблицы страниц: последняя запись каталога страниц указывает на себя.
Я хочу переназначить стек и дать ему виртуальный адрес. Поскольку 0xFFC00000-0xFFFFFFFF используются методом рекурсивной страницы, я использую 0xFFC00000 в качестве виртуального адреса стека, который я сопоставляю с физическим 0x90000.
Затем я заново инициализирую GDT.
Теперь состояние моей системы таково:
(qemu) info registers
EAX=000241a0 EBX=c00019de ECX=00000001 EDX=000241a0
ESI=00008137 EDI=00103800 EBP=ffc00000 ESP=ffc00000
EIP=c00019de EFL=00000087 [--S--PC] 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 =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= c0004100 00000027
IDT= 00000000 000003ff
CR0=80000011 CR2=00000000 CR3=0009c000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
код переотображения стека:
STACK equ 0xFFC00000
STACK_PHY equ 0x90000
global refresh_stack ;A solution for switching stacks
refresh_stack:
mov ebx,[esp] ;Return address
mov esp,STACK
mov ebp,STACK
jmp ebx
Я хочу удалить отображение идентификаторов как таковое:
void remove_identity_map() //This would remove the 4M identity map
{
if (entry_is_present(_page_directory[0]))
_page_directory[0] = 0; //Unmapping the whole of 4M
flush_tlb();
}
Где flush_tlb:
flush_tlb:
mov eax,cr3
mov cr3,eax
ret
Минимальный воспроизводимый пример (примерно)
void kmain()
{
set_recursive_map();
refresh_stack();
install_gdt(); //The standard 4 entries Data/Code * User/kernel
remove_identity_map();
.......
.......
}
Место, где происходит ошибка, - это когда я flush_tlb (). Если я закомментирую эту строку, код будет работать, как и ожидалось, но мы увидим кэшированные копии. Однако, когда я его держу, система (эмулятор) перезагружается с B IOS! (Тройная ошибка ???)
Кроме того, я использую qemu, и после того, как я заболел sh tlb, я попытался for(;;);
использовать qemu-monitor для info tlb
... Кажется, он не покраснел. Все предыдущие записи присутствуют ..
Где я могу ошибаться?
Примечание. Когда я выполнял отладку (пошаговое выполнение) с помощью gdb, доступ к адресу 0xFFC00000 был не возможно после того, как я сбросил tlb ... Но это имеет смысл, я просто удалил запись каталога страниц, соответствующую таблице страниц 0 ..
Обновление: одно переназначение, которое я не сделал видео памяти! Для текстового режима я все еще обращаюсь к 0xB8000. Поскольку мой обработчик исключений также печатает на экран, это верный источник тройной ошибки !!!