diff options
author | Robert Richter <robert.richter@amd.com> | 2010-09-21 09:49:31 -0400 |
---|---|---|
committer | Robert Richter <robert.richter@amd.com> | 2010-10-15 06:50:42 -0400 |
commit | 25da6950475becb35d7a3bb3b5fbdc715a76887e (patch) | |
tree | ce77e751ee711b08ddc5fd3cc6e159a093676b5b /arch/x86/oprofile/op_model_amd.c | |
parent | 53b39e9480ef8a286cef9899c455a979acd0eed9 (diff) |
oprofile, x86: Add support for IBS branch target address reporting
This patch adds support for IBS branch target address reporting. A new
MSR (MSRC001_103B IBS Branch Target Address) has been added that
provides the logical address in canonical form for the branch
target. The size of the IBS sample that is transferred to the userland
has been increased.
For backward compatibility, the userland daemon must explicit enable
the feature by writing to the oprofilefs file
ibs_op/branch_target
After enabling branch target address reporting, the userland daemon
must handle the extended size of the IBS sample.
Signed-off-by: Robert Richter <robert.richter@amd.com>
Diffstat (limited to 'arch/x86/oprofile/op_model_amd.c')
-rw-r--r-- | arch/x86/oprofile/op_model_amd.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 9d4509736772..9de33fa9531a 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c | |||
@@ -55,10 +55,13 @@ struct ibs_config { | |||
55 | unsigned long max_cnt_op; | 55 | unsigned long max_cnt_op; |
56 | unsigned long rand_en; | 56 | unsigned long rand_en; |
57 | unsigned long dispatched_ops; | 57 | unsigned long dispatched_ops; |
58 | unsigned long branch_target; | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | struct ibs_state { | 61 | struct ibs_state { |
61 | u64 ibs_op_ctl; | 62 | u64 ibs_op_ctl; |
63 | int branch_target; | ||
64 | unsigned long sample_size; | ||
62 | }; | 65 | }; |
63 | 66 | ||
64 | static struct ibs_config ibs_config; | 67 | static struct ibs_config ibs_config; |
@@ -79,6 +82,7 @@ static struct ibs_state ibs_state; | |||
79 | #define IBS_CAPS_OPSAM (1U<<2) | 82 | #define IBS_CAPS_OPSAM (1U<<2) |
80 | #define IBS_CAPS_RDWROPCNT (1U<<3) | 83 | #define IBS_CAPS_RDWROPCNT (1U<<3) |
81 | #define IBS_CAPS_OPCNT (1U<<4) | 84 | #define IBS_CAPS_OPCNT (1U<<4) |
85 | #define IBS_CAPS_BRNTRGT (1U<<5) | ||
82 | 86 | ||
83 | #define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \ | 87 | #define IBS_CAPS_DEFAULT (IBS_CAPS_AVAIL \ |
84 | | IBS_CAPS_FETCHSAM \ | 88 | | IBS_CAPS_FETCHSAM \ |
@@ -207,8 +211,8 @@ op_amd_handle_ibs(struct pt_regs * const regs, | |||
207 | rdmsrl(MSR_AMD64_IBSOPCTL, ctl); | 211 | rdmsrl(MSR_AMD64_IBSOPCTL, ctl); |
208 | if (ctl & IBS_OP_VAL) { | 212 | if (ctl & IBS_OP_VAL) { |
209 | rdmsrl(MSR_AMD64_IBSOPRIP, val); | 213 | rdmsrl(MSR_AMD64_IBSOPRIP, val); |
210 | oprofile_write_reserve(&entry, regs, val, | 214 | oprofile_write_reserve(&entry, regs, val, IBS_OP_CODE, |
211 | IBS_OP_CODE, IBS_OP_SIZE); | 215 | ibs_state.sample_size); |
212 | oprofile_add_data64(&entry, val); | 216 | oprofile_add_data64(&entry, val); |
213 | rdmsrl(MSR_AMD64_IBSOPDATA, val); | 217 | rdmsrl(MSR_AMD64_IBSOPDATA, val); |
214 | oprofile_add_data64(&entry, val); | 218 | oprofile_add_data64(&entry, val); |
@@ -220,6 +224,10 @@ op_amd_handle_ibs(struct pt_regs * const regs, | |||
220 | oprofile_add_data64(&entry, val); | 224 | oprofile_add_data64(&entry, val); |
221 | rdmsrl(MSR_AMD64_IBSDCPHYSAD, val); | 225 | rdmsrl(MSR_AMD64_IBSDCPHYSAD, val); |
222 | oprofile_add_data64(&entry, val); | 226 | oprofile_add_data64(&entry, val); |
227 | if (ibs_state.branch_target) { | ||
228 | rdmsrl(MSR_AMD64_IBSBRTARGET, val); | ||
229 | oprofile_add_data(&entry, (unsigned long)val); | ||
230 | } | ||
223 | oprofile_write_commit(&entry); | 231 | oprofile_write_commit(&entry); |
224 | 232 | ||
225 | /* reenable the IRQ */ | 233 | /* reenable the IRQ */ |
@@ -266,6 +274,11 @@ static inline void op_amd_start_ibs(void) | |||
266 | val |= ibs_config.dispatched_ops ? IBS_OP_CNT_CTL : 0; | 274 | val |= ibs_config.dispatched_ops ? IBS_OP_CNT_CTL : 0; |
267 | val |= IBS_OP_ENABLE; | 275 | val |= IBS_OP_ENABLE; |
268 | ibs_state.ibs_op_ctl = val; | 276 | ibs_state.ibs_op_ctl = val; |
277 | ibs_state.sample_size = IBS_OP_SIZE; | ||
278 | if (ibs_config.branch_target) { | ||
279 | ibs_state.branch_target = 1; | ||
280 | ibs_state.sample_size++; | ||
281 | } | ||
269 | val = op_amd_randomize_ibs_op(ibs_state.ibs_op_ctl); | 282 | val = op_amd_randomize_ibs_op(ibs_state.ibs_op_ctl); |
270 | wrmsrl(MSR_AMD64_IBSOPCTL, val); | 283 | wrmsrl(MSR_AMD64_IBSOPCTL, val); |
271 | } | 284 | } |
@@ -540,11 +553,9 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root) | |||
540 | /* model specific files */ | 553 | /* model specific files */ |
541 | 554 | ||
542 | /* setup some reasonable defaults */ | 555 | /* setup some reasonable defaults */ |
556 | memset(&ibs_config, 0, sizeof(ibs_config)); | ||
543 | ibs_config.max_cnt_fetch = 250000; | 557 | ibs_config.max_cnt_fetch = 250000; |
544 | ibs_config.fetch_enabled = 0; | ||
545 | ibs_config.max_cnt_op = 250000; | 558 | ibs_config.max_cnt_op = 250000; |
546 | ibs_config.op_enabled = 0; | ||
547 | ibs_config.dispatched_ops = 0; | ||
548 | 559 | ||
549 | if (ibs_caps & IBS_CAPS_FETCHSAM) { | 560 | if (ibs_caps & IBS_CAPS_FETCHSAM) { |
550 | dir = oprofilefs_mkdir(sb, root, "ibs_fetch"); | 561 | dir = oprofilefs_mkdir(sb, root, "ibs_fetch"); |
@@ -565,6 +576,9 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root) | |||
565 | if (ibs_caps & IBS_CAPS_OPCNT) | 576 | if (ibs_caps & IBS_CAPS_OPCNT) |
566 | oprofilefs_create_ulong(sb, dir, "dispatched_ops", | 577 | oprofilefs_create_ulong(sb, dir, "dispatched_ops", |
567 | &ibs_config.dispatched_ops); | 578 | &ibs_config.dispatched_ops); |
579 | if (ibs_caps & IBS_CAPS_BRNTRGT) | ||
580 | oprofilefs_create_ulong(sb, dir, "branch_target", | ||
581 | &ibs_config.branch_target); | ||
568 | } | 582 | } |
569 | 583 | ||
570 | return 0; | 584 | return 0; |