Module Name: src Committed By: martin Date: Sun Dec 14 17:02:38 UTC 2014
Modified Files: src/usr.sbin/cpuctl/arch [netbsd-7]: i386.c Log Message: Pull up following revision(s) (requested by msaitoh in ticket #326): usr.sbin/cpuctl/arch/i386.c: revision 1.60 usr.sbin/cpuctl/arch/i386.c: revision 1.61 usr.sbin/cpuctl/arch/i386.c: revision 1.62 usr.sbin/cpuctl/arch/i386.c: revision 1.63 usr.sbin/cpuctl/arch/i386.c: revision 1.64 Add code to detect hypervisor. The code was based from FreeBSD and ported by Kengo Nakahara. kern/49379: Hypervisor's name typo Move some printf()s from cpu_probe_base_features() to identifycpu(). Those printf()s are used for "identify" command but cpu_probe_base_features() is shared by ucodeupdate_check(), too. This change fixes a problem that the "ucode" command print extra output. Add newline if ci_tsc_freq is 0 to not to break the output. Don't print the microcode version if the ioctl failed to not to print garbage. To generate a diff of this commit: cvs rdiff -u -r1.58.2.1 -r1.58.2.2 src/usr.sbin/cpuctl/arch/i386.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/cpuctl/arch/i386.c diff -u src/usr.sbin/cpuctl/arch/i386.c:1.58.2.1 src/usr.sbin/cpuctl/arch/i386.c:1.58.2.2 --- src/usr.sbin/cpuctl/arch/i386.c:1.58.2.1 Fri Dec 12 16:44:35 2014 +++ src/usr.sbin/cpuctl/arch/i386.c Sun Dec 14 17:02:38 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: i386.c,v 1.58.2.1 2014/12/12 16:44:35 martin Exp $ */ +/* $NetBSD: i386.c,v 1.58.2.2 2014/12/14 17:02:38 martin Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: i386.c,v 1.58.2.1 2014/12/12 16:44:35 martin Exp $"); +__RCSID("$NetBSD: i386.c,v 1.58.2.2 2014/12/14 17:02:38 martin Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -220,6 +220,7 @@ static void tmx86_get_longrun_status(u_i static void transmeta_cpu_info(struct cpu_info *); /* Common functions */ static void cpu_probe_base_features(struct cpu_info *, const char *); +static void cpu_probe_hv_features(struct cpu_info *, const char *); static void cpu_probe_features(struct cpu_info *); static void print_bits(const char *, const char *, const char *, uint32_t); static void identifycpu_cpuids(struct cpu_info *); @@ -1443,40 +1444,17 @@ cpu_probe_base_features(struct cpu_info ci->ci_vendor[1] = descs[3]; ci->ci_vendor[3] = 0; - aprint_verbose("%s: highest basic info %08x\n", cpuname, - ci->ci_cpuid_level); - if (verbose) { - int bf; - - for (bf = 0; bf <= ci->ci_cpuid_level; bf++) { - x86_cpuid(bf, descs); - printf("%s: %08x: %08x %08x %08x %08x\n", cpuname, - bf, descs[0], descs[1], descs[2], descs[3]); - } - } - /* * Fn8000_0000: * - Get cpuid extended function's max level. */ x86_cpuid(0x80000000, descs); - if (descs[0] >= 0x80000000) { + if (descs[0] >= 0x80000000) ci->ci_cpuid_extlevel = descs[0]; - aprint_verbose("%s: highest extended info %08x\n", cpuname, - ci->ci_cpuid_extlevel); - } else { + else { /* Set lower value than 0x80000000 */ ci->ci_cpuid_extlevel = 0; } - if (verbose) { - unsigned int ef; - - for (ef = 0x80000000; ef <= ci->ci_cpuid_extlevel; ef++) { - x86_cpuid(ef, descs); - printf("%s: %08x: %08x %08x %08x %08x\n", cpuname, - ef, descs[0], descs[1], descs[2], descs[3]); - } - } /* * Fn8000_000[2-4]: @@ -1546,6 +1524,51 @@ cpu_probe_base_features(struct cpu_info } static void +cpu_probe_hv_features(struct cpu_info *ci, const char *cpuname) +{ + uint32_t descs[4]; + char hv_sig[13]; + char *p; + const char *hv_name; + int i; + + /* + * [RFC] CPUID usage for interaction between Hypervisors and Linux. + * http://lkml.org/lkml/2008/10/1/246 + * + * KB1009458: Mechanisms to determine if software is running in + * a VMware virtual machine + * http://kb.vmware.com/kb/1009458 + */ + if ((ci->ci_feat_val[1] & CPUID2_RAZ) != 0) { + x86_cpuid(0x40000000, descs); + for (i = 1, p = hv_sig; i < 4; i++, p += sizeof(descs) / 4) + memcpy(p, &descs[i], sizeof(descs[i])); + *p = '\0'; + /* + * HV vendor ID string + * ------------+-------------- + * KVM "KVMKVMKVM" + * Microsoft "Microsoft Hv" + * VMware "VMwareVMware" + * Xen "XenVMMXenVMM" + */ + if (strncmp(hv_sig, "KVMKVMKVM", 9) == 0) + hv_name = "KVM"; + else if (strncmp(hv_sig, "Microsoft Hv", 12) == 0) + hv_name = "Hyper-V"; + else if (strncmp(hv_sig, "VMwareVMware", 12) == 0) + hv_name = "VMware"; + else if (strncmp(hv_sig, "XenVMMXenVMM", 12) == 0) + hv_name = "Xen"; + else + hv_name = "unknown"; + + printf("%s: Running on hypervisor: %s\n", cpuname, hv_name); + } +} + +static void cpu_probe_features(struct cpu_info *ci) { const struct cpu_cpuid_nameclass *cpup = NULL; @@ -1660,6 +1683,7 @@ identifycpu(int fd, const char *cpuname) const struct cpu_cpuid_nameclass *cpup = NULL; const struct cpu_cpuid_family *cpufam; struct cpu_info *ci, cistore; + u_int descs[4]; size_t sz; struct cpu_ucode_version ucode; union { @@ -1669,6 +1693,31 @@ identifycpu(int fd, const char *cpuname) ci = &cistore; cpu_probe_base_features(ci, cpuname); + aprint_verbose("%s: highest basic info %08x\n", cpuname, + ci->ci_cpuid_level); + if (verbose) { + int bf; + + for (bf = 0; bf <= ci->ci_cpuid_level; bf++) { + x86_cpuid(bf, descs); + printf("%s: %08x: %08x %08x %08x %08x\n", cpuname, + bf, descs[0], descs[1], descs[2], descs[3]); + } + } + if (ci->ci_cpuid_extlevel >= 0x80000000) + aprint_verbose("%s: highest extended info %08x\n", cpuname, + ci->ci_cpuid_extlevel); + if (verbose) { + unsigned int ef; + + for (ef = 0x80000000; ef <= ci->ci_cpuid_extlevel; ef++) { + x86_cpuid(ef, descs); + printf("%s: %08x: %08x %08x %08x %08x\n", cpuname, + ef, descs[0], descs[1], descs[2], descs[3]); + } + } + + cpu_probe_hv_features(ci, cpuname); cpu_probe_features(ci); if (ci->ci_cpu_type >= 0) { @@ -1787,9 +1836,10 @@ identifycpu(int fd, const char *cpuname) aprint_normal(" (%s-class)", classnames[class]); if (ci->ci_tsc_freq != 0) - aprint_normal(", %ju.%02ju MHz\n", + aprint_normal(", %ju.%02ju MHz", ((uintmax_t)ci->ci_tsc_freq + 4999) / 1000000, (((uintmax_t)ci->ci_tsc_freq + 4999) / 10000) % 100); + aprint_normal("\n"); aprint_normal_dev(ci->ci_dev, "family %#x model %#x stepping %#x", ci->ci_family, ci->ci_model, CPUID_TO_STEPPING(ci->ci_signature)); @@ -1945,6 +1995,8 @@ identifycpu(int fd, const char *cpuname) ucode_64.loader_version = ucode.loader_version; if (ioctl(fd, IOC_CPU_UCODE_GET_VERSION_64, &ucode_64) < 0) return; +#else + return; #endif }