asmfuncs.s
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· S 代码 · 共 1,390 行 · 第 1/4 页
S
1,390 行
//++
// Copyright (c) 2004, Intel Corporation
// All rights reserved. This program and the accompanying materials
// are licensed and made available under the terms and conditions of the BSD License
// which accompanies this distribution. The full text of the license may be found at
// http://opensource.org/licenses/bsd-license.php
//
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
// Module Name:
//
// AsmFuncs.s
//
// Abstract:
//
// Low level IPF routines used by the debug support driver
//
// Revision History:
//
//--
#include "common.i"
#include "Ds64Macros.i"
.global PatchSaveBuffer
.global IpfContextBuf
.global CommonHandler
.global ExternalInterruptCount
/////////////////////////////////////////////
//
// Name:
// InstructionCacheFlush
//
// Description:
// Flushes instruction cache for specified number of bytes
//
.global InstructionCacheFlush
.proc InstructionCacheFlush
.align 32
InstructionCacheFlush::
{ .mii
alloc r3=2, 0, 0, 0
cmp4.leu p0,p6=32, r33;;
(p6) mov r33=32;;
}
{ .mii
nop.m 0
zxt4 r29=r33;;
dep.z r30=r29, 0, 5;;
}
{ .mii
cmp4.eq p0,p7=r0, r30
shr.u r28=r29, 5;;
(p7) adds r28=1, r28;;
}
{ .mii
nop.m 0
shl r27=r28, 5;;
zxt4 r26=r27;;
}
{ .mfb
add r31=r26, r32
nop.f 0
nop.b 0
}
LoopBack: // $L143:
{ .mii
fc r32
adds r32=32, r32;;
cmp.ltu p14,p15=r32, r31
}
{ .mfb
nop.m 0
nop.f 0
//(p14) br.cond.dptk.few $L143#;;
(p14) br.cond.dptk.few LoopBack;;
}
{ .mmi
sync.i;;
srlz.i
nop.i 0;;
}
{ .mfb
nop.m 0
nop.f 0
br.ret.sptk.few b0;;
}
.endp InstructionCacheFlush
/////////////////////////////////////////////
//
// Name:
// ChainHandler
//
// Description:
// Chains an interrupt handler
//
// The purpose of this function is to enable chaining of the external interrupt.
// Since there's no clean SAL abstraction for doing this, we must do it
// surreptitiously.
//
// The reserved IVT entry at offset 0x3400 is coopted for use by this handler.
// According to Itanium architecture, it is reserved. Strictly speaking, this is
// not safe, as we're cheating and violating the Itanium architecture. However,
// as long as we're the only ones cheating, we should be OK. Without hooks in
// the SAL to enable IVT management, there aren't many good options.
//
// The strategy is to replace the first bundle of the external interrupt handler
// with our own that will branch into a piece of code we've supplied and located
// in the reserved IVT entry. Only the first bundle of the external interrupt
// IVT entry is modified.
//
// The original bundle is moved and relocated to space
// allocated within the reserved IVT entry. The next bundle following is
// is generated to go a hard coded branch back to the second bundle of the
// external interrupt IVT entry just in case the first bundle had no branch.
//
// Our new code will execute our handler, and then fall through to the
// original bundle after restoring all context appropriately.
//
// The following is a representation of what the IVT memory map looks like with
// our chained handler installed:
//
//
//
//
//
// This IVT entry is Failsafe bundle
// reserved by the
// Itanium architecture Original bundle 0
// and is used for
// for locating our
// handler and the
// original bundle Patch code...
// zero of the ext
// interrupt handler
//
// RSVD (3400) Unused
//
//
//
//
//
//
//
//
//
//
//
//
// EXT_INT (3000) Bundle 0 Bundle zero - This one is
// modified, all other bundles
// in the EXT_INT entry are
// untouched.
//
//
// Arguments:
//
// Returns:
//
// Notes:
//
//
.global ChainHandler
.proc ChainHandler
ChainHandler:
NESTED_SETUP( 0,2+3,3,0 )
mov r8=1 // r8 = success
mov r2=cr.iva;;
//
// NOTE: There's a potential hazard here in that we're simply stealing a bunch of
// bundles (memory) from the IVT and assuming there's no catastrophic side effect.
//
// First, save IVT area we're taking over with the patch so we can restore it later
//
addl out0=PATCH_ENTRY_OFFSET, r2 // out0 = source buffer
movl out1=PatchSaveBuffer // out1 = destination buffer
mov out2=0x40;; // out2 = number of bundles to copy... save entire IDT entry
br.call.sptk.few b0 = CopyBundles
// Next, copy the patch code into the IVT
movl out0=PatchCode // out0 = source buffer of patch code
addl out1=PATCH_OFFSET, r2 // out1 = destination buffer - in IVT
mov out2=NUM_PATCH_BUNDLES;; // out2 = number of bundles to copy
br.call.sptk.few b0 = CopyBundles
// copy original bundle 0 from the external interrupt handler to the
// appropriate place in the reserved IVT interrupt slot
addl out0=EXT_INT_ENTRY_OFFSET, r2 // out0 = source buffer
addl out1=RELOCATED_EXT_INT, r2 // out1 = destination buffer - in reserved IVT
mov out2=1;; // out2 = copy 1 bundle
br.call.sptk.few b0 = CopyBundles
// Now relocate it there because it very likely had a branch instruction that
// that must now be fixed up.
addl out0=RELOCATED_EXT_INT, r2 // out0 = new runtime address of bundle - in reserved IVT
addl out1=EXT_INT_ENTRY_OFFSET, r2;;// out1 = IP address of previous location
mov out2=out0;; // out2 = IP address of new location
br.call.sptk.few b0 = RelocateBundle
// Now copy into the failsafe branch into the next bundle just in case
// the original ext int bundle 0 bundle did not contain a branch instruction
movl out0=FailsafeBranch // out0 = source buffer
addl out1=FAILSAFE_BRANCH_OFFSET, r2 // out1 = destination buffer - in reserved IVT
mov out2=1;; // out2 = copy 1 bundle
br.call.sptk.few b0 = CopyBundles
// Last, copy in our replacement for the external interrupt IVT entry bundle 0
movl out0=PatchCodeNewBun0 // out0 = source buffer - our replacement bundle 0
addl out1=EXT_INT_ENTRY_OFFSET, r2 // out1 = destination buffer - bundle 0 of External interrupt entry
mov out2=1;; // out2 = copy 1 bundle
br.call.sptk.few b0 = CopyBundles
ChainHandlerDone:
NESTED_RETURN
.endp ChainHandler
/////////////////////////////////////////////
//
// Name:
// UnchainHandler
//
// Description:
// Unchains an interrupt handler
//
// Arguments:
//
// Returns:
//
// Notes:
//
//
.global UnchainHandler
.proc UnchainHandler
UnchainHandler:
NESTED_SETUP( 0,2+3,3,0 )
mov r8=1 // r8 = success
mov r2=cr.iva;; // r2 = interrupt vector address
// First copy original Ext Int bundle 0 back to it's proper home...
addl out0=RELOCATED_EXT_INT, r2 // out0 = source - in reserved IVT
addl out1=EXT_INT_ENTRY_OFFSET, r2 // out1 = destination buffer - first bundle of Ext Int entry
mov out2=1;; // out2 = copy 1 bundle
br.call.sptk.few b0 = CopyBundles
// Now, relocate it again...
addl out0=EXT_INT_ENTRY_OFFSET, r2 // out1 = New runtime address
addl out1=RELOCATED_EXT_INT, r2;; // out0 = IP address of previous location
mov out2=out0;; // out2 = IP address of new location
br.call.sptk.few b0 = RelocateBundle
// Last, restore the patch area
movl out0=PatchSaveBuffer // out0 = source buffer
addl out1=PATCH_ENTRY_OFFSET, r2 // out1 = destination buffer
mov out2=0x40;; // out2 = number of bundles to copy... save entire IDT entry
br.call.sptk.few b0 = CopyBundles
UnchainHandlerDone:
NESTED_RETURN
.endp UnchainHandler
/////////////////////////////////////////////
//
// Name:
// CopyBundles
//
// Description:
// Copies instruction bundles - flushes icache as necessary
//
// Arguments:
// in0 - Bundle source
// in1 - Bundle destination
// in2 - Bundle count
//
// Returns:
//
// Notes:
// This procedure is a leaf routine
//
.proc CopyBundles
CopyBundles:
NESTED_SETUP(3,2+1,0,0)
shl in2=in2, 1;; // in2 = count of 8 byte blocks to copy
CopyBundlesLoop:
cmp.eq p14, p15 = 0, in2;; // Check if done
(p14) br.sptk.few CopyBundlesDone;;
ld8 loc2=[in0], 0x8;; // loc2 = source bytes
st8 [in1]=loc2;; // [in1] = destination bytes
fc in1;; // Flush instruction cache
sync.i;; // Ensure local and remote data/inst caches in sync
srlz.i;; // Ensure sync has been observed
add in1=0x8, in1;; // in1 = next destination
add in2=-1, in2;; // in2 = decrement 8 bytes blocks to copy
br.sptk.few CopyBundlesLoop;;
CopyBundlesDone:
NESTED_RETURN
.endp CopyBundles
/////////////////////////////////////////////
//
// Name:
// RelocateBundle
//
// Description:
// Relocates an instruction bundle by updating any ip-relative branch instructions.
//
// Arguments:
// in0 - Runtime address of bundle
// in1 - IP address of previous location of bundle
// in2 - IP address of new location of bundle
//
// Returns:
// in0 - 1 if successful or 0 if unsuccessful
//
// Notes:
// This routine examines all slots in the given bundle that are destined for the
// branch execution unit. If any of these slots contain an IP-relative branch
// namely instructions B1, B2, B3, or B6, the slot is fixed-up with a new relative
// address. Errors can occur if a branch cannot be reached.
//
.proc RelocateBundle
RelocateBundle:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?