From 81c661ab1e517996c6418b9d3d540ee7e92aae35 Mon Sep 17 00:00:00 2001 From: jharper5 Date: Tue, 16 Apr 2024 13:57:21 -0700 Subject: [PATCH 1/3] run without root permission --- perf-collect.py | 4 +++- src/perf_helpers.py | 28 +++++++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/perf-collect.py b/perf-collect.py index e3d95cb..9b04714 100644 --- a/perf-collect.py +++ b/perf-collect.py @@ -295,7 +295,9 @@ def validate_file(fname): sys.exit() if os.geteuid() != 0: - crash("Must run PerfSpect as root, please re-run") + logging.warning( + "PerfSpect requires elevated permissions to run. User is not root. Proceeding anyway..." + ) # disable nmi watchdog before collecting perf nmi_watchdog = perf_helpers.disable_nmi_watchdog() diff --git a/src/perf_helpers.py b/src/perf_helpers.py index c6d4456..e02dfe9 100644 --- a/src/perf_helpers.py +++ b/src/perf_helpers.py @@ -145,7 +145,9 @@ def disable_nmi_watchdog(): proc_output = subprocess.check_output(["cat", "/proc/sys/kernel/nmi_watchdog"]) nmi_watchdog_status = int(proc_output.decode().strip()) if nmi_watchdog_status == 1: - proc_output = subprocess.check_output(["sysctl", "kernel.nmi_watchdog=0"]) + proc_output = subprocess.check_output( + ["sysctl", "kernel.nmi_watchdog=0"], stderr=subprocess.STDOUT + ) new_watchdog_status = int( proc_output.decode().strip().replace("kernel.nmi_watchdog = ", "") ) @@ -158,7 +160,7 @@ def disable_nmi_watchdog(): logging.info("nmi_watchdog already disabled. No change needed.") return nmi_watchdog_status except (ValueError, FileNotFoundError, subprocess.CalledProcessError) as e: - crash(f"Failed to disable nmi_watchdog: {e}") + logging.warning(f"Failed to disable nmi_watchdog: {e}") # enable nmi watchdog @@ -183,15 +185,19 @@ def set_perf_event_mux_interval(reset, interval_ms, mux_interval): if os.path.isdir(dirpath): muxfile = os.path.join(dirpath, "perf_event_mux_interval_ms") if os.path.isfile(muxfile): - with open(muxfile, "w") as f_mux: - val = 0 - if reset: - val = int(mux_interval[f]) - else: - if int(mux_interval[f]): - val = int(interval_ms) - if val: - f_mux.write(str(val)) + try: + with open(muxfile, "w") as f_mux: + val = 0 + if reset: + val = int(mux_interval[f]) + else: + if int(mux_interval[f]): + val = int(interval_ms) + if val: + f_mux.write(str(val)) + except OSError as e: + logging.warning(f"Failed to write mux interval: {e}") + break # get linux kernel version From 956324fd71a1d94145866dfb59f868f482320241 Mon Sep 17 00:00:00 2001 From: jharper5 Date: Tue, 14 May 2024 07:06:33 -0700 Subject: [PATCH 2/3] improve TMA event support detection --- perf-collect.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/perf-collect.py b/perf-collect.py index 9b04714..bfc5430 100644 --- a/perf-collect.py +++ b/perf-collect.py @@ -161,6 +161,7 @@ def supports_psi(): def tma_supported(): perf_out = "" try: + # run perf stat briefly to determine if these two events are supported perf = subprocess.Popen( shlex.split( "perf stat -a -e '{cpu/event=0x00,umask=0x04,period=10000003,name='TOPDOWN.SLOTS'/,cpu/event=0x00,umask=0x81,period=10000003,name='PERF_METRICS.BAD_SPECULATION'/}' sleep .1" @@ -170,9 +171,11 @@ def tma_supported(): ) perf_out = perf.communicate()[0].decode() except subprocess.CalledProcessError: + logging.info("perf stat exited with error while checking for TMA support") return False try: + # create a dictionary of perf events and their counts from perf stat output events = { a.split()[1]: int(a.split()[0].replace(",", "")) for a in filter( @@ -181,10 +184,17 @@ def tma_supported(): ) } except Exception: + logging.info("error parsing perf stat output while checking for TMA support") return False # This is a perf artifact of no vPMU support if events["TOPDOWN.SLOTS"] == events["PERF_METRICS.BAD_SPECULATION"]: + logging.info("TOPDOWN.SLOTS and PERF_METRICS.BAD_SPECULATION counts are equal") + return False + + # A zero value on either of these metrics is an indication that the TMA events are not supported + if events["TOPDOWN.SLOTS"] == 0 or events["PERF_METRICS.BAD_SPECULATION"] == 0: + logging.info("TOPDOWN.SLOTS or PERF_METRICS.BAD_SPECULATION count is zero") return False return True From c5657320a283f8652efc09de2068845f9956afcd Mon Sep 17 00:00:00 2001 From: jharper5 Date: Tue, 14 May 2024 08:31:41 -0700 Subject: [PATCH 3/3] fix event filtering --- src/prepare_perf_events.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/prepare_perf_events.py b/src/prepare_perf_events.py index c236645..8daeba5 100644 --- a/src/prepare_perf_events.py +++ b/src/prepare_perf_events.py @@ -63,8 +63,8 @@ def is_cpu_event(line): if ( (len(tmp_list) == 1 or tmp_list[0] == "cpu" or tmp_list[0].startswith("cstate")) and "OCR." not in line - and "uops_retired.ms" not in line - and "int_misc.unknown_branch_cycles" not in line + and "uops_retired.ms" not in line.lower() + and "int_misc.unknown_branch_cycles" not in line.lower() and "power/" not in line ): return True