x86: cpufunc: Add rdtsc_ordered()

Add a variant of 'rdtsc()' that performs the ordered version of 'rdtsc'
appropriate for the invoking x86 variant.

Also, expose the 'lfence'-ed and 'mfence'-ed 'rdtsc()' variants needed
by 'rdtsc_ordered()' for general use.

Sponsored by:	Juniper Networks, Inc.
Sponsored by:	Klara, Inc.
Reviewed by:	kib
Differential Revision:	https://reviews.freebsd.org/D31416
This commit is contained in:
Adam Fenn 2021-07-28 10:12:00 -07:00 committed by Konstantin Belousov
parent 908e277230
commit 652ae7b114
4 changed files with 45 additions and 0 deletions

View File

@ -355,6 +355,20 @@ rdtsc(void)
return (low | ((uint64_t)high << 32));
}
static __inline uint64_t
rdtsc_ordered_lfence(void)
{
lfence();
return (rdtsc());
}
static __inline uint64_t
rdtsc_ordered_mfence(void)
{
mfence();
return (rdtsc());
}
static __inline uint64_t
rdtscp(void)
{

View File

@ -394,6 +394,20 @@ rdtsc(void)
return (rv);
}
static __inline uint64_t
rdtsc_ordered_lfence(void)
{
lfence();
return (rdtsc());
}
static __inline uint64_t
rdtsc_ordered_mfence(void)
{
mfence();
return (rdtsc());
}
static __inline uint64_t
rdtscp(void)
{

View File

@ -154,6 +154,7 @@ int user_dbreg_trap(register_t dr6);
int minidumpsys(struct dumperinfo *);
struct pcb *get_pcb_td(struct thread *td);
void x86_set_fork_retval(struct thread *td);
uint64_t rdtsc_ordered(void);
/*
* MSR ops for x86_msr_op()

View File

@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/cputypes.h>
#include <machine/specialreg.h>
#include <machine/md_var.h>
@ -88,6 +89,7 @@ __FBSDID("$FreeBSD$");
#include <machine/elan_mmcr.h>
#endif
#include <x86/acpica_machdep.h>
#include <x86/ifunc.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@ -1508,3 +1510,17 @@ acpi_get_fadt_bootflags(uint16_t *flagsp)
return (false);
#endif
}
DEFINE_IFUNC(, uint64_t, rdtsc_ordered, (void))
{
bool cpu_is_amd = cpu_vendor_id == CPU_VENDOR_AMD ||
cpu_vendor_id == CPU_VENDOR_HYGON;
if ((amd_feature & AMDID_RDTSCP) != 0)
return (rdtscp);
else if ((cpu_feature & CPUID_SSE2) != 0)
return (cpu_is_amd ? rdtsc_ordered_mfence :
rdtsc_ordered_lfence);
else
return (rdtsc);
}