-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
topdown: Protect topdown on heterogeneous processors with rseq #329
Open
willowec
wants to merge
7
commits into
icl-utk-edu:master
Choose a base branch
from
willowec:topdown-rdpmc-protected
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…S MSR Add a component that collects Intel's topdown metrics from the PERF_METRICS MSR and automatically converts the raw metric values to user-consumable percentages. The intent of this component is to provide an intuitive interface for accessing topdown metrics on the supported processors. Tested on a RaptorLake-S/HX machine (family/model/stepping 0x6/0xb7/0x1). To add other supported architectures the switch statment in _topdown_init_component() should be populated for the architecture's model number, whether it supports level 2 topdown metrics, and in the case of a heterogeneous processor what core type it must be run on.
While the offical Software Developer Manual only lists the availability of the PERF_METRICS MSR for three architectures, we can use the 'perfmon' repository maintained by Intel to discover what architectures support the MSR (repo here: https://github.com/intel/perfmon). Architectures that the repository demonstrates support the events 'PERF_METRICS.BACKEND_BOUND', 'PERF_METRICS.FRONTEND_BOUND', etc. must support the topdown level 1 metrics of the PERF_METRICS MSR. Similarly, the presence of the events 'PERF_METRICS.FETCH_LATENCY', 'PERF_METRICS.MEMORY_BOUND', etc. demonstrates support for topdown L2 metrics in the PERF_METRICS MSR. By cross-referencing the architecture names in the perfmon repository with their DisplayFamily/DisplayModel values in Table 2-1 of volume 4 of the IA32 SDM, we can add support for the following architectures: - Rocket Lake - Ice Lake (icl & icx) - Tiger Lake - Sapphire Rapids - Meteor Lake (redwood cove p-core only) - Alder Lake (golden cove p-core only) - Granite Rapids - Everald Rapids None of these additional architectures have been tested with the topdown component yet. While Arrow Lake is shown to support L1 & L2 metrics in the prefmon repository, its FamilyModel is not yet available in the IA32 SDM so it has not been added.
All of Intel's heterogeneous CPUs that support the PERF_METRICS MSR only support it for their performance (p-core) cores. This means that if a program that is being measured using the topdown component in PAPI happens to be rescheduled to a e-core during its runtime, PAPI will segfault. To fix this, add a check in _topdown_start() and _topdown_stop() to exit gracefully if the core affinity of the process has changed to an unsupported core type.
Previously, the x86intrin.h header file had been included in order to provide definitions for _rdpmc(). However, this has caused the github actions testing compilation of the component on ARM systems to fail. Therefore, remove the include and add a manual definition for _rdpmc() taken from the perf_event component.
To prevent programs using the topdown component on heterogeneous processors that only supply the PERF_METRICS MSR on some of their cores from segfaulting due to trying to read the MSR after being moved to an unsupported core type, the topdown component periodically checks it is on a supported core and exits if not. Previously, this check occured at the start of PAPI_start and PAPI_stop. After writing a script that starts a program being calipered with the topdown component and moves it to an unsupported core after a random amount of time, for N=100,000 tests the heterogeneous checks failed to prevent a segmentation fault 0.08% of the time. This patch moves the heterogeneous checks to occur only directly before the rdpmc calls, resulting in cleaner code and a reduced segfault prevention failure rate of 0.064%. While it is frustrating that the failure rate is non-zero, since there appears to be no way to tell a process to ignore changes to its affinity, I believe there to be no perfect solution at this time.
Previously, the topdown component calculated metrics by taking the difference of the metrics before and the metrics after the calculated code block using Equation 1: M% = (Mb*Sb/255 - Ma*Sa/255) / (Sb - Sa) * 100 (1) where Mx are the raw bytes of the metric before and after the calipered code block and Sx are the slots. However, if Sa = 0 this simplifies to M% = Mb/255 * 100 (2) Therefore it is sufficient to simply reset the PERF_METRICS MSR and SLOTS during PAPI_start() and then use Equation 2 in PAPI_stop, reducing the number of dangerous rdpmc calls, reducing overhead, and simplifying the code.
On Intel's heterogeneous multicore processors such as Raptor Lake, the PERF_METRICS MSR is only available on the performance cores (p-cores). If the rdpmc instruction is executed attempting to access the MSR while the process is on an efficient core (e-core), a segmentation fault occurs. Previously, the topdown component has used a simple check before every execution of the rdpmc instruction to ensure the core the program is bound to is a p-core. However, this can fail if the program is moved to another core between the check and the execution of rdpmc. While rare, a worst-case scenario test that repeatedly moves a program which is using the topdown component from p-core to e-core at a random time saw 338 segmentation faults out of 1 million affinity switches (a 0.0338% error rate). This is a non-zero number of segmentation faults, and we can do better. Use librseq to protect the rdpmc instruction with a restartable sequence (rseq). When the process is preempted by an affinity change, the sequence immediately aborts and can be restarted. By keeping the check that the process is on a p-core and the rdpmc instruction itself within the critical section of the rseq, it is guaranteed that the rdpmc instruction will never be executed on an invalid core. The same test described in the previous paragraph sees 0 segmentation faults.
9071109
to
8731432
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Pull Request Description
This PR extends #286 with
librseq
to guarantee that attempting to access thePERF_METRICS
MSR on an Intel heterogeneous multicore processor will never result in a segmentation fault in the event of an unexpected process migration from p-core to e-core.The topdown component dynamically loads
librseq
, and falls back to the protections introduced in #286 iflibrseq
cannot be found or loaded. This PR is tested on a Raptor Lake machine, with patched version oflibrseq
that fixes an issue preventing it from being dynamically loaded.As of the opening of this PR,
librseq
cannot be dynamically loaded due to a static thread-local storage structure it uses. However, the maintainer has indicated that this will be removed in the future (seelibrseq
#22). Until it is removed, there is no urgency to merging this PR as it doesn't offer any benefits without a dynamically loadablelibrseq
.Thanks to Mathieu Desnoyers for the help understanding how restartable sequences work, for creating
librseq
, and for the help with how to use it.Author Checklist
Why this PR exists. Reference all relevant information, including background, issues, test failures, etc
Commits are self contained and only do one thing
Commits have a header of the form:
module: short description
Commits have a body (whenever relevant) containing a detailed description of the addressed problem and its solution
The PR needs to pass all the tests