amd-debug-tools 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of amd-debug-tools might be problematic. Click here for more details.
- amd_debug/__init__.py +1 -1
- amd_debug/bios.py +4 -2
- amd_debug/failures.py +1 -1
- amd_debug/installer.py +4 -2
- amd_debug/kernel.py +8 -0
- amd_debug/prerequisites.py +17 -27
- amd_debug/pstate.py +5 -3
- amd_debug/s2idle.py +33 -30
- amd_debug/sleep_report.py +128 -85
- amd_debug/templates/html +4 -2
- amd_debug/validator.py +21 -15
- {amd_debug_tools-0.2.2.dist-info → amd_debug_tools-0.2.4.dist-info}/METADATA +1 -1
- amd_debug_tools-0.2.4.dist-info/RECORD +45 -0
- launcher.py +0 -1
- test_bios.py +4 -4
- test_launcher.py +2 -1
- test_prerequisites.py +11 -19
- test_s2idle.py +41 -11
- test_sleep_report.py +29 -0
- test_validator.py +116 -7
- amd_debug_tools-0.2.2.dist-info/RECORD +0 -45
- {amd_debug_tools-0.2.2.dist-info → amd_debug_tools-0.2.4.dist-info}/WHEEL +0 -0
- {amd_debug_tools-0.2.2.dist-info → amd_debug_tools-0.2.4.dist-info}/entry_points.txt +0 -0
- {amd_debug_tools-0.2.2.dist-info → amd_debug_tools-0.2.4.dist-info}/licenses/LICENSE +0 -0
- {amd_debug_tools-0.2.2.dist-info → amd_debug_tools-0.2.4.dist-info}/top_level.txt +0 -0
amd_debug/__init__.py
CHANGED
amd_debug/bios.py
CHANGED
|
@@ -122,7 +122,7 @@ def parse_args():
|
|
|
122
122
|
return args
|
|
123
123
|
|
|
124
124
|
|
|
125
|
-
def main():
|
|
125
|
+
def main() -> None|int:
|
|
126
126
|
"""Main function"""
|
|
127
127
|
args = parse_args()
|
|
128
128
|
ret = False
|
|
@@ -135,4 +135,6 @@ def main():
|
|
|
135
135
|
elif args.command == "version":
|
|
136
136
|
print(version())
|
|
137
137
|
show_log_info()
|
|
138
|
-
|
|
138
|
+
if ret is False:
|
|
139
|
+
return 1
|
|
140
|
+
return
|
amd_debug/failures.py
CHANGED
|
@@ -142,7 +142,7 @@ class MissingDriver(S0i3Failure):
|
|
|
142
142
|
self.description = f"{slot} driver is missing"
|
|
143
143
|
self.explanation = (
|
|
144
144
|
f"No driver has been bound to PCI device {slot} "
|
|
145
|
-
"Without a driver, the hardware may be able to enter a low power
|
|
145
|
+
"Without a driver, the hardware may be able to enter a low power "
|
|
146
146
|
"state, but there may be spurious wake up events."
|
|
147
147
|
)
|
|
148
148
|
|
amd_debug/installer.py
CHANGED
|
@@ -446,7 +446,7 @@ def parse_args():
|
|
|
446
446
|
return parser.parse_args()
|
|
447
447
|
|
|
448
448
|
|
|
449
|
-
def install_dep_superset() ->
|
|
449
|
+
def install_dep_superset() -> None|int:
|
|
450
450
|
"""Install all python supserset dependencies"""
|
|
451
451
|
args = parse_args()
|
|
452
452
|
tool = Installer(tool_debug=args.tool_debug)
|
|
@@ -465,4 +465,6 @@ def install_dep_superset() -> bool:
|
|
|
465
465
|
if ret:
|
|
466
466
|
print_color("All dependencies installed", "✅")
|
|
467
467
|
show_log_info()
|
|
468
|
-
|
|
468
|
+
if ret is False:
|
|
469
|
+
return 1
|
|
470
|
+
return
|
amd_debug/kernel.py
CHANGED
|
@@ -19,6 +19,7 @@ def get_kernel_command_line() -> str:
|
|
|
19
19
|
"apparmor",
|
|
20
20
|
"audit",
|
|
21
21
|
"auto",
|
|
22
|
+
"bluetooth.disable_ertm",
|
|
22
23
|
"boot",
|
|
23
24
|
"BOOT_IMAGE",
|
|
24
25
|
"console",
|
|
@@ -29,6 +30,7 @@ def get_kernel_command_line() -> str:
|
|
|
29
30
|
"earlycon",
|
|
30
31
|
"earlyprintk",
|
|
31
32
|
"ether",
|
|
33
|
+
"init",
|
|
32
34
|
"initrd",
|
|
33
35
|
"ip",
|
|
34
36
|
"LANG",
|
|
@@ -47,7 +49,9 @@ def get_kernel_command_line() -> str:
|
|
|
47
49
|
"nfs.nfs4_unique_id",
|
|
48
50
|
"nfsroot",
|
|
49
51
|
"noplymouth",
|
|
52
|
+
"nowatchdog",
|
|
50
53
|
"ostree",
|
|
54
|
+
"preempt",
|
|
51
55
|
"quiet",
|
|
52
56
|
"rd.dm.uuid",
|
|
53
57
|
"rd.luks.allow-discards",
|
|
@@ -66,12 +70,15 @@ def get_kernel_command_line() -> str:
|
|
|
66
70
|
"ro",
|
|
67
71
|
"root",
|
|
68
72
|
"rootflags",
|
|
73
|
+
"rootfstype",
|
|
69
74
|
"roothash",
|
|
70
75
|
"rw",
|
|
71
76
|
"security",
|
|
77
|
+
"selinux",
|
|
72
78
|
"showopts",
|
|
73
79
|
"splash",
|
|
74
80
|
"swap",
|
|
81
|
+
"systemd.machine_id",
|
|
75
82
|
"systemd.mask",
|
|
76
83
|
"systemd.show_status",
|
|
77
84
|
"systemd.unit",
|
|
@@ -82,6 +89,7 @@ def get_kernel_command_line() -> str:
|
|
|
82
89
|
"verbose",
|
|
83
90
|
"vt.handoff",
|
|
84
91
|
"zfs",
|
|
92
|
+
"zswap.enabled",
|
|
85
93
|
]
|
|
86
94
|
# remove anything that starts with something in filtered from cmdline
|
|
87
95
|
return " ".join([x for x in cmdline.split() if not x.startswith(tuple(filtered))])
|
amd_debug/prerequisites.py
CHANGED
|
@@ -134,22 +134,19 @@ class PrerequisiteValidator(AmdTool):
|
|
|
134
134
|
if len(edids) == 0:
|
|
135
135
|
self.db.record_debug("No EDID data found")
|
|
136
136
|
return True
|
|
137
|
-
|
|
138
137
|
for name, p in edids.items():
|
|
139
138
|
output = None
|
|
140
|
-
for
|
|
139
|
+
for tool in ["di-edid-decode", "edid-decode"]:
|
|
141
140
|
try:
|
|
142
|
-
cmd = [
|
|
141
|
+
cmd = [tool, p]
|
|
143
142
|
output = subprocess.check_output(
|
|
144
143
|
cmd, stderr=subprocess.DEVNULL
|
|
145
|
-
).decode("utf-8")
|
|
144
|
+
).decode("utf-8", errors="ignore")
|
|
146
145
|
break
|
|
147
146
|
except FileNotFoundError:
|
|
148
147
|
self.db.record_debug(f"{cmd} not installed")
|
|
149
148
|
except subprocess.CalledProcessError as e:
|
|
150
|
-
|
|
151
|
-
f"failed to capture edid with {cmd}: {e.output}"
|
|
152
|
-
)
|
|
149
|
+
pass
|
|
153
150
|
if not output:
|
|
154
151
|
self.db.record_prereq("Failed to capture EDID table", "👀")
|
|
155
152
|
else:
|
|
@@ -245,7 +242,6 @@ class PrerequisiteValidator(AmdTool):
|
|
|
245
242
|
for dev in self.pyudev.list_devices(subsystem="pci", DRIVER="nvme"):
|
|
246
243
|
# https://git.kernel.org/torvalds/c/e79a10652bbd3
|
|
247
244
|
if minimum_kernel(6, 10):
|
|
248
|
-
self.db.record_debug("New enough kernel to avoid NVME check")
|
|
249
245
|
break
|
|
250
246
|
pci_slot_name = dev.properties["PCI_SLOT_NAME"]
|
|
251
247
|
vendor = dev.properties.get("ID_VENDOR_FROM_DATABASE", "")
|
|
@@ -319,7 +315,6 @@ class PrerequisiteValidator(AmdTool):
|
|
|
319
315
|
# not needed to check in newer kernels
|
|
320
316
|
# see https://github.com/torvalds/linux/commit/77f1972bdcf7513293e8bbe376b9fe837310ee9c
|
|
321
317
|
if minimum_kernel(6, 10):
|
|
322
|
-
self.db.record_debug("New enough kernel to avoid HSMP check")
|
|
323
318
|
return True
|
|
324
319
|
f = os.path.join("/", "boot", f"config-{platform.uname().release}")
|
|
325
320
|
if os.path.exists(f):
|
|
@@ -527,7 +522,7 @@ class PrerequisiteValidator(AmdTool):
|
|
|
527
522
|
f"{keys['sys_vendor']} {keys['product_name']} ({keys['product_family']})",
|
|
528
523
|
"💻",
|
|
529
524
|
)
|
|
530
|
-
debug_str = "DMI
|
|
525
|
+
debug_str = "DMI|value\n"
|
|
531
526
|
for key, value in keys.items():
|
|
532
527
|
if (
|
|
533
528
|
"product_name" in key
|
|
@@ -535,7 +530,7 @@ class PrerequisiteValidator(AmdTool):
|
|
|
535
530
|
or "product_family" in key
|
|
536
531
|
):
|
|
537
532
|
continue
|
|
538
|
-
debug_str += f"{key}
|
|
533
|
+
debug_str += f"{key}| {value}\n"
|
|
539
534
|
self.db.record_debug(debug_str)
|
|
540
535
|
return True
|
|
541
536
|
|
|
@@ -600,6 +595,9 @@ class PrerequisiteValidator(AmdTool):
|
|
|
600
595
|
with open(target, "rb") as r:
|
|
601
596
|
r.seek(0x70)
|
|
602
597
|
found = struct.unpack("<I", r.read(4))[0] & BIT(21)
|
|
598
|
+
except FileNotFoundError:
|
|
599
|
+
self.db.record_prereq("FADT check unavailable", "🚦")
|
|
600
|
+
return True
|
|
603
601
|
except PermissionError:
|
|
604
602
|
self.db.record_prereq("FADT check unavailable", "🚦")
|
|
605
603
|
return True
|
|
@@ -916,7 +914,7 @@ class PrerequisiteValidator(AmdTool):
|
|
|
916
914
|
devices = []
|
|
917
915
|
for dev in self.pyudev.list_devices(subsystem="pci"):
|
|
918
916
|
devices.append(dev)
|
|
919
|
-
debug_str = "PCI
|
|
917
|
+
debug_str = "PCI Slot | Vendor | Class | ID | ACPI path\n"
|
|
920
918
|
for dev in devices:
|
|
921
919
|
pci_id = dev.properties["PCI_ID"].lower()
|
|
922
920
|
pci_slot_name = dev.properties["PCI_SLOT_NAME"]
|
|
@@ -939,15 +937,12 @@ class PrerequisiteValidator(AmdTool):
|
|
|
939
937
|
p = os.path.join(dev.sys_path, "firmware_node", "path")
|
|
940
938
|
if os.path.exists(p):
|
|
941
939
|
acpi = read_file(p)
|
|
942
|
-
debug_str += (
|
|
943
|
-
f"{prefix}{pci_slot_name} : "
|
|
944
|
-
f"{database_vendor} {database_class} [{pci_id}] : {acpi}\n"
|
|
945
|
-
)
|
|
946
940
|
else:
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
941
|
+
acpi = ""
|
|
942
|
+
debug_str += (
|
|
943
|
+
f"{prefix}{pci_slot_name} | "
|
|
944
|
+
f"{database_vendor} | {database_class} | {pci_id} | {acpi}\n"
|
|
945
|
+
)
|
|
951
946
|
if debug_str:
|
|
952
947
|
self.db.record_debug(debug_str)
|
|
953
948
|
|
|
@@ -964,12 +959,8 @@ class PrerequisiteValidator(AmdTool):
|
|
|
964
959
|
if status == 0:
|
|
965
960
|
continue
|
|
966
961
|
devices.append(dev)
|
|
967
|
-
debug_str = "ACPI name
|
|
962
|
+
debug_str = "ACPI name | ACPI path | Kernel driver\n"
|
|
968
963
|
for dev in devices:
|
|
969
|
-
if dev == devices[-1]:
|
|
970
|
-
prefix = "└─"
|
|
971
|
-
else:
|
|
972
|
-
prefix = "│ "
|
|
973
964
|
p = os.path.join(dev.sys_path, "path")
|
|
974
965
|
pth = read_file(p)
|
|
975
966
|
p = os.path.join(dev.sys_path, "physical_node", "driver")
|
|
@@ -977,7 +968,7 @@ class PrerequisiteValidator(AmdTool):
|
|
|
977
968
|
driver = os.path.basename(os.readlink(p))
|
|
978
969
|
else:
|
|
979
970
|
driver = None
|
|
980
|
-
debug_str += f"{
|
|
971
|
+
debug_str += f"{dev.sys_name} | {pth} | {driver}\n"
|
|
981
972
|
if debug_str:
|
|
982
973
|
self.db.record_debug(debug_str)
|
|
983
974
|
return True
|
|
@@ -1157,7 +1148,6 @@ class PrerequisiteValidator(AmdTool):
|
|
|
1157
1148
|
if not found_iommu:
|
|
1158
1149
|
self.db.record_prereq("IOMMU disabled", "✅")
|
|
1159
1150
|
return True
|
|
1160
|
-
debug_str += "DMA protection:\n"
|
|
1161
1151
|
p = os.path.join("/", "sys", "firmware", "acpi", "tables", "IVRS")
|
|
1162
1152
|
with open(p, "rb") as f:
|
|
1163
1153
|
data = f.read()
|
amd_debug/pstate.py
CHANGED
|
@@ -300,15 +300,17 @@ def parse_args():
|
|
|
300
300
|
return parser.parse_args()
|
|
301
301
|
|
|
302
302
|
|
|
303
|
-
def main():
|
|
303
|
+
def main() -> None|int:
|
|
304
304
|
"""Main function"""
|
|
305
305
|
args = parse_args()
|
|
306
306
|
ret = False
|
|
307
307
|
if args.command == "version":
|
|
308
308
|
print(version())
|
|
309
|
-
return
|
|
309
|
+
return
|
|
310
310
|
elif args.command == "triage":
|
|
311
311
|
triage = AmdPstateTriage(args.tool_debug)
|
|
312
312
|
ret = triage.run()
|
|
313
313
|
show_log_info()
|
|
314
|
-
|
|
314
|
+
if ret is False:
|
|
315
|
+
return 1
|
|
316
|
+
return
|
amd_debug/s2idle.py
CHANGED
|
@@ -120,7 +120,7 @@ def prompt_report_arguments(since, until, fname, fmt, report_debug) -> str:
|
|
|
120
120
|
if report_debug is None:
|
|
121
121
|
inp = (
|
|
122
122
|
input(
|
|
123
|
-
f"{Headers.ReportDebugDescription} ({colorize_choices(Defaults.boolean_choices,
|
|
123
|
+
f"{Headers.ReportDebugDescription} ({colorize_choices(Defaults.boolean_choices, 'true')})? "
|
|
124
124
|
)
|
|
125
125
|
.lower()
|
|
126
126
|
.capitalize()
|
|
@@ -211,6 +211,14 @@ def run_test_cycle(
|
|
|
211
211
|
print("Failed to install dependencies")
|
|
212
212
|
return False
|
|
213
213
|
|
|
214
|
+
try:
|
|
215
|
+
duration, wait, count = prompt_test_arguments(duration, wait, count, rand)
|
|
216
|
+
since, until, fname, fmt, report_debug = prompt_report_arguments(
|
|
217
|
+
datetime.now().isoformat(), Defaults.until.isoformat(), fname, fmt, True
|
|
218
|
+
)
|
|
219
|
+
except KeyboardInterrupt:
|
|
220
|
+
sys.exit("\nTest cancelled")
|
|
221
|
+
|
|
214
222
|
try:
|
|
215
223
|
app = PrerequisiteValidator(debug)
|
|
216
224
|
run = app.run()
|
|
@@ -221,37 +229,32 @@ def run_test_cycle(
|
|
|
221
229
|
|
|
222
230
|
if run or force:
|
|
223
231
|
app = SleepValidator(tool_debug=debug, bios_debug=bios_debug)
|
|
224
|
-
try:
|
|
225
|
-
duration, wait, count = prompt_test_arguments(duration, wait, count, rand)
|
|
226
|
-
since, until, fname, fmt, report_debug = prompt_report_arguments(
|
|
227
|
-
datetime.now().isoformat(), Defaults.until.isoformat(), fname, fmt, True
|
|
228
|
-
)
|
|
229
|
-
except KeyboardInterrupt:
|
|
230
|
-
sys.exit("\nTest cancelled")
|
|
231
232
|
|
|
232
|
-
app.run(
|
|
233
|
+
run = app.run(
|
|
233
234
|
duration=duration,
|
|
234
235
|
wait=wait,
|
|
235
236
|
count=count,
|
|
236
237
|
rand=rand,
|
|
237
238
|
logind=logind,
|
|
238
239
|
)
|
|
240
|
+
else:
|
|
241
|
+
since = None
|
|
242
|
+
until = None
|
|
243
|
+
|
|
244
|
+
app = SleepReport(
|
|
245
|
+
since=since,
|
|
246
|
+
until=until,
|
|
247
|
+
fname=fname,
|
|
248
|
+
fmt=fmt,
|
|
249
|
+
tool_debug=debug,
|
|
250
|
+
report_debug=report_debug,
|
|
251
|
+
)
|
|
252
|
+
app.run()
|
|
239
253
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
until=until,
|
|
243
|
-
fname=fname,
|
|
244
|
-
fmt=fmt,
|
|
245
|
-
tool_debug=debug,
|
|
246
|
-
report_debug=report_debug,
|
|
247
|
-
)
|
|
248
|
-
app.run()
|
|
249
|
-
|
|
250
|
-
# open report in browser if it's html
|
|
251
|
-
display_report_file(fname, fmt)
|
|
254
|
+
# open report in browser if it's html
|
|
255
|
+
display_report_file(fname, fmt)
|
|
252
256
|
|
|
253
|
-
|
|
254
|
-
return False
|
|
257
|
+
return True
|
|
255
258
|
|
|
256
259
|
|
|
257
260
|
def install(debug) -> None:
|
|
@@ -308,10 +311,8 @@ def parse_args():
|
|
|
308
311
|
test_cmd.add_argument(
|
|
309
312
|
"--random",
|
|
310
313
|
action="store_true",
|
|
311
|
-
help=
|
|
312
|
-
|
|
313
|
-
"--duration and --wait arguments as an upper bound",
|
|
314
|
-
),
|
|
314
|
+
help="Run sleep cycles for random durations and wait, using the "
|
|
315
|
+
"--duration and --wait arguments as an upper bound",
|
|
315
316
|
)
|
|
316
317
|
test_cmd.add_argument(
|
|
317
318
|
"--force",
|
|
@@ -393,7 +394,7 @@ def parse_args():
|
|
|
393
394
|
return parser.parse_args()
|
|
394
395
|
|
|
395
396
|
|
|
396
|
-
def main():
|
|
397
|
+
def main() -> None|int:
|
|
397
398
|
"""Main function"""
|
|
398
399
|
args = parse_args()
|
|
399
400
|
ret = False
|
|
@@ -428,8 +429,10 @@ def main():
|
|
|
428
429
|
)
|
|
429
430
|
elif args.action == "version":
|
|
430
431
|
print(version())
|
|
431
|
-
return
|
|
432
|
+
return
|
|
432
433
|
else:
|
|
433
434
|
sys.exit("no action specified")
|
|
434
435
|
show_log_info()
|
|
435
|
-
|
|
436
|
+
if ret is False:
|
|
437
|
+
return 1
|
|
438
|
+
return
|