diff mbox

[RFC,v2,08/26] ARM: GICv3 ITS: map device and LPIs to the ITS on physdev_op hypercall

Message ID 20161222182446.18791-9-andre.przywara@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andre Przywara Dec. 22, 2016, 6:24 p.m. UTC
To get MSIs from devices forwarded to a CPU, we need to name the device
and its MSIs by mapping them to an ITS.
Since this involves queueing commands to the ITS command queue, we can't
really afford to do this during the guest's runtime, as this would open
up a denial-of-service attack vector.
So we require every device with MSI interrupts to be mapped explicitly by
Dom0. For Dom0 itself we can just use the existing PCI physdev_op
hypercalls, which the existing Linux kernel issues already.
So upon receipt of this hypercall we map the device to the hardware ITS
and prepare it to be later mapped by the virtual ITS by using the very
same device ID (for Dom0 only).
Also we ask for mapping 32 LPIs to cover 32 MSIs that the device may
use.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 xen/arch/arm/physdev.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

Comments

Stefano Stabellini Jan. 5, 2017, 9:23 p.m. UTC | #1
On Thu, 22 Dec 2016, Andre Przywara wrote:
> To get MSIs from devices forwarded to a CPU, we need to name the device
> and its MSIs by mapping them to an ITS.
> Since this involves queueing commands to the ITS command queue, we can't
> really afford to do this during the guest's runtime, as this would open
> up a denial-of-service attack vector.
> So we require every device with MSI interrupts to be mapped explicitly by
> Dom0. For Dom0 itself we can just use the existing PCI physdev_op
> hypercalls, which the existing Linux kernel issues already.
> So upon receipt of this hypercall we map the device to the hardware ITS
> and prepare it to be later mapped by the virtual ITS by using the very
> same device ID (for Dom0 only).
> Also we ask for mapping 32 LPIs to cover 32 MSIs that the device may
> use.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  xen/arch/arm/physdev.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/xen/arch/arm/physdev.c b/xen/arch/arm/physdev.c
> index 27bbbda..d9e6be3 100644
> --- a/xen/arch/arm/physdev.c
> +++ b/xen/arch/arm/physdev.c
> @@ -9,11 +9,35 @@
>  #include <xen/lib.h>
>  #include <xen/errno.h>
>  #include <xen/sched.h>
> +#include <xen/guest_access.h>
> +#include <asm/gic-its.h>
>  #include <asm/hypercall.h>
>  
>  
>  int do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
>  {
> +    struct physdev_manage_pci manage;
> +    struct domain *dom0;
> +    u32 devid;
> +    int ret;
> +
> +    switch (cmd)
> +    {
> +        case PHYSDEVOP_manage_pci_add:
> +        case PHYSDEVOP_manage_pci_remove:
> +            if ( copy_from_guest(&manage, arg, 1) != 0 )
> +                return -EFAULT;
> +
> +            dom0 = hardware_domain;

Please don't effectively name dom0 hardware_domain, just use
hardware_domain directly.


> +            devid = manage.bus << 8 | manage.devfn;
> +            /* Allocate an ITS device table with space for 32 MSIs */
> +            ret = gicv3_its_map_device(dom0, devid, devid, 5,
> +                                       cmd == PHYSDEVOP_manage_pci_add);

Why 32? Is it an arbitrary number? Shouldn't we figure out exactly the
number of events the device need?


> +            put_domain(dom0);

Where is the correspondent get_domain?


> +            return ret;
> +    }
> +
>      gdprintk(XENLOG_DEBUG, "PHYSDEVOP cmd=%d: not implemented\n", cmd);
>      return -ENOSYS;
>  }
> -- 
> 2.9.0
>
diff mbox

Patch

diff --git a/xen/arch/arm/physdev.c b/xen/arch/arm/physdev.c
index 27bbbda..d9e6be3 100644
--- a/xen/arch/arm/physdev.c
+++ b/xen/arch/arm/physdev.c
@@ -9,11 +9,35 @@ 
 #include <xen/lib.h>
 #include <xen/errno.h>
 #include <xen/sched.h>
+#include <xen/guest_access.h>
+#include <asm/gic-its.h>
 #include <asm/hypercall.h>
 
 
 int do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 {
+    struct physdev_manage_pci manage;
+    struct domain *dom0;
+    u32 devid;
+    int ret;
+
+    switch (cmd)
+    {
+        case PHYSDEVOP_manage_pci_add:
+        case PHYSDEVOP_manage_pci_remove:
+            if ( copy_from_guest(&manage, arg, 1) != 0 )
+                return -EFAULT;
+
+            dom0 = hardware_domain;
+            devid = manage.bus << 8 | manage.devfn;
+            /* Allocate an ITS device table with space for 32 MSIs */
+            ret = gicv3_its_map_device(dom0, devid, devid, 5,
+                                       cmd == PHYSDEVOP_manage_pci_add);
+
+            put_domain(dom0);
+            return ret;
+    }
+
     gdprintk(XENLOG_DEBUG, "PHYSDEVOP cmd=%d: not implemented\n", cmd);
     return -ENOSYS;
 }