407 lines
8.9 KiB
NASM
407 lines
8.9 KiB
NASM
|
|
title "miscellaneous MP primitives for the Corollary MP machines"
|
|
;++
|
|
;
|
|
;Copyright (c) 1992, 1993, 1994 Corollary Inc
|
|
;
|
|
;Module Name:
|
|
;
|
|
; cbusmisc.asm
|
|
;
|
|
;Abstract:
|
|
;
|
|
; This module contains miscellaneous MP primitives for the
|
|
; Corollary MP machines.
|
|
;
|
|
;Author:
|
|
;
|
|
; Landy Wang (landy@corollary.com) 26-Mar-1992
|
|
;
|
|
;Revision History:
|
|
;
|
|
;--
|
|
|
|
|
|
|
|
.386p
|
|
.xlist
|
|
include hal386.inc
|
|
include callconv.inc ; calling convention macros
|
|
include i386\kimacro.inc
|
|
include cbus.inc
|
|
|
|
;
|
|
; enable the Pentium internal cache to its full capability
|
|
;
|
|
CR0_INTERNAL_ON equ (not (CR0_NW or CR0_CD))
|
|
CR0_INTERNAL_OFF equ (CR0_NW or CR0_CD)
|
|
|
|
.list
|
|
|
|
INIT SEGMENT DWORD PUBLIC 'CODE' ; Start 32 bit code
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; i486cacheon
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function enables the calling processor's internal cache.
|
|
; Executed by each processor (via HalInitializeProcessor) in the
|
|
; Corollary Cbus1 and Cbus2 architectures.
|
|
;
|
|
; Note: This must be run before HalpInitializeStallExecution().
|
|
;
|
|
; Return Value:
|
|
; none.
|
|
;
|
|
;--
|
|
|
|
cPublicProc _i486cacheon ,0
|
|
|
|
pushfd
|
|
cli
|
|
|
|
; Enable the 486 processor internal cache if it wasn't already.
|
|
|
|
mov eax, cr0 ; get real cr0
|
|
test eax, CR0_INTERNAL_OFF ; see if CPU cache on already
|
|
jz short @f ; no op if it is
|
|
|
|
; hard code the WBINVD instruction to flush internal cache.
|
|
; this would cause an opcode trap on 386, but we will ship
|
|
; only 486 (Cbus1) and Pentium (Cbus2).
|
|
|
|
db 00fh ; ESCAPE
|
|
db 009h ; write-back invalidate
|
|
|
|
and eax, CR0_INTERNAL_ON ; enable CPU internal cache
|
|
jmp @f ; flush queues
|
|
@@:
|
|
mov cr0, eax ; put cr0 back
|
|
popfd
|
|
|
|
stdRET _i486cacheon
|
|
stdENDP _i486cacheon
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; i486cacheoff
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function disables the calling processor's internal cache.
|
|
; Executed by each processor (via HalInitializeProcessor) in the
|
|
; Corollary Cbus1 and Cbus2 architectures.
|
|
;
|
|
; Note: This must be run before HalpInitializeStallExecution().
|
|
;
|
|
; Return Value:
|
|
; none.
|
|
;
|
|
;--
|
|
|
|
cPublicProc _i486cacheoff ,0
|
|
|
|
pushfd
|
|
cli
|
|
|
|
; Disable the 486 processor internal cache if it wasn't already.
|
|
|
|
mov eax, cr0 ; get real cr0
|
|
test eax, CR0_INTERNAL_OFF ; see if CPU cache on already
|
|
jnz short @f ; no op if it is
|
|
|
|
; hard code the WBINVD instruction to flush internal cache.
|
|
; this would cause an opcode trap on 386, but we will ship
|
|
; only 486 (Cbus1) and Pentium (Cbus2).
|
|
|
|
db 00fh ; ESCAPE
|
|
db 009h ; write-back invalidate
|
|
|
|
or eax, CR0_INTERNAL_OFF ; disable CPU internal cache
|
|
jmp @f ; flush queues
|
|
@@:
|
|
mov cr0, eax ; put cr0 back
|
|
popfd
|
|
|
|
stdRET _i486cacheoff
|
|
stdENDP _i486cacheoff
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; CbusDefaultStall (VOID)
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine initializes the calling processor's stall execution to
|
|
; a reasonable value until we later give it a real value in HalInitSystem.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
cPublicProc _CbusDefaultStall ,0
|
|
mov dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
|
|
stdRET _CbusDefaultStall
|
|
stdENDP _CbusDefaultStall
|
|
|
|
INIT ends ; end 32 bit init code
|
|
|
|
_TEXT SEGMENT PARA PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
page ,132
|
|
subttl "KeQueryPerformanceCounter"
|
|
;++
|
|
;
|
|
; LARGE_INTEGER
|
|
; KeQueryPerformanceCounter (
|
|
; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine returns current 64-bit performance counter and,
|
|
; optionally, the Performance Frequency.
|
|
;
|
|
; Note this routine can NOT be called at Profiling interrupt
|
|
; service routine. Because this routine depends on IRR0 to determine
|
|
; the actual count.
|
|
;
|
|
; Also note that the performace counter returned by this routine
|
|
; is not necessary the value when this routine is just entered.
|
|
; The value returned is actually the counter value at any point
|
|
; between the routine is entered and is exited.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; PerformanceFrequency [TOS+4] - optionally, supplies the address
|
|
; of a variable to receive the performance counter frequency.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; Current value of the performance counter will be returned.
|
|
;
|
|
;--
|
|
|
|
|
|
cPublicProc _KeQueryPerformanceCounter ,1
|
|
|
|
jmp dword ptr [_CbusQueryPerformanceCounter]
|
|
|
|
stdENDP _KeQueryPerformanceCounter
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; HalCalibratePerformanceCounter (
|
|
; IN volatile PLONG Number
|
|
; )
|
|
;
|
|
; /*++
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine calibrates the performance counter value for a
|
|
; multiprocessor system. The calibration can be done by zeroing
|
|
; the current performance counter, or by calculating a per-processor
|
|
; skewing between each processor's counter.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; Number - Supplies a pointer to the count of the number of processors in
|
|
; the configuration.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;--
|
|
cPublicProc _HalCalibratePerformanceCounter,1
|
|
|
|
;
|
|
; Calibration is already handled by the Cbus HAL for both Cbus1
|
|
; and Cbus2.
|
|
;
|
|
|
|
stdRET _HalCalibratePerformanceCounter
|
|
|
|
stdENDP _HalCalibratePerformanceCounter
|
|
|
|
page ,132
|
|
subttl "CbusRebootHandler"
|
|
;++
|
|
;
|
|
; VOID
|
|
; CbusRebootHandler(
|
|
; VOID
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine is the interrupt handler for an IPI interrupt generated
|
|
; at a priority just below that of normal IPIs. Its function is to
|
|
; force all additional processors to flush their internal cache and halt.
|
|
; This puts the processors in a more conducive state for system reset.
|
|
;
|
|
; This routine is run only by the non-boot processors.
|
|
;
|
|
; Since this routine is entered directly via an interrupt gate, interrupt
|
|
; protection via cli is not necessary.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
ENTER_DR_ASSIST hirs_a, hirs_t
|
|
|
|
cPublicProc _CbusRebootHandler ,0
|
|
|
|
;
|
|
; Save machine state on trap frame
|
|
;
|
|
|
|
ENTER_INTERRUPT hirs_a, hirs_t
|
|
|
|
; keep it simple, just issue the EOI right now.
|
|
; no changing of taskpri/irql is needed here.
|
|
; Thus, the EOI serves as the HalEndSystemInterrupt.
|
|
|
|
mov eax, _CbusRebootVector
|
|
CBUS_EOI eax, ecx ; destroy eax & ecx
|
|
|
|
mov eax, dword ptr PCR[PcHal.PcrNumber]
|
|
|
|
; the boot processor will take care of the reboot from this point on.
|
|
; however, ensure that our internal cache is flushed and halt.
|
|
|
|
db 00fh ; ESCAPE
|
|
db 009h ; write-back invalidate
|
|
hlt
|
|
|
|
;
|
|
; we should never reach this point, but if we do, just return our
|
|
; processor number (loaded above).
|
|
;
|
|
stdRET _CbusRebootHandler
|
|
stdENDP _CbusRebootHandler
|
|
|
|
page ,132
|
|
subttl "Stall Execution"
|
|
;++
|
|
;
|
|
; VOID
|
|
; KeStallExecutionProcessor (
|
|
; IN ULONG MicroSeconds
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function stalls execution for the specified number of microseconds.
|
|
; KeStallExecutionProcessor
|
|
;
|
|
; Arguments:
|
|
;
|
|
; MicroSeconds - Supplies the number of microseconds that execution is to be
|
|
; stalled.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
|
|
MicroSeconds equ [esp + 4]
|
|
|
|
|
|
cPublicProc _KeStallExecutionProcessor ,1
|
|
|
|
mov ecx, MicroSeconds ; (ecx) = Microseconds
|
|
jecxz short kese10 ; return if no loop needed
|
|
|
|
mov eax, PCR[PcStallScaleFactor] ; get per microsecond
|
|
; loop count for the processor
|
|
mul ecx ; (eax) = desired loop count
|
|
|
|
if DBG
|
|
|
|
;
|
|
; Make sure we the loopcount is less than 4G and is not equal to zero
|
|
;
|
|
|
|
cmp edx, 0
|
|
jz short @f
|
|
int 3
|
|
|
|
align 4
|
|
@@: cmp eax,0
|
|
jnz short @f
|
|
int 3
|
|
@@:
|
|
endif
|
|
ALIGN 16
|
|
jmp kese05
|
|
|
|
ALIGN 16
|
|
kese05:
|
|
sub eax, 1 ; (eax) = (eax) - 1
|
|
jnz short kese05
|
|
|
|
align 4
|
|
kese10:
|
|
stdRET _KeStallExecutionProcessor
|
|
|
|
stdENDP _KeStallExecutionProcessor
|
|
|
|
;++
|
|
;
|
|
; ULONG
|
|
; HalSetTimeIncrement (
|
|
; IN ULONG DesiredIncrement
|
|
; )
|
|
;
|
|
; /*++
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine initializes the system time clock to generate an
|
|
; interrupt at every DesiredIncrement interval.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; DesiredIncrement - desired interval between every timer tick in
|
|
; 100ns units.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; The *REAL* time increment set - this can be different from what he
|
|
; requested due to hardware limitations.
|
|
;--
|
|
|
|
cPublicProc _HalSetTimeIncrement,1
|
|
|
|
mov eax, _CbusBackend ; use hardware handler
|
|
jmp HalSetTimeIncrement[ eax ] ; JMP to set the interval
|
|
; counter
|
|
stdENDP _HalSetTimeIncrement
|
|
|
|
_TEXT ends ; end 32 bit code
|
|
|
|
end
|