summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halx86/i386/ixmcaa.asm
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halx86/i386/ixmcaa.asm
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/halx86/i386/ixmcaa.asm')
-rw-r--r--private/ntos/nthals/halx86/i386/ixmcaa.asm420
1 files changed, 420 insertions, 0 deletions
diff --git a/private/ntos/nthals/halx86/i386/ixmcaa.asm b/private/ntos/nthals/halx86/i386/ixmcaa.asm
new file mode 100644
index 000000000..229621892
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixmcaa.asm
@@ -0,0 +1,420 @@
+;++
+;Module Name
+; imca.asm
+;
+;Abstract:
+; Assembly support needed for Intel MCA
+;
+; Author:
+; Anil Aggarwal (Intel Corp)
+;
+;Revision History:
+;
+;
+;--
+
+.586p
+ .xlist
+include hal386.inc
+include callconv.inc
+include i386\kimacro.inc
+ .list
+
+ EXTRNP _HalpMcaExceptionHandler,0
+ EXTRNP _KeBugCheckEx,5,IMPORT
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; DATA Segment
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+_DATA SEGMENT PARA PUBLIC 'DATA'
+;
+; MCA Exception task stack
+;
+
+MINIMUM_TSS_SIZE EQU TssIoMaps
+
+if DBG
+;
+; If we use DbgPrint, we need a larger stack
+;
+MCA_EXCEPTION_STACK_SIZE EQU 01000H
+else
+MCA_EXCEPTION_STACK_SIZE EQU 0100H
+endif
+
+KGDT_MCA_TSS EQU 0A0H
+
+
+ ;
+ ; TSS for MCA Exception
+ ;
+ align 16
+
+ public _HalpMcaExceptionTSS
+_HalpMcaExceptionTSS label byte
+ db MINIMUM_TSS_SIZE dup(0)
+
+ ;
+ ; Stack for MCA exception task
+ ;
+
+ public _HalpMcaExceptionStack
+ db MCA_EXCEPTION_STACK_SIZE dup ("*")
+_HalpMcaExceptionStack label byte
+
+_DATA ends
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; TEXT Segment
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ .586p
+
+;++
+;ULONGLONG
+;FASTCALL
+;RDMSR(
+; IN ULONG MsrAddress
+; )
+; Routine Description:
+; This function reads an MSR
+;
+; Arguments:
+; Msr: The address of MSR to be read
+;
+; Return Value:
+; Returns the low 32 bit of MSR in eax and high 32 bits of MSR in edx
+;
+;--
+cPublicFastCall RDMSR,1
+
+ rdmsr
+ fstRET RDMSR
+
+fstENDP RDMSR
+
+;++
+;
+;VOID
+;WRMSR(
+; IN ULONG MsrAddress,
+; IN ULONGLONG MsrValue
+; )
+; Routine Description:
+; This function writes an MSR
+;
+; Arguments:
+; Msr: The address of MSR to be written
+; Data: The value to be written to the MSR register
+;
+; Return Value:
+; None
+;
+;--
+
+cPublicProc _WRMSR,3
+
+ mov ecx, [esp + 4] ; MsrAddress
+ mov eax, [esp + 8] ; Low 32 bits of MsrValue
+ mov edx, [esp + 12] ; High 32 bits of MsrValue
+
+ wrmsr
+ stdRET _WRMSR
+
+stdENDP _WRMSR
+
+;++
+;
+;VOID
+;HalpSerialize(
+; VOID
+; )
+;
+; Routine Description:
+; This function implements the fence operation for out-of-order execution
+;
+; Arguments:
+; None
+;
+; Return Value:
+; None
+;
+;--
+
+cPublicProc _HalpSerialize,0
+
+ push ebx
+ xor eax, eax
+ cpuid
+ pop ebx
+
+ stdRET _HalpSerialize
+
+stdENDP _HalpSerialize
+
+
+;++
+;
+; Routine Description:
+;
+; Machine Check exception handler
+;
+;
+; Arguments:
+;
+; Return value:
+;
+; If the error is non-restartable, we will bugcheck.
+; Otherwise, we just return
+;
+;--
+ ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
+align dword
+ public _HalpMcaExceptionHandlerWrapper
+_HalpMcaExceptionHandlerWrapper proc
+.FPO (0, 0, 0, 0, 0, 2)
+
+ cli
+
+ ;
+ ; Update the TSS pointer in the PCR to point to the MCA TSS
+ ; (which is what we're running on, or else we wouldn't be here)
+ ;
+
+ push dword ptr PCR[PcTss]
+ mov eax, PCR[PcGdt]
+ mov ch, [eax+KGDT_MCA_TSS+KgdtBaseHi]
+ mov cl, [eax+KGDT_MCA_TSS+KgdtBaseMid]
+ shl ecx, 16
+ mov cx, [eax+KGDT_MCA_TSS+KgdtBaseLow]
+ mov PCR[PcTss], ecx
+
+ ;
+ ; Clear the busy bit in the TSS selector
+ ;
+ mov ecx, PCR[PcGdt]
+ lea eax, [ecx] + KGDT_MCA_TSS
+ mov byte ptr [eax+5], 089h ; 32bit, dpl=0, present, TSS32, not busy
+
+ ;
+ ; Clear Nested Task bit in EFLAGS
+ ;
+ pushfd
+ and [esp], not 04000h
+ popfd
+
+ ;
+ ; Check if there is a bugcheck-able error. If need to bugcheck, the
+ ; caller does it.
+ ;
+ stdCall _HalpMcaExceptionHandler
+
+ ;
+ ; We're back which means that the error was restartable.
+ ;
+
+ pop dword ptr PCR[PcTss] ; restore PcTss
+
+ mov ecx, PCR[PcGdt]
+ lea eax, [ecx] + KGDT_TSS
+ mov byte ptr [eax+5], 08bh ; 32bit, dpl=0, present, TSS32, *busy*
+
+ pushfd ; Set Nested Task bit in EFLAGS
+ or [esp], 04000h ; so iretd will do a tast switch
+ popfd
+
+ iretd ; Return from MCA Exception handler
+ jmp short _HalpMcaExceptionHandlerWrapper
+ ; For next Machine check exception
+
+_HalpMcaExceptionHandlerWrapper endp
+
+;++
+;
+; Routine Description:
+;
+; MCA exception is run off a small stack pointed to by MCA TSS. When
+; the error is non-restartable, this routine is called to switch to a larger
+; stack which is the overlay of ZW thunks (as is done for double fault stack)
+;
+; Arguments:
+;
+; The arguments to KeMachineCheck are passed to this function
+;
+; Return value:
+;
+; Never returns. End up doing the bugcheck.
+;
+;--
+
+cPublicProc _HalpMcaSwitchMcaExceptionStackAndBugCheck,5
+
+ ; Get Task gate descriptor for double fault handler
+ mov ecx, PCR[PcIdt] ; Get IDT address
+ lea eax, [ecx] + 040h ; DF Exception is 8
+
+ ; Get to TSS Descriptor of double fault handler TSS
+ xor ecx, ecx
+ mov cx, word ptr [eax+2]
+ add ecx, PCR[PcGdt]
+
+ ; Get the address of TSS from this TSS Descriptor
+ mov ah, [ecx+KgdtBaseHi]
+ mov al, [ecx+KgdtBaseMid]
+ shl eax, 16
+ mov ax, [ecx+KgdtBaseLow]
+
+ ; Get ESP from DF TSS
+ mov ecx, [eax+038h]
+
+ ; Save the passed arguments before we switch the stacks
+ mov eax, [esp+4]
+ mov ebx, [esp+8]
+ mov edx, [esp+12]
+ mov esi, [esp+16]
+ mov edi, [esp+20]
+
+ ; Use the ZW thunk area for the stack to operate on for crash
+ mov esp, ecx
+
+ stdCall _KeBugCheckEx, <eax, ebx, edx, esi, edi>
+
+ stdRET _HalpMcaSwitchMcaExceptionStackAndBugCheck
+
+stdENDP _HalpMcaSwitchMcaExceptionStackAndBugCheck
+
+_TEXT ends
+
+INIT SEGMENT DWORD PUBLIC 'CODE'
+
+;++
+;VOID
+;HalpMcaCurrentProcessorSetTSS(
+; VOID
+; )
+; Routine Description:
+; This function sets up the TSS for MCA exception 18
+;
+; Arguments:
+; Context: We don't care about this but is there since HalpGenericCall
+; needs one
+;
+; Return Value:
+; None
+;
+;--
+
+cPublicProc _HalpMcaCurrentProcessorSetTSS,0
+
+ ;
+ ; Edit IDT Entry for MCA Exception (18) to contain a task gate
+ ;
+ mov ecx, PCR[PcIdt] ; Get IDT address
+ lea eax, [ecx] + 090h ; MCA Exception is 18
+ mov byte ptr [eax + 5], 085h ; P=1,DPL=0,Type=5
+ mov word ptr [eax + 2], KGDT_MCA_TSS ; TSS Segment Selector
+
+ mov edx, offset FLAT:_HalpMcaExceptionTSS ; the address of TSS in edx
+
+ ;
+ ; Set various fields in TSS
+ ;
+ mov eax, cr3
+ mov [edx + TssCR3], eax
+
+ mov eax, offset FLAT:_HalpMcaExceptionStack; address of MCA Exception stack
+ mov dword ptr [edx+038h], eax ; Set ESP
+ mov dword ptr [edx+TssEsp0], eax ; Set ESP0
+
+ mov dword ptr [edx+020h], offset FLAT:_HalpMcaExceptionHandlerWrapper ; set EIP
+ mov dword ptr [edx+024h], 0 ; set EFLAGS
+ mov word ptr [edx+04ch],KGDT_R0_CODE ; set value for CS
+ mov word ptr [edx+058h],KGDT_R0_PCR ; set value for FS
+ mov [edx+050h], ss
+ mov word ptr [edx+048h],KGDT_R3_DATA OR RPL_MASK ; Es
+ mov word ptr [edx+054h],KGDT_R3_DATA OR RPL_MASK ; Ds
+
+ ;
+ ; Part that gets done in KiInitialiazeTSS()
+ ;
+ mov word ptr [edx + 08], KGDT_R0_DATA ; Set SS0
+ mov word ptr [edx + 060h],0 ; Set LDT
+ mov word ptr [edx + 064h],0 ; Set T bit
+ mov word ptr [edx + 066h],020adh ; I/O Map base address = sizeof(KTSS)+1
+
+ ;
+ ; Edit GDT entry for KGDT_MCA_TSS to create a valid TSS Descriptor
+ ;
+ mov ecx, PCR[PcGdt] ; Get GDT address
+ lea eax, [ecx] + KGDT_MCA_TSS ; offset of MCA TSS in GDT
+ mov ecx, eax
+
+ ;
+ ; Set Type field of TSS Descriptor
+ ;
+ mov byte ptr [ecx + 5], 089H ; P=1, DPL=0, Type = 9
+
+ ;
+ ; Set Base Address field of TSS Descriptor
+ ;
+ mov eax, edx ; TSS address in eax
+ mov [ecx + KgdtBaseLow], ax
+ shr eax, 16
+ mov [ecx + KgdtBaseHi],ah
+ mov [ecx + KgdtBaseMid],al
+
+ ;
+ ; Set Segment limit for TSS Descriptor
+ ;
+ mov eax, MINIMUM_TSS_SIZE
+ mov [ecx + KgdtLimitLow],ax
+
+ stdRET _HalpMcaCurrentProcessorSetTSS
+
+stdENDP _HalpMcaCurrentProcessorSetTSS
+
+
+;++
+;
+;VOID
+;HalpSetCr4MCEBit(
+; VOID
+; )
+;
+; Routine Description:
+; This function sets the CR4.MCE bit
+;
+; Arguments:
+; None
+;
+; Return Value:
+; None
+;
+;--
+
+cPublicProc _HalpSetCr4MCEBit,0
+
+ mov eax, cr4
+ or eax, CR4_MCE
+ mov cr4, eax
+ stdRET _HalpSetCr4MCEBit
+
+stdENDP _HalpSetCr4MCEBit
+
+
+INIT ends
+
+ end
+