-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[lldb][test] Unify and extend test infrastructure for checking CPU features #153914
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
Changes from 4 commits
fd3eff7
dd5f0b8
a1a4f38
fc06710
f31c6b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| """ | ||
| Platform-agnostic helper to query for CPU features. | ||
| """ | ||
|
|
||
| import re | ||
|
|
||
|
|
||
| class CPUFeature: | ||
| def __init__(self, linux_cpu_info_flag: str = None, darwin_sysctl_key: str = None): | ||
| self.cpu_info_flag = linux_cpu_info_flag | ||
| self.sysctl_key = darwin_sysctl_key | ||
|
|
||
| def __str__(self): | ||
| return self.cpu_info_flag | ||
|
|
||
| def is_supported(self, triple, cmd_runner): | ||
| if re.match(".*-.*-linux", triple): | ||
| err_msg, res = self._is_supported_linux(cmd_runner) | ||
| elif re.match(".*-apple-.*", triple): | ||
yln marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| err_msg, res = self._is_supported_darwin(cmd_runner) | ||
| else: | ||
| err_msg, res = None, False | ||
|
|
||
| if err_msg: | ||
| print(f"CPU feature check failed: {err_msg}") | ||
|
|
||
| return res | ||
|
|
||
| def _is_supported_linux(self, cmd_runner): | ||
| if not self.cpu_info_flag: | ||
| return "Unspecified cpuinfo flag", False | ||
yln marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| cmd = "cat /proc/cpuinfo" | ||
| err, retcode, output = cmd_runner(cmd) | ||
| if err.Fail() or retcode != 0: | ||
| return output, False | ||
|
|
||
| # FIXME: simple substring match, e.g., test for 'sme' will be true if | ||
| # 'sme2' or 'smefa64' is present | ||
| return None, (self.cpu_info_flag in output) | ||
yln marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| def _is_supported_darwin(self, cmd_runner): | ||
| if not self.sysctl_key: | ||
| return "Unspecified sysctl key", False | ||
yln marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| cmd = f"sysctl -n {self.sysctl_key}" | ||
| err, retcode, output = cmd_runner(cmd) | ||
| if err.Fail() or retcode != 0: | ||
| return output, False | ||
yln marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return None, (output.strip() == "1") | ||
|
|
||
|
|
||
| class AArch64: | ||
| FPMR = CPUFeature("fpmr") | ||
| GCS = CPUFeature("gcs") | ||
| MTE = CPUFeature("mte") | ||
| MTE_STORE_ONLY = CPUFeature("mtestoreonly") | ||
| PTR_AUTH = CPUFeature("paca", "hw.optional.arm.FEAT_PAuth2") | ||
| SME = CPUFeature("sme", "hw.optional.arm.FEAT_SME") | ||
| SME_FA64 = CPUFeature("smefa64") | ||
| SME2 = CPUFeature("sme2", "hw.optional.arm.FEAT_SME2") | ||
| SVE = CPUFeature("sve") | ||
|
|
||
|
|
||
| class Loong: | ||
| LASX = CPUFeature("lasx") | ||
| LSX = CPUFeature("lsx") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,6 +48,7 @@ | |
| # LLDB modules | ||
| import lldb | ||
| from . import configuration | ||
| from . import cpu_feature | ||
| from . import decorators | ||
| from . import lldbplatformutil | ||
| from . import lldbtest_config | ||
|
|
@@ -1315,39 +1316,6 @@ def isPPC64le(self): | |
| return True | ||
| return False | ||
|
|
||
| def getCPUInfo(self): | ||
| triple = self.dbg.GetSelectedPlatform().GetTriple() | ||
|
|
||
| # TODO other platforms, please implement this function | ||
| if not re.match(".*-.*-linux", triple): | ||
| return "" | ||
|
|
||
| # Need to do something different for non-Linux/Android targets | ||
| cpuinfo_path = self.getBuildArtifact("cpuinfo") | ||
| if configuration.lldb_platform_name: | ||
| self.runCmd( | ||
| 'platform get-file "/proc/cpuinfo" ' + cpuinfo_path, check=False | ||
| ) | ||
| if not self.res.Succeeded(): | ||
| if self.TraceOn(): | ||
| print( | ||
| 'Failed to get /proc/cpuinfo from remote: "{}"'.format( | ||
| self.res.GetOutput().strip() | ||
| ) | ||
| ) | ||
| print("All cpuinfo feature checks will fail.") | ||
| return "" | ||
| else: | ||
| cpuinfo_path = "/proc/cpuinfo" | ||
|
|
||
| try: | ||
| with open(cpuinfo_path, "r") as f: | ||
| cpuinfo = f.read() | ||
| except: | ||
| return "" | ||
|
|
||
| return cpuinfo | ||
|
|
||
| def isAArch64(self): | ||
| """Returns true if the architecture is AArch64.""" | ||
| arch = self.getArchitecture().lower() | ||
|
|
@@ -1360,39 +1328,47 @@ def isARM(self): | |
| self.getArchitecture().lower().startswith("arm") | ||
| ) | ||
|
|
||
| def isSupported(self, cpu_feature: cpu_feature.CPUFeature): | ||
| triple = self.dbg.GetSelectedPlatform().GetTriple() | ||
| cmd_runner = self.run_platform_command | ||
| return cpu_feature.is_supported(triple, cmd_runner) | ||
yln marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| def isAArch64SVE(self): | ||
| return self.isAArch64() and "sve" in self.getCPUInfo() | ||
| return self.isAArch64() and self.isSupported(cpu_feature.AArch64.SVE) | ||
|
|
||
| def isAArch64SME(self): | ||
| return self.isAArch64() and "sme" in self.getCPUInfo() | ||
| return self.isAArch64() and self.isSupported(cpu_feature.AArch64.SME) | ||
|
|
||
| def isAArch64SME2(self): | ||
| # If you have sme2, you also have sme. | ||
| return self.isAArch64() and "sme2" in self.getCPUInfo() | ||
| return self.isAArch64() and self.isSupported(cpu_feature.AArch64.SME2) | ||
|
|
||
| def isAArch64SMEFA64(self): | ||
| # smefa64 allows the use of the full A64 instruction set in streaming | ||
| # mode. This is required by certain test programs to setup register | ||
| # state. | ||
| cpuinfo = self.getCPUInfo() | ||
| return self.isAArch64() and "sme" in cpuinfo and "smefa64" in cpuinfo | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that One way to fix this would be to parse and merge the CPU flags in |
||
| return ( | ||
| self.isAArch64() | ||
| and self.isSupported(cpu_feature.AArch64.SME) | ||
| and self.isSupported(cpu_feature.AArch64.SME_FA64) | ||
| ) | ||
|
|
||
| def isAArch64MTE(self): | ||
| return self.isAArch64() and "mte" in self.getCPUInfo() | ||
| return self.isAArch64() and self.isSupported(cpu_feature.AArch64.MTE) | ||
|
|
||
| def isAArch64MTEStoreOnly(self): | ||
| return self.isAArch64() and "mtestoreonly" in self.getCPUInfo() | ||
| return self.isAArch64() and self.isSupported(cpu_feature.AArch64.MTE_STORE_ONLY) | ||
|
|
||
| def isAArch64GCS(self): | ||
| return self.isAArch64() and "gcs" in self.getCPUInfo() | ||
| return self.isAArch64() and self.isSupported(cpu_feature.AArch64.GCS) | ||
|
|
||
| def isAArch64PAuth(self): | ||
| if self.getArchitecture() == "arm64e": | ||
| return True | ||
| return self.isAArch64() and "paca" in self.getCPUInfo() | ||
| return self.isAArch64() and self.isSupported(cpu_feature.AArch64.PTR_AUTH) | ||
|
|
||
| def isAArch64FPMR(self): | ||
| return self.isAArch64() and "fpmr" in self.getCPUInfo() | ||
| return self.isAArch64() and self.isSupported(cpu_feature.AArch64.FPMR) | ||
|
|
||
| def isAArch64Windows(self): | ||
| """Returns true if the architecture is AArch64 and platform windows.""" | ||
|
|
@@ -1407,10 +1383,10 @@ def isLoongArch(self): | |
| return arch in ["loongarch64", "loongarch32"] | ||
|
|
||
| def isLoongArchLSX(self): | ||
| return self.isLoongArch() and "lsx" in self.getCPUInfo() | ||
| return self.isLoongArch() and self.isSupported(cpu_feature.Loong.LSX) | ||
|
|
||
| def isLoongArchLASX(self): | ||
| return self.isLoongArch() and "lasx" in self.getCPUInfo() | ||
| return self.isLoongArch() and self.isSupported(cpu_feature.Loong.LASX) | ||
|
|
||
| def isRISCV(self): | ||
| """Returns true if the architecture is RISCV64 or RISCV32.""" | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.