OSDev
http://osdev.su/

Сброс при входе в long mode
http://osdev.su/viewtopic.php?f=6&t=483
Страница 1 из 1

Автор:  grindars [ 06 янв 2012, 23:04 ]
Заголовок сообщения:  Сброс при входе в long mode

Решил тут вспомнить, как под интели писать, и начал с перехода в long mode. Переход выполняю строго по мануалу, но происходит сброс, хотя на исключения установлены обработчики.

Дано: защищенный режим, страничное преобразование выключено. В качестве загрузчика я использую SYSLINUX, поэтому содержимое GDT и IDT не определено, но задана плоская модель. Построены таблицы переадресации, базовый адрес PML4 загружен в cr3.

Во всех эмуляторах (QEMU, Bochs, VirtualBox, VMWare) код работает, на реальной машине - сбрасывает в момент включения страничной адресации, т.е. в момент перехода в long mode.

Делаю следующее:
  1. Запрещаю маскируемые и немаскируемые прерывания
  2. Строю и устанавливаю IDT на 32 исключения
  3. Загружаю GDT, содержащую следующие сегменты:
    • Сегмент 32-битного кода
    • Сегмент данных
    • Сегмент 64-битного кода
    • TSS для хранения стеков
  4. Перезагружаю CS сегментом кода, а DS, ES, FS, GS и SS - сегментом данных
  5. Загружаю новую TSS, заполненную нулями, в TR
  6. Включаю PAE (бит 5 регистра cr4)
  7. Включаю long mode (бит 8 MSR IA32_EFER)
  8. Включаю страничную адресацию
  9. Обнуляю IDT
  10. Делаю дальний переход для перезагрузки CS

По идее, сброс вызывает тройная ошибка, которая происходит после перехода в long mode из-за того, что IDT осталась 32-битная, но для нее нет причины: #PF быть не может, таблицы переадресации обеспечивают для загрузчика правильное отображение на те же адреса и разрешают чтение, запись, исполнение, а #GP или другие ошибки там просто нечему вызывать.

Маскировку NMI и загрузку ненулевой IDT я добавил позже, во время отладки. Без этого поведение было тем же самым.

Что я упускаю? Код переключалки.

Автор:  Bargest [ 15 янв 2012, 15:27 ]
Заголовок сообщения:  Re: Сброс при входе в long mode

Я брал код переключения из APM volume 2, параграф 14.8 Long-Mode Initialization Example. У меня работает. AMDшники не трогают лишний раз регистры DS, ES, FS, GS. Тем более до перехода в LM.

Автор:  grindars [ 18 янв 2012, 16:46 ]
Заголовок сообщения:  Re: Сброс при входе в long mode

Причина оказалась достаточно любопытной: ESP указывал на область памяти, которая не была отображена после перехода в режим совместимости. Интеловский мануал не упоминает о необходимости стека для перехода, но в амдовском примере есть такие строчки:
Код:
; Set up the protected-mode stack pointer, SS:ESP.
; Stack_sel must point to the previously-established stack
; descriptor (read/write data segment), located in the GDT.
; Skip setting DS/ES/FS/GS, because we are jumping right to
; 64-bit code.
;
mov ax, stack_sel
mov ss, ax
mov esp, esp0

Далее вплоть до дальнего перехода стек не используется, а после перехода - устанавливается 64-битный. Видимо, процессор выполняет какие-либо проверки стека во время перехода.

Автор:  Himik [ 20 янв 2012, 16:05 ]
Заголовок сообщения:  Re: Сброс при входе в long mode

grindars писал(а):
Причина оказалась достаточно любопытной: ESP указывал на область памяти, которая не была отображена после перехода в режим совместимости.

Действительно, ESP не был настроен на защищённый режим. Хотя и не ясно, какую роль он играет в процедуре настройки 64-битного режима, но в любом случае оставлять в нём мусор от реального режима неправильно, да и простейшие исключения не смогут обрабатываться.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/