summaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-07-03 14:59:27 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-07-03 14:59:27 +0100
commitb07cd3e748b3f27a17c27afeee578dc4eedb8dd5 (patch)
treec7a6d5ea8459801bcc120b30958397824b8453f3 /linux-user
parenta395717cbd26e7593d3c3fe81faca121ec6d13e8 (diff)
parent29f9cef39eb1ae55e82c6763eb22d7a1bdff7276 (diff)
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-3.0-20180703' into staging
ppc patch queue 2018-07-03 Here's a last minue pull request before today's soft freeze. Ideally I would have sent this earlier, but I was waiting for a couple of extra fixes I knew were close. And the freeze crept up on me, like always. Most of the changes here are bugfixes in any case. There are some cleanups as well, which have been in my staging tree for a little while. There are a couple of truly new features (some extensions to the sam460ex platform), but these are low risk, since they only affect a new and not really stabilized machine type anyway. Higlights are: * Mac platform improvements from Mark Cave-Ayland * Sam460ex improvements from BALATON Zoltan et al. * XICS interrupt handler cleanups from Cédric Le Goater * TCG improvements for atomic loads and stores from Richard Henderson * Assorted other bugfixes # gpg: Signature made Tue 03 Jul 2018 06:55:22 BST # gpg: using RSA key 6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-3.0-20180703: (35 commits) ppc: Include vga cirrus card into the compiling process target/ppc: Relax reserved bitmask of indexed store instructions target/ppc: set is_jmp on ppc_tr_breakpoint_check spapr: compute default value of "hpt-max-page-size" later target/ppc/kvm: don't pass cpu to kvm_get_smmu_info() target/ppc/kvm: get rid of kvm_get_fallback_smmu_info() ppc440_uc: Basic emulation of PPC440 DMA controller sam460ex: Add RTC device hw/timer: Add basic M41T80 emulation ppc4xx_i2c: Rewrite to model hardware more closely hw/ppc: Give sam46ex its own config option fpu_helper.c: fix setting FPSCR[FI] bit target/ppc: Implement the rest of gen_st_atomic target/ppc: Implement the rest of gen_ld_atomic target/ppc: Use atomic min/max helpers target/ppc: Use MO_ALIGN for EXIWX and ECOWX target/ppc: Split out gen_st_atomic target/ppc: Split out gen_ld_atomic target/ppc: Split out gen_load_locked target/ppc: Tidy gen_conditional_store ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # hw/ppc/spapr.c
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/ppc/cpu_loop.c121
1 files changed, 22 insertions, 99 deletions
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index 2fb516cb00..133a87f349 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -65,99 +65,23 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
return -1;
}
-static int do_store_exclusive(CPUPPCState *env)
-{
- target_ulong addr;
- target_ulong page_addr;
- target_ulong val, val2 __attribute__((unused)) = 0;
- int flags;
- int segv = 0;
-
- addr = env->reserve_ea;
- page_addr = addr & TARGET_PAGE_MASK;
- start_exclusive();
- mmap_lock();
- flags = page_get_flags(page_addr);
- if ((flags & PAGE_READ) == 0) {
- segv = 1;
- } else {
- int reg = env->reserve_info & 0x1f;
- int size = env->reserve_info >> 5;
- int stored = 0;
-
- if (addr == env->reserve_addr) {
- switch (size) {
- case 1: segv = get_user_u8(val, addr); break;
- case 2: segv = get_user_u16(val, addr); break;
- case 4: segv = get_user_u32(val, addr); break;
-#if defined(TARGET_PPC64)
- case 8: segv = get_user_u64(val, addr); break;
- case 16: {
- segv = get_user_u64(val, addr);
- if (!segv) {
- segv = get_user_u64(val2, addr + 8);
- }
- break;
- }
-#endif
- default: abort();
- }
- if (!segv && val == env->reserve_val) {
- val = env->gpr[reg];
- switch (size) {
- case 1: segv = put_user_u8(val, addr); break;
- case 2: segv = put_user_u16(val, addr); break;
- case 4: segv = put_user_u32(val, addr); break;
-#if defined(TARGET_PPC64)
- case 8: segv = put_user_u64(val, addr); break;
- case 16: {
- if (val2 == env->reserve_val2) {
- if (msr_le) {
- val2 = val;
- val = env->gpr[reg+1];
- } else {
- val2 = env->gpr[reg+1];
- }
- segv = put_user_u64(val, addr);
- if (!segv) {
- segv = put_user_u64(val2, addr + 8);
- }
- }
- break;
- }
-#endif
- default: abort();
- }
- if (!segv) {
- stored = 1;
- }
- }
- }
- env->crf[0] = (stored << 1) | xer_so;
- env->reserve_addr = (target_ulong)-1;
- }
- if (!segv) {
- env->nip += 4;
- }
- mmap_unlock();
- end_exclusive();
- return segv;
-}
-
void cpu_loop(CPUPPCState *env)
{
CPUState *cs = CPU(ppc_env_get_cpu(env));
target_siginfo_t info;
- int trapnr;
+ int trapnr, sig;
target_ulong ret;
for(;;) {
+ bool arch_interrupt;
+
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
process_queued_cpu_work(cs);
- switch(trapnr) {
+ arch_interrupt = true;
+ switch (trapnr) {
case POWERPC_EXCP_NONE:
/* Just go on */
break;
@@ -524,26 +448,15 @@ void cpu_loop(CPUPPCState *env)
}
env->gpr[3] = ret;
break;
- case POWERPC_EXCP_STCX:
- if (do_store_exclusive(env)) {
- info.si_signo = TARGET_SIGSEGV;
+ case EXCP_DEBUG:
+ sig = gdb_handlesig(cs, TARGET_SIGTRAP);
+ if (sig) {
+ info.si_signo = sig;
info.si_errno = 0;
- info.si_code = TARGET_SEGV_MAPERR;
- info._sifields._sigfault._addr = env->nip;
+ info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- }
- break;
- case EXCP_DEBUG:
- {
- int sig;
-
- sig = gdb_handlesig(cs, TARGET_SIGTRAP);
- if (sig) {
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- }
+ } else {
+ arch_interrupt = false;
}
break;
case EXCP_INTERRUPT:
@@ -551,12 +464,22 @@ void cpu_loop(CPUPPCState *env)
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
+ arch_interrupt = false;
break;
default:
cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr);
break;
}
process_pending_signals(env);
+
+ /* Most of the traps imply a transition through kernel mode,
+ * which implies an REI instruction has been executed. Which
+ * means that RX and LOCK_ADDR should be cleared. But there
+ * are a few exceptions for traps internal to QEMU.
+ */
+ if (arch_interrupt) {
+ env->reserve_addr = -1;
+ }
}
}