mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
core-util, cpu-x86: use __get_cpuid() instead of homegrown assembly
The get_cpuid() function in cpu-x86.c was buggy on x86-64. When building without optimizations, the homegrown assembly code overwrote the beginning of the function argument list on the stack. That happened to work fine on regular x86-64, but caused crashing with the x32 ABI. At least GCC and clang provide cpuid.h, which has the __get_cpuid() function that can be used instead of the homegrown assembly. The PA_REG_* constants can be removed as well, because they're not used any more. BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=103656
This commit is contained in:
parent
2062fc8b0e
commit
c8bd93c5a7
4 changed files with 38 additions and 48 deletions
|
|
@ -410,7 +410,7 @@ AC_SUBST([LIBLTDL])
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
|
|
||||||
# POSIX
|
# POSIX
|
||||||
AC_CHECK_HEADERS_ONCE([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \
|
AC_CHECK_HEADERS_ONCE([arpa/inet.h cpuid.h glob.h grp.h netdb.h netinet/in.h \
|
||||||
netinet/in_systm.h netinet/tcp.h poll.h pwd.h sched.h \
|
netinet/in_systm.h netinet/tcp.h poll.h pwd.h sched.h \
|
||||||
sys/mman.h sys/select.h sys/socket.h sys/wait.h \
|
sys/mman.h sys/select.h sys/socket.h sys/wait.h \
|
||||||
sys/uio.h syslog.h sys/dl.h dlfcn.h linux/sockios.h])
|
sys/uio.h syslog.h sys/dl.h dlfcn.h linux/sockios.h])
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,10 @@
|
||||||
#include <sys/personality.h>
|
#include <sys/personality.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CPUID_H
|
||||||
|
#include <cpuid.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pulse/xmalloc.h>
|
#include <pulse/xmalloc.h>
|
||||||
#include <pulse/util.h>
|
#include <pulse/util.h>
|
||||||
#include <pulse/utf8.h>
|
#include <pulse/utf8.h>
|
||||||
|
|
@ -136,7 +140,6 @@
|
||||||
#include <pulsecore/strbuf.h>
|
#include <pulsecore/strbuf.h>
|
||||||
#include <pulsecore/usergroup.h>
|
#include <pulsecore/usergroup.h>
|
||||||
#include <pulsecore/strlist.h>
|
#include <pulsecore/strlist.h>
|
||||||
#include <pulsecore/cpu-x86.h>
|
|
||||||
#include <pulsecore/pipe.h>
|
#include <pulsecore/pipe.h>
|
||||||
#include <pulsecore/once.h>
|
#include <pulsecore/once.h>
|
||||||
|
|
||||||
|
|
@ -3663,11 +3666,13 @@ bool pa_running_in_vm(void) {
|
||||||
|
|
||||||
/* Both CPUID and DMI are x86 specific interfaces... */
|
/* Both CPUID and DMI are x86 specific interfaces... */
|
||||||
|
|
||||||
uint32_t eax = 0x40000000;
|
#ifdef HAVE_CPUID_H
|
||||||
|
uint32_t eax;
|
||||||
union {
|
union {
|
||||||
uint32_t sig32[3];
|
uint32_t sig32[3];
|
||||||
char text[13];
|
char text[13];
|
||||||
} sig;
|
} sig;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
const char *const dmi_vendors[] = {
|
const char *const dmi_vendors[] = {
|
||||||
|
|
@ -3701,19 +3706,18 @@ bool pa_running_in_vm(void) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* http://lwn.net/Articles/301888/ */
|
#ifdef HAVE_CPUID_H
|
||||||
|
|
||||||
|
/* Hypervisors provide their signature on the 0x40000000 cpuid leaf.
|
||||||
|
* http://lwn.net/Articles/301888/
|
||||||
|
*
|
||||||
|
* XXX: Why are we checking a list of signatures instead of the
|
||||||
|
* "hypervisor present bit"? According to the LWN article, the "hypervisor
|
||||||
|
* present bit" would be available on bit 31 of ECX on leaf 0x1, and that
|
||||||
|
* bit would tell us directly whether we're in a virtual machine or not. */
|
||||||
pa_zero(sig);
|
pa_zero(sig);
|
||||||
|
if (__get_cpuid(0x40000000, &eax, &sig.sig32[0], &sig.sig32[1], &sig.sig32[2]) == 0)
|
||||||
__asm__ __volatile__ (
|
return false;
|
||||||
/* ebx/rbx is being used for PIC! */
|
|
||||||
" push %%"PA_REG_b" \n\t"
|
|
||||||
" cpuid \n\t"
|
|
||||||
" mov %%ebx, %1 \n\t"
|
|
||||||
" pop %%"PA_REG_b" \n\t"
|
|
||||||
|
|
||||||
: "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
|
|
||||||
: "0" (eax)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pa_streq(sig.text, "XenVMMXenVMM") ||
|
if (pa_streq(sig.text, "XenVMMXenVMM") ||
|
||||||
pa_streq(sig.text, "KVMKVMKVM") ||
|
pa_streq(sig.text, "KVMKVMKVM") ||
|
||||||
|
|
@ -3722,8 +3726,9 @@ bool pa_running_in_vm(void) {
|
||||||
/* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
|
/* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
|
||||||
pa_streq(sig.text, "Microsoft Hv"))
|
pa_streq(sig.text, "Microsoft Hv"))
|
||||||
return true;
|
return true;
|
||||||
|
#endif /* HAVE_CPUID_H */
|
||||||
|
|
||||||
#endif
|
#endif /* defined(__i386__) || defined(__x86_64__) */
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,35 +24,28 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_CPUID_H
|
||||||
|
#include <cpuid.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pulsecore/log.h>
|
#include <pulsecore/log.h>
|
||||||
|
|
||||||
#include "cpu-x86.h"
|
#include "cpu-x86.h"
|
||||||
|
|
||||||
#if defined (__i386__) || defined (__amd64__)
|
|
||||||
static void get_cpuid(uint32_t op, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
" push %%"PA_REG_b" \n\t"
|
|
||||||
" cpuid \n\t"
|
|
||||||
" mov %%ebx, %%esi \n\t"
|
|
||||||
" pop %%"PA_REG_b" \n\t"
|
|
||||||
|
|
||||||
: "=a" (*a), "=S" (*b), "=c" (*c), "=d" (*d)
|
|
||||||
: "0" (op)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void pa_cpu_get_x86_flags(pa_cpu_x86_flag_t *flags) {
|
void pa_cpu_get_x86_flags(pa_cpu_x86_flag_t *flags) {
|
||||||
#if defined (__i386__) || defined (__amd64__)
|
#if (defined(__i386__) || defined(__amd64__)) && defined(HAVE_CPUID_H)
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
uint32_t level;
|
uint32_t level;
|
||||||
|
|
||||||
*flags = 0;
|
*flags = 0;
|
||||||
|
|
||||||
/* get standard level */
|
/* get standard level */
|
||||||
get_cpuid(0x00000000, &level, &ebx, &ecx, &edx);
|
if (__get_cpuid(0x00000000, &level, &ebx, &ecx, &edx) == 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
if (level >= 1) {
|
if (level >= 1) {
|
||||||
get_cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
|
if (__get_cpuid(0x00000001, &eax, &ebx, &ecx, &edx) == 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
if (edx & (1<<15))
|
if (edx & (1<<15))
|
||||||
*flags |= PA_CPU_X86_CMOV;
|
*flags |= PA_CPU_X86_CMOV;
|
||||||
|
|
@ -80,9 +73,12 @@ void pa_cpu_get_x86_flags(pa_cpu_x86_flag_t *flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get extended level */
|
/* get extended level */
|
||||||
get_cpuid(0x80000000, &level, &ebx, &ecx, &edx);
|
if (__get_cpuid(0x80000000, &level, &ebx, &ecx, &edx) == 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
if (level >= 0x80000001) {
|
if (level >= 0x80000001) {
|
||||||
get_cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
|
if (__get_cpuid(0x80000001, &eax, &ebx, &ecx, &edx) == 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
if (edx & (1<<22))
|
if (edx & (1<<22))
|
||||||
*flags |= PA_CPU_X86_MMXEXT;
|
*flags |= PA_CPU_X86_MMXEXT;
|
||||||
|
|
@ -97,6 +93,7 @@ void pa_cpu_get_x86_flags(pa_cpu_x86_flag_t *flags) {
|
||||||
*flags |= PA_CPU_X86_3DNOW;
|
*flags |= PA_CPU_X86_3DNOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finish:
|
||||||
pa_log_info("CPU flags: %s%s%s%s%s%s%s%s%s%s%s",
|
pa_log_info("CPU flags: %s%s%s%s%s%s%s%s%s%s%s",
|
||||||
(*flags & PA_CPU_X86_CMOV) ? "CMOV " : "",
|
(*flags & PA_CPU_X86_CMOV) ? "CMOV " : "",
|
||||||
(*flags & PA_CPU_X86_MMX) ? "MMX " : "",
|
(*flags & PA_CPU_X86_MMX) ? "MMX " : "",
|
||||||
|
|
@ -109,7 +106,7 @@ void pa_cpu_get_x86_flags(pa_cpu_x86_flag_t *flags) {
|
||||||
(*flags & PA_CPU_X86_MMXEXT) ? "MMXEXT " : "",
|
(*flags & PA_CPU_X86_MMXEXT) ? "MMXEXT " : "",
|
||||||
(*flags & PA_CPU_X86_3DNOW) ? "3DNOW " : "",
|
(*flags & PA_CPU_X86_3DNOW) ? "3DNOW " : "",
|
||||||
(*flags & PA_CPU_X86_3DNOWEXT) ? "3DNOWEXT " : "");
|
(*flags & PA_CPU_X86_3DNOWEXT) ? "3DNOWEXT " : "");
|
||||||
#endif /* defined (__i386__) || defined (__amd64__) */
|
#endif /* (defined(__i386__) || defined(__amd64__)) && defined(HAVE_CPUID_H) */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pa_cpu_init_x86(pa_cpu_x86_flag_t *flags) {
|
bool pa_cpu_init_x86(pa_cpu_x86_flag_t *flags) {
|
||||||
|
|
|
||||||
|
|
@ -43,20 +43,8 @@ bool pa_cpu_init_x86 (pa_cpu_x86_flag_t *flags);
|
||||||
|
|
||||||
#if defined (__i386__)
|
#if defined (__i386__)
|
||||||
typedef int32_t pa_reg_x86;
|
typedef int32_t pa_reg_x86;
|
||||||
#define PA_REG_a "eax"
|
|
||||||
#define PA_REG_b "ebx"
|
|
||||||
#define PA_REG_c "ecx"
|
|
||||||
#define PA_REG_d "edx"
|
|
||||||
#define PA_REG_D "edi"
|
|
||||||
#define PA_REG_S "esi"
|
|
||||||
#elif defined (__amd64__)
|
#elif defined (__amd64__)
|
||||||
typedef int64_t pa_reg_x86;
|
typedef int64_t pa_reg_x86;
|
||||||
#define PA_REG_a "rax"
|
|
||||||
#define PA_REG_b "rbx"
|
|
||||||
#define PA_REG_c "rcx"
|
|
||||||
#define PA_REG_d "rdx"
|
|
||||||
#define PA_REG_D "rdi"
|
|
||||||
#define PA_REG_S "rsi"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* some optimized functions */
|
/* some optimized functions */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue