diff --git a/apps/uefi/Pfdi.inf b/apps/uefi/Pfdi.inf index 640828a5..68e3a01c 100644 --- a/apps/uefi/Pfdi.inf +++ b/apps/uefi/Pfdi.inf @@ -1,5 +1,5 @@ ## @file -# Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. +# Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. # SPDX-License-Identifier : Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,6 +32,8 @@ ../ ../../ app.c + acs_globals.c + acs_helpers.c pfdi_main.c ../../test_pool/pfdi/pfdi001.c ../../test_pool/pfdi/pfdi002.c @@ -49,6 +51,20 @@ ../../test_pool/pfdi/pfdi014.c ../../test_pool/pfdi/pfdi016.c ../../test_pool/pfdi/pfdi017.c + ../../test_pool/pfdi/pfdi018.c + ../../test_pool/pfdi/pfdi019.c + ../../test_pool/pfdi/pfdi020.c + ../../test_pool/pfdi/pfdi021.c + ../../test_pool/pfdi/pfdi022.c + ../../test_pool/pfdi/pfdi023.c + ../../test_pool/pfdi/pfdi024.c + ../../test_pool/pfdi/pfdi025.c + ../../test_pool/pfdi/pfdi026.c + ../../test_pool/pfdi/pfdi027.c + ../../test_pool/pfdi/pfdi028.c + ../../test_pool/pfdi/pfdi029.c + ../../test_pool/pfdi/pfdi030.c + ../../test_pool/pfdi/pfdi031.c [Packages] StdLib/StdLib.dec @@ -81,4 +97,4 @@ [BuildOptions] GCC:*_*_*_ASM_FLAGS = -march=armv8.1-a - GCC:*_*_*_CC_FLAGS = -O0 -DTARGET_UEFI -DEXCLUDE_RBX -I${ACS_PATH}/val + GCC:*_*_*_CC_FLAGS = -O0 -I${ACS_PATH}/ -I${ACS_PATH}/val -DTARGET_UEFI diff --git a/apps/uefi/pfdi_main.c b/apps/uefi/pfdi_main.c index ec030259..f8842b75 100644 --- a/apps/uefi/pfdi_main.c +++ b/apps/uefi/pfdi_main.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,281 +28,76 @@ #include "acs.h" -UINT32 g_print_level; -UINT32 g_acs_tests_pass; -UINT32 g_acs_tests_fail; -UINT32 *g_skip_test_num; -UINT32 g_num_skip; -UINT64 g_exception_ret_addr; -UINT32 g_print_mmio; -UINT32 g_curr_module; -UINT32 g_enable_module; -UINT32 *g_execute_tests; -UINT32 g_num_tests = 0; -UINT32 *g_execute_modules; -UINT32 g_num_modules = 0; -UINT32 g_acs_tests_total; - -SHELL_FILE_HANDLE g_acs_log_file_handle; - VOID HelpMsg ( VOID ) { - Print (L"\nUsage: pfdi.efi [-v ] | [-f ] | [-skip ] | [-t ] | [-m ]\n" - "Options:\n" - "-v Verbosity of the prints\n" - " 1 prints all, 5 prints only the errors\n" - " Note: pal_mmio prints can be enabled for specific modules by passing\n" - " module numbers along with global verbosity level 1\n" - " Module numbers are Interface 0, Dynamic Launch 1 ...\n" - " E.g., To enable mmio prints \n" - "-f Name of the log file to record the test results in\n" - "-skip Test(s) to be skipped\n" - " Refer to section pfdi ACS User Guide\n" - " To skip a module, use Module ID as mentioned in user guide\n" - " To skip a particular test within a module, use the exact testcase number\n" - "-t If Test ID(s) set, will only run the specified test(s), all others will be skipped.\n" - "-m If Module ID(s) set, will only run the specified module(s), all others will be skipped.\n" - ); + Print (L"\nUsage: pfdi.efi [options]\n" + "-f Log file to record test results\n" + "-h, -help Print this message\n" + "-m Run only the specified modules (comma-separated names)\n" + "-r Run specified rule IDs (comma-separated) or a rules file\n" + "-skip \n" + " Skip the specified rule IDs\n" + " Accepted value: PFDI\n" + "-skipmodule \n" + " Skip the specified modules\n" + "-v Verbosity of the prints (1-5)\n"); } -STATIC CONST SHELL_PARAM_ITEM ParamList[] = { - {L"-v", TypeValue}, // -v # Verbosity of the Prints. 1 shows all prints, 5 shows Errors - {L"-f", TypeValue}, // -f # Name of the log file to record the test results in. - {L"-skip", TypeValue}, // -skip # test(s) to skip execution - {L"-t", TypeValue}, // -t # Test to be run - {L"-m", TypeValue}, // -m # Module to be run - {L"-help", TypeFlag}, // -help # help : info about commands - {L"-h", TypeFlag}, // -h # help : info about commands +CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-f", TypeValue}, + {L"-h", TypeFlag}, + {L"-help", TypeFlag}, + {L"-m", TypeValue}, + {L"-r", TypeValue}, + {L"-skip", TypeValue}, + {L"-skipmodule", TypeValue}, + {L"-v", TypeValue}, {NULL, TypeMax} }; -/*** - Pfdi Compliance Suite Entry Point. - - Call the Entry points of individual modules. - - @retval 0 The application exited normally. - @retval Other An error occurred. -***/ -UINT32 -command_init () +static VOID +freePfdiAcsMem(void) { + val_pe_free_info_table(); + val_gic_free_info_table(); + val_free_shared_mem(); +} - LIST_ENTRY *ParamPackage; - CONST CHAR16 *CmdLineArg; - CHAR16 *ProbParam; - UINT32 Status; - UINT32 i; - UINT32 ReadVerbosity; - - // - // Process Command Line arguments - // - Status = ShellInitialize(); - Status = ShellCommandLineParse (ParamList, &ParamPackage, &ProbParam, TRUE); - if (Status) { - Print(L"Shell command line parse error %x\n", Status); - Print(L"Unrecognized option %s passed\n", ProbParam); - HelpMsg(); - return SHELL_INVALID_PARAMETER; - } - - // Options with Values - if (ShellCommandLineGetFlag (ParamPackage, L"-skip")) { - CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-skip"); - if (CmdLineArg == NULL) - { - Print(L"Invalid parameter passed for -skip\n", 0); - HelpMsg(); - return SHELL_INVALID_PARAMETER; - } - else - { - Status = gBS->AllocatePool(EfiBootServicesData, - StrLen(CmdLineArg), - (VOID **) &g_skip_test_num); - if (EFI_ERROR(Status)) - { - Print(L"Allocate memory for -skip failed \n", 0); - return ACS_PARSE_SKIP_RUN; - } - - g_skip_test_num[0] = StrDecimalToUintn((CONST CHAR16 *)(CmdLineArg+0)); - for (i = 0; i < StrLen(CmdLineArg); i++) { - if (*(CmdLineArg+i) == L',') { - g_skip_test_num[++g_num_skip] = StrDecimalToUintn((CONST CHAR16 *)(CmdLineArg+i+1)); - } - } - - g_num_skip++; - } - } - - // Options with Values - CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-v"); - if (CmdLineArg == NULL) { - g_print_level = 3; - } else { - ReadVerbosity = StrDecimalToUintn(CmdLineArg); - while (ReadVerbosity/10) { - g_enable_module |= (1 << ReadVerbosity%10); - ReadVerbosity /= 10; - } - g_print_level = ReadVerbosity; - if (g_print_level > 5) { - g_print_level = 3; - } - } - - // Options with Values - CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-f"); - if (CmdLineArg == NULL) { - g_acs_log_file_handle = NULL; - } else { - Status = ShellOpenFileByName(CmdLineArg, &g_acs_log_file_handle, - EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE, 0x0); - if (EFI_ERROR(Status)) { - Print(L"Failed to open log file %s\n", CmdLineArg); - g_acs_log_file_handle = NULL; - } +static UINT32 +apply_cli_defaults(void) +{ + if (g_rule_count == 0) { + g_arch_selection = ARCH_PFDI; } - // Options with Flags - if ((ShellCommandLineGetFlag (ParamPackage, L"-help")) || - (ShellCommandLineGetFlag (ParamPackage, L"-h"))) { - HelpMsg(); - return ACS_PARSE_SKIP_RUN; + if (g_level_filter_mode == LVL_FILTER_NONE) { + g_level_filter_mode = LVL_FILTER_MAX; + g_level_value = PFDI_LEVEL_1; } - // Options with Values - if (ShellCommandLineGetFlag (ParamPackage, L"-t")) { - CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t"); - if (CmdLineArg == NULL) - { - Print(L"Invalid parameter passed for -t\n", 0); - HelpMsg(); - return SHELL_INVALID_PARAMETER; - } - else - { - Status = gBS->AllocatePool(EfiBootServicesData, - StrLen(CmdLineArg), - (VOID **) &g_execute_tests); - if (EFI_ERROR(Status)) - { - Print(L"Allocate memory for -t failed \n", 0); - return ACS_PARSE_SKIP_RUN; - } - - /* Check if the first value to -t is a decimal character. */ - if (!ShellIsDecimalDigitCharacter(*CmdLineArg)) { - Print(L"Invalid parameter passed for -t\n", 0); - HelpMsg(); - return SHELL_INVALID_PARAMETER; - } - - g_execute_tests[0] = StrDecimalToUintn((CONST CHAR16 *)(CmdLineArg + 0)); - for (i = 0; i < StrLen(CmdLineArg); i++) { - if (*(CmdLineArg + i) == L',') { - g_execute_tests[++g_num_tests] = StrDecimalToUintn( - (CONST CHAR16 *)(CmdLineArg + i + 1)); - } - } - - g_num_tests++; - } + if (g_level_value >= PFDI_LEVEL_SENTINEL) { + val_print(ACS_PRINT_ERR, "\nInvalid level value passed (%d), ", g_level_value); + val_print(ACS_PRINT_ERR, "value should be less than %d.", PFDI_LEVEL_SENTINEL); + return ACS_STATUS_FAIL; } - // Options with Values - if (ShellCommandLineGetFlag (ParamPackage, L"-m")) { - CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-m"); - if (CmdLineArg == NULL) - { - Print(L"Invalid parameter passed for -m\n", 0); - HelpMsg(); - return SHELL_INVALID_PARAMETER; - } - else - { - Status = gBS->AllocatePool(EfiBootServicesData, - StrLen(CmdLineArg), - (VOID **) &g_execute_modules); - if (EFI_ERROR(Status)) - { - Print(L"Allocate memory for -m failed \n", 0); - return ACS_PARSE_SKIP_RUN; - } - - /* Check if the first value to -m is a decimal character. */ - if (!ShellIsDecimalDigitCharacter(*CmdLineArg)) { - Print(L"Invalid parameter passed for -m\n", 0); - HelpMsg(); - return SHELL_INVALID_PARAMETER; - } - - g_execute_modules[0] = StrDecimalToUintn((CONST CHAR16 *)(CmdLineArg + 0)); - for (i = 0; i < StrLen(CmdLineArg); i++) { - if (*(CmdLineArg + i) == L',') { - g_execute_modules[++g_num_modules] = StrDecimalToUintn( - (CONST CHAR16 *)(CmdLineArg + i + 1)); - } - } - - g_num_modules++; - } - } - return(0); -} - -EFI_STATUS -createPeInfoTable ( -) -{ - - EFI_STATUS Status; - - UINT64 *PeInfoTable; - - PeInfoTable = val_aligned_alloc(SIZE_4K, PE_INFO_TBL_SZ); - - Status = val_pe_create_info_table(PeInfoTable); - - return Status; - -} - -EFI_STATUS -createGicInfoTable ( -) -{ - EFI_STATUS Status; - UINT64 *GicInfoTable; - - GicInfoTable = val_aligned_alloc(SIZE_4K, GIC_INFO_TBL_SZ); - - Status = val_gic_create_info_table(GicInfoTable); - - return Status; - -} - -VOID -freePfdiAcsMem() -{ - val_pe_free_info_table(); - val_gic_free_info_table(); - val_free_shared_mem(); + return ACS_STATUS_PASS; } UINT32 execute_tests() { - UINT32 Status; + UINT32 Status; + + Status = apply_cli_defaults(); + if (Status != ACS_STATUS_PASS) { + goto exit_close; + } - val_print(ACS_PRINT_TEST, "\n\n Pfdi Architecture Compliance Suite", 0); + val_print(ACS_PRINT_TEST, "\n\n PFDI Architecture Compliance Suite", 0); val_print(ACS_PRINT_TEST, "\n Version %d.", PFDI_ACS_MAJOR_VER); val_print(ACS_PRINT_TEST, "%d.", PFDI_ACS_MINOR_VER); val_print(ACS_PRINT_TEST, "%d\n", PFDI_ACS_SUBMINOR_VER); @@ -311,43 +106,44 @@ execute_tests() val_print(ACS_PRINT_TEST, "\n Creating Platform Information Tables\n", 0); Status = createPeInfoTable(); - if (Status) { - if (g_acs_log_file_handle) - ShellCloseFile(&g_acs_log_file_handle); - return Status; - } + if (Status) + goto exit_close; Status = createGicInfoTable(); - if (Status) { - if (g_acs_log_file_handle) - ShellCloseFile(&g_acs_log_file_handle); - return Status; - } + if (Status) + goto exit_close; val_allocate_shared_mem(); - g_acs_tests_pass = 0; - g_acs_tests_fail = 0; - /* Starting Platform Fault Detection Interface Tests */ - Status = val_pfdi_execute_pfdi_tests(val_pe_get_num()); - if (Status != PFDI_ACS_NOT_IMPLEMENTED) { - /* Print Summary */ - val_print(ACS_PRINT_TEST, - "\n -------------------------------------------------------\n", 0); - val_print(ACS_PRINT_TEST, " Total Tests Run = %4d", g_acs_tests_total); - val_print(ACS_PRINT_TEST, " Tests Passed = %4d", g_acs_tests_pass); - val_print(ACS_PRINT_TEST, " Tests Failed = %4d\n", g_acs_tests_fail); - val_print(ACS_PRINT_TEST, " -------------------------------------------------------\n", 0); - val_print(ACS_PRINT_TEST, "\n *** Pfdi tests complete. *** \n\n", 0); + Status = val_pfdi_check_implementation(); + if (Status == PFDI_ACS_NOT_IMPLEMENTED) { + val_print(ACS_PRINT_ERR, "\n PFDI not implemented - Skipping all PFDI tests\n", 0); + goto exit_summary; + } else if (Status != ACS_STATUS_PASS) { + goto exit_summary; + } + + if ((g_rule_count > 0 && g_rule_list != NULL) || (g_arch_selection != ARCH_NONE)) { + g_rule_count = filter_rule_list_by_cli(&g_rule_list, g_rule_count); + if (g_rule_count == 0 || g_rule_list == NULL) + goto exit_summary; + + print_selection_summary(); + run_tests(g_rule_list, g_rule_count); } else { - val_print(ACS_PRINT_ERR, "\n PFDI not implemented - Skipping all PFDI tests\n", 0); + val_print(ACS_PRINT_TEST, "\nNo rules selected for execution.\n", 0); } +exit_summary: + val_print_acs_test_status_summary(); + val_print(ACS_PRINT_ERR, "\n *** PFDI tests complete. *** \n\n", 0); + +exit_close: freePfdiAcsMem(); if (g_acs_log_file_handle) { ShellCloseFile(&g_acs_log_file_handle); } - return 0; + return ACS_STATUS_PASS; } diff --git a/pal/uefi_acpi/src/pal_peripherals.c b/pal/uefi_acpi/src/pal_peripherals.c index 932fa2c5..14b1bac0 100644 --- a/pal/uefi_acpi/src/pal_peripherals.c +++ b/pal/uefi_acpi/src/pal_peripherals.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, 2020-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2018, 2020-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pal/uefi_dt/src/AArch64/AcsPfdiTest.S b/pal/uefi_dt/src/AArch64/AcsPfdiTest.S index 6ab9a976..17bc23f9 100644 --- a/pal/uefi_dt/src/AArch64/AcsPfdiTest.S +++ b/pal/uefi_dt/src/AArch64/AcsPfdiTest.S @@ -1,5 +1,5 @@ #/** @file -# Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. +# Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. # SPDX-License-Identifier : Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -79,7 +79,7 @@ finish: stp x11, x12, [x22], #16 stp x13, x14, [x22], #16 stp x15, x16, [x22], #16 - str x17, [x21] + str x17, [x22] // Store the SMC returned values x0-x4 into the ARM_SMC_ARGS structure. diff --git a/pal/uefi_dt/src/pal_peripherals.c b/pal/uefi_dt/src/pal_peripherals.c index fd282ccf..9f386acb 100644 --- a/pal/uefi_dt/src/pal_peripherals.c +++ b/pal/uefi_dt/src/pal_peripherals.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, 2020-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2018, 2020-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/patches/edk2_pfdi.patch b/patches/edk2_pfdi.patch index d159a01a..c362b9e1 100644 --- a/patches/edk2_pfdi.patch +++ b/patches/edk2_pfdi.patch @@ -1,6 +1,6 @@ ---- a/MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.c -+++ b/MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.c -@@ -90,8 +90,8 @@ +--- a/MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.c ++++ b/MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.c +@@ -90,8 +90,8 @@ // // Retrieve the pointer to the UEFI HII Config Routing Protocol // @@ -11,19 +11,19 @@ // // Retrieve the pointer to the optional UEFI HII Font Protocol ---- a/ShellPkg/ShellPkg.dsc -+++ b/ShellPkg/ShellPkg.dsc -@@ -66,6 +66,9 @@ +--- a/ShellPkg/ShellPkg.dsc ++++ b/ShellPkg/ShellPkg.dsc +@@ -66,6 +66,9 @@ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + BaseFdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf -+ ValLib|ShellPkg/Application/sysarch-acs/val/ValLib.inf ++ ValLib|ShellPkg/Application/sysarch-acs/val/ValLibRB.inf + PalLib|ShellPkg/Application/sysarch-acs/pal/uefi_dt/PalLib.inf [PcdsFixedAtBuild] gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF -@@ -93,6 +96,7 @@ +@@ -93,6 +96,7 @@ ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf @@ -31,3 +31,9 @@ ShellPkg/Application/Shell/Shell.inf { +@@ -157,4 +161,4 @@ + ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyApp.inf + + [BuildOptions] +- *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES ++ *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -D PFDI_DT_BUILD diff --git a/test_pool/exerciser/e003.c b/test_pool/exerciser/e003.c index ffac94f2..ddb9b2cd 100644 --- a/test_pool/exerciser/e003.c +++ b/test_pool/exerciser/e003.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2020-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2020-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test_pool/exerciser/e016.c b/test_pool/exerciser/e016.c index 4f08a3c7..71185c72 100644 --- a/test_pool/exerciser/e016.c +++ b/test_pool/exerciser/e016.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2023-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2023-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test_pool/exerciser/e021.c b/test_pool/exerciser/e021.c index 7a673e41..aeb315b7 100644 --- a/test_pool/exerciser/e021.c +++ b/test_pool/exerciser/e021.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2020-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2020-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test_pool/exerciser/e039.c b/test_pool/exerciser/e039.c index 300218c3..f308fda5 100644 --- a/test_pool/exerciser/e039.c +++ b/test_pool/exerciser/e039.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test_pool/pcie/p045.c b/test_pool/pcie/p045.c index e1e34dd5..14816ca4 100644 --- a/test_pool/pcie/p045.c +++ b/test_pool/pcie/p045.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test_pool/pcie/p094.c b/test_pool/pcie/p094.c index acaed193..fb87bac3 100644 --- a/test_pool/pcie/p094.c +++ b/test_pool/pcie/p094.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, 2020-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2018, 2020-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test_pool/pfdi/pfdi007.c b/test_pool/pfdi/pfdi007.c index 2e12d2fc..f4bc2da7 100644 --- a/test_pool/pfdi/pfdi007.c +++ b/test_pool/pfdi/pfdi007.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,153 +21,208 @@ #define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 7) #define TEST_RULE "R0076" -#define TEST_DESC "Execute Test Parts on PE " +#define TEST_DESC "Execute Test Parts and All Parts on PE " -static PFDI_RET_PARAMS *g_pfdi_run_status_details; +#define RUN_ALL_TEST_PARTS -1 + +static PFDI_RET_PARAMS *g_pfdi_range_status; +static PFDI_RET_PARAMS *g_pfdi_all_parts_status; static void pfdi_test_run(void) { uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); int64_t test_parts; - PFDI_RET_PARAMS *pfdi_buffer; + int64_t end; + PFDI_RET_PARAMS *pfdi_range, *pfdi_all; + + pfdi_range = g_pfdi_range_status + index; + pfdi_all = g_pfdi_all_parts_status + index; - pfdi_buffer = g_pfdi_run_status_details + index; + /* Run all test parts first, then retrieve test part count for range execution */ + pfdi_all->x0 = val_pfdi_pe_test_run(RUN_ALL_TEST_PARTS, RUN_ALL_TEST_PARTS, + &pfdi_all->x1, &pfdi_all->x2, &pfdi_all->x3, &pfdi_all->x4); + val_pfdi_invalidate_ret_params(pfdi_all); - /* Get Num of Test parts supported on curr PE */ + /* Now get Num of Test parts supported on current PE */ test_parts = val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); if (test_parts < PFDI_ACS_SUCCESS) { - val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + pfdi_range->x0 = test_parts; + val_pfdi_invalidate_ret_params(pfdi_range); + val_set_status(index, RESULT_FAIL(TEST_NUM, 6)); return; } - if (test_parts > 0) - test_parts = test_parts - 1; - - /* Invoke PFDI Run function for current PE index */ - pfdi_buffer->x0 = val_pfdi_pe_test_run(0, test_parts, - &pfdi_buffer->x1, &pfdi_buffer->x2, &pfdi_buffer->x3, &pfdi_buffer->x4); - - val_pfdi_invalidate_ret_params(pfdi_buffer); + end = (test_parts == 0) ? 0 : (test_parts - 1); + /* Run range */ + pfdi_range->x0 = val_pfdi_pe_test_run(0, end, + &pfdi_range->x1, &pfdi_range->x2, &pfdi_range->x3, &pfdi_range->x4); + val_pfdi_invalidate_ret_params(pfdi_range); val_set_status(index, RESULT_PASS(TEST_NUM, 1)); - return; } static void payload_run(void *arg) { uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t timeout, i = 0, test_fail = 0, check_x1 = 0; + uint32_t timeout, i = 0, test_fail = 0; uint32_t num_pe = *(uint32_t *)arg; - PFDI_RET_PARAMS *pfdi_buffer; + PFDI_RET_PARAMS *pfdi_range_buffer; + PFDI_RET_PARAMS *pfdi_all_parts_buffer; /* Allocate memory to save all PFDI run status and fault id's for all PE's */ - g_pfdi_run_status_details = - (PFDI_RET_PARAMS *) val_memory_calloc(num_pe, sizeof(PFDI_RET_PARAMS)); - if (g_pfdi_run_status_details == NULL) { - val_print(ACS_PRINT_ERR, - "\n Allocation for PFDI Run Function Failed", 0); + g_pfdi_range_status = + (PFDI_RET_PARAMS *) val_memory_calloc(num_pe, sizeof(PFDI_RET_PARAMS)); + if (g_pfdi_range_status == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for g_pfdi_range_status Failed", 0); val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); return; } + g_pfdi_all_parts_status = + (PFDI_RET_PARAMS *) val_memory_calloc(num_pe, sizeof(PFDI_RET_PARAMS)); + if (g_pfdi_all_parts_status == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for g_pfdi_all_parts_status Failed", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details_range; + } + + /* Invalidate both buffers in one pass */ for (i = 0; i < num_pe; i++) { - pfdi_buffer = g_pfdi_run_status_details + i; - val_pfdi_invalidate_ret_params(pfdi_buffer); + val_pfdi_invalidate_ret_params(g_pfdi_range_status + i); + val_pfdi_invalidate_ret_params(g_pfdi_all_parts_status + i); } - /* Invoke PFDI Run function for current PE index */ + /* Run tests on primary PE, then on all others */ pfdi_test_run(); - - /* Execute pfdi_test_run function in All PE's */ for (i = 0; i < num_pe; i++) { if (i != index) { timeout = TIMEOUT_LARGE; val_execute_on_pe(i, pfdi_test_run, 0); while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); - if (timeout == 0) { val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); - val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); - goto free_pfdi_details; + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + goto free_pfdi_details_both; } } } val_time_delay_ms(ONE_MILLISECOND); - /* Check return status of function for all PE's */ for (i = 0; i < num_pe; i++) { - pfdi_buffer = g_pfdi_run_status_details + i; - val_pfdi_invalidate_ret_params(pfdi_buffer); + pfdi_all_parts_buffer = g_pfdi_all_parts_status + i; + pfdi_range_buffer = g_pfdi_range_status + i; + val_pfdi_invalidate_ret_params(pfdi_all_parts_buffer); + val_pfdi_invalidate_ret_params(pfdi_range_buffer); test_fail = 0; - check_x1 = 0; - if (IS_TEST_FAIL(val_get_status(i))) { - val_print(ACS_PRINT_ERR, "\n Failed to get Test Part count on PE %d ", i); - val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); - goto free_pfdi_details; - } + /* All-parts validation */ + if (pfdi_all_parts_buffer->x0 == PFDI_ACS_SUCCESS) { + if (pfdi_all_parts_buffer->x1 != 0) { + val_print(ACS_PRINT_ERR, "\n X1 not zero for SUCCESS (all-parts): x1=0x%llx", + pfdi_all_parts_buffer->x1); + val_print(ACS_PRINT_ERR, " on PE %d", i); + test_fail++; + } - if (pfdi_buffer->x0 < PFDI_ACS_SUCCESS) { - if (pfdi_buffer->x0 == PFDI_ACS_FAULT_FOUND) { - if (pfdi_buffer->x1 == PFDI_ACS_UNKNOWN) { - val_print(ACS_PRINT_ERR, "\n Fault in PFDI test part on PE %d ", i); - val_print(ACS_PRINT_ERR, "cannot be identified", 0); - } else { - val_print(ACS_PRINT_ERR, "\n PFDI test part %lld ", pfdi_buffer->x1); - val_print(ACS_PRINT_ERR, "triggered the fault on PE %d", i); - } - } else if (pfdi_buffer->x0 == PFDI_ACS_ERROR) { - check_x1++; - val_print(ACS_PRINT_ERR, - "\n PFDI Test parts have executed but failed to complete on PE %d", i); + } else if (pfdi_all_parts_buffer->x0 == PFDI_ACS_FAULT_FOUND) { + /* FAULT_FOUND: x1 contains the faulty test part index (zero is valid) */ + if (pfdi_all_parts_buffer->x1 == PFDI_ACS_UNKNOWN) { + val_print(ACS_PRINT_ERR, "\n Fault in test part (all-parts) on PE %d ", i); + val_print(ACS_PRINT_ERR, "cannot be identified", 0); } else { - val_print(ACS_PRINT_ERR, - "\n PFDI PE Run function failed %lld ", pfdi_buffer->x0); - val_print(ACS_PRINT_ERR, "on PE %d", i); + val_print(ACS_PRINT_ERR, "\n Test part %lld (all-parts) ", pfdi_all_parts_buffer->x1); + val_print(ACS_PRINT_ERR, "triggered the fault on PE %d", i); + } + + } else if (pfdi_all_parts_buffer->x0 == PFDI_ACS_ERROR) { + if (pfdi_all_parts_buffer->x1 != 0) { + val_print(ACS_PRINT_ERR, "\n X1 not zero for ERROR (all-parts): x1=0x%llx", + pfdi_all_parts_buffer->x1); + val_print(ACS_PRINT_ERR, " on PE %d", i); test_fail++; } - } else if (pfdi_buffer->x0 == PFDI_ACS_SUCCESS) { - check_x1++; + val_print(ACS_PRINT_ERR, "\n All-parts execution failed on PE index %d", i); + } else { - val_print(ACS_PRINT_ERR, "\n PFDI PE Results function failed err = %lld", - pfdi_buffer->x0); - val_print(ACS_PRINT_ERR, "on PE %d", i); - check_x1++; + val_print(ACS_PRINT_ERR, "\n All-parts run returned unexpected x0 on PE index %d", i); test_fail++; } - if (check_x1) { - if (pfdi_buffer->x1 != 0) { - val_print(ACS_PRINT_ERR, "\n Register X1 is not zero:", 0); - val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->x1); - val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + /* Check X2-X4 are zero for all-parts execution */ + if (pfdi_all_parts_buffer->x2 || pfdi_all_parts_buffer->x3 || + pfdi_all_parts_buffer->x4) { + val_print(ACS_PRINT_ERR, "\n X2-X4 not zero (all-parts):", 0); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_all_parts_buffer->x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_all_parts_buffer->x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_all_parts_buffer->x4); + val_print(ACS_PRINT_ERR, " on PE %d", i); + test_fail++; + } + + /* Check if test part count acquisition failed on this PE */ + if (IS_TEST_FAIL(val_get_status(i))) { + val_print(ACS_PRINT_ERR, "\n Failed to get Test Part count on PE %d ", i); + test_fail++; + continue; + } + + /* Range validation */ + if (pfdi_range_buffer->x0 == PFDI_ACS_SUCCESS) { + if (pfdi_range_buffer->x1 != 0) { + val_print(ACS_PRINT_ERR, "\n X1 not zero for SUCCESS (range): x1=0x%llx", + pfdi_range_buffer->x1); + val_print(ACS_PRINT_ERR, " on PE %d", i); test_fail++; } + + } else if (pfdi_range_buffer->x0 == PFDI_ACS_FAULT_FOUND) { + /* FAULT_FOUND: x1 contains the faulty test part index (zero is valid) */ + if (pfdi_range_buffer->x1 == PFDI_ACS_UNKNOWN) { + val_print(ACS_PRINT_ERR, "\n Fault in test part (range) on PE %d ", i); + val_print(ACS_PRINT_ERR, "cannot be identified", 0); + } else { + val_print(ACS_PRINT_ERR, "\n Test part %lld (range) ", pfdi_range_buffer->x1); + val_print(ACS_PRINT_ERR, "triggered the fault on PE %d", i); + } + + } else if (pfdi_range_buffer->x0 == PFDI_ACS_ERROR) { + if (pfdi_range_buffer->x1 != 0) { + val_print(ACS_PRINT_ERR, "\n X1 not zero for ERROR (range): x1=0x%llx", + pfdi_range_buffer->x1); + val_print(ACS_PRINT_ERR, " on PE %d", i); + test_fail++; + } + val_print(ACS_PRINT_ERR, "\n Range execution failed to complete on PE %d", i); + + } else { + val_print(ACS_PRINT_ERR, "\n Range run returned unexpected x0 on PE %d", i); + test_fail++; } - if ((pfdi_buffer->x1 != 0) || (pfdi_buffer->x2 != 0) || - (pfdi_buffer->x3 != 0) || (pfdi_buffer->x4 != 0)) { - val_print(ACS_PRINT_ERR, "\n Registers X1-X4 are not zero:", 0); - val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->x1); - val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->x2); - val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->x3); - val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->x4); - val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + /* Check X2-X4 are zero for range execution */ + if (pfdi_range_buffer->x2 || pfdi_range_buffer->x3 || + pfdi_range_buffer->x4) { + val_print(ACS_PRINT_ERR, "\n X2-X4 not zero (range):", 0); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_range_buffer->x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_range_buffer->x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_range_buffer->x4); + val_print(ACS_PRINT_ERR, " on PE %d", i); test_fail++; } if (test_fail) - val_set_status(i, RESULT_FAIL(TEST_NUM, 4)); + val_set_status(i, RESULT_FAIL(TEST_NUM, 5)); else val_set_status(i, RESULT_PASS(TEST_NUM, 1)); } -free_pfdi_details: - val_memory_free((void *) g_pfdi_run_status_details); +free_pfdi_details_both: + val_memory_free((void *) g_pfdi_all_parts_status); - return; +free_pfdi_details_range: + val_memory_free((void *) g_pfdi_range_status); } uint32_t pfdi007_entry(uint32_t num_pe) diff --git a/test_pool/pfdi/pfdi012.c b/test_pool/pfdi/pfdi012.c index bea58aa2..d94acf1d 100644 --- a/test_pool/pfdi/pfdi012.c +++ b/test_pool/pfdi/pfdi012.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,191 +30,252 @@ test_config_t test_entries[] = { { ACS_PFDI_TEST_NUM_BASE + 15, "PFDI recovery after forced error ", "R0100"} }; -enum { - VERSION_UNSUPP = 0, - FEATURE_UNSUPP, - TESTID_UNKNOWN, - TESTPART_UNSUPP, - TESTRUN_FAULT, - RESULT_ERROR, - FWCHECK_UNSUPP, - STATUS_COUNT +static const char *pfdi_test_names[PFDI_FN_MAX_IDX] = { + [PFDI_FN_VERSION_IDX] = "Version Unsupported", + [PFDI_FN_FEATURES_IDX] = "Feature Unsupported", + [PFDI_FN_PE_TEST_ID_IDX] = "TEST ID Unknown", + [PFDI_FN_PE_TEST_PART_COUNT_IDX] = "TEST PART Unsupported", + [PFDI_FN_PE_TEST_RUN_IDX] = "TEST RUN Fault", + [PFDI_FN_PE_TEST_RESULT_IDX] = "Result Error", + [PFDI_FN_FW_CHECK_IDX] = "FW CHECK Unsupported", + [PFDI_FN_FORCE_ERROR_IDX] = "Force Error Unsupported", }; -static const char *pfdi_test_names[STATUS_COUNT] = { - [VERSION_UNSUPP] = "Version Unsupported", - [FEATURE_UNSUPP] = "Feature Unsupported", - [TESTID_UNKNOWN] = "TEST_ID Unknown", - [TESTPART_UNSUPP] = "TEST_PART Unsupported", - [TESTRUN_FAULT] = "TEST_RUN Fault", - [RESULT_ERROR] = "Result Error", - [FWCHECK_UNSUPP] = "FW_CHECK Unsupported", -}; - -static const int64_t fail_status[STATUS_COUNT] = { - [VERSION_UNSUPP] = PFDI_ACS_NOT_SUPPORTED, - [FEATURE_UNSUPP] = PFDI_ACS_NOT_SUPPORTED, - [TESTID_UNKNOWN] = PFDI_ACS_UNKNOWN, - [TESTPART_UNSUPP] = PFDI_ACS_NOT_SUPPORTED, - [TESTRUN_FAULT] = PFDI_ACS_FAULT_FOUND, - [RESULT_ERROR] = PFDI_ACS_ERROR, - [FWCHECK_UNSUPP] = PFDI_ACS_NOT_SUPPORTED, +static const int64_t fail_status[PFDI_FN_MAX_IDX] = { + [PFDI_FN_VERSION_IDX] = PFDI_ACS_NOT_SUPPORTED, + [PFDI_FN_FEATURES_IDX] = PFDI_ACS_NOT_SUPPORTED, + [PFDI_FN_PE_TEST_ID_IDX] = PFDI_ACS_UNKNOWN, + [PFDI_FN_PE_TEST_PART_COUNT_IDX] = PFDI_ACS_NOT_SUPPORTED, + [PFDI_FN_PE_TEST_RUN_IDX] = PFDI_ACS_FAULT_FOUND, + [PFDI_FN_PE_TEST_RESULT_IDX] = PFDI_ACS_ERROR, + [PFDI_FN_FW_CHECK_IDX] = PFDI_ACS_NOT_SUPPORTED, + [PFDI_FN_FORCE_ERROR_IDX] = PFDI_ACS_NOT_SUPPORTED, }; typedef struct { - int64_t status[STATUS_COUNT]; - int64_t x1[STATUS_COUNT]; - int64_t x2[STATUS_COUNT]; - int64_t x3[STATUS_COUNT]; - int64_t x4[STATUS_COUNT]; -} pfdi_fun_status; - -typedef struct { - pfdi_fun_status force_err; - pfdi_fun_status pfdi_func; + PFDI_RET_PARAMS force_err[PFDI_FN_MAX_IDX]; } pfdi_force_error_check; typedef struct { - int64_t status[STATUS_COUNT]; + int64_t force_err_status[PFDI_FN_MAX_IDX]; + int64_t alt_status[PFDI_FN_MAX_IDX]; + PFDI_RET_PARAMS rec_status[PFDI_FN_MAX_IDX]; + int64_t norm_mode_status[PFDI_FN_MAX_IDX]; } pfdi_err_recovery_check; static uint32_t test_num; pfdi_force_error_check *g_pfdi_force_error_check; pfdi_err_recovery_check *g_pfdi_err_recovery_check; -static volatile uint32_t g_pfdi_set_status = 1; - static void pfdi_error_injection(void) { uint32_t i, index = val_pe_get_index_mpid(val_pe_get_mpid()); - pfdi_force_error_check *status_buffer; - pfdi_fun_status *err; - pfdi_fun_status *fun; - - status_buffer = g_pfdi_force_error_check + index; - err = &status_buffer->force_err; - fun = &status_buffer->pfdi_func; - - /* ---- PFDI_VERSION force NOT_SUPPORTED---- */ - err->status[VERSION_UNSUPP] = val_pfdi_force_error(PFDI_FN_PFDI_VERSION, PFDI_ACS_NOT_SUPPORTED, - &err->x1[VERSION_UNSUPP], &err->x2[VERSION_UNSUPP], - &err->x3[VERSION_UNSUPP], &err->x4[VERSION_UNSUPP]); - if (err->status[VERSION_UNSUPP] == PFDI_ACS_SUCCESS) { - fun->status[VERSION_UNSUPP] = val_pfdi_version(NULL, NULL, NULL, NULL); + pfdi_force_error_check *pfdi_buffer; + PFDI_RET_PARAMS *err; + + pfdi_buffer = g_pfdi_force_error_check + index; + err = pfdi_buffer->force_err; + + /* PFDI_VERSION force NOT_SUPPORTED */ + err[PFDI_FN_VERSION_IDX].x0 = val_pfdi_force_error(PFDI_FN_PFDI_VERSION, PFDI_ACS_NOT_SUPPORTED, + &err[PFDI_FN_VERSION_IDX].x1, &err[PFDI_FN_VERSION_IDX].x2, + &err[PFDI_FN_VERSION_IDX].x3, &err[PFDI_FN_VERSION_IDX].x4); + val_pfdi_version(NULL, NULL, NULL, NULL); + + /* PFDI_FEATURES force NOT_SUPPORTED */ + err[PFDI_FN_FEATURES_IDX].x0 = val_pfdi_force_error(PFDI_FN_PFDI_FEATURES, + PFDI_ACS_NOT_SUPPORTED, &err[PFDI_FN_FEATURES_IDX].x1, &err[PFDI_FN_FEATURES_IDX].x2, + &err[PFDI_FN_FEATURES_IDX].x3, &err[PFDI_FN_FEATURES_IDX].x4); + val_pfdi_features(PFDI_FN_PFDI_VERSION, NULL, NULL, NULL, NULL); + + /* PFDI_PE_TEST_ID force UNKNOWN */ + err[PFDI_FN_PE_TEST_ID_IDX].x0 = val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_ID, PFDI_ACS_UNKNOWN, + &err[PFDI_FN_PE_TEST_ID_IDX].x1, &err[PFDI_FN_PE_TEST_ID_IDX].x2, + &err[PFDI_FN_PE_TEST_ID_IDX].x3, &err[PFDI_FN_PE_TEST_ID_IDX].x4); + val_pfdi_pe_test_id(NULL, NULL, NULL, NULL); + + /* PFDI_PE_TEST_PART_COUNT force NOT_SUPPORTED */ + err[PFDI_FN_PE_TEST_PART_COUNT_IDX].x0 = + val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_PART_COUNT, PFDI_ACS_NOT_SUPPORTED, + &err[PFDI_FN_PE_TEST_PART_COUNT_IDX].x1, &err[PFDI_FN_PE_TEST_PART_COUNT_IDX].x2, + &err[PFDI_FN_PE_TEST_PART_COUNT_IDX].x3, &err[PFDI_FN_PE_TEST_PART_COUNT_IDX].x4); + val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); + + /* PFDI_PE_TEST_RUN force FAULT_FOUND */ + err[PFDI_FN_PE_TEST_RUN_IDX].x0 = + val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RUN, PFDI_ACS_FAULT_FOUND, + &err[PFDI_FN_PE_TEST_RUN_IDX].x1, &err[PFDI_FN_PE_TEST_RUN_IDX].x2, + &err[PFDI_FN_PE_TEST_RUN_IDX].x3, &err[PFDI_FN_PE_TEST_RUN_IDX].x4); + val_pfdi_pe_test_run(PFDI_RUN_ALL_TEST_PARTS, PFDI_RUN_ALL_TEST_PARTS, NULL, NULL, NULL, NULL); + + /* PFDI_PE_TEST_RESULT force ERROR */ + err[PFDI_FN_PE_TEST_RESULT_IDX].x0 = + val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RESULT, PFDI_ACS_ERROR, + &err[PFDI_FN_PE_TEST_RESULT_IDX].x1, &err[PFDI_FN_PE_TEST_RESULT_IDX].x2, + &err[PFDI_FN_PE_TEST_RESULT_IDX].x3, &err[PFDI_FN_PE_TEST_RESULT_IDX].x4); + val_pfdi_pe_test_result(NULL, NULL, NULL, NULL); + + /* PFDI_FW_CHECK force NOT_SUPPORTED */ + err[PFDI_FN_FW_CHECK_IDX].x0 = + val_pfdi_force_error(PFDI_FN_PFDI_FW_CHECK, PFDI_ACS_NOT_SUPPORTED, + &err[PFDI_FN_FW_CHECK_IDX].x1, &err[PFDI_FN_FW_CHECK_IDX].x2, + &err[PFDI_FN_FW_CHECK_IDX].x3, &err[PFDI_FN_FW_CHECK_IDX].x4); + val_pfdi_fw_check(NULL, NULL, NULL, NULL); + + /* PFDI_FORCE_ERROR force NOT_SUPPORTED */ + err[PFDI_FN_FORCE_ERROR_IDX].x0 = + val_pfdi_force_error(PFDI_FN_PFDI_FORCE_ERROR, PFDI_ACS_NOT_SUPPORTED, + &err[PFDI_FN_FORCE_ERROR_IDX].x1, &err[PFDI_FN_FORCE_ERROR_IDX].x2, + &err[PFDI_FN_FORCE_ERROR_IDX].x3, &err[PFDI_FN_FORCE_ERROR_IDX].x4); + val_pfdi_force_error(PFDI_FN_PFDI_VERSION, PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + + for (i = 0; i < PFDI_FN_MAX_IDX; i++) { + val_pfdi_invalidate_ret_params(&err[i]); } - /* ---- PFDI_FEATURES force NOT_SUPPORTED ---- */ - err->status[FEATURE_UNSUPP] = val_pfdi_force_error(PFDI_FN_PFDI_FEATURES, - PFDI_ACS_NOT_SUPPORTED, &err->x1[FEATURE_UNSUPP], &err->x2[FEATURE_UNSUPP], - &err->x3[FEATURE_UNSUPP], &err->x4[FEATURE_UNSUPP]); - if (err->status[FEATURE_UNSUPP] == PFDI_ACS_SUCCESS) { - fun->status[FEATURE_UNSUPP] = val_pfdi_features(PFDI_FN_PFDI_VERSION, NULL, NULL, NULL, NULL); - } + val_set_status(index, RESULT_PASS(test_num, 1)); + return; +} - /* ---- PE_TEST_ID force UNKNOWN ---- */ - err->status[TESTID_UNKNOWN] = val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_ID, PFDI_ACS_UNKNOWN, - &err->x1[TESTID_UNKNOWN], &err->x2[TESTID_UNKNOWN], - &err->x3[TESTID_UNKNOWN], &err->x4[TESTID_UNKNOWN]); - if (err->status[TESTID_UNKNOWN] == PFDI_ACS_SUCCESS) { - fun->status[TESTID_UNKNOWN] = val_pfdi_pe_test_id(NULL, NULL, NULL, NULL); +static void pfdi_error_recovery(void) +{ + uint32_t i, index = val_pe_get_index_mpid(val_pe_get_mpid()); + pfdi_err_recovery_check *rec_buffer; + PFDI_RET_PARAMS *rec; + + rec_buffer = g_pfdi_err_recovery_check + index; + rec = rec_buffer->rec_status; + + /* PFDI_VERSION should behave normally after forced error */ + rec_buffer->force_err_status[PFDI_FN_VERSION_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_VERSION, PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + if (rec_buffer->force_err_status[PFDI_FN_VERSION_IDX] == PFDI_ACS_SUCCESS) { + /* Error should remain pending until PFDI_VERSION is called */ + rec_buffer->alt_status[PFDI_FN_VERSION_IDX] = + val_pfdi_features(PFDI_FN_PFDI_VERSION, NULL, NULL, NULL, NULL); + rec[PFDI_FN_VERSION_IDX].x0 = val_pfdi_version(&rec[PFDI_FN_VERSION_IDX].x1, + &rec[PFDI_FN_VERSION_IDX].x2, &rec[PFDI_FN_VERSION_IDX].x3, &rec[PFDI_FN_VERSION_IDX].x4); + /* Normal behaviour of PFDI_VERSION function after injected error */ + rec_buffer->norm_mode_status[PFDI_FN_VERSION_IDX] = val_pfdi_version(NULL, NULL, NULL, NULL); } - /* ---- TEST_PART_COUNT force NOT_SUPPORTED ---- */ - err->status[TESTPART_UNSUPP] = val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_PART_COUNT, - PFDI_ACS_NOT_SUPPORTED, &err->x1[TESTPART_UNSUPP], &err->x2[TESTPART_UNSUPP], - &err->x3[TESTPART_UNSUPP], &err->x4[TESTPART_UNSUPP]); - if (err->status[TESTPART_UNSUPP] == PFDI_ACS_SUCCESS) { - fun->status[TESTPART_UNSUPP] = val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); + /* PFDI_FEATURES should behave normally after forced error */ + rec_buffer->force_err_status[PFDI_FN_FEATURES_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_FEATURES, PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + if (rec_buffer->force_err_status[PFDI_FN_FEATURES_IDX] == PFDI_ACS_SUCCESS) { + /* Error should remain pending until PFDI_FEATURES is called */ + rec_buffer->alt_status[PFDI_FN_FEATURES_IDX] = val_pfdi_version(NULL, NULL, NULL, NULL); + rec[PFDI_FN_FEATURES_IDX].x0 = val_pfdi_features(PFDI_FN_PFDI_VERSION, + &rec[PFDI_FN_FEATURES_IDX].x1, &rec[PFDI_FN_FEATURES_IDX].x2, + &rec[PFDI_FN_FEATURES_IDX].x3, &rec[PFDI_FN_FEATURES_IDX].x4); + /* Normal behaviour of PFDI_FEATURES function after injected error */ + rec_buffer->norm_mode_status[PFDI_FN_FEATURES_IDX] = + val_pfdi_features(PFDI_FN_PFDI_VERSION, NULL, NULL, NULL, NULL); } - /* ---- TEST_RUN force FAULT_FOUND ---- */ - err->status[TESTRUN_FAULT] = val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RUN, PFDI_ACS_FAULT_FOUND, - &err->x1[TESTRUN_FAULT], &err->x2[TESTRUN_FAULT], - &err->x3[TESTRUN_FAULT], &err->x4[TESTRUN_FAULT]); - if (err->status[TESTRUN_FAULT] == PFDI_ACS_SUCCESS) { - fun->status[TESTRUN_FAULT] = val_pfdi_pe_test_run(-1, -1, NULL, NULL, NULL, NULL); + /* PE_TEST_ID should behave normally after forced error */ + rec_buffer->force_err_status[PFDI_FN_PE_TEST_ID_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_ID, PFDI_ACS_UNKNOWN, + NULL, NULL, NULL, NULL); + if (rec_buffer->force_err_status[PFDI_FN_PE_TEST_ID_IDX] == PFDI_ACS_SUCCESS) { + /* Error should remain pending until PFDI_PE_TEST_ID is called */ + rec_buffer->alt_status[PFDI_FN_PE_TEST_ID_IDX] = val_pfdi_version(NULL, NULL, NULL, NULL); + rec[PFDI_FN_PE_TEST_ID_IDX].x0 = + val_pfdi_pe_test_id(&rec[PFDI_FN_PE_TEST_ID_IDX].x1, &rec[PFDI_FN_PE_TEST_ID_IDX].x2, + &rec[PFDI_FN_PE_TEST_ID_IDX].x3, &rec[PFDI_FN_PE_TEST_ID_IDX].x4); + /* Normal behaviour of PFDI_PE_TEST_ID function after injected error */ + rec_buffer->norm_mode_status[PFDI_FN_PE_TEST_ID_IDX] = + val_pfdi_pe_test_id(NULL, NULL, NULL, NULL); } - /* ---- TEST_RESULT force ERROR ---- */ - err->status[RESULT_ERROR] = val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RESULT, PFDI_ACS_ERROR, - &err->x1[RESULT_ERROR], &err->x2[RESULT_ERROR], - &err->x3[RESULT_ERROR], &err->x4[RESULT_ERROR]); - if (err->status[RESULT_ERROR] == PFDI_ACS_SUCCESS) { - fun->status[RESULT_ERROR] = val_pfdi_pe_test_result(NULL, NULL, NULL, NULL); + /* PE_TEST_PART_COUNT should behave normally after forced error */ + rec_buffer->force_err_status[PFDI_FN_PE_TEST_PART_COUNT_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_PART_COUNT, PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + if (rec_buffer->force_err_status[PFDI_FN_PE_TEST_PART_COUNT_IDX] == PFDI_ACS_SUCCESS) { + /* Error should remain pending until PFDI_PE_TEST_PART_COUNT is called */ + rec_buffer->alt_status[PFDI_FN_PE_TEST_PART_COUNT_IDX] = + val_pfdi_version(NULL, NULL, NULL, NULL); + rec[PFDI_FN_PE_TEST_PART_COUNT_IDX].x0 = + val_pfdi_pe_test_part_count(&rec[PFDI_FN_PE_TEST_PART_COUNT_IDX].x1, + &rec[PFDI_FN_PE_TEST_PART_COUNT_IDX].x2, &rec[PFDI_FN_PE_TEST_PART_COUNT_IDX].x3, + &rec[PFDI_FN_PE_TEST_PART_COUNT_IDX].x4); + /* Normal behaviour of PFDI_PE_TEST_PART_COUNT function after injected error */ + rec_buffer->norm_mode_status[PFDI_FN_PE_TEST_PART_COUNT_IDX] = + val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); } - /* ---- FW_CHECK force NOT_SUPPORTED ---- */ - err->status[FWCHECK_UNSUPP] = val_pfdi_force_error(PFDI_FN_PFDI_FW_CHECK, - PFDI_ACS_NOT_SUPPORTED, &err->x1[FWCHECK_UNSUPP], &err->x2[FWCHECK_UNSUPP], - &err->x3[FWCHECK_UNSUPP], &err->x4[FWCHECK_UNSUPP]); - if (err->status[FWCHECK_UNSUPP] == PFDI_ACS_SUCCESS) { - fun->status[FWCHECK_UNSUPP] = val_pfdi_fw_check(NULL, NULL, NULL, NULL); + /* PE_TEST_RUN should behave normally after forced error */ + rec_buffer->force_err_status[PFDI_FN_PE_TEST_RUN_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RUN, PFDI_ACS_FAULT_FOUND, + NULL, NULL, NULL, NULL); + if (rec_buffer->force_err_status[PFDI_FN_PE_TEST_RUN_IDX] == PFDI_ACS_SUCCESS) { + /* Error should remain pending until PFDI_PE_TEST_RUN is called */ + rec_buffer->alt_status[PFDI_FN_PE_TEST_RUN_IDX] = val_pfdi_version(NULL, NULL, NULL, NULL); + rec[PFDI_FN_PE_TEST_RUN_IDX].x0 = + val_pfdi_pe_test_run(PFDI_RUN_ALL_TEST_PARTS, PFDI_RUN_ALL_TEST_PARTS, + &rec[PFDI_FN_PE_TEST_RUN_IDX].x1, &rec[PFDI_FN_PE_TEST_RUN_IDX].x2, + &rec[PFDI_FN_PE_TEST_RUN_IDX].x3, &rec[PFDI_FN_PE_TEST_RUN_IDX].x4); + /* Normal behaviour of PFDI_PE_TEST_RUN function after injected error */ + rec_buffer->norm_mode_status[PFDI_FN_PE_TEST_RUN_IDX] = + val_pfdi_pe_test_run(PFDI_RUN_ALL_TEST_PARTS, PFDI_RUN_ALL_TEST_PARTS, + NULL, NULL, NULL, NULL); } - for (i = 0; i < STATUS_COUNT; i++) { - val_data_cache_ops_by_va((addr_t)&err->status[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&err->x1[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&err->x2[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&err->x3[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&err->x4[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&fun->status[i], CLEAN_AND_INVALIDATE); + /* PE_TEST_RESULT should behave normally after forced error */ + rec_buffer->force_err_status[PFDI_FN_PE_TEST_RESULT_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RESULT, PFDI_ACS_ERROR, + NULL, NULL, NULL, NULL); + if (rec_buffer->force_err_status[PFDI_FN_PE_TEST_RESULT_IDX] == PFDI_ACS_SUCCESS) { + /* Error should remain pending until PFDI_PE_TEST_RESULT is called */ + rec_buffer->alt_status[PFDI_FN_PE_TEST_RESULT_IDX] = val_pfdi_version(NULL, NULL, NULL, NULL); + rec[PFDI_FN_PE_TEST_RESULT_IDX].x0 = + val_pfdi_pe_test_result(&rec[PFDI_FN_PE_TEST_RESULT_IDX].x1, + &rec[PFDI_FN_PE_TEST_RESULT_IDX].x2, &rec[PFDI_FN_PE_TEST_RESULT_IDX].x3, + &rec[PFDI_FN_PE_TEST_RESULT_IDX].x4); + /* Normal behaviour of PFDI_PE_TEST_RESULT function after injected error */ + rec_buffer->norm_mode_status[PFDI_FN_PE_TEST_RESULT_IDX] = + val_pfdi_pe_test_result(NULL, NULL, NULL, NULL); } - val_data_cache_ops_by_va((addr_t)&g_pfdi_set_status, CLEAN_AND_INVALIDATE); - if (g_pfdi_set_status) - val_set_status(index, RESULT_PASS(test_num, 1)); - - return; -} - -static void pfdi_error_recovery(void) -{ - uint32_t i, index = val_pe_get_index_mpid(val_pe_get_mpid()); - pfdi_force_error_check *error_buffer; - pfdi_err_recovery_check *recovery_buffer; - - error_buffer = g_pfdi_force_error_check + index; - recovery_buffer = g_pfdi_err_recovery_check + index; - - /* Invoke PFDI Force Error Injection for current PE index */ - pfdi_error_injection(); - - for (i = 0; i < STATUS_COUNT; i++) { - val_data_cache_ops_by_va((addr_t)&error_buffer->force_err.status[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&error_buffer->pfdi_func.status[i], CLEAN_AND_INVALIDATE); + /* FW_CHECK should behave normally after forced error */ + rec_buffer->force_err_status[PFDI_FN_FW_CHECK_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_FW_CHECK, PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + if (rec_buffer->force_err_status[PFDI_FN_FW_CHECK_IDX] == PFDI_ACS_SUCCESS) { + /* Error should remain pending until PFDI_FW_CHECK is called */ + rec_buffer->alt_status[PFDI_FN_FW_CHECK_IDX] = val_pfdi_version(NULL, NULL, NULL, NULL); + rec[PFDI_FN_FW_CHECK_IDX].x0 = + val_pfdi_fw_check(&rec[PFDI_FN_FW_CHECK_IDX].x1, &rec[PFDI_FN_FW_CHECK_IDX].x2, + &rec[PFDI_FN_FW_CHECK_IDX].x3, &rec[PFDI_FN_FW_CHECK_IDX].x4); + /* Normal behaviour of PFDI_FW_CHECK function after injected error */ + rec_buffer->norm_mode_status[PFDI_FN_FW_CHECK_IDX] = + val_pfdi_fw_check(NULL, NULL, NULL, NULL); } - /* ---- PFDI_VERSION should behave normally after forced error ---- */ - if (error_buffer->pfdi_func.status[VERSION_UNSUPP] == fail_status[VERSION_UNSUPP]) - recovery_buffer->status[VERSION_UNSUPP] = val_pfdi_version(NULL, NULL, NULL, NULL); - - /* ---- PFDI_FEATURES should behave normally after forced error ---- */ - if (error_buffer->pfdi_func.status[FEATURE_UNSUPP] == fail_status[FEATURE_UNSUPP]) - recovery_buffer->status[FEATURE_UNSUPP] = val_pfdi_features(PFDI_FN_PFDI_VERSION, - NULL, NULL, NULL, NULL); - - /* ---- PE_TEST_ID should behave normally after forced error ---- */ - if (error_buffer->pfdi_func.status[TESTID_UNKNOWN] == fail_status[TESTID_UNKNOWN]) - recovery_buffer->status[TESTID_UNKNOWN] = val_pfdi_pe_test_id(NULL, NULL, NULL, NULL); - - /* ---- PE_TEST_PART_COUNT should behave normally after forced error ---- */ - if (error_buffer->pfdi_func.status[TESTPART_UNSUPP] == fail_status[TESTPART_UNSUPP]) - recovery_buffer->status[TESTPART_UNSUPP] = val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); - - /* ---- PE_TEST_RUN should behave normally after forced error ---- */ - if (error_buffer->pfdi_func.status[TESTRUN_FAULT] == fail_status[TESTRUN_FAULT]) - recovery_buffer->status[TESTRUN_FAULT] = val_pfdi_pe_test_run(-1, -1, NULL, NULL, NULL, NULL); - - /* ---- PE_TEST_RESULT should behave normally after forced error ---- */ - if (error_buffer->pfdi_func.status[RESULT_ERROR] == fail_status[RESULT_ERROR]) - recovery_buffer->status[RESULT_ERROR] = val_pfdi_pe_test_result(NULL, NULL, NULL, NULL); - - /* ---- FW_CHECK should behave normally after forced error ---- */ - if (error_buffer->pfdi_func.status[FWCHECK_UNSUPP] == fail_status[FWCHECK_UNSUPP]) - recovery_buffer->status[FWCHECK_UNSUPP] = val_pfdi_fw_check(NULL, NULL, NULL, NULL); + /* FORCE_ERROR should behave normally after forced error */ + rec_buffer->force_err_status[PFDI_FN_FORCE_ERROR_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_FORCE_ERROR, PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + if (rec_buffer->force_err_status[PFDI_FN_FORCE_ERROR_IDX] == PFDI_ACS_SUCCESS) { + /* Error should remain pending until PFDI_FORCE_ERROR is called */ + rec_buffer->alt_status[PFDI_FN_FORCE_ERROR_IDX] = val_pfdi_version(NULL, NULL, NULL, NULL); + rec[PFDI_FN_FORCE_ERROR_IDX].x0 = val_pfdi_force_error(PFDI_FN_PFDI_FORCE_ERROR, 0, + &rec[PFDI_FN_FORCE_ERROR_IDX].x1, &rec[PFDI_FN_FORCE_ERROR_IDX].x2, + &rec[PFDI_FN_FORCE_ERROR_IDX].x3, &rec[PFDI_FN_FORCE_ERROR_IDX].x4); + /* Normal behaviour of PFDI_FORCE_ERROR function after injected error */ + rec_buffer->norm_mode_status[PFDI_FN_FORCE_ERROR_IDX] = + val_pfdi_force_error(PFDI_FN_PFDI_FORCE_ERROR, 0, NULL, NULL, NULL, NULL); + } - for (i = 0; i < STATUS_COUNT; i++) { - val_data_cache_ops_by_va((addr_t)&recovery_buffer->status[i], CLEAN_AND_INVALIDATE); + for (i = 0; i < PFDI_FN_MAX_IDX; i++) { + val_data_cache_ops_by_va((addr_t)&rec_buffer->force_err_status[i], CLEAN_AND_INVALIDATE); + val_data_cache_ops_by_va((addr_t)&rec_buffer->alt_status[i], CLEAN_AND_INVALIDATE); + val_pfdi_invalidate_ret_params(&rec[i]); + val_data_cache_ops_by_va((addr_t)&rec_buffer->norm_mode_status[i], CLEAN_AND_INVALIDATE); } val_set_status(index, RESULT_PASS(test_num, 1)); @@ -224,32 +285,24 @@ static void pfdi_error_recovery(void) static void payload_pfdi_error_injection(void *arg) { uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t timeout, i = 0, j = 0, run_fail = 0; - pfdi_force_error_check *status_buffer; + uint32_t timeout = 0, i = 0, j = 0, run_fail = 0; + pfdi_force_error_check *pfdi_buffer; uint32_t num_pe = *(uint32_t *)arg; - g_pfdi_set_status = 1; - val_data_cache_ops_by_va((addr_t)&g_pfdi_set_status, CLEAN_AND_INVALIDATE); - /* Allocate memory to save all PFDI function status for all PE's */ g_pfdi_force_error_check = (pfdi_force_error_check *) val_memory_calloc(num_pe, sizeof(pfdi_force_error_check)); if (g_pfdi_force_error_check == NULL) { val_print(ACS_PRINT_ERR, - "\n Allocation for PFDI Invalid Function Check Failed", 0); + "\n Allocation for PFDI Force Error Check Failed", 0); val_set_status(index, RESULT_FAIL(test_num, 1)); return; } for (i = 0; i < num_pe; i++) { - status_buffer = g_pfdi_force_error_check + i; - for (j = 0; j < STATUS_COUNT; j++) { - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.status[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.x1[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.x2[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.x3[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.x4[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->pfdi_func.status[j], CLEAN_AND_INVALIDATE); + pfdi_buffer = g_pfdi_force_error_check + i; + for (j = 0; j < PFDI_FN_MAX_IDX; j++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->force_err[j]); } } @@ -275,42 +328,32 @@ static void payload_pfdi_error_injection(void *arg) /* Check return status of function for all PE's */ for (i = 0; i < num_pe; i++) { - status_buffer = g_pfdi_force_error_check + i; + pfdi_buffer = g_pfdi_force_error_check + i; run_fail = 0; - for (j = 0; j < STATUS_COUNT; j++) { - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.status[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.x1[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.x2[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.x3[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->force_err.x4[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&status_buffer->pfdi_func.status[j], CLEAN_AND_INVALIDATE); + for (j = 0; j < PFDI_FN_MAX_IDX; j++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->force_err[j]); - if (status_buffer->force_err.status[j] == PFDI_ACS_ERROR) { + if (pfdi_buffer->force_err[j].x0 == PFDI_ACS_ERROR) { val_print(ACS_PRINT_ERR, "\n PFDI Force Error can not be scheduled for %a", (uint64_t)pfdi_test_names[j]); - val_print(ACS_PRINT_ERR, " status %ld", status_buffer->force_err.status[j]); + val_print(ACS_PRINT_ERR, " status %ld", pfdi_buffer->force_err[j].x0); val_print(ACS_PRINT_ERR, " on PE index %d", i); - } else if (status_buffer->force_err.status[j] != PFDI_ACS_SUCCESS) { + } else if (pfdi_buffer->force_err[j].x0 != PFDI_ACS_SUCCESS) { val_print(ACS_PRINT_ERR, "\n PFDI Force Error failed for %a", (uint64_t)pfdi_test_names[j]); - val_print(ACS_PRINT_ERR, " err %ld", status_buffer->force_err.status[j]); - val_print(ACS_PRINT_ERR, " on PE index %d", i); - run_fail++; - } else if (status_buffer->pfdi_func.status[j] != fail_status[j]) { - val_print(ACS_PRINT_ERR, "\n PFDI return %a", (uint64_t)pfdi_test_names[j]); - val_print(ACS_PRINT_ERR, " check failed err %ld", status_buffer->pfdi_func.status[j]); + val_print(ACS_PRINT_ERR, " err %ld", pfdi_buffer->force_err[j].x0); val_print(ACS_PRINT_ERR, " on PE index %d", i); run_fail++; } - if ((status_buffer->force_err.x1[j] != 0) || (status_buffer->force_err.x2[j] != 0) || - (status_buffer->force_err.x3[j] != 0) || (status_buffer->force_err.x4[j] != 0)) { + if ((pfdi_buffer->force_err[j].x1 != 0) || (pfdi_buffer->force_err[j].x2 != 0) || + (pfdi_buffer->force_err[j].x3 != 0) || (pfdi_buffer->force_err[j].x4 != 0)) { val_print(ACS_PRINT_ERR, "\n Registers X1-X4 are not zero:", 0); - val_print(ACS_PRINT_ERR, " x1=0x%llx", status_buffer->force_err.x1[j]); - val_print(ACS_PRINT_ERR, " x2=0x%llx", status_buffer->force_err.x2[j]); - val_print(ACS_PRINT_ERR, " x3=0x%llx", status_buffer->force_err.x3[j]); - val_print(ACS_PRINT_ERR, " x4=0x%llx", status_buffer->force_err.x4[j]); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->force_err[j].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->force_err[j].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->force_err[j].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->force_err[j].x4); val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); val_print(ACS_PRINT_ERR, " for %a", (uint64_t)pfdi_test_names[j]); run_fail++; @@ -332,41 +375,27 @@ static void payload_pfdi_error_injection(void *arg) static void payload_pfdi_error_recovery_check(void *arg) { uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t timeout, i = 0, j = 0, run_fail = 0, run_skip = 0; - pfdi_force_error_check *error_buffer; - pfdi_err_recovery_check *recovery_buffer; + uint32_t timeout = 0, i = 0, j = 0, run_fail = 0, run_skip = 0; + pfdi_err_recovery_check *rec_buffer; uint32_t num_pe = *(uint32_t *)arg; - g_pfdi_set_status = 0; - val_data_cache_ops_by_va((addr_t)&g_pfdi_set_status, CLEAN_AND_INVALIDATE); - - /* Allocate memory to save Force Error status for all PE's */ - g_pfdi_force_error_check = (pfdi_force_error_check *) - val_memory_calloc(num_pe, sizeof(pfdi_force_error_check)); - if (g_pfdi_force_error_check == NULL) { - val_print(ACS_PRINT_ERR, - "\n Allocation for PFDI Invalid Function Check Failed", 0); - val_set_status(index, RESULT_FAIL(test_num, 1)); - return; - } - /* Allocate memory to save Error Recovery status for all PE's */ g_pfdi_err_recovery_check = (pfdi_err_recovery_check *) val_memory_calloc(num_pe, sizeof(pfdi_err_recovery_check)); if (g_pfdi_err_recovery_check == NULL) { val_print(ACS_PRINT_ERR, - "\n Allocation for PFDI Invalid Function Check Failed", 0); + "\n Allocation for PFDI Error Recovery Check Failed", 0); val_set_status(index, RESULT_FAIL(test_num, 2)); - goto free_pfdi_force_error; + return; } for (i = 0; i < num_pe; i++) { - error_buffer = g_pfdi_force_error_check + i; - recovery_buffer = g_pfdi_err_recovery_check + i; - for (j = 0; j < STATUS_COUNT; j++) { - val_data_cache_ops_by_va((addr_t)&error_buffer->force_err.status[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&error_buffer->pfdi_func.status[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&recovery_buffer->status[j], CLEAN_AND_INVALIDATE); + rec_buffer = g_pfdi_err_recovery_check + i; + for (j = 0; j < PFDI_FN_MAX_IDX; j++) { + val_data_cache_ops_by_va((addr_t)&rec_buffer->force_err_status[j], CLEAN_AND_INVALIDATE); + val_data_cache_ops_by_va((addr_t)&rec_buffer->alt_status[j], CLEAN_AND_INVALIDATE); + val_pfdi_invalidate_ret_params(&rec_buffer->rec_status[j]); + val_data_cache_ops_by_va((addr_t)&rec_buffer->norm_mode_status[j], CLEAN_AND_INVALIDATE); } } @@ -392,34 +421,58 @@ static void payload_pfdi_error_recovery_check(void *arg) /* Check return status of function for all PE's */ for (i = 0; i < num_pe; i++) { - error_buffer = g_pfdi_force_error_check + i; - recovery_buffer = g_pfdi_err_recovery_check + i; + rec_buffer = g_pfdi_err_recovery_check + i; run_fail = 0; run_skip = 0; - for (j = 0; j < STATUS_COUNT; j++) { - val_data_cache_ops_by_va((addr_t)&error_buffer->force_err.status[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&error_buffer->pfdi_func.status[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&recovery_buffer->status[j], CLEAN_AND_INVALIDATE); + for (j = 0; j < PFDI_FN_MAX_IDX; j++) { + val_data_cache_ops_by_va((addr_t)&rec_buffer->force_err_status[j], CLEAN_AND_INVALIDATE); + val_data_cache_ops_by_va((addr_t)&rec_buffer->alt_status[j], CLEAN_AND_INVALIDATE); + val_pfdi_invalidate_ret_params(&rec_buffer->rec_status[j]); + val_data_cache_ops_by_va((addr_t)&rec_buffer->norm_mode_status[j], CLEAN_AND_INVALIDATE); - if (error_buffer->force_err.status[j] != PFDI_ACS_SUCCESS) { + if (rec_buffer->force_err_status[j] != PFDI_ACS_SUCCESS) { val_print(ACS_PRINT_ERR, "\n PFDI Force Error failed for %a", (uint64_t)pfdi_test_names[j]); - val_print(ACS_PRINT_ERR, " err %ld", error_buffer->force_err.status[j]); + val_print(ACS_PRINT_ERR, " err %ld", rec_buffer->force_err_status[j]); val_print(ACS_PRINT_ERR, " on PE index %d, Skipping the test", i); run_skip++; - } else if (error_buffer->pfdi_func.status[j] != fail_status[j]) { + } + + if (rec_buffer->alt_status[j] == fail_status[j]) { + val_print(ACS_PRINT_ERR, + "\n PFDI Scheduled error affected unrelated function, return status %ld", + rec_buffer->alt_status[j]); + run_fail++; + } + + if (rec_buffer->rec_status[j].x0 != fail_status[j]) { val_print(ACS_PRINT_ERR, "\n PFDI return %a", (uint64_t)pfdi_test_names[j]); - val_print(ACS_PRINT_ERR, " check failed err %ld", error_buffer->pfdi_func.status[j]); - val_print(ACS_PRINT_ERR, " on PE index %d, Skipping the test", i); - run_skip++; - } else if (recovery_buffer->status[j] < PFDI_ACS_SUCCESS) { - val_print(ACS_PRINT_ERR, "\n PFDI Error Recovery for %a", + val_print(ACS_PRINT_ERR, " check failed err %ld", rec_buffer->rec_status[j].x0); + val_print(ACS_PRINT_ERR, " on PE index %d", i); + run_fail++; + } + + if (rec_buffer->norm_mode_status[j] == fail_status[j]) { + val_print(ACS_PRINT_ERR, "\n PFDI Error recovery failed for %a", (uint64_t)pfdi_test_names[j]); - val_print(ACS_PRINT_ERR, " failed err %ld", recovery_buffer->status[j]); + val_print(ACS_PRINT_ERR, " failed err %ld", rec_buffer->norm_mode_status[j]); val_print(ACS_PRINT_ERR, " on PE index %d", i); run_fail++; } + + if ((rec_buffer->rec_status[j].x1 != 0) || (rec_buffer->rec_status[j].x2 != 0) || + (rec_buffer->rec_status[j].x3 != 0) || (rec_buffer->rec_status[j].x4 != 0)) { + val_print(ACS_PRINT_ERR, "\n Registers X1-X4 are not zero:", 0); + val_print(ACS_PRINT_ERR, " x1=0x%llx", rec_buffer->rec_status[j].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", rec_buffer->rec_status[j].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", rec_buffer->rec_status[j].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", rec_buffer->rec_status[j].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + val_print(ACS_PRINT_ERR, " for %a", (uint64_t)pfdi_test_names[j]); + run_fail++; + } + } if (run_fail) @@ -433,9 +486,6 @@ static void payload_pfdi_error_recovery_check(void *arg) free_pfdi_error_recovery: val_memory_free((void *) g_pfdi_err_recovery_check); g_pfdi_err_recovery_check = NULL; -free_pfdi_force_error: - val_memory_free((void *) g_pfdi_force_error_check); - g_pfdi_force_error_check = NULL; return; } diff --git a/test_pool/pfdi/pfdi013.c b/test_pool/pfdi/pfdi013.c index 364322c9..9c8ecc92 100644 --- a/test_pool/pfdi/pfdi013.c +++ b/test_pool/pfdi/pfdi013.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,146 +20,114 @@ #include "val/include/acs_memory.h" #define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 13) -#define TEST_RULE "R0076" -#define TEST_DESC "Execute all available Test Parts on PE " +#define TEST_RULE "R0164" +#define TEST_DESC "Check PE Run with Start exceeds End " -#define RUN_ALL_TEST_PARTS -1 - -PFDI_RET_PARAMS *g_pfdi_run_avail; +static PFDI_RET_PARAMS *g_pfdi_status; +/* Execute the invalid parameter scenario: start index > end index */ static void -pfdi_test_run(void) +check_pe_test_run_start_exceeds_end(void) { - uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - PFDI_RET_PARAMS *pfdi_buffer; + uint32_t index; + PFDI_RET_PARAMS *pfdi_buffer; - pfdi_buffer = g_pfdi_run_avail + index; + index = val_pe_get_index_mpid(val_pe_get_mpid()); + pfdi_buffer = g_pfdi_status + index; - /* Invoke PFDI Run function for current PE index */ - pfdi_buffer->x0 = val_pfdi_pe_test_run(RUN_ALL_TEST_PARTS, RUN_ALL_TEST_PARTS, - &pfdi_buffer->x1, &pfdi_buffer->x2, &pfdi_buffer->x3, &pfdi_buffer->x4); + /* Execute invalid start > end case */ + pfdi_buffer->x0 = val_pfdi_pe_test_run(1, 0, + &pfdi_buffer->x1, + &pfdi_buffer->x2, + &pfdi_buffer->x3, + &pfdi_buffer->x4); - val_pfdi_invalidate_ret_params(pfdi_buffer); + val_pfdi_invalidate_ret_params(pfdi_buffer); - val_set_status(index, RESULT_PASS(TEST_NUM, 1)); - return; + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); } -static void payload_run(void *arg) +/* Validate that PFDI_PE_TEST_RUN returns INVALID_PARAMETERS for start > end */ +static void +payload_check_pe_test_run_start_exceeds_end(void *arg) { - uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t timeout, i = 0, test_fail = 0, check_x1 = 0; - uint32_t num_pe = *(uint32_t *)arg; - PFDI_RET_PARAMS *pfdi_buffer; - - - /* Allocate memory to save all PFDI run status and fault id's for all PE's */ - g_pfdi_run_avail = - (PFDI_RET_PARAMS *) val_memory_calloc(num_pe, sizeof(PFDI_RET_PARAMS)); - if (g_pfdi_run_avail == NULL) { - val_print(ACS_PRINT_ERR, - "\n Allocation for PFDI Run Function Failed", 0); - val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); - return; - } - - for (i = 0; i < num_pe; i++) { - pfdi_buffer = g_pfdi_run_avail + i; - val_pfdi_invalidate_ret_params(pfdi_buffer); - } + uint32_t num_pe = *((uint32_t *)arg); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t i = 0, timeout, test_fail = 0; + PFDI_RET_PARAMS *pfdi_buffer; + + g_pfdi_status = (PFDI_RET_PARAMS *) + val_memory_calloc(num_pe, sizeof(PFDI_RET_PARAMS)); + if (g_pfdi_status == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Run Function Failed", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } - /* Invoke PFDI Run function for current PE index */ - pfdi_test_run(); + check_pe_test_run_start_exceeds_end(); - /* Execute pfdi_test_run function in All PE's */ - for (i = 0; i < num_pe; i++) { - if (i != index) { - timeout = TIMEOUT_LARGE; - val_execute_on_pe(i, pfdi_test_run, 0); + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, check_pe_test_run_start_exceeds_end, 0); - while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); - if (timeout == 0) { - val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); - val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); - goto free_pfdi_details; - } + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } } - } - val_time_delay_ms(ONE_MILLISECOND); - /* Check return status of function for all PE's */ - for (i = 0; i < num_pe; i++) { - pfdi_buffer = g_pfdi_run_avail + i; - val_pfdi_invalidate_ret_params(pfdi_buffer); - test_fail = 0; - check_x1 = 0; - - if (pfdi_buffer->x0 < PFDI_ACS_SUCCESS) { - if (pfdi_buffer->x0 == PFDI_ACS_FAULT_FOUND) { - if (pfdi_buffer->x1 == PFDI_ACS_UNKNOWN) { - val_print(ACS_PRINT_ERR, "\n Fault in PFDI test part on PE %d ", i); - val_print(ACS_PRINT_ERR, "cannot be identified", 0); - } else { - val_print(ACS_PRINT_ERR, "\n PFDI test part %lld ", pfdi_buffer->x1); - val_print(ACS_PRINT_ERR, "triggered the fault on PE %d", i); + val_time_delay_ms(ONE_MILLISECOND); + + /* Check return status of function for all PE's */ + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_status + i; + + val_pfdi_invalidate_ret_params(pfdi_buffer); + + test_fail = 0; + + if (pfdi_buffer->x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n Invalid parameter test failed on PE %d", i); + val_print(ACS_PRINT_ERR, " (expected -3, got %ld)", pfdi_buffer->x0); + test_fail++; } - } else if (pfdi_buffer->x0 == PFDI_ACS_ERROR) { - check_x1++; - val_print(ACS_PRINT_ERR, - "\n PFDI Test parts have executed but failed to complete on PE %d", i); - } else { - val_print(ACS_PRINT_ERR, - "\n PFDI PE Run function failed %lld ", pfdi_buffer->x0); - val_print(ACS_PRINT_ERR, "on PE %d", i); - test_fail++; - } - } else { - check_x1++; - } - if (check_x1) { - if (pfdi_buffer->x1 != 0) { - val_print(ACS_PRINT_ERR, "\n Register X1 is not zero:", 0); - val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->x1); - val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); - test_fail++; - } - } + if ((pfdi_buffer->x1 != 0) || (pfdi_buffer->x2 != 0) || + (pfdi_buffer->x3 != 0) || (pfdi_buffer->x4 != 0)) { + val_print(ACS_PRINT_ERR, "\n Registers X1-X4 are not zero:", 0); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } - if ((pfdi_buffer->x2 != 0) || (pfdi_buffer->x3 != 0) || (pfdi_buffer->x4 != 0)) { - val_print(ACS_PRINT_ERR, "\n Registers X2-X4 are not zero:", 0); - val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->x2); - val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->x3); - val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->x4); - val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); - test_fail++; + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); } - if (test_fail) - val_set_status(i, RESULT_FAIL(TEST_NUM, 4)); - else - val_set_status(i, RESULT_PASS(TEST_NUM, 1)); - } - free_pfdi_details: - val_memory_free((void *) g_pfdi_run_avail); - - return; + val_memory_free((void *)g_pfdi_status); } +/* Entry point for test PFDI013 */ uint32_t pfdi013_entry(uint32_t num_pe) { - uint32_t status = ACS_STATUS_FAIL; - - status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); - - if (status != ACS_STATUS_SKIP) - val_run_test_configurable_payload(&num_pe, payload_run); + uint32_t status; - /* get the result from all PE and check for failure */ - status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); - val_report_status(0, ACS_END(TEST_NUM), NULL); + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_check_pe_test_run_start_exceeds_end); - return status; + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + return status; } diff --git a/test_pool/pfdi/pfdi014.c b/test_pool/pfdi/pfdi014.c index 804ce59b..7ac50937 100644 --- a/test_pool/pfdi/pfdi014.c +++ b/test_pool/pfdi/pfdi014.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,188 +20,130 @@ #include "val/include/acs_memory.h" #define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 14) -#define TEST_RULE "R0076" -#define TEST_DESC "Check PFDI run with invalid parameters " +#define TEST_RULE "R0165" +#define TEST_DESC "Check PE Run with Start exceeds max " -/** Invalid parameter invalid_cases (test_cnt filled dynamically) */ -#define NUM_INVALID_CASES 7 - -/** local struct for this test */ -typedef struct { - int64_t status[NUM_INVALID_CASES]; - int64_t fault_id[NUM_INVALID_CASES]; - int64_t x2[NUM_INVALID_CASES]; - int64_t x3[NUM_INVALID_CASES]; - int64_t x4[NUM_INVALID_CASES]; -} pfdi_pe_test_support_info; - -static pfdi_pe_test_support_info *g_pe_test_support_info; +static PFDI_RET_PARAMS *g_pfdi_status; +/* Execute invalid parameter case where start index exceeds max supported index */ static void -run_invalid_param_case(void) +check_pe_test_run_start_beyond_max(void) { - uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t i; - int64_t invalid_cases[NUM_INVALID_CASES][2]; - int64_t test_parts; - pfdi_pe_test_support_info *pfdi_buffer; - - pfdi_buffer = g_pe_test_support_info + index; - - /* Get Num of Test parts supported on curr PE */ - test_parts = val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); - if (test_parts < PFDI_ACS_SUCCESS) { - val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); - return; - } - - if (test_parts == 0) - test_parts = test_parts + 1; - - /** Populate invalid_cases with invalid parameter scenarios */ - invalid_cases[0][0] = 1; invalid_cases[0][1] = 0; /** start > end */ - invalid_cases[1][0] = test_parts; invalid_cases[1][1] = test_parts - 1; /** start > test_cnt-1 */ - invalid_cases[2][0] = 0; invalid_cases[2][1] = test_parts; /** end > test_cnt - 1 */ - invalid_cases[3][0] = -1; invalid_cases[3][1] = 0; /** start = -1, end != -1 */ - invalid_cases[4][0] = 0; invalid_cases[4][1] = -1; /** end = -1, start != -1 */ - invalid_cases[5][0] = -2; invalid_cases[5][1] = test_parts - 1;/** start < -1 */ - invalid_cases[6][0] = 0; invalid_cases[6][1] = -2; /** end < -1 */ - - - for (i = 0; i < NUM_INVALID_CASES; ++i) { - pfdi_buffer->status[i] = val_pfdi_pe_test_run(invalid_cases[i][0], invalid_cases[i][1], - &pfdi_buffer->fault_id[i], &pfdi_buffer->x2[i], - &pfdi_buffer->x3[i], &pfdi_buffer->x4[i]); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->status[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->fault_id[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x2[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x3[i], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x4[i], CLEAN_AND_INVALIDATE); - } - - - val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + uint32_t index; + int64_t test_parts; + PFDI_RET_PARAMS *pfdi_buffer; + + index = val_pe_get_index_mpid(val_pe_get_mpid()); + pfdi_buffer = g_pfdi_status + index; + + /* Get number of test parts supported on current PE */ + test_parts = val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); + if (test_parts < PFDI_ACS_SUCCESS) { + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + if (test_parts == 0) + test_parts = 1; + + /* Invalid case: start > test_cnt - 1 */ + pfdi_buffer->x0 = val_pfdi_pe_test_run(test_parts, test_parts - 1, + &pfdi_buffer->x1, &pfdi_buffer->x2, + &pfdi_buffer->x3, &pfdi_buffer->x4); + + val_pfdi_invalidate_ret_params(pfdi_buffer); + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); } -/** --------------- payload that orchestrates all PEs ------------------ */ +/* Validate test case where start index is beyond max supported index */ static void -payload_run_invalid_param_check(void *arg) +payload_check_pe_test_run_start_beyond_max(void *arg) { - uint32_t num_pe = *((uint32_t *)arg); - uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t i = 0, j = 0, timeout, test_fail = 0; - pfdi_pe_test_support_info *pfdi_buffer; - - - /* Allocate memory to save all PFDI run status and fault id's for all PE's */ - g_pe_test_support_info = (pfdi_pe_test_support_info *) - val_memory_calloc(num_pe, sizeof(pfdi_pe_test_support_info)); - if (g_pe_test_support_info == NULL) { - val_print(ACS_PRINT_ERR, - "\n Allocation for PFDI Run Function Failed", 0); - val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); - return; - } - - for (i = 0; i < num_pe; i++) { - pfdi_buffer = g_pe_test_support_info + i; - for (j = 0; j < NUM_INVALID_CASES; j++) { - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->status[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->fault_id[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x2[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x3[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x4[j], CLEAN_AND_INVALIDATE); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t i = 0, timeout, test_fail = 0; + PFDI_RET_PARAMS *pfdi_buffer; + + g_pfdi_status = (PFDI_RET_PARAMS *) + val_memory_calloc(num_pe, sizeof(PFDI_RET_PARAMS)); + if (g_pfdi_status == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Run Function Failed", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; } - } - - run_invalid_param_case(); - for (i = 0; i < num_pe; i++) { - if (i != index) { - timeout = TIMEOUT_LARGE; - val_execute_on_pe(i, run_invalid_param_case, 0); + check_pe_test_run_start_beyond_max(); - /** Wait for result or timeout */ - while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, check_pe_test_run_start_beyond_max, 0); - if (timeout == 0) { - val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); - val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); - goto free_pfdi_details; - } - } - } - val_time_delay_ms(ONE_MILLISECOND); - - /* Check return status of function for all PE's */ - for (i = 0; i < num_pe; i++) { - pfdi_buffer = g_pe_test_support_info + i; - for (j = 0; j < NUM_INVALID_CASES; j++) { - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->status[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->fault_id[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x2[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x3[j], CLEAN_AND_INVALIDATE); - val_data_cache_ops_by_va((addr_t)&pfdi_buffer->x4[j], CLEAN_AND_INVALIDATE); - } - test_fail = 0; + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); - if (IS_TEST_FAIL(val_get_status(i))) { - val_print(ACS_PRINT_ERR, "\n Failed to get Test Part count on PE %d ", i); - val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); - goto free_pfdi_details; + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } } - for (j = 0; j < NUM_INVALID_CASES; j++) { - /* Check if status is invalid parameters and fault_id is 0 */ - if (pfdi_buffer->status[j] != PFDI_ACS_INVALID_PARAMETERS) { - val_print(ACS_PRINT_ERR, - "\n Invalid param test failed on PE: %d", i); - val_print(ACS_PRINT_ERR, " expected status -3, return status %ld", pfdi_buffer->status[j]); - val_print(ACS_PRINT_ERR, " for case %d", j); - test_fail++; - } - - if (pfdi_buffer->fault_id[j] != 0) { - val_print(ACS_PRINT_ERR, - "\n Fault ID check failed on PE: %d ", i); - val_print(ACS_PRINT_ERR, "expected fault 0, return fault %ld", pfdi_buffer->fault_id[j]); - val_print(ACS_PRINT_ERR, " for case %d", j); - test_fail++; - } - - if ((pfdi_buffer->x2[j] != 0) || (pfdi_buffer->x3[j] != 0) || (pfdi_buffer->x4[j] != 0)) { - val_print(ACS_PRINT_ERR, "\n Registers X2-X4 are not zero:", 0); - val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->x2[j]); - val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->x3[j]); - val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->x4[j]); - val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); - val_print(ACS_PRINT_ERR, " for case %d", j); - test_fail++; - } + val_time_delay_ms(ONE_MILLISECOND); + + /* Check return status of function for all PE's */ + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_status + i; + + val_pfdi_invalidate_ret_params(pfdi_buffer); + + test_fail = 0; + + if (IS_TEST_FAIL(val_get_status(i))) { + val_print(ACS_PRINT_ERR, "\n Failed to get Test Part count on PE %d", i); + val_set_status(i, RESULT_SKIP(TEST_NUM, 1)); + continue; + } + + /* Expected result: x0 = -3, x1-x4 = 0 */ + if (pfdi_buffer->x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n Invalid parameter response on PE %d", i); + val_print(ACS_PRINT_ERR, " (expected -3, got %ld)", pfdi_buffer->x0); + test_fail++; + } + + if ((pfdi_buffer->x1 != 0) || (pfdi_buffer->x2 != 0) || + (pfdi_buffer->x3 != 0) || (pfdi_buffer->x4 != 0)) { + val_print(ACS_PRINT_ERR, "\n Registers X1-X4 are not zero:", 0); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 4)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); } - if (test_fail) - val_set_status(i, RESULT_FAIL(TEST_NUM, 4)); - else - val_set_status(i, RESULT_PASS(TEST_NUM, 1)); - } - free_pfdi_details: - val_memory_free((void *) g_pe_test_support_info); - - return; + val_memory_free((void *)g_pfdi_status); } -/** ---------------- ACS entry point ---------------- */ +/* Entry point for test PFDI014 */ uint32_t pfdi014_entry(uint32_t num_pe) { - uint32_t status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + uint32_t status; - if (status != ACS_STATUS_SKIP) - val_run_test_configurable_payload(&num_pe, - payload_run_invalid_param_check); + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_check_pe_test_run_start_beyond_max); - status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); - val_report_status(0, ACS_END(TEST_NUM), NULL); - return status; + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + return status; } diff --git a/test_pool/pfdi/pfdi018.c b/test_pool/pfdi/pfdi018.c new file mode 100644 index 00000000..3238057d --- /dev/null +++ b/test_pool/pfdi/pfdi018.c @@ -0,0 +1,149 @@ +/** @file + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/val_interface.h" +#include "val/include/acs_memory.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 18) +#define TEST_RULE "R0166" +#define TEST_DESC "Check PE Run with End exceeds max index " + +static PFDI_RET_PARAMS *g_pfdi_status; + +/* Execute invalid parameter test case: end index beyond max index */ +static void +check_pe_test_run_end_beyond_max(void) +{ + uint32_t index; + int64_t test_parts; + PFDI_RET_PARAMS *pfdi_buffer; + + index = val_pe_get_index_mpid(val_pe_get_mpid()); + pfdi_buffer = g_pfdi_status + index; + + /* Get number of test parts supported on current PE */ + test_parts = val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); + if (test_parts < PFDI_ACS_SUCCESS) { + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + if (test_parts == 0) + test_parts = 1; + + /* Execute with end > test_cnt - 1 */ + pfdi_buffer->x0 = val_pfdi_pe_test_run(0, test_parts, + &pfdi_buffer->x1, &pfdi_buffer->x2, + &pfdi_buffer->x3, &pfdi_buffer->x4); + + val_pfdi_invalidate_ret_params(pfdi_buffer); + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); +} + +/* Validate that PFDI_PE_TEST_RUN returns INVALID_PARAMETERS for end > max index */ +static void +payload_check_pe_test_run_end_beyond_max(void *arg) +{ + uint32_t num_pe = *((uint32_t *)arg); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t i = 0, timeout, test_fail = 0; + PFDI_RET_PARAMS *pfdi_buffer; + + g_pfdi_status = (PFDI_RET_PARAMS *) + val_memory_calloc(num_pe, sizeof(PFDI_RET_PARAMS)); + if (g_pfdi_status == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Run Function Failed", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + check_pe_test_run_end_beyond_max(); + + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, check_pe_test_run_end_beyond_max, 0); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + val_time_delay_ms(ONE_MILLISECOND); + + /* Check return status of function for all PE's */ + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_status + i; + + val_pfdi_invalidate_ret_params(pfdi_buffer); + + test_fail = 0; + + if (IS_TEST_FAIL(val_get_status(i))) { + val_print(ACS_PRINT_ERR, "\n Failed to get Test Part count on PE %d", i); + val_set_status(i, RESULT_SKIP(TEST_NUM, 1)); + continue; + } + + /* Expected result: x0 = -3, x1-x4 = 0 */ + if (pfdi_buffer->x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n Invalid parameter test failed on PE %d", i); + val_print(ACS_PRINT_ERR, " (expected -3, got %ld)", pfdi_buffer->x0); + test_fail++; + } + + if ((pfdi_buffer->x1 != 0) || (pfdi_buffer->x2 != 0) || + (pfdi_buffer->x3 != 0) || (pfdi_buffer->x4 != 0)) { + val_print(ACS_PRINT_ERR, "\n Registers X1-X4 are not zero:", 0); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->x4); + val_print(ACS_PRINT_ERR, " on PE %d", i); + test_fail++; + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 4)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *)g_pfdi_status); +} + +/* Entry point for test PFDI018 */ +uint32_t pfdi018_entry(uint32_t num_pe) +{ + uint32_t status; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_check_pe_test_run_end_beyond_max); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + return status; +} diff --git a/test_pool/pfdi/pfdi019.c b/test_pool/pfdi/pfdi019.c new file mode 100644 index 00000000..4ddf0ffe --- /dev/null +++ b/test_pool/pfdi/pfdi019.c @@ -0,0 +1,148 @@ +/** @file + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/val_interface.h" +#include "val/include/acs_memory.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 19) +#define TEST_RULE "R0167" +#define TEST_DESC "Check PE Run with Start or End equals -1 " + +static PFDI_RET_PARAMS *g_pfdi_status; + +/* Execute invalid parameter cases: + * Case 0: Start = -1, End != -1 + * Case 1: Start != -1, End = -1 + */ +static void +check_pe_test_run_either_minus_one(void) +{ + uint32_t index; + PFDI_RET_PARAMS *pfdi_buffer_case0, *pfdi_buffer_case1; + + index = val_pe_get_index_mpid(val_pe_get_mpid()); + pfdi_buffer_case0 = g_pfdi_status + index; + pfdi_buffer_case1 = g_pfdi_status + val_pe_get_num() + index; + + /* Case 0: Start = -1, End != -1 */ + pfdi_buffer_case0->x0 = val_pfdi_pe_test_run(-1, 0, + &pfdi_buffer_case0->x1, &pfdi_buffer_case0->x2, + &pfdi_buffer_case0->x3, &pfdi_buffer_case0->x4); + val_pfdi_invalidate_ret_params(pfdi_buffer_case0); + + /* Case 1: Start != -1, End = -1 */ + pfdi_buffer_case1->x0 = val_pfdi_pe_test_run(0, -1, + &pfdi_buffer_case1->x1, &pfdi_buffer_case1->x2, + &pfdi_buffer_case1->x3, &pfdi_buffer_case1->x4); + val_pfdi_invalidate_ret_params(pfdi_buffer_case1); + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); +} + +/* Validate PFDI returns INVALID_PARAMETERS for start = -1 or end = -1 only */ +static void +payload_check_pe_test_run_either_minus_one(void *arg) +{ + uint32_t num_pe = *((uint32_t *)arg); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t i = 0, j = 0, timeout, test_fail = 0; + PFDI_RET_PARAMS *pfdi_buffer; + + /* Allocate memory for 2 cases * num_pe */ + g_pfdi_status = (PFDI_RET_PARAMS *) + val_memory_calloc(2 * num_pe, sizeof(PFDI_RET_PARAMS)); + if (g_pfdi_status == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Run Function Failed", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + check_pe_test_run_either_minus_one(); + + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, check_pe_test_run_either_minus_one, 0); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + val_time_delay_ms(ONE_MILLISECOND); + + /* Check return status of function for all PE's */ + for (i = 0; i < num_pe; i++) { + test_fail = 0; + + for (j = 0; j < 2; j++) { + pfdi_buffer = g_pfdi_status + (j * num_pe) + i; + val_pfdi_invalidate_ret_params(pfdi_buffer); + + if (pfdi_buffer->x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n Invalid param test failed on PE: %d", i); + val_print(ACS_PRINT_ERR, " when %a", + (uint64_t)(j == 0 ? "Start is -1 but End is not -1" : + "End is -1 but Start is not -1")); + val_print(ACS_PRINT_ERR, " (expected -3, got %ld)", pfdi_buffer->x0); + test_fail++; + } + + if ((pfdi_buffer->x1 != 0) || (pfdi_buffer->x2 != 0) || + (pfdi_buffer->x3 != 0) || (pfdi_buffer->x4 != 0)) { + val_print(ACS_PRINT_ERR, "\n Registers X1-X4 are not zero:", 0); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->x4); + val_print(ACS_PRINT_ERR, " on PE %d", i); + val_print(ACS_PRINT_ERR, " when %a", + (uint64_t)(j == 0 ? "Start is -1 but End is not -1" : + "End is -1 but Start is not -1")); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 4)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *)g_pfdi_status); +} + +/* Entry point for test PFDI019 */ +uint32_t pfdi019_entry(uint32_t num_pe) +{ + uint32_t status; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_check_pe_test_run_either_minus_one); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + return status; +} diff --git a/test_pool/pfdi/pfdi020.c b/test_pool/pfdi/pfdi020.c new file mode 100644 index 00000000..0a514899 --- /dev/null +++ b/test_pool/pfdi/pfdi020.c @@ -0,0 +1,166 @@ +/** @file + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/val_interface.h" +#include "val/include/acs_memory.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 20) +#define TEST_RULE "R0168" +#define TEST_DESC "Check PE Run with Start or End less -1 " + +static PFDI_RET_PARAMS *g_pfdi_status; + +/* Execute invalid parameter test cases: + * Case 0: Start < -1 + * Case 1: End < -1 + */ +static void +check_pe_test_run_less_than_minus_one(void) +{ + uint32_t index; + int64_t test_parts; + PFDI_RET_PARAMS *pfdi_buffer_case0, *pfdi_buffer_case1; + + index = val_pe_get_index_mpid(val_pe_get_mpid()); + pfdi_buffer_case0 = g_pfdi_status + index; + pfdi_buffer_case1 = g_pfdi_status + val_pe_get_num() + index; + + /* Query number of supported test parts */ + test_parts = val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); + if (test_parts < PFDI_ACS_SUCCESS) { + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + if (test_parts == 0) + test_parts = 1; + + /* Case 0: Start < -1 */ + pfdi_buffer_case0->x0 = val_pfdi_pe_test_run(-2, test_parts - 1, + &pfdi_buffer_case0->x1, &pfdi_buffer_case0->x2, + &pfdi_buffer_case0->x3, &pfdi_buffer_case0->x4); + val_pfdi_invalidate_ret_params(pfdi_buffer_case0); + + /* Case 1: End < -1 */ + pfdi_buffer_case1->x0 = val_pfdi_pe_test_run(0, -2, + &pfdi_buffer_case1->x1, &pfdi_buffer_case1->x2, + &pfdi_buffer_case1->x3, &pfdi_buffer_case1->x4); + val_pfdi_invalidate_ret_params(pfdi_buffer_case1); + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); +} + +/* Validate that PFDI_PE_TEST_RUN returns INVALID_PARAMETERS for < -1 inputs */ +static void +payload_check_pe_test_run_less_than_minus_one(void *arg) +{ + uint32_t num_pe = *((uint32_t *)arg); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t i = 0, j = 0, timeout, test_fail = 0; + PFDI_RET_PARAMS *pfdi_buffer; + + /* Allocate memory for 2 cases * num_pe */ + g_pfdi_status = (PFDI_RET_PARAMS *) + val_memory_calloc(2 * num_pe, sizeof(PFDI_RET_PARAMS)); + if (g_pfdi_status == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Run Function Failed", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + check_pe_test_run_less_than_minus_one(); + + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, check_pe_test_run_less_than_minus_one, 0); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + val_time_delay_ms(ONE_MILLISECOND); + + /* Check return status of function for all PE's */ + for (i = 0; i < num_pe; i++) { + test_fail = 0; + + if (IS_TEST_FAIL(val_get_status(i))) { + val_print(ACS_PRINT_ERR, "\n Failed to get Test Part count on PE %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + continue; + } + + /* Expected result: x0 = -3, x1-x4 = 0 */ + for (j = 0; j < 2; j++) { + pfdi_buffer = g_pfdi_status + (j * num_pe) + i; + val_pfdi_invalidate_ret_params(pfdi_buffer); + + if (pfdi_buffer->x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n Invalid param test failed on PE: %d", i); + val_print(ACS_PRINT_ERR, " when %a", + (uint64_t)(j == 0 ? "Start is less than -1" : + "End is less than -1")); + val_print(ACS_PRINT_ERR, " (expected -3, got %ld)", pfdi_buffer->x0); + test_fail++; + } + + if ((pfdi_buffer->x1 != 0) || (pfdi_buffer->x2 != 0) || + (pfdi_buffer->x3 != 0) || (pfdi_buffer->x4 != 0)) { + val_print(ACS_PRINT_ERR, "\n Registers X1-X4 are not zero:", 0); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->x4); + val_print(ACS_PRINT_ERR, " on PE %d", i); + val_print(ACS_PRINT_ERR, " when %a", + (uint64_t)(j == 0 ? "Start is less than -1" : + "End is less than -1")); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 4)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *)g_pfdi_status); +} + +/* Entry point for test PFDI020 */ +uint32_t pfdi020_entry(uint32_t num_pe) +{ + uint32_t status; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_check_pe_test_run_less_than_minus_one); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + return status; +} diff --git a/test_pool/pfdi/pfdi021.c b/test_pool/pfdi/pfdi021.c new file mode 100644 index 00000000..0886a96b --- /dev/null +++ b/test_pool/pfdi/pfdi021.c @@ -0,0 +1,174 @@ +/** @file + * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 21) +#define TEST_RULE "R0155" +#define TEST_DESC "PFDI version invalid params check " + +#define NUM_REGS_TO_CHECK 4 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_REGS_TO_CHECK]; +} PFDI_INVAL_RETURNS; + +PFDI_INVAL_RETURNS *g_pfdi_invalid_version; + +void +pfdi_invalid_version_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_invalid_version + index; + + /* Invoke PFDI Version function for current PE index with invalid x1 parameter*/ + pfdi_buffer->inval[0].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_VERSION, PFDI_INVALID_X_VALUE, 0, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[0].x1, (unsigned long *)&pfdi_buffer->inval[0].x2, + (unsigned long *)&pfdi_buffer->inval[0].x3, (unsigned long *)&pfdi_buffer->inval[0].x4); + + /* Invoke PFDI Version function for current PE index with invalid x2 parameter*/ + pfdi_buffer->inval[1].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_VERSION, 0, PFDI_INVALID_X_VALUE, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[1].x1, (unsigned long *)&pfdi_buffer->inval[1].x2, + (unsigned long *)&pfdi_buffer->inval[1].x3, (unsigned long *)&pfdi_buffer->inval[1].x4); + + /* Invoke PFDI Version function for current PE index with invalid x3 parameter*/ + pfdi_buffer->inval[2].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_VERSION, 0, 0, PFDI_INVALID_X_VALUE, 0, 0, + (unsigned long *)&pfdi_buffer->inval[2].x1, (unsigned long *)&pfdi_buffer->inval[2].x2, + (unsigned long *)&pfdi_buffer->inval[2].x3, (unsigned long *)&pfdi_buffer->inval[2].x4); + + /* Invoke PFDI Version function for current PE index with invalid x4 parameter*/ + pfdi_buffer->inval[3].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_VERSION, 0, 0, 0, PFDI_INVALID_X_VALUE, 0, + (unsigned long *)&pfdi_buffer->inval[3].x1, (unsigned long *)&pfdi_buffer->inval[3].x2, + (unsigned long *)&pfdi_buffer->inval[3].x3, (unsigned long *)&pfdi_buffer->inval[3].x4); + + for (i = 0; i < NUM_REGS_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + return; +} + +static void payload_invalid_pe_version_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI Versions or status for all PE's */ + g_pfdi_invalid_version = (PFDI_INVAL_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_RETURNS)); + if (g_pfdi_invalid_version == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid Version Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_version + i; + for (num_regs = 0; num_regs < NUM_REGS_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_invalid_version_check for current PE index */ + pfdi_invalid_version_check(); + + /* Execute pfdi_invalid_version_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_invalid_version_check, (uint64_t)g_pfdi_invalid_version); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_version + i; + test_fail = 0; + inval_case = 0; + + /* If X1-X4 are non-zero, X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_REGS_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, + "\n PFDI version with invalid x%d", inval_case + 1); + val_print(ACS_PRINT_ERR, " param failed %ld, ", pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for x%d invalid case:", inval_case + 1); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_invalid_version); + + return; +} + +uint32_t pfdi021_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_invalid_pe_version_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi022.c b/test_pool/pfdi/pfdi022.c new file mode 100644 index 00000000..82ee9ad7 --- /dev/null +++ b/test_pool/pfdi/pfdi022.c @@ -0,0 +1,167 @@ +/** @file + * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 22) +#define TEST_RULE "R0179" +#define TEST_DESC "PFDI Feature invalid params check " + +#define NUM_REGS_TO_CHECK 3 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_REGS_TO_CHECK]; +} PFDI_INVAL_RETURNS; + +PFDI_INVAL_RETURNS *g_pfdi_invalid_feature; + +void +pfdi_invalid_feature_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_invalid_feature + index; + + /* Invoke PFDI Feature function for current PE index with invalid x2 parameter*/ + pfdi_buffer->inval[0].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FEATURES, PFDI_FN_PFDI_FEATURES, PFDI_INVALID_X_VALUE, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[0].x1, (unsigned long *)&pfdi_buffer->inval[0].x2, + (unsigned long *)&pfdi_buffer->inval[0].x3, (unsigned long *)&pfdi_buffer->inval[0].x4); + + /* Invoke PFDI Feature function for current PE index with invalid x3 parameter*/ + pfdi_buffer->inval[1].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FEATURES, PFDI_FN_PFDI_FEATURES, 0, PFDI_INVALID_X_VALUE, 0, 0, + (unsigned long *)&pfdi_buffer->inval[1].x1, (unsigned long *)&pfdi_buffer->inval[1].x2, + (unsigned long *)&pfdi_buffer->inval[1].x3, (unsigned long *)&pfdi_buffer->inval[1].x4); + + /* Invoke PFDI Feature function for current PE index with invalid x4 parameter*/ + pfdi_buffer->inval[2].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FEATURES, PFDI_FN_PFDI_FEATURES, 0, 0, PFDI_INVALID_X_VALUE, 0, + (unsigned long *)&pfdi_buffer->inval[2].x1, (unsigned long *)&pfdi_buffer->inval[2].x2, + (unsigned long *)&pfdi_buffer->inval[2].x3, (unsigned long *)&pfdi_buffer->inval[2].x4); + + for (i = 0; i < NUM_REGS_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + return; +} + +static void payload_invalid_pe_feature_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI features or status for all PE's */ + g_pfdi_invalid_feature = (PFDI_INVAL_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_RETURNS)); + if (g_pfdi_invalid_feature == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid Feature Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_feature + i; + for (num_regs = 0; num_regs < NUM_REGS_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_invalid_feature_check for current PE index */ + pfdi_invalid_feature_check(); + + /* Execute pfdi_invalid_feature_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_invalid_feature_check, (uint64_t)g_pfdi_invalid_feature); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_feature + i; + test_fail = 0; + inval_case = 0; + + /* If X2-X4 are non-zero, X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_REGS_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n PFDI feature with invalid x%d", inval_case + 2); + val_print(ACS_PRINT_ERR, " param failed %ld ", pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for x%d invalid case:", inval_case + 2); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_invalid_feature); + + return; +} + +uint32_t pfdi022_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_invalid_pe_feature_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi023.c b/test_pool/pfdi/pfdi023.c new file mode 100644 index 00000000..3d8210ec --- /dev/null +++ b/test_pool/pfdi/pfdi023.c @@ -0,0 +1,174 @@ +/** @file + * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 23) +#define TEST_RULE "R0158" +#define TEST_DESC "PFDI PE Test ID invalid params check " + +#define NUM_REGS_TO_CHECK 4 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_REGS_TO_CHECK]; +} PFDI_INVAL_RETURNS; + +PFDI_INVAL_RETURNS *g_pfdi_invalid_pe_test_id; + +void +pfdi_invalid_pe_test_id_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_invalid_pe_test_id + index; + + /* Invoke PFDI PE Test ID function for current PE index with invalid x1 parameter*/ + pfdi_buffer->inval[0].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_ID, PFDI_INVALID_X_VALUE, 0, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[0].x1, (unsigned long *)&pfdi_buffer->inval[0].x2, + (unsigned long *)&pfdi_buffer->inval[0].x3, (unsigned long *)&pfdi_buffer->inval[0].x4); + + /* Invoke PFDI PE Test ID function for current PE index with invalid x2 parameter*/ + pfdi_buffer->inval[1].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_ID, 0, PFDI_INVALID_X_VALUE, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[1].x1, (unsigned long *)&pfdi_buffer->inval[1].x2, + (unsigned long *)&pfdi_buffer->inval[1].x3, (unsigned long *)&pfdi_buffer->inval[1].x4); + + /* Invoke PFDI PE Test ID function for current PE index with invalid x3 parameter*/ + pfdi_buffer->inval[2].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_ID, 0, 0, PFDI_INVALID_X_VALUE, 0, 0, + (unsigned long *)&pfdi_buffer->inval[2].x1, (unsigned long *)&pfdi_buffer->inval[2].x2, + (unsigned long *)&pfdi_buffer->inval[2].x3, (unsigned long *)&pfdi_buffer->inval[2].x4); + + /* Invoke PFDI PE Test ID function for current PE index with invalid x4 parameter*/ + pfdi_buffer->inval[3].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_ID, 0, 0, 0, PFDI_INVALID_X_VALUE, 0, + (unsigned long *)&pfdi_buffer->inval[3].x1, (unsigned long *)&pfdi_buffer->inval[3].x2, + (unsigned long *)&pfdi_buffer->inval[3].x3, (unsigned long *)&pfdi_buffer->inval[3].x4); + + for (i = 0; i < NUM_REGS_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + return; +} + +static void payload_invalid_pe_test_id_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI PE Test IDs or status for all PE's */ + g_pfdi_invalid_pe_test_id = (PFDI_INVAL_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_RETURNS)); + if (g_pfdi_invalid_pe_test_id == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid PE Test ID Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_pe_test_id + i; + for (num_regs = 0; num_regs < NUM_REGS_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_invalid_pe_test_id_check for current PE index */ + pfdi_invalid_pe_test_id_check(); + + /* Execute pfdi_invalid_pe_test_id_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_invalid_pe_test_id_check, (uint64_t)g_pfdi_invalid_pe_test_id); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_pe_test_id + i; + test_fail = 0; + inval_case = 0; + + /* If X1-X4 are non-zero, X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_REGS_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, + "\n PFDI PE Test ID with invalid x%d", inval_case + 1); + val_print(ACS_PRINT_ERR, " param failed %ld, ", pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for x%d invalid case:", inval_case + 1); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_invalid_pe_test_id); + + return; +} + +uint32_t pfdi023_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_invalid_pe_test_id_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi024.c b/test_pool/pfdi/pfdi024.c new file mode 100644 index 00000000..fd642803 --- /dev/null +++ b/test_pool/pfdi/pfdi024.c @@ -0,0 +1,174 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 24) +#define TEST_RULE "R0160" +#define TEST_DESC "PFDI Test Part Count invalid params check " + +#define NUM_REGS_TO_CHECK 4 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_REGS_TO_CHECK]; +} PFDI_INVAL_RETURNS; + +PFDI_INVAL_RETURNS *g_pfdi_invalid_test_part_count; + +void +pfdi_invalid_test_parts_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_invalid_test_part_count + index; + + /* Invoke PFDI Test Part Count function for current PE index with invalid x1 parameter*/ + pfdi_buffer->inval[0].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_PART_COUNT, PFDI_INVALID_X_VALUE, 0, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[0].x1, (unsigned long *)&pfdi_buffer->inval[0].x2, + (unsigned long *)&pfdi_buffer->inval[0].x3, (unsigned long *)&pfdi_buffer->inval[0].x4); + + /* Invoke PFDI Test Part Count function for current PE index with invalid x2 parameter*/ + pfdi_buffer->inval[1].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_PART_COUNT, 0, PFDI_INVALID_X_VALUE, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[1].x1, (unsigned long *)&pfdi_buffer->inval[1].x2, + (unsigned long *)&pfdi_buffer->inval[1].x3, (unsigned long *)&pfdi_buffer->inval[1].x4); + + /* Invoke PFDI Test Part Count function for current PE index with invalid x3 parameter*/ + pfdi_buffer->inval[2].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_PART_COUNT, 0, 0, PFDI_INVALID_X_VALUE, 0, 0, + (unsigned long *)&pfdi_buffer->inval[2].x1, (unsigned long *)&pfdi_buffer->inval[2].x2, + (unsigned long *)&pfdi_buffer->inval[2].x3, (unsigned long *)&pfdi_buffer->inval[2].x4); + + /* Invoke PFDI Test Part Count function for current PE index with invalid x4 parameter*/ + pfdi_buffer->inval[3].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_PART_COUNT, 0, 0, 0, PFDI_INVALID_X_VALUE, 0, + (unsigned long *)&pfdi_buffer->inval[3].x1, (unsigned long *)&pfdi_buffer->inval[3].x2, + (unsigned long *)&pfdi_buffer->inval[3].x3, (unsigned long *)&pfdi_buffer->inval[3].x4); + + for (i = 0; i < NUM_REGS_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + return; +} + +static void payload_invalid_pe_test_part_count_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI Test Part Counts or status for all PE's */ + g_pfdi_invalid_test_part_count = (PFDI_INVAL_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_RETURNS)); + if (g_pfdi_invalid_test_part_count == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid Test Part Count Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_test_part_count + i; + for (num_regs = 0; num_regs < NUM_REGS_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_invalid_test_parts_check for current PE index */ + pfdi_invalid_test_parts_check(); + + /* Execute pfdi_invalid_test_parts_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_invalid_test_parts_check, (uint64_t)g_pfdi_invalid_test_part_count); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_test_part_count + i; + test_fail = 0; + inval_case = 0; + + /* If X1-X4 are non-zero, X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_REGS_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, + "\n PFDI Test Part Count with invalid x%d", inval_case + 1); + val_print(ACS_PRINT_ERR, " param failed %ld, ", pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for x%d invalid case:", inval_case + 1); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_invalid_test_part_count); + + return; +} + +uint32_t pfdi024_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_invalid_pe_test_part_count_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi025.c b/test_pool/pfdi/pfdi025.c new file mode 100644 index 00000000..e5fe891d --- /dev/null +++ b/test_pool/pfdi/pfdi025.c @@ -0,0 +1,174 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 25) +#define TEST_RULE "R0172" +#define TEST_DESC "PFDI PE Test Result invalid params check " + +#define NUM_REGS_TO_CHECK 4 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_REGS_TO_CHECK]; +} PFDI_INVAL_RETURNS; + +PFDI_INVAL_RETURNS *g_pfdi_invalid_test_result; + +void +pfdi_invalid_test_result_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_invalid_test_result + index; + + /* Invoke PFDI Test Result function for current PE index with invalid x1 parameter*/ + pfdi_buffer->inval[0].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_RESULT, PFDI_INVALID_X_VALUE, 0, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[0].x1, (unsigned long *)&pfdi_buffer->inval[0].x2, + (unsigned long *)&pfdi_buffer->inval[0].x3, (unsigned long *)&pfdi_buffer->inval[0].x4); + + /* Invoke PFDI Test Result function for current PE index with invalid x2 parameter*/ + pfdi_buffer->inval[1].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_RESULT, 0, PFDI_INVALID_X_VALUE, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[1].x1, (unsigned long *)&pfdi_buffer->inval[1].x2, + (unsigned long *)&pfdi_buffer->inval[1].x3, (unsigned long *)&pfdi_buffer->inval[1].x4); + + /* Invoke PFDI Test Result function for current PE index with invalid x3 parameter*/ + pfdi_buffer->inval[2].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_RESULT, 0, 0, PFDI_INVALID_X_VALUE, 0, 0, + (unsigned long *)&pfdi_buffer->inval[2].x1, (unsigned long *)&pfdi_buffer->inval[2].x2, + (unsigned long *)&pfdi_buffer->inval[2].x3, (unsigned long *)&pfdi_buffer->inval[2].x4); + + /* Invoke PFDI Test Result function for current PE index with invalid x4 parameter*/ + pfdi_buffer->inval[3].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_RESULT, 0, 0, 0, PFDI_INVALID_X_VALUE, 0, + (unsigned long *)&pfdi_buffer->inval[3].x1, (unsigned long *)&pfdi_buffer->inval[3].x2, + (unsigned long *)&pfdi_buffer->inval[3].x3, (unsigned long *)&pfdi_buffer->inval[3].x4); + + for (i = 0; i < NUM_REGS_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + return; +} + +static void payload_invalid_pe_test_result_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI Test Results or status for all PE's */ + g_pfdi_invalid_test_result = (PFDI_INVAL_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_RETURNS)); + if (g_pfdi_invalid_test_result == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid Test Result Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_test_result + i; + for (num_regs = 0; num_regs < NUM_REGS_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_invalid_test_result_check for current PE index */ + pfdi_invalid_test_result_check(); + + /* Execute pfdi_invalid_test_result_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_invalid_test_result_check, (uint64_t)g_pfdi_invalid_test_result); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_test_result + i; + test_fail = 0; + inval_case = 0; + + /* If X1-X4 are non-zero, X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_REGS_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, + "\n PFDI test_result with invalid x%d", inval_case + 1); + val_print(ACS_PRINT_ERR, " param failed %ld, ", pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for x%d invalid case:", inval_case + 1); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_invalid_test_result); + + return; +} + +uint32_t pfdi025_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_invalid_pe_test_result_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi026.c b/test_pool/pfdi/pfdi026.c new file mode 100644 index 00000000..09caa0a6 --- /dev/null +++ b/test_pool/pfdi/pfdi026.c @@ -0,0 +1,174 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 26) +#define TEST_RULE "R0173" +#define TEST_DESC "PFDI Firmware Check invalid params " + +#define NUM_REGS_TO_CHECK 4 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_REGS_TO_CHECK]; +} PFDI_INVAL_RETURNS; + +PFDI_INVAL_RETURNS *g_pfdi_invalid_fw_check; + +void +pfdi_invalid_fw_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_invalid_fw_check + index; + + /* Invoke PFDI Firmware Check function for current PE index with invalid x1 parameter*/ + pfdi_buffer->inval[0].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FW_CHECK, PFDI_INVALID_X_VALUE, 0, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[0].x1, (unsigned long *)&pfdi_buffer->inval[0].x2, + (unsigned long *)&pfdi_buffer->inval[0].x3, (unsigned long *)&pfdi_buffer->inval[0].x4); + + /* Invoke PFDI Firmware Check function for current PE index with invalid x2 parameter*/ + pfdi_buffer->inval[1].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FW_CHECK, 0, PFDI_INVALID_X_VALUE, 0, 0, 0, + (unsigned long *)&pfdi_buffer->inval[1].x1, (unsigned long *)&pfdi_buffer->inval[1].x2, + (unsigned long *)&pfdi_buffer->inval[1].x3, (unsigned long *)&pfdi_buffer->inval[1].x4); + + /* Invoke PFDI Firmware Check function for current PE index with invalid x3 parameter*/ + pfdi_buffer->inval[2].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FW_CHECK, 0, 0, PFDI_INVALID_X_VALUE, 0, 0, + (unsigned long *)&pfdi_buffer->inval[2].x1, (unsigned long *)&pfdi_buffer->inval[2].x2, + (unsigned long *)&pfdi_buffer->inval[2].x3, (unsigned long *)&pfdi_buffer->inval[2].x4); + + /* Invoke PFDI Firmware Check function for current PE index with invalid x4 parameter*/ + pfdi_buffer->inval[3].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FW_CHECK, 0, 0, 0, PFDI_INVALID_X_VALUE, 0, + (unsigned long *)&pfdi_buffer->inval[3].x1, (unsigned long *)&pfdi_buffer->inval[3].x2, + (unsigned long *)&pfdi_buffer->inval[3].x3, (unsigned long *)&pfdi_buffer->inval[3].x4); + + for (i = 0; i < NUM_REGS_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + return; +} + +static void payload_invalid_pe_fw_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI Firmware Checks or status for all PE's */ + g_pfdi_invalid_fw_check = (PFDI_INVAL_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_RETURNS)); + if (g_pfdi_invalid_fw_check == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid Firmware Check Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_fw_check + i; + for (num_regs = 0; num_regs < NUM_REGS_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_invalid_fw_check for current PE index */ + pfdi_invalid_fw_check(); + + /* Execute pfdi_invalid_fw_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_invalid_fw_check, (uint64_t)g_pfdi_invalid_fw_check); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_fw_check + i; + test_fail = 0; + inval_case = 0; + + /* If X1-X4 are non-zero, X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_REGS_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, + "\n PFDI fw_check with invalid x%d", inval_case + 1); + val_print(ACS_PRINT_ERR, " param failed %ld, ", pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for x%d invalid case:", inval_case + 1); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_invalid_fw_check); + + return; +} + +uint32_t pfdi026_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_invalid_pe_fw_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi027.c b/test_pool/pfdi/pfdi027.c new file mode 100644 index 00000000..43eb7b64 --- /dev/null +++ b/test_pool/pfdi/pfdi027.c @@ -0,0 +1,260 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/val_interface.h" +#include "val/include/acs_memory.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 27) +#define TEST_RULE "R0193" +#define TEST_DESC "Check FORCE ERROR overwrite behavior " + +static const char *pfdi_fn_names[PFDI_FN_MAX_IDX] = { + [PFDI_FN_VERSION_IDX] = "PFDI_VERSION", + [PFDI_FN_FEATURES_IDX] = "PFDI_FEATURES", + [PFDI_FN_PE_TEST_ID_IDX] = "PFDI_PE_TEST_ID", + [PFDI_FN_PE_TEST_PART_COUNT_IDX] = "PFDI_PE_TEST_PART_COUNT", + [PFDI_FN_PE_TEST_RUN_IDX] = "PFDI_PE_TEST_RUN", + [PFDI_FN_PE_TEST_RESULT_IDX] = "PFDI_PE_TEST_RESULT", + [PFDI_FN_FW_CHECK_IDX] = "PFDI_FW_CHECK" +}; + + +typedef struct { + int64_t first_error_x0; + int64_t second_error_x0; + int64_t first_call_x0; +} pfdi_error_injection_results; + +static pfdi_error_injection_results *g_results; + +/* Test error injection overwrite on current PE */ +static void +check_error_overwrite(void) +{ + uint32_t index; + uint32_t num_pe; + pfdi_error_injection_results *result; + + index = val_pe_get_index_mpid(val_pe_get_mpid()); + num_pe = val_pe_get_num(); + + /* + * Test sequence (per PE, per function): + * Step 1: Inject error A using PFDI_FORCE_ERROR + * Step 2: Inject error B using PFDI_FORCE_ERROR (must overwrite A) + * Step 3: Call target function: must return error B + */ + + /* PFDI_VERSION */ + result = g_results + (PFDI_FN_VERSION_IDX * num_pe) + index; + result->first_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_VERSION, + PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + result->second_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_VERSION, + PFDI_ACS_INVALID_PARAMETERS, + NULL, NULL, NULL, NULL); + result->first_call_x0 = (int64_t)val_pfdi_version(NULL, NULL, NULL, NULL); + val_data_cache_ops_by_va((addr_t)result, CLEAN_AND_INVALIDATE); + + /* PFDI_FEATURES */ + result = g_results + (PFDI_FN_FEATURES_IDX * num_pe) + index; + result->first_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_FEATURES, + PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + result->second_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_FEATURES, + PFDI_ACS_INVALID_PARAMETERS, + NULL, NULL, NULL, NULL); + result->first_call_x0 = (int64_t)val_pfdi_features(PFDI_FN_PFDI_VERSION, + NULL, NULL, NULL, NULL); + val_data_cache_ops_by_va((addr_t)result, CLEAN_AND_INVALIDATE); + + /* PFDI_PE_TEST_ID */ + result = g_results + (PFDI_FN_PE_TEST_ID_IDX * num_pe) + index; + result->first_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_ID, + PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + result->second_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_ID, + PFDI_ACS_INVALID_PARAMETERS, + NULL, NULL, NULL, NULL); + result->first_call_x0 = (int64_t)val_pfdi_pe_test_id(NULL, NULL, NULL, NULL); + val_data_cache_ops_by_va((addr_t)result, CLEAN_AND_INVALIDATE); + + /* PFDI_PE_TEST_PART_COUNT */ + result = g_results + (PFDI_FN_PE_TEST_PART_COUNT_IDX * num_pe) + index; + result->first_error_x0 = (int64_t)val_pfdi_force_error( + PFDI_FN_PFDI_PE_TEST_PART_COUNT, PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + result->second_error_x0 = (int64_t)val_pfdi_force_error( + PFDI_FN_PFDI_PE_TEST_PART_COUNT, PFDI_ACS_INVALID_PARAMETERS, + NULL, NULL, NULL, NULL); + result->first_call_x0 = (int64_t)val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); + val_data_cache_ops_by_va((addr_t)result, CLEAN_AND_INVALIDATE); + + /* PFDI_PE_TEST_RUN */ + result = g_results + (PFDI_FN_PE_TEST_RUN_IDX * num_pe) + index; + result->first_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RUN, + PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + result->second_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RUN, + PFDI_ACS_INVALID_PARAMETERS, + NULL, NULL, NULL, NULL); + result->first_call_x0 = (int64_t)val_pfdi_pe_test_run(-1, -1, NULL, NULL, NULL, NULL); + val_data_cache_ops_by_va((addr_t)result, CLEAN_AND_INVALIDATE); + + /* PFDI_PE_TEST_RESULT */ + result = g_results + (PFDI_FN_PE_TEST_RESULT_IDX * num_pe) + index; + result->first_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RESULT, + PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + result->second_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_PE_TEST_RESULT, + PFDI_ACS_INVALID_PARAMETERS, + NULL, NULL, NULL, NULL); + result->first_call_x0 = (int64_t)val_pfdi_pe_test_result(NULL, NULL, NULL, NULL); + val_data_cache_ops_by_va((addr_t)result, CLEAN_AND_INVALIDATE); + + /* PFDI_FW_CHECK */ + result = g_results + (PFDI_FN_FW_CHECK_IDX * num_pe) + index; + result->first_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_FW_CHECK, + PFDI_ACS_NOT_SUPPORTED, + NULL, NULL, NULL, NULL); + result->second_error_x0 = (int64_t)val_pfdi_force_error(PFDI_FN_PFDI_FW_CHECK, + PFDI_ACS_INVALID_PARAMETERS, + NULL, NULL, NULL, NULL); + result->first_call_x0 = (int64_t)val_pfdi_fw_check(NULL, NULL, NULL, NULL); + val_data_cache_ops_by_va((addr_t)result, CLEAN_AND_INVALIDATE); + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); +} + +/* Validate error injection overwrite behavior across all PEs */ +static void +payload_check_error_overwrite(void *arg) +{ + uint32_t num_pe = *((uint32_t *)arg); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t i, j, timeout, test_fail, test_skip; + pfdi_error_injection_results *result; + + g_results = (pfdi_error_injection_results *) + val_memory_calloc(num_pe * PFDI_FN_MAX_IDX, sizeof(pfdi_error_injection_results)); + if (g_results == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for results Failed", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + /* Execute test on primary PE */ + check_error_overwrite(); + + /* Execute test on all other PEs */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, check_error_overwrite, 0); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_results; + } + } + } + + val_time_delay_ms(ONE_MILLISECOND); + + /* Validate results from all PEs and all functions */ + for (i = 0; i < num_pe; i++) { + test_fail = 0; + test_skip = 0; + + for (j = 0; j < PFDI_FN_FORCE_ERROR_IDX; j++) { + result = g_results + (j * num_pe) + i; + val_data_cache_ops_by_va((addr_t)result, INVALIDATE); + + /* Validate first FORCE_ERROR call status */ + if (result->first_error_x0 == PFDI_ACS_ERROR) { + val_print(ACS_PRINT_WARN, "\n FORCE_ERROR first %a error; skipping checks", + (uint64_t)pfdi_fn_names[j]); + val_print(ACS_PRINT_WARN, " on PE index %d", i); + test_skip++; + continue; + } + if (result->first_error_x0 != PFDI_ACS_SUCCESS) { + val_print(ACS_PRINT_ERR, "\n PFDI force_error %a ", (uint64_t)pfdi_fn_names[j]); + val_print(ACS_PRINT_ERR, "first injection failed err %ld ", + (int64_t)result->first_error_x0); + val_print(ACS_PRINT_ERR, "on PE index %d", i); + test_fail++; + } + + /* Validate second FORCE_ERROR call status */ + if (result->second_error_x0 == PFDI_ACS_ERROR) { + val_print(ACS_PRINT_WARN, "\n FORCE_ERROR second %a error; skipping checks", + (uint64_t)pfdi_fn_names[j]); + val_print(ACS_PRINT_WARN, " on PE index %d", i); + test_skip++; + continue; + } + if (result->second_error_x0 != PFDI_ACS_SUCCESS) { + val_print(ACS_PRINT_ERR, "\n PFDI force_error %a ", (uint64_t)pfdi_fn_names[j]); + val_print(ACS_PRINT_ERR, "second injection failed err %ld ", + (int64_t)result->second_error_x0); + val_print(ACS_PRINT_ERR, "on PE index %d", i); + test_fail++; + } + + /* Validate first call returns second injected error (overwrite behavior) */ + if (result->first_call_x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n PFDI return %a ", (uint64_t)pfdi_fn_names[j]); + val_print(ACS_PRINT_ERR, "overwrite check failed err %ld ", + (int64_t)result->first_call_x0); + val_print(ACS_PRINT_ERR, "expected %ld ", (int64_t)PFDI_ACS_INVALID_PARAMETERS); + val_print(ACS_PRINT_ERR, "on PE index %d", i); + if (result->first_call_x0 == PFDI_ACS_NOT_SUPPORTED) + val_print(ACS_PRINT_ERR, " (second error did not overwrite first)", 0); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else if (test_skip) + val_set_status(i, RESULT_SKIP(TEST_NUM, 1)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_results: + val_memory_free((void *)g_results); +} + +uint32_t +pfdi027_entry(uint32_t num_pe) +{ + uint32_t status; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_check_error_overwrite); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + return status; +} diff --git a/test_pool/pfdi/pfdi028.c b/test_pool/pfdi/pfdi028.c new file mode 100644 index 00000000..bef82617 --- /dev/null +++ b/test_pool/pfdi/pfdi028.c @@ -0,0 +1,273 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/val_interface.h" +#include "val/include/acs_memory.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 28) +#define TEST_RULE "R0194" +#define TEST_DESC "Check FORCE ERROR PE locality behavior " + +static const char *pfdi_fn_names[PFDI_FN_MAX_IDX] = { + [PFDI_FN_VERSION_IDX] = "PFDI_VERSION", + [PFDI_FN_FEATURES_IDX] = "PFDI_FEATURES", + [PFDI_FN_PE_TEST_ID_IDX] = "PFDI_PE_TEST_ID", + [PFDI_FN_PE_TEST_PART_COUNT_IDX] = "PFDI_PE_TEST_PART_COUNT", + [PFDI_FN_PE_TEST_RUN_IDX] = "PFDI_PE_TEST_RUN", + [PFDI_FN_PE_TEST_RESULT_IDX] = "PFDI_PE_TEST_RESULT", + [PFDI_FN_FW_CHECK_IDX] = "PFDI_FW_CHECK" +}; +#define PFDI_FN_TARGET_COUNT (PFDI_FN_FW_CHECK_IDX + 1U) + +/* Per-PE storage for scheduled and observed PFDI results */ +typedef struct { + int64_t x0[PFDI_FN_MAX_IDX]; +} pfdi_fun_status; + +typedef struct { + pfdi_fun_status force_err; + pfdi_fun_status cross_pe; + pfdi_fun_status same_pe_first; +} pfdi_pe_locality_check; + +/* Single buffer for PE-locality test results */ +static pfdi_pe_locality_check *g_pfdi_pe_locality_check; + +/* Clean+invalidate cache lines for all x0 entries in a status array */ +static void +cache_clean_pfdi_status(pfdi_fun_status *status) +{ + uint32_t i; + + for (i = 0; i < PFDI_FN_TARGET_COUNT; i++) + val_data_cache_ops_by_va((addr_t)&status->x0[i], CLEAN_AND_INVALIDATE); +} + +/* Call all PFDI functions and store x0 results */ +static void +call_all_pfdi_functions(pfdi_fun_status *out) +{ + out->x0[PFDI_FN_VERSION_IDX] = + val_pfdi_version(NULL, NULL, NULL, NULL); + + out->x0[PFDI_FN_FEATURES_IDX] = + val_pfdi_features(PFDI_FN_PFDI_VERSION, NULL, NULL, NULL, NULL); + + out->x0[PFDI_FN_PE_TEST_ID_IDX] = + val_pfdi_pe_test_id(NULL, NULL, NULL, NULL); + + out->x0[PFDI_FN_PE_TEST_PART_COUNT_IDX] = + val_pfdi_pe_test_part_count(NULL, NULL, NULL, NULL); + + out->x0[PFDI_FN_PE_TEST_RUN_IDX] = + val_pfdi_pe_test_run(-1, -1, NULL, NULL, NULL, NULL); + + out->x0[PFDI_FN_PE_TEST_RESULT_IDX] = + val_pfdi_pe_test_result(NULL, NULL, NULL, NULL); + + out->x0[PFDI_FN_FW_CHECK_IDX] = + val_pfdi_fw_check(NULL, NULL, NULL, NULL); + + cache_clean_pfdi_status(out); +} + +/* schedule injected errors on the calling PE */ +static void +inject_errors_on_calling_pe(void) +{ + pfdi_fun_status *err = &g_pfdi_pe_locality_check->force_err; + uint32_t fn_id; + uint32_t idx; + + /* Step 1: schedule an injected error per target function on the calling PE */ + for (fn_id = PFDI_FN_PFDI_VERSION; fn_id <= PFDI_FN_PFDI_FW_CHECK; fn_id++) { + idx = fn_id - PFDI_FN_PFDI_VERSION; + err->x0[idx] = val_pfdi_force_error( + fn_id, PFDI_ACS_UNKNOWN, + NULL, NULL, NULL, NULL); + + } + + /* Make injection results visible to other PEs */ + cache_clean_pfdi_status(err); +} + +/* Step 3 helper: call all target functions on the calling PE */ +static void +consume_errors_on_calling_pe(void) +{ + pfdi_fun_status *same_first = &g_pfdi_pe_locality_check->same_pe_first; + + /* Step 3: consume injected errors on the calling PE */ + call_all_pfdi_functions(same_first); + +} + +/* Step 2: Other PE calls all PFDI functions. + * Injected errors must NOT be visible on a different PE. + */ +static void +call_pfdi_functions_on_other_pe(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + pfdi_fun_status *cross_pe = &g_pfdi_pe_locality_check->cross_pe; + + call_all_pfdi_functions(cross_pe); + + val_set_status(index, RESULT_PASS(TEST_NUM, 2)); + return; +} + +static void +payload_check_pe_locality(void *arg) +{ + uint32_t num_pe = *((uint32_t *)arg); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t other_pe_index; + uint32_t timeout; + uint32_t i; + uint32_t idx; + uint32_t test_fail = 0; + uint32_t test_skip = 0; + pfdi_fun_status *err; + pfdi_fun_status *cross_pe; + pfdi_fun_status *same_first; + + if (num_pe < 2) { + val_print(ACS_PRINT_WARN, "\n Test requires minimum 2 PEs, skipping", 0); + val_set_status(index, RESULT_SKIP(TEST_NUM, 1)); + return; + } + + other_pe_index = (index == 0) ? 1 : 0; + + g_pfdi_pe_locality_check = (pfdi_pe_locality_check *) + val_memory_calloc(1, sizeof(pfdi_pe_locality_check)); + if (g_pfdi_pe_locality_check == NULL) { + val_print(ACS_PRINT_ERR, "\n Memory allocation failed", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + cache_clean_pfdi_status(&g_pfdi_pe_locality_check->force_err); + cache_clean_pfdi_status(&g_pfdi_pe_locality_check->cross_pe); + cache_clean_pfdi_status(&g_pfdi_pe_locality_check->same_pe_first); + + /* + * Test sequence: + * Step 1: Calling PE injects errors for all PFDI functions + * Step 2: Other PE calls all PFDI functions and observes normal behavior + * Step 3: Calling PE calls all PFDI functions and observes injected results + */ + + /* Step 1: inject errors on the calling PE */ + inject_errors_on_calling_pe(); + + /* Step 2: run calls on another PE and wait for completion */ + val_execute_on_pe(other_pe_index, call_pfdi_functions_on_other_pe, 0); + + /* Wait for the other PE to finish its calls */ + timeout = TIMEOUT_LARGE; + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(other_pe_index)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** waiting for other PE index = %d", + other_pe_index); + val_set_status(index, RESULT_FAIL(TEST_NUM, 2)); + goto free_locality_buffer; + } + + consume_errors_on_calling_pe(); + + /* Collect per-PE result buffers for validation */ + err = &g_pfdi_pe_locality_check->force_err; + same_first = &g_pfdi_pe_locality_check->same_pe_first; + cross_pe = &g_pfdi_pe_locality_check->cross_pe; + + cache_clean_pfdi_status(err); + cache_clean_pfdi_status(same_first); + cache_clean_pfdi_status(cross_pe); + + /* Validate per-target results for cross-PE isolation and same-PE delivery */ + for (i = 0; i < PFDI_FN_TARGET_COUNT; i++) { + idx = i; + + if (err->x0[idx] == PFDI_ACS_ERROR) { + val_print(ACS_PRINT_WARN, "\n FORCE_ERROR %a error; skipping checks", + (uint64_t)pfdi_fn_names[idx]); + val_print(ACS_PRINT_WARN, " on PE index %d", index); + test_skip++; + continue; + } + + if (err->x0[idx] != PFDI_ACS_SUCCESS) { + val_print(ACS_PRINT_ERR, "\n PFDI Force Error failed for %a", + (uint64_t)pfdi_fn_names[idx]); + val_print(ACS_PRINT_ERR, " x0=%ld", err->x0[idx]); + val_print(ACS_PRINT_ERR, " on PE index %d", index); + test_fail++; + continue; + } + + if (cross_pe->x0[idx] == PFDI_ACS_UNKNOWN) { + val_print(ACS_PRINT_ERR, "\n Other PE saw injected error for %a", + (uint64_t)pfdi_fn_names[idx]); + val_print(ACS_PRINT_ERR, " x0=%ld", cross_pe->x0[idx]); + val_print(ACS_PRINT_ERR, " on PE index %d", other_pe_index); + test_fail++; + } + + if (same_first->x0[idx] != PFDI_ACS_UNKNOWN) { + val_print(ACS_PRINT_ERR, "\n Calling PE did not see injected error for %a", + (uint64_t)pfdi_fn_names[idx]); + val_print(ACS_PRINT_ERR, " x0=%ld", same_first->x0[idx]); + val_print(ACS_PRINT_ERR, " on PE index %d", index); + test_fail++; + } + + } + + /* Report aggregate pass/fail for the calling PE */ + if (test_fail) { + val_set_status(index, RESULT_FAIL(TEST_NUM, 3)); + } else if (test_skip) { + val_set_status(index, RESULT_SKIP(TEST_NUM, 2)); + } else { + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + } + +free_locality_buffer: + val_memory_free((void *)g_pfdi_pe_locality_check); + g_pfdi_pe_locality_check = NULL; +} + +uint32_t +pfdi028_entry(uint32_t num_pe) +{ + uint32_t status; + if (num_pe > 2) + num_pe = 2; + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_check_pe_locality); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi029.c b/test_pool/pfdi/pfdi029.c new file mode 100644 index 00000000..cf868bdd --- /dev/null +++ b/test_pool/pfdi/pfdi029.c @@ -0,0 +1,163 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 29) +#define TEST_RULE "R0163" +#define TEST_DESC "PFDI Test Run invalid params check " + +#define NUM_REGS_TO_CHECK 2 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_REGS_TO_CHECK]; +} PFDI_INVAL_RETURNS; + +PFDI_INVAL_RETURNS *g_pfdi_invalid_run; + +static void +pfdi_invalid_run_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_invalid_run + index; + + /* Invoke PFDI Run function for current PE index with invalid x3 parameter*/ + pfdi_buffer->inval[0].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_RUN, PFDI_RUN_ALL_TEST_PARTS, + PFDI_RUN_ALL_TEST_PARTS, PFDI_INVALID_X_VALUE, 0, 0, + (unsigned long *)&pfdi_buffer->inval[0].x1, (unsigned long *)&pfdi_buffer->inval[0].x2, + (unsigned long *)&pfdi_buffer->inval[0].x3, (unsigned long *)&pfdi_buffer->inval[0].x4); + + /* Invoke PFDI Run function for current PE index with invalid x4 parameter*/ + pfdi_buffer->inval[1].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_PE_TEST_RUN, PFDI_RUN_ALL_TEST_PARTS, + PFDI_RUN_ALL_TEST_PARTS, 0, PFDI_INVALID_X_VALUE, 0, + (unsigned long *)&pfdi_buffer->inval[1].x1, (unsigned long *)&pfdi_buffer->inval[1].x2, + (unsigned long *)&pfdi_buffer->inval[1].x3, (unsigned long *)&pfdi_buffer->inval[1].x4); + + for (i = 0; i < NUM_REGS_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + return; +} + +static void payload_invalid_run_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout = 0, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI Test Run or status for all PE's */ + g_pfdi_invalid_run = (PFDI_INVAL_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_RETURNS)); + if (g_pfdi_invalid_run == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid Test Run Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_run + i; + for (num_regs = 0; num_regs < NUM_REGS_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_invalid_run_check for current PE index */ + pfdi_invalid_run_check(); + + /* Execute pfdi_invalid_run_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_invalid_run_check, 0); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_run + i; + test_fail = 0; + inval_case = 0; + + /* If X3-X4 are non-zero, return params X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_REGS_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n PFDI test run with invalid x%d", inval_case + 2); + val_print(ACS_PRINT_ERR, " param failed %ld ", pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for x%d invalid case:", inval_case + 2); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_invalid_run); + + return; +} + +uint32_t pfdi029_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_invalid_run_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi030.c b/test_pool/pfdi/pfdi030.c new file mode 100644 index 00000000..3d66b907 --- /dev/null +++ b/test_pool/pfdi/pfdi030.c @@ -0,0 +1,163 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 30) +#define TEST_RULE "R0180" +#define TEST_DESC "PFDI Force Error invalid params check " + +#define NUM_REGS_TO_CHECK 2 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_REGS_TO_CHECK]; +} PFDI_INVAL_RETURNS; + +PFDI_INVAL_RETURNS *g_pfdi_invalid_force_error; + +static void +pfdi_invalid_force_error_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_invalid_force_error + index; + + /* Invoke PFDI Force Error function for current PE index with invalid x3 parameter*/ + pfdi_buffer->inval[0].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FORCE_ERROR, PFDI_FN_PFDI_FORCE_ERROR, + PFDI_ACS_UNKNOWN, PFDI_INVALID_X_VALUE, 0, 0, + (unsigned long *)&pfdi_buffer->inval[0].x1, (unsigned long *)&pfdi_buffer->inval[0].x2, + (unsigned long *)&pfdi_buffer->inval[0].x3, (unsigned long *)&pfdi_buffer->inval[0].x4); + + /* Invoke PFDI Force Error function for current PE index with invalid x4 parameter*/ + pfdi_buffer->inval[1].x0 = val_invoke_pfdi_fn( + PFDI_FN_PFDI_FORCE_ERROR, PFDI_FN_PFDI_FORCE_ERROR, + PFDI_ACS_UNKNOWN, 0, PFDI_INVALID_X_VALUE, 0, + (unsigned long *)&pfdi_buffer->inval[1].x1, (unsigned long *)&pfdi_buffer->inval[1].x2, + (unsigned long *)&pfdi_buffer->inval[1].x3, (unsigned long *)&pfdi_buffer->inval[1].x4); + + for (i = 0; i < NUM_REGS_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 1)); + return; +} + +static void payload_invalid_force_error_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout = 0, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI Force Error or status for all PE's */ + g_pfdi_invalid_force_error = (PFDI_INVAL_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_RETURNS)); + if (g_pfdi_invalid_force_error == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid Force Error Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_force_error + i; + for (num_regs = 0; num_regs < NUM_REGS_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_invalid_force_error_check for current PE index */ + pfdi_invalid_force_error_check(); + + /* Execute pfdi_invalid_force_error_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_invalid_force_error_check, 0); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_invalid_force_error + i; + test_fail = 0; + inval_case = 0; + + /* If X3-X4 are non-zero, return params X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_REGS_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n PFDI force_error with invalid x%d", inval_case + 2); + val_print(ACS_PRINT_ERR, " param failed %ld ", pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for x%d invalid case:", inval_case + 2); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_invalid_force_error); + + return; +} + +uint32_t pfdi030_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_invalid_force_error_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/test_pool/pfdi/pfdi031.c b/test_pool/pfdi/pfdi031.c new file mode 100644 index 00000000..6226680a --- /dev/null +++ b/test_pool/pfdi/pfdi031.c @@ -0,0 +1,162 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * 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. + **/ + +#include "val/include/acs_val.h" +#include "val/include/acs_memory.h" +#include "val/include/val_interface.h" + +#define TEST_NUM (ACS_PFDI_TEST_NUM_BASE + 31) +#define TEST_RULE "R0176" +#define TEST_DESC "PFDI Force Error invalid function ID check" + +#define NUM_FUNC_TO_CHECK 2 + +typedef struct{ + PFDI_RET_PARAMS inval[NUM_FUNC_TO_CHECK]; +} PFDI_INVAL_FUNC_RETURNS; + +PFDI_INVAL_FUNC_RETURNS *g_pfdi_force_error_invalid_fn; + +static void +pfdi_force_error_invalid_fn_check(void) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()), i; + PFDI_INVAL_FUNC_RETURNS *pfdi_buffer; + + pfdi_buffer = g_pfdi_force_error_invalid_fn + index; + + /* Invoke PFDI Force Error function for current PE index with reserved function ID */ + pfdi_buffer->inval[0].x0 = val_pfdi_force_error(PFDI_FN_PFDI_RESERVED, PFDI_ACS_NOT_SUPPORTED, + &pfdi_buffer->inval[0].x1, &pfdi_buffer->inval[0].x2, + &pfdi_buffer->inval[0].x3, &pfdi_buffer->inval[0].x4); + + /* Invoke PFDI Force Error function for current PE index with invalid function ID */ + pfdi_buffer->inval[1].x0 = val_pfdi_force_error(PFDI_FN_PFDI_INVALID, PFDI_ACS_NOT_SUPPORTED, + &pfdi_buffer->inval[1].x1, &pfdi_buffer->inval[1].x2, + &pfdi_buffer->inval[1].x3, &pfdi_buffer->inval[1].x4); + + for (i = 0; i < NUM_FUNC_TO_CHECK; i++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[i]); + } + + val_set_status(index, RESULT_PASS(TEST_NUM, 2)); + return; +} + +static void payload_force_error_invalid_fn_check(void *arg) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t num_pe = *((uint32_t *)arg); + uint32_t timeout = 0, i = 0, num_regs = 0; + uint32_t test_fail = 0; + uint32_t inval_case = 0; + PFDI_INVAL_FUNC_RETURNS *pfdi_buffer; + + /* Allocate memory to save all PFDI Force Error or status for all PE's */ + g_pfdi_force_error_invalid_fn = (PFDI_INVAL_FUNC_RETURNS *) + val_memory_calloc(num_pe, sizeof(PFDI_INVAL_FUNC_RETURNS)); + if (g_pfdi_force_error_invalid_fn == NULL) { + val_print(ACS_PRINT_ERR, "\n Allocation for PFDI Invalid Force Error Failed \n", 0); + val_set_status(index, RESULT_FAIL(TEST_NUM, 1)); + return; + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_force_error_invalid_fn + i; + for (num_regs = 0; num_regs < NUM_FUNC_TO_CHECK; num_regs++) { + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[num_regs]); + } + } + + /* Invoke pfdi_force_error_invalid_fn_check for current PE index */ + pfdi_force_error_invalid_fn_check(); + + /* Execute pfdi_force_error_invalid_fn_check function in All PE's */ + for (i = 0; i < num_pe; i++) { + if (i != index) { + timeout = TIMEOUT_LARGE; + val_execute_on_pe(i, pfdi_force_error_invalid_fn_check, 0); + + while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); + + if (timeout == 0) { + val_print(ACS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + val_set_status(i, RESULT_FAIL(TEST_NUM, 2)); + goto free_pfdi_details; + } + } + } + + for (i = 0; i < num_pe; i++) { + pfdi_buffer = g_pfdi_force_error_invalid_fn + i; + test_fail = 0; + inval_case = 0; + + /* If X3-X4 are non-zero, return params X0=INVALID_PARAM and X1-X4=0 */ + for (inval_case = 0; inval_case < NUM_FUNC_TO_CHECK; inval_case++) { + + val_pfdi_invalidate_ret_params(&pfdi_buffer->inval[inval_case]); + + if (pfdi_buffer->inval[inval_case].x0 != PFDI_ACS_INVALID_PARAMETERS) { + val_print(ACS_PRINT_ERR, "\n PFDI force_error with invalid %a", + (inval_case == 0) ? (uint64_t)"RESERVED" : (uint64_t)"INVALID"); + val_print(ACS_PRINT_ERR, " function ID failed status %ld ", + pfdi_buffer->inval[inval_case].x0); + val_print(ACS_PRINT_ERR, "on PE = %d", i); + test_fail++; + } + + if ((pfdi_buffer->inval[inval_case].x1 != 0) || (pfdi_buffer->inval[inval_case].x2 != 0) || + (pfdi_buffer->inval[inval_case].x3 != 0) || (pfdi_buffer->inval[inval_case].x4 != 0)) { + val_print(ACS_PRINT_ERR, + "\n Registers X1-X4 are not zero for %a function ID:", + (inval_case == 0) ? (uint64_t)"RESERVED" : (uint64_t)"INVALID"); + val_print(ACS_PRINT_ERR, " x1=0x%llx", pfdi_buffer->inval[inval_case].x1); + val_print(ACS_PRINT_ERR, " x2=0x%llx", pfdi_buffer->inval[inval_case].x2); + val_print(ACS_PRINT_ERR, " x3=0x%llx", pfdi_buffer->inval[inval_case].x3); + val_print(ACS_PRINT_ERR, " x4=0x%llx", pfdi_buffer->inval[inval_case].x4); + val_print(ACS_PRINT_ERR, "\n Failed on PE = %d", i); + test_fail++; + } + } + + if (test_fail) + val_set_status(i, RESULT_FAIL(TEST_NUM, 3)); + else + val_set_status(i, RESULT_PASS(TEST_NUM, 1)); + } + +free_pfdi_details: + val_memory_free((void *) g_pfdi_force_error_invalid_fn); + + return; +} + +uint32_t pfdi031_entry(uint32_t num_pe) +{ + uint32_t status = ACS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + + if (status != ACS_STATUS_SKIP) + val_run_test_configurable_payload(&num_pe, payload_force_error_invalid_fn_check); + + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + val_report_status(0, ACS_END(TEST_NUM), NULL); + + return status; +} diff --git a/val/ValLib.inf b/val/ValLib.inf index 84f6de26..1e22cbf0 100644 --- a/val/ValLib.inf +++ b/val/ValLib.inf @@ -79,7 +79,6 @@ src/mpam_execute_test.c src/drtm_execute_test.c src/pc_bsa_execute_test.c - src/pfdi_execute_test.c [Packages] MdePkg/MdePkg.dec diff --git a/val/ValLibRB.inf b/val/ValLibRB.inf index 9e657a32..e2f618e5 100644 --- a/val/ValLibRB.inf +++ b/val/ValLibRB.inf @@ -60,6 +60,7 @@ src/acs_ete.c src/acs_pcc.c src/acs_interface.c + src/acs_pfdi.c src/acs_msc_error.c src/acs_tpm.c driver/smmu_v3/smmu_v3.c diff --git a/val/include/acs_memory.h b/val/include/acs_memory.h index 04dcc2c5..9c1f160b 100644 --- a/val/include/acs_memory.h +++ b/val/include/acs_memory.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2021, 2023-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2021, 2023-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/val/include/acs_pfdi.h b/val/include/acs_pfdi.h index df80a056..3af5929d 100644 --- a/val/include/acs_pfdi.h +++ b/val/include/acs_pfdi.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,6 +45,8 @@ #define VAL_PFDI_RESERVED_BYTE_ZERO 0x0 #define PFDI_ACS_NOT_IMPLEMENTED 0x1 +#define PFDI_INVALID_X_VALUE 0xF +#define PFDI_RUN_ALL_TEST_PARTS -1 typedef enum { PFDI_ACS_SUCCESS = 0, @@ -57,4 +59,16 @@ typedef enum { PFDI_ACS_TEST_COUNT_ZERO = -8 } PFDI_ACS_RET_CODE; +typedef enum { + PFDI_FN_VERSION_IDX = 0, + PFDI_FN_FEATURES_IDX, + PFDI_FN_PE_TEST_ID_IDX, + PFDI_FN_PE_TEST_PART_COUNT_IDX, + PFDI_FN_PE_TEST_RUN_IDX, + PFDI_FN_PE_TEST_RESULT_IDX, + PFDI_FN_FW_CHECK_IDX, + PFDI_FN_FORCE_ERROR_IDX, + PFDI_FN_MAX_IDX +} PFDI_FN_INDEX; + #endif /* __ACS_PFDI_H */ diff --git a/val/include/rule_based_execution.h b/val/include/rule_based_execution.h index b948b046..ba364896 100644 --- a/val/include/rule_based_execution.h +++ b/val/include/rule_based_execution.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -77,6 +77,11 @@ typedef struct { VBSA_LEVEL_e level; } vbsa_rule_entry_t; +typedef struct { + RULE_ID_e rule_id; + PFDI_LEVEL_e level; +} pfdi_rule_entry_t; + /* ---------------------------- Helper functions declarations ---------------------------------- */ void quick_sort_rule_list(RULE_ID_e *rule_list, uint32_t list_size); uint32_t check_module_init(MODULE_NAME_e module_id); @@ -97,6 +102,7 @@ extern const bsa_rule_entry_t bsa_rule_list[]; extern const sbsa_rule_entry_t sbsa_rule_list[]; extern const pcbsa_rule_entry_t pcbsa_rule_list[]; extern const vbsa_rule_entry_t vbsa_rule_list[]; +extern const pfdi_rule_entry_t pfdi_rule_list[]; /* Global selections configured by the app */ extern uint32_t g_level_filter_mode; /* LEVEL_FILTER_MODE_e */ diff --git a/val/include/rule_based_execution_enum.h b/val/include/rule_based_execution_enum.h index 38607b87..a4acb4e9 100644 --- a/val/include/rule_based_execution_enum.h +++ b/val/include/rule_based_execution_enum.h @@ -526,6 +526,39 @@ typedef enum { V_L2PE_02, V_L2WD_01, + /* PFDI rules */ + R0040, + R0053, + R0060, + R0066, + R0071, + R0076, + R0082, + R0089, + R0099, + R0100, + R0102, + R0104, + R0154, + R0155, + R0156, + R0157, + R0158, + R0160, + R0163, + R0164, + R0165, + R0166, + R0167, + R0168, + R0172, + R0173, + R0176, + R0179, + R0180, + R0193, + R0194, + /* Sentinel must remain last */ RULE_ID_SENTINEL } RULE_ID_e; @@ -890,6 +923,37 @@ typedef enum { P100_ENTRY, P104_ENTRY, GPU_04_ENTRY, + PFDI001_ENTRY, + PFDI002_ENTRY, + PFDI003_ENTRY, + PFDI004_ENTRY, + PFDI005_ENTRY, + PFDI006_ENTRY, + PFDI007_ENTRY, + PFDI008_ENTRY, + PFDI009_ENTRY, + PFDI010_ENTRY, + PFDI011_ENTRY, + PFDI012_ENTRY, + PFDI013_ENTRY, + PFDI014_ENTRY, + PFDI015_ENTRY, + PFDI016_ENTRY, + PFDI017_ENTRY, + PFDI018_ENTRY, + PFDI019_ENTRY, + PFDI020_ENTRY, + PFDI021_ENTRY, + PFDI022_ENTRY, + PFDI023_ENTRY, + PFDI024_ENTRY, + PFDI025_ENTRY, + PFDI026_ENTRY, + PFDI027_ENTRY, + PFDI028_ENTRY, + PFDI029_ENTRY, + PFDI030_ENTRY, + PFDI031_ENTRY, TEST_ENTRY_SENTINEL } TEST_ENTRY_ID_e; @@ -912,6 +976,7 @@ typedef enum { ETE, TPM, POWER_WAKEUP, + PFDI, MODULE_ID_SENTINEL /* need to be in last */ } MODULE_NAME_e; @@ -955,6 +1020,12 @@ typedef enum { VBSA_LEVEL_SENTINEL /* Keep last */ } VBSA_LEVEL_e; +/* PFDI levels enum */ +typedef enum { + PFDI_LEVEL_1 = 1, + PFDI_LEVEL_SENTINEL /* Keep last */ +} PFDI_LEVEL_e; + /* Software views enum for BSA */ typedef enum { SW_OS, @@ -969,13 +1040,14 @@ typedef enum { PLATFORM_LINUX = 1 << 2 // 0x04 } PLATFORM_e; -/* Architecture selection for rule expansion via -a */ +/* Architecture selection for rule expansion */ typedef enum { ARCH_NONE = 0, ARCH_BSA, ARCH_SBSA, ARCH_PCBSA, - ARCH_VBSA + ARCH_VBSA, + ARCH_PFDI } ARCH_SEL_e; /* Level filter mode for CLI selection */ diff --git a/val/include/val_interface.h b/val/include/val_interface.h index 1d79ffd9..c78016bd 100644 --- a/val/include/val_interface.h +++ b/val/include/val_interface.h @@ -850,7 +850,7 @@ val_pfdi_verify_regs(ARM_SMC_ARGS *args, int32_t conduit, uint64_t post_smc_regs[REG_COUNT_X5_X17]); void val_pfdi_invalidate_ret_params(PFDI_RET_PARAMS *args); -uint32_t val_pfdi_execute_pfdi_tests(uint32_t num_pe); +uint32_t val_pfdi_check_implementation(void); uint32_t pfdi001_entry(uint32_t num_pe); uint32_t pfdi002_entry(uint32_t num_pe); @@ -869,5 +869,19 @@ uint32_t pfdi014_entry(uint32_t num_pe); uint32_t pfdi015_entry(uint32_t num_pe); uint32_t pfdi016_entry(uint32_t num_pe); uint32_t pfdi017_entry(uint32_t num_pe); +uint32_t pfdi018_entry(uint32_t num_pe); +uint32_t pfdi019_entry(uint32_t num_pe); +uint32_t pfdi020_entry(uint32_t num_pe); +uint32_t pfdi021_entry(uint32_t num_pe); +uint32_t pfdi022_entry(uint32_t num_pe); +uint32_t pfdi023_entry(uint32_t num_pe); +uint32_t pfdi024_entry(uint32_t num_pe); +uint32_t pfdi025_entry(uint32_t num_pe); +uint32_t pfdi026_entry(uint32_t num_pe); +uint32_t pfdi027_entry(uint32_t num_pe); +uint32_t pfdi028_entry(uint32_t num_pe); +uint32_t pfdi029_entry(uint32_t num_pe); +uint32_t pfdi030_entry(uint32_t num_pe); +uint32_t pfdi031_entry(uint32_t num_pe); #endif diff --git a/val/src/acs_memory.c b/val/src/acs_memory.c index 47432e40..04e389ae 100644 --- a/val/src/acs_memory.c +++ b/val/src/acs_memory.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/val/src/acs_pfdi.c b/val/src/acs_pfdi.c index 9a12d434..1c58d2cd 100644 --- a/val/src/acs_pfdi.c +++ b/val/src/acs_pfdi.c @@ -1,7 +1,7 @@ /** @file * PFDI API * - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,6 +25,33 @@ extern int32_t gPsciConduit; +/** + @brief Probe to see if the platform implements any PFDI entry points. + 1. Caller - Application layer. + 2. Prerequisite - None. + @return ACS_STATUS_PASS if at least one call is supported, else PFDI_ACS_NOT_IMPLEMENTED. +**/ +uint32_t +val_pfdi_check_implementation(void) +{ + uint32_t f_id; + uint32_t test_skip = 1; + int64_t pfdi_fn_status; + + for (f_id = PFDI_FN_PFDI_VERSION; f_id <= PFDI_FN_PFDI_FORCE_ERROR; f_id++) { + pfdi_fn_status = val_invoke_pfdi_fn(f_id, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + if (pfdi_fn_status != PFDI_ACS_NOT_SUPPORTED) { + test_skip = 0; + break; + } + } + + if (test_skip) + return PFDI_ACS_NOT_IMPLEMENTED; + + return ACS_STATUS_PASS; +} + /** @brief This function checks if reserved_bits received are zero @param reserved_bits reserved bits value received diff --git a/val/src/pfdi_execute_test.c b/val/src/pfdi_execute_test.c deleted file mode 100644 index 1bc1e7f5..00000000 --- a/val/src/pfdi_execute_test.c +++ /dev/null @@ -1,91 +0,0 @@ -/** @file - * Pfdi API - * - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. - * SPDX-License-Identifier : Apache-2.0 - * - * 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. - **/ - -#include "include/acs_val.h" -#include "include/val_interface.h" -#include "include/acs_common.h" -#include "include/pal_interface.h" -#include "include/acs_std_smc.h" - -/** - @brief This API will execute all PFDI tests - 1. Caller - Application layer. - 2. Prerequisite - @param num_pe - the number of PE to run these tests on. - @return Consolidated status of all the tests run. -**/ -uint32_t -val_pfdi_execute_pfdi_tests(uint32_t num_pe) -{ - uint32_t status, i; - uint32_t f_id, test_skip = 1; - int64_t pfdi_fn_status; - - for (i = 0; i < g_num_skip; i++) { - if (g_skip_test_num[i] == ACS_PFDI_TEST_NUM_BASE) { - val_print(ACS_PRINT_INFO, "\n USER Override - Skipping all PFDI tests\n", 0); - return ACS_STATUS_SKIP; - } - } - - /* Check if there are any tests to be executed in current module with user override options*/ - status = val_check_skip_module(ACS_PFDI_TEST_NUM_BASE); - if (status) { - val_print(ACS_PRINT_INFO, "\n USER Override - Skipping all PFDI tests\n", 0); - return ACS_STATUS_SKIP; - } - - for (f_id = PFDI_FN_PFDI_VERSION; f_id <= PFDI_FN_PFDI_FORCE_ERROR; f_id++) { - pfdi_fn_status = val_invoke_pfdi_fn(f_id, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); - if (pfdi_fn_status != PFDI_ACS_NOT_SUPPORTED) { - test_skip = 0; - break; - } - } - - if (test_skip) - return PFDI_ACS_NOT_IMPLEMENTED; - - status = ACS_STATUS_PASS; - - val_print_test_start("PFDI"); - g_curr_module = 1 << PFDI_MODULE; - - status = pfdi001_entry(num_pe); - status |= pfdi002_entry(num_pe); - status |= pfdi003_entry(num_pe); - status |= pfdi004_entry(num_pe); - status |= pfdi005_entry(num_pe); - status |= pfdi006_entry(num_pe); - status |= pfdi007_entry(num_pe); - status |= pfdi008_entry(num_pe); - status |= pfdi009_entry(num_pe); - status |= pfdi010_entry(num_pe); - status |= pfdi011_entry(num_pe); - status |= pfdi012_entry(num_pe); - status |= pfdi013_entry(num_pe); - status |= pfdi014_entry(num_pe); - status |= pfdi015_entry(num_pe); - status |= pfdi016_entry(num_pe); - status |= pfdi017_entry(num_pe); - - val_print_test_end(status, "PFDI"); - - return status; -} diff --git a/val/src/rule_based_orchestrator.c b/val/src/rule_based_orchestrator.c index 56f3cce2..2af887c8 100644 --- a/val/src/rule_based_orchestrator.c +++ b/val/src/rule_based_orchestrator.c @@ -131,6 +131,7 @@ uint32_t filter_rule_list_by_cli(RULE_ID_e **rule_list, uint32_t list_size) const sbsa_rule_entry_t *sbsa_tbl = NULL; const pcbsa_rule_entry_t *pcbsa_tbl = NULL; const vbsa_rule_entry_t *vbsa_tbl = NULL; + const pfdi_rule_entry_t *pfdi_tbl = NULL; uint32_t tbl_count = 0; /* if pointer is NULL, API misuse return */ @@ -158,6 +159,10 @@ uint32_t filter_rule_list_by_cli(RULE_ID_e **rule_list, uint32_t list_size) while (vbsa_rule_list[add_count].rule_id != RULE_ID_SENTINEL) add_count++; vbsa_tbl = vbsa_rule_list; + } else if (g_arch_selection == ARCH_PFDI) { + while (pfdi_rule_list[add_count].rule_id != RULE_ID_SENTINEL) + add_count++; + pfdi_tbl = pfdi_rule_list; } if (add_count > 0) { @@ -195,6 +200,12 @@ uint32_t filter_rule_list_by_cli(RULE_ID_e **rule_list, uint32_t list_size) if (!rule_in_list(rid, new_list, new_count)) new_list[new_count++] = rid; } + } else if (pfdi_tbl) { + for (i = 0; i < add_count; i++) { + RULE_ID_e rid = pfdi_tbl[i].rule_id; + if (!rule_in_list(rid, new_list, new_count)) + new_list[new_count++] = rid; + } } /* Free old buffer (if allocated via VAL) and update pointer */ @@ -219,6 +230,9 @@ uint32_t filter_rule_list_by_cli(RULE_ID_e **rule_list, uint32_t list_size) vbsa_tbl = vbsa_rule_list; while (vbsa_tbl[tbl_count].rule_id != RULE_ID_SENTINEL) tbl_count++; } + } else if (g_arch_selection == ARCH_PFDI) { + pfdi_tbl = pfdi_rule_list; + while (pfdi_tbl[tbl_count].rule_id != RULE_ID_SENTINEL) tbl_count++; } /* if rule list is NULL no filtering required */ @@ -351,6 +365,20 @@ uint32_t filter_rule_list_by_cli(RULE_ID_e **rule_list, uint32_t list_size) break; } } + } else if (pfdi_tbl) { + for (uint32_t ti = 0; ti < tbl_count; ti++) { + if (pfdi_tbl[ti].rule_id == rule) { + found_entry = 1; + if (g_level_filter_mode == LVL_FILTER_ONLY) { + if ((uint32_t)pfdi_tbl[ti].level != g_level_value) + skip = 1; + } else if (g_level_filter_mode == LVL_FILTER_MAX) { + if ((uint32_t)pfdi_tbl[ti].level > g_level_value) + skip = 1; + } + break; + } + } } /* If not found in table, conservatively skip or keep? Keep by default */ diff --git a/val/src/rule_enum_string_map.c b/val/src/rule_enum_string_map.c index 0e8afbfa..d078187d 100644 --- a/val/src/rule_enum_string_map.c +++ b/val/src/rule_enum_string_map.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -508,6 +508,40 @@ char *rule_id_string[RULE_ID_SENTINEL] = { [V_L2PE_01] = "V_L2PE_01", [V_L2PE_02] = "V_L2PE_02", [V_L2WD_01] = "V_L2WD_01", + + /* PFDI rules */ + [R0040] = "R0040", + [R0053] = "R0053", + [R0060] = "R0060", + [R0066] = "R0066", + [R0071] = "R0071", + [R0076] = "R0076", + [R0082] = "R0082", + [R0089] = "R0089", + [R0099] = "R0099", + [R0100] = "R0100", + [R0102] = "R0102", + [R0104] = "R0104", + [R0154] = "R0154", + [R0155] = "R0155", + [R0156] = "R0156", + [R0157] = "R0157", + [R0158] = "R0158", + [R0160] = "R0160", + [R0163] = "R0163", + [R0164] = "R0164", + [R0165] = "R0165", + [R0166] = "R0166", + [R0167] = "R0167", + [R0168] = "R0168", + [R0172] = "R0172", + [R0173] = "R0173", + [R0176] = "R0176", + [R0179] = "R0179", + [R0180] = "R0180", + [R0193] = "R0193", + [R0194] = "R0194", + }; /* Module name strings mapping to MODULE_NAME_e */ @@ -528,4 +562,5 @@ char *module_name_string[MODULE_ID_SENTINEL] = { [ETE] = "ETE", [TPM] = "TPM", [POWER_WAKEUP] = "POWER_WAKEUP", + [PFDI] = "PFDI", }; diff --git a/val/src/rule_lookup.c b/val/src/rule_lookup.c index 75f07d93..825b40d4 100644 --- a/val/src/rule_lookup.c +++ b/val/src/rule_lookup.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -400,4 +400,40 @@ const vbsa_rule_entry_t vbsa_rule_list[] = { /* Sentinel to indicate end-of-list */ { RULE_ID_SENTINEL, VBSA_LEVEL_SENTINEL } +}; + +/* PFDI rule checklist (single level at present) */ +const pfdi_rule_entry_t pfdi_rule_list[] = { + { R0040, PFDI_LEVEL_1 }, + { R0053, PFDI_LEVEL_1 }, + { R0060, PFDI_LEVEL_1 }, + { R0066, PFDI_LEVEL_1 }, + { R0071, PFDI_LEVEL_1 }, + { R0076, PFDI_LEVEL_1 }, + { R0082, PFDI_LEVEL_1 }, + { R0089, PFDI_LEVEL_1 }, + { R0099, PFDI_LEVEL_1 }, + { R0100, PFDI_LEVEL_1 }, + { R0102, PFDI_LEVEL_1 }, + { R0104, PFDI_LEVEL_1 }, + { R0154, PFDI_LEVEL_1 }, + { R0155, PFDI_LEVEL_1 }, + { R0156, PFDI_LEVEL_1 }, + { R0157, PFDI_LEVEL_1 }, + { R0158, PFDI_LEVEL_1 }, + { R0160, PFDI_LEVEL_1 }, + { R0163, PFDI_LEVEL_1 }, + { R0164, PFDI_LEVEL_1 }, + { R0165, PFDI_LEVEL_1 }, + { R0166, PFDI_LEVEL_1 }, + { R0167, PFDI_LEVEL_1 }, + { R0168, PFDI_LEVEL_1 }, + { R0172, PFDI_LEVEL_1 }, + { R0173, PFDI_LEVEL_1 }, + { R0176, PFDI_LEVEL_1 }, + { R0179, PFDI_LEVEL_1 }, + { R0180, PFDI_LEVEL_1 }, + { R0193, PFDI_LEVEL_1 }, + { R0194, PFDI_LEVEL_1 }, + { RULE_ID_SENTINEL, PFDI_LEVEL_SENTINEL } }; \ No newline at end of file diff --git a/val/src/rule_metadata.c b/val/src/rule_metadata.c index f31156c6..00ca5678 100644 --- a/val/src/rule_metadata.c +++ b/val/src/rule_metadata.c @@ -2603,6 +2603,255 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = { .flag = BASE_RULE, .test_num = ACS_PE_TEST_NUM_BASE + 10, }, + /* PFDI ACS entries */ + [R0053] = { + .test_entry_id = PFDI001_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PFDI Version is returned", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 1, + }, + [R0104] = { + .test_entry_id = PFDI002_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PFDI Version in All PE's", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 2, + }, + [R0102] = { + .test_entry_id = PFDI003_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PFDI mandatory functions", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 3, + }, + [R0060] = { + .test_entry_id = PFDI004_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PFDI Feature function support", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 4, + }, + [R0066] = { + .test_entry_id = PFDI005_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PE HW test mechanism info", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 5, + }, + [R0071] = { + .test_entry_id = PFDI006_ENTRY, + .module_id = PFDI, + .rule_desc = "Check num of Test Part supported", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 6, + }, + [R0076] = { + .test_entry_id = PFDI007_ENTRY, + .module_id = PFDI, + .rule_desc = "Execute Test Parts and All Parts on PE", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 7, + }, + [R0082] = { + .test_entry_id = PFDI008_ENTRY, + .module_id = PFDI, + .rule_desc = "Query PE boot test status", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 8, + }, + [R0089] = { + .test_entry_id = PFDI009_ENTRY, + .module_id = PFDI, + .rule_desc = "Query PFDI firmware check on all PEs", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 9, + }, + [R0156] = { + .test_entry_id = PFDI010_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI reserved function support check", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 10, + }, + [R0040] = { + .test_entry_id = PFDI011_ENTRY, + .module_id = PFDI, + .rule_desc = "Check if X5 to X17 are preserved", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 11, + }, + [R0099] = { + .test_entry_id = PFDI012_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI forced error injection", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 12, + }, + [R0164] = { + .test_entry_id = PFDI013_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PE Run with Start exceeds End", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 13, + }, + [R0165] = { + .test_entry_id = PFDI014_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PE Run with Start exceeds max", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 14, + }, + [R0100] = { + .test_entry_id = PFDI015_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI recovery after forced error", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 15, + }, + [R0157] = { + .test_entry_id = PFDI016_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PFDI feature for invalid function", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 16, + }, + [R0154] = { + .test_entry_id = PFDI017_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PFDI unsupported function", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 17, + }, + [R0166] = { + .test_entry_id = PFDI018_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PE Run with End exceeds max index", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 18, + }, + [R0167] = { + .test_entry_id = PFDI019_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PE Run with Start or End equals -1", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 19, + }, + [R0168] = { + .test_entry_id = PFDI020_ENTRY, + .module_id = PFDI, + .rule_desc = "Check PE Run with Start or End less -1", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 20, + }, + [R0155] = { + .test_entry_id = PFDI021_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI version invalid params check", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 21, + }, + [R0179] = { + .test_entry_id = PFDI022_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI Feature invalid params check", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 22, + }, + [R0158] = { + .test_entry_id = PFDI023_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI PE Test ID invalid params check", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 23, + }, + [R0160] = { + .test_entry_id = PFDI024_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI Test Part Count invalid params", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 24, + }, + [R0172] = { + .test_entry_id = PFDI025_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI PE Test Result invalid params check", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 25, + }, + [R0173] = { + .test_entry_id = PFDI026_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI Firmware Check invalid params", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 26, + }, + [R0193] = { + .test_entry_id = PFDI027_ENTRY, + .module_id = PFDI, + .rule_desc = "Check FORCE ERROR overwrite behavior", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 27, + }, + [R0194] = { + .test_entry_id = PFDI028_ENTRY, + .module_id = PFDI, + .rule_desc = "Check FORCE ERROR PE locality behavior", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 28, + }, + [R0163] = { + .test_entry_id = PFDI029_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI Test Run invalid params check", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 29, + }, + [R0180] = { + .test_entry_id = PFDI030_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI Force Error invalid params check", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 30, + }, + [R0176] = { + .test_entry_id = PFDI031_ENTRY, + .module_id = PFDI, + .rule_desc = "PFDI Force Error invalid function ID check", + .platform_bitmask = PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_PFDI_TEST_NUM_BASE + 31, + }, }; /* Following structure maps test entry enums with entry function pointers @@ -2640,6 +2889,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = { /* TARGET_UEFI */ #if defined(TARGET_UEFI) +#ifndef PFDI_DT_BUILD [D001_ENTRY] = d001_entry, [D002_ENTRY] = d002_entry, [D003_ENTRY] = d003_entry, @@ -2983,6 +3233,40 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = { [W003_ENTRY] = w003_entry, [V_L1WK_02_05_ENTRY] = v_l1wk_02_05_entry, [V_L1PP_00_ENTRY] = v_l1pp_00_entry, +#endif /* PFDI_DT_BUILD */ +#if defined(PFDI_DT_BUILD) + [PFDI001_ENTRY] = pfdi001_entry, + [PFDI002_ENTRY] = pfdi002_entry, + [PFDI003_ENTRY] = pfdi003_entry, + [PFDI004_ENTRY] = pfdi004_entry, + [PFDI005_ENTRY] = pfdi005_entry, + [PFDI006_ENTRY] = pfdi006_entry, + [PFDI007_ENTRY] = pfdi007_entry, + [PFDI008_ENTRY] = pfdi008_entry, + [PFDI009_ENTRY] = pfdi009_entry, + [PFDI010_ENTRY] = pfdi010_entry, + [PFDI011_ENTRY] = pfdi011_entry, + [PFDI012_ENTRY] = pfdi012_entry, + [PFDI013_ENTRY] = pfdi013_entry, + [PFDI014_ENTRY] = pfdi014_entry, + [PFDI015_ENTRY] = pfdi015_entry, + [PFDI016_ENTRY] = pfdi016_entry, + [PFDI017_ENTRY] = pfdi017_entry, + [PFDI018_ENTRY] = pfdi018_entry, + [PFDI019_ENTRY] = pfdi019_entry, + [PFDI020_ENTRY] = pfdi020_entry, + [PFDI021_ENTRY] = pfdi021_entry, + [PFDI022_ENTRY] = pfdi022_entry, + [PFDI023_ENTRY] = pfdi023_entry, + [PFDI024_ENTRY] = pfdi024_entry, + [PFDI025_ENTRY] = pfdi025_entry, + [PFDI026_ENTRY] = pfdi026_entry, + [PFDI027_ENTRY] = pfdi027_entry, + [PFDI028_ENTRY] = pfdi028_entry, + [PFDI029_ENTRY] = pfdi029_entry, + [PFDI030_ENTRY] = pfdi030_entry, + [PFDI031_ENTRY] = pfdi031_entry, +#endif /* PFDI_DT_BUILD */ #endif /* TARGET_UEFI */ /* TARGET_BAREMETAL */ diff --git a/val/val_bsa.cmake b/val/val_bsa.cmake index fa44c2f2..546bf1a9 100644 --- a/val/val_bsa.cmake +++ b/val/val_bsa.cmake @@ -1,5 +1,5 @@ ## @file - # Copyright (c) 2023-2025, Arm Limited or its affiliates. All rights reserved. + # Copyright (c) 2023-2026, Arm Limited or its affiliates. All rights reserved. # SPDX-License-Identifier : Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/val/val_sbsa.cmake b/val/val_sbsa.cmake index 6922c018..3de18087 100644 --- a/val/val_sbsa.cmake +++ b/val/val_sbsa.cmake @@ -1,5 +1,5 @@ ## @file - # Copyright (c) 2023-2025, Arm Limited or its affiliates. All rights reserved. + # Copyright (c) 2023-2026, Arm Limited or its affiliates. All rights reserved. # SPDX-License-Identifier : Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License");