diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:31:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:31:25 -0500 |
commit | 526ea064f953fc5ad2fb905b537f490b9374a0f0 (patch) | |
tree | c4ff0cb65ce6442863c7c342f641a41f0995329a /arch/x86 | |
parent | db5e53fbf0abf5cadc83be57032242e5e7c6c394 (diff) | |
parent | d69d59f49763e6bd047c591c6c1f84c8e13da931 (diff) |
Merge branch 'oprofile-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'oprofile-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
oprofile: select RING_BUFFER
ring_buffer: adding EXPORT_SYMBOLs
oprofile: fix lost sample counter
oprofile: remove nr_available_slots()
oprofile: port to the new ring_buffer
ring_buffer: add remaining cpu functions to ring_buffer.h
oprofile: moving cpu_buffer_reset() to cpu_buffer.h
oprofile: adding cpu_buffer_entries()
oprofile: adding cpu_buffer_write_commit()
oprofile: adding cpu buffer r/w access functions
ftrace: remove unused function arg in trace_iterator_increment()
ring_buffer: update description for ring_buffer_alloc()
oprofile: set values to default when creating oprofilefs
oprofile: implement switch/case in buffer_sync.c
x86/oprofile: cleanup IBS init/exit functions in op_model_amd.c
x86/oprofile: reordering IBS code in op_model_amd.c
oprofile: fix typo
oprofile: whitspace changes only
oprofile: update comment for oprofile_add_sample()
oprofile: comment cleanup
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/oprofile/op_model_amd.c | 89 |
1 files changed, 46 insertions, 43 deletions
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 509513760a6e..98658f25f542 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c | |||
@@ -65,11 +65,13 @@ static unsigned long reset_value[NUM_COUNTERS]; | |||
65 | #define IBS_FETCH_BEGIN 3 | 65 | #define IBS_FETCH_BEGIN 3 |
66 | #define IBS_OP_BEGIN 4 | 66 | #define IBS_OP_BEGIN 4 |
67 | 67 | ||
68 | /* The function interface needs to be fixed, something like add | 68 | /* |
69 | data. Should then be added to linux/oprofile.h. */ | 69 | * The function interface needs to be fixed, something like add |
70 | * data. Should then be added to linux/oprofile.h. | ||
71 | */ | ||
70 | extern void | 72 | extern void |
71 | oprofile_add_ibs_sample(struct pt_regs *const regs, | 73 | oprofile_add_ibs_sample(struct pt_regs * const regs, |
72 | unsigned int *const ibs_sample, int ibs_code); | 74 | unsigned int * const ibs_sample, int ibs_code); |
73 | 75 | ||
74 | struct ibs_fetch_sample { | 76 | struct ibs_fetch_sample { |
75 | /* MSRC001_1031 IBS Fetch Linear Address Register */ | 77 | /* MSRC001_1031 IBS Fetch Linear Address Register */ |
@@ -104,11 +106,6 @@ struct ibs_op_sample { | |||
104 | unsigned int ibs_dc_phys_high; | 106 | unsigned int ibs_dc_phys_high; |
105 | }; | 107 | }; |
106 | 108 | ||
107 | /* | ||
108 | * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+ | ||
109 | */ | ||
110 | static void clear_ibs_nmi(void); | ||
111 | |||
112 | static int ibs_allowed; /* AMD Family10h and later */ | 109 | static int ibs_allowed; /* AMD Family10h and later */ |
113 | 110 | ||
114 | struct op_ibs_config { | 111 | struct op_ibs_config { |
@@ -223,7 +220,7 @@ op_amd_handle_ibs(struct pt_regs * const regs, | |||
223 | (unsigned int *)&ibs_fetch, | 220 | (unsigned int *)&ibs_fetch, |
224 | IBS_FETCH_BEGIN); | 221 | IBS_FETCH_BEGIN); |
225 | 222 | ||
226 | /*reenable the IRQ */ | 223 | /* reenable the IRQ */ |
227 | rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); | 224 | rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); |
228 | high &= ~IBS_FETCH_HIGH_VALID_BIT; | 225 | high &= ~IBS_FETCH_HIGH_VALID_BIT; |
229 | high |= IBS_FETCH_HIGH_ENABLE; | 226 | high |= IBS_FETCH_HIGH_ENABLE; |
@@ -331,8 +328,10 @@ static void op_amd_stop(struct op_msrs const * const msrs) | |||
331 | unsigned int low, high; | 328 | unsigned int low, high; |
332 | int i; | 329 | int i; |
333 | 330 | ||
334 | /* Subtle: stop on all counters to avoid race with | 331 | /* |
335 | * setting our pm callback */ | 332 | * Subtle: stop on all counters to avoid race with setting our |
333 | * pm callback | ||
334 | */ | ||
336 | for (i = 0 ; i < NUM_COUNTERS ; ++i) { | 335 | for (i = 0 ; i < NUM_COUNTERS ; ++i) { |
337 | if (!reset_value[i]) | 336 | if (!reset_value[i]) |
338 | continue; | 337 | continue; |
@@ -343,13 +342,15 @@ static void op_amd_stop(struct op_msrs const * const msrs) | |||
343 | 342 | ||
344 | #ifdef CONFIG_OPROFILE_IBS | 343 | #ifdef CONFIG_OPROFILE_IBS |
345 | if (ibs_allowed && ibs_config.fetch_enabled) { | 344 | if (ibs_allowed && ibs_config.fetch_enabled) { |
346 | low = 0; /* clear max count and enable */ | 345 | /* clear max count and enable */ |
346 | low = 0; | ||
347 | high = 0; | 347 | high = 0; |
348 | wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); | 348 | wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); |
349 | } | 349 | } |
350 | 350 | ||
351 | if (ibs_allowed && ibs_config.op_enabled) { | 351 | if (ibs_allowed && ibs_config.op_enabled) { |
352 | low = 0; /* clear max count and enable */ | 352 | /* clear max count and enable */ |
353 | low = 0; | ||
353 | high = 0; | 354 | high = 0; |
354 | wrmsr(MSR_AMD64_IBSOPCTL, low, high); | 355 | wrmsr(MSR_AMD64_IBSOPCTL, low, high); |
355 | } | 356 | } |
@@ -370,18 +371,7 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) | |||
370 | } | 371 | } |
371 | } | 372 | } |
372 | 373 | ||
373 | #ifndef CONFIG_OPROFILE_IBS | 374 | #ifdef CONFIG_OPROFILE_IBS |
374 | |||
375 | /* no IBS support */ | ||
376 | |||
377 | static int op_amd_init(struct oprofile_operations *ops) | ||
378 | { | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static void op_amd_exit(void) {} | ||
383 | |||
384 | #else | ||
385 | 375 | ||
386 | static u8 ibs_eilvt_off; | 376 | static u8 ibs_eilvt_off; |
387 | 377 | ||
@@ -395,7 +385,7 @@ static inline void apic_clear_ibs_nmi_per_cpu(void *arg) | |||
395 | setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); | 385 | setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); |
396 | } | 386 | } |
397 | 387 | ||
398 | static int pfm_amd64_setup_eilvt(void) | 388 | static int init_ibs_nmi(void) |
399 | { | 389 | { |
400 | #define IBSCTL_LVTOFFSETVAL (1 << 8) | 390 | #define IBSCTL_LVTOFFSETVAL (1 << 8) |
401 | #define IBSCTL 0x1cc | 391 | #define IBSCTL 0x1cc |
@@ -443,18 +433,22 @@ static int pfm_amd64_setup_eilvt(void) | |||
443 | return 0; | 433 | return 0; |
444 | } | 434 | } |
445 | 435 | ||
446 | /* | 436 | /* uninitialize the APIC for the IBS interrupts if needed */ |
447 | * initialize the APIC for the IBS interrupts | 437 | static void clear_ibs_nmi(void) |
448 | * if available (AMD Family10h rev B0 and later) | 438 | { |
449 | */ | 439 | if (ibs_allowed) |
450 | static void setup_ibs(void) | 440 | on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); |
441 | } | ||
442 | |||
443 | /* initialize the APIC for the IBS interrupts if available */ | ||
444 | static void ibs_init(void) | ||
451 | { | 445 | { |
452 | ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); | 446 | ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); |
453 | 447 | ||
454 | if (!ibs_allowed) | 448 | if (!ibs_allowed) |
455 | return; | 449 | return; |
456 | 450 | ||
457 | if (pfm_amd64_setup_eilvt()) { | 451 | if (init_ibs_nmi()) { |
458 | ibs_allowed = 0; | 452 | ibs_allowed = 0; |
459 | return; | 453 | return; |
460 | } | 454 | } |
@@ -462,14 +456,12 @@ static void setup_ibs(void) | |||
462 | printk(KERN_INFO "oprofile: AMD IBS detected\n"); | 456 | printk(KERN_INFO "oprofile: AMD IBS detected\n"); |
463 | } | 457 | } |
464 | 458 | ||
465 | 459 | static void ibs_exit(void) | |
466 | /* | ||
467 | * unitialize the APIC for the IBS interrupts if needed on AMD Family10h | ||
468 | * rev B0 and later */ | ||
469 | static void clear_ibs_nmi(void) | ||
470 | { | 460 | { |
471 | if (ibs_allowed) | 461 | if (!ibs_allowed) |
472 | on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); | 462 | return; |
463 | |||
464 | clear_ibs_nmi(); | ||
473 | } | 465 | } |
474 | 466 | ||
475 | static int (*create_arch_files)(struct super_block *sb, struct dentry *root); | 467 | static int (*create_arch_files)(struct super_block *sb, struct dentry *root); |
@@ -519,7 +511,7 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root) | |||
519 | 511 | ||
520 | static int op_amd_init(struct oprofile_operations *ops) | 512 | static int op_amd_init(struct oprofile_operations *ops) |
521 | { | 513 | { |
522 | setup_ibs(); | 514 | ibs_init(); |
523 | create_arch_files = ops->create_files; | 515 | create_arch_files = ops->create_files; |
524 | ops->create_files = setup_ibs_files; | 516 | ops->create_files = setup_ibs_files; |
525 | return 0; | 517 | return 0; |
@@ -527,10 +519,21 @@ static int op_amd_init(struct oprofile_operations *ops) | |||
527 | 519 | ||
528 | static void op_amd_exit(void) | 520 | static void op_amd_exit(void) |
529 | { | 521 | { |
530 | clear_ibs_nmi(); | 522 | ibs_exit(); |
531 | } | 523 | } |
532 | 524 | ||
533 | #endif | 525 | #else |
526 | |||
527 | /* no IBS support */ | ||
528 | |||
529 | static int op_amd_init(struct oprofile_operations *ops) | ||
530 | { | ||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static void op_amd_exit(void) {} | ||
535 | |||
536 | #endif /* CONFIG_OPROFILE_IBS */ | ||
534 | 537 | ||
535 | struct op_x86_model_spec const op_amd_spec = { | 538 | struct op_x86_model_spec const op_amd_spec = { |
536 | .init = op_amd_init, | 539 | .init = op_amd_init, |