Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: Claudio Imbrenda <imbrenda@linux.ibm.com>
To: Maxim Levitsky <mlevitsk@redhat.com>
Cc: kvm@vger.kernel.org, "Andrew Jones" <drjones@redhat.com>,
	"Alexandru Elisei" <alexandru.elisei@arm.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Thomas Huth" <thuth@redhat.com>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Nico Boehr" <nrb@linux.ibm.com>,
	"Cathy Avery" <cavery@redhat.com>,
	"Janosch Frank" <frankja@linux.ibm.com>
Subject: Re: [kvm-unit-tests PATCH v3 11/27] lib: Add random number generator
Date: Wed, 14 Dec 2022 11:33:54 +0100	[thread overview]
Message-ID: <20221214113354.46a6a505@p-imbrenda> (raw)
In-Reply-To: <f27f5791caaf01d379027c6802fdeb953bd59c22.camel@redhat.com>

On Tue, 06 Dec 2022 16:07:39 +0200
Maxim Levitsky <mlevitsk@redhat.com> wrote:

> On Wed, 2022-11-23 at 10:28 +0100, Claudio Imbrenda wrote:
> > On Tue, 22 Nov 2022 18:11:36 +0200
> > Maxim Levitsky <mlevitsk@redhat.com> wrote:
> >   
> > > Add a simple pseudo random number generator which can be used
> > > in the tests to add randomeness in a controlled manner.  
> > 
> > ahh, yes I have wanted something like this in the library for quite some
> > time! thanks!
> > 
> > I have some comments regarding the interfaces (see below), and also a
> > request, if you could split the x86 part in a different patch, so we
> > can have a "pure" lib patch, and then you can have an x86-only patch
> > that uses the new interface
> >   
> > > For x86 add a wrapper which initializes the PRNG with RDRAND,
> > > unless RANDOM_SEED env variable is set, in which case it is used
> > > instead.
> > > 
> > > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
> > > ---
> > >  Makefile              |  3 ++-
> > >  README.md             |  1 +
> > >  lib/prng.c            | 41 +++++++++++++++++++++++++++++++++++++++++
> > >  lib/prng.h            | 23 +++++++++++++++++++++++
> > >  lib/x86/random.c      | 33 +++++++++++++++++++++++++++++++++
> > >  lib/x86/random.h      | 17 +++++++++++++++++
> > >  scripts/arch-run.bash |  2 +-
> > >  x86/Makefile.common   |  1 +
> > >  8 files changed, 119 insertions(+), 2 deletions(-)
> > >  create mode 100644 lib/prng.c
> > >  create mode 100644 lib/prng.h
> > >  create mode 100644 lib/x86/random.c
> > >  create mode 100644 lib/x86/random.h
> > > 
> > > diff --git a/Makefile b/Makefile
> > > index 6ed5deac..384b5acf 100644
> > > --- a/Makefile
> > > +++ b/Makefile
> > > @@ -29,7 +29,8 @@ cflatobjs := \
> > >  	lib/string.o \
> > >  	lib/abort.o \
> > >  	lib/report.o \
> > > -	lib/stack.o
> > > +	lib/stack.o \
> > > +	lib/prng.o
> > >  
> > >  # libfdt paths
> > >  LIBFDT_objdir = lib/libfdt
> > > diff --git a/README.md b/README.md
> > > index 6e82dc22..5a677a03 100644
> > > --- a/README.md
> > > +++ b/README.md
> > > @@ -91,6 +91,7 @@ the framework.  The list of reserved environment variables is below
> > >      QEMU_ACCEL                   either kvm, hvf or tcg
> > >      QEMU_VERSION_STRING          string of the form `qemu -h | head -1`
> > >      KERNEL_VERSION_STRING        string of the form `uname -r`
> > > +    TEST_SEED                    integer to force a fixed seed for the prng
> > >  
> > >  Additionally these self-explanatory variables are reserved
> > >  
> > > diff --git a/lib/prng.c b/lib/prng.c
> > > new file mode 100644
> > > index 00000000..d9342eb3
> > > --- /dev/null
> > > +++ b/lib/prng.c
> > > @@ -0,0 +1,41 @@
> > > +
> > > +/*
> > > + * Random number generator that is usable from guest code. This is the
> > > + * Park-Miller LCG using standard constants.
> > > + */
> > > +
> > > +#include "libcflat.h"
> > > +#include "prng.h"
> > > +
> > > +struct random_state new_random_state(uint32_t seed)
> > > +{
> > > +	struct random_state s = {.seed = seed};
> > > +	return s;
> > > +}
> > > +
> > > +uint32_t random_u32(struct random_state *state)
> > > +{
> > > +	state->seed = (uint64_t)state->seed * 48271 % ((uint32_t)(1 << 31) - 1);  
> > 
> > why not:
> > 
> > state->seed = state->seed * 48271ULL % (BIT_ULL(31) - 1);
> > 
> > I think it's more readable  
> 
> I copied this code vertabium from a patch that was send to in-kernel selftests
> as Sean suggested me to do.

fair enough :)

> 
> I to be honest would have picked some more complex random generator like the
> Mersenne Twister or something like that, since performance is not an issue here,
> and this generator is I think geared toward beeing as fast as possible.

I think that the important thing is that the generator is random enough
to confuse the various branch predictors and prefetchers. If the code
is simple, it's even better, because it's easier to understand.

> 
> But againg I don't care much about this, any source of randomness is better
> that nothing.

exactly

> 
> >   
> > > +	return state->seed;
> > > +}
> > > +
> > > +
> > > +uint32_t random_range(struct random_state *state, uint32_t min, uint32_t max)
> > > +{
> > > +	uint32_t val = random_u32(state);
> > > +
> > > +	return val % (max - min + 1) + min;  
> > 
> > what happens if max == UINT_MAX and min = 0 ?
> > 
> > maybe:
> > 
> > if (max - min == UINT_MAX)
> > 	return val;  
> 
> Makes sense.
> >   
> > > +}
> > > +
> > > +/*
> > > + * Returns true randomly in 'percent_true' cases (e.g if percent_true = 70.0,
> > > + * it will return true in 70.0% of cases)
> > > + */
> > > +bool random_decision(struct random_state *state, float percent_true)  
> > 
> > I'm not a fan of floats in the lib...
> >   
> > > +{
> > > +	if (percent_true == 0)
> > > +		return 0;
> > > +	if (percent_true == 100)
> > > +		return 1;
> > > +	return random_range(state, 1, 10000) < (uint32_t)(percent_true * 100);  
> > 
> > ...especially when you are only using 2 decimal places anyway  
> 
> I was thinking the same about this, there are pros and cons,
> Using a fixed point integer is a bit less usable but overall I don't mind
> using it.

maybe you can add a wrapper macro?

#define RANDOM_DECISION_F(state, percent) \
	random_decision((state), 100 * (percent))

would be functionally equivalent (I think), but only generate fp code
when actually used. (feel free to chose a nicer name for it)

> 
> 
> 
> > 
> > can you rewrite it to take an unsigned int? 
> > e.g. if percent_true = 7123, it will return true in 71.23% of the cases
> > 
> > then you can rewrite the last line like this:
> > 
> > return random_range(state, 1, 10000) < percent_true;
> >   
> > > +}
> > > diff --git a/lib/prng.h b/lib/prng.h
> > > new file mode 100644
> > > index 00000000..61d3a48b
> > > --- /dev/null
> > > +++ b/lib/prng.h
> > > @@ -0,0 +1,23 @@
> > > +
> > > +#ifndef SRC_LIB_PRNG_H_
> > > +#define SRC_LIB_PRNG_H_
> > > +
> > > +struct random_state {
> > > +	uint32_t seed;
> > > +};
> > > +
> > > +struct random_state new_random_state(uint32_t seed);
> > > +uint32_t random_u32(struct random_state *state);
> > > +
> > > +/*
> > > + * return a random number from min to max (included)
> > > + */
> > > +uint32_t random_range(struct random_state *state, uint32_t min, uint32_t max);
> > > +
> > > +/*
> > > + * Returns true randomly in 'percent_true' cases (e.g if percent_true = 70.0,
> > > + * it will return true in 70.0% of cases)
> > > + */
> > > +bool random_decision(struct random_state *state, float percent_true);
> > > +
> > > +#endif /* SRC_LIB_PRNG_H_ */  
> > 
> > and then put the rest below in a new patch  
> 
> No problem. Note that x86 specific bits can be minimized
> but that requires plumbing in several things that you would
> take for granted, and in particular, env vars
> are x86 specific, and apic id is x86 specific.

I'm not sure I understand your point. The lib code above does not depend
on the arch code below, so you can split this into a non-arch patch, and
an arch patch that uses the non-arch patch. I think it's cleaner to not
mix common code and arch code.

> 
> When a random number generator is wired to a new arch,
> this can be fixed.
> 
> Best regards,
> 	Maxim Levitsky
> 
> >   
> > > diff --git a/lib/x86/random.c b/lib/x86/random.c
> > > new file mode 100644
> > > index 00000000..fcdd5fe8
> > > --- /dev/null
> > > +++ b/lib/x86/random.c
> > > @@ -0,0 +1,33 @@
> > > +
> > > +#include "libcflat.h"
> > > +#include "processor.h"
> > > +#include "prng.h"
> > > +#include "smp.h"
> > > +#include "asm/spinlock.h"
> > > +#include "random.h"
> > > +
> > > +static u32 test_seed;
> > > +static bool initialized;
> > > +
> > > +void init_prng(void)
> > > +{
> > > +	char *test_seed_str = getenv("TEST_SEED");
> > > +
> > > +	if (test_seed_str && strlen(test_seed_str))
> > > +		test_seed = atol(test_seed_str);
> > > +	else
> > > +#ifdef __x86_64__
> > > +		test_seed =  (u32)rdrand();
> > > +#else
> > > +		test_seed = (u32)(rdtsc() << 4);
> > > +#endif
> > > +	initialized = true;
> > > +
> > > +	printf("Test seed: %u\n", (unsigned int)test_seed);
> > > +}
> > > +
> > > +struct random_state get_prng(void)
> > > +{
> > > +	assert(initialized);
> > > +	return new_random_state(test_seed + this_cpu_read_smp_id());
> > > +}
> > > diff --git a/lib/x86/random.h b/lib/x86/random.h
> > > new file mode 100644
> > > index 00000000..795b450b
> > > --- /dev/null
> > > +++ b/lib/x86/random.h
> > > @@ -0,0 +1,17 @@
> > > +/*
> > > + * prng.h
> > > + *
> > > + *  Created on: Nov 9, 2022
> > > + *      Author: mlevitsk
> > > + */
> > > +
> > > +#ifndef SRC_LIB_X86_RANDOM_H_
> > > +#define SRC_LIB_X86_RANDOM_H_
> > > +
> > > +#include "libcflat.h"
> > > +#include "prng.h"
> > > +
> > > +void init_prng(void);
> > > +struct random_state get_prng(void);
> > > +
> > > +#endif /* SRC_LIB_X86_RANDOM_H_ */
> > > diff --git a/scripts/arch-run.bash b/scripts/arch-run.bash
> > > index 51e4b97b..238d19f8 100644
> > > --- a/scripts/arch-run.bash
> > > +++ b/scripts/arch-run.bash
> > > @@ -298,7 +298,7 @@ env_params ()
> > >  	KERNEL_EXTRAVERSION=${KERNEL_EXTRAVERSION%%[!0-9]*}
> > >  	! [[ $KERNEL_SUBLEVEL =~ ^[0-9]+$ ]] && unset $KERNEL_SUBLEVEL
> > >  	! [[ $KERNEL_EXTRAVERSION =~ ^[0-9]+$ ]] && unset $KERNEL_EXTRAVERSION
> > > -	env_add_params KERNEL_VERSION_STRING KERNEL_VERSION KERNEL_PATCHLEVEL KERNEL_SUBLEVEL KERNEL_EXTRAVERSION
> > > +	env_add_params KERNEL_VERSION_STRING KERNEL_VERSION KERNEL_PATCHLEVEL KERNEL_SUBLEVEL KERNEL_EXTRAVERSION TEST_SEED
> > >  }
> > >  
> > >  env_file ()
> > > diff --git a/x86/Makefile.common b/x86/Makefile.common
> > > index 698a48ab..fa0a50e6 100644
> > > --- a/x86/Makefile.common
> > > +++ b/x86/Makefile.common
> > > @@ -23,6 +23,7 @@ cflatobjs += lib/x86/stack.o
> > >  cflatobjs += lib/x86/fault_test.o
> > >  cflatobjs += lib/x86/delay.o
> > >  cflatobjs += lib/x86/pmu.o
> > > +cflatobjs += lib/x86/random.o
> > >  ifeq ($(CONFIG_EFI),y)
> > >  cflatobjs += lib/x86/amd_sev.o
> > >  cflatobjs += lib/efi.o  
> 
> 


  reply	other threads:[~2022-12-14 10:34 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-22 16:11 [kvm-unit-tests PATCH v3 00/27] kvm-unit-tests: set of fixes and new tests Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 01/27] x86: replace irq_{enable|disable}() with sti()/cli() Maxim Levitsky
2022-12-01 13:46   ` Emanuele Giuseppe Esposito
2022-12-06 13:55     ` Maxim Levitsky
2022-12-06 14:15       ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 02/27] x86: introduce sti_nop() and sti_nop_cli() Maxim Levitsky
2022-12-01 13:46   ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 03/27] x86: add few helper functions for apic local timer Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 04/27] svm: remove nop after stgi/clgi Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 05/27] svm: make svm_intr_intercept_mix_if/gif test a bit more robust Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 06/27] svm: use apic_start_timer/apic_stop_timer instead of open coding it Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 07/27] x86: Add test for #SMI during interrupt window Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 08/27] x86: Add a simple test for SYSENTER instruction Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 09/27] svm: add simple nested shutdown test Maxim Levitsky
2022-12-01 13:46   ` Emanuele Giuseppe Esposito
2022-12-06 13:56     ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 10/27] SVM: add two tests for exitintinto on exception Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 11/27] lib: Add random number generator Maxim Levitsky
2022-11-23  9:28   ` Claudio Imbrenda
2022-11-23 12:54     ` Andrew Jones
2022-12-06 13:57       ` Maxim Levitsky
2022-12-06 14:07     ` Maxim Levitsky
2022-12-14 10:33       ` Claudio Imbrenda [this message]
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 12/27] x86: add IPI stress test Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 13/27] svm: remove get_npt_pte extern Maxim Levitsky
2022-12-01 13:46   ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 14/27] svm: move svm spec definitions to lib/x86/svm.h Maxim Levitsky
2022-12-01 13:54   ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 15/27] svm: move some svm support functions into lib/x86/svm_lib.h Maxim Levitsky
2022-12-01 13:59   ` Emanuele Giuseppe Esposito
2022-12-06 14:10     ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 16/27] svm: move setup_svm() to svm_lib.c Maxim Levitsky
2022-12-01 16:14   ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 17/27] svm: correctly skip if NPT not supported Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 18/27] svm: move vmcb_ident to svm_lib.c Maxim Levitsky
2022-12-01 16:18   ` Emanuele Giuseppe Esposito
2022-12-06 14:11     ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 19/27] svm: rewerite vm entry macros Maxim Levitsky
2022-12-02 10:14   ` Emanuele Giuseppe Esposito
2022-12-06 13:56     ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 20/27] svm: move v2 tests run into test_run Maxim Levitsky
2022-12-02  9:53   ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 21/27] svm: cleanup the default_prepare Maxim Levitsky
2022-12-02  9:45   ` Emanuele Giuseppe Esposito
2022-12-06 13:56     ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 22/27] svm: introduce svm_vcpu Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 23/27] svm: introduce struct svm_test_context Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 24/27] svm: use svm_test_context in v2 tests Maxim Levitsky
2022-12-02 10:27   ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 25/27] svm: move nested vcpu to test context Maxim Levitsky
2022-12-02 10:22   ` Emanuele Giuseppe Esposito
2022-12-06 14:29     ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 26/27] svm: move test_guest_func " Maxim Levitsky
2022-12-02 10:28   ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 27/27] x86: ipi_stress: add optional SVM support Maxim Levitsky
2023-06-07 23:25 ` [kvm-unit-tests PATCH v3 00/27] kvm-unit-tests: set of fixes and new tests Sean Christopherson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221214113354.46a6a505@p-imbrenda \
    --to=imbrenda@linux.ibm.com \
    --cc=alex.bennee@linaro.org \
    --cc=alexandru.elisei@arm.com \
    --cc=cavery@redhat.com \
    --cc=drjones@redhat.com \
    --cc=frankja@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=mlevitsk@redhat.com \
    --cc=nrb@linux.ibm.com \
    --cc=pbonzini@redhat.com \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox