From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792561; cv=none; d=zohomail.com; s=zohoarc; b=MrLVJ69tvHymKuE8VDQnia4Gz0r8Ip2g6yEkIAdyXRAfdy9BvV5cNGXvQM8l8uM1Avt6CY0JuXBZULSynBWr8tzn/I9dz+SyWCh/9jvCiMlkqOrnM6a3hDxfXDXbCRqL3lcybSoEFtWgK6qXx9lQ23WDMQP0R3P9bg/IN9G0k7s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792561; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=jBiKGLRVWD6R5ghsdYi6NUZaIFY15k0Kx1vkOFC8LEk=; b=hZ1zR+PBsVxrpyeCOuVy0+f8+9IbnIXXRCKMpTTiG8PESft8bdo6UdfnoRWSHJgx1x6hqghpgPB/U0dxEBGWZ8k5nkHe5A12TPkJXuFK8VbzluPWJ9yb9dzQFJ+DVIsNg+44zjfAb6yLraY8mXLvt4iMB6QceAkQ/n3ggoxF/aA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17767925616121005.3984942156138; Tue, 21 Apr 2026 10:29:21 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtM-0003rb-J1; Tue, 21 Apr 2026 13:28:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEt5-0003mB-Er for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:54 -0400 Received: from mail-oa1-x2c.google.com ([2001:4860:4864:20::2c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEsx-0006h2-Dz for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:45 -0400 Received: by mail-oa1-x2c.google.com with SMTP id 586e51a60fabf-40f0e14b9f9so2633154fac.1 for ; Tue, 21 Apr 2026 10:27:42 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792461; x=1777397261; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=jBiKGLRVWD6R5ghsdYi6NUZaIFY15k0Kx1vkOFC8LEk=; b=CImT+m36QKg8bnOFcmgsAEH75Nu7/P+N0225sWk5o2K5rQAYO3iBc3eHxy7ECCIIZ6 41ou3l6msjVevST+UTIx1Rjp6JF+e8CC4NTfD/LKP35+piFYWszWFRjYUrK7XyqjVg+c RmnCNsUZEKv+GCgZmzHF0QllZvp75boaZQi8NKwqSBhnDOa3nVQaj3+pZoOQ3HtAfFHH vwQRgVZCz9MJn4ZnAq5axYRrlGXoT2HYZQUJz87yeNvH2mAn/YwDIfGC1JzdN3UGkHFN /P8DW7LjzLxSFaVAZITHItkY+v1KycP7wpRmEAYMwP5hAXpGkyYhyZfmjgE5QFcR5ZNR F7/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792461; x=1777397261; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=jBiKGLRVWD6R5ghsdYi6NUZaIFY15k0Kx1vkOFC8LEk=; b=JM8qb1zI3ul1lMwYH38b1JGhCB6RoWxhf+gYI4Yzyue2N9vlV9HtsivCGDuaQkWyh4 khBA4CBwbisIjUAUzCDbkse5ZRZG8QjJdV7YzmnRPJ79RGNeK0b2u+G6MY6qEiurh4vl wHluy384xSTS/1zf5lPMWpX3FrnLNQs6RC5YQ6skwxQ1JEDeRqjCQqQtCFOQXFbmVGOb B5ZOuPPfnGJ6913cqno/8aeVjoVDToUnSp/8Z/BAK+nrpzcLj1N+2Q73jf2lpkgySPDz x+l3/Iy621pSWMx4n2UOESoWvl/Gr0vCr7y0iDIvsjtkbOoVx+GCn6OeFnv8lr+rGMOJ iIBw== X-Gm-Message-State: AOJu0Yx0KbM38TuyRCCEQ1f4Ao655de145cPX3+M0llY/8X1y+QTYqvC 7EDffs/ymiWeNjT13mCU6qbJiWH5uL0N6sN0Cs6sSqY+jNiYlrCJf8px X-Gm-Gg: AeBDiev4Dd2BufVOLoWNO8cjpR0ZqJy4m2ouuwLXrxvoL2WjQDFE2vYQwY+YuOJxigV MOayh5pWUA3qLM5eUpvDKBvYgv3/IlShtxRJsCDvzg3LHAV44Mo+o9l1Eexl2SPDJXhqED1aziB 7PI85qNnQPNEXZzprAmHtO4rrbKdQUYuB4eXG2ATL4DizqLIff/DJ46jXgTkurlZhalNUKZ7Cp3 /BH8GHApcrWdRcqOu1eu6WVIQHzJxvWXntWTtyjHNNyPfkE1jbb/LFTn6BGvgQ3MsMN5nXUVYKQ XODV1JngvumEZi2enexU8rZjuCkvUbrfPzV4YNBA+76ul1pW7usFqPbkEcNxWkL1kRwKoriVIKN KgLKw4h+YRhvgpaJTEI560DF2OwzaJ/+gGHtdIs9lemWvoYeDvqkz2qUxpvIOkxc0syf1cW7ltf mJyG4cksu+LoLL7N/fkqIliYVaw4RSoTjB0ASXFPSe1C4MwLclWVvfyXB/tqm1KDO1OARZ48kNH 9AE5S27LUi9v+pAuGOoUGPiuABliOC02GR7ih5Znwvp2CX2u2PXKlrOn3EJcxP//er/EqqSbIqa NiV7tQ== X-Received: by 2002:a05:6870:8108:b0:41b:f7f5:e8a7 with SMTP id 586e51a60fabf-42abf2ec957mr11899246fac.15.1776792460278; Tue, 21 Apr 2026 10:27:40 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:28 -0600 Subject: [PATCH v2 01/13] linux-user/mips, target/mips: honor MIPS_FIXADE for unaligned accesses MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-1-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::2c; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x2c.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792564730154100 Linux/MIPS enables software fixups for user-mode unaligned scalar accesses by default through MIPS_FIXADE/TIF_FIXADE. QEMU linux-user did not model that ABI, so MIPS guests took fatal AdEL/AdES exceptions unless translation was forced to use unaligned host accesses. Replace the target-specific workaround with a generic MIPS linux-user implementation: - key MIPS translation blocks on the linux-user unaligned policy, - implement sysmips(MIPS_FIXADE) to toggle that policy, - raise SIGBUS/BUS_ADRALN when fixups are disabled, and - handle the existing sysmips(MIPS_ATOMIC_SET) and MIPS_FLUSH_CACHE commands in the new target-side sysmips dispatcher. This makes the default behaviour match native Linux/MIPS more closely and keeps the signal semantics consistent with the kernel ABI without regressing other user-mode sysmips commands. Signed-off-by: James Hilliard --- linux-user/mips/cpu_loop.c | 5 ++++ linux-user/mips/target_syscall.h | 3 ++ linux-user/mips64/target_syscall.h | 3 ++ linux-user/syscall.c | 60 ++++++++++++++++++++++++++++++++++= ++++ target/mips/cpu.c | 8 +++-- target/mips/cpu.h | 4 +++ target/mips/tcg/translate.c | 6 +++- 7 files changed, 86 insertions(+), 3 deletions(-) diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index fa264b27ec..ff9d293c29 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -161,6 +161,11 @@ done_syscall: case EXCP_DSPDIS: force_sig(TARGET_SIGILL); break; + case EXCP_AdEL: + case EXCP_AdES: + force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, + env->CP0_BadVAddr); + break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_sysc= all.h index dfcdf320b7..be6942445a 100644 --- a/linux-user/mips/target_syscall.h +++ b/linux-user/mips/target_syscall.h @@ -10,6 +10,9 @@ #define TARGET_MCL_ONFAULT 4 =20 #define TARGET_FORCE_SHMLBA +#define TARGET_SYSMIPS_FLUSH_CACHE 3 +#define TARGET_SYSMIPS_FIXADE 7 +#define TARGET_SYSMIPS_ATOMIC_SET 2001 =20 static inline abi_ulong target_shmlba(CPUMIPSState *env) { diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_= syscall.h index 9135bf5e8b..c11d0a0888 100644 --- a/linux-user/mips64/target_syscall.h +++ b/linux-user/mips64/target_syscall.h @@ -10,6 +10,9 @@ #define TARGET_MCL_ONFAULT 4 =20 #define TARGET_FORCE_SHMLBA +#define TARGET_SYSMIPS_FLUSH_CACHE 3 +#define TARGET_SYSMIPS_FIXADE 7 +#define TARGET_SYSMIPS_ATOMIC_SET 2001 =20 static inline abi_ulong target_shmlba(CPUMIPSState *env) { diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f4b74ad350..8671526186 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6595,6 +6595,62 @@ static abi_long do_prctl_syscall_user_dispatch(CPUAr= chState *env, } } =20 +#ifdef TARGET_NR_sysmips +static abi_long do_sysmips_atomic_set(CPUArchState *env, abi_ulong addr, + abi_long value) +{ + uint32_t *ptr; + abi_long old; + + if (addr & 3) { + return -TARGET_EINVAL; + } + + ptr =3D lock_user(VERIFY_WRITE, addr, sizeof(*ptr), true); + if (!ptr) { + return -TARGET_EINVAL; + } + + old =3D tswap32(qatomic_xchg(ptr, tswap32((uint32_t)value))); + unlock_user(ptr, addr, sizeof(*ptr)); + + /* + * MIPS uses a separate error flag, but the common linux-user syscall + * path infers that flag from the return value. Successful atomic_set + * results can overlap the target errno range, so write the result + * registers here and ask the CPU loop to leave them alone. + */ + if ((abi_ulong)old >=3D (abi_ulong)-TARGET_EDQUOT) { + env->active_tc.gpr[2] =3D old; + env->active_tc.gpr[7] =3D 0; + return -QEMU_ESIGRETURN; + } + + return old; +} + +static abi_long do_sysmips(CPUArchState *env, abi_long cmd, abi_long arg1, + abi_long arg2) +{ + CPUState *cs =3D env_cpu(env); + + switch (cmd) { + case TARGET_SYSMIPS_ATOMIC_SET: + return do_sysmips_atomic_set(env, arg1, arg2); + case TARGET_SYSMIPS_FIXADE: + if (arg1 & ~3) { + return -TARGET_EINVAL; + } + cs->prctl_unalign_sigbus =3D !(arg1 & 1); + return 0; + case TARGET_SYSMIPS_FLUSH_CACHE: + return 0; + default: + return -TARGET_EINVAL; + } +} +#endif + static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { @@ -12067,6 +12123,10 @@ static abi_long do_syscall1(CPUArchState *cpu_env,= int num, abi_long arg1, case TARGET_NR_prctl: return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5); break; +#ifdef TARGET_NR_sysmips + case TARGET_NR_sysmips: + return do_sysmips(cpu_env, arg1, arg2, arg3); +#endif #ifdef TARGET_NR_arch_prctl case TARGET_NR_arch_prctl: return do_arch_prctl(cpu_env, arg1, arg2); diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 5f88c077db..ec70c10985 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -555,11 +555,15 @@ static int mips_cpu_mmu_index(CPUState *cs, bool ifun= c) static TCGTBCPUState mips_get_tb_cpu_state(CPUState *cs) { CPUMIPSState *env =3D cpu_env(cs); + uint32_t flags =3D env->hflags & MIPS_HFLAG_TB_MASK; + +#ifdef CONFIG_USER_ONLY + flags |=3D TB_FLAG_UNALIGN * !cs->prctl_unalign_sigbus; +#endif =20 return (TCGTBCPUState){ .pc =3D env->active_tc.PC, - .flags =3D env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK | - MIPS_HFLAG_HWRENA_ULR), + .flags =3D flags, }; } =20 diff --git a/target/mips/cpu.h b/target/mips/cpu.h index ed662135cb..ac81470576 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1161,6 +1161,10 @@ typedef struct CPUArchState { #define MIPS_HFLAG_ELPA 0x4000000 #define MIPS_HFLAG_ITC_CACHE 0x8000000 /* CACHE instr. operates on ITC ta= g */ #define MIPS_HFLAG_ERL 0x10000000 /* error level flag */ +#define MIPS_HFLAG_TB_MASK (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK | \ + MIPS_HFLAG_HWRENA_ULR) + +#define TB_FLAG_UNALIGN 0x40000000 target_ulong btarget; /* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ =20 diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 54849e9ff1..2e3fe1fa16 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -15067,6 +15067,7 @@ static void mips_tr_init_disas_context(DisasContext= Base *dcbase, CPUState *cs) { DisasContext *ctx =3D container_of(dcbase, DisasContext, base); CPUMIPSState *env =3D cpu_env(cs); + uint32_t tb_flags =3D ctx->base.tb->flags; =20 ctx->page_start =3D ctx->base.pc_first & TARGET_PAGE_MASK; ctx->saved_pc =3D -1; @@ -15089,7 +15090,7 @@ static void mips_tr_init_disas_context(DisasContext= Base *dcbase, CPUState *cs) ctx->CP0_LLAddr_shift =3D env->CP0_LLAddr_shift; ctx->cmgcr =3D (env->CP0_Config3 >> CP0C3_CMGCR) & 1; /* Restore delay slot state from the tb context. */ - ctx->hflags =3D (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 = bits? */ + ctx->hflags =3D tb_flags & MIPS_HFLAG_TB_MASK; ctx->ulri =3D (env->CP0_Config3 >> CP0C3_ULRI) & 1; ctx->ps =3D ((env->active_fpu.fcr0 >> FCR0_PS) & 1) || (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)); @@ -15109,6 +15110,9 @@ static void mips_tr_init_disas_context(DisasContext= Base *dcbase, CPUState *cs) ctx->default_tcg_memop_mask =3D (!(ctx->insn_flags & ISA_NANOMIPS32) && (ctx->insn_flags & (ISA_MIPS_R6 | INSN_LOONGSON3A))) ? MO_UNALN : MO_ALIGN; + if (tb_flags & TB_FLAG_UNALIGN) { + ctx->default_tcg_memop_mask =3D MO_UNALN; + } =20 /* * Execute a branch and its delay slot as a single instruction. --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792564; cv=none; d=zohomail.com; s=zohoarc; b=WGzDLLT8uqGcmMHc4SZlM06eO2RKq59Ot3c7ufdzxf33iN6I4Cco+SKoVb2EVlJdo8rIMQStaKJuSdU+w0wr2zdAELqJtKEyzs4aBN0dAUgjKtkSpzt9NZjvyiuVlV4ulhJCvOzltEqaa+zTmF9K63BFoLQsuuBlnGhfcLuV5Co= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792564; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Gu2YLJ24XV2eW3iG8BpKQlGIGVRYDVb1RgP8oSGX5xg=; b=Yj9QvRjlqtD8DdSAGs3oxYc+3/r91bkCRLvMXovC0zrhX52nd9S9vTnGPI596oBDizd++SvzdReMwxE9o+x0YfrsnflbC4r0+IbpLwvoEUiwpg8osw42difk+B9Z0CtE6ARQyRYOjV3GY0dCnacHWXlB5WJYWFazGo79d6jM/D8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792564934568.3141211229583; Tue, 21 Apr 2026 10:29:24 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtQ-00041x-S0; Tue, 21 Apr 2026 13:28:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEt5-0003mD-H5 for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:53 -0400 Received: from mail-oa1-x2b.google.com ([2001:4860:4864:20::2b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEsw-0006h0-Me for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:44 -0400 Received: by mail-oa1-x2b.google.com with SMTP id 586e51a60fabf-415e568a7ecso1911196fac.0 for ; Tue, 21 Apr 2026 10:27:42 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792461; x=1777397261; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=Gu2YLJ24XV2eW3iG8BpKQlGIGVRYDVb1RgP8oSGX5xg=; b=BGOc3Edi6E5jfO0NLq6/pSZ/ajRljuiF3REC0u5SCga9jRdAoBwxChQ+d7upH13C9T hdkN5nNS9oI+hgGeIMgIcV5KoYq72HHs5LcWUjwWDzWsw6+ihPrk8DEagPa1Y/zFjWXz hYlgACWFuCOGYeJAd3GoTtMjAMxUXx+jvYF4X1LTpoHSIs4wjhdGJFkSwM0Pi7QDNMg2 c7RsP59DzOuZ2p2Pv9nfjlGIt/IraabifIsKmbNcnBsaA25sm5FWu8b4soH4PL0TiYgp cGT9q/XC8VH0jRKOO/lu9l/UjQmwu48fwrZmr5c/oAFivApU+iwYrt1u3E4DJB30MHJa hk7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792461; x=1777397261; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=Gu2YLJ24XV2eW3iG8BpKQlGIGVRYDVb1RgP8oSGX5xg=; b=iTYoJiklclVfIdsVxvgkqsoue2HUtRlV/bCG6TdGC7qbxC2FxX9eAj8ODMacO4WZDU u/rq5d7zXaorWoVRfnDAt3YBgfKSLxolPbQEUVDqma82D90LAQtzu9M8+u4ebq4d0rN+ 4O1pD9XvRa12XUrrkCbUGCx+6j5JurMkZ2NCX/mTCR0wwf60pZCqvbPiV6UiQ/kcJLSd TAnvXeMVMFOhpUNZWBXjkRyprnfoeGE1neeey4PVirobMgnGOVl+tOL2Hc97B7GrE3CM UFojQ6/iT58B4TnQ65aE2ssrgCZ51BKRELC75ILspvKnsSO7RBWZQr0zwTER7Uute30j Wjcw== X-Gm-Message-State: AOJu0YzUQFXYh8HWRQrCtDzC85ozfCEvA8fD4wi6c2RZ1UWXkN5dT8B7 +lyxquitcQ376B6+8mpn/qQMqf6SJ5U25Iu/gIzTxlLzszScu5b02PhL X-Gm-Gg: AeBDieu1WsDpLJ4lHXDB2lTxAwtXgyd/3sUAjidyDiw0WvseWps4p6e8lmemumL3qYF y/QF2XW20lnmdhvSYfiUtfHsaT6EaFdHRan/gYWM4Vw6brbnH88xwPkKjHI/MBRSA+gFPyl8Iss 9PTeu7728cxNJedmOOWS0q//Kg1surJnuI4iiPG4NNHOmRuFiRh4Lb0iz9gEFkBLGWYwrx6EqlG ZArmeJ+9eu0dbFofOgXXBKMw3x74qdMIEUIBu6rQ6o/xcSaWa8aeo55BSqUQg75Hg2eJ5ydigW4 CGsQnqaXT0I++O0YnkP6+kG9t20bAK9iu4o8/DwqfVpOXgkkBxG/IrF6z2zzAVQRQRyZQoWhsUe KJNdAvT236V+Fj+DVVlpeGimkCqKpGPiviB3h2OO5QHTssydkQ+Xzm+cAh8G3q7sOgEWkEmTnCz CArpltNvzoYQk+YeMXOk/A9kCl8wfgrXv29mPrKjNt2J2VHxym63/Bym1owHhYrVuhzkR6djdC4 mMkWyZqrXMPrU//ziiIl1gQ3ke1fh4mRUfD0iuVJsrzrBSjY2hNssze5Bb0wJxOdCe29UyESr5Z MUD484BY15/pF2lO X-Received: by 2002:a05:6871:384e:b0:42c:2464:4ec3 with SMTP id 586e51a60fabf-42c2466f612mr2412690fac.38.1776792461139; Tue, 21 Apr 2026 10:27:41 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:29 -0600 Subject: [PATCH v2 02/13] target/mips: fix Octeon arithmetic destination handling MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-2-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::2b; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x2b.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792568574154100 BADDU and DMUL write their results to rd, not rt. Avoid treating rt =3D=3D $zero as a nop, and route writes through gen_store_gpr() so rd =3D=3D $zero is handled consistently. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Split the BADDU/DMUL destination handling fix out of the Octeon arithmetic instruction patch. (suggested by Philippe Mathieu-Daud=C3= =A9) --- target/mips/tcg/octeon_translate.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index b2eca29e06..41e0d770f5 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -45,7 +45,7 @@ static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a) { TCGv t0, t1; =20 - if (a->rt =3D=3D 0) { + if (a->rd =3D=3D 0) { /* nop */ return true; } @@ -55,8 +55,9 @@ static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a) gen_load_gpr(t0, a->rs); gen_load_gpr(t1, a->rt); =20 - tcg_gen_add_tl(t0, t0, t1); - tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff); + tcg_gen_add_i64(t0, t0, t1); + tcg_gen_andi_i64(t0, t0, 0xff); + gen_store_gpr(t0, a->rd); return true; } =20 @@ -64,7 +65,7 @@ static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a) { TCGv t0, t1; =20 - if (a->rt =3D=3D 0) { + if (a->rd =3D=3D 0) { /* nop */ return true; } @@ -74,7 +75,8 @@ static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a) gen_load_gpr(t0, a->rs); gen_load_gpr(t1, a->rt); =20 - tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1); + tcg_gen_mul_i64(t0, t0, t1); + gen_store_gpr(t0, a->rd); return true; } =20 --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792506; cv=none; d=zohomail.com; s=zohoarc; b=enEZrTHkYUzx4zCQu6qR7RJl5UA2sF6wuHcFI8Krv/I/XF6StT+FZeZYn1dFKAXOS8pqcGesl2YyIuqQnKZxBKzQ6wNIZ7QGdK5anR2f6f3LUrOlzLU9dKgInVXIUwxU7szy6HkdgNBuiZ9IErFiovCzO6SohXPf7a57+hGNMn0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792506; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=kgzwGQYDZtqHRkDL6zR0riBaHHmRrVYiB8biiUGPmfo=; b=B34gyfWbqlScRBRKuQLX0fF85kCmqTCpwJSll5DzkE1Dw2uA5pvSTaDZfwUXCQ79c3CLeUAXxkHIoVIAe3wxg4/Rj2KGZ8LGhQz2cupSVBWSv1bnUi8iaSRBOwCY4uV8JED7SRbh5goni9RNMOrx/fJT5ophALWYQ1zWZgdYIec= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792506442994.0740567669586; Tue, 21 Apr 2026 10:28:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtO-0003z7-JM; Tue, 21 Apr 2026 13:28:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEt5-0003mE-HC for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:54 -0400 Received: from mail-oo1-xc30.google.com ([2607:f8b0:4864:20::c30]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEsx-0006hJ-Gy for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:46 -0400 Received: by mail-oo1-xc30.google.com with SMTP id 006d021491bc7-6948b5b1c53so1212530eaf.1 for ; Tue, 21 Apr 2026 10:27:43 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792462; x=1777397262; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=kgzwGQYDZtqHRkDL6zR0riBaHHmRrVYiB8biiUGPmfo=; b=f801x8Ja4cmH/KHBVA+lLgNCWysFHJvuPqw4fF76mGpHv9wf3I0Kaj+7973dEUXojK wOcStprnmmXv8dXMtdbKDtiOrIo0BTrJwFQhTQ4sIy64bhDJlo9OWK2HR69Mgd2aWVdz BizPu1euPTPLjc9Xlc0LRz/W+KBUqBHXG7JhFSbX2qYlIkquETSJ+6rnjRGQCDw9xz4b kd6cEynGTX/zhdFTCXRQg4wQvvgxskApsLAJPTLHNaXSsUmiC73I9B9/YIP49sC5TIHb /0jxzmel+VfEsqenSEtIkUSz8FlVMLnwbnik4v7q4ytM1v6j2qGOEUCgJfCjwF0G6pPY Lgeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792462; x=1777397262; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=kgzwGQYDZtqHRkDL6zR0riBaHHmRrVYiB8biiUGPmfo=; b=FTaHQM81a44Hq10f+wsQr4Zj6rPy1AvO0BeyKfOh6ULG8oI6bF7HZKleQ/gLMlwDPB Qq3i4MdmTIeU3hmo1m1Xm/az5LVjgeySHT2SEoJAcrBmsHk/jA3MGtvrYp/6piWGp9Dq 3DZDxngblpdnMG8ljbY5C/o+eNAu6GojmUcT0otEjh/97RHxogNTUmfIjL6I9+oRFO5g 5znf4nWR5KdX7YFamtVZzLchFRBeJJXBNvEVf9cDqQcJXjegW2OhdKtrB76v5NJnhT39 UejqY0LnwfFNe6pQhI2QmJPGHQp8AEerW48xwLey5Wgtcqb10TqnvEfuCdAgioBjqSe9 2wog== X-Gm-Message-State: AOJu0YwIDA7+GOc+5du7KhW4kRWgHHKD/Jd1rZDVJPK5ngcZGfwv7SAT iAY8Vvu9AWyXTdMHeiOrqrMbUr8idtpHZcarejW+ZGvqeMOuoSDy9NQP X-Gm-Gg: AeBDieu5s0+/Yy5NBSs1XjAMAFW46yEc3Y3fZ/8gNbbCbwKzZcvNBFlcRsMAxs4DwHK SpT3Dr0Vd3NZJXxzxW8+ihjtiB3ctge/JUTUsA11An6dNY3EDw46+XV+gbl55V5visLr2jeDlPD 4RlGxHjjUfs06I6Y3qmWZwbE4imukbeRlB+HESInDp3WkEej6I96SHuSu3Oo/eoSEcCIVZtSre6 5eXkZeTjchSrPNPO+JQfFXWT1i1xCbXJs+u4h0vpAolkfyLaiD+YaX8Z0od/BsJzrnoSsOvM1y3 hvuV7gehtWAlQfTeUuH2N6yWAC4O/RQAyr8vKHu6wTBdz1+UyBolzAJxWGi5Dy/Z1xoGNPemGKw OXgxULzkrI6qcSwmU1/B4N6sJwvFtsIq4pbo0EW07k08644lzyv09TWzy38rZbnqf4EePDbhf4z r3GFsTmd+pjshQydZ4YBcTICg7CvGf0iJ+aRYryVY66BVuSfDetFNsvdiT3CqC6Y5Sa5L2U8e88 qv1S2kQ+sEnISmN8WOaTdKyxZOPEN9Adaqa/CnkwTJz/Mxs72kShMWFJ2ZQ5I6PZkFEwACbN/26 ap4+2YGYs18IvvXq X-Received: by 2002:a05:6820:f03:b0:67b:f12a:dfcb with SMTP id 006d021491bc7-69462f2ee31mr11258364eaf.60.1776792462189; Tue, 21 Apr 2026 10:27:42 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:30 -0600 Subject: [PATCH v2 03/13] target/mips: split Octeon SEQ/SNE decode MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-3-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::c30; envelope-from=james.hilliard1@gmail.com; helo=mail-oo1-xc30.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792507984154100 Decode the equality and inequality forms as explicit SEQ/SNE and SEQI/SNEI instructions rather than using shared generated SEQNE/SEQNEI entries. The explicit decoder names match the architectural mnemonics, which makes the translator entry points and trace/debug output easier to correlate with the instruction set. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Split the SEQ/SNE decode cleanup out of the Octeon arithmetic instruction patch. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/tcg/octeon.decode | 8 ++++++-- target/mips/tcg/octeon_translate.c | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode index 102a05860d..8a262feb1d 100644 --- a/target/mips/tcg/octeon.decode +++ b/target/mips/tcg/octeon.decode @@ -30,6 +30,8 @@ BBIT 11 set:1 . 10 rs:5 ..... offset:s16 p=3D%bbi= t_p # SNEI rt, rs, immediate =20 @r3 ...... rs:5 rt:5 rd:5 ..... ...... +&cmp3 rs rt rd ne +&cmpi rs rt imm ne %bitfield_p 0:1 6:5 @bitfield ...... rs:5 rt:5 lenm1:5 ..... ..... . p=3D%bitfield_p =20 @@ -38,8 +40,10 @@ DMUL 011100 ..... ..... ..... 00000 000011 @r3 EXTS 011100 ..... ..... ..... ..... 11101 . @bitfield CINS 011100 ..... ..... ..... ..... 11001 . @bitfield POP 011100 rs:5 00000 rd:5 00000 10110 dw:1 -SEQNE 011100 rs:5 rt:5 rd:5 00000 10101 ne:1 -SEQNEI 011100 rs:5 rt:5 imm:s10 10111 ne:1 +SEQ 011100 rs:5 rt:5 rd:5 00000 101010 &cmp3 ne=3D0 +SNE 011100 rs:5 rt:5 rd:5 00000 101011 &cmp3 ne=3D1 +SEQI 011100 rs:5 rt:5 imm:s10 101110 &cmpi ne=3D0 +SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi ne=3D1 =20 &lx base index rd @lx ...... base:5 index:5 rd:5 ...... ..... &lx diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index 41e0d770f5..fce01eb196 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -131,7 +131,7 @@ static bool trans_POP(DisasContext *ctx, arg_POP *a) return true; } =20 -static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a) +static bool trans_seqne(DisasContext *ctx, const arg_cmp3 *a) { TCGv t0, t1; =20 @@ -154,7 +154,17 @@ static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *= a) return true; } =20 -static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a) +static bool trans_SEQ(DisasContext *ctx, arg_cmp3 *a) +{ + return trans_seqne(ctx, a); +} + +static bool trans_SNE(DisasContext *ctx, arg_cmp3 *a) +{ + return trans_seqne(ctx, a); +} + +static bool trans_seqnei(DisasContext *ctx, const arg_cmpi *a) { TCGv t0; =20 @@ -168,7 +178,7 @@ static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI = *a) gen_load_gpr(t0, a->rs); =20 /* Sign-extend to 64 bit value */ - target_ulong imm =3D a->imm; + int64_t imm =3D a->imm; if (a->ne) { tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm); } else { @@ -177,6 +187,16 @@ static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI= *a) return true; } =20 +static bool trans_SEQI(DisasContext *ctx, arg_cmpi *a) +{ + return trans_seqnei(ctx, a); +} + +static bool trans_SNEI(DisasContext *ctx, arg_cmpi *a) +{ + return trans_seqnei(ctx, a); +} + static bool trans_lx(DisasContext *ctx, arg_lx *a, MemOp mop) { gen_lx(ctx, a->rd, a->base, a->index, mop); --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792560; cv=none; d=zohomail.com; s=zohoarc; b=a347S2PJagvMicTl03JQu0Zl5lq9OLOQNtmESmRkzWt+evWhg/3iPe77+akVL85dX9rfCtIO2N4HRuRRiQc4HDa12Pyot9DxYdXtIyPDA0Zxn9sfa3qWe2fzFAhhZIeedwv/lcUYlDNQyzGW0qag/083ZdmLDEVmdhpAXVL5doY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792560; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=mfdyYv/dTUTBorCKUtHWx0TpDUjZosLCy+lrLFfRytI=; b=R9PxQuwm6aVfkItnWYYMufUlamYa2npxHoVNVk3OPWnaPD1wvQbnrmRmCWp/5AGS4CtHl/kcuOz6saSOg0otCrumuL/61Jpv6TrUv029Kf/pbHjM66sfu1wl+Jo1S8Qaxx9yRdrQaO35i+475T8QVns41+Qz1p93R6nE/7Fi0pw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792560325915.2493308203381; Tue, 21 Apr 2026 10:29:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtR-000434-Fr; Tue, 21 Apr 2026 13:28:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtB-0003nT-Sx for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:59 -0400 Received: from mail-oa1-x36.google.com ([2001:4860:4864:20::36]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt6-0006hS-GW for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:55 -0400 Received: by mail-oa1-x36.google.com with SMTP id 586e51a60fabf-41708f6c3feso2904203fac.3 for ; Tue, 21 Apr 2026 10:27:44 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792463; x=1777397263; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=mfdyYv/dTUTBorCKUtHWx0TpDUjZosLCy+lrLFfRytI=; b=hwfD3oZNj2o4QL5AwNjmvhyX9LrVVc1JHOtQdbSQWMEsfFHTqFVdUraN7RQHD/11tk /cO7tDf/G0wcFhykfUJIjogURpgnL9IgX73bFZ7pTbLdyI1bUDhkSnOeak/ykj3v3lX6 1irxuaCWwLFnnAnMcrzOsi2+HAX5D6ZR0UPjo+dAr7QbtNjNi3NpbrjBVdGEQzCuFlH2 kkkhpn7xzt9Z/oY9Xnxh2zyXOtHzG7ekjEut72jOjrgcjNKtutpuS2SYGCEQwGSN9XNw NahIr12lZeA5Tlid0a1X20A92jEua/KXXoL6szTanxYFKEkzMx7aAqf+KoINpvO9/410 jUfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792463; x=1777397263; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=mfdyYv/dTUTBorCKUtHWx0TpDUjZosLCy+lrLFfRytI=; b=DoI3h45dbKqUfWLelEr9aDvPN8LeLo6Ig6O+xQb2Jau3shsaKXkVMDdZ98Eu6jeGww LCWPVDIVn7G+Ixb37yij88ZAQe8MKw5s8lObAs319zNWOE2WVU+yZPCOvPnqSSc+GRdR sD6lSo/WLjZ71ckOol58c69AegQKgZHH7gPU1d7YmqQpsauGaP7oOqLOoDHk9KvWn+WX GfSN0nQw+ya+4nX4V0GFfpx84Z0nwR6ZxoVCAa13K2gT2mYxcXz+44f3Q6kwLSq3yP69 JIMUO8ZXw/VXROhKV6SSci55u+4WthDsa9QfkqIqvV7E+0wU8CUgd/WVYd67Us43Stcx vOQg== X-Gm-Message-State: AOJu0Yxs+zT0CJ8bDylV9kSQiKEVHmq7XWhPLFrTHnnb5tjU5ukfooF1 GQ3C7oRrY8gEKOIk2EJwTlW45w3kzWoH+ol3uL+CKjnJd8jh5j5aAdS8 X-Gm-Gg: AeBDietJN9aqtpzaB0D4dCaa6hbSdZQz1g8q9igDOsYJz/+JCRvIMbPrtDXMw61vPUb sXKbWf9N/IdtWeVugzMpDyQM2I7YQ1Tk98myciYXhpNLauAPs6Sh0U2zZE/6tBMWGgwEo1VqkjV AVFZlrgQI6kqKV7KQdygmskj1JVzmvjN+Jb7zAXktLGqXD/SM8YXpC9uTenysqGASSYqnMRWv0a qMNR76LNTh5XQruuDSyOYPOTfZ/wc3pZNZOfxIjSRA7vi1NbkkJT0LSET6zCh0tT3CnWd0LSGQn DYPPuIHBi/a0qRaY4az6nj7Ev0569CXw3uRqwpwWoZjS/pCc+DWvboUJwTLJ1E7o42g7JqrM+2g XVUaCX93TgIM6CQKcmxtA+4LIihPGVwIZC66+itnm9ZCjla0Ri7eZffrdEp0gnw6kwzyro6nFGR 1K3ykJZKPVnSk0HEGVIxDWESpqXKnYzhPD+GN02t4WhcAMwQ70HB6TJFwhugi3D5m2Pbb7tm6gx C9ApmtjriibUDj0yG2Fixx3M2YV3sUaJ79oTcvveee7dUEocooczkCO26Z9rel4ooZ0AvdZ3mkl iQdiMjwJGnrJEYi1 X-Received: by 2002:a05:6870:44d1:b0:3f1:6d93:4386 with SMTP id 586e51a60fabf-42abf2171f5mr11561447fac.1.1776792462967; Tue, 21 Apr 2026 10:27:42 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:31 -0600 Subject: [PATCH v2 04/13] target/mips: use explicit i64 TCG ops for Octeon translation MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-4-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::36; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x36.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792562750154100 Octeon instructions are only available on 64-bit CPUs. Use explicit i64 TCG temporaries and operations in the existing Octeon translator paths, and reject 64-bit-only forms when decoding for a non-64-bit target. This matches the architectural restriction directly and avoids depending on target_ulong width in translator code that is only valid for MIPS64. Signed-off-by: James Hilliard --- target/mips/tcg/octeon_translate.c | 76 +++++++++++++++++++++++-----------= ---- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index fce01eb196..73090ce6d8 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -13,9 +13,15 @@ /* Include the auto-generated decoder. */ #include "decode-octeon.c.inc" =20 +static bool octeon_check_64(DisasContext *ctx) +{ + check_mips_64(ctx); + return ctx->base.is_jmp =3D=3D DISAS_NEXT; +} + static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a) { - TCGv p; + TCGv_i64 p; =20 if (ctx->hflags & MIPS_HFLAG_BMASK) { LOG_DISAS("Branch in delay / forbidden slot at PC 0x%" VADDR_PRIx = "\n", @@ -25,14 +31,14 @@ static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a) } =20 /* Load needed operands */ - TCGv t0 =3D tcg_temp_new(); + TCGv_i64 t0 =3D tcg_temp_new_i64(); gen_load_gpr(t0, a->rs); =20 - p =3D tcg_constant_tl(1ULL << a->p); + p =3D tcg_constant_i64(1ULL << a->p); if (a->set) { - tcg_gen_and_tl(bcond, p, t0); + tcg_gen_and_i64(bcond, p, t0); } else { - tcg_gen_andc_tl(bcond, p, t0); + tcg_gen_andc_i64(bcond, p, t0); } =20 ctx->hflags |=3D MIPS_HFLAG_BC; @@ -43,15 +49,15 @@ static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a) =20 static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a) { - TCGv t0, t1; + TCGv_i64 t0, t1; =20 if (a->rd =3D=3D 0) { /* nop */ return true; } =20 - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); + t0 =3D tcg_temp_new_i64(); + t1 =3D tcg_temp_new_i64(); gen_load_gpr(t0, a->rs); gen_load_gpr(t1, a->rt); =20 @@ -63,15 +69,19 @@ static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a) =20 static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a) { - TCGv t0, t1; + TCGv_i64 t0, t1; + + if (!octeon_check_64(ctx)) { + return true; + } =20 if (a->rd =3D=3D 0) { /* nop */ return true; } =20 - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); + t0 =3D tcg_temp_new_i64(); + t1 =3D tcg_temp_new_i64(); gen_load_gpr(t0, a->rs); gen_load_gpr(t1, a->rt); =20 @@ -82,74 +92,78 @@ static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a) =20 static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a) { - TCGv t0; + TCGv_i64 t0; =20 if (a->rt =3D=3D 0) { /* nop */ return true; } =20 - t0 =3D tcg_temp_new(); + t0 =3D tcg_temp_new_i64(); gen_load_gpr(t0, a->rs); - tcg_gen_sextract_tl(t0, t0, a->p, a->lenm1 + 1); + tcg_gen_sextract_i64(t0, t0, a->p, a->lenm1 + 1); gen_store_gpr(t0, a->rt); return true; } =20 static bool trans_CINS(DisasContext *ctx, arg_CINS *a) { - TCGv t0; + TCGv_i64 t0; =20 if (a->rt =3D=3D 0) { /* nop */ return true; } =20 - t0 =3D tcg_temp_new(); + t0 =3D tcg_temp_new_i64(); gen_load_gpr(t0, a->rs); - tcg_gen_deposit_z_tl(t0, t0, a->p, a->lenm1 + 1); + tcg_gen_deposit_z_i64(t0, t0, a->p, a->lenm1 + 1); gen_store_gpr(t0, a->rt); return true; } =20 static bool trans_POP(DisasContext *ctx, arg_POP *a) { - TCGv t0; + TCGv_i64 t0; + + if (a->dw && !octeon_check_64(ctx)) { + return true; + } =20 if (a->rd =3D=3D 0) { /* nop */ return true; } =20 - t0 =3D tcg_temp_new(); + t0 =3D tcg_temp_new_i64(); gen_load_gpr(t0, a->rs); if (!a->dw) { tcg_gen_andi_i64(t0, t0, 0xffffffff); } - tcg_gen_ctpop_tl(t0, t0); + tcg_gen_ctpop_i64(t0, t0); gen_store_gpr(t0, a->rd); return true; } =20 static bool trans_seqne(DisasContext *ctx, const arg_cmp3 *a) { - TCGv t0, t1; + TCGv_i64 t0, t1; =20 if (a->rd =3D=3D 0) { /* nop */ return true; } =20 - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); + t0 =3D tcg_temp_new_i64(); + t1 =3D tcg_temp_new_i64(); =20 gen_load_gpr(t0, a->rs); gen_load_gpr(t1, a->rt); =20 if (a->ne) { - tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[a->rd], t1, t0); + tcg_gen_setcond_i64(TCG_COND_NE, cpu_gpr[a->rd], t1, t0); } else { - tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0); + tcg_gen_setcond_i64(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0); } return true; } @@ -166,23 +180,23 @@ static bool trans_SNE(DisasContext *ctx, arg_cmp3 *a) =20 static bool trans_seqnei(DisasContext *ctx, const arg_cmpi *a) { - TCGv t0; + TCGv_i64 t0; =20 if (a->rt =3D=3D 0) { /* nop */ return true; } =20 - t0 =3D tcg_temp_new(); + t0 =3D tcg_temp_new_i64(); =20 gen_load_gpr(t0, a->rs); =20 /* Sign-extend to 64 bit value */ int64_t imm =3D a->imm; if (a->ne) { - tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm); + tcg_gen_setcondi_i64(TCG_COND_NE, cpu_gpr[a->rt], t0, imm); } else { - tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm); + tcg_gen_setcondi_i64(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm); } return true; } @@ -199,6 +213,10 @@ static bool trans_SNEI(DisasContext *ctx, arg_cmpi *a) =20 static bool trans_lx(DisasContext *ctx, arg_lx *a, MemOp mop) { + if (mop =3D=3D MO_UQ && !octeon_check_64(ctx)) { + return true; + } + gen_lx(ctx, a->rd, a->base, a->index, mop); =20 return true; --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792593; cv=none; d=zohomail.com; s=zohoarc; b=axHcWvPH+kNGlPVEDFXTbcFVMskYJdRPw/S5oulzLH+v9ivUF2xDZNvVuqqaHEdpbRC1gFkh1FkK23sGEritYnL3nh/VbSFHBNI22ECUjvEWqs7Hu+l5Zbn6XIU27ppO6eLnmCLBkVnoL7oTMpikukZyuA1XvFY4Bs4nnBYA1t0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792593; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BIsUw1mp7IHlqAyWM9/A9YdCTgfbL/y/tQpzXOmlOQ0=; b=c2RbCQPbPQRAsJ1BTD03l1y4uVmIoHP5lfp5CwW/DGsh9mGq7xbX+wRWL9nkhDioVJxk9eYQrYx1DdgAVUnHR95FwefjhBxK3oHHM9pm8iagyC94pFWWkXhKZFcNcz1hpmQ/0JUJrYZRfsM+CdDxz37uTHKAHQlcrPoDbwvinH0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792593758388.38776484483276; Tue, 21 Apr 2026 10:29:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtN-0003u8-5e; Tue, 21 Apr 2026 13:28:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtB-0003nM-CA for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:58 -0400 Received: from mail-oa1-x33.google.com ([2001:4860:4864:20::33]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt5-0006hi-84 for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:54 -0400 Received: by mail-oa1-x33.google.com with SMTP id 586e51a60fabf-415e568a7ecso1911221fac.0 for ; Tue, 21 Apr 2026 10:27:44 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792464; x=1777397264; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=BIsUw1mp7IHlqAyWM9/A9YdCTgfbL/y/tQpzXOmlOQ0=; b=Bm9F9t0avNpLIH5IEs95LaGXk8ArQeNe5z+dqFv81uHMJyQiZQ68kOhLR1oJk4WjFG TnOakXtTAU92e8vM5FyP5BSwPZqmFw3sMsFFMNgHsTkJ/nFiOy7AqcNJmUwdOdrZ/mrb Tp/SDbRvW+HzcpE2/r4pqK12I6ZB6h390GlOmS8lR0k/awFCQ0BQaXdwQJ9ZR1B5mkOe dS19imuC138BonTL3rUZdWzyuhWup3IZeqqI3PKDoquF6h9hHq2NWAFbLHu28MaQDZDH 1DBWymwf19xW7p1eWF4DWO19HyniMcZs+oUdXQ+dvuRBYIATizFv7F2rTJp5Ho6x3cgo A0xQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792464; x=1777397264; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=BIsUw1mp7IHlqAyWM9/A9YdCTgfbL/y/tQpzXOmlOQ0=; b=NJBGX57sn/d8I3BKU/x6SfLCSURv5zAS1rOUm5660huZr9vNvkSW9n67Z+/BNNRqhW ZFibCHtFSvLYNn4zqLJUkSD3mmxg1/z3WIC+4qx25qTP3EfRxfBmFsf490qR/Gdv3kza 3Ncx6OeT7FSg5YJ8bI7HzsRAVdBimg7fimibCf5CdlTuUp0NIz5qYCKqBqZpfx/3AqUZ DmXOV9hb+b1OSfEuGB9wSYu1WXZaADLxVj5TDo4FxQskRlQo9yi03gk+DyXgnVj2jq5o 1VKA0M/YtBGiB9N4WzHSJ13eH6yYqWd9N5xAq0xlc/8Dvt6PFILCM5Ph3q0j2zuLByR6 D+DQ== X-Gm-Message-State: AOJu0Yzshsf36ecMA4n/S7wST9XlL6UG7FkYXkutXQMclQJELcqw2KRp OCrF8R+ssUz4yuFXe7rVYIqfEjtNWTMqJz9SUOxRV/wv0YozIDLcKn65 X-Gm-Gg: AeBDieveDhycG28hTGwTPmVfYfoV181RIp7I6khCmChbOheJost53dtX3YCBd843KnP Bocn7bFYcJcM9fcN3t/taqncwhjyZzMcVFZuHBpBNnpJwNLtURunvsEV50oat5adQLmHf6oW10s p/j9jK6KlTtdRAZa6JdThYUXIH5Dw7iGkQJtjdOrm2sKvC1fe5G3asMrL4osbXOuxFENNLkSzg3 lkxPi654KUo+S+SQMojQxWKinHoPBe00yrQYXPs8F3S8gbPd+fUNaoP78bIoggUJpcALEElc9aa JwUg0lkeLSNsAWDfc5wh3xiXkS95rvbuE3YxdkJl9KL2ZdS11ikT9doOD9/jK9ZhC0Bgeq9e3rz vdx6bqwzw26wQrXv49tZhtmgJyVaCkBTwTPe6Thmg/aVi9VTXlvIXYFgibmTg7oChjlZg8yUxO/ r010mikXYEklpB6mXRqQ+M32/cUfIMFVRbIPY/jVhuDh1TAfB/YnYS5C9ekJK6k7DK/EfzDtgZT mBoX/0MZrRY63P51ij6eYup8V1QDihVxJoXsVDKuGp4WFTCmNjEOTYz6ZjX6T+hkUWYRLq66iUX YacIHSNwumijpxrQ X-Received: by 2002:a05:6870:b61a:b0:424:6bf4:314e with SMTP id 586e51a60fabf-42aded18a4dmr11650984fac.18.1776792463872; Tue, 21 Apr 2026 10:27:43 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:32 -0600 Subject: [PATCH v2 05/13] target/mips: add Octeon arithmetic and memory instructions MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-5-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::33; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x33.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792597191154100 Octeon CPUs define additional integer, memory, and multiply operations beyond the base MIPS64 ISA. Add the missing decode and helper support for the remaining regular Octeon instructions used by existing user-mode workloads. This covers the indexed load forms, cache block zero operations, the Octeon multiply family, population count handling, and related arithmetic and atomic memory operations in the translator and helper layer. Add a TCG smoke test that exercises the arithmetic, compare, population count, and multiplier instructions introduced here. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Fold the initial Octeon arithmetic and multiplier smoke test into this patch. - Keep SAA/SAAD atomics naturally aligned for Octeon L2 transactions. - Split pre-existing BADDU/DMUL and SEQ/SNE translator changes into preliminary patches. (suggested by Philippe Mathieu-Daud=C3=A9) - Store Octeon multiplier state in uint64_t arrays instead of target_ulong scalar fields. (suggested by Philippe Mathieu-Daud=C3=A9) - Keep Octeon68XX CPU feature exposure out of this patch. (suggested by Philippe Mathieu-Daud=C3=A9) --- MAINTAINERS | 2 + target/mips/cpu.h | 4 + target/mips/helper.h | 3 + target/mips/system/machine.c | 33 +++++ target/mips/tcg/octeon.decode | 22 ++++ target/mips/tcg/octeon_translate.c | 166 ++++++++++++++++++++++= ++++ target/mips/tcg/op_helper.c | 99 +++++++++++++++ tests/tcg/mips/Makefile.target | 11 ++ tests/tcg/mips/user/isa/octeon/octeon-insns.c | 145 ++++++++++++++++++++++ tests/tcg/mips64/Makefile.target | 20 ++++ tests/tcg/mips64el/Makefile.target | 8 ++ 11 files changed, 513 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ad215eced8..3cfb10d076 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -306,6 +306,8 @@ F: target/mips/ F: disas/*mips.c F: docs/system/cpu-models-mips.rst.inc F: tests/tcg/mips/ +F: tests/tcg/mips64/ +F: tests/tcg/mips64el/ =20 OpenRISC TCG CPUs M: Stafford Horne diff --git a/target/mips/cpu.h b/target/mips/cpu.h index ac81470576..540edf2906 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -497,6 +497,10 @@ struct TCState { target_ulong CP0_TCScheFBack; int32_t CP0_Debug_tcstatus; target_ulong CP0_UserLocal; + struct { + uint64_t MPL[2 * 3]; + uint64_t P[2 * 3]; + } octeon; =20 int32_t msacsr; =20 diff --git a/target/mips/helper.h b/target/mips/helper.h index b6cd53c853..756ef92bfd 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -24,6 +24,9 @@ DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_3(crc32, tl, tl, tl, i32) DEF_HELPER_3(crc32c, tl, tl, tl, i32) DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32) +DEF_HELPER_3(octeon_vmulu, i64, env, i64, i64) +DEF_HELPER_3(octeon_vmm0, i64, env, i64, i64) +DEF_HELPER_3(octeon_v3mulu, i64, env, i64, i64) =20 /* microMIPS functions */ DEF_HELPER_4(lwm, void, env, tl, tl, i32) diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c index 473d3ab036..c29b7c56fa 100644 --- a/target/mips/system/machine.c +++ b/target/mips/system/machine.c @@ -118,6 +118,17 @@ static const VMStateDescription vmstate_inactive_tc = =3D { .fields =3D vmstate_tc_fields }; =20 +static const VMStateDescription vmstate_octeon_multiplier_tc =3D { + .name =3D "cpu/tc/octeon_multiplier", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT64_ARRAY(octeon.MPL, TCState, 2 * 3), + VMSTATE_UINT64_ARRAY(octeon.P, TCState, 2 * 3), + VMSTATE_END_OF_LIST() + } +}; + /* MVP state */ =20 static const VMStateDescription vmstate_mvp =3D { @@ -237,6 +248,27 @@ static const VMStateDescription mips_vmstate_timer =3D= { } }; =20 +static bool mips_octeon_needed(void *opaque) +{ + MIPSCPU *cpu =3D opaque; + + return cpu->env.insn_flags & INSN_OCTEON; +} + +static const VMStateDescription mips_vmstate_octeon_multiplier =3D { + .name =3D "cpu/octeon_multiplier", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D mips_octeon_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_STRUCT(env.active_tc, MIPSCPU, 1, + vmstate_octeon_multiplier_tc, TCState), + VMSTATE_STRUCT_ARRAY(env.tcs, MIPSCPU, MIPS_SHADOW_SET_MAX, 1, + vmstate_octeon_multiplier_tc, TCState), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_mips_cpu =3D { .name =3D "cpu", .version_id =3D 21, @@ -353,6 +385,7 @@ const VMStateDescription vmstate_mips_cpu =3D { }, .subsections =3D (const VMStateDescription * const []) { &mips_vmstate_timer, + &mips_vmstate_octeon_multiplier, NULL } }; diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode index 8a262feb1d..2eb15aa17f 100644 --- a/target/mips/tcg/octeon.decode +++ b/target/mips/tcg/octeon.decode @@ -44,10 +44,32 @@ SEQ 011100 rs:5 rt:5 rd:5 00000 101010 &cmp3 n= e=3D0 SNE 011100 rs:5 rt:5 rd:5 00000 101011 &cmp3 ne=3D1 SEQI 011100 rs:5 rt:5 imm:s10 101110 &cmpi ne=3D0 SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi ne=3D1 +&r2 rs rt +MTM0 011100 rs:5 rt:5 00000 00000 001000 &r2 +MTP0 011100 rs:5 rt:5 00000 00000 001001 &r2 +MTP1 011100 rs:5 rt:5 00000 00000 001010 &r2 +MTP2 011100 rs:5 rt:5 00000 00000 001011 &r2 +MTM1 011100 rs:5 rt:5 00000 00000 001100 &r2 +MTM2 011100 rs:5 rt:5 00000 00000 001101 &r2 +VMULU 011100 ..... ..... ..... 00000 001111 @r3 +VMM0 011100 ..... ..... ..... 00000 010000 @r3 +V3MULU 011100 ..... ..... ..... 00000 010001 @r3 + +&saa base rt +@saa ...... base:5 rt:5 ................ &saa +SAA 011100 ..... ..... 00000 00000 011000 @saa +SAAD 011100 ..... ..... 00000 00000 011001 @saa + +&zcb base +ZCB 011100 base:5 00000 00000 11100 011111 &zcb +ZCBT 011100 base:5 00000 00000 11101 011111 &zcb =20 &lx base index rd @lx ...... base:5 index:5 rd:5 ...... ..... &lx LWX 011111 ..... ..... ..... 00000 001010 @lx LHX 011111 ..... ..... ..... 00100 001010 @lx +LHUX 011111 ..... ..... ..... 10100 001010 @lx LBUX 011111 ..... ..... ..... 00110 001010 @lx +LWUX 011111 ..... ..... ..... 10000 001010 @lx +LBX 011111 ..... ..... ..... 10110 001010 @lx LDX 011111 ..... ..... ..... 01000 001010 @lx diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index 73090ce6d8..cdb4d36c8e 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -13,6 +13,8 @@ /* Include the auto-generated decoder. */ #include "decode-octeon.c.inc" =20 +typedef void gen_helper_lmi(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64); + static bool octeon_check_64(DisasContext *ctx) { check_mips_64(ctx); @@ -222,7 +224,171 @@ static bool trans_lx(DisasContext *ctx, arg_lx *a, Me= mOp mop) return true; } =20 +static bool trans_saa(DisasContext *ctx, arg_saa *a, MemOp mop) +{ + if (mop =3D=3D MO_UQ && !octeon_check_64(ctx)) { + return true; + } + + TCGv_i64 addr =3D tcg_temp_new_i64(); + MemOp amo =3D mo_endian(ctx) | mop | MO_ALIGN; + + gen_base_offset_addr(ctx, addr, a->base, 0); + + if (mop =3D=3D MO_UQ) { + TCGv_i64 value =3D tcg_temp_new_i64(); + TCGv_i64 old =3D tcg_temp_new_i64(); + + gen_load_gpr(value, a->rt); + tcg_gen_atomic_fetch_add_i64(old, addr, value, ctx->mem_idx, amo); + } else { + TCGv_i64 value =3D tcg_temp_new_i64(); + TCGv_i32 value32 =3D tcg_temp_new_i32(); + TCGv_i32 old =3D tcg_temp_new_i32(); + + gen_load_gpr(value, a->rt); + tcg_gen_extrl_i64_i32(value32, value); + tcg_gen_atomic_fetch_add_i32(old, addr, value32, ctx->mem_idx, amo= ); + } + + return true; +} + +static bool trans_ZCB(DisasContext *ctx, arg_zcb *a) +{ + TCGv_i64 addr =3D tcg_temp_new_i64(); + TCGv_i64 line =3D tcg_temp_new_i64(); + TCGv_i64 zero =3D tcg_constant_i64(0); + + gen_base_offset_addr(ctx, addr, a->base, 0); + + /* + * QEMU models ZCB/ZCBT as zeroing the containing 128-byte cache line + * in guest memory. + */ + tcg_gen_andi_i64(line, addr, ~0x7fULL); + + for (int i =3D 0; i < 16; i++) { + TCGv_i64 slot =3D tcg_temp_new_i64(); + + tcg_gen_addi_i64(slot, line, i * 8); + tcg_gen_qemu_st_i64(zero, slot, ctx->mem_idx, mo_endian(ctx) | MO_= UQ); + } + + return true; +} + +static bool trans_ZCBT(DisasContext *ctx, arg_zcb *a) +{ + return trans_ZCB(ctx, a); +} + +static ptrdiff_t octeon_tc_mpl_offset(unsigned int index) +{ + return offsetof(CPUMIPSState, active_tc.octeon.MPL[index]); +} + +static ptrdiff_t octeon_tc_p_offset(unsigned int index) +{ + return offsetof(CPUMIPSState, active_tc.octeon.P[index]); +} + +static void octeon_store_tc_field(ptrdiff_t offset, TCGv_i64 value) +{ + tcg_gen_st_i64(value, tcg_env, offset); +} + +static void octeon_zero_partial_product_state(void) +{ + TCGv_i64 zero =3D tcg_constant_i64(0); + + for (int i =3D 0; i < 2 * 3; i++) { + octeon_store_tc_field(octeon_tc_p_offset(i), zero); + } +} + +static void octeon_clear_upper_multiplier_state(void) +{ + TCGv_i64 zero =3D tcg_constant_i64(0); + + /* + * MTM0 starts a new multiplier chain. Guest code relies on a single + * MTM0 load making the remaining multiplier limbs zero unless later + * MTM1/MTM2 instructions explicitly populate them. + */ + octeon_store_tc_field(octeon_tc_mpl_offset(1), zero); + octeon_store_tc_field(octeon_tc_mpl_offset(2), zero); + octeon_store_tc_field(octeon_tc_mpl_offset(4), zero); + octeon_store_tc_field(octeon_tc_mpl_offset(5), zero); +} + +static bool trans_mtm(DisasContext *ctx, arg_r2 *a, unsigned int index) +{ + if (!octeon_check_64(ctx)) { + return true; + } + + TCGv_i64 value =3D tcg_temp_new_i64(); + + gen_load_gpr(value, a->rs); + octeon_store_tc_field(octeon_tc_mpl_offset(index), value); + gen_load_gpr(value, a->rt); + octeon_store_tc_field(octeon_tc_mpl_offset(index + 3), value); + if (index =3D=3D 0) { + octeon_clear_upper_multiplier_state(); + } + octeon_zero_partial_product_state(); + return true; +} + +static bool trans_mtp(DisasContext *ctx, arg_r2 *a, unsigned int index) +{ + if (!octeon_check_64(ctx)) { + return true; + } + + TCGv_i64 value =3D tcg_temp_new_i64(); + + gen_load_gpr(value, a->rs); + octeon_store_tc_field(octeon_tc_p_offset(index), value); + gen_load_gpr(value, a->rt); + octeon_store_tc_field(octeon_tc_p_offset(index + 3), value); + return true; +} + +static bool trans_vmul(DisasContext *ctx, arg_decode_ext_octeon1 *a, + gen_helper_lmi *helper) +{ + if (!octeon_check_64(ctx)) { + return true; + } + + TCGv_i64 rs =3D tcg_temp_new_i64(); + TCGv_i64 rt =3D tcg_temp_new_i64(); + TCGv_i64 rd =3D tcg_temp_new_i64(); + + gen_load_gpr(rs, a->rs); + gen_load_gpr(rt, a->rt); + helper(rd, tcg_env, rs, rt); + gen_store_gpr(rd, a->rd); + return true; +} + +TRANS(SAA, trans_saa, MO_UL); +TRANS(SAAD, trans_saa, MO_UQ); +TRANS(LBX, trans_lx, MO_SB); TRANS(LBUX, trans_lx, MO_UB); TRANS(LHX, trans_lx, MO_SW); +TRANS(LHUX, trans_lx, MO_UW); TRANS(LWX, trans_lx, MO_SL); +TRANS(LWUX, trans_lx, MO_UL); TRANS(LDX, trans_lx, MO_UQ); +TRANS(MTM0, trans_mtm, 0); +TRANS(MTM1, trans_mtm, 1); +TRANS(MTM2, trans_mtm, 2); +TRANS(MTP0, trans_mtp, 0); +TRANS(MTP1, trans_mtp, 1); +TRANS(MTP2, trans_mtp, 2); +TRANS(VMULU, trans_vmul, gen_helper_octeon_vmulu); +TRANS(VMM0, trans_vmul, gen_helper_octeon_vmm0); +TRANS(V3MULU, trans_vmul, gen_helper_octeon_v3mulu); diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c index 4502ae2b5b..47b13a583c 100644 --- a/target/mips/tcg/op_helper.c +++ b/target/mips/tcg/op_helper.c @@ -144,6 +144,105 @@ target_ulong helper_rotx(target_ulong rs, uint32_t sh= ift, uint32_t shiftx, return (int64_t)(int32_t)(uint32_t)tmp5; } =20 +static void octeon_add_limb(uint64_t *sum, int limb_count, + uint64_t value, int limb) +{ + while (limb < limb_count) { + uint64_t old =3D sum[limb]; + + sum[limb] +=3D value; + if (sum[limb] >=3D old) { + break; + } + value =3D 1; + limb++; + } +} + +uint64_t helper_octeon_vmulu(CPUMIPSState *env, uint64_t rs, uint64_t rt) +{ + uint64_t lo, hi; + uint64_t sum[3] =3D {}; + + mulu64(&lo, &hi, env->active_tc.octeon.MPL[0], rs); + sum[0] =3D lo; + sum[1] =3D hi; + + mulu64(&lo, &hi, env->active_tc.octeon.MPL[1], rs); + octeon_add_limb(sum, 3, lo, 1); + octeon_add_limb(sum, 3, hi, 2); + + octeon_add_limb(sum, 3, rt, 0); + octeon_add_limb(sum, 3, env->active_tc.octeon.P[0], 0); + octeon_add_limb(sum, 3, env->active_tc.octeon.P[1], 1); + + env->active_tc.octeon.P[0] =3D sum[1]; + env->active_tc.octeon.P[1] =3D sum[2]; + return sum[0]; +} + +uint64_t helper_octeon_vmm0(CPUMIPSState *env, uint64_t rs, uint64_t rt) +{ + uint64_t lo =3D helper_octeon_vmulu(env, rs, rt); + + /* + * Complete the VMULU accumulation, then apply the MTM0-style state + * update with the low result and a zero high operand. + */ + env->active_tc.octeon.MPL[0] =3D lo; + env->active_tc.octeon.MPL[3] =3D 0; + for (int i =3D 0; i < 2 * 3; i++) { + env->active_tc.octeon.P[i] =3D 0; + } + return lo; +} + +uint64_t helper_octeon_v3mulu(CPUMIPSState *env, uint64_t rs, uint64_t rt) +{ + uint64_t lo, hi; + uint64_t sum[7] =3D {}; + + mulu64(&lo, &hi, env->active_tc.octeon.MPL[0], rs); + sum[0] =3D lo; + sum[1] =3D hi; + + mulu64(&lo, &hi, env->active_tc.octeon.MPL[1], rs); + octeon_add_limb(sum, 7, lo, 1); + octeon_add_limb(sum, 7, hi, 2); + + mulu64(&lo, &hi, env->active_tc.octeon.MPL[2], rs); + octeon_add_limb(sum, 7, lo, 2); + octeon_add_limb(sum, 7, hi, 3); + + mulu64(&lo, &hi, env->active_tc.octeon.MPL[3], rs); + octeon_add_limb(sum, 7, lo, 3); + octeon_add_limb(sum, 7, hi, 4); + + mulu64(&lo, &hi, env->active_tc.octeon.MPL[4], rs); + octeon_add_limb(sum, 7, lo, 4); + octeon_add_limb(sum, 7, hi, 5); + + mulu64(&lo, &hi, env->active_tc.octeon.MPL[5], rs); + octeon_add_limb(sum, 7, lo, 5); + octeon_add_limb(sum, 7, hi, 6); + + octeon_add_limb(sum, 7, rt, 0); + octeon_add_limb(sum, 7, env->active_tc.octeon.P[0], 0); + octeon_add_limb(sum, 7, env->active_tc.octeon.P[1], 1); + octeon_add_limb(sum, 7, env->active_tc.octeon.P[2], 2); + octeon_add_limb(sum, 7, env->active_tc.octeon.P[3], 3); + octeon_add_limb(sum, 7, env->active_tc.octeon.P[4], 4); + octeon_add_limb(sum, 7, env->active_tc.octeon.P[5], 5); + + env->active_tc.octeon.P[0] =3D sum[1]; + env->active_tc.octeon.P[1] =3D sum[2]; + env->active_tc.octeon.P[2] =3D sum[3]; + env->active_tc.octeon.P[3] =3D sum[4]; + env->active_tc.octeon.P[4] =3D sum[5]; + env->active_tc.octeon.P[5] =3D sum[6]; + return sum[0]; +} + /* these crc32 functions are based on target/loongarch/tcg/op_helper.c */ target_ulong helper_crc32(target_ulong val, target_ulong m, uint32_t sz) { diff --git a/tests/tcg/mips/Makefile.target b/tests/tcg/mips/Makefile.target index 5d17c1706e..d9dc16f8ec 100644 --- a/tests/tcg/mips/Makefile.target +++ b/tests/tcg/mips/Makefile.target @@ -8,6 +8,17 @@ MIPS_SRC=3D$(SRC_PATH)/tests/tcg/mips # Set search path for all sources VPATH +=3D $(MIPS_SRC) =20 +ifneq ($(findstring 64,$(TARGET_NAME)),) +VPATH +=3D $(MIPS_SRC)/user/isa/octeon + +MIPS64_TESTS=3Docteon-insns + +TESTS +=3D $(MIPS64_TESTS) + +octeon-insns: CFLAGS+=3D-mabi=3D64 +run-octeon-insns: QEMU_OPTS+=3D-cpu Octeon68XX +endif + # hello-mips is 32 bit only ifeq ($(findstring 64,$(TARGET_NAME)),) MIPS_TESTS=3Dhello-mips diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips= /user/isa/octeon/octeon-insns.c new file mode 100644 index 0000000000..e9db93d1b6 --- /dev/null +++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c @@ -0,0 +1,145 @@ +/* + * Test Octeon-specific user-mode instructions. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include + +static uint64_t octeon_baddu(uint64_t rs, uint64_t rt) +{ + uint64_t rd; + + asm volatile( + "move $8, %[rs]\n\t" + "move $9, %[rt]\n\t" + ".word 0x71095028\n\t" /* baddu $10, $8, $9 */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [rs] "r" (rs), [rt] "r" (rt) + : "$8", "$9", "$10"); + + return rd; +} + +static uint64_t octeon_dmul(uint64_t rs, uint64_t rt) +{ + uint64_t rd; + + asm volatile( + "move $8, %[rs]\n\t" + "move $9, %[rt]\n\t" + ".word 0x71095003\n\t" /* dmul $10, $8, $9 */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [rs] "r" (rs), [rt] "r" (rt) + : "$8", "$9", "$10"); + + return rd; +} + +static uint64_t octeon_dpop(uint64_t rs) +{ + uint64_t rd; + + asm volatile( + "move $8, %[rs]\n\t" + ".word 0x7100502d\n\t" /* dpop $10, $8 */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [rs] "r" (rs) + : "$8", "$10"); + + return rd; +} + +static uint64_t octeon_seq(uint64_t rs, uint64_t rt) +{ + uint64_t rd; + + asm volatile( + "move $8, %[rs]\n\t" + "move $9, %[rt]\n\t" + ".word 0x7109502a\n\t" /* seq $10, $8, $9 */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [rs] "r" (rs), [rt] "r" (rt) + : "$8", "$9", "$10"); + + return rd; +} + +static uint64_t octeon_sne(uint64_t rs, uint64_t rt) +{ + uint64_t rd; + + asm volatile( + "move $8, %[rs]\n\t" + "move $9, %[rt]\n\t" + ".word 0x7109502b\n\t" /* sne $10, $8, $9 */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [rs] "r" (rs), [rt] "r" (rt) + : "$8", "$9", "$10"); + + return rd; +} + +static uint64_t octeon_vmulu(uint64_t mpl0, uint64_t rs, uint64_t rt) +{ + uint64_t rd; + + asm volatile( + "move $8, %[mpl0]\n\t" + "move $9, $0\n\t" + ".word 0x71090008\n\t" /* mtm0 $8, $9 */ + "move $8, %[rs]\n\t" + "move $9, %[rt]\n\t" + ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [mpl0] "r" (mpl0), [rs] "r" (rs), [rt] "r" (rt) + : "$8", "$9", "$10"); + + return rd; +} + +static uint64_t octeon_vmm0(uint64_t mpl0, uint64_t p0, + uint64_t rs, uint64_t rt) +{ + uint64_t rd; + + asm volatile( + "move $8, %[mpl0]\n\t" + "move $9, $0\n\t" + ".word 0x71090008\n\t" /* mtm0 $8, $9 */ + "move $8, %[p0]\n\t" + "move $9, $0\n\t" + ".word 0x71090009\n\t" /* mtp0 $8, $9 */ + "move $8, %[rs]\n\t" + "move $9, %[rt]\n\t" + ".word 0x71095010\n\t" /* vmm0 $10, $8, $9 */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [mpl0] "r" (mpl0), [p0] "r" (p0), + [rs] "r" (rs), [rt] "r" (rt) + : "$8", "$9", "$10"); + + return rd; +} + +int main(void) +{ + assert(octeon_baddu(0x123, 0x0f0) =3D=3D 0x13); + assert(octeon_dmul(0x12345678, 0x10) =3D=3D 0x123456780); + assert(octeon_dpop(0xf0f0f0f0f0f0f0f0ULL) =3D=3D 32); + assert(octeon_seq(0xabc, 0xabc) =3D=3D 1); + assert(octeon_seq(0xabc, 0xdef) =3D=3D 0); + assert(octeon_sne(0xabc, 0xabc) =3D=3D 0); + assert(octeon_sne(0xabc, 0xdef) =3D=3D 1); + assert(octeon_vmulu(5, 7, 11) =3D=3D 46); + assert(octeon_vmm0(5, 13, 7, 11) =3D=3D 59); + + return 0; +} diff --git a/tests/tcg/mips64/Makefile.target b/tests/tcg/mips64/Makefile.t= arget new file mode 100644 index 0000000000..042855844a --- /dev/null +++ b/tests/tcg/mips64/Makefile.target @@ -0,0 +1,20 @@ +# -*- Mode: makefile -*- +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# MIPS64 - included from tests/tcg/Makefile.target +# + +MIPS64_SRC=3D$(SRC_PATH)/tests/tcg/mips64 +MIPS_OCTEON_SRC=3D$(SRC_PATH)/tests/tcg/mips/user/isa/octeon + +# Set search path for all sources +VPATH +=3D $(MIPS64_SRC) $(MIPS_OCTEON_SRC) + +MIPS64_TESTS=3Docteon-insns + +TESTS +=3D $(MIPS64_TESTS) + +$(MIPS64_TESTS): CFLAGS+=3D-mabi=3D64 + +run-octeon-insns: QEMU_OPTS+=3D-cpu Octeon68XX diff --git a/tests/tcg/mips64el/Makefile.target b/tests/tcg/mips64el/Makefi= le.target new file mode 100644 index 0000000000..dbc5f8dc5f --- /dev/null +++ b/tests/tcg/mips64el/Makefile.target @@ -0,0 +1,8 @@ +# -*- Mode: makefile -*- +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# MIPS64 little-endian - included from tests/tcg/Makefile.target +# + +include $(SRC_PATH)/tests/tcg/mips64/Makefile.target --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792593; cv=none; d=zohomail.com; s=zohoarc; b=DzVWMu/LXlKXoGXoBqc6d28Ck+Z8Z4aIwmxGhX0Tyu8EjqELXwaIY+7btE/3nn/hQK0np6J+Z5IbZRyl/cSLZapj5wn8yAVqjvBH1YseD3hvcVFVmg/EngJmfbcsr3Yb5kN6J4pOrtDVteeCNHS/TEQo0XD0jPSgASbEIXZvhnY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792593; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=dyhSVxFzZNOrVlRzPjL3hlTh6qJUz61vh/f8LgovAlo=; b=aI6TVJvqcJrU6J3U+oSINxmC6YEyQ6LBUAV9y9SAHv0ZwBKZBUxhv39O4nvS9ElXngI6ouGeSYEkhjDKwvX1+zbYREiPiaOKJjWdLttGUknvuNH6pmEvAR9A8zOnW00gJDlc76LbQdymyfx7iCyqdXbI2jL9TZtYsEZbL4pWHrI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792593255488.32509156398794; Tue, 21 Apr 2026 10:29:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtN-0003wr-Om; Tue, 21 Apr 2026 13:28:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtC-0003nZ-0g for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:28:01 -0400 Received: from mail-ot1-x32b.google.com ([2607:f8b0:4864:20::32b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt6-0006hr-Gl for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:55 -0400 Received: by mail-ot1-x32b.google.com with SMTP id 46e09a7af769-7dcdd23fcdfso379757a34.3 for ; Tue, 21 Apr 2026 10:27:45 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792465; x=1777397265; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=dyhSVxFzZNOrVlRzPjL3hlTh6qJUz61vh/f8LgovAlo=; b=WsDcpe8tt57MUrirM7LsqayGpwM2++0EjqjLRi+yydEQxc5BhQAw4u4t/5HGOnl/sg 0nvwcMk7bQZQAoL6z/XQIiToyWm1aJKqh5016UAw6hGBGWkxNKVmMej8OahvODukoAug by9qRcgIKA+TK4feJjOFET3mUXn6pF8GovXM7euZ7FET+smS56z5R/Px2xMcJ0CaaAWN pbdF4+1CysWZSW3JRMjceeQKvHHlVSQ+3nO8W4EFMoGCzkajqa6y+6YW/KoYio9HmsJo JO9vb2PLpD5JFlHYHAzIMpvRY/Ypgsgv0wtbRC4fTfS84f8ZVJ3w804x9aur7YvD0Qh+ AJ6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792465; x=1777397265; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=dyhSVxFzZNOrVlRzPjL3hlTh6qJUz61vh/f8LgovAlo=; b=IBMKcSPrIqX3V062B9qocuYlHMLN5xJRU5Tu/LX6b+XCrGHiSBxp8OmgdTbH+bzk6/ uvuyUuginYzRDvR06CRXcemrsCNtbmuQNypLhI1eECGtfFFjvP7q5ckcm4SwrDhke++z 62ifXvdCwU2Wh8o3uR2T8vWUaNLFrmNP54mjSHVA5dMWPu9b7XalEkYqAioQywd6LAqu Lbt7Dk22+Xu5p5Ufi8jKOI72lTiYmw8KkDSFslCvfcFIFMBajTKSyM7dstIH9ppvfhZB aWuzCx68YPWseB7bUk1JyxXn18bH7aGgq/laZRKLsF/6xaM9NT4IB/ftWN2EWguKhRKc e6zw== X-Gm-Message-State: AOJu0Yw4Oqzxl0GTdQb+U1//bi+tRvEBBh2+RtOjkys1i6nAhU5ItFIJ L/BUprqmQydmH732qoHXZ5Rqw9oJLN6SuoR2UpX+vsw2BSs2EktjXwnT X-Gm-Gg: AeBDieuSeOT7ezrIS84SH7UAI2bGMf1ei/+7rQbEr+iWspbfTQBcOYGrvsR2/zdtxFF +tMtoUFzrPmqMZltHUZS1XxfRBzrYwXy+yNk3HMIpxBl1CyqGqzEh3KIYRS0fqa4wz1Cwr+wl8M HVyRBqNsQwVbVmsa6k3sjq6GxB6IGMema0brXuQEzACtbykgtx/kVYQ8O17Q89Jpj8Ncy3uQyKR GXaspqd+snxtAs5MeJtH28y17iHx7eb9Z4p/IctdZ7PWPhGjpvHn5ncjqIjg4XY+FzSA0XEdUtg 5lHozyIYWX0k4TwXSqWdaqul4devSvIveJjKYJKZEg9wKGf1JWi4NfsQcIF8UF2vKSnTXLCbmbu 6g98fgXkrIvq4pudIqVPn1K/RiiYZjvqdxOcvNarSUYvxN4TjvKyMfV5R9o6Q7TGx0xq+ykzeXN 6l90scMNl1TWBRxZnLeth8P4b6/kto6WFP1I9jQhRSqFwpYYM9NMEJNYd5WLqlzN1xfXhtWT+jX ayO9eUwi1LTLGLa3hpyGPclNtasG/bdXrfIopOFLhKwspl5pmGoRDNYTowZXdiPnnx4hsWmF4rt 6ApxuQ== X-Received: by 2002:a4a:edca:0:b0:692:3df6:79c6 with SMTP id 006d021491bc7-69462f24574mr9876123eaf.49.1776792464810; Tue, 21 Apr 2026 10:27:44 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:33 -0600 Subject: [PATCH v2 06/13] target/mips: add Octeon LA* atomic instructions MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-6-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::32b; envelope-from=james.hilliard1@gmail.com; helo=mail-ot1-x32b.google.com X-Spam_score_int: -7 X-Spam_score: -0.8 X-Spam_bar: / X-Spam_report: (-0.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FORGED_GMAIL_RCVD=1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792594235158500 Implement the Octeon LA* read-modify-write atomic instruction family: LAI/LAID, LAD/LADD, LAA/LAAD, LAS/LASD, LAC/LACD, and LAW/LAWD. These operations are architecturally distinct from SAA/SAAD and are used by existing Octeon user-mode code for atomic counters, bit operations, and exchange-style updates. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Keep LA* atomics naturally aligned per Octeon L2 transaction semantics. - Use explicit i64 TCG ops in the LA* translator paths. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/tcg/octeon.decode | 17 ++++ target/mips/tcg/octeon_translate.c | 170 +++++++++++++++++++++++++++++++++= ++++ 2 files changed, 187 insertions(+) diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode index 2eb15aa17f..9dcc5a6ae0 100644 --- a/target/mips/tcg/octeon.decode +++ b/target/mips/tcg/octeon.decode @@ -60,6 +60,23 @@ V3MULU 011100 ..... ..... ..... 00000 010001 @r3 SAA 011100 ..... ..... 00000 00000 011000 @saa SAAD 011100 ..... ..... 00000 00000 011001 @saa =20 +&la base rd +&laa base add rd +@la ...... base:5 ..... rd:5 ........... &la +@laa ...... base:5 add:5 rd:5 ........... &laa +LAI 011100 ..... 00000 ..... 00010 011111 @la +LAID 011100 ..... 00000 ..... 00011 011111 @la +LAD 011100 ..... 00000 ..... 00110 011111 @la +LADD 011100 ..... 00000 ..... 00111 011111 @la +LAA 011100 ..... ..... ..... 10010 011111 @laa +LAAD 011100 ..... ..... ..... 10011 011111 @laa +LAS 011100 ..... 00000 ..... 01010 011111 @la +LASD 011100 ..... 00000 ..... 01011 011111 @la +LAC 011100 ..... 00000 ..... 01110 011111 @la +LACD 011100 ..... 00000 ..... 01111 011111 @la +LAW 011100 ..... ..... ..... 10110 011111 @laa +LAWD 011100 ..... ..... ..... 10111 011111 @laa + &zcb base ZCB 011100 base:5 00000 00000 11100 011111 &zcb ZCBT 011100 base:5 00000 00000 11101 011111 &zcb diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index cdb4d36c8e..6309cd5fff 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -254,6 +254,164 @@ static bool trans_saa(DisasContext *ctx, arg_saa *a, = MemOp mop) return true; } =20 +static bool trans_la_common(DisasContext *ctx, int base, int add_reg, int = rd, + int64_t imm, bool dw) +{ + if (dw && !octeon_check_64(ctx)) { + return true; + } + + TCGv_i64 addr =3D tcg_temp_new_i64(); + + gen_base_offset_addr(ctx, addr, base, 0); + + if (dw) { +#if TARGET_LONG_BITS =3D=3D 64 + TCGv_i64 value =3D tcg_temp_new_i64(); + TCGv_i64 old =3D tcg_temp_new_i64(); + MemOp amo =3D mo_endian(ctx) | MO_UQ | MO_ALIGN; + + if (add_reg >=3D 0) { + gen_load_gpr(value, add_reg); + } else { + tcg_gen_movi_i64(value, imm); + } + + tcg_gen_atomic_fetch_add_i64(old, addr, value, ctx->mem_idx, amo); + gen_store_gpr(old, rd); +#endif + } else { + TCGv_i64 old =3D tcg_temp_new_i64(); + TCGv_i32 value32 =3D tcg_temp_new_i32(); + TCGv_i32 old32 =3D tcg_temp_new_i32(); + MemOp amo =3D mo_endian(ctx) | MO_UL | MO_ALIGN; + + if (add_reg < 0) { + tcg_gen_movi_i32(value32, imm); + } else { + TCGv_i64 value =3D tcg_temp_new_i64(); + + gen_load_gpr(value, add_reg); + tcg_gen_extrl_i64_i32(value32, value); + } + + tcg_gen_atomic_fetch_add_i32(old32, addr, value32, ctx->mem_idx, a= mo); + tcg_gen_ext_i32_i64(old, old32); + gen_store_gpr(old, rd); + } + + return true; +} + +static bool trans_law_common(DisasContext *ctx, int base, int add_reg, int= rd, + int64_t imm, bool dw) +{ + if (dw && !octeon_check_64(ctx)) { + return true; + } + + TCGv_i64 addr =3D tcg_temp_new_i64(); + + gen_base_offset_addr(ctx, addr, base, 0); + + if (dw) { +#if TARGET_LONG_BITS =3D=3D 64 + TCGv_i64 value =3D tcg_temp_new_i64(); + TCGv_i64 old =3D tcg_temp_new_i64(); + MemOp amo =3D mo_endian(ctx) | MO_UQ | MO_ALIGN; + + if (add_reg >=3D 0) { + gen_load_gpr(value, add_reg); + } else { + tcg_gen_movi_i64(value, imm); + } + + tcg_gen_atomic_xchg_i64(old, addr, value, ctx->mem_idx, amo); + gen_store_gpr(old, rd); +#endif + } else { + TCGv_i64 old =3D tcg_temp_new_i64(); + TCGv_i32 value32 =3D tcg_temp_new_i32(); + TCGv_i32 old32 =3D tcg_temp_new_i32(); + MemOp amo =3D mo_endian(ctx) | MO_UL | MO_ALIGN; + + if (add_reg >=3D 0) { + TCGv_i64 value =3D tcg_temp_new_i64(); + + gen_load_gpr(value, add_reg); + tcg_gen_extrl_i64_i32(value32, value); + } else { + tcg_gen_movi_i32(value32, imm); + } + + tcg_gen_atomic_xchg_i32(old32, addr, value32, ctx->mem_idx, amo); + tcg_gen_ext_i32_i64(old, old32); + gen_store_gpr(old, rd); + } + + return true; +} + +static bool trans_lai(DisasContext *ctx, arg_la *a, int unused) +{ + return trans_la_common(ctx, a->base, -1, a->rd, 1, false); +} + +static bool trans_laid(DisasContext *ctx, arg_la *a, int unused) +{ + return trans_la_common(ctx, a->base, -1, a->rd, 1, true); +} + +static bool trans_lad(DisasContext *ctx, arg_la *a, int unused) +{ + return trans_la_common(ctx, a->base, -1, a->rd, -1, false); +} + +static bool trans_ladd(DisasContext *ctx, arg_la *a, int unused) +{ + return trans_la_common(ctx, a->base, -1, a->rd, -1, true); +} + +static bool trans_laa(DisasContext *ctx, arg_laa *a, int unused) +{ + return trans_la_common(ctx, a->base, a->add, a->rd, 0, false); +} + +static bool trans_laad(DisasContext *ctx, arg_laa *a, int unused) +{ + return trans_la_common(ctx, a->base, a->add, a->rd, 0, true); +} + +static bool trans_las(DisasContext *ctx, arg_la *a, int unused) +{ + return trans_law_common(ctx, a->base, -1, a->rd, -1, false); +} + +static bool trans_lasd(DisasContext *ctx, arg_la *a, int unused) +{ + return trans_law_common(ctx, a->base, -1, a->rd, -1, true); +} + +static bool trans_lac(DisasContext *ctx, arg_la *a, int unused) +{ + return trans_law_common(ctx, a->base, -1, a->rd, 0, false); +} + +static bool trans_lacd(DisasContext *ctx, arg_la *a, int unused) +{ + return trans_law_common(ctx, a->base, -1, a->rd, 0, true); +} + +static bool trans_law(DisasContext *ctx, arg_laa *a, int unused) +{ + return trans_law_common(ctx, a->base, a->add, a->rd, 0, false); +} + +static bool trans_lawd(DisasContext *ctx, arg_laa *a, int unused) +{ + return trans_law_common(ctx, a->base, a->add, a->rd, 0, true); +} + static bool trans_ZCB(DisasContext *ctx, arg_zcb *a) { TCGv_i64 addr =3D tcg_temp_new_i64(); @@ -376,6 +534,18 @@ static bool trans_vmul(DisasContext *ctx, arg_decode_e= xt_octeon1 *a, =20 TRANS(SAA, trans_saa, MO_UL); TRANS(SAAD, trans_saa, MO_UQ); +TRANS(LAI, trans_lai, 0); +TRANS(LAID, trans_laid, 0); +TRANS(LAD, trans_lad, 0); +TRANS(LADD, trans_ladd, 0); +TRANS(LAA, trans_laa, 0); +TRANS(LAAD, trans_laad, 0); +TRANS(LAS, trans_las, 0); +TRANS(LASD, trans_lasd, 0); +TRANS(LAC, trans_lac, 0); +TRANS(LACD, trans_lacd, 0); +TRANS(LAW, trans_law, 0); +TRANS(LAWD, trans_lawd, 0); TRANS(LBX, trans_lx, MO_SB); TRANS(LBUX, trans_lx, MO_UB); TRANS(LHX, trans_lx, MO_SW); --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792580; cv=none; d=zohomail.com; s=zohoarc; b=NGYh9kagbRtcMv1Ar2b6NtDZVwEa3AeJNt1TJqaXOR7Q2Hn0292B22sbe/95F4XAPvcgBw8xmHroYMK4Ui4+v8P5EQ6jt8u8pnIDo3e83aS2S8YAEHABywZ1h6SBHalgzxqw9/NVj9zFJlAWkDhVgXHY/cBO40jOAkOpb291vj0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792580; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=J90ro9vd/+OCgHNOe/fQYAmiD6Gu+yQKI1y3Fv35DmQ=; b=lMPc9jf5igdjyxJviok0gpFPsGoUdh/d0SJmVSV3EkuYzFA6tlMVIMYEiO8n6uLEzDZTWWNgnCh1HZRG7wmAgqVyrpkidJZDT0/3YU5FAyu0h0zqS/lkKkZ+6oLHMnEydVm9DjjsjRU2nkDffNiPsChVJn+aP1JfqXTDBqWf2jA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792580879410.65598868525717; Tue, 21 Apr 2026 10:29:40 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtQ-00041M-H2; Tue, 21 Apr 2026 13:28:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtG-0003pg-7X for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:28:03 -0400 Received: from mail-oa1-x29.google.com ([2001:4860:4864:20::29]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt6-0006hw-H5 for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:28:00 -0400 Received: by mail-oa1-x29.google.com with SMTP id 586e51a60fabf-42fbf95cca8so4344fac.0 for ; Tue, 21 Apr 2026 10:27:47 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792466; x=1777397266; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=J90ro9vd/+OCgHNOe/fQYAmiD6Gu+yQKI1y3Fv35DmQ=; b=k5VeV0SLig97OnvLj/YWaZl6gsdDVRb6eTi1oyL48YKnsTOIruUCuPeBnNStcqWzLp UxGWgKCVOx9nAzIaQqiZ5YbL8Kg1b5DFz8Lmlm3X83aHZ3yGS/fkVzocGvfALNDeBlkc 07/vAoqbQjgs8UH6Njn1vu3nTuZTxzPlse4eqw8dZ/zDIrOg2dPIlFLvYbkTGABew3gu ifQ1aIyTRh7P81H2svbWbxAbUS0YMZw4RiMfRZ8wjYeZWYvtykrpSm/OKtKAUnLqrwST sA6UbOPRQfEFXzKfxsWWZtjwBfz46wkLUwhB6776+MbPEyqaBenRBOHNPFA5tvvDQqHn PMRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792466; x=1777397266; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=J90ro9vd/+OCgHNOe/fQYAmiD6Gu+yQKI1y3Fv35DmQ=; b=JOWyvjQHPqbz0XGPF2SY6ahqhszhhQDvXQrac3NecrPDEYz2ghER1uXUfJoSN/TbRz H2KXcUDdfSNeEbGW0sbSm8/NSspp67z/2DSuo7H3MqkUzu9PEyuj7zu8Us8u6kX0AfzO as9K5RFhYcUR0rLeKTDeMhVDp2d2/O+mljtrWtGsVtaK6a+XO3ydVeKjRhsiJBI/m47s c0n49kfyHEiPJyZSYxGb6t5iSSAqKcgHaSDpij4SWKR2g3J7mJYroX2d0ESUpP10Yl5Y x6CDLWcqPlHS0QIM2vTnQmfY0staAsW6RbEMPuzTdbbDdbWxaQbOXWOneK6Q/3BxVbtv B47w== X-Gm-Message-State: AOJu0YzUjPRA83n2gcB8/GpqP4kk6d7saGDLObR+RaHdxlW4EbyFanvl dAEl84L2tYW4CxB0cfAOz0xJD33Nr80OgD6dMHN4lJjaV5aRUMy+3eTD X-Gm-Gg: AeBDieuA2sQV4//PoqToRX7lf+s4+HxYsET1JHqifK2gOR8Dx6Pr8kMnG7mehT6FKPT BTW/ZbaswcT0dC0d9oQqB97BqjViPz23uf+S0VLCoRaweMkZDnK5FoWvS25Rz1HdMPcwknzHFul l8xLluRqVCCHFC2UPS+OKJBqLQk1MVCDWXiXz4OV+wFj03notzjlEsCGlsK2WOD4UAuSKX8t+g0 MuulZgkj4LI8uJN1hrUjvmvUSyr3vj0+dBdmkEHqq3DXo7bPsA0ED7Gz9g3+JFaDNDDm+kKT3DD i0Q8vp/KQxe1JKvLC3HkrCOgS5T4yHGAEWH0Cx52X5lChIOX99c/HHHOz/BsY1vJrWmB/sb/CI0 t+/wTuOVKsD967uC7NoiVjmv6JJMhtLZEisWVirawrmTnXZ8/APlHaR4yUbaN3hVwDWRcAD/5cW JIW5ZQsX/8xshbe0OGv3wL/8tMlzJv64zbLuznAcRolMMFVnbygkZZfLtHXz4Nouo6oejiuAuq0 c8ccZ+hfpXKO1uOXjXToGfbuVuP3LZWcw/Uo7GytCMLp3JejeIGINvice/F+Rqd8DVfsqlSqmfd N+I+8sG+kpwV+KM9 X-Received: by 2002:a05:6820:1620:b0:67e:1a79:1f30 with SMTP id 006d021491bc7-69462e2e231mr9107988eaf.1.1776792465731; Tue, 21 Apr 2026 10:27:45 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:34 -0600 Subject: [PATCH v2 07/13] target/mips: add Octeon COP2 crypto core support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-7-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::29; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x29.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792582864154100 Octeon processors expose their crypto engines through selector-driven DMFC2/DMTC2 accesses rather than architected standalone opcodes. Add the common COP2 state, selector decode, and helper plumbing for the base engine set. This covers the hash, AES, CRC, GFM, 3DES, KASUMI, and SNOW3G engines and moves the implementation into octeon_crypto.c to keep the MIPS helper layer manageable. Model the AES result/input selector bank as writable as well as readable. Octeon COP2 engines use these slots as result-input staging registers, so the shared bank belongs with the base selector support. Extend the TCG smoke test with AES key-register readback checks for the selector window introduced here. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Fold the AES COP2 selector readback smoke coverage into this patch. - Move Octeon COP2 decode plumbing into octeon_translate.c. (suggested by Philippe Mathieu-Daud=C3=A9) - Use uint64_t/i64 helper types for Octeon COP2 state transfers. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/cpu.h | 165 +++ target/mips/helper.h | 2 + target/mips/system/machine.c | 37 + target/mips/tcg/meson.build | 1 + target/mips/tcg/octeon_crypto.c | 1654 +++++++++++++++++++++= ++++ target/mips/tcg/octeon_translate.c | 210 ++++ target/mips/tcg/translate.c | 9 + target/mips/tcg/translate.h | 1 + tests/tcg/mips/user/isa/octeon/octeon-insns.c | 71 ++ 9 files changed, 2150 insertions(+) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 540edf2906..9e398e1ce5 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -529,6 +529,169 @@ struct TCState { }; =20 struct MIPSITUState; +typedef enum MIPSOcteonSharedMode { + OCTEON_SHARED_MODE_NONE =3D 0, + OCTEON_SHARED_MODE_SHA512, + OCTEON_SHARED_MODE_SNOW3G, +} MIPSOcteonSharedMode; + +typedef enum MIPSOcteonCop2Sel { + OCTEON_COP2_SEL_HSH_DAT0 =3D 0x0040, + OCTEON_COP2_SEL_HSH_DAT1, + OCTEON_COP2_SEL_HSH_DAT2, + OCTEON_COP2_SEL_HSH_DAT3, + OCTEON_COP2_SEL_HSH_DAT4, + OCTEON_COP2_SEL_HSH_DAT5, + OCTEON_COP2_SEL_HSH_DAT6, + OCTEON_COP2_SEL_HSH_IV0 =3D 0x0048, + OCTEON_COP2_SEL_HSH_IV1, + OCTEON_COP2_SEL_HSH_IV2, + OCTEON_COP2_SEL_HSH_IV3, + OCTEON_COP2_SEL_SHA3_DAT24 =3D 0x0050, + OCTEON_COP2_SEL_SHA3_DAT15_WRITE =3D 0x0051, + OCTEON_COP2_SEL_HSH_STARTSHA1_COMPAT =3D 0x0057, + OCTEON_COP2_SEL_GFM_MUL_REFLECT0 =3D 0x0058, + OCTEON_COP2_SEL_GFM_MUL_REFLECT1, + OCTEON_COP2_SEL_GFM_RESINP_REFLECT0 =3D 0x005a, + OCTEON_COP2_SEL_GFM_RESINP_REFLECT1, + OCTEON_COP2_SEL_GFM_XOR0_REFLECT =3D 0x005c, + OCTEON_COP2_SEL_3DES_KEY0 =3D 0x0080, + OCTEON_COP2_SEL_3DES_KEY1, + OCTEON_COP2_SEL_3DES_KEY2, + OCTEON_COP2_SEL_3DES_IV =3D 0x0084, + OCTEON_COP2_SEL_3DES_RESULT =3D 0x0088, + OCTEON_COP2_SEL_3DES_RESULT_IN =3D 0x0098, + OCTEON_COP2_SEL_3DES_ENC_CBC =3D 0x4088, + /* + * Octeon reuses the 3DES key/result bank for KASUMI and only adds + * KASUMI-specific operation selectors. + */ + OCTEON_COP2_SEL_KAS_ENC_CBC =3D 0x4089, + OCTEON_COP2_SEL_3DES_ENC =3D 0x408a, + OCTEON_COP2_SEL_KAS_ENC =3D 0x408b, + OCTEON_COP2_SEL_3DES_DEC_CBC =3D 0x408c, + OCTEON_COP2_SEL_3DES_DEC =3D 0x408e, + OCTEON_COP2_SEL_AES_RESULT0 =3D 0x0100, + OCTEON_COP2_SEL_AES_RESULT1, + OCTEON_COP2_SEL_AES_IV0, + OCTEON_COP2_SEL_AES_IV1, + OCTEON_COP2_SEL_AES_KEY0, + OCTEON_COP2_SEL_AES_KEY1, + OCTEON_COP2_SEL_AES_KEY2, + OCTEON_COP2_SEL_AES_KEY3, + OCTEON_COP2_SEL_AES_ENC_CBC0 =3D 0x0108, + OCTEON_COP2_SEL_AES_ENC0 =3D 0x010a, + OCTEON_COP2_SEL_AES_DEC_CBC0 =3D 0x010c, + OCTEON_COP2_SEL_AES_DEC0 =3D 0x010e, + OCTEON_COP2_SEL_AES_KEYLENGTH =3D 0x0110, + OCTEON_COP2_SEL_AES_DAT0 =3D 0x0111, + OCTEON_COP2_SEL_CRC_POLYNOMIAL =3D 0x0200, + OCTEON_COP2_SEL_CRC_IV =3D 0x0201, + OCTEON_COP2_SEL_CRC_LEN =3D 0x0202, + OCTEON_COP2_SEL_CRC_IV_REFLECT =3D 0x0203, + OCTEON_COP2_SEL_CRC_WRITE_BYTE =3D 0x0204, + OCTEON_COP2_SEL_CRC_WRITE_HALF =3D 0x0205, + OCTEON_COP2_SEL_CRC_WRITE_WORD =3D 0x0206, + OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL =3D 0x4200, + OCTEON_COP2_SEL_CRC_WRITE_LEN =3D 0x1202, + OCTEON_COP2_SEL_CRC_WRITE_IV_REFLECT =3D 0x0211, + OCTEON_COP2_SEL_CRC_WRITE_BYTE_REFLECT =3D 0x0214, + OCTEON_COP2_SEL_CRC_WRITE_HALF_REFLECT =3D 0x0215, + OCTEON_COP2_SEL_CRC_WRITE_WORD_REFLECT =3D 0x0216, + OCTEON_COP2_SEL_CRC_WRITE_DWORD =3D 0x1207, + OCTEON_COP2_SEL_CRC_WRITE_VAR =3D 0x1208, + OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL_REFLECT =3D 0x4210, + OCTEON_COP2_SEL_CRC_WRITE_DWORD_REFLECT =3D 0x1217, + OCTEON_COP2_SEL_CRC_WRITE_VAR_REFLECT =3D 0x1218, + /* + * Octeon shares 0x0240..0x0257 between SHA512 state/data and the SNOW= 3G + * RESULT/FSM/LFSR window. + */ + OCTEON_COP2_SEL_HSH_DATW0 =3D 0x0240, + OCTEON_COP2_SEL_HSH_DATW1, + OCTEON_COP2_SEL_HSH_DATW2, + OCTEON_COP2_SEL_HSH_DATW3, + OCTEON_COP2_SEL_HSH_DATW4, + OCTEON_COP2_SEL_HSH_DATW5, + OCTEON_COP2_SEL_HSH_DATW6, + OCTEON_COP2_SEL_HSH_DATW7, + OCTEON_COP2_SEL_HSH_DATW8, + OCTEON_COP2_SEL_HSH_DATW9, + OCTEON_COP2_SEL_HSH_DATW10, + OCTEON_COP2_SEL_HSH_DATW11, + OCTEON_COP2_SEL_HSH_DATW12, + OCTEON_COP2_SEL_HSH_DATW13, + OCTEON_COP2_SEL_HSH_DATW14, + OCTEON_COP2_SEL_HSH_DATW15, + OCTEON_COP2_SEL_HSH_IVW0 =3D 0x0250, + OCTEON_COP2_SEL_HSH_IVW1, + OCTEON_COP2_SEL_HSH_IVW2, + OCTEON_COP2_SEL_HSH_IVW3, + OCTEON_COP2_SEL_HSH_IVW4, + OCTEON_COP2_SEL_HSH_IVW5, + OCTEON_COP2_SEL_HSH_IVW6, + OCTEON_COP2_SEL_HSH_IVW7, + OCTEON_COP2_SEL_SNOW3G_LFSR0 =3D 0x0240, + OCTEON_COP2_SEL_SNOW3G_LFSR1, + OCTEON_COP2_SEL_SNOW3G_LFSR2, + OCTEON_COP2_SEL_SNOW3G_LFSR3, + OCTEON_COP2_SEL_SNOW3G_LFSR4, + OCTEON_COP2_SEL_SNOW3G_LFSR5, + OCTEON_COP2_SEL_SNOW3G_LFSR6, + OCTEON_COP2_SEL_SNOW3G_LFSR7, + OCTEON_COP2_SEL_SNOW3G_RESULT =3D 0x0250, + OCTEON_COP2_SEL_SNOW3G_FSM0, + OCTEON_COP2_SEL_SNOW3G_FSM1, + OCTEON_COP2_SEL_SNOW3G_FSM2, + OCTEON_COP2_SEL_GFM_MUL0 =3D 0x0258, + OCTEON_COP2_SEL_GFM_MUL1, + OCTEON_COP2_SEL_GFM_RESINP0, + OCTEON_COP2_SEL_GFM_RESINP1, + OCTEON_COP2_SEL_GFM_XOR0, + OCTEON_COP2_SEL_GFM_POLY =3D 0x025e, + OCTEON_COP2_SEL_AES_ENC_CBC1 =3D 0x3109, + OCTEON_COP2_SEL_AES_ENC1 =3D 0x310b, + OCTEON_COP2_SEL_AES_DEC_CBC1 =3D 0x310d, + OCTEON_COP2_SEL_AES_DEC1 =3D 0x310f, + OCTEON_COP2_SEL_HSH_STARTMD5 =3D 0x4047, + OCTEON_COP2_SEL_SNOW3G_START =3D 0x404d, + OCTEON_COP2_SEL_SNOW3G_MORE =3D 0x404e, + OCTEON_COP2_SEL_HSH_STARTSHA256 =3D 0x404f, + OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT =3D 0x405d, + OCTEON_COP2_SEL_HSH_STARTSHA1 =3D 0x4057, + OCTEON_COP2_SEL_HSH_STARTSHA512 =3D 0x424f, + OCTEON_COP2_SEL_GFM_XORMUL1 =3D 0x425d, +} MIPSOcteonCop2Sel; + +typedef struct MIPSOcteonCryptoState { + uint64_t des3_key[3]; + uint64_t des3_iv; + uint64_t des3_result; + uint64_t hash_state[4]; + uint64_t hash_block[8]; + uint64_t sha512_state[8]; + uint64_t sha512_block[16]; + uint64_t aes_iv[2]; + uint64_t aes_key[4]; + uint64_t aes_result[2]; + uint64_t aes_input[2]; + uint64_t gfm_mul[2]; + uint64_t gfm_result[2]; + uint64_t gfm_xor0; + uint64_t gfm_reflect_mul[2]; + uint64_t gfm_reflect_result[2]; + uint64_t gfm_reflect_xor0; + uint16_t gfm_poly; + uint8_t aes_keylen; + uint32_t shared_mode; + uint32_t crc_poly; + uint32_t crc_iv; + uint32_t crc_len; + uint32_t snow3g_fsm[3]; + uint32_t snow3g_lfsr[16]; + uint64_t snow3g_result; +} MIPSOcteonCryptoState; + typedef struct CPUArchState { TCState active_tc; CPUMIPSFPUContext active_fpu; @@ -550,6 +713,8 @@ typedef struct CPUArchState { #define MSAIR_ProcID 8 #define MSAIR_Rev 0 =20 + MIPSOcteonCryptoState octeon_crypto; + /* * CP0 Register 0 */ diff --git a/target/mips/helper.h b/target/mips/helper.h index 756ef92bfd..899120d0ca 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -27,6 +27,8 @@ DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32,= i32, i32) DEF_HELPER_3(octeon_vmulu, i64, env, i64, i64) DEF_HELPER_3(octeon_vmm0, i64, env, i64, i64) DEF_HELPER_3(octeon_v3mulu, i64, env, i64, i64) +DEF_HELPER_2(octeon_cop2_dmfc2, i64, env, i32) +DEF_HELPER_3(octeon_cop2_dmtc2, void, env, i64, i32) =20 /* microMIPS functions */ DEF_HELPER_4(lwm, void, env, tl, tl, i32) diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c index c29b7c56fa..d5452a3157 100644 --- a/target/mips/system/machine.c +++ b/target/mips/system/machine.c @@ -269,6 +269,42 @@ static const VMStateDescription mips_vmstate_octeon_mu= ltiplier =3D { } }; =20 +static const VMStateDescription mips_vmstate_octeon_crypto =3D { + .name =3D "cpu/octeon_crypto", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D mips_octeon_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT64_ARRAY(env.octeon_crypto.des3_key, MIPSCPU, 3), + VMSTATE_UINT64(env.octeon_crypto.des3_iv, MIPSCPU), + VMSTATE_UINT64(env.octeon_crypto.des3_result, MIPSCPU), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.hash_state, MIPSCPU, 4), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.hash_block, MIPSCPU, 8), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.sha512_state, MIPSCPU, 8), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.sha512_block, MIPSCPU, 16), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_iv, MIPSCPU, 2), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_key, MIPSCPU, 4), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_result, MIPSCPU, 2), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_input, MIPSCPU, 2), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_mul, MIPSCPU, 2), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_result, MIPSCPU, 2), + VMSTATE_UINT64(env.octeon_crypto.gfm_xor0, MIPSCPU), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_reflect_mul, MIPSCPU, 2= ), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.gfm_reflect_result, MIPSCPU= , 2), + VMSTATE_UINT64(env.octeon_crypto.gfm_reflect_xor0, MIPSCPU), + VMSTATE_UINT16(env.octeon_crypto.gfm_poly, MIPSCPU), + VMSTATE_UINT8(env.octeon_crypto.aes_keylen, MIPSCPU), + VMSTATE_UINT32(env.octeon_crypto.shared_mode, MIPSCPU), + VMSTATE_UINT32(env.octeon_crypto.crc_poly, MIPSCPU), + VMSTATE_UINT32(env.octeon_crypto.crc_iv, MIPSCPU), + VMSTATE_UINT32(env.octeon_crypto.crc_len, MIPSCPU), + VMSTATE_UINT32_ARRAY(env.octeon_crypto.snow3g_fsm, MIPSCPU, 3), + VMSTATE_UINT32_ARRAY(env.octeon_crypto.snow3g_lfsr, MIPSCPU, 16), + VMSTATE_UINT64(env.octeon_crypto.snow3g_result, MIPSCPU), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_mips_cpu =3D { .name =3D "cpu", .version_id =3D 21, @@ -386,6 +422,7 @@ const VMStateDescription vmstate_mips_cpu =3D { .subsections =3D (const VMStateDescription * const []) { &mips_vmstate_timer, &mips_vmstate_octeon_multiplier, + &mips_vmstate_octeon_crypto, NULL } }; diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build index fff9cd6c7f..4ee359874a 100644 --- a/target/mips/tcg/meson.build +++ b/target/mips/tcg/meson.build @@ -18,6 +18,7 @@ mips_ss.add(files( 'lmmi_helper.c', 'msa_helper.c', 'msa_translate.c', + 'octeon_crypto.c', 'op_helper.c', 'rel6_translate.c', 'translate.c', diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypt= o.c new file mode 100644 index 0000000000..43012ff027 --- /dev/null +++ b/target/mips/tcg/octeon_crypto.c @@ -0,0 +1,1654 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * MIPS Octeon crypto emulation helpers. + * + * Copyright (c) 2026 James Hilliard + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "internal.h" +#include "exec/helper-proto.h" +#include "crypto/aes.h" +#include "crypto/clmul.h" +#include "qemu/bitops.h" +#include "qemu/host-utils.h" + +static inline void octeon_set_shared_mode(MIPSOcteonCryptoState *crypto, + MIPSOcteonSharedMode mode) +{ + crypto->shared_mode =3D mode; +} + +static inline uint32_t octeon_crc_reflect32_by_byte(uint32_t v) +{ + return bswap32(revbit32(v)); +} + +static uint32_t octeon_crc_state_reflect(const MIPSOcteonCryptoState *cryp= to) +{ + return octeon_crc_reflect32_by_byte(crypto->crc_iv); +} + +static void octeon_crc_set_state_reflect(MIPSOcteonCryptoState *crypto, + uint32_t state) +{ + crypto->crc_iv =3D octeon_crc_reflect32_by_byte(state); +} + +static void octeon_crc_update_normal(MIPSOcteonCryptoState *crypto, + uint64_t value, unsigned int bytes) +{ + uint32_t crc =3D crypto->crc_iv; + uint32_t poly =3D crypto->crc_poly; + + for (unsigned int i =3D 0; i < bytes; i++) { + uint8_t byte =3D value >> ((bytes - 1 - i) * 8); + + crc ^=3D (uint32_t)byte << 24; + for (int bit =3D 0; bit < 8; bit++) { + if (crc & 0x80000000U) { + crc =3D (crc << 1) ^ poly; + } else { + crc <<=3D 1; + } + } + } + + crypto->crc_iv =3D crc; +} + +static void octeon_crc_update_reflect(MIPSOcteonCryptoState *crypto, + uint64_t value, unsigned int bytes) +{ + uint32_t crc =3D octeon_crc_state_reflect(crypto); + uint32_t poly =3D bswap32(crypto->crc_poly); + + for (unsigned int i =3D 0; i < bytes; i++) { + uint8_t byte =3D value >> ((bytes - 1 - i) * 8); + + crc ^=3D byte; + for (int bit =3D 0; bit < 8; bit++) { + if (crc & 1U) { + crc =3D (crc >> 1) ^ poly; + } else { + crc >>=3D 1; + } + } + } + + octeon_crc_set_state_reflect(crypto, crc); +} + +static uint64_t octeon_gfm_reduce64(Int128 product, uint8_t poly) +{ + uint64_t lo =3D int128_getlo(product); + uint64_t hi =3D int128_gethi(product); + + while (hi) { + int bit =3D 63 - clz64(hi); + uint64_t shifted_poly =3D (uint64_t)poly << bit; + + hi ^=3D 1ULL << bit; + lo ^=3D shifted_poly; + if (bit > 56) { + hi ^=3D (uint64_t)poly >> (64 - bit); + } + } + + return lo; +} + +static void octeon_gfm_mul64_uia2(const uint64_t x[2], const uint64_t y[2], + uint8_t poly, uint64_t out[2]) +{ + uint64_t vx =3D revbit64(x[1]); + uint64_t vy =3D revbit64(y[0]); + Int128 product =3D clmul_64(vx, vy); + uint64_t res =3D octeon_gfm_reduce64(product, revbit32(poly) >> 24); + + out[0] =3D 0; + out[1] =3D revbit64(res); +} + +static void octeon_gfm_mul_reflect(MIPSOcteonCryptoState *crypto, uint64_t= q) +{ + uint64_t in[2] =3D { + crypto->gfm_reflect_result[0] ^ crypto->gfm_reflect_xor0, + crypto->gfm_reflect_result[1] ^ q, + }; + + octeon_gfm_mul64_uia2(in, crypto->gfm_reflect_mul, + crypto->gfm_poly, crypto->gfm_reflect_result); + crypto->gfm_reflect_xor0 =3D 0; +} + +static inline void octeon_hash_load_reg_words_be(uint64_t reg, + uint32_t *hi, uint32_t *l= o) +{ + uint8_t buf[8]; + + stq_be_p(buf, reg); + *hi =3D ldl_be_p(buf); + *lo =3D ldl_be_p(buf + 4); +} + +static inline void octeon_hash_load_reg_words_le(uint64_t reg, + uint32_t *lo0, uint32_t *= lo1) +{ + uint8_t buf[8]; + + stq_be_p(buf, reg); + *lo0 =3D ldl_le_p(buf); + *lo1 =3D ldl_le_p(buf + 4); +} + +static inline uint64_t octeon_hash_store_reg_words_be(uint32_t hi, uint32_= t lo) +{ + uint8_t buf[8]; + + stl_be_p(buf, hi); + stl_be_p(buf + 4, lo); + return ldq_be_p(buf); +} + +static inline uint64_t octeon_hash_store_reg_words_le(uint32_t lo0, + uint32_t lo1) +{ + uint8_t buf[8]; + + stl_le_p(buf, lo0); + stl_le_p(buf + 4, lo1); + return ldq_be_p(buf); +} + +static void octeon_md5_transform(MIPSOcteonCryptoState *crypto) +{ + static const uint32_t k[64] =3D { + 0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU, + 0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U, + 0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU, + 0x6b901122U, 0xfd987193U, 0xa679438eU, 0x49b40821U, + 0xf61e2562U, 0xc040b340U, 0x265e5a51U, 0xe9b6c7aaU, + 0xd62f105dU, 0x02441453U, 0xd8a1e681U, 0xe7d3fbc8U, + 0x21e1cde6U, 0xc33707d6U, 0xf4d50d87U, 0x455a14edU, + 0xa9e3e905U, 0xfcefa3f8U, 0x676f02d9U, 0x8d2a4c8aU, + 0xfffa3942U, 0x8771f681U, 0x6d9d6122U, 0xfde5380cU, + 0xa4beea44U, 0x4bdecfa9U, 0xf6bb4b60U, 0xbebfbc70U, + 0x289b7ec6U, 0xeaa127faU, 0xd4ef3085U, 0x04881d05U, + 0xd9d4d039U, 0xe6db99e5U, 0x1fa27cf8U, 0xc4ac5665U, + 0xf4292244U, 0x432aff97U, 0xab9423a7U, 0xfc93a039U, + 0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU, 0x85845dd1U, + 0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U, + 0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U, + }; + static const uint8_t s[64] =3D { + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, + }; + uint8_t block_bytes[64]; + uint32_t m[16]; + uint32_t a, b, c, d; + uint32_t aa, bb, cc, dd; + int i; + + for (i =3D 0; i < 8; i++) { + stq_be_p(block_bytes + (i * 8), crypto->hash_block[i]); + m[i * 2] =3D ldl_le_p(block_bytes + (i * 8)); + m[i * 2 + 1] =3D ldl_le_p(block_bytes + (i * 8) + 4); + } + + octeon_hash_load_reg_words_le(crypto->hash_state[0], &a, &b); + octeon_hash_load_reg_words_le(crypto->hash_state[1], &c, &d); + aa =3D a; + bb =3D b; + cc =3D c; + dd =3D d; + + for (i =3D 0; i < 64; i++) { + uint32_t f, g, tmp; + + if (i < 16) { + f =3D (b & c) | ((~b) & d); + g =3D i; + } else if (i < 32) { + f =3D (d & b) | ((~d) & c); + g =3D (5 * i + 1) & 0xf; + } else if (i < 48) { + f =3D b ^ c ^ d; + g =3D (3 * i + 5) & 0xf; + } else { + f =3D c ^ (b | (~d)); + g =3D (7 * i) & 0xf; + } + + tmp =3D d; + d =3D c; + c =3D b; + b =3D b + rol32(a + f + k[i] + m[g], s[i]); + a =3D tmp; + } + + a +=3D aa; + b +=3D bb; + c +=3D cc; + d +=3D dd; + crypto->hash_state[0] =3D octeon_hash_store_reg_words_le(a, b); + crypto->hash_state[1] =3D octeon_hash_store_reg_words_le(c, d); +} + +static void octeon_sha1_transform(MIPSOcteonCryptoState *crypto) +{ + uint32_t w[80]; + uint32_t a, b, c, d, e; + int i; + + for (i =3D 0; i < 8; i++) { + octeon_hash_load_reg_words_be(crypto->hash_block[i], + &w[i * 2], &w[i * 2 + 1]); + } + for (i =3D 16; i < 80; i++) { + w[i] =3D rol32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1); + } + + octeon_hash_load_reg_words_be(crypto->hash_state[0], &a, &b); + octeon_hash_load_reg_words_be(crypto->hash_state[1], &c, &d); + e =3D crypto->hash_state[2] >> 32; + + for (i =3D 0; i < 80; i++) { + uint32_t f, k, temp; + + if (i < 20) { + f =3D (b & c) | ((~b) & d); + k =3D 0x5a827999; + } else if (i < 40) { + f =3D b ^ c ^ d; + k =3D 0x6ed9eba1; + } else if (i < 60) { + f =3D (b & c) | (b & d) | (c & d); + k =3D 0x8f1bbcdc; + } else { + f =3D b ^ c ^ d; + k =3D 0xca62c1d6; + } + + temp =3D rol32(a, 5) + f + e + k + w[i]; + e =3D d; + d =3D c; + c =3D rol32(b, 30); + b =3D a; + a =3D temp; + } + + octeon_hash_load_reg_words_be(crypto->hash_state[0], &w[0], &w[1]); + octeon_hash_load_reg_words_be(crypto->hash_state[1], &w[2], &w[3]); + w[4] =3D crypto->hash_state[2] >> 32; + w[0] +=3D a; + w[1] +=3D b; + w[2] +=3D c; + w[3] +=3D d; + w[4] +=3D e; + crypto->hash_state[0] =3D octeon_hash_store_reg_words_be(w[0], w[1]); + crypto->hash_state[1] =3D octeon_hash_store_reg_words_be(w[2], w[3]); + crypto->hash_state[2] =3D (uint64_t)w[4] << 32; +} + +static void octeon_sha256_transform(MIPSOcteonCryptoState *crypto) +{ + static const uint32_t k[64] =3D { + 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, + 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, + 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, + 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U, + 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, + 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, + 0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, + 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U, + 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U, + 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U, + 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, + 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U, + 0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U, + 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U, + 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, + 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U, + }; + uint32_t w[64]; + uint32_t a, b, c, d, e, f, g, h; + uint32_t orig[8]; + int i; + + for (i =3D 0; i < 8; i++) { + octeon_hash_load_reg_words_be(crypto->hash_block[i], + &w[i * 2], &w[i * 2 + 1]); + } + for (i =3D 16; i < 64; i++) { + uint32_t s0 =3D ror32(w[i - 15], 7) ^ + ror32(w[i - 15], 18) ^ + (w[i - 15] >> 3); + uint32_t s1 =3D ror32(w[i - 2], 17) ^ + ror32(w[i - 2], 19) ^ + (w[i - 2] >> 10); + w[i] =3D w[i - 16] + s0 + w[i - 7] + s1; + } + + for (i =3D 0; i < 4; i++) { + octeon_hash_load_reg_words_be(crypto->hash_state[i], + &orig[i * 2], &orig[i * 2 + 1]); + } + a =3D orig[0]; + b =3D orig[1]; + c =3D orig[2]; + d =3D orig[3]; + e =3D orig[4]; + f =3D orig[5]; + g =3D orig[6]; + h =3D orig[7]; + + for (i =3D 0; i < 64; i++) { + uint32_t s1 =3D ror32(e, 6) ^ + ror32(e, 11) ^ + ror32(e, 25); + uint32_t ch =3D (e & f) ^ ((~e) & g); + uint32_t temp1 =3D h + s1 + ch + k[i] + w[i]; + uint32_t s0 =3D ror32(a, 2) ^ + ror32(a, 13) ^ + ror32(a, 22); + uint32_t maj =3D (a & b) ^ (a & c) ^ (b & c); + uint32_t temp2 =3D s0 + maj; + + h =3D g; + g =3D f; + f =3D e; + e =3D d + temp1; + d =3D c; + c =3D b; + b =3D a; + a =3D temp1 + temp2; + } + + orig[0] +=3D a; + orig[1] +=3D b; + orig[2] +=3D c; + orig[3] +=3D d; + orig[4] +=3D e; + orig[5] +=3D f; + orig[6] +=3D g; + orig[7] +=3D h; + for (i =3D 0; i < 4; i++) { + crypto->hash_state[i] =3D + octeon_hash_store_reg_words_be(orig[i * 2], orig[i * 2 + 1]); + } +} + +static void octeon_sha512_transform(MIPSOcteonCryptoState *crypto) +{ + static const uint64_t k[80] =3D { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, + }; + uint64_t w[80]; + uint64_t a, b, c, d, e, f, g, h; + int i; + + for (i =3D 0; i < 16; i++) { + w[i] =3D crypto->sha512_block[i]; + } + for (i =3D 16; i < 80; i++) { + uint64_t s0 =3D ror64(w[i - 15], 1) ^ + ror64(w[i - 15], 8) ^ + (w[i - 15] >> 7); + uint64_t s1 =3D ror64(w[i - 2], 19) ^ + ror64(w[i - 2], 61) ^ + (w[i - 2] >> 6); + w[i] =3D w[i - 16] + s0 + w[i - 7] + s1; + } + + a =3D crypto->sha512_state[0]; + b =3D crypto->sha512_state[1]; + c =3D crypto->sha512_state[2]; + d =3D crypto->sha512_state[3]; + e =3D crypto->sha512_state[4]; + f =3D crypto->sha512_state[5]; + g =3D crypto->sha512_state[6]; + h =3D crypto->sha512_state[7]; + + for (i =3D 0; i < 80; i++) { + uint64_t s0 =3D ror64(a, 28) ^ + ror64(a, 34) ^ + ror64(a, 39); + uint64_t s1 =3D ror64(e, 14) ^ + ror64(e, 18) ^ + ror64(e, 41); + uint64_t ch =3D (e & f) ^ ((~e) & g); + uint64_t maj =3D (a & b) ^ (a & c) ^ (b & c); + uint64_t temp1 =3D h + s1 + ch + k[i] + w[i]; + uint64_t temp2 =3D s0 + maj; + + h =3D g; + g =3D f; + f =3D e; + e =3D d + temp1; + d =3D c; + c =3D b; + b =3D a; + a =3D temp1 + temp2; + } + + crypto->sha512_state[0] +=3D a; + crypto->sha512_state[1] +=3D b; + crypto->sha512_state[2] +=3D c; + crypto->sha512_state[3] +=3D d; + crypto->sha512_state[4] +=3D e; + crypto->sha512_state[5] +=3D f; + crypto->sha512_state[6] +=3D g; + crypto->sha512_state[7] +=3D h; +} + +static void octeon_store_shared_hash_dat(MIPSOcteonCryptoState *crypto, + uint32_t sel, uint64_t value) +{ + switch (sel) { + case OCTEON_COP2_SEL_HSH_DATW0 ... OCTEON_COP2_SEL_HSH_DATW14: + crypto->sha512_block[sel - OCTEON_COP2_SEL_HSH_DATW0] =3D value; + break; + case OCTEON_COP2_SEL_HSH_IVW0 ... OCTEON_COP2_SEL_HSH_IVW7: + crypto->sha512_state[sel - OCTEON_COP2_SEL_HSH_IVW0] =3D value; + break; + default: + g_assert_not_reached(); + } +} + +static const uint8_t octeon_snow3g_sr[256] =3D { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, +}; + +static const uint8_t octeon_snow3g_sq[256] =3D { + 0x25, 0x24, 0x73, 0x67, 0xd7, 0xae, 0x5c, 0x30, + 0xa4, 0xee, 0x6e, 0xcb, 0x7d, 0xb5, 0x82, 0xdb, + 0xe4, 0x8e, 0x48, 0x49, 0x4f, 0x5d, 0x6a, 0x78, + 0x70, 0x88, 0xe8, 0x5f, 0x5e, 0x84, 0x65, 0xe2, + 0xd8, 0xe9, 0xcc, 0xed, 0x40, 0x2f, 0x11, 0x28, + 0x57, 0xd2, 0xac, 0xe3, 0x4a, 0x15, 0x1b, 0xb9, + 0xb2, 0x80, 0x85, 0xa6, 0x2e, 0x02, 0x47, 0x29, + 0x07, 0x4b, 0x0e, 0xc1, 0x51, 0xaa, 0x89, 0xd4, + 0xca, 0x01, 0x46, 0xb3, 0xef, 0xdd, 0x44, 0x7b, + 0xc2, 0x7f, 0xbe, 0xc3, 0x9f, 0x20, 0x4c, 0x64, + 0x83, 0xa2, 0x68, 0x42, 0x13, 0xb4, 0x41, 0xcd, + 0xba, 0xc6, 0xbb, 0x6d, 0x4d, 0x71, 0x21, 0xf4, + 0x8d, 0xb0, 0xe5, 0x93, 0xfe, 0x8f, 0xe6, 0xcf, + 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xfa, + 0xbc, 0x0f, 0x08, 0x52, 0x1d, 0x55, 0x1a, 0xc5, + 0x4e, 0x23, 0x69, 0x7a, 0x92, 0xff, 0x5b, 0x5a, + 0xeb, 0x9a, 0x1c, 0xa9, 0xd1, 0x7e, 0x0d, 0xfc, + 0x50, 0x8a, 0xb6, 0x62, 0xf5, 0x0a, 0xf8, 0xdc, + 0x03, 0x3c, 0x0c, 0x39, 0xf1, 0xb8, 0xf3, 0x3d, + 0xf2, 0xd5, 0x97, 0x66, 0x81, 0x32, 0xa0, 0x00, + 0x06, 0xce, 0xf6, 0xea, 0xb7, 0x17, 0xf7, 0x8c, + 0x79, 0xd6, 0xa7, 0xbf, 0x8b, 0x3f, 0x1f, 0x53, + 0x63, 0x75, 0x35, 0x2c, 0x60, 0xfd, 0x27, 0xd3, + 0x94, 0xa5, 0x7c, 0xa1, 0x05, 0x58, 0x2d, 0xbd, + 0xd9, 0xc7, 0xaf, 0x6b, 0x54, 0x0b, 0xe0, 0x38, + 0x04, 0xc8, 0x9d, 0xe7, 0x14, 0xb1, 0x87, 0x9c, + 0xdf, 0x6f, 0xf9, 0xda, 0x2a, 0xc4, 0x59, 0x16, + 0x74, 0x91, 0xab, 0x26, 0x61, 0x76, 0x34, 0x2b, + 0xad, 0x99, 0xfb, 0x72, 0xec, 0x33, 0x12, 0xde, + 0x98, 0x3b, 0xc0, 0x9b, 0x3e, 0x18, 0x10, 0x3a, + 0x56, 0xe1, 0x77, 0xc9, 0x1e, 0x9e, 0x95, 0xa3, + 0x90, 0x19, 0xa8, 0x6c, 0x09, 0xd0, 0xf0, 0x86, +}; + +static inline uint8_t octeon_snow3g_mulx(uint8_t v, uint8_t c) +{ + return (v & 0x80) ? ((v << 1) ^ c) : (v << 1); +} + +static uint8_t octeon_snow3g_mulxpow(uint8_t v, unsigned int n, uint8_t c) +{ + while (n-- > 0) { + v =3D octeon_snow3g_mulx(v, c); + } + return v; +} + +static inline uint32_t octeon_snow3g_pack32(uint8_t b0, uint8_t b1, + uint8_t b2, uint8_t b3) +{ + return ((uint32_t)b0 << 24) | ((uint32_t)b1 << 16) | + ((uint32_t)b2 << 8) | b3; +} + +static uint32_t octeon_snow3g_mulalpha(uint8_t c) +{ + return octeon_snow3g_pack32(octeon_snow3g_mulxpow(c, 23, 0xa9), + octeon_snow3g_mulxpow(c, 245, 0xa9), + octeon_snow3g_mulxpow(c, 48, 0xa9), + octeon_snow3g_mulxpow(c, 239, 0xa9)); +} + +static uint32_t octeon_snow3g_divalpha(uint8_t c) +{ + return octeon_snow3g_pack32(octeon_snow3g_mulxpow(c, 16, 0xa9), + octeon_snow3g_mulxpow(c, 39, 0xa9), + octeon_snow3g_mulxpow(c, 6, 0xa9), + octeon_snow3g_mulxpow(c, 64, 0xa9)); +} + +static uint32_t octeon_snow3g_s1(uint32_t w) +{ + uint8_t x0 =3D octeon_snow3g_sr[w >> 24]; + uint8_t x1 =3D octeon_snow3g_sr[(uint8_t)(w >> 16)]; + uint8_t x2 =3D octeon_snow3g_sr[(uint8_t)(w >> 8)]; + uint8_t x3 =3D octeon_snow3g_sr[(uint8_t)w]; + uint8_t r0 =3D octeon_snow3g_mulx(x0, 0x1b) ^ x1 ^ x2 ^ + octeon_snow3g_mulx(x3, 0x1b) ^ x3; + uint8_t r1 =3D octeon_snow3g_mulx(x0, 0x1b) ^ x0 ^ + octeon_snow3g_mulx(x1, 0x1b) ^ x2 ^ x3; + uint8_t r2 =3D x0 ^ octeon_snow3g_mulx(x1, 0x1b) ^ x1 ^ + octeon_snow3g_mulx(x2, 0x1b) ^ x3; + uint8_t r3 =3D x0 ^ x1 ^ octeon_snow3g_mulx(x2, 0x1b) ^ x2 ^ + octeon_snow3g_mulx(x3, 0x1b); + + return octeon_snow3g_pack32(r0, r1, r2, r3); +} + +static uint32_t octeon_snow3g_s2(uint32_t w) +{ + uint8_t x0 =3D octeon_snow3g_sq[w >> 24]; + uint8_t x1 =3D octeon_snow3g_sq[(uint8_t)(w >> 16)]; + uint8_t x2 =3D octeon_snow3g_sq[(uint8_t)(w >> 8)]; + uint8_t x3 =3D octeon_snow3g_sq[(uint8_t)w]; + uint8_t r0 =3D octeon_snow3g_mulx(x0, 0x69) ^ x1 ^ x2 ^ + octeon_snow3g_mulx(x3, 0x69) ^ x3; + uint8_t r1 =3D octeon_snow3g_mulx(x0, 0x69) ^ x0 ^ + octeon_snow3g_mulx(x1, 0x69) ^ x2 ^ x3; + uint8_t r2 =3D x0 ^ octeon_snow3g_mulx(x1, 0x69) ^ x1 ^ + octeon_snow3g_mulx(x2, 0x69) ^ x3; + uint8_t r3 =3D x0 ^ x1 ^ octeon_snow3g_mulx(x2, 0x69) ^ x2 ^ + octeon_snow3g_mulx(x3, 0x69); + + return octeon_snow3g_pack32(r0, r1, r2, r3); +} + +static uint32_t octeon_snow3g_clock_fsm(MIPSOcteonCryptoState *crypto) +{ + uint32_t f =3D (uint32_t)(crypto->snow3g_lfsr[15] + crypto->snow3g_fsm= [0]) ^ + crypto->snow3g_fsm[1]; + uint32_t r =3D (uint32_t)(crypto->snow3g_fsm[1] + + (crypto->snow3g_fsm[2] ^ crypto->snow3g_lfsr[5= ])); + + crypto->snow3g_fsm[2] =3D octeon_snow3g_s2(crypto->snow3g_fsm[1]); + crypto->snow3g_fsm[1] =3D octeon_snow3g_s1(crypto->snow3g_fsm[0]); + crypto->snow3g_fsm[0] =3D r; + return f; +} + +static void octeon_snow3g_clock_lfsr(MIPSOcteonCryptoState *crypto, + bool init_mode, uint32_t f) +{ + uint32_t s0 =3D crypto->snow3g_lfsr[0]; + uint32_t s11 =3D crypto->snow3g_lfsr[11]; + uint32_t v =3D (s0 << 8) ^ octeon_snow3g_mulalpha(s0 >> 24) ^ + crypto->snow3g_lfsr[2] ^ (s11 >> 8) ^ + octeon_snow3g_divalpha((uint8_t)s11); + int i; + + if (init_mode) { + v ^=3D f; + } + + for (i =3D 0; i < 15; i++) { + crypto->snow3g_lfsr[i] =3D crypto->snow3g_lfsr[i + 1]; + } + crypto->snow3g_lfsr[15] =3D v; +} + +static uint32_t octeon_snow3g_generate_word(MIPSOcteonCryptoState *crypto) +{ + uint32_t f =3D octeon_snow3g_clock_fsm(crypto); + uint32_t z =3D f ^ crypto->snow3g_lfsr[0]; + + octeon_snow3g_clock_lfsr(crypto, false, 0); + return z; +} + +static void octeon_snow3g_queue_result(MIPSOcteonCryptoState *crypto) +{ + uint32_t z0 =3D octeon_snow3g_generate_word(crypto); + uint32_t z1 =3D octeon_snow3g_generate_word(crypto); + + crypto->snow3g_result =3D ((uint64_t)z0 << 32) | z1; +} + +static void octeon_snow3g_start(MIPSOcteonCryptoState *crypto, uint64_t q) +{ + int i; + + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SNOW3G); + for (i =3D 0; i < 7; i++) { + uint64_t pair =3D crypto->sha512_block[i]; + + crypto->snow3g_lfsr[i * 2] =3D pair >> 32; + crypto->snow3g_lfsr[i * 2 + 1] =3D pair; + } + crypto->snow3g_lfsr[14] =3D q >> 32; + crypto->snow3g_lfsr[15] =3D q; + memset(crypto->snow3g_fsm, 0, sizeof(crypto->snow3g_fsm)); + + for (i =3D 0; i < 32; i++) { + uint32_t f =3D octeon_snow3g_clock_fsm(crypto); + + octeon_snow3g_clock_lfsr(crypto, true, f); + } + + (void)octeon_snow3g_clock_fsm(crypto); + octeon_snow3g_clock_lfsr(crypto, false, 0); + octeon_snow3g_queue_result(crypto); +} + +static void octeon_snow3g_more(MIPSOcteonCryptoState *crypto) +{ + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SNOW3G); + octeon_snow3g_queue_result(crypto); +} + +static int octeon_aes_key_bits(const MIPSOcteonCryptoState *crypto) +{ + enum { + OCTEON_AES_KEYLEN_128 =3D 1, + OCTEON_AES_KEYLEN_192 =3D 2, + OCTEON_AES_KEYLEN_256 =3D 3, + }; + + switch (crypto->aes_keylen) { + case OCTEON_AES_KEYLEN_128: + return 128; + case OCTEON_AES_KEYLEN_192: + return 192; + case OCTEON_AES_KEYLEN_256: + return 256; + default: + return 0; + } +} + +static const uint8_t octeon_des_ip[64] =3D { + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7, +}; + +static const uint8_t octeon_des_fp[64] =3D { + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25, +}; + +static const uint8_t octeon_des_e[48] =3D { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1, +}; + +static const uint8_t octeon_des_p[32] =3D { + 16, 7, 20, 21, 29, 12, 28, 17, + 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, + 19, 13, 30, 6, 22, 11, 4, 25, +}; + +static const uint8_t octeon_des_pc1[56] =3D { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4, +}; + +static const uint8_t octeon_des_pc2[48] =3D { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32, +}; + +static const uint8_t octeon_des_rotations[16] =3D { + 1, 1, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 1, +}; + +static const uint8_t octeon_des_sboxes[8][64] =3D { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11, + }, +}; + +static const uint8_t octeon_kasumi_s7[128] =3D { + 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18, + 123, 33, 55, 113, 39, 114, 21, 67, 65, 12, 47, 73, 46, 27, + 25, 111, 124, 81, 53, 9, 121, 79, 52, 60, 58, 48, 101, 127, + 40, 120, 104, 70, 71, 43, 20, 122, 72, 61, 23, 109, 13, 100, + 77, 1, 16, 7, 82, 10, 105, 98, 117, 116, 76, 11, 89, 106, + 0, 125, 118, 99, 86, 69, 30, 57, 126, 87, 112, 51, 17, 5, + 95, 14, 90, 84, 91, 8, 35, 103, 32, 97, 28, 66, 102, 31, + 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29, 115, 44, + 64, 107, 108, 24, 110, 83, 36, 78, 42, 19, 15, 41, 88, 119, + 59, 3, +}; + +static const uint16_t octeon_kasumi_s9[512] =3D { + 167, 239, 161, 379, 391, 334, 9, 338, 38, 226, 48, 358, 452, 385, + 90, 397, 183, 253, 147, 331, 415, 340, 51, 362, 306, 500, 262, 82, + 216, 159, 356, 177, 175, 241, 489, 37, 206, 17, 0, 333, 44, 254, + 378, 58, 143, 220, 81, 400, 95, 3, 315, 245, 54, 235, 218, 405, + 472, 264, 172, 494, 371, 290, 399, 76, 165, 197, 395, 121, 257, 480, + 423, 212, 240, 28, 462, 176, 406, 507, 288, 223, 501, 407, 249, 265, + 89, 186, 221, 428, 164, 74, 440, 196, 458, 421, 350, 163, 232, 158, + 134, 354, 13, 250, 491, 142, 191, 69, 193, 425, 152, 227, 366, 135, + 344, 300, 276, 242, 437, 320, 113, 278, 11, 243, 87, 317, 36, 93, + 496, 27, 487, 446, 482, 41, 68, 156, 457, 131, 326, 403, 339, 20, + 39, 115, 442, 124, 475, 384, 508, 53, 112, 170, 479, 151, 126, 169, + 73, 268, 279, 321, 168, 364, 363, 292, 46, 499, 393, 327, 324, 24, + 456, 267, 157, 460, 488, 426, 309, 229, 439, 506, 208, 271, 349, 401, + 434, 236, 16, 209, 359, 52, 56, 120, 199, 277, 465, 416, 252, 287, + 246, 6, 83, 305, 420, 345, 153, 502, 65, 61, 244, 282, 173, 222, + 418, 67, 386, 368, 261, 101, 476, 291, 195, 430, 49, 79, 166, 330, + 280, 383, 373, 128, 382, 408, 155, 495, 367, 388, 274, 107, 459, 417, + 62, 454, 132, 225, 203, 316, 234, 14, 301, 91, 503, 286, 424, 211, + 347, 307, 140, 374, 35, 103, 125, 427, 19, 214, 453, 146, 498, 314, + 444, 230, 256, 329, 198, 285, 50, 116, 78, 410, 10, 205, 510, 171, + 231, 45, 139, 467, 29, 86, 505, 32, 72, 26, 342, 150, 313, 490, + 431, 238, 411, 325, 149, 473, 40, 119, 174, 355, 185, 233, 389, 71, + 448, 273, 372, 55, 110, 178, 322, 12, 469, 392, 369, 190, 1, 109, + 375, 137, 181, 88, 75, 308, 260, 484, 98, 272, 370, 275, 412, 111, + 336, 318, 4, 504, 492, 259, 304, 77, 337, 435, 21, 357, 303, 332, + 483, 18, 47, 85, 25, 497, 474, 289, 100, 269, 296, 478, 270, 106, + 31, 104, 433, 84, 414, 486, 394, 96, 99, 154, 511, 148, 413, 361, + 409, 255, 162, 215, 302, 201, 266, 351, 343, 144, 441, 365, 108, 298, + 251, 34, 182, 509, 138, 210, 335, 133, 311, 352, 328, 141, 396, 346, + 123, 319, 450, 281, 429, 228, 443, 481, 92, 404, 485, 422, 248, 297, + 23, 213, 130, 466, 22, 217, 283, 70, 294, 360, 419, 127, 312, 377, + 7, 468, 194, 2, 117, 295, 463, 258, 224, 447, 247, 187, 80, 398, + 284, 353, 105, 390, 299, 471, 470, 184, 57, 200, 348, 63, 204, 188, + 33, 451, 97, 30, 310, 219, 94, 160, 129, 493, 64, 179, 263, 102, + 189, 207, 114, 402, 438, 477, 387, 122, 192, 42, 381, 5, 145, 118, + 180, 449, 293, 323, 136, 380, 43, 66, 60, 455, 341, 445, 202, 432, + 8, 237, 15, 376, 436, 464, 59, 461, +}; + +static const uint16_t octeon_kasumi_constants[8] =3D { + 0x0123, 0x4567, 0x89ab, 0xcdef, 0xfedc, 0xba98, 0x7654, 0x3210, +}; + +typedef struct OcteonKasumiSubkeys { + uint16_t kli1[8]; + uint16_t kli2[8]; + uint16_t koi1[8]; + uint16_t koi2[8]; + uint16_t koi3[8]; + uint16_t kii1[8]; + uint16_t kii2[8]; + uint16_t kii3[8]; +} OcteonKasumiSubkeys; + +static uint64_t octeon_des_permute(uint64_t input, const uint8_t *table, + size_t output_bits, size_t input_bits) +{ + uint64_t out =3D 0; + + for (size_t i =3D 0; i < output_bits; i++) { + unsigned src =3D table[i] - 1; + + out =3D (out << 1) | ((input >> (input_bits - 1 - src)) & 1); + } + return out; +} + +static uint32_t octeon_des_rotate28(uint32_t v, unsigned shift) +{ + return ((v << shift) | (v >> (28 - shift))) & 0x0fffffffU; +} + +static void octeon_des_expand_subkeys(uint64_t key, uint64_t subkeys[16]) +{ + uint64_t permuted =3D octeon_des_permute(key, octeon_des_pc1, + ARRAY_SIZE(octeon_des_pc1), 64); + uint32_t c =3D (permuted >> 28) & 0x0fffffffU; + uint32_t d =3D permuted & 0x0fffffffU; + + for (int i =3D 0; i < 16; i++) { + c =3D octeon_des_rotate28(c, octeon_des_rotations[i]); + d =3D octeon_des_rotate28(d, octeon_des_rotations[i]); + subkeys[i] =3D octeon_des_permute(((uint64_t)c << 28) | d, + octeon_des_pc2, + ARRAY_SIZE(octeon_des_pc2), 56); + } +} + +static uint32_t octeon_des_f(uint32_t r, uint64_t subkey) +{ + uint64_t expanded =3D octeon_des_permute(r, octeon_des_e, + ARRAY_SIZE(octeon_des_e), 32); + uint32_t out =3D 0; + + expanded ^=3D subkey; + for (int i =3D 0; i < 8; i++) { + uint8_t sextet =3D (expanded >> (42 - i * 6)) & 0x3f; + uint8_t row =3D ((sextet & 0x20) >> 4) | (sextet & 0x01); + uint8_t col =3D (sextet >> 1) & 0x0f; + + out =3D (out << 4) | octeon_des_sboxes[i][row * 16 + col]; + } + + return octeon_des_permute(out, octeon_des_p, ARRAY_SIZE(octeon_des_p),= 32); +} + +static uint64_t octeon_des_block_crypt(uint64_t block, uint64_t key, + bool encrypt) +{ + uint64_t subkeys[16]; + uint64_t permuted =3D octeon_des_permute(block, octeon_des_ip, + ARRAY_SIZE(octeon_des_ip), 64); + uint32_t l =3D permuted >> 32; + uint32_t r =3D permuted; + + octeon_des_expand_subkeys(key, subkeys); + + for (int i =3D 0; i < 16; i++) { + uint32_t next =3D l ^ octeon_des_f(r, subkeys[encrypt ? i : 15 - i= ]); + + l =3D r; + r =3D next; + } + + return octeon_des_permute(((uint64_t)r << 32) | l, + octeon_des_fp, ARRAY_SIZE(octeon_des_fp), 64= ); +} + +static uint64_t octeon_3des_block_crypt(uint64_t block, const uint64_t key= s[3], + bool encrypt) +{ + if (encrypt) { + block =3D octeon_des_block_crypt(block, keys[0], true); + block =3D octeon_des_block_crypt(block, keys[1], false); + block =3D octeon_des_block_crypt(block, keys[2], true); + } else { + block =3D octeon_des_block_crypt(block, keys[2], false); + block =3D octeon_des_block_crypt(block, keys[1], true); + block =3D octeon_des_block_crypt(block, keys[0], false); + } + return block; +} + +static void octeon_3des_crypt_common(MIPSOcteonCryptoState *crypto, + uint64_t input_reg, + bool encrypt, bool cbc) +{ + const uint64_t keys[3] =3D { + crypto->des3_key[0], + crypto->des3_key[1], + crypto->des3_key[2], + }; + uint64_t block =3D input_reg; + + if (cbc) { + if (encrypt) { + block ^=3D crypto->des3_iv; + block =3D octeon_3des_block_crypt(block, keys, true); + crypto->des3_iv =3D block; + } else { + block =3D octeon_3des_block_crypt(block, keys, false); + block ^=3D crypto->des3_iv; + crypto->des3_iv =3D input_reg; + } + } else { + block =3D octeon_3des_block_crypt(block, keys, encrypt); + } + + crypto->des3_result =3D block; +} + +static inline uint16_t octeon_rol16(uint16_t value, unsigned int bits) +{ + return (value << bits) | (value >> (16 - bits)); +} + +static void octeon_kasumi_key_schedule(const uint64_t key_regs[2], + OcteonKasumiSubkeys *subkeys) +{ + uint16_t key[8]; + uint16_t key_prime[8]; + + key[0] =3D key_regs[0] >> 48; + key[1] =3D key_regs[0] >> 32; + key[2] =3D key_regs[0] >> 16; + key[3] =3D key_regs[0]; + key[4] =3D key_regs[1] >> 48; + key[5] =3D key_regs[1] >> 32; + key[6] =3D key_regs[1] >> 16; + key[7] =3D key_regs[1]; + + for (int i =3D 0; i < 8; i++) { + key_prime[i] =3D key[i] ^ octeon_kasumi_constants[i]; + } + + for (int i =3D 0; i < 8; i++) { + subkeys->kli1[i] =3D octeon_rol16(key[i], 1); + subkeys->kli2[i] =3D key_prime[(i + 2) & 7]; + subkeys->koi1[i] =3D octeon_rol16(key[(i + 1) & 7], 5); + subkeys->koi2[i] =3D octeon_rol16(key[(i + 5) & 7], 8); + subkeys->koi3[i] =3D octeon_rol16(key[(i + 6) & 7], 13); + subkeys->kii1[i] =3D key_prime[(i + 4) & 7]; + subkeys->kii2[i] =3D key_prime[(i + 3) & 7]; + subkeys->kii3[i] =3D key_prime[(i + 7) & 7]; + } +} + +static uint16_t octeon_kasumi_fi(uint16_t in, uint16_t subkey) +{ + uint16_t nine =3D in >> 7; + uint16_t seven =3D in & 0x7f; + + nine =3D octeon_kasumi_s9[nine] ^ seven; + seven =3D octeon_kasumi_s7[seven] ^ (nine & 0x7f); + seven ^=3D subkey >> 9; + nine ^=3D subkey & 0x1ff; + nine =3D octeon_kasumi_s9[nine] ^ seven; + seven =3D octeon_kasumi_s7[seven] ^ (nine & 0x7f); + return (seven << 9) | nine; +} + +static uint32_t octeon_kasumi_fo(uint32_t in, int index, + const OcteonKasumiSubkeys *subkeys) +{ + uint16_t left =3D in >> 16; + uint16_t right =3D in; + + left ^=3D subkeys->koi1[index]; + left =3D octeon_kasumi_fi(left, subkeys->kii1[index]); + left ^=3D right; + right ^=3D subkeys->koi2[index]; + right =3D octeon_kasumi_fi(right, subkeys->kii2[index]); + right ^=3D left; + left ^=3D subkeys->koi3[index]; + left =3D octeon_kasumi_fi(left, subkeys->kii3[index]); + left ^=3D right; + + return ((uint32_t)right << 16) | left; +} + +static uint32_t octeon_kasumi_fl(uint32_t in, int index, + const OcteonKasumiSubkeys *subkeys) +{ + uint16_t left =3D in >> 16; + uint16_t right =3D in; + uint16_t a =3D left & subkeys->kli1[index]; + uint16_t b; + + right ^=3D octeon_rol16(a, 1); + b =3D right | subkeys->kli2[index]; + left ^=3D octeon_rol16(b, 1); + return ((uint32_t)left << 16) | right; +} + +static uint64_t octeon_kasumi_block_encrypt(uint64_t block, + const uint64_t key_regs[2]) +{ + OcteonKasumiSubkeys subkeys; + uint32_t left =3D block >> 32; + uint32_t right =3D block; + + octeon_kasumi_key_schedule(key_regs, &subkeys); + + for (int i =3D 0; i < 8; ) { + uint32_t temp =3D octeon_kasumi_fl(left, i, &subkeys); + + temp =3D octeon_kasumi_fo(temp, i++, &subkeys); + right ^=3D temp; + temp =3D octeon_kasumi_fo(right, i, &subkeys); + temp =3D octeon_kasumi_fl(temp, i++, &subkeys); + left ^=3D temp; + } + + return ((uint64_t)left << 32) | right; +} + +static void octeon_kasumi_crypt_common(MIPSOcteonCryptoState *crypto, + uint64_t input_reg, bool cbc) +{ + const uint64_t key_regs[2] =3D { + crypto->des3_key[0], + crypto->des3_key[1], + }; + uint64_t block =3D input_reg; + + if (cbc) { + block ^=3D crypto->des3_iv; + } + + block =3D octeon_kasumi_block_encrypt(block, key_regs); + if (cbc) { + crypto->des3_iv =3D block; + } + crypto->des3_result =3D block; +} + +static void octeon_aes_load_key(const MIPSOcteonCryptoState *crypto, + uint8_t *key, size_t keylen) +{ + stq_be_p(key, crypto->aes_key[0]); + stq_be_p(key + 8, crypto->aes_key[1]); + if (keylen > 16) { + stq_be_p(key + 16, crypto->aes_key[2]); + } + if (keylen > 24) { + stq_be_p(key + 24, crypto->aes_key[3]); + } +} + +static void octeon_aes_load_block(const uint64_t regs[2], uint8_t *block) +{ + stq_be_p(block, regs[0]); + stq_be_p(block + 8, regs[1]); +} + +static void octeon_aes_store_block(uint64_t regs[2], const uint8_t *block) +{ + regs[0] =3D ldq_be_p(block); + regs[1] =3D ldq_be_p(block + 8); +} + +static void octeon_aes_encrypt_common(MIPSOcteonCryptoState *crypto, bool = cbc) +{ + AES_KEY key; + uint8_t in[16]; + uint8_t out[16]; + uint8_t iv[16]; + uint8_t raw_key[32] =3D {}; + int bits =3D octeon_aes_key_bits(crypto); + + if (!bits) { + return; + } + + octeon_aes_load_key(crypto, raw_key, bits / 8); + octeon_aes_load_block(crypto->aes_input, in); + if (cbc) { + int i; + + octeon_aes_load_block(crypto->aes_iv, iv); + for (i =3D 0; i < sizeof(in); i++) { + in[i] ^=3D iv[i]; + } + } + + AES_set_encrypt_key(raw_key, bits, &key); + AES_encrypt(in, out, &key); + octeon_aes_store_block(crypto->aes_result, out); + if (cbc) { + octeon_aes_store_block(crypto->aes_iv, out); + } +} + +static void octeon_aes_decrypt_common(MIPSOcteonCryptoState *crypto, bool = cbc) +{ + AES_KEY key; + uint8_t in[16]; + uint8_t out[16]; + uint8_t iv[16]; + uint8_t next_iv[16]; + uint8_t raw_key[32] =3D {}; + int bits =3D octeon_aes_key_bits(crypto); + int i; + + if (!bits) { + return; + } + + octeon_aes_load_key(crypto, raw_key, bits / 8); + octeon_aes_load_block(crypto->aes_input, in); + if (cbc) { + memcpy(next_iv, in, sizeof(next_iv)); + octeon_aes_load_block(crypto->aes_iv, iv); + } + + AES_set_decrypt_key(raw_key, bits, &key); + AES_decrypt(in, out, &key); + if (cbc) { + for (i =3D 0; i < sizeof(out); i++) { + out[i] ^=3D iv[i]; + } + } + + octeon_aes_store_block(crypto->aes_result, out); + if (cbc) { + octeon_aes_store_block(crypto->aes_iv, next_iv); + } +} + +static void octeon_gfm_mul(const uint64_t x[2], const uint64_t y[2], + uint16_t poly, uint64_t out[2]) +{ + uint64_t zh =3D 0, zl =3D 0; + uint64_t vh =3D y[0], vl =3D y[1]; + uint64_t rh =3D (uint64_t)poly << 48; + int i; + + for (i =3D 0; i < 128; i++) { + bool bit; + bool lsb; + + if (i < 64) { + bit =3D (x[0] >> (63 - i)) & 1; + } else { + bit =3D (x[1] >> (127 - i)) & 1; + } + if (bit) { + zh ^=3D vh; + zl ^=3D vl; + } + + lsb =3D vl & 1; + vl =3D (vh << 63) | (vl >> 1); + vh >>=3D 1; + if (lsb) { + vh ^=3D rh; + } + } + + out[0] =3D zh; + out[1] =3D zl; +} + +uint64_t helper_octeon_cop2_dmfc2(CPUMIPSState *env, uint32_t sel) +{ + MIPSOcteonCryptoState *crypto =3D &env->octeon_crypto; + + if (crypto->shared_mode =3D=3D OCTEON_SHARED_MODE_SNOW3G) { + if (sel >=3D OCTEON_COP2_SEL_SNOW3G_LFSR0 && + sel <=3D OCTEON_COP2_SEL_SNOW3G_LFSR7) { + unsigned int idx =3D sel - OCTEON_COP2_SEL_SNOW3G_LFSR0; + + return ((uint64_t)crypto->snow3g_lfsr[idx * 2] << 32) | + crypto->snow3g_lfsr[idx * 2 + 1]; + } + switch (sel) { + case OCTEON_COP2_SEL_SNOW3G_RESULT: + return crypto->snow3g_result; + case OCTEON_COP2_SEL_SNOW3G_FSM0: + case OCTEON_COP2_SEL_SNOW3G_FSM1: + case OCTEON_COP2_SEL_SNOW3G_FSM2: + return crypto->snow3g_fsm[sel - OCTEON_COP2_SEL_SNOW3G_FSM0]; + default: + break; + } + } + + switch (sel) { + case OCTEON_COP2_SEL_3DES_KEY0: + case OCTEON_COP2_SEL_3DES_KEY1: + case OCTEON_COP2_SEL_3DES_KEY2: + return crypto->des3_key[sel - OCTEON_COP2_SEL_3DES_KEY0]; + case OCTEON_COP2_SEL_3DES_IV: + return crypto->des3_iv; + case OCTEON_COP2_SEL_3DES_RESULT: + case OCTEON_COP2_SEL_3DES_RESULT_IN: + return crypto->des3_result; + case OCTEON_COP2_SEL_AES_RESULT0: + case OCTEON_COP2_SEL_AES_RESULT1: + return crypto->aes_result[sel - OCTEON_COP2_SEL_AES_RESULT0]; + case OCTEON_COP2_SEL_AES_KEY0: + case OCTEON_COP2_SEL_AES_KEY1: + case OCTEON_COP2_SEL_AES_KEY2: + case OCTEON_COP2_SEL_AES_KEY3: + return crypto->aes_key[sel - OCTEON_COP2_SEL_AES_KEY0]; + case OCTEON_COP2_SEL_AES_KEYLENGTH: + return crypto->aes_keylen; + case OCTEON_COP2_SEL_AES_DAT0: + return crypto->aes_input[0]; + case OCTEON_COP2_SEL_AES_IV0: + case OCTEON_COP2_SEL_AES_IV1: + return crypto->aes_iv[sel - OCTEON_COP2_SEL_AES_IV0]; + case OCTEON_COP2_SEL_CRC_POLYNOMIAL: + return crypto->crc_poly; + case OCTEON_COP2_SEL_CRC_IV: + return crypto->crc_iv; + case OCTEON_COP2_SEL_CRC_LEN: + return crypto->crc_len; + case OCTEON_COP2_SEL_CRC_IV_REFLECT: + return octeon_crc_reflect32_by_byte(crypto->crc_iv); + case OCTEON_COP2_SEL_HSH_DATW0: + case OCTEON_COP2_SEL_HSH_DATW1: + case OCTEON_COP2_SEL_HSH_DATW2: + case OCTEON_COP2_SEL_HSH_DATW3: + case OCTEON_COP2_SEL_HSH_DATW4: + case OCTEON_COP2_SEL_HSH_DATW5: + case OCTEON_COP2_SEL_HSH_DATW6: + case OCTEON_COP2_SEL_HSH_DATW7: + case OCTEON_COP2_SEL_HSH_DATW8: + case OCTEON_COP2_SEL_HSH_DATW9: + case OCTEON_COP2_SEL_HSH_DATW10: + case OCTEON_COP2_SEL_HSH_DATW11: + case OCTEON_COP2_SEL_HSH_DATW12: + case OCTEON_COP2_SEL_HSH_DATW13: + case OCTEON_COP2_SEL_HSH_DATW14: + return crypto->sha512_block[sel - OCTEON_COP2_SEL_HSH_DATW0]; + case OCTEON_COP2_SEL_HSH_DATW15: + return crypto->sha512_block[15]; + case OCTEON_COP2_SEL_HSH_IVW0: + case OCTEON_COP2_SEL_HSH_IVW1: + case OCTEON_COP2_SEL_HSH_IVW2: + case OCTEON_COP2_SEL_HSH_IVW3: + case OCTEON_COP2_SEL_HSH_IVW4: + case OCTEON_COP2_SEL_HSH_IVW5: + case OCTEON_COP2_SEL_HSH_IVW6: + case OCTEON_COP2_SEL_HSH_IVW7: + return crypto->sha512_state[sel - OCTEON_COP2_SEL_HSH_IVW0]; + case OCTEON_COP2_SEL_HSH_IV0: + case OCTEON_COP2_SEL_HSH_IV1: + case OCTEON_COP2_SEL_HSH_IV2: + case OCTEON_COP2_SEL_HSH_IV3: + return crypto->hash_state[sel - OCTEON_COP2_SEL_HSH_IV0]; + case OCTEON_COP2_SEL_GFM_MUL_REFLECT0: + case OCTEON_COP2_SEL_GFM_MUL_REFLECT1: + return crypto->gfm_reflect_mul[sel - OCTEON_COP2_SEL_GFM_MUL_REFLE= CT0]; + case OCTEON_COP2_SEL_GFM_RESINP_REFLECT0: + case OCTEON_COP2_SEL_GFM_RESINP_REFLECT1: + return crypto->gfm_reflect_result[ + sel - OCTEON_COP2_SEL_GFM_RESINP_REFLECT0]; + case OCTEON_COP2_SEL_GFM_MUL0: + case OCTEON_COP2_SEL_GFM_MUL1: + return crypto->gfm_mul[sel - OCTEON_COP2_SEL_GFM_MUL0]; + case OCTEON_COP2_SEL_GFM_RESINP0: + case OCTEON_COP2_SEL_GFM_RESINP1: + return crypto->gfm_result[sel - OCTEON_COP2_SEL_GFM_RESINP0]; + case OCTEON_COP2_SEL_GFM_POLY: + return crypto->gfm_poly; + default: + return 0; + } +} + +void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uint64_t value, + uint32_t sel) +{ + MIPSOcteonCryptoState *crypto =3D &env->octeon_crypto; + uint64_t q =3D (uint64_t)value; + + switch (sel) { + case OCTEON_COP2_SEL_3DES_KEY0: + case OCTEON_COP2_SEL_3DES_KEY1: + case OCTEON_COP2_SEL_3DES_KEY2: + crypto->des3_key[sel - OCTEON_COP2_SEL_3DES_KEY0] =3D q; + break; + case OCTEON_COP2_SEL_3DES_IV: + crypto->des3_iv =3D q; + break; + case OCTEON_COP2_SEL_3DES_RESULT_IN: + crypto->des3_result =3D q; + break; + case OCTEON_COP2_SEL_3DES_ENC_CBC: + octeon_3des_crypt_common(crypto, q, true, true); + break; + case OCTEON_COP2_SEL_KAS_ENC_CBC: + octeon_kasumi_crypt_common(crypto, q, true); + break; + case OCTEON_COP2_SEL_3DES_ENC: + octeon_3des_crypt_common(crypto, q, true, false); + break; + case OCTEON_COP2_SEL_KAS_ENC: + octeon_kasumi_crypt_common(crypto, q, false); + break; + case OCTEON_COP2_SEL_3DES_DEC_CBC: + octeon_3des_crypt_common(crypto, q, false, true); + break; + case OCTEON_COP2_SEL_3DES_DEC: + octeon_3des_crypt_common(crypto, q, false, false); + break; + case OCTEON_COP2_SEL_AES_RESULT0: + case OCTEON_COP2_SEL_AES_RESULT1: + crypto->aes_input[sel - OCTEON_COP2_SEL_AES_RESULT0] =3D q; + crypto->aes_result[sel - OCTEON_COP2_SEL_AES_RESULT0] =3D q; + break; + case OCTEON_COP2_SEL_AES_IV0: + case OCTEON_COP2_SEL_AES_IV1: + crypto->aes_iv[sel - OCTEON_COP2_SEL_AES_IV0] =3D q; + break; + case OCTEON_COP2_SEL_AES_KEY0: + case OCTEON_COP2_SEL_AES_KEY1: + case OCTEON_COP2_SEL_AES_KEY2: + case OCTEON_COP2_SEL_AES_KEY3: + crypto->aes_key[sel - OCTEON_COP2_SEL_AES_KEY0] =3D q; + break; + case OCTEON_COP2_SEL_AES_ENC_CBC0: + case OCTEON_COP2_SEL_AES_ENC0: + case OCTEON_COP2_SEL_AES_DEC_CBC0: + case OCTEON_COP2_SEL_AES_DEC0: + crypto->aes_input[0] =3D q; + break; + case OCTEON_COP2_SEL_AES_KEYLENGTH: + crypto->aes_keylen =3D q; + break; + case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL: + case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL_REFLECT: + crypto->crc_poly =3D q; + break; + case OCTEON_COP2_SEL_CRC_IV: + crypto->crc_iv =3D q; + break; + case OCTEON_COP2_SEL_CRC_WRITE_LEN: + crypto->crc_len =3D q; + break; + case OCTEON_COP2_SEL_CRC_WRITE_IV_REFLECT: + crypto->crc_iv =3D octeon_crc_reflect32_by_byte((uint32_t)q); + break; + case OCTEON_COP2_SEL_CRC_WRITE_BYTE: + octeon_crc_update_normal(crypto, q, 1); + break; + case OCTEON_COP2_SEL_CRC_WRITE_HALF: + octeon_crc_update_normal(crypto, q, 2); + break; + case OCTEON_COP2_SEL_CRC_WRITE_WORD: + octeon_crc_update_normal(crypto, q, 4); + break; + case OCTEON_COP2_SEL_CRC_WRITE_DWORD: + octeon_crc_update_normal(crypto, q, 8); + break; + case OCTEON_COP2_SEL_CRC_WRITE_VAR: + octeon_crc_update_normal(crypto, q, MIN(8U, crypto->crc_len)); + break; + case OCTEON_COP2_SEL_CRC_WRITE_BYTE_REFLECT: + octeon_crc_update_reflect(crypto, q, 1); + break; + case OCTEON_COP2_SEL_CRC_WRITE_HALF_REFLECT: + octeon_crc_update_reflect(crypto, q, 2); + break; + case OCTEON_COP2_SEL_CRC_WRITE_WORD_REFLECT: + octeon_crc_update_reflect(crypto, q, 4); + break; + case OCTEON_COP2_SEL_CRC_WRITE_DWORD_REFLECT: + octeon_crc_update_reflect(crypto, q, 8); + break; + case OCTEON_COP2_SEL_CRC_WRITE_VAR_REFLECT: + octeon_crc_update_reflect(crypto, q, MIN(8U, crypto->crc_len)); + break; + case OCTEON_COP2_SEL_HSH_DATW0: + case OCTEON_COP2_SEL_HSH_DATW1: + case OCTEON_COP2_SEL_HSH_DATW2: + case OCTEON_COP2_SEL_HSH_DATW3: + case OCTEON_COP2_SEL_HSH_DATW4: + case OCTEON_COP2_SEL_HSH_DATW5: + case OCTEON_COP2_SEL_HSH_DATW6: + case OCTEON_COP2_SEL_HSH_DATW7: + case OCTEON_COP2_SEL_HSH_DATW8: + case OCTEON_COP2_SEL_HSH_DATW9: + case OCTEON_COP2_SEL_HSH_DATW10: + case OCTEON_COP2_SEL_HSH_DATW11: + case OCTEON_COP2_SEL_HSH_DATW12: + case OCTEON_COP2_SEL_HSH_DATW13: + case OCTEON_COP2_SEL_HSH_DATW14: + octeon_store_shared_hash_dat(crypto, sel, q); + break; + case OCTEON_COP2_SEL_HSH_DATW15: + case OCTEON_COP2_SEL_HSH_STARTSHA512: + crypto->sha512_block[15] =3D q; + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA512); + octeon_sha512_transform(crypto); + break; + case OCTEON_COP2_SEL_HSH_IVW0: + case OCTEON_COP2_SEL_HSH_IVW1: + case OCTEON_COP2_SEL_HSH_IVW2: + case OCTEON_COP2_SEL_HSH_IVW3: + case OCTEON_COP2_SEL_HSH_IVW4: + case OCTEON_COP2_SEL_HSH_IVW5: + case OCTEON_COP2_SEL_HSH_IVW6: + case OCTEON_COP2_SEL_HSH_IVW7: + octeon_store_shared_hash_dat(crypto, sel, q); + break; + case OCTEON_COP2_SEL_GFM_MUL_REFLECT0: + case OCTEON_COP2_SEL_GFM_MUL_REFLECT1: + crypto->gfm_reflect_mul[ + sel - OCTEON_COP2_SEL_GFM_MUL_REFLECT0] =3D q; + break; + case OCTEON_COP2_SEL_GFM_XOR0_REFLECT: + crypto->gfm_reflect_xor0 =3D q; + break; + case OCTEON_COP2_SEL_GFM_MUL0: + case OCTEON_COP2_SEL_GFM_MUL1: + crypto->gfm_mul[sel - OCTEON_COP2_SEL_GFM_MUL0] =3D q; + break; + case OCTEON_COP2_SEL_GFM_RESINP0: + case OCTEON_COP2_SEL_GFM_RESINP1: + crypto->gfm_result[sel - OCTEON_COP2_SEL_GFM_RESINP0] =3D q; + break; + case OCTEON_COP2_SEL_GFM_XOR0: + crypto->gfm_xor0 =3D q; + break; + case OCTEON_COP2_SEL_GFM_POLY: + crypto->gfm_poly =3D q; + break; + case OCTEON_COP2_SEL_HSH_DAT0: + case OCTEON_COP2_SEL_HSH_DAT1: + case OCTEON_COP2_SEL_HSH_DAT2: + case OCTEON_COP2_SEL_HSH_DAT3: + case OCTEON_COP2_SEL_HSH_DAT4: + case OCTEON_COP2_SEL_HSH_DAT5: + case OCTEON_COP2_SEL_HSH_DAT6: + crypto->hash_block[sel - OCTEON_COP2_SEL_HSH_DAT0] =3D q; + break; + case OCTEON_COP2_SEL_HSH_IV0: + case OCTEON_COP2_SEL_HSH_IV1: + case OCTEON_COP2_SEL_HSH_IV2: + case OCTEON_COP2_SEL_HSH_IV3: + crypto->hash_state[sel - OCTEON_COP2_SEL_HSH_IV0] =3D q; + break; + case OCTEON_COP2_SEL_HSH_STARTMD5: + crypto->hash_block[7] =3D q; + octeon_md5_transform(crypto); + break; + case OCTEON_COP2_SEL_HSH_STARTSHA256: + crypto->hash_block[7] =3D q; + octeon_sha256_transform(crypto); + break; + case OCTEON_COP2_SEL_HSH_STARTSHA1_COMPAT: + case OCTEON_COP2_SEL_HSH_STARTSHA1: + crypto->hash_block[7] =3D q; + octeon_sha1_transform(crypto); + break; + case OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT: + octeon_gfm_mul_reflect(crypto, q); + break; + case OCTEON_COP2_SEL_AES_ENC_CBC1: + crypto->aes_input[1] =3D q; + octeon_aes_encrypt_common(crypto, true); + break; + case OCTEON_COP2_SEL_AES_ENC1: + crypto->aes_input[1] =3D q; + octeon_aes_encrypt_common(crypto, false); + break; + case OCTEON_COP2_SEL_AES_DEC_CBC1: + crypto->aes_input[1] =3D q; + octeon_aes_decrypt_common(crypto, true); + break; + case OCTEON_COP2_SEL_AES_DEC1: + crypto->aes_input[1] =3D q; + octeon_aes_decrypt_common(crypto, false); + break; + case OCTEON_COP2_SEL_GFM_XORMUL1: { + uint64_t in[2] =3D { + crypto->gfm_result[0] ^ crypto->gfm_xor0, + crypto->gfm_result[1] ^ q, + }; + + /* + * A 64-bit reflected GFM operation uses this XORMUL1 path when the + * block is programmed with only MUL0, an 8-bit polynomial, and a = zero + * high input half. Detect that shape and use the reflected helper + * instead of the normal GHASH-style multiplier. + */ + if (crypto->gfm_poly <=3D 0xff && + crypto->gfm_mul[1] =3D=3D 0 && + in[0] =3D=3D 0) { + octeon_gfm_mul64_uia2(in, crypto->gfm_mul, + crypto->gfm_poly, crypto->gfm_result); + } else { + octeon_gfm_mul(in, crypto->gfm_mul, crypto->gfm_poly, + crypto->gfm_result); + } + /* + * GFM_XOR0 is a write-only staging half consumed by the next XORM= UL1 + * operation, so clear it once the combined multiply has been issu= ed. + */ + crypto->gfm_xor0 =3D 0; + break; + } + case OCTEON_COP2_SEL_SNOW3G_START: + octeon_snow3g_start(crypto, q); + break; + case OCTEON_COP2_SEL_SNOW3G_MORE: + octeon_snow3g_more(crypto); + break; + default: + break; + } +} diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index 6309cd5fff..ac5065398d 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -21,6 +21,216 @@ static bool octeon_check_64(DisasContext *ctx) return ctx->base.is_jmp =3D=3D DISAS_NEXT; } =20 +static bool octeon_cop2_is_supported_dmfc2(uint16_t sel) +{ + switch (sel) { + case OCTEON_COP2_SEL_3DES_KEY0: + case OCTEON_COP2_SEL_3DES_KEY1: + case OCTEON_COP2_SEL_3DES_KEY2: + case OCTEON_COP2_SEL_3DES_IV: + case OCTEON_COP2_SEL_3DES_RESULT: + case OCTEON_COP2_SEL_3DES_RESULT_IN: + case OCTEON_COP2_SEL_AES_RESULT0: + case OCTEON_COP2_SEL_AES_RESULT1: + case OCTEON_COP2_SEL_AES_KEY0: + case OCTEON_COP2_SEL_AES_KEY1: + case OCTEON_COP2_SEL_AES_KEY2: + case OCTEON_COP2_SEL_AES_KEY3: + case OCTEON_COP2_SEL_AES_KEYLENGTH: + case OCTEON_COP2_SEL_CRC_POLYNOMIAL: + case OCTEON_COP2_SEL_AES_IV0: + case OCTEON_COP2_SEL_AES_IV1: + case OCTEON_COP2_SEL_CRC_IV: + case OCTEON_COP2_SEL_CRC_LEN: + case OCTEON_COP2_SEL_CRC_IV_REFLECT: + case OCTEON_COP2_SEL_HSH_DATW0: + case OCTEON_COP2_SEL_HSH_DATW1: + case OCTEON_COP2_SEL_HSH_DATW2: + case OCTEON_COP2_SEL_HSH_DATW3: + case OCTEON_COP2_SEL_HSH_DATW4: + case OCTEON_COP2_SEL_HSH_DATW5: + case OCTEON_COP2_SEL_HSH_DATW6: + case OCTEON_COP2_SEL_HSH_DATW7: + case OCTEON_COP2_SEL_HSH_DATW8: + case OCTEON_COP2_SEL_HSH_DATW9: + case OCTEON_COP2_SEL_HSH_DATW10: + case OCTEON_COP2_SEL_HSH_DATW11: + case OCTEON_COP2_SEL_HSH_DATW12: + case OCTEON_COP2_SEL_HSH_DATW13: + case OCTEON_COP2_SEL_HSH_DATW14: + case OCTEON_COP2_SEL_HSH_DATW15: + case OCTEON_COP2_SEL_HSH_IV0: + case OCTEON_COP2_SEL_HSH_IV1: + case OCTEON_COP2_SEL_HSH_IV2: + case OCTEON_COP2_SEL_HSH_IV3: + case OCTEON_COP2_SEL_HSH_IVW0: + case OCTEON_COP2_SEL_HSH_IVW1: + case OCTEON_COP2_SEL_HSH_IVW2: + case OCTEON_COP2_SEL_HSH_IVW3: + case OCTEON_COP2_SEL_HSH_IVW4: + case OCTEON_COP2_SEL_HSH_IVW5: + case OCTEON_COP2_SEL_HSH_IVW6: + case OCTEON_COP2_SEL_HSH_IVW7: + case OCTEON_COP2_SEL_AES_DAT0: + case OCTEON_COP2_SEL_GFM_MUL_REFLECT0: + case OCTEON_COP2_SEL_GFM_MUL_REFLECT1: + case OCTEON_COP2_SEL_GFM_RESINP_REFLECT0: + case OCTEON_COP2_SEL_GFM_RESINP_REFLECT1: + case OCTEON_COP2_SEL_GFM_MUL0: + case OCTEON_COP2_SEL_GFM_MUL1: + case OCTEON_COP2_SEL_GFM_RESINP0: + case OCTEON_COP2_SEL_GFM_RESINP1: + case OCTEON_COP2_SEL_GFM_POLY: + return true; + default: + return false; + } +} + +static bool octeon_cop2_is_supported_dmtc2(uint16_t sel) +{ + switch (sel) { + case OCTEON_COP2_SEL_3DES_KEY0: + case OCTEON_COP2_SEL_3DES_KEY1: + case OCTEON_COP2_SEL_3DES_KEY2: + case OCTEON_COP2_SEL_3DES_IV: + case OCTEON_COP2_SEL_3DES_RESULT_IN: + case OCTEON_COP2_SEL_3DES_ENC_CBC: + case OCTEON_COP2_SEL_KAS_ENC_CBC: + case OCTEON_COP2_SEL_3DES_ENC: + case OCTEON_COP2_SEL_KAS_ENC: + case OCTEON_COP2_SEL_3DES_DEC_CBC: + case OCTEON_COP2_SEL_3DES_DEC: + case OCTEON_COP2_SEL_AES_RESULT0: + case OCTEON_COP2_SEL_AES_RESULT1: + case OCTEON_COP2_SEL_AES_IV0: + case OCTEON_COP2_SEL_AES_IV1: + case OCTEON_COP2_SEL_AES_KEY0: + case OCTEON_COP2_SEL_AES_KEY1: + case OCTEON_COP2_SEL_AES_KEY2: + case OCTEON_COP2_SEL_AES_KEY3: + case OCTEON_COP2_SEL_AES_ENC_CBC0: + case OCTEON_COP2_SEL_AES_ENC0: + case OCTEON_COP2_SEL_AES_DEC_CBC0: + case OCTEON_COP2_SEL_AES_DEC0: + case OCTEON_COP2_SEL_AES_KEYLENGTH: + case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL: + case OCTEON_COP2_SEL_CRC_IV: + case OCTEON_COP2_SEL_CRC_WRITE_LEN: + case OCTEON_COP2_SEL_CRC_WRITE_IV_REFLECT: + case OCTEON_COP2_SEL_CRC_WRITE_BYTE: + case OCTEON_COP2_SEL_CRC_WRITE_HALF: + case OCTEON_COP2_SEL_CRC_WRITE_WORD: + case OCTEON_COP2_SEL_CRC_WRITE_DWORD: + case OCTEON_COP2_SEL_CRC_WRITE_VAR: + case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL_REFLECT: + case OCTEON_COP2_SEL_CRC_WRITE_BYTE_REFLECT: + case OCTEON_COP2_SEL_CRC_WRITE_HALF_REFLECT: + case OCTEON_COP2_SEL_CRC_WRITE_WORD_REFLECT: + case OCTEON_COP2_SEL_CRC_WRITE_DWORD_REFLECT: + case OCTEON_COP2_SEL_CRC_WRITE_VAR_REFLECT: + case OCTEON_COP2_SEL_HSH_DAT0: + case OCTEON_COP2_SEL_HSH_DAT1: + case OCTEON_COP2_SEL_HSH_DAT2: + case OCTEON_COP2_SEL_HSH_DAT3: + case OCTEON_COP2_SEL_HSH_DAT4: + case OCTEON_COP2_SEL_HSH_DAT5: + case OCTEON_COP2_SEL_HSH_DAT6: + case OCTEON_COP2_SEL_HSH_IV0: + case OCTEON_COP2_SEL_HSH_IV1: + case OCTEON_COP2_SEL_HSH_IV2: + case OCTEON_COP2_SEL_HSH_IV3: + case OCTEON_COP2_SEL_HSH_DATW0: + case OCTEON_COP2_SEL_HSH_DATW1: + case OCTEON_COP2_SEL_HSH_DATW2: + case OCTEON_COP2_SEL_HSH_DATW3: + case OCTEON_COP2_SEL_HSH_DATW4: + case OCTEON_COP2_SEL_HSH_DATW5: + case OCTEON_COP2_SEL_HSH_DATW6: + case OCTEON_COP2_SEL_HSH_DATW7: + case OCTEON_COP2_SEL_HSH_DATW8: + case OCTEON_COP2_SEL_HSH_DATW9: + case OCTEON_COP2_SEL_HSH_DATW10: + case OCTEON_COP2_SEL_HSH_DATW11: + case OCTEON_COP2_SEL_HSH_DATW12: + case OCTEON_COP2_SEL_HSH_DATW13: + case OCTEON_COP2_SEL_HSH_DATW14: + case OCTEON_COP2_SEL_HSH_DATW15: + case OCTEON_COP2_SEL_HSH_IVW0: + case OCTEON_COP2_SEL_HSH_IVW1: + case OCTEON_COP2_SEL_HSH_IVW2: + case OCTEON_COP2_SEL_HSH_IVW3: + case OCTEON_COP2_SEL_HSH_IVW4: + case OCTEON_COP2_SEL_HSH_IVW5: + case OCTEON_COP2_SEL_HSH_IVW6: + case OCTEON_COP2_SEL_HSH_IVW7: + case OCTEON_COP2_SEL_GFM_MUL_REFLECT0: + case OCTEON_COP2_SEL_GFM_MUL_REFLECT1: + case OCTEON_COP2_SEL_GFM_XOR0_REFLECT: + case OCTEON_COP2_SEL_GFM_MUL0: + case OCTEON_COP2_SEL_GFM_MUL1: + case OCTEON_COP2_SEL_GFM_RESINP0: + case OCTEON_COP2_SEL_GFM_RESINP1: + case OCTEON_COP2_SEL_GFM_XOR0: + case OCTEON_COP2_SEL_GFM_POLY: + case OCTEON_COP2_SEL_HSH_STARTSHA1_COMPAT: + case OCTEON_COP2_SEL_HSH_STARTMD5: + case OCTEON_COP2_SEL_SNOW3G_START: + case OCTEON_COP2_SEL_SNOW3G_MORE: + case OCTEON_COP2_SEL_HSH_STARTSHA256: + case OCTEON_COP2_SEL_HSH_STARTSHA1: + case OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT: + case OCTEON_COP2_SEL_HSH_STARTSHA512: + case OCTEON_COP2_SEL_GFM_XORMUL1: + case OCTEON_COP2_SEL_AES_ENC_CBC1: + case OCTEON_COP2_SEL_AES_ENC1: + case OCTEON_COP2_SEL_AES_DEC_CBC1: + case OCTEON_COP2_SEL_AES_DEC1: + return true; + default: + return false; + } +} + +bool gen_octeon_cop2(DisasContext *ctx) +{ + enum { + OCTEON_CP2_RS_DMFC2 =3D 0x01, + OCTEON_CP2_RS_DMTC2 =3D 0x05, + }; + int rs =3D extract32(ctx->opcode, 21, 5); + int rt =3D extract32(ctx->opcode, 16, 5); + uint16_t sel =3D ctx->opcode; + TCGv_i64 t0; + + switch (rs) { + case OCTEON_CP2_RS_DMFC2: + if (!octeon_check_64(ctx)) { + return true; + } + if (!octeon_cop2_is_supported_dmfc2(sel)) { + return false; + } + t0 =3D tcg_temp_new_i64(); + gen_helper_octeon_cop2_dmfc2(t0, tcg_env, tcg_constant_i32(sel)); + gen_store_gpr(t0, rt); + return true; + case OCTEON_CP2_RS_DMTC2: + if (!octeon_check_64(ctx)) { + return true; + } + if (!octeon_cop2_is_supported_dmtc2(sel)) { + return false; + } + t0 =3D tcg_temp_new_i64(); + gen_load_gpr(t0, rt); + gen_helper_octeon_cop2_dmtc2(tcg_env, t0, tcg_constant_i32(sel)); + return true; + default: + return false; + } +} + static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a) { TCGv_i64 p; diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 2e3fe1fa16..ca9cee7ed6 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -14860,6 +14860,15 @@ static bool decode_opc_legacy(CPUMIPSState *env, D= isasContext *ctx) } break; case OPC_CP2: +#if defined(TARGET_MIPS64) + if (ctx->insn_flags & INSN_OCTEON) { + if (gen_octeon_cop2(ctx)) { + break; + } + generate_exception_err(ctx, EXCP_CpU, 2); + break; + } +#endif check_insn(ctx, ASE_LMMI); /* Note that these instructions use different fields. */ gen_loongson_multimedia(ctx, sa, rd, rt); diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index 89dde1e712..feb3c47c44 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -232,6 +232,7 @@ bool decode_ext_loongson(DisasContext *ctx, uint32_t in= sn); bool decode_ase_lcsr(DisasContext *ctx, uint32_t insn); bool decode_ext_tx79(DisasContext *ctx, uint32_t insn); bool decode_ext_octeon(DisasContext *ctx, uint32_t insn); +bool gen_octeon_cop2(DisasContext *ctx); #endif bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn); =20 diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips= /user/isa/octeon/octeon-insns.c index e9db93d1b6..059527fe5d 100644 --- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c +++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c @@ -129,6 +129,70 @@ static uint64_t octeon_vmm0(uint64_t mpl0, uint64_t p0, return rd; } =20 +static uint64_t octeon_cop2_key0_readback(uint64_t value) +{ + uint64_t rd; + + asm volatile( + "move $8, %[value]\n\t" + ".word 0x48a80104\n\t" /* dmtc2 $8, AES_KEY0 selector */ + ".word 0x482a0104\n\t" /* dmfc2 $10, AES_KEY0 selector */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [value] "r" (value) + : "$8", "$10"); + + return rd; +} + +static uint64_t octeon_cop2_key2_readback(uint64_t value) +{ + uint64_t rd; + + asm volatile( + "move $8, %[value]\n\t" + ".word 0x48a80106\n\t" /* dmtc2 $8, AES_KEY2 selector */ + ".word 0x482a0106\n\t" /* dmfc2 $10, AES_KEY2 selector */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [value] "r" (value) + : "$8", "$10"); + + return rd; +} + +static uint64_t octeon_cop2_key3_readback(uint64_t value) +{ + uint64_t rd; + + asm volatile( + "move $8, %[value]\n\t" + ".word 0x48a80107\n\t" /* dmtc2 $8, AES_KEY3 selector */ + ".word 0x482a0107\n\t" /* dmfc2 $10, AES_KEY3 selector */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [value] "r" (value) + : "$8", "$10"); + + return rd; +} + +static uint64_t octeon_cop2_keylength_readback(uint64_t value) +{ + uint64_t rd; + + asm volatile( + "move $8, %[value]\n\t" + ".word 0x48a80110\n\t" /* dmtc2 $8, AES_KEYLENGTH selector */ + ".word 0x482a0110\n\t" /* dmfc2 $10, AES_KEYLENGTH selector */ + "move %[rd], $10\n\t" + : [rd] "=3Dr" (rd) + : [value] "r" (value) + : "$8", "$10"); + + return rd; +} + int main(void) { assert(octeon_baddu(0x123, 0x0f0) =3D=3D 0x13); @@ -140,6 +204,13 @@ int main(void) assert(octeon_sne(0xabc, 0xdef) =3D=3D 1); assert(octeon_vmulu(5, 7, 11) =3D=3D 46); assert(octeon_vmm0(5, 13, 7, 11) =3D=3D 59); + assert(octeon_cop2_key0_readback(0x1122334455667788ULL) =3D=3D + 0x1122334455667788ULL); + assert(octeon_cop2_key2_readback(0x8877665544332211ULL) =3D=3D + 0x8877665544332211ULL); + assert(octeon_cop2_key3_readback(0x0102030405060708ULL) =3D=3D + 0x0102030405060708ULL); + assert(octeon_cop2_keylength_readback(0xa5) =3D=3D 0xa5); =20 return 0; } --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792518; cv=none; d=zohomail.com; s=zohoarc; b=NXJWWZZmMmD79PzbNcawrzGSSVA1DQRla0X2weajgrzO3ooSZc/ikIeuIHOkkRUENz8iQgdArCTiBrc9i0xZ0/qlLcI8lkSR0JU2ZSeyp2Y7PkUvQ67GF/QWWpAEWImbLYKe3ZJN004IJA6ugc0ehvjDBNn0f26lOkTkILShhwc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792518; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ME6KoWLBE0ODBY+GKyHQ9Gtlam6/znsLV6zes+dXvhw=; b=C4ohj9E2NDzqhBucfuFihfGgqPDLqCN7O/GU6J31csmRXQ0SvI1NYWXP6ZCFdv4WV0kEdmXXvoXL3iXuHNE6Tvhzqlr7AgbtqQriepI8WOYZo1slmGt2VXBJ6W+lO0fqOjAJJ/Q4p9OfwVEyeiocFf+Zj4ze3qjnGylYFlLLjkg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792518203595.7838234850913; Tue, 21 Apr 2026 10:28:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtP-00040Q-GR; Tue, 21 Apr 2026 13:28:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEt8-0003mh-EB for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:56 -0400 Received: from mail-oa1-x32.google.com ([2001:4860:4864:20::32]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt5-0006hy-84 for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:53 -0400 Received: by mail-oa1-x32.google.com with SMTP id 586e51a60fabf-40f1ffba6a0so3007810fac.0 for ; Tue, 21 Apr 2026 10:27:47 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792467; x=1777397267; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=ME6KoWLBE0ODBY+GKyHQ9Gtlam6/znsLV6zes+dXvhw=; b=VEoAT0og+jfMiX3JRX/S5JoT1y29FBpJ5UUfGZ68aMARqu19Joz3m8vhlj5DCvYoag jyDfpxbHxk2e1lNA2ycqjFDAnJby3mQevoDgs3ZpIpAr4E4izBQpYcnOLLsh9vGq3oee jgYdPWvXca3RhDidkcVlyr5Lo02pY1an7lw+BLmcTet66k2AIGw6eZaZTEr0j9rbID1F zkJSIWeCYl61Pdgwe0Iq7hRIJu4qgBpsCD7rpbvcREb72dhL/FcuSGfme1REKWf2BixS PAU04TSqoznPXMpfoKB4yLqR6yOrOqN7xem3mKnA1t4XzrVseX2INSb6rKSSEzMbdnHM b/IQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792467; x=1777397267; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=ME6KoWLBE0ODBY+GKyHQ9Gtlam6/znsLV6zes+dXvhw=; b=k+mRRn5OKF2tJZeBJWWk4b15iuYiB0b4Ft0ZSX333WIwSOn5Iu2y2Jiqv7xFpFmZ9L 0YKlQFkbXS1Ke9iqmbBeKlafjH0IQ1j+4Vna3bxjnhEwyYzP0Glah3DLgNzleTtx1/s1 Sj94yVJeWlL+PHl20qo/a/+i+XLqJFv4txGg+RvKj3oDQXj9y+34Xg9pWW3nGC0dVQwR jKCVIoRxAPL2qa9yg/b6oLY5VgVjhrqulcKFNdlLAoSupIi2+vGj9hCFI908/4axjEoY nDhp41BwePXAS9aPcM/dakyq90Ovf6MmEZ+/VDeTucOJP1ParKmTUacRgenXwCr7UsWF IrUg== X-Gm-Message-State: AOJu0Ywolkdjfgq73vBBR7vCTKx54E1AstRCUijme+7j2tUwj2F10ktZ mbNYAHESPw87XPY3XtdYnTQMkS+hCuVO9z0Lw56IURtGypAM0sa1F+nW X-Gm-Gg: AeBDieukyWyPsNcIcNgB6J4kWuot9wkEk66dKRWFljOjPz9YwimaYmQlHmB4AE3BiZU eoopAAWgUBt3csez2uL078VJV4664OFjK+1PXJr6dIXOBS1MVj2I+B/XxQI1nTef/RxJPPkcYfh HdXTRXVlnw+YS/urvsndOVsPDSEWNhy2Mz6D4KrdtcaIC78pTl7VXhKNT1PfchuDedVGoB39NMc w3vzS6L0aywUgfh0xsXinEqyn0uJ5HErBJ0vL3ECI+iPa6PKNs2Rj/UW/5PzajI2xZM2AVfZeHA IzTkklCdLJN/GchxYcOXrqWny61rZ2D8XDQ+EvXOXUHax4GLmSQU9Tz5hxPvAkE7iAtGHkfZ26Y dgF1I9Q8ywDv4kqW910YaGflyz6KwovUSx5un4/hCghSnbTESLFWpGNdg2tS4npYS7zPV4dyyqX kNpVcisS3SQL4iWrnYxaW8/JM5khCVCcG8ajcyRjn9k7SnRT0LsHsYhNu3BDlq7IucCKnyZiJBb 7NLyJqdPzHVi4Pq6I36oibP87iRGc+uZ9rb6r9bnMhivBBfNV1nfrfXUXyfh3chllGoVJrnw7aq cNJOaQ== X-Received: by 2002:a05:6870:e997:b0:42c:24f6:f190 with SMTP id 586e51a60fabf-42c24f724d4mr2765105fac.17.1776792466585; Tue, 21 Apr 2026 10:27:46 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:35 -0600 Subject: [PATCH v2 08/13] target/mips: add Octeon SMS4 crypto support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-8-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::32; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x32.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792520074154100 On Octeon, the SMS4 engine is exposed through selectors that alias the AES register bank. Add the missing selectors and model the shared RESULT, IV, and key state so the hardware interface matches the processor behaviour. Use the in-tree SM4 tables to implement the block operation without adding a host crypto dependency. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Add selector dispatch updates in octeon_translate.c after moving COP2 decode out of translate.c. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/cpu.h | 18 ++++++ target/mips/tcg/octeon_crypto.c | 109 +++++++++++++++++++++++++++++++++= ++++ target/mips/tcg/octeon_translate.c | 4 ++ 3 files changed, 131 insertions(+) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 9e398e1ce5..887aeff12d 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -585,6 +585,20 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_AES_DEC0 =3D 0x010e, OCTEON_COP2_SEL_AES_KEYLENGTH =3D 0x0110, OCTEON_COP2_SEL_AES_DAT0 =3D 0x0111, + /* + * SMS4 reuses the AES result/input, IV, and key banks and only adds + * operation selectors for ECB/CBC encrypt/decrypt. + */ + OCTEON_COP2_SEL_SMS4_RESINP0 =3D OCTEON_COP2_SEL_AES_RESULT0, + OCTEON_COP2_SEL_SMS4_RESINP1 =3D OCTEON_COP2_SEL_AES_RESULT1, + OCTEON_COP2_SEL_SMS4_IV0 =3D OCTEON_COP2_SEL_AES_IV0, + OCTEON_COP2_SEL_SMS4_IV1 =3D OCTEON_COP2_SEL_AES_IV1, + OCTEON_COP2_SEL_SMS4_KEY0 =3D OCTEON_COP2_SEL_AES_KEY0, + OCTEON_COP2_SEL_SMS4_KEY1 =3D OCTEON_COP2_SEL_AES_KEY1, + OCTEON_COP2_SEL_SMS4_ENC_CBC0 =3D OCTEON_COP2_SEL_AES_ENC_CBC0, + OCTEON_COP2_SEL_SMS4_ENC0 =3D OCTEON_COP2_SEL_AES_ENC0, + OCTEON_COP2_SEL_SMS4_DEC_CBC0 =3D OCTEON_COP2_SEL_AES_DEC_CBC0, + OCTEON_COP2_SEL_SMS4_DEC0 =3D OCTEON_COP2_SEL_AES_DEC0, OCTEON_COP2_SEL_CRC_POLYNOMIAL =3D 0x0200, OCTEON_COP2_SEL_CRC_IV =3D 0x0201, OCTEON_COP2_SEL_CRC_LEN =3D 0x0202, @@ -653,6 +667,10 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_AES_ENC1 =3D 0x310b, OCTEON_COP2_SEL_AES_DEC_CBC1 =3D 0x310d, OCTEON_COP2_SEL_AES_DEC1 =3D 0x310f, + OCTEON_COP2_SEL_SMS4_ENC_CBC1 =3D 0x3119, + OCTEON_COP2_SEL_SMS4_ENC1 =3D 0x311b, + OCTEON_COP2_SEL_SMS4_DEC_CBC1 =3D 0x311d, + OCTEON_COP2_SEL_SMS4_DEC1 =3D 0x311f, OCTEON_COP2_SEL_HSH_STARTMD5 =3D 0x4047, OCTEON_COP2_SEL_SNOW3G_START =3D 0x404d, OCTEON_COP2_SEL_SNOW3G_MORE =3D 0x404e, diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypt= o.c index 43012ff027..177d112483 100644 --- a/target/mips/tcg/octeon_crypto.c +++ b/target/mips/tcg/octeon_crypto.c @@ -12,6 +12,7 @@ #include "exec/helper-proto.h" #include "crypto/aes.h" #include "crypto/clmul.h" +#include "crypto/sm4.h" #include "qemu/bitops.h" #include "qemu/host-utils.h" =20 @@ -745,6 +746,57 @@ static int octeon_aes_key_bits(const MIPSOcteonCryptoS= tate *crypto) } } =20 +static inline uint32_t octeon_sms4_t(uint32_t x) +{ + x =3D sm4_subword(x); + return x ^ rol32(x, 2) ^ rol32(x, 10) ^ + rol32(x, 18) ^ rol32(x, 24); +} + +static inline uint32_t octeon_sms4_t_key(uint32_t x) +{ + x =3D sm4_subword(x); + return x ^ rol32(x, 13) ^ rol32(x, 23); +} + +static void octeon_sms4_expand_key(const uint8_t *key, uint32_t round_keys= [32]) +{ + static const uint32_t fk[4] =3D { + 0xa3b1bac6U, 0x56aa3350U, 0x677d9197U, 0xb27022dcU, + }; + uint32_t k[36]; + + for (int i =3D 0; i < 4; i++) { + k[i] =3D ldl_be_p(key + i * 4) ^ fk[i]; + } + for (int i =3D 0; i < 32; i++) { + k[i + 4] =3D k[i] ^ octeon_sms4_t_key(k[i + 1] ^ k[i + 2] ^ + k[i + 3] ^ sm4_ck[i]); + round_keys[i] =3D k[i + 4]; + } +} + +static void octeon_sms4_crypt_block(const uint8_t *in, uint8_t *out, + const uint32_t round_keys[32], + bool encrypt) +{ + uint32_t x[36]; + + for (int i =3D 0; i < 4; i++) { + x[i] =3D ldl_be_p(in + i * 4); + } + for (int i =3D 0; i < 32; i++) { + uint32_t rk =3D round_keys[encrypt ? i : 31 - i]; + + x[i + 4] =3D x[i] ^ octeon_sms4_t(x[i + 1] ^ x[i + 2] ^ + x[i + 3] ^ rk); + } + stl_be_p(out, x[35]); + stl_be_p(out + 4, x[34]); + stl_be_p(out + 8, x[33]); + stl_be_p(out + 12, x[32]); +} + static const uint8_t octeon_des_ip[64] =3D { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, @@ -1198,6 +1250,47 @@ static void octeon_aes_store_block(uint64_t regs[2],= const uint8_t *block) regs[1] =3D ldq_be_p(block + 8); } =20 +static void octeon_sms4_crypt_common(MIPSOcteonCryptoState *crypto, + bool encrypt, bool cbc) +{ + uint8_t key[16]; + uint8_t in[16]; + uint8_t out[16]; + uint8_t iv[16]; + uint8_t next_iv[16]; + uint32_t round_keys[32]; + + /* + * SMS4 aliases the AES state onto the RESULT/RESINP, IV, and KEY bank= s, + * with only the operation selectors remaining distinct. + */ + octeon_aes_load_key(crypto, key, sizeof(key)); + octeon_aes_load_block(crypto->aes_input, in); + if (cbc) { + octeon_aes_load_block(crypto->aes_iv, iv); + if (encrypt) { + for (int i =3D 0; i < sizeof(in); i++) { + in[i] ^=3D iv[i]; + } + } else { + memcpy(next_iv, in, sizeof(next_iv)); + } + } + + octeon_sms4_expand_key(key, round_keys); + octeon_sms4_crypt_block(in, out, round_keys, encrypt); + if (cbc && !encrypt) { + for (int i =3D 0; i < sizeof(out); i++) { + out[i] ^=3D iv[i]; + } + } + + octeon_aes_store_block(crypto->aes_result, out); + if (cbc) { + octeon_aes_store_block(crypto->aes_iv, encrypt ? out : next_iv); + } +} + static void octeon_aes_encrypt_common(MIPSOcteonCryptoState *crypto, bool = cbc) { AES_KEY key; @@ -1614,6 +1707,22 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uin= t64_t value, crypto->aes_input[1] =3D q; octeon_aes_decrypt_common(crypto, false); break; + case OCTEON_COP2_SEL_SMS4_ENC_CBC1: + crypto->aes_input[1] =3D q; + octeon_sms4_crypt_common(crypto, true, true); + break; + case OCTEON_COP2_SEL_SMS4_ENC1: + crypto->aes_input[1] =3D q; + octeon_sms4_crypt_common(crypto, true, false); + break; + case OCTEON_COP2_SEL_SMS4_DEC_CBC1: + crypto->aes_input[1] =3D q; + octeon_sms4_crypt_common(crypto, false, true); + break; + case OCTEON_COP2_SEL_SMS4_DEC1: + crypto->aes_input[1] =3D q; + octeon_sms4_crypt_common(crypto, false, false); + break; case OCTEON_COP2_SEL_GFM_XORMUL1: { uint64_t in[2] =3D { crypto->gfm_result[0] ^ crypto->gfm_xor0, diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index ac5065398d..84fe3b38d0 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -186,6 +186,10 @@ static bool octeon_cop2_is_supported_dmtc2(uint16_t se= l) case OCTEON_COP2_SEL_AES_ENC1: case OCTEON_COP2_SEL_AES_DEC_CBC1: case OCTEON_COP2_SEL_AES_DEC1: + case OCTEON_COP2_SEL_SMS4_ENC_CBC1: + case OCTEON_COP2_SEL_SMS4_ENC1: + case OCTEON_COP2_SEL_SMS4_DEC_CBC1: + case OCTEON_COP2_SEL_SMS4_DEC1: return true; default: return false; --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792569; cv=none; d=zohomail.com; s=zohoarc; b=CRKkBXdeQ0fZB6wsbzBeDrMGEkDDtXmyXDTrgLo4Z9CgxRAU8gj+k6NG9fubsA/fVXkzpCruVZHbEC8G1iTERnJrVgOeBJMT/kyHr6xEUgvbaHmxf3zw3Ndeh61BlK+or2b+jWUTrgEkgf/i3BYznFItv5SLymw/+xvmQqVv1Es= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792569; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qysWhW4sZ2k4fvCSAIQwvHK+YYsE649PPxBVUHi+4QU=; b=k6Pr/XgRGoLQiG3gnuN+1sTt1/BbMsv0qBsqpI0O+Lt3k2crbHdPMA9pIalpg1sKdZ4obCWvo/+94bTU4k5/e5ywAej+P9YLqA4Qw1XZzsI7jE7ce75uHgvtMSLUQlC1JjEmelUTFF3TqmMRY2UnkrKW0N9RUKdVZutP227D3ww= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17767925695440.07232950037348473; Tue, 21 Apr 2026 10:29:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtP-00040V-MC; Tue, 21 Apr 2026 13:28:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtB-0003nb-Vt for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:28:01 -0400 Received: from mail-oa1-x2a.google.com ([2001:4860:4864:20::2a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt6-0006i4-Gv for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:56 -0400 Received: by mail-oa1-x2a.google.com with SMTP id 586e51a60fabf-4042905015cso2777194fac.0 for ; Tue, 21 Apr 2026 10:27:48 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792468; x=1777397268; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=qysWhW4sZ2k4fvCSAIQwvHK+YYsE649PPxBVUHi+4QU=; b=UbxClxG44gRSTWTFqqFK8jBPaLlNuMLdDDXimOHIjPhWM6FoA7ct8dC1CtbAqImx9r gnCR4KUSBGXx9ejyKImVfEMsRuOp7aqIUU8um7fhoCET/A/b2AJcTZq39XpmHU2sRwq7 H9q3S45HPcxCOzuQqIUHmYnG+yvQOeefaF3GKP1d9/85LzPxg9/Vtqb8s4fxJDU+BNM7 WnCMIx1IINpSYUnTt9ASDGdyhFDQ4DDpvQ8eKrGsXYxUWHi42TkvxZq6CosLimfIrZPm vzgMq3XIn8wb6bMgz2g3g8EKsN7i33I5sCOtI/mvmWOYUXCHONDsJSniCHNnReXh1O7l BBQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792468; x=1777397268; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=qysWhW4sZ2k4fvCSAIQwvHK+YYsE649PPxBVUHi+4QU=; b=ZakpLLy2dZC1ddyPIeIYXC0Z/0xyCcSFRDMaDlaIYht0aJtKql4H0qGQ9KLeliJzLn 4l9aA665gaR20YCrG0Zn/xxRSwAURg3dy/KRl6sSgYuunMC2uoz2hyicdAVWSv/i5AtV DnHEsI8EabT2f7vQxVyrtvOonfkh2bRAS5LY6hfTWOjbxM8yzwPEULUmDQcUhyq/2+P8 t+7loQqWeL1SR0skhYkRE63lxOEP0UyTfsda/XsIDrfECL2Cohu+6xEu9FB2EIW5jnou OWlqWEvpti61kDMg9saNh3jFrQEUYQ8yYzWntBS5vRrn6UcYyhbGoMsSFNCgRLl99Uoh nwjQ== X-Gm-Message-State: AOJu0Yyn+Qdp9MQjuu+09KgBNr5+BypsQ+ewBU/2a8sc3xK1Onq8mMmg /4KddW/h/nzdiaMmeqilZQFksBI5qUUZtDswDqaj+VnmS5xShLolMn8kFQex5A== X-Gm-Gg: AeBDieutWJbVcYG2beoqMintEWzNzubYVxFEFiwE9VIyFQQoaF+m4wzX/apOSylkJZH cwHDNAzQbkbn3deeXTI+L0qnJYfEJqaSI4qM2upS+95KMIUv1y04Mrh8n3r+aIWmwyOzR24L++R 7sN5BGFOsBv2wh+8OToJNeiPjgcNYaycKu7m7+KY6K5Ak1S7zzgJ3O1PzuaxFihZQ18OwVLPWiV umfnICB1GurNh5hs+52yPKzU2EgxHErFz2z2qgISzn5eO0fMjV61WCpWVkH4s/p0drTVdOoKXhd IXfGo5Y8urJgl5dZ0NRg5uSGfx/BOoS7zuASPU4eGLF0d2nQ715zn3j0witqDl+C/TdkrbE7uNd nQ5C0yVxdawLGNGkrmwXjsrPaEgyQN98PtHq8n/LLj+ASW8SnlMeLbFOGL0qtoJaCDPNSWjDtqQ IVO9jyTeCWPykYxFr592QwVeI286smM+mUBlIfAJLKofcxMMu5UCUw4Am29F3K6Np/328wJEZzI i7VSjRiHLBOZAd8Doqm95OCcH9D1Mf8TdoNsrt055xL9+qAlNwET7tvb5k/8Oyc7/m+m2U3P3E1 oSIQTg== X-Received: by 2002:a05:6870:968d:b0:409:81eb:cf56 with SMTP id 586e51a60fabf-42aded2a4e3mr11684930fac.27.1776792467541; Tue, 21 Apr 2026 10:27:47 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:36 -0600 Subject: [PATCH v2 09/13] target/mips: add Octeon SHA3 crypto support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-9-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::2a; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x2a.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792572645154100 Add the Octeon SHA3 register window and STARTOP selector. Keep the shared HSH/SHA3/SHA512 write path coherent, then model the dedicated 25-lane Keccak state and the Keccak-f[1600] permutation so the COP2 SHA3 interface follows the hardware behaviour. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Use switch ranges and g_assert_not_reached() for SHA3 selector position decoding. (suggested by Philippe Mathieu-Daud=C3=A9) - Add selector dispatch updates in octeon_translate.c after moving COP2 decode out of translate.c. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/cpu.h | 22 +++++ target/mips/system/machine.c | 1 + target/mips/tcg/octeon_crypto.c | 171 +++++++++++++++++++++++++++++++++= ++++ target/mips/tcg/octeon_translate.c | 22 +++++ 4 files changed, 216 insertions(+) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 887aeff12d..34fe7e1285 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -533,6 +533,7 @@ typedef enum MIPSOcteonSharedMode { OCTEON_SHARED_MODE_NONE =3D 0, OCTEON_SHARED_MODE_SHA512, OCTEON_SHARED_MODE_SNOW3G, + OCTEON_SHARED_MODE_SHA3, } MIPSOcteonSharedMode; =20 typedef enum MIPSOcteonCop2Sel { @@ -637,6 +638,7 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_HSH_DATW13, OCTEON_COP2_SEL_HSH_DATW14, OCTEON_COP2_SEL_HSH_DATW15, + OCTEON_COP2_SEL_SHA3_DAT15_READ =3D 0x024f, OCTEON_COP2_SEL_HSH_IVW0 =3D 0x0250, OCTEON_COP2_SEL_HSH_IVW1, OCTEON_COP2_SEL_HSH_IVW2, @@ -663,6 +665,24 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_GFM_RESINP1, OCTEON_COP2_SEL_GFM_XOR0, OCTEON_COP2_SEL_GFM_POLY =3D 0x025e, + OCTEON_COP2_SEL_SHA3_XORDAT0 =3D 0x02c0, + OCTEON_COP2_SEL_SHA3_XORDAT1, + OCTEON_COP2_SEL_SHA3_XORDAT2, + OCTEON_COP2_SEL_SHA3_XORDAT3, + OCTEON_COP2_SEL_SHA3_XORDAT4, + OCTEON_COP2_SEL_SHA3_XORDAT5, + OCTEON_COP2_SEL_SHA3_XORDAT6, + OCTEON_COP2_SEL_SHA3_XORDAT7, + OCTEON_COP2_SEL_SHA3_XORDAT8, + OCTEON_COP2_SEL_SHA3_XORDAT9, + OCTEON_COP2_SEL_SHA3_XORDAT10, + OCTEON_COP2_SEL_SHA3_XORDAT11, + OCTEON_COP2_SEL_SHA3_XORDAT12, + OCTEON_COP2_SEL_SHA3_XORDAT13, + OCTEON_COP2_SEL_SHA3_XORDAT14, + OCTEON_COP2_SEL_SHA3_XORDAT15, + OCTEON_COP2_SEL_SHA3_XORDAT16, + OCTEON_COP2_SEL_SHA3_XORDAT17, OCTEON_COP2_SEL_AES_ENC_CBC1 =3D 0x3109, OCTEON_COP2_SEL_AES_ENC1 =3D 0x310b, OCTEON_COP2_SEL_AES_DEC_CBC1 =3D 0x310d, @@ -675,6 +695,7 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_SNOW3G_START =3D 0x404d, OCTEON_COP2_SEL_SNOW3G_MORE =3D 0x404e, OCTEON_COP2_SEL_HSH_STARTSHA256 =3D 0x404f, + OCTEON_COP2_SEL_SHA3_STARTOP =3D 0x4052, OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT =3D 0x405d, OCTEON_COP2_SEL_HSH_STARTSHA1 =3D 0x4057, OCTEON_COP2_SEL_HSH_STARTSHA512 =3D 0x424f, @@ -689,6 +710,7 @@ typedef struct MIPSOcteonCryptoState { uint64_t hash_block[8]; uint64_t sha512_state[8]; uint64_t sha512_block[16]; + uint64_t sha3_state[25]; uint64_t aes_iv[2]; uint64_t aes_key[4]; uint64_t aes_result[2]; diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c index d5452a3157..c646e8b836 100644 --- a/target/mips/system/machine.c +++ b/target/mips/system/machine.c @@ -282,6 +282,7 @@ static const VMStateDescription mips_vmstate_octeon_cry= pto =3D { VMSTATE_UINT64_ARRAY(env.octeon_crypto.hash_block, MIPSCPU, 8), VMSTATE_UINT64_ARRAY(env.octeon_crypto.sha512_state, MIPSCPU, 8), VMSTATE_UINT64_ARRAY(env.octeon_crypto.sha512_block, MIPSCPU, 16), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.sha3_state, MIPSCPU, 25), VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_iv, MIPSCPU, 2), VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_key, MIPSCPU, 4), VMSTATE_UINT64_ARRAY(env.octeon_crypto.aes_result, MIPSCPU, 2), diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypt= o.c index 177d112483..d9e66f3dc8 100644 --- a/target/mips/tcg/octeon_crypto.c +++ b/target/mips/tcg/octeon_crypto.c @@ -487,21 +487,150 @@ static void octeon_sha512_transform(MIPSOcteonCrypto= State *crypto) crypto->sha512_state[7] +=3D h; } =20 +static const uint64_t octeon_sha3_round_constants[24] =3D { + 0x0000000000000001ULL, 0x0000000000008082ULL, + 0x800000000000808aULL, 0x8000000080008000ULL, + 0x000000000000808bULL, 0x0000000080000001ULL, + 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x000000000000008aULL, 0x0000000000000088ULL, + 0x0000000080008009ULL, 0x000000008000000aULL, + 0x000000008000808bULL, 0x800000000000008bULL, + 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, + 0x000000000000800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, + 0x0000000080000001ULL, 0x8000000080008008ULL, +}; + +static const uint8_t octeon_sha3_rotation_constants[24] =3D { + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, +}; + +static const uint8_t octeon_sha3_pi_lanes[24] =3D { + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, +}; + +static void octeon_sha3_permute(MIPSOcteonCryptoState *crypto) +{ + uint64_t *state =3D crypto->sha3_state; + + for (int round =3D 0; round < 24; round++) { + uint64_t bc[5]; + uint64_t temp; + + for (int x =3D 0; x < 5; x++) { + bc[x] =3D state[x] ^ state[5 + x] ^ state[10 + x] ^ + state[15 + x] ^ state[20 + x]; + } + for (int x =3D 0; x < 5; x++) { + temp =3D bc[(x + 4) % 5] ^ rol64(bc[(x + 1) % 5], 1); + for (int y =3D 0; y < 25; y +=3D 5) { + state[y + x] ^=3D temp; + } + } + + temp =3D state[1]; + for (int i =3D 0; i < 24; i++) { + uint64_t next =3D state[octeon_sha3_pi_lanes[i]]; + + state[octeon_sha3_pi_lanes[i]] =3D + rol64(temp, octeon_sha3_rotation_constants[i]); + temp =3D next; + } + + for (int y =3D 0; y < 25; y +=3D 5) { + for (int x =3D 0; x < 5; x++) { + bc[x] =3D state[y + x]; + } + for (int x =3D 0; x < 5; x++) { + state[y + x] =3D bc[x] ^ ((~bc[(x + 1) % 5]) & bc[(x + 2) = % 5]); + } + } + + state[0] ^=3D octeon_sha3_round_constants[round]; + } +} + +static bool octeon_sha3_is_dat_sel(uint32_t sel) +{ + switch (sel) { + case OCTEON_COP2_SEL_HSH_DATW0 ... OCTEON_COP2_SEL_HSH_DATW15: + case OCTEON_COP2_SEL_HSH_IVW0 ... OCTEON_COP2_SEL_HSH_IVW7: + case OCTEON_COP2_SEL_SHA3_DAT15_WRITE: + case OCTEON_COP2_SEL_SHA3_DAT24: + return true; + default: + return false; + } +} + +static int octeon_sha3_dat_pos_from_sel(uint32_t sel) +{ + switch (sel) { + case OCTEON_COP2_SEL_HSH_DATW0 ... OCTEON_COP2_SEL_HSH_DATW14: + return sel - OCTEON_COP2_SEL_HSH_DATW0; + case OCTEON_COP2_SEL_HSH_IVW0 ... OCTEON_COP2_SEL_HSH_IVW7: + return 16 + (sel - OCTEON_COP2_SEL_HSH_IVW0); + case OCTEON_COP2_SEL_HSH_DATW15: + case OCTEON_COP2_SEL_SHA3_DAT15_WRITE: + return 15; + case OCTEON_COP2_SEL_SHA3_DAT24: + return 24; + default: + g_assert_not_reached(); + } +} + +static uint64_t octeon_sha3_reg_to_lane(uint64_t value) +{ + /* + * The COP2 register interface is consumed by big-endian MIPS code as + * 64-bit register values, while Keccak lanes are byte-little-endian. + */ + return bswap64(value); +} + +static uint64_t octeon_sha3_lane_to_reg(uint64_t value) +{ + return bswap64(value); +} + static void octeon_store_shared_hash_dat(MIPSOcteonCryptoState *crypto, uint32_t sel, uint64_t value) { switch (sel) { case OCTEON_COP2_SEL_HSH_DATW0 ... OCTEON_COP2_SEL_HSH_DATW14: crypto->sha512_block[sel - OCTEON_COP2_SEL_HSH_DATW0] =3D value; + crypto->sha3_state[sel - OCTEON_COP2_SEL_HSH_DATW0] =3D + octeon_sha3_reg_to_lane(value); break; case OCTEON_COP2_SEL_HSH_IVW0 ... OCTEON_COP2_SEL_HSH_IVW7: crypto->sha512_state[sel - OCTEON_COP2_SEL_HSH_IVW0] =3D value; + crypto->sha3_state[16 + (sel - OCTEON_COP2_SEL_HSH_IVW0)] =3D + octeon_sha3_reg_to_lane(value); + break; + case OCTEON_COP2_SEL_SHA3_DAT15_WRITE: + crypto->sha3_state[15] =3D octeon_sha3_reg_to_lane(value); + break; + case OCTEON_COP2_SEL_SHA3_DAT24: + crypto->sha3_state[24] =3D octeon_sha3_reg_to_lane(value); break; default: g_assert_not_reached(); } } =20 +static int octeon_sha3_xordat_pos_from_sel(uint32_t sel) +{ + if (sel >=3D OCTEON_COP2_SEL_SHA3_XORDAT0 && + sel <=3D OCTEON_COP2_SEL_SHA3_XORDAT17) { + return sel - OCTEON_COP2_SEL_SHA3_XORDAT0; + } + return -1; +} + static const uint8_t octeon_snow3g_sr[256] =3D { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, @@ -1396,6 +1525,7 @@ static void octeon_gfm_mul(const uint64_t x[2], const= uint64_t y[2], uint64_t helper_octeon_cop2_dmfc2(CPUMIPSState *env, uint32_t sel) { MIPSOcteonCryptoState *crypto =3D &env->octeon_crypto; + int sha3_pos; =20 if (crypto->shared_mode =3D=3D OCTEON_SHARED_MODE_SNOW3G) { if (sel >=3D OCTEON_COP2_SEL_SNOW3G_LFSR0 && @@ -1417,6 +1547,12 @@ uint64_t helper_octeon_cop2_dmfc2(CPUMIPSState *env,= uint32_t sel) } } =20 + if (crypto->shared_mode =3D=3D OCTEON_SHARED_MODE_SHA3 && + octeon_sha3_is_dat_sel(sel)) { + sha3_pos =3D octeon_sha3_dat_pos_from_sel(sel); + return octeon_sha3_lane_to_reg(crypto->sha3_state[sha3_pos]); + } + switch (sel) { case OCTEON_COP2_SEL_3DES_KEY0: case OCTEON_COP2_SEL_3DES_KEY1: @@ -1507,6 +1643,7 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uint= 64_t value, { MIPSOcteonCryptoState *crypto =3D &env->octeon_crypto; uint64_t q =3D (uint64_t)value; + int sha3_pos; =20 switch (sel) { case OCTEON_COP2_SEL_3DES_KEY0: @@ -1628,6 +1765,14 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uin= t64_t value, octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA512); octeon_sha512_transform(crypto); break; + case OCTEON_COP2_SEL_SHA3_DAT15_WRITE: + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA3); + octeon_store_shared_hash_dat(crypto, sel, q); + break; + case OCTEON_COP2_SEL_SHA3_DAT24: + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA3); + octeon_store_shared_hash_dat(crypto, sel, q); + break; case OCTEON_COP2_SEL_HSH_IVW0: case OCTEON_COP2_SEL_HSH_IVW1: case OCTEON_COP2_SEL_HSH_IVW2: @@ -1688,6 +1833,32 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uin= t64_t value, crypto->hash_block[7] =3D q; octeon_sha1_transform(crypto); break; + case OCTEON_COP2_SEL_SHA3_XORDAT0: + case OCTEON_COP2_SEL_SHA3_XORDAT1: + case OCTEON_COP2_SEL_SHA3_XORDAT2: + case OCTEON_COP2_SEL_SHA3_XORDAT3: + case OCTEON_COP2_SEL_SHA3_XORDAT4: + case OCTEON_COP2_SEL_SHA3_XORDAT5: + case OCTEON_COP2_SEL_SHA3_XORDAT6: + case OCTEON_COP2_SEL_SHA3_XORDAT7: + case OCTEON_COP2_SEL_SHA3_XORDAT8: + case OCTEON_COP2_SEL_SHA3_XORDAT9: + case OCTEON_COP2_SEL_SHA3_XORDAT10: + case OCTEON_COP2_SEL_SHA3_XORDAT11: + case OCTEON_COP2_SEL_SHA3_XORDAT12: + case OCTEON_COP2_SEL_SHA3_XORDAT13: + case OCTEON_COP2_SEL_SHA3_XORDAT14: + case OCTEON_COP2_SEL_SHA3_XORDAT15: + case OCTEON_COP2_SEL_SHA3_XORDAT16: + case OCTEON_COP2_SEL_SHA3_XORDAT17: + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA3); + sha3_pos =3D octeon_sha3_xordat_pos_from_sel(sel); + crypto->sha3_state[sha3_pos] ^=3D octeon_sha3_reg_to_lane(q); + break; + case OCTEON_COP2_SEL_SHA3_STARTOP: + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA3); + octeon_sha3_permute(crypto); + break; case OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT: octeon_gfm_mul_reflect(crypto, q); break; diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index 84fe3b38d0..3f8c17678a 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -72,6 +72,7 @@ static bool octeon_cop2_is_supported_dmfc2(uint16_t sel) case OCTEON_COP2_SEL_HSH_IVW6: case OCTEON_COP2_SEL_HSH_IVW7: case OCTEON_COP2_SEL_AES_DAT0: + case OCTEON_COP2_SEL_SHA3_DAT24: case OCTEON_COP2_SEL_GFM_MUL_REFLECT0: case OCTEON_COP2_SEL_GFM_MUL_REFLECT1: case OCTEON_COP2_SEL_GFM_RESINP_REFLECT0: @@ -156,6 +157,8 @@ static bool octeon_cop2_is_supported_dmtc2(uint16_t sel) case OCTEON_COP2_SEL_HSH_DATW13: case OCTEON_COP2_SEL_HSH_DATW14: case OCTEON_COP2_SEL_HSH_DATW15: + case OCTEON_COP2_SEL_SHA3_DAT24: + case OCTEON_COP2_SEL_SHA3_DAT15_WRITE: case OCTEON_COP2_SEL_HSH_IVW0: case OCTEON_COP2_SEL_HSH_IVW1: case OCTEON_COP2_SEL_HSH_IVW2: @@ -173,11 +176,30 @@ static bool octeon_cop2_is_supported_dmtc2(uint16_t s= el) case OCTEON_COP2_SEL_GFM_RESINP1: case OCTEON_COP2_SEL_GFM_XOR0: case OCTEON_COP2_SEL_GFM_POLY: + case OCTEON_COP2_SEL_SHA3_XORDAT0: + case OCTEON_COP2_SEL_SHA3_XORDAT1: + case OCTEON_COP2_SEL_SHA3_XORDAT2: + case OCTEON_COP2_SEL_SHA3_XORDAT3: + case OCTEON_COP2_SEL_SHA3_XORDAT4: + case OCTEON_COP2_SEL_SHA3_XORDAT5: + case OCTEON_COP2_SEL_SHA3_XORDAT6: + case OCTEON_COP2_SEL_SHA3_XORDAT7: + case OCTEON_COP2_SEL_SHA3_XORDAT8: + case OCTEON_COP2_SEL_SHA3_XORDAT9: + case OCTEON_COP2_SEL_SHA3_XORDAT10: + case OCTEON_COP2_SEL_SHA3_XORDAT11: + case OCTEON_COP2_SEL_SHA3_XORDAT12: + case OCTEON_COP2_SEL_SHA3_XORDAT13: + case OCTEON_COP2_SEL_SHA3_XORDAT14: + case OCTEON_COP2_SEL_SHA3_XORDAT15: + case OCTEON_COP2_SEL_SHA3_XORDAT16: + case OCTEON_COP2_SEL_SHA3_XORDAT17: case OCTEON_COP2_SEL_HSH_STARTSHA1_COMPAT: case OCTEON_COP2_SEL_HSH_STARTMD5: case OCTEON_COP2_SEL_SNOW3G_START: case OCTEON_COP2_SEL_SNOW3G_MORE: case OCTEON_COP2_SEL_HSH_STARTSHA256: + case OCTEON_COP2_SEL_SHA3_STARTOP: case OCTEON_COP2_SEL_HSH_STARTSHA1: case OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT: case OCTEON_COP2_SEL_HSH_STARTSHA512: --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792517; cv=none; d=zohomail.com; s=zohoarc; b=N/wBJOd8wzQVIl1h1f6/S/Qij12IYgOjsyXd2t0E07qLhUbSaNDP/UXX0U0BxdeQHB110lEmg1tM+6RM4n95E9Wv9669ztTOPw+LRd/86I/n7MhIt2AIr//DFGiZviLP9y0VXuGilEw57QbwdhOOwUG2DdBCPoJ+nqPHg4nLvGc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792517; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=wAm9XN2l98FgUJ7OPqkGVSIjNCjZCM50u3yUG5jYHmA=; b=T8JRnlwa4QpmavKrwvZeXya/Nfy4dLNNW2XUm9YwXvbvYWxfRWx2AXZRkwW9UNrrd7s94dbnrG8PkXNWkEDYlZFvT9w8+TU4az5HaKzicahlAXaIVsW/nIzkkM46fvaj2XoUfQXYslEWhr+zVYBsd0jnuTfHuOad2x9eiqBXLMo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177679251771982.34178385183748; Tue, 21 Apr 2026 10:28:37 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtO-00040A-Uc; Tue, 21 Apr 2026 13:28:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtB-0003nU-TA for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:59 -0400 Received: from mail-oa1-x2c.google.com ([2001:4860:4864:20::2c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt6-0006iE-Hh for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:56 -0400 Received: by mail-oa1-x2c.google.com with SMTP id 586e51a60fabf-4152698e745so1781631fac.1 for ; Tue, 21 Apr 2026 10:27:50 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792469; x=1777397269; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=wAm9XN2l98FgUJ7OPqkGVSIjNCjZCM50u3yUG5jYHmA=; b=TjTN+PEXrGByzK7Qh5/vaynupqVA2NlxPUnjILcP+UBmWxVV1RVzVE6EX7OFT5Zm9Y HiR+je6iFzr0BUdjb1D9lu3t6xh9ynUB/c2qJTyKFY85Fbw1kf6+nanmsYBVphZnjaii FWMD3dbO2GBsUn6N/crOYoSoPvfhu2tggl64fKvY4NNzadKWoezeUaLDYO37YUb79t24 CRa3wLWHskUH8ERCuJmWy5R3Tvg+M/f8+5xHCoNCJ1NkT5+G2KpF54if+xIjkKdcDk2G VvC2YmsT1SeEdGzdud+YQkiCAmYi3OqbHrjodlRHG1hgDDWq7EKHnMUoB4Ek11iBMc4L NIwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792469; x=1777397269; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=wAm9XN2l98FgUJ7OPqkGVSIjNCjZCM50u3yUG5jYHmA=; b=jq48t2/cCt23+vExsLgJOfuOObnrYBeU0Gh00X0g4N/6IFTyJfeLZX/3N2l9x1iWIg d/kjcYcLZhpvhopkXtM8PLb83P2qrGZlWDvzRZrbDJSMJJpybj8ktJJudWEjWG1oSt/4 5kSPUBLh7XjDzay5PtRT1p//ETKxVnwE6K6AzEnS5NbN+Mq3wnmTzpeuGb9yfyqKfC8v kMfYVK3C3DOZD2ySR+N5Fu2rMWQzSbfeR44Y86FdMbHwnF690+irgihfTBbC2xlLLJra 4vdoO9r7gDjljb8gQ5iuEwXsXtii/ILeI6oHFfuSwpg2jqsuEHth2AhFvjsPCOU5VFmW 2dbw== X-Gm-Message-State: AOJu0YxGrawRkuN0kWll3w+gFL3ugV8IwSuwKJRTQM5ZgXGN9uY/H7HY +aqRO2PUtd4bmZR0ZnPZyjCPMsje82/hDzrcTYm1xAS26sVDZqGv8RzXeqaZcA== X-Gm-Gg: AeBDietc4lVwFSM5+3XWazDXeekxse1d4MS8EOi3MkYM8HoVbs/gKKbZHrUcPkpbGUR lS7uGMk7+FC8DBw+h46Y4a62w8wXtqOcCa2XI1mMQSETBUbifVSRv9Jfo+6CkWt5XppGrToFobu OzUATH6atu650XFbO5U5Rf0pIZ0p8hInYnN8BNtwW9yBpJboNuAGNwKOAAhGQbY1rf0HSAyqG0R HUM23u8R34muqOpp1BWR62A06q9KM5d8ihdsPEQocX9N5Wf9rZnJFKj8n0IDBIzo/xQdl57Ux4w VN+663JYNBQLCkvQMyI3+7q9LJWlUw2Rka7oa/zbZO6OKSm6A5P37Kiyxdd3fhXFjvCFnyRRr7i 4mFo0MsoAJe88c5uAsW7BZulX1wrMhMTqWgS4bgyiUeXV9mAAZvoSi6N6TrKh2w8BAGMw8GUCIy /ndtpAAByTWjhHBQhiMNWAsq+2TPtYm6qVOhWxu1pi2oDzZBCILc+lZUR/bzZuDNISBDODW9SEQ SaWv9O+r7xqrAKEc6MwDPMMLvP7R5k8iaTML9lmLH8D+z1WNCsa24mfNVSTAnO7tqI/RVt1MlLS b8hNgQ== X-Received: by 2002:a05:6870:c6a0:b0:417:48fe:a8ce with SMTP id 586e51a60fabf-42abf213320mr11612186fac.4.1776792468567; Tue, 21 Apr 2026 10:27:48 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:37 -0600 Subject: [PATCH v2 10/13] target/mips: add Octeon ZUC crypto support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-10-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::2c; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x2c.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792519774158500 Add the Octeon ZUC START and MORE selectors and model the shared state window used by the hardware interface. This covers the keystream and MAC engine state, including the save-and-restore view that overlaps the HSH/SHA3 bank. Shared-window writes also update the SHA512/SHA3 backing state so guests can switch between engines without stale register contents. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Add shared-window selector predicates and assert on unreachable ZUC selector switches. (suggested by Philippe Mathieu-Daud=C3=A9) - Preserve aliased HSH/SHA3/SHA512 backing state during ZUC shared-window writes. - Add selector dispatch updates in octeon_translate.c after moving COP2 decode out of translate.c. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/cpu.h | 7 + target/mips/system/machine.c | 4 + target/mips/tcg/octeon_crypto.c | 353 +++++++++++++++++++++++++++++++++= ++++ target/mips/tcg/octeon_translate.c | 2 + 4 files changed, 366 insertions(+) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 34fe7e1285..437d43636b 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -533,6 +533,7 @@ typedef enum MIPSOcteonSharedMode { OCTEON_SHARED_MODE_NONE =3D 0, OCTEON_SHARED_MODE_SHA512, OCTEON_SHARED_MODE_SNOW3G, + OCTEON_SHARED_MODE_ZUC, OCTEON_SHARED_MODE_SHA3, } MIPSOcteonSharedMode; =20 @@ -696,6 +697,8 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_SNOW3G_MORE =3D 0x404e, OCTEON_COP2_SEL_HSH_STARTSHA256 =3D 0x404f, OCTEON_COP2_SEL_SHA3_STARTOP =3D 0x4052, + OCTEON_COP2_SEL_ZUC_START =3D 0x4055, + OCTEON_COP2_SEL_ZUC_MORE =3D 0x4056, OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT =3D 0x405d, OCTEON_COP2_SEL_HSH_STARTSHA1 =3D 0x4057, OCTEON_COP2_SEL_HSH_STARTSHA512 =3D 0x424f, @@ -730,6 +733,10 @@ typedef struct MIPSOcteonCryptoState { uint32_t snow3g_fsm[3]; uint32_t snow3g_lfsr[16]; uint64_t snow3g_result; + uint32_t zuc_fsm[2]; + uint32_t zuc_lfsr[16]; + uint32_t zuc_window[3]; + uint32_t zuc_tresult; } MIPSOcteonCryptoState; =20 typedef struct CPUArchState { diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c index c646e8b836..1176d879eb 100644 --- a/target/mips/system/machine.c +++ b/target/mips/system/machine.c @@ -302,6 +302,10 @@ static const VMStateDescription mips_vmstate_octeon_cr= ypto =3D { VMSTATE_UINT32_ARRAY(env.octeon_crypto.snow3g_fsm, MIPSCPU, 3), VMSTATE_UINT32_ARRAY(env.octeon_crypto.snow3g_lfsr, MIPSCPU, 16), VMSTATE_UINT64(env.octeon_crypto.snow3g_result, MIPSCPU), + VMSTATE_UINT32_ARRAY(env.octeon_crypto.zuc_fsm, MIPSCPU, 2), + VMSTATE_UINT32_ARRAY(env.octeon_crypto.zuc_lfsr, MIPSCPU, 16), + VMSTATE_UINT32_ARRAY(env.octeon_crypto.zuc_window, MIPSCPU, 3), + VMSTATE_UINT32(env.octeon_crypto.zuc_tresult, MIPSCPU), VMSTATE_END_OF_LIST() } }; diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypt= o.c index d9e66f3dc8..3ee56ef4c0 100644 --- a/target/mips/tcg/octeon_crypto.c +++ b/target/mips/tcg/octeon_crypto.c @@ -631,6 +631,277 @@ static int octeon_sha3_xordat_pos_from_sel(uint32_t s= el) return -1; } =20 +static const uint8_t octeon_zuc_s0[256] =3D { + 0x3e, 0x72, 0x5b, 0x47, 0xca, 0xe0, 0x00, 0x33, + 0x04, 0xd1, 0x54, 0x98, 0x09, 0xb9, 0x6d, 0xcb, + 0x7b, 0x1b, 0xf9, 0x32, 0xaf, 0x9d, 0x6a, 0xa5, + 0xb8, 0x2d, 0xfc, 0x1d, 0x08, 0x53, 0x03, 0x90, + 0x4d, 0x4e, 0x84, 0x99, 0xe4, 0xce, 0xd9, 0x91, + 0xdd, 0xb6, 0x85, 0x48, 0x8b, 0x29, 0x6e, 0xac, + 0xcd, 0xc1, 0xf8, 0x1e, 0x73, 0x43, 0x69, 0xc6, + 0xb5, 0xbd, 0xfd, 0x39, 0x63, 0x20, 0xd4, 0x38, + 0x76, 0x7d, 0xb2, 0xa7, 0xcf, 0xed, 0x57, 0xc5, + 0xf3, 0x2c, 0xbb, 0x14, 0x21, 0x06, 0x55, 0x9b, + 0xe3, 0xef, 0x5e, 0x31, 0x4f, 0x7f, 0x5a, 0xa4, + 0x0d, 0x82, 0x51, 0x49, 0x5f, 0xba, 0x58, 0x1c, + 0x4a, 0x16, 0xd5, 0x17, 0xa8, 0x92, 0x24, 0x1f, + 0x8c, 0xff, 0xd8, 0xae, 0x2e, 0x01, 0xd3, 0xad, + 0x3b, 0x4b, 0xda, 0x46, 0xeb, 0xc9, 0xde, 0x9a, + 0x8f, 0x87, 0xd7, 0x3a, 0x80, 0x6f, 0x2f, 0xc8, + 0xb1, 0xb4, 0x37, 0xf7, 0x0a, 0x22, 0x13, 0x28, + 0x7c, 0xcc, 0x3c, 0x89, 0xc7, 0xc3, 0x96, 0x56, + 0x07, 0xbf, 0x7e, 0xf0, 0x0b, 0x2b, 0x97, 0x52, + 0x35, 0x41, 0x79, 0x61, 0xa6, 0x4c, 0x10, 0xfe, + 0xbc, 0x26, 0x95, 0x88, 0x8a, 0xb0, 0xa3, 0xfb, + 0xc0, 0x18, 0x94, 0xf2, 0xe1, 0xe5, 0xe9, 0x5d, + 0xd0, 0xdc, 0x11, 0x66, 0x64, 0x5c, 0xec, 0x59, + 0x42, 0x75, 0x12, 0xf5, 0x74, 0x9c, 0xaa, 0x23, + 0x0e, 0x86, 0xab, 0xbe, 0x2a, 0x02, 0xe7, 0x67, + 0xe6, 0x44, 0xa2, 0x6c, 0xc2, 0x93, 0x9f, 0xf1, + 0xf6, 0xfa, 0x36, 0xd2, 0x50, 0x68, 0x9e, 0x62, + 0x71, 0x15, 0x3d, 0xd6, 0x40, 0xc4, 0xe2, 0x0f, + 0x8e, 0x83, 0x77, 0x6b, 0x25, 0x05, 0x3f, 0x0c, + 0x30, 0xea, 0x70, 0xb7, 0xa1, 0xe8, 0xa9, 0x65, + 0x8d, 0x27, 0x1a, 0xdb, 0x81, 0xb3, 0xa0, 0xf4, + 0x45, 0x7a, 0x19, 0xdf, 0xee, 0x78, 0x34, 0x60, +}; + +static const uint8_t octeon_zuc_s1[256] =3D { + 0x55, 0xc2, 0x63, 0x71, 0x3b, 0xc8, 0x47, 0x86, + 0x9f, 0x3c, 0xda, 0x5b, 0x29, 0xaa, 0xfd, 0x77, + 0x8c, 0xc5, 0x94, 0x0c, 0xa6, 0x1a, 0x13, 0x00, + 0xe3, 0xa8, 0x16, 0x72, 0x40, 0xf9, 0xf8, 0x42, + 0x44, 0x26, 0x68, 0x96, 0x81, 0xd9, 0x45, 0x3e, + 0x10, 0x76, 0xc6, 0xa7, 0x8b, 0x39, 0x43, 0xe1, + 0x3a, 0xb5, 0x56, 0x2a, 0xc0, 0x6d, 0xb3, 0x05, + 0x22, 0x66, 0xbf, 0xdc, 0x0b, 0xfa, 0x62, 0x48, + 0xdd, 0x20, 0x11, 0x06, 0x36, 0xc9, 0xc1, 0xcf, + 0xf6, 0x27, 0x52, 0xbb, 0x69, 0xf5, 0xd4, 0x87, + 0x7f, 0x84, 0x4c, 0xd2, 0x9c, 0x57, 0xa4, 0xbc, + 0x4f, 0x9a, 0xdf, 0xfe, 0xd6, 0x8d, 0x7a, 0xeb, + 0x2b, 0x53, 0xd8, 0x5c, 0xa1, 0x14, 0x17, 0xfb, + 0x23, 0xd5, 0x7d, 0x30, 0x67, 0x73, 0x08, 0x09, + 0xee, 0xb7, 0x70, 0x3f, 0x61, 0xb2, 0x19, 0x8e, + 0x4e, 0xe5, 0x4b, 0x93, 0x8f, 0x5d, 0xdb, 0xa9, + 0xad, 0xf1, 0xae, 0x2e, 0xcb, 0x0d, 0xfc, 0xf4, + 0x2d, 0x46, 0x6e, 0x1d, 0x97, 0xe8, 0xd1, 0xe9, + 0x4d, 0x37, 0xa5, 0x75, 0x5e, 0x83, 0x9e, 0xab, + 0x82, 0x9d, 0xb9, 0x1c, 0xe0, 0xcd, 0x49, 0x89, + 0x01, 0xb6, 0xbd, 0x58, 0x24, 0xa2, 0x5f, 0x38, + 0x78, 0x99, 0x15, 0x90, 0x50, 0xb8, 0x95, 0xe4, + 0xd0, 0x91, 0xc7, 0xce, 0xed, 0x0f, 0xb4, 0x6f, + 0xa0, 0xcc, 0xf0, 0x02, 0x4a, 0x79, 0xc3, 0xde, + 0xa3, 0xef, 0xea, 0x51, 0xe6, 0x6b, 0x18, 0xec, + 0x1b, 0x2c, 0x80, 0xf7, 0x74, 0xe7, 0xff, 0x21, + 0x5a, 0x6a, 0x54, 0x1e, 0x41, 0x31, 0x92, 0x35, + 0xc4, 0x33, 0x07, 0x0a, 0xba, 0x7e, 0x0e, 0x34, + 0x88, 0xb1, 0x98, 0x7c, 0xf3, 0x3d, 0x60, 0x6c, + 0x7b, 0xca, 0xd3, 0x1f, 0x32, 0x65, 0x04, 0x28, + 0x64, 0xbe, 0x85, 0x9b, 0x2f, 0x59, 0x8a, 0xd7, + 0xb0, 0x25, 0xac, 0xaf, 0x12, 0x03, 0xe2, 0xf2, +}; + +static inline uint32_t octeon_zuc_addm(uint32_t a, uint32_t b) +{ + uint32_t c =3D a + b; + + c =3D (c & 0x7fffffffU) + (c >> 31); + return c ? c : 0x7fffffffU; +} + +static inline uint32_t octeon_zuc_mul_by_pow2(uint32_t v, unsigned int shi= ft) +{ + return ((v << shift) | (v >> (31 - shift))) & 0x7fffffffU; +} + +static inline uint32_t octeon_zuc_make_u32(uint8_t a, uint8_t b, + uint8_t c, uint8_t d) +{ + return ((uint32_t)a << 24) | ((uint32_t)b << 16) | + ((uint32_t)c << 8) | d; +} + +static inline uint64_t octeon_zuc_pack_pair(uint32_t hi, uint32_t lo) +{ + return ((uint64_t)hi << 32) | lo; +} + +static void octeon_zuc_bit_reorganization(const MIPSOcteonCryptoState *cry= pto, + uint32_t x[4]) +{ + x[0] =3D ((crypto->zuc_lfsr[15] & 0x7fff8000U) << 1) | + (crypto->zuc_lfsr[14] & 0xffffU); + x[1] =3D ((crypto->zuc_lfsr[11] & 0xffffU) << 16) | + (crypto->zuc_lfsr[9] >> 15); + x[2] =3D ((crypto->zuc_lfsr[7] & 0xffffU) << 16) | + (crypto->zuc_lfsr[5] >> 15); + x[3] =3D ((crypto->zuc_lfsr[2] & 0xffffU) << 16) | + (crypto->zuc_lfsr[0] >> 15); +} + +static inline uint32_t octeon_zuc_l1(uint32_t x) +{ + return x ^ rol32(x, 2) ^ rol32(x, 10) ^ + rol32(x, 18) ^ rol32(x, 24); +} + +static inline uint32_t octeon_zuc_l2(uint32_t x) +{ + return x ^ rol32(x, 8) ^ rol32(x, 14) ^ + rol32(x, 22) ^ rol32(x, 30); +} + +static uint32_t octeon_zuc_f(MIPSOcteonCryptoState *crypto, const uint32_t= x[4]) +{ + uint32_t w =3D (x[0] ^ crypto->zuc_fsm[0]) + crypto->zuc_fsm[1]; + uint32_t w1 =3D crypto->zuc_fsm[0] + x[1]; + uint32_t w2 =3D crypto->zuc_fsm[1] ^ x[2]; + uint32_t u =3D octeon_zuc_l1((w1 << 16) | (w2 >> 16)); + uint32_t v =3D octeon_zuc_l2((w2 << 16) | (w1 >> 16)); + + crypto->zuc_fsm[0] =3D octeon_zuc_make_u32(octeon_zuc_s0[u >> 24], + octeon_zuc_s1[(uint8_t)(u >> = 16)], + octeon_zuc_s0[(uint8_t)(u >> = 8)], + octeon_zuc_s1[(uint8_t)u]); + crypto->zuc_fsm[1] =3D octeon_zuc_make_u32(octeon_zuc_s0[v >> 24], + octeon_zuc_s1[(uint8_t)(v >> = 16)], + octeon_zuc_s0[(uint8_t)(v >> = 8)], + octeon_zuc_s1[(uint8_t)v]); + return w; +} + +static void octeon_zuc_lfsr_step(MIPSOcteonCryptoState *crypto, + bool init_mode, uint32_t u) +{ + uint32_t f =3D crypto->zuc_lfsr[0]; + + f =3D octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(crypto->zuc_lfsr[0], 8= )); + f =3D octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(crypto->zuc_lfsr[4], 2= 0)); + f =3D octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(crypto->zuc_lfsr[10], = 21)); + f =3D octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(crypto->zuc_lfsr[13], = 17)); + f =3D octeon_zuc_addm(f, octeon_zuc_mul_by_pow2(crypto->zuc_lfsr[15], = 15)); + if (init_mode) { + f =3D octeon_zuc_addm(f, u); + } + + memmove(&crypto->zuc_lfsr[0], &crypto->zuc_lfsr[1], + 15 * sizeof(crypto->zuc_lfsr[0])); + crypto->zuc_lfsr[15] =3D f; +} + +static uint32_t octeon_zuc_generate_word(MIPSOcteonCryptoState *crypto) +{ + uint32_t x[4]; + uint32_t z; + + octeon_zuc_bit_reorganization(crypto, x); + z =3D octeon_zuc_f(crypto, x) ^ x[3]; + octeon_zuc_lfsr_step(crypto, false, 0); + return z; +} + +static void octeon_zuc_fill_window(MIPSOcteonCryptoState *crypto) +{ + crypto->zuc_window[0] =3D octeon_zuc_generate_word(crypto); + crypto->zuc_window[1] =3D octeon_zuc_generate_word(crypto); + crypto->zuc_window[2] =3D octeon_zuc_generate_word(crypto); +} + +static inline uint32_t +octeon_zuc_window_word(const MIPSOcteonCryptoState *crypto, unsigned int b= it) +{ + if (bit =3D=3D 0) { + return crypto->zuc_window[0]; + } + if (bit < 32) { + return (crypto->zuc_window[0] << bit) | + (crypto->zuc_window[1] >> (32 - bit)); + } + if (bit =3D=3D 32) { + return crypto->zuc_window[1]; + } + return (crypto->zuc_window[1] << (bit - 32)) | + (crypto->zuc_window[2] >> (64 - bit)); +} + +static void octeon_zuc_advance_window(MIPSOcteonCryptoState *crypto) +{ + crypto->zuc_window[0] =3D crypto->zuc_window[2]; + crypto->zuc_window[1] =3D octeon_zuc_generate_word(crypto); + crypto->zuc_window[2] =3D octeon_zuc_generate_word(crypto); +} + +static void octeon_zuc_start(MIPSOcteonCryptoState *crypto, uint64_t q) +{ + uint32_t x[4]; + bool restore_active =3D crypto->shared_mode =3D=3D OCTEON_SHARED_MODE_= ZUC; + + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_ZUC); + if (!restore_active) { + for (int i =3D 0; i < 7; i++) { + uint64_t pair =3D crypto->sha512_block[i]; + + crypto->zuc_lfsr[i * 2] =3D (pair >> 32) & 0x7fffffffU; + crypto->zuc_lfsr[i * 2 + 1] =3D pair & 0x7fffffffU; + } + } + crypto->zuc_lfsr[14] =3D (q >> 32) & 0x7fffffffU; + crypto->zuc_lfsr[15] =3D q & 0x7fffffffU; + crypto->zuc_fsm[0] =3D 0; + crypto->zuc_fsm[1] =3D 0; + crypto->zuc_tresult =3D 0; + + for (int i =3D 0; i < 32; i++) { + octeon_zuc_bit_reorganization(crypto, x); + octeon_zuc_lfsr_step(crypto, true, octeon_zuc_f(crypto, x) >> 1); + } + + octeon_zuc_bit_reorganization(crypto, x); + (void)octeon_zuc_f(crypto, x); + octeon_zuc_lfsr_step(crypto, false, 0); + octeon_zuc_fill_window(crypto); +} + +static void octeon_zuc_more(MIPSOcteonCryptoState *crypto, uint64_t q) +{ + uint32_t t =3D crypto->zuc_tresult; + + octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_ZUC); + for (unsigned int bit =3D 0; bit < 64; bit++) { + if ((q >> (63 - bit)) & 1) { + t ^=3D octeon_zuc_window_word(crypto, bit); + } + } + crypto->zuc_tresult =3D t; + octeon_zuc_advance_window(crypto); +} + +static bool octeon_zuc_is_shared_dmfc2_sel(uint32_t sel) +{ + switch (sel) { + case OCTEON_COP2_SEL_HSH_DATW0 ... OCTEON_COP2_SEL_HSH_DATW11: + case OCTEON_COP2_SEL_HSH_IVW0 ... OCTEON_COP2_SEL_HSH_IVW3: + case OCTEON_COP2_SEL_SHA3_DAT15_READ: + case OCTEON_COP2_SEL_SHA3_DAT24: + return true; + default: + return false; + } +} + +static bool octeon_zuc_is_shared_dmtc2_sel(uint32_t sel) +{ + switch (sel) { + case OCTEON_COP2_SEL_HSH_DATW0 ... OCTEON_COP2_SEL_HSH_DATW11: + case OCTEON_COP2_SEL_HSH_IVW0 ... OCTEON_COP2_SEL_HSH_IVW3: + case OCTEON_COP2_SEL_SHA3_DAT15_WRITE: + case OCTEON_COP2_SEL_SHA3_DAT24: + return true; + default: + return false; + } +} + static const uint8_t octeon_snow3g_sr[256] =3D { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, @@ -1527,6 +1798,39 @@ uint64_t helper_octeon_cop2_dmfc2(CPUMIPSState *env,= uint32_t sel) MIPSOcteonCryptoState *crypto =3D &env->octeon_crypto; int sha3_pos; =20 + if (crypto->shared_mode =3D=3D OCTEON_SHARED_MODE_ZUC && + octeon_zuc_is_shared_dmfc2_sel(sel)) { + if (sel >=3D OCTEON_COP2_SEL_HSH_DATW0 && + sel <=3D OCTEON_COP2_SEL_HSH_DATW7) { + unsigned int idx =3D sel - OCTEON_COP2_SEL_HSH_DATW0; + + return octeon_zuc_pack_pair(crypto->zuc_lfsr[idx * 2], + crypto->zuc_lfsr[idx * 2 + 1]); + } + switch (sel) { + case OCTEON_COP2_SEL_HSH_DATW8: + return octeon_zuc_pack_pair(crypto->zuc_fsm[0], crypto->zuc_fs= m[1]); + case OCTEON_COP2_SEL_HSH_DATW9: + case OCTEON_COP2_SEL_HSH_IVW0: + return octeon_zuc_pack_pair(crypto->zuc_window[0], + crypto->zuc_window[1]); + case OCTEON_COP2_SEL_HSH_DATW10: + return crypto->zuc_window[2]; + case OCTEON_COP2_SEL_HSH_DATW11: + case OCTEON_COP2_SEL_HSH_IVW3: + return crypto->zuc_tresult; + case OCTEON_COP2_SEL_SHA3_DAT15_READ: + case OCTEON_COP2_SEL_SHA3_DAT24: + return 0; + case OCTEON_COP2_SEL_HSH_IVW1: + return crypto->zuc_fsm[0]; + case OCTEON_COP2_SEL_HSH_IVW2: + return crypto->zuc_fsm[1]; + default: + g_assert_not_reached(); + } + } + if (crypto->shared_mode =3D=3D OCTEON_SHARED_MODE_SNOW3G) { if (sel >=3D OCTEON_COP2_SEL_SNOW3G_LFSR0 && sel <=3D OCTEON_COP2_SEL_SNOW3G_LFSR7) { @@ -1645,6 +1949,49 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uin= t64_t value, uint64_t q =3D (uint64_t)value; int sha3_pos; =20 + if (crypto->shared_mode =3D=3D OCTEON_SHARED_MODE_ZUC && + octeon_zuc_is_shared_dmtc2_sel(sel)) { + octeon_store_shared_hash_dat(crypto, sel, q); + + if (sel >=3D OCTEON_COP2_SEL_HSH_DATW0 && + sel <=3D OCTEON_COP2_SEL_HSH_DATW7) { + unsigned int idx =3D sel - OCTEON_COP2_SEL_HSH_DATW0; + + crypto->zuc_lfsr[idx * 2] =3D (q >> 32) & 0x7fffffffU; + crypto->zuc_lfsr[idx * 2 + 1] =3D q & 0x7fffffffU; + return; + } + switch (sel) { + case OCTEON_COP2_SEL_HSH_DATW8: + crypto->zuc_fsm[0] =3D q >> 32; + crypto->zuc_fsm[1] =3D q; + return; + case OCTEON_COP2_SEL_HSH_DATW9: + case OCTEON_COP2_SEL_HSH_IVW0: + crypto->zuc_window[0] =3D q >> 32; + crypto->zuc_window[1] =3D q; + return; + case OCTEON_COP2_SEL_HSH_DATW10: + crypto->zuc_window[2] =3D q; + return; + case OCTEON_COP2_SEL_HSH_DATW11: + case OCTEON_COP2_SEL_HSH_IVW3: + crypto->zuc_tresult =3D q; + return; + case OCTEON_COP2_SEL_SHA3_DAT15_WRITE: + case OCTEON_COP2_SEL_SHA3_DAT24: + return; + case OCTEON_COP2_SEL_HSH_IVW1: + crypto->zuc_fsm[0] =3D q; + return; + case OCTEON_COP2_SEL_HSH_IVW2: + crypto->zuc_fsm[1] =3D q; + return; + default: + g_assert_not_reached(); + } + } + switch (sel) { case OCTEON_COP2_SEL_3DES_KEY0: case OCTEON_COP2_SEL_3DES_KEY1: @@ -1859,6 +2206,12 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uin= t64_t value, octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA3); octeon_sha3_permute(crypto); break; + case OCTEON_COP2_SEL_ZUC_START: + octeon_zuc_start(crypto, q); + break; + case OCTEON_COP2_SEL_ZUC_MORE: + octeon_zuc_more(crypto, q); + break; case OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT: octeon_gfm_mul_reflect(crypto, q); break; diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index 3f8c17678a..965dab1b34 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -200,6 +200,8 @@ static bool octeon_cop2_is_supported_dmtc2(uint16_t sel) case OCTEON_COP2_SEL_SNOW3G_MORE: case OCTEON_COP2_SEL_HSH_STARTSHA256: case OCTEON_COP2_SEL_SHA3_STARTOP: + case OCTEON_COP2_SEL_ZUC_START: + case OCTEON_COP2_SEL_ZUC_MORE: case OCTEON_COP2_SEL_HSH_STARTSHA1: case OCTEON_COP2_SEL_GFM_XORMUL1_REFLECT: case OCTEON_COP2_SEL_HSH_STARTSHA512: --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792506; cv=none; d=zohomail.com; s=zohoarc; b=jRY5tVtKQvErMOc/vXVj2O4GqibuPGNUyZYVoDGshKsksYb4iy/4S+cSMb1UgB4YVe0EPfNp6r4Gy6H7WzSH9aN4l0KVgY31x9TGhsBQaXO7VjnBnmM0mZ/NAI2XoxO5AtV6AqeG2u4Lh3oRVd86ioGxxW6bc6jDqFuCLrM7r8o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792506; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=zy1jUHwquGXAF0/9oNRKMTQfF1h+MwqwETxxkbiCZYg=; b=dzWG5kq0d4X8hEGIulAUIV4rJRUBArer83V8t1HUeyIjv31FnkVAWr7QKZnpqdBQvxd5laNutTzjT4m4gC5xuThVmoIIpg8awl9vdMw2ebRJorvQ4gYF4fCH7GJVOBwNLyOmFwezJ6i3hrhsfQ/xA1Rg+paKDXTqSdkI1rzN07c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792506689429.12301017622747; Tue, 21 Apr 2026 10:28:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtQ-00040n-2j; Tue, 21 Apr 2026 13:28:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtC-0003nu-LT for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:28:01 -0400 Received: from mail-oa1-x36.google.com ([2001:4860:4864:20::36]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt7-0006iF-3C for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:58 -0400 Received: by mail-oa1-x36.google.com with SMTP id 586e51a60fabf-41708f6c3feso2904275fac.3 for ; Tue, 21 Apr 2026 10:27:50 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792470; x=1777397270; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=zy1jUHwquGXAF0/9oNRKMTQfF1h+MwqwETxxkbiCZYg=; b=nk9vIxntuQHLoWIZRFJDFb0dAWAq3F1ugXVwQhWqGQHJY5wqvuTb0g6nUBQ/L3KNTT yHs1APINjk++W/fJn2KLLMqZOjTx5DQD8lF+cJKv7Kh9PA9TsbBPQwZCOYLdRq8K1uTz HsRdm/k0C6/jyXeXCUSRz/BGmKr6rHYZOvwvDwG98+shbw79KMjDBZJ7LdwcNYSjrAWv YyceYoRm4DmKWBbSI9k7Gte2Pt9jaOTHuElwoQuRmf2beC0PEb22K+ZG5Y1CBE9GY7pd mzl9qek2Xuqt4/D9BwnDBg9wNlbzJs75hBV6pEozSLv3R7bqIM0slfj4J2cTKBPuEfAD D4Yg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792470; x=1777397270; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=zy1jUHwquGXAF0/9oNRKMTQfF1h+MwqwETxxkbiCZYg=; b=K0d6uckChXTiKk7qD/sWjrTRT+YA9ajpAjq84m6Z1CnCxPRziNxh+1SZQS5qo19e2z nEbgT81LrYpn7Dq3I2Ls2xg/e0hN96M/M7xjfqNTvTLNuTMkDzulERqMQmq4SVJMrrdF 7aNSNPSqoWzHeGNMSMdvWzoie0pUEejtRTUf9BpN2Ynu26kBF0wPckz1cGsa/1rculVr om6gBceLjw+jqUaaw3RnP93t7hgB0cMbNOSpQYVZExcMYvB21lrePhXG9nzpNrkJtvpz Bw7aqD0dYSU9UHJZPtt9IdBmiKci3UgfgljDHJb7mG1yjfanlOgUmtCD8pm8JX4TSEeY kT6g== X-Gm-Message-State: AOJu0YyJ2JMYmqnnjKdRcvM56qrWd2N7jP3TLS+w4HD5agsiaszgQEQS JKMBreNgg7c6sZvYPrQ12bKtJ2zlpEBOWNVXf8sMyHVayJZL9b+xlbs4 X-Gm-Gg: AeBDietntM4SFqxfJa0wQ8QKPoRVGpWGJzhZO5AIBZH0aCwyTX7OYq3PokFWhF1dMHL 7glCCCFORvYhw6RDkCS1YJ6MzJpCayf5PaFUGYZKBc1FcLs/Wc8O2DsuPbhjtAbtDXU6Y9w+3JO 1yDThoPDnVcyI+OVXkEQ9lOmBPJNe9r8lfYvpBpFuRvyy9/5ErmqM391Jo4mNy0HDxLKCDfTtj7 dCqbEjI2yxEeq3WNMWNSxM2sC/FETEJj0CWyTBD+e3aYEwNowLY5FiGtgmKJN1SEj1N3uo7qB3Z Yor0179NHZHfa/qu3DdCdiv6NZT5hyhb0umtRx1Oq023VWPfyLMUQPX0GLNdar4nbGR9+EUZG2f w0f7MGVBSxJxsh3dnnag94cIepi0oKM11T/V360D5cbQVKt9R38S+Lx47fRN9EtIYvge90HXay/ pnmKFWLtEC/Oh8jnaUwiN8BWe4QXvhgBybRq6t+qwdqRvqo1nt39g1N4hCGjqvBrECwzqS2S2PE jfIKdvXgA9Ob+GJedpNtb5lreCvQPYG76tFbE/px97nEywqXiFC0h0qg+eobEIsgz85Ze4i2PHt gwpolm4wjDdC8SQW X-Received: by 2002:a05:6870:9d81:b0:42c:6ea:3227 with SMTP id 586e51a60fabf-42c06ea5b06mr5790272fac.19.1776792469645; Tue, 21 Apr 2026 10:27:49 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:38 -0600 Subject: [PATCH v2 11/13] target/mips: add Octeon Camellia crypto support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-11-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::36; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x36.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792507851158500 Add the Octeon Camellia ROUND, FL, and FLINV selectors and model the round engine that reuses the AES RESULT/RESINP bank. Implement the Camellia F-function and FL layers directly from RFC 3713 so guest-managed key schedules can drive the engine through the hardware interface. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Drop the Octeon prefix from generic Camellia helper routines. (suggested by Philippe Mathieu-Daud=C3=A9) - Add selector dispatch updates in octeon_translate.c after moving COP2 decode out of translate.c. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/cpu.h | 9 +++ target/mips/tcg/octeon_crypto.c | 120 +++++++++++++++++++++++++++++++++= ++++ target/mips/tcg/octeon_translate.c | 3 + 3 files changed, 132 insertions(+) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 437d43636b..8411ef7de4 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -587,6 +587,14 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_AES_DEC0 =3D 0x010e, OCTEON_COP2_SEL_AES_KEYLENGTH =3D 0x0110, OCTEON_COP2_SEL_AES_DAT0 =3D 0x0111, + /* + * Camellia reuses the AES RESULT/RESINP bank and adds per-round and + * diffusion-layer selectors for the guest-managed key schedule. + */ + OCTEON_COP2_SEL_CAMELLIA_RESINP0 =3D OCTEON_COP2_SEL_AES_RESULT0, + OCTEON_COP2_SEL_CAMELLIA_RESINP1 =3D OCTEON_COP2_SEL_AES_RESULT1, + OCTEON_COP2_SEL_CAMELLIA_FL =3D 0x0115, + OCTEON_COP2_SEL_CAMELLIA_FLINV =3D 0x0116, /* * SMS4 reuses the AES result/input, IV, and key banks and only adds * operation selectors for ECB/CBC encrypt/decrypt. @@ -688,6 +696,7 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_AES_ENC1 =3D 0x310b, OCTEON_COP2_SEL_AES_DEC_CBC1 =3D 0x310d, OCTEON_COP2_SEL_AES_DEC1 =3D 0x310f, + OCTEON_COP2_SEL_CAMELLIA_ROUND =3D 0x3114, OCTEON_COP2_SEL_SMS4_ENC_CBC1 =3D 0x3119, OCTEON_COP2_SEL_SMS4_ENC1 =3D 0x311b, OCTEON_COP2_SEL_SMS4_DEC_CBC1 =3D 0x311d, diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypt= o.c index 3ee56ef4c0..9c5f19f41d 100644 --- a/target/mips/tcg/octeon_crypto.c +++ b/target/mips/tcg/octeon_crypto.c @@ -1650,6 +1650,117 @@ static void octeon_aes_store_block(uint64_t regs[2]= , const uint8_t *block) regs[1] =3D ldq_be_p(block + 8); } =20 +static const uint8_t camellia_sbox1[256] =3D { + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, + 174, 65, 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, + 29, 101, 146, 189, 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, + 220, 95, 94, 197, 11, 26, 166, 225, 57, 202, 213, 71, 93, 61, + 217, 1, 90, 214, 81, 86, 108, 77, 139, 13, 154, 102, 251, 204, + 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, 223, 76, 203, 194, + 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, 20, 88, + 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, + 105, 80, 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, + 224, 255, 100, 210, 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, + 230, 218, 9, 63, 221, 148, 135, 92, 131, 2, 205, 74, 144, 51, + 115, 103, 246, 243, 157, 127, 191, 226, 82, 155, 216, 38, 200, 55, + 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, 233, 121, 167, 140, + 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, 120, 152, + 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, + 241, 164, 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, + 119, 199, 128, 158, +}; + +static inline uint8_t camellia_rotl8(uint8_t v, unsigned int shift) +{ + return (v << shift) | (v >> (8 - shift)); +} + +static inline uint8_t camellia_sbox2(uint8_t x) +{ + return camellia_rotl8(camellia_sbox1[x], 1); +} + +static inline uint8_t camellia_sbox3(uint8_t x) +{ + return camellia_rotl8(camellia_sbox1[x], 7); +} + +static inline uint8_t camellia_sbox4(uint8_t x) +{ + return camellia_sbox1[camellia_rotl8(x, 1)]; +} + +static uint64_t camellia_f(uint64_t input, uint64_t key) +{ + uint64_t x =3D input ^ key; + uint8_t t1 =3D camellia_sbox1[x >> 56]; + uint8_t t2 =3D camellia_sbox2((x >> 48) & 0xff); + uint8_t t3 =3D camellia_sbox3((x >> 40) & 0xff); + uint8_t t4 =3D camellia_sbox4((x >> 32) & 0xff); + uint8_t t5 =3D camellia_sbox2((x >> 24) & 0xff); + uint8_t t6 =3D camellia_sbox3((x >> 16) & 0xff); + uint8_t t7 =3D camellia_sbox4((x >> 8) & 0xff); + uint8_t t8 =3D camellia_sbox1[x & 0xff]; + uint8_t y1 =3D t1 ^ t3 ^ t4 ^ t6 ^ t7 ^ t8; + uint8_t y2 =3D t1 ^ t2 ^ t4 ^ t5 ^ t7 ^ t8; + uint8_t y3 =3D t1 ^ t2 ^ t3 ^ t5 ^ t6 ^ t8; + uint8_t y4 =3D t2 ^ t3 ^ t4 ^ t5 ^ t6 ^ t7; + uint8_t y5 =3D t1 ^ t2 ^ t6 ^ t7 ^ t8; + uint8_t y6 =3D t2 ^ t3 ^ t5 ^ t7 ^ t8; + uint8_t y7 =3D t3 ^ t4 ^ t5 ^ t6 ^ t8; + uint8_t y8 =3D t1 ^ t4 ^ t5 ^ t6 ^ t7; + + return ((uint64_t)y1 << 56) | ((uint64_t)y2 << 48) | + ((uint64_t)y3 << 40) | ((uint64_t)y4 << 32) | + ((uint64_t)y5 << 24) | ((uint64_t)y6 << 16) | + ((uint64_t)y7 << 8) | y8; +} + +static uint64_t camellia_fl(uint64_t input, uint64_t key) +{ + uint32_t x1 =3D input >> 32; + uint32_t x2 =3D input; + uint32_t k1 =3D key >> 32; + uint32_t k2 =3D key; + + x2 ^=3D rol32(x1 & k1, 1); + x1 ^=3D x2 | k2; + return ((uint64_t)x1 << 32) | x2; +} + +static uint64_t camellia_flinv(uint64_t input, uint64_t key) +{ + uint32_t y1 =3D input >> 32; + uint32_t y2 =3D input; + uint32_t k1 =3D key >> 32; + uint32_t k2 =3D key; + + y1 ^=3D y2 | k2; + y2 ^=3D rol32(y1 & k1, 1); + return ((uint64_t)y1 << 32) | y2; +} + +static void octeon_camellia_round(MIPSOcteonCryptoState *crypto, uint64_t = key) +{ + uint64_t left =3D crypto->aes_result[0]; + uint64_t right =3D crypto->aes_result[1]; + + crypto->aes_result[0] =3D right ^ camellia_f(left, key); + crypto->aes_result[1] =3D left; +} + +static void octeon_camellia_fl_layer(MIPSOcteonCryptoState *crypto, + uint64_t key, bool inverse) +{ + uint64_t state =3D crypto->aes_result[inverse ? 1 : 0]; + + crypto->aes_result[inverse ? 1 : 0] =3D inverse ? + camellia_flinv(state, key) : + camellia_fl(state, key); +} + static void octeon_sms4_crypt_common(MIPSOcteonCryptoState *crypto, bool encrypt, bool cbc) { @@ -2046,6 +2157,12 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uin= t64_t value, case OCTEON_COP2_SEL_AES_KEYLENGTH: crypto->aes_keylen =3D q; break; + case OCTEON_COP2_SEL_CAMELLIA_FL: + octeon_camellia_fl_layer(crypto, q, false); + break; + case OCTEON_COP2_SEL_CAMELLIA_FLINV: + octeon_camellia_fl_layer(crypto, q, true); + break; case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL: case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL_REFLECT: crypto->crc_poly =3D q; @@ -2231,6 +2348,9 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uint= 64_t value, crypto->aes_input[1] =3D q; octeon_aes_decrypt_common(crypto, false); break; + case OCTEON_COP2_SEL_CAMELLIA_ROUND: + octeon_camellia_round(crypto, q); + break; case OCTEON_COP2_SEL_SMS4_ENC_CBC1: crypto->aes_input[1] =3D q; octeon_sms4_crypt_common(crypto, true, true); diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index 965dab1b34..004b937412 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -115,6 +115,8 @@ static bool octeon_cop2_is_supported_dmtc2(uint16_t sel) case OCTEON_COP2_SEL_AES_DEC_CBC0: case OCTEON_COP2_SEL_AES_DEC0: case OCTEON_COP2_SEL_AES_KEYLENGTH: + case OCTEON_COP2_SEL_CAMELLIA_FL: + case OCTEON_COP2_SEL_CAMELLIA_FLINV: case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL: case OCTEON_COP2_SEL_CRC_IV: case OCTEON_COP2_SEL_CRC_WRITE_LEN: @@ -210,6 +212,7 @@ static bool octeon_cop2_is_supported_dmtc2(uint16_t sel) case OCTEON_COP2_SEL_AES_ENC1: case OCTEON_COP2_SEL_AES_DEC_CBC1: case OCTEON_COP2_SEL_AES_DEC1: + case OCTEON_COP2_SEL_CAMELLIA_ROUND: case OCTEON_COP2_SEL_SMS4_ENC_CBC1: case OCTEON_COP2_SEL_SMS4_ENC1: case OCTEON_COP2_SEL_SMS4_DEC_CBC1: --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792587; cv=none; d=zohomail.com; s=zohoarc; b=a+PEIj8j+HkxUFVdhCaOHY0EsHsfwuox4Tj5pMrbaVuBEkwsEwei5OlJficnx0yypo26xwk6W3FikgXT19CgDGSTyQhwG7IeNo7g99bX5gLGJDE8HfTQVlpHiD+OI0MaELauGolSSYgvSZ6vA7yTLu8RGNSwhHINTXPD1nbWneg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792587; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=DcO28109DGAtSGWJEOODDDT7/DgWjTQwYneNmi0yLWk=; b=LSvYM3oU8ob+eNwAWRyz1DlKhe5crJtLuIolivggsDas5bDOH0bJJ8E9kOaaswTpMlkdX4/oZkeacw6YVa8wTD01LMy7MoE4s9MqoyV063wyvz6xaDUMZ35dphT4RawZZXcIx2F6mEAGK1aXqqjKcIsfM3IaHsgjhvmw5HUJ46Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776792587882818.2230271277839; Tue, 21 Apr 2026 10:29:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtR-000432-Ew; Tue, 21 Apr 2026 13:28:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtB-0003nV-Tv for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:59 -0400 Received: from mail-oa1-x29.google.com ([2001:4860:4864:20::29]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt6-0006iV-HE for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:56 -0400 Received: by mail-oa1-x29.google.com with SMTP id 586e51a60fabf-40427db1300so3548943fac.0 for ; Tue, 21 Apr 2026 10:27:51 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792471; x=1777397271; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=DcO28109DGAtSGWJEOODDDT7/DgWjTQwYneNmi0yLWk=; b=n1tSLFzqpsWtUML8nxKYSH3oiWF1chZdThs3+73xo6JST1yj8ncRVASUm4nXhxRubp RO5VhSbS7jjvgPIGEZFb2GM7uRUozzI3+tDrqTFJxcmJb2epIR5X8RWtE7reVRYEaZJw dFKC1OlY3v7qSfuf8NT7eQOZr4rXVWiTrkB8HL8ySf/ga4TGYQoEmvE0oBbg1Qu8MBT8 sZ373/3oLQgGjJ59CpLC2/wxpZ4LTn/dnbhhuQfZ8H6rzBqBYBtHt6aBJD7O54ZKijUs liHv1/Laollu6Rxre3FslddEWMeoHIrzomz44EM/9cIU8gTPmDJmG0AAMggryWIhhgRm Ijdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792471; x=1777397271; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=DcO28109DGAtSGWJEOODDDT7/DgWjTQwYneNmi0yLWk=; b=YK8J7aO2ZpxFAecXNj1y+0RJP7xmqngyhBuFPrA5hhcca1uBvXENXsDapdmJAasaPG s3k6Jk3+xhAtJfytscU3PNbxsRebQHTW+OlC8RLptz0cqnNOX6tpayLTaJqdrkxpy8G0 MgaC/M/NTLP7hQNRBn7h5M5DzK7IKb/VPL2aD4g29Wddhm97vHB/cRckxsKfp/xQ/Tbf qbYTI0l5g1ahPASr9cnfUcLzhwgDNZ1wcFlGk5Vxekzr2pMHdTMleTuVu1FRjUbkkNwg Rwq57cWR8v0IcJL7VJZbF972NAKQ0GeWd6HdzfKMjO4Aer0YvoZXBdPcunDoMSJOQKBq AEJw== X-Gm-Message-State: AOJu0Yy5uu8h+jocxA6LoS8ODLTeJycxtcHvjDgPlqnrakq2XlfwZjvx 7q6jzbkCCT3Ox1uU4ZXL+VDMLnXUmvn6pha3+lzDVAqj5ilJ0aUUtrUy X-Gm-Gg: AeBDietr/wXLEiKwPR1jrBe6I64oOVHGfbQZjeb50aijUPcwItSxE1fanMz0WS77rvT Y4p9M1Fbf/yW2M9xV9D/Fw0ypcydTdQpEveyv0xTLYP2wXiO2Wl+HOoMluxlqtB4CPfzuWPwXDM XaT3I2UOFADdKsIpV8fu+vvfDfEShM4hvBI6Nh6Vugb7+r2sz6TEaViZsxRPjgaKzCD7xuUUJhZ VgrZNp3aAVwRI8shi/RvRgcfAr/2AVY3t7kb4KfZEXhH+Etd6S4Qp9HrjpsEt09gP4HO+Rg3q+r 9h71U859eapyd9o6u42HWGuQXiXeh7Yz5H+Il6fxTvm1BjKWsNtuLPK/f2tUg4JT3NHuWceDseC 5RO6X5inKIX44nX4pFm15pKpPg3prD2xL/sZ5O4DDVF3AwyW72QvfP5YilDN7aa6g/3mVqJVPfH vA5OCPnNKeBjd/9HOkT+OEPpOZk9m6OQQS7xO2zD+2cZbU+DnPyK/urvCasIGF5KWeTNKhK5WIJ 3l/2MUgvBHMFuunp9R84s79hFtXBP1dhkdHz8zHHC65SfF3zVeP1g6PJIewl147s/eQ0uLzBV8b SzhwQBiHOdfK2iFF X-Received: by 2002:a05:6870:3047:b0:41c:c200:bfe0 with SMTP id 586e51a60fabf-42abf2f8179mr10305104fac.15.1776792470540; Tue, 21 Apr 2026 10:27:50 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:39 -0600 Subject: [PATCH v2 12/13] target/mips: add Octeon CHORD and LLM COP2 support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-12-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2001:4860:4864:20::29; envelope-from=james.hilliard1@gmail.com; helo=mail-oa1-x29.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792589935158500 Add the Octeon CHORD hardware register access path and the LLM narrow/wide read and write windows. Model both CHORD access forms, including the rdhwr $30 path and the legacy dmfc2 alias, and implement sparse backing storage for the two LLM sets so user-mode code can save, restore, and probe the architectural state. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Use neutral selector-slot wording for the LLM/CHORD alias comment. - Add selector dispatch updates in octeon_translate.c after moving COP2 decode out of translate.c. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/cpu.c | 67 +++++++++++++++++++++++++++++++++++ target/mips/cpu.h | 20 +++++++++++ target/mips/helper.h | 1 + target/mips/internal.h | 3 ++ target/mips/system/machine.c | 67 +++++++++++++++++++++++++++++++++++ target/mips/tcg/octeon_crypto.c | 72 ++++++++++++++++++++++++++++++++++= ++++ target/mips/tcg/octeon_translate.c | 13 +++++++ target/mips/tcg/op_helper.c | 6 ++++ target/mips/tcg/translate.c | 8 +++++ 9 files changed, 257 insertions(+) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index ec70c10985..ebcb814360 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -27,6 +27,7 @@ #include "internal.h" #include "kvm_mips.h" #include "qemu/module.h" +#include "qemu/qtree.h" #include "system/kvm.h" #include "system/qtest.h" #include "hw/core/qdev-properties.h" @@ -183,6 +184,57 @@ static bool mips_cpu_has_work(CPUState *cs) =20 #include "cpu-defs.c.inc" =20 +static gint mips_octeon_u64_tree_compare(gconstpointer a, gconstpointer b, + gpointer user_data) +{ + uint64_t av =3D *(const uint64_t *)a; + uint64_t bv =3D *(const uint64_t *)b; + + return (av > bv) - (av < bv); +} + +QTree *mips_octeon_llm_tree_new(void) +{ + return q_tree_new_full(mips_octeon_u64_tree_compare, + NULL, g_free, g_free); +} + +uint64_t mips_octeon_llm_load(QTree *tree, uint64_t addr) +{ + uint64_t key =3D addr; + uint64_t *value =3D tree ? q_tree_lookup(tree, &key) : NULL; + + return value ? *value : 0; +} + +void mips_octeon_llm_store(QTree **treep, uint64_t addr, uint64_t value) +{ + uint64_t *key; + uint64_t *stored; + + if (!*treep) { + *treep =3D mips_octeon_llm_tree_new(); + } + + key =3D g_new(uint64_t, 1); + stored =3D g_new(uint64_t, 1); + *key =3D addr; + *stored =3D value; + q_tree_replace(*treep, key, stored); +} + +static void mips_octeon_destroy_llm_state(MIPSOcteonCryptoState *crypto) +{ + if (crypto->llm_narrow) { + q_tree_destroy(crypto->llm_narrow); + crypto->llm_narrow =3D NULL; + } + if (crypto->llm_wide) { + q_tree_destroy(crypto->llm_wide); + crypto->llm_wide =3D NULL; + } +} + static void mips_cpu_reset_hold(Object *obj, ResetType type) { CPUState *cs =3D CPU(obj); @@ -194,6 +246,7 @@ static void mips_cpu_reset_hold(Object *obj, ResetType = type) mcc->parent_phases.hold(obj, type); } =20 + mips_octeon_destroy_llm_state(&env->octeon_crypto); memset(env, 0, offsetof(CPUMIPSState, end_reset_fields)); =20 /* Reset registers to their default values */ @@ -248,6 +301,9 @@ static void mips_cpu_reset_hold(Object *obj, ResetType = type) env->active_fpu.fcr31 =3D env->cpu_model->CP1_fcr31; env->msair =3D env->cpu_model->MSAIR; env->insn_flags =3D env->cpu_model->insn_flags; + if (env->insn_flags & INSN_OCTEON) { + env->octeon_crypto.chord =3D 1; + } =20 #if defined(CONFIG_USER_ONLY) env->CP0_Status =3D (MIPS_HFLAG_UM << CP0St_KSU); @@ -264,6 +320,9 @@ static void mips_cpu_reset_hold(Object *obj, ResetType = type) * hardware registers. */ env->CP0_HWREna |=3D 0x0000000F; + if (env->insn_flags & INSN_OCTEON) { + env->CP0_HWREna |=3D 0x40000000u; + } if (env->CP0_Config1 & (1 << CP0C1_FP)) { env->CP0_Status |=3D (1 << CP0St_CU1); } @@ -422,6 +481,13 @@ static void mips_cpu_reset_hold(Object *obj, ResetType= type) #endif } =20 +static void mips_cpu_finalize(Object *obj) +{ + MIPSCPU *cpu =3D MIPS_CPU(obj); + + mips_octeon_destroy_llm_state(&cpu->env.octeon_crypto); +} + static void mips_cpu_disas_set_info(const CPUState *cs, disassemble_info *= info) { const MIPSCPU *cpu =3D MIPS_CPU(cs); @@ -636,6 +702,7 @@ static const TypeInfo mips_cpu_type_info =3D { .instance_size =3D sizeof(MIPSCPU), .instance_align =3D __alignof(MIPSCPU), .instance_init =3D mips_cpu_initfn, + .instance_finalize =3D mips_cpu_finalize, .abstract =3D true, .class_size =3D sizeof(MIPSCPUClass), .class_init =3D mips_cpu_class_init, diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 8411ef7de4..e4ccb5e1c7 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -11,6 +11,7 @@ #include "fpu/softfloat-types.h" #include "hw/core/clock.h" #include "mips-defs.h" +#include "qemu/qtree.h" =20 typedef struct CPUMIPSTLBContext CPUMIPSTLBContext; =20 @@ -609,6 +610,21 @@ typedef enum MIPSOcteonCop2Sel { OCTEON_COP2_SEL_SMS4_ENC0 =3D OCTEON_COP2_SEL_AES_ENC0, OCTEON_COP2_SEL_SMS4_DEC_CBC0 =3D OCTEON_COP2_SEL_AES_DEC_CBC0, OCTEON_COP2_SEL_SMS4_DEC0 =3D OCTEON_COP2_SEL_AES_DEC0, + /* + * Selector 0x0400 is the narrow LLM read selector and is also used as= a + * DMFC2 alias for the CHORD POW tag-switch completion bit. + */ + OCTEON_COP2_SEL_LLM_READ_ADDR0 =3D 0x0400, + OCTEON_COP2_SEL_CHORD =3D OCTEON_COP2_SEL_LLM_READ_ADDR0, + OCTEON_COP2_SEL_LLM_WRITE_ADDR_INTERNAL0 =3D 0x0401, + OCTEON_COP2_SEL_LLM_DATA0 =3D 0x0402, + OCTEON_COP2_SEL_LLM_READ64_ADDR0 =3D 0x0404, + OCTEON_COP2_SEL_LLM_WRITE64_ADDR_INTERNAL0 =3D 0x0405, + OCTEON_COP2_SEL_LLM_READ_ADDR1 =3D 0x0408, + OCTEON_COP2_SEL_LLM_WRITE_ADDR_INTERNAL1 =3D 0x0409, + OCTEON_COP2_SEL_LLM_DATA1 =3D 0x040a, + OCTEON_COP2_SEL_LLM_READ64_ADDR1 =3D 0x040c, + OCTEON_COP2_SEL_LLM_WRITE64_ADDR_INTERNAL1 =3D 0x040d, OCTEON_COP2_SEL_CRC_POLYNOMIAL =3D 0x0200, OCTEON_COP2_SEL_CRC_IV =3D 0x0201, OCTEON_COP2_SEL_CRC_LEN =3D 0x0202, @@ -746,6 +762,10 @@ typedef struct MIPSOcteonCryptoState { uint32_t zuc_lfsr[16]; uint32_t zuc_window[3]; uint32_t zuc_tresult; + uint64_t llm_data[2]; + uint64_t chord; + QTree *llm_narrow; + QTree *llm_wide; } MIPSOcteonCryptoState; =20 typedef struct CPUArchState { diff --git a/target/mips/helper.h b/target/mips/helper.h index 899120d0ca..dad91d7451 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -200,6 +200,7 @@ DEF_HELPER_1(rdhwr_cc, tl, env) DEF_HELPER_1(rdhwr_ccres, tl, env) DEF_HELPER_1(rdhwr_performance, tl, env) DEF_HELPER_1(rdhwr_xnp, tl, env) +DEF_HELPER_1(rdhwr_chord, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) =20 diff --git a/target/mips/internal.h b/target/mips/internal.h index 28eb28936b..b40e65864a 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -93,6 +93,9 @@ extern const int mips_defs_number; =20 int mips_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +QTree *mips_octeon_llm_tree_new(void); +uint64_t mips_octeon_llm_load(QTree *tree, uint64_t addr); +void mips_octeon_llm_store(QTree **treep, uint64_t addr, uint64_t value); =20 #define USEG_LIMIT ((target_ulong)(int32_t)0x7FFFFFFFUL) #define KSEG0_BASE ((target_ulong)(int32_t)0x80000000UL) diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c index 1176d879eb..1ec94680af 100644 --- a/target/mips/system/machine.c +++ b/target/mips/system/machine.c @@ -129,6 +129,69 @@ static const VMStateDescription vmstate_octeon_multipl= ier_tc =3D { } }; =20 +typedef struct OcteonLLMTreePutData { + QEMUFile *f; +} OcteonLLMTreePutData; + +static gboolean put_octeon_llm_tree_entry(gpointer key, gpointer value, + gpointer user_data) +{ + OcteonLLMTreePutData *data =3D user_data; + + qemu_put_be64(data->f, *(uint64_t *)key); + qemu_put_be64(data->f, *(uint64_t *)value); + return false; +} + +static int put_octeon_llm_tree(QEMUFile *f, void *pv, size_t size, + const VMStateField *field, JSONWriter *vmde= sc) +{ + QTree *tree =3D *(QTree **)pv; + OcteonLLMTreePutData data =3D { .f =3D f }; + uint32_t nnodes =3D tree ? q_tree_nnodes(tree) : 0; + + qemu_put_be32(f, nnodes); + if (tree) { + q_tree_foreach(tree, put_octeon_llm_tree_entry, &data); + } + + return 0; +} + +static int get_octeon_llm_tree(QEMUFile *f, void *pv, size_t size, + const VMStateField *field) +{ + QTree **treep =3D pv; + uint32_t nnodes =3D qemu_get_be32(f); + + if (*treep) { + q_tree_destroy(*treep); + } + *treep =3D mips_octeon_llm_tree_new(); + + for (uint32_t i =3D 0; i < nnodes; i++) { + uint64_t addr =3D qemu_get_be64(f); + uint64_t value =3D qemu_get_be64(f); + + mips_octeon_llm_store(treep, addr, value); + } + + return 0; +} + +static const VMStateInfo vmstate_info_octeon_llm_tree =3D { + .name =3D "octeon_llm_tree", + .get =3D get_octeon_llm_tree, + .put =3D put_octeon_llm_tree, +}; + +#define VMSTATE_OCTEON_LLM_TREE(_f, _s) { \ + .name =3D stringify(_f), \ + .version_id =3D 1, \ + .info =3D &vmstate_info_octeon_llm_tree, \ + .offset =3D vmstate_offset_pointer(_s, _f, QTree), \ +} + /* MVP state */ =20 static const VMStateDescription vmstate_mvp =3D { @@ -306,6 +369,10 @@ static const VMStateDescription mips_vmstate_octeon_cr= ypto =3D { VMSTATE_UINT32_ARRAY(env.octeon_crypto.zuc_lfsr, MIPSCPU, 16), VMSTATE_UINT32_ARRAY(env.octeon_crypto.zuc_window, MIPSCPU, 3), VMSTATE_UINT32(env.octeon_crypto.zuc_tresult, MIPSCPU), + VMSTATE_UINT64_ARRAY(env.octeon_crypto.llm_data, MIPSCPU, 2), + VMSTATE_UINT64(env.octeon_crypto.chord, MIPSCPU), + VMSTATE_OCTEON_LLM_TREE(env.octeon_crypto.llm_narrow, MIPSCPU), + VMSTATE_OCTEON_LLM_TREE(env.octeon_crypto.llm_wide, MIPSCPU), VMSTATE_END_OF_LIST() } }; diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypt= o.c index 9c5f19f41d..3369993fc9 100644 --- a/target/mips/tcg/octeon_crypto.c +++ b/target/mips/tcg/octeon_crypto.c @@ -16,6 +16,42 @@ #include "qemu/bitops.h" #include "qemu/host-utils.h" =20 +#define OCTEON_LLM_NARROW_MASK ((1ULL << 36) - 1) + +static uint64_t octeon_llm_pack_narrow(uint64_t value) +{ + value &=3D OCTEON_LLM_NARROW_MASK; + return value | ((uint64_t)(ctpop64(value) & 1) << 36); +} + +static void octeon_llm_read(MIPSOcteonCryptoState *crypto, unsigned int se= t, + uint64_t addr, bool wide) +{ + uint64_t value; + + if (wide) { + value =3D mips_octeon_llm_load(crypto->llm_wide, addr); + } else { + value =3D octeon_llm_pack_narrow( + mips_octeon_llm_load(crypto->llm_narrow, addr)); + } + + crypto->llm_data[set] =3D value; +} + +static void octeon_llm_write(MIPSOcteonCryptoState *crypto, unsigned int s= et, + uint64_t addr, bool wide) +{ + uint64_t value =3D crypto->llm_data[set]; + + if (wide) { + mips_octeon_llm_store(&crypto->llm_wide, addr, value); + } else { + mips_octeon_llm_store(&crypto->llm_narrow, addr, + value & OCTEON_LLM_NARROW_MASK); + } +} + static inline void octeon_set_shared_mode(MIPSOcteonCryptoState *crypto, MIPSOcteonSharedMode mode) { @@ -2001,6 +2037,12 @@ uint64_t helper_octeon_cop2_dmfc2(CPUMIPSState *env,= uint32_t sel) return crypto->crc_len; case OCTEON_COP2_SEL_CRC_IV_REFLECT: return octeon_crc_reflect32_by_byte(crypto->crc_iv); + case OCTEON_COP2_SEL_CHORD: + return crypto->chord; + case OCTEON_COP2_SEL_LLM_DATA0: + return crypto->llm_data[0]; + case OCTEON_COP2_SEL_LLM_DATA1: + return crypto->llm_data[1]; case OCTEON_COP2_SEL_HSH_DATW0: case OCTEON_COP2_SEL_HSH_DATW1: case OCTEON_COP2_SEL_HSH_DATW2: @@ -2157,6 +2199,36 @@ void helper_octeon_cop2_dmtc2(CPUMIPSState *env, uin= t64_t value, case OCTEON_COP2_SEL_AES_KEYLENGTH: crypto->aes_keylen =3D q; break; + case OCTEON_COP2_SEL_LLM_READ_ADDR0: + octeon_llm_read(crypto, 0, q, false); + break; + case OCTEON_COP2_SEL_LLM_WRITE_ADDR_INTERNAL0: + octeon_llm_write(crypto, 0, q, false); + break; + case OCTEON_COP2_SEL_LLM_DATA0: + crypto->llm_data[0] =3D q; + break; + case OCTEON_COP2_SEL_LLM_READ64_ADDR0: + octeon_llm_read(crypto, 0, q, true); + break; + case OCTEON_COP2_SEL_LLM_WRITE64_ADDR_INTERNAL0: + octeon_llm_write(crypto, 0, q, true); + break; + case OCTEON_COP2_SEL_LLM_READ_ADDR1: + octeon_llm_read(crypto, 1, q, false); + break; + case OCTEON_COP2_SEL_LLM_WRITE_ADDR_INTERNAL1: + octeon_llm_write(crypto, 1, q, false); + break; + case OCTEON_COP2_SEL_LLM_DATA1: + crypto->llm_data[1] =3D q; + break; + case OCTEON_COP2_SEL_LLM_READ64_ADDR1: + octeon_llm_read(crypto, 1, q, true); + break; + case OCTEON_COP2_SEL_LLM_WRITE64_ADDR_INTERNAL1: + octeon_llm_write(crypto, 1, q, true); + break; case OCTEON_COP2_SEL_CAMELLIA_FL: octeon_camellia_fl_layer(crypto, q, false); break; diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_tr= anslate.c index 004b937412..d9c5d7ab83 100644 --- a/target/mips/tcg/octeon_translate.c +++ b/target/mips/tcg/octeon_translate.c @@ -82,6 +82,9 @@ static bool octeon_cop2_is_supported_dmfc2(uint16_t sel) case OCTEON_COP2_SEL_GFM_RESINP0: case OCTEON_COP2_SEL_GFM_RESINP1: case OCTEON_COP2_SEL_GFM_POLY: + case OCTEON_COP2_SEL_CHORD: + case OCTEON_COP2_SEL_LLM_DATA0: + case OCTEON_COP2_SEL_LLM_DATA1: return true; default: return false; @@ -117,6 +120,16 @@ static bool octeon_cop2_is_supported_dmtc2(uint16_t se= l) case OCTEON_COP2_SEL_AES_KEYLENGTH: case OCTEON_COP2_SEL_CAMELLIA_FL: case OCTEON_COP2_SEL_CAMELLIA_FLINV: + case OCTEON_COP2_SEL_LLM_READ_ADDR0: + case OCTEON_COP2_SEL_LLM_WRITE_ADDR_INTERNAL0: + case OCTEON_COP2_SEL_LLM_DATA0: + case OCTEON_COP2_SEL_LLM_READ64_ADDR0: + case OCTEON_COP2_SEL_LLM_WRITE64_ADDR_INTERNAL0: + case OCTEON_COP2_SEL_LLM_READ_ADDR1: + case OCTEON_COP2_SEL_LLM_WRITE_ADDR_INTERNAL1: + case OCTEON_COP2_SEL_LLM_DATA1: + case OCTEON_COP2_SEL_LLM_READ64_ADDR1: + case OCTEON_COP2_SEL_LLM_WRITE64_ADDR_INTERNAL1: case OCTEON_COP2_SEL_CRC_WRITE_POLYNOMIAL: case OCTEON_COP2_SEL_CRC_IV: case OCTEON_COP2_SEL_CRC_WRITE_LEN: diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c index 47b13a583c..d73ec80af0 100644 --- a/target/mips/tcg/op_helper.c +++ b/target/mips/tcg/op_helper.c @@ -354,6 +354,12 @@ target_ulong helper_rdhwr_xnp(CPUMIPSState *env) return (env->CP0_Config5 >> CP0C5_XNP) & 1; } =20 +target_ulong helper_rdhwr_chord(CPUMIPSState *env) +{ + check_hwrena(env, 30, GETPC()); + return env->octeon_crypto.chord; +} + void helper_pmon(CPUMIPSState *env, int function) { function /=3D 2; diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index ca9cee7ed6..183ae940ff 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -10920,6 +10920,14 @@ void gen_rdhwr(DisasContext *ctx, int rt, int rd, = int sel) } break; #endif + case 30: + if (!(ctx->insn_flags & INSN_OCTEON)) { + gen_reserved_instruction(ctx); + break; + } + gen_helper_rdhwr_chord(t0, tcg_env); + gen_store_gpr(t0, rt); + break; default: /* Invalid */ MIPS_INVAL("rdhwr"); gen_reserved_instruction(ctx); --=20 2.53.0 From nobody Sat May 30 20:11:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776792531; cv=none; d=zohomail.com; s=zohoarc; b=GY+yMISt8N7Xq277YBdc58SMOZEcSy/UFxXV6eVb5HnTwoUmn7RhyuSbSn12D+eGx+r5+B9yrp4H5duVaE2wxnr6YHlPYOrspuPTdvfAL9TcwCjPqUibdxLhH2fWGfd540IlhiwJkXqkFze0KYvfTjMMwF9TaGEWjK9OZtHn9s0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776792531; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+e7gZVu3bd1B1TAOHHGq3QFvnnISVO6cYOLHr5lct+Q=; b=MXjXeZkEoQRURaWxt0ska7WhUoa4VE7td87KbCrl6Hkx73X5lYyRaa/kJljupbB+ZDkfjaaREG3yDDFYPm9mPdY/TjpvjfZS7uRr8QoW5yi5Ah03eUQasoiKitVeKl6xBnDVhDP8KRb7NOAv5/mLPLTYz8a6xfBXzT3AkTIk2rY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17767925314586.708226500271508; Tue, 21 Apr 2026 10:28:51 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wFEtN-0003uW-8m; Tue, 21 Apr 2026 13:28:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wFEtC-0003nd-0u for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:28:01 -0400 Received: from mail-oi1-x230.google.com ([2607:f8b0:4864:20::230]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wFEt7-0006il-3W for qemu-devel@nongnu.org; Tue, 21 Apr 2026 13:27:57 -0400 Received: by mail-oi1-x230.google.com with SMTP id 5614622812f47-45f053b7b90so2575349b6e.0 for ; Tue, 21 Apr 2026 10:27:52 -0700 (PDT) Received: from mac.localdomain (97-118-149-104.hlrn.qwest.net. [97.118.149.104]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-42b8fe2c52bsm12209290fac.0.2026.04.21.10.27.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 10:27:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776792471; x=1777397271; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=+e7gZVu3bd1B1TAOHHGq3QFvnnISVO6cYOLHr5lct+Q=; b=rRB1NNKX7y4SWJopLWqEdefBDzfKR+biOyj3j/GAHEF3ygsjwgsJx25t7ijFqDI5u4 FlhMFQ/1lqtAZXmSCrhws8Ul5yfy3Bs3Q4J5siTq+xNd3rXFOZSHTx6HLm+tSGi5tbet uYTu/qyFB5TJqXmNlVZ31pkBR2q6qHkXy1FJu7JIVsH8U5x3VL3QISevCUvJTxFpPdB+ fTpiL/n/JhxyzvLqTUeOam2fu1SJlWnWA1MgEzqR921rRLcqYcaS+BPHNaEmE3SBGBen gcbOsWCO7Oup/+eVGCNfK6p1/FiGGX0I7Zyj9RrrJYqN5wKR+BhTSBw0X89zlzr9gTqr pPug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776792471; x=1777397271; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=+e7gZVu3bd1B1TAOHHGq3QFvnnISVO6cYOLHr5lct+Q=; b=CNgmlBjYcSgwAsXYqxX+rsDT6cmBF0kZi1zENAhYTLn1uzHW69WEYLJy3XbWVeBwNx frLwa0FGdCnu8tX1N6rFnqlTmANQwcez1C6JFzmibKA8Tt+kNXBbXjlZKO+O8lMpgtGy kRyoYHmqIG5VLiZGoW+X3Qo8jGiILo1K54IS7isKFg30P3pwJ9MkjIURyV3vQNPx83gl q3xWLlPkvUWQMS/1o4el0FvMW/By96Lg6wO4ChHiUyi1FTvrF+aOHBKW9ENl4E5ZqwZX JmtDGDVw0F54ziWb0liSg9Fr3gadwkJyuMAmaU7VqrOakRPDcQ1RQX4KI5wXevwMFq6G 8h1Q== X-Gm-Message-State: AOJu0YzK/bsFlQ82vAVzfJ8GGWdswtO52J/Us0XfVawYntY/OfJZohPB IEafWn1KN1g2X2C/CN857yJnhGb5bFh/hh31NvGU6fJHW9abD6IW7kf1 X-Gm-Gg: AeBDies3O9Gmi2cc3GaqegW4agVMN9TdinynyOxnk7iBGKWhAYo+F1tq4dhfxKMcstQ 15xxJL8LLHS20VSyNF6pFzmi/DXAAB8I0x4YS4DmB1iwVQPvEQBaX5iZyrp67w68J8Y82kQoR1X vcY9IYIvuA5HAR5sTDK+bEH2E63AR1wVK7hXpQgfN0jtX/qPh0m8IrfuAViL9DZJUj709ss+B4N l6xaNHHvHOqDaWyFR/VL78xjlqZcDzp51PLC5tFwlNEGYkHRuhj4S1YCDAzAalw9AcGjvVhLXJ2 AGGSFzzc8MzVRRdLfBt5Yf85iIAZSa3LqzKoFBbKitLjn806shz1yrCXR9QQFAOcs58VRa2zgeg Oy8Vpoibw+FlgH5XmGKcWrE2o3E8usqOSuEmG9PN7u6uEJHqDv0Cc1Pb2O+JQkko4oG0To5Xfbh uHuZhTP6azU6sFmoiqO6qatLq3ptbjsrGeKuVMN1+snntdi6ysglv26x3GQVVF4lpC+O14hgc3i OGA2JLDkZZLEJggwvbE5j/TQC3wRWLNxvXaM8UWSeR8OqzbeZy7sMVhKpwDJ0eNsSkjQsO9l6KZ 3bOBrw33nu9TQbS5 X-Received: by 2002:a05:6808:1441:b0:474:28c1:4877 with SMTP id 5614622812f47-4799cae8b90mr10299646b6e.39.1776792471480; Tue, 21 Apr 2026 10:27:51 -0700 (PDT) From: James Hilliard Date: Tue, 21 Apr 2026 11:27:40 -0600 Subject: [PATCH v2 13/13] target/mips: expose Octeon68XX floating-point support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260421-mips-octeon-missing-insns-v2-v2-13-a0791df188c9@gmail.com> References: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> In-Reply-To: <20260421-mips-octeon-missing-insns-v2-v2-0-a0791df188c9@gmail.com> To: qemu-devel@nongnu.org Cc: Laurent Vivier , Pierrick Bouvier , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , Huacai Chen , James Hilliard X-Mailer: b4 0.15.2 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::230; envelope-from=james.hilliard1@gmail.com; helo=mail-oi1-x230.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776792533742158500 Octeon68XX cores implement CP1. Advertise that in the CPU definition by setting Config1.FP, enabling the writable Status bits, and providing the FCR0/FCR31 defaults used by this CPU model. This lets guests observe the expected floating-point feature bits and use CP1 with -cpu Octeon68XX. Signed-off-by: James Hilliard --- Changes v1 -> v2: - Move this CPU-model correction into a separate final patch. (suggested by Philippe Mathieu-Daud=C3=A9) --- target/mips/cpu-defs.c.inc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc index d93b9d341a..6c084fcaea 100644 --- a/target/mips/cpu-defs.c.inc +++ b/target/mips/cpu-defs.c.inc @@ -997,7 +997,8 @@ const mips_def_t mips_defs[] =3D .CP0_PRid =3D 0x000D9100, .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_= AT) | (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 =3D MIPS_CONFIG1 | (0x3F << CP0C1_MMU) | + .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | + (0x3F << CP0C1_MMU) | (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA)= | (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA)= | (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), @@ -1011,7 +1012,12 @@ const mips_def_t mips_defs[] =3D .CP0_PageGrain =3D (1 << CP0PG_ELPA), .SYNCI_Step =3D 32, .CCRes =3D 2, - .CP0_Status_rw_bitmask =3D 0x12F8FFFF, + .CP0_Status_rw_bitmask =3D 0x36F8FFFF, + .CP1_fcr0 =3D (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) | + (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | + (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV= ), + .CP1_fcr31 =3D 0, + .CP1_fcr31_rw_bitmask =3D 0xFF83FFFF, .SEGBITS =3D 42, .PABITS =3D 49, .insn_flags =3D CPU_MIPS64R2 | INSN_OCTEON, --=20 2.53.0