plugins.h 24 KB

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