With `long` mapped to `isize`, `size_t`/`__kernel_size_t` mapped to
usize and `char` mapped to `u8`, many of the existing casts are no
longer necessary.
Signed-off-by: Gary Guo <gary(a)garyguo.net>
---
rust/kernel/kunit.rs | 10 ++--------
rust/kernel/print.rs | 4 ++--
rust/kernel/str.rs | 6 +++---
rust/kernel/uaccess.rs | 27 +++++++--------------------
4 files changed, 14 insertions(+), 33 deletions(-)
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 0ba77276ae7ef..766aeb1c6aea8 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -17,10 +17,7 @@ pub fn err(args: fmt::Arguments<'_>) {
// are passing.
#[cfg(CONFIG_PRINTK)]
unsafe {
- bindings::_printk(
- b"\x013%pA\0".as_ptr() as _,
- &args as *const _ as *const c_void,
- );
+ bindings::_printk(b"\x013%pA\0".as_ptr(), &args as *const _ as *const c_void);
}
}
@@ -33,10 +30,7 @@ pub fn info(args: fmt::Arguments<'_>) {
// are passing.
#[cfg(CONFIG_PRINTK)]
unsafe {
- bindings::_printk(
- b"\x016%pA\0".as_ptr() as _,
- &args as *const _ as *const c_void,
- );
+ bindings::_printk(b"\x016%pA\0".as_ptr(), &args as *const _ as *const c_void);
}
}
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index 508b0221256c9..90ae4f2568910 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -104,7 +104,7 @@ pub unsafe fn call_printk(
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_printk(
- format_string.as_ptr() as _,
+ format_string.as_ptr(),
module_name.as_ptr(),
&args as *const _ as *const c_void,
);
@@ -125,7 +125,7 @@ pub fn call_printk_cont(args: fmt::Arguments<'_>) {
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_printk(
- format_strings::CONT.as_ptr() as _,
+ format_strings::CONT.as_ptr(),
&args as *const _ as *const c_void,
);
}
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 3980d37bd4b29..2d30bca079e37 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -190,7 +190,7 @@ pub unsafe fn from_char_ptr<'a>(ptr: *const crate::ffi::c_char) -> &'a Self {
// to a `NUL`-terminated C string.
let len = unsafe { bindings::strlen(ptr) } + 1;
// SAFETY: Lifetime guaranteed by the safety precondition.
- let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len as _) };
+ let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len) };
// SAFETY: As `len` is returned by `strlen`, `bytes` does not contain interior `NUL`.
// As we have added 1 to `len`, the last byte is known to be `NUL`.
unsafe { Self::from_bytes_with_nul_unchecked(bytes) }
@@ -249,7 +249,7 @@ pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &mut CStr {
/// Returns a C pointer to the string.
#[inline]
pub const fn as_char_ptr(&self) -> *const crate::ffi::c_char {
- self.0.as_ptr() as _
+ self.0.as_ptr()
}
/// Convert the string to a byte slice without the trailing `NUL` byte.
@@ -817,7 +817,7 @@ pub fn try_from_fmt(args: fmt::Arguments<'_>) -> Result<Self, Error> {
// SAFETY: The buffer is valid for read because `f.bytes_written()` is bounded by `size`
// (which the minimum buffer size) and is non-zero (we wrote at least the `NUL` terminator)
// so `f.bytes_written() - 1` doesn't underflow.
- let ptr = unsafe { bindings::memchr(buf.as_ptr().cast(), 0, (f.bytes_written() - 1) as _) };
+ let ptr = unsafe { bindings::memchr(buf.as_ptr().cast(), 0, f.bytes_written() - 1) };
if !ptr.is_null() {
return Err(EINVAL);
}
diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs
index c746a1f1bb5ad..eb72fbcf152a1 100644
--- a/rust/kernel/uaccess.rs
+++ b/rust/kernel/uaccess.rs
@@ -8,7 +8,7 @@
alloc::Flags,
bindings,
error::Result,
- ffi::{c_ulong, c_void},
+ ffi::c_void,
prelude::*,
types::{AsBytes, FromBytes},
};
@@ -227,13 +227,9 @@ pub fn read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result {
if len > self.length {
return Err(EFAULT);
}
- let Ok(len_ulong) = c_ulong::try_from(len) else {
- return Err(EFAULT);
- };
- // SAFETY: `out_ptr` points into a mutable slice of length `len_ulong`, so we may write
+ // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write
// that many bytes to it.
- let res =
- unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len_ulong) };
+ let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len) };
if res != 0 {
return Err(EFAULT);
}
@@ -262,9 +258,6 @@ pub fn read<T: FromBytes>(&mut self) -> Result<T> {
if len > self.length {
return Err(EFAULT);
}
- let Ok(len_ulong) = c_ulong::try_from(len) else {
- return Err(EFAULT);
- };
let mut out: MaybeUninit<T> = MaybeUninit::uninit();
// SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes.
//
@@ -275,7 +268,7 @@ pub fn read<T: FromBytes>(&mut self) -> Result<T> {
bindings::_copy_from_user(
out.as_mut_ptr().cast::<c_void>(),
self.ptr as *const c_void,
- len_ulong,
+ len,
)
};
if res != 0 {
@@ -338,12 +331,9 @@ pub fn write_slice(&mut self, data: &[u8]) -> Result {
if len > self.length {
return Err(EFAULT);
}
- let Ok(len_ulong) = c_ulong::try_from(len) else {
- return Err(EFAULT);
- };
- // SAFETY: `data_ptr` points into an immutable slice of length `len_ulong`, so we may read
+ // SAFETY: `data_ptr` points into an immutable slice of length `len`, so we may read
// that many bytes from it.
- let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len_ulong) };
+ let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len) };
if res != 0 {
return Err(EFAULT);
}
@@ -362,9 +352,6 @@ pub fn write<T: AsBytes>(&mut self, value: &T) -> Result {
if len > self.length {
return Err(EFAULT);
}
- let Ok(len_ulong) = c_ulong::try_from(len) else {
- return Err(EFAULT);
- };
// SAFETY: The reference points to a value of type `T`, so it is valid for reading
// `size_of::<T>()` bytes.
//
@@ -375,7 +362,7 @@ pub fn write<T: AsBytes>(&mut self, value: &T) -> Result {
bindings::_copy_to_user(
self.ptr as *mut c_void,
(value as *const T).cast::<c_void>(),
- len_ulong,
+ len,
)
};
if res != 0 {
--
2.44.1
This patch allows progs to elide a null check on statically known map
lookup keys. In other words, if the verifier can statically prove that
the lookup will be in-bounds, allow the prog to drop the null check.
This is useful for two reasons:
1. Large numbers of nullness checks (especially when they cannot fail)
unnecessarily pushes prog towards BPF_COMPLEXITY_LIMIT_JMP_SEQ.
2. It forms a tighter contract between programmer and verifier.
For (1), bpftrace is starting to make heavier use of percpu scratch
maps. As a result, for user scripts with large number of unrolled loops,
we are starting to hit jump complexity verification errors. These
percpu lookups cannot fail anyways, as we only use static key values.
Eliding nullness probably results in less work for verifier as well.
For (2), percpu scratch maps are often used as a larger stack, as the
currrent stack is limited to 512 bytes. In these situations, it is
desirable for the programmer to express: "this lookup should never fail,
and if it does, it means I messed up the code". By omitting the null
check, the programmer can "ask" the verifier to double check the logic.
Changes from v1:
* Added a check for when R2 is not a ptr to stack
* Added a check for when stack is uninitialized (no stack slot yet)
* Fix spinlock reg id bumping
* Updated existing tests to account for null elision
* Added test case for when R2 can be both const and non-const
Daniel Xu (2):
bpf: verifier: Support eliding map lookup nullness
bpf: selftests: verifier: Add nullness elision tests
kernel/bpf/verifier.c | 64 ++++++-
tools/testing/selftests/bpf/progs/iters.c | 14 +-
.../selftests/bpf/progs/map_kptr_fail.c | 2 +-
.../bpf/progs/verifier_array_access.c | 166 ++++++++++++++++++
.../selftests/bpf/progs/verifier_map_in_map.c | 2 +-
.../testing/selftests/bpf/verifier/map_kptr.c | 2 +-
6 files changed, 239 insertions(+), 11 deletions(-)
--
2.46.0
Recently we committed a fix to allow processes to receive notifications for
non-zero exits via the process connector module. Commit is a4c9a56e6a2c.
However, for threads, when it does a pthread_exit(&exit_status) call, the
kernel is not aware of the exit status with which pthread_exit is called.
It is sent by child thread to the parent process, if it is waiting in
pthread_join(). Hence, for a thread exiting abnormally, kernel cannot
send notifications to any listening processes.
The exception to this is if the thread is sent a signal which it has not
handled, and dies along with it's process as a result; for eg. SIGSEGV or
SIGKILL. In this case, kernel is aware of the non-zero exit and sends a
notification for it.
For our use case, we cannot have parent wait in pthread_join, one of the
main reasons for this being that we do not want to track normal
pthread_exit(), which could be a very large number. We only want to be
notified of any abnormal exits. Hence, threads are created with
pthread_attr_t set to PTHREAD_CREATE_DETACHED.
To fix this problem, we add a new type PROC_CN_MCAST_NOTIFY to proc connector
API, which allows a thread to send it's exit status to kernel either when
it needs to call pthread_exit() with non-zero value to indicate some
error or from signal handler before pthread_exit().
Anjali Kulkarni (2):
connector/cn_proc: Handle threads for proc connector
connector/cn_proc: Selftest for threads case
drivers/connector/cn_proc.c | 11 ++-
include/linux/cn_proc.h | 5 +-
include/uapi/linux/cn_proc.h | 4 +-
kernel/exit.c | 5 +-
tools/testing/selftests/connector/Makefile | 23 ++++-
.../testing/selftests/connector/proc_filter.c | 5 +
tools/testing/selftests/connector/thread.c | 87 +++++++++++++++++
.../selftests/connector/thread_filter.c | 93 +++++++++++++++++++
8 files changed, 226 insertions(+), 7 deletions(-)
create mode 100644 tools/testing/selftests/connector/thread.c
create mode 100644 tools/testing/selftests/connector/thread_filter.c
--
2.45.2
Hi, all,
I was testing Linux torvalds tree vanilla kernel, and I've noticed for a number of releases this
./nci_dev stops testing until it's terminated (15).
Now, I tried to examine what went wrong, I hoped it will go away by itself. it didn't, so I am posting
a bug report.
The ./nci_dev seems to be stuck in several processes waiting on each other. I was able to produce
stacktraces. I am unable to tell if it is testsuite bug or a problem in underlying syscalls.
user@host:~/linux/kernel/linux_torvalds$ sudo gdb --pid 14132
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
Attaching to process 14132
Reading symbols from /home/marvin/linux/kernel/linux_torvalds/tools/testing/selftests/nci/nci_dev...
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...
Reading symbols from /usr/lib/debug/.build-id/6d/64b17fbac799e68da7ebd9985ddf9b5cb375e6.debug...
Reading symbols from /lib64/ld-linux-x86-64.so.2...
Reading symbols from /usr/lib/debug/.build-id/35/3e1b6cb0eebc08cf3ff812eae8a51b4efd684e.debug...
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007be7cf3107a7 in __GI___wait4 (pid=pid@entry=14133, stat_loc=stat_loc@entry=0x7ffef60482dc, options=options@entry=0, usage=usage@entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
warning: 30 ../sysdeps/unix/sysv/linux/wait4.c: No such file or directory
(gdb) where
#0 0x00007be7cf3107a7 in __GI___wait4 (pid=pid@entry=14133, stat_loc=stat_loc@entry=0x7ffef60482dc, options=options@entry=0, usage=usage@entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
#1 0x00007be7cf3108eb in __GI___waitpid (pid=pid@entry=14133, stat_loc=stat_loc@entry=0x7ffef60482dc, options=options@entry=0) at ./posix/waitpid.c:38
#2 0x00005d550d59299b in wrapper_NCI_start_poll (_metadata=0x7be7cf486000, variant=0x5d550d597020 <_NCI_NCI2_0_object>) at nci_dev.c:625
#3 0x00005d550d591a94 in __run_test (f=f@entry=0x5d550d5970a0 <_NCI_fixture_object>, variant=variant@entry=0x5d550d597020 <_NCI_NCI2_0_object>, t=t@entry=0x7be7cf486000) at ../kselftest_harness.h:1249
#4 0x00005d550d58fd47 in test_harness_run (argv=0x7ffef60488f8, argc=1) at ../kselftest_harness.h:1319
#5 main (argc=1, argv=0x7ffef60488f8) at nci_dev.c:904
(gdb)
user@host:~$ sudo gdb --pid 14133
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
Attaching to process 14133
[New LWP 14137]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007be7cf298d61 in __futex_abstimed_wait_common64 (private=128, cancel=true, abstime=0x0, op=265, expected=14137, futex_word=0x7be7cf000990) at ./nptl/futex-internal.c:57
warning: 57 ./nptl/futex-internal.c: No such file or directory
(gdb) where
#0 0x00007be7cf298d61 in __futex_abstimed_wait_common64 (private=128, cancel=true, abstime=0x0, op=265, expected=14137, futex_word=0x7be7cf000990) at ./nptl/futex-internal.c:57
#1 __futex_abstimed_wait_common (cancel=true, private=128, abstime=0x0, clockid=0, expected=14137, futex_word=0x7be7cf000990) at ./nptl/futex-internal.c:87
#2 __GI___futex_abstimed_wait_cancelable64 (futex_word=futex_word@entry=0x7be7cf000990, expected=14137, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=128)
at ./nptl/futex-internal.c:139
#3 0x00007be7cf29e793 in __pthread_clockjoin_ex (threadid=136235540547264, thread_return=thread_return@entry=0x7ffef6047dd0, clockid=clockid@entry=0, abstime=abstime@entry=0x0,
block=block@entry=true) at ./nptl/pthread_join_common.c:102
#4 0x00007be7cf29e633 in ___pthread_join (threadid=<optimized out>, thread_return=thread_return@entry=0x7ffef6047dd0) at ./nptl/pthread_join.c:24
#5 0x00005d550d591e48 in NCI_setup (_metadata=_metadata@entry=0x7be7cf486000, self=self@entry=0x7ffef60482e0, variant=<optimized out>) at nci_dev.c:447
#6 0x00005d550d5929f3 in wrapper_NCI_start_poll (_metadata=0x7be7cf486000, variant=0x5d550d597020 <_NCI_NCI2_0_object>) at nci_dev.c:625
#7 0x00005d550d591a94 in __run_test (f=f@entry=0x5d550d5970a0 <_NCI_fixture_object>, variant=variant@entry=0x5d550d597020 <_NCI_NCI2_0_object>, t=t@entry=0x7be7cf486000)
at ../kselftest_harness.h:1249
#8 0x00005d550d58fd47 in test_harness_run (argv=0x7ffef60488f8, argc=1) at ../kselftest_harness.h:1319
#9 main (argc=1, argv=0x7ffef60488f8) at nci_dev.c:904
(gdb)
I hope this can help you see what went wrong. The testing suite gets stuck on each run.
Best regards,
Mirsad Todorovac
Running this test on a small system produces different failures every
test checking deletions, and some flushes. From different test runs:
TEST: Common host entries configuration tests (L2) [FAIL]
Failed to delete L2 host entry
TEST: Common port group entries configuration tests (IPv4 (S, G)) [FAIL]
IPv4 (S, G) entry with VLAN 10 not deleted when VLAN was not specified
TEST: Common port group entries configuration tests (IPv6 (*, G)) [FAIL]
IPv6 (*, G) entry with VLAN 10 not deleted when VLAN was not specified
TEST: Flush tests [FAIL]
Entry not flushed by specified VLAN ID
TEST: Flush tests [FAIL]
IPv6 host entry not flushed by "nopermanent" state
Add a short sleep after deletion and flush to resolve this.
Create a delay variable just for this test to allow short sleep, the
lib.sh WAIT_TIME of 5 seconds makes the test far longer than necessary.
Tested on several weak systems with 0.1s delay:
- Ivy Bridge Celeron netbook (2014 x86_64)
- Raspberry Pi 3B (2016 aarch64)
- Small KVM VM on Intel 10th gen (2020 x86_64)
All these systems ran 25 test runs in a row with 100% pass OK.
Fixes: b6d00da08610 ("selftests: forwarding: Add bridge MDB test")
Signed-off-by: Jamie Bainbridge <jamie.bainbridge(a)gmail.com>
---
v2: Avoid false check failures as seen by Jakub Kicinski.
---
.../selftests/net/forwarding/bridge_mdb.sh | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/tools/testing/selftests/net/forwarding/bridge_mdb.sh b/tools/testing/selftests/net/forwarding/bridge_mdb.sh
index d9d587454d207931a539f59be15cbc63d471888f..49136279973d05d0e6b14237228ab58455554bb0 100755
--- a/tools/testing/selftests/net/forwarding/bridge_mdb.sh
+++ b/tools/testing/selftests/net/forwarding/bridge_mdb.sh
@@ -30,6 +30,9 @@ ALL_TESTS="
ctrl_test
"
+# time to wait for delete and flush to complete
+: "${SETTLE_DELAY:=0.1}"
+
NUM_NETIFS=4
source lib.sh
source tc_common.sh
@@ -152,6 +155,7 @@ cfg_test_host_common()
check_fail $? "Managed to replace $name host entry"
bridge mdb del dev br0 port br0 grp $grp $state vid 10
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp $grp vid 10 &> /dev/null
check_fail $? "Failed to delete $name host entry"
@@ -208,6 +212,7 @@ cfg_test_port_common()
check_err $? "Failed to replace $name entry"
bridge mdb del dev br0 port $swp1 $grp_key permanent vid 10
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 $grp_key vid 10 &> /dev/null
check_fail $? "Failed to delete $name entry"
@@ -230,6 +235,7 @@ cfg_test_port_common()
check_err $? "$name entry with VLAN 20 not added when VLAN was not specified"
bridge mdb del dev br0 port $swp1 $grp_key permanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 $grp_key vid 10 &> /dev/null
check_fail $? "$name entry with VLAN 10 not deleted when VLAN was not specified"
bridge mdb get dev br0 $grp_key vid 20 &> /dev/null
@@ -310,6 +316,7 @@ __cfg_test_port_ip_star_g()
bridge -d mdb get dev br0 grp $grp src $src1 vid 10 &> /dev/null
check_err $? "(S, G) entry not created"
bridge mdb del dev br0 port $swp1 grp $grp vid 10
+ sleep "$SETTLE_DELAY"
bridge -d mdb get dev br0 grp $grp vid 10 &> /dev/null
check_fail $? "(*, G) entry not deleted"
bridge -d mdb get dev br0 grp $grp src $src1 vid 10 &> /dev/null
@@ -828,6 +835,7 @@ cfg_test_flush()
bridge mdb add dev br0 port $swp1 grp 239.1.1.8 vid 10 temp
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
num_entries=$(bridge mdb show dev br0 | wc -l)
[[ $num_entries -eq 0 ]]
check_err $? 0 "Not all entries flushed after flush all"
@@ -840,6 +848,7 @@ cfg_test_flush()
bridge mdb add dev br0 port br0 grp 239.1.1.1 vid 10
bridge mdb flush dev br0 port $swp1
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp1"
check_fail $? "Entry not flushed by specified port"
@@ -849,11 +858,13 @@ cfg_test_flush()
check_err $? "Host entry flushed by wrong port"
bridge mdb flush dev br0 port br0
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port br0"
check_fail $? "Host entry not flushed by specified port"
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
# Check that when flushing by VLAN ID only entries programmed with the
# specified VLAN ID are flushed and the rest are not.
@@ -864,6 +875,7 @@ cfg_test_flush()
bridge mdb add dev br0 port $swp2 grp 239.1.1.1 vid 20
bridge mdb flush dev br0 vid 10
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 239.1.1.1 vid 10 &> /dev/null
check_fail $? "Entry not flushed by specified VLAN ID"
@@ -871,6 +883,7 @@ cfg_test_flush()
check_err $? "Entry flushed by wrong VLAN ID"
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
# Check that all permanent entries are flushed when "permanent" is
# specified and that temporary entries are not.
@@ -879,6 +892,7 @@ cfg_test_flush()
bridge mdb add dev br0 port $swp2 grp 239.1.1.1 temp vid 10
bridge mdb flush dev br0 permanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp1"
check_fail $? "Entry not flushed by \"permanent\" state"
@@ -886,6 +900,7 @@ cfg_test_flush()
check_err $? "Entry flushed by wrong state (\"permanent\")"
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
# Check that all temporary entries are flushed when "nopermanent" is
# specified and that permanent entries are not.
@@ -894,6 +909,7 @@ cfg_test_flush()
bridge mdb add dev br0 port $swp2 grp 239.1.1.1 temp vid 10
bridge mdb flush dev br0 nopermanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp1"
check_err $? "Entry flushed by wrong state (\"nopermanent\")"
@@ -901,6 +917,7 @@ cfg_test_flush()
check_fail $? "Entry not flushed by \"nopermanent\" state"
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
# Check that L2 host entries are not flushed when "nopermanent" is
# specified, but flushed when "permanent" is specified.
@@ -908,16 +925,19 @@ cfg_test_flush()
bridge mdb add dev br0 port br0 grp 01:02:03:04:05:06 permanent vid 10
bridge mdb flush dev br0 nopermanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 01:02:03:04:05:06 vid 10 &> /dev/null
check_err $? "L2 host entry flushed by wrong state (\"nopermanent\")"
bridge mdb flush dev br0 permanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 01:02:03:04:05:06 vid 10 &> /dev/null
check_fail $? "L2 host entry not flushed by \"permanent\" state"
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
# Check that IPv4 host entries are not flushed when "permanent" is
# specified, but flushed when "nopermanent" is specified.
@@ -925,16 +945,19 @@ cfg_test_flush()
bridge mdb add dev br0 port br0 grp 239.1.1.1 temp vid 10
bridge mdb flush dev br0 permanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 239.1.1.1 vid 10 &> /dev/null
check_err $? "IPv4 host entry flushed by wrong state (\"permanent\")"
bridge mdb flush dev br0 nopermanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 239.1.1.1 vid 10 &> /dev/null
check_fail $? "IPv4 host entry not flushed by \"nopermanent\" state"
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
# Check that IPv6 host entries are not flushed when "permanent" is
# specified, but flushed when "nopermanent" is specified.
@@ -942,16 +965,19 @@ cfg_test_flush()
bridge mdb add dev br0 port br0 grp ff0e::1 temp vid 10
bridge mdb flush dev br0 permanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp ff0e::1 vid 10 &> /dev/null
check_err $? "IPv6 host entry flushed by wrong state (\"permanent\")"
bridge mdb flush dev br0 nopermanent
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp ff0e::1 vid 10 &> /dev/null
check_fail $? "IPv6 host entry not flushed by \"nopermanent\" state"
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
# Check that when flushing by routing protocol only entries programmed
# with the specified routing protocol are flushed and the rest are not.
@@ -961,6 +987,7 @@ cfg_test_flush()
bridge mdb add dev br0 port br0 grp 239.1.1.1 vid 10
bridge mdb flush dev br0 proto bgp
+ sleep "$SETTLE_DELAY"
bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp1"
check_fail $? "Entry not flushed by specified routing protocol"
@@ -970,6 +997,7 @@ cfg_test_flush()
check_err $? "Host entry flushed by wrong routing protocol"
bridge mdb flush dev br0
+ sleep "$SETTLE_DELAY"
# Test that an error is returned when trying to flush using unsupported
# parameters.
--
2.39.2
Malicious guests can cause bus locks to degrade the performance of a
system. Non-WB (write-back) and misaligned locked RMW
(read-modify-write) instructions are referred to as "bus locks" and
require system wide synchronization among all processors to guarantee
the atomicity. The bus locks can impose notable performance penalties
for all processors within the system.
Support for the Bus Lock Threshold is indicated by CPUID
Fn8000_000A_EDX[29] BusLockThreshold=1, the VMCB provides a Bus Lock
Threshold enable bit and an unsigned 16-bit Bus Lock Threshold count.
VMCB intercept bit
VMCB Offset Bits Function
14h 5 Intercept bus lock operations
Bus lock threshold count
VMCB Offset Bits Function
120h 15:0 Bus lock counter
During VMRUN, the bus lock threshold count is fetched and stored in an
internal count register. Prior to executing a bus lock within the
guest, the processor verifies the count in the bus lock register. If
the count is greater than zero, the processor executes the bus lock,
reducing the count. However, if the count is zero, the bus lock
operation is not performed, and instead, a Bus Lock Threshold #VMEXIT
is triggered to transfer control to the Virtual Machine Monitor (VMM).
A Bus Lock Threshold #VMEXIT is reported to the VMM with VMEXIT code
0xA5h, VMEXIT_BUSLOCK. EXITINFO1 and EXITINFO2 are set to 0 on
a VMEXIT_BUSLOCK. On a #VMEXIT, the processor writes the current
value of the Bus Lock Threshold Counter to the VMCB.
More details about the Bus Lock Threshold feature can be found in AMD
APM [1].
Patches are prepared on kvm-x86/svm (704ec48fc2fb)
Testing done:
- Added a selftest for the Bus Lock Threadshold functionality.
- Tested the Bus Lock Threshold functionality on SEV and SEV-ES guests.
- Tested the Bus Lock Threshold functionality on nested guests.
Qemu changes can be found on:
Repo: https://github.com/AMDESE/qemu.git
Branch: buslock_threshold
Qemu commandline to use the bus lock threshold functionality:
qemu-system-x86_64 -enable-kvm -cpu EPYC-Turin,+svm -M q35,bus-lock-ratelimit=10 \ ..
[1]: AMD64 Architecture Programmer's Manual Pub. 24593, April 2024,
Vol 2, 15.14.5 Bus Lock Threshold.
https://bugzilla.kernel.org/attachment.cgi?id=306250
Manali Shukla (2):
x86/cpufeatures: Add CPUID feature bit for the Bus Lock Threshold
KVM: x86: nSVM: Implement support for nested Bus Lock Threshold
Nikunj A Dadhania (2):
KVM: SVM: Enable Bus lock threshold exit
KVM: selftests: Add bus lock exit test
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/svm.h | 5 +-
arch/x86/include/uapi/asm/svm.h | 2 +
arch/x86/kvm/governed_features.h | 1 +
arch/x86/kvm/svm/nested.c | 25 ++++
arch/x86/kvm/svm/svm.c | 48 ++++++++
arch/x86/kvm/svm/svm.h | 1 +
arch/x86/kvm/x86.h | 1 +
tools/testing/selftests/kvm/Makefile | 1 +
.../selftests/kvm/x86_64/svm_buslock_test.c | 114 ++++++++++++++++++
10 files changed, 198 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/kvm/x86_64/svm_buslock_test.c
base-commit: 704ec48fc2fbd4e41ec982662ad5bf1eee33eeb2
--
2.34.1
The series of patches are for doing basic tests of NIC driver.
Test comprises checks for auto-negotiation, speed,
duplex state and throughput between local NIC and partner.
Tools such as ethtool, iperf3 are used.
Signed-off-by: Mohan Prasad J <mohan.prasad(a)microchip.com>
---
Changes in v2:
- Changed the hardcoded implementation of speed, duplex states,
throughput to generic values, in order to support all type
of NIC drivers.
- Test executes based on the supported link modes between local
NIC driver and partner.
- Instead of lan743x directory, selftest file is now placed in
/selftests/drivers/net/hw.
---
Mohan Prasad J (3):
selftests: nic_basic_tests: Add selftest file for basic tests of NIC
selftests: nic_basic_tests: Add selftest case for speed and duplex
state checks
selftests: nic_basic_tests: Add selftest case for throughput check
.../testing/selftests/drivers/net/hw/Makefile | 1 +
.../drivers/net/hw/nic_basic_tests.py | 230 ++++++++++++++++++
2 files changed, 231 insertions(+)
create mode 100644 tools/testing/selftests/drivers/net/hw/nic_basic_tests.py
--
2.43.0
Newer 32-bit architectures e.g. riscv32 are using 64-bit time_t
from get go, they have not wired __NR_clock_adjtime at all
valid-adjtimex testcase fails to compile on such architectures.
if this condition is found then use 64-bit adjtime syscall
Signed-off-by: Khem Raj <raj.khem(a)gmail.com>
Cc: John Stultz <jstultz(a)google.com>
Cc: Shuah Khan <shuah(a)kernel.org>
---
tools/testing/selftests/timers/valid-adjtimex.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c
index d500884801d8..ff4ff8b1d127 100644
--- a/tools/testing/selftests/timers/valid-adjtimex.c
+++ b/tools/testing/selftests/timers/valid-adjtimex.c
@@ -39,7 +39,11 @@
#include <sys/syscall.h>
int clock_adjtime(clockid_t id, struct timex *tx)
{
+#if !defined(__NR_clock_adjtime) && defined(__NR_clock_adjtime64)
+ return syscall(__NR_clock_adjtime64, id, tx);
+#else
return syscall(__NR_clock_adjtime, id, tx);
+#endif
}