aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/common/Makefile1
-rw-r--r--xen/common/random.c29
-rw-r--r--xen/include/asm-arm/percpu.h11
-rw-r--r--xen/include/asm-arm/random.h9
-rw-r--r--xen/include/asm-x86/random.h16
-rw-r--r--xen/include/xen/cpumask.h19
-rw-r--r--xen/include/xen/random.h6
7 files changed, 90 insertions, 1 deletions
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 0dc20506cc..5486140888 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -17,6 +17,7 @@ obj-y += multicall.o
obj-y += notifier.o
obj-y += page_alloc.o
obj-y += preempt.o
+obj-y += random.o
obj-y += rangeset.o
obj-y += sched_credit.o
obj-y += sched_credit2.o
diff --git a/xen/common/random.c b/xen/common/random.c
new file mode 100644
index 0000000000..4a28a24b4c
--- /dev/null
+++ b/xen/common/random.c
@@ -0,0 +1,29 @@
+#include <xen/percpu.h>
+#include <xen/random.h>
+#include <xen/time.h>
+#include <asm/random.h>
+
+static DEFINE_PER_CPU(unsigned int, seed);
+
+unsigned int get_random(void)
+{
+ unsigned int next = this_cpu(seed), val = arch_get_random();
+
+ if ( unlikely(!next) )
+ next = val ?: NOW();
+
+ if ( !val )
+ {
+ unsigned int i;
+
+ for ( i = 0; i < sizeof(val) * 8; i += 11 )
+ {
+ next = next * 1103515245 + 12345;
+ val |= ((next >> 16) & 0x7ff) << i;
+ }
+ }
+
+ this_cpu(seed) = next;
+
+ return val;
+}
diff --git a/xen/include/asm-arm/percpu.h b/xen/include/asm-arm/percpu.h
index a0c38cebf4..71e7649f7d 100644
--- a/xen/include/asm-arm/percpu.h
+++ b/xen/include/asm-arm/percpu.h
@@ -2,6 +2,17 @@
#define __ARM_PERCPU_H__
#ifndef __ASSEMBLY__
+
+#include <xen/types.h>
+#include <asm/cpregs.h>
+#if defined(CONFIG_ARM_32)
+# include <asm/arm32/processor.h>
+#elif defined(CONFIG_ARM_64)
+# include <asm/arm64/processor.h>
+#else
+# error "unknown ARM variant"
+#endif
+
extern char __per_cpu_start[], __per_cpu_data_end[];
extern unsigned long __per_cpu_offset[NR_CPUS];
void percpu_init_areas(void);
diff --git a/xen/include/asm-arm/random.h b/xen/include/asm-arm/random.h
new file mode 100644
index 0000000000..b4acee276b
--- /dev/null
+++ b/xen/include/asm-arm/random.h
@@ -0,0 +1,9 @@
+#ifndef __ASM_RANDOM_H__
+#define __ASM_RANDOM_H__
+
+static inline unsigned int arch_get_random(void)
+{
+ return 0;
+}
+
+#endif /* __ASM_RANDOM_H__ */
diff --git a/xen/include/asm-x86/random.h b/xen/include/asm-x86/random.h
new file mode 100644
index 0000000000..6198e72a7b
--- /dev/null
+++ b/xen/include/asm-x86/random.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_RANDOM_H__
+#define __ASM_RANDOM_H__
+
+#include <asm/processor.h>
+
+static inline unsigned int arch_get_random(void)
+{
+ unsigned int val = 0;
+
+ if ( cpu_has(&current_cpu_data, X86_FEATURE_RDRAND) )
+ asm ( ".byte 0x0f,0xc7,0xf0" : "+a" (val) );
+
+ return val;
+}
+
+#endif /* __ASM_RANDOM_H__ */
diff --git a/xen/include/xen/cpumask.h b/xen/include/xen/cpumask.h
index f931cf2618..850b4a22d7 100644
--- a/xen/include/xen/cpumask.h
+++ b/xen/include/xen/cpumask.h
@@ -77,6 +77,7 @@
#include <xen/bitmap.h>
#include <xen/kernel.h>
+#include <xen/random.h>
typedef struct cpumask{ DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
@@ -245,7 +246,23 @@ static inline int cpumask_cycle(int n, const cpumask_t *srcp)
return nxt;
}
-#define cpumask_any(srcp) cpumask_first(srcp)
+static inline unsigned int cpumask_any(const cpumask_t *srcp)
+{
+ unsigned int cpu = cpumask_first(srcp);
+ unsigned int w = cpumask_weight(srcp);
+
+ if ( w > 1 && cpu < nr_cpu_ids )
+ for ( w = get_random() % w; w--; )
+ {
+ unsigned int next = cpumask_next(cpu, srcp);
+
+ if ( next >= nr_cpu_ids )
+ break;
+ cpu = next;
+ }
+
+ return cpu;
+}
/*
* Special-case data structure for "single bit set only" constant CPU masks.
diff --git a/xen/include/xen/random.h b/xen/include/xen/random.h
new file mode 100644
index 0000000000..7c43d87f59
--- /dev/null
+++ b/xen/include/xen/random.h
@@ -0,0 +1,6 @@
+#ifndef __XEN_RANDOM_H__
+#define __XEN_RANDOM_H__
+
+unsigned int get_random(void);
+
+#endif /* __XEN_RANDOM_H__ */