Re: [PATCH v13 12/18] target/s390x: Support protected key AES ECB for cpacf km instruction
Ilya Leoshkevich <[email protected]> Wed, 5 Aug 2026 13:17:23 +0200
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
On 8/5/26 10:28, Harald Freudenberger wrote: > On 2026-08-05 00:48, Ilya Leoshkevich wrote: >> On 8/3/26 18:12, Harald Freudenberger wrote: >>> Support the subfunctions CPACF_KM_PAES_128, CPACF_KM_PAES_192 >>> and CPACF_KM_PAES_256 for the cpacf km instruction. >>> >>> Tested-by: Holger Dengler <[email protected]> >>> Reviewed-by: Finn Callies <[email protected]> >>> Signed-off-by: Harald Freudenberger <[email protected]> >>> --- >>> target/s390x/gen-features.c | 3 ++ >>> target/s390x/tcg/cpacf.h | 4 ++ >>> target/s390x/tcg/cpacf_aes.c | 91 ++++++++++++++++++++++++++++++++ >>> target/s390x/tcg/crypto_helper.c | 7 +++ >>> 4 files changed, 105 insertions(+) >> >> [...] >> >>> + >>> + /* process up to MAX_BLOCKS_PER_RUN aes blocks */ >>> + for (i = 0; i < MAX_BLOCKS_PER_RUN && len >= AES_BLOCK_SIZE; i++) { >>> + aes_read_block(env, mmu_idx, ra, *src_ptr_reg + done, in); >>> + if (mod) { >>> + AES_decrypt(in, out, &exkey); >>> + } else { >>> + AES_encrypt(in, out, &exkey); >>> + } >>> + aes_write_block(env, mmu_idx, ra, *dst_ptr_reg + done, out); >>> + len -= AES_BLOCK_SIZE; >>> + done += AES_BLOCK_SIZE; >>> + } >>> + >>> + *src_ptr_reg = deposit64(*src_ptr_reg, 0, addr_reg_size, >>> + *src_ptr_reg + done); >>> + *dst_ptr_reg = deposit64(*dst_ptr_reg, 0, addr_reg_size, >>> + *dst_ptr_reg + done); >>> + *src_len_reg -= done; >> >> Should we update registers after each iteration? >> Otherwise there may be interesting effects due to swapped out pages when >> running in system emulation. > > I don't get this. Swapping and interruption of this code should not affect > the encrypted/decrypted result in memory and also not the register content. > But I assume that a CPACF instruction itself is some atomic operation. So > there needs to be a consistent state before and after the instruction. But > "while" the instruction is executed does not need to be consistent all the > time. Otherwise for example here the memory write and the update of the > registers should be atomic. I agree that the "while" state is in general not important, except for the special case when we get a memory-related exception in the middle of processing. Then we end up committing the "while" state and it can be observed by at least the exception handler. In this specific case I guess the whole instruction will be restarted and the application code will not have a chance to observe the inconsistency (memory updated, but registers are not), but it a) doesn't look very clean and b) has quadratic complexity: if 10 pages are swapped out, we will perform 1+2+...+10 decryptions. DFLTCC, which is similar, handles it like this: it processes as many pages as it can, and if the next page is not accessible, it returns CC3, updating memory and registers accordingly. Only if the very first page is not accessible it raises an exception. This makes sure we don't end up with a quadratic number of bytes decompressed. >> Blocks crossing the page boundary is a similar issue, not sure if it's >> that easy to solve. > > Well yes. This is a clear issue hanging around in all the memory read/write > crypto code here. I have no idea on how this could be solved. However, > sounds > like there will participate a new guy in the Qemu cpacf area soon. So maybe > he has some ideas to work this out. Looking at tcg/mem_helper.c, they use a static access_prepare() instruction to pre-check the address ranges; this function takes page crossings into account. Perhaps it can be made non-static and reused here as is? >> [...]