All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 01/29] ArmPkg: allow HYP timer interrupt to be omitted
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-12 11:18 ` Ard Biesheuvel
  2015-02-12 11:18 ` [PATCH v4 02/29] ArmPkg: allow patchable PCDs for memory, FD and FV addresses Ard Biesheuvel
                   ` (37 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:18 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

The DT binding for the ARM generic timer describes the secure,
non-secure, virtual and hypervisor timer interrupts, respectively.
However, under virtualization, only the virtual timer is usable, and
the device tree may omit the hypervisor timer interrupt. (Other timer
interrupts cannot be omitted simply due to the fact that the virtual
timer is listed third)

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPkg/Drivers/TimerDxe/TimerDxe.c                          | 14 +++++++++++---
 ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c |  6 +++---
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/ArmPkg/Drivers/TimerDxe/TimerDxe.c b/ArmPkg/Drivers/TimerDxe/TimerDxe.c
index d0a819fc2729..1169d426b255 100644
--- a/ArmPkg/Drivers/TimerDxe/TimerDxe.c
+++ b/ArmPkg/Drivers/TimerDxe/TimerDxe.c
@@ -369,7 +369,8 @@ TimerInitialize (
 {
   EFI_HANDLE  Handle = NULL;
   EFI_STATUS  Status;
-  UINTN TimerCtrlReg;
+  UINTN       TimerCtrlReg;
+  UINT32      TimerHypIntrNum;
 
   if (ArmIsArchTimerImplemented () == 0) {
     DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence cann't use this Driver \n"));
@@ -395,8 +396,15 @@ TimerInitialize (
   Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerVirtIntrNum), TimerInterruptHandler);
   ASSERT_EFI_ERROR (Status);
 
-  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerHypIntrNum), TimerInterruptHandler);
-  ASSERT_EFI_ERROR (Status);
+  //
+  // The hypervisor timer interrupt may be omitted by implementations that
+  // execute under virtualization.
+  //
+  TimerHypIntrNum = PcdGet32 (PcdArmArchTimerHypIntrNum);
+  if (TimerHypIntrNum != 0) {
+    Status = gInterrupt->RegisterInterruptSource (gInterrupt, TimerHypIntrNum, TimerInterruptHandler);
+    ASSERT_EFI_ERROR (Status);
+  }
 
   Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum), TimerInterruptHandler);
   ASSERT_EFI_ERROR (Status);
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
index 751864d4db9c..1d44f9ba02b3 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
@@ -274,7 +274,7 @@ InitializeVirtFdtDxe (
       //  hypervisor timers, in that order.
       //
       InterruptProp = fdt_getprop (DeviceTreeBase, Node, "interrupts", &Len);
-      ASSERT (Len == 48);
+      ASSERT (Len == 36 || Len == 48);
 
       SecIntrNum = fdt32_to_cpu (InterruptProp[0].Number)
                    + (InterruptProp[0].Type ? 16 : 0);
@@ -282,8 +282,8 @@ InitializeVirtFdtDxe (
                 + (InterruptProp[1].Type ? 16 : 0);
       VirtIntrNum = fdt32_to_cpu (InterruptProp[2].Number)
                     + (InterruptProp[2].Type ? 16 : 0);
-      HypIntrNum = fdt32_to_cpu (InterruptProp[3].Number)
-                   + (InterruptProp[3].Type ? 16 : 0);
+      HypIntrNum = Len < 48 ? 0 : fdt32_to_cpu (InterruptProp[3].Number)
+                                  + (InterruptProp[3].Type ? 16 : 0);
 
       DEBUG ((EFI_D_INFO, "Found Timer interrupts %d, %d, %d, %d\n",
         SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum));
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 02/29] ArmPkg: allow patchable PCDs for memory, FD and FV addresses
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
  2015-02-12 11:18 ` [PATCH v4 01/29] ArmPkg: allow HYP timer interrupt to be omitted Ard Biesheuvel
@ 2015-02-12 11:18 ` Ard Biesheuvel
  2015-02-12 11:18 ` [PATCH v4 03/29] ArmPlatformPkg: allow patchable PCD for FD base address Ard Biesheuvel
                   ` (36 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:18 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

In order to allow a runtime self relocating PrePi instance, change the
allowable PCD types for the following PCDs:

  gArmTokenSpaceGuid.PcdSystemMemoryBase
  gArmTokenSpaceGuid.PcdSystemMemorySize
  gArmTokenSpaceGuid.PcdFdBaseAddress
  gArmTokenSpaceGuid.PcdFvBaseAddress

to include PcdsPatchableInModule. This makes the build system correctly
distinguish fixed PCDs from PCDs whose value may be different from the
assigned value at compile time.

Note that this only affects platforms that explicitly mark these PCDs as
PatchableInModule in the DSC. All existing platforms that use FixedPcd
will not be affected by this change.

Contributed-under: TianoCore Contribution Agreement 1.0
Acked-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPkg/ArmPkg.dec | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index ced392980102..87dbd11b867f 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -96,14 +96,6 @@
   gArmTokenSpaceGuid.PcdSecureFvSize|0x0|UINT32|0x00000030
 
   #
-  # ARM Normal (or Non Secure) Firmware PCDs
-  #
-  gArmTokenSpaceGuid.PcdFdBaseAddress|0|UINT64|0x0000002B
-  gArmTokenSpaceGuid.PcdFdSize|0|UINT32|0x0000002C
-  gArmTokenSpaceGuid.PcdFvBaseAddress|0|UINT64|0x0000002D
-  gArmTokenSpaceGuid.PcdFvSize|0|UINT32|0x0000002E
-
-  #
   # ARM Hypervisor Firmware PCDs
   #
   gArmTokenSpaceGuid.PcdHypFdBaseAddress|0|UINT32|0x0000003A
@@ -130,6 +122,15 @@
   # Maximum file size for TFTP servers that do not support 'tsize' extension
   gArmTokenSpaceGuid.PcdMaxTftpFileSize|0x01000000|UINT32|0x00000000
 
+  #
+  # ARM Normal (or Non Secure) Firmware PCDs
+  #
+  gArmTokenSpaceGuid.PcdFdSize|0|UINT32|0x0000002C
+  gArmTokenSpaceGuid.PcdFvSize|0|UINT32|0x0000002E
+
+[PcdsFixedAtBuild.common, PcdsPatchableInModule.common]
+  gArmTokenSpaceGuid.PcdFdBaseAddress|0|UINT64|0x0000002B
+  gArmTokenSpaceGuid.PcdFvBaseAddress|0|UINT64|0x0000002D
 
 [PcdsFixedAtBuild.ARM]
   #
@@ -210,16 +211,18 @@
 
 
 #
-# These PCDs are also defined as 'PcdsDynamic' to be redefined when using UEFI in a
-# context of virtual machine.
+# These PCDs are also defined as 'PcdsDynamic' or 'PcdsPatchableInModule' to be
+# redefined when using UEFI in a context of virtual machine.
 #
-[PcdsFixedAtBuild.common, PcdsDynamic.common]
+[PcdsFixedAtBuild.common, PcdsDynamic.common, PcdsPatchableInModule.common]
+
   # System Memory (DRAM): These PCDs define the region of in-built system memory
   # Some platforms can get DRAM extensions, these additional regions will be declared
   # to UEFI by ArmPlatformLib
   gArmTokenSpaceGuid.PcdSystemMemoryBase|0|UINT64|0x00000029
   gArmTokenSpaceGuid.PcdSystemMemorySize|0|UINT64|0x0000002A
 
+[PcdsFixedAtBuild.common, PcdsDynamic.common]
   #
   # ARM Architectural Timer
   #
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 03/29] ArmPlatformPkg: allow patchable PCD for FD base address
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
  2015-02-12 11:18 ` [PATCH v4 01/29] ArmPkg: allow HYP timer interrupt to be omitted Ard Biesheuvel
  2015-02-12 11:18 ` [PATCH v4 02/29] ArmPkg: allow patchable PCDs for memory, FD and FV addresses Ard Biesheuvel
@ 2015-02-12 11:18 ` Ard Biesheuvel
  2015-02-12 11:18 ` [PATCH v4 04/29] ArmVirtualizationPkg: add GICv3 detection to VirtFdtDxe Ard Biesheuvel
                   ` (35 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:18 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This moves the reference to gArmTokenSpaceGuid.PcdFdBaseAddress
from the [FixedPcd] to the [Pcd] section in the INF file of
PrePiArmPlatformGlobalVariableLib so that its users may choose
to use a patchable PCD instead.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf b/ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf
index 596f5595412e..37de35e7d00e 100644
--- a/ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf
+++ b/ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf
@@ -34,7 +34,6 @@
   PcdLib
 
 [FixedPcd]
-  gArmTokenSpaceGuid.PcdFdBaseAddress
   gArmTokenSpaceGuid.PcdFdSize
 
   gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
@@ -43,4 +42,5 @@
 [Pcd]
   gArmTokenSpaceGuid.PcdSystemMemoryBase
   gArmTokenSpaceGuid.PcdSystemMemorySize
+  gArmTokenSpaceGuid.PcdFdBaseAddress
 
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 04/29] ArmVirtualizationPkg: add GICv3 detection to VirtFdtDxe
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (2 preceding siblings ...)
  2015-02-12 11:18 ` [PATCH v4 03/29] ArmPlatformPkg: allow patchable PCD for FD base address Ard Biesheuvel
@ 2015-02-12 11:18 ` Ard Biesheuvel
  2015-02-12 11:18 ` [PATCH v4 05/29] ArmVirtualizationPkg: allow patchable PCD for device tree base address Ard Biesheuvel
                   ` (34 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:18 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This adds support for detecting the presence of a GICv3 interrupt
controller from the device tree, and recording its distributor and
redistributor base addresses in their respective PCDs.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc |  1 +
 ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c   | 34 +++++++++++++++++++++++++++++++++-
 ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf |  1 +
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
index 32c8deb3b1d6..066108f66d28 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
@@ -172,6 +172,7 @@
   # ARM General Interrupt Controller
   #
   gArmTokenSpaceGuid.PcdGicDistributorBase|0x0
+  gArmTokenSpaceGuid.PcdGicRedistributorsBase|0x0
   gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x0
 
   ## PL031 RealTimeClock
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
index 1d44f9ba02b3..a12bd8686fcc 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
@@ -46,6 +46,7 @@ typedef enum {
   PropertyTypeTimer,
   PropertyTypePsci,
   PropertyTypeFwCfg,
+  PropertyTypeGicV3,
 } PROPERTY_TYPE;
 
 typedef struct {
@@ -62,6 +63,7 @@ STATIC CONST PROPERTY CompatibleProperties[] = {
   { PropertyTypeTimer,   "arm,armv8-timer"     },
   { PropertyTypePsci,    "arm,psci-0.2"        },
   { PropertyTypeFwCfg,   "qemu,fw-cfg-mmio"    },
+  { PropertyTypeGicV3,   "arm,gic-v3"          },
   { PropertyTypeUnknown, ""                    }
 };
 
@@ -114,7 +116,7 @@ InitializeVirtFdtDxe (
   VIRTIO_TRANSPORT_DEVICE_PATH   *DevicePath;
   EFI_HANDLE                     Handle;
   UINT64                         RegBase;
-  UINT64                         DistBase, CpuBase;
+  UINT64                         DistBase, CpuBase, RedistBase;
   CONST INTERRUPT_PROPERTY       *InterruptProp;
   INT32                          SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;
   CONST CHAR8                    *PsciMethod;
@@ -256,6 +258,36 @@ InitializeVirtFdtDxe (
       DEBUG ((EFI_D_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));
       break;
 
+    case PropertyTypeGicV3:
+      //
+      // The GIC v3 DT binding describes a series of at least 3 physical (base
+      // addresses, size) pairs: the distributor interface (GICD), at least one
+      // redistributor region (GICR) containing dedicated redistributor
+      // interfaces for all individual CPUs, and the CPU interface (GICC).
+      // Under virtualization, we assume that the first redistributor region
+      // listed covers the boot CPU. Also, our GICv3 driver only supports the
+      // system register CPU interface, so we can safely ignore the MMIO version
+      // which is listed after the sequence of redistributor interfaces.
+      // This means we are only interested in the first two memory regions
+      // supplied, and ignore everything else.
+      //
+      ASSERT (Len >= 32);
+
+      // RegProp[0..1] == { GICD base, GICD size }
+      DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
+      ASSERT (DistBase < MAX_UINT32);
+
+      // RegProp[2..3] == { GICR base, GICR size }
+      RedistBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]);
+      ASSERT (RedistBase < MAX_UINT32);
+
+      PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);
+      PcdSet32 (PcdGicRedistributorsBase, (UINT32)RedistBase);
+
+      DEBUG ((EFI_D_INFO, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
+        DistBase, RedistBase));
+      break;
+
     case PropertyTypeRtc:
       ASSERT (Len == 16);
 
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
index 514ce2fdf658..1ed02b6f3750 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
@@ -51,6 +51,7 @@
   gArmVirtualizationTokenSpaceGuid.PcdFwCfgSelectorAddress
   gArmVirtualizationTokenSpaceGuid.PcdFwCfgDataAddress
   gArmTokenSpaceGuid.PcdGicDistributorBase
+  gArmTokenSpaceGuid.PcdGicRedistributorsBase
   gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
   gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
   gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 05/29] ArmVirtualizationPkg: allow patchable PCD for device tree base address
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (3 preceding siblings ...)
  2015-02-12 11:18 ` [PATCH v4 04/29] ArmVirtualizationPkg: add GICv3 detection to VirtFdtDxe Ard Biesheuvel
@ 2015-02-12 11:18 ` Ard Biesheuvel
  2015-02-12 11:18 ` [PATCH v4 06/29] ArmVirtualizationPkg: move early UART discovery to PlatformPeim Ard Biesheuvel
                   ` (33 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:18 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

To allow a runtime self relocating PrePi instance to discover the base
address of the device tree at runtime, allow the use of a patchable PCD
for gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress.
We will not be using the build time patch tool in this case, but using
a patchable PCD will make the build system aware that its value is not
a compile time constant.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec                    | 2 +-
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
index 99411548aff6..d83117fc6abe 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
@@ -34,7 +34,7 @@
   gArmVirtualizationTokenSpaceGuid = { 0x0B6F5CA7, 0x4F53, 0x445A, { 0xB7, 0x6E, 0x2E, 0x36, 0x5B, 0x80, 0x63, 0x66 } }
   gEarlyPL011BaseAddressGuid       = { 0xB199DEA9, 0xFD5C, 0x4A84, { 0x80, 0x82, 0x2F, 0x41, 0x70, 0x78, 0x03, 0x05 } }
 
-[PcdsFixedAtBuild]
+[PcdsFixedAtBuild, PcdsPatchableInModule]
   #
   # This is the physical address where the device tree is expected to be stored
   # upon first entry into UEFI. This needs to be a FixedAtBuild PCD, so that we
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c
index aa4ced4582e8..3e3074af72f1 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c
@@ -96,7 +96,7 @@ ArmPlatformInitializeSystemMemory (
   ASSERT (HobData != NULL);
   *HobData = 0;
 
-  DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress);
+  DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
   ASSERT (DeviceTreeBase != NULL);
 
   //
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 06/29] ArmVirtualizationPkg: move early UART discovery to PlatformPeim
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (4 preceding siblings ...)
  2015-02-12 11:18 ` [PATCH v4 05/29] ArmVirtualizationPkg: allow patchable PCD for device tree base address Ard Biesheuvel
@ 2015-02-12 11:18 ` Ard Biesheuvel
  2015-02-12 11:18 ` [PATCH v4 07/29] ArmVirtualizationPkg: use a HOB to store device tree blob Ard Biesheuvel
                   ` (32 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:18 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This is partially motivated by the desire to use PrePi in a virt
environment, and in that configuration, ArmPlatformInitializeSystemMemory()
is never called. But actually, this is a more suitable place anyway.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf |  3 ---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c                           | 46 ++--------------------------------------------
 ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c                               | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf                             |  3 +++
 4 files changed, 53 insertions(+), 47 deletions(-)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf
index d1572882af1b..43b3c6ca1bef 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf
@@ -62,6 +62,3 @@
   gArmTokenSpaceGuid.PcdArmPrimaryCore
   gArmTokenSpaceGuid.PcdFdBaseAddress
   gArmTokenSpaceGuid.PcdFdSize
-
-[Guids]
-  gEarlyPL011BaseAddressGuid
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c
index 3e3074af72f1..17f268697583 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c
@@ -24,9 +24,6 @@
 #include <Pi/PiBootMode.h>
 #include <Uefi/UefiBaseType.h>
 #include <Uefi/UefiMultiPhase.h>
-#include <Pi/PiHob.h>
-#include <Library/HobLib.h>
-#include <Guid/EarlyPL011BaseAddress.h>
 
 /**
   Return the current Boot Mode
@@ -77,25 +74,13 @@ ArmPlatformInitializeSystemMemory (
   INT32        Node, Prev;
   UINT64       NewBase;
   UINT64       NewSize;
-  BOOLEAN      HaveMemory, HaveUART;
-  UINT64       *HobData;
   CONST CHAR8  *Type;
-  CONST CHAR8  *Compatible;
-  CONST CHAR8  *CompItem;
   INT32        Len;
   CONST UINT64 *RegProp;
-  UINT64       UartBase;
 
   NewBase = 0;
   NewSize = 0;
 
-  HaveMemory = FALSE;
-  HaveUART   = FALSE;
-
-  HobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *HobData);
-  ASSERT (HobData != NULL);
-  *HobData = 0;
-
   DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
   ASSERT (DeviceTreeBase != NULL);
 
@@ -107,7 +92,7 @@ ArmPlatformInitializeSystemMemory (
   //
   // Look for a memory node
   //
-  for (Prev = 0; !(HaveMemory && HaveUART); Prev = Node) {
+  for (Prev = 0;; Prev = Node) {
     Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
     if (Node < 0) {
       break;
@@ -140,34 +125,7 @@ ArmPlatformInitializeSystemMemory (
         DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n",
                __FUNCTION__));
       }
-      HaveMemory = TRUE;
-      continue;
-    }
-
-    //
-    // Check for UART node
-    //
-    Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
-
-    //
-    // Iterate over the NULL-separated items in the compatible string
-    //
-    for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
-      CompItem += 1 + AsciiStrLen (CompItem)) {
-
-      if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
-        RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
-        ASSERT (Len == 16);
-
-        UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
-
-        DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
-
-        *HobData = UartBase;
-
-        HaveUART = TRUE;
-        continue;
-      }
+      break;
     }
   }
 
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
index af0d6e87da9f..58bc2b828dcd 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
@@ -21,6 +21,8 @@
 #include <Library/PcdLib.h>
 #include <libfdt.h>
 
+#include <Guid/EarlyPL011BaseAddress.h>
+
 EFI_STATUS
 EFIAPI
 PlatformPeim (
@@ -30,6 +32,14 @@ PlatformPeim (
   VOID               *Base;
   VOID               *NewBase;
   UINTN              FdtSize;
+  UINT64             *UartHobData;
+  INT32              Node, Prev;
+  CONST CHAR8        *Compatible;
+  CONST CHAR8        *CompItem;
+  INT32              Len;
+  CONST UINT64       *RegProp;
+  UINT64             UartBase;
+
 
   Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress);
   ASSERT (fdt_check_header (Base) == 0);
@@ -41,6 +51,44 @@ PlatformPeim (
   CopyMem (NewBase, Base, FdtSize);
   PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)(UINTN)NewBase);
 
+  UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
+  ASSERT (UartHobData != NULL);
+  *UartHobData = 0;
+
+  //
+  // Look for a UART node
+  //
+  for (Prev = 0;; Prev = Node) {
+    Node = fdt_next_node (Base, Prev, NULL);
+    if (Node < 0) {
+      break;
+    }
+
+    //
+    // Check for UART node
+    //
+    Compatible = fdt_getprop (Base, Node, "compatible", &Len);
+
+    //
+    // Iterate over the NULL-separated items in the compatible string
+    //
+    for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
+      CompItem += 1 + AsciiStrLen (CompItem)) {
+
+      if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
+        RegProp = fdt_getprop (Base, Node, "reg", &Len);
+        ASSERT (Len == 16);
+
+        UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+
+        DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
+
+        *UartHobData = UartBase;
+        break;
+      }
+    }
+  }
+
   BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
 
   return EFI_SUCCESS;
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
index e544b528d261..a376fbd1f345 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
@@ -44,5 +44,8 @@
 [Pcd]
   gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress
 
+[Guids]
+  gEarlyPL011BaseAddressGuid
+
 [Depex]
   gEfiPeiMemoryDiscoveredPpiGuid
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 07/29] ArmVirtualizationPkg: use a HOB to store device tree blob
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (5 preceding siblings ...)
  2015-02-12 11:18 ` [PATCH v4 06/29] ArmVirtualizationPkg: move early UART discovery to PlatformPeim Ard Biesheuvel
@ 2015-02-12 11:18 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 08/29] ArmVirtualizationPkg: add padding to FDT allocation Ard Biesheuvel
                   ` (31 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:18 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

Instead of using a dynamic PCD, store the device tree address in a HOB
so that we can also run under a configuration that does not support
dynamic PCDs.

This also adds MemoryAllocationLib to the [LibraryClasses] section of
ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf, as this
dependency was formerly satisfied transitively through one of the
library dependencies that were dropped.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec                                              |  2 --
 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc                                             |  3 ---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf |  3 +--
 ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c                               | 11 ++++++++---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf                             |  4 +---
 ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c                                               | 10 ++++++++--
 ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf                                             |  3 ++-
 EmbeddedPkg/EmbeddedPkg.dec                                                                               |  2 ++
 EmbeddedPkg/Include/Guid/FdtHob.h                                                                         | 26 ++++++++++++++++++++++++++
 9 files changed, 48 insertions(+), 16 deletions(-)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
index d83117fc6abe..868488906643 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
@@ -44,8 +44,6 @@
   gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress|0x0|UINT64|0x00000001
 
 [PcdsDynamic, PcdsFixedAtBuild]
-  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0|UINT64|0x00000002
-
   #
   # ARM PSCI function invocations can be done either through hypervisor
   # calls (HVC) or secure monitor calls (SMC).
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
index 066108f66d28..f3c55b03440e 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
@@ -160,9 +160,6 @@
   # System Memory Size -- 1 MB initially, actual size will be fetched from DT
   gArmTokenSpaceGuid.PcdSystemMemorySize|0x00100000
 
-  # location of the device tree blob passed by QEMU
-  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0
-
   gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0
   gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0
   gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf
index 43b3c6ca1bef..2cff4b62ea0c 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf
@@ -30,11 +30,10 @@
 
 [LibraryClasses]
   IoLib
+  MemoryAllocationLib
   ArmLib
   PrintLib
   FdtLib
-  SerialPortLib
-  HobLib
 
 [Sources.common]
   Virt.c
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
index 58bc2b828dcd..c500d5964b25 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
@@ -22,6 +22,7 @@
 #include <libfdt.h>
 
 #include <Guid/EarlyPL011BaseAddress.h>
+#include <Guid/FdtHob.h>
 
 EFI_STATUS
 EFIAPI
@@ -32,6 +33,7 @@ PlatformPeim (
   VOID               *Base;
   VOID               *NewBase;
   UINTN              FdtSize;
+  UINT64             *FdtHobData;
   UINT64             *UartHobData;
   INT32              Node, Prev;
   CONST CHAR8        *Compatible;
@@ -41,15 +43,18 @@ PlatformPeim (
   UINT64             UartBase;
 
 
-  Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress);
+  Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
+  ASSERT (Base != NULL);
   ASSERT (fdt_check_header (Base) == 0);
 
   FdtSize = fdt_totalsize (Base);
   NewBase = AllocatePages (EFI_SIZE_TO_PAGES (FdtSize));
   ASSERT (NewBase != NULL);
-
   CopyMem (NewBase, Base, FdtSize);
-  PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)(UINTN)NewBase);
+
+  FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
+  ASSERT (FdtHobData != NULL);
+  *FdtHobData = (UINTN)NewBase;
 
   UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
   ASSERT (UartHobData != NULL);
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
index a376fbd1f345..96019e4009ff 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
@@ -41,11 +41,9 @@
   gArmTokenSpaceGuid.PcdFvSize
   gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
 
-[Pcd]
-  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress
-
 [Guids]
   gEarlyPL011BaseAddressGuid
+  gFdtHobGuid
 
 [Depex]
   gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
index a12bd8686fcc..0b6414d59d46 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
@@ -24,10 +24,12 @@
 #include <Library/DevicePathLib.h>
 #include <Library/PcdLib.h>
 #include <Library/DxeServicesLib.h>
+#include <Library/HobLib.h>
 #include <libfdt.h>
 
 #include <Guid/Fdt.h>
 #include <Guid/VirtioMmioTransport.h>
+#include <Guid/FdtHob.h>
 
 #pragma pack (1)
 typedef struct {
@@ -105,6 +107,7 @@ InitializeVirtFdtDxe (
   IN EFI_SYSTEM_TABLE     *SystemTable
   )
 {
+  VOID                           *Hob;
   VOID                           *DeviceTreeBase;
   INT32                          Node, Prev;
   INT32                          RtcNode;
@@ -125,8 +128,11 @@ InitializeVirtFdtDxe (
   UINT64                         FwCfgDataAddress;
   UINT64                         FwCfgDataSize;
 
-  DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeBaseAddress);
-  ASSERT (DeviceTreeBase != NULL);
+  Hob = GetFirstGuidHob(&gFdtHobGuid);
+  if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {
+    return EFI_NOT_FOUND;
+  }
+  DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);
 
   if (fdt_check_header (DeviceTreeBase) != 0) {
     DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, DeviceTreeBase));
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
index 1ed02b6f3750..0774fadda21c 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
@@ -40,13 +40,14 @@
   DxeServicesLib
   FdtLib
   VirtioMmioDeviceLib
+  HobLib
 
 [Guids]
   gFdtTableGuid
   gVirtioMmioTransportGuid
+  gFdtHobGuid
 
 [Pcd]
-  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress
   gArmVirtualizationTokenSpaceGuid.PcdArmPsciMethod
   gArmVirtualizationTokenSpaceGuid.PcdFwCfgSelectorAddress
   gArmVirtualizationTokenSpaceGuid.PcdFwCfgDataAddress
diff --git a/EmbeddedPkg/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec
index 600d0e54c4b3..2f261ece9212 100644
--- a/EmbeddedPkg/EmbeddedPkg.dec
+++ b/EmbeddedPkg/EmbeddedPkg.dec
@@ -52,6 +52,8 @@
   ## FDT Configuration Table
   # Include/Guid/Fdt.h
   gFdtTableGuid = { 0xb1b621d5, 0xf19c, 0x41a5, { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } }
+  # Include/Guid/FdtHob.h
+  gFdtHobGuid   = { 0x16958446, 0x19B7, 0x480B, { 0xB0, 0x47, 0x74, 0x85, 0xAD, 0x3F, 0x71, 0x6D } }
 
 [Protocols.common]
   gHardwareInterruptProtocolGuid =  { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } }
diff --git a/EmbeddedPkg/Include/Guid/FdtHob.h b/EmbeddedPkg/Include/Guid/FdtHob.h
new file mode 100644
index 000000000000..287729e0c350
--- /dev/null
+++ b/EmbeddedPkg/Include/Guid/FdtHob.h
@@ -0,0 +1,26 @@
+/** @file
+  GUID for the HOB that contains the copy of the flattened device tree blob
+
+  Copyright (C) 2014, Linaro Ltd.
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution. The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __FDT_HOB_H__
+#define __FDT_HOB_H__
+
+#define FDT_HOB_GUID { \
+          0x16958446, 0x19B7, 0x480B, \
+          { 0xB0, 0x47, 0x74, 0x85, 0xAD, 0x3F, 0x71, 0x6D } \
+        }
+
+extern EFI_GUID gFdtHobGuid;
+
+#endif
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 08/29] ArmVirtualizationPkg: add padding to FDT allocation
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (6 preceding siblings ...)
  2015-02-12 11:18 ` [PATCH v4 07/29] ArmVirtualizationPkg: use a HOB to store device tree blob Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 09/29] ArmVirtualizationPkg: add a relocatable version of PrePi Ard Biesheuvel
                   ` (30 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

Our primary user QEMU/mach-virt presents us with a FDT blob padded
to 64 KB with plenty of room to set additional properties. However,
in the general case, we should only add properties after making sure
there is enough room available.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec                  | 6 ++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c   | 8 +++++---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf | 1 +
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
index 868488906643..4ebfcddfa595 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
@@ -43,6 +43,12 @@
   #
   gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress|0x0|UINT64|0x00000001
 
+  #
+  # Padding in bytes to add to the device tree allocation, so that the DTB can
+  # be modified in place (default: 256 bytes)
+  #
+  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeAllocationPadding|256|UINT32|0x00000002
+
 [PcdsDynamic, PcdsFixedAtBuild]
   #
   # ARM PSCI function invocations can be done either through hypervisor
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
index c500d5964b25..bdf2b57fcb1e 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c
@@ -33,6 +33,7 @@ PlatformPeim (
   VOID               *Base;
   VOID               *NewBase;
   UINTN              FdtSize;
+  UINTN              FdtPages;
   UINT64             *FdtHobData;
   UINT64             *UartHobData;
   INT32              Node, Prev;
@@ -47,10 +48,11 @@ PlatformPeim (
   ASSERT (Base != NULL);
   ASSERT (fdt_check_header (Base) == 0);
 
-  FdtSize = fdt_totalsize (Base);
-  NewBase = AllocatePages (EFI_SIZE_TO_PAGES (FdtSize));
+  FdtSize = fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreeAllocationPadding);
+  FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
+  NewBase = AllocatePages (FdtPages);
   ASSERT (NewBase != NULL);
-  CopyMem (NewBase, Base, FdtSize);
+  fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
 
   FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
   ASSERT (FdtHobData != NULL);
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
index 96019e4009ff..6675a1f91561 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
@@ -40,6 +40,7 @@
   gArmTokenSpaceGuid.PcdFvBaseAddress
   gArmTokenSpaceGuid.PcdFvSize
   gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeAllocationPadding
 
 [Guids]
   gEarlyPL011BaseAddressGuid
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 09/29] ArmVirtualizationPkg: add a relocatable version of PrePi
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (7 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 08/29] ArmVirtualizationPkg: add padding to FDT allocation Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 10/29] ArmVirtualizationPkg: implement custom MemoryInitPeiLib Ard Biesheuvel
                   ` (29 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This patch introduces a relocatable PrePi, which can execute
from arbitrary offsets in RAM. This is intendend to be run
from a boot loader which passes a description of the actual
platform in a device tree, for instance.

This module is based on the PrePi implementations residing under
ArmPlatformPkg.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ArchPrePi.c                |  33 ++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ModuleEntryPoint.S         | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/LzmaDecompress.h                   | 103 ++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.c                            | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.h                            |  77 ++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/Scripts/PrePi-PIE.lds              |  42 ++++++++++++++++++++
 7 files changed, 746 insertions(+)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ArchPrePi.c b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ArchPrePi.c
new file mode 100644
index 000000000000..217986107e44
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ArchPrePi.c
@@ -0,0 +1,33 @@
+/** @file
+*
+*  Copyright (c) 2011-2013, ARM 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.
+*
+**/
+
+#include "PrePi.h"
+
+#include <Chipset/AArch64.h>
+
+VOID
+ArchInitialize (
+  VOID
+  )
+{
+  // Enable Floating Point
+  if (FixedPcdGet32 (PcdVFPEnabled)) {
+    ArmEnableVFP ();
+  }
+
+  if (ArmReadCurrentEL () == AARCH64_EL2) {
+    // Trap General Exceptions. All exceptions that would be routed to EL1 are routed to EL2
+    ArmWriteHcr (ARM_HCR_TGE);
+  }
+}
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ModuleEntryPoint.S
new file mode 100644
index 000000000000..568d0086d662
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ModuleEntryPoint.S
@@ -0,0 +1,180 @@
+//
+//  Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+//  Copyright (c) 2015, 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.
+//
+//
+
+#include <AsmMacroIoLibV8.h>
+#include <Base.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+
+.text
+.align 3
+
+GCC_ASM_IMPORT(ArmPlatformIsPrimaryCore)
+GCC_ASM_IMPORT(ArmReadMpidr)
+GCC_ASM_IMPORT(ArmPlatformPeiBootAction)
+GCC_ASM_IMPORT(ArmPlatformStackSet)
+GCC_ASM_EXPORT(_ModuleEntryPoint)
+
+StartupAddr:        .8byte ASM_PFX(CEntryPoint)
+
+ASM_PFX(_ModuleEntryPoint):
+  //
+  // We are built as a ET_DYN PIE executable, so we need to process all
+  // relative relocations regardless of whether or not we are executing from
+  // the same offset we were linked at. This is only possible if we are
+  // running from RAM.
+  //
+  adr   x8, __reloc_base
+  adr   x9, __reloc_start
+  adr   x10, __reloc_end
+
+.Lreloc_loop:
+  cmp   x9, x10
+  bhs   .Lreloc_done
+
+  //
+  // AArch64 uses the ELF64 RELA format, which means each entry in the
+  // relocation table consists of
+  //
+  //   UINT64 offset          : the relative offset of the value that needs to
+  //                            be relocated
+  //   UINT64 info            : relocation type and symbol index (the latter is
+  //                            not used for R_AARCH64_RELATIVE relocations)
+  //   UINT64 addend          : value to be added to the value being relocated
+  //
+  ldp   x11, x12, [x9], #24   // read offset into x11 and info into x12
+  cmp   x12, #0x403           // check info == R_AARCH64_RELATIVE?
+  bne   .Lreloc_loop          // not a relative relocation? then skip
+
+  ldr   x12, [x9, #-8]        // read addend into x12
+  add   x12, x12, x8          // add reloc base to addend to get relocated value
+  str   x12, [x11, x8]        // write relocated value at offset
+  b     .Lreloc_loop
+.Lreloc_done:
+
+  // Do early platform specific actions
+  bl    ASM_PFX(ArmPlatformPeiBootAction)
+
+  // Get ID of this CPU in Multicore system
+  bl    ASM_PFX(ArmReadMpidr)
+  // Keep a copy of the MpId register value
+  mov   x10, x0
+
+// Check if we can install the stack at the top of the System Memory or if we need
+// to install the stacks at the bottom of the Firmware Device (case the FD is located
+// at the top of the DRAM)
+_SetupStackPosition:
+  // Compute Top of System Memory
+  ldr   x1, PcdGet64 (PcdSystemMemoryBase)
+  ldr   x2, PcdGet64 (PcdSystemMemorySize)
+  sub   x2, x2, #1
+  add   x1, x1, x2      // x1 = SystemMemoryTop = PcdSystemMemoryBase + PcdSystemMemorySize
+
+  // Calculate Top of the Firmware Device
+  ldr   x2, PcdGet64 (PcdFdBaseAddress)
+  ldr   w3, PcdGet32 (PcdFdSize)
+  sub   x3, x3, #1
+  add   x3, x3, x2      // x3 = FdTop = PcdFdBaseAddress + PcdFdSize
+
+  // UEFI Memory Size (stacks are allocated in this region)
+  LoadConstantToReg (FixedPcdGet32(PcdSystemMemoryUefiRegionSize), x4)
+
+  //
+  // Reserve the memory for the UEFI region (contain stacks on its top)
+  //
+
+  // Calculate how much space there is between the top of the Firmware and the Top of the System Memory
+  subs  x0, x1, x3   // x0 = SystemMemoryTop - FdTop
+  b.mi  _SetupStack  // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM
+  cmp   x0, x4
+  b.ge  _SetupStack
+
+  // Case the top of stacks is the FdBaseAddress
+  mov   x1, x2
+
+_SetupStack:
+  // x1 contains the top of the stack (and the UEFI Memory)
+
+  // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment
+  // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the
+  // top of the memory space)
+  adds  x11, x1, #1
+  b.cs  _SetupOverflowStack
+
+_SetupAlignedStack:
+  mov   x1, x11
+  b     _GetBaseUefiMemory
+
+_SetupOverflowStack:
+  // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE
+  // aligned (4KB)
+  LoadConstantToReg (EFI_PAGE_MASK, x11)
+  and   x11, x11, x1
+  sub   x1, x1, x11
+
+_GetBaseUefiMemory:
+  // Calculate the Base of the UEFI Memory
+  sub   x11, x1, x4
+
+_GetStackBase:
+  // r1 = The top of the Mpcore Stacks
+  // Stack for the primary core = PrimaryCoreStack
+  LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2)
+  sub   x12, x1, x2
+
+  // Stack for the secondary core = Number of Cores - 1
+  LoadConstantToReg (FixedPcdGet32(PcdCoreCount), x0)
+  sub   x0, x0, #1
+  LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x1)
+  mul   x1, x1, x0
+  sub   x12, x12, x1
+
+  // x12 = The base of the MpCore Stacks (primary stack & secondary stacks)
+  mov   x0, x12
+  mov   x1, x10
+  //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize)
+  LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2)
+  LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x3)
+  bl    ASM_PFX(ArmPlatformStackSet)
+
+  // Is it the Primary Core ?
+  mov   x0, x10
+  bl    ASM_PFX(ArmPlatformIsPrimaryCore)
+  cmp   x0, #1
+  bne   _PrepareArguments
+
+_ReserveGlobalVariable:
+  LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), x0)
+  // InitializePrimaryStack($GlobalVariableSize, $Tmp1, $Tmp2)
+  InitializePrimaryStack(x0, x1, x2)
+
+_PrepareArguments:
+  mov   x0, x10
+  mov   x1, x11
+  mov   x2, x12
+  mov   x3, sp
+
+  // Move sec startup address into a data register
+  // Ensure we're jumping to FV version of the code (not boot remapped alias)
+  ldr   x4, StartupAddr
+
+  // Jump to PrePiCore C code
+  //    x0 = MpId
+  //    x1 = UefiMemoryBase
+  //    x2 = StacksBase
+  //    x3 = GlobalVariableBase
+  blr   x4
+
+_NeverReturn:
+  b _NeverReturn
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
new file mode 100755
index 000000000000..86cf870b79ac
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
@@ -0,0 +1,108 @@
+#/** @file
+#
+#  Copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR>
+#  Copyright (c) 2015, 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                    = 0x00010005
+  BASE_NAME                      = ArmVirtPrePiUniCoreRelocatable
+  FILE_GUID                      = f7d9fd14-9335-4389-80c5-334d6abfcced
+  MODULE_TYPE                    = SEC
+  VALID_ARCHITECTURES            = AARCH64
+  VERSION_STRING                 = 1.0
+
+[Sources]
+  PrePi.c
+
+[Sources.AArch64]
+  AArch64/ArchPrePi.c
+  AArch64/ModuleEntryPoint.S
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  ArmLib
+  IoLib
+  TimerLib
+  SerialPortLib
+  ExtractGuidedSectionLib
+  LzmaDecompressLib
+  PeCoffGetEntryPointLib
+  PrePiLib
+  ArmPlatformLib
+  ArmPlatformStackLib
+  MemoryAllocationLib
+  HobLib
+  PrePiHobListPointerLib
+  PlatformPeiLib
+  MemoryInitPeiLib
+
+[Ppis]
+  gArmMpCoreInfoPpiGuid
+
+[Guids]
+  gArmGlobalVariableGuid
+  gArmMpCoreInfoGuid
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+  gArmPlatformTokenSpaceGuid.PcdSendSgiToBringUpSecondaryCores
+
+[FixedPcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
+
+  gArmTokenSpaceGuid.PcdVFPEnabled
+
+  gArmTokenSpaceGuid.PcdFdSize
+  gArmTokenSpaceGuid.PcdFvSize
+
+  gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
+  gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize
+
+  gArmPlatformTokenSpaceGuid.PcdPeiGlobalVariableSize
+
+  gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+  gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
+  gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
+
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+
+[BuildOptions]
+  GCC:*_*_AARCH64_DLINK_FLAGS = -pie -T $(MODULE_DIR)/Scripts/PrePi-PIE.lds
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/LzmaDecompress.h b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/LzmaDecompress.h
new file mode 100644
index 000000000000..a79ff343d231
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/LzmaDecompress.h
@@ -0,0 +1,103 @@
+/** @file
+  LZMA Decompress Library header file
+
+  Copyright (c) 2006 - 2010, Intel Corporation. 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.
+
+**/
+
+#ifndef __LZMA_DECOMPRESS_H___
+#define __LZMA_DECOMPRESS_H___
+
+/**
+  Examines a GUIDed section and returns the size of the decoded buffer and the
+  size of an scratch buffer required to actually decode the data in a GUIDed section.
+
+  Examines a GUIDed section specified by InputSection.
+  If GUID for InputSection does not match the GUID that this handler supports,
+  then RETURN_UNSUPPORTED is returned.
+  If the required information can not be retrieved from InputSection,
+  then RETURN_INVALID_PARAMETER is returned.
+  If the GUID of InputSection does match the GUID that this handler supports,
+  then the size required to hold the decoded buffer is returned in OututBufferSize,
+  the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field
+  from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute.
+
+  If InputSection is NULL, then ASSERT().
+  If OutputBufferSize is NULL, then ASSERT().
+  If ScratchBufferSize is NULL, then ASSERT().
+  If SectionAttribute is NULL, then ASSERT().
+
+
+  @param[in]  InputSection       A pointer to a GUIDed section of an FFS formatted file.
+  @param[out] OutputBufferSize   A pointer to the size, in bytes, of an output buffer required
+                                 if the buffer specified by InputSection were decoded.
+  @param[out] ScratchBufferSize  A pointer to the size, in bytes, required as scratch space
+                                 if the buffer specified by InputSection were decoded.
+  @param[out] SectionAttribute   A pointer to the attributes of the GUIDed section. See the Attributes
+                                 field of EFI_GUID_DEFINED_SECTION in the PI Specification.
+
+  @retval  RETURN_SUCCESS            The information about InputSection was returned.
+  @retval  RETURN_UNSUPPORTED        The section specified by InputSection does not match the GUID this handler supports.
+  @retval  RETURN_INVALID_PARAMETER  The information can not be retrieved from the section specified by InputSection.
+
+**/
+RETURN_STATUS
+EFIAPI
+LzmaGuidedSectionGetInfo (
+  IN  CONST VOID  *InputSection,
+  OUT UINT32      *OutputBufferSize,
+  OUT UINT32      *ScratchBufferSize,
+  OUT UINT16      *SectionAttribute
+  );
+
+/**
+  Decompress a LZAM compressed GUIDed section into a caller allocated output buffer.
+
+  Decodes the GUIDed section specified by InputSection.
+  If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned.
+  If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned.
+  If the GUID of InputSection does match the GUID that this handler supports, then InputSection
+  is decoded into the buffer specified by OutputBuffer and the authentication status of this
+  decode operation is returned in AuthenticationStatus.  If the decoded buffer is identical to the
+  data in InputSection, then OutputBuffer is set to point at the data in InputSection.  Otherwise,
+  the decoded data will be placed in caller allocated buffer specified by OutputBuffer.
+
+  If InputSection is NULL, then ASSERT().
+  If OutputBuffer is NULL, then ASSERT().
+  If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT().
+  If AuthenticationStatus is NULL, then ASSERT().
+
+
+  @param[in]  InputSection  A pointer to a GUIDed section of an FFS formatted file.
+  @param[out] OutputBuffer  A pointer to a buffer that contains the result of a decode operation.
+  @param[out] ScratchBuffer A caller allocated buffer that may be required by this function
+                            as a scratch buffer to perform the decode operation.
+  @param[out] AuthenticationStatus
+                            A pointer to the authentication status of the decoded output buffer.
+                            See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
+                            section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must
+                            never be set by this handler.
+
+  @retval  RETURN_SUCCESS            The buffer specified by InputSection was decoded.
+  @retval  RETURN_UNSUPPORTED        The section specified by InputSection does not match the GUID this handler supports.
+  @retval  RETURN_INVALID_PARAMETER  The section specified by InputSection can not be decoded.
+
+**/
+RETURN_STATUS
+EFIAPI
+LzmaGuidedSectionExtraction (
+  IN CONST  VOID    *InputSection,
+  OUT       VOID    **OutputBuffer,
+  OUT       VOID    *ScratchBuffer,        OPTIONAL
+  OUT       UINT32  *AuthenticationStatus
+  );
+
+#endif // __LZMADECOMPRESS_H__
+
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.c b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.c
new file mode 100755
index 000000000000..0772805890f2
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.c
@@ -0,0 +1,203 @@
+/** @file
+*
+*  Copyright (c) 2011-2014, ARM 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.
+*
+**/
+
+#include <PiPei.h>
+
+#include <Library/PrePiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PrePiHobListPointerLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PerformanceLib.h>
+
+#include <Ppi/GuidedSectionExtraction.h>
+#include <Ppi/ArmMpCoreInfo.h>
+#include <Guid/LzmaDecompress.h>
+#include <Guid/ArmGlobalVariableHob.h>
+
+#include "PrePi.h"
+#include "LzmaDecompress.h"
+
+// Not used when PrePi in run in XIP mode
+UINTN mGlobalVariableBase = 0;
+
+EFI_STATUS
+EFIAPI
+ExtractGuidedSectionLibConstructor (
+  VOID
+  );
+
+EFI_STATUS
+EFIAPI
+LzmaDecompressLibConstructor (
+  VOID
+  );
+
+VOID
+EFIAPI
+BuildGlobalVariableHob (
+  IN EFI_PHYSICAL_ADDRESS         GlobalVariableBase,
+  IN UINT32                       GlobalVariableSize
+  )
+{
+  ARM_HOB_GLOBAL_VARIABLE  *Hob;
+
+  Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, sizeof (ARM_HOB_GLOBAL_VARIABLE));
+  ASSERT(Hob != NULL);
+
+  CopyGuid (&(Hob->Header.Name), &gArmGlobalVariableGuid);
+  Hob->GlobalVariableBase = GlobalVariableBase;
+  Hob->GlobalVariableSize = GlobalVariableSize;
+}
+
+EFI_STATUS
+GetPlatformPpi (
+  IN  EFI_GUID  *PpiGuid,
+  OUT VOID      **Ppi
+  )
+{
+  UINTN                   PpiListSize;
+  UINTN                   PpiListCount;
+  EFI_PEI_PPI_DESCRIPTOR  *PpiList;
+  UINTN                   Index;
+
+  PpiListSize = 0;
+  ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList);
+  PpiListCount = PpiListSize / sizeof(EFI_PEI_PPI_DESCRIPTOR);
+  for (Index = 0; Index < PpiListCount; Index++, PpiList++) {
+    if (CompareGuid (PpiList->Guid, PpiGuid) == TRUE) {
+      *Ppi = PpiList->Ppi;
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+VOID
+PrePiMain (
+  IN  UINTN                     UefiMemoryBase,
+  IN  UINTN                     StacksBase,
+  IN  UINTN                     GlobalVariableBase,
+  IN  UINT64                    StartTimeStamp
+  )
+{
+  EFI_HOB_HANDOFF_INFO_TABLE*   HobList;
+  EFI_STATUS                    Status;
+  CHAR8                         Buffer[100];
+  UINTN                         CharCount;
+  UINTN                         StacksSize;
+
+  // Initialize the architecture specific bits
+  ArchInitialize ();
+
+  // Initialize the Serial Port
+  SerialPortInitialize ();
+  CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"UEFI firmware (version %s built at %a on %a)\n\r",
+    (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
+  SerialPortWrite ((UINT8 *) Buffer, CharCount);
+
+  // Declare the PI/UEFI memory region
+  HobList = HobConstructor (
+    (VOID*)UefiMemoryBase,
+    FixedPcdGet32 (PcdSystemMemoryUefiRegionSize),
+    (VOID*)UefiMemoryBase,
+    (VOID*)StacksBase  // The top of the UEFI Memory is reserved for the stacks
+    );
+  PrePeiSetHobList (HobList);
+
+  // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
+  Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
+  ASSERT_EFI_ERROR (Status);
+
+  // Create the Stacks HOB (reserve the memory for all stacks)
+  StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize);
+  BuildStackHob (StacksBase, StacksSize);
+
+  // Declare the Global Variable HOB
+  BuildGlobalVariableHob (GlobalVariableBase, FixedPcdGet32 (PcdPeiGlobalVariableSize));
+
+  //TODO: Call CpuPei as a library
+  BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
+
+  // Set the Boot Mode
+  SetBootMode (ArmPlatformGetBootMode ());
+
+  // Initialize Platform HOBs (CpuHob and FvHob)
+  Status = PlatformPeim ();
+  ASSERT_EFI_ERROR (Status);
+
+  // Now, the HOB List has been initialized, we can register performance information
+  PERF_START (NULL, "PEI", NULL, StartTimeStamp);
+
+  // SEC phase needs to run library constructors by hand.
+  ExtractGuidedSectionLibConstructor ();
+  LzmaDecompressLibConstructor ();
+
+  // Build HOBs to pass up our version of stuff the DXE Core needs to save space
+  BuildPeCoffLoaderHob ();
+  BuildExtractSectionHob (
+    &gLzmaCustomDecompressGuid,
+    LzmaGuidedSectionGetInfo,
+    LzmaGuidedSectionExtraction
+    );
+
+  // Assume the FV that contains the SEC (our code) also contains a compressed FV.
+  Status = DecompressFirstFv ();
+  ASSERT_EFI_ERROR (Status);
+
+  // Load the DXE Core and transfer control to it
+  Status = LoadDxeCoreFromFv (NULL, 0);
+  ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+CEntryPoint (
+  IN  UINTN                     MpId,
+  IN  UINTN                     UefiMemoryBase,
+  IN  UINTN                     StacksBase,
+  IN  UINTN                     GlobalVariableBase
+  )
+{
+  UINT64   StartTimeStamp;
+
+  // Initialize the platform specific controllers
+  ArmPlatformInitialize (MpId);
+
+  if (PerformanceMeasurementEnabled ()) {
+    // Initialize the Timer Library to setup the Timer HW controller
+    TimerConstructor ();
+    // We cannot call yet the PerformanceLib because the HOB List has not been initialized
+    StartTimeStamp = GetPerformanceCounter ();
+  } else {
+    StartTimeStamp = 0;
+  }
+
+  // Data Cache enabled on Primary core when MMU is enabled.
+  ArmDisableDataCache ();
+  // Invalidate Data cache
+  ArmInvalidateDataCache ();
+  // Invalidate instruction cache
+  ArmInvalidateInstructionCache ();
+  // Enable Instruction Caches on all cores.
+  ArmEnableInstructionCache ();
+
+  // Define the Global Variable region
+  mGlobalVariableBase = GlobalVariableBase;
+
+  PrePiMain (UefiMemoryBase, StacksBase, GlobalVariableBase, StartTimeStamp);
+
+  // DXE Core should always load and never return
+  ASSERT (FALSE);
+}
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.h b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.h
new file mode 100644
index 000000000000..517429fab9a4
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.h
@@ -0,0 +1,77 @@
+/** @file
+*
+*  Copyright (c) 2011-2012, ARM 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.
+*
+**/
+
+#ifndef _PREPI_H_
+#define _PREPI_H_
+
+#include <PiPei.h>
+
+#include <Library/PcdLib.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HobLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/ArmPlatformLib.h>
+
+#define SerialPrint(txt)  SerialPortWrite (txt, AsciiStrLen(txt)+1);
+
+RETURN_STATUS
+EFIAPI
+TimerConstructor (
+  VOID
+  );
+
+VOID
+PrePiMain (
+  IN  UINTN                     UefiMemoryBase,
+  IN  UINTN                     StacksBase,
+  IN  UINTN                     GlobalVariableBase,
+  IN  UINT64                    StartTimeStamp
+  );
+
+EFI_STATUS
+EFIAPI
+MemoryPeim (
+  IN EFI_PHYSICAL_ADDRESS       UefiMemoryBase,
+  IN UINT64                     UefiMemorySize
+  );
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+  VOID
+  );
+
+// Either implemented by PrePiLib or by MemoryInitPei
+VOID
+BuildMemoryTypeInformationHob (
+  VOID
+  );
+
+EFI_STATUS
+GetPlatformPpi (
+  IN  EFI_GUID  *PpiGuid,
+  OUT VOID      **Ppi
+  );
+
+// Initialize the Architecture specific controllers
+VOID
+ArchInitialize (
+  VOID
+  );
+
+#endif /* _PREPI_H_ */
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/Scripts/PrePi-PIE.lds b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/Scripts/PrePi-PIE.lds
new file mode 100644
index 000000000000..32af0696aa6b
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/PrePi/Scripts/PrePi-PIE.lds
@@ -0,0 +1,42 @@
+#/** @file
+#
+#  Copyright (c) 2015, 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.
+#
+#**/
+
+SECTIONS
+{
+  .text 0x0 : {
+    PROVIDE(__reloc_base = .);
+
+    *(.text .text*)
+    *(.got .got*)
+    *(.rodata .rodata*)
+    *(.data .data*)
+
+    . = ALIGN(0x20);
+    PROVIDE(__reloc_start = .);
+    *(.rela .rela*)
+    PROVIDE(__reloc_end = .);
+  }
+  .bss ALIGN(0x20) : { *(.bss .bss*) }
+
+  /DISCARD/ : {
+    *(.note.GNU-stack)
+    *(.gnu_debuglink)
+    *(.interp)
+    *(.dynamic)
+    *(.dynsym)
+    *(.dynstr)
+    *(.hash)
+    *(.comment)
+  }
+}
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 10/29] ArmVirtualizationPkg: implement custom MemoryInitPeiLib
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (8 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 09/29] ArmVirtualizationPkg: add a relocatable version of PrePi Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 11/29] ArmVirtualizationPkg: allow patchable PCD for FV and DT base addresses Ard Biesheuvel
                   ` (28 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This implements a MemoryInitPeiLib instance that differs from the
stock ArmPlatformPkg version only in the fact that it does not remove
the memory used by the flash device (FD). The reason is that, when using
PrePi, the DXE core is started immediately and never returns so there is
no reason to preserve any of the memory that the flash device occupied
originally, and it is preferable to release is so that the OS loader
can reuse it. This is especially important for the relocatable PrePi
configuration, which is aimed at being launched from a boot loader that
itself adheres to the Linux arm64 boot protocol.

Contributed-under: TianoCore Contribution Agreement 1.0
Acked-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-By: Olivier Martin <olivier.martn@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 .../ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf          | 66 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 157 insertions(+)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c
new file mode 100644
index 000000000000..5f6cd059c47f
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c
@@ -0,0 +1,91 @@
+/** @file
+*
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*  Copyright (c) 2014, 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.
+*
+**/
+
+#include <PiPei.h>
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+VOID
+BuildMemoryTypeInformationHob (
+  VOID
+  );
+
+VOID
+InitMmu (
+  VOID
+  )
+{
+  ARM_MEMORY_REGION_DESCRIPTOR  *MemoryTable;
+  VOID                          *TranslationTableBase;
+  UINTN                         TranslationTableSize;
+  RETURN_STATUS                 Status;
+
+  // Get Virtual Memory Map from the Platform Library
+  ArmPlatformGetVirtualMemoryMap (&MemoryTable);
+
+  //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in
+  //      DRAM (even at the top of DRAM as it is the first permanent memory allocation)
+  Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Error: Failed to enable MMU\n"));
+  }
+}
+
+EFI_STATUS
+EFIAPI
+MemoryPeim (
+  IN EFI_PHYSICAL_ADDRESS               UefiMemoryBase,
+  IN UINT64                             UefiMemorySize
+  )
+{
+  EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
+
+  // Ensure PcdSystemMemorySize has been set
+  ASSERT (PcdGet64 (PcdSystemMemorySize) != 0);
+
+  //
+  // Now, the permanent memory has been installed, we can call AllocatePages()
+  //
+  ResourceAttributes = (
+      EFI_RESOURCE_ATTRIBUTE_PRESENT |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_TESTED
+  );
+
+  BuildResourceDescriptorHob (
+      EFI_RESOURCE_SYSTEM_MEMORY,
+      ResourceAttributes,
+      PcdGet64 (PcdSystemMemoryBase),
+      PcdGet64 (PcdSystemMemorySize)
+  );
+
+  // Build Memory Allocation Hob
+  InitMmu ();
+
+  if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
+    // Optional feature that helps prevent EFI memory map fragmentation.
+    BuildMemoryTypeInformationHob ();
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf
new file mode 100644
index 000000000000..fcdae06de7c2
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf
@@ -0,0 +1,66 @@
+#/** @file
+#
+#  Copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR>
+#  Copyright (c) 2014, 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                    = 0x00010005
+  BASE_NAME                      = ArmVirtMemoryInitPeiLib
+  FILE_GUID                      = 021b6156-3cc8-4e99-85ee-13d8a871edf2
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = MemoryInitPeiLib
+
+[Sources]
+  ArmVirtualizationMemoryInitPeiLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  HobLib
+  ArmLib
+  ArmPlatformLib
+
+[Guids]
+  gEfiMemoryTypeInformationGuid
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdFdSize
+
+  gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+
+[Depex]
+  TRUE
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 11/29] ArmVirtualizationPkg: allow patchable PCD for FV and DT base addresses
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (9 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 10/29] ArmVirtualizationPkg: implement custom MemoryInitPeiLib Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 12/29] ArmVirtualizationPkg: Xen/PV relocatable platformlib instance Ard Biesheuvel
                   ` (27 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

Allow the use of patchable PCDs for gArmTokenSpaceGuid.PcdFvBaseAddress
and gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
by moving them from the [FixedPcd] to the [Pcd] section in the INF file of
PlatformPeiLib.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
index 6675a1f91561..4fe0cbae3812 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
@@ -37,11 +37,13 @@
   FdtLib
 
 [FixedPcd]
-  gArmTokenSpaceGuid.PcdFvBaseAddress
   gArmTokenSpaceGuid.PcdFvSize
-  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
   gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeAllocationPadding
 
+[Pcd]
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+
 [Guids]
   gEarlyPL011BaseAddressGuid
   gFdtHobGuid
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 12/29] ArmVirtualizationPkg: Xen/PV relocatable platformlib instance
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (10 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 11/29] ArmVirtualizationPkg: allow patchable PCD for FV and DT base addresses Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 13/29] MdePkg/BaseSynchronizationLib: Added proper support for ARM architecture Ard Biesheuvel
                   ` (26 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

Add a ArmPlatformLib instance that can deal with the self relocation
and truly dynamic discovery of system RAM base and size.

Contributed-under: TianoCore Contribution Agreement 1.0
Acked-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S          | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S  | 167 ++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf |  59 +++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c                |  71 ++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c                     |  83 +++++++++++++++++++++++
 5 files changed, 617 insertions(+)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
new file mode 100644
index 000000000000..f919b63710f0
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+ * Theory of operation
+ * -------------------
+ *
+ * This code parses a Flattened Device Tree binary (DTB) to find the base of
+ * system RAM. It is written in assembly so that it can be executed before a
+ * stack has been set up.
+ *
+ * To find the base of system RAM, we have to traverse the FDT to find a memory
+ * node. In the context of this implementation, the first node that has a
+ * device_type property with the value 'memory' and a 'reg' property is
+ * acceptable, and the name of the node (memory[@xxx]) is ignored, as are any
+ * other nodes that match the above constraints.
+ *
+ * In pseudo code, this implementation does the following:
+ *
+ * for each node {
+ *	have_device_type = false
+ *	have_reg = false
+ *
+ *	for each property {
+ *		if property value == 'memory' {
+ *			if property name == 'device_type' {
+ *				have_device_type = true
+ *			}
+ *		} else {
+ *			if property name == 'reg' {
+ *				have_reg = true
+ *				membase = property value[0]
+ *				memsize = property value[1]
+ *			}
+ *		}
+ *	}
+ *	if have_device_type and have_reg {
+ *		return membase and memsize
+ *	}
+ * }
+ * return NOT_FOUND
+ */
+
+#define FDT_MAGIC		0xedfe0dd0
+
+#define FDT_BEGIN_NODE		0x1
+#define FDT_END_NODE		0x2
+#define FDT_PROP		0x3
+#define FDT_END			0x9
+
+	xMEMSIZE	.req	x0	// recorded system RAM size
+	xMEMBASE	.req	x1	// recorded system RAM base
+
+	xLR		.req	x8	// our preserved link register
+	xDTP		.req	x9	// pointer to traverse the DT structure
+	xSTRTAB		.req	x10	// pointer to the DTB string table
+	xMEMNODE	.req	x11	// bit field to record found properties
+
+#define HAVE_REG		0x1
+#define HAVE_DEVICE_TYPE	0x2
+
+	.text
+	.align	3
+_memory:
+	.asciz	"memory"
+_reg:
+	.asciz	"reg"
+_device_type:
+	.asciz	"device_type"
+
+	/*
+	 * Compare strings in x4 and x5, return in w7
+	 */
+	.align	3
+strcmp:
+	ldrb	w2, [x4], #1
+	ldrb	w3, [x5], #1
+	subs	w7, w2, w3
+	cbz	w2, 0f
+	cbz	w3, 0f
+	beq	strcmp
+0:	ret
+
+	.globl	find_memnode
+find_memnode:
+	// preserve link register
+	mov	xLR, x30
+	mov	xDTP, x0
+
+	/*
+	 * Check the DTB magic at offset 0
+	 */
+	movz	w4, #:abs_g0_nc:FDT_MAGIC
+	movk	w4, #:abs_g1:FDT_MAGIC
+	ldr	w5, [xDTP]
+	cmp	w4, w5
+	bne	err_invalid_magic
+
+	/*
+	 * Read the string offset and store it for later use
+	 */
+	ldr	w4, [xDTP, #12]
+	rev	w4, w4
+	add	xSTRTAB, xDTP, x4
+
+	/*
+	 * Read the struct offset and add it to the DT pointer
+	 */
+	ldr	w5, [xDTP, #8]
+	rev	w5, w5
+	add	xDTP, xDTP, x5
+
+	/*
+	 * Check current tag for FDT_BEGIN_NODE
+	 */
+	ldr	w5, [xDTP]
+	rev	w5, w5
+	cmp	w5, #FDT_BEGIN_NODE
+	bne	err_unexpected_begin_tag
+
+begin_node:
+	mov	xMEMNODE, #0
+	add	xDTP, xDTP, #4
+
+	/*
+	 * Advance xDTP past NULL terminated string
+	 */
+0:	ldrb	w4, [xDTP], #1
+	cbnz	w4, 0b
+
+next_tag:
+	/*
+	 * Align the DT pointer xDTP to the next 32-bit boundary
+	 */
+	add	xDTP, xDTP, #3
+	and	xDTP, xDTP, #~3
+
+	/*
+	 * Read the next tag, could be BEGIN_NODE, END_NODE, PROP, END
+	 */
+	ldr	w5, [xDTP]
+	rev	w5, w5
+	cmp	w5, #FDT_BEGIN_NODE
+	beq	begin_node
+	cmp	w5, #FDT_END_NODE
+	beq	end_node
+	cmp	w5, #FDT_PROP
+	beq	prop_node
+	cmp	w5, #FDT_END
+	beq	err_end_of_fdt
+	b	err_unexpected_tag
+
+prop_node:
+	/*
+	 * If propname == 'reg', record as membase and memsize
+	 * If propname == 'device_type' and value == 'memory',
+	 * set the 'is_memnode' flag for this node
+	 */
+	ldr	w6, [xDTP, #4]
+	add	xDTP, xDTP, #12
+	rev	w6, w6
+	mov	x5, xDTP
+	adr	x4, _memory
+	bl	strcmp
+
+	/*
+	 * Get handle to property name
+	 */
+	ldr	w5, [xDTP, #-4]
+	rev	w5, w5
+	add	x5, xSTRTAB, x5
+
+	cbz	w7, check_device_type
+
+	/*
+	 * Check for 'reg' property
+	 */
+	adr	x4, _reg
+	bl	strcmp
+	cbnz	w7, inc_and_next_tag
+
+	/*
+	 * Extract two 64-bit quantities from the 'reg' property. These values
+	 * will only be used if the node also turns out to have a device_type
+	 * property with a value of 'memory'.
+	 *
+	 * NOTE: xDTP is only guaranteed to be 32 bit aligned, and we are most
+	 *       likely executing with the MMU off, so we cannot use 64 bit
+	 *       wide accesses here.
+	 */
+	ldp	w4, w5, [xDTP]
+	orr	xMEMBASE, x4, x5, lsl #32
+	ldp	w4, w5, [xDTP, #8]
+	orr	xMEMSIZE, x4, x5, lsl #32
+	rev	xMEMBASE, xMEMBASE
+	rev	xMEMSIZE, xMEMSIZE
+	orr	xMEMNODE, xMEMNODE, #HAVE_REG
+	b	inc_and_next_tag
+
+check_device_type:
+	/*
+	 * Check whether the current property's name is 'device_type'
+	 */
+	adr	x4, _device_type
+	bl	strcmp
+	cbnz	w7, inc_and_next_tag
+	orr	xMEMNODE, xMEMNODE, #HAVE_DEVICE_TYPE
+
+inc_and_next_tag:
+	add	xDTP, xDTP, x6
+	b	next_tag
+
+end_node:
+	/*
+	 * Check for device_type = memory and reg = xxxx
+	 * If we have both, we are done
+	 */
+	add	xDTP, xDTP, #4
+	cmp	xMEMNODE, #(HAVE_REG | HAVE_DEVICE_TYPE)
+	bne	next_tag
+
+	ret	xLR
+
+err_invalid_magic:
+err_unexpected_begin_tag:
+err_unexpected_tag:
+err_end_of_fdt:
+	wfi
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S
new file mode 100644
index 000000000000..d6edc62efc0d
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S
@@ -0,0 +1,167 @@
+#
+#  Copyright (c) 2011-2013, ARM 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.
+#
+#
+
+#include <AsmMacroIoLibV8.h>
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+
+.text
+.align 2
+
+GCC_ASM_EXPORT(ArmPlatformPeiBootAction)
+GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore)
+GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId)
+GCC_ASM_EXPORT(ArmPlatformGetCorePosition)
+GCC_ASM_EXPORT(ArmGetPhysAddrTop)
+
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCore)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCoreMask)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdCoreCount)
+
+.LFdtMagic:
+  .byte   0xd0, 0x0d, 0xfe, 0xed
+
+.LArm64LinuxMagic:
+  .byte   0x41, 0x52, 0x4d, 0x64
+
+// VOID
+// ArmPlatformPeiBootAction (
+//   VOID   *DeviceTreeBaseAddress,   // passed by loader in x0
+//   VOID   *ImageBase                // passed by FDF trampoline in x1
+//   );
+ASM_PFX(ArmPlatformPeiBootAction):
+  mov   x29, x30            // preserve LR
+
+  //
+  // If we are booting from RAM using the Linux kernel boot protocol, x0 will
+  // point to the DTB image in memory. Otherwise, we are just coming out of
+  // reset, and x0 will be 0. Check also the FDT magic.
+  //
+  cbz   x0, .Lout
+  ldr   w8, .LFdtMagic
+  ldr   w9, [x0]
+  cmp   w8, w9
+  bne   .Lout
+
+  //
+  // The base of the runtime image has been preserved in x1. Check whether
+  // the expected magic number can be found in the header.
+  //
+  ldr   w8, .LArm64LinuxMagic
+  ldr   w9, [x1, #0x38]
+  cmp   w8, w9
+  bne   .Lout
+
+  //
+  //
+  // OK, so far so good. We have confirmed that we likely have a DTB and are
+  // booting via the arm64 Linux boot protocol. Update the base-of-image PCD
+  // to the actual relocated value, and add the shift of PcdFdBaseAddress to
+  // PcdFvBaseAddress as well
+  //
+  adr   x8, PcdGet64 (PcdFdBaseAddress)
+  adr   x9, PcdGet64 (PcdFvBaseAddress)
+  ldr   x6, [x8]
+  ldr   x7, [x9]
+  sub   x7, x7, x6
+  add   x7, x7, x1
+  str   x1, [x8]
+  str   x7, [x9]
+
+  //
+  // Copy the DTB to the slack space right after the 64 byte arm64/Linux style
+  // image header at the base of this image (defined in the FDF), and record the
+  // pointer in PcdDeviceTreeInitialBaseAddress.
+  //
+  adr   x8, PcdGet64 (PcdDeviceTreeInitialBaseAddress)
+  add   x1, x1, #0x40
+  str   x1, [x8]
+
+  ldr   w8, [x0, #4]          // get DTB size (BE)
+  mov   x9, x1
+  rev   w8, w8
+  add   x8, x8, x0
+0:ldp   x6, x7, [x0], #16
+  stp   x6, x7, [x9], #16
+  cmp   x0, x8
+  blt   0b
+
+  //
+  // Discover the memory size and offset from the DTB, and record in the
+  // respective PCDs
+  //
+  mov   x0, x1
+  bl    find_memnode    // returns (size, base) size in (x0, x1)
+  cbz   x0, .Lout
+
+  adr   x8, PcdGet64 (PcdSystemMemorySize)
+  adr   x9, PcdGet64 (PcdSystemMemoryBase)
+  str   x0, [x8]
+  str   x1, [x9]
+
+.Lout:
+  ret    x29
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_PFX(ArmPlatformGetPrimaryCoreMpId):
+  LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, x0)
+  ldrh   w0, [x0]
+  ret
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ASM_PFX(ArmPlatformIsPrimaryCore):
+  mov   x0, #1
+  ret
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+// With this function: CorePos = (ClusterId * 4) + CoreId
+ASM_PFX(ArmPlatformGetCorePosition):
+  and   x1, x0, #ARM_CORE_MASK
+  and   x0, x0, #ARM_CLUSTER_MASK
+  add   x0, x1, x0, LSR #6
+  ret
+
+//EFI_PHYSICAL_ADDRESS
+//GetPhysAddrTop (
+//  VOID
+//  );
+ASM_PFX(ArmGetPhysAddrTop):
+  mrs   x0, id_aa64mmfr0_el1
+  adr   x1, .LPARanges
+  and   x0, x0, #7
+  ldrb  w1, [x1, x0]
+  mov   x0, #1
+  lsl   x0, x0, x1
+  ret
+
+//
+// Bits 0..2 of the AA64MFR0_EL1 system register encode the size of the
+// physical address space support on this CPU:
+// 0 == 32 bits, 1 == 36 bits, etc etc
+// 6 and 7 are reserved
+//
+.LPARanges:
+  .byte 32, 36, 40, 42, 44, 48, -1, -1
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
new file mode 100644
index 000000000000..17bb0f9292e2
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
@@ -0,0 +1,59 @@
+#/* @file
+#  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+#  Copyright (c) 2014, 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.
+#
+#*/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ArmXenRelocatablePlatformLib
+  FILE_GUID                      = c8602718-4faa-4119-90ca-cae72509ac4c
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmPlatformLib|SEC PEIM
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
+
+[LibraryClasses]
+  IoLib
+  ArmLib
+  PrintLib
+
+[Sources.common]
+  RelocatableVirt.c
+  XenVirtMem.c
+
+[Sources.AARCH64]
+  AARCH64/RelocatableVirtHelper.S
+  AARCH64/MemnodeParser.S
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdCacheEnable
+  gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
+
+[PatchPcd]
+  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[FixedPcd]
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+  gArmTokenSpaceGuid.PcdArmPrimaryCore
+  gArmTokenSpaceGuid.PcdFdSize
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c
new file mode 100644
index 000000000000..c10c09fed2bd
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c
@@ -0,0 +1,71 @@
+/** @file
+*
+*  Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+*  Copyright (c) 2014, Linaro Limited. All rights reserved.
+*  Copyright (c) 2014, Red Hat, Inc.
+*
+*
+*  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 <Library/IoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <ArmPlatform.h>
+#include <Pi/PiBootMode.h>
+
+/**
+  Return the current Boot Mode
+
+  This function returns the boot reason on the platform
+
+  @return   Return the current Boot Mode of the platform
+
+**/
+EFI_BOOT_MODE
+ArmPlatformGetBootMode (
+  VOID
+  )
+{
+  return BOOT_WITH_FULL_CONFIGURATION;
+}
+
+/**
+  This function is called by PrePeiCore, in the SEC phase.
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+  IN  UINTN                     MpId
+  )
+{
+  //
+  // We are relying on ArmPlatformInitializeSystemMemory () being called from
+  // InitializeMemory (), which only occurs if the following feature is disabled
+  //
+  ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
+  return RETURN_SUCCESS;
+}
+
+VOID
+ArmPlatformInitializeSystemMemory (
+  VOID
+  )
+{
+}
+
+VOID
+ArmPlatformGetPlatformPpiList (
+  OUT UINTN                   *PpiListSize,
+  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
+  )
+{
+  *PpiListSize = 0;
+  *PpiList = NULL;
+}
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c
new file mode 100644
index 000000000000..657b840059c2
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c
@@ -0,0 +1,83 @@
+/** @file
+*
+*  Copyright (c) 2014, 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.
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <ArmPlatform.h>
+
+// Number of Virtual Memory Map Descriptors
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS          2
+
+// DDR attributes
+#define DDR_ATTRIBUTES_CACHED    ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
+#define DDR_ATTRIBUTES_UNCACHED  ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
+
+EFI_PHYSICAL_ADDRESS
+ArmGetPhysAddrTop (
+  VOID
+  );
+
+/**
+  Return the Virtual Memory Map of your platform
+
+  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
+  on your platform.
+
+  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR
+                                    describing a Physical-to-Virtual Memory
+                                    mapping. This array must be ended by a
+                                    zero-filled entry
+
+**/
+VOID
+ArmPlatformGetVirtualMemoryMap (
+  IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
+  )
+{
+  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  VirtualMemoryTable = AllocatePages (
+                         EFI_SIZE_TO_PAGES (
+                           sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
+                           * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
+                           )
+                         );
+
+  if (VirtualMemoryTable == NULL) {
+    DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));
+    return;
+  }
+
+  //
+  // Map the entire physical memory space as cached. The only device
+  // we care about is the GIC, which will be stage 2 mapped as a device
+  // by the hypervisor, which will override the cached mapping we install
+  // here.
+  //
+  VirtualMemoryTable[0].PhysicalBase = 0x0;
+  VirtualMemoryTable[0].VirtualBase  = 0x0;
+  VirtualMemoryTable[0].Length       = ArmGetPhysAddrTop ();
+  VirtualMemoryTable[0].Attributes   = DDR_ATTRIBUTES_CACHED;
+
+  // End of Table
+  ZeroMem (&VirtualMemoryTable[1], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
+
+  *VirtualMemoryMap = VirtualMemoryTable;
+}
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 13/29] MdePkg/BaseSynchronizationLib: Added proper support for ARM architecture
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (11 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 12/29] ArmVirtualizationPkg: Xen/PV relocatable platformlib instance Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange Ard Biesheuvel
                   ` (25 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This implements the following synchronization primitives for AArch64 (GCC)
and ARM (GCC & RVCT):

InternalSyncCompareExchange32
InternalSyncCompareExchange64
InternalSyncIncrement
InternalSyncDecrement

Note: these functions are implemented using the exclusive monitor,
which implies that they can only be used after the caches (and hence
the MMU) have been enabled.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S  | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c  | 115 -------------------------------------------------------------------------
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S      | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm    | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c      | 115 -------------------------------------------------------------------------
 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf |   5 ++--
 6 files changed, 497 insertions(+), 232 deletions(-)

diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
new file mode 100644
index 000000000000..601b00495f26
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
@@ -0,0 +1,159 @@
+//  Implementation of synchronization functions for ARM architecture (AArch64)
+//
+//  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
+//  Copyright (c) 2015, 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(InternalSyncCompareExchange32)
+GCC_ASM_EXPORT(InternalSyncCompareExchange64)
+GCC_ASM_EXPORT(InternalSyncIncrement)
+GCC_ASM_EXPORT(InternalSyncDecrement)
+
+/**
+  Performs an atomic compare exchange operation on a 32-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 32-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 32-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  32-bit value used in compare operation.
+  @param  ExchangeValue 32-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncCompareExchange32 (
+//  IN      volatile UINT32           *Value,
+//  IN      UINT32                    CompareValue,
+//  IN      UINT32                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange32):
+  dmb     sy
+
+InternalSyncCompareExchange32Again:
+  ldxr    w3, [x0]
+  cmp     w3, w1
+  bne     InternalSyncCompareExchange32Fail
+
+InternalSyncCompareExchange32Exchange:
+  stxr    w4, w2, [x0]
+  cbnz    w4, InternalSyncCompareExchange32Again
+
+InternalSyncCompareExchange32Fail:
+  dmb     sy
+  mov     w0, w3
+  ret
+
+/**
+  Performs an atomic compare exchange operation on a 64-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
+  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
+  The compare exchange operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 64-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  64-bit value used in compare operation.
+  @param  ExchangeValue 64-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT64
+//EFIAPI
+//InternalSyncCompareExchange64 (
+//  IN      volatile UINT64           *Value,
+//  IN      UINT64                    CompareValue,
+//  IN      UINT64                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange64):
+  dmb     sy
+
+InternalSyncCompareExchange64Again:
+  ldxr    x3, [x0]
+  cmp     x3, x1
+  bne     InternalSyncCompareExchange64Fail
+
+InternalSyncCompareExchange64Exchange:
+  stxr    w4, x2, [x0]
+  cbnz    w4, InternalSyncCompareExchange64Again
+
+InternalSyncCompareExchange64Fail:
+  dmb     sy
+  mov     x0, x3
+  ret
+
+/**
+  Performs an atomic increment of an 32-bit unsigned integer.
+
+  Performs an atomic increment of the 32-bit unsigned integer specified by
+  Value and returns the incremented value. The increment operation must be
+  performed using MP safe mechanisms. The state of the return value is not
+  guaranteed to be MP safe.
+
+  @param  Value A pointer to the 32-bit value to increment.
+
+  @return The incremented value.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncIncrement (
+//  IN      volatile UINT32           *Value
+//  )
+ASM_PFX(InternalSyncIncrement):
+  dmb     sy
+TryInternalSyncIncrement:
+  ldxr    w1, [x0]
+  add     w1, w1, #1
+  stxr    w2, w1, [x0]
+  cbnz    w2, TryInternalSyncIncrement
+  dmb     sy
+  ret
+
+/**
+  Performs an atomic decrement of an 32-bit unsigned integer.
+
+  Performs an atomic decrement of the 32-bit unsigned integer specified by
+  Value and returns the decrement value. The decrement operation must be
+  performed using MP safe mechanisms. The state of the return value is not
+  guaranteed to be MP safe.
+
+  @param  Value A pointer to the 32-bit value to decrement.
+
+  @return The decrement value.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncDecrement (
+//  IN      volatile UINT32           *Value
+//  )
+ASM_PFX(InternalSyncDecrement):
+  dmb     sy
+TryInternalSyncDecrement:
+  ldxr    w1, [x0]
+  sub     w1, w1, #1
+  stxr    w2, w1, [x0]
+  cbnz    w2, TryInternalSyncDecrement
+  dmb     sy
+  ret
diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c
deleted file mode 100644
index 2e619ccf873f..000000000000
--- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/** @file
-  Implementation of synchronization functions. Still needs to be ported
-
-  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
-  Portions copyright (c) 2008 - 2009, Apple Inc. 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.
-
-**/
-
-/**
-  Performs an atomic compare exchange operation on a 32-bit unsigned integer.
-
-  Performs an atomic compare exchange operation on the 32-bit unsigned integer
-  specified by Value.  If Value is equal to CompareValue, then Value is set to
-  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
-  then Value is returned.  The compare exchange operation must be performed using
-  MP safe mechanisms.
-
-  @param  Value         A pointer to the 32-bit value for the compare exchange
-                        operation.
-  @param  CompareValue  32-bit value used in compare operation.
-  @param  ExchangeValue 32-bit value used in exchange operation.
-
-  @return The original *Value before exchange.
-
-**/
-UINT32
-EFIAPI
-InternalSyncCompareExchange32 (
-  IN      volatile UINT32           *Value,
-  IN      UINT32                    CompareValue,
-  IN      UINT32                    ExchangeValue
-  )
-{
-  return *Value != CompareValue ? *Value :
-           ((*Value = ExchangeValue), CompareValue);
-}
-
-/**
-  Performs an atomic compare exchange operation on a 64-bit unsigned integer.
-
-  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
-  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
-  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
-  The compare exchange operation must be performed using MP safe mechanisms.
-
-  @param  Value         A pointer to the 64-bit value for the compare exchange
-                        operation.
-  @param  CompareValue  64-bit value used in compare operation.
-  @param  ExchangeValue 64-bit value used in exchange operation.
-
-  @return The original *Value before exchange.
-
-**/
-UINT64
-EFIAPI
-InternalSyncCompareExchange64 (
-  IN      volatile UINT64           *Value,
-  IN      UINT64                    CompareValue,
-  IN      UINT64                    ExchangeValue
-  )
-{
-  return *Value != CompareValue ? *Value :
-           ((*Value = ExchangeValue), CompareValue);
-}
-
-/**
-  Performs an atomic increment of an 32-bit unsigned integer.
-
-  Performs an atomic increment of the 32-bit unsigned integer specified by
-  Value and returns the incremented value. The increment operation must be
-  performed using MP safe mechanisms. The state of the return value is not
-  guaranteed to be MP safe.
-
-  @param  Value A pointer to the 32-bit value to increment.
-
-  @return The incremented value.
-
-**/
-UINT32
-EFIAPI
-InternalSyncIncrement (
-  IN      volatile UINT32           *Value
-  )
-{
-  return ++*Value;
-}
-
-/**
-  Performs an atomic decrement of an 32-bit unsigned integer.
-
-  Performs an atomic decrement of the 32-bit unsigned integer specified by
-  Value and returns the decrement value. The decrement operation must be
-  performed using MP safe mechanisms. The state of the return value is not
-  guaranteed to be MP safe.
-
-  @param  Value A pointer to the 32-bit value to decrement.
-
-  @return The decrement value.
-
-**/
-UINT32
-EFIAPI
-InternalSyncDecrement (
-  IN      volatile UINT32           *Value
-  )
-{
-  return --*Value;
-}
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
new file mode 100644
index 000000000000..0128f8f016bd
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
@@ -0,0 +1,167 @@
+//  Implementation of synchronization functions for ARM architecture
+//
+//  Copyright (c) 2012-2015, ARM 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(InternalSyncCompareExchange32)
+GCC_ASM_EXPORT(InternalSyncCompareExchange64)
+GCC_ASM_EXPORT(InternalSyncIncrement)
+GCC_ASM_EXPORT(InternalSyncDecrement)
+
+/**
+  Performs an atomic compare exchange operation on a 32-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 32-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 32-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  32-bit value used in compare operation.
+  @param  ExchangeValue 32-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncCompareExchange32 (
+//  IN      volatile UINT32           *Value,
+//  IN      UINT32                    CompareValue,
+//  IN      UINT32                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange32):
+  dmb
+
+InternalSyncCompareExchange32Again:
+  ldrex   r3, [r0]
+  cmp     r3, r1
+  bne     InternalSyncCompareExchange32Fail
+
+InternalSyncCompareExchange32Exchange:
+  strex   ip, r2, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange32Again
+
+InternalSyncCompareExchange32Fail:
+  dmb
+  mov     r0, r3
+  bx      lr
+
+/**
+  Performs an atomic compare exchange operation on a 64-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
+  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
+  The compare exchange operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 64-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  64-bit value used in compare operation.
+  @param  ExchangeValue 64-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT64
+//EFIAPI
+//InternalSyncCompareExchange64 (
+//  IN      volatile UINT64           *Value,         // r0
+//  IN      UINT64                    CompareValue,   // r2-r3
+//  IN      UINT64                    ExchangeValue   // stack
+//  )
+ASM_PFX(InternalSyncCompareExchange64):
+  push    { r4-r7 }
+  ldrd    r4, r5, [sp, #16]
+  dmb
+
+InternalSyncCompareExchange64Again:
+  ldrexd  r6, r7, [r0]
+  cmp     r6, r2
+  cmpeq   r7, r3
+  bne     InternalSyncCompareExchange64Fail
+
+InternalSyncCompareExchange64Exchange:
+  strexd  ip, r4, r5, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange64Again
+
+InternalSyncCompareExchange64Fail:
+  dmb
+  mov     r0, r6
+  mov     r1, r7
+  pop     { r4-r7 }
+  bx      lr
+
+/**
+  Performs an atomic increment of an 32-bit unsigned integer.
+
+  Performs an atomic increment of the 32-bit unsigned integer specified by
+  Value and returns the incremented value. The increment operation must be
+  performed using MP safe mechanisms. The state of the return value is not
+  guaranteed to be MP safe.
+
+  @param  Value A pointer to the 32-bit value to increment.
+
+  @return The incremented value.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncIncrement (
+//  IN      volatile UINT32           *Value
+//  )
+ASM_PFX(InternalSyncIncrement):
+  dmb
+TryInternalSyncIncrement:
+  ldrex   r1, [r0]
+  add     r1, r1, #1
+  strex   r2, r1, [r0]
+  cmp     r2, #0
+  bne     TryInternalSyncIncrement
+  dmb
+  bx      lr
+
+/**
+  Performs an atomic decrement of an 32-bit unsigned integer.
+
+  Performs an atomic decrement of the 32-bit unsigned integer specified by
+  Value and returns the decrement value. The decrement operation must be
+  performed using MP safe mechanisms. The state of the return value is not
+  guaranteed to be MP safe.
+
+  @param  Value A pointer to the 32-bit value to decrement.
+
+  @return The decrement value.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncDecrement (
+//  IN      volatile UINT32           *Value
+//  )
+ASM_PFX(InternalSyncDecrement):
+  dmb
+TryInternalSyncDecrement:
+  ldrex   r1, [r0]
+  sub     r1, r1, #1
+  strex   r2, r1, [r0]
+  cmp     r2, #0
+  bne     TryInternalSyncDecrement
+  dmb
+  bx      lr
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
new file mode 100644
index 000000000000..f9f80737774a
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
@@ -0,0 +1,168 @@
+//  Implementation of synchronization functions for ARM architecture
+//
+//  Copyright (c) 2012-2015, ARM 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.
+//
+//
+
+    EXPORT  InternalSyncCompareExchange32
+    EXPORT  InternalSyncCompareExchange64
+    EXPORT  InternalSyncIncrement
+    EXPORT  InternalSyncDecrement
+
+    AREA   ArmSynchronization, CODE, READONLY
+
+/**
+  Performs an atomic compare exchange operation on a 32-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 32-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 32-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  32-bit value used in compare operation.
+  @param  ExchangeValue 32-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncCompareExchange32 (
+//  IN      volatile UINT32           *Value,
+//  IN      UINT32                    CompareValue,
+//  IN      UINT32                    ExchangeValue
+//  )
+InternalSyncCompareExchange32
+  dmb
+
+InternalSyncCompareExchange32Again
+  ldrex   r3, [r0]
+  cmp     r3, r1
+  bne     InternalSyncCompareExchange32Fail
+
+InternalSyncCompareExchange32Exchange
+  strex   ip, r2, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange32Again
+
+InternalSyncCompareExchange32Fail
+  dmb
+  mov     r0, r3
+  bx      lr
+
+/**
+  Performs an atomic compare exchange operation on a 64-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
+  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
+  The compare exchange operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 64-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  64-bit value used in compare operation.
+  @param  ExchangeValue 64-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT64
+//EFIAPI
+//InternalSyncCompareExchange64 (
+//  IN      volatile UINT64           *Value,         // r0
+//  IN      UINT64                    CompareValue,   // r2-r3
+//  IN      UINT64                    ExchangeValue   // stack
+//  )
+InternalSyncCompareExchange64
+  push    { r4-r7 }
+  ldrd    r4, r5, [sp, #16]
+  dmb
+
+InternalSyncCompareExchange64Again
+  ldrexd  r6, r7, [r0]
+  cmp     r6, r2
+  cmpeq   r7, r3
+  bne     InternalSyncCompareExchange64Fail
+
+InternalSyncCompareExchange64Exchange
+  strexd  ip, r4, r5, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange64Again
+
+InternalSyncCompareExchange64Fail
+  dmb
+  mov     r0, r6
+  mov     r1, r7
+  pop     { r4-r7 }
+  bx      lr
+
+/**
+  Performs an atomic increment of an 32-bit unsigned integer.
+
+  Performs an atomic increment of the 32-bit unsigned integer specified by
+  Value and returns the incremented value. The increment operation must be
+  performed using MP safe mechanisms. The state of the return value is not
+  guaranteed to be MP safe.
+
+  @param  Value A pointer to the 32-bit value to increment.
+
+  @return The incremented value.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncIncrement (
+//  IN      volatile UINT32           *Value
+//  )
+InternalSyncIncrement
+  dmb
+TryInternalSyncIncrement
+  ldrex   r1, [r0]
+  add     r1, r1, #1
+  strex   r2, r1, [r0]
+  cmp     r2, #0
+  bne     TryInternalSyncIncrement
+  dmb
+  bx      lr
+
+/**
+  Performs an atomic decrement of an 32-bit unsigned integer.
+
+  Performs an atomic decrement of the 32-bit unsigned integer specified by
+  Value and returns the decrement value. The decrement operation must be
+  performed using MP safe mechanisms. The state of the return value is not
+  guaranteed to be MP safe.
+
+  @param  Value A pointer to the 32-bit value to decrement.
+
+  @return The decrement value.
+
+**/
+//UINT32
+//EFIAPI
+//InternalSyncDecrement (
+//  IN      volatile UINT32           *Value
+//  )
+InternalSyncDecrement
+  dmb
+TryInternalSyncDecrement
+  ldrex   r1, [r0]
+  sub     r1, r1, #1
+  strex   r2, r1, [r0]
+  cmp     r2, #0
+  bne     TryInternalSyncDecrement
+  dmb
+  bx      lr
+
+  END
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c
deleted file mode 100644
index 9ddaa098b22f..000000000000
--- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/** @file
-  Implementation of synchronization functions. Still needs to be ported
-
-  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
-  Portions copyright (c) 2008 - 2009, Apple Inc. 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.
-
-**/
-
-/**
-  Performs an atomic compare exchange operation on a 32-bit unsigned integer.
-
-  Performs an atomic compare exchange operation on the 32-bit unsigned integer
-  specified by Value.  If Value is equal to CompareValue, then Value is set to
-  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
-  then Value is returned.  The compare exchange operation must be performed using
-  MP safe mechanisms.
-
-  @param  Value         A pointer to the 32-bit value for the compare exchange
-                        operation.
-  @param  CompareValue  32-bit value used in compare operation.
-  @param  ExchangeValue 32-bit value used in exchange operation.
-
-  @return The original *Value before exchange.
-
-**/
-UINT32
-EFIAPI
-InternalSyncCompareExchange32 (
-  IN      volatile UINT32           *Value,
-  IN      UINT32                    CompareValue,
-  IN      UINT32                    ExchangeValue
-  )
-{
-  return *Value != CompareValue ? *Value :
-           ((*Value = ExchangeValue), CompareValue);
-}
-
-/**
-  Performs an atomic compare exchange operation on a 64-bit unsigned integer.
-
-  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified 
-  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and 
-  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned. 
-  The compare exchange operation must be performed using MP safe mechanisms.
-
-  @param  Value         A pointer to the 64-bit value for the compare exchange
-                        operation.
-  @param  CompareValue  64-bit value used in compare operation.
-  @param  ExchangeValue 64-bit value used in exchange operation.
-
-  @return The original *Value before exchange.
-
-**/
-UINT64
-EFIAPI
-InternalSyncCompareExchange64 (
-  IN      volatile UINT64           *Value,
-  IN      UINT64                    CompareValue,
-  IN      UINT64                    ExchangeValue
-  )
-{
-  return *Value != CompareValue ? *Value :
-           ((*Value = ExchangeValue), CompareValue);
-}
-
-/**
-  Performs an atomic increment of an 32-bit unsigned integer.
-
-  Performs an atomic increment of the 32-bit unsigned integer specified by
-  Value and returns the incremented value. The increment operation must be
-  performed using MP safe mechanisms. The state of the return value is not
-  guaranteed to be MP safe.
-
-  @param  Value A pointer to the 32-bit value to increment.
-
-  @return The incremented value.
-
-**/
-UINT32
-EFIAPI
-InternalSyncIncrement (
-  IN      volatile UINT32           *Value
-  )
-{
-  return ++*Value;
-}
-
-/**
-  Performs an atomic decrement of an 32-bit unsigned integer.
-
-  Performs an atomic decrement of the 32-bit unsigned integer specified by
-  Value and returns the decrement value. The decrement operation must be
-  performed using MP safe mechanisms. The state of the return value is not
-  guaranteed to be MP safe.
-
-  @param  Value A pointer to the 32-bit value to decrement.
-
-  @return The decrement value.
-
-**/
-UINT32
-EFIAPI
-InternalSyncDecrement (
-  IN      volatile UINT32           *Value
-  )
-{
-  return --*Value;
-}
diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
old mode 100644
new mode 100755
index bf9cf67a85cc..5e3b4e6b9bf2
--- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
@@ -78,11 +78,12 @@
 
 [Sources.ARM]
   Synchronization.c
-  Arm/Synchronization.c
+  Arm/Synchronization.asm       | RVCT
+  Arm/Synchronization.S         | GCC
 
 [Sources.AARCH64]
   Synchronization.c
-  AArch64/Synchronization.c
+  AArch64/Synchronization.S
 
 [Packages]
   MdePkg/MdePkg.dec
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (12 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 13/29] MdePkg/BaseSynchronizationLib: Added proper support for ARM architecture Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 15/29] Ovmf/Xen: move Xen interface version to <xen.h> Ard Biesheuvel
                   ` (24 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This implements the function InterlockedCompareExchange16 () for all
architectures, using architecture and toolchain specific intrinsics
or primitive assembler instructions.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 17 files changed, 622 insertions(+)

diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
index f97569739914..7b97683ca0af 100644
--- a/MdePkg/Include/Library/SynchronizationLib.h
+++ b/MdePkg/Include/Library/SynchronizationLib.h
@@ -184,6 +184,32 @@ InterlockedDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  );
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
index 601b00495f26..ecb87fc12755 100644
--- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
+++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
@@ -16,12 +16,56 @@
 .text
 .align 3
 
+GCC_ASM_EXPORT(InternalSyncCompareExchange16)
 GCC_ASM_EXPORT(InternalSyncCompareExchange32)
 GCC_ASM_EXPORT(InternalSyncCompareExchange64)
 GCC_ASM_EXPORT(InternalSyncIncrement)
 GCC_ASM_EXPORT(InternalSyncDecrement)
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange16):
+  uxth    w1, w1
+  uxth    w2, w2
+  dmb     sy
+
+InternalSyncCompareExchange16Again:
+  ldxrh   w3, [x0]
+  cmp     w3, w1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange:
+  stxrh   w4, w2, [x0]
+  cbnz    w4, InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail:
+  dmb     sy
+  mov     w0, w3
+  ret
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
index 0128f8f016bd..d699eb40d2a2 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
+++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
@@ -1,6 +1,7 @@
 //  Implementation of synchronization functions for ARM architecture
 //
 //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
+//  Copyright (c) 2015, 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
@@ -15,12 +16,55 @@
 .text
 .align 3
 
+GCC_ASM_EXPORT(InternalSyncCompareExchange16)
 GCC_ASM_EXPORT(InternalSyncCompareExchange32)
 GCC_ASM_EXPORT(InternalSyncCompareExchange64)
 GCC_ASM_EXPORT(InternalSyncIncrement)
 GCC_ASM_EXPORT(InternalSyncDecrement)
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange16):
+  dmb
+
+InternalSyncCompareExchange16Again:
+  ldrexh  r3, [r0]
+  cmp     r3, r1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange:
+  strexh  ip, r2, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail:
+  dmb
+  mov     r0, r3
+  bx      lr
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
index f9f80737774a..dbc599114093 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
+++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
@@ -1,6 +1,7 @@
 //  Implementation of synchronization functions for ARM architecture
 //
 //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
+//  Copyright (c) 2015, 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
@@ -12,6 +13,7 @@
 //
 //
 
+    EXPORT  InternalSyncCompareExchange16
     EXPORT  InternalSyncCompareExchange32
     EXPORT  InternalSyncCompareExchange64
     EXPORT  InternalSyncIncrement
@@ -20,6 +22,48 @@
     AREA   ArmSynchronization, CODE, READONLY
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+InternalSyncCompareExchange16
+  dmb
+
+InternalSyncCompareExchange16Again
+  ldrexh  r3, [r0]
+  cmp     r3, r1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange
+  strexh  ip, r2, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail
+  dmb
+  mov     r0, r3
+  bx      lr
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
--- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
@@ -32,12 +32,14 @@
 [Sources.IA32]
   Ia32/InterlockedCompareExchange64.c | MSFT 
   Ia32/InterlockedCompareExchange32.c | MSFT 
+  Ia32/InterlockedCompareExchange16.c | MSFT
   Ia32/InterlockedDecrement.c | MSFT 
   Ia32/InterlockedIncrement.c | MSFT 
   SynchronizationMsc.c  | MSFT
 
   Ia32/InterlockedCompareExchange64.asm | INTEL 
   Ia32/InterlockedCompareExchange32.asm | INTEL 
+  Ia32/InterlockedCompareExchange16.asm | INTEL
   Ia32/InterlockedDecrement.asm | INTEL 
   Ia32/InterlockedIncrement.asm | INTEL 
   Synchronization.c | INTEL
@@ -48,9 +50,11 @@
 [Sources.X64]
   X64/InterlockedCompareExchange64.c | MSFT
   X64/InterlockedCompareExchange32.c | MSFT
+  X64/InterlockedCompareExchange16.c | MSFT
   
   X64/InterlockedCompareExchange64.asm | INTEL
   X64/InterlockedCompareExchange32.asm | INTEL
+  X64/InterlockedCompareExchange16.asm | INTEL
   
   X64/InterlockedDecrement.c | MSFT 
   X64/InterlockedIncrement.c | MSFT 
@@ -67,6 +71,7 @@
   Ipf/Synchronization.c
   Ipf/InterlockedCompareExchange64.s
   Ipf/InterlockedCompareExchange32.s
+  Ipf/InterlockedCompareExchange16.s
 
   Synchronization.c     | INTEL 
   SynchronizationMsc.c  | MSFT 
diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
index e42824c75d12..76f702324156 100644
--- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
+++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
@@ -63,6 +63,32 @@ InternalSyncDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in compare operation.
+  @param  ExchangeValue A 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      volatile UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  );
+
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
index 9c34b9f128ed..a57860203b12 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
@@ -13,6 +13,37 @@
 **/
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit
+  unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit
+  unsigned integer specified by Value.  If Value is equal to
+  CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to
+  CompareValue, then Value is returned. The compare exchange
+  operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the
+                        compare exchange operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      volatile UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  return *Value != CompareValue ? *Value :
+           ((*Value = ExchangeValue), CompareValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit
   unsigned integer.
 
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
index b5a7827fc0e8..bd81aad6c243 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
@@ -88,6 +88,48 @@ InternalSyncDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN OUT volatile  UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+
+  __asm__ __volatile__ (
+    "                     \n\t"
+    "lock                 \n\t"
+    "cmpxchgw    %1, %2   \n\t"
+    : "=a" (CompareValue)
+    : "q"  (ExchangeValue),
+      "m"  (*Value),
+      "0"  (CompareValue)
+    : "memory",
+      "cc"
+    );
+
+  return CompareValue;
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
new file mode 100644
index 000000000000..f8705042661d
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
@@ -0,0 +1,46 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015, 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.
+;
+; Module Name:
+;
+;   InterlockedCompareExchange16.Asm
+;
+; Abstract:
+;
+;   InterlockedCompareExchange16 function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    .486
+    .model  flat,C
+    .code
+
+;------------------------------------------------------------------------------
+; UINT16
+; EFIAPI
+; InternalSyncCompareExchange16 (
+;   IN      UINT16                    *Value,
+;   IN      UINT16                    CompareValue,
+;   IN      UINT16                    ExchangeValue
+;   );
+;------------------------------------------------------------------------------
+InternalSyncCompareExchange16   PROC
+    mov     ecx, [esp + 4]
+    mov     eax, [esp + 8]
+    mov     edx, [esp + 12]
+    lock    cmpxchg [ecx], dx
+    ret
+InternalSyncCompareExchange16   ENDP
+
+    END
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
new file mode 100644
index 000000000000..3d06dd9baa63
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
@@ -0,0 +1,51 @@
+/** @file
+  InterlockedCompareExchange16 function
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, 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.
+
+**/
+
+
+
+
+/**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  _asm {
+    mov     ecx, Value
+    mov     eax, CompareValue
+    mov     edx, ExchangeValue
+    lock    cmpxchg [ecx], dx
+  }
+}
+
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
new file mode 100644
index 000000000000..1e56942a98cb
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
@@ -0,0 +1,30 @@
+/// @file
+///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
+///   based architecture.
+///
+/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+/// Copyright (c) 2015, 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.
+///
+/// Module Name:  InterlockedCompareExchange16.s
+///
+///
+
+.auto
+.text
+
+.proc   InternalSyncCompareExchange16
+.type   InternalSyncCompareExchange16, @function
+InternalSyncCompareExchange16::
+        zxt2                r33 = r33
+        mov                 ar.ccv = r33
+        cmpxchg2.rel        r8  = [r32], r34
+        mf
+        br.ret.sptk.many    b0
+.endp   InternalSyncCompareExchange16
diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
index 0eea40ba1622..4218a265a0ec 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
@@ -277,6 +277,37 @@ InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
index badf73c1a6ce..587f5a771c35 100644
--- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
+++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
@@ -293,6 +293,37 @@ InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in compare operation.
+  @param  ExchangeValue A 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
index 9b20236acfa6..ca21f5dccee5 100644
--- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
+++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
@@ -295,6 +295,37 @@ InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in a compare operation.
+  @param  ExchangeValue A 16-bit value used in an exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
index ceb80aed94f8..6347073fee51 100644
--- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
@@ -89,6 +89,50 @@ InternalSyncDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN OUT volatile  UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+
+
+  __asm__ __volatile__ (
+    "lock                 \n\t"
+    "cmpxchgw    %3, %1       "
+    : "=a" (CompareValue),
+      "=m" (*Value)
+    : "a"  (CompareValue),
+      "r"  (ExchangeValue),
+      "m"  (*Value)
+    : "memory",
+      "cc"
+    );
+
+  return CompareValue;
+}
+
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
new file mode 100644
index 000000000000..8fe2aae1a28b
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
@@ -0,0 +1,42 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015, 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.
+;
+; Module Name:
+;
+;   InterlockedCompareExchange16.Asm
+;
+; Abstract:
+;
+;   InterlockedCompareExchange16 function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    .code
+
+;------------------------------------------------------------------------------
+; UINT16
+; EFIAPI
+; InterlockedCompareExchange16 (
+;   IN      UINT16                    *Value,
+;   IN      UINT16                    CompareValue,
+;   IN      UINT16                    ExchangeValue
+;   );
+;------------------------------------------------------------------------------
+InternalSyncCompareExchange16   PROC
+    mov     eax, edx
+    lock    cmpxchg [rcx], r8w
+    ret
+InternalSyncCompareExchange16   ENDP
+
+    END
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
new file mode 100644
index 000000000000..76aa6fbc0e81
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
@@ -0,0 +1,54 @@
+/** @file
+  InterlockedCompareExchange16 function
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, 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.
+
+**/
+
+/**
+  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
+**/
+
+__int16 _InterlockedCompareExchange16(
+   __int16 volatile * Destination,
+   __int16 Exchange,
+   __int16 Comperand
+);
+
+#pragma intrinsic(_InterlockedCompareExchange16)
+
+/**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
+  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
+  The compare exchange operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
+}
+
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 15/29] Ovmf/Xen: move Xen interface version to <xen.h>
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (13 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 16/29] Ovmf/Xen: fix pointer to int cast in XenBusDxe Ard Biesheuvel
                   ` (23 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

Tiancore has its private copy of the Xen headers, and all drivers
that depend on it should use the same Xen interface version, so
let's move the #define to xen.h itself.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/Include/IndustryStandard/Xen/xen.h | 5 +++++
 OvmfPkg/XenBusDxe/XenBusDxe.h              | 5 -----
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h          | 4 ----
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/OvmfPkg/Include/IndustryStandard/Xen/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/xen.h
index 79697fcb6152..1cd7ab3ab136 100644
--- a/OvmfPkg/Include/IndustryStandard/Xen/xen.h
+++ b/OvmfPkg/Include/IndustryStandard/Xen/xen.h
@@ -27,6 +27,11 @@
 #ifndef __XEN_PUBLIC_XEN_H__
 #define __XEN_PUBLIC_XEN_H__
 
+//
+// Xen interface version used by Tianocore
+//
+#define __XEN_INTERFACE_VERSION__ 0x00040400
+
 #include "xen-compat.h"
 
 #if defined(MDE_CPU_IA32) || defined(MDE_CPU_X64)
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 11640223ebf4..80253b7d1ca9 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -19,11 +19,6 @@
 #include <Uefi.h>
 
 //
-// Xen interface version used
-//
-#define  __XEN_INTERFACE_VERSION__ 0x00040400
-
-//
 // Libraries
 //
 #include <Library/UefiBootServicesTableLib.h>
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
index e5b1b5f4b90d..c0b62c4f38ca 100644
--- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
@@ -18,10 +18,6 @@
 
 #include <Uefi.h>
 
-//
-// Xen interface version used
-//
-#define __XEN_INTERFACE_VERSION__ 0x00040400
 #define xen_mb() MemoryFence()
 #define xen_rmb() MemoryFence()
 #define xen_wmb() MemoryFence()
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 16/29] Ovmf/Xen: fix pointer to int cast in XenBusDxe
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (14 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 15/29] Ovmf/Xen: move Xen interface version to <xen.h> Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 17/29] Ovmf/Xen: refactor XenBusDxe hypercall implementation Ard Biesheuvel
                   ` (22 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

On ARM, xen_pfn_t is 64 bits but the size of a pointer is only
32 bits, so casting between them needs to go via (UINTN). Also
move the xen_pfn_t cast outside the shift so that we can avoid
shifting 64-bit quantities on 32-bit architectures, which may
require runtime library support.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/XenBusDxe/GrantTable.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c
index 37d3bf786c64..8405edc51bc4 100644
--- a/OvmfPkg/XenBusDxe/GrantTable.c
+++ b/OvmfPkg/XenBusDxe/GrantTable.c
@@ -160,7 +160,7 @@ XenGrantTableInit (
     Parameters.domid = DOMID_SELF;
     Parameters.idx = Index;
     Parameters.space = XENMAPSPACE_grant_table;
-    Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;
+    Parameters.gpfn = (xen_pfn_t) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
     ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameters);
     if (ReturnCode != 0) {
       DEBUG ((EFI_D_ERROR, "Xen GrantTable, add_to_physmap hypercall error: %d\n", ReturnCode));
@@ -182,7 +182,7 @@ XenGrantTableDeinit (
 
   for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {
     Parameters.domid = DOMID_SELF;
-    Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;
+    Parameters.gpfn = (xen_pfn_t) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
     DEBUG ((EFI_D_INFO, "Xen GrantTable, removing %X\n", Parameters.gpfn));
     ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_remove_from_physmap, &Parameters);
     if (ReturnCode != 0) {
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 17/29] Ovmf/Xen: refactor XenBusDxe hypercall implementation
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (15 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 16/29] Ovmf/Xen: fix pointer to int cast in XenBusDxe Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 18/29] Ovmf/Xen: move XenBusDxe hypercall code to separate library Ard Biesheuvel
                   ` (21 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This refactors the Xen hypercall implementation that is part of the
XenBusDxe driver, in preparation of splitting it off entirely into
a XenHypercallLib library. This involves:
- removing the dependency on XENBUS_DEVICE* pointers in the XenHypercall()
  prototypes
- moving the discovered hyperpage address to a global variable
- moving XenGetSharedInfoPage() to its only user XenBusDxe.c (the shared info
  page is not strictly part of the Xen hypercall interface, and is not used
  by other expected users of XenHypercallLib such as the Xen console version
  of SerialPortLib
- reimplement XenHypercall2() in C and move the indexing of the hyperpage
  there; the existing asm implementations are renamed to __XenHypercall2() and
  invoked from the new C implementation.

Contributed-under: TianoCore Contribution Agreement 1.0
Acked-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/XenBusDxe/EventChannel.c      | 11 +++--------
 OvmfPkg/XenBusDxe/GrantTable.c        |  4 ++--
 OvmfPkg/XenBusDxe/Ia32/hypercall.nasm |  6 +++---
 OvmfPkg/XenBusDxe/X64/hypercall.nasm  |  6 +++---
 OvmfPkg/XenBusDxe/XenBusDxe.c         | 44 +++++++++++++++++++++++++++++++++++++++++++-
 OvmfPkg/XenBusDxe/XenBusDxe.h         |  1 -
 OvmfPkg/XenBusDxe/XenHypercall.c      | 61 +++++++++++++++++++++++++------------------------------------
 OvmfPkg/XenBusDxe/XenHypercall.h      | 28 +++-------------------------
 OvmfPkg/XenBusDxe/XenStore.c          |  4 ++--
 9 files changed, 84 insertions(+), 81 deletions(-)

diff --git a/OvmfPkg/XenBusDxe/EventChannel.c b/OvmfPkg/XenBusDxe/EventChannel.c
index 03efaf9cb904..a86323e6adfd 100644
--- a/OvmfPkg/XenBusDxe/EventChannel.c
+++ b/OvmfPkg/XenBusDxe/EventChannel.c
@@ -28,7 +28,7 @@ XenEventChannelNotify (
   evtchn_send_t Send;
 
   Send.port = Port;
-  ReturnCode = XenHypercallEventChannelOp (Dev, EVTCHNOP_send, &Send);
+  ReturnCode = XenHypercallEventChannelOp (EVTCHNOP_send, &Send);
   return (UINT32)ReturnCode;
 }
 
@@ -40,15 +40,12 @@ XenBusEventChannelAllocate (
   OUT evtchn_port_t   *Port
   )
 {
-  XENBUS_PRIVATE_DATA *Private;
   evtchn_alloc_unbound_t Parameter;
   UINT32 ReturnCode;
 
-  Private = XENBUS_PRIVATE_DATA_FROM_THIS (This);
-
   Parameter.dom = DOMID_SELF;
   Parameter.remote_dom = DomainId;
-  ReturnCode = (UINT32)XenHypercallEventChannelOp (Private->Dev,
+  ReturnCode = (UINT32)XenHypercallEventChannelOp (
                                    EVTCHNOP_alloc_unbound,
                                    &Parameter);
   if (ReturnCode != 0) {
@@ -79,10 +76,8 @@ XenBusEventChannelClose (
   IN evtchn_port_t   Port
   )
 {
-  XENBUS_PRIVATE_DATA *Private;
   evtchn_close_t Close;
 
-  Private = XENBUS_PRIVATE_DATA_FROM_THIS (This);
   Close.port = Port;
-  return (UINT32)XenHypercallEventChannelOp (Private->Dev, EVTCHNOP_close, &Close);
+  return (UINT32)XenHypercallEventChannelOp (EVTCHNOP_close, &Close);
 }
diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c
index 8405edc51bc4..53cb99f0e004 100644
--- a/OvmfPkg/XenBusDxe/GrantTable.c
+++ b/OvmfPkg/XenBusDxe/GrantTable.c
@@ -161,7 +161,7 @@ XenGrantTableInit (
     Parameters.idx = Index;
     Parameters.space = XENMAPSPACE_grant_table;
     Parameters.gpfn = (xen_pfn_t) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
-    ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameters);
+    ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);
     if (ReturnCode != 0) {
       DEBUG ((EFI_D_ERROR, "Xen GrantTable, add_to_physmap hypercall error: %d\n", ReturnCode));
     }
@@ -184,7 +184,7 @@ XenGrantTableDeinit (
     Parameters.domid = DOMID_SELF;
     Parameters.gpfn = (xen_pfn_t) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
     DEBUG ((EFI_D_INFO, "Xen GrantTable, removing %X\n", Parameters.gpfn));
-    ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_remove_from_physmap, &Parameters);
+    ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);
     if (ReturnCode != 0) {
       DEBUG ((EFI_D_ERROR, "Xen GrantTable, remove_from_physmap hypercall error: %d\n", ReturnCode));
     }
diff --git a/OvmfPkg/XenBusDxe/Ia32/hypercall.nasm b/OvmfPkg/XenBusDxe/Ia32/hypercall.nasm
index 8547c30b81ee..e0fa71bb5ba8 100644
--- a/OvmfPkg/XenBusDxe/Ia32/hypercall.nasm
+++ b/OvmfPkg/XenBusDxe/Ia32/hypercall.nasm
@@ -2,13 +2,13 @@ SECTION .text
 
 ; INTN
 ; EFIAPI
-; XenHypercall2 (
+; __XenHypercall2 (
 ;   IN     VOID *HypercallAddr,
 ;   IN OUT INTN Arg1,
 ;   IN OUT INTN Arg2
 ;   );
-global ASM_PFX(XenHypercall2)
-ASM_PFX(XenHypercall2):
+global ASM_PFX(__XenHypercall2)
+ASM_PFX(__XenHypercall2):
   ; Save only ebx, ecx is supposed to be a scratch register and needs to be
   ; saved by the caller
   push ebx
diff --git a/OvmfPkg/XenBusDxe/X64/hypercall.nasm b/OvmfPkg/XenBusDxe/X64/hypercall.nasm
index 177f271ef094..5e6a0c05c5c4 100644
--- a/OvmfPkg/XenBusDxe/X64/hypercall.nasm
+++ b/OvmfPkg/XenBusDxe/X64/hypercall.nasm
@@ -3,13 +3,13 @@ SECTION .text
 
 ; INTN
 ; EFIAPI
-; XenHypercall2 (
+; __XenHypercall2 (
 ;   IN     VOID *HypercallAddr,
 ;   IN OUT INTN Arg1,
 ;   IN OUT INTN Arg2
 ;   );
-global ASM_PFX(XenHypercall2)
-ASM_PFX(XenHypercall2):
+global ASM_PFX(__XenHypercall2)
+ASM_PFX(__XenHypercall2):
   push rdi
   push rsi
   ; Copy HypercallAddr to rax
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index 7a7fd82d559d..d333b331b6db 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -34,6 +34,8 @@
 #include "XenStore.h"
 #include "XenBus.h"
 
+#include <IndustryStandard/Xen/hvm/params.h>
+#include <IndustryStandard/Xen/memory.h>
 
 ///
 /// Driver Binding Protocol instance
@@ -52,6 +54,46 @@ STATIC EFI_LOCK       mMyDeviceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_CALLBACK
 STATIC XENBUS_DEVICE *mMyDevice = NULL;
 
 /**
+  Map the shared_info_t page into memory.
+
+  @param Dev    A XENBUS_DEVICE instance.
+
+  @retval EFI_SUCCESS     Dev->SharedInfo whill contain a pointer to
+                          the shared info page
+  @retval EFI_LOAD_ERROR  The shared info page could not be mapped. The
+                          hypercall returned an error.
+**/
+STATIC
+EFI_STATUS
+XenGetSharedInfoPage (
+  IN OUT XENBUS_DEVICE *Dev
+  )
+{
+  xen_add_to_physmap_t Parameter;
+
+  ASSERT (Dev->SharedInfo == NULL);
+
+  Parameter.domid = DOMID_SELF;
+  Parameter.space = XENMAPSPACE_shared_info;
+  Parameter.idx = 0;
+
+  //
+  // using reserved page because the page is not released when Linux is
+  // starting because of the add_to_physmap. QEMU might try to access the
+  // page, and fail because it have no right to do so (segv).
+  //
+  Dev->SharedInfo = AllocateReservedPages (1);
+  Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT;
+  if (XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameter) != 0) {
+    FreePages (Dev->SharedInfo, 1);
+    Dev->SharedInfo = NULL;
+    return EFI_LOAD_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
   Unloads an image.
 
   @param  ImageHandle           Handle that identifies the image to be unloaded.
@@ -348,7 +390,7 @@ XenBusDxeDriverBindingStart (
   MmioAddr = BarDesc->AddrRangeMin;
   FreePool (BarDesc);
 
-  Status = XenHyperpageInit (Dev);
+  Status = XenHyperpageInit ();
   if (EFI_ERROR (Status)) {
     DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage.\n"));
     Status = EFI_UNSUPPORTED;
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 80253b7d1ca9..9b7219906a69 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -91,7 +91,6 @@ struct _XENBUS_DEVICE {
   EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
   LIST_ENTRY                    ChildList;
 
-  VOID                          *Hyperpage;
   shared_info_t                 *SharedInfo;
 };
 
diff --git a/OvmfPkg/XenBusDxe/XenHypercall.c b/OvmfPkg/XenBusDxe/XenHypercall.c
index 34d92e76b7e3..19c34bdd0cec 100644
--- a/OvmfPkg/XenBusDxe/XenHypercall.c
+++ b/OvmfPkg/XenBusDxe/XenHypercall.c
@@ -23,9 +23,21 @@
 #include <IndustryStandard/Xen/hvm/params.h>
 #include <IndustryStandard/Xen/memory.h>
 
+STATIC VOID       *HyperPage;
+
+//
+// Interface exposed by the ASM implementation of the core hypercall
+//
+INTN
+EFIAPI
+__XenHypercall2 (
+  IN     VOID *HypercallAddr,
+  IN OUT INTN Arg1,
+  IN OUT INTN Arg2
+  );
+
 EFI_STATUS
 XenHyperpageInit (
-  IN OUT XENBUS_DEVICE *Dev
   )
 {
   EFI_HOB_GUID_TYPE   *GuidHob;
@@ -36,24 +48,21 @@ XenHyperpageInit (
     return EFI_NOT_FOUND;
   }
   XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob);
-  Dev->Hyperpage = XenInfo->HyperPages;
+  HyperPage = XenInfo->HyperPages;
   return EFI_SUCCESS;
 }
 
 UINT64
 XenHypercallHvmGetParam (
-  IN XENBUS_DEVICE *Dev,
   IN UINT32        Index
   )
 {
   xen_hvm_param_t     Parameter;
   INTN                Error;
 
-  ASSERT (Dev->Hyperpage != NULL);
-
   Parameter.domid = DOMID_SELF;
   Parameter.index = Index;
-  Error = XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_hvm_op * 32,
+  Error = XenHypercall2 (__HYPERVISOR_hvm_op,
                          HVMOP_get_param, (INTN) &Parameter);
   if (Error != 0) {
     DEBUG ((EFI_D_ERROR,
@@ -66,53 +75,33 @@ XenHypercallHvmGetParam (
 
 INTN
 XenHypercallMemoryOp (
-  IN     XENBUS_DEVICE *Dev,
   IN     UINTN Operation,
   IN OUT VOID *Arguments
   )
 {
-  ASSERT (Dev->Hyperpage != NULL);
-  return XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_memory_op * 32,
+  return XenHypercall2 (__HYPERVISOR_memory_op,
                         Operation, (INTN) Arguments);
 }
 
 INTN
 XenHypercallEventChannelOp (
-  IN     XENBUS_DEVICE *Dev,
   IN     INTN Operation,
   IN OUT VOID *Arguments
   )
 {
-  ASSERT (Dev->Hyperpage != NULL);
-  return XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_event_channel_op * 32,
+  return XenHypercall2 (__HYPERVISOR_event_channel_op,
                         Operation, (INTN) Arguments);
 }
 
-EFI_STATUS
-XenGetSharedInfoPage (
-  IN OUT XENBUS_DEVICE *Dev
+INTN
+EFIAPI
+XenHypercall2 (
+  IN     INTN HypercallID,
+  IN OUT INTN Arg1,
+  IN OUT INTN Arg2
   )
 {
-  xen_add_to_physmap_t Parameter;
+  ASSERT (HyperPage != NULL);
 
-  ASSERT (Dev->SharedInfo == NULL);
-
-  Parameter.domid = DOMID_SELF;
-  Parameter.space = XENMAPSPACE_shared_info;
-  Parameter.idx = 0;
-
-  //
-  // using reserved page because the page is not released when Linux is
-  // starting because of the add_to_physmap. QEMU might try to access the
-  // page, and fail because it have no right to do so (segv).
-  //
-  Dev->SharedInfo = AllocateReservedPages (1);
-  Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT;
-  if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameter) != 0) {
-    FreePages (Dev->SharedInfo, 1);
-    Dev->SharedInfo = NULL;
-    return EFI_LOAD_ERROR;
-  }
-
-  return EFI_SUCCESS;
+  return __XenHypercall2 ((UINT8*)HyperPage + HypercallID * 32, Arg1, Arg2);
 }
diff --git a/OvmfPkg/XenBusDxe/XenHypercall.h b/OvmfPkg/XenBusDxe/XenHypercall.h
index 06693830e16e..9d49e33eb5af 100644
--- a/OvmfPkg/XenBusDxe/XenHypercall.h
+++ b/OvmfPkg/XenBusDxe/XenHypercall.h
@@ -18,9 +18,9 @@
 
 /**
   This function will put the two arguments in the right place (registers) and
-  call HypercallAddr, which correspond to an entry in the hypercall pages.
+  invoke the hypercall identified by HypercallID.
 
-  @param HypercallAddr  A memory address where the hypercall to call is.
+  @param HypercallID    The symbolic ID of the hypercall to be invoked
   @param Arg1           First argument.
   @param Arg2           Second argument.
 
@@ -29,7 +29,7 @@
 INTN
 EFIAPI
 XenHypercall2 (
-  IN     VOID *HypercallAddr,
+  IN     INTN HypercallID,
   IN OUT INTN Arg1,
   IN OUT INTN Arg2
   );
@@ -44,27 +44,23 @@ XenHypercall2 (
 **/
 EFI_STATUS
 XenHyperpageInit (
-  XENBUS_DEVICE *Dev
   );
 
 /**
   Return the value of the HVM parameter Index.
 
-  @param Dev    A XENBUS_DEVICE instance.
   @param Index  The parameter to get, e.g. HVM_PARAM_STORE_EVTCHN.
 
   @return   The value of the asked parameter or 0 in case of error.
 **/
 UINT64
 XenHypercallHvmGetParam (
-  XENBUS_DEVICE *Dev,
   UINT32 Index
   );
 
 /**
   Hypercall to do different operation on the memory.
 
-  @param Dev        A XENBUS_DEVICE instance.
   @param Operation  The operation number, e.g. XENMEM_add_to_physmap.
   @param Arguments  The arguments associated to the operation.
 
@@ -73,7 +69,6 @@ XenHypercallHvmGetParam (
 **/
 INTN
 XenHypercallMemoryOp (
-  IN     XENBUS_DEVICE *Dev,
   IN     UINTN Operation,
   IN OUT VOID *Arguments
   );
@@ -81,7 +76,6 @@ XenHypercallMemoryOp (
 /**
   Do an operation on the event channels.
 
-  @param Dev        A XENBUS_DEVICE instance.
   @param Operation  The operation number, e.g. EVTCHNOP_send.
   @param Arguments  The argument associated to the operation.
 
@@ -90,24 +84,8 @@ XenHypercallMemoryOp (
 **/
 INTN
 XenHypercallEventChannelOp (
-  IN     XENBUS_DEVICE *Dev,
   IN     INTN Operation,
   IN OUT VOID *Arguments
   );
 
-/**
-  Map the shared_info_t page into memory.
-
-  @param Dev    A XENBUS_DEVICE instance.
-
-  @retval EFI_SUCCESS     Dev->SharedInfo whill contain a pointer to
-                          the shared info page
-  @retval EFI_LOAD_ERROR  The shared info page could not be mapped. The
-                          hypercall returned an error.
-**/
-EFI_STATUS
-XenGetSharedInfoPage (
-  IN OUT XENBUS_DEVICE *Dev
-  );
-
 #endif
diff --git a/OvmfPkg/XenBusDxe/XenStore.c b/OvmfPkg/XenBusDxe/XenStore.c
index 2df8f5348585..7ec1e634bc5c 100644
--- a/OvmfPkg/XenBusDxe/XenStore.c
+++ b/OvmfPkg/XenBusDxe/XenStore.c
@@ -1057,8 +1057,8 @@ XenStoreInit (
 
   xs.Dev = Dev;
 
-  xs.EventChannel = (evtchn_port_t)XenHypercallHvmGetParam (Dev, HVM_PARAM_STORE_EVTCHN);
-  XenStoreGpfn = (UINTN)XenHypercallHvmGetParam (Dev, HVM_PARAM_STORE_PFN);
+  xs.EventChannel = (evtchn_port_t)XenHypercallHvmGetParam (HVM_PARAM_STORE_EVTCHN);
+  XenStoreGpfn = (UINTN)XenHypercallHvmGetParam (HVM_PARAM_STORE_PFN);
   xs.XenStore = (VOID *) (XenStoreGpfn << EFI_PAGE_SHIFT);
   DEBUG ((EFI_D_INFO, "XenBusInit: XenBus rings @%p, event channel %x\n",
           xs.XenStore, xs.EventChannel));
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 18/29] Ovmf/Xen: move XenBusDxe hypercall code to separate library
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (16 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 17/29] Ovmf/Xen: refactor XenBusDxe hypercall implementation Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 19/29] Ovmf/Xen: introduce XENIO_PROTOCOL Ard Biesheuvel
                   ` (20 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This moves all of the Xen hypercall code that was private to XenBusDxe
to a new library class XenHypercallLib. This will allow us to reimplement
it for ARM, and to export the Xen hypercall functionality to other parts
of the code, such as a Xen console SerialPortLib driver.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/{XenBusDxe/XenHypercall.h => Include/Library/XenHypercallLib.h} | 16 ++--------------
 OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm      |  0
 OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm       |  0
 OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/XenHypercall.c           | 48 ++----------------------------------------------
 OvmfPkg/Library/XenHypercallLib/XenHypercallIntel.c                     | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf                | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/OvmfPkg.dec                                                     |  4 ++++
 OvmfPkg/OvmfPkgIa32.dsc                                                 |  1 +
 OvmfPkg/OvmfPkgIa32X64.dsc                                              |  1 +
 OvmfPkg/OvmfPkgX64.dsc                                                  |  1 +
 OvmfPkg/XenBusDxe/EventChannel.c                                        |  3 ++-
 OvmfPkg/XenBusDxe/GrantTable.c                                          |  2 +-
 OvmfPkg/XenBusDxe/XenBusDxe.c                                           |  9 +--------
 OvmfPkg/XenBusDxe/XenBusDxe.inf                                         | 11 +----------
 OvmfPkg/XenBusDxe/XenStore.c                                            |  2 +-
 15 files changed, 146 insertions(+), 81 deletions(-)

diff --git a/OvmfPkg/XenBusDxe/XenHypercall.h b/OvmfPkg/Include/Library/XenHypercallLib.h
similarity index 82%
rename from OvmfPkg/XenBusDxe/XenHypercall.h
rename to OvmfPkg/Include/Library/XenHypercallLib.h
index 9d49e33eb5af..7a170ff3b90e 100644
--- a/OvmfPkg/XenBusDxe/XenHypercall.h
+++ b/OvmfPkg/Include/Library/XenHypercallLib.h
@@ -13,8 +13,8 @@
 
 **/
 
-#ifndef __XENBUS_DXE_HYPERCALL_H__
-#define __XENBUS_DXE_HYPERCALL_H__
+#ifndef __XEN_HYPERCALL_LIB_H__
+#define __XEN_HYPERCALL_LIB_H__
 
 /**
   This function will put the two arguments in the right place (registers) and
@@ -35,18 +35,6 @@ XenHypercall2 (
   );
 
 /**
-  Get the page where all hypercall are from the XenInfo hob.
-
-  @param Dev    A XENBUS_DEVICE instance.
-
-  @retval EFI_NOT_FOUND   hyperpage could not be found.
-  @retval EFI_SUCCESS     Successfully retrieve the hyperpage pointer.
-**/
-EFI_STATUS
-XenHyperpageInit (
-  );
-
-/**
   Return the value of the HVM parameter Index.
 
   @param Index  The parameter to get, e.g. HVM_PARAM_STORE_EVTCHN.
diff --git a/OvmfPkg/XenBusDxe/Ia32/hypercall.nasm b/OvmfPkg/Library/XenHypercallLib/Ia32/hypercall.nasm
similarity index 100%
rename from OvmfPkg/XenBusDxe/Ia32/hypercall.nasm
rename to OvmfPkg/Library/XenHypercallLib/Ia32/hypercall.nasm
diff --git a/OvmfPkg/XenBusDxe/X64/hypercall.nasm b/OvmfPkg/Library/XenHypercallLib/X64/hypercall.nasm
similarity index 100%
rename from OvmfPkg/XenBusDxe/X64/hypercall.nasm
rename to OvmfPkg/Library/XenHypercallLib/X64/hypercall.nasm
diff --git a/OvmfPkg/XenBusDxe/XenHypercall.c b/OvmfPkg/Library/XenHypercallLib/XenHypercall.c
similarity index 60%
rename from OvmfPkg/XenBusDxe/XenHypercall.c
rename to OvmfPkg/Library/XenHypercallLib/XenHypercall.c
index 19c34bdd0cec..ecc757cf707c 100644
--- a/OvmfPkg/XenBusDxe/XenHypercall.c
+++ b/OvmfPkg/Library/XenHypercallLib/XenHypercall.c
@@ -14,43 +14,12 @@
 **/
 
 #include <PiDxe.h>
-#include <Library/HobLib.h>
-#include <Guid/XenInfo.h>
-
-#include "XenBusDxe.h"
-#include "XenHypercall.h"
 
 #include <IndustryStandard/Xen/hvm/params.h>
 #include <IndustryStandard/Xen/memory.h>
 
-STATIC VOID       *HyperPage;
-
-//
-// Interface exposed by the ASM implementation of the core hypercall
-//
-INTN
-EFIAPI
-__XenHypercall2 (
-  IN     VOID *HypercallAddr,
-  IN OUT INTN Arg1,
-  IN OUT INTN Arg2
-  );
-
-EFI_STATUS
-XenHyperpageInit (
-  )
-{
-  EFI_HOB_GUID_TYPE   *GuidHob;
-  EFI_XEN_INFO        *XenInfo;
-
-  GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
-  if (GuidHob == NULL) {
-    return EFI_NOT_FOUND;
-  }
-  XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob);
-  HyperPage = XenInfo->HyperPages;
-  return EFI_SUCCESS;
-}
+#include <Library/DebugLib.h>
+#include <Library/XenHypercallLib.h>
 
 UINT64
 XenHypercallHvmGetParam (
@@ -92,16 +61,3 @@ XenHypercallEventChannelOp (
   return XenHypercall2 (__HYPERVISOR_event_channel_op,
                         Operation, (INTN) Arguments);
 }
-
-INTN
-EFIAPI
-XenHypercall2 (
-  IN     INTN HypercallID,
-  IN OUT INTN Arg1,
-  IN OUT INTN Arg2
-  )
-{
-  ASSERT (HyperPage != NULL);
-
-  return __XenHypercall2 ((UINT8*)HyperPage + HypercallID * 32, Arg1, Arg2);
-}
diff --git a/OvmfPkg/Library/XenHypercallLib/XenHypercallIntel.c b/OvmfPkg/Library/XenHypercallLib/XenHypercallIntel.c
new file mode 100644
index 000000000000..362640f6a16f
--- /dev/null
+++ b/OvmfPkg/Library/XenHypercallLib/XenHypercallIntel.c
@@ -0,0 +1,77 @@
+/** @file
+  Xen Hypercall Library implementation for Intel architecture
+
+Copyright (c) 2014, 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 that 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 <PiDxe.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Guid/XenInfo.h>
+
+STATIC VOID    *HyperPage;
+
+//
+// Interface exposed by the ASM implementation of the core hypercall
+//
+INTN
+EFIAPI
+__XenHypercall2 (
+  IN     VOID *HypercallAddr,
+  IN OUT INTN Arg1,
+  IN OUT INTN Arg2
+  );
+
+/**
+  Library constructor: retrieves the Hyperpage address
+  from the gEfiXenInfoGuid HOB
+**/
+
+RETURN_STATUS
+EFIAPI
+XenHypercallLibIntelInit (
+  VOID
+  )
+{
+  EFI_HOB_GUID_TYPE   *GuidHob;
+  EFI_XEN_INFO        *XenInfo;
+
+  GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
+  if (GuidHob == NULL) {
+    return RETURN_NOT_FOUND;
+  }
+  XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob);
+  HyperPage = XenInfo->HyperPages;
+  return RETURN_SUCCESS;
+}
+
+/**
+  This function will put the two arguments in the right place (registers) and
+  invoke the hypercall identified by HypercallID.
+
+  @param HypercallID    The symbolic ID of the hypercall to be invoked
+  @param Arg1           First argument.
+  @param Arg2           Second argument.
+
+  @return   Return 0 if success otherwise it return an errno.
+**/
+INTN
+EFIAPI
+XenHypercall2 (
+  IN     INTN HypercallID,
+  IN OUT INTN Arg1,
+  IN OUT INTN Arg2
+  )
+{
+  ASSERT (HyperPage != NULL);
+
+  return __XenHypercall2 ((UINT8*)HyperPage + HypercallID * 32, Arg1, Arg2);
+}
diff --git a/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
new file mode 100644
index 000000000000..2afd608f4a05
--- /dev/null
+++ b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
@@ -0,0 +1,52 @@
+## @file
+#  Xen Hypercall abstraction lib for Intel architecture
+#
+#  Copyright (c) 2014, 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                    = 0x00010005
+  BASE_NAME                      = XenHypercallLibIntel
+  FILE_GUID                      = B5EE9A32-CA5A-49A8-82E3-ADA4CCB77C7C
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = XenHypercallLib|DXE_DRIVER UEFI_DRIVER
+  CONSTRUCTOR                    = XenHypercallLibIntelInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  XenHypercallIntel.c
+
+[Sources.IA32]
+  Ia32/hypercall.nasm
+
+[Sources.X64]
+  X64/hypercall.nasm
+
+[Sources]
+  XenHypercall.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  HobLib
+  DebugLib
+
+[Guids]
+  gEfiXenInfoGuid
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 6eb551a8d436..30a9fb1e9b42 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -44,6 +44,10 @@
   #
   SerializeVariablesLib|Include/Library/SerializeVariablesLib.h
 
+  ##  @libraryclass  Invoke Xen hypercalls
+  #
+  XenHypercallLib|Include/Library/XenHypercallLib.h
+
 [Guids]
   gUefiOvmfPkgTokenSpaceGuid      = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
   gEfiXenInfoGuid                 = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index ca656698754b..90540272745c 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -128,6 +128,7 @@
   S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
   SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
   OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
+  XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
 
 [LibraryClasses.common]
 !if $(SECURE_BOOT_ENABLE) == TRUE
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 4b4a1da717c1..0a331eda8be0 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -133,6 +133,7 @@
   S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
   SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
   OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
+  XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
 
 [LibraryClasses.common]
 !if $(SECURE_BOOT_ENABLE) == TRUE
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index eb3f34b8350b..e2b37c271681 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -133,6 +133,7 @@
   S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
   SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
   OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
+  XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
 
 [LibraryClasses.common]
 !if $(SECURE_BOOT_ENABLE) == TRUE
diff --git a/OvmfPkg/XenBusDxe/EventChannel.c b/OvmfPkg/XenBusDxe/EventChannel.c
index a86323e6adfd..6a36dca29911 100644
--- a/OvmfPkg/XenBusDxe/EventChannel.c
+++ b/OvmfPkg/XenBusDxe/EventChannel.c
@@ -16,7 +16,8 @@
 
 **/
 #include "EventChannel.h"
-#include "XenHypercall.h"
+
+#include <Library/XenHypercallLib.h>
 
 UINT32
 XenEventChannelNotify (
diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c
index 53cb99f0e004..a80d5eff39cd 100644
--- a/OvmfPkg/XenBusDxe/GrantTable.c
+++ b/OvmfPkg/XenBusDxe/GrantTable.c
@@ -34,7 +34,7 @@
 
 #include <IndustryStandard/Xen/memory.h>
 
-#include "XenHypercall.h"
+#include <Library/XenHypercallLib.h>
 
 #include "GrantTable.h"
 #include "InterlockedCompareExchange16.h"
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index d333b331b6db..cc334c086c1f 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -26,10 +26,10 @@
 #include <IndustryStandard/Pci.h>
 #include <IndustryStandard/Acpi.h>
 #include <Library/DebugLib.h>
+#include <Library/XenHypercallLib.h>
 
 #include "XenBusDxe.h"
 
-#include "XenHypercall.h"
 #include "GrantTable.h"
 #include "XenStore.h"
 #include "XenBus.h"
@@ -390,13 +390,6 @@ XenBusDxeDriverBindingStart (
   MmioAddr = BarDesc->AddrRangeMin;
   FreePool (BarDesc);
 
-  Status = XenHyperpageInit ();
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage.\n"));
-    Status = EFI_UNSUPPORTED;
-    goto ErrorAllocated;
-  }
-
   Status = XenGetSharedInfoPage (Dev);
   if (EFI_ERROR (Status)) {
     DEBUG ((EFI_D_ERROR, "XenBus: Unable to get the shared info page.\n"));
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index 4ce474345452..714607dbd6f8 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -34,8 +34,6 @@
   DriverBinding.h
   ComponentName.c
   ComponentName.h
-  XenHypercall.c
-  XenHypercall.h
   InterlockedCompareExchange16.c
   InterlockedCompareExchange16.h
   GrantTable.c
@@ -49,12 +47,10 @@
   Helpers.c
 
 [Sources.IA32]
-  Ia32/hypercall.nasm
   Ia32/InterlockedCompareExchange16.nasm
   Ia32/TestAndClearBit.nasm
 
 [Sources.X64]
-  X64/hypercall.nasm
   X64/InterlockedCompareExchange16.nasm
   X64/TestAndClearBit.nasm
 
@@ -67,8 +63,7 @@
   UefiLib
   DevicePathLib
   DebugLib
-  HobLib
-
+  XenHypercallLib
 
 [Protocols]
   gEfiDriverBindingProtocolGuid
@@ -77,7 +72,3 @@
   gEfiComponentNameProtocolGuid
   gXenBusProtocolGuid
 
-
-[Guids]
-  gEfiXenInfoGuid
-
diff --git a/OvmfPkg/XenBusDxe/XenStore.c b/OvmfPkg/XenBusDxe/XenStore.c
index 7ec1e634bc5c..9850f1e644fc 100644
--- a/OvmfPkg/XenBusDxe/XenStore.c
+++ b/OvmfPkg/XenBusDxe/XenStore.c
@@ -60,8 +60,8 @@
 
 #include <IndustryStandard/Xen/hvm/params.h>
 
-#include "XenHypercall.h"
 #include "EventChannel.h"
+#include <Library/XenHypercallLib.h>
 
 //
 // Private Data Structures
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 19/29] Ovmf/Xen: introduce XENIO_PROTOCOL
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (17 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 18/29] Ovmf/Xen: move XenBusDxe hypercall code to separate library Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-19 17:30   ` Anthony PERARD
  2015-02-12 11:19 ` [PATCH v4 20/29] Ovmf/Xen: add separate driver for Xen PCI device Ard Biesheuvel
                   ` (19 subsequent siblings)
  38 siblings, 1 reply; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This introduces the abstract XENIO_PROTOCOL that will be used to
communicate the Xen grant table address to drivers supporting this
protocol. Primary purpose is allowing us to change the XenBusDxe
implementation so that it can support non-PCI Xen implementations
such as Xen on ARM.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/Include/Protocol/XenIo.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/OvmfPkg.dec              |  1 +
 2 files changed, 49 insertions(+)

diff --git a/OvmfPkg/Include/Protocol/XenIo.h b/OvmfPkg/Include/Protocol/XenIo.h
new file mode 100644
index 000000000000..510391f3b3e8
--- /dev/null
+++ b/OvmfPkg/Include/Protocol/XenIo.h
@@ -0,0 +1,48 @@
+/** @file
+  XenIo protocol to abstract arch specific details
+
+  The Xen implementations for the Intel and ARM archictures differ in the way
+  the base address of the grant table is communicated to the guest. The former
+  uses a virtual PCI device, while the latter uses a device tree node.
+  In order to allow the XenBusDxe UEFI driver to be reused for the non-PCI
+  Xen implementation, this abstract protocol can be installed on a handle
+  with the appropriate base address.
+
+  Copyright (C) 2014, Linaro Ltd.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PROTOCOL_XENIO_H__
+#define __PROTOCOL_XENIO_H__
+
+#include <IndustryStandard/Xen/xen.h>
+
+#define XENIO_PROTOCOL_GUID \
+  {0x6efac84f, 0x0ab0, 0x4747, {0x81, 0xbe, 0x85, 0x55, 0x62, 0x59, 0x04, 0x49}}
+
+///
+/// Forward declaration
+///
+typedef struct _XENIO_PROTOCOL XENIO_PROTOCOL;
+
+///
+/// Protocol structure
+///
+struct _XENIO_PROTOCOL {
+  //
+  // Protocol data fields
+  //
+  EFI_PHYSICAL_ADDRESS          GrantTableAddress;
+};
+
+extern EFI_GUID gXenIoProtocolGuid;
+
+#endif
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 30a9fb1e9b42..3711fa922311 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -58,6 +58,7 @@
   gVirtioDeviceProtocolGuid       = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}
   gBlockMmioProtocolGuid          = {0x6b558ce3, 0x69e5, 0x4c67, {0xa6, 0x34, 0xf7, 0xfe, 0x72, 0xad, 0xbe, 0x84}}
   gXenBusProtocolGuid             = {0x3d3ca290, 0xb9a5, 0x11e3, {0xb7, 0x5d, 0xb8, 0xac, 0x6f, 0x7d, 0x65, 0xe6}}
+  gXenIoProtocolGuid              = {0x6efac84f, 0x0ab0, 0x4747, {0x81, 0xbe, 0x85, 0x55, 0x62, 0x59, 0x04, 0x49}}
 
 [PcdsFixedAtBuild]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 20/29] Ovmf/Xen: add separate driver for Xen PCI device
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (18 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 19/29] Ovmf/Xen: introduce XENIO_PROTOCOL Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 21/29] Ovmf/Xen: move XenBusDxe to abstract XENIO_PROTOCOL Ard Biesheuvel
                   ` (18 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

Prepare for making XenBusDxe suitable for use with non-PCI devices
(such as the DT node exposed by Xen on ARM) by introducing a separate
DXE driver that binds to the Xen virtual PCI device and exposes the
abstract XENIO_PROTOCOL for XenBusDxe to bind against.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/XenIoPciDxe/XenIoPciDxe.c   | 367 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf |  45 +++++++++++++++++
 2 files changed, 412 insertions(+)

diff --git a/OvmfPkg/XenIoPciDxe/XenIoPciDxe.c b/OvmfPkg/XenIoPciDxe/XenIoPciDxe.c
new file mode 100644
index 000000000000..c205cf74db34
--- /dev/null
+++ b/OvmfPkg/XenIoPciDxe/XenIoPciDxe.c
@@ -0,0 +1,367 @@
+/** @file
+
+  Driver for the virtual Xen PCI device
+
+  Copyright (C) 2012, Red Hat, Inc.
+  Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2013, ARM Ltd.
+  Copyright (C) 2015, Linaro Ltd.
+
+  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 <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/PciIo.h>
+#include <Protocol/XenIo.h>
+
+#define PCI_VENDOR_ID_XEN                0x5853
+#define PCI_DEVICE_ID_XEN_PLATFORM       0x0001
+
+/**
+
+  Device probe function for this driver.
+
+  The DXE core calls this function for any given device in order to see if the
+  driver can drive the device.
+
+  @param[in]  This                The EFI_DRIVER_BINDING_PROTOCOL object
+                                  incorporating this driver (independently of
+                                  any device).
+
+  @param[in] DeviceHandle         The device to probe.
+
+  @param[in] RemainingDevicePath  Relevant only for bus drivers, ignored.
+
+
+  @retval EFI_SUCCESS      The driver supports the device being probed.
+
+  @retval EFI_UNSUPPORTED  The driver does not support the device being probed.
+
+  @return                  Error codes from the OpenProtocol() boot service or
+                           the PciIo protocol.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+XenIoPciDeviceBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  DeviceHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  )
+{
+  EFI_STATUS          Status;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  PCI_TYPE00          Pci;
+
+  //
+  // Attempt to open the device with the PciIo set of interfaces. On success,
+  // the protocol is "instantiated" for the PCI device. Covers duplicate open
+  // attempts (EFI_ALREADY_STARTED).
+  //
+  Status = gBS->OpenProtocol (
+                  DeviceHandle,               // candidate device
+                  &gEfiPciIoProtocolGuid,     // for generic PCI access
+                  (VOID **)&PciIo,            // handle to instantiate
+                  This->DriverBindingHandle,  // requestor driver identity
+                  DeviceHandle,               // ControllerHandle, according to
+                                              // the UEFI Driver Model
+                  EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to
+                                              // the device; to be released
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Read entire PCI configuration header for more extensive check ahead.
+  //
+  Status = PciIo->Pci.Read (
+                        PciIo,                        // (protocol, device)
+                                                      // handle
+                        EfiPciIoWidthUint32,          // access width & copy
+                                                      // mode
+                        0,                            // Offset
+                        sizeof Pci / sizeof (UINT32), // Count
+                        &Pci                          // target buffer
+                        );
+
+  if (Status == EFI_SUCCESS) {
+    if ((Pci.Hdr.VendorId == PCI_VENDOR_ID_XEN) &&
+        (Pci.Hdr.DeviceId == PCI_DEVICE_ID_XEN_PLATFORM)) {
+      Status = EFI_SUCCESS;
+    } else {
+      Status = EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // We needed PCI IO access only transitorily, to see whether we support the
+  // device or not.
+  //
+  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle, DeviceHandle);
+
+  return Status;
+}
+
+/**
+
+  After we've pronounced support for a specific device in
+  DriverBindingSupported(), we start managing said device (passed in by the
+  Driver Exeuction Environment) with the following service.
+
+  See DriverBindingSupported() for specification references.
+
+  @param[in]  This                The EFI_DRIVER_BINDING_PROTOCOL object
+                                  incorporating this driver (independently of
+                                  any device).
+
+  @param[in] DeviceHandle         The supported device to drive.
+
+  @param[in] RemainingDevicePath  Relevant only for bus drivers, ignored.
+
+
+  @retval EFI_SUCCESS           The device was started.
+
+  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+
+  @return                       Error codes from the OpenProtocol() boot
+                                service, the PciIo protocol or the
+                                InstallProtocolInterface() boot service.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+XenIoPciDeviceBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  DeviceHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  )
+{
+  EFI_STATUS                        Status;
+  XENIO_PROTOCOL                    *XenIo;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
+
+  XenIo = (XENIO_PROTOCOL *) AllocateZeroPool (sizeof *XenIo);
+  if (XenIo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+                  (VOID **)&PciIo, This->DriverBindingHandle,
+                  DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+  if (EFI_ERROR (Status)) {
+    goto FreeXenIo;
+  }
+
+  //
+  // The BAR1 of this PCI device is used for shared memory and is supposed to
+  // look like MMIO. The address space of the BAR1 will be used to map the
+  // Grant Table.
+  //
+  Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
+
+  /* Get a Memory address for mapping the Grant Table. */
+  DEBUG ((EFI_D_INFO, "XenIoPci: BAR at %LX\n", BarDesc->AddrRangeMin));
+  XenIo->GrantTableAddress = BarDesc->AddrRangeMin;
+  FreePool (BarDesc);
+
+  Status = gBS->InstallProtocolInterface (&DeviceHandle,
+             &gXenIoProtocolGuid, EFI_NATIVE_INTERFACE, XenIo);
+
+  if (!EFI_ERROR (Status)) {
+    return EFI_SUCCESS;
+  }
+
+  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle, DeviceHandle);
+
+FreeXenIo:
+  FreePool (XenIo);
+
+  return Status;
+}
+
+/**
+
+  Stop driving the XenIo PCI device
+
+  @param[in] This               The EFI_DRIVER_BINDING_PROTOCOL object
+                                incorporating this driver (independently of any
+                                device).
+
+  @param[in] DeviceHandle       Stop driving this device.
+
+  @param[in] NumberOfChildren   Since this function belongs to a device driver
+                                only (as opposed to a bus driver), the caller
+                                environment sets NumberOfChildren to zero, and
+                                we ignore it.
+
+  @param[in] ChildHandleBuffer  Ignored (corresponding to NumberOfChildren).
+
+  @retval EFI_SUCCESS           Driver instance has been stopped and the PCI
+                                configuration attributes have been restored.
+
+  @return                       Error codes from the OpenProtocol() or
+                                CloseProtocol(), UninstallProtocolInterface()
+                                boot services.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+XenIoPciDeviceBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  DeviceHandle,
+  IN UINTN                       NumberOfChildren,
+  IN EFI_HANDLE                  *ChildHandleBuffer
+  )
+{
+  EFI_STATUS               Status;
+  XENIO_PROTOCOL           *XenIo;
+
+  Status = gBS->OpenProtocol (
+                  DeviceHandle,                  // candidate device
+                  &gXenIoProtocolGuid,           // retrieve the XenIo iface
+                  (VOID **)&XenIo,               // target pointer
+                  This->DriverBindingHandle,     // requestor driver identity
+                  DeviceHandle,                  // requesting lookup for dev.
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Handle Stop() requests for in-use driver instances gracefully.
+  //
+  Status = gBS->UninstallProtocolInterface (DeviceHandle,
+                  &gXenIoProtocolGuid, XenIo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle, DeviceHandle);
+
+  FreePool (XenIo);
+
+  return Status;
+}
+
+
+//
+// The static object that groups the Supported() (ie. probe), Start() and
+// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
+// C, 10.1 EFI Driver Binding Protocol.
+//
+STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+  &XenIoPciDeviceBindingSupported,
+  &XenIoPciDeviceBindingStart,
+  &XenIoPciDeviceBindingStop,
+  0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
+  NULL, // ImageHandle, to be overwritten by
+        // EfiLibInstallDriverBindingComponentName2() in XenIoPciDeviceEntryPoint()
+  NULL  // DriverBindingHandle, ditto
+};
+
+
+//
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
+// in English, for display on standard console devices. This is recommended for
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
+//
+STATIC
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
+  { "eng;en", L"XenIo PCI Driver" },
+  { NULL,     NULL                }
+};
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+
+EFI_STATUS
+EFIAPI
+XenIoPciGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gComponentName) // Iso639Language
+           );
+}
+
+EFI_STATUS
+EFIAPI
+XenIoPciGetDeviceName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  EFI_HANDLE                  DeviceHandle,
+  IN  EFI_HANDLE                  ChildHandle,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **ControllerName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+  &XenIoPciGetDriverName,
+  &XenIoPciGetDeviceName,
+  "eng" // SupportedLanguages, ISO 639-2 language codes
+};
+
+STATIC
+EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &XenIoPciGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &XenIoPciGetDeviceName,
+  "en" // SupportedLanguages, RFC 4646 language codes
+};
+
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+XenIoPciDeviceEntryPoint (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  return EfiLibInstallDriverBindingComponentName2 (
+           ImageHandle,
+           SystemTable,
+           &gDriverBinding,
+           ImageHandle,
+           &gComponentName,
+           &gComponentName2
+           );
+}
diff --git a/OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf b/OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
new file mode 100644
index 000000000000..b32075a38163
--- /dev/null
+++ b/OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
@@ -0,0 +1,45 @@
+## @file
+#  Driver for the virtual Xen PCI device
+#
+#  Copyright (C) 2015, Linaro Ltd.
+#
+#  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               = 0x00010005
+  BASE_NAME                 = XenIoPciDxe
+  FILE_GUID                 = cf569f50-de44-4f54-b4d7-f4ae25cda599
+  MODULE_TYPE               = UEFI_DRIVER
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = XenIoPciDeviceEntryPoint
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[Sources]
+  XenIoPciDxe.c
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  UefiLib
+  DebugLib
+
+[Protocols]
+  gEfiDriverBindingProtocolGuid
+  gEfiPciIoProtocolGuid
+  gEfiComponentName2ProtocolGuid
+  gEfiComponentNameProtocolGuid
+  gXenIoProtocolGuid
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 21/29] Ovmf/Xen: move XenBusDxe to abstract XENIO_PROTOCOL
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (19 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 20/29] Ovmf/Xen: add separate driver for Xen PCI device Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 22/29] Ovmf/Xen: implement XenHypercallLib for ARM Ard Biesheuvel
                   ` (17 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

While Xen on Intel uses a virtual PCI device to communicate the
base address of the grant table, the ARM implementation uses a DT
node, which is fundamentally incompatible with the way XenBusDxe is
implemented, i.e., as a UEFI Driver Model implementation for a PCI
device.

Contributed-under: TianoCore Contribution Agreement 1.0
Acked-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/OvmfPkgIa32.dsc           |  1 +
 OvmfPkg/OvmfPkgIa32.fdf           |  1 +
 OvmfPkg/OvmfPkgIa32X64.dsc        |  1 +
 OvmfPkg/OvmfPkgIa32X64.fdf        |  1 +
 OvmfPkg/OvmfPkgX64.dsc            |  1 +
 OvmfPkg/OvmfPkgX64.fdf            |  1 +
 OvmfPkg/XenBusDxe/ComponentName.c |  2 +-
 OvmfPkg/XenBusDxe/GrantTable.c    |  5 ++---
 OvmfPkg/XenBusDxe/GrantTable.h    |  3 +--
 OvmfPkg/XenBusDxe/XenBus.c        |  6 +++---
 OvmfPkg/XenBusDxe/XenBusDxe.c     | 55 +++++++++++++------------------------------------------
 OvmfPkg/XenBusDxe/XenBusDxe.h     |  8 ++------
 OvmfPkg/XenBusDxe/XenBusDxe.inf   |  2 +-
 13 files changed, 29 insertions(+), 58 deletions(-)

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 90540272745c..8c880613851d 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -444,6 +444,7 @@
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+  OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
   OvmfPkg/XenBusDxe/XenBusDxe.inf
   OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index f47e7ddc7834..ecef963d1e85 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -227,6 +227,7 @@ INF  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
 INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF  OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
 INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
 INF  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 0a331eda8be0..ff32ecefd07b 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -451,6 +451,7 @@
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+  OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
   OvmfPkg/XenBusDxe/XenBusDxe.inf
   OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 4c034460d5d2..29414ff04082 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -227,6 +227,7 @@ INF  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
 INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF  OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
 INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
 INF  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index e2b37c271681..8bac6dc313f0 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -449,6 +449,7 @@
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+  OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
   OvmfPkg/XenBusDxe/XenBusDxe.inf
   OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 2323eb2edf33..f1feb698ba66 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -227,6 +227,7 @@ INF  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
 INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF  OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
 INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
 INF  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 
diff --git a/OvmfPkg/XenBusDxe/ComponentName.c b/OvmfPkg/XenBusDxe/ComponentName.c
index 4530509e65dc..3f2dd406c77d 100644
--- a/OvmfPkg/XenBusDxe/ComponentName.c
+++ b/OvmfPkg/XenBusDxe/ComponentName.c
@@ -155,7 +155,7 @@ XenBusDxeComponentNameGetControllerName (
   Status = EfiTestManagedDevice (
              ControllerHandle,
              gXenBusDxeDriverBinding.DriverBindingHandle,
-             &gEfiPciIoProtocolGuid
+             &gXenIoProtocolGuid
              );
   if (EFI_ERROR (Status)) {
     return Status;
diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c
index a80d5eff39cd..19117fbe0373 100644
--- a/OvmfPkg/XenBusDxe/GrantTable.c
+++ b/OvmfPkg/XenBusDxe/GrantTable.c
@@ -139,8 +139,7 @@ XenGrantTableEndAccess (
 
 VOID
 XenGrantTableInit (
-  IN XENBUS_DEVICE  *Dev,
-  IN UINT64         MmioAddr
+  IN XENBUS_DEVICE  *Dev
   )
 {
   xen_add_to_physmap_t Parameters;
@@ -155,7 +154,7 @@ XenGrantTableInit (
     XenGrantTablePutFreeEntry ((grant_ref_t)Index);
   }
 
-  GrantTable = (VOID*)(UINTN) MmioAddr;
+  GrantTable = (VOID*)(UINTN) Dev->XenIo->GrantTableAddress;
   for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {
     Parameters.domid = DOMID_SELF;
     Parameters.idx = Index;
diff --git a/OvmfPkg/XenBusDxe/GrantTable.h b/OvmfPkg/XenBusDxe/GrantTable.h
index 5772c56662df..194275ba7ed5 100644
--- a/OvmfPkg/XenBusDxe/GrantTable.h
+++ b/OvmfPkg/XenBusDxe/GrantTable.h
@@ -29,8 +29,7 @@
 **/
 VOID
 XenGrantTableInit (
-  IN XENBUS_DEVICE  *Dev,
-  IN UINT64         MmioAddr
+  IN XENBUS_DEVICE  *Dev
   );
 
 /**
diff --git a/OvmfPkg/XenBusDxe/XenBus.c b/OvmfPkg/XenBusDxe/XenBus.c
index f69c27dd184a..ee9526c33252 100644
--- a/OvmfPkg/XenBusDxe/XenBus.c
+++ b/OvmfPkg/XenBusDxe/XenBus.c
@@ -138,7 +138,7 @@ XenBusAddDevice (
   XENBUS_PRIVATE_DATA *Private;
   EFI_STATUS Status;
   XENBUS_DEVICE_PATH *TempXenBusPath;
-  VOID *ChildPciIo;
+  VOID *ChildXenIo;
 
   AsciiSPrint (DevicePath, sizeof (DevicePath),
                "device/%a/%a", Type, Id);
@@ -208,8 +208,8 @@ XenBusAddDevice (
     }
 
     Status = gBS->OpenProtocol (Dev->ControllerHandle,
-               &gEfiPciIoProtocolGuid,
-               &ChildPciIo, Dev->This->DriverBindingHandle,
+               &gXenIoProtocolGuid,
+               &ChildXenIo, Dev->This->DriverBindingHandle,
                Private->Handle,
                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
     if (EFI_ERROR (Status)) {
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index cc334c086c1f..2c4a08673ce6 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -23,8 +23,6 @@
 
 **/
 
-#include <IndustryStandard/Pci.h>
-#include <IndustryStandard/Acpi.h>
 #include <Library/DebugLib.h>
 #include <Library/XenHypercallLib.h>
 
@@ -233,34 +231,22 @@ XenBusDxeDriverBindingSupported (
   )
 {
   EFI_STATUS          Status;
-  EFI_PCI_IO_PROTOCOL *PciIo;
-  PCI_TYPE00          Pci;
+  XENIO_PROTOCOL      *XenIo;
 
   Status = gBS->OpenProtocol (
                      ControllerHandle,
-                     &gEfiPciIoProtocolGuid,
-                     (VOID **)&PciIo,
+                     &gXenIoProtocolGuid,
+                     (VOID **)&XenIo,
                      This->DriverBindingHandle,
                      ControllerHandle,
                      EFI_OPEN_PROTOCOL_BY_DRIVER
                      );
+
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0,
-                            sizeof Pci / sizeof (UINT32), &Pci);
-
-  if (Status == EFI_SUCCESS) {
-    if (Pci.Hdr.VendorId == PCI_VENDOR_ID_XEN &&
-        Pci.Hdr.DeviceId == PCI_DEVICE_ID_XEN_PLATFORM) {
-      Status = EFI_SUCCESS;
-    } else {
-      Status = EFI_UNSUPPORTED;
-    }
-  }
-
-  gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
+  gBS->CloseProtocol (ControllerHandle, &gXenIoProtocolGuid,
          This->DriverBindingHandle, ControllerHandle);
 
   return Status;
@@ -326,19 +312,18 @@ XenBusDxeDriverBindingStart (
 {
   EFI_STATUS Status;
   XENBUS_DEVICE *Dev;
-  EFI_PCI_IO_PROTOCOL *PciIo;
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
-  UINT64 MmioAddr;
+  XENIO_PROTOCOL *XenIo;
   EFI_DEVICE_PATH_PROTOCOL *DevicePath;
 
   Status = gBS->OpenProtocol (
                      ControllerHandle,
-                     &gEfiPciIoProtocolGuid,
-                     (VOID **) &PciIo,
+                     &gXenIoProtocolGuid,
+                     (VOID**)&XenIo,
                      This->DriverBindingHandle,
                      ControllerHandle,
                      EFI_OPEN_PROTOCOL_BY_DRIVER
                      );
+
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -360,7 +345,7 @@ XenBusDxeDriverBindingStart (
   Dev->Signature = XENBUS_DEVICE_SIGNATURE;
   Dev->This = This;
   Dev->ControllerHandle = ControllerHandle;
-  Dev->PciIo = PciIo;
+  Dev->XenIo = XenIo;
   Dev->DevicePath = DevicePath;
   InitializeListHead (&Dev->ChildList);
 
@@ -376,20 +361,6 @@ XenBusDxeDriverBindingStart (
   mMyDevice = Dev;
   EfiReleaseLock (&mMyDeviceLock);
 
-  //
-  // The BAR1 of this PCI device is used for shared memory and is supposed to
-  // look like MMIO. The address space of the BAR1 will be used to map the
-  // Grant Table.
-  //
-  Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc);
-  ASSERT_EFI_ERROR (Status);
-  ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
-
-  /* Get a Memory address for mapping the Grant Table. */
-  DEBUG ((EFI_D_INFO, "XenBus: BAR at %LX\n", BarDesc->AddrRangeMin));
-  MmioAddr = BarDesc->AddrRangeMin;
-  FreePool (BarDesc);
-
   Status = XenGetSharedInfoPage (Dev);
   if (EFI_ERROR (Status)) {
     DEBUG ((EFI_D_ERROR, "XenBus: Unable to get the shared info page.\n"));
@@ -397,7 +368,7 @@ XenBusDxeDriverBindingStart (
     goto ErrorAllocated;
   }
 
-  XenGrantTableInit (Dev, MmioAddr);
+  XenGrantTableInit (Dev);
 
   Status = XenStoreInit (Dev);
   ASSERT_EFI_ERROR (Status);
@@ -417,7 +388,7 @@ ErrorAllocated:
   gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid,
                       This->DriverBindingHandle, ControllerHandle);
 ErrorOpenningProtocol:
-  gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
+  gBS->CloseProtocol (ControllerHandle, &gXenIoProtocolGuid,
                       This->DriverBindingHandle, ControllerHandle);
   return Status;
 }
@@ -507,7 +478,7 @@ XenBusDxeDriverBindingStop (
 
   gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid,
          This->DriverBindingHandle, ControllerHandle);
-  gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
+  gBS->CloseProtocol (ControllerHandle, &gXenIoProtocolGuid,
          This->DriverBindingHandle, ControllerHandle);
 
   mMyDevice = NULL;
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 9b7219906a69..6c306e017b07 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -39,7 +39,7 @@
 //
 // Consumed Protocols
 //
-#include <Protocol/PciIo.h>
+#include <Protocol/XenIo.h>
 
 
 //
@@ -73,10 +73,6 @@ extern EFI_COMPONENT_NAME_PROTOCOL  gXenBusDxeComponentName;
 //
 #include <IndustryStandard/Xen/xen.h>
 
-#define PCI_VENDOR_ID_XEN                0x5853
-#define PCI_DEVICE_ID_XEN_PLATFORM       0x0001
-
-
 typedef struct _XENBUS_DEVICE_PATH XENBUS_DEVICE_PATH;
 typedef struct _XENBUS_DEVICE XENBUS_DEVICE;
 
@@ -86,7 +82,7 @@ struct _XENBUS_DEVICE {
   UINT32                        Signature;
   EFI_DRIVER_BINDING_PROTOCOL   *This;
   EFI_HANDLE                    ControllerHandle;
-  EFI_PCI_IO_PROTOCOL           *PciIo;
+  XENIO_PROTOCOL                *XenIo;
   EFI_EVENT                     ExitBootEvent;
   EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
   LIST_ENTRY                    ChildList;
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index 714607dbd6f8..31553ac5a64a 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -67,8 +67,8 @@
 
 [Protocols]
   gEfiDriverBindingProtocolGuid
-  gEfiPciIoProtocolGuid
   gEfiComponentName2ProtocolGuid
   gEfiComponentNameProtocolGuid
   gXenBusProtocolGuid
+  gXenIoProtocolGuid
 
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 22/29] Ovmf/Xen: implement XenHypercallLib for ARM
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (20 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 21/29] Ovmf/Xen: move XenBusDxe to abstract XENIO_PROTOCOL Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 23/29] Ovmf/Xen: port XenBusDxe to other architectures Ard Biesheuvel
                   ` (16 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This patch adds an implementation of XenHypercallLib for both
AArch64 and AArch32 execution modes on ARM systems.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h    | 436 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/Include/IndustryStandard/Xen/xen.h             |   2 +-
 OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S    |  26 +++++++
 OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S        |  25 +++++++
 OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf |  40 +++++++++++
 5 files changed, 528 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h
new file mode 100644
index 000000000000..655a221f6337
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h
@@ -0,0 +1,436 @@
+/******************************************************************************
+ * arch-arm.h
+ *
+ * Guest OS interface to ARM Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright 2011 (C) Citrix Systems
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_ARM_H__
+#define __XEN_PUBLIC_ARCH_ARM_H__
+
+/*
+ * `incontents 50 arm_abi Hypercall Calling Convention
+ *
+ * A hypercall is issued using the ARM HVC instruction.
+ *
+ * A hypercall can take up to 5 arguments. These are passed in
+ * registers, the first argument in x0/r0 (for arm64/arm32 guests
+ * respectively irrespective of whether the underlying hypervisor is
+ * 32- or 64-bit), the second argument in x1/r1, the third in x2/r2,
+ * the forth in x3/r3 and the fifth in x4/r4.
+ *
+ * The hypercall number is passed in r12 (arm) or x16 (arm64). In both
+ * cases the relevant ARM procedure calling convention specifies this
+ * is an inter-procedure-call scratch register (e.g. for use in linker
+ * stubs). This use does not conflict with use during a hypercall.
+ *
+ * The HVC ISS must contain a Xen specific TAG: XEN_HYPERCALL_TAG.
+ *
+ * The return value is in x0/r0.
+ *
+ * The hypercall will clobber x16/r12 and the argument registers used
+ * by that hypercall (except r0 which is the return value) i.e. in
+ * addition to x16/r12 a 2 argument hypercall will clobber x1/r1 and a
+ * 4 argument hypercall will clobber x1/r1, x2/r2 and x3/r3.
+ *
+ * Parameter structs passed to hypercalls are laid out according to
+ * the Procedure Call Standard for the ARM Architecture (AAPCS, AKA
+ * EABI) and Procedure Call Standard for the ARM 64-bit Architecture
+ * (AAPCS64). Where there is a conflict the 64-bit standard should be
+ * used regardless of guest type. Structures which are passed as
+ * hypercall arguments are always little endian.
+ *
+ * All memory which is shared with other entities in the system
+ * (including the hypervisor and other guests) must reside in memory
+ * which is mapped as Normal Inner-cacheable. This applies to:
+ *  - hypercall arguments passed via a pointer to guest memory.
+ *  - memory shared via the grant table mechanism (including PV I/O
+ *    rings etc).
+ *  - memory shared with the hypervisor (struct shared_info, struct
+ *    vcpu_info, the grant table, etc).
+ *
+ * Any Inner cache allocation strategy (Write-Back, Write-Through etc)
+ * is acceptable. There is no restriction on the Outer-cacheability.
+ */
+
+/*
+ * `incontents 55 arm_hcall Supported Hypercalls
+ *
+ * Xen on ARM makes extensive use of hardware facilities and therefore
+ * only a subset of the potential hypercalls are required.
+ *
+ * Since ARM uses second stage paging any machine/physical addresses
+ * passed to hypercalls are Guest Physical Addresses (Intermediate
+ * Physical Addresses) unless otherwise noted.
+ *
+ * The following hypercalls (and sub operations) are supported on the
+ * ARM platform. Other hypercalls should be considered
+ * unavailable/unsupported.
+ *
+ *  HYPERVISOR_memory_op
+ *   All generic sub-operations.
+ *
+ *   In addition the following arch specific sub-ops:
+ *    * XENMEM_add_to_physmap
+ *    * XENMEM_add_to_physmap_batch
+ *
+ *  HYPERVISOR_domctl
+ *   All generic sub-operations, with the exception of:
+ *    * XEN_DOMCTL_iomem_permission (not yet implemented)
+ *    * XEN_DOMCTL_irq_permission (not yet implemented)
+ *
+ *  HYPERVISOR_sched_op
+ *   All generic sub-operations, with the exception of:
+ *    * SCHEDOP_block -- prefer wfi hardware instruction
+ *
+ *  HYPERVISOR_console_io
+ *   All generic sub-operations
+ *
+ *  HYPERVISOR_xen_version
+ *   All generic sub-operations
+ *
+ *  HYPERVISOR_event_channel_op
+ *   All generic sub-operations
+ *
+ *  HYPERVISOR_physdev_op
+ *   No sub-operations are currenty supported
+ *
+ *  HYPERVISOR_sysctl
+ *   All generic sub-operations, with the exception of:
+ *    * XEN_SYSCTL_page_offline_op
+ *    * XEN_SYSCTL_get_pmstat
+ *    * XEN_SYSCTL_pm_op
+ *
+ *  HYPERVISOR_hvm_op
+ *   Exactly these sub-operations are supported:
+ *    * HVMOP_set_param
+ *    * HVMOP_get_param
+ *
+ *  HYPERVISOR_grant_table_op
+ *   All generic sub-operations
+ *
+ *  HYPERVISOR_vcpu_op
+ *   Exactly these sub-operations are supported:
+ *    * VCPUOP_register_vcpu_info
+ *    * VCPUOP_register_runstate_memory_area
+ *
+ *
+ * Other notes on the ARM ABI:
+ *
+ * - struct start_info is not exported to ARM guests.
+ *
+ * - struct shared_info is mapped by ARM guests using the
+ *   HYPERVISOR_memory_op sub-op XENMEM_add_to_physmap, passing
+ *   XENMAPSPACE_shared_info as space parameter.
+ *
+ * - All the per-cpu struct vcpu_info are mapped by ARM guests using the
+ *   HYPERVISOR_vcpu_op sub-op VCPUOP_register_vcpu_info, including cpu0
+ *   struct vcpu_info.
+ *
+ * - The grant table is mapped using the HYPERVISOR_memory_op sub-op
+ *   XENMEM_add_to_physmap, passing XENMAPSPACE_grant_table as space
+ *   parameter. The memory range specified under the Xen compatible
+ *   hypervisor node on device tree can be used as target gpfn for the
+ *   mapping.
+ *
+ * - Xenstore is initialized by using the two hvm_params
+ *   HVM_PARAM_STORE_PFN and HVM_PARAM_STORE_EVTCHN. They can be read
+ *   with the HYPERVISOR_hvm_op sub-op HVMOP_get_param.
+ *
+ * - The paravirtualized console is initialized by using the two
+ *   hvm_params HVM_PARAM_CONSOLE_PFN and HVM_PARAM_CONSOLE_EVTCHN. They
+ *   can be read with the HYPERVISOR_hvm_op sub-op HVMOP_get_param.
+ *
+ * - Event channel notifications are delivered using the percpu GIC
+ *   interrupt specified under the Xen compatible hypervisor node on
+ *   device tree.
+ *
+ * - The device tree Xen compatible node is fully described under Linux
+ *   at Documentation/devicetree/bindings/arm/xen.txt.
+ */
+
+#define XEN_HYPERCALL_TAG   0XEA1
+
+#define uint64_aligned_t UINT64 __attribute__((aligned(8)))
+
+#ifndef __ASSEMBLY__
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type)                  \
+    typedef union { type *p; unsigned long q; }                 \
+        __guest_handle_ ## name;                                \
+    typedef union { type *p; uint64_aligned_t q; }              \
+        __guest_handle_64_ ## name;
+
+/*
+ * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
+ * in a struct in memory. On ARM is always 8 bytes sizes and 8 bytes
+ * aligned.
+ * XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an
+ * hypercall argument. It is 4 bytes on aarch and 8 bytes on aarch64.
+ */
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
+    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
+#define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define __XEN_GUEST_HANDLE(name)        __guest_handle_64_ ## name
+#define XEN_GUEST_HANDLE(name)          __XEN_GUEST_HANDLE(name)
+/* this is going to be changed on 64 bit */
+#define XEN_GUEST_HANDLE_PARAM(name)    __guest_handle_ ## name
+#define set_xen_guest_handle_raw(hnd, val)                  \
+    do {                                                    \
+        typeof(&(hnd)) _sxghr_tmp = &(hnd);                 \
+        _sxghr_tmp->q = 0;                                  \
+        _sxghr_tmp->p = val;                                \
+    } while ( 0 )
+#ifdef __XEN_TOOLS__
+#define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
+#endif
+#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/* Anonymous union includes both 32- and 64-bit names (e.g., r0/x0). */
+# define __DECL_REG(n64, n32) union {          \
+        UINT64 n64;                          \
+        UINT32 n32;                          \
+    }
+#else
+/* Non-gcc sources must always use the proper 64-bit name (e.g., x0). */
+#define __DECL_REG(n64, n32) UINT64 n64
+#endif
+
+struct vcpu_guest_core_regs
+{
+    /*         Aarch64       Aarch32 */
+    __DECL_REG(x0,           r0_usr);
+    __DECL_REG(x1,           r1_usr);
+    __DECL_REG(x2,           r2_usr);
+    __DECL_REG(x3,           r3_usr);
+    __DECL_REG(x4,           r4_usr);
+    __DECL_REG(x5,           r5_usr);
+    __DECL_REG(x6,           r6_usr);
+    __DECL_REG(x7,           r7_usr);
+    __DECL_REG(x8,           r8_usr);
+    __DECL_REG(x9,           r9_usr);
+    __DECL_REG(x10,          r10_usr);
+    __DECL_REG(x11,          r11_usr);
+    __DECL_REG(x12,          r12_usr);
+
+    __DECL_REG(x13,          sp_usr);
+    __DECL_REG(x14,          lr_usr);
+
+    __DECL_REG(x15,          __unused_sp_hyp);
+
+    __DECL_REG(x16,          lr_irq);
+    __DECL_REG(x17,          sp_irq);
+
+    __DECL_REG(x18,          lr_svc);
+    __DECL_REG(x19,          sp_svc);
+
+    __DECL_REG(x20,          lr_abt);
+    __DECL_REG(x21,          sp_abt);
+
+    __DECL_REG(x22,          lr_und);
+    __DECL_REG(x23,          sp_und);
+
+    __DECL_REG(x24,          r8_fiq);
+    __DECL_REG(x25,          r9_fiq);
+    __DECL_REG(x26,          r10_fiq);
+    __DECL_REG(x27,          r11_fiq);
+    __DECL_REG(x28,          r12_fiq);
+
+    __DECL_REG(x29,          sp_fiq);
+    __DECL_REG(x30,          lr_fiq);
+
+    /* Return address and mode */
+    __DECL_REG(pc64,         pc32);             /* ELR_EL2 */
+    UINT32 cpsr;                              /* SPSR_EL2 */
+
+    union {
+        UINT32 spsr_el1;       /* AArch64 */
+        UINT32 spsr_svc;       /* AArch32 */
+    };
+
+    /* AArch32 guests only */
+    UINT32 spsr_fiq, spsr_irq, spsr_und, spsr_abt;
+
+    /* AArch64 guests only */
+    UINT64 sp_el0;
+    UINT64 sp_el1, elr_el1;
+};
+typedef struct vcpu_guest_core_regs vcpu_guest_core_regs_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_core_regs_t);
+
+#undef __DECL_REG
+
+typedef UINT64 xen_pfn_t;
+#define PRI_xen_pfn PRIx64
+
+/* Maximum number of virtual CPUs in legacy multi-processor guests. */
+/* Only one. All other VCPUS must use VCPUOP_register_vcpu_info */
+#define XEN_LEGACY_MAX_VCPUS 1
+
+typedef UINT64 xen_ulong_t;
+#define PRI_xen_ulong PRIx64
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+struct vcpu_guest_context {
+#define _VGCF_online                   0
+#define VGCF_online                    (1<<_VGCF_online)
+    UINT32 flags;                         /* VGCF_* */
+
+    struct vcpu_guest_core_regs user_regs;  /* Core CPU registers */
+
+    UINT32 sctlr;
+    UINT64 ttbcr, ttbr0, ttbr1;
+};
+typedef struct vcpu_guest_context vcpu_guest_context_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+#endif
+
+struct arch_vcpu_info {
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+struct arch_shared_info {
+};
+typedef struct arch_shared_info arch_shared_info_t;
+typedef UINT64 xen_callback_t;
+
+#endif
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/* PSR bits (CPSR, SPSR)*/
+
+#define PSR_THUMB       (1<<5)        /* Thumb Mode enable */
+#define PSR_FIQ_MASK    (1<<6)        /* Fast Interrupt mask */
+#define PSR_IRQ_MASK    (1<<7)        /* Interrupt mask */
+#define PSR_ABT_MASK    (1<<8)        /* Asynchronous Abort mask */
+#define PSR_BIG_ENDIAN  (1<<9)        /* arm32: Big Endian Mode */
+#define PSR_DBG_MASK    (1<<9)        /* arm64: Debug Exception mask */
+#define PSR_IT_MASK     (0x0600fc00)  /* Thumb If-Then Mask */
+#define PSR_JAZELLE     (1<<24)       /* Jazelle Mode */
+
+/* 32 bit modes */
+#define PSR_MODE_USR 0x10
+#define PSR_MODE_FIQ 0x11
+#define PSR_MODE_IRQ 0x12
+#define PSR_MODE_SVC 0x13
+#define PSR_MODE_MON 0x16
+#define PSR_MODE_ABT 0x17
+#define PSR_MODE_HYP 0x1a
+#define PSR_MODE_UND 0x1b
+#define PSR_MODE_SYS 0x1f
+
+/* 64 bit modes */
+#define PSR_MODE_BIT  0x10 /* Set iff AArch32 */
+#define PSR_MODE_EL3h 0x0d
+#define PSR_MODE_EL3t 0x0c
+#define PSR_MODE_EL2h 0x09
+#define PSR_MODE_EL2t 0x08
+#define PSR_MODE_EL1h 0x05
+#define PSR_MODE_EL1t 0x04
+#define PSR_MODE_EL0t 0x00
+
+#define PSR_GUEST32_INIT  (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC)
+#define PSR_GUEST64_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_EL1h)
+
+#define SCTLR_GUEST_INIT    0x00c50078
+
+/*
+ * Virtual machine platform (memory layout, interrupts)
+ *
+ * These are defined for consistency between the tools and the
+ * hypervisor. Guests must not rely on these hardcoded values but
+ * should instead use the FDT.
+ */
+
+/* Physical Address Space */
+
+/* vGIC mappings: Only one set of mapping is used by the guest.
+ * Therefore they can overlap.
+ */
+
+/* vGIC v2 mappings */
+#define GUEST_GICD_BASE   0x03001000ULL
+#define GUEST_GICD_SIZE   0x00001000ULL
+#define GUEST_GICC_BASE   0x03002000ULL
+#define GUEST_GICC_SIZE   0x00000100ULL
+
+/* vGIC v3 mappings */
+#define GUEST_GICV3_GICD_BASE      0x03001000ULL
+#define GUEST_GICV3_GICD_SIZE      0x00010000ULL
+
+#define GUEST_GICV3_RDIST_STRIDE   0x20000ULL
+#define GUEST_GICV3_RDIST_REGIONS  1
+
+#define GUEST_GICV3_GICR0_BASE     0x03020000ULL    /* vCPU0 - vCPU7 */
+#define GUEST_GICV3_GICR0_SIZE     0x00100000ULL
+
+/* 16MB == 4096 pages reserved for guest to use as a region to map its
+ * grant table in.
+ */
+#define GUEST_GNTTAB_BASE 0x38000000ULL
+#define GUEST_GNTTAB_SIZE 0x01000000ULL
+
+#define GUEST_MAGIC_BASE  0x39000000ULL
+#define GUEST_MAGIC_SIZE  0x01000000ULL
+
+#define GUEST_RAM_BANKS   2
+
+#define GUEST_RAM0_BASE   0x40000000ULL /* 3GB of low RAM @ 1GB */
+#define GUEST_RAM0_SIZE   0xc0000000ULL
+
+#define GUEST_RAM1_BASE   0x0200000000ULL /* 1016GB of RAM @ 8GB */
+#define GUEST_RAM1_SIZE   0xfe00000000ULL
+
+#define GUEST_RAM_BASE    GUEST_RAM0_BASE /* Lowest RAM address */
+/* Largest amount of actual RAM, not including holes */
+#define GUEST_RAM_MAX     (GUEST_RAM0_SIZE + GUEST_RAM1_SIZE)
+/* Suitable for e.g. const uint64_t ramfoo[] = GUEST_RAM_BANK_FOOS; */
+#define GUEST_RAM_BANK_BASES   { GUEST_RAM0_BASE, GUEST_RAM1_BASE }
+#define GUEST_RAM_BANK_SIZES   { GUEST_RAM0_SIZE, GUEST_RAM1_SIZE }
+
+/* Interrupts */
+#define GUEST_TIMER_VIRT_PPI    27
+#define GUEST_TIMER_PHYS_S_PPI  29
+#define GUEST_TIMER_PHYS_NS_PPI 30
+#define GUEST_EVTCHN_PPI        31
+
+/* PSCI functions */
+#define PSCI_cpu_suspend 0
+#define PSCI_cpu_off     1
+#define PSCI_cpu_on      2
+#define PSCI_migrate     3
+
+#endif
+
+#endif /*  __XEN_PUBLIC_ARCH_ARM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/xen.h
index 1cd7ab3ab136..8596ca1bd26f 100644
--- a/OvmfPkg/Include/IndustryStandard/Xen/xen.h
+++ b/OvmfPkg/Include/IndustryStandard/Xen/xen.h
@@ -37,7 +37,7 @@
 #if defined(MDE_CPU_IA32) || defined(MDE_CPU_X64)
 #include "arch-x86/xen.h"
 #elif defined(__arm__) || defined (__aarch64__)
-#include "arch-arm.h"
+#include "arch-arm/xen.h"
 #else
 #error "Unsupported architecture"
 #endif
diff --git a/OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S b/OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S
new file mode 100644
index 000000000000..b1b5d4cc3f28
--- /dev/null
+++ b/OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S
@@ -0,0 +1,26 @@
+
+/** @file
+  AArch64 implementation of XenHypercall2
+
+  Copyright (C) 2014, Linaro Ltd.
+
+  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 <IndustryStandard/Xen/arch-arm/xen.h>
+
+  .text
+  .global   ASM_PFX(XenHypercall2)
+ASM_PFX(XenHypercall2):
+  mov     x16, x0
+  mov     x0, x1
+  mov     x1, x2
+  hvc     #XEN_HYPERCALL_TAG
+  ret
diff --git a/OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S b/OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S
new file mode 100644
index 000000000000..b38e1a8f18da
--- /dev/null
+++ b/OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S
@@ -0,0 +1,25 @@
+/** @file
+  ARM (AArch32) implementation of XenHypercall2
+
+  Copyright (C) 2014, Linaro Ltd.
+
+  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 <IndustryStandard/Xen/arch-arm/xen.h>
+
+  .text
+  .global   ASM_PFX(XenHypercall2)
+ASM_PFX(XenHypercall2):
+  mov     r12, r0
+  mov     r0, r1
+  mov     r1, r2
+  hvc     #XEN_HYPERCALL_TAG
+  bx      lr
diff --git a/OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf
new file mode 100644
index 000000000000..9cbbeb5d8789
--- /dev/null
+++ b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf
@@ -0,0 +1,40 @@
+## @file
+#  Xen Hypercall abstraction lib for ARM architecture
+#
+#  Copyright (c) 2014, 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                    = 0x00010005
+  BASE_NAME                      = XenHypercallLibArm
+  FILE_GUID                      = 9607AC2E-FCB9-499B-9475-612282019568
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = XenHypercallLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ARM AARCH64
+#
+
+[Sources.ARM]
+  Arm/Hypercall.S
+
+[Sources.AARCH64]
+  Aarch64/Hypercall.S
+
+[Sources]
+  XenHypercall.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 23/29] Ovmf/Xen: port XenBusDxe to other architectures
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (21 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 22/29] Ovmf/Xen: implement XenHypercallLib for ARM Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 24/29] Ovmf/Xen: add Xen PV console SerialPortLib driver Ard Biesheuvel
                   ` (15 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This patch updates XenBusDxe to use the 16-bit compare and exchange
function that was introduced for this purpose to the
BaseSynchronizationLib. It also provides a new generic implementation
of TestAndClearBit () using the same 16-bit compare and exchange, making
this module fully architecture agnostic.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/XenBusDxe/GrantTable.c                           |  2 +-
 OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm | 42 ------------------------------------------
 OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm              | 16 ----------------
 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c         | 33 ---------------------------------
 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h         | 38 --------------------------------------
 OvmfPkg/XenBusDxe/TestAndClearBit.c                      | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm  | 41 -----------------------------------------
 OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm               | 15 ---------------
 OvmfPkg/XenBusDxe/XenBusDxe.h                            |  2 +-
 OvmfPkg/XenBusDxe/XenBusDxe.inf                          | 12 ++----------
 10 files changed, 50 insertions(+), 197 deletions(-)

diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c
index 19117fbe0373..6e47483f136f 100644
--- a/OvmfPkg/XenBusDxe/GrantTable.c
+++ b/OvmfPkg/XenBusDxe/GrantTable.c
@@ -35,9 +35,9 @@
 #include <IndustryStandard/Xen/memory.h>
 
 #include <Library/XenHypercallLib.h>
+#include <Library/SynchronizationLib.h>
 
 #include "GrantTable.h"
-#include "InterlockedCompareExchange16.h"
 
 #define NR_RESERVED_ENTRIES 8
 
diff --git a/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm
deleted file mode 100644
index d45582dd8109..000000000000
--- a/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm
+++ /dev/null
@@ -1,42 +0,0 @@
-;------------------------------------------------------------------------------
-;
-; Copyright (c) 2006, Intel Corporation. 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.
-;
-; Module Name:
-;
-;   InterlockedCompareExchange16.Asm
-;
-; Abstract:
-;
-;   InterlockedCompareExchange16 function
-;
-; Notes:
-;
-;------------------------------------------------------------------------------
-
-    SECTION .text
-
-;------------------------------------------------------------------------------
-; UINT32
-; EFIAPI
-; InternalSyncCompareExchange16 (
-;   IN      UINT16                    *Value,
-;   IN      UINT16                    CompareValue,
-;   IN      UINT16                    ExchangeValue
-;   );
-;------------------------------------------------------------------------------
-global ASM_PFX(InternalSyncCompareExchange16)
-ASM_PFX(InternalSyncCompareExchange16):
-    mov     ecx, [esp + 4]
-    mov     eax, [esp + 8]
-    mov     edx, [esp + 12]
-    lock    cmpxchg [ecx], dx
-    ret
-
diff --git a/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm b/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm
deleted file mode 100644
index d77f74ef249d..000000000000
--- a/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm
+++ /dev/null
@@ -1,16 +0,0 @@
-SECTION .text
-
-; INT32
-; EFIAPI
-; TestAndClearBit (
-;   IN  INT32 Bit,
-;   IN  volatile VOID* Address
-;   );
-global ASM_PFX(TestAndClearBit)
-ASM_PFX(TestAndClearBit):
-  mov ecx, [esp + 4]
-  mov edx, [esp + 8]
-  lock btr [edx], ecx
-  sbb eax, eax
-  ret
-
diff --git a/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
deleted file mode 100644
index 2b0fadd88dd1..000000000000
--- a/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <Library/DebugLib.h>
-#include "InterlockedCompareExchange16.h"
-
-/**
-  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
-
-  Performs an atomic compare exchange operation on the 16-bit unsigned integer
-  specified by Value.  If Value is equal to CompareValue, then Value is set to
-  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
-  then Value is returned.  The compare exchange operation must be performed using
-  MP safe mechanisms.
-
-  If Value is NULL, then ASSERT().
-
-  @param  Value         A pointer to the 16-bit value for the compare exchange
-                        operation.
-  @param  CompareValue  16-bit value used in compare operation.
-  @param  ExchangeValue 16-bit value used in exchange operation.
-
-  @return The original *Value before exchange.
-
-**/
-UINT16
-EFIAPI
-InterlockedCompareExchange16 (
-  IN OUT  UINT16                    *Value,
-  IN      UINT16                    CompareValue,
-  IN      UINT16                    ExchangeValue
-  )
-{
-  ASSERT (Value != NULL);
-  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
-}
diff --git a/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h
deleted file mode 100644
index fd3f15b1c8d6..000000000000
--- a/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
-  Assembly implementation of InterlockedCompareExchange16.
-
-  Look at the documentation of InterlockedCompareExchange16.
-**/
-UINT16
-EFIAPI
-InternalSyncCompareExchange16 (
-  IN      volatile UINT16           *Value,
-  IN      UINT16                    CompareValue,
-  IN      UINT16                    ExchangeValue
-  );
-
-/**
-  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
-
-  Performs an atomic compare exchange operation on the 16-bit unsigned integer
-  specified by Value.  If Value is equal to CompareValue, then Value is set to
-  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
-  then Value is returned.  The compare exchange operation must be performed using
-  MP safe mechanisms.
-
-  If Value is NULL, then ASSERT().
-
-  @param  Value         A pointer to the 16-bit value for the compare exchange
-                        operation.
-  @param  CompareValue  16-bit value used in compare operation.
-  @param  ExchangeValue 16-bit value used in exchange operation.
-
-  @return The original *Value before exchange.
-**/
-UINT16
-EFIAPI
-InterlockedCompareExchange16 (
-  IN OUT  UINT16                    *Value,
-  IN      UINT16                    CompareValue,
-  IN      UINT16                    ExchangeValue
-  );
diff --git a/OvmfPkg/XenBusDxe/TestAndClearBit.c b/OvmfPkg/XenBusDxe/TestAndClearBit.c
new file mode 100644
index 000000000000..e971b40a89ce
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/TestAndClearBit.c
@@ -0,0 +1,46 @@
+/** @file
+  Implementation of TestAndClearBit using compare-exchange primitive
+
+  Copyright (C) 2015, Linaro Ltd.
+
+  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 <Base.h>
+#include <Library/SynchronizationLib.h>
+
+INT32
+EFIAPI
+TestAndClearBit (
+  IN INT32            Bit,
+  IN VOID             *Address
+  )
+{
+  UINT16    Word;
+  UINT16    Mask;
+
+  //
+  // Calculate the effective address relative to 'Address' based on the
+  // higher order bits of 'Bit'. Use signed shift instead of division to
+  // ensure we round towards -Inf, and end up with a positive shift in
+  // 'Bit', even if 'Bit' itself is negative.
+  //
+  Address += (Bit >> 4) * sizeof(UINT16);
+
+  Word = *(UINT16 *)Address;
+  Mask = 1U << (Bit & 15);
+
+  while (Word & Mask) {
+    if (Word == InterlockedCompareExchange16 (Address, Word, Word & ~Mask)) {
+      return 1;
+    }
+  }
+  return 0;
+}
diff --git a/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm
deleted file mode 100644
index 048d1f32f6b9..000000000000
--- a/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm
+++ /dev/null
@@ -1,41 +0,0 @@
-;------------------------------------------------------------------------------
-;
-; Copyright (c) 2006, Intel Corporation. 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.
-;
-; Module Name:
-;
-;   InterlockedCompareExchange16.Asm
-;
-; Abstract:
-;
-;   InterlockedCompareExchange16 function
-;
-; Notes:
-;
-;------------------------------------------------------------------------------
-
-    DEFAULT REL
-    SECTION .text
-
-;------------------------------------------------------------------------------
-; UINT16
-; EFIAPI
-; InterlockedCompareExchange16 (
-;   IN      UINT16                    *Value,
-;   IN      UINT16                    CompareValue,
-;   IN      UINT16                    ExchangeValue
-;   );
-;------------------------------------------------------------------------------
-global ASM_PFX(InternalSyncCompareExchange16)
-ASM_PFX(InternalSyncCompareExchange16):
-    mov     eax, edx
-    lock    cmpxchg [rcx], r8w
-    ret
-
diff --git a/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm b/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm
deleted file mode 100644
index a4859a62a250..000000000000
--- a/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm
+++ /dev/null
@@ -1,15 +0,0 @@
-DEFAULT REL
-SECTION .text
-
-; INT32
-; EFIAPI
-; TestAndClearBit (
-;   IN  INT32 Bit,                // rcx
-;   IN  volatile VOID* Address    // rdx
-;   );
-global ASM_PFX(TestAndClearBit)
-ASM_PFX(TestAndClearBit):
-  lock btr [rdx], ecx
-  sbb eax, eax
-  ret
-
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 6c306e017b07..953e4b72e85e 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -122,7 +122,7 @@ INT32
 EFIAPI
 TestAndClearBit (
   IN INT32 Bit,
-  IN volatile VOID *Address
+  IN VOID  *Address
   );
 
 CHAR8*
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index 31553ac5a64a..f0c5db98b1f4 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -34,8 +34,6 @@
   DriverBinding.h
   ComponentName.c
   ComponentName.h
-  InterlockedCompareExchange16.c
-  InterlockedCompareExchange16.h
   GrantTable.c
   GrantTable.h
   EventChannel.c
@@ -45,14 +43,7 @@
   XenBus.c
   XenBus.h
   Helpers.c
-
-[Sources.IA32]
-  Ia32/InterlockedCompareExchange16.nasm
-  Ia32/TestAndClearBit.nasm
-
-[Sources.X64]
-  X64/InterlockedCompareExchange16.nasm
-  X64/TestAndClearBit.nasm
+  TestAndClearBit.c
 
 [LibraryClasses]
   UefiDriverEntryPoint
@@ -64,6 +55,7 @@
   DevicePathLib
   DebugLib
   XenHypercallLib
+  SynchronizationLib
 
 [Protocols]
   gEfiDriverBindingProtocolGuid
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 24/29] Ovmf/Xen: add Xen PV console SerialPortLib driver
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (22 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 23/29] Ovmf/Xen: port XenBusDxe to other architectures Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 25/29] ArmVirtualizationPkg: implement dummy RealTimeClockLib for Xen Ard Biesheuvel
                   ` (14 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This implements a SerialPortLib instance that wires up to the
PV console ring used by domU guests. Also imports the required
upstream Xen io/console.h header.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/Include/IndustryStandard/Xen/io/console.h                   |  51 ++++++++++++++++++++++++++++++++++
 OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c   | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf |  35 ++++++++++++++++++++++++
 3 files changed, 242 insertions(+)

diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/console.h b/OvmfPkg/Include/IndustryStandard/Xen/io/console.h
new file mode 100644
index 000000000000..f1caa9765bcf
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/io/console.h
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * console.h
+ *
+ * Console I/O interface for Xen guest OSes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
+#define __XEN_PUBLIC_IO_CONSOLE_H__
+
+typedef UINT32 XENCONS_RING_IDX;
+
+#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
+
+struct xencons_interface {
+    char in[1024];
+    char out[2048];
+    XENCONS_RING_IDX in_cons, in_prod;
+    XENCONS_RING_IDX out_cons, out_prod;
+};
+
+#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c b/OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c
new file mode 100644
index 000000000000..98022354cf31
--- /dev/null
+++ b/OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c
@@ -0,0 +1,156 @@
+/** @file
+  Xen console SerialPortLib instance
+
+  Copyright (c) 2015, 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+
+#include <Library/BaseLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/XenHypercallLib.h>
+
+#include <IndustryStandard/Xen/io/console.h>
+#include <IndustryStandard/Xen/hvm/params.h>
+#include <IndustryStandard/Xen/event_channel.h>
+
+//
+// The code below expects these global variables to be mutable, even in the case
+// that we have been incorporated into SEC or PEIM phase modules (which is
+// allowed by our INF description). While this is a dangerous assumption to make
+// in general, it is actually fine for the Xen domU (guest) environment that
+// this module is intended for, as UEFI always executes from DRAM in that case.
+//
+STATIC evtchn_send_t              mXenConsoleEventChain;
+STATIC struct xencons_interface   *mXenConsoleInterface;
+
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+  VOID
+  )
+{
+  if (!mXenConsoleInterface) {
+    mXenConsoleEventChain.port = (UINT32)XenHypercallHvmGetParam (HVM_PARAM_CONSOLE_EVTCHN);
+    mXenConsoleInterface = (struct xencons_interface *)(UINTN)
+      (XenHypercallHvmGetParam (HVM_PARAM_CONSOLE_PFN) << EFI_PAGE_SHIFT);
+
+    //
+    // No point in ASSERT'ing here as we won't be seeing the output
+    //
+  }
+  return RETURN_SUCCESS;
+}
+
+/**
+  Write data to serial device.
+
+  @param  Buffer           Point of data buffer which need to be written.
+  @param  NumberOfBytes    Number of output bytes which are cached in Buffer.
+
+  @retval 0                Write data failed.
+  @retval !0               Actual number of bytes written to serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+  IN UINT8     *Buffer,
+  IN UINTN     NumberOfBytes
+  )
+{
+  XENCONS_RING_IDX  Consumer, Producer;
+  UINTN             Sent;
+
+  if (!mXenConsoleInterface) {
+    return 0;
+  }
+
+  Consumer = mXenConsoleInterface->out_cons;
+  Producer = mXenConsoleInterface->out_prod;
+
+  MemoryFence ();
+
+  Sent = 0;
+  while (Sent < NumberOfBytes && ((Producer - Consumer) < sizeof (mXenConsoleInterface->out)))
+    mXenConsoleInterface->out[MASK_XENCONS_IDX(Producer++, mXenConsoleInterface->out)] = Buffer[Sent++];
+
+  MemoryFence ();
+
+  mXenConsoleInterface->out_prod = Producer;
+
+  if (Sent > 0) {
+    XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain);
+  }
+
+  return Sent;
+}
+
+/**
+  Read data from serial device and save the data in buffer.
+
+  @param  Buffer           Point of data buffer which need to be written.
+  @param  NumberOfBytes    Size of Buffer[].
+
+  @retval 0                Read data failed.
+  @retval !0               Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+  OUT UINT8     *Buffer,
+  IN  UINTN     NumberOfBytes
+)
+{
+  XENCONS_RING_IDX  Consumer, Producer;
+  UINTN             Received;
+
+  if (!mXenConsoleInterface) {
+    return 0;
+  }
+
+  Consumer = mXenConsoleInterface->in_cons;
+  Producer = mXenConsoleInterface->in_prod;
+
+  MemoryFence ();
+
+  Received = 0;
+  while (Received < NumberOfBytes && Consumer < Producer)
+     Buffer[Received++] = mXenConsoleInterface->in[MASK_XENCONS_IDX(Consumer++, mXenConsoleInterface->in)];
+
+  MemoryFence ();
+
+  mXenConsoleInterface->in_cons = Consumer;
+
+  XenHypercallEventChannelOp (EVTCHNOP_send, &mXenConsoleEventChain);
+
+  return Received;
+}
+
+/**
+  Check to see if any data is available to be read from the debug device.
+
+  @retval TRUE       At least one byte of data is available to be read
+  @retval FALSE      No data is available to be read
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+  VOID
+  )
+{
+  return mXenConsoleInterface &&
+    mXenConsoleInterface->in_cons != mXenConsoleInterface->in_prod;
+}
diff --git a/OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf b/OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
new file mode 100644
index 000000000000..8a7411558fa3
--- /dev/null
+++ b/OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
@@ -0,0 +1,35 @@
+#/** @file
+#
+#  Component description file for XenConsoleSerialPortLib module
+#
+#  Copyright (c) 2015, 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                    = 0x00010005
+  BASE_NAME                      = XenConsoleSerialPortLib
+  FILE_GUID                      = 401406DD-BCAC-4B91-9F4E-72A7FEBE4762
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SerialPortLib
+  CONSTRUCTOR                    = SerialPortInitialize
+
+[Sources.common]
+  XenConsoleSerialPortLib.c
+
+[LibraryClasses]
+  BaseLib
+  XenHypercallLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 25/29] ArmVirtualizationPkg: implement dummy RealTimeClockLib for Xen
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (23 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 24/29] Ovmf/Xen: add Xen PV console SerialPortLib driver Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 26/29] Ovfm/Xen: add a Vendor Hardware device path GUID for the XenBus root Ard Biesheuvel
                   ` (13 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This implements a dummy RealTimeClockLib for Xen, as there is no
guest interface to access the time kept by Xen that can be shared
between UEFI and the OS.

Contributed-under: TianoCore Contribution Agreement 1.0
Acked-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-By: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c   | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf |  38 +++++++++++++++++
 2 files changed, 234 insertions(+)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c
new file mode 100644
index 000000000000..70204ac22a92
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c
@@ -0,0 +1,196 @@
+/** @file
+  Implement EFI RealTimeClock runtime services via Xen shared info page
+
+  Copyright (c) 2015, 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 <Uefi.h>
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+/**
+  Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME
+ **/
+STATIC
+VOID
+EpochToEfiTime (
+  IN  UINTN     EpochSeconds,
+  OUT EFI_TIME  *Time
+  )
+{
+  UINTN         a;
+  UINTN         b;
+  UINTN         c;
+  UINTN         d;
+  UINTN         g;
+  UINTN         j;
+  UINTN         m;
+  UINTN         y;
+  UINTN         da;
+  UINTN         db;
+  UINTN         dc;
+  UINTN         dg;
+  UINTN         hh;
+  UINTN         mm;
+  UINTN         ss;
+  UINTN         J;
+
+  J  = (EpochSeconds / 86400) + 2440588;
+  j  = J + 32044;
+  g  = j / 146097;
+  dg = j % 146097;
+  c  = (((dg / 36524) + 1) * 3) / 4;
+  dc = dg - (c * 36524);
+  b  = dc / 1461;
+  db = dc % 1461;
+  a  = (((db / 365) + 1) * 3) / 4;
+  da = db - (a * 365);
+  y  = (g * 400) + (c * 100) + (b * 4) + a;
+  m  = (((da * 5) + 308) / 153) - 2;
+  d  = da - (((m + 4) * 153) / 5) + 122;
+
+  Time->Year  = y - 4800 + ((m + 2) / 12);
+  Time->Month = ((m + 2) % 12) + 1;
+  Time->Day   = d + 1;
+
+  ss = EpochSeconds % 60;
+  a  = (EpochSeconds - ss) / 60;
+  mm = a % 60;
+  b = (a - mm) / 60;
+  hh = b % 24;
+
+  Time->Hour        = hh;
+  Time->Minute      = mm;
+  Time->Second      = ss;
+  Time->Nanosecond  = 0;
+
+}
+
+/**
+  Returns the current time and date information, and the time-keeping capabilities
+  of the hardware platform.
+
+  @param  Time                  A pointer to storage to receive a snapshot of the current time.
+  @param  Capabilities          An optional pointer to a buffer to receive the real time clock
+                                device's capabilities.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER Time is NULL.
+  @retval EFI_DEVICE_ERROR      The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+  OUT EFI_TIME                *Time,
+  OUT  EFI_TIME_CAPABILITIES  *Capabilities
+  )
+{
+  ASSERT (Time != NULL);
+
+  //
+  // For now, there is nothing that we can do besides returning a bogus time,
+  // as Xen's timekeeping uses a shared info page which cannot be shared
+  // between UEFI and the OS
+  //
+  EpochToEfiTime(1421770011, Time);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Sets the current local time and date information.
+
+  @param  Time                  A pointer to the current time.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER A time field is out of range.
+  @retval EFI_DEVICE_ERROR      The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetTime (
+  IN EFI_TIME                *Time
+  )
+{
+  return EFI_DEVICE_ERROR;
+}
+
+
+/**
+  Returns the current wakeup alarm clock setting.
+
+  @param  Enabled               Indicates if the alarm is currently enabled or disabled.
+  @param  Pending               Indicates if the alarm signal is pending and requires acknowledgement.
+  @param  Time                  The current alarm setting.
+
+  @retval EFI_SUCCESS           The alarm settings were returned.
+  @retval EFI_INVALID_PARAMETER Any parameter is NULL.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetWakeupTime (
+  OUT BOOLEAN     *Enabled,
+  OUT BOOLEAN     *Pending,
+  OUT EFI_TIME    *Time
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Sets the system wakeup alarm clock time.
+
+  @param  Enabled               Enable or disable the wakeup alarm.
+  @param  Time                  If Enable is TRUE, the time to set the wakeup alarm for.
+
+  @retval EFI_SUCCESS           If Enable is TRUE, then the wakeup alarm was enabled. If
+                                Enable is FALSE, then the wakeup alarm was disabled.
+  @retval EFI_INVALID_PARAMETER A time field is out of range.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be set due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetWakeupTime (
+  IN BOOLEAN      Enabled,
+  OUT EFI_TIME    *Time
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This can be the entry point to an application
+  written to this specification, an EFI boot service driver, or an EFI runtime driver.
+
+  @param  ImageHandle           Handle that identifies the loaded image.
+  @param  SystemTable           System Table for this image.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRtcInitialize (
+  IN EFI_HANDLE                            ImageHandle,
+  IN EFI_SYSTEM_TABLE                      *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
new file mode 100644
index 000000000000..aafbfda6b491
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
@@ -0,0 +1,38 @@
+#/** @file
+#
+# Copyright (c) 2015, L 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                    = 0x00010005
+  BASE_NAME                      = XenRealTimeClockLib
+  FILE_GUID                      = EC2557E8-7005-430B-9F6F-9BA109698248
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = RealTimeClockLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION
+
+[Sources.common]
+  XenRealTimeClockLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  UefiLib
+  DebugLib
+  DxeServicesTableLib
+  UefiRuntimeLib
+
+[Guids]
+  gEfiEventVirtualAddressChangeGuid
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 26/29] Ovfm/Xen: add a Vendor Hardware device path GUID for the XenBus root
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (24 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 25/29] ArmVirtualizationPkg: implement dummy RealTimeClockLib for Xen Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 27/29] ArmVirtualizationPkg: add XenIoMmioLib Ard Biesheuvel
                   ` (12 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

On non-PCI Xen guests (such as ARM), the XenBus root is not a PCI
device but an abstract 'platform' device. Add a dedicated Vendor
Hardware device path GUID to identify this node.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/Include/Guid/XenBusRootDevice.h | 24 ++++++++++++++++++++++++
 OvmfPkg/OvmfPkg.dec                     |  1 +
 2 files changed, 25 insertions(+)

diff --git a/OvmfPkg/Include/Guid/XenBusRootDevice.h b/OvmfPkg/Include/Guid/XenBusRootDevice.h
new file mode 100644
index 000000000000..2b6e71018052
--- /dev/null
+++ b/OvmfPkg/Include/Guid/XenBusRootDevice.h
@@ -0,0 +1,24 @@
+/** @file
+  GUID to be used to identify the XenBus root node on non-PCI Xen guests
+
+  Copyright (C) 2015, Linaro Ltd.
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License that accompanies this
+  distribution. The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __XENBUS_ROOT_DEVICE_H__
+#define __XENBUS_ROOT_DEVICE_H__
+
+#define XENBUS_ROOT_DEVICE_GUID \
+{0xa732241f, 0x383d, 0x4d9c, {0x8a, 0xe1, 0x8e, 0x09, 0x83, 0x75, 0x89, 0xd7}}
+
+extern EFI_GUID gXenBusRootDeviceGuid;
+
+#endif
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 3711fa922311..d61600225919 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -53,6 +53,7 @@
   gEfiXenInfoGuid                 = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
   gOvmfPlatformConfigGuid         = {0x7235c51c, 0x0c80, 0x4cab, {0x87, 0xac, 0x3b, 0x08, 0x4a, 0x63, 0x04, 0xb1}}
   gVirtioMmioTransportGuid        = {0x837dca9e, 0xe874, 0x4d82, {0xb2, 0x9a, 0x23, 0xfe, 0x0e, 0x23, 0xd1, 0xe2}}
+  gXenBusRootDeviceGuid           = {0xa732241f, 0x383d, 0x4d9c, {0x8a, 0xe1, 0x8e, 0x09, 0x83, 0x75, 0x89, 0xd7}}
 
 [Protocols]
   gVirtioDeviceProtocolGuid       = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 27/29] ArmVirtualizationPkg: add XenIoMmioLib
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (25 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 26/29] Ovfm/Xen: add a Vendor Hardware device path GUID for the XenBus root Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 28/29] ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen, xen" DT node Ard Biesheuvel
                   ` (11 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This adds a XenIoMmioLib declaration and implementation that can
be invoked to install the XENIO_PROTOCOL and a corresponding
grant table address on a EFI handle.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 OvmfPkg/Include/Library/XenIoMmioLib.h        |  64 +++++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.c   | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf |  39 ++++++++++++++++++++++++++++++
 OvmfPkg/OvmfPkg.dec                           |   4 ++++
 4 files changed, 273 insertions(+)

diff --git a/OvmfPkg/Include/Library/XenIoMmioLib.h b/OvmfPkg/Include/Library/XenIoMmioLib.h
new file mode 100644
index 000000000000..3986c72c574e
--- /dev/null
+++ b/OvmfPkg/Include/Library/XenIoMmioLib.h
@@ -0,0 +1,64 @@
+/** @file
+*  Manage XenBus device path and I/O handles
+*
+*  Copyright (c) 2015, 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.
+*
+**/
+
+#ifndef _XENIO_MMIO_DEVICE_LIB_H_
+#define _XENIO_MMIO_DEVICE_LIB_H_
+
+/**
+
+  Install the XENBUS_ROOT_DEVICE_PATH and XENIO_PROTOCOL protocols on
+  the handle pointed to by @Handle, or on a new handle if it points to
+  NULL
+
+  @param  Handle                Pointer to the handle to install the protocols
+                                on, may point to a NULL handle.
+
+  @param  GrantTableAddress     The address of the Xen grant table
+
+  @retval EFI_SUCCESS           Protocols were installed successfully
+
+  @retval EFI_OUT_OF_RESOURCES  The function failed to allocate memory required
+                                by the XenIo MMIO and device path protocols
+
+  @return                       Status code returned by the boot service
+                                InstallMultipleProtocolInterfaces ()
+
+**/
+EFI_STATUS
+XenIoMmioInstall (
+  IN OUT   EFI_HANDLE              *Handle,
+  IN       EFI_PHYSICAL_ADDRESS    GrantTableAddress
+  );
+
+
+/**
+
+  Uninstall the XENBUS_ROOT_DEVICE_PATH and XENIO_PROTOCOL protocols
+
+  @param  Handle          Handle onto which the protocols have been installed
+                          earlier by XenIoMmioInstall ()
+
+  @retval EFI_SUCCESS     Protocols were uninstalled successfully
+
+  @return                 Status code returned by the boot service
+                          UninstallMultipleProtocolInterfaces ()
+
+**/
+EFI_STATUS
+XenIoMmioUninstall (
+  IN       EFI_HANDLE              Handle
+  );
+
+#endif
diff --git a/OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.c b/OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.c
new file mode 100644
index 000000000000..c710e85865c3
--- /dev/null
+++ b/OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.c
@@ -0,0 +1,166 @@
+/** @file
+*  Manage XenBus device path and I/O handles
+*
+*  Copyright (c) 2015, 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 <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/XenIoMmioLib.h>
+
+#include <Protocol/XenIo.h>
+#include <Guid/XenBusRootDevice.h>
+
+#pragma pack (1)
+typedef struct {
+  VENDOR_DEVICE_PATH                  Vendor;
+  EFI_PHYSICAL_ADDRESS                GrantTableAddress;
+  EFI_DEVICE_PATH_PROTOCOL            End;
+} XENBUS_ROOT_DEVICE_PATH;
+#pragma pack ()
+
+STATIC CONST XENBUS_ROOT_DEVICE_PATH mXenBusRootDevicePathTemplate = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      { sizeof (VENDOR_DEVICE_PATH) + sizeof (EFI_PHYSICAL_ADDRESS), 0 }
+    },
+    XENBUS_ROOT_DEVICE_GUID,
+  },
+  0,
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+  }
+};
+
+/**
+
+  Install the XENBUS_ROOT_DEVICE_PATH and XENIO_PROTOCOL protocols on
+  the handle pointed to by @Handle, or on a new handle if it points to
+  NULL
+
+  @param  Handle                Pointer to the handle to install the protocols
+                                on, may point to a NULL handle.
+
+  @param  GrantTableAddress     The address of the Xen grant table
+
+  @retval EFI_SUCCESS           Protocols were installed successfully
+
+  @retval EFI_OUT_OF_RESOURCES  The function failed to allocate memory required
+                                by the XenIo MMIO and device path protocols
+
+  @return                       Status code returned by the boot service
+                                InstallMultipleProtocolInterfaces ()
+
+**/
+EFI_STATUS
+XenIoMmioInstall (
+  IN OUT   EFI_HANDLE              *Handle,
+  IN       EFI_PHYSICAL_ADDRESS    GrantTableAddress
+  )
+{
+  EFI_STATUS                     Status;
+  XENIO_PROTOCOL                 *XenIo;
+  XENBUS_ROOT_DEVICE_PATH        *XenBusDevicePath;
+  EFI_HANDLE                     OutHandle;
+
+  ASSERT (Handle != NULL);
+
+  OutHandle = *Handle;
+
+  XenIo = AllocateZeroPool (sizeof *XenIo);
+  if (!XenIo) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  XenIo->GrantTableAddress = GrantTableAddress;
+
+  XenBusDevicePath = AllocateCopyPool (sizeof *XenBusDevicePath,
+                       &mXenBusRootDevicePathTemplate);
+  if (!XenBusDevicePath) {
+    DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto FreeXenIo;
+  }
+  XenBusDevicePath->GrantTableAddress = GrantTableAddress;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (&OutHandle,
+                  &gEfiDevicePathProtocolGuid, XenBusDevicePath,
+                  &gXenIoProtocolGuid, XenIo,
+                  NULL);
+  if (!EFI_ERROR (Status)) {
+    *Handle = OutHandle;
+    return EFI_SUCCESS;
+  }
+  
+  DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH and "
+    "XENIO_PROTOCOL protocols on handle %p (Status == %r)\n",
+    __FUNCTION__, OutHandle, Status));
+
+  FreePool (XenBusDevicePath);
+
+FreeXenIo:
+  FreePool (XenIo);
+  return Status;
+}
+
+/**
+
+  Uninstall the XENBUS_ROOT_DEVICE_PATH and XENIO_PROTOCOL protocols
+
+  @param  Handle          Handle onto which the protocols have been installed
+                          earlier by XenIoMmioInstall ()
+
+  @retval EFI_SUCCESS     Protocols were uninstalled successfully
+
+  @return                 Status code returned by the boot service
+                          UninstallMultipleProtocolInterfaces ()
+
+**/
+EFI_STATUS
+XenIoMmioUninstall (
+  IN       EFI_HANDLE              Handle
+  )
+{
+  EFI_STATUS    Status;
+  VOID          *XenIo;
+  VOID          *XenBusDevicePath;
+
+  XenBusDevicePath = NULL;
+  gBS->OpenProtocol (Handle, &gEfiDevicePathProtocolGuid, &XenBusDevicePath,
+         NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+  XenIo = NULL;
+  gBS->OpenProtocol (Handle, &gXenIoProtocolGuid, &XenIo,
+         NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (Handle,
+                  &gEfiDevicePathProtocolGuid, XenBusDevicePath,
+                  &gXenIoProtocolGuid, XenIo,
+                  NULL);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  FreePool (XenBusDevicePath);
+  FreePool (XenIo);
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf b/OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf
new file mode 100644
index 000000000000..16cc4530355e
--- /dev/null
+++ b/OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf
@@ -0,0 +1,39 @@
+## @file
+#  Manage XenBus device path and I/O handles
+#
+#  Copyright (c) 2015, 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                    = 0x00010005
+  BASE_NAME                      = XenIoMmioLib
+  FILE_GUID                      = de9bdc19-8434-47bb-be3c-7f28f2101fd0
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = XenIoMmioLib
+
+[Sources]
+  XenIoMmioLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+
+[Guids]
+  gXenBusRootDeviceGuid
+
+[Protocols]
+  gEfiDevicePathProtocolGuid
+  gXenIoProtocolGuid
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index d61600225919..4cb70dc98e79 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -48,6 +48,10 @@
   #
   XenHypercallLib|Include/Library/XenHypercallLib.h
 
+  ##  @libraryclass  Manage XenBus device path and I/O handles
+  #
+  XenIoMmioLib|Include/Library/XenIoMmioLib.h
+
 [Guids]
   gUefiOvmfPkgTokenSpaceGuid      = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
   gEfiXenInfoGuid                 = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 28/29] ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen, xen" DT node
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (26 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 27/29] ArmVirtualizationPkg: add XenIoMmioLib Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 11:19 ` [PATCH v4 29/29] ArmVirtualizationPkg: add platform description for Xen guests Ard Biesheuvel
                   ` (10 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This patchs adds support to VirtFdtDxe for the Xen DT node which
contains the base address of the Grant Table. This data is communicated
to XenBusDxe using a XENIO_PROTOCOL instance.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc |  2 ++
 ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c   | 23 +++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf |  1 +
 3 files changed, 26 insertions(+)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc
index f17cd2f5d876..e7a03cd13d3a 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc
@@ -100,6 +100,8 @@
   BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf
   FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
 
+  XenIoMmioLib|OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf
+
 [LibraryClasses.common.SEC]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
   ArmPlatformSecExtraActionLib|ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.inf
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
index 0b6414d59d46..2cc4610376b9 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c
@@ -26,6 +26,7 @@
 #include <Library/DxeServicesLib.h>
 #include <Library/HobLib.h>
 #include <libfdt.h>
+#include <Library/XenIoMmioLib.h>
 
 #include <Guid/Fdt.h>
 #include <Guid/VirtioMmioTransport.h>
@@ -49,6 +50,7 @@ typedef enum {
   PropertyTypePsci,
   PropertyTypeFwCfg,
   PropertyTypeGicV3,
+  PropertyTypeXen,
 } PROPERTY_TYPE;
 
 typedef struct {
@@ -66,6 +68,7 @@ STATIC CONST PROPERTY CompatibleProperties[] = {
   { PropertyTypePsci,    "arm,psci-0.2"        },
   { PropertyTypeFwCfg,   "qemu,fw-cfg-mmio"    },
   { PropertyTypeGicV3,   "arm,gic-v3"          },
+  { PropertyTypeXen,     "xen,xen"             },
   { PropertyTypeUnknown, ""                    }
 };
 
@@ -345,6 +348,26 @@ InitializeVirtFdtDxe (
       }
       break;
 
+    case PropertyTypeXen:
+      ASSERT (Len == 16);
+
+      //
+      // Retrieve the reg base from this node and wire it up to the
+      // MMIO flavor of the XenBus root device I/O protocol
+      //
+      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
+      Handle = NULL;
+      Status = XenIoMmioInstall (&Handle, RegBase);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((EFI_D_ERROR, "%a: XenIoMmioInstall () failed on a new handle "
+          "(Status == %r)\n", __FUNCTION__, Status));
+        break;
+      }
+
+      DEBUG ((EFI_D_INFO, "Found Xen node with Grant table @ 0x%Lx\n", RegBase));
+
+      break;
+
     default:
       break;
     }
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
index 0774fadda21c..a7eef1b979cb 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
@@ -41,6 +41,7 @@
   FdtLib
   VirtioMmioDeviceLib
   HobLib
+  XenIoMmioLib
 
 [Guids]
   gFdtTableGuid
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v4 29/29] ArmVirtualizationPkg: add platform description for Xen guests
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (27 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 28/29] ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen, xen" DT node Ard Biesheuvel
@ 2015-02-12 11:19 ` Ard Biesheuvel
  2015-02-12 21:18 ` [PATCH v4 00/29] Xen/ARM guest support Jordan Justen
                   ` (9 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-12 11:19 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, jordan.l.justen, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

This adds the .dsc and .fdf descriptions to build a UEFI image that
is bootable by a Xen guest on 64-bit ARM (AArch64)

Contributed-under: TianoCore Contribution Agreement 1.0
Acked-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.dsc | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 520 insertions(+)

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.dsc
new file mode 100644
index 000000000000..eb9167b6f816
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.dsc
@@ -0,0 +1,218 @@
+#
+#  Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+#  Copyright (c) 2014, 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.
+#
+#
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  PLATFORM_NAME                  = ArmVirtualizationXen
+  PLATFORM_GUID                  = d1c43be3-3373-4a06-86fb-d1cb3083a207
+  PLATFORM_VERSION               = 0.1
+  DSC_SPECIFICATION              = 0x00010005
+  OUTPUT_DIRECTORY               = Build/ArmVirtualizationXen-$(ARCH)
+  SUPPORTED_ARCHITECTURES        = AARCH64
+  BUILD_TARGETS                  = DEBUG|RELEASE
+  SKUID_IDENTIFIER               = DEFAULT
+  FLASH_DEFINITION               = ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf
+
+!include ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc
+
+[LibraryClasses]
+  SerialPortLib|OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
+  RealTimeClockLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
+  XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf
+
+[LibraryClasses.AARCH64]
+  ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf
+  ArmCpuLib|ArmPkg/Drivers/ArmCpuLib/ArmCortexAEMv8Lib/ArmCortexAEMv8Lib.inf
+
+[LibraryClasses.ARM]
+  ArmLib|ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf
+  ArmCpuLib|ArmPkg/Drivers/ArmCpuLib/ArmCortexA15Lib/ArmCortexA15Lib.inf
+
+[LibraryClasses.common]
+  # Virtio Support
+  VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+  VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
+
+  ArmPlatformLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
+  ArmPlatformSysConfigLib|ArmPlatformPkg/Library/ArmPlatformSysConfigLibNull/ArmPlatformSysConfigLibNull.inf
+
+  TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
+
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+  GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
+  PlatformBdsLib|ArmPlatformPkg/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf
+  CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+  UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+
+[LibraryClasses.AARCH64.SEC]
+  ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf
+
+[LibraryClasses.ARM.SEC]
+  ArmLib|ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf
+
+[BuildOptions]
+  RVCT:*_*_ARM_PLATFORM_FLAGS == --cpu Cortex-A15 -I$(WORKSPACE)/ArmPlatformPkg/ArmVirtualizationPkg/Include
+  GCC:*_*_ARM_PLATFORM_FLAGS == -mcpu=cortex-a15 -I$(WORKSPACE)/ArmPlatformPkg/ArmVirtualizationPkg/Include
+  GCC:*_*_AARCH64_PLATFORM_FLAGS == -I$(WORKSPACE)/ArmPlatformPkg/ArmVirtualizationPkg/Include
+ 
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsFixedAtBuild.common]
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+
+  gArmPlatformTokenSpaceGuid.PcdFirmwareVendor|"XEN-UEFI"
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString|L"$(FIRMWARE_VER)"
+
+  gArmPlatformTokenSpaceGuid.PcdCoreCount|1
+!if $(ARCH) == AARCH64
+  gArmTokenSpaceGuid.PcdVFPEnabled|1
+!endif
+
+  gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x4000
+
+  # Size of the region used by UEFI in permanent memory (Reserved 64MB)
+  gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x04000000
+
+  #
+  # ARM Virtual Architectural Timer
+  #
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|0
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }
+
+[PcdsPatchableInModule.common]
+  #
+  # This will be overridden in the code
+  #
+  gArmTokenSpaceGuid.PcdSystemMemoryBase|0x0
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x0
+  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress|0x0
+
+  gArmTokenSpaceGuid.PcdFdBaseAddress|0x0
+  gArmTokenSpaceGuid.PcdFvBaseAddress|0x0
+
+[PcdsDynamicDefault.common]
+
+  gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0
+  gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0
+  gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
+  gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x0
+
+  #
+  # ARM General Interrupt Controller
+  #
+  gArmTokenSpaceGuid.PcdGicDistributorBase|0x0
+  gArmTokenSpaceGuid.PcdGicRedistributorsBase|0x0
+  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x0
+
+  ## PL031 RealTimeClock
+  gArmPlatformTokenSpaceGuid.PcdPL031RtcBase|0x0
+
+  gArmVirtualizationTokenSpaceGuid.PcdFwCfgSelectorAddress|0x0
+  gArmVirtualizationTokenSpaceGuid.PcdFwCfgDataAddress|0x0
+
+  gArmVirtualizationTokenSpaceGuid.PcdArmPsciMethod|0
+
+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform
+#
+################################################################################
+[Components.common]
+  #
+  # PEI Phase modules
+  #
+  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf {
+    <LibraryClasses>
+      ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
+      LzmaDecompressLib|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+      PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
+      HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf
+      PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
+      MemoryInitPeiLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf
+      ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64LibPrePi.inf
+      MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf
+      ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf
+      SerialPortLib|OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
+  }
+
+  #
+  # DXE
+  #
+  MdeModulePkg/Core/Dxe/DxeMain.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
+  }
+  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+  #
+  # Architectural Protocols
+  #
+  ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+
+  MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+
+  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+  EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
+  EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+  EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
+
+  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+  EmbeddedPkg/SerialDxe/SerialDxe.inf
+
+  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+
+  ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+  ArmPkg/Drivers/TimerDxe/TimerDxe.inf
+  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+
+  #
+  # Platform Driver
+  #
+  ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
+
+  #
+  # FAT filesystem + GPT/MBR partitioning
+  #
+  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+
+  #
+  # Bds
+  #
+  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+  MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+  IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
+
+  OvmfPkg/XenBusDxe/XenBusDxe.inf
+  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf
new file mode 100644
index 000000000000..07ae02a362d4
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf
@@ -0,0 +1,302 @@
+#
+#  Copyright (c) 2011, 2013, ARM Limited. All rights reserved.
+#  Copyright (c) 2014, 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.
+#
+
+################################################################################
+#
+# FD Section
+# The [FD] Section is made up of the definition statements and a
+# description of what goes into  the Flash Device Image.  Each FD section
+# defines one flash "device" image.  A flash device image may be one of
+# the following: Removable media bootable image (like a boot floppy
+# image,) an Option ROM image (that would be "flashed" into an add-in
+# card,) a System "Flash"  image (that would be burned into a system's
+# flash) or an Update ("Capsule") image that will be used to update and
+# existing system flash.
+#
+################################################################################
+
+[FD.XEN_EFI]
+BaseAddress   = 0x00000000|gArmTokenSpaceGuid.PcdFdBaseAddress
+Size          = 0x00200000|gArmTokenSpaceGuid.PcdFdSize
+ErasePolarity = 1
+
+# This one is tricky, it must be: BlockSize * NumBlocks = Size
+BlockSize     = 0x00001000
+NumBlocks     = 0x200
+
+################################################################################
+#
+# Following are lists of FD Region layout which correspond to the locations of different
+# images within the flash device.
+#
+# Regions must be defined in ascending order and may not overlap.
+#
+# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by
+# the pipe "|" character, followed by the size of the region, also in hex with the leading
+# "0x" characters. Like:
+# Offset|Size
+# PcdOffsetCName|PcdSizeCName
+# RegionType <FV, DATA, or FILE>
+#
+################################################################################
+
+#
+# Implement the Linux kernel header layout so that the Xen loader will identify
+# it as something bootable, and execute it with a FDT pointer in x0. This area
+# will be reused to store a copy of the FDT so round it up to 8 KB.
+#
+0x00000000|0x00002000
+DATA = {
+  0x01, 0x00, 0x00, 0x10,                         # code0: adr x1, .
+  0xff, 0x07, 0x00, 0x14,                         # code1: b 0x2000
+  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, # text_offset: 512 KB
+  0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, # image_size: 2 MB
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # flags
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # res2
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # res3
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # res4
+  0x41, 0x52, 0x4d, 0x64,                         # magic: "ARM\x64"
+  0x00, 0x00, 0x00, 0x00                          # res5
+}
+
+0x00002000|0x001fe000
+gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
+FV = FVMAIN_COMPACT
+
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file.  This section also defines order the components and modules are positioned
+# within the image.  The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+
+[FV.FvMain]
+BlockSize          = 0x40
+NumBlocks          = 0         # This FV gets compressed so make it just big enough
+FvAlignment        = 16        # FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+  APRIORI DXE {
+    INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+    INF ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
+  }
+  INF MdeModulePkg/Core/Dxe/DxeMain.inf
+  INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+  INF ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf
+
+  #
+  # PI DXE Drivers producing Architectural Protocols (EFI Services)
+  #
+  INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+  INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+  INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+  INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+
+  INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+
+  INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+  INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
+  INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+  INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
+  INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+
+  #
+  # Multiple Console IO support
+  #
+  INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+  INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+  INF EmbeddedPkg/SerialDxe/SerialDxe.inf
+
+  INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+  INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
+  INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+
+  #
+  # FAT filesystem + GPT/MBR partitioning
+  #
+  INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+  INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+  INF FatBinPkg/EnhancedFatDxe/Fat.inf
+  INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+
+  #
+  # UEFI application (Shell Embedded Boot Loader)
+  #
+  INF ShellBinPkg/UefiShell/UefiShell.inf
+
+  #
+  # Bds
+  #
+  INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+  INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+  INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+  INF IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
+
+  INF OvmfPkg/XenBusDxe/XenBusDxe.inf
+  INF OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
+
+[FV.FVMAIN_COMPACT]
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+  INF ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
+
+  FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+    SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+      SECTION FV_IMAGE = FVMAIN
+    }
+  }
+
+
+################################################################################
+#
+# Rules are use with the [FV] section's module INF type to define
+# how an FFS file is created for a given INF file. The following Rule are the default
+# rules for the different module type. User can add the customized rules to define the
+# content of the FFS file.
+#
+################################################################################
+
+
+############################################################################
+# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section   #
+############################################################################
+#
+#[Rule.Common.DXE_DRIVER]
+#  FILE DRIVER = $(NAMED_GUID) {
+#    DXE_DEPEX    DXE_DEPEX               Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+#    COMPRESS PI_STD {
+#      GUIDED {
+#        PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+#        UI       STRING="$(MODULE_NAME)" Optional
+#        VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+#      }
+#    }
+#  }
+#
+############################################################################
+
+[Rule.Common.SEC]
+  FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
+    TE  TE Align = 4K                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
+
+[Rule.Common.PEI_CORE]
+  FILE PEI_CORE = $(NAMED_GUID) {
+    TE     TE Align = 8                 $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI     STRING ="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.PEIM]
+  FILE PEIM = $(NAMED_GUID) {
+     PEI_DEPEX PEI_DEPEX Optional       $(INF_OUTPUT)/$(MODULE_NAME).depex
+     TE       TE Align = 8              $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.PEIM.TIANOCOMPRESSED]
+  FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
+    PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+    GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
+      PE32      PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+      UI        STRING="$(MODULE_NAME)" Optional
+    }
+  }
+
+[Rule.Common.DXE_CORE]
+  FILE DXE_CORE = $(NAMED_GUID) {
+    PE32     PE32                       $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.UEFI_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.DXE_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.UEFI_APPLICATION]
+  FILE APPLICATION = $(NAMED_GUID) {
+    UI     STRING ="$(MODULE_NAME)"     Optional
+    PE32   PE32                         $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX DXE_DEPEX Optional      |.depex
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+  FILE APPLICATION = $(NAMED_GUID) {
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+  FILE FREEFORM = $(NAMED_GUID) {
+    RAW       ACPI                    |.acpi
+    RAW       ASL                     |.aml
+    UI        STRING="$(MODULE_NAME)" Optional
+  }
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 00/29] Xen/ARM guest support
       [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
                   ` (28 preceding siblings ...)
  2015-02-12 11:19 ` [PATCH v4 29/29] ArmVirtualizationPkg: add platform description for Xen guests Ard Biesheuvel
@ 2015-02-12 21:18 ` Jordan Justen
       [not found] ` <20150212211855.11478.90744@jljusten-hsw>
                   ` (8 subsequent siblings)
  38 siblings, 0 replies; 46+ messages in thread
From: Jordan Justen @ 2015-02-12 21:18 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, edk2-devel, leif.lindholm, xen-devel,
	roy.franz, michael.d.kinney, anthony.perard, lersek


[-- Attachment #1.1: Type: text/plain, Size: 22647 bytes --]

Do you have this in a public branch based on this tree?
https://github.com/tianocore/edk2

On 2015-02-12 03:18:52, Ard Biesheuvel wrote:
> This series implements support for executing Tianocore inside a Xen
> guest domain on 64-bit ARM systems (AArch64)
> 
> The first part addresses ARM platform specifics, primarily to allow a
> Tianocore binary image to be runtime relocatable, and execute from DRAM.
> 
> The second part refactors the XenBus support, and adds some missing device
> drivers that are needed to execute on ARM: a Xen PV console and a real time
> clock driver.
> 
> Finally, patch #29 wraps it all together and implements the .dsc and .fdf
> platform descriptions that can be used to build the binary image.
> 
> NOTES:
> - the Xen RTC driver is a dummy implementation, as it is a Runtime driver which
>   is callable through Runtime Services from the OS, and this is currently not
>   supportable under Xen, due to the need to share the shared info page between
>   the OS and the firmware
> - UEFI maps the entire physical memory space as cached, and relies on Xen to
>   use the correct stage2 mappings for regions that are backed by devices, such
>   as the GIC or device passthrough. The reason is that the I/O console ring and
>   grant table are backed by RAM that Xen maps as cached, which means that UEFI
>   *must* map those as cached as well. Instead of discovering those regions
>   early on (i.e., before enabling the MMU) it is much easier to rely on the
>   architecturally mandated behavior that stage2 device mappings supersede stage1
>   cached mappings for the same region.
> - this code is not yet tested on x86 (still only build tested for v4)
> 
> Changes since v3:
> - rebased onto Olivier's pending GICv3 patches
> - moved InterlockedCompareExchange16 () to BaseSynchronizationLib
> - reimplemented XenBusDxe's TestAndClearBit () using
>   InterlockedCompareExchange16 () so that XenBusDxe itself is now completely
>   architecture agnostic
> - various minor style and comment changes based on review feedback from
>   Laszlo and Olivier
> - added acks and R-b's
> 
> Changes since v2:
> - rebased onto latest upstream containing Laszlo's ARM generic timer changes,
>   with Olivier's pending GICv3 patches applied on top;
> - moved the relocatable PrePi to a completely separate module, and dropped
>   patches changing the original ARM PrePi code: all required changes have been
>   incorporated directly into the split off version
> - dropped the ARM BDS entirely, only Intel BDS supported as of now
> - added a constructor to XenConsoleSerialPortLib, otherwise there is no output
>   from the release build;
> - implemented all review comments regarding style and correctness, including
>   cleaning up the DSC in the final patch
> - added acks and R-b's
> 
> Changes since v1:
> - move to PatchableInModule PCDs for the runtime self-relocating PrePi: this is
>   semantically more correct, and will make the build system help us spot if
>   there are remaining instances of FixedPcdGetXX() which need attention
> - split some prepi and xen patches to make it easier on the reviewers
> - split off the PCI support from XenBusDxe instead of the frankenstein DXE from
>   v1
> - implemented review comments regarding moving of files, splitting of libraries
>   and some EDK2 optimizations suggested by Laszlo (casting, use of specific
>   types etc)
> - added some acks and R-b's
> 
> 
> 
> Ard Biesheuvel (29):
>   ArmPkg: allow HYP timer interrupt to be omitted
>   ArmPkg: allow patchable PCDs for memory, FD and FV addresses
>   ArmPlatformPkg: allow patchable PCD for FD base address
>   ArmVirtualizationPkg: add GICv3 detection to VirtFdtDxe
>   ArmVirtualizationPkg: allow patchable PCD for device tree base address
>   ArmVirtualizationPkg: move early UART discovery to PlatformPeim
>   ArmVirtualizationPkg: use a HOB to store device tree blob
>   ArmVirtualizationPkg: add padding to FDT allocation
>   ArmVirtualizationPkg: add a relocatable version of PrePi
>   ArmVirtualizationPkg: implement custom MemoryInitPeiLib
>   ArmVirtualizationPkg: allow patchable PCD for FV and DT base addresses
>   ArmVirtualizationPkg: Xen/PV relocatable platformlib instance
>   MdePkg/BaseSynchronizationLib: Added proper support for ARM
>     architecture
>   MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
>   Ovmf/Xen: move Xen interface version to <xen.h>
>   Ovmf/Xen: fix pointer to int cast in XenBusDxe
>   Ovmf/Xen: refactor XenBusDxe hypercall implementation
>   Ovmf/Xen: move XenBusDxe hypercall code to separate library
>   Ovmf/Xen: introduce XENIO_PROTOCOL
>   Ovmf/Xen: add separate driver for Xen PCI device
>   Ovmf/Xen: move XenBusDxe to abstract XENIO_PROTOCOL
>   Ovmf/Xen: implement XenHypercallLib for ARM
>   Ovmf/Xen: port XenBusDxe to other architectures
>   Ovmf/Xen: add Xen PV console SerialPortLib driver
>   ArmVirtualizationPkg: implement dummy RealTimeClockLib for Xen
>   Ovfm/Xen: add a Vendor Hardware device path GUID for the XenBus root
>   ArmVirtualizationPkg: add XenIoMmioLib
>   ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen,xen" DT
>     node
>   ArmVirtualizationPkg: add platform description for Xen guests
> 
>  ArmPkg/ArmPkg.dec                                                                                                 |  25 ++--
>  ArmPkg/Drivers/TimerDxe/TimerDxe.c                                                                                |  14 +-
>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc                                                     |   2 +
>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec                                                      |  10 +-
>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc                                                     |   4 +-
>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.dsc                                                      | 218 +++++++++++++++++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf                                                      | 302 ++++++++++++++++++++++++++++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c |  91 ++++++++++++
>  .../ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf          |  66 +++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf         |   6 +-
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c                                   |  48 +------
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S                  | 237 +++++++++++++++++++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S          | 167 ++++++++++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf         |  59 ++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c                        |  71 ++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c                             |  83 +++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c                                       |  65 ++++++++-
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf                                     |  10 +-
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c                             | 196 ++++++++++++++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf                           |  38 +++++
>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ArchPrePi.c                                                     |  33 +++++
>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ModuleEntryPoint.S                                              | 180 ++++++++++++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf                                      | 108 +++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/LzmaDecompress.h                                                        | 103 ++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.c                                                                 | 203 +++++++++++++++++++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.h                                                                 |  77 +++++++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/Scripts/PrePi-PIE.lds                                                   |  42 ++++++
>  ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c                                                       |  73 +++++++++-
>  ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf                                                     |   5 +-
>  ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf                   |   2 +-
>  EmbeddedPkg/EmbeddedPkg.dec                                                                                       |   2 +
>  EmbeddedPkg/Include/Guid/FdtHob.h                                                                                 |  26 ++++
>  MdePkg/Include/Library/SynchronizationLib.h                                                                       |  26 ++++
>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S                                                   | 203 +++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c                                                   | 115 ----------------
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                                                       | 211 ++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm                                                     | 212 ++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c                                                       | 115 ----------------
>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf                                                  |  10 +-
>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h                                           |  26 ++++
>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                                                       |  31 +++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                                                            |  42 ++++++
>  .../Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm                                          |  88 ++++++------
>  .../InterlockedCompareExchange16.h => MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   |  89 +++++++-----
>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s                                          |  30 ++++
>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                                                           |  31 +++++
>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                                                             |  44 ++++++
>  .../Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm                                           |  83 +++++------
>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c                                          |  54 ++++++++
>  OvmfPkg/Include/Guid/XenBusRootDevice.h                                                                           |  24 ++++
>  OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h                                                               | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  OvmfPkg/Include/IndustryStandard/Xen/io/console.h                                                                 |  51 +++++++
>  OvmfPkg/Include/IndustryStandard/Xen/xen.h                                                                        |   7 +-
>  OvmfPkg/{XenBusDxe/XenHypercall.h => Include/Library/XenHypercallLib.h}                                           |  44 +-----
>  OvmfPkg/Include/Library/XenIoMmioLib.h                                                                            |  64 +++++++++
>  OvmfPkg/Include/Protocol/XenIo.h                                                                                  |  48 +++++++
>  OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c                                                 | 156 +++++++++++++++++++++
>  OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf                                               |  35 +++++
>  OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S                                                               |  26 ++++
>  OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S                                                                   |  25 ++++
>  OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm                                                |   6 +-
>  OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm                                                 |   6 +-
>  OvmfPkg/Library/XenHypercallLib/XenHypercall.c                                                                    |  63 +++++++++
>  OvmfPkg/Library/XenHypercallLib/XenHypercallIntel.c                                                               |  77 +++++++++++
>  OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf                                                            |  40 ++++++
>  OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf                                                          |  52 +++++++
>  OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.c                                                                       | 166 ++++++++++++++++++++++
>  OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf                                                                     |  39 ++++++
>  OvmfPkg/OvmfPkg.dec                                                                                               |  10 ++
>  OvmfPkg/OvmfPkgIa32.dsc                                                                                           |   2 +
>  OvmfPkg/OvmfPkgIa32.fdf                                                                                           |   1 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                                                                                        |   2 +
>  OvmfPkg/OvmfPkgIa32X64.fdf                                                                                        |   1 +
>  OvmfPkg/OvmfPkgX64.dsc                                                                                            |   2 +
>  OvmfPkg/OvmfPkgX64.fdf                                                                                            |   1 +
>  OvmfPkg/XenBusDxe/ComponentName.c                                                                                 |   2 +-
>  OvmfPkg/XenBusDxe/EventChannel.c                                                                                  |  14 +-
>  OvmfPkg/XenBusDxe/GrantTable.c                                                                                    |  17 ++-
>  OvmfPkg/XenBusDxe/GrantTable.h                                                                                    |   3 +-
>  OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm                                                                       |  16 ---
>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c                                                                  |  33 -----
>  OvmfPkg/XenBusDxe/TestAndClearBit.c                                                                               |  46 +++++++
>  OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm                                                                        |  15 --
>  OvmfPkg/XenBusDxe/XenBus.c                                                                                        |   6 +-
>  OvmfPkg/XenBusDxe/XenBusDxe.c                                                                                     | 106 +++++++-------
>  OvmfPkg/XenBusDxe/XenBusDxe.h                                                                                     |  16 +--
>  OvmfPkg/XenBusDxe/XenBusDxe.inf                                                                                   |  25 +---
>  OvmfPkg/XenBusDxe/XenHypercall.c                                                                                  | 118 ----------------
>  OvmfPkg/XenBusDxe/XenStore.c                                                                                      |   6 +-
>  OvmfPkg/XenIoPciDxe/XenIoPciDxe.c                                                                                 | 367 ++++++++++++++++++++++++++++++++++++++++++++++++
>  OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf                                                                               |  45 ++++++
>  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h                                                                                 |   4 -
>  92 files changed, 5417 insertions(+), 782 deletions(-)
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.dsc
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ArchPrePi.c
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ModuleEntryPoint.S
>  create mode 100755 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/LzmaDecompress.h
>  create mode 100755 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.c
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.h
>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/Scripts/PrePi-PIE.lds
>  create mode 100644 EmbeddedPkg/Include/Guid/FdtHob.h
>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>  delete mode 100644 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c
>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>  delete mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c
>  mode change 100644 => 100755 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>  rename OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm => MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm (86%)
>  rename OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h => MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c (52%)
>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>  rename OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm => MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm (88%)
>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>  create mode 100644 OvmfPkg/Include/Guid/XenBusRootDevice.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/console.h
>  rename OvmfPkg/{XenBusDxe/XenHypercall.h => Include/Library/XenHypercallLib.h} (59%)
>  create mode 100644 OvmfPkg/Include/Library/XenIoMmioLib.h
>  create mode 100644 OvmfPkg/Include/Protocol/XenIo.h
>  create mode 100644 OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c
>  create mode 100644 OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
>  create mode 100644 OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S
>  create mode 100644 OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S
>  rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm (81%)
>  rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm (78%)
>  create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercall.c
>  create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallIntel.c
>  create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf
>  create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
>  create mode 100644 OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.c
>  create mode 100644 OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf
>  delete mode 100644 OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm
>  delete mode 100644 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
>  create mode 100644 OvmfPkg/XenBusDxe/TestAndClearBit.c
>  delete mode 100644 OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm
>  delete mode 100644 OvmfPkg/XenBusDxe/XenHypercall.c
>  create mode 100644 OvmfPkg/XenIoPciDxe/XenIoPciDxe.c
>  create mode 100644 OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
> 
> -- 
> 1.8.3.2
> 

[-- Attachment #1.2: signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAABCAAGBQJU3Ri/AAoJEDf5n2jK+ZLrG5UQAIizst43MF4Qn3STf65jiKU8
kRiLy0BGkhmMzwEvfGJKIGCUZt4FbyDnhHC0nwD6swAJU58SdJYNQbqgJl3B7Rdm
a11fxnlcSk9iPSoUKNoOdTavtDcEgZmjJtfjU7nMUvuDu3e4u5G+MScmePqlHKyZ
6AA13CJIy0pH9AiFjvKA5jQIjG9Zq7qc3wr1prM9ABulIRkZcAhvbOv5pu4H6OG3
LmGTQ+7JCFW9t3ATxEuWKSZ5gtNd2Hyo7ghk15gUx6op5eSwu5iqfXQLw6d2j645
S7FwJXjZfcq2lyqGM2w2G8UCg7SkYzLDeREaU5B1bG6/JdJubsS3XUmNlolrA9mS
Qo9sngKGw//35ZdPIkg5lWCeN+4CcC/z62qv+NZwc/yHE2XJ5pUYiXle4sc99ZnX
bi5ARcVpGzkVOrhzAo6fGjmyNy/B64xp2z5C/rwwhXnOsWJH6+wWq9Rd0wtPJ/9/
/XOy9PtbSx++z37vYX3niLPG3/2cpkk/YxXQzWF54eo5JrtxSZSWJMCUJEgFbbC6
xCoi4YUWi4w5THx/BHyM0qAF2xJRxyFGTxNiTAFfE74ONX9TOu9tBM/4tqmdELYi
PCfJZI2MEHw4Cz9d4o1sAB2UvAC3t+AcqlT4wbvc2ymeKW+8PYPiKnL8OcCM7T8d
RRi441APGmAH9bdRukwE
=zKwy
-----END PGP SIGNATURE-----

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 00/29] Xen/ARM guest support
       [not found] ` <20150212211855.11478.90744@jljusten-hsw>
@ 2015-02-13  0:18   ` Ard Biesheuvel
  0 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-13  0:18 UTC (permalink / raw)
  To: Jordan Justen
  Cc: Tian, Feng, Julien Grall, Ian Campbell, Olivier Martin,
	Stefano Stabellini, edk2-devel, Leif Lindholm, xen-devel,
	Roy Franz, Kinney, Michael D, Anthony PERARD, Laszlo Ersek

On 13 February 2015 at 05:18, Jordan Justen <jordan.l.justen@intel.com> wrote:
> Do you have this in a public branch based on this tree?
> https://github.com/tianocore/edk2
>

The patches are available here
https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/linaro-topic-xen

I also have a version rebased onto the latest upstream, and verified
that it builds ok
https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/linaro-topic-xen-v4-rebase

Regards,
Ard.


> On 2015-02-12 03:18:52, Ard Biesheuvel wrote:
>> This series implements support for executing Tianocore inside a Xen
>> guest domain on 64-bit ARM systems (AArch64)
>>
>> The first part addresses ARM platform specifics, primarily to allow a
>> Tianocore binary image to be runtime relocatable, and execute from DRAM.
>>
>> The second part refactors the XenBus support, and adds some missing device
>> drivers that are needed to execute on ARM: a Xen PV console and a real time
>> clock driver.
>>
>> Finally, patch #29 wraps it all together and implements the .dsc and .fdf
>> platform descriptions that can be used to build the binary image.
>>
>> NOTES:
>> - the Xen RTC driver is a dummy implementation, as it is a Runtime driver which
>>   is callable through Runtime Services from the OS, and this is currently not
>>   supportable under Xen, due to the need to share the shared info page between
>>   the OS and the firmware
>> - UEFI maps the entire physical memory space as cached, and relies on Xen to
>>   use the correct stage2 mappings for regions that are backed by devices, such
>>   as the GIC or device passthrough. The reason is that the I/O console ring and
>>   grant table are backed by RAM that Xen maps as cached, which means that UEFI
>>   *must* map those as cached as well. Instead of discovering those regions
>>   early on (i.e., before enabling the MMU) it is much easier to rely on the
>>   architecturally mandated behavior that stage2 device mappings supersede stage1
>>   cached mappings for the same region.
>> - this code is not yet tested on x86 (still only build tested for v4)
>>
>> Changes since v3:
>> - rebased onto Olivier's pending GICv3 patches
>> - moved InterlockedCompareExchange16 () to BaseSynchronizationLib
>> - reimplemented XenBusDxe's TestAndClearBit () using
>>   InterlockedCompareExchange16 () so that XenBusDxe itself is now completely
>>   architecture agnostic
>> - various minor style and comment changes based on review feedback from
>>   Laszlo and Olivier
>> - added acks and R-b's
>>
>> Changes since v2:
>> - rebased onto latest upstream containing Laszlo's ARM generic timer changes,
>>   with Olivier's pending GICv3 patches applied on top;
>> - moved the relocatable PrePi to a completely separate module, and dropped
>>   patches changing the original ARM PrePi code: all required changes have been
>>   incorporated directly into the split off version
>> - dropped the ARM BDS entirely, only Intel BDS supported as of now
>> - added a constructor to XenConsoleSerialPortLib, otherwise there is no output
>>   from the release build;
>> - implemented all review comments regarding style and correctness, including
>>   cleaning up the DSC in the final patch
>> - added acks and R-b's
>>
>> Changes since v1:
>> - move to PatchableInModule PCDs for the runtime self-relocating PrePi: this is
>>   semantically more correct, and will make the build system help us spot if
>>   there are remaining instances of FixedPcdGetXX() which need attention
>> - split some prepi and xen patches to make it easier on the reviewers
>> - split off the PCI support from XenBusDxe instead of the frankenstein DXE from
>>   v1
>> - implemented review comments regarding moving of files, splitting of libraries
>>   and some EDK2 optimizations suggested by Laszlo (casting, use of specific
>>   types etc)
>> - added some acks and R-b's
>>
>>
>>
>> Ard Biesheuvel (29):
>>   ArmPkg: allow HYP timer interrupt to be omitted
>>   ArmPkg: allow patchable PCDs for memory, FD and FV addresses
>>   ArmPlatformPkg: allow patchable PCD for FD base address
>>   ArmVirtualizationPkg: add GICv3 detection to VirtFdtDxe
>>   ArmVirtualizationPkg: allow patchable PCD for device tree base address
>>   ArmVirtualizationPkg: move early UART discovery to PlatformPeim
>>   ArmVirtualizationPkg: use a HOB to store device tree blob
>>   ArmVirtualizationPkg: add padding to FDT allocation
>>   ArmVirtualizationPkg: add a relocatable version of PrePi
>>   ArmVirtualizationPkg: implement custom MemoryInitPeiLib
>>   ArmVirtualizationPkg: allow patchable PCD for FV and DT base addresses
>>   ArmVirtualizationPkg: Xen/PV relocatable platformlib instance
>>   MdePkg/BaseSynchronizationLib: Added proper support for ARM
>>     architecture
>>   MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
>>   Ovmf/Xen: move Xen interface version to <xen.h>
>>   Ovmf/Xen: fix pointer to int cast in XenBusDxe
>>   Ovmf/Xen: refactor XenBusDxe hypercall implementation
>>   Ovmf/Xen: move XenBusDxe hypercall code to separate library
>>   Ovmf/Xen: introduce XENIO_PROTOCOL
>>   Ovmf/Xen: add separate driver for Xen PCI device
>>   Ovmf/Xen: move XenBusDxe to abstract XENIO_PROTOCOL
>>   Ovmf/Xen: implement XenHypercallLib for ARM
>>   Ovmf/Xen: port XenBusDxe to other architectures
>>   Ovmf/Xen: add Xen PV console SerialPortLib driver
>>   ArmVirtualizationPkg: implement dummy RealTimeClockLib for Xen
>>   Ovfm/Xen: add a Vendor Hardware device path GUID for the XenBus root
>>   ArmVirtualizationPkg: add XenIoMmioLib
>>   ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen,xen" DT
>>     node
>>   ArmVirtualizationPkg: add platform description for Xen guests
>>
>>  ArmPkg/ArmPkg.dec                                                                                                 |  25 ++--
>>  ArmPkg/Drivers/TimerDxe/TimerDxe.c                                                                                |  14 +-
>>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc                                                     |   2 +
>>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec                                                      |  10 +-
>>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc                                                     |   4 +-
>>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.dsc                                                      | 218 +++++++++++++++++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf                                                      | 302 ++++++++++++++++++++++++++++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c |  91 ++++++++++++
>>  .../ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf          |  66 +++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf         |   6 +-
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c                                   |  48 +------
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S                  | 237 +++++++++++++++++++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S          | 167 ++++++++++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf         |  59 ++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c                        |  71 ++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c                             |  83 +++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c                                       |  65 ++++++++-
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf                                     |  10 +-
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c                             | 196 ++++++++++++++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf                           |  38 +++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ArchPrePi.c                                                     |  33 +++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ModuleEntryPoint.S                                              | 180 ++++++++++++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf                                      | 108 +++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/LzmaDecompress.h                                                        | 103 ++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.c                                                                 | 203 +++++++++++++++++++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.h                                                                 |  77 +++++++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/PrePi/Scripts/PrePi-PIE.lds                                                   |  42 ++++++
>>  ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c                                                       |  73 +++++++++-
>>  ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf                                                     |   5 +-
>>  ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf                   |   2 +-
>>  EmbeddedPkg/EmbeddedPkg.dec                                                                                       |   2 +
>>  EmbeddedPkg/Include/Guid/FdtHob.h                                                                                 |  26 ++++
>>  MdePkg/Include/Library/SynchronizationLib.h                                                                       |  26 ++++
>>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S                                                   | 203 +++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c                                                   | 115 ----------------
>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                                                       | 211 ++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm                                                     | 212 ++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c                                                       | 115 ----------------
>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf                                                  |  10 +-
>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h                                           |  26 ++++
>>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                                                       |  31 +++++
>>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                                                            |  42 ++++++
>>  .../Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm                                          |  88 ++++++------
>>  .../InterlockedCompareExchange16.h => MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   |  89 +++++++-----
>>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s                                          |  30 ++++
>>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                                                           |  31 +++++
>>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                                                             |  44 ++++++
>>  .../Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm                                           |  83 +++++------
>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c                                          |  54 ++++++++
>>  OvmfPkg/Include/Guid/XenBusRootDevice.h                                                                           |  24 ++++
>>  OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h                                                               | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  OvmfPkg/Include/IndustryStandard/Xen/io/console.h                                                                 |  51 +++++++
>>  OvmfPkg/Include/IndustryStandard/Xen/xen.h                                                                        |   7 +-
>>  OvmfPkg/{XenBusDxe/XenHypercall.h => Include/Library/XenHypercallLib.h}                                           |  44 +-----
>>  OvmfPkg/Include/Library/XenIoMmioLib.h                                                                            |  64 +++++++++
>>  OvmfPkg/Include/Protocol/XenIo.h                                                                                  |  48 +++++++
>>  OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c                                                 | 156 +++++++++++++++++++++
>>  OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf                                               |  35 +++++
>>  OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S                                                               |  26 ++++
>>  OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S                                                                   |  25 ++++
>>  OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm                                                |   6 +-
>>  OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm                                                 |   6 +-
>>  OvmfPkg/Library/XenHypercallLib/XenHypercall.c                                                                    |  63 +++++++++
>>  OvmfPkg/Library/XenHypercallLib/XenHypercallIntel.c                                                               |  77 +++++++++++
>>  OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf                                                            |  40 ++++++
>>  OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf                                                          |  52 +++++++
>>  OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.c                                                                       | 166 ++++++++++++++++++++++
>>  OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf                                                                     |  39 ++++++
>>  OvmfPkg/OvmfPkg.dec                                                                                               |  10 ++
>>  OvmfPkg/OvmfPkgIa32.dsc                                                                                           |   2 +
>>  OvmfPkg/OvmfPkgIa32.fdf                                                                                           |   1 +
>>  OvmfPkg/OvmfPkgIa32X64.dsc                                                                                        |   2 +
>>  OvmfPkg/OvmfPkgIa32X64.fdf                                                                                        |   1 +
>>  OvmfPkg/OvmfPkgX64.dsc                                                                                            |   2 +
>>  OvmfPkg/OvmfPkgX64.fdf                                                                                            |   1 +
>>  OvmfPkg/XenBusDxe/ComponentName.c                                                                                 |   2 +-
>>  OvmfPkg/XenBusDxe/EventChannel.c                                                                                  |  14 +-
>>  OvmfPkg/XenBusDxe/GrantTable.c                                                                                    |  17 ++-
>>  OvmfPkg/XenBusDxe/GrantTable.h                                                                                    |   3 +-
>>  OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm                                                                       |  16 ---
>>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c                                                                  |  33 -----
>>  OvmfPkg/XenBusDxe/TestAndClearBit.c                                                                               |  46 +++++++
>>  OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm                                                                        |  15 --
>>  OvmfPkg/XenBusDxe/XenBus.c                                                                                        |   6 +-
>>  OvmfPkg/XenBusDxe/XenBusDxe.c                                                                                     | 106 +++++++-------
>>  OvmfPkg/XenBusDxe/XenBusDxe.h                                                                                     |  16 +--
>>  OvmfPkg/XenBusDxe/XenBusDxe.inf                                                                                   |  25 +---
>>  OvmfPkg/XenBusDxe/XenHypercall.c                                                                                  | 118 ----------------
>>  OvmfPkg/XenBusDxe/XenStore.c                                                                                      |   6 +-
>>  OvmfPkg/XenIoPciDxe/XenIoPciDxe.c                                                                                 | 367 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf                                                                               |  45 ++++++
>>  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h                                                                                 |   4 -
>>  92 files changed, 5417 insertions(+), 782 deletions(-)
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.dsc
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationXen.fdf
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ArchPrePi.c
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/AArch64/ModuleEntryPoint.S
>>  create mode 100755 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/LzmaDecompress.h
>>  create mode 100755 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.c
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/PrePi.h
>>  create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/PrePi/Scripts/PrePi-PIE.lds
>>  create mode 100644 EmbeddedPkg/Include/Guid/FdtHob.h
>>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>>  delete mode 100644 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c
>>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>>  delete mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c
>>  mode change 100644 => 100755 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>>  rename OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm => MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm (86%)
>>  rename OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h => MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c (52%)
>>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>>  rename OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm => MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm (88%)
>>  create mode 100644 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>>  create mode 100644 OvmfPkg/Include/Guid/XenBusRootDevice.h
>>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h
>>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/console.h
>>  rename OvmfPkg/{XenBusDxe/XenHypercall.h => Include/Library/XenHypercallLib.h} (59%)
>>  create mode 100644 OvmfPkg/Include/Library/XenIoMmioLib.h
>>  create mode 100644 OvmfPkg/Include/Protocol/XenIo.h
>>  create mode 100644 OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c
>>  create mode 100644 OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
>>  create mode 100644 OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S
>>  create mode 100644 OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S
>>  rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm (81%)
>>  rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm (78%)
>>  create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercall.c
>>  create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallIntel.c
>>  create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf
>>  create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
>>  create mode 100644 OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.c
>>  create mode 100644 OvmfPkg/Library/XenIoMmioLib/XenIoMmioLib.inf
>>  delete mode 100644 OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm
>>  delete mode 100644 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
>>  create mode 100644 OvmfPkg/XenBusDxe/TestAndClearBit.c
>>  delete mode 100644 OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm
>>  delete mode 100644 OvmfPkg/XenBusDxe/XenHypercall.c
>>  create mode 100644 OvmfPkg/XenIoPciDxe/XenIoPciDxe.c
>>  create mode 100644 OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
>>
>> --
>> 1.8.3.2
>>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
       [not found] ` <1423739961-5945-15-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-17 17:40   ` Jordan Justen
       [not found]   ` <20150217174047.8141.17529@jljusten-ivy>
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 46+ messages in thread
From: Jordan Justen @ 2015-02-17 17:40 UTC (permalink / raw)
  To: edk2-devel, olivier.martin, lersek, roy.franz, leif.lindholm,
	stefano.stabellini, ian.campbell, anthony.perard, xen-devel,
	julien.grall, michael.d.kinney, feng.tian
  Cc: Ard Biesheuvel

Ard,

For the subject, I think
MdePkg/BaseSynchronizationLib: Add InterlockedCompareExchange16
would be better.

Acked-by: Jordan Justen <jordan.l.justen@intel.com>

Thanks for working to move this to a common location.

Mike,

I think Anthony tested the IA32 and X64 implementations with Xen. For
IPF, I don't think it has been tested.

-Jordan

On 2015-02-12 03:19:06, Ard Biesheuvel wrote:
> This implements the function InterlockedCompareExchange16 () for all
> architectures, using architecture and toolchain specific intrinsics
> or primitive assembler instructions.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Reviewed-by: Olivier Martin <olivier.martin@arm.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  17 files changed, 622 insertions(+)
> 
> diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
> index f97569739914..7b97683ca0af 100644
> --- a/MdePkg/Include/Library/SynchronizationLib.h
> +++ b/MdePkg/Include/Library/SynchronizationLib.h
> @@ -184,6 +184,32 @@ InterlockedDecrement (
>  
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  );
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> index 601b00495f26..ecb87fc12755 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> @@ -16,12 +16,56 @@
>  .text
>  .align 3
>  
> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>  GCC_ASM_EXPORT(InternalSyncIncrement)
>  GCC_ASM_EXPORT(InternalSyncDecrement)
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +ASM_PFX(InternalSyncCompareExchange16):
> +  uxth    w1, w1
> +  uxth    w2, w2
> +  dmb     sy
> +
> +InternalSyncCompareExchange16Again:
> +  ldxrh   w3, [x0]
> +  cmp     w3, w1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange:
> +  stxrh   w4, w2, [x0]
> +  cbnz    w4, InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail:
> +  dmb     sy
> +  mov     w0, w3
> +  ret
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> index 0128f8f016bd..d699eb40d2a2 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> @@ -1,6 +1,7 @@
>  //  Implementation of synchronization functions for ARM architecture
>  //
>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
> +//  Copyright (c) 2015, 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
> @@ -15,12 +16,55 @@
>  .text
>  .align 3
>  
> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>  GCC_ASM_EXPORT(InternalSyncIncrement)
>  GCC_ASM_EXPORT(InternalSyncDecrement)
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +ASM_PFX(InternalSyncCompareExchange16):
> +  dmb
> +
> +InternalSyncCompareExchange16Again:
> +  ldrexh  r3, [r0]
> +  cmp     r3, r1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange:
> +  strexh  ip, r2, [r0]
> +  cmp     ip, #0
> +  bne     InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail:
> +  dmb
> +  mov     r0, r3
> +  bx      lr
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> index f9f80737774a..dbc599114093 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> @@ -1,6 +1,7 @@
>  //  Implementation of synchronization functions for ARM architecture
>  //
>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
> +//  Copyright (c) 2015, 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
> @@ -12,6 +13,7 @@
>  //
>  //
>  
> +    EXPORT  InternalSyncCompareExchange16
>      EXPORT  InternalSyncCompareExchange32
>      EXPORT  InternalSyncCompareExchange64
>      EXPORT  InternalSyncIncrement
> @@ -20,6 +22,48 @@
>      AREA   ArmSynchronization, CODE, READONLY
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +InternalSyncCompareExchange16
> +  dmb
> +
> +InternalSyncCompareExchange16Again
> +  ldrexh  r3, [r0]
> +  cmp     r3, r1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange
> +  strexh  ip, r2, [r0]
> +  cmp     ip, #0
> +  bne     InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail
> +  dmb
> +  mov     r0, r3
> +  bx      lr
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> @@ -32,12 +32,14 @@
>  [Sources.IA32]
>    Ia32/InterlockedCompareExchange64.c | MSFT 
>    Ia32/InterlockedCompareExchange32.c | MSFT 
> +  Ia32/InterlockedCompareExchange16.c | MSFT
>    Ia32/InterlockedDecrement.c | MSFT 
>    Ia32/InterlockedIncrement.c | MSFT 
>    SynchronizationMsc.c  | MSFT
>  
>    Ia32/InterlockedCompareExchange64.asm | INTEL 
>    Ia32/InterlockedCompareExchange32.asm | INTEL 
> +  Ia32/InterlockedCompareExchange16.asm | INTEL
>    Ia32/InterlockedDecrement.asm | INTEL 
>    Ia32/InterlockedIncrement.asm | INTEL 
>    Synchronization.c | INTEL
> @@ -48,9 +50,11 @@
>  [Sources.X64]
>    X64/InterlockedCompareExchange64.c | MSFT
>    X64/InterlockedCompareExchange32.c | MSFT
> +  X64/InterlockedCompareExchange16.c | MSFT
>    
>    X64/InterlockedCompareExchange64.asm | INTEL
>    X64/InterlockedCompareExchange32.asm | INTEL
> +  X64/InterlockedCompareExchange16.asm | INTEL
>    
>    X64/InterlockedDecrement.c | MSFT 
>    X64/InterlockedIncrement.c | MSFT 
> @@ -67,6 +71,7 @@
>    Ipf/Synchronization.c
>    Ipf/InterlockedCompareExchange64.s
>    Ipf/InterlockedCompareExchange32.s
> +  Ipf/InterlockedCompareExchange16.s
>  
>    Synchronization.c     | INTEL 
>    SynchronizationMsc.c  | MSFT 
> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> index e42824c75d12..76f702324156 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> @@ -63,6 +63,32 @@ InternalSyncDecrement (
>  
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in compare operation.
> +  @param  ExchangeValue A 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      volatile UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  );
> +
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> index 9c34b9f128ed..a57860203b12 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> @@ -13,6 +13,37 @@
>  **/
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit
> +  unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit
> +  unsigned integer specified by Value.  If Value is equal to
> +  CompareValue, then Value is set to ExchangeValue and
> +  CompareValue is returned.  If Value is not equal to
> +  CompareValue, then Value is returned. The compare exchange
> +  operation must be performed using MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the
> +                        compare exchange operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      volatile UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  return *Value != CompareValue ? *Value :
> +           ((*Value = ExchangeValue), CompareValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit
>    unsigned integer.
>  
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> index b5a7827fc0e8..bd81aad6c243 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> @@ -88,6 +88,48 @@ InternalSyncDecrement (
>  }
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN OUT volatile  UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +
> +  __asm__ __volatile__ (
> +    "                     \n    "
> +    "lock                 \n    "
> +    "cmpxchgw    %1, %2   \n    "
> +    : "=a" (CompareValue)
> +    : "q"  (ExchangeValue),
> +      "m"  (*Value),
> +      "0"  (CompareValue)
> +    : "memory",
> +      "cc"
> +    );
> +
> +  return CompareValue;
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
> new file mode 100644
> index 000000000000..f8705042661d
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
> @@ -0,0 +1,46 @@
> +;------------------------------------------------------------------------------
> +;
> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
> +; Copyright (c) 2015, 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.
> +;
> +; Module Name:
> +;
> +;   InterlockedCompareExchange16.Asm
> +;
> +; Abstract:
> +;
> +;   InterlockedCompareExchange16 function
> +;
> +; Notes:
> +;
> +;------------------------------------------------------------------------------
> +
> +    .486
> +    .model  flat,C
> +    .code
> +
> +;------------------------------------------------------------------------------
> +; UINT16
> +; EFIAPI
> +; InternalSyncCompareExchange16 (
> +;   IN      UINT16                    *Value,
> +;   IN      UINT16                    CompareValue,
> +;   IN      UINT16                    ExchangeValue
> +;   );
> +;------------------------------------------------------------------------------
> +InternalSyncCompareExchange16   PROC
> +    mov     ecx, [esp + 4]
> +    mov     eax, [esp + 8]
> +    mov     edx, [esp + 12]
> +    lock    cmpxchg [ecx], dx
> +    ret
> +InternalSyncCompareExchange16   ENDP
> +
> +    END
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
> new file mode 100644
> index 000000000000..3d06dd9baa63
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
> @@ -0,0 +1,51 @@
> +/** @file
> +  InterlockedCompareExchange16 function
> +
> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2015, 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.
> +
> +**/
> +
> +
> +
> +
> +/**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  _asm {
> +    mov     ecx, Value
> +    mov     eax, CompareValue
> +    mov     edx, ExchangeValue
> +    lock    cmpxchg [ecx], dx
> +  }
> +}
> +
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
> new file mode 100644
> index 000000000000..1e56942a98cb
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
> @@ -0,0 +1,30 @@
> +/// @file
> +///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
> +///   based architecture.
> +///
> +/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
> +/// Copyright (c) 2015, 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.
> +///
> +/// Module Name:  InterlockedCompareExchange16.s
> +///
> +///
> +
> +.auto
> +.text
> +
> +.proc   InternalSyncCompareExchange16
> +.type   InternalSyncCompareExchange16, @function
> +InternalSyncCompareExchange16::
> +        zxt2                r33 = r33
> +        mov                 ar.ccv = r33
> +        cmpxchg2.rel        r8  = [r32], r34
> +        mf
> +        br.ret.sptk.many    b0
> +.endp   InternalSyncCompareExchange16
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> index 0eea40ba1622..4218a265a0ec 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> @@ -277,6 +277,37 @@ InterlockedDecrement (
>  }
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> index badf73c1a6ce..587f5a771c35 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> @@ -293,6 +293,37 @@ InterlockedDecrement (
>  }
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in compare operation.
> +  @param  ExchangeValue A 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> index 9b20236acfa6..ca21f5dccee5 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> @@ -295,6 +295,37 @@ InterlockedDecrement (
>  }
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in a compare operation.
> +  @param  ExchangeValue A 16-bit value used in an exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> index ceb80aed94f8..6347073fee51 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> @@ -89,6 +89,50 @@ InternalSyncDecrement (
>  
>  
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN OUT volatile  UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +
> +
> +  __asm__ __volatile__ (
> +    "lock                 \n    "
> +    "cmpxchgw    %3, %1       "
> +    : "=a" (CompareValue),
> +      "=m" (*Value)
> +    : "a"  (CompareValue),
> +      "r"  (ExchangeValue),
> +      "m"  (*Value)
> +    : "memory",
> +      "cc"
> +    );
> +
> +  return CompareValue;
> +}
> +
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>  
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
> new file mode 100644
> index 000000000000..8fe2aae1a28b
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
> @@ -0,0 +1,42 @@
> +;------------------------------------------------------------------------------
> +;
> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
> +; Copyright (c) 2015, 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.
> +;
> +; Module Name:
> +;
> +;   InterlockedCompareExchange16.Asm
> +;
> +; Abstract:
> +;
> +;   InterlockedCompareExchange16 function
> +;
> +; Notes:
> +;
> +;------------------------------------------------------------------------------
> +
> +    .code
> +
> +;------------------------------------------------------------------------------
> +; UINT16
> +; EFIAPI
> +; InterlockedCompareExchange16 (
> +;   IN      UINT16                    *Value,
> +;   IN      UINT16                    CompareValue,
> +;   IN      UINT16                    ExchangeValue
> +;   );
> +;------------------------------------------------------------------------------
> +InternalSyncCompareExchange16   PROC
> +    mov     eax, edx
> +    lock    cmpxchg [rcx], r8w
> +    ret
> +InternalSyncCompareExchange16   ENDP
> +
> +    END
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
> new file mode 100644
> index 000000000000..76aa6fbc0e81
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
> @@ -0,0 +1,54 @@
> +/** @file
> +  InterlockedCompareExchange16 function
> +
> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2015, 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.
> +
> +**/
> +
> +/**
> +  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
> +**/
> +
> +__int16 _InterlockedCompareExchange16(
> +   __int16 volatile * Destination,
> +   __int16 Exchange,
> +   __int16 Comperand
> +);
> +
> +#pragma intrinsic(_InterlockedCompareExchange16)
> +
> +/**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
> +  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
> +  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
> +  The compare exchange operation must be performed using MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
> +}
> +
> -- 
> 1.8.3.2
> 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
       [not found]   ` <20150217174047.8141.17529@jljusten-ivy>
@ 2015-02-18  8:37     ` Ard Biesheuvel
       [not found]     ` <CAKv+Gu8M-V4Vgf2+sHLZS+n37Qbm+TxJpFpU27qDfHt=gR3+Bw@mail.gmail.com>
  1 sibling, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-18  8:37 UTC (permalink / raw)
  To: Jordan Justen
  Cc: Tian, Feng, Julien Grall, Ian Campbell, Olivier Martin,
	Stefano Stabellini, edk2-devel, Leif Lindholm, xen-devel,
	Roy Franz, Kinney, Michael D, Anthony PERARD, Laszlo Ersek

On 17 February 2015 at 18:40, Jordan Justen <jordan.l.justen@intel.com> wrote:
> Ard,
>
> For the subject, I think
> MdePkg/BaseSynchronizationLib: Add InterlockedCompareExchange16
> would be better.
>

OK

> Acked-by: Jordan Justen <jordan.l.justen@intel.com>
>

Thanks

> Thanks for working to move this to a common location.
>

No problem

> Mike,
>
> I think Anthony tested the IA32 and X64 implementations with Xen. For
> IPF, I don't think it has been tested.
>

As mentioned in the other thread, Anthony seems to be incommunicado,
and some other of the Xen guys have replied that Xen on OVMF/x86 is
broken for other reasons so they cannot positively confirm that
everything still works, even though the x86 changes other than the
PCI/xenbus split are primarily refactoring of existing code.

As far as IPF is concerned: I don't think Xen or Ovmf can be built for
IPF anyway, but I think a build test and visual inspection of the .S
file should be sufficient here?

Thanks,
Ard.


> On 2015-02-12 03:19:06, Ard Biesheuvel wrote:
>> This implements the function InterlockedCompareExchange16 () for all
>> architectures, using architecture and toolchain specific intrinsics
>> or primitive assembler instructions.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Reviewed-by: Olivier Martin <olivier.martin@arm.com>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  17 files changed, 622 insertions(+)
>>
>> diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
>> index f97569739914..7b97683ca0af 100644
>> --- a/MdePkg/Include/Library/SynchronizationLib.h
>> +++ b/MdePkg/Include/Library/SynchronizationLib.h
>> @@ -184,6 +184,32 @@ InterlockedDecrement (
>>
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  If Value is NULL, then ASSERT().
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +**/
>> +UINT16
>> +EFIAPI
>> +InterlockedCompareExchange16 (
>> +  IN OUT  UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  );
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>> index 601b00495f26..ecb87fc12755 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>> +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>> @@ -16,12 +16,56 @@
>>  .text
>>  .align 3
>>
>> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>>  GCC_ASM_EXPORT(InternalSyncIncrement)
>>  GCC_ASM_EXPORT(InternalSyncDecrement)
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +//UINT16
>> +//EFIAPI
>> +//InternalSyncCompareExchange16 (
>> +//  IN      volatile UINT16           *Value,
>> +//  IN      UINT16                    CompareValue,
>> +//  IN      UINT16                    ExchangeValue
>> +//  )
>> +ASM_PFX(InternalSyncCompareExchange16):
>> +  uxth    w1, w1
>> +  uxth    w2, w2
>> +  dmb     sy
>> +
>> +InternalSyncCompareExchange16Again:
>> +  ldxrh   w3, [x0]
>> +  cmp     w3, w1
>> +  bne     InternalSyncCompareExchange16Fail
>> +
>> +InternalSyncCompareExchange16Exchange:
>> +  stxrh   w4, w2, [x0]
>> +  cbnz    w4, InternalSyncCompareExchange16Again
>> +
>> +InternalSyncCompareExchange16Fail:
>> +  dmb     sy
>> +  mov     w0, w3
>> +  ret
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>> index 0128f8f016bd..d699eb40d2a2 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>> @@ -1,6 +1,7 @@
>>  //  Implementation of synchronization functions for ARM architecture
>>  //
>>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
>> +//  Copyright (c) 2015, 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
>> @@ -15,12 +16,55 @@
>>  .text
>>  .align 3
>>
>> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>>  GCC_ASM_EXPORT(InternalSyncIncrement)
>>  GCC_ASM_EXPORT(InternalSyncDecrement)
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +//UINT16
>> +//EFIAPI
>> +//InternalSyncCompareExchange16 (
>> +//  IN      volatile UINT16           *Value,
>> +//  IN      UINT16                    CompareValue,
>> +//  IN      UINT16                    ExchangeValue
>> +//  )
>> +ASM_PFX(InternalSyncCompareExchange16):
>> +  dmb
>> +
>> +InternalSyncCompareExchange16Again:
>> +  ldrexh  r3, [r0]
>> +  cmp     r3, r1
>> +  bne     InternalSyncCompareExchange16Fail
>> +
>> +InternalSyncCompareExchange16Exchange:
>> +  strexh  ip, r2, [r0]
>> +  cmp     ip, #0
>> +  bne     InternalSyncCompareExchange16Again
>> +
>> +InternalSyncCompareExchange16Fail:
>> +  dmb
>> +  mov     r0, r3
>> +  bx      lr
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>> index f9f80737774a..dbc599114093 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>> @@ -1,6 +1,7 @@
>>  //  Implementation of synchronization functions for ARM architecture
>>  //
>>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
>> +//  Copyright (c) 2015, 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
>> @@ -12,6 +13,7 @@
>>  //
>>  //
>>
>> +    EXPORT  InternalSyncCompareExchange16
>>      EXPORT  InternalSyncCompareExchange32
>>      EXPORT  InternalSyncCompareExchange64
>>      EXPORT  InternalSyncIncrement
>> @@ -20,6 +22,48 @@
>>      AREA   ArmSynchronization, CODE, READONLY
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +//UINT16
>> +//EFIAPI
>> +//InternalSyncCompareExchange16 (
>> +//  IN      volatile UINT16           *Value,
>> +//  IN      UINT16                    CompareValue,
>> +//  IN      UINT16                    ExchangeValue
>> +//  )
>> +InternalSyncCompareExchange16
>> +  dmb
>> +
>> +InternalSyncCompareExchange16Again
>> +  ldrexh  r3, [r0]
>> +  cmp     r3, r1
>> +  bne     InternalSyncCompareExchange16Fail
>> +
>> +InternalSyncCompareExchange16Exchange
>> +  strexh  ip, r2, [r0]
>> +  cmp     ip, #0
>> +  bne     InternalSyncCompareExchange16Again
>> +
>> +InternalSyncCompareExchange16Fail
>> +  dmb
>> +  mov     r0, r3
>> +  bx      lr
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>> index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
>> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>> @@ -32,12 +32,14 @@
>>  [Sources.IA32]
>>    Ia32/InterlockedCompareExchange64.c | MSFT
>>    Ia32/InterlockedCompareExchange32.c | MSFT
>> +  Ia32/InterlockedCompareExchange16.c | MSFT
>>    Ia32/InterlockedDecrement.c | MSFT
>>    Ia32/InterlockedIncrement.c | MSFT
>>    SynchronizationMsc.c  | MSFT
>>
>>    Ia32/InterlockedCompareExchange64.asm | INTEL
>>    Ia32/InterlockedCompareExchange32.asm | INTEL
>> +  Ia32/InterlockedCompareExchange16.asm | INTEL
>>    Ia32/InterlockedDecrement.asm | INTEL
>>    Ia32/InterlockedIncrement.asm | INTEL
>>    Synchronization.c | INTEL
>> @@ -48,9 +50,11 @@
>>  [Sources.X64]
>>    X64/InterlockedCompareExchange64.c | MSFT
>>    X64/InterlockedCompareExchange32.c | MSFT
>> +  X64/InterlockedCompareExchange16.c | MSFT
>>
>>    X64/InterlockedCompareExchange64.asm | INTEL
>>    X64/InterlockedCompareExchange32.asm | INTEL
>> +  X64/InterlockedCompareExchange16.asm | INTEL
>>
>>    X64/InterlockedDecrement.c | MSFT
>>    X64/InterlockedIncrement.c | MSFT
>> @@ -67,6 +71,7 @@
>>    Ipf/Synchronization.c
>>    Ipf/InterlockedCompareExchange64.s
>>    Ipf/InterlockedCompareExchange32.s
>> +  Ipf/InterlockedCompareExchange16.s
>>
>>    Synchronization.c     | INTEL
>>    SynchronizationMsc.c  | MSFT
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>> index e42824c75d12..76f702324156 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>> @@ -63,6 +63,32 @@ InternalSyncDecrement (
>>
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  A 16-bit value used in compare operation.
>> +  @param  ExchangeValue A 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN      volatile UINT16           *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  );
>> +
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>> index 9c34b9f128ed..a57860203b12 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>> @@ -13,6 +13,37 @@
>>  **/
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit
>> +  unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit
>> +  unsigned integer specified by Value.  If Value is equal to
>> +  CompareValue, then Value is set to ExchangeValue and
>> +  CompareValue is returned.  If Value is not equal to
>> +  CompareValue, then Value is returned. The compare exchange
>> +  operation must be performed using MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the
>> +                        compare exchange operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN      volatile UINT16           *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  return *Value != CompareValue ? *Value :
>> +           ((*Value = ExchangeValue), CompareValue);
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit
>>    unsigned integer.
>>
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>> index b5a7827fc0e8..bd81aad6c243 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>> @@ -88,6 +88,48 @@ InternalSyncDecrement (
>>  }
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN OUT volatile  UINT16           *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +
>> +  __asm__ __volatile__ (
>> +    "                     \n    "
>> +    "lock                 \n    "
>> +    "cmpxchgw    %1, %2   \n    "
>> +    : "=a" (CompareValue)
>> +    : "q"  (ExchangeValue),
>> +      "m"  (*Value),
>> +      "0"  (CompareValue)
>> +    : "memory",
>> +      "cc"
>> +    );
>> +
>> +  return CompareValue;
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
>> new file mode 100644
>> index 000000000000..f8705042661d
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
>> @@ -0,0 +1,46 @@
>> +;------------------------------------------------------------------------------
>> +;
>> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
>> +; Copyright (c) 2015, 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.
>> +;
>> +; Module Name:
>> +;
>> +;   InterlockedCompareExchange16.Asm
>> +;
>> +; Abstract:
>> +;
>> +;   InterlockedCompareExchange16 function
>> +;
>> +; Notes:
>> +;
>> +;------------------------------------------------------------------------------
>> +
>> +    .486
>> +    .model  flat,C
>> +    .code
>> +
>> +;------------------------------------------------------------------------------
>> +; UINT16
>> +; EFIAPI
>> +; InternalSyncCompareExchange16 (
>> +;   IN      UINT16                    *Value,
>> +;   IN      UINT16                    CompareValue,
>> +;   IN      UINT16                    ExchangeValue
>> +;   );
>> +;------------------------------------------------------------------------------
>> +InternalSyncCompareExchange16   PROC
>> +    mov     ecx, [esp + 4]
>> +    mov     eax, [esp + 8]
>> +    mov     edx, [esp + 12]
>> +    lock    cmpxchg [ecx], dx
>> +    ret
>> +InternalSyncCompareExchange16   ENDP
>> +
>> +    END
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
>> new file mode 100644
>> index 000000000000..3d06dd9baa63
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
>> @@ -0,0 +1,51 @@
>> +/** @file
>> +  InterlockedCompareExchange16 function
>> +
>> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
>> +  Copyright (c) 2015, 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.
>> +
>> +**/
>> +
>> +
>> +
>> +
>> +/**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN      UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  _asm {
>> +    mov     ecx, Value
>> +    mov     eax, CompareValue
>> +    mov     edx, ExchangeValue
>> +    lock    cmpxchg [ecx], dx
>> +  }
>> +}
>> +
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>> new file mode 100644
>> index 000000000000..1e56942a98cb
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>> @@ -0,0 +1,30 @@
>> +/// @file
>> +///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
>> +///   based architecture.
>> +///
>> +/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
>> +/// Copyright (c) 2015, 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.
>> +///
>> +/// Module Name:  InterlockedCompareExchange16.s
>> +///
>> +///
>> +
>> +.auto
>> +.text
>> +
>> +.proc   InternalSyncCompareExchange16
>> +.type   InternalSyncCompareExchange16, @function
>> +InternalSyncCompareExchange16::
>> +        zxt2                r33 = r33
>> +        mov                 ar.ccv = r33
>> +        cmpxchg2.rel        r8  = [r32], r34
>> +        mf
>> +        br.ret.sptk.many    b0
>> +.endp   InternalSyncCompareExchange16
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>> index 0eea40ba1622..4218a265a0ec 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>> @@ -277,6 +277,37 @@ InterlockedDecrement (
>>  }
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  If Value is NULL, then ASSERT().
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InterlockedCompareExchange16 (
>> +  IN OUT  UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  ASSERT (Value != NULL);
>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>> index badf73c1a6ce..587f5a771c35 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>> @@ -293,6 +293,37 @@ InterlockedDecrement (
>>  }
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  If Value is NULL, then ASSERT().
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  A 16-bit value used in compare operation.
>> +  @param  ExchangeValue A 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InterlockedCompareExchange16 (
>> +  IN OUT  UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  ASSERT (Value != NULL);
>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>> index 9b20236acfa6..ca21f5dccee5 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>> @@ -295,6 +295,37 @@ InterlockedDecrement (
>>  }
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  If Value is NULL, then ASSERT().
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  A 16-bit value used in a compare operation.
>> +  @param  ExchangeValue A 16-bit value used in an exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InterlockedCompareExchange16 (
>> +  IN OUT  UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  ASSERT (Value != NULL);
>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>> index ceb80aed94f8..6347073fee51 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>> @@ -89,6 +89,50 @@ InternalSyncDecrement (
>>
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN OUT volatile  UINT16           *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +
>> +
>> +  __asm__ __volatile__ (
>> +    "lock                 \n    "
>> +    "cmpxchgw    %3, %1       "
>> +    : "=a" (CompareValue),
>> +      "=m" (*Value)
>> +    : "a"  (CompareValue),
>> +      "r"  (ExchangeValue),
>> +      "m"  (*Value)
>> +    : "memory",
>> +      "cc"
>> +    );
>> +
>> +  return CompareValue;
>> +}
>> +
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
>> new file mode 100644
>> index 000000000000..8fe2aae1a28b
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
>> @@ -0,0 +1,42 @@
>> +;------------------------------------------------------------------------------
>> +;
>> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
>> +; Copyright (c) 2015, 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.
>> +;
>> +; Module Name:
>> +;
>> +;   InterlockedCompareExchange16.Asm
>> +;
>> +; Abstract:
>> +;
>> +;   InterlockedCompareExchange16 function
>> +;
>> +; Notes:
>> +;
>> +;------------------------------------------------------------------------------
>> +
>> +    .code
>> +
>> +;------------------------------------------------------------------------------
>> +; UINT16
>> +; EFIAPI
>> +; InterlockedCompareExchange16 (
>> +;   IN      UINT16                    *Value,
>> +;   IN      UINT16                    CompareValue,
>> +;   IN      UINT16                    ExchangeValue
>> +;   );
>> +;------------------------------------------------------------------------------
>> +InternalSyncCompareExchange16   PROC
>> +    mov     eax, edx
>> +    lock    cmpxchg [rcx], r8w
>> +    ret
>> +InternalSyncCompareExchange16   ENDP
>> +
>> +    END
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>> new file mode 100644
>> index 000000000000..76aa6fbc0e81
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>> @@ -0,0 +1,54 @@
>> +/** @file
>> +  InterlockedCompareExchange16 function
>> +
>> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
>> +  Copyright (c) 2015, 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.
>> +
>> +**/
>> +
>> +/**
>> +  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
>> +**/
>> +
>> +__int16 _InterlockedCompareExchange16(
>> +   __int16 volatile * Destination,
>> +   __int16 Exchange,
>> +   __int16 Comperand
>> +);
>> +
>> +#pragma intrinsic(_InterlockedCompareExchange16)
>> +
>> +/**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
>> +  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
>> +  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
>> +  The compare exchange operation must be performed using MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN      UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
>> +}
>> +
>> --
>> 1.8.3.2
>>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 15/29] Ovmf/Xen: move Xen interface version to <xen.h>
       [not found] ` <1423739961-5945-16-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-19 15:02   ` Anthony PERARD
  0 siblings, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-19 15:02 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, jordan.l.justen, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, michael.d.kinney, lersek

On Thu, Feb 12, 2015 at 07:19:07PM +0800, Ard Biesheuvel wrote:
> Tiancore has its private copy of the Xen headers, and all drivers
> that depend on it should use the same Xen interface version, so
> let's move the #define to xen.h itself.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Acked-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>

-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 16/29] Ovmf/Xen: fix pointer to int cast in XenBusDxe
       [not found] ` <1423739961-5945-17-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-19 15:31   ` Anthony PERARD
  0 siblings, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-19 15:31 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, jordan.l.justen, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, michael.d.kinney, lersek

On Thu, Feb 12, 2015 at 07:19:08PM +0800, Ard Biesheuvel wrote:
> On ARM, xen_pfn_t is 64 bits but the size of a pointer is only
> 32 bits, so casting between them needs to go via (UINTN). Also
> move the xen_pfn_t cast outside the shift so that we can avoid
> shifting 64-bit quantities on 32-bit architectures, which may
> require runtime library support.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>

-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 17/29] Ovmf/Xen: refactor XenBusDxe hypercall implementation
       [not found] ` <1423739961-5945-18-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-19 16:05   ` Anthony PERARD
  0 siblings, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-19 16:05 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, jordan.l.justen, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, michael.d.kinney, lersek

On Thu, Feb 12, 2015 at 07:19:09PM +0800, Ard Biesheuvel wrote:
> This refactors the Xen hypercall implementation that is part of the
> XenBusDxe driver, in preparation of splitting it off entirely into
> a XenHypercallLib library. This involves:
> - removing the dependency on XENBUS_DEVICE* pointers in the XenHypercall()
>   prototypes
> - moving the discovered hyperpage address to a global variable
> - moving XenGetSharedInfoPage() to its only user XenBusDxe.c (the shared info
>   page is not strictly part of the Xen hypercall interface, and is not used
>   by other expected users of XenHypercallLib such as the Xen console version
>   of SerialPortLib
> - reimplement XenHypercall2() in C and move the indexing of the hyperpage
>   there; the existing asm implementations are renamed to __XenHypercall2() and
>   invoked from the new C implementation.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Acked-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  OvmfPkg/XenBusDxe/EventChannel.c      | 11 +++--------
>  OvmfPkg/XenBusDxe/GrantTable.c        |  4 ++--
>  OvmfPkg/XenBusDxe/Ia32/hypercall.nasm |  6 +++---
>  OvmfPkg/XenBusDxe/X64/hypercall.nasm  |  6 +++---
>  OvmfPkg/XenBusDxe/XenBusDxe.c         | 44 +++++++++++++++++++++++++++++++++++++++++++-
>  OvmfPkg/XenBusDxe/XenBusDxe.h         |  1 -
>  OvmfPkg/XenBusDxe/XenHypercall.c      | 61 +++++++++++++++++++++++++------------------------------------
>  OvmfPkg/XenBusDxe/XenHypercall.h      | 28 +++-------------------------
>  OvmfPkg/XenBusDxe/XenStore.c          |  4 ++--
>  9 files changed, 84 insertions(+), 81 deletions(-)
> 


> diff --git a/OvmfPkg/XenBusDxe/XenHypercall.c b/OvmfPkg/XenBusDxe/XenHypercall.c
> index 34d92e76b7e3..19c34bdd0cec 100644
> --- a/OvmfPkg/XenBusDxe/XenHypercall.c
> +++ b/OvmfPkg/XenBusDxe/XenHypercall.c
> @@ -23,9 +23,21 @@
>  #include <IndustryStandard/Xen/hvm/params.h>
>  #include <IndustryStandard/Xen/memory.h>
>  
> +STATIC VOID       *HyperPage;
> +
> +//
> +// Interface exposed by the ASM implementation of the core hypercall
> +//
> +INTN
> +EFIAPI
> +__XenHypercall2 (
> +  IN     VOID *HypercallAddr,
> +  IN OUT INTN Arg1,
> +  IN OUT INTN Arg2
> +  );
> +
>  EFI_STATUS
>  XenHyperpageInit (
> -  IN OUT XENBUS_DEVICE *Dev
>    )
>  {
>    EFI_HOB_GUID_TYPE   *GuidHob;
> @@ -36,24 +48,21 @@ XenHyperpageInit (
>      return EFI_NOT_FOUND;
>    }
>    XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob);
> -  Dev->Hyperpage = XenInfo->HyperPages;
> +  HyperPage = XenInfo->HyperPages;
>    return EFI_SUCCESS;
>  }
>  
>  UINT64
>  XenHypercallHvmGetParam (
> -  IN XENBUS_DEVICE *Dev,
>    IN UINT32        Index
>    )
>  {
>    xen_hvm_param_t     Parameter;
>    INTN                Error;
>  
> -  ASSERT (Dev->Hyperpage != NULL);
> -
>    Parameter.domid = DOMID_SELF;
>    Parameter.index = Index;
> -  Error = XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_hvm_op * 32,
> +  Error = XenHypercall2 (__HYPERVISOR_hvm_op,
>                           HVMOP_get_param, (INTN) &Parameter);
>    if (Error != 0) {
>      DEBUG ((EFI_D_ERROR,
> @@ -66,53 +75,33 @@ XenHypercallHvmGetParam (
>  
>  INTN
>  XenHypercallMemoryOp (
> -  IN     XENBUS_DEVICE *Dev,
>    IN     UINTN Operation,
>    IN OUT VOID *Arguments
>    )
>  {
> -  ASSERT (Dev->Hyperpage != NULL);
> -  return XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_memory_op * 32,
> +  return XenHypercall2 (__HYPERVISOR_memory_op,
>                          Operation, (INTN) Arguments);
>  }
>  
>  INTN
>  XenHypercallEventChannelOp (
> -  IN     XENBUS_DEVICE *Dev,
>    IN     INTN Operation,
>    IN OUT VOID *Arguments
>    )
>  {
> -  ASSERT (Dev->Hyperpage != NULL);
> -  return XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_event_channel_op * 32,
> +  return XenHypercall2 (__HYPERVISOR_event_channel_op,
>                          Operation, (INTN) Arguments);
>  }
>  
> -EFI_STATUS
> -XenGetSharedInfoPage (
> -  IN OUT XENBUS_DEVICE *Dev
> +INTN
> +EFIAPI
> +XenHypercall2 (
> +  IN     INTN HypercallID,

This could be an unsigned since HypercallID should probably not be
negative.

Beside this comment,
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>

> +  IN OUT INTN Arg1,
> +  IN OUT INTN Arg2
>    )
>  {
> -  xen_add_to_physmap_t Parameter;
> +  ASSERT (HyperPage != NULL);
>  
> -  ASSERT (Dev->SharedInfo == NULL);
> -
> -  Parameter.domid = DOMID_SELF;
> -  Parameter.space = XENMAPSPACE_shared_info;
> -  Parameter.idx = 0;
> -
> -  //
> -  // using reserved page because the page is not released when Linux is
> -  // starting because of the add_to_physmap. QEMU might try to access the
> -  // page, and fail because it have no right to do so (segv).
> -  //
> -  Dev->SharedInfo = AllocateReservedPages (1);
> -  Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT;
> -  if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameter) != 0) {
> -    FreePages (Dev->SharedInfo, 1);
> -    Dev->SharedInfo = NULL;
> -    return EFI_LOAD_ERROR;
> -  }
> -
> -  return EFI_SUCCESS;
> +  return __XenHypercall2 ((UINT8*)HyperPage + HypercallID * 32, Arg1, Arg2);
>  }

-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 18/29] Ovmf/Xen: move XenBusDxe hypercall code to separate library
       [not found] ` <1423739961-5945-19-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-19 17:25   ` Anthony PERARD
  0 siblings, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-19 17:25 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, jordan.l.justen, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, michael.d.kinney, lersek

On Thu, Feb 12, 2015 at 07:19:10PM +0800, Ard Biesheuvel wrote:
> This moves all of the Xen hypercall code that was private to XenBusDxe
> to a new library class XenHypercallLib. This will allow us to reimplement
> it for ARM, and to export the Xen hypercall functionality to other parts
> of the code, such as a Xen console SerialPortLib driver.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>

-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 19/29] Ovmf/Xen: introduce XENIO_PROTOCOL
  2015-02-12 11:19 ` [PATCH v4 19/29] Ovmf/Xen: introduce XENIO_PROTOCOL Ard Biesheuvel
@ 2015-02-19 17:30   ` Anthony PERARD
  0 siblings, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-19 17:30 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, jordan.l.justen, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, michael.d.kinney, lersek

On Thu, Feb 12, 2015 at 07:19:11PM +0800, Ard Biesheuvel wrote:
> This introduces the abstract XENIO_PROTOCOL that will be used to
> communicate the Xen grant table address to drivers supporting this
> protocol. Primary purpose is allowing us to change the XenBusDxe
> implementation so that it can support non-PCI Xen implementations
> such as Xen on ARM.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>


-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 20/29] Ovmf/Xen: add separate driver for Xen PCI device
       [not found] ` <1423739961-5945-21-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-19 18:43   ` Anthony PERARD
  0 siblings, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-19 18:43 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, jordan.l.justen, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, michael.d.kinney, lersek

On Thu, Feb 12, 2015 at 07:19:12PM +0800, Ard Biesheuvel wrote:
> Prepare for making XenBusDxe suitable for use with non-PCI devices
> (such as the DT node exposed by Xen on ARM) by introducing a separate
> DXE driver that binds to the Xen virtual PCI device and exposes the
> abstract XENIO_PROTOCOL for XenBusDxe to bind against.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>

-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 21/29] Ovmf/Xen: move XenBusDxe to abstract XENIO_PROTOCOL
       [not found] ` <1423739961-5945-22-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-20 14:10   ` Anthony PERARD
  0 siblings, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-20 14:10 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, jordan.l.justen, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, michael.d.kinney, lersek

On Thu, Feb 12, 2015 at 07:19:13PM +0800, Ard Biesheuvel wrote:
> While Xen on Intel uses a virtual PCI device to communicate the
> base address of the grant table, the ARM implementation uses a DT
> node, which is fundamentally incompatible with the way XenBusDxe is
> implemented, i.e., as a UEFI Driver Model implementation for a PCI
> device.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Acked-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>

-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 23/29] Ovmf/Xen: port XenBusDxe to other architectures
       [not found] ` <1423739961-5945-24-git-send-email-ard.biesheuvel@linaro.org>
@ 2015-02-23 15:16   ` Anthony PERARD
       [not found]   ` <20150223151617.GU1345@perard.uk.xensource.com>
  1 sibling, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-23 15:16 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: feng.tian, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, jordan.l.justen, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, michael.d.kinney, lersek

On Thu, Feb 12, 2015 at 07:19:15PM +0800, Ard Biesheuvel wrote:
> This patch updates XenBusDxe to use the 16-bit compare and exchange
> function that was introduced for this purpose to the
> BaseSynchronizationLib. It also provides a new generic implementation
> of TestAndClearBit () using the same 16-bit compare and exchange, making
> this module fully architecture agnostic.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  OvmfPkg/XenBusDxe/GrantTable.c                           |  2 +-
>  OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm | 42 ------------------------------------------
>  OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm              | 16 ----------------
>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c         | 33 ---------------------------------
>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h         | 38 --------------------------------------
>  OvmfPkg/XenBusDxe/TestAndClearBit.c                      | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm  | 41 -----------------------------------------
>  OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm               | 15 ---------------
>  OvmfPkg/XenBusDxe/XenBusDxe.h                            |  2 +-
>  OvmfPkg/XenBusDxe/XenBusDxe.inf                          | 12 ++----------
>  10 files changed, 50 insertions(+), 197 deletions(-)
> 
> diff --git a/OvmfPkg/XenBusDxe/TestAndClearBit.c b/OvmfPkg/XenBusDxe/TestAndClearBit.c
> new file mode 100644
> index 000000000000..e971b40a89ce
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/TestAndClearBit.c
> @@ -0,0 +1,46 @@
> +/** @file
> +  Implementation of TestAndClearBit using compare-exchange primitive
> +
> +  Copyright (C) 2015, Linaro Ltd.
> +
> +  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 <Base.h>
> +#include <Library/SynchronizationLib.h>
> +
> +INT32
> +EFIAPI
> +TestAndClearBit (
> +  IN INT32            Bit,
> +  IN VOID             *Address
> +  )
> +{
> +  UINT16    Word;
> +  UINT16    Mask;
> +
> +  //
> +  // Calculate the effective address relative to 'Address' based on the
> +  // higher order bits of 'Bit'. Use signed shift instead of division to
> +  // ensure we round towards -Inf, and end up with a positive shift in
> +  // 'Bit', even if 'Bit' itself is negative.
> +  //
> +  Address += (Bit >> 4) * sizeof(UINT16);
> +
> +  Word = *(UINT16 *)Address;
> +  Mask = 1U << (Bit & 15);
> +
> +  while (Word & Mask) {
> +    if (Word == InterlockedCompareExchange16 (Address, Word, Word & ~Mask)) {

I think there is an infinite loop here, if the value pointed by Address
change between "Word = *Address" and this call to
InterlockedCompareExchange16.

> +      return 1;
> +    }
> +  }
> +  return 0;
> +}
> diff --git a/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm b/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm
> deleted file mode 100644
> index a4859a62a250..000000000000
> --- a/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm
> +++ /dev/null
> @@ -1,15 +0,0 @@
> -DEFAULT REL
> -SECTION .text
> -
> -; INT32
> -; EFIAPI
> -; TestAndClearBit (
> -;   IN  INT32 Bit,                // rcx
> -;   IN  volatile VOID* Address    // rdx
> -;   );
> -global ASM_PFX(TestAndClearBit)
> -ASM_PFX(TestAndClearBit):
> -  lock btr [rdx], ecx
> -  sbb eax, eax
> -  ret
> -
> diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
> index 6c306e017b07..953e4b72e85e 100644
> --- a/OvmfPkg/XenBusDxe/XenBusDxe.h
> +++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
> @@ -122,7 +122,7 @@ INT32
>  EFIAPI
>  TestAndClearBit (
>    IN INT32 Bit,
> -  IN volatile VOID *Address
> +  IN VOID  *Address
>    );
>  
>  CHAR8*
> diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> index 31553ac5a64a..f0c5db98b1f4 100644
> --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
> +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> @@ -34,8 +34,6 @@
>    DriverBinding.h
>    ComponentName.c
>    ComponentName.h
> -  InterlockedCompareExchange16.c
> -  InterlockedCompareExchange16.h
>    GrantTable.c
>    GrantTable.h
>    EventChannel.c
> @@ -45,14 +43,7 @@
>    XenBus.c
>    XenBus.h
>    Helpers.c
> -
> -[Sources.IA32]
> -  Ia32/InterlockedCompareExchange16.nasm
> -  Ia32/TestAndClearBit.nasm
> -
> -[Sources.X64]
> -  X64/InterlockedCompareExchange16.nasm
> -  X64/TestAndClearBit.nasm
> +  TestAndClearBit.c
>  
>  [LibraryClasses]
>    UefiDriverEntryPoint
> @@ -64,6 +55,7 @@
>    DevicePathLib
>    DebugLib
>    XenHypercallLib
> +  SynchronizationLib
>  
>  [Protocols]
>    gEfiDriverBindingProtocolGuid

-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 23/29] Ovmf/Xen: port XenBusDxe to other architectures
       [not found]   ` <20150223151617.GU1345@perard.uk.xensource.com>
@ 2015-02-23 17:54     ` Ard Biesheuvel
       [not found]     ` <CAKv+Gu-EA3q4z89WxSZbQ9BUjFU9tnGEQRmEBxjzqM+-_bCuVw@mail.gmail.com>
  1 sibling, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-23 17:54 UTC (permalink / raw)
  To: Anthony PERARD
  Cc: Tian, Feng, Julien Grall, Ian Campbell, Olivier Martin,
	Stefano Stabellini, Jordan Justen, edk2-devel, Leif Lindholm,
	xen-devel, Roy Franz, Kinney, Michael D, Laszlo Ersek

On 23 February 2015 at 15:16, Anthony PERARD <anthony.perard@citrix.com> wrote:
> On Thu, Feb 12, 2015 at 07:19:15PM +0800, Ard Biesheuvel wrote:
>> This patch updates XenBusDxe to use the 16-bit compare and exchange
>> function that was introduced for this purpose to the
>> BaseSynchronizationLib. It also provides a new generic implementation
>> of TestAndClearBit () using the same 16-bit compare and exchange, making
>> this module fully architecture agnostic.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  OvmfPkg/XenBusDxe/GrantTable.c                           |  2 +-
>>  OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm | 42 ------------------------------------------
>>  OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm              | 16 ----------------
>>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c         | 33 ---------------------------------
>>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h         | 38 --------------------------------------
>>  OvmfPkg/XenBusDxe/TestAndClearBit.c                      | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>>  OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm  | 41 -----------------------------------------
>>  OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm               | 15 ---------------
>>  OvmfPkg/XenBusDxe/XenBusDxe.h                            |  2 +-
>>  OvmfPkg/XenBusDxe/XenBusDxe.inf                          | 12 ++----------
>>  10 files changed, 50 insertions(+), 197 deletions(-)
>>
>> diff --git a/OvmfPkg/XenBusDxe/TestAndClearBit.c b/OvmfPkg/XenBusDxe/TestAndClearBit.c
>> new file mode 100644
>> index 000000000000..e971b40a89ce
>> --- /dev/null
>> +++ b/OvmfPkg/XenBusDxe/TestAndClearBit.c
>> @@ -0,0 +1,46 @@
>> +/** @file
>> +  Implementation of TestAndClearBit using compare-exchange primitive
>> +
>> +  Copyright (C) 2015, Linaro Ltd.
>> +
>> +  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 <Base.h>
>> +#include <Library/SynchronizationLib.h>
>> +
>> +INT32
>> +EFIAPI
>> +TestAndClearBit (
>> +  IN INT32            Bit,
>> +  IN VOID             *Address
>> +  )
>> +{
>> +  UINT16    Word;
>> +  UINT16    Mask;
>> +
>> +  //
>> +  // Calculate the effective address relative to 'Address' based on the
>> +  // higher order bits of 'Bit'. Use signed shift instead of division to
>> +  // ensure we round towards -Inf, and end up with a positive shift in
>> +  // 'Bit', even if 'Bit' itself is negative.
>> +  //
>> +  Address += (Bit >> 4) * sizeof(UINT16);
>> +
>> +  Word = *(UINT16 *)Address;
>> +  Mask = 1U << (Bit & 15);
>> +
>> +  while (Word & Mask) {
>> +    if (Word == InterlockedCompareExchange16 (Address, Word, Word & ~Mask)) {
>
> I think there is an infinite loop here, if the value pointed by Address
> change between "Word = *Address" and this call to
> InterlockedCompareExchange16.
>

You're quite right. I need to re-read Word at every iteration,
something like (with UINT16 Read added):

  for (Word = *(UINT16 *) Address; Word & Mask; Word = Read) {
    Read = InterlockedCompareExchange16 (Address, Word, Word & ~Mask);
    if (Read == Word) {
      return 1;
    }
  }

perhaps?


>> +      return 1;
>> +    }
>> +  }
>> +  return 0;
>> +}
>> diff --git a/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm b/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm
>> deleted file mode 100644
>> index a4859a62a250..000000000000
>> --- a/OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm
>> +++ /dev/null
>> @@ -1,15 +0,0 @@
>> -DEFAULT REL
>> -SECTION .text
>> -
>> -; INT32
>> -; EFIAPI
>> -; TestAndClearBit (
>> -;   IN  INT32 Bit,                // rcx
>> -;   IN  volatile VOID* Address    // rdx
>> -;   );
>> -global ASM_PFX(TestAndClearBit)
>> -ASM_PFX(TestAndClearBit):
>> -  lock btr [rdx], ecx
>> -  sbb eax, eax
>> -  ret
>> -
>> diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
>> index 6c306e017b07..953e4b72e85e 100644
>> --- a/OvmfPkg/XenBusDxe/XenBusDxe.h
>> +++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
>> @@ -122,7 +122,7 @@ INT32
>>  EFIAPI
>>  TestAndClearBit (
>>    IN INT32 Bit,
>> -  IN volatile VOID *Address
>> +  IN VOID  *Address
>>    );
>>
>>  CHAR8*
>> diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
>> index 31553ac5a64a..f0c5db98b1f4 100644
>> --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
>> +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
>> @@ -34,8 +34,6 @@
>>    DriverBinding.h
>>    ComponentName.c
>>    ComponentName.h
>> -  InterlockedCompareExchange16.c
>> -  InterlockedCompareExchange16.h
>>    GrantTable.c
>>    GrantTable.h
>>    EventChannel.c
>> @@ -45,14 +43,7 @@
>>    XenBus.c
>>    XenBus.h
>>    Helpers.c
>> -
>> -[Sources.IA32]
>> -  Ia32/InterlockedCompareExchange16.nasm
>> -  Ia32/TestAndClearBit.nasm
>> -
>> -[Sources.X64]
>> -  X64/InterlockedCompareExchange16.nasm
>> -  X64/TestAndClearBit.nasm
>> +  TestAndClearBit.c
>>
>>  [LibraryClasses]
>>    UefiDriverEntryPoint
>> @@ -64,6 +55,7 @@
>>    DevicePathLib
>>    DebugLib
>>    XenHypercallLib
>> +  SynchronizationLib
>>
>>  [Protocols]
>>    gEfiDriverBindingProtocolGuid
>
> --
> Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 23/29] Ovmf/Xen: port XenBusDxe to other architectures
       [not found]     ` <CAKv+Gu-EA3q4z89WxSZbQ9BUjFU9tnGEQRmEBxjzqM+-_bCuVw@mail.gmail.com>
@ 2015-02-23 18:25       ` Anthony PERARD
  0 siblings, 0 replies; 46+ messages in thread
From: Anthony PERARD @ 2015-02-23 18:25 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Tian, Feng, Julien Grall, Ian Campbell, Olivier Martin,
	Stefano Stabellini, Jordan Justen, edk2-devel, Leif Lindholm,
	xen-devel, Roy Franz, Kinney, Michael D, Laszlo Ersek

On Mon, Feb 23, 2015 at 05:54:03PM +0000, Ard Biesheuvel wrote:
> On 23 February 2015 at 15:16, Anthony PERARD <anthony.perard@citrix.com> wrote:
> > On Thu, Feb 12, 2015 at 07:19:15PM +0800, Ard Biesheuvel wrote:
> >> This patch updates XenBusDxe to use the 16-bit compare and exchange
> >> function that was introduced for this purpose to the
> >> BaseSynchronizationLib. It also provides a new generic implementation
> >> of TestAndClearBit () using the same 16-bit compare and exchange, making
> >> this module fully architecture agnostic.
> >>
> >> Contributed-under: TianoCore Contribution Agreement 1.0
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> ---
> >>  OvmfPkg/XenBusDxe/GrantTable.c                           |  2 +-
> >>  OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.nasm | 42 ------------------------------------------
> >>  OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.nasm              | 16 ----------------
> >>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c         | 33 ---------------------------------
> >>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h         | 38 --------------------------------------
> >>  OvmfPkg/XenBusDxe/TestAndClearBit.c                      | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> >>  OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.nasm  | 41 -----------------------------------------
> >>  OvmfPkg/XenBusDxe/X64/TestAndClearBit.nasm               | 15 ---------------
> >>  OvmfPkg/XenBusDxe/XenBusDxe.h                            |  2 +-
> >>  OvmfPkg/XenBusDxe/XenBusDxe.inf                          | 12 ++----------
> >>  10 files changed, 50 insertions(+), 197 deletions(-)
> >>
> >> diff --git a/OvmfPkg/XenBusDxe/TestAndClearBit.c b/OvmfPkg/XenBusDxe/TestAndClearBit.c
> >> new file mode 100644
> >> index 000000000000..e971b40a89ce
> >> --- /dev/null
> >> +++ b/OvmfPkg/XenBusDxe/TestAndClearBit.c
> >> @@ -0,0 +1,46 @@
> >> +/** @file
> >> +  Implementation of TestAndClearBit using compare-exchange primitive
> >> +
> >> +  Copyright (C) 2015, Linaro Ltd.
> >> +
> >> +  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 <Base.h>
> >> +#include <Library/SynchronizationLib.h>
> >> +
> >> +INT32
> >> +EFIAPI
> >> +TestAndClearBit (
> >> +  IN INT32            Bit,
> >> +  IN VOID             *Address
> >> +  )
> >> +{
> >> +  UINT16    Word;
> >> +  UINT16    Mask;
> >> +
> >> +  //
> >> +  // Calculate the effective address relative to 'Address' based on the
> >> +  // higher order bits of 'Bit'. Use signed shift instead of division to
> >> +  // ensure we round towards -Inf, and end up with a positive shift in
> >> +  // 'Bit', even if 'Bit' itself is negative.
> >> +  //
> >> +  Address += (Bit >> 4) * sizeof(UINT16);
> >> +
> >> +  Word = *(UINT16 *)Address;
> >> +  Mask = 1U << (Bit & 15);
> >> +
> >> +  while (Word & Mask) {
> >> +    if (Word == InterlockedCompareExchange16 (Address, Word, Word & ~Mask)) {
> >
> > I think there is an infinite loop here, if the value pointed by Address
> > change between "Word = *Address" and this call to
> > InterlockedCompareExchange16.
> >
> 
> You're quite right. I need to re-read Word at every iteration,
> something like (with UINT16 Read added):
> 
>   for (Word = *(UINT16 *) Address; Word & Mask; Word = Read) {
>     Read = InterlockedCompareExchange16 (Address, Word, Word & ~Mask);
>     if (Read == Word) {
>       return 1;
>     }
>   }
> 
> perhaps?

Yes, that looks correct now.
Thanks,

> 
> >> +      return 1;
> >> +    }
> >> +  }
> >> +  return 0;
> >> +}

-- 
Anthony PERARD

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
       [not found]     ` <CAKv+Gu8M-V4Vgf2+sHLZS+n37Qbm+TxJpFpU27qDfHt=gR3+Bw@mail.gmail.com>
@ 2015-02-23 20:33       ` Ard Biesheuvel
  0 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-23 20:33 UTC (permalink / raw)
  To: Jordan Justen
  Cc: Tian, Feng, Julien Grall, Ian Campbell, Olivier Martin,
	Stefano Stabellini, edk2-devel, Leif Lindholm, xen-devel,
	Roy Franz, Kinney, Michael D, Anthony PERARD, Laszlo Ersek

On 18 February 2015 at 08:37, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 17 February 2015 at 18:40, Jordan Justen <jordan.l.justen@intel.com> wrote:
>> Ard,
>>
>> For the subject, I think
>> MdePkg/BaseSynchronizationLib: Add InterlockedCompareExchange16
>> would be better.
>>
>
> OK
>
>> Acked-by: Jordan Justen <jordan.l.justen@intel.com>
>>
>
> Thanks
>
>> Thanks for working to move this to a common location.
>>
>
> No problem
>
>> Mike,
>>
>> I think Anthony tested the IA32 and X64 implementations with Xen. For
>> IPF, I don't think it has been tested.
>>
>
> As mentioned in the other thread, Anthony seems to be incommunicado,
> and some other of the Xen guys have replied that Xen on OVMF/x86 is
> broken for other reasons so they cannot positively confirm that
> everything still works, even though the x86 changes other than the
> PCI/xenbus split are primarily refactoring of existing code.
>
> As far as IPF is concerned: I don't think Xen or Ovmf can be built for
> IPF anyway, but I think a build test and visual inspection of the .S
> file should be sufficient here?
>

Hello Jordan, Michael,

As I mentioned in the other thread, this series is now tested on ARM
and x86, and no regressions were reported.
The only thing holding back this series is the confirmation that the
IPF build has not been broken by introducing the
InterlockedCompareExchange16() function, which i would gladly test
myself, but I really don't have access to the required build
environment.

So please, could you have a look, or perhaps appoint someone else to
handle it in your place?

Thanks,
Ard.


>> On 2015-02-12 03:19:06, Ard Biesheuvel wrote:
>>> This implements the function InterlockedCompareExchange16 () for all
>>> architectures, using architecture and toolchain specific intrinsics
>>> or primitive assembler instructions.
>>>
>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>> Reviewed-by: Olivier Martin <olivier.martin@arm.com>
>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>> ---
>>>  MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
>>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  17 files changed, 622 insertions(+)
>>>
>>> diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
>>> index f97569739914..7b97683ca0af 100644
>>> --- a/MdePkg/Include/Library/SynchronizationLib.h
>>> +++ b/MdePkg/Include/Library/SynchronizationLib.h
>>> @@ -184,6 +184,32 @@ InterlockedDecrement (
>>>
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  If Value is NULL, then ASSERT().
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InterlockedCompareExchange16 (
>>> +  IN OUT  UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  );
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>>> index 601b00495f26..ecb87fc12755 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>>> @@ -16,12 +16,56 @@
>>>  .text
>>>  .align 3
>>>
>>> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>>>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>>>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>>>  GCC_ASM_EXPORT(InternalSyncIncrement)
>>>  GCC_ASM_EXPORT(InternalSyncDecrement)
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +//UINT16
>>> +//EFIAPI
>>> +//InternalSyncCompareExchange16 (
>>> +//  IN      volatile UINT16           *Value,
>>> +//  IN      UINT16                    CompareValue,
>>> +//  IN      UINT16                    ExchangeValue
>>> +//  )
>>> +ASM_PFX(InternalSyncCompareExchange16):
>>> +  uxth    w1, w1
>>> +  uxth    w2, w2
>>> +  dmb     sy
>>> +
>>> +InternalSyncCompareExchange16Again:
>>> +  ldxrh   w3, [x0]
>>> +  cmp     w3, w1
>>> +  bne     InternalSyncCompareExchange16Fail
>>> +
>>> +InternalSyncCompareExchange16Exchange:
>>> +  stxrh   w4, w2, [x0]
>>> +  cbnz    w4, InternalSyncCompareExchange16Again
>>> +
>>> +InternalSyncCompareExchange16Fail:
>>> +  dmb     sy
>>> +  mov     w0, w3
>>> +  ret
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>>> index 0128f8f016bd..d699eb40d2a2 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>>> @@ -1,6 +1,7 @@
>>>  //  Implementation of synchronization functions for ARM architecture
>>>  //
>>>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
>>> +//  Copyright (c) 2015, 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
>>> @@ -15,12 +16,55 @@
>>>  .text
>>>  .align 3
>>>
>>> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>>>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>>>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>>>  GCC_ASM_EXPORT(InternalSyncIncrement)
>>>  GCC_ASM_EXPORT(InternalSyncDecrement)
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +//UINT16
>>> +//EFIAPI
>>> +//InternalSyncCompareExchange16 (
>>> +//  IN      volatile UINT16           *Value,
>>> +//  IN      UINT16                    CompareValue,
>>> +//  IN      UINT16                    ExchangeValue
>>> +//  )
>>> +ASM_PFX(InternalSyncCompareExchange16):
>>> +  dmb
>>> +
>>> +InternalSyncCompareExchange16Again:
>>> +  ldrexh  r3, [r0]
>>> +  cmp     r3, r1
>>> +  bne     InternalSyncCompareExchange16Fail
>>> +
>>> +InternalSyncCompareExchange16Exchange:
>>> +  strexh  ip, r2, [r0]
>>> +  cmp     ip, #0
>>> +  bne     InternalSyncCompareExchange16Again
>>> +
>>> +InternalSyncCompareExchange16Fail:
>>> +  dmb
>>> +  mov     r0, r3
>>> +  bx      lr
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>>> index f9f80737774a..dbc599114093 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>>> @@ -1,6 +1,7 @@
>>>  //  Implementation of synchronization functions for ARM architecture
>>>  //
>>>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
>>> +//  Copyright (c) 2015, 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
>>> @@ -12,6 +13,7 @@
>>>  //
>>>  //
>>>
>>> +    EXPORT  InternalSyncCompareExchange16
>>>      EXPORT  InternalSyncCompareExchange32
>>>      EXPORT  InternalSyncCompareExchange64
>>>      EXPORT  InternalSyncIncrement
>>> @@ -20,6 +22,48 @@
>>>      AREA   ArmSynchronization, CODE, READONLY
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +//UINT16
>>> +//EFIAPI
>>> +//InternalSyncCompareExchange16 (
>>> +//  IN      volatile UINT16           *Value,
>>> +//  IN      UINT16                    CompareValue,
>>> +//  IN      UINT16                    ExchangeValue
>>> +//  )
>>> +InternalSyncCompareExchange16
>>> +  dmb
>>> +
>>> +InternalSyncCompareExchange16Again
>>> +  ldrexh  r3, [r0]
>>> +  cmp     r3, r1
>>> +  bne     InternalSyncCompareExchange16Fail
>>> +
>>> +InternalSyncCompareExchange16Exchange
>>> +  strexh  ip, r2, [r0]
>>> +  cmp     ip, #0
>>> +  bne     InternalSyncCompareExchange16Again
>>> +
>>> +InternalSyncCompareExchange16Fail
>>> +  dmb
>>> +  mov     r0, r3
>>> +  bx      lr
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>>> index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
>>> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>>> @@ -32,12 +32,14 @@
>>>  [Sources.IA32]
>>>    Ia32/InterlockedCompareExchange64.c | MSFT
>>>    Ia32/InterlockedCompareExchange32.c | MSFT
>>> +  Ia32/InterlockedCompareExchange16.c | MSFT
>>>    Ia32/InterlockedDecrement.c | MSFT
>>>    Ia32/InterlockedIncrement.c | MSFT
>>>    SynchronizationMsc.c  | MSFT
>>>
>>>    Ia32/InterlockedCompareExchange64.asm | INTEL
>>>    Ia32/InterlockedCompareExchange32.asm | INTEL
>>> +  Ia32/InterlockedCompareExchange16.asm | INTEL
>>>    Ia32/InterlockedDecrement.asm | INTEL
>>>    Ia32/InterlockedIncrement.asm | INTEL
>>>    Synchronization.c | INTEL
>>> @@ -48,9 +50,11 @@
>>>  [Sources.X64]
>>>    X64/InterlockedCompareExchange64.c | MSFT
>>>    X64/InterlockedCompareExchange32.c | MSFT
>>> +  X64/InterlockedCompareExchange16.c | MSFT
>>>
>>>    X64/InterlockedCompareExchange64.asm | INTEL
>>>    X64/InterlockedCompareExchange32.asm | INTEL
>>> +  X64/InterlockedCompareExchange16.asm | INTEL
>>>
>>>    X64/InterlockedDecrement.c | MSFT
>>>    X64/InterlockedIncrement.c | MSFT
>>> @@ -67,6 +71,7 @@
>>>    Ipf/Synchronization.c
>>>    Ipf/InterlockedCompareExchange64.s
>>>    Ipf/InterlockedCompareExchange32.s
>>> +  Ipf/InterlockedCompareExchange16.s
>>>
>>>    Synchronization.c     | INTEL
>>>    SynchronizationMsc.c  | MSFT
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>>> index e42824c75d12..76f702324156 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>>> @@ -63,6 +63,32 @@ InternalSyncDecrement (
>>>
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  A 16-bit value used in compare operation.
>>> +  @param  ExchangeValue A 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN      volatile UINT16           *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  );
>>> +
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>>> index 9c34b9f128ed..a57860203b12 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>>> @@ -13,6 +13,37 @@
>>>  **/
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit
>>> +  unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit
>>> +  unsigned integer specified by Value.  If Value is equal to
>>> +  CompareValue, then Value is set to ExchangeValue and
>>> +  CompareValue is returned.  If Value is not equal to
>>> +  CompareValue, then Value is returned. The compare exchange
>>> +  operation must be performed using MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the
>>> +                        compare exchange operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN      volatile UINT16           *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  return *Value != CompareValue ? *Value :
>>> +           ((*Value = ExchangeValue), CompareValue);
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit
>>>    unsigned integer.
>>>
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>>> index b5a7827fc0e8..bd81aad6c243 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>>> @@ -88,6 +88,48 @@ InternalSyncDecrement (
>>>  }
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN OUT volatile  UINT16           *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +
>>> +  __asm__ __volatile__ (
>>> +    "                     \n    "
>>> +    "lock                 \n    "
>>> +    "cmpxchgw    %1, %2   \n    "
>>> +    : "=a" (CompareValue)
>>> +    : "q"  (ExchangeValue),
>>> +      "m"  (*Value),
>>> +      "0"  (CompareValue)
>>> +    : "memory",
>>> +      "cc"
>>> +    );
>>> +
>>> +  return CompareValue;
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
>>> new file mode 100644
>>> index 000000000000..f8705042661d
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
>>> @@ -0,0 +1,46 @@
>>> +;------------------------------------------------------------------------------
>>> +;
>>> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
>>> +; Copyright (c) 2015, 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.
>>> +;
>>> +; Module Name:
>>> +;
>>> +;   InterlockedCompareExchange16.Asm
>>> +;
>>> +; Abstract:
>>> +;
>>> +;   InterlockedCompareExchange16 function
>>> +;
>>> +; Notes:
>>> +;
>>> +;------------------------------------------------------------------------------
>>> +
>>> +    .486
>>> +    .model  flat,C
>>> +    .code
>>> +
>>> +;------------------------------------------------------------------------------
>>> +; UINT16
>>> +; EFIAPI
>>> +; InternalSyncCompareExchange16 (
>>> +;   IN      UINT16                    *Value,
>>> +;   IN      UINT16                    CompareValue,
>>> +;   IN      UINT16                    ExchangeValue
>>> +;   );
>>> +;------------------------------------------------------------------------------
>>> +InternalSyncCompareExchange16   PROC
>>> +    mov     ecx, [esp + 4]
>>> +    mov     eax, [esp + 8]
>>> +    mov     edx, [esp + 12]
>>> +    lock    cmpxchg [ecx], dx
>>> +    ret
>>> +InternalSyncCompareExchange16   ENDP
>>> +
>>> +    END
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
>>> new file mode 100644
>>> index 000000000000..3d06dd9baa63
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
>>> @@ -0,0 +1,51 @@
>>> +/** @file
>>> +  InterlockedCompareExchange16 function
>>> +
>>> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
>>> +  Copyright (c) 2015, 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.
>>> +
>>> +**/
>>> +
>>> +
>>> +
>>> +
>>> +/**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN      UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  _asm {
>>> +    mov     ecx, Value
>>> +    mov     eax, CompareValue
>>> +    mov     edx, ExchangeValue
>>> +    lock    cmpxchg [ecx], dx
>>> +  }
>>> +}
>>> +
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>>> new file mode 100644
>>> index 000000000000..1e56942a98cb
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>>> @@ -0,0 +1,30 @@
>>> +/// @file
>>> +///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
>>> +///   based architecture.
>>> +///
>>> +/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
>>> +/// Copyright (c) 2015, 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.
>>> +///
>>> +/// Module Name:  InterlockedCompareExchange16.s
>>> +///
>>> +///
>>> +
>>> +.auto
>>> +.text
>>> +
>>> +.proc   InternalSyncCompareExchange16
>>> +.type   InternalSyncCompareExchange16, @function
>>> +InternalSyncCompareExchange16::
>>> +        zxt2                r33 = r33
>>> +        mov                 ar.ccv = r33
>>> +        cmpxchg2.rel        r8  = [r32], r34
>>> +        mf
>>> +        br.ret.sptk.many    b0
>>> +.endp   InternalSyncCompareExchange16
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>>> index 0eea40ba1622..4218a265a0ec 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>>> @@ -277,6 +277,37 @@ InterlockedDecrement (
>>>  }
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  If Value is NULL, then ASSERT().
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InterlockedCompareExchange16 (
>>> +  IN OUT  UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  ASSERT (Value != NULL);
>>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>>> index badf73c1a6ce..587f5a771c35 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>>> @@ -293,6 +293,37 @@ InterlockedDecrement (
>>>  }
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  If Value is NULL, then ASSERT().
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  A 16-bit value used in compare operation.
>>> +  @param  ExchangeValue A 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InterlockedCompareExchange16 (
>>> +  IN OUT  UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  ASSERT (Value != NULL);
>>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>>> index 9b20236acfa6..ca21f5dccee5 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>>> @@ -295,6 +295,37 @@ InterlockedDecrement (
>>>  }
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  If Value is NULL, then ASSERT().
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  A 16-bit value used in a compare operation.
>>> +  @param  ExchangeValue A 16-bit value used in an exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InterlockedCompareExchange16 (
>>> +  IN OUT  UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  ASSERT (Value != NULL);
>>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>>> index ceb80aed94f8..6347073fee51 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>>> @@ -89,6 +89,50 @@ InternalSyncDecrement (
>>>
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN OUT volatile  UINT16           *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +
>>> +
>>> +  __asm__ __volatile__ (
>>> +    "lock                 \n    "
>>> +    "cmpxchgw    %3, %1       "
>>> +    : "=a" (CompareValue),
>>> +      "=m" (*Value)
>>> +    : "a"  (CompareValue),
>>> +      "r"  (ExchangeValue),
>>> +      "m"  (*Value)
>>> +    : "memory",
>>> +      "cc"
>>> +    );
>>> +
>>> +  return CompareValue;
>>> +}
>>> +
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
>>> new file mode 100644
>>> index 000000000000..8fe2aae1a28b
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
>>> @@ -0,0 +1,42 @@
>>> +;------------------------------------------------------------------------------
>>> +;
>>> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
>>> +; Copyright (c) 2015, 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.
>>> +;
>>> +; Module Name:
>>> +;
>>> +;   InterlockedCompareExchange16.Asm
>>> +;
>>> +; Abstract:
>>> +;
>>> +;   InterlockedCompareExchange16 function
>>> +;
>>> +; Notes:
>>> +;
>>> +;------------------------------------------------------------------------------
>>> +
>>> +    .code
>>> +
>>> +;------------------------------------------------------------------------------
>>> +; UINT16
>>> +; EFIAPI
>>> +; InterlockedCompareExchange16 (
>>> +;   IN      UINT16                    *Value,
>>> +;   IN      UINT16                    CompareValue,
>>> +;   IN      UINT16                    ExchangeValue
>>> +;   );
>>> +;------------------------------------------------------------------------------
>>> +InternalSyncCompareExchange16   PROC
>>> +    mov     eax, edx
>>> +    lock    cmpxchg [rcx], r8w
>>> +    ret
>>> +InternalSyncCompareExchange16   ENDP
>>> +
>>> +    END
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>>> new file mode 100644
>>> index 000000000000..76aa6fbc0e81
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>>> @@ -0,0 +1,54 @@
>>> +/** @file
>>> +  InterlockedCompareExchange16 function
>>> +
>>> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
>>> +  Copyright (c) 2015, 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.
>>> +
>>> +**/
>>> +
>>> +/**
>>> +  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
>>> +**/
>>> +
>>> +__int16 _InterlockedCompareExchange16(
>>> +   __int16 volatile * Destination,
>>> +   __int16 Exchange,
>>> +   __int16 Comperand
>>> +);
>>> +
>>> +#pragma intrinsic(_InterlockedCompareExchange16)
>>> +
>>> +/**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
>>> +  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
>>> +  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
>>> +  The compare exchange operation must be performed using MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN      UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
>>> +}
>>> +
>>> --
>>> 1.8.3.2
>>>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
       [not found] ` <1423739961-5945-15-git-send-email-ard.biesheuvel@linaro.org>
  2015-02-17 17:40   ` [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange Jordan Justen
       [not found]   ` <20150217174047.8141.17529@jljusten-ivy>
@ 2015-02-25 21:56   ` Kinney, Michael D
       [not found]   ` <E92EE9817A31E24EB0585FDF735412F563081986@ORSMSX113.amr.corp.intel.com>
  3 siblings, 0 replies; 46+ messages in thread
From: Kinney, Michael D @ 2015-02-25 21:56 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel, olivier.martin, lersek, roy.franz,
	leif.lindholm, stefano.stabellini, ian.campbell, anthony.perard,
	xen-devel, julien.grall, Justen, Jordan L, Tian, Feng, Kinney,
	Michael D

Ard Biesheuvel,

Thank you for providing the implementation of this new function for all supported CPU architectures.  The one for IPF looks correct and passes builds.  However, I am seeing some build breaks and some issues with the IA32 and X64 versions.  The following changes are required to your patch to build with VS20xx compilers and for the code generated by asm/Inline asm to match code generated by VS20xx compiler intrinsics.  I have not built and disassembled GCC yet, but I think GCC inline asm should generate the expected 16-bit register load operations that have been addressed here.

--- Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm	Mon Jan 19 14:26:36 1970
+++ Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm	Mon Jan 19 14:26:36 1970
@@ -37,8 +37,8 @@
 ;------------------------------------------------------------------------------
 InternalSyncCompareExchange16   PROC
     mov     ecx, [esp + 4]
-    mov     eax, [esp + 8]
-    mov     edx, [esp + 12]
+    mov     ax, [esp + 8]
+    mov     dx, [esp + 12]
     lock    cmpxchg [ecx], dx
     ret
 InternalSyncCompareExchange16   ENDP
--- Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c	Mon Jan 19 14:26:36 1970
+++ Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c	Mon Jan 19 14:26:36 1970
@@ -43,8 +43,8 @@
 {
   _asm {
     mov     ecx, Value
-    mov     eax, CompareValue
-    mov     edx, ExchangeValue
+    mov     ax, CompareValue
+    mov     dx, ExchangeValue
     lock    cmpxchg [ecx], dx
   }
 }
--- Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm	Mon Jan 19 14:26:36 1970
+++ Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm	Mon Jan 19 14:26:36 1970
@@ -34,7 +34,7 @@
 ;   );
 ;------------------------------------------------------------------------------
 InternalSyncCompareExchange16   PROC
-    mov     eax, edx
+    mov     ax, dx
     lock    cmpxchg [rcx], r8w
     ret
 InternalSyncCompareExchange16   ENDP

Best regards,

Mike

-----Original Message-----
From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] 
Sent: Thursday, February 12, 2015 3:19 AM
To: edk2-devel@lists.sourceforge.net; olivier.martin@arm.com; lersek@redhat.com; roy.franz@linaro.org; leif.lindholm@linaro.org; stefano.stabellini@eu.citrix.com; ian.campbell@citrix.com; anthony.perard@citrix.com; xen-devel@lists.xen.org; julien.grall@linaro.org; Justen, Jordan L; Kinney, Michael D; Tian, Feng
Cc: Ard Biesheuvel
Subject: [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange

This implements the function InterlockedCompareExchange16 () for all
architectures, using architecture and toolchain specific intrinsics
or primitive assembler instructions.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 17 files changed, 622 insertions(+)

diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
index f97569739914..7b97683ca0af 100644
--- a/MdePkg/Include/Library/SynchronizationLib.h
+++ b/MdePkg/Include/Library/SynchronizationLib.h
@@ -184,6 +184,32 @@ InterlockedDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  );
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
index 601b00495f26..ecb87fc12755 100644
--- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
+++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
@@ -16,12 +16,56 @@
 .text
 .align 3
 
+GCC_ASM_EXPORT(InternalSyncCompareExchange16)
 GCC_ASM_EXPORT(InternalSyncCompareExchange32)
 GCC_ASM_EXPORT(InternalSyncCompareExchange64)
 GCC_ASM_EXPORT(InternalSyncIncrement)
 GCC_ASM_EXPORT(InternalSyncDecrement)
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange16):
+  uxth    w1, w1
+  uxth    w2, w2
+  dmb     sy
+
+InternalSyncCompareExchange16Again:
+  ldxrh   w3, [x0]
+  cmp     w3, w1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange:
+  stxrh   w4, w2, [x0]
+  cbnz    w4, InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail:
+  dmb     sy
+  mov     w0, w3
+  ret
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
index 0128f8f016bd..d699eb40d2a2 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
+++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
@@ -1,6 +1,7 @@
 //  Implementation of synchronization functions for ARM architecture
 //
 //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
+//  Copyright (c) 2015, 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
@@ -15,12 +16,55 @@
 .text
 .align 3
 
+GCC_ASM_EXPORT(InternalSyncCompareExchange16)
 GCC_ASM_EXPORT(InternalSyncCompareExchange32)
 GCC_ASM_EXPORT(InternalSyncCompareExchange64)
 GCC_ASM_EXPORT(InternalSyncIncrement)
 GCC_ASM_EXPORT(InternalSyncDecrement)
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange16):
+  dmb
+
+InternalSyncCompareExchange16Again:
+  ldrexh  r3, [r0]
+  cmp     r3, r1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange:
+  strexh  ip, r2, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail:
+  dmb
+  mov     r0, r3
+  bx      lr
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
index f9f80737774a..dbc599114093 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
+++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
@@ -1,6 +1,7 @@
 //  Implementation of synchronization functions for ARM architecture
 //
 //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
+//  Copyright (c) 2015, 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
@@ -12,6 +13,7 @@
 //
 //
 
+    EXPORT  InternalSyncCompareExchange16
     EXPORT  InternalSyncCompareExchange32
     EXPORT  InternalSyncCompareExchange64
     EXPORT  InternalSyncIncrement
@@ -20,6 +22,48 @@
     AREA   ArmSynchronization, CODE, READONLY
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+InternalSyncCompareExchange16
+  dmb
+
+InternalSyncCompareExchange16Again
+  ldrexh  r3, [r0]
+  cmp     r3, r1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange
+  strexh  ip, r2, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail
+  dmb
+  mov     r0, r3
+  bx      lr
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
--- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
@@ -32,12 +32,14 @@
 [Sources.IA32]
   Ia32/InterlockedCompareExchange64.c | MSFT 
   Ia32/InterlockedCompareExchange32.c | MSFT 
+  Ia32/InterlockedCompareExchange16.c | MSFT
   Ia32/InterlockedDecrement.c | MSFT 
   Ia32/InterlockedIncrement.c | MSFT 
   SynchronizationMsc.c  | MSFT
 
   Ia32/InterlockedCompareExchange64.asm | INTEL 
   Ia32/InterlockedCompareExchange32.asm | INTEL 
+  Ia32/InterlockedCompareExchange16.asm | INTEL
   Ia32/InterlockedDecrement.asm | INTEL 
   Ia32/InterlockedIncrement.asm | INTEL 
   Synchronization.c | INTEL
@@ -48,9 +50,11 @@
 [Sources.X64]
   X64/InterlockedCompareExchange64.c | MSFT
   X64/InterlockedCompareExchange32.c | MSFT
+  X64/InterlockedCompareExchange16.c | MSFT
   
   X64/InterlockedCompareExchange64.asm | INTEL
   X64/InterlockedCompareExchange32.asm | INTEL
+  X64/InterlockedCompareExchange16.asm | INTEL
   
   X64/InterlockedDecrement.c | MSFT 
   X64/InterlockedIncrement.c | MSFT 
@@ -67,6 +71,7 @@
   Ipf/Synchronization.c
   Ipf/InterlockedCompareExchange64.s
   Ipf/InterlockedCompareExchange32.s
+  Ipf/InterlockedCompareExchange16.s
 
   Synchronization.c     | INTEL 
   SynchronizationMsc.c  | MSFT 
diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
index e42824c75d12..76f702324156 100644
--- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
+++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
@@ -63,6 +63,32 @@ InternalSyncDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in compare operation.
+  @param  ExchangeValue A 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      volatile UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  );
+
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
index 9c34b9f128ed..a57860203b12 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
@@ -13,6 +13,37 @@
 **/
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit
+  unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit
+  unsigned integer specified by Value.  If Value is equal to
+  CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to
+  CompareValue, then Value is returned. The compare exchange
+  operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the
+                        compare exchange operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      volatile UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  return *Value != CompareValue ? *Value :
+           ((*Value = ExchangeValue), CompareValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit
   unsigned integer.
 
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
index b5a7827fc0e8..bd81aad6c243 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
@@ -88,6 +88,48 @@ InternalSyncDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN OUT volatile  UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+
+  __asm__ __volatile__ (
+    "                     \n\t"
+    "lock                 \n\t"
+    "cmpxchgw    %1, %2   \n\t"
+    : "=a" (CompareValue)
+    : "q"  (ExchangeValue),
+      "m"  (*Value),
+      "0"  (CompareValue)
+    : "memory",
+      "cc"
+    );
+
+  return CompareValue;
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
new file mode 100644
index 000000000000..f8705042661d
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
@@ -0,0 +1,46 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015, 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.
+;
+; Module Name:
+;
+;   InterlockedCompareExchange16.Asm
+;
+; Abstract:
+;
+;   InterlockedCompareExchange16 function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    .486
+    .model  flat,C
+    .code
+
+;------------------------------------------------------------------------------
+; UINT16
+; EFIAPI
+; InternalSyncCompareExchange16 (
+;   IN      UINT16                    *Value,
+;   IN      UINT16                    CompareValue,
+;   IN      UINT16                    ExchangeValue
+;   );
+;------------------------------------------------------------------------------
+InternalSyncCompareExchange16   PROC
+    mov     ecx, [esp + 4]
+    mov     eax, [esp + 8]
+    mov     edx, [esp + 12]
+    lock    cmpxchg [ecx], dx
+    ret
+InternalSyncCompareExchange16   ENDP
+
+    END
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
new file mode 100644
index 000000000000..3d06dd9baa63
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
@@ -0,0 +1,51 @@
+/** @file
+  InterlockedCompareExchange16 function
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, 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.
+
+**/
+
+
+
+
+/**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  _asm {
+    mov     ecx, Value
+    mov     eax, CompareValue
+    mov     edx, ExchangeValue
+    lock    cmpxchg [ecx], dx
+  }
+}
+
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
new file mode 100644
index 000000000000..1e56942a98cb
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
@@ -0,0 +1,30 @@
+/// @file
+///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
+///   based architecture.
+///
+/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+/// Copyright (c) 2015, 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.
+///
+/// Module Name:  InterlockedCompareExchange16.s
+///
+///
+
+.auto
+.text
+
+.proc   InternalSyncCompareExchange16
+.type   InternalSyncCompareExchange16, @function
+InternalSyncCompareExchange16::
+        zxt2                r33 = r33
+        mov                 ar.ccv = r33
+        cmpxchg2.rel        r8  = [r32], r34
+        mf
+        br.ret.sptk.many    b0
+.endp   InternalSyncCompareExchange16
diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
index 0eea40ba1622..4218a265a0ec 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
@@ -277,6 +277,37 @@ InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
index badf73c1a6ce..587f5a771c35 100644
--- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
+++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
@@ -293,6 +293,37 @@ InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in compare operation.
+  @param  ExchangeValue A 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
index 9b20236acfa6..ca21f5dccee5 100644
--- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
+++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
@@ -295,6 +295,37 @@ InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in a compare operation.
+  @param  ExchangeValue A 16-bit value used in an exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
index ceb80aed94f8..6347073fee51 100644
--- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
@@ -89,6 +89,50 @@ InternalSyncDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN OUT volatile  UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+
+
+  __asm__ __volatile__ (
+    "lock                 \n\t"
+    "cmpxchgw    %3, %1       "
+    : "=a" (CompareValue),
+      "=m" (*Value)
+    : "a"  (CompareValue),
+      "r"  (ExchangeValue),
+      "m"  (*Value)
+    : "memory",
+      "cc"
+    );
+
+  return CompareValue;
+}
+
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
new file mode 100644
index 000000000000..8fe2aae1a28b
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
@@ -0,0 +1,42 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015, 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.
+;
+; Module Name:
+;
+;   InterlockedCompareExchange16.Asm
+;
+; Abstract:
+;
+;   InterlockedCompareExchange16 function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    .code
+
+;------------------------------------------------------------------------------
+; UINT16
+; EFIAPI
+; InterlockedCompareExchange16 (
+;   IN      UINT16                    *Value,
+;   IN      UINT16                    CompareValue,
+;   IN      UINT16                    ExchangeValue
+;   );
+;------------------------------------------------------------------------------
+InternalSyncCompareExchange16   PROC
+    mov     eax, edx
+    lock    cmpxchg [rcx], r8w
+    ret
+InternalSyncCompareExchange16   ENDP
+
+    END
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
new file mode 100644
index 000000000000..76aa6fbc0e81
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
@@ -0,0 +1,54 @@
+/** @file
+  InterlockedCompareExchange16 function
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, 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.
+
+**/
+
+/**
+  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
+**/
+
+__int16 _InterlockedCompareExchange16(
+   __int16 volatile * Destination,
+   __int16 Exchange,
+   __int16 Comperand
+);
+
+#pragma intrinsic(_InterlockedCompareExchange16)
+
+/**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
+  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
+  The compare exchange operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
+}
+
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
       [not found]   ` <E92EE9817A31E24EB0585FDF735412F563081986@ORSMSX113.amr.corp.intel.com>
@ 2015-02-25 22:19     ` Ard Biesheuvel
  0 siblings, 0 replies; 46+ messages in thread
From: Ard Biesheuvel @ 2015-02-25 22:19 UTC (permalink / raw)
  To: Kinney, Michael D
  Cc: Tian, Feng, julien.grall, ian.campbell, olivier.martin,
	stefano.stabellini, Justen, Jordan L, edk2-devel, leif.lindholm,
	xen-devel, roy.franz, anthony.perard, lersek

On 25 February 2015 at 21:56, Kinney, Michael D
<michael.d.kinney@intel.com> wrote:
> Ard Biesheuvel,
>
> Thank you for providing the implementation of this new function for all supported CPU architectures.  The one for IPF looks correct and passes builds.

Good. Thanks for confirming that.

> However, I am seeing some build breaks and some issues with the IA32 and X64 versions.  The following changes are required to your patch to build with VS20xx compilers and for the code generated by asm/Inline asm to match code generated by VS20xx compiler intrinsics.

OK, I will update the patch with your suggested changes.

> I have not built and disassembled GCC yet, but I think GCC inline asm should generate the expected 16-bit register load operations that have been addressed here.
>

This is what I get for X64 and IA32, respectively:

Disassembly of section .text.InternalSyncCompareExchange16:

0000000000000000 <InternalSyncCompareExchange16>:
   0: 55                   push   %rbp
   1: 48 89 e5             mov    %rsp,%rbp
   4: 48 89 4d 10           mov    %rcx,0x10(%rbp)
   8: 89 d0                 mov    %edx,%eax
   a: 44 89 c2             mov    %r8d,%edx
   d: 66 89 45 18           mov    %ax,0x18(%rbp)
  11: 66 89 55 20           mov    %dx,0x20(%rbp)
  15: 4c 8b 45 10           mov    0x10(%rbp),%r8
  19: 0f b7 45 18           movzwl 0x18(%rbp),%eax
  1d: 0f b7 55 20           movzwl 0x20(%rbp),%edx
  21: 48 8b 4d 10           mov    0x10(%rbp),%rcx
  25: f0 66 41 0f b1 10     lock cmpxchg %dx,(%r8)
  2b: 66 89 45 18           mov    %ax,0x18(%rbp)
  2f: 0f b7 45 18           movzwl 0x18(%rbp),%eax
  33: 5d                   pop    %rbp
  34: c3                   retq

Disassembly of section .text.InternalSyncCompareExchange16:

00000000 <InternalSyncCompareExchange16>:
   0: 55                   push   %ebp
   1: 89 e5                 mov    %esp,%ebp
   3: 8b 45 0c             mov    0xc(%ebp),%eax
   6: 8b 55 10             mov    0x10(%ebp),%edx
   9: 8b 4d 08             mov    0x8(%ebp),%ecx
   c: f0 66 0f b1 11       lock cmpxchg %dx,(%ecx)
  11: 5d                   pop    %ebp
  12: c3                   ret

The latter looks equivalent to me, but perhaps you could confirm that
the former does the right thing?

Thanks a lot for taking the time,
Ard.



> --- Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm        Mon Jan 19 14:26:36 1970
> +++ Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm        Mon Jan 19 14:26:36 1970
> @@ -37,8 +37,8 @@
>  ;------------------------------------------------------------------------------
>  InternalSyncCompareExchange16   PROC
>      mov     ecx, [esp + 4]
> -    mov     eax, [esp + 8]
> -    mov     edx, [esp + 12]
> +    mov     ax, [esp + 8]
> +    mov     dx, [esp + 12]
>      lock    cmpxchg [ecx], dx
>      ret
>  InternalSyncCompareExchange16   ENDP
> --- Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c  Mon Jan 19 14:26:36 1970
> +++ Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c  Mon Jan 19 14:26:36 1970
> @@ -43,8 +43,8 @@
>  {
>    _asm {
>      mov     ecx, Value
> -    mov     eax, CompareValue
> -    mov     edx, ExchangeValue
> +    mov     ax, CompareValue
> +    mov     dx, ExchangeValue
>      lock    cmpxchg [ecx], dx
>    }
>  }
> --- Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm Mon Jan 19 14:26:36 1970
> +++ Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm Mon Jan 19 14:26:36 1970
> @@ -34,7 +34,7 @@
>  ;   );
>  ;------------------------------------------------------------------------------
>  InternalSyncCompareExchange16   PROC
> -    mov     eax, edx
> +    mov     ax, dx
>      lock    cmpxchg [rcx], r8w
>      ret
>  InternalSyncCompareExchange16   ENDP
>
> Best regards,
>
> Mike
>
> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Thursday, February 12, 2015 3:19 AM
> To: edk2-devel@lists.sourceforge.net; olivier.martin@arm.com; lersek@redhat.com; roy.franz@linaro.org; leif.lindholm@linaro.org; stefano.stabellini@eu.citrix.com; ian.campbell@citrix.com; anthony.perard@citrix.com; xen-devel@lists.xen.org; julien.grall@linaro.org; Justen, Jordan L; Kinney, Michael D; Tian, Feng
> Cc: Ard Biesheuvel
> Subject: [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
>
> This implements the function InterlockedCompareExchange16 () for all
> architectures, using architecture and toolchain specific intrinsics
> or primitive assembler instructions.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Reviewed-by: Olivier Martin <olivier.martin@arm.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  17 files changed, 622 insertions(+)
>
> diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
> index f97569739914..7b97683ca0af 100644
> --- a/MdePkg/Include/Library/SynchronizationLib.h
> +++ b/MdePkg/Include/Library/SynchronizationLib.h
> @@ -184,6 +184,32 @@ InterlockedDecrement (
>
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  );
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> index 601b00495f26..ecb87fc12755 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> @@ -16,12 +16,56 @@
>  .text
>  .align 3
>
> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>  GCC_ASM_EXPORT(InternalSyncIncrement)
>  GCC_ASM_EXPORT(InternalSyncDecrement)
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +ASM_PFX(InternalSyncCompareExchange16):
> +  uxth    w1, w1
> +  uxth    w2, w2
> +  dmb     sy
> +
> +InternalSyncCompareExchange16Again:
> +  ldxrh   w3, [x0]
> +  cmp     w3, w1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange:
> +  stxrh   w4, w2, [x0]
> +  cbnz    w4, InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail:
> +  dmb     sy
> +  mov     w0, w3
> +  ret
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> index 0128f8f016bd..d699eb40d2a2 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> @@ -1,6 +1,7 @@
>  //  Implementation of synchronization functions for ARM architecture
>  //
>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
> +//  Copyright (c) 2015, 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
> @@ -15,12 +16,55 @@
>  .text
>  .align 3
>
> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>  GCC_ASM_EXPORT(InternalSyncIncrement)
>  GCC_ASM_EXPORT(InternalSyncDecrement)
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +ASM_PFX(InternalSyncCompareExchange16):
> +  dmb
> +
> +InternalSyncCompareExchange16Again:
> +  ldrexh  r3, [r0]
> +  cmp     r3, r1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange:
> +  strexh  ip, r2, [r0]
> +  cmp     ip, #0
> +  bne     InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail:
> +  dmb
> +  mov     r0, r3
> +  bx      lr
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> index f9f80737774a..dbc599114093 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> @@ -1,6 +1,7 @@
>  //  Implementation of synchronization functions for ARM architecture
>  //
>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
> +//  Copyright (c) 2015, 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
> @@ -12,6 +13,7 @@
>  //
>  //
>
> +    EXPORT  InternalSyncCompareExchange16
>      EXPORT  InternalSyncCompareExchange32
>      EXPORT  InternalSyncCompareExchange64
>      EXPORT  InternalSyncIncrement
> @@ -20,6 +22,48 @@
>      AREA   ArmSynchronization, CODE, READONLY
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +InternalSyncCompareExchange16
> +  dmb
> +
> +InternalSyncCompareExchange16Again
> +  ldrexh  r3, [r0]
> +  cmp     r3, r1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange
> +  strexh  ip, r2, [r0]
> +  cmp     ip, #0
> +  bne     InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail
> +  dmb
> +  mov     r0, r3
> +  bx      lr
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> @@ -32,12 +32,14 @@
>  [Sources.IA32]
>    Ia32/InterlockedCompareExchange64.c | MSFT
>    Ia32/InterlockedCompareExchange32.c | MSFT
> +  Ia32/InterlockedCompareExchange16.c | MSFT
>    Ia32/InterlockedDecrement.c | MSFT
>    Ia32/InterlockedIncrement.c | MSFT
>    SynchronizationMsc.c  | MSFT
>
>    Ia32/InterlockedCompareExchange64.asm | INTEL
>    Ia32/InterlockedCompareExchange32.asm | INTEL
> +  Ia32/InterlockedCompareExchange16.asm | INTEL
>    Ia32/InterlockedDecrement.asm | INTEL
>    Ia32/InterlockedIncrement.asm | INTEL
>    Synchronization.c | INTEL
> @@ -48,9 +50,11 @@
>  [Sources.X64]
>    X64/InterlockedCompareExchange64.c | MSFT
>    X64/InterlockedCompareExchange32.c | MSFT
> +  X64/InterlockedCompareExchange16.c | MSFT
>
>    X64/InterlockedCompareExchange64.asm | INTEL
>    X64/InterlockedCompareExchange32.asm | INTEL
> +  X64/InterlockedCompareExchange16.asm | INTEL
>
>    X64/InterlockedDecrement.c | MSFT
>    X64/InterlockedIncrement.c | MSFT
> @@ -67,6 +71,7 @@
>    Ipf/Synchronization.c
>    Ipf/InterlockedCompareExchange64.s
>    Ipf/InterlockedCompareExchange32.s
> +  Ipf/InterlockedCompareExchange16.s
>
>    Synchronization.c     | INTEL
>    SynchronizationMsc.c  | MSFT
> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> index e42824c75d12..76f702324156 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> @@ -63,6 +63,32 @@ InternalSyncDecrement (
>
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in compare operation.
> +  @param  ExchangeValue A 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      volatile UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  );
> +
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> index 9c34b9f128ed..a57860203b12 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> @@ -13,6 +13,37 @@
>  **/
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit
> +  unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit
> +  unsigned integer specified by Value.  If Value is equal to
> +  CompareValue, then Value is set to ExchangeValue and
> +  CompareValue is returned.  If Value is not equal to
> +  CompareValue, then Value is returned. The compare exchange
> +  operation must be performed using MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the
> +                        compare exchange operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      volatile UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  return *Value != CompareValue ? *Value :
> +           ((*Value = ExchangeValue), CompareValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit
>    unsigned integer.
>
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> index b5a7827fc0e8..bd81aad6c243 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> @@ -88,6 +88,48 @@ InternalSyncDecrement (
>  }
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN OUT volatile  UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +
> +  __asm__ __volatile__ (
> +    "                     \n\t"
> +    "lock                 \n\t"
> +    "cmpxchgw    %1, %2   \n\t"
> +    : "=a" (CompareValue)
> +    : "q"  (ExchangeValue),
> +      "m"  (*Value),
> +      "0"  (CompareValue)
> +    : "memory",
> +      "cc"
> +    );
> +
> +  return CompareValue;
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
> new file mode 100644
> index 000000000000..f8705042661d
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
> @@ -0,0 +1,46 @@
> +;------------------------------------------------------------------------------
> +;
> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
> +; Copyright (c) 2015, 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.
> +;
> +; Module Name:
> +;
> +;   InterlockedCompareExchange16.Asm
> +;
> +; Abstract:
> +;
> +;   InterlockedCompareExchange16 function
> +;
> +; Notes:
> +;
> +;------------------------------------------------------------------------------
> +
> +    .486
> +    .model  flat,C
> +    .code
> +
> +;------------------------------------------------------------------------------
> +; UINT16
> +; EFIAPI
> +; InternalSyncCompareExchange16 (
> +;   IN      UINT16                    *Value,
> +;   IN      UINT16                    CompareValue,
> +;   IN      UINT16                    ExchangeValue
> +;   );
> +;------------------------------------------------------------------------------
> +InternalSyncCompareExchange16   PROC
> +    mov     ecx, [esp + 4]
> +    mov     eax, [esp + 8]
> +    mov     edx, [esp + 12]
> +    lock    cmpxchg [ecx], dx
> +    ret
> +InternalSyncCompareExchange16   ENDP
> +
> +    END
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
> new file mode 100644
> index 000000000000..3d06dd9baa63
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
> @@ -0,0 +1,51 @@
> +/** @file
> +  InterlockedCompareExchange16 function
> +
> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2015, 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.
> +
> +**/
> +
> +
> +
> +
> +/**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  _asm {
> +    mov     ecx, Value
> +    mov     eax, CompareValue
> +    mov     edx, ExchangeValue
> +    lock    cmpxchg [ecx], dx
> +  }
> +}
> +
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
> new file mode 100644
> index 000000000000..1e56942a98cb
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
> @@ -0,0 +1,30 @@
> +/// @file
> +///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
> +///   based architecture.
> +///
> +/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
> +/// Copyright (c) 2015, 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.
> +///
> +/// Module Name:  InterlockedCompareExchange16.s
> +///
> +///
> +
> +.auto
> +.text
> +
> +.proc   InternalSyncCompareExchange16
> +.type   InternalSyncCompareExchange16, @function
> +InternalSyncCompareExchange16::
> +        zxt2                r33 = r33
> +        mov                 ar.ccv = r33
> +        cmpxchg2.rel        r8  = [r32], r34
> +        mf
> +        br.ret.sptk.many    b0
> +.endp   InternalSyncCompareExchange16
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> index 0eea40ba1622..4218a265a0ec 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> @@ -277,6 +277,37 @@ InterlockedDecrement (
>  }
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> index badf73c1a6ce..587f5a771c35 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> @@ -293,6 +293,37 @@ InterlockedDecrement (
>  }
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in compare operation.
> +  @param  ExchangeValue A 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> index 9b20236acfa6..ca21f5dccee5 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> @@ -295,6 +295,37 @@ InterlockedDecrement (
>  }
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in a compare operation.
> +  @param  ExchangeValue A 16-bit value used in an exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> index ceb80aed94f8..6347073fee51 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> @@ -89,6 +89,50 @@ InternalSyncDecrement (
>
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN OUT volatile  UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +
> +
> +  __asm__ __volatile__ (
> +    "lock                 \n\t"
> +    "cmpxchgw    %3, %1       "
> +    : "=a" (CompareValue),
> +      "=m" (*Value)
> +    : "a"  (CompareValue),
> +      "r"  (ExchangeValue),
> +      "m"  (*Value)
> +    : "memory",
> +      "cc"
> +    );
> +
> +  return CompareValue;
> +}
> +
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
> new file mode 100644
> index 000000000000..8fe2aae1a28b
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
> @@ -0,0 +1,42 @@
> +;------------------------------------------------------------------------------
> +;
> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
> +; Copyright (c) 2015, 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.
> +;
> +; Module Name:
> +;
> +;   InterlockedCompareExchange16.Asm
> +;
> +; Abstract:
> +;
> +;   InterlockedCompareExchange16 function
> +;
> +; Notes:
> +;
> +;------------------------------------------------------------------------------
> +
> +    .code
> +
> +;------------------------------------------------------------------------------
> +; UINT16
> +; EFIAPI
> +; InterlockedCompareExchange16 (
> +;   IN      UINT16                    *Value,
> +;   IN      UINT16                    CompareValue,
> +;   IN      UINT16                    ExchangeValue
> +;   );
> +;------------------------------------------------------------------------------
> +InternalSyncCompareExchange16   PROC
> +    mov     eax, edx
> +    lock    cmpxchg [rcx], r8w
> +    ret
> +InternalSyncCompareExchange16   ENDP
> +
> +    END
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
> new file mode 100644
> index 000000000000..76aa6fbc0e81
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
> @@ -0,0 +1,54 @@
> +/** @file
> +  InterlockedCompareExchange16 function
> +
> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2015, 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.
> +
> +**/
> +
> +/**
> +  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
> +**/
> +
> +__int16 _InterlockedCompareExchange16(
> +   __int16 volatile * Destination,
> +   __int16 Exchange,
> +   __int16 Comperand
> +);
> +
> +#pragma intrinsic(_InterlockedCompareExchange16)
> +
> +/**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
> +  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
> +  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
> +  The compare exchange operation must be performed using MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
> +}
> +
> --
> 1.8.3.2
>

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2015-02-25 22:19 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1423739961-5945-1-git-send-email-ard.biesheuvel@linaro.org>
2015-02-12 11:18 ` [PATCH v4 01/29] ArmPkg: allow HYP timer interrupt to be omitted Ard Biesheuvel
2015-02-12 11:18 ` [PATCH v4 02/29] ArmPkg: allow patchable PCDs for memory, FD and FV addresses Ard Biesheuvel
2015-02-12 11:18 ` [PATCH v4 03/29] ArmPlatformPkg: allow patchable PCD for FD base address Ard Biesheuvel
2015-02-12 11:18 ` [PATCH v4 04/29] ArmVirtualizationPkg: add GICv3 detection to VirtFdtDxe Ard Biesheuvel
2015-02-12 11:18 ` [PATCH v4 05/29] ArmVirtualizationPkg: allow patchable PCD for device tree base address Ard Biesheuvel
2015-02-12 11:18 ` [PATCH v4 06/29] ArmVirtualizationPkg: move early UART discovery to PlatformPeim Ard Biesheuvel
2015-02-12 11:18 ` [PATCH v4 07/29] ArmVirtualizationPkg: use a HOB to store device tree blob Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 08/29] ArmVirtualizationPkg: add padding to FDT allocation Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 09/29] ArmVirtualizationPkg: add a relocatable version of PrePi Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 10/29] ArmVirtualizationPkg: implement custom MemoryInitPeiLib Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 11/29] ArmVirtualizationPkg: allow patchable PCD for FV and DT base addresses Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 12/29] ArmVirtualizationPkg: Xen/PV relocatable platformlib instance Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 13/29] MdePkg/BaseSynchronizationLib: Added proper support for ARM architecture Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 15/29] Ovmf/Xen: move Xen interface version to <xen.h> Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 16/29] Ovmf/Xen: fix pointer to int cast in XenBusDxe Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 17/29] Ovmf/Xen: refactor XenBusDxe hypercall implementation Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 18/29] Ovmf/Xen: move XenBusDxe hypercall code to separate library Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 19/29] Ovmf/Xen: introduce XENIO_PROTOCOL Ard Biesheuvel
2015-02-19 17:30   ` Anthony PERARD
2015-02-12 11:19 ` [PATCH v4 20/29] Ovmf/Xen: add separate driver for Xen PCI device Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 21/29] Ovmf/Xen: move XenBusDxe to abstract XENIO_PROTOCOL Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 22/29] Ovmf/Xen: implement XenHypercallLib for ARM Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 23/29] Ovmf/Xen: port XenBusDxe to other architectures Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 24/29] Ovmf/Xen: add Xen PV console SerialPortLib driver Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 25/29] ArmVirtualizationPkg: implement dummy RealTimeClockLib for Xen Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 26/29] Ovfm/Xen: add a Vendor Hardware device path GUID for the XenBus root Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 27/29] ArmVirtualizationPkg: add XenIoMmioLib Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 28/29] ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen, xen" DT node Ard Biesheuvel
2015-02-12 11:19 ` [PATCH v4 29/29] ArmVirtualizationPkg: add platform description for Xen guests Ard Biesheuvel
2015-02-12 21:18 ` [PATCH v4 00/29] Xen/ARM guest support Jordan Justen
     [not found] ` <20150212211855.11478.90744@jljusten-hsw>
2015-02-13  0:18   ` Ard Biesheuvel
     [not found] ` <1423739961-5945-15-git-send-email-ard.biesheuvel@linaro.org>
2015-02-17 17:40   ` [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange Jordan Justen
     [not found]   ` <20150217174047.8141.17529@jljusten-ivy>
2015-02-18  8:37     ` Ard Biesheuvel
     [not found]     ` <CAKv+Gu8M-V4Vgf2+sHLZS+n37Qbm+TxJpFpU27qDfHt=gR3+Bw@mail.gmail.com>
2015-02-23 20:33       ` Ard Biesheuvel
2015-02-25 21:56   ` Kinney, Michael D
     [not found]   ` <E92EE9817A31E24EB0585FDF735412F563081986@ORSMSX113.amr.corp.intel.com>
2015-02-25 22:19     ` Ard Biesheuvel
     [not found] ` <1423739961-5945-16-git-send-email-ard.biesheuvel@linaro.org>
2015-02-19 15:02   ` [PATCH v4 15/29] Ovmf/Xen: move Xen interface version to <xen.h> Anthony PERARD
     [not found] ` <1423739961-5945-17-git-send-email-ard.biesheuvel@linaro.org>
2015-02-19 15:31   ` [PATCH v4 16/29] Ovmf/Xen: fix pointer to int cast in XenBusDxe Anthony PERARD
     [not found] ` <1423739961-5945-18-git-send-email-ard.biesheuvel@linaro.org>
2015-02-19 16:05   ` [PATCH v4 17/29] Ovmf/Xen: refactor XenBusDxe hypercall implementation Anthony PERARD
     [not found] ` <1423739961-5945-19-git-send-email-ard.biesheuvel@linaro.org>
2015-02-19 17:25   ` [PATCH v4 18/29] Ovmf/Xen: move XenBusDxe hypercall code to separate library Anthony PERARD
     [not found] ` <1423739961-5945-21-git-send-email-ard.biesheuvel@linaro.org>
2015-02-19 18:43   ` [PATCH v4 20/29] Ovmf/Xen: add separate driver for Xen PCI device Anthony PERARD
     [not found] ` <1423739961-5945-22-git-send-email-ard.biesheuvel@linaro.org>
2015-02-20 14:10   ` [PATCH v4 21/29] Ovmf/Xen: move XenBusDxe to abstract XENIO_PROTOCOL Anthony PERARD
     [not found] ` <1423739961-5945-24-git-send-email-ard.biesheuvel@linaro.org>
2015-02-23 15:16   ` [PATCH v4 23/29] Ovmf/Xen: port XenBusDxe to other architectures Anthony PERARD
     [not found]   ` <20150223151617.GU1345@perard.uk.xensource.com>
2015-02-23 17:54     ` Ard Biesheuvel
     [not found]     ` <CAKv+Gu-EA3q4z89WxSZbQ9BUjFU9tnGEQRmEBxjzqM+-_bCuVw@mail.gmail.com>
2015-02-23 18:25       ` Anthony PERARD

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.