#include <sys/personality.h>
#endif
+#ifdef HAVE_CPUID_H
+#include <cpuid.h>
+#endif
+
#include <pulse/xmalloc.h>
#include <pulse/util.h>
#include <pulse/utf8.h>
#include <pulsecore/strbuf.h>
#include <pulsecore/usergroup.h>
#include <pulsecore/strlist.h>
-#include <pulsecore/cpu-x86.h>
#include <pulsecore/pipe.h>
#include <pulsecore/once.h>
/* Both CPUID and DMI are x86 specific interfaces... */
- uint32_t eax = 0x40000000;
+#ifdef HAVE_CPUID_H
+ uint32_t eax;
union {
uint32_t sig32[3];
char text[13];
} sig;
+#endif
#ifdef __linux__
const char *const dmi_vendors[] = {
#endif
- /* http://lwn.net/Articles/301888/ */
- pa_zero(sig);
-
- __asm__ __volatile__ (
- /* 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"
+#ifdef HAVE_CPUID_H
- : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
- : "0" (eax)
- );
+ /* 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);
+ if (__get_cpuid(0x40000000, &eax, &sig.sig32[0], &sig.sig32[1], &sig.sig32[2]) == 0)
+ return false;
if (pa_streq(sig.text, "XenVMMXenVMM") ||
pa_streq(sig.text, "KVMKVMKVM") ||
/* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
pa_streq(sig.text, "Microsoft Hv"))
return true;
+#endif /* HAVE_CPUID_H */
-#endif
+#endif /* defined(__i386__) || defined(__x86_64__) */
return false;
}
#include <stdint.h>
+#ifdef HAVE_CPUID_H
+#include <cpuid.h>
+#endif
+
#include <pulsecore/log.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) {
-#if defined (__i386__) || defined (__amd64__)
+#if (defined(__i386__) || defined(__amd64__)) && defined(HAVE_CPUID_H)
uint32_t eax, ebx, ecx, edx;
uint32_t level;
*flags = 0;
/* get standard level */
- get_cpuid(0x00000000, &level, &ebx, &ecx, &edx);
+ if (__get_cpuid(0x00000000, &level, &ebx, &ecx, &edx) == 0)
+ goto finish;
+
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))
*flags |= PA_CPU_X86_CMOV;
}
/* get extended level */
- get_cpuid(0x80000000, &level, &ebx, &ecx, &edx);
+ if (__get_cpuid(0x80000000, &level, &ebx, &ecx, &edx) == 0)
+ goto finish;
+
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))
*flags |= PA_CPU_X86_MMXEXT;
*flags |= PA_CPU_X86_3DNOW;
}
+finish:
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_MMX) ? "MMX " : "",
(*flags & PA_CPU_X86_MMXEXT) ? "MMXEXT " : "",
(*flags & PA_CPU_X86_3DNOW) ? "3DNOW " : "",
(*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) {