Fast System Call

Internal structure and you change requests/suggestions
  • А если программа, написанная с использованием sysenter запускается на процессоре, который не поддерживает fast system call, то как тогда быть ?
  • В программах, использующих макрос mcall, изменять вообще ничего не нужно будет, насколько я понимаю? Кроме самого макроса, естественно, в котором вместо `int 0x40` будет `mov dword[SYSENTER_VAR], ..mcall // mov [SYSENTER_VAR + 4], esp // sysenter // ..mcall: `.
  • Да, с макросами вообше проблем не будет, кроме того можно писать проверку, если нет быстрых вызовов - то прерывание.
  • Тогда уж быстрее делать call dword ptr [using_syscall] и инициализировать using_syscall либо адресом процедуры int 0x40, либо предлагаемым вариантом. Хотя предложение что-то пихать по нулевому адресу мне категорически не нравится.
    Ещё вариант: на старых процессорах sysenter вызывает исключение, но его ведь ядро может перехватить и проэмулировать...
  • Хорошо что решил этим заняться. У меня было желание но времени нет.

    Сохранять регистры в DS:0 нельзя, многопоточные программы не будут работать. Тормозила наверняка pid_to_slot тем более она совсем не нужна. Номер слота текущей задачи хранится в переменной [CURRENT_TASK], она есть в const.inc. sysint_stack_data больше нет память под PL_0 стек выделяется динамически, странно что код работал. Поэтому надо изменить на
    mov eax,[CURRENT_TASK]
    shl eax,8
    mov eax,[PROC_BASE+eax+APPDATA.pl0_stack]
    lea esp, [eax+RING0_STACK_SIZE]

    RING0_STACK_SIZE сейчас не определена её надо добавить в const.inc
    RING0_STACK_SIZE equ 0x2000-512 ;512 байт для контекста FPU

    Ещё ты несколько раз перегружаешь сегментные регистры хотя хватает одного раза
    mov eax, [ss:sysenter_stack - 8]
    задавать явно сегмент не зачем это ведь тот же ds
    Last edited by Serge on Sat Feb 24, 2007 7:03 pm, edited 1 time in total.
  • Ghost
    если сохранять регистра в стеке то можно так:

    Code: Select all

       push ecx
       push edx
       push ebp
       mov ebp, esp
       push $+4   ;адрес возврата   ;2 байта ->|
       sysenter                     ;2 байта   |
    ;@@:                            ;       <--|
       pop ebp
       pop edx
       pop ecx
    
    @@ и @F лучше не использовать или могут быть проблемы с другими метками в программе


    адрес возврата будет в [ebp-4]
    после загрузки правильного esp надо сохранить ebp в стеке
    тогда для возврата
    pop ecx ; ebp он же ring_3 esp
    mov edx, [ecx-4]
    sysexit
  • http://iam.gorodok.net/fc_ker.zip
    Вот изменённые файлы для текущего ядра (#369) с добавленной функцией - заглушкой + тестовое приложение (test), оно выводит (на доску отладки) примерное количество тактов, затраченных на вызов в цикле 0x100000 раз фунции заглушки методом быстрого вызова и по прерыванию. У меня в среднем такие значения:

    000000001F700000 <- Fast call
    000000000E000000 <- Interrupt

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

    Code: Select all

    sysenter_entry:
    	; Настраиваем стек
    	cli
    	push	eax
    	mov	eax, [ss:CURRENT_TASK]
    	shl	eax, 8
    	mov	eax, [ss:PROC_BASE + eax + APPDATA.pl0_stack]
    	lea	esp, [ss:eax + RING0_STACK_SIZE]	; configure ESP
    	mov	eax, [ss:sysenter_stack - 4]		; eax - original eax, from app
    	sti
    	;------------------
    	...
    	;------------------
    	mov	edx, [SYSENTER_VAR]		; eip
    	mov	ecx, [SYSENTER_VAR + 4]	; esp
    	sysexit
    
    Но выигрыш от использывания быстрых вызовов ожидался больше... А может всё дело в моём AMD K7...

    Проверьте кто может, и сообшите результаты.

    P.S. Сохранение регистров пока оставил как было, переделаю на стек (это видимо лучший вариант т.к. в основном программы не хранят данные в [ESP - 4|8], и это будет прозрачно относительно варианта с прерыванием) + нормальное сохранение/передачу чегистров после того как скорость хотябы останется на уровне прерываний.

    Про DS - в том месте кода DS - селектор кода программы, кстати замене сегмента много кушает? Если да то можно и попыхтеть над кодом.

    Про Menuet OS, сколько можно тянуть его наследство? Ктонибудь мне обьяснит смысл переворачивания регистров? Да, уйти от этого не просто но с каждым месяцем API растёт и это становится ещё сложнее.
    Или например :

    Code: Select all

    pop   eax 
    popad
    в обработчике сис вызова? без этого конечно все смешения в возвр. регистрам изменятся, но тянуть этот баласт тоже не дело. Или я не прав?
    Сейчас я слушаю : Image
  • Ghost

    У меня было тоже самое. Проверял разные варианты, запрещал прерывание и отключал кеш, нифига не помогло. Прерывание работало в два раза быстрее. Тогда начал читать описание команд и вспомнил почему не стал их делать.
    Ржал полчаса.
    Команды расчитаны на плоскую память и устанавливают базу сегментов в 0 а у приложений база 0х60400000.
    Происходит страничная ошибка с нарушением права доступа и в дело вступает обработчик страничных ошибок. Но он не обрабатывает такие ошибки потому что их никогда не возникало. Поэтому он просто возвращает управление назад. Из стека загружаются сохранённые сегментные регистры и на этот раз там правильные значения и программа продолжает работу.
    Во всёи есть один положительный момент. Защита ядра таблицами страниц работает правильно. Надо залить код на SVN. Я закончил драйвер и скоро выложу ядро с новым распределением памяти под плоскую модель.
    Можно будет сделать пробную "плоскую" версию и проверить ещё раз.
  • Хех. Буду ждать "плоскую" версию.

    По поводу SVN : куда лить? В trunk вроде этому коду пока не место, в branches - тоже не особо, изменений не много.

    Думаю плоскую версию ты в branches выложиш, туда и вызовы пойдут, а пока допишу сохранение регистров на текущем ядре, отпишусь здесь.

    Ещё есть идея про SEH (Structured|Sexual Exception Handler), он и компиллерам (C/C++ - try/catch, etc) на пользу пойдёт и несуществуюший КОП обойти позволит, но это только идея :)
  • Ghost
    Пиши в транк. Код хороший и уже работает :) Можно обкатать разные варианты вызовов и макросов. У АМД есть своя пара syscal/sysret. Они ее делали позже Интел и продумана она лучше. Тоже стоит добавить.
    > несуществуюший КОП обойти позволит
    Что такое КОП ?
  • КОП - Код ОПерации (OpCode)

    Дописать поддержку SYSCALL/SYSRET не сложно, вызовы должны даже проше выглядеть, т.к. EIP автоматом копируется в ECX, а заморочек с ESP вообше нет. Но пока остается проблема с нулевой базой:

    A new descriptor is loaded for CS to specify a fixed 4-Gbyte flat segment as follows:
    - The CS_base is set to zero.
    - The CS_limit is set to 4 Gbyte.
    - The CS segment attributes are set to Read-only.

    Сегодня - завтра напишу код, надеюсь что он хоть и со страничными нарушениями, но будет работать.
  • Добавил SYSCALL/SYSRET, кое как работают.
    Всё на SVN

    Вызов через SYSENTER, вместо int 0x40:

    Code: Select all

    SYSENTER_VAR	equ	0
    	mov	dword[SYSENTER_VAR], @f
    	mov	[SYSENTER_VAR + 4], esp
    	sysenter		; портятся ecx, edx
    @@:
    Вызов через SYSCALL, вместо int 0x40:

    Code: Select all

    	push	ecx
    	syscall
    	pop	ecx
  • У меня в эмуляторе VMWARE 5.5.0
    E42093F49 <-Fast call
    143B6C251 <- Interrupt
  • На реальной машине с ядром 378:
    Image
    Last edited by Heavyiron on Fri Oct 10, 2008 1:02 am, edited 1 time in total.
  • Who is online

    Users browsing this forum: No registered users and 3 guests