Local APIC

Тема в разделе "WASM.NT.KERNEL", создана пользователем Hairy, 25 янв 2008.

  1. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    кто мешает вызвать MmMapIoSpace() до программирования таймера
    т. е получить линейный адрес, отображающий страницу (0xFEE00000 - 0xFEE01000)
     
  2. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    спасибо щас попробую
     
  3. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    Ничего не получаеться :dntknw:

    При любом раскладе (MmMapIoSpace - отрабатывает отлично), когда я пытаюсь хоть как то запрограмить local APIC вылетает BSOD :dntknw:

    /* сил моих больше нет ... все выхи над этим сидел и пару дней до этого ... */
     
  4. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    если у кого нибуть есть код рабочий, пожалуйста, можете мне его дать? :|
     
  5. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    В винде есть промапленный апик, я не понял причины проблемы.
    Посмотрите код KfRaiseIrql для hal, где идет запись в TPR:

    .text:80012278 KfRaiseIrql proc near ; CODE XREF: sub_800122F8+5p
    .text:80012278 ; sub_80014C26+4Fp ...
    .text:80012278 movzx edx, cl
    .text:8001227B movzx ecx, ds:_HalpIRQLtoTPR[edx]
    .text:80012282 mov eax, ds:0FFFE0080h
    .text:80012287 mov ds:0FFFE0080h, ecx
    .text:8001228D shr eax, 4
    .text:80012290 movzx eax, ds:_HalpIRQLtoTPR[eax]
    .text:80012297 retn
    .text:80012297 KfRaiseIrql endp

    Насколько я помню этот адрес даже вроде не меняется от версии к версии
     
  6. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    так. всё равно не работает.

    пошёл по порядку:
    1. есть функция призваная найти вектор для конкретного прерывания
    Код (Text):
    1. BYTE search_irq_vector( BYTE irqnum )
    2. {
    3.     unsigned char *pIoRegSel;
    4.     unsigned char *pIoWin;
    5.     BYTE ch;
    6.     PHYSICAL_ADDRESS phys;
    7.     PVOID pAddr;
    8.  
    9.     phys.QuadPart = 0xFEC00000;
    10.     pAddr = MmMapIoSpace( phys, 0x1000, MmNonCached );
    11.     if( pAddr == NULL )
    12.         return 0;
    13.  
    14.     pIoRegSel = (unsigned char *) pAddr;
    15.     pIoWin = (unsigned char *) (pAddr) + 0x10;
    16.  
    17.     *pIoRegSel = 0x10 + irqnum * 2;  
    18.     ch = *pIoWin;
    19.  
    20.     MmUnmapIoSpace( pAddr, 0x1000 );
    21.  
    22.     return ch;
    23. }
    первая непонятка в том что почему то эта функция всегда возращает 0xFF, будь то IRQ0 или IRQ1, или ....

    далее есть структура IDT
    Код (Text):
    1. typedef struct _idt
    2. {
    3.     WORD l_offs;
    4.     WORD sel;
    5.     BYTE res;
    6.     union
    7.     {
    8.         BYTE attrs;
    9.         struct
    10.         {
    11.             BYTE type:4;
    12.             BYTE rs:1;
    13.             BYTE dpl:2;
    14.             BYTE p:1;
    15.         };
    16.     };
    17.     WORD h_offs;
    18. } idt;
    далее получаю таблицу idt следующим образом:

    Код (Text):
    1. idt *ptable;
    2.  
    3. __asm
    4. {
    5.     mov eax, [ptable]
    6.     sidt [eax]
    7. }
    и следовательно по идеи обработчик прерывания IRQ0 должен находиться в ptable[search_irq_vector( 0 )], но правильн оли это при search_irq_vector( 0 ) == 0xFF?

    и ещё есть вопрос по обработчику самого прерывания на данный момент он у меня выглядит следующим образом:
    Код (Text):
    1. __declspec( naked ) void Handler()
    2. {
    3.     PHYSICAL_ADDRESS APICAddr;
    4.     unsigned char * APICptr;
    5.  
    6.     __asm pushad;
    7.  
    8.     APICAddr.LowPart = 0xFEE00000;
    9.     APICAddr.HighPart = 0;
    10.     APICptr = (unsigned char *) MmMapIoSpace( APICAddr, 0x1000, MmNonCached );
    11.  
    12.     if( APICptr != NULL )
    13.     {
    14.         // тут делаем свои надобности
    15.  
    16.         __asm
    17.         {
    18.             mov eax, APICptr
    19.             add eax, 0x0B0
    20.             mov ebx, 0x0               
    21.             mov [eax], ebx      // сообщанем APIC что мы закончили обработку прерывания
    22.         }
    23.  
    24.         MmUnmapIoSpace( APICptr, 0x1000 );
    25.     }
    26.  
    27.     __asm
    28.     {
    29.         popad
    30.         jmp [oldisr]
    31.     }
    32. }
    всё ли я корректно делаю?

    ещё хоетлось бы узнать как можно MmMapIoSpace заменить на ассемблерный код, уж очень не красиво смотриться перемешка asm и С... хотелось бы что бы было всё единообразно.
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    У меня по началу тоже бсодило, когда устанавливал коэфициен деления 128, меньше работает. Видимо ОС использует прерывания от этого таймера для планирования(прерывание #FDh).
    Без MmMapIoSpace можно попробовать сборкой: записать в память код(например mov eax,dword ptr ds:[Address]),
    а затем записать вместо Address, виртуальный адрес регистра.
    Я не могу понять что делает search_irq_vector(), ищет адре обработчика прерывания по его номеру в IDT ?
     
  8. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    search_irq_vector ищёт номер записи в таблицы IDT для конкретного прерывания.
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Код (Text):
    1. IDTR_FIELD struct
    2. _Limit  WORD ?  ;Предел таблицы IDT(её размер)
    3. _Base   PVOID ? ;Адрес начала IDT
    4. IDTR_FIELD ends
    5. PIDTR_FIELD typedef ptr IDTR_FIELD
    6.  
    7. INTERRUPT_GATE struct   ;Дескриптор шлюза прерывания в IDT
    8. OffsetLo        WORD ?          ;Bits 0-15
    9. Selector        WORD ?          ;Bits 16-31
    10. AccessRights    WORD ?
    11. comment '
    12. RECORD \
    13.             _Present:1,     ;Bits 15 Присутствие сегмента в памяти. Если этот бит установлен, то сегмент есть в памяти, если сброшен, то его нет.        
    14.             _Dpl:2          ;Bits 13-14 Поле DPL (Descriptor Privilege Level) - Уровень привилегий, который имеет объект, описываемый данным дескриптором.
    15.             _System:1,      ;Bits 12 Бит S (System) - определяет системный объект. Если этот бит установлен, то дескриптор определяет сегмент кода или данных, а если сброшен, то системный объект (например, сегмент состояния задачи, локальную дескрипторную таблицу, шлюз).
    16.             _Default_Big:1, ;Bits 11 D - это размер шлюза: 1 = 32 бита; 0 = 16 бит.
    17.             _Type:3,            ;Bits 8-10 [110]
    18.             _Undefined1:8'
    19. OffsetHi        WORD ?     
    20. INTERRUPT_GATE ends
    21. PINTERRUPT_GATE typedef ptr INTERRUPT_GATE
    22.  
    23. GetInterruptVector proc InterruptNumber:ULONG
    24. Local Descriptor:IDTR_FIELD
    25. ;Определяет вектор прерывания для текущего процессора.
    26. ;Не проверяет на корректность параметры.
    27. ;Вход: InterruptNumber - номер прерывания
    28. ;Выход: Eax:Вектор, Edx:Селектор, Ecx:Атрибуты
    29.     cli
    30.     sidt Descriptor
    31.     mov eax,InterruptNumber
    32.     mov edx,Descriptor._Base    ;адрес IDT
    33.     lea edx,[edx+eax*SizeOf INTERRUPT_GATE]
    34.     assume edx:PINTERRUPT_GATE
    35.     movzx eax,[edx].OffsetHi
    36.     shl eax,16
    37.     movzx ecx,[edx].AccessRights
    38.     or ax,[edx].OffsetLo
    39.     mov dx,[edx].Selector
    40.     movzx ecx,cx
    41.     movzx edx,dx
    42.     sti
    43.     ret
    44. GetInterruptVector endp
    45.  
    46. SetInterruptVector proc PrivilegeLevel:ULONG, InterruptNumber:ULONG, Vector:PVOID, Selector:ULONG
    47. Local Descriptor:IDTR_FIELD
    48. ;Устанавливает вектор прерывания для текущего процессора.
    49. ;Не проверяет на корректность параметры.
    50.     cli
    51.     sidt Descriptor
    52.     mov eax,InterruptNumber
    53.     mov edx,Descriptor._Base    ;адрес IDT
    54.     lea edx,[edx+eax*SizeOf INTERRUPT_GATE]
    55.     assume edx:PINTERRUPT_GATE
    56.     mov eax,Vector
    57.     mov [edx].OffsetLo,ax
    58.     shr eax,16
    59.     mov [edx].OffsetHi,ax
    60.     mov eax,Selector
    61.     mov [edx].Selector,ax
    62.     mov eax,PrivilegeLevel
    63.     mov [edx].AccessRights,1000111000000000b
    64.     .if Eax
    65.     or [edx].AccessRights,0110000000000000b
    66.     .endif
    67.     sti
    68.     ret
    69. SetInterruptVector endp
    70.  
    71. IsValidInterruptGate proc InterruptNumber:ULONG
    72. Local Descriptor:IDTR_FIELD
    73. ;Проверяет корректность шлюза прерывания для текущего процессора.
    74. ;Вход: InterruptNumber - номер прерывания
    75.     cli
    76.     mov eax,InterruptNumber
    77.     sidt Descriptor
    78.     lea eax,[eax*SizeOf INTERRUPT_GATE]
    79.     cmp ax,Descriptor._Limit
    80.     jnc error_
    81.     mov edx,Descriptor._Base    ;адрес IDT
    82.     lea edx,[edx+eax]
    83.     assume edx:PINTERRUPT_GATE
    84.     movzx eax,[edx].OffsetHi
    85.     shl eax,16 
    86.     or ax,[edx].OffsetLo
    87.     test eax,eax
    88.     jz error_
    89.     movzx edx,[edx].Selector
    90.     test dx,dx
    91.     jz error_
    92.     movzx eax,[edx].AccessRights
    93.     test eax,1000000000000000b
    94.     jz error_
    95.     test eax,0001000000000000b
    96.     jnz error_
    97.     and ah,111b
    98.     cmp ah,110b
    99.     jz exit_
    100. error_:
    101.     xor eax,eax
    102. exit_:
    103.     sti
    104.     ret
    105. IsValidInterruptGate endp
     
  10. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    в спецификации на I/O APIC по поводу Data Register написано следующее
    а у тебя насколько я вижу идет не 32-х разрядный доступ к нему
     
  11. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    2rei3er

    Указатели дело такое(что DWORD*, что BYTE* - разница будет только в смещенгиях от начала указателя)... я завтра попробую сменить тип данных, но не думаю что это что то изменит.
    А может быть так что если не задан обработчик прерывания то значение будет 0xFF и нужно будет заводить самому (руками) запись в таблице?
     
  12. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    2Clerk

    Спасибо попробую завтра в Вашим методом.
     
  13. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    есть какие-нибудь замечания по обработчику прерывания от local APIC timer? (ну малоли, моя грамотность может наделать и 3 ошибки в одном слове....)
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Вот чтото нашёл:
    http://www.o3one.org/sources/oz_hw_smproc_486.s
     
  15. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    2Clerk

    спасибо, попробую разобраться что там написано (читаеться ооочень тяжело)...
     
  16. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    тот адресс что я получаю через sidt для самой таблицы IDT, я так понимаю его нужно тоже преобразовывать через MmMapIoSpace, что бы можно было с ним работать? или нет?
     
  17. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    нет
    он линейный
    не всегда
    я тоже не думаю ;)
    думаю, такое вполне вероятно
    но не для всех же линий IRQ
    кстати, какой у тебя чипсет?
     
  18. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    2rei3er

    не знаю (уже не на работе), а что от разных чипсетов может что-то поменяться?
     
  19. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    адрес 0xFEC00000 нигде не стандартизован, т. е есть вероятность, что где-то он может быть другим
     
  20. Hairy

    Hairy Сёма

    Публикаций:
    0
    Регистрация:
    25 янв 2008
    Сообщения:
    39
    Адрес:
    Ад на земле
    хм.. как вариант стоит проверить.. а это можно узнать из cpuid или каких нибудь MSR (как например адрес регистров для local APIC)? (завтра то я скорее всего найду эту информацию на работе, но если Вы её знаете может поделитесь?) ;)