* for the best explanations of this ordering.
*/
-/*
- * If a bitmap has a number of bits which is not a multiple of 8 then
- * the last few bits of the last byte of the bitmap can be
- * unexpectedly set which can confuse consumers (e.g. in the tools)
- * who also round up their loops to 8 bits. Ensure we clear those left
- * over bits so as to prevent surprises.
- */
-static void clamp_last_byte(uint8_t *bp, unsigned int nbits)
-{
- unsigned int remainder = nbits % 8;
-
- if (remainder)
- bp[nbits/8] &= (1U << remainder) - 1;
-}
-
int __bitmap_empty(const unsigned long *bitmap, unsigned int bits)
{
int k, lim = bits/BITS_PER_LONG;
nbits -= 8;
}
}
- clamp_last_byte(bp, nbits);
}
static void bitmap_byte_to_long(unsigned long *lp, const uint8_t *bp,
#elif defined(__LITTLE_ENDIAN)
-static void bitmap_long_to_byte(uint8_t *bp, const unsigned long *lp,
- unsigned int nbits)
-{
- memcpy(bp, lp, DIV_ROUND_UP(nbits, BITS_PER_BYTE));
- clamp_last_byte(bp, nbits);
-}
+#define LITTLE_ENDIAN 1 /* For IS_ENABLED(). */
+
+/* Unused function, but a declaration is needed. */
+void bitmap_long_to_byte(uint8_t *bp, const unsigned long *lp,
+ unsigned int nbits);
static void bitmap_byte_to_long(unsigned long *lp, const uint8_t *bp,
unsigned int nbits)
uint8_t zero = 0;
int err = 0;
unsigned int xen_bytes = DIV_ROUND_UP(nbits, BITS_PER_BYTE);
- uint8_t *bytemap = xmalloc_array(uint8_t, xen_bytes);
+ const uint8_t *bytemap;
+ uint8_t last, *buf = NULL;
- if ( !bytemap )
- return -ENOMEM;
+ if ( !IS_ENABLED(LITTLE_ENDIAN) )
+ {
+ buf = xmalloc_array(uint8_t, xen_bytes);
+ if ( !buf )
+ return -ENOMEM;
+
+ bitmap_long_to_byte(buf, bitmap, nbits);
+
+ bytemap = buf;
+ }
+ else
+ bytemap = (const uint8_t *)bitmap;
guest_bytes = DIV_ROUND_UP(xenctl_bitmap->nr_bits, BITS_PER_BYTE);
copy_bytes = min(guest_bytes, xen_bytes);
- bitmap_long_to_byte(bytemap, bitmap, nbits);
+ if ( copy_bytes > 1 &&
+ copy_to_guest(xenctl_bitmap->bitmap, bytemap, copy_bytes - 1) )
+ err = -EFAULT;
+
+ /*
+ * If a bitmap has a number of bits which is not a multiple of 8 then the
+ * last few bits of the last byte of the bitmap can be unexpectedly set,
+ * which can confuse consumers (e.g. in the tools), who also may round up
+ * their loops to 8 bits. Ensure we clear those left over bits so as to
+ * prevent surprises.
+ */
+ last = bytemap[nbits / 8];
+ if ( nbits % 8 )
+ last &= (1U << (nbits % 8)) - 1;
+
+ xfree(buf);
if ( copy_bytes &&
- copy_to_guest(xenctl_bitmap->bitmap, bytemap, copy_bytes) )
+ copy_to_guest_offset(xenctl_bitmap->bitmap, copy_bytes - 1, &last, 1) )
err = -EFAULT;
- xfree(bytemap);
-
for ( i = copy_bytes; !err && i < guest_bytes; i++ )
if ( copy_to_guest_offset(xenctl_bitmap->bitmap, i, &zero, 1) )
err = -EFAULT;