From fdd2ba30952c89a935f94a3a68bfca2ad8efaae5 Mon Sep 17 00:00:00 2001 From: fedora Cloud User Date: Mon, 8 Apr 2024 05:43:12 +0000 Subject: [PATCH] RC1 --- LICENSE | 2 +- Makefile | 16 ++-- README.md | 53 +++++++++++- main.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++++ main.h | 17 +++- testbench.c | 2 +- 6 files changed, 316 insertions(+), 10 deletions(-) diff --git a/LICENSE b/LICENSE index c9634a4..ae3132f 100644 --- a/LICENSE +++ b/LICENSE @@ -58,7 +58,7 @@ 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 2024 Jackrabbit-Labs-LLC +Copyright 2024 Jackrabbit-Founders-LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Makefile b/Makefile index 1673fad..1159ce5 100644 --- a/Makefile +++ b/Makefile @@ -13,16 +13,16 @@ # ****************************************************************************** CC=gcc -CFLAGS= -g3 -O0 -Wall -Wextra -MACROS= -INCLUDE_DIR=/usr/local/include -LIB_DIR=/usr/local/lib +CFLAGS?= -g3 -O0 -Wall -Wextra +MACROS?=-D CXLS_VERBOSE +INCLUDE_DIR?=/usr/local/include +LIB_DIR?=/usr/local/lib INCLUDE_PATH=-I $(INCLUDE_DIR) LIB_PATH=-L $(LIB_DIR) LIBS=-l fmapi -l arrayutils -l pciutils TARGET=cxlstate -all: testbench lib$(TARGET).a +all: lib$(TARGET).a testbench: testbench.c main.o $(CC) $^ $(CFLAGS) $(MACROS) $(INCLUDE_PATH) $(LIB_PATH) $(LIBS) -o $@ @@ -43,7 +43,11 @@ install: lib$(TARGET).a sudo cp lib$(TARGET).a $(LIB_DIR)/ sudo cp main.h $(INCLUDE_DIR)/$(TARGET).h -.PHONY: all clean doc install +uninstall: + sudo rm $(LIB_DIR)/lib$(TARGET).a + sudo rm $(INCLUDE_DIR)/$(TARGET).h + +.PHONY: all clean doc install uninstall # Variables # $^ Will expand to be all the sensitivity list diff --git a/README.md b/README.md index a7428c0..21535ef 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,53 @@ -# CXL_state-release +# Overview + +This is a C library that provides a software representation of the state of a +CXL switch and attached devices. + +# Supported Operating System Versions + +- Ubuntu 23.10 +- Fedora 38, 39 + +# Building + +1. Install OS libraries + +Install the following build packages to compile the software on the following +operating systems. + +**Ubuntu:** + +```bash +apt install build-essential libpci-dev +``` + +**Fedora:** + +```bash +``` + +2. Build Dependencies + +This library is dependent upon the following projects. + +- [array_utils](https://github.com/JackrabbitLabs/array_utils) +- [pci_utils](https://github.com/JackrabbitLabs/pci_utils) +- [fmapi](https://github.com/JackrabbitLabs/fmapi) + +For each of these repositories, in the order listed, clone and execute: + +```bash +make install +``` + +This will install a library (.a) and header file to the standard os location +(e.g. /usr/local/include, /usr/local/lib) + +3. Build + +After building the required dependencies run: + +```bash +make +``` diff --git a/main.c b/main.c index 99bfdc5..7c7c1ba 100644 --- a/main.c +++ b/main.c @@ -13,6 +13,12 @@ /* INCLUDES ==================================================================*/ +/* gettid() + */ +#define _GNU_SOURCE + +#include + /* printf() */ #include @@ -58,6 +64,24 @@ /* MACROS ====================================================================*/ +#ifdef CXLS_VERBOSE + #define INIT unsigned step = 0; + #define ENTER if (cxls_verbosity & CXVB_CALLSTACK) printf("%d:%s Enter\n", gettid(), __FUNCTION__); + #define STEP step++; if (cxls_verbosity & CXVB_STEPS) printf("%d:%s STEP: %u\n", gettid(), __FUNCTION__, step); + #define HEX32(m, i) if (cxls_verbosity & CXVB_STEPS) printf("%d:%s STEP: %u %s: 0x%x\n", gettid(), __FUNCTION__, step, m, i); + #define INT32(m, i) if (cxls_verbosity & CXVB_STEPS) printf("%d:%s STEP: %u %s: %d\n", gettid(), __FUNCTION__, step, m, i); + #define EXIT(rc) if (cxls_verbosity & CXVB_CALLSTACK) printf("%d:%s Exit: %d\n", gettid(), __FUNCTION__,rc); +#else + #define INIT + #define ENTER + #define STEP + #define HEX32(m, i) + #define INT32(m, i) + #define EXIT(rc) +#endif // CSE_VERBOSE + +#define IFV(u) if (cxls_verbosity & u) + /* ENUMERATIONS ==============================================================*/ /* STRUCTS ===================================================================*/ @@ -66,8 +90,220 @@ /* GLOBAL VARIABLES ==========================================================*/ +__u64 cxls_verbosity = 0; + /* FUNCTIONS =================================================================*/ +/** + * Copy data from a device definition to a port + * + * @param p struct cxl_port* to fill with data + * @param d struct cxl_device* to pull the data from + * @param dir char* for the directory name for mmaped files + * + * STEPS: + * 1: Copy basic parameters + * 2: Copy PCIe config space to the port + * 3: Copy MLD information if present + * 4: Memory Map a file if requested by the device profile + */ +int cxls_connect(struct cxl_port *p, struct cxl_device *d, char *dir) +{ + INIT + int rv; + unsigned i; + char filename[CXLN_FILE_NAME]; + FILE *fp; + + ENTER + + // Initialize variables + rv = 1; + + // Validate Inputs + if (d->name == NULL) + goto end; + + STEP // 1: Copy basic parameters + p->dv = d->dv; + p->dt = d->dt; + p->cv = d->cv; + p->ltssm = FMLS_L0; + p->lane = 0; + p->lane_rev = 0; + p->perst = 0; + p->pwrctrl = 0; + p->ld = 0; + + // If the device definition says this is a rootport then set as an Upstream Port + if( d->rootport == 1 ) + p->state = FMPS_USP; + else + p->state = FMPS_DSP; + + // Pick the lower of the two widths + if (d->mlw < p->mlw) + p->nlw = d->mlw << 4; + else + p->nlw = p->mlw << 4; + + // Pick the lower of the two speeds + if (d->mls < p->mls) + p->cls = d->mls; + else + p->cls = p->mls; + + // Set present bit + p->prsnt = 1; + + STEP // 2: Copy PCIe config space to the port + memcpy(p->cfgspace, d->cfgspace, CXLN_CFG_SPACE); + + STEP // 3: Copy MLD information if present + if (d->mld != NULL) + { + p->ld = d->mld->num; + + // Allocate memory for MLD object in the port + p->mld = malloc(sizeof(struct cxl_mld)); + + // Copy MLD from device definition to port + memcpy(p->mld, d->mld, sizeof(struct cxl_mld)); + + for ( i = 0 ; i < d->mld->num ; i++ ) + { + // Allocate memory for each LD pcie config space + p->mld->cfgspace[i] = malloc(CXLN_CFG_SPACE); + + // Copy PCIe config space from device definition to port + memcpy(p->mld->cfgspace[i], d->cfgspace, CXLN_CFG_SPACE); + } + } + + STEP // 4: Memory Map a file if requested by the device profile + if (d->mld != NULL && d->mld->mmap == 1) + { + // Prepare filename + sprintf(filename, "%s/port%02d", dir, p->ppid); + + // Create file + fp = fopen(filename, "w+"); + if (fp == NULL) { + printf("Error: Could not open file: %s\n", filename); + goto end; + } + + // Truncate file to desired length + rv = ftruncate(fileno(fp), p->mld->memory_size); + if (rv != 0) { + printf("Error: Could not truncate file. Memory Size: 0x%llx errno: %d\n", p->mld->memory_size, errno); + goto end; + } + + // mmap file + p->mld->memspace = mmap(NULL, p->mld->memory_size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(fp), 0); + if (p->mld->memspace == NULL) { + printf("Error: Could not mmap the file. errno: %d\n", errno); + rv = 1; + goto end; + } + + // Save the filename to the port mld object + p->mld->file = strdup(filename); + + // Close file + fclose(fp); + + } + + rv = 0; + +end: + + return rv; +} + +/** + * Clear / Free data from a port device definition + * + * This function essemtially makes it appear as if the device has been removed from the slot + * + * @param p struct cxl_port* The port to clear of values + * + * STEPS: + * 1: Clear basic parameters + * 2: Clear PCIe config space + * 3: Free device name + * 4: Unmemmap MLD if present + * 5: Free PCIe cfg space for each ld + * 6: Free MLD if present + */ +int cxls_disconnect(struct cxl_port *p) +{ + INIT + int rv; + unsigned i; + + ENTER + + // Initialize variables + rv = 1; + + STEP // 1: Clear basic parameters + p->dv = 0; + p->dt = 0; + p->cv = 0; + p->nlw = 0; + p->cls = 0; + p->ltssm = 0; + p->lane = 0; + p->lane_rev = 0; + p->perst = 0; + p->prsnt = 0; + p->pwrctrl = 0; + p->ld = 0; + + STEP // 2: Clear PCIe config space + memset(p->cfgspace, 0, CXLN_CFG_SPACE); + + STEP // 3: Free device name + if (p->device_name != NULL) + { + free(p->device_name); + p->device_name = NULL; + } + + STEP // 4: Unmemmap MLD if present + if (p->mld != NULL && p->mld->memspace != NULL) + { + msync (p->mld->memspace, p->mld->memory_size, MS_SYNC); + munmap(p->mld->memspace, p->mld->memory_size); + p->mld->memspace = NULL; + } + + STEP // 5: Free PCIe cfg space for each ld + if (p->mld != NULL) + { + for ( i = 0 ; i < p->mld->num ; i++ ) { + if ( p->mld->cfgspace[i] != NULL ) { + free(p->mld->cfgspace[i]); + p->mld->cfgspace[i] = NULL; + } + } + } + + STEP // 6: Free MLD if present + if (p->mld != NULL) + { + free(p->mld); + p->mld = NULL; + } + + rv = 0; + + return rv; +} + /** * Initialize state object with default values * diff --git a/main.h b/main.h index f6fe03b..322af3f 100644 --- a/main.h +++ b/main.h @@ -37,6 +37,16 @@ /* ENUMERATIONS ==============================================================*/ +/** + * CXLS Verbosity Bit Field (VB) + */ +enum _CXVB +{ + CXVB_GENERAL = (0x01 << 0), + CXVB_CALLSTACK = (0x01 << 1), + CXVB_STEPS = (0x01 << 2) +}; + /* STRUCTS ===================================================================*/ /** @@ -211,11 +221,16 @@ struct cxl_switch /* GLOBAL VARIABLES ==========================================================*/ +extern __u64 cxls_verbosity; + /* PROTOTYPES ================================================================*/ struct cxl_switch *cxls_init(unsigned ports, unsigned vcss, unsigned vppbs); - void cxls_free (struct cxl_switch *s); + +int cxls_connect (struct cxl_port *p, struct cxl_device *d, char *dir); +int cxls_disconnect (struct cxl_port *p); + void cxls_prnt (struct cxl_switch *s); void cxls_prnt_identity (struct cxl_switch *s, unsigned indent); void cxls_prnt_devices (struct cxl_switch *s); diff --git a/testbench.c b/testbench.c index ec081c1..d723692 100644 --- a/testbench.c +++ b/testbench.c @@ -15,7 +15,7 @@ #include -#include "cxlstate.h" +#include "main.h" /* MACROS ====================================================================*/