[Accel-config] [PATCH v4 7/7] accel-config/test: add cache flush operation support

Tony Zhu <tony.zhu at intel.com> Mon, 21 Feb 2022 09:34:23 +0800
Newsgroups dev.linux.lists.accel-config
Message-ID <[email protected]>
The Cache Flush operation flushes the processor caches at
the Destination Address.

Signed-off-by: Tony Zhu <tony.zhu(a)intel.com>
---
 test/dsa.c      | 77 +++++++++++++++++++++++++++++++++++++++++++++++++
 test/dsa.h      |  7 +++++
 test/dsa_test.c | 10 +++++++
 test/prep.c     | 46 +++++++++++++++++++++++++++++
 4 files changed, 140 insertions(+)

diff --git a/test/dsa.c b/test/dsa.c
index fa3b8d6..8bc5dd5 100644
--- a/test/dsa.c
+++ b/test/dsa.c
@@ -696,6 +696,23 @@ int init_dif_updt(struct task *tsk, int tflags, int opcode, unsigned long xfer_s
 	return DSA_STATUS_OK;
 }
 
+int init_cflush(struct task *tsk, int tflags, int opcode, unsigned long xfer_size)
+{
+	unsigned long force_align = ADDR_ALIGNMENT;
+
+	tsk->pattern = 0x0123456789abcdef;
+	tsk->opcode = opcode;
+	tsk->test_flags = tflags;
+	tsk->xfer_size = xfer_size;
+
+	tsk->dst1 = aligned_alloc(force_align, xfer_size);
+	if (!tsk->dst1)
+		return -ENOMEM;
+	memset_pattern(tsk->dst1, tsk->pattern, xfer_size);
+
+	return DSA_STATUS_OK;
+}
+
 /* this function is re-used by batch task */
 int init_task(struct task *tsk, int tflags, int opcode,
 	      unsigned long xfer_size)
@@ -755,6 +772,10 @@ int init_task(struct task *tsk, int tflags, int opcode,
 	case DSA_OPCODE_DIF_UPDT:
 		rc = init_dif_updt(tsk, tflags, opcode, xfer_size);
 		break;
+
+	case DSA_OPCODE_CFLUSH:
+		rc = init_cflush(tsk, tflags, opcode, xfer_size);
+		break;
 	}
 
 	if (rc != DSA_STATUS_OK) {
@@ -1828,6 +1849,62 @@ int dsa_dif_updt_multi_task_nodes(struct dsa_context *ctx)
 	return ret;
 }
 
+int dsa_wait_cflush(struct dsa_context *ctx, struct task *tsk)
+{
+	struct dsa_hw_desc *desc = tsk->desc;
+	struct dsa_completion_record *comp = tsk->comp;
+
+	int rc;
+
+again:
+	rc = dsa_wait_on_desc_timeout(comp, ms_timeout);
+	if (rc < 0) {
+		err("cflush desc timeout\n");
+		return DSA_STATUS_TIMEOUT;
+	}
+
+	/* re-submit if PAGE_FAULT reported by HW && BOF is off */
+	if (stat_val(comp->status) == DSA_COMP_PAGE_FAULT_NOBOF &&
+	    !(desc->flags & IDXD_OP_FLAG_BOF)) {
+		dsa_reprep_cflush(ctx, tsk);
+		goto again;
+	}
+
+	return DSA_STATUS_OK;
+}
+
+int dsa_cflush_multi_task_nodes(struct dsa_context *ctx)
+{
+	struct task_node *tsk_node = ctx->multi_task_node;
+	int ret = DSA_STATUS_OK;
+
+	while (tsk_node) {
+		tsk_node->tsk->dflags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
+		if ((tsk_node->tsk->test_flags & TEST_FLAGS_BOF) && ctx->bof)
+			tsk_node->tsk->dflags |= IDXD_OP_FLAG_BOF;
+
+		dsa_prep_cflush(tsk_node->tsk);
+		tsk_node = tsk_node->next;
+	}
+
+	tsk_node = ctx->multi_task_node;
+	while (tsk_node) {
+		dsa_desc_submit(ctx, tsk_node->tsk->desc);
+		tsk_node = tsk_node->next;
+	}
+	tsk_node = ctx->multi_task_node;
+	info("Submitted all cflush jobs\n");
+
+	while (tsk_node) {
+		ret = dsa_wait_cflush(ctx, tsk_node->tsk);
+		if (ret != DSA_STATUS_OK)
+			info("Desc: %p failed with ret: %d\n",
+			     tsk_node->tsk->desc, tsk_node->tsk->comp->status);
+		tsk_node = tsk_node->next;
+	}
+	return ret;
+}
+
 /* mismatch_expected: expect mismatched buffer with success status 0x1 */
 int task_result_verify(struct task *tsk, int mismatch_expected)
 {
diff --git a/test/dsa.h b/test/dsa.h
index 9157741..6094d5c 100644
--- a/test/dsa.h
+++ b/test/dsa.h
@@ -270,6 +270,7 @@ int init_dif_check(struct task *tsk, int tflags, int opcode, unsigned long xfer_
 int init_dif_ins(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
 int init_dif_strp(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
 int init_dif_updt(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
+int init_cflush(struct task *tsk, int tflags, int opcode, unsigned long xfer_size);
 int init_task(struct task *tsk, int tflags, int opcode,
 	      unsigned long xfer_size);
 
@@ -312,6 +313,9 @@ int dsa_dif_strp_multi_task_nodes(struct dsa_context *ctx);
 int dsa_dif_updt_multi_task_nodes(struct dsa_context *ctx);
 int dsa_wait_dif(struct dsa_context *ctx, struct task *tsk);
 
+int dsa_cflush_multi_task_nodes(struct dsa_context *ctx);
+int dsa_wait_cflush(struct dsa_context *ctx, struct task *tsk);
+
 void dsa_prep_noop(struct task *tsk);
 void dsa_prep_drain(struct task *tsk);
 void dsa_prep_memcpy(struct task *tsk);
@@ -337,6 +341,8 @@ void dsa_prep_dif_insert(struct task *tsk);
 void dsa_prep_dif_strip(struct task *tsk);
 void dsa_prep_dif_update(struct task *tsk);
 void dsa_reprep_dif(struct dsa_context *ctx, struct task *tsk);
+void dsa_prep_cflush(struct task *tsk);
+void dsa_reprep_cflush(struct dsa_context *ctx, struct task *tsk);
 
 int task_result_verify(struct task *tsk, int mismatch_expected);
 int task_result_verify_task_nodes(struct dsa_context *ctx, int mismatch_expected);
@@ -371,6 +377,7 @@ void dsa_prep_batch_dif_check(struct batch_task *btsk);
 void dsa_prep_batch_dif_insert(struct batch_task *btsk);
 void dsa_prep_batch_dif_strip(struct batch_task *btsk);
 void dsa_prep_batch_dif_update(struct batch_task *btsk);
+void dsa_prep_batch_cflush(struct batch_task *btsk);
 int dsa_wait_batch(struct batch_task *btsk);
 
 void dsa_free(struct dsa_context *ctx);
diff --git a/test/dsa_test.c b/test/dsa_test.c
index a702f75..8e8dc25 100644
--- a/test/dsa_test.c
+++ b/test/dsa_test.c
@@ -127,6 +127,10 @@ static int test_batch(struct dsa_context *ctx, size_t buf_size,
 				dsa_prep_batch_dif_update(btsk_node->btsk);
 				break;
 
+			case DSA_OPCODE_CFLUSH:
+				dsa_prep_batch_cflush(btsk_node->btsk);
+				break;
+
 			default:
 				err("Unsupported op %#x\n", bopcode);
 				return -EINVAL;
@@ -478,6 +482,11 @@ static int test_memory(struct dsa_context *ctx, size_t buf_size,
 			if (rc != DSA_STATUS_OK)
 				return rc;
 			break;
+		case DSA_OPCODE_CFLUSH:
+			rc = dsa_cflush_multi_task_nodes(ctx);
+			if (rc != DSA_STATUS_OK)
+				return rc;
+			break;
 		default:
 			err("Unsupported op %#x\n", opcode);
 			return -EINVAL;
@@ -726,6 +735,7 @@ int main(int argc, char *argv[])
 	case DSA_OPCODE_COMPARE:
 	case DSA_OPCODE_COMPVAL:
 	case DSA_OPCODE_DUALCAST:
+	case DSA_OPCODE_CFLUSH:
 		rc = test_memory(dsa, buf_size, tflags, opcode, num_desc);
 		if (rc != DSA_STATUS_OK)
 			goto error;
diff --git a/test/prep.c b/test/prep.c
index 5f85b7c..2f79030 100644
--- a/test/prep.c
+++ b/test/prep.c
@@ -720,6 +720,52 @@ void dsa_prep_batch_dif_update(struct batch_task *btsk)
 	}
 }
 
+void dsa_prep_cflush(struct task *tsk)
+{
+	info("preparing descriptor for cflush\n");
+
+	dsa_prep_desc_common(tsk->desc, tsk->opcode, (uint64_t)(tsk->dst1),
+			     (uint64_t)(tsk->src1), tsk->xfer_size, tsk->dflags);
+	tsk->desc->completion_addr = (uint64_t)(tsk->comp);
+	tsk->comp->status = 0;
+}
+
+void dsa_reprep_cflush(struct dsa_context *ctx, struct task *tsk)
+{
+	struct dsa_completion_record *compl = tsk->comp;
+	struct dsa_hw_desc *hw = tsk->desc;
+
+	info("PF addr %#lx dir %d bc %#x\n",
+	     compl->fault_addr, compl->result,
+	     compl->bytes_completed);
+
+	hw->xfer_size -= compl->bytes_completed;
+
+	hw->src_addr += compl->bytes_completed;
+
+	resolve_page_fault(compl->fault_addr, compl->status);
+
+	compl->status = 0;
+
+	dsa_desc_submit(ctx, hw);
+}
+
+void dsa_prep_batch_cflush(struct batch_task *btsk)
+{
+	int i;
+	struct task *sub_task;
+
+	for (i = 0; i < btsk->task_num; i++) {
+		sub_task = &btsk->sub_tasks[i];
+		dsa_prep_desc_common(sub_task->desc, sub_task->opcode,
+				     (uint64_t)(sub_task->dst1),
+				     (uint64_t)(sub_task->src1),
+				     sub_task->xfer_size, sub_task->dflags);
+		sub_task->desc->completion_addr = (uint64_t)(sub_task->comp);
+		sub_task->comp->status = 0;
+	}
+}
+
 void dsa_prep_batch(struct batch_task *btsk, unsigned long desc_flags)
 {
 	struct task *ctsk = btsk->core_task;
-- 
2.27.0