[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