mirror of
https://github.com/systemd/systemd.git
synced 2024-10-30 06:25:37 +03:00
sd-boot: don't use TSC in virtualized environments
Replaces: f699bd81e8
Fixes: #22060
This commit is contained in:
parent
16cec133c6
commit
3bcc999fa5
@ -2,18 +2,47 @@
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#include "ticks.h"
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static BOOLEAN in_hypervisor(void) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
|
||||
/* The TSC might or might not be virtualized in VMs (and thus might not be accurate or start at zero
|
||||
* at boot), depending on hypervisor and CPU functionality. If it's not virtualized it's not useful
|
||||
* for keeping time, hence don't attempt to use it.
|
||||
*
|
||||
* This is a dumbed down version of src/basic/virt.c's detect_vm() that safely works in the UEFI
|
||||
* environment. */
|
||||
|
||||
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0)
|
||||
return FALSE;
|
||||
|
||||
return !!(ecx & 0x80000000U);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __x86_64__
|
||||
static UINT64 ticks_read(void) {
|
||||
UINT64 a, d;
|
||||
|
||||
if (in_hypervisor())
|
||||
return 0;
|
||||
|
||||
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
|
||||
return (d << 32) | a;
|
||||
}
|
||||
#elif defined(__i386__)
|
||||
static UINT64 ticks_read(void) {
|
||||
UINT64 val;
|
||||
|
||||
if (in_hypervisor())
|
||||
return 0;
|
||||
|
||||
__asm__ volatile ("rdtsc" : "=A" (val));
|
||||
return val;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user