Skip to content

Commit 3bcc999

Browse files
committed
sd-boot: don't use TSC in virtualized environments
Replaces: f699bd8 Fixes: systemd#22060
1 parent 16cec13 commit 3bcc999

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

src/boot/efi/ticks.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,47 @@
22

33
#include <efi.h>
44
#include <efilib.h>
5+
#if defined(__i386__) || defined(__x86_64__)
6+
#include <cpuid.h>
7+
#endif
58

69
#include "ticks.h"
710

11+
#if defined(__i386__) || defined(__x86_64__)
12+
static BOOLEAN in_hypervisor(void) {
13+
uint32_t eax, ebx, ecx, edx;
14+
15+
/* The TSC might or might not be virtualized in VMs (and thus might not be accurate or start at zero
16+
* at boot), depending on hypervisor and CPU functionality. If it's not virtualized it's not useful
17+
* for keeping time, hence don't attempt to use it.
18+
*
19+
* This is a dumbed down version of src/basic/virt.c's detect_vm() that safely works in the UEFI
20+
* environment. */
21+
22+
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0)
23+
return FALSE;
24+
25+
return !!(ecx & 0x80000000U);
26+
}
27+
#endif
28+
829
#ifdef __x86_64__
930
static UINT64 ticks_read(void) {
1031
UINT64 a, d;
32+
33+
if (in_hypervisor())
34+
return 0;
35+
1136
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
1237
return (d << 32) | a;
1338
}
1439
#elif defined(__i386__)
1540
static UINT64 ticks_read(void) {
1641
UINT64 val;
42+
43+
if (in_hypervisor())
44+
return 0;
45+
1746
__asm__ volatile ("rdtsc" : "=A" (val));
1847
return val;
1948
}

0 commit comments

Comments
 (0)