From: Harald Freudenberger <freude@linux.ibm.com>
To: richard.henderson@linaro.org, iii@linux.ibm.com,
david@kernel.org, thuth@redhat.com, berrange@redhat.com
Cc: qemu-s390x@nongnu.org, qemu-devel@nongnu.org,
linux-s390@vger.kernel.org, dengler@linux.ibm.com,
borntraeger@linux.ibm.com, fcallies@linux.ibm.com,
cohuck@redhat.com
Subject: [PATCH v14 05/19] target/s390x: Add helper functions for copy memory to and from guest
Date: Thu, 6 Aug 2026 17:12:47 +0200 [thread overview]
Message-ID: <20260806151302.26846-6-freude@linux.ibm.com> (raw)
In-Reply-To: <20260806151302.26846-1-freude@linux.ibm.com>
Add some simple helper functions to copy memory from guest to a local
buffer and the other way around:
- read_guest_wrap_u8()
- write_guest_wrap_u8()
- read_guest_wrap_u32()
- write_guest_wrap_u32()
- read_guest_wrap_u64()
- write_guest_wrap_u64()
The reader functions read from guest memory into an array of
u8/u32/u64 with BE conversion. Similar the writer functions write an
array of u8/u32/u64 into guest memory with BE conversion.
All these functions are intended to be used for the crypto
implementations thus are located in crypto_helper.h.
Rework and simplify the sha 256 and sha 512 implementations to use
these helper functions.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
target/s390x/tcg/cpacf_sha256.c | 63 ++++---------------
target/s390x/tcg/cpacf_sha512.c | 63 ++++---------------
target/s390x/tcg/crypto_helper.c | 1 +
target/s390x/tcg/crypto_helper.h | 100 +++++++++++++++++++++++++++++++
4 files changed, 123 insertions(+), 104 deletions(-)
create mode 100644 target/s390x/tcg/crypto_helper.h
diff --git a/target/s390x/tcg/cpacf_sha256.c b/target/s390x/tcg/cpacf_sha256.c
index 7e57e497a3..f895f9e20c 100644
--- a/target/s390x/tcg/cpacf_sha256.c
+++ b/target/s390x/tcg/cpacf_sha256.c
@@ -18,6 +18,7 @@
#include "accel/tcg/cpu-ldst-common.h"
#include "accel/tcg/cpu-mmu-index.h"
#include "target/s390x/tcg/cpacf.h"
+#include "target/s390x/tcg/crypto_helper.h"
static uint32_t R(uint32_t x, int c)
{
@@ -103,53 +104,13 @@ static void sha256_bda_be32(uint32_t a[8], uint32_t w[16])
sha256_bda(a, t);
}
-static void sha256_read_icv(CPUS390XState *env, const int mmu_idx,
- uint64_t addr, uint32_t a[8], uintptr_t ra)
-{
- const MemOpIdx oi = make_memop_idx(MO_BE | MO_32 | MO_UNALN, mmu_idx);
-
- for (int i = 0; i < 8; i++, addr += 4) {
- a[i] = cpu_ldl_mmu(env, wrap_address(env, addr), oi, ra);
- }
-}
-
-static void sha256_write_ocv(CPUS390XState *env, const int mmu_idx,
- uint64_t addr, uint32_t a[8], uintptr_t ra)
-{
- const MemOpIdx oi = make_memop_idx(MO_BE | MO_32 | MO_UNALN, mmu_idx);
-
- for (int i = 0; i < 8; i++, addr += 4) {
- cpu_stl_mmu(env, wrap_address(env, addr), a[i], oi, ra);
- }
-}
-
-static void sha256_read_block(CPUS390XState *env, const int mmu_idx,
- uint64_t addr, uint32_t a[16], uintptr_t ra)
-{
- const MemOpIdx oi = make_memop_idx(MO_BE | MO_32 | MO_UNALN, mmu_idx);
-
- for (int i = 0; i < 16; i++, addr += 4) {
- a[i] = cpu_ldl_mmu(env, wrap_address(env, addr), oi, ra);
- }
-}
-
-static void sha256_read_mbl_be32(CPUS390XState *env, const int mmu_idx,
- uint64_t addr, uint8_t a[8], uintptr_t ra)
-{
- const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx);
-
- for (int i = 0; i < 8; i++, addr += 1) {
- a[i] = cpu_ldb_mmu(env, wrap_address(env, addr), oi, ra);
- }
-}
-
int cpacf_sha256(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
uint64_t param_addr, uint64_t *message_reg, uint64_t *len_reg,
uint32_t type)
{
enum { MAX_BLOCKS_PER_RUN = 128 }; /* 128 * 64 = 8K */
uint64_t len = *len_reg, processed = 0;
- int i, message_reg_len = 64;
+ int message_reg_len = 64;
uint32_t a[8];
g_assert(type == S390_FEAT_TYPE_KIMD || type == S390_FEAT_TYPE_KLMD);
@@ -164,7 +125,8 @@ int cpacf_sha256(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
}
- sha256_read_icv(env, mmu_idx, param_addr, a, ra);
+ /* read icv (8 * u32) */
+ read_guest_wrap_u32(env, mmu_idx, ra, param_addr, a, 8);
/* Process full blocks first. */
for (; len >= 64; len -= 64, processed += 64) {
@@ -174,21 +136,18 @@ int cpacf_sha256(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
break;
}
- sha256_read_block(env, mmu_idx, *message_reg + processed, w, ra);
+ /* read sha256 block (16 * u32) */
+ read_guest_wrap_u32(env, mmu_idx, ra, *message_reg + processed, w, 16);
sha256_bda(a, w);
}
/* KLMD: Process partial/empty block last. */
if (type == S390_FEAT_TYPE_KLMD && len < 64) {
- const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx);
uint8_t x[64];
- /* Read the remainder of the message byte-per-byte. */
- for (i = 0; i < len; i++) {
- uint64_t addr = wrap_address(env, *message_reg + processed + i);
+ /* Read the remainder of the message. */
+ read_guest_wrap_u8(env, mmu_idx, ra, *message_reg + processed, x, len);
- x[i] = cpu_ldb_mmu(env, addr, oi, ra);
- }
/* Pad the remainder with zero and set the top bit. */
memset(x + len, 0, 64 - len);
x[len] = 0x80;
@@ -198,13 +157,13 @@ int cpacf_sha256(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
* or use an additional one.
*/
if (len < 56) {
- sha256_read_mbl_be32(env, mmu_idx, param_addr + 32, x + 56, ra);
+ read_guest_wrap_u8(env, mmu_idx, ra, param_addr + 32, x + 56, 8);
}
sha256_bda_be32(a, (uint32_t *)x);
if (len >= 56) {
memset(x, 0, 56);
- sha256_read_mbl_be32(env, mmu_idx, param_addr + 32, x + 56, ra);
+ read_guest_wrap_u8(env, mmu_idx, ra, param_addr + 32, x + 56, 8);
sha256_bda_be32(a, (uint32_t *)x);
}
@@ -219,7 +178,7 @@ int cpacf_sha256(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
* TODO: if writing fails halfway through (e.g., when crossing page
* boundaries), we're in trouble. We'd need something like access_prepare().
*/
- sha256_write_ocv(env, mmu_idx, param_addr, a, ra);
+ write_guest_wrap_u32(env, mmu_idx, ra, param_addr, a, 8);
*message_reg = deposit64(*message_reg, 0, message_reg_len,
*message_reg + processed);
*len_reg -= processed;
diff --git a/target/s390x/tcg/cpacf_sha512.c b/target/s390x/tcg/cpacf_sha512.c
index ebfecc70f7..fa42eff336 100644
--- a/target/s390x/tcg/cpacf_sha512.c
+++ b/target/s390x/tcg/cpacf_sha512.c
@@ -17,6 +17,7 @@
#include "accel/tcg/cpu-ldst-common.h"
#include "accel/tcg/cpu-mmu-index.h"
#include "target/s390x/tcg/cpacf.h"
+#include "target/s390x/tcg/crypto_helper.h"
static uint64_t R(uint64_t x, int c)
{
@@ -118,53 +119,13 @@ static void sha512_bda_be64(uint64_t a[8], uint64_t w[16])
sha512_bda(a, t);
}
-static void sha512_read_icv(CPUS390XState *env, const int mmu_idx,
- uint64_t addr, uint64_t a[8], uintptr_t ra)
-{
- const MemOpIdx oi = make_memop_idx(MO_BE | MO_64 | MO_UNALN, mmu_idx);
-
- for (int i = 0; i < 8; i++, addr += 8) {
- a[i] = cpu_ldq_mmu(env, wrap_address(env, addr), oi, ra);
- }
-}
-
-static void sha512_write_ocv(CPUS390XState *env, const int mmu_idx,
- uint64_t addr, uint64_t a[8], uintptr_t ra)
-{
- const MemOpIdx oi = make_memop_idx(MO_BE | MO_64 | MO_UNALN, mmu_idx);
-
- for (int i = 0; i < 8; i++, addr += 8) {
- cpu_stq_mmu(env, wrap_address(env, addr), a[i], oi, ra);
- }
-}
-
-static void sha512_read_block(CPUS390XState *env, const int mmu_idx,
- uint64_t addr, uint64_t a[16], uintptr_t ra)
-{
- const MemOpIdx oi = make_memop_idx(MO_BE | MO_64 | MO_UNALN, mmu_idx);
-
- for (int i = 0; i < 16; i++, addr += 8) {
- a[i] = cpu_ldq_mmu(env, wrap_address(env, addr), oi, ra);
- }
-}
-
-static void sha512_read_mbl_be64(CPUS390XState *env, const int mmu_idx,
- uint64_t addr, uint8_t a[16], uintptr_t ra)
-{
- const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx);
-
- for (int i = 0; i < 16; i++, addr += 1) {
- a[i] = cpu_ldb_mmu(env, wrap_address(env, addr), oi, ra);
- }
-}
-
int cpacf_sha512(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
uint64_t param_addr, uint64_t *message_reg, uint64_t *len_reg,
uint32_t type)
{
enum { MAX_BLOCKS_PER_RUN = 64 }; /* Arbitrary: keep interactivity. */
uint64_t len = *len_reg, a[8], processed = 0;
- int i, message_reg_len = 64;
+ int message_reg_len = 64;
g_assert(type == S390_FEAT_TYPE_KIMD || type == S390_FEAT_TYPE_KLMD);
@@ -178,7 +139,8 @@ int cpacf_sha512(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra);
}
- sha512_read_icv(env, mmu_idx, param_addr, a, ra);
+ /* read icv (8 * u64) */
+ read_guest_wrap_u64(env, mmu_idx, ra, param_addr, a, 8);
/* Process full blocks first. */
for (; len >= 128; len -= 128, processed += 128) {
@@ -188,21 +150,18 @@ int cpacf_sha512(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
break;
}
- sha512_read_block(env, mmu_idx, *message_reg + processed, w, ra);
+ /* read sha512 block (16 * u64) */
+ read_guest_wrap_u64(env, mmu_idx, ra, *message_reg + processed, w, 16);
sha512_bda(a, w);
}
/* KLMD: Process partial/empty block last. */
if (type == S390_FEAT_TYPE_KLMD && len < 128) {
- const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx);
uint8_t x[128];
- /* Read the remainder of the message byte-per-byte. */
- for (i = 0; i < len; i++) {
- uint64_t addr = wrap_address(env, *message_reg + processed + i);
+ /* Read the remainder of the message. */
+ read_guest_wrap_u8(env, mmu_idx, ra, *message_reg + processed, x, len);
- x[i] = cpu_ldb_mmu(env, addr, oi, ra);
- }
/* Pad the remainder with zero and set the top bit. */
memset(x + len, 0, 128 - len);
x[len] = 128;
@@ -212,13 +171,13 @@ int cpacf_sha512(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
* or use an additional one.
*/
if (len < 112) {
- sha512_read_mbl_be64(env, mmu_idx, param_addr + 64, x + 112, ra);
+ read_guest_wrap_u8(env, mmu_idx, ra, param_addr + 64, x + 112, 16);
}
sha512_bda_be64(a, (uint64_t *)x);
if (len >= 112) {
memset(x, 0, 112);
- sha512_read_mbl_be64(env, mmu_idx, param_addr + 64, x + 112, ra);
+ read_guest_wrap_u8(env, mmu_idx, ra, param_addr + 64, x + 112, 16);
sha512_bda_be64(a, (uint64_t *)x);
}
@@ -233,7 +192,7 @@ int cpacf_sha512(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
* TODO: if writing fails halfway through (e.g., when crossing page
* boundaries), we're in trouble. We'd need something like access_prepare().
*/
- sha512_write_ocv(env, mmu_idx, param_addr, a, ra);
+ write_guest_wrap_u64(env, mmu_idx, ra, param_addr, a, 8);
*message_reg = deposit64(*message_reg, 0, message_reg_len,
*message_reg + processed);
*len_reg -= processed;
diff --git a/target/s390x/tcg/crypto_helper.c b/target/s390x/tcg/crypto_helper.c
index 6c296f6731..d996caf56a 100644
--- a/target/s390x/tcg/crypto_helper.c
+++ b/target/s390x/tcg/crypto_helper.c
@@ -20,6 +20,7 @@
#include "accel/tcg/cpu-ldst-common.h"
#include "accel/tcg/cpu-mmu-index.h"
#include "target/s390x/tcg/cpacf.h"
+#include "target/s390x/tcg/crypto_helper.h"
static void fill_buf_random(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
uint64_t *buf_reg, uint64_t *len_reg)
diff --git a/target/s390x/tcg/crypto_helper.h b/target/s390x/tcg/crypto_helper.h
new file mode 100644
index 0000000000..2364e46029
--- /dev/null
+++ b/target/s390x/tcg/crypto_helper.h
@@ -0,0 +1,100 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Crypto helper functions
+ */
+
+#ifndef TARGET_S390_CRYPTO_HELPER_H
+#define TARGET_S390_CRYPTO_HELPER_H
+
+/*
+ * helper function to read len * u8 from guest to local buffer
+ */
+static inline void read_guest_wrap_u8(CPUS390XState *env, const int mmu_idx,
+ const uintptr_t ra, uint64_t guest_addr,
+ uint8_t *dest, size_t len)
+{
+ const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx);
+
+ for (size_t i = 0; i < len; i++, guest_addr++) {
+ uint64_t waddr = wrap_address(env, guest_addr);
+ dest[i] = cpu_ldb_mmu(env, waddr, oi, ra);
+ }
+}
+
+/*
+ * helper function to write len * u8 from local buffer to guest
+ */
+static inline void write_guest_wrap_u8(CPUS390XState *env, const int mmu_idx,
+ const uintptr_t ra, uint64_t guest_addr,
+ const uint8_t *src, size_t len)
+{
+ const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx);
+
+ for (size_t i = 0; i < len; i++, guest_addr++) {
+ uint64_t waddr = wrap_address(env, guest_addr);
+ cpu_stb_mmu(env, waddr, src[i], oi, ra);
+ }
+}
+
+/*
+ * helper function to read len * u32 from guest to local buffer
+ */
+static inline void read_guest_wrap_u32(CPUS390XState *env, const int mmu_idx,
+ const uintptr_t ra, uint64_t guest_addr,
+ uint32_t *dest, size_t len)
+{
+ const MemOpIdx oi = make_memop_idx(MO_BE | MO_32 | MO_UNALN, mmu_idx);
+
+ for (size_t i = 0; i < len; i++, guest_addr += 4) {
+ uint64_t waddr = wrap_address(env, guest_addr);
+ dest[i] = cpu_ldl_mmu(env, waddr, oi, ra);
+ }
+}
+
+/*
+ * helper function to write len * u32 from local buffer to guest
+ */
+static inline void write_guest_wrap_u32(CPUS390XState *env, const int mmu_idx,
+ const uintptr_t ra, uint64_t guest_addr,
+ const uint32_t *src, size_t len)
+{
+ const MemOpIdx oi = make_memop_idx(MO_BE | MO_32 | MO_UNALN, mmu_idx);
+
+ for (size_t i = 0; i < len; i++, guest_addr += 4) {
+ uint64_t waddr = wrap_address(env, guest_addr);
+ cpu_stl_mmu(env, waddr, src[i], oi, ra);
+ }
+}
+
+/*
+ * helper function to read len * u64 from guest to local buffer
+ */
+static inline void read_guest_wrap_u64(CPUS390XState *env, const int mmu_idx,
+ const uintptr_t ra, uint64_t guest_addr,
+ uint64_t *dest, size_t len)
+{
+ const MemOpIdx oi = make_memop_idx(MO_BE | MO_64 | MO_UNALN, mmu_idx);
+
+ for (size_t i = 0; i < len; i++, guest_addr += 8) {
+ uint64_t waddr = wrap_address(env, guest_addr);
+ dest[i] = cpu_ldq_mmu(env, waddr, oi, ra);
+ }
+}
+
+/*
+ * helper function to write len * u64 from local buffer to guest
+ */
+static inline void write_guest_wrap_u64(CPUS390XState *env, const int mmu_idx,
+ const uintptr_t ra, uint64_t guest_addr,
+ const uint64_t *src, size_t len)
+{
+ const MemOpIdx oi = make_memop_idx(MO_BE | MO_64 | MO_UNALN, mmu_idx);
+
+ for (size_t i = 0; i < len; i++, guest_addr += 8) {
+ uint64_t waddr = wrap_address(env, guest_addr);
+ cpu_stq_mmu(env, waddr, src[i], oi, ra);
+ }
+}
+
+#endif /* TARGET_S390_CRYPTO_HELPER_H */
--
2.43.0
next prev parent reply other threads:[~2026-08-06 15:13 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-06 15:12 [PATCH v14 00/19] target/s390x: Extend qemu CPACF support Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 01/19] target/s390x: Fix missing privileged flag at PCKMO instruction Harald Freudenberger
2026-08-06 18:48 ` Ilya Leoshkevich
2026-08-06 15:12 ` [PATCH v14 02/19] target/s390x: Rework s390 cpacf implementations Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 03/19] target/s390x: Move cpacf sha512 code into a new file Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 04/19] target/s390x: Support cpacf sha256 Harald Freudenberger
2026-08-06 15:12 ` Harald Freudenberger [this message]
2026-08-06 15:12 ` [PATCH v14 06/19] crypto: Add aes-helpers file to support some AES modes Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 07/19] target/s390x: Support AES ECB for cpacf km instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 08/19] target/s390x: Support AES CBC for cpacf kmc instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 09/19] target/s390x: Support AES CTR for cpacf kmctr instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 10/19] target/s390x: Minimal AES XTS support for cpacf pcc instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 11/19] target/s390x: Support AES XTS for cpacf km instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 12/19] target/s390x: Base support for cpacf protected keys and pckmo Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 13/19] target/s390x: Support protected key AES ECB for cpacf km instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 14/19] target/s390x: Support protected key AES CBC for cpacf kmc instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 15/19] target/s390x: Support protected key AES CTR for cpacf kmctr instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 16/19] target/s390x: Minimal protected key AES XTS support for cpacf pcc instruction Harald Freudenberger
2026-08-06 15:12 ` [PATCH v14 17/19] target/s390x: Support protected key AES XTS for cpacf km instruction Harald Freudenberger
2026-08-06 15:13 ` [PATCH v14 18/19] docs/s390: Document CPACF instructions support Harald Freudenberger
2026-08-06 15:13 ` [PATCH v14 19/19] tests/tcg/s390x: Add tests for CPACF instructions Harald Freudenberger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260806151302.26846-6-freude@linux.ibm.com \
--to=freude@linux.ibm.com \
--cc=berrange@redhat.com \
--cc=borntraeger@linux.ibm.com \
--cc=cohuck@redhat.com \
--cc=david@kernel.org \
--cc=dengler@linux.ibm.com \
--cc=fcallies@linux.ibm.com \
--cc=iii@linux.ibm.com \
--cc=linux-s390@vger.kernel.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-s390x@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox