diff mbox series

[v18,5/6] target-arm: kvm64: inject synchronous External Abort

Message ID 20190906083152.25716-6-zhengxiang9@huawei.com (mailing list archive)
State New, archived
Headers show
Series Add ARMv8 RAS virtualization support in QEMU | expand

Commit Message

Xiang Zheng Sept. 6, 2019, 8:31 a.m. UTC
From: Dongjiu Geng <gengdongjiu@huawei.com>

Introduce kvm_inject_arm_sea() function in which we will setup the type
of exception and the syndrome information in order to inject a virtual
synchronous external abort. When switching to guest, it will jump to the
synchronous external abort vector table entry.

The ESR_ELx.DFSC is set to synchronous external abort(0x10), and
ESR_ELx.FnV is set to not valid(0x1), which will tell guest that FAR is
not valid and hold an UNKNOWN value. These values will be set to KVM
register structures through KVM_SET_ONE_REG IOCTL.

Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
---
 target/arm/helper.c     |  2 +-
 target/arm/internals.h  |  5 +++--
 target/arm/kvm64.c      | 34 ++++++++++++++++++++++++++++++++++
 target/arm/tlb_helper.c |  2 +-
 4 files changed, 39 insertions(+), 4 deletions(-)

Comments

Peter Maydell Sept. 27, 2019, 1:33 p.m. UTC | #1
On Fri, 6 Sep 2019 at 09:33, Xiang Zheng <zhengxiang9@huawei.com> wrote:
>
> From: Dongjiu Geng <gengdongjiu@huawei.com>
>
> Introduce kvm_inject_arm_sea() function in which we will setup the type
> of exception and the syndrome information in order to inject a virtual
> synchronous external abort. When switching to guest, it will jump to the
> synchronous external abort vector table entry.
>
> The ESR_ELx.DFSC is set to synchronous external abort(0x10), and
> ESR_ELx.FnV is set to not valid(0x1), which will tell guest that FAR is
> not valid and hold an UNKNOWN value. These values will be set to KVM
> register structures through KVM_SET_ONE_REG IOCTL.
>
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>

> +/* Inject synchronous external abort */
> +static void kvm_inject_arm_sea(CPUState *c)

This will cause a compilation failure at this point in
the patch series, because the compiler will complain about
a static function which is defined but never used.
To avoid breaking bisection, we need to put the definition
of the function in the same patch where it's used.

> +{
> +    ARMCPU *cpu = ARM_CPU(c);
> +    CPUARMState *env = &cpu->env;
> +    CPUClass *cc = CPU_GET_CLASS(c);
> +    uint32_t esr;
> +    bool same_el;
> +
> +    /**
> +     * Set the exception type to synchronous data abort
> +     * and the target exception Level to EL1.
> +     */

This comment doesn't really tell us anything that's not obvious
from the two lines of code that it's commenting on:

> +    c->exception_index = EXCP_DATA_ABORT;
> +    env->exception.target_el = 1;
> +
> +    /*
> +     * Set the DFSC to synchronous external abort and set FnV to not valid,
> +     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
> +     */
> +
> +    /* This exception comes from lower or current exception level. */

This comment too is stating the obvious I think.

> +    same_el = arm_current_el(env) == env->exception.target_el;
> +    esr = syn_data_abort_no_iss(same_el, 1, 0, 0, 0, 0, 0x10);
> +
> +    env->exception.syndrome = esr;
> +
> +    /**

There's a stray second '*' in this comment-start.


> +     * The vcpu thread already hold BQL, so no need hold again when
> +     * calling do_interrupt

I think this requirement would be better placed as a
comment at the top of the function noting that callers
must hold the iothread lock.

> +     */
> +    cc->do_interrupt(c);
> +}
> +
>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>
> diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
> index 5feb312941..499672ebbc 100644
> --- a/target/arm/tlb_helper.c
> +++ b/target/arm/tlb_helper.c
> @@ -33,7 +33,7 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
>       * ISV field.
>       */
>      if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
> -        syn = syn_data_abort_no_iss(same_el,
> +        syn = syn_data_abort_no_iss(same_el, 0,
>                                      ea, 0, s1ptw, is_write, fsc);
>      } else {
>          /*
> --
> 2.19.1

thanks
-- PMM
Xiang Zheng Oct. 8, 2019, 8:05 a.m. UTC | #2
On 2019/9/27 21:33, Peter Maydell wrote:
> On Fri, 6 Sep 2019 at 09:33, Xiang Zheng <zhengxiang9@huawei.com> wrote:
>>
>> From: Dongjiu Geng <gengdongjiu@huawei.com>
>>
>> Introduce kvm_inject_arm_sea() function in which we will setup the type
>> of exception and the syndrome information in order to inject a virtual
>> synchronous external abort. When switching to guest, it will jump to the
>> synchronous external abort vector table entry.
>>
>> The ESR_ELx.DFSC is set to synchronous external abort(0x10), and
>> ESR_ELx.FnV is set to not valid(0x1), which will tell guest that FAR is
>> not valid and hold an UNKNOWN value. These values will be set to KVM
>> register structures through KVM_SET_ONE_REG IOCTL.
>>
>> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
>> Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
> 
>> +/* Inject synchronous external abort */
>> +static void kvm_inject_arm_sea(CPUState *c)
> 
> This will cause a compilation failure at this point in
> the patch series, because the compiler will complain about
> a static function which is defined but never used.
> To avoid breaking bisection, we need to put the definition
> of the function in the same patch where it's used.

Thanks, I will merge this patch with the next patch.

> 
>> +{
>> +    ARMCPU *cpu = ARM_CPU(c);
>> +    CPUARMState *env = &cpu->env;
>> +    CPUClass *cc = CPU_GET_CLASS(c);
>> +    uint32_t esr;
>> +    bool same_el;
>> +
>> +    /**
>> +     * Set the exception type to synchronous data abort
>> +     * and the target exception Level to EL1.
>> +     */
> 
> This comment doesn't really tell us anything that's not obvious
> from the two lines of code that it's commenting on:

Yes, I will remove this comment.

> 
>> +    c->exception_index = EXCP_DATA_ABORT;
>> +    env->exception.target_el = 1;
>> +
>> +    /*
>> +     * Set the DFSC to synchronous external abort and set FnV to not valid,
>> +     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
>> +     */
>> +
>> +    /* This exception comes from lower or current exception level. */
> 
> This comment too is stating the obvious I think.

I will remove it too.

> 
>> +    same_el = arm_current_el(env) == env->exception.target_el;
>> +    esr = syn_data_abort_no_iss(same_el, 1, 0, 0, 0, 0, 0x10);
>> +
>> +    env->exception.syndrome = esr;
>> +
>> +    /**
> 
> There's a stray second '*' in this comment-start.

OK, I will remove this stray '*'.

> 
> 
>> +     * The vcpu thread already hold BQL, so no need hold again when
>> +     * calling do_interrupt
> 
> I think this requirement would be better placed as a
> comment at the top of the function noting that callers
> must hold the iothread lock.

OK, I will add the comment at the top of the function.

> 
>> +     */
>> +    cc->do_interrupt(c);
>> +}
>> +
>>  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
>>                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
>>
>> diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
>> index 5feb312941..499672ebbc 100644
>> --- a/target/arm/tlb_helper.c
>> +++ b/target/arm/tlb_helper.c
>> @@ -33,7 +33,7 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
>>       * ISV field.
>>       */
>>      if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
>> -        syn = syn_data_abort_no_iss(same_el,
>> +        syn = syn_data_abort_no_iss(same_el, 0,
>>                                      ea, 0, s1ptw, is_write, fsc);
>>      } else {
>>          /*
>> --
>> 2.19.1
> 
> thanks
> -- PMM
> 
> .
>
diff mbox series

Patch

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 507026c915..a13baeb085 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3005,7 +3005,7 @@  static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
              * Report exception with ESR indicating a fault due to a
              * translation table walk for a cache maintenance instruction.
              */
-            syn = syn_data_abort_no_iss(current_el == target_el,
+            syn = syn_data_abort_no_iss(current_el == target_el, 0,
                                         fi.ea, 1, fi.s1ptw, 1, fsc);
             env->exception.vaddress = value;
             env->exception.fsr = fsr;
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 232d963875..98cde702ad 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -451,13 +451,14 @@  static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
         | ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc;
 }
 
-static inline uint32_t syn_data_abort_no_iss(int same_el,
+static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv,
                                              int ea, int cm, int s1ptw,
                                              int wnr, int fsc)
 {
     return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
            | ARM_EL_IL
-           | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
+           | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7)
+           | (wnr << 6) | fsc;
 }
 
 static inline uint32_t syn_data_abort_with_iss(int same_el,
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 28f6db57d5..bf6edaa3f6 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -710,6 +710,40 @@  int kvm_arm_cpreg_level(uint64_t regidx)
     return KVM_PUT_RUNTIME_STATE;
 }
 
+/* Inject synchronous external abort */
+static void kvm_inject_arm_sea(CPUState *c)
+{
+    ARMCPU *cpu = ARM_CPU(c);
+    CPUARMState *env = &cpu->env;
+    CPUClass *cc = CPU_GET_CLASS(c);
+    uint32_t esr;
+    bool same_el;
+
+    /**
+     * Set the exception type to synchronous data abort
+     * and the target exception Level to EL1.
+     */
+    c->exception_index = EXCP_DATA_ABORT;
+    env->exception.target_el = 1;
+
+    /*
+     * Set the DFSC to synchronous external abort and set FnV to not valid,
+     * this will tell guest the FAR_ELx is UNKNOWN for this abort.
+     */
+
+    /* This exception comes from lower or current exception level. */
+    same_el = arm_current_el(env) == env->exception.target_el;
+    esr = syn_data_abort_no_iss(same_el, 1, 0, 0, 0, 0, 0x10);
+
+    env->exception.syndrome = esr;
+
+    /**
+     * The vcpu thread already hold BQL, so no need hold again when
+     * calling do_interrupt
+     */
+    cc->do_interrupt(c);
+}
+
 #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
                  KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
 
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index 5feb312941..499672ebbc 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -33,7 +33,7 @@  static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
      * ISV field.
      */
     if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
-        syn = syn_data_abort_no_iss(same_el,
+        syn = syn_data_abort_no_iss(same_el, 0,
                                     ea, 0, s1ptw, is_write, fsc);
     } else {
         /*