[HAL/APIC/AMD64]

- add common amd64 asm trap macros
- fix amd64 version of HackEoi
- send EOI in amd64 trap exit code, so we avoid using HackEoi
- modify HalpClockInterruptHandler for better portability
- fix amd64 TscCalibrationISR

svn path=/trunk/; revision=53719
This commit is contained in:
Timo Kreuzer 2011-09-16 09:39:41 +00:00
parent 52d89c3b87
commit 4dfa3c52a3
5 changed files with 242 additions and 29 deletions

View file

@ -13,11 +13,10 @@
#ifdef _M_AMD64 #ifdef _M_AMD64
#include <ksamd64.inc> #include <ksamd64.inc>
#include <trapamd64.inc> #include <trapamd64.inc>
#define KI_PUSH_FAKE_ERROR_CODE TF_PUSH_FAKE_ERROR_CODE
.code .code
TRAP_ENTRY HalpClockInterrupt, KI_PUSH_FAKE_ERROR_CODE TRAP_ENTRY HalpClockInterrupt, (TF_VOLATILES OR TF_SEND_EOI)
TRAP_ENTRY HalpProfileInterrupt, KI_PUSH_FAKE_ERROR_CODE TRAP_ENTRY HalpProfileInterrupt, (TF_VOLATILES OR TF_SEND_EOI)
PUBLIC ApicSpuriousService PUBLIC ApicSpuriousService
ApicSpuriousService: ApicSpuriousService:
@ -37,6 +36,7 @@ HackEoi:
mov dword ptr [HEX(0FFFFFFFFFFFE00B0)], 0 mov dword ptr [HEX(0FFFFFFFFFFFE00B0)], 0
iretq iretq
HackEoiReturn: HackEoiReturn:
add rsp, 8 // esp was changed by the iret to the pushed value
ret ret
#else #else

View file

@ -109,32 +109,36 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
/* Enter trap */ /* Enter trap */
KiEnterInterruptTrap(TrapFrame); KiEnterInterruptTrap(TrapFrame);
#ifdef _M_AMD64
/* This is for debugging */
TrapFrame->ErrorCode = 0xc10c4;
#endif
/* Start the interrupt */ /* Start the interrupt */
if (HalBeginSystemInterrupt(CLOCK_LEVEL, HalpClockVector, &Irql)) if (!HalBeginSystemInterrupt(CLOCK_LEVEL, HalpClockVector, &Irql))
{ {
/* Read register C, so that the next interrupt can happen */ /* Spurious, just end the interrupt */
HalpReadCmos(RTC_REGISTER_C);; KiEoiHelper(TrapFrame);
/* Save increment */
LastIncrement = HalpCurrentTimeIncrement;
/* Check if someone changed the time rate */
if (HalpClockSetMSRate)
{
/* Set new clock rate */
RtcSetClockRate(HalpCurrentRate);
/* We're done */
HalpClockSetMSRate = FALSE;
}
/* Update the system time -- the kernel will exit this trap */
KeUpdateSystemTime(TrapFrame, LastIncrement, Irql);
} }
/* Spurious, just end the interrupt */ /* Read register C, so that the next interrupt can happen */
KiEoiHelper(TrapFrame); HalpReadCmos(RTC_REGISTER_C);;
/* Save increment */
LastIncrement = HalpCurrentTimeIncrement;
/* Check if someone changed the time rate */
if (HalpClockSetMSRate)
{
/* Set new clock rate */
RtcSetClockRate(HalpCurrentRate);
/* We're done */
HalpClockSetMSRate = FALSE;
}
/* Update the system time -- on x86 the kernel will exit this trap */
KeUpdateSystemTime(TrapFrame, LastIncrement, Irql);
} }
VOID VOID

View file

@ -55,10 +55,12 @@ _CalibrationISR_Exit:
EXTERN TscCalibrationPhase:BYTE EXTERN TscCalibrationPhase:BYTE
EXTERN TscCalibrationArray:DWORD EXTERN TscCalibrationArray:DWORD
EXTERN HalpSendEOI:PROC
PUBLIC TscCalibrationISR PUBLIC TscCalibrationISR
FUNC TscCalibrationISR FUNC TscCalibrationISR
push rax push rax
push rbx
push rcx push rcx
push rdx push rdx
.ENDPROLOG .ENDPROLOG
@ -74,17 +76,28 @@ FUNC TscCalibrationISR
jnb CalibrationISR_Exit jnb CalibrationISR_Exit
/* Store the current value */ /* Store the current value */
shl rcx, 1 shl rcx, 3
lea rax, [TscCalibrationArray] lea rbx, [TscCalibrationArray]
mov dword ptr [rax + rcx], eax mov dword ptr [rbx + rcx], eax
mov dword ptr [rax + rcx + 4], edx mov dword ptr [rbx + rcx + 4], edx
/* Advance phase */ /* Advance phase */
inc byte ptr [TscCalibrationPhase] inc byte ptr [TscCalibrationPhase]
CalibrationISR_Exit: CalibrationISR_Exit:
/* Read CMOS register C */
mov al, HEX(0C)
out HEX(70), al
jmp $+2
in al, HEX(71)
jmp $+2
/* Send EOI */
call HalpSendEOI
pop rdx pop rdx
pop rcx pop rcx
pop rbx
pop rax pop rax
iretq iretq
ENDFUNC TscCalibrationISR ENDFUNC TscCalibrationISR

View file

@ -846,7 +846,7 @@ HalpInitProcessor(
#define KfLowerIrql KeLowerIrql #define KfLowerIrql KeLowerIrql
#define KiEnterInterruptTrap(TrapFrame) /* We do all neccessary in asm code */ #define KiEnterInterruptTrap(TrapFrame) /* We do all neccessary in asm code */
#define KiEoiHelper(TrapFrame) return /* Just return to the caller */ #define KiEoiHelper(TrapFrame) return /* Just return to the caller */
#define HalBeginSystemInterrupt(Irql, Vector, OldIrql) (KeRaiseIrql(Irql, OldIrql), TRUE) #define HalBeginSystemInterrupt(Irql, Vector, OldIrql) TRUE
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
/* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */ /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
#define KiAcquireSpinLock(SpinLock) #define KiAcquireSpinLock(SpinLock)

View file

@ -0,0 +1,196 @@
APIC_EOI = HEX(0FFFFFFFFFFFE00B0)
TF_VOLATILES = HEX(01)
TF_NONVOLATILES = HEX(02)
TF_XMM = HEX(04)
TF_SEGMENTS = HEX(08)
TF_DEBUG = HEX(10)
TF_IRQL = HEX(20)
TF_SAVE_ALL = (TF_VOLATILES OR TF_NONVOLATILES OR TF_XMM OR TF_SEGMENTS)
TF_HAS_ERROR_CODE = HEX(40)
TF_SEND_EOI = HEX(80)
/*
* EnterTrap - Allocate KTRAP_FRAME_LENGTH and save registers to it
*/
MACRO(EnterTrap, Flags)
LOCAL dont_swap
/* Save the trap flags for this trap */
CurrentTrapFlags = VAL(Flags)
/* Size of hardware trap frame */
if (Flags AND TF_HAS_ERROR_CODE)
.pushframe code
SIZE_INITIAL_FRAME = 6 * 8
else
.pushframe
SIZE_INITIAL_FRAME = 5 * 8
endif
/* Make room for a KTRAP_FRAME */
sub rsp, (KTRAP_FRAME_LENGTH - SIZE_INITIAL_FRAME)
.allocstack (KTRAP_FRAME_LENGTH - SIZE_INITIAL_FRAME)
.endprolog
/* Save rbp and rax */
mov [rsp + KTRAP_FRAME_Rbp], rbp
mov [rsp + KTRAP_FRAME_Rax], rax
/* Point rbp to the KTRAP_FRAME */
lea rbp, [rsp]
if (Flags AND TF_NONVOLATILES)
/* Save non-volatile registers */
mov [rbp + KTRAP_FRAME_Rbx], rbx
mov [rbp + KTRAP_FRAME_Rdi], rdi
mov [rbp + KTRAP_FRAME_Rsi], rsi
endif
if (Flags AND TF_VOLATILES)
/* Save volatile registers */
mov [rbp + KTRAP_FRAME_Rcx], rcx
mov [rbp + KTRAP_FRAME_Rdx], rdx
mov [rbp + KTRAP_FRAME_R8], r8
mov [rbp + KTRAP_FRAME_R9], r9
mov [rbp + KTRAP_FRAME_R10], r10
mov [rbp + KTRAP_FRAME_R11], r11
endif
if (Flags AND TF_XMM)
/* Save xmm registers */
movdqa [rbp + KTRAP_FRAME_Xmm0], xmm0
movdqa [rbp + KTRAP_FRAME_Xmm1], xmm1
movdqa [rbp + KTRAP_FRAME_Xmm2], xmm2
movdqa [rbp + KTRAP_FRAME_Xmm3], xmm3
movdqa [rbp + KTRAP_FRAME_Xmm4], xmm4
movdqa [rbp + KTRAP_FRAME_Xmm5], xmm5
endif
if (Flags AND TF_SEGMENTS)
/* Save segment selectors */
mov [rbp + KTRAP_FRAME_SegDs], ds
mov [rbp + KTRAP_FRAME_SegEs], es
mov [rbp + KTRAP_FRAME_SegFs], fs
mov [rbp + KTRAP_FRAME_SegGs], gs
endif
/* Save previous mode and swap gs when it was UserMode */
mov ax, [rbp + KTRAP_FRAME_SegCs]
and al, 1
mov [rbp + KTRAP_FRAME_PreviousMode], al
jz dont_swap
swapgs
dont_swap:
if (Flags AND TF_IRQL)
/* Save previous irql */
mov rax, cr8
mov [rbp + KTRAP_FRAME_PreviousIrql], al
endif
if (Flags AND TF_DEBUG)
/* Save debug registers */
mov rax, dr0
mov [rbp + KTRAP_FRAME_Dr0], rax
mov rax, dr1
mov [rbp + KTRAP_FRAME_Dr1], rax
mov rax, dr2
mov [rbp + KTRAP_FRAME_Dr2], rax
mov rax, dr3
mov [rbp + KTRAP_FRAME_Dr3], rax
mov rax, dr6
mov [rbp + KTRAP_FRAME_Dr6], rax
mov rax, dr7
mov [rbp + KTRAP_FRAME_Dr7], rax
endif
/* Make sure the direction flag is cleared */
cld
ENDM
/*
* ExitTrap - Restore registers and free stack space
*/
MACRO(ExitTrap, Flags)
LOCAL dont_swap_back
if (Flags AND TF_SEGMENTS)
/* Restore segment selectors */
mov ds, [rbp + KTRAP_FRAME_SegDs]
mov es, [rbp + KTRAP_FRAME_SegEs]
mov fs, [rbp + KTRAP_FRAME_SegFs]
endif
if (Flags AND TF_IRQL)
/* Restore previous irql */
movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql]
mov cr8, rax
endif
test byte ptr [rbp + KTRAP_FRAME_PreviousMode], 1
jz dont_swap_back
swapgs
dont_swap_back:
if (Flags AND TF_NONVOLATILES)
/* Restore non-volatile registers */
mov rbx, [rbp + KTRAP_FRAME_Rbx]
mov rdi, [rbp + KTRAP_FRAME_Rdi]
mov rsi, [rbp + KTRAP_FRAME_Rsi]
endif
if (Flags AND TF_VOLATILES)
/* Restore volatile registers */
mov rax, [rbp + KTRAP_FRAME_Rax]
mov rcx, [rbp + KTRAP_FRAME_Rcx]
mov rdx, [rbp + KTRAP_FRAME_Rdx]
mov r8, [rbp + KTRAP_FRAME_R8]
mov r9, [rbp + KTRAP_FRAME_R9]
mov r10, [rbp + KTRAP_FRAME_R10]
mov r11, [rbp + KTRAP_FRAME_R11]
endif
if (Flags AND TF_XMM)
/* Restore xmm registers */
movdqa xmm0, [rbp + KTRAP_FRAME_Xmm0]
movdqa xmm1, [rbp + KTRAP_FRAME_Xmm1]
movdqa xmm2, [rbp + KTRAP_FRAME_Xmm2]
movdqa xmm3, [rbp + KTRAP_FRAME_Xmm3]
movdqa xmm4, [rbp + KTRAP_FRAME_Xmm4]
movdqa xmm5, [rbp + KTRAP_FRAME_Xmm5]
endif
/* Restore rbp */
mov rbp, [rbp + KTRAP_FRAME_Rbp]
/* Adjust stack pointer */
add rsp, KTRAP_FRAME_Rip
if (Flags AND TF_SEND_EOI)
/* Write 0 to the local APIC EOI register */
mov dword ptr [APIC_EOI], 0
endif
/* Return from the trap */
iretq
ENDM
MACRO(TRAP_ENTRY, Trap, Flags)
EXTERN Trap&Handler :PROC
PUBLIC &Trap
FUNC &Trap
/* Common code to create the trap frame */
EnterTrap Flags
/* Call the C handler */
mov rcx, rbp
call Trap&Handler
/* Leave */
ExitTrap Flags
ENDFUNC &Trap
ENDM