[PATCH v13 04/18] target/s390x: Add helper functions for copy memory to and from guest
Harald Freudenberger <[email protected]> Mon, 3 Aug 2026 18:12:21 +0200
| Newsgroups | org.nongnu.qemu-devel,org.kernel.vger.linux-s390 |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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