Signed-off-by: Barry Kasindorf <[EMAIL PROTECTED]>
Signed-off-by: Mark Langsdorf <[EMAIL PROTECTED]>
---
 nmi_int.c    |   43 +++++++++++++++++++++++++++++++++++++++++--
 op_counter.h |    9 +++++++++
 2 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 9510b08..f47b614 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -31,6 +31,7 @@ static void nmi_stop(void);

 /* 0 == registered but off, 1 == registered and on */
 static int nmi_enabled = 0;
+int ibs_allowed;       /* AMD Family 10h+ */

 #ifdef CONFIG_PM

@@ -214,6 +215,11 @@ static int nmi_setup(void)
                }

        }
+
+       /*setup AMD Family10h IBS irq if needed */
+       if (ibs_allowed)
+               setup_ibs_nmi();
+
        on_each_cpu(nmi_save_registers, NULL, 0, 1);
        on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
        nmi_enabled = 1;
@@ -270,6 +276,10 @@ static void nmi_shutdown(void)
        unregister_die_notifier(&profile_exceptions_nb);
        model->shutdown(cpu_msrs);
        free_msrs();
+
+       /*clear AMD Family 10h IBS irq if needed */
+       if (ibs_allowed)
+               clear_ibs_nmi();
 }

 static void nmi_cpu_start(void *dummy)
@@ -296,13 +306,15 @@ static void nmi_stop(void)
 }

 struct op_counter_config counter_config[OP_MAX_COUNTER];
+struct op_ibs_config ibs_config;

 static int nmi_create_files(struct super_block *sb, struct dentry *root)
 {
        unsigned int i;
+       struct dentry *dir;

        for (i = 0; i < model->num_counters; ++i) {
-               struct dentry *dir;
+
                char buf[4];

                /* quick little hack to _not_ expose a counter if it is not
@@ -323,6 +335,31 @@ static int nmi_create_files(struct super_block *sb, struct 
dentry *root)
                oprofilefs_create_ulong(sb, dir, "user", 
&counter_config[i].user);
        }

+       /* Setup AMD Family 10h IBS control if needed */
+       if (ibs_allowed) {
+               char buf[12];
+
+               /* setup some reasonable defaults */
+               ibs_config.max_cnt_fetch = 250000;
+               ibs_config.FETCH_enabled = 0;
+               ibs_config.max_cnt_op = 250000;
+               ibs_config.OP_enabled = 0;
+               snprintf(buf,  sizeof(buf), "ibs_fetch");
+               dir = oprofilefs_mkdir(sb, root, buf);
+               oprofilefs_create_ulong(sb, dir, "ran_enable",
+                                       &ibs_config.rand_en);
+               oprofilefs_create_ulong(sb, dir, "enable",
+                                       &ibs_config.FETCH_enabled);
+               oprofilefs_create_ulong(sb, dir, "max_count",
+                                       &ibs_config.max_cnt_fetch);
+               snprintf(buf,  sizeof(buf), "ibs_uops");
+               dir = oprofilefs_mkdir(sb, root, buf);
+               oprofilefs_create_ulong(sb, dir, "enable",
+                                       &ibs_config.OP_enabled);
+               oprofilefs_create_ulong(sb, dir, "max_count",
+                                       &ibs_config.max_cnt_op);
+       }
+
        return 0;
 }

@@ -391,6 +428,7 @@ int __init op_nmi_init(struct oprofile_operations *ops)
        __u8 vendor = boot_cpu_data.x86_vendor;
        __u8 family = boot_cpu_data.x86;
        char *cpu_type;
+       uint32_t eax, ebx, ecx, edx;

        if (!cpu_has_apic)
                return -ENODEV;
@@ -414,9 +452,17 @@ int __init op_nmi_init(struct oprofile_operations *ops)
                        break;
                case 0x10:
                        model = &op_athlon_spec;
-                       cpu_type = "x86-64/family10";
+                       cpu_type = "x86-64/family10h";
+                       /* This CPU has IBS capability */
+                       ibs_allowed = 1;
                        break;
                }
+               /* see if IBS is available */
+               if (family >= 0x10) {
+                       cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
+                       if (ecx & 0x40)
+                               ibs_allowed = 1;
+               }
                break;

        case X86_VENDOR_INTEL:
diff --git a/arch/x86/oprofile/op_counter.h b/arch/x86/oprofile/op_counter.h
index 2880b15..5681445 100644
--- a/arch/x86/oprofile/op_counter.h
+++ b/arch/x86/oprofile/op_counter.h
@@ -26,4 +26,13 @@ struct op_counter_config {

 extern struct op_counter_config counter_config[];

+struct op_ibs_config {
+       unsigned long OP_enabled;
+       unsigned long FETCH_enabled;
+       unsigned long max_cnt_fetch;
+       unsigned long max_cnt_op;
+       unsigned long rand_en;
+};
+
+extern struct op_ibs_config ibs_config;
 #endif /* OP_COUNTER_H */


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to