eBPF already allows programs to be preloaded and kept running without
intervention from user space. There is a dedicated kernel module called
bpf_preload, which contains the light skeleton of the iterators_bpf eBPF
program. If this module is enabled in the kernel configuration, its loading
will be triggered when the bpf filesystem is mounted (unless the module is
built-in), and the links of iterators_bpf are pinned in that filesystem
(they will appear as the progs.debug and maps.debug files).
However, the current mechanism, if used to preload an LSM, would not offer
the same security guarantees of LSMs integrated in the security subsystem.
Also, it is not generic enough to be used for preloading arbitrary eBPF
programs, unless the bpf_preload code is heavily modified.
More specifically, the security problems are:
- any program can be pinned to the bpf filesystem without limitations
(unless a MAC mechanism enforces some restrictions);
- programs being executed can be terminated at any time by deleting the
pinned objects or unmounting the bpf filesystem.
The usability problems are:
- only a fixed amount of links can be pinned;
- only links can be pinned, other object types are not supported;
- code to pin objects has to be written manually;
- preloading multiple eBPF programs is not practical, bpf_preload has to be
modified to include additional light skeletons.
Solve the security problems by mounting the bpf filesystem from the kernel,
by preloading authenticated kernel modules (e.g. with module.sig_enforce)
and by pinning objects to that filesystem. This particular filesystem
instance guarantees that desired eBPF programs run until the very end of
the kernel lifecycle, since even root cannot interfere with it.
Solve the usability problems by generalizing the pinning function, to
handle not only links but also maps and progs. Also increment the object
reference count and call the pinning function directly from the preload
method (currently in the bpf_preload kernel module) rather than from the
bpf filesystem code itself, so that a generic eBPF program can do those
operations depending on its objects (this also avoids the limitation of the
fixed-size array for storing the objects to pin).
Then, simplify the process of pinning objects defined by a generic eBPF
program by automatically generating the required methods in the light
skeleton. Also, generate a separate kernel module for each eBPF program to
preload, so that existing ones don't have to be modified. Finally, support
preloading multiple eBPF programs by allowing users to specify a list from
the kernel configuration, at build time, or with the new kernel option
bpf_preload_list=, at run-time.
To summarize, this patch set makes it possible to plug in out-of-tree LSMs
matching the security guarantees of their counterpart in the security
subsystem, without having to modify the kernel itself. The same benefits
are extended to other eBPF program types.
Only one remaining problem is how to support auto-attaching eBPF programs
with LSM type. It will be solved with a separate patch set.
Patches 1-2 export some definitions, to build out-of-tree kernel modules
with eBPF programs to preload. Patches 3-4 allow eBPF programs to pin
objects by themselves. Patches 5-10 automatically generate the methods for
preloading in the light skeleton. Patches 11-14 make it possible to preload
multiple eBPF programs. Patch 15 automatically generates the kernel module
for preloading an eBPF program, patch 16 does a kernel mount of the bpf
filesystem, and finally patches 17-18 test the functionality introduced.
Roberto Sassu (18):
bpf: Export bpf_link_inc()
bpf-preload: Move bpf_preload.h to include/linux
bpf-preload: Generalize object pinning from the kernel
bpf-preload: Export and call bpf_obj_do_pin_kernel()
bpf-preload: Generate static variables
bpf-preload: Generate free_objs_and_skel()
bpf-preload: Generate preload()
bpf-preload: Generate load_skel()
bpf-preload: Generate code to pin non-internal maps
bpf-preload: Generate bpf_preload_ops
bpf-preload: Store multiple bpf_preload_ops structures in a linked
list
bpf-preload: Implement new registration method for preloading eBPF
programs
bpf-preload: Move pinned links and maps to a dedicated directory in
bpffs
bpf-preload: Switch to new preload registration method
bpf-preload: Generate code of kernel module to preload
bpf-preload: Do kernel mount to ensure that pinned objects don't
disappear
bpf-preload/selftests: Add test for automatic generation of preload
methods
bpf-preload/selftests: Preload a test eBPF program and check pinned
objects
.../admin-guide/kernel-parameters.txt | 8 +
fs/namespace.c | 1 +
include/linux/bpf.h | 5 +
include/linux/bpf_preload.h | 37 ++
init/main.c | 2 +
kernel/bpf/inode.c | 295 +++++++++--
kernel/bpf/preload/Kconfig | 25 +-
kernel/bpf/preload/bpf_preload.h | 16 -
kernel/bpf/preload/bpf_preload_kern.c | 85 +---
kernel/bpf/preload/iterators/Makefile | 9 +-
.../bpf/preload/iterators/iterators.lskel.h | 466 +++++++++++-------
kernel/bpf/syscall.c | 1 +
.../bpf/bpftool/Documentation/bpftool-gen.rst | 13 +
tools/bpf/bpftool/bash-completion/bpftool | 6 +-
tools/bpf/bpftool/gen.c | 331 +++++++++++++
tools/bpf/bpftool/main.c | 7 +-
tools/bpf/bpftool/main.h | 1 +
tools/testing/selftests/bpf/Makefile | 32 +-
.../bpf/bpf_testmod_preload/.gitignore | 7 +
.../bpf/bpf_testmod_preload/Makefile | 20 +
.../gen_preload_methods.expected.diff | 97 ++++
.../bpf/prog_tests/test_gen_preload_methods.c | 27 +
.../bpf/prog_tests/test_preload_methods.c | 69 +++
.../selftests/bpf/progs/gen_preload_methods.c | 23 +
24 files changed, 1246 insertions(+), 337 deletions(-)
create mode 100644 include/linux/bpf_preload.h
delete mode 100644 kernel/bpf/preload/bpf_preload.h
create mode 100644 tools/testing/selftests/bpf/bpf_testmod_preload/.gitignore
create mode 100644 tools/testing/selftests/bpf/bpf_testmod_preload/Makefile
create mode 100644 tools/testing/selftests/bpf/prog_tests/gen_preload_methods.expected.diff
create mode 100644 tools/testing/selftests/bpf/prog_tests/test_gen_preload_methods.c
create mode 100644 tools/testing/selftests/bpf/prog_tests/test_preload_methods.c
create mode 100644 tools/testing/selftests/bpf/progs/gen_preload_methods.c
--
2.32.0
There are some issues in parse_num_list():
1. The end variable is assigned twice when parsing_end is true.
2. The function does not check that parsing_end should finally be false.
Clean up parse_num_list() and fix these issues.
Signed-off-by: Yuntao Wang <ytcoode(a)gmail.com>
---
tools/testing/selftests/bpf/testing_helpers.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/bpf/testing_helpers.c b/tools/testing/selftests/bpf/testing_helpers.c
index 795b6798ccee..82f0e2d99c23 100644
--- a/tools/testing/selftests/bpf/testing_helpers.c
+++ b/tools/testing/selftests/bpf/testing_helpers.c
@@ -20,16 +20,16 @@ int parse_num_list(const char *s, bool **num_set, int *num_set_len)
if (errno)
return -errno;
- if (parsing_end)
- end = num;
- else
+ if (!parsing_end) {
start = num;
+ if (*next == '-') {
+ s = next + 1;
+ parsing_end = true;
+ continue;
+ }
+ }
- if (!parsing_end && *next == '-') {
- s = next + 1;
- parsing_end = true;
- continue;
- } else if (*next == ',') {
+ if (*next == ',') {
parsing_end = false;
s = next + 1;
end = num;
@@ -60,7 +60,7 @@ int parse_num_list(const char *s, bool **num_set, int *num_set_len)
set[i] = true;
}
- if (!set)
+ if (!set || parsing_end)
return -EINVAL;
*num_set = set;
--
2.35.1
This patch series revisits the proposal for a GPU cgroup controller to
track and limit memory allocations by various device/allocator
subsystems. The patch series also contains a simple prototype to
illustrate how Android intends to implement DMA-BUF allocator
attribution using the GPU cgroup controller. The prototype does not
include resource limit enforcements.
Changelog:
v4:
Skip test if not run as root per Shuah Khan
Add better test logging for abnormal child termination per Shuah Khan
Adjust ordering of charge/uncharge during transfer to avoid potentially
hitting cgroup limit per Michal Koutný
Adjust gpucg_try_charge critical section for charge transfer functionality
Fix uninitialized return code error for dmabuf_try_charge error case
v3:
Remove Upstreaming Plan from gpu-cgroup.rst per John Stultz
Use more common dual author commit message format per John Stultz
Remove android from binder changes title per Todd Kjos
Add a kselftest for this new behavior per Greg Kroah-Hartman
Include details on behavior for all combinations of kernel/userspace
versions in changelog (thanks Suren Baghdasaryan) per Greg Kroah-Hartman.
Fix pid and uid types in binder UAPI header
v2:
See the previous revision of this change submitted by Hridya Valsaraju
at: https://lore.kernel.org/all/20220115010622.3185921-1-hridya@google.com/
Move dma-buf cgroup charge transfer from a dma_buf_op defined by every
heap to a single dma-buf function for all heaps per Daniel Vetter and
Christian König. Pointers to struct gpucg and struct gpucg_device
tracking the current associations were added to the dma_buf struct to
achieve this.
Fix incorrect Kconfig help section indentation per Randy Dunlap.
History of the GPU cgroup controller
====================================
The GPU/DRM cgroup controller came into being when a consensus[1]
was reached that the resources it tracked were unsuitable to be integrated
into memcg. Originally, the proposed controller was specific to the DRM
subsystem and was intended to track GEM buffers and GPU-specific
resources[2]. In order to help establish a unified memory accounting model
for all GPU and all related subsystems, Daniel Vetter put forth a
suggestion to move it out of the DRM subsystem so that it can be used by
other DMA-BUF exporters as well[3]. This RFC proposes an interface that
does the same.
[1]: https://patchwork.kernel.org/project/dri-devel/cover/20190501140438.9506-1-…
[2]: https://lore.kernel.org/amd-gfx/20210126214626.16260-1-brian.welty@intel.co…
[3]: https://lore.kernel.org/amd-gfx/YCVOl8%2F87bqRSQei@phenom.ffwll.local/
Hridya Valsaraju (5):
gpu: rfc: Proposal for a GPU cgroup controller
cgroup: gpu: Add a cgroup controller for allocator attribution of GPU
memory
dmabuf: heaps: export system_heap buffers with GPU cgroup charging
dmabuf: Add gpu cgroup charge transfer function
binder: Add a buffer flag to relinquish ownership of fds
T.J. Mercier (3):
dmabuf: Use the GPU cgroup charge/uncharge APIs
binder: use __kernel_pid_t and __kernel_uid_t for userspace
selftests: Add binder cgroup gpu memory transfer test
Documentation/gpu/rfc/gpu-cgroup.rst | 183 +++++++
Documentation/gpu/rfc/index.rst | 4 +
drivers/android/binder.c | 26 +
drivers/dma-buf/dma-buf.c | 107 ++++
drivers/dma-buf/dma-heap.c | 27 +
drivers/dma-buf/heaps/system_heap.c | 3 +
include/linux/cgroup_gpu.h | 139 +++++
include/linux/cgroup_subsys.h | 4 +
include/linux/dma-buf.h | 22 +-
include/linux/dma-heap.h | 11 +
include/uapi/linux/android/binder.h | 5 +-
init/Kconfig | 7 +
kernel/cgroup/Makefile | 1 +
kernel/cgroup/gpu.c | 362 +++++++++++++
.../selftests/drivers/android/binder/Makefile | 8 +
.../drivers/android/binder/binder_util.c | 254 +++++++++
.../drivers/android/binder/binder_util.h | 32 ++
.../selftests/drivers/android/binder/config | 4 +
.../binder/test_dmabuf_cgroup_transfer.c | 484 ++++++++++++++++++
19 files changed, 1679 insertions(+), 4 deletions(-)
create mode 100644 Documentation/gpu/rfc/gpu-cgroup.rst
create mode 100644 include/linux/cgroup_gpu.h
create mode 100644 kernel/cgroup/gpu.c
create mode 100644 tools/testing/selftests/drivers/android/binder/Makefile
create mode 100644 tools/testing/selftests/drivers/android/binder/binder_util.c
create mode 100644 tools/testing/selftests/drivers/android/binder/binder_util.h
create mode 100644 tools/testing/selftests/drivers/android/binder/config
create mode 100644 tools/testing/selftests/drivers/android/binder/test_dmabuf_cgroup_transfer.c
--
2.35.1.1021.g381101b075-goog
On Fri, 2022-03-11 at 17:24 +0100, Vincent Whitchurch wrote:
> Import the libvhost-user from QEMU for use in the implementation of the
> virtio devices in the roadtest backend.
>
So hm, I wonder if this is the sensible thing to do?
Not that I mind importing qemu code, but:
1) the implementation is rather complex in some places, and has support
for a LOT of virtio/vhost-user features that are really not needed
in these cases, for performance etc. It's also close to 4k LOC.
2) the implementation doesn't support time-travel mode which might come
in handy
We have another implementation that might be simpler:
https://github.com/linux-test-project/usfstl/blob/main/src/vhost.c
but it probably has dependencies on other things in this library, but
vhost.c itself is only ~1k LOC. (But I need to update it, I'm sure we
have some unpublished bugfixes etc. in this code)
johannes
Dzień dobry!
Czy mógłbym przedstawić rozwiązanie, które umożliwia monitoring każdego auta w czasie rzeczywistym w tym jego pozycję, zużycie paliwa i przebieg?
Dodatkowo nasze narzędzie minimalizuje koszty utrzymania samochodów, skraca czas przejazdów, a także tworzenie planu tras czy dostaw.
Z naszej wiedzy i doświadczenia korzysta już ponad 49 tys. Klientów. Monitorujemy 809 000 pojazdów na całym świecie, co jest naszą najlepszą wizytówką.
Bardzo proszę o e-maila zwrotnego, jeśli moglibyśmy wspólnie omówić potencjał wykorzystania takiego rozwiązania w Państwa firmie.
Pozdrawiam,
Marek Onufrowicz
Currently, when we run test_progs with just executable file name, for
example 'PATH=. test_progs-no_alu32', cd_flavor_subdir() will not check
if test_progs is running as a flavored test runner and switch into
corresponding sub-directory.
This will cause test_progs-no_alu32 executed by the
'PATH=. test_progs-no_alu32' command to run in the wrong directory and
load the wrong BPF objects.
Signed-off-by: Yuntao Wang <ytcoode(a)gmail.com>
---
tools/testing/selftests/bpf/test_progs.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index 2ecb73a65206..0a4b45d7b515 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -761,8 +761,10 @@ int cd_flavor_subdir(const char *exec_name)
const char *flavor = strrchr(exec_name, '/');
if (!flavor)
- return 0;
- flavor++;
+ flavor = exec_name;
+ else
+ flavor++;
+
flavor = strrchr(flavor, '-');
if (!flavor)
return 0;
--
2.35.1
If a memop fails due to key checked protection, after already having
written to the guest, don't indicate suppression to the guest, as that
would imply that memory wasn't modified.
This could be considered a fix to the code introducing storage key
support, however this is a bug in KVM only if we emulate an
instructions writing to an operand spanning multiple pages, which I
don't believe we do.
Janis Schoetterl-Glausch (2):
KVM: s390: Don't indicate suppression on dirtying, failing memop
KVM: s390: selftest: Test suppression indication on key prot exception
arch/s390/kvm/gaccess.c | 47 ++++++++++++++---------
tools/testing/selftests/kvm/s390x/memop.c | 43 ++++++++++++++++++++-
2 files changed, 70 insertions(+), 20 deletions(-)
base-commit: 1ebdbeb03efe89f01f15df038a589077df3d21f5
--
2.32.0
From: Ricardo Koller <ricarkol(a)google.com>
[ Upstream commit b53de63a89244c196d8a2ea76b6754e3fdb4b626 ]
vgic_poke_irq() checks that the attr argument passed to the vgic device
ioctl is sane. Make this check tighter by moving it to after the last
attr update.
Signed-off-by: Ricardo Koller <ricarkol(a)google.com>
Reported-by: Reiji Watanabe <reijiw(a)google.com>
Cc: Andrew Jones <drjones(a)redhat.com>
Reviewed-by: Andrew Jones <drjones(a)redhat.com>
Signed-off-by: Marc Zyngier <maz(a)kernel.org>
Link: https://lore.kernel.org/r/20220127030858.3269036-6-ricarkol@google.com
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
---
tools/testing/selftests/kvm/lib/aarch64/vgic.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/kvm/lib/aarch64/vgic.c b/tools/testing/selftests/kvm/lib/aarch64/vgic.c
index 7c876ccf9294..5d45046c1b80 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/vgic.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/vgic.c
@@ -140,9 +140,6 @@ static void vgic_poke_irq(int gic_fd, uint32_t intid,
uint64_t val;
bool intid_is_private = INTID_IS_SGI(intid) || INTID_IS_PPI(intid);
- /* Check that the addr part of the attr is within 32 bits. */
- assert(attr <= KVM_DEV_ARM_VGIC_OFFSET_MASK);
-
uint32_t group = intid_is_private ? KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
: KVM_DEV_ARM_VGIC_GRP_DIST_REGS;
@@ -152,6 +149,9 @@ static void vgic_poke_irq(int gic_fd, uint32_t intid,
attr += SZ_64K;
}
+ /* Check that the addr part of the attr is within 32 bits. */
+ assert((attr & ~KVM_DEV_ARM_VGIC_OFFSET_MASK) == 0);
+
/*
* All calls will succeed, even with invalid intid's, as long as the
* addr part of the attr is within 32 bits (checked above). An invalid
--
2.34.1
From: Ricardo Koller <ricarkol(a)google.com>
[ Upstream commit a5cd38fd9c47b23abc6df08d6ee6a71b39038185 ]
Fix the formatting of some comments and the wording of one of them (in
gicv3_access_reg).
Signed-off-by: Ricardo Koller <ricarkol(a)google.com>
Reported-by: Reiji Watanabe <reijiw(a)google.com>
Cc: Andrew Jones <drjones(a)redhat.com>
Reviewed-by: Andrew Jones <drjones(a)redhat.com>
Signed-off-by: Marc Zyngier <maz(a)kernel.org>
Link: https://lore.kernel.org/r/20220127030858.3269036-5-ricarkol@google.com
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
---
tools/testing/selftests/kvm/aarch64/vgic_irq.c | 12 ++++++++----
tools/testing/selftests/kvm/lib/aarch64/gic_v3.c | 10 ++++++----
tools/testing/selftests/kvm/lib/aarch64/vgic.c | 3 ++-
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/kvm/aarch64/vgic_irq.c b/tools/testing/selftests/kvm/aarch64/vgic_irq.c
index 48e43e24d240..554ca649d470 100644
--- a/tools/testing/selftests/kvm/aarch64/vgic_irq.c
+++ b/tools/testing/selftests/kvm/aarch64/vgic_irq.c
@@ -306,7 +306,8 @@ static void guest_restore_active(struct test_args *args,
uint32_t prio, intid, ap1r;
int i;
- /* Set the priorities of the first (KVM_NUM_PRIOS - 1) IRQs
+ /*
+ * Set the priorities of the first (KVM_NUM_PRIOS - 1) IRQs
* in descending order, so intid+1 can preempt intid.
*/
for (i = 0, prio = (num - 1) * 8; i < num; i++, prio -= 8) {
@@ -315,7 +316,8 @@ static void guest_restore_active(struct test_args *args,
gic_set_priority(intid, prio);
}
- /* In a real migration, KVM would restore all GIC state before running
+ /*
+ * In a real migration, KVM would restore all GIC state before running
* guest code.
*/
for (i = 0; i < num; i++) {
@@ -503,7 +505,8 @@ static void guest_code(struct test_args *args)
test_injection_failure(args, f);
}
- /* Restore the active state of IRQs. This would happen when live
+ /*
+ * Restore the active state of IRQs. This would happen when live
* migrating IRQs in the middle of being handled.
*/
for_each_supported_activate_fn(args, set_active_fns, f)
@@ -844,7 +847,8 @@ int main(int argc, char **argv)
}
}
- /* If the user just specified nr_irqs and/or gic_version, then run all
+ /*
+ * If the user just specified nr_irqs and/or gic_version, then run all
* combinations.
*/
if (default_args) {
diff --git a/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c b/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
index e4945fe66620..263bf3ed8fd5 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
@@ -19,7 +19,7 @@ struct gicv3_data {
unsigned int nr_spis;
};
-#define sgi_base_from_redist(redist_base) (redist_base + SZ_64K)
+#define sgi_base_from_redist(redist_base) (redist_base + SZ_64K)
#define DIST_BIT (1U << 31)
enum gicv3_intid_range {
@@ -105,7 +105,8 @@ static void gicv3_set_eoi_split(bool split)
{
uint32_t val;
- /* All other fields are read-only, so no need to read CTLR first. In
+ /*
+ * All other fields are read-only, so no need to read CTLR first. In
* fact, the kernel does the same.
*/
val = split ? (1U << 1) : 0;
@@ -160,8 +161,9 @@ static void gicv3_access_reg(uint32_t intid, uint64_t offset,
GUEST_ASSERT(bits_per_field <= reg_bits);
GUEST_ASSERT(!write || *val < (1U << bits_per_field));
- /* Some registers like IROUTER are 64 bit long. Those are currently not
- * supported by readl nor writel, so just asserting here until then.
+ /*
+ * This function does not support 64 bit accesses. Just asserting here
+ * until we implement readq/writeq.
*/
GUEST_ASSERT(reg_bits == 32);
diff --git a/tools/testing/selftests/kvm/lib/aarch64/vgic.c b/tools/testing/selftests/kvm/lib/aarch64/vgic.c
index f5cd0c536d85..7c876ccf9294 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/vgic.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/vgic.c
@@ -152,7 +152,8 @@ static void vgic_poke_irq(int gic_fd, uint32_t intid,
attr += SZ_64K;
}
- /* All calls will succeed, even with invalid intid's, as long as the
+ /*
+ * All calls will succeed, even with invalid intid's, as long as the
* addr part of the attr is within 32 bits (checked above). An invalid
* intid will just make the read/writes point to above the intended
* register space (i.e., ICPENDR after ISPENDR).
--
2.34.1
From: Ricardo Koller <ricarkol(a)google.com>
[ Upstream commit 5b7898648f02083012900e48d063e51ccbdad165 ]
kvm_set_gsi_routing_irqchip_check(expect_failure=true) is used to check
the error code returned by the kernel when trying to setup an invalid
gsi routing table. The ioctl fails if "pin >= KVM_IRQCHIP_NUM_PINS", so
kvm_set_gsi_routing_irqchip_check() should test the error only when
"intid >= KVM_IRQCHIP_NUM_PINS+32". The issue is that the test check is
"intid >= KVM_IRQCHIP_NUM_PINS", so for a case like "intid =
KVM_IRQCHIP_NUM_PINS" the test wrongly assumes that the kernel will
return an error. Fix this by using the right check.
Signed-off-by: Ricardo Koller <ricarkol(a)google.com>
Reported-by: Reiji Watanabe <reijiw(a)google.com>
Cc: Andrew Jones <drjones(a)redhat.com>
Signed-off-by: Marc Zyngier <maz(a)kernel.org>
Link: https://lore.kernel.org/r/20220127030858.3269036-4-ricarkol@google.com
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
---
tools/testing/selftests/kvm/aarch64/vgic_irq.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/kvm/aarch64/vgic_irq.c b/tools/testing/selftests/kvm/aarch64/vgic_irq.c
index 7f3afee5cc00..48e43e24d240 100644
--- a/tools/testing/selftests/kvm/aarch64/vgic_irq.c
+++ b/tools/testing/selftests/kvm/aarch64/vgic_irq.c
@@ -573,8 +573,8 @@ static void kvm_set_gsi_routing_irqchip_check(struct kvm_vm *vm,
kvm_gsi_routing_write(vm, routing);
} else {
ret = _kvm_gsi_routing_write(vm, routing);
- /* The kernel only checks for KVM_IRQCHIP_NUM_PINS. */
- if (intid >= KVM_IRQCHIP_NUM_PINS)
+ /* The kernel only checks e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS */
+ if (((uint64_t)intid + num - 1 - MIN_SPI) >= KVM_IRQCHIP_NUM_PINS)
TEST_ASSERT(ret != 0 && errno == EINVAL,
"Bad intid %u did not cause KVM_SET_GSI_ROUTING "
"error: rc: %i errno: %i", intid, ret, errno);
--
2.34.1
From: Ricardo Koller <ricarkol(a)google.com>
[ Upstream commit cc94d47ce16d4147d546e47c8248e8bd12ba5fe5 ]
The val argument in gicv3_access_reg can have any value when used for a
read, not necessarily 0. Fix the assert by checking val only for
writes.
Signed-off-by: Ricardo Koller <ricarkol(a)google.com>
Reported-by: Reiji Watanabe <reijiw(a)google.com>
Cc: Andrew Jones <drjones(a)redhat.com>
Reviewed-by: Andrew Jones <drjones(a)redhat.com>
Signed-off-by: Marc Zyngier <maz(a)kernel.org>
Link: https://lore.kernel.org/r/20220127030858.3269036-2-ricarkol@google.com
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
---
tools/testing/selftests/kvm/lib/aarch64/gic_v3.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c b/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
index 00f613c0583c..e4945fe66620 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
@@ -159,7 +159,7 @@ static void gicv3_access_reg(uint32_t intid, uint64_t offset,
uint32_t cpu_or_dist;
GUEST_ASSERT(bits_per_field <= reg_bits);
- GUEST_ASSERT(*val < (1U << bits_per_field));
+ GUEST_ASSERT(!write || *val < (1U << bits_per_field));
/* Some registers like IROUTER are 64 bit long. Those are currently not
* supported by readl nor writel, so just asserting here until then.
*/
--
2.34.1
Hi,
This is a followup of my v1 at [0] and v2 at [1].
The short summary of the previous cover letter and discussions is that
HID could benefit from BPF for the following use cases:
- simple fixup of report descriptor:
benefits are faster development time and testing, with the produced
bpf program being shipped in the kernel directly (the shipping part
is *not* addressed here).
- Universal Stylus Interface:
allows a user-space program to define its own kernel interface
- Surface Dial:
somehow similar to the previous one except that userspace can decide
to change the shape of the exported device
- firewall:
still partly missing there, there is not yet interception of hidraw
calls, but it's coming in a followup series, I promise
- tracing:
well, tracing.
I think I addressed the comments from the previous version, but there are
a few things I'd like to note here:
- I did not take the various rev-by and tested-by (thanks a lot for those)
because the uapi changed significantly in v3, so I am not very confident
in taking those rev-by blindly
- I mentioned in my discussion with Song that I'll put a summary of the uapi
in the cover letter, but I ended up adding a (long) file in the Documentation
directory. So please maybe start by reading 17/17 to have an overview of
what I want to achieve
- I added in the libbpf and bpf the new type BPF_HID_DRIVER_EVENT, even though
I don't have a user of it right now in the kernel. I wanted to have them in
the docs, but we might not want to have them ready here.
In terms of code, it just means that we can attach such programs types
but that they will never get triggered.
Anyway, I have been mulling on this for the past 2 weeks, and I think that
maybe sharing this now is better than me just starring at the code over and
over.
Short summary of changes:
v3:
===
- squashed back together most of the libbpf and bpf changes into bigger
commits that give a better overview of the whole interactions
- reworked the user API to not expose .data as a directly accessible field
from the context, but instead forces everyone to use hid_bpf_get_data (or
get/set_bits)
- added BPF_HID_DRIVER_EVENT (see note above)
- addressed the various nitpicks from v2
- added a big Documentation file (and so adding now the doc maintainers to the
long list of recipients)
v2:
===
- split the series by subsystem (bpf, HID, libbpf, selftests and
samples)
- Added an extra patch at the beginning to not require CAP_NET_ADMIN for
BPF_PROG_TYPE_LIRC_MODE2 (please shout if this is wrong)
- made the bpf context attached to HID program of dynamic size:
* the first 1 kB will be able to be addressed directly
* the rest can be retrieved through bpf_hid_{set|get}_data
(note that I am definitivey not happy with that API, because there
is part of it in bits and other in bytes. ouch)
- added an extra patch to prevent non GPL HID bpf programs to be loaded
of type BPF_PROG_TYPE_HID
* same here, not really happy but I don't know where to put that check
in verifier.c
- added a new flag BPF_F_INSERT_HEAD for BPF_LINK_CREATE syscall when in
used with HID program types.
* this flag is used for tracing, to be able to load a program before
any others that might already have been inserted and that might
change the data stream.
Cheers,
Benjamin
[0] https://lore.kernel.org/linux-input/20220224110828.2168231-1-benjamin.tisso…
[1] https://lore.kernel.org/linux-input/20220304172852.274126-1-benjamin.tissoi…
Benjamin Tissoires (17):
bpf: add new is_sys_admin_prog_type() helper
bpf: introduce hid program type
bpf/verifier: prevent non GPL programs to be loaded against HID
libbpf: add HID program type and API
HID: hook up with bpf
HID: allow to change the report descriptor from an eBPF program
selftests/bpf: add tests for the HID-bpf initial implementation
selftests/bpf: add report descriptor fixup tests
selftests/bpf: Add a test for BPF_F_INSERT_HEAD
selftests/bpf: add test for user call of HID bpf programs
samples/bpf: add new hid_mouse example
bpf/hid: add more HID helpers
HID: bpf: implement hid_bpf_get|set_bits
HID: add implementation of bpf_hid_raw_request
selftests/bpf: add tests for hid_{get|set}_bits helpers
selftests/bpf: add tests for bpf_hid_hw_request
Documentation: add HID-BPF docs
Documentation/hid/hid-bpf.rst | 444 +++++++++++
Documentation/hid/index.rst | 1 +
drivers/hid/Makefile | 1 +
drivers/hid/hid-bpf.c | 328 ++++++++
drivers/hid/hid-core.c | 34 +-
include/linux/bpf-hid.h | 127 +++
include/linux/bpf_types.h | 4 +
include/linux/hid.h | 36 +-
include/uapi/linux/bpf.h | 67 ++
include/uapi/linux/bpf_hid.h | 71 ++
include/uapi/linux/hid.h | 10 +
kernel/bpf/Makefile | 3 +
kernel/bpf/btf.c | 1 +
kernel/bpf/hid.c | 728 +++++++++++++++++
kernel/bpf/syscall.c | 27 +-
kernel/bpf/verifier.c | 7 +
samples/bpf/.gitignore | 1 +
samples/bpf/Makefile | 4 +
samples/bpf/hid_mouse_kern.c | 117 +++
samples/bpf/hid_mouse_user.c | 129 +++
tools/include/uapi/linux/bpf.h | 67 ++
tools/lib/bpf/libbpf.c | 23 +-
tools/lib/bpf/libbpf.h | 2 +
tools/lib/bpf/libbpf.map | 1 +
tools/testing/selftests/bpf/config | 3 +
tools/testing/selftests/bpf/prog_tests/hid.c | 788 +++++++++++++++++++
tools/testing/selftests/bpf/progs/hid.c | 205 +++++
27 files changed, 3204 insertions(+), 25 deletions(-)
create mode 100644 Documentation/hid/hid-bpf.rst
create mode 100644 drivers/hid/hid-bpf.c
create mode 100644 include/linux/bpf-hid.h
create mode 100644 include/uapi/linux/bpf_hid.h
create mode 100644 kernel/bpf/hid.c
create mode 100644 samples/bpf/hid_mouse_kern.c
create mode 100644 samples/bpf/hid_mouse_user.c
create mode 100644 tools/testing/selftests/bpf/prog_tests/hid.c
create mode 100644 tools/testing/selftests/bpf/progs/hid.c
--
2.35.1
Hi Team,
Can anyone help me on this ? Hope you will do the needful as soon as possible.
Regards
Sarath P T
From: P T, Sarath
Sent: 14 March 2022 13:19
To: 'linux-kselftest-mirror(a)lists.linaro.org' <linux-kselftest-mirror(a)lists.linaro.org>
Subject: clarification on tap_timeout function
Hi Team,
I need a clarification the function "tap_timeout" which is being used in the runner.sh , the one will give the result format in the TAP 13 protocol. Below I am giving the function.
tap_timeout()
{
# Make sure tests will time out if utility is available.
if [ -x /usr/bin/timeout ] ; then
/usr/bin/timeout --foreground "$kselftest_timeout" "$1"
else
"$1"
fi
}
Need a clarification why we are using the function "tap_timout" and why the "kselftest_timeout" variable declared as 45 seconds by default. It will be very helpful if you are clarifying these things for me.
Regards
Sarath PT
Before Linux 5.17, there was a problem with the CMOS RTC driver:
cmos_read_alarm() and cmos_set_alarm() did not check for the UIP (Update
in progress) bit, which could have caused it to sometimes fail silently
and read bogus values or do not set the alarm correctly.
Luckily, this issue was masked by cmos_read_time() invocations in core
RTC code - see https://marc.info/?l=linux-rtc&m=164858416511425&w=4
To avoid such a problem in the future in some other driver, I wrote a
test unit that reads the alarm time many times in a row. As the alarm
time is usually read once and cached by the RTC core, this requires a
way for userspace to trigger direct alarm time read from hardware. I
think that debugfs is the natural choice for this.
So, introduce /sys/kernel/debug/rtc/rtcX/wakealarm_raw. This interface
as implemented here does not seem to be that useful to userspace, so
there is little risk that it will become kernel ABI.
Is this approach correct and worth it?
TODO:
- should I add a new Kconfig option (like CONFIG_RTC_INTF_DEBUGFS), or
just use CONFIG_DEBUG_FS here? I wouldn't like to create unnecessary
config options in the kernel.
Signed-off-by: Mateusz Jończyk <mat.jonczyk(a)o2.pl>
Cc: Alessandro Zummo <a.zummo(a)towertech.it>
Cc: Alexandre Belloni <alexandre.belloni(a)bootlin.com>
Cc: Shuah Khan <shuah(a)kernel.org>
---
drivers/rtc/Makefile | 1 +
drivers/rtc/class.c | 3 ++
drivers/rtc/debugfs.c | 112 ++++++++++++++++++++++++++++++++++++++++
drivers/rtc/interface.c | 3 +-
include/linux/rtc.h | 16 ++++++
5 files changed, 133 insertions(+), 2 deletions(-)
create mode 100644 drivers/rtc/debugfs.c
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 678a8ef4abae..50e166a97f54 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -14,6 +14,7 @@ rtc-core-$(CONFIG_RTC_NVMEM) += nvmem.o
rtc-core-$(CONFIG_RTC_INTF_DEV) += dev.o
rtc-core-$(CONFIG_RTC_INTF_PROC) += proc.o
rtc-core-$(CONFIG_RTC_INTF_SYSFS) += sysfs.o
+rtc-core-$(CONFIG_DEBUG_FS) += debugfs.o
obj-$(CONFIG_RTC_LIB_KUNIT_TEST) += lib_test.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 4b460c61f1d8..5673b7b26c0d 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -334,6 +334,7 @@ static void devm_rtc_unregister_device(void *data)
* Remove innards of this RTC, then disable it, before
* letting any rtc_class_open() users access it again
*/
+ rtc_debugfs_del_device(rtc);
rtc_proc_del_device(rtc);
if (!test_bit(RTC_NO_CDEV, &rtc->flags))
cdev_device_del(&rtc->char_dev, &rtc->dev);
@@ -417,6 +418,7 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
}
rtc_proc_add_device(rtc);
+ rtc_debugfs_add_device(rtc);
dev_info(rtc->dev.parent, "registered as %s\n",
dev_name(&rtc->dev));
@@ -476,6 +478,7 @@ static int __init rtc_init(void)
}
rtc_class->pm = RTC_CLASS_DEV_PM_OPS;
rtc_dev_init();
+ rtc_debugfs_init();
return 0;
}
subsys_initcall(rtc_init);
diff --git a/drivers/rtc/debugfs.c b/drivers/rtc/debugfs.c
new file mode 100644
index 000000000000..5ceed5504033
--- /dev/null
+++ b/drivers/rtc/debugfs.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Debugfs interface for testing RTC alarms.
+ */
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/rtc.h>
+
+static struct dentry *rtc_main_debugfs_dir;
+
+void rtc_debugfs_init(void)
+{
+ struct dentry *ret = debugfs_create_dir("rtc", NULL);
+
+ // No error is critical here
+ if (!IS_ERR(ret))
+ rtc_main_debugfs_dir = ret;
+}
+
+/*
+ * Handler for /sys/kernel/debug/rtc/rtcX/wakealarm_raw .
+ * This function reads the RTC alarm time directly from hardware. If the RTC
+ * alarm is enabled, this function returns the alarm time modulo 24h in seconds
+ * since midnight.
+ *
+ * Should be only used for testing of the RTC alarm read functionality in
+ * drivers - to make sure that the driver returns consistent values.
+ *
+ * Used in tools/testing/selftests/rtc/rtctest.c .
+ */
+static int rtc_debugfs_alarm_read(void *p, u64 *out)
+{
+ int ret;
+ struct rtc_device *rtc = p;
+ struct rtc_wkalrm alm;
+
+ /* Using rtc_read_alarm_internal() instead of __rtc_read_alarm() will
+ * allow us to avoid any interaction with rtc_read_time() and possibly
+ * see more issues.
+ */
+ ret = rtc_read_alarm_internal(rtc, &alm);
+ if (ret != 0)
+ return ret;
+
+ if (!alm.enabled) {
+ *out = -1;
+ return 0;
+ }
+
+ /* It does not matter if the device does not support seconds resolution
+ * of the RTC alarm.
+ */
+ if (test_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features))
+ alm.time.tm_sec = 0;
+
+ /* The selftest code works with fully defined alarms only.
+ */
+ if (alm.time.tm_sec == -1 || alm.time.tm_min == -1 || alm.time.tm_hour == -1) {
+ *out = -2;
+ return 0;
+ }
+
+ /* Check if the alarm time is correct.
+ * rtc_valid_tm() does not allow fields containing "-1", so put in
+ * something to satisfy it.
+ */
+ if (alm.time.tm_year == -1)
+ alm.time.tm_year = 100;
+ if (alm.time.tm_mon == -1)
+ alm.time.tm_mon = 0;
+ if (alm.time.tm_mday == -1)
+ alm.time.tm_mday = 1;
+ if (rtc_valid_tm(&alm.time))
+ return -EINVAL;
+
+ /* We do not duplicate the logic in __rtc_read_alarm() and instead only
+ * return the alarm time modulo 24h, which all devices should support.
+ * This should be enough for testing purposes.
+ */
+ *out = alm.time.tm_hour * 3600 + alm.time.tm_min * 60 + alm.time.tm_sec;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(rtc_alarm_raw, rtc_debugfs_alarm_read, NULL, "%lld\n");
+
+void rtc_debugfs_add_device(struct rtc_device *rtc)
+{
+ struct dentry *dev_dir;
+
+ if (!rtc_main_debugfs_dir)
+ return;
+
+ dev_dir = debugfs_create_dir(dev_name(&rtc->dev), rtc_main_debugfs_dir);
+
+ if (IS_ERR(dev_dir)) {
+ rtc->debugfs_dir = NULL;
+ return;
+ }
+ rtc->debugfs_dir = dev_dir;
+
+ if (test_bit(RTC_FEATURE_ALARM, rtc->features) && rtc->ops->read_alarm) {
+ debugfs_create_file("wakealarm_raw", 0444, dev_dir,
+ rtc, &rtc_alarm_raw);
+ }
+}
+
+void rtc_debugfs_del_device(struct rtc_device *rtc)
+{
+ debugfs_remove_recursive(rtc->debugfs_dir);
+ rtc->debugfs_dir = NULL;
+}
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index d8e835798153..51c801c82472 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -175,8 +175,7 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
}
EXPORT_SYMBOL_GPL(rtc_set_time);
-static int rtc_read_alarm_internal(struct rtc_device *rtc,
- struct rtc_wkalrm *alarm)
+int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
int err;
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 47fd1c2d3a57..4665bc238a94 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -41,6 +41,7 @@ static inline time64_t rtc_tm_sub(struct rtc_time *lhs, struct rtc_time *rhs)
#include <linux/mutex.h>
#include <linux/timerqueue.h>
#include <linux/workqueue.h>
+#include <linux/debugfs.h>
extern struct class *rtc_class;
@@ -152,6 +153,10 @@ struct rtc_device {
time64_t offset_secs;
bool set_start_time;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_dir;
+#endif
+
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
struct work_struct uie_task;
struct timer_list uie_timer;
@@ -190,6 +195,7 @@ extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
extern int rtc_read_alarm(struct rtc_device *rtc,
struct rtc_wkalrm *alrm);
+int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
extern int rtc_set_alarm(struct rtc_device *rtc,
struct rtc_wkalrm *alrm);
extern int rtc_initialize_alarm(struct rtc_device *rtc,
@@ -262,4 +268,14 @@ int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
return 0;
}
#endif
+
+#ifdef CONFIG_DEBUG_FS
+void rtc_debugfs_init(void);
+void rtc_debugfs_add_device(struct rtc_device *rtc);
+void rtc_debugfs_del_device(struct rtc_device *rtc);
+#else /* CONFIG_DEBUG_FS */
+static inline void rtc_debugfs_init(void) {}
+static inline void rtc_debugfs_add_device(struct rtc_device *rtc) {}
+static inline void rtc_debugfs_del_device(struct rtc_device *rtc) {}
+#endif /* CONFIG_DEBUG_FS */
#endif /* _LINUX_RTC_H_ */
--
2.25.1
Print two possible reasons /sys/kernel/debug/gup_test
cannot be opened to help users of this test diagnose
failures.
Signed-off-by: Sidhartha Kumar <sidhartha.kumar(a)oracle.com>
Cc: stable(a)vger.kernel.org # 5.15+
---
tools/testing/selftests/vm/gup_test.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/vm/gup_test.c b/tools/testing/selftests/vm/gup_test.c
index fe043f67798b0..c496bcefa7a0e 100644
--- a/tools/testing/selftests/vm/gup_test.c
+++ b/tools/testing/selftests/vm/gup_test.c
@@ -205,7 +205,9 @@ int main(int argc, char **argv)
gup_fd = open("/sys/kernel/debug/gup_test", O_RDWR);
if (gup_fd == -1) {
- perror("open");
+ perror("failed to open /sys/kernel/debug/gup_test");
+ printf("check if CONFIG_GUP_TEST is enabled in kernel config\n");
+ printf("check if debugfs is mounted at /sys/kernel/debug\n");
exit(1);
}
--
2.24.1
On 3/30/2022 12:03 PM, Jarkko Sakkinen wrote:
> On Wed, 2022-03-30 at 10:40 -0700, Reinette Chatre wrote:
>> Could you please elaborate how the compiler will fix it up?
>
> Sure.
>
> Here's the disassembly of the RBX version:
>
> [0x000021a9]> pi 1
> lea rax, [rbx + loc.encl_stack]
>
> Here's the same with s/RBX/RIP/:
>
> [0x000021a9]> pi 5
> lea rax, loc.encl_stack
>
> Compiler will substitute correct offset relative to the RIP,
> well, because it can and it makes sense.
It does not make sense to me because, as proven with my test,
the two threads end up sharing the same stack memory.
Reinette
Simplify the test_encl_bootstrap.S flow by using rip-relative addressing.
Compiler does the right thing here, and this removes dependency on where
TCS entries need to be located in the binary, i.e. allows the binary layout
changed freely in the future.
Cc: Reinette Chatre <reinette.chatre(a)intel.com>
Cc: Dave Hansen <dave.hansen(a)linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko(a)kernel.org>
---
tools/testing/selftests/sgx/test_encl_bootstrap.S | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/tools/testing/selftests/sgx/test_encl_bootstrap.S b/tools/testing/selftests/sgx/test_encl_bootstrap.S
index 82fb0dfcbd23..1c1b5c6c4ffe 100644
--- a/tools/testing/selftests/sgx/test_encl_bootstrap.S
+++ b/tools/testing/selftests/sgx/test_encl_bootstrap.S
@@ -40,11 +40,7 @@
.text
encl_entry:
- # RBX contains the base address for TCS, which is the first address
- # inside the enclave for TCS #1 and one page into the enclave for
- # TCS #2. By adding the value of encl_stack to it, we get
- # the absolute address for the stack.
- lea (encl_stack)(%rbx), %rax
+ lea (encl_stack)(%rip), %rax
xchg %rsp, %rax
push %rax
--
2.35.1
Beste begunstigde,
Je hebt een liefdadigheidsdonatie van ($ 10.000.000,00) van Mr. Mike Weirsky, een winnaar van een powerball-jackpotloterij van $ 273 miljoen. Ik doneer aan 5 willekeurige personen als je deze e-mail ontvangt, dan is je e-mail geselecteerd na een spin-ball. Ik heb vrijwillig besloten om het bedrag van $ 10 miljoen USD aan jou te doneren als een van de geselecteerde 5, om mijn winst te verifiëren
Vriendelijk antwoord op: mike.weirsky.foundation003(a)gmail.com
Voor uw claim.
Commit ddbd60c779b4 ("kunit: use --build_dir=.kunit as default") changed
the default --build_dir, which had the side effect of making
`.kunitconfig` move to `.kunit/.kunitconfig`.
However, the first few lines of kunit/start.rst never got updated, oops.
Fix this by telling people to run kunit.py first, which will
automatically generate the .kunit directory and .kunitconfig file, and
then edit the file manually as desired.
Reported-by: Yifan Yuan <alpc_metic(a)live.com>
Signed-off-by: Daniel Latypov <dlatypov(a)google.com>
---
v1 -> v2: rebase onto 5.17 (had the kunit docs rewrite)
---
Documentation/dev-tools/kunit/start.rst | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Documentation/dev-tools/kunit/start.rst b/Documentation/dev-tools/kunit/start.rst
index ad168d16968f..867a4bba6bf6 100644
--- a/Documentation/dev-tools/kunit/start.rst
+++ b/Documentation/dev-tools/kunit/start.rst
@@ -41,13 +41,18 @@ or ``VFAT_FS``. To run ``FAT_KUNIT_TEST``, the ``.kunitconfig`` has:
CONFIG_MSDOS_FS=y
CONFIG_FAT_KUNIT_TEST=y
-1. A good starting point for the ``.kunitconfig``, is the KUnit default
- config. Run the command:
+1. A good starting point for the ``.kunitconfig`` is the KUnit default config.
+ You can generate it by running:
.. code-block:: bash
cd $PATH_TO_LINUX_REPO
- cp tools/testing/kunit/configs/default.config .kunitconfig
+ tools/testing/kunit/kunit.py config
+ cat .kunit/.kunitconfig
+
+.. note ::
+ ``.kunitconfig`` lives in the ``--build_dir`` used by kunit.py, which is
+ ``.kunit`` by default.
.. note ::
You may want to remove CONFIG_KUNIT_ALL_TESTS from the ``.kunitconfig`` as
base-commit: c2741453478badf571ef020d160053e8d5e1ba94
--
2.35.0.rc2.247.g8bbb082509-goog
From: Yang Guang <yang.guang5(a)zte.com.cn>
Running the seccomp tests under the kernel with "defconfig"
shouldn't fail. Because the CONFIG_USER_NS is not support
in "defconfig". So skip this test case is better.
Signed-off-by: Yang Guang <yang.guang5(a)zte.com.cn>
Signed-off-by: David Yang <davidcomponentone(a)gmail.com>
---
tools/testing/selftests/seccomp/seccomp_bpf.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 313bb0cbfb1e..e9a61cb2eb88 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -3742,7 +3742,10 @@ TEST(user_notification_fault_recv)
struct seccomp_notif req = {};
struct seccomp_notif_resp resp = {};
- ASSERT_EQ(unshare(CLONE_NEWUSER), 0);
+ ASSERT_EQ(unshare(CLONE_NEWUSER), 0) {
+ if (errno == EINVAL)
+ SKIP(return, "kernel missing CLONE_NEWUSER support");
+ }
listener = user_notif_syscall(__NR_getppid,
SECCOMP_FILTER_FLAG_NEW_LISTENER);
--
2.30.2
The Architecture chapter of the KUnit documentation tried to include
copies of the kernel-doc for a couple of things, despite these already
existing in the API documentation. This lead to some warnings:
architecture:31: ./include/kunit/test.h:3: WARNING: Duplicate C declaration, also defined at dev-tools/kunit/api/test:66.
Declaration is '.. c:struct:: kunit_case'.
architecture:163: ./include/kunit/test.h:1217: WARNING: Duplicate C declaration, also defined at dev-tools/kunit/api/test:1217.
Declaration is '.. c:macro:: KUNIT_ARRAY_PARAM'.
architecture.rst:3: WARNING: Duplicate C declaration, also defined at dev-tools/kunit/api/test:66.
Declaration is '.. c:struct:: kunit_case'.
architecture.rst:1217: WARNING: Duplicate C declaration, also defined at dev-tools/kunit/api/test:1217.
Declaration is '.. c:macro:: KUNIT_ARRAY_PARAM'.
Get rid of these, and cleanup the mentions of the struct and macro in
question so that sphinx generates a link to the existing copy of the
documentation in the api/test document.
Fixes: bc145b370c ("Documentation: KUnit: Added KUnit Architecture")
Signed-off-by: David Gow <davidgow(a)google.com>
---
Documentation/dev-tools/kunit/architecture.rst | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/Documentation/dev-tools/kunit/architecture.rst b/Documentation/dev-tools/kunit/architecture.rst
index aa2cea821e25..ff9c85a0bff2 100644
--- a/Documentation/dev-tools/kunit/architecture.rst
+++ b/Documentation/dev-tools/kunit/architecture.rst
@@ -26,10 +26,7 @@ The fundamental unit in KUnit is the test case. The KUnit test cases are
grouped into KUnit suites. A KUnit test case is a function with type
signature ``void (*)(struct kunit *test)``.
These test case functions are wrapped in a struct called
-``struct kunit_case``. For code, see:
-
-.. kernel-doc:: include/kunit/test.h
- :identifiers: kunit_case
+struct kunit_case.
.. note:
``generate_params`` is optional for non-parameterized tests.
@@ -152,18 +149,12 @@ Parameterized Tests
Each KUnit parameterized test is associated with a collection of
parameters. The test is invoked multiple times, once for each parameter
value and the parameter is stored in the ``param_value`` field.
-The test case includes a ``KUNIT_CASE_PARAM()`` macro that accepts a
+The test case includes a KUNIT_CASE_PARAM() macro that accepts a
generator function.
The generator function is passed the previous parameter and returns the next
parameter. It also provides a macro to generate common-case generators based on
arrays.
-For code, see:
-
-.. kernel-doc:: include/kunit/test.h
- :identifiers: KUNIT_ARRAY_PARAM
-
-
kunit_tool (Command Line Test Harness)
======================================
--
2.35.1.1021.g381101b075-goog
Recent changes have made it so the current set is not sufficient.
Namely, CONFIG_DEBUG_INFO is not being set even when explicitly asked.
Specifying a version of the debug info fixes this.
Pick CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT as an option that's
hopefully less fragile (esp. given we're tied to GCC 6 and lower).
Signed-off-by: Daniel Latypov <dlatypov(a)google.com>
---
Documentation/dev-tools/kunit/running_tips.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Documentation/dev-tools/kunit/running_tips.rst b/Documentation/dev-tools/kunit/running_tips.rst
index 7b6d26a25959..c36f6760087d 100644
--- a/Documentation/dev-tools/kunit/running_tips.rst
+++ b/Documentation/dev-tools/kunit/running_tips.rst
@@ -114,6 +114,7 @@ Instead of enabling ``CONFIG_GCOV_KERNEL=y``, we can set these options:
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
+ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_GCOV=y
@@ -122,7 +123,7 @@ Putting it together into a copy-pastable sequence of commands:
.. code-block:: bash
# Append coverage options to the current config
- $ echo -e "CONFIG_DEBUG_KERNEL=y\nCONFIG_DEBUG_INFO=y\nCONFIG_GCOV=y" >> .kunit/.kunitconfig
+ $ echo -e "CONFIG_DEBUG_KERNEL=y\nCONFIG_DEBUG_INFO=y\nCONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y\nCONFIG_GCOV=y" >> .kunit/.kunitconfig
$ ./tools/testing/kunit/kunit.py run
# Extract the coverage information from the build dir (.kunit/)
$ lcov -t "my_kunit_tests" -o coverage.info -c -d .kunit/
base-commit: b14ffae378aa1db993e62b01392e70d1e585fb23
--
2.35.1.1021.g381101b075-goog
Background:
Currently, a reader looking at kunit/test.h will find the file is quite
long, and the first meaty comment is a doc comment about struct
kunit_resource.
Most users will not ever use the KUnit resource API directly.
They'll use kunit_kmalloc() and friends, or decide it's simpler to do
cleanups via labels (it often can be) instead of figuring out how to use
the API.
It's also logically separate from everything else in test.h.
Removing it from the file doesn't cause any compilation errors (since
struct kunit has `struct list_head resources` to store them).
This commit:
Let's move it into a kunit/resource.h file and give it a separate page
in the docs, kunit/api/resource.rst.
We include resource.h at the bottom of test.h since
* don't want to force existing users to add a new include if they use the API
* it accesses `lock` inside `struct kunit` in a inline func
* so we can't just forward declare, and the alternatives require
uninlining the func, adding hepers to lock/unlock, or other more
invasive changes.
Now the first big comment in test.h is about kunit_case, which is a lot
more relevant to what a new user wants to know.
A side effect of this is git blame won't properly track history by
default, users need to run
$ git blame -L ,1 -C17 include/kunit/resource.h
Signed-off-by: Daniel Latypov <dlatypov(a)google.com>
Reviewed-by: David Gow <davidgow(a)google.com>
Reviewed-by: Brendan Higgins <brendanhiggins(a)google.com>
---
v1 -> v2: add TODO to make users #include resource.h, drop redundant fwd
decl of struct kunit in resource.h
v2 -> v3: no change.
---
Documentation/dev-tools/kunit/api/index.rst | 5 +
.../dev-tools/kunit/api/resource.rst | 13 +
include/kunit/resource.h | 318 ++++++++++++++++++
include/kunit/test.h | 303 +----------------
4 files changed, 340 insertions(+), 299 deletions(-)
create mode 100644 Documentation/dev-tools/kunit/api/resource.rst
create mode 100644 include/kunit/resource.h
diff --git a/Documentation/dev-tools/kunit/api/index.rst b/Documentation/dev-tools/kunit/api/index.rst
index 3006cadcf44a..45ce04823f9f 100644
--- a/Documentation/dev-tools/kunit/api/index.rst
+++ b/Documentation/dev-tools/kunit/api/index.rst
@@ -6,6 +6,7 @@ API Reference
.. toctree::
test
+ resource
This section documents the KUnit kernel testing API. It is divided into the
following sections:
@@ -13,3 +14,7 @@ following sections:
Documentation/dev-tools/kunit/api/test.rst
- documents all of the standard testing API
+
+Documentation/dev-tools/kunit/api/resource.rst
+
+ - documents the KUnit resource API
diff --git a/Documentation/dev-tools/kunit/api/resource.rst b/Documentation/dev-tools/kunit/api/resource.rst
new file mode 100644
index 000000000000..0a94f831259e
--- /dev/null
+++ b/Documentation/dev-tools/kunit/api/resource.rst
@@ -0,0 +1,13 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+Resource API
+============
+
+This file documents the KUnit resource API.
+
+Most users won't need to use this API directly, power users can use it to store
+state on a per-test basis, register custom cleanup actions, and more.
+
+.. kernel-doc:: include/kunit/resource.h
+ :internal:
diff --git a/include/kunit/resource.h b/include/kunit/resource.h
new file mode 100644
index 000000000000..7ab1fd83972b
--- /dev/null
+++ b/include/kunit/resource.h
@@ -0,0 +1,318 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KUnit resource API for test managed resources (allocations, etc.).
+ *
+ * Copyright (C) 2022, Google LLC.
+ * Author: Daniel Latypov <dlatypov(a)google.com>
+ */
+
+#ifndef _KUNIT_RESOURCE_H
+#define _KUNIT_RESOURCE_H
+
+#include <kunit/test.h>
+
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct kunit_resource;
+
+typedef int (*kunit_resource_init_t)(struct kunit_resource *, void *);
+typedef void (*kunit_resource_free_t)(struct kunit_resource *);
+
+/**
+ * struct kunit_resource - represents a *test managed resource*
+ * @data: for the user to store arbitrary data.
+ * @name: optional name
+ * @free: a user supplied function to free the resource. Populated by
+ * kunit_resource_alloc().
+ *
+ * Represents a *test managed resource*, a resource which will automatically be
+ * cleaned up at the end of a test case.
+ *
+ * Resources are reference counted so if a resource is retrieved via
+ * kunit_alloc_and_get_resource() or kunit_find_resource(), we need
+ * to call kunit_put_resource() to reduce the resource reference count
+ * when finished with it. Note that kunit_alloc_resource() does not require a
+ * kunit_resource_put() because it does not retrieve the resource itself.
+ *
+ * Example:
+ *
+ * .. code-block:: c
+ *
+ * struct kunit_kmalloc_params {
+ * size_t size;
+ * gfp_t gfp;
+ * };
+ *
+ * static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
+ * {
+ * struct kunit_kmalloc_params *params = context;
+ * res->data = kmalloc(params->size, params->gfp);
+ *
+ * if (!res->data)
+ * return -ENOMEM;
+ *
+ * return 0;
+ * }
+ *
+ * static void kunit_kmalloc_free(struct kunit_resource *res)
+ * {
+ * kfree(res->data);
+ * }
+ *
+ * void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
+ * {
+ * struct kunit_kmalloc_params params;
+ *
+ * params.size = size;
+ * params.gfp = gfp;
+ *
+ * return kunit_alloc_resource(test, kunit_kmalloc_init,
+ * kunit_kmalloc_free, ¶ms);
+ * }
+ *
+ * Resources can also be named, with lookup/removal done on a name
+ * basis also. kunit_add_named_resource(), kunit_find_named_resource()
+ * and kunit_destroy_named_resource(). Resource names must be
+ * unique within the test instance.
+ */
+struct kunit_resource {
+ void *data;
+ const char *name;
+ kunit_resource_free_t free;
+
+ /* private: internal use only. */
+ struct kref refcount;
+ struct list_head node;
+};
+
+/*
+ * Like kunit_alloc_resource() below, but returns the struct kunit_resource
+ * object that contains the allocation. This is mostly for testing purposes.
+ */
+struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ gfp_t internal_gfp,
+ void *context);
+
+/**
+ * kunit_get_resource() - Hold resource for use. Should not need to be used
+ * by most users as we automatically get resources
+ * retrieved by kunit_find_resource*().
+ * @res: resource
+ */
+static inline void kunit_get_resource(struct kunit_resource *res)
+{
+ kref_get(&res->refcount);
+}
+
+/*
+ * Called when refcount reaches zero via kunit_put_resource();
+ * should not be called directly.
+ */
+static inline void kunit_release_resource(struct kref *kref)
+{
+ struct kunit_resource *res = container_of(kref, struct kunit_resource,
+ refcount);
+
+ /* If free function is defined, resource was dynamically allocated. */
+ if (res->free) {
+ res->free(res);
+ kfree(res);
+ }
+}
+
+/**
+ * kunit_put_resource() - When caller is done with retrieved resource,
+ * kunit_put_resource() should be called to drop
+ * reference count. The resource list maintains
+ * a reference count on resources, so if no users
+ * are utilizing a resource and it is removed from
+ * the resource list, it will be freed via the
+ * associated free function (if any). Only
+ * needs to be used if we alloc_and_get() or
+ * find() resource.
+ * @res: resource
+ */
+static inline void kunit_put_resource(struct kunit_resource *res)
+{
+ kref_put(&res->refcount, kunit_release_resource);
+}
+
+/**
+ * kunit_add_resource() - Add a *test managed resource*.
+ * @test: The test context object.
+ * @init: a user-supplied function to initialize the result (if needed). If
+ * none is supplied, the resource data value is simply set to @data.
+ * If an init function is supplied, @data is passed to it instead.
+ * @free: a user-supplied function to free the resource (if needed).
+ * @res: The resource.
+ * @data: value to pass to init function or set in resource data field.
+ */
+int kunit_add_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ struct kunit_resource *res,
+ void *data);
+
+/**
+ * kunit_add_named_resource() - Add a named *test managed resource*.
+ * @test: The test context object.
+ * @init: a user-supplied function to initialize the resource data, if needed.
+ * @free: a user-supplied function to free the resource data, if needed.
+ * @res: The resource.
+ * @name: name to be set for resource.
+ * @data: value to pass to init function or set in resource data field.
+ */
+int kunit_add_named_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ struct kunit_resource *res,
+ const char *name,
+ void *data);
+
+/**
+ * kunit_alloc_resource() - Allocates a *test managed resource*.
+ * @test: The test context object.
+ * @init: a user supplied function to initialize the resource.
+ * @free: a user supplied function to free the resource.
+ * @internal_gfp: gfp to use for internal allocations, if unsure, use GFP_KERNEL
+ * @context: for the user to pass in arbitrary data to the init function.
+ *
+ * Allocates a *test managed resource*, a resource which will automatically be
+ * cleaned up at the end of a test case. See &struct kunit_resource for an
+ * example.
+ *
+ * Note: KUnit needs to allocate memory for a kunit_resource object. You must
+ * specify an @internal_gfp that is compatible with the use context of your
+ * resource.
+ */
+static inline void *kunit_alloc_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ gfp_t internal_gfp,
+ void *context)
+{
+ struct kunit_resource *res;
+
+ res = kzalloc(sizeof(*res), internal_gfp);
+ if (!res)
+ return NULL;
+
+ if (!kunit_add_resource(test, init, free, res, context))
+ return res->data;
+
+ return NULL;
+}
+
+typedef bool (*kunit_resource_match_t)(struct kunit *test,
+ struct kunit_resource *res,
+ void *match_data);
+
+/**
+ * kunit_resource_instance_match() - Match a resource with the same instance.
+ * @test: Test case to which the resource belongs.
+ * @res: The resource.
+ * @match_data: The resource pointer to match against.
+ *
+ * An instance of kunit_resource_match_t that matches a resource whose
+ * allocation matches @match_data.
+ */
+static inline bool kunit_resource_instance_match(struct kunit *test,
+ struct kunit_resource *res,
+ void *match_data)
+{
+ return res->data == match_data;
+}
+
+/**
+ * kunit_resource_name_match() - Match a resource with the same name.
+ * @test: Test case to which the resource belongs.
+ * @res: The resource.
+ * @match_name: The name to match against.
+ */
+static inline bool kunit_resource_name_match(struct kunit *test,
+ struct kunit_resource *res,
+ void *match_name)
+{
+ return res->name && strcmp(res->name, match_name) == 0;
+}
+
+/**
+ * kunit_find_resource() - Find a resource using match function/data.
+ * @test: Test case to which the resource belongs.
+ * @match: match function to be applied to resources/match data.
+ * @match_data: data to be used in matching.
+ */
+static inline struct kunit_resource *
+kunit_find_resource(struct kunit *test,
+ kunit_resource_match_t match,
+ void *match_data)
+{
+ struct kunit_resource *res, *found = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&test->lock, flags);
+
+ list_for_each_entry_reverse(res, &test->resources, node) {
+ if (match(test, res, (void *)match_data)) {
+ found = res;
+ kunit_get_resource(found);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&test->lock, flags);
+
+ return found;
+}
+
+/**
+ * kunit_find_named_resource() - Find a resource using match name.
+ * @test: Test case to which the resource belongs.
+ * @name: match name.
+ */
+static inline struct kunit_resource *
+kunit_find_named_resource(struct kunit *test,
+ const char *name)
+{
+ return kunit_find_resource(test, kunit_resource_name_match,
+ (void *)name);
+}
+
+/**
+ * kunit_destroy_resource() - Find a kunit_resource and destroy it.
+ * @test: Test case to which the resource belongs.
+ * @match: Match function. Returns whether a given resource matches @match_data.
+ * @match_data: Data passed into @match.
+ *
+ * RETURNS:
+ * 0 if kunit_resource is found and freed, -ENOENT if not found.
+ */
+int kunit_destroy_resource(struct kunit *test,
+ kunit_resource_match_t match,
+ void *match_data);
+
+static inline int kunit_destroy_named_resource(struct kunit *test,
+ const char *name)
+{
+ return kunit_destroy_resource(test, kunit_resource_name_match,
+ (void *)name);
+}
+
+/**
+ * kunit_remove_resource() - remove resource from resource list associated with
+ * test.
+ * @test: The test context object.
+ * @res: The resource to be removed.
+ *
+ * Note that the resource will not be immediately freed since it is likely
+ * the caller has a reference to it via alloc_and_get() or find();
+ * in this case a final call to kunit_put_resource() is required.
+ */
+void kunit_remove_resource(struct kunit *test, struct kunit_resource *res);
+
+#endif /* _KUNIT_RESOURCE_H */
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 00b9ff7783ab..d04f9e2fd5e7 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -27,78 +27,6 @@
#include <asm/rwonce.h>
-struct kunit_resource;
-
-typedef int (*kunit_resource_init_t)(struct kunit_resource *, void *);
-typedef void (*kunit_resource_free_t)(struct kunit_resource *);
-
-/**
- * struct kunit_resource - represents a *test managed resource*
- * @data: for the user to store arbitrary data.
- * @name: optional name
- * @free: a user supplied function to free the resource. Populated by
- * kunit_resource_alloc().
- *
- * Represents a *test managed resource*, a resource which will automatically be
- * cleaned up at the end of a test case.
- *
- * Resources are reference counted so if a resource is retrieved via
- * kunit_alloc_and_get_resource() or kunit_find_resource(), we need
- * to call kunit_put_resource() to reduce the resource reference count
- * when finished with it. Note that kunit_alloc_resource() does not require a
- * kunit_resource_put() because it does not retrieve the resource itself.
- *
- * Example:
- *
- * .. code-block:: c
- *
- * struct kunit_kmalloc_params {
- * size_t size;
- * gfp_t gfp;
- * };
- *
- * static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
- * {
- * struct kunit_kmalloc_params *params = context;
- * res->data = kmalloc(params->size, params->gfp);
- *
- * if (!res->data)
- * return -ENOMEM;
- *
- * return 0;
- * }
- *
- * static void kunit_kmalloc_free(struct kunit_resource *res)
- * {
- * kfree(res->data);
- * }
- *
- * void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
- * {
- * struct kunit_kmalloc_params params;
- *
- * params.size = size;
- * params.gfp = gfp;
- *
- * return kunit_alloc_resource(test, kunit_kmalloc_init,
- * kunit_kmalloc_free, ¶ms);
- * }
- *
- * Resources can also be named, with lookup/removal done on a name
- * basis also. kunit_add_named_resource(), kunit_find_named_resource()
- * and kunit_destroy_named_resource(). Resource names must be
- * unique within the test instance.
- */
-struct kunit_resource {
- void *data;
- const char *name;
- kunit_resource_free_t free;
-
- /* private: internal use only. */
- struct kref refcount;
- struct list_head node;
-};
-
struct kunit;
/* Size of log associated with test. */
@@ -385,233 +313,6 @@ static inline int kunit_run_all_tests(void)
enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite);
-/*
- * Like kunit_alloc_resource() below, but returns the struct kunit_resource
- * object that contains the allocation. This is mostly for testing purposes.
- */
-struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- gfp_t internal_gfp,
- void *context);
-
-/**
- * kunit_get_resource() - Hold resource for use. Should not need to be used
- * by most users as we automatically get resources
- * retrieved by kunit_find_resource*().
- * @res: resource
- */
-static inline void kunit_get_resource(struct kunit_resource *res)
-{
- kref_get(&res->refcount);
-}
-
-/*
- * Called when refcount reaches zero via kunit_put_resources();
- * should not be called directly.
- */
-static inline void kunit_release_resource(struct kref *kref)
-{
- struct kunit_resource *res = container_of(kref, struct kunit_resource,
- refcount);
-
- /* If free function is defined, resource was dynamically allocated. */
- if (res->free) {
- res->free(res);
- kfree(res);
- }
-}
-
-/**
- * kunit_put_resource() - When caller is done with retrieved resource,
- * kunit_put_resource() should be called to drop
- * reference count. The resource list maintains
- * a reference count on resources, so if no users
- * are utilizing a resource and it is removed from
- * the resource list, it will be freed via the
- * associated free function (if any). Only
- * needs to be used if we alloc_and_get() or
- * find() resource.
- * @res: resource
- */
-static inline void kunit_put_resource(struct kunit_resource *res)
-{
- kref_put(&res->refcount, kunit_release_resource);
-}
-
-/**
- * kunit_add_resource() - Add a *test managed resource*.
- * @test: The test context object.
- * @init: a user-supplied function to initialize the result (if needed). If
- * none is supplied, the resource data value is simply set to @data.
- * If an init function is supplied, @data is passed to it instead.
- * @free: a user-supplied function to free the resource (if needed).
- * @res: The resource.
- * @data: value to pass to init function or set in resource data field.
- */
-int kunit_add_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- struct kunit_resource *res,
- void *data);
-
-/**
- * kunit_add_named_resource() - Add a named *test managed resource*.
- * @test: The test context object.
- * @init: a user-supplied function to initialize the resource data, if needed.
- * @free: a user-supplied function to free the resource data, if needed.
- * @res: The resource.
- * @name: name to be set for resource.
- * @data: value to pass to init function or set in resource data field.
- */
-int kunit_add_named_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- struct kunit_resource *res,
- const char *name,
- void *data);
-
-/**
- * kunit_alloc_resource() - Allocates a *test managed resource*.
- * @test: The test context object.
- * @init: a user supplied function to initialize the resource.
- * @free: a user supplied function to free the resource.
- * @internal_gfp: gfp to use for internal allocations, if unsure, use GFP_KERNEL
- * @context: for the user to pass in arbitrary data to the init function.
- *
- * Allocates a *test managed resource*, a resource which will automatically be
- * cleaned up at the end of a test case. See &struct kunit_resource for an
- * example.
- *
- * Note: KUnit needs to allocate memory for a kunit_resource object. You must
- * specify an @internal_gfp that is compatible with the use context of your
- * resource.
- */
-static inline void *kunit_alloc_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- gfp_t internal_gfp,
- void *context)
-{
- struct kunit_resource *res;
-
- res = kzalloc(sizeof(*res), internal_gfp);
- if (!res)
- return NULL;
-
- if (!kunit_add_resource(test, init, free, res, context))
- return res->data;
-
- return NULL;
-}
-
-typedef bool (*kunit_resource_match_t)(struct kunit *test,
- struct kunit_resource *res,
- void *match_data);
-
-/**
- * kunit_resource_instance_match() - Match a resource with the same instance.
- * @test: Test case to which the resource belongs.
- * @res: The resource.
- * @match_data: The resource pointer to match against.
- *
- * An instance of kunit_resource_match_t that matches a resource whose
- * allocation matches @match_data.
- */
-static inline bool kunit_resource_instance_match(struct kunit *test,
- struct kunit_resource *res,
- void *match_data)
-{
- return res->data == match_data;
-}
-
-/**
- * kunit_resource_name_match() - Match a resource with the same name.
- * @test: Test case to which the resource belongs.
- * @res: The resource.
- * @match_name: The name to match against.
- */
-static inline bool kunit_resource_name_match(struct kunit *test,
- struct kunit_resource *res,
- void *match_name)
-{
- return res->name && strcmp(res->name, match_name) == 0;
-}
-
-/**
- * kunit_find_resource() - Find a resource using match function/data.
- * @test: Test case to which the resource belongs.
- * @match: match function to be applied to resources/match data.
- * @match_data: data to be used in matching.
- */
-static inline struct kunit_resource *
-kunit_find_resource(struct kunit *test,
- kunit_resource_match_t match,
- void *match_data)
-{
- struct kunit_resource *res, *found = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&test->lock, flags);
-
- list_for_each_entry_reverse(res, &test->resources, node) {
- if (match(test, res, (void *)match_data)) {
- found = res;
- kunit_get_resource(found);
- break;
- }
- }
-
- spin_unlock_irqrestore(&test->lock, flags);
-
- return found;
-}
-
-/**
- * kunit_find_named_resource() - Find a resource using match name.
- * @test: Test case to which the resource belongs.
- * @name: match name.
- */
-static inline struct kunit_resource *
-kunit_find_named_resource(struct kunit *test,
- const char *name)
-{
- return kunit_find_resource(test, kunit_resource_name_match,
- (void *)name);
-}
-
-/**
- * kunit_destroy_resource() - Find a kunit_resource and destroy it.
- * @test: Test case to which the resource belongs.
- * @match: Match function. Returns whether a given resource matches @match_data.
- * @match_data: Data passed into @match.
- *
- * RETURNS:
- * 0 if kunit_resource is found and freed, -ENOENT if not found.
- */
-int kunit_destroy_resource(struct kunit *test,
- kunit_resource_match_t match,
- void *match_data);
-
-static inline int kunit_destroy_named_resource(struct kunit *test,
- const char *name)
-{
- return kunit_destroy_resource(test, kunit_resource_name_match,
- (void *)name);
-}
-
-/**
- * kunit_remove_resource() - remove resource from resource list associated with
- * test.
- * @test: The test context object.
- * @res: The resource to be removed.
- *
- * Note that the resource will not be immediately freed since it is likely
- * the caller has a reference to it via alloc_and_get() or find();
- * in this case a final call to kunit_put_resource() is required.
- */
-void kunit_remove_resource(struct kunit *test, struct kunit_resource *res);
-
/**
* kunit_kmalloc_array() - Like kmalloc_array() except the allocation is *test managed*.
* @test: The test context object.
@@ -1526,4 +1227,8 @@ do { \
return NULL; \
}
+// TODO(dlatypov(a)google.com): consider eventually migrating users to explicitly
+// include resource.h themselves if they need it.
+#include <kunit/resource.h>
+
#endif /* _KUNIT_TEST_H */
base-commit: b14ffae378aa1db993e62b01392e70d1e585fb23
--
2.35.1.1021.g381101b075-goog
Background:
Currently, a reader looking at kunit/test.h will find the file is quite
long, and the first meaty comment is a doc comment about struct
kunit_resource.
Most users will not ever use the KUnit resource API directly.
They'll use kunit_kmalloc() and friends, or decide it's simpler to do
cleanups via labels (it often can be) instead of figuring out how to use
the API.
It's also logically separate from everything else in test.h.
Removing it from the file doesn't cause any compilation errors (since
struct kunit has `struct list_head resources` to store them).
This commit:
Let's move it into a kunit/resource.h file and give it a separate page
in the docs, kunit/api/resource.rst.
We include resource.h at the bottom of test.h since
* don't want to force existing users to add a new include if they use the API
* it accesses `lock` inside `struct kunit` in a inline func
* so we can't just forward declare, and the alternatives require
uninlining the func, adding hepers to lock/unlock, or other more
invasive changes.
Now the first big comment in test.h is about kunit_case, which is a lot
more relevant to what a new user wants to know.
A side effect of this is git blame won't properly track history by
default, users need to run
$ git blame -L ,1 -C17 include/kunit/resource.h
Signed-off-by: Daniel Latypov <dlatypov(a)google.com>
Reviewed-by: David Gow <davidgow(a)google.com>
Reviewed-by: Brendan Higgins <brendanhiggins(a)google.com>
---
v1 -> v2: add TODO to make users #include resource.h, drop redundant fwd
decl of struct kunit in resource.h
---
Documentation/dev-tools/kunit/api/index.rst | 5 +
.../dev-tools/kunit/api/resource.rst | 13 +
include/kunit/resource.h | 318 ++++++++++++++++++
include/kunit/test.h | 303 +----------------
4 files changed, 340 insertions(+), 299 deletions(-)
create mode 100644 Documentation/dev-tools/kunit/api/resource.rst
create mode 100644 include/kunit/resource.h
diff --git a/Documentation/dev-tools/kunit/api/index.rst b/Documentation/dev-tools/kunit/api/index.rst
index 3006cadcf44a..45ce04823f9f 100644
--- a/Documentation/dev-tools/kunit/api/index.rst
+++ b/Documentation/dev-tools/kunit/api/index.rst
@@ -6,6 +6,7 @@ API Reference
.. toctree::
test
+ resource
This section documents the KUnit kernel testing API. It is divided into the
following sections:
@@ -13,3 +14,7 @@ following sections:
Documentation/dev-tools/kunit/api/test.rst
- documents all of the standard testing API
+
+Documentation/dev-tools/kunit/api/resource.rst
+
+ - documents the KUnit resource API
diff --git a/Documentation/dev-tools/kunit/api/resource.rst b/Documentation/dev-tools/kunit/api/resource.rst
new file mode 100644
index 000000000000..0a94f831259e
--- /dev/null
+++ b/Documentation/dev-tools/kunit/api/resource.rst
@@ -0,0 +1,13 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+Resource API
+============
+
+This file documents the KUnit resource API.
+
+Most users won't need to use this API directly, power users can use it to store
+state on a per-test basis, register custom cleanup actions, and more.
+
+.. kernel-doc:: include/kunit/resource.h
+ :internal:
diff --git a/include/kunit/resource.h b/include/kunit/resource.h
new file mode 100644
index 000000000000..7ab1fd83972b
--- /dev/null
+++ b/include/kunit/resource.h
@@ -0,0 +1,318 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KUnit resource API for test managed resources (allocations, etc.).
+ *
+ * Copyright (C) 2022, Google LLC.
+ * Author: Daniel Latypov <dlatypov(a)google.com>
+ */
+
+#ifndef _KUNIT_RESOURCE_H
+#define _KUNIT_RESOURCE_H
+
+#include <kunit/test.h>
+
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct kunit_resource;
+
+typedef int (*kunit_resource_init_t)(struct kunit_resource *, void *);
+typedef void (*kunit_resource_free_t)(struct kunit_resource *);
+
+/**
+ * struct kunit_resource - represents a *test managed resource*
+ * @data: for the user to store arbitrary data.
+ * @name: optional name
+ * @free: a user supplied function to free the resource. Populated by
+ * kunit_resource_alloc().
+ *
+ * Represents a *test managed resource*, a resource which will automatically be
+ * cleaned up at the end of a test case.
+ *
+ * Resources are reference counted so if a resource is retrieved via
+ * kunit_alloc_and_get_resource() or kunit_find_resource(), we need
+ * to call kunit_put_resource() to reduce the resource reference count
+ * when finished with it. Note that kunit_alloc_resource() does not require a
+ * kunit_resource_put() because it does not retrieve the resource itself.
+ *
+ * Example:
+ *
+ * .. code-block:: c
+ *
+ * struct kunit_kmalloc_params {
+ * size_t size;
+ * gfp_t gfp;
+ * };
+ *
+ * static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
+ * {
+ * struct kunit_kmalloc_params *params = context;
+ * res->data = kmalloc(params->size, params->gfp);
+ *
+ * if (!res->data)
+ * return -ENOMEM;
+ *
+ * return 0;
+ * }
+ *
+ * static void kunit_kmalloc_free(struct kunit_resource *res)
+ * {
+ * kfree(res->data);
+ * }
+ *
+ * void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
+ * {
+ * struct kunit_kmalloc_params params;
+ *
+ * params.size = size;
+ * params.gfp = gfp;
+ *
+ * return kunit_alloc_resource(test, kunit_kmalloc_init,
+ * kunit_kmalloc_free, ¶ms);
+ * }
+ *
+ * Resources can also be named, with lookup/removal done on a name
+ * basis also. kunit_add_named_resource(), kunit_find_named_resource()
+ * and kunit_destroy_named_resource(). Resource names must be
+ * unique within the test instance.
+ */
+struct kunit_resource {
+ void *data;
+ const char *name;
+ kunit_resource_free_t free;
+
+ /* private: internal use only. */
+ struct kref refcount;
+ struct list_head node;
+};
+
+/*
+ * Like kunit_alloc_resource() below, but returns the struct kunit_resource
+ * object that contains the allocation. This is mostly for testing purposes.
+ */
+struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ gfp_t internal_gfp,
+ void *context);
+
+/**
+ * kunit_get_resource() - Hold resource for use. Should not need to be used
+ * by most users as we automatically get resources
+ * retrieved by kunit_find_resource*().
+ * @res: resource
+ */
+static inline void kunit_get_resource(struct kunit_resource *res)
+{
+ kref_get(&res->refcount);
+}
+
+/*
+ * Called when refcount reaches zero via kunit_put_resource();
+ * should not be called directly.
+ */
+static inline void kunit_release_resource(struct kref *kref)
+{
+ struct kunit_resource *res = container_of(kref, struct kunit_resource,
+ refcount);
+
+ /* If free function is defined, resource was dynamically allocated. */
+ if (res->free) {
+ res->free(res);
+ kfree(res);
+ }
+}
+
+/**
+ * kunit_put_resource() - When caller is done with retrieved resource,
+ * kunit_put_resource() should be called to drop
+ * reference count. The resource list maintains
+ * a reference count on resources, so if no users
+ * are utilizing a resource and it is removed from
+ * the resource list, it will be freed via the
+ * associated free function (if any). Only
+ * needs to be used if we alloc_and_get() or
+ * find() resource.
+ * @res: resource
+ */
+static inline void kunit_put_resource(struct kunit_resource *res)
+{
+ kref_put(&res->refcount, kunit_release_resource);
+}
+
+/**
+ * kunit_add_resource() - Add a *test managed resource*.
+ * @test: The test context object.
+ * @init: a user-supplied function to initialize the result (if needed). If
+ * none is supplied, the resource data value is simply set to @data.
+ * If an init function is supplied, @data is passed to it instead.
+ * @free: a user-supplied function to free the resource (if needed).
+ * @res: The resource.
+ * @data: value to pass to init function or set in resource data field.
+ */
+int kunit_add_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ struct kunit_resource *res,
+ void *data);
+
+/**
+ * kunit_add_named_resource() - Add a named *test managed resource*.
+ * @test: The test context object.
+ * @init: a user-supplied function to initialize the resource data, if needed.
+ * @free: a user-supplied function to free the resource data, if needed.
+ * @res: The resource.
+ * @name: name to be set for resource.
+ * @data: value to pass to init function or set in resource data field.
+ */
+int kunit_add_named_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ struct kunit_resource *res,
+ const char *name,
+ void *data);
+
+/**
+ * kunit_alloc_resource() - Allocates a *test managed resource*.
+ * @test: The test context object.
+ * @init: a user supplied function to initialize the resource.
+ * @free: a user supplied function to free the resource.
+ * @internal_gfp: gfp to use for internal allocations, if unsure, use GFP_KERNEL
+ * @context: for the user to pass in arbitrary data to the init function.
+ *
+ * Allocates a *test managed resource*, a resource which will automatically be
+ * cleaned up at the end of a test case. See &struct kunit_resource for an
+ * example.
+ *
+ * Note: KUnit needs to allocate memory for a kunit_resource object. You must
+ * specify an @internal_gfp that is compatible with the use context of your
+ * resource.
+ */
+static inline void *kunit_alloc_resource(struct kunit *test,
+ kunit_resource_init_t init,
+ kunit_resource_free_t free,
+ gfp_t internal_gfp,
+ void *context)
+{
+ struct kunit_resource *res;
+
+ res = kzalloc(sizeof(*res), internal_gfp);
+ if (!res)
+ return NULL;
+
+ if (!kunit_add_resource(test, init, free, res, context))
+ return res->data;
+
+ return NULL;
+}
+
+typedef bool (*kunit_resource_match_t)(struct kunit *test,
+ struct kunit_resource *res,
+ void *match_data);
+
+/**
+ * kunit_resource_instance_match() - Match a resource with the same instance.
+ * @test: Test case to which the resource belongs.
+ * @res: The resource.
+ * @match_data: The resource pointer to match against.
+ *
+ * An instance of kunit_resource_match_t that matches a resource whose
+ * allocation matches @match_data.
+ */
+static inline bool kunit_resource_instance_match(struct kunit *test,
+ struct kunit_resource *res,
+ void *match_data)
+{
+ return res->data == match_data;
+}
+
+/**
+ * kunit_resource_name_match() - Match a resource with the same name.
+ * @test: Test case to which the resource belongs.
+ * @res: The resource.
+ * @match_name: The name to match against.
+ */
+static inline bool kunit_resource_name_match(struct kunit *test,
+ struct kunit_resource *res,
+ void *match_name)
+{
+ return res->name && strcmp(res->name, match_name) == 0;
+}
+
+/**
+ * kunit_find_resource() - Find a resource using match function/data.
+ * @test: Test case to which the resource belongs.
+ * @match: match function to be applied to resources/match data.
+ * @match_data: data to be used in matching.
+ */
+static inline struct kunit_resource *
+kunit_find_resource(struct kunit *test,
+ kunit_resource_match_t match,
+ void *match_data)
+{
+ struct kunit_resource *res, *found = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&test->lock, flags);
+
+ list_for_each_entry_reverse(res, &test->resources, node) {
+ if (match(test, res, (void *)match_data)) {
+ found = res;
+ kunit_get_resource(found);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&test->lock, flags);
+
+ return found;
+}
+
+/**
+ * kunit_find_named_resource() - Find a resource using match name.
+ * @test: Test case to which the resource belongs.
+ * @name: match name.
+ */
+static inline struct kunit_resource *
+kunit_find_named_resource(struct kunit *test,
+ const char *name)
+{
+ return kunit_find_resource(test, kunit_resource_name_match,
+ (void *)name);
+}
+
+/**
+ * kunit_destroy_resource() - Find a kunit_resource and destroy it.
+ * @test: Test case to which the resource belongs.
+ * @match: Match function. Returns whether a given resource matches @match_data.
+ * @match_data: Data passed into @match.
+ *
+ * RETURNS:
+ * 0 if kunit_resource is found and freed, -ENOENT if not found.
+ */
+int kunit_destroy_resource(struct kunit *test,
+ kunit_resource_match_t match,
+ void *match_data);
+
+static inline int kunit_destroy_named_resource(struct kunit *test,
+ const char *name)
+{
+ return kunit_destroy_resource(test, kunit_resource_name_match,
+ (void *)name);
+}
+
+/**
+ * kunit_remove_resource() - remove resource from resource list associated with
+ * test.
+ * @test: The test context object.
+ * @res: The resource to be removed.
+ *
+ * Note that the resource will not be immediately freed since it is likely
+ * the caller has a reference to it via alloc_and_get() or find();
+ * in this case a final call to kunit_put_resource() is required.
+ */
+void kunit_remove_resource(struct kunit *test, struct kunit_resource *res);
+
+#endif /* _KUNIT_RESOURCE_H */
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 00b9ff7783ab..d04f9e2fd5e7 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -27,78 +27,6 @@
#include <asm/rwonce.h>
-struct kunit_resource;
-
-typedef int (*kunit_resource_init_t)(struct kunit_resource *, void *);
-typedef void (*kunit_resource_free_t)(struct kunit_resource *);
-
-/**
- * struct kunit_resource - represents a *test managed resource*
- * @data: for the user to store arbitrary data.
- * @name: optional name
- * @free: a user supplied function to free the resource. Populated by
- * kunit_resource_alloc().
- *
- * Represents a *test managed resource*, a resource which will automatically be
- * cleaned up at the end of a test case.
- *
- * Resources are reference counted so if a resource is retrieved via
- * kunit_alloc_and_get_resource() or kunit_find_resource(), we need
- * to call kunit_put_resource() to reduce the resource reference count
- * when finished with it. Note that kunit_alloc_resource() does not require a
- * kunit_resource_put() because it does not retrieve the resource itself.
- *
- * Example:
- *
- * .. code-block:: c
- *
- * struct kunit_kmalloc_params {
- * size_t size;
- * gfp_t gfp;
- * };
- *
- * static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
- * {
- * struct kunit_kmalloc_params *params = context;
- * res->data = kmalloc(params->size, params->gfp);
- *
- * if (!res->data)
- * return -ENOMEM;
- *
- * return 0;
- * }
- *
- * static void kunit_kmalloc_free(struct kunit_resource *res)
- * {
- * kfree(res->data);
- * }
- *
- * void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
- * {
- * struct kunit_kmalloc_params params;
- *
- * params.size = size;
- * params.gfp = gfp;
- *
- * return kunit_alloc_resource(test, kunit_kmalloc_init,
- * kunit_kmalloc_free, ¶ms);
- * }
- *
- * Resources can also be named, with lookup/removal done on a name
- * basis also. kunit_add_named_resource(), kunit_find_named_resource()
- * and kunit_destroy_named_resource(). Resource names must be
- * unique within the test instance.
- */
-struct kunit_resource {
- void *data;
- const char *name;
- kunit_resource_free_t free;
-
- /* private: internal use only. */
- struct kref refcount;
- struct list_head node;
-};
-
struct kunit;
/* Size of log associated with test. */
@@ -385,233 +313,6 @@ static inline int kunit_run_all_tests(void)
enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite);
-/*
- * Like kunit_alloc_resource() below, but returns the struct kunit_resource
- * object that contains the allocation. This is mostly for testing purposes.
- */
-struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- gfp_t internal_gfp,
- void *context);
-
-/**
- * kunit_get_resource() - Hold resource for use. Should not need to be used
- * by most users as we automatically get resources
- * retrieved by kunit_find_resource*().
- * @res: resource
- */
-static inline void kunit_get_resource(struct kunit_resource *res)
-{
- kref_get(&res->refcount);
-}
-
-/*
- * Called when refcount reaches zero via kunit_put_resources();
- * should not be called directly.
- */
-static inline void kunit_release_resource(struct kref *kref)
-{
- struct kunit_resource *res = container_of(kref, struct kunit_resource,
- refcount);
-
- /* If free function is defined, resource was dynamically allocated. */
- if (res->free) {
- res->free(res);
- kfree(res);
- }
-}
-
-/**
- * kunit_put_resource() - When caller is done with retrieved resource,
- * kunit_put_resource() should be called to drop
- * reference count. The resource list maintains
- * a reference count on resources, so if no users
- * are utilizing a resource and it is removed from
- * the resource list, it will be freed via the
- * associated free function (if any). Only
- * needs to be used if we alloc_and_get() or
- * find() resource.
- * @res: resource
- */
-static inline void kunit_put_resource(struct kunit_resource *res)
-{
- kref_put(&res->refcount, kunit_release_resource);
-}
-
-/**
- * kunit_add_resource() - Add a *test managed resource*.
- * @test: The test context object.
- * @init: a user-supplied function to initialize the result (if needed). If
- * none is supplied, the resource data value is simply set to @data.
- * If an init function is supplied, @data is passed to it instead.
- * @free: a user-supplied function to free the resource (if needed).
- * @res: The resource.
- * @data: value to pass to init function or set in resource data field.
- */
-int kunit_add_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- struct kunit_resource *res,
- void *data);
-
-/**
- * kunit_add_named_resource() - Add a named *test managed resource*.
- * @test: The test context object.
- * @init: a user-supplied function to initialize the resource data, if needed.
- * @free: a user-supplied function to free the resource data, if needed.
- * @res: The resource.
- * @name: name to be set for resource.
- * @data: value to pass to init function or set in resource data field.
- */
-int kunit_add_named_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- struct kunit_resource *res,
- const char *name,
- void *data);
-
-/**
- * kunit_alloc_resource() - Allocates a *test managed resource*.
- * @test: The test context object.
- * @init: a user supplied function to initialize the resource.
- * @free: a user supplied function to free the resource.
- * @internal_gfp: gfp to use for internal allocations, if unsure, use GFP_KERNEL
- * @context: for the user to pass in arbitrary data to the init function.
- *
- * Allocates a *test managed resource*, a resource which will automatically be
- * cleaned up at the end of a test case. See &struct kunit_resource for an
- * example.
- *
- * Note: KUnit needs to allocate memory for a kunit_resource object. You must
- * specify an @internal_gfp that is compatible with the use context of your
- * resource.
- */
-static inline void *kunit_alloc_resource(struct kunit *test,
- kunit_resource_init_t init,
- kunit_resource_free_t free,
- gfp_t internal_gfp,
- void *context)
-{
- struct kunit_resource *res;
-
- res = kzalloc(sizeof(*res), internal_gfp);
- if (!res)
- return NULL;
-
- if (!kunit_add_resource(test, init, free, res, context))
- return res->data;
-
- return NULL;
-}
-
-typedef bool (*kunit_resource_match_t)(struct kunit *test,
- struct kunit_resource *res,
- void *match_data);
-
-/**
- * kunit_resource_instance_match() - Match a resource with the same instance.
- * @test: Test case to which the resource belongs.
- * @res: The resource.
- * @match_data: The resource pointer to match against.
- *
- * An instance of kunit_resource_match_t that matches a resource whose
- * allocation matches @match_data.
- */
-static inline bool kunit_resource_instance_match(struct kunit *test,
- struct kunit_resource *res,
- void *match_data)
-{
- return res->data == match_data;
-}
-
-/**
- * kunit_resource_name_match() - Match a resource with the same name.
- * @test: Test case to which the resource belongs.
- * @res: The resource.
- * @match_name: The name to match against.
- */
-static inline bool kunit_resource_name_match(struct kunit *test,
- struct kunit_resource *res,
- void *match_name)
-{
- return res->name && strcmp(res->name, match_name) == 0;
-}
-
-/**
- * kunit_find_resource() - Find a resource using match function/data.
- * @test: Test case to which the resource belongs.
- * @match: match function to be applied to resources/match data.
- * @match_data: data to be used in matching.
- */
-static inline struct kunit_resource *
-kunit_find_resource(struct kunit *test,
- kunit_resource_match_t match,
- void *match_data)
-{
- struct kunit_resource *res, *found = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&test->lock, flags);
-
- list_for_each_entry_reverse(res, &test->resources, node) {
- if (match(test, res, (void *)match_data)) {
- found = res;
- kunit_get_resource(found);
- break;
- }
- }
-
- spin_unlock_irqrestore(&test->lock, flags);
-
- return found;
-}
-
-/**
- * kunit_find_named_resource() - Find a resource using match name.
- * @test: Test case to which the resource belongs.
- * @name: match name.
- */
-static inline struct kunit_resource *
-kunit_find_named_resource(struct kunit *test,
- const char *name)
-{
- return kunit_find_resource(test, kunit_resource_name_match,
- (void *)name);
-}
-
-/**
- * kunit_destroy_resource() - Find a kunit_resource and destroy it.
- * @test: Test case to which the resource belongs.
- * @match: Match function. Returns whether a given resource matches @match_data.
- * @match_data: Data passed into @match.
- *
- * RETURNS:
- * 0 if kunit_resource is found and freed, -ENOENT if not found.
- */
-int kunit_destroy_resource(struct kunit *test,
- kunit_resource_match_t match,
- void *match_data);
-
-static inline int kunit_destroy_named_resource(struct kunit *test,
- const char *name)
-{
- return kunit_destroy_resource(test, kunit_resource_name_match,
- (void *)name);
-}
-
-/**
- * kunit_remove_resource() - remove resource from resource list associated with
- * test.
- * @test: The test context object.
- * @res: The resource to be removed.
- *
- * Note that the resource will not be immediately freed since it is likely
- * the caller has a reference to it via alloc_and_get() or find();
- * in this case a final call to kunit_put_resource() is required.
- */
-void kunit_remove_resource(struct kunit *test, struct kunit_resource *res);
-
/**
* kunit_kmalloc_array() - Like kmalloc_array() except the allocation is *test managed*.
* @test: The test context object.
@@ -1526,4 +1227,8 @@ do { \
return NULL; \
}
+// TODO(dlatypov(a)google.com): consider eventually migrating users to explicitly
+// include resource.h themselves if they need it.
+#include <kunit/resource.h>
+
#endif /* _KUNIT_TEST_H */
base-commit: b14ffae378aa1db993e62b01392e70d1e585fb23
--
2.35.1.1021.g381101b075-goog
On Fri, Mar 11, 2022 at 4:14 AM Daniel Gutson
<daniel.gutson(a)eclypsium.com> wrote:
>
>
>
> El vie., 11 mar. 2022 4:02 a. m., David Gow <davidgow(a)google.com> escribió:
>>
>> On Thu, Mar 10, 2022 at 01:02:10PM -0800, Brendan Higgins wrote:
>> > Add support for a new kind of kunit_suite registration macro called
>> > kunit_test_init_suite(); this new registration macro allows the
>> > registration of kunit_suites that reference functions marked __init and
>> > data marked __initdata.
>> >
>> > Signed-off-by: Brendan Higgins <brendanhiggins(a)google.com>
>> > ---
>> >
>> > This patch is in response to a KUnit user issue[1] in which the user was
>> > attempting to test some init functions; although this is a functional
>> > solution as long as KUnit tests only run during the init phase, we will
>> > need to do more work if we ever allow tests to run after the init phase
>> > is over; it is for this reason that this patch adds a new registration
>> > macro rather than simply modifying the existing macros.
>> >
>> > [1] https://groups.google.com/g/kunit-dev/c/XDjieRHEneg/m/D0rFCwVABgAJ
>> >
>> > ---
>>
>> I'm a little concerned that this is just removing the warnings, but do
>> agree that this is safe enough for the moment. At least the information
>> about which tests need __init is preserved by the use of a different
>> macro.
>>
>> I guess one day we'll need a second list of 'init' tests or something...
>
>
> Hi, could you please detail about this? Why a second list?
>
I assume this is referring to a future where we want to run tests
_after_ the init phase.
In that case, we'd need to be able to separately register tests that
run during and those that run after.
(Or we could have one list and just tag each suite as init/post-init.
If we ever had >2 "phases" where we run tests, this might be the more
scalable option)
Is it likely we'd have tests run after?
Not in the near future, I don't think. But it could be asked for.
For context, here's where built-in KUnit tests currently run:
https://elixir.bootlin.com/linux/v5.17-rc7/source/init/main.c#L1615
That'd probably become kunit_run_init_tests() and then we'd have
another kunit_run_post_init_tests() called later, or something.
This patch set extends the locked port feature for devices
that are behind a locked port, but do not have the ability to
authorize themselves as a supplicant using IEEE 802.1X.
Such devices can be printers, meters or anything related to
fixed installations. Instead of 802.1X authorization, devices
can get access based on their MAC addresses being whitelisted.
For an authorization daemon to detect that a device is trying
to get access through a locked port, the bridge will add the
MAC address of the device to the FDB with a locked flag to it.
Thus the authorization daemon can catch the FDB add event and
check if the MAC address is in the whitelist and if so replace
the FDB entry without the locked flag enabled, and thus open
the port for the device.
This feature is known as MAC-Auth or MAC Authentication Bypass
(MAB) in Cisco terminology, where the full MAB concept involves
additional Cisco infrastructure for authorization. There is no
real authentication process, as the MAC address of the device
is the only input the authorization daemon, in the general
case, has to base the decision if to unlock the port or not.
With this patch set, an implementation of the offloaded case is
supplied for the mv88e6xxx driver. When a packet ingresses on
a locked port, an ATU miss violation event will occur. When
handling such ATU miss violation interrupts, the MAC address of
the device is added to the FDB with a zero destination port
vector (DPV) and the MAC address is communicated through the
switchdev layer to the bridge, so that a FDB entry with the
locked flag enabled can be added.
Hans Schultz (4):
net: bridge: add fdb flag to extent locked port feature
net: switchdev: add support for offloading of fdb locked flag
net: dsa: mv88e6xxx: mac-auth/MAB implementation
selftests: forwarding: add test of MAC-Auth Bypass to locked port
tests
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 10 +--
drivers/net/dsa/mv88e6xxx/chip.h | 5 ++
drivers/net/dsa/mv88e6xxx/global1.h | 1 +
drivers/net/dsa/mv88e6xxx/global1_atu.c | 29 ++++++-
.../net/dsa/mv88e6xxx/mv88e6xxx_switchdev.c | 75 +++++++++++++++++++
.../net/dsa/mv88e6xxx/mv88e6xxx_switchdev.h | 20 +++++
drivers/net/dsa/mv88e6xxx/port.c | 17 ++++-
drivers/net/dsa/mv88e6xxx/port.h | 1 +
include/net/switchdev.h | 3 +-
include/uapi/linux/neighbour.h | 1 +
net/bridge/br.c | 3 +-
net/bridge/br_fdb.c | 13 +++-
net/bridge/br_input.c | 10 ++-
net/bridge/br_private.h | 5 +-
.../net/forwarding/bridge_locked_port.sh | 29 ++++++-
16 files changed, 206 insertions(+), 17 deletions(-)
create mode 100644 drivers/net/dsa/mv88e6xxx/mv88e6xxx_switchdev.c
create mode 100644 drivers/net/dsa/mv88e6xxx/mv88e6xxx_switchdev.h
--
2.30.2
Dzień dobry,
stworzyliśmy specjalną ofertę dla firm, na kompleksową obsługę inwestycji w fotowoltaikę.
Specjalizujemy się w zakresie doboru, montażu i serwisie instalacji fotowoltaicznych, dysponujemy najnowocześniejszymi rozwiązania, które zapewnią Państwu oczekiwane rezultaty.
Możemy przygotować dla Państwa wstępną kalkulację i przeanalizować efekty możliwe do osiągnięcia.
Czy są Państwo otwarci na wstępną rozmowę w tym temacie?
Pozdrawiam
Arkadiusz Sokołowski