All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough
@ 2015-03-19 19:29 Julien Grall
  2015-03-19 19:29 ` [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts Julien Grall
                   ` (34 more replies)
  0 siblings, 35 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: ian.campbell, manish.jaggi, Julien Grall, tim, robert.vanvossen,
	stefano.stabellini, suravee.suthikulpanit, Josh.Whitehead,
	andrii.tseglytskyi

Hello all,

This is the fourth version of this patch series to add support for platform
device passthrough on ARM.

In order to passthrough a non-PCI device, the user will have to:
    - Map manually MMIO/IRQ
    - Describe the device in the newly partial device tree support
    - Specify the list of device protected by an IOMMU to assign to the
    guest.

While this solution is primitive, this is allow us to support more complex
device in Xen with an little additionnal work for the user. Attempting to
do it automatically is more difficult because we may not know the dependencies
between devices (for instance a Network card and a phy).

To avoid adding code in DOM0 to manage platform device deassignment, the
user has to add the property "xen,passthrough" to the device tree node
describing the device. This can be easily done via U-Boot. For instance,
if we want to passthrough the second network card of a Midway server to the
guest. The user will have to add the following line the u-boot script:

    fdt set /soc/ethernet@fff51000 xen,passthrough

This series has been tested on Midway by assigning the secondary network card
to a guest (see instruction below). Though, it requires a separate patch as
we decide to not support the Midway SMMU within the new drivers.

I plan to do futher testing on other boards.

A working tree can be found here:
    git://xenbits.xen.org/julieng/xen-unstable.git branch passthrough-v4

Major changes in v4:
    - The partial device tree option can only be used with trusted
    device tree
    - Add more documentation
    - Use DOMCTL_bind_pt_irq rather than PHYSDEVOP_map_pirq
    - Add XSM support for non-PCI passthrough

Major changes in v3:
    - Rework the approach to passthrough a device (xen,passthrough +
      partial device tree).
    - Extend the existing hypercalls to assign/deassign device rather than
    adding new one.
    - Merge series [4] and [5] in this serie.

Major changes in v2:
     - Drop the patch #1 of the previous version
     - Virtual IRQ are not anymore equal to the physical interrupt
     - Move the hypercall to get DT informations for privcmd to domctl
     - Split the domain creation in 2 two parts to allow per guest
     VGIC configuration (such as the number of SPIs).
     - Bunch of typoes, commit improvement, function renaming.

For all changes see in each patch.

Ian: I think, patch #1-#5 has been acked by all relevant people. Can you push
them to xen unstable?

Sincerely yours,

[1] http://lists.xen.org/archives/html/xen-devel/2014-07/msg04090.html
[2] http://lists.xenproject.org/archives/html/xen-devel/2014-12/msg01386.html
[3] http://lists.xenproject.org/archives/html/xen-devel/2014-12/msg01612.html
[4] http://lists.xen.org/archives/html/xen-devel/2014-11/msg01672.html
[5] http://lists.xenproject.org/archives/html/xen-devel/2014-07/msg02098.html

=========================================================================

Instructions to passthrough a non-PCI device

The example will use the secondary network card for the midway server.

1) Mark the device to let Xen knowns the device will be used for passthrough.
This is done in the device tree node describing the device by adding the
property "xen,passthrough". The command to do it in U-Boot is:

    fdt set /soc/ethernet@fff51000 xen,passthrough

2) Create the partial device tree describing the device. The IRQ are mapped
1:1 to the guest (i.e VIRQ == IRQ). For MMIO will have to find hole in the
guest memory layout (see xen/include/public/arch-arm.h, noted the layout
is not stable and can change between 2 releases version of Xen).

/dts-v1/;

/ {
    #address-cells = <2>;
    #size-cells = <2>;

    aliases {
        net = &mac0;
    };

    passthrough {
        compatible = "simple-bus";
        ranges;
        #address-cells = <2>;
        #size-cells = <2>;
    	mac0: ethernet@10000000 {
	    	compatible = "calxeda,hb-xgmac";
            reg = <0 0x10000000 0 0x1000>;
    		interrupts = <0 80 4  0 81 4  0 82 4>;
            /* dma-coherent can't be set because it requires platform
             * specific code for highbank
             */
/*	    	dma-coherent; */
    	};

        foo {
            my = <&mac0>;
        };
    };
};

3) Compile the partial guest device with dtc (Device Tree Compiler).
For our purpose, the compiled file will be called guest-midway.dtb and
placed in /root in DOM0.

3) Add the following options in the guest configuration file:

device_tree = "/root/guest-midway.dtb"
dtdev = [ "/soc/ethernet@fff51000" ]
irqs = [ 112, 113, 114 ]
iomem = [ "0xfff51,1@0x10000" ]

Cc: manish.jaggi@caviumnetworks.com
Cc: suravee.suthikulpanit@amd.com
Cc: andrii.tseglytskyi@globallogic.com
Cc: robert.vanvossen@dornerworks.com
Cc: Josh.Whitehead@dornerworks.com

Julien Grall (33):
  xen/arm: Divide GIC initialization in 2 parts
  xen/dts: Allow only IRQ translation that are mapped to main GIC
  xen/dts: Use unsigned int for MMIO and IRQ index
  xen/arm: vgic: Introduce a function to initialize pending_irq
  xen/arm: Map disabled device in DOM0
  xen/arm: Introduce xen,passthrough property
  xen: guestcopy: Provide an helper to safely copy string from guest
  MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE"
  xen: Extend DOMCTL createdomain to support arch configuration
  xen/arm: Allow virq != irq
  xen/arm: route_irq_to_guest: Check validity of the IRQ
  xen/arm: gic: Add sanity checks gic_route_irq_to_guest
  xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter
  xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber
  xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts
  xen/arm: Let the toolstack configure the number of SPIs
  xen/arm: vgic: Add spi_to_pending
  xen/arm: Release IRQ routed to a domain when it's destroying
  xen/arm: Implement hypercall DOMCTL_{,un}bind_pt_pirq
  xen/dts: Provide an helper to get a DT node from a path provided by a
    guest
  xen/passthrough: Introduce iommu_construct
  xen/passthrough: arm: release the DT devices assigned to a guest
    earlier
  xen/passthrough: iommu_deassign_device_dt: By default reassign device
    to nobody
  xen/iommu: arm: Wire iommu DOMCTL for ARM
  xen/xsm: Add helpers to check permission for device tree passthrough
  xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device
  tools/libxl: Create a per-arch function to map IRQ to a domain
  tools/libxl: Check if fdt_{first,next}_subnode are present in libfdt
  tools/(lib)xl: Add partial device tree support for ARM
  tools/libxl: arm: Use an higher value for the GIC phandle
  libxl: Add support for non-PCI passthrough
  xl: Add new option dtdev
  docs/misc: arm: Add documentation about non-PCI passthrough

 MAINTAINERS                                  |   2 +
 docs/man/xl.cfg.pod.5                        |  15 ++
 docs/misc/arm/device-tree/passthrough.txt    |   9 +
 docs/misc/arm/passthrough.txt                |  58 +++++++
 tools/config.h.in                            |   6 +
 tools/configure.ac                           |   5 +
 tools/flask/policy/policy/modules/xen/xen.if |   2 +-
 tools/libxc/include/xenctrl.h                |  32 +++-
 tools/libxc/xc_domain.c                      | 160 +++++++++++++++---
 tools/libxl/Makefile                         |   2 +-
 tools/libxl/libxl.h                          |   6 +
 tools/libxl/libxl_arch.h                     |  10 ++
 tools/libxl/libxl_arm.c                      | 236 +++++++++++++++++++++++++--
 tools/libxl/libxl_create.c                   |  58 ++++++-
 tools/libxl/libxl_dm.c                       |   3 +-
 tools/libxl/libxl_dom.c                      |   2 +-
 tools/libxl/libxl_fdt.c                      |  84 ++++++++++
 tools/libxl/libxl_internal.h                 |  12 +-
 tools/libxl/libxl_types.idl                  |   6 +
 tools/libxl/libxl_x86.c                      |  23 +++
 tools/libxl/xl_cmdimpl.c                     |  23 ++-
 xen/arch/arm/device.c                        |   2 +-
 xen/arch/arm/domain.c                        |  34 +++-
 xen/arch/arm/domain_build.c                  | 114 +++++++++----
 xen/arch/arm/domctl.c                        |  91 ++++++++---
 xen/arch/arm/gic-v2.c                        |  86 +++++-----
 xen/arch/arm/gic-v3.c                        |  91 ++++++-----
 xen/arch/arm/gic.c                           |  97 +++++++++--
 xen/arch/arm/irq.c                           | 162 ++++++++++++++++--
 xen/arch/arm/mm.c                            |   6 +-
 xen/arch/arm/platforms/omap5.c               |  12 --
 xen/arch/arm/platforms/xgene-storm.c         |   2 +-
 xen/arch/arm/setup.c                         |  10 +-
 xen/arch/arm/vgic-v2.c                       |   2 +-
 xen/arch/arm/vgic-v3.c                       |   2 +-
 xen/arch/arm/vgic.c                          |  73 ++++++---
 xen/arch/x86/domain.c                        |   3 +-
 xen/arch/x86/mm.c                            |   6 +-
 xen/arch/x86/setup.c                         |   8 +-
 xen/common/Makefile                          |   1 +
 xen/common/device_tree.c                     |  43 ++++-
 xen/common/domain.c                          |   7 +-
 xen/common/domctl.c                          |   3 +-
 xen/common/guestcopy.c                       |  31 ++++
 xen/common/schedule.c                        |   3 +-
 xen/drivers/passthrough/arm/iommu.c          |   7 +-
 xen/drivers/passthrough/arm/smmu.c           |   8 +-
 xen/drivers/passthrough/device_tree.c        | 136 +++++++++++++--
 xen/drivers/passthrough/iommu.c              |  35 +++-
 xen/drivers/passthrough/pci.c                |  69 ++++----
 xen/include/asm-arm/domain.h                 |   2 +
 xen/include/asm-arm/gic.h                    |  18 +-
 xen/include/asm-arm/irq.h                    |   8 +-
 xen/include/asm-arm/setup.h                  |   1 +
 xen/include/asm-arm/vgic.h                   |   9 +-
 xen/include/public/arch-arm.h                |  10 ++
 xen/include/public/arch-x86/xen.h            |   4 +
 xen/include/public/domctl.h                  |  46 +++---
 xen/include/xen/device_tree.h                |  32 +++-
 xen/include/xen/domain.h                     |   3 +-
 xen/include/xen/guest_access.h               |   5 +
 xen/include/xen/iommu.h                      |   7 +-
 xen/include/xen/sched.h                      |   9 +-
 xen/include/xsm/dummy.h                      |  47 ++++--
 xen/include/xsm/xsm.h                        |  55 +++++--
 xen/xsm/dummy.c                              |  10 +-
 xen/xsm/flask/avc.c                          |   3 +
 xen/xsm/flask/flask_op.c                     |  49 ++----
 xen/xsm/flask/hooks.c                        | 142 +++++++++++-----
 xen/xsm/flask/include/avc.h                  |   2 +
 xen/xsm/flask/policy/access_vectors          |   4 +-
 71 files changed, 1880 insertions(+), 484 deletions(-)
 create mode 100644 docs/misc/arm/device-tree/passthrough.txt
 create mode 100644 docs/misc/arm/passthrough.txt
 create mode 100644 tools/libxl/libxl_fdt.c
 create mode 100644 xen/common/guestcopy.c

-- 
2.1.4

^ permalink raw reply	[flat|nested] 103+ messages in thread

* [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:44   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 02/33] xen/dts: Allow only IRQ translation that are mapped to main GIC Julien Grall
                   ` (33 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Zoltan Kiss, ian.campbell, Stefano Stabellini, Julien Grall, tim,
	Frediano Ziglio, stefano.stabellini

Currently the function to translate IRQ from the device tree is set
unconditionally  to be able to be able to retrieve serial/timer IRQ before the
GIC has been initialized.

It assumes that the xlate function won't ever changed. We may also need to
have the primary interrupt controller very early.

Rework the gic initialization in 2 parts:
    - gic_preinit: Get the interrupt controller device tree node and set
up GIC and xlate callbacks
    - gic_init: Initialize the interrupt controller and the boot CPU
    interrupts.

The former function will be called just after the IRQ subsystem as been
initialized.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Frediano Ziglio <frediano.ziglio@huawei.com>
Cc: Zoltan Kiss <zoltan.kiss@huawei.com>

---
    Note that the HIP04 GIC driver has not been modified because I don't
    have a platform where I can test my changes. Although, the code is
    still building.

    I let the Hisilicon guys (Frediano and Zoltan) providing a suitable
    patch for there platform.

    Meanwhile, I think it can go upstream as it has been acked by both
    Ian and Stefano.

    Changes in v4:
        - Rebase on the latest staging (no functional changes)
        - Add Ian and Stefano's ack
        - Typo in the commit message

    Changes in v3:
        - Patch was previously sent in a separate series [1]
        - Reorder the function to avoid forward declaration
        - Make gic-v3 driver compliant to the new interface
        - Remove spurious field addition in gicv2 structure

    Changelog based on the separate series:

    Changes in v3:
        - Patch added.

    [1] https://patches.linaro.org/33313/
---
 xen/arch/arm/gic-v2.c     | 70 ++++++++++++++++++++++---------------------
 xen/arch/arm/gic-v3.c     | 75 ++++++++++++++++++++++++-----------------------
 xen/arch/arm/gic.c        | 16 ++++++++--
 xen/arch/arm/setup.c      |  3 +-
 xen/include/asm-arm/gic.h |  8 +++++
 5 files changed, 100 insertions(+), 72 deletions(-)

diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index 20cdbc9..3be4ad6 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -674,37 +674,10 @@ static hw_irq_controller gicv2_guest_irq_type = {
     .set_affinity = gicv2_irq_set_affinity,
 };
 
-const static struct gic_hw_operations gicv2_ops = {
-    .info                = &gicv2_info,
-    .secondary_init      = gicv2_secondary_cpu_init,
-    .save_state          = gicv2_save_state,
-    .restore_state       = gicv2_restore_state,
-    .dump_state          = gicv2_dump_state,
-    .gicv_setup          = gicv2v_setup,
-    .gic_host_irq_type   = &gicv2_host_irq_type,
-    .gic_guest_irq_type  = &gicv2_guest_irq_type,
-    .eoi_irq             = gicv2_eoi_irq,
-    .deactivate_irq      = gicv2_dir_irq,
-    .read_irq            = gicv2_read_irq,
-    .set_irq_properties  = gicv2_set_irq_properties,
-    .send_SGI            = gicv2_send_SGI,
-    .disable_interface   = gicv2_disable_interface,
-    .update_lr           = gicv2_update_lr,
-    .update_hcr_status   = gicv2_hcr_status,
-    .clear_lr            = gicv2_clear_lr,
-    .read_lr             = gicv2_read_lr,
-    .write_lr            = gicv2_write_lr,
-    .read_vmcr_priority  = gicv2_read_vmcr_priority,
-    .read_apr            = gicv2_read_apr,
-    .make_dt_node        = gicv2_make_dt_node,
-};
-
-/* Set up the GIC */
-static int __init gicv2_init(struct dt_device_node *node, const void *data)
+static int __init gicv2_init(void)
 {
     int res;
-
-    dt_device_set_used_by(node, DOMID_XEN);
+    const struct dt_device_node *node = gicv2_info.node;
 
     res = dt_device_get_address(node, 0, &gicv2.dbase, NULL);
     if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) )
@@ -727,9 +700,6 @@ static int __init gicv2_init(struct dt_device_node *node, const void *data)
         panic("GICv2: Cannot find the maintenance IRQ");
     gicv2_info.maintenance_irq = res;
 
-    /* Set the GIC as the primary interrupt controller */
-    dt_interrupt_controller = node;
-
     /* TODO: Add check on distributor, cpu size */
 
     printk("GICv2 initialization:\n"
@@ -774,8 +744,42 @@ static int __init gicv2_init(struct dt_device_node *node, const void *data)
 
     spin_unlock(&gicv2.lock);
 
+    return 0;
+}
+
+const static struct gic_hw_operations gicv2_ops = {
+    .info                = &gicv2_info,
+    .init                = gicv2_init,
+    .secondary_init      = gicv2_secondary_cpu_init,
+    .save_state          = gicv2_save_state,
+    .restore_state       = gicv2_restore_state,
+    .dump_state          = gicv2_dump_state,
+    .gicv_setup          = gicv2v_setup,
+    .gic_host_irq_type   = &gicv2_host_irq_type,
+    .gic_guest_irq_type  = &gicv2_guest_irq_type,
+    .eoi_irq             = gicv2_eoi_irq,
+    .deactivate_irq      = gicv2_dir_irq,
+    .read_irq            = gicv2_read_irq,
+    .set_irq_properties  = gicv2_set_irq_properties,
+    .send_SGI            = gicv2_send_SGI,
+    .disable_interface   = gicv2_disable_interface,
+    .update_lr           = gicv2_update_lr,
+    .update_hcr_status   = gicv2_hcr_status,
+    .clear_lr            = gicv2_clear_lr,
+    .read_lr             = gicv2_read_lr,
+    .write_lr            = gicv2_write_lr,
+    .read_vmcr_priority  = gicv2_read_vmcr_priority,
+    .read_apr            = gicv2_read_apr,
+    .make_dt_node        = gicv2_make_dt_node,
+};
+
+/* Set up the GIC */
+static int __init gicv2_preinit(struct dt_device_node *node, const void *data)
+{
     gicv2_info.hw_version = GIC_V2;
+    gicv2_info.node = node;
     register_gic_ops(&gicv2_ops);
+    dt_irq_xlate = gic_irq_xlate;
 
     return 0;
 }
@@ -788,7 +792,7 @@ static const struct dt_device_match gicv2_dt_match[] __initconst =
 
 DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
         .dt_match = gicv2_dt_match,
-        .init = gicv2_init,
+        .init = gicv2_preinit,
 DT_DEVICE_END
 
 /*
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index ab80670..48772f1 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1173,31 +1173,6 @@ static const hw_irq_controller gicv3_guest_irq_type = {
     .set_affinity = gicv3_irq_set_affinity,
 };
 
-static const struct gic_hw_operations gicv3_ops = {
-    .info                = &gicv3_info,
-    .save_state          = gicv3_save_state,
-    .restore_state       = gicv3_restore_state,
-    .dump_state          = gicv3_dump_state,
-    .gicv_setup          = gicv_v3_init,
-    .gic_host_irq_type   = &gicv3_host_irq_type,
-    .gic_guest_irq_type  = &gicv3_guest_irq_type,
-    .eoi_irq             = gicv3_eoi_irq,
-    .deactivate_irq      = gicv3_dir_irq,
-    .read_irq            = gicv3_read_irq,
-    .set_irq_properties  = gicv3_set_irq_properties,
-    .send_SGI            = gicv3_send_sgi,
-    .disable_interface   = gicv3_disable_interface,
-    .update_lr           = gicv3_update_lr,
-    .update_hcr_status   = gicv3_hcr_status,
-    .clear_lr            = gicv3_clear_lr,
-    .read_lr             = gicv3_read_lr,
-    .write_lr            = gicv3_write_lr,
-    .read_vmcr_priority  = gicv3_read_vmcr_priority,
-    .read_apr            = gicv3_read_apr,
-    .secondary_init      = gicv3_secondary_cpu_init,
-    .make_dt_node        = gicv3_make_dt_node,
-};
-
 static int __init cmp_rdist(const void *a, const void *b)
 {
     const struct rdist_region *l = a, *r = a;
@@ -1207,11 +1182,12 @@ static int __init cmp_rdist(const void *a, const void *b)
 }
 
 /* Set up the GIC */
-static int __init gicv3_init(struct dt_device_node *node, const void *data)
+static int __init gicv3_init(void)
 {
     struct rdist_region *rdist_regs;
     int res, i;
     uint32_t reg;
+    const struct dt_device_node *node = gicv3_info.node;
 
     if ( !cpu_has_gicv3 )
     {
@@ -1219,8 +1195,6 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
         return -ENODEV;
     }
 
-    dt_device_set_used_by(node, DOMID_XEN);
-
     res = dt_device_get_address(node, 0, &gicv3.dbase, &gicv3.dbase_size);
     if ( res || !gicv3.dbase )
         panic("GICv3: Cannot find a valid distributor address");
@@ -1274,9 +1248,6 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
         panic("GICv3: Cannot find the maintenance IRQ");
     gicv3_info.maintenance_irq = res;
 
-    /* Set the GIC as the primary interrupt controller */
-    dt_interrupt_controller = node;
-
     for ( i = 0; i < gicv3.rdist_count; i++ )
     {
         /* map dbase & rdist regions */
@@ -1311,15 +1282,47 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
     res = gicv3_cpu_init();
     gicv3_hyp_init();
 
-    gicv3_info.hw_version = GIC_V3;
-    /* Register hw ops*/
-    register_gic_ops(&gicv3_ops);
-
     spin_unlock(&gicv3.lock);
 
     return res;
 }
 
+static const struct gic_hw_operations gicv3_ops = {
+    .info                = &gicv3_info,
+    .init                = gicv3_init,
+    .save_state          = gicv3_save_state,
+    .restore_state       = gicv3_restore_state,
+    .dump_state          = gicv3_dump_state,
+    .gicv_setup          = gicv_v3_init,
+    .gic_host_irq_type   = &gicv3_host_irq_type,
+    .gic_guest_irq_type  = &gicv3_guest_irq_type,
+    .eoi_irq             = gicv3_eoi_irq,
+    .deactivate_irq      = gicv3_dir_irq,
+    .read_irq            = gicv3_read_irq,
+    .set_irq_properties  = gicv3_set_irq_properties,
+    .send_SGI            = gicv3_send_sgi,
+    .disable_interface   = gicv3_disable_interface,
+    .update_lr           = gicv3_update_lr,
+    .update_hcr_status   = gicv3_hcr_status,
+    .clear_lr            = gicv3_clear_lr,
+    .read_lr             = gicv3_read_lr,
+    .write_lr            = gicv3_write_lr,
+    .read_vmcr_priority  = gicv3_read_vmcr_priority,
+    .read_apr            = gicv3_read_apr,
+    .secondary_init      = gicv3_secondary_cpu_init,
+    .make_dt_node        = gicv3_make_dt_node,
+};
+
+static int __init gicv3_preinit(struct dt_device_node *node, const void *data)
+{
+    gicv3_info.hw_version = GIC_V3;
+    gicv3_info.node = node;
+    register_gic_ops(&gicv3_ops);
+    dt_irq_xlate = gic_irq_xlate;
+
+    return 0;
+}
+
 static const struct dt_device_match gicv3_dt_match[] __initconst =
 {
     DT_MATCH_GIC_V3,
@@ -1328,7 +1331,7 @@ static const struct dt_device_match gicv3_dt_match[] __initconst =
 
 DT_DEVICE_START(gicv3, "GICv3", DEVICE_GIC)
         .dt_match = gicv3_dt_match,
-        .init = gicv3_init,
+        .init = gicv3_preinit,
 DT_DEVICE_END
 
 /*
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 940fb8e..8e7f24b 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -163,8 +163,10 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
     return 0;
 }
 
-/* Set up the GIC */
-void __init gic_init(void)
+/* Find the interrupt controller and set up the callback to translate
+ * device tree IRQ.
+ */
+void __init gic_preinit(void)
 {
     int rc;
     struct dt_device_node *node;
@@ -189,6 +191,16 @@ void __init gic_init(void)
     if ( !num_gics )
         panic("Unable to find compatible GIC in the device tree");
 
+    /* Set the GIC as the primary interrupt controller */
+    dt_interrupt_controller = node;
+    dt_device_set_used_by(node, DOMID_XEN);
+}
+
+/* Set up the GIC */
+void __init gic_init(void)
+{
+    if ( gic_hw_ops->init() )
+        panic("Failed to initialize the GIC drivers");
     /* Clear LR mask for cpu0 */
     clear_cpu_lr_mask();
 }
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index b905c9f..4f05f57 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -752,7 +752,6 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     vm_init();
     dt_unflatten_host_device_tree();
-    dt_irq_xlate = gic_irq_xlate;
 
     init_IRQ();
 
@@ -760,6 +759,8 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     preinit_xen_time();
 
+    gic_preinit();
+
     dt_uart_init();
     console_init_preirq();
     console_init_ring();
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 89a9b6f..b16f98e 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -232,6 +232,10 @@ extern void gic_remove_from_queues(struct vcpu *v, unsigned int virtual_irq);
 
 /* Accept an interrupt from the GIC and dispatch its handler */
 extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq);
+/* Find the interrupt controller and set up the callback to translate
+ * device tree IRQ.
+ */
+extern void gic_preinit(void);
 /* Bring up the interrupt controller, and report # cpus attached */
 extern void gic_init(void);
 /* Bring up a secondary CPU's per-CPU GIC interface */
@@ -284,11 +288,15 @@ struct gic_info {
     uint8_t nr_lrs;
     /* Maintenance irq number */
     unsigned int maintenance_irq;
+    /* Pointer to the device tree node representing the interrupt controller */
+    const struct dt_device_node *node;
 };
 
 struct gic_hw_operations {
     /* Hold GIC HW information */
     const struct gic_info *info;
+    /* Initialize the GIC and the boot CPU */
+    int (*init)(void);
     /* Save GIC registers */
     void (*save_state)(struct vcpu *);
     /* Restore GIC registers */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 02/33] xen/dts: Allow only IRQ translation that are mapped to main GIC
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
  2015-03-19 19:29 ` [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-19 19:29 ` [PATCH v4 03/33] xen/dts: Use unsigned int for MMIO and IRQ index Julien Grall
                   ` (32 subsequent siblings)
  34 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

Xen is only able to handle one GIC controller. Some platforms may contain
other interrupt controllers.

Make sure to only translate IRQ mapped into the GIC handled by Xen.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---

    Changes in v4:
        - Add Ian's and Stefano's ack

    Changes in v3:
        - Patch was previously sent a separate series [1]
        - Rework the comment in dt_irq_translate.

    Changelog based on the separate series:

    Changes in v3:
        - Add an ASSERT to check that dt_interrupt_controller is not
        NULL.

    Changes in v2:
        - Fix compilation...

    [1] https://patches.linaro.org/33312/
---
 xen/common/device_tree.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index d1c716f..26fa298 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -1058,8 +1058,14 @@ int dt_irq_translate(const struct dt_raw_irq *raw,
                      struct dt_irq *out_irq)
 {
     ASSERT(dt_irq_xlate != NULL);
+    ASSERT(dt_interrupt_controller != NULL);
 
-    /* TODO: Retrieve the right irq_xlate. This is only work for the gic */
+    /*
+     * TODO: Retrieve the right irq_xlate. This is only works for the primary
+     * interrupt controller.
+     */
+    if ( raw->controller != dt_interrupt_controller )
+        return -EINVAL;
 
     return dt_irq_xlate(raw->specifier, raw->size,
                         &out_irq->irq, &out_irq->type);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 03/33] xen/dts: Use unsigned int for MMIO and IRQ index
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
  2015-03-19 19:29 ` [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts Julien Grall
  2015-03-19 19:29 ` [PATCH v4 02/33] xen/dts: Allow only IRQ translation that are mapped to main GIC Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-19 19:29 ` [PATCH v4 04/33] xen/arm: vgic: Introduce a function to initialize pending_irq Julien Grall
                   ` (31 subsequent siblings)
  34 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

There is no reason to use signed integer for an index.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---
    Changes in v4:
        - Add Ian's ack

    Changes in v3:
        - Slightly update commit message to drop the reference to new
        hypercalls.
        - Add Stefano's acked

    Changes in v2:
        - Use unsigned int instead fancy one like unsigned or uint32_t
---
 xen/common/device_tree.c      | 11 ++++++-----
 xen/include/xen/device_tree.h |  7 ++++---
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 26fa298..25880e8 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -496,7 +496,7 @@ static const struct dt_bus *dt_match_bus(const struct dt_device_node *np)
 }
 
 static const __be32 *dt_get_address(const struct dt_device_node *dev,
-                                    int index, u64 *size,
+                                    unsigned int index, u64 *size,
                                     unsigned int *flags)
 {
     const __be32 *prop;
@@ -683,7 +683,7 @@ bail:
 }
 
 /* dt_device_address - Translate device tree address and return it */
-int dt_device_get_address(const struct dt_device_node *dev, int index,
+int dt_device_get_address(const struct dt_device_node *dev, unsigned int index,
                           u64 *addr, u64 *size)
 {
     const __be32 *addrp;
@@ -1006,7 +1006,8 @@ fail:
     return -EINVAL;
 }
 
-int dt_device_get_raw_irq(const struct dt_device_node *device, int index,
+int dt_device_get_raw_irq(const struct dt_device_node *device,
+                          unsigned int index,
                           struct dt_raw_irq *out_irq)
 {
     const struct dt_device_node *p;
@@ -1014,7 +1015,7 @@ int dt_device_get_raw_irq(const struct dt_device_node *device, int index,
     u32 intsize, intlen;
     int res = -EINVAL;
 
-    dt_dprintk("dt_device_get_raw_irq: dev=%s, index=%d\n",
+    dt_dprintk("dt_device_get_raw_irq: dev=%s, index=%u\n",
                device->full_name, index);
 
     /* Get the interrupts property */
@@ -1071,7 +1072,7 @@ int dt_irq_translate(const struct dt_raw_irq *raw,
                         &out_irq->irq, &out_irq->type);
 }
 
-int dt_device_get_irq(const struct dt_device_node *device, int index,
+int dt_device_get_irq(const struct dt_device_node *device, unsigned int index,
                       struct dt_irq *out_irq)
 {
     struct dt_raw_irq raw;
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index c8a0375..6bbee6d 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -474,7 +474,7 @@ const struct dt_device_node *dt_get_parent(const struct dt_device_node *node);
  * This function resolves an address, walking the tree, for a give
  * device-tree node. It returns 0 on success.
  */
-int dt_device_get_address(const struct dt_device_node *dev, int index,
+int dt_device_get_address(const struct dt_device_node *dev, unsigned int index,
                           u64 *addr, u64 *size);
 
 /**
@@ -504,7 +504,7 @@ unsigned int dt_number_of_address(const struct dt_device_node *device);
  * This function resolves an interrupt, walking the tree, for a given
  * device-tree node. It's the high level pendant to dt_device_get_raw_irq().
  */
-int dt_device_get_irq(const struct dt_device_node *device, int index,
+int dt_device_get_irq(const struct dt_device_node *device, unsigned int index,
                       struct dt_irq *irq);
 
 /**
@@ -516,7 +516,8 @@ int dt_device_get_irq(const struct dt_device_node *device, int index,
  * This function resolves an interrupt for a device, no translation is
  * made. dt_irq_translate can be called after.
  */
-int dt_device_get_raw_irq(const struct dt_device_node *device, int index,
+int dt_device_get_raw_irq(const struct dt_device_node *device,
+                          unsigned int index,
                           struct dt_raw_irq *irq);
 
 /**
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 04/33] xen/arm: vgic: Introduce a function to initialize pending_irq
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (2 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 03/33] xen/dts: Use unsigned int for MMIO and IRQ index Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-19 19:29 ` [PATCH v4 05/33] xen/arm: Map disabled device in DOM0 Julien Grall
                   ` (30 subsequent siblings)
  34 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

The structure pending_irq is initialized in the same way in 2 different
places. Introduce vgic_init_pending_irq to avoid code duplication.

Also move the setting of the irq field into this function as we need to
initialize it once rather than every time an IRQ is injected to the guest.

Finally, use unsigned int for the "irq" field to be consistent with the
virq variable

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---
    Changes in v4:
        - Add Ian's ack
        - Typoes in the commit message

    Changes in v3:
        - Add Stefano's acked
        - The irq field is now unsigned int
        - Update commit message to speak about the int -> unsigned int
        change
        - Use "unsigned int" rather than "unsigned"

    Changes in v2:
        - Patch added
---
 xen/arch/arm/gic.c         |  2 +-
 xen/arch/arm/vgic.c        | 19 ++++++++++---------
 xen/include/asm-arm/vgic.h |  2 +-
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 8e7f24b..ba7950b 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -630,7 +630,7 @@ void gic_dump_info(struct vcpu *v)
 
     list_for_each_entry ( p, &v->arch.vgic.inflight_irqs, inflight )
     {
-        printk("Inflight irq=%d lr=%u\n", p->irq, p->lr);
+        printk("Inflight irq=%u lr=%u\n", p->irq, p->lr);
     }
 
     list_for_each_entry( p, &v->arch.vgic.lr_pending, lr_queue )
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index c14d79d..0b4fa57 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -61,6 +61,13 @@ struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq)
     return vgic_get_rank(v, rank);
 }
 
+static void vgic_init_pending_irq(struct pending_irq *p, unsigned int virq)
+{
+    INIT_LIST_HEAD(&p->inflight);
+    INIT_LIST_HEAD(&p->lr_queue);
+    p->irq = virq;
+}
+
 int domain_vgic_init(struct domain *d)
 {
     int i;
@@ -101,10 +108,8 @@ int domain_vgic_init(struct domain *d)
         return -ENOMEM;
 
     for (i=0; i<d->arch.vgic.nr_spis; i++)
-    {
-        INIT_LIST_HEAD(&d->arch.vgic.pending_irqs[i].inflight);
-        INIT_LIST_HEAD(&d->arch.vgic.pending_irqs[i].lr_queue);
-    }
+        vgic_init_pending_irq(&d->arch.vgic.pending_irqs[i], i + 32);
+
     for (i=0; i<DOMAIN_NR_RANKS(d); i++)
         spin_lock_init(&d->arch.vgic.shared_irqs[i].lock);
 
@@ -148,10 +153,7 @@ int vcpu_vgic_init(struct vcpu *v)
 
     memset(&v->arch.vgic.pending_irqs, 0, sizeof(v->arch.vgic.pending_irqs));
     for (i = 0; i < 32; i++)
-    {
-        INIT_LIST_HEAD(&v->arch.vgic.pending_irqs[i].inflight);
-        INIT_LIST_HEAD(&v->arch.vgic.pending_irqs[i].lr_queue);
-    }
+        vgic_init_pending_irq(&v->arch.vgic.pending_irqs[i], i);
 
     INIT_LIST_HEAD(&v->arch.vgic.inflight_irqs);
     INIT_LIST_HEAD(&v->arch.vgic.lr_pending);
@@ -409,7 +411,6 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
         goto out;
     }
 
-    n->irq = irq;
     n->priority = priority;
 
     /* the irq is enabled */
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index dd93872..0d0d114 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -67,7 +67,7 @@ struct pending_irq
 #define GIC_IRQ_GUEST_MIGRATING   4
     unsigned long status;
     struct irq_desc *desc; /* only set it the irq corresponds to a physical irq */
-    int irq;
+    unsigned int irq;
 #define GIC_INVALID_LR         ~(uint8_t)0
     uint8_t lr;
     uint8_t priority;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 05/33] xen/arm: Map disabled device in DOM0
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (3 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 04/33] xen/arm: vgic: Introduce a function to initialize pending_irq Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-19 19:29 ` [PATCH v4 06/33] xen/arm: Introduce xen, passthrough property Julien Grall
                   ` (29 subsequent siblings)
  34 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: ian.campbell, Stefano Stabellini, Julien Grall, tim,
	stefano.stabellini, Andrii Tseglytskyi

The check to avoid mapping disabled devices in DOM0 was added in
anticipation of the device passthrough. But, a brand new property will
be added later to mark device which will be passthrough.

Also, remove the memory type check as we already skipped them earlier in
the function via skip_matches.

Furthermore, some platform (such as the OMAP) may try to poke device even
if the property "status" is set to "disabled".

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Andrii Tseglytskyi <andrii.tseglytskyi@globallogic.com>

---
    Changes in v4:
        - Typoes in the commit message
        - Add Ian and Stefano's ack

    Changes in v3:
        - Patch added
        - "xen/arm: follow-up to allow DOM0 manage IRQ and MMIO" has
        been split in 2 patch [1]
        - Drop the check for memory type. Thoses nodes have been
        blacklisted.

[1] https://patches.linaro.org/34669/
---
 xen/arch/arm/domain_build.c    | 19 +++----------------
 xen/arch/arm/platforms/omap5.c | 12 ------------
 2 files changed, 3 insertions(+), 28 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index ab4ad65..31b32df 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1085,22 +1085,9 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
         return 0;
     }
 
-    /*
-     * Some device doesn't need to be mapped in Xen:
-     *  - Memory: the guest will see a different view of memory. It will
-     *  be allocated later.
-     *  - Disabled device: Linux is able to cope with status="disabled"
-     *  property. Therefore these device doesn't need to be mapped. This
-     *  solution can be use later for pass through.
-     */
-    if ( !dt_device_type_is_equal(node, "memory") &&
-         dt_device_is_available(node) )
-    {
-        res = map_device(d, node);
-
-        if ( res )
-            return res;
-    }
+    res = map_device(d, node);
+    if ( res)
+        return res;
 
     /*
      * The property "name" is used to have a different name on older FDT
diff --git a/xen/arch/arm/platforms/omap5.c b/xen/arch/arm/platforms/omap5.c
index 9d6e504..e7bf30d 100644
--- a/xen/arch/arm/platforms/omap5.c
+++ b/xen/arch/arm/platforms/omap5.c
@@ -155,17 +155,6 @@ static const char * const dra7_dt_compat[] __initconst =
     NULL
 };
 
-static const struct dt_device_match dra7_blacklist_dev[] __initconst =
-{
-    /* OMAP Linux kernel handles devices with status "disabled" in a
-     * weird manner - tries to reset them. While their memory ranges
-     * are not mapped, this leads to data aborts, so skip these devices
-     * from DT for dom0.
-     */
-    DT_MATCH_NOT_AVAILABLE(),
-    { /* sentinel */ },
-};
-
 PLATFORM_START(omap5, "TI OMAP5")
     .compatible = omap5_dt_compat,
     .init_time = omap5_init_time,
@@ -185,7 +174,6 @@ PLATFORM_START(dra7, "TI DRA7")
 
     .dom0_gnttab_start = 0x4b000000,
     .dom0_gnttab_size = 0x20000,
-    .blacklist_dev = dra7_blacklist_dev,
 PLATFORM_END
 
 /*
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 06/33] xen/arm: Introduce xen, passthrough property
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (4 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 05/33] xen/arm: Map disabled device in DOM0 Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:25   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest Julien Grall
                   ` (28 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

When a device is marked for passthrough (via the new property
"xen,passthrough"), dom0 must not access to the device (i.e not
loading a driver), but should be able to manage the MMIO/interrupt
of the passthrough device.

The latter part will allow the toolstack to map MMIO/IRQ when a device
is pass through to a guest.

The property "xen,passthrough" will be translated as 'status="disabled"'
in the device tree to avoid DOM0 using the device. We assume that DOM0 is
able to cope with this property (already the case for Linux, and
required by ePAPR).

Rework the function map_device (renamed into handle_device) to:

* For a given device node:
    - Give permission to manage IRQ/MMIO for this device
    - Retrieve the IRQ configuration (i.e edge/level) from the device
    tree
* When the device is not marked for guest passthrough:
    - Assign the device to the guest if it's protected by an IOMMU
    - Map the IRQs and MMIOs regions to the guest

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

---
    Changes in v4:
        - Add Stefano's ack
        - Rebase on the latest staging (no function changes)
        - Rework the device passthrough documentation to be weaker
        - Coding style and typoes

    Changes in v3:
        - This patch was formely "xen/arm: Follow-up to allow DOM0
        manage IRQ and MMIO". It has been split in 2 parts [1].
        - Update commit title and improve message
        - Remove spurious change

[1] https://patches.linaro.org/34669/
---
 docs/misc/arm/device-tree/passthrough.txt |  9 +++
 xen/arch/arm/device.c                     |  2 +-
 xen/arch/arm/domain_build.c               | 97 ++++++++++++++++++++++++-------
 xen/common/device_tree.c                  |  6 ++
 xen/include/xen/device_tree.h             | 11 ++++
 5 files changed, 103 insertions(+), 22 deletions(-)
 create mode 100644 docs/misc/arm/device-tree/passthrough.txt

diff --git a/docs/misc/arm/device-tree/passthrough.txt b/docs/misc/arm/device-tree/passthrough.txt
new file mode 100644
index 0000000..6715646
--- /dev/null
+++ b/docs/misc/arm/device-tree/passthrough.txt
@@ -0,0 +1,9 @@
+Device passthrough
+===================
+
+Any device with the property "xen,passthrough" set will not be exposed to
+DOM0 and therefore no driver will be loaded.
+
+It is highly recommended to set this property on devices which are passed
+through since many devices will not cope with being accessed by dom0 and
+then handed over to another domain.
diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
index 675784c..0b53f6a 100644
--- a/xen/arch/arm/device.c
+++ b/xen/arch/arm/device.c
@@ -30,7 +30,7 @@ int __init device_init(struct dt_device_node *dev, enum device_class class,
 
     ASSERT(dev != NULL);
 
-    if ( !dt_device_is_available(dev) )
+    if ( !dt_device_is_available(dev) || dt_device_for_passthrough(dev) )
         return  -ENODEV;
 
     for ( desc = _sdevice; desc != _edevice; desc++ )
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 31b32df..2eb31ad 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -402,7 +402,7 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
                             const struct dt_device_node *node)
 {
     const char *bootargs = NULL;
-    const struct dt_property *prop;
+    const struct dt_property *prop, *status = NULL;
     int res = 0;
     int had_dom0_bootargs = 0;
 
@@ -457,6 +457,17 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
             }
         }
 
+        /* Don't expose the property "xen,passthrough" to the guest */
+        if ( dt_property_name_is_equal(prop, "xen,passthrough") )
+            continue;
+
+        /* Remember and skip the status property as Xen may modify it later */
+        if ( dt_property_name_is_equal(prop, "status") )
+        {
+            status = prop;
+            continue;
+        }
+
         res = fdt_property(kinfo->fdt, prop->name, prop_data, prop_len);
 
         xfree(new_data);
@@ -465,6 +476,19 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
             return res;
     }
 
+    /*
+     * Override the property "status" to disable the device when it's
+     * marked for passthrough.
+     */
+    if ( dt_device_for_passthrough(node) )
+        res = fdt_property_string(kinfo->fdt, "status", "disabled");
+    else if ( status )
+        res = fdt_property(kinfo->fdt, "status", status->value,
+                           status->length);
+
+    if ( res )
+        return res;
+
     if ( dt_node_path_is_equal(node, "/chosen") )
     {
         const struct bootmodule *mod = kinfo->initrd_bootmodule;
@@ -903,8 +927,15 @@ static int make_timer_node(const struct domain *d, void *fdt,
     return res;
 }
 
-/* Map the device in the domain */
-static int map_device(struct domain *d, struct dt_device_node *dev)
+/*
+ * For a given device node:
+ *  - Give permission to the guest to manage IRQ and MMIO range
+ *  - Retrieve the IRQ configuration (i.e edge/level) from device tree
+ * When the device is not marked for guest passthrough:
+ *  - Assign the device to the guest if it's protected by an IOMMU
+ *  - Map the IRQs and iomem regions to DOM0
+ */
+static int handle_device(struct domain *d, struct dt_device_node *dev)
 {
     unsigned int nirq;
     unsigned int naddr;
@@ -913,13 +944,15 @@ static int map_device(struct domain *d, struct dt_device_node *dev)
     unsigned int irq;
     struct dt_raw_irq rirq;
     u64 addr, size;
+    bool_t need_mapping = !dt_device_for_passthrough(dev);
 
     nirq = dt_number_of_irq(dev);
     naddr = dt_number_of_address(dev);
 
-    DPRINT("%s nirq = %d naddr = %u\n", dt_node_full_name(dev), nirq, naddr);
+    DPRINT("%s passthrough = %d nirq = %d naddr = %u\n", dt_node_full_name(dev),
+           need_mapping, nirq, naddr);
 
-    if ( dt_device_is_protected(dev) )
+    if ( dt_device_is_protected(dev) && need_mapping )
     {
         DPRINT("%s setup iommu\n", dt_node_full_name(dev));
         res = iommu_assign_dt_device(d, dev);
@@ -931,7 +964,7 @@ static int map_device(struct domain *d, struct dt_device_node *dev)
         }
     }
 
-    /* Map IRQs */
+    /* Give permission and map IRQs */
     for ( i = 0; i < nirq; i++ )
     {
         res = dt_device_get_raw_irq(dev, i, &rirq);
@@ -970,16 +1003,34 @@ static int map_device(struct domain *d, struct dt_device_node *dev)
          * the IRQ twice. This can legitimately happen if the IRQ is shared
          */
         vgic_reserve_virq(d, irq);
-        res = route_irq_to_guest(d, irq, dt_node_name(dev));
+
+        res = irq_permit_access(d, irq);
         if ( res )
         {
-            printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
-                   irq, d->domain_id);
+            printk(XENLOG_ERR "Unable to permit to dom%u access to IRQ %u\n",
+                   d->domain_id, irq);
             return res;
         }
+
+        if ( need_mapping )
+        {
+            /*
+             * Checking the return of vgic_reserve_virq is not
+             * necessary. It should not fail except when we try to map
+             * twice the IRQ. This can happen if the IRQ is shared
+             */
+            vgic_reserve_virq(d, irq);
+            res = route_irq_to_guest(d, irq, dt_node_name(dev));
+            if ( res )
+            {
+                printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
+                       irq, d->domain_id);
+                return res;
+            }
+        }
     }
 
-    /* Map the address ranges */
+    /* Give permission and map MMIOs */
     for ( i = 0; i < naddr; i++ )
     {
         res = dt_device_get_address(dev, i, &addr, &size);
@@ -1003,17 +1054,21 @@ static int map_device(struct domain *d, struct dt_device_node *dev)
                    addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
             return res;
         }
-        res = map_mmio_regions(d,
-                               paddr_to_pfn(addr & PAGE_MASK),
-                               DIV_ROUND_UP(size, PAGE_SIZE),
-                               paddr_to_pfn(addr & PAGE_MASK));
-        if ( res )
+
+        if ( need_mapping )
         {
-            printk(XENLOG_ERR "Unable to map 0x%"PRIx64
-                   " - 0x%"PRIx64" in domain %d\n",
-                   addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1,
-                   d->domain_id);
-            return res;
+            res = map_mmio_regions(d,
+                                   paddr_to_pfn(addr & PAGE_MASK),
+                                   DIV_ROUND_UP(size, PAGE_SIZE),
+                                   paddr_to_pfn(addr & PAGE_MASK));
+            if ( res )
+            {
+                printk(XENLOG_ERR "Unable to map 0x%"PRIx64
+                       " - 0x%"PRIx64" in domain %d\n",
+                       addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1,
+                       d->domain_id);
+                return res;
+            }
         }
     }
 
@@ -1085,7 +1140,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
         return 0;
     }
 
-    res = map_device(d, node);
+    res = handle_device(d, node);
     if ( res)
         return res;
 
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 25880e8..02cae91 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -1104,6 +1104,12 @@ bool_t dt_device_is_available(const struct dt_device_node *device)
     return 0;
 }
 
+bool_t dt_device_for_passthrough(const struct dt_device_node *device)
+{
+    return (dt_find_property(device, "xen,passthrough", NULL) != NULL);
+
+}
+
 static int __dt_parse_phandle_with_args(const struct dt_device_node *np,
                                         const char *list_name,
                                         const char *cells_name,
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 6bbee6d..57eb3ee 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -556,6 +556,17 @@ int dt_n_addr_cells(const struct dt_device_node *np);
 bool_t dt_device_is_available(const struct dt_device_node *device);
 
 /**
+ * dt_device_for_passthrough - Check if a device will be used for
+ * passthrough later
+ *
+ * @device: Node to check
+ *
+ * Return true if the property "xen,passthrough" is present in the node,
+ * false otherwise.
+ */
+bool_t dt_device_for_passthrough(const struct dt_device_node *device);
+
+/**
  * dt_match_node - Tell if a device_node has a matching of dt_device_match
  * @matches: array of dt_device_match structures to search in
  * @node: the dt_device_node structure to match against
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (5 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 06/33] xen/arm: Introduce xen, passthrough property Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 13:24   ` Andrew Cooper
  2015-03-19 19:29 ` [PATCH v4 08/33] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE" Julien Grall
                   ` (27 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini, Jan Beulich, Daniel De Graaf

Flask code already provides a helper to copy a string from guest. In a later
patch, the new DT hypercalls will need a similar function.

To avoid code duplication, copy the flask helper (flask_copying_string) to
common code:
    - Rename into safe_copy_string_from_guest
    - Add comment to explain the extra +1
    - Return the buffer directly and use the macros provided by
    xen/err.h to return an error code if necessary.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>

---
    Changes in v4:
        - Use -ENOBUFS rather than -ENOENT
        - Fix coding style in comment
        - Typoes in commit message
        - Convert the new flask_copying_string (for DT) in
        safe_copy_string_from_guest
        - Add Ian and Daniel's ack

    Changes in v3:
        - Use macros of xen/err.h to return either the buffer or an
        error code
        - Reuse size_t instead of unsigned long
        - Update comment and commit message

    Changes in v2:
        - Rename copy_string_from_guest into safe_copy_string_from_guest
        - Update commit message and comment in the code
---
 xen/common/Makefile            |  1 +
 xen/common/guestcopy.c         | 31 ++++++++++++++++++++++++++
 xen/include/xen/guest_access.h |  5 +++++
 xen/xsm/flask/flask_op.c       | 49 +++++++++++-------------------------------
 4 files changed, 50 insertions(+), 36 deletions(-)
 create mode 100644 xen/common/guestcopy.c

diff --git a/xen/common/Makefile b/xen/common/Makefile
index 1956091..cf15887 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -9,6 +9,7 @@ obj-y += event_2l.o
 obj-y += event_channel.o
 obj-y += event_fifo.o
 obj-y += grant_table.o
+obj-y += guestcopy.o
 obj-y += irq.o
 obj-y += kernel.o
 obj-y += keyhandler.o
diff --git a/xen/common/guestcopy.c b/xen/common/guestcopy.c
new file mode 100644
index 0000000..1645cbd
--- /dev/null
+++ b/xen/common/guestcopy.c
@@ -0,0 +1,31 @@
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/guest_access.h>
+#include <xen/err.h>
+
+/*
+ * The function copies a string from the guest and adds a NUL to
+ * make sure the string is correctly terminated.
+ */
+void *safe_copy_string_from_guest(XEN_GUEST_HANDLE(char) u_buf,
+                                  size_t size, size_t max_size)
+{
+    char *tmp;
+
+    if ( size > max_size )
+        return ERR_PTR(-ENOBUFS);
+
+    /* Add an extra +1 to append \0 */
+    tmp = xmalloc_array(char, size + 1);
+    if ( !tmp )
+        return ERR_PTR(-ENOMEM);
+
+    if ( copy_from_guest(tmp, u_buf, size) )
+    {
+        xfree(tmp);
+        return ERR_PTR(-EFAULT);
+    }
+    tmp[size] = 0;
+
+    return tmp;
+}
diff --git a/xen/include/xen/guest_access.h b/xen/include/xen/guest_access.h
index 373454e..55645e6 100644
--- a/xen/include/xen/guest_access.h
+++ b/xen/include/xen/guest_access.h
@@ -8,6 +8,8 @@
 #define __XEN_GUEST_ACCESS_H__
 
 #include <asm/guest_access.h>
+#include <xen/types.h>
+#include <public/xen.h>
 
 #define copy_to_guest(hnd, ptr, nr)                     \
     copy_to_guest_offset(hnd, 0, ptr, nr)
@@ -27,4 +29,7 @@
 #define __clear_guest(hnd, nr)                          \
     __clear_guest_offset(hnd, 0, nr)
 
+void *safe_copy_string_from_guest(XEN_GUEST_HANDLE(char) u_buf,
+                                 size_t size, size_t max_size);
+
 #endif /* __XEN_GUEST_ACCESS_H__ */
diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
index 47aacc1..802ffd4 100644
--- a/xen/xsm/flask/flask_op.c
+++ b/xen/xsm/flask/flask_op.c
@@ -12,6 +12,7 @@
 #include <xen/event.h>
 #include <xsm/xsm.h>
 #include <xen/guest_access.h>
+#include <xen/err.h>
 
 #include <public/xsm/flask_op.h>
 
@@ -93,29 +94,6 @@ static int domain_has_security(struct domain *d, u32 perms)
                         perms, NULL);
 }
 
-static int flask_copyin_string(XEN_GUEST_HANDLE(char) u_buf, char **buf,
-                               size_t size, size_t max_size)
-{
-    char *tmp;
-
-    if ( size > max_size )
-        return -ENOENT;
-
-    tmp = xmalloc_array(char, size + 1);
-    if ( !tmp )
-        return -ENOMEM;
-
-    if ( copy_from_guest(tmp, u_buf, size) )
-    {
-        xfree(tmp);
-        return -EFAULT;
-    }
-    tmp[size] = 0;
-
-    *buf = tmp;
-    return 0;
-}
-
 #endif /* COMPAT */
 
 static int flask_security_user(struct xen_flask_userlist *arg)
@@ -129,9 +107,9 @@ static int flask_security_user(struct xen_flask_userlist *arg)
     if ( rv )
         return rv;
 
-    rv = flask_copyin_string(arg->u.user, &user, arg->size, PAGE_SIZE);
-    if ( rv )
-        return rv;
+    user = safe_copy_string_from_guest(arg->u.user, arg->size, PAGE_SIZE);
+    if ( IS_ERR(user) )
+        return PTR_ERR(user);
 
     rv = security_get_user_sids(arg->start_sid, user, &sids, &nsids);
     if ( rv < 0 )
@@ -244,9 +222,9 @@ static int flask_security_context(struct xen_flask_sid_context *arg)
     if ( rv )
         return rv;
 
-    rv = flask_copyin_string(arg->context, &buf, arg->size, PAGE_SIZE);
-    if ( rv )
-        return rv;
+    buf = safe_copy_string_from_guest(arg->context, arg->size, PAGE_SIZE);
+    if ( IS_ERR(buf) )
+        return PTR_ERR(buf);
 
     rv = security_context_to_sid(buf, arg->size, &arg->sid);
     if ( rv < 0 )
@@ -336,14 +314,13 @@ static int flask_security_setavc_threshold(struct xen_flask_setavc_threshold *ar
 static int flask_security_resolve_bool(struct xen_flask_boolean *arg)
 {
     char *name;
-    int rv;
 
     if ( arg->bool_id != -1 )
         return 0;
 
-    rv = flask_copyin_string(arg->name, &name, arg->size, bool_maxstr);
-    if ( rv )
-        return rv;
+    name = safe_copy_string_from_guest(arg->name, arg->size, bool_maxstr);
+    if ( IS_ERR(name) )
+        return PTR_ERR(name);
 
     arg->bool_id = security_find_bool(name);
     arg->size = 0;
@@ -574,9 +551,9 @@ static int flask_devicetree_label(struct xen_flask_devicetree_label *arg)
     if ( rv )
         return rv;
 
-    rv = flask_copyin_string(arg->path, &buf, arg->length, PAGE_SIZE);
-    if ( rv )
-        return rv;
+    buf = safe_copy_string_from_guest(arg->path, arg->length, PAGE_SIZE);
+    if ( IS_ERR(buf) )
+        return PTR_ERR(buf);
 
     /* buf is consumed or freed by this function */
     rv = security_devicetree_setlabel(buf, sid);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 08/33] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE"
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (6 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:26   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 09/33] xen: Extend DOMCTL createdomain to support arch configuration Julien Grall
                   ` (26 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini, Jan Beulich

Suggested-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Keir Fraser <keir@xen.org>

---
    Changes in v4:
        - Patch added
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d88fca3..3558164 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -158,6 +158,7 @@ F:	xen/common/libfdt/
 F:	xen/common/device_tree.c
 F:	xen/include/xen/libfdt/
 F:	xen/include/xen/device_tree.h
+F:	xen/drivers/passthrough/device_tree.c
 
 EFI
 M:     Jan Beulich <jbeulich@suse.com>
@@ -214,6 +215,7 @@ F:	xen/drivers/passthrough/
 X:	xen/drivers/passthrough/amd/
 X:	xen/drivers/passthrough/arm/
 X:	xen/drivers/passthrough/vtd/
+X:	xen/drivers/passthrough/device_tree.c
 F:	xen/include/xen/iommu.h
 
 KEXEC
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 09/33] xen: Extend DOMCTL createdomain to support arch configuration
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (7 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 08/33] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE" Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:39   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 10/33] xen/arm: Allow virq != irq Julien Grall
                   ` (25 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, Stefano Stabellini, George Dunlap,
	Ian Jackson, Julien Grall, tim, stefano.stabellini, Jan Beulich,
	Andrew Cooper, Keir Fraser, Daniel De Graaf

On ARM the virtual GIC may differ between each guest (emulated GIC version,
number of SPIs...). This information is already known at the domain creation
and can never change.

For now only the gic_version is set. In the long run, there will be more
parameters such as the number of SPIs. All will be required to be set at the
same time.

A new arch-specific structure arch_domainconfig has been created, the x86
one doesn't have any specific configuration, for now, a dummy structure
(C-spec compliant) has been created.

Some external tools (qemu, xenstore) may be required to create a domain.
Rather than asking them to take care of the arch-specific domain
configuration, let the current function (xc_domain_create) chose a
default configuration and introduce a new one (xc_domain_create_config).

This patch also drops the previously introduced DOMCTL arm_configure_domain
in Xen 4.5, as it has been made useless.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <george.dunlap@eu.citrix.com>

---
    This is a follow-up of http://lists.xen.org/archives/html/xen-devel/2014-11/msg00522.html

    Interesting discussion about the implication of this series:
        - http://lists.xen.org/archives/html/xen-devel/2015-02/msg02721.html
        - http://lists.xen.org/archives/html/xen-devel/2015-02/msg03306.html

    As ARM will only support migration v2, it would be possible to
    create a specific section which will store arch-configuration.

    For the xc_domain_create, Stefano S. was looking to drop PV domain
    creation support in QEMU. So maybe I could simply extend xc_domain_create
    and drop the xc_domain_create_config.

    Note: XEN_DOMCTL_INTERFACE_VERSION has been bumped by the commit
    e1890c4 "time: widen wallclock seconds to 64 bits".

    Changes in v4:
        - Typoes in the commit message
        - Bump the XEN_DOMCTL_INTERFACE_VERSION
        - Add Jan's ack for x86 and the common hypervisors pieces
        - Add Daniel's ack for XSM
        - Add Stefano's ack
        - Drop unused include in arch/arm/domctl.c (was added specially
          for the DOMCTL)
        - Remove a spurious line change in libxl_create.c

    Changes in v3:
        - Patch was previously sent in a separate series [1]
        - Rename arch_domainconfig to xen_arch_domainconfig
        - Drop the typedef
        - Pass NULL for DOM0 config on x86
        - Drop spurious changes
        - Update comment in start_xen in arch/arm/setup.c

        [1] https://patches.linaro.org/41083/
---
 tools/flask/policy/policy/modules/xen/xen.if |  2 +-
 tools/libxc/include/xenctrl.h                | 14 +++++----
 tools/libxc/xc_domain.c                      | 46 ++++++++++++++++------------
 tools/libxl/libxl_arch.h                     |  6 ++++
 tools/libxl/libxl_arm.c                      | 28 ++++++++++-------
 tools/libxl/libxl_create.c                   | 20 +++++++++---
 tools/libxl/libxl_dm.c                       |  3 +-
 tools/libxl/libxl_dom.c                      |  2 +-
 tools/libxl/libxl_internal.h                 |  7 +++--
 tools/libxl/libxl_x86.c                      | 10 ++++++
 xen/arch/arm/domain.c                        | 28 ++++++++++++++++-
 xen/arch/arm/domctl.c                        | 36 ----------------------
 xen/arch/arm/mm.c                            |  6 ++--
 xen/arch/arm/setup.c                         |  6 +++-
 xen/arch/x86/domain.c                        |  3 +-
 xen/arch/x86/mm.c                            |  6 ++--
 xen/arch/x86/setup.c                         |  8 +++--
 xen/common/domain.c                          |  7 +++--
 xen/common/domctl.c                          |  3 +-
 xen/common/schedule.c                        |  3 +-
 xen/include/public/arch-arm.h                |  8 +++++
 xen/include/public/arch-x86/xen.h            |  4 +++
 xen/include/public/domctl.h                  | 18 +----------
 xen/include/xen/domain.h                     |  3 +-
 xen/include/xen/sched.h                      |  9 ++++--
 xen/xsm/flask/hooks.c                        |  3 --
 xen/xsm/flask/policy/access_vectors          |  2 --
 27 files changed, 169 insertions(+), 122 deletions(-)

diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if
index 2d32e1c..620d151 100644
--- a/tools/flask/policy/policy/modules/xen/xen.if
+++ b/tools/flask/policy/policy/modules/xen/xen.if
@@ -51,7 +51,7 @@ define(`create_domain_common', `
 			getaffinity setaffinity setvcpuextstate };
 	allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim
 			set_max_evtchn set_vnumainfo get_vnumainfo cacheflush
-			psr_cmt_op configure_domain };
+			psr_cmt_op };
 	allow $1 $2:security check_context;
 	allow $1 $2:shadow enable;
 	allow $1 $2:mmu { map_read map_write adjust memorymap physmap pinpage mmuext_op updatemp };
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index df18292..60b61b6 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -477,18 +477,20 @@ typedef union
 } start_info_any_t;
 #endif
 
+
+typedef struct xen_arch_domainconfig xc_domain_configuration_t;
+int xc_domain_create_config(xc_interface *xch,
+                            uint32_t ssidref,
+                            xen_domain_handle_t handle,
+                            uint32_t flags,
+                            uint32_t *pdomid,
+                            xc_domain_configuration_t *config);
 int xc_domain_create(xc_interface *xch,
                      uint32_t ssidref,
                      xen_domain_handle_t handle,
                      uint32_t flags,
                      uint32_t *pdomid);
 
-#if defined(__arm__) || defined(__aarch64__)
-typedef xen_domctl_arm_configuredomain_t xc_domain_configuration_t;
-
-int xc_domain_configure(xc_interface *xch, uint32_t domid,
-                        xc_domain_configuration_t *config);
-#endif
 
 /* Functions to produce a dump of a given domain
  *  xc_domain_dumpcore - produces a dump to a specified file
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 845d1d7..448e958 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -27,11 +27,12 @@
 #include <xen/memory.h>
 #include <xen/hvm/hvm_op.h>
 
-int xc_domain_create(xc_interface *xch,
-                     uint32_t ssidref,
-                     xen_domain_handle_t handle,
-                     uint32_t flags,
-                     uint32_t *pdomid)
+int xc_domain_create_config(xc_interface *xch,
+                            uint32_t ssidref,
+                            xen_domain_handle_t handle,
+                            uint32_t flags,
+                            uint32_t *pdomid,
+                            xc_domain_configuration_t *config)
 {
     int err;
     DECLARE_DOMCTL;
@@ -41,32 +42,39 @@ int xc_domain_create(xc_interface *xch,
     domctl.u.createdomain.ssidref = ssidref;
     domctl.u.createdomain.flags   = flags;
     memcpy(domctl.u.createdomain.handle, handle, sizeof(xen_domain_handle_t));
+    /* xc_domain_configure_t is an alias of arch_domainconfig_t */
+    memcpy(&domctl.u.createdomain.config, config, sizeof(*config));
     if ( (err = do_domctl(xch, &domctl)) != 0 )
         return err;
 
     *pdomid = (uint16_t)domctl.domain;
+    memcpy(config, &domctl.u.createdomain.config, sizeof(*config));
+
     return 0;
 }
 
-#if defined(__arm__) || defined(__aarch64__)
-int xc_domain_configure(xc_interface *xch, uint32_t domid,
-                        xc_domain_configuration_t *config)
+int xc_domain_create(xc_interface *xch,
+                     uint32_t ssidref,
+                     xen_domain_handle_t handle,
+                     uint32_t flags,
+                     uint32_t *pdomid)
 {
-    int rc;
-    DECLARE_DOMCTL;
+    xc_domain_configuration_t config;
 
-    domctl.cmd = XEN_DOMCTL_arm_configure_domain;
-    domctl.domain = (domid_t)domid;
-    /* xc_domain_configure_t is an alias of xen_domctl_arm_configuredomain */
-    memcpy(&domctl.u.configuredomain, config, sizeof(*config));
+    memset(&config, 0, sizeof(config));
 
-    rc = do_domctl(xch, &domctl);
-    if ( !rc )
-        memcpy(config, &domctl.u.configuredomain, sizeof(*config));
+#if defined (__i386) || defined(__x86_64__)
+    /* No arch-specific configuration for now */
+#elif defined (__arm__) || defined(__aarch64__)
+    config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
 
-    return rc;
+    return xc_domain_create_config(xch, ssidref, handle,
+                                   flags, pdomid, &config);
 }
-#endif
 
 int xc_domain_cacheflush(xc_interface *xch, uint32_t domid,
                          xen_pfn_t start_pfn, xen_pfn_t nr_pfns)
diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
index e249048..cae64c0 100644
--- a/tools/libxl/libxl_arch.h
+++ b/tools/libxl/libxl_arch.h
@@ -15,6 +15,11 @@
 #ifndef LIBXL_ARCH_H
 #define LIBXL_ARCH_H
 
+/* fill the arch specific configuration for the domain */
+int libxl__arch_domain_prepare_config(libxl__gc *gc,
+                                      libxl_domain_config *d_config,
+                                      xc_domain_configuration_t *xc_config);
+
 /* arch specific internal domain creation function */
 int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
                uint32_t domid);
@@ -22,6 +27,7 @@ int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
 /* setup arch specific hardware description, i.e. DTB on ARM */
 int libxl__arch_domain_init_hw_description(libxl__gc *gc,
                                            libxl_domain_build_info *info,
+                                           libxl__domain_build_state *state,
                                            struct xc_dom_image *dom);
 /* finalize arch specific hardware description. */
 int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 7da254f..dc0919a 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -35,6 +35,15 @@ static const char *gicv_to_string(uint8_t gic_version)
     }
 }
 
+int libxl__arch_domain_prepare_config(libxl__gc *gc,
+                                      libxl_domain_config *d_config,
+                                      xc_domain_configuration_t *xc_config)
+{
+    xc_config->gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
+
+    return 0;
+}
+
 int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
                               uint32_t domid)
 {
@@ -516,9 +525,9 @@ out:
 
 int libxl__arch_domain_init_hw_description(libxl__gc *gc,
                                            libxl_domain_build_info *info,
+                                           libxl__domain_build_state *state,
                                            struct xc_dom_image *dom)
 {
-    xc_domain_configuration_t config;
     void *fdt = NULL;
     int rc, res;
     size_t fdt_size = 0;
@@ -526,6 +535,9 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc,
     const libxl_version_info *vers;
     const struct arch_info *ainfo;
 
+    /* convenience aliases */
+    xc_domain_configuration_t *xc_config = &state->config;
+
     assert(info->type == LIBXL_DOMAIN_TYPE_PV);
 
     vers = libxl_get_version_info(CTX);
@@ -534,16 +546,9 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc,
     ainfo = get_arch_info(gc, dom);
     if (ainfo == NULL) return ERROR_FAIL;
 
-    LOG(DEBUG, "configure the domain");
-    config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
-    if (xc_domain_configure(CTX->xch, dom->guest_domid, &config) != 0) {
-        LOG(ERROR, "couldn't configure the domain");
-        return ERROR_FAIL;
-    }
-
     LOG(DEBUG, "constructing DTB for Xen version %d.%d guest",
         vers->xen_version_major, vers->xen_version_minor);
-    LOG(DEBUG, "  - vGIC version: %s", gicv_to_string(config.gic_version));
+    LOG(DEBUG, " - vGIC version: %s\n", gicv_to_string(xc_config->gic_version));
 
 /*
  * Call "call" handling FDT_ERR_*. Will either:
@@ -592,7 +597,7 @@ next_resize:
 
         FDT( make_memory_nodes(gc, fdt, dom) );
 
-        switch (config.gic_version) {
+        switch (xc_config->gic_version) {
         case XEN_DOMCTL_CONFIG_GIC_V2:
             FDT( make_gicv2_node(gc, fdt,
                                  GUEST_GICD_BASE, GUEST_GICD_SIZE,
@@ -602,7 +607,8 @@ next_resize:
             FDT( make_gicv3_node(gc, fdt) );
             break;
         default:
-            LOG(ERROR, "Unknown GIC version %d", config.gic_version);
+            LOG(ERROR, "Unknown GIC version %s",
+                gicv_to_string(xc_config->gic_version));
             rc = ERROR_FAIL;
             goto out;
         }
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index af04248..e5a343f 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -497,8 +497,8 @@ out:
     return ret;
 }
 
-int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
-                       uint32_t *domid)
+int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
+                       uint32_t *domid, xc_domain_configuration_t *xc_config)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
     int flags, ret, rc, nb_vm;
@@ -511,6 +511,8 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
     xen_domain_handle_t handle;
     libxl_vminfo *vm_list;
 
+    /* convenience aliases */
+    libxl_domain_create_info *info = &d_config->c_info;
 
     assert(!libxl_domid_valid_guest(*domid));
 
@@ -539,7 +541,16 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
     /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
     libxl_uuid_copy(ctx, (libxl_uuid *)handle, &info->uuid);
 
-    ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
+    ret = libxl__arch_domain_prepare_config(gc, d_config, xc_config);
+    if (ret < 0) {
+        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "fail to get domain config");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    ret = xc_domain_create_config(ctx->xch, info->ssidref,
+                                  handle, flags, domid,
+                                  xc_config);
     if (ret < 0) {
         LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "domain creation fail");
         rc = ERROR_FAIL;
@@ -772,6 +783,7 @@ static void initiate_domain_create(libxl__egc *egc,
 
     /* convenience aliases */
     libxl_domain_config *const d_config = dcs->guest_config;
+    libxl__domain_build_state *const state = &dcs->build_state;
     const int restore_fd = dcs->restore_fd;
     memset(&dcs->build_state, 0, sizeof(dcs->build_state));
 
@@ -865,7 +877,7 @@ static void initiate_domain_create(libxl__egc *egc,
     ret = libxl__domain_create_info_setdefault(gc, &d_config->c_info);
     if (ret) goto error_out;
 
-    ret = libxl__domain_make(gc, &d_config->c_info, &domid);
+    ret = libxl__domain_make(gc, d_config, &domid, &state->config);
     if (ret) {
         LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot make domain: %d", ret);
         dcs->guest_domid = domid;
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index fc88d68..4c1ab6c 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -1089,7 +1089,8 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
     stubdom_state->pv_ramdisk.path = "";
 
     /* fixme: this function can leak the stubdom if it fails */
-    ret = libxl__domain_make(gc, &dm_config->c_info, &sdss->pvqemu.guest_domid);
+    ret = libxl__domain_make(gc, dm_config, &sdss->pvqemu.guest_domid,
+                             &stubdom_state->config);
     if (ret)
         goto out;
     uint32_t dm_domid = sdss->pvqemu.guest_domid;
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index ace8a66..dc92da4 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -663,7 +663,7 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid,
         LOGE(ERROR, "xc_dom_parse_image failed");
         goto out;
     }
-    if ( (ret = libxl__arch_domain_init_hw_description(gc, info, dom)) != 0 ) {
+    if ( (ret = libxl__arch_domain_init_hw_description(gc, info, state, dom)) != 0 ) {
         LOGE(ERROR, "libxl__arch_domain_init_hw_description failed");
         goto out;
     }
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index d2b19a0..46fa624 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -992,6 +992,8 @@ typedef struct {
 
     xen_vmemrange_t *vmemranges;
     uint32_t num_vmemranges;
+
+    xc_domain_configuration_t config;
 } libxl__domain_build_state;
 
 _hidden int libxl__build_pre(libxl__gc *gc, uint32_t domid,
@@ -1481,8 +1483,9 @@ _hidden  void libxl__exec(libxl__gc *gc, int stdinfd, int stdoutfd,
  /* on entry, libxl_domid_valid_guest(domid) must be false;
   * on exit (even error exit), domid may be valid and refer to a domain */
 _hidden int libxl__domain_make(libxl__gc *gc,
-                               libxl_domain_create_info *info,
-                               uint32_t *domid);
+                               libxl_domain_config *d_config,
+                               uint32_t *domid,
+                               xc_domain_configuration_t *xc_config);
 
 _hidden int libxl__domain_build(libxl__gc *gc,
                                 libxl_domain_config *d_config,
diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
index fd45ead..3149896 100644
--- a/tools/libxl/libxl_x86.c
+++ b/tools/libxl/libxl_x86.c
@@ -1,6 +1,15 @@
 #include "libxl_internal.h"
 #include "libxl_arch.h"
 
+int libxl__arch_domain_prepare_config(libxl__gc *gc,
+                                      libxl_domain_config *d_config,
+                                      xc_domain_configuration_t *xc_config)
+{
+    /* No specific configuration right now */
+
+    return 0;
+}
+
 static const char *e820_names(int type)
 {
     switch (type) {
@@ -327,6 +336,7 @@ int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
 
 int libxl__arch_domain_init_hw_description(libxl__gc *gc,
                                            libxl_domain_build_info *info,
+                                           libxl__domain_build_state *state,
                                            struct xc_dom_image *dom)
 {
     return 0;
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index fdba081..ce9f349 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -503,9 +503,11 @@ void vcpu_destroy(struct vcpu *v)
     free_xenheap_pages(v->arch.stack, STACK_ORDER);
 }
 
-int arch_domain_create(struct domain *d, unsigned int domcr_flags)
+int arch_domain_create(struct domain *d, unsigned int domcr_flags,
+                       struct xen_arch_domainconfig *config)
 {
     int rc;
+    uint8_t gic_version;
 
     d->arch.relmem = RELMEM_not_started;
 
@@ -513,6 +515,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
     if ( is_idle_domain(d) )
         return 0;
 
+    ASSERT(config != NULL);
     if ( (rc = p2m_init(d)) != 0 )
         goto fail;
 
@@ -533,6 +536,29 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
     if ( (rc = p2m_alloc_table(d)) != 0 )
         goto fail;
 
+    /*
+     * Currently the vGIC is emulating the same version of the
+     * hardware GIC. Only the value XEN_DOMCTL_CONFIG_GIC_DEFAULT
+     * is allowed. The DOMCTL will return the actual version of the
+     * GIC.
+     */
+    rc = -EOPNOTSUPP;
+    if ( config->gic_version != XEN_DOMCTL_CONFIG_GIC_DEFAULT )
+        goto fail;
+
+    switch ( gic_hw_version() )
+    {
+    case GIC_V3:
+        gic_version = XEN_DOMCTL_CONFIG_GIC_V3;
+        break;
+    case GIC_V2:
+        gic_version = XEN_DOMCTL_CONFIG_GIC_V2;
+        break;
+    default:
+        BUG();
+    }
+    config->gic_version = gic_version;
+
     if ( (rc = gicv_setup(d)) != 0 )
         goto fail;
 
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index d246e84..6f30af7 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -10,8 +10,6 @@
 #include <xen/errno.h>
 #include <xen/sched.h>
 #include <xen/hypercall.h>
-#include <asm/gic.h>
-#include <xen/guest_access.h>
 #include <public/domctl.h>
 
 long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
@@ -32,40 +30,6 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
 
         return p2m_cache_flush(d, s, e);
     }
-    case XEN_DOMCTL_arm_configure_domain:
-    {
-        uint8_t gic_version;
-
-        /*
-         * Currently the vGIC is emulating the same version of the
-         * hardware GIC. Only the value XEN_DOMCTL_CONFIG_GIC_DEFAULT
-         * is allowed. The DOMCTL will return the actual version of the
-         * GIC.
-         */
-        if ( domctl->u.configuredomain.gic_version != XEN_DOMCTL_CONFIG_GIC_DEFAULT )
-            return -EOPNOTSUPP;
-
-        switch ( gic_hw_version() )
-        {
-        case GIC_V3:
-            gic_version = XEN_DOMCTL_CONFIG_GIC_V3;
-            break;
-        case GIC_V2:
-            gic_version = XEN_DOMCTL_CONFIG_GIC_V2;
-            break;
-        default:
-            BUG();
-        }
-
-        domctl->u.configuredomain.gic_version = gic_version;
-
-        /* TODO: Make the copy generic for all ARCH domctl */
-        if ( __copy_to_guest(u_domctl, domctl, 1) )
-            return -EFAULT;
-
-        return 0;
-    }
-
     default:
         return subarch_do_domctl(domctl, d, u_domctl);
     }
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 7d4ba0c..9128af1 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -399,7 +399,7 @@ void __init arch_init_memory(void)
      * Any Xen-heap pages that we will allow to be mapped will have
      * their domain field set to dom_xen.
      */
-    dom_xen = domain_create(DOMID_XEN, DOMCRF_dummy, 0);
+    dom_xen = domain_create(DOMID_XEN, DOMCRF_dummy, 0, NULL);
     BUG_ON(IS_ERR(dom_xen));
 
     /*
@@ -407,14 +407,14 @@ void __init arch_init_memory(void)
      * This domain owns I/O pages that are within the range of the page_info
      * array. Mappings occur at the priv of the caller.
      */
-    dom_io = domain_create(DOMID_IO, DOMCRF_dummy, 0);
+    dom_io = domain_create(DOMID_IO, DOMCRF_dummy, 0, NULL);
     BUG_ON(IS_ERR(dom_io));
 
     /*
      * Initialise our COW domain.
      * This domain owns sharable pages.
      */
-    dom_cow = domain_create(DOMID_COW, DOMCRF_dummy, 0);
+    dom_cow = domain_create(DOMID_COW, DOMCRF_dummy, 0, NULL);
     BUG_ON(IS_ERR(dom_cow));
 }
 
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 4f05f57..defe39e 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -710,6 +710,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     const char *cmdline;
     struct bootmodule *xen_bootmodule;
     struct domain *dom0;
+    struct xen_arch_domainconfig config;
 
     setup_cache();
 
@@ -827,7 +828,10 @@ void __init start_xen(unsigned long boot_phys_offset,
     do_initcalls();
 
     /* Create initial domain 0. */
-    dom0 = domain_create(0, 0, 0);
+    /* The vGIC for DOM0 is exactly emulated the hardware GIC */
+    config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
+
+    dom0 = domain_create(0, 0, 0, &config);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
             panic("Error creating domain 0");
 
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 04c1898..4ad4d19 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -507,7 +507,8 @@ void vcpu_destroy(struct vcpu *v)
         xfree(v->arch.pv_vcpu.trap_ctxt);
 }
 
-int arch_domain_create(struct domain *d, unsigned int domcr_flags)
+int arch_domain_create(struct domain *d, unsigned int domcr_flags,
+                       struct xen_arch_domainconfig *config)
 {
     int i, paging_initialised = 0;
     int rc = -ENOMEM;
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 45acfb5..7d9d446 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -275,7 +275,7 @@ void __init arch_init_memory(void)
      * Hidden PCI devices will also be associated with this domain
      * (but be [partly] controlled by Dom0 nevertheless).
      */
-    dom_xen = domain_create(DOMID_XEN, DOMCRF_dummy, 0);
+    dom_xen = domain_create(DOMID_XEN, DOMCRF_dummy, 0, NULL);
     BUG_ON(IS_ERR(dom_xen));
     INIT_LIST_HEAD(&dom_xen->arch.pdev_list);
 
@@ -284,14 +284,14 @@ void __init arch_init_memory(void)
      * This domain owns I/O pages that are within the range of the page_info
      * array. Mappings occur at the priv of the caller.
      */
-    dom_io = domain_create(DOMID_IO, DOMCRF_dummy, 0);
+    dom_io = domain_create(DOMID_IO, DOMCRF_dummy, 0, NULL);
     BUG_ON(IS_ERR(dom_io));
     
     /*
      * Initialise our COW domain.
      * This domain owns sharable pages.
      */
-    dom_cow = domain_create(DOMID_COW, DOMCRF_dummy, 0);
+    dom_cow = domain_create(DOMID_COW, DOMCRF_dummy, 0, NULL);
     BUG_ON(IS_ERR(dom_cow));
 
     /* First 1MB of RAM is historically marked as I/O. */
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 384df03..f0cc8d5 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1360,8 +1360,12 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     if ( opt_dom0pvh )
         domcr_flags |= DOMCRF_pvh | DOMCRF_hap;
 
-    /* Create initial domain 0. */
-    dom0 = domain_create(0, domcr_flags, 0);
+    /*
+     * Create initial domain 0.
+     * x86 doesn't support arch-configuration. So it's fine to pass
+     * NULL.
+     */
+    dom0 = domain_create(0, domcr_flags, 0, NULL);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
         panic("Error creating domain 0");
 
diff --git a/xen/common/domain.c b/xen/common/domain.c
index aa78fd7..fcf8a38 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -242,8 +242,9 @@ static void __init parse_extra_guest_irqs(const char *s)
 }
 custom_param("extra_guest_irqs", parse_extra_guest_irqs);
 
-struct domain *domain_create(
-    domid_t domid, unsigned int domcr_flags, uint32_t ssidref)
+struct domain *domain_create(domid_t domid, unsigned int domcr_flags,
+                             uint32_t ssidref,
+                             struct xen_arch_domainconfig *config)
 {
     struct domain *d, **pd, *old_hwdom = NULL;
     enum { INIT_xsm = 1u<<0, INIT_watchdog = 1u<<1, INIT_rangeset = 1u<<2,
@@ -353,7 +354,7 @@ struct domain *domain_create(
             goto fail;
     }
 
-    if ( (err = arch_domain_create(d, domcr_flags)) != 0 )
+    if ( (err = arch_domain_create(d, domcr_flags, config)) != 0 )
         goto fail;
     init_status |= INIT_arch;
 
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index d396cc4..f0ba67d 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -589,7 +589,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
         if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_oos_off )
             domcr_flags |= DOMCRF_oos_off;
 
-        d = domain_create(dom, domcr_flags, op->u.createdomain.ssidref);
+        d = domain_create(dom, domcr_flags, op->u.createdomain.ssidref,
+                          &op->u.createdomain.config);
         if ( IS_ERR(d) )
         {
             ret = PTR_ERR(d);
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index ef79847..967c8d4 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -1419,7 +1419,8 @@ void __init scheduler_init(void)
         sched_ratelimit_us = SCHED_DEFAULT_RATELIMIT_US;
     }
 
-    idle_domain = domain_create(DOMID_IDLE, 0, 0);
+    /* There is no need of arch-specific configuration for an idle domain */
+    idle_domain = domain_create(DOMID_IDLE, 0, 0, NULL);
     BUG_ON(IS_ERR(idle_domain));
     idle_domain->vcpu = idle_vcpu;
     idle_domain->max_vcpus = nr_cpu_ids;
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index c2dcb66..ed7e98f 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -309,6 +309,14 @@ struct arch_shared_info {
 typedef struct arch_shared_info arch_shared_info_t;
 typedef uint64_t xen_callback_t;
 
+#define XEN_DOMCTL_CONFIG_GIC_DEFAULT   0
+#define XEN_DOMCTL_CONFIG_GIC_V2        1
+#define XEN_DOMCTL_CONFIG_GIC_V3        2
+struct xen_arch_domainconfig {
+    /* IN/OUT */
+    uint8_t gic_version;
+};
+
 #endif
 
 #if defined(__XEN__) || defined(__XEN_TOOLS__)
diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h
index 232d4a5..cea3fe7 100644
--- a/xen/include/public/arch-x86/xen.h
+++ b/xen/include/public/arch-x86/xen.h
@@ -262,6 +262,10 @@ struct arch_shared_info {
 };
 typedef struct arch_shared_info arch_shared_info_t;
 
+struct xen_arch_domainconfig {
+    char dummy;
+};
+
 #endif /* !__ASSEMBLY__ */
 
 /*
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index ca0e51e..d6c1ec7 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -64,23 +64,11 @@ struct xen_domctl_createdomain {
 #define _XEN_DOMCTL_CDF_pvh_guest     4
 #define XEN_DOMCTL_CDF_pvh_guest      (1U<<_XEN_DOMCTL_CDF_pvh_guest)
     uint32_t flags;
+    struct xen_arch_domainconfig config;
 };
 typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t);
 
-#if defined(__arm__) || defined(__aarch64__)
-#define XEN_DOMCTL_CONFIG_GIC_DEFAULT   0
-#define XEN_DOMCTL_CONFIG_GIC_V2        1
-#define XEN_DOMCTL_CONFIG_GIC_V3        2
-/* XEN_DOMCTL_configure_domain */
-struct xen_domctl_arm_configuredomain {
-    /* IN/OUT parameters */
-    uint8_t gic_version;
-};
-typedef struct xen_domctl_arm_configuredomain xen_domctl_arm_configuredomain_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_arm_configuredomain_t);
-#endif
-
 /* XEN_DOMCTL_getdomaininfo */
 struct xen_domctl_getdomaininfo {
     /* OUT variables. */
@@ -1079,7 +1067,6 @@ struct xen_domctl {
 #define XEN_DOMCTL_set_vcpu_msrs                 73
 #define XEN_DOMCTL_setvnumainfo                  74
 #define XEN_DOMCTL_psr_cmt_op                    75
-#define XEN_DOMCTL_arm_configure_domain          76
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -1088,9 +1075,6 @@ struct xen_domctl {
     domid_t  domain;
     union {
         struct xen_domctl_createdomain      createdomain;
-#if defined(__arm__) || defined(__aarch64__)
-        struct xen_domctl_arm_configuredomain configuredomain;
-#endif
         struct xen_domctl_getdomaininfo     getdomaininfo;
         struct xen_domctl_getmemlist        getmemlist;
         struct xen_domctl_getpageframeinfo  getpageframeinfo;
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 920f524..848db8a 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -56,7 +56,8 @@ void vcpu_destroy(struct vcpu *v);
 int map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset);
 void unmap_vcpu_info(struct vcpu *v);
 
-int arch_domain_create(struct domain *d, unsigned int domcr_flags);
+int arch_domain_create(struct domain *d, unsigned int domcr_flags,
+                       struct xen_arch_domainconfig *config);
 
 void arch_domain_destroy(struct domain *d);
 
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index ccd7ed8..e9b6ef7 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -525,8 +525,13 @@ static inline void get_knownalive_domain(struct domain *d)
 int domain_set_node_affinity(struct domain *d, const nodemask_t *affinity);
 void domain_update_node_affinity(struct domain *d);
 
-struct domain *domain_create(
-    domid_t domid, unsigned int domcr_flags, uint32_t ssidref);
+/*
+ * Create a domain: the configuration is only necessary for real domain
+ * (i.e !DOMCRF_dummy, excluded idle domain).
+ */
+struct domain *domain_create(domid_t domid, unsigned int domcr_flags,
+                             uint32_t ssidref,
+                             struct xen_arch_domainconfig *config);
  /* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */
 #define _DOMCRF_hvm           0
 #define DOMCRF_hvm            (1U<<_DOMCRF_hvm)
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 05dafedd..b453605 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -729,9 +729,6 @@ static int flask_domctl(struct domain *d, int cmd)
     case XEN_DOMCTL_psr_cmt_op:
         return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__PSR_CMT_OP);
 
-    case XEN_DOMCTL_arm_configure_domain:
-        return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__CONFIGURE_DOMAIN);
-
     default:
         printk("flask_domctl: Unknown op %d\n", cmd);
         return -EPERM;
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index 8f44b9d..3451f8f 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -219,8 +219,6 @@ class domain2
     get_vnumainfo
 # XEN_DOMCTL_psr_cmt_op
     psr_cmt_op
-# XEN_DOMCTL_configure_domain
-    configure_domain
 }
 
 # Similar to class domain, but primarily contains domctls related to HVM domains
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 10/33] xen/arm: Allow virq != irq
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (8 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 09/33] xen: Extend DOMCTL createdomain to support arch configuration Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:41   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
                   ` (24 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

Currently, Xen is assuming that the virtual IRQ will always be the same
as IRQ.

Modify route_guest_irq to take the virtual IRQ in parameter which allow
Xen to assign a different IRQ number. Also store the vIRQ in the desc
action to easily retrieve the IRQ target when we need to inject the
interrupt.

As DOM0 will get most the devices, the vIRQ is equal to the IRQ in that case.

At the same time modify the behavior of irq_get_domain. The function now
requires that the irq_desc belongs to an IRQ assigned to a guest.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

---
    Changes in v4:
        - Add Stefano's ack
        - Typoes and rewording the commit message

    Changes in v3
        - Spelling/grammar nits
        - Fix compilation on ARM64. Forgot to update route_irq_to_guest
          call for xgene platform.
        - Add a word about irq_get_domain behavior change
        - More s/irq/virq/ because of the rebasing on the latest staging

    Changes in v2:
        - Patch added
---
 xen/arch/arm/domain_build.c          |  2 +-
 xen/arch/arm/gic.c                   |  5 ++--
 xen/arch/arm/irq.c                   | 47 ++++++++++++++++++++++++++----------
 xen/arch/arm/platforms/xgene-storm.c |  2 +-
 xen/arch/arm/vgic.c                  | 20 +++++++--------
 xen/include/asm-arm/gic.h            |  3 ++-
 xen/include/asm-arm/irq.h            |  4 +--
 xen/include/asm-arm/vgic.h           |  4 +--
 8 files changed, 55 insertions(+), 32 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 2eb31ad..24a0242 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1020,7 +1020,7 @@ static int handle_device(struct domain *d, struct dt_device_node *dev)
              * twice the IRQ. This can happen if the IRQ is shared
              */
             vgic_reserve_virq(d, irq);
-            res = route_irq_to_guest(d, irq, dt_node_name(dev));
+            res = route_irq_to_guest(d, irq, irq, dt_node_name(dev));
             if ( res )
             {
                 printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index ba7950b..fe8f69b 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -126,7 +126,8 @@ void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
 /* Program the GIC to route an interrupt to a guest
  *   - desc.lock must be held
  */
-void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
+void gic_route_irq_to_guest(struct domain *d, unsigned int virq,
+                            struct irq_desc *desc,
                             const cpumask_t *cpu_mask, unsigned int priority)
 {
     struct pending_irq *p;
@@ -139,7 +140,7 @@ void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
 
     /* Use vcpu0 to retrieve the pending_irq struct. Given that we only
      * route SPIs to guests, it doesn't make any difference. */
-    p = irq_to_pending(d->vcpu[0], desc->irq);
+    p = irq_to_pending(d->vcpu[0], virq);
     p->desc = desc;
 }
 
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index cb9c99b..beb746a 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -31,6 +31,13 @@
 static unsigned int local_irqs_type[NR_LOCAL_IRQS];
 static DEFINE_SPINLOCK(local_irqs_type_lock);
 
+/* Describe an IRQ assigned to a guest */
+struct irq_guest
+{
+    struct domain *d;
+    unsigned int virq;
+};
+
 static void ack_none(struct irq_desc *irq)
 {
     printk("unexpected IRQ trap at irq %02x\n", irq->irq);
@@ -122,18 +129,20 @@ void __cpuinit init_secondary_IRQ(void)
     BUG_ON(init_local_irq_data() < 0);
 }
 
-static inline struct domain *irq_get_domain(struct irq_desc *desc)
+static inline struct irq_guest *irq_get_guest_info(struct irq_desc *desc)
 {
     ASSERT(spin_is_locked(&desc->lock));
-
-    if ( !test_bit(_IRQ_GUEST, &desc->status) )
-        return dom_xen;
-
+    ASSERT(test_bit(_IRQ_GUEST, &desc->status));
     ASSERT(desc->action != NULL);
 
     return desc->action->dev_id;
 }
 
+static inline struct domain *irq_get_domain(struct irq_desc *desc)
+{
+    return irq_get_guest_info(desc)->d;
+}
+
 void irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask)
 {
     if ( desc != NULL )
@@ -204,7 +213,7 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
 
     if ( test_bit(_IRQ_GUEST, &desc->status) )
     {
-        struct domain *d = irq_get_domain(desc);
+        struct irq_guest *info = irq_get_guest_info(desc);
 
         perfc_incr(guest_irqs);
         desc->handler->end(desc);
@@ -214,7 +223,7 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
 
         /* the irq cannot be a PPI, we only support delivery of SPIs to
          * guests */
-        vgic_vcpu_inject_spi(d, irq);
+        vgic_vcpu_inject_spi(info->d, info->virq);
         goto out_no_end;
     }
 
@@ -378,19 +387,30 @@ err:
     return rc;
 }
 
-int route_irq_to_guest(struct domain *d, unsigned int irq,
-                       const char * devname)
+int route_irq_to_guest(struct domain *d, unsigned int virq,
+                       unsigned int irq, const char * devname)
 {
     struct irqaction *action;
-    struct irq_desc *desc = irq_to_desc(irq);
+    struct irq_guest *info;
+    struct irq_desc *desc;
     unsigned long flags;
     int retval = 0;
 
     action = xmalloc(struct irqaction);
-    if (!action)
+    if ( !action )
+        return -ENOMEM;
+
+    info = xmalloc(struct irq_guest);
+    if ( !info )
+    {
+        xfree(action);
         return -ENOMEM;
+    }
+
+    info->d = d;
+    info->virq = virq;
 
-    action->dev_id = d;
+    action->dev_id = info;
     action->name = devname;
     action->free_on_release = 1;
 
@@ -421,7 +441,7 @@ int route_irq_to_guest(struct domain *d, unsigned int irq,
     if ( retval )
         goto out;
 
-    gic_route_irq_to_guest(d, desc, cpumask_of(smp_processor_id()),
+    gic_route_irq_to_guest(d, virq, desc, cpumask_of(smp_processor_id()),
                            GIC_PRI_IRQ);
     spin_unlock_irqrestore(&desc->lock, flags);
     return 0;
@@ -429,6 +449,7 @@ int route_irq_to_guest(struct domain *d, unsigned int irq,
 out:
     spin_unlock_irqrestore(&desc->lock, flags);
     xfree(action);
+    xfree(info);
 
     return retval;
 }
diff --git a/xen/arch/arm/platforms/xgene-storm.c b/xen/arch/arm/platforms/xgene-storm.c
index eee650e..1812e5b 100644
--- a/xen/arch/arm/platforms/xgene-storm.c
+++ b/xen/arch/arm/platforms/xgene-storm.c
@@ -75,7 +75,7 @@ static int map_one_spi(struct domain *d, const char *what,
         printk("Failed to reserve vIRQ %u on dom%d\n",
                irq, d->domain_id);
 
-    ret = route_irq_to_guest(d, irq, what);
+    ret = route_irq_to_guest(d, irq, irq, what);
     if ( ret )
         printk("Failed to route %s to dom%d\n", what, d->domain_id);
 
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 0b4fa57..c07822f 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -382,16 +382,16 @@ void vgic_clear_pending_irqs(struct vcpu *v)
     spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
 }
 
-void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
+void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq)
 {
     uint8_t priority;
-    struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
-    struct pending_irq *iter, *n = irq_to_pending(v, irq);
+    struct vgic_irq_rank *rank = vgic_rank_irq(v, virq);
+    struct pending_irq *iter, *n = irq_to_pending(v, virq);
     unsigned long flags;
     bool_t running;
 
     vgic_lock_rank(v, rank, flags);
-    priority = v->domain->arch.vgic.handler->get_irq_priority(v, irq);
+    priority = v->domain->arch.vgic.handler->get_irq_priority(v, virq);
     vgic_unlock_rank(v, rank, flags);
 
     spin_lock_irqsave(&v->arch.vgic.lock, flags);
@@ -407,7 +407,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
 
     if ( !list_empty(&n->inflight) )
     {
-        gic_raise_inflight_irq(v, irq);
+        gic_raise_inflight_irq(v, virq);
         goto out;
     }
 
@@ -415,7 +415,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
 
     /* the irq is enabled */
     if ( test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) )
-        gic_raise_guest_irq(v, irq, priority);
+        gic_raise_guest_irq(v, virq, priority);
 
     list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight )
     {
@@ -438,15 +438,15 @@ out:
     }
 }
 
-void vgic_vcpu_inject_spi(struct domain *d, unsigned int irq)
+void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq)
 {
     struct vcpu *v;
 
     /* the IRQ needs to be an SPI */
-    ASSERT(irq >= 32 && irq <= gic_number_lines());
+    ASSERT(virq >= 32 && virq <= vgic_num_irqs(d));
 
-    v = vgic_get_target_vcpu(d->vcpu[0], irq);
-    vgic_vcpu_inject_irq(v, irq);
+    v = vgic_get_target_vcpu(d->vcpu[0], virq);
+    vgic_vcpu_inject_irq(v, virq);
 }
 
 void arch_evtchn_inject(struct vcpu *v)
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index b16f98e..bb2a922 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -216,7 +216,8 @@ extern enum gic_version gic_hw_version(void);
 /* Program the GIC to route an interrupt */
 extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
                                  unsigned int priority);
-extern void gic_route_irq_to_guest(struct domain *, struct irq_desc *desc,
+extern void gic_route_irq_to_guest(struct domain *, unsigned int virq,
+                                   struct irq_desc *desc,
                                    const cpumask_t *cpu_mask,
                                    unsigned int priority);
 
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 435dfcd..f00eb11 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -40,8 +40,8 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
 void init_IRQ(void);
 void init_secondary_IRQ(void);
 
-int route_irq_to_guest(struct domain *d, unsigned int irq,
-                       const char *devname);
+int route_irq_to_guest(struct domain *d, unsigned int virq,
+                       unsigned int irq, const char *devname);
 void arch_move_irqs(struct vcpu *v);
 
 /* Set IRQ type for an SPI */
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 0d0d114..aba0d80 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -181,8 +181,8 @@ extern int domain_vgic_init(struct domain *d);
 extern void domain_vgic_free(struct domain *d);
 extern int vcpu_vgic_init(struct vcpu *v);
 extern struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int irq);
-extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq);
-extern void vgic_vcpu_inject_spi(struct domain *d, unsigned int irq);
+extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq);
+extern void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq);
 extern void vgic_clear_pending_irqs(struct vcpu *v);
 extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
 extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, int s);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (9 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 10/33] xen/arm: Allow virq != irq Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-20 11:36   ` Stefano Stabellini
  2015-03-31 10:43   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 12/33] xen/arm: gic: Add sanity checks gic_route_irq_to_guest Julien Grall
                   ` (23 subsequent siblings)
  34 siblings, 2 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

Currently Xen only supports SPIs routing for guest, add a function
is_assignable_irq to check if we can assign a given IRQ to the guest.

Secondly, make sure the vIRQ is not the greater that the number of IRQs
configured in the vGIC and it's an SPI.

Thirdly, when the IRQ is already assigned to the domain, check the user
is not asking to use a different vIRQ than the one already bound.

Finally, desc->arch.type which contains the IRQ type (i.e level/edge) must
be correctly configured before. The misconfiguration can happen when:
    - the device has been blacklisted for the current platform
    - the IRQ has not been described in the device tree

Also, use XENLOG_G_ERR in the error message within the function as it will
be later called from a guest.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Changes in v4:
        - Use NR_LOCAL_IRQS rather than 32
        - Move the check to the IRQ and irq_to_desc after the vIRQ check
        - Typoes and rewording the commit message and in the patch
        - Use printk rather than dprintk.

    Changes in v3:
        - Fix typo in commit message and comment
        - Add a check that the vIRQ is an SPI
        - Check if the user is not asking for a different vIRQ when the
        IRQ is already assigned to the guest

    Changes in v2:
        - Rename is_routable_irq into is_assignable_irq
        - Check if the IRQ is not greater than the number handled by the
        number of IRQs handled by the gic
        - Move is_assignable_irq in irq.c rather than defining in the
        header irq.h
        - Retrieve the irq descriptor after checking the validity of the
        IRQ
        - vgic_num_irqs has been moved in a separate patch
        - Fix the irq check against vgic_num_irqs
        - Use virq instead of irq for vGIC sanity check
---
 xen/arch/arm/irq.c        | 59 +++++++++++++++++++++++++++++++++++++++++++----
 xen/include/asm-arm/irq.h |  2 ++
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index beb746a..4c3e381 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -387,6 +387,16 @@ err:
     return rc;
 }
 
+bool_t is_assignable_irq(unsigned int irq)
+{
+    /* For now, we can only route SPIs to the guest */
+    return ((irq >= NR_LOCAL_IRQS) && (irq < gic_number_lines()));
+}
+
+/*
+ * Route an IRQ to a specific guest.
+ * For now only SPIs are assignable to the guest.
+ */
 int route_irq_to_guest(struct domain *d, unsigned int virq,
                        unsigned int irq, const char * devname)
 {
@@ -396,6 +406,28 @@ int route_irq_to_guest(struct domain *d, unsigned int virq,
     unsigned long flags;
     int retval = 0;
 
+    if ( virq >= vgic_num_irqs(d) )
+    {
+        printk(XENLOG_G_ERR
+               "the vIRQ number %u is too high for domain %u (max = %u)\n",
+               irq, d->domain_id, vgic_num_irqs(d));
+        return -EINVAL;
+    }
+
+    /* Only routing to virtual SPIs is supported */
+    if ( virq < NR_LOCAL_IRQS )
+    {
+        printk(XENLOG_G_ERR "IRQ can only be routed to an SPI");
+        return -EINVAL;
+    }
+
+    if ( !is_assignable_irq(irq) )
+    {
+        printk(XENLOG_G_ERR "the IRQ%u is not routable\n", irq);
+        return -EINVAL;
+    }
+    desc = irq_to_desc(irq);
+
     action = xmalloc(struct irqaction);
     if ( !action )
         return -ENOMEM;
@@ -416,8 +448,18 @@ int route_irq_to_guest(struct domain *d, unsigned int virq,
 
     spin_lock_irqsave(&desc->lock, flags);
 
-    /* If the IRQ is already used by someone
-     *  - If it's the same domain -> Xen doesn't need to update the IRQ desc
+    if ( desc->arch.type == DT_IRQ_TYPE_INVALID )
+    {
+        printk(XENLOG_G_ERR "IRQ %u has not been configured\n", irq);
+        retval = -EIO;
+        goto out;
+    }
+
+    /*
+     * If the IRQ is already used by someone
+     *  - If it's the same domain -> Xen doesn't need to update the IRQ desc.
+     *  For safety check if we are not trying to assign the IRQ to a
+     *  different vIRQ.
      *  - Otherwise -> For now, don't allow the IRQ to be shared between
      *  Xen and domains.
      */
@@ -426,13 +468,22 @@ int route_irq_to_guest(struct domain *d, unsigned int virq,
         struct domain *ad = irq_get_domain(desc);
 
         if ( test_bit(_IRQ_GUEST, &desc->status) && d == ad )
+        {
+            if ( irq_get_guest_info(desc)->virq != virq )
+            {
+                printk(XENLOG_G_ERR
+                       "d%u: IRQ %u is already assigned to vIRQ %u\n",
+                       d->domain_id, irq, irq_get_guest_info(desc)->virq);
+                retval = -EBUSY;
+            }
             goto out;
+        }
 
         if ( test_bit(_IRQ_GUEST, &desc->status) )
-            printk(XENLOG_ERR "ERROR: IRQ %u is already used by domain %u\n",
+            printk(XENLOG_G_ERR "IRQ %u is already used by domain %u\n",
                    irq, ad->domain_id);
         else
-            printk(XENLOG_ERR "ERROR: IRQ %u is already used by Xen\n", irq);
+            printk(XENLOG_G_ERR "IRQ %u is already used by Xen\n", irq);
         retval = -EBUSY;
         goto out;
     }
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index f00eb11..71b39e7 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -37,6 +37,8 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
 
 #define domain_pirq_to_irq(d, pirq) (pirq)
 
+bool_t is_assignable_irq(unsigned int irq);
+
 void init_IRQ(void);
 void init_secondary_IRQ(void);
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 12/33] xen/arm: gic: Add sanity checks gic_route_irq_to_guest
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (10 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:44   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
                   ` (22 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

With the addition of interrupt assignment to guest, we need to make sure
the guest can't blow up the interrupt management in Xen.

Before associating the IRQ to a vIRQ we need to make sure:
    - the vIRQ is not already associated to another IRQ
    - the guest didn't enable the vIRQ

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

---
    Changes in v4:
        - Move functional change (GIC_IRQ_PRI -> priority) in a separate
        patch.
        - Split the 2 conditions of the ASSERT in 2 different ASSERTs
        - Typoes
        - Add Stefano's ack

    Changes in v3:
        - Patch added
---
 xen/arch/arm/gic.c        | 35 +++++++++++++++++++++++++++--------
 xen/arch/arm/irq.c        | 12 ++++++++++--
 xen/include/asm-arm/gic.h |  7 +++----
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index fe8f69b..2709415 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -126,22 +126,41 @@ void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
 /* Program the GIC to route an interrupt to a guest
  *   - desc.lock must be held
  */
-void gic_route_irq_to_guest(struct domain *d, unsigned int virq,
-                            struct irq_desc *desc,
-                            const cpumask_t *cpu_mask, unsigned int priority)
+int gic_route_irq_to_guest(struct domain *d, unsigned int virq,
+                           struct irq_desc *desc, unsigned int priority)
 {
-    struct pending_irq *p;
+    unsigned long flags;
+    /* Use vcpu0 to retrieve the pending_irq struct. Given that we only
+     * route SPIs to guests, it doesn't make any difference. */
+    struct vcpu *v_target = vgic_get_target_vcpu(d->vcpu[0], virq);
+    struct vgic_irq_rank *rank = vgic_rank_irq(v_target, virq);
+    struct pending_irq *p = irq_to_pending(v_target, virq);
+    int res = -EBUSY;
+
     ASSERT(spin_is_locked(&desc->lock));
+    /* Caller has already checked that the IRQ is an SPI */
+    ASSERT(virq >= 32);
+    ASSERT(virq < vgic_num_irqs(d));
+
+    vgic_lock_rank(v_target, rank, flags);
+
+    if ( p->desc ||
+         /* The VIRQ should not be already enabled by the guest */
+         test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) )
+        goto out;
 
     desc->handler = gic_hw_ops->gic_guest_irq_type;
     set_bit(_IRQ_GUEST, &desc->status);
 
-    gic_set_irq_properties(desc, cpumask_of(smp_processor_id()), GIC_PRI_IRQ);
+    gic_set_irq_properties(desc, cpumask_of(v_target->processor), GIC_PRI_IRQ);
 
-    /* Use vcpu0 to retrieve the pending_irq struct. Given that we only
-     * route SPIs to guests, it doesn't make any difference. */
-    p = irq_to_pending(d->vcpu[0], virq);
     p->desc = desc;
+    res = 0;
+
+out:
+    vgic_unlock_rank(v_target, rank, flags);
+
+    return res;
 }
 
 int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 4c3e381..b2ddf6b 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -492,14 +492,22 @@ int route_irq_to_guest(struct domain *d, unsigned int virq,
     if ( retval )
         goto out;
 
-    gic_route_irq_to_guest(d, virq, desc, cpumask_of(smp_processor_id()),
-                           GIC_PRI_IRQ);
+    retval = gic_route_irq_to_guest(d, virq, desc, GIC_PRI_IRQ);
+
     spin_unlock_irqrestore(&desc->lock, flags);
+
+    if ( retval )
+    {
+        release_irq(desc->irq, info);
+        goto free_info;
+    }
+
     return 0;
 
 out:
     spin_unlock_irqrestore(&desc->lock, flags);
     xfree(action);
+free_info:
     xfree(info);
 
     return retval;
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index bb2a922..ef4bf9a 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -216,10 +216,9 @@ extern enum gic_version gic_hw_version(void);
 /* Program the GIC to route an interrupt */
 extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
                                  unsigned int priority);
-extern void gic_route_irq_to_guest(struct domain *, unsigned int virq,
-                                   struct irq_desc *desc,
-                                   const cpumask_t *cpu_mask,
-                                   unsigned int priority);
+extern int gic_route_irq_to_guest(struct domain *, unsigned int virq,
+                                  struct irq_desc *desc,
+                                  unsigned int priority);
 
 extern void gic_inject(void);
 extern void gic_clear_pending_irqs(struct vcpu *v);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (11 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 12/33] xen/arm: gic: Add sanity checks gic_route_irq_to_guest Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-20 11:51   ` Stefano Stabellini
  2015-03-31 10:45   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 14/33] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber Julien Grall
                   ` (21 subsequent siblings)
  34 siblings, 2 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

The priority is already hardcoded in route_irq_to_guest and therefore
can't be controlled by the guest.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Changes in v4:
        - Patch added
---
 xen/arch/arm/gic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 2709415..5f34997 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -152,7 +152,7 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int virq,
     desc->handler = gic_hw_ops->gic_guest_irq_type;
     set_bit(_IRQ_GUEST, &desc->status);
 
-    gic_set_irq_properties(desc, cpumask_of(v_target->processor), GIC_PRI_IRQ);
+    gic_set_irq_properties(desc, cpumask_of(v_target->processor), priority);
 
     p->desc = desc;
     res = 0;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 14/33] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (12 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:46   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 15/33] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts Julien Grall
                   ` (20 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

The formula of GICD_TYPER.ITLinesNumber is 32(N + 1).

As the number of SPIs suppported by the domain may not be a multiple of
32, we have to round up the number before using it.

At the same time remove the mask GICD_TYPE_LINES which is pointless.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Changes in v4:
        - Patch added
---
 xen/arch/arm/vgic-v2.c | 2 +-
 xen/arch/arm/vgic-v3.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 40619b2..b5a8f29 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -55,7 +55,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         /* No secure world support for guests. */
         vgic_lock(v);
         *r = ( ((v->domain->max_vcpus - 1) << GICD_TYPE_CPUS_SHIFT) )
-            |( ((v->domain->arch.vgic.nr_spis / 32)) & GICD_TYPE_LINES );
+            | DIV_ROUND_UP(v->domain->arch.vgic.nr_spis, 32);
         vgic_unlock(v);
         return 1;
     case GICD_IIDR:
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index ec79c2a..96c1be8 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -700,7 +700,7 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         if ( dabt.size != DABT_WORD ) goto bad_width;
         /* No secure world support for guests. */
         *r = ((ncpus - 1) << GICD_TYPE_CPUS_SHIFT |
-              ((v->domain->arch.vgic.nr_spis / 32) & GICD_TYPE_LINES));
+              DIV_ROUND_UP(v->domain->arch.vgic.nr_spis, 32));
 
         *r |= (irq_bits - 1) << GICD_TYPE_ID_BITS_SHIFT;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 15/33] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (13 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 14/33] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:47   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs Julien Grall
                   ` (19 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Zoltan Kiss, ian.campbell, Julien Grall, tim, Frediano Ziglio,
	stefano.stabellini

GICD_TYPER.ITLinesNumber can encode up to 1024 interrupts. Although,
IRQ 1020-1023 are reserved for special purpose.

The result is used by the callers of gic_number_lines in order to check
the validity of an IRQ.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Frediano Ziglio <frediano.ziglio@huawei.com>
Cc: Zoltan Kiss <zoltan.kiss@huawei.com>

---
    The GIC HIP04 driver would need a similar if they have some IRQ
    reserved below 512. Maintainers are CCed.

    Changes in v4:
        - This patch was formerly sent separatly
        https://patches.linaro.org/45373/
        - s/(unsigned)1020/1020U/
---
 xen/arch/arm/gic-v2.c | 16 ++++++++++------
 xen/arch/arm/gic-v3.c | 16 ++++++++++------
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index 3be4ad6..cfefb39 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -256,6 +256,7 @@ static void __init gicv2_dist_init(void)
     uint32_t type;
     uint32_t cpumask;
     uint32_t gic_cpus;
+    unsigned int nr_lines;
     int i;
 
     cpumask = readl_gicd(GICD_ITARGETSR) & 0xff;
@@ -266,31 +267,34 @@ static void __init gicv2_dist_init(void)
     writel_gicd(0, GICD_CTLR);
 
     type = readl_gicd(GICD_TYPER);
-    gicv2_info.nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
+    nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
     gic_cpus = 1 + ((type & GICD_TYPE_CPUS) >> 5);
     printk("GICv2: %d lines, %d cpu%s%s (IID %8.8x).\n",
-           gicv2_info.nr_lines, gic_cpus, (gic_cpus == 1) ? "" : "s",
+           nr_lines, gic_cpus, (gic_cpus == 1) ? "" : "s",
            (type & GICD_TYPE_SEC) ? ", secure" : "",
            readl_gicd(GICD_IIDR));
 
     /* Default all global IRQs to level, active low */
-    for ( i = 32; i < gicv2_info.nr_lines; i += 16 )
+    for ( i = 32; i < nr_lines; i += 16 )
         writel_gicd(0x0, GICD_ICFGR + (i / 16) * 4);
 
     /* Route all global IRQs to this CPU */
-    for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+    for ( i = 32; i < nr_lines; i += 4 )
         writel_gicd(cpumask, GICD_ITARGETSR + (i / 4) * 4);
 
     /* Default priority for global interrupts */
-    for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+    for ( i = 32; i < nr_lines; i += 4 )
         writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
                     GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
                     GICD_IPRIORITYR + (i / 4) * 4);
 
     /* Disable all global interrupts */
-    for ( i = 32; i < gicv2_info.nr_lines; i += 32 )
+    for ( i = 32; i < nr_lines; i += 32 )
         writel_gicd(~0x0, GICD_ICENABLER + (i / 32) * 4);
 
+    /* Only 1020 interrupts are supported */
+    gicv2_info.nr_lines = min(1020U, nr_lines);
+
     /* Turn on the distributor */
     writel_gicd(GICD_CTL_ENABLE, GICD_CTLR);
 }
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 48772f1..b0f498e 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -528,23 +528,24 @@ static void __init gicv3_dist_init(void)
     uint32_t type;
     uint32_t priority;
     uint64_t affinity;
+    unsigned int nr_lines;
     int i;
 
     /* Disable the distributor */
     writel_relaxed(0, GICD + GICD_CTLR);
 
     type = readl_relaxed(GICD + GICD_TYPER);
-    gicv3_info.nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
+    nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
 
     printk("GICv3: %d lines, (IID %8.8x).\n",
-           gicv3_info.nr_lines, readl_relaxed(GICD + GICD_IIDR));
+           nr_lines, readl_relaxed(GICD + GICD_IIDR));
 
     /* Default all global IRQs to level, active low */
-    for ( i = NR_GIC_LOCAL_IRQS; i < gicv3_info.nr_lines; i += 16 )
+    for ( i = NR_GIC_LOCAL_IRQS; i < nr_lines; i += 16 )
         writel_relaxed(0, GICD + GICD_ICFGR + (i / 16) * 4);
 
     /* Default priority for global interrupts */
-    for ( i = NR_GIC_LOCAL_IRQS; i < gicv3_info.nr_lines; i += 4 )
+    for ( i = NR_GIC_LOCAL_IRQS; i < nr_lines; i += 4 )
     {
         priority = (GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
                     GIC_PRI_IRQ << 8 | GIC_PRI_IRQ);
@@ -552,7 +553,7 @@ static void __init gicv3_dist_init(void)
     }
 
     /* Disable all global interrupts */
-    for ( i = NR_GIC_LOCAL_IRQS; i < gicv3_info.nr_lines; i += 32 )
+    for ( i = NR_GIC_LOCAL_IRQS; i < nr_lines; i += 32 )
         writel_relaxed(0xffffffff, GICD + GICD_ICENABLER + (i / 32) * 4);
 
     gicv3_dist_wait_for_rwp();
@@ -566,8 +567,11 @@ static void __init gicv3_dist_init(void)
     /* Make sure we don't broadcast the interrupt */
     affinity &= ~GICD_IROUTER_SPI_MODE_ANY;
 
-    for ( i = NR_GIC_LOCAL_IRQS; i < gicv3_info.nr_lines; i++ )
+    for ( i = NR_GIC_LOCAL_IRQS; i < nr_lines; i++ )
         writeq_relaxed(affinity, GICD + GICD_IROUTER + i * 8);
+
+    /* Only 1020 interrupts are supported */
+    gicv3_info.nr_lines = min(1020U, nr_lines);
 }
 
 static int gicv3_enable_redist(void)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (14 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 15/33] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:54   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 17/33] xen/arm: vgic: Add spi_to_pending Julien Grall
                   ` (18 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini, Jan Beulich

Each domain may have a different number of IRQs depending on the devices
assigned to it.

Rather re-using the number of IRQs used by the hardwared GIC, let the
toolstack specify the number of SPIs when the domain is created. This
will avoid to waste memory.

To calculate the number of SPIs, we take advantage of the fact that the
libxl interface can only expose 1:1 mapping and look for the largest SPI
in the list.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Wei Liu <wei.liu2@citrix.com>

---
    Changes in v4:
        - Check the number of SPIs supported by the virtual GIC against
        the number supported by the hardware GIC.
        - Use uint32_t rather than int in the toolstack code.
        - Initialize spi after the check in the toolstack code
        - Typoes

    Changes in v3:
        - Fix typoes
        - A separate has been created to extend the DOMCTL create domain

    Changes in v2:
        - Patch added
---
 tools/libxc/xc_domain.c       |  1 +
 tools/libxl/libxl_arm.c       | 21 +++++++++++++++++++++
 xen/arch/arm/domain.c         |  2 +-
 xen/arch/arm/setup.c          |  1 +
 xen/arch/arm/vgic.c           | 11 ++++++-----
 xen/include/asm-arm/domain.h  |  2 ++
 xen/include/asm-arm/setup.h   |  1 +
 xen/include/asm-arm/vgic.h    |  2 +-
 xen/include/public/arch-arm.h |  2 ++
 9 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 448e958..579d266 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -67,6 +67,7 @@ int xc_domain_create(xc_interface *xch,
     /* No arch-specific configuration for now */
 #elif defined (__arm__) || defined(__aarch64__)
     config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
+    config.nr_spis = 0;
 #else
     errno = ENOSYS;
     return -1;
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index dc0919a..2407c2e 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -39,6 +39,27 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
                                       libxl_domain_config *d_config,
                                       xc_domain_configuration_t *xc_config)
 {
+    uint32_t nr_spis = 0;
+    unsigned int i;
+
+    for (i = 0; i < d_config->b_info.num_irqs; i++) {
+        uint32_t irq = d_config->b_info.irqs[i];
+        uint32_t spi;
+
+        if (irq < 32)
+            continue;
+
+        spi = irq - 32;
+
+        if (nr_spis <= spi)
+            nr_spis = spi + 1;
+    }
+
+    LOG(DEBUG, "Configure the domain");
+
+    xc_config->nr_spis = nr_spis;
+    LOG(DEBUG, " - Allocate %u SPIs", nr_spis);
+
     xc_config->gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
 
     return 0;
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index ce9f349..7c5bf9f 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -562,7 +562,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
     if ( (rc = gicv_setup(d)) != 0 )
         goto fail;
 
-    if ( (rc = domain_vgic_init(d)) != 0 )
+    if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
         goto fail;
 
     if ( (rc = domain_vtimer_init(d)) != 0 )
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index defe39e..c935266 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -830,6 +830,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     /* Create initial domain 0. */
     /* The vGIC for DOM0 is exactly emulated the hardware GIC */
     config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
+    config.nr_spis = gic_number_lines() - 32;
 
     dom0 = domain_create(0, 0, 0, &config);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index c07822f..74751e0 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -68,16 +68,17 @@ static void vgic_init_pending_irq(struct pending_irq *p, unsigned int virq)
     p->irq = virq;
 }
 
-int domain_vgic_init(struct domain *d)
+int domain_vgic_init(struct domain *d, unsigned int nr_spis)
 {
     int i;
 
     d->arch.vgic.ctlr = 0;
 
-    if ( is_hardware_domain(d) )
-        d->arch.vgic.nr_spis = gic_number_lines() - 32;
-    else
-        d->arch.vgic.nr_spis = 0; /* We don't need SPIs for the guest */
+    /* Limit the number of SPIs supported base on the hardware */
+    if ( nr_spis > (gic_number_lines() - NR_LOCAL_IRQS) )
+        return -EINVAL;
+
+    d->arch.vgic.nr_spis = nr_spis;
 
     switch ( gic_hw_version() )
     {
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 9e0419e..6dacfef 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -125,6 +125,8 @@ struct arch_domain
     unsigned int evtchn_irq;
 }  __cacheline_aligned;
 
+#define domain_is_configured(d) ((d)->arch.is_configured)
+
 struct arch_vcpu
 {
     struct {
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index ba5a67d..254cc17 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -54,6 +54,7 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
 void arch_get_xen_caps(xen_capabilities_info_t *info);
 
 int construct_dom0(struct domain *d);
+int configure_dom0(struct domain *d);
 
 void discard_initial_modules(void);
 
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index aba0d80..647f2fe 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -177,7 +177,7 @@ enum gic_sgi_mode;
 
 #define vgic_num_irqs(d)        ((d)->arch.vgic.nr_spis + 32)
 
-extern int domain_vgic_init(struct domain *d);
+extern int domain_vgic_init(struct domain *d, unsigned int nr_spis);
 extern void domain_vgic_free(struct domain *d);
 extern int vcpu_vgic_init(struct vcpu *v);
 extern struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int irq);
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index ed7e98f..c029e0f 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -315,6 +315,8 @@ typedef uint64_t xen_callback_t;
 struct xen_arch_domainconfig {
     /* IN/OUT */
     uint8_t gic_version;
+    /* IN */
+    uint32_t nr_spis;
 };
 
 #endif
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 17/33] xen/arm: vgic: Add spi_to_pending
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (15 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:55   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 18/33] xen/arm: Release IRQ routed to a domain when it's destroying Julien Grall
                   ` (17 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

Introduce spi_to_pending in order retrieve the irq_pending structure for
a specific SPI.

It's not possible to re-use irq_to_pending because it's required a VCPU
and some call of the new function may during domain destruction after
the VCPUs are freed.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Changes in v4:
        - Patch added
---
 xen/arch/arm/vgic.c        | 7 +++++++
 xen/include/asm-arm/vgic.h | 1 +
 2 files changed, 8 insertions(+)

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 74751e0..fc283ec 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -371,6 +371,13 @@ struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq)
     return n;
 }
 
+struct pending_irq *spi_to_pending(struct domain *d, unsigned int irq)
+{
+    ASSERT(irq >= NR_LOCAL_IRQS);
+
+    return &d->arch.vgic.pending_irqs[irq - 32];
+}
+
 void vgic_clear_pending_irqs(struct vcpu *v)
 {
     struct pending_irq *p, *t;
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 647f2fe..8d22532 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -185,6 +185,7 @@ extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq);
 extern void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq);
 extern void vgic_clear_pending_irqs(struct vcpu *v);
 extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
+extern struct pending_irq *spi_to_pending(struct domain *d, unsigned int irq);
 extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, int s);
 extern struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq);
 extern int vgic_emulate(struct cpu_user_regs *regs, union hsr hsr);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 18/33] xen/arm: Release IRQ routed to a domain when it's destroying
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (16 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 17/33] xen/arm: vgic: Add spi_to_pending Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 10:58   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq Julien Grall
                   ` (16 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

Xen has to release IRQ routed to a domain in order to reuse later.
Currently only SPIs can be routed to the guest so we only need to
browse SPIs for a specific domain.

Furthermore, a guest can crash and let the IRQ in an incorrect state
(i.e has not being EOIed). Xen will have to reset the IRQ in order to
be able to reuse the IRQ later.

Introduce 2 new functions for release an IRQ routed to a domain:
    - release_guest_irq: upper level to retrieve the IRQ, call the GIC
    code and release the action
    - gic_remove_guest_irq: Check if we can remove the IRQ, and reset
    it if necessary

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Changes in v4:
        - Reorder the code flow
        - Typoes and coding style
        - Use the newly helper spi_to_pending

    Changes in v3:
        - Take the vgic rank lock to protect p->desc
        - Correctly check if the IRQ is disabled
        - Extend the check on the virq in release_guest_irq
        - Use vgic_get_target_vcpu to get the target vCPU
        - Remove spurious change

    Changes in v2:
        - Drop the desc->handler = &no_irq_type in release_irq as it's
        buggy if the IRQ is routed to Xen
        - Add release_guest_irq and gic_remove_guest_irq
---
 xen/arch/arm/gic.c        | 45 +++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/irq.c        | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/vgic.c       | 16 ++++++++++++++++
 xen/include/asm-arm/gic.h |  4 ++++
 xen/include/asm-arm/irq.h |  2 ++
 5 files changed, 113 insertions(+)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 5f34997..f023e4f 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -163,6 +163,51 @@ out:
     return res;
 }
 
+/* This function only works with SPIs for now */
+int gic_remove_irq_from_guest(struct domain *d, unsigned int virq,
+                              struct irq_desc *desc)
+{
+    struct vcpu *v_target = vgic_get_target_vcpu(d->vcpu[0], virq);
+    struct vgic_irq_rank *rank = vgic_rank_irq(v_target, virq);
+    struct pending_irq *p = irq_to_pending(v_target, virq);
+    unsigned long flags;
+
+    ASSERT(spin_is_locked(&desc->lock));
+    ASSERT(test_bit(_IRQ_GUEST, &desc->status));
+    ASSERT(p->desc == desc);
+
+    vgic_lock_rank(v_target, rank, flags);
+
+    if ( d->is_dying )
+    {
+        desc->handler->shutdown(desc);
+
+        /* EOI the IRQ it it has not been done by the guest */
+        if ( test_bit(_IRQ_INPROGRESS, &desc->status) )
+            gic_hw_ops->deactivate_irq(desc);
+        clear_bit(_IRQ_INPROGRESS, &desc->status);
+    }
+    else
+    {
+        /*
+         * TODO: Handle eviction from LRs For now, deny
+         * remove if the IRQ is inflight or not disabled.
+         */
+        if ( test_bit(_IRQ_INPROGRESS, &desc->status) ||
+             !test_bit(_IRQ_DISABLED, &desc->status) )
+            return -EBUSY;
+    }
+
+    clear_bit(_IRQ_GUEST, &desc->status);
+    desc->handler = &no_irq_type;
+
+    p->desc = NULL;
+
+    vgic_unlock_rank(v_target, rank, flags);
+
+    return 0;
+}
+
 int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
                   unsigned int *out_hwirq,
                   unsigned int *out_type)
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index b2ddf6b..376c9f2 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -513,6 +513,52 @@ free_info:
     return retval;
 }
 
+int release_guest_irq(struct domain *d, unsigned int virq)
+{
+    struct irq_desc *desc;
+    struct irq_guest *info;
+    unsigned long flags;
+    struct pending_irq *p;
+    int ret;
+
+    /* Only SPIs are supported */
+    if ( virq < NR_LOCAL_IRQS || virq >= vgic_num_irqs(d) )
+        return -EINVAL;
+
+    p = spi_to_pending(d, virq);
+    if ( !p->desc )
+        return -EINVAL;
+
+    desc = p->desc;
+
+    spin_lock_irqsave(&desc->lock, flags);
+
+    ret = -EINVAL;
+    if ( !test_bit(_IRQ_GUEST, &desc->status) )
+        goto unlock;
+
+    info = irq_get_guest_info(desc);
+    ret = -EINVAL;
+    if ( d != info->d )
+        goto unlock;
+
+    ret = gic_remove_irq_from_guest(d, virq, desc);
+    if ( ret )
+        goto unlock;
+
+    spin_unlock_irqrestore(&desc->lock, flags);
+
+    release_irq(desc->irq, info);
+    xfree(info);
+
+    return 0;
+
+unlock:
+    spin_unlock_irqrestore(&desc->lock, flags);
+
+    return ret;
+}
+
 /*
  * pirq event channels. We don't use these on ARM, instead we use the
  * features of the GIC to inject virtualised normal interrupts.
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index fc283ec..93d0139 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -135,6 +135,22 @@ void register_vgic_ops(struct domain *d, const struct vgic_ops *ops)
 
 void domain_vgic_free(struct domain *d)
 {
+    int i;
+    int ret;
+
+    for ( i = 0; i < (d->arch.vgic.nr_spis); i++ )
+    {
+        struct pending_irq *p = spi_to_pending(d, i + 32);
+
+        if ( p->desc )
+        {
+            ret = release_guest_irq(d, p->irq);
+            if ( ret )
+                dprintk(XENLOG_G_WARNING, "d%u: Failed to release virq %u ret = %d\n",
+                        d->domain_id, p->irq, ret);
+        }
+    }
+
     xfree(d->arch.vgic.shared_irqs);
     xfree(d->arch.vgic.pending_irqs);
     xfree(d->arch.vgic.allocated_irqs);
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index ef4bf9a..9e2acb7 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -220,6 +220,10 @@ extern int gic_route_irq_to_guest(struct domain *, unsigned int virq,
                                   struct irq_desc *desc,
                                   unsigned int priority);
 
+/* Remove an IRQ passthrough to a guest */
+int gic_remove_irq_from_guest(struct domain *d, unsigned int virq,
+                              struct irq_desc *desc);
+
 extern void gic_inject(void);
 extern void gic_clear_pending_irqs(struct vcpu *v);
 extern int gic_events_need_delivery(void);
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 71b39e7..34b492b 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -44,6 +44,8 @@ void init_secondary_IRQ(void);
 
 int route_irq_to_guest(struct domain *d, unsigned int virq,
                        unsigned int irq, const char *devname);
+int release_guest_irq(struct domain *d, unsigned int irq);
+
 void arch_move_irqs(struct vcpu *v);
 
 /* Set IRQ type for an SPI */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (17 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 18/33] xen/arm: Release IRQ routed to a domain when it's destroying Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:11   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 20/33] xen/dts: Provide an helper to get a DT node from a path provided by a guest Julien Grall
                   ` (15 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Jan Beulich

On x86, an IRQ is assigned in 2 steps to an HVM guest:
    - The toolstack is calling PHYSDEVOP_map_pirq in order to create a
    guest PIRQ (IRQ bound to an event channel)
    - The emulator (QEMU) is calling DOMCTL_bind_pt_irq in order to
    bind the IRQ

On ARM, there is no concept of PIRQ as the IRQ can be assigned to a
virtual IRQ using the interrupt controller.

It's not clear if we will need 2 different hypercalls on ARM to assign
IRQ and, for now, only the toolstack will manage IRQ.

In order to avoid re-using a fixed ABI hypercall (PHYSDEVOP_*) for a
different purpose and allow us more time to figure out the right out,
only DOMCTL_{,un}bind_pt_pirq is implemented on ARM.

The DOMCTL is extended with a new type PT_IRQ_TYPE_SPI and only IRQ ==
vIRQ (i.e machine_irq == spi) is supported.

Concerning XSM, even if ARM is using one hypercall rather than 2, the
resulting check is nearly the same.

XSM PHYSDEVOP_map_pirq:
    1) Check if the current domain can add resource to the domain
    2) Check if the current domain has permission to add the IRQ
    3) Check if the target domain has permission to use the IRQ

XSM DOMCTL_bind_pirq_irq:
    1) Check if the current domain can add resource to the domain
    2) Check if the current domain has permission to bind the IRQ
    3) Check if the target domain has permission to use the IRQ

Rather than checking that the current domain can both add and bind the
IRQ, we only check the bind permission. I think this is not a big deal
because we don't have emulator on ARM and therefore no disaggregation is
required.

Note: The toolstack changes for routing an IRQ to a guest will be done
in a separate patch.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Jan Beulich <jbeulich@suse.com>

---
    Contrawise PHYSDEV, DOMCTL interface is not fixed. This version is
    using a DOMCTL in order to let us more to to see if we need a new
    PHYSDEV op for vIRQ assignation.

    DOMCTL_unbind_pt_irq has been implemented, although I haven't test
    it. I'm not sure if we want to keep it.

    Concerning XSM, the final security check is fairly the same:

    Changes in v4:
        - Move the implementation from PHYSDEV to DOMCTL. Reuse
        DOMCTL_{,un}bind_pt_irq for this purpose.

    Changes in v3:
        - Functions to allocate/release/reserved a VIRQ has been moved
        in a separate patch
        - Make clear that only MAP_PIRQ_GSI is only supported for now

    Changes in v2:
        - Add PHYSDEVOP_unmap_pirq
        - Rework commit message
        - Add functions to allocate/release a VIRQ
        - is_routable_irq has been renamed into is_assignable_irq
---
 tools/libxc/include/xenctrl.h |  8 +++--
 tools/libxc/xc_domain.c       | 18 +++++++++--
 xen/arch/arm/domctl.c         | 66 ++++++++++++++++++++++++++++++++++++++++
 xen/include/public/domctl.h   |  4 +++
 xen/include/xsm/dummy.h       | 24 +++++++--------
 xen/include/xsm/xsm.h         | 28 ++++++++---------
 xen/xsm/dummy.c               |  4 +--
 xen/xsm/flask/hooks.c         | 70 ++++++++++++++++++++++---------------------
 8 files changed, 156 insertions(+), 66 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 60b61b6..b6212bf 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2090,7 +2090,7 @@ int xc_domain_bind_pt_irq(xc_interface *xch,
                           uint8_t bus,
                           uint8_t device,
                           uint8_t intx,
-                          uint8_t isa_irq);
+                          uint16_t isa_irq);
 
 int xc_domain_unbind_pt_irq(xc_interface *xch,
                           uint32_t domid,
@@ -2099,7 +2099,7 @@ int xc_domain_unbind_pt_irq(xc_interface *xch,
                           uint8_t bus,
                           uint8_t device,
                           uint8_t intx,
-                          uint8_t isa_irq);
+                          uint16_t isa_irq);
 
 int xc_domain_bind_pt_pci_irq(xc_interface *xch,
                               uint32_t domid,
@@ -2112,6 +2112,10 @@ int xc_domain_bind_pt_isa_irq(xc_interface *xch,
                               uint32_t domid,
                               uint8_t machine_irq);
 
+int xc_domain_bind_pt_spi_irq(xc_interface *xch,
+                              uint32_t domid,
+                              uint16_t spi);
+
 int xc_domain_set_machine_address_size(xc_interface *xch,
 				       uint32_t domid,
 				       unsigned int width);
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 579d266..8243b70 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1764,7 +1764,7 @@ int xc_domain_bind_pt_irq(
     uint8_t bus,
     uint8_t device,
     uint8_t intx,
-    uint8_t isa_irq)
+    uint16_t isa_irq)
 {
     int rc;
     xen_domctl_bind_pt_irq_t * bind;
@@ -1788,6 +1788,9 @@ int xc_domain_bind_pt_irq(
     case PT_IRQ_TYPE_ISA:
         bind->u.isa.isa_irq = isa_irq;
         break;
+    case PT_IRQ_TYPE_SPI:
+        bind->u.spi.spi = isa_irq;
+        break;
     default:
         errno = EINVAL;
         return -1;
@@ -1805,7 +1808,7 @@ int xc_domain_unbind_pt_irq(
     uint8_t bus,
     uint8_t device,
     uint8_t intx,
-    uint8_t isa_irq)
+    uint16_t isa_irq)
 {
     int rc;
     xen_domctl_bind_pt_irq_t * bind;
@@ -1829,6 +1832,8 @@ int xc_domain_unbind_pt_irq(
     case PT_IRQ_TYPE_ISA:
         bind->u.isa.isa_irq = isa_irq;
         break;
+    case PT_IRQ_TYPE_SPI:
+        bind->u.spi.spi = isa_irq;
     default:
         errno = EINVAL;
         return -1;
@@ -1861,6 +1866,15 @@ int xc_domain_bind_pt_isa_irq(
                                   PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq));
 }
 
+int xc_domain_bind_pt_spi_irq(
+    xc_interface *xch,
+    uint32_t domid,
+    uint16_t spi)
+{
+    return (xc_domain_bind_pt_irq(xch, domid, spi,
+                                  PT_IRQ_TYPE_SPI, 0, 0, 0, spi));
+}
+
 int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *minfo)
 {
     struct domain_info_context _di = { .guest_width = minfo->guest_width,
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 6f30af7..f5d5a10 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -10,6 +10,8 @@
 #include <xen/errno.h>
 #include <xen/sched.h>
 #include <xen/hypercall.h>
+#include <xen/iocap.h>
+#include <xsm/xsm.h>
 #include <public/domctl.h>
 
 long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
@@ -30,6 +32,70 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
 
         return p2m_cache_flush(d, s, e);
     }
+    case XEN_DOMCTL_bind_pt_irq:
+    {
+        int rc;
+        xen_domctl_bind_pt_irq_t *bind = &domctl->u.bind_pt_irq;
+        uint32_t irq = bind->u.spi.spi;
+        uint32_t virq = bind->machine_irq;
+
+        /* We only support PT_IRQ_TYPE_SPI */
+        if ( bind->irq_type != PT_IRQ_TYPE_SPI )
+            return -EOPNOTSUPP;
+
+        /*
+         * XXX: For now map the interrupt 1:1. Other support will require to
+         * modify domain_pirq_to_irq macro.
+         */
+        if ( irq != virq )
+            return -EINVAL;
+
+        rc = xsm_bind_pt_irq(XSM_HOOK, d, bind);
+        if ( rc )
+            return rc;
+
+        if ( !irq_access_permitted(current->domain, irq) )
+            return -EPERM;
+
+        if ( !vgic_reserve_virq(d, virq) )
+            return -EBUSY;
+
+        rc = route_irq_to_guest(d, virq, irq, "routed IRQ");
+        if ( rc )
+            vgic_free_virq(d, virq);
+
+        return rc;
+    }
+    case XEN_DOMCTL_unbind_pt_irq:
+    {
+        int rc;
+        xen_domctl_bind_pt_irq_t *bind = &domctl->u.bind_pt_irq;
+        uint32_t irq = bind->u.spi.spi;
+        uint32_t virq = bind->machine_irq;
+
+        /* We only support PT_IRQ_TYPE_SPI */
+        if ( bind->irq_type != PT_IRQ_TYPE_SPI )
+            return -EOPNOTSUPP;
+
+        /* For now map the interrupt 1:1 */
+        if ( irq != virq )
+            return -EINVAL;
+
+        rc = xsm_unbind_pt_irq(XSM_HOOK, d, bind);
+        if ( rc )
+            return rc;
+
+        if ( !irq_access_permitted(current->domain, irq) )
+            return -EPERM;
+
+        rc = release_guest_irq(d, virq);
+        if ( rc )
+            return rc;
+
+        vgic_free_virq(d, virq);
+
+        return 0;
+    }
     default:
         return subarch_do_domctl(domctl, d, u_domctl);
     }
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index d6c1ec7..7f90150 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -504,6 +504,7 @@ typedef enum pt_irq_type_e {
     PT_IRQ_TYPE_ISA,
     PT_IRQ_TYPE_MSI,
     PT_IRQ_TYPE_MSI_TRANSLATE,
+    PT_IRQ_TYPE_SPI,    /* ARM: valid range 32-1019 */
 } pt_irq_type_t;
 struct xen_domctl_bind_pt_irq {
     uint32_t machine_irq;
@@ -524,6 +525,9 @@ struct xen_domctl_bind_pt_irq {
             uint32_t gflags;
             uint64_aligned_t gtable;
         } msi;
+        struct {
+            uint16_t spi;
+        } spi;
     } u;
 };
 typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t;
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index f20e89c..da414c7 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -445,6 +445,18 @@ static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
     return xsm_default_action(action, current->domain, d);
 }
 
+static XSM_INLINE int xsm_bind_pt_irq(XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
+{
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
+}
+
+static XSM_INLINE int xsm_unbind_pt_irq(XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
+{
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
+}
+
 static XSM_INLINE int xsm_unmap_domain_irq(XSM_DEFAULT_ARG struct domain *d, int irq, void *data)
 {
     XSM_ASSERT_ACTION(XSM_HOOK);
@@ -631,18 +643,6 @@ static XSM_INLINE int xsm_priv_mapping(XSM_DEFAULT_ARG struct domain *d, struct
     return xsm_default_action(action, d, t);
 }
 
-static XSM_INLINE int xsm_bind_pt_irq(XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
-{
-    XSM_ASSERT_ACTION(XSM_HOOK);
-    return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int xsm_unbind_pt_irq(XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
-{
-    XSM_ASSERT_ACTION(XSM_HOOK);
-    return xsm_default_action(action, current->domain, d);
-}
-
 static XSM_INLINE int xsm_ioport_permission(XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
     XSM_ASSERT_ACTION(XSM_HOOK);
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 0437735..99a59d0 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -107,6 +107,8 @@ struct xsm_operations {
     int (*map_domain_irq) (struct domain *d, int irq, void *data);
     int (*unmap_domain_pirq) (struct domain *d);
     int (*unmap_domain_irq) (struct domain *d, int irq, void *data);
+    int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
+    int (*unbind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
     int (*irq_permission) (struct domain *d, int pirq, uint8_t allow);
     int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow);
     int (*iomem_mapping) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow);
@@ -169,8 +171,6 @@ struct xsm_operations {
     int (*mmuext_op) (struct domain *d, struct domain *f);
     int (*update_va_mapping) (struct domain *d, struct domain *f, l1_pgentry_t pte);
     int (*priv_mapping) (struct domain *d, struct domain *t);
-    int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
-    int (*unbind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
     int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow);
     int (*ioport_mapping) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow);
 #endif
@@ -419,6 +419,18 @@ static inline int xsm_unmap_domain_irq (xsm_default_t def, struct domain *d, int
     return xsm_ops->unmap_domain_irq(d, irq, data);
 }
 
+static inline int xsm_bind_pt_irq(xsm_default_t def, struct domain *d,
+                                                struct xen_domctl_bind_pt_irq *bind)
+{
+    return xsm_ops->bind_pt_irq(d, bind);
+}
+
+static inline int xsm_unbind_pt_irq(xsm_default_t def, struct domain *d,
+                                                struct xen_domctl_bind_pt_irq *bind)
+{
+    return xsm_ops->unbind_pt_irq(d, bind);
+}
+
 static inline int xsm_irq_permission (xsm_default_t def, struct domain *d, int pirq, uint8_t allow)
 {
     return xsm_ops->irq_permission(d, pirq, allow);
@@ -643,18 +655,6 @@ static inline int xsm_priv_mapping(xsm_default_t def, struct domain *d, struct d
     return xsm_ops->priv_mapping(d, t);
 }
 
-static inline int xsm_bind_pt_irq(xsm_default_t def, struct domain *d,
-                                                struct xen_domctl_bind_pt_irq *bind)
-{
-    return xsm_ops->bind_pt_irq(d, bind);
-}
-
-static inline int xsm_unbind_pt_irq(xsm_default_t def, struct domain *d,
-                                                struct xen_domctl_bind_pt_irq *bind)
-{
-    return xsm_ops->unbind_pt_irq(d, bind);
-}
-
 static inline int xsm_ioport_permission (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
     return xsm_ops->ioport_permission(d, s, e, allow);
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index 8eb3050..b69a019 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -81,6 +81,8 @@ void xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, map_domain_irq);
     set_to_dummy_if_null(ops, unmap_domain_pirq);
     set_to_dummy_if_null(ops, unmap_domain_irq);
+    set_to_dummy_if_null(ops, bind_pt_irq);
+    set_to_dummy_if_null(ops, unbind_pt_irq);
     set_to_dummy_if_null(ops, irq_permission);
     set_to_dummy_if_null(ops, iomem_permission);
     set_to_dummy_if_null(ops, iomem_mapping);
@@ -140,8 +142,6 @@ void xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, mmuext_op);
     set_to_dummy_if_null(ops, update_va_mapping);
     set_to_dummy_if_null(ops, priv_mapping);
-    set_to_dummy_if_null(ops, bind_pt_irq);
-    set_to_dummy_if_null(ops, unbind_pt_irq);
     set_to_dummy_if_null(ops, ioport_permission);
     set_to_dummy_if_null(ops, ioport_mapping);
 #endif
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index b453605..e1cc16a 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -580,12 +580,14 @@ static int flask_domctl(struct domain *d, int cmd)
 #ifdef HAS_MEM_ACCESS
     case XEN_DOMCTL_mem_event_op:
 #endif
+
+    /* These have individual XSM hooks (arch/../domctl.c) */
+    case XEN_DOMCTL_bind_pt_irq:
+    case XEN_DOMCTL_unbind_pt_irq:
 #ifdef CONFIG_X86
     /* These have individual XSM hooks (arch/x86/domctl.c) */
     case XEN_DOMCTL_shadow_op:
     case XEN_DOMCTL_ioport_permission:
-    case XEN_DOMCTL_bind_pt_irq:
-    case XEN_DOMCTL_unbind_pt_irq:
     case XEN_DOMCTL_ioport_mapping:
     /* These have individual XSM hooks (drivers/passthrough/iommu.c) */
     case XEN_DOMCTL_get_device_group:
@@ -911,6 +913,36 @@ static int flask_unmap_domain_irq (struct domain *d, int irq, void *data)
     return rc;
 }
 
+static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind)
+{
+    u32 dsid, rsid;
+    int rc = -EPERM;
+    int irq;
+    struct avc_audit_data ad;
+
+    rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
+    if ( rc )
+        return rc;
+
+    irq = domain_pirq_to_irq(d, bind->machine_irq);
+
+    rc = get_irq_sid(irq, &rsid, &ad);
+    if ( rc )
+        return rc;
+
+    rc = avc_current_has_perm(rsid, SECCLASS_HVM, HVM__BIND_IRQ, &ad);
+    if ( rc )
+        return rc;
+
+    dsid = domain_sid(d);
+    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+}
+
+static int flask_unbind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind)
+{
+    return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
+}
+
 static int flask_irq_permission (struct domain *d, int pirq, uint8_t access)
 {
     /* the PIRQ number is not useful; real IRQ is checked during mapping */
@@ -1468,36 +1500,6 @@ static int flask_priv_mapping(struct domain *d, struct domain *t)
 {
     return domain_has_perm(d, t, SECCLASS_MMU, MMU__TARGET_HACK);
 }
-
-static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind)
-{
-    u32 dsid, rsid;
-    int rc = -EPERM;
-    int irq;
-    struct avc_audit_data ad;
-
-    rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
-    if ( rc )
-        return rc;
-
-    irq = domain_pirq_to_irq(d, bind->machine_irq);
-
-    rc = get_irq_sid(irq, &rsid, &ad);
-    if ( rc )
-        return rc;
-
-    rc = avc_current_has_perm(rsid, SECCLASS_HVM, HVM__BIND_IRQ, &ad);
-    if ( rc )
-        return rc;
-
-    dsid = domain_sid(d);
-    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
-}
-
-static int flask_unbind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind)
-{
-    return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
-}
 #endif /* CONFIG_X86 */
 
 long do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op);
@@ -1556,6 +1558,8 @@ static struct xsm_operations flask_ops = {
     .map_domain_irq = flask_map_domain_irq,
     .unmap_domain_pirq = flask_unmap_domain_pirq,
     .unmap_domain_irq = flask_unmap_domain_irq,
+    .bind_pt_irq = flask_bind_pt_irq,
+    .unbind_pt_irq = flask_unbind_pt_irq,
     .irq_permission = flask_irq_permission,
     .iomem_permission = flask_iomem_permission,
     .iomem_mapping = flask_iomem_mapping,
@@ -1616,8 +1620,6 @@ static struct xsm_operations flask_ops = {
     .mmuext_op = flask_mmuext_op,
     .update_va_mapping = flask_update_va_mapping,
     .priv_mapping = flask_priv_mapping,
-    .bind_pt_irq = flask_bind_pt_irq,
-    .unbind_pt_irq = flask_unbind_pt_irq,
     .ioport_permission = flask_ioport_permission,
     .ioport_mapping = flask_ioport_mapping,
 #endif
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 20/33] xen/dts: Provide an helper to get a DT node from a path provided by a guest
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (18 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:12   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct Julien Grall
                   ` (14 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

The maximum size of the copied string has been chosen based on the value
use by XSM in similar case.

Furthermore, Linux seems to allow path up to 4096 characters. Though
this could vary from one OS to another.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Changes in v4:
        - Drop DEVICE_TREE_MAX_PATHLEN
        - Bump the value to PAGE_SIZE (i.e 4096). It's used in XSM and
        this value seems sensible for Linux
        - Clarify how the maximum size has been chosen

    Changes in v3:
        - Use the new prototype of safe_copy_string_from_guest

    Changes in v2:
        - guest_copy_string_from_guest has been renamed into
        safe_copy_string_from_guest
---
 xen/common/device_tree.c      | 18 ++++++++++++++++++
 xen/include/xen/device_tree.h | 14 ++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 02cae91..31f169b 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -13,6 +13,7 @@
 #include <xen/config.h>
 #include <xen/types.h>
 #include <xen/init.h>
+#include <xen/guest_access.h>
 #include <xen/device_tree.h>
 #include <xen/kernel.h>
 #include <xen/lib.h>
@@ -23,6 +24,7 @@
 #include <xen/cpumask.h>
 #include <xen/ctype.h>
 #include <asm/setup.h>
+#include <xen/err.h>
 
 const void *device_tree_flattened;
 dt_irq_xlate_func dt_irq_xlate;
@@ -277,6 +279,22 @@ struct dt_device_node *dt_find_node_by_path(const char *path)
     return np;
 }
 
+int dt_find_node_by_gpath(XEN_GUEST_HANDLE(char) u_path, uint32_t u_plen,
+                          struct dt_device_node **node)
+{
+    char *path;
+
+    path = safe_copy_string_from_guest(u_path, u_plen, PAGE_SIZE);
+    if ( IS_ERR(path) )
+        return PTR_ERR(path);
+
+    *node = dt_find_node_by_path(path);
+
+    xfree(path);
+
+    return (*node == NULL) ? -ESRCH : 0;
+}
+
 struct dt_device_node *dt_find_node_by_alias(const char *alias)
 {
     const struct dt_alias_prop *app;
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 57eb3ee..e187780 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -456,6 +456,20 @@ struct dt_device_node *dt_find_node_by_alias(const char *alias);
  */
 struct dt_device_node *dt_find_node_by_path(const char *path);
 
+
+/**
+ * dt_find_node_by_gpath - Same as dt_find_node_by_path but retrieve the
+ * path from the guest
+ *
+ * @u_path: Xen Guest handle to the buffer containing the path
+ * @u_plen: Length of the buffer
+ * @node: TODO
+ *
+ * Return 0 if succeed otherwise -errno
+ */
+int dt_find_node_by_gpath(XEN_GUEST_HANDLE(char) u_path, uint32_t u_plen,
+                          struct dt_device_node **node);
+
 /**
  * dt_get_parent - Get a node's parent if any
  * @node: Node to get parent
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (19 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 20/33] xen/dts: Provide an helper to get a DT node from a path provided by a guest Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-20 10:53   ` Jan Beulich
  2015-03-31 11:13   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 22/33] xen/passthrough: arm: release the DT devices assigned to a guest earlier Julien Grall
                   ` (13 subsequent siblings)
  34 siblings, 2 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Jan Beulich

This new function will correctly initialize the IOMMU page table for the
current domain.

Also use it in iommu_assign_dt_device even though the current IOMMU
implementation on ARM shares P2M with the processor.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Jan Beulich <jbeulich@suse.com>

---
    Changes in v4:
        - Move memory_type_changed in iommu_construct. Added by commit
        06ed8cc "x86: avoid needless EPT table ajustment and cache
        flush"
        - And an ASSERT and a comment in iommu_assign_dt_device to
        explain why the call is safe for DOM0

    Changes in v3:
        - The ASSERT in iommu_construct was redundant with the if ()
        - Remove d->need_iommu = 1 in assign_device has it's already
        done by iommu_construct.
        - Simplify the code in the caller of iommu_construct

    Changes in v2:
        - Add missing Signed-off-by
        - Rename iommu_buildup to iommu_construct
---
 xen/drivers/passthrough/arm/iommu.c   |  6 ++++++
 xen/drivers/passthrough/device_tree.c | 12 ++++++++++++
 xen/drivers/passthrough/iommu.c       | 26 ++++++++++++++++++++++++++
 xen/drivers/passthrough/pci.c         | 22 ++++------------------
 xen/include/xen/iommu.h               |  2 ++
 5 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/xen/drivers/passthrough/arm/iommu.c b/xen/drivers/passthrough/arm/iommu.c
index 3007b99..9234657 100644
--- a/xen/drivers/passthrough/arm/iommu.c
+++ b/xen/drivers/passthrough/arm/iommu.c
@@ -68,3 +68,9 @@ void arch_iommu_domain_destroy(struct domain *d)
 {
     iommu_dt_domain_destroy(d);
 }
+
+int arch_iommu_populate_page_table(struct domain *d)
+{
+    /* The IOMMU shares the p2m with the CPU */
+    return -ENOSYS;
+}
diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c
index 377d41d..4d82a09 100644
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -41,6 +41,18 @@ int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev)
     if ( !list_empty(&dev->domain_list) )
         goto fail;
 
+    if ( need_iommu(d) <= 0 )
+    {
+        /*
+         * The hwdom is forced to use IOMMU for protecting assigned
+         * device. Therefore the IOMMU data is already set up.
+         */
+        ASSERT(!is_hardware_domain(d));
+        rc = iommu_construct(d);
+        if ( rc )
+            goto fail;
+    }
+
     rc = hd->platform_ops->assign_device(d, 0, dt_to_dev(dev));
 
     if ( rc )
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index 92ea26f..faddd50 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -187,6 +187,32 @@ void iommu_teardown(struct domain *d)
     tasklet_schedule(&iommu_pt_cleanup_tasklet);
 }
 
+int iommu_construct(struct domain *d)
+{
+    int rc = 0;
+
+    if ( need_iommu(d) > 0 )
+        return 0;
+
+    if ( !iommu_use_hap_pt(d) )
+    {
+        rc = arch_iommu_populate_page_table(d);
+        if ( rc )
+            return rc;
+    }
+
+    d->need_iommu = 1;
+    /*
+     * There may be dirty cache lines when a device is assigned
+     * and before need_iommu(d) becoming true, this will cause
+     * memory_type_changed lose effect if memory type changes.
+     * Call memory_type_changed here to amend this.
+     */
+    memory_type_changed(d);
+
+    return rc;
+}
+
 void iommu_domain_destroy(struct domain *d)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 4b83583..18b74f4 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -1353,25 +1353,11 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
     if ( !spin_trylock(&pcidevs_lock) )
         return -ERESTART;
 
-    if ( need_iommu(d) <= 0 )
+    rc = iommu_construct(d);
+    if ( rc )
     {
-        if ( !iommu_use_hap_pt(d) )
-        {
-            rc = arch_iommu_populate_page_table(d);
-            if ( rc )
-            {
-                spin_unlock(&pcidevs_lock);
-                return rc;
-            }
-        }
-        d->need_iommu = 1;
-        /*
-         * There may be dirty cache lines when a device is assigned
-         * and before need_iommu(d) becoming true, this will cause
-         * memory_type_changed lose effect if memory type changes.
-         * Call memory_type_changed here to amend this.
-         */
-        memory_type_changed(d);
+        spin_unlock(&pcidevs_lock);
+        return rc;
     }
 
     pdev = pci_get_pdev_by_domain(hardware_domain, seg, bus, devfn);
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index bf4aff0..e9d2d5c 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -65,6 +65,8 @@ int arch_iommu_domain_init(struct domain *d);
 int arch_iommu_populate_page_table(struct domain *d);
 void arch_iommu_check_autotranslated_hwdom(struct domain *d);
 
+int iommu_construct(struct domain *d);
+
 /* Function used internally, use iommu_domain_destroy */
 void iommu_teardown(struct domain *d);
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 22/33] xen/passthrough: arm: release the DT devices assigned to a guest earlier
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (20 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:16   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 23/33] xen/passthrough: iommu_deassign_device_dt: By default reassign device to nobody Julien Grall
                   ` (12 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: ian.campbell, Julien Grall, tim, Robert VanVossen,
	stefano.stabellini, Jan Beulich

The toolstack may not have deassigned every device used by a guest.
Therefore we have to go through the device list and remove them before
asking the IOMMU drivers to release memory for this domain.

This can be done by moving the call to the release function when we
relinquish the resources. The IOMMU part will be destroyed later when
the domain is freed.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Signed-off-by: Robert VanVossen <robert.vanvossen@dornerworks.com>
Acked-by: Jan Beulich <jbeulich@suse.com>

---
    Changes in v4:
        - Typoes in commit message
        - Add Jan's ack
        - iommu_release_dt_devices was only release the first device by
        mistake. Thanks for Robert VanVossen for spotting it.

    Changes in v3:
        - Patch added. Superseed the patch "xen/passthrough: call
        arch_iommu_domain_destroy before calling iommu teardown" in
        the previous patch series.
---
 xen/arch/arm/domain.c                 | 4 ++++
 xen/drivers/passthrough/arm/iommu.c   | 1 -
 xen/drivers/passthrough/device_tree.c | 7 ++++++-
 xen/include/xen/iommu.h               | 2 +-
 4 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 7c5bf9f..7ebdce3 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -767,6 +767,10 @@ int domain_relinquish_resources(struct domain *d)
     switch ( d->arch.relmem )
     {
     case RELMEM_not_started:
+        ret = iommu_release_dt_devices(d);
+        if ( ret )
+            return ret;
+
         d->arch.relmem = RELMEM_xen;
         /* Falltrough */
 
diff --git a/xen/drivers/passthrough/arm/iommu.c b/xen/drivers/passthrough/arm/iommu.c
index 9234657..95b1abb 100644
--- a/xen/drivers/passthrough/arm/iommu.c
+++ b/xen/drivers/passthrough/arm/iommu.c
@@ -66,7 +66,6 @@ int arch_iommu_domain_init(struct domain *d)
 
 void arch_iommu_domain_destroy(struct domain *d)
 {
-    iommu_dt_domain_destroy(d);
 }
 
 int arch_iommu_populate_page_table(struct domain *d)
diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c
index 4d82a09..05ab274 100644
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -105,7 +105,7 @@ int iommu_dt_domain_init(struct domain *d)
     return 0;
 }
 
-void iommu_dt_domain_destroy(struct domain *d)
+int iommu_release_dt_devices(struct domain *d)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
     struct dt_device_node *dev, *_dev;
@@ -115,7 +115,12 @@ void iommu_dt_domain_destroy(struct domain *d)
     {
         rc = iommu_deassign_dt_device(d, dev);
         if ( rc )
+        {
             dprintk(XENLOG_ERR, "Failed to deassign %s in domain %u\n",
                     dt_node_full_name(dev), d->domain_id);
+            return rc;
+        }
     }
+
+    return 0;
 }
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index e9d2d5c..d9c9ede 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -117,7 +117,7 @@ void iommu_read_msi_from_ire(struct msi_desc *msi_desc, struct msi_msg *msg);
 int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev);
 int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev);
 int iommu_dt_domain_init(struct domain *d);
-void iommu_dt_domain_destroy(struct domain *d);
+int iommu_release_dt_devices(struct domain *d);
 
 #endif /* HAS_DEVICE_TREE */
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 23/33] xen/passthrough: iommu_deassign_device_dt: By default reassign device to nobody
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (21 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 22/33] xen/passthrough: arm: release the DT devices assigned to a guest earlier Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:16   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 24/33] xen/iommu: arm: Wire iommu DOMCTL for ARM Julien Grall
                   ` (11 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

Currently, when the device is deassigned from a domain, we directly reassign
to DOM0.

As the device may not have been correctly reset, this may lead to corruption or
expose some part of DOM0 memory. Also, we may have no way to reset some
platform devices.

If Xen reassigns the device to "nobody", it may receive some global/context
fault because the transaction has failed (indeed the context has been
marked invalid). Unfortunately there is no simple way to quiesce a buggy
hardware. I think we could live with that for a first version of platform
device passthrough.

DOM0 will have to issue an hypercall to assign the device to itself if it
wants to use it.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@citrix.com>

---
    Note: This behavior is documented in a following patch which extend
    DOMCT_*assign_device to support non-PCI passthrough.

    Changes in v4:
        - Add Stefano's ack

    Changes in v3:
        - Use the coding style of the new SMMU drivers

    Changes in v2:
        - Fix typoes in the commit message
        - Update commit message
---
 xen/drivers/passthrough/arm/smmu.c    | 8 +++++++-
 xen/drivers/passthrough/device_tree.c | 9 +++------
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
index a7a7da9..7261834 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -2649,7 +2649,7 @@ static int arm_smmu_reassign_dev(struct domain *s, struct domain *t,
 	int ret = 0;
 
 	/* Don't allow remapping on other domain than hwdom */
-	if (t != hardware_domain)
+	if (t && t != hardware_domain)
 		return -EPERM;
 
 	if (t == s)
@@ -2659,6 +2659,12 @@ static int arm_smmu_reassign_dev(struct domain *s, struct domain *t,
 	if (ret)
 		return ret;
 
+	if (t) {
+		ret = arm_smmu_assign_dev(t, devfn, dev);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c
index 05ab274..0ec4103 100644
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -80,15 +80,12 @@ int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev)
 
     spin_lock(&dtdevs_lock);
 
-    rc = hd->platform_ops->reassign_device(d, hardware_domain,
-                                           0, dt_to_dev(dev));
+    rc = hd->platform_ops->reassign_device(d, NULL, 0, dt_to_dev(dev));
     if ( rc )
         goto fail;
 
-    list_del(&dev->domain_list);
-
-    dt_device_set_used_by(dev, hardware_domain->domain_id);
-    list_add(&dev->domain_list, &domain_hvm_iommu(hardware_domain)->dt_devices);
+    list_del_init(&dev->domain_list);
+    dt_device_set_used_by(dev, DOMID_IO);
 
 fail:
     spin_unlock(&dtdevs_lock);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 24/33] xen/iommu: arm: Wire iommu DOMCTL for ARM
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (22 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 23/33] xen/passthrough: iommu_deassign_device_dt: By default reassign device to nobody Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-19 19:29 ` [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough Julien Grall
                   ` (10 subsequent siblings)
  34 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---
    Changes in v4:
        - Add Ian's ack

    Changes in v3:
        - Add Stefano's ack

    Changes in v2:
        - Don't move the call in common code.
---
 xen/arch/arm/domctl.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index f5d5a10..fab9ff7 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -97,7 +97,16 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
         return 0;
     }
     default:
-        return subarch_do_domctl(domctl, d, u_domctl);
+    {
+        int rc;
+
+        rc = subarch_do_domctl(domctl, d, u_domctl);
+
+        if ( rc == -ENOSYS )
+            rc = iommu_do_domctl(domctl, d, u_domctl);
+
+        return rc;
+    }
     }
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (23 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 24/33] xen/iommu: arm: Wire iommu DOMCTL for ARM Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:17   ` Ian Campbell
  2015-03-31 17:12   ` Daniel De Graaf
  2015-03-19 19:29 ` [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device Julien Grall
                   ` (9 subsequent siblings)
  34 siblings, 2 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Daniel De Graaf, Julien Grall, tim, ian.campbell

This is a follow-up of commit 525ee49 "xsm: add device tree labeling
support" which add support for device tree labelling in flask.

Those helpers will be use latter when non-pci passthrough (i.e device
tree) will be added.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>

---
    Changes in v4:
        - Patch added
---
 xen/include/xsm/dummy.h             | 23 +++++++++++++
 xen/include/xsm/xsm.h               | 27 +++++++++++++++
 xen/xsm/dummy.c                     |  6 ++++
 xen/xsm/flask/avc.c                 |  3 ++
 xen/xsm/flask/hooks.c               | 69 ++++++++++++++++++++++++++++++++++++-
 xen/xsm/flask/include/avc.h         |  2 ++
 xen/xsm/flask/policy/access_vectors |  2 +-
 7 files changed, 130 insertions(+), 2 deletions(-)

diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index da414c7..8157252 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -350,6 +350,29 @@ static XSM_INLINE int xsm_deassign_device(XSM_DEFAULT_ARG struct domain *d, uint
 
 #endif /* HAS_PASSTHROUGH && HAS_PCI */
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+static XSM_INLINE int xsm_test_assign_dtdevice(XSM_DEFAULT_ARG const char *dtpath)
+{
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, NULL);
+}
+
+static XSM_INLINE int xsm_assign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
+                                          const char *dtpath)
+{
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
+}
+
+static XSM_INLINE int xsm_deassign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
+                                            const char *dtpath)
+{
+    XSM_ASSERT_ACTION(XSM_HOOK);
+    return xsm_default_action(action, current->domain, d);
+}
+
+#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
+
 static XSM_INLINE int xsm_resource_plug_core(XSM_DEFAULT_VOID)
 {
     XSM_ASSERT_ACTION(XSM_HOOK);
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 99a59d0..a0eaaa1 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -121,6 +121,12 @@ struct xsm_operations {
     int (*deassign_device) (struct domain *d, uint32_t machine_bdf);
 #endif
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+    int (*test_assign_dtdevice) (const char *dtpath);
+    int (*assign_dtdevice) (struct domain *d, const char *dtpath);
+    int (*deassign_dtdevice) (struct domain *d, const char *dtpath);
+#endif
+
     int (*resource_plug_core) (void);
     int (*resource_unplug_core) (void);
     int (*resource_plug_pci) (uint32_t machine_bdf);
@@ -473,6 +479,27 @@ static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint3
 }
 #endif /* HAS_PASSTHROUGH && HAS_PCI) */
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+static inline int xsm_assign_dtdevice(xsm_default_t def, struct domain *d,
+                                      const char *dtpath)
+{
+    return xsm_ops->assign_dtdevice(d, dtpath);
+}
+
+static inline int xsm_test_assign_dtdevice(xsm_default_t def,
+                                           const char *dtpath)
+{
+    return xsm_ops->test_assign_dtdevice(dtpath);
+}
+
+static inline int xsm_deassign_dtdevice(xsm_default_t def, struct domain *d,
+                                        const char *dtpath)
+{
+    return xsm_ops->deassign_dtdevice(d, dtpath);
+}
+
+#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
+
 static inline int xsm_resource_plug_pci (xsm_default_t def, uint32_t machine_bdf)
 {
     return xsm_ops->resource_plug_pci(machine_bdf);
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index b69a019..cd88e76 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -96,6 +96,12 @@ void xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, deassign_device);
 #endif
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+    set_to_dummy_if_null(ops, test_assign_dtdevice);
+    set_to_dummy_if_null(ops, assign_dtdevice);
+    set_to_dummy_if_null(ops, deassign_dtdevice);
+#endif
+
     set_to_dummy_if_null(ops, resource_plug_core);
     set_to_dummy_if_null(ops, resource_unplug_core);
     set_to_dummy_if_null(ops, resource_plug_pci);
diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c
index b1a4f8a..31bc702 100644
--- a/xen/xsm/flask/avc.c
+++ b/xen/xsm/flask/avc.c
@@ -600,6 +600,9 @@ void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
     case AVC_AUDIT_DATA_MEMORY:
         avc_printk(&buf, "pte=%#lx mfn=%#lx ", a->memory.pte, a->memory.mfn);
         break;
+    case AVC_AUDIT_DATA_DTDEV:
+        avc_printk(&buf, "dtdevice=%s ", a->dtdev);
+        break;
     }
 
     avc_dump_query(&buf, ssid, tsid, tclass);
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index e1cc16a..9652034 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -589,7 +589,12 @@ static int flask_domctl(struct domain *d, int cmd)
     case XEN_DOMCTL_shadow_op:
     case XEN_DOMCTL_ioport_permission:
     case XEN_DOMCTL_ioport_mapping:
-    /* These have individual XSM hooks (drivers/passthrough/iommu.c) */
+#endif
+#ifdef HAS_PASSTHROUGH
+    /*
+     * These have individual XSM hooks
+     * (drivers/passthrough/{pci,device_tree.c)
+     */
     case XEN_DOMCTL_get_device_group:
     case XEN_DOMCTL_test_assign_device:
     case XEN_DOMCTL_assign_device:
@@ -1231,6 +1236,62 @@ static int flask_deassign_device(struct domain *d, uint32_t machine_bdf)
 }
 #endif /* HAS_PASSTHROUGH && HAS_PCI */
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+static int flask_test_assign_dtdevice(const char *dtpath)
+{
+    u32 rsid;
+    int rc = -EPERM;
+
+    rc = security_devicetree_sid(dtpath, &rsid);
+    if ( rc )
+        return rc;
+
+    return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE,
+                                NULL);
+}
+
+static int flask_assign_dtdevice(struct domain *d, const char *dtpath)
+{
+    u32 dsid, rsid;
+    int rc = -EPERM;
+    struct avc_audit_data ad;
+
+    rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
+    if ( rc )
+        return rc;
+
+    rc = security_devicetree_sid(dtpath, &rsid);
+    if ( rc )
+        return rc;
+
+    AVC_AUDIT_DATA_INIT(&ad, DTDEV);
+    ad.dtdev = dtpath;
+    rc = avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, &ad);
+    if ( rc )
+        return rc;
+
+    dsid = domain_sid(d);
+    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+}
+
+static int flask_deassign_dtdevice(struct domain *d, const char *dtpath)
+{
+    u32 rsid;
+    int rc = -EPERM;
+
+    rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
+    if ( rc )
+        return rc;
+
+    rc = security_devicetree_sid(dtpath, &rsid);
+    if ( rc )
+        return rc;
+
+    return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE,
+                                NULL);
+}
+#endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
+
 #ifdef HAS_MEM_ACCESS
 static int flask_mem_event_control(struct domain *d, int mode, int op)
 {
@@ -1598,6 +1659,12 @@ static struct xsm_operations flask_ops = {
     .deassign_device = flask_deassign_device,
 #endif
 
+#if defined(HAS_PASSTHROUGH) && defined(HAS_DEVICE_TREE)
+    .test_assign_dtdevice = flask_test_assign_dtdevice,
+    .assign_dtdevice = flask_assign_dtdevice,
+    .deassign_dtdevice = flask_deassign_dtdevice,
+#endif
+
 #ifdef HAS_MEM_ACCESS
     .mem_event_control = flask_mem_event_control,
     .mem_event_op = flask_mem_event_op,
diff --git a/xen/xsm/flask/include/avc.h b/xen/xsm/flask/include/avc.h
index c7a99fc..4283562 100644
--- a/xen/xsm/flask/include/avc.h
+++ b/xen/xsm/flask/include/avc.h
@@ -39,6 +39,7 @@ struct avc_audit_data {
 #define AVC_AUDIT_DATA_IRQ   2
 #define AVC_AUDIT_DATA_RANGE 3
 #define AVC_AUDIT_DATA_MEMORY 4
+#define AVC_AUDIT_DATA_DTDEV 5
     struct domain *sdom;
     struct domain *tdom;
     union {
@@ -52,6 +53,7 @@ struct avc_audit_data {
             unsigned long pte;
             unsigned long mfn;
         } memory;
+        const char *dtdev;
     };
 };
 
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index 3451f8f..739d62d 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -416,7 +416,7 @@ class resource
     remove_iomem
 # XEN_DOMCTL_get_device_group, XEN_DOMCTL_test_assign_device:
 #  source = domain making the hypercall
-#  target = PCI device being queried
+#  target = device being queried
     stat_device
 # XEN_DOMCTL_assign_device
     add_device
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (24 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-20 11:01   ` Jan Beulich
  2015-03-31 11:24   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 27/33] tools/libxl: Create a per-arch function to map IRQ to a domain Julien Grall
                   ` (8 subsequent siblings)
  34 siblings, 2 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini, Jan Beulich

A device node is described by a path. It will be used to retrieved the
node in the device tree and assign the related device to the domain.

Only non-PCI protected by an IOMMU can be assigned to a guest.

Also document the behavior of XEN_DOMCTL_deassign_device in the public
headers which differ between non-PCI and PCI.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>

---
    Changes in v4:
        - Add XSM bits
        - Return -ENODEV rather than -ENOSYS
        - Move the if (...) into the ifdef (see iommu.c)
        - Document the behavior of XEN_DOMCTL_deassign_device
        - Use PCI_BUS and PCI_DEVFN2 when it's possible
        - iommu_dt_device_is_assigned now returns 0 when the device is
        not protected

    Changes in v2:
        - Use a different number for XEN_DOMCTL_assign_dt_device
---
 tools/libxc/include/xenctrl.h         |  10 ++++
 tools/libxc/xc_domain.c               |  95 ++++++++++++++++++++++++++++--
 xen/drivers/passthrough/device_tree.c | 108 +++++++++++++++++++++++++++++++++-
 xen/drivers/passthrough/iommu.c       |   9 ++-
 xen/drivers/passthrough/pci.c         |  47 ++++++++++-----
 xen/include/public/domctl.h           |  24 +++++++-
 xen/include/xen/iommu.h               |   3 +
 7 files changed, 271 insertions(+), 25 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index b6212bf..4648cb0 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2055,6 +2055,16 @@ int xc_deassign_device(xc_interface *xch,
                      uint32_t domid,
                      uint32_t machine_sbdf);
 
+int xc_assign_dt_device(xc_interface *xch,
+                        uint32_t domid,
+                        char *path);
+int xc_test_assign_dt_device(xc_interface *xch,
+                             uint32_t domid,
+                             char *path);
+int xc_deassign_dt_device(xc_interface *xch,
+                          uint32_t domid,
+                          char *path);
+
 int xc_domain_memory_mapping(xc_interface *xch,
                              uint32_t domid,
                              unsigned long first_gfn,
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 8243b70..924a180 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1633,7 +1633,8 @@ int xc_assign_device(
 
     domctl.cmd = XEN_DOMCTL_assign_device;
     domctl.domain = domid;
-    domctl.u.assign_device.machine_sbdf = machine_sbdf;
+    domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI;
+    domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf;
 
     return do_domctl(xch, &domctl);
 }
@@ -1682,7 +1683,8 @@ int xc_test_assign_device(
 
     domctl.cmd = XEN_DOMCTL_test_assign_device;
     domctl.domain = domid;
-    domctl.u.assign_device.machine_sbdf = machine_sbdf;
+    domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI;
+    domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf;
 
     return do_domctl(xch, &domctl);
 }
@@ -1696,11 +1698,96 @@ int xc_deassign_device(
 
     domctl.cmd = XEN_DOMCTL_deassign_device;
     domctl.domain = domid;
-    domctl.u.assign_device.machine_sbdf = machine_sbdf;
- 
+    domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI;
+    domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf;
+
     return do_domctl(xch, &domctl);
 }
 
+int xc_assign_dt_device(
+    xc_interface *xch,
+    uint32_t domid,
+    char *path)
+{
+    int rc;
+    size_t size = strlen(path);
+    DECLARE_DOMCTL;
+    DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN);
+
+    if ( xc_hypercall_bounce_pre(xch, path) )
+        return -1;
+
+    domctl.cmd = XEN_DOMCTL_assign_device;
+    domctl.domain = (domid_t)domid;
+
+    domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT;
+    domctl.u.assign_device.u.dt.size = size;
+    set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path);
+
+    rc = do_domctl(xch, &domctl);
+
+    xc_hypercall_bounce_post(xch, path);
+
+    return rc;
+}
+
+int xc_test_assign_dt_device(
+    xc_interface *xch,
+    uint32_t domid,
+    char *path)
+{
+    int rc;
+    size_t size = strlen(path);
+    DECLARE_DOMCTL;
+    DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN);
+
+    if ( xc_hypercall_bounce_pre(xch, path) )
+        return -1;
+
+    domctl.cmd = XEN_DOMCTL_test_assign_device;
+    domctl.domain = (domid_t)domid;
+
+    domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT;
+    domctl.u.assign_device.u.dt.size = size;
+    set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path);
+
+    rc = do_domctl(xch, &domctl);
+
+    xc_hypercall_bounce_post(xch, path);
+
+    return rc;
+}
+
+int xc_deassign_dt_device(
+    xc_interface *xch,
+    uint32_t domid,
+    char *path)
+{
+    int rc;
+    size_t size = strlen(path);
+    DECLARE_DOMCTL;
+    DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN);
+
+    if ( xc_hypercall_bounce_pre(xch, path) )
+        return -1;
+
+    domctl.cmd = XEN_DOMCTL_deassign_device;
+    domctl.domain = (domid_t)domid;
+
+    domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT;
+    domctl.u.assign_device.u.dt.size = size;
+    set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path);
+
+    rc = do_domctl(xch, &domctl);
+
+    xc_hypercall_bounce_post(xch, path);
+
+    return rc;
+}
+
+
+
+
 int xc_domain_update_msi_irq(
     xc_interface *xch,
     uint32_t domid,
diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c
index 0ec4103..c37efeb 100644
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -1,9 +1,6 @@
 /*
  * Code to passthrough a device tree node to a guest
  *
- * TODO: This contains only the necessary code to protected device passed to
- * dom0. It will need some updates when device passthrough will is added.
- *
  * Julien Grall <julien.grall@linaro.org>
  * Copyright (c) 2014 Linaro Limited.
  *
@@ -20,8 +17,10 @@
 
 #include <xen/lib.h>
 #include <xen/sched.h>
+#include <xen/guest_access.h>
 #include <xen/iommu.h>
 #include <xen/device_tree.h>
+#include <xsm/xsm.h>
 
 static spinlock_t dtdevs_lock = SPIN_LOCK_UNLOCKED;
 
@@ -93,6 +92,20 @@ fail:
     return rc;
 }
 
+static bool_t iommu_dt_device_is_assigned(const struct dt_device_node *dev)
+{
+    bool_t assigned = 0;
+
+    if ( !dt_device_is_protected(dev) )
+        return 0;
+
+    spin_lock(&dtdevs_lock);
+    assigned = !list_empty(&dev->domain_list);
+    spin_unlock(&dtdevs_lock);
+
+    return assigned;
+}
+
 int iommu_dt_domain_init(struct domain *d)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
@@ -121,3 +134,92 @@ int iommu_release_dt_devices(struct domain *d)
 
     return 0;
 }
+
+int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d,
+                       XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
+{
+    int ret;
+    struct dt_device_node *dev;
+
+    /* TODO: How to deal with XSM? */
+    /* TODO: Do we need to check is_dying? Mostly to protect against
+     * hypercall trying to passthrough a device while we are
+     * dying.
+     */
+
+    switch ( domctl->cmd )
+    {
+    case XEN_DOMCTL_assign_device:
+        ret = -ENODEV;
+        if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT )
+            break;
+
+        ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path,
+                                    domctl->u.assign_device.u.dt.size,
+                                    &dev);
+        if ( ret )
+            break;
+
+        ret = xsm_assign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev));
+        if ( ret )
+            break;
+
+        ret = iommu_assign_dt_device(d, dev);
+
+        if ( ret )
+            printk(XENLOG_G_ERR "XEN_DOMCTL_assign_dt_device: assign \"%s\""
+                   " to dom%u failed (%d)\n",
+                   dt_node_full_name(dev), d->domain_id, ret);
+        break;
+
+    case XEN_DOMCTL_deassign_device:
+        ret = -ENODEV;
+        if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT )
+            break;
+
+        ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path,
+                                    domctl->u.assign_device.u.dt.size,
+                                    &dev);
+        if ( ret )
+            break;
+
+        ret = xsm_deassign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev));
+
+        ret = iommu_deassign_dt_device(d, dev);
+
+        if ( ret )
+            printk(XENLOG_G_ERR "XEN_DOMCTL_assign_dt_device: assign \"%s\""
+                   " to dom%u failed (%d)\n",
+                   dt_node_full_name(dev), d->domain_id, ret);
+        break;
+
+    case XEN_DOMCTL_test_assign_device:
+        ret = -ENODEV;
+        if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT )
+            break;
+
+        ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path,
+                                    domctl->u.assign_device.u.dt.size,
+                                    &dev);
+        if ( ret )
+            break;
+
+        ret = xsm_test_assign_dtdevice(XSM_HOOK, dt_node_full_name(dev));
+        if ( ret )
+            break;
+
+        if ( iommu_dt_device_is_assigned(dev) )
+        {
+            printk(XENLOG_G_ERR "%s already assigned.\n",
+                   dt_node_full_name(dev));
+            ret = -EINVAL;
+        }
+        break;
+
+    default:
+        ret = -ENOSYS;
+        break;
+    }
+
+    return ret;
+}
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index faddd50..a5d0831 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -335,7 +335,7 @@ int iommu_do_domctl(
     struct xen_domctl *domctl, struct domain *d,
     XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
 {
-    int ret = -ENOSYS;
+    int ret = -ENODEV;
 
     if ( !iommu_enabled )
         return -ENOSYS;
@@ -344,6 +344,13 @@ int iommu_do_domctl(
     ret = iommu_do_pci_domctl(domctl, d, u_domctl);
 #endif
 
+#ifdef HAS_DEVICE_TREE
+    if ( ret != -ENODEV)
+        return ret;
+
+    ret = iommu_do_dt_domctl(domctl, d, u_domctl);
+#endif
+
     return ret;
 }
 
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 18b74f4..5ddfd8d 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -1495,6 +1495,7 @@ int iommu_do_pci_domctl(
     u16 seg;
     u8 bus, devfn;
     int ret = 0;
+    uint32_t machine_sbdf;
 
     switch ( domctl->cmd )
     {
@@ -1508,8 +1509,8 @@ int iommu_do_pci_domctl(
             break;
 
         seg = domctl->u.get_device_group.machine_sbdf >> 16;
-        bus = (domctl->u.get_device_group.machine_sbdf >> 8) & 0xff;
-        devfn = domctl->u.get_device_group.machine_sbdf & 0xff;
+        bus = PCI_BUS(domctl->u.get_device_group.machine_sbdf);
+        devfn = PCI_DEVFN2(domctl->u.get_device_group.machine_sbdf);
         max_sdevs = domctl->u.get_device_group.max_sdevs;
         sdevs = domctl->u.get_device_group.sdev_array;
 
@@ -1531,13 +1532,19 @@ int iommu_do_pci_domctl(
     break;
 
     case XEN_DOMCTL_test_assign_device:
-        ret = xsm_test_assign_device(XSM_HOOK, domctl->u.assign_device.machine_sbdf);
+        ret = -ENODEV;
+        if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_PCI )
+            break;
+
+        machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf;
+
+        ret = xsm_test_assign_device(XSM_HOOK, machine_sbdf);
         if ( ret )
             break;
 
-        seg = domctl->u.assign_device.machine_sbdf >> 16;
-        bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
-        devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+        seg = machine_sbdf >> 16;
+        bus = PCI_BUS(machine_sbdf);
+        devfn = PCI_DEVFN2(machine_sbdf);
 
         if ( device_assigned(seg, bus, devfn) )
         {
@@ -1549,19 +1556,25 @@ int iommu_do_pci_domctl(
         break;
 
     case XEN_DOMCTL_assign_device:
+        ret = -ENODEV;
+        if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_PCI )
+            break;
+
         if ( unlikely(d->is_dying) )
         {
             ret = -EINVAL;
             break;
         }
 
-        ret = xsm_assign_device(XSM_HOOK, d, domctl->u.assign_device.machine_sbdf);
+        machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf;
+
+        ret = xsm_assign_device(XSM_HOOK, d, machine_sbdf);
         if ( ret )
             break;
 
-        seg = domctl->u.assign_device.machine_sbdf >> 16;
-        bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
-        devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+        seg = machine_sbdf >> 16;
+        bus = PCI_BUS(machine_sbdf);
+        devfn = PCI_DEVFN2(machine_sbdf);
 
         ret = device_assigned(seg, bus, devfn) ?:
               assign_device(d, seg, bus, devfn);
@@ -1577,13 +1590,19 @@ int iommu_do_pci_domctl(
         break;
 
     case XEN_DOMCTL_deassign_device:
-        ret = xsm_deassign_device(XSM_HOOK, d, domctl->u.assign_device.machine_sbdf);
+        ret = -ENODEV;
+        if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_PCI )
+            break;
+
+        machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf;
+
+        ret = xsm_deassign_device(XSM_HOOK, d, machine_sbdf);
         if ( ret )
             break;
 
-        seg = domctl->u.assign_device.machine_sbdf >> 16;
-        bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
-        devfn = domctl->u.assign_device.machine_sbdf & 0xff;
+        seg = machine_sbdf >> 16;
+        bus = PCI_BUS(machine_sbdf);
+        devfn = PCI_DEVFN2(machine_sbdf);
 
         spin_lock(&pcidevs_lock);
         ret = deassign_device(d, seg, bus, devfn);
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 7f90150..a7cb272 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -475,12 +475,30 @@ typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
 
 
-/* Assign PCI device to HVM guest. Sets up IOMMU structures. */
+/* Assign a device to a guest. Sets up IOMMU structures. */
 /* XEN_DOMCTL_assign_device */
 /* XEN_DOMCTL_test_assign_device */
-/* XEN_DOMCTL_deassign_device */
+/*
+ * XEN_DOMCTL_deassign_device: The behavior of this DOMCTL differs
+ * between the different type of device:
+ *  - PCI device (XEN_DOMCTL_DEV_PCI) will be reassigned to DOM0
+ *  - non-PCI device (XEN_DOMCTL_DEV_PCI) will left unassigned. DOM0
+ *  will have to call XEN_DOMCTL_assign_device in order to use the
+ *  device.
+ */
+#define XEN_DOMCTL_DEV_PCI      0
+#define XEN_DOMCTL_DEV_DT       1
 struct xen_domctl_assign_device {
-    uint32_t  machine_sbdf;   /* machine PCI ID of assigned device */
+    uint32_t dev;   /* XEN_DOMCTL_DEV_* */
+    union {
+        struct {
+            uint32_t machine_sbdf;   /* machine PCI ID of assigned device */
+        } pci;
+        struct {
+            uint32_t size; /* Length of the path */
+            XEN_GUEST_HANDLE_64(char) path; /* path to the device tree node */
+        } dt;
+    } u;
 };
 typedef struct xen_domctl_assign_device xen_domctl_assign_device_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t);
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index d9c9ede..b30bf41 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -119,6 +119,9 @@ int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev);
 int iommu_dt_domain_init(struct domain *d);
 int iommu_release_dt_devices(struct domain *d);
 
+int iommu_do_dt_domctl(struct xen_domctl *, struct domain *,
+                       XEN_GUEST_HANDLE_PARAM(xen_domctl_t));
+
 #endif /* HAS_DEVICE_TREE */
 
 struct page_info;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 27/33] tools/libxl: Create a per-arch function to map IRQ to a domain
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (25 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:26   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt Julien Grall
                   ` (7 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini

ARM and x86 use a different hypercall to map an IRQ to a domain.

The hypercall to give IRQ permission to the domain as also been moved
on the x86 specific function as ARM guest won't be able to manage the IRQ.
We may want to support it later.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>

---
    Changes in v4:
        - Patch added
---
 tools/libxl/libxl_arch.h   |  4 ++++
 tools/libxl/libxl_arm.c    |  7 +++++++
 tools/libxl/libxl_create.c |  6 ++----
 tools/libxl/libxl_x86.c    | 13 +++++++++++++
 4 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
index cae64c0..77b1f2a 100644
--- a/tools/libxl/libxl_arch.h
+++ b/tools/libxl/libxl_arch.h
@@ -39,4 +39,8 @@ int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
                                       uint32_t domid,
                                       libxl_domain_build_info *b_info,
                                       libxl__domain_build_state *state);
+
+/* arch specific irq map function */
+int libxl__arch_domain_map_irq(libxl__gc *gc, uint32_t domid, int irq);
+
 #endif
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 2407c2e..06e940b 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -742,6 +742,13 @@ int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
     return libxl__vnuma_build_vmemrange_pv_generic(gc, domid, info, state);
 }
 
+int libxl__arch_domain_map_irq(libxl__gc *gc, uint32_t domid, int irq)
+{
+    return xc_domain_bind_pt_irq(CTX->xch, domid, irq, PT_IRQ_TYPE_SPI,
+                                 0 /* Not used */, 0 /* Not used */,
+                                 0 /* Not used */, irq);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index e5a343f..15b464e 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -1205,11 +1205,9 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
 
         LOG(DEBUG, "dom%d irq %d", domid, irq);
 
-        ret = irq >= 0 ? xc_physdev_map_pirq(CTX->xch, domid, irq, &irq)
+        ret = irq >= 0 ? libxl__arch_domain_map_irq(gc, domid, irq)
                        : -EOVERFLOW;
-        if (!ret)
-            ret = xc_domain_irq_permission(CTX->xch, domid, irq, 1);
-        if (ret < 0) {
+        if (ret) {
             LOGE(ERROR, "failed give dom%d access to irq %d", domid, irq);
             ret = ERROR_FAIL;
             goto error_out;
diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
index 3149896..9f6ec18 100644
--- a/tools/libxl/libxl_x86.c
+++ b/tools/libxl/libxl_x86.c
@@ -427,6 +427,19 @@ out:
     return rc;
 }
 
+int libxl__arch_domain_map_irq(libxl__gc *gc, uint32_t domid, int irq)
+{
+    int ret;
+
+    ret = xc_physdev_map_pirq(CTX->xch, domid, irq, &irq);
+    if (ret)
+        return ret;
+
+    ret = xc_domain_irq_permission(CTX->xch, domid, irq, 1);
+
+    return ret;
+}
+
 /*
  * Local variables:
  * mode: C
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (26 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 27/33] tools/libxl: Create a per-arch function to map IRQ to a domain Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-19 19:42   ` Julien Grall
  2015-03-31 11:35   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM Julien Grall
                   ` (6 subsequent siblings)
  34 siblings, 2 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini

The functions fdt_{fisrt,next}_subnode may not be available because:
    * It has been introduced in 2013 => Doesn't work on Wheezy
    * The prototype exists but the functions are not exposed. Don't ask
    why...

The later has been fixed recently in the dtc repo [1]

When the functions are not available, implement our own in order to use
them in a following patch.

[1] git://git.kernel.org/pub/scm/utils/dtc/dtc.git
    commit a4b093f7366fdb429ca1781144d3985fa50d0fbb

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>

---

    Changes in v4:
        - Patch added
---
 tools/config.h.in       |  6 ++++
 tools/configure.ac      |  5 +++
 tools/libxl/Makefile    |  2 +-
 tools/libxl/libxl_fdt.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 tools/libxl/libxl_fdt.c

diff --git a/tools/config.h.in b/tools/config.h.in
index 2a0ae48..06f8b6c 100644
--- a/tools/config.h.in
+++ b/tools/config.h.in
@@ -3,6 +3,12 @@
 /* Blktap2 enabled */
 #undef HAVE_BLKTAP2
 
+/* Define to 1 if you have the `fdt_first_subnode' function. */
+#undef HAVE_FDT_FIRST_SUBNODE
+
+/* Define to 1 if you have the `fdt_next_subnode' function. */
+#undef HAVE_FDT_NEXT_SUBNODE
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
diff --git a/tools/configure.ac b/tools/configure.ac
index d31c2f3..cc13336 100644
--- a/tools/configure.ac
+++ b/tools/configure.ac
@@ -355,6 +355,11 @@ AC_SUBST(libiconv)
 case "$host_cpu" in
 arm*|aarch64)
 AC_CHECK_LIB([fdt], [fdt_create], [], [AC_MSG_ERROR([Could not find libfdt])])
+
+# The functions fdt_{first,next}_subnode may not be available because:
+#   * It has been introduced in 2013 => Doesn't work on Wheezy
+#   * The prototype exists but the functions are not exposed. Don't ask why...
+AC_CHECK_FUNCS([fdt_first_subnode fdt_next_subnode])
 esac
 
 # Checks for header files.
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 1b16598..d74aee1 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -59,7 +59,7 @@ endif
 LIBXL_OBJS-y += libxl_remus_device.o libxl_remus_disk_drbd.o
 
 LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o libxl_psr.o
-LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o libxl_arm.o
+LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o libxl_arm.o libxl_fdt.o
 
 ifeq ($(CONFIG_NetBSD),y)
 LIBXL_OBJS-y += libxl_netbsd.o
diff --git a/tools/libxl/libxl_fdt.c b/tools/libxl/libxl_fdt.c
new file mode 100644
index 0000000..f88e9f1
--- /dev/null
+++ b/tools/libxl/libxl_fdt.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libfdt.h>
+
+#ifndef HAVE_FDT_FIRST_SUBNODE
+int fdt_first_subnode(const void *fdt, int offset)
+{
+	int depth = 0;
+
+	offset = fdt_next_node(fdt, offset, &depth);
+	if (offset < 0 || depth != 1)
+		return -FDT_ERR_NOTFOUND;
+
+	return offset;
+}
+#endif
+
+#ifndef HAVE_FDT_NEXT_SUBNODE
+int fdt_next_subnode(const void *fdt, int offset)
+{
+	int depth = 1;
+
+	/*
+	 * With respect to the parent, the depth of the next subnode will be
+	 * the same as the last.
+	 */
+	do {
+		offset = fdt_next_node(fdt, offset, &depth);
+		if (offset < 0 || depth < 1)
+			return -FDT_ERR_NOTFOUND;
+	} while (depth > 1);
+
+	return offset;
+}
+#endif
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (27 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:41   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 30/33] tools/libxl: arm: Use an higher value for the GIC phandle Julien Grall
                   ` (5 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini

Let the user to pass additional nodes to the guest device tree. For
this purpose, everything in the node /passthrough from the partial
device tree will be copied into the guest device tree.

The node /aliases will be also copied to allow the user to define
aliases which can be used by the guest kernel.

A simple partial device tree will look like:

/dts-v1/;

/ {
        #address-cells = <2>;
        #size-cells = <2>;

        passthrough {
            compatible = "simple-bus";
            ranges;
            #address-cells = <2>;
            #size-cells = <2>;

            /* List of your nodes */
        }
};

Note that:
    * The interrupt-parent property will be added by the toolstack in
    the root node
    * The properties compatible, ranges, #address-cells and #size-cells
    in /passthrough are mandatory.

The helpers provided by the libfdt don't perform all the necessary
security check on a given device tree. Therefore, only trusted device
tree should be used.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>

---
    An example of the partial device tree, as long as how to passthrough
    a non-pci device will be added to the tree in a follow-up patch.

    A new LIBXL_HAVE_* will be added in the patch which add support for
    non-PCI passthrough as both are tight.

    Changes in v4:
        - Mark the option as unsafe
        - The _fdt_* helpers has been moved in a separate patch/file.
        Only the prototype is declared
        - The partial DT is considered valid. Remove some security check
        which make the code cleaner
        - Typoes

    Changes in v3:
        - Patch added
---
 docs/man/xl.cfg.pod.5       |  10 +++
 tools/libxl/libxl_arm.c     | 171 ++++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_types.idl |   1 +
 tools/libxl/xl_cmdimpl.c    |   1 +
 4 files changed, 183 insertions(+)

diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index 93cd7d2..bcbc277 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -453,6 +453,16 @@ not emulated.
 Specify that this domain is a driver domain. This enables certain
 features needed in order to run a driver domain.
 
+=item B<device_tree=PATH>
+
+Specify a partial device tree (compiled via the Device Tree Compiler).
+Everything under the node "/passthrough" will be copied into the guest
+device tree. For convenience, the node "/aliases" is also copied to allow
+the user to defined aliases which can be used by the guest kernel.
+
+Given the complexity of verifying the validity of a device tree, this
+option should only be used with trusted device tree.
+
 =back
 
 =head2 Devices
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 06e940b..54d197b 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -542,6 +542,156 @@ out:
     }
 }
 
+/* Only FDT v17 is supported */
+#define FDT_REQUIRED_VERSION    0x11
+
+static int check_partial_fdt(libxl__gc *gc, void *fdt, size_t size)
+{
+    int r;
+
+    if (size < FDT_V17_SIZE) {
+        LOG(ERROR, "Partial FDT is too small");
+        return ERROR_FAIL;
+    }
+
+    if (fdt_magic(fdt) != FDT_MAGIC) {
+        LOG(ERROR, "Partial FDT is not a valid Flat Device Tree");
+        return ERROR_FAIL;
+    }
+
+    if (fdt_version(fdt) != FDT_REQUIRED_VERSION) {
+        LOG(ERROR, "Partial FDT version not supported. Required 0x%x got 0x%x",
+            FDT_REQUIRED_VERSION, fdt_version(fdt));
+        return ERROR_FAIL;
+    }
+
+    r = fdt_check_header(fdt);
+    if (r) {
+        LOG(ERROR, "Failed to check the partial FDT (%d)", r);
+        return ERROR_FAIL;
+    }
+
+    if (fdt_totalsize(fdt) > size) {
+        LOG(ERROR, "Partial FDT totalsize is too big");
+        return ERROR_FAIL;
+    }
+
+    return 0;
+}
+
+static int copy_properties(libxl__gc *gc, void *fdt, void *pfdt,
+                           int nodeoff)
+{
+    int propoff, nameoff, r;
+    const struct fdt_property *prop;
+
+    for (propoff = fdt_first_property_offset(pfdt, nodeoff);
+         propoff >= 0;
+         propoff = fdt_next_property_offset(pfdt, propoff)) {
+
+        if (!(prop = fdt_get_property_by_offset(pfdt, propoff, NULL))) {
+            return -FDT_ERR_INTERNAL;
+        }
+
+        nameoff = fdt32_to_cpu(prop->nameoff);
+        r = fdt_property(fdt, fdt_string(pfdt, nameoff),
+                         prop->data, fdt32_to_cpu(prop->len));
+        if (r) return r;
+    }
+
+    /* FDT_ERR_NOTFOUND => There is no more properties for this node */
+    return (propoff != -FDT_ERR_NOTFOUND)? propoff : 0;
+}
+
+/*
+ * These functions are defined by libfdt or libxl_fdt.c if it's not
+ * present on the former.
+ */
+int fdt_next_subnode(const void *fdt, int offset);
+int fdt_first_subnode(const void *fdt, int offset);
+
+/* Copy a node from the partial device tree to the guest device tree */
+static int copy_node(libxl__gc *gc, void *fdt, void *pfdt,
+                     int nodeoff, int depth)
+{
+    int r;
+
+    r = fdt_begin_node(fdt, fdt_get_name(pfdt, nodeoff, NULL));
+    if (r) return r;
+
+    r = copy_properties(gc, fdt, pfdt, nodeoff);
+    if (r) return r;
+
+    for (nodeoff = fdt_first_subnode(pfdt, nodeoff);
+         nodeoff >= 0;
+         nodeoff = fdt_next_subnode(pfdt, nodeoff)) {
+        r = copy_node(gc, fdt, pfdt, nodeoff, depth + 1);
+        if (r) return r;
+    }
+
+    if (nodeoff != -FDT_ERR_NOTFOUND)
+        return nodeoff;
+
+    r = fdt_end_node(fdt);
+    if (r) return r;
+
+    return 0;
+}
+
+static int copy_node_by_path(libxl__gc *gc, const char *path,
+                             void *fdt, void *pfdt)
+{
+    int nodeoff, r;
+    const char *name = strrchr(path, '/');
+
+    if (!name)
+        return -FDT_ERR_INTERNAL;
+
+    name++;
+
+    /*
+     * The FDT function to look at a node doesn't take into account the
+     * unit (i.e anything after @) when search by name. Check if the
+     * name exactly matches.
+     */
+    nodeoff = fdt_path_offset(pfdt, path);
+    if (nodeoff < 0)
+        return nodeoff;
+
+    if (strcmp(fdt_get_name(pfdt, nodeoff, NULL), name))
+        return -FDT_ERR_NOTFOUND;
+
+    r = copy_node(gc, fdt, pfdt, nodeoff, 0);
+    if (r) return r;
+
+    return 0;
+}
+
+/*
+ * The partial device tree is not copied entirely. Only the relevant bits are
+ * copied to the guest device tree:
+ *  - /passthrough node
+ *  - /aliases node
+ */
+static int copy_partial_fdt(libxl__gc *gc, void *fdt, void *pfdt)
+{
+    int r;
+
+    r = copy_node_by_path(gc, "/passthrough", fdt, pfdt);
+    if (r < 0) {
+        LOG(ERROR, "Can't copy the node \"/passthrough\" from the partial FDT");
+        return r;
+    }
+
+    r = copy_node_by_path(gc, "/aliases", fdt, pfdt);
+    if (r < 0 && r != -FDT_ERR_NOTFOUND) {
+        LOG(ERROR, "Can't copy the node \"/aliases\" from the partial FDT");
+        return r;
+    }
+
+    return 0;
+}
+
 #define FDT_MAX_SIZE (1<<20)
 
 int libxl__arch_domain_init_hw_description(libxl__gc *gc,
@@ -550,8 +700,10 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc,
                                            struct xc_dom_image *dom)
 {
     void *fdt = NULL;
+    void *pfdt = NULL;
     int rc, res;
     size_t fdt_size = 0;
+    int pfdt_size = 0;
 
     const libxl_version_info *vers;
     const struct arch_info *ainfo;
@@ -571,6 +723,22 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc,
         vers->xen_version_major, vers->xen_version_minor);
     LOG(DEBUG, " - vGIC version: %s\n", gicv_to_string(xc_config->gic_version));
 
+    if (info->device_tree) {
+        LOG(DEBUG, " - Partial device tree provided: %s", info->device_tree);
+
+        rc = libxl_read_file_contents(CTX, info->device_tree,
+                                      &pfdt, &pfdt_size);
+        if (rc) {
+            LOGEV(ERROR, rc, "failed to read the partial device file %s",
+                  info->device_tree);
+            return ERROR_FAIL;
+        }
+        libxl__ptr_add(gc, pfdt);
+
+        if (check_partial_fdt(gc, pfdt, pfdt_size))
+            return ERROR_FAIL;
+    }
+
 /*
  * Call "call" handling FDT_ERR_*. Will either:
  * - loop back to retry_resize
@@ -637,6 +805,9 @@ next_resize:
         FDT( make_timer_node(gc, fdt, ainfo) );
         FDT( make_hypervisor_node(gc, fdt, vers) );
 
+        if (pfdt)
+            FDT( copy_partial_fdt(gc, fdt, pfdt) );
+
         FDT( fdt_end_node(fdt) );
 
         FDT( fdt_finish(fdt) );
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 0866433..c97e6ed 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -411,6 +411,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
     ("kernel",           string),
     ("cmdline",          string),
     ("ramdisk",          string),
+    ("device_tree",      string),
     ("u", KeyedUnion(None, libxl_domain_type, "type",
                 [("hvm", Struct(None, [("firmware",         string),
                                        ("bios",             libxl_bios_type),
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 394b55d..c2415ba 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1379,6 +1379,7 @@ static void parse_config_data(const char *config_source,
 
     xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
     xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
+    xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0);
     b_info->cmdline = parse_cmdline(config);
 
     xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 30/33] tools/libxl: arm: Use an higher value for the GIC phandle
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (28 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:43   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 31/33] libxl: Add support for non-PCI passthrough Julien Grall
                   ` (4 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini

The partial device tree may contains phandle. The Device Tree Compiler
tends to allocate the phandle from 1.

Reserve the ID 65000 for the GIC phandle. I think we can safely assume
that the partial device tree will never contain a such ID.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>

---
    It's not easily possible to track the maximum phandle in the partial
    device tree.

    We would need to parse it twice: one for looking the maximum
    phandle, and one for copying the nodes. This is because we have to
    know the phandle of the GIC when we create the properties of the
    root.

    As the phandle is encoded an unsigned 32 bits, I could use an higher
    value. Though, having 65000 phandle is already a lot...

    TODO: If it's necessary, I can check if the value has been used by
    another phandle in the device tree.

    Changes in v3:
        - Patch added
---
 tools/libxl/libxl_arm.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 54d197b..0723a47 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -80,10 +80,11 @@ static struct arch_info {
     {"xen-3.0-aarch64", "arm,armv8-timer", "arm,armv8" },
 };
 
-enum {
-    PHANDLE_NONE = 0,
-    PHANDLE_GIC,
-};
+/*
+ * The device tree compiler (DTC) is allocating the phandle from 1 to
+ * onwards. Reserve a high value for the GIC phandle.
+ */
+#define PHANDLE_GIC (65000)
 
 typedef uint32_t be32;
 typedef be32 gic_interrupt[3];
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 31/33] libxl: Add support for non-PCI passthrough
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (29 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 30/33] tools/libxl: arm: Use an higher value for the GIC phandle Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:49   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 32/33] xl: Add new option dtdev Julien Grall
                   ` (3 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini

On ARM, every non-PCI device are described in the device tree. Each of
them can be found via a path.

This patch introduces a very basic support, only the IOMMU will be set
up correctly. The user will have to:
    - Describe the device in the partial device tree
    - Map manually MMIO/IRQ

This is a first approach, that will allow to have a basic non-PCI
passthrough support in Xen. This could be improved later.

Furthermore add LIBXL_HAVE_DEVICETREE_PASSTHROUGH to indicate we
support non-PCI passthrough and partial device tree (introduced by a
previous patch).

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>

---
    Changes in v4:
        - Add LIBXL_HAVE_DEVICTREE_PASSTHROUGH to indicate we support
        non-PCI passthrough. This is also used in order to indicate
        partial device tree is supported
        - Remove libxl_dtdev.c as it contains only a 2 lines functions
        and call directly xc_* from libxl_create.c
        - Introduce domcreate_attach_dtdev

    Changes in v3:
        - Dynamic allocation has been dropped
        - Rework the commit message in accordance with the previous
        item

    Changes in v2:
        - Get DT infos earlier
        - Allocate/map IRQ in libxl__arch_domain_create rather than in
        libxl__device_dt_add
        - Use VIRQ rather than the PIRQ to construct the interrupts
        properties of the device tree
        - Correct cpumask in make_dtdev_node. We allow the interrupt to
        be used on the 8 CPUs
        - Fix LOGE when we map the MMIO region in the guest in
        libxl__device_dt_add. The domain and the IRQ were inverted
        - Calculate the number of SPIs to configure the VGIC
        - xc_physdev_dtdev_* helpers has been renamed to xc_dtdev_*
        - Rename libxl_device_dt to libxl_device_dtdev
---
 tools/libxl/libxl.h          |  6 ++++++
 tools/libxl/libxl_create.c   | 32 ++++++++++++++++++++++++++++++++
 tools/libxl/libxl_internal.h |  5 +++++
 tools/libxl/libxl_types.idl  |  5 +++++
 4 files changed, 48 insertions(+)

diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 6bc75c5..baaf06b 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -179,6 +179,12 @@
 #define LIBXL_HAVE_BUILDINFO_HVM_MMIO_HOLE_MEMKB 1
 
 /*
+ * libxl_domain_build_info has device_tree and libxl_device_dtdev
+ * exists. This mean non-PCI passthrough is supported for ARM
+ */
+#define LIBXL_HAVE_DEVICETREE_PASSTHROUGH 1
+
+/*
  * libxl ABI compatibility
  *
  * The only guarantee which libxl makes regarding ABI compatibility
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 15b464e..39c828b 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -751,6 +751,8 @@ static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
                                  int ret);
+static void domcreate_attach_dtdev(libxl__egc *egc,
+                                   libxl__domain_create_state *dcs);
 
 static void domcreate_console_available(libxl__egc *egc,
                                         libxl__domain_create_state *dcs);
@@ -1444,6 +1446,36 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
         }
     }
 
+    domcreate_attach_dtdev(egc, dcs);
+    return;
+
+error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_dtdev(libxl__egc *egc,
+                                   libxl__domain_create_state *dcs)
+{
+    STATE_AO_GC(dcs->ao);
+    int i;
+    int ret;
+    int domid = dcs->guest_domid;
+
+    /* convenience aliases */
+    libxl_domain_config *const d_config = dcs->guest_config;
+
+    for (i = 0; i < d_config->num_dtdevs; i++) {
+        const libxl_device_dtdev *dtdev = &d_config->dtdevs[i];
+
+        LOG(DEBUG, "Assign device \"%s\" to dom%u", dtdev->path, domid);
+        ret = xc_assign_dt_device(CTX->xch, domid, dtdev->path);
+        if (ret < 0) {
+            LOG(ERROR, "xc_assign_dtdevice failed: %d\n", ret);
+            goto error_out;
+        }
+    }
+
     domcreate_console_available(egc, dcs);
 
     domcreate_complete(egc, dcs, 0);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 46fa624..1191098 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1198,6 +1198,11 @@ _hidden int libxl__create_pci_backend(libxl__gc *gc, uint32_t domid,
                                       libxl_device_pci *pcidev, int num);
 _hidden int libxl__device_pci_destroy_all(libxl__gc *gc, uint32_t domid);
 
+/* from libxl_dtdev */
+
+_hidden int libxl__device_dt_add(libxl__gc *gc, uint32_t domid,
+                                 const libxl_device_dtdev *dtdev);
+
 /*----- xswait: wait for a xenstore node to be suitable -----*/
 
 typedef struct libxl__xswait_state libxl__xswait_state;
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index c97e6ed..2ab8587 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -534,6 +534,10 @@ libxl_device_pci = Struct("device_pci", [
     ("seize", bool),
     ])
 
+libxl_device_dtdev = Struct("device_dtdev", [
+    ("path", string),
+    ])
+
 libxl_device_vtpm = Struct("device_vtpm", [
     ("backend_domid",    libxl_domid),
     ("backend_domname",  string),
@@ -560,6 +564,7 @@ libxl_domain_config = Struct("domain_config", [
     ("disks", Array(libxl_device_disk, "num_disks")),
     ("nics", Array(libxl_device_nic, "num_nics")),
     ("pcidevs", Array(libxl_device_pci, "num_pcidevs")),
+    ("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")),
     ("vfbs", Array(libxl_device_vfb, "num_vfbs")),
     ("vkbs", Array(libxl_device_vkb, "num_vkbs")),
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 32/33] xl: Add new option dtdev
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (30 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 31/33] libxl: Add support for non-PCI passthrough Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:50   ` Ian Campbell
  2015-03-19 19:29 ` [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough Julien Grall
                   ` (2 subsequent siblings)
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini

The option "dtdev" will be used to passthrough a non-PCI device described
in the device tree to a guest.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>

---
    Changes in v4:
        - Typoes in the documentation
        - Wrap the line in xl_cmdimpl.c

    Changes in v2:
        - libxl_device_dt has been rename to libxl_device_dtdev
        - use xrealloc instead of realloc
---
 docs/man/xl.cfg.pod.5    |  5 +++++
 tools/libxl/xl_cmdimpl.c | 22 +++++++++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index bcbc277..9241000 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -779,6 +779,11 @@ More information about Xen gfx_passthru feature is available
 on the XenVGAPassthrough L<http://wiki.xen.org/wiki/XenVGAPassthrough>
 wiki page.
 
+=item B<dtdev=[ "DTDEV_PATH", "DTDEV_PATH", ... ]>
+
+Specifies the host device tree nodes to passthrough to this guest. Each
+DTDEV_PATH is the absolute path in the device tree.
+
 =item B<ioports=[ "IOPORT_RANGE", "IOPORT_RANGE", ... ]>
 
 Allow guest to access specific legacy I/O ports. Each B<IOPORT_RANGE>
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index c2415ba..ed82b6a 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1169,7 +1169,7 @@ static void parse_config_data(const char *config_source,
     long l, vcpus = 0;
     XLU_Config *config;
     XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms;
-    XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian;
+    XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
     int pci_power_mgmt = 0;
     int pci_msitranslate = 0;
@@ -1941,6 +1941,26 @@ skip_vfb:
             libxl_defbool_set(&b_info->u.pv.e820_host, true);
     }
 
+    if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) {
+        d_config->num_dtdevs = 0;
+        d_config->dtdevs = NULL;
+        for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) {
+            libxl_device_dtdev *dtdev;
+
+            d_config->dtdevs = xrealloc(d_config->dtdevs,
+                                        sizeof (libxl_device_dtdev) * (i + 1));
+            dtdev = d_config->dtdevs + d_config->num_dtdevs;
+            libxl_device_dtdev_init(dtdev);
+
+            dtdev->path = strdup(buf);
+            if (dtdev->path == NULL) {
+                fprintf(stderr, "unable to duplicate string for dtdevs\n");
+                exit(-1);
+            }
+            d_config->num_dtdevs++;
+        }
+    }
+
     switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
     case 0:
         {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (31 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 32/33] xl: Add new option dtdev Julien Grall
@ 2015-03-19 19:29 ` Julien Grall
  2015-03-31 11:55   ` Ian Campbell
  2015-03-20  1:22 ` [PATCH v4 00/33] xen/arm: Add support for " Edgar E. Iglesias
  2015-03-31 11:57 ` Ian Campbell
  34 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:29 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

Note that the example is done on Midway whose SMMU driver is not
supported on Xen upstream.

Currently, I don't have other platform where I can test non-PCI
passthrough.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Changes in v4:
        - Patch added
---
 docs/misc/arm/passthrough.txt | 58 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 docs/misc/arm/passthrough.txt

diff --git a/docs/misc/arm/passthrough.txt b/docs/misc/arm/passthrough.txt
new file mode 100644
index 0000000..cf6cc61
--- /dev/null
+++ b/docs/misc/arm/passthrough.txt
@@ -0,0 +1,58 @@
+Passthrough a non-pci device to a guest
+=======================================
+
+The example will use the secondary network card for the midway server.
+
+1) Mark the device to let Xen knowns the device will be used for passthrough.
+This is done in the device tree node describing the device by adding the
+property "xen,passthrough". The command to do it in U-Boot is:
+
+    fdt set /soc/ethernet@fff51000 xen,passthrough
+
+2) Create the partial device tree describing the device. The IRQ are mapped
+1:1 to the guest (i.e VIRQ == IRQ). For MMIO will have to find hole in the
+guest memory layout (see xen/include/public/arch-arm.h, noted the layout
+is not stable and can change between 2 releases version of Xen).
+
+/dts-v1/;
+
+/ {
+    /* #*cells are here to keep DTC happy */
+    #address-cells = <2>;
+    #size-cells = <2>;
+
+    aliases {
+        net = &mac0;
+    };
+
+    passthrough {
+        compatible = "simple-bus";
+        ranges;
+        #address-cells = <2>;
+        #size-cells = <2>;
+    	mac0: ethernet@10000000 {
+	    	compatible = "calxeda,hb-xgmac";
+            reg = <0 0x10000000 0 0x1000>;
+    		interrupts = <0 80 4  0 81 4  0 82 4>;
+    	};
+    };
+};
+
+Note:
+    * The interrupt-parent property will be added by the toolstack in the
+    root node;
+    * The properties compatible, ranges, #address-cells and #size-cells
+    in /passthrough are mandatory.
+
+3) Compile the partial guest device with dtc (Device Tree Compiler).
+For our purpose, the compiled file will be called guest-midway.dtb and
+placed in /root in DOM0.
+
+3) Add the following options in the guest configuration file:
+
+device_tree = "/root/guest-midway.dtb"
+dtdev = [ "/soc/ethernet@fff51000" ]
+irqs = [ 112, 113, 114 ]
+iomem = [ "0xfff51,1@0x10000" ]
+
+
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-03-19 19:29 ` [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt Julien Grall
@ 2015-03-19 19:42   ` Julien Grall
  2015-03-31 11:35   ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-19 19:42 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, stefano.stabellini, tim, ian.campbell, Wei Liu

Hi,

On 19/03/15 19:29, Julien Grall wrote:
> The functions fdt_{fisrt,next}_subnode may not be available because:
>     * It has been introduced in 2013 => Doesn't work on Wheezy
>     * The prototype exists but the functions are not exposed. Don't ask
>     why...
> 
> The later has been fixed recently in the dtc repo [1]
> 
> When the functions are not available, implement our own in order to use
> them in a following patch.
> 
> [1] git://git.kernel.org/pub/scm/utils/dtc/dtc.git
>     commit a4b093f7366fdb429ca1781144d3985fa50d0fbb
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> 
> ---

I forgot to add that this patch modify tools/configure.ac and therefore
require to regenerate tools/configure.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (32 preceding siblings ...)
  2015-03-19 19:29 ` [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough Julien Grall
@ 2015-03-20  1:22 ` Edgar E. Iglesias
  2015-03-20 17:34   ` Julien Grall
  2015-03-31 11:57 ` Ian Campbell
  34 siblings, 1 reply; 103+ messages in thread
From: Edgar E. Iglesias @ 2015-03-20  1:22 UTC (permalink / raw)
  To: Julien Grall
  Cc: ian.campbell, manish.jaggi, tim, robert.vanvossen,
	stefano.stabellini, suravee.suthikulpanit, Josh.Whitehead,
	xen-devel, andrii.tseglytskyi

On Thu, Mar 19, 2015 at 07:29:26PM +0000, Julien Grall wrote:
> Hello all,
> 
> This is the fourth version of this patch series to add support for platform
> device passthrough on ARM.
> 
> In order to passthrough a non-PCI device, the user will have to:
>     - Map manually MMIO/IRQ
>     - Describe the device in the newly partial device tree support
>     - Specify the list of device protected by an IOMMU to assign to the
>     guest.
> 
> While this solution is primitive, this is allow us to support more complex
> device in Xen with an little additionnal work for the user. Attempting to
> do it automatically is more difficult because we may not know the dependencies
> between devices (for instance a Network card and a phy).
> 
> To avoid adding code in DOM0 to manage platform device deassignment, the
> user has to add the property "xen,passthrough" to the device tree node
> describing the device. This can be easily done via U-Boot. For instance,
> if we want to passthrough the second network card of a Midway server to the
> guest. The user will have to add the following line the u-boot script:
> 
>     fdt set /soc/ethernet@fff51000 xen,passthrough
> 
> This series has been tested on Midway by assigning the secondary network card
> to a guest (see instruction below). Though, it requires a separate patch as
> we decide to not support the Midway SMMU within the new drivers.
> 
> I plan to do futher testing on other boards.

Hi Julien,

I did a bring-up of your work (an older version of your patches) on
ZynqMP QEMU and it works nicely. Thanks for working on this!

The partial device-tree support is nice and very flexible. I couldn't help
thinking that it would be nice to be able to describe more of the
guest with device-trees. It may be controversial but it would be cool
to be able to go:

xl create my-guest.dtb

A more down-to earth thing I ran into is that on the ZynqMP, the Cortex-A53
is setup to have 40 bits physical addresses. Our SMMU announces support
for up to 48bit input addresses (but can be configured for 40bits
aswell).

When XEN sets up passthrough for a dev, it probes the SMMU for the
max input address size and uses that as the input size for the
context. But because XEN reuses the page tables from p2m for the
SMMU, we end up in a miss-match.

I haven't looked at the details of how to fix but my gut feeling
is that we should be re-using the input size of the stage 2
page-tables as the input-size for the SMMU.
And only use the max input size of the SMMU to assert that it
is big enough. I may be missing something though.

The code in question is at the end of arm_smmu_device_cfg_probe(),
already merged.

Best regards,
Edgar

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct
  2015-03-19 19:29 ` [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct Julien Grall
@ 2015-03-20 10:53   ` Jan Beulich
  2015-03-31 11:13   ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Jan Beulich @ 2015-03-20 10:53 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, stefano.stabellini, ian.campbell, tim

>>> On 19.03.15 at 20:29, <julien.grall@linaro.org> wrote:
> --- a/xen/drivers/passthrough/iommu.c
> +++ b/xen/drivers/passthrough/iommu.c
> @@ -187,6 +187,32 @@ void iommu_teardown(struct domain *d)
>      tasklet_schedule(&iommu_pt_cleanup_tasklet);
>  }
>  
> +int iommu_construct(struct domain *d)
> +{
> +    int rc = 0;
> +
> +    if ( need_iommu(d) > 0 )
> +        return 0;
> +
> +    if ( !iommu_use_hap_pt(d) )
> +    {
> +        rc = arch_iommu_populate_page_table(d);
> +        if ( rc )
> +            return rc;
> +    }

Please limit the scope of rc to the body of this if(). With that
Acked-by: Jan Beulich <jbeulich@suse.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device
  2015-03-19 19:29 ` [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device Julien Grall
@ 2015-03-20 11:01   ` Jan Beulich
  2015-03-31 11:24   ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Jan Beulich @ 2015-03-20 11:01 UTC (permalink / raw)
  To: Julien Grall
  Cc: Wei Liu, ian.campbell, tim, Ian Jackson, stefano.stabellini, xen-devel

>>> On 19.03.15 at 20:29, <julien.grall@linaro.org> wrote:
> @@ -344,6 +344,13 @@ int iommu_do_domctl(
>      ret = iommu_do_pci_domctl(domctl, d, u_domctl);
>  #endif
>  
> +#ifdef HAS_DEVICE_TREE
> +    if ( ret != -ENODEV)
> +        return ret;
> +
> +    ret = iommu_do_dt_domctl(domctl, d, u_domctl);
> +#endif
> +
>      return ret;
>  }

I think inverting the if() condition and avoiding the extra return
path would be better, particularly in case any new code would get
added between the #endif and the final return. With that done
Acked-by: Jan Beulich <jbeulich@suse.com>
for the non-ARM, non-tools parts.

Jan

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ
  2015-03-19 19:29 ` [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
@ 2015-03-20 11:36   ` Stefano Stabellini
  2015-03-31 10:43   ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Stefano Stabellini @ 2015-03-20 11:36 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, ian.campbell, stefano.stabellini

On Thu, 19 Mar 2015, Julien Grall wrote:
> Currently Xen only supports SPIs routing for guest, add a function
> is_assignable_irq to check if we can assign a given IRQ to the guest.
> 
> Secondly, make sure the vIRQ is not the greater that the number of IRQs
> configured in the vGIC and it's an SPI.
> 
> Thirdly, when the IRQ is already assigned to the domain, check the user
> is not asking to use a different vIRQ than the one already bound.
> 
> Finally, desc->arch.type which contains the IRQ type (i.e level/edge) must
> be correctly configured before. The misconfiguration can happen when:
>     - the device has been blacklisted for the current platform
>     - the IRQ has not been described in the device tree
> 
> Also, use XENLOG_G_ERR in the error message within the function as it will
> be later called from a guest.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 

Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>


>     Changes in v4:
>         - Use NR_LOCAL_IRQS rather than 32
>         - Move the check to the IRQ and irq_to_desc after the vIRQ check
>         - Typoes and rewording the commit message and in the patch
>         - Use printk rather than dprintk.
> 
>     Changes in v3:
>         - Fix typo in commit message and comment
>         - Add a check that the vIRQ is an SPI
>         - Check if the user is not asking for a different vIRQ when the
>         IRQ is already assigned to the guest
> 
>     Changes in v2:
>         - Rename is_routable_irq into is_assignable_irq
>         - Check if the IRQ is not greater than the number handled by the
>         number of IRQs handled by the gic
>         - Move is_assignable_irq in irq.c rather than defining in the
>         header irq.h
>         - Retrieve the irq descriptor after checking the validity of the
>         IRQ
>         - vgic_num_irqs has been moved in a separate patch
>         - Fix the irq check against vgic_num_irqs
>         - Use virq instead of irq for vGIC sanity check
> ---
>  xen/arch/arm/irq.c        | 59 +++++++++++++++++++++++++++++++++++++++++++----
>  xen/include/asm-arm/irq.h |  2 ++
>  2 files changed, 57 insertions(+), 4 deletions(-)
> 
> diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
> index beb746a..4c3e381 100644
> --- a/xen/arch/arm/irq.c
> +++ b/xen/arch/arm/irq.c
> @@ -387,6 +387,16 @@ err:
>      return rc;
>  }
>  
> +bool_t is_assignable_irq(unsigned int irq)
> +{
> +    /* For now, we can only route SPIs to the guest */
> +    return ((irq >= NR_LOCAL_IRQS) && (irq < gic_number_lines()));
> +}
> +
> +/*
> + * Route an IRQ to a specific guest.
> + * For now only SPIs are assignable to the guest.
> + */
>  int route_irq_to_guest(struct domain *d, unsigned int virq,
>                         unsigned int irq, const char * devname)
>  {
> @@ -396,6 +406,28 @@ int route_irq_to_guest(struct domain *d, unsigned int virq,
>      unsigned long flags;
>      int retval = 0;
>  
> +    if ( virq >= vgic_num_irqs(d) )
> +    {
> +        printk(XENLOG_G_ERR
> +               "the vIRQ number %u is too high for domain %u (max = %u)\n",
> +               irq, d->domain_id, vgic_num_irqs(d));
> +        return -EINVAL;
> +    }
> +
> +    /* Only routing to virtual SPIs is supported */
> +    if ( virq < NR_LOCAL_IRQS )
> +    {
> +        printk(XENLOG_G_ERR "IRQ can only be routed to an SPI");
> +        return -EINVAL;
> +    }
> +
> +    if ( !is_assignable_irq(irq) )
> +    {
> +        printk(XENLOG_G_ERR "the IRQ%u is not routable\n", irq);
> +        return -EINVAL;
> +    }
> +    desc = irq_to_desc(irq);
> +
>      action = xmalloc(struct irqaction);
>      if ( !action )
>          return -ENOMEM;
> @@ -416,8 +448,18 @@ int route_irq_to_guest(struct domain *d, unsigned int virq,
>  
>      spin_lock_irqsave(&desc->lock, flags);
>  
> -    /* If the IRQ is already used by someone
> -     *  - If it's the same domain -> Xen doesn't need to update the IRQ desc
> +    if ( desc->arch.type == DT_IRQ_TYPE_INVALID )
> +    {
> +        printk(XENLOG_G_ERR "IRQ %u has not been configured\n", irq);
> +        retval = -EIO;
> +        goto out;
> +    }
> +
> +    /*
> +     * If the IRQ is already used by someone
> +     *  - If it's the same domain -> Xen doesn't need to update the IRQ desc.
> +     *  For safety check if we are not trying to assign the IRQ to a
> +     *  different vIRQ.
>       *  - Otherwise -> For now, don't allow the IRQ to be shared between
>       *  Xen and domains.
>       */
> @@ -426,13 +468,22 @@ int route_irq_to_guest(struct domain *d, unsigned int virq,
>          struct domain *ad = irq_get_domain(desc);
>  
>          if ( test_bit(_IRQ_GUEST, &desc->status) && d == ad )
> +        {
> +            if ( irq_get_guest_info(desc)->virq != virq )
> +            {
> +                printk(XENLOG_G_ERR
> +                       "d%u: IRQ %u is already assigned to vIRQ %u\n",
> +                       d->domain_id, irq, irq_get_guest_info(desc)->virq);
> +                retval = -EBUSY;
> +            }
>              goto out;
> +        }
>  
>          if ( test_bit(_IRQ_GUEST, &desc->status) )
> -            printk(XENLOG_ERR "ERROR: IRQ %u is already used by domain %u\n",
> +            printk(XENLOG_G_ERR "IRQ %u is already used by domain %u\n",
>                     irq, ad->domain_id);
>          else
> -            printk(XENLOG_ERR "ERROR: IRQ %u is already used by Xen\n", irq);
> +            printk(XENLOG_G_ERR "IRQ %u is already used by Xen\n", irq);
>          retval = -EBUSY;
>          goto out;
>      }
> diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
> index f00eb11..71b39e7 100644
> --- a/xen/include/asm-arm/irq.h
> +++ b/xen/include/asm-arm/irq.h
> @@ -37,6 +37,8 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
>  
>  #define domain_pirq_to_irq(d, pirq) (pirq)
>  
> +bool_t is_assignable_irq(unsigned int irq);
> +
>  void init_IRQ(void);
>  void init_secondary_IRQ(void);
>  
> -- 
> 2.1.4
> 

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter
  2015-03-19 19:29 ` [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
@ 2015-03-20 11:51   ` Stefano Stabellini
  2015-03-31 10:45   ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Stefano Stabellini @ 2015-03-20 11:51 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, ian.campbell, stefano.stabellini

On Thu, 19 Mar 2015, Julien Grall wrote:
> The priority is already hardcoded in route_irq_to_guest and therefore
> can't be controlled by the guest.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>


> ---
>     Changes in v4:
>         - Patch added
> ---
>  xen/arch/arm/gic.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index 2709415..5f34997 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -152,7 +152,7 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int virq,
>      desc->handler = gic_hw_ops->gic_guest_irq_type;
>      set_bit(_IRQ_GUEST, &desc->status);
>  
> -    gic_set_irq_properties(desc, cpumask_of(v_target->processor), GIC_PRI_IRQ);
> +    gic_set_irq_properties(desc, cpumask_of(v_target->processor), priority);
>  
>      p->desc = desc;
>      res = 0;
> -- 
> 2.1.4
> 

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough
  2015-03-20  1:22 ` [PATCH v4 00/33] xen/arm: Add support for " Edgar E. Iglesias
@ 2015-03-20 17:34   ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-20 17:34 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: ian.campbell, manish.jaggi, tim, robert.vanvossen,
	stefano.stabellini, suravee.suthikulpanit, Josh.Whitehead,
	xen-devel, andrii.tseglytskyi

On 20/03/2015 01:22, Edgar E. Iglesias wrote:
> Hi Julien,

Hello Edgar,

> The partial device-tree support is nice and very flexible. I couldn't help
> thinking that it would be nice to be able to describe more of the
> guest with device-trees. It may be controversial but it would be cool
> to be able to go:
>
> xl create my-guest.dtb

While it would be feasible to move some part of the IRQ/MMIO pass-thru 
in the device tree, there is some configuration options (such as the 
vif, the kernel...) that can't be easily be described in the 
configuration file.

> A more down-to earth thing I ran into is that on the ZynqMP, the Cortex-A53
> is setup to have 40 bits physical addresses. Our SMMU announces support
> for up to 48bit input addresses (but can be configured for 40bits
> aswell).
>
> When XEN sets up passthrough for a dev, it probes the SMMU for the
> max input address size and uses that as the input size for the
> context. But because XEN reuses the page tables from p2m for the
> SMMU, we end up in a miss-match.
>
> I haven't looked at the details of how to fix but my gut feeling
> is that we should be re-using the input size of the stage 2
> page-tables as the input-size for the SMMU.
> And only use the max input size of the SMMU to assert that it
> is big enough. I may be missing something though.

> The code in question is at the end of arm_smmu_device_cfg_probe(),
> already merged.

You are right, we should take into account the size of the CPU physical 
address.

Re-using the input size of the stage 2 page-tables seems the best solution.

Although, if I'm not mistaken, I have the inverse problem on one of our 
board. I.e the input-size of the SMMU is too small. I need to double check.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 06/33] xen/arm: Introduce xen, passthrough property
  2015-03-19 19:29 ` [PATCH v4 06/33] xen/arm: Introduce xen, passthrough property Julien Grall
@ 2015-03-31 10:25   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:25 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini, Stefano Stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> When a device is marked for passthrough (via the new property
> "xen,passthrough"), dom0 must not access to the device (i.e not
> loading a driver), but should be able to manage the MMIO/interrupt
> of the passthrough device.
> 
> The latter part will allow the toolstack to map MMIO/IRQ when a device
> is pass through to a guest.
> 
> The property "xen,passthrough" will be translated as 'status="disabled"'
> in the device tree to avoid DOM0 using the device. We assume that DOM0 is
> able to cope with this property (already the case for Linux, and
> required by ePAPR).
> 
> Rework the function map_device (renamed into handle_device) to:
> 
> * For a given device node:
>     - Give permission to manage IRQ/MMIO for this device
>     - Retrieve the IRQ configuration (i.e edge/level) from the device
>     tree
> * When the device is not marked for guest passthrough:
>     - Assign the device to the guest if it's protected by an IOMMU
>     - Map the IRQs and MMIOs regions to the guest
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 08/33] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE"
  2015-03-19 19:29 ` [PATCH v4 08/33] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE" Julien Grall
@ 2015-03-31 10:26   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:26 UTC (permalink / raw)
  To: Julien Grall
  Cc: Keir Fraser, tim, Ian Jackson, stefano.stabellini, Jan Beulich,
	xen-devel

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Suggested-by: Jan Beulich <jbeulich@suse.com>
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Keir Fraser <keir@xen.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 09/33] xen: Extend DOMCTL createdomain to support arch configuration
  2015-03-19 19:29 ` [PATCH v4 09/33] xen: Extend DOMCTL createdomain to support arch configuration Julien Grall
@ 2015-03-31 10:39   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:39 UTC (permalink / raw)
  To: Julien Grall
  Cc: Wei Liu, Stefano Stabellini, George Dunlap, Ian Jackson, tim,
	stefano.stabellini, Jan Beulich, Andrew Cooper, xen-devel,
	Daniel De Graaf, Keir Fraser

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> On ARM the virtual GIC may differ between each guest (emulated GIC version,
> number of SPIs...). This information is already known at the domain creation
> and can never change.
> 
> For now only the gic_version is set. In the long run, there will be more
> parameters such as the number of SPIs. All will be required to be set at the
> same time.
> 
> A new arch-specific structure arch_domainconfig has been created, the x86
> one doesn't have any specific configuration, for now, a dummy structure
> (C-spec compliant) has been created.
> 
> Some external tools (qemu, xenstore) may be required to create a domain.
> Rather than asking them to take care of the arch-specific domain
> configuration, let the current function (xc_domain_create) chose a
> default configuration and introduce a new one (xc_domain_create_config).
> 
> This patch also drops the previously introduced DOMCTL arm_configure_domain
> in Xen 4.5, as it has been made useless.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Acked-by: Jan Beulich <jbeulich@suse.com>
> Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> Cc: Keir Fraser <keir@xen.org>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: George Dunlap <george.dunlap@eu.citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

A couple of minor nits which I'll try and remember to fix on commit if a
resend of the series isn't needed for another reason.

> -    LOG(DEBUG, "  - vGIC version: %s", gicv_to_string(config.gic_version));
> +    LOG(DEBUG, " - vGIC version: %s\n", gicv_to_string(xc_config->gic_version));

Log adds the \n itself. 
>      /* Create initial domain 0. */
> -    dom0 = domain_create(0, 0, 0);
> +    /* The vGIC for DOM0 is exactly emulated the hardware GIC */

"emulating"

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 10/33] xen/arm: Allow virq != irq
  2015-03-19 19:29 ` [PATCH v4 10/33] xen/arm: Allow virq != irq Julien Grall
@ 2015-03-31 10:41   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:41 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini, Stefano Stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Currently, Xen is assuming that the virtual IRQ will always be the same
> as IRQ.
> 
> Modify route_guest_irq to take the virtual IRQ in parameter which allow
> Xen to assign a different IRQ number. Also store the vIRQ in the desc
> action to easily retrieve the IRQ target when we need to inject the
> interrupt.
> 
> As DOM0 will get most the devices, the vIRQ is equal to the IRQ in that case.
> 
> At the same time modify the behavior of irq_get_domain. The function now
> requires that the irq_desc belongs to an IRQ assigned to a guest.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ
  2015-03-19 19:29 ` [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
  2015-03-20 11:36   ` Stefano Stabellini
@ 2015-03-31 10:43   ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:43 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Currently Xen only supports SPIs routing for guest, add a function
> is_assignable_irq to check if we can assign a given IRQ to the guest.
> 
> Secondly, make sure the vIRQ is not the greater that the number of IRQs

s/that/than/

> configured in the vGIC and it's an SPI.
> 
> Thirdly, when the IRQ is already assigned to the domain, check the user
> is not asking to use a different vIRQ than the one already bound.
> 
> Finally, desc->arch.type which contains the IRQ type (i.e level/edge) must
> be correctly configured before. The misconfiguration can happen when:
>     - the device has been blacklisted for the current platform
>     - the IRQ has not been described in the device tree
> 
> Also, use XENLOG_G_ERR in the error message within the function as it will
> be later called from a guest.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 12/33] xen/arm: gic: Add sanity checks gic_route_irq_to_guest
  2015-03-19 19:29 ` [PATCH v4 12/33] xen/arm: gic: Add sanity checks gic_route_irq_to_guest Julien Grall
@ 2015-03-31 10:44   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:44 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini, Stefano Stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> With the addition of interrupt assignment to guest, we need to make sure
> the guest can't blow up the interrupt management in Xen.
> 
> Before associating the IRQ to a vIRQ we need to make sure:
>     - the vIRQ is not already associated to another IRQ
>     - the guest didn't enable the vIRQ
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter
  2015-03-19 19:29 ` [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
  2015-03-20 11:51   ` Stefano Stabellini
@ 2015-03-31 10:45   ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:45 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> The priority is already hardcoded in route_irq_to_guest and therefore
> can't be controlled by the guest.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 14/33] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber
  2015-03-19 19:29 ` [PATCH v4 14/33] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber Julien Grall
@ 2015-03-31 10:46   ` Ian Campbell
  2015-03-31 11:28     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:46 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> The formula of GICD_TYPER.ITLinesNumber is 32(N + 1).
> 
> As the number of SPIs suppported by the domain may not be a multiple of
> 32, we have to round up the number before using it.
> 
> At the same time remove the mask GICD_TYPE_LINES which is pointless.

I presume because something else has ensured that nr_spis is less than
the maximum value represented by the mask?

> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 15/33] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts
  2015-03-19 19:29 ` [PATCH v4 15/33] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts Julien Grall
@ 2015-03-31 10:47   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:47 UTC (permalink / raw)
  To: Julien Grall
  Cc: Frediano Ziglio, xen-devel, tim, stefano.stabellini, Zoltan Kiss

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> GICD_TYPER.ITLinesNumber can encode up to 1024 interrupts. Although,
> IRQ 1020-1023 are reserved for special purpose.
> 
> The result is used by the callers of gic_number_lines in order to check
> the validity of an IRQ.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Frediano Ziglio <frediano.ziglio@huawei.com>
> Cc: Zoltan Kiss <zoltan.kiss@huawei.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs
  2015-03-19 19:29 ` [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs Julien Grall
@ 2015-03-31 10:54   ` Ian Campbell
  2015-03-31 11:44     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:54 UTC (permalink / raw)
  To: Julien Grall
  Cc: Wei Liu, Ian Jackson, tim, stefano.stabellini, Jan Beulich, xen-devel

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> @@ -68,16 +68,17 @@ static void vgic_init_pending_irq(struct pending_irq *p, unsigned int virq)
>      p->irq = virq;
>  }
>  
> -int domain_vgic_init(struct domain *d)
> +int domain_vgic_init(struct domain *d, unsigned int nr_spis)
>  {
>      int i;
>  
>      d->arch.vgic.ctlr = 0;
>  
[...]
> +    /* Limit the number of SPIs supported base on the hardware */
> +    if ( nr_spis > (gic_number_lines() - NR_LOCAL_IRQS) )
> +        return -EINVAL;

Is there anything in the h/w which leads to this restriction?

If not then I think we should just check against the architectural 1020
limit and leave it at that.


> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index 9e0419e..6dacfef 100644
> --- a/xen/include/asm-arm/domain.h
> +++ b/xen/include/asm-arm/domain.h
> @@ -125,6 +125,8 @@ struct arch_domain
>      unsigned int evtchn_irq;
>  }  __cacheline_aligned;
>  
> +#define domain_is_configured(d) ((d)->arch.is_configured)
> +
>  struct arch_vcpu
>  {
>      struct {
> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> index ba5a67d..254cc17 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -54,6 +54,7 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
>  void arch_get_xen_caps(xen_capabilities_info_t *info);
>  
>  int construct_dom0(struct domain *d);
> +int configure_dom0(struct domain *d);

Are these two hunks stray from some other patch in the series?

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 17/33] xen/arm: vgic: Add spi_to_pending
  2015-03-19 19:29 ` [PATCH v4 17/33] xen/arm: vgic: Add spi_to_pending Julien Grall
@ 2015-03-31 10:55   ` Ian Campbell
  2015-03-31 11:58     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:55 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Introduce spi_to_pending in order retrieve the irq_pending structure for
> a specific SPI.
> 
> It's not possible to re-use irq_to_pending because it's required a VCPU

"it requires"

> and some call of the new function may during domain destruction after
> the VCPUs are freed.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

Although given the name I would expect it to take an spi (i.e. -32) not
an irq. I can't think of a better name though and perhaps that just
makes things harder for the caller.

Ian.

> 
> ---
>     Changes in v4:
>         - Patch added
> ---
>  xen/arch/arm/vgic.c        | 7 +++++++
>  xen/include/asm-arm/vgic.h | 1 +
>  2 files changed, 8 insertions(+)
> 
> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
> index 74751e0..fc283ec 100644
> --- a/xen/arch/arm/vgic.c
> +++ b/xen/arch/arm/vgic.c
> @@ -371,6 +371,13 @@ struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq)
>      return n;
>  }
>  
> +struct pending_irq *spi_to_pending(struct domain *d, unsigned int irq)
> +{
> +    ASSERT(irq >= NR_LOCAL_IRQS);
> +
> +    return &d->arch.vgic.pending_irqs[irq - 32];
> +}
> +
>  void vgic_clear_pending_irqs(struct vcpu *v)
>  {
>      struct pending_irq *p, *t;
> diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
> index 647f2fe..8d22532 100644
> --- a/xen/include/asm-arm/vgic.h
> +++ b/xen/include/asm-arm/vgic.h
> @@ -185,6 +185,7 @@ extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq);
>  extern void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq);
>  extern void vgic_clear_pending_irqs(struct vcpu *v);
>  extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
> +extern struct pending_irq *spi_to_pending(struct domain *d, unsigned int irq);
>  extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, int s);
>  extern struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq);
>  extern int vgic_emulate(struct cpu_user_regs *regs, union hsr hsr);

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 18/33] xen/arm: Release IRQ routed to a domain when it's destroying
  2015-03-19 19:29 ` [PATCH v4 18/33] xen/arm: Release IRQ routed to a domain when it's destroying Julien Grall
@ 2015-03-31 10:58   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 10:58 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Xen has to release IRQ routed to a domain in order to reuse later.
> Currently only SPIs can be routed to the guest so we only need to
> browse SPIs for a specific domain.
> 
> Furthermore, a guest can crash and let the IRQ in an incorrect state

"leave the irq"

> (i.e has not being EOIed). Xen will have to reset the IRQ in order to

s/being/been/

> be able to reuse the IRQ later.
> 
> Introduce 2 new functions for release an IRQ routed to a domain:
>     - release_guest_irq: upper level to retrieve the IRQ, call the GIC
>     code and release the action
>     - gic_remove_guest_irq: Check if we can remove the IRQ, and reset
>     it if necessary
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq
  2015-03-19 19:29 ` [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq Julien Grall
@ 2015-03-31 11:11   ` Ian Campbell
  2015-03-31 12:23     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:11 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Jan Beulich, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> On x86, an IRQ is assigned in 2 steps to an HVM guest:
>     - The toolstack is calling PHYSDEVOP_map_pirq in order to create a
>     guest PIRQ (IRQ bound to an event channel)
>     - The emulator (QEMU) is calling DOMCTL_bind_pt_irq in order to
>     bind the IRQ
> 
> On ARM, there is no concept of PIRQ as the IRQ can be assigned to a
> virtual IRQ using the interrupt controller.
> 
> It's not clear if we will need 2 different hypercalls on ARM to assign
> IRQ and, for now, only the toolstack will manage IRQ.
> 
> In order to avoid re-using a fixed ABI hypercall (PHYSDEVOP_*) for a
> different purpose and allow us more time to figure out the right out,

"figure out the right way"

> only DOMCTL_{,un}bind_pt_pirq is implemented on ARM.
> 
> The DOMCTL is extended with a new type PT_IRQ_TYPE_SPI and only IRQ ==
> vIRQ (i.e machine_irq == spi) is supported.
> 
> Concerning XSM, even if ARM is using one hypercall rather than 2, the
> resulting check is nearly the same.
> 
> XSM PHYSDEVOP_map_pirq:
>     1) Check if the current domain can add resource to the domain
>     2) Check if the current domain has permission to add the IRQ
>     3) Check if the target domain has permission to use the IRQ
> 
> XSM DOMCTL_bind_pirq_irq:
>     1) Check if the current domain can add resource to the domain
>     2) Check if the current domain has permission to bind the IRQ
>     3) Check if the target domain has permission to use the IRQ
> 
> Rather than checking that the current domain can both add and bind the
> IRQ, we only check the bind permission. I think this is not a big deal
> because we don't have emulator on ARM and therefore no disaggregation is
> required.

Is this because we don't have the "add" concept on arm?

> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
> index 579d266..8243b70 100644
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -1764,7 +1764,7 @@ int xc_domain_bind_pt_irq(
>      uint8_t bus,
>      uint8_t device,
>      uint8_t intx,
> -    uint8_t isa_irq)
> +    uint16_t isa_irq)

This interface is pretty awful, taking the union of all the options
needed for each type as separate parameters. Reusing the isa_irq
parameter is making this worse along a different axis as well.

AFAICT its only user is qemu-trad with PT_IRQ_TYPE_MSI_TRANSLATE.

I think we should discourage any new uses of this function, and hide any
ugliness in an internal static function to be used by the more specific
xc_domain_bind_pt_isa_irq et al. i.e. make the current
xc_doamin_bind_pt_irq an internal helper with a new name and a new
spi_irq parameter and make the replacement xc_domain_bind_pt_irq a
wrapper which handles only the set of types which it handles today and a
new xc_domain_bind_pt_spi_irq which exposes the new functionality.

Hopefully we can eventually remove xc_domain_bind_pt_irq. If you are
minded to you could do that today, but it's not required I think.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 20/33] xen/dts: Provide an helper to get a DT node from a path provided by a guest
  2015-03-19 19:29 ` [PATCH v4 20/33] xen/dts: Provide an helper to get a DT node from a path provided by a guest Julien Grall
@ 2015-03-31 11:12   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:12 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> The maximum size of the copied string has been chosen based on the value
> use by XSM in similar case.
> 
> Furthermore, Linux seems to allow path up to 4096 characters. Though
> this could vary from one OS to another.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct
  2015-03-19 19:29 ` [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct Julien Grall
  2015-03-20 10:53   ` Jan Beulich
@ 2015-03-31 11:13   ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:13 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Jan Beulich, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> This new function will correctly initialize the IOMMU page table for the
> current domain.
> 
> Also use it in iommu_assign_dt_device even though the current IOMMU
> implementation on ARM shares P2M with the processor.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Jan Beulich <jbeulich@suse.com>

With Jan's requested change:
Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 22/33] xen/passthrough: arm: release the DT devices assigned to a guest earlier
  2015-03-19 19:29 ` [PATCH v4 22/33] xen/passthrough: arm: release the DT devices assigned to a guest earlier Julien Grall
@ 2015-03-31 11:16   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:16 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Jan Beulich, tim, Robert VanVossen, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> The toolstack may not have deassigned every device used by a guest.
> Therefore we have to go through the device list and remove them before
> asking the IOMMU drivers to release memory for this domain.
> 
> This can be done by moving the call to the release function when we
> relinquish the resources. The IOMMU part will be destroyed later when
> the domain is freed.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Signed-off-by: Robert VanVossen <robert.vanvossen@dornerworks.com>
> Acked-by: Jan Beulich <jbeulich@suse.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 23/33] xen/passthrough: iommu_deassign_device_dt: By default reassign device to nobody
  2015-03-19 19:29 ` [PATCH v4 23/33] xen/passthrough: iommu_deassign_device_dt: By default reassign device to nobody Julien Grall
@ 2015-03-31 11:16   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:16 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Currently, when the device is deassigned from a domain, we directly reassign
> to DOM0.
> 
> As the device may not have been correctly reset, this may lead to corruption or
> expose some part of DOM0 memory. Also, we may have no way to reset some
> platform devices.
> 
> If Xen reassigns the device to "nobody", it may receive some global/context
> fault because the transaction has failed (indeed the context has been
> marked invalid). Unfortunately there is no simple way to quiesce a buggy
> hardware. I think we could live with that for a first version of platform
> device passthrough.
> 
> DOM0 will have to issue an hypercall to assign the device to itself if it
> wants to use it.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Acked-by: Stefano Stabellini <stefano.stabellini@citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough
  2015-03-19 19:29 ` [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough Julien Grall
@ 2015-03-31 11:17   ` Ian Campbell
  2015-03-31 17:12   ` Daniel De Graaf
  1 sibling, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:17 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, Daniel De Graaf, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> This is a follow-up of commit 525ee49 "xsm: add device tree labeling
> support" which add support for device tree labelling in flask.
> 
> Those helpers will be use latter when non-pci passthrough (i.e device
> tree) will be added.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>

Looks ok to me:

Acked-by: Ian Campbell <ian.campbell@citrix.com>

But I'd like to here from Daniel too.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device
  2015-03-19 19:29 ` [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device Julien Grall
  2015-03-20 11:01   ` Jan Beulich
@ 2015-03-31 11:24   ` Ian Campbell
  2015-03-31 12:30     ` Julien Grall
  1 sibling, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:24 UTC (permalink / raw)
  To: Julien Grall
  Cc: Wei Liu, Ian Jackson, tim, stefano.stabellini, Jan Beulich, xen-devel

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> +int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d,
> +                       XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
> +{
> +    int ret;
> +    struct dt_device_node *dev;
> +
> +    /* TODO: How to deal with XSM? */

Looks like you do in the following code? Old comment?

> +    /* TODO: Do we need to check is_dying? Mostly to protect against
> +     * hypercall trying to passthrough a device while we are
> +     * dying.

iommu_do_pci_domctl does in specific casses (i.e. assign device). I
guess you should follow that lead.

> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index 7f90150..a7cb272 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -475,12 +475,30 @@ typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
>  
> 
> -/* Assign PCI device to HVM guest. Sets up IOMMU structures. */
> +/* Assign a device to a guest. Sets up IOMMU structures. */
>  /* XEN_DOMCTL_assign_device */
>  /* XEN_DOMCTL_test_assign_device */
> -/* XEN_DOMCTL_deassign_device */
> +/*
> + * XEN_DOMCTL_deassign_device: The behavior of this DOMCTL differs
> + * between the different type of device:
> + *  - PCI device (XEN_DOMCTL_DEV_PCI) will be reassigned to DOM0
> + *  - non-PCI device (XEN_DOMCTL_DEV_PCI) will left unassigned. DOM0

Did you miss a ! before XEN_DOMCTL, or did you mean to say DT?

>From an ease of review PoV it would have been nice to add dev and u.pci
first since that would be mechanical, but nevermind now.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 27/33] tools/libxl: Create a per-arch function to map IRQ to a domain
  2015-03-19 19:29 ` [PATCH v4 27/33] tools/libxl: Create a per-arch function to map IRQ to a domain Julien Grall
@ 2015-03-31 11:26   ` Ian Campbell
  2015-03-31 12:33     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:26 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> ARM and x86 use a different hypercall to map an IRQ to a domain.
> 
> The hypercall to give IRQ permission to the domain as also been moved

"has also been".

> on the x86 specific function as ARM guest won't be able to manage the IRQ.

s/on the/to be an/?

> We may want to support it later.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 14/33] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber
  2015-03-31 10:46   ` Ian Campbell
@ 2015-03-31 11:28     ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-31 11:28 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, tim, stefano.stabellini

On 31/03/15 11:46, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> The formula of GICD_TYPER.ITLinesNumber is 32(N + 1).
>>
>> As the number of SPIs suppported by the domain may not be a multiple of
>> 32, we have to round up the number before using it.
>>
>> At the same time remove the mask GICD_TYPE_LINES which is pointless.
> 
> I presume because something else has ensured that nr_spis is less than
> the maximum value represented by the mask?

The number of SPIs is validated in domain_vgic_init.

We would be in trouble in the IRQ guest injection if this number is too
high.

> 
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Acked-by: Ian Campbell <ian.campbell@citrix.com>

Thanks,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-03-19 19:29 ` [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt Julien Grall
  2015-03-19 19:42   ` Julien Grall
@ 2015-03-31 11:35   ` Ian Campbell
  2015-03-31 12:46     ` Julien Grall
  1 sibling, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:35 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:

> The functions fdt_{fisrt,next}_subnode may not be available because:

"first"

> diff --git a/tools/libxl/libxl_fdt.c b/tools/libxl/libxl_fdt.c
> new file mode 100644
> index 0000000..f88e9f1
> --- /dev/null
> +++ b/tools/libxl/libxl_fdt.c

Since this is effectively shims for missing libfdt functionality how
about libxl_libfdt_compat.c or some such?

If wee wanted any fdt specific helpers as part of libxl itself then
those would want to use the libxl_fdt.c name.

> @@ -0,0 +1,84 @@
> +/*
> + * libfdt - Flat Device Tree manipulation
> + * Copyright (C) 2006 David Gibson, IBM Corporation.
> + *
> + * libfdt is dual licensed: you can use it either under the terms of
> + * the GPL, or the BSD license, at your option.

Since this is libxl, which should be LGPL I think we must therefore be
taking the BSD option. Perhaps we should make that clear? I'm not sure.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM
  2015-03-19 19:29 ` [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM Julien Grall
@ 2015-03-31 11:41   ` Ian Campbell
  2015-03-31 12:55     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:41 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Let the user to pass additional nodes to the guest device tree. For
> this purpose, everything in the node /passthrough from the partial
> device tree will be copied into the guest device tree.
> 
> The node /aliases will be also copied to allow the user to define
> aliases which can be used by the guest kernel.
> 
> A simple partial device tree will look like:
> 
> /dts-v1/;
> 
> / {
>         #address-cells = <2>;
>         #size-cells = <2>;
> 
>         passthrough {
>             compatible = "simple-bus";
>             ranges;
>             #address-cells = <2>;
>             #size-cells = <2>;
> 
>             /* List of your nodes */
>         }
> };
> 
> Note that:
>     * The interrupt-parent property will be added by the toolstack in
>     the root node
>     * The properties compatible, ranges, #address-cells and #size-cells
>     in /passthrough are mandatory.
> 
> The helpers provided by the libfdt don't perform all the necessary
> security check on a given device tree. Therefore, only trusted device
> tree should be used.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> 
> ---
>     An example of the partial device tree, as long as how to passthrough
>     a non-pci device will be added to the tree in a follow-up patch.
> 
>     A new LIBXL_HAVE_* will be added in the patch which add support for
>     non-PCI passthrough as both are tight.
> 
>     Changes in v4:
>         - Mark the option as unsafe
>         - The _fdt_* helpers has been moved in a separate patch/file.
>         Only the prototype is declared
>         - The partial DT is considered valid. Remove some security check
>         which make the code cleaner
>         - Typoes
> 
>     Changes in v3:
>         - Patch added
> ---
>  docs/man/xl.cfg.pod.5       |  10 +++
>  tools/libxl/libxl_arm.c     | 171 ++++++++++++++++++++++++++++++++++++++++++++
>  tools/libxl/libxl_types.idl |   1 +
>  tools/libxl/xl_cmdimpl.c    |   1 +

Needs a #define LIBXL_HAVE in libxl.h for 3rd party users of the
library.

>  4 files changed, 183 insertions(+)
> 
> diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
> index 93cd7d2..bcbc277 100644
> --- a/docs/man/xl.cfg.pod.5
> +++ b/docs/man/xl.cfg.pod.5
> @@ -453,6 +453,16 @@ not emulated.
>  Specify that this domain is a driver domain. This enables certain
>  features needed in order to run a driver domain.
>  
> +=item B<device_tree=PATH>
> +
> +Specify a partial device tree (compiled via the Device Tree Compiler).
> +Everything under the node "/passthrough" will be copied into the guest
> +device tree. For convenience, the node "/aliases" is also copied to allow
> +the user to defined aliases which can be used by the guest kernel.
> +
> +Given the complexity of verifying the validity of a device tree, this
> +option should only be used with trusted device tree.

This warning should be in the libxl API docs (i.e. the header or IDL)
somewhere too, so that 3rd party toolstacks know about it. In that
context it should perhaps be a lot more prominent and scarier sounding
too.

> +
>  =back
>  
>  =head2 Devices
> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
> index 06e940b..54d197b 100644
> --- a/tools/libxl/libxl_arm.c
> +++ b/tools/libxl/libxl_arm.c
> @@ -542,6 +542,156 @@ out:
>      }
>  }
>  
> +/* Only FDT v17 is supported */
> +#define FDT_REQUIRED_VERSION    0x11

Are versions >v17 broken? Or is there some other problem with being more
forward compatible?

(TBH, I've no idea how often this value changes, maybe it's unlikely to
now?)

> +    return (propoff != -FDT_ERR_NOTFOUND)? propoff : 0;
> +}
> +
> +/*
> + * These functions are defined by libfdt or libxl_fdt.c if it's not
> + * present on the former.
> + */
> +int fdt_next_subnode(const void *fdt, int offset);
> +int fdt_first_subnode(const void *fdt, int offset);

Better to use the prototype from the libfdt header if it is present,
i.e. wrap these in the associated ifdef-s.

I'm in two minds about suggesting putting all that into
libxl_libfdt_compat.h, up to you.


Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 30/33] tools/libxl: arm: Use an higher value for the GIC phandle
  2015-03-19 19:29 ` [PATCH v4 30/33] tools/libxl: arm: Use an higher value for the GIC phandle Julien Grall
@ 2015-03-31 11:43   ` Ian Campbell
  2015-04-09 12:36     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:43 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> The partial device tree may contains phandle. The Device Tree Compiler
> tends to allocate the phandle from 1.
> 
> Reserve the ID 65000 for the GIC phandle. I think we can safely assume
> that the partial device tree will never contain a such ID.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> 
> ---
>     It's not easily possible to track the maximum phandle in the partial
>     device tree.
> 
>     We would need to parse it twice: one for looking the maximum
>     phandle, and one for copying the nodes. This is because we have to
>     know the phandle of the GIC when we create the properties of the
>     root.

Or you could fill it in post-hoc like we do with e.g. the initramfs
location?

Anyway, this'll do for now:
Acked-by: Ian Campbell <ian.ampbell@citrix.com>

> 
>     As the phandle is encoded an unsigned 32 bits, I could use an higher
>     value. Though, having 65000 phandle is already a lot...
> 
>     TODO: If it's necessary, I can check if the value has been used by
>     another phandle in the device tree.

If that's easy enough to add then yes please, but if it is complex then
don't bother.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs
  2015-03-31 10:54   ` Ian Campbell
@ 2015-03-31 11:44     ` Julien Grall
  2015-03-31 11:59       ` Ian Campbell
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 11:44 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Wei Liu, Ian Jackson, tim, stefano.stabellini, Jan Beulich, xen-devel

Hi Ian,

On 31/03/15 11:54, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> @@ -68,16 +68,17 @@ static void vgic_init_pending_irq(struct pending_irq *p, unsigned int virq)
>>      p->irq = virq;
>>  }
>>  
>> -int domain_vgic_init(struct domain *d)
>> +int domain_vgic_init(struct domain *d, unsigned int nr_spis)
>>  {
>>      int i;
>>  
>>      d->arch.vgic.ctlr = 0;
>>  
> [...]
>> +    /* Limit the number of SPIs supported base on the hardware */
>> +    if ( nr_spis > (gic_number_lines() - NR_LOCAL_IRQS) )
>> +        return -EINVAL;
> 
> Is there anything in the h/w which leads to this restriction?

The h/w accept an VirtualID < 1020. Although, given that we can only
route a physical interrupt to the guest, it's pointless to support more
SPIs than the h/w does.

> If not then I think we should just check against the architectural 1020
> limit and leave it at that.

I would have to check on 988 (1020 - 32) which I find less readable.

>> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
>> index 9e0419e..6dacfef 100644
>> --- a/xen/include/asm-arm/domain.h
>> +++ b/xen/include/asm-arm/domain.h
>> @@ -125,6 +125,8 @@ struct arch_domain
>>      unsigned int evtchn_irq;
>>  }  __cacheline_aligned;
>>  
>> +#define domain_is_configured(d) ((d)->arch.is_configured)
>> +
>>  struct arch_vcpu
>>  {
>>      struct {
>> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
>> index ba5a67d..254cc17 100644
>> --- a/xen/include/asm-arm/setup.h
>> +++ b/xen/include/asm-arm/setup.h
>> @@ -54,6 +54,7 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
>>  void arch_get_xen_caps(xen_capabilities_info_t *info);
>>  
>>  int construct_dom0(struct domain *d);
>> +int configure_dom0(struct domain *d);
> 
> Are these two hunks stray from some other patch in the series?

No. It's part of an old version of this patch and I forgot to drop it.

I will resend a new version.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts
  2015-03-19 19:29 ` [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts Julien Grall
@ 2015-03-31 11:44   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:44 UTC (permalink / raw)
  To: Julien Grall
  Cc: Zoltan Kiss, Stefano Stabellini, tim, Frediano Ziglio,
	stefano.stabellini, xen-devel

Frediano, Zoltan,

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>     Note that the HIP04 GIC driver has not been modified because I don't
>     have a platform where I can test my changes. Although, the code is
>     still building.
> 
>     I let the Hisilicon guys (Frediano and Zoltan) providing a suitable
>     patch for there platform.

Are you going to provide an update for the hip04 driver for this change?

>     Meanwhile, I think it can go upstream as it has been acked by both
>     Ian and Stefano.
> 
>     Changes in v4:
>         - Rebase on the latest staging (no functional changes)
>         - Add Ian and Stefano's ack
>         - Typo in the commit message
> 
>     Changes in v3:
>         - Patch was previously sent in a separate series [1]
>         - Reorder the function to avoid forward declaration
>         - Make gic-v3 driver compliant to the new interface
>         - Remove spurious field addition in gicv2 structure
> 
>     Changelog based on the separate series:
> 
>     Changes in v3:
>         - Patch added.
> 
>     [1] https://patches.linaro.org/33313/
> ---
>  xen/arch/arm/gic-v2.c     | 70 ++++++++++++++++++++++---------------------
>  xen/arch/arm/gic-v3.c     | 75 ++++++++++++++++++++++++-----------------------
>  xen/arch/arm/gic.c        | 16 ++++++++--
>  xen/arch/arm/setup.c      |  3 +-
>  xen/include/asm-arm/gic.h |  8 +++++
>  5 files changed, 100 insertions(+), 72 deletions(-)
> 
> diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
> index 20cdbc9..3be4ad6 100644
> --- a/xen/arch/arm/gic-v2.c
> +++ b/xen/arch/arm/gic-v2.c
> @@ -674,37 +674,10 @@ static hw_irq_controller gicv2_guest_irq_type = {
>      .set_affinity = gicv2_irq_set_affinity,
>  };
>  
> -const static struct gic_hw_operations gicv2_ops = {
> -    .info                = &gicv2_info,
> -    .secondary_init      = gicv2_secondary_cpu_init,
> -    .save_state          = gicv2_save_state,
> -    .restore_state       = gicv2_restore_state,
> -    .dump_state          = gicv2_dump_state,
> -    .gicv_setup          = gicv2v_setup,
> -    .gic_host_irq_type   = &gicv2_host_irq_type,
> -    .gic_guest_irq_type  = &gicv2_guest_irq_type,
> -    .eoi_irq             = gicv2_eoi_irq,
> -    .deactivate_irq      = gicv2_dir_irq,
> -    .read_irq            = gicv2_read_irq,
> -    .set_irq_properties  = gicv2_set_irq_properties,
> -    .send_SGI            = gicv2_send_SGI,
> -    .disable_interface   = gicv2_disable_interface,
> -    .update_lr           = gicv2_update_lr,
> -    .update_hcr_status   = gicv2_hcr_status,
> -    .clear_lr            = gicv2_clear_lr,
> -    .read_lr             = gicv2_read_lr,
> -    .write_lr            = gicv2_write_lr,
> -    .read_vmcr_priority  = gicv2_read_vmcr_priority,
> -    .read_apr            = gicv2_read_apr,
> -    .make_dt_node        = gicv2_make_dt_node,
> -};
> -
> -/* Set up the GIC */
> -static int __init gicv2_init(struct dt_device_node *node, const void *data)
> +static int __init gicv2_init(void)
>  {
>      int res;
> -
> -    dt_device_set_used_by(node, DOMID_XEN);
> +    const struct dt_device_node *node = gicv2_info.node;
>  
>      res = dt_device_get_address(node, 0, &gicv2.dbase, NULL);
>      if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) )
> @@ -727,9 +700,6 @@ static int __init gicv2_init(struct dt_device_node *node, const void *data)
>          panic("GICv2: Cannot find the maintenance IRQ");
>      gicv2_info.maintenance_irq = res;
>  
> -    /* Set the GIC as the primary interrupt controller */
> -    dt_interrupt_controller = node;
> -
>      /* TODO: Add check on distributor, cpu size */
>  
>      printk("GICv2 initialization:\n"
> @@ -774,8 +744,42 @@ static int __init gicv2_init(struct dt_device_node *node, const void *data)
>  
>      spin_unlock(&gicv2.lock);
>  
> +    return 0;
> +}
> +
> +const static struct gic_hw_operations gicv2_ops = {
> +    .info                = &gicv2_info,
> +    .init                = gicv2_init,
> +    .secondary_init      = gicv2_secondary_cpu_init,
> +    .save_state          = gicv2_save_state,
> +    .restore_state       = gicv2_restore_state,
> +    .dump_state          = gicv2_dump_state,
> +    .gicv_setup          = gicv2v_setup,
> +    .gic_host_irq_type   = &gicv2_host_irq_type,
> +    .gic_guest_irq_type  = &gicv2_guest_irq_type,
> +    .eoi_irq             = gicv2_eoi_irq,
> +    .deactivate_irq      = gicv2_dir_irq,
> +    .read_irq            = gicv2_read_irq,
> +    .set_irq_properties  = gicv2_set_irq_properties,
> +    .send_SGI            = gicv2_send_SGI,
> +    .disable_interface   = gicv2_disable_interface,
> +    .update_lr           = gicv2_update_lr,
> +    .update_hcr_status   = gicv2_hcr_status,
> +    .clear_lr            = gicv2_clear_lr,
> +    .read_lr             = gicv2_read_lr,
> +    .write_lr            = gicv2_write_lr,
> +    .read_vmcr_priority  = gicv2_read_vmcr_priority,
> +    .read_apr            = gicv2_read_apr,
> +    .make_dt_node        = gicv2_make_dt_node,
> +};
> +
> +/* Set up the GIC */
> +static int __init gicv2_preinit(struct dt_device_node *node, const void *data)
> +{
>      gicv2_info.hw_version = GIC_V2;
> +    gicv2_info.node = node;
>      register_gic_ops(&gicv2_ops);
> +    dt_irq_xlate = gic_irq_xlate;
>  
>      return 0;
>  }
> @@ -788,7 +792,7 @@ static const struct dt_device_match gicv2_dt_match[] __initconst =
>  
>  DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
>          .dt_match = gicv2_dt_match,
> -        .init = gicv2_init,
> +        .init = gicv2_preinit,
>  DT_DEVICE_END
>  
>  /*
> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
> index ab80670..48772f1 100644
> --- a/xen/arch/arm/gic-v3.c
> +++ b/xen/arch/arm/gic-v3.c
> @@ -1173,31 +1173,6 @@ static const hw_irq_controller gicv3_guest_irq_type = {
>      .set_affinity = gicv3_irq_set_affinity,
>  };
>  
> -static const struct gic_hw_operations gicv3_ops = {
> -    .info                = &gicv3_info,
> -    .save_state          = gicv3_save_state,
> -    .restore_state       = gicv3_restore_state,
> -    .dump_state          = gicv3_dump_state,
> -    .gicv_setup          = gicv_v3_init,
> -    .gic_host_irq_type   = &gicv3_host_irq_type,
> -    .gic_guest_irq_type  = &gicv3_guest_irq_type,
> -    .eoi_irq             = gicv3_eoi_irq,
> -    .deactivate_irq      = gicv3_dir_irq,
> -    .read_irq            = gicv3_read_irq,
> -    .set_irq_properties  = gicv3_set_irq_properties,
> -    .send_SGI            = gicv3_send_sgi,
> -    .disable_interface   = gicv3_disable_interface,
> -    .update_lr           = gicv3_update_lr,
> -    .update_hcr_status   = gicv3_hcr_status,
> -    .clear_lr            = gicv3_clear_lr,
> -    .read_lr             = gicv3_read_lr,
> -    .write_lr            = gicv3_write_lr,
> -    .read_vmcr_priority  = gicv3_read_vmcr_priority,
> -    .read_apr            = gicv3_read_apr,
> -    .secondary_init      = gicv3_secondary_cpu_init,
> -    .make_dt_node        = gicv3_make_dt_node,
> -};
> -
>  static int __init cmp_rdist(const void *a, const void *b)
>  {
>      const struct rdist_region *l = a, *r = a;
> @@ -1207,11 +1182,12 @@ static int __init cmp_rdist(const void *a, const void *b)
>  }
>  
>  /* Set up the GIC */
> -static int __init gicv3_init(struct dt_device_node *node, const void *data)
> +static int __init gicv3_init(void)
>  {
>      struct rdist_region *rdist_regs;
>      int res, i;
>      uint32_t reg;
> +    const struct dt_device_node *node = gicv3_info.node;
>  
>      if ( !cpu_has_gicv3 )
>      {
> @@ -1219,8 +1195,6 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
>          return -ENODEV;
>      }
>  
> -    dt_device_set_used_by(node, DOMID_XEN);
> -
>      res = dt_device_get_address(node, 0, &gicv3.dbase, &gicv3.dbase_size);
>      if ( res || !gicv3.dbase )
>          panic("GICv3: Cannot find a valid distributor address");
> @@ -1274,9 +1248,6 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
>          panic("GICv3: Cannot find the maintenance IRQ");
>      gicv3_info.maintenance_irq = res;
>  
> -    /* Set the GIC as the primary interrupt controller */
> -    dt_interrupt_controller = node;
> -
>      for ( i = 0; i < gicv3.rdist_count; i++ )
>      {
>          /* map dbase & rdist regions */
> @@ -1311,15 +1282,47 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
>      res = gicv3_cpu_init();
>      gicv3_hyp_init();
>  
> -    gicv3_info.hw_version = GIC_V3;
> -    /* Register hw ops*/
> -    register_gic_ops(&gicv3_ops);
> -
>      spin_unlock(&gicv3.lock);
>  
>      return res;
>  }
>  
> +static const struct gic_hw_operations gicv3_ops = {
> +    .info                = &gicv3_info,
> +    .init                = gicv3_init,
> +    .save_state          = gicv3_save_state,
> +    .restore_state       = gicv3_restore_state,
> +    .dump_state          = gicv3_dump_state,
> +    .gicv_setup          = gicv_v3_init,
> +    .gic_host_irq_type   = &gicv3_host_irq_type,
> +    .gic_guest_irq_type  = &gicv3_guest_irq_type,
> +    .eoi_irq             = gicv3_eoi_irq,
> +    .deactivate_irq      = gicv3_dir_irq,
> +    .read_irq            = gicv3_read_irq,
> +    .set_irq_properties  = gicv3_set_irq_properties,
> +    .send_SGI            = gicv3_send_sgi,
> +    .disable_interface   = gicv3_disable_interface,
> +    .update_lr           = gicv3_update_lr,
> +    .update_hcr_status   = gicv3_hcr_status,
> +    .clear_lr            = gicv3_clear_lr,
> +    .read_lr             = gicv3_read_lr,
> +    .write_lr            = gicv3_write_lr,
> +    .read_vmcr_priority  = gicv3_read_vmcr_priority,
> +    .read_apr            = gicv3_read_apr,
> +    .secondary_init      = gicv3_secondary_cpu_init,
> +    .make_dt_node        = gicv3_make_dt_node,
> +};
> +
> +static int __init gicv3_preinit(struct dt_device_node *node, const void *data)
> +{
> +    gicv3_info.hw_version = GIC_V3;
> +    gicv3_info.node = node;
> +    register_gic_ops(&gicv3_ops);
> +    dt_irq_xlate = gic_irq_xlate;
> +
> +    return 0;
> +}
> +
>  static const struct dt_device_match gicv3_dt_match[] __initconst =
>  {
>      DT_MATCH_GIC_V3,
> @@ -1328,7 +1331,7 @@ static const struct dt_device_match gicv3_dt_match[] __initconst =
>  
>  DT_DEVICE_START(gicv3, "GICv3", DEVICE_GIC)
>          .dt_match = gicv3_dt_match,
> -        .init = gicv3_init,
> +        .init = gicv3_preinit,
>  DT_DEVICE_END
>  
>  /*
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index 940fb8e..8e7f24b 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -163,8 +163,10 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
>      return 0;
>  }
>  
> -/* Set up the GIC */
> -void __init gic_init(void)
> +/* Find the interrupt controller and set up the callback to translate
> + * device tree IRQ.
> + */
> +void __init gic_preinit(void)
>  {
>      int rc;
>      struct dt_device_node *node;
> @@ -189,6 +191,16 @@ void __init gic_init(void)
>      if ( !num_gics )
>          panic("Unable to find compatible GIC in the device tree");
>  
> +    /* Set the GIC as the primary interrupt controller */
> +    dt_interrupt_controller = node;
> +    dt_device_set_used_by(node, DOMID_XEN);
> +}
> +
> +/* Set up the GIC */
> +void __init gic_init(void)
> +{
> +    if ( gic_hw_ops->init() )
> +        panic("Failed to initialize the GIC drivers");
>      /* Clear LR mask for cpu0 */
>      clear_cpu_lr_mask();
>  }
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index b905c9f..4f05f57 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -752,7 +752,6 @@ void __init start_xen(unsigned long boot_phys_offset,
>  
>      vm_init();
>      dt_unflatten_host_device_tree();
> -    dt_irq_xlate = gic_irq_xlate;
>  
>      init_IRQ();
>  
> @@ -760,6 +759,8 @@ void __init start_xen(unsigned long boot_phys_offset,
>  
>      preinit_xen_time();
>  
> +    gic_preinit();
> +
>      dt_uart_init();
>      console_init_preirq();
>      console_init_ring();
> diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
> index 89a9b6f..b16f98e 100644
> --- a/xen/include/asm-arm/gic.h
> +++ b/xen/include/asm-arm/gic.h
> @@ -232,6 +232,10 @@ extern void gic_remove_from_queues(struct vcpu *v, unsigned int virtual_irq);
>  
>  /* Accept an interrupt from the GIC and dispatch its handler */
>  extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq);
> +/* Find the interrupt controller and set up the callback to translate
> + * device tree IRQ.
> + */
> +extern void gic_preinit(void);
>  /* Bring up the interrupt controller, and report # cpus attached */
>  extern void gic_init(void);
>  /* Bring up a secondary CPU's per-CPU GIC interface */
> @@ -284,11 +288,15 @@ struct gic_info {
>      uint8_t nr_lrs;
>      /* Maintenance irq number */
>      unsigned int maintenance_irq;
> +    /* Pointer to the device tree node representing the interrupt controller */
> +    const struct dt_device_node *node;
>  };
>  
>  struct gic_hw_operations {
>      /* Hold GIC HW information */
>      const struct gic_info *info;
> +    /* Initialize the GIC and the boot CPU */
> +    int (*init)(void);
>      /* Save GIC registers */
>      void (*save_state)(struct vcpu *);
>      /* Restore GIC registers */

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 31/33] libxl: Add support for non-PCI passthrough
  2015-03-19 19:29 ` [PATCH v4 31/33] libxl: Add support for non-PCI passthrough Julien Grall
@ 2015-03-31 11:49   ` Ian Campbell
  2015-03-31 13:00     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:49 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> On ARM, every non-PCI device are described in the device tree. Each of
> them can be found via a path.
> 
> This patch introduces a very basic support, only the IOMMU will be set
> up correctly. The user will have to:
>     - Describe the device in the partial device tree
>     - Map manually MMIO/IRQ
> 
> This is a first approach, that will allow to have a basic non-PCI
> passthrough support in Xen. This could be improved later.
> 
> Furthermore add LIBXL_HAVE_DEVICETREE_PASSTHROUGH to indicate we
> support non-PCI passthrough and partial device tree (introduced by a
> previous patch).

Ah, you can ignore my comment on the previous patch then.

The comment with the #define might be an OK place for the
big-scary-warning I mentioned in the previous patch too?

> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> 
> ---
>     Changes in v4:
>         - Add LIBXL_HAVE_DEVICTREE_PASSTHROUGH to indicate we support
>         non-PCI passthrough. This is also used in order to indicate
>         partial device tree is supported
>         - Remove libxl_dtdev.c as it contains only a 2 lines functions
>         and call directly xc_* from libxl_create.c
>         - Introduce domcreate_attach_dtdev
> 
>     Changes in v3:
>         - Dynamic allocation has been dropped
>         - Rework the commit message in accordance with the previous
>         item
> 
>     Changes in v2:
>         - Get DT infos earlier
>         - Allocate/map IRQ in libxl__arch_domain_create rather than in
>         libxl__device_dt_add
>         - Use VIRQ rather than the PIRQ to construct the interrupts
>         properties of the device tree
>         - Correct cpumask in make_dtdev_node. We allow the interrupt to
>         be used on the 8 CPUs
>         - Fix LOGE when we map the MMIO region in the guest in
>         libxl__device_dt_add. The domain and the IRQ were inverted
>         - Calculate the number of SPIs to configure the VGIC
>         - xc_physdev_dtdev_* helpers has been renamed to xc_dtdev_*
>         - Rename libxl_device_dt to libxl_device_dtdev
> ---
>  tools/libxl/libxl.h          |  6 ++++++
>  tools/libxl/libxl_create.c   | 32 ++++++++++++++++++++++++++++++++
>  tools/libxl/libxl_internal.h |  5 +++++
>  tools/libxl/libxl_types.idl  |  5 +++++
>  4 files changed, 48 insertions(+)
> 
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index 6bc75c5..baaf06b 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -179,6 +179,12 @@
>  #define LIBXL_HAVE_BUILDINFO_HVM_MMIO_HOLE_MEMKB 1
>  
>  /*
> + * libxl_domain_build_info has device_tree and libxl_device_dtdev
> + * exists. This mean non-PCI passthrough is supported for ARM

Rather than non-PCI I'd say device tree here, since I'm sure you aren't
supporting the new flargle-bus I've just invented...

> + *
> +#define LIBXL_HAVE_DEVICETREE_PASSTHROUGH 1
> +
> +/*
>   * libxl ABI compatibility
>   *
>   * The only guarantee which libxl makes regarding ABI compatibility
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index 15b464e..39c828b 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -751,6 +751,8 @@ static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
>                                     int ret);
>  static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
>                                   int ret);
> +static void domcreate_attach_dtdev(libxl__egc *egc,
> +                                   libxl__domain_create_state *dcs);
>  
>  static void domcreate_console_available(libxl__egc *egc,
>                                          libxl__domain_create_state *dcs);
> @@ -1444,6 +1446,36 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
>          }
>      }
>  
> +    domcreate_attach_dtdev(egc, dcs);
> +    return;
> +
> +error_out:
> +    assert(ret);
> +    domcreate_complete(egc, dcs, ret);
> +}
> +
> +static void domcreate_attach_dtdev(libxl__egc *egc,
> +                                   libxl__domain_create_state *dcs)

I know it isn't strictly needed, but I think for consistency this
function should take a ret and check it + propagate it via
domcreate_complete on error, like the other ones in the call chain do.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 32/33] xl: Add new option dtdev
  2015-03-19 19:29 ` [PATCH v4 32/33] xl: Add new option dtdev Julien Grall
@ 2015-03-31 11:50   ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:50 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> The option "dtdev" will be used to passthrough a non-PCI device described

s/non-PCI/device tree/ or just drop it.

> in the device tree to a guest.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough
  2015-03-19 19:29 ` [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough Julien Grall
@ 2015-03-31 11:55   ` Ian Campbell
  2015-03-31 13:03     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:55 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Note that the example is done on Midway whose SMMU driver is not
> supported on Xen upstream.
> 
> Currently, I don't have other platform where I can test non-PCI
> passthrough.

Please drop references to non-PCI in favour of talking about device tree
throughout.

> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> ---
>     Changes in v4:
>         - Patch added
> ---
>  docs/misc/arm/passthrough.txt | 58 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
>  create mode 100644 docs/misc/arm/passthrough.txt
> 
> diff --git a/docs/misc/arm/passthrough.txt b/docs/misc/arm/passthrough.txt
> new file mode 100644
> index 0000000..cf6cc61
> --- /dev/null
> +++ b/docs/misc/arm/passthrough.txt
> @@ -0,0 +1,58 @@
> +Passthrough a non-pci device to a guest
> +=======================================
> +
> +The example will use the secondary network card for the midway server.
> +
> +1) Mark the device to let Xen knowns the device will be used for passthrough.

s/knowns/know/

> +This is done in the device tree node describing the device by adding the
> +property "xen,passthrough". The command to do it in U-Boot is:
> +
> +    fdt set /soc/ethernet@fff51000 xen,passthrough
> +
> +2) Create the partial device tree describing the device. The IRQ are mapped

s/the/a/

> +1:1 to the guest (i.e VIRQ == IRQ). For MMIO will have to find hole in the

s/MMIO will/MMIO you will/
s/find hole/find a hole/

> +guest memory layout (see xen/include/public/arch-arm.h, noted the layout

s/noted/note that/

> +is not stable and can change between 2 releases version of Xen).

s/between 2 releases version/versions/

> +
> +/dts-v1/;
> +
> +/ {
> +    /* #*cells are here to keep DTC happy */
> +    #address-cells = <2>;
> +    #size-cells = <2>;
> +
> +    aliases {
> +        net = &mac0;
> +    };
> +
> +    passthrough {
> +        compatible = "simple-bus";
> +        ranges;
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +    	mac0: ethernet@10000000 {
> +	    	compatible = "calxeda,hb-xgmac";
> +            reg = <0 0x10000000 0 0x1000>;
> +    		interrupts = <0 80 4  0 81 4  0 82 4>;

Tabs vs spaces?

Is it worth making reference to looking at the host entry and copying
some of the relevant bits of that, or would that be more confusing?

> +    	};
> +    };
> +};
> +
> +Note:
> +    * The interrupt-parent property will be added by the toolstack in the
> +    root node;
> +    * The properties compatible, ranges, #address-cells and #size-cells
> +    in /passthrough are mandatory.

The following properties are mandatory within the /passthrough node:
  * compatible
  * ranges
  * ...

Are the values of any of them mandatory, i.e. simply-bus or empty
ranges?

> +
> +3) Compile the partial guest device with dtc (Device Tree Compiler).
> +For our purpose, the compiled file will be called guest-midway.dtb and
> +placed in /root in DOM0.

Can you give an example of the command line please, and
s/guest-midway/passthrough/ would be more generic.

> +3) Add the following options in the guest configuration file:

Please expand to say add the dtdev, irqs and iomem options with values
corresponding to the resources used by the to-be-passedthrough device.
Perhaps also reference xl.cfg(5).

> +device_tree = "/root/guest-midway.dtb"
> +dtdev = [ "/soc/ethernet@fff51000" ]
> +irqs = [ 112, 113, 114 ]
> +iomem = [ "0xfff51,1@0x10000" ]
> +
Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough
  2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (33 preceding siblings ...)
  2015-03-20  1:22 ` [PATCH v4 00/33] xen/arm: Add support for " Edgar E. Iglesias
@ 2015-03-31 11:57 ` Ian Campbell
  2015-03-31 13:07   ` Julien Grall
  34 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:57 UTC (permalink / raw)
  To: Julien Grall
  Cc: manish.jaggi, tim, robert.vanvossen, stefano.stabellini,
	suravee.suthikulpanit, Josh.Whitehead, xen-devel,
	andrii.tseglytskyi

On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:

I think there is a healthy chunk at the start which is all acked and
could be applied, could you let me know how far through the acked bit of
the series you think it would be sensible to apply now?

If there are any acked bits which follow unacked bits but which are
independent then let me know and I'll see if they can be applied.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 17/33] xen/arm: vgic: Add spi_to_pending
  2015-03-31 10:55   ` Ian Campbell
@ 2015-03-31 11:58     ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-31 11:58 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, tim, stefano.stabellini

Hi Ian,

On 31/03/15 11:55, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> Introduce spi_to_pending in order retrieve the irq_pending structure for
>> a specific SPI.
>>
>> It's not possible to re-use irq_to_pending because it's required a VCPU
> 
> "it requires"
> 
>> and some call of the new function may during domain destruction after
>> the VCPUs are freed.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Acked-by: Ian Campbell <ian.campbell@citrix.com>

Thanks.

> Although given the name I would expect it to take an spi (i.e. -32) not
> an irq. I can't think of a better name though and perhaps that just
> makes things harder for the caller..

It depends if you think relative or absolute. In this case, the absolute
value is easier to use.

FWIW, we already have SPI-specific function using absolute value.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs
  2015-03-31 11:44     ` Julien Grall
@ 2015-03-31 11:59       ` Ian Campbell
  2015-03-31 12:07         ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 11:59 UTC (permalink / raw)
  To: Julien Grall
  Cc: Wei Liu, Ian Jackson, tim, stefano.stabellini, Jan Beulich, xen-devel

On Tue, 2015-03-31 at 12:44 +0100, Julien Grall wrote:
> Hi Ian,
> 
> On 31/03/15 11:54, Ian Campbell wrote:
> > On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> >> @@ -68,16 +68,17 @@ static void vgic_init_pending_irq(struct pending_irq *p, unsigned int virq)
> >>      p->irq = virq;
> >>  }
> >>  
> >> -int domain_vgic_init(struct domain *d)
> >> +int domain_vgic_init(struct domain *d, unsigned int nr_spis)
> >>  {
> >>      int i;
> >>  
> >>      d->arch.vgic.ctlr = 0;
> >>  
> > [...]
> >> +    /* Limit the number of SPIs supported base on the hardware */
> >> +    if ( nr_spis > (gic_number_lines() - NR_LOCAL_IRQS) )
> >> +        return -EINVAL;
> > 
> > Is there anything in the h/w which leads to this restriction?
> 
> The h/w accept an VirtualID < 1020. Although, given that we can only
> route a physical interrupt to the guest, it's pointless to support more
> SPIs than the h/w does.

Right, but it's an artificial restriction at this level. Lets not
bother.

> > If not then I think we should just check against the architectural 1020
> > limit and leave it at that.
> 
> I would have to check on 988 (1020 - 32) which I find less readable.

I'd test nr_spis+32 < 1020, which I think is clear enough.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs
  2015-03-31 11:59       ` Ian Campbell
@ 2015-03-31 12:07         ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-31 12:07 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Wei Liu, Ian Jackson, tim, stefano.stabellini, Jan Beulich, xen-devel

On 31/03/15 12:59, Ian Campbell wrote:
>>> If not then I think we should just check against the architectural 1020
>>> limit and leave it at that.
>>
>> I would have to check on 988 (1020 - 32) which I find less readable.
> 
> I'd test nr_spis+32 < 1020, which I think is clear enough.

I will do that.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq
  2015-03-31 11:11   ` Ian Campbell
@ 2015-03-31 12:23     ` Julien Grall
  2015-03-31 12:31       ` Ian Campbell
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 12:23 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, tim, Jan Beulich, stefano.stabellini

Hi Ian,

On 31/03/15 12:11, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> On x86, an IRQ is assigned in 2 steps to an HVM guest:
>>     - The toolstack is calling PHYSDEVOP_map_pirq in order to create a
>>     guest PIRQ (IRQ bound to an event channel)
>>     - The emulator (QEMU) is calling DOMCTL_bind_pt_irq in order to
>>     bind the IRQ
>>
>> On ARM, there is no concept of PIRQ as the IRQ can be assigned to a
>> virtual IRQ using the interrupt controller.
>>
>> It's not clear if we will need 2 different hypercalls on ARM to assign
>> IRQ and, for now, only the toolstack will manage IRQ.
>>
>> In order to avoid re-using a fixed ABI hypercall (PHYSDEVOP_*) for a
>> different purpose and allow us more time to figure out the right out,
> 
> "figure out the right way"
> 
>> only DOMCTL_{,un}bind_pt_pirq is implemented on ARM.
>>
>> The DOMCTL is extended with a new type PT_IRQ_TYPE_SPI and only IRQ ==
>> vIRQ (i.e machine_irq == spi) is supported.
>>
>> Concerning XSM, even if ARM is using one hypercall rather than 2, the
>> resulting check is nearly the same.
>>
>> XSM PHYSDEVOP_map_pirq:
>>     1) Check if the current domain can add resource to the domain
>>     2) Check if the current domain has permission to add the IRQ
>>     3) Check if the target domain has permission to use the IRQ
>>
>> XSM DOMCTL_bind_pirq_irq:
>>     1) Check if the current domain can add resource to the domain
>>     2) Check if the current domain has permission to bind the IRQ
>>     3) Check if the target domain has permission to use the IRQ
>>
>> Rather than checking that the current domain can both add and bind the
>> IRQ, we only check the bind permission. I think this is not a big deal
>> because we don't have emulator on ARM and therefore no disaggregation is
>> required.
> 
> Is this because we don't have the "add" concept on arm?

We don't need the 2 concepts on ARM. So I choose on of them. The "bind"
concept is tight to DOMCTL_bind_irq on x86.

Although, thinking a bit more, it would make more sense to use check
"add" but not "bind".

This is because on x86, "add" concept if for the toolstack and "bind"
for the emulator/stubdomain.

FWIW, the example policy give both "add" and "bind" right to the
toolstack domain.

> 
>> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
>> index 579d266..8243b70 100644
>> --- a/tools/libxc/xc_domain.c
>> +++ b/tools/libxc/xc_domain.c
>> @@ -1764,7 +1764,7 @@ int xc_domain_bind_pt_irq(
>>      uint8_t bus,
>>      uint8_t device,
>>      uint8_t intx,
>> -    uint8_t isa_irq)
>> +    uint16_t isa_irq)
> 
> This interface is pretty awful, taking the union of all the options
> needed for each type as separate parameters. Reusing the isa_irq
> parameter is making this worse along a different axis as well.
> 
> AFAICT its only user is qemu-trad with PT_IRQ_TYPE_MSI_TRANSLATE.

I didn't find any other caller. I could replace the usage in
xc_domain_update_msi_irq.

> I think we should discourage any new uses of this function, and hide any
> ugliness in an internal static function to be used by the more specific
> xc_domain_bind_pt_isa_irq et al. i.e. make the current
> xc_doamin_bind_pt_irq an internal helper with a new name and a new
> spi_irq parameter and make the replacement xc_domain_bind_pt_irq a
> wrapper which handles only the set of types which it handles today and a
> new xc_domain_bind_pt_spi_irq which exposes the new functionality.
>
> Hopefully we can eventually remove xc_domain_bind_pt_irq. If you are
> minded to you could do that today, but it's not required I think.

IIRC, the libxc API is not stable so we could drop a function easily.

Every possible types of IRQ already have helpers. Making
xc_domain_bind_pt_irq static is the easiest things to do (compare to
clean the current function).

I will give a look.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device
  2015-03-31 11:24   ` Ian Campbell
@ 2015-03-31 12:30     ` Julien Grall
  2015-03-31 13:16       ` Ian Campbell
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 12:30 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Wei Liu, Ian Jackson, tim, stefano.stabellini, Jan Beulich, xen-devel

Hi Ian,

On 31/03/15 12:24, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> +int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d,
>> +                       XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>> +{
>> +    int ret;
>> +    struct dt_device_node *dev;
>> +
>> +    /* TODO: How to deal with XSM? */
> 
> Looks like you do in the following code? Old comment?

Old comment. I forgot to drop it.

>> +    /* TODO: Do we need to check is_dying? Mostly to protect against
>> +     * hypercall trying to passthrough a device while we are
>> +     * dying.
> 
> iommu_do_pci_domctl does in specific casses (i.e. assign device). I
> guess you should follow that lead.

I'm not sure to fully understand when is_dying should be used or not.

Looking to the PCI code, the is_dying has been added when we add code to
deal with page.

I would be inclined to say it's only necessary when deadling with page.
Can someone confirm me?

Otherwise, I don't why is_dying should be check here and not in other call.

> 
>> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
>> index 7f90150..a7cb272 100644
>> --- a/xen/include/public/domctl.h
>> +++ b/xen/include/public/domctl.h
>> @@ -475,12 +475,30 @@ typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
>>  DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
>>  
>>
>> -/* Assign PCI device to HVM guest. Sets up IOMMU structures. */
>> +/* Assign a device to a guest. Sets up IOMMU structures. */
>>  /* XEN_DOMCTL_assign_device */
>>  /* XEN_DOMCTL_test_assign_device */
>> -/* XEN_DOMCTL_deassign_device */
>> +/*
>> + * XEN_DOMCTL_deassign_device: The behavior of this DOMCTL differs
>> + * between the different type of device:
>> + *  - PCI device (XEN_DOMCTL_DEV_PCI) will be reassigned to DOM0
>> + *  - non-PCI device (XEN_DOMCTL_DEV_PCI) will left unassigned. DOM0
> 
> Did you miss a ! before XEN_DOMCTL, or did you mean to say DT?

I intended to say XEN_DOMCTL_DT. I will fix it.

> From an ease of review PoV it would have been nice to add dev and u.pci
> first since that would be mechanical, but nevermind now.

Sorry, I was too lazy to do it.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq
  2015-03-31 12:23     ` Julien Grall
@ 2015-03-31 12:31       ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 12:31 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Jan Beulich, stefano.stabellini

On Tue, 2015-03-31 at 13:23 +0100, Julien Grall wrote:
> Hi Ian,
> 
> On 31/03/15 12:11, Ian Campbell wrote:
> > On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> >> On x86, an IRQ is assigned in 2 steps to an HVM guest:
> >>     - The toolstack is calling PHYSDEVOP_map_pirq in order to create a
> >>     guest PIRQ (IRQ bound to an event channel)
> >>     - The emulator (QEMU) is calling DOMCTL_bind_pt_irq in order to
> >>     bind the IRQ
> >>
> >> On ARM, there is no concept of PIRQ as the IRQ can be assigned to a
> >> virtual IRQ using the interrupt controller.
> >>
> >> It's not clear if we will need 2 different hypercalls on ARM to assign
> >> IRQ and, for now, only the toolstack will manage IRQ.
> >>
> >> In order to avoid re-using a fixed ABI hypercall (PHYSDEVOP_*) for a
> >> different purpose and allow us more time to figure out the right out,
> > 
> > "figure out the right way"
> > 
> >> only DOMCTL_{,un}bind_pt_pirq is implemented on ARM.
> >>
> >> The DOMCTL is extended with a new type PT_IRQ_TYPE_SPI and only IRQ ==
> >> vIRQ (i.e machine_irq == spi) is supported.
> >>
> >> Concerning XSM, even if ARM is using one hypercall rather than 2, the
> >> resulting check is nearly the same.
> >>
> >> XSM PHYSDEVOP_map_pirq:
> >>     1) Check if the current domain can add resource to the domain
> >>     2) Check if the current domain has permission to add the IRQ
> >>     3) Check if the target domain has permission to use the IRQ
> >>
> >> XSM DOMCTL_bind_pirq_irq:
> >>     1) Check if the current domain can add resource to the domain
> >>     2) Check if the current domain has permission to bind the IRQ
> >>     3) Check if the target domain has permission to use the IRQ
> >>
> >> Rather than checking that the current domain can both add and bind the
> >> IRQ, we only check the bind permission. I think this is not a big deal
> >> because we don't have emulator on ARM and therefore no disaggregation is
> >> required.
> > 
> > Is this because we don't have the "add" concept on arm?
> 
> We don't need the 2 concepts on ARM. So I choose on of them. The "bind"
> concept is tight to DOMCTL_bind_irq on x86.
> 
> Although, thinking a bit more, it would make more sense to use check
> "add" but not "bind".
> 
> This is because on x86, "add" concept if for the toolstack and "bind"
> for the emulator/stubdomain.

OK.
> 
> FWIW, the example policy give both "add" and "bind" right to the
> toolstack domain.
> 
> > 
> >> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
> >> index 579d266..8243b70 100644
> >> --- a/tools/libxc/xc_domain.c
> >> +++ b/tools/libxc/xc_domain.c
> >> @@ -1764,7 +1764,7 @@ int xc_domain_bind_pt_irq(
> >>      uint8_t bus,
> >>      uint8_t device,
> >>      uint8_t intx,
> >> -    uint8_t isa_irq)
> >> +    uint16_t isa_irq)
> > 
> > This interface is pretty awful, taking the union of all the options
> > needed for each type as separate parameters. Reusing the isa_irq
> > parameter is making this worse along a different axis as well.
> > 
> > AFAICT its only user is qemu-trad with PT_IRQ_TYPE_MSI_TRANSLATE.
> 
> I didn't find any other caller. I could replace the usage in
> xc_domain_update_msi_irq.
> 
> > I think we should discourage any new uses of this function, and hide any
> > ugliness in an internal static function to be used by the more specific
> > xc_domain_bind_pt_isa_irq et al. i.e. make the current
> > xc_doamin_bind_pt_irq an internal helper with a new name and a new
> > spi_irq parameter and make the replacement xc_domain_bind_pt_irq a
> > wrapper which handles only the set of types which it handles today and a
> > new xc_domain_bind_pt_spi_irq which exposes the new functionality.
> >
> > Hopefully we can eventually remove xc_domain_bind_pt_irq. If you are
> > minded to you could do that today, but it's not required I think.
> 
> IIRC, the libxc API is not stable so we could drop a function easily.

Yes, I just didn't want to say that you must shave that yakk here, if
you are keen to do so them please have at it!

> Every possible types of IRQ already have helpers. Making
> xc_domain_bind_pt_irq static is the easiest things to do (compare to
> clean the current function).
> 
> I will give a look.

Thanks.
Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 27/33] tools/libxl: Create a per-arch function to map IRQ to a domain
  2015-03-31 11:26   ` Ian Campbell
@ 2015-03-31 12:33     ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-31 12:33 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

Hi Ian,

On 31/03/15 12:26, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> ARM and x86 use a different hypercall to map an IRQ to a domain.
>>
>> The hypercall to give IRQ permission to the domain as also been moved
> 
> "has also been".
> 
>> on the x86 specific function as ARM guest won't be able to manage the IRQ.
> 
> s/on the/to be an/?

Yes, I will fix it in the next version.

>> We may want to support it later.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
>> Cc: Wei Liu <wei.liu2@citrix.com>
> 
> Acked-by: Ian Campbell <ian.campbell@citrix.com>

Thanks,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-03-31 11:35   ` Ian Campbell
@ 2015-03-31 12:46     ` Julien Grall
  2015-03-31 13:18       ` Ian Campbell
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 12:46 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

Hi Ian,

On 31/03/15 12:35, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> 
>> The functions fdt_{fisrt,next}_subnode may not be available because:
> 
> "first"
> 
>> diff --git a/tools/libxl/libxl_fdt.c b/tools/libxl/libxl_fdt.c
>> new file mode 100644
>> index 0000000..f88e9f1
>> --- /dev/null
>> +++ b/tools/libxl/libxl_fdt.c
> 
> Since this is effectively shims for missing libfdt functionality how
> about libxl_libfdt_compat.c or some such?

I will rename the file.

> If wee wanted any fdt specific helpers as part of libxl itself then
> those would want to use the libxl_fdt.c name.
> 
>> @@ -0,0 +1,84 @@
>> +/*
>> + * libfdt - Flat Device Tree manipulation
>> + * Copyright (C) 2006 David Gibson, IBM Corporation.
>> + *
>> + * libfdt is dual licensed: you can use it either under the terms of
>> + * the GPL, or the BSD license, at your option.
> 
> Since this is libxl, which should be LGPL I think we must therefore be
> taking the BSD option. Perhaps we should make that clear? I'm not sure.

After speaking with Ian J. I will:
	- Drop the GPL license from the header as we use the BSD one
	- Add the libxl header license
	- Specify in the commit message why we chose the BSD license.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM
  2015-03-31 11:41   ` Ian Campbell
@ 2015-03-31 12:55     ` Julien Grall
  2015-03-31 13:19       ` Ian Campbell
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 12:55 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

Hi Ian,

On 31/03/15 12:41, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> Let the user to pass additional nodes to the guest device tree. For
>> this purpose, everything in the node /passthrough from the partial
>> device tree will be copied into the guest device tree.
>>
>> The node /aliases will be also copied to allow the user to define
>> aliases which can be used by the guest kernel.
>>
>> A simple partial device tree will look like:
>>
>> /dts-v1/;
>>
>> / {
>>         #address-cells = <2>;
>>         #size-cells = <2>;
>>
>>         passthrough {
>>             compatible = "simple-bus";
>>             ranges;
>>             #address-cells = <2>;
>>             #size-cells = <2>;
>>
>>             /* List of your nodes */
>>         }
>> };
>>
>> Note that:
>>     * The interrupt-parent property will be added by the toolstack in
>>     the root node
>>     * The properties compatible, ranges, #address-cells and #size-cells
>>     in /passthrough are mandatory.
>>
>> The helpers provided by the libfdt don't perform all the necessary
>> security check on a given device tree. Therefore, only trusted device
>> tree should be used.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
>> Cc: Wei Liu <wei.liu2@citrix.com>
>>
>> ---
>>     An example of the partial device tree, as long as how to passthrough
>>     a non-pci device will be added to the tree in a follow-up patch.
>>
>>     A new LIBXL_HAVE_* will be added in the patch which add support for
>>     non-PCI passthrough as both are tight.
>>
>>     Changes in v4:
>>         - Mark the option as unsafe
>>         - The _fdt_* helpers has been moved in a separate patch/file.
>>         Only the prototype is declared
>>         - The partial DT is considered valid. Remove some security check
>>         which make the code cleaner
>>         - Typoes
>>
>>     Changes in v3:
>>         - Patch added
>> ---
>>  docs/man/xl.cfg.pod.5       |  10 +++
>>  tools/libxl/libxl_arm.c     | 171 ++++++++++++++++++++++++++++++++++++++++++++
>>  tools/libxl/libxl_types.idl |   1 +
>>  tools/libxl/xl_cmdimpl.c    |   1 +
> 
> Needs a #define LIBXL_HAVE in libxl.h for 3rd party users of the
> library.

As said below the commit message:

"A new LIBXL_HAVE_* will be added in the patch which add support for
non-PCI passthrough as both are tight."

Having the define in the patch #31.

>>  4 files changed, 183 insertions(+)
>>
>> diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
>> index 93cd7d2..bcbc277 100644
>> --- a/docs/man/xl.cfg.pod.5
>> +++ b/docs/man/xl.cfg.pod.5
>> @@ -453,6 +453,16 @@ not emulated.
>>  Specify that this domain is a driver domain. This enables certain
>>  features needed in order to run a driver domain.
>>  
>> +=item B<device_tree=PATH>
>> +
>> +Specify a partial device tree (compiled via the Device Tree Compiler).
>> +Everything under the node "/passthrough" will be copied into the guest
>> +device tree. For convenience, the node "/aliases" is also copied to allow
>> +the user to defined aliases which can be used by the guest kernel.
>> +
>> +Given the complexity of verifying the validity of a device tree, this
>> +option should only be used with trusted device tree.
> 
> This warning should be in the libxl API docs (i.e. the header or IDL)
> somewhere too, so that 3rd party toolstacks know about it. In that
> context it should perhaps be a lot more prominent and scarier sounding
> too.

I will add it to the IDL. Should I keep there too for the xl documentation?

>> +
>>  =back
>>  
>>  =head2 Devices
>> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
>> index 06e940b..54d197b 100644
>> --- a/tools/libxl/libxl_arm.c
>> +++ b/tools/libxl/libxl_arm.c
>> @@ -542,6 +542,156 @@ out:
>>      }
>>  }
>>  
>> +/* Only FDT v17 is supported */
>> +#define FDT_REQUIRED_VERSION    0x11
> 
> Are versions >v17 broken? Or is there some other problem with being more
> forward compatible?
> (TBH, I've no idea how often this value changes, maybe it's unlikely to
> now?)

It was necessary on the previous version of this patch because I was
doing some security check specific to the v17.

I think this check is useless now. So I will drop it.

> 
>> +    return (propoff != -FDT_ERR_NOTFOUND)? propoff : 0;
>> +}
>> +
>> +/*
>> + * These functions are defined by libfdt or libxl_fdt.c if it's not
>> + * present on the former.
>> + */
>> +int fdt_next_subnode(const void *fdt, int offset);
>> +int fdt_first_subnode(const void *fdt, int offset);
> 
> Better to use the prototype from the libfdt header if it is present,
> i.e. wrap these in the associated ifdef-s.

The prototype may be defined in the libfdt header but the function not
exported.

I didn't wrap them into ifdef in order to make sure that the compiler
will complain if the 2 prototypes are different.

> 
> I'm in two minds about suggesting putting all that into
> libxl_libfdt_compat.h, up to you.

I didn't want to bother adding a new header file.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 31/33] libxl: Add support for non-PCI passthrough
  2015-03-31 11:49   ` Ian Campbell
@ 2015-03-31 13:00     ` Julien Grall
  2015-03-31 13:20       ` Ian Campbell
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 13:00 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

Hi Ian,

On 31/03/15 12:49, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> On ARM, every non-PCI device are described in the device tree. Each of
>> them can be found via a path.
>>
>> This patch introduces a very basic support, only the IOMMU will be set
>> up correctly. The user will have to:
>>     - Describe the device in the partial device tree
>>     - Map manually MMIO/IRQ
>>
>> This is a first approach, that will allow to have a basic non-PCI
>> passthrough support in Xen. This could be improved later.
>>
>> Furthermore add LIBXL_HAVE_DEVICETREE_PASSTHROUGH to indicate we
>> support non-PCI passthrough and partial device tree (introduced by a
>> previous patch).
> 
> Ah, you can ignore my comment on the previous patch then.
> 
> The comment with the #define might be an OK place for the
> big-scary-warning I mentioned in the previous patch too?

I think this IDL would be a more suitable place.

>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
>> Cc: Wei Liu <wei.liu2@citrix.com>
>>
>> ---
>>     Changes in v4:
>>         - Add LIBXL_HAVE_DEVICTREE_PASSTHROUGH to indicate we support
>>         non-PCI passthrough. This is also used in order to indicate
>>         partial device tree is supported
>>         - Remove libxl_dtdev.c as it contains only a 2 lines functions
>>         and call directly xc_* from libxl_create.c
>>         - Introduce domcreate_attach_dtdev
>>
>>     Changes in v3:
>>         - Dynamic allocation has been dropped
>>         - Rework the commit message in accordance with the previous
>>         item
>>
>>     Changes in v2:
>>         - Get DT infos earlier
>>         - Allocate/map IRQ in libxl__arch_domain_create rather than in
>>         libxl__device_dt_add
>>         - Use VIRQ rather than the PIRQ to construct the interrupts
>>         properties of the device tree
>>         - Correct cpumask in make_dtdev_node. We allow the interrupt to
>>         be used on the 8 CPUs
>>         - Fix LOGE when we map the MMIO region in the guest in
>>         libxl__device_dt_add. The domain and the IRQ were inverted
>>         - Calculate the number of SPIs to configure the VGIC
>>         - xc_physdev_dtdev_* helpers has been renamed to xc_dtdev_*
>>         - Rename libxl_device_dt to libxl_device_dtdev
>> ---
>>  tools/libxl/libxl.h          |  6 ++++++
>>  tools/libxl/libxl_create.c   | 32 ++++++++++++++++++++++++++++++++
>>  tools/libxl/libxl_internal.h |  5 +++++
>>  tools/libxl/libxl_types.idl  |  5 +++++
>>  4 files changed, 48 insertions(+)
>>
>> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
>> index 6bc75c5..baaf06b 100644
>> --- a/tools/libxl/libxl.h
>> +++ b/tools/libxl/libxl.h
>> @@ -179,6 +179,12 @@
>>  #define LIBXL_HAVE_BUILDINFO_HVM_MMIO_HOLE_MEMKB 1
>>  
>>  /*
>> + * libxl_domain_build_info has device_tree and libxl_device_dtdev
>> + * exists. This mean non-PCI passthrough is supported for ARM
> 
> Rather than non-PCI I'd say device tree here, since I'm sure you aren't
> supporting the new flargle-bus I've just invented...

Ok

> 
>> + *
>> +#define LIBXL_HAVE_DEVICETREE_PASSTHROUGH 1
>> +
>> +/*
>>   * libxl ABI compatibility
>>   *
>>   * The only guarantee which libxl makes regarding ABI compatibility
>> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
>> index 15b464e..39c828b 100644
>> --- a/tools/libxl/libxl_create.c
>> +++ b/tools/libxl/libxl_create.c
>> @@ -751,6 +751,8 @@ static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
>>                                     int ret);
>>  static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
>>                                   int ret);
>> +static void domcreate_attach_dtdev(libxl__egc *egc,
>> +                                   libxl__domain_create_state *dcs);
>>  
>>  static void domcreate_console_available(libxl__egc *egc,
>>                                          libxl__domain_create_state *dcs);
>> @@ -1444,6 +1446,36 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
>>          }
>>      }
>>  
>> +    domcreate_attach_dtdev(egc, dcs);
>> +    return;
>> +
>> +error_out:
>> +    assert(ret);
>> +    domcreate_complete(egc, dcs, ret);
>> +}
>> +
>> +static void domcreate_attach_dtdev(libxl__egc *egc,
>> +                                   libxl__domain_create_state *dcs)
> 
> I know it isn't strictly needed, but I think for consistency this
> function should take a ret and check it + propagate it via
> domcreate_complete on error, like the other ones in the call chain do.

The other caller have the ret because they use multidev. When it's not
the case (such as domcreate_console_available), the ret parameter is not
present.

So I'm not keen to add a new unused parameter.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough
  2015-03-31 11:55   ` Ian Campbell
@ 2015-03-31 13:03     ` Julien Grall
  2015-03-31 13:21       ` Ian Campbell
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 13:03 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, tim, stefano.stabellini

Hi Ian,

On 31/03/15 12:55, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> Note that the example is done on Midway whose SMMU driver is not
>> supported on Xen upstream.
>>
>> Currently, I don't have other platform where I can test non-PCI
>> passthrough.
> 
> Please drop references to non-PCI in favour of talking about device tree
> throughout.

Will do.

>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>>
>> ---
>>     Changes in v4:
>>         - Patch added
>> ---
>>  docs/misc/arm/passthrough.txt | 58 +++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 58 insertions(+)
>>  create mode 100644 docs/misc/arm/passthrough.txt
>>
>> diff --git a/docs/misc/arm/passthrough.txt b/docs/misc/arm/passthrough.txt
>> new file mode 100644
>> index 0000000..cf6cc61
>> --- /dev/null
>> +++ b/docs/misc/arm/passthrough.txt
>> @@ -0,0 +1,58 @@
>> +Passthrough a non-pci device to a guest
>> +=======================================
>> +
>> +The example will use the secondary network card for the midway server.
>> +
>> +1) Mark the device to let Xen knowns the device will be used for passthrough.
> 
> s/knowns/know/
> 
>> +This is done in the device tree node describing the device by adding the
>> +property "xen,passthrough". The command to do it in U-Boot is:
>> +
>> +    fdt set /soc/ethernet@fff51000 xen,passthrough
>> +
>> +2) Create the partial device tree describing the device. The IRQ are mapped
> 
> s/the/a/
> 
>> +1:1 to the guest (i.e VIRQ == IRQ). For MMIO will have to find hole in the
> 
> s/MMIO will/MMIO you will/
> s/find hole/find a hole/
> 
>> +guest memory layout (see xen/include/public/arch-arm.h, noted the layout
> 
> s/noted/note that/
> 
>> +is not stable and can change between 2 releases version of Xen).
> 
> s/between 2 releases version/versions/
> 
>> +
>> +/dts-v1/;
>> +
>> +/ {
>> +    /* #*cells are here to keep DTC happy */
>> +    #address-cells = <2>;
>> +    #size-cells = <2>;
>> +
>> +    aliases {
>> +        net = &mac0;
>> +    };
>> +
>> +    passthrough {
>> +        compatible = "simple-bus";
>> +        ranges;
>> +        #address-cells = <2>;
>> +        #size-cells = <2>;
>> +    	mac0: ethernet@10000000 {
>> +	    	compatible = "calxeda,hb-xgmac";
>> +            reg = <0 0x10000000 0 0x1000>;
>> +    		interrupts = <0 80 4  0 81 4  0 82 4>;
> 
> Tabs vs spaces?

I think so. I will fix it.

> 
> Is it worth making reference to looking at the host entry and copying
> some of the relevant bits of that, or would that be more confusing?

I don't understand the question here.

>> +    	};
>> +    };
>> +};
>> +
>> +Note:
>> +    * The interrupt-parent property will be added by the toolstack in the
>> +    root node;
>> +    * The properties compatible, ranges, #address-cells and #size-cells
>> +    in /passthrough are mandatory.
> 
> The following properties are mandatory within the /passthrough node:
>   * compatible
>   * ranges
>   * ...
> 
> Are the values of any of them mandatory, i.e. simply-bus or empty
> ranges?

"simple-bus" is mandatory. The empty ranges not.

> 
>> +
>> +3) Compile the partial guest device with dtc (Device Tree Compiler).
>> +For our purpose, the compiled file will be called guest-midway.dtb and
>> +placed in /root in DOM0.
> 
> Can you give an example of the command line please, and
> s/guest-midway/passthrough/ would be more generic.

I can.

> 
>> +3) Add the following options in the guest configuration file:
> 
> Please expand to say add the dtdev, irqs and iomem options with values
> corresponding to the resources used by the to-be-passedthrough device.
> Perhaps also reference xl.cfg(5).

Ok.

>> +device_tree = "/root/guest-midway.dtb"
>> +dtdev = [ "/soc/ethernet@fff51000" ]
>> +irqs = [ 112, 113, 114 ]
>> +iomem = [ "0xfff51,1@0x10000" ]
>> +

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough
  2015-03-31 11:57 ` Ian Campbell
@ 2015-03-31 13:07   ` Julien Grall
  2015-03-31 13:22     ` Ian Campbell
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 13:07 UTC (permalink / raw)
  To: Ian Campbell
  Cc: manish.jaggi, tim, robert.vanvossen, stefano.stabellini,
	suravee.suthikulpanit, Josh.Whitehead, xen-devel,
	andrii.tseglytskyi

Hi Ian,

On 31/03/15 12:57, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> 
> I think there is a healthy chunk at the start which is all acked and
> could be applied, could you let me know how far through the acked bit of
> the series you think it would be sensible to apply now?
> 
> If there are any acked bits which follow unacked bits but which are
> independent then let me know and I'll see if they can be applied.

Patch up to #15 (except #7 which miss an ack from Jan) can be pushed.

Although some of them contains nits. If it convenient for you, I can
resend the series with the nits fixed and patch sorted in order to apply
the first part.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device
  2015-03-31 12:30     ` Julien Grall
@ 2015-03-31 13:16       ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 13:16 UTC (permalink / raw)
  To: Julien Grall
  Cc: Wei Liu, Ian Jackson, tim, stefano.stabellini, Jan Beulich, xen-devel

On Tue, 2015-03-31 at 13:30 +0100, Julien Grall wrote:
> >> +    /* TODO: Do we need to check is_dying? Mostly to protect against
> >> +     * hypercall trying to passthrough a device while we are
> >> +     * dying.
> > 
> > iommu_do_pci_domctl does in specific casses (i.e. assign device). I
> > guess you should follow that lead.
> 
> I'm not sure to fully understand when is_dying should be used or not.
> 
> Looking to the PCI code, the is_dying has been added when we add code to
> deal with page.
> 
> I would be inclined to say it's only necessary when deadling with page.
> Can someone confirm me?
> 
> Otherwise, I don't why is_dying should be check here and not in other call.

it makes little sense to add a device to a domain which is dying, but
it's just about plausible you might want to remove it (e.g. to unwedge
something which has gone wrong).

Overall I think being consistent with other similar cases (e.g. PCI) is
the way to go.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-03-31 12:46     ` Julien Grall
@ 2015-03-31 13:18       ` Ian Campbell
  2015-04-07 17:15         ` Julien Grall
  2015-04-09 12:16         ` Ian Jackson
  0 siblings, 2 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 13:18 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Tue, 2015-03-31 at 13:46 +0100, Julien Grall wrote:
> Hi Ian,
> 
> On 31/03/15 12:35, Ian Campbell wrote:
> > On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> > 
> >> The functions fdt_{fisrt,next}_subnode may not be available because:
> > 
> > "first"
> > 
> >> diff --git a/tools/libxl/libxl_fdt.c b/tools/libxl/libxl_fdt.c
> >> new file mode 100644
> >> index 0000000..f88e9f1
> >> --- /dev/null
> >> +++ b/tools/libxl/libxl_fdt.c
> > 
> > Since this is effectively shims for missing libfdt functionality how
> > about libxl_libfdt_compat.c or some such?
> 
> I will rename the file.
> 
> > If wee wanted any fdt specific helpers as part of libxl itself then
> > those would want to use the libxl_fdt.c name.
> > 
> >> @@ -0,0 +1,84 @@
> >> +/*
> >> + * libfdt - Flat Device Tree manipulation
> >> + * Copyright (C) 2006 David Gibson, IBM Corporation.
> >> + *
> >> + * libfdt is dual licensed: you can use it either under the terms of
> >> + * the GPL, or the BSD license, at your option.
> > 
> > Since this is libxl, which should be LGPL I think we must therefore be
> > taking the BSD option. Perhaps we should make that clear? I'm not sure.
> 
> After speaking with Ian J. I will:
> 	- Drop the GPL license from the header as we use the BSD one
> 	- Add the libxl header license
> 	- Specify in the commit message why we chose the BSD license.

One downside to dropping the GPL bit is that any fixes which we get to
this code cannot then easily be upstreamed.

TBH I think it would be find to include both the GPL and BSD and to
include a comment that within the context of libxl we have chosen BSD
and so the overall license of the work remains LGPL. Ian may disagree
though.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM
  2015-03-31 12:55     ` Julien Grall
@ 2015-03-31 13:19       ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 13:19 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Tue, 2015-03-31 at 13:55 +0100, Julien Grall wrote:
> Hi Ian,
> 
> On 31/03/15 12:41, Ian Campbell wrote:
> > On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> >> Let the user to pass additional nodes to the guest device tree. For
> >> this purpose, everything in the node /passthrough from the partial
> >> device tree will be copied into the guest device tree.
> >>
> >> The node /aliases will be also copied to allow the user to define
> >> aliases which can be used by the guest kernel.
> >>
> >> A simple partial device tree will look like:
> >>
> >> /dts-v1/;
> >>
> >> / {
> >>         #address-cells = <2>;
> >>         #size-cells = <2>;
> >>
> >>         passthrough {
> >>             compatible = "simple-bus";
> >>             ranges;
> >>             #address-cells = <2>;
> >>             #size-cells = <2>;
> >>
> >>             /* List of your nodes */
> >>         }
> >> };
> >>
> >> Note that:
> >>     * The interrupt-parent property will be added by the toolstack in
> >>     the root node
> >>     * The properties compatible, ranges, #address-cells and #size-cells
> >>     in /passthrough are mandatory.
> >>
> >> The helpers provided by the libfdt don't perform all the necessary
> >> security check on a given device tree. Therefore, only trusted device
> >> tree should be used.
> >>
> >> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> >> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> >> Cc: Wei Liu <wei.liu2@citrix.com>
> >>
> >> ---
> >>     An example of the partial device tree, as long as how to passthrough
> >>     a non-pci device will be added to the tree in a follow-up patch.
> >>
> >>     A new LIBXL_HAVE_* will be added in the patch which add support for
> >>     non-PCI passthrough as both are tight.
> >>
> >>     Changes in v4:
> >>         - Mark the option as unsafe
> >>         - The _fdt_* helpers has been moved in a separate patch/file.
> >>         Only the prototype is declared
> >>         - The partial DT is considered valid. Remove some security check
> >>         which make the code cleaner
> >>         - Typoes
> >>
> >>     Changes in v3:
> >>         - Patch added
> >> ---
> >>  docs/man/xl.cfg.pod.5       |  10 +++
> >>  tools/libxl/libxl_arm.c     | 171 ++++++++++++++++++++++++++++++++++++++++++++
> >>  tools/libxl/libxl_types.idl |   1 +
> >>  tools/libxl/xl_cmdimpl.c    |   1 +
> > 
> > Needs a #define LIBXL_HAVE in libxl.h for 3rd party users of the
> > library.
> 
> As said below the commit message:

Oops, I couldn't remember v3 so I didn't read the changelog and missed
this, sorry.

> >>  4 files changed, 183 insertions(+)
> >>
> >> diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
> >> index 93cd7d2..bcbc277 100644
> >> --- a/docs/man/xl.cfg.pod.5
> >> +++ b/docs/man/xl.cfg.pod.5
> >> @@ -453,6 +453,16 @@ not emulated.
> >>  Specify that this domain is a driver domain. This enables certain
> >>  features needed in order to run a driver domain.
> >>  
> >> +=item B<device_tree=PATH>
> >> +
> >> +Specify a partial device tree (compiled via the Device Tree Compiler).
> >> +Everything under the node "/passthrough" will be copied into the guest
> >> +device tree. For convenience, the node "/aliases" is also copied to allow
> >> +the user to defined aliases which can be used by the guest kernel.
> >> +
> >> +Given the complexity of verifying the validity of a device tree, this
> >> +option should only be used with trusted device tree.
> > 
> > This warning should be in the libxl API docs (i.e. the header or IDL)
> > somewhere too, so that 3rd party toolstacks know about it. In that
> > context it should perhaps be a lot more prominent and scarier sounding
> > too.
> 
> I will add it to the IDL. Should I keep there too for the xl documentation?

I think it should be in both, libxl/IDL for developers and xl docs for
users.

> > 
> >> +    return (propoff != -FDT_ERR_NOTFOUND)? propoff : 0;
> >> +}
> >> +
> >> +/*
> >> + * These functions are defined by libfdt or libxl_fdt.c if it's not
> >> + * present on the former.
> >> + */
> >> +int fdt_next_subnode(const void *fdt, int offset);
> >> +int fdt_first_subnode(const void *fdt, int offset);
> > 
> > Better to use the prototype from the libfdt header if it is present,
> > i.e. wrap these in the associated ifdef-s.
> 
> The prototype may be defined in the libfdt header but the function not
> exported.
> 
> I didn't wrap them into ifdef in order to make sure that the compiler
> will complain if the 2 prototypes are different.

OK.

> 
> > 
> > I'm in two minds about suggesting putting all that into
> > libxl_libfdt_compat.h, up to you.
> 
> I didn't want to bother adding a new header file.
> 
> Regards,
> 

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 31/33] libxl: Add support for non-PCI passthrough
  2015-03-31 13:00     ` Julien Grall
@ 2015-03-31 13:20       ` Ian Campbell
  0 siblings, 0 replies; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 13:20 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

On Tue, 2015-03-31 at 14:00 +0100, Julien Grall wrote:

> >> +static void domcreate_attach_dtdev(libxl__egc *egc,
> >> +                                   libxl__domain_create_state *dcs)
> > 
> > I know it isn't strictly needed, but I think for consistency this
> > function should take a ret and check it + propagate it via
> > domcreate_complete on error, like the other ones in the call chain do.
> 
> The other caller have the ret because they use multidev. When it's not
> the case (such as domcreate_console_available), the ret parameter is not
> present.
> 
> So I'm not keen to add a new unused parameter.

OK, if it's inconsistent already no harm in another.

> 
> Regards,
> 

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough
  2015-03-31 13:03     ` Julien Grall
@ 2015-03-31 13:21       ` Ian Campbell
  2015-04-09 13:36         ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 13:21 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Tue, 2015-03-31 at 14:03 +0100, Julien Grall wrote:

> >> +    passthrough {
> >> +        compatible = "simple-bus";
> >> +        ranges;
> >> +        #address-cells = <2>;
> >> +        #size-cells = <2>;
> >> +    	mac0: ethernet@10000000 {
> >> +	    	compatible = "calxeda,hb-xgmac";
> >> +            reg = <0 0x10000000 0 0x1000>;
> >> +    		interrupts = <0 80 4  0 81 4  0 82 4>;
> > 
> > Tabs vs spaces?
> 
> I think so. I will fix it.
> 
> > 
> > Is it worth making reference to looking at the host entry and copying
> > some of the relevant bits of that, or would that be more confusing?
> 
> I don't understand the question here.

Should we give people a hint that to discover the contents of this node
they should refer to the equivalent entry in the host db.

> 
> >> +    	};
> >> +    };
> >> +};
> >> +
> >> +Note:
> >> +    * The interrupt-parent property will be added by the toolstack in the
> >> +    root node;
> >> +    * The properties compatible, ranges, #address-cells and #size-cells
> >> +    in /passthrough are mandatory.
> > 
> > The following properties are mandatory within the /passthrough node:
> >   * compatible
> >   * ranges
> >   * ...
> > 
> > Are the values of any of them mandatory, i.e. simply-bus or empty
> > ranges?
> 
> "simple-bus" is mandatory. The empty ranges not.

It's worth saying the former I think.

For the latter a non-empty ranges would require exciting calculations
and changes to the iomem parameter to match etc, so perhaps recommend
that it be empty?

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough
  2015-03-31 13:07   ` Julien Grall
@ 2015-03-31 13:22     ` Ian Campbell
  2015-04-01 14:21       ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-03-31 13:22 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, manish.jaggi, tim, stefano.stabellini

On Tue, 2015-03-31 at 14:07 +0100, Julien Grall wrote:
> Hi Ian,
> 
> On 31/03/15 12:57, Ian Campbell wrote:
> > On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> > 
> > I think there is a healthy chunk at the start which is all acked and
> > could be applied, could you let me know how far through the acked bit of
> > the series you think it would be sensible to apply now?
> > 
> > If there are any acked bits which follow unacked bits but which are
> > independent then let me know and I'll see if they can be applied.
> 
> Patch up to #15 (except #7 which miss an ack from Jan) can be pushed.
> 
> Although some of them contains nits. If it convenient for you, I can
> resend the series with the nits fixed and patch sorted in order to apply
> the first part.

That would be super, thanks.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest
  2015-03-19 19:29 ` [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest Julien Grall
@ 2015-03-31 13:24   ` Andrew Cooper
  2015-03-31 13:30     ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Andrew Cooper @ 2015-03-31 13:24 UTC (permalink / raw)
  To: xen-devel

On 19/03/15 19:29, Julien Grall wrote:
> Flask code already provides a helper to copy a string from guest. In a later
> patch, the new DT hypercalls will need a similar function.
>
> To avoid code duplication, copy the flask helper (flask_copying_string) to
> common code:
>     - Rename into safe_copy_string_from_guest
>     - Add comment to explain the extra +1
>     - Return the buffer directly and use the macros provided by
>     xen/err.h to return an error code if necessary.
>
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Keir Fraser <keir@xen.org>
>
> ---
>     Changes in v4:
>         - Use -ENOBUFS rather than -ENOENT
>         - Fix coding style in comment
>         - Typoes in commit message
>         - Convert the new flask_copying_string (for DT) in
>         safe_copy_string_from_guest
>         - Add Ian and Daniel's ack
>
>     Changes in v3:
>         - Use macros of xen/err.h to return either the buffer or an
>         error code
>         - Reuse size_t instead of unsigned long
>         - Update comment and commit message
>
>     Changes in v2:
>         - Rename copy_string_from_guest into safe_copy_string_from_guest
>         - Update commit message and comment in the code
> ---
>  xen/common/Makefile            |  1 +
>  xen/common/guestcopy.c         | 31 ++++++++++++++++++++++++++
>  xen/include/xen/guest_access.h |  5 +++++
>  xen/xsm/flask/flask_op.c       | 49 +++++++++++-------------------------------
>  4 files changed, 50 insertions(+), 36 deletions(-)
>  create mode 100644 xen/common/guestcopy.c
>
> diff --git a/xen/common/Makefile b/xen/common/Makefile
> index 1956091..cf15887 100644
> --- a/xen/common/Makefile
> +++ b/xen/common/Makefile
> @@ -9,6 +9,7 @@ obj-y += event_2l.o
>  obj-y += event_channel.o
>  obj-y += event_fifo.o
>  obj-y += grant_table.o
> +obj-y += guestcopy.o
>  obj-y += irq.o
>  obj-y += kernel.o
>  obj-y += keyhandler.o
> diff --git a/xen/common/guestcopy.c b/xen/common/guestcopy.c
> new file mode 100644
> index 0000000..1645cbd
> --- /dev/null
> +++ b/xen/common/guestcopy.c
> @@ -0,0 +1,31 @@
> +#include <xen/config.h>
> +#include <xen/lib.h>
> +#include <xen/guest_access.h>
> +#include <xen/err.h>
> +
> +/*
> + * The function copies a string from the guest and adds a NUL to
> + * make sure the string is correctly terminated.
> + */
> +void *safe_copy_string_from_guest(XEN_GUEST_HANDLE(char) u_buf,
> +                                  size_t size, size_t max_size)

If it is a NUL terminated string, you should return char* rather than void*.

Furthermore, two size parameters serves no useful purpose.  The caller
must always be in a position to decide a plausible upper bound.

> +{
> +    char *tmp;
> +
> +    if ( size > max_size )
> +        return ERR_PTR(-ENOBUFS);
> +
> +    /* Add an extra +1 to append \0 */
> +    tmp = xmalloc_array(char, size + 1);

Need to check that size + 1 doesn't overflow to 0.

> +    if ( !tmp )
> +        return ERR_PTR(-ENOMEM);
> +
> +    if ( copy_from_guest(tmp, u_buf, size) )
> +    {
> +        xfree(tmp);
> +        return ERR_PTR(-EFAULT);
> +    }
> +    tmp[size] = 0;

'\0' please.

~Andrew

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest
  2015-03-31 13:24   ` Andrew Cooper
@ 2015-03-31 13:30     ` Julien Grall
  2015-03-31 13:49       ` Andrew Cooper
  0 siblings, 1 reply; 103+ messages in thread
From: Julien Grall @ 2015-03-31 13:30 UTC (permalink / raw)
  To: Andrew Cooper, xen-devel

Hi Andrew,

On 31/03/15 14:24, Andrew Cooper wrote:
>> +/*
>> + * The function copies a string from the guest and adds a NUL to
>> + * make sure the string is correctly terminated.
>> + */
>> +void *safe_copy_string_from_guest(XEN_GUEST_HANDLE(char) u_buf,
>> +                                  size_t size, size_t max_size)
> 
> If it is a NUL terminated string, you should return char* rather than void*.

Ok.

> Furthermore, two size parameters serves no useful purpose.  The caller
> must always be in a position to decide a plausible upper bound.

I don't understand the problem to have two size parameters...

The first one is the size given by the guest while the second one if the
upper bound.

The maximum size may change from every caller. Hence the second size
parameter.

>> +{
>> +    char *tmp;
>> +
>> +    if ( size > max_size )
>> +        return ERR_PTR(-ENOBUFS);
>> +
>> +    /* Add an extra +1 to append \0 */
>> +    tmp = xmalloc_array(char, size + 1);
> 
> Need to check that size + 1 doesn't overflow to 0.

With the max_size controlled by the caller there is no need to check the
overflow.

If the caller decides to give a too high max_size then it's its problem.

> 
>> +    if ( !tmp )
>> +        return ERR_PTR(-ENOMEM);
>> +
>> +    if ( copy_from_guest(tmp, u_buf, size) )
>> +    {
>> +        xfree(tmp);
>> +        return ERR_PTR(-EFAULT);
>> +    }
>> +    tmp[size] = 0;
> 
> '\0' please.

Ok.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest
  2015-03-31 13:30     ` Julien Grall
@ 2015-03-31 13:49       ` Andrew Cooper
  2015-03-31 14:00         ` Julien Grall
  0 siblings, 1 reply; 103+ messages in thread
From: Andrew Cooper @ 2015-03-31 13:49 UTC (permalink / raw)
  To: Julien Grall, xen-devel

On 31/03/15 14:30, Julien Grall wrote:
>
>> Furthermore, two size parameters serves no useful purpose.  The caller
>> must always be in a position to decide a plausible upper bound.
> I don't understand the problem to have two size parameters...
>
> The first one is the size given by the guest while the second one if the
> upper bound.
>
> The maximum size may change from every caller. Hence the second size
> parameter.

The caller shouldn't even be calling safe_copy_string_from_guest() with
a guest-controlled-implausibly-large size.

The caller should be doing something like:

if ( usersize > PLAUSIBLE_UPPER_BOUND )
  ... fail
else
  data = safe_copy_string_from_guest(hnd, usersize).


Mixing plausibility checks and string copying in a single function is a
antipattern, and IMO should not be moved into a common helper function
like this.

~Andrew

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest
  2015-03-31 13:49       ` Andrew Cooper
@ 2015-03-31 14:00         ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-31 14:00 UTC (permalink / raw)
  To: Andrew Cooper, xen-devel

On 31/03/15 14:49, Andrew Cooper wrote:
> On 31/03/15 14:30, Julien Grall wrote:
>>
>>> Furthermore, two size parameters serves no useful purpose.  The caller
>>> must always be in a position to decide a plausible upper bound.
>> I don't understand the problem to have two size parameters...
>>
>> The first one is the size given by the guest while the second one if the
>> upper bound.
>>
>> The maximum size may change from every caller. Hence the second size
>> parameter.
> 
> The caller shouldn't even be calling safe_copy_string_from_guest() with
> a guest-controlled-implausibly-large size.
> 
> The caller should be doing something like:
> 
> if ( usersize > PLAUSIBLE_UPPER_BOUND )
>   ... fail
> else
>   data = safe_copy_string_from_guest(hnd, usersize).
> 
> 
> Mixing plausibility checks and string copying in a single function is a
> antipattern, and IMO should not be moved into a common helper function
> like this.

Why it's an antipattern? It's exactly the same as checking the validity
of the buffer in copy_from_guest...

safe_copy-string_from_guest will fail if the size is too high.

Caller of this function may forget to do the check and introduce a
security issue. Having the check in safe_copy_string_from_guest avoid
this problem.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough
  2015-03-19 19:29 ` [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough Julien Grall
  2015-03-31 11:17   ` Ian Campbell
@ 2015-03-31 17:12   ` Daniel De Graaf
  2015-03-31 17:14     ` Julien Grall
  1 sibling, 1 reply; 103+ messages in thread
From: Daniel De Graaf @ 2015-03-31 17:12 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: stefano.stabellini, tim, ian.campbell

On 03/19/2015 03:29 PM, Julien Grall wrote:
> This is a follow-up of commit 525ee49 "xsm: add device tree labeling
> support" which add support for device tree labelling in flask.
>
> Those helpers will be use latter when non-pci passthrough (i.e device
> tree) will be added.
>
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Looks good to me with one assumption below.

Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>

[...]
> diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c
> index b1a4f8a..31bc702 100644
> --- a/xen/xsm/flask/avc.c
> +++ b/xen/xsm/flask/avc.c
> @@ -600,6 +600,9 @@ void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
>       case AVC_AUDIT_DATA_MEMORY:
>           avc_printk(&buf, "pte=%#lx mfn=%#lx ", a->memory.pte, a->memory.mfn);
>           break;
> +    case AVC_AUDIT_DATA_DTDEV:
> +        avc_printk(&buf, "dtdevice=%s ", a->dtdev);
> +        break;
>       }
>
>       avc_dump_query(&buf, ssid, tsid, tclass);

This output could be end up being ambiguous if a device tree path can contain
spaces.  Am I correct in assuming that they are invalid in device tree paths?

-- 
Daniel De Graaf
National Security Agency

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough
  2015-03-31 17:12   ` Daniel De Graaf
@ 2015-03-31 17:14     ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-03-31 17:14 UTC (permalink / raw)
  To: Daniel De Graaf, xen-devel; +Cc: stefano.stabellini, tim, ian.campbell

Hi Daniel,

On 31/03/15 18:12, Daniel De Graaf wrote:
> On 03/19/2015 03:29 PM, Julien Grall wrote:
>> This is a follow-up of commit 525ee49 "xsm: add device tree labeling
>> support" which add support for device tree labelling in flask.
>>
>> Those helpers will be use latter when non-pci passthrough (i.e device
>> tree) will be added.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Looks good to me with one assumption below.
> 
> Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> 
> [...]
>> diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c
>> index b1a4f8a..31bc702 100644
>> --- a/xen/xsm/flask/avc.c
>> +++ b/xen/xsm/flask/avc.c
>> @@ -600,6 +600,9 @@ void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32
>> requested,
>>       case AVC_AUDIT_DATA_MEMORY:
>>           avc_printk(&buf, "pte=%#lx mfn=%#lx ", a->memory.pte,
>> a->memory.mfn);
>>           break;
>> +    case AVC_AUDIT_DATA_DTDEV:
>> +        avc_printk(&buf, "dtdevice=%s ", a->dtdev);
>> +        break;
>>       }
>>
>>       avc_dump_query(&buf, ssid, tsid, tclass);
> 
> This output could be end up being ambiguous if a device tree path can
> contain
> spaces.  Am I correct in assuming that they are invalid in device tree
> paths?

Correct.

Thanks,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough
  2015-03-31 13:22     ` Ian Campbell
@ 2015-04-01 14:21       ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-04-01 14:21 UTC (permalink / raw)
  To: Ian Campbell, Julien Grall
  Cc: xen-devel, manish.jaggi, tim, stefano.stabellini

On 31/03/15 14:22, Ian Campbell wrote:
> On Tue, 2015-03-31 at 14:07 +0100, Julien Grall wrote:
>> Hi Ian,
>>
>> On 31/03/15 12:57, Ian Campbell wrote:
>>> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>>>
>>> I think there is a healthy chunk at the start which is all acked and
>>> could be applied, could you let me know how far through the acked bit of
>>> the series you think it would be sensible to apply now?
>>>
>>> If there are any acked bits which follow unacked bits but which are
>>> independent then let me know and I'll see if they can be applied.
>>
>> Patch up to #15 (except #7 which miss an ack from Jan) can be pushed.
>>
>> Although some of them contains nits. If it convenient for you, I can
>> resend the series with the nits fixed and patch sorted in order to apply
>> the first part.
> 
> That would be super, thanks.

I will resend this series in 2 parts. First part will contains all the
patches acked than can be applied now. The second part the rest of the
series.

I will send the first part today and the second part later.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-03-31 13:18       ` Ian Campbell
@ 2015-04-07 17:15         ` Julien Grall
  2015-04-09 12:16         ` Ian Jackson
  1 sibling, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-04-07 17:15 UTC (permalink / raw)
  To: Ian Campbell, Julien Grall
  Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

Hi,

On 31/03/15 14:18, Ian Campbell wrote:
> On Tue, 2015-03-31 at 13:46 +0100, Julien Grall wrote:
>> Hi Ian,
>>
>> On 31/03/15 12:35, Ian Campbell wrote:
>>> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>>>
>>>> The functions fdt_{fisrt,next}_subnode may not be available because:
>>>
>>> "first"
>>>
>>>> diff --git a/tools/libxl/libxl_fdt.c b/tools/libxl/libxl_fdt.c
>>>> new file mode 100644
>>>> index 0000000..f88e9f1
>>>> --- /dev/null
>>>> +++ b/tools/libxl/libxl_fdt.c
>>>
>>> Since this is effectively shims for missing libfdt functionality how
>>> about libxl_libfdt_compat.c or some such?
>>
>> I will rename the file.
>>
>>> If wee wanted any fdt specific helpers as part of libxl itself then
>>> those would want to use the libxl_fdt.c name.
>>>
>>>> @@ -0,0 +1,84 @@
>>>> +/*
>>>> + * libfdt - Flat Device Tree manipulation
>>>> + * Copyright (C) 2006 David Gibson, IBM Corporation.
>>>> + *
>>>> + * libfdt is dual licensed: you can use it either under the terms of
>>>> + * the GPL, or the BSD license, at your option.
>>>
>>> Since this is libxl, which should be LGPL I think we must therefore be
>>> taking the BSD option. Perhaps we should make that clear? I'm not sure.
>>
>> After speaking with Ian J. I will:
>> 	- Drop the GPL license from the header as we use the BSD one
>> 	- Add the libxl header license
>> 	- Specify in the commit message why we chose the BSD license.
> 
> One downside to dropping the GPL bit is that any fixes which we get to
> this code cannot then easily be upstreamed.
> 
> TBH I think it would be find to include both the GPL and BSD and to
> include a comment that within the context of libxl we have chosen BSD
> and so the overall license of the work remains LGPL. Ian may disagree
> though.

Ian J., is it fine for you?

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-03-31 13:18       ` Ian Campbell
  2015-04-07 17:15         ` Julien Grall
@ 2015-04-09 12:16         ` Ian Jackson
  2015-04-09 13:59           ` Julien Grall
  2015-04-14 11:40           ` Ian Campbell
  1 sibling, 2 replies; 103+ messages in thread
From: Ian Jackson @ 2015-04-09 12:16 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, Julien Grall, tim, Wei Liu, stefano.stabellini

Ian Campbell writes ("Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first,next}_subnode are present in libfdt"):
> On Tue, 2015-03-31 at 13:46 +0100, Julien Grall wrote:
> > After speaking with Ian J. I will:
> > 	- Drop the GPL license from the header as we use the BSD one
> > 	- Add the libxl header license
> > 	- Specify in the commit message why we chose the BSD license.
> 
> One downside to dropping the GPL bit is that any fixes which we get to
> this code cannot then easily be upstreamed.

That's not the case.

AIUI upstream's version of this file is  BSD(2-clause) \union GPLv2.

Our copy of the file will be  BSD(2-clause) \union LGPLv2.1.

We write LGPLv2.1 in it only to be clear that when anyone distributes
libxl_libfdt.c as part of libxl they must comply with the terms of the
LGPLv2.1 for the whole of libxl including libfdt.

But the dual licence means that anyone who finds something in our
version that they want to send upstream, this is easy: they choose the
BSD(2-clause) option in the licence of our version, which (because
BSD(2-clause) is GPL*-compatible) grants the ability to distribute as
GPLv2.

I think that leaving the GPL licence notice in is simply confusing.
The GPLv2 doesn't grant any additional permissions not covered by
BSD(2-clause), and the extra restrictions implied by GPLv2 are
irrelevant in the context of libxl because we are relying entirely on
the BSD(2-clause) option from upstream.

> TBH I think it would be find to include both the GPL and BSD and to
> include a comment that within the context of libxl we have chosen BSD
> and so the overall license of the work remains LGPL. Ian may disagree
> though.

I would say something like this:

  Copyright 2010 Alice
  Copyright 2014 Carol
  Copyright 2015 Bob

  This file is part of libxl, and was originally taken from libfdt.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU Lesser General Public License as published
  by the Free Software Foundation; version 2.1 only. with the special
  exception on linking described in file LICENSE.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Lesser General Public License for more details.

  Additionally, this particular file is dual licensed.  That is,
  alternatively, at your option:

       Redistribution and use in source and binary forms, with or
       without modification, are permitted provided that the following
       conditions are met:

       1. Redistributions of source code must retain the above
          copyright notice, this list of conditions and the following
          disclaimer.
       2. Redistributions in binary form must reproduce the above
          copyright notice, this list of conditions and the following
          disclaimer in the documentation and/or other materials
          provided with the distribution.

       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
       CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
       INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
       MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
       EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  Note that this applies only to this file, and other files with a
  similar notice.  Also, note that when the same code is distributed
  along with the rest of libxl, you must comply with the terms of the
  LGPLv2.1 for the whole of libxl including this file.

  The intent is to permit, in particular, upstream libfdt to
  incorporate improvements to this file within upstream libfdt.  At
  the time of writing, upstream libfdt is dual licensed: 2-clause BSD
  (as above) and GPLv2-or-later.  The 2-clause BSD licence is
  compatible with both GPLv2-or-later and LGPLv2.1-only; this permits
  copying in both directions, and the optional licence upgrade to a
  copyleft licence by libdft upstream or the Xen Project,
  respectively.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 30/33] tools/libxl: arm: Use an higher value for the GIC phandle
  2015-03-31 11:43   ` Ian Campbell
@ 2015-04-09 12:36     ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-04-09 12:36 UTC (permalink / raw)
  To: Ian Campbell, Julien Grall
  Cc: xen-devel, tim, Ian Jackson, stefano.stabellini, Wei Liu

Hi Ian,

On 31/03/15 12:43, Ian Campbell wrote:
> On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
>> The partial device tree may contains phandle. The Device Tree Compiler
>> tends to allocate the phandle from 1.
>>
>> Reserve the ID 65000 for the GIC phandle. I think we can safely assume
>> that the partial device tree will never contain a such ID.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
>> Cc: Wei Liu <wei.liu2@citrix.com>
>>
>> ---
>>     It's not easily possible to track the maximum phandle in the partial
>>     device tree.
>>
>>     We would need to parse it twice: one for looking the maximum
>>     phandle, and one for copying the nodes. This is because we have to
>>     know the phandle of the GIC when we create the properties of the
>>     root.
> 
> Or you could fill it in post-hoc like we do with e.g. the initramfs
> location?

That would work. I will see for a follow-up of this patch series.

> Anyway, this'll do for now:
> Acked-by: Ian Campbell <ian.ampbell@citrix.com>
> 
>>
>>     As the phandle is encoded an unsigned 32 bits, I could use an higher
>>     value. Though, having 65000 phandle is already a lot...
>>
>>     TODO: If it's necessary, I can check if the value has been used by
>>     another phandle in the device tree.
> 
> If that's easy enough to add then yes please, but if it is complex then
> don't bother.

I would prefer to postpone and replace with a follow-up to allocate
dynamically the phandle.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough
  2015-03-31 13:21       ` Ian Campbell
@ 2015-04-09 13:36         ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-04-09 13:36 UTC (permalink / raw)
  To: Ian Campbell, Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On 31/03/15 14:21, Ian Campbell wrote:
> On Tue, 2015-03-31 at 14:03 +0100, Julien Grall wrote:
> 
>>>> +    passthrough {
>>>> +        compatible = "simple-bus";
>>>> +        ranges;
>>>> +        #address-cells = <2>;
>>>> +        #size-cells = <2>;
>>>> +    	mac0: ethernet@10000000 {
>>>> +	    	compatible = "calxeda,hb-xgmac";
>>>> +            reg = <0 0x10000000 0 0x1000>;
>>>> +    		interrupts = <0 80 4  0 81 4  0 82 4>;
>>>
>>> Tabs vs spaces?
>>
>> I think so. I will fix it.
>>
>>>
>>> Is it worth making reference to looking at the host entry and copying
>>> some of the relevant bits of that, or would that be more confusing?
>>
>> I don't understand the question here.
> 
> Should we give people a hint that to discover the contents of this node
> they should refer to the equivalent entry in the host db.

I don't think it's necessary.

In the current state, DT passthrough is very primitive and only a user
who is aware of device tree concept can use it (some properties can't be
added in the DT...).

>>
>>>> +    	};
>>>> +    };
>>>> +};
>>>> +
>>>> +Note:
>>>> +    * The interrupt-parent property will be added by the toolstack in the
>>>> +    root node;
>>>> +    * The properties compatible, ranges, #address-cells and #size-cells
>>>> +    in /passthrough are mandatory.
>>>
>>> The following properties are mandatory within the /passthrough node:
>>>   * compatible
>>>   * ranges
>>>   * ...
>>>
>>> Are the values of any of them mandatory, i.e. simply-bus or empty
>>> ranges?
>>
>> "simple-bus" is mandatory. The empty ranges not.
> 
> It's worth saying the former I think.
> 
> For the latter a non-empty ranges would require exciting calculations
> and changes to the iomem parameter to match etc, so perhaps recommend
> that it be empty?

I think the user is smart enough to decide which solution is better for him.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-04-09 12:16         ` Ian Jackson
@ 2015-04-09 13:59           ` Julien Grall
  2015-04-14 11:40           ` Ian Campbell
  1 sibling, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-04-09 13:59 UTC (permalink / raw)
  To: Ian Jackson, Ian Campbell
  Cc: xen-devel, Julien Grall, tim, Wei Liu, stefano.stabellini

Hi Ian,

On 09/04/15 13:16, Ian Jackson wrote:
> Ian Campbell writes ("Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first,next}_subnode are present in libfdt"):
>> On Tue, 2015-03-31 at 13:46 +0100, Julien Grall wrote:
>>> After speaking with Ian J. I will:
>>> 	- Drop the GPL license from the header as we use the BSD one
>>> 	- Add the libxl header license
>>> 	- Specify in the commit message why we chose the BSD license.
>>
>> One downside to dropping the GPL bit is that any fixes which we get to
>> this code cannot then easily be upstreamed.
> 
> That's not the case.
> 
> AIUI upstream's version of this file is  BSD(2-clause) \union GPLv2.

Right.

> Our copy of the file will be  BSD(2-clause) \union LGPLv2.1.
> 
> We write LGPLv2.1 in it only to be clear that when anyone distributes
> libxl_libfdt.c as part of libxl they must comply with the terms of the
> LGPLv2.1 for the whole of libxl including libfdt.
> 
> But the dual licence means that anyone who finds something in our
> version that they want to send upstream, this is easy: they choose the
> BSD(2-clause) option in the licence of our version, which (because
> BSD(2-clause) is GPL*-compatible) grants the ability to distribute as
> GPLv2.
> 
> I think that leaving the GPL licence notice in is simply confusing.
> The GPLv2 doesn't grant any additional permissions not covered by
> BSD(2-clause), and the extra restrictions implied by GPLv2 are
> irrelevant in the context of libxl because we are relying entirely on
> the BSD(2-clause) option from upstream.
> 
>> TBH I think it would be find to include both the GPL and BSD and to
>> include a comment that within the context of libxl we have chosen BSD
>> and so the overall license of the work remains LGPL. Ian may disagree
>> though.
> 
> I would say something like this:

I will reuse the text below and add your signed-off-by for the license part.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-04-09 12:16         ` Ian Jackson
  2015-04-09 13:59           ` Julien Grall
@ 2015-04-14 11:40           ` Ian Campbell
  2015-04-14 13:34             ` Julien Grall
  1 sibling, 1 reply; 103+ messages in thread
From: Ian Campbell @ 2015-04-14 11:40 UTC (permalink / raw)
  To: Ian Jackson; +Cc: xen-devel, Julien Grall, tim, Wei Liu, stefano.stabellini

On Thu, 2015-04-09 at 13:16 +0100, Ian Jackson wrote:
> I would say something like this:

WFM, in particular the final two paragraphs which I think clarify
everything which needs clarifying, thanks.

Ian.

^ permalink raw reply	[flat|nested] 103+ messages in thread

* Re: [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt
  2015-04-14 11:40           ` Ian Campbell
@ 2015-04-14 13:34             ` Julien Grall
  0 siblings, 0 replies; 103+ messages in thread
From: Julien Grall @ 2015-04-14 13:34 UTC (permalink / raw)
  To: Ian Campbell, Ian Jackson
  Cc: xen-devel, Julien Grall, tim, Wei Liu, stefano.stabellini

Hi Ian,

On 14/04/15 12:40, Ian Campbell wrote:
> On Thu, 2015-04-09 at 13:16 +0100, Ian Jackson wrote:
>> I would say something like this:
> 
> WFM, in particular the final two paragraphs which I think clarify
> everything which needs clarifying, thanks.

I've updated the patch with the new wording. I'll wait that you go
through all the patch series before sending a new version.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 103+ messages in thread

end of thread, other threads:[~2015-04-14 13:35 UTC | newest]

Thread overview: 103+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
2015-03-19 19:29 ` [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts Julien Grall
2015-03-31 11:44   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 02/33] xen/dts: Allow only IRQ translation that are mapped to main GIC Julien Grall
2015-03-19 19:29 ` [PATCH v4 03/33] xen/dts: Use unsigned int for MMIO and IRQ index Julien Grall
2015-03-19 19:29 ` [PATCH v4 04/33] xen/arm: vgic: Introduce a function to initialize pending_irq Julien Grall
2015-03-19 19:29 ` [PATCH v4 05/33] xen/arm: Map disabled device in DOM0 Julien Grall
2015-03-19 19:29 ` [PATCH v4 06/33] xen/arm: Introduce xen, passthrough property Julien Grall
2015-03-31 10:25   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest Julien Grall
2015-03-31 13:24   ` Andrew Cooper
2015-03-31 13:30     ` Julien Grall
2015-03-31 13:49       ` Andrew Cooper
2015-03-31 14:00         ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 08/33] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE" Julien Grall
2015-03-31 10:26   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 09/33] xen: Extend DOMCTL createdomain to support arch configuration Julien Grall
2015-03-31 10:39   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 10/33] xen/arm: Allow virq != irq Julien Grall
2015-03-31 10:41   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
2015-03-20 11:36   ` Stefano Stabellini
2015-03-31 10:43   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 12/33] xen/arm: gic: Add sanity checks gic_route_irq_to_guest Julien Grall
2015-03-31 10:44   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
2015-03-20 11:51   ` Stefano Stabellini
2015-03-31 10:45   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 14/33] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber Julien Grall
2015-03-31 10:46   ` Ian Campbell
2015-03-31 11:28     ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 15/33] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts Julien Grall
2015-03-31 10:47   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs Julien Grall
2015-03-31 10:54   ` Ian Campbell
2015-03-31 11:44     ` Julien Grall
2015-03-31 11:59       ` Ian Campbell
2015-03-31 12:07         ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 17/33] xen/arm: vgic: Add spi_to_pending Julien Grall
2015-03-31 10:55   ` Ian Campbell
2015-03-31 11:58     ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 18/33] xen/arm: Release IRQ routed to a domain when it's destroying Julien Grall
2015-03-31 10:58   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq Julien Grall
2015-03-31 11:11   ` Ian Campbell
2015-03-31 12:23     ` Julien Grall
2015-03-31 12:31       ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 20/33] xen/dts: Provide an helper to get a DT node from a path provided by a guest Julien Grall
2015-03-31 11:12   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct Julien Grall
2015-03-20 10:53   ` Jan Beulich
2015-03-31 11:13   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 22/33] xen/passthrough: arm: release the DT devices assigned to a guest earlier Julien Grall
2015-03-31 11:16   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 23/33] xen/passthrough: iommu_deassign_device_dt: By default reassign device to nobody Julien Grall
2015-03-31 11:16   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 24/33] xen/iommu: arm: Wire iommu DOMCTL for ARM Julien Grall
2015-03-19 19:29 ` [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough Julien Grall
2015-03-31 11:17   ` Ian Campbell
2015-03-31 17:12   ` Daniel De Graaf
2015-03-31 17:14     ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device Julien Grall
2015-03-20 11:01   ` Jan Beulich
2015-03-31 11:24   ` Ian Campbell
2015-03-31 12:30     ` Julien Grall
2015-03-31 13:16       ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 27/33] tools/libxl: Create a per-arch function to map IRQ to a domain Julien Grall
2015-03-31 11:26   ` Ian Campbell
2015-03-31 12:33     ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt Julien Grall
2015-03-19 19:42   ` Julien Grall
2015-03-31 11:35   ` Ian Campbell
2015-03-31 12:46     ` Julien Grall
2015-03-31 13:18       ` Ian Campbell
2015-04-07 17:15         ` Julien Grall
2015-04-09 12:16         ` Ian Jackson
2015-04-09 13:59           ` Julien Grall
2015-04-14 11:40           ` Ian Campbell
2015-04-14 13:34             ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM Julien Grall
2015-03-31 11:41   ` Ian Campbell
2015-03-31 12:55     ` Julien Grall
2015-03-31 13:19       ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 30/33] tools/libxl: arm: Use an higher value for the GIC phandle Julien Grall
2015-03-31 11:43   ` Ian Campbell
2015-04-09 12:36     ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 31/33] libxl: Add support for non-PCI passthrough Julien Grall
2015-03-31 11:49   ` Ian Campbell
2015-03-31 13:00     ` Julien Grall
2015-03-31 13:20       ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 32/33] xl: Add new option dtdev Julien Grall
2015-03-31 11:50   ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough Julien Grall
2015-03-31 11:55   ` Ian Campbell
2015-03-31 13:03     ` Julien Grall
2015-03-31 13:21       ` Ian Campbell
2015-04-09 13:36         ` Julien Grall
2015-03-20  1:22 ` [PATCH v4 00/33] xen/arm: Add support for " Edgar E. Iglesias
2015-03-20 17:34   ` Julien Grall
2015-03-31 11:57 ` Ian Campbell
2015-03-31 13:07   ` Julien Grall
2015-03-31 13:22     ` Ian Campbell
2015-04-01 14:21       ` Julien Grall

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.