From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.88; helo=mga01.intel.com; envelope-from=liming.gao@intel.com; receiver=edk2-devel@lists.01.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (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 16E492114844F for ; Thu, 7 Jun 2018 08:08:29 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Jun 2018 08:08:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,486,1520924400"; d="scan'208";a="62120411" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2018 08:08:29 -0700 Received: from fmsmsx112.amr.corp.intel.com (10.18.116.6) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 7 Jun 2018 08:08:29 -0700 Received: from shsmsx102.ccr.corp.intel.com (10.239.4.154) by FMSMSX112.amr.corp.intel.com (10.18.116.6) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 7 Jun 2018 08:08:27 -0700 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.87]) by shsmsx102.ccr.corp.intel.com ([169.254.2.223]) with mapi id 14.03.0319.002; Thu, 7 Jun 2018 23:08:26 +0800 From: "Gao, Liming" To: Ard Biesheuvel , "edk2-devel@lists.01.org" CC: "lersek@redhat.com" , "leif.lindholm@linaro.org" , "Kinney, Michael D" Thread-Topic: [PATCH] MdePkg/BaseIoLibIntrinsic: make BaseIoLibIntrinsic safe for ArmVirt/KVM Thread-Index: AQHT/kza7JEWA5/Tr0msG9/qtPTIAKRU5bIg Date: Thu, 7 Jun 2018 15:08:26 +0000 Message-ID: <4A89E2EF3DFEDB4C8BFDE51014F606A14E294430@SHSMSX104.ccr.corp.intel.com> References: <20180607104645.22278-1-ard.biesheuvel@linaro.org> In-Reply-To: <20180607104645.22278-1-ard.biesheuvel@linaro.org> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ctpclassification: CTP_NT x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiZjA0M2I3Y2MtZWEzMi00YmFhLWI1NDUtY2JhZTg0YWIxNTY1IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiV0FqNlJoUXFTT2pudEZ1ZjdjdkJnVmhXa2NreGxVN3dnTVVZVEpuZk52N1IzQWxqWnhTeG8wcUwweXhidVRmeSJ9 dlp-product: dlpe-windows dlp-version: 11.0.200.100 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH] MdePkg/BaseIoLibIntrinsic: make BaseIoLibIntrinsic safe for ArmVirt/KVM 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: Thu, 07 Jun 2018 15:08:30 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Ard: If this library instance is specific to ARM emulator with KVM, how about = add it into ArmVirtPkg? Thanks Liming > -----Original Message----- > From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] > Sent: Thursday, June 7, 2018 6:47 PM > To: edk2-devel@lists.01.org > Cc: lersek@redhat.com; leif.lindholm@linaro.org; Gao, Liming ; Kinney, Michael D > ; Ard Biesheuvel > Subject: [PATCH] MdePkg/BaseIoLibIntrinsic: make BaseIoLibIntrinsic safe = for ArmVirt/KVM >=20 > KVM on ARM refuses to decode load/store instructions used to perform > I/O to emulated devices, and instead relies on the exception syndrome > information to describe the operand register, access size, etc. > This is only possible for instructions that have a single input/output > register (as opposed to ones that increment the offset register, or > load/store pair instructions, etc). Otherwise, QEMU crashes with the > following error >=20 > error: kvm run failed Function not implemented > R00=3D01010101 R01=3D00000008 R02=3D00000048 R03=3D08000820 > R04=3D00000120 R05=3D7faaa0e0 R06=3D7faaa0dc R07=3D7faaa0e8 > R08=3D7faaa0ec R09=3D7faaa088 R10=3D000000ff R11=3D00000080 > R12=3Dff000000 R13=3D7fccfe08 R14=3D7faa835f R15=3D7faa887c > PSR=3D800001f3 N--- T svc32 > QEMU: Terminated >=20 > and KVM produces a warning such as the following in the kernel log >=20 > kvm [17646]: load/store instruction decoding not implemented >=20 > The IoLib implementation provided by MdePkg/Library/BaseIoLibIntrinsic > is based on C code, and when LTO is in effect, the MMIO accesses could > be merged with, e.g., manipulations of the loop counter, producing > opcodes that KVM does not support for emulated MMIO. >=20 > So let's add a special ArmVirt flavor of this library that implements > that actual load/store operations in assembler, ensuring that the > instructions involved can be emulated by KVM. >=20 > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ard Biesheuvel > --- > ArmVirtPkg/ArmVirt.dsc.inc | 2 +- > MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S | 164 ++= +++ > MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S | 161 ++= +++ > MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm | 165 ++= +++ > MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf | 50 ++ > MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c | 641 ++= ++++++++++++++++++ > 6 files changed, 1182 insertions(+), 1 deletion(-) >=20 > diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc > index 766e4f598a07..7464ac70ed1b 100644 > --- a/ArmVirtPkg/ArmVirt.dsc.inc > +++ b/ArmVirtPkg/ArmVirt.dsc.inc > @@ -41,7 +41,7 @@ [LibraryClasses.common] > PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf > PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BaseP= eCoffGetEntryPointLib.inf > PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf > - IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf > + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf > UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompr= essLib.inf > CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf >=20 > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S b/Md= ePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S > new file mode 100644 > index 000000000000..47be68a3e783 > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S > @@ -0,0 +1,164 @@ > +# > +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. > +# > +# This program and the accompanying materials are licensed and made ava= ilable > +# under the terms and conditions of the BSD License which accompanies t= his > +# 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 v= alue 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] > + dmb ld > + ret > + > +// > +// Writes an 8-bit MMIO register. > +// > +// Writes the 8-bit MMIO register specified by Address with the value s= pecified > +// by Value and returns Value. This function must guarantee that all MM= IO 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): > + dmb 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] > + dmb 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 MM= IO 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): > + dmb 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] > + dmb 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 MM= IO 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): > + dmb 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] > + dmb 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 MM= IO 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): > + dmb st > + str x1, [x0] > + ret > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S b/MdePkg= /Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S > new file mode 100644 > index 000000000000..438805ca7c24 > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S > @@ -0,0 +1,161 @@ > +# > +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. > +# > +# This program and the accompanying materials are licensed and made ava= ilable > +# under the terms and conditions of the BSD License which accompanies t= his > +# 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. > +# > +# > + > +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 v= alue 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] > + dmb > + bx lr > + > +// > +// Writes an 8-bit MMIO register. > +// > +// Writes the 8-bit MMIO register specified by Address with the value s= pecified > +// by Value and returns Value. This function must guarantee that all MM= IO 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): > + dmb 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] > + dmb > + 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 MM= IO 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): > + dmb 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] > + dmb > + 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 MM= IO 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): > + dmb 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] > + dmb > + 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 MM= IO 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): > + dmb st > + strd r2, r3, [r0] > + bx lr > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm b/MdeP= kg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm > new file mode 100644 > index 000000000000..82add82f800a > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm > @@ -0,0 +1,165 @@ > +; > +; Copyright (c) 2014-2018, Linaro Limited. All rights reserved. > +; > +; This program and the accompanying materials are licensed and made ava= ilable > +; under the terms and conditions of the BSD License which accompanies t= his > +; 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 va= lue 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] > + dmb > + bx lr > + > +; > +; Writes an 8-bit MMIO register. > +; > +; Writes the 8-bit MMIO register specified by Address with the value sp= ecified > +; by Value and returns Value. This function must guarantee that all MMI= O 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 > + dmb 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] > + dmb > + bx lr > + > +; > +; Writes a 16-bit MMIO register. > +; > +; Writes the 16-bit MMIO register specified by Address with the value s= pecified > +; by Value and returns Value. This function must guarantee that all MMI= O 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 > + dmb 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] > + dmb > + bx lr > + > +; > +; Writes a 32-bit MMIO register. > +; > +; Writes the 32-bit MMIO register specified by Address with the value s= pecified > +; by Value and returns Value. This function must guarantee that all MMI= O 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 > + dmb 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] > + dmb > + bx lr > + > +; > +; Writes a 64-bit MMIO register. > +; > +; Writes the 64-bit MMIO register specified by Address with the value s= pecified > +; by Value and returns Value. This function must guarantee that all MMI= O 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 > + dmb st > + strd r2, r3, [r0] > + bx lr > + > + END > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.= inf > b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf > new file mode 100644 > index 000000000000..5a1dc87ed2bd > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf > @@ -0,0 +1,50 @@ > +## @file > +# Instance of I/O Library using KVM/ARM safe assembler routines > +# > +# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved. > +# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved. > +# Copyright (c) 2017, AMD Incorporated. All rights reserved.
> +# Copyright (c) 2018, Linaro, Ltd. All rights reserved.
> +# > +# This program and the accompanying materials are licensed and made ava= ilable > +# under the terms and conditions of the BSD License which accompanies t= his > +# 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. > +# > +## > + > +[Defines] > + INF_VERSION =3D 0x0001001A > + BASE_NAME =3D BaseIoLibIntrinsicArmVirt > + FILE_GUID =3D 217102b4-b465-4a1d-a2de-93dd385ec48= 0 > + MODULE_TYPE =3D BASE > + VERSION_STRING =3D 1.0 > + LIBRARY_CLASS =3D IoLib > + > +# > +# VALID_ARCHITECTURES =3D ARM AARCH64 > +# > + > +[Sources] > + IoLibMmioBuffer.c > + BaseIoLibIntrinsicInternal.h > + IoHighLevel.c > + > +[Sources.ARM] > + IoLibArmVirt.c > + Arm/ArmVirtMmio.S | GCC > + Arm/ArmVirtMmio.asm | RVCT > + > +[Sources.AARCH64] > + IoLibArmVirt.c > + AArch64/ArmVirtMmio.S > + > +[Packages] > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + DebugLib > + BaseLib > diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c b/MdePkg/Li= brary/BaseIoLibIntrinsic/IoLibArmVirt.c > new file mode 100644 > index 000000000000..154d583246ac > --- /dev/null > +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c > @@ -0,0 +1,641 @@ > +/** @file > + I/O Library for ARM. > + > + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
> + Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved. > + Copyright (c) 2017, AMD Incorporated. All rights reserved.
> + Copyright (c) 2018, Linaro, Ltd. All rights reserved.
> + > + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + 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 I= MPLIED. > + > +**/ > + > +#include "BaseIoLibIntrinsicInternal.h" > + > +UINT8 > +EFIAPI > +MmioRead8Internal ( > + IN UINTN Address > + ); > + > +VOID > +EFIAPI > +MmioWrite8Internal ( > + IN UINTN Address, > + IN UINT8 Value > + ); > + > +UINT16 > +EFIAPI > +MmioRead16Internal ( > + IN UINTN Address > + ); > + > +VOID > +EFIAPI > +MmioWrite16Internal ( > + IN UINTN Address, > + IN UINT16 Value > + ); > + > +UINT32 > +EFIAPI > +MmioRead32Internal ( > + IN UINTN Address > + ); > + > +VOID > +EFIAPI > +MmioWrite32Internal ( > + IN UINTN Address, > + IN UINT32 Value > + ); > + > +UINT64 > +EFIAPI > +MmioRead64Internal ( > + IN UINTN Address > + ); > + > +VOID > +EFIAPI > +MmioWrite64Internal ( > + IN UINTN Address, > + IN UINT64 Value > + ); > + > +/** > + Reads an 8-bit I/O port. > + > + Reads the 8-bit I/O port specified by Port. The 8-bit read value is re= turned. > + This function must guarantee that all I/O read and write operations ar= e > + serialized. > + > + If 8-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to read. > + > + @return The value read. > + > +**/ > +UINT8 > +EFIAPI > +IoRead8 ( > + IN UINTN Port > + ) > +{ > + ASSERT (FALSE); > + return 0; > +} > + > +/** > + Writes an 8-bit I/O port. > + > + Writes the 8-bit I/O port specified by Port with the value specified b= y Value > + and returns Value. This function must guarantee that all I/O read and = write > + operations are serialized. > + > + If 8-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to write. > + @param Value The value to write to the I/O port. > + > + @return The value written the I/O port. > + > +**/ > +UINT8 > +EFIAPI > +IoWrite8 ( > + IN UINTN Port, > + IN UINT8 Value > + ) > +{ > + ASSERT (FALSE); > + return Value; > +} > + > +/** > + Reads a 16-bit I/O port. > + > + Reads the 16-bit I/O port specified by Port. The 16-bit read value is = returned. > + This function must guarantee that all I/O read and write operations ar= e > + serialized. > + > + If 16-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to read. > + > + @return The value read. > + > +**/ > +UINT16 > +EFIAPI > +IoRead16 ( > + IN UINTN Port > + ) > +{ > + ASSERT (FALSE); > + return 0; > +} > + > +/** > + Writes a 16-bit I/O port. > + > + Writes the 16-bit I/O port specified by Port with the value specified = by Value > + and returns Value. This function must guarantee that all I/O read and = write > + operations are serialized. > + > + If 16-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to write. > + @param Value The value to write to the I/O port. > + > + @return The value written the I/O port. > + > +**/ > +UINT16 > +EFIAPI > +IoWrite16 ( > + IN UINTN Port, > + IN UINT16 Value > + ) > +{ > + ASSERT (FALSE); > + return Value; > +} > + > +/** > + Reads a 32-bit I/O port. > + > + Reads the 32-bit I/O port specified by Port. The 32-bit read value is = returned. > + This function must guarantee that all I/O read and write operations ar= e > + serialized. > + > + If 32-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to read. > + > + @return The value read. > + > +**/ > +UINT32 > +EFIAPI > +IoRead32 ( > + IN UINTN Port > + ) > +{ > + ASSERT (FALSE); > + return 0; > +} > + > +/** > + Writes a 32-bit I/O port. > + > + Writes the 32-bit I/O port specified by Port with the value specified = by Value > + and returns Value. This function must guarantee that all I/O read and = write > + operations are serialized. > + > + If 32-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to write. > + @param Value The value to write to the I/O port. > + > + @return The value written the I/O port. > + > +**/ > +UINT32 > +EFIAPI > +IoWrite32 ( > + IN UINTN Port, > + IN UINT32 Value > + ) > +{ > + ASSERT (FALSE); > + return Value; > +} > + > +/** > + Reads a 64-bit I/O port. > + > + Reads the 64-bit I/O port specified by Port. The 64-bit read value is = returned. > + This function must guarantee that all I/O read and write operations ar= e > + serialized. > + > + If 64-bit I/O port operations are not supported, then ASSERT(). > + If Port is not aligned on a 64-bit boundary, then ASSERT(). > + > + @param Port The I/O port to read. > + > + @return The value read. > + > +**/ > +UINT64 > +EFIAPI > +IoRead64 ( > + IN UINTN Port > + ) > +{ > + ASSERT (FALSE); > + return 0; > +} > + > +/** > + Writes a 64-bit I/O port. > + > + Writes the 64-bit I/O port specified by Port with the value specified = by Value > + and returns Value. This function must guarantee that all I/O read and = write > + operations are serialized. > + > + If 64-bit I/O port operations are not supported, then ASSERT(). > + If Port is not aligned on a 64-bit boundary, then ASSERT(). > + > + @param Port The I/O port to write. > + @param Value The value to write to the I/O port. > + > + @return The value written to the I/O port. > + > +**/ > +UINT64 > +EFIAPI > +IoWrite64 ( > + IN UINTN Port, > + IN UINT64 Value > + ) > +{ > + ASSERT (FALSE); > + return 0; > +} > + > +/** > + Reads an 8-bit I/O port fifo into a block of memory. > + > + Reads the 8-bit I/O fifo port specified by Port. > + The port is read Count times, and the read data is > + stored in the provided Buffer. > + > + This function must guarantee that all I/O read and write operations ar= e > + serialized. > + > + If 8-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to read. > + @param Count The number of times to read I/O port. > + @param Buffer The buffer to store the read data into. > + > +**/ > +VOID > +EFIAPI > +IoReadFifo8 ( > + IN UINTN Port, > + IN UINTN Count, > + OUT VOID *Buffer > + ) > +{ > + ASSERT (FALSE); > +} > + > +/** > + Writes a block of memory into an 8-bit I/O port fifo. > + > + Writes the 8-bit I/O fifo port specified by Port. > + The port is written Count times, and the write data is > + retrieved from the provided Buffer. > + > + This function must guarantee that all I/O write and write operations a= re > + serialized. > + > + If 8-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to write. > + @param Count The number of times to write I/O port. > + @param Buffer The buffer to retrieve the write data from. > + > +**/ > +VOID > +EFIAPI > +IoWriteFifo8 ( > + IN UINTN Port, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + ASSERT (FALSE); > +} > + > +/** > + Reads a 16-bit I/O port fifo into a block of memory. > + > + Reads the 16-bit I/O fifo port specified by Port. > + The port is read Count times, and the read data is > + stored in the provided Buffer. > + > + This function must guarantee that all I/O read and write operations ar= e > + serialized. > + > + If 16-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to read. > + @param Count The number of times to read I/O port. > + @param Buffer The buffer to store the read data into. > + > +**/ > +VOID > +EFIAPI > +IoReadFifo16 ( > + IN UINTN Port, > + IN UINTN Count, > + OUT VOID *Buffer > + ) > +{ > + ASSERT (FALSE); > +} > + > +/** > + Writes a block of memory into a 16-bit I/O port fifo. > + > + Writes the 16-bit I/O fifo port specified by Port. > + The port is written Count times, and the write data is > + retrieved from the provided Buffer. > + > + This function must guarantee that all I/O write and write operations a= re > + serialized. > + > + If 16-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to write. > + @param Count The number of times to write I/O port. > + @param Buffer The buffer to retrieve the write data from. > + > +**/ > +VOID > +EFIAPI > +IoWriteFifo16 ( > + IN UINTN Port, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + ASSERT (FALSE); > +} > + > +/** > + Reads a 32-bit I/O port fifo into a block of memory. > + > + Reads the 32-bit I/O fifo port specified by Port. > + The port is read Count times, and the read data is > + stored in the provided Buffer. > + > + This function must guarantee that all I/O read and write operations ar= e > + serialized. > + > + If 32-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to read. > + @param Count The number of times to read I/O port. > + @param Buffer The buffer to store the read data into. > + > +**/ > +VOID > +EFIAPI > +IoReadFifo32 ( > + IN UINTN Port, > + IN UINTN Count, > + OUT VOID *Buffer > + ) > +{ > + ASSERT (FALSE); > +} > + > +/** > + Writes a block of memory into a 32-bit I/O port fifo. > + > + Writes the 32-bit I/O fifo port specified by Port. > + The port is written Count times, and the write data is > + retrieved from the provided Buffer. > + > + This function must guarantee that all I/O write and write operations a= re > + serialized. > + > + If 32-bit I/O port operations are not supported, then ASSERT(). > + > + @param Port The I/O port to write. > + @param Count The number of times to write I/O port. > + @param Buffer The buffer to retrieve the write data from. > + > +**/ > +VOID > +EFIAPI > +IoWriteFifo32 ( > + IN UINTN Port, > + IN UINTN Count, > + IN VOID *Buffer > + ) > +{ > + ASSERT (FALSE); > +} > + > +/** > + Reads an 8-bit MMIO register. > + > + Reads the 8-bit MMIO register specified by Address. The 8-bit read val= ue 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 > +MmioRead8 ( > + IN UINTN Address > + ) > +{ > + return MmioRead8Internal (Address); > +} > + > +/** > + Writes an 8-bit MMIO register. > + > + Writes the 8-bit MMIO register specified by Address with the value spe= cified > + 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. > + > +**/ > +UINT8 > +EFIAPI > +MmioWrite8 ( > + IN UINTN Address, > + IN UINT8 Value > + ) > +{ > + MmioWrite8Internal (Address, Value); > + return Value; > +} > + > +/** > + Reads a 16-bit MMIO register. > + > + Reads the 16-bit MMIO register specified by Address. The 16-bit read v= alue 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 > +MmioRead16 ( > + IN UINTN Address > + ) > +{ > + ASSERT ((Address & 1) =3D=3D 0); > + > + return MmioRead16Internal (Address); > +} > + > +/** > + Writes a 16-bit MMIO register. > + > + Writes the 16-bit MMIO register specified by Address with the value sp= ecified > + 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. > + > +**/ > +UINT16 > +EFIAPI > +MmioWrite16 ( > + IN UINTN Address, > + IN UINT16 Value > + ) > +{ > + ASSERT ((Address & 1) =3D=3D 0); > + > + MmioWrite16Internal (Address, Value); > + return Value; > +} > + > +/** > + Reads a 32-bit MMIO register. > + > + Reads the 32-bit MMIO register specified by Address. The 32-bit read v= alue 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 > +MmioRead32 ( > + IN UINTN Address > + ) > +{ > + ASSERT ((Address & 3) =3D=3D 0); > + > + return MmioRead32Internal (Address); > +} > + > +/** > + Writes a 32-bit MMIO register. > + > + Writes the 32-bit MMIO register specified by Address with the value sp= ecified > + 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. > + > +**/ > +UINT32 > +EFIAPI > +MmioWrite32 ( > + IN UINTN Address, > + IN UINT32 Value > + ) > +{ > + ASSERT ((Address & 3) =3D=3D 0); > + > + MmioWrite32Internal (Address, Value); > + return Value; > +} > + > +/** > + Reads a 64-bit MMIO register. > + > + Reads the 64-bit MMIO register specified by Address. The 64-bit read v= alue 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 > +MmioRead64 ( > + IN UINTN Address > + ) > +{ > + ASSERT ((Address & 7) =3D=3D 0); > + > + return MmioRead64Internal (Address); > +} > + > +/** > + Writes a 64-bit MMIO register. > + > + Writes the 64-bit MMIO register specified by Address with the value sp= ecified > + 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. > + > +**/ > +UINT64 > +EFIAPI > +MmioWrite64 ( > + IN UINTN Address, > + IN UINT64 Value > + ) > +{ > + ASSERT ((Address & 7) =3D=3D 0); > + > + MmioWrite64Internal (Address, Value); > + return Value; > +} > -- > 2.17.0