diff --git a/acs-drv/files/Makefile b/acs-drv/files/Makefile index f379595dc5eb2aea811b135a8457d57f36212fe6..24540e438a0f7e7439c629403b6383c62eb4cc15 100644 --- a/acs-drv/files/Makefile +++ b/acs-drv/files/Makefile @@ -29,12 +29,18 @@ bsa_acs-objs += bsa_acs_drv.o \ val/bsa_acs_val.o \ test_pool/bsa_acs_test.o \ platform/pal_linux/files/bsa_acs_pal.o -else +else ifeq ($(ACS), sbsa) obj-m += sbsa_acs.o sbsa_acs-objs += sbsa_acs_drv.o \ val/sbsa_acs_val.o \ test_pool/sbsa_acs_test.o \ platform/pal_linux/files/sbsa_acs_pal.o +else ifeq ($(ACS), pcbsa) +obj-m += pcbsa_acs.o +pcbsa_acs-objs += pcbsa_acs_drv.o \ + val/pcbsa_acs_val.o \ + test_pool/pcbsa_acs_test.o \ + platform/pal_linux/files/pcbsa_acs_pal.o endif @@ -54,6 +60,10 @@ bsa: sbsa: make -C $(KERNEL_SRC) M=$(PWD) ACS=sbsa modules +pcbsa: + make -C $(KERNEL_SRC) M=$(PWD) ACS=pcbsa modules + + modules_install: $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules_install diff --git a/acs-drv/files/build.sh b/acs-drv/files/build.sh index e85cd163d9aea4e82dd26f3996acc10ff2442826..e175ae4d479379c29c6858ddd39204f362a3251c 100755 --- a/acs-drv/files/build.sh +++ b/acs-drv/files/build.sh @@ -291,6 +291,28 @@ do_build_sbsa_module() popd } +do_build_pcbsa_module() +{ + echo "Building PC BSA Module....." + mkdir -p $BUILD_PATH + + pushd $WRK_DIR/linux-acs/acs-drv/files + + if [ $(uname -m) != "aarch64" ]; then + export KERNEL_SRC=$WRK_DIR/linux-${LINUX_KERNEL_VERSION}/out + export CROSS_COMPILE=$WRK_DIR/$GCC + else + check_and_install_kernel_headers + export KERNEL_SRC="/lib/modules/$(uname -r)/build" + fi + + ./acs_setup.sh $SYSARCH_PATH + ./linux_acs.sh pcbsa + cp pcbsa_acs.ko $BUILD_PATH + popd +} + + do_build_sbsa_app() { pushd $SYSARCH_PATH/apps/linux/sbsa-acs-app @@ -299,6 +321,16 @@ do_build_sbsa_app() popd } +do_build_pcbsa_app() +{ + pushd $SYSARCH_PATH/apps/linux/pcbsa-acs-app + make + cp pc_bsa $BUILD_PATH/pcbsa_app + popd +} + + + do_build_bsa_app() { pushd $SYSARCH_PATH/apps/linux/bsa-acs-app @@ -323,6 +355,8 @@ check_build_outputs() { local bsa_app=$(check_file "bsa_app") local sbsa_module=$(check_file "sbsa_acs.ko") local sbsa_app=$(check_file "sbsa_app") + local pcbsa_module=$(check_file "pcbsa_acs.ko") + local pcbsa_app=$(check_file "pcbsa_app") # Print status table echo "----------------------------------------" @@ -330,6 +364,7 @@ check_build_outputs() { echo "----------------------------------------" printf "%-6s %-10s %-10s\n" "BSA" "$bsa_module" "$bsa_app" printf "%-6s %-10s %-10s\n" "SBSA" "$sbsa_module" "$sbsa_app" + printf "%-6s %-10s %-10s\n" "PCBSA" "$pcbsa_module" "$pcbsa_app" echo "----------------------------------------" } @@ -347,8 +382,11 @@ fi do_build_bsa_module do_build_sbsa_module +do_build_pcbsa_module + do_build_bsa_app do_build_sbsa_app +do_build_pcbsa_app check_build_outputs diff --git a/acs-drv/files/linux_acs.sh b/acs-drv/files/linux_acs.sh index e1c2d7999aaee1d85896c9fa343d3e09e6709715..dcd4aaa89afb52f871d1c9d3899d30159d491be0 100755 --- a/acs-drv/files/linux_acs.sh +++ b/acs-drv/files/linux_acs.sh @@ -35,7 +35,7 @@ then fi if [ "$#" -ne 1 ]; then - echo "Usage: $0 " + echo "Usage: $0 " exit 1 fi diff --git a/acs-drv/files/pcbsa_acs_drv.c b/acs-drv/files/pcbsa_acs_drv.c new file mode 100755 index 0000000000000000000000000000000000000000..3f690f511cffe939d5c0530fa3a583eb73f4cc88 --- /dev/null +++ b/acs-drv/files/pcbsa_acs_drv.c @@ -0,0 +1,241 @@ +/* + * PC BSA ACS Kernel module Main file. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Copyright (C) 2025, Arm Limited + * + * Author: Prasanth Pulla + * + */ + +#include +#include "pcbsa_acs_drv.h" + +#include "val/include/val_interface.h" +#include "val/include/acs_common.h" +#include "val/include/acs_val.h" +#include "val/include/acs_pcie.h" + +test_params_t params; +test_msg_parms_t msg_params; + +static int len = 0; + +unsigned int g_pcbsa_level = 1; +unsigned int g_pcbsa_only_level = 0; +unsigned int g_print_level = 3; +unsigned int *g_skip_test_num; +unsigned int g_num_skip = 3; +unsigned int *g_execute_tests; +unsigned int *g_execute_modules; +unsigned int g_acs_tests_total; +unsigned int g_acs_tests_pass; +unsigned int g_acs_tests_fail; +uint64_t g_exception_ret_addr; +uint64_t g_stack_pointer; +uint64_t g_ret_addr; +unsigned int g_print_mmio; +unsigned int g_curr_module; +unsigned int g_enable_module; + +/* Fill in the array to run only specific tests or modules */ +unsigned int g_specific_tests[] = {}; +unsigned int g_specific_modules[] = {}; + +uint32_t g_num_tests = sizeof(g_specific_tests)/sizeof(unsigned int); +uint32_t g_num_modules = sizeof(g_specific_modules)/sizeof(unsigned int); + +uint64_t *g_pe_info_ptr; +uint64_t *g_per_info_ptr; + +char *g_msg_buf; +int tail_msg; +extern int num_msg; +int val_glue_execute_command(void); + +int +val_glue_execute_command(void) +{ + uint32_t status = 0; + g_print_level = params.arg1; + if (g_num_tests) { + g_execute_tests = g_specific_tests; + } + + if (g_num_modules) { + g_execute_modules = g_specific_modules; + } + + if (params.api_num == PCBSA_CREATE_INFO_TABLES) + { + g_acs_tests_total = 0; + g_acs_tests_pass = 0; + g_acs_tests_fail = 0; + tail_msg = 0; + + g_msg_buf = (char*) kmalloc(num_msg * sizeof(test_msg_parms_t), GFP_KERNEL); + + g_pe_info_ptr = kmalloc(PE_INFO_TBL_SZ, GFP_KERNEL); + status = val_pe_create_info_table(g_pe_info_ptr); + if (status) { + params.arg0 = DRV_STATUS_AVAILABLE; + params.arg1 = status; + return 1; + } + g_per_info_ptr = kmalloc(PERIPHERAL_INFO_TBL_SZ, GFP_KERNEL); + val_peripheral_create_info_table(g_per_info_ptr); + + val_allocate_shared_mem(); + + params.arg0 = DRV_STATUS_AVAILABLE; + params.arg1 = 0; + + } + + if (params.api_num == PCBSA_FREE_INFO_TABLES) + { + kfree(g_pe_info_ptr); + kfree(g_per_info_ptr); + kfree(g_msg_buf); + kfree(g_skip_test_num); + + } + + if (params.api_num == PCBSA_PCIE_EXECUTE_TEST) + { + params.arg0 = DRV_STATUS_PENDING; + val_pcbsa_pcie_execute_tests(params.level, params.num_pe); + val_print(ACS_PRINT_TEST, "\n ------------------------------------------------------------", 0); + val_print(ACS_PRINT_TEST, "\n Total Tests Run = %2d, ", g_acs_tests_total); + val_print(ACS_PRINT_TEST, "Tests Passed = %2d, ", g_acs_tests_pass); + val_print(ACS_PRINT_TEST, "Tests Failed = %2d ", g_acs_tests_fail); + val_print(ACS_PRINT_TEST, "\n ------------------------------------------------------------\n", 0); + params.arg0 = DRV_STATUS_AVAILABLE; + params.arg1 = val_get_status(0); + } + + if(params.api_num == PCBSA_UPDATE_SKIP_LIST){ + g_skip_test_num = (unsigned int*) kmalloc(g_num_skip * sizeof(unsigned int), GFP_KERNEL); + g_skip_test_num[0] = params.arg0; + g_skip_test_num[1] = params.arg1; + g_skip_test_num[2] = params.arg2; + } + + return 0; +} + +static +int pcbsa_proc_open(struct inode *sp_inode, struct file *sp_file) +{ + return 0; +} + +static +int pcbsa_proc_release(struct inode *sp_indoe, struct file *sp_file) +{ + return 0; +} + +static +ssize_t pcbsa_proc_read(struct file *sp_file,char __user *buf, size_t size, loff_t *offset) +{ + + int var; + var = copy_to_user(buf,¶ms,len); + return len; +} + +static +ssize_t pcbsa_proc_write(struct file *sp_file,const char __user *buf, size_t size, loff_t *offset) +{ + int var; + len = size; + var = copy_from_user(¶ms,buf,len); + val_glue_execute_command(); + return len; +} + +static +ssize_t pcbsa_msg_proc_read(struct file *sp_file,char __user *buf, size_t size, loff_t *offset) +{ + int length; + len = sizeof(test_msg_parms_t); + if(*offset == (tail_msg*len)) len=0; + + length = simple_read_from_buffer(buf, len, offset, g_msg_buf, num_msg * sizeof(test_msg_parms_t)); + + if(length != 0) + memset(g_msg_buf+(*offset)-len, 0, sizeof(test_msg_parms_t)); + + return length; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(5,6,0) +const struct proc_ops pcbsa_msg_fops = { + .proc_open = pcbsa_proc_open, + .proc_read = pcbsa_msg_proc_read, + .proc_release = pcbsa_proc_release +}; + +static const struct proc_ops fops = { + .proc_open = pcbsa_proc_open, + .proc_read = pcbsa_proc_read, + .proc_write = pcbsa_proc_write, + .proc_release = pcbsa_proc_release +}; +#else +struct file_operations pcbsa_msg_fops = { + .open = pcbsa_proc_open, + .read = pcbsa_msg_proc_read, + .release = pcbsa_proc_release +}; + +struct file_operations fops = { + .open = pcbsa_proc_open, + .read = pcbsa_proc_read, + .write = pcbsa_proc_write, + .release = pcbsa_proc_release +}; +#endif + +static int __init init_pcbsaproc (void) +{ + printk("init PC BSA Driver \n"); + if (!proc_create("pcbsa",0666,NULL,&fops)) { + printk("ERROR! proc_create\n"); + remove_proc_entry("pcbsa",NULL); + return -1; + } + + if (!proc_create("pcbsa_msg",0666,NULL,&pcbsa_msg_fops)) { + printk("ERROR! proc_create PC BSA Msg \n"); + remove_proc_entry("pcbsa_msg",NULL); + return -1; + } + + return 0; +} + +static +void __exit exit_pcbsaproc(void) +{ + remove_proc_entry("pcbsa",NULL); + remove_proc_entry("pcbsa_msg",NULL); + printk("exit PCBSA Driver \n"); +} + +MODULE_INFO(intree, "Y"); +MODULE_LICENSE("GPL"); +module_init(init_pcbsaproc); +module_exit(exit_pcbsaproc); diff --git a/acs-drv/files/pcbsa_acs_drv.h b/acs-drv/files/pcbsa_acs_drv.h new file mode 100644 index 0000000000000000000000000000000000000000..853df36608296254dff4c8e7ac3892573373d77f --- /dev/null +++ b/acs-drv/files/pcbsa_acs_drv.h @@ -0,0 +1,56 @@ +/* + * PC BSA ACS Kernel module header file. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Copyright (C) 2025, Arm Limited + * + * Author: Prasanth Pulla + * + */ + +#include +#include +#include +#include + +#include + +#define PCBSA_CREATE_INFO_TABLES 0x1000 +#define PCBSA_PCIE_EXECUTE_TEST 0x2000 +#define PCBSA_UPDATE_SKIP_LIST 0x3000 +#define PCBSA_FREE_INFO_TABLES 0x9000 + +/* STATUS MESSAGES */ +#define DRV_STATUS_AVAILABLE 0x10000000 +#define DRV_STATUS_PENDING 0x40000000 + +/* Please MAKE SURE all table sizes are 16 bytes aligned */ +#define PE_INFO_TBL_SZ 16384 /* Supports maximum 400 PEs [40 B each + 4 B header] */ +#define PERIPHERAL_INFO_TBL_SZ 8192 /* Supports maximum 145 PCIe peripheral device (anykind) [56 B each + 16 B header] */ + +typedef +struct __TEST_PARAMS__ +{ + unsigned int api_num; + unsigned int num_pe; + unsigned int level; + unsigned long arg0; + unsigned long arg1; + unsigned long arg2; +}test_params_t; + +typedef struct __TEST_PCBSA_MSG__ { + char string[92]; + unsigned long data; +}test_msg_parms_t; diff --git a/acs-drv/files/platform/pal_linux/files/Makefile b/acs-drv/files/platform/pal_linux/files/Makefile index a196cd58d901f705a0fe21ede1aa44101dce264b..a1919376310bfe6660b09e3f1dbf83a9422f54ab 100644 --- a/acs-drv/files/platform/pal_linux/files/Makefile +++ b/acs-drv/files/platform/pal_linux/files/Makefile @@ -33,15 +33,24 @@ bsa_acs_pal-objs += $(PAL_SRC)/pal_misc.o \ $(PAL_SRC)/pal_dma.o $(PAL_SRC)/pal_acpi.o $(PAL_SRC)/pal_gic.o \ $(PAL_SRC)/pal_dt.o $(PAL_SRC)/pal_acpi.o $(PAL_SRC)/pal_exerciser.o $(PAL_SRC)/bsa-dma-iommu.o ccflags-y=-I$(PWD)/$(ACS_DIR)/val/include -I$(PWD)/$(ACS_DIR)/val/include -I$(PWD)/$(ACS_DIR)/include -I$(PWD)/$(ACS_DIR)/include -I$(PWD) -I$(PWD)/../../ -I$(PWD)/../../../ -DTARGET_LINUX -Wall -Werror -else + +else ifeq ($(ACS), sbsa) obj-m += sbsa_acs_pal.o sbsa_acs_pal-objs += $(PAL_SRC)/pal_misc.o \ $(PAL_SRC)/pal_pe.o $(PAL_SRC)/pal_pcie.o $(PAL_SRC)/pal_pcie_enumeration.o \ $(PAL_SRC)/pal_smmu.o $(PAL_SRC)/pal_iovirt.o $(PAL_SRC)/pal_peripherals.o $(PAL_SRC)/bsa-dma-iommu.o\ $(PAL_SRC)/pal_dma.o $(PAL_SRC)/pal_acpi.o $(PAL_SRC)/pal_gic.o \ $(PAL_SRC)/pal_iovirt.o $(PAL_SRC)/pal_exerciser.o - ccflags-y=-I$(PWD)/$(ACS_DIR)/val/include -I$(PWD)/$(ACS_DIR)/val/include -I$(PWD)/$(ACS_DIR)/include -I$(PWD)/$(ACS_DIR)/include -I$(PWD) -I$(PWD)/../../ -I$(PWD)/../../../ -DTARGET_LINUX -DBUILD_SBSA -Wall -Werror + +else ifeq ($(ACS), pcbsa) +obj-m += pcbsa_acs_pal.o +pcbsa_acs_pal-objs += $(PAL_SRC)/pal_misc.o \ + $(PAL_SRC)/pal_pe.o $(PAL_SRC)/pal_pcie.o $(PAL_SRC)/pal_pcie_enumeration.o \ + $(PAL_SRC)/pal_smmu.o $(PAL_SRC)/pal_peripherals.o $(PAL_SRC)/bsa-dma-iommu.o \ + $(PAL_SRC)/pal_dma.o $(PAL_SRC)/pal_acpi.o $(PAL_SRC)/pal_gic.o \ + $(PAL_SRC)/pal_iovirt.o $(PAL_SRC)/pal_exerciser.o +ccflags-y=-I$(PWD)/$(ACS_DIR)/val/include -I$(PWD)/$(ACS_DIR)/val/include -I$(PWD)/$(ACS_DIR)/include -I$(PWD)/$(ACS_DIR)/include -I$(PWD) -I$(PWD)/../../ -I$(PWD)/../../../ -DTARGET_LINUX -DPC_BSA -Wall -Werror endif @@ -59,6 +68,9 @@ bsa: sbsa: make -C $(KERNEL_SRC) M=$(PWD) ACS=sbsa modules +pcbsa: + make -C $(KERNEL_SRC) M=$(PWD) ACS=pcbsa modules + modules_install: $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules_install diff --git a/acs-drv/files/platform/pal_linux/files/src/pal_iovirt.c b/acs-drv/files/platform/pal_linux/files/src/pal_iovirt.c index a717706a4e66af27c88bde15ccf16125f348c5a7..d3ed69558b878b073522122370b8505043315e62 100644 --- a/acs-drv/files/platform/pal_linux/files/src/pal_iovirt.c +++ b/acs-drv/files/platform/pal_linux/files/src/pal_iovirt.c @@ -415,7 +415,7 @@ pal_iovirt_create_info_table(IOVIRT_INFO_TABLE *iovirt_table) dump_iovirt_table(iovirt_table); check_mapping_overlap(iovirt_table); } -#ifndef BUILD_SBSA +#if !defined(BUILD_SBSA) && !defined(PC_BSA) else { pal_iovirt_create_info_table_dt(iovirt_table); return; diff --git a/acs-drv/files/platform/pal_linux/files/src/pal_pcie.c b/acs-drv/files/platform/pal_linux/files/src/pal_pcie.c index 2307b664f35a4548ed692fde9b30b7cd44c9fe41..9a592b933a6b794a7040746bae555024bc5d6274 100644 --- a/acs-drv/files/platform/pal_linux/files/src/pal_pcie.c +++ b/acs-drv/files/platform/pal_linux/files/src/pal_pcie.c @@ -231,7 +231,7 @@ pal_pcie_create_info_table(PCIE_INFO_TABLE *PcieTable) i++; PcieTable->num_entries++; } while((length < mcfg->header.length) && (entry)); -#ifndef BUILD_SBSA +#if !defined(BUILD_SBSA) && !defined(PC_BSA) } else { pal_pcie_create_info_table_dt(PcieTable); #endif diff --git a/acs-drv/files/platform/pal_linux/files/src/pal_pe.c b/acs-drv/files/platform/pal_linux/files/src/pal_pe.c index 90906f98caf33b79e447276b34a0bdd9d99ea7ac..d9a1139ed2aa299d7c58ca8f427dfe0ef1bd396d 100644 --- a/acs-drv/files/platform/pal_linux/files/src/pal_pe.c +++ b/acs-drv/files/platform/pal_linux/files/src/pal_pe.c @@ -68,7 +68,7 @@ pal_pe_create_info_table(PE_INFO_TABLE *PeTable) entry = (struct acpi_madt_generic_interrupt *) ((u8 *)entry + (entry->header.length)); } while(length < table_length); -#ifndef BUILD_SBSA +#if !defined(BUILD_SBSA) && !defined(PC_BSA) } else { // Get from DT //