From: "H. Peter Anvin" <hpa@zytor.com>
To: Stefan Bader <stefan.bader@canonical.com>
Cc: wei.y.yang@intel.com,
"xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>,
haitao.shan@intel.com, xin.li@intel.com,
Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Subject: Re: Xen HVM regression on certain Intel CPUs
Date: Wed, 27 Mar 2013 09:32:25 -0700 [thread overview]
Message-ID: <51531F19.6020606@zytor.com> (raw)
In-Reply-To: <51531D4F.5080900@canonical.com>
[-- Attachment #1: Type: text/plain, Size: 739 bytes --]
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
[-- Attachment #2: cpuid.c --]
[-- Type: text/x-csrc, Size: 3245 bytes --]
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
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;
}
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2013-03-27 16:32 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-27 15:26 Xen HVM regression on certain Intel CPUs Stefan Bader
2013-03-27 15:53 ` Stefan Bader
2013-03-27 16:04 ` Konrad Rzeszutek Wilk
2013-03-27 16:09 ` H. Peter Anvin
2013-03-27 16:24 ` Stefan Bader
2013-03-27 16:32 ` H. Peter Anvin [this message]
2013-03-27 16:32 ` Stefano Stabellini
2013-03-27 16:45 ` Stefan Bader
2013-03-27 16:52 ` H. Peter Anvin
2013-03-27 17:17 ` Stefan Bader
2013-03-27 17:23 ` H. Peter Anvin
2013-03-27 17:38 ` Stefan Bader
2013-03-28 13:34 ` Jan Beulich
2013-03-28 15:02 ` Stefan Bader
2013-03-28 16:39 ` Stefan Bader
2013-04-03 11:56 ` Stefan Bader
2013-04-03 12:43 ` Jan Beulich
2013-04-03 14:28 ` Keir Fraser
2013-04-03 15:00 ` Xu, Dongxiao
2013-04-03 15:48 ` H. Peter Anvin
2013-04-03 16:05 ` Jan Beulich
2013-03-27 17:28 ` Stefan Bader
2013-03-27 17:30 ` H. Peter Anvin
2013-03-27 17:40 ` Stefan Bader
2013-03-27 17:44 ` H. Peter Anvin
2013-03-27 20:24 ` Keir Fraser
2013-03-28 15:06 ` Stefan Bader
2013-03-28 15:42 ` H. Peter Anvin
2013-03-28 16:12 ` Stefan Bader
2013-03-27 16:18 ` H. Peter Anvin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51531F19.6020606@zytor.com \
--to=hpa@zytor.com \
--cc=haitao.shan@intel.com \
--cc=konrad.wilk@oracle.com \
--cc=stefan.bader@canonical.com \
--cc=wei.y.yang@intel.com \
--cc=xen-devel@lists.xensource.com \
--cc=xin.li@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.