From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=lersek@redhat.com; receiver=edk2-devel@lists.01.org Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id C17D021157401 for ; Tue, 5 Jun 2018 01:42:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2C6E0818A6B9; Tue, 5 Jun 2018 08:42:29 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-120-104.rdu2.redhat.com [10.10.120.104]) by smtp.corp.redhat.com (Postfix) with ESMTP id 066D4205D521; Tue, 5 Jun 2018 08:42:26 +0000 (UTC) To: Ard Biesheuvel , edk2-devel@lists.01.org Cc: leif.lindholm@linaro.org, liming.gao@intel.com, michael.d.kinney@intel.com References: <20180605073004.8632-1-ard.biesheuvel@linaro.org> From: Laszlo Ersek Message-ID: <13e35e1d-dc05-2c0c-13a3-c7a6c350d563@redhat.com> Date: Tue, 5 Jun 2018 10:42:26 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 MIME-Version: 1.0 In-Reply-To: <20180605073004.8632-1-ard.biesheuvel@linaro.org> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 05 Jun 2018 08:42:29 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 05 Jun 2018 08:42:29 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'lersek@redhat.com' RCPT:'' Subject: Re: [RFC PATCH] MdePkg/BaseIoLibIntrinsic ARM AARCH64: avoid C code for MMIO access X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Jun 2018 08:42:31 -0000 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit On 06/05/18 09:30, Ard Biesheuvel wrote: > Even though MMIO shares the address space with ordinary memory, the > accesses involved are *not* ordinary memory accesses, and so it is > a bad idea to let the compiler generate them using pointer dereferences. I think I slightly disagree with the wording here. Using volatile-qualified pointers (implying compiler barriers), possibly combined with CPU barriers (wrapped into C functions), seems valid in both practice and on the ISO C level. "volatile" does not guarantee atomicity, but an IoLib instance can still assume that, if it is tied to a specific toolchain, and the toolchain guarantees atomicity. Anyway: > > Instead, introduce a set of internal accessors implemented in assembler, > and call those from the various Mmio[Read|Write]XX () implementations. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ard Biesheuvel > --- > Open coding the MMIO accesses is a good idea in general, but it also works > around an issue that affects EDK2 running under KVM on ARM or AARCH64, where > LTO code generation results in MMIO accesses involving instructions that cannot > be emulated by the hypervisor. edk2 code (and developers!) are generally conscious about this issue, and call the IoLib APIs carefully. Thus, I believe that, with this patch, we can address the problem in edk2 "for good" -- we can trust that all such accesses will go through a few "choke points", and we can add the work-arounds to the "choke points". (This is exactly what I believe we aren't certain about with regard to the Linux kernel.) Therefore I welcome the patch! I just think the commit message should name the KVM workaround as the primary reason. The C code is not wrong (knowing the compiler), and the generated assembly is also not wrong on the bare metal. I don't insist though that you update the commit message; I prefer working code to documentation that's polished to my taste. :) Acked-by: Laszlo Ersek Thank you! Laszlo > > MdePkg/Library/BaseIoLibIntrinsic/AArch64/IoLibMmio.S | 164 ++++++++++++++++++ > MdePkg/Library/BaseIoLibIntrinsic/Arm/IoLibMmio.S | 164 ++++++++++++++++++ > MdePkg/Library/BaseIoLibIntrinsic/Arm/IoLibMmio.asm | 165 ++++++++++++++++++ > MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf | 9 +- > MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c | 36 ++-- > MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.h | 179 ++++++++++++++++++++ > 6 files changed, 692 insertions(+), 25 deletions(-) > > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/AArch64/IoLibMmio.S b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/IoLibMmio.S > new file mode 100644 > index 000000000000..ac96df602f7a > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/IoLibMmio.S > @@ -0,0 +1,164 @@ > +# > +# Copyright (c) 2014-2018, Linaro Limited. 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. > +# > +# > + > +.text > +.align 3 > + > +GCC_ASM_EXPORT(MmioRead8Internal) > +GCC_ASM_EXPORT(MmioWrite8Internal) > +GCC_ASM_EXPORT(MmioRead16Internal) > +GCC_ASM_EXPORT(MmioWrite16Internal) > +GCC_ASM_EXPORT(MmioRead32Internal) > +GCC_ASM_EXPORT(MmioWrite32Internal) > +GCC_ASM_EXPORT(MmioRead64Internal) > +GCC_ASM_EXPORT(MmioWrite64Internal) > + > +// > +// Reads an 8-bit MMIO register. > +// > +// Reads the 8-bit MMIO register specified by Address. The 8-bit read value is > +// returned. This function must guarantee that all MMIO read and write > +// operations are serialized. > +// > +// If 8-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to read. > +// > +// @return The value read. > +// > +ASM_PFX(MmioRead8Internal): > + ldrb w0, [x0] > + dsb ld > + ret > + > +// > +// Writes an 8-bit MMIO register. > +// > +// Writes the 8-bit MMIO register specified by Address with the value specified > +// by Value and returns Value. This function must guarantee that all MMIO read > +// and write operations are serialized. > +// > +// If 8-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to write. > +// @param Value The value to write to the MMIO register. > +// > +ASM_PFX(MmioWrite8Internal): > + dsb st > + strb w1, [x0] > + ret > + > +// > +// Reads a 16-bit MMIO register. > +// > +// Reads the 16-bit MMIO register specified by Address. The 16-bit read value is > +// returned. This function must guarantee that all MMIO read and write > +// operations are serialized. > +// > +// If 16-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to read. > +// > +// @return The value read. > +// > +ASM_PFX(MmioRead16Internal): > + ldrh w0, [x0] > + dsb ld > + ret > + > +// > +// Writes a 16-bit MMIO register. > +// > +// Writes the 16-bit MMIO register specified by Address with the value specified > +// by Value and returns Value. This function must guarantee that all MMIO read > +// and write operations are serialized. > +// > +// If 16-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to write. > +// @param Value The value to write to the MMIO register. > +// > +ASM_PFX(MmioWrite16Internal): > + dsb st > + strh w1, [x0] > + ret > + > +// > +// Reads a 32-bit MMIO register. > +// > +// Reads the 32-bit MMIO register specified by Address. The 32-bit read value is > +// returned. This function must guarantee that all MMIO read and write > +// operations are serialized. > +// > +// If 32-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to read. > +// > +// @return The value read. > +// > +ASM_PFX(MmioRead32Internal): > + ldr w0, [x0] > + dsb ld > + ret > + > +// > +// Writes a 32-bit MMIO register. > +// > +// Writes the 32-bit MMIO register specified by Address with the value specified > +// by Value and returns Value. This function must guarantee that all MMIO read > +// and write operations are serialized. > +// > +// If 32-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to write. > +// @param Value The value to write to the MMIO register. > +// > +ASM_PFX(MmioWrite32Internal): > + dsb st > + str w1, [x0] > + ret > + > +// > +// Reads a 64-bit MMIO register. > +// > +// Reads the 64-bit MMIO register specified by Address. The 64-bit read value is > +// returned. This function must guarantee that all MMIO read and write > +// operations are serialized. > +// > +// If 64-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to read. > +// > +// @return The value read. > +// > +ASM_PFX(MmioRead64Internal): > + ldr x0, [x0] > + dsb ld > + ret > + > +// > +// Writes a 64-bit MMIO register. > +// > +// Writes the 64-bit MMIO register specified by Address with the value specified > +// by Value and returns Value. This function must guarantee that all MMIO read > +// and write operations are serialized. > +// > +// If 64-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to write. > +// @param Value The value to write to the MMIO register. > +// > +ASM_PFX(MmioWrite64Internal): > + dsb st > + str x1, [x0] > + ret > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/Arm/IoLibMmio.S b/MdePkg/Library/BaseIoLibIntrinsic/Arm/IoLibMmio.S > new file mode 100644 > index 000000000000..09791951b2fd > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/Arm/IoLibMmio.S > @@ -0,0 +1,164 @@ > +# > +# Copyright (c) 2014-2018, Linaro Limited. 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. > +# > +# > + > +.text > +.align 3 > + > +GCC_ASM_EXPORT(MmioRead8Internal) > +GCC_ASM_EXPORT(MmioWrite8Internal) > +GCC_ASM_EXPORT(MmioRead16Internal) > +GCC_ASM_EXPORT(MmioWrite16Internal) > +GCC_ASM_EXPORT(MmioRead32Internal) > +GCC_ASM_EXPORT(MmioWrite32Internal) > +GCC_ASM_EXPORT(MmioRead64Internal) > +GCC_ASM_EXPORT(MmioWrite64Internal) > + > +// > +// Reads an 8-bit MMIO register. > +// > +// Reads the 8-bit MMIO register specified by Address. The 8-bit read value is > +// returned. This function must guarantee that all MMIO read and write > +// operations are serialized. > +// > +// If 8-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to read. > +// > +// @return The value read. > +// > +ASM_PFX(MmioRead8Internal): > + ldrb r0, [r0] > + dsb > + bx lr > + > +// > +// Writes an 8-bit MMIO register. > +// > +// Writes the 8-bit MMIO register specified by Address with the value specified > +// by Value and returns Value. This function must guarantee that all MMIO read > +// and write operations are serialized. > +// > +// If 8-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to write. > +// @param Value The value to write to the MMIO register. > +// > +ASM_PFX(MmioWrite8Internal): > + dsb st > + strb r1, [r0] > + bx lr > + > +// > +// Reads a 16-bit MMIO register. > +// > +// Reads the 16-bit MMIO register specified by Address. The 16-bit read value is > +// returned. This function must guarantee that all MMIO read and write > +// operations are serialized. > +// > +// If 16-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to read. > +// > +// @return The value read. > +// > +ASM_PFX(MmioRead16Internal): > + ldrh r0, [r0] > + dsb > + bx lr > + > +// > +// Writes a 16-bit MMIO register. > +// > +// Writes the 16-bit MMIO register specified by Address with the value specified > +// by Value and returns Value. This function must guarantee that all MMIO read > +// and write operations are serialized. > +// > +// If 16-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to write. > +// @param Value The value to write to the MMIO register. > +// > +ASM_PFX(MmioWrite16Internal): > + dsb st > + strh r1, [r0] > + bx lr > + > +// > +// Reads a 32-bit MMIO register. > +// > +// Reads the 32-bit MMIO register specified by Address. The 32-bit read value is > +// returned. This function must guarantee that all MMIO read and write > +// operations are serialized. > +// > +// If 32-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to read. > +// > +// @return The value read. > +// > +ASM_PFX(MmioRead32Internal): > + ldr r0, [r0] > + dsb > + bx lr > + > +// > +// Writes a 32-bit MMIO register. > +// > +// Writes the 32-bit MMIO register specified by Address with the value specified > +// by Value and returns Value. This function must guarantee that all MMIO read > +// and write operations are serialized. > +// > +// If 32-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to write. > +// @param Value The value to write to the MMIO register. > +// > +ASM_PFX(MmioWrite32Internal): > + dsb st > + str r1, [r0] > + bx lr > + > +// > +// Reads a 64-bit MMIO register. > +// > +// Reads the 64-bit MMIO register specified by Address. The 64-bit read value is > +// returned. This function must guarantee that all MMIO read and write > +// operations are serialized. > +// > +// If 64-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to read. > +// > +// @return The value read. > +// > +ASM_PFX(MmioRead64Internal): > + ldrd r0, r1, [r0] > + dsb > + bx lr > + > +// > +// Writes a 64-bit MMIO register. > +// > +// Writes the 64-bit MMIO register specified by Address with the value specified > +// by Value and returns Value. This function must guarantee that all MMIO read > +// and write operations are serialized. > +// > +// If 64-bit MMIO register operations are not supported, then ASSERT(). > +// > +// @param Address The MMIO register to write. > +// @param Value The value to write to the MMIO register. > +// > +ASM_PFX(MmioWrite64Internal): > + dsb st > + strd r2, r3, [r0] > + bx lr > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/Arm/IoLibMmio.asm b/MdePkg/Library/BaseIoLibIntrinsic/Arm/IoLibMmio.asm > new file mode 100644 > index 000000000000..59a92962cb21 > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/Arm/IoLibMmio.asm > @@ -0,0 +1,165 @@ > +; > +; Copyright (c) 2014-2018, Linaro Limited. 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. > +; > + > + > +AREA IoLibMmio, CODE, READONLY > + > +EXPORT MmioRead8Internal > +EXPORT MmioWrite8Internal > +EXPORT MmioRead16Internal > +EXPORT MmioWrite16Internal > +EXPORT MmioRead32Internal > +EXPORT MmioWrite32Internal > +EXPORT MmioRead64Internal > +EXPORT MmioWrite64Internal > + > +; > +; Reads an 8-bit MMIO register. > +; > +; Reads the 8-bit MMIO register specified by Address. The 8-bit read value is > +; returned. This function must guarantee that all MMIO read and write > +; operations are serialized. > +; > +; If 8-bit MMIO register operations are not supported, then ASSERT(). > +; > +; @param Address The MMIO register to read. > +; > +; @return The value read. > +; > +MmioRead8Internal > + ldrb r0, [r0] > + dsb > + bx lr > + > +; > +; Writes an 8-bit MMIO register. > +; > +; Writes the 8-bit MMIO register specified by Address with the value specified > +; by Value and returns Value. This function must guarantee that all MMIO read > +; and write operations are serialized. > +; > +; If 8-bit MMIO register operations are not supported, then ASSERT(). > +; > +; @param Address The MMIO register to write. > +; @param Value The value to write to the MMIO register. > +; > +MmioWrite8Internal > + dsb st > + strb r1, [r0] > + bx lr > + > +; > +; Reads a 16-bit MMIO register. > +; > +; Reads the 16-bit MMIO register specified by Address. The 16-bit read value is > +; returned. This function must guarantee that all MMIO read and write > +; operations are serialized. > +; > +; If 16-bit MMIO register operations are not supported, then ASSERT(). > +; > +; @param Address The MMIO register to read. > +; > +; @return The value read. > +; > +MmioRead16Internal > + ldrh r0, [r0] > + dsb > + bx lr > + > +; > +; Writes a 16-bit MMIO register. > +; > +; Writes the 16-bit MMIO register specified by Address with the value specified > +; by Value and returns Value. This function must guarantee that all MMIO read > +; and write operations are serialized. > +; > +; If 16-bit MMIO register operations are not supported, then ASSERT(). > +; > +; @param Address The MMIO register to write. > +; @param Value The value to write to the MMIO register. > +; > +MmioWrite16Internal > + dsb st > + strh r1, [r0] > + bx lr > + > +; > +; Reads a 32-bit MMIO register. > +; > +; Reads the 32-bit MMIO register specified by Address. The 32-bit read value is > +; returned. This function must guarantee that all MMIO read and write > +; operations are serialized. > +; > +; If 32-bit MMIO register operations are not supported, then ASSERT(). > +; > +; @param Address The MMIO register to read. > +; > +; @return The value read. > +; > +MmioRead32Internal > + ldr r0, [r0] > + dsb > + bx lr > + > +; > +; Writes a 32-bit MMIO register. > +; > +; Writes the 32-bit MMIO register specified by Address with the value specified > +; by Value and returns Value. This function must guarantee that all MMIO read > +; and write operations are serialized. > +; > +; If 32-bit MMIO register operations are not supported, then ASSERT(). > +; > +; @param Address The MMIO register to write. > +; @param Value The value to write to the MMIO register. > +; > +MmioWrite32Internal > + dsb st > + str r1, [r0] > + bx lr > + > +; > +; Reads a 64-bit MMIO register. > +; > +; Reads the 64-bit MMIO register specified by Address. The 64-bit read value is > +; returned. This function must guarantee that all MMIO read and write > +; operations are serialized. > +; > +; If 64-bit MMIO register operations are not supported, then ASSERT(). > +; > +; @param Address The MMIO register to read. > +; > +; @return The value read. > +; > +MmioRead64Internal > + ldrd r0, r1, [r0] > + dsb > + bx lr > + > +; > +; Writes a 64-bit MMIO register. > +; > +; Writes the 64-bit MMIO register specified by Address with the value specified > +; by Value and returns Value. This function must guarantee that all MMIO read > +; and write operations are serialized. > +; > +; If 64-bit MMIO register operations are not supported, then ASSERT(). > +; > +; @param Address The MMIO register to write. > +; @param Value The value to write to the MMIO register. > +; > +MmioWrite64Internal > + dsb st > + strd r2, r3, [r0] > + bx lr > + > + END > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf > index 8844b1ce4c2b..22813098e97a 100644 > --- a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf > +++ b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf > @@ -61,11 +61,16 @@ [Sources.EBC] > [Sources.IPF] > IoLibIpf.c > > -[Sources.ARM] > +[Sources.ARM, Sources.AARCH64] > IoLibArm.c > + IoLibArm.h > + > +[Sources.ARM] > + Arm/IoLibMmio.S | GCC > + Arm/IoLibMmio.asm | RVCT > > [Sources.AARCH64] > - IoLibArm.c > + AArch64/IoLibMmio.S > > [Packages] > MdePkg/MdePkg.dec > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c b/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c > index 5ce12ca56ae2..449bc5ebbf85 100644 > --- a/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c > +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c > @@ -20,6 +20,7 @@ > // Include common header file for this module. > // > #include "BaseIoLibIntrinsicInternal.h" > +#include "IoLibArm.h" > > /** > Reads an 8-bit I/O port. > @@ -411,10 +412,7 @@ MmioRead8 ( > IN UINTN Address > ) > { > - UINT8 Value; > - > - Value = *(volatile UINT8*)Address; > - return Value; > + return MmioRead8Internal (Address); > } > > /** > @@ -437,7 +435,7 @@ MmioWrite8 ( > IN UINT8 Value > ) > { > - *(volatile UINT8*)Address = Value; > + MmioWrite8Internal (Address, Value); > return Value; > } > > @@ -461,11 +459,7 @@ MmioRead16 ( > IN UINTN Address > ) > { > - UINT16 Value; > - > - ASSERT ((Address & 1) == 0); > - Value = *(volatile UINT16*)Address; > - return Value; > + return MmioRead16Internal (Address); > } > > /** > @@ -489,7 +483,8 @@ MmioWrite16 ( > ) > { > ASSERT ((Address & 1) == 0); > - *(volatile UINT16*)Address = Value; > + > + MmioWrite16Internal (Address, Value); > return Value; > } > > @@ -513,11 +508,7 @@ MmioRead32 ( > IN UINTN Address > ) > { > - UINT32 Value; > - > - ASSERT ((Address & 3) == 0); > - Value = *(volatile UINT32*)Address; > - return Value; > + return MmioRead32Internal (Address); > } > > /** > @@ -541,7 +532,8 @@ MmioWrite32 ( > ) > { > ASSERT ((Address & 3) == 0); > - *(volatile UINT32*)Address = Value; > + > + MmioWrite32Internal (Address, Value); > return Value; > } > > @@ -565,11 +557,9 @@ MmioRead64 ( > IN UINTN Address > ) > { > - UINT64 Value; > - > ASSERT ((Address & 7) == 0); > - Value = *(volatile UINT64*)Address; > - return Value; > + > + return MmioRead64Internal (Address); > } > > /** > @@ -593,7 +583,7 @@ MmioWrite64 ( > ) > { > ASSERT ((Address & 7) == 0); > - *(volatile UINT64*)Address = Value; > + > + MmioWrite64Internal (Address, Value); > return Value; > } > - > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.h b/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.h > new file mode 100644 > index 000000000000..6c63d0b5545b > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.h > @@ -0,0 +1,179 @@ > +/** @file > + Internal MMIO routines implemented in ARM assembler > + > + Copyright (c) 2018, Linaro, Ltd. 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. > + > +**/ > + > +#ifndef __BASEIOLIBINTRINSIC_IOLIBARM_H_ > +#define __BASEIOLIBINTRINSIC_IOLIBARM_H_ > + > +/** > + Reads an 8-bit MMIO register. > + > + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is > + returned. This function must guarantee that all MMIO read and write > + operations are serialized. > + > + If 8-bit MMIO register operations are not supported, then ASSERT(). > + > + @param Address The MMIO register to read. > + > + @return The value read. > + > +**/ > +UINT8 > +EFIAPI > +MmioRead8Internal ( > + IN UINTN Address > + ); > + > +/** > + Writes an 8-bit MMIO register. > + > + Writes the 8-bit MMIO register specified by Address with the value specified > + by Value. This function must guarantee that all MMIO read and write operations > + are serialized. > + > + If 8-bit MMIO register operations are not supported, then ASSERT(). > + > + @param Address The MMIO register to write. > + @param Value The value to write to the MMIO register. > + > +**/ > +VOID > +EFIAPI > +MmioWrite8Internal ( > + IN UINTN Address, > + IN UINT8 Value > + ); > + > +/** > + Reads a 16-bit MMIO register. > + > + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is > + returned. This function must guarantee that all MMIO read and write > + operations are serialized. > + > + If 16-bit MMIO register operations are not supported, then ASSERT(). > + > + @param Address The MMIO register to read. > + > + @return The value read. > + > +**/ > +UINT16 > +EFIAPI > +MmioRead16Internal ( > + IN UINTN Address > + ); > + > +/** > + Writes a 16-bit MMIO register. > + > + Writes the 16-bit MMIO register specified by Address with the value specified > + by Value. This function must guarantee that all MMIO read and write operations > + are serialized. > + > + If 16-bit MMIO register operations are not supported, then ASSERT(). > + > + @param Address The MMIO register to write. > + @param Value The value to write to the MMIO register. > + > +**/ > +VOID > +EFIAPI > +MmioWrite16Internal ( > + IN UINTN Address, > + IN UINT16 Value > + ); > + > +/** > + Reads a 32-bit MMIO register. > + > + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is > + returned. This function must guarantee that all MMIO read and write > + operations are serialized. > + > + If 32-bit MMIO register operations are not supported, then ASSERT(). > + > + @param Address The MMIO register to read. > + > + @return The value read. > + > +**/ > +UINT32 > +EFIAPI > +MmioRead32Internal ( > + IN UINTN Address > + ); > + > +/** > + Writes a 32-bit MMIO register. > + > + Writes the 32-bit MMIO register specified by Address with the value specified > + by Value. This function must guarantee that all MMIO read and write operations > + are serialized. > + > + If 32-bit MMIO register operations are not supported, then ASSERT(). > + > + @param Address The MMIO register to write. > + @param Value The value to write to the MMIO register. > + > +**/ > +VOID > +EFIAPI > +MmioWrite32Internal ( > + IN UINTN Address, > + IN UINT32 Value > + ); > + > +/** > + Reads a 64-bit MMIO register. > + > + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is > + returned. This function must guarantee that all MMIO read and write > + operations are serialized. > + > + If 64-bit MMIO register operations are not supported, then ASSERT(). > + > + @param Address The MMIO register to read. > + > + @return The value read. > + > +**/ > +UINT64 > +EFIAPI > +MmioRead64Internal ( > + IN UINTN Address > + ); > + > +/** > + Writes a 64-bit MMIO register. > + > + Writes the 64-bit MMIO register specified by Address with the value specified > + by Value. This function must guarantee that all MMIO read and write operations > + are serialized. > + > + If 64-bit MMIO register operations are not supported, then ASSERT(). > + > + @param Address The MMIO register to write. > + @param Value The value to write to the MMIO register. > + > +**/ > +VOID > +EFIAPI > +MmioWrite64Internal ( > + IN UINTN Address, > + IN UINT64 Value > + ); > + > +#endif >