diff --git a/README.md b/README.md index 5364530f..18310da1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## Server Base System Architecture -**Server Base System Architecture** (SBSA) specification specifies a hardware system architecture based on the ARM 64-bit architecture. Server system software such as operating systems, hypervisors, and firmware rely on this. It addresses processing element features and key aspects of system architecture. +**Server Base System Architecture** (SBSA) specification specifies a hardware system architecture based on the ARM 64-bit architecture. Server system software such as operating systems, hypervisors, and firmware rely on this. It addresses processing element features and key aspects of system architecture. For more information, download the [SBSA specification](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029b/index.html) @@ -17,7 +17,7 @@ A few tests are executed by running the SBSA ACS Linux application which in turn ## Release details - - Code Quality: REL v2.0 + - Code Quality: REL v2.1 - The tests are written for version 5.0 of the SBSA specification. - The compliance suite is not a substitute for design verification. - To review the SBSA ACS logs, ARM licensees can contact ARM directly through their partner managers. @@ -30,8 +30,8 @@ A few tests are executed by running the SBSA ACS Linux application which in turn - To get the latest version of the code with bug fixes and new features, use the master branch. ## Additional reading - - For details on the SBSA ACS UEFI Shell Application, see [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf). - - For details on the Design of the SBSA ACS, see [Validation Methodology Document](docs/SBSA_Val_Methodolgy.pdf). + - For details on the SBSA ACS UEFI Shell Application, see [SBSA ACS User Guide](docs/Arm_SBSA_Architecture_Compliance_User_Guide.pdf). + - For details on the Design of the SBSA ACS, see [Validation Methodology Document](docs/Arm_SBSA_Architecture_Compliance_Validation_Methodology.pdf). - For information about the test coverage scenarios that are implemented in the current release of ACS and the scenarios that are planned for the future releases, see [Testcase checklist](docs/testcase-checklist.md). diff --git a/docs/Arm_SBSA_Architecture_Compliance_User_Guide.pdf b/docs/Arm_SBSA_Architecture_Compliance_User_Guide.pdf new file mode 100755 index 00000000..63b9f00c Binary files /dev/null and b/docs/Arm_SBSA_Architecture_Compliance_User_Guide.pdf differ diff --git a/docs/Arm_SBSA_Architecture_Compliance_Validation_Methodology.pdf b/docs/Arm_SBSA_Architecture_Compliance_Validation_Methodology.pdf new file mode 100755 index 00000000..0980e94e Binary files /dev/null and b/docs/Arm_SBSA_Architecture_Compliance_Validation_Methodology.pdf differ diff --git a/docs/SBSA_ACS_User_Guide.pdf b/docs/SBSA_ACS_User_Guide.pdf deleted file mode 100755 index e31df0de..00000000 Binary files a/docs/SBSA_ACS_User_Guide.pdf and /dev/null differ diff --git a/docs/testcase-checklist.md b/docs/testcase-checklist.md index 9f0f63a0..410603af 100644 --- a/docs/testcase-checklist.md +++ b/docs/testcase-checklist.md @@ -60,26 +60,26 @@ | 302 | Watchdog | L2+ | Watchdog Signal 0 is routed as an SPIor LPI to the GIC and usable as a EL2 interrupt | 4.3.8 | yes | UEFI App | | 401 | PCIe | L1+ | Systems must map memory space to PCI Express configuration space, using the PCI Express Enhanced Configuration Access Mechanism (ECAM). Tests should be robust to ARI being implemented | 8.1 | yes | Linux driver | | 402 | PCIe | L1+ | The base address of each ECAM region is discoverable from system firmware data | 8.1 | yes | Linux driver | -| 403 | PCIe | L1+ | PEs are able to access the ECAM region | 8.1 | yes | Linux driver | -| 404 | PCIe | L1+ | All systems must support mapping PCI Express memory space as either device memory or non-cacheable memory | 8.2 | yes | Linux driver | -| 404 | PCIe | L1+ | When PCI Express memory space is mapped as normal memory, the system must support unaligned accesses to that region. | 8.2 | yes | Linux driver | +| 403, 801 | PCIe | L1+ | PEs are able to access the ECAM region | 8.1 | yes | Linux driver | +| 404, 802 | PCIe | L1+ | All systems must support mapping PCI Express memory space as either device memory or non-cacheable memory | 8.2 | yes | Linux driver | +| 404, 802 | PCIe | L1+ | When PCI Express memory space is mapped as normal memory, the system must support unaligned accesses to that region. | 8.2 | yes | Linux driver | | 405 | PCIe | L3+ | In systems that are compatible with level 3 or above of the SBSA, the addresses sent by PCI express devices must be presented to the memory system or SMMU unmodified | 8.3 | yes | Linux driver | | 405 | PCIe | L0+ | In a system where the PCI express does not use an SMMU, the PCI express devices have the same view of physical memory as the PEs | 8.3 | yes | Linux driver | -| 405 | PCIe | L0+ | PCIe I/O Coherency Scenarios without System MMU are covered | 8.7.1 | yes | Linux driver | +| 405, 803 | PCIe | L0+ | PCIe I/O Coherency Scenarios without System MMU are covered | 8.7.1 | yes | Linux driver | | 405 | PCIe | L1+ | PCIe I/O Coherency Scenarios with System MMU are covered | 8.7.2 | yes | Linux driver | | 406 | PCIe | L0+ | In a system with a SMMU for PCI express there are no transformations to addresses being sent by PCI express devices before they are presented as an input address to the SMMU. | 8.3 | yes | Linux driver | | 406 | PCIe | L3+ | the addresses sent by PCI express devices must be presented to the memory system or SMMU unmodified | 4.4.8 | yes | Linux driver | | 407 | PCIe | L1+ | Support for Message Signaled Interrupts (MSI/MSI-X) is required for PCI Express devices. MSI and MSI-X are edge-triggered interrupts that are delivered as a memory write transaction | 8.4 | yes | Linux driver | -| 408 | PCIe | L1+ | each unique MSI(-X) shall trigger an interrupt with a unique ID and the MSI(-X) shall target GIC registers requiring no hardware specific software to service the interrupt | 8.4 | No | Linux driver | +| 408, 804 | PCIe | L1+ | each unique MSI(-X) shall trigger an interrupt with a unique ID and the MSI(-X) shall target GIC registers requiring no hardware specific software to service the interrupt | 8.4 | Yes | Linux driver | | | PCIe | L1+ | Add GICv2/v3 support details | 8.4.1/2 | No | Linux driver | | 409 | GICv3 | L2+ | All MSIs and MSI-x are mapped to LPI | 4.3.2 | yes | Linux driver | -| 410 | PCIe | L3+ | If the system supports PCIe PASID, then at least 16 bits of PASID must be supported | 8.11 | yes | Linux driver | +| 410, 805 | PCIe | L3+ | If the system supports PCIe PASID, then at least 16 bits of PASID must be supported | 8.11 | yes | Linux driver | | 411 | PCIe | L0+ | The PCI Express root complex is in the same Inner Shareable domain as the PEs | 8.7 | yes | Linux driver | -| 412 | PCIe | L1+ | Each of the 4 legacy interrupt lines must be allocated a unique SPI ID and is programmed as level sensitive | 8.5 | yes | Linux driver | +| 412, 806 | PCIe | L1+ | Each of the 4 legacy interrupt lines must be allocated a unique SPI ID and is programmed as level sensitive | 8.5 | yes | Linux driver | | 413 | MemoryMap | L3+ | All Non-secure on-chip masters in a base server system that are expected to be under the control of the OS or hypervisor must be capable of addressing all of the NS address space. If the master goes through a SMMU then it must be capable of addressing all of the NS address space when the SMMU is off. | 4.4.3 | yes | Linux driver | | 413 | MemoryMap / PCIe | L3+ | Non-secure off-chip devices that cannot directly address all of the Non-secure address space must be placed behind a stage 1 System MMU compatible with the ARM SMMUv2 or SMMUv3 specification. that has an output address size large enough to address all of the Non-secure address space. | 4.4.3 | yes | Linux driver | | 414 | Peripheral Subsystems | L3+ | Memory Attributes of DMA traffic are one of (1) Inner WB, Outer WB, Inner Shareable (2) Inner/Outer Non-Cacheable (3) Device TypeIO Coherent DMA is as per (1) Inner/Outer WB, Inner Shareable | 4.4.8 | yes | Linux driver | -| 415 | PCIe | L0+ | PCI Express transactions not marked as No_snoop accessing memory that the PE translation tables attribute as cacheable and shared are I/O Coherent with the PEs. | 8.7 | yes | Linux driver | +| 415, 807 | PCIe | L0+ | PCI Express transactions not marked as No_snoop accessing memory that the PE translation tables attribute as cacheable and shared are I/O Coherent with the PEs. | 8.7 | yes | Linux driver | | 416 | PCIe | L4+ | For Non-prefetchable (NP) memory, type-1 headers only support 32bit address, systems complaint with SBSA level 4 or above must support 32bit programming of NP BARs on such endpoints | D.2 | yes | Linux driver | | 504 | Watchdog | L1+ | Watchdog Signal 0 should be able to wakeup at least one PE from various low power states. Based off power states supported - this should be covered for 1 of N condition with some PEs in low power and from the lowest power stated where the Watchdog is ON. | 4.2.6 | yes | UEFI App | | 504 | System counter and generic timer | L1+ | Unless all local PE timers are Always ON, a system timer based on architecture memory mapped generic timer view shall generate an SPI that wake the platform from states with semantics B,C,D,E,F,H,I | 4.2.3 | yes | UEFI App | diff --git a/linux_app/sbsa-acs-app.bb b/linux_app/sbsa-acs-app.bb index 2a33e6a2..00be5336 100644 --- a/linux_app/sbsa-acs-app.bb +++ b/linux_app/sbsa-acs-app.bb @@ -14,14 +14,13 @@ SRC_URI = "file://sbsa_app_main.c \ file://sbsa_drv_intf.c \ file://include/sbsa_drv_intf.h \ file://include/sbsa_app.h \ - https://raw.githubusercontent.com/ARM-software/sbsa-acs/master/val/include/sbsa_avs_common.h \ + file://include/sbsa_avs_common.h \ " -SRC_URI[md5sum] = "67ac822ba7b3a74c355c81663d8c7f21" S = "${WORKDIR}" do_compile() { - ${CC} sbsa_app_main.c sbsa_app_pcie.c sbsa_drv_intf.c -o sbsa + ${CC} sbsa_app_main.c sbsa_app_pcie.c sbsa_drv_intf.c -Iinclude -o sbsa } do_install() { diff --git a/linux_app/sbsa-acs-app/Makefile b/linux_app/sbsa-acs-app/Makefile index d80ee354..2aad49c9 100644 --- a/linux_app/sbsa-acs-app/Makefile +++ b/linux_app/sbsa-acs-app/Makefile @@ -27,7 +27,7 @@ program_LIBRARY_DIRS := program_LIBRARIES := CC := $(CROSS_COMPILE)gcc -CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) -DTARGET_LINUX -g +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) -DTARGET_LINUX -g -Werror LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) diff --git a/linux_app/sbsa-acs-app/include/sbsa_app.h b/linux_app/sbsa-acs-app/include/sbsa_app.h index 91f6f5fa..0fcda231 100644 --- a/linux_app/sbsa-acs-app/include/sbsa_app.h +++ b/linux_app/sbsa-acs-app/include/sbsa_app.h @@ -21,7 +21,7 @@ #define SBSA_APP_VERSION_MAJOR 2 -#define SBSA_APP_VERSION_MINOR 0 +#define SBSA_APP_VERSION_MINOR 1 #include "sbsa_drv_intf.h" @@ -31,4 +31,7 @@ typedef unsigned char char8_t; int execute_tests_pcie(int num_pe, int level, unsigned int print_level); +int +execute_tests_exerciser(int num_pe, int level, unsigned int print_level); + #endif diff --git a/linux_app/sbsa-acs-app/include/sbsa_drv_intf.h b/linux_app/sbsa-acs-app/include/sbsa_drv_intf.h index 0db80daf..1ad7171d 100644 --- a/linux_app/sbsa-acs-app/include/sbsa_drv_intf.h +++ b/linux_app/sbsa-acs-app/include/sbsa_drv_intf.h @@ -25,6 +25,7 @@ #define SBSA_CREATE_INFO_TABLES 0x1000 #define SBSA_PCIE_EXECUTE_TEST 0x2000 #define SBSA_UPDATE_SKIP_LIST 0x3000 +#define SBSA_EXERCISER_EXECUTE_TEST 0x4000 #define SBSA_FREE_INFO_TABLES 0x9000 diff --git a/linux_app/sbsa-acs-app/sbsa_app_main.c b/linux_app/sbsa-acs-app/sbsa_app_main.c index 83c5ce79..c82a37f5 100644 --- a/linux_app/sbsa-acs-app/sbsa_app_main.c +++ b/linux_app/sbsa-acs-app/sbsa_app_main.c @@ -64,6 +64,7 @@ main (int argc, char **argv) int c = 0,i=0; char *endptr, *pt; int status; + int run_exerciser = 0; struct option long_opt[] = { @@ -73,7 +74,7 @@ main (int argc, char **argv) }; /* Process Command Line arguments */ - while ((c = getopt_long(argc, argv, "hv:l:", long_opt, NULL)) != -1) + while ((c = getopt_long(argc, argv, "hv:l:e:", long_opt, NULL)) != -1) { switch (c) { @@ -95,6 +96,9 @@ main (int argc, char **argv) pt = strtok(NULL, ","); } break; + case 'e': + run_exerciser = 1; + break; case '?': if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); @@ -122,9 +126,13 @@ main (int argc, char **argv) return 0; } - printf("\n *** Starting PCIe tests *** \n"); - execute_tests_pcie(1, g_sbsa_level, g_print_level); - + if (run_exerciser) { + printf("\n *** Starting PCIe Exerciser tests *** \n"); + execute_tests_exerciser(1, g_sbsa_level, g_print_level); + } else { + printf("\n *** Starting PCIe tests *** \n"); + execute_tests_pcie(1, g_sbsa_level, g_print_level); + } printf("\n *** SBSA tests complete *** \n\n"); diff --git a/linux_app/sbsa-acs-app/sbsa_app_pcie.c b/linux_app/sbsa-acs-app/sbsa_app_pcie.c index 06f9e799..60db6f34 100644 --- a/linux_app/sbsa-acs-app/sbsa_app_pcie.c +++ b/linux_app/sbsa-acs-app/sbsa_app_pcie.c @@ -26,7 +26,6 @@ #include "include/sbsa_app.h" #include "include/sbsa_drv_intf.h" -#include "sbsa_avs_common.h" extern int g_skip_test_num[3]; @@ -43,3 +42,14 @@ execute_tests_pcie(int num_pe, int level, unsigned int print_level) status = call_drv_wait_for_completion(); return status; } + +int +execute_tests_exerciser(int num_pe, int level, unsigned int print_level) +{ + + int status; + call_update_skip_list(SBSA_UPDATE_SKIP_LIST, g_skip_test_num); + call_drv_execute_test(SBSA_EXERCISER_EXECUTE_TEST, num_pe, level, print_level, 0); + status = call_drv_wait_for_completion(); + return status; +} diff --git a/platform/pal_uefi/include/pal_uefi.h b/platform/pal_uefi/include/pal_uefi.h index ca18a6c4..6e8b0f3b 100644 --- a/platform/pal_uefi/include/pal_uefi.h +++ b/platform/pal_uefi/include/pal_uefi.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -223,8 +223,10 @@ typedef union { ID_MAP map; }NODE_DATA_MAP; +#define MAX_NAMED_COMP_LENGTH 256 + typedef union { - CHAR8 name[16]; + CHAR8 name[MAX_NAMED_COMP_LENGTH]; IOVIRT_RC_INFO_BLOCK rc; IOVIRT_PMCG_INFO_BLOCK pmcg; UINT32 its_count; diff --git a/platform/pal_uefi/src/pal_iovirt.c b/platform/pal_uefi/src/pal_iovirt.c index 15719359..25548aea 100644 --- a/platform/pal_uefi/src/pal_iovirt.c +++ b/platform/pal_uefi/src/pal_iovirt.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -226,7 +226,7 @@ iort_add_block(IORT_TABLE *iort, IORT_NODE *iort_node, IOVIRT_INFO_TABLE *IoVirt sbsa_print(AVS_PRINT_INFO, L"IORT node offset:%x, type: %d\n", (UINT8*)iort_node - (UINT8*)iort, iort_node->type); - SetMem(data, 0, sizeof(NODE_DATA)); + SetMem(data, sizeof(NODE_DATA), 0); /* Populate the fields that are independent of node type */ (*block)->type = iort_node->type; @@ -244,7 +244,8 @@ iort_add_block(IORT_TABLE *iort, IORT_NODE *iort_node, IOVIRT_INFO_TABLE *IoVirt count = &IoVirtTable->num_its_groups; break; case IOVIRT_NODE_NAMED_COMPONENT: - AsciiStrnCpyS((CHAR8*)(*data).name, 16, (CHAR8*)((IORT_NAMED_COMPONENT*)node_data)->device_name, 16); + AsciiStrnCpyS((CHAR8*)(*data).name, MAX_NAMED_COMP_LENGTH, + (CHAR8*)((IORT_NAMED_COMPONENT*)node_data)->device_name, (MAX_NAMED_COMP_LENGTH -1)); count = &IoVirtTable->num_named_components; break; case IOVIRT_NODE_PCI_ROOT_COMPLEX: diff --git a/test_pool/Makefile b/test_pool/Makefile index ca79eb63..35676d68 100644 --- a/test_pool/Makefile +++ b/test_pool/Makefile @@ -32,7 +32,13 @@ sbsa_acs_test-objs += $(TEST_POOL)/pcie/test_p001.o \ $(TEST_POOL)/pcie/test_p009.o $(TEST_POOL)/pcie/test_p010.o \ $(TEST_POOL)/pcie/test_p011.o $(TEST_POOL)/pcie/test_p012.o \ $(TEST_POOL)/pcie/test_p013.o $(TEST_POOL)/pcie/test_p014.o \ - $(TEST_POOL)/pcie/test_p015.o $(TEST_POOL)/pcie/test_p016.o + $(TEST_POOL)/pcie/test_p015.o $(TEST_POOL)/pcie/test_p016.o \ + $(TEST_POOL)/pcie/test_p017.o $(TEST_POOL)/pcie/test_p018.o \ + $(TEST_POOL)/pcie/test_p019.o \ + $(TEST_POOL)/exerciser/test_e001.o $(TEST_POOL)/exerciser/test_e002.o \ + $(TEST_POOL)/exerciser/test_e003.o $(TEST_POOL)/exerciser/test_e004.o \ + $(TEST_POOL)/exerciser/test_e005.o $(TEST_POOL)/exerciser/test_e006.o \ + $(TEST_POOL)/exerciser/test_e007.o ccflags-y=-I$(PWD)/$(ACS_DIR)/.. -I$(PWD)/$(ACS_DIR)/val/ -I$(PWD)/$(ACS_DIR)/ -DTARGET_LINUX -Wall -Werror diff --git a/test_pool/exerciser/test_e001.c b/test_pool/exerciser/test_e001.c new file mode 100644 index 00000000..f9f1debf --- /dev/null +++ b/test_pool/exerciser/test_e001.c @@ -0,0 +1,108 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_pcie_enumeration.h" +#include "val/include/sbsa_avs_pcie.h" +#include "val/include/sbsa_avs_exerciser.h" + +#define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 1) +#define TEST_DESC "Enhanced ECAM Memory access check " + + +static +void +payload(void) +{ + + uint32_t pe_index; + uint32_t data; + uint32_t bdf; + uint32_t start_bus; + uint32_t start_segment; + uint32_t start_bdf; + uint32_t instance; + uint32_t reg_index; + exerciser_data_t e_data; + + pe_index = val_pe_get_index_mpid(val_pe_get_mpid()); + instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + + /* Set start_bdf segment and bus numbers to 1st ecam region values */ + start_segment = val_pcie_get_info(PCIE_INFO_SEGMENT, 0); + start_bus = val_pcie_get_info(PCIE_INFO_START_BUS, 0); + start_bdf = PCIE_CREATE_BDF(start_segment, start_bus, 0, 0); + + while (instance-- != 0) { + + if (val_exerciser_get_data(EXERCISER_DATA_CFG_SPACE, &e_data, instance)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %d data read error ", instance); + goto check_fail; + } + + bdf = val_pcie_get_bdf(EXERCISER_CLASSCODE, start_bdf); + start_bdf = val_pcie_increment_bdf(bdf); + + /* Check ECAM config register read/write */ + for (reg_index = 0; reg_index < TEST_REG_COUNT; reg_index++) { + + if (e_data.cfg_space.reg[reg_index].attribute == ACCESS_TYPE_RW) { + val_pcie_write_cfg(bdf, e_data.cfg_space.reg[reg_index].offset, e_data.cfg_space.reg[reg_index].value); + } + + if (val_pcie_read_cfg(bdf, e_data.cfg_space.reg[reg_index].offset, &data) == PCIE_READ_ERR) { + val_print(AVS_PRINT_ERR, "\n Exerciser %d cfg reg read error ", instance); + goto check_fail; + } + + if (data != e_data.cfg_space.reg[reg_index].value) { + val_print(AVS_PRINT_ERR, "\n Exerciser cfg reg read write mismatch %d ", data); + goto check_fail; + } + + } + + } + + val_set_status(pe_index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); + return; + +check_fail: + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + +} + +uint32_t +e001_entry(void) +{ + uint32_t num_pe = 1; + uint32_t status = AVS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) + val_run_test_payload(TEST_NUM, num_pe, payload, 0); + + /* Get the result from all PE and check for failure */ + status = val_check_for_error(TEST_NUM, num_pe); + + val_report_status(0, SBSA_AVS_END(g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/exerciser/test_e002.c b/test_pool/exerciser/test_e002.c new file mode 100644 index 00000000..f8e32323 --- /dev/null +++ b/test_pool/exerciser/test_e002.c @@ -0,0 +1,129 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_pcie.h" +#include "val/include/sbsa_avs_memory.h" +#include "val/include/sbsa_avs_pcie_enumeration.h" +#include "val/include/sbsa_avs_exerciser.h" + +#define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 2) +#define TEST_DESC "PCIe BAR access check " + +#define TEST_DATA 0xDEADDAED +static const ARM_NORMAL_MEM ARM_NORMAL_MEM_ARRAY[] = {NORMAL_NC, NORMAL_WT}; +static const ARM_DEVICE_MEM ARM_DEVICE_MEM_ARRAY[] = {DEVICE_nGnRnE, DEVICE_nGnRE, DEVICE_nGRE, DEVICE_GRE}; + +static +void +payload(void) +{ + char *baseptr; + uint32_t idx; + uint32_t pe_index; + uint32_t instance; + exerciser_data_t e_data; + + pe_index = val_pe_get_index_mpid(val_pe_get_mpid()); + + /* Read the number of excerciser cards */ + instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + + while (instance-- != 0) { + + /* Get BAR 0 details for this instance */ + if (val_exerciser_get_data(EXERCISER_DATA_BAR0_SPACE, &e_data, instance)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %d data read error ", instance); + goto test_fail; + } + + /* Map mmio space to ARM device memory in MMU page tables */ + for (idx = 0; idx < sizeof(ARM_DEVICE_MEM_ARRAY)/sizeof(ARM_DEVICE_MEM_ARRAY[0]); idx++) { + + baseptr = (char *)val_memory_ioremap((void *)e_data.bar_space.base_addr, + 512, + ARM_DEVICE_MEM_ARRAY[idx]); + if (!baseptr) { + val_print(AVS_PRINT_ERR, "\n Failed in BAR ioremap for instance %x", instance); + goto test_fail; + } + + /* Write predefined data to BAR space and read it back */ + val_mmio_write((addr_t)baseptr, TEST_DATA); + if (TEST_DATA != val_mmio_read((addr_t)baseptr)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %d BAR space access error %x", instance); + goto test_fail; + } + + /* Remove BAR mapping from MMU page tables */ + val_memory_unmap(baseptr); + } + + /* Do additional checks if the BAR is pcie prefetchable mmio space */ + if (e_data.bar_space.type == MMIO_PREFETCHABLE) { + + /* Map the mmio space to ARM normal memory in MMU page tables */ + for (idx = 0; idx < sizeof(ARM_NORMAL_MEM_ARRAY)/sizeof(ARM_NORMAL_MEM_ARRAY[0]); idx++) { + baseptr = (char *)val_memory_ioremap((void *)e_data.bar_space.base_addr, + 512, + ARM_NORMAL_MEM_ARRAY[idx]); + if (!baseptr) { + val_print(AVS_PRINT_ERR, "\n Failed in BAR ioremap for instance %x", instance); + goto test_fail; + } + + /* Write predefined data to an unaligned address in mmio space and read it back */ + val_mmio_write((addr_t)(baseptr+3), TEST_DATA); + if (TEST_DATA != val_mmio_read((addr_t)(baseptr+3))) { + val_print(AVS_PRINT_ERR, "\n Exerciser %d BAR space access error %x", instance); + goto test_fail; + } + + /* Remove BAR mapping from MMU page tables */ + val_memory_unmap(baseptr); + } + } + + } + + val_set_status(pe_index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); + return; + +test_fail: + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + +} + +uint32_t +e002_entry(void) +{ + uint32_t num_pe = 1; + uint32_t status = AVS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) + val_run_test_payload(TEST_NUM, num_pe, payload, 0); + + /* Get the result from all PE and check for failure */ + status = val_check_for_error(TEST_NUM, num_pe); + + val_report_status(0, SBSA_AVS_END(g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/exerciser/test_e003.c b/test_pool/exerciser/test_e003.c new file mode 100644 index 00000000..5e2817d8 --- /dev/null +++ b/test_pool/exerciser/test_e003.c @@ -0,0 +1,137 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_dma.h" +#include "val/include/sbsa_avs_smmu.h" +#include "val/include/sbsa_avs_memory.h" +#include "val/include/sbsa_avs_exerciser.h" + +#define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 3) +#define TEST_DESC "PCIe Address translation check " + +#define TEST_DATA_BLK_SIZE 512 +#define TEST_DATA 0xDE + +static +void +write_test_data(void *buf, uint32_t size) +{ + + uint32_t index; + + for (index = 0; index < size; index++) { + *((char8_t *)buf + index) = TEST_DATA; + } + +} + +static +void +payload(void) +{ + + uint32_t pe_index; + uint32_t dma_len; + uint32_t base_index; + uint32_t instance; + void *src_buf_virt; + void *src_buf_phys; + void *dest_buf_virt; + void *dest_buf_phys; + + src_buf_phys = NULL; + pe_index = val_pe_get_index_mpid(val_pe_get_mpid()); + + /* Read the number of excerciser cards */ + instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + + while (instance-- != 0) { + + for (base_index = 0; base_index < TEST_DDR_REGION_CNT; base_index++) { + + /* Get a Caheable DDR Buffer of size test data block size */ + src_buf_virt = val_memory_alloc(TEST_DATA_BLK_SIZE); + if (!src_buf_virt) { + val_print(AVS_PRINT_ERR, "\n Cacheable mem alloc failure %x", 02); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + } + + /* Set the virtual addresses for test buffers */ + src_buf_phys = val_memory_virt_to_phys(src_buf_virt); + dest_buf_virt = src_buf_virt + (TEST_DATA_BLK_SIZE / 2); + dest_buf_phys = src_buf_phys + (TEST_DATA_BLK_SIZE / 2); + dma_len = TEST_DATA_BLK_SIZE / 2; + + /* Initialize the sender buffer with test specific data */ + write_test_data(src_buf_virt, dma_len); + + /* Program Exerciser DMA controller with sender buffer information */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)src_buf_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_TO_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA write failure to exerciser %4x", instance); + goto test_fail; + } + + /* READ Back from Exerciser to validate above DMA write */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dest_buf_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_FROM_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA read failure from exerciser %4x", instance); + goto test_fail; + } + + if (memcmp(src_buf_virt, dest_buf_virt, dma_len)) { + val_print(AVS_PRINT_ERR, "\n Data Comparasion failure for Exerciser %4x", instance); + goto test_fail; + } + + /* Return the buffer to the heap manager */ + val_memory_free(src_buf_virt); + } + + } + + val_set_status(pe_index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); + return; + +test_fail: + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + val_memory_free(src_buf_virt); + return; + +} + + +uint32_t +e003_entry(void) +{ + uint32_t num_pe = 1; + uint32_t status = AVS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) + val_run_test_payload(TEST_NUM, num_pe, payload, 0); + + /* Get the result from all PE and check for failure */ + status = val_check_for_error(TEST_NUM, num_pe); + + val_report_status(0, SBSA_AVS_END(g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/exerciser/test_e004.c b/test_pool/exerciser/test_e004.c new file mode 100644 index 00000000..c28c966d --- /dev/null +++ b/test_pool/exerciser/test_e004.c @@ -0,0 +1,188 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_pcie_enumeration.h" +#include "val/include/sbsa_avs_pcie.h" +#include "val/include/sbsa_avs_exerciser.h" + +#define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 4) +#define TEST_DESC "Generate MSI(X) interrupts " + + +static uint32_t instance; +static uint32_t irq_num; +static uint32_t mapped_irq_num; +static uint32_t irq_pending; + +static +int +intr_handler(void) +{ + /* Call exerciser specific function to handle the interrupt */ + val_exerciser_ops(CLEAR_INTR, irq_num, instance); + + /* Clear the interrupt pending state */ + irq_pending = 0; + + val_print(AVS_PRINT_DEBUG, "\n Received MSI interrupt %d ", irq_num); + return 0; +} + +/** + @brief Free memory allocated for a list of MSI(X) vectors + + @param list pointer to a list of MSI(X) vectors +**/ +static +void +free_msi_list (PERIPHERAL_VECTOR_LIST *list) +{ + PERIPHERAL_VECTOR_LIST *next_node; + PERIPHERAL_VECTOR_LIST *current_node; + + current_node = list; + while (current_node != NULL) { + next_node = current_node->next; + kfree (current_node); + current_node = next_node; + } +} + +static +void +payload (void) +{ + + uint32_t count = val_peripheral_get_info (NUM_ALL, 0); + uint32_t index = val_pe_get_index_mpid (val_pe_get_mpid()); + uint8_t status; + PERIPHERAL_VECTOR_LIST *current_dev_mvec; + PERIPHERAL_VECTOR_LIST *next_dev_mvec; + uint32_t e_bdf = 0; + uint32_t start_bus; + uint32_t start_segment; + uint32_t start_bdf; + uint32_t irq_offset; + uint32_t timeout; + uint32_t ret_val; + PERIPHERAL_VECTOR_LIST *e_mvec; + PERIPHERAL_VECTOR_LIST *temp_mvec; + + if(!count) { + val_set_status (index, RESULT_SKIP (g_sbsa_level, TEST_NUM, 3)); + return; + } + + status = 0; + current_dev_mvec = NULL; + next_dev_mvec = NULL; + + /* Read the number of excerciser cards */ + instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + + /* Set start_bdf segment and bus numbers to 1st ecam region values */ + start_segment = val_pcie_get_info(PCIE_INFO_SEGMENT, 0); + start_bus = val_pcie_get_info(PCIE_INFO_START_BUS, 0); + start_bdf = PCIE_CREATE_BDF(start_segment, start_bus, 0, 0); + + while (instance-- != 0) { + + /* Get the exerciser BDF */ + e_bdf = val_pcie_get_bdf(EXERCISER_CLASSCODE, start_bdf); + start_bdf = val_pcie_increment_bdf(e_bdf); + + e_mvec = NULL; + + /* Read the MSI vectors for this exerciser instance */ + if (val_get_msi_vectors(e_bdf, &e_mvec)) { + + temp_mvec = e_mvec; + + while (e_mvec) { + + for (irq_offset = 0; irq_offset < e_mvec->vector.vector_n_irqs; irq_offset++) { + + irq_num = e_mvec->vector.vector_irq_base + irq_offset; + mapped_irq_num = e_mvec->vector.vector_mapped_irq_base + irq_offset; + + /* Register the interrupt handler */ + ret_val = val_gic_request_irq(irq_num, mapped_irq_num, intr_handler); + if (ret_val) { + val_print(AVS_PRINT_ERR, "\n IRQ registration failed for instance %4x", instance); + val_set_status(index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + free_msi_list(temp_mvec); + return; + } + + /* Set the interrupt trigger status to pending */ + irq_pending = 1; + + /* Trigger the interrupt */ + val_exerciser_ops(GENERATE_MSI, irq_num, instance); + + /* PE busy polls to check the completion of interrupt service routine */ + timeout = TIMEOUT_LARGE; + while ((--timeout > 0) && irq_pending); + + if (timeout == 0) { + val_print(AVS_PRINT_ERR, "\n Interrupt trigger failed for instance %4x ", instance); + val_set_status(index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + val_gic_free_interrupt(irq_num, mapped_irq_num); + free_msi_list(temp_mvec); + return; + } + + /* Return the interrupt */ + val_gic_free_interrupt(irq_num, mapped_irq_num); + } + + e_mvec = e_mvec->next; + } + + /* Return this instance dynamic memory to the heap manager */ + free_msi_list(temp_mvec); + + } else { + val_print(AVS_PRINT_ERR, "\n Failed to get MSI vectors for instance %4x", instance); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + } + + } + +} + +uint32_t +e004_entry (void) +{ + uint32_t num_pe = 1; + uint32_t status = AVS_STATUS_FAIL; + + status = val_initialize_test (TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) { + val_run_test_payload (TEST_NUM, num_pe, payload, 0); + } + + /* Get the result from all PE and check for failure */ + status = val_check_for_error (TEST_NUM, num_pe); + + val_report_status (0, SBSA_AVS_END (g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/exerciser/test_e005.c b/test_pool/exerciser/test_e005.c new file mode 100644 index 00000000..6a437949 --- /dev/null +++ b/test_pool/exerciser/test_e005.c @@ -0,0 +1,186 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_smmu.h" +#include "val/include/sbsa_avs_pcie_enumeration.h" +#include "val/include/sbsa_avs_pcie.h" +#include "val/include/sbsa_avs_memory.h" +#include "val/include/sbsa_avs_exerciser.h" + +#define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 5) +#define TEST_DESC "Generate PASID PCIe transactions " + +#define MIN_PASID_SUPPORT (1 << 16) +#define TEST_DATA_BLK_SIZE 512 +#define TEST_DATA 0xDE + +void write_source_buf_data(void *buf, uint32_t size) +{ + + uint32_t index; + + for (index = 0; index < size; index++) { + *((char8_t *)buf + index) = TEST_DATA; + } + +} + +static void +payload(void) +{ + uint32_t pe_index; + uint32_t instance; + uint64_t e_bdf; + uint32_t e_valid_cnt; + uint32_t e_pasid; + uint64_t e_pasid_support; + uint32_t start_bus; + uint32_t start_segment; + uint32_t start_bdf; + uint32_t dma_len; + void *src_buf_virt; + void *src_buf_phys; + void *dest_buf_virt; + void *dest_buf_phys; + + e_valid_cnt = 0; + src_buf_virt = NULL; + pe_index = val_pe_get_index_mpid (val_pe_get_mpid()); + instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + + /* Set start_bdf segment and bus numbers to 1st ecam region values */ + start_segment = val_pcie_get_info(PCIE_INFO_SEGMENT, 0); + start_bus = val_pcie_get_info(PCIE_INFO_START_BUS, 0); + start_bdf = PCIE_CREATE_BDF(start_segment, start_bus, 0, 0); + + while (instance-- != 0) { + + /* Get exerciser bdf */ + e_bdf = val_pcie_get_bdf(EXERCISER_CLASSCODE, start_bdf); + start_bdf = val_pcie_increment_bdf(e_bdf); + + /* Check if exerciser and it's root port have PASID TLP Prefix support */ + val_exerciser_get_param(PASID_ATTRIBUTES, &e_bdf, &e_pasid_support, instance); + if(e_pasid_support == 0) { + continue; + } + + /* Increment the exerciser count with pasid support */ + e_valid_cnt++; + + /* Program exerciser and it's root port to start sending TLPs + * with PASID TLP Prefixes. This includes setting PASID Enable bit + * in exerciser PASID Control register and the implementation specific + * PASID Enable bit of the Root Port. + */ + if(val_exerciser_ops(PASID_TLP_START, (uint64_t)&e_pasid, instance)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %x PASID TLP Prefix enable error", instance); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + } + + /* Check if exerciser PASID is of minimum 16-bits width */ + if(e_pasid < MIN_PASID_SUPPORT) { + val_print(AVS_PRINT_ERR, "\n Exerciser %x PASID less than 16-bits width", instance); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + } + + /* Get a Caheable DDR Buffer of size test data block size */ + src_buf_virt = val_memory_alloc(TEST_DATA_BLK_SIZE); + if (!src_buf_virt) { + val_print(AVS_PRINT_ERR, "\n Cacheable mem alloc failure %x", 02); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + } + + /* Set the virtual addresses for test buffers */ + src_buf_phys = val_memory_virt_to_phys(src_buf_virt); + dest_buf_virt = src_buf_virt + (TEST_DATA_BLK_SIZE / 2); + dest_buf_phys = src_buf_phys + (TEST_DATA_BLK_SIZE / 2); + dma_len = TEST_DATA_BLK_SIZE / 2; + + /* Initialize the source buffer with test specific data */ + write_source_buf_data(src_buf_virt, dma_len); + + /* Program Exerciser DMA controller with the source buffer information */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)src_buf_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_TO_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA write failure to exerciser %4x", instance); + goto test_fail; + } + + /* READ Back from Exerciser to validate above DMA write */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dest_buf_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_FROM_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA read failure from exerciser %4x", instance); + goto test_fail; + } + + /* Disbale exerciser and it's root port to stop sending TLPs + * with PASID TLP Prefixes. This includes re-setting PASID Enable bit + * in exerciser PASID Control register and the implementation specific + * PASID Enable bit of the Root Port. + */ + if(val_exerciser_ops(PASID_TLP_STOP, (uint64_t)&e_pasid, instance)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %x PASID TLP Prefix disable error", instance); + goto test_fail; + } + + if (memcmp(src_buf_virt, dest_buf_virt, dma_len)) { + val_print(AVS_PRINT_ERR, "\n Data Comparison failure for Exerciser %4x", instance); + goto test_fail; + } + + } + + if (e_valid_cnt) { + val_memory_free(src_buf_virt); + val_set_status (pe_index, RESULT_PASS (g_sbsa_level, TEST_NUM, 01)); + } else { + val_set_status(pe_index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 00)); + } + + return; + +test_fail: + val_memory_free(src_buf_virt); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02));; + return; + +} + +uint32_t +e005_entry(void) +{ + uint32_t num_pe = 1; + uint32_t status = AVS_STATUS_FAIL; + + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) + val_run_test_payload(TEST_NUM, num_pe, payload, 0); + + /* Get the result from all PE and check for failure */ + status = val_check_for_error(TEST_NUM, num_pe); + + val_report_status(0, SBSA_AVS_END(g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/exerciser/test_e006.c b/test_pool/exerciser/test_e006.c new file mode 100644 index 00000000..c9613dca --- /dev/null +++ b/test_pool/exerciser/test_e006.c @@ -0,0 +1,192 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_pcie_enumeration.h" +#include "val/include/sbsa_avs_pcie.h" +#include "val/include/sbsa_avs_memory.h" +#include "val/include/sbsa_avs_exerciser.h" + +#define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 6) +#define TEST_DESC "Generate PCIe legacy interrupts " + +static uint32_t instance; +static uint32_t e_intr_line; +static uint32_t e_intr_pending; + +static void intr_handler(void) +{ + /* Call exerciser specific function to handle the interrupt */ + val_exerciser_ops(CLEAR_INTR, e_intr_line, instance); + + /* Clear the interrupt pending state */ + e_intr_pending = 0; + + val_print(AVS_PRINT_DEBUG, "\n Received legacy interrupt %d", e_intr_line); +} + +static +void +payload (void) +{ + + uint32_t pe_index; + uint8_t status; + uint32_t e_bdf; + uint32_t erp_bdf; + uint32_t e_valid_cnt; + uint32_t start_segment; + uint32_t start_bus; + uint32_t start_bdf; + uint8_t e_intr_pin; + uint8_t e_intr_line; + uint32_t ret_val; + uint32_t timeout; + PERIPHERAL_IRQ_MAP *erp_intr_map; + + status = 0; + e_valid_cnt = 0; + pe_index = val_pe_get_index_mpid(val_pe_get_mpid()); + + /* Read the number of excerciser cards */ + instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + + /* Set start_bdf segment and bus numbers to 1st ecam region values */ + start_segment = val_pcie_get_info(PCIE_INFO_SEGMENT, 0); + start_bus = val_pcie_get_info(PCIE_INFO_START_BUS, 0); + start_bdf = PCIE_CREATE_BDF(start_segment, start_bus, 0, 0); + + while (instance-- != 0) { + + /* Get the exerciser BDF */ + e_bdf = val_pcie_get_bdf(EXERCISER_CLASSCODE, start_bdf); + start_bdf = val_pcie_increment_bdf(e_bdf); + + /* Read exerciser Interrupt Pin register. A value of 00h + * indicates that the function uses no legacy interrupt + * Message(s). If a device implements a single legacy + * interrupt message, it must be INTA; if it implements + * two legacy interrupt messages, they must be INTA and + * INTB; and so forth. + */ + val_pci_read_config_byte(e_bdf, PCIE_INTERRUPT_PIN, &e_intr_pin); + + /* Read exerciser interrupt line routing information + * from Interrupt Line register. Values in this register + * are programmed by system software and are system + * architecture specific. + */ + if (e_intr_pin) { + val_pci_read_config_byte(e_bdf, PCIE_INTERRUPT_LINE, &e_intr_line); + } else { + continue; + } + + /* Increment the exerciser count with legacy interrupt support */ + e_valid_cnt++; + + /* Derive exerciser root port (ERP) bdf */ + erp_bdf = e_bdf; + if(val_pcie_get_root_port_bdf(&erp_bdf)) { + val_print(AVS_PRINT_ERR, "\n ERP %x BDF fetch error", instance); + val_set_status(pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + return; + } + + /* Allocate memory for interrupt mappings */ + erp_intr_map = val_memory_alloc(sizeof(PERIPHERAL_IRQ_MAP)); + if (!erp_intr_map) { + val_print (AVS_PRINT_ERR, "\n Memory allocation error", 00); + val_set_status(pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + return; + } + + /* Read ERP legacy interrupt mappings */ + status = val_pci_get_legacy_irq_map(erp_bdf, erp_intr_map); + + if (!status) { + + /* Register an interrupt handler to verify legacy interrupt functionality */ + ret_val = val_gic_install_isr(e_intr_line, intr_handler); + if (ret_val) + goto test_fail; + + /* Set the interrupt trigger status to pending */ + e_intr_pending = 1; + + /* Trigger the legacy interrupt */ + val_exerciser_ops(GENERATE_L_INTR, e_intr_line, instance); + + /* PE busy polls to check the completion of interrupt service routine */ + timeout = TIMEOUT_LARGE; + while ((--timeout > 0) && e_intr_pending); + + if (timeout == 0) { + val_gic_free_interrupt(e_intr_line, 0); + val_print(AVS_PRINT_ERR, "\n Interrupt trigger failed for instance %4x ", instance); + goto test_fail; + } + + /* Return the interrupt */ + val_gic_free_interrupt(e_intr_line, 0); + + } + + /* Return the interrupt mapping space to the Heap */ + val_memory_free(erp_intr_map); + + } + + if (!e_valid_cnt) { + val_set_status(pe_index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 00)); + return; + } + + if (!status) { + val_set_status (pe_index, RESULT_PASS (g_sbsa_level, TEST_NUM, 01)); + } else { + val_set_status (pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + } + + return; + +test_fail: + val_set_status(pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + val_memory_free(erp_intr_map); + return; + +} + +uint32_t +e006_entry (void) +{ + uint32_t num_pe = 1; + uint32_t status = AVS_STATUS_FAIL; + + status = val_initialize_test (TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) { + val_run_test_payload (TEST_NUM, num_pe, payload, 0); + } + + /* Get the result from all PE and check for failure */ + status = val_check_for_error (TEST_NUM, num_pe); + + val_report_status (0, SBSA_AVS_END (g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/exerciser/test_e007.c b/test_pool/exerciser/test_e007.c new file mode 100644 index 00000000..3e64014e --- /dev/null +++ b/test_pool/exerciser/test_e007.c @@ -0,0 +1,163 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" +#include "val/include/sbsa_avs_memory.h" +#include "val/include/sbsa_avs_exerciser.h" + +#include "val/include/sbsa_avs_pcie.h" +#include "val/include/sbsa_avs_pcie_enumeration.h" + +#define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 7) +#define TEST_DESC "Check PCI Express I/O Coherency " + +#define TEST_DATA_BLK_SIZE 512 +#define TEST_DATA 0xDE + +#define MEM_ATTR_CACHEABLE_SHAREABLE 0 +#define MEM_ATTR_NON_CACHEABLE 1 + +void init_source_buf_data(void *buf, uint32_t size) +{ + + uint32_t index; + + for (index = 0; index < size; index++) { + *((char8_t *)buf + index) = TEST_DATA; + } + +} + +static +void +payload (void) +{ + + uint32_t pe_index; + uint32_t instance; + uint32_t dma_len; + uint32_t e_bdf; + uint32_t start_segment; + uint32_t start_bus; + uint32_t start_bdf; + void *e_dev; + void *src_buf_virt; + void *src_buf_phys; + void *dest_buf_virt; + void *dest_buf_phys; + + e_dev = NULL; + src_buf_virt = NULL; + src_buf_phys = NULL; + pe_index = val_pe_get_index_mpid (val_pe_get_mpid()); + + /* Read the number of excerciser cards */ + instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + + /* Set start_bdf segment and bus numbers to 1st ecam region values */ + start_segment = val_pcie_get_info(PCIE_INFO_SEGMENT, 0); + start_bus = val_pcie_get_info(PCIE_INFO_START_BUS, 0); + start_bdf = PCIE_CREATE_BDF(start_segment, start_bus, 0, 0); + + while (instance-- != 0) { + + /* Get the exerciser BDF */ + e_bdf = val_pcie_get_bdf(EXERCISER_CLASSCODE, start_bdf); + start_bdf = val_pcie_increment_bdf(e_bdf); + + /* Derive exerciser device structure from its bdf */ + e_dev = val_pci_bdf_to_dev(e_bdf); + + /* Get a non-caheable DDR Buffer of size TEST_DATA_BLK_SIZE */ + src_buf_virt = val_memory_alloc_coherent(e_dev, TEST_DATA_BLK_SIZE, src_buf_phys); + if (!src_buf_virt) { + val_print(AVS_PRINT_ERR, "\n Non-cacheable mem alloc failure %x", 02); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + } + + /* Program exerciser to start sending TLPs with No Snoop attribute header. + * This includes setting Enable No snoop bit in exerciser control register. + */ + if(val_exerciser_ops(NO_SNOOP_TLP_START, 0, instance)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %x No Snoop enable error", instance); + goto test_fail; + } + + /* Set VA and PA addresses for the destination buffer and DMA size */ + dest_buf_virt = src_buf_virt + (TEST_DATA_BLK_SIZE / 2); + dest_buf_phys = src_buf_phys + (TEST_DATA_BLK_SIZE / 2); + dma_len = TEST_DATA_BLK_SIZE / 2; + + /* Initialize source buffer with test specific data */ + init_source_buf_data(src_buf_virt, dma_len); + + /* Program Exerciser DMA controller with the source buffer information */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)src_buf_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_TO_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA write failure to exerciser %4x", instance); + goto test_fail; + } + + /* READ Back from Exerciser to validate above DMA write */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dest_buf_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_FROM_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA read failure from exerciser %4x", instance); + goto test_fail; + } + + if (memcmp(src_buf_virt, dest_buf_virt, dma_len)) { + val_print(AVS_PRINT_ERR, "\n I/O coherency failure for Exerciser %4x", instance); + goto test_fail; + } + + /* Stop exerciser sending TLPs with No Snoop attribute header */ + if (val_exerciser_ops(NO_SNOOP_TLP_STOP, 0, instance)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %x No snoop TLP disable error", instance); + goto test_fail; + } + + } + + val_set_status(pe_index, RESULT_PASS(g_sbsa_level, TEST_NUM, 0)); + val_memory_free_coherent(e_dev, TEST_DATA_BLK_SIZE, src_buf_virt, src_buf_phys); + return; + +test_fail: + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + val_memory_free_coherent(e_dev, TEST_DATA_BLK_SIZE, src_buf_virt, src_buf_phys); + return; +} + +uint32_t +e007_entry (void) +{ + uint32_t num_pe = 1; + uint32_t status = AVS_STATUS_FAIL; + + status = val_initialize_test (TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) { + val_run_test_payload (TEST_NUM, num_pe, payload, 0); + } + + /* Get the result from all PE and check for failure */ + status = val_check_for_error (TEST_NUM, num_pe); + + val_report_status (0, SBSA_AVS_END (g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/pcie/test_p007.c b/test_pool/pcie/test_p007.c index 9c7094ea..74bfb9e2 100644 --- a/test_pool/pcie/test_p007.c +++ b/test_pool/pcie/test_p007.c @@ -54,7 +54,7 @@ payload(void) data = val_peripheral_get_info(ANY_FLAGS, count); if ((data & PER_FLAG_MSI_ENABLED) == 0) { - val_print(AVS_STATUS_ERR, "\n MSI should be enabled for a PCIe device ", 0); + val_print(AVS_PRINT_ERR, "\n MSI should be enabled for a PCIe device ", 0); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); status = 1; break; diff --git a/test_pool/pcie/test_p012.c b/test_pool/pcie/test_p012.c index 7ad8d905..8b25b1fb 100644 --- a/test_pool/pcie/test_p012.c +++ b/test_pool/pcie/test_p012.c @@ -55,7 +55,7 @@ payload (void) irq_map = kzalloc(sizeof(PERIPHERAL_IRQ_MAP), GFP_KERNEL); if (!irq_map) { - val_print (AVS_STATUS_ERR, "\n Memory allocation error", 0); + val_print (AVS_PRINT_ERR, "\n Memory allocation error", 0); val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 01)); return; } @@ -110,8 +110,8 @@ payload (void) if (irq_map->legacy_irq_map[current_irq_pin].irq_list[ccnt] == irq_map->legacy_irq_map[next_irq_pin].irq_list[ncnt]) { status = 7; - val_print (AVS_STATUS_ERR, "\n Legacy interrupt %c routing", pin_name(current_irq_pin)); - val_print (AVS_STATUS_ERR, "\n is the same as %c routing", pin_name(next_irq_pin)); + val_print (AVS_PRINT_ERR, "\n Legacy interrupt %c routing", pin_name(current_irq_pin)); + val_print (AVS_PRINT_ERR, "\n is the same as %c routing", pin_name(next_irq_pin)); } } } diff --git a/test_pool/pcie/test_p013.c b/test_pool/pcie/test_p013.c index 03b7d685..f705ace4 100644 --- a/test_pool/pcie/test_p013.c +++ b/test_pool/pcie/test_p013.c @@ -61,10 +61,10 @@ payload (void) data = val_pcie_is_devicedma_64bit(dev_bdf); if (data == 0) { if(!val_pcie_is_device_behind_smmu(dev_bdf)) { - val_print (AVS_STATUS_ERR, "\n WARNING:The device with bdf=0x%x doesn't support 64 bit addressing", dev_bdf); - val_print (AVS_STATUS_ERR, "\n and is not behind SMMU. Please install driver for this device and", 0); - val_print (AVS_STATUS_ERR, "\n test again. If driver is already installed, this test has failed.", 0); - val_print (AVS_STATUS_ERR, "\n The device is of type = %d", dev_type); + val_print (AVS_PRINT_ERR, "\n WARNING:The device with bdf=0x%x doesn't support 64 bit addressing", dev_bdf); + val_print (AVS_PRINT_ERR, "\n and is not behind SMMU. Please install driver for this device and", 0); + val_print (AVS_PRINT_ERR, "\n test again. If driver is already installed, this test has failed.", 0); + val_print (AVS_PRINT_ERR, "\n The device is of type = %d", dev_type); val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 1)); return; } diff --git a/test_pool/pcie/test_p015.c b/test_pool/pcie/test_p015.c index b27b04c0..af14ee8a 100644 --- a/test_pool/pcie/test_p015.c +++ b/test_pool/pcie/test_p015.c @@ -69,7 +69,7 @@ payload (void) } if(no_snoop_set) { - val_print (AVS_STATUS_ERR, "\n PCIe no snoop bit set to %d for a device with coherent DMA", no_snoop_set); + val_print (AVS_PRINT_ERR, "\n PCIe no snoop bit set to %d for a device with coherent DMA", no_snoop_set); val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 1)); } else { val_set_status (index, RESULT_PASS (g_sbsa_level, TEST_NUM, status)); diff --git a/test_pool/pcie/test_p016.c b/test_pool/pcie/test_p016.c index 6d6f7120..ceaa9474 100644 --- a/test_pool/pcie/test_p016.c +++ b/test_pool/pcie/test_p016.c @@ -55,7 +55,7 @@ static void payload(void) /* Allow only type-1 headers and skip others */ if (dev_type != 3) continue; - ret = val_pcie_io_read_cfg(dev_bdf, BAR0, &bar_data); + ret = val_pcie_read_cfg(dev_bdf, BAR0, &bar_data); if (bar_data) { /* Extract pref type */ data = VAL_EXTRACT_BITS(bar_data, 3, 3); @@ -64,7 +64,7 @@ static void payload(void) /* Extract mem type */ data = VAL_EXTRACT_BITS(bar_data, 1, 2); if (data != 0) { - val_print(AVS_STATUS_ERR, "\n NP type-1 pcie is not 32-bit mem type", 0); + val_print(AVS_PRINT_ERR, "\n NP type-1 pcie is not 32-bit mem type", 0); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); status = 2; break; @@ -72,7 +72,7 @@ static void payload(void) /* Scan the all PCIe bridge devices and check memory type */ ret = val_pcie_scan_bridge_devices_and_check_memtype(dev_bdf); if (ret) { - val_print(AVS_STATUS_ERR, "\n NP type-1 pcie bridge end device" + val_print(AVS_PRINT_ERR, "\n NP type-1 pcie bridge end device" "is not 32-bit mem type", 0); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); status = 2; diff --git a/test_pool/pcie/test_p017.c b/test_pool/pcie/test_p017.c new file mode 100644 index 00000000..bdf5b975 --- /dev/null +++ b/test_pool/pcie/test_p017.c @@ -0,0 +1,121 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_pcie.h" + +#define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 17) +#define TEST_DESC "Root port must implement minimal ACS features if P2P supported" + +static void payload(void) +{ + uint32_t index; + uint32_t count; + uint32_t valid_cnt; + uint8_t data; + uint16_t acs_data; + uint32_t pcie_type; + uint64_t dev_bdf; + + index = val_pe_get_index_mpid(val_pe_get_mpid()); + + valid_cnt = 0; + count = val_peripheral_get_info(NUM_ALL, 0); + if (!count) { + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); + return; + } + + while (count > 0) { + count--; + dev_bdf = val_peripheral_get_info(ANY_BDF, count); + + /* get the PCIe device/port type */ + pcie_type = val_pcie_get_pcie_type(dev_bdf); + if (pcie_type == PCIE_TYPE_ROOT_PORT) { + /* check if root port supports peer to peer */ + if (val_pcie_p2p_support(dev_bdf)) + continue; + + valid_cnt++; + val_pcie_read_ext_cap_word(dev_bdf, PCI_EXT_CAPID_ACS, PCI_CAPID_ACS, &acs_data); + if (!acs_data) + goto test_fail; + /* Extract ACS source validation bit */ + data = VAL_EXTRACT_BITS(acs_data, 0, 0); + if (!data) { + val_print(AVS_PRINT_ERR, "\n Source validation not supported", 0); + goto test_fail; + } + /* Extract ACS translation blocking bit */ + data = VAL_EXTRACT_BITS(acs_data, 1, 1); + if (!data) { + val_print(AVS_PRINT_ERR, "\n Translation blocking not supported", 0); + goto test_fail; + } + /* Extract ACS P2P request redirect bit */ + data = VAL_EXTRACT_BITS(acs_data, 2, 2); + if (!data) { + val_print(AVS_PRINT_ERR, "\n P2P request redirect not supported", 0); + goto test_fail; + } + /* Extract ACS P2P completion redirect bit */ + data = VAL_EXTRACT_BITS(acs_data, 3, 3); + if (!data) { + val_print(AVS_PRINT_ERR, "\n P2P completion redirect not supported", 0); + goto test_fail; + } + /* Extract ACS upstream forwarding bit */ + data = VAL_EXTRACT_BITS(acs_data, 4, 4); + if (!data) { + val_print(AVS_PRINT_ERR, "\n Upstream forwarding not supported", 0); + goto test_fail; + } + } else { + continue; + } + } + + if (!valid_cnt) { + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); + return; + } + + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); + return; + +test_fail: + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); +} + +uint32_t p017_entry(uint32_t num_pe) +{ + uint32_t status = AVS_STATUS_FAIL; + + /* This test is run on single processor */ + num_pe = 1; + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) + val_run_test_payload(TEST_NUM, num_pe, payload, 0); + + /* get the result from all PE and check for failure */ + status = val_check_for_error(TEST_NUM, num_pe); + val_report_status(0, SBSA_AVS_END(g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/pcie/test_p018.c b/test_pool/pcie/test_p018.c new file mode 100644 index 00000000..170b02e8 --- /dev/null +++ b/test_pool/pcie/test_p018.c @@ -0,0 +1,127 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_pcie.h" + +#define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 18) +#define TEST_DESC "All switches must implement minimal ACS features if P2P supported" + +static void payload(void) +{ + uint32_t index; + uint32_t count; + uint32_t valid_cnt; + uint8_t data; + uint16_t acs_data; + uint32_t pcie_type; + uint64_t dev_bdf; + + index = val_pe_get_index_mpid(val_pe_get_mpid()); + + valid_cnt = 0; + count = val_peripheral_get_info(NUM_ALL, 0); + if (!count) { + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); + return; + } + + while (count > 0) { + count--; + dev_bdf = val_peripheral_get_info(ANY_BDF, count); + + /* get the PCIe device/port type */ + pcie_type = val_pcie_get_pcie_type(dev_bdf); + if (pcie_type == PCIE_TYPE_DOWNSTREAM) { + /* check if switch supports peer to peer */ + if (val_pcie_p2p_support(dev_bdf)) + continue; + + valid_cnt++; + val_pcie_read_ext_cap_word(dev_bdf, PCI_EXT_CAPID_ACS, PCI_CAPID_ACS, &acs_data); + if (!acs_data) + goto test_fail; + /* Extract ACS source validation bit */ + data = VAL_EXTRACT_BITS(acs_data, 0, 0); + if (!data) { + val_print(AVS_PRINT_ERR, "\n Source validation not supported", 0); + goto test_fail; + } + /* Extract ACS translation blocking bit */ + data = VAL_EXTRACT_BITS(acs_data, 1, 1); + if (!data) { + val_print(AVS_PRINT_ERR, "\n Translation blocking not supported", 0); + goto test_fail; + } + /* Extract ACS P2P request redirect bit */ + data = VAL_EXTRACT_BITS(acs_data, 2, 2); + if (!data) { + val_print(AVS_PRINT_ERR, "\n P2P request redirect not supported", 0); + goto test_fail; + } + /* Extract ACS P2P completion redirect bit */ + data = VAL_EXTRACT_BITS(acs_data, 3, 3); + if (!data) { + val_print(AVS_PRINT_ERR, "\n P2P completion redirect not supported", 0); + goto test_fail; + } + /* Extract ACS upstream forwarding bit */ + data = VAL_EXTRACT_BITS(acs_data, 4, 4); + if (!data) { + val_print(AVS_PRINT_ERR, "\n Upstream forwarding not supported", 0); + goto test_fail; + } + /* Extract ACS direct translated P2P bit */ + data = VAL_EXTRACT_BITS(acs_data, 6, 6); + if (!data) { + val_print(AVS_PRINT_ERR, "\n Direct translated P2P not supported", 0); + goto test_fail; + } + } else { + continue; + } + } + + if (!valid_cnt) { + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); + return; + } + + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); + return; + +test_fail: + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); +} + +uint32_t p018_entry(uint32_t num_pe) +{ + uint32_t status = AVS_STATUS_FAIL; + + /* This test is run on single processor */ + num_pe = 1; + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) + val_run_test_payload(TEST_NUM, num_pe, payload, 0); + + /* get the result from all PE and check for failure */ + status = val_check_for_error(TEST_NUM, num_pe); + val_report_status(0, SBSA_AVS_END(g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/test_pool/pcie/test_p019.c b/test_pool/pcie/test_p019.c new file mode 100644 index 00000000..57763204 --- /dev/null +++ b/test_pool/pcie/test_p019.c @@ -0,0 +1,106 @@ +/** @file + * Copyright (c) 2018, 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/sbsa_avs_val.h" +#include "val/include/val_interface.h" + +#include "val/include/sbsa_avs_pcie.h" + +#define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 19) +#define TEST_DESC "Multifunction devices must implement minimal ACS features if P2P supported" + +static void payload(void) +{ + uint32_t index; + uint32_t count; + uint32_t valid_cnt; + uint8_t data; + uint16_t acs_data; + uint32_t pcie_type; + uint64_t dev_bdf; + + index = val_pe_get_index_mpid(val_pe_get_mpid()); + + valid_cnt = 0; + count = val_peripheral_get_info(NUM_ALL, 0); + if (!count) { + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); + return; + } + + while (count > 0) { + count--; + dev_bdf = val_peripheral_get_info(ANY_BDF, count); + + /* get the PCIe device/port type */ + pcie_type = val_pcie_get_pcie_type(dev_bdf); + if (pcie_type == PCIE_TYPE_ENDPOINT || + pcie_type == PCIE_TYPE_LEG_END || + pcie_type == PCIE_TYPE_UPSTREAM|| + pcie_type == PCIE_TYPE_RC_END) { + /* check if device supports multifunction */ + if (val_pcie_multifunction_support(dev_bdf)) + continue; + + /* check if PCIe device supports peer to peer */ + if (val_pcie_p2p_support(dev_bdf)) + continue; + + valid_cnt++; + val_pcie_read_ext_cap_word(dev_bdf, PCI_EXT_CAPID_ACS, PCI_CAPID_ACS, &acs_data); + if (!acs_data) { + val_print(AVS_PRINT_WARN, "\n ACS feature not supported", 0); + return; + } + /* Extract ACS P2P request redirect bit */ + data = VAL_EXTRACT_BITS(acs_data, 2, 2); + if (!data) { + val_print(AVS_PRINT_WARN, "\n P2P request redirect not supported", 0); + } + /* Extract ACS P2P completion redirect bit */ + data = VAL_EXTRACT_BITS(acs_data, 3, 3); + if (!data) { + val_print(AVS_PRINT_WARN, "\n P2P completion redirect not supported", 0); + } + /* Extract ACS direct translated P2P bit */ + data = VAL_EXTRACT_BITS(acs_data, 6, 6); + if (!data) { + val_print(AVS_PRINT_WARN, "\n Direct translated P2P not supported", 0); + } + } else { + continue; + } + } + + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); +} + +uint32_t p019_entry(uint32_t num_pe) +{ + uint32_t status = AVS_STATUS_FAIL; + + /* This test is run on single processor */ + num_pe = 1; + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe, g_sbsa_level); + if (status != AVS_STATUS_SKIP) + val_run_test_payload(TEST_NUM, num_pe, payload, 0); + + /* get the result from all PE and check for failure */ + status = val_check_for_error(TEST_NUM, num_pe); + val_report_status(0, SBSA_AVS_END(g_sbsa_level, TEST_NUM)); + + return status; +} diff --git a/uefi_app/SbsaAvs.h b/uefi_app/SbsaAvs.h index 22eadf97..10a6c4bc 100755 --- a/uefi_app/SbsaAvs.h +++ b/uefi_app/SbsaAvs.h @@ -21,7 +21,7 @@ #define SBSA_ACS_MAJOR_VER 2 - #define SBSA_ACS_MINOR_VER 0 + #define SBSA_ACS_MINOR_VER 1 #define G_SBSA_LEVEL 3 #define SBSA_MAX_LEVEL_SUPPORTED 5 diff --git a/val/Makefile b/val/Makefile index 829f05a9..17b77fe4 100644 --- a/val/Makefile +++ b/val/Makefile @@ -27,7 +27,7 @@ obj-m += sbsa_acs_val.o sbsa_acs_val-objs += $(VAL_SRC)/avs_status.o $(VAL_SRC)/avs_memory.o \ $(VAL_SRC)/avs_peripherals.o $(VAL_SRC)/avs_dma.o $(VAL_SRC)/avs_smmu.o \ $(VAL_SRC)/avs_test_infra.o $(VAL_SRC)/avs_pcie.o $(VAL_SRC)/avs_pe_infra.o \ - $(VAL_SRC)/avs_iovirt.o + $(VAL_SRC)/avs_iovirt.o $(VAL_SRC)/avs_gic_support.o $(VAL_SRC)/avs_exerciser.o ccflags-y=-I$(PWD)/$(ACS_DIR)/include -I$(PWD)/$(ACS_DIR)/ -DTARGET_LINUX -Wall -Werror diff --git a/val/include/pal_interface.h b/val/include/pal_interface.h index 06f322dd..251026fe 100755 --- a/val/include/pal_interface.h +++ b/val/include/pal_interface.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -108,6 +108,14 @@ typedef enum { ENTRY_TYPE_GICITS }GIC_INFO_TYPE_e; +/* Interrupt Trigger Type */ +typedef enum { + INTR_TRIGGER_INFO_LEVEL_LOW, + INTR_TRIGGER_INFO_LEVEL_HIGH, + INTR_TRIGGER_INFO_EDGE_FALLING, + INTR_TRIGGER_INFO_EDGE_RISING +}INTR_TRIGGER_INFO_TYPE_e; + /** @brief structure instance for GIC entry **/ @@ -126,7 +134,10 @@ typedef struct { void pal_gic_create_info_table(GIC_INFO_TABLE *gic_info_table); uint32_t pal_gic_install_isr(uint32_t int_id, void (*isr)(void)); -uint32_t pal_gic_end_of_interrupt(uint32_t int_id); +void pal_gic_end_of_interrupt(uint32_t int_id); +uint32_t pal_gic_request_irq(unsigned int irq_num, unsigned int mapped_irq_num, void *isr); +void pal_gic_free_interrupt(unsigned int irq_num, unsigned int mapped_irq_num); +uint32_t pal_gic_set_intr_trigger(uint32_t int_id, INTR_TRIGGER_INFO_TYPE_e trigger_type); /** Timer tests related definitions **/ @@ -224,6 +235,15 @@ typedef struct { uint64_t pal_pcie_get_mcfg_ecam(void); void pal_pcie_create_info_table(PCIE_INFO_TABLE *PcieTable); uint32_t pal_pcie_read_cfg(uint32_t bdf, uint32_t offset, uint32_t *data); +uint32_t pal_pcie_get_bdf_wrapper(uint32_t class_code, uint32_t start_bdf); +void *pal_pci_bdf_to_dev(uint32_t bdf); +void pal_pci_read_config_byte(uint32_t bdf, uint8_t offset, uint8_t *val); +void pal_pci_write_config_byte(uint32_t bdf, uint8_t offset, uint8_t val); +void pal_pcie_read_ext_cap_word(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn, + uint32_t ext_cap_id, uint8_t offset, uint16_t *val); +uint32_t pal_pcie_get_pcie_type(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn); +uint32_t pal_pcie_p2p_support(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn); +uint32_t pal_pcie_multifunction_support(uint32_t seg, uint32_t bus, uint32_t dev, uint32_t fn); /** @brief Instance of SMMU INFO block @@ -272,8 +292,10 @@ typedef union { ID_MAP map; }NODE_DATA_MAP; +#define MAX_NAMED_COMP_LENGTH 256 + typedef union { - char name[16]; + char name[MAX_NAMED_COMP_LENGTH]; IOVIRT_RC_INFO_BLOCK rc; IOVIRT_PMCG_INFO_BLOCK pmcg; uint32_t its_count; @@ -377,6 +399,7 @@ typedef struct { uint32_t vector_control; ///< IRQ to install an ISR uint32_t vector_irq_base; ///< Base IRQ for the vectors in the block uint32_t vector_n_irqs; ///< Number of irq vectors in the block + uint32_t vector_mapped_irq_base; ///< Mapped IRQ number base for this MSI }PERIPHERAL_VECTOR_BLOCK; typedef struct PERIPHERAL_VECTOR_LIST_STRUCT @@ -482,8 +505,11 @@ void pal_print(char8_t *string, uint64_t data); void pal_print_raw(uint64_t addr, char8_t *string, uint64_t data); -void *pal_mem_alloc(uint32_t size); +void *pal_mem_alloc(uint32_t size); +void *pal_mem_alloc_coherent(void *dev, unsigned int size, void *pa); void pal_mem_free(void *buffer); +void pal_mem_free_coherent(void *dev, unsigned int size, void *va, void *pa); +void *pal_mem_virt_to_phys(void *va); void pal_mem_allocate_shared(uint32_t num_pe, uint32_t sizeofentry); void pal_mem_free_shared(void); @@ -501,5 +527,118 @@ void pal_pe_data_cache_ops_by_va(uint64_t addr, uint32_t type); #define CLEAN 0x2 #define INVALIDATE 0x3 +/* Exerciser definitions */ +#define EXERCISER_CLASSCODE 0x010203 +#define MAX_ARRAY_SIZE 32 +#define TEST_REG_COUNT 10 +#define TEST_DDR_REGION_CNT 5 + +typedef struct { + uint64_t buf[MAX_ARRAY_SIZE]; +} EXERCISER_INFO_BLOCK; + +typedef struct { + uint32_t num_exerciser_cards; + EXERCISER_INFO_BLOCK info[]; //Array of information blocks - per stimulus generation controller +} EXERCISER_INFO_TABLE; + +typedef enum { + EXERCISER_NUM_CARDS = 0x1 +} EXERCISER_INFO_TYPE; + +typedef enum { + EDMA_NO_SUPPORT = 0x0, + EDMA_COHERENT = 0x1, + EDMA_NOT_COHERENT = 0x2, + EDMA_FROM_DEVICE = 0x3, + EDMA_TO_DEVICE = 0x4 +} EXERCISER_DMA_ATTR; + +typedef enum { + SNOOP_ATTRIBUTES = 0x1, + LEGACY_IRQ = 0x2, + MSIX_ATTRIBUTES = 0x3, + DMA_ATTRIBUTES = 0x4, + P2P_ATTRIBUTES = 0x5, + PASID_ATTRIBUTES = 0x6 +} EXERCISER_PARAM_TYPE; + +typedef enum { + EXERCISER_RESET = 0x1, + EXERCISER_ON = 0x2, + EXERCISER_OFF = 0x3, + EXERCISER_ERROR = 0x4 +} EXERCISER_STATE; + +typedef enum { + START_DMA = 0x1, + GENERATE_MSI = 0x2, + GENERATE_L_INTR = 0x3, //Legacy interrupt + MEM_READ = 0x4, + MEM_WRITE = 0x5, + CLEAR_INTR = 0x6, + PASID_TLP_START = 0x7, + PASID_TLP_STOP = 0x8, + NO_SNOOP_TLP_START = 0x9, + NO_SNOOP_TLP_STOP = 0xa +} EXERCISER_OPS; + +typedef enum { + ACCESS_TYPE_RD = 0x0, + ACCESS_TYPE_RW = 0x1 +} ECAM_REG_ATTRIBUTE; + +struct ecam_reg_data { + uint32_t offset; //Offset into 4096 bytes ecam config reg space + uint32_t attribute; + uint32_t value; +}; + +struct exerciser_data_cfg_space { + struct ecam_reg_data reg[TEST_REG_COUNT]; +}; + +typedef enum { + DEVICE_nGnRnE = 0x0, + DEVICE_nGnRE = 0x1, + DEVICE_nGRE = 0x2, + DEVICE_GRE = 0x3 +} ARM_DEVICE_MEM; + +typedef enum { + NORMAL_NC = 0x4, + NORMAL_WT = 0x5 +} ARM_NORMAL_MEM; + +typedef enum { + MMIO_PREFETCHABLE = 0x0, + MMIO_NON_PREFETCHABLE = 0x1 +} BAR_MEM_TYPE; + +struct exerciser_data_bar_space { + void *base_addr; + BAR_MEM_TYPE type; +}; + +typedef union exerciser_data { + struct exerciser_data_cfg_space cfg_space; + struct exerciser_data_bar_space bar_space; +} exerciser_data_t; + +typedef enum { + EXERCISER_DATA_CFG_SPACE = 0x1, + EXERCISER_DATA_BAR0_SPACE = 0x2, +} EXERCISER_DATA_TYPE; + + +void pal_exerciser_create_info_table(EXERCISER_INFO_TABLE *exerciser_info_table); +uint32_t pal_exerciser_get_info(EXERCISER_INFO_TYPE type, uint32_t instance); +uint32_t pal_exerciser_set_param(EXERCISER_PARAM_TYPE type, uint64_t value1, uint64_t value2, uint32_t instance); +uint32_t pal_exerciser_get_param(EXERCISER_PARAM_TYPE type, uint64_t *value1, uint64_t *value2, uint32_t instance); +uint32_t pal_exerciser_set_state(EXERCISER_STATE state, uint64_t *value, uint32_t instance); +uint32_t pal_exerciser_get_state(EXERCISER_STATE state, uint64_t *value, uint32_t instance); +uint32_t pal_exerciser_ops(EXERCISER_OPS ops, uint64_t param, uint32_t instance); +uint32_t pal_exerciser_get_data(EXERCISER_DATA_TYPE type, exerciser_data_t *data, uint32_t instance); + #endif diff --git a/val/include/sbsa_avs_common.h b/val/include/sbsa_avs_common.h index c133201a..efe0cf65 100755 --- a/val/include/sbsa_avs_common.h +++ b/val/include/sbsa_avs_common.h @@ -33,6 +33,7 @@ #define AVS_WAKEUP_TEST_NUM_BASE 500 #define AVS_PER_TEST_NUM_BASE 600 #define AVS_SMMU_TEST_NUM_BASE 700 +#define AVS_EXERCISER_TEST_NUM_BASE 800 #define AVS_SECURE_TEST_NUM_BASE 900 #define STATE_BIT 28 diff --git a/val/include/sbsa_avs_exerciser.h b/val/include/sbsa_avs_exerciser.h new file mode 100644 index 00000000..fc0787b8 --- /dev/null +++ b/val/include/sbsa_avs_exerciser.h @@ -0,0 +1,40 @@ +/** @file + * Copyright (c) 2016-2018, 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. + **/ + +#ifndef __SBSA_AVS_EXERCISER_H__ +#define __SBSA_AVS_EXERCISER_H__ + +void val_exerciser_create_info_table(EXERCISER_INFO_TABLE *exerciser_info_table); +uint32_t val_exerciser_get_info(EXERCISER_INFO_TYPE type, uint32_t instance); +uint32_t val_exerciser_set_param(EXERCISER_PARAM_TYPE type, uint64_t value1, uint64_t value2, uint32_t instance); +uint32_t val_exerciser_get_param(EXERCISER_PARAM_TYPE type, uint64_t *value1, uint64_t *value2, uint32_t instance); +uint32_t val_exerciser_set_state(EXERCISER_STATE state, uint64_t *value, uint32_t instance); +uint32_t val_exerciser_get_state(EXERCISER_STATE state, uint64_t *value, uint32_t instance); +uint32_t val_exerciser_ops(EXERCISER_OPS ops, uint64_t param, uint32_t instance); +uint32_t val_exerciser_get_data(EXERCISER_DATA_TYPE type, exerciser_data_t *data, uint32_t instance); +uint32_t val_exerciser_execute_tests(uint32_t level); + + +uint32_t e001_entry(void); +uint32_t e002_entry(void); +uint32_t e003_entry(void); +uint32_t e004_entry(void); +uint32_t e005_entry(void); +uint32_t e006_entry(void); +uint32_t e007_entry(void); + +#endif diff --git a/val/include/sbsa_avs_gic.h b/val/include/sbsa_avs_gic.h index f60f995a..ce12cd15 100644 --- a/val/include/sbsa_avs_gic.h +++ b/val/include/sbsa_avs_gic.h @@ -32,6 +32,14 @@ #ifndef __SBSA_AVS_GIC_H__ #define __SBSA_AVS_GIC_H__ +#define GICD_ISENABLER 0x100 +#define GICD_ICENABLER 0x180 +#define GICD_ISPENDR 0x200 +#define GICD_ISACTIVER0 0x300 +#define GICD_ICPENDR0 0x280 +#define GICD_ICACTIVER0 0x380 +#define GICD_IROUTER 0x6000 + uint32_t g001_entry(uint32_t num_pe); uint32_t @@ -41,4 +49,9 @@ g003_entry(uint32_t num_pe); uint32_t g004_entry(uint32_t num_pe); +uint32_t +val_get_max_intid(void); + +addr_t +val_get_gicd_base(void); #endif diff --git a/val/include/sbsa_avs_memory.h b/val/include/sbsa_avs_memory.h index 09f2f342..3870412f 100644 --- a/val/include/sbsa_avs_memory.h +++ b/val/include/sbsa_avs_memory.h @@ -1,26 +1,30 @@ -/** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. +/** @file + * Copyright (c) 2016-2018, 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. -**/ - -#ifndef __SBSA_AVS_MEMORY_H__ -#define __SBSA_AVS_MEMORY_H__ - -addr_t val_memory_ioremap(void *addr, uint32_t size, uint64_t attr); - -void val_memory_unmap(void *ptr); - - -#endif // __SBSA_AVS_PERIPHERAL_H__ + + * 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. +**/ + +#ifndef __SBSA_AVS_MEMORY_H__ +#define __SBSA_AVS_MEMORY_H__ + +addr_t val_memory_ioremap(void *addr, uint32_t size, uint64_t attr); + +void val_memory_unmap(void *ptr); +void *val_memory_alloc(uint32_t size); +void *val_memory_alloc_coherent(void *dev, uint32_t size, void *pa); +void val_memory_free(void *addr); +void val_memory_free_coherent(void *dev, uint32_t size, void *va, void *pa); +void *val_memory_virt_to_phys(void *va); + +#endif // __SBSA_AVS_PERIPHERAL_H__ diff --git a/val/include/sbsa_avs_pcie.h b/val/include/sbsa_avs_pcie.h index bad6554b..106900d4 100644 --- a/val/include/sbsa_avs_pcie.h +++ b/val/include/sbsa_avs_pcie.h @@ -29,6 +29,18 @@ #define PCIE_MAX_DEV 32 #define PCIE_MAX_FUNC 8 +#define PCIE_INTERRUPT_LINE 0x3c +#define PCIE_INTERRUPT_PIN 0x3d + +#define PCIE_TYPE_ROOT_PORT 0x04 /* Root Port */ +#define PCIE_TYPE_DOWNSTREAM 0x06 /* Downstream Port */ +#define PCIE_TYPE_ENDPOINT 0x0 /* Express Endpoint */ +#define PCIE_TYPE_LEG_END 0x01 /* Legacy Endpoint */ +#define PCIE_TYPE_UPSTREAM 0x05 /* Upstream Port */ +#define PCIE_TYPE_RC_END 0x09 /* Root Complex Integrated Endpoint */ +#define PCI_EXT_CAPID_ACS 0x0D /* Access Control Services */ +#define PCI_CAPID_ACS 0x04 /* ACS Capability Register */ + void val_pcie_write_cfg(uint32_t bdf, uint32_t offset, uint32_t data); uint32_t val_pcie_read_cfg(uint32_t bdf, uint32_t offset, uint32_t *data); uint32_t val_get_msi_vectors (uint32_t bdf, PERIPHERAL_VECTOR_LIST **mvector); @@ -69,6 +81,12 @@ val_pcie_get_dma_coherent(uint32_t bdf); uint32_t val_pcie_io_read_cfg(uint32_t bdf, uint32_t offset, uint32_t *data); +void +val_pci_read_config_byte(uint32_t bdf, uint8_t offset, uint8_t *val); + +void +val_pci_write_config_byte(uint32_t bdf, uint8_t offset, uint8_t val); + uint32_t p001_entry(uint32_t num_pe); @@ -114,5 +132,15 @@ p014_entry (uint32_t num_pe); uint32_t p015_entry (uint32_t num_pe); -uint32_t p016_entry (uint32_t num_pe); +uint32_t +p016_entry (uint32_t num_pe); + +uint32_t +p017_entry (uint32_t num_pe); + +uint32_t +p018_entry (uint32_t num_pe); + +uint32_t +p019_entry (uint32_t num_pe); #endif diff --git a/val/include/sbsa_avs_pcie_enumeration.h b/val/include/sbsa_avs_pcie_enumeration.h index cfc19593..87b2e218 100644 --- a/val/include/sbsa_avs_pcie_enumeration.h +++ b/val/include/sbsa_avs_pcie_enumeration.h @@ -98,3 +98,7 @@ typedef struct { PCI_BRIDGE_CONTROL_REGISTER Bridge; } PCI_TYPE01; +uint32_t val_pcie_increment_busdev(uint32_t start_bdf); +uint32_t val_pcie_increment_bdf(uint32_t bdf); +uint32_t val_pcie_get_bdf(uint32_t class_code, uint32_t start_bdf); +void *val_pci_bdf_to_dev(uint32_t bdf); diff --git a/val/include/val_interface.h b/val/include/val_interface.h index 062ca90d..ed2697db 100644 --- a/val/include/val_interface.h +++ b/val/include/val_interface.h @@ -83,6 +83,9 @@ uint32_t val_gic_route_interrupt_to_pe(uint32_t int_id, uint64_t mpidr); uint32_t val_gic_get_interrupt_state(uint32_t int_id); void val_gic_clear_interrupt(uint32_t int_id); void val_gic_cpuif_init(void); +uint32_t val_gic_request_irq(uint32_t irq_num, uint32_t mapped_irq_num, void *isr); +void val_gic_free_interrupt(uint32_t irq_num, uint32_t mapped_irq_num); +void val_gic_set_intr_trigger(uint32_t int_id, INTR_TRIGGER_INFO_TYPE_e trigger_type); /*TIMER VAL APIs */ typedef enum { @@ -124,7 +127,8 @@ typedef enum { WD_INFO_CTRL_BASE, WD_INFO_REFRESH_BASE, WD_INFO_GSIV, - WD_INFO_ISSECURE + WD_INFO_ISSECURE, + WD_INFO_IS_EDGE }WD_INFO_TYPE_e; void val_wd_create_info_table(uint64_t *wd_info_table); @@ -140,6 +144,10 @@ void val_pcie_free_info_table(void); uint32_t val_pcie_execute_tests(uint32_t level, uint32_t num_pe); uint32_t val_pcie_is_devicedma_64bit(uint32_t bdf); uint32_t val_pcie_scan_bridge_devices_and_check_memtype(uint32_t bdf); +void val_pcie_read_ext_cap_word(uint32_t bdf, uint32_t ext_cap_id, uint8_t offset, uint16_t *val); +uint32_t val_pcie_get_pcie_type(uint32_t bdf); +uint32_t val_pcie_p2p_support(uint32_t bdf); +uint32_t val_pcie_multifunction_support(uint32_t bdf); /* IO-VIRT APIs */ typedef enum { diff --git a/val/src/avs_exerciser.c b/val/src/avs_exerciser.c new file mode 100644 index 00000000..ebad2ba3 --- /dev/null +++ b/val/src/avs_exerciser.c @@ -0,0 +1,161 @@ +/** @file + * Copyright (c) 2016-2018, 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/sbsa_avs_val.h" +#include "include/sbsa_avs_exerciser.h" + +/** + @brief This API popultaes information from all the PCIe stimulus generation IP available + in the system into exerciser_info_table structure + @param exerciser_info_table - Table pointer to be filled by this API + @return exerciser_info_table - Contains info to communicate with stimulus generation hardware +**/ +void val_exerciser_create_info_table(EXERCISER_INFO_TABLE *exerciser_info_table) +{ + pal_exerciser_create_info_table(exerciser_info_table); +} + +/** + @brief This API returns the requested information about the PCIe stimulus hardware + @param type - Information type required from the stimulus hadrware + @param instance - Stimulus hadrware instance number + @return value - Information value for input type +**/ +uint32_t val_exerciser_get_info(EXERCISER_INFO_TYPE type, uint32_t instance) +{ + return pal_exerciser_get_info(type, instance); +} + +/** + @brief This API writes the configuration parameters of the PCIe stimulus generation hardware + @param type - Parameter type that needs to be set in the stimulus hadrware + @param value1 - Parameter 1 that needs to be set + @param value2 - Parameter 2 that needs to be set + @param instance - Stimulus hardware instance number + @return status - SUCCESS if the input paramter type is successfully written +**/ +uint32_t val_exerciser_set_param(EXERCISER_PARAM_TYPE type, uint64_t value1, uint64_t value2, uint32_t instance) +{ + return pal_exerciser_set_param(type, value1, value2, instance); +} + +/** + @brief This API reads the configuration parameters of the PCIe stimulus generation hardware + @param type - Parameter type that needs to be read from the stimulus hadrware + @param value1 - Parameter 1 that is read from hardware + @param value2 - Parameter 2 that is read from hardware + @param instance - Stimulus hardware instance number + @return status - SUCCESS if the requested paramter type is successfully read +**/ +uint32_t val_exerciser_get_param(EXERCISER_PARAM_TYPE type, uint64_t *value1, uint64_t *value2, uint32_t instance) +{ + return pal_exerciser_get_param(type, value1, value2, instance); +} + +/** + @brief This API sets the state of the PCIe stimulus generation hardware + @param state - State that needs to be set for the stimulus hadrware + @param value - Additional information associated with the state + @param instance - Stimulus hardware instance number + @return status - SUCCESS if the input state is successfully written to hardware +**/ +uint32_t val_exerciser_set_state(EXERCISER_STATE state, uint64_t *value, uint32_t instance) +{ + return pal_exerciser_set_state(state, value, instance); +} + +/** + @brief This API obtains the state of the PCIe stimulus generation hardware + @param state - State that is read from the stimulus hadrware + @param value - Additional information associated with the state + @param instance - Stimulus hardware instance number + @return status - SUCCESS if the state is successfully read from hardware +**/ +uint32_t val_exerciser_get_state(EXERCISER_STATE state, uint64_t *value, uint32_t instance) +{ + return pal_exerciser_get_state(state, value, instance); +} + +/** + @brief This API performs the input operation using the PCIe stimulus generation hardware + @param ops - Operation thta needs to be performed with the stimulus hadrware + @param value - Additional information to perform the operation + @param instance - Stimulus hardware instance number + @return status - SUCCESS if the operation is successfully performed using the hardware +**/ +uint32_t val_exerciser_ops(EXERCISER_OPS ops, uint64_t param, uint32_t instance) +{ + return pal_exerciser_ops(ops, param, instance); +} + +/** + @brief This API returns test specific data from the PCIe stimulus generation hardware + @param type - data type for which the data needs to be returned + @param data - test specific data to be be filled by pal layer + @param instance - Stimulus hardware instance number + @return status - SUCCESS if the requested data is successfully filled +**/ +uint32_t val_exerciser_get_data(EXERCISER_DATA_TYPE type, exerciser_data_t *data, uint32_t instance) +{ + return pal_exerciser_get_data(type, data, instance); +} + +/** + @brief This API executes all the Exerciser tests sequentially + 1. Caller - Application layer. + @param level - level of compliance being tested for. + @return Consolidated status of all the tests run. +**/ +uint32_t +val_exerciser_execute_tests(uint32_t level) +{ + uint32_t status, i; + uint32_t num_instances; + + if (level <= 3) { + val_print(AVS_PRINT_WARN, "Exerciser Sbsa compliance is only from Level %d \n", 4); + return AVS_STATUS_SKIP; + } + + for (i = 0; i < MAX_TEST_SKIP_NUM; i++){ + if (g_skip_test_num[i] == AVS_EXERCISER_TEST_NUM_BASE) { + val_print(AVS_PRINT_TEST, "\n USER Override - Skipping three Exerciser tests \n", 0); + return AVS_STATUS_SKIP; + } + } + + num_instances = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + if (num_instances == 0) { + val_print(AVS_PRINT_INFO, " No exerciser cards in the system %x", 0); + return AVS_STATUS_SKIP; + } + + status = e001_entry(); + status |= e002_entry(); + status |= e003_entry(); + status |= e004_entry(); + status |= e005_entry(); + status |= e006_entry(); + status |= e007_entry(); + + if (status != AVS_STATUS_PASS) { + val_print(AVS_PRINT_ERR, "\n One or more Exerciser tests have failed.... \n", status); + } + + return status; +} + diff --git a/val/src/avs_gic.c b/val/src/avs_gic.c index a2ae094b..99163e83 100644 --- a/val/src/avs_gic.c +++ b/val/src/avs_gic.c @@ -60,7 +60,6 @@ val_gic_execute_tests(uint32_t level, uint32_t num_pe) status |= g004_entry(num_pe); } - if (status != AVS_STATUS_PASS) val_print(AVS_PRINT_ERR, "\n One or more GIC tests failed. Check Log \n", 0); else @@ -191,36 +190,6 @@ val_get_max_intid(void) return 32 * ((val_mmio_read(val_get_gicd_base() + 0x004) & 0x1F) + 1); } -/** - @brief This function is installs the ISR pointed by the function pointer - the input Interrupt ID. - 1. Caller - Test Suite - 2. Prerequisite - val_gic_create_info_table - @param int_id Interrupt ID to install the ISR - @param isr Function pointer of the ISR - @return status -**/ -uint32_t -val_gic_install_isr(uint32_t int_id, void (*isr)(void)) -{ - uint32_t reg_offset = int_id / 32; - uint32_t reg_shift = int_id % 32; - if ((int_id > val_get_max_intid()) || (int_id == 0)) { - val_print(AVS_PRINT_ERR, "\n Invalid Interrupt ID number %d ", int_id); - return AVS_STATUS_ERR; - } - - pal_gic_install_isr(int_id, isr); - - if (int_id > 31) { - /**** UEFI GIC code is not enabling interrupt in the Distributor ***/ - /**** So, do this here as a fail-safe. Remove if PAL guarantees this ***/ - val_mmio_write(val_get_gicd_base() + GICD_ISENABLER + (4 * reg_offset), 1 << reg_shift); - } - - return 0; -} - /** @brief This function writes to end of interrupt register for relevant interrupt group. @@ -311,3 +280,22 @@ void val_gic_cpuif_init(void) val_gic_reg_write(ICC_BPR1_EL1, 0x7); val_gic_reg_write(ICC_PMR_EL1, 0xff); } + +/** + @brief This function will Set the trigger type Edge/Level based on the GTDT table + 1. Caller - Test Suite + 2. Prerequisite - val_gic_create_info_table + @param int_id Interrupt ID + @param trigger_type Interrupt Trigger Type + @return none +**/ +void val_gic_set_intr_trigger(uint32_t int_id, INTR_TRIGGER_INFO_TYPE_e trigger_type) +{ + uint32_t status; + + val_print(AVS_PRINT_DEBUG, "\n Setting Trigger type as %d ", trigger_type); + status = pal_gic_set_intr_trigger(int_id, trigger_type); + + if (status) + val_print(AVS_PRINT_ERR, "\n Error Could Not Configure Trigger Type", 0); +} diff --git a/val/src/avs_gic_support.c b/val/src/avs_gic_support.c index 7088dd51..dede14cd 100644 --- a/val/src/avs_gic_support.c +++ b/val/src/avs_gic_support.c @@ -13,13 +13,15 @@ * 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/sbsa_avs_val.h" +#include "include/sbsa_avs_gic.h" #include "include/sbsa_avs_gic_support.h" #include "include/sbsa_avs_common.h" +#ifndef TARGET_LINUX /** @brief This API provides a 'C' interface to call GIC System register reads 1. Caller - Test Suite @@ -43,6 +45,7 @@ val_gic_reg_read(uint32_t reg_id) return 0x0; } + /** @brief This API provides a 'C' interface to call GIC System register writes 1. Caller - Test Suite @@ -73,4 +76,63 @@ val_gic_reg_write(uint32_t reg_id, uint64_t write_data) } } +#endif +/** + @brief This function is installs the ISR pointed by the function pointer + the input Interrupt ID. + 1. Caller - Test Suite + 2. Prerequisite - val_gic_create_info_table + @param int_id Interrupt ID to install the ISR + @param isr Function pointer of the ISR + @return status +**/ +uint32_t +val_gic_install_isr(uint32_t int_id, void (*isr)(void)) +{ + uint32_t ret_val; +#ifndef TARGET_LINUX + uint32_t reg_offset = int_id / 32; + uint32_t reg_shift = int_id % 32; + + if ((int_id > val_get_max_intid()) || (int_id == 0)) { + val_print(AVS_PRINT_ERR, "\n Invalid Interrupt ID number %d ", int_id); + return AVS_STATUS_ERR; + } +#endif + + ret_val = pal_gic_install_isr(int_id, isr); + +#ifndef TARGET_LINUX + if (int_id > 31) { + /**** UEFI GIC code is not enabling interrupt in the Distributor ***/ + /**** So, do this here as a fail-safe. Remove if PAL guarantees this ***/ + val_mmio_write(val_get_gicd_base() + GICD_ISENABLER + (4 * reg_offset), 1 << reg_shift); + } +#endif + + return ret_val; +} + +/** + * @brief This function registers the specified interrupt + * @param irq_num hardware irq number + * @param mapped_irq_num Mapped irq number + * @param isr Interrupt service routine + * @return status + */ +uint32_t val_gic_request_irq(uint32_t irq_num, uint32_t mapped_irq_num, void *isr) +{ + return pal_gic_request_irq(irq_num, mapped_irq_num, isr); +} + +/** + * @brief This function free the registered interrupt line + * @param irq_num hardware irq number + * @param mapped_irq_num Mapped irq number + * @return none + */ +void val_gic_free_interrupt(uint32_t irq_num, uint32_t mapped_irq_num) +{ + pal_gic_free_interrupt(irq_num, mapped_irq_num); +} diff --git a/val/src/avs_memory.c b/val/src/avs_memory.c index da5eae01..e63b526d 100644 --- a/val/src/avs_memory.c +++ b/val/src/avs_memory.c @@ -179,3 +179,33 @@ val_memory_unmap(void *ptr) { pal_memory_unmap(ptr); } + +void * +val_memory_alloc(uint32_t size) +{ + return pal_mem_alloc(size); +} + +void * +val_memory_alloc_coherent(void *dev, uint32_t size, void *pa) +{ + return pal_mem_alloc_coherent(dev, size, pa); +} + +void +val_memory_free(void *addr) +{ + pal_mem_free(addr); +} + +void +val_memory_free_coherent(void *dev, uint32_t size, void *va, void *pa) +{ + pal_mem_free_coherent(dev, size, va, pa); +} + +void * +val_memory_virt_to_phys(void *va) +{ + return pal_mem_virt_to_phys(va); +} diff --git a/val/src/avs_pcie.c b/val/src/avs_pcie.c index e6eedfcf..1c96a7b0 100644 --- a/val/src/avs_pcie.c +++ b/val/src/avs_pcie.c @@ -203,14 +203,26 @@ val_pcie_execute_tests(uint32_t level, uint32_t num_pe) status |= p006_entry(num_pe); status |= p007_entry(num_pe); status |= p008_entry(num_pe); - status |= p009_entry(num_pe); - status |= p010_entry(num_pe); status |= p011_entry(num_pe); status |= p012_entry(num_pe); - status |= p013_entry(num_pe); - status |= p014_entry(num_pe); status |= p015_entry(num_pe); - status |= p016_entry(num_pe); + + if (level > 1) { + status |= p009_entry(num_pe); + } + + if (level > 2) { + status |= p010_entry(num_pe); + status |= p013_entry(num_pe); + status |= p014_entry(num_pe); + } + + if (level > 3) { + status |= p016_entry(num_pe); + status |= p017_entry(num_pe); + status |= p018_entry(num_pe); + status |= p019_entry(num_pe); + } #endif if (status != AVS_STATUS_PASS) { @@ -408,6 +420,7 @@ val_pcie_get_root_port_bdf(uint32_t *bdf) *bdf = PCIE_CREATE_BDF(seg, bus, dev, func); return 0; } + /** @brief This API returns the PCIe device type 1. Caller - Test Suite @@ -424,6 +437,51 @@ val_pcie_get_device_type(uint32_t bdf) PCIE_EXTRACT_BDF_FUNC (bdf)); } +/** + @brief This API checks the PCIe device P2P support + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @return 1 - P2P feature not supported 0 - P2P feature supported +**/ +uint32_t +val_pcie_p2p_support(uint32_t bdf) +{ + return pal_pcie_p2p_support(PCIE_EXTRACT_BDF_SEG (bdf), + PCIE_EXTRACT_BDF_BUS (bdf), + PCIE_EXTRACT_BDF_DEV (bdf), + PCIE_EXTRACT_BDF_FUNC (bdf)); +} + +/** + @brief This API checks the PCIe device multifunction support + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @return 1 - Multifunction not supported 0 - Multifunction supported +**/ +uint32_t +val_pcie_multifunction_support(uint32_t bdf) +{ + return pal_pcie_multifunction_support(PCIE_EXTRACT_BDF_SEG (bdf), + PCIE_EXTRACT_BDF_BUS (bdf), + PCIE_EXTRACT_BDF_DEV (bdf), + PCIE_EXTRACT_BDF_FUNC (bdf)); +} + +/** + @brief This API returns the PCIe device/port type + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @return Returns the PCIe device/port type +**/ +uint32_t +val_pcie_get_pcie_type(uint32_t bdf) +{ + return pal_pcie_get_pcie_type(PCIE_EXTRACT_BDF_SEG (bdf), + PCIE_EXTRACT_BDF_BUS (bdf), + PCIE_EXTRACT_BDF_DEV (bdf), + PCIE_EXTRACT_BDF_FUNC (bdf)); +} + /** @brief This API returns PCIe device snoop bit transaction attribute 1. Caller - Test Suite @@ -475,3 +533,129 @@ val_pcie_get_dma_coherent(uint32_t bdf) PCIE_EXTRACT_BDF_FUNC (bdf)); } +/** + @brief Increment the Dev/Bus number to the next valid value. + @param start_bdf - Segment/Bus/Dev/Func in the format of PCIE_CREATE_BDF + @return the new incremented BDF +**/ +uint32_t +val_pcie_increment_busdev(uint32_t start_bdf) +{ + + uint32_t seg = PCIE_EXTRACT_BDF_SEG(start_bdf); + uint32_t bus = PCIE_EXTRACT_BDF_BUS(start_bdf); + uint32_t dev = PCIE_EXTRACT_BDF_DEV(start_bdf); + + if (dev != PCIE_MAX_DEV) { + dev++; + } else { + bus++; + dev = 0; + } + + return PCIE_CREATE_BDF(seg, bus, dev, 0); +} + +/** + @brief Increment the segment/Bus/Dev/Bus number to the next valid value. + @param bdf - Segment/Bus/Dev/Func in the format of PCIE_CREATE_BDF + @return the new incremented BDF, else 0 to indicate incorrect input +**/ +uint32_t +val_pcie_increment_bdf(uint32_t bdf) +{ + + uint32_t seg; + uint32_t bus; + uint32_t dev; + uint32_t func; + uint32_t ecam_cnt; + uint32_t ecam_index = 0; + + seg = PCIE_EXTRACT_BDF_SEG(bdf); + bus = PCIE_EXTRACT_BDF_BUS(bdf); + dev = PCIE_EXTRACT_BDF_DEV(bdf); + func = PCIE_EXTRACT_BDF_FUNC(bdf); + + /* Derive the ecam index to which sbdf belongs */ + ecam_cnt = val_pcie_get_info(PCIE_INFO_NUM_ECAM, 0); + while (ecam_cnt--) { + if (seg == val_pcie_get_info(PCIE_INFO_SEGMENT, ecam_cnt)) { + ecam_index = ecam_cnt; + break; + } + } + + /* Return 0 to indicate incorrect input sbdf */ + if (ecam_cnt < 0) + return 0; + + /* Find the next Segment/Bus/Dev/Func */ + if (func < (PCIE_MAX_FUNC-1)) { + func++; + } else { + func = 0; + if (dev < (PCIE_MAX_DEV-1)) { + dev++; + } else { + dev = 0; + if (bus < val_pcie_get_info(PCIE_INFO_END_BUS, ecam_index)) { + bus++; + } else { + if ((ecam_index+1) < val_pcie_get_info(PCIE_INFO_NUM_ECAM, 0)) { + bus = val_pcie_get_info(PCIE_INFO_START_BUS, ecam_index+1); + seg = val_pcie_get_info(PCIE_INFO_SEGMENT, ecam_index+1); + } + else { + return 0; + } + } + } + } + + return PCIE_CREATE_BDF(seg, bus, dev, func); +} + +/** + @brief Returns the Bus, Dev, Function in the form (seg<<24 | bus<<16 | Dev <<8 | func) + @param class_code - is a 32bit value of format ClassCode << 16 | sub_class_code + @param start_bdf - is 0 : start enumeration from Host bridge + is not 0 : start enumeration from the input segment, bus, dev + this is needed as multiple controllers with same class code are + potentially present in a system. + @return the BDF of the device matching the class code +**/ +uint32_t +val_pcie_get_bdf(uint32_t class_code, uint32_t start_bdf) +{ + + return pal_pcie_get_bdf_wrapper(class_code, start_bdf); +} + +void * +val_pci_bdf_to_dev(uint32_t bdf) +{ + return pal_pci_bdf_to_dev(bdf); +} + +void +val_pcie_read_ext_cap_word(uint32_t bdf, uint32_t ext_cap_id, uint8_t offset, uint16_t *val) +{ + pal_pcie_read_ext_cap_word(PCIE_EXTRACT_BDF_SEG (bdf), + PCIE_EXTRACT_BDF_BUS(bdf), + PCIE_EXTRACT_BDF_DEV(bdf), + PCIE_EXTRACT_BDF_FUNC(bdf), + ext_cap_id, offset, val); +} + +void +val_pci_read_config_byte(uint32_t bdf, uint8_t offset, uint8_t *val) +{ + pal_pci_read_config_byte(bdf, offset, val); +} + +void +val_pci_write_config_byte(uint32_t bdf, uint8_t offset, uint8_t val) +{ + pal_pci_write_config_byte(bdf, offset, val); +} diff --git a/val/src/avs_wd.c b/val/src/avs_wd.c index 0afdaf37..ccf955a7 100644 --- a/val/src/avs_wd.c +++ b/val/src/avs_wd.c @@ -81,6 +81,8 @@ val_wd_get_info(uint32_t index, WD_INFO_TYPE_e info_type) return g_wd_info_table->wd_info[index].wd_gsiv; case WD_INFO_ISSECURE: return ((g_wd_info_table->wd_info[index].wd_flags >> 2) & 1); + case WD_INFO_IS_EDGE: + return ((g_wd_info_table->wd_info[index].wd_flags) & 1); default: return 0; }