Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
cc49b092
Commit
cc49b092
authored
May 10, 2010
by
Ingo Molnar
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'core' of
git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile
into oprofile
parents
7c224a03
bae663bc
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
130 additions
and
113 deletions
+130
-113
arch/x86/oprofile/nmi_int.c
arch/x86/oprofile/nmi_int.c
+113
-74
arch/x86/oprofile/op_model_amd.c
arch/x86/oprofile/op_model_amd.c
+16
-38
arch/x86/oprofile/op_x86_model.h
arch/x86/oprofile/op_x86_model.h
+1
-1
No files found.
arch/x86/oprofile/nmi_int.c
View file @
cc49b092
...
...
@@ -31,8 +31,9 @@ static struct op_x86_model_spec *model;
static
DEFINE_PER_CPU
(
struct
op_msrs
,
cpu_msrs
);
static
DEFINE_PER_CPU
(
unsigned
long
,
saved_lvtpc
);
/* 0 == registered but off, 1 == registered and on */
static
int
nmi_enabled
=
0
;
/* must be protected with get_online_cpus()/put_online_cpus(): */
static
int
nmi_enabled
;
static
int
ctr_running
;
struct
op_counter_config
counter_config
[
OP_MAX_COUNTER
];
...
...
@@ -61,12 +62,16 @@ static int profile_exceptions_notify(struct notifier_block *self,
{
struct
die_args
*
args
=
(
struct
die_args
*
)
data
;
int
ret
=
NOTIFY_DONE
;
int
cpu
=
smp_processor_id
();
switch
(
val
)
{
case
DIE_NMI
:
case
DIE_NMI_IPI
:
model
->
check_ctrs
(
args
->
regs
,
&
per_cpu
(
cpu_msrs
,
cpu
));
if
(
ctr_running
)
model
->
check_ctrs
(
args
->
regs
,
&
__get_cpu_var
(
cpu_msrs
));
else
if
(
!
nmi_enabled
)
break
;
else
model
->
stop
(
&
__get_cpu_var
(
cpu_msrs
));
ret
=
NOTIFY_STOP
;
break
;
default:
...
...
@@ -95,24 +100,36 @@ static void nmi_cpu_save_registers(struct op_msrs *msrs)
static
void
nmi_cpu_start
(
void
*
dummy
)
{
struct
op_msrs
const
*
msrs
=
&
__get_cpu_var
(
cpu_msrs
);
model
->
start
(
msrs
);
if
(
!
msrs
->
controls
)
WARN_ON_ONCE
(
1
);
else
model
->
start
(
msrs
);
}
static
int
nmi_start
(
void
)
{
get_online_cpus
();
on_each_cpu
(
nmi_cpu_start
,
NULL
,
1
);
ctr_running
=
1
;
put_online_cpus
();
return
0
;
}
static
void
nmi_cpu_stop
(
void
*
dummy
)
{
struct
op_msrs
const
*
msrs
=
&
__get_cpu_var
(
cpu_msrs
);
model
->
stop
(
msrs
);
if
(
!
msrs
->
controls
)
WARN_ON_ONCE
(
1
);
else
model
->
stop
(
msrs
);
}
static
void
nmi_stop
(
void
)
{
get_online_cpus
();
on_each_cpu
(
nmi_cpu_stop
,
NULL
,
1
);
ctr_running
=
0
;
put_online_cpus
();
}
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
...
...
@@ -252,7 +269,10 @@ static int nmi_switch_event(void)
if
(
nmi_multiplex_on
()
<
0
)
return
-
EINVAL
;
/* not necessary */
on_each_cpu
(
nmi_cpu_switch
,
NULL
,
1
);
get_online_cpus
();
if
(
ctr_running
)
on_each_cpu
(
nmi_cpu_switch
,
NULL
,
1
);
put_online_cpus
();
return
0
;
}
...
...
@@ -344,50 +364,6 @@ static struct notifier_block profile_exceptions_nb = {
.
priority
=
2
};
static
int
nmi_setup
(
void
)
{
int
err
=
0
;
int
cpu
;
if
(
!
allocate_msrs
())
return
-
ENOMEM
;
/* We need to serialize save and setup for HT because the subset
* of msrs are distinct for save and setup operations
*/
/* Assume saved/restored counters are the same on all CPUs */
err
=
model
->
fill_in_addresses
(
&
per_cpu
(
cpu_msrs
,
0
));
if
(
err
)
goto
fail
;
for_each_possible_cpu
(
cpu
)
{
if
(
!
cpu
)
continue
;
memcpy
(
per_cpu
(
cpu_msrs
,
cpu
).
counters
,
per_cpu
(
cpu_msrs
,
0
).
counters
,
sizeof
(
struct
op_msr
)
*
model
->
num_counters
);
memcpy
(
per_cpu
(
cpu_msrs
,
cpu
).
controls
,
per_cpu
(
cpu_msrs
,
0
).
controls
,
sizeof
(
struct
op_msr
)
*
model
->
num_controls
);
mux_clone
(
cpu
);
}
err
=
register_die_notifier
(
&
profile_exceptions_nb
);
if
(
err
)
goto
fail
;
on_each_cpu
(
nmi_cpu_setup
,
NULL
,
1
);
nmi_enabled
=
1
;
return
0
;
fail:
free_msrs
();
return
err
;
}
static
void
nmi_cpu_restore_registers
(
struct
op_msrs
*
msrs
)
{
struct
op_msr
*
counters
=
msrs
->
counters
;
...
...
@@ -421,19 +397,24 @@ static void nmi_cpu_shutdown(void *dummy)
apic_write
(
APIC_LVTPC
,
per_cpu
(
saved_lvtpc
,
cpu
));
apic_write
(
APIC_LVTERR
,
v
);
nmi_cpu_restore_registers
(
msrs
);
if
(
model
->
cpu_down
)
model
->
cpu_down
();
}
static
void
nmi_
shutdown
(
void
)
static
void
nmi_
cpu_up
(
void
*
dummy
)
{
struct
op_msrs
*
msrs
;
if
(
nmi_enabled
)
nmi_cpu_setup
(
dummy
);
if
(
ctr_running
)
nmi_cpu_start
(
dummy
);
}
nmi_enabled
=
0
;
on_each_cpu
(
nmi_cpu_shutdown
,
NULL
,
1
);
unregister_die_notifier
(
&
profile_exceptions_nb
);
msrs
=
&
get_cpu_var
(
cpu_msrs
);
model
->
shutdown
(
msrs
);
free_msrs
();
put_cpu_var
(
cpu_msrs
);
static
void
nmi_cpu_down
(
void
*
dummy
)
{
if
(
ctr_running
)
nmi_cpu_stop
(
dummy
);
if
(
nmi_enabled
)
nmi_cpu_shutdown
(
dummy
);
}
static
int
nmi_create_files
(
struct
super_block
*
sb
,
struct
dentry
*
root
)
...
...
@@ -465,7 +446,6 @@ static int nmi_create_files(struct super_block *sb, struct dentry *root)
return
0
;
}
#ifdef CONFIG_SMP
static
int
oprofile_cpu_notifier
(
struct
notifier_block
*
b
,
unsigned
long
action
,
void
*
data
)
{
...
...
@@ -473,10 +453,10 @@ static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action,
switch
(
action
)
{
case
CPU_DOWN_FAILED
:
case
CPU_ONLINE
:
smp_call_function_single
(
cpu
,
nmi_cpu_
start
,
NULL
,
0
);
smp_call_function_single
(
cpu
,
nmi_cpu_
up
,
NULL
,
0
);
break
;
case
CPU_DOWN_PREPARE
:
smp_call_function_single
(
cpu
,
nmi_cpu_
stop
,
NULL
,
1
);
smp_call_function_single
(
cpu
,
nmi_cpu_
down
,
NULL
,
1
);
break
;
}
return
NOTIFY_DONE
;
...
...
@@ -485,7 +465,75 @@ static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action,
static
struct
notifier_block
oprofile_cpu_nb
=
{
.
notifier_call
=
oprofile_cpu_notifier
};
#endif
static
int
nmi_setup
(
void
)
{
int
err
=
0
;
int
cpu
;
if
(
!
allocate_msrs
())
return
-
ENOMEM
;
/* We need to serialize save and setup for HT because the subset
* of msrs are distinct for save and setup operations
*/
/* Assume saved/restored counters are the same on all CPUs */
err
=
model
->
fill_in_addresses
(
&
per_cpu
(
cpu_msrs
,
0
));
if
(
err
)
goto
fail
;
for_each_possible_cpu
(
cpu
)
{
if
(
!
cpu
)
continue
;
memcpy
(
per_cpu
(
cpu_msrs
,
cpu
).
counters
,
per_cpu
(
cpu_msrs
,
0
).
counters
,
sizeof
(
struct
op_msr
)
*
model
->
num_counters
);
memcpy
(
per_cpu
(
cpu_msrs
,
cpu
).
controls
,
per_cpu
(
cpu_msrs
,
0
).
controls
,
sizeof
(
struct
op_msr
)
*
model
->
num_controls
);
mux_clone
(
cpu
);
}
nmi_enabled
=
0
;
ctr_running
=
0
;
barrier
();
err
=
register_die_notifier
(
&
profile_exceptions_nb
);
if
(
err
)
goto
fail
;
get_online_cpus
();
register_cpu_notifier
(
&
oprofile_cpu_nb
);
on_each_cpu
(
nmi_cpu_setup
,
NULL
,
1
);
nmi_enabled
=
1
;
put_online_cpus
();
return
0
;
fail:
free_msrs
();
return
err
;
}
static
void
nmi_shutdown
(
void
)
{
struct
op_msrs
*
msrs
;
get_online_cpus
();
unregister_cpu_notifier
(
&
oprofile_cpu_nb
);
on_each_cpu
(
nmi_cpu_shutdown
,
NULL
,
1
);
nmi_enabled
=
0
;
ctr_running
=
0
;
put_online_cpus
();
barrier
();
unregister_die_notifier
(
&
profile_exceptions_nb
);
msrs
=
&
get_cpu_var
(
cpu_msrs
);
model
->
shutdown
(
msrs
);
free_msrs
();
put_cpu_var
(
cpu_msrs
);
}
#ifdef CONFIG_PM
...
...
@@ -695,9 +743,6 @@ int __init op_nmi_init(struct oprofile_operations *ops)
return
-
ENODEV
;
}
#ifdef CONFIG_SMP
register_cpu_notifier
(
&
oprofile_cpu_nb
);
#endif
/* default values, can be overwritten by model */
ops
->
create_files
=
nmi_create_files
;
ops
->
setup
=
nmi_setup
;
...
...
@@ -724,12 +769,6 @@ int __init op_nmi_init(struct oprofile_operations *ops)
void
op_nmi_exit
(
void
)
{
if
(
using_nmi
)
{
if
(
using_nmi
)
exit_sysfs
();
#ifdef CONFIG_SMP
unregister_cpu_notifier
(
&
oprofile_cpu_nb
);
#endif
}
if
(
model
->
exit
)
model
->
exit
();
}
arch/x86/oprofile/op_model_amd.c
View file @
cc49b092
...
...
@@ -374,6 +374,15 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
val
|=
op_x86_get_ctrl
(
model
,
&
counter_config
[
virt
]);
wrmsrl
(
msrs
->
controls
[
i
].
addr
,
val
);
}
if
(
ibs_caps
)
setup_APIC_eilvt_ibs
(
0
,
APIC_EILVT_MSG_NMI
,
0
);
}
static
void
op_amd_cpu_shutdown
(
void
)
{
if
(
ibs_caps
)
setup_APIC_eilvt_ibs
(
0
,
APIC_EILVT_MSG_FIX
,
1
);
}
static
int
op_amd_check_ctrs
(
struct
pt_regs
*
const
regs
,
...
...
@@ -436,28 +445,16 @@ static void op_amd_stop(struct op_msrs const * const msrs)
op_amd_stop_ibs
();
}
static
u8
ibs_eilvt_off
;
static
inline
void
apic_init_ibs_nmi_per_cpu
(
void
*
arg
)
{
ibs_eilvt_off
=
setup_APIC_eilvt_ibs
(
0
,
APIC_EILVT_MSG_NMI
,
0
);
}
static
inline
void
apic_clear_ibs_nmi_per_cpu
(
void
*
arg
)
{
setup_APIC_eilvt_ibs
(
0
,
APIC_EILVT_MSG_FIX
,
1
);
}
static
int
init_ibs_nmi
(
void
)
static
int
__init_ibs_nmi
(
void
)
{
#define IBSCTL_LVTOFFSETVAL (1 << 8)
#define IBSCTL 0x1cc
struct
pci_dev
*
cpu_cfg
;
int
nodes
;
u32
value
=
0
;
u8
ibs_eilvt_off
;
/* per CPU setup */
on_each_cpu
(
apic_init_ibs_nmi_per_cpu
,
NULL
,
1
);
ibs_eilvt_off
=
setup_APIC_eilvt_ibs
(
0
,
APIC_EILVT_MSG_FIX
,
1
);
nodes
=
0
;
cpu_cfg
=
NULL
;
...
...
@@ -487,21 +484,15 @@ static int init_ibs_nmi(void)
return
0
;
}
/* uninitialize the APIC for the IBS interrupts if needed */
static
void
clear_ibs_nmi
(
void
)
{
on_each_cpu
(
apic_clear_ibs_nmi_per_cpu
,
NULL
,
1
);
}
/* initialize the APIC for the IBS interrupts if available */
static
void
i
bs_init
(
void
)
static
void
i
nit_ibs
(
void
)
{
ibs_caps
=
get_ibs_caps
();
if
(
!
ibs_caps
)
return
;
if
(
init_ibs_nmi
())
{
if
(
__
init_ibs_nmi
())
{
ibs_caps
=
0
;
return
;
}
...
...
@@ -510,14 +501,6 @@ static void ibs_init(void)
(
unsigned
)
ibs_caps
);
}
static
void
ibs_exit
(
void
)
{
if
(
!
ibs_caps
)
return
;
clear_ibs_nmi
();
}
static
int
(
*
create_arch_files
)(
struct
super_block
*
sb
,
struct
dentry
*
root
);
static
int
setup_ibs_files
(
struct
super_block
*
sb
,
struct
dentry
*
root
)
...
...
@@ -566,17 +549,12 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root)
static
int
op_amd_init
(
struct
oprofile_operations
*
ops
)
{
i
bs_init
();
i
nit_ibs
();
create_arch_files
=
ops
->
create_files
;
ops
->
create_files
=
setup_ibs_files
;
return
0
;
}
static
void
op_amd_exit
(
void
)
{
ibs_exit
();
}
struct
op_x86_model_spec
op_amd_spec
=
{
.
num_counters
=
NUM_COUNTERS
,
.
num_controls
=
NUM_COUNTERS
,
...
...
@@ -584,9 +562,9 @@ struct op_x86_model_spec op_amd_spec = {
.
reserved
=
MSR_AMD_EVENTSEL_RESERVED
,
.
event_mask
=
OP_EVENT_MASK
,
.
init
=
op_amd_init
,
.
exit
=
op_amd_exit
,
.
fill_in_addresses
=
&
op_amd_fill_in_addresses
,
.
setup_ctrs
=
&
op_amd_setup_ctrs
,
.
cpu_down
=
&
op_amd_cpu_shutdown
,
.
check_ctrs
=
&
op_amd_check_ctrs
,
.
start
=
&
op_amd_start
,
.
stop
=
&
op_amd_stop
,
...
...
arch/x86/oprofile/op_x86_model.h
View file @
cc49b092
...
...
@@ -40,10 +40,10 @@ struct op_x86_model_spec {
u64
reserved
;
u16
event_mask
;
int
(
*
init
)(
struct
oprofile_operations
*
ops
);
void
(
*
exit
)(
void
);
int
(
*
fill_in_addresses
)(
struct
op_msrs
*
const
msrs
);
void
(
*
setup_ctrs
)(
struct
op_x86_model_spec
const
*
model
,
struct
op_msrs
const
*
const
msrs
);
void
(
*
cpu_down
)(
void
);
int
(
*
check_ctrs
)(
struct
pt_regs
*
const
regs
,
struct
op_msrs
const
*
const
msrs
);
void
(
*
start
)(
struct
op_msrs
const
*
const
msrs
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment