|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [v2 16/16] xen/arm: traps: Merge do_trap_instr_abort_guest and do_trap_data_abort_guest
On Tue, 12 Dec 2017, Julien Grall wrote:
> The two helpers do_trap_instr_abort_guest and do_trap_data_abort_guest
> are used trap stage-2 abort. While the former is only handling prefetch
> abort and the latter data abort, they are very similarly and does not
> warrant to have separate helpers.
>
> For instance, merging the both will make easier to maintain stage-2 abort
> handling. So consolidate the two helpers in a new helper
> do_trap_stage2_abort.
>
> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>
> ---
> Changes in v2
> - Fix the way to compute npfec.write_access
> ---
> xen/arch/arm/traps.c | 133
> ++++++++++++++++-----------------------------------
> 1 file changed, 41 insertions(+), 92 deletions(-)
>
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 082396c26d..013c1600ec 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -1861,79 +1861,6 @@ static inline bool hpfar_is_valid(bool s1ptw, uint8_t
> fsc)
> return s1ptw || (fsc == FSC_FLT_TRANS && !check_workaround_834220());
> }
>
> -static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
> - const union hsr hsr)
> -{
> - int rc;
> - register_t gva;
> - uint8_t fsc = hsr.iabt.ifsc & ~FSC_LL_MASK;
> - paddr_t gpa;
> - mfn_t mfn;
> -
> - gva = get_hfar(false /* is_data */);
> -
> - /*
> - * If this bit has been set, it means that this instruction abort is
> caused
> - * by a guest external abort. We can handle this instruction abort as
> guest
> - * SError.
> - */
> - if ( hsr.iabt.eat )
> - return __do_trap_serror(regs, true);
> -
> -
> - if ( hpfar_is_valid(hsr.iabt.s1ptw, fsc) )
> - gpa = get_faulting_ipa(gva);
> - else
> - {
> - /*
> - * Flush the TLB to make sure the DTLB is clear before
> - * doing GVA->IPA translation. If we got here because of
> - * an entry only present in the ITLB, this translation may
> - * still be inaccurate.
> - */
> - flush_tlb_local();
> -
> - /*
> - * We may not be able to translate because someone is
> - * playing with the Stage-2 page table of the domain.
> - * Return to the guest.
> - */
> - rc = gva_to_ipa(gva, &gpa, GV2M_READ);
> - if ( rc == -EFAULT )
> - return; /* Try again */
> - }
> -
> - switch ( fsc )
> - {
> - case FSC_FLT_PERM:
> - {
> - const struct npfec npfec = {
> - .insn_fetch = 1,
> - .gla_valid = 1,
> - .kind = hsr.iabt.s1ptw ? npfec_kind_in_gpt : npfec_kind_with_gla
> - };
> -
> - p2m_mem_access_check(gpa, gva, npfec);
> - /*
> - * The only way to get here right now is because of mem_access,
> - * thus reinjecting the exception to the guest is never required.
> - */
> - return;
> - }
> - case FSC_FLT_TRANS:
> - /*
> - * The PT walk may have failed because someone was playing
> - * with the Stage-2 page table. Walk the Stage-2 PT to check
> - * if the entry exists. If it's the case, return to the guest
> - */
> - mfn = gfn_to_mfn(current->domain, _gfn(paddr_to_pfn(gpa)));
> - if ( !mfn_eq(mfn, INVALID_MFN) )
> - return;
> - }
> -
> - inject_iabt_exception(regs, gva, hsr.len);
> -}
> -
> static bool try_handle_mmio(struct cpu_user_regs *regs,
> const union hsr hsr,
> paddr_t gpa)
> @@ -1945,6 +1872,8 @@ static bool try_handle_mmio(struct cpu_user_regs *regs,
> };
> int rc;
>
> + ASSERT(hsr.ec == HSR_EC_DATA_ABORT_LOWER_EL);
> +
> /* stage-1 page table should never live in an emulated MMIO region */
> if ( dabt.s1ptw )
> return false;
> @@ -2000,29 +1929,43 @@ static bool try_map_mmio(gfn_t gfn)
> return !map_regions_p2mt(d, gfn, 1, mfn, p2m_mmio_direct_c);
> }
>
> -static void do_trap_data_abort_guest(struct cpu_user_regs *regs,
> - const union hsr hsr)
> +static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
> + const union hsr hsr)
> {
> - const struct hsr_dabt dabt = hsr.dabt;
> + /*
> + * The encoding of hsr_iabt is a subset of hsr_dabt. So use
> + * hsr_dabt to represent an abort fault.
> + */
> + const struct hsr_xabt xabt = hsr.xabt;
> int rc;
> vaddr_t gva;
> paddr_t gpa;
> - uint8_t fsc = hsr.dabt.dfsc & ~FSC_LL_MASK;
> + uint8_t fsc = xabt.fsc & ~FSC_LL_MASK;
> mfn_t mfn;
> + bool is_data = (hsr.ec == HSR_EC_DATA_ABORT_LOWER_EL);
>
> /*
> - * If this bit has been set, it means that this data abort is caused
> - * by a guest external abort. We treat this data abort as guest SError.
> + * If this bit has been set, it means that this stage-2 abort is caused
> + * by a guest external abort. We treat this stage-2 abort as guest
> SError.
> */
> - if ( dabt.eat )
> + if ( xabt.eat )
> return __do_trap_serror(regs, true);
>
> - gva = get_hfar(true /* is_data */);
> + gva = get_hfar(is_data);
>
> - if ( hpfar_is_valid(dabt.s1ptw, fsc) )
> + if ( hpfar_is_valid(xabt.s1ptw, fsc) )
> gpa = get_faulting_ipa(gva);
> else
> {
> + /*
> + * Flush the TLB to make sure the DTLB is clear before
> + * doing GVA->IPA translation. If we got here because of
> + * an entry only present in the ITLB, this translation may
> + * still be inaccurate.
> + */
> + if ( !is_data )
> + flush_tlb_local();
> +
> rc = gva_to_ipa(gva, &gpa, GV2M_READ);
> /*
> * We may not be able to translate because someone is
> @@ -2038,10 +1981,11 @@ static void do_trap_data_abort_guest(struct
> cpu_user_regs *regs,
> case FSC_FLT_PERM:
> {
> const struct npfec npfec = {
> - .read_access = !dabt.write,
> - .write_access = dabt.write,
> + .insn_fetch = !is_data,
> + .read_access = is_data && !hsr.dabt.write,
> + .write_access = is_data && hsr.dabt.write,
> .gla_valid = 1,
> - .kind = dabt.s1ptw ? npfec_kind_in_gpt : npfec_kind_with_gla
> + .kind = xabt.s1ptw ? npfec_kind_in_gpt : npfec_kind_with_gla
> };
>
> p2m_mem_access_check(gpa, gva, npfec);
> @@ -2055,8 +1999,10 @@ static void do_trap_data_abort_guest(struct
> cpu_user_regs *regs,
> /*
> * Attempt first to emulate the MMIO as the data abort will
> * likely happen in an emulated region.
> + *
> + * Note that emulated region cannot be executed
> */
> - if ( try_handle_mmio(regs, hsr, gpa) )
> + if ( is_data && try_handle_mmio(regs, hsr, gpa) )
> {
> advance_pc(regs, hsr);
> return;
> @@ -2071,18 +2017,21 @@ static void do_trap_data_abort_guest(struct
> cpu_user_regs *regs,
> if ( !mfn_eq(mfn, INVALID_MFN) )
> return;
>
> - if ( try_map_mmio(gaddr_to_gfn(gpa)) )
> + if ( is_data && try_map_mmio(gaddr_to_gfn(gpa)) )
> return;
>
> break;
> default:
> - gprintk(XENLOG_WARNING, "Unsupported DFSC: HSR=%#x DFSC=%#x\n",
> - hsr.bits, dabt.dfsc);
> + gprintk(XENLOG_WARNING, "Unsupported FSC: HSR=%#x DFSC=%#x\n",
> + hsr.bits, xabt.fsc);
> }
>
> gdprintk(XENLOG_DEBUG, "HSR=0x%x pc=%#"PRIregister" gva=%#"PRIvaddr
> " gpa=%#"PRIpaddr"\n", hsr.bits, regs->pc, gva, gpa);
> - inject_dabt_exception(regs, gva, hsr.len);
> + if ( is_data )
> + inject_dabt_exception(regs, gva, hsr.len);
> + else
> + inject_iabt_exception(regs, gva, hsr.len);
> }
>
> static void enter_hypervisor_head(struct cpu_user_regs *regs)
> @@ -2215,11 +2164,11 @@ void do_trap_guest_sync(struct cpu_user_regs *regs)
>
> case HSR_EC_INSTR_ABORT_LOWER_EL:
> perfc_incr(trap_iabt);
> - do_trap_instr_abort_guest(regs, hsr);
> + do_trap_stage2_abort_guest(regs, hsr);
> break;
> case HSR_EC_DATA_ABORT_LOWER_EL:
> perfc_incr(trap_dabt);
> - do_trap_data_abort_guest(regs, hsr);
> + do_trap_stage2_abort_guest(regs, hsr);
> break;
>
> default:
> --
> 2.11.0
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |