windows-nt/Source/XPSP1/NT/base/hals/halacpi/amd64/amd64s.asm

434 lines
6.8 KiB
NASM
Raw Normal View History

2020-09-26 03:20:57 -05:00
TITLE "AMD64 Support Routines"
;++
;
; Copyright (c) 2000 Microsoft Corporation
;
; Module Name:
;
; miscs.asm
;
; Abstract:
;
; This module implements various routines for the AMD64 that must be
; written in assembler.
;
; Author:
;
; Forrest Foltz (forrestf) 14-Oct-2000
;
; Environment:
;
; Kernel mode only.
;
;--
include kxamd64.inc
include ksamd64.inc
extern HalpMcaExceptionHandler:proc
;++
;
; ULONG
; HalpGetprocessorFlags(
; VOID
; )
;
; Routine Description:
;
; This function retrieves and returns the contents of the processor's
; flag register.
;
; Arguments:
;
; None.
;
; Return Value:
;
; The contents of the processor's flag register.
;
;--
HdiFrame struct
FlagsLow dd ? ; processor flags, low
FlagsHi dd ? ; processor flags, high
HdiFrame ends
NESTED_ENTRY HalpGetProcessorFlags, _TEXT$00
push_eflags ; get processor flags
END_PROLOGUE
pop rax
ret
NESTED_END HalpGetProcessorFlags, _TEXT$00
;++
;
; VOID
; HalProcessorIdle(
; VOID
; )
;
; Routine Description:
;
; This function is called when the current processor is idle.
;
; This function is called with interrupts disabled, and the processor
; is idle until it receives an interrupt. The does not need to return
; until an interrupt is received by the current processor.
;
; This is the lowest level of processor idle. It occurs frequently,
; and this function (alone) should not put the processor into a
; power savings mode which requeres large amount of time to enter & exit.
;
; Return Value:
;
;--
LEAF_ENTRY HalProcessorIdle, _TEXT$00
;
; the following code sequence "sti-halt" puts the processor
; into a Halted state, with interrupts enabled, without processing
; an interrupt before halting. The STI instruction has a delay
; slot such that it does not take effect until after the instruction
; following it - this has the effect of HALTing without allowing
; a possible interrupt and then enabling interrupts while HALTed.
;
;
; On an MP hal we don't stop the processor, since that causes
; the SNOOP to slow down as well
;
sti
ifdef NT_UP
hlt
endif
;
; Now return to the system. If there's still no work, then it
; will call us back to halt again.
;
ret
LEAF_END HalProcessorIdle, _TEXT$00
;++
;
; VOID
; HalpGenerateAPCInterrupt(
; VOID
; )
;
; Routine Description:
;
; This function generates an APC software interrupt.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
LEAF_ENTRY HalpGenerateAPCInterrupt, _TEXT$00
int 1
ret
LEAF_END HalpGenerateAPCInterrupt, _TEXT$00
;++
;
; VOID
; HalpGenerateDPCInterrupt(
; VOID
; )
;
; Routine Description:
;
; This function generates an DPC software interrupt.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
LEAF_ENTRY HalpGenerateDPCInterrupt, _TEXT$00
int 2
ret
LEAF_END HalpGenerateDPCInterrupt, _TEXT$00
;++
;
; VOID
; HalpGenerateUnexpectedInterrupt(
; VOID
; )
;
; Routine Description:
;
; This function generates an unexpected software interrupt.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
LEAF_ENTRY HalpGenerateUnexpectedInterrupt, _TEXT$00
int 0
ret
LEAF_END HalpGenerateUnexpectedInterrupt, _TEXT$00
;++
;
; VOID
; HalpHalt (
; VOID
; );
;
; Routine Description:
;
; Executes a hlt instruction. Should the hlt instruction execute,
; control is returned to the caller.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--*/
LEAF_ENTRY HalpHalt, _TEXT$0
hlt
ret
LEAF_END HalpHalt, _TEXT$0
;++
;
; VOID
; HalpIoDelay (
; VOID
; );
;
; Routine Description:
;
; Generate a delay after port I/O.
;
; Arguments:
;
; None.
;
; Return Value:
;
; None.
;
;--
LEAF_ENTRY HalpIoDelay, _TEXT$00
jmp $+2
jmp $+2
ret
LEAF_END HalpIoDelay, _TEXT$00
;++
;
; VOID
; HalpSerialize (
; VOID
; )
;
; Routine Description:
;
; This function implements the fence operation for out-of-order execution
;
; Arguments:
;
; None
;
; Return Value:
;
; None
;
;--
HsFrame struct
SavedRbx dq ? ; preserve RBX
HsFrame ends
NESTED_ENTRY HalpSerialize, _TEXT$00
push_reg rbx
END_PROLOGUE
cpuid
pop rbx
ret
NESTED_END HalpSerialize, _TEXT$00
;++
;
; StartPx_LMStub
;
; This routine is entered during startup of a secondary processor. We
; have just left StartPx_PMStub (xmstub.asm) and are running on an
; identity-mapped address space.
;
; Arguments:
;
; rdi -> idenity-mapped address of PROCESSOR_START_BLOCK
;
; Return Value:
;
; None
;
;--
LEAF_ENTRY HalpLMStub, _TEXT$00
;
; Get the final CR3 value, set rdi to the self-map address of
; the processor start block, and set CR3. We are now executing
; in image-loaded code, rather than code that has been copied to
; low memory.
;
mov rax, [rdi] + PsbProcessorState + PsCr3
mov rdi, [rdi] + PsbSelfMap
mov cr3, rax
lea rsi, [rdi] + PsbProcessorState
ltr WORD PTR [rsi] + SrTr
;
; Load this processor's GDT and IDT. Because PSB_GDDT32_CODE64 is
; identical to KGDT64_R0_CODE (asserted in mpsproca.c), no far jump
; is necessary to load a new CS.
;
lgdt fword ptr [rsi] + PsSpecialRegisters + SrGdtr
lidt fword ptr [rsi] + PsSpecialRegisters + SrIdtr
;
; Set rdx to point to the context frame and load the segment
; registers.
;
lea rdx, [rdi] + PsbProcessorState + PsContextFrame
mov es, [rdx] + CxSegES
mov fs, [rdx] + CxSegFS
mov gs, [rdx] + CxSegGS
mov ss, [rdx] + CxSegSS
;
; Load the debug registers
;
cld
xor rax, rax
mov dr7, rax
add esi, SrKernelDr0
.errnz (SrKernelDr1 - SrKernelDr0 - 1 * 8)
.errnz (SrKernelDr2 - SrKernelDr0 - 2 * 8)
.errnz (SrKernelDr3 - SrKernelDr0 - 3 * 8)
.errnz (SrKernelDr6 - SrKernelDr0 - 4 * 8)
.errnz (SrKernelDr7 - SrKernelDr0 - 5 * 8)
lodsq
mov dr0, rax
lodsq
mov dr1, rax
lodsq
mov dr2, rax
lodsq
mov dr3, rax
lodsq
mov dr6, rax
lodsq
mov dr7, rax
;
; Load the stack pointer, eflags and store the new IP in
; a return frame. Also push two registers that will be used
; to the very end.
;
mov rsp, [rdx] + CxRsp
pushq [rdx] + CxEflags
popfq
pushq [rdx] + CxRip
push rdx
push rdi
mov rax, [rdx] + CxRax
mov rbx, [rdx] + CxRbx
mov rcx, [rdx] + CxRcx
mov rsi, [rdx] + CxRsi
mov rbp, [rdx] + CxRbp
mov r8, [rdx] + CxR8
mov r9, [rdx] + CxR9
mov r10, [rdx] + CxR10
mov r11, [rdx] + CxR11
mov r12, [rdx] + CxR12
mov r13, [rdx] + CxR13
mov r14, [rdx] + CxR14
mov r15, [rdx] + CxR15
;
; Indicate that we've started, pop the remaining two registers and
; return.
;
inc DWORD PTR [rdi] + PsbCompletionFlag
pop rdi
pop rsi
ret
LEAF_END HalpLMStub, _TEXT$00
END