qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [Qemu-arm] [PATCH 2/7] target/arm: Split "get pending e


From: Philippe Mathieu-Daudé
Subject: Re: [Qemu-devel] [Qemu-arm] [PATCH 2/7] target/arm: Split "get pending exception info" from "acknowledge it"
Date: Mon, 5 Feb 2018 20:44:13 -0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2

On 01/30/2018 12:02 PM, Peter Maydell wrote:
> Currently armv7m_nvic_acknowledge_irq() does three things:
>  * make the current highest priority pending interrupt active
>  * return a bool indicating whether that interrupt is targeting
>    Secure or NonSecure state
>  * implicitly tell the caller which is the highest priority
>    pending interrupt by setting env->v7m.exception
> 
> We need to split these jobs, because v7m_exception_taken()
> needs to know whether the pending interrupt targets Secure so
> it can choose to stack callee-saves registers or not, but it
> must not make the interrupt active until after it has done
> that stacking, in case the stacking causes a derived exception.
> Similarly, it needs to know the number of the pending interrupt
> so it can read the correct vector table entry before the
> interrupt is made active, because vector table reads might
> also cause a derived exception.
> 
> Create a new armv7m_nvic_get_pending_irq_info() function which simply
> returns information about the highest priority pending interrupt, and
> use it to rearrange the v7m_exception_taken() code so we don't
> acknowledge the exception until we've done all the things which could
> possibly cause a derived exception.
> 
> Signed-off-by: Peter Maydell <address@hidden>
> ---
>  target/arm/cpu.h      | 19 ++++++++++++++++---
>  hw/intc/armv7m_nvic.c | 30 +++++++++++++++++++++++-------
>  target/arm/helper.c   | 16 ++++++++++++----
>  hw/intc/trace-events  |  3 ++-
>  4 files changed, 53 insertions(+), 15 deletions(-)
> 
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 9ed03e6..f21f68e 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1519,16 +1519,29 @@ void armv7m_nvic_set_pending(void *opaque, int irq, 
> bool secure);
>   */
>  void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
>  /**
> + * armv7m_nvic_get_pending_irq_info: return highest priority pending
> + *    exception, and whether it targets Secure state
> + * @opaque: the NVIC
> + * @pirq: set to pending exception number
> + * @ptargets_secure: set to whether pending exception targets Secure
> + *
> + * This function writes the number of the highest priority pending
> + * exception (the one which would be made active by
> + * armv7m_nvic_acknowledge_irq()) to @pirq, and sets @ptargets_secure
> + * to true if the current highest priority pending exception should
> + * be taken to Secure state, false for NS.
> + */
> +void armv7m_nvic_get_pending_irq_info(void *opaque, int *pirq,
> +                                      bool *ptargets_secure);
> +/**
>   * armv7m_nvic_acknowledge_irq: make highest priority pending exception 
> active
>   * @opaque: the NVIC
>   *
>   * Move the current highest priority pending exception from the pending
>   * state to the active state, and update v7m.exception to indicate that
>   * it is the exception currently being handled.
> - *
> - * Returns: true if exception should be taken to Secure state, false for NS
>   */
> -bool armv7m_nvic_acknowledge_irq(void *opaque);
> +void armv7m_nvic_acknowledge_irq(void *opaque);
>  /**
>   * armv7m_nvic_complete_irq: complete specified interrupt or exception
>   * @opaque: the NVIC
> diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
> index b4a6e7c..360889d 100644
> --- a/hw/intc/armv7m_nvic.c
> +++ b/hw/intc/armv7m_nvic.c
> @@ -650,24 +650,20 @@ void armv7m_nvic_set_pending_derived(void *opaque, int 
> irq, bool secure)
>  }
>  
>  /* Make pending IRQ active.  */
> -bool armv7m_nvic_acknowledge_irq(void *opaque)
> +void armv7m_nvic_acknowledge_irq(void *opaque)
>  {
>      NVICState *s = (NVICState *)opaque;
>      CPUARMState *env = &s->cpu->env;
>      const int pending = s->vectpending;
>      const int running = nvic_exec_prio(s);
>      VecInfo *vec;
> -    bool targets_secure;
>  
>      assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
>  
>      if (s->vectpending_is_s_banked) {
>          vec = &s->sec_vectors[pending];
> -        targets_secure = true;
>      } else {
>          vec = &s->vectors[pending];
> -        targets_secure = !exc_is_banked(s->vectpending) &&
> -            exc_targets_secure(s, s->vectpending);
>      }
>  
>      assert(vec->enabled);
> @@ -675,7 +671,7 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
>  
>      assert(s->vectpending_prio < running);
>  
> -    trace_nvic_acknowledge_irq(pending, s->vectpending_prio, targets_secure);
> +    trace_nvic_acknowledge_irq(pending, s->vectpending_prio);
>  
>      vec->active = 1;
>      vec->pending = 0;
> @@ -683,8 +679,28 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
>      write_v7m_exception(env, s->vectpending);
>  
>      nvic_irq_update(s);
> +}
> +
> +void armv7m_nvic_get_pending_irq_info(void *opaque,
> +                                      int *pirq, bool *ptargets_secure)
> +{
> +    NVICState *s = (NVICState *)opaque;
> +    const int pending = s->vectpending;
> +    bool targets_secure;
> +
> +    assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
> +
> +    if (s->vectpending_is_s_banked) {
> +        targets_secure = true;
> +    } else {
> +        targets_secure = !exc_is_banked(pending) &&
> +            exc_targets_secure(s, pending);
> +    }
> +
> +    trace_nvic_get_pending_irq_info(pending, targets_secure);
>  
> -    return targets_secure;

maybe:

assert(ptargets_secure && pirq);

(function is externally callable)

Reviewed-by: Philippe Mathieu-Daudé <address@hidden>

> +    *ptargets_secure = targets_secure;
> +    *pirq = pending;
>  }
>  
>  int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index bfce096..6062f38 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -6395,12 +6395,12 @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, 
> bool secure, bool threadmode,
>      }
>  }
>  
> -static uint32_t arm_v7m_load_vector(ARMCPU *cpu, bool targets_secure)
> +static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool 
> targets_secure)
>  {
>      CPUState *cs = CPU(cpu);
>      CPUARMState *env = &cpu->env;
>      MemTxResult result;
> -    hwaddr vec = env->v7m.vecbase[targets_secure] + env->v7m.exception * 4;
> +    hwaddr vec = env->v7m.vecbase[targets_secure] + exc * 4;
>      uint32_t addr;
>  
>      addr = address_space_ldl(cs->as, vec,
> @@ -6462,8 +6462,9 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t 
> lr, bool dotailchain)
>      CPUARMState *env = &cpu->env;
>      uint32_t addr;
>      bool targets_secure;
> +    int exc;
>  
> -    targets_secure = armv7m_nvic_acknowledge_irq(env->nvic);
> +    armv7m_nvic_get_pending_irq_info(env->nvic, &exc, &targets_secure);
>  
>      if (arm_feature(env, ARM_FEATURE_V8)) {
>          if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
> @@ -6531,6 +6532,14 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t 
> lr, bool dotailchain)
>          }
>      }
>  
> +    addr = arm_v7m_load_vector(cpu, exc, targets_secure);
> +
> +    /* Now we've done everything that might cause a derived exception
> +     * we can go ahead and activate whichever exception we're going to
> +     * take (which might now be the derived exception).
> +     */
> +    armv7m_nvic_acknowledge_irq(env->nvic);
> +
>      /* Switch to target security state -- must do this before writing SPSEL 
> */
>      switch_v7m_security_state(env, targets_secure);
>      write_v7m_control_spsel(env, 0);
> @@ -6538,7 +6547,6 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t 
> lr, bool dotailchain)
>      /* Clear IT bits */
>      env->condexec_bits = 0;
>      env->regs[14] = lr;
> -    addr = arm_v7m_load_vector(cpu, targets_secure);
>      env->regs[15] = addr & 0xfffffffe;
>      env->thumb = addr & 1;
>  }
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index 09e87d1..4092d28 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -180,7 +180,8 @@ nvic_escalate_disabled(int irq) "NVIC escalating irq %d 
> to HardFault: disabled"
>  nvic_set_pending(int irq, bool secure, bool derived, int en, int prio) "NVIC 
> set pending irq %d secure-bank %d derived %d (enabled: %d priority %d)"
>  nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear 
> pending irq %d secure-bank %d (enabled: %d priority %d)"
>  nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than 
> vectpending: setting irq line to 1"
> -nvic_acknowledge_irq(int irq, int prio, bool targets_secure) "NVIC 
> acknowledge IRQ: %d now active (prio %d targets_secure %d)"
> +nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active 
> (prio %d)"
> +nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: 
> targets_secure: %d"
>  nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
>  nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
>  nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg 
> read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
> 

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]