#include <Library/CpuLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/HobLib.h>\r
-#include <Library/LocalApicLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/PcdLib.h>\r
-#include <Library/SafeIntLib.h>\r
#include <Guid/XenInfo.h>\r
#include <IndustryStandard/E820.h>\r
#include <Library/ResourcePublicationLib.h>\r
\r
return EFI_SUCCESS;\r
}\r
-\r
-STATIC\r
-EFI_STATUS\r
-MapSharedInfoPage (\r
- IN VOID *PagePtr\r
- )\r
-{\r
- xen_add_to_physmap_t Parameters;\r
- INTN ReturnCode;\r
-\r
- Parameters.domid = DOMID_SELF;\r
- Parameters.space = XENMAPSPACE_shared_info;\r
- Parameters.idx = 0;\r
- Parameters.gpfn = (UINTN)PagePtr >> EFI_PAGE_SHIFT;\r
- ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);\r
- if (ReturnCode != 0) {\r
- return EFI_NO_MAPPING;\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-VOID\r
-UnmapXenPage (\r
- IN VOID *PagePtr\r
- )\r
-{\r
- xen_remove_from_physmap_t Parameters;\r
- INTN ReturnCode;\r
-\r
- Parameters.domid = DOMID_SELF;\r
- Parameters.gpfn = (UINTN)PagePtr >> EFI_PAGE_SHIFT;\r
- ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);\r
- ASSERT (ReturnCode == 0);\r
-}\r
-\r
-\r
-STATIC\r
-UINT64\r
-GetCpuFreq (\r
- IN XEN_VCPU_TIME_INFO *VcpuTime\r
- )\r
-{\r
- UINT32 Version;\r
- UINT32 TscToSystemMultiplier;\r
- INT8 TscShift;\r
- UINT64 CpuFreq;\r
-\r
- do {\r
- Version = VcpuTime->Version;\r
- MemoryFence ();\r
- TscToSystemMultiplier = VcpuTime->TscToSystemMultiplier;\r
- TscShift = VcpuTime->TscShift;\r
- MemoryFence ();\r
- } while (((Version & 1) != 0) && (Version != VcpuTime->Version));\r
-\r
- CpuFreq = DivU64x32 (LShiftU64 (1000000000ULL, 32), TscToSystemMultiplier);\r
- if (TscShift >= 0) {\r
- CpuFreq = RShiftU64 (CpuFreq, TscShift);\r
- } else {\r
- CpuFreq = LShiftU64 (CpuFreq, -TscShift);\r
- }\r
- return CpuFreq;\r
-}\r
-\r
-STATIC\r
-VOID\r
-XenDelay (\r
- IN XEN_VCPU_TIME_INFO *VcpuTimeInfo,\r
- IN UINT64 DelayNs\r
- )\r
-{\r
- UINT64 Tick;\r
- UINT64 CpuFreq;\r
- UINT64 Delay;\r
- UINT64 DelayTick;\r
- UINT64 NewTick;\r
- RETURN_STATUS Status;\r
-\r
- Tick = AsmReadTsc ();\r
-\r
- CpuFreq = GetCpuFreq (VcpuTimeInfo);\r
- Status = SafeUint64Mult (DelayNs, CpuFreq, &Delay);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR,\r
- "XenDelay (%lu ns): delay too big in relation to CPU freq %lu Hz\n",\r
- DelayNs, CpuFreq));\r
- ASSERT_EFI_ERROR (Status);\r
- CpuDeadLoop ();\r
- }\r
-\r
- DelayTick = DivU64x32 (Delay, 1000000000);\r
-\r
- NewTick = Tick + DelayTick;\r
-\r
- //\r
- // Check for overflow\r
- //\r
- if (NewTick < Tick) {\r
- //\r
- // Overflow, wait for TSC to also overflow\r
- //\r
- while (AsmReadTsc () >= Tick) {\r
- CpuPause ();\r
- }\r
- }\r
-\r
- while (AsmReadTsc () <= NewTick) {\r
- CpuPause ();\r
- }\r
-}\r
-\r
-\r
-/**\r
- Calculate the frequency of the Local Apic Timer\r
-**/\r
-VOID\r
-CalibrateLapicTimer (\r
- VOID\r
- )\r
-{\r
- XEN_SHARED_INFO *SharedInfo;\r
- XEN_VCPU_TIME_INFO *VcpuTimeInfo;\r
- UINT32 TimerTick, TimerTick2, DiffTimer;\r
- UINT64 TscTick, TscTick2;\r
- UINT64 Freq;\r
- UINT64 Dividend;\r
- EFI_STATUS Status;\r
-\r
-\r
- SharedInfo = (VOID*)((1ULL << mPhysMemAddressWidth) - EFI_PAGE_SIZE);\r
- Status = PhysicalAddressIdentityMapping ((EFI_PHYSICAL_ADDRESS)SharedInfo);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR,\r
- "Failed to add page table entry for Xen shared info page: %r\n",\r
- Status));\r
- ASSERT_EFI_ERROR (Status);\r
- return;\r
- }\r
-\r
- Status = MapSharedInfoPage (SharedInfo);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Failed to map Xen's shared info page: %r\n",\r
- Status));\r
- ASSERT_EFI_ERROR (Status);\r
- return;\r
- }\r
-\r
- VcpuTimeInfo = &SharedInfo->VcpuInfo[0].Time;\r
-\r
- InitializeApicTimer (1, MAX_UINT32, TRUE, 0);\r
- DisableApicTimerInterrupt ();\r
-\r
- TimerTick = GetApicTimerCurrentCount ();\r
- TscTick = AsmReadTsc ();\r
- XenDelay (VcpuTimeInfo, 1000000ULL);\r
- TimerTick2 = GetApicTimerCurrentCount ();\r
- TscTick2 = AsmReadTsc ();\r
-\r
-\r
- DiffTimer = TimerTick - TimerTick2;\r
- Status = SafeUint64Mult (GetCpuFreq (VcpuTimeInfo), DiffTimer, &Dividend);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "overflow while calculating APIC frequency\n"));\r
- DEBUG ((DEBUG_ERROR, "CPU freq: %lu Hz; APIC timer tick count for 1 ms: %u\n",\r
- GetCpuFreq (VcpuTimeInfo), DiffTimer));\r
- ASSERT_EFI_ERROR (Status);\r
- CpuDeadLoop ();\r
- }\r
-\r
- Freq = DivU64x64Remainder (Dividend, TscTick2 - TscTick, NULL);\r
- DEBUG ((DEBUG_INFO, "APIC Freq % 8lu Hz\n", Freq));\r
-\r
- UnmapXenPage (SharedInfo);\r
-}\r