blob: 5308d933c1e592b5f8281fd5cea0a8a851df06d6 [file] [log] [blame]
Madhukar Pappireddy172523b2020-12-31 19:25:33 -06001/*
Olivier Depreze71ec9c2022-02-28 18:57:26 +01002 * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
Madhukar Pappireddy172523b2020-12-31 19:25:33 -06003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdint.h>
8
Olivier Depreze71ec9c2022-02-28 18:57:26 +01009#include <assert.h>
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060010#include "cactus.h"
Olivier Depreze71ec9c2022-02-28 18:57:26 +010011#include <arch_helpers.h>
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060012#include "cactus_message_loop.h"
Daniel Boulbyf3da5912022-04-01 12:31:52 +010013#include <sp_platform_def.h>
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060014#include "cactus_test_cmds.h"
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060015#include <debug.h>
16#include <ffa_helpers.h>
17#include <mmio.h>
18#include "smmuv3_test_engine.h"
19#include <sp_helpers.h>
Daniel Boulbyf3da5912022-04-01 12:31:52 +010020#include "sp_tests.h"
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060021#include <spm_common.h>
22
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060023/* Miscellaneous */
24#define NO_SUBSTREAMID (0xFFFFFFFFU)
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060025#define LOOP_COUNT (5000U)
26
Olivier Depreze71ec9c2022-02-28 18:57:26 +010027static bool run_testengine(uint32_t operation, uintptr_t source_addr,
28 uintptr_t target_addr, size_t transfer_size,
29 uint32_t attributes)
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060030{
Olivier Depreze71ec9c2022-02-28 18:57:26 +010031 const uint32_t streamID_list[] = { 0U, 1U };
32 uintptr_t begin_addr;
33 uintptr_t end_addr;
34 uintptr_t dest_addr;
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060035 uint32_t status;
Olivier Depreze71ec9c2022-02-28 18:57:26 +010036 uint32_t f;
37 uint32_t attempts;
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060038
Olivier Depreze71ec9c2022-02-28 18:57:26 +010039 assert(operation == ENGINE_MEMCPY || operation == ENGINE_RAND48);
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060040
41 for (f = 0U; f < FRAME_COUNT; f++) {
Olivier Depreze71ec9c2022-02-28 18:57:26 +010042 begin_addr = source_addr + (transfer_size * f);
43 end_addr = begin_addr + transfer_size - 1U;
44
45 if (operation == ENGINE_MEMCPY) {
46 dest_addr = target_addr + (transfer_size * f);
47 } else {
48 dest_addr = 0;
49 }
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060050
51 /* Initiate DMA sequence */
52 mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), PCTRL_OFF, 0);
53 mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), DOWNSTREAM_PORT_OFF, 0);
54 mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), STREAM_ID_OFF, streamID_list[f%2]);
55 mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), SUBSTREAM_ID_OFF, NO_SUBSTREAMID);
56
57 mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), UCTRL_OFF, 0);
Olivier Depreze71ec9c2022-02-28 18:57:26 +010058 mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), ATTR_OFF, attributes);
59
60 if (operation == ENGINE_RAND48) {
61 mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), SEED_OFF, (f + 1) * 42);
62 }
63
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060064 mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), BEGIN_OFF, begin_addr);
65 mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), END_CTRL_OFF, end_addr);
66
67 /* Legal values for stride: 1 and any multiples of 8 */
68 mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), STRIDE_OFF, 1);
69 mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), UDATA_OFF, dest_addr);
70
Olivier Depreze71ec9c2022-02-28 18:57:26 +010071 mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF, operation);
72 VERBOSE("SMMUv3TestEngine: waiting completion for frame: %u\n", f);
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060073
74 /*
75 * It is guaranteed that a read of "cmd" fields after writing to it will
76 * immediately return ENGINE_FRAME_MISCONFIGURED if the command was
77 * invalid.
78 */
79 if (mmio_read32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF) == ENGINE_MIS_CFG) {
Olivier Depreze71ec9c2022-02-28 18:57:26 +010080 ERROR("SMMUv3TestEngine: misconfigured for frame: %u\n", f);
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060081 return false;
82 }
83
Olivier Depreze71ec9c2022-02-28 18:57:26 +010084 /* Wait for operation to be complete */
85 attempts = 0U;
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060086 while (attempts++ < LOOP_COUNT) {
87 status = mmio_read32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF);
88 if (status == ENGINE_HALTED) {
89 break;
90 } else if (status == ENGINE_ERROR) {
Olivier Depreze71ec9c2022-02-28 18:57:26 +010091 ERROR("SMMUv3: test failed, engine error.\n");
Madhukar Pappireddy172523b2020-12-31 19:25:33 -060092 return false;
93 }
94
95 /*
96 * TODO: Introduce a small delay here to make sure the
97 * CPU memory accesses do not starve the interconnect
98 * due to continuous polling.
99 */
100 }
101
102 if (attempts == LOOP_COUNT) {
Olivier Depreze71ec9c2022-02-28 18:57:26 +0100103 ERROR("SMMUv3: test failed, exceeded max. wait loop.\n");
Madhukar Pappireddy172523b2020-12-31 19:25:33 -0600104 return false;
105 }
106
107 dsbsy();
108 }
109
Olivier Depreze71ec9c2022-02-28 18:57:26 +0100110 return true;
111}
Madhukar Pappireddy172523b2020-12-31 19:25:33 -0600112
Olivier Depreze71ec9c2022-02-28 18:57:26 +0100113static bool run_smmuv3_memcpy(uintptr_t start_address, size_t size, uint32_t attributes)
114{
115 uintptr_t target_address;
116 size_t cpy_range = size >> 1;
117 bool ret;
118
119 /*
120 * The test engine's MEMCPY command copies data from the region in
121 * range [begin, end_incl] to the region with base address as udata.
122 * In this test, we configure the test engine to initiate memcpy from
123 * scratch page located at MEMCPY_SOURCE_BASE to the page located at
124 * address MEMCPY_TARGET_BASE
125 */
126
127 target_address = start_address + cpy_range;
128 ret = run_testengine(ENGINE_MEMCPY, start_address, target_address,
129 cpy_range / FRAME_COUNT, attributes);
130
131 if (ret) {
132 /*
133 * Invalidate cached entries to force the CPU to fetch the data from
134 * Main memory
135 */
136 inv_dcache_range(start_address, cpy_range);
137 inv_dcache_range(target_address, cpy_range);
138
139 /* Compare source and destination memory locations for data */
140 for (size_t i = 0U; i < (cpy_range / 8U); i++) {
141 if (mmio_read_64(start_address + 8 * i) !=
142 mmio_read_64(target_address + 8 * i)) {
143 ERROR("SMMUv3: Mem copy failed: %lx\n", target_address + 8 * i);
144 return false;
145 }
Madhukar Pappireddy172523b2020-12-31 19:25:33 -0600146 }
147 }
148
Olivier Depreze71ec9c2022-02-28 18:57:26 +0100149 return ret;
150}
151
152static bool run_smmuv3_rand48(uintptr_t start_address, size_t size, uint32_t attributes)
153{
154 return run_testengine(ENGINE_RAND48, start_address, 0, size / FRAME_COUNT, attributes);
Madhukar Pappireddy172523b2020-12-31 19:25:33 -0600155}
156
157CACTUS_CMD_HANDLER(smmuv3_cmd, CACTUS_DMA_SMMUv3_CMD)
158{
Daniel Boulbye79d2072021-03-03 11:34:53 +0000159 ffa_id_t vm_id = ffa_dir_msg_dest(*args);
160 ffa_id_t source = ffa_dir_msg_source(*args);
Olivier Depreze71ec9c2022-02-28 18:57:26 +0100161 uint32_t operation = args->arg4;
162 uintptr_t start_address = args->arg5;
163 size_t size = args->arg6;
164 uint32_t attributes = args->arg7;
Madhukar Pappireddy172523b2020-12-31 19:25:33 -0600165
Olivier Depreze71ec9c2022-02-28 18:57:26 +0100166 VERBOSE("Received request through direct message for DMA service.\n");
Madhukar Pappireddy172523b2020-12-31 19:25:33 -0600167
168 /*
169 * At present, the test cannot be run concurrently on multiple SPs as
170 * there is only one SMMUv3TestEngine IP in the FVP model. Hence, run
171 * the test only on the first SP.
172 */
173 if (vm_id != SPM_VM_ID_FIRST) {
174 return cactus_error_resp(vm_id, source, 0);
175 }
176
Olivier Depreze71ec9c2022-02-28 18:57:26 +0100177 switch (operation) {
178 case ENGINE_MEMCPY:
179 if (run_smmuv3_memcpy(start_address, size, attributes)) {
180 return cactus_success_resp(vm_id, source, 0);
181 }
182 break;
183 case ENGINE_RAND48:
184 if (run_smmuv3_rand48(start_address, size, attributes)) {
185 return cactus_success_resp(vm_id, source, 0);
186 }
187 break;
188 default:
189 ERROR("SMMUv3TestEngine: unsupported operation (%u).\n", operation);
190 break;
Madhukar Pappireddy172523b2020-12-31 19:25:33 -0600191 }
192
Olivier Depreze71ec9c2022-02-28 18:57:26 +0100193 return cactus_error_resp(vm_id, source, 0);
Madhukar Pappireddy172523b2020-12-31 19:25:33 -0600194}