diff --git a/apps/uefi/Bsa.inf b/apps/uefi/Bsa.inf
index 5e0d3f06..065ef1f7 100644
--- a/apps/uefi/Bsa.inf
+++ b/apps/uefi/Bsa.inf
@@ -78,6 +78,7 @@
../../test_pool/gic/its003.c
../../test_pool/gic/its004.c
../../test_pool/gic/its005.c
+ ../../test_pool/gic/its006.c
../../test_pool/timer/t001.c
../../test_pool/timer/t002.c
../../test_pool/timer/t003.c
diff --git a/apps/uefi/Mem.inf b/apps/uefi/Mem.inf
index cc8f4fa4..aa8a5e07 100644
--- a/apps/uefi/Mem.inf
+++ b/apps/uefi/Mem.inf
@@ -78,6 +78,7 @@
../../test_pool/gic/its003.c
../../test_pool/gic/its004.c
../../test_pool/gic/its005.c
+ ../../test_pool/gic/its006.c
../../test_pool/timer/t001.c
../../test_pool/timer/t002.c
../../test_pool/timer/t003.c
diff --git a/apps/uefi/Sbsa.inf b/apps/uefi/Sbsa.inf
index beb1bf7c..9274b607 100644
--- a/apps/uefi/Sbsa.inf
+++ b/apps/uefi/Sbsa.inf
@@ -81,6 +81,7 @@
../../test_pool/gic/its003.c
../../test_pool/gic/its004.c
../../test_pool/gic/its005.c
+ ../../test_pool/gic/its006.c
../../test_pool/timer/t001.c
../../test_pool/timer/t002.c
../../test_pool/timer/t003.c
diff --git a/apps/uefi/Vbsa.inf b/apps/uefi/Vbsa.inf
index aeab2678..44a04432 100644
--- a/apps/uefi/Vbsa.inf
+++ b/apps/uefi/Vbsa.inf
@@ -80,6 +80,7 @@
../../test_pool/gic/its003.c
../../test_pool/gic/its004.c
../../test_pool/gic/its005.c
+ ../../test_pool/gic/its006.c
../../test_pool/timer/t001.c
../../test_pool/timer/t002.c
../../test_pool/timer/t003.c
diff --git a/apps/uefi/pc_bsa.inf b/apps/uefi/pc_bsa.inf
index a444a559..72180e1a 100644
--- a/apps/uefi/pc_bsa.inf
+++ b/apps/uefi/pc_bsa.inf
@@ -81,6 +81,7 @@
../../test_pool/gic/its003.c
../../test_pool/gic/its004.c
../../test_pool/gic/its005.c
+ ../../test_pool/gic/its006.c
../../test_pool/timer/t001.c
../../test_pool/timer/t002.c
../../test_pool/timer/t003.c
diff --git a/apps/uefi/xbsa_acpi.inf b/apps/uefi/xbsa_acpi.inf
index 4ec27c86..0a76177e 100644
--- a/apps/uefi/xbsa_acpi.inf
+++ b/apps/uefi/xbsa_acpi.inf
@@ -80,6 +80,7 @@
../../test_pool/gic/its003.c
../../test_pool/gic/its004.c
../../test_pool/gic/its005.c
+ ../../test_pool/gic/its006.c
../../test_pool/timer/t001.c
../../test_pool/timer/t002.c
../../test_pool/timer/t003.c
diff --git a/docs/bsa/arm_bsa_testcase_checklist.md b/docs/bsa/arm_bsa_testcase_checklist.md
index 8db46c43..d7e5cde1 100644
--- a/docs/bsa/arm_bsa_testcase_checklist.md
+++ b/docs/bsa/arm_bsa_testcase_checklist.md
@@ -1686,12 +1686,12 @@ The checklist provides information about:
| ITS_08 |
- Not Covered |
- |
- |
- |
- |
- |
+ 1548 |
+ ITS blocks in group observe same DeviceID |
+ Yes |
+ Yes |
+ No |
+ Exerciser VIP required |
| ITS_DEV_1 |
@@ -1731,11 +1731,11 @@ The checklist provides information about:
| ITS_DEV_5 |
- Not Covered |
- |
- |
- |
- |
+ 256 |
+ MSI-capable devices have DeviceID |
+ Yes |
+ Yes |
+ No |
|
@@ -2204,12 +2204,12 @@ The checklist provides information about:
| ITS_08 |
- Not Covered |
- |
- |
- |
- |
- |
+ 1548 |
+ ITS blocks in group observe same DeviceID |
+ Yes |
+ Yes |
+ No |
+ Exerciser VIP required |
| ITS_DEV_1 |
@@ -2249,11 +2249,11 @@ The checklist provides information about:
| ITS_DEV_5 |
- Not Covered |
- |
- |
- |
- |
+ 256 |
+ MSI-capable devices have DeviceID |
+ Yes |
+ Yes |
+ No |
|
@@ -2980,12 +2980,12 @@ The checklist provides information about:
| ITS_08 |
- Not Covered |
- |
- |
- |
- |
- |
+ 1548 |
+ ITS blocks in group observe same DeviceID |
+ Yes |
+ Yes |
+ No |
+ Exerciser VIP required |
| ITS_DEV_1 |
@@ -3025,11 +3025,11 @@ The checklist provides information about:
| ITS_DEV_5 |
- Not Covered |
- |
- |
- |
- |
+ 256 |
+ MSI-capable devices have DeviceID |
+ Yes |
+ Yes |
+ No |
|
@@ -3765,6 +3765,8 @@ The checklist provides information about:
- Updated PCI_MM_02 coverage with test 906.
- Added direct B_PER_07 UART Non-secure register access coverage (test 605).
- Updated B_PER_08 to include ITS Rules.
+- Updated ITS_08, ITS_DEV_5
+
- **RI_ Added:** RI_PWR_1
- Updated B_WD_02.
- Updated checklist to be consistent with I-VGLFZ.
diff --git a/docs/sbsa/arm_sbsa_testcase_checklist.md b/docs/sbsa/arm_sbsa_testcase_checklist.md
index 298168c0..d91c2784 100644
--- a/docs/sbsa/arm_sbsa_testcase_checklist.md
+++ b/docs/sbsa/arm_sbsa_testcase_checklist.md
@@ -871,12 +871,12 @@ The checklist provides information about:
| ITS_08 |
- Not Covered |
- |
- |
- |
- |
- |
+ 1548 |
+ ITS blocks in group observe same DeviceID |
+ Yes |
+ Yes |
+ No |
+ Exerciser VIP required |
| ITS_DEV_1 |
@@ -916,11 +916,11 @@ The checklist provides information about:
| ITS_DEV_5 |
- Not Covered |
- |
- |
- |
- |
+ 256 |
+ MSI-capable devices have DeviceID |
+ Yes |
+ Yes |
+ No |
|
@@ -1647,12 +1647,12 @@ The checklist provides information about:
| ITS_08 |
- Not Covered |
- |
- |
- |
- |
- |
+ 1548 |
+ ITS blocks in group observe same DeviceID |
+ Yes |
+ Yes |
+ No |
+ Exerciser VIP required |
| ITS_DEV_1 |
@@ -1692,11 +1692,11 @@ The checklist provides information about:
| ITS_DEV_5 |
- Not Covered |
- |
- |
- |
- |
+ 256 |
+ MSI-capable devices have DeviceID |
+ Yes |
+ Yes |
+ No |
|
@@ -3678,6 +3678,7 @@ The checklist provides information about:
- Updated PCI_MM_02 coverage with test 907.
- Updated S_L5SM_04, S_L6PE_08, S_L6SM_04
- Added rule S_L5PE_03
+- Updated ITS_08, ITS_DEV_5
### v26.03_SBSA_8.0.1
- **FR Added:** LVQBC, KBRZG
diff --git a/test_pool/exerciser/e035.c b/test_pool/exerciser/e035.c
index 27bcb488..8bdd92a5 100644
--- a/test_pool/exerciser/e035.c
+++ b/test_pool/exerciser/e035.c
@@ -26,9 +26,15 @@
#define TEST_RULE "ITS_04"
#define TEST_DESC "MSI-cap device can target any ITS blk "
+#define TEST_NUM_2 (ACS_EXERCISER_TEST_NUM_BASE + 48)
+#define TEST_RULE_2 "ITS_08"
+#define TEST_DESC_2 "ITS blocks in group observe same DeviceID"
+
static uint32_t irq_pending;
static uint32_t base_lpi_id = 0x204C;
static uint32_t instance;
+static uint32_t its_04_result = RESULT_SKIP(0);
+static uint32_t its_04_result_valid;
static
void
@@ -191,19 +197,29 @@ payload (void)
uint32_t
e035_entry(uint32_t num_pe)
{
+ uint32_t index;
uint32_t status = ACS_STATUS_FAIL;
/* Run test on single PE */
num_pe = 1;
+ index = val_pe_get_index_mpid(val_pe_get_mpid());
+ its_04_result_valid = 0;
val_log_context((char8_t *)__FILE__, (char8_t *)__func__, __LINE__);
status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe);
if (status != ACS_STATUS_SKIP) {
- if (val_exerciser_test_init() != ACS_STATUS_PASS)
- return val_exerciser_get_init_result(TEST_RULE);
+ if (val_exerciser_test_init() != ACS_STATUS_PASS) {
+ status = val_exerciser_get_init_result(TEST_RULE);
+ its_04_result = status;
+ its_04_result_valid = 1;
+ return status;
+ }
val_run_test_payload(TEST_NUM, num_pe, payload, 0);
}
+ its_04_result = val_get_status(index);
+ its_04_result_valid = 1;
+
/* get the result from all PE and check for failure */
status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE);
@@ -211,3 +227,44 @@ e035_entry(uint32_t num_pe)
return status;
}
+
+/* Entry for ITS_08 rule.
+ 1. ITS_04 verifies that an MSI-capable device can target every ITS block in its ITS group.
+ 2. The test programs each ITS block with the same DeviceID for the given device and then
+ triggers an MSI.
+ 3. If any ITS block in the group does not observe that same DeviceID, the MSI mapping or
+ delivery through that ITS block is expected to fail.
+ 4. Therefore, the ITS_04 runtime result also provides coverage for ITS_08.
+*/
+uint32_t
+e048_entry(uint32_t num_pe)
+{
+ uint32_t index;
+ uint32_t status = ACS_STATUS_FAIL;
+
+ /* Run test on single PE */
+ num_pe = 1;
+ index = val_pe_get_index_mpid(val_pe_get_mpid());
+
+ val_log_context((char8_t *)__FILE__, (char8_t *)__func__, __LINE__);
+ status = val_initialize_test(TEST_NUM_2, TEST_DESC_2, num_pe);
+ if (status != ACS_STATUS_SKIP) {
+ /* ITS_08 uses the test result already collected by e035/ITS_04.
+ If a valid result is not available, then run the payload for ITS_08 */
+ if (its_04_result_valid)
+ val_set_status(index, its_04_result);
+ else {
+ if (val_exerciser_test_init() != ACS_STATUS_PASS)
+ val_set_status(index, val_exerciser_get_init_result(TEST_RULE_2));
+ else
+ val_run_test_payload(TEST_NUM_2, num_pe, payload, 0);
+ }
+ }
+
+ /* get the result from all PE and check for failure */
+ status = val_check_for_error(TEST_NUM_2, num_pe, TEST_RULE_2);
+
+ val_report_status(0, ACS_END(TEST_NUM_2), NULL);
+
+ return status;
+}
diff --git a/test_pool/gic/its006.c b/test_pool/gic/its006.c
new file mode 100644
index 00000000..607ec617
--- /dev/null
+++ b/test_pool/gic/its006.c
@@ -0,0 +1,112 @@
+/** @file
+ * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved.
+ * SPDX-License-Identifier : Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+#include "acs_val.h"
+#include "acs_iovirt.h"
+#include "acs_pcie.h"
+
+#define TEST_NUM (ACS_GIC_ITS_TEST_NUM_BASE + 6)
+#define TEST_RULE "ITS_DEV_5"
+#define TEST_DESC "MSI-capable devices have DeviceID "
+
+static
+void
+payload(void)
+{
+ uint32_t bdf;
+ uint32_t status;
+ uint32_t pe_index;
+ uint32_t tbl_index;
+ uint32_t device_id;
+ uint32_t stream_id;
+ uint32_t its_id;
+ uint32_t grp_id;
+ uint32_t cap_base;
+ uint32_t test_skip = 1;
+ uint32_t test_fails = 0;
+ pcie_device_bdf_table *bdf_tbl_ptr;
+
+ pe_index = val_pe_get_index_mpid(val_pe_get_mpid());
+ bdf_tbl_ptr = val_pcie_bdf_table_ptr();
+
+ if ((!bdf_tbl_ptr) || (!bdf_tbl_ptr->num_entries)) {
+ val_print(DEBUG, "\n No entries in BDF table");
+ val_set_status(pe_index, RESULT_SKIP(1));
+ return;
+ }
+
+ /* Check all enumerated PCIe functions that can originate MSI/MSI-X. */
+ for (tbl_index = 0; tbl_index < bdf_tbl_ptr->num_entries; tbl_index++)
+ {
+ bdf = bdf_tbl_ptr->device[tbl_index].bdf;
+
+ if ((val_pcie_find_capability(bdf, PCIE_CAP, CID_MSI, &cap_base) ==
+ PCIE_CAP_NOT_FOUND) &&
+ (val_pcie_find_capability(bdf, PCIE_CAP, CID_MSIX, &cap_base) ==
+ PCIE_CAP_NOT_FOUND))
+ continue;
+
+ test_skip = 0;
+ val_print(DEBUG, "\n Checking DeviceID association for BDF : 0x%x", bdf);
+
+ /* Every device that is expected to originate MSIs is associated with a DeviceID */
+ status = val_iovirt_get_device_info(PCIE_CREATE_BDF_PACKED(bdf),
+ PCIE_EXTRACT_BDF_SEG(bdf),
+ &device_id, &stream_id, &its_id);
+ if (status) {
+ val_print(ERROR, "\n DeviceID mapping not found for BDF : 0x%x", bdf);
+ test_fails++;
+ continue;
+ }
+
+ /* We get ITS ID associated with the device. Now check if ITS ID belongs to valid ITS grp */
+ status = val_iovirt_get_its_info(ITS_GET_GRP_INDEX_FOR_ID, 0, its_id, &grp_id);
+ if (status) {
+ /* Not a failure acc to this rule but an IORT violation */
+ val_print(ERROR, "\n ITS group not found for BDF : 0x%x", bdf);
+ val_print(ERROR, " ITS ID : 0x%x", its_id);
+ }
+ }
+
+ /* Partially covered, because this test only checks PCIe devices that advertise MSI/MSI-X support.
+ The rule, however, applies to all MSI-originating devices, not just PCIe devices. */
+ if (test_skip)
+ val_set_status(pe_index, RESULT_SKIP(2));
+ else if (test_fails)
+ val_set_status(pe_index, RESULT_FAIL(test_fails));
+ else
+ val_set_status(pe_index, RESULT_PARTIAL_COVERED);
+
+}
+
+uint32_t
+its006_entry(uint32_t num_pe)
+{
+ uint32_t status = ACS_STATUS_FAIL;
+
+ num_pe = 1; //This ITS test is run on single processor
+
+ val_log_context((char8_t *)__FILE__, (char8_t *)__func__, __LINE__);
+ status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe);
+ if (status != ACS_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, TEST_RULE);
+
+ val_report_status(0, ACS_END(TEST_NUM), NULL);
+
+ return status;
+}
diff --git a/tools/cmake/infra/bsa_test.txt b/tools/cmake/infra/bsa_test.txt
index 31138c04..ec21f421 100644
--- a/tools/cmake/infra/bsa_test.txt
+++ b/tools/cmake/infra/bsa_test.txt
@@ -44,6 +44,7 @@ its002.c
its003.c
its004.c
its005.c
+its006.c
t001.c
t002.c
t003.c
diff --git a/val/include/acs_exerciser.h b/val/include/acs_exerciser.h
index 556c17cd..8669666c 100644
--- a/val/include/acs_exerciser.h
+++ b/val/include/acs_exerciser.h
@@ -173,5 +173,6 @@ uint32_t e044_entry(uint32_t num_pe);
uint32_t e045_entry(uint32_t num_pe);
uint32_t e046_entry(uint32_t num_pe);
uint32_t e047_entry(uint32_t num_pe);
+uint32_t e048_entry(uint32_t num_pe);
#endif
diff --git a/val/include/acs_gic.h b/val/include/acs_gic.h
index 65337aa9..73da4af2 100644
--- a/val/include/acs_gic.h
+++ b/val/include/acs_gic.h
@@ -1,5 +1,5 @@
/** @file
- * Copyright (c) 2016-2018, 2021, 2023-2025, Arm Limited or its affiliates. All rights reserved.
+ * Copyright (c) 2016-2018, 2021, 2023-2026, Arm Limited or its affiliates. All rights reserved.
* SPDX-License-Identifier : Apache-2.0
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -103,6 +103,7 @@ uint32_t its002_entry(uint32_t num_pe);
uint32_t its003_entry(uint32_t num_pe);
uint32_t its004_entry(uint32_t num_pe);
uint32_t its005_entry(uint32_t num_pe);
+uint32_t its006_entry(uint32_t num_pe);
uint32_t g012_entry(uint32_t num_pe);
uint32_t g013_entry(uint32_t num_pe);
diff --git a/val/include/rule_based_execution_enum.h b/val/include/rule_based_execution_enum.h
index f6c41c96..f6814218 100644
--- a/val/include/rule_based_execution_enum.h
+++ b/val/include/rule_based_execution_enum.h
@@ -669,6 +669,7 @@ typedef enum {
ITS003_ENTRY,
ITS004_ENTRY,
ITS005_ENTRY,
+ ITS006_ENTRY,
G006_ENTRY,
G007_ENTRY,
G009_ENTRY,
@@ -961,6 +962,7 @@ typedef enum {
E045_ENTRY,
E046_ENTRY,
E047_ENTRY,
+ E048_ENTRY,
P094_ENTRY,
P096_ENTRY,
P097_ENTRY,
diff --git a/val/src/bsa_execute_test.c b/val/src/bsa_execute_test.c
index a5b61a8d..ffad06f9 100644
--- a/val/src/bsa_execute_test.c
+++ b/val/src/bsa_execute_test.c
@@ -297,6 +297,7 @@ val_bsa_gic_execute_tests(uint32_t num_pe, uint32_t *g_sw_view)
status |= its003_entry(num_pe);
status |= its004_entry(num_pe);
status |= its005_entry(num_pe);
+ status |= its006_entry(num_pe);
}
view_print_info(MODULE_END);
}
@@ -901,6 +902,7 @@ val_bsa_exerciser_execute_tests(uint32_t num_pe, uint32_t *g_sw_view)
status |= e012_entry(num_pe);
status |= e013_entry(num_pe);
status |= e035_entry(num_pe);
+ status |= e048_entry(num_pe);
}
status |= e014_entry(num_pe);
diff --git a/val/src/rule_metadata.c b/val/src/rule_metadata.c
index 211373d5..9c60fcb0 100644
--- a/val/src/rule_metadata.c
+++ b/val/src/rule_metadata.c
@@ -642,6 +642,14 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = {
.flag = BASE_RULE,
.test_num = ACS_GIC_ITS_TEST_NUM_BASE + 3,
},
+ [ITS_DEV_5] = {
+ .test_entry_id = ITS006_ENTRY,
+ .module_id = GIC,
+ .rule_desc = "MSI-capable devices have DeviceID",
+ .platform_bitmask = PLATFORM_BAREMETAL | PLATFORM_UEFI,
+ .flag = BASE_RULE,
+ .test_num = ACS_GIC_ITS_TEST_NUM_BASE + 6,
+ },
[ITS_DEV_7] = {
.test_entry_id = ITS004_ENTRY,
.module_id = GIC,
@@ -1750,6 +1758,14 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = {
.flag = BASE_RULE,
.test_num = ACS_EXERCISER_TEST_NUM_BASE + 12,
},
+ [ITS_08] = {
+ .test_entry_id = E048_ENTRY,
+ .module_id = PCIE,
+ .rule_desc = "ITS blocks in group observe same DeviceID",
+ .platform_bitmask = PLATFORM_BAREMETAL | PLATFORM_UEFI,
+ .flag = BASE_RULE,
+ .test_num = ACS_EXERCISER_TEST_NUM_BASE + 48,
+ },
[ITS_DEV_4] = {
.test_entry_id = E013_ENTRY,
.module_id = PCIE,
@@ -3257,18 +3273,12 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = {
[ITS_07] = {
.module_id = PCIE,
},
- [ITS_08] = {
- .module_id = PCIE,
- },
[ITS_DEV_1] = {
.module_id = PCIE,
},
[ITS_DEV_3] = {
.module_id = PCIE,
},
- [ITS_DEV_5] = {
- .module_id = PCIE,
- },
[ITS_DEV_9] = {
.module_id = PCIE,
},
@@ -3541,6 +3551,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = {
[E045_ENTRY] = e045_entry, // used for CXL_06.
[E046_ENTRY] = e046_entry,
[E047_ENTRY] = e047_entry,
+ [E048_ENTRY] = e048_entry,
[ETE001_ENTRY] = ete001_entry,
[ETE002_ENTRY] = ete002_entry,
[ETE003_ENTRY] = ete003_entry,
@@ -3640,6 +3651,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = {
[ITS003_ENTRY] = its003_entry,
[ITS004_ENTRY] = its004_entry,
[ITS005_ENTRY] = its005_entry,
+ [ITS006_ENTRY] = its006_entry,
[M001_ENTRY] = m001_entry,
[M002_ENTRY] = m002_entry,
[M003_ENTRY] = m003_entry,
@@ -4302,6 +4314,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = {
[G002_ENTRY] = g002_entry,
[ITS002_ENTRY] = its002_entry,
[ITS005_ENTRY] = its005_entry,
+ [ITS006_ENTRY] = its006_entry,
[ITS001_ENTRY] = its001_entry,
[G005_ENTRY] = g005_entry,
[G006_ENTRY] = g006_entry, // used in wrapper.
@@ -4367,6 +4380,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = {
[E006_ENTRY] = e006_entry, // used in wrapper.
[E046_ENTRY] = e046_entry,
[E047_ENTRY] = e047_entry,
+ [E048_ENTRY] = e048_entry,
[E015_ENTRY] = e015_entry, // used in wrapper.
[E001_ENTRY] = e001_entry, // used in wrapper.
[U005_ENTRY] = u005_entry, // used in wrapper.