From nobody Tue Feb 10 20:47:34 2026 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1517181937640976.7598172935593; Sun, 28 Jan 2018 15:25:37 -0800 (PST) Received: from localhost ([::1]:44959 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1efwKO-000136-Pb for importer@patchew.org; Sun, 28 Jan 2018 18:25:36 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52105) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1efwB7-0002mD-96 for qemu-devel@nongnu.org; Sun, 28 Jan 2018 18:16:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1efwB5-0008Rd-Ju for qemu-devel@nongnu.org; Sun, 28 Jan 2018 18:16:01 -0500 Received: from mail-pf0-x244.google.com ([2607:f8b0:400e:c00::244]:43758) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1efwB5-0008Qv-B9 for qemu-devel@nongnu.org; Sun, 28 Jan 2018 18:15:59 -0500 Received: by mail-pf0-x244.google.com with SMTP id y26so3252534pfi.10 for ; Sun, 28 Jan 2018 15:15:59 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id r27sm26949344pfj.75.2018.01.28.15.15.56 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 28 Jan 2018 15:15:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=eG5R/krhUh85JvFvLywMKrTWgyWfpA6v6Z/xTno+tRQ=; b=P2s0aNUglYXC1zQaTqhrefurW8AnYR0i5kjc8HzmuIh0476pxJ+ajjcsQ6iiMATCwI 14VJ/mi44E1wL+NQhPi1lhC7lE69mMNYFCBMPHExgrMU6J6Lu5fZpbDfa5vJOiie8pcH Ms4XHoJ+zFvHSBEdhq/fdQ1fRm5+YStlIMkWI= 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=eG5R/krhUh85JvFvLywMKrTWgyWfpA6v6Z/xTno+tRQ=; b=Y9H31tvvZSXy2ORHVzY0NnBRUGSLG0V3HKNggNdqA/fXnJrXrsAfg6N1b02TLQPYgt pZEIhyo4WsyE1eAXsgW5JPlfMfd8/ZYTkW1nvnVqiBtfYF+bfgjG6Ekmrxaq/Dg9nto6 CEDlyWv14O76SHojK0aM2OGs5DuWbE3CpJXH7EStcft+pkI2t1lV0osC6yT8h2M0QuR6 L0totKjx3PUCmaSQZeCe2I1D24viqFGeeTtXD5WqJmJL3HJBdFaL39Q9y7fcH3V2luGb 7DHFG5ymTAu9Bc2b2TFegcgdAyl9CPmcfsj84tVObE1jkATWKNM+jOxpNFXgOhHxmCFS Hrbw== X-Gm-Message-State: AKwxytcOqO5FJrLsCnYefANRc8rLr0lFb7plepMP1j72ugP4bN+fRXLS NXx/YxKwYWwQetCaJl0zqT4ibjZ6J9c= X-Google-Smtp-Source: AH8x224L55DzAOx5xIumomyzKYUc/QfDc2OH9JE7e/Rz7JF7WeezAkyn6vptsjYrw7+aLbrC8H6yvA== X-Received: by 2002:a17:902:68cb:: with SMTP id x11-v6mr19910725plm.198.1517181357930; Sun, 28 Jan 2018 15:15:57 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sun, 28 Jan 2018 15:15:02 -0800 Message-Id: <20180128231528.22719-18-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180128231528.22719-1-richard.henderson@linaro.org> References: <20180128231528.22719-1-richard.henderson@linaro.org> 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 v4 17/43] target/hppa: Implement tlb_fill 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: peter.maydell@linaro.org 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" However since HPPA has a software-managed TLB, and the relevant TLB manipulation instructions are not implemented, this does not actually do anything. Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 31 ++++++++- target/hppa/int_helper.c | 14 +++- target/hppa/mem_helper.c | 162 +++++++++++++++++++++++++++++++++++++++++++= ++-- 3 files changed, 197 insertions(+), 10 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 27cd5f03d8..bd8fe6af78 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -165,6 +165,22 @@ typedef int64_t target_sreg; #define TREG_FMT_ld "%"PRId64 #endif =20 +typedef struct { + uint64_t va_b; + uint64_t va_e; + target_ureg pa; + unsigned u : 1; + unsigned t : 1; + unsigned d : 1; + unsigned b : 1; + unsigned page_size : 4; + unsigned ar_type : 3; + unsigned ar_pl1 : 2; + unsigned ar_pl2 : 2; + unsigned entry_valid : 1; + unsigned access_id : 16; +} hppa_tlb_entry; + struct CPUHPPAState { target_ureg gr[32]; uint64_t fr[32]; @@ -198,6 +214,12 @@ struct CPUHPPAState { =20 /* Those resources are used only in QEMU core */ CPU_COMMON + + /* ??? The number of entries isn't specified by the architecture. */ + /* ??? Implement a unified itlb/dtlb for the moment. */ + /* ??? We should use a more intelligent data structure. */ + hppa_tlb_entry tlb[256]; + uint32_t tlb_last; }; =20 /** @@ -307,13 +329,18 @@ void cpu_hppa_loaded_fr0(CPUHPPAState *env); #define cpu_signal_handler cpu_hppa_signal_handler =20 int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc); -int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, - int rw, int midx); hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr); int hppa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); void hppa_cpu_do_interrupt(CPUState *cpu); bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req); void hppa_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function, int); +#ifdef CONFIG_USER_ONLY +int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, + int rw, int midx); +#else +int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, + int type, hwaddr *pphys, int *pprot); +#endif =20 #endif /* HPPA_CPU_H */ diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index 02963b80c6..3d668a3a4f 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -79,12 +79,24 @@ void hppa_cpu_do_interrupt(CPUState *cs) { /* Avoid reading directly from the virtual address, lest we raise another exception from some sort of TLB issue. */ + /* ??? An alternate fool-proof method would be to store the + instruction data into the unwind info. That's probably + a bit too much in the way of extra storage required. */ vaddr vaddr; hwaddr paddr; =20 paddr =3D vaddr =3D iaoq_f & -4; if (old_psw & PSW_C) { - vaddr =3D hppa_form_gva_psw(old_psw, iasq_f, iaoq_f & = -4); + int prot, t; + + vaddr =3D hppa_form_gva_psw(old_psw, iasq_f, vaddr); + t =3D hppa_get_physical_address(env, vaddr, MMU_KERNEL= _IDX, + 0, &paddr, &prot); + if (t >=3D 0) { + /* We can't re-load the instruction. */ + env->cr[CR_IIR] =3D 0; + break; + } } env->cr[CR_IIR] =3D ldl_phys(cs->as, paddr); } diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 65e2c95b78..67c57d9a41 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -36,18 +36,166 @@ int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr addr= ess, return 1; } #else +static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, vaddr addr) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(env->tlb); ++i) { + hppa_tlb_entry *ent =3D &env->tlb[i]; + if (ent->va_b <=3D addr && addr <=3D ent->va_e && ent->entry_valid= ) { + return ent; + } + } + return NULL; +} + +int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, + int type, hwaddr *pphys, int *pprot) +{ + hwaddr phys; + int prot, r_prot, w_prot, x_prot; + hppa_tlb_entry *ent; + int ret =3D -1; + + /* Virtual translation disabled. Direct map virtual to physical. */ + if (mmu_idx =3D=3D MMU_PHYS_IDX) { + phys =3D addr; + prot =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; + goto egress; + } + + /* Find a valid tlb entry that matches the virtual address. */ + ent =3D hppa_find_tlb(env, addr); + if (ent =3D=3D NULL) { + phys =3D 0; + prot =3D 0; + ret =3D (type & PAGE_EXEC ? EXCP_ITLB_MISS : EXCP_DTLB_MISS); + goto egress; + } + + /* We now know the physical address. */ + phys =3D ent->pa + (addr & ~TARGET_PAGE_MASK); + + /* Map TLB access_rights field to QEMU protection. */ + r_prot =3D (mmu_idx <=3D ent->ar_pl1) * PROT_READ; + w_prot =3D (mmu_idx <=3D ent->ar_pl2) * PROT_WRITE; + x_prot =3D (ent->ar_pl2 <=3D mmu_idx && mmu_idx <=3D ent->ar_pl1) * PR= OT_EXEC; + switch (ent->ar_type) { + case 0: /* read-only: data page */ + prot =3D r_prot; + break; + case 1: /* read/write: dynamic data page */ + prot =3D r_prot | w_prot; + break; + case 2: /* read/execute: normal code page */ + prot =3D r_prot | x_prot; + break; + case 3: /* read/write/execute: dynamic code page */ + prot =3D r_prot | w_prot | x_prot; + break; + default: /* execute: promote to privilege level type & 3 */ + prot =3D x_prot; + } + + /* ??? Check PSW_P and ent->access_prot. This can remove PROT_WRITE. = */ + + /* No guest access type indicates a non-architectural access from + within QEMU. Bypass checks for access, D, B and T bits. */ + if (type =3D=3D 0) { + goto egress; + } + + if (unlikely(!(prot & type))) { + /* The access isn't allowed -- Inst/Data Memory Protection Fault. = */ + ret =3D (type & PAGE_EXEC ? EXCP_IMP : EXCP_DMP); + goto egress; + } + + /* In reverse priority order, check for conditions which raise faults. + As we go, remove PROT bits that cover the condition we want to chec= k. + In this way, the resulting PROT will force a re-check of the + architectural TLB entry for the next access. */ + if (unlikely(!ent->d)) { + if (type & PAGE_WRITE) { + /* The D bit is not set -- TLB Dirty Bit Fault. */ + ret =3D EXCP_TLB_DIRTY; + } + prot &=3D PROT_READ | PROT_EXEC; + } + if (unlikely(ent->b)) { + if (type & PAGE_WRITE) { + /* The B bit is set -- Data Memory Break Fault. */ + ret =3D EXCP_DMB; + } + prot &=3D PROT_READ | PROT_EXEC; + } + if (unlikely(ent->t)) { + if (!(type & PAGE_EXEC)) { + /* The T bit is set -- Page Reference Fault. */ + ret =3D EXCP_PAGE_REF; + } + prot &=3D PROT_EXEC; + } + + egress: + *pphys =3D phys; + *pprot =3D prot; + return ret; +} + hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { - /* Stub */ - return addr; + HPPACPU *cpu =3D HPPA_CPU(cs); + hwaddr phys; + int prot, excp; + + /* If the (data) mmu is disabled, bypass translation. */ + /* ??? We really ought to know if the code mmu is disabled too, + in order to get the correct debugging dumps. */ + if (!(cpu->env.psw & PSW_D)) { + return addr; + } + + excp =3D hppa_get_physical_address(&cpu->env, addr, MMU_KERNEL_IDX, 0, + &phys, &prot); + + /* Since we're translating for debugging, the only error that is a + hard error is no translation at all. Otherwise, while a real cpu + access might not have permission, the debugger does. */ + return excp =3D=3D EXCP_DTLB_MISS ? -1 : phys; } =20 -void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType type, - int mmu_idx, uintptr_t retaddr) +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType type, int mmu_idx, uintptr_t retaddr) { - /* Stub */ - int prot =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; - hwaddr phys =3D addr; + HPPACPU *cpu =3D HPPA_CPU(cs); + int prot, excp, a_prot; + hwaddr phys; + + switch (type) { + case MMU_INST_FETCH: + a_prot =3D PROT_EXEC; + break; + case MMU_DATA_STORE: + a_prot =3D PROT_WRITE; + break; + default: + a_prot =3D PROT_READ; + break; + } + + excp =3D hppa_get_physical_address(&cpu->env, addr, mmu_idx, + a_prot, &phys, &prot); + if (unlikely(excp >=3D 0)) { + /* Failure. Raise the indicated exception. */ + cs->exception_index =3D excp; + if (cpu->env.psw & PSW_Q) { + /* ??? Needs tweaking for hppa64. */ + cpu->env.cr[CR_IOR] =3D addr; + cpu->env.cr[CR_ISR] =3D addr >> 32; + } + cpu_loop_exit_restore(cs, retaddr); + } =20 /* Success! Store the translation into the QEMU TLB. */ tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, --=20 2.14.3