Проблемы с удалением сопоставления идентификаторов в ядре x86 - PullRequest
1 голос
/ 31 марта 2020

Я занимаюсь разработкой операционной системы и вот моя цель. Я включил подкачку и хочу удалить отображение идентификаторов. Ранее у меня было два сопоставления: карта идентификации 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. Поскольку мой обработчик исключений также печатает на экран, это верный источник тройной ошибки !!!

1 Ответ

1 голос
/ 03 апреля 2020

Ну, похоже, я забыл переназначить видеопамять! Я все еще обращался к 0xb8000 для текстового режима VGA. Причиной вопроса было то, что я не определил этот доступ ниже 1M. Если бы у меня был вопрос, я бы не стал задавать вопрос;).

Поэтому это может быть хорошим уроком для людей, которые хотят удалить свою идентификационную карту после включения подкачки:

  • Remap gdt
  • Remap idt
  • Remap stack
  • Remap video_memory
...