|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 7/7] x86/nospec: Optimise array_index_mask_nospec() for power-of-2 arrays
When the compiler can determine that an array bound is a power of two, the
array index can be bounded even under speculation with a single and
instruction.
Respecify array_index_mask_nospec() to allow for masks other than ~0 and 0,
and introduce an IS_POWER_OF_2() helper.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Wei Liu <wl@xxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Juergen Gross <jgross@xxxxxxxx>
This optimisation is not safe on ARM, because some CPUs do data value
speculation, which is why the CSDB barrer was introduced.
---
xen/include/asm-x86/nospec.h | 25 +++++++++++++++++++------
xen/include/xen/config.h | 1 +
xen/include/xen/nospec.h | 3 ++-
3 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/xen/include/asm-x86/nospec.h b/xen/include/asm-x86/nospec.h
index 0039cd2713..4f36069eac 100644
--- a/xen/include/asm-x86/nospec.h
+++ b/xen/include/asm-x86/nospec.h
@@ -7,13 +7,20 @@
#include <asm/alternative.h>
/**
- * array_index_mask_nospec() - generate a mask that is ~0UL when the
- * bounds check succeeds and 0 otherwise
+ * array_index_mask_nospec() - generate a mask to bound an array index
+ * which is safe even under adverse speculation.
* @index: array element index
* @size: number of elements in array
*
- * Returns:
+ * In general, returns:
* 0 - (index < size)
+ *
+ * This yeild ~0UL in within-bounds case, and 0 in the out-of-bounds
+ * case.
+ *
+ * When the compiler can determine that the array is a power of two, a
+ * lower overhead option is to mask the index with a single and
+ * instruction.
*/
#define array_index_mask_nospec array_index_mask_nospec
static inline unsigned long array_index_mask_nospec(unsigned long index,
@@ -21,9 +28,15 @@ static inline unsigned long array_index_mask_nospec(unsigned
long index,
{
unsigned long mask;
- asm volatile ( "cmp %[size], %[index]; sbb %[mask], %[mask];"
- : [mask] "=r" (mask)
- : [size] "g" (size), [index] "r" (index) );
+ if ( __builtin_constant_p(size) && IS_POWER_OF_2(size) )
+ {
+ mask = size - 1;
+ OPTIMIZER_HIDE_VAR(mask);
+ }
+ else
+ asm volatile ( "cmp %[size], %[index]; sbb %[mask], %[mask];"
+ : [mask] "=r" (mask)
+ : [size] "g" (size), [index] "r" (index) );
return mask;
}
diff --git a/xen/include/xen/config.h b/xen/include/xen/config.h
index a106380a23..21c763617c 100644
--- a/xen/include/xen/config.h
+++ b/xen/include/xen/config.h
@@ -75,6 +75,7 @@
#define GB(_gb) (_AC(_gb, ULL) << 30)
#define IS_ALIGNED(val, align) (((val) & ((align) - 1)) == 0)
+#define IS_POWER_OF_2(val) ((val) && IS_ALIGNED(val, val))
#define __STR(...) #__VA_ARGS__
#define STR(...) __STR(__VA_ARGS__)
diff --git a/xen/include/xen/nospec.h b/xen/include/xen/nospec.h
index 7578210f16..cfc31f11b7 100644
--- a/xen/include/xen/nospec.h
+++ b/xen/include/xen/nospec.h
@@ -12,7 +12,8 @@
#include <asm/nospec.h>
/**
- * array_index_mask_nospec() - generate a ~0 mask when index < size, 0
otherwise
+ * array_index_mask_nospec() - generate a mask to bound an array index
+ * which is safe even under adverse speculation.
* @index: array element index
* @size: number of elements in array
*
--
2.11.0
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |