1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
# Copyright (C) 2019-2024 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Support library for testing ROCm (AMD GPU) GDB features.
# ROCM_PATH is used by hipcc as well.
if {[info exists ::env(ROCM_PATH)]} {
set rocm_path $::env(ROCM_PATH)
} else {
set rocm_path "/opt/rocm"
}
# Act as a drop-in replacement for "remote_exec host"
# that logs the failures.
proc log_host_exec { cmd } {
set result [remote_exec host "$cmd"]
set exit_status [lindex $result 0]
if {$exit_status != 0} {
# -1 indicates that $cmd could not be executed at all.
if {$exit_status == -1} {
verbose -log "Cannot execute $cmd."
} else {
verbose -log "$cmd returned an error."
}
}
return $result
}
# Detect available AMDGPU devices.
#
# Return a list of GPU devices that do exist on the system.
# The list will be empty when there's no GPU or the execution
# of rocm_agent_enumerator does not succeed. It is up to the
# caller of this procedure that what should happen when an empty
# list is returned.
gdb_caching_proc find_amdgpu_devices {} {
global rocm_path
set hip_gpu_devices [list]
set enumerator "rocm_agent_enumerator"
set targets ""
# Try the PATH first
set result [log_host_exec "$enumerator"]
if {[lindex $result 0] == 0} {
set targets [lindex $result 1]
} else {
# Now try the ROCM_PATH
set result [log_host_exec "$rocm_path/bin/$enumerator"]
if {[lindex $result 0] == 0} {
set targets [lindex $result 1]
}
}
if {$targets != ""} {
foreach dev $targets {
# Ignore the 'gfx000' device which identifies the host.
if {$dev != "gfx000"} {
lappend hip_gpu_devices $dev
}
}
}
return $hip_gpu_devices
}
# Get the list of GPU targets to compile for.
#
# If HCC_AMDGPU_TARGET is set in the environment, use it.
# Otherwise, consider the devices available on the system.
proc hcc_amdgpu_targets {} {
# First, look for HCC_AMDGPU_TARGET (same env var hipcc uses).
if {[info exists ::env(HCC_AMDGPU_TARGET)]} {
# We don't verify the contents of HCC_AMDGPU_TARGET.
# That's the toolchain's job.
return [split $::env(HCC_AMDGPU_TARGET) ","]
}
return [find_amdgpu_devices]
}
gdb_caching_proc allow_hipcc_tests {} {
# Only the native target supports ROCm debugging. E.g., when
# testing against GDBserver, there's no point in running the ROCm
# tests.
if {[target_info gdb_protocol] != ""} {
return {0 "remote debugging"}
}
if {![istarget "*-linux*"]} {
return {0 "target platform is not Linux"}
}
# Ensure that GDB is built with amd-dbgapi support.
set output [remote_exec host $::GDB "$::INTERNAL_GDBFLAGS --configuration"]
if { [string first "--with-amd-dbgapi" $output] == -1 } {
return {0 "amd-dbgapi not supported"}
}
# Check if there's any GPU device to run the tests on.
set devices [find_amdgpu_devices]
if {[llength $devices] == 0} {
return {0 "no suitable amdgpu targets found"}
}
# Check if we have a working hipcc compiler available.
# TARGETS won't be empty, because there's at least one GPU device.
set targets [hcc_amdgpu_targets]
set flags [list hip additional_flags=--offload-arch=[join $targets ","]]
if {![gdb_simple_compile hipprobe {
#include <hip/hip_runtime.h>
__global__ void
kern () {}
int
main ()
{
kern<<<1, 1>>> ();
if (hipDeviceSynchronize () != hipSuccess)
return -1;
return 0;
}
} executable $flags]} {
return {0 "failed to compile hip program"}
}
return 1
}
# The lock file used to ensure that only one GDB has access to the GPU
# at a time.
set gpu_lock_filename gpu-parallel.lock
# Run body under the GPU lock. Also calls gdb_exit before releasing
# the GPU lock.
proc with_rocm_gpu_lock { body } {
with_lock $::gpu_lock_filename {uplevel 1 $body}
# In case BODY returned early due to some testcase failing, and
# left GDB running, debugging the GPU.
gdb_exit
}
# Return true if all the devices support debugging multiple processes
# using the GPU.
proc hip_devices_support_debug_multi_process {} {
set unsupported_targets \
{gfx900 gfx906 gfx908 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032}
set targets [find_amdgpu_devices]
if { [llength $targets] == 0 } {
return 0
}
foreach target $targets {
if { [lsearch -exact $unsupported_targets $target] != -1 } {
return 0
}
}
return 1
}
# Return true if all the devices on the host support precise memory.
proc hip_devices_support_precise_memory {} {
set unsupported_targets \
{gfx900 gfx906 gfx908 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032}
set targets [find_amdgpu_devices]
if { [llength $targets] == 0 } {
return 0
}
foreach target $targets {
if { [lsearch -exact $unsupported_targets $target] != -1 } {
return 0
}
}
return 1
}
|