diff options
author | Kan Liang <kan.liang@intel.com> | 2016-03-20 04:33:36 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-03-31 04:30:34 -0400 |
commit | e633c65a1d5859da170a83d537d9762c07d12213 (patch) | |
tree | 73310d311d977f374f23aab743f4a5baa50816d2 | |
parent | 84c48d8d01b74a2b98c164513ca5e37c73166825 (diff) |
x86/perf/intel/uncore: Make the Intel uncore PMU driver modular
By default, the uncore driver will be built into the kernel. If it is
configured as a module, the supported CPU model can be auto loaded.
This patch also cleans up the code of uncore_cpu_init() and
uncore_pci_init().
Based-on-a-patch-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Link: http://lkml.kernel.org/r/1458462817-2475-1-git-send-email-kan.liang@intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/Kconfig | 6 | ||||
-rw-r--r-- | arch/x86/Kconfig.perf | 11 | ||||
-rw-r--r-- | arch/x86/events/Makefile | 9 | ||||
-rw-r--r-- | arch/x86/events/intel/Makefile | 6 | ||||
-rw-r--r-- | arch/x86/events/intel/uncore.c | 216 |
5 files changed, 148 insertions, 100 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a313c0e7e165..496218b8236b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -160,10 +160,6 @@ config INSTRUCTION_DECODER | |||
160 | def_bool y | 160 | def_bool y |
161 | depends on KPROBES || PERF_EVENTS || UPROBES | 161 | depends on KPROBES || PERF_EVENTS || UPROBES |
162 | 162 | ||
163 | config PERF_EVENTS_INTEL_UNCORE | ||
164 | def_bool y | ||
165 | depends on PERF_EVENTS && CPU_SUP_INTEL && PCI | ||
166 | |||
167 | config OUTPUT_FORMAT | 163 | config OUTPUT_FORMAT |
168 | string | 164 | string |
169 | default "elf32-i386" if X86_32 | 165 | default "elf32-i386" if X86_32 |
@@ -1042,6 +1038,8 @@ config X86_THERMAL_VECTOR | |||
1042 | def_bool y | 1038 | def_bool y |
1043 | depends on X86_MCE_INTEL | 1039 | depends on X86_MCE_INTEL |
1044 | 1040 | ||
1041 | source "arch/x86/Kconfig.perf" | ||
1042 | |||
1045 | config X86_LEGACY_VM86 | 1043 | config X86_LEGACY_VM86 |
1046 | bool "Legacy VM86 support" | 1044 | bool "Legacy VM86 support" |
1047 | default n | 1045 | default n |
diff --git a/arch/x86/Kconfig.perf b/arch/x86/Kconfig.perf new file mode 100644 index 000000000000..90b7f5878c96 --- /dev/null +++ b/arch/x86/Kconfig.perf | |||
@@ -0,0 +1,11 @@ | |||
1 | menu "Performance monitoring" | ||
2 | |||
3 | config PERF_EVENTS_INTEL_UNCORE | ||
4 | tristate "Intel uncore performance events" | ||
5 | depends on PERF_EVENTS && CPU_SUP_INTEL && PCI | ||
6 | default y | ||
7 | ---help--- | ||
8 | Include support for Intel uncore performance events. These are | ||
9 | available on NehalemEX and more modern processors. | ||
10 | |||
11 | endmenu | ||
diff --git a/arch/x86/events/Makefile b/arch/x86/events/Makefile index f59618a39990..1d392c39fe56 100644 --- a/arch/x86/events/Makefile +++ b/arch/x86/events/Makefile | |||
@@ -6,9 +6,6 @@ obj-$(CONFIG_X86_LOCAL_APIC) += amd/ibs.o msr.o | |||
6 | ifdef CONFIG_AMD_IOMMU | 6 | ifdef CONFIG_AMD_IOMMU |
7 | obj-$(CONFIG_CPU_SUP_AMD) += amd/iommu.o | 7 | obj-$(CONFIG_CPU_SUP_AMD) += amd/iommu.o |
8 | endif | 8 | endif |
9 | obj-$(CONFIG_CPU_SUP_INTEL) += intel/core.o intel/bts.o intel/cqm.o | 9 | |
10 | obj-$(CONFIG_CPU_SUP_INTEL) += intel/cstate.o intel/ds.o intel/knc.o | 10 | obj-$(CONFIG_CPU_SUP_INTEL) += msr.o |
11 | obj-$(CONFIG_CPU_SUP_INTEL) += intel/lbr.o intel/p4.o intel/p6.o intel/pt.o | 11 | obj-$(CONFIG_CPU_SUP_INTEL) += intel/ |
12 | obj-$(CONFIG_CPU_SUP_INTEL) += intel/rapl.o msr.o | ||
13 | obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel/uncore.o intel/uncore_nhmex.o | ||
14 | obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel/uncore_snb.o intel/uncore_snbep.o | ||
diff --git a/arch/x86/events/intel/Makefile b/arch/x86/events/intel/Makefile new file mode 100644 index 000000000000..a6c744871a73 --- /dev/null +++ b/arch/x86/events/intel/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | obj-$(CONFIG_CPU_SUP_INTEL) += core.o bts.o cqm.o | ||
2 | obj-$(CONFIG_CPU_SUP_INTEL) += cstate.o ds.o knc.o | ||
3 | obj-$(CONFIG_CPU_SUP_INTEL) += lbr.o p4.o p6.o pt.o | ||
4 | obj-$(CONFIG_CPU_SUP_INTEL) += rapl.o | ||
5 | obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o | ||
6 | intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o | ||
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index 7012d18bb293..17734a6ef474 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <asm/cpu_device_id.h> | ||
1 | #include "uncore.h" | 2 | #include "uncore.h" |
2 | 3 | ||
3 | static struct intel_uncore_type *empty_uncore[] = { NULL, }; | 4 | static struct intel_uncore_type *empty_uncore[] = { NULL, }; |
@@ -21,6 +22,8 @@ static struct event_constraint uncore_constraint_fixed = | |||
21 | struct event_constraint uncore_constraint_empty = | 22 | struct event_constraint uncore_constraint_empty = |
22 | EVENT_CONSTRAINT(0, 0, 0); | 23 | EVENT_CONSTRAINT(0, 0, 0); |
23 | 24 | ||
25 | MODULE_LICENSE("GPL"); | ||
26 | |||
24 | static int uncore_pcibus_to_physid(struct pci_bus *bus) | 27 | static int uncore_pcibus_to_physid(struct pci_bus *bus) |
25 | { | 28 | { |
26 | struct pci2phy_map *map; | 29 | struct pci2phy_map *map; |
@@ -754,7 +757,7 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu) | |||
754 | pmu->registered = false; | 757 | pmu->registered = false; |
755 | } | 758 | } |
756 | 759 | ||
757 | static void __init __uncore_exit_boxes(struct intel_uncore_type *type, int cpu) | 760 | static void __uncore_exit_boxes(struct intel_uncore_type *type, int cpu) |
758 | { | 761 | { |
759 | struct intel_uncore_pmu *pmu = type->pmus; | 762 | struct intel_uncore_pmu *pmu = type->pmus; |
760 | struct intel_uncore_box *box; | 763 | struct intel_uncore_box *box; |
@@ -770,7 +773,7 @@ static void __init __uncore_exit_boxes(struct intel_uncore_type *type, int cpu) | |||
770 | } | 773 | } |
771 | } | 774 | } |
772 | 775 | ||
773 | static void __init uncore_exit_boxes(void *dummy) | 776 | static void uncore_exit_boxes(void *dummy) |
774 | { | 777 | { |
775 | struct intel_uncore_type **types; | 778 | struct intel_uncore_type **types; |
776 | 779 | ||
@@ -787,7 +790,7 @@ static void uncore_free_boxes(struct intel_uncore_pmu *pmu) | |||
787 | kfree(pmu->boxes); | 790 | kfree(pmu->boxes); |
788 | } | 791 | } |
789 | 792 | ||
790 | static void __init uncore_type_exit(struct intel_uncore_type *type) | 793 | static void uncore_type_exit(struct intel_uncore_type *type) |
791 | { | 794 | { |
792 | struct intel_uncore_pmu *pmu = type->pmus; | 795 | struct intel_uncore_pmu *pmu = type->pmus; |
793 | int i; | 796 | int i; |
@@ -804,7 +807,7 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) | |||
804 | type->events_group = NULL; | 807 | type->events_group = NULL; |
805 | } | 808 | } |
806 | 809 | ||
807 | static void __init uncore_types_exit(struct intel_uncore_type **types) | 810 | static void uncore_types_exit(struct intel_uncore_type **types) |
808 | { | 811 | { |
809 | for (; *types; types++) | 812 | for (; *types; types++) |
810 | uncore_type_exit(*types); | 813 | uncore_type_exit(*types); |
@@ -989,46 +992,6 @@ static int __init uncore_pci_init(void) | |||
989 | size_t size; | 992 | size_t size; |
990 | int ret; | 993 | int ret; |
991 | 994 | ||
992 | switch (boot_cpu_data.x86_model) { | ||
993 | case 45: /* Sandy Bridge-EP */ | ||
994 | ret = snbep_uncore_pci_init(); | ||
995 | break; | ||
996 | case 62: /* Ivy Bridge-EP */ | ||
997 | ret = ivbep_uncore_pci_init(); | ||
998 | break; | ||
999 | case 63: /* Haswell-EP */ | ||
1000 | ret = hswep_uncore_pci_init(); | ||
1001 | break; | ||
1002 | case 79: /* BDX-EP */ | ||
1003 | case 86: /* BDX-DE */ | ||
1004 | ret = bdx_uncore_pci_init(); | ||
1005 | break; | ||
1006 | case 42: /* Sandy Bridge */ | ||
1007 | ret = snb_uncore_pci_init(); | ||
1008 | break; | ||
1009 | case 58: /* Ivy Bridge */ | ||
1010 | ret = ivb_uncore_pci_init(); | ||
1011 | break; | ||
1012 | case 60: /* Haswell */ | ||
1013 | case 69: /* Haswell Celeron */ | ||
1014 | ret = hsw_uncore_pci_init(); | ||
1015 | break; | ||
1016 | case 61: /* Broadwell */ | ||
1017 | ret = bdw_uncore_pci_init(); | ||
1018 | break; | ||
1019 | case 87: /* Knights Landing */ | ||
1020 | ret = knl_uncore_pci_init(); | ||
1021 | break; | ||
1022 | case 94: /* SkyLake */ | ||
1023 | ret = skl_uncore_pci_init(); | ||
1024 | break; | ||
1025 | default: | ||
1026 | return -ENODEV; | ||
1027 | } | ||
1028 | |||
1029 | if (ret) | ||
1030 | return ret; | ||
1031 | |||
1032 | size = max_packages * sizeof(struct pci_extra_dev); | 995 | size = max_packages * sizeof(struct pci_extra_dev); |
1033 | uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL); | 996 | uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL); |
1034 | if (!uncore_extra_pci_dev) { | 997 | if (!uncore_extra_pci_dev) { |
@@ -1060,7 +1023,7 @@ err: | |||
1060 | return ret; | 1023 | return ret; |
1061 | } | 1024 | } |
1062 | 1025 | ||
1063 | static void __init uncore_pci_exit(void) | 1026 | static void uncore_pci_exit(void) |
1064 | { | 1027 | { |
1065 | if (pcidrv_registered) { | 1028 | if (pcidrv_registered) { |
1066 | pcidrv_registered = false; | 1029 | pcidrv_registered = false; |
@@ -1287,46 +1250,6 @@ static int __init uncore_cpu_init(void) | |||
1287 | { | 1250 | { |
1288 | int ret; | 1251 | int ret; |
1289 | 1252 | ||
1290 | switch (boot_cpu_data.x86_model) { | ||
1291 | case 26: /* Nehalem */ | ||
1292 | case 30: | ||
1293 | case 37: /* Westmere */ | ||
1294 | case 44: | ||
1295 | nhm_uncore_cpu_init(); | ||
1296 | break; | ||
1297 | case 42: /* Sandy Bridge */ | ||
1298 | case 58: /* Ivy Bridge */ | ||
1299 | case 60: /* Haswell */ | ||
1300 | case 69: /* Haswell */ | ||
1301 | case 70: /* Haswell */ | ||
1302 | case 61: /* Broadwell */ | ||
1303 | case 71: /* Broadwell */ | ||
1304 | snb_uncore_cpu_init(); | ||
1305 | break; | ||
1306 | case 45: /* Sandy Bridge-EP */ | ||
1307 | snbep_uncore_cpu_init(); | ||
1308 | break; | ||
1309 | case 46: /* Nehalem-EX */ | ||
1310 | case 47: /* Westmere-EX aka. Xeon E7 */ | ||
1311 | nhmex_uncore_cpu_init(); | ||
1312 | break; | ||
1313 | case 62: /* Ivy Bridge-EP */ | ||
1314 | ivbep_uncore_cpu_init(); | ||
1315 | break; | ||
1316 | case 63: /* Haswell-EP */ | ||
1317 | hswep_uncore_cpu_init(); | ||
1318 | break; | ||
1319 | case 79: /* BDX-EP */ | ||
1320 | case 86: /* BDX-DE */ | ||
1321 | bdx_uncore_cpu_init(); | ||
1322 | break; | ||
1323 | case 87: /* Knights Landing */ | ||
1324 | knl_uncore_cpu_init(); | ||
1325 | break; | ||
1326 | default: | ||
1327 | return -ENODEV; | ||
1328 | } | ||
1329 | |||
1330 | ret = uncore_types_init(uncore_msr_uncores, true); | 1253 | ret = uncore_types_init(uncore_msr_uncores, true); |
1331 | if (ret) | 1254 | if (ret) |
1332 | goto err; | 1255 | goto err; |
@@ -1376,11 +1299,105 @@ static int __init uncore_cpumask_init(bool msr) | |||
1376 | return 0; | 1299 | return 0; |
1377 | } | 1300 | } |
1378 | 1301 | ||
1302 | #define X86_UNCORE_MODEL_MATCH(model, init) \ | ||
1303 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init } | ||
1304 | |||
1305 | struct intel_uncore_init_fun { | ||
1306 | void (*cpu_init)(void); | ||
1307 | int (*pci_init)(void); | ||
1308 | }; | ||
1309 | |||
1310 | static const struct intel_uncore_init_fun nhm_uncore_init __initconst = { | ||
1311 | .cpu_init = nhm_uncore_cpu_init, | ||
1312 | }; | ||
1313 | |||
1314 | static const struct intel_uncore_init_fun snb_uncore_init __initconst = { | ||
1315 | .cpu_init = snb_uncore_cpu_init, | ||
1316 | .pci_init = snb_uncore_pci_init, | ||
1317 | }; | ||
1318 | |||
1319 | static const struct intel_uncore_init_fun ivb_uncore_init __initconst = { | ||
1320 | .cpu_init = snb_uncore_cpu_init, | ||
1321 | .pci_init = ivb_uncore_pci_init, | ||
1322 | }; | ||
1323 | |||
1324 | static const struct intel_uncore_init_fun hsw_uncore_init __initconst = { | ||
1325 | .cpu_init = snb_uncore_cpu_init, | ||
1326 | .pci_init = hsw_uncore_pci_init, | ||
1327 | }; | ||
1328 | |||
1329 | static const struct intel_uncore_init_fun bdw_uncore_init __initconst = { | ||
1330 | .cpu_init = snb_uncore_cpu_init, | ||
1331 | .pci_init = bdw_uncore_pci_init, | ||
1332 | }; | ||
1333 | |||
1334 | static const struct intel_uncore_init_fun snbep_uncore_init __initconst = { | ||
1335 | .cpu_init = snbep_uncore_cpu_init, | ||
1336 | .pci_init = snbep_uncore_pci_init, | ||
1337 | }; | ||
1338 | |||
1339 | static const struct intel_uncore_init_fun nhmex_uncore_init __initconst = { | ||
1340 | .cpu_init = nhmex_uncore_cpu_init, | ||
1341 | }; | ||
1342 | |||
1343 | static const struct intel_uncore_init_fun ivbep_uncore_init __initconst = { | ||
1344 | .cpu_init = ivbep_uncore_cpu_init, | ||
1345 | .pci_init = ivbep_uncore_pci_init, | ||
1346 | }; | ||
1347 | |||
1348 | static const struct intel_uncore_init_fun hswep_uncore_init __initconst = { | ||
1349 | .cpu_init = hswep_uncore_cpu_init, | ||
1350 | .pci_init = hswep_uncore_pci_init, | ||
1351 | }; | ||
1352 | |||
1353 | static const struct intel_uncore_init_fun bdx_uncore_init __initconst = { | ||
1354 | .cpu_init = bdx_uncore_cpu_init, | ||
1355 | .pci_init = bdx_uncore_pci_init, | ||
1356 | }; | ||
1357 | |||
1358 | static const struct intel_uncore_init_fun knl_uncore_init __initconst = { | ||
1359 | .cpu_init = knl_uncore_cpu_init, | ||
1360 | .pci_init = knl_uncore_pci_init, | ||
1361 | }; | ||
1362 | |||
1363 | static const struct intel_uncore_init_fun skl_uncore_init __initconst = { | ||
1364 | .pci_init = skl_uncore_pci_init, | ||
1365 | }; | ||
1366 | |||
1367 | static const struct x86_cpu_id intel_uncore_match[] __initconst = { | ||
1368 | X86_UNCORE_MODEL_MATCH(26, nhm_uncore_init), /* Nehalem */ | ||
1369 | X86_UNCORE_MODEL_MATCH(30, nhm_uncore_init), | ||
1370 | X86_UNCORE_MODEL_MATCH(37, nhm_uncore_init), /* Westmere */ | ||
1371 | X86_UNCORE_MODEL_MATCH(44, nhm_uncore_init), | ||
1372 | X86_UNCORE_MODEL_MATCH(42, snb_uncore_init), /* Sandy Bridge */ | ||
1373 | X86_UNCORE_MODEL_MATCH(58, ivb_uncore_init), /* Ivy Bridge */ | ||
1374 | X86_UNCORE_MODEL_MATCH(60, hsw_uncore_init), /* Haswell */ | ||
1375 | X86_UNCORE_MODEL_MATCH(69, hsw_uncore_init), /* Haswell Celeron */ | ||
1376 | X86_UNCORE_MODEL_MATCH(70, hsw_uncore_init), /* Haswell */ | ||
1377 | X86_UNCORE_MODEL_MATCH(61, bdw_uncore_init), /* Broadwell */ | ||
1378 | X86_UNCORE_MODEL_MATCH(71, bdw_uncore_init), /* Broadwell */ | ||
1379 | X86_UNCORE_MODEL_MATCH(45, snbep_uncore_init), /* Sandy Bridge-EP */ | ||
1380 | X86_UNCORE_MODEL_MATCH(46, nhmex_uncore_init), /* Nehalem-EX */ | ||
1381 | X86_UNCORE_MODEL_MATCH(47, nhmex_uncore_init), /* Westmere-EX aka. Xeon E7 */ | ||
1382 | X86_UNCORE_MODEL_MATCH(62, ivbep_uncore_init), /* Ivy Bridge-EP */ | ||
1383 | X86_UNCORE_MODEL_MATCH(63, hswep_uncore_init), /* Haswell-EP */ | ||
1384 | X86_UNCORE_MODEL_MATCH(79, bdx_uncore_init), /* BDX-EP */ | ||
1385 | X86_UNCORE_MODEL_MATCH(86, bdx_uncore_init), /* BDX-DE */ | ||
1386 | X86_UNCORE_MODEL_MATCH(87, knl_uncore_init), /* Knights Landing */ | ||
1387 | X86_UNCORE_MODEL_MATCH(94, skl_uncore_init), /* SkyLake */ | ||
1388 | {}, | ||
1389 | }; | ||
1390 | |||
1391 | MODULE_DEVICE_TABLE(x86cpu, intel_uncore_match); | ||
1392 | |||
1379 | static int __init intel_uncore_init(void) | 1393 | static int __init intel_uncore_init(void) |
1380 | { | 1394 | { |
1381 | int pret, cret, ret; | 1395 | const struct x86_cpu_id *id; |
1396 | struct intel_uncore_init_fun *uncore_init; | ||
1397 | int pret = 0, cret = 0, ret; | ||
1382 | 1398 | ||
1383 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) | 1399 | id = x86_match_cpu(intel_uncore_match); |
1400 | if (!id) | ||
1384 | return -ENODEV; | 1401 | return -ENODEV; |
1385 | 1402 | ||
1386 | if (cpu_has_hypervisor) | 1403 | if (cpu_has_hypervisor) |
@@ -1388,8 +1405,17 @@ static int __init intel_uncore_init(void) | |||
1388 | 1405 | ||
1389 | max_packages = topology_max_packages(); | 1406 | max_packages = topology_max_packages(); |
1390 | 1407 | ||
1391 | pret = uncore_pci_init(); | 1408 | uncore_init = (struct intel_uncore_init_fun *)id->driver_data; |
1392 | cret = uncore_cpu_init(); | 1409 | if (uncore_init->pci_init) { |
1410 | pret = uncore_init->pci_init(); | ||
1411 | if (!pret) | ||
1412 | pret = uncore_pci_init(); | ||
1413 | } | ||
1414 | |||
1415 | if (uncore_init->cpu_init) { | ||
1416 | uncore_init->cpu_init(); | ||
1417 | cret = uncore_cpu_init(); | ||
1418 | } | ||
1393 | 1419 | ||
1394 | if (cret && pret) | 1420 | if (cret && pret) |
1395 | return -ENODEV; | 1421 | return -ENODEV; |
@@ -1409,4 +1435,14 @@ err: | |||
1409 | cpu_notifier_register_done(); | 1435 | cpu_notifier_register_done(); |
1410 | return ret; | 1436 | return ret; |
1411 | } | 1437 | } |
1412 | device_initcall(intel_uncore_init); | 1438 | module_init(intel_uncore_init); |
1439 | |||
1440 | static void __exit intel_uncore_exit(void) | ||
1441 | { | ||
1442 | cpu_notifier_register_begin(); | ||
1443 | __unregister_cpu_notifier(&uncore_cpu_nb); | ||
1444 | uncore_types_exit(uncore_msr_uncores); | ||
1445 | uncore_pci_exit(); | ||
1446 | cpu_notifier_register_done(); | ||
1447 | } | ||
1448 | module_exit(intel_uncore_exit); | ||