NT4/private/ntos/nthals/halcbus/i386/cbusmisc.asm
2020-09-30 17:12:29 +02:00

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