confused about use of KeSetSystemGroupAffinityThread

Hello,

I’m new to kernel / driver developing and have some questions on KeSetSystemGroupAffinityThread routine.

Like described in the help documents of the currend WinDDK it should change affinity of the current thread. If you got Win7 or later.

I wanted to read out some MSR registers from a processor.
To do this i made an IOCTL. When you call it you need to give it a PROCESSOR_NUMBER variable as input buffer.

I tried it this way (but it didn’t work):


ULONGLONG PState = 0;
PROCESSOR_NUMBER TargetProcessor;
PROCESSOR_NUMBER CurrentProcessor;
GROUP_AFFINITY TargetGroupAffinityThread;
GROUP_AFFINITY UserGroupAffinityThread; // affinity of user mode thread

RtlCopyMemory(&TargetProcessor, Irp->AssociatedIrp.SystemBuffer, sizeof(PROCESSOR_NUMBER));

KeGetCurrentProcessorNumberEx(&CurrentProcessor);

if(TargetProcessor.Group != CurrentProcessor.Group || TargetProcessor.Number != CurrentProcessor.Number)
{
TargetGroupAffinityThread.Group = TargetProcessor.Group;
TargetGroupAffinityThread.Mask = (KAFFINITY)1 << TargetProcessor.Number;

KeSetSystemGroupAffinityThread(&TargetGroupAffinityThread, &UserGroupAffinityThread);
}

// getting current pstate
// just the last 2 bits needed;
PState = __readmsr(0xC0010063) & 0x3;

*(PULONGLONG)Irp->AssociatedIrp.SystemBuffer = PState;
Irp->IoStatus.Information = 8;

if(TargetProcessor.Group != CurrentProcessor.Group || TargetProcessor.Number != CurrentProcessor.Number)
{
KeRevertToUserGroupAffinityThread(&UserGroupAffinityThread);
}

Looked okay for me, but it didn’t work, what ever PROCESSOR_NUMBER was set to.

I tried out a bit and the finaly working code just needs 5 more declared variables.
I didn’t even asigned any value to them!

HANDLE hThread;
KIRQL CurrentIrql;
KAFFINITY TargetAffinityThread;
PGROUP_AFFINITY pTargetGroupAffinityThread;
PGROUP_AFFINITY pUserGroupAffinityThread;

The hTread variable needs to be declared inside the if statement. If it is declared before, it will not work.

So, code now looks like this:


ULONGLONG PState = 0;
PROCESSOR_NUMBER TargetProcessor;
PROCESSOR_NUMBER CurrentProcessor;
GROUP_AFFINITY TargetGroupAffinityThread;
GROUP_AFFINITY UserGroupAffinityThread; // affinity of user mode thread
// declared but didn’t asigend any value
KIRQL CurrentIrql;
KAFFINITY TargetAffinityThread;
PGROUP_AFFINITY pTargetGroupAffinityThread;
PGROUP_AFFINITY pUserGroupAffinityThread;

RtlCopyMemory(&TargetProcessor, Irp->AssociatedIrp.SystemBuffer, sizeof(PROCESSOR_NUMBER));

KeGetCurrentProcessorNumberEx(&CurrentProcessor);

if(TargetProcessor.Group != CurrentProcessor.Group || TargetProcessor.Number != CurrentProcessor.Number)
{
HANDLE hThread; // needs to be here, any where else will not work
TargetGroupAffinityThread.Group = TargetProcessor.Group;

TargetGroupAffinityThread.Mask = (KAFFINITY)1 << TargetProcessor.Number;

KeSetSystemGroupAffinityThread(&TargetGroupAffinityThread, &UserGroupAffinityThread);
}

// getting current pstate
// just the last 2 bits needed;
PState = __readmsr(0xC0010063) & 0x3;

*(PULONGLONG)Irp->AssociatedIrp.SystemBuffer = PState;
Irp->IoStatus.Information = 8;

if(TargetProcessor.Group != CurrentProcessor.Group || TargetProcessor.Number != CurrentProcessor.Number)
{
KeRevertToUserGroupAffinityThread(&UserGroupAffinityThread);
}

That’s it - it works, but why?

Do you know “the magic” of those 2 variables i declared or what i am doing wrong?

Sorry for my english, I hope its not too bad. :slight_smile:

Greetings
Michael