On PowerPC (and other big endian and/or RISC architectures) bit
offsets in a bitmap are actually represented by a bit-offset from an
element in an array rather than a bit-offset from the base memory
pointer, see xen/include/asm-powerpc/bitops.h for a complete
explanation.
This complicates the conversion of cpumask_t from/to xenctl_cpumap.
The following patch allows an architecture to declare that bitops are
"by long" rather than "by bit" and use an alternate scheme for
encoding.
Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
---
diff -r b04e24db308f xen/common/domctl.c
--- a/xen/common/domctl.c Sun Dec 17 12:40:10 2006 -0500
+++ b/xen/common/domctl.c Fri Dec 15 17:03:47 2006 -0500
@@ -30,14 +30,36 @@ void cpumask_to_xenctl_cpumap(
void cpumask_to_xenctl_cpumap(
struct xenctl_cpumap *xenctl_cpumap, cpumask_t *cpumask)
{
- unsigned int guest_bytes, copy_bytes, i;
+ unsigned int guest_bytes, copy_bytes, xen_bytes, i;
uint8_t zero = 0;
+ cpumask_t local;
if ( guest_handle_is_null(xenctl_cpumap->bitmap) )
return;
guest_bytes = (xenctl_cpumap->nr_cpus + 7) / 8;
- copy_bytes = min_t(unsigned int, guest_bytes, (NR_CPUS + 7) / 8);
+
+ xen_bytes = (NR_CPUS + 7) / 8;
+ if (bitmap_by_long) {
+ if (((guest_bytes * 8) % BITS_PER_LONG) != 0) {
+ printk("%s: Unable to translate bitmap\n", __func__);
+ return;
+ }
+
+ /* local copy */
+ memcpy(cpus_addr(local), cpus_addr(*cpumask), sizeof (local));
+
+ /* clear unused bits */
+ for (i = NR_CPUS; i < sizeof(local) * 8; i++) {
+ /* non-atomic version */
+ __clear_bit(i, cpus_addr(local));
+ }
+
+ xen_bytes = sizeof(local);
+ cpumask = &local;
+ }
+
+ copy_bytes = min_t(unsigned int, guest_bytes, xen_bytes);
copy_to_guest(xenctl_cpumap->bitmap,
(uint8_t *)cpus_addr(*cpumask),
@@ -50,10 +72,20 @@ void xenctl_cpumap_to_cpumask(
void xenctl_cpumap_to_cpumask(
cpumask_t *cpumask, struct xenctl_cpumap *xenctl_cpumap)
{
- unsigned int guest_bytes, copy_bytes;
+ unsigned int guest_bytes, copy_bytes, xen_bytes;
guest_bytes = (xenctl_cpumap->nr_cpus + 7) / 8;
- copy_bytes = min_t(unsigned int, guest_bytes, (NR_CPUS + 7) / 8);
+ xen_bytes = (NR_CPUS + 7) / 8;
+
+ if (bitmap_by_long) {
+ if (((guest_bytes * 8) % BITS_PER_LONG) != 0) {
+ printk("%s: Unable to translate bitmap\n", __func__);
+ return;
+ }
+ xen_bytes = sizeof(*cpumask);
+ }
+
+ copy_bytes = min_t(unsigned int, guest_bytes, xen_bytes);
cpus_clear(*cpumask);
diff -r b04e24db308f xen/include/asm-powerpc/bitops.h
--- a/xen/include/asm-powerpc/bitops.h Sun Dec 17 12:40:10 2006 -0500
+++ b/xen/include/asm-powerpc/bitops.h Fri Dec 15 16:24:26 2006 -0500
@@ -41,6 +41,9 @@
#define _PPC64_BITOPS_H
#include <asm/memory.h>
+
+/* The following indicates that bitops are implemented as described above */
+#define bitmap_by_long (1)
/*
* clear_bit doesn't imply a memory barrier
diff -r b04e24db308f xen/include/xen/bitops.h
--- a/xen/include/xen/bitops.h Sun Dec 17 12:40:10 2006 -0500
+++ b/xen/include/xen/bitops.h Fri Dec 15 16:22:32 2006 -0500
@@ -75,6 +75,10 @@ static __inline__ int generic_fls(int x)
* scope
*/
#include <asm/bitops.h>
+
+#ifndef bitmap_by_long
+#define bitmap_by_long (0)
+#endif
static inline int generic_fls64(__u64 x)
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|