* [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill
@ 2019-05-09 6:02 Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 01/27] " Richard Henderson
` (26 more replies)
0 siblings, 27 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
Changes from v1:
* Do not unify user-only and system tlb_fill functions
(alpha, microblaze, nios2, s390x, sparc, xtensa).
* Split the mips patch into multiple.
* Other random changes per review.
Patches without review:
0009-target-microblaze-Convert-to-CPUClass-tlb_fill.patch
0010-target-mips-Pass-a-valid-error-to-raise_mmu_excep.patch (new)
0011-target-mips-Tidy-control-flow-in-mips_cpu_handle_.patch (new)
0012-target-mips-Convert-to-CPUClass-tlb_fill.patch
0014-target-nios2-Convert-to-CPUClass-tlb_fill.patch
0018-target-s390x-Convert-to-CPUClass-tlb_fill.patch
0020-target-sparc-Convert-to-CPUClass-tlb_fill.patch
0024-target-xtensa-Convert-to-CPUClass-tlb_fill.patch
Blurb from v1:
There is currently a lot of confusion between foo_cpu_handle_mmu_fault
and tlb_fill.
In particular, foo_cpu_handle_mmu_fault was only defined for user-only,
and its only valid action was to set up the cpu for cpu_loop_exit so
that we can deliver a SIGSEGV to the guest. And yet, we had code that
tried to return from the host SIGSEGV handler to retry the instruction.
We had, for some targets, a definition of foo_cpu_handle_mmu_fault
for softmmu. Sometimes this was called from tlb_fill, sometimes not.
Finally, we have a use case for SVE that wants a non-faulting tlb_fill,
so while we're changing the interface, let's go ahead and include that.
r~
Richard Henderson (27):
tcg: Add CPUClass::tlb_fill
target/alpha: Convert to CPUClass::tlb_fill
target/arm: Convert to CPUClass::tlb_fill
target/cris: Convert to CPUClass::tlb_fill
target/hppa: Convert to CPUClass::tlb_fill
target/i386: Convert to CPUClass::tlb_fill
target/lm32: Convert to CPUClass::tlb_fill
target/m68k: Convert to CPUClass::tlb_fill
target/microblaze: Convert to CPUClass::tlb_fill
target/mips: Pass a valid error to raise_mmu_exception for user-only
target/mips: Tidy control flow in mips_cpu_handle_mmu_fault
target/mips: Convert to CPUClass::tlb_fill
target/moxie: Convert to CPUClass::tlb_fill
target/nios2: Convert to CPUClass::tlb_fill
target/openrisc: Convert to CPUClass::tlb_fill
target/ppc: Convert to CPUClass::tlb_fill
target/riscv: Convert to CPUClass::tlb_fill
target/s390x: Convert to CPUClass::tlb_fill
target/sh4: Convert to CPUClass::tlb_fill
target/sparc: Convert to CPUClass::tlb_fill
target/tilegx: Convert to CPUClass::tlb_fill
target/tricore: Convert to CPUClass::tlb_fill
target/unicore32: Convert to CPUClass::tlb_fill
target/xtensa: Convert to CPUClass::tlb_fill
tcg: Use CPUClass::tlb_fill in cputlb.c
tcg: Remove CPUClass::handle_mmu_fault
tcg: Use tlb_fill probe from tlb_vaddr_to_host
include/exec/cpu_ldst.h | 50 ++-------
include/exec/exec-all.h | 9 --
include/qom/cpu.h | 12 +-
target/alpha/cpu.h | 5 +-
target/arm/internals.h | 10 +-
target/cris/cpu.h | 5 +-
target/hppa/cpu.h | 8 +-
target/i386/cpu.h | 5 +-
target/lm32/cpu.h | 5 +-
target/m68k/cpu.h | 5 +-
target/microblaze/cpu.h | 5 +-
target/mips/internal.h | 5 +-
target/moxie/cpu.h | 5 +-
target/nios2/cpu.h | 5 +-
target/openrisc/cpu.h | 5 +-
target/ppc/cpu.h | 7 +-
target/riscv/cpu.h | 5 +-
target/s390x/internal.h | 5 +-
target/sh4/cpu.h | 5 +-
target/sparc/cpu.h | 5 +-
target/tricore/cpu.h | 6 +-
target/unicore32/cpu.h | 5 +-
target/xtensa/cpu.h | 5 +-
accel/tcg/cputlb.c | 88 +++++++++++++--
accel/tcg/user-exec.c | 36 ++----
target/alpha/cpu.c | 5 +-
target/alpha/helper.c | 24 ++--
target/alpha/mem_helper.c | 16 ---
target/arm/cpu.c | 22 +---
target/arm/helper.c | 90 ++++++++-------
target/arm/op_helper.c | 29 +----
target/arm/sve_helper.c | 6 +-
target/cris/cpu.c | 5 +-
target/cris/helper.c | 61 ++++++-----
target/cris/op_helper.c | 28 -----
target/hppa/cpu.c | 5 +-
target/hppa/mem_helper.c | 16 ++-
target/i386/cpu.c | 5 +-
target/i386/excp_helper.c | 53 +++++----
target/i386/mem_helper.c | 21 ----
target/lm32/cpu.c | 5 +-
target/lm32/helper.c | 8 +-
target/lm32/op_helper.c | 16 ---
target/m68k/cpu.c | 2 +-
target/m68k/helper.c | 89 ++++++++-------
target/m68k/op_helper.c | 15 ---
target/microblaze/cpu.c | 5 +-
target/microblaze/helper.c | 101 ++++++++---------
target/microblaze/op_helper.c | 19 ----
target/mips/cpu.c | 5 +-
target/mips/helper.c | 81 ++++++--------
target/mips/op_helper.c | 15 ---
target/moxie/cpu.c | 5 +-
target/moxie/helper.c | 65 +++--------
target/nios2/cpu.c | 5 +-
target/nios2/helper.c | 166 ++++++++++++++--------------
target/nios2/mmu.c | 12 --
target/openrisc/cpu.c | 5 +-
target/openrisc/mmu.c | 69 ++++++------
target/ppc/mmu_helper.c | 16 ++-
target/ppc/translate_init.inc.c | 5 +-
target/ppc/user_only_helper.c | 14 ++-
target/riscv/cpu.c | 5 +-
target/riscv/cpu_helper.c | 50 ++++-----
target/s390x/cpu.c | 5 +-
target/s390x/excp_helper.c | 67 +++++++----
target/s390x/mem_helper.c | 16 ---
target/sh4/cpu.c | 5 +-
target/sh4/helper.c | 189 +++++++++++++++-----------------
target/sh4/op_helper.c | 12 --
target/sparc/cpu.c | 5 +-
target/sparc/ldst_helper.c | 15 ---
target/sparc/mmu_helper.c | 78 +++++++------
target/tilegx/cpu.c | 10 +-
target/tricore/cpu.c | 1 +
target/tricore/helper.c | 23 ++--
target/tricore/op_helper.c | 26 -----
target/unicore32/cpu.c | 5 +-
target/unicore32/helper.c | 23 ----
target/unicore32/op_helper.c | 14 ---
target/unicore32/softmmu.c | 13 ++-
target/xtensa/cpu.c | 5 +-
target/xtensa/helper.c | 33 +++---
83 files changed, 876 insertions(+), 1139 deletions(-)
--
2.17.1
^ permalink raw reply [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 01/27] tcg: Add CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 17:39 ` Alistair Francis
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 02/27] target/alpha: Convert to CPUClass::tlb_fill Richard Henderson
` (25 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
This hook will replace the (user-only mode specific) handle_mmu_fault
hook, and the (system mode specific) tlb_fill function.
The handle_mmu_fault hook was written as if there was a valid
way to recover from an mmu fault, and had 3 possible return states.
In reality, the only valid action is to raise an exception,
return to the main loop, and deliver the SIGSEGV to the guest.
Note that all of the current implementations of handle_mmu_fault
for guests which support linux-user do in fact only ever return 1,
which is the signal to return to the main loop.
Using the hook for system mode requires that all targets be converted,
so for now the hook is (optionally) used only from user-only mode.
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/qom/cpu.h | 9 +++++++++
accel/tcg/user-exec.c | 39 ++++++++++++++-------------------------
2 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 08abcbd3fe..c1f267b4e0 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -118,6 +118,12 @@ struct TranslationBlock;
* will need to do more. If this hook is not implemented then the
* default is to call @set_pc(tb->pc).
* @handle_mmu_fault: Callback for handling an MMU fault.
+ * @tlb_fill: Callback for handling a softmmu tlb miss or user-only
+ * address fault. For system mode, if the access is valid, call
+ * tlb_set_page and return true; if the access is invalid, and
+ * probe is true, return false; otherwise raise an exception and
+ * do not return. For user-only mode, always raise an exception
+ * and do not return.
* @get_phys_page_debug: Callback for obtaining a physical address.
* @get_phys_page_attrs_debug: Callback for obtaining a physical address and the
* associated memory transaction attributes to use for the access.
@@ -191,6 +197,9 @@ typedef struct CPUClass {
void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int size, int rw,
int mmu_index);
+ bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
MemTxAttrs *attrs);
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 0789984fe6..199f88c826 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -65,6 +65,7 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
CPUClass *cc;
int ret;
unsigned long address = (unsigned long)info->si_addr;
+ MMUAccessType access_type;
/* We must handle PC addresses from two different sources:
* a call return address and a signal frame address.
@@ -147,35 +148,23 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
are still valid segv ones */
address = h2g_nocheck(address);
- cc = CPU_GET_CLASS(cpu);
- /* see if it is an MMU fault */
- g_assert(cc->handle_mmu_fault);
- ret = cc->handle_mmu_fault(cpu, address, 0, is_write, MMU_USER_IDX);
-
- if (ret == 0) {
- /* The MMU fault was handled without causing real CPU fault.
- * Retain helper_retaddr for a possible second fault.
- */
- return 1;
- }
-
- /* All other paths lead to cpu_exit; clear helper_retaddr
- * for next execution.
+ /*
+ * There is no way the target can handle this other than raising
+ * an exception. Undo signal and retaddr state prior to longjmp.
*/
+ sigprocmask(SIG_SETMASK, old_set, NULL);
helper_retaddr = 0;
- if (ret < 0) {
- return 0; /* not an MMU fault */
+ cc = CPU_GET_CLASS(cpu);
+ if (cc->tlb_fill) {
+ access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
+ cc->tlb_fill(cpu, address, 0, access_type, MMU_USER_IDX, false, pc);
+ g_assert_not_reached();
+ } else {
+ ret = cc->handle_mmu_fault(cpu, address, 0, is_write, MMU_USER_IDX);
+ g_assert(ret > 0);
+ cpu_loop_exit_restore(cpu, pc);
}
-
- /* Now we have a real cpu fault. */
- cpu_restore_state(cpu, pc, true);
-
- sigprocmask(SIG_SETMASK, old_set, NULL);
- cpu_loop_exit(cpu);
-
- /* never comes here */
- return 1;
}
#if defined(__i386__)
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 02/27] target/alpha: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 01/27] " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 03/27] target/arm: " Richard Henderson
` (24 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Keep user-only and system tlb_fill separate.
---
target/alpha/cpu.h | 5 +++--
target/alpha/cpu.c | 5 ++---
target/alpha/helper.c | 30 +++++++++++++++++++++---------
target/alpha/mem_helper.c | 16 ----------------
4 files changed, 26 insertions(+), 30 deletions(-)
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 63bf3618ff..cf09112b6a 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -475,8 +475,9 @@ void alpha_cpu_list(void);
is returned if the signal was handled by the virtual CPU. */
int cpu_alpha_signal_handler(int host_signum, void *pinfo,
void *puc);
-int alpha_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool alpha_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index ad3588a44a..7c81be4111 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -225,9 +225,8 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
cc->set_pc = alpha_cpu_set_pc;
cc->gdb_read_register = alpha_cpu_gdb_read_register;
cc->gdb_write_register = alpha_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = alpha_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = alpha_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_transaction_failed = alpha_cpu_do_transaction_failed;
cc->do_unaligned_access = alpha_cpu_do_unaligned_access;
cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
diff --git a/target/alpha/helper.c b/target/alpha/helper.c
index 7201576aae..929a217455 100644
--- a/target/alpha/helper.c
+++ b/target/alpha/helper.c
@@ -104,14 +104,15 @@ void cpu_alpha_store_gr(CPUAlphaState *env, unsigned reg, uint64_t val)
}
#if defined(CONFIG_USER_ONLY)
-int alpha_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
+bool alpha_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
cs->exception_index = EXCP_MMFAULT;
cpu->env.trap_arg0 = address;
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
#else
/* Returns the OSF/1 entMM failure indication, or -1 on success. */
@@ -248,26 +249,37 @@ hwaddr alpha_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
return (fail >= 0 ? -1 : phys);
}
-int alpha_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, int rw,
- int mmu_idx)
+bool alpha_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
target_ulong phys;
int prot, fail;
- fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot);
+ fail = get_physical_address(env, addr, 1 << access_type,
+ mmu_idx, &phys, &prot);
if (unlikely(fail >= 0)) {
+ if (probe) {
+ return false;
+ }
cs->exception_index = EXCP_MMFAULT;
env->trap_arg0 = addr;
env->trap_arg1 = fail;
- env->trap_arg2 = (rw == 2 ? -1 : rw);
- return 1;
+ env->trap_arg2 = (access_type == MMU_INST_FETCH ? -1 : access_type);
+ cpu_loop_exit_restore(cs, retaddr);
}
tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK,
prot, mmu_idx, TARGET_PAGE_SIZE);
- return 0;
+ return true;
+}
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ alpha_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
#endif /* USER_ONLY */
diff --git a/target/alpha/mem_helper.c b/target/alpha/mem_helper.c
index 011bc73dca..934faa1d6f 100644
--- a/target/alpha/mem_helper.c
+++ b/target/alpha/mem_helper.c
@@ -62,20 +62,4 @@ void alpha_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
env->error_code = 0;
cpu_loop_exit_restore(cs, retaddr);
}
-
-/* try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = alpha_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret != 0)) {
- /* Exception index and error code are already set */
- cpu_loop_exit_restore(cs, retaddr);
- }
-}
#endif /* CONFIG_USER_ONLY */
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 03/27] target/arm: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 01/27] " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 02/27] target/alpha: Convert to CPUClass::tlb_fill Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 04/27] target/cris: " Richard Henderson
` (23 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Cc: qemu-arm@nongnu.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Reword a comment to match the new interface.
---
target/arm/internals.h | 10 +++--
target/arm/cpu.c | 22 +---------
target/arm/helper.c | 98 ++++++++++++++++++++++++++----------------
target/arm/op_helper.c | 29 ++-----------
4 files changed, 73 insertions(+), 86 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 587a1ddf58..5a02f458f3 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -761,10 +761,12 @@ static inline bool arm_extabort_type(MemTxResult result)
return result != MEMTX_DECODE_ERROR;
}
-/* Do a page table walk and add page to TLB if possible */
-bool arm_tlb_fill(CPUState *cpu, vaddr address,
- MMUAccessType access_type, int mmu_idx,
- ARMMMUFaultInfo *fi);
+bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
+
+void arm_deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type,
+ int mmu_idx, ARMMMUFaultInfo *fi) QEMU_NORETURN;
/* Return true if the stage 1 translation regime is using LPAE format page
* tables */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index a181fa8dc1..bb8e824c3e 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2133,23 +2133,6 @@ static Property arm_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST()
};
-#ifdef CONFIG_USER_ONLY
-static int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
-{
- ARMCPU *cpu = ARM_CPU(cs);
- CPUARMState *env = &cpu->env;
-
- env->exception.vaddress = address;
- if (rw == 2) {
- cs->exception_index = EXCP_PREFETCH_ABORT;
- } else {
- cs->exception_index = EXCP_DATA_ABORT;
- }
- return 1;
-}
-#endif
-
static gchar *arm_gdb_arch_name(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
@@ -2182,9 +2165,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->synchronize_from_tb = arm_cpu_synchronize_from_tb;
cc->gdb_read_register = arm_cpu_gdb_read_register;
cc->gdb_write_register = arm_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = arm_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = arm_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_interrupt = arm_cpu_do_interrupt;
cc->do_unaligned_access = arm_cpu_do_unaligned_access;
cc->do_transaction_failed = arm_cpu_do_transaction_failed;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 1e6eb0d0f3..f1a2b94ddb 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -12596,43 +12596,6 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
}
}
-/* Walk the page table and (if the mapping exists) add the page
- * to the TLB. Return false on success, or true on failure. Populate
- * fsr with ARM DFSR/IFSR fault register format value on failure.
- */
-bool arm_tlb_fill(CPUState *cs, vaddr address,
- MMUAccessType access_type, int mmu_idx,
- ARMMMUFaultInfo *fi)
-{
- ARMCPU *cpu = ARM_CPU(cs);
- CPUARMState *env = &cpu->env;
- hwaddr phys_addr;
- target_ulong page_size;
- int prot;
- int ret;
- MemTxAttrs attrs = {};
-
- ret = get_phys_addr(env, address, access_type,
- core_to_arm_mmu_idx(env, mmu_idx), &phys_addr,
- &attrs, &prot, &page_size, fi, NULL);
- if (!ret) {
- /*
- * Map a single [sub]page. Regions smaller than our declared
- * target page size are handled specially, so for those we
- * pass in the exact addresses.
- */
- if (page_size >= TARGET_PAGE_SIZE) {
- phys_addr &= TARGET_PAGE_MASK;
- address &= TARGET_PAGE_MASK;
- }
- tlb_set_page_with_attrs(cs, address, phys_addr, attrs,
- prot, mmu_idx, page_size);
- return 0;
- }
-
- return ret;
-}
-
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
MemTxAttrs *attrs)
{
@@ -13111,6 +13074,67 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
#endif
+bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+
+#ifdef CONFIG_USER_ONLY
+ cpu->env.exception.vaddress = address;
+ if (access_type == MMU_INST_FETCH) {
+ cs->exception_index = EXCP_PREFETCH_ABORT;
+ } else {
+ cs->exception_index = EXCP_DATA_ABORT;
+ }
+ cpu_loop_exit_restore(cs, retaddr);
+#else
+ hwaddr phys_addr;
+ target_ulong page_size;
+ int prot, ret;
+ MemTxAttrs attrs = {};
+ ARMMMUFaultInfo fi = {};
+
+ /*
+ * Walk the page table and (if the mapping exists) add the page
+ * to the TLB. On success, return true. Otherwise, if probing,
+ * return false. Otherwise populate fsr with ARM DFSR/IFSR fault
+ * register format, and signal the fault.
+ */
+ ret = get_phys_addr(&cpu->env, address, access_type,
+ core_to_arm_mmu_idx(&cpu->env, mmu_idx),
+ &phys_addr, &attrs, &prot, &page_size, &fi, NULL);
+ if (likely(!ret)) {
+ /*
+ * Map a single [sub]page. Regions smaller than our declared
+ * target page size are handled specially, so for those we
+ * pass in the exact addresses.
+ */
+ if (page_size >= TARGET_PAGE_SIZE) {
+ phys_addr &= TARGET_PAGE_MASK;
+ address &= TARGET_PAGE_MASK;
+ }
+ tlb_set_page_with_attrs(cs, address, phys_addr, attrs,
+ prot, mmu_idx, page_size);
+ return true;
+ } else if (probe) {
+ return false;
+ } else {
+ /* now we have a real cpu fault */
+ cpu_restore_state(cs, retaddr, true);
+ arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi);
+ }
+#endif
+}
+
+#ifndef CONFIG_USER_ONLY
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ arm_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
+}
+#endif
+
void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
{
/* Implement DC ZVA, which zeroes a fixed-length block of memory.
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 8698b4dc83..8ee15a4bd4 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -126,8 +126,8 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
return syn;
}
-static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type,
- int mmu_idx, ARMMMUFaultInfo *fi)
+void arm_deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type,
+ int mmu_idx, ARMMMUFaultInfo *fi)
{
CPUARMState *env = &cpu->env;
int target_el;
@@ -179,27 +179,6 @@ static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type,
raise_exception(env, exc, syn, target_el);
}
-/* try to fill the TLB and return an exception if error. If retaddr is
- * NULL, it means that the function was called in C code (i.e. not
- * from generated code or from helper.c)
- */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- bool ret;
- ARMMMUFaultInfo fi = {};
-
- ret = arm_tlb_fill(cs, addr, access_type, mmu_idx, &fi);
- if (unlikely(ret)) {
- ARMCPU *cpu = ARM_CPU(cs);
-
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr, true);
-
- deliver_fault(cpu, addr, access_type, mmu_idx, &fi);
- }
-}
-
/* Raise a data fault alignment exception for the specified virtual address */
void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
MMUAccessType access_type,
@@ -212,7 +191,7 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
cpu_restore_state(cs, retaddr, true);
fi.type = ARMFault_Alignment;
- deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
+ arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
}
/* arm_cpu_do_transaction_failed: handle a memory system error response
@@ -233,7 +212,7 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
fi.ea = arm_extabort_type(response);
fi.type = ARMFault_SyncExternal;
- deliver_fault(cpu, addr, access_type, mmu_idx, &fi);
+ arm_deliver_fault(cpu, addr, access_type, mmu_idx, &fi);
}
#endif /* !defined(CONFIG_USER_ONLY) */
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 04/27] target/cris: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (2 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 03/27] target/arm: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 05/27] target/hppa: " Richard Henderson
` (22 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Edgar E . Iglesias
Remove dumping of cpu state. Remove logging of PC, as that
value is garbage until cpu_restore_state.
Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/cpu.h | 5 +--
target/cris/cpu.c | 5 ++-
target/cris/helper.c | 67 +++++++++++++++++++++++------------------
target/cris/op_helper.c | 28 -----------------
4 files changed, 42 insertions(+), 63 deletions(-)
diff --git a/target/cris/cpu.h b/target/cris/cpu.h
index 0fbe771639..857de79e24 100644
--- a/target/cris/cpu.h
+++ b/target/cris/cpu.h
@@ -281,8 +281,9 @@ static inline int cpu_mmu_index (CPUCRISState *env, bool ifetch)
return !!(env->pregs[PR_CCS] & U_FLAG);
}
-int cris_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
/* Support function regs. */
#define SFR_RW_GC_CFG 0][0
diff --git a/target/cris/cpu.c b/target/cris/cpu.c
index 75729bfdd5..4e5288ae80 100644
--- a/target/cris/cpu.c
+++ b/target/cris/cpu.c
@@ -269,9 +269,8 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->set_pc = cris_cpu_set_pc;
cc->gdb_read_register = cris_cpu_gdb_read_register;
cc->gdb_write_register = cris_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = cris_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = cris_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = cris_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_cris_cpu;
#endif
diff --git a/target/cris/helper.c b/target/cris/helper.c
index 3939603c73..69464837c8 100644
--- a/target/cris/helper.c
+++ b/target/cris/helper.c
@@ -24,6 +24,7 @@
#include "qemu/host-utils.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
+#include "exec/helper-proto.h"
//#define CRIS_HELPER_DEBUG
@@ -53,15 +54,15 @@ void crisv10_cpu_do_interrupt(CPUState *cs)
cris_cpu_do_interrupt(cs);
}
-int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
CRISCPU *cpu = CRIS_CPU(cs);
cs->exception_index = 0xaa;
cpu->env.pregs[PR_EDA] = address;
- cpu_dump_state(cs, stderr, 0);
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
#else /* !CONFIG_USER_ONLY */
@@ -76,33 +77,19 @@ static void cris_shift_ccs(CPUCRISState *env)
env->pregs[PR_CCS] = ccs;
}
-int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;
struct cris_mmu_result res;
int prot, miss;
- int r = -1;
target_ulong phy;
- qemu_log_mask(CPU_LOG_MMU, "%s addr=%" VADDR_PRIx " pc=%x rw=%x\n",
- __func__, address, env->pc, rw);
miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
- rw, mmu_idx, 0);
- if (miss) {
- if (cs->exception_index == EXCP_BUSFAULT) {
- cpu_abort(cs,
- "CRIS: Illegal recursive bus fault."
- "addr=%" VADDR_PRIx " rw=%d\n",
- address, rw);
- }
-
- env->pregs[PR_EDA] = address;
- cs->exception_index = EXCP_BUSFAULT;
- env->fault_vector = res.bf_vec;
- r = 1;
- } else {
+ access_type, mmu_idx, 0);
+ if (likely(!miss)) {
/*
* Mask off the cache selection bit. The ETRAX busses do not
* see the top bit.
@@ -111,15 +98,35 @@ int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
prot = res.prot;
tlb_set_page(cs, address & TARGET_PAGE_MASK, phy,
prot, mmu_idx, TARGET_PAGE_SIZE);
- r = 0;
+ return true;
}
- if (r > 0) {
- qemu_log_mask(CPU_LOG_MMU,
- "%s returns %d irqreq=%x addr=%" VADDR_PRIx " phy=%x vec=%x"
- " pc=%x\n", __func__, r, cs->interrupt_request, address,
- res.phy, res.bf_vec, env->pc);
+
+ if (probe) {
+ return false;
}
- return r;
+
+ if (cs->exception_index == EXCP_BUSFAULT) {
+ cpu_abort(cs, "CRIS: Illegal recursive bus fault."
+ "addr=%" VADDR_PRIx " access_type=%d\n",
+ address, access_type);
+ }
+
+ env->pregs[PR_EDA] = address;
+ cs->exception_index = EXCP_BUSFAULT;
+ env->fault_vector = res.bf_vec;
+ if (retaddr) {
+ if (cpu_restore_state(cs, retaddr, true)) {
+ /* Evaluate flags after retranslation. */
+ helper_top_evaluate_flags(env);
+ }
+ }
+ cpu_loop_exit(cs);
+}
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ cris_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
void crisv10_cpu_do_interrupt(CPUState *cs)
diff --git a/target/cris/op_helper.c b/target/cris/op_helper.c
index 0ee3a3117b..26a395b413 100644
--- a/target/cris/op_helper.c
+++ b/target/cris/op_helper.c
@@ -37,34 +37,6 @@
#define D_LOG(...) do { } while (0)
#endif
-#if !defined(CONFIG_USER_ONLY)
-/* Try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- CRISCPU *cpu = CRIS_CPU(cs);
- CPUCRISState *env = &cpu->env;
- int ret;
-
- D_LOG("%s pc=%x tpc=%x ra=%p\n", __func__,
- env->pc, env->pregs[PR_EDA], (void *)retaddr);
- ret = cris_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret)) {
- if (retaddr) {
- /* now we have a real cpu fault */
- if (cpu_restore_state(cs, retaddr, true)) {
- /* Evaluate flags after retranslation. */
- helper_top_evaluate_flags(env);
- }
- }
- cpu_loop_exit(cs);
- }
-}
-
-#endif
-
void helper_raise_exception(CPUCRISState *env, uint32_t index)
{
CPUState *cs = CPU(cris_env_get_cpu(env));
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 05/27] target/hppa: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (3 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 04/27] target/cris: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 06/27] target/i386: " Richard Henderson
` (21 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/hppa/cpu.h | 8 ++++----
target/hppa/cpu.c | 5 ++---
target/hppa/mem_helper.c | 22 +++++++++++++++++-----
3 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 923346adb6..c1e0215e66 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -360,10 +360,10 @@ 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, int);
-#ifdef CONFIG_USER_ONLY
-int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size,
- int rw, int midx);
-#else
+bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
+#ifndef CONFIG_USER_ONLY
int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
int type, hwaddr *pphys, int *pprot);
extern const MemoryRegionOps hppa_io_eir_ops;
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index e64f48581e..9717ea1798 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -163,9 +163,8 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
cc->synchronize_from_tb = hppa_cpu_synchronize_from_tb;
cc->gdb_read_register = hppa_cpu_gdb_read_register;
cc->gdb_write_register = hppa_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = hppa_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = hppa_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_hppa_cpu;
#endif
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 77fb544838..5cee0c19b1 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -25,8 +25,9 @@
#include "trace.h"
#ifdef CONFIG_USER_ONLY
-int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
- int size, int rw, int mmu_idx)
+bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
HPPACPU *cpu = HPPA_CPU(cs);
@@ -34,7 +35,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
which would affect si_code. */
cs->exception_index = EXCP_DMP;
cpu->env.cr[CR_IOR] = address;
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
#else
static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, vaddr addr)
@@ -213,8 +214,9 @@ hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
return excp == EXCP_DTLB_MISS ? -1 : phys;
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType type, int mmu_idx, uintptr_t retaddr)
+bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
+ MMUAccessType type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env;
@@ -236,6 +238,9 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
excp = hppa_get_physical_address(env, addr, mmu_idx,
a_prot, &phys, &prot);
if (unlikely(excp >= 0)) {
+ if (probe) {
+ return false;
+ }
trace_hppa_tlb_fill_excp(env, addr, size, type, mmu_idx);
/* Failure. Raise the indicated exception. */
cs->exception_index = excp;
@@ -252,6 +257,13 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
/* Success! Store the translation into the QEMU TLB. */
tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK,
prot, mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+}
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType type, int mmu_idx, uintptr_t retaddr)
+{
+ hppa_cpu_tlb_fill(cs, addr, size, type, mmu_idx, false, retaddr);
}
/* Insert (Insn/Data) TLB Address. Note this is PA 1.1 only. */
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 06/27] target/i386: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (4 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 05/27] target/hppa: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 07/27] target/lm32: " Richard Henderson
` (20 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, Eduardo Habkost
We do not support probing, but we do not need it yet either.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/cpu.h | 5 ++--
target/i386/cpu.c | 5 ++--
target/i386/excp_helper.c | 61 +++++++++++++++++++++++++--------------
target/i386/mem_helper.c | 21 --------------
4 files changed, 44 insertions(+), 48 deletions(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 0128910661..fce6660bac 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1656,8 +1656,9 @@ void host_cpuid(uint32_t function, uint32_t count,
void host_vendor_fms(char *vendor, int *family, int *model, int *stepping);
/* helper.c */
-int x86_cpu_handle_mmu_fault(CPUState *cpu, vaddr addr, int size,
- int is_write, int mmu_idx);
+bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
void x86_cpu_set_a20(X86CPU *cpu, int a20_state);
#ifndef CONFIG_USER_ONLY
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 722c5514d4..3c98869577 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5915,9 +5915,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->gdb_write_register = x86_cpu_gdb_write_register;
cc->get_arch_id = x86_cpu_get_arch_id;
cc->get_paging_enabled = x86_cpu_get_paging_enabled;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = x86_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = x86_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->asidx_from_attrs = x86_asidx_from_attrs;
cc->get_memory_mapping = x86_cpu_get_memory_mapping;
cc->get_phys_page_debug = x86_cpu_get_phys_page_debug;
diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c
index 49231f6b69..68bf8e3f7c 100644
--- a/target/i386/excp_helper.c
+++ b/target/i386/excp_helper.c
@@ -137,26 +137,7 @@ void raise_exception_ra(CPUX86State *env, int exception_index, uintptr_t retaddr
raise_interrupt2(env, exception_index, 0, 0, 0, retaddr);
}
-#if defined(CONFIG_USER_ONLY)
-int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size,
- int is_write, int mmu_idx)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
-
- /* user mode only emulation */
- is_write &= 1;
- env->cr[2] = addr;
- env->error_code = (is_write << PG_ERROR_W_BIT);
- env->error_code |= PG_ERROR_U_MASK;
- cs->exception_index = EXCP0E_PAGE;
- env->exception_is_int = 0;
- env->exception_next_eip = -1;
- return 1;
-}
-
-#else
-
+#if !defined(CONFIG_USER_ONLY)
static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type,
int *prot)
{
@@ -365,8 +346,8 @@ static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type,
* 0 = nothing more to do
* 1 = generate PF fault
*/
-int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size,
- int is_write1, int mmu_idx)
+static int handle_mmu_fault(CPUState *cs, vaddr addr, int size,
+ int is_write1, int mmu_idx)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
@@ -691,3 +672,39 @@ do_check_protect_pse36:
return 1;
}
#endif
+
+bool x86_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+#ifdef CONFIG_USER_ONLY
+ /* user mode only emulation */
+ env->cr[2] = addr;
+ env->error_code = (access_type == MMU_DATA_STORE) << PG_ERROR_W_BIT;
+ env->error_code |= PG_ERROR_U_MASK;
+ cs->exception_index = EXCP0E_PAGE;
+ env->exception_is_int = 0;
+ env->exception_next_eip = -1;
+ cpu_loop_exit_restore(cs, retaddr);
+#else
+ env->retaddr = retaddr;
+ if (handle_mmu_fault(cs, addr, size, access_type, mmu_idx)) {
+ /* FIXME: On error in get_hphys we have already jumped out. */
+ g_assert(!probe);
+ raise_exception_err_ra(env, cs->exception_index,
+ env->error_code, retaddr);
+ }
+ return true;
+#endif
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ x86_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
+}
+#endif
diff --git a/target/i386/mem_helper.c b/target/i386/mem_helper.c
index 6cc53bcb40..1885df29d2 100644
--- a/target/i386/mem_helper.c
+++ b/target/i386/mem_helper.c
@@ -191,24 +191,3 @@ void helper_boundl(CPUX86State *env, target_ulong a0, int v)
raise_exception_ra(env, EXCP05_BOUND, GETPC());
}
}
-
-#if !defined(CONFIG_USER_ONLY)
-/* try to fill the TLB and return an exception if error. If retaddr is
- * NULL, it means that the function was called in C code (i.e. not
- * from generated code or from helper.c)
- */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- int ret;
-
- env->retaddr = retaddr;
- ret = x86_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (ret) {
- raise_exception_err_ra(env, cs->exception_index, env->error_code, retaddr);
- }
-}
-#endif
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 07/27] target/lm32: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (5 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 06/27] target/i386: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 08/27] target/m68k: " Richard Henderson
` (19 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Walle
Cc: Michael Walle <michael@walle.cc>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/lm32/cpu.h | 5 +++--
target/lm32/cpu.c | 5 ++---
target/lm32/helper.c | 12 +++++++++---
target/lm32/op_helper.c | 16 ----------------
4 files changed, 14 insertions(+), 24 deletions(-)
diff --git a/target/lm32/cpu.h b/target/lm32/cpu.h
index 9b1e6c2d58..d224d4426e 100644
--- a/target/lm32/cpu.h
+++ b/target/lm32/cpu.h
@@ -261,8 +261,9 @@ bool lm32_cpu_do_semihosting(CPUState *cs);
#define cpu_list lm32_cpu_list
#define cpu_signal_handler cpu_lm32_signal_handler
-int lm32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
#include "exec/cpu-all.h"
diff --git a/target/lm32/cpu.c b/target/lm32/cpu.c
index 282da19994..57c50c1578 100644
--- a/target/lm32/cpu.c
+++ b/target/lm32/cpu.c
@@ -231,9 +231,8 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
cc->set_pc = lm32_cpu_set_pc;
cc->gdb_read_register = lm32_cpu_gdb_read_register;
cc->gdb_write_register = lm32_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = lm32_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = lm32_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_lm32_cpu;
#endif
diff --git a/target/lm32/helper.c b/target/lm32/helper.c
index a039a993ff..1db9a5562e 100644
--- a/target/lm32/helper.c
+++ b/target/lm32/helper.c
@@ -25,8 +25,9 @@
#include "exec/semihost.h"
#include "exec/log.h"
-int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
LM32CPU *cpu = LM32_CPU(cs);
CPULM32State *env = &cpu->env;
@@ -40,8 +41,13 @@ int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
} else {
tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
}
+ return true;
+}
- return 0;
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ lm32_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
hwaddr lm32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
diff --git a/target/lm32/op_helper.c b/target/lm32/op_helper.c
index 234d55e056..be12b11b02 100644
--- a/target/lm32/op_helper.c
+++ b/target/lm32/op_helper.c
@@ -143,21 +143,5 @@ uint32_t HELPER(rcsr_jrx)(CPULM32State *env)
{
return lm32_juart_get_jrx(env->juart_state);
}
-
-/* Try to fill the TLB and return an exception if error. If retaddr is
- * NULL, it means that the function was called in C code (i.e. not
- * from generated code or from helper.c)
- */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = lm32_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret)) {
- /* now we have a real cpu fault */
- cpu_loop_exit_restore(cs, retaddr);
- }
-}
#endif
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 08/27] target/m68k: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (6 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 07/27] target/lm32: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 09/27] target/microblaze: " Richard Henderson
` (18 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Cc: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/m68k/cpu.h | 5 ++-
target/m68k/cpu.c | 2 +-
target/m68k/helper.c | 87 ++++++++++++++++++++++-------------------
target/m68k/op_helper.c | 15 -------
4 files changed, 50 insertions(+), 59 deletions(-)
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index ad41608341..683d3e2f79 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -542,8 +542,9 @@ static inline int cpu_mmu_index (CPUM68KState *env, bool ifetch)
return (env->sr & SR_S) == 0 ? 1 : 0;
}
-int m68k_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
void m68k_cpu_unassigned_access(CPUState *cs, hwaddr addr,
bool is_write, bool is_exec, int is_asi,
unsigned size);
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 582e3a73b3..6f441bc973 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -269,7 +269,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
cc->set_pc = m68k_cpu_set_pc;
cc->gdb_read_register = m68k_cpu_gdb_read_register;
cc->gdb_write_register = m68k_cpu_gdb_write_register;
- cc->handle_mmu_fault = m68k_cpu_handle_mmu_fault;
+ cc->tlb_fill = m68k_cpu_tlb_fill;
#if defined(CONFIG_SOFTMMU)
cc->do_unassigned_access = m68k_cpu_unassigned_access;
cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
index d958a34959..862f955f7b 100644
--- a/target/m68k/helper.c
+++ b/target/m68k/helper.c
@@ -353,20 +353,7 @@ void m68k_switch_sp(CPUM68KState *env)
env->current_sp = new_sp;
}
-#if defined(CONFIG_USER_ONLY)
-
-int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
-{
- M68kCPU *cpu = M68K_CPU(cs);
-
- cs->exception_index = EXCP_ACCESS;
- cpu->env.mmu.ar = address;
- return 1;
-}
-
-#else
-
+#if !defined(CONFIG_USER_ONLY)
/* MMU: 68040 only */
static void print_address_zone(uint32_t logical, uint32_t physical,
@@ -795,11 +782,36 @@ hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
return phys_addr;
}
-int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+/*
+ * Notify CPU of a pending interrupt. Prioritization and vectoring should
+ * be handled by the interrupt controller. Real hardware only requests
+ * the vector when the interrupt is acknowledged by the CPU. For
+ * simplicity we calculate it when the interrupt is signalled.
+ */
+void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
+{
+ CPUState *cs = CPU(cpu);
+ CPUM68KState *env = &cpu->env;
+
+ env->pending_level = level;
+ env->pending_vector = vector;
+ if (level) {
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ }
+}
+
+#endif
+
+bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType qemu_access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
M68kCPU *cpu = M68K_CPU(cs);
CPUM68KState *env = &cpu->env;
+
+#ifndef CONFIG_USER_ONLY
hwaddr physical;
int prot;
int access_type;
@@ -812,32 +824,35 @@ int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
address & TARGET_PAGE_MASK,
PAGE_READ | PAGE_WRITE | PAGE_EXEC,
mmu_idx, TARGET_PAGE_SIZE);
- return 0;
+ return true;
}
- if (rw == 2) {
+ if (qemu_access_type == MMU_INST_FETCH) {
access_type = ACCESS_CODE;
- rw = 0;
} else {
access_type = ACCESS_DATA;
- if (rw) {
+ if (qemu_access_type == MMU_DATA_STORE) {
access_type |= ACCESS_STORE;
}
}
-
if (mmu_idx != MMU_USER_IDX) {
access_type |= ACCESS_SUPER;
}
ret = get_physical_address(&cpu->env, &physical, &prot,
address, access_type, &page_size);
- if (ret == 0) {
+ if (likely(ret == 0)) {
address &= TARGET_PAGE_MASK;
physical += address & (page_size - 1);
tlb_set_page(cs, address, physical,
prot, mmu_idx, TARGET_PAGE_SIZE);
- return 0;
+ return true;
}
+
+ if (probe) {
+ return false;
+ }
+
/* page fault */
env->mmu.ssw = M68K_ATC_040;
switch (size) {
@@ -862,29 +877,19 @@ int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
if (!(access_type & ACCESS_STORE)) {
env->mmu.ssw |= M68K_RW_040;
}
- env->mmu.ar = address;
+#endif
+
cs->exception_index = EXCP_ACCESS;
- return 1;
+ env->mmu.ar = address;
+ cpu_loop_exit_restore(cs, retaddr);
}
-/* Notify CPU of a pending interrupt. Prioritization and vectoring should
- be handled by the interrupt controller. Real hardware only requests
- the vector when the interrupt is acknowledged by the CPU. For
- simplicitly we calculate it when the interrupt is signalled. */
-void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
+#ifndef CONFIG_USER_ONLY
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
- CPUState *cs = CPU(cpu);
- CPUM68KState *env = &cpu->env;
-
- env->pending_level = level;
- env->pending_vector = vector;
- if (level) {
- cpu_interrupt(cs, CPU_INTERRUPT_HARD);
- } else {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
- }
+ m68k_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
-
#endif
uint32_t HELPER(bitrev)(uint32_t x)
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 76f439985a..d421614727 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -36,21 +36,6 @@ static inline void do_interrupt_m68k_hardirq(CPUM68KState *env)
#else
-/* Try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = m68k_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret)) {
- /* now we have a real cpu fault */
- cpu_loop_exit_restore(cs, retaddr);
- }
-}
-
static void cf_rte(CPUM68KState *env)
{
uint32_t sp;
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 09/27] target/microblaze: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (7 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 08/27] target/m68k: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 9:59 ` Peter Maydell
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 10/27] target/mips: Pass a valid error to raise_mmu_exception for user-only Richard Henderson
` (17 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Edgar E . Iglesias
Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Keep user-only and system tlb_fill separate.
---
target/microblaze/cpu.h | 5 +-
target/microblaze/cpu.c | 5 +-
target/microblaze/helper.c | 107 ++++++++++++++++++----------------
target/microblaze/op_helper.c | 19 ------
4 files changed, 62 insertions(+), 74 deletions(-)
diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index f20e796865..7a9fb8f4aa 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -374,8 +374,9 @@ static inline int cpu_mmu_index (CPUMBState *env, bool ifetch)
return MMU_KERNEL_IDX;
}
-int mb_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
#include "exec/cpu-all.h"
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 5596cd5485..0ea549910b 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -304,9 +304,8 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
cc->set_pc = mb_cpu_set_pc;
cc->gdb_read_register = mb_cpu_gdb_read_register;
cc->gdb_write_register = mb_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = mb_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = mb_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_transaction_failed = mb_cpu_transaction_failed;
cc->get_phys_page_debug = mb_cpu_get_phys_page_debug;
#endif
diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c
index 9848e31d7f..a523c77959 100644
--- a/target/microblaze/helper.c
+++ b/target/microblaze/helper.c
@@ -38,73 +38,80 @@ void mb_cpu_do_interrupt(CPUState *cs)
env->regs[14] = env->sregs[SR_PC];
}
-int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
cs->exception_index = 0xaa;
- cpu_dump_state(cs, stderr, 0);
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
#else /* !CONFIG_USER_ONLY */
-int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;
+ struct microblaze_mmu_lookup lu;
unsigned int hit;
- int r = 1;
int prot;
- /* Translate if the MMU is available and enabled. */
- if (mmu_idx != MMU_NOMMU_IDX) {
- uint32_t vaddr, paddr;
- struct microblaze_mmu_lookup lu;
-
- hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx);
- if (hit) {
- vaddr = address & TARGET_PAGE_MASK;
- paddr = lu.paddr + vaddr - lu.vaddr;
-
- qemu_log_mask(CPU_LOG_MMU, "MMU map mmu=%d v=%x p=%x prot=%x\n",
- mmu_idx, vaddr, paddr, lu.prot);
- tlb_set_page(cs, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE);
- r = 0;
- } else {
- env->sregs[SR_EAR] = address;
- qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n",
- mmu_idx, address);
-
- switch (lu.err) {
- case ERR_PROT:
- env->sregs[SR_ESR] = rw == 2 ? 17 : 16;
- env->sregs[SR_ESR] |= (rw == 1) << 10;
- break;
- case ERR_MISS:
- env->sregs[SR_ESR] = rw == 2 ? 19 : 18;
- env->sregs[SR_ESR] |= (rw == 1) << 10;
- break;
- default:
- abort();
- break;
- }
-
- if (cs->exception_index == EXCP_MMU) {
- cpu_abort(cs, "recursive faults\n");
- }
-
- /* TLB miss. */
- cs->exception_index = EXCP_MMU;
- }
- } else {
+ if (mmu_idx == MMU_NOMMU_IDX) {
/* MMU disabled or not available. */
address &= TARGET_PAGE_MASK;
prot = PAGE_BITS;
tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
- r = 0;
+ return true;
}
- return r;
+
+ hit = mmu_translate(&env->mmu, &lu, address, access_type, mmu_idx);
+ if (likely(hit)) {
+ uint32_t vaddr = address & TARGET_PAGE_MASK;
+ uint32_t paddr = lu.paddr + vaddr - lu.vaddr;
+
+ qemu_log_mask(CPU_LOG_MMU, "MMU map mmu=%d v=%x p=%x prot=%x\n",
+ mmu_idx, vaddr, paddr, lu.prot);
+ tlb_set_page(cs, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+ }
+
+ /* TLB miss. */
+ if (probe) {
+ return false;
+ }
+
+ qemu_log_mask(CPU_LOG_MMU, "mmu=%d miss v=%" VADDR_PRIx "\n",
+ mmu_idx, address);
+
+ env->sregs[SR_EAR] = address;
+ switch (lu.err) {
+ case ERR_PROT:
+ env->sregs[SR_ESR] = access_type == MMU_INST_FETCH ? 17 : 16;
+ env->sregs[SR_ESR] |= (access_type == MMU_DATA_STORE) << 10;
+ break;
+ case ERR_MISS:
+ env->sregs[SR_ESR] = access_type == MMU_INST_FETCH ? 19 : 18;
+ env->sregs[SR_ESR] |= (access_type == MMU_DATA_STORE) << 10;
+ break;
+ default:
+ abort();
+ }
+
+ if (cs->exception_index == EXCP_MMU) {
+ cpu_abort(cs, "recursive faults\n");
+ }
+
+ /* TLB miss. */
+ cs->exception_index = EXCP_MMU;
+ cpu_loop_exit_restore(cs, retaddr);
+}
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ mb_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
void mb_cpu_do_interrupt(CPUState *cs)
diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c
index e23dcfdc20..b5dbb90d05 100644
--- a/target/microblaze/op_helper.c
+++ b/target/microblaze/op_helper.c
@@ -28,25 +28,6 @@
#define D(x)
-#if !defined(CONFIG_USER_ONLY)
-
-/* Try to fill the TLB and return an exception if error. If retaddr is
- * NULL, it means that the function was called in C code (i.e. not
- * from generated code or from helper.c)
- */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = mb_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret)) {
- /* now we have a real cpu fault */
- cpu_loop_exit_restore(cs, retaddr);
- }
-}
-#endif
-
void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
{
int test = ctrl & STREAM_TEST;
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 10/27] target/mips: Pass a valid error to raise_mmu_exception for user-only
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (8 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 09/27] target/microblaze: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 9:45 ` Philippe Mathieu-Daudé
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 11/27] target/mips: Tidy control flow in mips_cpu_handle_mmu_fault Richard Henderson
` (16 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
At present we give ret = 0, or TLBRET_MATCH. This gets matched
by the default case, which falls through to TLBRET_BADADDR.
However, it makes more sense to use a proper value. All of the
tlb-related exceptions are handled identically in cpu_loop.c,
so TLBRET_BADADDR is as good as any other. Retain it.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/mips/helper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/mips/helper.c b/target/mips/helper.c
index c44cdca3b5..cc7be7703a 100644
--- a/target/mips/helper.c
+++ b/target/mips/helper.c
@@ -884,7 +884,7 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
int prot;
int access_type;
#endif
- int ret = 0;
+ int ret = TLBRET_BADADDR;
#if 0
log_cpu_state(cs, 0);
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 11/27] target/mips: Tidy control flow in mips_cpu_handle_mmu_fault
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (9 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 10/27] target/mips: Pass a valid error to raise_mmu_exception for user-only Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 10:01 ` Philippe Mathieu-Daudé
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 12/27] target/mips: Convert to CPUClass::tlb_fill Richard Henderson
` (15 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
Since the only non-negative TLBRET_* value is TLBRET_MATCH,
the subsequent test for ret < 0 is useless. Use early return
to allow subsequent blocks to be unindented.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/mips/helper.c | 54 ++++++++++++++++++++------------------------
1 file changed, 24 insertions(+), 30 deletions(-)
diff --git a/target/mips/helper.c b/target/mips/helper.c
index cc7be7703a..86e622efb8 100644
--- a/target/mips/helper.c
+++ b/target/mips/helper.c
@@ -915,41 +915,35 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
tlb_set_page(cs, address & TARGET_PAGE_MASK,
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
mmu_idx, TARGET_PAGE_SIZE);
- ret = 0;
- } else if (ret < 0)
-#endif
- {
-#if !defined(CONFIG_USER_ONLY)
+ return 0;
+ }
#if !defined(TARGET_MIPS64)
- if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) {
- /*
- * Memory reads during hardware page table walking are performed
- * as if they were kernel-mode load instructions.
- */
- int mode = (env->hflags & MIPS_HFLAG_KSU);
- bool ret_walker;
- env->hflags &= ~MIPS_HFLAG_KSU;
- ret_walker = page_table_walk_refill(env, address, rw, mmu_idx);
- env->hflags |= mode;
- if (ret_walker) {
- ret = get_physical_address(env, &physical, &prot,
- address, rw, access_type, mmu_idx);
- if (ret == TLBRET_MATCH) {
- tlb_set_page(cs, address & TARGET_PAGE_MASK,
- physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
- mmu_idx, TARGET_PAGE_SIZE);
- ret = 0;
- return ret;
- }
+ if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) {
+ /*
+ * Memory reads during hardware page table walking are performed
+ * as if they were kernel-mode load instructions.
+ */
+ int mode = (env->hflags & MIPS_HFLAG_KSU);
+ bool ret_walker;
+ env->hflags &= ~MIPS_HFLAG_KSU;
+ ret_walker = page_table_walk_refill(env, address, rw, mmu_idx);
+ env->hflags |= mode;
+ if (ret_walker) {
+ ret = get_physical_address(env, &physical, &prot,
+ address, rw, access_type, mmu_idx);
+ if (ret == TLBRET_MATCH) {
+ tlb_set_page(cs, address & TARGET_PAGE_MASK,
+ physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
+ mmu_idx, TARGET_PAGE_SIZE);
+ return 0;
}
}
-#endif
-#endif
- raise_mmu_exception(env, address, rw, ret);
- ret = 1;
}
+#endif
+#endif
- return ret;
+ raise_mmu_exception(env, address, rw, ret);
+ return 1;
}
#if !defined(CONFIG_USER_ONLY)
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 12/27] target/mips: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (10 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 11/27] target/mips: Tidy control flow in mips_cpu_handle_mmu_fault Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 9:50 ` Philippe Mathieu-Daudé
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 13/27] target/moxie: " Richard Henderson
` (14 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Aleksandar Rikalo, Aleksandar Markovic
Note that env->active_tc.PC is removed from the qemu_log as that value
is garbage. The PC isn't recovered until cpu_restore_state, called from
cpu_loop_exit_restore, called from do_raise_exception_err.
Cc: Aleksandar Markovic <amarkovic@wavecomp.com>
Cc: Aleksandar Rikalo <arikalo@wavecomp.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Split out other mips cleanups to simplify the diff
---
target/mips/internal.h | 5 +++--
target/mips/cpu.c | 5 ++---
target/mips/helper.c | 45 ++++++++++++++++++++++-------------------
target/mips/op_helper.c | 15 --------------
4 files changed, 29 insertions(+), 41 deletions(-)
diff --git a/target/mips/internal.h b/target/mips/internal.h
index 286e3888ab..b2b41a51ab 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -202,8 +202,9 @@ void cpu_mips_start_count(CPUMIPSState *env);
void cpu_mips_stop_count(CPUMIPSState *env);
/* helper.c */
-int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
/* op_helper.c */
uint32_t float_class_s(uint32_t arg, float_status *fst);
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index e217fb3e36..ebdb834b97 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -197,9 +197,8 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
cc->gdb_read_register = mips_cpu_gdb_read_register;
cc->gdb_write_register = mips_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = mips_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = mips_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_unassigned_access = mips_cpu_unassigned_access;
cc->do_unaligned_access = mips_cpu_do_unaligned_access;
cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
diff --git a/target/mips/helper.c b/target/mips/helper.c
index 86e622efb8..3a4917ce7b 100644
--- a/target/mips/helper.c
+++ b/target/mips/helper.c
@@ -874,31 +874,25 @@ refill:
#endif
#endif
-int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
#if !defined(CONFIG_USER_ONLY)
hwaddr physical;
int prot;
- int access_type;
+ int mips_access_type;
#endif
int ret = TLBRET_BADADDR;
-#if 0
- log_cpu_state(cs, 0);
-#endif
- qemu_log_mask(CPU_LOG_MMU,
- "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
- __func__, env->active_tc.PC, address, rw, mmu_idx);
-
/* data access */
#if !defined(CONFIG_USER_ONLY)
/* XXX: put correct access by using cpu_restore_state() correctly */
- access_type = ACCESS_INT;
- ret = get_physical_address(env, &physical, &prot,
- address, rw, access_type, mmu_idx);
+ mips_access_type = ACCESS_INT;
+ ret = get_physical_address(env, &physical, &prot, address,
+ access_type, mips_access_type, mmu_idx);
switch (ret) {
case TLBRET_MATCH:
qemu_log_mask(CPU_LOG_MMU,
@@ -915,7 +909,7 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
tlb_set_page(cs, address & TARGET_PAGE_MASK,
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
mmu_idx, TARGET_PAGE_SIZE);
- return 0;
+ return true;
}
#if !defined(TARGET_MIPS64)
if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) {
@@ -926,27 +920,36 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
int mode = (env->hflags & MIPS_HFLAG_KSU);
bool ret_walker;
env->hflags &= ~MIPS_HFLAG_KSU;
- ret_walker = page_table_walk_refill(env, address, rw, mmu_idx);
+ ret_walker = page_table_walk_refill(env, address, access_type, mmu_idx);
env->hflags |= mode;
if (ret_walker) {
- ret = get_physical_address(env, &physical, &prot,
- address, rw, access_type, mmu_idx);
+ ret = get_physical_address(env, &physical, &prot, address,
+ access_type, mips_access_type, mmu_idx);
if (ret == TLBRET_MATCH) {
tlb_set_page(cs, address & TARGET_PAGE_MASK,
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
mmu_idx, TARGET_PAGE_SIZE);
- return 0;
+ return true;
}
}
}
#endif
+ if (probe) {
+ return false;
+ }
#endif
- raise_mmu_exception(env, address, rw, ret);
- return 1;
+ raise_mmu_exception(env, address, access_type, ret);
+ do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr);
+}
+
+#ifndef CONFIG_USER_ONLY
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ mips_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
-#if !defined(CONFIG_USER_ONLY)
hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw)
{
hwaddr physical;
diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index 0f272a5b93..6d86912958 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -2669,21 +2669,6 @@ void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
do_raise_exception_err(env, excp, error_code, retaddr);
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = mips_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (ret) {
- MIPSCPU *cpu = MIPS_CPU(cs);
- CPUMIPSState *env = &cpu->env;
-
- do_raise_exception_err(env, cs->exception_index,
- env->error_code, retaddr);
- }
-}
-
void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr,
bool is_write, bool is_exec, int unused,
unsigned size)
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 13/27] target/moxie: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (11 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 12/27] target/mips: Convert to CPUClass::tlb_fill Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 14/27] target/nios2: " Richard Henderson
` (13 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Anthony Green
Remove the user-only functions, as we don't have a user-only config.
Fix the unconditional call to tlb_set_page, even if the translation
failed.
Cc: Anthony Green <green@moxielogic.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/moxie/cpu.h | 5 ++--
target/moxie/cpu.c | 5 ++--
target/moxie/helper.c | 61 ++++++++++---------------------------------
3 files changed, 19 insertions(+), 52 deletions(-)
diff --git a/target/moxie/cpu.h b/target/moxie/cpu.h
index f3b6d83ae7..a63a96bc05 100644
--- a/target/moxie/cpu.h
+++ b/target/moxie/cpu.h
@@ -139,7 +139,8 @@ static inline void cpu_get_tb_cpu_state(CPUMoxieState *env, target_ulong *pc,
*flags = 0;
}
-int moxie_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size,
- int rw, int mmu_idx);
+bool moxie_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
#endif /* MOXIE_CPU_H */
diff --git a/target/moxie/cpu.c b/target/moxie/cpu.c
index 46434e65ba..02b2b47574 100644
--- a/target/moxie/cpu.c
+++ b/target/moxie/cpu.c
@@ -112,9 +112,8 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
cc->do_interrupt = moxie_cpu_do_interrupt;
cc->dump_state = moxie_cpu_dump_state;
cc->set_pc = moxie_cpu_set_pc;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = moxie_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = moxie_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_moxie_cpu;
#endif
diff --git a/target/moxie/helper.c b/target/moxie/helper.c
index 287a45232c..216cef057e 100644
--- a/target/moxie/helper.c
+++ b/target/moxie/helper.c
@@ -26,18 +26,10 @@
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
-/* Try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
void tlb_fill(CPUState *cs, target_ulong addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
- int ret;
-
- ret = moxie_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret)) {
- cpu_loop_exit_restore(cs, retaddr);
- }
+ moxie_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
void helper_raise_exception(CPUMoxieState *env, int ex)
@@ -85,53 +77,29 @@ void helper_debug(CPUMoxieState *env)
cpu_loop_exit(cs);
}
-#if defined(CONFIG_USER_ONLY)
-
-void moxie_cpu_do_interrupt(CPUState *cs)
-{
- CPUState *cs = CPU(moxie_env_get_cpu(env));
-
- cs->exception_index = -1;
-}
-
-int moxie_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
-{
- MoxieCPU *cpu = MOXIE_CPU(cs);
-
- cs->exception_index = 0xaa;
- cpu->env.debug1 = address;
- cpu_dump_state(cs, stderr, 0);
- return 1;
-}
-
-#else /* !CONFIG_USER_ONLY */
-
-int moxie_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
+bool moxie_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
MoxieCPU *cpu = MOXIE_CPU(cs);
CPUMoxieState *env = &cpu->env;
MoxieMMUResult res;
int prot, miss;
- target_ulong phy;
- int r = 1;
address &= TARGET_PAGE_MASK;
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- miss = moxie_mmu_translate(&res, env, address, rw, mmu_idx);
- if (miss) {
- /* handle the miss. */
- phy = 0;
- cs->exception_index = MOXIE_EX_MMU_MISS;
- } else {
- phy = res.phy;
- r = 0;
+ miss = moxie_mmu_translate(&res, env, address, access_type, mmu_idx);
+ if (likely(!miss)) {
+ tlb_set_page(cs, address, res.phy, prot, mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+ }
+ if (probe) {
+ return false;
}
- tlb_set_page(cs, address, phy, prot, mmu_idx, TARGET_PAGE_SIZE);
- return r;
-}
+ cs->exception_index = MOXIE_EX_MMU_MISS;
+ cpu_loop_exit_restore(cs, retaddr);
+}
void moxie_cpu_do_interrupt(CPUState *cs)
{
@@ -156,4 +124,3 @@ hwaddr moxie_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
}
return phy;
}
-#endif
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 14/27] target/nios2: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (12 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 13/27] target/moxie: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 10:02 ` Peter Maydell
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 15/27] target/openrisc: " Richard Henderson
` (12 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Marek Vasut, Chris Wulff
Remove the leftover debugging cpu_dump_state.
Cc: Chris Wulff <crwulff@gmail.com>
Cc: Marek Vasut <marex@denx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Keep user-only and system tlb_fill separate.
---
target/nios2/cpu.h | 5 +-
target/nios2/cpu.c | 5 +-
target/nios2/helper.c | 172 +++++++++++++++++++++---------------------
target/nios2/mmu.c | 12 ---
4 files changed, 91 insertions(+), 103 deletions(-)
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 881e7d58c9..60a916b2e5 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -252,8 +252,9 @@ static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch)
MMU_SUPERVISOR_IDX;
}
-int nios2_cpu_handle_mmu_fault(CPUState *env, vaddr address, int size,
- int rw, int mmu_idx);
+bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
static inline int cpu_interrupts_enabled(CPUNios2State *env)
{
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index fbfaa2ce26..186af4913d 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -200,9 +200,8 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data)
cc->dump_state = nios2_cpu_dump_state;
cc->set_pc = nios2_cpu_set_pc;
cc->disas_set_info = nios2_cpu_disas_set_info;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = nios2_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = nios2_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_unaligned_access = nios2_cpu_do_unaligned_access;
cc->get_phys_page_debug = nios2_cpu_get_phys_page_debug;
#endif
diff --git a/target/nios2/helper.c b/target/nios2/helper.c
index e01fc1ff3e..72884e4260 100644
--- a/target/nios2/helper.c
+++ b/target/nios2/helper.c
@@ -38,15 +38,16 @@ void nios2_cpu_do_interrupt(CPUState *cs)
env->regs[R_EA] = env->regs[R_PC] + 4;
}
-int nios2_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
+bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
cs->exception_index = 0xaa;
/* Page 0x1000 is kuser helper */
if (address < 0x1000 || address >= 0x2000) {
cpu_dump_state(cs, stderr, 0);
}
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
#else /* !CONFIG_USER_ONLY */
@@ -203,89 +204,6 @@ void nios2_cpu_do_interrupt(CPUState *cs)
}
}
-static int cpu_nios2_handle_virtual_page(
- CPUState *cs, target_ulong address, int rw, int mmu_idx)
-{
- Nios2CPU *cpu = NIOS2_CPU(cs);
- CPUNios2State *env = &cpu->env;
- target_ulong vaddr, paddr;
- Nios2MMULookup lu;
- unsigned int hit;
- hit = mmu_translate(env, &lu, address, rw, mmu_idx);
- if (hit) {
- vaddr = address & TARGET_PAGE_MASK;
- paddr = lu.paddr + vaddr - lu.vaddr;
-
- if (((rw == 0) && (lu.prot & PAGE_READ)) ||
- ((rw == 1) && (lu.prot & PAGE_WRITE)) ||
- ((rw == 2) && (lu.prot & PAGE_EXEC))) {
-
- tlb_set_page(cs, vaddr, paddr, lu.prot,
- mmu_idx, TARGET_PAGE_SIZE);
- return 0;
- } else {
- /* Permission violation */
- cs->exception_index = (rw == 0) ? EXCP_TLBR :
- ((rw == 1) ? EXCP_TLBW :
- EXCP_TLBX);
- }
- } else {
- cs->exception_index = EXCP_TLBD;
- }
-
- if (rw == 2) {
- env->regs[CR_TLBMISC] &= ~CR_TLBMISC_D;
- } else {
- env->regs[CR_TLBMISC] |= CR_TLBMISC_D;
- }
- env->regs[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK;
- env->regs[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK;
- env->mmu.pteaddr_wr = env->regs[CR_PTEADDR];
- env->regs[CR_BADADDR] = address;
- return 1;
-}
-
-int nios2_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
-{
- Nios2CPU *cpu = NIOS2_CPU(cs);
- CPUNios2State *env = &cpu->env;
-
- if (cpu->mmu_present) {
- if (MMU_SUPERVISOR_IDX == mmu_idx) {
- if (address >= 0xC0000000) {
- /* Kernel physical page - TLB bypassed */
- address &= TARGET_PAGE_MASK;
- tlb_set_page(cs, address, address, PAGE_BITS,
- mmu_idx, TARGET_PAGE_SIZE);
- } else if (address >= 0x80000000) {
- /* Kernel virtual page */
- return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx);
- } else {
- /* User virtual page */
- return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx);
- }
- } else {
- if (address >= 0x80000000) {
- /* Illegal access from user mode */
- cs->exception_index = EXCP_SUPERA;
- env->regs[CR_BADADDR] = address;
- return 1;
- } else {
- /* User virtual page */
- return cpu_nios2_handle_virtual_page(cs, address, rw, mmu_idx);
- }
- }
- } else {
- /* No MMU */
- address &= TARGET_PAGE_MASK;
- tlb_set_page(cs, address, address, PAGE_BITS,
- mmu_idx, TARGET_PAGE_SIZE);
- }
-
- return 0;
-}
-
hwaddr nios2_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
Nios2CPU *cpu = NIOS2_CPU(cs);
@@ -321,4 +239,86 @@ void nios2_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
env->regs[CR_EXCEPTION] = EXCP_UNALIGN << 2;
helper_raise_exception(env, EXCP_UNALIGN);
}
+
+bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
+{
+ Nios2CPU *cpu = NIOS2_CPU(cs);
+ CPUNios2State *env = &cpu->env;
+ unsigned int excp = EXCP_TLBD;
+ target_ulong vaddr, paddr;
+ Nios2MMULookup lu;
+ unsigned int hit;
+
+ if (!cpu->mmu_present) {
+ /* No MMU */
+ address &= TARGET_PAGE_MASK;
+ tlb_set_page(cs, address, address, PAGE_BITS,
+ mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+ }
+
+ if (MMU_SUPERVISOR_IDX == mmu_idx) {
+ if (address >= 0xC0000000) {
+ /* Kernel physical page - TLB bypassed */
+ address &= TARGET_PAGE_MASK;
+ tlb_set_page(cs, address, address, PAGE_BITS,
+ mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+ }
+ } else {
+ if (address >= 0x80000000) {
+ /* Illegal access from user mode */
+ if (probe) {
+ return false;
+ }
+ cs->exception_index = EXCP_SUPERA;
+ env->regs[CR_BADADDR] = address;
+ cpu_loop_exit_restore(cs, retaddr);
+ }
+ }
+
+ /* Virtual page. */
+ hit = mmu_translate(env, &lu, address, access_type, mmu_idx);
+ if (hit) {
+ vaddr = address & TARGET_PAGE_MASK;
+ paddr = lu.paddr + vaddr - lu.vaddr;
+
+ if (((access_type == MMU_DATA_LOAD) && (lu.prot & PAGE_READ)) ||
+ ((access_type == MMU_DATA_STORE) && (lu.prot & PAGE_WRITE)) ||
+ ((access_type == MMU_INST_FETCH) && (lu.prot & PAGE_EXEC))) {
+ tlb_set_page(cs, vaddr, paddr, lu.prot,
+ mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+ }
+
+ /* Permission violation */
+ excp = (access_type == MMU_DATA_LOAD ? EXCP_TLBR :
+ access_type == MMU_DATA_STORE ? EXCP_TLBW : EXCP_TLBX);
+ }
+
+ if (probe) {
+ return false;
+ }
+
+ if (access_type == MMU_INST_FETCH) {
+ env->regs[CR_TLBMISC] &= ~CR_TLBMISC_D;
+ } else {
+ env->regs[CR_TLBMISC] |= CR_TLBMISC_D;
+ }
+ env->regs[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK;
+ env->regs[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK;
+ env->mmu.pteaddr_wr = env->regs[CR_PTEADDR];
+
+ cs->exception_index = excp;
+ env->regs[CR_BADADDR] = address;
+ cpu_loop_exit_restore(cs, retaddr);
+}
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ nios2_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
+}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/nios2/mmu.c b/target/nios2/mmu.c
index 5acf442d8b..47fa474efb 100644
--- a/target/nios2/mmu.c
+++ b/target/nios2/mmu.c
@@ -36,18 +36,6 @@
#define MMU_LOG(x)
#endif
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = nios2_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret)) {
- /* now we have a real cpu fault */
- cpu_loop_exit_restore(cs, retaddr);
- }
-}
-
void mmu_read_debug(CPUNios2State *env, uint32_t rn)
{
switch (rn) {
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 15/27] target/openrisc: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (13 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 14/27] target/nios2: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 16/27] target/ppc: " Richard Henderson
` (11 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Stafford Horne
Cc: Stafford Horne <shorne@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/openrisc/cpu.h | 5 ++--
target/openrisc/cpu.c | 5 ++--
target/openrisc/mmu.c | 65 ++++++++++++++++++++++---------------------
3 files changed, 39 insertions(+), 36 deletions(-)
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index a50861955a..5b1ae803a1 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -344,8 +344,9 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void openrisc_translate_init(void);
-int openrisc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size,
- int rw, int mmu_idx);
+bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
int print_insn_or1k(bfd_vma addr, disassemble_info *info);
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index d125236977..3816baee70 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -149,9 +149,8 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
cc->set_pc = openrisc_cpu_set_pc;
cc->gdb_read_register = openrisc_cpu_gdb_read_register;
cc->gdb_write_register = openrisc_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = openrisc_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = openrisc_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_openrisc_cpu;
#endif
diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index e7d5219e11..991f3fafe8 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -107,16 +107,42 @@ static void raise_mmu_exception(OpenRISCCPU *cpu, target_ulong address,
cpu->env.lock_addr = -1;
}
-int openrisc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
+bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
-#ifdef CONFIG_USER_ONLY
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
- raise_mmu_exception(cpu, address, EXCP_DPF);
- return 1;
-#else
- g_assert_not_reached();
+ int excp = EXCP_DPF;
+
+#ifndef CONFIG_USER_ONLY
+ int prot;
+ hwaddr phys_addr;
+
+ if (mmu_idx == MMU_NOMMU_IDX) {
+ /* The mmu is disabled; lookups never fail. */
+ get_phys_nommu(&phys_addr, &prot, addr);
+ excp = 0;
+ } else {
+ bool super = mmu_idx == MMU_SUPERVISOR_IDX;
+ int need = (access_type == MMU_INST_FETCH ? PAGE_EXEC
+ : access_type == MMU_DATA_STORE ? PAGE_WRITE
+ : PAGE_READ);
+ excp = get_phys_mmu(cpu, &phys_addr, &prot, addr, need, super);
+ }
+
+ if (likely(excp == 0)) {
+ tlb_set_page(cs, addr & TARGET_PAGE_MASK,
+ phys_addr & TARGET_PAGE_MASK, prot,
+ mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+ }
+ if (probe) {
+ return false;
+ }
#endif
+
+ raise_mmu_exception(cpu, addr, excp);
+ cpu_loop_exit_restore(cs, retaddr);
}
#ifndef CONFIG_USER_ONLY
@@ -156,29 +182,6 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
void tlb_fill(CPUState *cs, target_ulong addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
- OpenRISCCPU *cpu = OPENRISC_CPU(cs);
- int prot, excp;
- hwaddr phys_addr;
-
- if (mmu_idx == MMU_NOMMU_IDX) {
- /* The mmu is disabled; lookups never fail. */
- get_phys_nommu(&phys_addr, &prot, addr);
- excp = 0;
- } else {
- bool super = mmu_idx == MMU_SUPERVISOR_IDX;
- int need = (access_type == MMU_INST_FETCH ? PAGE_EXEC
- : access_type == MMU_DATA_STORE ? PAGE_WRITE
- : PAGE_READ);
- excp = get_phys_mmu(cpu, &phys_addr, &prot, addr, need, super);
- }
-
- 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);
+ openrisc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, 0, retaddr);
}
#endif
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 16/27] target/ppc: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (14 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 15/27] target/openrisc: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 17/27] target/riscv: " Richard Henderson
` (10 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-ppc, David Gibson
Cc: qemu-ppc@nongnu.org
Cc: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/ppc/cpu.h | 7 +++----
target/ppc/mmu_helper.c | 22 +++++++++++++---------
target/ppc/translate_init.inc.c | 5 ++---
target/ppc/user_only_helper.c | 14 ++++++++------
4 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 5e7cf54b2f..d7f23ad5e0 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1311,10 +1311,9 @@ void ppc_translate_init(void);
* is returned if the signal was handled by the virtual CPU.
*/
int cpu_ppc_signal_handler(int host_signum, void *pinfo, void *puc);
-#if defined(CONFIG_USER_ONLY)
-int ppc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
-#endif
+bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
#if !defined(CONFIG_USER_ONLY)
void ppc_store_sdr1(CPUPPCState *env, target_ulong value);
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 1dbc9acb75..afcca50530 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -3057,15 +3057,9 @@ void helper_check_tlb_flush_global(CPUPPCState *env)
/*****************************************************************************/
-/*
- * try to fill the TLB and return an exception if error. If retaddr is
- * NULL, it means that the function was called in C code (i.e. not
- * from generated code or from helper.c)
- *
- * XXX: fix it to restore all registers
- */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
@@ -3078,7 +3072,17 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx);
}
if (unlikely(ret != 0)) {
+ if (probe) {
+ return false;
+ }
raise_exception_err_ra(env, cs->exception_index, env->error_code,
retaddr);
}
+ return true;
+}
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ ppc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 0394a9ddad..3f847de36c 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -10592,9 +10592,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = ppc_cpu_gdb_read_register;
cc->gdb_write_register = ppc_cpu_gdb_write_register;
cc->do_unaligned_access = ppc_cpu_do_unaligned_access;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = ppc_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = ppc_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_ppc_cpu;
#endif
diff --git a/target/ppc/user_only_helper.c b/target/ppc/user_only_helper.c
index 2f1477f102..683c03390d 100644
--- a/target/ppc/user_only_helper.c
+++ b/target/ppc/user_only_helper.c
@@ -20,21 +20,24 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "exec/exec-all.h"
-int ppc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+
+bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
int exception, error_code;
- if (rw == 2) {
+ if (access_type == MMU_INST_FETCH) {
exception = POWERPC_EXCP_ISI;
error_code = 0x40000000;
} else {
exception = POWERPC_EXCP_DSI;
error_code = 0x40000000;
- if (rw) {
+ if (access_type == MMU_DATA_STORE) {
error_code |= 0x02000000;
}
env->spr[SPR_DAR] = address;
@@ -42,6 +45,5 @@ int ppc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
}
cs->exception_index = exception;
env->error_code = error_code;
-
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 17/27] target/riscv: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (15 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 16/27] target/ppc: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 18/27] target/s390x: " Richard Henderson
` (9 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Palmer Dabbelt, qemu-riscv
Note that env->pc is removed from the qemu_log as that value is garbage.
The PC isn't recovered until cpu_restore_state, called from
cpu_loop_exit_restore, called from riscv_raise_exception.
Cc: qemu-riscv@nongnu.org
Cc: Palmer Dabbelt <palmer@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/riscv/cpu.h | 5 +++--
target/riscv/cpu.c | 5 ++---
target/riscv/cpu_helper.c | 46 ++++++++++++++++++---------------------
3 files changed, 26 insertions(+), 30 deletions(-)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7d9f48973f..c17184f4e4 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -261,8 +261,9 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type, int mmu_idx,
uintptr_t retaddr);
-int riscv_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size,
- int rw, int mmu_idx);
+bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
char *riscv_isa_string(RISCVCPU *cpu);
void riscv_cpu_list(void);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1bcf4eaeb8..34a54ef2ed 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -355,9 +355,8 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
#endif
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = riscv_cpu_disas_set_info;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = riscv_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = riscv_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_unaligned_access = riscv_cpu_do_unaligned_access;
cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug;
#endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b17f169681..2535435260 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -379,53 +379,49 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
riscv_raise_exception(env, cs->exception_index, retaddr);
}
-/* called by qemu's softmmu to fill the qemu tlb */
void tlb_fill(CPUState *cs, target_ulong addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
- int ret;
- ret = riscv_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (ret == TRANSLATE_FAIL) {
- RISCVCPU *cpu = RISCV_CPU(cs);
- CPURISCVState *env = &cpu->env;
- riscv_raise_exception(env, cs->exception_index, retaddr);
- }
+ riscv_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
-
#endif
-int riscv_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
+bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
+#ifndef CONFIG_USER_ONLY
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
-#if !defined(CONFIG_USER_ONLY)
hwaddr pa = 0;
int prot;
-#endif
int ret = TRANSLATE_FAIL;
- qemu_log_mask(CPU_LOG_MMU,
- "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx \
- %d\n", __func__, env->pc, address, rw, mmu_idx);
+ qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
+ __func__, address, access_type, mmu_idx);
+
+ ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx);
-#if !defined(CONFIG_USER_ONLY)
- ret = get_physical_address(env, &pa, &prot, address, rw, mmu_idx);
qemu_log_mask(CPU_LOG_MMU,
- "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx
- " prot %d\n", __func__, address, ret, pa, prot);
+ "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx
+ " prot %d\n", __func__, address, ret, pa, prot);
+
if (riscv_feature(env, RISCV_FEATURE_PMP) &&
- !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << rw)) {
+ !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) {
ret = TRANSLATE_FAIL;
}
if (ret == TRANSLATE_SUCCESS) {
tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK,
prot, mmu_idx, TARGET_PAGE_SIZE);
- } else if (ret == TRANSLATE_FAIL) {
- raise_mmu_exception(env, address, rw);
+ return true;
+ } else if (probe) {
+ return false;
+ } else {
+ raise_mmu_exception(env, address, access_type);
+ riscv_raise_exception(env, cs->exception_index, retaddr);
}
#else
- switch (rw) {
+ switch (access_type) {
case MMU_INST_FETCH:
cs->exception_index = RISCV_EXCP_INST_PAGE_FAULT;
break;
@@ -436,8 +432,8 @@ int riscv_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT;
break;
}
+ cpu_loop_exit_restore(cs, retaddr);
#endif
- return ret;
}
/*
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 18/27] target/s390x: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (16 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 17/27] target/riscv: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 7:04 ` David Hildenbrand
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 19/27] target/sh4: " Richard Henderson
` (8 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-s390x, Cornelia Huck, David Hildenbrand
Cc: qemu-s390x@nongnu.org
Cc: Cornelia Huck <cohuck@redhat.com>
Cc: David Hildenbrand <david@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Keep user-only and system tlb_fill separate.
---
target/s390x/internal.h | 5 +--
target/s390x/cpu.c | 5 ++-
target/s390x/excp_helper.c | 73 ++++++++++++++++++++++++++------------
target/s390x/mem_helper.c | 16 ---------
4 files changed, 55 insertions(+), 44 deletions(-)
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index 26575f2130..56534b38e0 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -263,8 +263,9 @@ ObjectClass *s390_cpu_class_by_name(const char *name);
void s390x_cpu_debug_excp_handler(CPUState *cs);
void s390_cpu_do_interrupt(CPUState *cpu);
bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
-int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr);
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index b58ef0a8ef..e28939032b 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -478,9 +478,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
cc->set_pc = s390_cpu_set_pc;
cc->gdb_read_register = s390_cpu_gdb_read_register;
cc->gdb_write_register = s390_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = s390_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = s390_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_s390_cpu;
cc->write_elf64_note = s390_cpu_write_elf64_note;
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index f84bfb1284..a4e134bcab 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -74,8 +74,9 @@ void s390_cpu_do_interrupt(CPUState *cs)
cs->exception_index = -1;
}
-int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
+bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
S390CPU *cpu = S390_CPU(cs);
@@ -83,7 +84,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
/* On real machines this value is dropped into LowMem. Since this
is userland, simply put this someplace that cpu_loop can find it. */
cpu->env.__excp_addr = address;
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
#else /* !CONFIG_USER_ONLY */
@@ -102,19 +103,20 @@ static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
}
}
-int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size,
- int rw, int mmu_idx)
+bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
target_ulong vaddr, raddr;
uint64_t asc;
- int prot;
+ int prot, fail;
qemu_log_mask(CPU_LOG_MMU, "%s: addr 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
- __func__, orig_vaddr, rw, mmu_idx);
+ __func__, address, access_type, mmu_idx);
- vaddr = orig_vaddr;
+ vaddr = address;
if (mmu_idx < MMU_REAL_IDX) {
asc = cpu_mmu_idx_to_asc(mmu_idx);
@@ -122,39 +124,64 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size,
if (!(env->psw.mask & PSW_MASK_64)) {
vaddr &= 0x7fffffff;
}
- if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) {
- return 1;
- }
+ fail = mmu_translate(env, vaddr, access_type, asc, &raddr, &prot, true);
} else if (mmu_idx == MMU_REAL_IDX) {
/* 31-Bit mode */
if (!(env->psw.mask & PSW_MASK_64)) {
vaddr &= 0x7fffffff;
}
- if (mmu_translate_real(env, vaddr, rw, &raddr, &prot)) {
- return 1;
- }
+ fail = mmu_translate_real(env, vaddr, access_type, &raddr, &prot);
} else {
- abort();
+ g_assert_not_reached();
}
/* check out of RAM access */
- if (!address_space_access_valid(&address_space_memory, raddr,
- TARGET_PAGE_SIZE, rw,
+ if (!fail &&
+ !address_space_access_valid(&address_space_memory, raddr,
+ TARGET_PAGE_SIZE, access_type,
MEMTXATTRS_UNSPECIFIED)) {
qemu_log_mask(CPU_LOG_MMU,
"%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n",
__func__, (uint64_t)raddr, (uint64_t)ram_size);
trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO);
- return 1;
+ fail = 1;
}
- qemu_log_mask(CPU_LOG_MMU, "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n",
- __func__, (uint64_t)vaddr, (uint64_t)raddr, prot);
+ if (!fail) {
+ qemu_log_mask(CPU_LOG_MMU,
+ "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n",
+ __func__, (uint64_t)vaddr, (uint64_t)raddr, prot);
+ tlb_set_page(cs, address & TARGET_PAGE_MASK, raddr, prot,
+ mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+ }
+ if (probe) {
+ return false;
+ }
- tlb_set_page(cs, orig_vaddr & TARGET_PAGE_MASK, raddr, prot,
- mmu_idx, TARGET_PAGE_SIZE);
+ cpu_restore_state(cs, retaddr, true);
- return 0;
+ /*
+ * The ILC value for code accesses is undefined. The important
+ * thing here is to *not* leave env->int_pgm_ilen set to ILEN_AUTO,
+ * which would cause do_program_interrupt to attempt to read from
+ * env->psw.addr again. C.f. the condition in trigger_page_fault,
+ * but is not universally applied.
+ *
+ * ??? If we remove ILEN_AUTO, by moving the computation of ILEN
+ * into cpu_restore_state, then we may remove this entirely.
+ */
+ if (access_type == MMU_INST_FETCH) {
+ env->int_pgm_ilen = 2;
+ }
+
+ cpu_loop_exit(cs);
+}
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ s390_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
static void do_program_interrupt(CPUS390XState *env)
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 3f76a8abfd..ffd5f02fbe 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -33,22 +33,6 @@
/*****************************************************************************/
/* Softmmu support */
-#if !defined(CONFIG_USER_ONLY)
-
-/* try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret = s390_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret != 0)) {
- cpu_loop_exit_restore(cs, retaddr);
- }
-}
-
-#endif
/* #define DEBUG_HELPER */
#ifdef DEBUG_HELPER
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 19/27] target/sh4: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (17 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 18/27] target/s390x: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 20/27] target/sparc: " Richard Henderson
` (7 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Aurelien Jarno
Cc: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/sh4/cpu.h | 5 +-
target/sh4/cpu.c | 5 +-
target/sh4/helper.c | 197 ++++++++++++++++++++---------------------
target/sh4/op_helper.c | 12 ---
4 files changed, 101 insertions(+), 118 deletions(-)
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index 84b08ff640..587b146399 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -243,8 +243,9 @@ void superh_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
void sh4_translate_init(void);
int cpu_sh4_signal_handler(int host_signum, void *pinfo,
void *puc);
-int superh_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
void sh4_cpu_list(void);
#if !defined(CONFIG_USER_ONLY)
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index da2799082e..c4736a0a73 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -229,9 +229,8 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
cc->synchronize_from_tb = superh_cpu_synchronize_from_tb;
cc->gdb_read_register = superh_cpu_gdb_read_register;
cc->gdb_write_register = superh_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = superh_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = superh_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_unaligned_access = superh_cpu_do_unaligned_access;
cc->get_phys_page_debug = superh_cpu_get_phys_page_debug;
#endif
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
index 2ff0cf4060..1df1e02a14 100644
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -27,43 +27,6 @@
#include "hw/sh4/sh_intc.h"
#endif
-#if defined(CONFIG_USER_ONLY)
-
-void superh_cpu_do_interrupt(CPUState *cs)
-{
- cs->exception_index = -1;
-}
-
-int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
-{
- SuperHCPU *cpu = SUPERH_CPU(cs);
- CPUSH4State *env = &cpu->env;
-
- env->tea = address;
- cs->exception_index = -1;
- switch (rw) {
- case 0:
- cs->exception_index = 0x0a0;
- break;
- case 1:
- cs->exception_index = 0x0c0;
- break;
- case 2:
- cs->exception_index = 0x0a0;
- break;
- }
- return 1;
-}
-
-int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
-{
- /* For user mode, only U0 area is cacheable. */
- return !(addr & 0x80000000);
-}
-
-#else /* !CONFIG_USER_ONLY */
-
#define MMU_OK 0
#define MMU_ITLB_MISS (-1)
#define MMU_ITLB_MULTIPLE (-2)
@@ -79,6 +42,21 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
#define MMU_DADDR_ERROR_READ (-12)
#define MMU_DADDR_ERROR_WRITE (-13)
+#if defined(CONFIG_USER_ONLY)
+
+void superh_cpu_do_interrupt(CPUState *cs)
+{
+ cs->exception_index = -1;
+}
+
+int cpu_sh4_is_cached(CPUSH4State *env, target_ulong addr)
+{
+ /* For user mode, only U0 area is cacheable. */
+ return !(addr & 0x80000000);
+}
+
+#else /* !CONFIG_USER_ONLY */
+
void superh_cpu_do_interrupt(CPUState *cs)
{
SuperHCPU *cpu = SUPERH_CPU(cs);
@@ -458,69 +436,6 @@ static int get_physical_address(CPUSH4State * env, target_ulong * physical,
return get_mmu_address(env, physical, prot, address, rw, access_type);
}
-int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
-{
- SuperHCPU *cpu = SUPERH_CPU(cs);
- CPUSH4State *env = &cpu->env;
- target_ulong physical;
- int prot, ret, access_type;
-
- access_type = ACCESS_INT;
- ret =
- get_physical_address(env, &physical, &prot, address, rw,
- access_type);
-
- if (ret != MMU_OK) {
- env->tea = address;
- if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) {
- env->pteh = (env->pteh & PTEH_ASID_MASK) |
- (address & PTEH_VPN_MASK);
- }
- switch (ret) {
- case MMU_ITLB_MISS:
- case MMU_DTLB_MISS_READ:
- cs->exception_index = 0x040;
- break;
- case MMU_DTLB_MULTIPLE:
- case MMU_ITLB_MULTIPLE:
- cs->exception_index = 0x140;
- break;
- case MMU_ITLB_VIOLATION:
- cs->exception_index = 0x0a0;
- break;
- case MMU_DTLB_MISS_WRITE:
- cs->exception_index = 0x060;
- break;
- case MMU_DTLB_INITIAL_WRITE:
- cs->exception_index = 0x080;
- break;
- case MMU_DTLB_VIOLATION_READ:
- cs->exception_index = 0x0a0;
- break;
- case MMU_DTLB_VIOLATION_WRITE:
- cs->exception_index = 0x0c0;
- break;
- case MMU_IADDR_ERROR:
- case MMU_DADDR_ERROR_READ:
- cs->exception_index = 0x0e0;
- break;
- case MMU_DADDR_ERROR_WRITE:
- cs->exception_index = 0x100;
- break;
- default:
- cpu_abort(cs, "Unhandled MMU fault");
- }
- return 1;
- }
-
- address &= TARGET_PAGE_MASK;
- physical &= TARGET_PAGE_MASK;
-
- tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE);
- return 0;
-}
-
hwaddr superh_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
SuperHCPU *cpu = SUPERH_CPU(cs);
@@ -745,7 +660,6 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr,
if (needs_tlb_flush) {
tlb_flush_page(CPU(sh_env_get_cpu(s)), vpn << 10);
}
-
} else {
int index = (addr & 0x00003f00) >> 8;
tlb_t * entry = &s->utlb[index];
@@ -885,3 +799,84 @@ bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
}
return false;
}
+
+bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
+{
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+ CPUSH4State *env = &cpu->env;
+ int ret;
+
+#ifdef CONFIG_USER_ONLY
+ ret = (access_type == MMU_DATA_STORE ? MMU_DTLB_VIOLATION_WRITE :
+ access_type == MMU_INST_FETCH ? MMU_ITLB_VIOLATION :
+ MMU_DTLB_VIOLATION_READ);
+#else
+ target_ulong physical;
+ int prot, sh_access_type;
+
+ sh_access_type = ACCESS_INT;
+ ret = get_physical_address(env, &physical, &prot, address,
+ access_type, sh_access_type);
+
+ if (ret == MMU_OK) {
+ address &= TARGET_PAGE_MASK;
+ physical &= TARGET_PAGE_MASK;
+ tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE);
+ return true;
+ }
+ if (probe) {
+ return false;
+ }
+
+ if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) {
+ env->pteh = (env->pteh & PTEH_ASID_MASK) | (address & PTEH_VPN_MASK);
+ }
+#endif
+
+ env->tea = address;
+ switch (ret) {
+ case MMU_ITLB_MISS:
+ case MMU_DTLB_MISS_READ:
+ cs->exception_index = 0x040;
+ break;
+ case MMU_DTLB_MULTIPLE:
+ case MMU_ITLB_MULTIPLE:
+ cs->exception_index = 0x140;
+ break;
+ case MMU_ITLB_VIOLATION:
+ cs->exception_index = 0x0a0;
+ break;
+ case MMU_DTLB_MISS_WRITE:
+ cs->exception_index = 0x060;
+ break;
+ case MMU_DTLB_INITIAL_WRITE:
+ cs->exception_index = 0x080;
+ break;
+ case MMU_DTLB_VIOLATION_READ:
+ cs->exception_index = 0x0a0;
+ break;
+ case MMU_DTLB_VIOLATION_WRITE:
+ cs->exception_index = 0x0c0;
+ break;
+ case MMU_IADDR_ERROR:
+ case MMU_DADDR_ERROR_READ:
+ cs->exception_index = 0x0e0;
+ break;
+ case MMU_DADDR_ERROR_WRITE:
+ cs->exception_index = 0x100;
+ break;
+ default:
+ cpu_abort(cs, "Unhandled MMU fault");
+ }
+ cpu_loop_exit_restore(cs, retaddr);
+}
+
+#ifndef CONFIG_USER_ONLY
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ superh_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
+}
+#endif
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index 4f825bae5a..599731966b 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -41,18 +41,6 @@ void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
cpu_loop_exit_restore(cs, retaddr);
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = superh_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (ret) {
- /* now we have a real cpu fault */
- cpu_loop_exit_restore(cs, retaddr);
- }
-}
-
#endif
void helper_ldtlb(CPUSH4State *env)
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 20/27] target/sparc: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (18 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 19/27] target/sh4: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 13:35 ` Peter Maydell
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 21/27] target/tilegx: " Richard Henderson
` (6 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Mark Cave-Ayland, Artyom Tarasenko
Cc: Artyom Tarasenko <atar4qemu@gmail.com>
Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Keep user-only, sparc32, and sparc64 tlb_fill separate.
---
target/sparc/cpu.h | 5 ++-
target/sparc/cpu.c | 5 +--
target/sparc/ldst_helper.c | 11 +-----
target/sparc/mmu_helper.c | 78 ++++++++++++++++++++++----------------
4 files changed, 51 insertions(+), 48 deletions(-)
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 85b9665ccc..f31e8535df 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -579,8 +579,9 @@ void cpu_raise_exception_ra(CPUSPARCState *, int, uintptr_t) QEMU_NORETURN;
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
void sparc_cpu_list(void);
/* mmu_helper.c */
-int sparc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
void dump_mmu(CPUSPARCState *env);
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index 4654c2a6a0..f93ce72eb9 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -875,9 +875,8 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
cc->gdb_read_register = sparc_cpu_gdb_read_register;
cc->gdb_write_register = sparc_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = sparc_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_unassigned_access = sparc_cpu_unassigned_access;
cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
index a7fcb84ac0..2558c08a64 100644
--- a/target/sparc/ldst_helper.c
+++ b/target/sparc/ldst_helper.c
@@ -1925,18 +1925,9 @@ void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr);
}
-/* try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
void tlb_fill(CPUState *cs, target_ulong addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
- int ret;
-
- ret = sparc_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (ret) {
- cpu_loop_exit_restore(cs, retaddr);
- }
+ sparc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
#endif
diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c
index afcc5b617d..7f811ea031 100644
--- a/target/sparc/mmu_helper.c
+++ b/target/sparc/mmu_helper.c
@@ -27,13 +27,14 @@
#if defined(CONFIG_USER_ONLY)
-int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
SPARCCPU *cpu = SPARC_CPU(cs);
CPUSPARCState *env = &cpu->env;
- if (rw & 2) {
+ if (access_type == MMU_INST_FETCH) {
cs->exception_index = TT_TFAULT;
} else {
cs->exception_index = TT_DFAULT;
@@ -43,7 +44,7 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
env->mmuregs[4] = address;
#endif
}
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
#else
@@ -208,8 +209,9 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
}
/* Perform address translation */
-int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
SPARCCPU *cpu = SPARC_CPU(cs);
CPUSPARCState *env = &cpu->env;
@@ -220,22 +222,18 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
address &= TARGET_PAGE_MASK;
error_code = get_physical_address(env, &paddr, &prot, &access_index,
- address, rw, mmu_idx, &page_size);
+ address, access_type,
+ mmu_idx, &page_size);
vaddr = address;
- if (error_code == 0) {
+ if (likely(error_code == 0)) {
qemu_log_mask(CPU_LOG_MMU,
- "Translate at %" VADDR_PRIx " -> " TARGET_FMT_plx ", vaddr "
- TARGET_FMT_lx "\n", address, paddr, vaddr);
+ "Translate at %" VADDR_PRIx " -> "
+ TARGET_FMT_plx ", vaddr " TARGET_FMT_lx "\n",
+ address, paddr, vaddr);
tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
- return 0;
+ return true;
}
- if (env->mmuregs[3]) { /* Fault status register */
- env->mmuregs[3] = 1; /* overflow (not read before another fault) */
- }
- env->mmuregs[3] |= (access_index << 5) | error_code | 2;
- env->mmuregs[4] = address; /* Fault address register */
-
if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
/* No fault mode: if a mapping is available, just override
permissions. If no mapping is available, redirect accesses to
@@ -243,15 +241,25 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
switching to normal mode. */
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
- return 0;
- } else {
- if (rw & 2) {
- cs->exception_index = TT_TFAULT;
- } else {
- cs->exception_index = TT_DFAULT;
- }
- return 1;
+ return true;
}
+
+ if (probe) {
+ return false;
+ }
+
+ if (env->mmuregs[3]) { /* Fault status register */
+ env->mmuregs[3] = 1; /* overflow (not read before another fault) */
+ }
+ env->mmuregs[3] |= (access_index << 5) | error_code | 2;
+ env->mmuregs[4] = address; /* Fault address register */
+
+ if (access_type == MMU_INST_FETCH) {
+ cs->exception_index = TT_TFAULT;
+ } else {
+ cs->exception_index = TT_DFAULT;
+ }
+ cpu_loop_exit_restore(cs, retaddr);
}
target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev)
@@ -713,20 +721,22 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
}
/* Perform address translation */
-int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
SPARCCPU *cpu = SPARC_CPU(cs);
CPUSPARCState *env = &cpu->env;
- target_ulong vaddr;
hwaddr paddr;
+ target_ulong vaddr;
target_ulong page_size;
int error_code = 0, prot, access_index;
address &= TARGET_PAGE_MASK;
error_code = get_physical_address(env, &paddr, &prot, &access_index,
- address, rw, mmu_idx, &page_size);
- if (error_code == 0) {
+ address, access_type,
+ mmu_idx, &page_size);
+ if (likely(error_code == 0)) {
vaddr = address;
trace_mmu_helper_mmu_fault(address, paddr, mmu_idx, env->tl,
@@ -734,10 +744,12 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
env->dmmu.mmu_secondary_context);
tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
- return 0;
+ return true;
}
- /* XXX */
- return 1;
+ if (probe) {
+ return false;
+ }
+ cpu_loop_exit_restore(cs, retaddr);
}
void dump_mmu(CPUSPARCState *env)
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 21/27] target/tilegx: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (19 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 20/27] target/sparc: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 22/27] target/tricore: " Richard Henderson
` (5 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/tilegx/cpu.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/target/tilegx/cpu.c b/target/tilegx/cpu.c
index b9d37105fa..b209c55387 100644
--- a/target/tilegx/cpu.c
+++ b/target/tilegx/cpu.c
@@ -25,6 +25,7 @@
#include "hw/qdev-properties.h"
#include "linux-user/syscall_defs.h"
#include "qemu/qemu-print.h"
+#include "exec/exec-all.h"
static void tilegx_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
@@ -111,8 +112,9 @@ static void tilegx_cpu_do_interrupt(CPUState *cs)
cs->exception_index = -1;
}
-static int tilegx_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int rw, int mmu_idx)
+static bool tilegx_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
TileGXCPU *cpu = TILEGX_CPU(cs);
@@ -122,7 +124,7 @@ static int tilegx_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
cpu->env.signo = TARGET_SIGSEGV;
cpu->env.sigcode = 0;
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
static bool tilegx_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
@@ -152,7 +154,7 @@ static void tilegx_cpu_class_init(ObjectClass *oc, void *data)
cc->cpu_exec_interrupt = tilegx_cpu_exec_interrupt;
cc->dump_state = tilegx_cpu_dump_state;
cc->set_pc = tilegx_cpu_set_pc;
- cc->handle_mmu_fault = tilegx_cpu_handle_mmu_fault;
+ cc->tlb_fill = tilegx_cpu_tlb_fill;
cc->gdb_num_core_regs = 0;
cc->tcg_initialize = tilegx_tcg_init;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 22/27] target/tricore: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (20 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 21/27] target/tilegx: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 9:43 ` Bastian Koppelmann
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 23/27] target/unicore32: " Richard Henderson
` (4 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Bastian Koppelmann
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/tricore/cpu.h | 6 +++---
target/tricore/cpu.c | 1 +
target/tricore/helper.c | 27 +++++++++++++++++++--------
target/tricore/op_helper.c | 26 --------------------------
4 files changed, 23 insertions(+), 37 deletions(-)
diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
index 64d1a9c75e..287f4328a3 100644
--- a/target/tricore/cpu.h
+++ b/target/tricore/cpu.h
@@ -417,8 +417,8 @@ static inline void cpu_get_tb_cpu_state(CPUTriCoreState *env, target_ulong *pc,
#define CPU_RESOLVING_TYPE TYPE_TRICORE_CPU
/* helpers.c */
-int cpu_tricore_handle_mmu_fault(CPUState *cpu, target_ulong address,
- int rw, int mmu_idx);
-#define cpu_handle_mmu_fault cpu_tricore_handle_mmu_fault
+bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
#endif /* TRICORE_CPU_H */
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index e8d37e4040..ea1199d27e 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -166,6 +166,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
cc->get_phys_page_attrs_debug = tricore_cpu_get_phys_page_attrs_debug;
cc->tcg_initialize = tricore_tcg_init;
+ cc->tlb_fill = tricore_cpu_tlb_fill;
}
#define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
index 78ee87c9ea..ed184fee3a 100644
--- a/target/tricore/helper.c
+++ b/target/tricore/helper.c
@@ -50,8 +50,9 @@ static void raise_mmu_exception(CPUTriCoreState *env, target_ulong address,
{
}
-int cpu_tricore_handle_mmu_fault(CPUState *cs, target_ulong address,
- int rw, int mmu_idx)
+bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType rw, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
TriCoreCPU *cpu = TRICORE_CPU(cs);
CPUTriCoreState *env = &cpu->env;
@@ -64,20 +65,30 @@ int cpu_tricore_handle_mmu_fault(CPUState *cs, target_ulong address,
access_type = ACCESS_INT;
ret = get_physical_address(env, &physical, &prot,
address, rw, access_type);
- qemu_log_mask(CPU_LOG_MMU, "%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx
- " prot %d\n", __func__, address, ret, physical, prot);
+
+ qemu_log_mask(CPU_LOG_MMU, "%s address=" TARGET_FMT_lx " ret %d physical "
+ TARGET_FMT_plx " prot %d\n",
+ __func__, (target_ulong)address, ret, physical, prot);
if (ret == TLBRET_MATCH) {
tlb_set_page(cs, address & TARGET_PAGE_MASK,
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
mmu_idx, TARGET_PAGE_SIZE);
- ret = 0;
- } else if (ret < 0) {
+ return true;
+ } else {
+ assert(ret < 0);
+ if (probe) {
+ return false;
+ }
raise_mmu_exception(env, address, rw, ret);
- ret = 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
+}
- return ret;
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ tricore_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
static void tricore_cpu_list_entry(gpointer data, gpointer user_data)
diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
index ed9dc0c83e..601e92f92a 100644
--- a/target/tricore/op_helper.c
+++ b/target/tricore/op_helper.c
@@ -2793,29 +2793,3 @@ uint32_t helper_psw_read(CPUTriCoreState *env)
{
return psw_read(env);
}
-
-
-static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env,
- uint32_t exception,
- int error_code,
- uintptr_t pc)
-{
- CPUState *cs = CPU(tricore_env_get_cpu(env));
- cs->exception_index = exception;
- env->error_code = error_code;
- /* now we have a real cpu fault */
- cpu_loop_exit_restore(cs, pc);
-}
-
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
- ret = cpu_tricore_handle_mmu_fault(cs, addr, access_type, mmu_idx);
- if (ret) {
- TriCoreCPU *cpu = TRICORE_CPU(cs);
- CPUTriCoreState *env = &cpu->env;
- do_raise_exception_err(env, cs->exception_index,
- env->error_code, retaddr);
- }
-}
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 23/27] target/unicore32: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (21 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 22/27] target/tricore: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 24/27] target/xtensa: " Richard Henderson
` (3 subsequent siblings)
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Guan Xuetao
Remove the user-only functions, as we no longer
have a user-only config.
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/unicore32/cpu.h | 5 +++--
target/unicore32/cpu.c | 5 +----
target/unicore32/helper.c | 23 -----------------------
target/unicore32/op_helper.c | 14 --------------
target/unicore32/softmmu.c | 19 +++++++++++++++----
5 files changed, 19 insertions(+), 47 deletions(-)
diff --git a/target/unicore32/cpu.h b/target/unicore32/cpu.h
index 24abe5e5c0..f052ee08bf 100644
--- a/target/unicore32/cpu.h
+++ b/target/unicore32/cpu.h
@@ -178,8 +178,9 @@ static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc
}
}
-int uc32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_idx);
+bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
void uc32_translate_init(void);
void switch_mode(CPUUniCore32State *, int);
diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c
index 2b49d1ca40..3f57c508a0 100644
--- a/target/unicore32/cpu.c
+++ b/target/unicore32/cpu.c
@@ -138,11 +138,8 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
cc->cpu_exec_interrupt = uc32_cpu_exec_interrupt;
cc->dump_state = uc32_cpu_dump_state;
cc->set_pc = uc32_cpu_set_pc;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = uc32_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = uc32_cpu_tlb_fill;
cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
-#endif
cc->tcg_initialize = uc32_translate_init;
dc->vmsd = &vmstate_uc32_cpu;
}
diff --git a/target/unicore32/helper.c b/target/unicore32/helper.c
index a5ff2ddb74..0d4914b48d 100644
--- a/target/unicore32/helper.c
+++ b/target/unicore32/helper.c
@@ -215,29 +215,6 @@ void helper_cp1_putc(target_ulong x)
}
#endif
-#ifdef CONFIG_USER_ONLY
-void switch_mode(CPUUniCore32State *env, int mode)
-{
- UniCore32CPU *cpu = uc32_env_get_cpu(env);
-
- if (mode != ASR_MODE_USER) {
- cpu_abort(CPU(cpu), "Tried to switch out of user mode\n");
- }
-}
-
-void uc32_cpu_do_interrupt(CPUState *cs)
-{
- cpu_abort(cs, "NO interrupt in user mode\n");
-}
-
-int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int access_type, int mmu_idx)
-{
- cpu_abort(cs, "NO mmu fault in user mode\n");
- return 1;
-}
-#endif
-
bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
diff --git a/target/unicore32/op_helper.c b/target/unicore32/op_helper.c
index e0a15882d3..797ba60dc9 100644
--- a/target/unicore32/op_helper.c
+++ b/target/unicore32/op_helper.c
@@ -242,17 +242,3 @@ uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
return ((uint32_t)x >> shift) | (x << (32 - shift));
}
}
-
-#ifndef CONFIG_USER_ONLY
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- int ret;
-
- ret = uc32_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
- if (unlikely(ret)) {
- /* now we have a real cpu fault */
- cpu_loop_exit_restore(cs, retaddr);
- }
-}
-#endif
diff --git a/target/unicore32/softmmu.c b/target/unicore32/softmmu.c
index 00c7e0d028..13678df4d7 100644
--- a/target/unicore32/softmmu.c
+++ b/target/unicore32/softmmu.c
@@ -215,8 +215,9 @@ do_fault:
return code;
}
-int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
- int access_type, int mmu_idx)
+bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
UniCore32CPU *cpu = UNICORE32_CPU(cs);
CPUUniCore32State *env = &cpu->env;
@@ -257,7 +258,11 @@ int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
phys_addr &= TARGET_PAGE_MASK;
address &= TARGET_PAGE_MASK;
tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size);
- return 0;
+ return true;
+ }
+
+ if (probe) {
+ return false;
}
env->cp0.c3_faultstatus = ret;
@@ -267,7 +272,13 @@ int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
} else {
cs->exception_index = UC32_EXCP_DTRAP;
}
- return ret;
+ cpu_loop_exit_restore(cs, retaddr);
+}
+
+void tlb_fill(CPUState *cs, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ uc32_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
}
hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 24/27] target/xtensa: Convert to CPUClass::tlb_fill
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (22 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 23/27] target/unicore32: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 9:56 ` Peter Maydell
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 25/27] tcg: Use CPUClass::tlb_fill in cputlb.c Richard Henderson
` (2 subsequent siblings)
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel; +Cc: Max Filippov
Cc: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Keep user-only and system tlb_fill separate.
---
target/xtensa/cpu.h | 5 +++--
target/xtensa/cpu.c | 5 ++---
target/xtensa/helper.c | 39 ++++++++++++++++++++++++++-------------
3 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 5d23e1345b..68d89f8faf 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -552,8 +552,9 @@ static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
#define ENV_OFFSET offsetof(XtensaCPU, env)
-int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int size,
- int mmu_idx);
+bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
void xtensa_cpu_do_interrupt(CPUState *cpu);
bool xtensa_cpu_exec_interrupt(CPUState *cpu, int interrupt_request);
void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index a54dbe4260..da1236377e 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -181,9 +181,8 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = xtensa_cpu_gdb_read_register;
cc->gdb_write_register = xtensa_cpu_gdb_write_register;
cc->gdb_stop_before_watchpoint = true;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = xtensa_cpu_handle_mmu_fault;
-#else
+ cc->tlb_fill = xtensa_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
cc->do_unaligned_access = xtensa_cpu_do_unaligned_access;
cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug;
cc->do_transaction_failed = xtensa_cpu_do_transaction_failed;
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index 5f37f378a3..5c94f934dd 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -240,19 +240,21 @@ void xtensa_cpu_list(void)
#ifdef CONFIG_USER_ONLY
-int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
- int mmu_idx)
+bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
XtensaCPU *cpu = XTENSA_CPU(cs);
CPUXtensaState *env = &cpu->env;
qemu_log_mask(CPU_LOG_INT,
"%s: rw = %d, address = 0x%08" VADDR_PRIx ", size = %d\n",
- __func__, rw, address, size);
+ __func__, access_type, address, size);
env->sregs[EXCVADDR] = address;
- env->sregs[EXCCAUSE] = rw ? STORE_PROHIBITED_CAUSE : LOAD_PROHIBITED_CAUSE;
+ env->sregs[EXCCAUSE] = (access_type == MMU_DATA_STORE ?
+ STORE_PROHIBITED_CAUSE : LOAD_PROHIBITED_CAUSE);
cs->exception_index = EXC_USER;
- return 1;
+ cpu_loop_exit_restore(cs, retaddr);
}
#else
@@ -273,31 +275,42 @@ void xtensa_cpu_do_unaligned_access(CPUState *cs,
}
}
-void tlb_fill(CPUState *cs, target_ulong vaddr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr)
{
XtensaCPU *cpu = XTENSA_CPU(cs);
CPUXtensaState *env = &cpu->env;
uint32_t paddr;
uint32_t page_size;
unsigned access;
- int ret = xtensa_get_physical_addr(env, true, vaddr, access_type, mmu_idx,
- &paddr, &page_size, &access);
+ int ret = xtensa_get_physical_addr(env, true, address, access_type,
+ mmu_idx, &paddr, &page_size, &access);
- qemu_log_mask(CPU_LOG_MMU, "%s(%08x, %d, %d) -> %08x, ret = %d\n",
- __func__, vaddr, access_type, mmu_idx, paddr, ret);
+ qemu_log_mask(CPU_LOG_MMU, "%s(%08" VADDR_PRIx
+ ", %d, %d) -> %08x, ret = %d\n",
+ __func__, address, access_type, mmu_idx, paddr, ret);
if (ret == 0) {
tlb_set_page(cs,
- vaddr & TARGET_PAGE_MASK,
+ address & TARGET_PAGE_MASK,
paddr & TARGET_PAGE_MASK,
access, mmu_idx, page_size);
+ return true;
+ } else if (probe) {
+ return false;
} else {
cpu_restore_state(cs, retaddr, true);
- HELPER(exception_cause_vaddr)(env, env->pc, ret, vaddr);
+ HELPER(exception_cause_vaddr)(env, env->pc, ret, address);
}
}
+void tlb_fill(CPUState *cs, target_ulong vaddr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ xtensa_cpu_tlb_fill(cs, vaddr, size, access_type, mmu_idx, false, retaddr);
+}
+
void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
unsigned size, MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 25/27] tcg: Use CPUClass::tlb_fill in cputlb.c
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (23 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 24/27] target/xtensa: " Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 26/27] tcg: Remove CPUClass::handle_mmu_fault Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 27/27] tcg: Use tlb_fill probe from tlb_vaddr_to_host Richard Henderson
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
We can now use the CPUClass hook instead of a named function.
Create a static tlb_fill function to avoid other changes within
cputlb.c. This also isolates the asserts within. Remove the
named tlb_fill function from all of the targets.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/exec/exec-all.h | 9 ---------
accel/tcg/cputlb.c | 19 +++++++++++++++++++
target/alpha/helper.c | 6 ------
target/arm/helper.c | 8 --------
target/cris/helper.c | 6 ------
target/hppa/mem_helper.c | 6 ------
target/i386/excp_helper.c | 8 --------
target/lm32/helper.c | 6 ------
target/m68k/helper.c | 8 --------
target/microblaze/helper.c | 6 ------
target/mips/helper.c | 6 ------
target/moxie/helper.c | 6 ------
target/nios2/helper.c | 6 ------
target/openrisc/mmu.c | 6 ------
target/ppc/mmu_helper.c | 6 ------
target/riscv/cpu_helper.c | 6 ------
target/s390x/excp_helper.c | 6 ------
target/sh4/helper.c | 8 --------
target/sparc/ldst_helper.c | 6 ------
target/tricore/helper.c | 6 ------
target/unicore32/softmmu.c | 6 ------
target/xtensa/helper.c | 6 ------
22 files changed, 19 insertions(+), 137 deletions(-)
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 58e988b3b1..31f0ecc461 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -474,15 +474,6 @@ static inline void assert_no_pages_locked(void)
*/
struct MemoryRegionSection *iotlb_to_section(CPUState *cpu,
hwaddr index, MemTxAttrs attrs);
-
-/*
- * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the
- * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must
- * be discarded and looked up again (e.g. via tlb_entry()).
- */
-void tlb_fill(CPUState *cpu, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr);
-
#endif
#if defined(CONFIG_USER_ONLY)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index f2f618217d..dfcd9ae168 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -855,6 +855,25 @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
return ram_addr;
}
+/*
+ * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the
+ * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must
+ * be discarded and looked up again (e.g. via tlb_entry()).
+ */
+static void tlb_fill(CPUState *cpu, target_ulong addr, int size,
+ MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+ bool ok;
+
+ /*
+ * This is not a probe, so only valid return is success; failure
+ * should result in exception + longjmp to the cpu loop.
+ */
+ ok = cc->tlb_fill(cpu, addr, size, access_type, mmu_idx, false, retaddr);
+ assert(ok);
+}
+
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
int mmu_idx,
target_ulong addr, uintptr_t retaddr,
diff --git a/target/alpha/helper.c b/target/alpha/helper.c
index 929a217455..5fe9c87912 100644
--- a/target/alpha/helper.c
+++ b/target/alpha/helper.c
@@ -275,12 +275,6 @@ bool alpha_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
prot, mmu_idx, TARGET_PAGE_SIZE);
return true;
}
-
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- alpha_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
#endif /* USER_ONLY */
void alpha_cpu_do_interrupt(CPUState *cs)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index f1a2b94ddb..e2d5c8e34f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -13127,14 +13127,6 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
#endif
}
-#ifndef CONFIG_USER_ONLY
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- arm_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-#endif
-
void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
{
/* Implement DC ZVA, which zeroes a fixed-length block of memory.
diff --git a/target/cris/helper.c b/target/cris/helper.c
index 69464837c8..b5159b8357 100644
--- a/target/cris/helper.c
+++ b/target/cris/helper.c
@@ -123,12 +123,6 @@ bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_loop_exit(cs);
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- cris_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-
void crisv10_cpu_do_interrupt(CPUState *cs)
{
CRISCPU *cpu = CRIS_CPU(cs);
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 5cee0c19b1..0fd3ac6645 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -260,12 +260,6 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
return true;
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType type, int mmu_idx, uintptr_t retaddr)
-{
- hppa_cpu_tlb_fill(cs, addr, size, type, mmu_idx, false, retaddr);
-}
-
/* Insert (Insn/Data) TLB Address. Note this is PA 1.1 only. */
void HELPER(itlba)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
{
diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c
index 68bf8e3f7c..fa1ead6404 100644
--- a/target/i386/excp_helper.c
+++ b/target/i386/excp_helper.c
@@ -700,11 +700,3 @@ bool x86_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
return true;
#endif
}
-
-#if !defined(CONFIG_USER_ONLY)
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- x86_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-#endif
diff --git a/target/lm32/helper.c b/target/lm32/helper.c
index 1db9a5562e..20ea17ba23 100644
--- a/target/lm32/helper.c
+++ b/target/lm32/helper.c
@@ -44,12 +44,6 @@ bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
return true;
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- lm32_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-
hwaddr lm32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
LM32CPU *cpu = LM32_CPU(cs);
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
index 862f955f7b..9fc9e646ff 100644
--- a/target/m68k/helper.c
+++ b/target/m68k/helper.c
@@ -884,14 +884,6 @@ bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_loop_exit_restore(cs, retaddr);
}
-#ifndef CONFIG_USER_ONLY
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- m68k_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-#endif
-
uint32_t HELPER(bitrev)(uint32_t x)
{
x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c
index a523c77959..ab2ceeb055 100644
--- a/target/microblaze/helper.c
+++ b/target/microblaze/helper.c
@@ -108,12 +108,6 @@ bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_loop_exit_restore(cs, retaddr);
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- mb_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-
void mb_cpu_do_interrupt(CPUState *cs)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
diff --git a/target/mips/helper.c b/target/mips/helper.c
index 3a4917ce7b..9799f2ede1 100644
--- a/target/mips/helper.c
+++ b/target/mips/helper.c
@@ -944,12 +944,6 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
}
#ifndef CONFIG_USER_ONLY
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- mips_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-
hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw)
{
hwaddr physical;
diff --git a/target/moxie/helper.c b/target/moxie/helper.c
index 216cef057e..f5c1d4181c 100644
--- a/target/moxie/helper.c
+++ b/target/moxie/helper.c
@@ -26,12 +26,6 @@
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- moxie_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-
void helper_raise_exception(CPUMoxieState *env, int ex)
{
CPUState *cs = CPU(moxie_env_get_cpu(env));
diff --git a/target/nios2/helper.c b/target/nios2/helper.c
index 72884e4260..5bf715e6dd 100644
--- a/target/nios2/helper.c
+++ b/target/nios2/helper.c
@@ -315,10 +315,4 @@ bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
env->regs[CR_BADADDR] = address;
cpu_loop_exit_restore(cs, retaddr);
}
-
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- nios2_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c
index 991f3fafe8..4e190514ca 100644
--- a/target/openrisc/mmu.c
+++ b/target/openrisc/mmu.c
@@ -178,10 +178,4 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
return phys_addr;
}
}
-
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- openrisc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, 0, retaddr);
-}
#endif
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index afcca50530..e605efa883 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -3080,9 +3080,3 @@ bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
}
return true;
}
-
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- ppc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 2535435260..41d6db41c3 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -378,12 +378,6 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
env->badaddr = addr;
riscv_raise_exception(env, cs->exception_index, retaddr);
}
-
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- riscv_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
#endif
bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index a4e134bcab..3a467b72c5 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -178,12 +178,6 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_loop_exit(cs);
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- s390_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-
static void do_program_interrupt(CPUS390XState *env)
{
uint64_t mask, addr;
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
index 1df1e02a14..074c74f337 100644
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -872,11 +872,3 @@ bool superh_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
}
cpu_loop_exit_restore(cs, retaddr);
}
-
-#ifndef CONFIG_USER_ONLY
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- superh_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-#endif
diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
index 2558c08a64..b4bf6faf41 100644
--- a/target/sparc/ldst_helper.c
+++ b/target/sparc/ldst_helper.c
@@ -1924,10 +1924,4 @@ void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
#endif
cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr);
}
-
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- sparc_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
#endif
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
index ed184fee3a..a680336850 100644
--- a/target/tricore/helper.c
+++ b/target/tricore/helper.c
@@ -85,12 +85,6 @@ bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
}
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- tricore_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-
static void tricore_cpu_list_entry(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
diff --git a/target/unicore32/softmmu.c b/target/unicore32/softmmu.c
index 13678df4d7..27f218abf0 100644
--- a/target/unicore32/softmmu.c
+++ b/target/unicore32/softmmu.c
@@ -275,12 +275,6 @@ bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_loop_exit_restore(cs, retaddr);
}
-void tlb_fill(CPUState *cs, target_ulong addr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- uc32_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
-}
-
hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
error_report("function uc32_cpu_get_phys_page_debug not "
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index 5c94f934dd..efb966b3bf 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -305,12 +305,6 @@ bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
}
}
-void tlb_fill(CPUState *cs, target_ulong vaddr, int size,
- MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
-{
- xtensa_cpu_tlb_fill(cs, vaddr, size, access_type, mmu_idx, false, retaddr);
-}
-
void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
unsigned size, MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 26/27] tcg: Remove CPUClass::handle_mmu_fault
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (24 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 25/27] tcg: Use CPUClass::tlb_fill in cputlb.c Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 27/27] tcg: Use tlb_fill probe from tlb_vaddr_to_host Richard Henderson
26 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
This hook is now completely replaced by tlb_fill.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/qom/cpu.h | 3 ---
accel/tcg/user-exec.c | 13 +++----------
2 files changed, 3 insertions(+), 13 deletions(-)
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index c1f267b4e0..32983f27c3 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -117,7 +117,6 @@ struct TranslationBlock;
* This always includes at least the program counter; some targets
* will need to do more. If this hook is not implemented then the
* default is to call @set_pc(tb->pc).
- * @handle_mmu_fault: Callback for handling an MMU fault.
* @tlb_fill: Callback for handling a softmmu tlb miss or user-only
* address fault. For system mode, if the access is valid, call
* tlb_set_page and return true; if the access is invalid, and
@@ -195,8 +194,6 @@ typedef struct CPUClass {
Error **errp);
void (*set_pc)(CPUState *cpu, vaddr value);
void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
- int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int size, int rw,
- int mmu_index);
bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 199f88c826..8cfbeb1b56 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -63,7 +63,6 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
{
CPUState *cpu = current_cpu;
CPUClass *cc;
- int ret;
unsigned long address = (unsigned long)info->si_addr;
MMUAccessType access_type;
@@ -156,15 +155,9 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
helper_retaddr = 0;
cc = CPU_GET_CLASS(cpu);
- if (cc->tlb_fill) {
- access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
- cc->tlb_fill(cpu, address, 0, access_type, MMU_USER_IDX, false, pc);
- g_assert_not_reached();
- } else {
- ret = cc->handle_mmu_fault(cpu, address, 0, is_write, MMU_USER_IDX);
- g_assert(ret > 0);
- cpu_loop_exit_restore(cpu, pc);
- }
+ access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
+ cc->tlb_fill(cpu, address, 0, access_type, MMU_USER_IDX, false, pc);
+ g_assert_not_reached();
}
#if defined(__i386__)
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PATCH v2 27/27] tcg: Use tlb_fill probe from tlb_vaddr_to_host
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
` (25 preceding siblings ...)
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 26/27] tcg: Remove CPUClass::handle_mmu_fault Richard Henderson
@ 2019-05-09 6:02 ` Richard Henderson
2019-05-09 9:56 ` Philippe Mathieu-Daudé
26 siblings, 1 reply; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 6:02 UTC (permalink / raw)
To: qemu-devel
Most of the existing users would continue around a loop which
would fault the tlb entry in via a normal load/store. But for
SVE we have a true non-faulting case which requires the new
probing form of tlb_fill.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Update function docs comment.
---
include/exec/cpu_ldst.h | 50 ++++++-----------------------
accel/tcg/cputlb.c | 69 ++++++++++++++++++++++++++++++++++++-----
target/arm/sve_helper.c | 6 +---
3 files changed, 72 insertions(+), 53 deletions(-)
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index d78041d7a0..7b28a839d2 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -433,50 +433,20 @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
* @mmu_idx: MMU index to use for lookup
*
* Look up the specified guest virtual index in the TCG softmmu TLB.
- * If the TLB contains a host virtual address suitable for direct RAM
- * access, then return it. Otherwise (TLB miss, TLB entry is for an
- * I/O access, etc) return NULL.
- *
- * This is the equivalent of the initial fast-path code used by
- * TCG backends for guest load and store accesses.
+ * If we can translate a host virtual address suitable for direct RAM
+ * access, without causing a guest exception, then return it.
+ * Otherwise (TLB entry is for an I/O access, guest software
+ * TLB fill required, etc) return NULL.
*/
+#ifdef CONFIG_USER_ONLY
static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
- int access_type, int mmu_idx)
+ MMUAccessType access_type, int mmu_idx)
{
-#if defined(CONFIG_USER_ONLY)
return g2h(addr);
-#else
- CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr);
- abi_ptr tlb_addr;
- uintptr_t haddr;
-
- switch (access_type) {
- case 0:
- tlb_addr = tlbentry->addr_read;
- break;
- case 1:
- tlb_addr = tlb_addr_write(tlbentry);
- break;
- case 2:
- tlb_addr = tlbentry->addr_code;
- break;
- default:
- g_assert_not_reached();
- }
-
- if (!tlb_hit(tlb_addr, addr)) {
- /* TLB entry is for a different page */
- return NULL;
- }
-
- if (tlb_addr & ~TARGET_PAGE_MASK) {
- /* IO access */
- return NULL;
- }
-
- haddr = addr + tlbentry->addend;
- return (void *)haddr;
-#endif /* defined(CONFIG_USER_ONLY) */
}
+#else
+void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
+ MMUAccessType access_type, int mmu_idx);
+#endif
#endif /* CPU_LDST_H */
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index dfcd9ae168..45a5c4e123 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1007,6 +1007,16 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
}
}
+static inline target_ulong tlb_read_ofs(CPUTLBEntry *entry, size_t ofs)
+{
+#if TCG_OVERSIZED_GUEST
+ return *(target_ulong *)((uintptr_t)entry + ofs);
+#else
+ /* ofs might correspond to .addr_write, so use atomic_read */
+ return atomic_read((target_ulong *)((uintptr_t)entry + ofs));
+#endif
+}
+
/* Return true if ADDR is present in the victim tlb, and has been copied
back to the main tlb. */
static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
@@ -1017,14 +1027,7 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
assert_cpu_is_self(ENV_GET_CPU(env));
for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
- target_ulong cmp;
-
- /* elt_ofs might correspond to .addr_write, so use atomic_read */
-#if TCG_OVERSIZED_GUEST
- cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
-#else
- cmp = atomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs));
-#endif
+ target_ulong cmp = tlb_read_ofs(vtlb, elt_ofs);
if (cmp == page) {
/* Found entry in victim tlb, swap tlb and iotlb. */
@@ -1108,6 +1111,56 @@ void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
}
}
+void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
+ MMUAccessType access_type, int mmu_idx)
+{
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ uintptr_t tlb_addr, page;
+ size_t elt_ofs;
+
+ switch (access_type) {
+ case MMU_DATA_LOAD:
+ elt_ofs = offsetof(CPUTLBEntry, addr_read);
+ break;
+ case MMU_DATA_STORE:
+ elt_ofs = offsetof(CPUTLBEntry, addr_write);
+ break;
+ case MMU_INST_FETCH:
+ elt_ofs = offsetof(CPUTLBEntry, addr_code);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ page = addr & TARGET_PAGE_MASK;
+ tlb_addr = tlb_read_ofs(entry, elt_ofs);
+
+ if (!tlb_hit_page(tlb_addr, page)) {
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+
+ if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page)) {
+ CPUState *cs = ENV_GET_CPU(env);
+ CPUClass *cc = CPU_GET_CLASS(cs);
+
+ if (!cc->tlb_fill(cs, addr, 0, access_type, mmu_idx, true, 0)) {
+ /* Non-faulting page table read failed. */
+ return NULL;
+ }
+
+ /* TLB resize via tlb_fill may have moved the entry. */
+ entry = tlb_entry(env, mmu_idx, addr);
+ }
+ tlb_addr = tlb_read_ofs(entry, elt_ofs);
+ }
+
+ if (tlb_addr & ~TARGET_PAGE_MASK) {
+ /* IO access */
+ return NULL;
+ }
+
+ return (void *)(addr + entry->addend);
+}
+
/* Probe for a read-modify-write atomic operation. Do not allow unaligned
* operations, or io operations to proceed. Return the host address. */
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
index bc847250dd..fd434c66ea 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -4598,11 +4598,7 @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr,
* in the real world, obviously.)
*
* Then there are the annoying special cases with watchpoints...
- *
- * TODO: Add a form of tlb_fill that does not raise an exception,
- * with a form of tlb_vaddr_to_host and a set of loads to match.
- * The non_fault_vaddr_to_host would handle everything, usually,
- * and the loads would handle the iomem path for watchpoints.
+ * TODO: Add a form of non-faulting loads using cc->tlb_fill(probe=true).
*/
host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
split = max_for_page(addr, mem_off, mem_max);
--
2.17.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 18/27] target/s390x: Convert to CPUClass::tlb_fill
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 18/27] target/s390x: " Richard Henderson
@ 2019-05-09 7:04 ` David Hildenbrand
0 siblings, 0 replies; 41+ messages in thread
From: David Hildenbrand @ 2019-05-09 7:04 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-s390x, Cornelia Huck
On 09.05.19 08:02, Richard Henderson wrote:
> Cc: qemu-s390x@nongnu.org
> Cc: Cornelia Huck <cohuck@redhat.com>
> Cc: David Hildenbrand <david@redhat.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v2: Keep user-only and system tlb_fill separate.
> ---
> target/s390x/internal.h | 5 +--
> target/s390x/cpu.c | 5 ++-
> target/s390x/excp_helper.c | 73 ++++++++++++++++++++++++++------------
> target/s390x/mem_helper.c | 16 ---------
> 4 files changed, 55 insertions(+), 44 deletions(-)
>
> diff --git a/target/s390x/internal.h b/target/s390x/internal.h
> index 26575f2130..56534b38e0 100644
> --- a/target/s390x/internal.h
> +++ b/target/s390x/internal.h
> @@ -263,8 +263,9 @@ ObjectClass *s390_cpu_class_by_name(const char *name);
> void s390x_cpu_debug_excp_handler(CPUState *cs);
> void s390_cpu_do_interrupt(CPUState *cpu);
> bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
> -int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
> - int mmu_idx);
> +bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> + MMUAccessType access_type, int mmu_idx,
> + bool probe, uintptr_t retaddr);
> void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
> MMUAccessType access_type,
> int mmu_idx, uintptr_t retaddr);
> diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
> index b58ef0a8ef..e28939032b 100644
> --- a/target/s390x/cpu.c
> +++ b/target/s390x/cpu.c
> @@ -478,9 +478,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
> cc->set_pc = s390_cpu_set_pc;
> cc->gdb_read_register = s390_cpu_gdb_read_register;
> cc->gdb_write_register = s390_cpu_gdb_write_register;
> -#ifdef CONFIG_USER_ONLY
> - cc->handle_mmu_fault = s390_cpu_handle_mmu_fault;
> -#else
> + cc->tlb_fill = s390_cpu_tlb_fill;
> +#ifndef CONFIG_USER_ONLY
> cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
> cc->vmsd = &vmstate_s390_cpu;
> cc->write_elf64_note = s390_cpu_write_elf64_note;
> diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
> index f84bfb1284..a4e134bcab 100644
> --- a/target/s390x/excp_helper.c
> +++ b/target/s390x/excp_helper.c
> @@ -74,8 +74,9 @@ void s390_cpu_do_interrupt(CPUState *cs)
> cs->exception_index = -1;
> }
>
> -int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
> - int rw, int mmu_idx)
> +bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> + MMUAccessType access_type, int mmu_idx,
> + bool probe, uintptr_t retaddr)
> {
> S390CPU *cpu = S390_CPU(cs);
>
> @@ -83,7 +84,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
> /* On real machines this value is dropped into LowMem. Since this
> is userland, simply put this someplace that cpu_loop can find it. */
> cpu->env.__excp_addr = address;
> - return 1;
> + cpu_loop_exit_restore(cs, retaddr);
> }
>
> #else /* !CONFIG_USER_ONLY */
> @@ -102,19 +103,20 @@ static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
> }
> }
>
> -int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size,
> - int rw, int mmu_idx)
> +bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> + MMUAccessType access_type, int mmu_idx,
> + bool probe, uintptr_t retaddr)
> {
> S390CPU *cpu = S390_CPU(cs);
> CPUS390XState *env = &cpu->env;
> target_ulong vaddr, raddr;
> uint64_t asc;
> - int prot;
> + int prot, fail;
>
> qemu_log_mask(CPU_LOG_MMU, "%s: addr 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
> - __func__, orig_vaddr, rw, mmu_idx);
> + __func__, address, access_type, mmu_idx);
>
> - vaddr = orig_vaddr;
> + vaddr = address;
>
> if (mmu_idx < MMU_REAL_IDX) {
> asc = cpu_mmu_idx_to_asc(mmu_idx);
> @@ -122,39 +124,64 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int size,
> if (!(env->psw.mask & PSW_MASK_64)) {
> vaddr &= 0x7fffffff;
> }
> - if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) {
> - return 1;
> - }
> + fail = mmu_translate(env, vaddr, access_type, asc, &raddr, &prot, true);
> } else if (mmu_idx == MMU_REAL_IDX) {
> /* 31-Bit mode */
> if (!(env->psw.mask & PSW_MASK_64)) {
> vaddr &= 0x7fffffff;
> }
> - if (mmu_translate_real(env, vaddr, rw, &raddr, &prot)) {
> - return 1;
> - }
> + fail = mmu_translate_real(env, vaddr, access_type, &raddr, &prot);
> } else {
> - abort();
> + g_assert_not_reached();
> }
>
> /* check out of RAM access */
> - if (!address_space_access_valid(&address_space_memory, raddr,
> - TARGET_PAGE_SIZE, rw,
> + if (!fail &&
> + !address_space_access_valid(&address_space_memory, raddr,
> + TARGET_PAGE_SIZE, access_type,
> MEMTXATTRS_UNSPECIFIED)) {
> qemu_log_mask(CPU_LOG_MMU,
> "%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n",
> __func__, (uint64_t)raddr, (uint64_t)ram_size);
> trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO);
> - return 1;
> + fail = 1;
> }
>
> - qemu_log_mask(CPU_LOG_MMU, "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n",
> - __func__, (uint64_t)vaddr, (uint64_t)raddr, prot);
> + if (!fail) {
> + qemu_log_mask(CPU_LOG_MMU,
> + "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n",
> + __func__, (uint64_t)vaddr, (uint64_t)raddr, prot);
> + tlb_set_page(cs, address & TARGET_PAGE_MASK, raddr, prot,
> + mmu_idx, TARGET_PAGE_SIZE);
> + return true;
> + }
> + if (probe) {
> + return false;
> + }
>
> - tlb_set_page(cs, orig_vaddr & TARGET_PAGE_MASK, raddr, prot,
> - mmu_idx, TARGET_PAGE_SIZE);
> + cpu_restore_state(cs, retaddr, true);
>
> - return 0;
> + /*
> + * The ILC value for code accesses is undefined. The important
> + * thing here is to *not* leave env->int_pgm_ilen set to ILEN_AUTO,
> + * which would cause do_program_interrupt to attempt to read from
> + * env->psw.addr again. C.f. the condition in trigger_page_fault,
> + * but is not universally applied.
> + *
> + * ??? If we remove ILEN_AUTO, by moving the computation of ILEN
> + * into cpu_restore_state, then we may remove this entirely.
> + */
> + if (access_type == MMU_INST_FETCH) {
> + env->int_pgm_ilen = 2;
> + }
> +
> + cpu_loop_exit(cs);
> +}
> +
> +void tlb_fill(CPUState *cs, target_ulong addr, int size,
> + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
> +{
> + s390_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
> }
>
> static void do_program_interrupt(CPUS390XState *env)
> diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
> index 3f76a8abfd..ffd5f02fbe 100644
> --- a/target/s390x/mem_helper.c
> +++ b/target/s390x/mem_helper.c
> @@ -33,22 +33,6 @@
>
> /*****************************************************************************/
> /* Softmmu support */
> -#if !defined(CONFIG_USER_ONLY)
> -
> -/* try to fill the TLB and return an exception if error. If retaddr is
> - NULL, it means that the function was called in C code (i.e. not
> - from generated code or from helper.c) */
> -/* XXX: fix it to restore all registers */
> -void tlb_fill(CPUState *cs, target_ulong addr, int size,
> - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
> -{
> - int ret = s390_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
> - if (unlikely(ret != 0)) {
> - cpu_loop_exit_restore(cs, retaddr);
> - }
> -}
> -
> -#endif
>
> /* #define DEBUG_HELPER */
> #ifdef DEBUG_HELPER
>
Reviewed-by: David Hildenbrand <david@redhat.com>
--
Thanks,
David / dhildenb
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 22/27] target/tricore: Convert to CPUClass::tlb_fill
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 22/27] target/tricore: " Richard Henderson
@ 2019-05-09 9:43 ` Bastian Koppelmann
0 siblings, 0 replies; 41+ messages in thread
From: Bastian Koppelmann @ 2019-05-09 9:43 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 5/9/19 8:02 AM, Richard Henderson wrote:
> Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/tricore/cpu.h | 6 +++---
> target/tricore/cpu.c | 1 +
> target/tricore/helper.c | 27 +++++++++++++++++++--------
> target/tricore/op_helper.c | 26 --------------------------
> 4 files changed, 23 insertions(+), 37 deletions(-)
Acked-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cheers,
Bastian
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 10/27] target/mips: Pass a valid error to raise_mmu_exception for user-only
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 10/27] target/mips: Pass a valid error to raise_mmu_exception for user-only Richard Henderson
@ 2019-05-09 9:45 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 41+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-05-09 9:45 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 5/9/19 8:02 AM, Richard Henderson wrote:
> At present we give ret = 0, or TLBRET_MATCH. This gets matched
> by the default case, which falls through to TLBRET_BADADDR.
> However, it makes more sense to use a proper value. All of the
> tlb-related exceptions are handled identically in cpu_loop.c,
> so TLBRET_BADADDR is as good as any other. Retain it.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/mips/helper.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/mips/helper.c b/target/mips/helper.c
> index c44cdca3b5..cc7be7703a 100644
> --- a/target/mips/helper.c
> +++ b/target/mips/helper.c
> @@ -884,7 +884,7 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
> int prot;
> int access_type;
> #endif
> - int ret = 0;
> + int ret = TLBRET_BADADDR;
>
> #if 0
> log_cpu_state(cs, 0);
>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 12/27] target/mips: Convert to CPUClass::tlb_fill
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 12/27] target/mips: Convert to CPUClass::tlb_fill Richard Henderson
@ 2019-05-09 9:50 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 41+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-05-09 9:50 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: Aleksandar Rikalo, Aleksandar Markovic
On 5/9/19 8:02 AM, Richard Henderson wrote:
> Note that env->active_tc.PC is removed from the qemu_log as that value
> is garbage. The PC isn't recovered until cpu_restore_state, called from
> cpu_loop_exit_restore, called from do_raise_exception_err.
>
> Cc: Aleksandar Markovic <amarkovic@wavecomp.com>
> Cc: Aleksandar Rikalo <arikalo@wavecomp.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v2: Split out other mips cleanups to simplify the diff
> ---
> target/mips/internal.h | 5 +++--
> target/mips/cpu.c | 5 ++---
> target/mips/helper.c | 45 ++++++++++++++++++++++-------------------
> target/mips/op_helper.c | 15 --------------
> 4 files changed, 29 insertions(+), 41 deletions(-)
>
> diff --git a/target/mips/internal.h b/target/mips/internal.h
> index 286e3888ab..b2b41a51ab 100644
> --- a/target/mips/internal.h
> +++ b/target/mips/internal.h
> @@ -202,8 +202,9 @@ void cpu_mips_start_count(CPUMIPSState *env);
> void cpu_mips_stop_count(CPUMIPSState *env);
>
> /* helper.c */
> -int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
> - int mmu_idx);
> +bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> + MMUAccessType access_type, int mmu_idx,
> + bool probe, uintptr_t retaddr);
>
> /* op_helper.c */
> uint32_t float_class_s(uint32_t arg, float_status *fst);
> diff --git a/target/mips/cpu.c b/target/mips/cpu.c
> index e217fb3e36..ebdb834b97 100644
> --- a/target/mips/cpu.c
> +++ b/target/mips/cpu.c
> @@ -197,9 +197,8 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
> cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
> cc->gdb_read_register = mips_cpu_gdb_read_register;
> cc->gdb_write_register = mips_cpu_gdb_write_register;
> -#ifdef CONFIG_USER_ONLY
> - cc->handle_mmu_fault = mips_cpu_handle_mmu_fault;
> -#else
> + cc->tlb_fill = mips_cpu_tlb_fill;
> +#ifndef CONFIG_USER_ONLY
> cc->do_unassigned_access = mips_cpu_unassigned_access;
> cc->do_unaligned_access = mips_cpu_do_unaligned_access;
> cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
> diff --git a/target/mips/helper.c b/target/mips/helper.c
> index 86e622efb8..3a4917ce7b 100644
> --- a/target/mips/helper.c
> +++ b/target/mips/helper.c
> @@ -874,31 +874,25 @@ refill:
> #endif
> #endif
>
> -int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
> - int mmu_idx)
> +bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> + MMUAccessType access_type, int mmu_idx,
> + bool probe, uintptr_t retaddr)
> {
> MIPSCPU *cpu = MIPS_CPU(cs);
> CPUMIPSState *env = &cpu->env;
> #if !defined(CONFIG_USER_ONLY)
> hwaddr physical;
> int prot;
> - int access_type;
> + int mips_access_type;
> #endif
> int ret = TLBRET_BADADDR;
>
> -#if 0
> - log_cpu_state(cs, 0);
> -#endif
> - qemu_log_mask(CPU_LOG_MMU,
> - "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
> - __func__, env->active_tc.PC, address, rw, mmu_idx);
> -
> /* data access */
> #if !defined(CONFIG_USER_ONLY)
> /* XXX: put correct access by using cpu_restore_state() correctly */
> - access_type = ACCESS_INT;
> - ret = get_physical_address(env, &physical, &prot,
> - address, rw, access_type, mmu_idx);
> + mips_access_type = ACCESS_INT;
> + ret = get_physical_address(env, &physical, &prot, address,
> + access_type, mips_access_type, mmu_idx);
> switch (ret) {
> case TLBRET_MATCH:
> qemu_log_mask(CPU_LOG_MMU,
> @@ -915,7 +909,7 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
> tlb_set_page(cs, address & TARGET_PAGE_MASK,
> physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
> mmu_idx, TARGET_PAGE_SIZE);
> - return 0;
> + return true;
> }
> #if !defined(TARGET_MIPS64)
> if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) {
> @@ -926,27 +920,36 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
> int mode = (env->hflags & MIPS_HFLAG_KSU);
> bool ret_walker;
> env->hflags &= ~MIPS_HFLAG_KSU;
> - ret_walker = page_table_walk_refill(env, address, rw, mmu_idx);
> + ret_walker = page_table_walk_refill(env, address, access_type, mmu_idx);
> env->hflags |= mode;
> if (ret_walker) {
> - ret = get_physical_address(env, &physical, &prot,
> - address, rw, access_type, mmu_idx);
> + ret = get_physical_address(env, &physical, &prot, address,
> + access_type, mips_access_type, mmu_idx);
> if (ret == TLBRET_MATCH) {
> tlb_set_page(cs, address & TARGET_PAGE_MASK,
> physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
> mmu_idx, TARGET_PAGE_SIZE);
> - return 0;
> + return true;
> }
> }
> }
> #endif
> + if (probe) {
> + return false;
> + }
> #endif
>
> - raise_mmu_exception(env, address, rw, ret);
> - return 1;
> + raise_mmu_exception(env, address, access_type, ret);
> + do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr);
> +}
> +
> +#ifndef CONFIG_USER_ONLY
> +void tlb_fill(CPUState *cs, target_ulong addr, int size,
> + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
> +{
> + mips_cpu_tlb_fill(cs, addr, size, access_type, mmu_idx, false, retaddr);
> }
>
> -#if !defined(CONFIG_USER_ONLY)
> hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw)
> {
> hwaddr physical;
> diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
> index 0f272a5b93..6d86912958 100644
> --- a/target/mips/op_helper.c
> +++ b/target/mips/op_helper.c
> @@ -2669,21 +2669,6 @@ void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
> do_raise_exception_err(env, excp, error_code, retaddr);
> }
>
> -void tlb_fill(CPUState *cs, target_ulong addr, int size,
> - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
> -{
> - int ret;
> -
> - ret = mips_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
> - if (ret) {
> - MIPSCPU *cpu = MIPS_CPU(cs);
> - CPUMIPSState *env = &cpu->env;
> -
> - do_raise_exception_err(env, cs->exception_index,
> - env->error_code, retaddr);
> - }
> -}
> -
> void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr,
> bool is_write, bool is_exec, int unused,
> unsigned size)
>
Ah! Way easier to review than v1 (thanks Peter for suggesting the split).
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 24/27] target/xtensa: Convert to CPUClass::tlb_fill
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 24/27] target/xtensa: " Richard Henderson
@ 2019-05-09 9:56 ` Peter Maydell
0 siblings, 0 replies; 41+ messages in thread
From: Peter Maydell @ 2019-05-09 9:56 UTC (permalink / raw)
To: Richard Henderson; +Cc: Max Filippov, QEMU Developers
On Thu, 9 May 2019 at 07:20, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Cc: Max Filippov <jcmvbkbc@gmail.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v2: Keep user-only and system tlb_fill separate.
> ---
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 27/27] tcg: Use tlb_fill probe from tlb_vaddr_to_host
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 27/27] tcg: Use tlb_fill probe from tlb_vaddr_to_host Richard Henderson
@ 2019-05-09 9:56 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 41+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-05-09 9:56 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 5/9/19 8:02 AM, Richard Henderson wrote:
> Most of the existing users would continue around a loop which
> would fault the tlb entry in via a normal load/store. But for
> SVE we have a true non-faulting case which requires the new
> probing form of tlb_fill.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v2: Update function docs comment.
> ---
> include/exec/cpu_ldst.h | 50 ++++++-----------------------
> accel/tcg/cputlb.c | 69 ++++++++++++++++++++++++++++++++++++-----
> target/arm/sve_helper.c | 6 +---
> 3 files changed, 72 insertions(+), 53 deletions(-)
>
> diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
> index d78041d7a0..7b28a839d2 100644
> --- a/include/exec/cpu_ldst.h
> +++ b/include/exec/cpu_ldst.h
> @@ -433,50 +433,20 @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
> * @mmu_idx: MMU index to use for lookup
> *
> * Look up the specified guest virtual index in the TCG softmmu TLB.
> - * If the TLB contains a host virtual address suitable for direct RAM
> - * access, then return it. Otherwise (TLB miss, TLB entry is for an
> - * I/O access, etc) return NULL.
> - *
> - * This is the equivalent of the initial fast-path code used by
> - * TCG backends for guest load and store accesses.
> + * If we can translate a host virtual address suitable for direct RAM
> + * access, without causing a guest exception, then return it.
> + * Otherwise (TLB entry is for an I/O access, guest software
> + * TLB fill required, etc) return NULL.
> */
> +#ifdef CONFIG_USER_ONLY
> static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
> - int access_type, int mmu_idx)
> + MMUAccessType access_type, int mmu_idx)
> {
> -#if defined(CONFIG_USER_ONLY)
> return g2h(addr);
> -#else
> - CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr);
> - abi_ptr tlb_addr;
> - uintptr_t haddr;
> -
> - switch (access_type) {
> - case 0:
> - tlb_addr = tlbentry->addr_read;
> - break;
> - case 1:
> - tlb_addr = tlb_addr_write(tlbentry);
> - break;
> - case 2:
> - tlb_addr = tlbentry->addr_code;
> - break;
> - default:
> - g_assert_not_reached();
> - }
> -
> - if (!tlb_hit(tlb_addr, addr)) {
> - /* TLB entry is for a different page */
> - return NULL;
> - }
> -
> - if (tlb_addr & ~TARGET_PAGE_MASK) {
> - /* IO access */
> - return NULL;
> - }
> -
> - haddr = addr + tlbentry->addend;
> - return (void *)haddr;
> -#endif /* defined(CONFIG_USER_ONLY) */
> }
> +#else
> +void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
> + MMUAccessType access_type, int mmu_idx);
> +#endif
>
> #endif /* CPU_LDST_H */
> diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
> index dfcd9ae168..45a5c4e123 100644
> --- a/accel/tcg/cputlb.c
> +++ b/accel/tcg/cputlb.c
> @@ -1007,6 +1007,16 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
> }
> }
>
> +static inline target_ulong tlb_read_ofs(CPUTLBEntry *entry, size_t ofs)
> +{
> +#if TCG_OVERSIZED_GUEST
> + return *(target_ulong *)((uintptr_t)entry + ofs);
> +#else
> + /* ofs might correspond to .addr_write, so use atomic_read */
> + return atomic_read((target_ulong *)((uintptr_t)entry + ofs));
> +#endif
> +}
> +
> /* Return true if ADDR is present in the victim tlb, and has been copied
> back to the main tlb. */
> static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
> @@ -1017,14 +1027,7 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
> assert_cpu_is_self(ENV_GET_CPU(env));
> for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
> CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
> - target_ulong cmp;
> -
> - /* elt_ofs might correspond to .addr_write, so use atomic_read */
> -#if TCG_OVERSIZED_GUEST
> - cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
> -#else
> - cmp = atomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs));
> -#endif
> + target_ulong cmp = tlb_read_ofs(vtlb, elt_ofs);
>
> if (cmp == page) {
> /* Found entry in victim tlb, swap tlb and iotlb. */
> @@ -1108,6 +1111,56 @@ void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
> }
> }
>
> +void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
> + MMUAccessType access_type, int mmu_idx)
> +{
> + CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
> + uintptr_t tlb_addr, page;
> + size_t elt_ofs;
> +
> + switch (access_type) {
> + case MMU_DATA_LOAD:
> + elt_ofs = offsetof(CPUTLBEntry, addr_read);
> + break;
> + case MMU_DATA_STORE:
> + elt_ofs = offsetof(CPUTLBEntry, addr_write);
> + break;
> + case MMU_INST_FETCH:
> + elt_ofs = offsetof(CPUTLBEntry, addr_code);
> + break;
> + default:
> + g_assert_not_reached();
> + }
> +
> + page = addr & TARGET_PAGE_MASK;
> + tlb_addr = tlb_read_ofs(entry, elt_ofs);
> +
> + if (!tlb_hit_page(tlb_addr, page)) {
> + uintptr_t index = tlb_index(env, mmu_idx, addr);
> +
> + if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page)) {
> + CPUState *cs = ENV_GET_CPU(env);
> + CPUClass *cc = CPU_GET_CLASS(cs);
> +
> + if (!cc->tlb_fill(cs, addr, 0, access_type, mmu_idx, true, 0)) {
> + /* Non-faulting page table read failed. */
> + return NULL;
> + }
> +
> + /* TLB resize via tlb_fill may have moved the entry. */
> + entry = tlb_entry(env, mmu_idx, addr);
> + }
> + tlb_addr = tlb_read_ofs(entry, elt_ofs);
> + }
> +
> + if (tlb_addr & ~TARGET_PAGE_MASK) {
> + /* IO access */
> + return NULL;
> + }
> +
> + return (void *)(addr + entry->addend);
> +}
> +
> /* Probe for a read-modify-write atomic operation. Do not allow unaligned
> * operations, or io operations to proceed. Return the host address. */
> static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
> diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
> index bc847250dd..fd434c66ea 100644
> --- a/target/arm/sve_helper.c
> +++ b/target/arm/sve_helper.c
> @@ -4598,11 +4598,7 @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr,
> * in the real world, obviously.)
> *
> * Then there are the annoying special cases with watchpoints...
> - *
> - * TODO: Add a form of tlb_fill that does not raise an exception,
> - * with a form of tlb_vaddr_to_host and a set of loads to match.
> - * The non_fault_vaddr_to_host would handle everything, usually,
> - * and the loads would handle the iomem path for watchpoints.
> + * TODO: Add a form of non-faulting loads using cc->tlb_fill(probe=true).
> */
> host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
> split = max_for_page(addr, mem_off, mem_max);
>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 09/27] target/microblaze: Convert to CPUClass::tlb_fill
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 09/27] target/microblaze: " Richard Henderson
@ 2019-05-09 9:59 ` Peter Maydell
0 siblings, 0 replies; 41+ messages in thread
From: Peter Maydell @ 2019-05-09 9:59 UTC (permalink / raw)
To: Richard Henderson; +Cc: Edgar E . Iglesias, QEMU Developers
On Thu, 9 May 2019 at 07:08, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v2: Keep user-only and system tlb_fill separate.
> ---
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 11/27] target/mips: Tidy control flow in mips_cpu_handle_mmu_fault
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 11/27] target/mips: Tidy control flow in mips_cpu_handle_mmu_fault Richard Henderson
@ 2019-05-09 10:01 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 41+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-05-09 10:01 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 5/9/19 8:02 AM, Richard Henderson wrote:
> Since the only non-negative TLBRET_* value is TLBRET_MATCH,
> the subsequent test for ret < 0 is useless. Use early return
> to allow subsequent blocks to be unindented.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/mips/helper.c | 54 ++++++++++++++++++++------------------------
> 1 file changed, 24 insertions(+), 30 deletions(-)
>
> diff --git a/target/mips/helper.c b/target/mips/helper.c
> index cc7be7703a..86e622efb8 100644
> --- a/target/mips/helper.c
> +++ b/target/mips/helper.c
> @@ -915,41 +915,35 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
> tlb_set_page(cs, address & TARGET_PAGE_MASK,
> physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
> mmu_idx, TARGET_PAGE_SIZE);
> - ret = 0;
> - } else if (ret < 0)
> -#endif
> - {
> -#if !defined(CONFIG_USER_ONLY)
> + return 0;
> + }
> #if !defined(TARGET_MIPS64)
> - if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) {
> - /*
> - * Memory reads during hardware page table walking are performed
> - * as if they were kernel-mode load instructions.
> - */
> - int mode = (env->hflags & MIPS_HFLAG_KSU);
> - bool ret_walker;
> - env->hflags &= ~MIPS_HFLAG_KSU;
> - ret_walker = page_table_walk_refill(env, address, rw, mmu_idx);
> - env->hflags |= mode;
> - if (ret_walker) {
> - ret = get_physical_address(env, &physical, &prot,
> - address, rw, access_type, mmu_idx);
> - if (ret == TLBRET_MATCH) {
> - tlb_set_page(cs, address & TARGET_PAGE_MASK,
> - physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
> - mmu_idx, TARGET_PAGE_SIZE);
> - ret = 0;
> - return ret;
> - }
> + if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) {
> + /*
> + * Memory reads during hardware page table walking are performed
> + * as if they were kernel-mode load instructions.
> + */
> + int mode = (env->hflags & MIPS_HFLAG_KSU);
> + bool ret_walker;
> + env->hflags &= ~MIPS_HFLAG_KSU;
> + ret_walker = page_table_walk_refill(env, address, rw, mmu_idx);
> + env->hflags |= mode;
> + if (ret_walker) {
> + ret = get_physical_address(env, &physical, &prot,
> + address, rw, access_type, mmu_idx);
> + if (ret == TLBRET_MATCH) {
> + tlb_set_page(cs, address & TARGET_PAGE_MASK,
> + physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
> + mmu_idx, TARGET_PAGE_SIZE);
> + return 0;
> }
> }
> -#endif
> -#endif
> - raise_mmu_exception(env, address, rw, ret);
> - ret = 1;
> }
> +#endif
> +#endif
>
> - return ret;
> + raise_mmu_exception(env, address, rw, ret);
> + return 1;
> }
>
> #if !defined(CONFIG_USER_ONLY)
>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 14/27] target/nios2: Convert to CPUClass::tlb_fill
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 14/27] target/nios2: " Richard Henderson
@ 2019-05-09 10:02 ` Peter Maydell
2019-05-09 15:43 ` Richard Henderson
0 siblings, 1 reply; 41+ messages in thread
From: Peter Maydell @ 2019-05-09 10:02 UTC (permalink / raw)
To: Richard Henderson; +Cc: Marek Vasut, Chris Wulff, QEMU Developers
On Thu, 9 May 2019 at 07:10, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Remove the leftover debugging cpu_dump_state.
>
> Cc: Chris Wulff <crwulff@gmail.com>
> Cc: Marek Vasut <marex@denx.de>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v2: Keep user-only and system tlb_fill separate.
> ---
> -int nios2_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
> - int rw, int mmu_idx)
> +bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> + MMUAccessType access_type, int mmu_idx,
> + bool probe, uintptr_t retaddr)
> {
> cs->exception_index = 0xaa;
> /* Page 0x1000 is kuser helper */
> if (address < 0x1000 || address >= 0x2000) {
> cpu_dump_state(cs, stderr, 0);
> }
> - return 1;
> + cpu_loop_exit_restore(cs, retaddr);
> }
Commit message says we delete cpu_dump_state() call but
the code doesn't seem to change it?
Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 20/27] target/sparc: Convert to CPUClass::tlb_fill
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 20/27] target/sparc: " Richard Henderson
@ 2019-05-09 13:35 ` Peter Maydell
2019-05-09 15:51 ` Richard Henderson
0 siblings, 1 reply; 41+ messages in thread
From: Peter Maydell @ 2019-05-09 13:35 UTC (permalink / raw)
To: Richard Henderson; +Cc: Mark Cave-Ayland, QEMU Developers, Artyom Tarasenko
On Thu, 9 May 2019 at 07:17, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Cc: Artyom Tarasenko <atar4qemu@gmail.com>
> Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v2: Keep user-only, sparc32, and sparc64 tlb_fill separate.
> ---
> target/sparc/cpu.h | 5 ++-
> target/sparc/cpu.c | 5 +--
> target/sparc/ldst_helper.c | 11 +-----
> target/sparc/mmu_helper.c | 78 ++++++++++++++++++++++----------------
> 4 files changed, 51 insertions(+), 48 deletions(-)
> /* Perform address translation */
> -int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
> - int mmu_idx)
> +bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> + MMUAccessType access_type, int mmu_idx,
> + bool probe, uintptr_t retaddr)
> {
> SPARCCPU *cpu = SPARC_CPU(cs);
> CPUSPARCState *env = &cpu->env;
> @@ -220,22 +222,18 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
>
> address &= TARGET_PAGE_MASK;
> error_code = get_physical_address(env, &paddr, &prot, &access_index,
> - address, rw, mmu_idx, &page_size);
> + address, access_type,
> + mmu_idx, &page_size);
> vaddr = address;
> - if (error_code == 0) {
> + if (likely(error_code == 0)) {
> qemu_log_mask(CPU_LOG_MMU,
> - "Translate at %" VADDR_PRIx " -> " TARGET_FMT_plx ", vaddr "
> - TARGET_FMT_lx "\n", address, paddr, vaddr);
> + "Translate at %" VADDR_PRIx " -> "
> + TARGET_FMT_plx ", vaddr " TARGET_FMT_lx "\n",
> + address, paddr, vaddr);
> tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
> - return 0;
> + return true;
> }
>
> - if (env->mmuregs[3]) { /* Fault status register */
> - env->mmuregs[3] = 1; /* overflow (not read before another fault) */
> - }
> - env->mmuregs[3] |= (access_index << 5) | error_code | 2;
> - env->mmuregs[4] = address; /* Fault address register */
> -
In the old code, we set these MMU registers before checking
for the MMU_NF case...
> if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
> /* No fault mode: if a mapping is available, just override
> permissions. If no mapping is available, redirect accesses to
> @@ -243,15 +241,25 @@ int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
> switching to normal mode. */
> prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
> - return 0;
> - } else {
> - if (rw & 2) {
> - cs->exception_index = TT_TFAULT;
> - } else {
> - cs->exception_index = TT_DFAULT;
> - }
> - return 1;
> + return true;
> }
> +
> + if (probe) {
> + return false;
> + }
> +
> + if (env->mmuregs[3]) { /* Fault status register */
> + env->mmuregs[3] = 1; /* overflow (not read before another fault) */
> + }
> + env->mmuregs[3] |= (access_index << 5) | error_code | 2;
> + env->mmuregs[4] = address; /* Fault address register */
> +
> + if (access_type == MMU_INST_FETCH) {
> + cs->exception_index = TT_TFAULT;
> + } else {
> + cs->exception_index = TT_DFAULT;
> + }
> + cpu_loop_exit_restore(cs, retaddr);
> }
...but in the new code we only set them if we're really
going to fault.
The v8 SPARC architecture manual appending H says that
when the NF bit is 1 faults detected by the MMU cause
FSR and FAR to be updated even though no fault is generated
to the processor. So I think the change here is not correct.
(The spec also says that ASI 9 is supposed to be special and
not affected by NF==1; and I think that since we put entries in
the TLB for the NF case we won't correctly set the fault address
register if the CPU makes two successive accesses to the same
page, because the second access won't take the slow path and
won't update the FAR. But those are pre-existing bugs.)
thanks
-- PMM
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 14/27] target/nios2: Convert to CPUClass::tlb_fill
2019-05-09 10:02 ` Peter Maydell
@ 2019-05-09 15:43 ` Richard Henderson
0 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 15:43 UTC (permalink / raw)
To: Peter Maydell; +Cc: Marek Vasut, Chris Wulff, QEMU Developers
On 5/9/19 3:02 AM, Peter Maydell wrote:
> On Thu, 9 May 2019 at 07:10, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> Remove the leftover debugging cpu_dump_state.
>>
>> Cc: Chris Wulff <crwulff@gmail.com>
>> Cc: Marek Vasut <marex@denx.de>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>> v2: Keep user-only and system tlb_fill separate.
>> ---
>
>> -int nios2_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size,
>> - int rw, int mmu_idx)
>> +bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>> + MMUAccessType access_type, int mmu_idx,
>> + bool probe, uintptr_t retaddr)
>> {
>> cs->exception_index = 0xaa;
>> /* Page 0x1000 is kuser helper */
>> if (address < 0x1000 || address >= 0x2000) {
>> cpu_dump_state(cs, stderr, 0);
>> }
>> - return 1;
>> + cpu_loop_exit_restore(cs, retaddr);
>> }
>
> Commit message says we delete cpu_dump_state() call but
> the code doesn't seem to change it?
>
> Otherwise
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Argh. Got lost in the other v2 changes.
r~
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 20/27] target/sparc: Convert to CPUClass::tlb_fill
2019-05-09 13:35 ` Peter Maydell
@ 2019-05-09 15:51 ` Richard Henderson
0 siblings, 0 replies; 41+ messages in thread
From: Richard Henderson @ 2019-05-09 15:51 UTC (permalink / raw)
To: Peter Maydell; +Cc: Mark Cave-Ayland, QEMU Developers, Artyom Tarasenko
On 5/9/19 6:35 AM, Peter Maydell wrote:
>> + if (probe) {
>> + return false;
>> + }
>> +
>> + if (env->mmuregs[3]) { /* Fault status register */
>> + env->mmuregs[3] = 1; /* overflow (not read before another fault) */
>> + }
>> + env->mmuregs[3] |= (access_index << 5) | error_code | 2;
>> + env->mmuregs[4] = address; /* Fault address register */
>> +
>> + if (access_type == MMU_INST_FETCH) {
>> + cs->exception_index = TT_TFAULT;
>> + } else {
>> + cs->exception_index = TT_DFAULT;
>> + }
>> + cpu_loop_exit_restore(cs, retaddr);
>> }
>
> ...but in the new code we only set them if we're really
> going to fault.
Yes, I made change assuming that would allow probe to work, which would seem to
require that the FSR not be modified.
> The v8 SPARC architecture manual appending H says that
> when the NF bit is 1 faults detected by the MMU cause
> FSR and FAR to be updated even though no fault is generated
> to the processor. So I think the change here is not correct.
>
> (The spec also says that ASI 9 is supposed to be special and
> not affected by NF==1; and I think that since we put entries in
> the TLB for the NF case we won't correctly set the fault address
> register if the CPU makes two successive accesses to the same
> page, because the second access won't take the slow path and
> won't update the FAR. But those are pre-existing bugs.)
Thanks for the pointers. They do look like pre-existing bugs.
I think the only thing to do for sparc is the same as i386 -- assert that probe
is unset. If someone ever decides to use tlb_vaddr_to_host from the sparc
backend, they'll have to come back and untangle this.
r~
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PATCH v2 01/27] tcg: Add CPUClass::tlb_fill
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 01/27] " Richard Henderson
@ 2019-05-09 17:39 ` Alistair Francis
0 siblings, 0 replies; 41+ messages in thread
From: Alistair Francis @ 2019-05-09 17:39 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel@nongnu.org Developers
On Wed, May 8, 2019 at 11:03 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This hook will replace the (user-only mode specific) handle_mmu_fault
> hook, and the (system mode specific) tlb_fill function.
>
> The handle_mmu_fault hook was written as if there was a valid
> way to recover from an mmu fault, and had 3 possible return states.
> In reality, the only valid action is to raise an exception,
> return to the main loop, and deliver the SIGSEGV to the guest.
>
> Note that all of the current implementations of handle_mmu_fault
> for guests which support linux-user do in fact only ever return 1,
> which is the signal to return to the main loop.
>
> Using the hook for system mode requires that all targets be converted,
> so for now the hook is (optionally) used only from user-only mode.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> include/qom/cpu.h | 9 +++++++++
> accel/tcg/user-exec.c | 39 ++++++++++++++-------------------------
> 2 files changed, 23 insertions(+), 25 deletions(-)
>
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index 08abcbd3fe..c1f267b4e0 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -118,6 +118,12 @@ struct TranslationBlock;
> * will need to do more. If this hook is not implemented then the
> * default is to call @set_pc(tb->pc).
> * @handle_mmu_fault: Callback for handling an MMU fault.
> + * @tlb_fill: Callback for handling a softmmu tlb miss or user-only
> + * address fault. For system mode, if the access is valid, call
> + * tlb_set_page and return true; if the access is invalid, and
> + * probe is true, return false; otherwise raise an exception and
> + * do not return. For user-only mode, always raise an exception
> + * and do not return.
> * @get_phys_page_debug: Callback for obtaining a physical address.
> * @get_phys_page_attrs_debug: Callback for obtaining a physical address and the
> * associated memory transaction attributes to use for the access.
> @@ -191,6 +197,9 @@ typedef struct CPUClass {
> void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
> int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int size, int rw,
> int mmu_index);
> + bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
> + MMUAccessType access_type, int mmu_idx,
> + bool probe, uintptr_t retaddr);
> hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
> hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
> MemTxAttrs *attrs);
> diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
> index 0789984fe6..199f88c826 100644
> --- a/accel/tcg/user-exec.c
> +++ b/accel/tcg/user-exec.c
> @@ -65,6 +65,7 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
> CPUClass *cc;
> int ret;
> unsigned long address = (unsigned long)info->si_addr;
> + MMUAccessType access_type;
>
> /* We must handle PC addresses from two different sources:
> * a call return address and a signal frame address.
> @@ -147,35 +148,23 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
> are still valid segv ones */
> address = h2g_nocheck(address);
>
> - cc = CPU_GET_CLASS(cpu);
> - /* see if it is an MMU fault */
> - g_assert(cc->handle_mmu_fault);
> - ret = cc->handle_mmu_fault(cpu, address, 0, is_write, MMU_USER_IDX);
> -
> - if (ret == 0) {
> - /* The MMU fault was handled without causing real CPU fault.
> - * Retain helper_retaddr for a possible second fault.
> - */
> - return 1;
> - }
> -
> - /* All other paths lead to cpu_exit; clear helper_retaddr
> - * for next execution.
> + /*
> + * There is no way the target can handle this other than raising
> + * an exception. Undo signal and retaddr state prior to longjmp.
> */
> + sigprocmask(SIG_SETMASK, old_set, NULL);
> helper_retaddr = 0;
>
> - if (ret < 0) {
> - return 0; /* not an MMU fault */
> + cc = CPU_GET_CLASS(cpu);
> + if (cc->tlb_fill) {
> + access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
> + cc->tlb_fill(cpu, address, 0, access_type, MMU_USER_IDX, false, pc);
> + g_assert_not_reached();
> + } else {
> + ret = cc->handle_mmu_fault(cpu, address, 0, is_write, MMU_USER_IDX);
> + g_assert(ret > 0);
> + cpu_loop_exit_restore(cpu, pc);
> }
> -
> - /* Now we have a real cpu fault. */
> - cpu_restore_state(cpu, pc, true);
> -
> - sigprocmask(SIG_SETMASK, old_set, NULL);
> - cpu_loop_exit(cpu);
> -
> - /* never comes here */
> - return 1;
> }
>
> #if defined(__i386__)
> --
> 2.17.1
>
>
^ permalink raw reply [flat|nested] 41+ messages in thread
end of thread, other threads:[~2019-05-09 17:42 UTC | newest]
Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-09 6:02 [Qemu-devel] [PATCH v2 00/27] tcg: Add CPUClass::tlb_fill Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 01/27] " Richard Henderson
2019-05-09 17:39 ` Alistair Francis
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 02/27] target/alpha: Convert to CPUClass::tlb_fill Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 03/27] target/arm: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 04/27] target/cris: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 05/27] target/hppa: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 06/27] target/i386: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 07/27] target/lm32: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 08/27] target/m68k: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 09/27] target/microblaze: " Richard Henderson
2019-05-09 9:59 ` Peter Maydell
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 10/27] target/mips: Pass a valid error to raise_mmu_exception for user-only Richard Henderson
2019-05-09 9:45 ` Philippe Mathieu-Daudé
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 11/27] target/mips: Tidy control flow in mips_cpu_handle_mmu_fault Richard Henderson
2019-05-09 10:01 ` Philippe Mathieu-Daudé
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 12/27] target/mips: Convert to CPUClass::tlb_fill Richard Henderson
2019-05-09 9:50 ` Philippe Mathieu-Daudé
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 13/27] target/moxie: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 14/27] target/nios2: " Richard Henderson
2019-05-09 10:02 ` Peter Maydell
2019-05-09 15:43 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 15/27] target/openrisc: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 16/27] target/ppc: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 17/27] target/riscv: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 18/27] target/s390x: " Richard Henderson
2019-05-09 7:04 ` David Hildenbrand
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 19/27] target/sh4: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 20/27] target/sparc: " Richard Henderson
2019-05-09 13:35 ` Peter Maydell
2019-05-09 15:51 ` Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 21/27] target/tilegx: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 22/27] target/tricore: " Richard Henderson
2019-05-09 9:43 ` Bastian Koppelmann
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 23/27] target/unicore32: " Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 24/27] target/xtensa: " Richard Henderson
2019-05-09 9:56 ` Peter Maydell
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 25/27] tcg: Use CPUClass::tlb_fill in cputlb.c Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 26/27] tcg: Remove CPUClass::handle_mmu_fault Richard Henderson
2019-05-09 6:02 ` [Qemu-devel] [PATCH v2 27/27] tcg: Use tlb_fill probe from tlb_vaddr_to_host Richard Henderson
2019-05-09 9:56 ` Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).