WRMSR causes triple fault
Posted: Wed Sep 22, 2004 8:43 pm
Okay... this is a very strange problem that has been puzzling me for days. I am trying to write to the MSRs necessary to set up SYSENTER/SYSEXIT system calls, and when I call wrmsr, the computer triple faults. (my WriteMSR is included below).
The strange problem about this is that my interrupt handling is known to work. If I place an "int 3" before the wrmsr, my kernel dumps the register states to the screen. EDX:EAX and ECX match what I would expect for the wrmsr instruction. If I place the "int 3" after the wrmsr instruction, the triple fault occurs. There is plenty of stack space (ie. it is not a kmode stack overflow triple fault).
Furthermore, it works fine under Bochs and on a Pentium 3 processor. The actual system call also works fine. It does not work on all the Pentium 4 computers that I have at home, but I cannot find any documentation in the Intel manuals about changes in MSR functionality. Interrupts are disabled and it is ring 0 code.
Also, according to the documentation, a #GP is generated if the MSR number is out of range or if reserved bits are set. I know that it is not GPF'ing since I successfully receive a GPF if I intentionally choose an invalid MSR address.
The register states reported by the int3 instruction are absolutely identical on both a working machine and a nonworking machine:
My GDT is set up correctly (ring 0 code, ring 0 data, ring 3 code, ring 3 data), since everything works fine on another computer and on bochs.
Sorry about the long read, but I wanted to ensure I gave enough information to solve the problem. It seems very suspicious to me. I want to know if anyone can see anything obviously wrong with this, or if you think something else is corrupt. Any ideas, even "did you turn your computer on"-type questions are fine, since I feel I am overlooking the obvious.
Thanks in advance.
The strange problem about this is that my interrupt handling is known to work. If I place an "int 3" before the wrmsr, my kernel dumps the register states to the screen. EDX:EAX and ECX match what I would expect for the wrmsr instruction. If I place the "int 3" after the wrmsr instruction, the triple fault occurs. There is plenty of stack space (ie. it is not a kmode stack overflow triple fault).
Furthermore, it works fine under Bochs and on a Pentium 3 processor. The actual system call also works fine. It does not work on all the Pentium 4 computers that I have at home, but I cannot find any documentation in the Intel manuals about changes in MSR functionality. Interrupts are disabled and it is ring 0 code.
Also, according to the documentation, a #GP is generated if the MSR number is out of range or if reserved bits are set. I know that it is not GPF'ing since I successfully receive a GPF if I intentionally choose an invalid MSR address.
The register states reported by the int3 instruction are absolutely identical on both a working machine and a nonworking machine:
Code: Select all
IoDumpContext() : ISR 0x03, code 0x00000000
EAX=0x803007FE ECX=0x00000176 EDX=0x00000000 EBX=0x00003A10 ESP=0x80006FBC
EBP=0x80006FEC ESI=0x00003A10 EDI=0x00000000 EIP=0x80302EBC EFL=0x00000046
CR0=0x80000011 CR1=0x00000000 CR2=0x00000000 CR3=0x00100000 CR4=0x00000000
CS=0x0008 DS=0x0010 ES=0x0010 FS=0x0010 GS=0x0010 SS=0x0010
Code: Select all
; void WriteMSR(unsigned int msr, unsigned int lowval)
_WriteMSR@8:
mov ecx, dword ptr [esp+4]
mov eax, dword ptr [esp+8]
xor edx, edx
wrmsr
ret 8
Thanks in advance.