]> xenbits.xensource.com Git - people/dariof/xen.git/commitdiff
xen/arm: gic: Relax barrier when sending an SGI
authorJulien Grall <julien.grall@arm.com>
Tue, 23 Oct 2018 14:25:13 +0000 (15:25 +0100)
committerJulien Grall <julien.grall@arm.com>
Mon, 12 Nov 2018 12:18:53 +0000 (12:18 +0000)
When sending an SGI to another CPU, we require a barrier to ensure that
any pending stores to normal memory are made visible to the recipient
before the interrupt arrives.

For GICv2, rather than using dsb(sy) before writel_gicd, we can instead
use dsb(ishst), since we just need to ensure that any pending normal
writes are visible within the inner-shareable domain before we poke the
GIC.

With this observation, we can then further weaken the barrier to a
dmb(ishst), since other CPUs in the inner-shareable domain must observe
the write to the distributor before the SGI is generated.

A DMB instruction can be used to ensure the relative order of only
memory accesses before and after the barrier. Since writes to system
registers are not memory operations, barrier DMB is not sufficient for
observalibility of memory accesses that occur before ICC_SGI1R_EL1
(GICv3).

For GICv3, a DSB instruction ensures that no instructions that appear in
program order after the DSB instruction, can execute until the DSB
instruction has completed.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Andrii Anisov <andrii_anisov@epam.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
xen/arch/arm/gic-v2.c
xen/arch/arm/gic-v3.c
xen/arch/arm/gic.c

index e7eb01f30aa705d0616b4fb499d1a280c39d65c0..1a744c576fca8e70109fa234fd0d52b8544ff5b9 100644 (file)
@@ -455,6 +455,12 @@ static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
     unsigned int mask = 0;
     cpumask_t online_mask;
 
+    /*
+     * Ensure that stores to Normal memory are visible to the other CPUs
+     * before they observe us issuing the IPI.
+     */
+    dmb(ishst);
+
     switch ( irqmode )
     {
     case SGI_TARGET_OTHERS:
index 264a981bab5c2cf155bea0288dedbdf3167c778a..6fbc1067577b9269b3fbb3e12ff91f08874b93c2 100644 (file)
@@ -984,6 +984,12 @@ static void gicv3_send_sgi_list(enum gic_sgi sgi, const cpumask_t *cpumask)
 static void gicv3_send_sgi(enum gic_sgi sgi, enum gic_sgi_mode mode,
                            const cpumask_t *cpumask)
 {
+    /*
+     * Ensure that stores to Normal memory are visible to the other CPUs
+     * before issuing the IPI.
+     */
+    dsb(st);
+
     switch ( mode )
     {
     case SGI_TARGET_OTHERS:
index 37c3af7197d6de0fabd00a570d4ac5f33ff4332d..6cc7dec7067ca584f5d74d5c7b9f35a2a17cd69b 100644 (file)
@@ -296,12 +296,6 @@ void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi)
 {
     ASSERT(sgi < 16); /* There are only 16 SGIs */
 
-   /*
-    * Ensure that stores to Normal memory are visible to the other CPUs
-    * before issuing the IPI.
-    * Matches the read barrier in do_sgi.
-    */
-    dsb(sy);
     gic_hw_ops->send_SGI(sgi, SGI_TARGET_LIST, cpumask);
 }
 
@@ -314,12 +308,6 @@ void send_SGI_self(enum gic_sgi sgi)
 {
     ASSERT(sgi < 16); /* There are only 16 SGIs */
 
-   /*
-    * Ensure that stores to Normal memory are visible to the other CPUs
-    * before issuing the IPI.
-    * Matches the read barrier in do_sgi.
-    */
-    dsb(sy);
     gic_hw_ops->send_SGI(sgi, SGI_TARGET_SELF, NULL);
 }
 
@@ -327,12 +315,6 @@ void send_SGI_allbutself(enum gic_sgi sgi)
 {
    ASSERT(sgi < 16); /* There are only 16 SGIs */
 
-   /*
-    * Ensure that stores to Normal memory are visible to the other CPUs
-    * before issuing the IPI.
-    * Matches the read barrier in do_sgi.
-    */
-   dsb(sy);
    gic_hw_ops->send_SGI(sgi, SGI_TARGET_OTHERS, NULL);
 }