|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/3] xen/arm: io: Distinguish unhandled IO from aborted one
On Tue, 30 Jan 2018, Julien Grall wrote:
> Currently, Xen is considering that an IO could either be handled or
> unhandled. When unhandled, the stage-2 abort function will try another
> way to resolve the abort.
>
> However, the MMIO emulation may return unhandled when the address
> belongs to an emulated range but was not correct. In that case, Xen
> should avodi to try another way and directly inject a guest data abort.
^ avoid
> Introduce a tri-state return to distinguish the following state:
> * IO_ABORT: The IO was handled but resulted to an abort
^ in an abort
> * IO_HANDLED: The IO was handled
> * IO_UNHANDLED: The IO was unhandled
>
> For now, it is considered that an IO belonging to an emulated range
> could either be handled or inject an abort. This could be revisit in the
> future if overlapped region exist (or we want to try another way to
> resolve the abort).
>
> Signed-off-by: Julien Grall <julien.grall@xxxxxxx>
> ---
> xen/arch/arm/io.c | 24 ++++++++++++++----------
> xen/arch/arm/traps.c | 34 +++++++++++++++++++++++-----------
> xen/include/asm-arm/mmio.h | 9 ++++++++-
> 3 files changed, 45 insertions(+), 22 deletions(-)
>
> diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
> index c748d8f5bf..a74ec21b86 100644
> --- a/xen/arch/arm/io.c
> +++ b/xen/arch/arm/io.c
> @@ -23,8 +23,9 @@
> #include <asm/current.h>
> #include <asm/mmio.h>
>
> -static int handle_read(const struct mmio_handler *handler, struct vcpu *v,
> - mmio_info_t *info)
> +static enum io_state handle_read(const struct mmio_handler *handler,
> + struct vcpu *v,
> + mmio_info_t *info)
> {
> const struct hsr_dabt dabt = info->dabt;
> struct cpu_user_regs *regs = guest_cpu_user_regs();
> @@ -37,7 +38,7 @@ static int handle_read(const struct mmio_handler *handler,
> struct vcpu *v,
> uint8_t size = (1 << dabt.size) * 8;
>
> if ( !handler->ops->read(v, info, &r, handler->priv) )
> - return 0;
> + return IO_ABORT;
>
> /*
> * Sign extend if required.
> @@ -57,17 +58,20 @@ static int handle_read(const struct mmio_handler
> *handler, struct vcpu *v,
>
> set_user_reg(regs, dabt.reg, r);
>
> - return 1;
> + return IO_HANDLED;
> }
>
> -static int handle_write(const struct mmio_handler *handler, struct vcpu *v,
> - mmio_info_t *info)
> +static enum io_state handle_write(const struct mmio_handler *handler,
> + struct vcpu *v,
> + mmio_info_t *info)
> {
> const struct hsr_dabt dabt = info->dabt;
> struct cpu_user_regs *regs = guest_cpu_user_regs();
> + int ret;
>
> - return handler->ops->write(v, info, get_user_reg(regs, dabt.reg),
> - handler->priv);
> + ret = handler->ops->write(v, info, get_user_reg(regs, dabt.reg),
> + handler->priv);
> + return ( ret ) ? IO_HANDLED : IO_ABORT;
> }
>
> /* This function assumes that mmio regions are not overlapped */
> @@ -100,14 +104,14 @@ static const struct mmio_handler
> *find_mmio_handler(struct domain *d,
> return handler;
> }
>
> -int handle_mmio(mmio_info_t *info)
> +enum io_state handle_mmio(mmio_info_t *info)
> {
> struct vcpu *v = current;
> const struct mmio_handler *handler = NULL;
>
> handler = find_mmio_handler(v->domain, info->gpa);
> if ( !handler )
> - return 0;
> + return IO_UNHANDLED;
>
> if ( info->dabt.write )
> return handle_write(handler, v, info);
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index c8534d6cff..843adf4959 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -1864,10 +1864,10 @@ static inline bool hpfar_is_valid(bool s1ptw, uint8_t
> fsc)
> return s1ptw || (fsc == FSC_FLT_TRANS && !check_workaround_834220());
> }
>
> -static bool try_handle_mmio(struct cpu_user_regs *regs,
> - const union hsr hsr,
> - paddr_t gpa)
> -{
> +static enum io_state try_handle_mmio(struct cpu_user_regs *regs,
> + const union hsr hsr,
> + paddr_t gpa)
> + {
> const struct hsr_dabt dabt = hsr.dabt;
> mmio_info_t info = {
> .gpa = gpa,
> @@ -1879,11 +1879,11 @@ static bool try_handle_mmio(struct cpu_user_regs
> *regs,
>
> /* stage-1 page table should never live in an emulated MMIO region */
> if ( dabt.s1ptw )
> - return false;
> + return IO_UNHANDLED;
>
> /* All the instructions used on emulated MMIO region should be valid */
> if ( !dabt.valid )
> - return false;
> + return IO_UNHANDLED;
>
> /*
> * Erratum 766422: Thumb store translation fault to Hypervisor may
> @@ -1896,11 +1896,11 @@ static bool try_handle_mmio(struct cpu_user_regs
> *regs,
> if ( rc )
> {
> gprintk(XENLOG_DEBUG, "Unable to decode instruction\n");
> - return false;
> + return IO_ABORT;
> }
> }
Why do the first two error checks result in IO_UNHANDLED, while the
third result in IO_ABORT? Specifically in relation to pagetable walk
failures due to someone else changing stage-2 entry simultaneously (see
comment toward the end of do_trap_stage2_abort_guest)?
> - return !!handle_mmio(&info);
> + return handle_mmio(&info);
> }
>
> /*
> @@ -2005,10 +2005,21 @@ static void do_trap_stage2_abort_guest(struct
> cpu_user_regs *regs,
> *
> * Note that emulated region cannot be executed
> */
> - if ( is_data && try_handle_mmio(regs, hsr, gpa) )
> + if ( is_data )
> {
> - advance_pc(regs, hsr);
> - return;
> + enum io_state state = try_handle_mmio(regs, hsr, gpa);
> +
> + switch ( state )
> + {
> + case IO_ABORT:
> + goto inject_abt;
> + case IO_HANDLED:
> + advance_pc(regs, hsr);
> + return;
> + case IO_UNHANDLED:
> + /* Nothing to do */
> + break;
> + }
> }
>
> /*
> @@ -2029,6 +2040,7 @@ static void do_trap_stage2_abort_guest(struct
> cpu_user_regs *regs,
> hsr.bits, xabt.fsc);
> }
>
> +inject_abt:
> gdprintk(XENLOG_DEBUG, "HSR=0x%x pc=%#"PRIregister" gva=%#"PRIvaddr
> " gpa=%#"PRIpaddr"\n", hsr.bits, regs->pc, gva, gpa);
> if ( is_data )
> diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
> index 37e2b7a707..baaecf6931 100644
> --- a/xen/include/asm-arm/mmio.h
> +++ b/xen/include/asm-arm/mmio.h
> @@ -32,6 +32,13 @@ typedef struct
> paddr_t gpa;
> } mmio_info_t;
>
> +enum io_state
> +{
> + IO_ABORT, /* The IO was handled by the helper and lead to an
> abort. */
^ led
> + IO_HANDLED, /* The IO was successfully handled by the helper. */
> + IO_UNHANDLED, /* The IO was not handled by the helper. */
> +};
> +
> typedef int (*mmio_read_t)(struct vcpu *v, mmio_info_t *info,
> register_t *r, void *priv);
> typedef int (*mmio_write_t)(struct vcpu *v, mmio_info_t *info,
> @@ -56,7 +63,7 @@ struct vmmio {
> struct mmio_handler *handlers;
> };
>
> -extern int handle_mmio(mmio_info_t *info);
> +extern enum io_state handle_mmio(mmio_info_t *info);
> void register_mmio_handler(struct domain *d,
> const struct mmio_handler_ops *ops,
> paddr_t addr, paddr_t size, void *priv);
> --
> 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 |