- дальний вызов (Solaris, BSD - селектор 7 смешение 0)
- шлюз прерывания (Kolibri, Linux, Windows до w2k)
- Fast System Call (Linux, WinXP и старше)
При реализации быстрых вызовов я остановился на SYSENTER/SYSEXIT от Intel, за подробностями : Intel® Architecture Software Developer’s Manual, или http://www.codeguru.com/cpp/w-p/system/ ... /c8223__1/
Краткая справка:
SYSENTER - Fast System Call
Обеспечивает максимально эффективный переход к коду на нулевок кольце, устанавливая регистры CS, EIP, SS, ESP следуюшим образом:
CS - SYSENTER_CS_MSR
SS - SYSENTER_CS_MSR + 8
ESP - SYSENTER_ESP_MSR
EIP - SYSENTER_EIP_MSR
SYSEXIT - Fast Return from Fast System Call
Обеспечивает максимально эффективный возврат из кода на нулевок кольце к коду на кольце 3, устанавливая регистры CS, EIP, SS, ESP следуюшим образом:
CS - SYSENTER_CS_MSR + 16
SS - SYSENTER_CS_MSR + 24
ESP - ECX
EIP - EDX
SYSENTER_CS_MSR - MSR[0x174]
SYSENTER_ESP_MSR - MSR[0x175]
SYSENTER_EIP_MSR - MSR[0x176]
За поддержку быстрых вызовов отвечает CPUID(1).EDX.bit_11 - SEP(SYSENTER/SYSEXIT present)
Как видно, особенностью бустрых вызовов является то что этот механизм не сохраняет адресс возврата в код кольца 3, в Linux/Win аргументы передаются через стек, поэтому в этих системах необходимые для возврата занчения ECX и EDX устанавливаются кодом приложения, но так как в KolibriOS большая часть функций использует эти регистры для передачи аргументов я предлагаю сохранять регистры в память приложения, например заголовок (адрес DS:0), тогда вызов функций будет выглядеть так:
Code: Select all
SYSENTER_VAR equ 0
...
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
Итак, список изменений:
const.inc
kernel.asm
boot\bootcode.inc
core\syscall.inc
##############[const.inc]##########################
Константы
Code: Select all
.............
.............
; CPU MSR names
MSR_SYSENTER_CS equ 0x174
MSR_SYSENTER_ESP equ 0x175
MSR_SYSENTER_EIP equ 0x176
.............
.............
Настройка MSR регистров
Code: Select all
.............
.............
; ENABLE PAGING
call test_cpu
bts [cpu_caps], CAPS_TSC ;force use rdtsc
; -------- SYSENTER/SYSEXIT init ----------
bt [cpu_caps], CAPS_SEP
jnc .SEnP ; SysEnter not Present
xor edx, edx
mov ecx, MSR_SYSENTER_CS
mov eax, os_code
wrmsr
mov ecx, MSR_SYSENTER_ESP
mov eax, sysenter_stack ; Check it
wrmsr
mov ecx, MSR_SYSENTER_EIP
mov eax, sysenter_entry
wrmsr
.SEnP:
; -----------------------------------------
.............
.............
Изменён порядок следования дескрипторов
Code: Select all
.............
.............
; GDT TABLE
gdts:
dw gdte-$-1
dd gdts
dw 0
; Внимание! порядок следуюшил четырёх селекторов не менять, используется в SYSENTER/SYSEXIT
; должно быть os_code, os_data, app_code, app_data
int_code_l:
os_code_l:
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10011010b
db 0x00
int_data_l:
os_data_l:
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10010010b
db 0x00
app_code_l:
dw 0xFFFF;((0x80000000-std_application_base_address) shr 12) and 0xffff
dw 0
db 0x40
db cpl3
dw G32+D32+0x6000+0x7;
app_data_l:
dw 0xFFFF;(0x80000000-std_application_base_address) shr 12 and 0xffff
dw 0
db 0x40
db drw3
dw G32+D32+0x6000+0x7;
; --------------- APM ---------------------
apm_code_32:
dw 0x0f ; limit 64kb
db 0, 0, 0
dw 11010000b *256 +10011010b
db 0x00
apm_code_16:
dw 0x0f
db 0, 0, 0
dw 10010000b *256 +10011010b
db 0x00
apm_data_16:
dw 0x0f
db 0, 0, 0
dw 10010000b *256 +10010010b
db 0x00
; -----------------------------------------
graph_data_l:
dw 0x7ff
dw 0x0000
db 0x00
dw 11010000b *256 +11110010b
db 0x00
.............
.............
Точка входа быстрого вызова
Code: Select all
.............
.............
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSENTER ENTRY ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
uglobal
times 100 db ?
sysenter_stack:
endg
align 32
SYSENTER_VAR equ 0
sysenter_entry:
; Настраиваем стек
cli
push ds
push eax
mov ax, os_data
mov ds, ax
mov eax, [0x3010]
mov eax, [eax + TASKDATA.pid]
call pid_to_slot ; не портит регистры
shl eax, 12
add eax, sysint_stack_data + 4096
mov esp, eax
mov eax, [sysenter_stack - 4]
mov ds, ax
mov eax, [ss:sysenter_stack - 8]
;------------------
push ds es
pushad
cld
mov ax, word os_data
mov ds, ax
mov es, ax
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, edi
mov edi, [esp + 28]
sti
push eax
and edi, 0xff
call dword [servetable + edi * 4]
pop eax
popad
pop es ds
;------------------
mov edx, [SYSENTER_VAR] ; eip
mov ecx, [SYSENTER_VAR + 4] ; esp
sysexit
iglobal
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SYSTEM FUNCTIONS TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.............
.............
Code: Select all
; <--- description --->
; compiler: FASM 1.50
; name: Basic window example for MenuetOS
; version: 1.01
; last update: 25/08/2004
; written by: Ivan Poddubny
; e-mail: ivan-yar@bk.ru
; adapted by: Mihailov Ilia
; <--- include all MeOS stuff --->
include "lang.inc"
include "macros.inc"
SYSENTER_VAR equ 0
; <--- start of MenuetOS application --->
MEOS_APP_START
; <--- start of code --->
CODE
call draw_window ; at first create and draw the window
wait_event: ; main cycle
mov eax, 10
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
cmp eax, 1 ; if event == 1
je redraw ; jump to redraw handler
cmp eax, 2 ; else if event == 2
je key ; jump to key handler
cmp eax, 3 ; else if event == 3
je button ; jump to button handler
jmp wait_event ; else return to the start of main cycle
redraw: ; redraw event handler
call draw_window
jmp wait_event
key: ; key event handler
mov eax, 2 ; get key code
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
jmp wait_event
button: ; button event handler
mov eax, 17 ; get button identifier
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
cmp ah, 1
jne wait_event ; return if button id != 1
or eax, -1 ; exit application
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
draw_window:
mov eax, 12 ; start drawing
mov ebx, 1
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
mov eax, 0 ; create and draw the window
mov ebx, 100 * 65536 + 300 ; (window_cx)*65536+(window_sx)
mov ecx, 100 * 65536 + 200 ; (window_cy)*65536+(window_sy)
mov edx, 0x03ffffff ; work area color & window type 3
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
mov eax, 4 ; window header
mov ebx, 8 * 65536 + 8 ; coordinates
mov ecx, 0x10ffffff ; color & font N1
mov edx, header ; address of text
mov esi, header.size ; length of text
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
mov eax, 12 ; finish drawing
mov ebx, 2
mov dword[SYSENTER_VAR], @f
mov [SYSENTER_VAR + 4], esp
sysenter
@@:
ret
; <--- initialised data --->
DATA
lsz header,\
ru, "˜ Ў«® Їа®Ја ¬¬л",\
en, "Template program",\
fr, "La programme poncive"
; <--- uninitialised data --->
UDATA
MEOS_APP_END
; <--- end of MenuetOS application --->