All of lore.kernel.org
 help / color / mirror / Atom feed
From: Riku Voipio <riku.voipio@iki.fi>
To: "Alex Bennée" <alex.bennee@linaro.org>
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Riku Voipio <riku.voipio@iki.fi>,
	qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2 07/10] target-arm: remove last users of cpsr_write
Date: Tue, 15 Jul 2014 16:43:09 +0300	[thread overview]
Message-ID: <20140715134309.GH607@afflict.kos.to> (raw)
In-Reply-To: <1405007407-23549-8-git-send-email-alex.bennee@linaro.org>

On Thu, Jul 10, 2014 at 04:50:04PM +0100, Alex Bennée wrote:
> And use the new machinery to to save and restore program state. The old
> cpsr_write function did some special handling for mode switches which
> has been moved into the helper function.

Again for the linux-user part,

Acked-by: Riku Voipio <riku.voipio@linaro.org>

> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> 
> ---
> v2:
>   - rebase
>   - add mask helper function
>   - checkpatch fixes
> 
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 9101541..5f7cc31 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -4184,7 +4184,7 @@ int main(int argc, char **argv, char **envp)
>  #elif defined(TARGET_ARM)
>      {
>          int i;
> -        cpsr_write(env, regs->uregs[16], 0xffffffff);
> +        restore_state_from_spsr(env, regs->uregs[16]);
>          for(i = 0; i < 16; i++) {
>              env->regs[i] = regs->uregs[i];
>          }
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 9c6727b..b6f9ef4 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -1599,38 +1599,39 @@ get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
>  
>  static void
>  setup_return(CPUARMState *env, struct target_sigaction *ka,
> -	     abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
> +             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
>  {
> -	abi_ulong handler = ka->_sa_handler;
> -	abi_ulong retcode;
> -	int thumb = handler & 1;
> -	uint32_t cpsr = save_state_to_spsr(env);
> +        abi_ulong handler = ka->_sa_handler;
> +        abi_ulong retcode;
> +        int thumb = handler & 1;
> +        uint32_t cpsr = save_state_to_spsr(env);
>  
> -	cpsr &= ~CPSR_IT;
> -	if (thumb) {
> -		cpsr |= CPSR_T;
> -	} else {
> -		cpsr &= ~CPSR_T;
> -	}
> +        cpsr &= ~CPSR_IT;
> +        if (thumb) {
> +                cpsr |= CPSR_T;
> +        } else {
> +                cpsr &= ~CPSR_T;
> +        }
>  
> -	if (ka->sa_flags & TARGET_SA_RESTORER) {
> -		retcode = ka->sa_restorer;
> -	} else {
> -		unsigned int idx = thumb;
> +        if (ka->sa_flags & TARGET_SA_RESTORER) {
> +                retcode = ka->sa_restorer;
> +        } else {
> +                unsigned int idx = thumb;
>  
> -		if (ka->sa_flags & TARGET_SA_SIGINFO)
> -			idx += 2;
> +                if (ka->sa_flags & TARGET_SA_SIGINFO) {
> +                        idx += 2;
> +                }
>  
> -        __put_user(retcodes[idx], rc);
> +                __put_user(retcodes[idx], rc);
>  
> -		retcode = rc_addr + thumb;
> -	}
> +                retcode = rc_addr + thumb;
> +        }
>  
> -	env->regs[0] = usig;
> -	env->regs[13] = frame_addr;
> -	env->regs[14] = retcode;
> -	env->regs[15] = handler & (thumb ? ~1 : ~3);
> -	cpsr_write(env, cpsr, 0xffffffff);
> +        env->regs[0] = usig;
> +        env->regs[13] = frame_addr;
> +        env->regs[14] = retcode;
> +        env->regs[15] = handler & (thumb ? ~1 : ~3);
> +        restore_state_from_spsr(env, cpsr);
>  }
>  
>  static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
> @@ -1858,12 +1859,14 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
>      __get_user(env->regs[15], &sc->arm_pc);
>  #ifdef TARGET_CONFIG_CPU_32
>      __get_user(cpsr, &sc->arm_cpsr);
> -        cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
> +    restore_state_from_masked_spsr(env,
> +                                   (CPSR_USER | CPSR_EXEC),
> +                                   cpsr);
>  #endif
>  
> -	err |= !valid_user_regs(env);
> +    err |= !valid_user_regs(env);
>  
> -	return err;
> +    return err;
>  }
>  
>  static long do_sigreturn_v1(CPUARMState *env)
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 3f23167..b56f1a8 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -795,6 +795,15 @@ static inline void restore_state_from_spsr(CPUARMState *env,
>      }
>  }
>  
> +/* Restore a few masked bits of the program state */
> +static inline void restore_state_from_masked_spsr(CPUARMState *env,
> +                                                  uint32_t mask,
> +                                                  uint32_t saved_state)
> +{
> +    uint32_t spsr = (save_state_to_spsr(env) & ~mask);
> +    spsr |= (saved_state & mask);
> +    return restore_state_from_spsr(env, spsr);
> +}
>  
>  void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>  
> diff --git a/target-arm/gdbstub.c b/target-arm/gdbstub.c
> index ec25f30..5e60589 100644
> --- a/target-arm/gdbstub.c
> +++ b/target-arm/gdbstub.c
> @@ -93,8 +93,12 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
>          }
>          return 4;
>      case 25:
> -        /* CPSR */
> -        cpsr_write(env, tmp, 0xffffffff);
> +        /* CPSR
> +         * FIXME?: as restore_state_from_spsr() doesn't do aarch32
> +         * special mode fixups this may break. However GDB doesn't
> +         * seem to be able to handle tracing over a mode switch anyway
> +         */
> +        restore_state_from_spsr(env, tmp);
>          return 4;
>      }
>      /* Unknown register.  */
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 030bcdd..6d755c0 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -2970,68 +2970,6 @@ void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque)
>      /* Helper coprocessor reset function for do-nothing-on-reset registers */
>  }
>  
> -static int bad_mode_switch(CPUARMState *env, int mode)
> -{
> -    /* Return true if it is not valid for us to switch to
> -     * this CPU mode (ie all the UNPREDICTABLE cases in
> -     * the ARM ARM CPSRWriteByInstr pseudocode).
> -     */
> -    switch (mode) {
> -    case ARM_CPU_MODE_USR:
> -    case ARM_CPU_MODE_SYS:
> -    case ARM_CPU_MODE_SVC:
> -    case ARM_CPU_MODE_ABT:
> -    case ARM_CPU_MODE_UND:
> -    case ARM_CPU_MODE_IRQ:
> -    case ARM_CPU_MODE_FIQ:
> -        return 0;
> -    default:
> -        return 1;
> -    }
> -}
> -
> -void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
> -{
> -    if (mask & CPSR_NZCV) {
> -        env->ZF = (~val) & CPSR_Z;
> -        env->NF = val;
> -        env->CF = (val >> 29) & 1;
> -        env->VF = (val << 3) & 0x80000000;
> -    }
> -    if (mask & CPSR_Q)
> -        env->QF = ((val & CPSR_Q) != 0);
> -    if (mask & CPSR_T)
> -        env->thumb = ((val & CPSR_T) != 0);
> -    if (mask & CPSR_IT_0_1) {
> -        env->condexec_bits &= ~3;
> -        env->condexec_bits |= (val >> 25) & 3;
> -    }
> -    if (mask & CPSR_IT_2_7) {
> -        env->condexec_bits &= 3;
> -        env->condexec_bits |= (val >> 8) & 0xfc;
> -    }
> -    if (mask & CPSR_GE) {
> -        env->GE = (val >> 16) & 0xf;
> -    }
> -
> -    env->daif &= ~(CPSR_AIF & mask);
> -    env->daif |= val & CPSR_AIF & mask;
> -
> -    if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
> -        if (bad_mode_switch(env, val & CPSR_M)) {
> -            /* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
> -             * We choose to ignore the attempt and leave the CPSR M field
> -             * untouched.
> -             */
> -            mask &= ~CPSR_M;
> -        } else {
> -            switch_mode(env, val & CPSR_M);
> -        }
> -    }
> -    mask &= ~CACHED_CPSR_BITS;
> -    env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
> -}
> -
>  /* Sign/zero extend */
>  uint32_t HELPER(sxtb16)(uint32_t x)
>  {
> diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
> index 789f52f..39117c7 100644
> --- a/target-arm/kvm32.c
> +++ b/target-arm/kvm32.c
> @@ -464,7 +464,7 @@ int kvm_arch_get_registers(CPUState *cs)
>      if (ret) {
>          return ret;
>      }
> -    cpsr_write(env, cpsr, 0xffffffff);
> +    restore_state_from_spsr(env, cpsr);
>  
>      /* Make sure the current mode regs are properly set */
>      mode = env->uncached_cpsr & CPSR_M;
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index 052a4bd..c17bdba 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -261,9 +261,47 @@ uint32_t HELPER(cpsr_read)(CPUARMState *env)
>      return save_state_to_spsr(env) & ~CPSR_EXEC;
>  }
>  
> +static int bad_mode_switch(CPUARMState *env, int mode)
> +{
> +    /* Return true if it is not valid for us to switch to
> +     * this CPU mode (ie all the UNPREDICTABLE cases in
> +     * the ARM ARM CPSRWriteByInstr pseudocode).
> +     */
> +    switch (mode) {
> +    case ARM_CPU_MODE_USR:
> +    case ARM_CPU_MODE_SYS:
> +    case ARM_CPU_MODE_SVC:
> +    case ARM_CPU_MODE_ABT:
> +    case ARM_CPU_MODE_UND:
> +    case ARM_CPU_MODE_IRQ:
> +    case ARM_CPU_MODE_FIQ:
> +        return 0;
> +    default:
> +        return 1;
> +    }
> +}
> +
>  void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
>  {
> -    cpsr_write(env, val, mask);
> +    uint32_t current_cpsr = save_state_to_spsr(env);
> +    uint32_t new_cpsr;
> +
> +    /* we may be triggering a mode change */
> +    if ((current_cpsr ^ val) & mask & CPSR_M) {
> +        if (bad_mode_switch(env, val & CPSR_M)) {
> +            /* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
> +             * We choose to ignore the attempt and leave the CPSR M field
> +             * untouched.
> +             */
> +            mask &= ~CPSR_M;
> +        } else {
> +            switch_mode(env, val & CPSR_M);
> +        }
> +    }
> +
> +    new_cpsr = current_cpsr & ~mask;
> +    new_cpsr |= (val & mask);
> +    restore_state_from_spsr(env, new_cpsr);
>  }
>  
>  /* Access to user mode registers from privileged modes.  */
> -- 
> 2.0.1
> 

  reply	other threads:[~2014-07-15 13:43 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-10 15:49 [Qemu-devel] [PATCH v2 00/10] aarch64 migration for TCG and KVM Alex Bennée
2014-07-10 15:49 ` [Qemu-devel] [PATCH v2 01/10] target-arm/cpu.h: document various program state functions Alex Bennée
2014-08-04 12:28   ` Peter Maydell
2014-07-10 15:49 ` [Qemu-devel] [PATCH v2 02/10] target-arm/cpu.h: common pstate save/restore Alex Bennée
2014-08-04 12:47   ` Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 03/10] target-arm: Support save/load for 64 bit CPUs Alex Bennée
2014-08-04 12:50   ` Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 04/10] target-arm: replace cpsr/xpsr/pstate_read calls Alex Bennée
2014-07-15 13:40   ` Riku Voipio
2014-08-04 12:59   ` Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 05/10] arm/nwfps: replace cpsr_write with set_condition_codes Alex Bennée
2014-07-15 13:41   ` Riku Voipio
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 06/10] linux-user/main.c: __kernel_cmpxchg set env->CF directly Alex Bennée
2014-07-15 13:39   ` Riku Voipio
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 07/10] target-arm: remove last users of cpsr_write Alex Bennée
2014-07-15 13:43   ` Riku Voipio [this message]
2014-08-04 13:01   ` Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 08/10] target-arm: remove final users of pstate_write Alex Bennée
2014-07-15 13:44   ` Riku Voipio
2014-07-10 15:50 ` [PATCH v2 09/10] target-arm/kvm.c: better error reporting Alex Bennée
2014-07-10 15:50   ` [Qemu-devel] " Alex Bennée
2014-08-04 13:03   ` Peter Maydell
2014-08-04 13:03     ` [Qemu-devel] " Peter Maydell
2014-07-10 15:50 ` [PATCH v2 10/10] target-arm/kvm: make reg sync code common between kvm32/64 Alex Bennée
2014-07-10 15:50   ` [Qemu-devel] " Alex Bennée
2014-08-04 13:04   ` Peter Maydell
2014-08-04 13:04     ` [Qemu-devel] " Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140715134309.GH607@afflict.kos.to \
    --to=riku.voipio@iki.fi \
    --cc=alex.bennee@linaro.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.