Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

673 lines
15 KiB

//++
//
// Module name
// miscs.s
// Author
// Allen Kay ([email protected]) Jun-12-95
// Description
// Misc. assembly functions.
//
//---
#include "ksia64.h"
.file "miscs.s"
.global PalProcPhysical
.global PalPhysicalBase
.global PalTrPs
.global IoPortPhysicalBase
.global IoPortTrPs
.global OsLoaderBase
//
// Setup CPU state to go from physical to virtual
//
LEAF_ENTRY(MempGoVirtual)
rpT0 = t21
rpT1 = t20
rTrPs = t19
rPPN = t18
rPsr = t17
rPsri = t22
//
// Save the state of psr.i before turning it off
//
mov rPsr = psr
movl rpT0 = (1 << PSR_I)
;;
and rPsri = rpT0, rPsr
mov ar.rsc = r0
;;
rsm (1 << PSR_I)
;;
rsm (1 << PSR_IC)
;;
srlz.i
;;
movl t0 = FPSR_FOR_KERNEL
;;
mov ar.fpsr = t0 // initialize fpsr
;;
//
// Initialize Region Registers
//
mov t1 = (START_GLOBAL_RID << RR_RID) | (PAGE_SHIFT << RR_PS) | RR_PS_VE
movl t3 = KSEG0_BASE
;;
mov rr[t3] = t1
//
// Invalidate all protection key registers
//
mov t1 = zero
;;
Bl_PKRLoop:
mov pkr[t1] = zero
;;
add t1 = 1, t1
;;
cmp.gtu pt0, pt1 = PKRNUM, t1
;;
(pt0) br.cond.sptk.few.clr Bl_PKRLoop
;;
//
// Setup the 1-to-1 translation for the loader
//
movl rpT1 = OsLoaderBase
;;
ld8 rpT0 = [rpT1]
;;
dep rpT0 = 0, rpT0, 0, PS_4M
movl rpT1 = PS_4M // Min page size.
// Size should include Text/Data/Stack/BackStore/BdPcr.
// SAL TLB Miss handlers provide TC 1:1 mapping.
;;
mov cr.ifa = rpT0
movl t4 = IITR_ATTRIBUTE_PPN_MASK // construct GR[r]
movl t5 = TR_VALUE(1,0,3,0,1,1,0,1)
;;
shl t2 = rpT1, ITIR_PS
and t6 = rpT0, t4 // t6 is PPN in GR[r]
;;
mov cr.itir = t2
;;
mov t3 = DTR_LOADER_INDEX // pre-assigned index
mov t4 = ITR_LOADER_INDEX // pre-assigned index
or t2 = t5, t6 // t2 is now GR[r]
;;
itr.d dtr[t3] = t2
;;
itr.i itr[t4] = t2
;;
//
// Setup a 64MB translation for the drivers.
//
movl t0 = KSEG0_BASE + BL_64M
;;
movl t2 = ITIR_VALUE(0,PS_64M)
mov cr.ifa = t0
;;
mov cr.itir = t2
;;
mov t3 = DTR_DRIVER0_INDEX
movl t2 = TR_VALUE(1,BL_64M,3,0,1,1,0,1)
;;
itr.d dtr[t3] = t2
;;
itr.i itr[t3] = t2
//
// Setup 16MB translation for kernel/hal binary.
//
movl t0 = KSEG0_BASE + BL_48M;
;;
movl t2 = ITIR_VALUE(0,PS_16M)
mov cr.ifa = t0
;;
mov cr.itir = t2
;;
mov t3 = DTR_KERNEL_INDEX
movl t2 = TR_VALUE(1,BL_48M,3,0,1,1,0,1)
;;
itr.d dtr[t3] = t2
;;
itr.i itr[t3] = t2
//
// Setup 16MB translation for decompression buffer used by setupldr.
//
movl t0 = KSEG0_BASE + BL_32M;
;;
movl t2 = ITIR_VALUE(0,PS_16M)
mov cr.ifa = t0
;;
mov cr.itir = t2
;;
mov t3 = BL_DECOMPRESS_INDEX
movl t2 = TR_VALUE(1,BL_32M,3,0,1,1,0,1)
;;
itr.d dtr[t3] = t2
;;
itr.i itr[t3] = t2
//
// Setup translation for I/O port space
//
movl rpT0 = IoPortPhysicalBase // IO Port base addr
movl rpT1 = IoPortTrPs // IO Port page size
movl t1 = VIRTUAL_IO_BASE
;;
ld8 t0 = [rpT0]
ld8 rTrPs = [rpT1]
mov cr.ifa = t1
movl t4 = IITR_ATTRIBUTE_PPN_MASK // construct GR[r]
movl t5 = TR_VALUE(1,0,3,0,1,1,4,1)
;;
shl t2 = rTrPs, ITIR_PS
and t6 = t0, t4 // t6 is PPN in GR[r]
;;
mov cr.itir = t2
;;
mov t3 = DTR_IO_PORT_INDEX // pre-assigned index
or t2 = t5, t6 // t2 is now GR[r]
;;
itr.d dtr[t3] = t2
//
// Turn on address translation, interrupt, psr.ed, protection key.
//
movl t1 = MASK_IA64(PSR_BN,1) | MASK_IA64(PSR_RT,1) | MASK_IA64(PSR_DT,1) | MASK_IA64(PSR_IC,1) | MASK_IA64(PSR_AC,1) | MASK_IA64(PSR_DB,1)
;;
or t1 = t1, rPsr
;;
mov cr.ipsr = t1
//
// Initialize DCR to defer all speculation faults
//
mov t0 = DCR_DEFER_ALL
;;
mov cr.dcr = t0
//
// Prepare to do RFI to return to the caller.
//
movl t0 = return_label
;;
mov cr.iip = t0
;;
mov cr.ifs = r0
;;
rfi
;;
return_label:
mov v0 = zero
;;
cmp.eq pt0, pt1 = zero, rPsri
;;
(pt1) ssm 1 << PSR_I // set PSR.i bit if it was set originally
srlz.i
;;
LEAF_RETURN
LEAF_EXIT(MempGoVirtual)
//
// Flip psr.it bit from virtual to physical addressing mode.
//
LEAF_ENTRY(FlipToPhysical)
rPsr = t17
rPsri = t18
rPi = t19
//
// Save the state of psr.i before turning it off
//
mov rPsr = psr
movl rPi = (1 << PSR_I)
;;
and rPsri = rPi, rPsr
rsm (1 << PSR_I)
;;
rsm (1 << PSR_IC)
;;
srlz.i
;;
mov rPsr = psr
movl t1 = ~ (MASK_IA64(PSR_RT,1) | MASK_IA64(PSR_DT,1))
movl t2 = MASK_IA64(PSR_BN,1) | MASK_IA64(PSR_IC,1)
;;
and t1 = t1, rPsr
;;
or t1 = t1, t2
;;
mov cr.ipsr = t1
//
// Prepare to do RFI to return to the caller.
//
movl t0 = FlipToPhysicalReturn
;;
mov cr.iip = t0
;;
mov cr.ifs = r0
;;
rfi
;;
FlipToPhysicalReturn:
mov v0 = zero
;;
cmp.eq pt0, pt1 = zero, rPsri
;;
(pt1) ssm 1 << PSR_I // set PSR.i bit if it was set originally
srlz.i
;;
LEAF_RETURN
LEAF_EXIT(FlipToPhysical)
//
// Flip psr.it bit from physical to virtual addressing mode.
//
LEAF_ENTRY(FlipToVirtual)
rPsr = t17
rPsri = t18
rPi = t19
//
// Save the state of psr.i before turning it off
//
mov rPsr = psr
movl rPi = (1 << PSR_I)
;;
and rPsri = rPi, rPsr
rsm (1 << PSR_I)
;;
rsm (1 << PSR_IC)
;;
srlz.i
;;
mov rPsr = psr
movl t1 = MASK_IA64(PSR_RT,1) | MASK_IA64(PSR_DT,1) | MASK_IA64(PSR_BN,1) | MASK_IA64(PSR_IC,1)
;;
or t1 = t1, rPsr
;;
mov cr.ipsr = t1
//
// Prepare to do RFI to return to the caller.
//
movl t0 = FlipToVirtualReturn
;;
mov cr.iip = t0
;;
mov cr.ifs = r0
;;
rfi
;;
FlipToVirtualReturn:
mov v0 = zero
;;
cmp.eq pt0, pt1 = zero, rPsri
;;
(pt1) ssm 1 << PSR_I // set PSR.i bit if it was set originally
srlz.i
;;
LEAF_RETURN
LEAF_EXIT(FlipToVirtual)
//++
//
// BOOLEAN
// IsPsrDtOn(VOID);
//
// Routine Description:
//
// This function returns the value of psr.dt for this cpu
//
// Arguements:
//
// Return Value:
//
// psr.dt
//
//--
LEAF_ENTRY(IsPsrDtOn)
mov t0 = psr
movl t1 = 1 << PSR_DT
;;
and t2 = t0, t1
;;
shr.u v0 = t2, PSR_DT
LEAF_RETURN
LEAF_EXIT(IsPsrDtOn)
//
// Clean up TR mappings used only by NT loader.
//
LEAF_ENTRY(BlTrCleanUp)
rpT0 = t22
rPsr = t17
//
// purge BL_DECOMPRESS_INDEX
//
movl t0 = PS_16M << PS_SHIFT
movl t1 = KSEG0_BASE + BL_32M
;;
ptr.d t1, t0
;;
//
// Turn on address translation, interrupt, psr.ed, protection key.
//
rsm (1 << PSR_I)
;;
rsm (1 << PSR_IC)
;;
srlz.i
;;
//
// At this point, turn on psr.it so that we can pass control to
// the kernel.
//
mov rPsr = psr
movl t1 = MASK_IA64(PSR_BN,1) | MASK_IA64(PSR_IT,1) | MASK_IA64(PSR_RT,1) | MASK_IA64(PSR_DT,1) | MASK_IA64(PSR_IC,1) | MASK_IA64(PSR_AC,1) | MASK_IA64(PSR_DB,1)
;;
or t1 = t1, rPsr
;;
mov cr.ipsr = t1
//
// Prepare to do RFI to return to the caller.
//
movl t0 = BlTrCleanupReturn
;;
mov cr.iip = t0
;;
mov cr.ifs = r0
;;
rfi
;;
BlTrCleanupReturn:
mov v0 = zero
;;
LEAF_RETURN
LEAF_EXIT (BlTrCleanUp)
//++
//
// VOID
// BlpPalProc(
// LONGLONG a0, /* PAL function ID */
// LONGLONG a1, /* PAL argument */
// LONGLONG a2, /* PAL argument */
// LONGLONG a3 /* PAL argument */
// );
//
// Routine Description
// This routine sets up the correct registers for input into PAL depending on
// if the call uses static or stacked registers, turns off interrupts, ensures
// the correct bank registers are being used and calls into the PAL.
//
// Return Values:
// r8->r11 contain the 4 64-bit return values for PAL, r8 is the status
//--
NESTED_ENTRY(BlpPalProc)
NESTED_SETUP(4,3,4,0)
PROLOGUE_END
// For both the static and stacked register conventions, load r28 with FunctionID
mov r28 = a0
// If static register calling convention (1-255, 512-767), copy arguments to r29->r31
// Otherwise, copy to out0->out3 so they are in r32->r35 in PAL_PROC
mov t0 = a0
;;
shr t0 = t0, 8
;;
tbit.z pt0, pt1 = t0, 0
;;
//
// Static proc: do br not call
//
(pt0) mov r29 = a1
(pt0) mov r30 = a2
(pt0) mov r31 = a3
//
// Stacked call
//
(pt1) mov out0 = a0
(pt1) mov out1 = a1
(pt1) mov out2 = a2
(pt1) mov out3 = a3
// Load up the address of PAL_PROC and call it
addl t1 = @gprel(PalProcPhysical), gp
;;
ld8 t0 = [t1]
;;
mov bt0 = t0
// Call into PAL_PROC
(pt0) addl t1 = @ltoff(PalReturn), gp
;;
(pt0) ld8 t0 = [t1]
;;
(pt0) mov brp = t0
;;
// Disable interrupts
DISABLE_INTERRUPTS(loc2)
;;
srlz.d
;;
(pt0) br.sptk.many bt0
;;
(pt1) br.call.sptk brp = bt0
;;
PalReturn:
// Restore the interrupt state
RESTORE_INTERRUPTS(loc2)
;;
NESTED_RETURN
NESTED_EXIT(BlpPalProc)
LEAF_ENTRY(BlpMapRamdiskPages)
//
// Setup a 1MB translation for the RAM disk pages. The starting physical
// address of the translation is the input page number, which must be a
// multiple of 1MB/8192. The starting virtual address is KSEG0 + 32MB.
//
// rsm to reset PSR.i bit
//
rsm 1 << PSR_I // reset PSR.i bit
;;
rsm 1 << PSR_IC // reset PSR.ic bit
;;
srlz.d // serialize
;;
srlz.i
;;
movl t0 = KSEG0_BASE
movl t2 = ITIR_VALUE(0,PS_1M)
;;
add t0 = t0, a0
;;
mov cr.ifa = t0
;;
mov cr.itir = t2
;;
mov t3 = BL_LOADER_INDEX
movl t2 = TR_VALUE(1,0,3,0,1,1,0,1)
;;
or t2 = t2, a0
mov v0 = t0
;;
itr.d dtr[t3] = t2
;;
itr.i itr[t3] = t2
;;
srlz.d // serialize
;;
srlz.i
;;
ssm 1 << PSR_IC // set PSR.ic bit again
;;
ssm 1 << PSR_I // set PSR.i bit again
;;
srlz.d // serialize
;;
srlz.i
;;
LEAF_RETURN
LEAF_EXIT(BlpMapRamdiskPages)
LEAF_ENTRY(BlpUnmapRamdiskPages)
//
// rsm to reset PSR.i bit
//
rsm 1 << PSR_I // reset PSR.i bit
;;
rsm 1 << PSR_IC // reset PSR.ic bit
;;
srlz.d // serialize
;;
srlz.i
;;
movl t0 = KSEG0_BASE
movl t2 = ITIR_VALUE(0,PS_1M)
;;
add t0 = t0, a0
;;
ptr.i t0, t2
;;
ptr.d t0, t2
;;
srlz.d // serialize
;;
srlz.i
;;
ssm 1 << PSR_IC // set PSR.ic bit again
;;
ssm 1 << PSR_I // set PSR.i bit again
;;
srlz.d // serialize
;;
srlz.i
;;
LEAF_RETURN
LEAF_EXIT(BlpUnmapRamdiskPages)
LEAF_ENTRY(BlpInitializeRamdiskMapping)
LEAF_RETURN
LEAF_EXIT(BlpInitializeRamdiskMapping)