This commit is contained in:
Grant Mackey 2024-04-08 05:43:12 +00:00
parent e264bdf897
commit fdd2ba3095
6 changed files with 316 additions and 10 deletions

View File

@ -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.

View File

@ -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

View File

@ -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
```

236
main.c
View File

@ -13,6 +13,12 @@
/* INCLUDES ==================================================================*/
/* gettid()
*/
#define _GNU_SOURCE
#include <unistd.h>
/* printf()
*/
#include <stdio.h>
@ -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
*

17
main.h
View File

@ -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);

View File

@ -15,7 +15,7 @@
#include <linux/types.h>
#include "cxlstate.h"
#include "main.h"
/* MACROS ====================================================================*/