[PATCH] selftests/mm: Confirm VA exhaustion without reliance on correctness of mmap()

2024-03-21 Thread Dev Jain
Currently, VA exhaustion is being checked by passing a hint to mmap() and
expecting it to fail. This patch makes a stricter test by successful write()
calls from /proc/self/maps to a dump file, confirming that a free chunk is
indeed not available.

Signed-off-by: Dev Jain 
---
Merge dependency: 
https://lore.kernel.org/all/20240314122250.68534-1-dev.j...@arm.com/

 .../selftests/mm/virtual_address_range.c  | 69 +++
 1 file changed, 69 insertions(+)

diff --git a/tools/testing/selftests/mm/virtual_address_range.c 
b/tools/testing/selftests/mm/virtual_address_range.c
index 7bcf8d48256a..31063613dfd9 100644
--- a/tools/testing/selftests/mm/virtual_address_range.c
+++ b/tools/testing/selftests/mm/virtual_address_range.c
@@ -12,6 +12,8 @@
 #include 
 #include 
 #include 
+#include 
+
 #include "../kselftest.h"
 
 /*
@@ -93,6 +95,69 @@ static int validate_lower_address_hint(void)
return 1;
 }
 
+static int validate_complete_va_space(void)
+{
+   unsigned long start_addr, end_addr, prev_end_addr;
+   char line[400];
+   char prot[6];
+   FILE *file;
+   int fd;
+
+   fd = open("va_dump", O_CREAT | O_WRONLY, 0600);
+   unlink("va_dump");
+   if (fd < 0) {
+   ksft_test_result_skip("cannot create or open dump file\n");
+   ksft_finished();
+   }
+
+   file = fopen("/proc/self/maps", "r");
+   if (file == NULL)
+   ksft_exit_fail_msg("cannot open /proc/self/maps\n");
+
+   prev_end_addr = 0;
+   while (fgets(line, sizeof(line), file)) {
+   unsigned long hop;
+   int ret;
+
+   ret = sscanf(line, "%lx-%lx %s[rwxp-]",
+&start_addr, &end_addr, prot);
+   if (ret != 3)
+   ksft_exit_fail_msg("sscanf failed, cannot parse\n");
+
+   /* end of userspace mappings; ignore vsyscall mapping */
+   if (start_addr & (1UL << 63))
+   return 0;
+
+   /* /proc/self/maps must have gaps less than 1GB only */
+   if (start_addr - prev_end_addr >= SZ_1GB)
+   return 1;
+
+   prev_end_addr = end_addr;
+
+   if (prot[0] != 'r')
+   continue;
+
+   /*
+* Confirm whether MAP_CHUNK_SIZE chunk can be found or not.
+* If write succeeds, no need to check MAP_CHUNK_SIZE - 1
+* addresses after that. If the address was not held by this
+* process, write would fail with errno set to EFAULT.
+* Anyways, if write returns anything apart from 1, exit the
+* program since that would mean a bug in /proc/self/maps.
+*/
+   hop = 0;
+   while (start_addr + hop < end_addr) {
+   if (write(fd, (void *)(start_addr + hop), 1) != 1)
+   return 1;
+   else
+   lseek(fd, 0, SEEK_SET);
+
+   hop += MAP_CHUNK_SIZE;
+   }
+   }
+   return 0;
+}
+
 int main(int argc, char *argv[])
 {
char *ptr[NR_CHUNKS_LOW];
@@ -135,6 +200,10 @@ int main(int argc, char *argv[])
validate_addr(hptr[i], 1);
}
hchunks = i;
+   if (validate_complete_va_space()) {
+   ksft_test_result_fail("BUG in mmap() or /proc/self/maps\n");
+   ksft_finished();
+   }
 
for (i = 0; i < lchunks; i++)
munmap(ptr[i], MAP_CHUNK_SIZE);
-- 
2.34.1




Re: [PATCH 1/8] iommu: Introduce a replace API for device pasid

2024-03-21 Thread Yi Liu

On 2024/3/21 14:16, Yi Liu wrote:

On 2024/3/20 20:38, Jason Gunthorpe wrote:

On Tue, Mar 19, 2024 at 03:29:39PM +0800, Yi Liu wrote:

On 2024/3/19 00:52, Jason Gunthorpe wrote:

On Wed, Mar 13, 2024 at 04:11:41PM +0800, Yi Liu wrote:


yes. how about your opinion? @Jason. I noticed the set_dev_pasid callback
and pasid_array update is under the group->lock, so update it should be
fine to adjust the order to update pasid_array after set_dev_pasid 
returns.


Yes, it makes some sense

But, also I would like it very much if we just have the core pass in
the actual old domain as a an addition function argument.


ok, this works too. For normal attach, just pass in a NULL old domain.


I think we have some small mistakes in multi-device group error
unwinding for remove because the global xarray can't isn't actually
going to be correct in all scenarios.


do you mean the __iommu_remove_group_pasid() call in the below function?
Currently, it is called when __iommu_set_group_pasid() failed. However,
__iommu_set_group_pasid() may need to do remove itself when error happens,
so the helper can be more self-contained. Or you mean something else?


Yes..


int iommu_attach_device_pasid(struct iommu_domain *domain,
  struct device *dev, ioasid_t pasid)
{
/* Caller must be a probed driver on dev */
struct iommu_group *group = dev->iommu_group;
void *curr;
int ret;

if (!domain->ops->set_dev_pasid)
    return -EOPNOTSUPP;

if (!group)
    return -ENODEV;

if (!dev_has_iommu(dev) || dev_iommu_ops(dev) != domain->owner)
    return -EINVAL;

mutex_lock(&group->mutex);
curr = xa_cmpxchg(&group->pasid_array, pasid, NULL, domain, 
GFP_KERNEL);

if (curr) {
    ret = xa_err(curr) ? : -EBUSY;
    goto out_unlock;
}

ret = __iommu_set_group_pasid(domain, group, pasid);


So here we have the xa set to the new domain


aha, yes. The underlying driver won't be able to get the correct domain
in the remove_dev_pasid callback.


if (ret) {
    __iommu_remove_group_pasid(group, pasid);


And here we still have it set to the new domain even though some of
the devices within the group failed to attach. The logic needs to be
more like the main domain attach path where iterate and then undo only
what we did


yes, the correct way is to undo what have been done before the fail
device. However, I somehow remember that pasid capability is only
available when the group is singleton. So iterate all devices of the
devices just means one device in fact. If this is true, then the
current code is fine although a bit confusing.


And the whole thing is easier to reason about if an input argument
specifies the current attached domain instead of having the driver
read it from the xarray.


yep, will correct it as a fix patch.


Hi Jason,

It appears there are two solutions here.

First, only undo the devices that have set_dev_pasid successfully in
the __iommu_set_group_pasid(), so the problematic
__iommu_remove_group_pasid() call at line 3378 [1] would go away.
This also makes the helper more self-contained. Draft patch in [2]

Second, pass in the domain to remove_dev_pasid(). Draft patch in [3]

Either of the above two should be able to solve the mistake you mentioned.
BTW. They are orthogonal, so it's also possible to apply both of them.
Which one is your preference then?

[1] 
https://github.com/torvalds/linux/blob/b3603fcb79b1036acae10602bffc4855a4b9af80/drivers/iommu/iommu.c#L3378
[2] 
https://github.com/yiliu1765/iommufd/commit/bb83270767ab460978a3452750f5e032b43e59bf
[3] 
https://github.com/yiliu1765/iommufd/commit/bd270b7b6619b8ba35dfaf9870df8728e370163f


Regards,
Yi Liu




Re: [PATCH 1/8] iommu: Introduce a replace API for device pasid

2024-03-21 Thread Jason Gunthorpe
On Thu, Mar 21, 2024 at 07:26:41PM +0800, Yi Liu wrote:
> > yes, the correct way is to undo what have been done before the fail
> > device. However, I somehow remember that pasid capability is only
> > available when the group is singleton. So iterate all devices of the
> > devices just means one device in fact. If this is true, then the
> > current code is fine although a bit confusing.

Platform devicse don't have that limitation.. It is PCI only.

> > > And the whole thing is easier to reason about if an input argument
> > > specifies the current attached domain instead of having the driver
> > > read it from the xarray.
> > 
> > yep, will correct it as a fix patch.
> 
> Hi Jason,
> 
> It appears there are two solutions here.
> 
> First, only undo the devices that have set_dev_pasid successfully in
> the __iommu_set_group_pasid(), so the problematic
> __iommu_remove_group_pasid() call at line 3378 [1] would go away.
> This also makes the helper more self-contained. Draft patch in [2]
> 
> Second, pass in the domain to remove_dev_pasid(). Draft patch in [3]
> 
> Either of the above two should be able to solve the mistake you mentioned.
> BTW. They are orthogonal, so it's also possible to apply both of them.
> Which one is your preference then?

I would do both because I also think it is not nice that the drivers
always have to have the boiler plate to read the xarray in their
remove..

Jason



Re: [PATCH 1/8] iommu: Introduce a replace API for device pasid

2024-03-21 Thread Yi Liu

On 2024/3/21 20:20, Jason Gunthorpe wrote:

On Thu, Mar 21, 2024 at 07:26:41PM +0800, Yi Liu wrote:

yes, the correct way is to undo what have been done before the fail
device. However, I somehow remember that pasid capability is only
available when the group is singleton. So iterate all devices of the
devices just means one device in fact. If this is true, then the
current code is fine although a bit confusing.


Platform devicse don't have that limitation.. It is PCI only.


ok.


And the whole thing is easier to reason about if an input argument
specifies the current attached domain instead of having the driver
read it from the xarray.


yep, will correct it as a fix patch.


Hi Jason,

It appears there are two solutions here.

First, only undo the devices that have set_dev_pasid successfully in
the __iommu_set_group_pasid(), so the problematic
__iommu_remove_group_pasid() call at line 3378 [1] would go away.
This also makes the helper more self-contained. Draft patch in [2]

Second, pass in the domain to remove_dev_pasid(). Draft patch in [3]

Either of the above two should be able to solve the mistake you mentioned.
BTW. They are orthogonal, so it's also possible to apply both of them.
Which one is your preference then?


I would do both because I also think it is not nice that the drivers
always have to have the boiler plate to read the xarray in their
remove..


sure. I'll send the two patches as Fix series.

--
Regards,
Yi Liu



Re: [PATCH] selftests: livepatch: Test atomic replace against multiple modules

2024-03-21 Thread Joe Lawrence
On 3/12/24 08:12, Marcos Paulo de Souza wrote:
> This new test checks if a livepatch with replace attribute set replaces
> all previously applied livepatches.
> 
> Signed-off-by: Marcos Paulo de Souza 
> ---
>  tools/testing/selftests/livepatch/Makefile |  3 +-
>  .../selftests/livepatch/test-atomic-replace.sh | 71 
> ++
>  2 files changed, 73 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/livepatch/Makefile 
> b/tools/testing/selftests/livepatch/Makefile
> index 35418a4790be..e92f61208d35 100644
> --- a/tools/testing/selftests/livepatch/Makefile
> +++ b/tools/testing/selftests/livepatch/Makefile
> @@ -10,7 +10,8 @@ TEST_PROGS := \
>   test-state.sh \
>   test-ftrace.sh \
>   test-sysfs.sh \
> - test-syscall.sh
> + test-syscall.sh \
> + test-atomic-replace.sh
>  
>  TEST_FILES := settings
>  
> diff --git a/tools/testing/selftests/livepatch/test-atomic-replace.sh 
> b/tools/testing/selftests/livepatch/test-atomic-replace.sh
> new file mode 100755
> index ..09a3dcdcb8de
> --- /dev/null
> +++ b/tools/testing/selftests/livepatch/test-atomic-replace.sh
> @@ -0,0 +1,71 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Copyright (C) 2024 SUSE
> +# Author: Marcos Paulo de Souza 
> +
> +. $(dirname $0)/functions.sh
> +
> +MOD_REPLACE=test_klp_atomic_replace
> +
> +setup_config
> +
> +# - Load three livepatch modules.
> +# - Load one more livepatch with replace being set, and check that only one
> +#   livepatch module is being listed.
> +
> +start_test "apply one liveptach to replace multiple livepatches"
> +
> +for mod in test_klp_livepatch test_klp_syscall test_klp_callbacks_demo; do
> + load_lp $mod
> +done
> +
> +nmods=$(ls /sys/kernel/livepatch | wc -l)
> +if [ $nmods -ne 3 ]; then
> + die "Expecting three modules listed, found $nmods"
> +fi
> +
> +load_lp $MOD_REPLACE replace=1
> +
> +nmods=$(ls /sys/kernel/livepatch | wc -l)
> +if [ $nmods -ne 1 ]; then
> + die "Expecting only one moduled listed, found $nmods"
> +fi
> +
> +disable_lp $MOD_REPLACE
> +unload_lp $MOD_REPLACE
> +
> +check_result "% insmod test_modules/test_klp_livepatch.ko
> +livepatch: enabling patch 'test_klp_livepatch'
> +livepatch: 'test_klp_livepatch': initializing patching transition
> +livepatch: 'test_klp_livepatch': starting patching transition
> +livepatch: 'test_klp_livepatch': completing patching transition
> +livepatch: 'test_klp_livepatch': patching complete
> +% insmod test_modules/test_klp_syscall.ko
> +livepatch: enabling patch 'test_klp_syscall'
> +livepatch: 'test_klp_syscall': initializing patching transition
> +livepatch: 'test_klp_syscall': starting patching transition
> +livepatch: 'test_klp_syscall': completing patching transition
> +livepatch: 'test_klp_syscall': patching complete
> +% insmod test_modules/test_klp_callbacks_demo.ko
> +livepatch: enabling patch 'test_klp_callbacks_demo'
> +livepatch: 'test_klp_callbacks_demo': initializing patching transition
> +test_klp_callbacks_demo: pre_patch_callback: vmlinux
> +livepatch: 'test_klp_callbacks_demo': starting patching transition
> +livepatch: 'test_klp_callbacks_demo': completing patching transition
> +test_klp_callbacks_demo: post_patch_callback: vmlinux
> +livepatch: 'test_klp_callbacks_demo': patching complete
> +% insmod test_modules/test_klp_atomic_replace.ko replace=1
> +livepatch: enabling patch 'test_klp_atomic_replace'
> +livepatch: 'test_klp_atomic_replace': initializing patching transition
> +livepatch: 'test_klp_atomic_replace': starting patching transition
> +livepatch: 'test_klp_atomic_replace': completing patching transition
> +livepatch: 'test_klp_atomic_replace': patching complete
> +% echo 0 > /sys/kernel/livepatch/test_klp_atomic_replace/enabled
> +livepatch: 'test_klp_atomic_replace': initializing unpatching transition
> +livepatch: 'test_klp_atomic_replace': starting unpatching transition
> +livepatch: 'test_klp_atomic_replace': completing unpatching transition
> +livepatch: 'test_klp_atomic_replace': unpatching complete
> +% rmmod test_klp_atomic_replace"
> +
> +exit 0
> 

Hi Marcos,

I'm not against adding a specific atomic replace test, but for a quick
tl/dr what is the difference between this new test and
test-livepatch.sh's "atomic replace livepatch" test?

If this one provides better coverage, should we follow up with removing
the existing one?

-- 
Joe




[PATCH] kunit: bail out early in __kunit_test_suites_init() if there are no suites to test

2024-03-21 Thread Scott Mayhew
Commit c72a870926c2 added a mutex to prevent kunit tests from running
concurrently.  Unfortunately that mutex gets locked during module load
regardless of whether the module actually has any kunit tests.  This
causes a problem for kunit tests that might need to load other kernel
modules (e.g. gss_krb5_test loading the camellia module).

So check to see if there are actually any tests to run before locking
the kunit_run_lock mutex.

Fixes: c72a870926c2 ("kunit: add ability to run tests after boot using debugfs")
Reported-by: Nico Pache 
Signed-off-by: Scott Mayhew 
---
 lib/kunit/test.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 1d1475578515..b8514dbb337c 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -712,6 +712,9 @@ int __kunit_test_suites_init(struct kunit_suite * const * 
const suites, int num_
 {
unsigned int i;
 
+   if (num_suites == 0)
+   return 0;
+
if (!kunit_enabled() && num_suites > 0) {
pr_info("kunit: disabled\n");
return 0;
-- 
2.43.0




Re: [PATCH bpf-next v4 3/6] bpf/helpers: introduce bpf_timer_set_sleepable_cb() kfunc

2024-03-21 Thread Benjamin Tissoires
On Mon, Mar 18, 2024 at 11:52 PM Eduard Zingerman  wrote:
>
> On Fri, 2024-03-15 at 15:29 +0100, Benjamin Tissoires wrote:
>
> This patch looks good to me, please see two nitpicks below.
> Acked-by: Eduard Zingerman 

Thanks!

>
> [...]
>
> > @@ -1350,6 +1358,11 @@ BPF_CALL_3(bpf_timer_start, struct bpf_timer_kern *, 
> > timer, u64, nsecs, u64, fla
> >   goto out;
> >   }
> >
> > + if (t->is_sleepable && !(flags & BPF_F_TIMER_SLEEPABLE)) {
> > + ret = -EINVAL;
> > + goto out;
> > + }
>
> Nit:
> the BPF_F_TIMER_ABS and BPF_F_TIMER_CPU_PIN don't affect
> sleepable timers, should this check be changed to:
> '(t->is_sleepable && flags != BPF_F_TIMER_SLEEPABLE)' ?

Sounds fair enough. Scheduled this for v5

>
> [...]
>
> > @@ -12151,6 +12175,16 @@ static int check_kfunc_call(struct 
> > bpf_verifier_env *env, struct bpf_insn *insn,
> >   }
> >   }
> >
> > + if (is_async_callback_calling_kfunc(meta.func_id)) {
> > + err = push_callback_call(env, insn, insn_idx, meta.subprogno,
> > +  set_timer_callback_state);
>
> Nit: still think that this fragment would be better as:
>
> if (is_bpf_timer_set_sleepable_cb_impl_kfunc(meta.func_id)) {
> err = push_callback_call(env, insn, insn_idx, meta.subprogno,
>  set_timer_callback_state);
>
> Because of the 'set_timer_callback_state' passed to push_callback_call().

Yeah, sorry I missed that part from the previous reviews.

Fixed in v5

Cheers,
Benjamin

>
> > + if (err) {
> > + verbose(env, "kfunc %s#%d failed callback 
> > verification\n",
> > + func_name, meta.func_id);
> > + return err;
> > + }
> > + }
> > +
> >   rcu_lock = is_kfunc_bpf_rcu_read_lock(&meta);
> >   rcu_unlock = is_kfunc_bpf_rcu_read_unlock(&meta);
> >
>




Re: [PATCH bpf-next v4 6/6] selftests/bpf: add sleepable timer tests

2024-03-21 Thread Benjamin Tissoires
On Tue, Mar 19, 2024 at 1:20 AM Eduard Zingerman  wrote:
>
> On Fri, 2024-03-15 at 15:29 +0100, Benjamin Tissoires wrote:
> > bpf_experimental.h and ../bpf_testmod/bpf_testmod_kfunc.h are both
> > including vmlinux.h, which is not compatible with including time.h
> > or bpf_tcp_helpers.h.
> >
> > So prevent vmlinux.h to be included, and override the few missing
> > types.
> >
> > Signed-off-by: Benjamin Tissoires 
>
> [...]
>
> > @@ -6,6 +6,14 @@
> >  #include 
> >  #include "bpf_tcp_helpers.h"
> >
> > +#define __VMLINUX_H__
> > +#define u32 __u32
> > +#define u64 __u64
> > +#include "bpf_experimental.h"
> > +struct prog_test_member1;
> > +#include "../bpf_testmod/bpf_testmod_kfunc.h"
> > +#undef __VMLINUX_H__
>
> Tbh, this looks very ugly.

heh :)

> Would it be possible to create a new tests file sleepable_timer.c
> and include bpf_experimental.h there, skipping time.h?

Sounds like an option, yeah :)

> It appears that for the new tests the only necessary definition from
> time.h is CLOCK_MONOTONIC.
>

Yeah, that #define should be the only one missing.

I'll try to come up with better tests in v5 :)

Cheers,
Benjamin




Re: [PATCH bpf-next v4 2/6] bpf/verifier: add bpf_timer as a kfunc capable type

2024-03-21 Thread Benjamin Tissoires
On Mon, Mar 18, 2024 at 10:59 PM Eduard Zingerman  wrote:
>
> On Fri, 2024-03-15 at 15:29 +0100, Benjamin Tissoires wrote:
> [...]
>
> > @@ -12021,6 +12034,12 @@ static int check_kfunc_args(struct 
> > bpf_verifier_env *env, struct bpf_kfunc_call_
> >   if (ret)
> >   return ret;
> >   break;
> > + case KF_ARG_PTR_TO_TIMER:
> > + if (reg->type != PTR_TO_MAP_VALUE) {
> > + verbose(env, "arg#%d doesn't point to a map 
> > value\n", i);
> > + return -EINVAL;
> > + }
> > + break;
>
> I think that pointer offset has to be checked as well,
> otherwise the following program verifies w/o error:

I initially thought it would be harder than it actually was.

Fixed (with the new test below) in v5.

Cheers,
Benjamin

>
> --- 8< 
>
> #include 
> #include 
> #include 
> #include 
> #include "bpf_tcp_helpers.h"
>
> extern int bpf_timer_set_sleepable_cb_impl(struct bpf_timer *timer,
> int (callback_fn)(void *map, int *key, struct bpf_timer 
> *timer), void *aux__ign) __ksym;
>
> #define bpf_timer_set_sleepable_cb(timer, cb) \
> bpf_timer_set_sleepable_cb_impl(timer, cb, NULL)
>
> struct elem {
> struct bpf_timer t;
> };
>
> struct {
> __uint(type, BPF_MAP_TYPE_ARRAY);
> __uint(max_entries, 2);
> __type(key, int);
> __type(value, struct elem);
> } array SEC(".maps");
>
> static int cb_sleepable(void *map, int *key, struct bpf_timer *timer)
> {
> return 0;
> }
>
> SEC("fentry/bpf_fentry_test5")
> int BPF_PROG2(test_sleepable, int, a)
> {
> struct bpf_timer *arr_timer;
> int array_key = 1;
>
> arr_timer = bpf_map_lookup_elem(&array, &array_key);
> if (!arr_timer)
> return 0;
> bpf_timer_init(arr_timer, &array, CLOCK_MONOTONIC);
> bpf_timer_set_sleepable_cb((void *)arr_timer + 1, // <-- note 
> incorrect offset
>cb_sleepable);
> bpf_timer_start(arr_timer, 0, 0);
> return 0;
> }
>
> char _license[] SEC("license") = "GPL";
>
>  >8 ---
>




Re: [PATCH bpf-next v4 4/6] bpf/helpers: mark the callback of bpf_timer_set_sleepable_cb() as sleepable

2024-03-21 Thread Benjamin Tissoires
On Tue, Mar 19, 2024 at 12:54 AM Eduard Zingerman  wrote:
>
> On Fri, 2024-03-15 at 15:29 +0100, Benjamin Tissoires wrote:
> [...]
>
> > @@ -5279,7 +5281,8 @@ static int map_kptr_match_type(struct 
> > bpf_verifier_env *env,
> >
> >  static bool in_sleepable(struct bpf_verifier_env *env)
> >  {
> > - return env->prog->sleepable;
> > + return env->prog->sleepable ||
> > +(env->cur_state && env->cur_state->in_sleepable);
> >  }
>
> I was curious why 'env->cur_state &&' check was needed and found that
> removing it caused an error in the following fragment:
>
> static int do_misc_fixups(struct bpf_verifier_env *env)
> {
> ...
> if (is_storage_get_function(insn->imm)) {
> if (!in_sleepable(env) ||
> env->insn_aux_data[i + 
> delta].storage_get_func_atomic)
> insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, 
> (__force __s32)GFP_ATOMIC);
> else
> insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, 
> (__force __s32)GFP_KERNEL);
> ...
> }
> ...
> }
>
> When do_misc_fixups() is done env->cur_state is NULL.
> Current implementation would use GFP_ATOMIC allocation even for
> sleepable callbacks, where GFP_KERNEL is sufficient.
> Is this is something we want to address?

I honestly have no idea of the impact there.

AFAICT, if env->cur_state is not set, we don't even know if the
callback will be sleepable or not, so if there is a small penalty,
then it's the safest option, no?

Cheers,
Benjamin

>
> >
> >  /* The non-sleepable programs and sleepable programs with explicit 
> > bpf_rcu_read_lock()
>




[PATCH v1] uffd-unit-tests: Fix ARM related issue with fork after pthread_create

2024-03-21 Thread Edward Liaw
Following issue was observed while running the uffd-unit-tests selftest
on ARM devices. On x86_64 no issues were detected:

pthread_create followed by fork caused deadlock in certain cases
wherein fork required some work to be completed by the created thread.
Used synchronization to ensure that created thread's start function has
started before invoking fork.

Signed-off-by: Lokesh Gidra 
[edliaw: Refactored to use atomic_bool]
Signed-off-by: Edward Liaw 
---
 tools/testing/selftests/mm/uffd-common.c |  4 +++-
 tools/testing/selftests/mm/uffd-common.h |  2 ++
 tools/testing/selftests/mm/uffd-unit-tests.c | 10 ++
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/mm/uffd-common.c 
b/tools/testing/selftests/mm/uffd-common.c
index b0ac0ec2356d..14ed98c3a389 100644
--- a/tools/testing/selftests/mm/uffd-common.c
+++ b/tools/testing/selftests/mm/uffd-common.c
@@ -17,7 +17,7 @@ bool map_shared;
 bool test_uffdio_wp = true;
 unsigned long long *count_verify;
 uffd_test_ops_t *uffd_test_ops;
-uffd_test_case_ops_t *uffd_test_case_ops;
+atomic_bool ready_for_fork;
 
 static int uffd_mem_fd_create(off_t mem_size, bool hugetlb)
 {
@@ -518,6 +518,8 @@ void *uffd_poll_thread(void *arg)
pollfd[1].fd = pipefd[cpu*2];
pollfd[1].events = POLLIN;
 
+   ready_for_fork = true;
+
for (;;) {
ret = poll(pollfd, 2, -1);
if (ret <= 0) {
diff --git a/tools/testing/selftests/mm/uffd-common.h 
b/tools/testing/selftests/mm/uffd-common.h
index cb055282c89c..cc5629c3d2aa 100644
--- a/tools/testing/selftests/mm/uffd-common.h
+++ b/tools/testing/selftests/mm/uffd-common.h
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "../kselftest.h"
 #include "vm_util.h"
@@ -103,6 +104,7 @@ extern bool map_shared;
 extern bool test_uffdio_wp;
 extern unsigned long long *count_verify;
 extern volatile bool test_uffdio_copy_eexist;
+extern atomic_bool ready_for_fork;
 
 extern uffd_test_ops_t anon_uffd_test_ops;
 extern uffd_test_ops_t shmem_uffd_test_ops;
diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c 
b/tools/testing/selftests/mm/uffd-unit-tests.c
index 2b9f8cc52639..4a48dc617c6b 100644
--- a/tools/testing/selftests/mm/uffd-unit-tests.c
+++ b/tools/testing/selftests/mm/uffd-unit-tests.c
@@ -775,6 +775,8 @@ static void uffd_sigbus_test_common(bool wp)
char c;
struct uffd_args args = { 0 };
 
+   ready_for_fork = false;
+
fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
 
if (uffd_register(uffd, area_dst, nr_pages * page_size,
@@ -790,6 +792,9 @@ static void uffd_sigbus_test_common(bool wp)
if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
err("uffd_poll_thread create");
 
+   while (!ready_for_fork)
+   ; /* Wait for the poll_thread to start executing before forking 
*/
+
pid = fork();
if (pid < 0)
err("fork");
@@ -829,6 +834,8 @@ static void uffd_events_test_common(bool wp)
char c;
struct uffd_args args = { 0 };
 
+   ready_for_fork = false;
+
fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
if (uffd_register(uffd, area_dst, nr_pages * page_size,
  true, wp, false))
@@ -838,6 +845,9 @@ static void uffd_events_test_common(bool wp)
if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
err("uffd_poll_thread create");
 
+   while (!ready_for_fork)
+   ; /* Wait for the poll_thread to start executing before forking 
*/
+
pid = fork();
if (pid < 0)
err("fork");
-- 
2.44.0.396.g6e790dbe36-goog




Re: [BUG] selftests/net: test_vxlan_mdb.sh: 84 out of 642 tests [FAIL]

2024-03-21 Thread Mirsad Todorovac




On 3/20/24 12:01, Ido Schimmel wrote:

On Wed, Mar 20, 2024 at 01:47:36AM +0100, Mirsad Todorovac wrote:

On 3/19/24 15:25, Ido Schimmel wrote:

Will look into it today or later this week.


Thank you for considering this.


Can you please try the following patch?

https://github.com/idosch/linux/commit/58f25dd8766dbe9ac50c76b44f9ba92350ebb5c6.patch


Congratulations, apparently, your patch had fixed them all:

# TEST: Torture test  [ OK ]
#
# Data path: MDB torture test - IPv6 overlay / IPv6 underlay
# --
# TEST: Torture test  [ OK ]
#
# Tests passed: 642
# Tests failed:   0
ok 90 selftests: net: test_vxlan_mdb.sh

Please consider adding:

Tested-by: Mirsad Todorovac 

at your convenience.

Shalom, and have a great evening!

Best regards,
Mirsad Todorovac



Re: [BUG] selftests/net: test_vxlan_mdb.sh: 84 out of 642 tests [FAIL]

2024-03-21 Thread Mirsad Todorovac




On 3/20/24 12:01, Ido Schimmel wrote:

On Wed, Mar 20, 2024 at 01:47:36AM +0100, Mirsad Todorovac wrote:

On 3/19/24 15:25, Ido Schimmel wrote:

Will look into it today or later this week.


Thank you for considering this.


Can you please try the following patch?

https://github.com/idosch/linux/commit/58f25dd8766dbe9ac50c76b44f9ba92350ebb5c6.patch


Congratulations, apparently, your patch had fixed them all:

# TEST: Torture test  [ OK ]
#
# Data path: MDB torture test - IPv6 overlay / IPv6 underlay
# --
# TEST: Torture test  [ OK ]
#
# Tests passed: 642
# Tests failed:   0
ok 90 selftests: net: test_vxlan_mdb.sh

Please consider adding:

Tested-by: Mirsad Todorovac 

at your convenience.

Shalom, and have a great evening!

Best regards,
Mirsad Todorovac



[PATCH v2] uffd-unit-tests: Fix ARM related issue with fork after pthread_create

2024-03-21 Thread Edward Liaw
Following issue was observed while running the uffd-unit-tests selftest
on ARM devices. On x86_64 no issues were detected:

pthread_create followed by fork caused deadlock in certain cases
wherein fork required some work to be completed by the created thread.
Used synchronization to ensure that created thread's start function has
started before invoking fork.

Signed-off-by: Lokesh Gidra 
[edliaw: Refactored to use atomic_bool]
Signed-off-by: Edward Liaw 
---
 tools/testing/selftests/mm/uffd-common.c |  3 +++
 tools/testing/selftests/mm/uffd-common.h |  2 ++
 tools/testing/selftests/mm/uffd-unit-tests.c | 10 ++
 3 files changed, 15 insertions(+)

diff --git a/tools/testing/selftests/mm/uffd-common.c 
b/tools/testing/selftests/mm/uffd-common.c
index b0ac0ec2356d..7ad6ba660c7d 100644
--- a/tools/testing/selftests/mm/uffd-common.c
+++ b/tools/testing/selftests/mm/uffd-common.c
@@ -18,6 +18,7 @@ bool test_uffdio_wp = true;
 unsigned long long *count_verify;
 uffd_test_ops_t *uffd_test_ops;
 uffd_test_case_ops_t *uffd_test_case_ops;
+atomic_bool ready_for_fork;
 
 static int uffd_mem_fd_create(off_t mem_size, bool hugetlb)
 {
@@ -518,6 +519,8 @@ void *uffd_poll_thread(void *arg)
pollfd[1].fd = pipefd[cpu*2];
pollfd[1].events = POLLIN;
 
+   ready_for_fork = true;
+
for (;;) {
ret = poll(pollfd, 2, -1);
if (ret <= 0) {
diff --git a/tools/testing/selftests/mm/uffd-common.h 
b/tools/testing/selftests/mm/uffd-common.h
index cb055282c89c..cc5629c3d2aa 100644
--- a/tools/testing/selftests/mm/uffd-common.h
+++ b/tools/testing/selftests/mm/uffd-common.h
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "../kselftest.h"
 #include "vm_util.h"
@@ -103,6 +104,7 @@ extern bool map_shared;
 extern bool test_uffdio_wp;
 extern unsigned long long *count_verify;
 extern volatile bool test_uffdio_copy_eexist;
+extern atomic_bool ready_for_fork;
 
 extern uffd_test_ops_t anon_uffd_test_ops;
 extern uffd_test_ops_t shmem_uffd_test_ops;
diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c 
b/tools/testing/selftests/mm/uffd-unit-tests.c
index 2b9f8cc52639..4a48dc617c6b 100644
--- a/tools/testing/selftests/mm/uffd-unit-tests.c
+++ b/tools/testing/selftests/mm/uffd-unit-tests.c
@@ -775,6 +775,8 @@ static void uffd_sigbus_test_common(bool wp)
char c;
struct uffd_args args = { 0 };
 
+   ready_for_fork = false;
+
fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
 
if (uffd_register(uffd, area_dst, nr_pages * page_size,
@@ -790,6 +792,9 @@ static void uffd_sigbus_test_common(bool wp)
if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
err("uffd_poll_thread create");
 
+   while (!ready_for_fork)
+   ; /* Wait for the poll_thread to start executing before forking 
*/
+
pid = fork();
if (pid < 0)
err("fork");
@@ -829,6 +834,8 @@ static void uffd_events_test_common(bool wp)
char c;
struct uffd_args args = { 0 };
 
+   ready_for_fork = false;
+
fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
if (uffd_register(uffd, area_dst, nr_pages * page_size,
  true, wp, false))
@@ -838,6 +845,9 @@ static void uffd_events_test_common(bool wp)
if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
err("uffd_poll_thread create");
 
+   while (!ready_for_fork)
+   ; /* Wait for the poll_thread to start executing before forking 
*/
+
pid = fork();
if (pid < 0)
err("fork");
-- 
2.44.0.396.g6e790dbe36-goog




Re: [PATCH] selftests/mm: Confirm VA exhaustion without reliance on correctness of mmap()

2024-03-21 Thread Andrew Morton
On Thu, 21 Mar 2024 16:05:22 +0530 Dev Jain  wrote:

> Currently, VA exhaustion is being checked by passing a hint to mmap() and
> expecting it to fail. This patch makes a stricter test by successful write()
> calls from /proc/self/maps to a dump file, confirming that a free chunk is
> indeed not available.

What's wrong with the current approach?



Re: [RFC PATCH v5 01/29] KVM: selftests: Add function to allow one-to-one GVA to GPA mappings

2024-03-21 Thread Zhang, Dongsheng X



On 12/12/2023 12:46 PM, Sagi Shahar wrote:
> From: Ackerley Tng 
> 
> One-to-one GVA to GPA mappings can be used in the guest to set up boot
> sequences during which paging is enabled, hence requiring a transition
> from using physical to virtual addresses in consecutive instructions.
> 
> Signed-off-by: Ackerley Tng 
> Signed-off-by: Ryan Afranji 
> Signed-off-by: Sagi Shahar 
> ---
>  .../selftests/kvm/include/kvm_util_base.h |  2 +
>  tools/testing/selftests/kvm/lib/kvm_util.c| 63 ---
>  2 files changed, 55 insertions(+), 10 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h 
> b/tools/testing/selftests/kvm/include/kvm_util_base.h
> index 1426e88ebdc7..c2e5c5f25dfc 100644
> --- a/tools/testing/selftests/kvm/include/kvm_util_base.h
> +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h
> @@ -564,6 +564,8 @@ vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, 
> vm_vaddr_t vaddr_min);
>  vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t 
> vaddr_min,
>   enum kvm_mem_region_type type);
>  vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t 
> vaddr_min);
> +vm_vaddr_t vm_vaddr_alloc_1to1(struct kvm_vm *vm, size_t sz,
> +vm_vaddr_t vaddr_min, uint32_t data_memslot);
>  vm_vaddr_t vm_vaddr_alloc_pages(struct kvm_vm *vm, int nr_pages);
>  vm_vaddr_t __vm_vaddr_alloc_page(struct kvm_vm *vm,
>enum kvm_mem_region_type type);
> diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c 
> b/tools/testing/selftests/kvm/lib/kvm_util.c
> index febc63d7a46b..4f1ae0f1eef0 100644
> --- a/tools/testing/selftests/kvm/lib/kvm_util.c
> +++ b/tools/testing/selftests/kvm/lib/kvm_util.c
> @@ -1388,17 +1388,37 @@ vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, 
> size_t sz,
>   return pgidx_start * vm->page_size;
>  }
>  
> +/*
> + * VM Virtual Address Allocate Shared/Encrypted
> + *
> + * Input Args:
> + *   vm - Virtual Machine
> + *   sz - Size in bytes
> + *   vaddr_min - Minimum starting virtual address
> + *   paddr_min - Minimum starting physical address
> + *   data_memslot - memslot number to allocate in
> + *   encrypt - Whether the region should be handled as encrypted
> + *
> + * Output Args: None
> + *
> + * Return:
> + *   Starting guest virtual address
> + *
> + * Allocates at least sz bytes within the virtual address space of the vm
> + * given by vm.  The allocated bytes are mapped to a virtual address >=
> + * the address given by vaddr_min.  Note that each allocation uses a
> + * a unique set of pages, with the minimum real allocation being at least
> + * a page.
> + */
>  static vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz,
> -  vm_vaddr_t vaddr_min,
> -  enum kvm_mem_region_type type,
> -  bool encrypt)
> +  vm_vaddr_t vaddr_min, vm_paddr_t paddr_min,
> +  uint32_t data_memslot, bool encrypt)
>  {
>   uint64_t pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0);
>  
>   virt_pgd_alloc(vm);
> - vm_paddr_t paddr = _vm_phy_pages_alloc(vm, pages,
> -   KVM_UTIL_MIN_PFN * vm->page_size,
> -   vm->memslots[type], encrypt);
> + vm_paddr_t paddr = _vm_phy_pages_alloc(vm, pages, paddr_min,
> +data_memslot, encrypt);
>  
>   /*
>* Find an unused range of virtual page addresses of at least
> @@ -1408,8 +1428,7 @@ static vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, 
> size_t sz,
>  
>   /* Map the virtual pages. */
>   for (vm_vaddr_t vaddr = vaddr_start; pages > 0;
> - pages--, vaddr += vm->page_size, paddr += vm->page_size) {
> -
> +  pages--, vaddr += vm->page_size, paddr += vm->page_size) {
>   virt_pg_map(vm, vaddr, paddr);
>  
>   sparsebit_set(vm->vpages_mapped, vaddr >> vm->page_shift);
> @@ -1421,12 +1440,16 @@ static vm_vaddr_t vm_vaddr_alloc(struct kvm_vm 
> *vm, size_t sz,
>  vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t 
> vaddr_min,
>   enum kvm_mem_region_type type)
>  {
> - return vm_vaddr_alloc(vm, sz, vaddr_min, type, vm->protected);
> + return vm_vaddr_alloc(vm, sz, vaddr_min,
> +   KVM_UTIL_MIN_PFN * vm->page_size,
> +   vm->memslots[type], vm->protected);
>  }
>  
>  vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t 
> vaddr_min)
>  {
> - return vm_vaddr_alloc(vm, sz, vaddr_min, MEM_REGION_TEST_DATA, 
> false);
> + return vm_vaddr_alloc(vm, sz, vaddr_min,
> +   KVM_UTIL_MIN_PFN * vm->page_size,
> +   vm->m

Re: [RFC PATCH v5 05/29] KVM: selftests: Add helper functions to create TDX VMs

2024-03-21 Thread Zhang, Dongsheng X



On 12/12/2023 12:46 PM, Sagi Shahar wrote:
> From: Erdem Aktas 
> 
> TDX requires additional IOCTLs to initialize VM and vCPUs to add
> private memory and to finalize the VM memory. Also additional utility
> functions are provided to manipulate a TD, similar to those that
> manipulate a VM in the current selftest framework.
> 
> A TD's initial register state cannot be manipulated directly by
> setting the VM's memory, hence boot code is provided at the TD's reset
> vector. This boot code takes boot parameters loaded in the TD's memory
> and sets up the TD for the selftest.
> 
> Signed-off-by: Erdem Aktas 
> Signed-off-by: Ryan Afranji 
> Signed-off-by: Sagi Shahar 
> Co-developed-by: Ackerley Tng 
> Signed-off-by: Ackerley Tng 
> ---
>  tools/testing/selftests/kvm/Makefile  |   2 +
>  .../kvm/include/x86_64/tdx/td_boot.h  |  82 
>  .../kvm/include/x86_64/tdx/td_boot_asm.h  |  16 +
>  .../kvm/include/x86_64/tdx/tdx_util.h |  16 +
>  .../selftests/kvm/lib/x86_64/tdx/td_boot.S| 101 
>  .../selftests/kvm/lib/x86_64/tdx/tdx_util.c   | 434 ++
>  6 files changed, 651 insertions(+)
>  create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/td_boot.h
>  create mode 100644 
> tools/testing/selftests/kvm/include/x86_64/tdx/td_boot_asm.h
>  create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h
>  create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/td_boot.S
>  create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c
> 
> diff --git a/tools/testing/selftests/kvm/Makefile 
> b/tools/testing/selftests/kvm/Makefile
> index b11ac221aba4..a35150ab855f 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -50,6 +50,8 @@ LIBKVM_x86_64 += lib/x86_64/svm.c
>  LIBKVM_x86_64 += lib/x86_64/ucall.c
>  LIBKVM_x86_64 += lib/x86_64/vmx.c
>  LIBKVM_x86_64 += lib/x86_64/sev.c
> +LIBKVM_x86_64 += lib/x86_64/tdx/tdx_util.c
> +LIBKVM_x86_64 += lib/x86_64/tdx/td_boot.S
>  
>  LIBKVM_aarch64 += lib/aarch64/gic.c
>  LIBKVM_aarch64 += lib/aarch64/gic_v3.c
> diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot.h 
> b/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot.h
> new file mode 100644
> index ..148057e569d6
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot.h
> @@ -0,0 +1,82 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +#ifndef SELFTEST_TDX_TD_BOOT_H
> +#define SELFTEST_TDX_TD_BOOT_H
> +
> +#include 
> +#include "tdx/td_boot_asm.h"
> +
> +/*
> + * Layout for boot section (not to scale)
> + *
> + *  GPA
> + * ┌─┬──0x1__ (4GB)
> + * │   Boot code trampoline  │
> + * ├─┼──0x0__fff0: Reset vector (16B below 
> 4GB)
> + * │   Boot code │
> + * ├─┼──td_boot will be copied here, so that the
> + * │ │  jmp to td_boot is exactly at the reset 
> vector
> + * │   Empty space   │
> + * │ │
> + * ├─┤
> + * │ │
> + * │ │
> + * │   Boot parameters   │
> + * │ │
> + * │ │
> + * └─┴──0x0__: TD_BOOT_PARAMETERS_GPA
> + */
> +#define FOUR_GIGABYTES_GPA (4ULL << 30)
> +
> +/**
> + * The exact memory layout for LGDT or LIDT instructions.
> + */
> +struct __packed td_boot_parameters_dtr {
> + uint16_t limit;
> + uint32_t base;
> +};
> +
> +/**
> + * The exact layout in memory required for a ljmp, including the selector for
> + * changing code segment.
> + */
> +struct __packed td_boot_parameters_ljmp_target {
> + uint32_t eip_gva;
> + uint16_t code64_sel;
> +};
> +
> +/**
> + * Allows each vCPU to be initialized with different eip and esp.
> + */
> +struct __packed td_per_vcpu_parameters {
> + uint32_t esp_gva;
> + struct td_boot_parameters_ljmp_target ljmp_target;
> +};
> +
> +/**
> + * Boot parameters for the TD.
> + *
> + * Unlike a regular VM, we can't ask KVM to set registers such as esp, eip, 
> etc
> + * before boot, so to run selftests, these registers' values have to be
> + * initialized by the TD.
> + *
> + * This struct is loaded in TD private memory at TD_BOOT_PARAMETERS_GPA.
> + *
> + * The TD boot code will read off parameters from this struct and set up the
> + * vcpu for executing selftests.
> + */
> +struct __packed td_boot_parameters {
> + uint32_t cr0;
> + uint32_t cr3;
> + uint32_t cr4;
> + struct td_boot_parameters_dtr gdtr;
> + struct td_boot_parameters_dtr idtr;
> + struct td_per_vcpu_parameters per_vcpu[];
> +};
> +
> +extern void td_boot(void);
> +extern void reset_vector(void);
> +extern void td_boot_code_end(void);
> +
> +#define TD_BOOT_CODE_SIZE (td_boot_code_end -

[PATCH v1] selftests/mm: sigbus-wp test requires UFFD_FEATURE_WP_HUGETLBFS_SHMEM

2024-03-21 Thread Edward Liaw
The sigbus-wp test requires the UFFD_FEATURE_WP_HUGETLBFS_SHMEM flag for
shmem and hugetlb targets.  Otherwise it is not backwards compatible
with kernels <5.19 and fails with EINVAL.

Signed-off-by: Edward Liaw 
---
 tools/testing/selftests/mm/uffd-unit-tests.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c 
b/tools/testing/selftests/mm/uffd-unit-tests.c
index 4a48dc617c6b..21ec23206ab4 100644
--- a/tools/testing/selftests/mm/uffd-unit-tests.c
+++ b/tools/testing/selftests/mm/uffd-unit-tests.c
@@ -1437,7 +1437,8 @@ uffd_test_case_t uffd_tests[] = {
.uffd_fn = uffd_sigbus_wp_test,
.mem_targets = MEM_ALL,
.uffd_feature_required = UFFD_FEATURE_SIGBUS |
-   UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP,
+   UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP |
+   UFFD_FEATURE_WP_HUGETLBFS_SHMEM,
},
{
.name = "events",
-- 
2.44.0.396.g6e790dbe36-goog




Re: [RFC PATCH v5 08/29] KVM: selftests: TDX: Add TDX lifecycle test

2024-03-21 Thread Zhang, Dongsheng X



On 12/12/2023 12:46 PM, Sagi Shahar wrote:
> From: Erdem Aktas 
> 
> Adding a test to verify TDX lifecycle by creating a TD and running a
> dummy TDG.VP.VMCALL  inside it.
> 
> Signed-off-by: Erdem Aktas 
> Signed-off-by: Ryan Afranji 
> Signed-off-by: Sagi Shahar 
> Co-developed-by: Ackerley Tng 
> Signed-off-by: Ackerley Tng 
> ---
>  tools/testing/selftests/kvm/Makefile  |  4 +
>  .../selftests/kvm/include/x86_64/tdx/tdcall.h | 35 
>  .../selftests/kvm/include/x86_64/tdx/tdx.h| 12 +++
>  .../kvm/include/x86_64/tdx/test_util.h| 52 +++
>  .../selftests/kvm/lib/x86_64/tdx/tdcall.S | 90 +++
>  .../selftests/kvm/lib/x86_64/tdx/tdx.c| 27 ++
>  .../selftests/kvm/lib/x86_64/tdx/tdx_util.c   |  1 +
>  .../selftests/kvm/lib/x86_64/tdx/test_util.c  | 34 +++
>  .../selftests/kvm/x86_64/tdx_vm_tests.c   | 45 ++
>  9 files changed, 300 insertions(+)
>  create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h
>  create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
>  create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h
>  create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S
>  create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
>  create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c
>  create mode 100644 tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
> 
> diff --git a/tools/testing/selftests/kvm/Makefile 
> b/tools/testing/selftests/kvm/Makefile
> index a35150ab855f..80d4a50eeb9f 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -52,6 +52,9 @@ LIBKVM_x86_64 += lib/x86_64/vmx.c
>  LIBKVM_x86_64 += lib/x86_64/sev.c
>  LIBKVM_x86_64 += lib/x86_64/tdx/tdx_util.c
>  LIBKVM_x86_64 += lib/x86_64/tdx/td_boot.S
> +LIBKVM_x86_64 += lib/x86_64/tdx/tdcall.S
> +LIBKVM_x86_64 += lib/x86_64/tdx/tdx.c
> +LIBKVM_x86_64 += lib/x86_64/tdx/test_util.c
>  
>  LIBKVM_aarch64 += lib/aarch64/gic.c
>  LIBKVM_aarch64 += lib/aarch64/gic_v3.c
> @@ -152,6 +155,7 @@ TEST_GEN_PROGS_x86_64 += set_memory_region_test
>  TEST_GEN_PROGS_x86_64 += steal_time
>  TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test
>  TEST_GEN_PROGS_x86_64 += system_counter_offset_test
> +TEST_GEN_PROGS_x86_64 += x86_64/tdx_vm_tests
>  
>  # Compiled outputs used by test targets
>  TEST_GEN_PROGS_EXTENDED_x86_64 += x86_64/nx_huge_pages_test
> diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h 
> b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h
> new file mode 100644
> index ..78001bfec9c8
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/* Adapted from arch/x86/include/asm/shared/tdx.h */
> +
> +#ifndef SELFTESTS_TDX_TDCALL_H
> +#define SELFTESTS_TDX_TDCALL_H
> +
> +#include 
> +#include 
> +
> +#define TDG_VP_VMCALL_INSTRUCTION_IO_READ 0
> +#define TDG_VP_VMCALL_INSTRUCTION_IO_WRITE 1

Nit:
Probably we can define the following instead in test_util.c?
/* Port I/O direction */
#define PORT_READ   0
#define PORT_WRITE  1

Then use them in place of 
TDG_VP_VMCALL_INSTRUCTION_IO_READ/TDG_VP_VMCALL_INSTRUCTION_IO_WRITE?
which are too long

> +
> +#define TDX_HCALL_HAS_OUTPUT BIT(0)
> +
> +#define TDX_HYPERCALL_STANDARD 0
> +
> +/*
> + * Used in __tdx_hypercall() to pass down and get back registers' values of
> + * the TDCALL instruction when requesting services from the VMM.
> + *
> + * This is a software only structure and not part of the TDX module/VMM ABI.
> + */
> +struct tdx_hypercall_args {
> + u64 r10;
> + u64 r11;
> + u64 r12;
> + u64 r13;
> + u64 r14;
> + u64 r15;
> +};
> +
> +/* Used to request services from the VMM */
> +u64 __tdx_hypercall(struct tdx_hypercall_args *args, unsigned long flags);
> +
> +#endif // SELFTESTS_TDX_TDCALL_H
> diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h 
> b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> new file mode 100644
> index ..a7161efe4ee2
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +#ifndef SELFTEST_TDX_TDX_H
> +#define SELFTEST_TDX_TDX_H
> +
> +#include 
> +
> +#define TDG_VP_VMCALL_INSTRUCTION_IO 30

Nit:
arch/x86/include/uapi/asm/vmx.h already exports the following define:
#define EXIT_REASON_IO_INSTRUCTION  30

Linux kernel example (arch/x86/coco/tdx/tdx.c):
static bool handle_in(struct pt_regs *regs, int size, int port)
{
struct tdx_module_args args = {
.r10 = TDX_HYPERCALL_STANDARD,
.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
.r12 = size,
.r13 = PORT_READ,
.r14 = port,
};

So just like the kernel, here we can also use EXIT_REASON_IO_INSTRUCTION in 
place of TDG_VP_VMCAL

Re: [PATCH] kunit: bail out early in __kunit_test_suites_init() if there are no suites to test

2024-03-21 Thread Rae Moar
On Thu, Mar 21, 2024 at 10:32 AM Scott Mayhew  wrote:
>
> Commit c72a870926c2 added a mutex to prevent kunit tests from running
> concurrently.  Unfortunately that mutex gets locked during module load
> regardless of whether the module actually has any kunit tests.  This
> causes a problem for kunit tests that might need to load other kernel
> modules (e.g. gss_krb5_test loading the camellia module).
>
> So check to see if there are actually any tests to run before locking
> the kunit_run_lock mutex.
>
> Fixes: c72a870926c2 ("kunit: add ability to run tests after boot using 
> debugfs")
> Reported-by: Nico Pache 
> Signed-off-by: Scott Mayhew 

Hi!

Sorry about this bug. Thanks for the patch! We should definitely add this check.

Reviewed-by: Rae Moar 

Thanks!

-Rae

> ---
>  lib/kunit/test.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/lib/kunit/test.c b/lib/kunit/test.c
> index 1d1475578515..b8514dbb337c 100644
> --- a/lib/kunit/test.c
> +++ b/lib/kunit/test.c
> @@ -712,6 +712,9 @@ int __kunit_test_suites_init(struct kunit_suite * const * 
> const suites, int num_
>  {
> unsigned int i;
>
> +   if (num_suites == 0)
> +   return 0;
> +
> if (!kunit_enabled() && num_suites > 0) {
> pr_info("kunit: disabled\n");
> return 0;
> --
> 2.43.0
>



Re: [PATCH v1] selftests/mm: sigbus-wp test requires UFFD_FEATURE_WP_HUGETLBFS_SHMEM

2024-03-21 Thread Andrew Morton
On Thu, 21 Mar 2024 23:20:21 + Edward Liaw  wrote:

> The sigbus-wp test requires the UFFD_FEATURE_WP_HUGETLBFS_SHMEM flag for
> shmem and hugetlb targets.  Otherwise it is not backwards compatible
> with kernels <5.19 and fails with EINVAL.
> 
> ...
>
> --- a/tools/testing/selftests/mm/uffd-unit-tests.c
> +++ b/tools/testing/selftests/mm/uffd-unit-tests.c
> @@ -1437,7 +1437,8 @@ uffd_test_case_t uffd_tests[] = {
>   .uffd_fn = uffd_sigbus_wp_test,
>   .mem_targets = MEM_ALL,
>   .uffd_feature_required = UFFD_FEATURE_SIGBUS |
> - UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP,
> + UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP |
> + UFFD_FEATURE_WP_HUGETLBFS_SHMEM,
>   },
>   {
>   .name = "events",

Thanks, I'll add

Fixes: 73c1ea939b65 ("selftests/mm: move uffd sig/events tests into uffd unit 
tests")
Cc: 



Re: [RFC PATCH v5 15/29] KVM: selftests: TDX: Add TDX MSR read/write tests

2024-03-21 Thread Zhang, Dongsheng X



On 12/12/2023 12:46 PM, Sagi Shahar wrote:
> The test verifies reads and writes for MSR registers with different access
> level.
> 
> Signed-off-by: Sagi Shahar 
> Signed-off-by: Ackerley Tng 
> Signed-off-by: Ryan Afranji 
> ---
>  .../selftests/kvm/include/x86_64/tdx/tdx.h|   5 +
>  .../selftests/kvm/lib/x86_64/tdx/tdx.c|  27 +++
>  .../selftests/kvm/x86_64/tdx_vm_tests.c   | 209 ++
>  3 files changed, 241 insertions(+)
> 
> diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h 
> b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> index 63788012bf94..85ba6aab79a7 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> @@ -9,11 +9,16 @@
>  #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003
>  
>  #define TDG_VP_VMCALL_INSTRUCTION_IO 30
> +#define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31
> +#define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32

Nit:
"arch/x86/include/uapi/asm/vmx.h" already defined the following defs:
#define EXIT_REASON_IO_INSTRUCTION  30
#define EXIT_REASON_MSR_READ31
#define EXIT_REASON_MSR_WRITE   32


> +
>  void handle_userspace_tdg_vp_vmcall_exit(struct kvm_vcpu *vcpu);
>  uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size,
> uint64_t write, uint64_t *data);
>  void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t 
> data_gpa);
>  uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12,
>   uint64_t *r13, uint64_t *r14);
> +uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t 
> *ret_value);
> +uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value);
>  
>  #endif // SELFTEST_TDX_TDX_H
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c 
> b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> index e5a9e13c62e2..88ea6f2a6469 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> @@ -87,3 +87,30 @@ uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, 
> uint64_t *r12,
>  
>   return ret;
>  }
> +
> +uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_value)
> +{
> + uint64_t ret;
> + struct tdx_hypercall_args args = {
> + .r11 = TDG_VP_VMCALL_INSTRUCTION_RDMSR,
> + .r12 = index,
> + };
> +
> + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT);
> +
> + if (ret_value)
> + *ret_value = args.r11;
> +
> + return ret;
> +}
> +
> +uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value)
> +{
> + struct tdx_hypercall_args args = {
> + .r11 = TDG_VP_VMCALL_INSTRUCTION_WRMSR,
> + .r12 = index,
> + .r13 = value,
> + };
> +
> + return __tdx_hypercall(&args, 0);
> +}
> diff --git a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c 
> b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
> index 699cba36e9ce..5db3701cc6d9 100644
> --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
> +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
> @@ -515,6 +515,213 @@ void verify_guest_reads(void)
>   printf("\t ... PASSED\n");
>  }
>  
> +/*
> + * Define a filter which denies all MSR access except the following:
> + * MSR_X2APIC_APIC_ICR: Allow read/write access (allowed by default)
> + * MSR_IA32_MISC_ENABLE: Allow read access
> + * MSR_IA32_POWER_CTL: Allow write access
> + */
> +#define MSR_X2APIC_APIC_ICR 0x830
> +static u64 tdx_msr_test_allow_bits = 0x;

Nit:
0x is error prone to define? the following?
static u64 tdx_msr_test_allow_bits = ~0ULL;


> +struct kvm_msr_filter tdx_msr_test_filter = {
> + .flags = KVM_MSR_FILTER_DEFAULT_DENY,
> + .ranges = {
> + {
> + .flags = KVM_MSR_FILTER_READ,
> + .nmsrs = 1,
> + .base = MSR_IA32_MISC_ENABLE,
> + .bitmap = (uint8_t *)&tdx_msr_test_allow_bits,
> + }, {
> + .flags = KVM_MSR_FILTER_WRITE,
> + .nmsrs = 1,
> + .base = MSR_IA32_POWER_CTL,
> + .bitmap = (uint8_t *)&tdx_msr_test_allow_bits,
> + },
> + },
> +};
> +
> +/*
> + * Verifies MSR read functionality.
> + */
> +void guest_msr_read(void)
> +{
> + uint64_t data;
> + uint64_t ret;
> +
> + ret = tdg_vp_vmcall_instruction_rdmsr(MSR_X2APIC_APIC_ICR, &data);
> + if (ret)
> + tdx_test_fatal(ret);
> +
> + ret = tdx_test_report_64bit_to_user_space(data);
> + if (ret)
> + tdx_test_fatal(ret);
> +
> + ret = tdg_vp_vmcall_instruction_rdmsr(MSR_IA32_MISC_ENABLE, &data);
> + if (ret)
> + tdx_test_fatal(ret);
> +
> + ret = tdx_test_report_64bit_to_user_space(data);
> + if (ret)
> + tdx_t

Re: [RFC PATCH v5 17/29] KVM: selftests: TDX: Add TDX MMIO reads test

2024-03-21 Thread Zhang, Dongsheng X



On 12/12/2023 12:46 PM, Sagi Shahar wrote:
> The test verifies MMIO reads of various sizes from the host to the guest.
> 
> Signed-off-by: Sagi Shahar 
> Signed-off-by: Ackerley Tng 
> Signed-off-by: Ryan Afranji 
> ---
>  .../selftests/kvm/include/x86_64/tdx/tdcall.h |  2 +
>  .../selftests/kvm/include/x86_64/tdx/tdx.h|  3 +
>  .../kvm/include/x86_64/tdx/test_util.h| 23 +
>  .../selftests/kvm/lib/x86_64/tdx/tdx.c| 19 
>  .../selftests/kvm/x86_64/tdx_vm_tests.c   | 87 +++
>  5 files changed, 134 insertions(+)
> 
> diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h 
> b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h
> index b5e94b7c48fa..95fcdbd8404e 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h
> @@ -9,6 +9,8 @@
>  
>  #define TDG_VP_VMCALL_INSTRUCTION_IO_READ 0
>  #define TDG_VP_VMCALL_INSTRUCTION_IO_WRITE 1
> +#define TDG_VP_VMCALL_VE_REQUEST_MMIO_READ 0
> +#define TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE 1
>  
>  #define TDG_VP_VMCALL_SUCCESS 0x
>  #define TDG_VP_VMCALL_INVALID_OPERAND 0x8000
> diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h 
> b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> index b18e39d20498..13ce60df5684 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> @@ -12,6 +12,7 @@
>  #define TDG_VP_VMCALL_INSTRUCTION_IO 30
>  #define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31
>  #define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32
> +#define TDG_VP_VMCALL_VE_REQUEST_MMIO 48
>  
>  void handle_userspace_tdg_vp_vmcall_exit(struct kvm_vcpu *vcpu);
>  uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size,
> @@ -22,5 +23,7 @@ uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, 
> uint64_t *r12,
>  uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t 
> *ret_value);
>  uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value);
>  uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag);
> +uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size,
> + uint64_t *data_out);
>  
>  #endif // SELFTEST_TDX_TDX_H
> diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h 
> b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h
> index 8a9b6a1bec3e..af412b764604 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h
> @@ -35,6 +35,29 @@
>   (VCPU)->run->io.direction); \
>   } while (0)
>  
> +
> +/**
> + * Assert that some MMIO operation involving TDG.VP.VMCALL <#VERequestMMIO> 
> was
> + * called in the guest.
> + */
> +#define TDX_TEST_ASSERT_MMIO(VCPU, ADDR, SIZE, DIR)  \
> + do {\
> + TEST_ASSERT((VCPU)->run->exit_reason == KVM_EXIT_MMIO,  \
> + "Got exit_reason other than KVM_EXIT_MMIO: %u (%s)\n", \
> + (VCPU)->run->exit_reason,   \
> + exit_reason_str((VCPU)->run->exit_reason)); \
> + \
> + TEST_ASSERT(((VCPU)->run->exit_reason == KVM_EXIT_MMIO) && \
> + ((VCPU)->run->mmio.phys_addr == (ADDR)) &&  \
> + ((VCPU)->run->mmio.len == (SIZE)) &&\
> + ((VCPU)->run->mmio.is_write == (DIR)),  \
> + "Got an unexpected MMIO exit values: %u (%s) %llu %d 
> %d\n", \
> + (VCPU)->run->exit_reason,   \
> + exit_reason_str((VCPU)->run->exit_reason),  \
> + (VCPU)->run->mmio.phys_addr, (VCPU)->run->mmio.len, \
> + (VCPU)->run->mmio.is_write);\
> + } while (0)
> +
>  /**
>   * Check and report if there was some failure in the guest, either an 
> exception
>   * like a triple fault, or if a tdx_test_fatal() was hit.
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c 
> b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> index 9485bafedc38..b19f07ebc0e7 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> @@ -124,3 +124,22 @@ uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t 
> interrupt_blocked_flag)
>  
>   return __tdx_hypercall(&args, 0);
>  }
> +
> +uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size,
> + uint64_t *data_out)
> +{
> + uint64_t ret;
> + struct tdx_hypercall_args args = {
> + .r11 = TDG_VP_VMCALL_VE_REQUEST_MMIO,
> +   

Re: [RFC PATCH v5 18/29] KVM: selftests: TDX: Add TDX MMIO writes test

2024-03-21 Thread Zhang, Dongsheng X



On 12/12/2023 12:46 PM, Sagi Shahar wrote:
> The test verifies MMIO writes of various sizes from the guest to the host.
> 
> Signed-off-by: Sagi Shahar 
> Signed-off-by: Ackerley Tng 
> Signed-off-by: Ryan Afranji 
> ---
>  .../selftests/kvm/include/x86_64/tdx/tdx.h|  2 +
>  .../selftests/kvm/lib/x86_64/tdx/tdx.c| 14 +++
>  .../selftests/kvm/x86_64/tdx_vm_tests.c   | 85 +++
>  3 files changed, 101 insertions(+)
> 
> diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h 
> b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> index 13ce60df5684..502b670ea699 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h
> @@ -25,5 +25,7 @@ uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, 
> uint64_t value);
>  uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag);
>  uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size,
>   uint64_t *data_out);
> +uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size,
> + uint64_t data_in);
>  
>  #endif // SELFTEST_TDX_TDX_H
> diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c 
> b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> index b19f07ebc0e7..f4afa09f7e3d 100644
> --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c
> @@ -143,3 +143,17 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t 
> address, uint64_t size,
>  
>   return ret;
>  }
> +
> +uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size,
> + uint64_t data_in)
> +{
> + struct tdx_hypercall_args args = {
> + .r11 = TDG_VP_VMCALL_VE_REQUEST_MMIO,
> + .r12 = size,
> + .r13 = TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE,
> + .r14 = address,
> + .r15 = data_in,
> + };
> +
> + return __tdx_hypercall(&args, 0);
> +}
> diff --git a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c 
> b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
> index 48902b69d13e..5e28ba828a92 100644
> --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
> +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c
> @@ -885,6 +885,90 @@ void verify_mmio_reads(void)
>   printf("\t ... PASSED\n");
>  }
>  
> +void guest_mmio_writes(void)
> +{
> + uint64_t ret;
> +
> + ret = tdg_vp_vmcall_ve_request_mmio_write(TDX_MMIO_TEST_ADDR, 1, 0x12);
> + if (ret)
> + tdx_test_fatal(ret);
> +
> + ret = tdg_vp_vmcall_ve_request_mmio_write(TDX_MMIO_TEST_ADDR, 2, 
> 0x1234);
> + if (ret)
> + tdx_test_fatal(ret);
> +
> + ret = tdg_vp_vmcall_ve_request_mmio_write(TDX_MMIO_TEST_ADDR, 4, 
> 0x12345678);
> + if (ret)
> + tdx_test_fatal(ret);
> +
> + ret = tdg_vp_vmcall_ve_request_mmio_write(TDX_MMIO_TEST_ADDR, 8, 
> 0x1234567890ABCDEF);
> + if (ret)
> + tdx_test_fatal(ret);
> +
> + // Write across page boundary.
> + ret = tdg_vp_vmcall_ve_request_mmio_write(PAGE_SIZE - 1, 8, 0);
> + if (ret)
> + tdx_test_fatal(ret);
> +
> + tdx_test_success();
> +}
> +
> +/*
> + * Varifies guest MMIO writes.
> + */

Nit: typo?  Varifies ==> Verifies

> +void verify_mmio_writes(void)
> +{
> + struct kvm_vm *vm;
> + struct kvm_vcpu *vcpu;
> +
> + uint8_t byte_1;
> + uint16_t byte_2;
> + uint32_t byte_4;
> + uint64_t byte_8;
> +
> + vm = td_create();
> + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0);
> + vcpu = td_vcpu_add(vm, 0, guest_mmio_writes);
> + td_finalize(vm);
> +
> + printf("Verifying TD MMIO writes:\n");
> +
> + td_vcpu_run(vcpu);
> + TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
> + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 1, 
> TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE);
> + byte_1 = *(uint8_t *)(vcpu->run->mmio.data);
> +
> + td_vcpu_run(vcpu);
> + TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
> + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 2, 
> TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE);
> + byte_2 = *(uint16_t *)(vcpu->run->mmio.data);
> +
> + td_vcpu_run(vcpu);
> + TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
> + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 4, 
> TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE);
> + byte_4 = *(uint32_t *)(vcpu->run->mmio.data);
> +
> + td_vcpu_run(vcpu);
> + TDX_TEST_CHECK_GUEST_FAILURE(vcpu);
> + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 8, 
> TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE);
> + byte_8 = *(uint64_t *)(vcpu->run->mmio.data);
> +
> + TEST_ASSERT_EQ(byte_1, 0x12);
> + TEST_ASSERT_EQ(byte_2, 0x1234);
> + TEST_ASSERT_EQ(byte_4, 0x12345678);
> + TEST_ASSERT_EQ(byte_8, 0x1234567890ABCDEF);
> +
> + td_vcpu_run(vcpu);
> + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYST

Re: [PATCH] Documentation: kunit: correct KUNIT_VERY_SLOW to KUNIT_SPEED_VERY_SLOW

2024-03-21 Thread David Gow
On Wed, 20 Mar 2024 at 16:18, Kemeng Shi  wrote:
>
> There is no KUNIT_VERY_SLOW, I guess we mean KUNIT_SPEED_VERY_SLOW.
>
> Signed-off-by: Kemeng Shi 
> ---

Nice catch, thanks!

Reviewed-by: David Gow 

Cheers,
-- David

>  Documentation/dev-tools/kunit/running_tips.rst | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/dev-tools/kunit/running_tips.rst 
> b/Documentation/dev-tools/kunit/running_tips.rst
> index bd689db6fdd2..482f598d141c 100644
> --- a/Documentation/dev-tools/kunit/running_tips.rst
> +++ b/Documentation/dev-tools/kunit/running_tips.rst
> @@ -294,7 +294,7 @@ macro to define the test case instead of 
> ``KUNIT_CASE(test_name)``.
>  .. code-block:: c
>
> static const struct kunit_attributes example_attr = {
> -   .speed = KUNIT_VERY_SLOW,
> +   .speed = KUNIT_SPEED_VERY_SLOW,
> };
>
> static struct kunit_case example_test_cases[] = {
> @@ -311,7 +311,7 @@ suite definition.
>  .. code-block:: c
>
> static const struct kunit_attributes example_attr = {
> -   .speed = KUNIT_VERY_SLOW,
> +   .speed = KUNIT_SPEED_VERY_SLOW,
> };
>
> static struct kunit_suite example_test_suite = {
> --
> 2.30.0
>
> --
> You received this message because you are subscribed to the Google Groups 
> "KUnit Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to kunit-dev+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/kunit-dev/20240320171424.6536-1-shikemeng%40huaweicloud.com.


smime.p7s
Description: S/MIME Cryptographic Signature


Re: [PATCH] selftests/mm: Confirm VA exhaustion without reliance on correctness of mmap()

2024-03-21 Thread Dev Jain



On 3/22/24 03:21, Andrew Morton wrote:

On Thu, 21 Mar 2024 16:05:22 +0530 Dev Jain  wrote:


Currently, VA exhaustion is being checked by passing a hint to mmap() and
expecting it to fail. This patch makes a stricter test by successful write()
calls from /proc/self/maps to a dump file, confirming that a free chunk is
indeed not available.

What's wrong with the current approach?
While populating the lower VA space, mmap() fails because we have 
exhausted the space.


Then, in validate_lower_address_hint(), because mmap() fails, we confirm 
that we have


indeed exhausted the space. There is a circular logic involved here.

Assume that there is a bug in mmap(), also assume that it exists 
independent of whether


you pass a hint address or not; that for some reason it is not able to 
find a 1GB chunk.


My idea is to assert the exhaustion against some other method.


Also, in the following line in validate_complete_va_space():

        if (start_addr - prev_end_addr >= SZ_1GB)

I made a small error, I forgot to use MAP_CHUNK_SIZE instead of SZ_1GB.