Fast System Call

Internal structure and you change requests/suggestions
  • Ghost

    Я проверил работу без сохранения ds и es. Всё работает. На быстрых вызовах даёт заметный прирост. Сегменты можно было загружать всего один раз если бы не дурацкая осбенность IA32. Все дескрипторы проверяются при загрузке селектора и выдают ошибку сразу, а gdt[0] нельзя использовать но можно загружать без всяких проверок. Приходится в обработчиках прерываний явно перегружать селекторы.
  • Ghost

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

    Верхние 4 Мб памяти приложения образуют область локальных данных потока. Каждый поток в многопоточном приложении сможет выделить там память для своих локальных переменных которые будут защищены от других потоков.
    Вершину этой области займут системные данные. Сверху вниз: каталог таблиц страниц (PDBR), область сохранения FPU, точка входа ядра, стек. Все адреса будут фиксированными (по крайней мере пока ядро загруженно) Кроме того в зависимости от типа приложения на место точки входа будет копироваться соответствующий код. Таким образом каждая программа вызывая прерывание или fastcall попадёт именно на свою точку входа, а ядро сможет безопасно экспортировать для драйверов и сервисов функции к которым обычные программы не должны иметь доступ.

    Адреса стека и входа будут опрделяться при загрузке ядра (будут задаваться константами) так что никаких вычислений делать не надо.

    Надо подумать над передачей параметров для новых вызовов
  • мега-кул, ребята! ваши иследования помогли разобраться в теме int vs sysenter..
    вобщем, тоже вот крутилась в голове идея на тему "служебных входов" в kmode в win2k, без особо лишних телодвижений (иногда довольно тесно приходится общаться с железяками, в связке с SoftICE).

    И хотя это было не особо актуально - ну какбы усё боле-менее работало через драйвера, а вот решил заюзать прерывания - всетаки, как никак инструкция CPU, а не какие нить, системные функции (в которых я мало рублю, да и так, надебажив, этак с километр, пропадет охота там чето юзать).

    что получилось.. поскрёб тут по сусекам в поисках DPL3 backdor'ов, и ага! int 2Ah, вроде как без дела торчит, с софт-айсом выйти на код обработчика, трабл особо никаких. не долго думая меняю обработчик забитый в глубинах
    ntoskrnl следующим макаром.

    Code: Select all

       xchg ecx, esp
       jmp  ecx
    
    и.. бугага, бугага, бугага, код пашет так как и планировалось - в ring3 проге, обрабатываю прерывания.

    Code: Select all

    function int2A (_eax, _edx, _ecx :integer):integer;
    asm
             pop   ecx  //  eip to return in r3
             int $2A 
             nop
             nop
             nop
             nop
             iretd;
    end;
    
    Потом мне этого показалось маловато, решил зохавать и sysenter. Вот, нарисовалась тестовая прога.
    {$apptype console}
    program test; uses windows;
    const
    count = 20000000;
    MSR_SYSENTER_CS = $174;
    MSR_SYSENTER_ESP = $175;
    MSR_SYSENTER_EIP = $176;

    var i, dwStart : integer;

    function sys_enter:integer;
    asm
    sti
    sysexit
    end;

    function sysenter(_eax, _edx, _ecx :integer):integer;
    asm

    pop edx // eip to return in r3
    mov ecx, esp // esp to return in r3
    sysenter
    end;

    function int2A (_eax, _edx, _ecx :integer):integer;
    asm
    pop ecx // eip to return in r3
    int $2A
    nop
    nop
    nop
    nop
    iretd;
    end;


    procedure setup_MSR;
    asm
    pop ecx
    mov ebp, esp
    int $2A

    xor edx, edx
    lea eax, sys_enter //загрузить указатель обработчика
    mov ecx, MSR_SYSENTER_EIP
    wrmsr

    mov ecx, MSR_SYSENTER_CS
    mov eax, 8 //WinNT kmode selector
    wrmsr

    mov eax, ebp
    mov ecx, MSR_SYSENTER_ESP
    wrmsr
    iretd
    end;

    begin
    write ('Wait... ');
    Setup_MSR;
    dwStart := GetTickCount;
    for i:= 0 to count do int2A(0,0,0);
    Write('int test: ', GetTickCount - dwStart, ', ');

    dwStart := GetTickCount;
    for i:= 0 to count do sysenter(0,0,0);
    Writeln('sysenter test: ', GetTickCount - dwStart);

    end.
    результаты (на cel-1300):
    Wait... int test: 4204, sysenter test: 1031

    в принципе, с пивком потянет.

    Так, веду кой какие разработки DOSx расширителя (по мотивам WDOSx & FreeDOS32),
    вот.. ну а эNTяа2k, довольно ничего так полигон, для обкатки решений..
    боле-менее на DOS начал смахивать, (хыы, а вместо Turbo Pascal7 - Turbo Delphi)... вотъ...
  • ой.. сори очепятался с esp... ну конечно же

    Code: Select all

    00064DBC: 870C24      xchg        ecx,[esp]
    00064DBF:  FFE1           jmp         ecx
    00064DC1:  90              nop
    
    смещения для ntoskrnl for win2ksp2 (ProductVersion 5.00.2195.2951)...
    реальная тачка несравниться с VMWARE или VirtPC ;) не тот драйв...
  • N†OSKRNL
    Про SYSENTER + win2k : http://www.anticracking.sk/EliCZ/infos/syscall.zip
    Это конечно здорово, но в рамках Колибри оффтоп )
  • Ghost - спасибо, комрад, супер семпл! просто когда темой занялся, гоогл вот к вам забросил, чему я весьма признателен... ну вы монстры!))) Serge - мега респект!

    а селекторных регистров , воистину нужно избегать, всеми путями.. да уж
    если бы не дурацкая осбенность IA32
    которые так и прут, особено в экстримальнейших местах, таких как обработка прерываний или исключений.

    вон скажем, тот же int 2a думал юзать без лишних регистровых
    затрат, на передачу тогоже pop ecx .. однако в итоге пришлось таких огородов
    городить (навроде откопать указатель из стека, нормализовать данные), что пришлось таки отказаться, от такого казалосьбы, небольшого удобства.. (да и не поместилось оно в очень сжатых рамках обработчика =(((
  • Это глюк или так и должно быть: тест syscal при ядре из файла flat.7z показывает ускорение по сравнению с прерыванием, но в ядре svn 429 syscall уже в несколько раз медленее чем прерывание. При использовании обновленного syscall test выполняется только часть тестов.
  • Прирост производительности будет только на плоском ядре и на реальном железе.
  • Heavyiron wrote:Кстати, обнаружил некоторую странность: начиная с какой-то ревизии (и в официальном и во flat-kernel) на доске отладки во вкладке USER есть надписи, типа "cess - done", иногда просто буква "e", иногда "New process: loadind" (в зависимости от того, где запускаю). Так и должно быть или это глюк?
    Это вызвано тем, что размер буфера под данные доски отладки кто-то увеличил до 4096 байт (svn утверждает, что последним к соответствующей строчке прикасался mike.dld в ревизии 373), а приложение board при запуске очищает только 1024 байт.
  • Новые тесты с новой ревизией #442 на Barton 2500+ (K7):
    69bdc73-> SYSENTER
    880128C-> SYSCALL
    BDbfC06-> Interrupt

    Для сравнения результаты от Heavyiron

    тест с новой ревизией #400 на Sempron 2500+ (K7):
    880B78B -> SYSENTER
    9E0104C -> SYSCALL
    DE18A36 -> Interrupt
  • Новые тесты на новом железе:
    7F0C850 -> SYSENTER
    9D87F5C -> SYSCALL
    E6142A9 -> INT 0x40
  • Все, для выбора варианта компиляции нужно изменить в svn\programs\config.inc значение переменной на "р5", "р6" либо "k6" для вызовов через прерывание, sysenter или syscall соответственно. После этого можно компилить старыми скриптами или же использовать build_all.bat, который спросит и все сделает сам, даже по папкам раскинет в \bin-е :)
  • Угу, и скомпилированные с "p6" и "k6" программы вообще не будут работать на старых компах до каких-то-там пней.
    Ушёл к умным, знающим и культурным людям.
  • ...и размерчик у выходных файлов с "p6"/"k6" заметно побольше будет...
  • Who is online

    Users browsing this forum: No registered users and 12 guests