From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c0b::242; helo=mail-it0-x242.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it0-x242.google.com (mail-it0-x242.google.com [IPv6:2607:f8b0:4001:c0b::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 1E9932115C319 for ; Thu, 7 Jun 2018 08:09:35 -0700 (PDT) Received: by mail-it0-x242.google.com with SMTP id n7-v6so13310897itn.1 for ; Thu, 07 Jun 2018 08:09:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=zkHnmRppGnv1wxqMCOYr0wjkFUJ+ALDh04MoQgu9mf8=; b=DKaELxgCdvMemw3SVy2I94prYPOliJ0xp0rmXyqHGuWiAKs1SrKZj53aBZFojyzoWU JMEuMZ8gXABBlQe9QqIBoTTvxi5Q7vroFYcHZhINr+c2E7BTLC4UBd06E/1Pq1GjaA5w 6TGogcNPHs8hJioxOuODXv7bu3IurqSKjjOec= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=zkHnmRppGnv1wxqMCOYr0wjkFUJ+ALDh04MoQgu9mf8=; b=M4DnnAKFXxVKD+papFsqWb1TDADr02nmjJYXqOzxG1AdrWcTWMKAOsvnFjcGQWWd1N qyVA8tu+tsUNeaJ4rKuSfdcYsayiNVtr1Ir69vQ8HyQSUa+FwA53WTlNuSD1QHuVvNmb gw3N1Ot3eQS2KJRnrl3ljIW+F1VaFevSMtCEwlF1tpivphAEEIdUhdKV2zKYb/v7F8So UQTnAsB0r7tXgFqC83zOOGEgkSPm2enOTbDQay3nI0rfS0Y1nkmx4a28ozy8dI/l7MFW K1ybB6b6ixYxbLYzncSNhaqw03dq4Ncf9OUBjoqd7+U31H4jx0xfZBQcjlTMHgVRUS2L 88+A== X-Gm-Message-State: APt69E0y7VvFxGzRKwWV0bb3tLwWcTM0fFiAeGwvI8QngkWFeNiu8aID RFUoyYLLRN3GKNiC4Oe0uG+J68w6T1jdBbMVkVLIFg== X-Google-Smtp-Source: ADUXVKIjCNh1GFrtoKY5gyKyuRuA4H6om5iL6tG64V2nYLGZ3Dl7NIBPHnkKINEour/QaSMPW/7j4cum2LacY2ybwW8= X-Received: by 2002:a24:534e:: with SMTP id n75-v6mr2305262itb.138.1528384173908; Thu, 07 Jun 2018 08:09:33 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a6b:bbc7:0:0:0:0:0 with HTTP; Thu, 7 Jun 2018 08:09:33 -0700 (PDT) In-Reply-To: <4A89E2EF3DFEDB4C8BFDE51014F606A14E294430@SHSMSX104.ccr.corp.intel.com> References: <20180607104645.22278-1-ard.biesheuvel@linaro.org> <4A89E2EF3DFEDB4C8BFDE51014F606A14E294430@SHSMSX104.ccr.corp.intel.com> From: Ard Biesheuvel Date: Thu, 7 Jun 2018 17:09:33 +0200 Message-ID: To: "Gao, Liming" , "lersek@redhat.com" Cc: "edk2-devel@lists.01.org" , "leif.lindholm@linaro.org" , "Kinney, Michael D" 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:09:35 -0000 Content-Type: text/plain; charset="UTF-8" On 7 June 2018 at 17:08, Gao, Liming wrote: > Ard: > If this library instance is specific to ARM emulator with KVM, how about add it into ArmVirtPkg? > Laszlo, do you want to take this question? >> -----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 >> >> 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 >> >> error: kvm run failed Function not implemented >> R00=01010101 R01=00000008 R02=00000048 R03=08000820 >> R04=00000120 R05=7faaa0e0 R06=7faaa0dc R07=7faaa0e8 >> R08=7faaa0ec R09=7faaa088 R10=000000ff R11=00000080 >> R12=ff000000 R13=7fccfe08 R14=7faa835f R15=7faa887c >> PSR=800001f3 N--- T svc32 >> QEMU: Terminated >> >> and KVM produces a warning such as the following in the kernel log >> >> kvm [17646]: load/store instruction decoding not implemented >> >> 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. >> >> 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. >> >> 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(-) >> >> 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/BasePeCoffGetEntryPointLib.inf >> PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf >> - IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf >> + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf >> UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf >> CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf >> >> diff --git a/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S b/MdePkg/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 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] >> + dmb 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): >> + 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 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): >> + 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 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): >> + 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 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): >> + 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 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. >> +# >> +# >> + >> +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] >> + dmb >> + 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): >> + 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 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): >> + 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 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): >> + 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 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): >> + dmb st >> + strd r2, r3, [r0] >> + bx lr >> diff --git a/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm b/MdePkg/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 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] >> + dmb >> + 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 >> + 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 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 >> + 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 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 >> + 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 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 >> + 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 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. >> +# >> +## >> + >> +[Defines] >> + INF_VERSION = 0x0001001A >> + BASE_NAME = BaseIoLibIntrinsicArmVirt >> + FILE_GUID = 217102b4-b465-4a1d-a2de-93dd385ec480 >> + MODULE_TYPE = BASE >> + VERSION_STRING = 1.0 >> + LIBRARY_CLASS = IoLib >> + >> +# >> +# VALID_ARCHITECTURES = 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/Library/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 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 "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 returned. >> + 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 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 by 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 are >> + 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 are >> + 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 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 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 are >> + 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 are >> + 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 are >> + 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 are >> + 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 are >> + 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 are >> + 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 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 >> +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 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. >> + >> +**/ >> +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 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 >> +MmioRead16 ( >> + IN UINTN Address >> + ) >> +{ >> + ASSERT ((Address & 1) == 0); >> + >> + return MmioRead16Internal (Address); >> +} >> + >> +/** >> + 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. >> + >> +**/ >> +UINT16 >> +EFIAPI >> +MmioWrite16 ( >> + IN UINTN Address, >> + IN UINT16 Value >> + ) >> +{ >> + ASSERT ((Address & 1) == 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 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 >> +MmioRead32 ( >> + IN UINTN Address >> + ) >> +{ >> + ASSERT ((Address & 3) == 0); >> + >> + return MmioRead32Internal (Address); >> +} >> + >> +/** >> + 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. >> + >> +**/ >> +UINT32 >> +EFIAPI >> +MmioWrite32 ( >> + IN UINTN Address, >> + IN UINT32 Value >> + ) >> +{ >> + ASSERT ((Address & 3) == 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 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 >> +MmioRead64 ( >> + IN UINTN Address >> + ) >> +{ >> + ASSERT ((Address & 7) == 0); >> + >> + return MmioRead64Internal (Address); >> +} >> + >> +/** >> + 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. >> + >> +**/ >> +UINT64 >> +EFIAPI >> +MmioWrite64 ( >> + IN UINTN Address, >> + IN UINT64 Value >> + ) >> +{ >> + ASSERT ((Address & 7) == 0); >> + >> + MmioWrite64Internal (Address, Value); >> + return Value; >> +} >> -- >> 2.17.0 >