diff options
-rw-r--r-- | xen/common/Makefile | 1 | ||||
-rw-r--r-- | xen/common/random.c | 29 | ||||
-rw-r--r-- | xen/include/asm-arm/percpu.h | 11 | ||||
-rw-r--r-- | xen/include/asm-arm/random.h | 9 | ||||
-rw-r--r-- | xen/include/asm-x86/random.h | 16 | ||||
-rw-r--r-- | xen/include/xen/cpumask.h | 19 | ||||
-rw-r--r-- | xen/include/xen/random.h | 6 |
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(¤t_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__ */ |