return true;
}
+static void hash_iov_unmap(AspeedHACEState *s, struct iovec *iov,
+ hwaddr *mapped_lens, int iov_count)
+{
+ for (; iov_count > 0; iov_count--) {
+ address_space_unmap(&s->dram_as, iov[iov_count - 1].iov_base,
+ mapped_lens[iov_count - 1], false,
+ mapped_lens[iov_count - 1]);
+ }
+}
+
static int hash_prepare_direct_iov(AspeedHACEState *s, struct iovec *iov,
- bool acc_mode, bool *acc_final_request)
+ bool acc_mode, bool *acc_final_request,
+ hwaddr *mapped_lens)
{
uint32_t total_msg_len;
uint32_t pad_offset;
iov[0].iov_base = haddr;
iov_idx = 1;
+ mapped_lens[0] = plen;
if (acc_mode) {
if (!hash_accumulate_len(s, plen)) {
+ hash_iov_unmap(s, iov, mapped_lens, 1);
return -1;
}
}
static int hash_prepare_sg_iov(AspeedHACEState *s, struct iovec *iov,
- bool acc_mode, bool *acc_final_request)
+ bool acc_mode, bool *acc_final_request,
+ hwaddr *mapped_lens)
{
uint32_t total_msg_len;
uint32_t pad_offset;
int iov_idx;
hwaddr plen;
void *haddr;
+ int iov_mapped = 0;
src = hash_get_source_addr(s);
for (iov_idx = 0; !(len & SG_LIST_LEN_LAST); iov_idx++) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Failed to set end of sg list marker\n",
__func__);
- return -1;
+ goto fail;
}
len = address_space_ldl_le(&s->dram_as, src,
"%s: Unable to map address, sg_addr=0x%x, "
"plen=0x%" HWADDR_PRIx "\n",
__func__, sg_addr, plen);
- return -1;
+ goto fail;
}
src += SG_LIST_ENTRY_SIZE;
iov[iov_idx].iov_base = haddr;
+ iov_mapped = iov_idx + 1;
+ mapped_lens[iov_idx] = plen;
if (acc_mode) {
if (!hash_accumulate_len(s, plen)) {
- return -1;
+ goto fail;
}
if (has_padding(s, &iov[iov_idx], plen, &total_msg_len,
}
return iov_idx;
+
+fail:
+ hash_iov_unmap(s, iov, mapped_lens, iov_mapped);
+ return -1;
}
static uint64_t hash_get_digest_addr(AspeedHACEState *s)
static void hash_write_digest_and_unmap_iov(AspeedHACEState *s,
struct iovec *iov,
int iov_idx,
+ hwaddr *mapped_lens,
uint8_t *digest_buf,
size_t digest_len)
{
hace_hexdump("digest", (char *)digest_buf, digest_len);
}
- for (; iov_idx > 0; iov_idx--) {
- address_space_unmap(&s->dram_as, iov[iov_idx - 1].iov_base,
- iov[iov_idx - 1].iov_len, false,
- iov[iov_idx - 1].iov_len);
- }
+ hash_iov_unmap(s, iov, mapped_lens, iov_idx);
}
static void hash_execute_non_acc_mode(AspeedHACEState *s, int algo,
- struct iovec *iov, int iov_idx)
+ struct iovec *iov, int iov_idx,
+ hwaddr *mapped_lens)
{
g_autofree uint8_t *digest_buf = NULL;
Error *local_err = NULL;
"%s: qcrypto hash bytesv failed : %s",
__func__, error_get_pretty(local_err));
error_free(local_err);
+ hash_iov_unmap(s, iov, mapped_lens, iov_idx);
return;
}
- hash_write_digest_and_unmap_iov(s, iov, iov_idx, digest_buf, digest_len);
+ hash_write_digest_and_unmap_iov(s, iov, iov_idx, mapped_lens,
+ digest_buf, digest_len);
}
static void hash_execute_acc_mode(AspeedHACEState *s, int algo,
struct iovec *iov, int iov_idx,
- bool final_request)
+ bool final_request, hwaddr *mapped_lens)
{
g_autofree uint8_t *digest_buf = NULL;
Error *local_err = NULL;
qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto hash new failed : %s",
__func__, error_get_pretty(local_err));
error_free(local_err);
+ hash_iov_unmap(s, iov, mapped_lens, iov_idx);
return;
}
}
qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto hash updatev failed : %s",
__func__, error_get_pretty(local_err));
error_free(local_err);
+ hash_iov_unmap(s, iov, mapped_lens, iov_idx);
return;
}
s->total_req_len = 0;
}
- hash_write_digest_and_unmap_iov(s, iov, iov_idx, digest_buf, digest_len);
+ hash_write_digest_and_unmap_iov(s, iov, iov_idx, mapped_lens,
+ digest_buf, digest_len);
}
static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode,
bool acc_mode)
{
QEMU_UNINITIALIZED struct iovec iov[ASPEED_HACE_MAX_SG];
+ hwaddr mapped_lens[ASPEED_HACE_MAX_SG] = { 0 };
bool acc_final_request = false;
int iov_idx = -1;
/* Prepares the iov for hashing operations based on the selected mode */
if (sg_mode) {
- iov_idx = hash_prepare_sg_iov(s, iov, acc_mode, &acc_final_request);
+ iov_idx = hash_prepare_sg_iov(s, iov, acc_mode, &acc_final_request,
+ mapped_lens);
} else {
iov_idx = hash_prepare_direct_iov(s, iov, acc_mode,
- &acc_final_request);
+ &acc_final_request, mapped_lens);
}
if (iov_idx <= 0) {
/* Executes the hash operation */
if (acc_mode) {
- hash_execute_acc_mode(s, algo, iov, iov_idx, acc_final_request);
+ hash_execute_acc_mode(s, algo, iov, iov_idx, acc_final_request,
+ mapped_lens);
} else {
- hash_execute_non_acc_mode(s, algo, iov, iov_idx);
+ hash_execute_non_acc_mode(s, algo, iov, iov_idx, mapped_lens);
}
}