feat(realm_host_mgmt): support multiple devices in DA test
Connect all off-chip pcie devices with TSM. This setup secure session,
IDE and programs DVSEC RMEDA.
Host assigns all devices that are connected with TSM to a Realm. And
Realm locks and accepts the assigned device.
This patch adds host_da_workflow_on_all_offchip_devices testcase.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Id8ea54f9c9aad45787a0aac106a9260f68a63ec5
diff --git a/include/runtime_services/host_realm_managment/host_da_helper.h b/include/runtime_services/host_realm_managment/host_da_helper.h
index e60948d..f650bef 100644
--- a/include/runtime_services/host_realm_managment/host_da_helper.h
+++ b/include/runtime_services/host_realm_managment/host_da_helper.h
@@ -8,6 +8,7 @@
#define HOST_DA_HELPER_H
#include <host_realm_rmi.h>
+#include <pcie.h>
/*
* Skip DA test if any of the below check is true
@@ -35,6 +36,9 @@
/* SPDM_MAX_CERTIFICATE_CHAIN_SIZE is 64KB */
#define HOST_PDEV_CERT_LEN_MAX (64 * 1024)
+/* todo: This macro can come from platform layer */
+#define HOST_PDEV_MAX 32
+
/*
* Measurement max supported is 4KB.
* todo: This will be increased if device supports returning more measurements
@@ -68,9 +72,11 @@
size_t public_key_metadata_len;
unsigned char public_key_sig_algo;
- /* PCIe details: bdf, DOE, Stream id, IO range */
- uint32_t bdf;
- uint32_t doe_cap_base;
+ /* Is this device connected to TSM */
+ bool is_connected_to_tsm;
+
+ /* The PCIe device for this host_pdev */
+ pcie_dev_t *dev;
};
struct host_vdev {
@@ -105,16 +111,18 @@
size_t ifc_report_len;
};
+void host_pdevs_init(void);
+bool is_host_pdev_independently_attested(struct host_pdev *h_pdev);
int host_create_realm_with_feat_da(struct realm *realm);
int host_pdev_create(struct host_pdev *h_pdev);
int host_pdev_reclaim(struct host_pdev *h_pdev);
int host_pdev_setup(struct host_pdev *h_pdev);
int host_pdev_transition(struct host_pdev *h_pdev, unsigned char to_state);
-int host_assign_vdev_to_realm(struct realm *realm, struct host_pdev *h_pdev,
- struct host_vdev *h_vdev);
-int host_unassign_vdev_from_realm(struct realm *realm, struct host_pdev *h_pdev,
- struct host_vdev *h_vdev);
+int host_assign_vdev_to_realm(struct realm *realm, struct host_vdev *h_vdev,
+ unsigned long tdi_id, void *pdev_ptr);
+int host_unassign_vdev_from_realm(struct realm *realm, struct host_vdev *h_vdev);
+
u_register_t host_dev_mem_map(struct realm *realm, u_register_t dev_pa,
long map_level, u_register_t *dev_ipa);
diff --git a/include/runtime_services/host_realm_managment/host_realm_rmi.h b/include/runtime_services/host_realm_managment/host_realm_rmi.h
index 18e47a1..05570fd 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -1234,7 +1234,7 @@
/* Bits16: Segment ID */
SET_MEMBER_RMI(unsigned short segment_id, 0x10, 0x18);
/* Address: ECAM base address of the PCIe configuration space */
- SET_MEMBER_RMI(unsigned short ecam_addr, 0x18, 0x20);
+ SET_MEMBER_RMI(unsigned long ecam_addr, 0x18, 0x20);
/* Bits16: Root Port identifier */
SET_MEMBER_RMI(unsigned short root_id, 0x20, 0x28);
/* UInt64: Certificate identifier */
diff --git a/realm/realm_da.c b/realm/realm_da.c
index c442b21..a0e812c 100644
--- a/realm/realm_da.c
+++ b/realm/realm_da.c
@@ -62,6 +62,11 @@
return false;
}
+ realm_printf("======================================\n");
+ realm_printf("Realm: Lock -> Accept -> Unlock device: (bdf: 0x%x)\n",
+ rdev->id);
+ realm_printf("======================================\n");
+
rsi_rc = realm_rsi_rdev_get_state(rdev);
if (rsi_rc != RSI_SUCCESS) {
return false;
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_da_helper.c b/tftf/tests/runtime_services/host_realm_managment/host_da_helper.c
index 8bcf370..c9a82c2 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_da_helper.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_da_helper.c
@@ -6,16 +6,17 @@
*/
#include <stdint.h>
-
#include <arch_features.h>
#include <debug.h>
#include <heap/page_alloc.h>
#include <host_da_helper.h>
#include <host_realm_helper.h>
#include <host_realm_mem_layout.h>
+#include <pcie_spec.h>
#include <pcie_doe.h>
-extern struct host_pdev gbl_host_pdev;
+extern int gbl_host_pdev_count;
+extern struct host_pdev gbl_host_pdevs[32];
extern struct host_vdev gbl_host_vdev;
static const char * const pdev_state_str[] = {
@@ -28,7 +29,7 @@
"RMI_PDEV_STATE_ERROR"
};
-struct host_vdev *find_host_vdev_from_id(unsigned long vdev_id)
+static struct host_vdev *find_host_vdev_from_id(unsigned long vdev_id)
{
struct host_vdev *h_vdev = &gbl_host_vdev;
@@ -39,18 +40,23 @@
return NULL;
}
-struct host_pdev *find_host_pdev_from_pdev_ptr(unsigned long pdev_ptr)
+static struct host_pdev *find_host_pdev_from_pdev_ptr(unsigned long pdev_ptr)
{
- struct host_pdev *h_pdev = &gbl_host_pdev;
+ uint32_t i;
+ struct host_pdev *h_pdev;
- if (h_pdev->pdev == (void *)pdev_ptr) {
- return h_pdev;
+ for (i = 0; i < gbl_host_pdev_count; i++) {
+ h_pdev = &gbl_host_pdevs[i];
+
+ if (h_pdev->pdev == (void *)pdev_ptr) {
+ return h_pdev;
+ }
}
return NULL;
}
-struct host_vdev *find_host_vdev_from_vdev_ptr(unsigned long vdev_ptr)
+static struct host_vdev *find_host_vdev_from_vdev_ptr(unsigned long vdev_ptr)
{
struct host_vdev *h_vdev = &gbl_host_vdev;
@@ -122,9 +128,11 @@
pdev_params->flags = h_pdev->pdev_flags;
pdev_params->cert_id = h_pdev->cert_slot_id;
- pdev_params->pdev_id = h_pdev->bdf;
+ pdev_params->pdev_id = h_pdev->dev->bdf;
pdev_params->num_aux = h_pdev->pdev_aux_num;
pdev_params->hash_algo = h_pdev->pdev_hash_algo;
+ pdev_params->root_id = h_pdev->dev->rp_dev->bdf;
+ pdev_params->ecam_addr = h_pdev->dev->ecam_base;
for (i = 0; i < h_pdev->pdev_aux_num; i++) {
pdev_params->aux[i] = (uintptr_t)h_pdev->pdev_aux[i];
}
@@ -340,7 +348,8 @@
}
resp_len = 0UL;
- rc = pcie_doe_communicate(doe_header, h_pdev->bdf, h_pdev->doe_cap_base,
+ rc = pcie_doe_communicate(doe_header, h_pdev->dev->bdf,
+ h_pdev->dev->doe_cap_base,
(void *)dcomm_enter->req_addr,
dcomm_exit->req_len,
(void *)dcomm_enter->resp_addr, &resp_len);
@@ -493,7 +502,10 @@
u_register_t ret, count;
int i;
- memset(h_pdev, 0, sizeof(struct host_pdev));
+ /* RCiEP devices not supported by RMM */
+ if (h_pdev->dev->dp_type == RCiEP) {
+ return -1;
+ }
/* Allocate granule for PDEV and delegate */
h_pdev->pdev = page_alloc(PAGE_SIZE);
@@ -512,10 +524,20 @@
* Off chip PCIe device - set flags as non coherent device protected by
* end to end IDE, with SPDM.
*/
- h_pdev->pdev_flags = (INPLACE(RMI_PDEV_FLAGS_SPDM, RMI_PDEV_SPDM_TRUE) |
- INPLACE(RMI_PDEV_FLAGS_IDE, RMI_PDEV_IDE_TRUE) |
- INPLACE(RMI_PDEV_FLAGS_COHERENT,
- RMI_PDEV_COHERENT_FALSE));
+ h_pdev->pdev_flags = 0;
+
+ /* Set IDE based on device capability */
+ if (pcie_dev_has_ide(h_pdev->dev)) {
+ h_pdev->pdev_flags |= INPLACE(RMI_PDEV_FLAGS_IDE,
+ RMI_PDEV_IDE_TRUE);
+ }
+
+ /* Supports SPDM */
+ h_pdev->pdev_flags |= INPLACE(RMI_PDEV_FLAGS_SPDM, RMI_PDEV_SPDM_TRUE);
+
+ /* Not a coherent device */
+ h_pdev->pdev_flags |= INPLACE(RMI_PDEV_FLAGS_COHERENT,
+ RMI_PDEV_COHERENT_FALSE);
/* Get num of aux granules required for this PDEV */
ret = host_rmi_pdev_aux_count(h_pdev->pdev_flags, &count);
@@ -606,7 +628,6 @@
return -1;
}
-
/*
* Stop PDEV and ternimate secure session and call PDEV destroy
*/
@@ -642,10 +663,13 @@
ERROR("Aux granule undelegate failed 0x%lx\n", ret);
result = -1;
}
+
+ h_pdev->pdev_aux[i] = NULL;
}
/* Undelegate PDEV granule */
ret = host_rmi_granule_undelegate((u_register_t)h_pdev->pdev);
+ h_pdev->pdev = NULL;
if (ret != RMI_SUCCESS) {
ERROR("PDEV undelegate failed 0x%lx\n", ret);
result = -1;
@@ -683,7 +707,8 @@
* response buffer, VDEV AUX granules and memory required to device
* measurements, interface report.
*/
-static int host_vdev_setup(struct host_pdev *h_pdev, struct host_vdev *h_vdev)
+static int host_vdev_setup(struct host_vdev *h_vdev, unsigned long tdi_id,
+ void *pdev_ptr)
{
u_register_t ret;
@@ -694,9 +719,9 @@
* the VMM view of vdev_id and Realm view of device_id must match.
*/
h_vdev->vdev_id = 0UL;
- h_vdev->tdi_id = h_pdev->bdf;
+ h_vdev->tdi_id = tdi_id;
h_vdev->flags = 0UL;
- h_vdev->pdev_ptr = h_pdev->pdev;
+ h_vdev->pdev_ptr = pdev_ptr;
/* Allocate granule for VDEV and delegate */
h_vdev->vdev_ptr = (void *)page_alloc(PAGE_SIZE);
@@ -751,15 +776,14 @@
return -1;
}
-int host_assign_vdev_to_realm(struct realm *realm,
- struct host_pdev *h_pdev,
- struct host_vdev *h_vdev)
+int host_assign_vdev_to_realm(struct realm *realm, struct host_vdev *h_vdev,
+ unsigned long tdi_id, void *pdev_ptr)
{
struct rmi_vdev_params *vdev_params;
u_register_t ret;
int rc;
- rc = host_vdev_setup(h_pdev, h_vdev);
+ rc = host_vdev_setup(h_vdev, tdi_id, pdev_ptr);
if (rc != 0) {
return rc;
}
@@ -778,12 +802,12 @@
* This is TDI id, this must be same as PDEV ID for assigning the whole
* device.
*/
- vdev_params->tdi_id = h_pdev->bdf;
+ vdev_params->tdi_id = tdi_id;
vdev_params->flags = h_vdev->flags;
vdev_params->num_aux = 0UL;
- ret = host_rmi_vdev_create(realm->rd, (u_register_t)h_pdev->pdev,
+ ret = host_rmi_vdev_create(realm->rd, (u_register_t)pdev_ptr,
(u_register_t)h_vdev->vdev_ptr,
(u_register_t)vdev_params);
if (ret != RMI_SUCCESS) {
@@ -794,10 +818,9 @@
return 0;
}
-int host_unassign_vdev_from_realm(struct realm *realm,
- struct host_pdev *h_pdev,
- struct host_vdev *h_vdev)
+int host_unassign_vdev_from_realm(struct realm *realm, struct host_vdev *h_vdev)
{
+ struct host_pdev *h_pdev;
u_register_t ret, state;
int rc;
@@ -818,6 +841,9 @@
return -1;
}
+ h_pdev = find_host_pdev_from_pdev_ptr((unsigned long)h_vdev->pdev_ptr);
+ assert(h_pdev);
+
/* Do VDEV communicate to move VDEV from STOPPING to STOPPED state */
rc = host_dev_communicate(h_pdev, h_vdev, RMI_VDEV_STATE_STOPPED);
if (rc != 0) {
@@ -825,14 +851,15 @@
return rc;
}
- ret = host_rmi_vdev_destroy(realm->rd, (u_register_t)h_pdev->pdev,
- (u_register_t)h_vdev->vdev_ptr);
+ ret = host_rmi_vdev_destroy(realm->rd,
+ (u_register_t)h_vdev->pdev_ptr,
+ (u_register_t)h_vdev->vdev_ptr);
if (ret != RMI_SUCCESS) {
ERROR("VDEV destroy failed\n");
return -1;
}
- ret = host_rmi_granule_undelegate((u_register_t)(u_register_t)h_vdev->vdev_ptr);
+ ret = host_rmi_granule_undelegate((u_register_t)h_vdev->vdev_ptr);
if (ret != RMI_SUCCESS) {
ERROR("VDEV undelegate failed\n");
return -1;
@@ -921,3 +948,83 @@
*dev_ipa = map_addr;
return REALM_SUCCESS;
}
+
+bool is_host_pdev_independently_attested(struct host_pdev *h_pdev)
+{
+ assert(h_pdev);
+ assert(h_pdev->dev);
+
+ if ((pcie_dev_has_doe(h_pdev->dev)) &&
+ (pcie_dev_has_ide(h_pdev->dev)) &&
+ (h_pdev->dev->rp_dev != NULL) &&
+ (pcie_dev_has_ide(h_pdev->dev->rp_dev)) &&
+ (pcie_dev_has_dvsec_rmeda(h_pdev->dev->rp_dev))) {
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Find all PCIe off-chip devices that confimrs to TEE-IO standards
+ * Devices that supports DOE, IDE, TDISP with RootPort that supports
+ * RME DA are initlized in host_pdevs[]
+ */
+void host_pdevs_init(void)
+{
+ static bool gbl_host_pdevs_init_done;
+ pcie_device_bdf_table_t *bdf_table;
+ pcie_dev_t *dev;
+ uint32_t i;
+ uint32_t cnt = 0;
+
+ if (gbl_host_pdevs_init_done) {
+ return;
+ }
+
+ /* When called for the first time this does PCIe enumeration */
+ pcie_init();
+
+ INFO("Initializing host_pdevs\n");
+ bdf_table = pcie_get_bdf_table();
+ if ((bdf_table == NULL) || (bdf_table->num_entries == 0)) {
+ goto out_init;
+ }
+
+ for (i = 0; i < bdf_table->num_entries; i++) {
+ dev = &bdf_table->device[i];
+
+ if ((dev->dp_type != EP) && (dev->dp_type != RCiEP)) {
+ continue;
+ }
+
+ if ((dev->dp_type == EP) && (dev->rp_dev == NULL)) {
+ INFO("No RP found for Device %x:%x.%x\n",
+ PCIE_EXTRACT_BDF_BUS(dev->bdf),
+ PCIE_EXTRACT_BDF_DEV(dev->bdf),
+ PCIE_EXTRACT_BDF_FUNC(dev->bdf));
+ continue;
+ }
+
+ /*
+ * Skip VF in multi function device as it can't be treated as
+ * PDEV
+ */
+ if (PCIE_EXTRACT_BDF_FUNC(dev->bdf) != 0) {
+ continue;
+ }
+
+ /* Initialize host_pdev */
+ gbl_host_pdevs[cnt].dev = dev;
+ cnt++;
+
+ if (cnt == HOST_PDEV_MAX) {
+ WARN("Max host_pdev count reached.\n");
+ break;
+ }
+ }
+
+out_init:
+ gbl_host_pdevs_init_done = true;
+ gbl_host_pdev_count = cnt;
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_rmi_da_flow.c b/tftf/tests/runtime_services/host_realm_managment/host_rmi_da_flow.c
index 96f79a7..5b41e55 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_rmi_da_flow.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_rmi_da_flow.c
@@ -20,9 +20,34 @@
#include <spdm.h>
#include <test_helpers.h>
-struct host_pdev gbl_host_pdev;
+int gbl_host_pdev_count;
+struct host_pdev gbl_host_pdevs[HOST_PDEV_MAX];
struct host_vdev gbl_host_vdev;
+static test_result_t tsm_disconnect_device(struct host_pdev *h_pdev)
+{
+ int rc;
+
+ assert(h_pdev->is_connected_to_tsm);
+
+ INFO("===========================================\n");
+ INFO("Host: TSM disconnect device: (0x%x) %x:%x.%x\n",
+ h_pdev->dev->bdf,
+ PCIE_EXTRACT_BDF_BUS(h_pdev->dev->bdf),
+ PCIE_EXTRACT_BDF_DEV(h_pdev->dev->bdf),
+ PCIE_EXTRACT_BDF_FUNC(h_pdev->dev->bdf));
+ INFO("===========================================\n");
+
+ rc = host_pdev_reclaim(h_pdev);
+ if (rc != 0) {
+ return TEST_RESULT_FAIL;
+ }
+
+ h_pdev->is_connected_to_tsm = false;
+
+ return TEST_RESULT_SUCCESS;
+}
+
/*
* This invokes various RMI calls related to PDEV, VDEV management that does
* PDEV create/communicate/set_key/abort/stop/destroy and assigns the device
@@ -31,58 +56,27 @@
* 1. Create a Realm with DA feature enabled
* 2. Find a known PCIe endpoint and connect with TSM to get_cert and establish
* secure session
- * 3. Assign the PCIe endpoint (a PF) to the Realm
- * 4. Call Realm to do DA related RSI calls
- * 5. Unassign the PCIe endpoint from the Realm
- * 6. Delete the Realm
- * 7. Reclaim the PCIe TDI from TSM
*/
-test_result_t host_invoke_rmi_da_flow(void)
+static test_result_t tsm_connect_device(struct host_pdev *h_pdev)
{
- u_register_t rmi_feat_reg0;
- uint32_t pdev_bdf, doe_cap_base;
- struct host_pdev *h_pdev;
- struct host_vdev *h_vdev;
- uint8_t public_key_algo;
int rc;
- bool realm_rc;
- struct realm realm;
- test_result_t result = TEST_RESULT_FAIL;
+ uint8_t public_key_algo;
- SKIP_DA_TEST_IF_PREREQS_NOT_MET(rmi_feat_reg0);
- SKIP_TEST_IF_DOE_NOT_SUPPORTED(pdev_bdf, doe_cap_base);
-
- INFO("DA on bdf: 0x%x, doe_cap_base: 0x%x\n", pdev_bdf, doe_cap_base);
-
- /*
- * Create a Realm with DA feature enabled
- *
- * todo: creating this after host_pdev_setup causes Realm create to
- * fail.
- */
- rc = host_create_realm_with_feat_da(&realm);
- if (rc != 0) {
- INFO("Realm create with feat_da failed\n");
- return TEST_RESULT_FAIL;
- }
-
- INFO("Realm created with feat_da enabled\n");
-
- h_pdev = &gbl_host_pdev;
- h_vdev = &gbl_host_vdev;
+ INFO("======================================\n");
+ INFO("Host: TSM connect device: (0x%x) %x:%x.%x\n",
+ h_pdev->dev->bdf,
+ PCIE_EXTRACT_BDF_BUS(h_pdev->dev->bdf),
+ PCIE_EXTRACT_BDF_DEV(h_pdev->dev->bdf),
+ PCIE_EXTRACT_BDF_FUNC(h_pdev->dev->bdf));
+ INFO("======================================\n");
/* Allocate granules. Skip DA ABIs if host_pdev_setup fails */
rc = host_pdev_setup(h_pdev);
if (rc == -1) {
- INFO("host_pdev_setup failed.\n");
- (void)host_destroy_realm(&realm);
+ ERROR("host_pdev_setup failed.\n");
return TEST_RESULT_FAIL;
}
- /* todo: move to tdi_pdev_setup */
- h_pdev->bdf = pdev_bdf;
- h_pdev->doe_cap_base = doe_cap_base;
-
/* Call rmi_pdev_create to transition PDEV to STATE_NEW */
rc = host_pdev_transition(h_pdev, RMI_PDEV_STATE_NEW);
if (rc != 0) {
@@ -123,71 +117,223 @@
/* Call rmi_pdev_set_key transition PDEV to HAS_KEY */
rc = host_pdev_transition(h_pdev, RMI_PDEV_STATE_HAS_KEY);
if (rc != 0) {
- INFO("PDEV transition: PDEV_NEEDS_KEY -> PDEV_HAS_KEY failed\n");
+ ERROR("PDEV transition: PDEV_NEEDS_KEY -> PDEV_HAS_KEY failed\n");
goto err_pdev_reclaim;
}
/* Call rmi_pdev_comminucate to transition PDEV to READY state */
rc = host_pdev_transition(h_pdev, RMI_PDEV_STATE_READY);
if (rc != 0) {
- INFO("PDEV transition: PDEV_HAS_KEY -> PDEV_READY failed\n");
+ ERROR("PDEV transition: PDEV_HAS_KEY -> PDEV_READY failed\n");
goto err_pdev_reclaim;
}
-
- /*
- * 3 Assign VDEV (the PCIe endpoint) from the Realm
- */
- rc = host_assign_vdev_to_realm(&realm, h_pdev, h_vdev);
- if (rc != 0) {
- INFO("VDEV assign to realm failed\n");
- /* TF-RMM has support till here. Change error code temporarily */
- result = TEST_RESULT_SUCCESS;
- goto err_pdev_reclaim;
- }
-
- /*
- * 4 Call Realm to do DA related RSI calls
- */
- realm_rc = host_enter_realm_execute(&realm, REALM_DA_RSI_CALLS,
- RMI_EXIT_HOST_CALL, 0U);
- if (!realm_rc) {
- INFO("Realm DA_RSI_CALLS failed\n");
- goto err_pdev_reclaim;
- }
-
- /*
- * 5 Unassign VDEV (the PCIe endpoint) from the Realm
- */
- rc = host_unassign_vdev_from_realm(&realm, h_pdev, h_vdev);
- if (rc != 0) {
- INFO("VDEV unassign to realm failed\n");
- goto err_pdev_reclaim;
- }
-
- /*
- * 6 Destroy the Realm
- */
- if (!host_destroy_realm(&realm)) {
- INFO("Realm destroy failed\n");
- (void)host_pdev_reclaim(h_pdev);
- return TEST_RESULT_FAIL;
- }
-
- /*
- * 7 Reclaim PDEV (the PCIe TDI) from TSM
- */
- rc = host_pdev_reclaim(h_pdev);
- if (rc != 0) {
- INFO("Reclaim PDEV from TSM failed\n");
- return TEST_RESULT_FAIL;
- }
+ h_pdev->is_connected_to_tsm = true;
return TEST_RESULT_SUCCESS;
err_pdev_reclaim:
- (void)host_destroy_realm(&realm);
(void)host_pdev_reclaim(h_pdev);
+
+ return TEST_RESULT_FAIL;
+}
+
+/* Iterate thorough all host_pdevs and try to connect to TSM */
+static test_result_t tsm_connect_devices(void)
+{
+ uint32_t i;
+ int count = 0;
+ struct host_pdev *h_pdev;
+ test_result_t result = TEST_RESULT_SKIPPED;
+
+ for (i = 0; i < gbl_host_pdev_count; i++) {
+ h_pdev = &gbl_host_pdevs[i];
+
+ if (!is_host_pdev_independently_attested(h_pdev)) {
+ continue;
+ }
+
+ result = tsm_connect_device(h_pdev);
+ if (result != TEST_RESULT_SUCCESS) {
+ ERROR("tsm_connect_device: 0x%x failed\n",
+ h_pdev->dev->bdf);
+ break;
+ }
+
+ count++;
+ }
+
+ if (count != 0U) {
+ INFO("%d devices connected to TSM\n", count);
+ } else {
+ INFO("No device connected to TSM\n");
+ }
+
+ return result;
+}
+
+/* Iterate thorough all connected host_pdevs and disconnect from TSM */
+static test_result_t tsm_disconnect_devices(void)
+{
+ uint32_t i;
+ struct host_pdev *h_pdev;
+ test_result_t rc;
+ bool return_error = false;
+
+ for (i = 0; i < gbl_host_pdev_count; i++) {
+ h_pdev = &gbl_host_pdevs[i];
+
+ if (h_pdev->is_connected_to_tsm) {
+ rc = tsm_disconnect_device(h_pdev);
+ if (rc != TEST_RESULT_SUCCESS) {
+ /* Set error, continue with other devices */
+ return_error = true;
+ }
+ }
+ }
+
+ if (return_error) {
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
+
+static test_result_t realm_assign_unassign_device(struct realm *realm_ptr,
+ struct host_vdev *h_vdev,
+ unsigned long tdi_id,
+ void *pdev_ptr)
+{
+ int rc;
+ bool realm_rc;
+
+ /* Assign VDEV */
+ INFO("======================================\n");
+ INFO("Host: Assign device: (0x%x) %x:%x.%x to Realm \n",
+ (uint32_t)tdi_id,
+ PCIE_EXTRACT_BDF_BUS((uint32_t)tdi_id),
+ PCIE_EXTRACT_BDF_DEV((uint32_t)tdi_id),
+ PCIE_EXTRACT_BDF_FUNC((uint32_t)tdi_id));
+ INFO("======================================\n");
+
+ rc = host_assign_vdev_to_realm(realm_ptr, h_vdev, tdi_id, pdev_ptr);
+ if (rc != 0) {
+ ERROR("VDEV assign to realm failed\n");
+ /* TF-RMM has support till here. Change error code temporarily */
+ return TEST_RESULT_SUCCESS;
+ /* return TEST_RESULT_FAIL */
+ }
+
+ /* Enter Realm. Lock -> Accept -> Unlock the assigned device */
+ realm_rc = host_enter_realm_execute(realm_ptr, REALM_DA_RSI_CALLS,
+ RMI_EXIT_HOST_CALL, 0U);
+
+ /* Unassign VDEV */
+ INFO("======================================\n");
+ INFO("Host: Unassign device: (0x%x) %x:%x.%x from Realm \n",
+ (uint32_t)tdi_id,
+ PCIE_EXTRACT_BDF_BUS((uint32_t)tdi_id),
+ PCIE_EXTRACT_BDF_DEV((uint32_t)tdi_id),
+ PCIE_EXTRACT_BDF_FUNC((uint32_t)tdi_id));
+ INFO("======================================\n");
+
+ rc = host_unassign_vdev_from_realm(realm_ptr, h_vdev);
+ if (rc != 0) {
+ ERROR("VDEV unassign to realm failed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ if (!realm_rc) {
+ ERROR("Realm DA_RSI_CALLS failed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
+
+static test_result_t
+realm_assign_unassign_devices(struct realm *realm_ptr)
+{
+ uint32_t i;
+ test_result_t rc;
+ struct host_pdev *h_pdev;
+ struct host_vdev *h_vdev;
+
+ for (i = 0; i < gbl_host_pdev_count; i++) {
+ h_pdev = &gbl_host_pdevs[i];
+
+ if (h_pdev->is_connected_to_tsm) {
+ h_vdev = &gbl_host_vdev;
+
+ rc = realm_assign_unassign_device(realm_ptr, h_vdev,
+ h_pdev->dev->bdf,
+ h_pdev->pdev);
+ if (rc != TEST_RESULT_SUCCESS) {
+ break;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * Iterate thorugh all host_pdevs and do
+ * TSM connect
+ * TSM disconnect
+ */
+test_result_t host_da_workflow_on_all_offchip_devices(void)
+{
+ int rc;
+ struct realm realm;
+ test_result_t result;
+ bool return_error = false;
+ u_register_t rmi_feat_reg0;
+
+ SKIP_DA_TEST_IF_PREREQS_NOT_MET(rmi_feat_reg0);
+ host_pdevs_init();
+
+ /*
+ * Create a Realm with DA feature enabled
+ *
+ * todo: creating this after host_pdev_setup causes Realm create to
+ * fail.
+ */
+ rc = host_create_realm_with_feat_da(&realm);
+ if (rc != 0) {
+ ERROR("Realm create with feat_da failed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Connect all devices with TSM */
+ result = tsm_connect_devices();
+ if (result == TEST_RESULT_SKIPPED) {
+ goto out_rm_realm;
+ } else if (result != TEST_RESULT_SUCCESS) {
+ return_error = true;
+ }
+
+ /* Assign all TSM connected devices to a Realm */
+ result = realm_assign_unassign_devices(&realm);
+ if (result != TEST_RESULT_SUCCESS) {
+ return_error = true;
+ }
+
+ result = tsm_disconnect_devices();
+ if (result != TEST_RESULT_SUCCESS) {
+ return_error = true;
+ }
+
+out_rm_realm:
+ /* Destroy the Realm */
+ if (!host_destroy_realm(&realm)) {
+ return_error = true;
+ }
+
+ if (return_error) {
+ result = TEST_RESULT_FAIL;
+ }
+
return result;
}
@@ -205,6 +351,8 @@
return TEST_RESULT_SKIPPED;
}
+ host_pdevs_init();
+
/* Initialize Host NS heap memory */
ret = page_pool_init((u_register_t)PAGE_POOL_BASE,
(u_register_t)PAGE_POOL_MAX_SIZE);
@@ -213,7 +361,7 @@
return TEST_RESULT_FAIL;
}
- h_pdev = &gbl_host_pdev;
+ h_pdev = &gbl_host_pdevs[0];
/*
* Call rmi_pdev_create with invalid pdev, expect an error
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index 064f988..c9dc0cb 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -173,8 +173,8 @@
<!-- Test cases related to Dev Mem Map and Unmap -->
<testcase name="Realm payload Dev Mem Map and Unmap"
function="host_realm_dev_mem_map_unmap" />
- <!-- Invoke RMI calls related to DA PDEV/VDEV management -->
- <testcase name="Invoke RMI DA ABIs "
- function="host_invoke_rmi_da_flow" />
+ <!-- Invoke DA workflow on PCIe off-chip device -->
+ <testcase name="DA workflow on all PCIe off-chip devices"
+ function="host_da_workflow_on_all_offchip_devices" />
</testsuite>
</testsuites>