Fault при перезагрузке GDT в защищенном режиме

Тема в разделе "WASM.OS.DEVEL", создана пользователем KonstantinBart, 6 дек 2007.

  1. KonstantinBart

    KonstantinBart New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2007
    Сообщения:
    20
    Всем доброго времени суток!
    В драйвере (kernel-mode) попытался переинициализировать GDT (на рабочей WinXP, соответственно в защищенном режиме). ОС вываливает Fault и предлагает перегрузиться или выключиться.
    Вот пример кода (MASM):

    Код (Text):
    1. .386p
    2. .model flat
    3. public _GetCr0@0
    4.  
    5. .data
    6.  
    7. GDT     db 0
    8.         db 0
    9.         db 0
    10.         db 0
    11.         db 0
    12.         db 0
    13.         db 0
    14.         db 0
    15.  
    16.         db 0FFh
    17.         db 0FFh
    18.         db 0
    19.         db 0
    20.         db 0
    21.         db 10010010b    ;92h
    22.         db 10001111b    ;8Fh
    23.         db 0
    24.  
    25. gdtr    dw $ - GDT - 1
    26.         dd ?
    27.  
    28. .code
    29.  
    30. _GetCr0@0:
    31.     jmp short _main
    32.  
    33. _main:
    34.  
    35.         call disable_interrupts
    36.         call initialize_gdt
    37.         call enable_interrupts
    38.         ret
    39.  
    40. disable_interrupts:
    41.         cli
    42.         in al, 70h
    43.         or al, 80h
    44.         out 70h, al
    45.         ret
    46.  
    47. initialize_gdt:
    48.         mov  eax, 0
    49.         add eax, offset GDT
    50.         mov dword ptr gdtr + 2, eax
    51.         lgdt fword ptr gdtr
    52.         ret
    53.  
    54. enable_interrupts:
    55.         in al, 70h
    56.         and al, 7Fh
    57.         out 70h, al
    58.         sti
    59.         ret
    60.  
    61. end _GetCr0@0
    Валится на выполнении lgdt...если закомментить - то всё работает нормально.
    Где тут собака зарыта? Подскажите пожалуйста.
     
  2. Sedov

    Sedov New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2007
    Сообщения:
    8
    А где дескриптор для стека?
    Валится у тебя не на Lgdt а на ret-е.
     
  3. KonstantinBart

    KonstantinBart New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2007
    Сообщения:
    20
    Что-то я не допонял...а причем тут дескриптор для стека? Ведь я же только инициализирую новую дескрипторную таблицу с 2-мя дескрипторами: нулевым и данных....далее формирую GDTR и вызываю инструкцию lgdt....
    И именно она у меня не выполняется!
     
  4. KonstantinBart

    KonstantinBart New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2007
    Сообщения:
    20
    Что-то я не допонял...а причем тут дескриптор для стека? Ведь я же только инициализирую новую дескрипторную таблицу с 2-мя дескрипторами: нулевым и данных....далее формирую GDTR и вызываю инструкцию lgdt....
    И именно она у меня не выполняется!

    Кстати, вот в софт айсе перед выполнением команды такое поимел:
    EAX: F7D8FF80
    EBP: F7C72C7C
    ESP: F7C72C58
    EIP: F7D8F4AA
    CS: 0008
    DS: 0023
    SS: 0010

    Вот из сегмента кода:
    0008:F7D8F4AA LGDT FWORD PTR [F7D8FF90]

    Вот дамп памяти:
    0010:F7D8FF90 0F 00 80 FF D8 F7
    0010:F7D8FF80 00 00 00 00 00 00 00 00 - FF FF 00 00 00 92 8F 00

    Тут вроде бы все верно GDT загружается по адресу F7D8FF90, там шестибайтный GDTR последние 4 байта которого указывают на адрес таблицы GDT (на нулевой дескриптор)...после выполнения команды - комп перегружается...
     
  5. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    блин...
    ну нет у тебя соответсвия между селекторами и дескрипторами
    GDT ты изменил, но ядро использует селекторы дескрипторов, которые соответствуют GDT, созданной самим ядром
     
  6. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    конечно бсод будет. заменил GDT которая используется системой на непонятно что, и надеешься что ОСт так и будет работать?
     
  7. Sedov

    Sedov New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2007
    Сообщения:
    8
    Поясняю: при какой-либо работе со стеком, проверяются регистры ss, esp;
    при работе с сегментом кода: cs, eip;
    при работе с сегментом данных: ds+адрес заданный явно/через регистр/память;
    в случае невыполнения каких-либо требований по безопасности сегментов происходит исключение, номер исключения зависит от того какие условия вызвали это исключение.
    в данном случае сама перезагрузка Gdt исключения не выдает, а вот ret вызывает исключения по целому ряду параметров: авария стека (в твоем варианте его вообще нет так что ты вообще не имеешь права использовать ret), авария сигмента кода (точно не скажу сейчас, но скорее всего выход за пределы отведенной области)
    Вот и думай. А еще лучше читай описания.
     
  8. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    с чего ты взял, что стека нет?
    каким образом по-твоему проходят вызовы disable_interrupts и initialize_gdt?
     
  9. Sedov

    Sedov New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2007
    Сообщения:
    8
    rei3er, стек не описан в gdt это раз, а во-вторых никак не происходит его переинициализация после перезагрузки gdt. следовательно его для процессора нет, хотя стек должен быть, хотя бы для выполнения команды ret. Вот процессор долго не думая и выдает исключительную ситуацию.

    Имеется в виду ситуация после перезагрузки gdt.
     
  10. KonstantinBart

    KonstantinBart New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2007
    Сообщения:
    20
    Странно....у меня ret используется 4 раза....получается, что стек всё-таки есть!
    А селекторы переназначить? Ну как бы я об этом забыл...это получается что-то типа:
    Код (Text):
    1. mov     ax, 8
    2.         mov     сs, ax
    Или что-то еще нужно?
     
  11. Sedov

    Sedov New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2007
    Сообщения:
    8
    После выполнения lgdt стэк у тебя исчезает напроч!!!!!!!!!!
    Селекторы переназначаются именно так. Не забудь создать еще одну запись в gdt для стека и данных и после перезагрузки gdt переназначить соответствующие селекторы
     
  12. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    ты не прав, старые значения селектора и дескриптора сегмента стека остаются закэшированными в SS (10 байт: 2 байта - селектор, 8 байт - дескриптор) после изменения GDTR
    и они используется (явные/неявные операции над стеком) без обращения к GDTR
     
  13. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Sedov отчасти прав - проблема в стеке. Но трабл возникает не из-за того, что в GDT не описан сегмент стека. Проблема в том, что в GDT определено только 2 дескриптора, т.е.
    лимит = 15. На момент загрузки GDTR и выполнения ret - в SS наверняка хранится значение
    больше 8 (10h,18h,20h...?). А при выполнении ret проц проверяет попадает ли селектор сегмента стека в предел GDT - в рез-те #GP и т.д.
    Курите маны на команду ret :)
     
  14. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    Medstrax
    лимит стека проверяется исходя из соответствующего значения дескриптора, который закэширован в скрытой части сегментного регистра SS
    тут ret а не far ret
    курите сами )
     
  15. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    господа, тут проблема в возможном несоответствии селекторов ядра и дескрипторов в новой GDT
    и совсем необязательно этим дескритором будет дескриптор сегмента стека
     
  16. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Фигню порешь
    Цитата из мана
    #GP(selector)...if the return code or STACK SEGMENT SELECTOR index is not within its descriptor table limits
    А какой ret - обычный или far - здесь пох ;)
     
  17. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Еще раз повторю - речь идет не о лимите сегмента стека, а о лимите GDT куда селектор SS
    не попадает скорей всего
     
  18. wan1786

    wan1786 New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2007
    Сообщения:
    19
    Нда. Нонаме прав заминить всю табличку нельзя, можно только дабавить дескриптор. вот только зачем тебе это?
     
  19. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    почитай лучше часть 2B интеловского мануала (а именно псевдокод выполнения RET)
    хотя ладно, вот он
    так что фигню порешь ты
    выполнение обычного RET не вызывает #GP по селектору
     
  20. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    я эти вещи читал еще 10 лет назад
    а вот ты похоже мои слова или не хочешь понять или не можешь ;)
    моя цитата взята из того же мануала, см.дальше - где описаны исключения