windows-nt/Source/XPSP1/NT/base/hals/halx86/i386/ixmcaa.asm
2020-09-26 16:20:57 +08:00

300 lines
7.1 KiB
NASM

;++
;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
KGDT_MCA_TSS EQU 0A0H
MINIMUM_TSS_SIZE EQU TssIoMaps
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TEXT Segment
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_TEXT SEGMENT PARA PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.586p
;++
;
;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
_TEXT ends
INIT SEGMENT DWORD PUBLIC 'CODE'
;++
;VOID
;HalpMcaCurrentProcessorSetTSS(
; IN PULONG pTSS // MCE TSS area for this processor
; )
; Routine Description:
; This function sets up the TSS for MCA exception 18
;
; Arguments:
; pTSS : Pointer to the TSS to be used for MCE
;
; Return Value:
; None
;
;--
cPublicProc _HalpMcaCurrentProcessorSetTSS,1
;
; 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, [esp+4] ; the address of TSS in edx
;
; Set various fields in TSS
;
mov eax, cr3
mov [edx + TssCR3], eax
;
; Get double fault stack 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]
;
; Set address of MCA Exception stack to double fault stack address
;
mov dword ptr [edx+038h], ecx ; Set ESP
mov dword ptr [edx+TssEsp0], ecx ; 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
INIT ends
PAGELK SEGMENT DWORD PUBLIC 'CODE'
;++
;
;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
PAGELK ends
end