diff mbox series

[V5,14/22] arm/ioreq: Introduce arch specific bits for IOREQ/DM features

Message ID 1611601709-28361-15-git-send-email-olekstysh@gmail.com (mailing list archive)
State Superseded
Headers show
Series IOREQ feature (+ virtio-mmio) on Arm | expand

Commit Message

Oleksandr Tyshchenko Jan. 25, 2021, 7:08 p.m. UTC
From: Julien Grall <julien.grall@arm.com>

This patch adds basic IOREQ/DM support on Arm. The subsequent
patches will improve functionality and add remaining bits.

The IOREQ/DM features are supposed to be built with IOREQ_SERVER
option enabled, which is disabled by default on Arm for now.

Please note, the "PIO handling" TODO is expected to left unaddressed
for the current series. It is not an big issue for now while Xen
doesn't have support for vPCI on Arm. On Arm64 they are only used
for PCI IO Bar and we would probably want to expose them to emulator
as PIO access to make a DM completely arch-agnostic. So "PIO handling"
should be implemented when we add support for vPCI.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
[On Arm only]
Tested-by: Wei Chen <Wei.Chen@arm.com>

---
Please note, this is a split/cleanup/hardening of Julien's PoC:
"Add support for Guest IO forwarding to a device emulator"

***
I admit, I didn't resolve header dependencies completely.
For now, public/hvm/dm_op.h is included by xen/dm.h, but ought to be included
by arch/arm/dm.c. Details here:
https://lore.kernel.org/xen-devel/e0bc7f80-974e-945d-4605-173bd05302af@gmail.com/
***

Changes RFC -> V1:
   - was split into:
     - arm/ioreq: Introduce arch specific bits for IOREQ/DM features
     - xen/mm: Handle properly reference in set_foreign_p2m_entry() on Arm
   - update patch description
   - update asm-arm/hvm/ioreq.h according to the newly introduced arch functions:
     - arch_hvm_destroy_ioreq_server()
     - arch_handle_hvm_io_completion()
   - update arch files to include xen/ioreq.h
   - remove HVMOP plumbing
   - rewrite a logic to handle properly case when hvm_send_ioreq() returns IO_RETRY
   - add a logic to handle properly handle_hvm_io_completion() return value
   - rename handle_mmio() to ioreq_handle_complete_mmio()
   - move paging_mark_pfn_dirty() to asm-arm/paging.h
   - remove forward declaration for hvm_ioreq_server in asm-arm/paging.h
   - move try_fwd_ioserv() to ioreq.c, provide stubs if !CONFIG_IOREQ_SERVER
   - do not remove #ifdef CONFIG_IOREQ_SERVER in memory.c for guarding xen/ioreq.h
   - use gdprintk in try_fwd_ioserv(), remove unneeded prints
   - update list of #include-s
   - move has_vpci() to asm-arm/domain.h
   - add a comment (TODO) to unimplemented yet handle_pio()
   - remove hvm_mmio_first(last)_byte() and hvm_ioreq_(page/vcpu/server) structs
     from the arch files, they were already moved to the common code
   - remove set_foreign_p2m_entry() changes, they will be properly implemented
     in the follow-up patch
   - select IOREQ_SERVER for Arm instead of Arm64 in Kconfig
   - remove x86's realmode and other unneeded stubs from xen/ioreq.h
   - clafify ioreq_t p.df usage in try_fwd_ioserv()
   - set ioreq_t p.count to 1 in try_fwd_ioserv()

Changes V1 -> V2:
   - was split into:
     - arm/ioreq: Introduce arch specific bits for IOREQ/DM features
     - xen/arm: Stick around in leave_hypervisor_to_guest until I/O has completed
   - update the author of a patch
   - update patch description
   - move a loop in leave_hypervisor_to_guest() to a separate patch
   - set IOREQ_SERVER disabled by default
   - remove already clarified /* XXX */
   - replace BUG() by ASSERT_UNREACHABLE() in handle_pio()
   - remove default case for handling the return value of try_handle_mmio()
   - remove struct hvm_domain, enum hvm_io_completion, struct hvm_vcpu_io,
     struct hvm_vcpu from asm-arm/domain.h, these are common materials now
   - update everything according to the recent changes (IOREQ related function
     names don't contain "hvm" prefixes/infixes anymore, IOREQ related fields
     are part of common struct vcpu/domain now, etc)

Changes V2 -> V3:
   - update patch according the "legacy interface" is x86 specific
   - add dummy arch hooks
   - remove dummy paging_mark_pfn_dirty()
   - don’t include <xen/domain_page.h> in common ioreq.c
   - don’t include <public/hvm/ioreq.h> in arch ioreq.h
   - remove #define ioreq_params(d, i)

Changes V3 -> V4:
   - rebase
   - update patch according to the renaming IO_ -> VIO_ (io_ -> vio_)
     and misc changes to arch hooks
   - update patch according to the IOREQ related dm-op handling changes
   - don't include <xen/ioreq.h> from arch header
   - make all arch hooks out-of-line
   - add a comment above IOREQ_STATUS_* #define-s

Changes V4 -> V5:
   - change the placement of ioreq_server_destroy_all() in arm/domain.c
   - don't include public/hvm/dm_op.h by asm-arm/domain.h
   - include public/hvm/dm_op.h by xen/dm.h
   - put arch ioreq.h directly into asm-arm subdir
   - remove do_dm_op() in arm/dm.c, this is a common material now
   - remove obsolete ioreq_complete_mmio() from asm-arm/ioreq.h
   - optimize arch_ioreq_complete_mmio() to not call try_handle_mmio(),
     but try_handle_mmio(), use ASSERT_UNREACHABLE() if state is incorrect
   - split changes to check_for_vcpu_work() to be squashed with patch #15
---
---
 xen/arch/arm/Makefile        |   2 +
 xen/arch/arm/dm.c            |  97 +++++++++++++++++++
 xen/arch/arm/domain.c        |   9 ++
 xen/arch/arm/io.c            |  12 ++-
 xen/arch/arm/ioreq.c         | 215 +++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/traps.c         |   6 ++
 xen/include/asm-arm/domain.h |   2 +
 xen/include/asm-arm/ioreq.h  |  70 ++++++++++++++
 xen/include/asm-arm/mmio.h   |   1 +
 xen/include/xen/dm.h         |   2 +
 10 files changed, 415 insertions(+), 1 deletion(-)
 create mode 100644 xen/arch/arm/dm.c
 create mode 100644 xen/arch/arm/ioreq.c
 create mode 100644 xen/include/asm-arm/ioreq.h

Comments

Stefano Stabellini Jan. 25, 2021, 8:19 p.m. UTC | #1
On Mon, 25 Jan 2021, Oleksandr Tyshchenko wrote:
> From: Julien Grall <julien.grall@arm.com>
> 
> This patch adds basic IOREQ/DM support on Arm. The subsequent
> patches will improve functionality and add remaining bits.
> 
> The IOREQ/DM features are supposed to be built with IOREQ_SERVER
> option enabled, which is disabled by default on Arm for now.
> 
> Please note, the "PIO handling" TODO is expected to left unaddressed
> for the current series. It is not an big issue for now while Xen
> doesn't have support for vPCI on Arm. On Arm64 they are only used
> for PCI IO Bar and we would probably want to expose them to emulator
> as PIO access to make a DM completely arch-agnostic. So "PIO handling"
> should be implemented when we add support for vPCI.
> 
> Signed-off-by: Julien Grall <julien.grall@arm.com>
> Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> [On Arm only]
> Tested-by: Wei Chen <Wei.Chen@arm.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
> Please note, this is a split/cleanup/hardening of Julien's PoC:
> "Add support for Guest IO forwarding to a device emulator"
> 
> ***
> I admit, I didn't resolve header dependencies completely.
> For now, public/hvm/dm_op.h is included by xen/dm.h, but ought to be included
> by arch/arm/dm.c. Details here:
> https://lore.kernel.org/xen-devel/e0bc7f80-974e-945d-4605-173bd05302af@gmail.com/
> ***
> 
> Changes RFC -> V1:
>    - was split into:
>      - arm/ioreq: Introduce arch specific bits for IOREQ/DM features
>      - xen/mm: Handle properly reference in set_foreign_p2m_entry() on Arm
>    - update patch description
>    - update asm-arm/hvm/ioreq.h according to the newly introduced arch functions:
>      - arch_hvm_destroy_ioreq_server()
>      - arch_handle_hvm_io_completion()
>    - update arch files to include xen/ioreq.h
>    - remove HVMOP plumbing
>    - rewrite a logic to handle properly case when hvm_send_ioreq() returns IO_RETRY
>    - add a logic to handle properly handle_hvm_io_completion() return value
>    - rename handle_mmio() to ioreq_handle_complete_mmio()
>    - move paging_mark_pfn_dirty() to asm-arm/paging.h
>    - remove forward declaration for hvm_ioreq_server in asm-arm/paging.h
>    - move try_fwd_ioserv() to ioreq.c, provide stubs if !CONFIG_IOREQ_SERVER
>    - do not remove #ifdef CONFIG_IOREQ_SERVER in memory.c for guarding xen/ioreq.h
>    - use gdprintk in try_fwd_ioserv(), remove unneeded prints
>    - update list of #include-s
>    - move has_vpci() to asm-arm/domain.h
>    - add a comment (TODO) to unimplemented yet handle_pio()
>    - remove hvm_mmio_first(last)_byte() and hvm_ioreq_(page/vcpu/server) structs
>      from the arch files, they were already moved to the common code
>    - remove set_foreign_p2m_entry() changes, they will be properly implemented
>      in the follow-up patch
>    - select IOREQ_SERVER for Arm instead of Arm64 in Kconfig
>    - remove x86's realmode and other unneeded stubs from xen/ioreq.h
>    - clafify ioreq_t p.df usage in try_fwd_ioserv()
>    - set ioreq_t p.count to 1 in try_fwd_ioserv()
> 
> Changes V1 -> V2:
>    - was split into:
>      - arm/ioreq: Introduce arch specific bits for IOREQ/DM features
>      - xen/arm: Stick around in leave_hypervisor_to_guest until I/O has completed
>    - update the author of a patch
>    - update patch description
>    - move a loop in leave_hypervisor_to_guest() to a separate patch
>    - set IOREQ_SERVER disabled by default
>    - remove already clarified /* XXX */
>    - replace BUG() by ASSERT_UNREACHABLE() in handle_pio()
>    - remove default case for handling the return value of try_handle_mmio()
>    - remove struct hvm_domain, enum hvm_io_completion, struct hvm_vcpu_io,
>      struct hvm_vcpu from asm-arm/domain.h, these are common materials now
>    - update everything according to the recent changes (IOREQ related function
>      names don't contain "hvm" prefixes/infixes anymore, IOREQ related fields
>      are part of common struct vcpu/domain now, etc)
> 
> Changes V2 -> V3:
>    - update patch according the "legacy interface" is x86 specific
>    - add dummy arch hooks
>    - remove dummy paging_mark_pfn_dirty()
>    - don’t include <xen/domain_page.h> in common ioreq.c
>    - don’t include <public/hvm/ioreq.h> in arch ioreq.h
>    - remove #define ioreq_params(d, i)
> 
> Changes V3 -> V4:
>    - rebase
>    - update patch according to the renaming IO_ -> VIO_ (io_ -> vio_)
>      and misc changes to arch hooks
>    - update patch according to the IOREQ related dm-op handling changes
>    - don't include <xen/ioreq.h> from arch header
>    - make all arch hooks out-of-line
>    - add a comment above IOREQ_STATUS_* #define-s
> 
> Changes V4 -> V5:
>    - change the placement of ioreq_server_destroy_all() in arm/domain.c
>    - don't include public/hvm/dm_op.h by asm-arm/domain.h
>    - include public/hvm/dm_op.h by xen/dm.h
>    - put arch ioreq.h directly into asm-arm subdir
>    - remove do_dm_op() in arm/dm.c, this is a common material now
>    - remove obsolete ioreq_complete_mmio() from asm-arm/ioreq.h
>    - optimize arch_ioreq_complete_mmio() to not call try_handle_mmio(),
>      but try_handle_mmio(), use ASSERT_UNREACHABLE() if state is incorrect
>    - split changes to check_for_vcpu_work() to be squashed with patch #15
> ---
> ---
>  xen/arch/arm/Makefile        |   2 +
>  xen/arch/arm/dm.c            |  97 +++++++++++++++++++
>  xen/arch/arm/domain.c        |   9 ++
>  xen/arch/arm/io.c            |  12 ++-
>  xen/arch/arm/ioreq.c         | 215 +++++++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/traps.c         |   6 ++
>  xen/include/asm-arm/domain.h |   2 +
>  xen/include/asm-arm/ioreq.h  |  70 ++++++++++++++
>  xen/include/asm-arm/mmio.h   |   1 +
>  xen/include/xen/dm.h         |   2 +
>  10 files changed, 415 insertions(+), 1 deletion(-)
>  create mode 100644 xen/arch/arm/dm.c
>  create mode 100644 xen/arch/arm/ioreq.c
>  create mode 100644 xen/include/asm-arm/ioreq.h
> 
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 512ffdd..16e6523 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -13,6 +13,7 @@ obj-y += cpuerrata.o
>  obj-y += cpufeature.o
>  obj-y += decode.o
>  obj-y += device.o
> +obj-$(CONFIG_IOREQ_SERVER) += dm.o
>  obj-y += domain.o
>  obj-y += domain_build.init.o
>  obj-y += domctl.o
> @@ -27,6 +28,7 @@ obj-y += guest_atomics.o
>  obj-y += guest_walk.o
>  obj-y += hvm.o
>  obj-y += io.o
> +obj-$(CONFIG_IOREQ_SERVER) += ioreq.o
>  obj-y += irq.o
>  obj-y += kernel.init.o
>  obj-$(CONFIG_LIVEPATCH) += livepatch.o
> diff --git a/xen/arch/arm/dm.c b/xen/arch/arm/dm.c
> new file mode 100644
> index 0000000..f254ed7
> --- /dev/null
> +++ b/xen/arch/arm/dm.c
> @@ -0,0 +1,97 @@
> +/*
> + * Copyright (c) 2019 Arm ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <xen/dm.h>
> +#include <xen/guest_access.h>
> +#include <xen/hypercall.h>
> +#include <xen/ioreq.h>
> +#include <xen/nospec.h>
> +
> +int dm_op(const struct dmop_args *op_args)
> +{
> +    struct domain *d;
> +    struct xen_dm_op op;
> +    bool const_op = true;
> +    long rc;
> +    size_t offset;
> +
> +    static const uint8_t op_size[] = {
> +        [XEN_DMOP_create_ioreq_server]              = sizeof(struct xen_dm_op_create_ioreq_server),
> +        [XEN_DMOP_get_ioreq_server_info]            = sizeof(struct xen_dm_op_get_ioreq_server_info),
> +        [XEN_DMOP_map_io_range_to_ioreq_server]     = sizeof(struct xen_dm_op_ioreq_server_range),
> +        [XEN_DMOP_unmap_io_range_from_ioreq_server] = sizeof(struct xen_dm_op_ioreq_server_range),
> +        [XEN_DMOP_set_ioreq_server_state]           = sizeof(struct xen_dm_op_set_ioreq_server_state),
> +        [XEN_DMOP_destroy_ioreq_server]             = sizeof(struct xen_dm_op_destroy_ioreq_server),
> +    };
> +
> +    rc = rcu_lock_remote_domain_by_id(op_args->domid, &d);
> +    if ( rc )
> +        return rc;
> +
> +    rc = xsm_dm_op(XSM_DM_PRIV, d);
> +    if ( rc )
> +        goto out;
> +
> +    offset = offsetof(struct xen_dm_op, u);
> +
> +    rc = -EFAULT;
> +    if ( op_args->buf[0].size < offset )
> +        goto out;
> +
> +    if ( copy_from_guest_offset((void *)&op, op_args->buf[0].h, 0, offset) )
> +        goto out;
> +
> +    if ( op.op >= ARRAY_SIZE(op_size) )
> +    {
> +        rc = -EOPNOTSUPP;
> +        goto out;
> +    }
> +
> +    op.op = array_index_nospec(op.op, ARRAY_SIZE(op_size));
> +
> +    if ( op_args->buf[0].size < offset + op_size[op.op] )
> +        goto out;
> +
> +    if ( copy_from_guest_offset((void *)&op.u, op_args->buf[0].h, offset,
> +                                op_size[op.op]) )
> +        goto out;
> +
> +    rc = -EINVAL;
> +    if ( op.pad )
> +        goto out;
> +
> +    rc = ioreq_server_dm_op(&op, d, &const_op);
> +
> +    if ( (!rc || rc == -ERESTART) &&
> +         !const_op && copy_to_guest_offset(op_args->buf[0].h, offset,
> +                                           (void *)&op.u, op_size[op.op]) )
> +        rc = -EFAULT;
> +
> + out:
> +    rcu_unlock_domain(d);
> +
> +    return rc;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 18cafcd..bdd3d3e 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -15,6 +15,7 @@
>  #include <xen/guest_access.h>
>  #include <xen/hypercall.h>
>  #include <xen/init.h>
> +#include <xen/ioreq.h>
>  #include <xen/lib.h>
>  #include <xen/livepatch.h>
>  #include <xen/sched.h>
> @@ -696,6 +697,10 @@ int arch_domain_create(struct domain *d,
>  
>      ASSERT(config != NULL);
>  
> +#ifdef CONFIG_IOREQ_SERVER
> +    ioreq_domain_init(d);
> +#endif
> +
>      /* p2m_init relies on some value initialized by the IOMMU subsystem */
>      if ( (rc = iommu_domain_init(d, config->iommu_opts)) != 0 )
>          goto fail;
> @@ -1009,6 +1014,10 @@ int domain_relinquish_resources(struct domain *d)
>           */
>          domain_vpl011_deinit(d);
>  
> +#ifdef CONFIG_IOREQ_SERVER
> +        ioreq_server_destroy_all(d);
> +#endif
> +
>      PROGRESS(tee):
>          ret = tee_relinquish_resources(d);
>          if (ret )
> diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
> index ae7ef96..7ac0303 100644
> --- a/xen/arch/arm/io.c
> +++ b/xen/arch/arm/io.c
> @@ -16,12 +16,14 @@
>   * GNU General Public License for more details.
>   */
>  
> +#include <xen/ioreq.h>
>  #include <xen/lib.h>
>  #include <xen/spinlock.h>
>  #include <xen/sched.h>
>  #include <xen/sort.h>
>  #include <asm/cpuerrata.h>
>  #include <asm/current.h>
> +#include <asm/ioreq.h>
>  #include <asm/mmio.h>
>  
>  #include "decode.h"
> @@ -123,7 +125,15 @@ enum io_state try_handle_mmio(struct cpu_user_regs *regs,
>  
>      handler = find_mmio_handler(v->domain, info.gpa);
>      if ( !handler )
> -        return IO_UNHANDLED;
> +    {
> +        int rc;
> +
> +        rc = try_fwd_ioserv(regs, v, &info);
> +        if ( rc == IO_HANDLED )
> +            return handle_ioserv(regs, v);
> +
> +        return rc;
> +    }
>  
>      /* All the instructions used on emulated MMIO region should be valid */
>      if ( !dabt.valid )
> diff --git a/xen/arch/arm/ioreq.c b/xen/arch/arm/ioreq.c
> new file mode 100644
> index 0000000..ffeeb0b
> --- /dev/null
> +++ b/xen/arch/arm/ioreq.c
> @@ -0,0 +1,215 @@
> +/*
> + * arm/ioreq.c: hardware virtual machine I/O emulation
> + *
> + * Copyright (c) 2019 Arm ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <xen/domain.h>
> +#include <xen/ioreq.h>
> +
> +#include <asm/traps.h>
> +
> +#include <public/hvm/ioreq.h>
> +
> +enum io_state handle_ioserv(struct cpu_user_regs *regs, struct vcpu *v)
> +{
> +    const union hsr hsr = { .bits = regs->hsr };
> +    const struct hsr_dabt dabt = hsr.dabt;
> +    /* Code is similar to handle_read */
> +    uint8_t size = (1 << dabt.size) * 8;
> +    register_t r = v->io.req.data;
> +
> +    /* We are done with the IO */
> +    v->io.req.state = STATE_IOREQ_NONE;
> +
> +    if ( dabt.write )
> +        return IO_HANDLED;
> +
> +    /*
> +     * Sign extend if required.
> +     * Note that we expect the read handler to have zeroed the bits
> +     * outside the requested access size.
> +     */
> +    if ( dabt.sign && (r & (1UL << (size - 1))) )
> +    {
> +        /*
> +         * We are relying on register_t using the same as
> +         * an unsigned long in order to keep the 32-bit assembly
> +         * code smaller.
> +         */
> +        BUILD_BUG_ON(sizeof(register_t) != sizeof(unsigned long));
> +        r |= (~0UL) << size;
> +    }
> +
> +    set_user_reg(regs, dabt.reg, r);
> +
> +    return IO_HANDLED;
> +}
> +
> +enum io_state try_fwd_ioserv(struct cpu_user_regs *regs,
> +                             struct vcpu *v, mmio_info_t *info)
> +{
> +    struct vcpu_io *vio = &v->io;
> +    ioreq_t p = {
> +        .type = IOREQ_TYPE_COPY,
> +        .addr = info->gpa,
> +        .size = 1 << info->dabt.size,
> +        .count = 1,
> +        .dir = !info->dabt.write,
> +        /*
> +         * On x86, df is used by 'rep' instruction to tell the direction
> +         * to iterate (forward or backward).
> +         * On Arm, all the accesses to MMIO region will do a single
> +         * memory access. So for now, we can safely always set to 0.
> +         */
> +        .df = 0,
> +        .data = get_user_reg(regs, info->dabt.reg),
> +        .state = STATE_IOREQ_READY,
> +    };
> +    struct ioreq_server *s = NULL;
> +    enum io_state rc;
> +
> +    switch ( vio->req.state )
> +    {
> +    case STATE_IOREQ_NONE:
> +        break;
> +
> +    default:
> +        gdprintk(XENLOG_ERR, "wrong state %u\n", vio->req.state);
> +        return IO_ABORT;
> +    }
> +
> +    s = ioreq_server_select(v->domain, &p);
> +    if ( !s )
> +        return IO_UNHANDLED;
> +
> +    if ( !info->dabt.valid )
> +        return IO_ABORT;
> +
> +    vio->req = p;
> +
> +    rc = ioreq_send(s, &p, 0);
> +    if ( rc != IO_RETRY || v->domain->is_shutting_down )
> +        vio->req.state = STATE_IOREQ_NONE;
> +    else if ( !ioreq_needs_completion(&vio->req) )
> +        rc = IO_HANDLED;
> +    else
> +        vio->completion = VIO_mmio_completion;
> +
> +    return rc;
> +}
> +
> +bool arch_ioreq_complete_mmio(void)
> +{
> +    struct vcpu *v = current;
> +    struct cpu_user_regs *regs = guest_cpu_user_regs();
> +    const union hsr hsr = { .bits = regs->hsr };
> +
> +    if ( v->io.req.state != STATE_IORESP_READY )
> +    {
> +        ASSERT_UNREACHABLE();
> +        return false;
> +    }
> +
> +    if ( handle_ioserv(regs, v) == IO_HANDLED )
> +    {
> +        advance_pc(regs, hsr);
> +        return true;
> +    }
> +
> +    return false;
> +}
> +
> +bool arch_vcpu_ioreq_completion(enum vio_completion completion)
> +{
> +    ASSERT_UNREACHABLE();
> +    return true;
> +}
> +
> +/*
> + * The "legacy" mechanism of mapping magic pages for the IOREQ servers
> + * is x86 specific, so the following hooks don't need to be implemented on Arm:
> + * - arch_ioreq_server_map_pages
> + * - arch_ioreq_server_unmap_pages
> + * - arch_ioreq_server_enable
> + * - arch_ioreq_server_disable
> + */
> +int arch_ioreq_server_map_pages(struct ioreq_server *s)
> +{
> +    return -EOPNOTSUPP;
> +}
> +
> +void arch_ioreq_server_unmap_pages(struct ioreq_server *s)
> +{
> +}
> +
> +void arch_ioreq_server_enable(struct ioreq_server *s)
> +{
> +}
> +
> +void arch_ioreq_server_disable(struct ioreq_server *s)
> +{
> +}
> +
> +void arch_ioreq_server_destroy(struct ioreq_server *s)
> +{
> +}
> +
> +int arch_ioreq_server_map_mem_type(struct domain *d,
> +                                   struct ioreq_server *s,
> +                                   uint32_t flags)
> +{
> +    return -EOPNOTSUPP;
> +}
> +
> +void arch_ioreq_server_map_mem_type_completed(struct domain *d,
> +                                              struct ioreq_server *s,
> +                                              uint32_t flags)
> +{
> +}
> +
> +bool arch_ioreq_server_destroy_all(struct domain *d)
> +{
> +    return true;
> +}
> +
> +bool arch_ioreq_server_get_type_addr(const struct domain *d,
> +                                     const ioreq_t *p,
> +                                     uint8_t *type,
> +                                     uint64_t *addr)
> +{
> +    if ( p->type != IOREQ_TYPE_COPY && p->type != IOREQ_TYPE_PIO )
> +        return false;
> +
> +    *type = (p->type == IOREQ_TYPE_PIO) ?
> +             XEN_DMOP_IO_RANGE_PORT : XEN_DMOP_IO_RANGE_MEMORY;
> +    *addr = p->addr;
> +
> +    return true;
> +}
> +
> +void arch_ioreq_domain_init(struct domain *d)
> +{
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 1af1bb9..b0cd8f9 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -1385,6 +1385,9 @@ static arm_hypercall_t arm_hypercall_table[] = {
>  #ifdef CONFIG_HYPFS
>      HYPERCALL(hypfs_op, 5),
>  #endif
> +#ifdef CONFIG_IOREQ_SERVER
> +    HYPERCALL(dm_op, 3),
> +#endif
>  };
>  
>  #ifndef NDEBUG
> @@ -1956,6 +1959,9 @@ static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
>              case IO_HANDLED:
>                  advance_pc(regs, hsr);
>                  return;
> +            case IO_RETRY:
> +                /* finish later */
> +                return;
>              case IO_UNHANDLED:
>                  /* IO unhandled, try another way to handle it. */
>                  break;
> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index 6819a3b..1da90f2 100644
> --- a/xen/include/asm-arm/domain.h
> +++ b/xen/include/asm-arm/domain.h
> @@ -262,6 +262,8 @@ static inline void arch_vcpu_block(struct vcpu *v) {}
>  
>  #define arch_vm_assist_valid_mask(d) (1UL << VMASST_TYPE_runstate_update_flag)
>  
> +#define has_vpci(d)    ({ (void)(d); false; })
> +
>  #endif /* __ASM_DOMAIN_H__ */
>  
>  /*
> diff --git a/xen/include/asm-arm/ioreq.h b/xen/include/asm-arm/ioreq.h
> new file mode 100644
> index 0000000..5018597
> --- /dev/null
> +++ b/xen/include/asm-arm/ioreq.h
> @@ -0,0 +1,70 @@
> +/*
> + * ioreq.h: Hardware virtual machine assist interface definitions.
> + *
> + * Copyright (c) 2016 Citrix Systems Inc.
> + * Copyright (c) 2019 Arm ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __ASM_ARM_IOREQ_H__
> +#define __ASM_ARM_IOREQ_H__
> +
> +#ifdef CONFIG_IOREQ_SERVER
> +enum io_state handle_ioserv(struct cpu_user_regs *regs, struct vcpu *v);
> +enum io_state try_fwd_ioserv(struct cpu_user_regs *regs,
> +                             struct vcpu *v, mmio_info_t *info);
> +#else
> +static inline enum io_state handle_ioserv(struct cpu_user_regs *regs,
> +                                          struct vcpu *v)
> +{
> +    return IO_UNHANDLED;
> +}
> +
> +static inline enum io_state try_fwd_ioserv(struct cpu_user_regs *regs,
> +                                           struct vcpu *v, mmio_info_t *info)
> +{
> +    return IO_UNHANDLED;
> +}
> +#endif
> +
> +static inline bool handle_pio(uint16_t port, unsigned int size, int dir)
> +{
> +    /*
> +     * TODO: For Arm64, the main user will be PCI. So this should be
> +     * implemented when we add support for vPCI.
> +     */
> +    ASSERT_UNREACHABLE();
> +    return true;
> +}
> +
> +static inline void msix_write_completion(struct vcpu *v)
> +{
> +}
> +
> +/* This correlation must not be altered */
> +#define IOREQ_STATUS_HANDLED     IO_HANDLED
> +#define IOREQ_STATUS_UNHANDLED   IO_UNHANDLED
> +#define IOREQ_STATUS_RETRY       IO_RETRY
> +
> +#endif /* __ASM_ARM_IOREQ_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
> index 8dbfb27..7ab873c 100644
> --- a/xen/include/asm-arm/mmio.h
> +++ b/xen/include/asm-arm/mmio.h
> @@ -37,6 +37,7 @@ enum io_state
>      IO_ABORT,       /* The IO was handled by the helper and led to an abort. */
>      IO_HANDLED,     /* The IO was successfully handled by the helper. */
>      IO_UNHANDLED,   /* The IO was not handled by the helper. */
> +    IO_RETRY,       /* Retry the emulation for some reason */
>  };
>  
>  typedef int (*mmio_read_t)(struct vcpu *v, mmio_info_t *info,
> diff --git a/xen/include/xen/dm.h b/xen/include/xen/dm.h
> index 4bd7e57..7f9f0bd 100644
> --- a/xen/include/xen/dm.h
> +++ b/xen/include/xen/dm.h
> @@ -19,6 +19,8 @@
>  
>  #include <xen/sched.h>
>  
> +#include <public/hvm/dm_op.h>
> +
>  struct dmop_args {
>      domid_t domid;
>      unsigned int nr_bufs;
> -- 
> 2.7.4
>
Jan Beulich Jan. 26, 2021, 9:15 a.m. UTC | #2
On 25.01.2021 20:08, Oleksandr Tyshchenko wrote:
> --- a/xen/include/xen/dm.h
> +++ b/xen/include/xen/dm.h
> @@ -19,6 +19,8 @@
>  
>  #include <xen/sched.h>
>  
> +#include <public/hvm/dm_op.h>
> +
>  struct dmop_args {
>      domid_t domid;
>      unsigned int nr_bufs;

How come this becomes necessary at this point in the series, when
nothing else in this header changes, and nothing changes in the
public headers at all? Is it perhaps a .c file that needs the
#include instead? Headers shouldn't pull in other headers without
clear need - as indicated in reply to a prior version, we have
way too many bad examples (causing headaches in certain cases),
and we'd like to avoid gaining more. (Oh, I notice you actually
have a post-commit-message remark about this, but then this
patch should be marked RFC until the issue was resolved.)

Jan
Oleksandr Tyshchenko Jan. 27, 2021, 9:54 a.m. UTC | #3
On 26.01.21 11:15, Jan Beulich wrote:

Hi Jan

> On 25.01.2021 20:08, Oleksandr Tyshchenko wrote:
>> --- a/xen/include/xen/dm.h
>> +++ b/xen/include/xen/dm.h
>> @@ -19,6 +19,8 @@
>>   
>>   #include <xen/sched.h>
>>   
>> +#include <public/hvm/dm_op.h>
>> +
>>   struct dmop_args {
>>       domid_t domid;
>>       unsigned int nr_bufs;
> How come this becomes necessary at this point in the series, when
> nothing else in this header changes, and nothing changes in the
> public headers at all? Is it perhaps a .c file that needs the
> #include instead? Headers shouldn't pull in other headers without
> clear need - as indicated in reply to a prior version, we have
> way too many bad examples (causing headaches in certain cases),
> and we'd like to avoid gaining more.

Yes, I understand this and completely agree. I remember last discussion 
on that, this is not forgotten. The only reason I made this (non 
entirely correct) change is to make
series compilable on Arm with IOREQ support enabled. If I considered 
this change as a correct one I would make it from the very beginning (in 
patch #9 which adds this common header)...
I added remark to draw reviewer's attention on the fact that I got stuck 
with resolving that, what I did wrong and how it should be done 
properly. The problem is that I didn't manage to make it properly.

Of course, I tried to include it directly by dm.c, but this didn't help 
much without violating "alphabetical order" rule. Details here:
https://lore.kernel.org/xen-devel/e0bc7f80-974e-945d-4605-173bd05302af@gmail.com/

I would appreciate any input on that.

> (Oh, I notice you actually
> have a post-commit-message remark about this, but then this
> patch should be marked RFC until the issue was resolved.)

Agree, I should have marked this patch as RFC to avoid misunderstanding.
Jan Beulich Jan. 27, 2021, 10:15 a.m. UTC | #4
On 27.01.2021 10:54, Oleksandr wrote:
> 
> On 26.01.21 11:15, Jan Beulich wrote:
> 
> Hi Jan
> 
>> On 25.01.2021 20:08, Oleksandr Tyshchenko wrote:
>>> --- a/xen/include/xen/dm.h
>>> +++ b/xen/include/xen/dm.h
>>> @@ -19,6 +19,8 @@
>>>   
>>>   #include <xen/sched.h>
>>>   
>>> +#include <public/hvm/dm_op.h>
>>> +
>>>   struct dmop_args {
>>>       domid_t domid;
>>>       unsigned int nr_bufs;
>> How come this becomes necessary at this point in the series, when
>> nothing else in this header changes, and nothing changes in the
>> public headers at all? Is it perhaps a .c file that needs the
>> #include instead? Headers shouldn't pull in other headers without
>> clear need - as indicated in reply to a prior version, we have
>> way too many bad examples (causing headaches in certain cases),
>> and we'd like to avoid gaining more.
> 
> Yes, I understand this and completely agree. I remember last discussion 
> on that, this is not forgotten. The only reason I made this (non 
> entirely correct) change is to make
> series compilable on Arm with IOREQ support enabled. If I considered 
> this change as a correct one I would make it from the very beginning (in 
> patch #9 which adds this common header)...
> I added remark to draw reviewer's attention on the fact that I got stuck 
> with resolving that, what I did wrong and how it should be done 
> properly. The problem is that I didn't manage to make it properly.
> 
> Of course, I tried to include it directly by dm.c, but this didn't help 
> much without violating "alphabetical order" rule. Details here:
> https://lore.kernel.org/xen-devel/e0bc7f80-974e-945d-4605-173bd05302af@gmail.com/
> 
> I would appreciate any input on that.

I'll try to reply there.

Jan
Julien Grall Jan. 27, 2021, 5:01 p.m. UTC | #5
Hi Jan,

On 26/01/2021 09:15, Jan Beulich wrote:
> On 25.01.2021 20:08, Oleksandr Tyshchenko wrote:
>> --- a/xen/include/xen/dm.h
>> +++ b/xen/include/xen/dm.h
>> @@ -19,6 +19,8 @@
>>   
>>   #include <xen/sched.h>
>>   
>> +#include <public/hvm/dm_op.h>
>> +
>>   struct dmop_args {
>>       domid_t domid;
>>       unsigned int nr_bufs;
> 
> How come this becomes necessary at this point in the series, when
> nothing else in this header changes, and nothing changes in the
> public headers at all? Is it perhaps a .c file that needs the
> #include instead? Headers shouldn't pull in other headers without
> clear need - as indicated in reply to a prior version, we have
> way too many bad examples (causing headaches in certain cases),
> and we'd like to avoid gaining more. (Oh, I notice you actually
> have a post-commit-message remark about this, but then this
> patch should be marked RFC until the issue was resolved.)

dm.h contains the following:

struct dmop_args {
     domid_t domid;
     unsigned int nr_bufs;
     /* Reserve enough buf elements for all current hypercalls. */
     struct xen_dm_op_buf buf[2];
};

The struct xen_dm_op_buf is defined public/hvm/dm_op.h. On x86, this 
will be indirectly included via:
    ->  xen/sched.h
     ->  xen/domain.h
      ->  asm/domain.h
       ->  asm/hvm/domain.h
        ->  public/hvm/dm_op.h

It looks like this was include from asm/hvm/domain.h because, before 
this series, NR_IO_RANGE_TYPES made use of a DMOP definition.

With this series, the type is now moved in ioreq.h. So I think we may be 
able to drop the include from asm/hvm/domain.h (this would avoid to 
include it everywhere...).

I also think we want to include public/hvm/dm_op.h in xen/dm.h because 
it is included directly by *.c.

Cheers,
Jan Beulich Jan. 27, 2021, 5:04 p.m. UTC | #6
On 27.01.2021 18:01, Julien Grall wrote:
> Hi Jan,
> 
> On 26/01/2021 09:15, Jan Beulich wrote:
>> On 25.01.2021 20:08, Oleksandr Tyshchenko wrote:
>>> --- a/xen/include/xen/dm.h
>>> +++ b/xen/include/xen/dm.h
>>> @@ -19,6 +19,8 @@
>>>   
>>>   #include <xen/sched.h>
>>>   
>>> +#include <public/hvm/dm_op.h>
>>> +
>>>   struct dmop_args {
>>>       domid_t domid;
>>>       unsigned int nr_bufs;
>>
>> How come this becomes necessary at this point in the series, when
>> nothing else in this header changes, and nothing changes in the
>> public headers at all? Is it perhaps a .c file that needs the
>> #include instead? Headers shouldn't pull in other headers without
>> clear need - as indicated in reply to a prior version, we have
>> way too many bad examples (causing headaches in certain cases),
>> and we'd like to avoid gaining more. (Oh, I notice you actually
>> have a post-commit-message remark about this, but then this
>> patch should be marked RFC until the issue was resolved.)
> 
> dm.h contains the following:
> 
> struct dmop_args {
>      domid_t domid;
>      unsigned int nr_bufs;
>      /* Reserve enough buf elements for all current hypercalls. */
>      struct xen_dm_op_buf buf[2];
> };

Which means the public header should be included, yes, but
right away at the point this dependency appears, not at a
random point later in the series.

Jan

> The struct xen_dm_op_buf is defined public/hvm/dm_op.h. On x86, this 
> will be indirectly included via:
>     ->  xen/sched.h
>      ->  xen/domain.h
>       ->  asm/domain.h
>        ->  asm/hvm/domain.h
>         ->  public/hvm/dm_op.h
> 
> It looks like this was include from asm/hvm/domain.h because, before 
> this series, NR_IO_RANGE_TYPES made use of a DMOP definition.
> 
> With this series, the type is now moved in ioreq.h. So I think we may be 
> able to drop the include from asm/hvm/domain.h (this would avoid to 
> include it everywhere...).
> 
> I also think we want to include public/hvm/dm_op.h in xen/dm.h because 
> it is included directly by *.c.
> 
> Cheers,
>
Julien Grall Jan. 27, 2021, 6:33 p.m. UTC | #7
Hi,

On 25/01/2021 19:08, Oleksandr Tyshchenko wrote:
> +enum io_state try_fwd_ioserv(struct cpu_user_regs *regs,
> +                             struct vcpu *v, mmio_info_t *info)
> +{
> +    struct vcpu_io *vio = &v->io;
> +    ioreq_t p = {
> +        .type = IOREQ_TYPE_COPY,
> +        .addr = info->gpa,
> +        .size = 1 << info->dabt.size,
> +        .count = 1,
> +        .dir = !info->dabt.write,
> +        /*
> +         * On x86, df is used by 'rep' instruction to tell the direction
> +         * to iterate (forward or backward).
> +         * On Arm, all the accesses to MMIO region will do a single
> +         * memory access. So for now, we can safely always set to 0.
> +         */
> +        .df = 0,
> +        .data = get_user_reg(regs, info->dabt.reg),
> +        .state = STATE_IOREQ_READY,
> +    };
> +    struct ioreq_server *s = NULL;
> +    enum io_state rc;
> +
> +    switch ( vio->req.state )
> +    {
> +    case STATE_IOREQ_NONE:
> +        break;
> +
> +    default:
> +        gdprintk(XENLOG_ERR, "wrong state %u\n", vio->req.state);
> +        return IO_ABORT;
> +    }

NIT: Given there is only one case, I think this can become a:

if ( vio->req.state != STATE_IOREQ_NONE )
{
   gdprintk(...);
   return IO_ABORT;
}

It is up to you whether you want to fix it now, later, or never :).

Aside the discussion about dm.h, the rest of the code looks good to me. 
It is nice to see the arch part of IOREQ is small :).

Cheers,
Oleksandr Tyshchenko Jan. 27, 2021, 7:20 p.m. UTC | #8
On 27.01.21 20:33, Julien Grall wrote:

Hi Julien

> Hi,
>
> On 25/01/2021 19:08, Oleksandr Tyshchenko wrote:
>> +enum io_state try_fwd_ioserv(struct cpu_user_regs *regs,
>> +                             struct vcpu *v, mmio_info_t *info)
>> +{
>> +    struct vcpu_io *vio = &v->io;
>> +    ioreq_t p = {
>> +        .type = IOREQ_TYPE_COPY,
>> +        .addr = info->gpa,
>> +        .size = 1 << info->dabt.size,
>> +        .count = 1,
>> +        .dir = !info->dabt.write,
>> +        /*
>> +         * On x86, df is used by 'rep' instruction to tell the 
>> direction
>> +         * to iterate (forward or backward).
>> +         * On Arm, all the accesses to MMIO region will do a single
>> +         * memory access. So for now, we can safely always set to 0.
>> +         */
>> +        .df = 0,
>> +        .data = get_user_reg(regs, info->dabt.reg),
>> +        .state = STATE_IOREQ_READY,
>> +    };
>> +    struct ioreq_server *s = NULL;
>> +    enum io_state rc;
>> +
>> +    switch ( vio->req.state )
>> +    {
>> +    case STATE_IOREQ_NONE:
>> +        break;
>> +
>> +    default:
>> +        gdprintk(XENLOG_ERR, "wrong state %u\n", vio->req.state);
>> +        return IO_ABORT;
>> +    }
>
> NIT: Given there is only one case, I think this can become a:
>
> if ( vio->req.state != STATE_IOREQ_NONE )
> {
>   gdprintk(...);
>   return IO_ABORT;
> }
>
> It is up to you whether you want to fix it now, later, or never :).

V6 is planned, so will fix)


>
> Aside the discussion about dm.h, the rest of the code looks good to 
> me. It is nice to see the arch part of IOREQ is small :).

I do agree, it is much smaller than it was for RFC series)

Yes, I will add required changes to dm.h in the patch which introduces 
that header, but ...


 >>> So I think we may be able to drop the include from asm/hvm/domain.h 
(this would avoid to include it everywhere...).

I have tried that, but other CUs use definitions from 
public/hvm/dm_op.h, for example:

p2m-pt.c: In function 'p2m_type_to_flags':
p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' undeclared 
(first use in this function)
          if ( p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
                                  ^
So, I would prefer to leave it as is, please let me know if you think 
otherwise.


>
> Cheers,
>
Julien Grall Jan. 28, 2021, 9:40 a.m. UTC | #9
Hi Oleksandr,

On 27/01/2021 19:20, Oleksandr wrote:
  >  >>> So I think we may be able to drop the include from 
asm/hvm/domain.h
> (this would avoid to include it everywhere...).
> 
> I have tried that, but other CUs use definitions from 
> public/hvm/dm_op.h, for example:
> 
> p2m-pt.c: In function 'p2m_type_to_flags':
> p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' undeclared 
> (first use in this function)
>           if ( p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
>                                   ^
> So, I would prefer to leave it as is, please let me know if you think 
> otherwise.

AFAICT, there is only 2 places (p2m-pt.c and p2m-ept.c) that requires 
<public/hvm/dm_op.h> but doesn't directly include it. Folding the diff 
below in patch #4 should do the job:

diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index 975ab403f235..23d411f01d2f 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -17,6 +17,7 @@

  #include <xen/domain_page.h>
  #include <xen/sched.h>
+#include <public/hvm/dm_op.h>
  #include <asm/altp2m.h>
  #include <asm/current.h>
  #include <asm/paging.h>
diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
index c43d5d0413a1..f2afcf49a368 100644
--- a/xen/arch/x86/mm/p2m-pt.c
+++ b/xen/arch/x86/mm/p2m-pt.c
@@ -27,6 +27,7 @@
  #include <xen/vm_event.h>
  #include <xen/event.h>
  #include <xen/trace.h>
+#include <public/hvm/dm_op.h>
  #include <public/vm_event.h>
  #include <asm/altp2m.h>
  #include <asm/domain.h>
diff --git a/xen/include/asm-x86/hvm/domain.h 
b/xen/include/asm-x86/hvm/domain.h
index 3b36c2f41fa1..f26c1a2e2d5f 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -28,8 +28,6 @@
  #include <asm/hvm/vmx/vmcs.h>
  #include <asm/hvm/svm/vmcb.h>

-#include <public/hvm/dm_op.h>
-
  #ifdef CONFIG_MEM_SHARING
  struct mem_sharing_domain
  {

You would then need to move the include of <public/hvm/dm_op.h> in 
<xen/dm.h> from this patch to patch #9.

Cheers,
Oleksandr Tyshchenko Jan. 28, 2021, 11:33 a.m. UTC | #10
On 28.01.21 11:40, Julien Grall wrote:

Hi Julien

> Hi Oleksandr,
>
> On 27/01/2021 19:20, Oleksandr wrote:
>  >  >>> So I think we may be able to drop the include from 
> asm/hvm/domain.h
>> (this would avoid to include it everywhere...).
>>
>> I have tried that, but other CUs use definitions from 
>> public/hvm/dm_op.h, for example:
>>
>> p2m-pt.c: In function 'p2m_type_to_flags':
>> p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' undeclared 
>> (first use in this function)
>>           if ( p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
>>                                   ^
>> So, I would prefer to leave it as is, please let me know if you think 
>> otherwise.
>
> AFAICT, there is only 2 places (p2m-pt.c and p2m-ept.c) that requires 
> <public/hvm/dm_op.h> but doesn't directly include it. Folding the diff 
> below in patch #4 should do the job:

ok, will do


>
> diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
> index 975ab403f235..23d411f01d2f 100644
> --- a/xen/arch/x86/mm/p2m-ept.c
> +++ b/xen/arch/x86/mm/p2m-ept.c
> @@ -17,6 +17,7 @@
>
>  #include <xen/domain_page.h>
>  #include <xen/sched.h>
> +#include <public/hvm/dm_op.h>
>  #include <asm/altp2m.h>
>  #include <asm/current.h>
>  #include <asm/paging.h>
> diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
> index c43d5d0413a1..f2afcf49a368 100644
> --- a/xen/arch/x86/mm/p2m-pt.c
> +++ b/xen/arch/x86/mm/p2m-pt.c
> @@ -27,6 +27,7 @@
>  #include <xen/vm_event.h>
>  #include <xen/event.h>
>  #include <xen/trace.h>
> +#include <public/hvm/dm_op.h>
>  #include <public/vm_event.h>
>  #include <asm/altp2m.h>
>  #include <asm/domain.h>
> diff --git a/xen/include/asm-x86/hvm/domain.h 
> b/xen/include/asm-x86/hvm/domain.h
> index 3b36c2f41fa1..f26c1a2e2d5f 100644
> --- a/xen/include/asm-x86/hvm/domain.h
> +++ b/xen/include/asm-x86/hvm/domain.h
> @@ -28,8 +28,6 @@
>  #include <asm/hvm/vmx/vmcs.h>
>  #include <asm/hvm/svm/vmcb.h>
>
> -#include <public/hvm/dm_op.h>
> -
>  #ifdef CONFIG_MEM_SHARING
>  struct mem_sharing_domain
>  {
>
> You would then need to move the include of <public/hvm/dm_op.h> in 
> <xen/dm.h> from this patch to patch #9.

yes, sure
Oleksandr Tyshchenko Jan. 28, 2021, 1:39 p.m. UTC | #11
On 28.01.21 13:33, Oleksandr wrote:

Hi Julien

>
> On 28.01.21 11:40, Julien Grall wrote:
>
> Hi Julien
>
>> Hi Oleksandr,
>>
>> On 27/01/2021 19:20, Oleksandr wrote:
>>  >  >>> So I think we may be able to drop the include from 
>> asm/hvm/domain.h
>>> (this would avoid to include it everywhere...).
>>>
>>> I have tried that, but other CUs use definitions from 
>>> public/hvm/dm_op.h, for example:
>>>
>>> p2m-pt.c: In function 'p2m_type_to_flags':
>>> p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' undeclared 
>>> (first use in this function)
>>>           if ( p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
>>>                                   ^
>>> So, I would prefer to leave it as is, please let me know if you 
>>> think otherwise.
>>
>> AFAICT, there is only 2 places (p2m-pt.c and p2m-ept.c) that requires 
>> <public/hvm/dm_op.h> but doesn't directly include it. Folding the 
>> diff below in patch #4 should do the job:
>
> ok, will do


Just to clarify, you mentioned about patch #4, but shouldn't we make 
these changes in patch #9 which actually tries to sort dm related stuff?


>
>
>>
>> diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
>> index 975ab403f235..23d411f01d2f 100644
>> --- a/xen/arch/x86/mm/p2m-ept.c
>> +++ b/xen/arch/x86/mm/p2m-ept.c
>> @@ -17,6 +17,7 @@
>>
>>  #include <xen/domain_page.h>
>>  #include <xen/sched.h>
>> +#include <public/hvm/dm_op.h>
>>  #include <asm/altp2m.h>
>>  #include <asm/current.h>
>>  #include <asm/paging.h>
>> diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
>> index c43d5d0413a1..f2afcf49a368 100644
>> --- a/xen/arch/x86/mm/p2m-pt.c
>> +++ b/xen/arch/x86/mm/p2m-pt.c
>> @@ -27,6 +27,7 @@
>>  #include <xen/vm_event.h>
>>  #include <xen/event.h>
>>  #include <xen/trace.h>
>> +#include <public/hvm/dm_op.h>
>>  #include <public/vm_event.h>
>>  #include <asm/altp2m.h>
>>  #include <asm/domain.h>
>> diff --git a/xen/include/asm-x86/hvm/domain.h 
>> b/xen/include/asm-x86/hvm/domain.h
>> index 3b36c2f41fa1..f26c1a2e2d5f 100644
>> --- a/xen/include/asm-x86/hvm/domain.h
>> +++ b/xen/include/asm-x86/hvm/domain.h
>> @@ -28,8 +28,6 @@
>>  #include <asm/hvm/vmx/vmcs.h>
>>  #include <asm/hvm/svm/vmcb.h>
>>
>> -#include <public/hvm/dm_op.h>
>> -
>>  #ifdef CONFIG_MEM_SHARING
>>  struct mem_sharing_domain
>>  {
>>
>> You would then need to move the include of <public/hvm/dm_op.h> in 
>> <xen/dm.h> from this patch to patch #9.
>
> yes, sure
>
>
Oleksandr Tyshchenko Jan. 28, 2021, 2:29 p.m. UTC | #12
Hi Julien


On 28.01.21 15:39, Oleksandr wrote:
>
> On 28.01.21 13:33, Oleksandr wrote:
>
> Hi Julien
>
>>
>> On 28.01.21 11:40, Julien Grall wrote:
>>
>> Hi Julien
>>
>>> Hi Oleksandr,
>>>
>>> On 27/01/2021 19:20, Oleksandr wrote:
>>>  >  >>> So I think we may be able to drop the include from 
>>> asm/hvm/domain.h
>>>> (this would avoid to include it everywhere...).
>>>>
>>>> I have tried that, but other CUs use definitions from 
>>>> public/hvm/dm_op.h, for example:
>>>>
>>>> p2m-pt.c: In function 'p2m_type_to_flags':
>>>> p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' undeclared 
>>>> (first use in this function)
>>>>           if ( p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
>>>>                                   ^
>>>> So, I would prefer to leave it as is, please let me know if you 
>>>> think otherwise.
>>>
>>> AFAICT, there is only 2 places (p2m-pt.c and p2m-ept.c) that 
>>> requires <public/hvm/dm_op.h> but doesn't directly include it. 
>>> Folding the diff below in patch #4 should do the job:
>>
>> ok, will do
>
>
> Just to clarify, you mentioned about patch #4, but shouldn't we make 
> these changes in patch #9 which actually tries to sort dm related stuff?

or a least in patch #8 which moves the stuff from asm-x86/hvm/domain.h 
to xen/ioreq.h (including the user of XEN_DMOP_IO_RANGE_PCI),

what do you think?


As for proposed changes, can confirm they work.


>
>
>>
>>
>>>
>>> diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
>>> index 975ab403f235..23d411f01d2f 100644
>>> --- a/xen/arch/x86/mm/p2m-ept.c
>>> +++ b/xen/arch/x86/mm/p2m-ept.c
>>> @@ -17,6 +17,7 @@
>>>
>>>  #include <xen/domain_page.h>
>>>  #include <xen/sched.h>
>>> +#include <public/hvm/dm_op.h>
>>>  #include <asm/altp2m.h>
>>>  #include <asm/current.h>
>>>  #include <asm/paging.h>
>>> diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
>>> index c43d5d0413a1..f2afcf49a368 100644
>>> --- a/xen/arch/x86/mm/p2m-pt.c
>>> +++ b/xen/arch/x86/mm/p2m-pt.c
>>> @@ -27,6 +27,7 @@
>>>  #include <xen/vm_event.h>
>>>  #include <xen/event.h>
>>>  #include <xen/trace.h>
>>> +#include <public/hvm/dm_op.h>
>>>  #include <public/vm_event.h>
>>>  #include <asm/altp2m.h>
>>>  #include <asm/domain.h>
>>> diff --git a/xen/include/asm-x86/hvm/domain.h 
>>> b/xen/include/asm-x86/hvm/domain.h
>>> index 3b36c2f41fa1..f26c1a2e2d5f 100644
>>> --- a/xen/include/asm-x86/hvm/domain.h
>>> +++ b/xen/include/asm-x86/hvm/domain.h
>>> @@ -28,8 +28,6 @@
>>>  #include <asm/hvm/vmx/vmcs.h>
>>>  #include <asm/hvm/svm/vmcb.h>
>>>
>>> -#include <public/hvm/dm_op.h>
>>> -
>>>  #ifdef CONFIG_MEM_SHARING
>>>  struct mem_sharing_domain
>>>  {
>>>
>>> You would then need to move the include of <public/hvm/dm_op.h> in 
>>> <xen/dm.h> from this patch to patch #9.
>>
>> yes, sure
>>
>>
Julien Grall Jan. 28, 2021, 2:41 p.m. UTC | #13
On 28/01/2021 14:29, Oleksandr wrote:
> 
> Hi Julien
> 
> 
> On 28.01.21 15:39, Oleksandr wrote:
>>
>> On 28.01.21 13:33, Oleksandr wrote:
>>
>> Hi Julien
>>
>>>
>>> On 28.01.21 11:40, Julien Grall wrote:
>>>
>>> Hi Julien
>>>
>>>> Hi Oleksandr,
>>>>
>>>> On 27/01/2021 19:20, Oleksandr wrote:
>>>>  >  >>> So I think we may be able to drop the include from 
>>>> asm/hvm/domain.h
>>>>> (this would avoid to include it everywhere...).
>>>>>
>>>>> I have tried that, but other CUs use definitions from 
>>>>> public/hvm/dm_op.h, for example:
>>>>>
>>>>> p2m-pt.c: In function 'p2m_type_to_flags':
>>>>> p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' undeclared 
>>>>> (first use in this function)
>>>>>           if ( p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
>>>>>                                   ^
>>>>> So, I would prefer to leave it as is, please let me know if you 
>>>>> think otherwise.
>>>>
>>>> AFAICT, there is only 2 places (p2m-pt.c and p2m-ept.c) that 
>>>> requires <public/hvm/dm_op.h> but doesn't directly include it. 
>>>> Folding the diff below in patch #4 should do the job:
>>>
>>> ok, will do
>>
>>
>> Just to clarify, you mentioned about patch #4, but shouldn't we make 
>> these changes in patch #9 which actually tries to sort dm related stuff?
> 
> or a least in patch #8 which moves the stuff from asm-x86/hvm/domain.h 
> to xen/ioreq.h (including the user of XEN_DMOP_IO_RANGE_PCI),

I looked at the header asm-x86/hvm/domain.h after applying patch #4, 
there is nothing requiring DMOP from there.

I tried to build it with this series applied up to patch #4 + my diff. 
It does build without any issue.

Cheers,
Oleksandr Tyshchenko Jan. 28, 2021, 2:52 p.m. UTC | #14
On 28.01.21 16:41, Julien Grall wrote:

Hi Julien

>
>
> On 28/01/2021 14:29, Oleksandr wrote:
>>
>> Hi Julien
>>
>>
>> On 28.01.21 15:39, Oleksandr wrote:
>>>
>>> On 28.01.21 13:33, Oleksandr wrote:
>>>
>>> Hi Julien
>>>
>>>>
>>>> On 28.01.21 11:40, Julien Grall wrote:
>>>>
>>>> Hi Julien
>>>>
>>>>> Hi Oleksandr,
>>>>>
>>>>> On 27/01/2021 19:20, Oleksandr wrote:
>>>>>  >  >>> So I think we may be able to drop the include from 
>>>>> asm/hvm/domain.h
>>>>>> (this would avoid to include it everywhere...).
>>>>>>
>>>>>> I have tried that, but other CUs use definitions from 
>>>>>> public/hvm/dm_op.h, for example:
>>>>>>
>>>>>> p2m-pt.c: In function 'p2m_type_to_flags':
>>>>>> p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' 
>>>>>> undeclared (first use in this function)
>>>>>>           if ( p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
>>>>>>                                   ^
>>>>>> So, I would prefer to leave it as is, please let me know if you 
>>>>>> think otherwise.
>>>>>
>>>>> AFAICT, there is only 2 places (p2m-pt.c and p2m-ept.c) that 
>>>>> requires <public/hvm/dm_op.h> but doesn't directly include it. 
>>>>> Folding the diff below in patch #4 should do the job:
>>>>
>>>> ok, will do
>>>
>>>
>>> Just to clarify, you mentioned about patch #4, but shouldn't we make 
>>> these changes in patch #9 which actually tries to sort dm related 
>>> stuff?
>>
>> or a least in patch #8 which moves the stuff from 
>> asm-x86/hvm/domain.h to xen/ioreq.h (including the user of 
>> XEN_DMOP_IO_RANGE_PCI),
>
> I looked at the header asm-x86/hvm/domain.h after applying patch #4, 
> there is nothing requiring DMOP from there.
>
> I tried to build it with this series applied up to patch #4 + my diff. 
> It does build without any issue.

Hmm, interesting. I might miss something, but I got an build issue if I 
split these changes with patch #4 and build the series up to this patch:

In file included from 
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/include/asm/domain.h:7:0,
                  from 
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/include/xen/domain.h:8,
                  from 
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/include/xen/sched.h:11,
                  from 
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/include/asm/paging.h:29,
                  from 
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/include/asm/guest_access.h:11,
                  from 
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/include/xen/guest_access.h:10,
                  from compat.c:1:
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/include/asm/hvm/domain.h:44:28: 
error: 'XEN_DMOP_IO_RANGE_PCI' undeclared here (not in a function)
  #define NR_IO_RANGE_TYPES (XEN_DMOP_IO_RANGE_PCI + 1)
                             ^
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/include/asm/hvm/domain.h:60:35: 
note: in expansion of macro 'NR_IO_RANGE_TYPES'
      struct rangeset        *range[NR_IO_RANGE_TYPES];
                                    ^
/media/b/build/build/tmp/work/x86_64-xt-linux/domd-image-weston/1.0-r0/repo/build/tmp/work/aarch64-poky-linux/xen/4.14.0+gitAUTOINC+2c6e5a8ceb-r0/git/xen/Rules.mk:189: 
recipe for target 'compat.o' failed
make[3]: *** [compat.o] Error 1


>
> Cheers,
>
Julien Grall Jan. 28, 2021, 3:08 p.m. UTC | #15
On 28/01/2021 14:52, Oleksandr wrote:
> 
> On 28.01.21 16:41, Julien Grall wrote:
>> On 28/01/2021 14:29, Oleksandr wrote:
>>> On 28.01.21 15:39, Oleksandr wrote:
>>>>
>>>> On 28.01.21 13:33, Oleksandr wrote:
>>>>
>>>> Hi Julien
>>>>
>>>>>
>>>>> On 28.01.21 11:40, Julien Grall wrote:
>>>>>
>>>>> Hi Julien
>>>>>
>>>>>> Hi Oleksandr,
>>>>>>
>>>>>> On 27/01/2021 19:20, Oleksandr wrote:
>>>>>>  >  >>> So I think we may be able to drop the include from 
>>>>>> asm/hvm/domain.h
>>>>>>> (this would avoid to include it everywhere...).
>>>>>>>
>>>>>>> I have tried that, but other CUs use definitions from 
>>>>>>> public/hvm/dm_op.h, for example:
>>>>>>>
>>>>>>> p2m-pt.c: In function 'p2m_type_to_flags':
>>>>>>> p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' 
>>>>>>> undeclared (first use in this function)
>>>>>>>           if ( p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
>>>>>>>                                   ^
>>>>>>> So, I would prefer to leave it as is, please let me know if you 
>>>>>>> think otherwise.
>>>>>>
>>>>>> AFAICT, there is only 2 places (p2m-pt.c and p2m-ept.c) that 
>>>>>> requires <public/hvm/dm_op.h> but doesn't directly include it. 
>>>>>> Folding the diff below in patch #4 should do the job:
>>>>>
>>>>> ok, will do
>>>>
>>>>
>>>> Just to clarify, you mentioned about patch #4, but shouldn't we make 
>>>> these changes in patch #9 which actually tries to sort dm related 
>>>> stuff?
>>>
>>> or a least in patch #8 which moves the stuff from 
>>> asm-x86/hvm/domain.h to xen/ioreq.h (including the user of 
>>> XEN_DMOP_IO_RANGE_PCI),
>>
>> I looked at the header asm-x86/hvm/domain.h after applying patch #4, 
>> there is nothing requiring DMOP from there.
>>
>> I tried to build it with this series applied up to patch #4 + my diff. 
>> It does build without any issue.
> 
> Hmm, interesting. I might miss something, but I got an build issue if I 
> split these changes with patch #4 and build the series up to this patch:

I think I looked and tried with the wrong commit. :( This was moved in 
patch #7 (xen/ioreq: Make x86's hvm_ioreq_(page/vcpu/server) structs 
common).

Sorry for the confusion.

Cheers,
Oleksandr Tyshchenko Jan. 28, 2021, 5:50 p.m. UTC | #16
On 28.01.21 17:08, Julien Grall wrote:

Hi Julien

>
>
> On 28/01/2021 14:52, Oleksandr wrote:
>>
>> On 28.01.21 16:41, Julien Grall wrote:
>>> On 28/01/2021 14:29, Oleksandr wrote:
>>>> On 28.01.21 15:39, Oleksandr wrote:
>>>>>
>>>>> On 28.01.21 13:33, Oleksandr wrote:
>>>>>
>>>>> Hi Julien
>>>>>
>>>>>>
>>>>>> On 28.01.21 11:40, Julien Grall wrote:
>>>>>>
>>>>>> Hi Julien
>>>>>>
>>>>>>> Hi Oleksandr,
>>>>>>>
>>>>>>> On 27/01/2021 19:20, Oleksandr wrote:
>>>>>>>  >  >>> So I think we may be able to drop the include from 
>>>>>>> asm/hvm/domain.h
>>>>>>>> (this would avoid to include it everywhere...).
>>>>>>>>
>>>>>>>> I have tried that, but other CUs use definitions from 
>>>>>>>> public/hvm/dm_op.h, for example:
>>>>>>>>
>>>>>>>> p2m-pt.c: In function 'p2m_type_to_flags':
>>>>>>>> p2m-pt.c:87:33: error: 'XEN_DMOP_IOREQ_MEM_ACCESS_WRITE' 
>>>>>>>> undeclared (first use in this function)
>>>>>>>>           if ( p2m->ioreq.flags & 
>>>>>>>> XEN_DMOP_IOREQ_MEM_ACCESS_WRITE )
>>>>>>>>                                   ^
>>>>>>>> So, I would prefer to leave it as is, please let me know if you 
>>>>>>>> think otherwise.
>>>>>>>
>>>>>>> AFAICT, there is only 2 places (p2m-pt.c and p2m-ept.c) that 
>>>>>>> requires <public/hvm/dm_op.h> but doesn't directly include it. 
>>>>>>> Folding the diff below in patch #4 should do the job:
>>>>>>
>>>>>> ok, will do
>>>>>
>>>>>
>>>>> Just to clarify, you mentioned about patch #4, but shouldn't we 
>>>>> make these changes in patch #9 which actually tries to sort dm 
>>>>> related stuff?
>>>>
>>>> or a least in patch #8 which moves the stuff from 
>>>> asm-x86/hvm/domain.h to xen/ioreq.h (including the user of 
>>>> XEN_DMOP_IO_RANGE_PCI),
>>>
>>> I looked at the header asm-x86/hvm/domain.h after applying patch #4, 
>>> there is nothing requiring DMOP from there.
>>>
>>> I tried to build it with this series applied up to patch #4 + my 
>>> diff. It does build without any issue.
>>
>> Hmm, interesting. I might miss something, but I got an build issue if 
>> I split these changes with patch #4 and build the series up to this 
>> patch:
>
> I think I looked and tried with the wrong commit. :( This was moved in 
> patch #7 (xen/ioreq: Make x86's hvm_ioreq_(page/vcpu/server) structs 
> common).
>
> Sorry for the confusion.

No problem.


So I will merge these changes with patch #7 (that already has all 
required approvals) with the following justification:

Also there is no need to include public/hvm/dm_op.h by
asm-x86/hvm/domain.h anymore since #define NR_IO_RANGE_TYPES
(which uses XEN_DMOP_IO_RANGE_PCI) gets moved to another location.
Instead include it by 2 places (p2m-pt.c and p2m-ept.c) which
require that header, but don't directly include it so far.


If there are any objections please let me know.
diff mbox series

Patch

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 512ffdd..16e6523 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -13,6 +13,7 @@  obj-y += cpuerrata.o
 obj-y += cpufeature.o
 obj-y += decode.o
 obj-y += device.o
+obj-$(CONFIG_IOREQ_SERVER) += dm.o
 obj-y += domain.o
 obj-y += domain_build.init.o
 obj-y += domctl.o
@@ -27,6 +28,7 @@  obj-y += guest_atomics.o
 obj-y += guest_walk.o
 obj-y += hvm.o
 obj-y += io.o
+obj-$(CONFIG_IOREQ_SERVER) += ioreq.o
 obj-y += irq.o
 obj-y += kernel.init.o
 obj-$(CONFIG_LIVEPATCH) += livepatch.o
diff --git a/xen/arch/arm/dm.c b/xen/arch/arm/dm.c
new file mode 100644
index 0000000..f254ed7
--- /dev/null
+++ b/xen/arch/arm/dm.c
@@ -0,0 +1,97 @@ 
+/*
+ * Copyright (c) 2019 Arm ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/dm.h>
+#include <xen/guest_access.h>
+#include <xen/hypercall.h>
+#include <xen/ioreq.h>
+#include <xen/nospec.h>
+
+int dm_op(const struct dmop_args *op_args)
+{
+    struct domain *d;
+    struct xen_dm_op op;
+    bool const_op = true;
+    long rc;
+    size_t offset;
+
+    static const uint8_t op_size[] = {
+        [XEN_DMOP_create_ioreq_server]              = sizeof(struct xen_dm_op_create_ioreq_server),
+        [XEN_DMOP_get_ioreq_server_info]            = sizeof(struct xen_dm_op_get_ioreq_server_info),
+        [XEN_DMOP_map_io_range_to_ioreq_server]     = sizeof(struct xen_dm_op_ioreq_server_range),
+        [XEN_DMOP_unmap_io_range_from_ioreq_server] = sizeof(struct xen_dm_op_ioreq_server_range),
+        [XEN_DMOP_set_ioreq_server_state]           = sizeof(struct xen_dm_op_set_ioreq_server_state),
+        [XEN_DMOP_destroy_ioreq_server]             = sizeof(struct xen_dm_op_destroy_ioreq_server),
+    };
+
+    rc = rcu_lock_remote_domain_by_id(op_args->domid, &d);
+    if ( rc )
+        return rc;
+
+    rc = xsm_dm_op(XSM_DM_PRIV, d);
+    if ( rc )
+        goto out;
+
+    offset = offsetof(struct xen_dm_op, u);
+
+    rc = -EFAULT;
+    if ( op_args->buf[0].size < offset )
+        goto out;
+
+    if ( copy_from_guest_offset((void *)&op, op_args->buf[0].h, 0, offset) )
+        goto out;
+
+    if ( op.op >= ARRAY_SIZE(op_size) )
+    {
+        rc = -EOPNOTSUPP;
+        goto out;
+    }
+
+    op.op = array_index_nospec(op.op, ARRAY_SIZE(op_size));
+
+    if ( op_args->buf[0].size < offset + op_size[op.op] )
+        goto out;
+
+    if ( copy_from_guest_offset((void *)&op.u, op_args->buf[0].h, offset,
+                                op_size[op.op]) )
+        goto out;
+
+    rc = -EINVAL;
+    if ( op.pad )
+        goto out;
+
+    rc = ioreq_server_dm_op(&op, d, &const_op);
+
+    if ( (!rc || rc == -ERESTART) &&
+         !const_op && copy_to_guest_offset(op_args->buf[0].h, offset,
+                                           (void *)&op.u, op_size[op.op]) )
+        rc = -EFAULT;
+
+ out:
+    rcu_unlock_domain(d);
+
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 18cafcd..bdd3d3e 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -15,6 +15,7 @@ 
 #include <xen/guest_access.h>
 #include <xen/hypercall.h>
 #include <xen/init.h>
+#include <xen/ioreq.h>
 #include <xen/lib.h>
 #include <xen/livepatch.h>
 #include <xen/sched.h>
@@ -696,6 +697,10 @@  int arch_domain_create(struct domain *d,
 
     ASSERT(config != NULL);
 
+#ifdef CONFIG_IOREQ_SERVER
+    ioreq_domain_init(d);
+#endif
+
     /* p2m_init relies on some value initialized by the IOMMU subsystem */
     if ( (rc = iommu_domain_init(d, config->iommu_opts)) != 0 )
         goto fail;
@@ -1009,6 +1014,10 @@  int domain_relinquish_resources(struct domain *d)
          */
         domain_vpl011_deinit(d);
 
+#ifdef CONFIG_IOREQ_SERVER
+        ioreq_server_destroy_all(d);
+#endif
+
     PROGRESS(tee):
         ret = tee_relinquish_resources(d);
         if (ret )
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index ae7ef96..7ac0303 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -16,12 +16,14 @@ 
  * GNU General Public License for more details.
  */
 
+#include <xen/ioreq.h>
 #include <xen/lib.h>
 #include <xen/spinlock.h>
 #include <xen/sched.h>
 #include <xen/sort.h>
 #include <asm/cpuerrata.h>
 #include <asm/current.h>
+#include <asm/ioreq.h>
 #include <asm/mmio.h>
 
 #include "decode.h"
@@ -123,7 +125,15 @@  enum io_state try_handle_mmio(struct cpu_user_regs *regs,
 
     handler = find_mmio_handler(v->domain, info.gpa);
     if ( !handler )
-        return IO_UNHANDLED;
+    {
+        int rc;
+
+        rc = try_fwd_ioserv(regs, v, &info);
+        if ( rc == IO_HANDLED )
+            return handle_ioserv(regs, v);
+
+        return rc;
+    }
 
     /* All the instructions used on emulated MMIO region should be valid */
     if ( !dabt.valid )
diff --git a/xen/arch/arm/ioreq.c b/xen/arch/arm/ioreq.c
new file mode 100644
index 0000000..ffeeb0b
--- /dev/null
+++ b/xen/arch/arm/ioreq.c
@@ -0,0 +1,215 @@ 
+/*
+ * arm/ioreq.c: hardware virtual machine I/O emulation
+ *
+ * Copyright (c) 2019 Arm ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/domain.h>
+#include <xen/ioreq.h>
+
+#include <asm/traps.h>
+
+#include <public/hvm/ioreq.h>
+
+enum io_state handle_ioserv(struct cpu_user_regs *regs, struct vcpu *v)
+{
+    const union hsr hsr = { .bits = regs->hsr };
+    const struct hsr_dabt dabt = hsr.dabt;
+    /* Code is similar to handle_read */
+    uint8_t size = (1 << dabt.size) * 8;
+    register_t r = v->io.req.data;
+
+    /* We are done with the IO */
+    v->io.req.state = STATE_IOREQ_NONE;
+
+    if ( dabt.write )
+        return IO_HANDLED;
+
+    /*
+     * Sign extend if required.
+     * Note that we expect the read handler to have zeroed the bits
+     * outside the requested access size.
+     */
+    if ( dabt.sign && (r & (1UL << (size - 1))) )
+    {
+        /*
+         * We are relying on register_t using the same as
+         * an unsigned long in order to keep the 32-bit assembly
+         * code smaller.
+         */
+        BUILD_BUG_ON(sizeof(register_t) != sizeof(unsigned long));
+        r |= (~0UL) << size;
+    }
+
+    set_user_reg(regs, dabt.reg, r);
+
+    return IO_HANDLED;
+}
+
+enum io_state try_fwd_ioserv(struct cpu_user_regs *regs,
+                             struct vcpu *v, mmio_info_t *info)
+{
+    struct vcpu_io *vio = &v->io;
+    ioreq_t p = {
+        .type = IOREQ_TYPE_COPY,
+        .addr = info->gpa,
+        .size = 1 << info->dabt.size,
+        .count = 1,
+        .dir = !info->dabt.write,
+        /*
+         * On x86, df is used by 'rep' instruction to tell the direction
+         * to iterate (forward or backward).
+         * On Arm, all the accesses to MMIO region will do a single
+         * memory access. So for now, we can safely always set to 0.
+         */
+        .df = 0,
+        .data = get_user_reg(regs, info->dabt.reg),
+        .state = STATE_IOREQ_READY,
+    };
+    struct ioreq_server *s = NULL;
+    enum io_state rc;
+
+    switch ( vio->req.state )
+    {
+    case STATE_IOREQ_NONE:
+        break;
+
+    default:
+        gdprintk(XENLOG_ERR, "wrong state %u\n", vio->req.state);
+        return IO_ABORT;
+    }
+
+    s = ioreq_server_select(v->domain, &p);
+    if ( !s )
+        return IO_UNHANDLED;
+
+    if ( !info->dabt.valid )
+        return IO_ABORT;
+
+    vio->req = p;
+
+    rc = ioreq_send(s, &p, 0);
+    if ( rc != IO_RETRY || v->domain->is_shutting_down )
+        vio->req.state = STATE_IOREQ_NONE;
+    else if ( !ioreq_needs_completion(&vio->req) )
+        rc = IO_HANDLED;
+    else
+        vio->completion = VIO_mmio_completion;
+
+    return rc;
+}
+
+bool arch_ioreq_complete_mmio(void)
+{
+    struct vcpu *v = current;
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
+    const union hsr hsr = { .bits = regs->hsr };
+
+    if ( v->io.req.state != STATE_IORESP_READY )
+    {
+        ASSERT_UNREACHABLE();
+        return false;
+    }
+
+    if ( handle_ioserv(regs, v) == IO_HANDLED )
+    {
+        advance_pc(regs, hsr);
+        return true;
+    }
+
+    return false;
+}
+
+bool arch_vcpu_ioreq_completion(enum vio_completion completion)
+{
+    ASSERT_UNREACHABLE();
+    return true;
+}
+
+/*
+ * The "legacy" mechanism of mapping magic pages for the IOREQ servers
+ * is x86 specific, so the following hooks don't need to be implemented on Arm:
+ * - arch_ioreq_server_map_pages
+ * - arch_ioreq_server_unmap_pages
+ * - arch_ioreq_server_enable
+ * - arch_ioreq_server_disable
+ */
+int arch_ioreq_server_map_pages(struct ioreq_server *s)
+{
+    return -EOPNOTSUPP;
+}
+
+void arch_ioreq_server_unmap_pages(struct ioreq_server *s)
+{
+}
+
+void arch_ioreq_server_enable(struct ioreq_server *s)
+{
+}
+
+void arch_ioreq_server_disable(struct ioreq_server *s)
+{
+}
+
+void arch_ioreq_server_destroy(struct ioreq_server *s)
+{
+}
+
+int arch_ioreq_server_map_mem_type(struct domain *d,
+                                   struct ioreq_server *s,
+                                   uint32_t flags)
+{
+    return -EOPNOTSUPP;
+}
+
+void arch_ioreq_server_map_mem_type_completed(struct domain *d,
+                                              struct ioreq_server *s,
+                                              uint32_t flags)
+{
+}
+
+bool arch_ioreq_server_destroy_all(struct domain *d)
+{
+    return true;
+}
+
+bool arch_ioreq_server_get_type_addr(const struct domain *d,
+                                     const ioreq_t *p,
+                                     uint8_t *type,
+                                     uint64_t *addr)
+{
+    if ( p->type != IOREQ_TYPE_COPY && p->type != IOREQ_TYPE_PIO )
+        return false;
+
+    *type = (p->type == IOREQ_TYPE_PIO) ?
+             XEN_DMOP_IO_RANGE_PORT : XEN_DMOP_IO_RANGE_MEMORY;
+    *addr = p->addr;
+
+    return true;
+}
+
+void arch_ioreq_domain_init(struct domain *d)
+{
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 1af1bb9..b0cd8f9 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1385,6 +1385,9 @@  static arm_hypercall_t arm_hypercall_table[] = {
 #ifdef CONFIG_HYPFS
     HYPERCALL(hypfs_op, 5),
 #endif
+#ifdef CONFIG_IOREQ_SERVER
+    HYPERCALL(dm_op, 3),
+#endif
 };
 
 #ifndef NDEBUG
@@ -1956,6 +1959,9 @@  static void do_trap_stage2_abort_guest(struct cpu_user_regs *regs,
             case IO_HANDLED:
                 advance_pc(regs, hsr);
                 return;
+            case IO_RETRY:
+                /* finish later */
+                return;
             case IO_UNHANDLED:
                 /* IO unhandled, try another way to handle it. */
                 break;
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 6819a3b..1da90f2 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -262,6 +262,8 @@  static inline void arch_vcpu_block(struct vcpu *v) {}
 
 #define arch_vm_assist_valid_mask(d) (1UL << VMASST_TYPE_runstate_update_flag)
 
+#define has_vpci(d)    ({ (void)(d); false; })
+
 #endif /* __ASM_DOMAIN_H__ */
 
 /*
diff --git a/xen/include/asm-arm/ioreq.h b/xen/include/asm-arm/ioreq.h
new file mode 100644
index 0000000..5018597
--- /dev/null
+++ b/xen/include/asm-arm/ioreq.h
@@ -0,0 +1,70 @@ 
+/*
+ * ioreq.h: Hardware virtual machine assist interface definitions.
+ *
+ * Copyright (c) 2016 Citrix Systems Inc.
+ * Copyright (c) 2019 Arm ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_ARM_IOREQ_H__
+#define __ASM_ARM_IOREQ_H__
+
+#ifdef CONFIG_IOREQ_SERVER
+enum io_state handle_ioserv(struct cpu_user_regs *regs, struct vcpu *v);
+enum io_state try_fwd_ioserv(struct cpu_user_regs *regs,
+                             struct vcpu *v, mmio_info_t *info);
+#else
+static inline enum io_state handle_ioserv(struct cpu_user_regs *regs,
+                                          struct vcpu *v)
+{
+    return IO_UNHANDLED;
+}
+
+static inline enum io_state try_fwd_ioserv(struct cpu_user_regs *regs,
+                                           struct vcpu *v, mmio_info_t *info)
+{
+    return IO_UNHANDLED;
+}
+#endif
+
+static inline bool handle_pio(uint16_t port, unsigned int size, int dir)
+{
+    /*
+     * TODO: For Arm64, the main user will be PCI. So this should be
+     * implemented when we add support for vPCI.
+     */
+    ASSERT_UNREACHABLE();
+    return true;
+}
+
+static inline void msix_write_completion(struct vcpu *v)
+{
+}
+
+/* This correlation must not be altered */
+#define IOREQ_STATUS_HANDLED     IO_HANDLED
+#define IOREQ_STATUS_UNHANDLED   IO_UNHANDLED
+#define IOREQ_STATUS_RETRY       IO_RETRY
+
+#endif /* __ASM_ARM_IOREQ_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index 8dbfb27..7ab873c 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -37,6 +37,7 @@  enum io_state
     IO_ABORT,       /* The IO was handled by the helper and led to an abort. */
     IO_HANDLED,     /* The IO was successfully handled by the helper. */
     IO_UNHANDLED,   /* The IO was not handled by the helper. */
+    IO_RETRY,       /* Retry the emulation for some reason */
 };
 
 typedef int (*mmio_read_t)(struct vcpu *v, mmio_info_t *info,
diff --git a/xen/include/xen/dm.h b/xen/include/xen/dm.h
index 4bd7e57..7f9f0bd 100644
--- a/xen/include/xen/dm.h
+++ b/xen/include/xen/dm.h
@@ -19,6 +19,8 @@ 
 
 #include <xen/sched.h>
 
+#include <public/hvm/dm_op.h>
+
 struct dmop_args {
     domid_t domid;
     unsigned int nr_bufs;