|
|
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
|