From patchwork Mon Jun 2 16:21:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Alex_Benn=C3=A9e?= X-Patchwork-Id: 31303 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f72.google.com (mail-pb0-f72.google.com [209.85.160.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 57A73203C2 for ; Mon, 2 Jun 2014 17:36:54 +0000 (UTC) Received: by mail-pb0-f72.google.com with SMTP id ma3sf20515044pbc.7 for ; Mon, 02 Jun 2014 10:36:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=IRk1tYa+G7QM7lv6czmNwHZsacpcTPHimLVpGjgMGT0=; b=StJ30hNFjcyq/IVf6hxrp3xMs4J0gRXbYG4dkO2QDbqDM3mtftxgPz1z1RvAY2LLsd N03zrTX7K2qWv9+9zB7l1NeV/1JXHVVEjLYd7bGz2gdoOPkeRXEpYCPWfOGY5e5t0X35 /RkVTtbXnoFt0cDlgGU6JWULL46GFCHZNyo3HXGZl6ZOKMpfEjLSXM1M6pnM2sgjyQSE 5c+ykDylP4V/tEJmBcmEOIiTF4vzZHA0UBQpyyl/Oe0R0KDRoNI0dwesQM08+LurmF4o rFjD/dPVuw9hjmnQU5N5qHLiGKXXSMLI7wZF3aGHnmwUUVtqlvF9/jdBaXwTdJI42BW4 Nzpw== X-Gm-Message-State: ALoCoQkak59Ut0dGQrF9bZVmpTfp3s9ahLUBmy12SCMgXxYSZNhmns614+LoYehVvchj0vSD0N0I X-Received: by 10.66.232.38 with SMTP id tl6mr13727237pac.33.1401730613570; Mon, 02 Jun 2014 10:36:53 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.98.225 with SMTP id o88ls2117782qge.88.gmail; Mon, 02 Jun 2014 10:36:53 -0700 (PDT) X-Received: by 10.221.59.194 with SMTP id wp2mr1920895vcb.59.1401730613413; Mon, 02 Jun 2014 10:36:53 -0700 (PDT) Received: from mail-ve0-f182.google.com (mail-ve0-f182.google.com [209.85.128.182]) by mx.google.com with ESMTPS id ot8si8303818vcb.95.2014.06.02.10.36.53 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 02 Jun 2014 10:36:53 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.128.182 as permitted sender) client-ip=209.85.128.182; Received: by mail-ve0-f182.google.com with SMTP id sa20so5736032veb.27 for ; Mon, 02 Jun 2014 10:36:53 -0700 (PDT) X-Received: by 10.52.76.134 with SMTP id k6mr1786455vdw.62.1401730613227; Mon, 02 Jun 2014 10:36:53 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.221.72 with SMTP id ib8csp114960vcb; Mon, 2 Jun 2014 10:36:52 -0700 (PDT) X-Received: by 10.224.147.80 with SMTP id k16mr50274484qav.40.1401730612645; Mon, 02 Jun 2014 10:36:52 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id jh10si18282987qcb.30.2014.06.02.10.36.52 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 02 Jun 2014 10:36:52 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:47725 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WrV1Y-0006pU-66 for patch@linaro.org; Mon, 02 Jun 2014 12:23:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39501) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WrV0Y-0005E0-1Y for qemu-devel@nongnu.org; Mon, 02 Jun 2014 12:22:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WrV0S-0007Iw-3C for qemu-devel@nongnu.org; Mon, 02 Jun 2014 12:22:45 -0400 Received: from static.88-198-71-155.clients.your-server.de ([88.198.71.155]:41886 helo=socrates.bennee.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WrV0R-0007Im-PL for qemu-devel@nongnu.org; Mon, 02 Jun 2014 12:22:40 -0400 Received: from localhost ([127.0.0.1] helo=zen.linaro.local) by socrates.bennee.com with esmtp (Exim 4.80) (envelope-from ) id 1WrV1a-0007B7-5n; Mon, 02 Jun 2014 18:23:50 +0200 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= To: qemu-devel@nongnu.org Date: Mon, 2 Jun 2014 17:21:58 +0100 Message-Id: <1401726122-11132-5-git-send-email-alex.bennee@linaro.org> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1401726122-11132-1-git-send-email-alex.bennee@linaro.org> References: <1401726122-11132-1-git-send-email-alex.bennee@linaro.org> X-SA-Exim-Connect-IP: 127.0.0.1 X-SA-Exim-Mail-From: alex.bennee@linaro.org X-SA-Exim-Scanned: No (on socrates.bennee.com); SAEximRunCond expanded to false X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 88.198.71.155 Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, Riku Voipio , =?UTF-8?q?Alex=20Benn=C3=A9e?= , greg.bellows@linaro.org Subject: [Qemu-devel] [RCF PATCH 4/8] target-arm: replace cpsr_read/pstate_read calls X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: alex.bennee@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.128.182 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Use the unified save_state_to_spsr. I've also updated the interrupt helpers to restore via the restore_state_from_spsr() functions. In the aarch32 case this also needs to call switch_mode() to do the appropriate fiddling. diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 995f999..a93a969 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -321,7 +321,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *en (*regs)[14] = tswapreg(env->regs[14]); (*regs)[15] = tswapreg(env->regs[15]); - (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env)); + (*regs)[16] = tswapreg(save_state_to_spsr((CPUARMState *)env)); (*regs)[17] = tswapreg(env->regs[0]); /* XXX */ } @@ -506,7 +506,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, (*regs)[i] = tswapreg(env->xregs[i]); } (*regs)[32] = tswapreg(env->pc); - (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env)); + (*regs)[33] = tswapreg(save_state_to_spsr((CPUARMState *)env)); } #define USE_ELF_CORE_DUMP diff --git a/linux-user/main.c b/linux-user/main.c index 882186e..22d0197 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -547,7 +547,7 @@ do_kernel_trap(CPUARMState *env) operations. However things like ldrex/strex are much harder so there's not much point trying. */ start_exclusive(); - cpsr = cpsr_read(env); + cpsr = save_state_to_spsr(env); addr = env->regs[2]; /* FIXME: This should SEGV if the access fails. */ if (get_user_u32(val, addr)) diff --git a/linux-user/signal.c b/linux-user/signal.c index 5b8a01f..ee2a79f 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -1240,7 +1240,7 @@ static int target_setup_sigframe(struct target_rt_sigframe *sf, } __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp); __put_user(env->pc, &sf->uc.tuc_mcontext.pc); - __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate); + __put_user(save_state_to_spsr(env), &sf->uc.tuc_mcontext.pstate); __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address); @@ -1592,7 +1592,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ __put_user(env->regs[14], &sc->arm_lr); __put_user(env->regs[15], &sc->arm_pc); #ifdef TARGET_CONFIG_CPU_32 - __put_user(cpsr_read(env), &sc->arm_cpsr); + __put_user(save_state_to_spsr(env), &sc->arm_cpsr); #endif __put_user(/* current->thread.trap_no */ 0, &sc->trap_no); @@ -1624,7 +1624,7 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, abi_ulong handler = ka->_sa_handler; abi_ulong retcode; int thumb = handler & 1; - uint32_t cpsr = cpsr_read(env); + uint32_t cpsr = save_state_to_spsr(env); cpsr &= ~CPSR_IT; if (thumb) { diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 9e41f82..cfdc1cb 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -460,30 +460,8 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, #define PSTATE_MODE_EL1t 4 #define PSTATE_MODE_EL0t 0 -/* ARMv8 ARM D1.7 Process state, PSTATE - * - * 31 28 27 24 23 22 21 20 22 21 20 19 16 15 8 7 5 4 0 - * +------+------+-------+-----+--------+---+------+------+-----+------+ - * | NZCV | DAIF | SS IL | EL | nRW SP | Q | GE | IT | JTE | Mode | - * +------+------+-------+-----+--------+---+------+------+-----+------+ - * - * The PSTATE is an abstraction of a number of Return the current - * PSTATE value. This is only valid for A64 hardware although can be - * read when in AArch32 mode. - */ -static inline uint32_t pstate_read(CPUARMState *env) -{ - int ZF; - - g_assert(is_a64(env)); - - ZF = (env->ZF == 0); - return (env->NF & 0x80000000) | (ZF << 30) - | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) - | env->pstate | env->daif; -} - -/* Update the current PSTATE value. This doesn't include nRW which is */ +/* Update the current PSTATE value. This doesn't include nRW which + * indicates if we are in 64 or 32 bit mode */ static inline void pstate_write(CPUARMState *env, uint32_t val) { g_assert(is_a64(env)); @@ -500,9 +478,8 @@ static inline void pstate_write(CPUARMState *env, uint32_t val) * * Unlike the above PSTATE implementation these functions will attempt * to switch processor mode when the M[4:0] bits are set. - */ -uint32_t cpsr_read(CPUARMState *env); -/* Set the CPSR. Note that some bits of mask must be all-set or all-clear. */ + * + * Note that some bits of mask must be all-set or all-clear. */ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask); /* ARMv7-M ARM B1.4.2, special purpose program status register xPSR */ @@ -760,6 +737,14 @@ static inline uint32_t save_state_to_spsr(CPUARMState *env) return final_spsr; } +/* Restore the program state and mode. + * + * There is nothing that stops the execution state from being changed + * here and any restrictions should be enforced by the calling + * function. Also aarch32 execution state changes (new EL) need extra + * special handling which should be done by the calling function + * before the switch. + */ static inline void restore_state_from_spsr(CPUARMState *env, uint32_t saved_state) { /* Process the integer flags directly */ diff --git a/target-arm/gdbstub.c b/target-arm/gdbstub.c index 1c34396..ec25f30 100644 --- a/target-arm/gdbstub.c +++ b/target-arm/gdbstub.c @@ -53,7 +53,7 @@ int arm_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) return gdb_get_reg32(mem_buf, 0); case 25: /* CPSR */ - return gdb_get_reg32(mem_buf, cpsr_read(env)); + return gdb_get_reg32(mem_buf, save_state_to_spsr(env)); } /* Unknown register. */ return 0; diff --git a/target-arm/gdbstub64.c b/target-arm/gdbstub64.c index 8f3b8d1..76d1b91 100644 --- a/target-arm/gdbstub64.c +++ b/target-arm/gdbstub64.c @@ -35,7 +35,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) case 32: return gdb_get_reg64(mem_buf, env->pc); case 33: - return gdb_get_reg32(mem_buf, pstate_read(env)); + return gdb_get_reg32(mem_buf, save_state_to_spsr(env)); } /* Unknown register. */ return 0; @@ -62,7 +62,7 @@ int aarch64_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) env->pc = tmp; return 8; case 33: - /* CPSR */ + /* SPSR */ pstate_write(env, tmp); return 4; } diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c index 48ca351..1ca3164 100644 --- a/target-arm/helper-a64.c +++ b/target-arm/helper-a64.c @@ -445,6 +445,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs) CPUARMState *env = &cpu->env; target_ulong addr = env->cp15.vbar_el[1]; int i; + uint32_t spsr = save_state_to_spsr(env); if (arm_current_pl(env) == 0) { if (env->aarch64) { @@ -452,7 +453,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs) } else { addr += 0x600; } - } else if (pstate_read(env) & PSTATE_SP) { + } else if (spsr & PSTATE_SP) { addr += 0x200; } @@ -488,12 +489,12 @@ void aarch64_cpu_do_interrupt(CPUState *cs) } if (is_a64(env)) { - env->banked_spsr[aarch64_banked_spsr_index(1)] = pstate_read(env); + env->banked_spsr[aarch64_banked_spsr_index(1)] = spsr; env->sp_el[arm_current_pl(env)] = env->xregs[31]; env->xregs[31] = env->sp_el[1]; env->elr_el[1] = env->pc; } else { - env->banked_spsr[0] = cpsr_read(env); + env->banked_spsr[0] = spsr; if (!env->thumb) { env->cp15.esr_el[1] |= 1 << 25; } @@ -506,6 +507,7 @@ void aarch64_cpu_do_interrupt(CPUState *cs) env->condexec_bits = 0; } + // TODO: restore_state_from_spsr() env->aarch64 = 1; pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h); diff --git a/target-arm/helper.c b/target-arm/helper.c index ec031f5..e23cec4 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2979,17 +2979,6 @@ static int bad_mode_switch(CPUARMState *env, int mode) } } -uint32_t cpsr_read(CPUARMState *env) -{ - int ZF; - ZF = (env->ZF == 0); - return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) | - (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) - | (env->thumb << 5) | ((env->condexec_bits & 3) << 25) - | ((env->condexec_bits & 0xfc) << 8) - | (env->GE << 16) | (env->daif & CPSR_AIF); -} - void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) { if (mask & CPSR_NZCV) { @@ -3468,7 +3457,8 @@ void arm_cpu_do_interrupt(CPUState *cs) addr += env->cp15.vbar_el[1]; } switch_mode (env, new_mode); - env->spsr = cpsr_read(env); + env->spsr = save_state_to_spsr(env); + /* TODO: restore_state_from_spsr */ /* Clear IT bits. */ env->condexec_bits = 0; /* Switch to the new mode, and to the correct instruction set. */ diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c index b79750c..de3063f 100644 --- a/target-arm/kvm32.c +++ b/target-arm/kvm32.c @@ -385,7 +385,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) } /* Special cases which aren't a single CPUARMState field */ - cpsr = cpsr_read(env); + cpsr = save_state_to_spsr(env); r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr); r.addr = (uintptr_t)(&cpsr); diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c index 70f311b..83df952 100644 --- a/target-arm/kvm64.c +++ b/target-arm/kvm64.c @@ -145,7 +145,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) } /* Note that KVM thinks pstate is 64 bit but we use a uint32_t */ - val = pstate_read(env); + val = save_state_to_spsr(env); reg.id = AARCH64_CORE_REG(regs.pstate); reg.addr = (uintptr_t) &val; ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index b28f694..b58bcdf 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -273,7 +273,7 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, uint32_t HELPER(cpsr_read)(CPUARMState *env) { - return cpsr_read(env) & ~CPSR_EXEC; + return save_state_to_spsr(env) & ~CPSR_EXEC; } void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) @@ -401,10 +401,9 @@ void HELPER(exception_return)(CPUARMState *env) if (spsr & PSTATE_nRW) { /* TODO: We currently assume EL1/2/3 are running in AArch64. */ - env->aarch64 = 0; new_el = 0; - env->uncached_cpsr = 0x10; - cpsr_write(env, spsr, ~0); + switch_mode(env, spsr & CPSR_M); + for (i = 0; i < 15; i++) { env->regs[i] = env->xregs[i]; } @@ -427,11 +426,11 @@ void HELPER(exception_return)(CPUARMState *env) /* Return to EL0 with M[0] bit set */ goto illegal_return; } - env->aarch64 = 1; - pstate_write(env, spsr); env->xregs[31] = env->sp_el[new_el]; env->pc = env->elr_el[cur_el]; } + /* This will set env->aarch64 as appropriate */ + restore_state_from_spsr(env, spsr); return; @@ -446,8 +445,8 @@ illegal_return: env->pstate |= PSTATE_IL; env->pc = env->elr_el[cur_el]; spsr &= PSTATE_NZCV | PSTATE_DAIF; - spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF); - pstate_write(env, spsr); + spsr |= save_state_to_spsr(env) & ~(PSTATE_NZCV | PSTATE_DAIF); + restore_state_from_spsr(env, spsr); } /* ??? Flag setting arithmetic is awkward because we need to do comparisons. diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 9f964df..28216a3 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -123,7 +123,7 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, { ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; - uint32_t psr = pstate_read(env); + uint32_t psr = save_state_to_spsr(env); int i; cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", diff --git a/target-arm/translate.c b/target-arm/translate.c index 7f6fcd6..2429744 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11075,7 +11075,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, else cpu_fprintf(f, " "); } - psr = cpsr_read(env); + psr = save_state_to_spsr(env); cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n", psr, psr & (1 << 31) ? 'N' : '-',