diff --git a/README.md b/README.md index 376f216e..eff5b470 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ A few tests are executed by running the SBSA ACS Linux application which in turn ## Release details - - Code Quality: REL v2.2 + - Code Quality: REL v2.3 - The tests are written for version 5.0 of the SBSA specification. - The compliance suite is not a substitute for design verification. - To review the SBSA ACS logs, ARM licensees can contact ARM directly through their partner managers. diff --git a/changelog.txt b/changelog.txt index 0f5d4ecb..c1913c77 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +v19.09_REL2.3 +* SBSA: PCI Express Exerciser Enhancements +* SBSA: EL1 Exception Level Support for QEMU Default Configurations + v19.04_REL2.2 * SBSA: Support for baremetal templates with documentation. diff --git a/linux_app/sbsa-acs-app/include/sbsa_app.h b/linux_app/sbsa-acs-app/include/sbsa_app.h index 23ed6d71..4394d324 100644 --- a/linux_app/sbsa-acs-app/include/sbsa_app.h +++ b/linux_app/sbsa-acs-app/include/sbsa_app.h @@ -21,7 +21,7 @@ #define SBSA_APP_VERSION_MAJOR 2 -#define SBSA_APP_VERSION_MINOR 2 +#define SBSA_APP_VERSION_MINOR 3 #include "sbsa_drv_intf.h" diff --git a/platform/pal_uefi/SbsaPalLib.inf b/platform/pal_uefi/SbsaPalLib.inf index a09cbee0..337ecb9c 100644 --- a/platform/pal_uefi/SbsaPalLib.inf +++ b/platform/pal_uefi/SbsaPalLib.inf @@ -1,5 +1,5 @@ ## @file -# Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. +# Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. # SPDX-License-Identifier : Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,6 +37,8 @@ src/pal_iovirt.c src/pal_pcie_enumeration.c src/pal_peripherals.c + src/pal_exerciser.c + src/pal_smmu.c [Packages] MdePkg/MdePkg.dec @@ -62,6 +64,7 @@ gHardwareInterruptProtocolGuid ## CONSUMES gEfiCpuArchProtocolGuid ## CONSUMES gEfiPciIoProtocolGuid ## CONSUMES + gHardwareInterrupt2ProtocolGuid ## CONSUMES [Guids] gEfiAcpi20TableGuid diff --git a/platform/pal_uefi/include/pal_exerciser.h b/platform/pal_uefi/include/pal_exerciser.h new file mode 100644 index 00000000..ed8b5a15 --- /dev/null +++ b/platform/pal_uefi/include/pal_exerciser.h @@ -0,0 +1,132 @@ +/** @file + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +**/ + +#ifndef __PAL_EXERCISER_H__ +#define __PAL_EXERCISER_H__ + +#define EXERCISER_CLASSCODE 0x010203 +#define MAX_ARRAY_SIZE 32 +#define TEST_REG_COUNT 10 +#define TEST_DDR_REGION_CNT 16 + +typedef struct { + UINT64 buf[MAX_ARRAY_SIZE]; +} EXERCISER_INFO_BLOCK; + +typedef struct { + UINT32 num_exerciser_cards; + EXERCISER_INFO_BLOCK info[]; //Array of information blocks - per stimulus generation controller +} EXERCISER_INFO_TABLE; + +typedef enum { + EXERCISER_NUM_CARDS = 0x1 +} EXERCISER_INFO_TYPE; + +typedef enum { + EDMA_NO_SUPPORT = 0x0, + EDMA_COHERENT = 0x1, + EDMA_NOT_COHERENT = 0x2, + EDMA_FROM_DEVICE = 0x3, + EDMA_TO_DEVICE = 0x4 +} EXERCISER_DMA_ATTR; + +typedef enum { + SNOOP_ATTRIBUTES = 0x1, + LEGACY_IRQ = 0x2, + MSIX_ATTRIBUTES = 0x3, + DMA_ATTRIBUTES = 0x4, + P2P_ATTRIBUTES = 0x5, + PASID_ATTRIBUTES = 0x6 +} EXERCISER_PARAM_TYPE; + +typedef enum { + EXERCISER_RESET = 0x1, + EXERCISER_ON = 0x2, + EXERCISER_OFF = 0x3, + EXERCISER_ERROR = 0x4 +} EXERCISER_STATE; + +typedef enum { + START_DMA = 0x1, + GENERATE_MSI = 0x2, + GENERATE_L_INTR = 0x3, //Legacy interrupt + MEM_READ = 0x4, + MEM_WRITE = 0x5, + CLEAR_INTR = 0x6, + PASID_TLP_START = 0x7, + PASID_TLP_STOP = 0x8, + NO_SNOOP_CLEAR_TLP_START = 0x9, + NO_SNOOP_CLEAR_TLP_STOP = 0xa +} EXERCISER_OPS; + +typedef enum { + ACCESS_TYPE_RD = 0x0, + ACCESS_TYPE_RW = 0x1 +} ECAM_REG_ATTRIBUTE; + +struct ecam_reg_data { + UINT32 offset; //Offset into 4096 bytes ecam config reg space + UINT32 attribute; + UINT32 value; +}; + +struct exerciser_data_cfg_space { + struct ecam_reg_data reg[TEST_REG_COUNT]; +}; + +typedef enum { + DEVICE_nGnRnE = 0x0, + DEVICE_nGnRE = 0x1, + DEVICE_nGRE = 0x2, + DEVICE_GRE = 0x3 +} ARM_DEVICE_MEM; + +typedef enum { + NORMAL_NC = 0x4, + NORMAL_WT = 0x5 +} ARM_NORMAL_MEM; + +typedef enum { + MMIO_PREFETCHABLE = 0x0, + MMIO_NON_PREFETCHABLE = 0x1 +} BAR_MEM_TYPE; + +struct exerciser_data_bar_space { + void *base_addr; + BAR_MEM_TYPE type; +}; + +typedef union exerciser_data { + struct exerciser_data_cfg_space cfg_space; + struct exerciser_data_bar_space bar_space; +} exerciser_data_t; + +typedef enum { + EXERCISER_DATA_CFG_SPACE = 0x1, + EXERCISER_DATA_BAR0_SPACE = 0x2, +} EXERCISER_DATA_TYPE; + +VOID pal_exerciser_create_info_table (EXERCISER_INFO_TABLE *ExerciserInfoTable); +UINT32 pal_exerciser_get_info(EXERCISER_INFO_TYPE Type, UINT32 Instance); +UINT32 pal_exerciser_set_param(EXERCISER_PARAM_TYPE Type, UINT64 Value1, UINT64 Value2, UINT32 Instance); +UINT32 pal_exerciser_get_param(EXERCISER_PARAM_TYPE Type, UINT64 *Value1, UINT64 *Value2, UINT32 Instance); +UINT32 pal_exerciser_set_state(EXERCISER_STATE State, UINT64 *Value, UINT32 Instance); +UINT32 pal_exerciser_get_state(EXERCISER_STATE State, UINT64 *Value, UINT32 Instance); +UINT32 pal_exerciser_ops(EXERCISER_OPS Ops, UINT64 Param, UINT32 Instance); +UINT32 pal_exerciser_get_data(EXERCISER_DATA_TYPE Type, exerciser_data_t *Data, UINT32 Instance); + +#endif diff --git a/platform/pal_uefi/include/pal_uefi.h b/platform/pal_uefi/include/pal_uefi.h index 6e8b0f3b..86acd219 100644 --- a/platform/pal_uefi/include/pal_uefi.h +++ b/platform/pal_uefi/include/pal_uefi.h @@ -82,6 +82,14 @@ typedef enum { ENTRY_TYPE_GICITS }GIC_INFO_TYPE_e; +/* Interrupt Trigger Type */ +typedef enum { + INTR_TRIGGER_INFO_LEVEL_LOW, + INTR_TRIGGER_INFO_LEVEL_HIGH, + INTR_TRIGGER_INFO_EDGE_FALLING, + INTR_TRIGGER_INFO_EDGE_RISING +}INTR_TRIGGER_INFO_TYPE_e; + /** @brief structure instance for GIC entry **/ @@ -176,6 +184,9 @@ typedef struct { PCIE_INFO_BLOCK block[]; }PCIE_INFO_TABLE; +VOID *pal_pci_bdf_to_dev(UINT32 bdf); +VOID pal_pci_read_config_byte(UINT32 bdf, UINT8 offset, UINT8 *data); + /** @brief Instance of SMMU INFO block **/ @@ -188,6 +199,7 @@ typedef struct { UINT32 segment; UINT32 ats_attr; UINT32 cca; //Cache Coherency Attribute + UINT64 smmu_base; }IOVIRT_RC_INFO_BLOCK; typedef struct { @@ -300,6 +312,42 @@ typedef struct { PERIPHERAL_INFO_BLOCK info[]; ///< Array of Information blocks - instantiated for each peripheral }PERIPHERAL_INFO_TABLE; +/** + @brief MSI(X) controllers info structure +**/ + +typedef struct { + UINT32 vector_upper_addr; ///< Bus Device Function + UINT32 vector_lower_addr; ///< Base Address of the controller + UINT32 vector_data; ///< Base Address of the controller + UINT32 vector_control; ///< IRQ to install an ISR + UINT32 vector_irq_base; ///< Base IRQ for the vectors in the block + UINT32 vector_n_irqs; ///< Number of irq vectors in the block + UINT32 vector_mapped_irq_base; ///< Mapped IRQ number base for this MSI +}PERIPHERAL_VECTOR_BLOCK; + +typedef struct PERIPHERAL_VECTOR_LIST_STRUCT +{ + PERIPHERAL_VECTOR_BLOCK vector; + struct PERIPHERAL_VECTOR_LIST_STRUCT *next; +}PERIPHERAL_VECTOR_LIST; + +UINT32 pal_get_msi_vectors (UINT32 seg, UINT32 bus, UINT32 dev, UINT32 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 irq_list[MAX_IRQ_CNT]; + UINT32 irq_count; +} PERIFERAL_IRQ_LIST; + +typedef struct { + PERIFERAL_IRQ_LIST legacy_irq_map[LEGACY_PCI_IRQ_CNT]; +} PERIPHERAL_IRQ_MAP; + +UINT32 pal_pcie_get_root_port_bdf(UINT32 *seg, UINT32 *bus, UINT32 *dev, UINT32 *func); + /* Memory INFO table */ typedef enum { MEMORY_TYPE_DEVICE = 0x1000, @@ -328,4 +376,9 @@ typedef struct { VOID pal_memory_create_info_table(MEMORY_INFO_TABLE *memoryInfoTable); +VOID *pal_mem_alloc(UINT32 size); +VOID *pal_mem_alloc_coherent(UINT32 bdf, UINT32 size, VOID *pa); +VOID pal_mem_free_coherent(UINT32 bdf, UINT32 size, VOID *va, VOID *pa); +VOID *pal_mem_virt_to_phys(VOID *va); + #endif diff --git a/platform/pal_uefi/include/sbsa_pcie_enum.h b/platform/pal_uefi/include/sbsa_pcie_enum.h index b3fb8685..b92162b4 100644 --- a/platform/pal_uefi/include/sbsa_pcie_enum.h +++ b/platform/pal_uefi/include/sbsa_pcie_enum.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,4 +36,10 @@ palPcieGetBdf(UINT32 class_code, UINT32 start_busdev); UINT64 palPcieGetBase(UINT32 bdf, UINT32 bar_index); +VOID * +pal_pci_bdf_to_dev(UINT32 bdf); + +VOID +pal_pci_read_config_byte(UINT32 bdf, UINT8 offset, UINT8 *val); + #endif diff --git a/platform/pal_uefi/src/pal_exerciser.c b/platform/pal_uefi/src/pal_exerciser.c new file mode 100644 index 00000000..3411ccf1 --- /dev/null +++ b/platform/pal_uefi/src/pal_exerciser.c @@ -0,0 +1,155 @@ +/** @file + * Copyright (c) 2018-2019, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. +**/ + + +/* This is a place-holder file. Porting to match implementation is required */ + +#include "include/pal_exerciser.h" + +/** + @brief This API popultaes information from all the PCIe stimulus generation IP available + in the system into exerciser_info_table structure + @param ExerciserInfoTable - Table pointer to be filled by this API + @return ExerciserInfoTable - Contains info to communicate with stimulus generation hardware +**/ +VOID +pal_exerciser_create_info_table ( + EXERCISER_INFO_TABLE *ExerciserInfoTable + ) +{ + return; +} + +/** + @brief This API returns the requested information about the PCIe stimulus hardware + @param Type - Information type required from the stimulus hadrware + @param Instance - Stimulus hadrware instance number + @return Value - Information value for input type +**/ +UINT32 +pal_exerciser_get_info ( + EXERCISER_INFO_TYPE Type, + UINT32 Instance + ) +{ + return 0; +} + +/** + @brief This API writes the configuration parameters of the PCIe stimulus generation hardware + @param Type - Parameter type that needs to be set in the stimulus hadrware + @param Value1 - Parameter 1 that needs to be set + @param Value2 - Parameter 2 that needs to be set + @param Instance - Stimulus hardware instance number + @return Status - SUCCESS if the input paramter type is successfully written +**/ +UINT32 pal_exerciser_set_param ( + EXERCISER_PARAM_TYPE Type, + UINT64 Value1, + UINT64 Value2, + UINT32 Instance + ) +{ + return 0; +} + +/** + @brief This API reads the configuration parameters of the PCIe stimulus generation hardware + @param Type - Parameter type that needs to be read from the stimulus hadrware + @param Value1 - Parameter 1 that is read from hardware + @param Value2 - Parameter 2 that is read from hardware + @param Instance - Stimulus hardware instance number + @return Status - SUCCESS if the requested paramter type is successfully read +**/ +UINT32 +pal_exerciser_get_param ( + EXERCISER_PARAM_TYPE Type, + UINT64 *Value1, + UINT64 *Value2, + UINT32 Instance + ) +{ + return 0; +} + +/** + @brief This API sets the state of the PCIe stimulus generation hardware + @param State - State that needs to be set for the stimulus hadrware + @param Value - Additional information associated with the state + @param Instance - Stimulus hardware instance number + @return Status - SUCCESS if the input state is successfully written to hardware +**/ +UINT32 +pal_exerciser_set_state ( + EXERCISER_STATE State, + UINT64 *Value, + UINT32 Instance + ) +{ + return 0; +} + +/** + @brief This API obtains the state of the PCIe stimulus generation hardware + @param State - State that is read from the stimulus hadrware + @param Value - Additional information associated with the state + @param Instance - Stimulus hardware instance number + @return Status - SUCCESS if the state is successfully read from hardware +**/ +UINT32 +pal_exerciser_get_state ( + EXERCISER_STATE State, + UINT64 *Value, + UINT32 Instance + ) +{ + return 0; +} + +/** + @brief This API performs the input operation using the PCIe stimulus generation hardware + @param Ops - Operation thta needs to be performed with the stimulus hadrware + @param Value - Additional information to perform the operation + @param Instance - Stimulus hardware instance number + @return Status - SUCCESS if the operation is successfully performed using the hardware +**/ +UINT32 +pal_exerciser_ops ( + EXERCISER_OPS Ops, + UINT64 Param, + UINT32 Instance + ) +{ + return 0; +} + +/** + @brief This API returns test specific data from the PCIe stimulus generation hardware + @param type - data type for which the data needs to be returned + @param data - test specific data to be be filled by pal layer + @param instance - Stimulus hardware instance number + @return status - SUCCESS if the requested data is successfully filled +**/ +UINT32 +pal_exerciser_get_data ( + EXERCISER_DATA_TYPE Type, + exerciser_data_t *Data, + UINT32 Instance + ) +{ + return 0; +} diff --git a/platform/pal_uefi/src/pal_gic.c b/platform/pal_uefi/src/pal_gic.c index 51a9da33..a8337b9a 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-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,12 +23,14 @@ #include "Include/IndustryStandard/Acpi61.h" #include #include +#include #include "include/pal_uefi.h" static EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *gMadtHdr; EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL; +EFI_HARDWARE_INTERRUPT2_PROTOCOL *gInterrupt2 = NULL; UINT64 @@ -180,3 +182,59 @@ pal_gic_end_of_interrupt(UINT32 int_id) return 0; } +/** + @brief Set Trigger type Edge/Level + + @param int_id Interrupt ID which needs to be enabled and service routine installed for + @param trigger_type Interrupt Trigger Type Edge/Trigger + + @return Status of the operation +**/ +UINT32 +pal_gic_set_intr_trigger(UINT32 int_id, INTR_TRIGGER_INFO_TYPE_e trigger_type) +{ + + EFI_STATUS Status; + + /* Find the interrupt protocol. */ + Status = gBS->LocateProtocol (&gHardwareInterrupt2ProtocolGuid, NULL, (VOID **)&gInterrupt2); + if (EFI_ERROR(Status)) { + return 0xFFFFFFFF; + } + + Status = gInterrupt2->SetTriggerType ( + gInterrupt2, + int_id, + trigger_type + ); + + if (EFI_ERROR(Status)) + return 0xFFFFFFFF; + + return 0; +} + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +UINT32 +pal_gic_request_irq ( + UINT32 IrqNum, + UINT32 MappedIrqNum, + VOID *Isr + ) +{ + return 0; +} + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +VOID +pal_gic_free_irq ( + UINT32 IrqNum, + UINT32 MappedIrqNum + ) +{ + +} diff --git a/platform/pal_uefi/src/pal_iovirt.c b/platform/pal_uefi/src/pal_iovirt.c index 25548aea..3efde163 100644 --- a/platform/pal_uefi/src/pal_iovirt.c +++ b/platform/pal_uefi/src/pal_iovirt.c @@ -220,6 +220,8 @@ iort_add_block(IORT_TABLE *iort, IORT_NODE *iort_node, IOVIRT_INFO_TABLE *IoVirt { UINT32 offset, *count; IOVIRT_BLOCK *next_block; + IOVIRT_BLOCK *temp_block; + NODE_DATA *temp_data; NODE_DATA_MAP *data_map = &((*block)->data_map[0]); NODE_DATA *data = &((*block)->data); VOID *node_data = &(iort_node->node_data[0]); @@ -316,6 +318,20 @@ iort_add_block(IORT_TABLE *iort, IORT_NODE *iort_node, IOVIRT_INFO_TABLE *IoVirt (*data_map).map.output_ref = offset; data_map++; map++; + + /* Derive the smmu base to which this RC node is connected. + * If the RC is behind a SMMU, save SMMU base to RC structure. + * Else save NULL pointer. + */ + temp_block = ADD_PTR(IOVIRT_BLOCK, IoVirtTable, offset); + (*data).rc.smmu_base = 0; + if (((*block)->type == IOVIRT_NODE_PCI_ROOT_COMPLEX) && + ((temp_block->type == IOVIRT_NODE_SMMU) || + (temp_block->type == IOVIRT_NODE_SMMU_V3))) { + temp_data = &(temp_block->data); + (*data).rc.smmu_base = (*temp_data).smmu.base; + } + } } /* So we successfully added a new block. Calculate its offset */ @@ -367,6 +383,7 @@ pal_iovirt_create_info_table(IOVIRT_INFO_TABLE *IoVirtTable) /* Point to the first IORT node */ iort_node = ADD_PTR(IORT_NODE, iort, iort->node_offset); iort_end = ADD_PTR(IORT_NODE, iort, iort->header.Length); + /* Create iovirt block for each IORT node*/ for (i = 0; i < iort->node_count; i++) { if (iort_node >= iort_end) { @@ -414,3 +431,30 @@ pal_iovirt_unique_rid_strid_map(UINT64 rc_block) return 0; return 1; } + +UINT64 +pal_iovirt_get_rc_smmu_base ( + IOVIRT_INFO_TABLE *Iovirt, + UINT32 RcSegmentNum + ) +{ + UINT32 i; + IOVIRT_BLOCK *block; + + /* As per IORT acpi table, it is assumed that + * PCI segment numbers have a one-to-one mapping + * with root complexes. Each segment number can + * represent only one root complex. + */ + block = &(Iovirt->blocks[0]); + for(i = 0; i < Iovirt->num_blocks; i++, block = IOVIRT_NEXT_BLOCK(block)) { + if (block->data.rc.segment == RcSegmentNum) { + return block->data.rc.smmu_base; + } + } + + /* The Root Complex represented by rc_seg_num + * is not behind any SMMU. Return NULL pointer + */ + return 0; +} diff --git a/platform/pal_uefi/src/pal_misc.c b/platform/pal_uefi/src/pal_misc.c index ea4e32b6..5e414e82 100644 --- a/platform/pal_uefi/src/pal_misc.c +++ b/platform/pal_uefi/src/pal_misc.c @@ -19,6 +19,8 @@ #include #include #include +#include + #include "include/pal_uefi.h" @@ -146,6 +148,42 @@ pal_mem_free(VOID *Buffer) gBS->FreePool (Buffer); } +/** + @brief Compare the contents of the src and dest buffers + @param Src - source buffer to be compared + @param Dest - destination buffer to be compared + @param Len - Length of the comparison to be performed + + @return Zero if the buffer contecnts are same, else Nonzero +**/ +UINT32 +pal_mem_compare ( + VOID *Src, + VOID *Dest, + UINT32 Len + ) +{ + return CompareMem (Src, Dest, Len); +} + +/** + @brie a buffer with a known specified input value + @param Buf - Pointer to the buffer to fill + @param Size - Number of bytes in buffer to fill + @param Value - Value to fill buffer with + + @return None +**/ +VOID +pal_mem_set ( + VOID *Buf, + UINT32 Size, + UINT8 Value + ) +{ + SetMem(Buf, Size, Value); +} + /** @brief Allocate memory which is to be used to share data across PEs @@ -202,3 +240,52 @@ pal_mem_free_shared() { gBS->FreePool ((VOID *)gSharedMemory); } + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +VOID * +pal_mem_alloc ( + UINT32 Size + ) +{ + return NULL; +} + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +VOID * +pal_mem_alloc_coherent ( + UINT32 Bdf, + UINT32 Size, + VOID *Pa + ) +{ + return NULL; +} + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +VOID +pal_mem_free_coherent ( + UINT32 Bdf, + UINT32 Size, + VOID *Va, + VOID *Pa + ) +{ + +} + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +VOID * +pal_mem_virt_to_phys ( + VOID *Va + ) +{ + return NULL; +} diff --git a/platform/pal_uefi/src/pal_pcie.c b/platform/pal_uefi/src/pal_pcie.c index 1706ed90..15da8923 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-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -166,3 +166,47 @@ pal_pcie_read_cfg(UINT32 Bdf, UINT32 offset, UINT32 *data) } return PCIE_READ_ERR; } + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +UINT32 +pal_get_msi_vectors ( + UINT32 Seg, + UINT32 Bus, + UINT32 Dev, + UINT32 Fn, + PERIPHERAL_VECTOR_LIST **MVector + ) +{ + return 0; +} + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +UINT32 +pal_pcie_get_legacy_irq_map ( + UINT32 Seg, + UINT32 Bus, + UINT32 Dev, + UINT32 Fn, + PERIPHERAL_IRQ_MAP *IrqMap + ) +{ + return 0; +} + +/* Place holder function. Need to be + * implemented if needed in later releases + */ +UINT32 +pal_pcie_get_root_port_bdf ( + UINT32 *Seg, + UINT32 *Bus, + UINT32 *Dev, + UINT32 *Func + ) +{ + return 0; +} diff --git a/platform/pal_uefi/src/pal_pcie_enumeration.c b/platform/pal_uefi/src/pal_pcie_enumeration.c index 0e34637f..c69d25dd 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-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -54,7 +54,6 @@ incrementBusDev(UINT32 StartBdf) return PCIE_CREATE_BDF(Seg, Bus, Dev, 0); } - /** @brief Returns the Bus, Dev, Function (in the form seg<<24 | bus<<16 | Dev <<8 | func) for a matching class code. @@ -124,6 +123,26 @@ palPcieGetBdf(UINT32 ClassCode, UINT32 StartBdf) return 0; } +/** + @brief Returns the Bus, Dev, Function (in the form seg<<24 | bus<<16 | Dev <<8 | func) + for a matching class code. + + @param ClassCode - is a 32bit value of format ClassCode << 16 | sub_class_code + @param StartBdf - is 0 : start enumeration from Host bridge + is not 0 : start enumeration from the input segment, bus, dev + this is needed as multiple controllers with same class code are + potentially present in a system. + @return the BDF of the device matching the class code +**/ +UINT32 +pal_pcie_get_bdf_wrapper ( + UINT32 ClassCode, + UINT32 StartBdf + ) +{ + + return palPcieGetBdf(ClassCode, StartBdf); +} /** @brief This API returns the Base Address Register value for a given BDF and index @@ -176,3 +195,20 @@ palPcieGetBase(UINT32 bdf, UINT32 bar_index) return 0; } +VOID * +pal_pci_bdf_to_dev ( + UINT32 Bdf + ) +{ + return NULL; +} + +VOID +pal_pci_read_config_byte ( + UINT32 Bdf, + UINT8 Offset, + UINT8 *Val + ) +{ + +} diff --git a/platform/pal_uefi/src/pal_smmu.c b/platform/pal_uefi/src/pal_smmu.c new file mode 100644 index 00000000..7f55a8b0 --- /dev/null +++ b/platform/pal_uefi/src/pal_smmu.c @@ -0,0 +1,62 @@ +/** @file + * Copyright (c) 2019, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. +**/ + +/* This is a place-holder file. Need to be implemented if needed in later releases */ + +/** + @brief This API prepares the smmu page tables to support input PasId + @param SmmuBase - Physical addr of the SMMU for which PasId support is needed + @param PasId - Process Address Space identifier + @return zero for success, one for failure +**/ +UINT32 +pal_smmu_create_pasid_entry ( + UINT64 SmmuBase, + UINT32 PasId + ) +{ + return 1; +} + +/** + @brief This API globally disables the SMMU based on input base address + @param SmmuBase - Physical addr of the SMMU that needs to be globally disabled + @return zero for success, one for failure +**/ + +UINT32 +pal_smmu_disable ( + UINT64 SmmuBase + ) +{ + return 0; +} + +/** + @brief This API converts physical address to IO virtual address + @param SmmuBase - Physical addr of the SMMU for pa to iova conversion + @param Pa - Physical address to use in conversion + @return zero for success, one for failure +*/ +UINT64 +pal_smmu_pa2iova ( + UINT64 SmmuBase, + UINT64 Pa + ) +{ + return 0; +} diff --git a/platform/pal_uefi/src/pal_timer_wd.c b/platform/pal_uefi/src/pal_timer_wd.c index b1a64031..2986f930 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-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -110,7 +110,8 @@ pal_timer_create_info_table(TIMER_INFO_TABLE *TimerTable) 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++) { - sbsa_print(AVS_PRINT_INFO, L"Found timer entry \n"); + sbsa_print(AVS_PRINT_INFO, L"Found timer entry \n"); + GtEntry->frame_num[i] = GtBlockTimer->GTFrameNumber; GtEntry->GtCntBase[i] = GtBlockTimer->CntBaseX; GtEntry->GtCntEl0Base[i] = GtBlockTimer->CntEL0BaseX; GtEntry->gsiv[i] = GtBlockTimer->GTxPhysicalTimerGSIV; diff --git a/prebuilt_images/v19.09_REL2.3/Sbsa.efi b/prebuilt_images/v19.09_REL2.3/Sbsa.efi new file mode 100644 index 00000000..1d44c480 Binary files /dev/null and b/prebuilt_images/v19.09_REL2.3/Sbsa.efi differ diff --git a/test_pool/exerciser/test_e003.c b/test_pool/exerciser/test_e003.c index 5e2817d8..97364c76 100644 --- a/test_pool/exerciser/test_e003.c +++ b/test_pool/exerciser/test_e003.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,18 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ + #include "val/include/sbsa_avs_val.h" #include "val/include/val_interface.h" -#include "val/include/sbsa_avs_dma.h" #include "val/include/sbsa_avs_smmu.h" #include "val/include/sbsa_avs_memory.h" +#include "val/include/sbsa_avs_pcie_enumeration.h" +#include "val/include/sbsa_avs_pcie.h" #include "val/include/sbsa_avs_exerciser.h" #define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 3) #define TEST_DESC "PCIe Address translation check " -#define TEST_DATA_BLK_SIZE 512 +#define TEST_DATA_BLK_SIZE (16*1024) #define TEST_DATA 0xDE static @@ -39,6 +41,7 @@ write_test_data(void *buf, uint32_t size) *((char8_t *)buf + index) = TEST_DATA; } + val_data_cache_ops_by_va((addr_t)buf, CLEAN_AND_INVALIDATE); } static @@ -50,59 +53,83 @@ payload(void) uint32_t dma_len; uint32_t base_index; uint32_t instance; - void *src_buf_virt; - void *src_buf_phys; - void *dest_buf_virt; - void *dest_buf_phys; - - src_buf_phys = NULL; + uint32_t start_bus; + uint32_t start_segment; + uint32_t start_bdf; + uint32_t e_bdf; + uint32_t smmu_index; + void *dram_buf1_virt; + void *dram_buf1_phys; + void *dram_buf2_virt; + void *dram_buf2_phys; + void *dram_buf2_iova; + + dram_buf1_phys = NULL; pe_index = val_pe_get_index_mpid(val_pe_get_mpid()); - - /* Read the number of excerciser cards */ instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); + /* Set start_bdf segment and bus numbers to 1st ecam region values */ + start_segment = val_pcie_get_info(PCIE_INFO_SEGMENT, 0); + start_bus = val_pcie_get_info(PCIE_INFO_START_BUS, 0); + start_bdf = PCIE_CREATE_BDF(start_segment, start_bus, 0, 0); + while (instance-- != 0) { + /* Get exerciser bdf */ + e_bdf = val_pcie_get_bdf(EXERCISER_CLASSCODE, start_bdf); + start_bdf = val_pcie_increment_bdf(e_bdf); + + /* Get SMMU node index for this exerciser instance */ + smmu_index = val_iovirt_get_rc_smmu_index(PCIE_EXTRACT_BDF_SEG(e_bdf)); + for (base_index = 0; base_index < TEST_DDR_REGION_CNT; base_index++) { - /* Get a Caheable DDR Buffer of size test data block size */ - src_buf_virt = val_memory_alloc(TEST_DATA_BLK_SIZE); - if (!src_buf_virt) { + /* Get a non-cacheable DDR Buffer of size test data block size */ + dram_buf1_virt = val_memory_alloc(TEST_DATA_BLK_SIZE); + if (!dram_buf1_virt) { val_print(AVS_PRINT_ERR, "\n Cacheable mem alloc failure %x", 02); val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); return; } /* Set the virtual addresses for test buffers */ - src_buf_phys = val_memory_virt_to_phys(src_buf_virt); - dest_buf_virt = src_buf_virt + (TEST_DATA_BLK_SIZE / 2); - dest_buf_phys = src_buf_phys + (TEST_DATA_BLK_SIZE / 2); + dram_buf1_phys = val_memory_virt_to_phys(dram_buf1_virt); + dram_buf2_virt = dram_buf1_virt + (TEST_DATA_BLK_SIZE / 2); + dram_buf2_phys = dram_buf1_phys + (TEST_DATA_BLK_SIZE / 2); dma_len = TEST_DATA_BLK_SIZE / 2; + if (smmu_index == AVS_INVALID_INDEX) { + dram_buf2_iova = dram_buf2_phys; + } else { + dram_buf2_iova = (void *)val_smmu_pa2iova(smmu_index, (uint64_t)dram_buf2_phys); + } /* Initialize the sender buffer with test specific data */ - write_test_data(src_buf_virt, dma_len); + write_test_data(dram_buf1_virt, dma_len); - /* Program Exerciser DMA controller with sender buffer information */ - val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)src_buf_phys, dma_len, instance); + /* Program Exerciser DMA controller with sender buffer information. + * As exerciser is not behind SMMU, IOVA is same as PA. Use PA to + * program the exerciser DMA. + */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dram_buf1_phys, dma_len, instance); if (val_exerciser_ops(START_DMA, EDMA_TO_DEVICE, instance)) { val_print(AVS_PRINT_ERR, "\n DMA write failure to exerciser %4x", instance); goto test_fail; } /* READ Back from Exerciser to validate above DMA write */ - val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dest_buf_phys, dma_len, instance); + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dram_buf2_iova, dma_len, instance); if (val_exerciser_ops(START_DMA, EDMA_FROM_DEVICE, instance)) { val_print(AVS_PRINT_ERR, "\n DMA read failure from exerciser %4x", instance); goto test_fail; } - if (memcmp(src_buf_virt, dest_buf_virt, dma_len)) { + if (val_memory_compare(dram_buf1_virt, dram_buf2_virt, dma_len)) { val_print(AVS_PRINT_ERR, "\n Data Comparasion failure for Exerciser %4x", instance); goto test_fail; } /* Return the buffer to the heap manager */ - val_memory_free(src_buf_virt); + val_memory_free(dram_buf1_virt); } } @@ -112,7 +139,7 @@ payload(void) test_fail: val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); - val_memory_free(src_buf_virt); + val_memory_free(dram_buf1_virt); return; } diff --git a/test_pool/exerciser/test_e004.c b/test_pool/exerciser/test_e004.c index c28c966d..ebb3ba89 100644 --- a/test_pool/exerciser/test_e004.c +++ b/test_pool/exerciser/test_e004.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +19,7 @@ #include "val/include/sbsa_avs_pcie_enumeration.h" #include "val/include/sbsa_avs_pcie.h" +#include "val/include/sbsa_avs_memory.h" #include "val/include/sbsa_avs_exerciser.h" #define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 4) @@ -59,7 +60,7 @@ free_msi_list (PERIPHERAL_VECTOR_LIST *list) current_node = list; while (current_node != NULL) { next_node = current_node->next; - kfree (current_node); + val_memory_free(current_node); current_node = next_node; } } @@ -71,9 +72,6 @@ payload (void) uint32_t count = val_peripheral_get_info (NUM_ALL, 0); uint32_t index = val_pe_get_index_mpid (val_pe_get_mpid()); - uint8_t status; - PERIPHERAL_VECTOR_LIST *current_dev_mvec; - PERIPHERAL_VECTOR_LIST *next_dev_mvec; uint32_t e_bdf = 0; uint32_t start_bus; uint32_t start_segment; @@ -89,10 +87,6 @@ payload (void) return; } - status = 0; - current_dev_mvec = NULL; - next_dev_mvec = NULL; - /* Read the number of excerciser cards */ instance = val_exerciser_get_info(EXERCISER_NUM_CARDS, 0); @@ -143,13 +137,13 @@ payload (void) if (timeout == 0) { val_print(AVS_PRINT_ERR, "\n Interrupt trigger failed for instance %4x ", instance); val_set_status(index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); - val_gic_free_interrupt(irq_num, mapped_irq_num); + val_gic_free_irq(irq_num, mapped_irq_num); free_msi_list(temp_mvec); return; } /* Return the interrupt */ - val_gic_free_interrupt(irq_num, mapped_irq_num); + val_gic_free_irq(irq_num, mapped_irq_num); } e_mvec = e_mvec->next; diff --git a/test_pool/exerciser/test_e005.c b/test_pool/exerciser/test_e005.c index 6a437949..027f2ec0 100644 --- a/test_pool/exerciser/test_e005.c +++ b/test_pool/exerciser/test_e005.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,7 @@ #define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 5) #define TEST_DESC "Generate PASID PCIe transactions " -#define MIN_PASID_SUPPORT (1 << 16) +#define TEST_PASID_VALUE ((1 << 16) + (1 << 12)) #define TEST_DATA_BLK_SIZE 512 #define TEST_DATA 0xDE @@ -55,6 +55,7 @@ payload(void) uint32_t start_segment; uint32_t start_bdf; uint32_t dma_len; + uint32_t smmu_index; void *src_buf_virt; void *src_buf_phys; void *dest_buf_virt; @@ -85,6 +86,24 @@ payload(void) /* Increment the exerciser count with pasid support */ e_valid_cnt++; + /* Find SMMU node index for this pcie endpoint */ + smmu_index = val_iovirt_get_rc_smmu_index(PCIE_EXTRACT_BDF_SEG(e_bdf)); + if (smmu_index == AVS_INVALID_INDEX) { + continue; + } + + /* If the smmu already support the requested pasid, + * return success. Else, PAL layer has to set up the + * corresponding page tables correctlyi and then return + * to support e_pasid. Upon success return zero, else one. + */ + e_pasid = TEST_PASID_VALUE; + if(val_smmu_create_pasid_entry(smmu_index, e_pasid)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %x smmu PASID enable error", instance); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + } + /* Program exerciser and it's root port to start sending TLPs * with PASID TLP Prefixes. This includes setting PASID Enable bit * in exerciser PASID Control register and the implementation specific @@ -96,13 +115,6 @@ payload(void) return; } - /* Check if exerciser PASID is of minimum 16-bits width */ - if(e_pasid < MIN_PASID_SUPPORT) { - val_print(AVS_PRINT_ERR, "\n Exerciser %x PASID less than 16-bits width", instance); - val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); - return; - } - /* Get a Caheable DDR Buffer of size test data block size */ src_buf_virt = val_memory_alloc(TEST_DATA_BLK_SIZE); if (!src_buf_virt) { @@ -144,7 +156,7 @@ payload(void) goto test_fail; } - if (memcmp(src_buf_virt, dest_buf_virt, dma_len)) { + if (val_memory_compare(src_buf_virt, dest_buf_virt, dma_len)) { val_print(AVS_PRINT_ERR, "\n Data Comparison failure for Exerciser %4x", instance); goto test_fail; } diff --git a/test_pool/exerciser/test_e006.c b/test_pool/exerciser/test_e006.c index c9613dca..be93fc24 100644 --- a/test_pool/exerciser/test_e006.c +++ b/test_pool/exerciser/test_e006.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,21 +25,24 @@ #define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 6) #define TEST_DESC "Generate PCIe legacy interrupts " +#define LEGACY_INTR_PIN_COUNT 4 + static uint32_t instance; static uint32_t e_intr_line; static uint32_t e_intr_pending; static void intr_handler(void) { - /* Call exerciser specific function to handle the interrupt */ - val_exerciser_ops(CLEAR_INTR, e_intr_line, instance); + /* Call exerciser specific function to handle the interrupt */ + val_exerciser_ops(CLEAR_INTR, e_intr_line, instance); - /* Clear the interrupt pending state */ - e_intr_pending = 0; + /* Clear the interrupt pending state */ + e_intr_pending = 0; - val_print(AVS_PRINT_DEBUG, "\n Received legacy interrupt %d", e_intr_line); + val_print(AVS_PRINT_DEBUG, "\n Received legacy interrupt %d", e_intr_line); } + static void payload (void) @@ -49,18 +52,16 @@ payload (void) uint8_t status; uint32_t e_bdf; uint32_t erp_bdf; - uint32_t e_valid_cnt; uint32_t start_segment; uint32_t start_bus; uint32_t start_bdf; - uint8_t e_intr_pin; - uint8_t e_intr_line; uint32_t ret_val; uint32_t timeout; + uint32_t e_intr_pin; + uint32_t pin_index; PERIPHERAL_IRQ_MAP *erp_intr_map; status = 0; - e_valid_cnt = 0; pe_index = val_pe_get_index_mpid(val_pe_get_mpid()); /* Read the number of excerciser cards */ @@ -71,99 +72,82 @@ payload (void) start_bus = val_pcie_get_info(PCIE_INFO_START_BUS, 0); start_bdf = PCIE_CREATE_BDF(start_segment, start_bus, 0, 0); + /* Allocate memory for interrupt mappings */ + erp_intr_map = val_memory_alloc(sizeof(PERIPHERAL_IRQ_MAP)); + if (!erp_intr_map) { + val_print (AVS_PRINT_ERR, "\n Memory allocation error", 00); + val_set_status(pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + return; + } + while (instance-- != 0) { /* Get the exerciser BDF */ e_bdf = val_pcie_get_bdf(EXERCISER_CLASSCODE, start_bdf); start_bdf = val_pcie_increment_bdf(e_bdf); - /* Read exerciser Interrupt Pin register. A value of 00h - * indicates that the function uses no legacy interrupt - * Message(s). If a device implements a single legacy - * interrupt message, it must be INTA; if it implements - * two legacy interrupt messages, they must be INTA and - * INTB; and so forth. - */ - val_pci_read_config_byte(e_bdf, PCIE_INTERRUPT_PIN, &e_intr_pin); - - /* Read exerciser interrupt line routing information - * from Interrupt Line register. Values in this register - * are programmed by system software and are system - * architecture specific. - */ - if (e_intr_pin) { - val_pci_read_config_byte(e_bdf, PCIE_INTERRUPT_LINE, &e_intr_line); - } else { - continue; - } - - /* Increment the exerciser count with legacy interrupt support */ - e_valid_cnt++; + for (pin_index = 1; pin_index <= LEGACY_INTR_PIN_COUNT; pin_index++) { + + /* Write to exerciser Interrupt Pin register. A value of 00h + * indicates that the function uses no legacy interrupt + * Message(s). Writing a value of 01h indicates, exerciser + * supports legacy interrupt message INTA; Writing a value + * of 02h indicates support for INTB; and so forth. + */ + val_pcie_read_cfg(e_bdf, PCIE_INTERRUPT_LINE, &e_intr_pin); + e_intr_pin = (e_intr_pin & (~0xFF00)) | (pin_index << 8); + val_pcie_write_cfg(e_bdf, PCIE_INTERRUPT_LINE, e_intr_pin); + + /* Derive exerciser root port (ERP) bdf */ + erp_bdf = e_bdf; + if (val_pcie_get_root_port_bdf(&erp_bdf)) { + val_print(AVS_PRINT_ERR, "\n ERP %x BDF fetch error", instance); + val_set_status(pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); + val_memory_free(erp_intr_map); + return; + } + + /* Read ERP legacy interrupt mappings */ + status = val_pci_get_legacy_irq_map(erp_bdf, erp_intr_map); + if (!status) { + + e_intr_line = erp_intr_map->legacy_irq_map[pin_index].irq_list[0]; + + /* Register an interrupt handler to verify legacy interrupt functionality */ + ret_val = val_gic_install_isr(e_intr_line, intr_handler); + if (ret_val) + goto test_fail; + + /* Set the interrupt trigger status to pending */ + e_intr_pending = 1; + + /* Trigger the legacy interrupt */ + val_exerciser_ops(GENERATE_L_INTR, e_intr_line, instance); + + /* PE busy polls to check the completion of interrupt service routine */ + timeout = TIMEOUT_LARGE; + while ((--timeout > 0) && e_intr_pending); + + if (timeout == 0) { + val_gic_free_irq(e_intr_line, 0); + val_print(AVS_PRINT_ERR, "\n Interrupt trigger failed for instance %4x ", instance); + goto test_fail; + } + + /* Return the interrupt */ + val_gic_free_irq(e_intr_line, 0); + + } else { + val_print (AVS_PRINT_ERR, "\n Legacy interrupt mapping Read error", status); + goto test_fail; + } - /* Derive exerciser root port (ERP) bdf */ - erp_bdf = e_bdf; - if(val_pcie_get_root_port_bdf(&erp_bdf)) { - val_print(AVS_PRINT_ERR, "\n ERP %x BDF fetch error", instance); - val_set_status(pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); - return; } - /* Allocate memory for interrupt mappings */ - erp_intr_map = val_memory_alloc(sizeof(PERIPHERAL_IRQ_MAP)); - if (!erp_intr_map) { - val_print (AVS_PRINT_ERR, "\n Memory allocation error", 00); - val_set_status(pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); - return; - } - - /* Read ERP legacy interrupt mappings */ - status = val_pci_get_legacy_irq_map(erp_bdf, erp_intr_map); - - if (!status) { - - /* Register an interrupt handler to verify legacy interrupt functionality */ - ret_val = val_gic_install_isr(e_intr_line, intr_handler); - if (ret_val) - goto test_fail; - - /* Set the interrupt trigger status to pending */ - e_intr_pending = 1; - - /* Trigger the legacy interrupt */ - val_exerciser_ops(GENERATE_L_INTR, e_intr_line, instance); - - /* PE busy polls to check the completion of interrupt service routine */ - timeout = TIMEOUT_LARGE; - while ((--timeout > 0) && e_intr_pending); - - if (timeout == 0) { - val_gic_free_interrupt(e_intr_line, 0); - val_print(AVS_PRINT_ERR, "\n Interrupt trigger failed for instance %4x ", instance); - goto test_fail; - } - - /* Return the interrupt */ - val_gic_free_interrupt(e_intr_line, 0); - - } - - /* Return the interrupt mapping space to the Heap */ - val_memory_free(erp_intr_map); - } - if (!e_valid_cnt) { - val_set_status(pe_index, RESULT_SKIP(g_sbsa_level, TEST_NUM, 00)); - return; - } - - if (!status) { - val_set_status (pe_index, RESULT_PASS (g_sbsa_level, TEST_NUM, 01)); - } else { - val_set_status (pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); - } - - return; + val_memory_free(erp_intr_map); + val_set_status (pe_index, RESULT_PASS (g_sbsa_level, TEST_NUM, 01)); test_fail: val_set_status(pe_index, RESULT_FAIL (g_sbsa_level, TEST_NUM, 02)); diff --git a/test_pool/exerciser/test_e007.c b/test_pool/exerciser/test_e007.c index 3e64014e..6582aaa6 100644 --- a/test_pool/exerciser/test_e007.c +++ b/test_pool/exerciser/test_e007.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,34 +14,137 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ + + +/* First test sequence - Initialize a main memory region marked as WB, + * outer shareable by the PE page tables. CPU Write to this region with + * new data and ensure that the new data is cached in the CPU caches. + * Read the same data locations from the Exerciser with NS=0. The + * exerciser should get the latest data (hardware enforced cache coherency + * expected). + * + * Second test sequence - Initialize a main memory region marked as WB, + * outer shareable by the PE page tables. CPU reads these locations and + * ensures that the data is cached in its caches. Exerciser Writes to + * this region with new data and with NS=0. CPU reads the same data + * locations. The CPU should get the latest data (hardware enforced + * cache coherency expected). + * + * The above cases verify exerciser dma data check (both read and write) + * The test assume PCIe RC addr space is within PE outer shareable domain. + */ + #include "val/include/sbsa_avs_val.h" #include "val/include/val_interface.h" #include "val/include/sbsa_avs_memory.h" #include "val/include/sbsa_avs_exerciser.h" +#include "val/include/sbsa_avs_smmu.h" #include "val/include/sbsa_avs_pcie.h" #include "val/include/sbsa_avs_pcie_enumeration.h" #define TEST_NUM (AVS_EXERCISER_TEST_NUM_BASE + 7) #define TEST_DESC "Check PCI Express I/O Coherency " -#define TEST_DATA_BLK_SIZE 512 -#define TEST_DATA 0xDE +#define TEST_DATA_BLK_SIZE (4*1024) +#define KNOWN_DATA 0xDE +#define NEW_DATA 0xAD + + +uint32_t test_sequence2(void *dram_buf1_virt, void *dram_buf1_phys, uint32_t e_bdf, uint32_t instance) +{ + + uint32_t dma_len; + void *dram_buf2_virt; + void *dram_buf2_phys; + + /* Set up a second dram buffer to send NEW_DATA to exerciser memory */ + dram_buf2_virt = dram_buf1_virt + (TEST_DATA_BLK_SIZE / 2); + dram_buf2_phys = dram_buf1_phys + (TEST_DATA_BLK_SIZE / 2); + dma_len = TEST_DATA_BLK_SIZE / 2; + + /* Write dram_buf1 with known data, this causes caching of the buffer */ + val_memory_set(dram_buf1_virt, dma_len, KNOWN_DATA); + + /* Write dram_buf2 with known data and flush the buffer to main memory */ + val_memory_set(dram_buf2_virt, dma_len, NEW_DATA); + val_data_cache_ops_by_va((addr_t)dram_buf2_virt, CLEAN_AND_INVALIDATE); + + /* Perform DMA OUT to copy contents of dram_buf2 to exerciser memory */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dram_buf2_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_TO_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA write failure to exerciser %4x", instance); + return 1; + } + + /* Perform DMA IN to copy content back from exerciser memory to dram_buf1 */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dram_buf1_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_FROM_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA read failure from exerciser %4x", instance); + return 1; + } + + /* Invalidate dram_buf1 and dram_buf2 contents present in CPU caches */ + val_data_cache_ops_by_va((addr_t)dram_buf1_virt, INVALIDATE); + val_data_cache_ops_by_va((addr_t)dram_buf2_virt, INVALIDATE); + + /* Compare the contents of ddr_buf1 and ddr_buf2 for NEW_DATA */ + if (val_memory_compare(dram_buf1_virt, dram_buf2_virt, dma_len)) { + val_print(AVS_PRINT_ERR, "\n I/O coherency failure for Exerciser %4x", instance); + return 1; + } -#define MEM_ATTR_CACHEABLE_SHAREABLE 0 -#define MEM_ATTR_NON_CACHEABLE 1 + /* Return success */ + return 0; +} -void init_source_buf_data(void *buf, uint32_t size) +uint32_t test_sequence1(void *dram_buf1_virt, void *dram_buf1_phys, uint32_t e_bdf, uint32_t instance) { - uint32_t index; + uint32_t dma_len; + void *dram_buf2_virt; + + dram_buf2_virt = dram_buf1_virt + (TEST_DATA_BLK_SIZE / 2); + dma_len = TEST_DATA_BLK_SIZE / 2; + + /* Write dram_buf1 with known data and flush the buffer to main memory */ + val_memory_set(dram_buf1_virt, dma_len, KNOWN_DATA); + val_data_cache_ops_by_va((addr_t)dram_buf1_virt, CLEAN_AND_INVALIDATE); + + /* Write dram_buf1 cache with new data, don't flush the data to main memory */ + val_memory_set(dram_buf1_virt, dma_len, NEW_DATA); - for (index = 0; index < size; index++) { - *((char8_t *)buf + index) = TEST_DATA; + /* Perform DMA OUT to copy contents of dram_buf1 to exerciser memory */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dram_buf1_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_TO_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA write failure to exerciser %4x", instance); + return 1; + } + + /* Perform DMA IN to copy the content from exerciser memory to dram_buf1 */ + val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dram_buf1_phys, dma_len, instance); + if (val_exerciser_ops(START_DMA, EDMA_FROM_DEVICE, instance)) { + val_print(AVS_PRINT_ERR, "\n DMA read failure from exerciser %4x", instance); + return 1; + } + + /* Write dram_buf2 with NEW_DATA to compare dram_buf1 content */ + val_memory_set(dram_buf2_virt, dma_len, NEW_DATA); + + /* Invalidate dram_buf1 contents present in CPU caches */ + val_data_cache_ops_by_va((addr_t)dram_buf1_virt, INVALIDATE); + + /* Compare the contents of ddr_buf1 and ddr_buf2 for NEW_DATA */ + if (val_memory_compare(dram_buf1_virt, dram_buf2_virt, dma_len)) { + val_print(AVS_PRINT_ERR, "\n I/O coherency failure for Exerciser %4x", instance); + return 1; } + /* Return success */ + return 0; } + static void payload (void) @@ -49,20 +152,17 @@ payload (void) uint32_t pe_index; uint32_t instance; - uint32_t dma_len; uint32_t e_bdf; uint32_t start_segment; uint32_t start_bus; uint32_t start_bdf; - void *e_dev; - void *src_buf_virt; - void *src_buf_phys; - void *dest_buf_virt; - void *dest_buf_phys; - - e_dev = NULL; - src_buf_virt = NULL; - src_buf_phys = NULL; + uint32_t smmu_index; + void *dram_buf1_virt; + void *dram_buf1_phys; + + dram_buf1_virt = NULL; + dram_buf1_phys = NULL; + pe_index = val_pe_get_index_mpid (val_pe_get_mpid()); /* Read the number of excerciser cards */ @@ -79,67 +179,62 @@ payload (void) e_bdf = val_pcie_get_bdf(EXERCISER_CLASSCODE, start_bdf); start_bdf = val_pcie_increment_bdf(e_bdf); - /* Derive exerciser device structure from its bdf */ - e_dev = val_pci_bdf_to_dev(e_bdf); - - /* Get a non-caheable DDR Buffer of size TEST_DATA_BLK_SIZE */ - src_buf_virt = val_memory_alloc_coherent(e_dev, TEST_DATA_BLK_SIZE, src_buf_phys); - if (!src_buf_virt) { - val_print(AVS_PRINT_ERR, "\n Non-cacheable mem alloc failure %x", 02); - val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); - return; - } + /* Find SMMU node index for this exerciser instance */ + smmu_index = val_iovirt_get_rc_smmu_index(PCIE_EXTRACT_BDF_SEG(e_bdf)); - /* Program exerciser to start sending TLPs with No Snoop attribute header. - * This includes setting Enable No snoop bit in exerciser control register. + /* Disable SMMU globally so that the transaction passes + * through the SMMU without any address modification. + * Global attributes, such as memory type or Shareability, + * might be applied from the SMMU_GBPA register of the SMMU. + * Or, the SMMU_GBPA register might be configured to abort + * all transactions. Do this only if the RC is behind an SMMU. */ - if(val_exerciser_ops(NO_SNOOP_TLP_START, 0, instance)) { - val_print(AVS_PRINT_ERR, "\n Exerciser %x No Snoop enable error", instance); - goto test_fail; + if (smmu_index != AVS_INVALID_INDEX) { + if(val_smmu_disable(smmu_index)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %x smmu disable error", instance); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; + } } - /* Set VA and PA addresses for the destination buffer and DMA size */ - dest_buf_virt = src_buf_virt + (TEST_DATA_BLK_SIZE / 2); - dest_buf_phys = src_buf_phys + (TEST_DATA_BLK_SIZE / 2); - dma_len = TEST_DATA_BLK_SIZE / 2; - - /* Initialize source buffer with test specific data */ - init_source_buf_data(src_buf_virt, dma_len); - - /* Program Exerciser DMA controller with the source buffer information */ - val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)src_buf_phys, dma_len, instance); - if (val_exerciser_ops(START_DMA, EDMA_TO_DEVICE, instance)) { - val_print(AVS_PRINT_ERR, "\n DMA write failure to exerciser %4x", instance); - goto test_fail; + /* Get a WB, outer shareable DDR Buffer of size TEST_DATA_BLK_SIZE */ + dram_buf1_virt = val_memory_alloc_coherent(e_bdf, TEST_DATA_BLK_SIZE, dram_buf1_phys); + if (!dram_buf1_virt) { + val_print(AVS_PRINT_ERR, "\n WB and OSH mem alloc failure %x", 02); + val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); + return; } - /* READ Back from Exerciser to validate above DMA write */ - val_exerciser_set_param(DMA_ATTRIBUTES, (uint64_t)dest_buf_phys, dma_len, instance); - if (val_exerciser_ops(START_DMA, EDMA_FROM_DEVICE, instance)) { - val_print(AVS_PRINT_ERR, "\n DMA read failure from exerciser %4x", instance); - goto test_fail; + /* Program exerciser hierarchy to start sending/receiving TLPs + * with No Snoop attribute header. This includes enabling + * No snoop bit in exerciser control register. + */ + if (val_exerciser_ops(NO_SNOOP_CLEAR_TLP_START, 0, instance)) { + val_print(AVS_PRINT_ERR, "\n Exerciser %x No Snoop enable error", instance); + goto test_fail; } - if (memcmp(src_buf_virt, dest_buf_virt, dma_len)) { - val_print(AVS_PRINT_ERR, "\n I/O coherency failure for Exerciser %4x", instance); - goto test_fail; - } + if (test_sequence1(dram_buf1_virt, dram_buf1_phys, e_bdf, instance) || + test_sequence2(dram_buf1_virt, dram_buf1_phys, e_bdf, instance)) + goto test_fail; - /* Stop exerciser sending TLPs with No Snoop attribute header */ - if (val_exerciser_ops(NO_SNOOP_TLP_STOP, 0, instance)) { + /* Stop exerciser hierarchy sending/receiving TLPs with No Snoop attribute header */ + if (val_exerciser_ops(NO_SNOOP_CLEAR_TLP_STOP, 0, instance)) { val_print(AVS_PRINT_ERR, "\n Exerciser %x No snoop TLP disable error", instance); goto test_fail; } + /* Return this exerciser dma memory back to the heap manager */ + val_memory_free_coherent(e_bdf, TEST_DATA_BLK_SIZE, dram_buf1_virt, dram_buf1_phys); + } val_set_status(pe_index, RESULT_PASS(g_sbsa_level, TEST_NUM, 0)); - val_memory_free_coherent(e_dev, TEST_DATA_BLK_SIZE, src_buf_virt, src_buf_phys); return; test_fail: val_set_status(pe_index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 02)); - val_memory_free_coherent(e_dev, TEST_DATA_BLK_SIZE, src_buf_virt, src_buf_phys); + val_memory_free_coherent(e_bdf, TEST_DATA_BLK_SIZE, dram_buf1_virt, dram_buf1_phys); return; } diff --git a/test_pool/pcie/test_p003.c b/test_pool/pcie/test_p003.c index bd04c39d..4faf492e 100755 --- a/test_pool/pcie/test_p003.c +++ b/test_pool/pcie/test_p003.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +23,10 @@ #define TEST_NUM (AVS_PCIE_TEST_NUM_BASE + 3) #define TEST_DESC "Check ECAM Memory accessibility " +#define PCIE_VENDOR_ID_REG_OFFSET 0x0 +#define PCIE_CACHE_LINE_SIZE_REG_OFFSET 0xC + + static void payload(void) @@ -34,6 +38,9 @@ payload(void) uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); uint32_t bdf = 0; uint32_t bus, segment; + uint32_t end_bus; + uint32_t bus_index; + uint32_t dev_index; uint32_t ret; num_ecam = val_pcie_get_info(PCIE_INFO_NUM_ECAM, 0); @@ -56,24 +63,39 @@ payload(void) num_ecam--; segment = val_pcie_get_info(PCIE_INFO_SEGMENT, num_ecam); bus = val_pcie_get_info(PCIE_INFO_START_BUS, num_ecam); + end_bus = val_pcie_get_info(PCIE_INFO_END_BUS, num_ecam); bdf = PCIE_CREATE_BDF(segment, bus, 0, 0); - ret = val_pcie_read_cfg(bdf, 0, &data); - - //If this is really PCIe CFG space, Device ID and Vendor ID cannot be 0 or 0xFFFF - if (ret == PCIE_READ_ERR || (data == 0) || ((data & 0xFFFF) == 0xFFFF)) { - val_print(AVS_PRINT_ERR, "\n Incorrect data at ECAM Base %4x ", data); - val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, 01)); - return; + ret = val_pcie_read_cfg(bdf, PCIE_VENDOR_ID_REG_OFFSET, &data); + if (data == 0xFFFFFFFF) { + val_print(AVS_PRINT_ERR, "\n First device in a ECAM space is not a valid device", 0); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, (bus << 8))); + return; } - ret = val_pcie_read_cfg(bdf, 0xC, &data); - - //If this really is PCIe CFG, Header type[6:0] must be 01 or 00 - if (ret == PCIE_READ_ERR || ((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; + for(bus_index = bus; bus_index <= end_bus; bus_index++) { + for(dev_index = 0; dev_index < PCIE_MAX_DEV; dev_index++) { + + /* Only function zero is checked */ + bdf = PCIE_CREATE_BDF(segment, bus_index, dev_index, 0); + ret = val_pcie_read_cfg(bdf, PCIE_VENDOR_ID_REG_OFFSET, &data); + + //If this is really PCIe CFG space, Device ID and Vendor ID cannot be 0 or 0xFFFF + if (ret == PCIE_READ_ERR || (data == 0) || ((data != 0xFFFFFFFF) && ((data & 0xFFFF) == 0xFFFF))) { + val_print(AVS_PRINT_ERR, "\n Incorrect data at ECAM Base %4x ", data); + val_set_status(index, RESULT_FAIL(g_sbsa_level, TEST_NUM, (bus_index << 8)|dev_index)); + return; + } + + ret = val_pcie_read_cfg(bdf, PCIE_CACHE_LINE_SIZE_REG_OFFSET, &data); + + //If this really is PCIe CFG, Header type[6:0] must be 01 or 00 + if (ret == PCIE_READ_ERR || ((data != 0xFFFFFFFF) && (((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, (bus_index << 8)|dev_index)); + return; + } + } } } diff --git a/test_pool/pcie/test_p010.c b/test_pool/pcie/test_p010.c index 868fffba..7344b81a 100644 --- a/test_pool/pcie/test_p010.c +++ b/test_pool/pcie/test_p010.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -56,7 +56,7 @@ payload(void) { 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) + if((max_pasids = val_smmu_max_pasids(num_smmu)) > 0) { skip = 0; if(max_pasids < MIN_PASID_SUPPORT) diff --git a/test_pool/pe/test_c008.c b/test_pool/pe/test_c008.c index 4b3be2b1..0c0aa572 100755 --- a/test_pool/pe/test_c008.c +++ b/test_pool/pe/test_c008.c @@ -29,7 +29,12 @@ payload() uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); /* Check the current endianness setting of SCTLR.EE */ - data = val_pe_reg_read(SCTLR_EL2); + if (val_pe_reg_read(CurrentEL) == AARCH64_EL2) { + data = val_pe_reg_read(SCTLR_EL2); + } else if (val_pe_reg_read(CurrentEL) == AARCH64_EL1) { + data = val_pe_reg_read(SCTLR_EL1); + } + if (((data >> 25) & 1) == 0) //Bit 25 must be 0 val_set_status(index, RESULT_PASS(g_sbsa_level, TEST_NUM, 02)); else diff --git a/test_pool/power_wakeup/test_u001.c b/test_pool/power_wakeup/test_u001.c index 1cb5ac76..1211c5ab 100755 --- a/test_pool/power_wakeup/test_u001.c +++ b/test_pool/power_wakeup/test_u001.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,7 @@ **/ #include "val/include/sbsa_avs_val.h" +#include "val/include/sbsa_avs_pe.h" #include "val/include/val_interface.h" #include "val/include/sbsa_avs_wakeup.h" @@ -303,10 +304,13 @@ u001_entry(uint32_t num_pe) val_run_test_payload(TEST_NUM2, num_pe, payload2, 0); status |= val_check_for_error(TEST_NUM2, num_pe); - status_test = val_initialize_test(TEST_NUM3, TEST_DESC3, num_pe, g_sbsa_level); - if (status_test != AVS_STATUS_SKIP) - val_run_test_payload(TEST_NUM3, num_pe, payload3, 0); - status |= val_check_for_error(TEST_NUM3, num_pe); + /* Run this test if current exception level is EL2 */ + if (val_pe_reg_read(CurrentEL) == AARCH64_EL2) { + status_test = val_initialize_test(TEST_NUM3, TEST_DESC3, num_pe, g_sbsa_level); + if (status_test != AVS_STATUS_SKIP) + val_run_test_payload(TEST_NUM3, num_pe, payload3, 0); + status |= val_check_for_error(TEST_NUM3, num_pe); + } status_test = val_initialize_test(TEST_NUM4, TEST_DESC4, num_pe, g_sbsa_level); if (status_test != AVS_STATUS_SKIP) diff --git a/uefi_app/SbsaAvs.h b/uefi_app/SbsaAvs.h index ec887b20..bdb64916 100755 --- a/uefi_app/SbsaAvs.h +++ b/uefi_app/SbsaAvs.h @@ -21,7 +21,7 @@ #define SBSA_ACS_MAJOR_VER 2 - #define SBSA_ACS_MINOR_VER 2 + #define SBSA_ACS_MINOR_VER 3 #define G_SBSA_LEVEL 3 #define SBSA_MAX_LEVEL_SUPPORTED 5 diff --git a/uefi_app/SbsaAvs.inf b/uefi_app/SbsaAvs.inf index 95d18352..514dcffe 100755 --- a/uefi_app/SbsaAvs.inf +++ b/uefi_app/SbsaAvs.inf @@ -1,5 +1,5 @@ ## @file -# Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. +# Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. # SPDX-License-Identifier : Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -92,6 +92,13 @@ ../test_pool/peripherals/test_d003.c ../test_pool/peripherals/test_m001.c ../test_pool/peripherals/test_m002.c + ../test_pool/exerciser/test_e001.c + ../test_pool/exerciser/test_e002.c + ../test_pool/exerciser/test_e003.c + ../test_pool/exerciser/test_e004.c + ../test_pool/exerciser/test_e005.c + ../test_pool/exerciser/test_e006.c + ../test_pool/exerciser/test_e007.c [Packages] EmbeddedPkg/EmbeddedPkg.dec diff --git a/uefi_app/SbsaAvsMain.c b/uefi_app/SbsaAvsMain.c index f78f2236..ca235b34 100755 --- a/uefi_app/SbsaAvsMain.c +++ b/uefi_app/SbsaAvsMain.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -433,6 +433,9 @@ ShellAppMain ( Print(L"\n *** Starting IO Virtualization tests *** \n"); Status |= val_smmu_execute_tests(g_sbsa_level, val_pe_get_num()); + Print(L"\n *** Starting PCIe Exerciser tests *** \n"); + Status |= val_exerciser_execute_tests(g_sbsa_level); + print_test_status: val_print(AVS_PRINT_TEST, "\n ------------------------------------------------------- \n", 0); val_print(AVS_PRINT_TEST, " Total Tests run = %4d;", g_sbsa_tests_total); diff --git a/val/SbsaValLib.inf b/val/SbsaValLib.inf index f0426080..d34aa3f0 100644 --- a/val/SbsaValLib.inf +++ b/val/SbsaValLib.inf @@ -1,5 +1,5 @@ ## @file -# Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. +# Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. # SPDX-License-Identifier : Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,6 +44,7 @@ src/avs_peripherals.c src/avs_secure.c src/avs_memory.c + src/avs_exerciser.c [Packages] MdePkg/MdePkg.dec diff --git a/val/include/pal_interface.h b/val/include/pal_interface.h index 251026fe..b2d227db 100755 --- a/val/include/pal_interface.h +++ b/val/include/pal_interface.h @@ -136,7 +136,7 @@ void pal_gic_create_info_table(GIC_INFO_TABLE *gic_info_table); uint32_t pal_gic_install_isr(uint32_t int_id, void (*isr)(void)); void pal_gic_end_of_interrupt(uint32_t int_id); uint32_t pal_gic_request_irq(unsigned int irq_num, unsigned int mapped_irq_num, void *isr); -void pal_gic_free_interrupt(unsigned int irq_num, unsigned int mapped_irq_num); +void pal_gic_free_irq(unsigned int irq_num, unsigned int mapped_irq_num); uint32_t pal_gic_set_intr_trigger(uint32_t int_id, INTR_TRIGGER_INFO_TYPE_e trigger_type); @@ -257,6 +257,7 @@ typedef struct { uint32_t segment; uint32_t ats_attr; uint32_t cca; //Cache Coherency Attribute + uint64_t smmu_base; }IOVIRT_RC_INFO_BLOCK; typedef struct { @@ -326,6 +327,7 @@ typedef struct { 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); +uint64_t pal_iovirt_get_rc_smmu_base(IOVIRT_INFO_TABLE *iovirt, uint32_t rc_seg_num); /** @brief SMMU Info Table @@ -340,6 +342,9 @@ 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); +uint32_t pal_smmu_create_pasid_entry(uint64_t smmu_base, uint32_t pasid); +uint32_t pal_smmu_disable(uint64_t smmu_base); +uint64_t pal_smmu_pa2iova(uint64_t smmu_base, uint64_t pa); /** Peripheral Tests related definitions **/ @@ -506,9 +511,11 @@ void pal_print_raw(uint64_t addr, char8_t *string, uint64_t data); void *pal_mem_alloc(uint32_t size); -void *pal_mem_alloc_coherent(void *dev, unsigned int size, void *pa); +void *pal_mem_alloc_coherent(uint32_t bdf, uint32_t size, void *pa); void pal_mem_free(void *buffer); -void pal_mem_free_coherent(void *dev, unsigned int size, void *va, void *pa); +int pal_mem_compare(void *src, void *dest, uint32_t len); +void pal_mem_set(void *buf, uint32_t size, uint8_t value); +void pal_mem_free_coherent(uint32_t bdf, unsigned int size, void *va, void *pa); void *pal_mem_virt_to_phys(void *va); void pal_mem_allocate_shared(uint32_t num_pe, uint32_t sizeofentry); @@ -531,7 +538,7 @@ void pal_pe_data_cache_ops_by_va(uint64_t addr, uint32_t type); #define EXERCISER_CLASSCODE 0x010203 #define MAX_ARRAY_SIZE 32 #define TEST_REG_COUNT 10 -#define TEST_DDR_REGION_CNT 5 +#define TEST_DDR_REGION_CNT 16 typedef struct { uint64_t buf[MAX_ARRAY_SIZE]; @@ -579,8 +586,8 @@ typedef enum { CLEAR_INTR = 0x6, PASID_TLP_START = 0x7, PASID_TLP_STOP = 0x8, - NO_SNOOP_TLP_START = 0x9, - NO_SNOOP_TLP_STOP = 0xa + NO_SNOOP_CLEAR_TLP_START = 0x9, + NO_SNOOP_CLEAR_TLP_STOP = 0xa } EXERCISER_OPS; typedef enum { diff --git a/val/include/sbsa_avs_memory.h b/val/include/sbsa_avs_memory.h index 3870412f..f8ad3761 100644 --- a/val/include/sbsa_avs_memory.h +++ b/val/include/sbsa_avs_memory.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,9 +22,11 @@ addr_t val_memory_ioremap(void *addr, uint32_t size, uint64_t attr); void val_memory_unmap(void *ptr); void *val_memory_alloc(uint32_t size); -void *val_memory_alloc_coherent(void *dev, uint32_t size, void *pa); +void *val_memory_alloc_coherent(uint32_t bdf, uint32_t size, void *pa); void val_memory_free(void *addr); -void val_memory_free_coherent(void *dev, uint32_t size, void *va, void *pa); +int val_memory_compare(void *src, void *dest, uint32_t len); +void val_memory_set(void *buf, uint32_t size, uint8_t value); +void val_memory_free_coherent(uint32_t bdf, uint32_t size, void *va, void *pa); void *val_memory_virt_to_phys(void *va); #endif // __SBSA_AVS_PERIPHERAL_H__ diff --git a/val/include/sbsa_avs_pcie.h b/val/include/sbsa_avs_pcie.h index 106900d4..d64fef63 100644 --- a/val/include/sbsa_avs_pcie.h +++ b/val/include/sbsa_avs_pcie.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -81,12 +81,6 @@ val_pcie_get_dma_coherent(uint32_t bdf); uint32_t val_pcie_io_read_cfg(uint32_t bdf, uint32_t offset, uint32_t *data); -void -val_pci_read_config_byte(uint32_t bdf, uint8_t offset, uint8_t *val); - -void -val_pci_write_config_byte(uint32_t bdf, uint8_t offset, uint8_t val); - uint32_t p001_entry(uint32_t num_pe); diff --git a/val/include/sbsa_avs_pe.h b/val/include/sbsa_avs_pe.h index 973a5293..fad7187c 100644 --- a/val/include/sbsa_avs_pe.h +++ b/val/include/sbsa_avs_pe.h @@ -29,6 +29,9 @@ #define EXCEPT_AARCH64_FIQ 2 #define EXCEPT_AARCH64_SERROR 3 +// AArch64 Exception Level +#define AARCH64_EL2 0x8 +#define AARCH64_EL1 0x4 typedef enum { MPIDR_EL1 = 1, @@ -44,6 +47,7 @@ typedef enum { ID_AA64ISAR1_EL1, SCTLR_EL3, SCTLR_EL2, + SCTLR_EL1, PMCR_EL0, PMOVSSET_EL0, PMOVSCLR_EL0, @@ -118,6 +122,8 @@ uint64_t AA64ReadSctlr3(void); uint64_t AA64ReadSctlr2(void); +uint64_t AA64ReadSctlr1(void); + uint64_t AA64ReadPmcr(void); uint64_t AA64ReadIdDfr0(void); diff --git a/val/include/sbsa_avs_smmu.h b/val/include/sbsa_avs_smmu.h index 3563097e..c9766c6d 100644 --- a/val/include/sbsa_avs_smmu.h +++ b/val/include/sbsa_avs_smmu.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +37,17 @@ 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); +val_smmu_max_pasids(uint32_t smmu_index); + +uint32_t +val_smmu_create_pasid_entry(uint32_t smmu_index, uint32_t pasid); + +uint32_t +val_smmu_disable(uint32_t smmu_index); + +uint64_t +val_smmu_pa2iova(uint32_t smmu_index, uint64_t pa); + uint32_t i001_entry(uint32_t num_pe); diff --git a/val/include/val_interface.h b/val/include/val_interface.h index ed2697db..78ebf118 100644 --- a/val/include/val_interface.h +++ b/val/include/val_interface.h @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,6 +34,8 @@ #define AVS_STATUS_SKIP 0x10000000 #define AVS_STATUS_PASS 0x0 +#define AVS_INVALID_INDEX 0xFFFFFFFF + #define VAL_EXTRACT_BITS(data, start, end) ((data >> start) & ((1ul << (end-start+1))-1)) /* GENERIC VAL APIs */ @@ -84,7 +86,7 @@ uint32_t val_gic_get_interrupt_state(uint32_t int_id); void val_gic_clear_interrupt(uint32_t int_id); void val_gic_cpuif_init(void); uint32_t val_gic_request_irq(uint32_t irq_num, uint32_t mapped_irq_num, void *isr); -void val_gic_free_interrupt(uint32_t irq_num, uint32_t mapped_irq_num); +void val_gic_free_irq(uint32_t irq_num, uint32_t mapped_irq_num); void val_gic_set_intr_trigger(uint32_t int_id, INTR_TRIGGER_INFO_TYPE_e trigger_type); /*TIMER VAL APIs */ @@ -102,6 +104,7 @@ typedef enum { TIMER_INFO_IS_PLATFORM_TIMER_SECURE, TIMER_INFO_SYS_CNTL_BASE, TIMER_INFO_SYS_CNT_BASE_N, + TIMER_INFO_FRAME_NUM, TIMER_INFO_SYS_INTID, TIMER_INFO_SYS_TIMER_STATUS }TIMER_INFO_e; @@ -180,10 +183,10 @@ typedef enum { void val_iovirt_create_info_table(uint64_t *iovirt_info_table); void val_iovirt_free_info_table(void); +uint32_t val_iovirt_get_rc_smmu_index(uint32_t rc_seg_num); uint32_t val_smmu_execute_tests(uint32_t level, uint32_t num_pe); uint64_t val_smmu_get_info(SMMU_INFO_e, uint32_t index); - typedef enum { DMA_NUM_CTRL = 1, DMA_HOST_INFO, @@ -291,4 +294,7 @@ uint32_t val_secure_get_result(SBSA_SMC_t *smc, uint32_t timeout); uint32_t val_secure_execute_tests(uint32_t level, uint32_t num_pe); uint32_t val_secure_trusted_firmware_init(void); +/* PCIe Exerciser tests */ +uint32_t val_exerciser_execute_tests(uint32_t level); + #endif diff --git a/val/src/AArch64/PeRegSysSupport.S b/val/src/AArch64/PeRegSysSupport.S index bba7a9dc..09b445e8 100644 --- a/val/src/AArch64/PeRegSysSupport.S +++ b/val/src/AArch64/PeRegSysSupport.S @@ -1,5 +1,5 @@ #/** @file -# Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. +# Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. # SPDX-License-Identifier : Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,6 +50,7 @@ GCC_ASM_EXPORT (AA64ReadIsar0) GCC_ASM_EXPORT (AA64ReadIsar1) GCC_ASM_EXPORT (AA64ReadSctlr3) GCC_ASM_EXPORT (AA64ReadSctlr2) +GCC_ASM_EXPORT (AA64ReadSctlr1) GCC_ASM_EXPORT (AA64ReadPmcr) GCC_ASM_EXPORT (AA64ReadIdDfr0) GCC_ASM_EXPORT (AA64ReadIdDfr1) @@ -154,6 +155,10 @@ ASM_PFX(AA64ReadSctlr2): mrs x0, sctlr_el2 ret +ASM_PFX(AA64ReadSctlr1): + mrs x0, sctlr_el1 + ret + ASM_PFX(AA64ReadPmcr): mrs x0, pmcr_el0 ret diff --git a/val/src/avs_gic_support.c b/val/src/avs_gic_support.c index dede14cd..8ead7299 100644 --- a/val/src/avs_gic_support.c +++ b/val/src/avs_gic_support.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -132,7 +132,7 @@ uint32_t val_gic_request_irq(uint32_t irq_num, uint32_t mapped_irq_num, void *is * @param mapped_irq_num Mapped irq number * @return none */ -void val_gic_free_interrupt(uint32_t irq_num, uint32_t mapped_irq_num) +void val_gic_free_irq(uint32_t irq_num, uint32_t mapped_irq_num) { - pal_gic_free_interrupt(irq_num, mapped_irq_num); + pal_gic_free_irq(irq_num, mapped_irq_num); } diff --git a/val/src/avs_iovirt.c b/val/src/avs_iovirt.c index a776124d..d097a4c1 100644 --- a/val/src/avs_iovirt.c +++ b/val/src/avs_iovirt.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -264,3 +264,23 @@ val_iovirt_free_info_table() { pal_mem_free((void *)g_iovirt_info_table); } + +uint32_t +val_iovirt_get_rc_smmu_index(uint32_t rc_seg_num) +{ + + uint32_t num_smmu; + uint64_t smmu_base; + + smmu_base = pal_iovirt_get_rc_smmu_base(g_iovirt_info_table, rc_seg_num); + if (smmu_base) { + num_smmu = val_smmu_get_info(SMMU_NUM_CTRL, 0); + while (num_smmu--) { + if (smmu_base == val_smmu_get_info(SMMU_CTRL_BASE, num_smmu)) + return num_smmu; + } + } + + val_print(AVS_PRINT_ERR, "RC with segment number %d is not behind any SMMU", rc_seg_num); + return AVS_INVALID_INDEX; +} diff --git a/val/src/avs_memory.c b/val/src/avs_memory.c index e63b526d..fa6424db 100644 --- a/val/src/avs_memory.c +++ b/val/src/avs_memory.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -187,9 +187,9 @@ val_memory_alloc(uint32_t size) } void * -val_memory_alloc_coherent(void *dev, uint32_t size, void *pa) +val_memory_alloc_coherent(uint32_t bdf, uint32_t size, void *pa) { - return pal_mem_alloc_coherent(dev, size, pa); + return pal_mem_alloc_coherent(bdf, size, pa); } void @@ -198,10 +198,22 @@ val_memory_free(void *addr) pal_mem_free(addr); } +int +val_memory_compare(void *src, void *dest, uint32_t len) +{ + return pal_mem_compare(src, dest, len); +} + +void +val_memory_set(void *buf, uint32_t size, uint8_t value) +{ + pal_mem_set(buf, size, value); +} + void -val_memory_free_coherent(void *dev, uint32_t size, void *va, void *pa) +val_memory_free_coherent(uint32_t bdf, uint32_t size, void *va, void *pa) { - pal_mem_free_coherent(dev, size, va, pa); + pal_mem_free_coherent(bdf, size, va, pa); } void * diff --git a/val/src/avs_pcie.c b/val/src/avs_pcie.c index 1de080d7..1323f401 100644 --- a/val/src/avs_pcie.c +++ b/val/src/avs_pcie.c @@ -647,15 +647,3 @@ val_pcie_read_ext_cap_word(uint32_t bdf, uint32_t ext_cap_id, uint8_t offset, ui PCIE_EXTRACT_BDF_FUNC(bdf), ext_cap_id, offset, val); } - -void -val_pci_read_config_byte(uint32_t bdf, uint8_t offset, uint8_t *val) -{ - pal_pci_read_config_byte(bdf, offset, val); -} - -void -val_pci_write_config_byte(uint32_t bdf, uint8_t offset, uint8_t val) -{ - pal_pci_write_config_byte(bdf, offset, val); -} diff --git a/val/src/avs_pe.c b/val/src/avs_pe.c index 7454d44e..d4edfc5d 100644 --- a/val/src/avs_pe.c +++ b/val/src/avs_pe.c @@ -129,6 +129,8 @@ val_pe_reg_read(uint32_t reg_id) return AA64ReadSctlr3(); case SCTLR_EL2: return AA64ReadSctlr2(); + case SCTLR_EL1: + return AA64ReadSctlr1(); case PMCR_EL0: return AA64ReadPmcr(); case ID_AA64DFR0_EL1: diff --git a/val/src/avs_smmu.c b/val/src/avs_smmu.c index 844eafb8..33c8c177 100644 --- a/val/src/avs_smmu.c +++ b/val/src/avs_smmu.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -174,7 +174,37 @@ val_smmu_ops(SMMU_OPS_e ops, uint32_t smmu_index, void *param1, void *param2) } uint32_t -val_smmu_max_pasids(uint64_t smmu_base) +val_smmu_max_pasids(uint32_t smmu_index) { + uint64_t smmu_base; + + smmu_base = val_smmu_get_info(SMMU_CTRL_BASE, smmu_index); return pal_smmu_max_pasids(smmu_base); } + +uint32_t +val_smmu_create_pasid_entry(uint32_t smmu_index, uint32_t pasid) +{ + uint64_t smmu_base; + + smmu_base = val_smmu_get_info(SMMU_CTRL_BASE, smmu_index); + return pal_smmu_create_pasid_entry(smmu_base, pasid); +} + +uint32_t +val_smmu_disable(uint32_t smmu_index) +{ + uint64_t smmu_base; + + smmu_base = val_smmu_get_info(SMMU_CTRL_BASE, smmu_index); + return pal_smmu_disable(smmu_base); +} + +uint64_t +val_smmu_pa2iova(uint32_t smmu_index, uint64_t pa) +{ + uint64_t smmu_base; + + smmu_base = val_smmu_get_info(SMMU_CTRL_BASE, smmu_index); + return pal_smmu_pa2iova(smmu_base, pa); +} diff --git a/val/src/avs_timer.c b/val/src/avs_timer.c index 7c989ef2..167c6819 100644 --- a/val/src/avs_timer.c +++ b/val/src/avs_timer.c @@ -1,5 +1,5 @@ /** @file - * Copyright (c) 2016-2018, Arm Limited or its affiliates. All rights reserved. + * Copyright (c) 2016-2019, Arm Limited or its affiliates. All rights reserved. * SPDX-License-Identifier : Apache-2.0 * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,7 @@ **/ #include "include/sbsa_avs_val.h" +#include "include/sbsa_avs_pe.h" #include "include/sbsa_avs_timer_support.h" #include "include/sbsa_avs_timer.h" #include "include/sbsa_avs_common.h" @@ -46,7 +47,12 @@ val_timer_execute_tests(uint32_t level, uint32_t num_pe) status = t001_entry(num_pe); status |= t002_entry(num_pe); status |= t003_entry(num_pe); - status |= t004_entry(num_pe); + + /* Run this test if current exception level is EL2 */ + if (val_pe_reg_read(CurrentEL) == AARCH64_EL2) { + status |= t004_entry(num_pe); + } + status |= t005_entry(num_pe); status |= t006_entry(num_pe); status_sys_timer = t007_entry(num_pe); @@ -110,6 +116,10 @@ val_timer_get_info(TIMER_INFO_e info_type, uint64_t instance) val_platform_timer_get_entry_index (instance, &block_num, &block_index); if (block_num != 0xFFFF) return g_timer_info_table->gt_info[block_num].GtCntBase[block_index]; + case TIMER_INFO_FRAME_NUM: + val_platform_timer_get_entry_index (instance, &block_num, &block_index); + if (block_num != 0xFFFF) + return g_timer_info_table->gt_info[block_num].frame_num[block_index]; case TIMER_INFO_SYS_INTID: val_platform_timer_get_entry_index (instance, &block_num, &block_index); if (block_num != 0xFFFF) @@ -143,6 +153,7 @@ val_platform_timer_get_entry_index(uint64_t instance, uint32_t *block, uint32_t *block = *block + 1; } } + /** @brief This API enables the Architecture timer whose register is given as the input parameter. 1. Caller - VAL @@ -159,6 +170,7 @@ ArmGenericTimerEnableTimer ( uint64_t timer_ctrl_reg; timer_ctrl_reg = ArmArchTimerReadReg (reg); + timer_ctrl_reg &= (~ARM_ARCH_TIMER_IMASK); timer_ctrl_reg |= ARM_ARCH_TIMER_ENABLE; ArmArchTimerWriteReg (reg, &timer_ctrl_reg); } @@ -179,6 +191,7 @@ ArmGenericTimerDisableTimer ( uint64_t timer_ctrl_reg; timer_ctrl_reg = ArmArchTimerReadReg (reg); + timer_ctrl_reg |= ARM_ARCH_TIMER_IMASK; timer_ctrl_reg &= ~ARM_ARCH_TIMER_ENABLE; ArmArchTimerWriteReg (reg, &timer_ctrl_reg); } @@ -342,16 +355,20 @@ val_timer_skip_if_cntbase_access_not_allowed(uint64_t index) { uint64_t cnt_ctl_base; uint32_t data; + uint32_t frame_num = 0; cnt_ctl_base = val_timer_get_info(TIMER_INFO_SYS_CNTL_BASE, index); + frame_num = val_timer_get_info(TIMER_INFO_FRAME_NUM, index); + if(cnt_ctl_base){ - data = val_mmio_read(cnt_ctl_base + 0x40); + /* should we also check if this frame is non-secure before accessing this register? */ + data = val_mmio_read(cnt_ctl_base + 0x40 + frame_num * 4); if((data & 0x1) == 0x1) return 0; else{ data |= 0x1; - val_mmio_write(cnt_ctl_base + 0x40, data); - data = val_mmio_read(cnt_ctl_base + 0x40); + val_mmio_write(cnt_ctl_base + 0x40 + frame_num * 4, data); + data = val_mmio_read(cnt_ctl_base + 0x40 + frame_num * 4); if((data & 0x1) == 1) return 0; else