From mboxrd@z Thu Jan 1 00:00:00 1970 From: "H. Peter Anvin" Subject: Re: Xen HVM regression on certain Intel CPUs Date: Wed, 27 Mar 2013 09:32:25 -0700 Message-ID: <51531F19.6020606@zytor.com> References: <51530F9F.10805@canonical.com> <515315EC.4030803@canonical.com> <20130327160427.GB6688@phenom.dumpdata.com> <515319AF.1050900@zytor.com> <51531D4F.5080900@canonical.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------020505040604060702040701" Return-path: In-Reply-To: <51531D4F.5080900@canonical.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Stefan Bader Cc: wei.y.yang@intel.com, "xen-devel@lists.xensource.com" , haitao.shan@intel.com, xin.li@intel.com, Konrad Rzeszutek Wilk List-Id: xen-devel@lists.xenproject.org This is a multi-part message in MIME format. --------------020505040604060702040701 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 03/27/2013 09:24 AM, Stefan Bader wrote: >> >> When you say Xen HVM, am I correct in assuming that neither CPUID >> nor CR4 operations in the main kernel are run through >> paravirt_ops? > > Not paravirt ops likely but the hypervisor traps access. At least > cpuid from within a hvm guest I expect to be filtered. So when > checking things I went to bare-metal. > > Will fetch more info and get back. > Hypervisor traps is one thing... they should be consistent no matter where in the code they happen... unless they are broken. Try this CPUID program. This uses the kernel /dev interface which may be somewhat suboptimal in case CPUID in userspace actually differs, but it would be interesting to know what it outputs. -hpa --------------020505040604060702040701 Content-Type: text/x-csrc; name="cpuid.c" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="cpuid.c" #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include struct cpuid { uint32_t eax, ebx, ecx, edx; }; static int cpuid(int cpu, uint32_t leaf, uint32_t subleaf, struct cpuid *data) { static int fd = -1; static int last_cpu; off_t offset = leaf + ((off_t)subleaf << 32); if (fd < 0 || last_cpu != cpu) { char devstr[64]; if (fd >= 0) close(fd); snprintf(devstr, sizeof devstr, "/dev/cpu/%d/cpuid", cpu); fd = open(devstr, O_RDONLY); last_cpu = cpu; } return pread(fd, data, sizeof(*data), offset) == sizeof(*data) ? 0 : -1; } static char *make_string(uint32_t val) { static char string[5] = "xxxx"; int i, ch; for ( i = 0 ; i < 4 ; i++ ) { ch = val & 0xff; string[i] = isprint(ch) ? ch : '.'; val >>= 8; } return string; } static void print_cpuid_level(uint32_t leaf, uint32_t subleaf, struct cpuid *lvl) { printf("%08x %08x: ", leaf, subleaf); printf("%08x %s ", lvl->eax, make_string(lvl->eax)); printf("%08x %s ", lvl->ebx, make_string(lvl->ebx)); printf("%08x %s ", lvl->ecx, make_string(lvl->ecx)); printf("%08x %s\n", lvl->edx, make_string(lvl->edx)); } static void dump_cpuid_leaf(int cpu, uint32_t leaf) { struct cpuid lvl, lastlvl, lvl0; uint32_t subleaf; cpuid(cpu, leaf, 0, &lvl0); print_cpuid_level(leaf, 0, &lvl0); /* * There is no standard mechanism for enumerating the number of * subleaves, this is a heuristic... */ lastlvl = lvl0; for (subleaf = 1; subleaf != 0; subleaf++) { if (cpuid(cpu, leaf, subleaf, &lvl)) return; switch (leaf) { case 4: if ((lvl.eax & 0x1f) == 0 || !memcmp(&lvl, &lastlvl, sizeof lvl)) return; break; case 7: if (subleaf >= lvl0.eax) return; break; case 0xb: if ((lvl.ecx & ~0xff) == 0) return; case 0xd: if ((lvl.eax | lvl.ebx | lvl.ecx | lvl.edx) == 0) return; default: /* Generic, anticipatory rules */ /* Exclude ecx here for levels which return the initial ecx value */ if ((lvl.eax | lvl.ebx | lvl.ecx | lvl.edx) == 0) return; if (!memcmp(&lvl, &lvl0, sizeof lvl)) return; break; } print_cpuid_level(leaf, subleaf, &lvl); lastlvl = lvl; } } static void dump_levels(int cpu, uint32_t region) { static struct cpuid invalid_leaf; struct cpuid max; uint32_t n; if (cpuid(cpu, region, 0, &max)) return; /* * Intel processors may return the last group 0 CPUID leaf instead * all zero for a not-present level */ if (region == 0) { cpuid(cpu, max.eax+1, 0, &invalid_leaf); } else { if (!memcmp(&max, &invalid_leaf, sizeof(struct cpuid))) return; } if ( (max.eax & 0xffff0000) == region ) { for ( n = region ; n <= max.eax ; n++ ) { dump_cpuid_leaf(cpu, n); } } } int main(int argc, char *argv[]) { int cpu; uint32_t n; cpu = (argc > 1) ? atoi(argv[1]) : 0; printf("Leaf Subleaf EAX EBX ECX EDX \n"); for ( n = 0 ; n <= 0xffff ; n++ ) { dump_levels(cpu, n << 16); } return 0; } --------------020505040604060702040701 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel --------------020505040604060702040701--