LINUX.ORG.RU

Защищенный режим


0

0

Туплю че-то
Для переключения между защищенным и реальным режимом нужно выполнить следующую последовательность телодвижений :
1 Запрещаем прерывания
2 Выставляем флаг PE - и опаньки - мы в protected mode

Теперь чтобы вернуться взад , в реальность :

3 Вертаем 0 в PE
4 Разрешаем прерывания

У меня затык происходит сразу после 3-го шага - я подозреваю,что этого из-за того, что в кодовый сегмент CS надо вернуть реальное значение,
которое там было перед установкой защищенного режима :

main:

call disable_interrupts
call set_PE
call clear_PE # вот после этой команды все валится
call enable_interrupts

ret


disable_interrupts:
cli
ret

enable_interrupts:
sti
ret

set_PE:
mov %cr0,%eax
orl $1,%eax
mov %eax,%cr0
ret

clear_PE:
mov %cr0,%eax
and $0xFE,%al
mov %eax,%cr0
ret



★★★★★

вообще неплохо бы было ещё проинитить gdt и заенаблить a20 гейт. а здесь, имхо, проблема в том переключаться нежно через %cs см. intel manual for developers vol 3 + arch/i386/boot/setup.S

578 # Now we want to move to protected mode ...

579 cmpw $0, %cs:realmode_swtch

580 jz rmodeswtch_normal

581

582 lcall *%cs:realmode_swtch

583

584 jmp rmodeswtch_end

asgard
()

ссс

код более чем ужасен.очередь предвыборки должна сбрасываться после _КАЖДОГО_ПЕРХОДА_МЕЖДУ_РЕЖИМАМИ_ .у вас этого нет => часть команд предвыбранные в real mode будут выполняться в protected mode что как занефик приведет к #GP.кроме того неплохо запретить NMI и не делать этих жутких call.

int_0dh
()
Ответ на: ссс от int_0dh

Ну очередь предвыборки так или иначе сбросится far jmp который нужен для загрузки кодового селектора после перехода RM->PM и обратно.

А NMI то зачем запрещать ? Кувыркания с контроллером прерываний много, а вызывается оно только по parity error все равно... А parity error ставит под сомнение вообще работоспособность машины как таковую.

anonymous
()
Ответ на: комментарий от anonymous

ссс

1) естессно сброситься при jmp far, но покажите мне этот jmp far в приведенном топикстартером коде 2)NMI не имеет никакого отношения к контроллеру прерываний (иначе оно не было бы NMI) 3)условия в которых оно вызывается - board dependet. код же должен работать на любой x86 доске(CPU >= 80386) (google,например, про MCA bus)

int_0dh
()
Ответ на: комментарий от anonymous

ссс

1) естессно сброситься при jmp far, но покажите мне этот jmp far в приведенном топикстартером коде 2)NMI не имеет никакого отношения к контроллеру прерываний (иначе оно не было бы NMI) 3)условия в которых оно вызывается - board dependet. код же должен работать на любой x86 доске(CPU >= 80386) (google,например, про MCA bus)

int_0dh
()
Ответ на: ссс от int_0dh

> 2)NMI не имеет никакого отношения к контроллеру прерываний (иначе оно не было бы NMI) 3)условия в которых оно вызывается - board dependet.

Я не знаю единого и документированого способа запретить NMI. Более того, на то оно и NMI чтобы не запрещалось. Поэтому предположил что это как-то может быть завязано на PIC. Косвенным образом.

anonymous
()
Ответ на: комментарий от anonymous

Наваял я пример
Он работает как загрузчик, я его тестировал в вмваре
Вроде как-бы я переключаюсь в защищенный режим, при этом:
запрещаю прерывания
загружаю таблицу всего из 2-х дескрипторов
устанавливаю бит PE=1
загружаю селектор по 2-му дескриптору
вроде вертаюсь взад в реал

Но при этом: ничего уже не могу вывести на экран начиная с момента загрузки защищенного режима
Код:
.code16
.text


mov $0x07C0, %ax
mov %ax, %ds

mov $msg0, %si
call Print


ljmp $0, $Start
Start: xor %ax, %ax
mov %ax, %ds
mov %ax, %ss
mov $0x8200, %sp

cli
push %ds
push %si

lgdt (gdtinfo)

mov %cr0, %eax # Enable protected mode
or $1, %al
mov %eax, %cr0

mov $0x8, %ax # Load selector 1, 32bit flat data
mov %ax, %ds

mov $0x0f01, %ax
mov %ax, %ds:(0xB8000)


mov %cr0, %eax # Shut off protected mode
xor $1, %al
mov %eax, %cr0


pop %si
pop %ds # Get the realmode segment back and enable interrupts
sti

mov $msg2, %si
call Print


2:
jmp 2b


Print:
mov $0x0E, %ah
xor %bx, %bx
1:
lodsb
or %al, %al
jz 2f

# INT 0x10 VIDEO TELETYPE
# AH=0xE AL=Character [BH=VideoPage BL=Attribute]
int $0x10
jmp 1b
2:
ret


gdtinfo: .word gdtend - gdt - 1
.long gdt

gdt: .long 0 # Descriptor 0 is the NULL descriptor
.long 0
gdtkerneldata: # 32bit Flat Data, 0-4GB Writable
.word 0xFFFF
.word 0
.byte 0
.byte 0x92
.byte 0xCF
.byte 0
gdtend:


msg0: .asciz "boot...\n"
msg1: .asciz "we are in protected mode ...\n"
msg2: .asciz "we are in real mode ...\n"
.org 510
.word 0xAA55

kto_tama ★★★★★
() автор топика
Ответ на: комментарий от kto_tama

значиццо так.

1) в gdt должно быть 3 дескриптора(нулевой, код, дата)

2) После входа в защищенный режим сделать так:
(1(0x8)-дескриптор кода,2(0x10) - данных)
flush:


    mov ax, 0x10 

    mov ds, ax

    mov es, ax

    mov fs, ax

    mov gs, ax

    mov ss, ax

    jmp 0x08:flush2

flush2:

    ret 


3)
>Но при этом: ничего уже не могу вывести на экран начиная с момента загрузки защищенного режима 

>mov $0x0f01, %ax
>mov %ax, %ds:(0xB8000) 

зачем такой изврат в pmode ? напрямую надо


xnix ★★
()
Ответ на: комментарий от Mr_Nobody

почитал последнюю ссылку , и возник вопрос :
для того чтобы загрузить в регистр gdtr глобальную таблицу дескрипторов ,нужно выполнить такой алгоритм :
1 вычисляем физический адрес глобальной таблицы дескрипторов в памяти
2 вычисляем предел - или размер - этой таблицы
3 загружаем полученные параметры в gdtr
вот что касаемо первого пункта :
алгоритм вычисления физического адреса таков : сначала определяем начальный адрес сегмента данных,потом смещение глобальной таблицы относительно этого начала , ну и складываем эти 2 величины - и физический адрес таблицы готов
так вот тупой вопрос - глобальная таблица обязана находиться в сегменте данных ?
т.е. это даже не обсуждается ? :-)

kto_tama ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.