public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Gao, Liming" <liming.gao@intel.com>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>,
	"lersek@redhat.com" <lersek@redhat.com>,
	"leif.lindholm@linaro.org" <leif.lindholm@linaro.org>
Subject: Re: [PATCH v3 1/2] MdePkg/BaseIoLibIntrinsic: make BaseIoLibIntrinsic safe for ArmVirt/KVM
Date: Mon, 11 Jun 2018 15:51:53 +0000	[thread overview]
Message-ID: <4A89E2EF3DFEDB4C8BFDE51014F606A14E29592C@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <20180611072553.30050-1-ard.biesheuvel@linaro.org>

Reviewed-by: Liming Gao <liming.gao@intel.com>

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard Biesheuvel
> Sent: Monday, June 11, 2018 3:26 PM
> To: edk2-devel@lists.01.org
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; lersek@redhat.com; Gao, Liming <liming.gao@intel.com>;
> leif.lindholm@linaro.org; Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Subject: [edk2] [PATCH v3 1/2] 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 <ard.biesheuvel@linaro.org>
> ---
> v3: add missing prototype comments in IoLibArmVirt.c
>     remove mention of ASSERT () from description of internal asm routines
> v2: add missing .uni file
>     split off ArmVirtPkg change
>     add VS2017 version of AArch64 asm file
>     add reference to MdePkg.dsc
> 
>  MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S         | 148 ++++
>  MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm       | 149 ++++
>  MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S             | 145 ++++
>  MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm           | 149 ++++
>  MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf |  52 ++
>  MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni |  23 +
>  MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c                | 733 ++++++++++++++++++++
>  MdePkg/MdePkg.dsc                                               |   1 +
>  8 files changed, 1400 insertions(+)
> 
> diff --git a/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S
> new file mode 100644
> index 000000000000..85f59324270c
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S
> @@ -0,0 +1,148 @@
> +#
> +#  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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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/AArch64/ArmVirtMmio.asm
> b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm
> new file mode 100644
> index 000000000000..bd235a5dd441
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm
> @@ -0,0 +1,149 @@
> +;
> +;  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.
> +;
> +;  @param  Address The MMIO register to read.
> +;
> +;  @return The value read.
> +;
> +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.
> +;
> +;  @param  Address The MMIO register to write.
> +;  @param  Value   The value to write to the MMIO register.
> +;
> +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.
> +;
> +;  @param  Address The MMIO register to read.
> +;
> +;  @return The value read.
> +;
> +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.
> +;
> +;  @param  Address The MMIO register to write.
> +;  @param  Value   The value to write to the MMIO register.
> +;
> +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.
> +;
> +;  @param  Address The MMIO register to read.
> +;
> +;  @return The value read.
> +;
> +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.
> +;
> +;  @param  Address The MMIO register to write.
> +;  @param  Value   The value to write to the MMIO register.
> +;
> +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.
> +;
> +;  @param  Address The MMIO register to read.
> +;
> +;  @return The value read.
> +;
> +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.
> +;
> +;  @param  Address The MMIO register to write.
> +;  @param  Value   The value to write to the MMIO register.
> +;
> +MmioWrite64Internal
> +  dmb     st
> +  str     x1, [x0]
> +  ret
> +
> +  END
> diff --git a/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S b/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S
> new file mode 100644
> index 000000000000..1e91e87fb887
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S
> @@ -0,0 +1,145 @@
> +#
> +#  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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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.
> +//
> +//  @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..cff99b86a99c
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm
> @@ -0,0 +1,149 @@
> +;
> +;  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.
> +;
> +;  @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.
> +;
> +;  @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.
> +;
> +;  @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.
> +;
> +;  @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.
> +;
> +;  @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.
> +;
> +;  @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.
> +;
> +;  @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.
> +;
> +;  @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..1e39ad533fac
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf
> @@ -0,0 +1,52 @@
> +## @file
> +#  Instance of I/O Library using KVM/ARM safe assembler routines
> +#
> +#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
> +#  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
> +#  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +#  Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials are licensed and made available
> +#  under the terms and conditions of the BSD License which accompanies this
> +#  distribution. The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php.
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001A
> +  BASE_NAME                      = BaseIoLibIntrinsicArmVirt
> +  MODULE_UNI_FILE                = BaseIoLibIntrinsicArmVirt.uni
> +  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   | GCC
> +  AArch64/ArmVirtMmio.asm | MSFT
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +  BaseLib
> diff --git a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni
> b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni
> new file mode 100644
> index 000000000000..a1109c520453
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni
> @@ -0,0 +1,23 @@
> +// /** @file
> +//   Instance of I/O Library using KVM/ARM safe assembler routines
> +//
> +//   Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
> +//   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
> +//   Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +//   Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
> +//
> +//   This program and the accompanying materials are licensed and made available
> +//   under the terms and conditions of the BSD License which accompanies this
> +//   distribution. The full text of the license may be found at
> +//   http://opensource.org/licenses/bsd-license.php.
> +//
> +//   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +//   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "Instance of I/O Library using KVM/ARM safe assembler routines"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "I/O Library that uses assembler routines to perform MMIO
> accesses, to prevent link time code generation under LTO from emitting instructions that KVM on ARM cannot deal with."
> +
> diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c b/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c
> new file mode 100644
> index 000000000000..1a1b77967d55
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c
> @@ -0,0 +1,733 @@
> +/** @file
> +  I/O Library for ARM.
> +
> +  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
> +  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
> +  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +  Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
> +
> +  This program and the accompanying materials are licensed and made available
> +  under the terms and conditions of the BSD License which accompanies this
> +  distribution. The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include "BaseIoLibIntrinsicInternal.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.
> +
> +  @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 and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  @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.
> +
> +  @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 and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  @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.
> +
> +  @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 and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  @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.
> +
> +  @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 and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  @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
> +  );
> +
> +/**
> +  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;
> +}
> diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
> index 60efd722e9d7..cf20bc3a1fcf 100644
> --- a/MdePkg/MdePkg.dsc
> +++ b/MdePkg/MdePkg.dsc
> @@ -186,6 +186,7 @@ [Components.EBC]
>    MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
> 
>  [Components.ARM, Components.AARCH64]
> +  MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf
>    MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
> 
>  [BuildOptions]
> --
> 2.17.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


  parent reply	other threads:[~2018-06-11 15:51 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-11  7:25 [PATCH v3 1/2] MdePkg/BaseIoLibIntrinsic: make BaseIoLibIntrinsic safe for ArmVirt/KVM Ard Biesheuvel
2018-06-11  7:25 ` [PATCH v3 2/2] ArmVirtPkg: switch to KVM safe IoLib implementation Ard Biesheuvel
2018-06-11 10:44   ` Laszlo Ersek
2018-06-11 16:05     ` Ard Biesheuvel
2018-06-11 10:44 ` [PATCH v3 1/2] MdePkg/BaseIoLibIntrinsic: make BaseIoLibIntrinsic safe for ArmVirt/KVM Laszlo Ersek
2018-06-11 15:51 ` Gao, Liming [this message]
2018-06-11 16:04   ` Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A89E2EF3DFEDB4C8BFDE51014F606A14E29592C@SHSMSX104.ccr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox