deroko
February 8th, 2008, 12:00
SoftICE uses drX to perform step over. One interesting question is how does it do that on MP system? It could happen that thread is running at one CPU, but code which is executed in certain procedure could switch to different CPU, and still SoftICE manages to stepover correctly. How is that possible? Using IPI, of course.
The best example is this code if steped over in SoftICE:
both calls will be steped over correctly, and that's because SoftICE sends IPI with Shorthand = All excluding self set in ICR to set drXes on both CPUs.
I also wrote earlier that softice changes NMI handler from TaskGate to IdtGate on single cpu machine, but when I viewed IDT on MP system from SoftICE, it used TaskGate to hook NMI. So there are certain rules which have to be followed when drX access occurs from NMI and TaskGate.
Handler must NOT iret if access to drX occurs from NMI, because iret will unblock NMI. Handler also must not use DbgPrint, or anything else that can trigger iret when executing from NMI...
Also if we are in NMI, SoftIce won't clear NT flag in eflags, so any iret will lead to previous task. We can avoid this problem by clearing NT flag, but again, we unblock NMI using iret, so this is sidenote, not a real problem.
This problem with iret is solved easily, by changing the way we return from int1 when it's caused from NMI:
Bingo... dr7.GD is now working in mp system running sice
The best example is this code if steped over in SoftICE:
Code:
KeSetAffinityThread(cur_thread, 1<<0);
KeSetAffinityThread(cur_thread, 1<<1);
both calls will be steped over correctly, and that's because SoftICE sends IPI with Shorthand = All excluding self set in ICR to set drXes on both CPUs.
I also wrote earlier that softice changes NMI handler from TaskGate to IdtGate on single cpu machine, but when I viewed IDT on MP system from SoftICE, it used TaskGate to hook NMI. So there are certain rules which have to be followed when drX access occurs from NMI and TaskGate.
Handler must NOT iret if access to drX occurs from NMI, because iret will unblock NMI. Handler also must not use DbgPrint, or anything else that can trigger iret when executing from NMI...
Also if we are in NMI, SoftIce won't clear NT flag in eflags, so any iret will lead to previous task. We can avoid this problem by clearing NT flag, but again, we unblock NMI using iret, so this is sidenote, not a real problem.
This problem with iret is solved easily, by changing the way we return from int1 when it's caused from NMI:
Code:
__s0: str ax ;get task register
cmp ax, 58h ;check if it is NMI
je __nmi
pop es ;not NMI so exit normally
pop ds
pop fs
popad
iretd
__nmi: mov eax, [esp.regEflags]
push eax ;NMI!! - restore eflags
popfd
pop es ;r0 epilog
pop ds
pop fs
popad
retn 8 ;ret to interupted code and
;clear cs/eflags stored on
;stack...
Bingo... dr7.GD is now working in mp system running sice
