Доброго времени суток! Уважаемые форумчане, дайте пример переводапроцессора в long mode c формированием нужных структур. С Уважением, Александр.
Не могу понать пару вещей: 1. Код (Text): ; Init several field mov dword[pde.base],010000011b ; PS or Present or Write mov dword[pdpe.base],pde.base+3 ; Present or Write mov dword[pml4e.base],pdpe.base+3 ; Present or Write почему записи 32х битные? Вроде нужно использовать 64х битные. 2.Для чего нужен 64х битный дескриптор? Сколько их должно быть.
1. у всех полей размер равен 8 байтам, но в старшей части находится только старшая часть адреса (и бит для запрета выполнения на странице, но по умолчанию он не нужен). и все флаги находятся в младшей части, вот она и редактируется 2. Дексрипторы были 64 битными ещё в обычном защищённом режиме. Если мне не изменяет память, то в long mode расширились до 128 бит только дескрипторы TSS и все дскрипторы в IDT. В long mode в GDT должно быть как минимум два дескриптора: один для кода и ещё один для всего остального. ( у него достаточно выставить только поле Present) P.S. В мануалах от Intel режим long mode (IA-32e) объясняется как-то не внятно, поэтому я рекомендовал бы курить маны от AMD, в манах от AMD всё написано более внятно и понятнее. Это только моё ИМХО
Немного поигравшись, получил следующее: Код (Text): [BITS 16] [ORG 0x7c00] _start: cli mov ax, cs mov ds, ax mov ss, ax mov sp, _start ;; Загрузка регистра GDTR: lgdt [gd_reg] ;; Включение A20: in al, 0x92 or al, 2 out 0x92, al ;; Установка бита PE регистра CR0 mov eax, cr0 or al, 1 mov cr0, eax ;; С помощью длинного прыжка мы загружаем ;; селектор нужного сегмента в регистр CS ;; (напрямую это сделать нельзя) ;; 8 (1000b) - первый дескриптор в GDT, RPL=0 jmp 0x8: _protected [BITS 32] _protected: ;; Загрузим регистры DS и SS селектором ;; сегмента данных mov ax, 0x10 mov ds, ax mov ss, ax ;; Готовимся к переходу в 64-битный режим mov es, ax mov edi, 0x100000 mov ecx, 0x1000 xor eax,eax rep stosd mov edi, 0x100000 ;; PML4E mov eax, 0x101007 stosd mov edi, 0x101000 ;; PDPE add eax, 0x1000 stosd mov edi, 0x102000 ;; PDE add eax, 0x1000 stosd mov edi, 0x103000 mov eax, 0x7 mov ecx, 512 fill: stosd mov edx,eax xor eax,eax add edi, 0x4 stosd mov eax,edx add eax,0x1000 loop fill ;; Начинаем переход mov eax,cr4 bts eax,5 mov cr4,eax mov eax,0x100000 mov cr3,eax mov ecx,0xC0000080 rdmsr bts eax,8 wrmsr mov eax,cr0 bts eax,31 mov cr0,eax jmp 0x18: _64 [BITS 64] _64: mov ax,0x28 mov ss,ax mov ds,ax mov byte [0xB805], 'A' jmp _64 [BITS 32] gdt: dw 0, 0, 0, 0 ; Нулевой дескриптор db 0xFF ; Сегмент кода с DPL=0 db 0xFF ; Базой=0 и Лимитом=4 Гб db 0x00 db 0x00 db 0x00 db 10011010b db 0xCF db 0x00 db 0xFF ; Сегмент данных с DPL=0 db 0xFF ; Базой=0 и Лимитом=4Гб db 0x00 db 0x00 db 0x00 db 10010010b db 0xCF db 0x00 db 0xFF ; Сегмент кода с DPL=0 db 0xFF ; 64 битный сегмен, 0x18 db 0x00 db 0x00 db 0x00 db 10011010b db 0xAF db 0x00 db 0xFF ; Сегмент данных с DPL=0 db 0xFF ; 64 битный сегмен, 0x28 db 0x00 db 0x00 db 0x00 db 10010010b db 0xAF db 0x00 ;; Значение, которое мы загрузим в GDTR: gd_reg: dw 8192 dd gdt times 510-($-$$) db 0 db 0xaa, 0x55 На экран ничего не выводится... VirtualBox пишет в лог: Код (Text): 00:00:03.844 Guest CPUM state: se 00:00:03.844 eax=e0000011 ebx=00000000 ecx=c0000080 edx=00000000 esi=0000bff0 edi=00104800 00:00:03.844 eip=00007ca8 esp=00007c00 ebp=00000000 iopl=0 rf nv up di pl zr na pe nc 00:00:03.844 cs={0008 base=0000000000000000 limit=ffffffff flags=0000c09b} dr0=00000000 dr1=00000000 00:00:03.844 ds={0010 base=0000000000000000 limit=ffffffff flags=0000c093} dr2=00000000 dr3=00000000 00:00:03.844 es={0010 base=0000000000000000 limit=ffffffff flags=0000c093} dr4=00000000 dr5=00000000 00:00:03.844 fs={0000 base=0000000000000000 limit=ffffffff flags=0001c000} dr6=ffff0ff0 dr7=00000400 00:00:03.844 gs={0000 base=0000000000000000 limit=ffffffff flags=0001c000} cr0=e0000011 cr2=00007ca8 00:00:03.844 ss={0010 base=0000000000000000 limit=ffffffff flags=0000c093} cr3=00100000 cr4=00000020 00:00:03.844 gdtr=0000000000007cc4:2000 idtr=0000000000000000:ffff eflags=00010002 00:00:03.844 ldtr={0000 base=00000000 limit=00000000 flags=00000082} 00:00:03.844 tr ={0000 base=00000000 limit=0000ffff flags=0000008b} 00:00:03.844 SysEnter={cs=0000 eip=00000000 esp=00000000} 00:00:03.844 FPU: 00:00:03.844 FCW=037f FSW=0000 FTW=00 00:00:03.844 res1=00 FOP=0000 FPUIP=00000000 CS=0000 Rsvrd1=0000 00:00:03.844 FPUDP=0000 DS=0000 Rsvrd2=0000 MXCSR=00000000 MXCSR_MASK=00000000 00:00:03.844 MSR: 00:00:03.844 EFER =0000000000000500 00:00:03.844 PAT =0007040600070406 00:00:03.844 STAR =0000000000000000 00:00:03.844 CSTAR =0000000000000000 00:00:03.844 LSTAR =0000000000000000 00:00:03.844 SFMASK =0000000000000000 00:00:03.844 KERNELGSBASE =0000000000000000 00:00:03.844 *** 00:00:03.844 Guest paging mode: AMD64, changed 2 times, A20 enabled 00:00:03.844 Shadow paging mode: AMD64 00:00:03.844 Host paging mode: PAE+G Как я понял - не осуществляется переход в 64-битный сегмент.
exst Вообще в идеале надо бы проверять, поддерживается ли 64 битный режим (Хотя я вбокс не юзал, юзал QEMU) Дальше, A20 у вас как то странно открывается. Я не так делал Код (Text): ;Откроем линию а20 open_a20: mov al,0d1h ;команда управления out 64h,al ;линией А20 mov al,0dfh ;код открытия out 60h,al ;линии А20 ret Едем дальше зачем сразу прерывания запрещать ? А если уж запрещать (чтоб изменить cr0) то и NMI тоже запрещать надо. Код (Text): ;Запрещаем прерывания cli ;запрет аппаратных прерываний mov al,80h ;запрет NMI out 70h,al ;порт КМОП микросхемы Адрес видеопамяти у вас какой, то не такой Бред. Там как минимум 0xb8000 Почему так криво дескрипторы описаны? Разве сложно описать для данных, для стека, для кода, для видеопамяти. Это же удобно в дальнейшем Ладно в общем прикрепляю свою наработку. Надеюсь поможет. С комментариями. Когда то делал для универа, для студентов новую лабу, ну и преподу, экземпл) Там и адресация, и прерывания.
64 бита на виртуалке поддерживаются. Пробовал menuet64. С адресом видеопамяти вышла очепятка. А мои 64-битные дескрипторы и страничная разметка правильно описаны? P.S. Не выкачивается прикрепленный файл. Пробовал с разных компов.
exst Например сегмент кода в 64 битовом сегменте: [ LIMIT | BASE | PDLSTYPE GD0ALIMT | BASE ] CODE64_descr db 0FFh, 0FFh, 00h, 00h, 00h, 10011011b, 10101111b, 00 Надо так , а у вас 10011010 , куда accessed дели в типе сегмента?
Делал по аналогии с 32-битным. Только поменял местами биты L и D. Из АМДшной документации: Видимо от них нет толку.
Посмотрел ваш код. Появилась пара вопросов: 1)Если использовать страницы по 2МБ и разметить ими 1Гб, а на машине (ну или виртуалке) установлено меньше памяти будет ли ошибка? 2)Для чего очищаете cr2? Код (Text): xor eax,eax mov cr2,eax
exst Не разу так не пробовал, но ошибка будет только если вы обратитесь по тем адресам. Хотя вам никто не мешает разметить один и тот же регион несколько раз, тем самым с эмулировать подкачку при определенных условиях. cr2 содержит линейный адрес где (при случае) произошло нарушение Page Fault. Тем самым в обработчике прерываний можно его увидеть..
Ясно. Как я понял программа у меня останавливается на инструкции перехода в 64хбитный сегмент. Куда теперь копать? Может ли быть связана ошибка с разметкой страниц? Или же копать дескриптор. P.S.Воспользовался вашим дескриптором сегмента кода.
exst Ну вначале протестите программу до перехода в 64 битный режим (до джампа) выведете на экран что нить наподобие "Я в 32 битном режиме". А далее по нарастающей. Заполняйте страницы. Сделайте переходы. И вообще по моему исходнику ориентируйтесь, сравнивайте каждый шаг. в чем отличее.
exst, пробуй запускать код на Bochs. на ней как-то проще отлаживать. я когда то хотел включить режим PAE в защищённом режиме, оказалось что VitualBox поддерживает PAE через жопу (впрочем, может эта ошибка уже устранена)
TermoSINteZ, спасибо. Воспользовался вашей 2МБ разметкой) Код (Text): mov esi,0x100000 emms pxor mm0,mm0 mov ecx,2048 null: movq [ds:esi],mm0 add esi,8 loop null mov dword [ds:0x100000],0x100000 + 4096 + 15 mov dword [ds:0x100000+4096],0x100000 + 8192 + 15 xor esi,esi mov ecx,15 + 128 mov eax,0x200000 paging: mov dword [ds:0x100000+8192+esi],ecx add ecx,eax add esi,8 cmp esi,8*512 jne paging В VirtualBox отлично работает при 32 битной винде. )
exst просто поймите, что: при 4 килобайтной организации у нас 5 уровней PML4TE, PDPTE, PDE, PTE, Page Offset при 2х мегабайтной организации у нас 4 уровня PML4TE, PDPTE, PDE, Page Offset
При 1Гб организации еще проще, однако, ни разу я не встречал ее поддержку... Может только в новых АМД...