MdePkg/BaseMemoryLibOptDxe ARM|AARCH64: implement accelerated GUID functions

As reported by Vishal, CompareGuid() is a hotspot, and switching from
BaseMemoryLibStm in ArmPkg/ to BaseMemoryLibOptDxe causes a noticeable
performance regression due to the fact that BaseMemoryLibOptDxe uses
unaligned accessors explicitly to implement CompareGuid() and the related
functions.

Since BaseMemoryLibOptDxe on ARM and AARCH64 can only be used in contexts
where unaligned accesses are allowed, reimplement these functions for ARM
and AARCH64 specifically, using wide accessors that can tolerate any
misalignment.

Reported-by: "Oliyil Kunnil, Vishal" <vishalo@qti.qualcomm.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Ard Biesheuvel 2016-09-16 11:25:52 +01:00
parent 60fe5e8a9c
commit 217b3ac093
5 changed files with 333 additions and 1 deletions

View File

@ -0,0 +1,40 @@
//
// Copyright (c) 2016, Linaro Limited
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Linaro nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
.text
.align 5
ASM_GLOBAL ASM_PFX(InternalMemCompareGuid)
ASM_PFX(InternalMemCompareGuid):
mov x2, xzr
ldp x3, x4, [x0]
cbz x1, 0f
ldp x1, x2, [x1]
0: cmp x1, x3
ccmp x2, x4, #0, eq
cset w0, eq
ret

View File

@ -0,0 +1,65 @@
//
// Copyright (c) 2016, Linaro Limited
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Linaro nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
.text
.thumb
.syntax unified
.align 5
ASM_GLOBAL ASM_PFX(InternalMemCompareGuid)
ASM_PFX(InternalMemCompareGuid):
push {r4, lr}
ldr r2, [r0]
ldr r3, [r0, #4]
ldr r4, [r0, #8]
ldr r0, [r0, #12]
cbz r1, 1f
ldr ip, [r1]
ldr lr, [r1, #4]
cmp r2, ip
it eq
cmpeq r3, lr
beq 0f
movs r0, #0
pop {r4, pc}
0: ldr r2, [r1, #8]
ldr r3, [r1, #12]
cmp r4, r2
it eq
cmpeq r0, r3
bne 2f
movs r0, #1
pop {r4, pc}
1: orrs r2, r2, r3
orrs r4, r4, r0
movs r0, #1
orrs r2, r2, r4
2: it ne
movne r0, #0
pop {r4, pc}

View File

@ -0,0 +1,70 @@
;
; Copyright (c) 2016, Linaro Limited
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the Linaro nor the
; names of its contributors may be used to endorse or promote products
; derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
; HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
EXPORT InternalMemCompareGuid
THUMB
AREA CompareGuid, CODE, READONLY, CODEALIGN, ALIGN=5
InternalMemCompareGuid
push {r4, lr}
ldr r2, [r0]
ldr r3, [r0, #4]
ldr r4, [r0, #8]
ldr r0, [r0, #12]
cbz r1, L1
ldr ip, [r1]
ldr lr, [r1, #4]
cmp r2, ip
it eq
cmpeq r3, lr
beq L0
movs r0, #0
pop {r4, pc}
L0
ldr r2, [r1, #8]
ldr r3, [r1, #12]
cmp r4, r2
it eq
cmpeq r0, r3
bne L2
movs r0, #1
pop {r4, pc}
L1
orrs r2, r2, r3
orrs r4, r4, r0
movs r0, #1
orrs r2, r2, r4
L2
it ne
movne r0, #0
pop {r4, pc}
END

View File

@ -0,0 +1,152 @@
/** @file
Implementation of GUID functions for ARM and AARCH64
Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
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.
**/
#include "MemLibInternals.h"
BOOLEAN
EFIAPI
InternalMemCompareGuid (
IN CONST GUID *Guid1,
IN CONST GUID *Guid2
);
/**
Copies a source GUID to a destination GUID.
This function copies the contents of the 128-bit GUID specified by SourceGuid to
DestinationGuid, and returns DestinationGuid.
If DestinationGuid is NULL, then ASSERT().
If SourceGuid is NULL, then ASSERT().
@param DestinationGuid The pointer to the destination GUID.
@param SourceGuid The pointer to the source GUID.
@return DestinationGuid.
**/
GUID *
EFIAPI
CopyGuid (
OUT GUID *DestinationGuid,
IN CONST GUID *SourceGuid
)
{
ASSERT (DestinationGuid != NULL);
ASSERT (SourceGuid != NULL);
return InternalMemCopyMem (DestinationGuid, SourceGuid, sizeof (GUID));
}
/**
Compares two GUIDs.
This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned.
If there are any bit differences in the two GUIDs, then FALSE is returned.
If Guid1 is NULL, then ASSERT().
If Guid2 is NULL, then ASSERT().
@param Guid1 A pointer to a 128 bit GUID.
@param Guid2 A pointer to a 128 bit GUID.
@retval TRUE Guid1 and Guid2 are identical.
@retval FALSE Guid1 and Guid2 are not identical.
**/
BOOLEAN
EFIAPI
CompareGuid (
IN CONST GUID *Guid1,
IN CONST GUID *Guid2
)
{
ASSERT (Guid1 != NULL);
ASSERT (Guid2 != NULL);
return InternalMemCompareGuid (Guid1, Guid2);
}
/**
Scans a target buffer for a GUID, and returns a pointer to the matching GUID
in the target buffer.
This function searches the target buffer specified by Buffer and Length from
the lowest address to the highest address at 128-bit increments for the 128-bit
GUID value that matches Guid. If a match is found, then a pointer to the matching
GUID in the target buffer is returned. If no match is found, then NULL is returned.
If Length is 0, then NULL is returned.
If Length > 0 and Buffer is NULL, then ASSERT().
If Buffer is not aligned on a 32-bit boundary, then ASSERT().
If Length is not aligned on a 128-bit boundary, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the target buffer to scan.
@param Length The number of bytes in Buffer to scan.
@param Guid The value to search for in the target buffer.
@return A pointer to the matching Guid in the target buffer or NULL otherwise.
**/
VOID *
EFIAPI
ScanGuid (
IN CONST VOID *Buffer,
IN UINTN Length,
IN CONST GUID *Guid
)
{
CONST GUID *GuidPtr;
ASSERT (((UINTN)Buffer & (sizeof (Guid->Data1) - 1)) == 0);
ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1));
ASSERT ((Length & (sizeof (*GuidPtr) - 1)) == 0);
GuidPtr = (GUID*)Buffer;
Buffer = GuidPtr + Length / sizeof (*GuidPtr);
while (GuidPtr < (CONST GUID*)Buffer) {
if (InternalMemCompareGuid (GuidPtr, Guid)) {
return (VOID*)GuidPtr;
}
GuidPtr++;
}
return NULL;
}
/**
Checks if the given GUID is a zero GUID.
This function checks whether the given GUID is a zero GUID. If the GUID is
identical to a zero GUID then TRUE is returned. Otherwise, FALSE is returned.
If Guid is NULL, then ASSERT().
@param Guid The pointer to a 128 bit GUID.
@retval TRUE Guid is a zero GUID.
@retval FALSE Guid is not a zero GUID.
**/
BOOLEAN
EFIAPI
IsZeroGuid (
IN CONST GUID *Guid
)
{
ASSERT (Guid != NULL);
return InternalMemCompareGuid (Guid, NULL);
}

View File

@ -79,6 +79,7 @@
Ia32/CopyMem.nasm
Ia32/CopyMem.asm
Ia32/IsZeroBuffer.nasm
MemLibGuid.c
[Sources.X64]
X64/ScanMem64.nasm
@ -115,6 +116,7 @@
X64/CopyMem.asm
X64/CopyMem.S
X64/IsZeroBuffer.nasm
MemLibGuid.c
[Defines.ARM, Defines.AARCH64]
#
@ -130,20 +132,24 @@
Arm/SetMem.S |GCC
Arm/CopyMem.S |GCC
Arm/CompareMem.S |GCC
Arm/CompareGuid.S |GCC
Arm/ScanMem.asm |RVCT
Arm/SetMem.asm |RVCT
Arm/CopyMem.asm |RVCT
Arm/CompareMem.asm |RVCT
Arm/CompareGuid.asm |RVCT
[Sources.AARCH64]
AArch64/ScanMem.S
AArch64/SetMem.S
AArch64/CopyMem.S
AArch64/CompareMem.S
AArch64/CompareGuid.S
[Sources.ARM, Sources.AARCH64]
Arm/ScanMemGeneric.c
Arm/MemLibGuid.c
[Sources]
ScanMem64Wrapper.c
@ -158,7 +164,6 @@
SetMemWrapper.c
CopyMemWrapper.c
IsZeroBufferWrapper.c
MemLibGuid.c
[Packages]
MdePkg/MdePkg.dec