From nobody Tue Feb 10 09:59:30 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.44 as permitted sender) client-ip=209.85.128.44; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f44.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.44 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com; dmarc=fail(p=none dis=none) header.from=amsat.org ARC-Seal: i=1; a=rsa-sha256; t=1619972304; cv=none; d=zohomail.com; s=zohoarc; b=VLHMKo+gDbmLZeGQrngVJpY/G1Tyvrf0ci6Md/CeTc/R2O7hKdUjlj6aLUA7eQJz7GWt+UfYEMer6vnR0QlVrsW1ZaZPIZTUaGH0z9ZCk8qJlz5VoTyWu3t6BsPkqZ/nFa8Fd89gEqhMVCC/DWpv1s1PnLh2ZWJjHk7r5HnXtvc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1619972304; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=fOCW3qxGbXTdprDd4pm0/slzthSBWtj0LaXQ5LQYGS4=; b=Cc3/XkSDsVWvAZJB29KM337k6bx9G2IhPaGj04XqAad5loHw0b2+tx4xQ8qHn3qwd9emO8fsf2FWXPFREQYETluHUEZYSh+Z/vendM3X8WWrWL3qDlHAAS05+vM0UjVUe7bV1W9+UVhepLYIhAMh0gQXGz+h0y9oRyPrCfEPU2c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.44 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) by mx.zohomail.com with SMTPS id 16199723049201021.3207461048405; Sun, 2 May 2021 09:18:24 -0700 (PDT) Received: by mail-wm1-f44.google.com with SMTP id g65so1924215wmg.2 for ; Sun, 02 May 2021 09:18:24 -0700 (PDT) Return-Path: Return-Path: Received: from localhost.localdomain (anancy-651-1-208-144.w109-217.abo.wanadoo.fr. [109.217.237.144]) by smtp.gmail.com with ESMTPSA id v18sm10905506wro.18.2021.05.02.09.18.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 May 2021 09:18:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fOCW3qxGbXTdprDd4pm0/slzthSBWtj0LaXQ5LQYGS4=; b=DaOHrrsXajWQftZOLnUKkkoUl6Uteq/7Yy0Tr+UXc0xV6zwbe2xljdJMSPXnJZDN9N +Xpzfowz/7EJ0fu8Iq3m/1MRtKWRj9TqIR63QHqomk1RRKRrsVQivcH+5H9tvRLipz4p VZ0O6dqkURHkqbY/5w+76Wl0dALASpiS4tAvMGgXrb16vCA0kLOl3KJqH746jQOHq6V9 UfBdCGH9HMyfCLHw1dNnXK2A+3rMp1ndNfTASJhxOktQ6I+32zbPspuZgvS1563qHR61 OxQw5grkInjkznVUp0nIlR9q+CjcSkT7mhwiR0UVI8Yxh81/rmrXQLrdp07CEF+XYpS9 iWvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=fOCW3qxGbXTdprDd4pm0/slzthSBWtj0LaXQ5LQYGS4=; b=DlWRDizAhSfV8WzvvZ9WhMP1ddTDnLP6SULSWJCRpTqoYFv6bN0ll0hy7hFU5pFaSm hUPfE5Afbvg/R0A2SLkyxxSd8hUk1d1FjrHa5NHTTdAnVIXqfNA6gob157+CY43m8Xyc 1iaD5joUNU8xFUImck2uV303jzNyEzSDJQ5rm7WqdhodaEiuLixyKe42kOYkMVPCXUzW BxglyjSxx83YmYHxYJ/kfhTapN/P7/2VHqzNGmh8mr1K7nZelreb1f3lgOhxICvJpgzC WD/4py6pfv//CXTe/heMB6mc1TZYnsA9147ssgeFnFHp392BbRmMX9004RclkbDfh0nM UMPg== X-Gm-Message-State: AOAM533B2BGABQnWPDfGb6auzmBrgKCC/LJAPaKrN70Bkz5U39967S1M k3ccXYbsxg+1wIAofqibn7c= X-Google-Smtp-Source: ABdhPJx+ma4EcM5KZQrOrOg+YKKtymjua/DB9dEjFADsAzN7xNbTLmj72UBHVyWeAdE2DBUacfedrA== X-Received: by 2002:a05:600c:3581:: with SMTP id p1mr26997623wmq.35.1619972302958; Sun, 02 May 2021 09:18:22 -0700 (PDT) Sender: =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: Jiaxun Yang , Aurelien Jarno , Aleksandar Rikalo , Huacai Chen , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson Subject: [PULL 31/36] target/mips: Move TLB management helpers to tcg/sysemu/tlb_helper.c Date: Sun, 2 May 2021 18:15:33 +0200 Message-Id: <20210502161538.534038-32-f4bug@amsat.org> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210502161538.534038-1-f4bug@amsat.org> References: <20210502161538.534038-1-f4bug@amsat.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) Move TLB management helpers to tcg/sysemu/tlb_helper.c. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210428170410.479308-26-f4bug@amsat.org> --- target/mips/helper.h | 10 - target/mips/internal.h | 7 - target/mips/tcg/sysemu_helper.h.inc | 9 + target/mips/op_helper.c | 333 ---------------------------- target/mips/tcg/sysemu/tlb_helper.c | 331 +++++++++++++++++++++++++++ 5 files changed, 340 insertions(+), 350 deletions(-) diff --git a/target/mips/helper.h b/target/mips/helper.h index d49620f9282..ba301ae160d 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -202,16 +202,6 @@ FOP_PROTO(sune) FOP_PROTO(sne) #undef FOP_PROTO =20 -/* Special functions */ -#ifndef CONFIG_USER_ONLY -DEF_HELPER_1(tlbwi, void, env) -DEF_HELPER_1(tlbwr, void, env) -DEF_HELPER_1(tlbp, void, env) -DEF_HELPER_1(tlbr, void, env) -DEF_HELPER_1(tlbinv, void, env) -DEF_HELPER_1(tlbinvf, void, env) -DEF_HELPER_3(ginvt, void, env, tl, i32) -#endif /* !CONFIG_USER_ONLY */ DEF_HELPER_1(rdhwr_cpunum, tl, env) DEF_HELPER_1(rdhwr_synci_step, tl, env) DEF_HELPER_1(rdhwr_cc, tl, env) diff --git a/target/mips/internal.h b/target/mips/internal.h index c1751700731..a1c7f658c2b 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -152,13 +152,6 @@ struct CPUMIPSTLBContext { } mmu; }; =20 -void r4k_helper_tlbwi(CPUMIPSState *env); -void r4k_helper_tlbwr(CPUMIPSState *env); -void r4k_helper_tlbp(CPUMIPSState *env); -void r4k_helper_tlbr(CPUMIPSState *env); -void r4k_helper_tlbinv(CPUMIPSState *env); -void r4k_helper_tlbinvf(CPUMIPSState *env); - void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, unsigned size, MMUAccessType access_type, diff --git a/target/mips/tcg/sysemu_helper.h.inc b/target/mips/tcg/sysemu_h= elper.h.inc index 1ccbf687237..4353a966f97 100644 --- a/target/mips/tcg/sysemu_helper.h.inc +++ b/target/mips/tcg/sysemu_helper.h.inc @@ -167,6 +167,15 @@ DEF_HELPER_1(evpe, tl, env) DEF_HELPER_1(dvp, tl, env) DEF_HELPER_1(evp, tl, env) =20 +/* TLB */ +DEF_HELPER_1(tlbwi, void, env) +DEF_HELPER_1(tlbwr, void, env) +DEF_HELPER_1(tlbp, void, env) +DEF_HELPER_1(tlbr, void, env) +DEF_HELPER_1(tlbinv, void, env) +DEF_HELPER_1(tlbinvf, void, env) +DEF_HELPER_3(ginvt, void, env, tl, i32) + /* Special */ DEF_HELPER_1(di, tl, env) DEF_HELPER_1(ei, tl, env) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index a7fe1de8c42..cb2a7e96fc3 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -324,339 +324,6 @@ target_ulong helper_yield(CPUMIPSState *env, target_u= long arg) return env->CP0_YQMask; } =20 -#ifndef CONFIG_USER_ONLY -/* TLB management */ -static void r4k_mips_tlb_flush_extra(CPUMIPSState *env, int first) -{ - /* Discard entries from env->tlb[first] onwards. */ - while (env->tlb->tlb_in_use > first) { - r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0); - } -} - -static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo) -{ -#if defined(TARGET_MIPS64) - return extract64(entrylo, 6, 54); -#else - return extract64(entrylo, 6, 24) | /* PFN */ - (extract64(entrylo, 32, 32) << 24); /* PFNX */ -#endif -} - -static void r4k_fill_tlb(CPUMIPSState *env, int idx) -{ - r4k_tlb_t *tlb; - uint64_t mask =3D env->CP0_PageMask >> (TARGET_PAGE_BITS + 1); - - /* XXX: detect conflicting TLBs and raise a MCHECK exception when need= ed */ - tlb =3D &env->tlb->mmu.r4k.tlb[idx]; - if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) { - tlb->EHINV =3D 1; - return; - } - tlb->EHINV =3D 0; - tlb->VPN =3D env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); -#if defined(TARGET_MIPS64) - tlb->VPN &=3D env->SEGMask; -#endif - tlb->ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; - tlb->MMID =3D env->CP0_MemoryMapID; - tlb->PageMask =3D env->CP0_PageMask; - tlb->G =3D env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; - tlb->V0 =3D (env->CP0_EntryLo0 & 2) !=3D 0; - tlb->D0 =3D (env->CP0_EntryLo0 & 4) !=3D 0; - tlb->C0 =3D (env->CP0_EntryLo0 >> 3) & 0x7; - tlb->XI0 =3D (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; - tlb->RI0 =3D (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; - tlb->PFN[0] =3D (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) = << 12; - tlb->V1 =3D (env->CP0_EntryLo1 & 2) !=3D 0; - tlb->D1 =3D (env->CP0_EntryLo1 & 4) !=3D 0; - tlb->C1 =3D (env->CP0_EntryLo1 >> 3) & 0x7; - tlb->XI1 =3D (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; - tlb->RI1 =3D (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; - tlb->PFN[1] =3D (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) = << 12; -} - -void r4k_helper_tlbinv(CPUMIPSState *env) -{ - bool mi =3D !!((env->CP0_Config5 >> CP0C5_MI) & 1); - uint16_t ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; - uint32_t MMID =3D env->CP0_MemoryMapID; - uint32_t tlb_mmid; - r4k_tlb_t *tlb; - int idx; - - MMID =3D mi ? MMID : (uint32_t) ASID; - for (idx =3D 0; idx < env->tlb->nb_tlb; idx++) { - tlb =3D &env->tlb->mmu.r4k.tlb[idx]; - tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; - if (!tlb->G && tlb_mmid =3D=3D MMID) { - tlb->EHINV =3D 1; - } - } - cpu_mips_tlb_flush(env); -} - -void r4k_helper_tlbinvf(CPUMIPSState *env) -{ - int idx; - - for (idx =3D 0; idx < env->tlb->nb_tlb; idx++) { - env->tlb->mmu.r4k.tlb[idx].EHINV =3D 1; - } - cpu_mips_tlb_flush(env); -} - -void r4k_helper_tlbwi(CPUMIPSState *env) -{ - bool mi =3D !!((env->CP0_Config5 >> CP0C5_MI) & 1); - target_ulong VPN; - uint16_t ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; - uint32_t MMID =3D env->CP0_MemoryMapID; - uint32_t tlb_mmid; - bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1; - r4k_tlb_t *tlb; - int idx; - - MMID =3D mi ? MMID : (uint32_t) ASID; - - idx =3D (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; - tlb =3D &env->tlb->mmu.r4k.tlb[idx]; - VPN =3D env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); -#if defined(TARGET_MIPS64) - VPN &=3D env->SEGMask; -#endif - EHINV =3D (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) !=3D 0; - G =3D env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; - V0 =3D (env->CP0_EntryLo0 & 2) !=3D 0; - D0 =3D (env->CP0_EntryLo0 & 4) !=3D 0; - XI0 =3D (env->CP0_EntryLo0 >> CP0EnLo_XI) &1; - RI0 =3D (env->CP0_EntryLo0 >> CP0EnLo_RI) &1; - V1 =3D (env->CP0_EntryLo1 & 2) !=3D 0; - D1 =3D (env->CP0_EntryLo1 & 4) !=3D 0; - XI1 =3D (env->CP0_EntryLo1 >> CP0EnLo_XI) &1; - RI1 =3D (env->CP0_EntryLo1 >> CP0EnLo_RI) &1; - - tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; - /* - * Discard cached TLB entries, unless tlbwi is just upgrading access - * permissions on the current entry. - */ - if (tlb->VPN !=3D VPN || tlb_mmid !=3D MMID || tlb->G !=3D G || - (!tlb->EHINV && EHINV) || - (tlb->V0 && !V0) || (tlb->D0 && !D0) || - (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) || - (tlb->V1 && !V1) || (tlb->D1 && !D1) || - (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) { - r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); - } - - r4k_invalidate_tlb(env, idx, 0); - r4k_fill_tlb(env, idx); -} - -void r4k_helper_tlbwr(CPUMIPSState *env) -{ - int r =3D cpu_mips_get_random(env); - - r4k_invalidate_tlb(env, r, 1); - r4k_fill_tlb(env, r); -} - -void r4k_helper_tlbp(CPUMIPSState *env) -{ - bool mi =3D !!((env->CP0_Config5 >> CP0C5_MI) & 1); - r4k_tlb_t *tlb; - target_ulong mask; - target_ulong tag; - target_ulong VPN; - uint16_t ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; - uint32_t MMID =3D env->CP0_MemoryMapID; - uint32_t tlb_mmid; - int i; - - MMID =3D mi ? MMID : (uint32_t) ASID; - for (i =3D 0; i < env->tlb->nb_tlb; i++) { - tlb =3D &env->tlb->mmu.r4k.tlb[i]; - /* 1k pages are not supported. */ - mask =3D tlb->PageMask | ~(TARGET_PAGE_MASK << 1); - tag =3D env->CP0_EntryHi & ~mask; - VPN =3D tlb->VPN & ~mask; -#if defined(TARGET_MIPS64) - tag &=3D env->SEGMask; -#endif - tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; - /* Check ASID/MMID, virtual page number & size */ - if ((tlb->G =3D=3D 1 || tlb_mmid =3D=3D MMID) && VPN =3D=3D tag &&= !tlb->EHINV) { - /* TLB match */ - env->CP0_Index =3D i; - break; - } - } - if (i =3D=3D env->tlb->nb_tlb) { - /* No match. Discard any shadow entries, if any of them match. */ - for (i =3D env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) { - tlb =3D &env->tlb->mmu.r4k.tlb[i]; - /* 1k pages are not supported. */ - mask =3D tlb->PageMask | ~(TARGET_PAGE_MASK << 1); - tag =3D env->CP0_EntryHi & ~mask; - VPN =3D tlb->VPN & ~mask; -#if defined(TARGET_MIPS64) - tag &=3D env->SEGMask; -#endif - tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; - /* Check ASID/MMID, virtual page number & size */ - if ((tlb->G =3D=3D 1 || tlb_mmid =3D=3D MMID) && VPN =3D=3D ta= g) { - r4k_mips_tlb_flush_extra(env, i); - break; - } - } - - env->CP0_Index |=3D 0x80000000; - } -} - -static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn) -{ -#if defined(TARGET_MIPS64) - return tlb_pfn << 6; -#else - return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */ - (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */ -#endif -} - -void r4k_helper_tlbr(CPUMIPSState *env) -{ - bool mi =3D !!((env->CP0_Config5 >> CP0C5_MI) & 1); - uint16_t ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; - uint32_t MMID =3D env->CP0_MemoryMapID; - uint32_t tlb_mmid; - r4k_tlb_t *tlb; - int idx; - - MMID =3D mi ? MMID : (uint32_t) ASID; - idx =3D (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; - tlb =3D &env->tlb->mmu.r4k.tlb[idx]; - - tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; - /* If this will change the current ASID/MMID, flush qemu's TLB. */ - if (MMID !=3D tlb_mmid) { - cpu_mips_tlb_flush(env); - } - - r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); - - if (tlb->EHINV) { - env->CP0_EntryHi =3D 1 << CP0EnHi_EHINV; - env->CP0_PageMask =3D 0; - env->CP0_EntryLo0 =3D 0; - env->CP0_EntryLo1 =3D 0; - } else { - env->CP0_EntryHi =3D mi ? tlb->VPN : tlb->VPN | tlb->ASID; - env->CP0_MemoryMapID =3D tlb->MMID; - env->CP0_PageMask =3D tlb->PageMask; - env->CP0_EntryLo0 =3D tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | - ((uint64_t)tlb->RI0 << CP0EnLo_RI) | - ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3= ) | - get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12); - env->CP0_EntryLo1 =3D tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | - ((uint64_t)tlb->RI1 << CP0EnLo_RI) | - ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3= ) | - get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12); - } -} - -void helper_tlbwi(CPUMIPSState *env) -{ - env->tlb->helper_tlbwi(env); -} - -void helper_tlbwr(CPUMIPSState *env) -{ - env->tlb->helper_tlbwr(env); -} - -void helper_tlbp(CPUMIPSState *env) -{ - env->tlb->helper_tlbp(env); -} - -void helper_tlbr(CPUMIPSState *env) -{ - env->tlb->helper_tlbr(env); -} - -void helper_tlbinv(CPUMIPSState *env) -{ - env->tlb->helper_tlbinv(env); -} - -void helper_tlbinvf(CPUMIPSState *env) -{ - env->tlb->helper_tlbinvf(env); -} - -static void global_invalidate_tlb(CPUMIPSState *env, - uint32_t invMsgVPN2, - uint8_t invMsgR, - uint32_t invMsgMMid, - bool invAll, - bool invVAMMid, - bool invMMid, - bool invVA) -{ - - int idx; - r4k_tlb_t *tlb; - bool VAMatch; - bool MMidMatch; - - for (idx =3D 0; idx < env->tlb->nb_tlb; idx++) { - tlb =3D &env->tlb->mmu.r4k.tlb[idx]; - VAMatch =3D - (((tlb->VPN & ~tlb->PageMask) =3D=3D (invMsgVPN2 & ~tlb->PageM= ask)) -#ifdef TARGET_MIPS64 - && - (extract64(env->CP0_EntryHi, 62, 2) =3D=3D invMsgR) -#endif - ); - MMidMatch =3D tlb->MMID =3D=3D invMsgMMid; - if ((invAll && (idx > env->CP0_Wired)) || - (VAMatch && invVAMMid && (tlb->G || MMidMatch)) || - (VAMatch && invVA) || - (MMidMatch && !(tlb->G) && invMMid)) { - tlb->EHINV =3D 1; - } - } - cpu_mips_tlb_flush(env); -} - -void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type) -{ - bool invAll =3D type =3D=3D 0; - bool invVA =3D type =3D=3D 1; - bool invMMid =3D type =3D=3D 2; - bool invVAMMid =3D type =3D=3D 3; - uint32_t invMsgVPN2 =3D arg & (TARGET_PAGE_MASK << 1); - uint8_t invMsgR =3D 0; - uint32_t invMsgMMid =3D env->CP0_MemoryMapID; - CPUState *other_cs =3D first_cpu; - -#ifdef TARGET_MIPS64 - invMsgR =3D extract64(arg, 62, 2); -#endif - - CPU_FOREACH(other_cs) { - MIPSCPU *other_cpu =3D MIPS_CPU(other_cs); - global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsg= MMid, - invAll, invVAMMid, invMMid, invVA); - } -} - -#endif /* !CONFIG_USER_ONLY */ - static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) { diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/t= lb_helper.c index a45146a2b21..259f780d19f 100644 --- a/target/mips/tcg/sysemu/tlb_helper.c +++ b/target/mips/tcg/sysemu/tlb_helper.c @@ -24,6 +24,337 @@ #include "exec/cpu_ldst.h" #include "exec/log.h" #include "hw/mips/cpudevs.h" +#include "exec/helper-proto.h" + +/* TLB management */ +static void r4k_mips_tlb_flush_extra(CPUMIPSState *env, int first) +{ + /* Discard entries from env->tlb[first] onwards. */ + while (env->tlb->tlb_in_use > first) { + r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0); + } +} + +static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo) +{ +#if defined(TARGET_MIPS64) + return extract64(entrylo, 6, 54); +#else + return extract64(entrylo, 6, 24) | /* PFN */ + (extract64(entrylo, 32, 32) << 24); /* PFNX */ +#endif +} + +static void r4k_fill_tlb(CPUMIPSState *env, int idx) +{ + r4k_tlb_t *tlb; + uint64_t mask =3D env->CP0_PageMask >> (TARGET_PAGE_BITS + 1); + + /* XXX: detect conflicting TLBs and raise a MCHECK exception when need= ed */ + tlb =3D &env->tlb->mmu.r4k.tlb[idx]; + if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) { + tlb->EHINV =3D 1; + return; + } + tlb->EHINV =3D 0; + tlb->VPN =3D env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); +#if defined(TARGET_MIPS64) + tlb->VPN &=3D env->SEGMask; +#endif + tlb->ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; + tlb->MMID =3D env->CP0_MemoryMapID; + tlb->PageMask =3D env->CP0_PageMask; + tlb->G =3D env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; + tlb->V0 =3D (env->CP0_EntryLo0 & 2) !=3D 0; + tlb->D0 =3D (env->CP0_EntryLo0 & 4) !=3D 0; + tlb->C0 =3D (env->CP0_EntryLo0 >> 3) & 0x7; + tlb->XI0 =3D (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; + tlb->RI0 =3D (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; + tlb->PFN[0] =3D (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) = << 12; + tlb->V1 =3D (env->CP0_EntryLo1 & 2) !=3D 0; + tlb->D1 =3D (env->CP0_EntryLo1 & 4) !=3D 0; + tlb->C1 =3D (env->CP0_EntryLo1 >> 3) & 0x7; + tlb->XI1 =3D (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; + tlb->RI1 =3D (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; + tlb->PFN[1] =3D (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) = << 12; +} + +static void r4k_helper_tlbinv(CPUMIPSState *env) +{ + bool mi =3D !!((env->CP0_Config5 >> CP0C5_MI) & 1); + uint16_t ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; + uint32_t MMID =3D env->CP0_MemoryMapID; + uint32_t tlb_mmid; + r4k_tlb_t *tlb; + int idx; + + MMID =3D mi ? MMID : (uint32_t) ASID; + for (idx =3D 0; idx < env->tlb->nb_tlb; idx++) { + tlb =3D &env->tlb->mmu.r4k.tlb[idx]; + tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; + if (!tlb->G && tlb_mmid =3D=3D MMID) { + tlb->EHINV =3D 1; + } + } + cpu_mips_tlb_flush(env); +} + +static void r4k_helper_tlbinvf(CPUMIPSState *env) +{ + int idx; + + for (idx =3D 0; idx < env->tlb->nb_tlb; idx++) { + env->tlb->mmu.r4k.tlb[idx].EHINV =3D 1; + } + cpu_mips_tlb_flush(env); +} + +static void r4k_helper_tlbwi(CPUMIPSState *env) +{ + bool mi =3D !!((env->CP0_Config5 >> CP0C5_MI) & 1); + target_ulong VPN; + uint16_t ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; + uint32_t MMID =3D env->CP0_MemoryMapID; + uint32_t tlb_mmid; + bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1; + r4k_tlb_t *tlb; + int idx; + + MMID =3D mi ? MMID : (uint32_t) ASID; + + idx =3D (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; + tlb =3D &env->tlb->mmu.r4k.tlb[idx]; + VPN =3D env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); +#if defined(TARGET_MIPS64) + VPN &=3D env->SEGMask; +#endif + EHINV =3D (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) !=3D 0; + G =3D env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; + V0 =3D (env->CP0_EntryLo0 & 2) !=3D 0; + D0 =3D (env->CP0_EntryLo0 & 4) !=3D 0; + XI0 =3D (env->CP0_EntryLo0 >> CP0EnLo_XI) &1; + RI0 =3D (env->CP0_EntryLo0 >> CP0EnLo_RI) &1; + V1 =3D (env->CP0_EntryLo1 & 2) !=3D 0; + D1 =3D (env->CP0_EntryLo1 & 4) !=3D 0; + XI1 =3D (env->CP0_EntryLo1 >> CP0EnLo_XI) &1; + RI1 =3D (env->CP0_EntryLo1 >> CP0EnLo_RI) &1; + + tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; + /* + * Discard cached TLB entries, unless tlbwi is just upgrading access + * permissions on the current entry. + */ + if (tlb->VPN !=3D VPN || tlb_mmid !=3D MMID || tlb->G !=3D G || + (!tlb->EHINV && EHINV) || + (tlb->V0 && !V0) || (tlb->D0 && !D0) || + (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) || + (tlb->V1 && !V1) || (tlb->D1 && !D1) || + (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) { + r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); + } + + r4k_invalidate_tlb(env, idx, 0); + r4k_fill_tlb(env, idx); +} + +static void r4k_helper_tlbwr(CPUMIPSState *env) +{ + int r =3D cpu_mips_get_random(env); + + r4k_invalidate_tlb(env, r, 1); + r4k_fill_tlb(env, r); +} + +static void r4k_helper_tlbp(CPUMIPSState *env) +{ + bool mi =3D !!((env->CP0_Config5 >> CP0C5_MI) & 1); + r4k_tlb_t *tlb; + target_ulong mask; + target_ulong tag; + target_ulong VPN; + uint16_t ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; + uint32_t MMID =3D env->CP0_MemoryMapID; + uint32_t tlb_mmid; + int i; + + MMID =3D mi ? MMID : (uint32_t) ASID; + for (i =3D 0; i < env->tlb->nb_tlb; i++) { + tlb =3D &env->tlb->mmu.r4k.tlb[i]; + /* 1k pages are not supported. */ + mask =3D tlb->PageMask | ~(TARGET_PAGE_MASK << 1); + tag =3D env->CP0_EntryHi & ~mask; + VPN =3D tlb->VPN & ~mask; +#if defined(TARGET_MIPS64) + tag &=3D env->SEGMask; +#endif + tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; + /* Check ASID/MMID, virtual page number & size */ + if ((tlb->G =3D=3D 1 || tlb_mmid =3D=3D MMID) && VPN =3D=3D tag &&= !tlb->EHINV) { + /* TLB match */ + env->CP0_Index =3D i; + break; + } + } + if (i =3D=3D env->tlb->nb_tlb) { + /* No match. Discard any shadow entries, if any of them match. */ + for (i =3D env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) { + tlb =3D &env->tlb->mmu.r4k.tlb[i]; + /* 1k pages are not supported. */ + mask =3D tlb->PageMask | ~(TARGET_PAGE_MASK << 1); + tag =3D env->CP0_EntryHi & ~mask; + VPN =3D tlb->VPN & ~mask; +#if defined(TARGET_MIPS64) + tag &=3D env->SEGMask; +#endif + tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; + /* Check ASID/MMID, virtual page number & size */ + if ((tlb->G =3D=3D 1 || tlb_mmid =3D=3D MMID) && VPN =3D=3D ta= g) { + r4k_mips_tlb_flush_extra(env, i); + break; + } + } + + env->CP0_Index |=3D 0x80000000; + } +} + +static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn) +{ +#if defined(TARGET_MIPS64) + return tlb_pfn << 6; +#else + return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */ + (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */ +#endif +} + +static void r4k_helper_tlbr(CPUMIPSState *env) +{ + bool mi =3D !!((env->CP0_Config5 >> CP0C5_MI) & 1); + uint16_t ASID =3D env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; + uint32_t MMID =3D env->CP0_MemoryMapID; + uint32_t tlb_mmid; + r4k_tlb_t *tlb; + int idx; + + MMID =3D mi ? MMID : (uint32_t) ASID; + idx =3D (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; + tlb =3D &env->tlb->mmu.r4k.tlb[idx]; + + tlb_mmid =3D mi ? tlb->MMID : (uint32_t) tlb->ASID; + /* If this will change the current ASID/MMID, flush qemu's TLB. */ + if (MMID !=3D tlb_mmid) { + cpu_mips_tlb_flush(env); + } + + r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); + + if (tlb->EHINV) { + env->CP0_EntryHi =3D 1 << CP0EnHi_EHINV; + env->CP0_PageMask =3D 0; + env->CP0_EntryLo0 =3D 0; + env->CP0_EntryLo1 =3D 0; + } else { + env->CP0_EntryHi =3D mi ? tlb->VPN : tlb->VPN | tlb->ASID; + env->CP0_MemoryMapID =3D tlb->MMID; + env->CP0_PageMask =3D tlb->PageMask; + env->CP0_EntryLo0 =3D tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | + ((uint64_t)tlb->RI0 << CP0EnLo_RI) | + ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3= ) | + get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12); + env->CP0_EntryLo1 =3D tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | + ((uint64_t)tlb->RI1 << CP0EnLo_RI) | + ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3= ) | + get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12); + } +} + +void helper_tlbwi(CPUMIPSState *env) +{ + env->tlb->helper_tlbwi(env); +} + +void helper_tlbwr(CPUMIPSState *env) +{ + env->tlb->helper_tlbwr(env); +} + +void helper_tlbp(CPUMIPSState *env) +{ + env->tlb->helper_tlbp(env); +} + +void helper_tlbr(CPUMIPSState *env) +{ + env->tlb->helper_tlbr(env); +} + +void helper_tlbinv(CPUMIPSState *env) +{ + env->tlb->helper_tlbinv(env); +} + +void helper_tlbinvf(CPUMIPSState *env) +{ + env->tlb->helper_tlbinvf(env); +} + +static void global_invalidate_tlb(CPUMIPSState *env, + uint32_t invMsgVPN2, + uint8_t invMsgR, + uint32_t invMsgMMid, + bool invAll, + bool invVAMMid, + bool invMMid, + bool invVA) +{ + + int idx; + r4k_tlb_t *tlb; + bool VAMatch; + bool MMidMatch; + + for (idx =3D 0; idx < env->tlb->nb_tlb; idx++) { + tlb =3D &env->tlb->mmu.r4k.tlb[idx]; + VAMatch =3D + (((tlb->VPN & ~tlb->PageMask) =3D=3D (invMsgVPN2 & ~tlb->PageM= ask)) +#ifdef TARGET_MIPS64 + && + (extract64(env->CP0_EntryHi, 62, 2) =3D=3D invMsgR) +#endif + ); + MMidMatch =3D tlb->MMID =3D=3D invMsgMMid; + if ((invAll && (idx > env->CP0_Wired)) || + (VAMatch && invVAMMid && (tlb->G || MMidMatch)) || + (VAMatch && invVA) || + (MMidMatch && !(tlb->G) && invMMid)) { + tlb->EHINV =3D 1; + } + } + cpu_mips_tlb_flush(env); +} + +void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type) +{ + bool invAll =3D type =3D=3D 0; + bool invVA =3D type =3D=3D 1; + bool invMMid =3D type =3D=3D 2; + bool invVAMMid =3D type =3D=3D 3; + uint32_t invMsgVPN2 =3D arg & (TARGET_PAGE_MASK << 1); + uint8_t invMsgR =3D 0; + uint32_t invMsgMMid =3D env->CP0_MemoryMapID; + CPUState *other_cs =3D first_cpu; + +#ifdef TARGET_MIPS64 + invMsgR =3D extract64(arg, 62, 2); +#endif + + CPU_FOREACH(other_cs) { + MIPSCPU *other_cpu =3D MIPS_CPU(other_cs); + global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsg= MMid, + invAll, invVAMMid, invMMid, invVA); + } +} =20 /* no MMU emulation */ static int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *pr= ot, --=20 2.26.3