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/AArch64/ArmVirtMmio.asm b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm
new file mode 100644
index 000000000000..0a3d9fc9c94a
--- /dev/null
+++ b/MdePkg/Library/BaseIoLibIntrinsic/AArch64/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    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.
+;
+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.
+;
+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.
+;
+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.
+;
+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.
+;
+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.
+;
+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.
+;
+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..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..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..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.<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"
+
+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;
+}
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]
