btrace: identify cpu

Add a struct for identifying a processor and use it in linux-btrace.c when
identifying the processor we're running on.

We will need this feature for the new btrace format.

2015-02-09  Markus Metzger  <markus.t.metzger@intel.com>

	* common/btrace-common.h (btrace_cpu_vendor, btrace_cpu): New.
	* nat/linux-btrace.c: (btrace_this_cpu): New.
	(cpu_supports_bts): Call btrace_this_cpu.
	(intel_supports_bts): Add cpu parameter.
This commit is contained in:
Markus Metzger 2014-02-14 09:25:40 +01:00
parent 7d5c24b3ae
commit afb778a2a8
3 changed files with 83 additions and 22 deletions

View file

@ -1,3 +1,10 @@
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
* common/btrace-common.h (btrace_cpu_vendor, btrace_cpu): New.
* nat/linux-btrace.c: (btrace_this_cpu): New.
(cpu_supports_bts): Call btrace_this_cpu.
(intel_supports_bts): Add cpu parameter.
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
* btrace.h (btrace_insn_class): New.

View file

@ -61,6 +61,34 @@ enum btrace_format
BTRACE_FORMAT_BTS
};
/* An enumeration of cpu vendors. */
enum btrace_cpu_vendor
{
/* We do not know this vendor. */
CV_UNKNOWN,
/* Intel. */
CV_INTEL
};
/* A cpu identifier. */
struct btrace_cpu
{
/* The processor vendor. */
enum btrace_cpu_vendor vendor;
/* The cpu family. */
unsigned short family;
/* The cpu model. */
unsigned char model;
/* The cpu stepping. */
unsigned char stepping;
};
/* A BTS configuration. */
struct btrace_config_bts

View file

@ -59,6 +59,41 @@ struct perf_event_sample
struct perf_event_bts bts;
};
/* Identify the cpu we're running on. */
static struct btrace_cpu
btrace_this_cpu (void)
{
struct btrace_cpu cpu;
unsigned int eax, ebx, ecx, edx;
int ok;
memset (&cpu, 0, sizeof (cpu));
ok = x86_cpuid (0, &eax, &ebx, &ecx, &edx);
if (ok != 0)
{
if (ebx == signature_INTEL_ebx && ecx == signature_INTEL_ecx
&& edx == signature_INTEL_edx)
{
unsigned int cpuid, ignore;
ok = x86_cpuid (1, &cpuid, &ignore, &ignore, &ignore);
if (ok != 0)
{
cpu.vendor = CV_INTEL;
cpu.family = (cpuid >> 8) & 0xf;
cpu.model = (cpuid >> 4) & 0xf;
if (cpu.family == 0x6)
cpu.model += (cpuid >> 12) & 0xf0;
}
}
}
return cpu;
}
/* Return non-zero if there is new data in PEVENT; zero otherwise. */
static int
@ -302,22 +337,12 @@ kernel_supports_bts (void)
/* Check whether an Intel cpu supports BTS. */
static int
intel_supports_bts (void)
intel_supports_bts (const struct btrace_cpu *cpu)
{
unsigned int cpuid, model, family;
if (!x86_cpuid (1, &cpuid, NULL, NULL, NULL))
return 0;
family = (cpuid >> 8) & 0xf;
model = (cpuid >> 4) & 0xf;
switch (family)
switch (cpu->family)
{
case 0x6:
model += (cpuid >> 12) & 0xf0;
switch (model)
switch (cpu->model)
{
case 0x1a: /* Nehalem */
case 0x1f:
@ -345,17 +370,18 @@ intel_supports_bts (void)
static int
cpu_supports_bts (void)
{
unsigned int ebx, ecx, edx;
struct btrace_cpu cpu;
if (!x86_cpuid (0, NULL, &ebx, &ecx, &edx))
return 0;
cpu = btrace_this_cpu ();
switch (cpu.vendor)
{
default:
/* Don't know about others. Let's assume they do. */
return 1;
if (ebx == signature_INTEL_ebx && ecx == signature_INTEL_ecx
&& edx == signature_INTEL_edx)
return intel_supports_bts ();
/* Don't know about others. Let's assume they do. */
return 1;
case CV_INTEL:
return intel_supports_bts (&cpu);
}
}
/* Check whether the linux target supports BTS. */