читать на ядре 0 в Kernel Force

Тема в разделе "WASM.NT.KERNEL", создана пользователем zky02, 16 янв 2024.

  1. zky02

    zky02 New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2024
    Сообщения:
    4
    это правильный подход?


    Код (Text):
    1. class TSingleProcessorMode
    2. {
    3.     KDPC DpcTraps[MAXIMUM_PROCESSORS];
    4.     volatile LONGLONG Stall;
    5.     unsigned __int64 cr9;
    6.     KPRIORITY SavedPriority;
    7.     int  CpuCount;
    8.     static void DpcRoutine(KDPC* pDpc, void* pContext, void* pArg1, void* pArg2);
    9. public:
    10.     void Initialize();
    11.     void Enter();
    12.     void Exit();
    13. };
    14.  
    15. void TSingleProcessorMode::Initialize()
    16. {
    17.     RtlZeroMemory(this, sizeof(TSingleProcessorMode));
    18.     CpuCount = (int)KeQueryActiveProcessorCount(nullptr);
    19.     if (CpuCount > 1)
    20.     {
    21.         for (int i = 0; i < CpuCount; i++)
    22.         {
    23.             KeInitializeDpc(&DpcTraps[i], DpcRoutine, this);
    24.             KeSetImportanceDpc(&DpcTraps[i], LowImportance);
    25.             KeSetTargetProcessorDpc(&DpcTraps[i], i);
    26.         }
    27.     }
    28. }
    29.  
    30. void TSingleProcessorMode::DpcRoutine(KDPC* pDpc, void* pContext, void* pArg1, void* pArg2)
    31. {
    32.   TSingleProcessorMode* pThis = (TSingleProcessorMode*)pContext;
    33.   auto cr8 = __readcr8();
    34.   __writecr8(HIGH_LEVEL);
    35.   _disable();
    36.   InterlockedDecrement64(&pThis->Stall);
    37.   do
    38.   _mm_pause();
    39.   while (pThis->Stall > 0);
    40.   _enable();
    41.   __writecr8(cr8);
    42. }
    43.  
    44. void TSingleProcessorMode::Enter()
    45. {
    46.     cr9 = __readcr8();
    47.     if (CpuCount > 1)
    48.     {
    49.         SavedPriority = KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY - 1);
    50.         KAFFINITY ActiveProcessors = KeQueryActiveProcessors();
    51.         __writecr8(DISPATCH_LEVEL);
    52.         ULONG CurrentProcessor = (ULONG)KeGetCurrentProcessorNumber();
    53.         Stall = 1;
    54.  
    55.         for (int i = CpuCount - 1; i >= 0; i--)
    56.         {
    57.             if (i != CurrentProcessor && (ActiveProcessors & (1ull << i)) != 0)
    58.             {
    59.                 InterlockedIncrement64(&Stall);
    60.                 KeInsertQueueDpc(&DpcTraps[i], 0, 0);
    61.             }
    62.         }
    63.  
    64.         __writecr8(cr9);
    65.  
    66.  
    67.         while (InterlockedAdd64(&Stall, -1) > 0)
    68.         {
    69.             _mm_pause();
    70.         }
    71.  
    72.         __writecr8(HIGH_LEVEL);
    73.         _disable();
    74.     }
    75.     else
    76.     {
    77.         __writecr8(HIGH_LEVEL);
    78.         _disable();
    79.     }
    80. }
    81.  
    82. void TSingleProcessorMode::Exit()
    83. {
    84.     if (CpuCount > 1)
    85.     {
    86.         InterlockedExchange64(&Stall, -1);
    87.         _enable();
    88.         __writecr8(cr9);
    89.         KeSetPriorityThread(KeGetCurrentThread(), SavedPriority);
    90.     }
    91.     else
    92.     {
    93.         _enable();
    94.         __writecr8(cr9);
    95.     }
    96. }
    --- Сообщение объединено, 17 янв 2024 ---
    Проблема в том, что чтение происходит на ядре 6, а не на ядре 0.

    [​IMG]
     
    Последнее редактирование: 17 янв 2024
  2. comrade

    comrade Константин Ёпрст

    Публикаций:
    0
    Регистрация:
    16 сен 2002
    Сообщения:
    232
    Адрес:
    Russian Federation
    &DpcTraps[[index]] а не &DpcTraps ? линии 23-26. Иначе получается что атрибуты ставятся только на первый элемент массива
     
  3. zky02

    zky02 New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2024
    Сообщения:
    4
    Да, я исправил ошибку. Теперь, как остановить все процессоры и поставить в очередь только на нулевом ядре
     
  4. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.406
    Адрес:
    Россия, Нижний Новгород
    Можешь сделать KeSetSystemAffinityThreadEx своему потоку, назначив его на нужное тебе ядро (на нулевое), после этого всем другим ядрам отправляешь DPC со спинлоком.
    В этом случае текущий поток гарантированно будет выполняться на нужном тебе ядре, а все другие потоки будут ждать.
    И насчёт прерываний, поднимать IRQL до HIGH_LEVEL или отключать прерывания не требуется, т.к. на DISPATCH_LEVEL планировщик уже не работает.
    А если надо отключить все прерывания, то cli достаточно, поднимать в cr8 не требуется, т.к. cli равнозначен поднятию до HIGH_LEVEL, и прервать его могут только NMI и SMI.
     
    comrade, zky02 и q2e74 нравится это.
  5. zky02

    zky02 New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2024
    Сообщения:
    4
    :drinks: большое спасибо
     
  6. zky02

    zky02 New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2024
    Сообщения:
    4
    Я нашел еще один хороший способ чтения в ядре 0
    Замените 6 на ваше максимальное количество процессоров

    Код (Text):
    1. const ULONG numberOfProcessors = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
    2.     PROCESSOR_NUMBER processorNumber;
    3.  
    4.     NTSTATUS Status = KeGetProcessorNumberFromIndex(numberOfProcessors - 6, &processorNumber);
    5.     if (!NT_SUCCESS(Status))
    6.     {
    7.         return;
    8.     }
    9.  
    10.     processorNumber.Group;
    11.     processorNumber.Number;
    12.  
    13.      Status = ZwSetInformationThread(ZwCurrentThread(), ThreadIdealProcessorEx, &processorNumber, sizeof(processorNumber));
    14.     if (!NT_SUCCESS(Status))
    15.         return;
    16.  
    17.     KAFFINITY ProcessAffinity = (KAFFINITY)(1ull << processorNumber.Number);
    18.      Status = ZwSetInformationProcess(ZwCurrentProcess(), ProcessAffinityMask, &ProcessAffinity, sizeof(ProcessAffinity));
    19.     if (!NT_SUCCESS(Status))
    20.         return;
    21.     KAFFINITY ThreadAffinity = (KAFFINITY)(1ull << processorNumber.Number);
    22.     Status = ZwSetInformationThread(ZwCurrentThread(), ThreadAffinityMask, &ThreadAffinity, sizeof(ThreadAffinity));
    23.     if (!NT_SUCCESS(Status))
    24.         return;
    [​IMG] :dance3:
     
  7. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.406
    Адрес:
    Россия, Нижний Новгород
    А это то же самое: внутри ZwSetInformationThread(ThreadAffinityMask) сведётся к KeSetSystemAffinityThreadEx.