diff --git a/.gitignore b/.gitignore index 3bbd457c..415606f1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ cscope.* *~ .project .cproject - +*.o* +sbsa #Ignore build directory build/ diff --git a/README.md b/README.md index efa03535..656979e5 100644 --- a/README.md +++ b/README.md @@ -2,48 +2,57 @@ # Server Base System Architecture - Architecture Compliance Suite -## Server Base System Architecture (SBSA) -The **Server Base Systems Architecture** (SBSA) specification specifies a hardware system architecture, based on ARM 64-bit architecture, which server system software, such as operating systems, hypervisors and firmware can rely on. It addresses PE features and key aspects of system architecture. +## 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. For more information, download the [SBSA specification](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029/index.html) -## SBSA - Architecture Compliance Suite (ACS) +## SBSA - Architecture Compliance Suite -SBSA **Architecture compliance suite** is a collection of self-checking, portable C-based tests. -These tests check an implementation for compliance against SBSA specification version 3.0. -Amajority of the tests are executed from UEFI Shell by executing the SBSA UEFI shell application. -A few tests are executed by running the SBSA Linux application which in turn depends on the SBSA Linux kernel module. +SBSA **Architecture Compliance Suite** (ACS) is a collection of self-checking, portable C-based tests. +This suite includes a set of examples of the invariant behaviours that are provided by the [SBSA](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029/index.html) specification, so that implementers can verify if these behaviours have been interpreted correctly. +Most of the tests are executed from UEFI Shell by executing the SBSA UEFI shell application. +A few tests are executed by running the SBSA ACS Linux application which in turn depends on the SBSA ACS Linux kernel module. ## Release details - - Code Quality : Beta - - Test results should not be taken as a true indication of compliance; there may be false positives/negetives. - - Test coverage is not complete yet. See the [Testcase checklist](docs/testcase-checklist.md) for details. + - Code Quality: REL v1.0 + - The tests are written for version 3.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. + - To know about the gaps in the test coverage, see [Testcase checklist](docs/testcase-checklist.md). -1. For details on the SBSA ACS UEFI Shell Application, refer to the [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf) -2. For more details on the Design of the SBSA ACS, refer to the [Validation Methodology Document](docs/SBSA_Val_Methodolgy.pdf) -3. For details on the test coverage, the scenarios implemented in the present release of the ACS and the scenarios planned in the future release, refer to the [Testcase checklist](docs/testcase-checklist.md) -## Github branch +## GitHub branch - To pick up the release version of the code, checkout the release branch. - To get the latest version of the code with bug fixes and new features, use the master branch. -### SBSA ACS Linux kernel module - - The Linux kernel module files and the kernel patch file to enable the export of a few kernel APIs needed for the PCIe and IOMMU tests are located at [linux-arm.org/git](http://www.linux-arm.org/git?p=linux-acs.git). +## 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 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). + + +## SBSA ACS Linux kernel module +To enable the export of a few kernel APIs that are necessary for PCIe and IOMMU tests, Linux kernel module and a kernel patch file are required. These files are available at [linux-arm.org/git](http://www.linux-arm.org/git?p=linux-acs.git). ## Target platforms - Any AARCH64 enterprise Platform which boots UEFI and Linux OS. + Any AARCH64 Enterprise Platform that boots UEFI and Linux OS. -### Prerequisites -1. Any mainstream Linux based OS distribution -2. git clone [EDK2 tree](https://github.com/tianocore/edk2) -3. Install GCC 5.3 or later toolchain for Linux from [here](https://releases.linaro.org/components/toolchain/binaries/) -4. Install the Build pre-requisite packages to build EDK2. The details are beyond the scope of this document. +## ACS build steps - UEFI Shell application +### Prerequisites + Before starting the ACS build, ensure that the following requirements are met. -### ACS build steps - UEFI Shell application +- Any mainstream Linux based OS distribution. +- git clone [EDK2 tree](https://github.com/tianocore/edk2). +- Install GCC 5.3 or later toolchain for Linux from [here](https://releases.linaro.org/components/toolchain/binaries/). +- Install the build prerequisite packages to build EDK2. +Note: The details of the packages are beyond the scope of this document. + +To start the ACS build, perform the following steps: 1. cd local_edk2_path 2. git clone https://github.com/ARM-software/sbsa-acs AppPkg/Applications/sbsa-acs @@ -52,16 +61,20 @@ A few tests are executed by running the SBSA Linux application which in turn dep - Add SbsaPalLib|AppPkg/Applications/sbsa-acs/platform/pal_uefi/SbsaPalLib.inf 4. Add AppPkg/Applications/sbsa-acs/uefi_app/SbsaAvs.inf in the [components] section of ShellPkg/ShellPkg.dsc -#### Linux build environment +### Linux build environment +If the build environment is Linux, perform the following steps: 1. export GCC49_AARCH64_PREFIX= GCC5.3 toolchain path pointing to /bin/aarch64-linux-gnu- 2. source edksetup.sh 3. make -C BaseTools/Source/C 4. source AppPkg/Applications/sbsa-acs/tools/scripts/avsbuild.sh -#### Windows build environment +### Windows build environment +If the build environment is Windows, perform the following steps: 1. Set the toolchain path to GCC53 or above. 2. Setup the environment for AARCH64 EDK2 build. -3. Build the SBSA shell application. Example: build -a AARCH64 -t GCC49 -p ShellPkg/ShellPkg.dsc -m +3. Build the SBSA shell application. + For example, + build -a AARCH64 -t GCC49 -p ShellPkg/ShellPkg.dsc -m AppPkg/Applications/sbsa-acs/uefi_app/SbsaAvs.inf ### Build output @@ -72,62 +85,63 @@ edk2_path /Build/Shell/DEBUG_GCC49/AARCH64/Sbsa.efi ## Test suite execution -The compliance suite execution will vary depending on the Test environment. The below steps assume that the test suite is invoked via the UEFI shell application which is provided as part of the Kit. +The execution of the compliance suite varies depending on the test environment. These steps assume that the test suite is invoked through the ACS UEFI shell application. -For more information on the SBSA UEFI Shell application, please refer to the USER Guide which is a part of the SBSA Architecture Compliance Kit. +For details about the SBSA ACS UEFI Shell application, see [SBSA ACS USER Guide](docs/SBSA_ACS_User_Guide.pdf) ### Post-Silicon -On a system where a USB port is available and functional, follow the below steps +On a system where a USB port is available and functional, perform the following steps: -1. Copy the Sbsa.efi to a USB Flash drive -2. Plug in the USB Flash drive to one of the functional USB ports on the system -3. Boot the system to UEFI shell -4. Execute “map –r” command to determine the file system number of the plugged in USB drive -5. Type “fs” where is replaced by the number determined in the step above -6. Run the executable “Sbsa.efi” with the appropriate parameters to start the compliance tests - - for details on the parameters, refer to [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf) -7. Copy the UART console output to a log file for analysis and certification +1. Copy 'Sbsa.efi' to a USB Flash drive. +2. Plug in the USB Flash drive to one of the functional USB ports on the system. +3. Boot the system to UEFI shell. +4. To determine the file system number of the plugged in USB drive, execute 'map -r' command. +5. Type 'fsx' where 'x' is replaced by the number determined in step 4. +6. To start the compliance tests, run the executable Sbsa.efi with the appropriate parameters. + For details on the parameters, refer to [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf) +7. Copy the UART console output to a log file for analysis and certification. ### Emulation environment with secondary storage +On an emulation environment with secondary storage, perform the following steps: -1. Create an Image file which contains the Sbsa.efi file. For Example: +1. Create an image file which contains the 'Sbsa.efi' file. For Example: - mkfs.vfat -C -n HD0 hda.img 2097152 - sudo mount -o rw,loop=/dev/loop0,uid=`whoami`,gid=`whoami` hda.img /mnt/sbsa - cp "/Sbsa.efi" /mnt/sbsa/ - sudo umount /mnt/sbsa -2. Load the image file to the secondary storage using a backdoor. The steps to do this is Emulation environment specific and beyond the scope of this documentation. +2. Load the image file to the secondary storage using a backdoor. The steps followed to load the image file are Emulation environment specific and beyond the scope of this document. 3. Boot the system to UEFI shell. -4. Execute “map –r” command to determine the file system number of the secondary storage. -5. Type “fs” where is replaced by the number determined in the step above. -6. Run the executable “Sbsa.efi” to start the compliance tests. - - for details on the parameters, refer to [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf) -7. Copy the UART console output to a log file for analysis and certification +4. To determine the file system number of the secondary storage, execute 'map -r' command. +5. Type 'fsx' where 'x' is replaced by the number determined in step 4. +6. To start the compliance tests, run the executable Sbsa.efi with the appropriate parameters. + For details on the parameters, see [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf) +7. Copy the UART console output to a log file for analysis and certification. + ### Emulation environment without secondary storage -On an Emulation platform where secondary storage is not available. +On an Emulation platform where secondary storage is not available, perform the following steps: -1. Add the Sbsa.efi file as part of the UEFI FD file. - - Add SbsaAvs.inf and the dependant VAL and PAL inf files to the Platform dsc and fdf files. +1. Add the path to 'Sbsa.efi' file in the UEFI FD file. 2. Build UEFI image including the UEFI Shell. 3. Boot the system to UEFI shell. -4. Run the executable “Sbsa.efi” to start the compliance tests. - - for details on the parameters, refer to [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf) +4. Run the executable 'Sbsa.efi' to start the compliance tests. For details about the parameters, see [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf). 5. Copy the UART console output to a log file for analysis and certification. -## Linux OS based tests -Certain PCIe and IOMMU tests require Linux operating system with kernel version 4.10 or above. The description on how to build and run these tests are part of the [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf). +## Linux OS-based tests +Certain PCIe and IOMMU tests require Linux operating system with kernel version 4.10 or above. The procedure to build and run these tests is described in [SBSA ACS User Guide](docs/SBSA_ACS_User_Guide.pdf). ## License SBSA ACS is distributed under Apache v2.0 License. -## Feedback, contrubutions and support +## Feedback, contributions and support - - Please use the GitHub Issue Tracker associated with this repository for feedback. - - ARM licensees may contact ARM directly via their partner managers. - - We welcome code contributions via GitHub Pull requests. Please see "Contributing Code" section of the documentation for details. + - For feedback, use the GitHub Issue Tracker that is associated with this repository. + - For support, please send an email to "support-enterprise-acs@arm.com" with details. + - ARM licensees can contact ARM directly through their partner managers. + - ARM welcomes code contributions through GitHub pull requests. See GitHub documentation on how to raise pull requests. diff --git a/docs/SBSA_ACS_User_Guide.pdf b/docs/SBSA_ACS_User_Guide.pdf index 07a0acf7..41243fb5 100755 Binary files a/docs/SBSA_ACS_User_Guide.pdf and b/docs/SBSA_ACS_User_Guide.pdf differ diff --git a/docs/SBSA_Val_Methodolgy.pdf b/docs/SBSA_Val_Methodolgy.pdf index 86b864c3..da854e72 100755 Binary files a/docs/SBSA_Val_Methodolgy.pdf and b/docs/SBSA_Val_Methodolgy.pdf differ diff --git a/docs/testcase-checklist.md b/docs/testcase-checklist.md index 203acc79..11f2c1c5 100644 --- a/docs/testcase-checklist.md +++ b/docs/testcase-checklist.md @@ -3,128 +3,122 @@ ## Test Number mapped to SBSA specification section - Also, indicates the test coverage. - - The last 2 columns indicate tests implemented in this release and those planned for future releases. - -| Test Number | Component | Level | Test assertion | Section | Checked by ACS Now | Planned in Future release | -|----------------|----------------------------------|-------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|--------------------|---------------------------| -| 1 | PE | L0 | Number must be < 8 | 4.1.1 | yes | | -| 2 | PE | L0+ | PE(s) must implement SIMD extensions | 4.1.1 | yes | | -| 3 | PE | L0+ | PE(s) shall implement 16 bit ASID support | 4.1.1 | yes | | -| 4 | PE | L0+ | PE(s) shall support 4KB and 64KB at stage 1 and 2 | 4.1.1 | yes | | -| 5 | PE | L0+ | cache architecture type VIPT or PIPT | 4.1.1 | yes | | -| 6 | PE | L0+ | All PE(s) are coherent in the same same inner sharable domain | 4.1.1 | yes | | -| 7 | PE | L0+ | PE(s) where export restrictions allow should implement cryptography extensions | 4.1.1 | yes | | -| 8 | PE | L0+ | PE(s) shall implement LE support | 4.1.1 | yes | | -| 9 | PE | L0+ | PE(s) shall implement EL2 | 4.1.1 | yes | | -| 10 | PE | L0+ | PE(s) shall implement AArch64 at all levels | 4.1.1 | yes | | -| 11 | PE | L1- | The PMU overflow signal for each PE must be wired as a unique SPI or PPI with no intervening logic | 4.1.1 | yes | | -| 11 | PE | L2+ | The PMU overflow signal from each PE must be wired to a unique PPI interrupt with no intervening logic. PPI must be 23 | 4.3.1 | yes | | -| 12 | PE | L0 | Each PE will implement a minimal of four programable PMU counters | 4.1.1 | yes | | -| 12 | PE | L1+ | Each PE must implement a minimum of six programmable PMU counters | 4.2.1 | yes | | -| 13 | PE | L0+ | Each PE will implement a minimal of four synchronous watchpoints | 4.1.1 | yes | | -| 14 | PE | L0 | Each PE implements a minimum of four breakpoints, two of which must be able to match virtual address, contextID or VMID | 4.1.1 | yes | | -| 14 | PE | L1+ | Each PE must implement a minimum of six breakpoints, two of which must be able to match virtual address, contextID or VMID | 4.2.1 | yes | | -| 15 | PE | L0+ | All PE(s) are architecturally symetric (allowed exceptions in Appendix C) | 4.1.1 | yes | | -| 16 | PE | L3+ | Each PE implements EL3 Exception Level | 4.4.1 | yes | | -| 17 | PE | L3+ | Each PE implements CRC32 instructions | 4.4.1 | yes | | -| 18 | PE | L2+ | PMBIRQ will be wired as PPI 21 | 4.3.2.2 | yes | | -| | GICv2 | L1- | GICv2 will be implemented | 4.1.2 | deprecated | no | -| | GICv2 | L1- | The system shall implement at least 8 non-secure SGIs asssigned interrupt IDs 0-7 | 4.1.2 | deprecated | no | -| | GICv2 | L1- | For GIC400 specifically it is necessary to ensure that GICCC base is 4KB before a 64KB boundary | 4.1.2 | deprecated | no | -| | GICv2m | L1 | The system must implement at least one Non-secure MSI frame with a minimum of 32 SPIs | | deprecated | no | -| | GICv2m | L1 | If the base server system includes PCI Express then the base server system must implement a GICv2m interrupt controller | 4.2.2 | deprecated | no | -| 21 | GICv3 | L2+ | Interrupt controller shall conform to GICv3 specification | 4.3.2 | yes | | -| 22 | GICv3 | L2+ | If the base server system includes PCI Express then the GICv3 interrupt controller shall implement ITS and LPI | 4.3.2 | yes | | -| 23 | GIC | L3+ | The GICv3 interrupt controller shall support two Security states | 4.4.4 | yes | | -| 24 | GICv2/3 | L2+ | GIC maintenance interrupt shall be wired as PPI 25 | 4.3.2.4 | yes | | -| 31 | System counter and generic timer | L0+ | Must run between 10Mhz and 400Mhz | 4.1.5 | yes | | -| 32 | System counter and generic timer | L1- | The local PE timer when expiring must generate a PPI when EL1 physical timer expires | 4.1.5 | yes | | -| 32 | System counter and generic timer | L2+ | The local PE timer when expiring must generate a PPI when EL1 physical timer expires, and PPI must be 30 | 4.1.54.3.2.1 | yes | | -| 33 | System counter and generic timer | L1- | The local PE timer when expiring must generate a PPI when the virtual timer expires | 4.1.5 | yes | | -| 33 | System counter and generic timer | L2+ | The local PE timer when expiring must generate a PPI when the virtual timer expires, and PPI must be 27 | 4.1.54.3.2.1 | yes | | -| 34 | System counter and generic timer | L1- | The local PE timer when expiring must generate a PPI when EL2 physical timer expires | 4.1.5 | yes | | -| 34 | System counter and generic timer | L2+ | The local PE timer when expiring must generate a PPI when EL2 physical timer expires, and PPI must be 26 | 4.1.54.3.2.1 | yes | | -| 35 | System counter and generic timer | L1- | For systems where PE are 8.1 or greater local PE timer when expiring must generate a PPI when EL2 virtual timer expires | 4.1.5 | yes | | -| 35 | System counter and generic timer | L2+ | For systems where PE are 8.1 or greater local PE timer when expiring must generate a PPI when EL2 virtual timer expires, and PPI must be 28 | 4.1.54.3.2.1 | yes | | -| 36 | System counter and generic timer | L1+ | In systems that implement EL3, the memory mapped timer (the CNTBaseN frame and associated CNTCTLBase frame) must be mapped into the Non-secure address space | 4.2.3. | yes | | -| 37 | System counter and generic timer | L1+ | Unless all local PE timers are Always ON, a system timer based on architecture memory mapped generic itmer view shall generate an SPI | 4.2.3 | yes | | -| 41 | Watchdog | L1+ | system implements a Generic Watchdog as specified in APPENDIX A: Generic Watchdog. | | yes | | -| 41 | Watchdog | L3+ | The watchdog required by level 2 must have both its register frames mapped on to Non-secure address space; this is referred to as the Non-secure watchdog | 4.4.7 | yes | | -| 42 | Watchdog | L1- | Watchdog Signal 0 is routed as an SPI to the GIC and usable as a EL2 interrupt | 4.2.4 | yes | | -| 42 | Watchdog | L2+ | Watchdog Signal 0 is routed as an SPIor LPI to the GIC and usable as a EL2 interrupt | 4.3.8 | yes | | -| 901 | Watchdog | L1+ | Watchdog Signal 1 is available. This may be confirmed in the data base. This may not be possible to exersice as its handling is platform specific | 4.2.4 | yes | | -| 73 | Watchdog | L1+ | Watchdog Signal 0 should be able to wakeup at least one PE from various low power states. | 4.2.6 | yes | | -| 51 | PCIe | L1+ | Systems must map memory space to PCI Express configuration space, using the PCI Express Enhanced Configuration Access Mechanism (ECAM). | 8.1 | yes | | -| 52 | PCIe | L1+ | The base address of each ECAM region is discoverable from system firmware data | 8.1 | yes | | -| 53 | PCIe | L1+ | PEs are able to access the ECAM region | 8.1 | yes | | -| 54 | PCIe | L1+ | All systems must support mapping PCI Express memory space as either device memory or non-cacheable memory | 8.2 | yes | | -| 54 | PCIe | L1+ | When PCI Express memory space is mapped as normal memory, the system must support unaligned accesses to that region. | 8.2 | yes | | -| 61 | IO Virtualisation | L0+ | SMMU if present must spport a 64KB granule, For L1- this would be an SMMUv1 for L2 SMMUv2, and | 4.1.4 | yes | | -| 62 | SMMU | L3+ | All the System MMUs in the system must the compliant with the same architecture version | 4.4.5 | yes | | -| 63 | SMMU | L3+ | If SMMUv3 is in use, The integration of the System MMUs is compliant with the specification in APPENDIX H: SMMUv3 Integration | 4.4.5Appendix H | yes | | -| | IO Virtualisation | L0+ | Policing is required at stage 2 | 4.1.4 | yes | | -| 63 | IO Virtualisation | L2+ | Stage 2 System MMU functionality must be provided by a System MMU compatible with the ARM SMMUv2 spec | 4.3.5 | yes | | -| 63 | SMMU | L3+ | Stage 2 System MMU functionality must be provided by a System MMU compatible with the ARM SMMUv2 or SMMUv3 specification | 4.4.5 | yes | | -| | SMMU | L3+ | If SMMUv2 is in use, Each context bank must present a unique physical interrupt to the GIC | 4.4.5 | no | yes | -| 71, 72, 73, 74 | Wakeup semantics | L0+ | Whilst in state B a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | yes | | -| | Wakeup semantics | L0+ | Whilst in state C a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | no | -| | Wakeup semantics | L0+ | Whilst in state D a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | no | -| | Wakeup semantics | L0+ | Whilst in state E a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | no | -| 75 | Wakeup semantics | L0+ | Whilst in state F a PE must not wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | yes | | -| | Wakeup semantics | L0+ | Whilst in state G a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | no | -| | Wakeup semantics | L0+ | Whilst in state H a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | no | -| 81 | Peripheral Subsystems | L0+ | If the system has a USB2.0 host controller peripheral it must conform to EHCI v1.1 or later | 4.1.8 | yes | | -| 81 | Peripheral Subsystems | L0+ | If the system has a USB3.0 host controller peripheral it must conform to XHCI v1.0 or later - | 4.1.8 | yes | | -| 82 | Peripheral Subsystems | L0+ | If the system has a SATA host controller peripheral it must conform to AHCI v1.3 or later | 4.1.8 | yes | | -| 83 | Peripheral Subsystems | L1+ | For the purpose of system development and bring up, the base server system shall include a Generic UART. The UARTINTR interrupt output is connected to the GIC as an SPI. | 4.2.7 | yes | | -| 83 | Peripheral Subsystems | L3+ | Check that that Generic UART is mapped to Non-Secure address space | 4.4.8 | yes | | -| 84 | Peripheral Subsystems | L2+ | UARTINTR of the generic UART shall be connected as SPI or LPI | 4.3.9 | yes | | -| 85 | MemoryMap | L0+ | Accesses to part of the memory map that is unpopulated should not deadlock and cause a precise data abort, SEI or SPU interrupt delivered to the GIC | 4.1.3 | yes | | -| 85 | MemoryMap | L2+ | Where a memory access is to an unpopulated part of the addressable memory space, accesses must be terminated in a manner that is presented to the PE as either a precise Data Abort or that causes a system error interrupt or an SPI or LPI interrupt to be delivered to the GIC. | 4.3.3 | yes | | -| 902 | System counter and generic timer | L0+ | Must implement at least 56 bits | 4.1.5 | yes | | -| 902 | System counter and generic timer | L0+ | The counter shall be sized and programmed to ensure that rollover never occurs in pract | 4.1.5 | yes | | -| 903 | System counter and generic timer | L1- | The local PE timer when expiring must generate a PPI when EL3 physical timer expires | 4.1.5 | yes | | -| 903 | System counter and generic timer | L2+ | The local PE timer when expiring must generate a PPI when EL3 physical timer expires, and PPI must be 29 | 4.1.54.3.2.1 | yes | | -| 906 | Peripheral Subsystems | L3 FW | Secure Generic UART is present. It is not aliased in Non-secure address space. The UARTINTR output of the secure generic UART is connected to the GIC as an SPI | 4.5.4 | yes | | -| 71, 72 | System counter and generic timer | L0+ | Any local timers that are marked by PE as always ON must be able to wake up the system. This applies to expiry of all non-secure views of the local timer (CNTV/P/HP/HV) | 4.1.54.1.7 | yes | | -| 904 | System counter and generic timer | L0+ | Any local timers that are marked by PE as always ON must be able to wake up the system. This applies to expiry of all secure views of the local timer (CNTPS) | 4.1.54.1.7 | yes | | -| 38 | System counter and generic timer | L0 | A system specific system timer shall generate an SPI | 4.1.54.1.7 | yes | | -| 74 | System counter and generic timer | L0 | A system specific system timer shall generate an SPI that wake the platform from states with semantics B,C,D,E,F,H,I | 4.1.54.1.7 | no | | -| 74 | 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 | | -| | Power State Semantics | L2+ | System MMUs and, in the future, GICv3, make use of tables in memory in the power states where GIC is On, system memory shall be available and will respond to requests without requiring intervention from software. | 4.1.7 | no | | -| 902 | System counter and generic timer | L1+ | In systems that implement EL3, CNTControlBase should be mapped to Secure address space only | 4.2.3 | yes | | -| 902 | System counter and generic timer | L1+ | Generic Timer required registers are implemented as specified in section 4.2.3.1 "Summary of required registers of the CNTControlBase frame" | 4.2.3.1 | yes | | -| | Wakeup semantics | L1+ | Power States A-I as described in "Requirements on power state semantics" shall be covered | 4.2.5 | no | no | -| 55 | 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 | | -| 55 | 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 | | -| 56 | 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 | | -| 57 | 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 | | -| | 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 | yes | -| | PCIe | L1+ | Add GICv2/v3 support details | 8.4.1/2 | no | yes | -| | PCIe | L1+ | Each of the 4 legacy interrupt lines must be allocated a unique SPI ID and is programmed as level sensitive | 8.5 | no | yes | -| | PCIe | L1+ | only registers defined in the PCI Express specification and the ARM GIC specification are used to deliver legacy interrupts | 8.5 | no | yes | -| | PCIe | L1+ | Hardware support for I/O Virtualization is optional, but if required shall use a System MMU compliant with the ARM System MMU specification | 8.6 | no | yes | -| | PCIe | L1+ | Each function, or virtual function, that requires hardware I/O virtualization is associated with a SMMU context. The programming of this association is IMPLEMENTATION DEFINED and is expected to be described by system firmware data. | 8.6 | no | yes | -| | 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 | no | yes | -| | PCIe | L0+ | The PCI Express root complex is in the same Inner Shareable domain as the PEs | 8.7 | no | yes | -| | PCIe | L0+ | PCI Express transactions marked as No_snoop accessing memory that the PE translation tables attribute as cacheable and shared behave correctly when appropriate SW coherence is deployed | 8.7 | no | yes | -| 55 | PCIe | L0+ | PCIe I/O Coherency Scenarios without System MMU are covered | 8.7.1 | yes | | -| 55 | PCIe | L1+ | PCIe I/O Coherency Scenarios with System MMU are covered | 8.7.2 | yes | | -| | PCIe | L1+ | All end points claiming PCIe support must follow PCIe rules. | 8.9 | no | yes | -| | PCIe | L3+ | Systems compatible with level 3 or above of the SBSA must not deadlock if PCI express devices attempt peer-to-peer transactions even if the system does not support peer-to-peer traffic | 8.10 | no | yes | -| | PCIe | L3+ | If the system supports PCIe PASID, then at least 16 bits of PASID must be supported | 8.11 | no | yes | -| | GICv3 | L2+ | All MSIs and MSI-x are mapped to LPI | 4.3.2 | no | yes | -| | Debug | L2+ | COMMIRQ interrupt for Debug Communications Channel will be wired as PPI 22 | 4.3.2.1 | no | no | -| | Debug | L2+ | Cross trigger interface interrupt shall be wired as PPI 24 | 4.3.2.3 | no | no | -| | System counter and generic timer | L2+ | Where a system wake up timer is present it shall generate an SPI o LPI that wake the platform from states with semantics B,C,D,E,F,H,I | 4.3.6 | no | yes | -| | 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 | no | yes | -| | 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 | no | yes | -| 36 | System counter and generic timer | L3+ | If the system includes a system wakeup timer, this memory-mapped timer must be mapped on to Non-secure address space | 4.4.6 | yes | | -| 56 | PCIe | L3+ | the addresses sent by PCI express devices must be presented to the memory system or SMMU unmodified | 4.4.8 | yes | | -| | 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 | no | yes | -| 86 | Peripheral Subsystems | L3 FW | Some memory is mapped in secure address space. The memory shall not be aliased in Non-secure address space | 4.5.1 | yes | | -| | System counter and generic timer | L3 FW | A secure system wakeup timer is present and the interrupt is presented to GIC as a SPI | 4.5.2 | no | yes | -| 901 | Watchdog | L3 FW | The Watchdog Signal 1 is routed as a SPI to GIC and usable as an EL3 interrupt, directly targetting a single PE | 4.5.3 | yes | | -| 904 | Watchdog | L3 FW | Secure Watchdog is implemented. Secure watchdog is not-aliased in non-secure address space. Signal 0 if secure watchdog is routed as an SPI and usable as an interrupt to EL3, directly targetting a single PE | 4.5.3 | yes | | -| | Watchdog | L3 FW | Routing of Signal 1 of Secure Watchdog to Platform | 4.5.3 | no | no | +| Test Number | Component | Level | Test assertion | Section | Checked by ACS Now | Test Environment | +|----------------|----------------------------------|-------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|--------------------|----------------------------| +| 1 | PE | L0 | Number must be < 8 | 4.1.1 | yes | UEFI App | +| 2 | PE | L0+ | PE(s) must implement SIMD extensions | 4.1.1 | yes | UEFI App | +| 3 | PE | L0+ | PE(s) shall implement 16 bit ASID support | 4.1.1 | yes | UEFI App | +| 4 | PE | L0+ | PE(s) shall support 4KB and 64KB at stage 1 and 2 | 4.1.1 | yes | UEFI App | +| 5 | PE | L0+ | cache architecture type VIPT or PIPT | 4.1.1 | yes | UEFI App | +| 6 | PE | L0+ | All PE(s) are coherent in the same same inner sharable domain | 4.1.1 | yes | UEFI App | +| 7 | PE | L0+ | PE(s) where export restrictions allow should implement cryptography extensions | 4.1.1 | yes | UEFI App | +| 8 | PE | L0+ | PE(s) shall implement LE support | 4.1.1 | yes | UEFI App | +| 9 | PE | L0+ | PE(s) shall implement EL2 | 4.1.1 | yes | UEFI App | +| 10 | PE | L0+ | PE(s) shall implement AArch64 at all levels | 4.1.1 | yes | UEFI App | +| 11 | PE | L1- | The PMU overflow signal for each PE must be wired as a unique SPI or PPI with no intervening logic | 4.1.1 | yes | UEFI App | +| 11 | PE | L2+ | The PMU overflow signal from each PE must be wired to a unique PPI interrupt with no intervening logic. PPI must be 23 | 4.3.1 | yes | UEFI App | +| 12 | PE | L0 | Each PE will implement a minimal of four programable PMU counters | 4.1.1 | yes | UEFI App | +| 12 | PE | L1+ | Each PE must implement a minimum of six programmable PMU counters | 4.2.1 | yes | UEFI App | +| 13 | PE | L0+ | Each PE will implement a minimal of four synchronous watchpoints | 4.1.1 | yes | UEFI App | +| 14 | PE | L0 | Each PE implements a minimum of four breakpoints, two of which must be able to match virtual address, contextID or VMID | 4.1.1 | yes | UEFI App | +| 14 | PE | L1+ | Each PE must implement a minimum of six breakpoints, two of which must be able to match virtual address, contextID or VMID | 4.2.1 | yes | UEFI App | +| 15 | PE | L0+ | All PE(s) are architecturally symetric (allowed exceptions in Appendix C) | 4.1.1 | yes | UEFI App | +| 16 | PE | L3+ | Each PE implements EL3 Exception Level | 4.4.1 | yes | UEFI App | +| 17 | PE | L3+ | Each PE implements CRC32 instructions | 4.4.1 | yes | UEFI App | +| 18 | PE | L2+ | PMBIRQ will be wired as PPI 21 | 4.3.2.2 | yes | UEFI App | +| 21 | GICv3 | L2+ | Interrupt controller shall conform to GICv3 specification | 4.3.2 | yes | UEFI App | +| 22 | GICv3 | L2+ | If the base server system includes PCI Express then the GICv3 interrupt controller shall implement ITS and LPI | 4.3.2 | yes | UEFI App | +| 23 | GIC | L3+ | The GICv3 interrupt controller shall support two Security states | 4.4.4 | yes | UEFI App | +| 24 | GICv2/3 | L2+ | GIC maintenance interrupt shall be wired as PPI 25 | 4.3.2.4 | yes | UEFI App | +| 31 | System counter and generic timer | L0+ | Must run between 10Mhz and 400Mhz | 4.1.5 | yes | UEFI App | +| 32 | System counter and generic timer | L1- | The local PE timer when expiring must generate a PPI when EL1 physical timer expires | 4.1.5 | yes | UEFI App | +| 32 | System counter and generic timer | L2+ | The local PE timer when expiring must generate a PPI when EL1 physical timer expires, and PPI must be 30 | 4.1.54.3.2.1 | yes | UEFI App | +| 33 | System counter and generic timer | L1- | The local PE timer when expiring must generate a PPI when the virtual timer expires | 4.1.5 | yes | UEFI App | +| 33 | System counter and generic timer | L2+ | The local PE timer when expiring must generate a PPI when the virtual timer expires, and PPI must be 27 | 4.1.54.3.2.1 | yes | UEFI App | +| 34 | System counter and generic timer | L1- | The local PE timer when expiring must generate a PPI when EL2 physical timer expires | 4.1.5 | yes | UEFI App | +| 34 | System counter and generic timer | L2+ | The local PE timer when expiring must generate a PPI when EL2 physical timer expires, and PPI must be 26 | 4.1.54.3.2.1 | yes | UEFI App | +| 35 | System counter and generic timer | L1- | For systems where PE are 8.1 or greater local PE timer when expiring must generate a PPI when EL2 virtual timer expires | 4.1.5 | yes | UEFI App | +| 35 | System counter and generic timer | L2+ | For systems where PE are 8.1 or greater local PE timer when expiring must generate a PPI when EL2 virtual timer expires, and PPI must be 28 | 4.1.54.3.2.1 | yes | UEFI App | +| 36 | System counter and generic timer | L1+ | In systems that implement EL3, the memory mapped timer (the CNTBaseN frame and associated CNTCTLBase frame) must be mapped into the Non-secure address space | 4.2.3. | yes | UEFI App | +| 36 | System counter and generic timer | L3+ | If the system includes a system wakeup timer, this memory-mapped timer must be mapped on to Non-secure address space | 4.4.6 | yes | UEFI App | +| 37 | System counter and generic timer | L1+ | Unless all local PE timers are Always ON, a system timer based on architecture memory mapped generic itmer view shall generate an SPI | 4.2.3 | yes | UEFI App | +| 38 | System counter and generic timer | L0 | A system specific system timer shall generate an SPI | 4.1.54.1.7 | yes | UEFI App | +| 41 | Watchdog | L1+ | system implements a Generic Watchdog as specified in APPENDIX A: Generic Watchdog. | | yes | UEFI App | +| 41 | Watchdog | L3+ | The watchdog required by level 2 must have both its register frames mapped on to Non-secure address space; this is referred to as the Non-secure watchdog | 4.4.7 | yes | UEFI App | +| 42 | Watchdog | L1- | Watchdog Signal 0 is routed as an SPI to the GIC and usable as a EL2 interrupt | 4.2.4 | yes | UEFI App | +| 42 | 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 | +| 51 | 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 | +| 52 | PCIe | L1+ | The base address of each ECAM region is discoverable from system firmware data | 8.1 | yes | Linux driver | +| 53 | PCIe | L1+ | PEs are able to access the ECAM region | 8.1 | yes | Linux driver | +| 54 | PCIe | L1+ | All systems must support mapping PCI Express memory space as either device memory or non-cacheable memory | 8.2 | yes | Linux driver | +| 54 | 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 | +| 55 | 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 | +| 55 | 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 | +| 55 | PCIe | L0+ | PCIe I/O Coherency Scenarios without System MMU are covered | 8.7.1 | yes | Linux driver | +| 55 | PCIe | L1+ | PCIe I/O Coherency Scenarios with System MMU are covered | 8.7.2 | yes | Linux driver | +| 56 | 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 | +| 56 | 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 | +| 57 | 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 | +| 58 | 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 | +| 58 | PCIe | L1+ | Add GICv2/v3 support details | 8.4.1/2 | yes | Linux driver | +| 59 | GICv3 | L2+ | All MSIs and MSI-x are mapped to LPI | 4.3.2 | yes | Linux driver | +| 60 | PCIe | L3+ | If the system supports PCIe PASID, then at least 16 bits of PASID must be supported | 8.11 | yes | Linux driver | +| 61 | PCIe | L0+ | The PCI Express root complex is in the same Inner Shareable domain as the PEs | 8.7 | yes | Linux driver | +| 62 | 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 | +| 63 | 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 | +| 63 | 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 | +| 64 | 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 | +| 65 | 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 | +| 74 | 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 | +| 74 | 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 | +| 75 | System counter and generic timer | L0 | A system specific system timer shall generate an SPI that wake the platform from states with semantics B,C,D,E,F,H,I | 4.1.54.1.7 | no | UEFI App | +| 75 | Wakeup semantics | L0+ | Whilst in state F a PE must not wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | yes | UEFI App | +| 81 | Peripheral Subsystems | L0+ | If the system has a USB2.0 host controller peripheral it must conform to EHCI v1.1 or later - Peripheral subsystems which do not conform to the above are permitted, provided that they are not required to boot and install an OS | 4.1.8 | yes | UEFI App | +| 81 | Peripheral Subsystems | L0+ | If the system has a USB3.0 host controller peripheral it must conform to XHCI v1.0 or later - Peripheral subsystems which do not conform to the above are permitted, provided that they are not required to boot and install an OS | 4.1.8 | yes | UEFI App | +| 82 | Peripheral Subsystems | L0+ | If the system has a SATA host controller peripheral it must conform to AHCI v1.3 or later - Peripheral subsystems which do not conform to the above are permitted, provided that they are not required to boot and install an OS | 4.1.8 | yes | UEFI App | +| 83 | Peripheral Subsystems | L1+ | For the purpose of system development and bring up, the base server system shall include a Generic UART. The Generic UART is specified in Appendix B. The UARTINTR interrupt output is connected to the GIC as an SPI. | 4.2.7 | yes | UEFI App | +| 83 | Peripheral Subsystems | L3+ | Check that that Generic UART is mapped to Non-Secure address space | 4.4.8 | yes | UEFI App | +| 84 | Peripheral Subsystems | L2+ | UARTINTR of the generic UART shall be connected as SPI or LPI | 4.3.9 | yes | UEFI App | +| 85 | MemoryMap | L0+ | Accesses to part of the memory map that is unpopulated should not deadlock and cause a precise data abort, SEI or SPU interrupt delivered to the GIC | 4.1.3 | yes | UEFI App | +| 85 | MemoryMap | L2+ | Where a memory access is to an unpopulated part of the addressable memory space, accesses must be terminated in a manner that is presented to the PE as either a precise Data Abort or that causes a system error interrupt or an SPI or LPI interrupt to be delivered to the GIC. | 4.3.3 | yes | UEFI App | +| 86 | Peripheral Subsystems | L3 FW | Some memory is mapped in secure address space. The memory shall not be aliased in Non-secure address space | 4.5.1 | yes | UEFI App | +| 91 | IO Virtualisation | L0+ | SMMU if present must spport a 64KB granule, For L1- this would be an SMMUv1 for L2 SMMUv2, and | 4.1.4 | yes | UEFI App | +| 92 | SMMU | L3+ | All the System MMUs in the system must the compliant with the same architecture version | 4.4.5 | yes | UEFI App | +| 93 | SMMU | L3+ | If SMMUv3 is in use, The integration of the System MMUs is compliant with the specification in APPENDIX H: SMMUv3 Integration | 4.4.5Appendix H | yes | UEFI App | +| 93 | IO Virtualisation | L2+ | Stage 2 System MMU functionality must be provided by a System MMU compatible with the ARM SMMUv2 spec | 4.3.5 | yes | UEFI App | +| 93 | SMMU | L3+ | Stage 2 System MMU functionality must be provided by a System MMU compatible with the ARM SMMUv2 or SMMUv3 specification | 4.4.5 | yes | UEFI App | +| 93 | PCIe | L1+ | Hardware support for I/O Virtualization is optional, but if required shall use a System MMU compliant with the ARM System MMU specification | 8.6 | yes | UEFI App | +| 93 | IO Virtualisation | L0+ | Policing is required at stage 2 | 4.1.4 | yes | UEFI App | +| 94 | SMMU | L3+ | The SMMUv3 spec requires that PCIe root complex must not use the stall model due to potential deadlock. | Appendix H | yes | UEFI App | +| 95 | SMMU | L3+ | If SMMUv2 is in use, Each context bank must present a unique physical interrupt to the GIC | 4.4.5 | yes | UEFI App | +| 96 | PCIe | L1+ | Each function, or virtual function, that requires hardware I/O virtualization is associated with a SMMU context. The programming of this association is IMPLEMENTATION DEFINED and is expected to be described by system firmware data. | 8.6 | yes | UEFI App | +| 901 | Watchdog | L1+ | Watchdog Signal 1 is available. This may be confirmed in the data base. This may not be possible to exersice as its handling is platform specific | 4.2.4 | yes | Secure FW | +| 901 | Watchdog | L3 FW | The Watchdog Signal 1 is routed as a SPI to GIC and usable as an EL3 interrupt, directly targetting a single PE | 4.5.3 | yes | Secure FW | +| 902 | System counter and generic timer | L0+ | Must implement at least 56 bits | 4.1.5 | yes | Secure FW | +| 902 | System counter and generic timer | L0+ | The counter shall be sized and programmed to ensure that rollover never occurs in pract | 4.1.5 | yes | Secure FW | +| 902 | System counter and generic timer | L1+ | In systems that implement EL3, CNTControlBase should be mapped to Secure address space only | 4.2.3 | yes | Secure FW | +| 902 | System counter and generic timer | L1+ | Generic Timer required registers are implemented as specified in section 4.2.3.1 "Summary of required registers of the CNTControlBase frame" | 4.2.3.1 | yes | Secure FW | +| 903 | System counter and generic timer | L1- | The local PE timer when expiring must generate a PPI when EL3 physical timer expires | 4.1.5 | yes | Secure FW | +| 903 | System counter and generic timer | L2+ | The local PE timer when expiring must generate a PPI when EL3 physical timer expires, and PPI must be 29 | 4.1.54.3.2.1 | yes | Secure FW | +| 904 | System counter and generic timer | L0+ | Any local timers that are marked by PE as always ON must be able to wake up the system. This applies to expiry of all secure views of the local timer (CNTPS) | 4.1.54.1.7 | yes | Secure FW | +| 904 | Watchdog | L3 FW | Secure Watchdog is implemented. Secure watchdog is not-aliased in non-secure address space. Signal 0 if secure watchdog is routed as an SPI and usable as an interrupt to EL3, directly targetting a single PE | 4.5.3 | yes | Secure FW | +| 905 | Peripheral Subsystems | L3 FW | Secure Generic UART is present. It is not aliased in Non-secure address space. The UARTINTR output of the secure generic UART is connected to the GIC as an SPI | 4.5.4 | yes | Secure FW | +| 906 | System counter and generic timer | L3 FW | A secure system wakeup timer is present and the interrupt is presented to GIC as a SPI | 4.5.2 | yes | Secure FW | +| 71, 72 | System counter and generic timer | L0+ | Any local timers that are marked by PE as always ON must be able to wake up the system. This applies to expiry of all non-secure views of the local timer (CNTV/P/HP/HV) | 4.1.54.1.7 | yes | UEFI App | +| 71, 72, 73, 74 | Wakeup semantics | L0+ | Whilst in state B a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | yes | UEFI App | +| | PCIe | L1+ | only registers defined in the PCI Express specification and the ARM GIC specification are used to deliver legacy interrupts | 8.5 | yes | ARM Enterprise ACS package | +| | PCIe | L1+ | All end points claiming PCIe support must follow PCIe rules. | 8.9 | yes | ARM Enterprise ACS package | +| | Wakeup semantics | L0+ | Whilst in state C a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | | +| | Wakeup semantics | L0+ | Whilst in state D a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | | +| | Wakeup semantics | L0+ | Whilst in state E a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | | +| | Wakeup semantics | L0+ | Whilst in state G a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | | +| | Wakeup semantics | L0+ | Whilst in state H a PE must be able to wake upon receipt of an SGI, PPI or SPI that directly targets the PE | 4.3.4/7 | no | | +| | Power State Semantics | L2+ | System MMUs and, in the future, GICv3, make use of tables in memory in the power states where GIC is ‘On’, system memory shall be available and will respond to requests without requiring intervention from software. | 4.1.7 | no | | +| | Wakeup semantics | L1+ | Power States A-I as described in "Requirements on power state semantics" shall be covered | 4.2.5 | no | | +| | PCIe | L0+ | PCI Express transactions marked as No_snoop accessing memory that the PE translation tables attribute as cacheable and shared behave correctly when appropriate SW coherence is deployed | 8.7 | no | | +| | PCIe | L3+ | Systems compatible with level 3 or above of the SBSA must not deadlock if PCI express devices attempt peer-to-peer transactions – even if the system does not support peer-to-peer traffic | 8.10 | no | | +| | Debug | L2+ | COMMIRQ interrupt for Debug Communications Channel will be wired as PPI 22 | 4.3.2.1 | no | | +| | Debug | L2+ | Cross trigger interface interrupt shall be wired as PPI 24 | 4.3.2.3 | no | | +| | System counter and generic timer | L2+ | Where a system wake up timer is present it shall generate an SPI or LPI that wake the platform from states with semantics B,C,D,E,F,H,I | 4.3.6 | no | | +| | Watchdog | L3 FW | Routing of Signal 1 of Secure Watchdog to Platform | 4.5.3 | no | | diff --git a/linux_app/sbsa-acs-app/Makefile b/linux_app/sbsa-acs-app/Makefile index 76b91c81..c363d207 100644 --- a/linux_app/sbsa-acs-app/Makefile +++ b/linux_app/sbsa-acs-app/Makefile @@ -24,7 +24,7 @@ program_OBJS := $(program_C_OBJS) $(program_CXX_OBJS) program_INCLUDE_DIRS := ../../ ../../val/include program_LIBRARY_DIRS := program_LIBRARIES := -CC := $(GCC49_AARCH64_PREFIX)gcc +CC := $(CROSS_COMPILE)gcc CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) -DTARGET_LINUX -g LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) @@ -35,7 +35,7 @@ LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) all: $(program_NAME) $(program_NAME): $(program_OBJS) - $(GCC49_AARCH64_PREFIX)gcc -static $(program_OBJS) -o $(program_NAME) + $(CROSS_COMPILE)gcc -static $(program_OBJS) -o $(program_NAME) clean: @- $(RM) $(program_NAME) diff --git a/linux_app/sbsa-acs-app/include/sbsa_app.h b/linux_app/sbsa-acs-app/include/sbsa_app.h index 861a1056..245a6bfb 100644 --- a/linux_app/sbsa-acs-app/include/sbsa_app.h +++ b/linux_app/sbsa-acs-app/include/sbsa_app.h @@ -19,8 +19,8 @@ #define __SBSA_APP_LINUX_H__ -#define SBSA_APP_VERSION_MAJOR 0 -#define SBSA_APP_VERSION_MINOR 5 +#define SBSA_APP_VERSION_MAJOR 1 +#define SBSA_APP_VERSION_MINOR 0 #include "sbsa_drv_intf.h" @@ -28,6 +28,6 @@ typedef unsigned long int addr_t; typedef unsigned char char8_t; int -execute_tests_pcie(int num_pe, int level); +execute_tests_pcie(int num_pe, int level, unsigned int print_level); #endif diff --git a/linux_app/sbsa-acs-app/include/sbsa_avs_common.h b/linux_app/sbsa-acs-app/include/sbsa_avs_common.h index f85fd8cb..ade94fd0 100755 --- a/linux_app/sbsa-acs-app/include/sbsa_avs_common.h +++ b/linux_app/sbsa-acs-app/include/sbsa_avs_common.h @@ -29,9 +29,9 @@ #define AVS_TIMER_TEST_NUM_BASE 30 #define AVS_WD_TEST_NUM_BASE 40 #define AVS_PCIE_TEST_NUM_BASE 50 -#define AVS_SMMU_TEST_NUM_BASE 60 #define AVS_WAKEUP_TEST_NUM_BASE 70 #define AVS_PER_TEST_NUM_BASE 80 +#define AVS_SMMU_TEST_NUM_BASE 90 #define AVS_SECURE_TEST_NUM_BASE 900 #define STATE_BIT 28 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 fdffed5d..45d3d0f3 100644 --- a/linux_app/sbsa-acs-app/include/sbsa_drv_intf.h +++ b/linux_app/sbsa-acs-app/include/sbsa_drv_intf.h @@ -22,7 +22,8 @@ /* API NUMBERS to COMMUNICATE with DRIVER */ #define SBSA_CREATE_INFO_TABLES 0x1000 -#define SBSA_EXECUTE_TEST 0x2000 +#define SBSA_PCIE_EXECUTE_TEST 0x2000 +#define SBSA_UPDATE_SKIP_LIST 0x3000 #define SBSA_FREE_INFO_TABLES 0x9000 @@ -43,9 +44,14 @@ call_drv_clean_test_env(); int call_drv_execute_test(unsigned int test_num, unsigned int num_pe, - unsigned int level, unsigned long int test_input); + unsigned int level, unsigned int print_level, unsigned long int test_input); + +int +call_update_skip_list(unsigned int api_num, int *p_skip_test_num); int call_drv_wait_for_completion(); +int read_from_proc_sbsa_msg(); + #endif diff --git a/linux_app/sbsa-acs-app/sbsa_app_main.c b/linux_app/sbsa-acs-app/sbsa_app_main.c index ea555f73..943f948f 100644 --- a/linux_app/sbsa-acs-app/sbsa_app_main.c +++ b/linux_app/sbsa-acs-app/sbsa_app_main.c @@ -21,16 +21,18 @@ #include #include #include "include/sbsa_app.h" +#include int g_sbsa_level = 3; int g_print_level = 3; -int g_skip_test_num[3]; +int g_skip_test_num[3] = {10000, 10000, 10000}; +unsigned long int g_exception_ret_addr; int -initialize_test_environment() +initialize_test_environment(unsigned int print_level) { - return call_drv_init_test_env(); + return call_drv_init_test_env(print_level); } void @@ -40,16 +42,37 @@ cleanup_test_environment() call_drv_clean_test_env(); } +void print_help(){ + printf ("\nUsage: Sbsa [-v ] | [-l ] | [--skip ]\n" + "Options:\n" + "-v Verbosity of the Prints\n" + " 1 shows all prints, 5 shows Errors\n" + "-l Level of compliance to be tested for\n" + " As per SBSA spec, 0 to 3\n" + "--skip Test(s) to be skipped\n" + " Refer to section 4 of SBSA_ACS_User_Guide\n" + " To skip a module, use Model_ID as mentioned in user guide\n" + " To skip a particular test within a module, use the exact testcase number\n" + ); +} + int main (int argc, char **argv) { - int c = 0; - char *endptr; + int c = 0,i=0; + char *endptr, *pt; int status; + struct option long_opt[] = + { + {"skip", required_argument, NULL, 'n'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + /* Process Command Line arguments */ - while ((c = getopt (argc, argv, "v:l:")) != -1) + while ((c = getopt_long(argc, argv, "hv:l:", long_opt, NULL)) != -1) { switch (c) { @@ -59,6 +82,18 @@ main (int argc, char **argv) case 'l': g_sbsa_level = strtol(optarg, &endptr, 10); break; + case 'h': + print_help(); + return 1; + break; + case 'n':/*SKIP tests */ + pt = strtok(optarg, ","); + while((pt!=NULL) && (i<3)){ + int a = atoi(pt); + g_skip_test_num[i++] = a; + pt = strtok(NULL, ","); + } + break; case '?': if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); @@ -74,23 +109,23 @@ main (int argc, char **argv) printf ("\n ************ SBSA Architecture Compliance Suite ********* \n"); - printf (" version %d.%d \n", SBSA_APP_VERSION_MAJOR, SBSA_APP_VERSION_MINOR); + printf (" Version %d.%d \n", SBSA_APP_VERSION_MAJOR, SBSA_APP_VERSION_MINOR); - printf ("\n Starting Compliance verification for Level %2d (Print level is %2d)\n\n", g_sbsa_level, g_print_level); + printf ("\n Starting tests for level %2d (Print level is %2d)\n\n", g_sbsa_level, g_print_level); - printf (" Gathering System information.... \n"); - status = initialize_test_environment(); + printf (" Gathering system information.... \n"); + status = initialize_test_environment(g_print_level); if (status) { - printf ("Cannot Initialize test environment. Exiting.... \n"); + printf ("Cannot initialize test environment. Exiting.... \n"); return 0; } printf("\n *** Starting PCIe tests *** \n"); - execute_tests_pcie(1, g_sbsa_level); + execute_tests_pcie(1, g_sbsa_level, g_print_level); - printf("\n *** SBSA Compliance Test Complete. check dmesg for detailed log. *** \n\n"); + printf("\n *** SBSA tests complete *** \n\n"); cleanup_test_environment(); diff --git a/linux_app/sbsa-acs-app/sbsa_app_pcie.c b/linux_app/sbsa-acs-app/sbsa_app_pcie.c index 71832dcb..34c2081a 100644 --- a/linux_app/sbsa-acs-app/sbsa_app_pcie.c +++ b/linux_app/sbsa-acs-app/sbsa_app_pcie.c @@ -27,33 +27,18 @@ #include "sbsa_avs_common.h" +extern int g_skip_test_num[3]; + /** This function calls the SBSA Kernel Module in a loop to execute all the PCIe tests **/ int -execute_tests_pcie(int num_pe, int level) +execute_tests_pcie(int num_pe, int level, unsigned int print_level) { int status; - int test_num; - - for (test_num = AVS_PCIE_TEST_NUM_BASE + 1; test_num <= AVS_PCIE_TEST_NUM_BASE + 7; test_num++) - { - /* Execute PCIe tests one bys one */ - printf("Executing Test %d : ", test_num); - call_drv_execute_test(test_num, num_pe, level, 0); - status = call_drv_wait_for_completion(); - if (IS_TEST_PASS(status)) - printf("RESULT: PASS \n"); - else { - if (IS_TEST_SKIP(status)) - printf("RESULT: SKIP \n"); - else - printf("RESULT: FAIL \n"); - if (test_num == AVS_PCIE_TEST_NUM_BASE + 1) { - printf("\n No ECAM, No point continuing with PCIe tests \n"); - break; - } - } - } + call_update_skip_list(SBSA_UPDATE_SKIP_LIST, g_skip_test_num); + call_drv_execute_test(SBSA_PCIE_EXECUTE_TEST, num_pe, level, print_level, 0); + status = call_drv_wait_for_completion(); + return status; } diff --git a/linux_app/sbsa-acs-app/sbsa_drv_intf.c b/linux_app/sbsa-acs-app/sbsa_drv_intf.c index 0c38987c..2bb577ce 100644 --- a/linux_app/sbsa-acs-app/sbsa_drv_intf.c +++ b/linux_app/sbsa-acs-app/sbsa_drv_intf.c @@ -21,9 +21,6 @@ #include #include "include/sbsa_drv_intf.h" -#define SIZE 1 -#define NUMELEM 5 - typedef struct __SBSA_DRV_PARMS__ { @@ -73,15 +70,17 @@ call_drv_wait_for_completion() arg0 = DRV_STATUS_PENDING; - while (arg0 == DRV_STATUS_PENDING) + while (arg0 == DRV_STATUS_PENDING){ call_drv_get_status(&arg0, &arg1, &arg2); + read_from_proc_sbsa_msg(); + } return arg1; } int -call_drv_init_test_env() +call_drv_init_test_env(unsigned int print_level) { FILE *fd = NULL; sbsa_drv_parms_t test_params; @@ -95,7 +94,7 @@ call_drv_init_test_env() } test_params.api_num = SBSA_CREATE_INFO_TABLES; - test_params.arg1 = 0; + test_params.arg1 = print_level; test_params.arg2 = 0; fwrite(&test_params,1,sizeof(test_params),fd); @@ -132,8 +131,8 @@ call_drv_clean_test_env() } int -call_drv_execute_test(unsigned int test_num, unsigned int num_pe, - unsigned int level, unsigned long int test_input) +call_drv_execute_test(unsigned int api_num, unsigned int num_pe, + unsigned int level, unsigned int print_level, unsigned long int test_input) { FILE *fd = NULL; sbsa_drv_parms_t test_params; @@ -146,11 +145,11 @@ call_drv_execute_test(unsigned int test_num, unsigned int num_pe, return 1; } - test_params.api_num = SBSA_EXECUTE_TEST; + test_params.api_num = api_num; test_params.num_pe = num_pe; test_params.level = level; - test_params.arg0 = test_num; - test_params.arg1 = test_input; + test_params.arg0 = test_input; + test_params.arg1 = print_level; test_params.arg2 = 0; fwrite(&test_params,1,sizeof(test_params),fd); @@ -159,12 +158,58 @@ call_drv_execute_test(unsigned int test_num, unsigned int num_pe, } - int -pal_os_driver_release() +call_update_skip_list(unsigned int api_num, int *p_skip_test_num) { + FILE *fd = NULL; + sbsa_drv_parms_t test_params; + + fd = fopen("/proc/sbsa", "rw+"); + + if (NULL == fd) + { + printf("fopen failed \n"); + return 1; + } + test_params.api_num = api_num; + test_params.num_pe = 0; + test_params.level = 0; + test_params.arg0 = p_skip_test_num[0]; + test_params.arg1 = p_skip_test_num[1]; + test_params.arg2 = p_skip_test_num[2]; + fwrite(&test_params,1,sizeof(test_params),fd); + + fclose(fd); } +typedef struct __SBSA_MSG__ { + char string[92]; + unsigned long data; +}sbsa_msg_parms_t; + +int read_from_proc_sbsa_msg() { + + char buf_msg[sizeof(sbsa_msg_parms_t)]; + + FILE *fd = NULL; + sbsa_msg_parms_t msg_params; + + fd = fopen("/proc/sbsa_msg", "r"); + + fseek(fd, 0, SEEK_SET); + + if (NULL == fd) { + printf("fopen failed \n"); + return 1; + } + + /* Print Until buffer is empty */ + while(fread(buf_msg,sizeof(buf_msg),1,fd)){ + printf("%s", buf_msg); + } + + fclose(fd); +} diff --git a/platform/pal_uefi/SbsaPalLib.inf b/platform/pal_uefi/SbsaPalLib.inf index 684e98ea..451397a7 100644 --- a/platform/pal_uefi/SbsaPalLib.inf +++ b/platform/pal_uefi/SbsaPalLib.inf @@ -34,7 +34,6 @@ src/pal_timer_wd.c src/pal_pcie.c src/pal_iovirt.c - src/pal_smmu.c src/pal_pcie_enumeration.c src/pal_peripherals.c @@ -68,4 +67,4 @@ gEfiAcpiTableGuid [BuildOptions] - GCC:*_*_*_ASM_FLAGS = -march=armv8.1-a + GCC:*_*_*_ASM_FLAGS = -march=armv8.2-a diff --git a/platform/pal_uefi/include/pal_uefi.h b/platform/pal_uefi/include/pal_uefi.h index 8699508d..b5bdcf4d 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, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,14 @@ #ifndef __PAL_UEFI_H__ #define __PAL_UEFI_H__ -extern void* g_sbsa_log_file_handle; +extern VOID* g_sbsa_log_file_handle; +extern UINT32 g_print_level; + +#define AVS_PRINT_ERR 5 /* Only Errors. use this to de-clutter the terminal and focus only on specifics */ +#define AVS_PRINT_WARN 4 /* Only warnings & errors. use this to de-clutter the terminal and focus only on specifics */ +#define AVS_PRINT_TEST 3 /* Test description and result descriptions. THIS is DEFAULT */ +#define AVS_PRINT_DEBUG 2 /* For Debug statements. contains register dumps etc */ +#define AVS_PRINT_INFO 1 /* Print all statements. Do not use unless really needed */ typedef struct { UINT64 Arg0; @@ -30,6 +37,8 @@ typedef struct { UINT64 Arg7; } ARM_SMC_ARGS; +#define sbsa_print(verbose, string, ...) if(verbose >= g_print_level) \ + Print(string, ##__VA_ARGS__) typedef struct { UINT32 num_of_pe; @@ -50,7 +59,7 @@ typedef struct { PE_INFO_ENTRY pe_info[]; }PE_INFO_TABLE; -void pal_pe_data_cache_ops_by_va(UINT64 addr, UINT32 type); +VOID pal_pe_data_cache_ops_by_va(UINT64 addr, UINT32 type); #define CLEAN_AND_INVALIDATE 0x1 #define CLEAN 0x2 @@ -79,7 +88,7 @@ typedef struct { }GIC_INFO_ENTRY; /** - @brief GIC Information Table + @brief GIC Information Table **/ typedef struct { GIC_INFO_HDR header; @@ -97,10 +106,9 @@ typedef struct { UINT32 virtual_timer_flag; UINT32 virtual_timer_gsiv; UINT32 el2_virt_timer_gsiv; - UINT64 CntControl_base; - UINT64 CntRead_base; UINT32 num_platform_timer; UINT32 num_watchdog; + UINT32 sys_timer_status; }TIMER_INFO_HDR; #define TIMER_TYPE_SYS_TIMER 0x2001 @@ -181,6 +189,12 @@ typedef enum { IOVIRT_NODE_SMMU_V3 = 0x04 }IOVIRT_NODE_TYPE; +typedef enum { + IOVIRT_FLAG_DEVID_OVERLAP_SHIFT, + IOVIRT_FLAG_STRID_OVERLAP_SHIFT, + IOVIRT_FLAG_SMMU_CTX_INT_SHIFT, +}IOVIRT_FLAG_SHIFT; + typedef struct { UINT32 input_base; UINT32 id_count; @@ -204,6 +218,7 @@ typedef struct { UINT32 type; UINT32 num_data_map; NODE_DATA data; + UINT32 flags; NODE_DATA_MAP data_map[]; }IOVIRT_BLOCK; @@ -230,12 +245,15 @@ typedef struct { UINT32 num_usb; ///< Number of USB Controllers UINT32 num_sata; ///< Number of SATA Controllers UINT32 num_uart; ///< Number of UART Controllers + UINT32 num_all; ///< Number of all PCI Controllers }PERIPHERAL_INFO_HDR; typedef enum { PERIPHERAL_TYPE_USB = 0x2000, PERIPHERAL_TYPE_SATA, - PERIPHERAL_TYPE_UART + PERIPHERAL_TYPE_UART, + PERIPHERAL_TYPE_OTHER, + PERIPHERAL_TYPE_NONE }PER_INFO_TYPE_e; /** @@ -248,6 +266,9 @@ typedef struct { UINT64 base1; ///< Base Address of the controller UINT32 irq; ///< IRQ to install an ISR UINT32 flags; + UINT32 msi; ///< MSI Enabled + UINT32 msix; ///< MSIX Enabled + UINT32 max_pasids; }PERIPHERAL_INFO_BLOCK; /** @@ -284,6 +305,6 @@ typedef struct { } MEMORY_INFO_TABLE; -void pal_memory_create_info_table(MEMORY_INFO_TABLE *memoryInfoTable); +VOID pal_memory_create_info_table(MEMORY_INFO_TABLE *memoryInfoTable); #endif diff --git a/platform/pal_uefi/src/AArch64/AvsTestInfra.S b/platform/pal_uefi/src/AArch64/AvsTestInfra.S index 9bfae852..cd3b9f17 100644 --- a/platform/pal_uefi/src/AArch64/AvsTestInfra.S +++ b/platform/pal_uefi/src/AArch64/AvsTestInfra.S @@ -39,4 +39,3 @@ ASM_PFX(DataCacheInvalidateVA): dsb ish isb ret - diff --git a/platform/pal_uefi/src/pal_acpi.c b/platform/pal_uefi/src/pal_acpi.c index 73bb175b..0b429fca 100644 --- a/platform/pal_uefi/src/pal_acpi.c +++ b/platform/pal_uefi/src/pal_acpi.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ #include #include "Include/IndustryStandard/Acpi61.h" +#include "include/pal_uefi.h" /** @brief Use UEFI System Table to look up Acpi20TableGuid and returns the Xsdt Address @@ -43,7 +44,6 @@ pal_get_xsdt_ptr() CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) ) { // A match was found. - // Rsdp = (EFI_ACPI_6_1_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable; break; } @@ -74,7 +74,7 @@ pal_get_madt_ptr() Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) pal_get_xsdt_ptr(); if (Xsdt == NULL) { - Print(L"XSDT not found \n"); + sbsa_print(AVS_PRINT_ERR, L"XSDT not found \n"); return 0; } @@ -108,7 +108,7 @@ pal_get_gtdt_ptr() Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) pal_get_xsdt_ptr(); if (Xsdt == NULL) { - Print(L"XSDT not found \n"); + sbsa_print(AVS_PRINT_ERR, L"XSDT not found \n"); return 0; } @@ -141,7 +141,7 @@ pal_get_mcfg_ptr() Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) pal_get_xsdt_ptr(); if (Xsdt == NULL) { - Print(L"XSDT not found \n"); + sbsa_print(AVS_PRINT_ERR, L"XSDT not found \n"); return 0; } @@ -158,7 +158,7 @@ pal_get_mcfg_ptr() } /** - @brief Iterate through the tables pointed by XSDT and return MCFG Table address + @brief Iterate through the tables pointed by XSDT and return SPCR Table address @param None @@ -174,7 +174,7 @@ pal_get_spcr_ptr() Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) pal_get_xsdt_ptr(); if (Xsdt == NULL) { - Print(L"XSDT not found \n"); + sbsa_print(AVS_PRINT_ERR, L"XSDT not found \n"); return 0; } @@ -207,7 +207,7 @@ pal_get_iort_ptr() Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) pal_get_xsdt_ptr(); if (Xsdt == NULL) { - Print(L"XSDT not found \n"); + sbsa_print(AVS_PRINT_ERR, L"XSDT not found \n"); return 0; } diff --git a/platform/pal_uefi/src/pal_gic.c b/platform/pal_uefi/src/pal_gic.c index adb7cf8c..22a8eec2 100644 --- a/platform/pal_uefi/src/pal_gic.c +++ b/platform/pal_uefi/src/pal_gic.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,22 +33,6 @@ EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL; UINT64 pal_get_madt_ptr(); -/* - *Example table - * info = { {3, 4, 1, 1}, - * {0x1000, 0x2fc00000}, - * {0x1000, 0x2fc00000}, - * {0x1000, 0x2fc00000}, - * {0x1000, 0x2fc00000}, - * {0x1001, 0x2fd00000}, - * {0x1001, 0x2fd00000}, - * {0x1001, 0x2fd00000}, - * {0x1001, 0x2fd00000}, - * {0x1002, 0x2fe00000}, - * {0x1003, 0x2ff00000}, - * }; - * - */ /** @brief Populate information about the GIC sub-system at the input address. In a UEFI-ACPI framework, this information is part of the MADT table. @@ -60,13 +44,13 @@ pal_get_madt_ptr(); VOID pal_gic_create_info_table(GIC_INFO_TABLE *GicTable) { - EFI_ACPI_6_1_GIC_STRUCTURE *Entry; - GIC_INFO_ENTRY *GicEntry; + EFI_ACPI_6_1_GIC_STRUCTURE *Entry = NULL; + GIC_INFO_ENTRY *GicEntry = NULL; UINT32 Length= 0; UINT32 TableLength; if (GicTable == NULL) { - Print(L"Input GIC Table Pointer is NULL. Cannot create GIC INFO \n"); + sbsa_print(AVS_PRINT_ERR, L"Input GIC Table Pointer is NULL. Cannot create GIC INFO \n"); return; } @@ -78,11 +62,11 @@ pal_gic_create_info_table(GIC_INFO_TABLE *GicTable) gMadtHdr = (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *) pal_get_madt_ptr(); - if (gMadtHdr != 0) { + if (gMadtHdr != NULL) { TableLength = gMadtHdr->Header.Length; - //Print(L" MADT is at %x and length is %x \n", gMadtHdr, TableLength); + sbsa_print(AVS_PRINT_INFO, L" MADT is at %x and length is %x \n", gMadtHdr, TableLength); } else { - Print(L"MADT not found \n"); + sbsa_print(AVS_PRINT_ERR, L" MADT not found \n"); return; } @@ -96,15 +80,15 @@ pal_gic_create_info_table(GIC_INFO_TABLE *GicTable) if (Entry->PhysicalBaseAddress != 0) { GicEntry->type = ENTRY_TYPE_CPUIF; GicEntry->base = Entry->PhysicalBaseAddress; - //Print(L"GIC CPUIF base %x \n", GicEntry->base); + sbsa_print(AVS_PRINT_INFO, L"GIC CPUIF base %x \n", GicEntry->base); GicEntry++; } if (Entry->GICRBaseAddress != 0) { GicEntry->type = ENTRY_TYPE_GICRD; GicEntry->base = Entry->GICRBaseAddress; - //Print(L"GIC RD base %x \n", GicEntry->base); - GicTable->header.num_gicrd++; + sbsa_print(AVS_PRINT_INFO, L"GIC RD base %x \n", GicEntry->base); + GicTable->header.num_gicrd++; GicEntry++; } } @@ -113,15 +97,15 @@ pal_gic_create_info_table(GIC_INFO_TABLE *GicTable) GicEntry->type = ENTRY_TYPE_GICD; GicEntry->base = ((EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE *)Entry)->PhysicalBaseAddress; GicTable->header.gic_version = ((EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE *)Entry)->GicVersion; - GicTable->header.num_gicd++; + GicTable->header.num_gicd++; GicEntry++; } if (Entry->Type == EFI_ACPI_6_1_GIC_ITS) { GicEntry->type = ENTRY_TYPE_GICITS; GicEntry->base = ((EFI_ACPI_6_1_GIC_ITS_STRUCTURE *)Entry)->PhysicalBaseAddress; - //Print(L"GIC ITS base %x \n", GicEntry->base); - GicTable->header.num_its++; + sbsa_print(AVS_PRINT_INFO, L"GIC ITS base %x \n", GicEntry->base); + GicTable->header.num_its++; GicEntry++; } Length += Entry->Length; @@ -154,15 +138,11 @@ pal_gic_install_isr(UINT32 int_id, VOID (*isr)()) if (EFI_ERROR(Status)) { return 0xFFFFFFFF; } - - // + //First disable the interrupt to enable a clean handoff to our Interrupt handler. - // gInterrupt->DisableInterruptSource(gInterrupt, int_id); - // //Register our handler - // Status = gInterrupt->RegisterInterruptSource (gInterrupt, int_id, isr); if (EFI_ERROR(Status)) { Status = gInterrupt->RegisterInterruptSource (gInterrupt, int_id, NULL); //Deregister existing handler @@ -193,9 +173,7 @@ pal_gic_end_of_interrupt(UINT32 int_id) return 0xFFFFFFFF; } - // //EndOfInterrupt. - // gInterrupt->EndOfInterrupt(gInterrupt, int_id); return 0; diff --git a/platform/pal_uefi/src/pal_iovirt.c b/platform/pal_uefi/src/pal_iovirt.c index ae337f13..4b2c8ba6 100644 --- a/platform/pal_uefi/src/pal_iovirt.c +++ b/platform/pal_uefi/src/pal_iovirt.c @@ -52,32 +52,43 @@ dump_block(IOVIRT_BLOCK *block) { NODE_DATA_MAP *map = &block->data_map[0]; switch(block->type) { case IOVIRT_NODE_ITS_GROUP: - Print(L"\nITS Group:\n Num ITS:%d\n", (*map).id[0]); + sbsa_print(AVS_PRINT_INFO, L"\nITS Group:\n Num ITS:%d\n", (*map).id[0]); for(i = 0; i < block->data.its_count; i++) - Print(L"%d ", (*map).id[i]); - Print(L"\n"); + sbsa_print(AVS_PRINT_INFO, L"%d ", (*map).id[i]); + sbsa_print(AVS_PRINT_INFO, L"\n"); return; case IOVIRT_NODE_NAMED_COMPONENT: - Print(L"\nNamed Component:\n Device Name:%a\n", block->data.name); + sbsa_print(AVS_PRINT_INFO, L"\nNamed Component:\n Device Name:%a\n", block->data.name); break; case IOVIRT_NODE_PCI_ROOT_COMPLEX: - Print(L"\nRoot Complex:\n PCI segment number:%d\n", block->data.segment); + sbsa_print(AVS_PRINT_INFO, L"\nRoot Complex:\n PCI segment number:%d\n", block->data.segment); break; case IOVIRT_NODE_SMMU: case IOVIRT_NODE_SMMU_V3: - Print(L"\nSMMU:\n Major Rev:%d\n Base Address:0x%x\n", block->data.smmu.arch_major_rev, block->data.smmu.base); + sbsa_print(AVS_PRINT_INFO, L"\nSMMU:\n Major Rev:%d\n Base Address:0x%x\n", block->data.smmu.arch_major_rev, block->data.smmu.base); break; } - Print(L"Number of ID Mappings:%d\n", block->num_data_map); + sbsa_print(AVS_PRINT_INFO, L"Number of ID Mappings:%d\n", block->num_data_map); for(i = 0; i < block->num_data_map; i++, map++) { - Print(L"\n input_base:0x%x\n id_count:0x%x\n output_base:0x%x\n output ref:0x%x\n", + sbsa_print(AVS_PRINT_INFO, L"\n input_base:0x%x\n id_count:0x%x\n output_base:0x%x\n output ref:0x%x\n", (*map).map.input_base, (*map).map.id_count, (*map).map.output_base, (*map).map.output_ref); } - Print(L"\n"); + sbsa_print(AVS_PRINT_INFO, L"\n"); +} + +STATIC UINTN +smmu_ctx_int_distinct(UINT64 *ctx_int, INTN ctx_int_cnt) { + INTN i, j; + for(i = 0; i < ctx_int_cnt - 1; i++) { + for(j = i + 1; j < ctx_int_cnt; j++) { + if(*((UINT32*)&ctx_int[i]) == *((UINT32*)&ctx_int[j])) + return 0; + } + } + return 1; } -/* STATIC VOID dump_iort_table(IOVIRT_INFO_TABLE *iovirt) { @@ -86,51 +97,67 @@ dump_iort_table(IOVIRT_INFO_TABLE *iovirt) for(i = 0; i < iovirt->num_blocks; i++, block = IOVIRT_NEXT_BLOCK(block)) dump_block(block); } -*/ /** @brief Check ID mappings in all blocks for any overlap of ID ranges @param iort IoVirt table **/ STATIC VOID -check_mapping_overlap(IOVIRT_INFO_TABLE *iort) +check_mapping_overlap(IOVIRT_INFO_TABLE *iovirt) { - IOVIRT_BLOCK *key_block = &iort->blocks[0], *block, *tmp; + IOVIRT_BLOCK *key_block = &iovirt->blocks[0], *block, *tmp; NODE_DATA_MAP *key_map = &key_block->data_map[0], *map; - UINT32 i,j,k,l,a,b,c,d; + UINT32 n_key_blocks, n_blocks, n_key_maps, n_maps; + UINT32 key_start, key_end, start, end; /* Starting from first block, compare each mapping with all the */ /* mappings that follow it in the table */ - for(i = 0; i < iort->num_blocks; i++, key_block = IOVIRT_NEXT_BLOCK(key_block)) { + for(key_block = &iovirt->blocks[0], n_key_blocks = iovirt->num_blocks; + n_key_blocks > 0; + key_block = IOVIRT_NEXT_BLOCK(key_block), n_key_blocks--) + { if(key_block->type == IOVIRT_NODE_ITS_GROUP) continue; - for(j = 0, key_map = &key_block->data_map[0]; j < key_block->num_data_map; j++, key_map++) { - a = (*key_map).map.output_base; - b = a + (*key_map).map.id_count; - for(k = i, block = key_block; k < iort->num_blocks; k++, block = IOVIRT_NEXT_BLOCK(block)) { + for(key_map = &key_block->data_map[0], n_key_maps = key_block->num_data_map; + n_key_maps > 0; + key_map++, n_key_maps--) + { + key_start = (*key_map).map.output_base; + key_end = key_start + (*key_map).map.id_count - 1; + for(block = key_block, n_blocks = n_key_blocks; + n_blocks > 0; + block = IOVIRT_NEXT_BLOCK(block), n_blocks--) + { if(block->type == IOVIRT_NODE_ITS_GROUP) continue; - l = 0; + n_maps = block->num_data_map; map = &block->data_map[0]; if(block == key_block) { map = key_map+1; - l = j + 1; + n_maps--; } - for(;l < block->num_data_map; l++, map++) { + for(;n_maps > 0; map++, n_maps--) + { if((*map).map.output_ref != (*key_map).map.output_ref) continue; - c = (*map).map.output_base; - d = c + (*map).map.id_count; - if((a >= c && a <=d) || - (b >= c && b <=d) || - (a < c && b > d)) { - tmp = ADD_PTR(IOVIRT_BLOCK, iort, (*map).map.output_ref); - if(tmp->type == IOVIRT_NODE_ITS_GROUP) - Print(L"\nOverlapping device ids %x-%x and %x-%x \n", a, b, c, d); - else - Print(L"\nOverlapping stream ids %x-%x and %x-%x \n", a, b, c, d); - Print(L"for the following 2 blocks\n"); - dump_block(block); - dump_block(key_block); + start = (*map).map.output_base; + end = start + (*map).map.id_count - 1; + if((key_start >= start && key_start <= end) || + (key_end >= start && key_end <= end) || + (key_start < start && key_end > end)) + { + tmp = ADD_PTR(IOVIRT_BLOCK, iovirt, (*map).map.output_ref); + if(tmp->type == IOVIRT_NODE_ITS_GROUP) { + key_block->flags |= (1 << IOVIRT_FLAG_DEVID_OVERLAP_SHIFT); + block->flags |= (1 << IOVIRT_FLAG_DEVID_OVERLAP_SHIFT); + sbsa_print(AVS_PRINT_INFO, L"\nOverlapping device ids %x-%x and %x-%x \n", + key_start, key_end, start, end); + } + else { + key_block->flags |= (1 << IOVIRT_FLAG_STRID_OVERLAP_SHIFT); + block->flags |= (1 << IOVIRT_FLAG_STRID_OVERLAP_SHIFT); + sbsa_print(AVS_PRINT_INFO, L"\nOverlapping stream ids %x-%x and %x-%x \n", + key_start, key_end, start, end); + } } } } @@ -148,15 +175,15 @@ check_mapping_overlap(IOVIRT_INFO_TABLE *iort) STATIC UINT32 find_block(IOVIRT_BLOCK *key, IOVIRT_INFO_TABLE *IoVirtTable) { IOVIRT_BLOCK *block = &IoVirtTable->blocks[0]; - NODE_DATA_MAP *data_map; + UINT8 *cmp_end; UINT32 i, cmp_size; for(i = 0; i < IoVirtTable->num_blocks; i++, block = IOVIRT_NEXT_BLOCK(block)) { - data_map = &block->data_map[0]; - cmp_size = (UINT8*)data_map - (UINT8*)block; + cmp_end = (UINT8*) &block->flags; + cmp_size = cmp_end - (UINT8*)block; if(key->type == block->type) { /* Compare identfiers array as well in case of ITS group */ if(block->type == IOVIRT_NODE_ITS_GROUP) - cmp_size += block->data.its_count * sizeof(UINT32); + cmp_size += (block->data.its_count * sizeof(UINT32) + sizeof(block->flags)); if(!CompareMem(key, block, cmp_size)) return (UINT8*)block - (UINT8*)IoVirtTable; } @@ -174,10 +201,10 @@ find_block(IOVIRT_BLOCK *key, IOVIRT_INFO_TABLE *IoVirtTable) { where IOVIRT block is to be added. This is modified to the next address where new IOVIRT block can be created. - @return offset from the IO Virt base address to the IOVIRT block + @return offset from the IOVirt Table base address to the IOVIRT block base address passed in **block OR - offset from the IO Virt base address to the IOVIRT block + offset from the IO Virt Table base address to the IOVIRT block base address where this block is already present in the table. **/ @@ -190,7 +217,7 @@ iort_add_block(IORT_TABLE *iort, IORT_NODE *iort_node, IOVIRT_INFO_TABLE *IoVirt NODE_DATA *data = &((*block)->data); VOID *node_data = &(iort_node->node_data[0]); - /* Populate the fields independent of node type */ + /* Populate the fields that are independent of node type */ (*block)->type = iort_node->type; (*block)->num_data_map = iort_node->mapping_count; /* Populate fields dependent on node type */ @@ -211,6 +238,7 @@ iort_add_block(IORT_TABLE *iort, IORT_NODE *iort_node, IOVIRT_INFO_TABLE *IoVirt break; case IOVIRT_NODE_PCI_ROOT_COMPLEX: (*data).segment = ((IORT_ROOT_COMPLEX*)node_data)->pci_segment_number; + CopyMem(&(*data_map).id[0], &((IORT_ROOT_COMPLEX*)node_data)->memory_properties, sizeof(UINT32) * 3); count = &IoVirtTable->num_pci_rcs; break; case IOVIRT_NODE_SMMU: @@ -224,7 +252,7 @@ iort_add_block(IORT_TABLE *iort, IORT_NODE *iort_node, IOVIRT_INFO_TABLE *IoVirt count = &IoVirtTable->num_smmus; break; default: - Print(L"Invalid IORT node type\n"); + sbsa_print(AVS_PRINT_ERR, L"Invalid IORT node type\n"); return (UINT32) -1; } @@ -234,8 +262,17 @@ iort_add_block(IORT_TABLE *iort, IORT_NODE *iort_node, IOVIRT_INFO_TABLE *IoVirt if(offset) return offset; + (*block)->flags = 0; /* Calculate the position where next block should be added */ next_block = ADD_PTR(IOVIRT_BLOCK, data_map, (*block)->num_data_map * sizeof(NODE_DATA_MAP)); + if(iort_node->type == IOVIRT_NODE_SMMU) { + /* Check if the context bank interrupt ids for this smmu node are unique. Set the flags accordingly */ + if(!smmu_ctx_int_distinct(ADD_PTR(UINT64, iort_node, ((IORT_SMMU *)node_data)->context_interrupt_offset), + ((IORT_SMMU *)node_data)->context_interrupt_count)) + { + (*block)->flags |= (1 << IOVIRT_FLAG_SMMU_CTX_INT_SHIFT); + } + } if((*block)->type != IOVIRT_NODE_ITS_GROUP) { IORT_ID_MAPPING *map = ADD_PTR(IORT_ID_MAPPING, iort_node, iort_node->mapping_offset); @@ -309,12 +346,47 @@ pal_iovirt_create_info_table(IOVIRT_INFO_TABLE *IoVirtTable) /* Create iovirt block for each IORT node*/ for (i = 0; i < iort->node_count; i++) { if (iort_node >= iort_end) { - Print(L"Bad IORT table \n"); + sbsa_print(AVS_PRINT_ERR, L"Bad IORT table \n"); return; } iort_add_block(iort, iort_node, IoVirtTable, &next_block); iort_node = ADD_PTR(IORT_NODE, iort_node, iort_node->length); } - //dump_iort_table(IoVirtTable); + dump_iort_table(IoVirtTable); check_mapping_overlap(IoVirtTable); } + +/** + @brief Check if given SMMU node has unique context bank interrupt ids + + @param smmu_block smmu IOVIRT block base address + + @return 0 if test fails, 1 if test passes +**/ +UINT32 +pal_iovirt_check_unique_ctx_intid(UINT64 smmu_block) +{ + IOVIRT_BLOCK *block = (IOVIRT_BLOCK *)smmu_block; + /* This test has already been done while parsing IORT */ + /* Check the flags to get the test result */ + if(block->flags & (1 << IOVIRT_FLAG_SMMU_CTX_INT_SHIFT)) + return 0; + return 1; +} + +/** + @brief Check if given root complex node has unique requestor id to stream id mapping + + @param rc_block root complex IOVIRT block base address + + @return 0 if test fails, 1 if test passes +**/ + +UINT32 +pal_iovirt_unique_rid_strid_map(UINT64 rc_block) +{ + IOVIRT_BLOCK *block = (IOVIRT_BLOCK *)rc_block; + if(block->flags & (1 << IOVIRT_FLAG_STRID_OVERLAP_SHIFT)) + return 0; + return 1; +} diff --git a/platform/pal_uefi/src/pal_misc.c b/platform/pal_uefi/src/pal_misc.c index 015e1898..0c3d6b08 100644 --- a/platform/pal_uefi/src/pal_misc.c +++ b/platform/pal_uefi/src/pal_misc.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ UINT8 *gSharedMemory; /** - @brief Provides a single point of abstraction to read from all + @brief Provides a single point of abstraction to read from all Memory Mapped IO address @param addr 64-bit address @@ -37,19 +37,18 @@ pal_mmio_read(UINT64 addr) UINT32 data; if (addr & 0x3) { - Print(L"\n Error-Input address is not aligned. Masking the last 2 bits \n"); + sbsa_print(AVS_PRINT_WARN, L"\n Error-Input address is not aligned. Masking the last 2 bits \n"); addr = addr & ~(0x3); //make sure addr is aligned to 4 bytes } - //Print(L"Address = %8x ", addr); data = (*(volatile UINT32 *)addr); - //Print(L" data = %8x \n", data); + sbsa_print(AVS_PRINT_INFO, L" pal_mmio_read Address = %8x Data = %x \n", addr, data); - return data; + return data; } /** - @brief Provides a single point of abstraction to write to all + @brief Provides a single point of abstraction to write to all Memory Mapped IO address @param addr 64-bit address @@ -60,7 +59,7 @@ pal_mmio_read(UINT64 addr) VOID pal_mmio_write(UINT64 addr, UINT32 data) { - //Print(L"Address = %8x Data = %8x \n", addr, data); + sbsa_print(AVS_PRINT_INFO, L" pal_mmio_write Address = %8x Data = %x \n", addr, data); *(volatile UINT32 *)addr = data; } @@ -85,13 +84,14 @@ pal_print(CHAR8 *string, UINT64 data) AsciiPrint(Buffer); Status = ShellWriteFile(g_sbsa_log_file_handle, &BufferSize, (VOID*)Buffer); if(EFI_ERROR(Status)) - Print(L"Error in writing to log file\n"); + sbsa_print(AVS_PRINT_ERR, L"Error in writing to log file\n"); } else AsciiPrint(string, data); } /** - @brief Sends a string to the output console + @brief Sends a string to the output console without using UEFI print function + This function will get COMM port address and directly writes to the addr char-by-char @param string An ASCII string @param data data for the formatted output @@ -101,10 +101,37 @@ pal_print(CHAR8 *string, UINT64 data) VOID pal_print_raw(UINT64 addr, CHAR8 *string, UINT64 data) { - UINTN i = 0; - while(string[i] != '\0') - *(volatile UINT8 *)addr = string[i++]; + UINT8 j, buffer[16]; + INT8 i=0; + for(;*string!='\0';++string){ + if(*string == '%'){ + ++string; + if(*string == 'd'){ + while(data != 0){ + j = data%10; + data = data/10; + buffer[i]= j + 48 ; + i = i+1; + } + } else if(*string == 'x' || *string == 'X'){ + while(data != 0){ + j = data & 0xf; + data = data >> 4; + buffer[i]= j + ((j > 9) ? 55 : 48) ; + i = i+1; + } + } + if(i>0) { + while(i>=0) + *(volatile UINT8 *)addr = buffer[--i]; + } else + *(volatile UINT8 *)addr = 48; + + } else + *(volatile UINT8 *)addr = *string; + } } + /** @brief Free the memory allocated by UEFI Framework APIs @param Buffer the base address of the memory range to be freed @@ -130,16 +157,16 @@ VOID pal_mem_allocate_shared(UINT32 num_pe, UINT32 sizeofentry) { EFI_STATUS Status; - gSharedMemory = 0; + gSharedMemory = 0; Status = gBS->AllocatePool ( EfiBootServicesData, (num_pe * sizeofentry), (VOID **) &gSharedMemory ); - //Print(L"Shared memory is %llx \n", gSharedMemory); + sbsa_print(AVS_PRINT_INFO, L"Shared memory is %llx \n", gSharedMemory); if (EFI_ERROR(Status)) { - Print(L"Allocate Pool shared memory failed %x \n", Status); + sbsa_print(AVS_PRINT_ERR, L"Allocate Pool shared memory failed %x \n", Status); } pal_pe_data_cache_ops_by_va((UINT64)&gSharedMemory, CLEAN_AND_INVALIDATE); @@ -149,6 +176,10 @@ pal_mem_allocate_shared(UINT32 num_pe, UINT32 sizeofentry) /** @brief Return the base address of the shared memory region to the VAL layer + + @param None + + @return shared memory region address **/ UINT64 pal_mem_get_shared_addr() @@ -160,6 +191,10 @@ pal_mem_get_shared_addr() /** @brief Free the shared memory region allocated above + + @param None + + @return None **/ VOID pal_mem_free_shared() diff --git a/platform/pal_uefi/src/pal_pcie.c b/platform/pal_uefi/src/pal_pcie.c index 74318552..16d408fa 100644 --- a/platform/pal_uefi/src/pal_pcie.c +++ b/platform/pal_uefi/src/pal_pcie.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,10 @@ pal_get_mcfg_ptr(); /** @brief Returns the PCI ECAM address from the ACPI MCFG Table address + + @param None + + @return None **/ UINT64 pal_pcie_get_mcfg_ecam() @@ -42,9 +46,9 @@ pal_pcie_get_mcfg_ecam() gMcfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *) pal_get_mcfg_ptr(); - if (gMcfgHdr == 0) { - //Print(L"ACPI - MCFG Table not found. Setting ECAM Base to 0. \n"); - return 0x0; + if (gMcfgHdr == NULL) { + sbsa_print(AVS_PRINT_WARN, L"ACPI - MCFG Table not found. Setting ECAM Base to 0. \n"); + return 0x0; } Entry = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *) (gMcfgHdr + 1); @@ -55,28 +59,39 @@ pal_pcie_get_mcfg_ecam() /** @brief Fill the PCIE Info table with the details of the PCIe sub-system + + @param PcieTable - Address where the PCIe information needs to be filled. + + @return None **/ VOID pal_pcie_create_info_table(PCIE_INFO_TABLE *PcieTable) { - EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *Entry; + EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *Entry = NULL; UINT32 length = sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER); UINT32 i = 0; + if (PcieTable == NULL) { + sbsa_print(AVS_PRINT_ERR, L"Input PCIe Table Pointer is NULL. Cannot create PCIe INFO \n"); + return; + } + PcieTable->num_entries = 0; gMcfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *) pal_get_mcfg_ptr(); - if (gMcfgHdr == 0) { - if(PLATFORM_OVERRIDE_PCIE_ECAM_BASE) { - PcieTable->block[i].ecam_base = PLATFORM_OVERRIDE_PCIE_ECAM_BASE; - PcieTable->block[i].start_bus_num = PLATFORM_OVERRIDE_PCIE_START_BUS_NUM; - PcieTable->block[i].segment_num = 0; - PcieTable->num_entries = 1; - } - //Print(L"ACPI - MCFG Table not found. Setting ECAM Base to 0. \n"); - return; + if (gMcfgHdr == NULL) { + sbsa_print(AVS_PRINT_DEBUG, L"ACPI - MCFG Table not found. \n"); + return; + } + + if(PLATFORM_OVERRIDE_PCIE_ECAM_BASE) { + PcieTable->block[i].ecam_base = PLATFORM_OVERRIDE_PCIE_ECAM_BASE; + PcieTable->block[i].start_bus_num = PLATFORM_OVERRIDE_PCIE_START_BUS_NUM; + PcieTable->block[i].segment_num = 0; + PcieTable->num_entries = 1; + return; } Entry = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *) (gMcfgHdr + 1); diff --git a/platform/pal_uefi/src/pal_pcie_enumeration.c b/platform/pal_uefi/src/pal_pcie_enumeration.c index faa5cc46..a7487234 100644 --- a/platform/pal_uefi/src/pal_pcie_enumeration.c +++ b/platform/pal_uefi/src/pal_pcie_enumeration.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,14 +25,15 @@ #include #include "include/sbsa_pcie_enum.h" +#include "include/pal_uefi.h" /** - @brief Increment the Device number (and Bus number if Dev num reaches 32) to the next valid value. + @brief Increment the Device number (and Bus number if Dev num reaches 32) to the next valid value. @param StartBdf Segment/Bus/Dev/Func in the format created by PCIE_CREATE_BDF - @return the new incremented BDF + @return the new incremented BDF **/ UINT32 incrementBusDev(UINT32 StartBdf) @@ -82,7 +83,7 @@ palPcieGetBdf(UINT32 ClassCode, UINT32 StartBdf) Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer); if (EFI_ERROR (Status)) { - //AsciiPrint ("No PCI devices found in the system\n"); + sbsa_print(AVS_PRINT_INFO,L"No PCI devices found in the system\n"); return EFI_SUCCESS; } @@ -106,9 +107,7 @@ palPcieGetBdf(UINT32 ClassCode, UINT32 StartBdf) Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), &PciHeader); if (!EFI_ERROR (Status)) { Hdr = &PciHeader.Bridge.Hdr; - - /*AsciiPrint ("\n%03d.%02d.%02d class_code = %d %d", Bus, Dev, Index, - Hdr->ClassCode[1], Hdr->ClassCode[2]);*/ + sbsa_print(AVS_PRINT_INFO,L"\n%03d.%02d.%02d class_code = %d %d", Bus, Dev, Index, Hdr->ClassCode[1], Hdr->ClassCode[2]); if (Hdr->ClassCode[2] == ((ClassCode >> 16) & 0xFF)) { if (Hdr->ClassCode[1] == ((ClassCode >> 8) & 0xFF)) { /* Found our device */ @@ -148,7 +147,7 @@ palPcieGetBase(UINT32 bdf, UINT32 bar_index) Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer); if (EFI_ERROR (Status)) { - AsciiPrint ("No PCI devices found in the system\n"); + sbsa_print(AVS_PRINT_INFO,L"No PCI devices found in the system\n"); return EFI_SUCCESS; } @@ -174,5 +173,5 @@ palPcieGetBase(UINT32 bdf, UINT32 bar_index) } return 0; -} +} diff --git a/platform/pal_uefi/src/pal_pe.c b/platform/pal_uefi/src/pal_pe.c index 8a43ac59..b8ab4e8e 100644 --- a/platform/pal_uefi/src/pal_pe.c +++ b/platform/pal_uefi/src/pal_pe.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ UINT8 *gSecondaryPeStack; UINT64 gMpidrMax; #define SIZE_STACK_SECONDARY_PE 0x100 //256 bytes per core +#define UPDATE_AFF_MAX(src,dest,mask) ((dest & mask) > (src & mask) ? (dest & mask) : (src & mask)) UINT64 pal_get_madt_ptr(); @@ -52,7 +53,7 @@ PalGetSecondaryStackBase() } /** - @brief Returns the Max MPIDR. + @brief Returns the Max of each 8-bit Affinity fields in MPIDR. @param None @return Max MPIDR **/ @@ -75,21 +76,21 @@ VOID PalAllocateSecondaryStack(UINT64 mpidr) { EFI_STATUS Status; - UINT32 MaxPe, Aff0, Aff1, Aff2, Aff3; + UINT32 NumPe, Aff0, Aff1, Aff2, Aff3; Aff0 = ((mpidr & 0x00000000ff) >> 0); Aff1 = ((mpidr & 0x000000ff00) >> 8); Aff2 = ((mpidr & 0x0000ff0000) >> 16); Aff3 = ((mpidr & 0xff00000000) >> 32); - MaxPe = ((Aff3+1) * (Aff2+1) * (Aff1+1) * (Aff0+1)); + NumPe = ((Aff3+1) * (Aff2+1) * (Aff1+1) * (Aff0+1)); if (gSecondaryPeStack == NULL) { Status = gBS->AllocatePool ( EfiBootServicesData, - (MaxPe * SIZE_STACK_SECONDARY_PE), + (NumPe * SIZE_STACK_SECONDARY_PE), (VOID **) &gSecondaryPeStack); if (EFI_ERROR(Status)) { - Print(L"\n FATAL - Allocation for Seconday stack failed %x \n", Status); + sbsa_print(AVS_PRINT_ERR, L"\n FATAL - Allocation for Seconday stack failed %x \n", Status); } pal_pe_data_cache_ops_by_va((UINT64)&gSecondaryPeStack, CLEAN_AND_INVALIDATE); } @@ -104,30 +105,36 @@ PalAllocateSecondaryStack(UINT64 mpidr) @return None **/ -void +VOID pal_pe_create_info_table(PE_INFO_TABLE *PeTable) { - EFI_ACPI_6_1_GIC_STRUCTURE *Entry; - PE_INFO_ENTRY *Ptr = PeTable->pe_info; + EFI_ACPI_6_1_GIC_STRUCTURE *Entry = NULL; + PE_INFO_ENTRY *Ptr = NULL; UINT32 TableLength = 0; UINT32 Length = 0; UINT64 MpidrAff0Max = 0, MpidrAff1Max = 0, MpidrAff2Max = 0, MpidrAff3Max = 0; - gMadtHdr = (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *) pal_get_madt_ptr(); + if (PeTable == NULL) { + sbsa_print(AVS_PRINT_ERR, L"Input PE Table Pointer is NULL. Cannot create PE INFO \n"); + return; + } - PeTable->header.num_of_pe = 0; + gMadtHdr = (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *) pal_get_madt_ptr(); - if (gMadtHdr != 0) { + if (gMadtHdr != NULL) { TableLength = gMadtHdr->Header.Length; - //Print(L" MADT is at %x and length is %x \n", gMadtHdr, TableLength); + sbsa_print(AVS_PRINT_INFO, L" MADT is at %x and length is %x \n", gMadtHdr, TableLength); } else { - Print(L"MADT not found \n"); + sbsa_print(AVS_PRINT_ERR, L"MADT not found \n"); return; } + PeTable->header.num_of_pe = 0; + Entry = (EFI_ACPI_6_1_GIC_STRUCTURE *) (gMadtHdr + 1); Length = sizeof (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER); + Ptr = PeTable->pe_info; do { @@ -136,15 +143,15 @@ pal_pe_create_info_table(PE_INFO_TABLE *PeTable) Ptr->mpidr = Entry->MPIDR; Ptr->pe_num = PeTable->header.num_of_pe; Ptr->pmu_gsiv = Entry->PerformanceInterruptGsiv; - //Print(L"FOUND an entry %x %x \n", Ptr->mpidr, Ptr->pe_num); + sbsa_print(AVS_PRINT_DEBUG, L"MPIDR %x PE num %x \n", Ptr->mpidr, Ptr->pe_num); pal_pe_data_cache_ops_by_va((UINT64)Ptr, CLEAN_AND_INVALIDATE); Ptr++; PeTable->header.num_of_pe++; - MpidrAff0Max = ((Entry->MPIDR & 0x000000ff) > (MpidrAff0Max & 0x000000ff))? (Entry->MPIDR & 0x000000ff) : (MpidrAff0Max & 0x000000ff); - MpidrAff1Max = ((Entry->MPIDR & 0x0000ff00) > (MpidrAff1Max & 0x0000ff00))? (Entry->MPIDR & 0x0000ff00) : (MpidrAff1Max & 0x0000ff00); - MpidrAff2Max = ((Entry->MPIDR & 0x00ff0000) > (MpidrAff2Max & 0x00ff0000))? (Entry->MPIDR & 0x00ff0000) : (MpidrAff2Max & 0x00ff0000); - MpidrAff3Max = ((Entry->MPIDR & 0xff00000000) > (MpidrAff3Max & 0xff00000000))? (Entry->MPIDR & 0xff00000000) : (MpidrAff3Max & 0xff00000000); + MpidrAff0Max = UPDATE_AFF_MAX(MpidrAff0Max, Entry->MPIDR, 0x000000ff); + MpidrAff1Max = UPDATE_AFF_MAX(MpidrAff1Max, Entry->MPIDR, 0x0000ff00); + MpidrAff2Max = UPDATE_AFF_MAX(MpidrAff2Max, Entry->MPIDR, 0x00ff0000); + MpidrAff3Max = UPDATE_AFF_MAX(MpidrAff3Max, Entry->MPIDR, 0xff00000000); } Length += Entry->Length; @@ -175,26 +182,19 @@ pal_pe_install_esr(UINT32 ExceptionType, VOID (*esr)(UINT64, VOID *)) EFI_STATUS Status; EFI_CPU_ARCH_PROTOCOL *Cpu; - - // // Get the CPU protocol that this driver requires. - // Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu); if (EFI_ERROR (Status)) { return Status; } - // // Unregister the default exception handler. - // Status = Cpu->RegisterInterruptHandler (Cpu, ExceptionType, NULL); if (EFI_ERROR (Status)) { return Status; } - // // Register to receive interrupts - // Status = Cpu->RegisterInterruptHandler (Cpu, ExceptionType, (EFI_CPU_INTERRUPT_HANDLER)esr); if (EFI_ERROR (Status)) { return Status; @@ -203,17 +203,11 @@ pal_pe_install_esr(UINT32 ExceptionType, VOID (*esr)(UINT64, VOID *)) return EFI_SUCCESS; } -/** - Trigger an SMC call - - SMC calls can take up to 7 arguments and return up to 4 return values. - Therefore, the 4 first fields in the ARM_SMC_ARGS structure are used - for both input and output values. - -**/ - /** @brief Make the SMC call using AARCH64 Assembly code + SMC calls can take up to 7 arguments and return up to 4 return values. + Therefore, the 4 first fields in the ARM_SMC_ARGS structure are used + for both input and output values. @param Argumets to pass to the EL3 firmware @@ -243,12 +237,46 @@ pal_pe_execute_payload(ARM_SMC_ARGS *ArmSmcArgs) pal_pe_call_smc(ArmSmcArgs); } +/** + @brief Update the ELR to return from exception handler to a desired address + + @param context - exception context structure + @param offset - address with which ELR should be updated + + @return None +**/ VOID pal_pe_update_elr(VOID *context, UINT64 offset) { ((EFI_SYSTEM_CONTEXT_AARCH64*)context)->ELR = offset; } +/** + @brief Get the Exception syndrome from UEFI exception handler + + @param context - exception context structure + + @return ESR +**/ +UINT64 +pal_pe_get_esr(VOID *context) +{ + return ((EFI_SYSTEM_CONTEXT_AARCH64*)context)->ESR; +} + +/** + @brief Get the FAR from UEFI exception handler + + @param context - exception context structure + + @return FAR +**/ +UINT64 +pal_pe_get_far(VOID *context) +{ + return ((EFI_SYSTEM_CONTEXT_AARCH64*)context)->FAR; +} + VOID DataCacheCleanInvalidateVA(UINT64 addr); @@ -258,6 +286,14 @@ DataCacheCleanVA(UINT64 addr); VOID DataCacheInvalidateVA(UINT64 addr); +/** + @brief Perform cache maintenance operation on an address + + @param addr - address on which cache ops to be performed + @param type - type of cache ops + + @return None +**/ VOID pal_pe_data_cache_ops_by_va(UINT64 addr, UINT32 type) { diff --git a/platform/pal_uefi/src/pal_peripherals.c b/platform/pal_uefi/src/pal_peripherals.c index 29512243..78445fe1 100644 --- a/platform/pal_uefi/src/pal_peripherals.c +++ b/platform/pal_uefi/src/pal_peripherals.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,14 +37,26 @@ UINT64 pal_get_spcr_ptr(); +/** + @brief This API fills in the PERIPHERAL_INFO_TABLE with information about peripherals + in the system. This is achieved by parsing the ACPI - SPCR table and PCIe config space. + + @param peripheralInfoTable - Address where the Peripheral information needs to be filled. + + @return None +**/ VOID pal_peripheral_create_info_table(PERIPHERAL_INFO_TABLE *peripheralInfoTable) { UINT32 DeviceBdf = 0; UINT32 StartBdf = 0; - PERIPHERAL_INFO_BLOCK *per_info; - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *spcr; + PERIPHERAL_INFO_BLOCK *per_info = NULL; + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *spcr = NULL; + if (peripheralInfoTable == NULL) { + sbsa_print(AVS_PRINT_ERR, L"Input Peripheral Table Pointer is NULL. Cannot create Peripheral INFO \n"); + return; + } per_info = peripheralInfoTable->info; @@ -60,7 +72,7 @@ pal_peripheral_create_info_table(PERIPHERAL_INFO_TABLE *peripheralInfoTable) per_info->type = PERIPHERAL_TYPE_USB; per_info->base0 = palPcieGetBase(DeviceBdf, BAR0); per_info->bdf = DeviceBdf; - //Print(L"Found a USB controller %4x \n", per_info->base0); + sbsa_print(AVS_PRINT_INFO, L"Found a USB controller %4x \n", per_info->base0); peripheralInfoTable->header.num_usb++; per_info++; } @@ -68,7 +80,6 @@ pal_peripheral_create_info_table(PERIPHERAL_INFO_TABLE *peripheralInfoTable) } while (DeviceBdf != 0); - StartBdf = 0; /* check for any SATA Controllers */ do { @@ -78,12 +89,12 @@ pal_peripheral_create_info_table(PERIPHERAL_INFO_TABLE *peripheralInfoTable) per_info->type = PERIPHERAL_TYPE_SATA; per_info->base0 = palPcieGetBase(DeviceBdf, BAR0); per_info->bdf = DeviceBdf; - Print(L"Found a SATA controller %4x \n", per_info->base0); + sbsa_print(AVS_PRINT_INFO, L"Found a SATA controller %4x \n", per_info->base0); peripheralInfoTable->header.num_sata++; per_info++; - //Increment and check if we have more controllers - StartBdf = incrementBusDev(DeviceBdf); } + //Increment and check if we have more controllers + StartBdf = incrementBusDev(DeviceBdf); } while (DeviceBdf != 0); @@ -111,6 +122,14 @@ pal_peripheral_create_info_table(PERIPHERAL_INFO_TABLE *peripheralInfoTable) } +/** + @brief Check if the memory type is reserved for UEFI + + @param EFI_MEMORY_TYPE - Type of UEFI memory. + + @return true if memory reserved for UEFI usage + false otherwise +**/ BOOLEAN IsUefiMemory(EFI_MEMORY_TYPE type) { @@ -132,6 +151,14 @@ IsUefiMemory(EFI_MEMORY_TYPE type) } +/** + @brief Check if the memory type is normal + + @param EFI_MEMORY_TYPE - Type of UEFI memory. + + @return true if memory is normal + false otherwise +**/ BOOLEAN IsNormalMemory(EFI_MEMORY_TYPE type) { @@ -145,6 +172,14 @@ IsNormalMemory(EFI_MEMORY_TYPE type) } +/** + @brief Check if the memory type is device + + @param EFI_MEMORY_TYPE - Type of UEFI memory. + + @return true if memory is device + false otherwise +**/ BOOLEAN IsDeviceMemory(EFI_MEMORY_TYPE type) { @@ -160,13 +195,21 @@ IsDeviceMemory(EFI_MEMORY_TYPE type) } +/** + @brief This API fills in the MEMORY_INFO_TABLE with information about memory in the + system. This is achieved by parsing the UEFI memory map. + + @param peripheralInfoTable - Address where the Peripheral information needs to be filled. + + @return None +**/ VOID pal_memory_create_info_table(MEMORY_INFO_TABLE *memoryInfoTable) { UINTN MemoryMapSize; - EFI_MEMORY_DESCRIPTOR *MemoryMap; - EFI_MEMORY_DESCRIPTOR *MemoryMapPtr; + EFI_MEMORY_DESCRIPTOR *MemoryMap = NULL; + EFI_MEMORY_DESCRIPTOR *MemoryMapPtr = NULL; EFI_PHYSICAL_ADDRESS Address; UINTN MapKey; UINTN DescriptorSize; @@ -175,6 +218,11 @@ pal_memory_create_info_table(MEMORY_INFO_TABLE *memoryInfoTable) EFI_STATUS Status; UINT32 Index, i = 0; + if (memoryInfoTable == NULL) { + sbsa_print(AVS_PRINT_ERR, L"Input Memory Table Pointer is NULL. Cannot create Memory INFO \n"); + return; + } + // Retrieve the UEFI Memory Map MemoryMap = NULL; @@ -197,10 +245,9 @@ pal_memory_create_info_table(MEMORY_INFO_TABLE *memoryInfoTable) if (!EFI_ERROR (Status)) { MemoryMapPtr = MemoryMap; for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) { - /* Print(L"Reserved region of type %d [0x%lX, 0x%lX]\n", - MemoryMapPtr->Type, - (UINTN)MemoryMapPtr->PhysicalStart, - (UINTN)(MemoryMapPtr->PhysicalStart + MemoryMapPtr->NumberOfPages * EFI_PAGE_SIZE));*/ + sbsa_print(AVS_PRINT_INFO, L"Reserved region of type %d [0x%lX, 0x%lX]\n", + MemoryMapPtr->Type, (UINTN)MemoryMapPtr->PhysicalStart, + (UINTN)(MemoryMapPtr->PhysicalStart + MemoryMapPtr->NumberOfPages * EFI_PAGE_SIZE)); if (IsUefiMemory ((EFI_MEMORY_TYPE)MemoryMapPtr->Type)) { memoryInfoTable->info[i].type = MEMORY_TYPE_RESERVED; } else { @@ -224,7 +271,6 @@ pal_memory_create_info_table(MEMORY_INFO_TABLE *memoryInfoTable) memoryInfoTable->info[i].type = MEMORY_TYPE_LAST_ENTRY; } - //pal_mem_free(&Address); } UINT64 diff --git a/platform/pal_uefi/src/pal_smmu.c b/platform/pal_uefi/src/pal_smmu.c deleted file mode 100644 index f36c7f60..00000000 --- a/platform/pal_uefi/src/pal_smmu.c +++ /dev/null @@ -1,45 +0,0 @@ -/** @file - * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. - - * 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 -#include -#include - -#include -#include - -#include "Include/IndustryStandard/Acpi61.h" - -#include "include/pal_uefi.h" -#include "include/platform_override.h" - - -/** - @brief Gather Information about SMMU subsystem -**/ -VOID -pal_smmu_create_info_table(SMMU_INFO_TABLE *SmmuTable) -{ - SmmuTable->smmu_num_ctrl = 0; - - if(PLATFORM_OVERRIDE_SMMU_BASE) { - SmmuTable->smmu_block[0].base = PLATFORM_OVERRIDE_SMMU_BASE; - SmmuTable->smmu_block[0].arch_major_rev = PLATFORM_OVERRIDE_SMMU_ARCH_MAJOR; - SmmuTable->smmu_num_ctrl = 1; - } - return; -} diff --git a/platform/pal_uefi/src/pal_timer_wd.c b/platform/pal_uefi/src/pal_timer_wd.c index a40617be..c6923dbe 100644 --- a/platform/pal_uefi/src/pal_timer_wd.c +++ b/platform/pal_uefi/src/pal_timer_wd.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016, ARM Limited or its affiliates. All rights reserved. + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ static EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE *gGtdtHdr; UINT64 pal_get_gtdt_ptr(); - /* Information about only one timer can be mentioned as an Override */ static VOID @@ -43,18 +42,14 @@ pal_timer_platform_override(TIMER_INFO_TABLE *TimerTable) TimerTable->gt_info[0].GtCntBase[0] = PLATFORM_OVERRIDE_CNTBASE_N; TimerTable->gt_info[0].gsiv[0] = PLATFORM_OVERRIDE_PLATFORM_TIMER_GSIV; } - - // //GTDT does not have this information yet. - // if (PLATFORM_OVERRIDE_EL2_VIR_TIMER_GSIV) { TimerTable->header.el2_virt_timer_gsiv = PLATFORM_OVERRIDE_EL2_VIR_TIMER_GSIV; } } - /** @brief This API fills in the TIMER_INFO_TABLE with information about local and system timers in the system. This is achieved by parsing the ACPI - GTDT table. @@ -66,30 +61,30 @@ pal_timer_platform_override(TIMER_INFO_TABLE *TimerTable) VOID pal_timer_create_info_table(TIMER_INFO_TABLE *TimerTable) { - EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *Entry; - EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE *GtBlockTimer; - TIMER_INFO_GTBLOCK *GtEntry; + EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *Entry = NULL; + EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE *GtBlockTimer = NULL; + TIMER_INFO_GTBLOCK *GtEntry = NULL; UINT32 Length= 0; UINT32 i; UINT32 num_of_entries; - if (TimerTable == NULL) + if (TimerTable == NULL) { + sbsa_print(AVS_PRINT_ERR, L"Input Timer Table Pointer is NULL. Cannot create Timer INFO \n"); return; + } GtEntry = TimerTable->gt_info; - TimerTable->header.CntControl_base = 0; TimerTable->header.num_platform_timer = 0; gGtdtHdr = (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE *) pal_get_gtdt_ptr(); if (gGtdtHdr == NULL) { - Print(L"GTDT not found \n"); + sbsa_print(AVS_PRINT_ERR, L"GTDT not found \n"); return; } - //Print(L" GTDT is at %x and length is %x \n", gGtdtHdr, gGtdtHdr->Header.Length); + sbsa_print(AVS_PRINT_INFO, L" GTDT is at %x and length is %x \n", gGtdtHdr, gGtdtHdr->Header.Length); //Fill in our internal table - TimerTable->header.s_el1_timer_flag = gGtdtHdr->SecurePL1TimerFlags; TimerTable->header.ns_el1_timer_flag = gGtdtHdr->NonSecurePL1TimerFlags; TimerTable->header.el2_timer_flag = gGtdtHdr->NonSecurePL2TimerFlags; @@ -98,32 +93,29 @@ pal_timer_create_info_table(TIMER_INFO_TABLE *TimerTable) TimerTable->header.el2_timer_gsiv = gGtdtHdr->NonSecurePL2TimerGSIV; TimerTable->header.virtual_timer_flag = gGtdtHdr->VirtualTimerFlags; TimerTable->header.virtual_timer_gsiv = gGtdtHdr->VirtualTimerGSIV; - - TimerTable->header.CntControl_base = gGtdtHdr->CntControlBasePhysicalAddress; - TimerTable->header.CntRead_base = gGtdtHdr->CntReadBasePhysicalAddress; - + Length = gGtdtHdr->PlatformTimerOffset; Entry = (EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE *) ((UINT8 *)gGtdtHdr + Length); Length = sizeof (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE); num_of_entries = gGtdtHdr->PlatformTimerCount; - //Print(L"CntCtrlBase = %x CntReadBase = %x num of sys timers= %x length= %x \n", TimerTable->header.CntCtrl_base, TimerTable->header.CntRead_base, TimerTable->header.num_platform_timer, Entry->Type); - while(num_of_entries) { if (Entry->Type == EFI_ACPI_6_1_GTDT_GT_BLOCK) { - //Print(L"Found block entry \n"); + sbsa_print(AVS_PRINT_INFO, L"Found block entry \n"); GtEntry->type = TIMER_TYPE_SYS_TIMER; GtEntry->block_cntl_base = Entry->CntCtlBase; GtEntry->timer_count = Entry->GTBlockTimerCount; - GtBlockTimer = (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE *)(((UINT8 *)Entry) + Entry->GTBlockTimerOffset); + sbsa_print(AVS_PRINT_DEBUG, L"CNTCTLBase = %x \n", GtEntry->block_cntl_base); + GtBlockTimer = (EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE *)(((UINT8 *)Entry) + Entry->GTBlockTimerOffset); for (i = 0; i < GtEntry->timer_count; i++) { - //Print(L"Found timer entry \n"); + sbsa_print(AVS_PRINT_INFO, L"Found timer entry \n"); GtEntry->GtCntBase[i] = GtBlockTimer->CntBaseX; GtEntry->GtCntEl0Base[i] = GtBlockTimer->CntEL0BaseX; GtEntry->gsiv[i] = GtBlockTimer->GTxPhysicalTimerGSIV; GtEntry->virt_gsiv[i] = GtBlockTimer->GTxVirtualTimerGSIV; GtEntry->flags[i] = GtBlockTimer->GTxPhysicalTimerFlags | (GtBlockTimer->GTxVirtualTimerFlags << 8) | (GtBlockTimer->GTxCommonFlags << 16); + sbsa_print(AVS_PRINT_DEBUG, L"CNTBaseN = %x for sys counter = %d\n", GtEntry->GtCntBase[i], i); GtBlockTimer++; TimerTable->header.num_platform_timer++; } @@ -141,10 +133,8 @@ pal_timer_create_info_table(TIMER_INFO_TABLE *TimerTable) pal_timer_platform_override(TimerTable); - } - /* Only one watchdog information can be assigned as an override */ VOID pal_wd_platform_override(WD_INFO_TABLE *WdTable) @@ -157,11 +147,10 @@ pal_wd_platform_override(WD_INFO_TABLE *WdTable) WdTable->wd_info[0].wd_gsiv = PLATFORM_OVERRIDE_WD_GSIV; WdTable->wd_info[0].wd_flags = 0; } - + return; } - /** @brief This API fills in the WD_INFO_TABLE with information about Watchdogs in the system. This is achieved by parsing the ACPI - GTDT table. @@ -175,16 +164,22 @@ VOID pal_wd_create_info_table(WD_INFO_TABLE *WdTable) { - EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *Entry; - WD_INFO_BLOCK *WdEntry = WdTable->wd_info; + EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *Entry = NULL; + WD_INFO_BLOCK *WdEntry = NULL; UINT32 Length= 0; UINT32 num_of_entries; + if (WdTable == NULL) { + sbsa_print(AVS_PRINT_ERR, L"Input Watchdog Table Pointer is NULL. Cannot create Watchdog INFO \n"); + return; + } + + WdEntry = WdTable->wd_info; WdTable->header.num_wd = 0; gGtdtHdr = (EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE *) pal_get_gtdt_ptr(); if (gGtdtHdr == NULL) { - Print(L"GTDT not found \n"); + sbsa_print(AVS_PRINT_ERR, L"GTDT not found \n"); return; } @@ -199,13 +194,14 @@ pal_wd_create_info_table(WD_INFO_TABLE *WdTable) if (Entry->Type == EFI_ACPI_6_1_GTDT_GT_BLOCK) { //Skip. this info is added in the timer info function } - + if (Entry->Type == EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG) { WdEntry->wd_refresh_base = Entry->RefreshFramePhysicalAddress; WdEntry->wd_ctrl_base = Entry->WatchdogControlFramePhysicalAddress; WdEntry->wd_gsiv = Entry->WatchdogTimerGSIV; WdEntry->wd_flags = Entry->WatchdogTimerFlags; WdTable->header.num_wd++; + sbsa_print(AVS_PRINT_DEBUG, L"Watchdog base = 0x%x INTID = 0x%x \n", WdEntry->wd_ctrl_base, WdEntry->wd_gsiv); WdEntry++; } Entry = (EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *) ((UINT8 *)Entry + (Entry->Length)); diff --git a/platform/secure_sw/arm-tf/sbsa_acs_platform.h b/platform/secure_sw/arm-tf/sbsa_acs_platform.h index 59449ff9..6316ac70 100644 --- a/platform/secure_sw/arm-tf/sbsa_acs_platform.h +++ b/platform/secure_sw/arm-tf/sbsa_acs_platform.h @@ -22,21 +22,25 @@ @brief SECURE DEVICE Definitions - Modify them to match the Target Platform **/ - #define SBSA_CNTControlBase ARM_SYS_CNTCTL_BASE - #define SBSA_CNTReadBase ARM_SYS_CNTREAD_BASE - #define SBSA_CNTCTLBase ARM_SYS_TIMCTL_BASE + #define SBSA_CNTControlBase ARM_SYS_CNTCTL_BASE + #define SBSA_CNTReadBase ARM_SYS_CNTREAD_BASE + #define SBSA_CNTCTLBase ARM_SYS_TIMCTL_BASE - #define SBSA_GENERIC_TWDOG_BASE 0 - #define SBSA_SP805_TWDOG_BASE ARM_SP805_TWDG_BASE - #define WDOG_UNLOCK_KEY 0x1ACCE551 + #define SBSA_SECURE_SYSTEM_TIMER 0 + #define SBSA_SECURE_CNTBaseN 0 + #define SBSA_SECURE_SYS_TIMER_INTID 0 - #define SBSA_SEC_UART_BASE PLAT_ARM_BL31_RUN_UART_BASE - #define SBSA_SEC_UART_GSIV 0 //148 + #define SBSA_GENERIC_TWDOG_BASE 0 + #define SBSA_SP805_TWDOG_BASE ARM_SP805_TWDG_BASE + #define WDOG_UNLOCK_KEY 0x1ACCE551 - #define SBSA_TRUSTED_SRAM_BASE1 ARM_TRUSTED_SRAM_BASE + 0x00 - #define SBSA_TRUSTED_SRAM_BASE2 ARM_TRUSTED_SRAM_BASE + 0x20 - #define SBSA_TRUSTED_SRAM_BASE3 ARM_TRUSTED_SRAM_BASE + 0x40 - #define SBSA_TRUSTED_SRAM_BASE4 ARM_TRUSTED_SRAM_BASE + 0x60 + #define SBSA_SEC_UART_BASE PLAT_ARM_BL31_RUN_UART_BASE + #define SBSA_SEC_UART_GSIV 0 //148 + + #define SBSA_TRUSTED_SRAM_BASE1 ARM_TRUSTED_SRAM_BASE + 0x00 + #define SBSA_TRUSTED_SRAM_BASE2 ARM_TRUSTED_SRAM_BASE + 0x20 + #define SBSA_TRUSTED_SRAM_BASE3 ARM_TRUSTED_SRAM_BASE + 0x40 + #define SBSA_TRUSTED_SRAM_BASE4 ARM_TRUSTED_SRAM_BASE + 0x60 /** @brief PLATFORM FUNCTIONS - Modify this based on the Target Platform diff --git a/platform/secure_sw/arm-tf/sbsa_avs.h b/platform/secure_sw/arm-tf/sbsa_avs.h index 19c5187b..0a383bef 100644 --- a/platform/secure_sw/arm-tf/sbsa_avs.h +++ b/platform/secure_sw/arm-tf/sbsa_avs.h @@ -52,6 +52,7 @@ void sbsa_acs_set_status(unsigned int status, unsigned int data); typedef enum { SBSA_SECURE_TEST_NSWD_WS1=0x1000, SBSA_SECURE_TEST_SYS_COUNTER, + SBSA_SECURE_TEST_SYS_TIMER_INT, SBSA_SECURE_TEST_WD_WS0, SBSA_SECURE_TEST_SEC_UART, SBSA_SECURE_TEST_CNTBASE, diff --git a/platform/secure_sw/arm-tf/sbsa_avs_main.c b/platform/secure_sw/arm-tf/sbsa_avs_main.c index 0d5366ae..36f9e746 100644 --- a/platform/secure_sw/arm-tf/sbsa_avs_main.c +++ b/platform/secure_sw/arm-tf/sbsa_avs_main.c @@ -51,7 +51,7 @@ sbsa_acs_default_handler(int test_index, int sbsa_acs_nswdg_intr(int int_id_expected) { - uint32_t timeout = 10000, int_id; + uint32_t timeout = 100000, int_id; while(--timeout){ int_id = sbsa_acs_get_pending_interrupt_id(); @@ -165,6 +165,55 @@ sbsa_acs_system_counter_entry() return 0; } +/** + @brief This API checks System Timer interrupt +**/ +int +sbsa_acs_system_timer_interrupt() +{ + uint32_t timeout = 100000; + uint32_t timer_expire_val = 100; + uint32_t int_id; + + if(SBSA_SECURE_SYSTEM_TIMER == 0){ + sbsa_acs_set_status(ACS_STATUS_FAIL, 0x1); + acs_printf("Secure Sytem timer is not implemented for SBSA L3-FW compliant platform\n"); + return 0; + } + if(SBSA_SECURE_CNTBaseN == 0){ + sbsa_acs_set_status(ACS_STATUS_FAIL, 0x2); + acs_printf("CNTBaseN can't be 0 for SBSA L3-FW compliant platform\n"); + return 0; + } + sbsa_acs_mmio_write(SBSA_SECURE_CNTBaseN + 0x28, timer_expire_val); + sbsa_acs_mmio_write(SBSA_SECURE_CNTBaseN + 0x2C, 1); + + while(--timeout) { + int_id = sbsa_acs_get_pending_interrupt_id(); + if (int_id != 0xFFFFFFFF) + break; + } + acs_printf("Stop the System Timer %x \n", timeout); + /* Stop the System Timer */ + sbsa_acs_mmio_write(SBSA_SECURE_CNTBaseN + 0x2C, 0); + + if (timeout) + { + sbsa_acs_acknowledge_interrupt(); + sbsa_acs_end_of_interrupt(int_id); + if(int_id != SBSA_SECURE_SYS_TIMER_INTID){ + sbsa_acs_set_status(ACS_STATUS_FAIL, 0x3); + acs_printf("Secure System Timer Interrupt-ID is incorrect, intID = 0x%x \n", int_id); + } else { + sbsa_acs_set_status(ACS_STATUS_PASS, 0x0); + } + + } else { + acs_printf("Secure System Timer did not generate an Interrupt \n"); + sbsa_acs_set_status(ACS_STATUS_FAIL, 0x4); + } + return 0; +} /** @brief This API checks if watchdog WS0 signal routed as interrupt to EL3 **/ @@ -172,7 +221,8 @@ int sbsa_acs_wd_ws0_test() { volatile uint32_t int_id; - uint32_t timeout = 0x500; + uint32_t timeout = 100000; + uint32_t timer_expire_val = 100; uint32_t wdog_type = (SBSA_GENERIC_TWDOG_BASE) ? SBSA_GENERIC : ((SBSA_SP805_TWDOG_BASE) ? SP805 : 0); if(wdog_type == 0){ @@ -183,7 +233,7 @@ sbsa_acs_wd_ws0_test() sbsa_acs_mmio_write(SBSA_GENERIC_TWDOG_BASE + 0x0, 0); acs_printf("Enabling watchdog \n"); - sbsa_acs_mmio_write(SBSA_GENERIC_TWDOG_BASE + 0x8, 0x50); + sbsa_acs_mmio_write(SBSA_GENERIC_TWDOG_BASE + 0x8, timer_expire_val); sbsa_acs_mmio_write(SBSA_GENERIC_TWDOG_BASE + 0x0, 0x1); while(--timeout) { @@ -407,6 +457,9 @@ uint64_t sbsa_smc_handler(uint32_t smc_fid, case SBSA_SECURE_TEST_SYS_COUNTER: SMC_RET1(handle, sbsa_acs_system_counter_entry()); + case SBSA_SECURE_TEST_SYS_TIMER_INT: + SMC_RET1(handle, sbsa_acs_system_timer_interrupt()); + case SBSA_SECURE_TEST_WD_WS0: SMC_RET1(handle, sbsa_acs_wd_ws0_test()); diff --git a/test_pool/gic/test_g003.c b/test_pool/gic/test_g003.c index 9fd11810..1c9852fd 100755 --- a/test_pool/gic/test_g003.c +++ b/test_pool/gic/test_g003.c @@ -34,7 +34,7 @@ payload() if (data != 0) val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); - + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); } diff --git a/test_pool/io_virt/test_i001.c b/test_pool/io_virt/test_i001.c index 56cdae13..fb9cda04 100755 --- a/test_pool/io_virt/test_i001.c +++ b/test_pool/io_virt/test_i001.c @@ -20,7 +20,7 @@ #include "val/include/sbsa_avs_smmu.h" #define TEST_NUM (AVS_SMMU_TEST_NUM_BASE + 1) -#define TEST_DESC "Check 64KB Granularity support " +#define TEST_DESC "Check 64KB Granularity support " static void diff --git a/test_pool/io_virt/test_i002.c b/test_pool/io_virt/test_i002.c index 43e2e721..20d585fc 100755 --- a/test_pool/io_virt/test_i002.c +++ b/test_pool/io_virt/test_i002.c @@ -20,7 +20,7 @@ #include "val/include/sbsa_avs_smmu.h" #define TEST_NUM (AVS_SMMU_TEST_NUM_BASE + 2) -#define TEST_DESC "All SMMUs have same Arch Revision " +#define TEST_DESC "All SMMUs have same Arch Revision " static void diff --git a/test_pool/io_virt/test_i003.c b/test_pool/io_virt/test_i003.c index 489e07ce..decbaabc 100755 --- a/test_pool/io_virt/test_i003.c +++ b/test_pool/io_virt/test_i003.c @@ -20,7 +20,7 @@ #include "val/include/sbsa_avs_smmu.h" #define TEST_NUM (AVS_SMMU_TEST_NUM_BASE + 3) -#define TEST_DESC "SMMU Compatibility Check " +#define TEST_DESC "SMMU Compatibility Check " static void @@ -74,7 +74,7 @@ payload() return; } } - + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); } diff --git a/test_pool/io_virt/test_i004.c b/test_pool/io_virt/test_i004.c index 8c810afe..3a2043b6 100755 --- a/test_pool/io_virt/test_i004.c +++ b/test_pool/io_virt/test_i004.c @@ -21,7 +21,7 @@ #include "val/include/sbsa_avs_pcie.h" #define TEST_NUM (AVS_SMMU_TEST_NUM_BASE + 4) -#define TEST_DESC "If PCIe, Check Stall model " +#define TEST_DESC "If PCIe, Check Stall model " static void diff --git a/test_pool/io_virt/test_i005.c b/test_pool/io_virt/test_i005.c new file mode 100644 index 00000000..9cd8c290 --- /dev/null +++ b/test_pool/io_virt/test_i005.c @@ -0,0 +1,73 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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_iovirt.h" + +#define TEST_NUM (AVS_SMMU_TEST_NUM_BASE + 5) +#define TEST_DESC "SMMUv2 unique intr per ctxt bank " + +static +void +payload() +{ + uint32_t num_smmu; + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + + num_smmu = val_smmu_get_info(SMMU_NUM_CTRL, 0); + + if (num_smmu == 0) { + val_print(AVS_PRINT_ERR, "\n No SMMU Controllers are discovered ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); + return; + } + + while (num_smmu--) { + if (val_smmu_get_info(SMMU_CTRL_ARCH_MAJOR_REV, num_smmu) == 3) { + val_print(AVS_PRINT_WARN, "\n Not Valid for SMMU v3 ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 2)); + return; + } + + if(!val_iovirt_check_unique_ctx_intid(num_smmu)) { + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 1)); + } else { + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 0)); + } + } +} + +uint32_t +i005_entry(uint32_t num_pe) +{ + + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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/io_virt/test_i006.c b/test_pool/io_virt/test_i006.c new file mode 100644 index 00000000..bb37a4d6 --- /dev/null +++ b/test_pool/io_virt/test_i006.c @@ -0,0 +1,67 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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_iovirt.h" + +#define TEST_NUM (AVS_SMMU_TEST_NUM_BASE + 6) +#define TEST_DESC "Unique stream id for each req id " + +static +void +payload() +{ + int num_rc; + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + + num_rc = val_iovirt_get_pcie_rc_info(NUM_PCIE_RC, 0); + if(!num_rc) { + val_print(AVS_PRINT_ERR, "\n No Root Complex discovered ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); + return; + } + while(num_rc--) { + if(!val_iovirt_unique_rid_strid_map(num_rc)) { + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 1)); + break; + } + } + if(num_rc < 0) + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 0)); +} + + +uint32_t +i006_entry(uint32_t num_pe) +{ + + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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_p002.c b/test_pool/pcie/test_p002.c index 13daf666..877bf899 100755 --- a/test_pool/pcie/test_p002.c +++ b/test_pool/pcie/test_p002.c @@ -33,7 +33,7 @@ payload(void) ecam_base = val_pcie_get_info(PCIE_INFO_MCFG_ECAM, 0); if (ecam_base == 0) { - val_print(AVS_PRINT_ERR, "\n ECAM base not in MCFG %4x ", ecam_base); + val_print(AVS_PRINT_ERR, "\n ECAM base not in MCFG %4x ", ecam_base); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); return; } diff --git a/test_pool/pcie/test_p003.c b/test_pool/pcie/test_p003.c index 74c057a2..cb6f9397 100755 --- a/test_pool/pcie/test_p003.c +++ b/test_pool/pcie/test_p003.c @@ -29,12 +29,27 @@ payload(void) uint64_t data; uint32_t num_ecam; + uint64_t ecam_base; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); uint32_t bdf = 0; uint32_t bus, segment; num_ecam = val_pcie_get_info(PCIE_INFO_NUM_ECAM, 0); + if (num_ecam == 0) { + val_print(AVS_PRINT_ERR, "\n No ECAM in MCFG ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); + return; + } + + ecam_base = val_pcie_get_info(PCIE_INFO_MCFG_ECAM, 0); + + if (ecam_base == 0) { + val_print(AVS_PRINT_ERR, "\n ECAM Base in MCFG is 0 ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); + return; + } + while (num_ecam) { num_ecam--; segment = val_pcie_get_info(PCIE_INFO_SEGMENT, num_ecam); @@ -52,8 +67,8 @@ payload(void) data = val_pcie_read_cfg(bdf, 0xC); - //If this really is PCIe CFG, Header type must be 01 or 00 - if (((data >> 16) & 0xFF) > 01) { + //If this really is PCIe CFG, Header type[6:0] must be 01 or 00 + if (((data >> 16) & 0x7F) > 01) { val_print(AVS_PRINT_ERR, "\n Incorrect PCIe CFG Hdr type %4x ", data); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); return; diff --git a/test_pool/pcie/test_p004.c b/test_pool/pcie/test_p004.c index cb546ef7..2cdf0996 100755 --- a/test_pool/pcie/test_p004.c +++ b/test_pool/pcie/test_p004.c @@ -21,7 +21,7 @@ /* SBSA-checklist 63 & 64 */ #define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 4) -#define TEST_DESC "Check PCIe Unaligned access, Norm mem" +#define TEST_DESC "PCIe Unaligned access, Norm mem " static void diff --git a/test_pool/pcie/test_p005.c b/test_pool/pcie/test_p005.c index 7e7ead1d..16eb726e 100644 --- a/test_pool/pcie/test_p005.c +++ b/test_pool/pcie/test_p005.c @@ -41,7 +41,7 @@ payload(void) target_dev_index = val_dma_get_info(DMA_NUM_CTRL, 0); if (!target_dev_index) { - val_print(AVS_PRINT_WARN, "\n No DMA controllers detected... ", 0); + val_print(AVS_PRINT_WARN, "\n No DMA controllers detected... ", 0); val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); return; } diff --git a/test_pool/pcie/test_p006.c b/test_pool/pcie/test_p006.c index 8eb7a17a..8a01d7b4 100644 --- a/test_pool/pcie/test_p006.c +++ b/test_pool/pcie/test_p006.c @@ -20,7 +20,7 @@ #include "val/include/sbsa_avs_smmu.h" #define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 6) -#define TEST_DESC "No extra addr translation - SMMU" +#define TEST_DESC "No extra addr translation - SMMU " /* For all DMA masters populated in the Info table, which are behind an SMMU, @@ -41,7 +41,7 @@ payload(void) target_dev_index = val_dma_get_info(DMA_NUM_CTRL, 0); if (!target_dev_index) { - val_print(AVS_PRINT_TEST, "\n No DMA controllers detected... ", 0); + val_print(AVS_PRINT_TEST, "\n No DMA controllers detected... ", 0); val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 02)); return; } diff --git a/test_pool/pcie/test_p007.c b/test_pool/pcie/test_p007.c index 31a7f3e7..8d4e8b00 100644 --- a/test_pool/pcie/test_p007.c +++ b/test_pool/pcie/test_p007.c @@ -30,18 +30,24 @@ payload(void) uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); uint32_t data; + if (!count){ + val_print(AVS_PRINT_WARN, "\n Skipping because no SATA controller present ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); + return; + } + while (count != 0) { data = val_peripheral_get_info(SATA_FLAGS, count - 1); if ((data & PER_FLAG_MSI_ENABLED) == 0) { - val_print(AVS_STATUS_ERR, " MSI should be enabled for a PCIe device ", 0); + val_print(AVS_STATUS_ERR, "\n MSI should be enabled for a PCIe device ", 0); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); break; } else { if (val_peripheral_get_info(SATA_GSIV, count - 1)) val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); else { - val_print(AVS_STATUS_ERR, " IRQ not assigned to the Device ", 0); + val_print(AVS_STATUS_ERR, "\n IRQ not assigned to the Device ", 0); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); break; } @@ -53,7 +59,7 @@ payload(void) uint32_t p007_entry(uint32_t num_pe) -{ +{ uint32_t status = AVS_STATUS_FAIL; num_pe = 1; //This test is run on single processor diff --git a/test_pool/pcie/test_p008.c b/test_pool/pcie/test_p008.c new file mode 100644 index 00000000..559795ff --- /dev/null +++ b/test_pool/pcie/test_p008.c @@ -0,0 +1,199 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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 + 8) +#define TEST_DESC "Check MSI(X) vectors uniqueness " + +/** + @brief Returns MSI(X) status of the device + + @param dev_index index of PCI device + + @return 0 device does not support MSI(X) + @return 1 device supports MSI(X) +**/ +static +uint32_t +check_msi_status (uint32_t dev_index) { + uint32_t data; + + data = val_peripheral_get_info (ANY_FLAGS, dev_index); + + if ((data & PER_FLAG_MSI_ENABLED) && + val_peripheral_get_info (ANY_GSIV, dev_index)) { + return 1; + } + + return 0; +} + +/** + @brief Compare two lists of MSI(X) vectors + + @param list_one pointer to a first list of MSI(X) vectors + @param list_two pointer to a second list of MSI(X) vectors + + @return 0 no vectors duplicates are found + @return 1 lists contain at leas one common MSI(X) vector +**/ +static +uint32_t +check_list_duplicates (PERIPHERAL_VECTOR_LIST *list_one, PERIPHERAL_VECTOR_LIST *list_two) +{ + PERIPHERAL_VECTOR_LIST *flist_node; + PERIPHERAL_VECTOR_LIST *slist_node; + + uint32_t fcount = 0; + uint32_t scount = 0; + + flist_node = list_one; + slist_node = list_two; + + while (flist_node != NULL) { + while (slist_node != NULL) { + if ((flist_node->vector.vector_lower_addr == slist_node->vector.vector_lower_addr) && + (flist_node->vector.vector_upper_addr == slist_node->vector.vector_upper_addr) && + (flist_node->vector.vector_data == slist_node->vector.vector_data)) { + return 1; + } + slist_node = slist_node->next; + scount++; + } + slist_node = list_two; + flist_node = flist_node->next; + fcount++; + scount = 0; + } + + 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 +clean_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; + uint64_t current_dev_bdf; + uint64_t next_dev_bdf; + uint32_t count_next; + + 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; + + /* + Pull each discovered PCI device and its list of MSI(X) vectors. + Compare this list with MSI(X) vector lists of other discovered + PCI devices and find duplicates exist. + */ + while (count > 0 && !status) { + count_next = count - 1; + if (check_msi_status (count - 1)) { + /* Get BDF of a device */ + current_dev_bdf = val_peripheral_get_info (ANY_BDF, count - 1); + if (current_dev_bdf) { + val_print (AVS_PRINT_INFO, " Checking PCI device with BDF %4X\n", current_dev_bdf); + /* Read MSI(X) vectors */ + if (val_get_msi_vectors (current_dev_bdf, ¤t_dev_mvec)) { + + /* Pull other PCI devices left in the devices list */ + while (count_next > 0 && !status) { + if (check_msi_status (count_next - 1)) { + /* Get BDF of a device */ + next_dev_bdf = val_peripheral_get_info (ANY_BDF, count_next - 1); + /* Read MSI(X) vectors */ + if (val_get_msi_vectors (next_dev_bdf, &next_dev_mvec)) { + /* Compare two lists of MSI(X) vectors */ + if(check_list_duplicates (current_dev_mvec, next_dev_mvec)) { + val_print (AVS_STATUS_ERR, "\n Allocated MSIs are not unique", 0); + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + status = 1; + } + clean_msi_list (next_dev_mvec); + } + } + count_next--; + } + + clean_msi_list (current_dev_mvec); + } + } else { + val_print (AVS_STATUS_ERR, "\n Failed to get address of PCI device", 0); + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 01)); + status = 1; + } + } + count--; + } + + if (!status) { + val_set_status (index, RESULT_PASS (g_sbsa_level, TEST_NUM, 01)); + } +} + +uint32_t +p008_entry (uint32_t num_pe) +{ + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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_p009.c b/test_pool/pcie/test_p009.c new file mode 100644 index 00000000..cfde0e1a --- /dev/null +++ b/test_pool/pcie/test_p009.c @@ -0,0 +1,144 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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 + 9) +#define TEST_DESC "Check all MSI(X) vectors are LPIs " + +#define LPI_BASE 8192 + +/** + @brief Returns MSI(X) status of the device + + @param dev_index index of PCI device + + @return 0 device does not support MSI(X) + @return 1 device supports MSI(X) +**/ +static +uint32_t +check_msi_status (uint32_t dev_index) { + uint32_t data; + + data = val_peripheral_get_info (ANY_FLAGS, dev_index); + + if ((data & PER_FLAG_MSI_ENABLED) && + val_peripheral_get_info (ANY_GSIV, dev_index)) { + return 1; + } + + 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 +clean_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 *dev_mvec, *mvec; + uint64_t dev_bdf; + + if(!count) { + val_set_status (index, RESULT_SKIP (g_sbsa_level, TEST_NUM, 2)); + return; + } + + status = 0; + dev_mvec = NULL; + + /* + Pull each discovered PCI device and its list of MSI(X) vectors. + Check whether every vector IRQ number is an LPI or not. + */ + while (count > 0 && !status) { + if (check_msi_status (count - 1)) { + /* Get BDF of a device */ + dev_bdf = val_peripheral_get_info (ANY_BDF, count - 1); + if (dev_bdf) { + val_print (AVS_PRINT_INFO, " Checking PCI device with BDF %4X\n", dev_bdf); + /* Read MSI(X) vectors */ + if (val_get_msi_vectors (dev_bdf, &dev_mvec)) { + mvec = dev_mvec; + while(mvec) { + if(mvec->vector.vector_irq_base < LPI_BASE) { + val_print(AVS_PRINT_INFO, " MSI vector irq %d is not an LPI\n", mvec->vector.vector_irq_base); + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, mvec->vector.vector_irq_base)); + status = 1; + } + mvec = mvec->next; + } + clean_msi_list (dev_mvec); + } + } else { + val_print (AVS_STATUS_ERR, "\n Failed to get address of PCI device", 0); + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 1)); + status = 1; + } + } + count--; + } + + if (!status) { + val_set_status (index, RESULT_PASS (g_sbsa_level, TEST_NUM, 0)); + } +} + +uint32_t +p009_entry (uint32_t num_pe) +{ + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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_p010.c b/test_pool/pcie/test_p010.c new file mode 100644 index 00000000..f7309145 --- /dev/null +++ b/test_pool/pcie/test_p010.c @@ -0,0 +1,96 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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" + +#define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 10) +#define TEST_DESC "PASID support atleast 16 bits " + +#define MIN_PASID_SUPPORT (1 << 16) + +static void +payload(void) +{ + int num_per = 0, num_smmu = 0, skip = 1; + uint32_t max_pasids = 0; + uint32_t index = val_pe_get_index_mpid (val_pe_get_mpid()); + + num_per = val_peripheral_get_info(NUM_ALL, 0); + /* For each peripheral check for PASID support */ + /* If PASID is supported, test the max number of PASIDs supported */ + for(num_per--; num_per >= 0; num_per--) + { + if((max_pasids = val_peripheral_get_info(MAX_PASIDS, num_per)) > 0) + { + skip = 0; + if(max_pasids < MIN_PASID_SUPPORT) + { + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 1)); + break; + } + } + } + if(num_per < 0) + { + /* For each SMMUv3 check for PASID support */ + /* If PASID is supported, test the max number of PASIDs supported */ + num_smmu = val_smmu_get_info(SMMU_NUM_CTRL, 0); + for(num_smmu--; num_smmu >= 0; num_smmu--) + { + if(val_smmu_get_info(SMMU_CTRL_ARCH_MAJOR_REV, num_smmu) == 3) + { + if((max_pasids = val_smmu_max_pasids(val_smmu_get_info(SMMU_CTRL_BASE, num_smmu))) > 0) + { + skip = 0; + if(max_pasids < MIN_PASID_SUPPORT) + { + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 2)); + break; + } + } + } + } + } + if(num_smmu < 0) { + if(skip) + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 3)); + else + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 0)); + } +} + +uint32_t +p010_entry(uint32_t num_pe) +{ + + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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_p011.c b/test_pool/pcie/test_p011.c new file mode 100644 index 00000000..e1730569 --- /dev/null +++ b/test_pool/pcie/test_p011.c @@ -0,0 +1,75 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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_iovirt.h" + +#define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 11) +#define TEST_DESC "PCIe RC & PE, Same Inner SH Domain" + +#define SHAREABILITY_BIT (1UL << 57) + +static void +payload(void) +{ + uint32_t num_pcie_rc; + uint64_t mem_attr; + uint32_t index = val_pe_get_index_mpid (val_pe_get_mpid()); + + num_pcie_rc = val_iovirt_get_pcie_rc_info(NUM_PCIE_RC,0); + + if(!num_pcie_rc){ + val_print(AVS_PRINT_WARN, "\n Skip because no PCIe RC detected ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); + return; + } + + while(num_pcie_rc){ + num_pcie_rc--; // Index is one lesser than the component number being accessed + mem_attr = val_iovirt_get_pcie_rc_info(RC_MEM_ATTRIBUTE, num_pcie_rc); + + if(mem_attr & SHAREABILITY_BIT) + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); + else { + val_print(AVS_PRINT_ERR, "\n Failed mem attribute check for PCIe RC %d", num_pcie_rc); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); + return; + } + } + +} + +uint32_t +p011_entry(uint32_t num_pe) +{ + + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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_p012.c b/test_pool/pcie/test_p012.c new file mode 100644 index 00000000..eb4d6084 --- /dev/null +++ b/test_pool/pcie/test_p012.c @@ -0,0 +1,147 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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 + 12) +#define TEST_DESC "PCI legacy interrupt SPI ID unique" + +static inline char pin_name(int pin) +{ + return 'A' + pin; +} + +static +void +payload (void) +{ + + uint32_t index; + uint32_t count; + PERIPHERAL_IRQ_MAP *irq_map; + uint8_t status; + uint32_t current_irq_pin; + uint32_t next_irq_pin; + uint64_t dev_bdf; + uint32_t ccnt; + uint32_t ncnt; + + current_irq_pin = 0; + status = 0; + next_irq_pin = current_irq_pin + 1; + index = val_pe_get_index_mpid (val_pe_get_mpid()); + count = val_peripheral_get_info (NUM_ALL, 0); + + if(!count) { + val_set_status (index, RESULT_SKIP (g_sbsa_level, TEST_NUM, 3)); + return; + } + + irq_map = kzalloc(sizeof(PERIPHERAL_IRQ_MAP), GFP_KERNEL); + if (!irq_map) { + val_print (AVS_STATUS_ERR, "\n Memory allocation error", 0); + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 01)); + return; + } + + /* get legacy IRQ info from PCI devices */ + while (count > 0 && status == 0) { + if (val_peripheral_get_info (ANY_GSIV, count-1)) { + dev_bdf = val_peripheral_get_info (ANY_BDF, count-1); + status = val_pci_get_legacy_irq_map (dev_bdf, irq_map); + + switch (status) { + case 0: + break; + case 1: + val_print (AVS_STATUS_ERR, "\n Unable to access PCI bridge device", 0); + break; + case 2: + val_print (AVS_STATUS_ERR, "\n Unable to fetch _PRT ACPI handle", 0); + break; + case 3: + val_print (AVS_STATUS_ERR, "\n Unable to access _PRT ACPI object", 0); + break; + case 4: + val_print (AVS_STATUS_ERR, "\n Interrupt hard-wire error", 0); + break; + case 5: + val_print (AVS_STATUS_ERR, "\n Legacy interrupt out of range", 0); + break; + case 6: + val_print (AVS_STATUS_ERR, "\n Maximum number of interrupts has been reached", 0); + break; + default: + val_print (AVS_STATUS_ERR, "\n Unknown error", 0); + break; + } + } + count--; + } + + /* Compare IRQ routings */ + if (!status) { + while (current_irq_pin < LEGACY_PCI_IRQ_CNT && status == 0) { + while (next_irq_pin < LEGACY_PCI_IRQ_CNT && status == 0) { + + for (ccnt = 0; (ccnt < irq_map->legacy_irq_map[current_irq_pin].irq_count) && (status == 0); ccnt++) { + for (ncnt = 0; (ncnt < irq_map->legacy_irq_map[next_irq_pin].irq_count) && (status == 0); ncnt++) { + 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)); + } + } + } + + next_irq_pin++; + } + current_irq_pin++; + next_irq_pin = current_irq_pin + 1; + } + } + + kfree (irq_map); + + if (!status) { + val_set_status (index, RESULT_PASS (g_sbsa_level, TEST_NUM, 01)); + } else { + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, status)); + } +} + +uint32_t +p012_entry (uint32_t num_pe) +{ + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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_p013.c b/test_pool/pcie/test_p013.c new file mode 100644 index 00000000..70be797d --- /dev/null +++ b/test_pool/pcie/test_p013.c @@ -0,0 +1,138 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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 + 13) +#define TEST_DESC "Addressability of Non-Sec masters " + +#define BAR_64BIT_SUPPORT 0x2 +#define ADDR_TYPE_MASK 0x6 +#define BAR0_OFFSET 0x10 +#define BAR2_OFFSET 0x18 + +static +void +payload (void) +{ + + uint32_t index; + uint32_t count; + uint32_t data; + uint32_t dev_type; + uint32_t smmu_checked = 0; + uint32_t dev_bdf; + + index = val_pe_get_index_mpid (val_pe_get_mpid()); + count = val_peripheral_get_info (NUM_ALL, 0); + val_print (AVS_PRINT_WARN, "\n Num of devices %d", count); + + if(!count) { + val_print (AVS_PRINT_WARN, "\n Skip as No peripherals detected ", 0); + val_set_status (index, RESULT_SKIP (g_sbsa_level, TEST_NUM, 1)); + return; + } + + while (count) { + count--; + dev_bdf = (uint32_t)val_peripheral_get_info (ANY_BDF, count); + dev_type = val_pcie_get_device_type(dev_bdf); // 1: Normal PCIe device, 2: PCIe Host bridge, 3: PCIe bridge device, else: INVALID + smmu_checked = 0; + + if(!dev_type) { + val_print (AVS_PRINT_WARN, "\n NULL pointer returned, while finding pdev", 0); + val_print (AVS_PRINT_WARN, "\n Skipping this device (bdf = 0x%x) and continuing with other devices", dev_bdf); + continue; + } + + data = val_pcie_read_cfg(dev_bdf, BAR0_OFFSET); + if(BAR_64BIT_SUPPORT != ((data & ADDR_TYPE_MASK) >> 1)) { + if(!val_pcie_is_device_behind_smmu(dev_bdf)) { + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 1)); + val_print (AVS_STATUS_ERR, "\n The device with bdf=0x%x doesn't support 64 bit addressing", dev_bdf); + val_print (AVS_STATUS_ERR, "\n for BAR0, and is not behind SMMU", 0); + val_print (AVS_STATUS_ERR, "\n The device is of type = %d", dev_type); + return; + } + smmu_checked++; + } + + if(dev_type == 1){ + if(!smmu_checked){ + data = val_pcie_read_cfg(dev_bdf, BAR2_OFFSET); + if(BAR_64BIT_SUPPORT != ((data & ADDR_TYPE_MASK) >> 1)) { + if(!val_pcie_is_device_behind_smmu(dev_bdf)) { + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 1)); + val_print (AVS_STATUS_ERR, "\n The device with bdf=0x%x doesn't support 64 bit addressing", dev_bdf); + val_print (AVS_STATUS_ERR, "\n for BAR2, and is not behind SMMU", 0); + return; + } + smmu_checked++; + } + } + } + + if((dev_type == 1) || (dev_type == 3)){ + if(!smmu_checked){ + data = val_pcie_get_root_port_bdf(&dev_bdf); + if(data) { + if(data == 1){ + val_print (AVS_PRINT_WARN, "\n NULL pointer returned, while finding root port (pdev->bus->self)", 0); + val_print (AVS_PRINT_WARN, "\n Skipping this device (bdf = 0x%x) and continuing with other devices", dev_bdf); + continue; + } else if(data == 2) { + val_print (AVS_PRINT_WARN, "\n NULL pointer returned from the root port function", 0); + val_print (AVS_PRINT_WARN, "\n Skipping this device (bdf = 0x%x) and continuing with other devices", dev_bdf); + continue; + } + } + data = val_pcie_read_cfg(dev_bdf, BAR0_OFFSET); + if(BAR_64BIT_SUPPORT != ((data & ADDR_TYPE_MASK) >> 1)) { + if(!val_pcie_is_device_behind_smmu(dev_bdf)) { + val_print (AVS_STATUS_ERR, "\n The device root bridge doesn't support 64 bit addressing", 0); + val_print (AVS_STATUS_ERR, "\n , and is not behind SMMU", 0); + val_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 1)); + return; + } + } + } + } + } + + val_set_status (index, RESULT_PASS (g_sbsa_level, TEST_NUM, 01)); +} + +uint32_t +p013_entry (uint32_t num_pe) +{ + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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_p014.c b/test_pool/pcie/test_p014.c new file mode 100644 index 00000000..3901b3e0 --- /dev/null +++ b/test_pool/pcie/test_p014.c @@ -0,0 +1,114 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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" + +#define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 14) +#define TEST_DESC "Memory attributes of DMA traffic " + + +/* For all DMA masters populated in the Info table, which are behind an SMMU, + verify there are no additional translations before address is given to SMMU */ +static +void +payload(void) +{ + + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t target_dev_index; + uint32_t status = 0; + addr_t dma_addr = 0; + void *buffer; + uint32_t attr, sh; + int ret; + + target_dev_index = val_dma_get_info(DMA_NUM_CTRL, 0); + + if (!target_dev_index) + { + val_print(AVS_PRINT_TEST, "\n No DMA controllers detected... ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 03)); + return; + } + + while (target_dev_index) + { + target_dev_index--; //index is zero based + if(val_dma_get_info(DMA_HOST_COHERENT, target_dev_index)) + { + dma_addr = val_dma_mem_alloc(&buffer, 512, target_dev_index, DMA_COHERENT); + ret = val_dma_mem_get_attrs(buffer, &attr, &sh); + if(ret) + { + val_print(AVS_PRINT_ERR, "\n DMA controler %d: Failed to get memory attributes\n", target_dev_index); + status = 1; + continue; + } + if(!(MEM_NORMAL_WB_IN_OUT(attr) && MEM_SH_INNER(sh))) + { + val_print(AVS_PRINT_INFO, "\n DMA controler %d: IO Coherent DMA memory should be inner/outer writeback, inner shareable\n", target_dev_index); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); + status = 1; + } + } + else { + dma_addr = val_dma_mem_alloc(&buffer, 512, target_dev_index, DMA_NOT_COHERENT); + ret = val_dma_mem_get_attrs(buffer, &attr, &sh); + if(ret) + { + val_print(AVS_PRINT_ERR, "\n DMA controler %d: Failed to get memory attributes\n", target_dev_index); + status = 1; + continue; + } + if(!((MEM_NORMAL_WB_IN_OUT(attr) && MEM_SH_INNER(sh)) || + MEM_NORMAL_NC_IN_OUT(attr) || + MEM_DEVICE(attr))) + { + val_print(AVS_PRINT_INFO, + "\n DMA controler %d: DMA memory should be inner/outer writeback inner shareable, inner/outer non-cacheable, or device type\n", + target_dev_index); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + status = 1; + } + } + } + if(!status) + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 0)); +} + + +uint32_t +p014_entry(uint32_t num_pe) +{ + + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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_p015.c b/test_pool/pcie/test_p015.c new file mode 100644 index 00000000..8b63b599 --- /dev/null +++ b/test_pool/pcie/test_p015.c @@ -0,0 +1,91 @@ +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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 + 15) +#define TEST_DESC "PCIe No Snoop transaction attr " + +static +void +payload (void) +{ + + uint32_t index; + uint32_t count; + uint32_t no_snoop_set; + uint32_t status; + uint64_t dev_bdf; + + status = 0; + no_snoop_set = 0; + index = val_pe_get_index_mpid (val_pe_get_mpid()); + count = val_peripheral_get_info (NUM_ALL, 0); + + if(!count) { + val_set_status (index, RESULT_SKIP (g_sbsa_level, TEST_NUM, 3)); + return; + } + + /* Read No Snoop bit from the device control register */ + while (count > 0) { + count--; + dev_bdf = val_peripheral_get_info (ANY_BDF, count); + if (val_pcie_get_dma_support (dev_bdf) == 1) { + val_print (AVS_PRINT_INFO, " have DMA support on %X", dev_bdf); + if (val_pcie_get_dma_coherent(dev_bdf) == 1) { + val_print (AVS_PRINT_INFO, " DMA is coherent on %X", dev_bdf); + status = val_pcie_get_snoop_bit (dev_bdf); + if (status != 2) { + no_snoop_set |= status; + val_print (AVS_PRINT_INFO, " no snoop bit is %d", status); + } + } else { + val_print (AVS_PRINT_INFO, " DMA is not coherent on %X", dev_bdf); + } + } + } + + 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_set_status (index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 1)); + } else { + val_set_status (index, RESULT_PASS (g_sbsa_level, TEST_NUM, status)); + } + +} + +uint32_t +p015_entry (uint32_t num_pe) +{ + uint32_t status = AVS_STATUS_FAIL; + + num_pe = 1; //This test is run on single processor + + 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/pe/test_c001.c b/test_pool/pe/test_c001.c index 52890ab8..0d9037f0 100755 --- a/test_pool/pe/test_c001.c +++ b/test_pool/pe/test_c001.c @@ -73,4 +73,4 @@ c001_entry() val_report_status(0, SBSA_AVS_END(g_sbsa_level, TEST_NUM)); return status; -} +} \ No newline at end of file diff --git a/test_pool/pe/test_c013.c b/test_pool/pe/test_c013.c index 572a11ba..78912eef 100755 --- a/test_pool/pe/test_c013.c +++ b/test_pool/pe/test_c013.c @@ -29,7 +29,7 @@ payload() data = val_pe_reg_read(ID_AA64DFR0_EL1); - if (((data >> 20) & 0xF) > 2) //bits 23:20 for Number of watchpoints - 1 + if (((data >> 20) & 0xF) > 2) //bits 23:20 for Number of watchpoints - 1 val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); else val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); diff --git a/test_pool/pe/test_c014.c b/test_pool/pe/test_c014.c index a0702961..dae9f05e 100755 --- a/test_pool/pe/test_c014.c +++ b/test_pool/pe/test_c014.c @@ -28,17 +28,17 @@ void payload() data = val_pe_reg_read(ID_AA64DFR0_EL1); - if ((g_sbsa_level == 0) && ((data >> 12) & 0xF) < 3) { //bits 15:12 for Number of breakpoints - 1 + if ((g_sbsa_level == 0) && ((data >> 12) & 0xF) < 3) { //bits 15:12 for Number of breakpoints - 1 val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); return; } - if ((g_sbsa_level > 0) && ((data >> 12) & 0xF) < 5) { //bits 15:12 for Number of breakpoints - 1 + if ((g_sbsa_level > 0) && ((data >> 12) & 0xF) < 5) { //bits 15:12 for Number of breakpoints - 1 val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); return; } - if (((data >> 28) > 0)) //bits 31:28 for Number of context aware breakpoints - 1 + if (((data >> 28) > 0)) //bits 31:28 for Number of context aware breakpoints - 1 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)); diff --git a/test_pool/pe/test_c015.c b/test_pool/pe/test_c015.c index 3fff3c24..bb88ec5d 100755 --- a/test_pool/pe/test_c015.c +++ b/test_pool/pe/test_c015.c @@ -20,7 +20,7 @@ #define TEST_NUM (AVS_PE_TEST_NUM_BASE + 15) #define TEST_DESC "Check Arch symmetry across PE " -#define NUM_OF_REGISTERS 34 +#define NUM_OF_REGISTERS 32 #define RAS 1 #define SPE 2 @@ -29,9 +29,7 @@ #define MASK_AA64MMFR0 0xF #define MASK_MIDR 0x00F0FFFF -#define MASK_VPIDR 0x00F0FFFF #define MASK_MPIDR 0xFF3FFFFFFF -#define MASK_VMPIDR 0xFF3FFFFFFF #define MASK_CTR 0xC000 #define MASK_CCSIDR 0xFFFFFF0 #define MASK_PMCR 0xFFFF @@ -57,9 +55,7 @@ reg_details reg_list[] = { {ID_AA64ISAR0_EL1, 0x0, "ID_AA64ISAR0_EL1", 0x0 }, {ID_AA64ISAR1_EL1, 0x0, "ID_AA64ISAR1_EL1", 0x0 }, {MPIDR_EL1, MASK_MPIDR, "MPIDR_EL1" , 0x0 }, - {VMPIDR_EL2, MASK_VMPIDR, "VMPIDR_EL2" , 0x0 }, {MIDR_EL1, MASK_MIDR, "MIDR_EL1" , 0x0 }, - {VPIDR_EL2, MASK_VPIDR, "VPIDR_EL2" , 0x0 }, {CCSIDR_EL1, MASK_CCSIDR, "CCSIDR_EL1" , 0x0 }, {ID_DFR0_EL1, 0x0, "ID_DFR0_EL1" , AA32}, {ID_ISAR0_EL1, 0x0, "ID_ISAR0_EL1" , AA32}, @@ -177,31 +173,32 @@ payload(uint32_t num_pe) uint32_t timeout; uint64_t debug_data=0, array_index=0; - for (i = 0; i < NUM_OF_REGISTERS; i++) - { + if (num_pe == 1) { + val_print(AVS_PRINT_WARN, "\n Skipping as num of PE is 1 ", 0); + val_set_status(my_index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); + return; + } + + for (i = 0; i < NUM_OF_REGISTERS; i++) { rd_data_array[i] = return_reg_value(reg_list[i].reg_name, reg_list[i].dependency); val_data_cache_ops_by_va((addr_t)(rd_data_array + i), CLEAN_AND_INVALIDATE); } - for (i = 0; i < num_pe; i++) - { - if (i != my_index) - { + for (i = 0; i < num_pe; i++) { + if (i != my_index) { timeout=TIMEOUT_LARGE; val_execute_on_pe(i, id_regs_check, 0); while ((--timeout) && (IS_RESULT_PENDING(val_get_status(i)))); - if(timeout == 0) - { - val_print(AVS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); + if(timeout == 0) { + val_print(AVS_PRINT_ERR, "\n **Timed out** for PE index = %d", i); val_set_status(i, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); return; } - if(IS_TEST_FAIL(val_get_status(i))) - { + if(IS_TEST_FAIL(val_get_status(i))) { val_get_test_data(i, &debug_data, &array_index); - val_print(AVS_PRINT_ERR, "\n Reg compare failed for PE index=%d for Register: ", i); + val_print(AVS_PRINT_ERR, "\n Reg compare failed for PE index=%d for Register: ", i); val_print(AVS_PRINT_ERR, reg_list[array_index].reg_desc, 0); val_print(AVS_PRINT_ERR, "\n Current PE value = 0x%llx", rd_data_array[array_index] & (~reg_list[array_index].reg_mask)); val_print(AVS_PRINT_ERR, " Other PE value = 0x%llx", debug_data); diff --git a/test_pool/peripherals/test_d003.c b/test_pool/peripherals/test_d003.c index fedf88c2..b56f21bc 100755 --- a/test_pool/peripherals/test_d003.c +++ b/test_pool/peripherals/test_d003.c @@ -51,7 +51,7 @@ uart_reg_write(uint32_t offset, uint32_t width_mask, uint32_t data) if (width_mask & WIDTH_BIT16) *((uint16_t *)(l_uart_base + offset)) = (uint16_t)data; - + if (width_mask & WIDTH_BIT32) *((uint32_t *)(l_uart_base + offset)) = (uint32_t)data; @@ -80,7 +80,7 @@ void uart_disable_txintr() { uint32_t data; - + /* mask TX interrupt bit 5 in */ data = uart_reg_read(SBSA_UARTIMSC, WIDTH_BIT32); data = data & (~(1<<5)); @@ -211,7 +211,7 @@ payload1() val_set_status(index, RESULT_PENDING(g_sbsa_level, TEST_NUM2)); val_gic_install_isr(int_id, isr); uart_enable_txintr(); - val_print(AVS_PRINT_DEBUG, "\n Test Message ", 0); + val_print(g_print_level, "\n Test Message ", 0); } else { val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM2, 01)); } diff --git a/test_pool/power_wakeup/test_u001.c b/test_pool/power_wakeup/test_u001.c index fb7b040b..81a062ae 100755 --- a/test_pool/power_wakeup/test_u001.c +++ b/test_pool/power_wakeup/test_u001.c @@ -33,6 +33,7 @@ #define TEST_DESC5 "Wake from System Timer Interrupt " static uint32_t intid; +uint64_t timer_num; static void @@ -40,7 +41,7 @@ isr_failsafe() { uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); val_timer_set_phy_el1(0); - val_print(AVS_PRINT_INFO, "\n Received Failsafe interrupt ", 0); + val_print(AVS_PRINT_ERR, "\n Received Failsafe interrupt ", 0); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); intid = val_timer_get_info(TIMER_INFO_PHY_EL1_INTID, 0); val_gic_end_of_interrupt(intid); @@ -90,17 +91,10 @@ void isr4() { uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); -// uint64_t wd_num = val_get_wd_info(0, WD_INFO_COUNT); - - /* We received our interrupt, we don't know which WD instance generated - the interrupt, so just ahead and disable all */ -// while(wd_num) -// val_set_wd_ws0(wd_num, 0); - - val_wd_set_ws0(0, 0); + val_wd_set_ws0(timer_num, 0); val_print(AVS_PRINT_INFO, "\n Received WS0 interrupt ", 0); val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM4, 01)); - intid = val_wd_get_info(0, WD_INFO_GSIV); + intid = val_wd_get_info(timer_num, WD_INFO_GSIV); val_gic_end_of_interrupt(intid); } @@ -108,11 +102,12 @@ static void isr5() { - uint64_t cnt_base_n = val_timer_get_info(TIMER_INFO_SYS_CNT_BASE_N, 0); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint64_t cnt_base_n = val_timer_get_info(TIMER_INFO_SYS_CNT_BASE_N, timer_num); val_timer_disable_system_timer((addr_t)cnt_base_n); val_print(AVS_PRINT_INFO, "\n Received Sys timer interrupt ", 0); - val_set_status(0, RESULT_PASS(g_sbsa_level, TEST_NUM5, 01)); - intid = val_timer_get_info(TIMER_INFO_SYS_INTID, 0); + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM5, 01)); + intid = val_timer_get_info(TIMER_INFO_SYS_INTID, timer_num); val_gic_end_of_interrupt(intid); } @@ -120,7 +115,7 @@ isr5() void wakeup_set_failsafe() { - uint64_t timer_expire_val = 900000; + uint64_t timer_expire_val = TIMEOUT_LARGE; intid = val_timer_get_info(TIMER_INFO_PHY_EL1_INTID, 0); val_gic_install_isr(intid, isr_failsafe); @@ -138,7 +133,7 @@ static void payload1() { - uint64_t timer_expire_val = 100000; + uint64_t timer_expire_val = TIMEOUT_SMALL; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); @@ -154,7 +149,7 @@ static void payload2() { - uint64_t timer_expire_val = 100000; + uint64_t timer_expire_val = TIMEOUT_SMALL; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM2, 01)); @@ -171,7 +166,7 @@ static void payload3() { - uint64_t timer_expire_val = 100000; + uint64_t timer_expire_val = TIMEOUT_SMALL; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM3, 01)); @@ -188,25 +183,38 @@ static void payload4() { - uint32_t status; - uint64_t timer_expire_val = 100000; + uint32_t status, ns_wdg = 0; + uint64_t timer_expire_val = TIMEOUT_SMALL; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM4, 01)); + timer_num = val_wd_get_info(0, WD_INFO_COUNT); + if(!timer_num){ + val_print(AVS_PRINT_WARN, "\n No watchdog implemented ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM4, 01)); + return; + } + + while(timer_num--) { + if(val_wd_get_info(timer_num, WD_INFO_ISSECURE)) + continue; - if (val_wd_get_info(0, WD_INFO_COUNT)) { - intid = val_wd_get_info(0, WD_INFO_GSIV); + ns_wdg++; + intid = val_wd_get_info(timer_num, WD_INFO_GSIV); status = val_gic_install_isr(intid, isr4); if (status == 0) { wakeup_set_failsafe(); - val_wd_set_ws0(0, timer_expire_val); + val_wd_set_ws0(timer_num, timer_expire_val); val_power_enter_semantic(SBSA_POWER_SEM_B); wakeup_clear_failsafe(); } else { val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM4, 01)); } - } else { - val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM4, 01)); + } + + if(!ns_wdg){ + val_print(AVS_PRINT_WARN, "\n No non-secure watchdog implemented ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM4, 02)); + return; } } @@ -216,32 +224,49 @@ void payload5() { uint64_t cnt_base_n; - uint32_t timeout = TIMEOUT_MEDIUM; - uint32_t status; + uint64_t timer_expire_val = TIMEOUT_SMALL; + uint32_t status, ns_timer = 0; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - if (val_timer_get_info(TIMER_INFO_NUM_PLATFORM_TIMERS, 0)) { + timer_num = val_timer_get_info(TIMER_INFO_NUM_PLATFORM_TIMERS, 0); + if(!timer_num){ + val_print(AVS_PRINT_WARN, "\n No system timers implemented ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM5, 01)); + return; + } + + while(timer_num--) { + + if(val_timer_get_info(TIMER_INFO_IS_PLATFORM_TIMER_SECURE, timer_num)) + continue; + + ns_timer++; + status = val_timer_get_info(TIMER_INFO_SYS_TIMER_STATUS, 0); + if(status != AVS_STATUS_PASS){ + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM5, 02)); + return; + } //Read CNTACR to determine whether access permission from NS state is permitted - status = val_timer_skip_if_cntbase_access_not_allowed(0); + status = val_timer_skip_if_cntbase_access_not_allowed(timer_num); if(status == AVS_STATUS_SKIP){ - val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM5, 02)); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM5, 03)); return; } - cnt_base_n = val_timer_get_info(TIMER_INFO_SYS_CNT_BASE_N, 0); + cnt_base_n = val_timer_get_info(TIMER_INFO_SYS_CNT_BASE_N, timer_num); if(cnt_base_n == 0){ - val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM5, 03)); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM5, 04)); return; } - intid = val_timer_get_info(TIMER_INFO_SYS_INTID, 0); + intid = val_timer_get_info(TIMER_INFO_SYS_INTID, timer_num); status = val_gic_install_isr(intid, isr5); if(status == 0) { wakeup_set_failsafe(); /* enable System timer */ - val_timer_set_system_timer((addr_t)cnt_base_n, timeout); + val_timer_set_system_timer((addr_t)cnt_base_n, timer_expire_val); val_power_enter_semantic(SBSA_POWER_SEM_B); wakeup_clear_failsafe(); } else{ @@ -249,8 +274,10 @@ payload5() return; } } - else{ - val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM5, 01)); + + if(!ns_timer){ + val_print(AVS_PRINT_WARN, "\n No non-secure systimer implemented ", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM4, 03)); return; } } diff --git a/test_pool/power_wakeup/test_u002.c b/test_pool/power_wakeup/test_u002.c index ddf09943..ed4b10ba 100755 --- a/test_pool/power_wakeup/test_u002.c +++ b/test_pool/power_wakeup/test_u002.c @@ -25,6 +25,8 @@ #define TEST_DESC "Test No-Wake from Power Semantic F" static uint32_t intid, wakeup_event, cnt_base_n=0; +static uint64_t timer_num, wd_num; + #define WATCHDOG_SEMF 0x1 #define SYSTIMER_SEMF 0x2 @@ -37,7 +39,7 @@ isr() if(wakeup_event == SYSTIMER_SEMF) val_timer_disable_system_timer((addr_t)cnt_base_n); else if(wakeup_event == WATCHDOG_SEMF) - val_wd_set_ws0(0, 0); + val_wd_set_ws0(wd_num, 0); val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); val_gic_end_of_interrupt(intid); @@ -46,20 +48,40 @@ isr() uint32_t wakeup_event_for_semantic_f() { - uint64_t num; - num = val_wd_get_info(0, WD_INFO_COUNT); + uint32_t ns_timer = 0, ns_wdg = 0; + wd_num = val_wd_get_info(0, WD_INFO_COUNT); - if(num == 0){ - num = val_timer_get_info(TIMER_INFO_NUM_PLATFORM_TIMERS, 0); - if(num == 0) + if(wd_num == 0){ + timer_num = val_timer_get_info(TIMER_INFO_NUM_PLATFORM_TIMERS, 0); + if(timer_num == 0) return 0; else{ - intid = val_timer_get_info(TIMER_INFO_SYS_INTID, 0); + while(timer_num--) { + if(val_timer_get_info(TIMER_INFO_IS_PLATFORM_TIMER_SECURE, timer_num)) + continue; + else{ + ns_timer++; + break; + } + } + if(ns_timer == 0) + return 0; + intid = val_timer_get_info(TIMER_INFO_SYS_INTID, timer_num); return SYSTIMER_SEMF; } } else{ - intid = val_wd_get_info(0, WD_INFO_GSIV); + while(wd_num--) { + if(val_wd_get_info(wd_num, WD_INFO_ISSECURE)) + continue; + else{ + ns_wdg++; + break; + } + } + if(ns_wdg == 0) + return 0; + intid = val_wd_get_info(wd_num, WD_INFO_GSIV); return WATCHDOG_SEMF; } @@ -128,11 +150,11 @@ payload() // Step5: Program timer/watchdog, which on expiry will generate an interrupt // and wake target PE if(wakeup_event == SYSTIMER_SEMF){ - cnt_base_n = val_timer_get_info(TIMER_INFO_SYS_CNT_BASE_N, 0); + cnt_base_n = val_timer_get_info(TIMER_INFO_SYS_CNT_BASE_N, timer_num); val_timer_set_system_timer((addr_t)cnt_base_n, timer_expire_ticks); } else if(wakeup_event == WATCHDOG_SEMF){ - val_wd_set_ws0(0, timer_expire_ticks); + val_wd_set_ws0(wd_num, timer_expire_ticks); } // Step6: Wait for target PE to update the status, if a timeout occurs that would mean that @@ -148,7 +170,7 @@ payload() if(wakeup_event == SYSTIMER_SEMF) val_timer_disable_system_timer((addr_t)cnt_base_n); else if(wakeup_event == WATCHDOG_SEMF) - val_wd_set_ws0(0, 0); + val_wd_set_ws0(wd_num, 0); val_gic_clear_interrupt(intid); } @@ -167,7 +189,7 @@ payload() if(wakeup_event == SYSTIMER_SEMF) val_timer_set_system_timer((addr_t)cnt_base_n, timer_expire_ticks); else if(wakeup_event == WATCHDOG_SEMF) - val_wd_set_ws0(0, timer_expire_ticks); + val_wd_set_ws0(wd_num, timer_expire_ticks); val_print(AVS_PRINT_INFO, "\n Interrupt generating sequence triggered", 0); @@ -182,7 +204,7 @@ payload() if(wakeup_event == SYSTIMER_SEMF) val_timer_disable_system_timer((addr_t)cnt_base_n); else if(wakeup_event == WATCHDOG_SEMF) - val_wd_set_ws0(0, 0); + val_wd_set_ws0(wd_num, 0); val_gic_clear_interrupt(intid); val_gic_end_of_interrupt(intid); // trigger END of interrupt for above interrupt diff --git a/test_pool/secure/test_s001.c b/test_pool/secure/test_s001.c index b84f9371..389da0d6 100755 --- a/test_pool/secure/test_s001.c +++ b/test_pool/secure/test_s001.c @@ -21,7 +21,7 @@ #include "val/include/sbsa_avs_secure.h" #define TEST_NUM (AVS_SECURE_TEST_NUM_BASE + 1) -#define TEST_DESC "Check NS Watchdog WS1 interrupt " +#define TEST_DESC "Check NS Watchdog WS1 interrupt " static void @@ -39,21 +39,21 @@ static void payload() { - uint32_t int_id_ws0, int_id_ws1; - uint64_t wd_num = 1; //val_wd_get_info(0, INFO_WD_COUNT); - uint32_t timeout = 2, timeout_intr=0; - uint32_t timer_expire_ticks = 10000; + uint32_t int_id_ws0, int_id_ws1, ns_wdg = 0; + uint64_t wd_num = val_wd_get_info(0, WD_INFO_COUNT); + uint32_t timeout = 2, timeout_intr; + uint32_t timer_expire_ticks = 1000; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); SBSA_SMC_t smc; if (wd_num == 0) { - //no watchdogs in the system. Fail this test and return - val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); + val_print(AVS_PRINT_WARN, "\n No Watchdogs reported %d ", wd_num); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); return; } - + do { wd_num--; //array index starts from 0, so subtract 1 from count @@ -61,19 +61,21 @@ payload() if (val_wd_get_info(wd_num, WD_INFO_ISSECURE)) continue; //Skip Secure watchdog + ns_wdg++; + timeout_intr = TIMEOUT_LARGE; + val_set_status(index, RESULT_PENDING(g_sbsa_level, TEST_NUM)); // Set the initial result to pending + int_id_ws0 = val_wd_get_info(wd_num, WD_INFO_GSIV); int_id_ws1 = val_wd_get_info(wd_num+1, WD_INFO_GSIV); // ACPI table for WS1 may need to be populated val_print(AVS_PRINT_DEBUG, "\n WS0 Interrupt id %d ", int_id_ws0); val_print(AVS_PRINT_DEBUG, "\n WS1 Interrupt id %d ", int_id_ws1); val_gic_install_isr(int_id_ws0, isr); - val_gic_install_isr(int_id_ws1, isr); // ISR doesn't matter here, + val_gic_install_isr(int_id_ws1, isr); // ISR doesn't matter here, // because interrupt is routed to EL3 val_wd_set_ws0(wd_num, timer_expire_ticks); - timeout_intr = 2*timer_expire_ticks; - while (!(IS_TEST_PASS(val_get_status(index))) && (--timeout_intr)); if(timeout_intr == 0){ @@ -99,13 +101,19 @@ payload() val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 03)); } + // Stop watchdog and signal end of interrupt to gic, it should be done after receiving both + // WS0 and WS1 interrupts + val_wd_set_ws0(wd_num, 0); + val_gic_end_of_interrupt(int_id_ws0); }while(wd_num); - // Stop watchdog and signal end of interrupt to gic, it should be done after receiving both - // WS0 and WS1 interrupts - val_wd_set_ws0(0, 0); - val_gic_end_of_interrupt(int_id_ws0); + if(!ns_wdg) { + val_print(AVS_PRINT_WARN, "\n No non-secure Watchdogs reported", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 02)); + return; + } + } uint32_t diff --git a/test_pool/secure/test_s003.c b/test_pool/secure/test_s003.c index 0baba1e7..4be2754b 100755 --- a/test_pool/secure/test_s003.c +++ b/test_pool/secure/test_s003.c @@ -39,20 +39,12 @@ secure_test_list list[] = { "Check Secure UART Access ", 0, 0, 0}, {(AVS_SECURE_TEST_NUM_BASE + 6), SBSA_SECURE_TEST_WAKEUP, "Check Wakeup from Secure timer ", 0, 0, 0}, - {(AVS_SECURE_TEST_NUM_BASE + 7), SBSA_SECURE_TEST_FINISH, + {(AVS_SECURE_TEST_NUM_BASE + 7), SBSA_SECURE_TEST_SYS_TIMER_INT, + "System Wakeup Timer interrupt ", 0, 0, 0}, + {(AVS_SECURE_TEST_NUM_BASE + 8), SBSA_SECURE_TEST_FINISH, "Last entry ", 0, 0, 0} }; -static -void -esr() -{ - val_print(AVS_PRINT_TEST, "\n Received FIQ ", 0); - //AArch64FlushCache((uint64_t)payload); - //update_x28(gnext_line); - val_set_status(0, RESULT_PASS(g_sbsa_level, 904, 01)); -} - static void start_secure_tests(uint32_t num_pe) @@ -63,8 +55,6 @@ start_secure_tests(uint32_t num_pe) uint32_t status; SBSA_SMC_t smc; - val_pe_install_esr(EXCEPT_AARCH64_FIQ, esr); - while (list[i].test_index != SBSA_SECURE_TEST_FINISH) { smc.test_index = list[i].test_index; diff --git a/test_pool/timer_wd/test_t002.c b/test_pool/timer_wd/test_t002.c index 0a27378e..fa91346b 100755 --- a/test_pool/timer_wd/test_t002.c +++ b/test_pool/timer_wd/test_t002.c @@ -40,8 +40,8 @@ void payload() { - uint32_t timeout = 0x100000; - uint32_t timer_expire_val = 10000; + uint32_t timeout = TIMEOUT_LARGE; + uint32_t timer_expire_val = 100; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); intid = val_timer_get_info(TIMER_INFO_PHY_EL1_INTID, 0); @@ -61,8 +61,10 @@ payload() while ((--timeout > 0) && (IS_RESULT_PENDING(val_get_status(index)))); - if (timeout == 0) + if (timeout == 0){ + val_print(AVS_PRINT_ERR, "\n EL0-Phy timer interrupt not received on %d ", intid); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); + } } diff --git a/test_pool/timer_wd/test_t003.c b/test_pool/timer_wd/test_t003.c index d2bc949f..b4988533 100755 --- a/test_pool/timer_wd/test_t003.c +++ b/test_pool/timer_wd/test_t003.c @@ -37,14 +37,13 @@ isr() } - static void payload() { - uint32_t timeout = 0x100000; - uint64_t timer_expire_val = 10000; + uint32_t timeout = TIMEOUT_LARGE; + uint64_t timer_expire_val = 100; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); intid = val_timer_get_info(TIMER_INFO_VIR_EL1_INTID, 0); @@ -62,8 +61,10 @@ payload() while ((--timeout > 0) && (IS_RESULT_PENDING(val_get_status(index)))); - if (timeout == 0) + if (timeout == 0) { + val_print(AVS_PRINT_ERR, "\n EL0-Virtual timer interrupt not received on %d ", intid); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); + } } diff --git a/test_pool/timer_wd/test_t004.c b/test_pool/timer_wd/test_t004.c index ab8bc34d..b343f700 100755 --- a/test_pool/timer_wd/test_t004.c +++ b/test_pool/timer_wd/test_t004.c @@ -37,14 +37,13 @@ isr() } - static void payload() { - uint32_t timeout = 0x100000; - uint64_t timer_expire_val = 10000; + uint32_t timeout = TIMEOUT_LARGE; + uint64_t timer_expire_val = 100; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); intid = val_timer_get_info(TIMER_INFO_PHY_EL2_INTID, 0); @@ -63,8 +62,10 @@ payload() while ((--timeout > 0) && (IS_RESULT_PENDING(val_get_status(index)))); - if (timeout == 0) + if (timeout == 0) { + val_print(AVS_PRINT_ERR, "\n EL2-Phy timer interrupt not received on %d ", intid); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); + } } diff --git a/test_pool/timer_wd/test_t005.c b/test_pool/timer_wd/test_t005.c index 0f25471c..6d72eaa6 100755 --- a/test_pool/timer_wd/test_t005.c +++ b/test_pool/timer_wd/test_t005.c @@ -44,8 +44,8 @@ void payload() { - uint32_t timeout = 0x100000; - uint64_t timer_expire_val = 10000; + uint32_t timeout = TIMEOUT_LARGE; + uint64_t timer_expire_val = 100; uint64_t data = 0; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); @@ -57,12 +57,12 @@ payload() val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); return; } - + intid = val_timer_get_info(TIMER_INFO_VIR_EL2_INTID, 0); /* For SBSA level 2 and above, the PPI has to be a specific value.*/ if (g_sbsa_level > 1) { if (intid != 28) { - val_print(AVS_PRINT_ERR, "\n Incorrect PPI value %d ", intid); + val_print(AVS_PRINT_ERR, "\n Incorrect PPI value %d ", intid); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); return; } @@ -74,8 +74,10 @@ payload() while ((--timeout > 0) && (IS_RESULT_PENDING(val_get_status(index)))); - if (timeout == 0) + if (timeout == 0) { + val_print(AVS_PRINT_ERR, "\n EL2-Virtual timer interrupt not received on %d ", intid); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); + } } diff --git a/test_pool/timer_wd/test_t007.c b/test_pool/timer_wd/test_t007.c index b4affaa8..f452e508 100755 --- a/test_pool/timer_wd/test_t007.c +++ b/test_pool/timer_wd/test_t007.c @@ -22,6 +22,8 @@ #define TEST_NUM (AVS_TIMER_TEST_NUM_BASE + 7) #define TEST_DESC "CNTCTLBase & CNTBaseN access " +#define ARBIT_VALUE 0xA000 + static void payload() @@ -34,7 +36,7 @@ payload() if (!timer_num) { val_print(AVS_PRINT_WARN, "\n No System timers are defined ", 0); - val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 0x1)); return; } @@ -49,43 +51,75 @@ payload() if (cnt_ctl_base == 0) { val_print(AVS_PRINT_WARN, "\n CNTCTL BASE_N is zero ", 0); - val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 02)); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 0x2)); return; } + data = val_mmio_read(cnt_ctl_base + 0x8); + if (data == 0x0) { + val_print(AVS_PRINT_ERR, "\n Unexpected value for CNTCTLBase.CNTTIDR %x ", data); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 0x1)); + return; + } + val_mmio_write(cnt_ctl_base + 0x8, 0xFFFFFFFF); + if(data != val_mmio_read(cnt_ctl_base + 0x8)) { + val_print(AVS_PRINT_ERR, "\n Read-write check failed for CNTCTLBase.CNTTIDR, expected value %x ", data); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 0x2)); + return; + } data = val_mmio_read(cnt_ctl_base + 0xFD0); if ((data == 0x0) || ((data & 0xFFFF) == 0xFFFF)) { - val_print(AVS_PRINT_ERR, "\n Unxepected value for CNTCTLBase.CounterID %x ", data); - val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 04)); + val_print(AVS_PRINT_ERR, "\n Unexpected value for CNTCTLBase.CounterID %x ", data); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 0x3)); return; } if (cnt_base_n == 0) { val_print(AVS_PRINT_WARN, "\n CNT_BASE_N is zero ", 0); - val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 02)); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 0x3)); return; } data = val_mmio_read(cnt_base_n + 0x0); - val_mmio_write(cnt_base_n + 0x0, 0xFFFFFF); - if(data != val_mmio_read(cnt_base_n + 0x0)) { - val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 05)); - val_print(AVS_PRINT_ERR, "\n CNTBaseN offset 0 should be read-only ", 0); + val_mmio_write(cnt_base_n + 0x0, data - ARBIT_VALUE); // Writes to Read-Only registers should be ignored + if(val_mmio_read(cnt_base_n + 0x0) < data) { + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 0x4)); + val_print(AVS_PRINT_ERR, "\n CNTBaseN offset 0 should be read-only ", 0); + return; + } + + data = 0x3; + val_mmio_write(cnt_base_n + 0x2C, data); + if(data != (val_mmio_read(cnt_base_n + 0x2C) & 0x3)) { + val_print(AVS_PRINT_ERR, "\n Read-write check failed for CNTBaseN.CNTP_CTL, expected value %x ", data); + val_print(AVS_PRINT_ERR, "\n Read value %x ", val_mmio_read(cnt_base_n + 0x2C)); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 0x5)); + val_mmio_write(cnt_base_n + 0x2C, 0x0); // Disable the timer before return + return; + } + val_mmio_write(cnt_base_n + 0x2C, 0x0); // Disable timer + + data = 0xFF00FF00; + val_mmio_write(cnt_base_n + 0x20, data); + if(data != val_mmio_read(cnt_base_n + 0x20)) { + val_print(AVS_PRINT_ERR, "\n Read-write check failed for CNTBaseN.CNTP_CVAL[31:0], expected value %x ", data); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 0x6)); return; } - data = val_mmio_read(cnt_ctl_base + 0x10); - if (!data) { - val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 03)); - val_print(AVS_PRINT_ERR, "\n CNTBaseN.CNTFRQ should not be 0 ", 0); + data = 0x00FF00FF; + val_mmio_write(cnt_base_n + 0x24, data); + if(data != val_mmio_read(cnt_base_n + 0x24)) { + val_print(AVS_PRINT_ERR, "\n Read-write check failed for CNTBaseN.CNTP_CVAL[63:32], expected value %x ", data); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 0x7)); return; } data = val_mmio_read(cnt_base_n + 0xFD0); if ((data == 0x0) || ((data & 0xFFFF) == 0xFFFF)) { - val_print(AVS_PRINT_ERR, "\n Unxepected value for CNTBaseN.CounterID %x ", data); - val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 06)); + val_print(AVS_PRINT_ERR, "\n Unexpected value for CNTBaseN.CounterID %x ", data); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 0x8)); return; } diff --git a/test_pool/timer_wd/test_t008.c b/test_pool/timer_wd/test_t008.c index 2393b020..cc58446f 100644 --- a/test_pool/timer_wd/test_t008.c +++ b/test_pool/timer_wd/test_t008.c @@ -25,16 +25,17 @@ #define TEST_DESC "Generate Mem Mapped SYS Timer Intr" static uint32_t intid; +static uint64_t cnt_base_n; static void isr() { - uint64_t cnt_base_n = val_timer_get_info(TIMER_INFO_SYS_CNT_BASE_N, 0); + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); val_print(AVS_PRINT_INFO, "\n Received interrupt ", 0); val_timer_disable_system_timer((addr_t)cnt_base_n); - val_set_status(0, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); val_gic_end_of_interrupt(intid); } @@ -44,9 +45,9 @@ void payload() { - uint64_t cnt_base_n; - uint32_t timeout = TIMEOUT_MEDIUM; - uint32_t status; + volatile uint32_t timeout; + uint32_t timer_expire_val = 1000; + uint32_t status, ns_timer = 0; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); uint64_t timer_num = val_timer_get_info(TIMER_INFO_NUM_PLATFORM_TIMERS, 0); @@ -62,6 +63,10 @@ payload() if (val_timer_get_info(TIMER_INFO_IS_PLATFORM_TIMER_SECURE, timer_num)) continue; //Skip Secure Timer + ns_timer++; + timeout = TIMEOUT_LARGE; + val_set_status(index, RESULT_PENDING(g_sbsa_level, TEST_NUM)); // Set the initial result to pending + //Read CNTACR to determine whether access permission from NS state is permitted status = val_timer_skip_if_cntbase_access_not_allowed(timer_num); if(status == AVS_STATUS_SKIP){ @@ -82,13 +87,21 @@ payload() val_gic_install_isr(intid, isr); /* enable System timer */ - val_timer_set_system_timer((addr_t)cnt_base_n, timeout); + val_timer_set_system_timer((addr_t)cnt_base_n, timer_expire_val); while ((--timeout > 0) && (IS_RESULT_PENDING(val_get_status(index)))); - if (timeout == 0) + if (timeout == 0){ + val_print(AVS_PRINT_ERR, "\n Sys timer interrupt not received on %d ", intid); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); - timer_num = 0; + return; + } + } + + if(!ns_timer) { + val_print(AVS_PRINT_WARN, "\n No non-secure systimer implemented", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 04)); + return; } } diff --git a/test_pool/timer_wd/test_w001.c b/test_pool/timer_wd/test_w001.c index 501d437a..421a3a63 100755 --- a/test_pool/timer_wd/test_w001.c +++ b/test_pool/timer_wd/test_w001.c @@ -31,23 +31,23 @@ payload() uint64_t refresh_base; uint64_t wd_num = val_wd_get_info(0, WD_INFO_COUNT); uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t data; + uint32_t data, ns_wdg = 0; val_print(AVS_PRINT_DEBUG, "\n Found %d watchdogs in ACPI table ", wd_num); if (wd_num == 0) { - //no watchdogs in the system. Fail this test and return val_print(AVS_PRINT_WARN, "\n No Watchdogs reported %d ", wd_num); - val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 01)); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); return; } - + do { wd_num--; //array index starts from 0, so subtract 1 from count if (val_wd_get_info(wd_num, WD_INFO_ISSECURE)) continue; //Skip Secure watchdog + ns_wdg++; refresh_base = val_wd_get_info(wd_num, WD_INFO_REFRESH_BASE); val_print(AVS_PRINT_INFO, "\n Watchdog Refresh base is %x ", refresh_base); ctrl_base = val_wd_get_info(wd_num, WD_INFO_CTRL_BASE); @@ -68,6 +68,12 @@ payload() } } while(wd_num); + if(!ns_wdg) { + val_print(AVS_PRINT_WARN, "\n No non-secure Watchdogs reported", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 02)); + return; + } + val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); } diff --git a/test_pool/timer_wd/test_w002.c b/test_pool/timer_wd/test_w002.c index ca83e0de..9845e143 100755 --- a/test_pool/timer_wd/test_w002.c +++ b/test_pool/timer_wd/test_w002.c @@ -24,21 +24,15 @@ #define TEST_DESC "Check Watchdog WS0 interrupt " static uint32_t int_id; +static uint64_t wd_num; static void isr() { uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); -// uint64_t wd_num = val_wd_get_info(0, WD_INFO_COUNT); - - /* We received our interrupt, we don't know which WD instance generated - the interrupt, so just ahead and disable all */ -// while(wd_num) -// val_wd_set_ws0(wd_num, 0); - - val_wd_set_ws0(0, 0); - val_print(AVS_PRINT_DEBUG, "\n Received WS0 interrupt ", 0); + val_wd_set_ws0(wd_num, 0); + val_print(AVS_PRINT_DEBUG, "\n Received WS0 interrupt ", 0); val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 01)); val_gic_end_of_interrupt(int_id); } @@ -49,26 +43,30 @@ void payload() { - uint64_t wd_num = 1; //val_wd_get_info(0, INFO_WD_COUNT); - uint32_t timeout = 0x1000000; - uint64_t timer_expire_ticks = 10000; + uint32_t timeout, ns_wdg = 0; + uint64_t timer_expire_ticks = 100; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + wd_num = val_wd_get_info(0, WD_INFO_COUNT); if (wd_num == 0) { - //no watchdogs in the system. Fail this test and return + val_print(AVS_PRINT_WARN, "\n No Watchdogs reported %d ", wd_num); val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); return; } - + do { wd_num--; //array index starts from 0, so subtract 1 from count if (val_wd_get_info(wd_num, WD_INFO_ISSECURE)) continue; //Skip Secure watchdog + ns_wdg++; + timeout = TIMEOUT_LARGE; + val_set_status(index, RESULT_PENDING(g_sbsa_level, TEST_NUM)); // Set the initial result to pending + int_id = val_wd_get_info(wd_num, WD_INFO_GSIV); - val_print(AVS_PRINT_DEBUG, "\n WS0 Interrupt id %d ", int_id); + val_print(AVS_PRINT_DEBUG, "\n WS0 Interrupt id %d ", int_id); val_gic_install_isr(int_id, isr); @@ -77,13 +75,19 @@ payload() while ((--timeout > 0) && (IS_RESULT_PENDING(val_get_status(index)))); if (timeout == 0) { - val_print(AVS_PRINT_ERR, "\n WS0 Interrupt not received on %d ", int_id); - val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); + val_print(AVS_PRINT_ERR, "\n WS0 Interrupt not received on %d ", int_id); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); return; } } while(wd_num); + if(!ns_wdg) { + val_print(AVS_PRINT_WARN, "\n No non-secure Watchdogs reported", 0); + val_set_status(index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 02)); + return; + } + } uint32_t diff --git a/uefi_app/SbsaAvs.h b/uefi_app/SbsaAvs.h index d8ab2dfe..5a581e8c 100755 --- a/uefi_app/SbsaAvs.h +++ b/uefi_app/SbsaAvs.h @@ -19,11 +19,20 @@ - #define SBSA_ACS_MAJOR_VER 0 - #define SBSA_ACS_MINOR_VER 8 + #define SBSA_ACS_MAJOR_VER 1 + #define SBSA_ACS_MINOR_VER 0 #define G_SBSA_LEVEL 3 #define G_PRINT_LEVEL AVS_PRINT_TEST + #define PE_INFO_TBL_SZ 8192 + #define GIC_INFO_TBL_SZ 2048 + #define TIMER_INFO_TBL_SZ 1024 + #define WD_INFO_TBL_SZ 512 + #define MEM_INFO_TBL_SZ 4096 + #define IOVIRT_INFO_TBL_SZ 4096 + #define PERIPHERAL_INFO_TBL_SZ 1024 + #define PCIE_INFO_TBL_SZ 64 + #endif diff --git a/uefi_app/SbsaAvs.inf b/uefi_app/SbsaAvs.inf index 4462e16c..de037783 100755 --- a/uefi_app/SbsaAvs.inf +++ b/uefi_app/SbsaAvs.inf @@ -1,113 +1,115 @@ -## @file -# Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. -# -# 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. -## - - -[Defines] - INF_VERSION = 0x00010006 - BASE_NAME = Sbsa - FILE_GUID = a912f198-7f0e-4803-b908-b757b806ec83 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 0.1 - ENTRY_POINT = ShellCEntryLib - -# -# VALID_ARCHITECTURES = AARCH64 -# - -[Sources.AARCH64] - ../ - SbsaAvsMain.c - ../test_pool/secure/test_s001.c - ../test_pool/secure/test_s002.c - ../test_pool/secure/test_s003.c - ../test_pool/pe/test_c001.c - ../test_pool/pe/test_c002.c - ../test_pool/pe/test_c003.c - ../test_pool/pe/test_c004.c - ../test_pool/pe/test_c005.c - ../test_pool/pe/test_c006.c - ../test_pool/pe/test_c007.c - ../test_pool/pe/test_c008.c - ../test_pool/pe/test_c009.c - ../test_pool/pe/test_c010.c - ../test_pool/pe/test_c011.c - ../test_pool/pe/test_c012.c - ../test_pool/pe/test_c013.c - ../test_pool/pe/test_c014.c - ../test_pool/pe/test_c015.c - ../test_pool/pe/test_c016.c - ../test_pool/pe/test_c017.c - ../test_pool/pe/test_c018.c - ../test_pool/gic/test_g001.c - ../test_pool/gic/test_g002.c - ../test_pool/gic/test_g003.c - ../test_pool/gic/test_g004.c - ../test_pool/timer_wd/test_t001.c - ../test_pool/timer_wd/test_t002.c - ../test_pool/timer_wd/test_t003.c - ../test_pool/timer_wd/test_t004.c - ../test_pool/timer_wd/test_t005.c - ../test_pool/timer_wd/test_t006.c - ../test_pool/timer_wd/test_t007.c - ../test_pool/timer_wd/test_t008.c - ../test_pool/timer_wd/test_w001.c - ../test_pool/timer_wd/test_w002.c - ../test_pool/pcie/test_p001.c - ../test_pool/pcie/test_p002.c - ../test_pool/pcie/test_p003.c - ../test_pool/io_virt/test_i001.c - ../test_pool/io_virt/test_i002.c - ../test_pool/io_virt/test_i003.c - ../test_pool/io_virt/test_i004.c - ../test_pool/power_wakeup/test_u001.c - ../test_pool/power_wakeup/test_u002.c - ../test_pool/peripherals/test_d001.c - ../test_pool/peripherals/test_d002.c - ../test_pool/peripherals/test_d003.c - ../test_pool/peripherals/test_m001.c - ../test_pool/peripherals/test_m002.c - -[Packages] - EmbeddedPkg/EmbeddedPkg.dec - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - ShellPkg/ShellPkg.dec - EdkCompatibilityPkg/EdkCompatibilityPkg.dec - -[LibraryClasses] - SbsaValLib - SbsaPalLib - UefiLib - ShellLib - DebugLib - BaseMemoryLib - ShellCEntryLib - UefiBootServicesTableLib - UefiRuntimeServicesTableLib - -[Protocols] - gEfiAcpiTableProtocolGuid ## CONSUMES - gHardwareInterruptProtocolGuid ## CONSUMES - gEfiCpuArchProtocolGuid ## CONSUMES - gEfiPciIoProtocolGuid ## CONSUMES +## @file +# Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. +# +# 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. +## + + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = Sbsa + FILE_GUID = a912f198-7f0e-4803-b908-b757b806ec83 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 0.1 + ENTRY_POINT = ShellCEntryLib + +# +# VALID_ARCHITECTURES = AARCH64 +# + +[Sources.AARCH64] + ../ + SbsaAvsMain.c + ../test_pool/secure/test_s001.c + ../test_pool/secure/test_s002.c + ../test_pool/secure/test_s003.c + ../test_pool/pe/test_c001.c + ../test_pool/pe/test_c002.c + ../test_pool/pe/test_c003.c + ../test_pool/pe/test_c004.c + ../test_pool/pe/test_c005.c + ../test_pool/pe/test_c006.c + ../test_pool/pe/test_c007.c + ../test_pool/pe/test_c008.c + ../test_pool/pe/test_c009.c + ../test_pool/pe/test_c010.c + ../test_pool/pe/test_c011.c + ../test_pool/pe/test_c012.c + ../test_pool/pe/test_c013.c + ../test_pool/pe/test_c014.c + ../test_pool/pe/test_c015.c + ../test_pool/pe/test_c016.c + ../test_pool/pe/test_c017.c + ../test_pool/pe/test_c018.c + ../test_pool/gic/test_g001.c + ../test_pool/gic/test_g002.c + ../test_pool/gic/test_g003.c + ../test_pool/gic/test_g004.c + ../test_pool/timer_wd/test_t001.c + ../test_pool/timer_wd/test_t002.c + ../test_pool/timer_wd/test_t003.c + ../test_pool/timer_wd/test_t004.c + ../test_pool/timer_wd/test_t005.c + ../test_pool/timer_wd/test_t006.c + ../test_pool/timer_wd/test_t007.c + ../test_pool/timer_wd/test_t008.c + ../test_pool/timer_wd/test_w001.c + ../test_pool/timer_wd/test_w002.c + ../test_pool/pcie/test_p001.c + ../test_pool/pcie/test_p002.c + ../test_pool/pcie/test_p003.c + ../test_pool/io_virt/test_i001.c + ../test_pool/io_virt/test_i002.c + ../test_pool/io_virt/test_i003.c + ../test_pool/io_virt/test_i004.c + ../test_pool/io_virt/test_i005.c + ../test_pool/io_virt/test_i006.c + ../test_pool/power_wakeup/test_u001.c + ../test_pool/power_wakeup/test_u002.c + ../test_pool/peripherals/test_d001.c + ../test_pool/peripherals/test_d002.c + ../test_pool/peripherals/test_d003.c + ../test_pool/peripherals/test_m001.c + ../test_pool/peripherals/test_m002.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + EdkCompatibilityPkg/EdkCompatibilityPkg.dec + +[LibraryClasses] + SbsaValLib + SbsaPalLib + UefiLib + ShellLib + DebugLib + BaseMemoryLib + ShellCEntryLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + +[Protocols] + gEfiAcpiTableProtocolGuid ## CONSUMES + gHardwareInterruptProtocolGuid ## CONSUMES + gEfiCpuArchProtocolGuid ## CONSUMES + gEfiPciIoProtocolGuid ## CONSUMES gEfiLoadedImageProtocolGuid ## CONSUMES - -[Guids] - gEfiAcpi20TableGuid - gEfiAcpiTableGuid - -[BuildOptions] - GCC:*_*_*_ASM_FLAGS = -march=armv8.1-a + +[Guids] + gEfiAcpi20TableGuid + gEfiAcpiTableGuid + +[BuildOptions] + GCC:*_*_*_ASM_FLAGS = -march=armv8.1-a diff --git a/uefi_app/SbsaAvsMain.c b/uefi_app/SbsaAvsMain.c index 43c899e3..e1f70fea 100755 --- a/uefi_app/SbsaAvsMain.c +++ b/uefi_app/SbsaAvsMain.c @@ -1,40 +1,46 @@ -/** @file - * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. - - * 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 -#include -#include -#include - -#include "val/include/val_interface.h" +/** @file + * Copyright (c) 2017, ARM Limited or its affiliates. All rights reserved. + + * 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 +#include +#include +#include +#include +#include + +#include "val/include/val_interface.h" #include "val/include/sbsa_avs_pe.h" - -#include "SbsaAvs.h" - - -UINT32 g_sbsa_level; -UINT32 g_print_level; -UINT32 g_execute_secure; -UINT32 g_skip_test_num[3] = {10000, 10000, 10000}; -UINT32 g_sbsa_tests_total; -UINT32 g_sbsa_tests_pass; -UINT32 g_sbsa_tests_fail; -SHELL_FILE_HANDLE g_sbsa_log_file_handle; - +#include "val/include/sbsa_avs_val.h" + +#include "SbsaAvs.h" + + +UINT32 g_sbsa_level; +UINT32 g_print_level; +UINT32 g_execute_secure; +UINT32 g_skip_test_num[3] = {10000, 10000, 10000}; +UINT32 g_sbsa_tests_total; +UINT32 g_sbsa_tests_pass; +UINT32 g_sbsa_tests_fail; +UINT64 g_stack_pointer; +UINT64 g_exception_ret_addr; +UINT64 g_ret_addr; +SHELL_FILE_HANDLE g_sbsa_log_file_handle; + STATIC VOID FlushImage (VOID) { EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; @@ -49,390 +55,399 @@ STATIC VOID FlushImage (VOID) } -EFI_STATUS -createPeInfoTable ( -) -{ - - EFI_STATUS Status; - - UINT64 *PeInfoTable; - -/* allowing room for growth, at present each entry is 16 bytes, so we can support upto 511 PEs with 8192 bytes*/ - Status = gBS->AllocatePool ( EfiBootServicesData, - 8192, - (VOID **) &PeInfoTable ); - - if (EFI_ERROR(Status)) - { - Print(L"Allocate Pool failed %x \n", Status); - return Status; - } - - Status = val_pe_create_info_table(PeInfoTable); - - return Status; - -} - -EFI_STATUS -createGicInfoTable ( -) -{ - EFI_STATUS Status; - UINT64 *GicInfoTable; - - Status = gBS->AllocatePool (EfiBootServicesData, - 2048, - (VOID **) &GicInfoTable); - - if (EFI_ERROR(Status)) - { - Print(L"Allocate Pool failed %x \n", Status); - return Status; - } - - Status = val_gic_create_info_table(GicInfoTable); - - return Status; - -} - - -EFI_STATUS -createTimerInfoTable( -) -{ - UINT64 *TimerInfoTable; - EFI_STATUS Status; - - Status = gBS->AllocatePool (EfiBootServicesData, - 1024, - (VOID **) &TimerInfoTable); - - if (EFI_ERROR(Status)) - { - Print(L"Allocate Pool failed %x \n", Status); - return Status; - } - val_timer_create_info_table(TimerInfoTable); - - return Status; -} - -EFI_STATUS -createWatchdogInfoTable( -) -{ - UINT64 *WdInfoTable; - EFI_STATUS Status; - - Status = gBS->AllocatePool (EfiBootServicesData, - 512, - (VOID **) &WdInfoTable); - - if (EFI_ERROR(Status)) - { - Print(L"Allocate Pool failed %x \n", Status); - return Status; - } - val_wd_create_info_table(WdInfoTable); - - return Status; - -} - - -EFI_STATUS -createPcieVirtInfoTable( -) -{ - UINT64 *PcieInfoTable; - UINT64 *IoVirtInfoTable; - - EFI_STATUS Status; - - Status = gBS->AllocatePool (EfiBootServicesData, - 64, - (VOID **) &PcieInfoTable); - - if (EFI_ERROR(Status)) - { - Print(L"Allocate Pool failed %x \n", Status); - return Status; - } - val_pcie_create_info_table(PcieInfoTable); - - Status = gBS->AllocatePool (EfiBootServicesData, - 4096, - (VOID **) &IoVirtInfoTable); - - if (EFI_ERROR(Status)) - { - Print(L"Allocate Pool failed %x \n", Status); - return Status; - } - val_iovirt_create_info_table(IoVirtInfoTable); - - return Status; -} - -EFI_STATUS -createPeripheralInfoTable( -) -{ - UINT64 *PeripheralInfoTable; - UINT64 *MemoryInfoTable; - - EFI_STATUS Status; - - Status = gBS->AllocatePool (EfiBootServicesData, - 1024, - (VOID **) &PeripheralInfoTable); - - if (EFI_ERROR(Status)) - { - Print(L"Allocate Pool failed %x \n", Status); - return Status; - } - val_peripheral_create_info_table(PeripheralInfoTable); - - Status = gBS->AllocatePool (EfiBootServicesData, - 4096, - (VOID **) &MemoryInfoTable); - - if (EFI_ERROR(Status)) - { - Print(L"Allocate Pool failed %x \n", Status); - return Status; - } - - val_memory_create_info_table(MemoryInfoTable); - - return Status; -} - -VOID -freeSbsaAvsMem() -{ - - val_pe_free_info_table(); - val_gic_free_info_table(); - val_timer_free_info_table(); - val_wd_free_info_table(); - val_pcie_free_info_table(); - val_iovirt_free_info_table(); - val_peripheral_free_info_table(); - val_free_shared_mem(); -} - -VOID -HelpMsg ( - VOID - ) -{ - Print (L"\nUsage: Sbsa.efi [-v ] | [-l ] | [-f ] | [-s] | [-skip ]\n" - "Options:\n" - "-v Verbosity of the Prints\n" - " 1 shows all prints, 5 shows Errors\n" - "-l Level of compliance to be tested for\n" - " As per SBSA spec, 0 to 3\n" - "-f Name of the log file to record the test results in\n" - "-s Enable the execution of secure tests\n" - "-skip Test(s) to be skipped\n" - " Refer to section 4 of SBSA_ACS_UEFI_App_User_Guide\n" - " To skip a module, use Model_ID as mentioned in user guide\n" - " To skip a particular test within a module, use the exact testcase number\n" - ); -} - -STATIC CONST SHELL_PARAM_ITEM ParamList[] = { - {L"-v" , TypeValue}, // -v # Verbosity of the Prints. 1 shows all prints, 5 shows Errors - {L"-l" , TypeValue}, // -l # Level of compliance to be tested for. - {L"-f" , TypeValue}, // -f # Name of the log file to record the test results in. - {L"-s" , TypeFlag}, // -s # Binary Flag to enable the execution of secure tests. - {L"-skip" , TypeValue}, // -skip # test(s) to skip execution - {L"-help" , TypeFlag}, // -help # help : info about commands - {L"-h" , TypeFlag}, // -h # help : info about commands - {NULL , TypeMax} - }; - - -/*** - SBSA Compliance Suite Entry Point. - - Call the Entry points of individual modules. - - @retval 0 The application exited normally. - @retval Other An error occurred. -***/ -INTN -EFIAPI -ShellAppMain ( - IN UINTN Argc, - IN CHAR16 **Argv - ) -{ - - LIST_ENTRY *ParamPackage; - CONST CHAR16 *CmdLineArg; - CHAR16 *ProbParam; - UINT32 Status; - UINT32 i,j=0; - - - // - // Process Command Line arguments - // - Status = ShellInitialize(); - Status = ShellCommandLineParse (ParamList, &ParamPackage, &ProbParam, TRUE); - if (Status) { - Print(L"Shell command line parse error %x\n", Status); - Print(L"Unrecognized option %s passed\n", ProbParam); - HelpMsg(); - return SHELL_INVALID_PARAMETER; - } - - for (i=1 ; i 3) { - g_sbsa_level = G_SBSA_LEVEL; - } - } - - - // Options with Values - CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-v"); - if (CmdLineArg == NULL) { - g_print_level = G_PRINT_LEVEL; - } else { - g_print_level = StrDecimalToUintn(CmdLineArg); - if (g_print_level > 5) { - g_print_level = G_PRINT_LEVEL; - } - } - - // Options with Values - CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-f"); - if (CmdLineArg == NULL) { - g_sbsa_log_file_handle = NULL; - } else { - Status = ShellOpenFileByName(CmdLineArg, &g_sbsa_log_file_handle, - EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE, 0x0); - if(EFI_ERROR(Status)) { - Print(L"Failed to open log file %s\n", CmdLineArg); - g_sbsa_log_file_handle = NULL; - } - } - - - // Options with Values - if ((ShellCommandLineGetFlag (ParamPackage, L"-help")) || (ShellCommandLineGetFlag (ParamPackage, L"-h"))){ - HelpMsg(); - return 0; - } - - // - // Initialize global counters - // - g_sbsa_tests_total = 0; - g_sbsa_tests_pass = 0; - g_sbsa_tests_fail = 0; - - Print(L"\n\n SBSA Compliance Suite \n"); - Print(L" Version %d.%d \n", SBSA_ACS_MAJOR_VER, SBSA_ACS_MINOR_VER); - - - Print(L"\n Starting Compliance verification for Level %2d (Print level is %2d)\n\n", g_sbsa_level, g_print_level); - - - Print(L" Creating Platform Information Tables \n"); - Status = createPeInfoTable(); - if (Status) - return Status; - - Status = createGicInfoTable(); - if (Status) - return Status; - - createTimerInfoTable(); - createWatchdogInfoTable(); - createPcieVirtInfoTable(); - createPeripheralInfoTable(); - - val_allocate_shared_mem(); - +EFI_STATUS +createPeInfoTable ( +) +{ + + EFI_STATUS Status; + + UINT64 *PeInfoTable; + +/* allowing room for growth, at present each entry is 16 bytes, so we can support upto 511 PEs with 8192 bytes*/ + Status = gBS->AllocatePool ( EfiBootServicesData, + PE_INFO_TBL_SZ, + (VOID **) &PeInfoTable ); + + if (EFI_ERROR(Status)) + { + Print(L"Allocate Pool failed %x \n", Status); + return Status; + } + + Status = val_pe_create_info_table(PeInfoTable); + + return Status; + +} + +EFI_STATUS +createGicInfoTable ( +) +{ + EFI_STATUS Status; + UINT64 *GicInfoTable; + + Status = gBS->AllocatePool (EfiBootServicesData, + GIC_INFO_TBL_SZ, + (VOID **) &GicInfoTable); + + if (EFI_ERROR(Status)) + { + Print(L"Allocate Pool failed %x \n", Status); + return Status; + } + + Status = val_gic_create_info_table(GicInfoTable); + + return Status; + +} + + +EFI_STATUS +createTimerInfoTable( +) +{ + UINT64 *TimerInfoTable; + EFI_STATUS Status; + + Status = gBS->AllocatePool (EfiBootServicesData, + TIMER_INFO_TBL_SZ, + (VOID **) &TimerInfoTable); + + if (EFI_ERROR(Status)) + { + Print(L"Allocate Pool failed %x \n", Status); + return Status; + } + val_timer_create_info_table(TimerInfoTable); + + return Status; +} + +EFI_STATUS +createWatchdogInfoTable( +) +{ + UINT64 *WdInfoTable; + EFI_STATUS Status; + + Status = gBS->AllocatePool (EfiBootServicesData, + WD_INFO_TBL_SZ, + (VOID **) &WdInfoTable); + + if (EFI_ERROR(Status)) + { + Print(L"Allocate Pool failed %x \n", Status); + return Status; + } + val_wd_create_info_table(WdInfoTable); + + return Status; + +} + + +EFI_STATUS +createPcieVirtInfoTable( +) +{ + UINT64 *PcieInfoTable; + UINT64 *IoVirtInfoTable; + + EFI_STATUS Status; + + Status = gBS->AllocatePool (EfiBootServicesData, + PCIE_INFO_TBL_SZ, + (VOID **) &PcieInfoTable); + + if (EFI_ERROR(Status)) + { + Print(L"Allocate Pool failed %x \n", Status); + return Status; + } + val_pcie_create_info_table(PcieInfoTable); + + Status = gBS->AllocatePool (EfiBootServicesData, + IOVIRT_INFO_TBL_SZ, + (VOID **) &IoVirtInfoTable); + + if (EFI_ERROR(Status)) + { + Print(L"Allocate Pool failed %x \n", Status); + return Status; + } + val_iovirt_create_info_table(IoVirtInfoTable); + + return Status; +} + +EFI_STATUS +createPeripheralInfoTable( +) +{ + UINT64 *PeripheralInfoTable; + UINT64 *MemoryInfoTable; + + EFI_STATUS Status; + + Status = gBS->AllocatePool (EfiBootServicesData, + PERIPHERAL_INFO_TBL_SZ, + (VOID **) &PeripheralInfoTable); + + if (EFI_ERROR(Status)) + { + Print(L"Allocate Pool failed %x \n", Status); + return Status; + } + val_peripheral_create_info_table(PeripheralInfoTable); + + Status = gBS->AllocatePool (EfiBootServicesData, + MEM_INFO_TBL_SZ, + (VOID **) &MemoryInfoTable); + + if (EFI_ERROR(Status)) + { + Print(L"Allocate Pool failed %x \n", Status); + return Status; + } + + val_memory_create_info_table(MemoryInfoTable); + + return Status; +} + +VOID +freeSbsaAvsMem() +{ + + val_pe_free_info_table(); + val_gic_free_info_table(); + val_timer_free_info_table(); + val_wd_free_info_table(); + val_pcie_free_info_table(); + val_iovirt_free_info_table(); + val_peripheral_free_info_table(); + val_free_shared_mem(); +} + +VOID +HelpMsg ( + VOID + ) +{ + Print (L"\nUsage: Sbsa.efi [-v ] | [-l ] | [-f ] | [-s] | [-skip ]\n" + "Options:\n" + "-v Verbosity of the Prints\n" + " 1 shows all prints, 5 shows Errors\n" + "-l Level of compliance to be tested for\n" + " As per SBSA spec, 0 to 3\n" + "-f Name of the log file to record the test results in\n" + "-s Enable the execution of secure tests\n" + "-skip Test(s) to be skipped\n" + " Refer to section 4 of SBSA_ACS_User_Guide\n" + " To skip a module, use Model_ID as mentioned in user guide\n" + " To skip a particular test within a module, use the exact testcase number\n" + ); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-v" , TypeValue}, // -v # Verbosity of the Prints. 1 shows all prints, 5 shows Errors + {L"-l" , TypeValue}, // -l # Level of compliance to be tested for. + {L"-f" , TypeValue}, // -f # Name of the log file to record the test results in. + {L"-s" , TypeFlag}, // -s # Binary Flag to enable the execution of secure tests. + {L"-skip" , TypeValue}, // -skip # test(s) to skip execution + {L"-help" , TypeFlag}, // -help # help : info about commands + {L"-h" , TypeFlag}, // -h # help : info about commands + {NULL , TypeMax} + }; + + +/*** + SBSA Compliance Suite Entry Point. + + Call the Entry points of individual modules. + + @retval 0 The application exited normally. + @retval Other An error occurred. +***/ +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + + LIST_ENTRY *ParamPackage; + CONST CHAR16 *CmdLineArg; + CHAR16 *ProbParam; + UINT32 Status; + UINT32 i,j=0; + VOID *branch_label; + + + // + // Process Command Line arguments + // + Status = ShellInitialize(); + Status = ShellCommandLineParse (ParamList, &ParamPackage, &ProbParam, TRUE); + if (Status) { + Print(L"Shell command line parse error %x\n", Status); + Print(L"Unrecognized option %s passed\n", ProbParam); + HelpMsg(); + return SHELL_INVALID_PARAMETER; + } + + for (i=1 ; i 3) { + g_sbsa_level = G_SBSA_LEVEL; + } + } + + + // Options with Values + CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-v"); + if (CmdLineArg == NULL) { + g_print_level = G_PRINT_LEVEL; + } else { + g_print_level = StrDecimalToUintn(CmdLineArg); + if (g_print_level > 5) { + g_print_level = G_PRINT_LEVEL; + } + } + + // Options with Values + CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-f"); + if (CmdLineArg == NULL) { + g_sbsa_log_file_handle = NULL; + } else { + Status = ShellOpenFileByName(CmdLineArg, &g_sbsa_log_file_handle, + EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE, 0x0); + if(EFI_ERROR(Status)) { + Print(L"Failed to open log file %s\n", CmdLineArg); + g_sbsa_log_file_handle = NULL; + } + } + + + // Options with Values + if ((ShellCommandLineGetFlag (ParamPackage, L"-help")) || (ShellCommandLineGetFlag (ParamPackage, L"-h"))){ + HelpMsg(); + return 0; + } + + // + // Initialize global counters + // + g_sbsa_tests_total = 0; + g_sbsa_tests_pass = 0; + g_sbsa_tests_fail = 0; + + Print(L"\n\n SBSA Architecture Compliance Suite \n"); + Print(L" Version %d.%d \n", SBSA_ACS_MAJOR_VER, SBSA_ACS_MINOR_VER); + + + Print(L"\n Starting tests for level %2d (Print level is %2d)\n\n", g_sbsa_level, g_print_level); + + + Print(L" Creating Platform Information Tables \n"); + Status = createPeInfoTable(); + if (Status) + return Status; + + Status = createGicInfoTable(); + if (Status) + return Status; + + createTimerInfoTable(); + createWatchdogInfoTable(); + createPcieVirtInfoTable(); + createPeripheralInfoTable(); + + val_allocate_shared_mem(); + + // Initialise exception vector, so any unexpected exception gets handled by default SBSA exception handler + branch_label = &&print_test_status; + val_pe_context_save(AA64ReadSp(), (uint64_t)branch_label); + val_pe_initialize_default_exception_handler(val_pe_default_esr); FlushImage(); - if (g_execute_secure == TRUE) { - Print(L"\n *** Starting Secure FW tests *** \n"); - val_secure_execute_tests(g_sbsa_level, val_pe_get_num()); - Print(L"\n *** Secure FW tests Completed *** \n"); - } - - Print(L"\n *** Starting PE tests *** \n"); - Status = val_pe_execute_tests(g_sbsa_level, val_pe_get_num()); - - Print(L"\n *** Starting GIC tests *** \n"); - Status |= val_gic_execute_tests(g_sbsa_level, val_pe_get_num()); - - Print(L"\n *** Starting Timer tests *** \n"); - Status |= val_timer_execute_tests(g_sbsa_level, val_pe_get_num()); - - Print(L"\n *** Starting Watchdog tests *** \n"); - Status |= val_wd_execute_tests(g_sbsa_level, val_pe_get_num()); - - Print(L"\n *** Starting PCIe tests *** \n"); - Status |= val_pcie_execute_tests(g_sbsa_level, val_pe_get_num()); - - Print(L"\n *** Starting IO Virtualization tests *** \n"); - Status |= val_smmu_execute_tests(g_sbsa_level, val_pe_get_num()); - - Print(L"\n *** Starting Power and Wakeup semantic tests *** \n"); - Status |= val_wakeup_execute_tests(g_sbsa_level, val_pe_get_num()); - - Print(L"\n *** Starting Peripheral tests *** \n"); - Status |= val_peripheral_execute_tests(g_sbsa_level, val_pe_get_num()); - - val_print(AVS_PRINT_TEST, "\n ------------------------------------------------------- \n", 0); - val_print(AVS_PRINT_TEST, " Total Tests run = %4d;", g_sbsa_tests_total); - val_print(AVS_PRINT_TEST, " Tests Passed = %4d", g_sbsa_tests_pass); - val_print(AVS_PRINT_TEST, " Tests Failed = %4d\n", g_sbsa_tests_fail); - val_print(AVS_PRINT_TEST, " --------------------------------------------------------- \n", 0); - - freeSbsaAvsMem(); - - if(g_sbsa_log_file_handle) { - ShellCloseFile(&g_sbsa_log_file_handle); - } - - Print(L"\n *** SBSA Compliance Test Complete. Reset the System. *** \n\n"); - return(0); -} + if (g_execute_secure == TRUE) { + Print(L"\n *** Starting Secure FW tests *** \n"); + val_secure_execute_tests(g_sbsa_level, val_pe_get_num()); + Print(L"\n *** Secure FW tests completed *** \n"); + } + + Print(L"\n *** Starting PE tests *** \n"); + Status = val_pe_execute_tests(g_sbsa_level, val_pe_get_num()); + + Print(L"\n *** Starting GIC tests *** \n"); + Status |= val_gic_execute_tests(g_sbsa_level, val_pe_get_num()); + + Print(L"\n *** Starting Timer tests *** \n"); + Status |= val_timer_execute_tests(g_sbsa_level, val_pe_get_num()); + + Print(L"\n *** Starting Watchdog tests *** \n"); + Status |= val_wd_execute_tests(g_sbsa_level, val_pe_get_num()); + + Print(L"\n *** Starting PCIe tests *** \n"); + Status |= val_pcie_execute_tests(g_sbsa_level, val_pe_get_num()); + + Print(L"\n *** Starting Power and Wakeup semantic tests *** \n"); + Status |= val_wakeup_execute_tests(g_sbsa_level, val_pe_get_num()); + + Print(L"\n *** Starting Peripheral tests *** \n"); + Status |= val_peripheral_execute_tests(g_sbsa_level, val_pe_get_num()); + + Print(L"\n *** Starting IO Virtualization tests *** \n"); + Status |= val_smmu_execute_tests(g_sbsa_level, val_pe_get_num()); + +print_test_status: + val_print(AVS_PRINT_TEST, "\n ------------------------------------------------------- \n", 0); + val_print(AVS_PRINT_TEST, " Total Tests run = %4d;", g_sbsa_tests_total); + val_print(AVS_PRINT_TEST, " Tests Passed = %4d", g_sbsa_tests_pass); + val_print(AVS_PRINT_TEST, " Tests Failed = %4d\n", g_sbsa_tests_fail); + val_print(AVS_PRINT_TEST, " --------------------------------------------------------- \n", 0); + + freeSbsaAvsMem(); + + if(g_sbsa_log_file_handle) { + ShellCloseFile(&g_sbsa_log_file_handle); + } + + Print(L"\n *** SBSA tests complete. Reset the system. *** \n\n"); + + val_pe_context_restore(AA64WriteSp(g_stack_pointer)); + + return(0); +} diff --git a/val/SbsaValLib.inf b/val/SbsaValLib.inf index 366a4bfa..9018d6d5 100644 --- a/val/SbsaValLib.inf +++ b/val/SbsaValLib.inf @@ -48,4 +48,4 @@ MdePkg/MdePkg.dec [BuildOptions] - GCC:*_*_*_ASM_FLAGS = -march=armv8.1-a + GCC:*_*_*_ASM_FLAGS = -march=armv8.2-a diff --git a/val/include/pal_interface.h b/val/include/pal_interface.h index 7bc6473f..3f5690ae 100755 --- a/val/include/pal_interface.h +++ b/val/include/pal_interface.h @@ -26,6 +26,7 @@ typedef long long int addr_t; #else typedef CHAR8 char8_t; + typedef CHAR16 char16_t; typedef UINT8 uint8_t; typedef UINT16 uint16_t; typedef UINT32 uint32_t; @@ -66,7 +67,7 @@ typedef struct { void pal_pe_create_info_table(PE_INFO_TABLE *pe_info_table); /** - @brief Structure to Pass SMC arguments. Return data is also filled into + @brief Structure to Pass SMC arguments. Return data is also filled into the same structure. **/ typedef struct { @@ -142,10 +143,9 @@ typedef struct { uint32_t virtual_timer_flag; uint32_t virtual_timer_gsiv; uint32_t el2_virt_timer_gsiv; - uint64_t CntControl_base; - uint64_t CntRead_base; uint32_t num_platform_timer; uint32_t num_watchdog; + uint32_t sys_timer_status; }TIMER_INFO_HDR; #define TIMER_TYPE_SYS_TIMER 0x2001 @@ -238,6 +238,12 @@ typedef enum { IOVIRT_NODE_SMMU_V3 = 0x04 }IOVIRT_NODE_TYPE; +typedef enum { + IOVIRT_FLAG_DEVID_OVERLAP_SHIFT, + IOVIRT_FLAG_STRID_OVERLAP_SHIFT, + IOVIRT_FLAG_SMMU_CTX_INT_SHIFT, +}IOVIRT_FLAG_SHIFT; + typedef struct { uint32_t input_base; uint32_t id_count; @@ -261,6 +267,7 @@ typedef struct { uint32_t type; uint32_t num_data_map; NODE_DATA data; + uint32_t flags; NODE_DATA_MAP data_map[]; }IOVIRT_BLOCK; @@ -275,6 +282,10 @@ typedef struct { IOVIRT_BLOCK blocks[]; }IOVIRT_INFO_TABLE; +void pal_iovirt_create_info_table(IOVIRT_INFO_TABLE *iovirt); +uint32_t pal_iovirt_check_unique_ctx_intid(uint64_t smmu_block); +uint32_t pal_iovirt_unique_rid_strid_map(uint64_t rc_block); + /** @brief SMMU Info Table **/ @@ -287,6 +298,7 @@ void pal_smmu_create_info_table(SMMU_INFO_TABLE *smmu_info_table); uint32_t pal_smmu_check_device_iova(void *port, uint64_t dma_addr); void pal_smmu_device_start_monitor_iova(void *port); void pal_smmu_device_stop_monitor_iova(void *port); +uint32_t pal_smmu_max_pasids(uint64_t smmu_base); /** Peripheral Tests related definitions **/ @@ -298,12 +310,15 @@ typedef struct { uint32_t num_usb; ///< Number of USB Controllers uint32_t num_sata; ///< Number of SATA Controllers uint32_t num_uart; ///< Number of UART Controllers + uint32_t num_all; ///< Number of all PCI Controllers }PERIPHERAL_INFO_HDR; typedef enum { PERIPHERAL_TYPE_USB = 0x2000, PERIPHERAL_TYPE_SATA, - PERIPHERAL_TYPE_UART + PERIPHERAL_TYPE_UART, + PERIPHERAL_TYPE_OTHER, + PERIPHERAL_TYPE_NONE }PER_INFO_TYPE_e; /** @@ -316,6 +331,9 @@ typedef struct { uint64_t base1; ///< Base Address of the controller uint32_t irq; ///< IRQ to install an ISR uint32_t flags; + uint32_t msi; ///< MSI Enabled + uint32_t msix; ///< MSIX Enabled + uint32_t max_pasids; }PERIPHERAL_INFO_BLOCK; /** @@ -328,6 +346,48 @@ typedef struct { void pal_peripheral_create_info_table(PERIPHERAL_INFO_TABLE *per_info_table); +/** + @brief MSI(X) controllers info structure +**/ + +typedef struct { + uint32_t vector_upper_addr; ///< Bus Device Function + uint32_t vector_lower_addr; ///< Base Address of the controller + uint32_t vector_data; ///< Base Address of the controller + uint32_t vector_control; ///< IRQ to install an ISR + uint32_t vector_irq_base; ///< Base IRQ for the vectors in the block +}PERIPHERAL_VECTOR_BLOCK; + +typedef struct PERIPHERAL_VECTOR_LIST_STRUCT +{ + PERIPHERAL_VECTOR_BLOCK vector; + struct PERIPHERAL_VECTOR_LIST_STRUCT *next; +}PERIPHERAL_VECTOR_LIST; + +uint32_t pal_get_msi_vectors (uint32_t bus, uint32_t dev, uint32_t fn, PERIPHERAL_VECTOR_LIST **mvector); + +#define LEGACY_PCI_IRQ_CNT 4 // Legacy PCI IRQ A, B, C. and D +#define MAX_IRQ_CNT 0xFFFF // This value is arbitrary and may have to be adjusted + +typedef struct { + uint32_t irq_list[MAX_IRQ_CNT]; + uint32_t irq_count; +} PERIFERAL_IRQ_LIST; + +typedef struct { + PERIFERAL_IRQ_LIST legacy_irq_map[LEGACY_PCI_IRQ_CNT]; +} PERIPHERAL_IRQ_MAP; + +#define DEVCTL_SNOOP_BIT 11 // Device control register no snoop bit + +uint32_t pal_pcie_get_legacy_irq_map(uint32_t bus, uint32_t dev, uint32_t fn, PERIPHERAL_IRQ_MAP *irq_map); +uint32_t pal_pcie_is_device_behind_smmu(uint32_t bus, uint32_t dev, uint32_t fn); +uint32_t pal_pcie_get_root_port_bdf(uint32_t *seg, uint32_t *bus, uint32_t *dev, uint32_t *func); +uint32_t pal_pcie_get_device_type(uint32_t bus, uint32_t dev, uint32_t fn); +uint32_t pal_pcie_get_snoop_bit(uint32_t bus, uint32_t dev, uint32_t fn); +uint32_t pal_pcie_get_dma_support(uint32_t bus, uint32_t dev, uint32_t fn); +uint32_t pal_pcie_get_dma_coherent(uint32_t bus, uint32_t dev, uint32_t fn); + /** @brief DMA controllers info structure **/ @@ -360,6 +420,7 @@ uint32_t pal_dma_start_to_device(void *dma_source_buf, uint32_t length, void *host, void *target, uint32_t timeout); void pal_dma_scsi_get_dma_addr(void *port, void *dma_addr, uint32_t *dma_len); +int pal_dma_mem_get_attrs(void *buf, uint32_t *attr, uint32_t *sh); /* Memory INFO table */ @@ -394,6 +455,7 @@ void pal_memory_unmap(void *addr); 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_free(void *buffer); @@ -405,6 +467,8 @@ uint32_t pal_mmio_read(uint64_t addr); void pal_mmio_write(uint64_t addr, uint32_t data); void pal_pe_update_elr(void *context, uint64_t offset); +uint64_t pal_pe_get_esr(void *context); +uint64_t pal_pe_get_far(void *context); void pal_pe_data_cache_ops_by_va(uint64_t addr, uint32_t type); #define CLEAN_AND_INVALIDATE 0x1 diff --git a/val/include/sbsa_avs_cfg.h b/val/include/sbsa_avs_cfg.h index 3d53836b..0884db10 100644 --- a/val/include/sbsa_avs_cfg.h +++ b/val/include/sbsa_avs_cfg.h @@ -26,5 +26,8 @@ extern uint32_t g_skip_test_num[MAX_TEST_SKIP_NUM]; extern uint32_t g_sbsa_tests_total; extern uint32_t g_sbsa_tests_pass; extern uint32_t g_sbsa_tests_fail; +extern uint64_t g_stack_pointer; +extern uint64_t g_exception_ret_addr; +extern uint64_t g_ret_addr; #endif diff --git a/val/include/sbsa_avs_common.h b/val/include/sbsa_avs_common.h index 4b2f9457..51cf8802 100755 --- a/val/include/sbsa_avs_common.h +++ b/val/include/sbsa_avs_common.h @@ -29,9 +29,9 @@ #define AVS_TIMER_TEST_NUM_BASE 30 #define AVS_WD_TEST_NUM_BASE 40 #define AVS_PCIE_TEST_NUM_BASE 50 -#define AVS_SMMU_TEST_NUM_BASE 60 #define AVS_WAKEUP_TEST_NUM_BASE 70 #define AVS_PER_TEST_NUM_BASE 80 +#define AVS_SMMU_TEST_NUM_BASE 90 #define AVS_SECURE_TEST_NUM_BASE 900 #define STATE_BIT 28 diff --git a/val/include/sbsa_avs_iovirt.h b/val/include/sbsa_avs_iovirt.h index 56b8a97e..5d1ac3cc 100644 --- a/val/include/sbsa_avs_iovirt.h +++ b/val/include/sbsa_avs_iovirt.h @@ -18,6 +18,9 @@ #define __SBSA_AVS_IOVIRT_H__ uint64_t val_iovirt_get_smmu_info(SMMU_INFO_e type, uint32_t index); +uint32_t val_iovirt_check_unique_ctx_intid(uint32_t smmu_index); +uint32_t val_iovirt_unique_rid_strid_map(uint32_t rc_index); int val_iovirt_get_device_id(uint32_t rid, uint32_t segment, uint32_t *device_id, uint32_t *stream_id); +uint64_t val_iovirt_get_pcie_rc_info(PCIE_RC_INFO_e type, uint32_t index); #endif diff --git a/val/include/sbsa_avs_pcie.h b/val/include/sbsa_avs_pcie.h index 238a6629..a213f361 100644 --- a/val/include/sbsa_avs_pcie.h +++ b/val/include/sbsa_avs_pcie.h @@ -30,6 +30,7 @@ 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 val_get_msi_vectors (uint32_t bdf, PERIPHERAL_VECTOR_LIST **mvector); typedef enum { PCIE_INFO_NUM_ECAM = 1, @@ -43,6 +44,27 @@ typedef enum { uint64_t val_pcie_get_info(PCIE_INFO_e type, uint32_t index); +uint32_t +val_pci_get_legacy_irq_map (uint32_t bdf, PERIPHERAL_IRQ_MAP *irq_map); + +uint32_t +val_pcie_is_device_behind_smmu(uint32_t bdf); + +uint32_t +val_pcie_get_device_type(uint32_t bdf); + +uint32_t +val_pcie_get_root_port_bdf(uint32_t *bdf); + +uint32_t +val_pcie_get_snoop_bit (uint32_t bdf); + +uint32_t +val_pcie_get_dma_support(uint32_t bdf); + +uint32_t +val_pcie_get_dma_coherent(uint32_t bdf); + uint32_t p001_entry(uint32_t num_pe); @@ -64,4 +86,28 @@ p006_entry(uint32_t num_pe); uint32_t p007_entry(uint32_t num_pe); +uint32_t +p008_entry (uint32_t num_pe); + +uint32_t +p009_entry (uint32_t num_pe); + +uint32_t +p010_entry (uint32_t num_pe); + +uint32_t +p011_entry (uint32_t num_pe); + +uint32_t +p012_entry (uint32_t num_pe); + +uint32_t +p013_entry (uint32_t num_pe); + +uint32_t +p014_entry (uint32_t num_pe); + +uint32_t +p015_entry (uint32_t num_pe); + #endif diff --git a/val/include/sbsa_avs_pe.h b/val/include/sbsa_avs_pe.h index 13b9f438..2ac62025 100644 --- a/val/include/sbsa_avs_pe.h +++ b/val/include/sbsa_avs_pe.h @@ -20,7 +20,7 @@ #define MAX_NUM_PE_LEVEL0 0x8 #define MAX_NUM_PE_LEVEL2 (2 << 27) -// +// // AARCH64 processor exception types. // #define EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS 0 @@ -88,7 +88,8 @@ typedef enum { PMSFCR_EL1, PMBPTR_EL1, PMBLIMITR_EL1, - ESR_EL2 + ESR_EL2, + FAR_EL2 }SBSA_AVS_PE_REGS; @@ -216,6 +217,12 @@ void AA64WritePmblimitr(uint64_t write_data); uint64_t AA64ReadEsr2(void); +uint64_t AA64ReadSp(void); + +uint64_t AA64WriteSp(uint64_t write_data); + +uint64_t AA64ReadFar2(void); + void SpeProgramUnderProfiling(uint64_t interval, uint64_t address); void DisableSpe(void); @@ -224,12 +231,20 @@ uint32_t BigEndianCheck(uint64_t *ptr); void val_pe_update_elr(void *context, uint64_t offset); +uint64_t val_pe_get_esr(void *context); + +uint64_t val_pe_get_far(void *context); + void val_pe_spe_program_under_profiling(uint64_t interval, addr_t address); void val_pe_spe_disable(void); uint32_t val_pe_bigend_check(uint64_t *ptr); +void val_pe_context_save(uint64_t sp, uint64_t elr); +void val_pe_initialize_default_exception_handler(void (*esr)(uint64_t, void *)); +void val_pe_context_restore(uint64_t sp); +void val_pe_default_esr(uint64_t interrupt_type, void *context); void val_pe_cache_clean_range(uint64_t start_addr, uint64_t length); uint32_t c001_entry(void); diff --git a/val/include/sbsa_avs_secure.h b/val/include/sbsa_avs_secure.h index 88a9e05c..12fe70ce 100644 --- a/val/include/sbsa_avs_secure.h +++ b/val/include/sbsa_avs_secure.h @@ -25,6 +25,7 @@ typedef enum { SBSA_SECURE_TEST_NSWD_WS1=0x1000, SBSA_SECURE_TEST_SYS_COUNTER, + SBSA_SECURE_TEST_SYS_TIMER_INT, SBSA_SECURE_TEST_WD_WS0, SBSA_SECURE_TEST_UART, SBSA_SECURE_TEST_CNTBASE, diff --git a/val/include/sbsa_avs_smmu.h b/val/include/sbsa_avs_smmu.h index 0285391f..3cfaf7a4 100644 --- a/val/include/sbsa_avs_smmu.h +++ b/val/include/sbsa_avs_smmu.h @@ -35,6 +35,9 @@ val_smmu_read_cfg(uint32_t offset, uint32_t index); uint64_t val_smmu_ops(SMMU_OPS_e ops, uint32_t index, void *param1, void *param2); +uint32_t +val_smmu_max_pasids(uint64_t smmu_base); + uint32_t i001_entry(uint32_t num_pe); uint32_t @@ -43,6 +46,9 @@ uint32_t i003_entry(uint32_t num_pe); uint32_t i004_entry(uint32_t num_pe); - +uint32_t +i005_entry(uint32_t num_pe); +uint32_t +i006_entry(uint32_t num_pe); #endif diff --git a/val/include/sbsa_avs_val.h b/val/include/sbsa_avs_val.h index 23bd7cbb..a1d54107 100755 --- a/val/include/sbsa_avs_val.h +++ b/val/include/sbsa_avs_val.h @@ -26,7 +26,7 @@ typedef struct { uint64_t data0; uint64_t data1; - uint32_t status; + uint32_t status; }VAL_SHARED_MEM_t; uint64_t diff --git a/val/include/val_interface.h b/val/include/val_interface.h index 5e1cb792..e95b0e70 100644 --- a/val/include/val_interface.h +++ b/val/include/val_interface.h @@ -42,6 +42,7 @@ void val_set_test_data(uint32_t index, uint64_t addr, uint64_t test_data); void val_get_test_data(uint32_t index, uint64_t *data0, uint64_t *data1); + /* VAL PE APIs */ uint32_t val_pe_execute_tests(uint32_t level, uint32_t num_pe); uint32_t val_pe_create_info_table(uint64_t *pe_info_table); @@ -95,7 +96,8 @@ typedef enum { TIMER_INFO_IS_PLATFORM_TIMER_SECURE, TIMER_INFO_SYS_CNTL_BASE, TIMER_INFO_SYS_CNT_BASE_N, - TIMER_INFO_SYS_INTID + TIMER_INFO_SYS_INTID, + TIMER_INFO_SYS_TIMER_STATUS }TIMER_INFO_e; #define SBSA_TIMER_FLAG_ALWAYS_ON 0x4 @@ -138,7 +140,8 @@ uint32_t val_pcie_execute_tests(uint32_t level, uint32_t num_pe); typedef enum { SMMU_NUM_CTRL = 1, SMMU_CTRL_BASE, - SMMU_CTRL_ARCH_MAJOR_REV + SMMU_CTRL_ARCH_MAJOR_REV, + SMMU_IOVIRT_BLOCK }SMMU_INFO_e; typedef enum { @@ -154,6 +157,14 @@ typedef enum { SMMU_SET_ATTR, }SMMU_OPS_e; +typedef enum { + NUM_PCIE_RC = 1, + RC_SEGMENT_NUM, + RC_ATS_ATTRIBUTE, + RC_MEM_ATTRIBUTE, + RC_IOVIRT_BLOCK +}PCIE_RC_INFO_e; + void val_iovirt_create_info_table(uint64_t *iovirt_info_table); void val_iovirt_free_info_table(void); uint32_t val_smmu_execute_tests(uint32_t level, uint32_t num_pe); @@ -176,6 +187,7 @@ uint32_t val_dma_start_from_device(void *buffer, uint32_t length, uint32_t index uint32_t val_dma_start_to_device(void *buffer, uint32_t length, uint32_t index); uint32_t val_dma_iommu_check_iova(uint32_t ctrl_index, addr_t dma_addr, addr_t cpu_addr); void val_dma_device_get_dma_addr(uint32_t ctrl_index, void *dma_addr, uint32_t *cpu_len); +int val_dma_mem_get_attrs(void *buf, uint32_t *attr, uint32_t *sh); /* POWER and WAKEUP APIs */ @@ -202,6 +214,7 @@ typedef enum { NUM_USB, NUM_SATA, NUM_UART, + NUM_ALL, USB_BASE0, USB_FLAGS, USB_GSIV, @@ -213,7 +226,11 @@ typedef enum { SATA_BDF, UART_BASE0, UART_GSIV, - UART_FLAGS + UART_FLAGS, + ANY_FLAGS, + ANY_GSIV, + ANY_BDF, + MAX_PASIDS }PERIPHERAL_INFO_e; void val_peripheral_create_info_table(uint64_t *peripheral_info_table); @@ -233,6 +250,13 @@ typedef enum { #define MEM_ATTR_UNCACHED 0x2000 #define MEM_ATTR_CACHED 0x1000 +/* Identify memory type using MAIR attribute, refer to ARM ARM VMSA for details */ + +#define MEM_NORMAL_WB_IN_OUT(attr) (((attr & 0xcc) == 0xcc) || (((attr & 0x7) >= 5) && (((attr >> 4) & 0x7) >= 5))) +#define MEM_NORMAL_NC_IN_OUT(attr) (attr == 0x44) +#define MEM_DEVICE(attr) ((attr & 0xf0) == 0) +#define MEM_SH_INNER(sh) (sh == 0x3) + void val_memory_create_info_table(uint64_t *memory_info_table); void val_memory_free_info_table(void); uint32_t val_memory_execute_tests(uint32_t level, uint32_t num_pe); diff --git a/val/src/AArch64/ArchTimerSupport.S b/val/src/AArch64/ArchTimerSupport.S index 540a501f..e327c58a 100644 --- a/val/src/AArch64/ArchTimerSupport.S +++ b/val/src/AArch64/ArchTimerSupport.S @@ -63,6 +63,7 @@ ASM_PFX(ArmReadCntkCtl): ASM_PFX(ArmWriteCntkCtl): msr cntkctl_el1, x0 // Write to CNTK_CTL (Timer PL1 Control Register) + isb ret @@ -73,6 +74,7 @@ ASM_PFX(ArmReadCntpTval): ASM_PFX(ArmWriteCntpTval): msr cntp_tval_el0, x0 // Write to CNTP_TVAL (PL1 physical timer value register) + isb ret @@ -83,6 +85,7 @@ ASM_PFX(ArmReadCntpCtl): ASM_PFX(ArmWriteCntpCtl): msr cntp_ctl_el0, x0 // Write to CNTP_CTL (PL1 Physical Timer Control Register) + isb ret @@ -93,6 +96,7 @@ ASM_PFX(ArmReadCntvTval): ASM_PFX(ArmWriteCntvTval): msr cntv_tval_el0, x0 // Write to CNTV_TVAL (Virtual Timer Value register) + isb ret @@ -103,6 +107,7 @@ ASM_PFX(ArmReadCntvCtl): ASM_PFX(ArmWriteCntvCtl): msr cntv_ctl_el0, x0 // Write to CNTV_CTL (Virtual Timer Control Register) + isb ret @@ -118,6 +123,7 @@ ASM_PFX(ArmReadCntpCval): ASM_PFX(ArmWriteCntpCval): msr cntp_cval_el0, x0 // Write to CNTP_CTVAL (Physical Timer Compare Value Register) + isb ret @@ -128,6 +134,7 @@ ASM_PFX(ArmReadCntvCval): ASM_PFX(ArmWriteCntvCval): msr cntv_cval_el0, x0 // write to CNTV_CTVAL (Virtual Timer Compare Value Register) + isb ret @@ -138,6 +145,7 @@ ASM_PFX(ArmReadCntvOff): ASM_PFX(ArmWriteCntvOff): msr cntvoff_el2, x0 // Write to CNTVOFF (Virtual Offset register) + isb ret ASM_PFX(ArmReadCnthpCtl): @@ -147,6 +155,7 @@ ASM_PFX(ArmReadCnthpCtl): ASM_PFX(ArmWriteCnthpCtl): msr cnthp_ctl_el2, x0 + isb ret ASM_PFX(ArmReadCnthpTval): @@ -156,6 +165,7 @@ ASM_PFX(ArmReadCnthpTval): ASM_PFX(ArmWriteCnthpTval): msr cnthp_tval_el2, x0 + isb ret ASM_PFX(ArmReadCnthvCtl): @@ -165,6 +175,7 @@ ASM_PFX(ArmReadCnthvCtl): ASM_PFX(ArmWriteCnthvCtl): msr cnthv_ctl_el2, x0 + isb ret ASM_PFX(ArmReadCnthvTval): @@ -174,6 +185,7 @@ ASM_PFX(ArmReadCnthvTval): ASM_PFX(ArmWriteCnthvTval): msr cnthv_tval_el2, x0 + isb ret diff --git a/val/src/AArch64/PeRegSysSupport.S b/val/src/AArch64/PeRegSysSupport.S index 21163fa4..ceac94d7 100644 --- a/val/src/AArch64/PeRegSysSupport.S +++ b/val/src/AArch64/PeRegSysSupport.S @@ -102,6 +102,9 @@ GCC_ASM_EXPORT (AA64WritePmsfcr) GCC_ASM_EXPORT (AA64WritePmbptr) GCC_ASM_EXPORT (AA64WritePmblimitr) GCC_ASM_EXPORT (AA64ReadEsr2) +GCC_ASM_EXPORT (AA64ReadSp) +GCC_ASM_EXPORT (AA64WriteSp) +GCC_ASM_EXPORT (AA64ReadFar2) ASM_PFX(ArmReadMpidr): mrs x0, mpidr_el1 // read EL1 MPIDR @@ -368,3 +371,15 @@ ASM_PFX(AA64ReadEsr2): mrs x0, esr_el2 ret +ASM_PFX(AA64ReadSp): + mov x0, sp + ret + +ASM_PFX(AA64WriteSp): + mov sp, x0 + ret + +ASM_PFX(AA64ReadFar2): + mrs x0, far_el2 + ret + diff --git a/val/src/avs_dma.c b/val/src/avs_dma.c index 83a721e7..d11efb1f 100644 --- a/val/src/avs_dma.c +++ b/val/src/avs_dma.c @@ -90,7 +90,7 @@ val_dma_create_info_table(uint64_t *dma_info_ptr) pal_dma_create_info_table(g_dma_info_table); - val_print(AVS_PRINT_TEST, " DMA_INFO: Number of DMA CTRL in PCIe: %x \n", val_dma_get_info(DMA_NUM_CTRL, 0)); + val_print(AVS_PRINT_TEST, " DMA_INFO: Number of DMA CTRL in PCIe : %x \n", val_dma_get_info(DMA_NUM_CTRL, 0)); } @@ -169,3 +169,9 @@ val_dma_device_get_dma_addr(uint32_t ctrl_index, void *dma_addr, uint32_t *cpu_l pal_dma_scsi_get_dma_addr(ap, dma_addr, cpu_len); } + +int +val_dma_mem_get_attrs(void *buf, uint32_t *attr, uint32_t *sh) +{ + return pal_dma_mem_get_attrs(buf, attr, sh); +} diff --git a/val/src/avs_gic.c b/val/src/avs_gic.c index a1f57f76..6eb66996 100644 --- a/val/src/avs_gic.c +++ b/val/src/avs_gic.c @@ -46,7 +46,7 @@ val_gic_execute_tests(uint32_t level, uint32_t num_pe) if (status != AVS_STATUS_PASS) { val_print(AVS_PRINT_WARN, "\n Skip remaining GIC tests.\n ",0); - return status; + return status; } if (level > 1) { @@ -137,7 +137,7 @@ val_get_gicd_base(void) } /** - @brief This function is a single point of entry to retrieve + @brief This function is a single point of entry to retrieve all GIC related information. 1. Caller - Test Suite 2. Prerequisite - val_gic_create_info_table diff --git a/val/src/avs_gic_support.c b/val/src/avs_gic_support.c index 0d020f42..0a6a3ac2 100644 --- a/val/src/avs_gic_support.c +++ b/val/src/avs_gic_support.c @@ -24,7 +24,7 @@ 1. Caller - Test Suite 2. Prerequisite - None @param reg_id - the system register index for which data is returned - @return the value read from the system register. + @return the value read from the system register. **/ uint64_t val_gic_reg_read(uint32_t reg_id) diff --git a/val/src/avs_iovirt.c b/val/src/avs_iovirt.c index feefbc42..9a183d89 100644 --- a/val/src/avs_iovirt.c +++ b/val/src/avs_iovirt.c @@ -16,9 +16,9 @@ #include "include/sbsa_avs_val.h" #include "include/sbsa_avs_common.h" +#include "include/sbsa_avs_iovirt.h" IOVIRT_INFO_TABLE *g_iovirt_info_table; -void pal_iovirt_create_info_table(IOVIRT_INFO_TABLE *iovirt); /** @brief This API is a single point of entry to retrieve @@ -58,6 +58,8 @@ val_iovirt_get_smmu_info(SMMU_INFO_e type, uint32_t index) return block->data.smmu.arch_major_rev; case SMMU_CTRL_BASE: return block->data.smmu.base; + case SMMU_IOVIRT_BLOCK: + return (uint64_t)block; default: val_print(AVS_PRINT_ERR, "This SMMU info option not supported %d \n", type); return 0; @@ -75,6 +77,75 @@ val_iovirt_get_smmu_info(SMMU_INFO_e type, uint32_t index) return j; } +/** + @brief This API is a single point of entry to retrieve + PCIe Root Complex Node info stored in the iovirt Info table + 1. Caller - Test suite + 2. Prerequisite - val_iovirt_create_info_table + @param type the type of information being requested + @return 64-bit data +**/ +uint64_t +val_iovirt_get_pcie_rc_info(PCIE_RC_INFO_e type, uint32_t index) +{ + uint32_t i,j = 0; + uint64_t mem_attr=0; + IOVIRT_BLOCK *block; + + if (g_iovirt_info_table == NULL) + { + val_print(AVS_PRINT_ERR, "GET_PCIe_RC_INFO: iovirt info table is not created \n", 0); + return 0; + } + + if(type == NUM_PCIE_RC) + return g_iovirt_info_table->num_pci_rcs; + + /* Go through the table return the relevant field value for the SMMU block */ + /* at the index position */ + block = &g_iovirt_info_table->blocks[0]; + for(i = 0; i < g_iovirt_info_table->num_blocks; i++, block=IOVIRT_NEXT_BLOCK(block)) + { + if(block->type == IOVIRT_NODE_PCI_ROOT_COMPLEX) + { + if(j == index) + { + switch(type) + { + case RC_SEGMENT_NUM: + return block->data.segment; + case RC_MEM_ATTRIBUTE: + mem_attr = block->data_map[index].id[1]; + mem_attr = mem_attr << 32; + return (block->data_map[index].id[0] | mem_attr); + case RC_ATS_ATTRIBUTE: + return block->data_map[index].id[2]; + case RC_IOVIRT_BLOCK: + return (uint64_t)block; + default: + val_print(AVS_PRINT_ERR, "This PCIe RC info option not supported %d \n", type); + return 0; + } + } + j++; + } + } + if (index > j-1) + { + val_print(AVS_PRINT_ERR, "GET_PCIe_RC_INFO: Index (%d) is greater than num of PCIe-RC \n", index); + return 0; + } + return j; + +} + +uint32_t +val_iovirt_unique_rid_strid_map(uint32_t rc_index) +{ + uint64_t block = val_iovirt_get_pcie_rc_info(RC_IOVIRT_BLOCK, rc_index); + return pal_iovirt_unique_rid_strid_map(block); +} + /** @brief Calculate the device id and stream id orresponding to the requestor id @param rid Requestor ID @@ -183,9 +254,15 @@ val_iovirt_create_info_table(uint64_t *iovirt_info_table) val_iovirt_get_smmu_info(SMMU_NUM_CTRL, 0)); } +uint32_t +val_iovirt_check_unique_ctx_intid(uint32_t smmu_index) +{ + uint64_t smmu_block = val_iovirt_get_smmu_info(SMMU_IOVIRT_BLOCK, smmu_index); + return pal_iovirt_check_unique_ctx_intid(smmu_block); +} + void val_iovirt_free_info_table() { pal_mem_free((void *)g_iovirt_info_table); } - diff --git a/val/src/avs_pcie.c b/val/src/avs_pcie.c index 941477b8..257d43c7 100644 --- a/val/src/avs_pcie.c +++ b/val/src/avs_pcie.c @@ -62,16 +62,16 @@ val_pcie_read_cfg(uint32_t bdf, uint32_t offset) (bus <= val_pcie_get_info(PCIE_INFO_END_BUS, i)) && (segment == val_pcie_get_info(PCIE_INFO_SEGMENT, i))) { ecam_base = val_pcie_get_info(PCIE_INFO_ECAM, i); - - if (ecam_base == 0) { - val_print(AVS_PRINT_ERR, "\n Read PCIe_CFG: ECAM Base is zero ", 0); - return 0; - } break; } i++; } + if (ecam_base == 0) { + val_print(AVS_PRINT_ERR, "\n Read PCIe_CFG: ECAM Base is zero ", 0); + return 0; + } + /* There are 8 functions / device, 32 devices / Bus and each has a 4KB config space */ cfg_addr = (bus * PCIE_MAX_DEV * PCIE_MAX_FUNC * 4096) + \ (dev * PCIE_MAX_FUNC * 4096) + func; @@ -99,6 +99,7 @@ val_pcie_write_cfg(uint32_t bdf, uint32_t offset, uint32_t data) uint32_t bus = PCIE_EXTRACT_BDF_BUS(bdf); uint32_t dev = PCIE_EXTRACT_BDF_DEV(bdf); uint32_t func = PCIE_EXTRACT_BDF_FUNC(bdf); + uint32_t segment = PCIE_EXTRACT_BDF_SEG(bdf); uint32_t cfg_addr; addr_t ecam_base = 0; uint32_t i = 0; @@ -118,18 +119,19 @@ val_pcie_write_cfg(uint32_t bdf, uint32_t offset, uint32_t data) { if ((bus >= val_pcie_get_info(PCIE_INFO_START_BUS, i)) && - (bus <= val_pcie_get_info(PCIE_INFO_END_BUS, i))) { + (bus <= val_pcie_get_info(PCIE_INFO_END_BUS, i)) && + (segment == val_pcie_get_info(PCIE_INFO_SEGMENT, i))) { ecam_base = val_pcie_get_info(PCIE_INFO_ECAM, i); - - if (ecam_base == 0) { - val_print(AVS_PRINT_ERR, "\n Read PCIe_CFG: ECAM Base is zero ", 0); - return; - } break; } i++; } + if (ecam_base == 0) { + val_print(AVS_PRINT_ERR, "\n Read PCIe_CFG: ECAM Base is zero ", 0); + return; + } + /* There are 8 functions / device, 32 devices / Bus and each has a 4KB config space */ cfg_addr = (bus * PCIE_MAX_DEV * PCIE_MAX_FUNC * 4096) + \ (dev * PCIE_MAX_FUNC * 4096) + func; @@ -174,6 +176,21 @@ val_pcie_execute_tests(uint32_t level, uint32_t num_pe) status |= p002_entry(num_pe); status |= p003_entry(num_pe); +#ifdef TARGET_LINUX + status |= p004_entry(num_pe); + status |= p005_entry(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); +#endif + if (status != AVS_STATUS_PASS) { val_print(AVS_PRINT_ERR, "\n One or more PCIe tests have failed.... \n", status); } @@ -262,3 +279,125 @@ val_pcie_get_info(PCIE_INFO_e type, uint32_t index) return 0; } +/** + @brief This API returns list of MSI(X) vectors for a specified device + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @param mvector - Pointer to MSI vector's list head + + @return number of MSI(X) vectors +**/ +uint32_t +val_get_msi_vectors (uint32_t bdf, PERIPHERAL_VECTOR_LIST **mvector) +{ + return pal_get_msi_vectors (PCIE_EXTRACT_BDF_BUS (bdf), + PCIE_EXTRACT_BDF_DEV (bdf), + PCIE_EXTRACT_BDF_FUNC (bdf), + mvector); +} + +/** + @brief This API returns legacy interrupts routing map + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @param irq_map - Pointer to IRQ map structure + + @return status code +**/ +uint32_t +val_pci_get_legacy_irq_map (uint32_t bdf, PERIPHERAL_IRQ_MAP *irq_map) +{ + return pal_pcie_get_legacy_irq_map (PCIE_EXTRACT_BDF_BUS (bdf), + PCIE_EXTRACT_BDF_DEV (bdf), + PCIE_EXTRACT_BDF_FUNC (bdf), + irq_map); +} +/** + @brief This API checks if device is behind SMMU + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @return 0 -> not present, nonzero -> present +**/ +uint32_t +val_pcie_is_device_behind_smmu(uint32_t bdf) +{ + return pal_pcie_is_device_behind_smmu(PCIE_EXTRACT_BDF_BUS (bdf), + PCIE_EXTRACT_BDF_DEV (bdf), + PCIE_EXTRACT_BDF_FUNC (bdf)); +} +/** + @brief This API returns the bdf of root port + @param bdf - PCIe BUS/Device/Function + + @return status & BDF of root port +**/ +uint32_t +val_pcie_get_root_port_bdf(uint32_t *bdf) +{ + uint32_t bus = PCIE_EXTRACT_BDF_BUS (*bdf); + uint32_t dev = PCIE_EXTRACT_BDF_DEV (*bdf); + uint32_t func = PCIE_EXTRACT_BDF_FUNC (*bdf); + uint32_t seg = PCIE_EXTRACT_BDF_SEG (*bdf); + uint32_t status; + status = pal_pcie_get_root_port_bdf(&seg, &bus, &dev, &func); + if(status) + return status; + + *bdf = PCIE_CREATE_BDF(seg, bus, dev, func); + return 0; +} +/** + @brief This API returns the PCIe device type + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @return 0: Normal PCIe device, 1: PCIe bridge device, + 2: PCIe Host bridge, else: INVALID +**/ +uint32_t +val_pcie_get_device_type(uint32_t bdf) +{ + return pal_pcie_get_device_type(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 + @param bdf - PCIe BUS/Device/Function + @return 0 snoop + 1 no snoop + 2 device error +**/ +uint32_t +val_pcie_get_snoop_bit(uint32_t bdf) +{ + return pal_pcie_get_snoop_bit(PCIE_EXTRACT_BDF_BUS (bdf), PCIE_EXTRACT_BDF_DEV (bdf), PCIE_EXTRACT_BDF_FUNC (bdf)); +} + +/** + @brief This API returns PCIe device DMA support + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @return 0 no support + 1 support + 2 device error +**/ +uint32_t +val_pcie_get_dma_support(uint32_t bdf) +{ + return pal_pcie_get_dma_support(PCIE_EXTRACT_BDF_BUS (bdf), PCIE_EXTRACT_BDF_DEV (bdf), PCIE_EXTRACT_BDF_FUNC (bdf)); +} + +/** + @brief This API returns PCIe device DMA coherency support + 1. Caller - Test Suite + @param bdf - PCIe BUS/Device/Function + @return 0 DMA is not coherent + 1 DMA is coherent + 2 device error +**/ +uint32_t +val_pcie_get_dma_coherent(uint32_t bdf) +{ + return pal_pcie_get_dma_coherent(PCIE_EXTRACT_BDF_BUS (bdf), PCIE_EXTRACT_BDF_DEV (bdf), PCIE_EXTRACT_BDF_FUNC (bdf)); +} + diff --git a/val/src/avs_pe.c b/val/src/avs_pe.c index 4de04c26..af9ef97b 100644 --- a/val/src/avs_pe.c +++ b/val/src/avs_pe.c @@ -90,7 +90,7 @@ val_pe_execute_tests(uint32_t level, uint32_t num_pe) 1. Caller - Test Suite 2. Prerequisite - None @param reg_id - the system register index for which data is returned - @return the value read from the system register. + @return the value read from the system register. **/ uint64_t val_pe_reg_read(uint32_t reg_id) @@ -197,6 +197,8 @@ val_pe_reg_read(uint32_t reg_id) return AA64ReadErr3fr(); case ESR_EL2: return AA64ReadEsr2(); + case FAR_EL2: + return AA64ReadFar2(); default: val_report_status(val_pe_get_index_mpid(val_pe_get_mpid()), RESULT_FAIL(g_sbsa_level, 0, 0x78)); } @@ -265,7 +267,7 @@ val_pe_reg_write(uint32_t reg_id, uint64_t write_data) 1. Caller - Test Suite 2. Prerequisite - None @param None - @return 1 if EL3 is present, 0 if EL3 is not implemented + @return 1 if EL3 is present, 0 if EL3 is not implemented **/ uint8_t val_is_el3_enabled() @@ -281,7 +283,7 @@ val_is_el3_enabled() 1. Caller - Test Suite 2. Prerequisite - None @param None - @return 1 if EL2 is present, 0 if EL2 is not implemented + @return 1 if EL2 is present, 0 if EL2 is not implemented **/ uint8_t val_is_el2_enabled() @@ -323,7 +325,7 @@ val_pe_get_pmu_gsiv(uint32_t index) as argument over which an SPE event is exected to be generated. 1. Caller - Test Suite 2. Prerequisite - None - @param interval - The interval after completion of which SPE event + @param interval - The interval after completion of which SPE event would be generated @param address - Address on which to trigger the SPE @return None. diff --git a/val/src/avs_pe_infra.c b/val/src/avs_pe_infra.c index 0356b9ee..57ccbf6f 100644 --- a/val/src/avs_pe_infra.c +++ b/val/src/avs_pe_infra.c @@ -227,26 +227,6 @@ val_execute_on_pe(uint32_t index, void (*payload)(void), uint64_t test_input) } -/** - @brief Cache clean operation on a defined address range -**/ -void -val_pe_cache_clean_range(uint64_t start_addr, uint64_t length) -{ -#ifndef TARGET_LINUX - uint64_t aligned_addr, end_addr, line_length; - - line_length = 2 << ((val_pe_reg_read(CTR_EL0) >> 16) & 0xf); - aligned_addr = start_addr - (start_addr & (line_length-1)); - end_addr = start_addr + length; - - while(aligned_addr < end_addr){ - val_data_cache_ops_by_va(aligned_addr, CLEAN); - aligned_addr += line_length; - } -#endif -} - /** @brief This API installs the Exception handler pointed by the function pointer to the input exception type. @@ -269,3 +249,71 @@ val_pe_install_esr(uint32_t exception_type, void (*esr)(uint64_t, void *)) return 0; } + + +/** + @brief Save context data (LR, SP and ELR in case of unexpected exception) +**/ +void +val_pe_context_save(uint64_t sp, uint64_t elr) +{ + g_stack_pointer = sp; + g_exception_ret_addr = elr; + g_ret_addr = *(uint64_t *)(g_stack_pointer+8); +} + +/** + @brief Restore context data (LR, SP for return to a known location) +**/ +void +val_pe_context_restore(uint64_t sp) +{ + sp = 0; + *(uint64_t *)(g_stack_pointer+8) = g_ret_addr; +} + +/** + @brief Initialise exception vector with the default handler +**/ +void +val_pe_initialize_default_exception_handler(void (*esr)(uint64_t, void *)) +{ + val_pe_install_esr(EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS, esr); +} + +/** + @brief Default handler which, if installed into exception vector, will be + called in case of unexpected exceptions +**/ +void +val_pe_default_esr(uint64_t interrupt_type, void *context) +{ + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + val_print(AVS_PRINT_WARN, "\n Unexpected exception occured", 0); +#ifndef TARGET_LINUX + val_print(AVS_PRINT_WARN, "\n FAR reported = 0x%x", val_pe_get_far(context)); + val_print(AVS_PRINT_WARN, "\n ESR reported = 0x%x", val_pe_get_esr(context)); +#endif + val_set_status(index, RESULT_FAIL(g_sbsa_level, 0, 01)); + val_pe_update_elr(context, g_exception_ret_addr); +} + +/** + @brief Cache clean operation on a defined address range +**/ +void +val_pe_cache_clean_range(uint64_t start_addr, uint64_t length) +{ +#ifndef TARGET_LINUX + uint64_t aligned_addr, end_addr, line_length; + + line_length = 2 << ((val_pe_reg_read(CTR_EL0) >> 16) & 0xf); + aligned_addr = start_addr - (start_addr & (line_length-1)); + end_addr = start_addr + length; + + while(aligned_addr < end_addr){ + val_data_cache_ops_by_va(aligned_addr, CLEAN); + aligned_addr += line_length; + } +#endif +} diff --git a/val/src/avs_peripherals.c b/val/src/avs_peripherals.c index d7ad0143..c539e56d 100644 --- a/val/src/avs_peripherals.c +++ b/val/src/avs_peripherals.c @@ -65,7 +65,7 @@ val_peripheral_execute_tests(uint32_t level, uint32_t num_pe) @param type - Type of peripheral whose index needs to be returned @param instance - Instance number is '0' based. - @result Index of peripheral matching type and instance + @result Index of peripheral matching type and instance **/ uint32_t @@ -74,7 +74,7 @@ val_peripheral_get_entry_index(uint32_t type, uint32_t instance) uint32_t i = 0; while (g_peripheral_info_table->info[i].type != 0xFF) { - if (g_peripheral_info_table->info[i].type == type) { + if (type == PERIPHERAL_TYPE_NONE || g_peripheral_info_table->info[i].type == type) { if (instance == 0) return i; else @@ -83,7 +83,7 @@ val_peripheral_get_entry_index(uint32_t type, uint32_t instance) } i++; } - return 0xFF; + return 0xFFFF; } /** @@ -93,7 +93,7 @@ val_peripheral_get_entry_index(uint32_t type, uint32_t instance) @param info_type - Type of peripheral whose index needs to be returned @param instance - id (0' based) for which the info has to be returned - @result 64-bit data of peripheral matching type and instance + @result 64-bit data of peripheral matching type and instance **/ uint64_t val_peripheral_get_info(PERIPHERAL_INFO_e info_type, uint32_t instance) @@ -110,75 +110,93 @@ val_peripheral_get_info(PERIPHERAL_INFO_e info_type, uint32_t instance) return g_peripheral_info_table->header.num_sata; case NUM_UART: return g_peripheral_info_table->header.num_uart; + case NUM_ALL: + return g_peripheral_info_table->header.num_all; case USB_BASE0: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_USB, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].base0; case USB_FLAGS: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_USB, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].flags; case USB_GSIV: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_USB, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].irq; case USB_BDF: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_USB, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].bdf; case SATA_BASE0: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_SATA, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].base0; case SATA_BASE1: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_SATA, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].base1; case SATA_FLAGS: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_SATA, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].flags; case SATA_BDF: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_SATA, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].bdf; case SATA_GSIV: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_SATA, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].irq; case UART_BASE0: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_UART, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].base0; case UART_GSIV: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_UART, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].irq; case UART_FLAGS: i = val_peripheral_get_entry_index(PERIPHERAL_TYPE_UART, instance); - if (i != 0xFF) + if (i != 0xFFFF) return g_peripheral_info_table->info[i].flags; + case ANY_FLAGS: + i = val_peripheral_get_entry_index (PERIPHERAL_TYPE_NONE, instance); + if (i != 0xFFFF) + return g_peripheral_info_table->info[i].flags; + case ANY_GSIV: + i = val_peripheral_get_entry_index (PERIPHERAL_TYPE_NONE, instance); + if (i != 0xFFFF) + return g_peripheral_info_table->info[i].irq; + case ANY_BDF: + i = val_peripheral_get_entry_index (PERIPHERAL_TYPE_NONE, instance); + if (i != 0xFFFF) + return g_peripheral_info_table->info[i].bdf; + case MAX_PASIDS: + i = val_peripheral_get_entry_index (PERIPHERAL_TYPE_NONE, instance); + if (i != 0xFFFF) + return g_peripheral_info_table->info[i].max_pasids; default: break; } return 0; } -/* +/* * val_create_peripheralinfo_table: * Caller Application layer. * Prerequisite Memory allocated and passed as argument. - * Description This function will call PAL layer to fill all relevant peripheral + * Description This function will call PAL layer to fill all relevant peripheral * information into the g_peripheral_info_table pointer. */ /** - @brief This API calls PAL layer to fill all relevant peripheral + @brief This API calls PAL layer to fill all relevant peripheral information into the g_peripheral_info_table pointer 1. Caller - Application layer 2. Prerequisite - Memory allocated and passed as argument @param info_table - pointer to a memory where peripheral data is filled - @result None + @result None **/ void diff --git a/val/src/avs_smmu.c b/val/src/avs_smmu.c index de1fe1df..79029081 100644 --- a/val/src/avs_smmu.c +++ b/val/src/avs_smmu.c @@ -78,6 +78,8 @@ val_smmu_execute_tests(uint32_t level, uint32_t num_pe) } status |= i004_entry(num_pe); + status |= i005_entry(num_pe); + status |= i006_entry(num_pe); if (status != AVS_STATUS_PASS) { val_print(AVS_PRINT_ERR, "\n One or more SMMU tests have failed... \n", status); @@ -178,3 +180,9 @@ val_smmu_ops(SMMU_OPS_e ops, uint32_t smmu_index, void *param1, void *param2) return 0; } + +uint32_t +val_smmu_max_pasids(uint64_t smmu_base) +{ + return pal_smmu_max_pasids(smmu_base); +} diff --git a/val/src/avs_status.c b/val/src/avs_status.c index 4a670ff6..7e53a37f 100644 --- a/val/src/avs_status.c +++ b/val/src/avs_status.c @@ -19,7 +19,7 @@ /** - @brief Parse the input status and print the appropriate information to console + @brief Parse the input status and print the appropriate information to console 1. Caller - Application layer 2. Prerequisite - None @param index - index of the PE who is reporting this status. @@ -56,7 +56,7 @@ val_report_status(uint32_t index, uint32_t status) } /** - @brief Record the state and status of the test execution + @brief Record the state and status of the test execution 1. Caller - Test Suite 2. Prerequisite - val_allocate_shared_mem @param index - index of the PE who is reporting this status. @@ -87,7 +87,7 @@ uint32_t val_get_status(uint32_t index) { volatile VAL_SHARED_MEM_t *mem; - + mem = (VAL_SHARED_MEM_t *) pal_mem_get_shared_addr(); mem = mem + index; diff --git a/val/src/avs_test_infra.c b/val/src/avs_test_infra.c index 98a28ae8..7c1a14ee 100644 --- a/val/src/avs_test_infra.c +++ b/val/src/avs_test_infra.c @@ -15,6 +15,7 @@ **/ #include "include/sbsa_avs_val.h" +#include "include/sbsa_avs_pe.h" #include "include/sbsa_avs_common.h" /** @@ -73,7 +74,6 @@ val_print_raw(uint32_t level, char8_t *string, uint64_t data) uint32_t val_mmio_read(addr_t addr) { - val_print(AVS_PRINT_DEBUG, "\n val_mmio_read: addr is %x ", addr); return pal_mmio_read(addr); } @@ -116,10 +116,10 @@ val_initialize_test(uint32_t test_num, char8_t *desc, uint32_t num_pe, uint32_t uint32_t i; uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - val_print(AVS_PRINT_ERR, "%4d : ", test_num); //Always print this val_print(AVS_PRINT_TEST, desc, 0); val_report_status(0, SBSA_AVS_START(level, test_num)); + val_pe_initialize_default_exception_handler(val_pe_default_esr); g_sbsa_tests_total++; @@ -385,3 +385,31 @@ val_pe_update_elr(void *context, uint64_t offset) { pal_pe_update_elr(context, offset); } + +/** + @brief Get ESR from exception context +**/ +uint64_t +val_pe_get_esr(void *context) +{ + return pal_pe_get_esr(context); +} + +/** + @brief Get FAR from exception context +**/ +uint64_t +val_pe_get_far(void *context) +{ + return pal_pe_get_far(context); +} + +/** + @brief Write to an address, meant for debugging purpose +**/ +void +val_debug_brk(uint32_t data) +{ + addr_t address = 0x9000F000; // address = pal_get_debug_address(); + *(addr_t *)address = data; +} diff --git a/val/src/avs_timer.c b/val/src/avs_timer.c index 724193ff..d92a1973 100644 --- a/val/src/avs_timer.c +++ b/val/src/avs_timer.c @@ -57,6 +57,8 @@ val_timer_execute_tests(uint32_t level, uint32_t num_pe) status |= status_sys_timer; + g_timer_info_table->header.sys_timer_status = status_sys_timer; + if (status != 0) val_print(AVS_PRINT_TEST, "\n *** One or more tests have Failed/Skipped.*** \n", 0); else @@ -117,6 +119,8 @@ val_timer_get_info(TIMER_INFO_e info_type, uint64_t instance) return g_timer_info_table->header.virtual_timer_flag; case TIMER_INFO_PHY_EL2_FLAGS: return g_timer_info_table->header.el2_timer_flag; + case TIMER_INFO_SYS_TIMER_STATUS: + return g_timer_info_table->header.sys_timer_status; default: return 0; } @@ -291,7 +295,7 @@ val_timer_create_info_table(uint64_t *timer_info_table) val_timer_set_phy_el1(0); val_print(AVS_PRINT_TEST, " TIMER_INFO: Number of system timers : %4d \n", g_timer_info_table->header.num_platform_timer); - + } /** diff --git a/val/src/avs_wd.c b/val/src/avs_wd.c index 8004d58b..b0bc77b0 100644 --- a/val/src/avs_wd.c +++ b/val/src/avs_wd.c @@ -59,7 +59,7 @@ val_wd_execute_tests(uint32_t level, uint32_t num_pe) } /** - @brief This API is a single point of entry to retrieve + @brief This API is a single point of entry to retrieve information stored in the WD Info table 1. Caller - Test Suite 2. Prerequisite - val_wd_create_info_table @@ -109,7 +109,7 @@ val_wd_create_info_table(uint64_t *wd_info_table) g_wd_info_table = (WD_INFO_TABLE *)wd_info_table; pal_wd_create_info_table(g_wd_info_table); - + val_print(AVS_PRINT_TEST, " WATCHDOG_INFO: Number of Watchdogs : %4d \n", val_wd_get_info(0, WD_INFO_COUNT)); }