Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOPMP Reference Model #41

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
*.pdf
# Object files
*.o

# Libraries
*.a

# Executables
*.exe
*.out

# Coverage Files
*.gcno
*.gcda

# Binary Files
iopmp_ref_model/bin/
iopmp_ref_model/lib/
111 changes: 111 additions & 0 deletions iopmp_ref_model/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Directories
BIN_DIR := bin
SRC_DIR := src
VERIF := verif
TEST_DIR := $(VERIF)/tests
LIB_DIR := lib
cov =
COVFLAGS =
ifeq ($(cov), 1)
COVFLAGS += -fprofile-arcs -ftest-coverage -lgcov --coverage
endif

# Compiler and flags
CC := gcc
CFLAGS := -Wall -Werror $(COVFLAGS) -I./include -Iverif/
LDFLAGS := -lm

# Common source files
COMMON_SOURCES := $(SRC_DIR)/iopmp_reg.c \
$(SRC_DIR)/iopmp_interrupt.c \
$(SRC_DIR)/iopmp_rule_analyzer.c \
$(SRC_DIR)/iopmp_validate.c \
$(SRC_DIR)/iopmp_error_capture.c \
$(VERIF)/test_utils.c

# Models and configurations
MODELS := full_model:fullmodel.c:0:0 \
rapid_k_model:rapidmodel.c:0:1 \
dynamic_k_model:dynamicmodel.c:0:2 \
isolation_model:isolationmodel.c:1:0 \
compact_k_model:compactmodel.c:1:1 \
unnamed_model_1:unnamed_model_1.c:1:2 \
unnamed_model_2:unnamed_model_2.c:2:0 \
unnamed_model_3:unnamed_model_3.c:2:1 \
unnamed_model_4:unnamed_model_4.c:2:2

# Targets
.PHONY: all build run clean

all: build run

# Ensure the directories exist
$(BIN_DIR):
mkdir -p $(BIN_DIR)

$(LIB_DIR):
mkdir -p $(LIB_DIR)

# Build all models into libraries and executables
build: $(BIN_DIR) $(LIB_DIR)
@if [ -z "$(model)" ]; then \
echo "Building all models..."; \
for entry in $(MODELS); do \
model=$$(echo $$entry | cut -d':' -f1); \
source=$$(echo $$entry | cut -d':' -f2); \
srcmd_fmt=$$(echo $$entry | cut -d':' -f3); \
mdcfg_fmt=$$(echo $$entry | cut -d':' -f4); \
echo "Building library and executable for $$model..."; \
obj_files=""; \
for src in $(COMMON_SOURCES) $(TEST_DIR)/$$source; do \
obj_file=$$(basename $$src .c).o; \
$(CC) $(CFLAGS) -DSRCMD_FMT=$$srcmd_fmt -DMDCFG_FMT=$$mdcfg_fmt -c $$src -o $$obj_file; \
obj_files="$$obj_files $$obj_file"; \
done; \
ar rcD $(LIB_DIR)/$$model.a $$obj_files > /dev/null 2>&1; \
ranlib $(LIB_DIR)/$$model.a; \
$(CC) $(CFLAGS) -DSRCMD_FMT=$$srcmd_fmt -DMDCFG_FMT=$$mdcfg_fmt \
$(TEST_DIR)/$$source -L$(LIB_DIR) -l:$$model.a -o $(BIN_DIR)/$$model $(LDFLAGS); \
echo "Library and executable for $$model built successfully."; \
rm -f $$obj_files; \
done; \
else \
entry=$$(echo "$(MODELS)" | tr ' ' '\n' | grep -E "^$(model):"); \
if [ -z "$$entry" ]; then \
echo "Error: Model $(model) not found."; \
exit 1; \
fi; \
source=$$(echo $$entry | cut -d':' -f2); \
srcmd_fmt=$$(echo $$entry | cut -d':' -f3); \
mdcfg_fmt=$$(echo $$entry | cut -d':' -f4); \
echo "Building library and executable for $(model)..."; \
obj_files=""; \
for src in $(COMMON_SOURCES) $(TEST_DIR)/$$source; do \
obj_file=$$(basename $$src .c).o; \
$(CC) $(CFLAGS) -DSRCMD_FMT=$$srcmd_fmt -DMDCFG_FMT=$$mdcfg_fmt -c $$src -o $$obj_file; \
obj_files="$$obj_files $$obj_file"; \
done; \
ar rcD $(LIB_DIR)/$(model).a $$obj_files > /dev/null 2>&1; \
ranlib $(LIB_DIR)/$(model).a; \
$(CC) $(CFLAGS) -DSRCMD_FMT=$$srcmd_fmt -DMDCFG_FMT=$$mdcfg_fmt \
$(TEST_DIR)/$$source -L$(LIB_DIR) -l:$$model.a -o $(BIN_DIR)/$$model $(LDFLAGS); \
echo "Library and executable for $(model) built successfully."; \
rm -f $$obj_files; \
fi

# Run all compiled binaries
run:
@for model in $(MODELS); do \
target=$${model%%:*}; \
binary=$(BIN_DIR)/$$target; \
if [ -f $$binary ]; then \
echo "Running $$binary..."; \
$$binary; \
else \
echo "Binary $$binary not found. Did you build it?"; \
fi; \
done

# Clean the binary and library directories
clean:
rm -rf bin/ lib/ *.gcno *.gcda
120 changes: 120 additions & 0 deletions iopmp_ref_model/README.md

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions iopmp_ref_model/include/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/***************************************************************************
// Author: Yazan Hussnain ([email protected])
// Date: October 21, 2024
// Description: This file contains all the configuration parameters
// that a user could change before compilation.
***************************************************************************/

#define IOPMP_TOR_EN 1
#define IOPMP_SPS_EN 1
#define IOPMP_PARIENT_PROG 0
#define IOPMP_RRID_TRANSL_EN 1
#define IOPMP_RRID_TRANSL_PROG 0
#define IOPMP_CHK_X 1
#define IOPMP_NO_X 0
#define IOPMP_NO_W 0
#define IOPMP_STALL_EN 1
#define IOPMP_PEIS 1
#define IOPMP_PEES 1
#define IOPMP_MFR_EN 1
#define IOPMP_MD_ENTRY_NUM 3
#define IOPMP_MD_NUM 63 // Max 63 MD is supported
#define IOPMP_ADDRH_EN 1
#define IOPMP_ENABLE 0
#define IOPMP_ENTRY_NUM 512
#define IOPMP_PRIO_ENTRY 16
#define IOPMP_RRID_TRANSL 48
#define USER 0x80 // It could be any user defined value, incase of error suppression
#define ERROR_CAPTURE_EN 1
#define IMP_ERROR_REQID 1
#define IMP_MDLCK 1
#define MSI_EN 1
#define STALL_BUF_DEPTH 32
#define SRC_ENFORCEMENT_EN 0

#define ENTRY_OFFSET 0x2000

#define REG_INTF_BUS_WIDTH 4

#if (SRCMD_FMT == 0)
#define IOPMP_RRID_NUM 64
#elif (SRCMD_FMT == 1)
#define IOPMP_RRID_NUM 63 // Max RRID Num could be 63 when SRCMD_FMT is 1, because RRID is directly mapped to MD's
#else
#define IOPMP_RRID_NUM 32 // Max RRID Num could be 32 when SRCMD_FMT is 2, because SRCMD_PERM is 32 bits
#endif
76 changes: 76 additions & 0 deletions iopmp_ref_model/include/iopmp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/***************************************************************************
// Authors: Mazhar Ali ([email protected])
// Gull Ahmed ([email protected])
// Date: October 21, 2024
// Description: IOPMP Header File
// This header file defines structures, macros, and function prototypes
// for the Input/Output Physical Memory Protection (IOPMP). It includes
// the primary modes of operation for the IOPMP (off, TOR, NA4, NAPOT) and
// provides declarations for the primary functions used to process access
// requests, match addresses, check permissions, analyze rules, and handle
// error capture. Additionally, macros for testing and transaction checks
// are defined to support validation and debugging.
***************************************************************************/

#ifndef IOPMP_H
#define IOPMP_H

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include "iopmp_registers.h"
#include "iopmp_req_rsp.h"

// IOPMP Mode Types: Define operational modes for IOPMP
#define IOPMP_OFF 0 // IOPMP is disabled
#define IOPMP_TOR 1 // Top-of-Range mode
#define IOPMP_NA4 2 // Naturally aligned 4-byte regions
#define IOPMP_NAPOT 3 // Naturally aligned power of two regions

#define BUS_ERROR 0xC
#define MSI_DATA_BYTE 0x4
#define MAX_SVS 0xFFFF

#define WORD_BITS 32
#define SRCMD_REG_STRIDE 32
#define ENTRY_REG_STRIDE 16
#define MIN_REG_WIDTH 4

// Helper Macros for Register Calculations
#define SRCMD_TABLE_INDEX(offset) (((offset) - SRCMD_TABLE_BASE_OFFSET) / SRCMD_REG_STRIDE)
#define ENTRY_TABLE_INDEX(offset) (((offset) - ENTRY_TABLE_BASE_OFFSET) / ENTRY_REG_STRIDE)
#define SRCMD_REG_INDEX(offset) ((((offset) - SRCMD_TABLE_BASE_OFFSET) % SRCMD_REG_STRIDE) / MIN_REG_WIDTH)
#define ENTRY_REG_INDEX(offset) ((((offset) - ENTRY_TABLE_BASE_OFFSET) % ENTRY_REG_STRIDE) / MIN_REG_WIDTH)
#define IS_IN_RANGE(offset, start, end) (((offset) >= (start)) && ((offset) <= (end)))
#define CONCAT32(upr_bits, lwr_bits) (((uint64_t)upr_bits << WORD_BITS) | lwr_bits)
#define IS_MD_ASSOCIATED(md_num, srcmd_en_md, srcmd_enh_mdh) \
((md_num < 31) ? ((srcmd_en_md >> md_num) & 1) : ((srcmd_enh_mdh >> (md_num - 31)) & 1))

#define MASK_BIT_POS(BIT_POS) ((1U << BIT_POS) - 1)
#define GET_BIT(VAL, BIT_NUM) ((VAL >> BIT_NUM) & 1)


// Global Variables: Definitions for IOPMP global variables
extern iopmp_regs_t g_reg_file; // Global register file for IOPMP
extern iopmp_entries_t iopmp_entries; // IOPMP entry table
extern err_mfrs_t err_svs; // Error status vector
extern int intrpt_suppress; // Set when interrupt is suppressed
extern int error_suppress; // Set when error is suppressed
extern int rrid_stall[IOPMP_RRID_NUM]; // Stall status array for requester IDs
extern int stall_cntr; // Counts stalled transactions

extern uint8_t write_memory(char *data, uint64_t addr, uint32_t size);

// Function Declarations: Core IOPMP operations
int iopmpAddrRange(uint64_t *startAddr, uint64_t *endAddr, uint64_t prev_iopmpaddr, uint64_t iopmpaddr, entry_cfg_t iopmpcfg);
int iopmpMatchAddr(iopmp_trans_req_t trans_req, uint64_t lo, uint64_t hi, int is_priority);
iopmpMatchStatus_t iopmpCheckPerms(uint16_t rrid, perm_type_e req_perm, entry_cfg_t iopmpcfg, uint8_t md);
iopmpMatchStatus_t iopmpRuleAnalyzer(iopmp_trans_req_t trans_req, uint64_t prev_iopmpaddr, uint64_t iopmpaddr, entry_cfg_t iopmpcfg, uint8_t md, int is_priority);
iopmp_trans_rsp_t iopmp_validate_access(iopmp_trans_req_t trans_req, uint8_t *intrpt);
void errorCapture(perm_type_e trans_type, uint8_t error_type, uint16_t rrid, uint16_t entry_id, uint64_t err_addr, uint8_t *intrpt);
void generate_interrupt(uint8_t *intrpt);

#endif // IOPMP_H
Loading