From nobody Tue Nov 4 19:05:32 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530541288619560.0291060655874; Mon, 2 Jul 2018 07:21:28 -0700 (PDT) Received: from localhost ([::1]:33078 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fZzhn-0001Un-Qp for importer@patchew.org; Mon, 02 Jul 2018 10:21:27 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47805) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fZzM9-0002oB-HY for qemu-devel@nongnu.org; Mon, 02 Jul 2018 09:59:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fZzM7-0008OB-OZ for qemu-devel@nongnu.org; Mon, 02 Jul 2018 09:59:05 -0400 Received: from mail-pf0-x244.google.com ([2607:f8b0:400e:c00::244]:39640) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fZzM7-0008Nr-Ei for qemu-devel@nongnu.org; Mon, 02 Jul 2018 09:59:03 -0400 Received: by mail-pf0-x244.google.com with SMTP id s21-v6so7566331pfm.6 for ; Mon, 02 Jul 2018 06:59:03 -0700 (PDT) Received: from localhost (g90.124-44-6.ppp.wakwak.ne.jp. [124.44.6.90]) by smtp.gmail.com with ESMTPSA id m86-v6sm13414711pfi.47.2018.07.02.06.59.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 02 Jul 2018 06:59:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QAqh/3eTuvXq/YfChPe5U3ubjoePgMt1L0T6W0B22sE=; b=VT1dHxoGojLdJ4iGHStXmRsFJTAatH1QrpGRyWjj0qjJlVr1Uvy+hVtTenJH+MQUyB bpWmpfX3pbgE2UEfyGTIDuU5gyoaHjUJB0oEKYqfVb5pW2Dtw64rMnpAjc1/975vYPnJ zTtwPQI9NHSjAqLILVadUtoAQ2dfrqMp6dr8ZvBhLhr1mX0Mm18G7GV7Uy+vBwikDvWk AXkCvLnE1OauQe1URPIVd3pPmorVl1BL0Zt1M0dJ9jRQjPdnh3ZfM3ab8h3q67NCGnVe CtsOrIty91G/XcOa/J417qAySlonlQuAVaYpsMflerWvHcDcM6qsz8b54vAPFuEH1cE7 4bhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QAqh/3eTuvXq/YfChPe5U3ubjoePgMt1L0T6W0B22sE=; b=UH5ECiz42YFKpnIGEqI/Zy9J1evD3U8IoaIbQctWhpTMNvpPYK9IUdztwyua9AGUV1 U0wfbHpuip0SxeGdrc412ekvpdn1/F4swoF66qtpsX6IEOlZWAHPlDBVbrLdW+8Pbhkg MaCpifKvMT5RQOwB72POpClTueePdTDOTNOa121HcCFii1o5Tps8h1PuL0arFEg1vAkW okEEVhJ1zz4eTg4ih7VWCTxz9Rl/133gFNw13g34llp58q77wrhTngh2X3NX0oxMyvoZ jptXHs84kqufx4WgZ8CWpHygTUXpF5nW2mbJGLrS+hUSM3O9fxprWovbXY5L0yc0dVPc 0zJA== X-Gm-Message-State: APt69E3kPeK8ZdO+47L9pG4dJJeF0wSTW22UK5UFCGx9l84WkIJZWRSg zRefanJd3//4gb3Ho9p210A= X-Google-Smtp-Source: AAOMgpfFpDIMlMb8zYQfJ6BEvcNbRoAdGhwU4V1mcjeHMyZnqaS8cbdltOYDVt1usPcztEFfN9Mm1w== X-Received: by 2002:aa7:820e:: with SMTP id k14-v6mr25462594pfi.97.1530539942317; Mon, 02 Jul 2018 06:59:02 -0700 (PDT) From: Stafford Horne To: Peter Maydell Date: Mon, 2 Jul 2018 22:58:01 +0900 Message-Id: <20180702135806.7087-21-shorne@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180702135806.7087-1-shorne@gmail.com> References: <20180702135806.7087-1-shorne@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::244 Subject: [Qemu-devel] [PULL 20/25] target/openrisc: Reorg tlb lookup X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stafford Horne , Richard Henderson , QEMU Development Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Richard Henderson While openrisc has a split i/d tlb, qemu does not. Perform a lookup on both i & d tlbs in parallel and put the composite rights into qemu's tlb. This avoids ping-ponging the qemu tlb between EXEC and READ. Signed-off-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/cpu.h | 8 -- target/openrisc/mmu.c | 250 +++++++++++++++--------------------------- 2 files changed, 88 insertions(+), 170 deletions(-) diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index b180e30e9e..f1b31bc24a 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -237,14 +237,6 @@ enum { UXE =3D (1 << 7), }; =20 -/* check if tlb available */ -enum { - TLBRET_INVALID =3D -3, - TLBRET_NOMATCH =3D -2, - TLBRET_BADADDR =3D -1, - TLBRET_MATCH =3D 0 -}; - typedef struct OpenRISCTLBEntry { uint32_t mr; uint32_t tr; diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index f4c0a3e217..d3796ae41e 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -29,148 +29,78 @@ #endif =20 #ifndef CONFIG_USER_ONLY -static inline int get_phys_nommu(hwaddr *physical, int *prot, - target_ulong address) +static inline void get_phys_nommu(hwaddr *phys_addr, int *prot, + target_ulong address) { - *physical =3D address; + *phys_addr =3D address; *prot =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; - return TLBRET_MATCH; } =20 -static int get_phys_code(OpenRISCCPU *cpu, hwaddr *physical, int *prot, - target_ulong address, int rw, bool supervisor) +static int get_phys_mmu(OpenRISCCPU *cpu, hwaddr *phys_addr, int *prot, + target_ulong addr, int need, bool super) { - int vpn =3D address >> TARGET_PAGE_BITS; - int idx =3D vpn & TLB_MASK; - int right =3D 0; - uint32_t mr =3D cpu->env.tlb.itlb[idx].mr; - uint32_t tr =3D cpu->env.tlb.itlb[idx].tr; - - if ((mr >> TARGET_PAGE_BITS) !=3D vpn) { - return TLBRET_NOMATCH; - } - if (!(mr & 1)) { - return TLBRET_INVALID; - } - if (supervisor) { - if (tr & SXE) { - right |=3D PAGE_EXEC; - } - } else { - if (tr & UXE) { - right |=3D PAGE_EXEC; + int idx =3D (addr >> TARGET_PAGE_BITS) & TLB_MASK; + uint32_t imr =3D cpu->env.tlb.itlb[idx].mr; + uint32_t itr =3D cpu->env.tlb.itlb[idx].tr; + uint32_t dmr =3D cpu->env.tlb.dtlb[idx].mr; + uint32_t dtr =3D cpu->env.tlb.dtlb[idx].tr; + int right, match, valid; + + /* If the ITLB and DTLB indexes map to the same page, we want to + load all permissions all at once. If the destination pages do + not match, zap the one we don't need. */ + if (unlikely((itr ^ dtr) & TARGET_PAGE_MASK)) { + if (need & PAGE_EXEC) { + dmr =3D dtr =3D 0; + } else { + imr =3D itr =3D 0; } } - if ((rw & 2) && ((right & PAGE_EXEC) =3D=3D 0)) { - return TLBRET_BADADDR; - } =20 - *physical =3D (tr & TARGET_PAGE_MASK) | (address & ~TARGET_PAGE_MASK); - *prot =3D right; - return TLBRET_MATCH; -} + /* Check if either of the entries matches the source address. */ + match =3D (imr ^ addr) & TARGET_PAGE_MASK ? 0 : PAGE_EXEC; + match |=3D (dmr ^ addr) & TARGET_PAGE_MASK ? 0 : PAGE_READ | PAGE_WRIT= E; =20 -static int get_phys_data(OpenRISCCPU *cpu, hwaddr *physical, int *prot, - target_ulong address, int rw, bool supervisor) -{ - int vpn =3D address >> TARGET_PAGE_BITS; - int idx =3D vpn & TLB_MASK; - int right =3D 0; - uint32_t mr =3D cpu->env.tlb.dtlb[idx].mr; - uint32_t tr =3D cpu->env.tlb.dtlb[idx].tr; + /* Check if either of the entries is valid. */ + valid =3D imr & 1 ? PAGE_EXEC : 0; + valid |=3D dmr & 1 ? PAGE_READ | PAGE_WRITE : 0; + valid &=3D match; =20 - if ((mr >> TARGET_PAGE_BITS) !=3D vpn) { - return TLBRET_NOMATCH; - } - if (!(mr & 1)) { - return TLBRET_INVALID; - } - if (supervisor) { - if (tr & SRE) { - right |=3D PAGE_READ; - } - if (tr & SWE) { - right |=3D PAGE_WRITE; - } - } else { - if (tr & URE) { - right |=3D PAGE_READ; - } - if (tr & UWE) { - right |=3D PAGE_WRITE; - } - } - - if (!(rw & 1) && ((right & PAGE_READ) =3D=3D 0)) { - return TLBRET_BADADDR; - } - if ((rw & 1) && ((right & PAGE_WRITE) =3D=3D 0)) { - return TLBRET_BADADDR; - } + /* Collect the permissions from the entries. */ + right =3D itr & (super ? SXE : UXE) ? PAGE_EXEC : 0; + right |=3D dtr & (super ? SRE : URE) ? PAGE_READ : 0; + right |=3D dtr & (super ? SWE : UWE) ? PAGE_WRITE : 0; + right &=3D valid; =20 - *physical =3D (tr & TARGET_PAGE_MASK) | (address & ~TARGET_PAGE_MASK); + /* Note that above we validated that itr and dtr match on page. + So oring them together changes nothing without having to + check which one we needed. We also want to store to these + variables even on failure, as it avoids compiler warnings. */ + *phys_addr =3D ((itr | dtr) & TARGET_PAGE_MASK) | (addr & ~TARGET_PAGE= _MASK); *prot =3D right; - return TLBRET_MATCH; -} =20 -static int get_phys_addr(OpenRISCCPU *cpu, hwaddr *physical, - int *prot, target_ulong address, int rw) -{ - bool supervisor =3D (cpu->env.sr & SR_SM) !=3D 0; - int ret; + qemu_log_mask(CPU_LOG_MMU, + "MMU lookup: need %d match %d valid %d right %d -> %s\n", + need, match, valid, right, (need & right) ? "OK" : "FAIL= "); =20 - /* Assume nommu results for a moment. */ - ret =3D get_phys_nommu(physical, prot, address); + /* Check the collective permissions are present. */ + if (likely(need & right)) { + return 0; /* success! */ + } =20 - /* Overwrite with TLB lookup if enabled. */ - if (rw =3D=3D MMU_INST_FETCH) { - if (cpu->env.sr & SR_IME) { - ret =3D get_phys_code(cpu, physical, prot, address, rw, superv= isor); - } + /* Determine what kind of failure we have. */ + if (need & valid) { + return need & PAGE_EXEC ? EXCP_IPF : EXCP_DPF; } else { - if (cpu->env.sr & SR_DME) { - ret =3D get_phys_data(cpu, physical, prot, address, rw, superv= isor); - } + return need & PAGE_EXEC ? EXCP_ITLBMISS : EXCP_DTLBMISS; } - - return ret; } #endif =20 -static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU *cpu, - target_ulong address, - int rw, int tlb_error) +static void raise_mmu_exception(OpenRISCCPU *cpu, target_ulong address, + int exception) { CPUState *cs =3D CPU(cpu); - int exception =3D 0; - - switch (tlb_error) { - default: - if (rw =3D=3D 2) { - exception =3D EXCP_IPF; - } else { - exception =3D EXCP_DPF; - } - break; -#ifndef CONFIG_USER_ONLY - case TLBRET_BADADDR: - if (rw =3D=3D 2) { - exception =3D EXCP_IPF; - } else { - exception =3D EXCP_DPF; - } - break; - case TLBRET_INVALID: - case TLBRET_NOMATCH: - /* No TLB match for a mapped address */ - if (rw =3D=3D 2) { - exception =3D EXCP_ITLBMISS; - } else { - exception =3D EXCP_DTLBMISS; - } - break; -#endif - } =20 cs->exception_index =3D exception; cpu->env.eear =3D address; @@ -182,7 +112,7 @@ int openrisc_cpu_handle_mmu_fault(CPUState *cs, vaddr a= ddress, int size, { #ifdef CONFIG_USER_ONLY OpenRISCCPU *cpu =3D OPENRISC_CPU(cs); - cpu_openrisc_raise_mmu_exception(cpu, address, rw, 0); + raise_mmu_exception(cpu, address, EXCP_DPF); return 1; #else g_assert_not_reached(); @@ -193,27 +123,32 @@ int openrisc_cpu_handle_mmu_fault(CPUState *cs, vaddr= address, int size, hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { OpenRISCCPU *cpu =3D OPENRISC_CPU(cs); + int prot, excp, sr =3D cpu->env.sr; hwaddr phys_addr; - int prot; - int miss; =20 - /* Check memory for any kind of address, since during debug the - gdb can ask for anything, check data tlb for address */ - miss =3D get_phys_addr(cpu, &phys_addr, &prot, addr, 0); + switch (sr & (SR_DME | SR_IME)) { + case SR_DME | SR_IME: + /* The mmu is definitely enabled. */ + excp =3D get_phys_mmu(cpu, &phys_addr, &prot, addr, + PROT_EXEC | PROT_READ | PROT_WRITE, + (sr & SR_SM) !=3D 0); + return excp ? -1 : phys_addr; =20 - /* Check instruction tlb */ - if (miss) { - miss =3D get_phys_addr(cpu, &phys_addr, &prot, addr, MMU_INST_FETC= H); - } - - /* Last, fall back to a plain address */ - if (miss) { - miss =3D get_phys_nommu(&phys_addr, &prot, addr); - } + default: + /* The mmu is partially enabled, and we don't really have + a "real" access type. Begin by trying the mmu, but if + that fails try again without. */ + excp =3D get_phys_mmu(cpu, &phys_addr, &prot, addr, + PROT_EXEC | PROT_READ | PROT_WRITE, + (sr & SR_SM) !=3D 0); + if (!excp) { + return phys_addr; + } + /* fallthru */ =20 - if (miss) { - return -1; - } else { + case 0: + /* The mmu is definitely disabled; lookups never fail. */ + get_phys_nommu(&phys_addr, &prot, addr); return phys_addr; } } @@ -222,37 +157,28 @@ void tlb_fill(CPUState *cs, target_ulong addr, int si= ze, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { OpenRISCCPU *cpu =3D OPENRISC_CPU(cs); - int ret, prot =3D 0; - hwaddr physical =3D 0; + int prot, excp; + hwaddr phys_addr; =20 if (mmu_idx =3D=3D MMU_NOMMU_IDX) { - ret =3D get_phys_nommu(&physical, &prot, addr); + /* The mmu is disabled; lookups never fail. */ + get_phys_nommu(&phys_addr, &prot, addr); + excp =3D 0; } else { bool super =3D mmu_idx =3D=3D MMU_SUPERVISOR_IDX; - if (access_type =3D=3D MMU_INST_FETCH) { - ret =3D get_phys_code(cpu, &physical, &prot, addr, 2, super); - } else { - ret =3D get_phys_data(cpu, &physical, &prot, addr, - access_type =3D=3D MMU_DATA_STORE, super); - } + int need =3D (access_type =3D=3D MMU_INST_FETCH ? PROT_EXEC + : access_type =3D=3D MMU_DATA_STORE ? PROT_WRITE + : PROT_READ); + excp =3D get_phys_mmu(cpu, &phys_addr, &prot, addr, need, super); } =20 - if (ret =3D=3D TLBRET_MATCH) { - tlb_set_page(cs, addr & TARGET_PAGE_MASK, - physical & TARGET_PAGE_MASK, prot, - mmu_idx, TARGET_PAGE_SIZE); - } else if (ret < 0) { - int rw; - if (access_type =3D=3D MMU_INST_FETCH) { - rw =3D 2; - } else if (access_type =3D=3D MMU_DATA_STORE) { - rw =3D 1; - } else { - rw =3D 0; - } - cpu_openrisc_raise_mmu_exception(cpu, addr, rw, ret); - /* Raise Exception. */ + if (unlikely(excp)) { + raise_mmu_exception(cpu, addr, excp); cpu_loop_exit_restore(cs, retaddr); } + + tlb_set_page(cs, addr & TARGET_PAGE_MASK, + phys_addr & TARGET_PAGE_MASK, prot, + mmu_idx, TARGET_PAGE_SIZE); } #endif --=20 2.17.0