pax_global_header00006660000000000000000000000064132765415060014523gustar00rootroot0000000000000052 comment=eef62146748bd8a4916c42d5340394376e812f1d libcxl-1.7/000077500000000000000000000000001327654150600126475ustar00rootroot00000000000000libcxl-1.7/.gitignore000066400000000000000000000000651327654150600146400ustar00rootroot00000000000000*.d *.o *.so *.a *~ *.orig .*.swp include/misc/cxl.h libcxl-1.7/LICENSE000066400000000000000000000261361327654150600136640ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. libcxl-1.7/Makefile000066400000000000000000000044171327654150600143150ustar00rootroot00000000000000srcdir = $(PWD) include Makefile.vars OBJS = libcxl.o libcxl_sysfs.o CFLAGS += -I include # change VERS_LIB if new git tag VERS_LIB = 1.7 LIBNAME = libcxl.so.$(VERS_LIB) # change VERS_SONAME only if library breaks backward compatibility. # refer to file symver.map VERS_SONAME=1 LIBSONAME = libcxl.so.$(VERS_SONAME) SONAMEOPT = -Wl,-soname,$(LIBSONAME) all: check_cxl_header $(LIBSONAME) libcxl.so libcxl.a HAS_WGET = $(shell /bin/which wget > /dev/null 2>&1 && echo y || echo n) HAS_CURL = $(shell /bin/which curl > /dev/null 2>&1 && echo y || echo n) # Update this to test a single feature from the most recent header we require: CHECK_CXL_HEADER_IS_UP_TO_DATE = $(shell /bin/echo -e \\\#include $(1)\\\nint i = CXL_START_WORK_TID\; | \ $(CC) $(CFLAGS) -Werror -x c -S -o /dev/null - >/dev/null 2>&1 && echo y || echo n) check_cxl_header: ifeq ($(call CHECK_CXL_HEADER_IS_UP_TO_DATE,""),n) mkdir -p include/misc ifeq (${HAS_WGET},y) $(call Q,WGET include/misc/cxl.h, wget -O include/misc/cxl.h -q http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/include/uapi/misc/cxl.h) else ifeq (${HAS_CURL},y) $(call Q,CURL include/misc/cxl.h, curl -o include/misc/cxl.h -s http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/include/uapi/misc/cxl.h) else $(error 'cxl.h is non-existant or out of date, Download from http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/include/uapi/misc/cxl.h and place in ${PWD}/include/misc/cxl.h') endif endif libcxl.o libcxl_sysfs.o : CFLAGS += -fPIC libcxl.so: $(LIBNAME) ln -sf $(LIBNAME) libcxl.so $(LIBSONAME): $(LIBNAME) ln -sf $(LIBNAME) $(LIBSONAME) $(LIBNAME): libcxl.o libcxl_sysfs.o symver.map $(call Q,CC, $(CC) $(CFLAGS) $(LDFLAGS) -shared libcxl.o libcxl_sysfs.o -o $(LIBNAME), $(LIBNAME)) -Wl,--version-script symver.map $(SONAMEOPT) libcxl.a: libcxl.o libcxl_sysfs.o $(call Q,AR, ar rcs libcxl.a libcxl.o libcxl_sysfs.o, libcxl.a) include Makefile.rules clean: rm -f *.o *.d libcxl.so* libcxl.a include/misc/cxl.h install: all mkdir -p $(DESTDIR)$(libdir) mkdir -p $(DESTDIR)$(includedir) install -m 0755 $(LIBNAME) $(DESTDIR)$(libdir)/ cp -d libcxl.so $(LIBSONAME) $(DESTDIR)$(libdir)/ install -m 0644 libcxl.h $(DESTDIR)$(includedir)/ .PHONY: clean all install libcxl-1.7/Makefile.rules000066400000000000000000000011011327654150600154310ustar00rootroot00000000000000# Basic makefile rules -include $(OBJS:.o=.d) ifdef V VERBOSE:= $(V) else VERBOSE:= 0 endif ifeq ($(VERBOSE),1) define Q $(2) endef else define Q @/bin/echo -e " [$1]\t$(3)" @$(2) endef endif %.o : %.c $(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<, $@) $(call Q,CC, $(CC) -MM $(CPPFLAGS) $(CFLAGS) $^ > $*.d, $*.d) $(call Q,SED, sed -i -e "s#^$(@F)#$@#" $*.d, $*.d) ifeq ($(BIT32),y) libdir = $(prefix)/lib else libdir = $(prefix)/lib64 endif prefix = /usr/local/ datadir = $(prefix)/share includedir = $(prefix)/include mandir = $(datadir)/man libcxl-1.7/Makefile.vars000066400000000000000000000003321327654150600152570ustar00rootroot00000000000000# Disable built-in rules MAKEFLAGS += -rR AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld CC = $(CROSS_COMPILE)gcc CFLAGS += -g -Wall -Werror -O2 -I$(CURDIR) ifeq ($(BIT32),y) CFLAGS += -m32 else CFLAGS += -m64 endif libcxl-1.7/README.md000066400000000000000000000024121327654150600141250ustar00rootroot00000000000000libcxl ====== The coherent accelerator interface is designed to allow the coherent connection of accelerators (FPGAs and other devices) to a POWER system. Coherent in this context means that the accelerator and CPUs can both access system memory directly and with the same effective addresses. IBM refers to this as the Coherent Accelerator Processor Interface (CAPI). In the Linux world it is referred to by the name CXL to avoid confusion with the ISDN CAPI subsystem. The Linux kernel interacts with the device POWER Service Layer (PSL). Userland interacts with the device Accelerator Function Unit (AFU). See the Linux kernel source file [Documentation/powerpc/cxl.txt][1] for a detailed description of the coherent accelerator interface. The CXL library provides a userland API to coherently attached devices. CXL devices can be enumerated. Their capabilities can be queried. AFUs can be opened, attached to the current process, and started. Jobs, described by AFU specific Work Element Descriptors (WEDs), can be submitted and executed by AFUs. AFU MMIO space can be mapped into the current process memory, and AFUs can be configured and controlled via MMIO reads and writes. [1]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/Documentation/powerpc/cxl.txt libcxl-1.7/libcxl.c000066400000000000000000000703031327654150600142730ustar00rootroot00000000000000/* * Copyright 2014,2015 International Business Machines * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE /* For asprintf */ #define _DEFAULT_SOURCE #define __STDC_FORMAT_MACROS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libcxl.h" #include #include "libcxl_internal.h" #if defined CXL_START_WORK_TID #include #endif #undef DEBUG #ifdef DEBUG #define _s1(x) #x #define _s(x) _s1(x) #define pr_devel(...) \ fprintf(stderr, _s(__FILE__) ":" _s(__LINE__) ": " __VA_ARGS__ ); #define pr_here() \ pr_devel("<-- DEBUG TRACE -->\n"); #else #define pr_devel(...) do { } while (0); #define pr_here() do { } while (0); #endif #define CXL_EVENT_READ_FAIL 0xffff static struct cxl_adapter_h * malloc_adapter(void) { struct cxl_adapter_h *adapter; if (!(adapter = malloc(sizeof(struct cxl_adapter_h)))) return NULL; memset(adapter, 0, sizeof(struct cxl_adapter_h)); return adapter; } char * cxl_adapter_dev_name(struct cxl_adapter_h *adapter) { return adapter->enum_ent->d_name; } static struct cxl_afu_h * malloc_afu(void) { struct cxl_afu_h *afu; if (!(afu = malloc(sizeof(struct cxl_afu_h)))) return NULL; memset(afu, 0, sizeof(struct cxl_afu_h)); afu->fd = -1; afu->process_element = -1; afu->mmio_addr = NULL; afu->dev_name = NULL; afu->sysfs_path = NULL; afu->fd_errbuff = -1; afu->errbuff_size = -1; #if defined CXL_START_WORK_TID afu->pid = -1; #endif return afu; } char * cxl_afu_dev_name(struct cxl_afu_h *afu) { if (afu->enum_ent) return afu->enum_ent->d_name; return afu->dev_name; } int cxl_afu_fd(struct cxl_afu_h *afu) { return afu->fd; } /* * Adapter Enumeration */ static int is_cxl_adapter_filename(char *name) { int rc; regex_t preg; if (*name != 'c') return 0; if (regcomp(&preg, "^card[0-9]\\+$", REG_NOSUB)) return 0; rc = (regexec(&preg, name, 0, NULL, 0) != REG_NOMATCH); regfree(&preg); return rc; } static int is_cxl_afu_filename(char *name) { int rc; regex_t preg; if (*name != 'a') return 0; if (regcomp(&preg, "^afu[0-9]\\+\\.[0-9]\\+$", REG_NOSUB)) return 0; rc = (regexec(&preg, name, 0, NULL, 0) != REG_NOMATCH); regfree(&preg); return rc; } static int cxl_sysfs_adapter(char **bufp, struct cxl_adapter_h *adapter) { return asprintf(bufp, CXL_SYSFS_CLASS"/%s", cxl_adapter_dev_name(adapter)); } struct cxl_adapter_h * cxl_adapter_next(struct cxl_adapter_h *adapter) { if (adapter == NULL) { if (!(adapter = malloc_adapter())) return NULL; memset(adapter, 0, sizeof(struct cxl_adapter_h)); if (!(adapter->enum_dir = opendir(CXL_SYSFS_CLASS))) { if (errno == ENOENT) errno = ENODEV; goto end; } } errno = 0; do { if (!(adapter->enum_ent = readdir(adapter->enum_dir))) goto end; } while (!is_cxl_adapter_filename(adapter->enum_ent->d_name)); if (cxl_sysfs_adapter(&adapter->sysfs_path, adapter) == -1) goto end; return adapter; end: cxl_adapter_free(adapter); return NULL; } void cxl_adapter_free(struct cxl_adapter_h *adapter) { if (!adapter) return; if (adapter->enum_dir) closedir(adapter->enum_dir); if (adapter->sysfs_path) free(adapter->sysfs_path); free(adapter); } /* * AFU Enumeration */ static void _cxl_afu_free(struct cxl_afu_h *afu, int free_adapter) { if (!afu) return; if (afu->enum_dir) closedir(afu->enum_dir); if (afu->sysfs_path) free(afu->sysfs_path); if (free_adapter && afu->adapter) cxl_adapter_free(afu->adapter); if (afu->mmio_addr) cxl_mmio_unmap(afu); if (afu->fd != -1) close(afu->fd); if (afu->fd_errbuff != -1) close(afu->fd_errbuff); if (afu->dev_name) free(afu->dev_name); if (afu->event_buf) { free(afu->event_buf); afu->event_buf = NULL; } free(afu); } void cxl_afu_free(struct cxl_afu_h *afu) { _cxl_afu_free(afu, 1); } int cxl_afu_opened(struct cxl_afu_h *afu) { if (afu == NULL) { errno = EINVAL; return -1; } return (afu->fd != -1); } static int cxl_sysfs_fd(char **bufp, struct cxl_afu_h *afu) { struct cxl_afu_id afuid; char suffix = '\0'; int fd = cxl_afu_fd(afu); /* fetch the afu id via ioctl to the kernel driver */ if (ioctl(fd, CXL_IOCTL_GET_AFU_ID, &afuid) < 0) { struct stat sb; /* if the ioctl is not recognized, fallback to old method */ if ((errno != EINVAL) || (fstat(fd, &sb) < 0) || !S_ISCHR(sb.st_mode)) return -1; return asprintf(bufp, "/sys/dev/char/%i:%i", major(sb.st_rdev), minor(sb.st_rdev)); } switch (afuid.afu_mode) { case CXL_MODE_DEDICATED: suffix = 'd'; break; case CXL_MODE_DIRECTED: suffix = (afuid.flags & CXL_AFUID_FLAG_SLAVE) ? 's' : 'm'; break; default: errno = EINVAL; return -1; } return asprintf(bufp, "/sys/class/cxl/afu%i.%i%c", afuid.card_id, afuid.afu_offset, suffix); } static int cxl_afu_sysfs(struct cxl_afu_h *afu, char **bufp) { if (afu->fd >= 0) return cxl_sysfs_fd(bufp, afu); return asprintf(bufp, CXL_SYSFS_CLASS"/%s", cxl_afu_dev_name(afu)); } struct cxl_afu_h * cxl_adapter_afu_next(struct cxl_adapter_h *adapter, struct cxl_afu_h *afu) { char *dir_path; if (afu == NULL) { assert(adapter); if (!(afu = malloc_afu())) return NULL; if (cxl_sysfs_adapter(&dir_path, adapter) == -1) goto end; if (!(afu->enum_dir = opendir(dir_path))) goto err_free; } errno = 0; do { if (!(afu->enum_ent = readdir(afu->enum_dir))) goto end; } while (!is_cxl_afu_filename(afu->enum_ent->d_name)); if (cxl_afu_sysfs(afu, &afu->sysfs_path) == -1) goto err_free; return afu; err_free: free(dir_path); end: _cxl_afu_free(afu, 0); return NULL; } struct cxl_afu_h * cxl_afu_next(struct cxl_afu_h *afu) { struct cxl_adapter_h *adapter = NULL; if (afu) adapter = afu->adapter; else if (!(adapter = cxl_adapter_next(NULL))) return NULL; do { if ((afu = cxl_adapter_afu_next(adapter, afu))) afu->adapter = adapter; else adapter = cxl_adapter_next(adapter); } while (adapter && !afu); return afu; } static int sysfs_subsystem(char **bufp, const char *path) { char *subsystem_path, *name, *buf; char subsystem_link[256]; int len; int rc = -1; if ((asprintf(&subsystem_path, "%s/subsystem", path)) == -1) return -1; /* lstat returns sb.st_size == 0 for symlinks in /sys (WTF WHY???), so * we use a static buffer since we have NFI how large to allocate */ if ((len = readlink(subsystem_path, subsystem_link, sizeof(subsystem_link) - 1)) == -1) goto out; if (len >= sizeof(subsystem_link) - 1) goto out; subsystem_link[len] = '\0'; name = basename(subsystem_link); if (!(buf = malloc(strlen(name) + 1))) goto out; strcpy(buf, name); *bufp = buf; rc = 0; out: free(subsystem_path); return rc; } int cxl_afu_sysfs_pci(struct cxl_afu_h *afu, char **pathp) { char *path, *new_path, *subsys; struct stat sb; if (afu == NULL || pathp == NULL) { errno = EINVAL; return -1; } if ((path = strdup(afu->sysfs_path)) == NULL) return -1; do { if ((asprintf(&new_path, "%s/device", path)) == -1) goto err; free(path); path = new_path; if ((sysfs_subsystem(&subsys, path)) == -1) { if (errno == ENOENT) continue; goto err; } if (!(strcmp(subsys, "pci"))) { free(subsys); *pathp = path; return 0; } free(subsys); } while (stat(path, &sb) != -1); err: free(path); return -1; } static int major_minor_match(int dirfd, char *dev_name, int major, int minor) { struct stat sb; if (fstatat(dirfd, dev_name, &sb, 0) == -1) return 0; if (!S_ISCHR(sb.st_mode)) return 0; return major(sb.st_rdev) == major && minor(sb.st_rdev) == minor; } static char *find_dev_name(int major, int minor) { int saved_errno; DIR *enum_dir; struct dirent *enum_ent; int fd; char *dev_name = NULL; if ((enum_dir = opendir(CXL_DEV_DIR)) == NULL) return NULL; fd = dirfd(enum_dir); saved_errno = errno; errno = 0; do { if (!(enum_ent = readdir(enum_dir))) { if (errno == 0) errno = saved_errno; goto err_exit; } } while (!major_minor_match(fd, enum_ent->d_name, major, minor)); if ((dev_name = strdup(enum_ent->d_name)) == NULL) goto err_exit; closedir(enum_dir); return dev_name; err_exit: closedir(enum_dir); return NULL; } int cxl_afu_get_process_element(struct cxl_afu_h *afu) { int process_element; int rc; if (afu == NULL) { errno = EINVAL; return -1; } if (afu->process_element >= 0) /* return cached version */ return afu->process_element; rc = ioctl(afu->fd, CXL_IOCTL_GET_PROCESS_ELEMENT, &process_element); if (rc < 0) return rc; afu->process_element = process_element; return process_element; } /* Open Functions */ static int open_afu_dev(struct cxl_afu_h *afu, char *path) { struct stat sb; long api_version; int fd; if ((fd = open(path, O_RDWR | O_CLOEXEC)) < 0) return fd; afu->fd = fd; /* Verify that this is an AFU file we just opened */ if (fstat(fd, &sb) < 0) goto err; if (!S_ISCHR(sb.st_mode)) goto err; if (!(afu->dev_name = find_dev_name(major(sb.st_rdev), minor(sb.st_rdev)))) goto err; if (! afu->sysfs_path) if (cxl_afu_sysfs(afu, &afu->sysfs_path) == -1) goto err; if (cxl_get_api_version_compatible(afu, &api_version)) goto err; if (api_version > CXL_KERNEL_API_VERSION) { errno = EPROTO; goto err_close; } return 0; err: errno = ENODEV; err_close: if (afu->dev_name) free(afu->dev_name); close(fd); afu->fd = -1; return -1; } struct cxl_afu_h * cxl_afu_open_dev(char *path) { struct cxl_afu_h *afu; if (!(afu = malloc_afu())) return NULL; if (open_afu_dev(afu, path) < 0) goto err; return afu; err: cxl_afu_free(afu); return NULL; } static char *new_sysfs_path(char *sysfs_path, enum cxl_views view) { char lastchar; char *newpath; switch (view) { case CXL_VIEW_DEDICATED: lastchar = 'd'; break; case CXL_VIEW_MASTER: lastchar = 'm'; break; case CXL_VIEW_SLAVE: lastchar = 's'; break; default: return NULL; } switch (*(sysfs_path + strlen(sysfs_path) - 1)) { case 'd': case 'm': case 's': if ((newpath = strdup(sysfs_path)) == NULL) return NULL; *(newpath + strlen(newpath) - 1) = lastchar; break; default: if (asprintf(&newpath, "%s%c", sysfs_path, lastchar) == -1) return NULL; } return newpath; } struct cxl_afu_h * cxl_afu_open_h(struct cxl_afu_h *afu, enum cxl_views view) { char *dev_name = NULL; char *dev_path = NULL; struct cxl_afu_h *new_afu = NULL; long sysfs_major, sysfs_minor; if (!(new_afu = malloc_afu())) goto err_pass; if (!(new_afu->sysfs_path = new_sysfs_path(afu->sysfs_path, view))) goto err_pass; if (cxl_get_dev(new_afu, &sysfs_major, &sysfs_minor) < 0) goto err_exit; if (!(dev_name = find_dev_name(sysfs_major, sysfs_minor))) goto err_exit; if (asprintf(&dev_path, CXL_DEV_DIR"/%s", dev_name) == -1) goto err_pass; if (open_afu_dev(new_afu, dev_path) < 0) goto err_pass; free(dev_name); free(dev_path); return new_afu; err_exit: errno = ENODEV; err_pass: if (dev_name) free(dev_name); if (dev_path) free(dev_path); if (new_afu) free(new_afu); return NULL; } struct cxl_afu_h * cxl_afu_fd_to_h(int fd) { struct cxl_afu_h *afu; struct stat sb; long api_version; if (!(afu = malloc_afu())) return NULL; /* Verify that the passed in fd is an AFU fd */ if (fstat(fd, &sb) < 0) goto err_exit; afu->fd = fd; if (S_ISCHR(sb.st_mode)) { afu->dev_name = find_dev_name(major(sb.st_rdev), minor(sb.st_rdev)); if (!afu->dev_name) goto enodev; } else { /* Could be an anonymous inode - see if the get_afu_id ioctl succeeds */ afu->dev_name = NULL; } if (cxl_afu_sysfs(afu, &afu->sysfs_path) == -1) goto err_exit; if (cxl_get_api_version_compatible(afu, &api_version)) goto err_exit; if (api_version > CXL_KERNEL_API_VERSION) { errno = EPROTO; goto err_exit; } return afu; enodev: errno = ENODEV; err_exit: free(afu); return NULL; } int cxl_afu_attach(struct cxl_afu_h *afu, __u64 wed) { struct cxl_ioctl_start_work work; if (afu == NULL || afu->fd < 0) { errno = EINVAL; return -1; } #if defined CXL_START_WORK_TID /* get the internal kernel "pid" of the Thread ID */ afu->pid = syscall(SYS_gettid); #endif memset(&work, 0, sizeof(work)); work.work_element_descriptor = wed; return ioctl(afu->fd, CXL_IOCTL_START_WORK, &work); } int cxl_afu_attach_full(struct cxl_afu_h *afu, __u64 wed, __u16 num_interrupts, __u64 amr) { struct cxl_ioctl_start_work work; if (afu == NULL || afu->fd < 0) { errno = EINVAL; return -1; } #if defined CXL_START_WORK_TID /* get the internal kernel "pid" of the Thread ID */ afu->pid = syscall(SYS_gettid); #endif memset(&work, 0, sizeof(work)); work.work_element_descriptor = wed; work.flags = CXL_START_WORK_NUM_IRQS | CXL_START_WORK_AMR; work.num_interrupts = num_interrupts; work.amr = amr; return ioctl(afu->fd, CXL_IOCTL_START_WORK, &work); } inline int cxl_afu_attach_work(struct cxl_afu_h *afu, struct cxl_ioctl_start_work *work) { if (afu == NULL || afu->fd < 0 || work == NULL) { errno = EINVAL; return -1; } #if defined CXL_START_WORK_TID /* get the internal kernel "pid" of the Thread ID */ afu->pid = syscall(SYS_gettid); #endif return ioctl(afu->fd, CXL_IOCTL_START_WORK, work); } inline struct cxl_ioctl_start_work *cxl_work_alloc(void) { return calloc(1, sizeof(struct cxl_ioctl_start_work)); } inline int cxl_work_free(struct cxl_ioctl_start_work *work) { if (work == NULL) { errno = EINVAL; return -1; } free(work); return 0; } inline int cxl_work_get_amr(struct cxl_ioctl_start_work *work, __u64 *valp) { if (work == NULL) { errno = EINVAL; return -1; } *valp = work->amr; return 0; } inline int cxl_work_get_num_irqs(struct cxl_ioctl_start_work *work, __s16 *valp) { if (work == NULL) { errno = EINVAL; return -1; } *valp = work->num_interrupts; return 0; } inline int cxl_work_get_wed(struct cxl_ioctl_start_work *work, __u64 *valp) { if (work == NULL) { errno = EINVAL; return -1; } *valp = work->work_element_descriptor; return 0; } #if defined CXL_START_WORK_TID inline int cxl_work_get_tid(struct cxl_ioctl_start_work *work, __u16 *valp) { if (work == NULL || work->tid == -1) { errno = EINVAL; return -1; } *valp = work->tid; return 0; } #endif inline int cxl_work_set_amr(struct cxl_ioctl_start_work *work, __u64 amr) { if (work == NULL) { errno = EINVAL; return -1; } work->amr = amr; if (amr) work->flags |= CXL_START_WORK_AMR; else work->flags &= ~(CXL_START_WORK_AMR); return 0; } inline int cxl_work_set_num_irqs(struct cxl_ioctl_start_work *work, __s16 irqs) { if (work == NULL) { errno = EINVAL; return -1; } work->num_interrupts = irqs; if (irqs >= 0) work->flags |= CXL_START_WORK_NUM_IRQS; else work->flags &= ~(CXL_START_WORK_NUM_IRQS); return 0; } inline int cxl_work_set_wed(struct cxl_ioctl_start_work *work, __u64 wed) { if (work == NULL) { errno = EINVAL; return -1; } work->work_element_descriptor = wed; return 0; } #if defined CXL_START_WORK_TID inline int cxl_work_enable_wait(struct cxl_ioctl_start_work *work) { if (work == NULL) { errno = EINVAL; return -1; } work->flags |= CXL_START_WORK_TID; return 0; } inline int cxl_work_disable_wait(struct cxl_ioctl_start_work *work) { if (work == NULL) { errno = EINVAL; return -1; } work->flags &= ~(CXL_START_WORK_TID); return 0; } #endif /* * Event description print helpers */ static int cxl_fprint_afu_interrupt(FILE *stream, struct cxl_event_afu_interrupt *event) { return fprintf(stream, "AFU Interrupt %i\n", event->irq); } static int cxl_fprint_data_storage(FILE *stream, struct cxl_event_data_storage *event) { return fprintf(stream, "AFU Invalid memory reference: 0x%"PRIx64"\n", (uint64_t) event->addr); } static int cxl_fprint_afu_error(FILE *stream, struct cxl_event_afu_error *event) { return fprintf(stream, "AFU Error: 0x%"PRIx64"\n", (uint64_t) event->error); } static int hexdump(FILE *stream, __u8 *addr, ssize_t size) { unsigned i, j, c = 0; for (i = 0; i < size; i += 4) { for (j = i; j < size && j < i + 4; j++) c += fprintf(stream, "%.2x", addr[j]); c += fprintf(stream, " "); } c += fprintf(stream, "\n"); return c; } int cxl_fprint_unknown_event(FILE *stream, struct cxl_event *event) { int ret; if (!event) { errno = EINVAL; return -1; } ret = fprintf(stream, "CXL Unknown Event %i: ", event->header.type); if (ret < 0) return ret; ret += hexdump(stream, (__u8 *)event, event->header.size); return ret; } /* * Print a description of the given event to the file stream. */ int cxl_fprint_event(FILE *stream, struct cxl_event *event) { if (!event) { errno = EINVAL; return -1; } switch (event->header.type) { case CXL_EVENT_READ_FAIL: fprintf(stderr, "cxl_fprint_event: CXL Read failed\n"); errno = ENODATA; return -1; case CXL_EVENT_AFU_INTERRUPT: return cxl_fprint_afu_interrupt(stream, &event->irq); case CXL_EVENT_DATA_STORAGE: return cxl_fprint_data_storage(stream, &event->fault); case CXL_EVENT_AFU_ERROR: return cxl_fprint_afu_error(stream, &event->afu_error); default: return cxl_fprint_unknown_event(stream, event); } } static inline void poison(__u8 *ptr, ssize_t len) { unsigned int toxin = 0xDEADBEEF; __u8 *end; for (end = ptr + len; ptr < end; ptr++) *ptr = (toxin >> (8 * (3 - ((uintptr_t)ptr % 4)))) & 0xff; } static inline int fetch_cached_event(struct cxl_afu_h *afu, struct cxl_event *event) { int size; /* Local events caches, let's send it out */ size = afu->event_buf_first->header.size; memcpy(event, afu->event_buf_first, size); afu->event_buf_first = (struct cxl_event *) ((char *)afu->event_buf_first + size); assert(afu->event_buf_first <= afu->event_buf_end); return 0; } static int event_cached(struct cxl_afu_h *afu) { return afu->event_buf_first != afu->event_buf_end; } int cxl_event_pending(struct cxl_afu_h *afu) { struct pollfd fds[1] = {{cxl_afu_fd(afu), POLLIN, 0}}; if (afu == NULL) { errno = EINVAL; return -1; } if (event_cached(afu)) return 1; return poll(fds, 1, 0); } int cxl_read_event(struct cxl_afu_h *afu, struct cxl_event *event) { struct cxl_event *p = NULL; ssize_t size; int rc = 0; if (afu == NULL || event == NULL) { errno = EINVAL; return -1; } /* Init buffer */ if (!afu->event_buf) { p = malloc(CXL_READ_MIN_SIZE); if (!p) { errno = ENOMEM; return -1; } afu->event_buf = p; afu->event_buf_first = afu->event_buf; afu->event_buf_end = afu->event_buf; } /* Send buffered event */ if (event_cached(afu)) { rc = fetch_cached_event(afu, event); return rc; } if (afu->fd < 0) { errno = EINVAL; return -1; } /* Looks like we need to go read some data from the kernel */ size = read(afu->fd, afu->event_buf, CXL_READ_MIN_SIZE); if (size <= 0) { poison((__u8 *)event, sizeof(*event)); event->header.type = CXL_EVENT_READ_FAIL; event->header.size = 0; if (size < 0) return size; errno = ENODATA; return -1; } /* check for at least 1 event */ assert(size >= afu->event_buf->header.size); afu->event_buf_first = afu->event_buf; afu->event_buf_end = (struct cxl_event *) ((char *)afu->event_buf + size); return fetch_cached_event(afu, event); } /* * Read an event from the AFU when an event of type is expected. For AFU * interrupts, the expected AFU interrupt number may also be supplied (0 will * accept any AFU interrupt). * * Returns 0 if the read event was of the expected type and (if applicable) * AFU interrupt number. If the event did not match the type & interrupt * number, it returns -1. * * If the read() syscall failed for some reason (e.g. no event pending when * using non-blocking IO, etc) it will return -2 and errno will be set * appropriately. */ int cxl_read_expected_event(struct cxl_afu_h *afu, struct cxl_event *event, __u32 type, __u16 irq) { int rv; if ((rv = cxl_read_event(afu, event)) < 0) return rv; #if 0 printf("cxl_read_expected_event: Poisoning %li bytes from %p, event: %p, size: %li, rv: %i\n", size - rv, (void*)(((__u8 *)event) + rv), (void*)event, size, rv); hexdump(stderr, (__u8 *)event, size); #endif if (event->header.type != type) return -1; if ((type == CXL_EVENT_AFU_INTERRUPT) && irq) { if (!(event->irq.irq == irq)) return -1; } return 0; } /* Userspace MMIO functions */ int cxl_mmio_map(struct cxl_afu_h *afu, __u32 flags) { void *addr; long size; if (afu == NULL) { errno = EINVAL; return -1; } if (flags & ~(CXL_MMIO_FLAGS)) goto err; if (!cxl_afu_opened(afu)) goto err; if (cxl_get_mmio_size(afu, &size) < 0) return -1; afu->mmio_size = (size_t)size; addr = mmap(NULL, afu->mmio_size, PROT_READ|PROT_WRITE, MAP_SHARED, afu->fd, 0); if (addr == MAP_FAILED) return -1; afu->mmio_flags = flags; afu->mmio_addr = addr; return 0; err: errno = ENODEV; return -1; } int cxl_mmio_unmap(struct cxl_afu_h *afu) { if (!afu || !afu->mmio_addr) { errno = EINVAL; return -1; } if (munmap(afu->mmio_addr, afu->mmio_size)) return -1; afu->mmio_addr = NULL; return 0; } int cxl_mmio_ptr(struct cxl_afu_h *afu, void **mmio_ptrp) { if (afu == NULL || afu->mmio_addr == NULL) { errno = EINVAL; return -1; } *mmio_ptrp = afu->mmio_addr; return 0; } static int cxl_sigbus_handler_installed; static struct sigaction cxl_sigbus_old_action; static __thread jmp_buf cxl_sigbus_env; static __thread int cxl_sigbus_jmp_enabled; static inline int cxl_mmio_try(void) { int ret; if (!cxl_sigbus_handler_installed) return 0; ret = sigsetjmp(cxl_sigbus_env, 1); if (!ret) cxl_sigbus_jmp_enabled = 1; return ret; } static inline void cxl_mmio_success(void) { cxl_sigbus_jmp_enabled = 0; } #ifdef __PPC64__ static inline void _cxl_mmio_write64(struct cxl_afu_h *afu, uint64_t offset, uint64_t data) { __asm__ __volatile__("sync ; std%U0%X0 %1,%0" : "=m"(*(__u64 *)(afu->mmio_addr + offset)) : "r"(data)); } static inline uint64_t _cxl_mmio_read64(struct cxl_afu_h *afu, uint64_t offset) { uint64_t d; __asm__ __volatile__("ld%U1%X1 %0,%1; sync" : "=r"(d) : "m"(*(__u64 *)(afu->mmio_addr + offset))); return d; } #else /* __PPC64__ */ static inline void _cxl_mmio_write64(struct cxl_afu_h *afu, uint64_t offset, uint64_t data) { uint32_t d32; d32 = (data >> 32); __asm__ __volatile__("sync ; stw%U0%X0 %1,%0" : "=m"(*(__u64 *)(afu->mmio_addr + offset)) : "r"(d32)); d32 = data; __asm__ __volatile__("sync ; stw%U0%X0 %1,%0" : "=m"(*(__u64 *)(afu->mmio_addr + offset + 4)) : "r"(d32)); } static inline uint64_t _cxl_mmio_read64(struct cxl_afu_h *afu, uint64_t offset) { uint64_t d; uint32_t d32; __asm__ __volatile__("lwz%U1%X1 %0,%1; sync" : "=r"(d32) : "m"(*(__u64 *)(afu->mmio_addr + offset))); d = d32; __asm__ __volatile__("lwz%U1%X1 %0,%1; sync" : "=r"(d32) : "m"(*(__u64 *)(afu->mmio_addr + offset + 4))); return (d << 32) | d32; } #endif /* __PPC64__ */ static inline void _cxl_mmio_write32(struct cxl_afu_h *afu, uint64_t offset, uint32_t data) { __asm__ __volatile__("sync ; stw%U0%X0 %1,%0" : "=m"(*(__u64 *)(afu->mmio_addr + offset)) : "r"(data)); } static inline uint32_t _cxl_mmio_read32(struct cxl_afu_h *afu, uint64_t offset) { uint32_t d; __asm__ __volatile__("lwz%U1%X1 %0,%1; sync" : "=r"(d) : "m"(*(__u64 *)(afu->mmio_addr + offset))); return d; } int cxl_mmio_write64(struct cxl_afu_h *afu, uint64_t offset, uint64_t data) { if (!afu || !afu->mmio_addr) goto out; if (offset >= afu->mmio_size) goto out; if (offset & 0x7) goto out; if ((afu->mmio_flags & CXL_MMIO_ENDIAN_MASK) == CXL_MMIO_LITTLE_ENDIAN) data = htole64(data); if ((afu->mmio_flags & CXL_MMIO_ENDIAN_MASK) == CXL_MMIO_BIG_ENDIAN) data = htobe64(data); if (cxl_mmio_try()) goto fail; _cxl_mmio_write64(afu, offset, data); cxl_mmio_success(); return 0; out: errno = EINVAL; return -1; fail: if (!cxl_sigbus_handler_installed) { /* TODO: use pthread_sigqueue / sigqueue / rt_tgsigqueueinfo to * pass the faulting address */ raise(SIGBUS); } errno = EIO; return -1; } int cxl_mmio_read64(struct cxl_afu_h *afu, uint64_t offset, uint64_t *data) { uint64_t d; if (!afu || !afu->mmio_addr) goto out; if (offset >= afu->mmio_size) goto out; if (offset & 0x7) goto out; if (cxl_mmio_try()) goto fail; d = _cxl_mmio_read64(afu, offset); cxl_mmio_success(); if (d == 0xffffffffffffffffull) goto fail; *data = d; if ((afu->mmio_flags & CXL_MMIO_ENDIAN_MASK) == CXL_MMIO_LITTLE_ENDIAN) *data = le64toh(d); if ((afu->mmio_flags & CXL_MMIO_ENDIAN_MASK) == CXL_MMIO_BIG_ENDIAN) *data = be64toh(d); return 0; out: errno = EINVAL; return -1; fail: if (!cxl_sigbus_handler_installed) { /* TODO: use pthread_sigqueue / sigqueue / rt_tgsigqueueinfo to * pass the faulting address */ raise(SIGBUS); } *data = 0xffffffffffffffffull; errno = EIO; return -1; } int cxl_mmio_write32(struct cxl_afu_h *afu, uint64_t offset, uint32_t data) { if (!afu || !afu->mmio_addr) goto out; if (offset >= afu->mmio_size) goto out; if (offset & 0x3) goto out; if ((afu->mmio_flags & CXL_MMIO_ENDIAN_MASK) == CXL_MMIO_LITTLE_ENDIAN) data = htole32(data); if ((afu->mmio_flags & CXL_MMIO_ENDIAN_MASK) == CXL_MMIO_BIG_ENDIAN) data = htobe32(data); if (cxl_mmio_try()) goto fail; _cxl_mmio_write32(afu, offset, data); cxl_mmio_success(); return 0; out: errno = EINVAL; return -1; fail: if (!cxl_sigbus_handler_installed) { /* TODO: use pthread_sigqueue / sigqueue / rt_tgsigqueueinfo to * pass the faulting address */ raise(SIGBUS); } errno = EIO; return -1; } int cxl_mmio_read32(struct cxl_afu_h *afu, uint64_t offset, uint32_t *data) { uint32_t d; if (!afu || !afu->mmio_addr) goto out; if (offset >= afu->mmio_size) goto out; if (offset & 0x3) goto out; if (cxl_mmio_try()) goto fail; d = _cxl_mmio_read32(afu, offset); cxl_mmio_success(); if (d == 0xffffffff) goto fail; *data = d; if ((afu->mmio_flags & CXL_MMIO_ENDIAN_MASK) == CXL_MMIO_LITTLE_ENDIAN) *data = le32toh(d); if ((afu->mmio_flags & CXL_MMIO_ENDIAN_MASK) == CXL_MMIO_BIG_ENDIAN) *data = be32toh(d); return 0; out: errno = EINVAL; return -1; fail: if (!cxl_sigbus_handler_installed) { /* TODO: use pthread_sigqueue / sigqueue / rt_tgsigqueueinfo to * pass the faulting address */ raise(SIGBUS); } *data = 0xffffffff; errno = EIO; return -1; } static void cxl_sigbus_action(int sig, siginfo_t *info, void *context) { if (info->si_code == BUS_ADRERR && cxl_sigbus_jmp_enabled) { /* fprintf(stderr, "libcxl: SIGBUS handler caught bad access to %p\n", info->si_addr); */ siglongjmp(cxl_sigbus_env, 1); } if (cxl_sigbus_old_action.sa_handler == SIG_IGN) { /* fprintf(stderr, "libcxl: Ignoring SIGBUS\n"); */ return; } if (cxl_sigbus_old_action.sa_handler == SIG_DFL) { /* fprintf(stderr, "libcxl: Raising default SIGBUS handler\n"); */ sigaction(SIGBUS, &cxl_sigbus_old_action, NULL); raise(SIGBUS); } /* * Chain to any other installed SIGBUS handlers. Do this after checking * valid values of sa_handler as the two are stored as a union. */ if (cxl_sigbus_old_action.sa_sigaction) { /* fprintf(stderr, "libcxl: Calling chained SIGBUS handler\n"); */ cxl_sigbus_old_action.sa_sigaction(sig, info, context); } } int cxl_mmio_install_sigbus_handler(void) { struct sigaction act; if (cxl_sigbus_handler_installed) return 0; cxl_sigbus_handler_installed = 1; memset(&act, 0, sizeof(struct sigaction)); act.sa_sigaction = cxl_sigbus_action; act.sa_flags = SA_SIGINFO; return sigaction(SIGBUS, &act, &cxl_sigbus_old_action); } #if defined CXL_START_WORK_TID int cxl_afu_host_thread_wait(struct cxl_afu_h *afu, volatile __u64 *uword) { if (afu == NULL) { errno = EINVAL; return -1; } if (afu->pid != syscall(SYS_gettid)) { errno = EPERM; return -1; } while (*uword == 0) { asm volatile ("wait"); } return 0; } #endif libcxl-1.7/libcxl.h000066400000000000000000000234451327654150600143050ustar00rootroot00000000000000/* * Copyright 2014,2015 International Business Machines * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _LIBCXL_H #define _LIBCXL_H #include #include #include #ifdef __cplusplus extern "C" { #endif #define CXL_KERNEL_API_VERSION 1 #define CXL_SYSFS_CLASS "/sys/class/cxl" #define CXL_DEV_DIR "/dev/cxl" /* * Opaque types */ struct cxl_adapter_h; struct cxl_afu_h; struct cxl_ioctl_start_work; /* * Adapter Enumeration * * Repeatedly call cxl_adapter_next() (or use the cxl_for_each_adapter macro) * to enumerate the available CXL adapters. * * cxl_adapter_next() will implicitly free used buffers if it is called on the * last adapter, or cxl_adapter_free() can be called explicitly. */ struct cxl_adapter_h * cxl_adapter_next(struct cxl_adapter_h *adapter); char * cxl_adapter_dev_name(struct cxl_adapter_h *adapter); void cxl_adapter_free(struct cxl_adapter_h *adapter); #define cxl_for_each_adapter(adapter) \ for (adapter = cxl_adapter_next(NULL); adapter; adapter = cxl_adapter_next(adapter)) /* * AFU Enumeration * * Repeatedly call cxl_adapter_afu_next() (or use the * cxl_for_each_adapter_afu macro) to enumerate AFUs on a specific CXL * adapter, or use cxl_afu_next() or cxl_for_each_afu to enumerate AFUs over * all CXL adapters in the system. * * For instance, if you just want to find any AFU attached to the system but * don't particularly care which one, just do: * struct cxl_afu_h *afu_h = cxl_afu_next(NULL); * * cxl_[adapter]_afu_next() will implicitly free used buffers if it is called * on the last AFU, or cxl_afu_free() can be called explicitly. */ struct cxl_afu_h * cxl_adapter_afu_next(struct cxl_adapter_h *adapter, struct cxl_afu_h *afu); struct cxl_afu_h * cxl_afu_next(struct cxl_afu_h *afu); char * cxl_afu_dev_name(struct cxl_afu_h *afu); #define cxl_for_each_adapter_afu(adapter, afu) \ for (afu = cxl_adapter_afu_next(adapter, NULL); afu; afu = cxl_adapter_afu_next(adapter, afu)) #define cxl_for_each_afu(afu) \ for (afu = cxl_afu_next(NULL); afu; afu = cxl_afu_next(afu)) enum cxl_views { CXL_VIEW_DEDICATED = 0, CXL_VIEW_MASTER, CXL_VIEW_SLAVE }; /* * Open AFU - either by path, by AFU being enumerated, or tie into an AFU file * descriptor that has already been opened. The AFU file descriptor will be * closed by cxl_afu_free() regardless of how it was opened. */ struct cxl_afu_h * cxl_afu_open_dev(char *path); struct cxl_afu_h * cxl_afu_open_h(struct cxl_afu_h *afu, enum cxl_views view); struct cxl_afu_h * cxl_afu_fd_to_h(int fd); void cxl_afu_free(struct cxl_afu_h *afu); int cxl_afu_opened(struct cxl_afu_h *afu); /* * Attach AFU context to this process */ struct cxl_ioctl_start_work *cxl_work_alloc(void); int cxl_work_free(struct cxl_ioctl_start_work *work); int cxl_work_get_amr(struct cxl_ioctl_start_work *work, __u64 *valp); int cxl_work_get_num_irqs(struct cxl_ioctl_start_work *work, __s16 *valp); int cxl_work_get_wed(struct cxl_ioctl_start_work *work, __u64 *valp); int cxl_work_set_amr(struct cxl_ioctl_start_work *work, __u64 amr); int cxl_work_set_num_irqs(struct cxl_ioctl_start_work *work, __s16 num_irqs); int cxl_work_set_wed(struct cxl_ioctl_start_work *work, __u64 wed); #if defined CXL_START_WORK_TID int cxl_work_get_tid(struct cxl_ioctl_start_work *work, __u16 *valp); int cxl_work_enable_wait(struct cxl_ioctl_start_work *work); int cxl_work_disable_wait(struct cxl_ioctl_start_work *work); #endif int cxl_afu_attach(struct cxl_afu_h *afu, __u64 wed); int cxl_afu_attach_work(struct cxl_afu_h *afu, struct cxl_ioctl_start_work *work); /* Deprecated interface */ int cxl_afu_attach_full(struct cxl_afu_h *afu, __u64 wed, __u16 num_interrupts, __u64 amr); /* * Get AFU process element */ int cxl_afu_get_process_element(struct cxl_afu_h *afu); /* * Returns the file descriptor for the open AFU to use with event loops. * Returns -1 if the AFU is not open. */ int cxl_afu_fd(struct cxl_afu_h *afu); /* * sysfs helpers */ /* * NOTE: On success, this function automatically allocates the returned * buffer, which must be freed by the caller (much like asprintf). */ int cxl_afu_sysfs_pci(struct cxl_afu_h *afu, char **pathp); /* Flags for cxl_get/set_mode and cxl_get_modes_supported */ #define CXL_MODE_DEDICATED 0x1 #define CXL_MODE_DIRECTED 0x2 #define CXL_MODE_TIME_SLICED 0x4 /* Values for cxl_get/set_prefault_mode */ enum cxl_prefault_mode { CXL_PREFAULT_MODE_NONE = 0, CXL_PREFAULT_MODE_WED, CXL_PREFAULT_MODE_ALL, }; /* Values for cxl_get_image_loaded */ enum cxl_image { CXL_IMAGE_FACTORY = 0, CXL_IMAGE_USER, }; /* * Get/set attribute values. * Return 0 on success, -1 on error. */ int cxl_get_api_version(struct cxl_afu_h *afu, long *valp); int cxl_get_api_version_compatible(struct cxl_afu_h *afu, long *valp); int cxl_get_cr_class(struct cxl_afu_h *afu, long cr_num, long *valp); int cxl_get_cr_device(struct cxl_afu_h *afu, long cr_num, long *valp); int cxl_get_cr_vendor(struct cxl_afu_h *afu, long cr_num, long *valp); int cxl_get_irqs_max(struct cxl_afu_h *afu, long *valp); int cxl_set_irqs_max(struct cxl_afu_h *afu, long value); int cxl_get_irqs_min(struct cxl_afu_h *afu, long *valp); int cxl_get_mmio_size(struct cxl_afu_h *afu, long *valp); int cxl_get_mode(struct cxl_afu_h *afu, long *valp); int cxl_set_mode(struct cxl_afu_h *afu, long value); int cxl_get_modes_supported(struct cxl_afu_h *afu, long *valp); int cxl_get_prefault_mode(struct cxl_afu_h *afu, enum cxl_prefault_mode *valp); int cxl_set_prefault_mode(struct cxl_afu_h *afu, enum cxl_prefault_mode value); int cxl_get_pp_mmio_len(struct cxl_afu_h *afu, long *valp); int cxl_get_pp_mmio_off(struct cxl_afu_h *afu, long *valp); int cxl_get_base_image(struct cxl_adapter_h *adapter, long *valp); int cxl_get_caia_version(struct cxl_adapter_h *adapter, long *majorp, long *minorp); int cxl_get_image_loaded(struct cxl_adapter_h *adapter, enum cxl_image *valp); int cxl_get_psl_revision(struct cxl_adapter_h *adapter, long *valp); int cxl_get_psl_timebase_synced(struct cxl_adapter_h *adapter, long *valp); int cxl_get_tunneled_ops_supported(struct cxl_adapter_h *adapter, long *valp); /* * Events */ int cxl_event_pending(struct cxl_afu_h *afu); int cxl_read_event(struct cxl_afu_h *afu, struct cxl_event *event); int cxl_read_expected_event(struct cxl_afu_h *afu, struct cxl_event *event, __u32 type, __u16 irq); /* * fprint wrappers to print out CXL events - useful for debugging. * cxl_fprint_event will select the appropriate implementation based on the * event type and cxl_fprint_unknown_event will print out a hex dump of the * raw event. */ int cxl_fprint_event(FILE *stream, struct cxl_event *event); int cxl_fprint_unknown_event(FILE *stream, struct cxl_event *event); /* * AFU MMIO functions * * The below assessors will byte swap based on what is passed to map. Also a * full memory barrier 'sync' will proceed a write and follow a read. More * relaxed assessors can be created using a pointer derived from cxl_mmio_ptr(). */ #define CXL_MMIO_BIG_ENDIAN 0x1 #define CXL_MMIO_LITTLE_ENDIAN 0x2 #define CXL_MMIO_HOST_ENDIAN 0x3 #define CXL_MMIO_ENDIAN_MASK 0x3 #define CXL_MMIO_FLAGS 0x3 int cxl_mmio_map(struct cxl_afu_h *afu, __u32 flags); int cxl_mmio_unmap(struct cxl_afu_h *afu); int cxl_mmio_ptr(struct cxl_afu_h *afu, void **mmio_ptrp); int cxl_mmio_write64(struct cxl_afu_h *afu, uint64_t offset, uint64_t data); int cxl_mmio_read64(struct cxl_afu_h *afu, uint64_t offset, uint64_t *data); int cxl_mmio_write32(struct cxl_afu_h *afu, uint64_t offset, uint32_t data); int cxl_mmio_read32(struct cxl_afu_h *afu, uint64_t offset, uint32_t *data); /* * Calling this function will install the libcxl SIGBUS handler. This will * catch bad MMIO accesses (e.g. due to hardware failures) that would otherwise * terminate the program and make the above mmio functions return errors * instead. * * Call this once per process prior to any MMIO accesses. */ int cxl_mmio_install_sigbus_handler(void); /** * Returns the size of afu_err_buff in bytes. * @param afu Handle to the afu. * @param valp Pointer to the location where size is copied to. * @return In case of success '0' is returned. In case of an error or * the afu_err_buff doesn't exist, -1 is returned and errno is set * appropriately. */ int cxl_errinfo_size(struct cxl_afu_h *afu, size_t *valp); /** * Read and copy the contents of afu_err_info buffer into the provided buffer. * @param afu Handle to the afu * @param dst Pointer to the buffer where data would be copied. * @param off Start offset within the afu_err_info handle. * @param len Number of bytes to be copied after the start offset. * @return The number of bytes copied from the afu_err_buff to dst. In case of * an error or the afu_err_buff doesn't exist, -1 is returned and errno is set * appropriately. */ ssize_t cxl_errinfo_read(struct cxl_afu_h *afu, void *dst, off_t off, size_t len); #if defined CXL_START_WORK_TID /** * Execute the instruction "wait" while the value of the shared * memory (uword) has not changed. Only the current thread, which has * attached the work, may be asleep. * @param uword Pointer to the shared memory to exit from the loop. * @return In case of success '0' is returned. In case of an error or * the afu doesn't exist, -1 is returned and errno is set * appropriately. */ int cxl_afu_host_thread_wait(struct cxl_afu_h *afu, volatile __u64 *uword); #endif #ifdef __cplusplus } #endif #endif libcxl-1.7/libcxl_internal.h000066400000000000000000000026541327654150600162000ustar00rootroot00000000000000/* * Copyright 2014,2015 International Business Machines * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _LIBCXL_INTERNAL_H #define _LIBCXL_INTERNAL_H #include #include #include struct cxl_adapter_h { DIR *enum_dir; struct dirent *enum_ent; char *sysfs_path; }; struct cxl_afu_h { struct cxl_adapter_h *adapter; /* Only used if allocated by us */ DIR *enum_dir; int process_element; struct dirent *enum_ent; struct cxl_event *event_buf; /* Event buffer storage */ struct cxl_event *event_buf_first; /* First event to read */ struct cxl_event *event_buf_end; /* End of events */ char *dev_name; char *sysfs_path; int fd; void *mmio_addr; __u32 mmio_flags; size_t mmio_size; int fd_errbuff; /* fd to the afu_err_buff */ size_t errbuff_size; #if defined CXL_START_WORK_TID int pid; #endif }; int cxl_get_dev(struct cxl_afu_h *afu, long *majorp, long *minorp); #endif libcxl-1.7/libcxl_sysfs.c000066400000000000000000000327371327654150600155330ustar00rootroot00000000000000/* * Copyright 2014,2015 International Business Machines * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "libcxl.h" #include "libcxl_internal.h" enum cxl_sysfs_attr { /* AFU */ API_VERSION = 0, API_VERSION_COMPATIBLE, CR_CLASS, CR_DEVICE, CR_VENDOR, IRQS_MAX, IRQS_MIN, MMIO_SIZE, MODE, MODES_SUPPORTED, PREFAULT_MODE, /* AFU Master or Slave */ DEV, PP_MMIO_LEN, PP_MMIO_OFF, /* Card */ BASE_IMAGE, CAIA_VERSION, IMAGE_LOADED, PSL_REVISION, PSL_TIMEBASE_SYNCED, TUNNELED_OPS_SUPPORTED, /* Add new attrs above this */ CXL_ATTR_MAX }; struct cxl_sysfs_entry { char *name; int (*scan_func)(char *attr_str, long *major, long *minor); int expected_num; }; static int scan_int(char *attr_str, long *majorp, long *minorp); static int scan_hex(char *attr_str, long *majorp, long *minorp); static int scan_dev(char *attr_str, long *majorp, long *minorp); static int scan_mode(char *attr_str, long *majorp, long *minorp); static int scan_modes(char *attr_str, long *majorp, long *minorp); static int scan_prefault_mode(char *attr_str, long *majorp, long *minorp); static int scan_caia_version(char *attr_str, long *majorp, long *minorp); static int scan_image(char *attr_str, long *majorp, long *minorp); static struct cxl_sysfs_entry sysfs_entry[CXL_ATTR_MAX] = { [API_VERSION] = { "api_version", scan_int, 1 }, [API_VERSION_COMPATIBLE] = { "api_version_compatible", scan_int, 1 }, [CR_CLASS] = { "cr%ld/class", scan_hex, 1 }, [CR_DEVICE] = { "cr%ld/device", scan_hex, 1 }, [CR_VENDOR] = { "cr%ld/vendor", scan_hex, 1 }, [IRQS_MAX] = { "irqs_max", scan_int, 1 }, [IRQS_MIN] = { "irqs_min", scan_int, 1 }, [MMIO_SIZE] = { "mmio_size", scan_int, 1 }, [MODE] = { "mode", scan_mode, 1 }, [MODES_SUPPORTED] = { "modes_supported", scan_modes, 1 }, [PREFAULT_MODE] = { "prefault_mode", scan_prefault_mode, 1 }, [DEV] = { "dev", scan_dev, 2 }, [PP_MMIO_LEN] = { "pp_mmio_len", scan_int, 1 }, [PP_MMIO_OFF] = { "pp_mmio_off", scan_int, 1 }, [BASE_IMAGE] = { "base_image", scan_int, 1 }, [CAIA_VERSION] = { "caia_version", scan_caia_version, 2 }, [IMAGE_LOADED] = { "image_loaded", scan_image, 1 }, [PSL_REVISION] = { "psl_revision", scan_int, 1 }, [PSL_TIMEBASE_SYNCED] = { "psl_timebase_synced", scan_int, 1 }, [TUNNELED_OPS_SUPPORTED] = { "tunneled_ops_supported", scan_int, 1 }, }; #define OUT_OF_RANGE(attr) ((attr) < 0 || (attr) >= CXL_ATTR_MAX || \ (sysfs_entry[attr].name == NULL)) static int scan_int(char *attr_str, long *majorp, long *minorp) { return sscanf(attr_str, "%ld", majorp); } static int scan_hex(char *attr_str, long *majorp, long *minorp) { return sscanf(attr_str, "0x%lx", majorp); } static int scan_dev(char *attr_str, long *majorp, long *minorp) { return sscanf(attr_str, "%ld:%ld", majorp, minorp); } static int scan_caia_version(char *attr_str, long *majorp, long *minorp) { return sscanf(attr_str, "%ld.%ld", majorp, minorp); } static int scan_mode(char *attr_str, long *majorp, long *minorp) { int count; char buf[18]; if ((count = sscanf(attr_str, "%17s", buf)) != 1) return -1; if (!strcmp(buf, "dedicated_process")) { *majorp = CXL_MODE_DEDICATED; count = 0; } else if (!strcmp(buf, "afu_directed")) { *majorp = CXL_MODE_DIRECTED; count = 0; } return (count == 0); } static int scan_modes(char *attr_str, long *majorp, long *minorp) { long val1, val2 = 0; char buf1[18], buf2[18]; int rc; if ((rc = sscanf(attr_str, "%17s\n%17s", buf1, buf2)) <= 0) return -1; if (rc == 2 && scan_mode(buf2, &val2, NULL) != 1) return -1; if (scan_mode(buf1, &val1, NULL) != 1) return -1; *majorp = val1|val2; return 1; } static int scan_prefault_mode(char *attr_str, long *majorp, long *minorp) { int count; char buf[24]; if ((count = sscanf(attr_str, "%23s", buf)) != 1) return -1; if (!strcmp(buf, "none")) { *majorp = CXL_PREFAULT_MODE_NONE; count = 0; } else if (!strcmp(buf, "work_element_descriptor")) { *majorp = CXL_PREFAULT_MODE_WED; count = 0; } else if (!strcmp(buf, "all")) { *majorp = CXL_PREFAULT_MODE_ALL; count = 0; } return (count == 0); } static int scan_image(char *attr_str, long *majorp, long *minorp) { int count; char buf[8]; if ((count = sscanf(attr_str, "%7s", buf)) != 1) return -1; if (!strcmp(buf, "factory")) { *majorp = CXL_IMAGE_FACTORY; count = 0; } else if (!strcmp(buf, "user")) { *majorp = CXL_IMAGE_USER; count = 0; } return (count == 0); } static char *sysfs_attr_name(enum cxl_sysfs_attr attr) { if (OUT_OF_RANGE(attr)) return NULL; return sysfs_entry[attr].name; } #define BUFLEN 256 static char *sysfs_get_path(char *path, char *attr_name) { char *attr_path = NULL; char *new_path; struct stat sb; path = strdup(path); if (path == NULL) return NULL; /* * Try to open the attribute in sysfs. If it doesn't exist, keep * following "device/" path down until we find it. */ while (stat(path, &sb) != -1) { if (asprintf(&attr_path, "%s/%s", path, attr_name) == -1) goto out; if (stat(attr_path, &sb) == 0) { free(path); return attr_path; } if (errno != ENOENT) /* Something unexpected beside it not existing */ goto enodev; /* If it doesn't exist, walk down "device/" link */ if (asprintf(&new_path, "%s/device", path) == -1) goto out; free(path); path = new_path; free(attr_path); } /* Directory doesn't exist */ enodev: errno = ENODEV; out: if (attr_path) free(attr_path); free(path); return NULL; } static char *read_sysfs_str(char *attr_path) { int fd, count; char buf[BUFLEN]; fd = open(attr_path, O_RDONLY); free(attr_path); if (fd == -1) return NULL; count = read(fd, buf, BUFLEN); close(fd); if (count == -1) return NULL; buf[count - 1] = '\0'; return strdup(buf); } static int scan_sysfs_str(enum cxl_sysfs_attr attr, char *attr_str, long *majorp, long *minorp) { int (*scan_func)(char *attr_str, long *majorp, long *minorp); if (OUT_OF_RANGE(attr)) return -1; scan_func = sysfs_entry[attr].scan_func; if (scan_func == NULL) return -1; return (*scan_func)(attr_str, majorp, minorp); } static int read_sysfs(char *sysfs_path, enum cxl_sysfs_attr attr, long *majorp, long *minorp) { char *attr_name; char *attr_path; char *buf; int expected, ret; if (OUT_OF_RANGE(attr)) return -1; attr_name = sysfs_attr_name(attr); if (attr_name == NULL) return -1; /* * Hack: * For configuration record attributes, attr_name is a printf * format with one parameter, the configuration record number, * pointed to by minorp. */ switch (attr) { case CR_CLASS: case CR_DEVICE: case CR_VENDOR: if (asprintf(&buf, attr_name, *minorp) == -1) return -1; attr_path = sysfs_get_path(sysfs_path, buf); free(buf); break; default: attr_path = sysfs_get_path(sysfs_path, attr_name); } if (attr_path == NULL) return -1; if ((buf = read_sysfs_str(attr_path)) == NULL) return -1; expected = sysfs_entry[attr].expected_num; ret = scan_sysfs_str(attr, buf, majorp, minorp); free(buf); return (ret == expected) ? 0 : -1; } static int read_sysfs_afu(struct cxl_afu_h *afu, enum cxl_sysfs_attr attr, long *majorp, long *minorp) { if ((afu == NULL) || (afu->sysfs_path == NULL)) { errno = EINVAL; return -1; } return read_sysfs(afu->sysfs_path, attr, majorp, minorp); } static int read_sysfs_adapter(struct cxl_adapter_h *adapter, enum cxl_sysfs_attr attr, long *majorp, long *minorp) { if ((adapter == NULL) || (adapter->sysfs_path == NULL)) { errno = EINVAL; return -1; } return read_sysfs(adapter->sysfs_path, attr, majorp, minorp); } int cxl_get_api_version(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, API_VERSION, valp, NULL); } int cxl_get_api_version_compatible(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, API_VERSION_COMPATIBLE, valp, NULL); } int cxl_get_cr_class(struct cxl_afu_h *afu, long cr_num, long *valp) { return read_sysfs_afu(afu, CR_CLASS, valp, &cr_num); } int cxl_get_cr_device(struct cxl_afu_h *afu, long cr_num, long *valp) { return read_sysfs_afu(afu, CR_DEVICE, valp, &cr_num); } int cxl_get_cr_vendor(struct cxl_afu_h *afu, long cr_num, long *valp) { return read_sysfs_afu(afu, CR_VENDOR, valp, &cr_num); } int cxl_get_irqs_max(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, IRQS_MAX, valp, NULL); } int cxl_get_irqs_min(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, IRQS_MIN, valp, NULL); } int cxl_get_mmio_size(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, MMIO_SIZE, valp, NULL); } int cxl_get_mode(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, MODE, valp, NULL); } int cxl_get_modes_supported(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, MODES_SUPPORTED, valp, NULL); } int cxl_get_prefault_mode(struct cxl_afu_h *afu, enum cxl_prefault_mode *valp) { long value; int ret; ret = read_sysfs_afu(afu, PREFAULT_MODE, &value, NULL); *valp = (enum cxl_prefault_mode)value; return ret; } int cxl_get_dev(struct cxl_afu_h *afu, long *majorp, long *minorp) { return read_sysfs_afu(afu, DEV, majorp, minorp); } int cxl_get_pp_mmio_len(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, PP_MMIO_LEN, valp, NULL); } int cxl_get_pp_mmio_off(struct cxl_afu_h *afu, long *valp) { return read_sysfs_afu(afu, PP_MMIO_OFF, valp, NULL); } int cxl_get_base_image(struct cxl_adapter_h *adapter, long *valp) { return read_sysfs_adapter(adapter, BASE_IMAGE, valp, NULL); } int cxl_get_caia_version(struct cxl_adapter_h *adapter, long *majorp, long *minorp) { return read_sysfs_adapter(adapter, CAIA_VERSION, majorp, minorp); } int cxl_get_image_loaded(struct cxl_adapter_h *adapter, enum cxl_image *valp) { return read_sysfs_adapter(adapter, IMAGE_LOADED, (long *)valp, NULL); } int cxl_get_psl_revision(struct cxl_adapter_h *adapter, long *valp) { return read_sysfs_adapter(adapter, PSL_REVISION, valp, NULL); } int cxl_get_psl_timebase_synced(struct cxl_adapter_h *adapter, long *valp) { return read_sysfs_adapter(adapter, PSL_TIMEBASE_SYNCED, valp, NULL); } int cxl_get_tunneled_ops_supported(struct cxl_adapter_h *adapter, long *valp) { return read_sysfs_adapter(adapter, TUNNELED_OPS_SUPPORTED, valp, NULL); } static int write_sysfs_str(char *path, enum cxl_sysfs_attr attr, char *str) { char *attr_name; char *attr_path; int fd, count; if (OUT_OF_RANGE(attr)) return -1; if (path == NULL) return -1; attr_name = sysfs_attr_name(attr); if (attr_name == NULL) return -1; attr_path = sysfs_get_path(path, attr_name); if (attr_path == NULL) return -1; fd = open(attr_path, O_WRONLY); free(attr_path); if (fd == -1) return -1; count = write(fd, str, strlen(str)); close(fd); if (count == -1) return -1; return 0; } static int write_sysfs_afu(struct cxl_afu_h *afu, enum cxl_sysfs_attr attr, char* str) { if ((afu == NULL) || (afu->sysfs_path == NULL)) { errno = EINVAL; return -1; } return write_sysfs_str(afu->sysfs_path, attr, str); } int cxl_set_irqs_max(struct cxl_afu_h *afu, long value) { char *buf; int ret; if (asprintf(&buf, "%ld", value) == -1) return -1; ret = write_sysfs_afu(afu, IRQS_MAX, buf); free(buf); return ret; } int cxl_set_mode(struct cxl_afu_h *afu, long value) { char *str; switch (value) { case CXL_MODE_DEDICATED: str = "dedicated_process"; break; case CXL_MODE_DIRECTED: str = "afu_directed"; break; default: errno = EINVAL; return -1; } return write_sysfs_afu(afu, MODE, str); } int cxl_set_prefault_mode(struct cxl_afu_h *afu, enum cxl_prefault_mode value) { char *str; switch (value) { case CXL_PREFAULT_MODE_NONE: str = "none"; break; case CXL_PREFAULT_MODE_WED: str = "work_element_descriptor"; break; case CXL_PREFAULT_MODE_ALL: str = "all"; break; default: errno = EINVAL; return -1; } return write_sysfs_afu(afu, PREFAULT_MODE, str); } /* Returns the total size of the afu_err_buff in bytes */ int cxl_errinfo_size(struct cxl_afu_h *afu, size_t *valp) { /* check if we need to fetch the size of the buffer */ if (afu->errbuff_size == -1) { char * path; struct stat st; path = sysfs_get_path(afu->sysfs_path, "afu_err_buff"); if (path == NULL) return -1; /* get the file size */ if (stat(path, &st) < 0) { free(path); return -1; } afu->errbuff_size = st.st_size; free(path); } *valp = afu->errbuff_size; return 0; } /* Read and copies contents to afu_err_buff to the provided buffer */ ssize_t cxl_errinfo_read(struct cxl_afu_h *afu, void *dst, off_t off, size_t len) { /* check if we need to open the descriptor */ if (afu->fd_errbuff == -1) { char * path; path = sysfs_get_path(afu->sysfs_path, "afu_err_buff"); if (path == NULL) return -1; afu->fd_errbuff = open(path, O_RDONLY | O_CLOEXEC); free(path); if (afu->fd_errbuff == -1) return -1; } /* seek to right offset and read contents */ if (lseek(afu->fd_errbuff, off, SEEK_SET) < 0) return -1; return read(afu->fd_errbuff, dst, len); } libcxl-1.7/man3/000077500000000000000000000000001327654150600135055ustar00rootroot00000000000000libcxl-1.7/man3/Makefile000066400000000000000000000011601327654150600151430ustar00rootroot00000000000000SRC = $(wildcard *.3) HTML = $(SRC:.3=.3.html) TXT = $(SRC:.3=.3.txt) all: $(HTML) $(TXT) clean: rm -f *.3.html *.3.txt %.3.html: %.3 man2html -r <$< >$@; [ -s $@ ] %.3.txt: %.3 ./man2txt <$< >$@; [ -s $@ ] cxl.3.txt: cxl.3 ./man2txt <$< | ./foldtbl >$@; [ -s $@ ] cxl_for_each_adapter.3.html: cxl_adapter_next.3.html cp -f $< $@ cxl_for_each_adapter_afu.3.html: cxl_adapter_afu_next.3.html cp -f $< $@ cxl_for_each_afu.3.html: cxl_afu_next.3.html cp -f $< $@ include ../Makefile.rules install: mkdir -p $(DESTDIR)$(mandir)/man3 install -m 0644 $(SRC) $(DESTDIR)$(mandir)/man3/ .PHONY: all clean install libcxl-1.7/man3/cxl.3000066400000000000000000000224721327654150600143660ustar00rootroot00000000000000.\" Copyright 2015-2018 IBM Corp. .\" .TH CXL 3 2018-04-26 "LIBCXL 1.7" "CXL Programmer's Manual" .SH NAME cxl \- Coherent Accelerator Interface (CXL) library functions .SH SYNOPSIS .B #include .SH DESCRIPTION .SS Introduction The coherent accelerator interface is designed to allow the coherent connection of accelerators (FPGAs and other devices) to a POWER system. Coherent in this context means that the accelerator and CPUs can both access system memory directly and with the same effective addresses. IBM refers to this as the Coherent Accelerator Processor Interface (CAPI). In the Linux world it is referred to by the name CXL to avoid confusion with the ISDN CAPI subsystem. .PP The Linux kernel interacts with the device POWER Service Layer (PSL). Userland interacts with the device Accelerator Function Unit (AFU). See the Linux kernel source file .B Documentation/powerpc/cxl.txt for a detailed description of the coherent accelerator interface. .PP The CXL library provides a userland API to coherently attached devices. CXL devices can be enumerated. Their capabilities can be queried. AFUs can be opened, attached to the current process, and started. Jobs, described by AFU specific Work Element Descriptors (WEDs), can be submitted and executed by AFUs. AFU MMIO space can be mapped into the current process memory, and AFUs can be configured and controlled via MMIO reads and writes. Also if an AFU exports an AFU Error Buffer (afu_err_buff), its contents can be queried. .SS Constant macros .TS ; lb lb lb l. Macro Description _ CXL_DEV_DIR CXL device directory pathname CXL_KERNEL_API_VERSION maximum supported CXL kernel API compatible version CXL_MMIO_BIG_ENDIAN big-endian AFU flag CXL_MMIO_HOST_ENDIAN host-endian AFU flag CXL_MMIO_LITTLE_ENDIAN little-endian AFU flag CXL_MODE_DEDICATED dedicated process mode flag CXL_MODE_DIRECTED AFU directed mode flag CXL_SYSFS_CLASS sysfs CXL class pathname .TE .SS Enumeration macros .TS ; lb lb lb l. Macro Description _ cxl_for_each_adapter enumerate the available CXL adapters cxl_for_each_adapter_afu enumerate the AFUs of a CXL adapter cxl_for_each_afu enumerate the available AFUs .TE .SS Enumeration functions .TS ; lb lb lb l. Function Description _ cxl_adapter_dev_name return the CXL adapter device name cxl_adapter_free free the CXL adapter data structures cxl_adapter_next iterate to the next CXL adapter cxl_adapter_afu_next iterate to the next AFU of a CXL adapter cxl_afu_dev_name return the AFU device name cxl_afu_next iterate to the next AFU .TE .SS Open AFU functions .TS ; lb lb lb l. Function Description _ cxl_afu_fd return the file descriptor of an AFU handle cxl_afu_fd_to_h create an AFU handle from the file descriptor of an already open AFU cxl_afu_free free the data structures of an AFU handle cxl_afu_get_process_element get the process element associated with an open AFU handle cxl_afu_open_dev open an AFU by device name cxl_afu_open_h open an AFU by AFU handle cxl_afu_opened return whether an AFU handle is opened .TE .SS Work Structure Handling functions .TS ; lb lb lb l. Function Description _ cxl_work_alloc allocate and initialize a work structure cxl_work_disable_wait indicate that a host thread will not wait cxl_work_enable_wait indicate that a host thread will wait cxl_work_free free a work structure cxl_work_get_amr get the value of the authority mask register cxl_work_get_num_irqs get the number of interrupts requested cxl_work_get_tid get the tid of the thread that will wait cxl_work_get_wed get the value of the work element descriptor cxl_work_set_amr set the value of the authority mask register cxl_work_set_num_irqs set the number of interrupts requested cxl_work_set_wed set the value of the work element descriptor .TE .SS Attach AFU Context functions .TS ; lb lb lb l. Function Description _ cxl_afu_attach attach the calling process's memory to an open AFU cxl_afu_attach_full attach the calling process's memory to an open AFU (Deprecated Interface) cxl_afu_attach_work attach the calling process's memory to an open AFU .TE .SS Wait for AFU Notification function .TS ; lb lb lb l. Function Description _ cxl_afu_host_thread_wait wait for AFU notification .TE .SS CXL Adapter Sysfs Helper functions .TS ; lb lb lb l. Function Description _ cxl_get_base_image get the revision level of the initial PSL image loaded on the CXL device cxl_get_caia_version get the CAIA version supported by a CXL adapter cxl_get_image_loaded returns which of the user and factory PSL images is currently loaded on the CXL device cxl_get_psl_revision get the revision level of the current PSL image loaded on the CXL device cxl_get_psl_timebase_synced get the status of timebase on the CXL device cxl_get_tunneled_ops_supported get the status of tunneled operations on the CXL device .TE .SS AFU Directed Master Context Sysfs Helper functions .TS ; lb lb lb l. Function Description _ cxl_get_mmio_size get the total size of the MMIO space of an AFU, including all per-process areas cxl_get_pp_mmio_len get the per-process MMIO space length cxl_get_pp_mmio_off get the per-process MMIO space offset .TE .SS AFU Context Sysfs Helper functions .TS ; lb lb lb l. Function Description _ cxl_afu_sysfs_pci get the sysfs path to the PCI device corresponding with an AFU cxl_get_mmio_size get the size of the MMIO space available to a non-master process cxl_get_mode get the current programming mode of an AFU cxl_get_modes_supported get the programming modes supported by an AFU cxl_get_prefault_mode get the mode for prefaulting segments cxl_get_api_version get the version of the kernel CXL API cxl_get_api_version_compatible get the lowest CXL API version compatible with the kernel cxl_get_cr_class get the class code out of an AFU configuration record cxl_get_cr_device get the device ID out of an AFU configuration record cxl_get_cr_vendor get the vendor ID out of an AFU configuration record cxl_get_irqs_max get the maximum number of AFU interrupts available to a context, if it was the only context running cxl_get_irqs_min get the minimum number of AFU interrupts required for each context cxl_set_irqs_max administratively restrict the maximum number of AFU interrupts that can be used by a single context cxl_set_mode set the programming mode of an AFU cxl_set_prefault_mode set the mode for prefaulting segments .TE .SS Events functions .TS ; lb lb lb l. Function Description _ cxl_fprint_event print out a description of a CXL event for debugging cxl_fprint_unknown_event print out a hex dump of a raw CXL event for debugging cxl_event_pending return whether a CXL event is pending cxl_read_event read one CXL event from an AFU cxl_read_expected_event read one CXL event from an AFU, and treat it as a failure, if it did not match an expected event .TE .SS AFU MMIO functions .TS ; lb lb lb l. Function Description _ cxl_mmio_map map the per-process Problem State Area of an AFU to memory cxl_mmio_ptr return the address of the mapped AFU Problem State Area cxl_mmio_read32 read a 32-bit word from the mapped AFU Problem State Area cxl_mmio_read64 read a 64-bit word from the mapped AFU Problem State Area cxl_mmio_unmap unmap an AFU Problem State Area cxl_mmio_write32 write a 32-bit word to the mapped AFU Problem State Area cxl_mmio_write64 write a 32-bit word to the mapped AFU Problem State Area .TE .SS AFU Error Buffer query functions .TS ; lb lb lb l. Function Description _ cxl_errinfo_read read and copy the contents of afu_err_info buffer into the provided buffer cxl_errinfo_size returns the size of afu_err_buff in bytes .TE .SH SEE ALSO .BR cxl_adapter_afu_next (3), .BR cxl_adapter_dev_name (3), .BR cxl_adapter_free (3), .BR cxl_adapter_next (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_fd (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_free (3), .BR cxl_afu_get_process_element (3), .BR cxl_afu_host_thread_wait (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3), .BR cxl_afu_sysfs_pci (3), .BR cxl_errinfo_read (3), .BR cxl_errinfo_size (3), .BR cxl_event_pending (3), .BR cxl_for_each_adapter (3), .BR cxl_for_each_adapter_afu (3), .BR cxl_for_each_afu (3), .BR cxl_fprint_event (3), .BR cxl_fprint_unknown_event (3), .BR cxl_get_api_version (3), .BR cxl_get_api_version_compatible (3), .BR cxl_get_base_image (3), .BR cxl_get_caia_version (3), .BR cxl_get_cr_class (3), .BR cxl_get_cr_device (3), .BR cxl_get_cr_vendor (3), .BR cxl_get_image_loaded (3), .BR cxl_get_irqs_max (3), .BR cxl_get_irqs_min (3), .BR cxl_get_mmio_size (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_get_pp_mmio_len (3), .BR cxl_get_pp_mmio_off (3), .BR cxl_get_prefault_mode (3), .BR cxl_get_psl_revision (3), .BR cxl_get_psl_timebase_synced (3), .BR cxl_get_tunneled_ops_supported (3), .BR cxl_mmio_install_sigbus_handler (3), .BR cxl_mmio_map (3), .BR cxl_mmio_ptr (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_unmap (3), .BR cxl_mmio_write32 (3), .BR cxl_mmio_write64 (3), .BR cxl_read_event (3), .BR cxl_read_expected_event (3), .BR cxl_set_irqs_max (3), .BR cxl_set_mode (3), .BR cxl_set_prefault_mode (3) .BR cxl_work_alloc (3), .BR cxl_work_disable_wait (3), .BR cxl_work_enable_wait (3), .BR cxl_work_free (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_get_tid (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_num_irqs (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_adapter_afu_next.3000066400000000000000000000033131327654150600177500ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_ADAPTER_AFU_NEXT 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_adapter_afu_next \- iterate to the next AFU of a CXL adapter .PP cxl_for_each_adapter_afu \- iteration macro .SH SYNOPSIS .B #include .PP .B "struct cxl_afu_h *cxl_adapter_afu_next(struct cxl_adapter_h" .BI * adapter ", struct cxl_afu_h *" afu ); .SH DESCRIPTION .BR cxl_adapter_afu_next () returns an AFU handle describing the next AFU of the CXL .IR adapter . .PP When .I afu is NULL, then an AFU handle is allocated, and the first available AFU of .I adapter is returned. .PP When .I afu is the last AFU of the current .IR adapter , then the AFU handle is freed, .I errno is set to zero, and NULL is returned. Alternatively, the AFU handle can be freed explicitly with .BR cxl_afu_free (). .SH RETURN VALUE On success, an AFU handle is returned, or NULL is returned and .I errno is set to zero. On error, NULL is returned, and .I errno is set appropriately. .SH ERRORS .TP .B ENODEV Unsupported kernel CXL API. .TP .B ENOMEM Insufficient memory. .SH EXAMPLE The CXL library provides the following macro to enumerate the AFUs of a CXL adapter: .PP .nf #define cxl_for_each_adapter_afu(adapter, afu) \\ for (afu = cxl_adapter_afu_next(adapter, NULL); afu; \\ afu = cxl_adapter_afu_next(NULL, afu)) .fi .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_free (3), .BR cxl_afu_next (3), .BR cxl_afu_sysfs_pci (3), .BR cxl_get_mmio_size (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_get_pp_mmio_len (3), .BR cxl_get_pp_mmio_off (3), .BR cxl_get_prefault_mode (3), .BR cxl_set_mode (3), .BR cxl_set_prefault_mode (3) libcxl-1.7/man3/cxl_adapter_dev_name.3000066400000000000000000000010411327654150600177110ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_ADAPTER_DEV_NAME 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_adapter_dev_name \- return the CXL adapter device name .SH SYNOPSIS .B #include .PP .B "char *cxl_adapter_dev_name(struct cxl_adapter_h" .BI * adapter ); .SH DESCRIPTION .BR cxl_adapter_dev_name () returns the basename of the device associated to the CXL adapter handle .IR adapter . The devices of the CXL adapters are named .BR card0 , .BR card1 , etc. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3) libcxl-1.7/man3/cxl_adapter_free.3000066400000000000000000000010051327654150600170540ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_ADAPTER_FREE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_adapter_free \- free the CXL adapter data structures .SH SYNOPSIS .B #include .PP .B "void cxl_adapter_free(struct cxl_adapter_h" .BI * adapter ); .SH DESCRIPTION .BR cxl_adapter_free () frees the CXL .I adapter handle, previously allocated by .BR cxl_adapter_next (), as well as its associated data structures and memory buffers. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3) libcxl-1.7/man3/cxl_adapter_next.3000066400000000000000000000031301327654150600171120ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_ADAPTER_NEXT 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_adapter_next \- iterate to the next CXL adapter .PP cxl_for_each_adapter \- iteration macro .SH SYNOPSIS .B #include .PP .B "struct cxl_adapter_h *cxl_adapter_next(struct cxl_adapter_h" .BI * adapter ); .SH DESCRIPTION .BR cxl_adapter_next () returns an adapter handle describing the next available CXL adapter. .PP When .I adapter is NULL, then an adapter handle is allocated, and the first available adapter is returned. .PP When .I adapter is the last CXL adapter available, then the adapter handle is freed, .I errno is set to zero, and NULL is returned. Alternatively, the adapter handle can be freed explicitly with .BR cxl_adapter_free (). .SH RETURN VALUE On success, an adapter handle is returned, or NULL is returned and .I errno is set to zero. On error, NULL is returned, and .I errno is set appropriately. .SH ERRORS .TP .B ENODEV Unsupported kernel CXL API. .TP .B ENOMEM Insufficient memory. .SH EXAMPLE The CXL library provides the following macro to enumerate all CXL adapters: .PP .nf #define cxl_for_each_adapter(adapter) \\ for (adapter = cxl_adapter_next(NULL); adapter; \\ adapter = cxl_adapter_next(adapter)) .fi .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_adapter_dev_name (3), .BR cxl_adapter_free (3), .BR cxl_afu_next (3), .BR cxl_get_base_image (3), .BR cxl_get_caia_version (3), .BR cxl_get_image_loaded (3), .BR cxl_get_psl_revision (3), .BR cxl_get_psl_timebase_synced (3), .BR cxl_get_tunneled_ops_supported (3) libcxl-1.7/man3/cxl_afu_attach.3000066400000000000000000000031551327654150600165420ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_ATTACH 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_attach \- attach the calling process's memory to an open AFU .SH SYNOPSIS .B #include .PP .B "int cxl_afu_attach(struct cxl_afu_h" .BI * afu ", __u64 " wed ); .SH DESCRIPTION .BR cxl_afu_attach () attaches a context of .I afu to the current process, specifies .I wed as the initial work element descriptor, and starts the AFU context. .PP On success, all memory mapped into this process is accessible to the AFU context using the same effective addresses. No additional calls are required to map/unmap memory. The AFU memory context will be updated as userspace allocates and frees memory. .PP The work element descriptor .I wed is a 64-bit argument defined by the AFU. Typically this is an effective address pointing to an AFU specific structure describing what work to perform. .PP The minimum number of userspace interrupts required by the AFU will be allocated. This value is returned by .BR cxl_get_irqs_min (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or AFU not opened. .TP .B ENOMEM Not enough memory. .TP .B ENOSPC Not enough interrupts available. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_free (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_opened (3), .BR cxl_get_irqs_max (3), .BR cxl_get_irqs_min (3), .BR cxl_get_prefault_mode (3), .BR cxl_mmio_map (3), .BR cxl_set_mode (3), .BR cxl_set_prefault_mode (3) libcxl-1.7/man3/cxl_afu_attach_full.3000066400000000000000000000035421327654150600175640ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_ATTACH_FULL 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_attach_full \- attach the calling process's memory to an open AFU .SH SYNOPSIS .B #include .PP .B "int cxl_afu_attach_full(struct cxl_afu_h" .BI * afu ", __u64 " wed , .BI "__u16 " num_interrupts ", __u64 " amr ); .SH DESCRIPTION .BR cxl_afu_attach_full () attaches a context of .I afu to the current process, specifies .I wed as the initial work element descriptor, requests .IR num_interrupts , sets the authority mask register .IR amr , and starts the AFU context. .PP On success, all memory mapped into this process is accessible to the AFU context using the same effective addresses. No additional calls are required to map/unmap memory. The AFU memory context will be updated as userspace allocates and frees memory. .PP The work element descriptor .I wed is a 64-bit argument defined by the AFU. Typically this is an effective address pointing to an AFU specific structure describing what work to perform. .PP The number of requested userspace interrupts .I num_interrupts must be in the range defined by .BR cxl_get_irqs_min () and .BR cxl_get_irqs_max (). .PP The authority mask register .I amr is the same as the powerpc AMR. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or AFU not opened. .TP .B ENOMEM Not enough memory. .TP .B ENOSPC Not enough interrupts available. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_free (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_opened (3), .BR cxl_get_irqs_max (3), .BR cxl_get_irqs_min (3), .BR cxl_get_prefault_mode (3), .BR cxl_mmio_map (3), .BR cxl_set_irqs_max (3), .BR cxl_set_mode (3), .BR cxl_set_prefault_mode (3) libcxl-1.7/man3/cxl_afu_attach_work.3000066400000000000000000000051371327654150600176060ustar00rootroot00000000000000.\" Copyright 2015-2018 IBM Corp. .\" .TH CXL_AFU_ATTACH_WORK 3 2018-02-13 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_attach_work \- attach the calling process's memory to an open AFU .SH SYNOPSIS .B #include .PP .B "int cxl_afu_attach_work(struct cxl_afu_h" .BI * afu ", struct cxl_ioctl_start_work *" work ); .SH DESCRIPTION .BR cxl_afu_attach_work () attaches a context of .I afu to the current process, specifying various parameters via the .I work structure, and starts the AFU context. .PP On success, all memory mapped into this process is accessible to the AFU context using the same effective addresses. No additional calls are required to map/unmap memory. The AFU memory context will be updated as userspace allocates and frees memory. .PP Four parameters can be set in the .I work structure: .PP .BR cxl_work_set_wed () sets the work element descriptor, a 64-bit argument defined by the AFU. Typically this is an effective address pointing to an AFU specific structure describing what work to perform. .PP .BR cxl_work_set_num_irqs () requests a number of userspace interrupts, in the range defined by .BR cxl_get_irqs_min () and .BR cxl_get_irqs_max (). A negative value specifies that .BR cxl_afu_attach_work () should allocate the minimum number of interrupts required by an AFU context, returned by .BR cxl_get_irqs_min (). .PP .BR cxl_work_set_amr () sets the authority mask register (same as the powerpc AMR). A null value indicates that the authority mask register should not be set. .PP .BR cxl_work_enable_wait() indicates that the thread that will attach an AFU context requires to be able to wait and be notified by the AFU with .BR cxl_afu_host_thread_wait (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or AFU not opened. .TP .B ENOMEM Not enough memory. .TP .B ENOSPC Not enough interrupts available. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_free (3), .BR cxl_afu_host_thread_wait(3), .BR cxl_afu_open_dev (3), .BR cxl_afu_opened (3), .BR cxl_get_irqs_max (3), .BR cxl_get_irqs_min (3), .BR cxl_get_prefault_mode (3), .BR cxl_mmio_map (3), .BR cxl_set_irqs_max (3), .BR cxl_set_mode (3), .BR cxl_set_prefault_mode (3), .BR cxl_work_alloc (3), .BR cxl_work_disable_wait (3), .BR cxl_work_enable_wait (3), .BR cxl_work_free (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_get_tid (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_num_irqs (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_afu_dev_name.3000066400000000000000000000021331327654150600170470ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_DEV_NAME 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_dev_name \- return the AFU device name .SH SYNOPSIS .B #include .PP .B "char *cxl_afu_dev_name(struct cxl_afu_h" .BI * afu ); .SH DESCRIPTION .BR cxl_afu_dev_name () returns the basename of the device associated to .IR afu . The AFU devices of the CXL adapter .BI card are named .BI afu .0 \fR, .BI afu .1 \fR, etc. AFUs opened in dedicated process mode, or AFU directed mode in master or slave context, are respectly suffixed with .BR d , .BR m , and .BR s . .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_fd (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_get_process_element (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3), .BR cxl_afu_sysfs_pci (3) libcxl-1.7/man3/cxl_afu_fd.3000066400000000000000000000011131327654150600156570ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_FD 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_fd \- return the file descriptor of an AFU handle .SH SYNOPSIS .B #include .PP .B "int cxl_afu_fd(struct cxl_afu_h" .BI * afu ); .SH DESCRIPTION .BR cxl_afu_fd () returns the file descriptor of an open AFU, or \-1 if .I afu has not been opened. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_free (3), .BR cxl_afu_get_process_element (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3) libcxl-1.7/man3/cxl_afu_fd_to_h.3000066400000000000000000000034631327654150600167020ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_FD_TO_H 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_fd_to_h \- create an AFU handle from the file descriptor of an already open AFU .SH SYNOPSIS .B #include .PP .B "struct cxl_afu_h cxl_afu_fd_to_h(int" .IB fd ); .SH DESCRIPTION .BR cxl_afu_fd_to_h () returns an AFU handle from the already open AFU device associated to the file descriptor .IR fd . .PP A dedicated process mode AFU only has one context and only allows the device to be opened once. An AFU directed mode AFU can have many contexts, the device can be opened once for each context that is available. .SH RETURN VALUE On success, an AFU handle is returned. On error, NULL is returned, and .I errno is set appropriately. .SH ERRORS .TP .B EBADF Bad file descriptor. .TP .B ENODEV Kernel does not support CXL devices, or device is not an AFU. .TP .B ENOMEM Insufficient memory. .TP .B ENOSPC No AFU context available. .TP .B EPROTO Unsupported kernel CXL API version. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_fd (3), .BR cxl_afu_free (3), .BR cxl_afu_get_process_element (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3), .BR cxl_get_api_version (3), .BR cxl_get_api_version_compatible (3), .BR cxl_get_cr_class (3), .BR cxl_get_cr_device (3), .BR cxl_get_cr_vendor (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_read_event (3), .BR cxl_read_expected_event (3), .BR cxl_set_mode (3), .BR open (2) libcxl-1.7/man3/cxl_afu_free.3000066400000000000000000000011771327654150600162210ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_FREE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_free \- free the data structures of an AFU handle .SH SYNOPSIS .B #include .PP .B "void cxl_afu_free(struct cxl_afu_h" .BI * afu ); .SH DESCRIPTION .BR cxl_afu_free () frees the data structures and memory buffers of .IR afu . .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_fd (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3) libcxl-1.7/man3/cxl_afu_get_process_element.3000066400000000000000000000014511327654150600213210ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_GET_PROCESS_ELEMENT 3 2017-05-24 "LIBCXL 1.5" "CXL Manual" .SH NAME cxl_afu_get_process_element \- get the process element associated with an open AFU handle .SH SYNOPSIS .B #include .PP .BI "int cxl_afu_get_process_element(struct cxl_afu_h *" afu ); .SH DESCRIPTION .BR cxl_afu_get_process_element () returns the process element number associated with the open .IR afu . .SH RETURN VALUE On success, the process element number is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B EIO AFU not opened. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_fd (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3) libcxl-1.7/man3/cxl_afu_host_thread_wait.3000066400000000000000000000027631327654150600206320ustar00rootroot00000000000000.\" Copyright 2018 IBM Corp. .\" .TH CXL_AFU_HOST_THREAD_WAIT 3 2018-04-24 "LIBCXL 1.6" "CXL Manual" .SH NAME cxl_afu_host_thread_wait \- wait for AFU notification .SH SYNOPSIS .B #include .PP .B "int afu_host_thread_wait(struct cxl_afu_h" .BI * afu ", volatile __u64 *" uword ); .SH DESCRIPTION The tunneled operation as_notify is supported on POWER9. See .BR cxl_get_tunneled_ops_supported (). .PP The thread calling .BR afu_host_thread_wait () executes the instruction "wait" and goes to sleep. It will resume execution upon receiving an interrupt or an .I afu notification. It will then check the value of the shared memory word pointed to by .IR uword . The thread will loop and sleep again while the value of .I uword is equal to zero. It will return from .BR afu_host_thread_wait () when the value of .I uword becomes different from zero. .PP The thread calling .BR afu_host_thread_wait () must have attached an .I afu context to a work structure with .BR cxl_afu_attach_work () The work structure must have been wait-enabled with .BR cxl_work_enable_wait (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value .TP .B EPERM AFU context not attached by current thread, or wait not enabled .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_host_thread_wait (3), .BR cxl_get_tunneled_ops_supported (3), .BR cxl_work_disable_wait (3), .BR cxl_work_enable_wait (3), .BR cxl_work_get_tid (3) libcxl-1.7/man3/cxl_afu_next.3000066400000000000000000000030011327654150600162420ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_NEXT 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_next \- iterate to the next AFU .PP cxl_for_each_afu \- iteration macro .SH SYNOPSIS .B #include .PP .B "struct cxl_afu_h *cxl_afu_next(struct cxl_afu_h" .BI * afu ); .SH DESCRIPTION .BR cxl_afu_next () returns an AFU handle describing the next available AFU. .PP When .I afu is NULL, then an AFU handle is allocated, and the first available AFU is returned. .PP When .I afu is the last AFU available, then the AFU handle is freed, .I errno is set to zero, and NULL is returned. Alternatively, the AFU handle can be freed explicitly with .BR cxl_afu_free (). .SH RETURN VALUE On success, an AFU handle is returned, or NULL is returned and .I errno is set to zero. On error, NULL is returned, and .I errno is set appropriately. .SH ERRORS .TP .B ENODEV Kernel does not support CXL devices. .TP .B ENOMEM Insufficient memory. .SH EXAMPLE The CXL library provides the following macro to enumerate all AFUs: .PP .nf #define cxl_for_each_afu(afu) \\ for (afu = cxl_afu_next(NULL); afu; afu = cxl_afu_next(afu)) .fi .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_adapter_next (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_free (3), .BR cxl_afu_sysfs_pci (3), .BR cxl_get_mmio_size (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_get_pp_mmio_len (3), .BR cxl_get_pp_mmio_off (3), .BR cxl_get_prefault_mode (3), .BR cxl_set_mode (3), .BR cxl_set_prefault_mode (3) libcxl-1.7/man3/cxl_afu_open_dev.3000066400000000000000000000033461327654150600170770ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_OPEN_DEV 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_open_dev \- open an AFU by device name .SH SYNOPSIS .B #include .PP .B "struct cxl_afu_h cxl_afu_open_dev(char" .BI * path ); .SH DESCRIPTION .BR cxl_afu_open_dev () opens the device .I path and returns an AFU handle. .PP A dedicated process mode AFU only has one context and only allows the device to be opened once. An AFU directed mode AFU can have many contexts, the device can be opened once for each context that is available. .SH RETURN VALUE On success, an AFU handle is returned. On error, NULL is returned, and .I errno is set appropriately. .SH ERRORS .TP .B ENODEV Kernel does not support CXL devices, or device is not an AFU. .TP .B ENOENT Device does not exist. .TP .B ENOMEM Insufficient memory. .TP .B ENOSPC No AFU context available. .TP .B EPROTO Unsupported kernel CXL API version. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_fd (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_free (3), .BR cxl_afu_get_process_element (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3), .BR cxl_get_api_version (3), .BR cxl_get_api_version_compatible (3), .BR cxl_get_cr_class (3), .BR cxl_get_cr_device (3), .BR cxl_get_cr_vendor (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_read_event (3), .BR cxl_read_expected_event (3), .BR cxl_set_mode (3), .BR open (2) libcxl-1.7/man3/cxl_afu_open_h.3000066400000000000000000000035561327654150600165530ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_OPEN_H 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_open_h \- open an AFU by AFU handle .SH SYNOPSIS .B #include .PP .B "struct cxl_afu_h cxl_afu_open_h(struct cxl_afu_h" .BI * afu ", enum cxl_views " view ); .SH DESCRIPTION .BR cxl_afu_open_h () opens the device and returns a new AFU handle for .IR afu , as specified by the CXL .IR view : .TP .B CXL_VIEW_DEDICATED AFU opened in dedicated process mode, .TP .B CXL_VIEW_MASTER AFU opened in AFU directed mode, master context, .TP .B CXL_VIEW_SLAVE AFU opened in AFU directed mode, slave context. .PP A dedicated process mode AFU only has one context and only allows the device to be opened once. An AFU directed mode AFU can have many contexts, the device can be opened once for each context that is available. .SH RETURN VALUE On success, an AFU handle is returned. On error, NULL is returned, and .I errno is set appropriately. .SH ERRORS .TP .B ENODEV The AFU does not support this view. .TP .B ENOMEM Insufficient memory. .TP .B ENOSPC No AFU context available. .TP .B EPROTO Unsupported kernel CXL API version. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_fd (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_free (3), .BR cxl_afu_get_process_element (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_opened (3), .BR cxl_get_api_version (3), .BR cxl_get_api_version_compatible (3), .BR cxl_get_cr_class (3), .BR cxl_get_cr_device (3), .BR cxl_get_cr_vendor (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_read_event (3), .BR cxl_read_expected_event (3), .BR cxl_set_mode (3), .BR open (2) libcxl-1.7/man3/cxl_afu_opened.3000066400000000000000000000015221327654150600165440ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_OPENED 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_opened \- return whether an AFU handle is opened .SH SYNOPSIS .B #include .PP .B "int cxl_afu_opened(struct cxl_afu_h" .BI * afu ); .SH DESCRIPTION .BR cxl_afu_opened () returns 1 if .I afu is open, or else 0. .SH RETURN VALUE On success, 0 or 1 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_fd (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_free (3), .BR cxl_afu_get_process_element (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_read_event (3), .BR cxl_read_expected_event (3) libcxl-1.7/man3/cxl_afu_sysfs_pci.3000066400000000000000000000016631327654150600173020ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_AFU_SYSFS_PCI 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_afu_sysfs_pci \- get the sysfs path to the PCI device corresponding with an AFU .SH SYNOPSIS .B #include .PP .B "int cxl_afu_sysfs_pci(struct cxl_afu_h" .BI * afu ", char **" pathp ); .SH DESCRIPTION .BR cxl_afu_sysfs_pci () copies the address of a buffer containing the sysfs path to the PCI device corresponding with .I afu into the pointer .IR pathp . .PP On success, this function automatically allocates the returned buffer, which must be freed by the caller (much like asprintf). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR asprintf (3), .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_dev_name (3), .BR cxl_afu_next (3), .BR free (3) libcxl-1.7/man3/cxl_errinfo_read.3000066400000000000000000000031721327654150600171010ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_ERRINFO_READ 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_errinfo_read \- Read and copy the contents of afu_err_info buffer .SH SYNOPSIS .BR #include .PP .BI "ssize_t cxl_errinfo_read(struct cxl_afu_h " .BI * afu ", void *" dst ", off_t " off ", size_t " len ); .SH DESCRIPTION .PP .BR cxl_errinfo_read " attempts to read upto" .IR len " bytes located at offset " off " in " AFU Error Buffer and copy it to user provided buffer located at .IR dst "." .PP AFU Error Buffer is used by the afu to report application specific errors. The contents of this buffer are afu specific and are intended to be interpreted by the application interacting with the afu. .SH RETURN VALUE On success, returns the number of bytes copied from the afu_err_buff to .IB dst . On error, -1 is returned, .I errno is set appropriately and the contents at .I dst are not touched. .SH ERRORS .TP .B ENOENT The AFU does not export afu_err_buff region. .TP .B EACCES Permission to read the contents of AFU Error buffer is denied. .TP .B ENOMEM Insufficient memory. .TP .B ENOSPC No AFU context available. .TP .B EPROTO Unsupported kernel CXL API version. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .TP .BI /dev/cxl/afu . /afu_err_buff AFU Error Buffer contents. The contents of this file are application specific and depends on the AFU being used. .SH SEE ALSO .BR cxl (3), .BR cxl_errinfo_size (3) libcxl-1.7/man3/cxl_errinfo_size.3000066400000000000000000000027151327654150600171420ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_ERRINFO_SIZE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_errinfo_size \- returns the size of afu_err_buff in bytes .SH SYNOPSIS .BR #include .PP .BI "int cxl_errinfo_size(struct cxl_afu_h " .BI * afu ", size_t *" valp ); .SH DESCRIPTION .PP .BR cxl_errinfo_size stores the size (in bytes) of the .B AFU Error Buffer associated with the provided .IB afu context handle at .IB valp . .PP Applications can also use this function to determine if the afu_err_buff exists for the attached .IR afu . .SH RETURN VALUE On success, 0 is returned and size of the buffer is stored at .I valp On error, -1 is returned, .I errno is set appropriately and the contents at .I valp are not touched .SH ERRORS .TP .B ENOENT The AFU does not export afu_err_buff region. .TP .B EACCES Permission to read the contents of AFU Error buffer is denied. .TP .B ENOMEM Insufficient memory. .TP .B ENOSPC No AFU context available. .TP .B EPROTO Unsupported kernel CXL API version. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .TP .BI /dev/cxl/afu . /afu_err_buff AFU Error Buffer contents. The contents of this file are application specific and depends on the AFU being used. .SH SEE ALSO .BR cxl (3), .BR cxl_errinfo_read (3) libcxl-1.7/man3/cxl_event_pending.3000066400000000000000000000012521327654150600172640ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_EVENT_PENDING 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_event_pending \- return whether a CXL event is pending .SH SYNOPSIS .B #include .PP .B "int cxl_event_pending(struct cxl_afu_h" .BI * afu ); .SH DESCRIPTION .BR cxl_event_pending () returns 1 if a CXL event can be read from .IR afu , or else 0. .SH RETURN VALUE On success, 0 or 1 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_fprint_event (3), .BR cxl_fprint_unknown_event (3), .BR cxl_read_event (3), .BR cxl_read_expected_event (3) libcxl-1.7/man3/cxl_for_each_adapter.3000066400000000000000000000000341327654150600177020ustar00rootroot00000000000000.so man3/cxl_adapter_next.3 libcxl-1.7/man3/cxl_for_each_adapter_afu.3000066400000000000000000000000401327654150600205320ustar00rootroot00000000000000.so man3/cxl_adapter_afu_next.3 libcxl-1.7/man3/cxl_for_each_afu.3000066400000000000000000000000301327654150600170310ustar00rootroot00000000000000.so man3/cxl_afu_next.3 libcxl-1.7/man3/cxl_fprint_event.3000066400000000000000000000017611327654150600171470ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_FPRINT_EVENT 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_fprint_event \- print out a description of a CXL event for debugging .SH SYNOPSIS .B #include .br .B #include .PP .BI "int cxl_fprint_event(FILE *" stream , .BI "struct cxl_event *" event ); .SH DESCRIPTION .BR cxl_fprint_event () prints out a description of the CXL .I event to the file .IR stream . .PP The description is based on the event type. If the type is unknown, then .BR cxl_fprint_event () calls .BR cxl_fprint_unknown_event () instead, and prints out a hex dump of the raw event. .SH RETURN VALUE On success, the number of bytes written to .I stream is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODATA No data available. .SH SEE ALSO .BR cxl (3), .BR cxl_fprint_unknown_event (3), .BR cxl_event_pending (3), .BR cxl_read_event (3), .BR cxl_read_expected_event (3) libcxl-1.7/man3/cxl_fprint_unknown_event.3000066400000000000000000000014341327654150600207230ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_FPRINT_UNKNOWN_EVENT 3 2017-05-24 "LIBCXL 1.5" "CXL Manual" .SH NAME cxl_fprint_unknown_event \- print out a hex dump of a raw CXL event for debugging .SH SYNOPSIS .B #include .br .B #include .PP .BI "int cxl_fprint_unknown_event(FILE *" stream , .BI "struct cxl_event *" event ); .SH DESCRIPTION .BR cxl_fprint_unknown_event () prints out a hex dump of the raw CXL .I event to the file .IR stream . .SH RETURN VALUE On success, the number of bytes written to .I stream is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_fprint_event (3), .BR cxl_event_pending (3), .BR cxl_read_event (3), .BR cxl_read_expected_event (3) libcxl-1.7/man3/cxl_get_api_version.3000066400000000000000000000015071327654150600176170ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_API_VERSION 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_api_version \- get the version of the kernel CXL API .SH SYNOPSIS .B #include .PP .B "int cxl_get_api_version(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_api_version () copies the CXL API version of .I afu to the long integer pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_get_api_version_compatible (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_get_prefault_mode (3) libcxl-1.7/man3/cxl_get_api_version_compatible.3000066400000000000000000000016371327654150600220220ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_API_VERSION_COMPATIBLE 3 2017-05-24 "LIBCXL 1.5" "CXL Manual" .SH NAME cxl_get_api_version_compatible \- get the lowest CXL API version compatible with the kernel .SH SYNOPSIS .B #include .PP .B "int cxl_get_api_version_compatible(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_api_version_compatible () copies the lowest CXL API version compatible with the kernel, supported by .IR afu , to the long integer pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_get_api_version (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_get_prefault_mode (3) libcxl-1.7/man3/cxl_get_base_image.3000066400000000000000000000021211327654150600173460ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_BASE_IMAGE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_base_image \- get the revision level of the initial PSL image loaded on the CXL device .SH SYNOPSIS .B #include .PP .B "int cxl_get_base_image(struct cxl_adapter_h" .BI * adapter ", long *" valp ); .SH DESCRIPTION For CXL devices that support loadable PSLs, .BR cxl_get_base_image () identifies the revision level of the base image. For FPGAs, this attribute identifies the image contained in the on-card flash which is loaded during the initial program load. The .I adapter base image revision level is copied to the long integer pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3), .BR cxl_get_caia_version (3), .BR cxl_get_image_loaded (3), .BR cxl_get_psl_revision (3), .BR cxl_get_psl_timebase_synced (3), .BR cxl_get_tunneled_ops_supported (3) libcxl-1.7/man3/cxl_get_caia_version.3000066400000000000000000000016471327654150600177500ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_CAIA_VERSION 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_caia_version \- get the CAIA version supported by a CXL adapter .SH SYNOPSIS .B #include .PP .B "int cxl_get_caia_version(struct cxl_adapter_h" .BI * adapter ", long *" majorp , .BI "long *" minorp ); .SH DESCRIPTION .BR cxl_get_caia_version () copies the major and minor values of the CAIA version implemented on .I adapter to the long integers pointed to by .I majorp and .IR minorp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3), .BR cxl_get_base_image (3), .BR cxl_get_image_loaded (3), .BR cxl_get_psl_revision (3), .BR cxl_get_psl_timebase_synced (3), .BR cxl_get_tunneled_ops_supported (3) libcxl-1.7/man3/cxl_get_cr_class.3000066400000000000000000000016511327654150600170720ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_CR_CLASS 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_cr_class \- get the class code out of an AFU configuration record .SH SYNOPSIS .B #include .PP .B "int cxl_get_cr_class(struct cxl_afu_h" .BI * afu ", long " cr_num ", long *" valp ); .SH DESCRIPTION .BR cxl_get_cr_class () copies the class code found in the .I afu configuration record number .IR cr_num , to the long integer pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODEV Configuration record does not exist. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_get_cr_device (3), .BR cxl_get_cr_vendor (3) libcxl-1.7/man3/cxl_get_cr_device.3000066400000000000000000000016521327654150600172250ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_CR_DEVICE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_cr_device \- get the device ID out of an AFU configuration record .SH SYNOPSIS .B #include .PP .B "int cxl_get_cr_device(struct cxl_afu_h" .BI * afu ", long " cr_num ", long *" valp ); .SH DESCRIPTION .BR cxl_get_cr_device () copies the device ID found in the .I afu configuration record number .IR cr_num , to the long integer pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODEV Configuration record does not exist. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_get_cr_class (3), .BR cxl_get_cr_vendor (3) libcxl-1.7/man3/cxl_get_cr_vendor.3000066400000000000000000000016521327654150600172630ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_CR_VENDOR 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_cr_vendor \- get the vendor ID out of an AFU configuration record .SH SYNOPSIS .B #include .PP .B "int cxl_get_cr_vendor(struct cxl_afu_h" .BI * afu ", long " cr_num ", long *" valp ); .SH DESCRIPTION .BR cxl_get_cr_vendor () copies the vendor ID found in the .I afu configuration record number .IR cr_num , to the long integer pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODEV Configuration record does not exist. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_get_cr_class (3), .BR cxl_get_cr_device (3) libcxl-1.7/man3/cxl_get_image_loaded.3000066400000000000000000000020241327654150600176660ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_IMAGE_LOADED 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_image_loaded \- returns which of the user and factory PSL images is currently loaded on the CXL device .SH SYNOPSIS .B #include .PP .B "int cxl_get_image_loaded(struct cxl_adapter_h" .BI * adapter ", enum cxl_image *" valp ); .SH DESCRIPTION .BR cxl_get_image_loaded () copies which of the user and factory PSL images is current ly loaded on the CXL device .I adapter to the long integer pointed to by .IR valp . The .B "enum cxl_image" value will be .B CXL_IMAGE_FACTORY or .BR CXL_IMAGE_USER . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3), .BR cxl_get_base_image (3), .BR cxl_get_caia_version (3), .BR cxl_get_psl_revision (3), .BR cxl_get_psl_timebase_synced (3), .BR cxl_get_tunneled_ops_supported (3) libcxl-1.7/man3/cxl_get_irqs_max.3000066400000000000000000000024211327654150600171200ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_IRQS_MAX 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_irqs_max \- get the maximum number of AFU interrupts available to a context, if it was the only context running .SH SYNOPSIS .B #include .PP .B "int cxl_get_irqs_max(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_irqs_max () copies to the long integer pointed to by .I valp the maximum number of AFU interrupts available to a context of .IR afu , if it was the only context running. .PP This is the maximum number of interrupts that may be requested when calling .BR cxl_afu_attach_full () or .BR cxl_afu_attach_work () for .IR afu . The default on probe is the maximum that hardware can support. It can be administratively restricted with .BR cxl_set_irqs_max (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_get_irqs_min (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_get_prefault_mode (3), .BR cxl_set_irqs_max (3), .BR cxl_work_set_num_irqs (3) libcxl-1.7/man3/cxl_get_irqs_min.3000066400000000000000000000021641327654150600171220ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_IRQS_MIN 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_irqs_min \- get the minimum number of AFU interrupts required for each context .SH SYNOPSIS .B #include .PP .B "int cxl_get_irqs_min(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_irqs_min () copies to the long integer pointed to by .I valp the minimum number of AFU interrupts required for each context of .IR afu . .PP This is the minimum number that must be requested when calling .BR cxl_afu_attach_full () or .BR cxl_afu_attach_work () for .IR afu . It is implicitly requested by .BR cxl_afu_attach (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_get_irqs_max (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_get_prefault_mode (3), .BR cxl_set_irqs_max (3), .BR cxl_work_set_num_irqs (3) libcxl-1.7/man3/cxl_get_mmio_size.3000066400000000000000000000026731327654150600173010ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_MMIO_SIZE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_mmio_size \- get the total size of the MMIO space of an AFU, including all per-process areas .PP cxl_get_mmio_size \- get the size of the MMIO space available to a non-master process .SH SYNOPSIS .B #include .PP .B "int cxl_get_mmio_size(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_mmio_size () copies the size of the MMIO space of .I afu to the long integer pointed to by .IR valp . .PP In AFU directed mode, the master context MMIO space includes all slave context per-process MMIO areas. In slave context, .BR cxl_get_mmio_size () returns the size of the per-process MMIO space. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODEV Invalid AFU device. .TP .B ENOMEM Insufficient memory. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_next (3), .BR cxl_mmio_map (3), .BR cxl_mmio_ptr (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_unmap (3), .BR cxl_mmio_write32 (3), .BR cxl_mmio_write64 (3) libcxl-1.7/man3/cxl_get_mode.3000066400000000000000000000020761327654150600162270ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_MODE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_mode \- get the current programming mode of an AFU .SH SYNOPSIS .B #include .PP .B "int cxl_get_mode(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_mode () copies the current programming mode used by .I afu to the long integer pointed to by .IR valp . Mode will be one of the modes returned by .BR cxl_get_modes_supported (): .B CXL_MODE_DEDICATED or .BR CXL_MODE_DIRECTED , .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_get_api_version (3), .BR cxl_get_api_version_compatible (3), .BR cxl_get_irqs_max (3), .BR cxl_get_irqs_min (3), .BR cxl_get_modes_supported (3), .BR cxl_get_prefault_mode (3), .BR cxl_set_mode (3) libcxl-1.7/man3/cxl_get_modes_supported.3000066400000000000000000000021051327654150600205100ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_MODES_SUPPORTED 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_modes_supported \- get the programming modes supported by an AFU .SH SYNOPSIS .B #include .PP .B "int cxl_get_mode_supported(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_mode_supported () copies the mask of the modes supported by .I afu to the long integer pointed to by .IR valp . The following bits may be set in the mode mask: .B CXL_MODE_DEDICATED and .BR CXL_MODE_DIRECTED . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_get_api_version (3), .BR cxl_get_api_version_compatible (3), .BR cxl_get_irqs_max (3), .BR cxl_get_irqs_min (3), .BR cxl_get_mode (3), .BR cxl_get_prefault_mode (3), .BR cxl_set_mode (3) libcxl-1.7/man3/cxl_get_pp_mmio_len.3000066400000000000000000000016241327654150600175770ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_PP_MMIO_LEN 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_pp_mmio_len \- get the per-process MMIO space length .SH SYNOPSIS .B #include .PP .B "int cxl_get_pp_mmio_len(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_pp_mmio_len () copies the per-process MMIO space length of .I afu to the long integer pointed to by .IR valp . The AFU must be opened in AFU directed mode, master context. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODEV Invalid AFU device. .TP .B ENOMEM Insufficient memory. .SH FILES .TP .BI /dev/cxl/afu . m AFU device in directed mode, master context. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_next (3), .BR cxl_get_pp_mmio_off (3) libcxl-1.7/man3/cxl_get_pp_mmio_off.3000066400000000000000000000016241327654150600175730ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_PP_MMIO_OFF 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_pp_mmio_off \- get the per-process MMIO space offset .SH SYNOPSIS .B #include .PP .B "int cxl_get_pp_mmio_off(struct cxl_afu_h" .BI * afu ", long *" valp ); .SH DESCRIPTION .BR cxl_get_pp_mmio_off () copies the per-process MMIO space offset of .I afu to the long integer pointed to by .IR valp . The AFU must be opened in AFU directed mode, master context. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODEV Invalid AFU device. .TP .B ENOMEM Insufficient memory. .SH FILES .TP .BI /dev/cxl/afu . m AFU device in directed mode, master context. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_next (3), .BR cxl_get_pp_mmio_len (3) libcxl-1.7/man3/cxl_get_prefault_mode.3000066400000000000000000000027641327654150600201350ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_PREFAULT_MODE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_prefault_mode \- get the mode for prefaulting segments .SH SYNOPSIS .B #include .PP .B "int cxl_get_prefault_mode(struct cxl_afu_h" .BI * afu ", enum cxl_prefault_mode *" valp ); .SH DESCRIPTION .BR cxl_get_prefault_mode () gets the current mode used for prefaulting in segments into the segment table when performing .BR cxl_afu_attach (). The prefault_mode of .I afu is copied to the long integer pointed to by .IR valp . Mode will be one of the .B "enum cxl_prefault_mode" values: .TP .B CXL_PREFAULT_MODE_NONE No prefaulting (default). .TP .B CXL_PREFAULT_MODE_WED Treat the work element descriptor as an effective address and prefault what it points to. .TP .B CXL_PREFAULT_MODE_ALL Prefault all the segments mapped by the process calling .BR cxl_afu_attach (), .BR cxl_afu_attach_full () or .BR cxl_afu_attach_work (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_next (3), .BR cxl_get_api_version (3), .BR cxl_get_api_version_compatible (3), .BR cxl_get_irqs_max (3), .BR cxl_get_irqs_min (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3), .BR cxl_set_prefault_mode (3) libcxl-1.7/man3/cxl_get_psl_revision.3000066400000000000000000000016261327654150600200170ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_PSL_REVISION 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_get_psl_revision \- get the revision level of the current PSL image loaded on the CXL device .SH SYNOPSIS .B #include .PP .B "int cxl_get_psl_revision(struct cxl_adapter_h" .BI * adapter ", long *" valp ); .SH DESCRIPTION .BR cxl_get_psl_revision () copies the revision level of the current PSL image loaded on the CXL .I adapter to the long integer pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3), .BR cxl_get_base_image (3), .BR cxl_get_caia_version (3), .BR cxl_get_image_loaded (3) .BR cxl_get_psl_timebase_synced (3), .BR cxl_get_tunneled_ops_supported (3) libcxl-1.7/man3/cxl_get_psl_timebase_synced.3000066400000000000000000000020301327654150600213050ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_GET_PSL_TIMEBASE_SYNCED 3 2017-05-24 "LIBCXL 1.5" "CXL Manual" .SH NAME cxl_get_psl_timebase_synced \- get the status of timebase on the CXL device .SH SYNOPSIS .B #include .PP .B "int cxl_get_psl_timebase_synced(struct cxl_adapter_h" .BI * adapter ", long *" valp ); .SH DESCRIPTION .BR cxl_get_psl_timebase_synced () copies the status of timebase on the CXL .I adapter to the long integer pointed to by .IR valp . This value will be 1 if the PSL timebase register is synchronized with the core timebase register, 0 otherwise. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODEV The kernel does not export the PSL timebase status. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3), .BR cxl_get_base_image (3), .BR cxl_get_caia_version (3), .BR cxl_get_image_loaded (3), .BR cxl_get_psl_revision (3), .BR cxl_get_tunneled_ops_supported(3) libcxl-1.7/man3/cxl_get_tunneled_ops_supported.3000066400000000000000000000025761327654150600221140ustar00rootroot00000000000000.\" Copyright 2018 IBM Corp. .\" .TH CXL_GET_TUNNELED_OPS_SUPPORTED 3 2018-04-26 "LIBCXL 1.7" "CXL Manual" .SH NAME cxl_get_tunneled_ops_supported \- get the status of tunneled operations on the CXL device .SH SYNOPSIS .B #include .PP .B "int cxl_get_tunneled_ops_supported(struct cxl_adapter_h" .BI * adapter ", long *" valp ); .SH DESCRIPTION .BR cxl_get_tunneled_ops_supported () copies the status of tunneled operations on the CXL .I adapter to the long integer pointed to by .IR valp . This value will be 1 if tunneled operations are supported in capi mode, 0 otherwise. .PP Tunneled operations (atomics and as_notify) are supported on POWER9. Libcxl functions related to as_notify are .BR cxl_afu_host_thread_wait (), .BR cxl_work_disable_wait (), .BR cxl_work_enable_wait () and .BR cxl_work_get_tid (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .TP .B ENODEV The kernel does not export the tunneled operations status. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_next (3), .BR cxl_afu_host_thread_wait (3), .BR cxl_get_base_image (3), .BR cxl_get_caia_version (3), .BR cxl_get_image_loaded (3), .BR cxl_get_psl_revision (3), .BR cxl_get_timebase_synced (3) .BR cxl_work_disable_wait (3), .BR cxl_work_enable_wait (3), .BR cxl_work_get_tid (3) libcxl-1.7/man3/cxl_mmio_install_sigbus_handler.3000066400000000000000000000040701327654150600222000ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_MMIO_INSTALL_SIGBUS_HANDLER 3 2017-05-24 "" "CXL Programmer's Manual" .SH NAME cxl_mmio_install_sigbus_handler \- install the libcxl SIGBUS handler to catch MMIO access errors .SH SYNOPSIS .B #include .PP .B "int cxl_mmio_install_sigbus_handler();" .SH DESCRIPTION .BR cxl_mmio_install_sigbus_handler () installs the libcxl SIGBUS handler, which changes the behaviour of .BR cxl_mmio_read32 (), .BR cxl_mmio_read64 (), .BR cxl_mmio_write32 () and .BR cxl_mmio_write64 () on IO errors. If a SIGBUS is received from the kernel during one of these calls the libcxl SIGBUS handler will catch it and cause these calls to return -1 and set errno to EIO. If the libcxl SIGBUS handler has not been installed before these calls are made (and the application has not installed it's own handler), the SIGBUS from the kernel would terminate the program, which may be preferable in many cases for simplicity. Additionally, if the handler has not been installed and the cxl_mmio_read* calls detect an error due to a read of all F's, they will themselves raise a SIGBUS to terminate the program. This simplifies handling of IO errors for the application as it needs to either install the sigbus handler and be prepared to handle errors from the MMIO accessor functions, or treat any such error as fatal and receive a SIGBUS. The libcxl SIGBUS handler can chain to a handler installed by the application prior to calling .BR cxl_mmio_install_sigbus_handler(). If the handler is invoked and libcxl determines that the signal was not due to an IO error from a CXL MMIO access, it will call any SIGBUS handler that was previously installed. If the handler had previously been set to SIG_IGN it will ignore the signal and if it had been set to SIG_DFL it will remove itself and re-raise the signal, thereby terminating the program. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH SEE ALSO .BR cxl (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_write32 (3), .BR cxl_mmio_write64 (3) libcxl-1.7/man3/cxl_mmio_map.3000066400000000000000000000041561327654150600162430ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_MMIO_MAP 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_mmio_map \- map the per-process Problem State Area of an AFU to memory .SH SYNOPSIS .B #include .PP .B "int cxl_mmio_map(struct cxl_afu_h" .BI * afu ", __u32 " flag ); .SH DESCRIPTION .BR cxl_mmio_map () maps the per-process Problem State Area of .I afu to the current process memory, and declares AFU endianness according to .IR flag . The size and contents of this area are specific each AFU. The size can be discovered with .BR cxl_get_mmio_size (). .PP In AFU directed mode, master contexts are allowed to map all of the MMIO space and slave contexts are allowed to only map the per process MMIO space associated with the context. In dedicated process mode the entire MMIO space can always be mapped. .PP The possible values of .I flag are: .TP .B CXL_MMIO_BIG_ENDIAN AFU data is big-endian .TP .B CXL_MMIO_LITTLE_ENDIAN AFU data is little-endian .TP .B CXL_MMIO_HOST_ENDIAN AFU uses the same endianness as host. .PP Subsequent .BR cxl_mmio_read32 (), .BR cxl_mmio_read64 (), .BR cxl_mmio_write32 () and .BR cxl_mmio_write64 () will honor .I flag and swap bytes on behalf of the application when required. Only 32 and 64-bit accesses are supported by POWER8 and POWER9. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or AFU does not support MMIO space. .TP .B EIO AFU context is not attached. .TP .B ENODEV AFU not opened, or missing flags. .TP .B ENOMEM Insufficient memory. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_get_mmio_size (3), .BR cxl_mmio_ptr (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_unmap (3), .BR cxl_mmio_write32 (3), .BR cxl_mmio_write64 (3), .BR mmap (3) libcxl-1.7/man3/cxl_mmio_ptr.3000066400000000000000000000015141327654150600162660ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_MMIO_PTR 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_mmio_ptr \- return the address of the mapped AFU Problem State Area .SH SYNOPSIS .B #include .PP .B "int cxl_mmio_ptr(struct cxl_afu_h" .BI * afu ", void **" mmio_ptr ); .SH DESCRIPTION .BR cxl_mmio_ptr () copies the address of the mapped Problem State Area of .I afu to the pointer .IR mmio_ptr . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or MMIO space not mapped. .TP .B ENOMEM Insufficient memory. .SH SEE ALSO .BR cxl (3), .BR cxl_get_mmio_size (3), .BR cxl_mmio_map (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_unmap (3), .BR cxl_mmio_write32 (3), .BR cxl_mmio_write64 (3) libcxl-1.7/man3/cxl_mmio_read32.3000066400000000000000000000037421327654150600165460ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_MMIO_READ32 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_mmio_read32 \- read a 32-bit word from the mapped AFU Problem State Area .SH SYNOPSIS .B #include .PP .B "int cxl_mmio_read32(struct cxl_afu_h " .BI * afu ", uint64_t " offset , .BI "uint32_t *" data ); .SH DESCRIPTION .BR cxl_mmio_read32 () reads the 32-bit word at .I offset from the address of the mapped Problem State Area of .IR afu , and copies its value to the word pointed to by .IR data . The copy will include byte swapping if the AFU endianness declared by .BR cxl_mmio_map () differs from the host endianness. .PP .I offset is a byte address that is aligned on a word (4 byte) boundary. It must be lower than the MMIO size returned by .BR cxl_get_mmio_size (). The address of the mapped MMIO space is returned by .BR cxl_mmio_ptr (). .PP If the MMIO access fails due to an IO error, a SIGBUS may be sent to the application, which would ordinarily result in the process being terminated. libcxl provides an optional SIGBUS handler, which can be installed with .BR cxl_mmio_install_sigbus_handler (). .PP Installing this signal handler prior to using the MMIO accessor functions will cause them to return -1 and set .I errno to EIO in the event of an IO error. Additionally, if this handler has NOT been installed, the cxl_mmio_read* functions will raise a SIGBUS in the event that they detect an IO error due to a read of all F's for consistency. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or unmapped MMIO space. .TP .B EIO An unrecoverable error .RB ( cxl_mmio_install_sigbus_handler () must have been previously called) .SH SEE ALSO .BR cxl (3), .BR cxl_get_mmio_size (3), .BR cxl_mmio_install_sigbus_handler (3), .BR cxl_mmio_map (3), .BR cxl_mmio_ptr (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_unmap (3), .BR cxl_mmio_write32 (3), .BR cxl_mmio_write64 (3) libcxl-1.7/man3/cxl_mmio_read64.3000066400000000000000000000037361327654150600165560ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_MMIO_READ64 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_mmio_read64 \- read a 64-bit word from the mapped AFU Problem State Area .SH SYNOPSIS .B #include .PP .B "int cxl_mmio_read64(struct cxl_afu_h " .BI * afu ", uint64_t " offset , .BI "uint64_t *" data ); .SH DESCRIPTION .BR cxl_mmio_read64 () reads the 64-bit word at .I offset from the address of the mapped Problem State Area of .IR afu , and copies its value to the word pointed to by .IR data . The copy will include byte swapping if the AFU endianness declared by .BR cxl_mmio_map () differs from the host endianness. .PP .I offset is a byte address, aligned on a double word (8-byte) boundary. It must be lower than the MMIO size returned by .BR cxl_get_mmio_size (). The address of the mapped MMIO space is returned by .BR cxl_mmio_ptr (). .PP If the MMIO access fails due to an IO error, a SIGBUS may be sent to the application, which would ordinarily result in the process being terminated. libcxl provides an optional SIGBUS handler, which can be installed with .BR cxl_mmio_install_sigbus_handler (). Installing this signal handler prior to using the MMIO accessor functions will cause them to return -1 and set .I errno to EIO in the event of an IO error. Additionally, if this handler has NOT been installed, the cxl_mmio_read* functions will raise a SIGBUS in the event that they detect an IO error due to a read of all F's for consistency. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or unmapped MMIO space. .TP .B EIO An unrecoverable error .RB ( cxl_mmio_install_sigbus_handler () must have been previously called) .SH SEE ALSO .BR cxl (3), .BR cxl_get_mmio_size (3), .BR cxl_mmio_install_sigbus_handler (3), .BR cxl_mmio_map (3), .BR cxl_mmio_ptr (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_unmap (3), .BR cxl_mmio_write32 (3), .BR cxl_mmio_write64 (3) libcxl-1.7/man3/cxl_mmio_unmap.3000066400000000000000000000013511327654150600166000ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_MMIO_UNMAP 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_mmio_unmap \- unmap an AFU Problem State Area .SH SYNOPSIS .B #include .PP .BI "int cxl_mmio_unmap(struct cxl_afu_h *" afu ); .SH DESCRIPTION .BR cxl_mmio_map () unmaps the AFU Problem State Area of .IR afu . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or unmapped AFU Problem State Area .SH SEE ALSO .BR cxl (3), .BR cxl_get_mmio_size (3), .BR cxl_mmio_map (3), .BR cxl_mmio_ptr (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_write32 (3), .BR cxl_mmio_write64 (3), .BR munmap (3) libcxl-1.7/man3/cxl_mmio_write32.3000066400000000000000000000033441327654150600167630ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_MMIO_WRITE32 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_mmio_write32 \- write a 32-bit word to the mapped AFU Problem State Area .SH SYNOPSIS .B #include .PP .B "int cxl_mmio_write32(struct cxl_afu_h " .BI * afu ", uint64_t " offset , .BI "uint32_t " data ); .SH DESCRIPTION .BR cxl_mmio_write32 () writes the 32-bit word .I data at .I offset from the address of the mapped Problem State Area of .IR afu . Bytes will be swapped if the AFU endianness declared by .BR cxl_mmio_map () differs from the host endianness. .PP .I offset is a byte address that is aligned on a word (4 byte) boundary. It must be lower than the MMIO size returned by .BR cxl_get_mmio_size (). The address of the mapped MMIO space is returned by .BR cxl_mmio_ptr (). .PP If the MMIO access fails due to an IO error, a SIGBUS may be sent to the application, which would ordinarily result in the process being terminated. libcxl provides an optional SIGBUS handler, which can be installed with .BR cxl_mmio_install_sigbus_handler (). Installing this signal handler prior to using the MMIO accessor functions will cause them to return -1 and set .I errno to EIO in the event of an IO error. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or unmapped MMIO space. .TP .B EIO An unrecoverable error .RB ( cxl_mmio_install_sigbus_handler () must have been previously called) .SH SEE ALSO .BR cxl (3), .BR cxl_get_mmio_size (3), .BR cxl_mmio_install_sigbus_handler (3), .BR cxl_mmio_map (3), .BR cxl_mmio_ptr (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_unmap (3), .BR cxl_mmio_write64 (3) libcxl-1.7/man3/cxl_mmio_write64.3000066400000000000000000000033441327654150600167700ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_MMIO_WRITE64 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_mmio_write64 \- write a 64-bit word to the mapped AFU Problem State Area .SH SYNOPSIS .B #include .PP .B "int cxl_mmio_write64(struct cxl_afu_h " .BI * afu ", uint64_t " offset , .BI "uint64_t " data ); .SH DESCRIPTION .BR cxl_mmio_write64 () writes the 64-bit word .I data at .I offset from the address of the mapped Problem State Area of .IR afu . Bytes will be swapped if the AFU endianness declared by .BR cxl_mmio_map () differs from the host endianness. .PP .I offset is a byte address, aligned on a double word (8-byte) boundary. It must be lower than the MMIO size returned by .BR cxl_get_mmio_size (). The address of the mapped MMIO space is returned by .BR cxl_mmio_ptr (). .PP If the MMIO access fails due to an IO error, a SIGBUS may be sent to the application, which would ordinarily result in the process being terminated. libcxl provides an optional SIGBUS handler, which can be installed with .BR cxl_mmio_install_sigbus_handler (). Installing this signal handler prior to using the MMIO accessor functions will cause them to return -1 and set .I errno to EIO in the event of an IO error. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or unmapped MMIO space. .TP .B EIO An unrecoverable error .RB ( cxl_mmio_install_sigbus_handler () must have been previously called) .SH SEE ALSO .BR cxl (3), .BR cxl_get_mmio_size (3), .BR cxl_mmio_install_sigbus_handler (3), .BR cxl_mmio_map (3), .BR cxl_mmio_ptr (3), .BR cxl_mmio_read32 (3), .BR cxl_mmio_read64 (3), .BR cxl_mmio_unmap (3), .BR cxl_mmio_write32 (3) libcxl-1.7/man3/cxl_read_event.3000066400000000000000000000025241327654150600165560ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_READ_EVENT 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_read_event \- read one CXL event from an AFU .SH SYNOPSIS .B #include .PP .BI "int cxl_read_event(struct cxl_afu_h *" afu , .BI "struct cxl_event *" event ); .SH DESCRIPTION .BR cxl_read_event () reads one CXL event from .IR afu , and copies it to the structure pointed to by .IR event . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EAGAIN AFU device opened with .BR O_NONBLOCK , and no data immediately available. .TP .B EINTR Interrupted .BR read () system call. .TP .B EINVAL Invalid argument value, or AFU not opened. .TP .B EIO Unrecoverable error. .TP .B ENODATA No data returned by .BR read (). .TP .B ENOMEM Insufficient memory. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3), .BR cxl_fprint_event (3), .BR cxl_fprint_unknown_event (3), .BR cxl_event_pending (3), .BR cxl_read_expected_event (3), .BR open (2), .BR read (2) libcxl-1.7/man3/cxl_read_expected_event.3000066400000000000000000000033751327654150600204440ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_READ_EXPECTED_EVENT 3 2017-05-24 "LIBCXL 1.5" "CXL Manual" .SH NAME cxl_read_expected_event \- read one CXL event from an AFU, and treat it as a failure, if it did not match an expected event .SH SYNOPSIS .B #include .PP .BI "int cxl_read_expected_event(struct cxl_afu_h *" afu , .BI "struct cxl_event *" event ", __u32 " type , .BI "__u16 " irq ); .SH DESCRIPTION .BR cxl_read_expected_event () reads one CXL event from .IR afu , when an event of .I type is expected, and copies it to the structure pointed to by .IR event . For AFU interrupts, the expected AFU interrupt number .I irq may also be supplied (0 will accept any AFU interrupt). .SH RETURN VALUE On success, 0 is returned if the read event was of the expected type and (if applicable) AFU interrupt number. If the event did not match the type and interrupt, -1 is returned. .PP On error, \-2 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EAGAIN AFU device opened with .BR O_NONBLOCK , and no data immediately available. .TP .B EINTR Interrupted .BR read () system call. .TP .B EINVAL Invalid argument value, or AFU not opened. .TP .B EIO Unrecoverable error. .TP .B ENODATA No data returned by .BR read (). .TP .B ENOMEM Insufficient memory. .SH FILES .TP .BI /dev/cxl/afu . d AFU device in dedicated process mode. .TP .BI /dev/cxl/afu . m AFU device in AFU directed mode, master context. .TP .BI /dev/cxl/afu . s AFU device in AFU directed mode, slave context. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3), .BR cxl_fprint_event (3), .BR cxl_fprint_unknown_event (3), .BR cxl_event_pending (3), .BR cxl_read_event (3), .BR open (2), .BR read (2) libcxl-1.7/man3/cxl_set_irqs_max.3000066400000000000000000000015511327654150600171370ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_SET_IRQS_MAX 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_set_irqs_max \- administratively restrict the maximum number of AFU interrupts .SH SYNOPSIS .B #include .PP .B "int cxl_set_irqs_max(struct cxl_afu_h" .BI * afu ", long " value ); .SH DESCRIPTION .BR cxl_set_irqs_max () sets the maximum number of interrupts that can be requested for .IR afu , when calling .BR cxl_afu_attach_full () or .BR cxl_afu_attach_work (). .I value must be greater or equal to the value returned by .BR cxl_get_irqs_min (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_get_irqs_max (3), .BR cxl_get_irqs_min (3) libcxl-1.7/man3/cxl_set_mode.3000066400000000000000000000020121327654150600162310ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_SET_MODE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_set_mode \- set the programming mode of an AFU .SH SYNOPSIS .B #include .PP .B "int cxl_set_mode(struct cxl_afu_h" .BI * afu ", long " value ); .SH DESCRIPTION .BR cxl_set_mode () sets the programming mode of .I afu to .IR value . .I value must be one of the modes returned by .BR cxl_get_modes_supported (): .B CXL_MODE_DEDICATED or .BR CXL_MODE_DIRECTED . Mode will be changed provided that no user contexts are attached. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EBUSY User context attached. .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_fd_to_h (3), .BR cxl_afu_next (3), .BR cxl_afu_open_dev (3), .BR cxl_afu_open_h (3), .BR cxl_get_mode (3), .BR cxl_get_modes_supported (3) libcxl-1.7/man3/cxl_set_prefault_mode.3000066400000000000000000000024011327654150600201350ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_SET_PREFAULT_MODE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_set_prefault_mode \- set the mode for prefaulting segments .SH SYNOPSIS .B #include .PP .B "int cxl_set_prefault_mode(struct cxl_afu_h" .BI * afu ", enum cxl_prefault_mode " value ); .SH DESCRIPTION .BR cxl_set_prefault_mode () sets the prefault mode of .I afu to .IR value . The current mode will be used for prefaulting in segments into the segment table when performing .BR cxl_afu_attach (), .BR cxl_afu_attach_full () or .BR cxl_afu_attach_work (). Mode must be one of the .B "enum cxl_prefault_mode" values: .TP .B CXL_PREFAULT_MODE_NONE No prefaulting (default). .TP .B CXL_PREFAULT_MODE_WED Treat the work element descriptor as an effective address and prefault what it points to. .TP .B CXL_PREFAULT_MODE_ALL Prefault all the segments mapped by the process calling .BR cxl_afu_attach (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_adapter_afu_next (3), .BR cxl_afu_attach (3), .BR cxl_afu_attach_full (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_next (3), .BR cxl_get_prefault_mode (3) libcxl-1.7/man3/cxl_work_alloc.3000066400000000000000000000016711327654150600166000ustar00rootroot00000000000000.\" Copyright 2015-2018 IBM Corp. .\" .TH CXL_WORK_ALLOC 3 2018-02-13 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_work_alloc \- allocate and initialize a work structure .SH SYNOPSIS .B #include .PP .B "struct cxl_ioctl_start_work *cxl_work_alloc();" .SH DESCRIPTION .BR cxl_work_alloc () allocates, initializes, and returns a pointer to a work structure, that can be populated and passed to .BR cxl_afu_attach_work (). .SH RETURN VALUE On success, a pointer to the allocated structure is returned. On error, NULL is returned and .I errno is set appropriately. .SH ERRORS .TP .B ENOMEM Not enough memory. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_work_disable_wait (3), .BR cxl_work_enable_wait (3), .BR cxl_work_free (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_get_tid (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_num_irqs (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_work_disable_wait.3000066400000000000000000000021651327654150600201340ustar00rootroot00000000000000.\" Copyright 2018 IBM Corp. .\" .TH CXL_WORK_DISABLE_WAIT 3 2018-04-24 "LIBCXL 1.6" "CXL Programmer's Manual" .SH NAME cxl_work_disable_wait \- indicate that a host thread will not wait .SH SYNOPSIS .B #include .PP .B "int cxl_work_disable_wait(struct cxl_ioctl_start_work" .BI * work ); .SH DESCRIPTION The tunneled operation as_notify is supported on POWER9. See .BR cxl_get_tunneled_ops_supported (). .PP .BR cxl_work_disable_wait () indicates in the .I work structure allocated by .BR cxl_work_alloc (), that the thread that will attach an AFU context with .BR cxl_afu_attach_work () will not call .BR cxl_afu_host_thread_wait (). .PP This is the default behaviour. Calling this function is only required to cancel a previous call to .BR cxl_work_enable_wait (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_host_thread_wait (3), .BR cxl_get_tunneled_ops_supported (3), .BR cxl_work_alloc (3), .BR cxl_work_enable_wait (3), .BR cxl_work_get_tid (3) libcxl-1.7/man3/cxl_work_enable_wait.3000066400000000000000000000020301327654150600177460ustar00rootroot00000000000000.\" Copyright 2018 IBM Corp. .\" .TH CXL_WORK_ENABLE_WAIT 3 2018-04-24 "LIBCXL 1.6" "CXL Programmer's Manual" .SH NAME cxl_work_enable_wait \- indicate that a host thread will wait .SH SYNOPSIS .B #include .PP .B "int cxl_work_enable_wait(struct cxl_ioctl_start_work" .BI * work ); .SH DESCRIPTION The tunneled operation as_notify is supported on POWER9. See .BR cxl_get_tunneled_ops_supported (). .PP .BR cxl_work_enable_wait () indicates in the .I work structure allocated by .BR cxl_work_alloc (), that the thread that will attach an AFU context with .BR cxl_afu_attach_work () requires to be able to wait and be notified by the AFU with .BR cxl_afu_host_thread_wait (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_host_thread_wait (3), .BR cxl_get_tunneled_ops_supported (3), .BR cxl_work_alloc (3), .BR cxl_work_disable_wait (3), .BR cxl_work_get_tid (3) libcxl-1.7/man3/cxl_work_free.3000066400000000000000000000013741327654150600164270ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_WORK_FREE 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_work_get_free \- free a work structure .SH SYNOPSIS .B #include .PP .B "int cxl_work_free(struct cxl_ioctl_start_work" .BI * work ); .SH DESCRIPTION .BR cxl_work_free () frees the .I work structure allocated by .BR cxl_work_alloc (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_work_alloc (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_num_irqs (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_work_get_amr.3000066400000000000000000000015371327654150600171250ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_WORK_GET_AMR 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_work_get_amr \- get the value of the authority mask register .SH SYNOPSIS .B #include .PP .B "int cxl_work_get_amr(struct cxl_ioctl_start_work" .BI * work ", __u64 *" valp ); .SH DESCRIPTION .BR cxl_work_get_amr () copies the value of the authority mask register from the struct .I work to the unsigned word pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_work_alloc (3), .BR cxl_work_free (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_num_irqs (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_work_get_num_irqs.3000066400000000000000000000015271327654150600202020ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_WORK_GET_NUM_IRQS 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_work_get_num_irqs \- get the number of interrupts requested .SH SYNOPSIS .B #include .PP .B "int cxl_work_get_num_irqs(struct cxl_ioctl_start_work" .BI * work ", __s16 *" valp ); .SH DESCRIPTION .BR cxl_work_get_num_irqs () copies the requested number of interrupts from .I work to the short integer pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_work_alloc (3), .BR cxl_work_free (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_num_irqs (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_work_get_tid.3000066400000000000000000000024201327654150600171160ustar00rootroot00000000000000.\" Copyright 2018 IBM Corp. .\" .TH CXL_WORK_GET_TID 3 2018-04-24 "LIBCXL 1.6" "CXL Programmer's Manual" .SH NAME cxl_work_get_tid \- get the tid of the thread that will wait .SH SYNOPSIS .B #include .PP .B "int cxl_work_get_tid(struct cxl_ioctl_start_work" .BI * work ", __u16 *" valp ); .SH DESCRIPTION The tunneled operation as_notify is supported on POWER9. See .BR cxl_get_tunneled_ops_supported (). .PP .BR cxl_work_get_tid () copies to the address pointed to by .I valp the 16-bit tid value assigned by .BR cxl_afu_attach_work () to the thread that will wait to be notified by the AFU with .BR cxl_afu_host_thread_wait (). The .I work structure must have been wait-enabled with .BR cxl_work_enable_wait (). .PP Note: the 16-bit tid returned by .BR cxl_work_get_tid () is a capi-specific value, unrelated to the thread ID returned by the Linux system call .BR gettid (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value, or AFU context not attached, or wait not enabled .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_afu_host_thread_wait (3), .BR cxl_get_tunneled_ops_supported (3), .BR cxl_work_disable_wait (3), .BR cxl_work_enable_wait (3), .BR gettid(2) libcxl-1.7/man3/cxl_work_get_wed.3000066400000000000000000000015371327654150600171250ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_WORK_GET_WED 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_work_get_wed \- get the value of the work element descriptor .SH SYNOPSIS .B #include .PP .B "int cxl_work_get_wed(struct cxl_ioctl_start_work" .BI * work ", __u64 *" valp ); .SH DESCRIPTION .BR cxl_work_get_wed () copies the value of the work element descriptor from the struct .I work to the unsigned word pointed to by .IR valp . .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_work_alloc (3), .BR cxl_work_free (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_num_irqs (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_work_set_amr.3000066400000000000000000000016401327654150600171340ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_WORK_SET_AMR 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_work_set_amr \- set the value of the authority mask register .SH SYNOPSIS .B #include .PP .B "int cxl_work_set_amr(struct cxl_ioctl_start_work" .BI * work ", __u64 " amr ); .SH DESCRIPTION .BR cxl_work_set_amr () sets the value of the authority mask register .I amr into the struct .IR work . A null value indicates that the authority mask register should not be set by .BR cxl_afu_attach_work (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_work_alloc (3), .BR cxl_work_free (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_num_irqs (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_work_set_num_irqs.3000066400000000000000000000020111327654150600202030ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_WORK_SET_NUM_IRQS 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_work_set_num_irqs \- set the number of interrupts requested .SH SYNOPSIS .B #include .PP .B "int cxl_work_set_num_irqs(struct cxl_ioctl_start_work" .BI * work ", __s16 " num_irqs ); .SH DESCRIPTION .BR cxl_work_set_num_irqs () sets the number of interrupts requested .I num_irqs into the struct .IR work . If the value is negative, then .BR cxl_afu_attach_work (), will allocate the minimum number of interrupts required by an AFU context, returned by .BR cxl_get_irqs_min (). .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_get_irqs_min (3), .BR cxl_work_alloc (3), .BR cxl_work_free (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_wed (3) libcxl-1.7/man3/cxl_work_set_wed.3000066400000000000000000000017611327654150600171400ustar00rootroot00000000000000.\" Copyright 2015-2017 IBM Corp. .\" .TH CXL_WORK_SET_WED 3 2017-05-24 "LIBCXL 1.5" "CXL Programmer's Manual" .SH NAME cxl_work_set_wed \- set the value of the work element descriptor .SH SYNOPSIS .B #include .PP .B "int cxl_work_set_wed(struct cxl_ioctl_start_work" .BI * work ", __u64 " wed ); .SH DESCRIPTION .BR cxl_work_set_wed () sets the value of the work element descriptor .I wed into the struct .IR work . The work element descriptor .I wed is a 64-bit argument defined by the AFU. Typically this is an effective address pointing to an AFU specific structure describing what work to perform. .SH RETURN VALUE On success, 0 is returned. On error, \-1 is returned and .I errno is set appropriately. .SH ERRORS .TP .B EINVAL Invalid argument value. .SH SEE ALSO .BR cxl (3), .BR cxl_afu_attach_work (3), .BR cxl_work_alloc (3), .BR cxl_work_free (3), .BR cxl_work_get_amr (3), .BR cxl_work_get_num_irqs (3), .BR cxl_work_get_wed (3), .BR cxl_work_set_amr (3), .BR cxl_work_set_num_irqs (3) libcxl-1.7/man3/foldtbl000077500000000000000000000010721327654150600150610ustar00rootroot00000000000000#!/bin/sh # foldtbl - fold long table lines awk 'BEGIN { sep = " " for (i = 0; i < 72; i++) sep = sep "-" } length() > 79 && $1 ~ /^-/ { print sep next } length() > 79 { line1 = $0 line2 = "" tab = index($0, " " $2 " ") len = length() # move words exceeding column 78 to line2 while (len > 79) { len = len - length($NF) -1 line2 = " " $NF line2 NF = NF - 1 } # prepend initial white spaces to line2 for (i = 1; i < tab; i++) line2 = " " line2 # print truncated line1 and line2 print substr(line1, 1, len) print line2 next } { print }' libcxl-1.7/man3/man2txt000077500000000000000000000002461327654150600150320ustar00rootroot00000000000000#!/bin/sh # man2txt - format a man page into plain text tbl | groff -man -I.. -Tascii | sed -e 's/\(.\)\o010\1/\1/g' -e 's/_\o010//g' -e 's/\o033\[[0-9][0-9]*m//g' libcxl-1.7/symver.map000066400000000000000000000032071327654150600146750ustar00rootroot00000000000000LIBCXL_1 { global: cxl_adapter_next; cxl_adapter_dev_name; cxl_adapter_free; cxl_adapter_afu_next; cxl_afu_next; cxl_afu_dev_name; cxl_afu_open_dev; cxl_afu_open_h; cxl_afu_fd_to_h; cxl_afu_free; cxl_afu_opened; cxl_afu_attach_full; cxl_afu_attach; cxl_afu_get_process_element; cxl_afu_fd; cxl_afu_sysfs_pci; cxl_get_api_version; cxl_get_api_version_compatible; cxl_get_irqs_max; cxl_set_irqs_max; cxl_get_irqs_min; cxl_get_mmio_size; cxl_get_mode; cxl_set_mode; cxl_get_modes_supported; cxl_get_prefault_mode; cxl_set_prefault_mode; cxl_get_pp_mmio_len; cxl_get_pp_mmio_off; cxl_get_base_image; cxl_get_caia_version; cxl_get_image_loaded; cxl_get_psl_revision; cxl_read_event; cxl_read_expected_event; cxl_fprint_event; cxl_fprint_unknown_event; cxl_mmio_map; cxl_mmio_unmap; cxl_mmio_ptr; cxl_mmio_write64; cxl_mmio_read64; cxl_mmio_write32; cxl_mmio_read32; cxl_mmio_install_sigbus_handler; cxl_errinfo_size; cxl_errinfo_read; local: *; }; LIBCXL_1.1 { global: cxl_get_cr_class; cxl_get_cr_device; cxl_get_cr_vendor; } LIBCXL_1; LIBCXL_1.2 { global: cxl_afu_attach_work; cxl_work_alloc; cxl_work_free; cxl_work_get_amr; cxl_work_get_num_irqs; cxl_work_get_wed; cxl_work_set_amr; cxl_work_set_num_irqs; cxl_work_set_wed; cxl_event_pending; } LIBCXL_1.1; LIBCXL_1.4 { global: cxl_get_psl_timebase_synced; } LIBCXL_1.2; LIBCXL_1.6 { global: cxl_afu_host_thread_wait; cxl_work_disable_wait; cxl_work_enable_wait; cxl_work_get_tid; } LIBCXL_1.4; LIBCXL_1.7 { global: cxl_get_tunneled_ops_supported; } LIBCXL_1.6;