public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Anthony PERARD" <anthony.perard@citrix.com>
To: <devel@edk2.groups.io>
Cc: "Michael D Kinney" <michael.d.kinney@intel.com>,
	"Ard Biesheuvel" <ard.biesheuvel@linaro.org>,
	"Anthony Perard" <anthony.perard@citrix.com>,
	xen-devel@lists.xenproject.org,
	"Laszlo Ersek" <lersek@redhat.com>,
	"Liming Gao" <liming.gao@intel.com>,
	"Jordan Justen" <jordan.l.justen@intel.com>,
	"Julien Grall" <julien@xen.org>,
	"Roger Pau Monné" <roger.pau@citrix.com>
Subject: [PATCH 4/5] OvmfPkg/XenPlatformPei: Calibrate APIC timer frequency
Date: Wed, 29 Jan 2020 12:12:34 +0000	[thread overview]
Message-ID: <20200129121235.1814563-5-anthony.perard@citrix.com> (raw)
In-Reply-To: <20200129121235.1814563-1-anthony.perard@citrix.com>

Calculate the frequency of the APIC timer that Xen provides.

Even though the frequency is currently hard-coded, it isn't part of
the public ABI that Xen provides and thus may change at any time. OVMF
needs to determine the frequency by an other mean.

Fortunately, Xen provides a way to determines the frequency of the
TSC, so we can use TSC to calibrate the frequency of the APIC timer.
That information is found in the shared_info page which we map and
unmap once done (XenBusDxe is going to map the page somewhere else).

The calculated frequency is only logged in this patch, it will be used
in a following patch.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2490
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
CC: Roger Pau Monné <roger.pau@citrix.com>
---
 OvmfPkg/XenPlatformPei/XenPlatformPei.inf |   1 +
 OvmfPkg/XenPlatformPei/Platform.h         |   5 +
 OvmfPkg/XenPlatformPei/Platform.c         |   1 +
 OvmfPkg/XenPlatformPei/Xen.c              | 123 ++++++++++++++++++++++
 4 files changed, 130 insertions(+)

diff --git a/OvmfPkg/XenPlatformPei/XenPlatformPei.inf b/OvmfPkg/XenPlatformPei/XenPlatformPei.inf
index 0ef77db92c03..335a442538c2 100644
--- a/OvmfPkg/XenPlatformPei/XenPlatformPei.inf
+++ b/OvmfPkg/XenPlatformPei/XenPlatformPei.inf
@@ -52,6 +52,7 @@ [LibraryClasses]
   DebugLib
   HobLib
   IoLib
+  LocalApicLib
   PciLib
   ResourcePublicationLib
   PeiServicesLib
diff --git a/OvmfPkg/XenPlatformPei/Platform.h b/OvmfPkg/XenPlatformPei/Platform.h
index 7661f4a8de0a..97e482a065f0 100644
--- a/OvmfPkg/XenPlatformPei/Platform.h
+++ b/OvmfPkg/XenPlatformPei/Platform.h
@@ -127,6 +127,11 @@ XenGetE820Map (
   UINT32 *Count
   );
 
+VOID
+CalibrateLapicTimer (
+  VOID
+  );
+
 extern EFI_BOOT_MODE mBootMode;
 
 extern UINT8 mPhysMemAddressWidth;
diff --git a/OvmfPkg/XenPlatformPei/Platform.c b/OvmfPkg/XenPlatformPei/Platform.c
index 717fd0ab1a45..e9511eb40c62 100644
--- a/OvmfPkg/XenPlatformPei/Platform.c
+++ b/OvmfPkg/XenPlatformPei/Platform.c
@@ -448,6 +448,7 @@ InitializeXenPlatform (
   InitializeRamRegions ();
 
   InitializeXen ();
+  CalibrateLapicTimer ();
 
   if (mBootMode != BOOT_ON_S3_RESUME) {
     ReserveEmuVariableNvStore ();
diff --git a/OvmfPkg/XenPlatformPei/Xen.c b/OvmfPkg/XenPlatformPei/Xen.c
index c41fecdc486e..d6cdc9a8e31c 100644
--- a/OvmfPkg/XenPlatformPei/Xen.c
+++ b/OvmfPkg/XenPlatformPei/Xen.c
@@ -19,6 +19,7 @@
 //
 #include <Library/DebugLib.h>
 #include <Library/HobLib.h>
+#include <Library/LocalApicLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/PcdLib.h>
 #include <Guid/XenInfo.h>
@@ -386,3 +387,125 @@ InitializeXen (
 
   return EFI_SUCCESS;
 }
+
+
+EFI_STATUS
+MapSharedInfoPage (
+  IN VOID *PagePtr
+  )
+{
+  xen_add_to_physmap_t  Parameters;
+  INTN                  ReturnCode;
+
+  Parameters.domid = DOMID_SELF;
+  Parameters.space = XENMAPSPACE_shared_info;
+  Parameters.idx = 0;
+  Parameters.gpfn = (UINTN) PagePtr >> EFI_PAGE_SHIFT;
+  ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);
+  if (ReturnCode != 0) {
+    return EFI_NO_MAPPING;
+  }
+  return EFI_SUCCESS;
+}
+
+VOID
+UnmapXenPage (
+  IN VOID *PagePtr
+  )
+{
+  xen_remove_from_physmap_t Parameters;
+  INTN                      ReturnCode;
+
+  Parameters.domid = DOMID_SELF;
+  Parameters.gpfn = (UINTN) PagePtr >> EFI_PAGE_SHIFT;
+  ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);
+  ASSERT (ReturnCode == 0);
+}
+
+
+STATIC
+UINT64
+GetCPUFreq (
+  IN XEN_VCPU_TIME_INFO *VcpuTime
+  )
+{
+  UINT32 Version;
+  UINT32 TSCToSystemMultiplier;
+  INT8   TSCShift;
+  UINT64 CPUFreq;
+
+  do {
+    Version = VcpuTime->Version;
+    MemoryFence ();
+    TSCToSystemMultiplier = VcpuTime->TSCToSystemMultiplier;
+    TSCShift = VcpuTime->TSCShift;
+    MemoryFence ();
+  } while (((Version & 1) != 0) && (Version != VcpuTime->Version));
+
+  CPUFreq = (1000000000ULL << 32) / TSCToSystemMultiplier;
+  if (TSCShift >= 0) {
+      CPUFreq >>= VcpuTime->TSCShift;
+  } else {
+      CPUFreq <<= -VcpuTime->TSCShift;
+  }
+  return CPUFreq;
+}
+
+VOID
+XenDelay (
+  IN XEN_VCPU_TIME_INFO *VcpuTimeInfo,
+  IN UINT64             DelayNs
+  )
+{
+  UINT64 Tick;
+
+  Tick = AsmReadTsc ();
+  Tick += (DelayNs * GetCPUFreq (VcpuTimeInfo)) / 1000000000ULL;
+  while (AsmReadTsc() <= Tick) {
+    CpuPause();
+  }
+}
+
+
+/**
+  Calculate the frequency of the Local Apic Timer
+**/
+VOID
+CalibrateLapicTimer (
+  VOID
+  )
+{
+  XEN_SHARED_INFO       *SharedInfo;
+  XEN_VCPU_TIME_INFO    *VcpuTimeInfo;
+  UINT32                TimerTick, TimerTick2;
+  UINT64                TscTick, TscTick2;
+  UINT64                Freq;
+  EFI_STATUS            Status;
+
+  SharedInfo = AllocatePages (1);
+  Status = MapSharedInfoPage (SharedInfo);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  VcpuTimeInfo = &SharedInfo->VcpuInfo[0].Time;
+
+  InitializeApicTimer (1, MAX_UINT32, TRUE, 0);
+  DisableApicTimerInterrupt ();
+
+  TimerTick = GetApicTimerCurrentCount ();
+  TscTick = AsmReadTsc ();
+  XenDelay (VcpuTimeInfo, 1000000ULL);
+  TimerTick2 = GetApicTimerCurrentCount ();
+  TscTick2 = AsmReadTsc ();
+
+  Freq = (GetCPUFreq (VcpuTimeInfo) * (TimerTick - TimerTick2))
+    / (TscTick2 - TscTick);
+  DEBUG ((DEBUG_INFO, "APIC Freq % 8lu Hz\n", Freq));
+
+  UnmapXenPage (SharedInfo);
+
+Exit:
+  FreePages (SharedInfo, 1);
+}
-- 
Anthony PERARD


  parent reply	other threads:[~2020-01-29 12:12 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-29 12:12 [PATCH 0/5] OvmfXen: Set PcdFSBClock at runtime Anthony PERARD
2020-01-29 12:12 ` [PATCH 1/5] OvmfPkg/XenResetVector: Silent a warning from nasm Anthony PERARD
2020-01-29 16:08   ` Laszlo Ersek
2020-01-29 12:12 ` [PATCH 2/5] MdePkg: Allow PcdFSBClock to by Dynamic Anthony PERARD
2020-01-29 16:10   ` Laszlo Ersek
2020-02-03  1:34     ` Liming Gao
2020-02-03 15:34       ` Anthony PERARD
2020-02-03 17:26         ` Anthony PERARD
2020-02-04  6:49           ` [edk2-devel] " Liming Gao
2020-01-29 12:12 ` [PATCH 3/5] OvmfPkg/IndustryStandard/Xen: Apply EDK2 coding style to XEN_VCPU_TIME_INFO Anthony PERARD
2020-01-29 16:14   ` Laszlo Ersek
2020-01-30 10:31     ` Anthony PERARD
2020-01-29 12:12 ` Anthony PERARD [this message]
2020-01-29 16:29   ` [PATCH 4/5] OvmfPkg/XenPlatformPei: Calibrate APIC timer frequency Laszlo Ersek
2020-01-30  9:12   ` Roger Pau Monné
2020-01-30 12:44     ` Anthony PERARD
2020-01-30 13:10       ` [Xen-devel] " Andrew Cooper
2020-01-29 12:12 ` [PATCH 5/5] OvmfPkg/OvmfXen: Set PcdFSBClock Anthony PERARD
2020-01-29 16:36   ` Laszlo Ersek

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20200129121235.1814563-5-anthony.perard@citrix.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

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

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