/src/hwloc/include/hwloc/plugins.h
Line | Count | Source |
1 | | /* |
2 | | * SPDX-License-Identifier: BSD-3-Clause |
3 | | * Copyright © 2013-2025 Inria. All rights reserved. |
4 | | * Copyright © 2016 Cisco Systems, Inc. All rights reserved. |
5 | | * Copyright © 2025 Siemens Corporation and/or its affiliates. All rights reserved. |
6 | | * See COPYING in top-level directory. |
7 | | */ |
8 | | |
9 | | #ifndef HWLOC_PLUGINS_H |
10 | | #define HWLOC_PLUGINS_H |
11 | | |
12 | | /** \file |
13 | | * \brief Public interface for building hwloc plugins. |
14 | | */ |
15 | | |
16 | | struct hwloc_backend; |
17 | | |
18 | | #include "hwloc.h" |
19 | | |
20 | | #ifdef HWLOC_INSIDE_PLUGIN |
21 | | /* needed for hwloc_plugin_check_namespace() */ |
22 | | #ifdef HWLOC_HAVE_LTDL |
23 | | #include <ltdl.h> |
24 | | #elif !defined(HWLOC_WIN_SYS) |
25 | | #include <dlfcn.h> |
26 | | #endif |
27 | | #endif |
28 | | |
29 | | |
30 | | |
31 | | /** \defgroup hwlocality_disc_components Components and Plugins: Discovery components and backends |
32 | | * |
33 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
34 | | * |
35 | | * @{ |
36 | | */ |
37 | | |
38 | | /** \brief Discovery component structure |
39 | | * |
40 | | * This is the major kind of components, taking care of the discovery. |
41 | | * They are registered by generic components, either statically-built or as plugins. |
42 | | */ |
43 | | struct hwloc_disc_component { |
44 | | /** \brief Name. |
45 | | * If this component is built as a plugin, this name does not have to match the plugin filename. |
46 | | */ |
47 | | const char *name; |
48 | | |
49 | | /** \brief Discovery phases performed by this component. |
50 | | * OR'ed set of ::hwloc_disc_phase_t |
51 | | */ |
52 | | unsigned phases; |
53 | | |
54 | | /** \brief Component phases to exclude, as an OR'ed set of ::hwloc_disc_phase_t. |
55 | | * |
56 | | * For a GLOBAL component, this usually includes all other phases (\c ~UL). |
57 | | * |
58 | | * Other components only exclude types that may bring conflicting |
59 | | * topology information. MISC components should likely not be excluded |
60 | | * since they usually bring non-primary additional information. |
61 | | */ |
62 | | unsigned excluded_phases; |
63 | | |
64 | | /** \brief Instantiate callback to create a backend from the component. |
65 | | * Parameters data1, data2, data3 are NULL except for components |
66 | | * that have special enabling routines such as hwloc_topology_set_xml(). */ |
67 | | struct hwloc_backend * (*instantiate)(struct hwloc_topology *topology, struct hwloc_disc_component *component, unsigned excluded_phases, const void *data1, const void *data2, const void *data3); |
68 | | |
69 | | /** \brief Component priority. |
70 | | * Used to sort topology->components, higher priority first. |
71 | | * Also used to decide between two components with the same name. |
72 | | * |
73 | | * Usual values are |
74 | | * 50 for native OS (or platform) components, |
75 | | * 45 for x86, |
76 | | * 40 for no-OS fallback, |
77 | | * 30 for global components (xml, synthetic), |
78 | | * 20 for pci, |
79 | | * 10 for other misc components (opencl etc.). |
80 | | */ |
81 | | unsigned priority; |
82 | | |
83 | | /** \brief Enabled by default. |
84 | | * If unset, if will be disabled unless explicitly requested. |
85 | | */ |
86 | | unsigned enabled_by_default; |
87 | | |
88 | | /** \private Used internally to list components by priority on topology->components |
89 | | * (the component structure is usually read-only, |
90 | | * the core copies it before using this field for queueing) |
91 | | */ |
92 | | struct hwloc_disc_component * next; |
93 | | }; |
94 | | |
95 | | /** \brief Discovery phase */ |
96 | | typedef enum hwloc_disc_phase_e { |
97 | | /** \brief xml or synthetic, platform-specific components. |
98 | | * Discovers everything including CPU, memory, I/O and everything else. |
99 | | * A component with a Global phase usually excludes all other phases. |
100 | | * \hideinitializer */ |
101 | | HWLOC_DISC_PHASE_GLOBAL = (1U<<0), |
102 | | |
103 | | /** \brief CPU discovery. |
104 | | * \hideinitializer */ |
105 | | HWLOC_DISC_PHASE_CPU = (1U<<1), |
106 | | |
107 | | /** \brief Attach memory to existing CPU objects. |
108 | | * \hideinitializer */ |
109 | | HWLOC_DISC_PHASE_MEMORY = (1U<<2), |
110 | | |
111 | | /** \brief Attach PCI devices and bridges to existing CPU objects. |
112 | | * \hideinitializer */ |
113 | | HWLOC_DISC_PHASE_PCI = (1U<<3), |
114 | | |
115 | | /** \brief I/O discovery that requires PCI devices (OS devices such as OpenCL, CUDA, etc.). |
116 | | * \hideinitializer */ |
117 | | HWLOC_DISC_PHASE_IO = (1U<<4), |
118 | | |
119 | | /** \brief Misc objects that gets added below anything else. |
120 | | * \hideinitializer */ |
121 | | HWLOC_DISC_PHASE_MISC = (1U<<5), |
122 | | |
123 | | /** \brief Annotating existing objects, adding distances, etc. |
124 | | * \hideinitializer */ |
125 | | HWLOC_DISC_PHASE_ANNOTATE = (1U<<6), |
126 | | |
127 | | /** \brief Final tweaks to a ready-to-use topology. |
128 | | * This phase runs once the topology is loaded, before it is returned to the topology. |
129 | | * Hence it may only use the main hwloc API for modifying the topology, |
130 | | * for instance by restricting it, adding info attributes, etc. |
131 | | * \hideinitializer */ |
132 | | HWLOC_DISC_PHASE_TWEAK = (1U<<7) |
133 | | } hwloc_disc_phase_t; |
134 | | |
135 | | /** \brief Discovery status flags */ |
136 | | enum hwloc_disc_status_flag_e { |
137 | | /** \brief The sets of allowed resources were already retrieved \hideinitializer */ |
138 | | HWLOC_DISC_STATUS_FLAG_GOT_ALLOWED_RESOURCES = (1UL<<1) |
139 | | }; |
140 | | |
141 | | /** \brief Discovery status structure |
142 | | * |
143 | | * Used by the core and backends to inform about what has been/is being done |
144 | | * during the discovery process. |
145 | | */ |
146 | | struct hwloc_disc_status { |
147 | | /** \brief The current discovery phase that is performed. |
148 | | * Must match one of the phases in the component phases field. |
149 | | */ |
150 | | hwloc_disc_phase_t phase; |
151 | | |
152 | | /** \brief Dynamically excluded phases. |
153 | | * If a component decides during discovery that some phases are no longer needed. |
154 | | */ |
155 | | unsigned excluded_phases; |
156 | | |
157 | | /** \brief OR'ed set of ::hwloc_disc_status_flag_e */ |
158 | | unsigned long flags; |
159 | | }; |
160 | | |
161 | | /** \brief Discovery backend structure |
162 | | * |
163 | | * A backend is the instantiation of a discovery component. |
164 | | * When a component gets enabled for a topology, |
165 | | * its instantiate() callback creates a backend. |
166 | | * |
167 | | * hwloc_backend_alloc() initializes all fields to default values |
168 | | * that the component may change (except "component" and "next") |
169 | | * before enabling the backend with hwloc_backend_enable(). |
170 | | * |
171 | | * Most backends assume that the topology is_thissystem flag is |
172 | | * set because they talk to the underlying operating system. |
173 | | * However they may still be used in topologies without the |
174 | | * is_thissystem flag for debugging reasons. |
175 | | * In practice, they are usually auto-disabled in such cases |
176 | | * (excluded by xml or synthetic backends, or by environment |
177 | | * variables when changing the Linux fsroot or the x86 cpuid path). |
178 | | */ |
179 | | struct hwloc_backend { |
180 | | /** \private Reserved for the core, set by hwloc_backend_alloc() */ |
181 | | struct hwloc_disc_component * component; |
182 | | /** \private Reserved for the core, set by hwloc_backend_enable() */ |
183 | | struct hwloc_topology * topology; |
184 | | /** \private Reserved for the core. Set to 1 if forced through envvar, 0 otherwise. */ |
185 | | int envvar_forced; |
186 | | /** \private Reserved for the core. Used internally to list backends topology->backends. */ |
187 | | struct hwloc_backend * next; |
188 | | |
189 | | /** \brief Discovery phases performed by this component, possibly without some of them if excluded by other components. |
190 | | * OR'ed set of ::hwloc_disc_phase_t |
191 | | */ |
192 | | unsigned phases; |
193 | | |
194 | | /** \brief Backend flags, currently always 0. */ |
195 | | unsigned long flags; |
196 | | |
197 | | /** \brief Backend-specific 'is_thissystem' property. |
198 | | * Set to 0 if the backend disables the thissystem flag for this topology |
199 | | * (e.g. loading from xml or synthetic string, |
200 | | * or using a different fsroot on Linux, or a x86 CPUID dump). |
201 | | * Set to -1 if the backend doesn't care (default). |
202 | | */ |
203 | | int is_thissystem; |
204 | | |
205 | | /** \brief Callback for freeing things stored inside the private data. |
206 | | * May be NULL. |
207 | | */ |
208 | | void (*disable)(struct hwloc_backend *backend); |
209 | | |
210 | | /** \brief Main discovery callback. |
211 | | * returns -1 on error, either because it couldn't add its objects ot the existing topology, |
212 | | * or because of an actual discovery/gathering failure. |
213 | | * May be NULL. |
214 | | */ |
215 | | int (*discover)(struct hwloc_backend *backend, struct hwloc_disc_status *status); |
216 | | |
217 | | /** \brief Callback to retrieve the locality of a PCI object. |
218 | | * Called by the PCI core when attaching PCI hierarchy to CPU objects. |
219 | | * May be NULL. |
220 | | */ |
221 | | int (*get_pci_busid_cpuset)(struct hwloc_backend *backend, struct hwloc_pcidev_attr_s *busid, hwloc_bitmap_t cpuset); |
222 | | }; |
223 | | |
224 | | /** \brief Return the private data pointer at the end of a backend structure. */ |
225 | | #define HWLOC_BACKEND_PRIVATE_DATA(_backend) (void*)(((char*)(_backend)) + sizeof(struct hwloc_backend)) |
226 | | |
227 | | /** \brief Allocate a backend structure, set good default values, initialize backend->component and topology, etc. |
228 | | * The caller will then modify whatever needed, and call hwloc_backend_enable(). |
229 | | * If \p private_data_size is positive, additional space is allocated at the end |
230 | | * of the structure for storing backend private data. That space may be obtained |
231 | | * with HWLOC_BACKEND_PRIVATE_DATA() and may be freely modified by the backend. |
232 | | */ |
233 | | HWLOC_DECLSPEC struct hwloc_backend * hwloc_backend_alloc(struct hwloc_topology *topology, struct hwloc_disc_component *component, unsigned long private_data_size); |
234 | | |
235 | | /** \brief Enable a previously allocated and setup backend. */ |
236 | | HWLOC_DECLSPEC int hwloc_backend_enable(struct hwloc_backend *backend); |
237 | | |
238 | | /** @} */ |
239 | | |
240 | | |
241 | | |
242 | | |
243 | | /** \defgroup hwlocality_generic_components Components and Plugins: Generic components |
244 | | * |
245 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
246 | | * |
247 | | * @{ |
248 | | */ |
249 | | |
250 | | /** \brief Generic component type */ |
251 | | typedef enum hwloc_component_type_e { |
252 | | /** \brief The data field must point to a struct hwloc_disc_component. */ |
253 | | HWLOC_COMPONENT_TYPE_DISC, |
254 | | |
255 | | /** \brief The data field must point to a struct hwloc_xml_component. */ |
256 | | HWLOC_COMPONENT_TYPE_XML |
257 | | } hwloc_component_type_t; |
258 | | |
259 | | /** \brief Generic component structure |
260 | | * |
261 | | * Generic components structure, either statically listed by configure in static-components.h |
262 | | * or dynamically loaded as a plugin. |
263 | | */ |
264 | | struct hwloc_component { |
265 | | /** \brief Component ABI version, set to ::HWLOC_COMPONENT_ABI */ |
266 | | unsigned abi; |
267 | | |
268 | | /** \brief Process-wide component initialization callback. |
269 | | * |
270 | | * This optional callback is called when the component is registered |
271 | | * to the hwloc core (after loading the plugin). |
272 | | * |
273 | | * When the component is built as a plugin, this callback |
274 | | * should call hwloc_check_plugin_namespace() |
275 | | * and return an negative error code on error. |
276 | | * |
277 | | * \p flags is always 0 for now. |
278 | | * |
279 | | * \return 0 on success, or a negative code on error. |
280 | | * |
281 | | * \note If the component uses ltdl for loading its own plugins, |
282 | | * it should load/unload them only in init() and finalize(), |
283 | | * to avoid race conditions with hwloc's use of ltdl. |
284 | | */ |
285 | | int (*init)(unsigned long flags); |
286 | | |
287 | | /** \brief Process-wide component termination callback. |
288 | | * |
289 | | * This optional callback is called after unregistering the component |
290 | | * from the hwloc core (before unloading the plugin). |
291 | | * |
292 | | * \p flags is always 0 for now. |
293 | | * |
294 | | * \note If the component uses ltdl for loading its own plugins, |
295 | | * it should load/unload them only in init() and finalize(), |
296 | | * to avoid race conditions with hwloc's use of ltdl. |
297 | | */ |
298 | | void (*finalize)(unsigned long flags); |
299 | | |
300 | | /** \brief Component type */ |
301 | | hwloc_component_type_t type; |
302 | | |
303 | | /** \brief Component flags, unused for now */ |
304 | | unsigned long flags; |
305 | | |
306 | | /** \brief Component data, pointing to a struct hwloc_disc_component or struct hwloc_xml_component. */ |
307 | | void * data; |
308 | | }; |
309 | | |
310 | | /** \brief Make sure that plugins can lookup core symbols. |
311 | | * |
312 | | * This is a sanity check to avoid lazy-lookup failures when libhwloc |
313 | | * is loaded within a plugin, and later tries to load its own plugins. |
314 | | * This may fail (and abort the program) if libhwloc symbols are in a |
315 | | * private namespace. |
316 | | * |
317 | | * \return 0 on success. |
318 | | * \return -1 if the plugin cannot be successfully loaded. The caller |
319 | | * plugin init() callback should return a negative error code as well. |
320 | | * |
321 | | * Plugins should call this function in their init() callback to avoid |
322 | | * later crashes if lazy symbol resolution is used by the upper layer that |
323 | | * loaded hwloc (e.g. OpenCL implementations using dlopen with RTLD_LAZY). |
324 | | * |
325 | | * \note The build system must define HWLOC_INSIDE_PLUGIN if and only if |
326 | | * building the caller as a plugin. |
327 | | * |
328 | | * \note This function should remain inline so plugins can call it even |
329 | | * when they cannot find libhwloc symbols. |
330 | | */ |
331 | | static __hwloc_inline int |
332 | | hwloc_plugin_check_namespace(const char *pluginname __hwloc_attribute_unused, const char *symbol __hwloc_attribute_unused) |
333 | 0 | { |
334 | 0 | #ifdef HWLOC_INSIDE_PLUGIN |
335 | 0 | void *sym; |
336 | 0 | #ifdef HWLOC_HAVE_LTDL |
337 | 0 | lt_dlhandle handle = lt_dlopen(NULL); |
338 | 0 | #elif defined(HWLOC_WIN_SYS) |
339 | 0 | HMODULE handle = GetModuleHandleA(NULL); |
340 | 0 | #else |
341 | 0 | void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL); |
342 | 0 | #endif |
343 | 0 | if (!handle) |
344 | 0 | /* cannot check, assume things will work */ |
345 | 0 | return 0; |
346 | 0 | #ifdef HWLOC_HAVE_LTDL |
347 | 0 | sym = lt_dlsym(handle, symbol); |
348 | 0 | lt_dlclose(handle); |
349 | 0 | #elif defined(HWLOC_WIN_SYS) |
350 | 0 | sym = GetModuleHandleA("hwloc.dll"); |
351 | 0 | FreeLibrary(handle); |
352 | 0 | #else |
353 | 0 | sym = dlsym(handle, symbol); |
354 | 0 | dlclose(handle); |
355 | 0 | #endif |
356 | 0 | if (!sym) { |
357 | 0 | static int verboseenv_checked = 0; |
358 | 0 | static int verboseenv_value = 0; |
359 | 0 | if (!verboseenv_checked) { |
360 | 0 | const char *verboseenv = getenv("HWLOC_PLUGINS_VERBOSE"); |
361 | 0 | verboseenv_value = verboseenv ? atoi(verboseenv) : 0; |
362 | 0 | verboseenv_checked = 1; |
363 | 0 | } |
364 | 0 | if (verboseenv_value) |
365 | 0 | fprintf(stderr, "Plugin `%s' disabling itself because it cannot find the `%s' core symbol.\n", |
366 | 0 | pluginname, symbol); |
367 | 0 | return -1; |
368 | 0 | } |
369 | 0 | #endif /* HWLOC_INSIDE_PLUGIN */ |
370 | 0 | return 0; |
371 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_plugin_check_namespace Unexecuted instantiation: base64.c:hwloc_plugin_check_namespace |
372 | | |
373 | | /** @} */ |
374 | | |
375 | | |
376 | | |
377 | | |
378 | | /** \defgroup hwlocality_components_core_funcs Components and Plugins: Core functions to be used by components |
379 | | * |
380 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
381 | | * |
382 | | * @{ |
383 | | */ |
384 | | |
385 | | /** \brief Get the mask of error messages to display |
386 | | * |
387 | | * The mask is a OR'ed set of HWLOC_SHOWMSG_* as defined below. |
388 | | * |
389 | | * By default, only critical errors are shown. |
390 | | * May be configured with the HWLOC_SHOW_ERRORS envvar |
391 | | * (or the obsolete HWLOC_HIDE_ERRORS). |
392 | | * lstopo enables all error messages (HWLOC_SHOW_ERRORS=all). |
393 | | * hwloc-bind enables binding error messages (HWLOC_SHOW_ERRORS=bind). |
394 | | */ |
395 | | HWLOC_DECLSPEC unsigned long hwloc_show_errors_mask(void); |
396 | | |
397 | | #define HWLOC_SHOW_ERRORS(_flag) (hwloc_show_errors_mask() & (_flag)) |
398 | | |
399 | | #define HWLOC_SHOWMSG_CRITICAL (1UL<<0) |
400 | | /* non-critical messages: |
401 | | * failure to initialize CUDA, etc. */ |
402 | | #define HWLOC_SHOWMSG_BIND (1UL<<1) /* binding */ |
403 | | #define HWLOC_SHOWMSG_SYNTHETIC (1UL<<2) /* synthetic */ |
404 | | #define HWLOC_SHOWMSG_XML (1UL<<3) /* XML */ |
405 | | #define HWLOC_SHOWMSG_COMPONENTS (1UL<<4) /* Components */ |
406 | | #define HWLOC_SHOWMSG_PLUGINS (1UL<<5) /* Plugins */ |
407 | | /* all messages */ |
408 | | #define HWLOC_SHOWMSG_ALL (~0UL) |
409 | | |
410 | | /* backward compatibility until all callers are converted to passing a mask */ |
411 | | #define HWLOC_SHOW_CRITICAL_ERRORS() HWLOC_SHOW_ERRORS(HWLOC_SHOWMSG_CRITICAL) |
412 | | #define HWLOC_SHOW_ALL_ERRORS() HWLOC_SHOW_ERRORS(HWLOC_SHOWMSG_ALL) |
413 | | |
414 | | |
415 | | /** \brief Add an object to the topology. |
416 | | * |
417 | | * Insert new object \p obj in the topology starting under existing object \p root |
418 | | * (if \c NULL, the topology root object is used). |
419 | | * |
420 | | * It is sorted along the tree of other objects according to the inclusion of |
421 | | * cpusets, to eventually be added as a child of the smallest object including |
422 | | * this object. |
423 | | * |
424 | | * If the cpuset is empty, the type of the object (and maybe some attributes) |
425 | | * must be enough to find where to insert the object. This is especially true |
426 | | * for NUMA nodes with memory and no CPUs. |
427 | | * |
428 | | * The given object should not have children. |
429 | | * |
430 | | * This shall only be called before levels are built. |
431 | | * |
432 | | * The caller should check whether the object type is filtered-out before calling this function. |
433 | | * |
434 | | * The topology cpuset/nodesets will be enlarged to include the object sets. |
435 | | * |
436 | | * \p reason is a unique string identifying where and why this insertion call was performed |
437 | | * (it will be displayed in case of internal insertion error). |
438 | | * |
439 | | * Returns the object on success. |
440 | | * Returns NULL and frees obj on error. |
441 | | * Returns another object and frees obj if it was merged with an identical pre-existing object. |
442 | | */ |
443 | | HWLOC_DECLSPEC hwloc_obj_t |
444 | | hwloc__insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t root, |
445 | | hwloc_obj_t obj, const char *reason); |
446 | | |
447 | | /** \brief Insert an object somewhere in the topology. |
448 | | * |
449 | | * It is added as the last child of the given parent. |
450 | | * The cpuset is completely ignored, so strange objects such as I/O devices should |
451 | | * preferably be inserted with this. |
452 | | * |
453 | | * When used for "normal" children with cpusets (when importing from XML |
454 | | * when duplicating a topology), the caller should make sure that: |
455 | | * - children are inserted in order, |
456 | | * - children cpusets do not intersect. |
457 | | * |
458 | | * The given object may have normal, I/O or Misc children, as long as they are in order as well. |
459 | | * These children must have valid parent and next_sibling pointers. |
460 | | * |
461 | | * The caller should check whether the object type is filtered-out before calling this function. |
462 | | */ |
463 | | HWLOC_DECLSPEC void hwloc_insert_object_by_parent(struct hwloc_topology *topology, hwloc_obj_t parent, hwloc_obj_t obj); |
464 | | |
465 | | /** \brief Allocate and initialize an object of the given type and physical index. |
466 | | * |
467 | | * If \p os_index is unknown or irrelevant, use \c HWLOC_UNKNOWN_INDEX. |
468 | | */ |
469 | | HWLOC_DECLSPEC hwloc_obj_t hwloc_alloc_setup_object(hwloc_topology_t topology, hwloc_obj_type_t type, unsigned os_index); |
470 | | |
471 | | /** \brief Setup object cpusets/nodesets by OR'ing its children. |
472 | | * |
473 | | * Used when adding an object late in the topology. |
474 | | * Will update the new object by OR'ing all its new children sets. |
475 | | * |
476 | | * Used when PCI backend adds a hostbridge parent, when distances |
477 | | * add a new Group, etc. |
478 | | */ |
479 | | HWLOC_DECLSPEC int hwloc_obj_add_children_sets(hwloc_obj_t obj); |
480 | | |
481 | | /** \brief Request a reconnection of children and levels in the topology. |
482 | | * |
483 | | * May be used by backends during discovery if they need arrays or lists |
484 | | * of object within levels or children to be fully connected. |
485 | | * |
486 | | * \p flags is currently unused, must 0. |
487 | | */ |
488 | | HWLOC_DECLSPEC int hwloc_topology_reconnect(hwloc_topology_t topology, unsigned long flags __hwloc_attribute_unused); |
489 | | |
490 | | /** @} */ |
491 | | |
492 | | |
493 | | |
494 | | |
495 | | /** \defgroup hwlocality_components_filtering Components and Plugins: Filtering objects |
496 | | * |
497 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
498 | | * |
499 | | * @{ |
500 | | */ |
501 | | |
502 | | /** \brief Check whether the given PCI device classid is important. |
503 | | * |
504 | | * \return 1 if important, 0 otherwise. |
505 | | */ |
506 | | static __hwloc_inline int |
507 | | hwloc_filter_check_pcidev_subtype_important(unsigned classid) |
508 | 0 | { |
509 | 0 | unsigned baseclass = classid >> 8; |
510 | 0 | return (baseclass == 0x03 /* PCI_BASE_CLASS_DISPLAY */ |
511 | 0 | || baseclass == 0x02 /* PCI_BASE_CLASS_NETWORK */ |
512 | 0 | || baseclass == 0x01 /* PCI_BASE_CLASS_STORAGE */ |
513 | 0 | || baseclass == 0x00 /* Unclassified, for Atos/Bull BXI */ |
514 | 0 | || baseclass == 0x0b /* PCI_BASE_CLASS_PROCESSOR */ |
515 | 0 | || classid == 0x0c04 /* PCI_CLASS_SERIAL_FIBER */ |
516 | 0 | || classid == 0x0c06 /* PCI_CLASS_SERIAL_INFINIBAND */ |
517 | 0 | || classid == 0x0502 /* PCI_CLASS_MEMORY_CXL */ |
518 | 0 | || baseclass == 0x06 /* PCI_BASE_CLASS_BRIDGE with non-PCI downstream. the core will drop the useless ones later */ |
519 | 0 | || baseclass == 0x12 /* Processing Accelerators */); |
520 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_filter_check_pcidev_subtype_important Unexecuted instantiation: base64.c:hwloc_filter_check_pcidev_subtype_important |
521 | | |
522 | | /** \brief Check whether the given OS device subtype is important. |
523 | | * |
524 | | * \return 1 if important, 0 otherwise. |
525 | | */ |
526 | | static __hwloc_inline int |
527 | | hwloc_filter_check_osdev_subtype_important(hwloc_obj_osdev_types_t subtype) |
528 | 0 | { |
529 | 0 | return (subtype && subtype != HWLOC_OBJ_OSDEV_DMA); |
530 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_filter_check_osdev_subtype_important Unexecuted instantiation: base64.c:hwloc_filter_check_osdev_subtype_important |
531 | | |
532 | | /** \brief Check whether a non-I/O object type should be filtered-out. |
533 | | * |
534 | | * Cannot be used for I/O objects. |
535 | | * |
536 | | * \return 1 if the object type should be kept, 0 otherwise. |
537 | | */ |
538 | | static __hwloc_inline int |
539 | | hwloc_filter_check_keep_object_type(hwloc_topology_t topology, hwloc_obj_type_t type) |
540 | 0 | { |
541 | 0 | enum hwloc_type_filter_e filter = HWLOC_TYPE_FILTER_KEEP_NONE; |
542 | 0 | hwloc_topology_get_type_filter(topology, type, &filter); |
543 | 0 | assert(filter != HWLOC_TYPE_FILTER_KEEP_IMPORTANT); /* IMPORTANT only used for I/O */ |
544 | 0 | return filter == HWLOC_TYPE_FILTER_KEEP_NONE ? 0 : 1; |
545 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_filter_check_keep_object_type Unexecuted instantiation: base64.c:hwloc_filter_check_keep_object_type |
546 | | |
547 | | /** \brief Check whether the given object should be filtered-out. |
548 | | * |
549 | | * \return 1 if the object type should be kept, 0 otherwise. |
550 | | */ |
551 | | static __hwloc_inline int |
552 | | hwloc_filter_check_keep_object(hwloc_topology_t topology, hwloc_obj_t obj) |
553 | 0 | { |
554 | 0 | hwloc_obj_type_t type = obj->type; |
555 | 0 | enum hwloc_type_filter_e filter = HWLOC_TYPE_FILTER_KEEP_NONE; |
556 | 0 | hwloc_topology_get_type_filter(topology, type, &filter); |
557 | 0 | if (filter == HWLOC_TYPE_FILTER_KEEP_NONE) |
558 | 0 | return 0; |
559 | 0 | if (filter == HWLOC_TYPE_FILTER_KEEP_IMPORTANT) { |
560 | 0 | if (type == HWLOC_OBJ_PCI_DEVICE) |
561 | 0 | return hwloc_filter_check_pcidev_subtype_important(obj->attr->pcidev.class_id); |
562 | 0 | if (type == HWLOC_OBJ_OS_DEVICE) |
563 | 0 | return hwloc_filter_check_osdev_subtype_important(obj->attr->osdev.types); |
564 | 0 | } |
565 | 0 | return 1; |
566 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_filter_check_keep_object Unexecuted instantiation: base64.c:hwloc_filter_check_keep_object |
567 | | |
568 | | /** @} */ |
569 | | |
570 | | |
571 | | |
572 | | |
573 | | /** \defgroup hwlocality_components_pcidisc Components and Plugins: helpers for PCI discovery |
574 | | * |
575 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
576 | | * |
577 | | * @{ |
578 | | */ |
579 | | |
580 | | /** \brief Return the offset of the given capability in the PCI config space buffer |
581 | | * |
582 | | * This function requires a 256-bytes config space. Unknown/unavailable bytes should be set to 0xff. |
583 | | */ |
584 | | HWLOC_DECLSPEC unsigned hwloc_pcidisc_find_cap(const unsigned char *config, unsigned cap); |
585 | | |
586 | | /** \brief Fill linkspeed by reading the PCI config space where PCI_CAP_ID_EXP is at position offset. |
587 | | * |
588 | | * Needs 20 bytes of EXP capability block starting at offset in the config space |
589 | | * for registers up to link status. |
590 | | */ |
591 | | HWLOC_DECLSPEC int hwloc_pcidisc_find_linkspeed(const unsigned char *config, unsigned offset, float *linkspeed); |
592 | | |
593 | | /** \brief Return the hwloc object type (PCI device or Bridge) for the given class and configuration space. |
594 | | * |
595 | | * This function requires 16 bytes of common configuration header at the beginning of config. |
596 | | */ |
597 | | HWLOC_DECLSPEC hwloc_obj_type_t hwloc_pcidisc_check_bridge_type(unsigned device_class, const unsigned char *config); |
598 | | |
599 | | /** \brief Fills the attributes of the given PCI bridge using the given PCI config space. |
600 | | * |
601 | | * This function requires 32 bytes of common configuration header at the beginning of config. |
602 | | * |
603 | | * Returns -1 and destroys /p obj if bridge fields are invalid. |
604 | | */ |
605 | | HWLOC_DECLSPEC int hwloc_pcidisc_find_bridge_buses(unsigned domain, unsigned bus, unsigned dev, unsigned func, |
606 | | unsigned *secondary_busp, unsigned *subordinate_busp, |
607 | | const unsigned char *config); |
608 | | |
609 | | /** \brief Insert a PCI object in the given PCI tree by looking at PCI bus IDs. |
610 | | * |
611 | | * If \p treep points to \c NULL, the new object is inserted there. |
612 | | */ |
613 | | HWLOC_DECLSPEC void hwloc_pcidisc_tree_insert_by_busid(struct hwloc_obj **treep, struct hwloc_obj *obj); |
614 | | |
615 | | /** \brief Add some hostbridges on top of the given tree of PCI objects and attach them to the topology. |
616 | | * |
617 | | * Other backends may lookup PCI objects or localities (for instance to attach OS devices) |
618 | | * by using hwloc_pcidisc_find_by_busid() or hwloc_pcidisc_find_busid_parent(). |
619 | | */ |
620 | | HWLOC_DECLSPEC int hwloc_pcidisc_tree_attach(struct hwloc_topology *topology, struct hwloc_obj *tree); |
621 | | |
622 | | /** @} */ |
623 | | |
624 | | |
625 | | |
626 | | |
627 | | /** \defgroup hwlocality_components_pcifind Components and Plugins: finding PCI objects during other discoveries |
628 | | * |
629 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
630 | | * |
631 | | * @{ |
632 | | */ |
633 | | |
634 | | /** \brief Find the object or a parent of a PCI bus ID. |
635 | | * |
636 | | * When attaching a new object (typically an OS device) whose locality |
637 | | * is specified by PCI bus ID, this function returns the PCI object |
638 | | * to use as a parent for attaching. |
639 | | * |
640 | | * If the exact PCI device with this bus ID exists, it is returned. |
641 | | * Otherwise (for instance if it was filtered out), the function returns |
642 | | * another object with similar locality (for instance a parent bridge, |
643 | | * or the local CPU Package). |
644 | | */ |
645 | | HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_parent_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func); |
646 | | |
647 | | /** \brief Find the PCI device or bridge matching a PCI bus ID exactly. |
648 | | * |
649 | | * This is useful for adding specific information about some objects |
650 | | * based on their PCI id. When it comes to attaching objects based on |
651 | | * PCI locality, hwloc_pci_find_parent_by_busid() should be preferred. |
652 | | */ |
653 | | HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func); |
654 | | |
655 | | |
656 | | /** @} */ |
657 | | |
658 | | |
659 | | |
660 | | |
661 | | /** \defgroup hwlocality_components_distances Components and Plugins: distances |
662 | | * |
663 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
664 | | * |
665 | | * @{ |
666 | | */ |
667 | | |
668 | | /** \brief Handle to a new distances structure during its addition to the topology. */ |
669 | | typedef void * hwloc_backend_distances_add_handle_t; |
670 | | |
671 | | /** \brief Create a new empty distances structure. |
672 | | * |
673 | | * This is identical to hwloc_distances_add_create() |
674 | | * but this variant is designed for backend inserting |
675 | | * distances during topology discovery. |
676 | | */ |
677 | | HWLOC_DECLSPEC hwloc_backend_distances_add_handle_t |
678 | | hwloc_backend_distances_add_create(hwloc_topology_t topology, |
679 | | const char *name, unsigned long kind, |
680 | | unsigned long flags); |
681 | | |
682 | | /** \brief Specify the objects and values in a new empty distances structure. |
683 | | * |
684 | | * This is similar to hwloc_distances_add_values() |
685 | | * but this variant is designed for backend inserting |
686 | | * distances during topology discovery. |
687 | | * |
688 | | * The only semantical difference is that \p objs and \p values |
689 | | * are not duplicated, but directly attached to the topology. |
690 | | * On success, these arrays are given to the core and should not |
691 | | * ever be freed by the caller anymore. |
692 | | */ |
693 | | HWLOC_DECLSPEC int |
694 | | hwloc_backend_distances_add_values(hwloc_topology_t topology, |
695 | | hwloc_backend_distances_add_handle_t handle, |
696 | | unsigned nbobjs, hwloc_obj_t *objs, |
697 | | hwloc_uint64_t *values, |
698 | | unsigned long flags); |
699 | | |
700 | | /** \brief Commit a new distances structure. |
701 | | * |
702 | | * This is similar to hwloc_distances_add_commit() |
703 | | * but this variant is designed for backend inserting |
704 | | * distances during topology discovery. |
705 | | */ |
706 | | HWLOC_DECLSPEC int |
707 | | hwloc_backend_distances_add_commit(hwloc_topology_t topology, |
708 | | hwloc_backend_distances_add_handle_t handle, |
709 | | unsigned long flags); |
710 | | |
711 | | /** @} */ |
712 | | |
713 | | |
714 | | |
715 | | |
716 | | #endif /* HWLOC_PLUGINS_H */ |