|
23 | 23 | #include <linux/platform_device.h> |
24 | 24 | #include <linux/sched_clock.h> |
25 | 25 | #include <linux/smp.h> |
| 26 | +#include <linux/nmi.h> |
| 27 | +#include <linux/cpufreq.h> |
26 | 28 |
|
27 | 29 | /* ARMv8 Cortex-A53 specific event types. */ |
28 | 30 | #define ARMV8_A53_PERFCTR_PREF_LINEFILL 0xC2 |
@@ -1248,10 +1250,21 @@ static struct platform_driver armv8_pmu_driver = { |
1248 | 1250 |
|
1249 | 1251 | static int __init armv8_pmu_driver_init(void) |
1250 | 1252 | { |
| 1253 | + int ret; |
| 1254 | + |
1251 | 1255 | if (acpi_disabled) |
1252 | | - return platform_driver_register(&armv8_pmu_driver); |
| 1256 | + ret = platform_driver_register(&armv8_pmu_driver); |
1253 | 1257 | else |
1254 | | - return arm_pmu_acpi_probe(armv8_pmuv3_init); |
| 1258 | + ret = arm_pmu_acpi_probe(armv8_pmuv3_init); |
| 1259 | + |
| 1260 | + /* |
| 1261 | + * Try to re-initialize lockup detector after PMU init in |
| 1262 | + * case PMU events are triggered via NMIs. |
| 1263 | + */ |
| 1264 | + if (ret == 0 && arm_pmu_irq_is_nmi()) |
| 1265 | + lockup_detector_init(); |
| 1266 | + |
| 1267 | + return ret; |
1255 | 1268 | } |
1256 | 1269 | device_initcall(armv8_pmu_driver_init) |
1257 | 1270 |
|
@@ -1309,3 +1322,27 @@ void arch_perf_update_userpage(struct perf_event *event, |
1309 | 1322 | userpg->cap_user_time_zero = 1; |
1310 | 1323 | userpg->cap_user_time_short = 1; |
1311 | 1324 | } |
| 1325 | + |
| 1326 | +#ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF |
| 1327 | +/* |
| 1328 | + * Safe maximum CPU frequency in case a particular platform doesn't implement |
| 1329 | + * cpufreq driver. Although, architecture doesn't put any restrictions on |
| 1330 | + * maximum frequency but 5 GHz seems to be safe maximum given the available |
| 1331 | + * Arm CPUs in the market which are clocked much less than 5 GHz. On the other |
| 1332 | + * hand, we can't make it much higher as it would lead to a large hard-lockup |
| 1333 | + * detection timeout on parts which are running slower (eg. 1GHz on |
| 1334 | + * Developerbox) and doesn't possess a cpufreq driver. |
| 1335 | + */ |
| 1336 | +#define SAFE_MAX_CPU_FREQ 5000000000UL // 5 GHz |
| 1337 | +u64 hw_nmi_get_sample_period(int watchdog_thresh) |
| 1338 | +{ |
| 1339 | + unsigned int cpu = smp_processor_id(); |
| 1340 | + unsigned long max_cpu_freq; |
| 1341 | + |
| 1342 | + max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL; |
| 1343 | + if (!max_cpu_freq) |
| 1344 | + max_cpu_freq = SAFE_MAX_CPU_FREQ; |
| 1345 | + |
| 1346 | + return (u64)max_cpu_freq * watchdog_thresh; |
| 1347 | +} |
| 1348 | +#endif |
0 commit comments