All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough
@ 2015-04-01 16:21 Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 01/14] xen/arm: Divide GIC initialization in 2 parts Julien Grall
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel; +Cc: Julien Grall, stefano.stabellini, tim, ian.campbell

Hello all,

This is the first part of the non-PCI passthrough series. It contains all
patches acked than can go now in Xen upstream.

Another patch series will be sent later in order to fully support non-PCI
passthrough.

Regards,

Julien Grall (14):
  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
  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

 MAINTAINERS                                  |   2 +
 docs/misc/arm/device-tree/passthrough.txt    |   9 +++
 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/device.c                        |   2 +-
 xen/arch/arm/domain.c                        |  28 ++++++-
 xen/arch/arm/domain_build.c                  | 114 +++++++++++++++++---------
 xen/arch/arm/domctl.c                        |  36 ---------
 xen/arch/arm/gic-v2.c                        |  86 +++++++++++---------
 xen/arch/arm/gic-v3.c                        |  91 +++++++++++----------
 xen/arch/arm/gic.c                           |  52 +++++++++---
 xen/arch/arm/irq.c                           | 116 ++++++++++++++++++++++-----
 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                         |   9 ++-
 xen/arch/arm/vgic-v2.c                       |   2 +-
 xen/arch/arm/vgic-v3.c                       |   2 +-
 xen/arch/arm/vgic.c                          |  39 ++++-----
 xen/arch/x86/domain.c                        |   3 +-
 xen/arch/x86/mm.c                            |   6 +-
 xen/arch/x86/setup.c                         |   8 +-
 xen/common/device_tree.c                     |  25 ++++--
 xen/common/domain.c                          |   7 +-
 xen/common/domctl.c                          |   3 +-
 xen/common/schedule.c                        |   3 +-
 xen/include/asm-arm/gic.h                    |  14 +++-
 xen/include/asm-arm/irq.h                    |   6 +-
 xen/include/asm-arm/vgic.h                   |   6 +-
 xen/include/public/arch-arm.h                |   8 ++
 xen/include/public/arch-x86/xen.h            |   4 +
 xen/include/public/domctl.h                  |  18 +----
 xen/include/xen/device_tree.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 -
 45 files changed, 572 insertions(+), 320 deletions(-)
 create mode 100644 docs/misc/arm/device-tree/passthrough.txt

-- 
2.1.4

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

* [PATCH v5 p1 01/14] xen/arm: Divide GIC initialization in 2 parts
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 02/14] xen/dts: Allow only IRQ translation that are mapped to main GIC Julien Grall
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel
  Cc: Zoltan Kiss, ian.campbell, Stefano Stabellini, Julien Grall, tim,
	Frediano Ziglio, stefano.stabellini

From: Julien Grall <julien.grall@linaro.org>

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] 16+ messages in thread

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

From: Julien Grall <julien.grall@linaro.org>

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] 16+ messages in thread

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

From: Julien Grall <julien.grall@linaro.org>

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] 16+ messages in thread

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

From: Julien Grall <julien.grall@linaro.org>

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 7b27900..fc6f851 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] 16+ messages in thread

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

From: Julien Grall <julien.grall@linaro.org>

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] 16+ messages in thread

* [PATCH v5 p1 06/14] xen/arm: Introduce xen, passthrough property
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (4 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 05/14] xen/arm: Map disabled device in DOM0 Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 07/14] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE" Julien Grall
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

From: Julien Grall <julien.grall@linaro.org>

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>

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

    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] 16+ messages in thread

* [PATCH v5 p1 07/14] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE"
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (5 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 06/14] xen/arm: Introduce xen, passthrough property Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 08/14] xen: Extend DOMCTL createdomain to support arch configuration Julien Grall
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel
  Cc: Keir Fraser, ian.campbell, tim, Julien Grall, Ian Jackson,
	stefano.stabellini, Jan Beulich

From: Julien Grall <julien.grall@linaro.org>

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

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

    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] 16+ messages in thread

* [PATCH v5 p1 08/14] xen: Extend DOMCTL createdomain to support arch configuration
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (6 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 07/14] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE" Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 09/14] xen/arm: Allow virq != irq Julien Grall
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 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

From: Julien Grall <julien.grall@linaro.org>

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>
Acked-by: Ian Campbell <ian.campbell@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 v5:
        - Remove "\n" in LOG
        - Typoes in comment
        - Add Ian's ack

    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 552ace8..44c7ac0 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 ae33234..95e3098 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..946618c 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", 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 1a6333a..f20565a 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -1098,7 +1098,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 26a0382..a88db69 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -707,7 +707,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 7f81dd3..3aba221 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -993,6 +993,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,
@@ -1482,8 +1484,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 376b477..5e9a8d2 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) {
@@ -324,6 +333,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 887fc10..e4d6fc8 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -531,9 +531,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;
 
@@ -541,6 +543,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;
 
@@ -561,6 +564,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 d103f8f..11a0be8 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..4ec7c13 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 emulating 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 393aa26..d2d9663 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 3e38761..b724aa5 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 c7885ff..89e4827 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 2b192ab..4ddaadf 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 c8bcb2d..b502a49 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -592,7 +592,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 462ff91..88770c6 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -1418,7 +1418,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 0c9f474..8803ab2 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. */
@@ -1080,7 +1068,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
@@ -1089,9 +1076,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 ecdcdec..026c072 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 4e2c1b7..34e5ab4 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 fe5406d..f89825c 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] 16+ messages in thread

* [PATCH v5 p1 09/14] xen/arm: Allow virq != irq
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (7 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 08/14] xen: Extend DOMCTL createdomain to support arch configuration Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 10/14] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

From: Julien Grall <julien.grall@linaro.org>

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>

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

    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 fc6f851..8f91962 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] 16+ messages in thread

* [PATCH v5 p1 10/14] xen/arm: route_irq_to_guest: Check validity of the IRQ
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (8 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 09/14] xen/arm: Allow virq != irq Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 11/14] xen/arm: gic: Add sanity checks gic_route_irq_to_guest Julien Grall
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

From: Julien Grall <julien.grall@linaro.org>

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 than 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---
    Changes in v5:
        - Typoe in the commit message
        - Add Ian and Stefano's ack

    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] 16+ messages in thread

* [PATCH v5 p1 11/14] xen/arm: gic: Add sanity checks gic_route_irq_to_guest
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (9 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 10/14] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 12/14] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel
  Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Stefano Stabellini

From: Julien Grall <julien.grall@linaro.org>

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>

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

    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] 16+ messages in thread

* [PATCH v5 p1 12/14] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (10 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 11/14] xen/arm: gic: Add sanity checks gic_route_irq_to_guest Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 13/14] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber Julien Grall
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

From: Julien Grall <julien.grall@linaro.org>

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@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

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

    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] 16+ messages in thread

* [PATCH v5 p1 13/14] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (11 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 12/14] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-01 16:21 ` [PATCH v5 p1 14/14] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts Julien Grall
  2015-04-02 10:13 ` [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Ian Campbell
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell

From: Julien Grall <julien.grall@linaro.org>

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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

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

    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 81fbb26..45a46c3 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] 16+ messages in thread

* [PATCH v5 p1 14/14] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (12 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 13/14] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber Julien Grall
@ 2015-04-01 16:21 ` Julien Grall
  2015-04-02 10:13 ` [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Ian Campbell
  14 siblings, 0 replies; 16+ messages in thread
From: Julien Grall @ 2015-04-01 16:21 UTC (permalink / raw)
  To: xen-devel
  Cc: Zoltan Kiss, ian.campbell, Julien Grall, tim, Frediano Ziglio,
	stefano.stabellini

From: Julien Grall <julien.grall@linaro.org>

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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
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 v5:
        - Add Ian's ack

    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] 16+ messages in thread

* Re: [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough
  2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
                   ` (13 preceding siblings ...)
  2015-04-01 16:21 ` [PATCH v5 p1 14/14] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts Julien Grall
@ 2015-04-02 10:13 ` Ian Campbell
  14 siblings, 0 replies; 16+ messages in thread
From: Ian Campbell @ 2015-04-02 10:13 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini

On Wed, 2015-04-01 at 17:21 +0100, Julien Grall wrote:
> Hello all,
> 
> This is the first part of the non-PCI passthrough series. It contains all
> patches acked than can go now in Xen upstream.

I applied the shovel to this whole series...

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

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

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-01 16:21 [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 01/14] xen/arm: Divide GIC initialization in 2 parts Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 02/14] xen/dts: Allow only IRQ translation that are mapped to main GIC Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 03/14] xen/dts: Use unsigned int for MMIO and IRQ index Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 04/14] xen/arm: vgic: Introduce a function to initialize pending_irq Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 05/14] xen/arm: Map disabled device in DOM0 Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 06/14] xen/arm: Introduce xen, passthrough property Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 07/14] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE" Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 08/14] xen: Extend DOMCTL createdomain to support arch configuration Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 09/14] xen/arm: Allow virq != irq Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 10/14] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 11/14] xen/arm: gic: Add sanity checks gic_route_irq_to_guest Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 12/14] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 13/14] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber Julien Grall
2015-04-01 16:21 ` [PATCH v5 p1 14/14] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts Julien Grall
2015-04-02 10:13 ` [PATCH v5 p1 00/14] xen/arm: Add support for non-PCI passthrough Ian Campbell

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.