Commit dcd8f32e authored by John Levon's avatar John Levon Committed by Linus Torvalds

[PATCH] oprofile: Pentium IV support

The below patch implements a P4 driver for OProfile, mostly written
by Graydon Hoare.
parent bd83dce2
...@@ -63,8 +63,6 @@ extern void show_registers(struct pt_regs *regs); ...@@ -63,8 +63,6 @@ extern void show_registers(struct pt_regs *regs);
CRU_ESCR0 (with any non-null event selector) through a complemented CRU_ESCR0 (with any non-null event selector) through a complemented
max threshold. [IA32-Vol3, Section 14.9.9] */ max threshold. [IA32-Vol3, Section 14.9.9] */
#define MSR_P4_IQ_COUNTER0 0x30C #define MSR_P4_IQ_COUNTER0 0x30C
#define MSR_P4_IQ_CCCR0 0x36C
#define MSR_P4_CRU_ESCR0 0x3B8
#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR) #define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
#define P4_NMI_IQ_CCCR0 \ #define P4_NMI_IQ_CCCR0 \
(P4_CCCR_OVF_PMI|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ (P4_CCCR_OVF_PMI|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
......
...@@ -7,4 +7,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ ...@@ -7,4 +7,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofile-y := $(DRIVER_OBJS) init.o timer_int.o oprofile-y := $(DRIVER_OBJS) init.o timer_int.o
oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \
op_model_ppro.o op_model_ppro.o op_model_p4.o
...@@ -214,12 +214,62 @@ struct oprofile_operations nmi_ops = { ...@@ -214,12 +214,62 @@ struct oprofile_operations nmi_ops = {
.stop = nmi_stop .stop = nmi_stop
}; };
#if !defined(CONFIG_X86_64)
static int __init p4_init(enum oprofile_cpu * cpu)
{
__u8 cpu_model = current_cpu_data.x86_model;
if (cpu_model > 3)
return 0;
#ifndef CONFIG_SMP
*cpu = OPROFILE_CPU_P4;
model = &op_p4_spec;
return 1;
#else
switch (smp_num_siblings) {
case 1:
*cpu = OPROFILE_CPU_P4;
model = &op_p4_spec;
return 1;
case 2:
*cpu = OPROFILE_CPU_P4_HT2;
model = &op_p4_ht2_spec;
return 1;
}
#endif
printk(KERN_INFO "oprofile: P4 HyperThreading detected with > 2 threads\n");
printk(KERN_INFO "oprofile: Reverting to timer mode.\n");
return 0;
}
static int __init ppro_init(enum oprofile_cpu * cpu)
{
__u8 cpu_model = current_cpu_data.x86_model;
if (cpu_model > 5) {
*cpu = OPROFILE_CPU_PIII;
} else if (cpu_model > 2) {
*cpu = OPROFILE_CPU_PII;
} else {
*cpu = OPROFILE_CPU_PPRO;
}
model = &op_ppro_spec;
return 1;
}
#endif /* !CONFIG_X86_64 */
int __init nmi_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu) int __init nmi_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu)
{ {
__u8 vendor = current_cpu_data.x86_vendor; __u8 vendor = current_cpu_data.x86_vendor;
__u8 family = current_cpu_data.x86; __u8 family = current_cpu_data.x86;
__u8 cpu_model = current_cpu_data.x86_model;
if (!cpu_has_apic) if (!cpu_has_apic)
return 0; return 0;
...@@ -233,23 +283,26 @@ int __init nmi_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu) ...@@ -233,23 +283,26 @@ int __init nmi_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu)
*cpu = OPROFILE_CPU_ATHLON; *cpu = OPROFILE_CPU_ATHLON;
break; break;
#ifndef CONFIG_X86_64 #if !defined(CONFIG_X86_64)
case X86_VENDOR_INTEL: case X86_VENDOR_INTEL:
/* Less than a P6-class processor */ switch (family) {
if (family != 6) /* Pentium IV */
return 0; case 0xf:
if (!p4_init(cpu))
if (cpu_model > 5) { return 0;
*cpu = OPROFILE_CPU_PIII; break;
} else if (cpu_model > 2) {
*cpu = OPROFILE_CPU_PII; /* A P6-class processor */
} else { case 6:
*cpu = OPROFILE_CPU_PPRO; if (!ppro_init(cpu))
return 0;
break;
default:
return 0;
} }
model = &op_ppro_spec;
break; break;
#endif #endif /* !CONFIG_X86_64 */
default: default:
return 0; return 0;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#ifndef OP_COUNTER_H #ifndef OP_COUNTER_H
#define OP_COUNTER_H #define OP_COUNTER_H
#define OP_MAX_COUNTER 4 #define OP_MAX_COUNTER 8
/* Per-perfctr configuration as set via /* Per-perfctr configuration as set via
* oprofilefs. * oprofilefs.
......
This diff is collapsed.
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
#ifndef OP_X86_MODEL_H #ifndef OP_X86_MODEL_H
#define OP_X86_MODEL_H #define OP_X86_MODEL_H
/* will need re-working for Pentium IV */ /* Pentium IV needs all these */
#define MAX_MSR 4 #define MAX_MSR 63
struct op_saved_msr { struct op_saved_msr {
unsigned int high; unsigned int high;
...@@ -47,6 +47,8 @@ struct op_x86_model_spec { ...@@ -47,6 +47,8 @@ struct op_x86_model_spec {
}; };
extern struct op_x86_model_spec const op_ppro_spec; extern struct op_x86_model_spec const op_ppro_spec;
extern struct op_x86_model_spec const op_p4_spec;
extern struct op_x86_model_spec const op_p4_ht2_spec;
extern struct op_x86_model_spec const op_athlon_spec; extern struct op_x86_model_spec const op_athlon_spec;
#endif /* OP_X86_MODEL_H */ #endif /* OP_X86_MODEL_H */
...@@ -93,6 +93,90 @@ ...@@ -93,6 +93,90 @@
#define MSR_IA32_MC0_ADDR 0x402 #define MSR_IA32_MC0_ADDR 0x402
#define MSR_IA32_MC0_MISC 0x403 #define MSR_IA32_MC0_MISC 0x403
/* Pentium IV performance counter MSRs */
#define MSR_P4_BPU_PERFCTR0 0x300
#define MSR_P4_BPU_PERFCTR1 0x301
#define MSR_P4_BPU_PERFCTR2 0x302
#define MSR_P4_BPU_PERFCTR3 0x303
#define MSR_P4_MS_PERFCTR0 0x304
#define MSR_P4_MS_PERFCTR1 0x305
#define MSR_P4_MS_PERFCTR2 0x306
#define MSR_P4_MS_PERFCTR3 0x307
#define MSR_P4_FLAME_PERFCTR0 0x308
#define MSR_P4_FLAME_PERFCTR1 0x309
#define MSR_P4_FLAME_PERFCTR2 0x30a
#define MSR_P4_FLAME_PERFCTR3 0x30b
#define MSR_P4_IQ_PERFCTR0 0x30c
#define MSR_P4_IQ_PERFCTR1 0x30d
#define MSR_P4_IQ_PERFCTR2 0x30e
#define MSR_P4_IQ_PERFCTR3 0x30f
#define MSR_P4_IQ_PERFCTR4 0x310
#define MSR_P4_IQ_PERFCTR5 0x311
#define MSR_P4_BPU_CCCR0 0x360
#define MSR_P4_BPU_CCCR1 0x361
#define MSR_P4_BPU_CCCR2 0x362
#define MSR_P4_BPU_CCCR3 0x363
#define MSR_P4_MS_CCCR0 0x364
#define MSR_P4_MS_CCCR1 0x365
#define MSR_P4_MS_CCCR2 0x366
#define MSR_P4_MS_CCCR3 0x367
#define MSR_P4_FLAME_CCCR0 0x368
#define MSR_P4_FLAME_CCCR1 0x369
#define MSR_P4_FLAME_CCCR2 0x36a
#define MSR_P4_FLAME_CCCR3 0x36b
#define MSR_P4_IQ_CCCR0 0x36c
#define MSR_P4_IQ_CCCR1 0x36d
#define MSR_P4_IQ_CCCR2 0x36e
#define MSR_P4_IQ_CCCR3 0x36f
#define MSR_P4_IQ_CCCR4 0x370
#define MSR_P4_IQ_CCCR5 0x371
#define MSR_P4_ALF_ESCR0 0x3ca
#define MSR_P4_ALF_ESCR1 0x3cb
#define MSR_P4_BPU_ESCR0 0x3b2
#define MSR_P4_BPU_ESCR1 0x3b3
#define MSR_P4_BSU_ESCR0 0x3a0
#define MSR_P4_BSU_ESCR1 0x3a1
#define MSR_P4_CRU_ESCR0 0x3b8
#define MSR_P4_CRU_ESCR1 0x3b9
#define MSR_P4_CRU_ESCR2 0x3cc
#define MSR_P4_CRU_ESCR3 0x3cd
#define MSR_P4_CRU_ESCR4 0x3e0
#define MSR_P4_CRU_ESCR5 0x3e1
#define MSR_P4_DAC_ESCR0 0x3a8
#define MSR_P4_DAC_ESCR1 0x3a9
#define MSR_P4_FIRM_ESCR0 0x3a4
#define MSR_P4_FIRM_ESCR1 0x3a5
#define MSR_P4_FLAME_ESCR0 0x3a6
#define MSR_P4_FLAME_ESCR1 0x3a7
#define MSR_P4_FSB_ESCR0 0x3a2
#define MSR_P4_FSB_ESCR1 0x3a3
#define MSR_P4_IQ_ESCR0 0x3ba
#define MSR_P4_IQ_ESCR1 0x3bb
#define MSR_P4_IS_ESCR0 0x3b4
#define MSR_P4_IS_ESCR1 0x3b5
#define MSR_P4_ITLB_ESCR0 0x3b6
#define MSR_P4_ITLB_ESCR1 0x3b7
#define MSR_P4_IX_ESCR0 0x3c8
#define MSR_P4_IX_ESCR1 0x3c9
#define MSR_P4_MOB_ESCR0 0x3aa
#define MSR_P4_MOB_ESCR1 0x3ab
#define MSR_P4_MS_ESCR0 0x3c0
#define MSR_P4_MS_ESCR1 0x3c1
#define MSR_P4_PMH_ESCR0 0x3ac
#define MSR_P4_PMH_ESCR1 0x3ad
#define MSR_P4_RAT_ESCR0 0x3bc
#define MSR_P4_RAT_ESCR1 0x3bd
#define MSR_P4_SAAT_ESCR0 0x3ae
#define MSR_P4_SAAT_ESCR1 0x3af
#define MSR_P4_SSU_ESCR0 0x3be
#define MSR_P4_SSU_ESCR1 0x3bf /* guess: not defined in manual */
#define MSR_P4_TBPU_ESCR0 0x3c2
#define MSR_P4_TBPU_ESCR1 0x3c3
#define MSR_P4_TC_ESCR0 0x3c4
#define MSR_P4_TC_ESCR1 0x3c5
#define MSR_P4_U2L_ESCR0 0x3b0
#define MSR_P4_U2L_ESCR1 0x3b1
/* AMD Defined MSRs */ /* AMD Defined MSRs */
#define MSR_K6_EFER 0xC0000080 #define MSR_K6_EFER 0xC0000080
#define MSR_K6_STAR 0xC0000081 #define MSR_K6_STAR 0xC0000081
......
...@@ -21,12 +21,22 @@ struct super_block; ...@@ -21,12 +21,22 @@ struct super_block;
struct dentry; struct dentry;
struct file_operations; struct file_operations;
/* This is duplicated from user-space so
* must be kept in sync :(
*/
enum oprofile_cpu { enum oprofile_cpu {
OPROFILE_CPU_PPRO, OPROFILE_CPU_PPRO,
OPROFILE_CPU_PII, OPROFILE_CPU_PII,
OPROFILE_CPU_PIII, OPROFILE_CPU_PIII,
OPROFILE_CPU_ATHLON, OPROFILE_CPU_ATHLON,
OPROFILE_CPU_TIMER OPROFILE_CPU_TIMER,
OPROFILE_UNUSED1, /* 2.4's RTC mode */
OPROFILE_CPU_P4,
OPROFILE_CPU_IA64,
OPROFILE_CPU_IA64_1,
OPROFILE_CPU_IA64_2,
OPROFILE_CPU_HAMMER,
OPROFILE_CPU_P4_HT2
}; };
/* Operations structure to be filled in */ /* Operations structure to be filled in */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment