From 5cbf121240d4abf19e5ceb2918fcd35f5930b9f1 Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Thu, 21 May 2026 10:26:50 +0800 Subject: [PATCH 1/5] BM/PMU: add 9 ACR functional test cases Signed-off-by: Xudong Hao (cherry picked from commit 4f05a4a09fbbf2e8ffb7b8c8579e61a44c8459c1) --- BM/pmu/pmu_tests.sh | 209 ++++++++++++++++++++++++++++++++++++++++++-- BM/pmu/tests-cwf | 9 ++ BM/pmu/tests-dmr | 9 ++ 3 files changed, 222 insertions(+), 5 deletions(-) diff --git a/BM/pmu/pmu_tests.sh b/BM/pmu/pmu_tests.sh index 04bf48d4..ca22e8a1 100755 --- a/BM/pmu/pmu_tests.sh +++ b/BM/pmu/pmu_tests.sh @@ -20,8 +20,9 @@ source ../.env usage() { cat <<__EOF - usage: ./${0##*/} [-t TESTCASE_ID] [-H] + usage: ./${0##*/} [-t TESTCASE_ID] [-l LOOP_TIMES] [-H] -t TEST CASE ID + -l stress loop times, default 10 (for acr_stress) -H show this __EOF } @@ -482,7 +483,6 @@ rdpmc_user_disable() { local logfile4="temp4.log" #23H.00H:EBX[2]: RDPMC_USR_DISABLE do_cmd "cpuid_check 23 0 0 0 b 2" - [ $? -ne 0 ] && die "Platform does not support RDPMC USR DISABLE feature" rdpmc_attr=$1 echo $rdpmc_attr > /sys/devices/cpu/rdpmc @@ -497,8 +497,9 @@ rdpmc_user_disable() { 0) for file in $logfile1 $logfile2 $logfile3 $logfile4; do - cat $file | grep "Receive and handle #GP fault" - [ $? -eq 0 ] || die "rdpmc user disable test fail with rdpmc 0" + if ! cat $file | grep "Receive and handle #GP fault"; then + die "rdpmc user disable test fail with rdpmc 0" + fi clear_files $file done ;; @@ -528,6 +529,174 @@ rdpmc_user_disable() { esac } +# ACR (Auto Counter Reload) test functions +acr_detect_pmu() { + local pmu + for pmu in cpu cpu_core cpu_atom; do + if [[ -f /sys/devices/${pmu}/format/acr_mask ]]; then + ACR_PMU=$pmu + return 0 + fi + done + return 1 +} + +acr_cpuid_test() { + # 07H.01H:EAX[8] ArchPerfMonExt should be set first + do_cmd "cpuid_check 7 0 1 0 a 8" + # ACR CPUID + do_cmd "cpuid_check 23 0 0 0 a 2" +} + +acr_format_test() { + local cputype=$1 + if [[ -z $cputype ]]; then + acr_detect_pmu || die "No PMU exposes acr_mask, platform may not support ACR" + cputype=$ACR_PMU + fi + do_cmd "test -f /sys/devices/${cputype}/format/acr_mask" +} + +acr_basic_test() { + local cputype=$1 + local perfdata="acr_basic.data" + local logfile="acr_basic.log" + local scriptlog="acr_basic_script.log" + local cpunums="" + + if [[ -z $cputype ]]; then + acr_detect_pmu || die "No PMU exposes acr_mask, skip ACR basic" + cputype=$ACR_PMU + fi + + [[ $cputype != "cpu" ]] && cpunums=$(cat /sys/devices/${cputype}/cpus) + clear_files $perfdata $logfile $scriptlog + + if [[ -n $cpunums ]]; then + perf record -o $perfdata \ + -e "{${cputype}/instructions,period=200000,acr_mask=0x2/,${cputype}/cycles,period=100000,acr_mask=0x3/}" \ + -a taskset -c $cpunums sleep 1 >& $logfile + else + perf record -o $perfdata \ + -e "{${cputype}/instructions,period=200000,acr_mask=0x2/,${cputype}/cycles,period=100000,acr_mask=0x3/}" \ + -a sleep 1 >& $logfile + fi + + sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") + [[ -n $sample_count && $sample_count -gt 0 ]] || die "ACR basic: samples = 0!" + + perf script -i $perfdata > $scriptlog 2>&1 + instr_count=$(grep -c "instructions" $scriptlog) + cycles_count=$(grep -c "cycles" $scriptlog) + [[ $instr_count -gt 0 ]] || die "ACR basic: no instructions samples in perf script output!" + [[ $cycles_count -eq 0 ]] || die "ACR basic: cycles should not produce samples, found $cycles_count!" + + clear_files $perfdata $logfile $scriptlog +} + +acr_ratio_to_prev_test() { + local cputype=$1 + local perfdata="acr_ratio.data" + local logfile="acr_ratio.log" + local scriptlog="acr_ratio_script.log" + local cpunums="" + + if [[ -z $cputype ]]; then + acr_detect_pmu || die "No PMU exposes acr_mask, skip ratio-to-prev" + cputype=$ACR_PMU + fi + + [[ $cputype != "cpu" ]] && cpunums=$(cat /sys/devices/${cputype}/cpus) + clear_files $perfdata $logfile $scriptlog + + if [[ -n $cpunums ]]; then + perf record -o $perfdata \ + -e "{${cputype}/instructions/,${cputype}/cycles,period=100000,ratio-to-prev=0.5/}" \ + -a taskset -c $cpunums sleep 1 >& $logfile + else + perf record -o $perfdata \ + -e "{${cputype}/instructions/,${cputype}/cycles,period=100000,ratio-to-prev=0.5/}" \ + -a sleep 1 >& $logfile + fi + + sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") + [[ -n $sample_count && $sample_count -gt 0 ]] || die "ACR ratio-to-prev: samples = 0!" + + perf script -i $perfdata > $scriptlog 2>&1 + instr_count=$(grep -c "instructions" $scriptlog) + cycles_count=$(grep -c "cycles" $scriptlog) + [[ $instr_count -gt 0 ]] || die "ACR ratio-to-prev: no instructions samples in perf script output!" + [[ $cycles_count -eq 0 ]] || die "ACR ratio-to-prev: cycles should not produce samples, found $cycles_count!" + + clear_files $perfdata $logfile $scriptlog +} + +acr_stat_test() { + local cputype=$1 + local logfile="acr_stat.log" + + if [[ -z $cputype ]]; then + acr_detect_pmu || die "No PMU exposes acr_mask, skip ACR stat" + cputype=$ACR_PMU + fi + + clear_files $logfile + perf stat -e "{${cputype}/instructions,period=200000,acr_mask=0x2/,${cputype}/cycles,period=100000,acr_mask=0x3/}" \ + -a sleep 1 >& $logfile + clear_files $logfile +} + +acr_reject_freq_test() { + local cputype + acr_detect_pmu || die "No PMU exposes acr_mask, skip ACR reject freq" + cputype=$ACR_PMU + + should_fail "perf record -o /dev/null -e '{${cputype}/instructions,acr_mask=0x2/,${cputype}/cycles,acr_mask=0x3/}' -F 1000 -a true 2>/dev/null" +} + +acr_reject_ppp_test() { + local cputype + acr_detect_pmu || die "No PMU exposes acr_mask, skip ACR reject ppp" + cputype=$ACR_PMU + + should_fail "perf record -o /dev/null -e '{${cputype}/instructions,period=200000,acr_mask=0x2/ppp,${cputype}/cycles,period=100000,acr_mask=0x3/}' -a true 2>/dev/null" +} + +acr_reject_contiguity_test() { + local cputype + acr_detect_pmu || die "No PMU exposes acr_mask, skip ACR reject contiguity" + cputype=$ACR_PMU + + should_fail "perf record -o /dev/null -e '{${cputype}/instructions,period=200000,acr_mask=0x2/,dummy,${cputype}/cycles,period=100000,acr_mask=0x3/}' -a true 2>/dev/null" +} + +acr_stress_test() { + local cputype=$1 + : "${STRESS_TIMES:=10}" + for ((i = 0; i < STRESS_TIMES; i++)); do + acr_basic_test "$cputype" + acr_ratio_to_prev_test "$cputype" + acr_stat_test "$cputype" + done +} + +acr_run_on_supported_pmus() { + local fn=$1 + local has_hybrid=0 + + if [[ -f /sys/devices/cpu_atom/format/acr_mask ]]; then + has_hybrid=1 + $fn "cpu_atom" + fi + if [[ -f /sys/devices/cpu_core/format/acr_mask ]]; then + has_hybrid=1 + $fn "cpu_core" + fi + + [[ $has_hybrid -eq 1 ]] && return 0 + $fn +} + pmu_test() { case $TEST_SCENARIO in fix_counter) @@ -611,15 +780,45 @@ pmu_test() { rdpmc_user_disable_2) rdpmc_user_disable 2 ;; + acr_cpuid) + acr_cpuid_test + ;; + acr_format) + acr_run_on_supported_pmus acr_format_test + ;; + acr_basic) + acr_run_on_supported_pmus acr_basic_test + ;; + acr_ratio_to_prev) + acr_run_on_supported_pmus acr_ratio_to_prev_test + ;; + acr_stat) + acr_run_on_supported_pmus acr_stat_test + ;; + acr_reject_freq) + acr_reject_freq_test + ;; + acr_reject_ppp) + acr_reject_ppp_test + ;; + acr_reject_contiguity) + acr_reject_contiguity_test + ;; + acr_stress) + acr_run_on_supported_pmus acr_stress_test + ;; esac return 0 } -while getopts :t:H arg; do +while getopts :t:l:H arg; do case $arg in t) TEST_SCENARIO=$OPTARG ;; + l) + STRESS_TIMES=$OPTARG + ;; H) usage && exit 0 ;; diff --git a/BM/pmu/tests-cwf b/BM/pmu/tests-cwf index 2cfa0f1a..95158214 100644 --- a/BM/pmu/tests-cwf +++ b/BM/pmu/tests-cwf @@ -42,3 +42,12 @@ pmu_tests.sh -t counting pmu_tests.sh -t sampling pmu_tests.sh -t counting_multi pmu_cstate_tests.sh -t cstate_event_list +pmu_tests.sh -t acr_cpuid +pmu_tests.sh -t acr_format +pmu_tests.sh -t acr_basic +pmu_tests.sh -t acr_ratio_to_prev +pmu_tests.sh -t acr_stat +pmu_tests.sh -t acr_reject_freq +pmu_tests.sh -t acr_reject_ppp +pmu_tests.sh -t acr_reject_contiguity +pmu_tests.sh -t acr_stress -l 10 diff --git a/BM/pmu/tests-dmr b/BM/pmu/tests-dmr index d9ff9fa9..762293e5 100644 --- a/BM/pmu/tests-dmr +++ b/BM/pmu/tests-dmr @@ -37,3 +37,12 @@ pmu_tests.sh -t rdpmc_user_disable_0 pmu_tests.sh -t rdpmc_user_disable_1 pmu_tests.sh -t rdpmc_user_disable_2 pmu_cstate_tests.sh -t cstate_event_list +pmu_tests.sh -t acr_cpuid +pmu_tests.sh -t acr_format +pmu_tests.sh -t acr_basic +pmu_tests.sh -t acr_ratio_to_prev +pmu_tests.sh -t acr_stat +pmu_tests.sh -t acr_reject_freq +pmu_tests.sh -t acr_reject_ppp +pmu_tests.sh -t acr_reject_contiguity +pmu_tests.sh -t acr_stress -l 10 From 386adf08fc34158ede63eb3a9246477a5d93410e Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Tue, 9 Jun 2026 13:57:38 +0800 Subject: [PATCH 2/5] BM/PMU: remove arch_pebs_counter_group_stress from DMR list arch_pebs_counter_group_stress test case need 6 fixed counters which is only supported on CWF. Signed-off-by: Xudong Hao (cherry picked from commit 6b4da2117e71510caa5813ca4439b0692ea3a779) --- BM/pmu/pmu_tests.sh | 4 ++-- BM/pmu/tests-dmr | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/BM/pmu/pmu_tests.sh b/BM/pmu/pmu_tests.sh index ca22e8a1..a1196a73 100755 --- a/BM/pmu/pmu_tests.sh +++ b/BM/pmu/pmu_tests.sh @@ -282,7 +282,7 @@ arch_pebs_counter_group_stress_test() { logfile="temp.txt" #because nmi_watchdog will occupy one fix counter, so disable it echo 0 > /proc/sys/kernel/nmi_watchdog - event="{branches,branches,branches,branches,branches,branches,branches,branches,cycles,instructions,ref-cycles,topdown-bad-spec,topdown-fe-bound,topdown-retiring" + event="{branches,branches,branches,branches,branches,branches,branches,branches,cycles,instructions,ref-cycles,topdown-bad-spec,topdown-fe-bound,topdown-retiring}" perf record -o $perfdata -e "$event:p" -a -- sleep 1 2>&1|tee $logfile sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") count=$(perf report -D -i $perfdata| grep -c "PERF_RECORD_SAMPLE") @@ -738,7 +738,7 @@ pmu_test() { arch_pebs_counter_group) arch_pebs_counter_group_test ;; - arch_pebs_counter_group_stres) + arch_pebs_counter_group_stress) arch_pebs_counter_group_stress_test ;; arch_pebs_gp_counter) diff --git a/BM/pmu/tests-dmr b/BM/pmu/tests-dmr index 762293e5..3c239c15 100644 --- a/BM/pmu/tests-dmr +++ b/BM/pmu/tests-dmr @@ -30,7 +30,6 @@ pmu_tests.sh -t arch_pebs_cpuid pmu_tests.sh -t arch_pebs_gp_reg_group pmu_tests.sh -t arch_pebs_xer_group pmu_tests.sh -t arch_pebs_counter_group -pmu_tests.sh -t arch_pebs_counter_group_stress pmu_tests.sh -t arch_pebs_gp_counter pmu_tests.sh -t arch_pebs_basic_group pmu_tests.sh -t rdpmc_user_disable_0 From c654559d2952123bd0aae4af188e898013786214 Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Tue, 9 Jun 2026 14:39:06 +0800 Subject: [PATCH 3/5] BM/PMU: Fix false negative issue for TOPDOWN event Signed-off-by: Xudong Hao (cherry picked from commit 6b34523db8b146fdfeb7ba11b9a6e6daea7bfd28) --- BM/pmu/pmu_tests.sh | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/BM/pmu/pmu_tests.sh b/BM/pmu/pmu_tests.sh index a1196a73..26fe63dd 100755 --- a/BM/pmu/pmu_tests.sh +++ b/BM/pmu/pmu_tests.sh @@ -267,8 +267,8 @@ arch_pebs_counter_group_test() { sample_count=$(grep "sample" $logfile_s | awk '{print $10}' | tr -cd "0-9") #[[ $sample_count -eq 0 ]] && die "samples = 0!" if [[ $sample_count -eq 0 ]]; then - die "samples = 0!" clear_files $logfile $perfdata $perfdata_s $logfile_s + die "samples = 0!" fi sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") count=$(perf report -D -i $perfdata| grep -c "PERF_RECORD_SAMPLE") @@ -284,6 +284,10 @@ arch_pebs_counter_group_stress_test() { echo 0 > /proc/sys/kernel/nmi_watchdog event="{branches,branches,branches,branches,branches,branches,branches,branches,cycles,instructions,ref-cycles,topdown-bad-spec,topdown-fe-bound,topdown-retiring}" perf record -o $perfdata -e "$event:p" -a -- sleep 1 2>&1|tee $logfile + if grep "Error" $logfile > /dev/null; then + clear_files $logfile $perfdata + die "Sampling some events failed!" + fi sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") count=$(perf report -D -i $perfdata| grep -c "PERF_RECORD_SAMPLE") clear_files $logfile $perfdata @@ -384,25 +388,25 @@ sampling_test() { perf_log="perf.log" clear_files $perf_log do_cmd "perf record -o $perfdata -e $e_topdown_bad_spec $benchmark >& $perf_log" - samples=$(grep "sample" $perf_log | awk '{print $10}' | tr -cd "0-9") + samples=$(perf report -D -i perf.data |grep -A 1 $e_topdown_bad_spec |grep -i "sample" | awk '{print $3}' | tr -cd "0-9") clear_files $perf_log $perfdata test_print_trc "$e_topdown_bad_spec sample = $samples" [[ $samples -eq 0 ]] && die "samples = 0 for $e_topdown_bad_spec!" do_cmd "perf record -o $perfdata -e $e_topdown_fe_bound $benchmark >& $perf_log" - samples=$(grep "sample" $perf_log | awk '{print $10}' | tr -cd "0-9") + samples=$(perf report -D -i perf.data |grep -A 1 $e_topdown_fe_bound |grep -i "sample" | awk '{print $3}' | tr -cd "0-9") clear_files $perf_log $perfdata test_print_trc "$e_topdown_fe_bound sample = $samples" [[ $samples -eq 0 ]] && die "samples = 0 for $e_topdown_fe_bound!" do_cmd "perf record -o $perfdata -e $e_topdown_retiring $benchmark >& $perf_log" - samples=$(grep "sample" $perf_log | awk '{print $10}' | tr -cd "0-9") + samples=$(perf report -D -i perf.data |grep -A 1 $e_topdown_retiring |grep -i "sample" | awk '{print $3}' | tr -cd "0-9") clear_files $perf_log $perfdata test_print_trc "$e_topdown_retiring sample = $samples" [[ $samples -eq 0 ]] && die "samples = 0 for $e_topdown_retiring!" do_cmd "perf record -o $perfdata -e $e_topdown_be_bound $benchmark >& $perf_log" - samples=$(grep "sample" $perf_log | awk '{print $10}' | tr -cd "0-9") + samples=$(perf report -D -i perf.data |grep -A 1 $e_topdown_be_bound |grep -i "sample" | awk '{print $3}' | tr -cd "0-9") clear_files $perf_log $perfdata test_print_trc "$e_topdown_be_bound sample = $samples" [[ $samples -eq 0 ]] && die "samples = 0 for $e_topdown_be_bound!" From 4ff8a0c0925c273c126da5d23bb9d83e253407a2 Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Wed, 22 Jul 2026 23:07:03 -0400 Subject: [PATCH 4/5] BM/PMU apebs: add GPR, GP counter, Fixed counter tests and extend XMM/IP test - pebs_gpr_test: dynamic GPR register sampling via perf record -I, excludes SSP - pebs_gp_counter_test: GP counter PEBS sampling with branches:p/P event - pebs_fixed_counter_test: fixed counter PEBS sampling with instructions:p/P event - adaptive_pebs_msr_test: check platform MSR support adaptive PEBS - update XMM test to extend all XMM registers dynamically - update ip_test to verify eventing IP correctness Signed-off-by: Xudong Hao (cherry picked from commit 53a8b98141d162a7c3d2c4bf3a38e569b0e42df4) --- BM/pmu/apebs_tests.sh | 139 +++++++++++++++++++++++++++++++++---- BM/pmu/tests | 7 ++ BM/pmu/tests-adaptive_pebs | 28 ++++++++ BM/pmu/tests-cwf | 12 ++++ BM/pmu/tests-dmr | 12 ++++ BM/pmu/tests-gnr | 13 ++++ 6 files changed, 196 insertions(+), 15 deletions(-) create mode 100644 BM/pmu/tests-adaptive_pebs diff --git a/BM/pmu/apebs_tests.sh b/BM/pmu/apebs_tests.sh index ae74ce8c..6369dbfd 100755 --- a/BM/pmu/apebs_tests.sh +++ b/BM/pmu/apebs_tests.sh @@ -45,26 +45,66 @@ lbr_test() { [[ $sample_count -eq $count ]] || die "samples does not match!" } +pebs_event_test() { + local event_name=$1 + local level=$2 + perfdata="pebs.data" + logfile="temp.txt" + clear_files $perfdata $logfile + event="${event_name}:$level" + benchmark="sleep 1" + perf record -o "$perfdata" -e "$event" -a $benchmark 2>&1|tee "$logfile" + sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") + count=$(perf report -D -i $perfdata | grep -A 1 "$event_name" | grep "SAMPLE events" | awk '{print $3}') + clear_files $perfdata $logfile + test_print_trc "sample_count = $sample_count; count = $count" + [[ $sample_count -eq 0 ]] && die "samples = 0!" + [[ $sample_count -eq $count ]] || die "samples does not match!" +} + +pebs_gp_counter_test() { + pebs_event_test "branches" "$1" +} + +pebs_fixed_counter_test() { + pebs_event_test "instructions" "$1" +} + +adaptive_pebs_msr_test() { + # MSR_IA32_PERF_CAPABILITIES(0x345) bit 14 indicates adaptive PEBS support. + bit_14=$(rdmsr 0x345 -f 14:14) + test_print_trc "MSR IA32_PERF_CAPABILITIES(0x345) bit 14 is: $bit_14" + [[ $bit_14 -eq 1 ]] || die "Adaptive PEBS msr bit is not set!" +} + xmm_test() { level=$1 perfdata="pebs.data" logfile="temp.txt" simdfile="simd.txt" local reg_type=0 + local xmm_arg="" + local xmm_count=0 perf record -I? 2>&1|tee $simdfile grep 'XMM0-15' $simdfile > /dev/null && reg_type=0 grep 'XMM0 XMM1' $simdfile > /dev/null && reg_type=1 if [[ $reg_type -eq 0 ]]; then - xmm_reg="XMM" + xmm_arg="XMM" mul=$((2 * 16)) elif [[ $reg_type -eq 1 ]]; then - xmm_reg="XMM0" - mul=2 + xmm_arg=$(tr ' ,:()' '\n' < $simdfile | awk ' + { tok=toupper($0) } + tok ~ /^XMM[0-9]+$/ && !seen[tok]++ { list = list ? list "," tok : tok } + END { print list } + ') + xmm_count=$(echo "$xmm_arg" | tr ',' '\n' | wc -l) + mul=$((2 * xmm_count)) fi - - perf record -o $perfdata -I${xmm_reg} -e cycles:"$level" -a sleep 1 2>&1|tee $logfile + + test_print_trc "XMM arg: $xmm_arg, mul: $mul" + perf record -o $perfdata -I${xmm_arg} -e cycles:"$level" -C 0 sleep 1 2>&1|tee $logfile sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") - count=$(perf report -D -i $perfdata| grep -c "${xmm_reg}") + count=$(perf report -D -i $perfdata| grep -c "XMM") clear_files $perfdata $logfile $simdfile test_print_trc "before sample_count = $sample_count; count = $count" sample_count=$((sample_count * mul)) @@ -73,22 +113,70 @@ xmm_test() { [[ $sample_count -eq $count ]] || die "samples does not match!" } +pebs_gpr_test() { + level=$1 + perfdata="pebs.data" + logfile="temp.txt" + regfile="reg.txt" + reportfile="report.txt" + gpr_regs=() + gpr_csv="" + clear_files $perfdata $logfile $regfile $reportfile + + event="cycles:$level" + benchmark="sleep 1" + + perf record -I? 2>&1|tee "$regfile" + gpr_csv=$(tr ' ,:()' '\n' < $regfile | awk ' + { + tok=toupper($0) + if (tok == "" || tok == "SSP") + next + if (tok ~ /^(R[0-9]+|[ABCD]X|[SD]I|BP|SP|IP|FLAGS|[CDEFGS]S)$/ && !seen[tok]++) + list = list ? list "," tok : tok + } + END { print list } + ') + + [ -z "$gpr_csv" ] && die "The system doesn't expose supported GPR registers in perf -I? output!" + IFS=',' read -r -a gpr_regs <<< "$gpr_csv" + test_print_trc "Detected GPR list: $gpr_csv" + + perf record -o "$perfdata" -I"${gpr_csv}" -e "$event" -C 0 $benchmark 2>&1|tee "$logfile" + sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") + perf report -D -i "$perfdata" > "$reportfile" + count=0 + for reg in "${gpr_regs[@]}"; do + reg_count=$(grep -v events "$reportfile" | grep -c "\. ${reg} ") + count=$((count + reg_count)) + done + gpr_total=${#gpr_regs[@]} + test_print_trc "sample_count = $sample_count; gpr_total = $gpr_total; count = $count" + sample_count=$((sample_count * gpr_total)) + test_print_trc "expected_gpr_records = $sample_count" + clear_files $perfdata $logfile $regfile $reportfile + [[ $sample_count -eq 0 ]] && die "samples = 0!" + [[ $sample_count -eq $count ]] || die "samples does not match!" +} + ip_test() { level=$1 perfdata="pebs.data" logfile="temp.txt" - task="mem-loads" - model=$(grep model /proc/cpuinfo | awk '{print $3}' | head -1) - [[ $model -eq 150 ]] && task="cycles" - [[ $model -eq 156 ]] && task="cycles" - test_print_trc "task=$task" - perf mem record -o "$perfdata" -t load -a sleep 1 2> "$logfile" + clear_files $perfdata $logfile + + event="cycles:$level" + benchmark="sleep 1" + + perf record -o "$perfdata" -e "$event" -a $benchmark 2>&1|tee "$logfile" sample_count=$(grep "sample" $logfile | awk '{print $10}' | tr -cd "0-9") - count=$(perf report -D -i $perfdata| grep -c "data_src") + ip_count=$(perf script -i "$perfdata" -F ip | awk '$1 ~ /^[0-9a-fA-F]+$/ {c++} END {print c+0}') + nonzero_ip_count=$(perf script -i "$perfdata" -F ip | awk '$1 ~ /^[0-9a-fA-F]+$/ && $1 != "0" && $1 != "0000000000000000" {c++} END {print c+0}') clear_files $perfdata $logfile - test_print_trc "sample_count = $sample_count; count = $count" + test_print_trc "sample_count = $sample_count; ip_count = $ip_count; nonzero_ip_count = $nonzero_ip_count" [[ $sample_count -eq 0 ]] && die "samples = 0!" - [[ $sample_count -eq $count ]] || die "samples does not match!" + [[ $sample_count -eq $ip_count ]] || die "sample count does not match EventingIP count!" + [[ $ip_count -eq $nonzero_ip_count ]] || die "zero EventingIP was found in samples!" } data_src_test() { @@ -123,6 +211,27 @@ apebs_test() { xmm_2) xmm_test P ;; + gpr_1) + pebs_gpr_test p + ;; + gpr_2) + pebs_gpr_test P + ;; + gp_counter_1) + pebs_gp_counter_test p + ;; + gp_counter_2) + pebs_gp_counter_test P + ;; + fixed_counter_1) + pebs_fixed_counter_test p + ;; + fixed_counter_2) + pebs_fixed_counter_test P + ;; + adaptive_pebs_msr) + adaptive_pebs_msr_test + ;; ip_1) ip_test p ;; diff --git a/BM/pmu/tests b/BM/pmu/tests index a27587ce..d5f45702 100644 --- a/BM/pmu/tests +++ b/BM/pmu/tests @@ -5,6 +5,13 @@ apebs_tests.sh -t lbr_1 -w 1 apebs_tests.sh -t lbr_2 -w 1 apebs_tests.sh -t xmm_1 -w 1 apebs_tests.sh -t xmm_2 -w 1 +apebs_tests.sh -t gpr_1 -w 1 +apebs_tests.sh -t gpr_2 -w 1 +apebs_tests.sh -t gp_counter_1 -w 1 +apebs_tests.sh -t gp_counter_2 -w 1 +apebs_tests.sh -t fixed_counter_1 -w 1 +apebs_tests.sh -t fixed_counter_2 -w 1 +apebs_tests.sh -t adaptive_pebs_msr -w 0 apebs_tests.sh -t ip_1 -w 1 apebs_tests.sh -t ip_2 -w 1 apebs_tests.sh -t data_src -w 1 diff --git a/BM/pmu/tests-adaptive_pebs b/BM/pmu/tests-adaptive_pebs new file mode 100644 index 00000000..1cc8cc6e --- /dev/null +++ b/BM/pmu/tests-adaptive_pebs @@ -0,0 +1,28 @@ +# This file collects all adaptive PEBS test cases +apebs_tests.sh -t adaptive_pebs_msr -w 0 +apebs_tests.sh -t data_src -w 0 +apebs_tests.sh -t data_src -w 1 +apebs_tests.sh -t fixed_counter_1 -w 0 +apebs_tests.sh -t fixed_counter_1 -w 1 +apebs_tests.sh -t fixed_counter_2 -w 0 +apebs_tests.sh -t fixed_counter_2 -w 1 +apebs_tests.sh -t gp_counter_1 -w 0 +apebs_tests.sh -t gp_counter_1 -w 1 +apebs_tests.sh -t gp_counter_2 -w 0 +apebs_tests.sh -t gp_counter_2 -w 1 +apebs_tests.sh -t gpr_1 -w 0 +apebs_tests.sh -t gpr_1 -w 1 +apebs_tests.sh -t gpr_2 -w 0 +apebs_tests.sh -t gpr_2 -w 1 +apebs_tests.sh -t ip_1 -w 0 +apebs_tests.sh -t ip_1 -w 1 +apebs_tests.sh -t ip_2 -w 0 +apebs_tests.sh -t ip_2 -w 1 +apebs_tests.sh -t large_pebs -w 0 +apebs_tests.sh -t large_pebs -w 1 +apebs_tests.sh -t lbr_1 -w 0 +apebs_tests.sh -t lbr_1 -w 1 +apebs_tests.sh -t lbr_2 -w 0 +apebs_tests.sh -t lbr_2 -w 1 +apebs_tests.sh -t xmm_1 -w 1 +apebs_tests.sh -t xmm_2 -w 1 diff --git a/BM/pmu/tests-cwf b/BM/pmu/tests-cwf index 95158214..8c9b9494 100644 --- a/BM/pmu/tests-cwf +++ b/BM/pmu/tests-cwf @@ -10,10 +10,22 @@ apebs_tests.sh -t ip_1 -w 0 apebs_tests.sh -t ip_2 -w 0 apebs_tests.sh -t lbr_1 -w 0 apebs_tests.sh -t lbr_2 -w 0 +apebs_tests.sh -t gpr_1 -w 0 +apebs_tests.sh -t gpr_2 -w 0 +apebs_tests.sh -t gp_counter_1 -w 0 +apebs_tests.sh -t gp_counter_2 -w 0 +apebs_tests.sh -t fixed_counter_1 -w 0 +apebs_tests.sh -t fixed_counter_2 -w 0 apebs_tests.sh -t large_pebs -w 0 apebs_tests.sh -t large_pebs -w 1 apebs_tests.sh -t xmm_1 -w 1 apebs_tests.sh -t xmm_2 -w 1 +apebs_tests.sh -t gpr_1 -w 1 +apebs_tests.sh -t gpr_2 -w 1 +apebs_tests.sh -t gp_counter_1 -w 1 +apebs_tests.sh -t gp_counter_2 -w 1 +apebs_tests.sh -t fixed_counter_1 -w 1 +apebs_tests.sh -t fixed_counter_2 -w 1 apebs_tests.sh -t ip_1 -w 1 apebs_tests.sh -t ip_2 -w 1 apebs_tests.sh -t data_src -w 1 diff --git a/BM/pmu/tests-dmr b/BM/pmu/tests-dmr index 3c239c15..e1ad9bc2 100644 --- a/BM/pmu/tests-dmr +++ b/BM/pmu/tests-dmr @@ -10,10 +10,22 @@ apebs_tests.sh -t ip_1 -w 0 apebs_tests.sh -t ip_2 -w 0 apebs_tests.sh -t lbr_1 -w 0 apebs_tests.sh -t lbr_2 -w 0 +apebs_tests.sh -t gpr_1 -w 0 +apebs_tests.sh -t gpr_2 -w 0 +apebs_tests.sh -t gp_counter_1 -w 0 +apebs_tests.sh -t gp_counter_2 -w 0 +apebs_tests.sh -t fixed_counter_1 -w 0 +apebs_tests.sh -t fixed_counter_2 -w 0 apebs_tests.sh -t large_pebs -w 0 apebs_tests.sh -t large_pebs -w 1 apebs_tests.sh -t xmm_1 -w 1 apebs_tests.sh -t xmm_2 -w 1 +apebs_tests.sh -t gpr_1 -w 1 +apebs_tests.sh -t gpr_2 -w 1 +apebs_tests.sh -t gp_counter_1 -w 1 +apebs_tests.sh -t gp_counter_2 -w 1 +apebs_tests.sh -t fixed_counter_1 -w 1 +apebs_tests.sh -t fixed_counter_2 -w 1 apebs_tests.sh -t ip_1 -w 1 apebs_tests.sh -t ip_2 -w 1 apebs_tests.sh -t data_src -w 1 diff --git a/BM/pmu/tests-gnr b/BM/pmu/tests-gnr index b14d6bec..0636003a 100644 --- a/BM/pmu/tests-gnr +++ b/BM/pmu/tests-gnr @@ -9,10 +9,23 @@ apebs_tests.sh -t ip_1 -w 0 apebs_tests.sh -t ip_2 -w 0 apebs_tests.sh -t lbr_1 -w 0 apebs_tests.sh -t lbr_2 -w 0 +apebs_tests.sh -t gpr_1 -w 0 +apebs_tests.sh -t gpr_2 -w 0 +apebs_tests.sh -t gp_counter_1 -w 0 +apebs_tests.sh -t gp_counter_2 -w 0 +apebs_tests.sh -t fixed_counter_1 -w 0 +apebs_tests.sh -t fixed_counter_2 -w 0 +apebs_tests.sh -t adaptive_pebs_msr -w 0 apebs_tests.sh -t large_pebs -w 0 apebs_tests.sh -t large_pebs -w 1 apebs_tests.sh -t xmm_1 -w 1 apebs_tests.sh -t xmm_2 -w 1 +apebs_tests.sh -t gpr_1 -w 1 +apebs_tests.sh -t gpr_2 -w 1 +apebs_tests.sh -t gp_counter_1 -w 1 +apebs_tests.sh -t gp_counter_2 -w 1 +apebs_tests.sh -t fixed_counter_1 -w 1 +apebs_tests.sh -t fixed_counter_2 -w 1 apebs_tests.sh -t ip_1 -w 1 apebs_tests.sh -t ip_2 -w 1 apebs_tests.sh -t data_src -w 1 From e4d15df549a7d093e8c820720055eb508afa46b4 Mon Sep 17 00:00:00 2001 From: Xudong Hao Date: Wed, 5 Aug 2026 07:51:48 +0000 Subject: [PATCH 5/5] BM/PMU: add 2 PEBS memory region tag test cases Add pebs_mrt_local_ram and pebs_mrt_snoop_hit test cases that verify PEBS data_src memory-region tag decoding on Diamond Rapids: - pebs_mrt_local_ram: collect PEBS mem-loads-aux samples and verify local RAM memory-region bits are correctly reported. - pebs_mrt_snoop_hit: collect PEBS mem-loads samples across cores and verify local shared-cache snoop HIT patterns. Signed-off-by: Xudong Hao (cherry picked from commit 7e6b65ae6c3ec069c476635f80e7a0f456196e14) --- BM/pmu/Makefile | 11 +- BM/pmu/pebs_mrt_workload.c | 281 +++++++++++++++++++++++++++++++++++++ BM/pmu/pmu_tests.sh | 136 ++++++++++++++++++ BM/pmu/tests-dmr | 2 + 4 files changed, 427 insertions(+), 3 deletions(-) create mode 100644 BM/pmu/pebs_mrt_workload.c diff --git a/BM/pmu/Makefile b/BM/pmu/Makefile index 2a85a00c..4d74f72f 100644 --- a/BM/pmu/Makefile +++ b/BM/pmu/Makefile @@ -2,10 +2,15 @@ # Copyright (c) 2026 Intel Corporation. CC = gcc -TARGET = rdpmc_user_disable_test +TARGET = rdpmc_user_disable_test pebs_mrt_workload -$(TARGET): rdpmc_user_disable_test.c +$(TARGET): rdpmc_user_disable_test.c pebs_mrt_workload.c + +rdpmc_user_disable_test: rdpmc_user_disable_test.c $(CC) -o $@ $< +pebs_mrt_workload: pebs_mrt_workload.c + $(CC) -O2 -pthread -o $@ $< + clean: - rm -f $(TARGET) + rm -f rdpmc_user_disable_test pebs_mrt_workload diff --git a/BM/pmu/pebs_mrt_workload.c b/BM/pmu/pebs_mrt_workload.c new file mode 100644 index 00000000..847a27d3 --- /dev/null +++ b/BM/pmu/pebs_mrt_workload.c @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2026 Intel Corporation. + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#define CACHELINE 64 +#define RAM_SIZE (256UL * 1024 * 1024) +#define RAM_STRIDE 4096UL +#define LOCAL_RAM_ITERS 200000UL +#define SNOOP_ITERS 200000UL +#define SNOOP_BATCH_LINES 256UL +#define MISS_EVICT_SIZE (2UL * 1024 * 1024) + +enum mode_id { + MODE_LOCAL_RAM, + MODE_SNOOP_NA, + MODE_SNOOP_HIT, + MODE_SNOOP_MISS, +}; + +struct cacheline_u64 { + volatile uint64_t v[CACHELINE / sizeof(uint64_t)]; +} __attribute__((aligned(CACHELINE))); + +struct snoop_phase { + volatile unsigned int v; + uint8_t pad[CACHELINE - sizeof(unsigned int)]; +} __attribute__((aligned(CACHELINE))); + +struct snoop_ctx { + struct snoop_phase phase; + struct cacheline_u64 lines[SNOOP_BATCH_LINES]; + uint8_t *evict_buf; + int worker_cpu; + enum mode_id mode; + unsigned long batches; + volatile uint64_t sink; +}; + +static inline void cpu_relax(void) +{ + asm volatile("pause" ::: "memory"); +} + +static inline void clflushopt_line(const void *ptr) +{ + asm volatile("clflushopt (%0)" : : "r"(ptr) : "memory"); +} + +static inline void cldemote_line(const void *ptr) +{ + asm volatile("cldemote (%0)" : : "r"(ptr) : "memory"); +} + +static inline void mfence_all(void) +{ + asm volatile("mfence" ::: "memory"); +} + +static inline unsigned int phase_load(struct snoop_phase *phase) +{ + return __atomic_load_n(&phase->v, __ATOMIC_SEQ_CST); +} + +static inline void phase_store(struct snoop_phase *phase, unsigned int value) +{ + __atomic_store_n(&phase->v, value, __ATOMIC_SEQ_CST); +} + +static void die_errno(const char *msg) +{ + fprintf(stderr, "%s: %s\n", msg, strerror(errno)); + exit(EXIT_FAILURE); +} + +static void bind_cpu(int cpu) +{ + cpu_set_t set; + + CPU_ZERO(&set); + CPU_SET(cpu, &set); + if (sched_setaffinity(0, sizeof(set), &set) != 0) + die_errno("sched_setaffinity"); +} + +static void *worker_thread(void *arg) +{ + struct snoop_ctx *ctx = arg; + unsigned long i; + volatile uint64_t tmp = 0; + + bind_cpu(ctx->worker_cpu); + for (i = 0; i < ctx->batches; i++) { + unsigned long j; + + while (phase_load(&ctx->phase) != 0) + cpu_relax(); + for (j = 0; j < SNOOP_BATCH_LINES; j++) + clflushopt_line((const void *)&ctx->lines[j].v[0]); + mfence_all(); + for (j = 0; j < SNOOP_BATCH_LINES; j++) + tmp += ctx->lines[j].v[0]; + if (ctx->mode == MODE_SNOOP_MISS) { + mfence_all(); + for (j = 0; j < MISS_EVICT_SIZE; j += CACHELINE) + tmp += ctx->evict_buf[j]; + } + mfence_all(); + phase_store(&ctx->phase, 1); + while (phase_load(&ctx->phase) != 2) + cpu_relax(); + phase_store(&ctx->phase, 0); + } + ctx->sink = tmp; + return NULL; +} + +static void run_local_ram(int reader_cpu, unsigned long iters) +{ + uint8_t *buf; + unsigned long i; + volatile uint64_t sink = 0; + + bind_cpu(reader_cpu); + if (posix_memalign((void **)&buf, CACHELINE, RAM_SIZE) != 0) { + fprintf(stderr, "posix_memalign failed\n"); + exit(EXIT_FAILURE); + } + memset(buf, 0x5a, RAM_SIZE); + mfence_all(); + + for (i = 0; i < iters; i++) { + size_t off = (i * RAM_STRIDE) & (RAM_SIZE - CACHELINE); + volatile uint64_t *ptr = (volatile uint64_t *)(buf + off); + + clflushopt_line((const void *)ptr); + mfence_all(); + sink += *ptr; + } + + fprintf(stderr, "local_ram_sink=%llu\n", (unsigned long long)sink); + free(buf); +} + +static void run_snoop_mode(int reader_cpu, int worker_cpu, enum mode_id mode, unsigned long iters) +{ + struct snoop_ctx ctx; + pthread_t worker; + unsigned long i; + volatile uint64_t sink = 0; + + bind_cpu(reader_cpu); + memset(&ctx, 0, sizeof(ctx)); + ctx.worker_cpu = worker_cpu; + ctx.mode = mode; + ctx.batches = (iters + SNOOP_BATCH_LINES - 1) / SNOOP_BATCH_LINES; + for (i = 0; i < SNOOP_BATCH_LINES; i++) + ctx.lines[i].v[0] = 0x123456789abcdef0ULL + i; + if (mode == MODE_SNOOP_HIT || mode == MODE_SNOOP_MISS) { + if (posix_memalign((void **)&ctx.evict_buf, CACHELINE, MISS_EVICT_SIZE) != 0) { + fprintf(stderr, "posix_memalign failed\n"); + exit(EXIT_FAILURE); + } + memset(ctx.evict_buf, 0xa5, MISS_EVICT_SIZE); + } + if (mode != MODE_SNOOP_NA) { + if (pthread_create(&worker, NULL, worker_thread, &ctx) != 0) + die_errno("pthread_create"); + } + + for (i = 0; i < ctx.batches; i++) { + unsigned long j; + + if (mode == MODE_SNOOP_NA) { + for (j = 0; j < SNOOP_BATCH_LINES; j++) + clflushopt_line((const void *)&ctx.lines[j].v[0]); + mfence_all(); + for (j = 0; j < SNOOP_BATCH_LINES; j++) + sink += ctx.lines[j].v[0]; + continue; + } + + while (phase_load(&ctx.phase) != 1) + cpu_relax(); + for (j = 0; j < SNOOP_BATCH_LINES; j++) + sink += ctx.lines[j].v[0]; + if (mode == MODE_SNOOP_HIT) { + for (j = 0; j < SNOOP_BATCH_LINES; j++) + cldemote_line((const void *)&ctx.lines[j].v[0]); + mfence_all(); + for (j = 0; j < MISS_EVICT_SIZE; j += CACHELINE) + sink += ctx.evict_buf[j]; + } + for (j = 0; j < SNOOP_BATCH_LINES; j++) + sink += ctx.lines[j].v[0]; + phase_store(&ctx.phase, 2); + while (phase_load(&ctx.phase) != 0) + cpu_relax(); + } + + if (mode != MODE_SNOOP_NA) + pthread_join(worker, NULL); + free(ctx.evict_buf); + fprintf(stderr, "snoop_sink=%llu worker_sink=%llu\n", + (unsigned long long)sink, + (unsigned long long)ctx.sink); +} + +static enum mode_id parse_mode(const char *arg) +{ + if (!strcmp(arg, "local-ram")) + return MODE_LOCAL_RAM; + if (!strcmp(arg, "snoop-na")) + return MODE_SNOOP_NA; + if (!strcmp(arg, "snoop-hit")) + return MODE_SNOOP_HIT; + if (!strcmp(arg, "snoop-miss")) + return MODE_SNOOP_MISS; + fprintf(stderr, "unknown mode: %s\n", arg); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + enum mode_id mode = MODE_LOCAL_RAM; + unsigned long iters = 0; + int reader_cpu = 0; + int worker_cpu = 1; + int opt; + + while ((opt = getopt(argc, argv, "i:m:r:w:")) != -1) { + switch (opt) { + case 'i': + iters = strtoul(optarg, NULL, 0); + break; + case 'm': + mode = parse_mode(optarg); + break; + case 'r': + reader_cpu = atoi(optarg); + break; + case 'w': + worker_cpu = atoi(optarg); + break; + default: + fprintf(stderr, + "usage: %s -m [-r cpu] [-w cpu]\n", + argv[0]); + return EXIT_FAILURE; + } + } + + if (!iters) + iters = mode == MODE_LOCAL_RAM ? LOCAL_RAM_ITERS : SNOOP_ITERS; + + if (reader_cpu == worker_cpu && mode != MODE_SNOOP_NA && mode != MODE_LOCAL_RAM) { + fprintf(stderr, "reader and worker CPUs must differ\n"); + return EXIT_FAILURE; + } + + switch (mode) { + case MODE_LOCAL_RAM: + run_local_ram(reader_cpu, iters); + break; + case MODE_SNOOP_NA: + case MODE_SNOOP_HIT: + case MODE_SNOOP_MISS: + run_snoop_mode(reader_cpu, worker_cpu, mode, iters); + break; + } + + return EXIT_SUCCESS; +} diff --git a/BM/pmu/pmu_tests.sh b/BM/pmu/pmu_tests.sh index 26fe63dd..d4c52f61 100755 --- a/BM/pmu/pmu_tests.sh +++ b/BM/pmu/pmu_tests.sh @@ -701,6 +701,136 @@ acr_run_on_supported_pmus() { $fn } +get_pebs_mrt_workload() { + local benchmark src + + src="$(pwd)/pebs_mrt_workload.c" + benchmark="$(pwd)/pebs_mrt_workload" + [[ -f "$src" ]] || die "workload source $src does not exist!" + if [[ ! -x "$benchmark" || "$src" -nt "$benchmark" ]]; then + gcc -O2 -pthread -o "$benchmark" "$src" || die "failed to build $benchmark" + fi + [[ -x "$benchmark" ]] || die "benchmark $benchmark does not exist!" + echo "$benchmark" +} + +find_first_online_cpu() { + local cpu_dir cpu + + for cpu_dir in /sys/devices/system/cpu/cpu[0-9]*; do + cpu=${cpu_dir##*cpu} + if [[ -f "$cpu_dir/online" ]] && [[ $(cat "$cpu_dir/online") -ne 1 ]]; then + continue + fi + echo "$cpu" + return 0 + done + + die "No online CPU found!" +} + +list_cross_core_worker_cpus() { + local reader_cpu=$1 + local reader_dir="/sys/devices/system/cpu/cpu${reader_cpu}" + local reader_core reader_pkg cpu_dir cpu core_id pkg_id workers="" + + [[ -d "$reader_dir" ]] || die "reader CPU $reader_cpu is not present!" + reader_core=$(cat "$reader_dir/topology/core_id") + reader_pkg=$(cat "$reader_dir/topology/physical_package_id") + for cpu_dir in /sys/devices/system/cpu/cpu[0-9]*; do + cpu=${cpu_dir##*cpu} + [[ "$cpu" == "$reader_cpu" ]] && continue + if [[ -f "$cpu_dir/online" ]] && [[ $(cat "$cpu_dir/online") -ne 1 ]]; then + continue + fi + core_id=$(cat "$cpu_dir/topology/core_id") + pkg_id=$(cat "$cpu_dir/topology/physical_package_id") + if [[ "$pkg_id" == "$reader_pkg" && "$core_id" != "$reader_core" ]]; then + workers+="$cpu " + fi + done + + [[ -n "$workers" ]] || die "No online cross-core CPU pair found!" + echo "$workers" +} + +pebs_mrt_local_ram_test() { + local perfdata="pebs_mrt_local_ram.data" + local perfdump="pebs_mrt_local_ram.dump" + local logfile="pebs_mrt_local_ram.log" + local benchmark sample_count local_ram_count + + benchmark=$(get_pebs_mrt_workload) + clear_files "$perfdata" "$perfdump" "$logfile" + do_cmd "perf record -d -o $perfdata -C 0 -c 200 -e '{cpu/event=0x03,umask=0x82/,cpu/mem-loads,ldlat=3/}:P' -- $benchmark -m local-ram -r 0 -i 200000 2>&1|tee $logfile" + sample_count=$(grep "sample" "$logfile" | awk '{print $10}' | tr -cd "0-9") + [[ -n "$sample_count" ]] || die "No samples found in $logfile!" + perf report --stdio -D -i "$perfdata" > "$perfdump" + local_ram_count=$(python3 - "$perfdump" <<'PY' +import sys +count = 0 +for line in open(sys.argv[1], errors='ignore'): + if 'data_src:' not in line: + continue + value = int(line.split()[-1], 16) + if not (value & 0x2): + continue + region = (value >> 46) & 0x1f + lvl_num = (value >> 33) & 0xf + remote = (value >> 37) & 0x1 + if 0x8 <= region <= 0xf and lvl_num == 0xd and remote == 0: + count += 1 +print(count) +PY +) || die "failed to decode perf data_src values" + test_print_trc "sample_count=$sample_count local_ram_count=$local_ram_count" + [[ $sample_count -gt 0 ]] || die "samples = 0!" + [[ $local_ram_count -gt 0 ]] || die "no local RAM memory-region samples found!" + clear_files "$perfdata" "$perfdump" "$logfile" +} + +pebs_mrt_snoop_hit_test() { + local perfdata="pebs_mrt_snoop_hit.data" + local perfdump="pebs_mrt_snoop_hit.dump" + local logfile="pebs_mrt_snoop_hit.log" + local benchmark sample_count reader_cpu worker_cpu worker_cpus + local snoop_na_count snoop_miss_count snoop_hit_count snoop_hitm_count snoop_none_count + + reader_cpu=$(find_first_online_cpu) + worker_cpus=$(list_cross_core_worker_cpus "$reader_cpu") + benchmark=$(get_pebs_mrt_workload) + for worker_cpu in $worker_cpus; do + clear_files "$perfdata" "$perfdump" "$logfile" + do_cmd "perf record -d -o $perfdata -c 100 -e 'cpu/mem-loads/P' -- $benchmark -m snoop-hit -r $reader_cpu -w $worker_cpu -i 262144 2>&1|tee $logfile" + sample_count=$(grep "sample" "$logfile" | awk '{print $10}' | tr -cd "0-9") + perf report --stdio -D -i "$perfdata" > "$perfdump" + read -r snoop_na_count snoop_miss_count snoop_hit_count snoop_hitm_count snoop_none_count <<< "$(python3 - "$perfdump" <<'PY' +import sys +counts = {1: 0, 2: 0, 4: 0, 8: 0, 16: 0} +for line in open(sys.argv[1], errors='ignore'): + if 'data_src:' not in line: + continue + value = int(line.split()[-1], 16) + region = (value >> 46) & 0x1f + lvl_num = (value >> 33) & 0xf + snoop = (value >> 19) & 0x1f + if region == 0x2 and lvl_num == 0x3 and snoop in counts: + counts[snoop] += 1 +print(counts[1], counts[8], counts[4], counts[16], counts[2]) +PY + )" || die "failed to decode snoop data_src values" + test_print_trc "reader_cpu=$reader_cpu worker_cpu=$worker_cpu sample_count=$sample_count source2_snoop_na=$snoop_na_count source2_snoop_miss=$snoop_miss_count source2_snoop_hit=$snoop_hit_count source2_snoop_hitm=$snoop_hitm_count source2_snoop_none=$snoop_none_count" + [[ $sample_count -gt 0 ]] || die "samples = 0!" + if [[ $snoop_hit_count -gt 0 ]]; then + clear_files "$perfdata" "$perfdump" "$logfile" + return 0 + fi + done + + clear_files "$perfdata" "$perfdump" "$logfile" + die "no local shared-cache snoop HIT samples found!" +} + pmu_test() { case $TEST_SCENARIO in fix_counter) @@ -811,6 +941,12 @@ pmu_test() { acr_stress) acr_run_on_supported_pmus acr_stress_test ;; + pebs_mrt_local_ram) + pebs_mrt_local_ram_test + ;; + pebs_mrt_snoop_hit) + pebs_mrt_snoop_hit_test + ;; esac return 0 } diff --git a/BM/pmu/tests-dmr b/BM/pmu/tests-dmr index e1ad9bc2..4f939ee9 100644 --- a/BM/pmu/tests-dmr +++ b/BM/pmu/tests-dmr @@ -57,3 +57,5 @@ pmu_tests.sh -t acr_reject_freq pmu_tests.sh -t acr_reject_ppp pmu_tests.sh -t acr_reject_contiguity pmu_tests.sh -t acr_stress -l 10 +pmu_tests.sh -t pebs_mrt_local_ram +pmu_tests.sh -t pebs_mrt_snoop_hit