From patchwork Thu Nov 24 15:15:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055086 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9E62C4321E for ; Thu, 24 Nov 2022 15:18:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229966AbiKXPSE (ORCPT ); Thu, 24 Nov 2022 10:18:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57378 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229706AbiKXPSC (ORCPT ); Thu, 24 Nov 2022 10:18:02 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1367715B4C1 for ; Thu, 24 Nov 2022 07:16:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302975; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KAJYIVS7w3VHw6GPJCxv8d/p+6Nx7C8D/UTcdk+DlLc=; b=E72kW2PkeKR4fI+wL689/nMls4h0qvTzspRPJJ3lpzXAy0BEOW+YMrMkxeIWYDkwMx4RKV pjKMbOLDlLZXOulA9rvn+TCs0tC4pLFvJXyeMlpOKn2jMYXKx36UFxWj7l9DAgLmqQcse6 ubtVQaC9nYzlu1XZdyqMkyhUDNyqC8c= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-422-HPzI6D8PNnm5Bc0Sqkuylw-1; Thu, 24 Nov 2022 10:16:12 -0500 X-MC-Unique: HPzI6D8PNnm5Bc0Sqkuylw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8C61E29AB3F2; Thu, 24 Nov 2022 15:16:11 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id CE91640C2064; Thu, 24 Nov 2022 15:16:09 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 01/10] bpftool: generate json output of skeletons Date: Thu, 24 Nov 2022 16:15:54 +0100 Message-Id: <20221124151603.807536-2-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net X-Patchwork-State: RFC So we can then build light skeletons with loaders in any language. Signed-off-by: Benjamin Tissoires --- tools/bpf/bpftool/gen.c | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c index cf8b4e525c88..818a5209b3ac 100644 --- a/tools/bpf/bpftool/gen.c +++ b/tools/bpf/bpftool/gen.c @@ -904,6 +904,96 @@ codegen_progs_skeleton(struct bpf_object *obj, size_t prog_cnt, bool populate_li } } +static int gen_json(struct bpf_object *obj, const char *obj_name, size_t file_sz, uint8_t *obj_data) +{ + struct bpf_program *prog; + struct bpf_map *map; + char ident[256]; + + jsonw_start_object(json_wtr); /* root object */ + + jsonw_string_field(json_wtr, "name", obj_name); + + jsonw_bool_field(json_wtr, "use_loader", use_loader); + + /* print all maps */ + jsonw_name(json_wtr, "maps"); + jsonw_start_array(json_wtr); + bpf_object__for_each_map(map, obj) { + if (!get_map_ident(map, ident, sizeof(ident))) { + p_err("ignoring unrecognized internal map '%s'...", + bpf_map__name(map)); + continue; + } + + jsonw_start_object(json_wtr); /* map object */ + jsonw_string_field(json_wtr, "ident", ident); + jsonw_string_field(json_wtr, "name", bpf_map__name(map)); + + /* print mmap data value */ + if (is_internal_mmapable_map(map, ident, sizeof(ident))) { + const void *mmap_data = NULL; + size_t mmap_size = 0; + + mmap_data = bpf_map__initial_value(map, &mmap_size); + + jsonw_uint_field(json_wtr, "size", mmap_size); + jsonw_uint_field(json_wtr, "mmap_sz", bpf_map_mmap_sz(map)); + jsonw_name(json_wtr, "data"); + print_hex_data_json((uint8_t *)mmap_data, mmap_size); + + } + jsonw_end_object(json_wtr); /* map object */ + } + jsonw_end_array(json_wtr); + + /* print all progs */ + jsonw_name(json_wtr, "progs"); + jsonw_start_array(json_wtr); + bpf_object__for_each_program(prog, obj) { + jsonw_start_object(json_wtr); /* prog object */ + jsonw_string_field(json_wtr, "name", bpf_program__name(prog)); + jsonw_string_field(json_wtr, "sec", bpf_program__section_name(prog)); + jsonw_end_object(json_wtr); /* prog object */ + } + jsonw_end_array(json_wtr); + + /* print object data */ + if (use_loader) { + DECLARE_LIBBPF_OPTS(gen_loader_opts, opts); + int err = 0; + + err = bpf_object__gen_loader(obj, &opts); + if (err) + return err; + + err = bpf_object__load(obj); + if (err) { + p_err("failed to load object file"); + return err; + } + /* If there was no error during load then gen_loader_opts + * are populated with the loader program. + */ + + jsonw_uint_field(json_wtr, "data_sz", opts.data_sz); + jsonw_name(json_wtr, "data"); + print_hex_data_json((uint8_t *)opts.data, opts.data_sz); + + jsonw_uint_field(json_wtr, "insns_sz", opts.insns_sz); + jsonw_name(json_wtr, "insns"); + print_hex_data_json((uint8_t *)opts.insns, opts.insns_sz); + + } else { + jsonw_name(json_wtr, "data"); + print_hex_data_json(obj_data, file_sz); + } + + jsonw_end_object(json_wtr); /* root object */ + + return 0; +} + static int do_skeleton(int argc, char **argv) { char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")]; @@ -986,6 +1076,11 @@ static int do_skeleton(int argc, char **argv) goto out; } + if (json_output) { + err = gen_json(obj, obj_name, file_sz, (uint8_t *)obj_data); + goto out; + } + bpf_object__for_each_map(map, obj) { if (!get_map_ident(map, ident, sizeof(ident))) { p_err("ignoring unrecognized internal map '%s'...", From patchwork Thu Nov 24 15:15:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055087 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A7453C352A1 for ; Thu, 24 Nov 2022 15:18:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229706AbiKXPSH (ORCPT ); Thu, 24 Nov 2022 10:18:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57396 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229910AbiKXPSC (ORCPT ); Thu, 24 Nov 2022 10:18:02 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 385AE16E8CA for ; Thu, 24 Nov 2022 07:16:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302978; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1gSBxJ3JD+Lhw0lQsSl13cc2SNWiLM1GIUzZ7OkQbMU=; b=U691ylK/wZVwKQHKn+/WUaWE/P2hCyuSW6QSgXsblBHUvqYbJcVV+2YHX+6wiQ9sgBQ4lN MDMcVxXMFSHlQ/Wy7MpC38MYPkJdQKAs74b2iCEqeGsZGXY9UKmxOqTiMF8LQZKKhdhTzn lWdx4ZrhefYBgv6c8yVarOnLyvqh6fM= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-9-2nluelRgODCohAjC4AFX6g-1; Thu, 24 Nov 2022 10:16:14 -0500 X-MC-Unique: 2nluelRgODCohAjC4AFX6g-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 87F903C01E03; Thu, 24 Nov 2022 15:16:13 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id C7AEF40C2064; Thu, 24 Nov 2022 15:16:11 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 02/10] WIP: bpf: allow to pin programs from the kernel when bpffs is mounted Date: Thu, 24 Nov 2022 16:15:55 +0100 Message-Id: <20221124151603.807536-3-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net X-Patchwork-State: RFC I want to be able to pin programs loaded by the kernel and expose them through the bpffs so userspace knows what is loaded. There are a few things missings in this WIP: - locking on bpffs_sb - ability to create a hierarchy from the kernel: I'd like to store all of my programs in /sys/fs/bpf/hid, not everything at the root of the mount - ability to store programs when bpffs is not mounted Signed-off-by: Benjamin Tissoires --- include/linux/bpf.h | 1 + kernel/bpf/inode.c | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 0566705c1d4e..f5a7dca520eb 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1806,6 +1806,7 @@ struct bpf_link *bpf_link_get_curr_or_next(u32 *id); int bpf_obj_pin_user(u32 ufd, const char __user *pathname); int bpf_obj_get_user(const char __user *pathname, int flags); +int bpf_prog_pin_kernel(const char *name, struct bpf_prog *prog); #define BPF_ITER_FUNC_PREFIX "bpf_iter_" #define DEFINE_BPF_ITER_FUNC(target, args...) \ diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index 4f841e16779e..7be24ffad7f7 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -29,6 +29,9 @@ enum bpf_type { BPF_TYPE_LINK, }; + +static struct super_block *bpffs_sb; + static void *bpf_any_get(void *raw, enum bpf_type type) { switch (type) { @@ -435,6 +438,34 @@ static int bpf_iter_link_pin_kernel(struct dentry *parent, return ret; } +/* pin a program in the bpffs */ +/* TODO: handle path relative to mount point instead of plain name by recreating + * the hierarchy, like in drivers/base/devtmpfs.c + */ +int bpf_prog_pin_kernel(const char *name, struct bpf_prog *prog) +{ + struct dentry *parent; + umode_t mode = S_IFREG | S_IRUSR; + struct dentry *dentry; + int ret; + + if (!bpffs_sb) + return -ENOENT; + + parent = bpffs_sb->s_root; + + inode_lock(parent->d_inode); + dentry = lookup_one_len(name, parent, strlen(name)); + if (IS_ERR(dentry)) { + inode_unlock(parent->d_inode); + return PTR_ERR(dentry); + } + ret = bpf_mkprog(dentry, mode, prog); + dput(dentry); + inode_unlock(parent->d_inode); + return ret; +} + static int bpf_obj_do_pin(const char __user *pathname, void *raw, enum bpf_type type) { @@ -758,6 +789,8 @@ static int bpf_fill_super(struct super_block *sb, struct fs_context *fc) inode->i_mode &= ~S_IALLUGO; populate_bpffs(sb->s_root); inode->i_mode |= S_ISVTX | opts->mode; + + bpffs_sb = sb; return 0; } @@ -795,12 +828,18 @@ static int bpf_init_fs_context(struct fs_context *fc) return 0; } +static void bpf_kill_sb(struct super_block *sb) +{ + bpffs_sb = NULL; + kill_litter_super(sb); +} + static struct file_system_type bpf_fs_type = { .owner = THIS_MODULE, .name = "bpf", .init_fs_context = bpf_init_fs_context, .parameters = bpf_fs_parameters, - .kill_sb = kill_litter_super, + .kill_sb = bpf_kill_sb, }; static int __init bpf_init(void) From patchwork Thu Nov 24 15:15:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055089 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A860C433FE for ; Thu, 24 Nov 2022 15:19:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230076AbiKXPTH (ORCPT ); Thu, 24 Nov 2022 10:19:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230004AbiKXPTC (ORCPT ); Thu, 24 Nov 2022 10:19:02 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1896D16E8EB for ; Thu, 24 Nov 2022 07:16:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302981; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3NqYTNWqKXsbAI7x1/28J4Ht9r4YR+5xoo18QliLmNU=; b=YlZE9SmAUjAfau6ucziGVgfFzzd3EmJR53u4kEfCjMbPqjRrW/sv5Jfylkptei60INLvlI KNyou/YJ426tKVt0OW69S6EzN7Xu0MWd199TGxYWQGqUmCIYLE2UaH3ucn+ucgHizjMG1i AgKCCDiJ2B5+YOiBkF6alt/hTWNxmVk= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-654-Q9d2T61xNyWEl_5TupuZ2g-1; Thu, 24 Nov 2022 10:16:16 -0500 X-MC-Unique: Q9d2T61xNyWEl_5TupuZ2g-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 820FA802C16; Thu, 24 Nov 2022 15:16:15 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id C350F40C2066; Thu, 24 Nov 2022 15:16:13 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 03/10] HID: add a tool to convert a bpf source into a generic bpf loader Date: Thu, 24 Nov 2022 16:15:56 +0100 Message-Id: <20221124151603.807536-4-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC We first use bpftool to generate a json representation of the program, and then use a python script to convert it into a C array element that will be able to be generically loaded by the kernel. Signed-off-by: Benjamin Tissoires --- MAINTAINERS | 1 + drivers/hid/bpf/progs/Makefile | 105 +++++++++++ drivers/hid/bpf/progs/hid_bpf.h | 15 ++ drivers/hid/bpf/progs/hid_bpf_helpers.h | 22 +++ drivers/hid/bpf/progs/hid_bpf_progs.h | 49 +++++ tools/hid/build_progs_list.py | 231 ++++++++++++++++++++++++ 6 files changed, 423 insertions(+) create mode 100644 drivers/hid/bpf/progs/Makefile create mode 100644 drivers/hid/bpf/progs/hid_bpf.h create mode 100644 drivers/hid/bpf/progs/hid_bpf_helpers.h create mode 100644 drivers/hid/bpf/progs/hid_bpf_progs.h create mode 100755 tools/hid/build_progs_list.py diff --git a/MAINTAINERS b/MAINTAINERS index 752126fba795..8580895e280f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9102,6 +9102,7 @@ F: drivers/hid/ F: include/linux/hid* F: include/uapi/linux/hid* F: samples/hid/ +F: tools/hid F: tools/testing/selftests/hid/ HID LOGITECH DRIVERS diff --git a/drivers/hid/bpf/progs/Makefile b/drivers/hid/bpf/progs/Makefile new file mode 100644 index 000000000000..ee0203d3349a --- /dev/null +++ b/drivers/hid/bpf/progs/Makefile @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: GPL-2.0 +OUTPUT := .output +abs_out := $(abspath $(OUTPUT)) + +CLANG ?= clang +LLC ?= llc +LLVM_STRIP ?= llvm-strip + +TOOLS_PATH := $(abspath ../../../../tools) +BPFTOOL_SRC := $(TOOLS_PATH)/bpf/bpftool +BPFTOOL_OUTPUT := $(abs_out)/bpftool +DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)/bootstrap/bpftool +BPFTOOL ?= $(DEFAULT_BPFTOOL) + +LIBBPF_SRC := $(TOOLS_PATH)/lib/bpf +LIBBPF_OUTPUT := $(abs_out)/libbpf +LIBBPF_DESTDIR := $(LIBBPF_OUTPUT) +LIBBPF_INCLUDE := $(LIBBPF_DESTDIR)/include +BPFOBJ := $(LIBBPF_OUTPUT)/libbpf.a + +HID_BPF_CONVERTER := $(TOOLS_PATH)/hid/build_progs_list.py + +INCLUDES := -I$(OUTPUT) -I$(LIBBPF_INCLUDE) -I$(TOOLS_PATH)/include/uapi +CFLAGS := -g -Wall + +VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \ + $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \ + ../../../../vmlinux \ + /sys/kernel/btf/vmlinux \ + /boot/vmlinux-$(shell uname -r) +VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS)))) +ifeq ($(VMLINUX_BTF),) +$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)") +endif + +ifeq ($(V),1) +Q = +msg = +else +Q = @ +msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; +MAKEFLAGS += --no-print-directory +submake_extras := feature_display=0 +endif + +.DELETE_ON_ERROR: + +.PHONY: all + +TARGETS = $(patsubst %.bpf.c,%.hidbpf.h, $(wildcard *.bpf.c)) +TARGETS += hid_bpf_progs.h + +all: $(TARGETS) + +clean: + $(call msg,CLEAN) + $(Q)rm -rf $(OUTPUT) $(TARGETS) + +$(OUTPUT)/%.json: $(OUTPUT)/%.bpf.o | $(BPFTOOL) + $(call msg,GEN-SKEL,$@) + $(Q)$(BPFTOOL) gen skeleton -L -j $< > $@ + +%.hidbpf.h: $(OUTPUT)/%.json | $(HID_BPF_CONVERTER) + $(call msg,GEN-HIDBPF,$@) + $(Q)$(HID_BPF_CONVERTER) build_prog $< -o $@ + +hid_bpf_progs.h: $(addprefix $(OUTPUT)/,$(patsubst %.bpf.c,%.json, $(wildcard *.bpf.c))) | $(HID_BPF_CONVERTER) + $(call msg,GEN-HIDBPF-LIST,$@) + $(Q)$(HID_BPF_CONVERTER) build_list $< -o $@ + +$(OUTPUT)/%.bpf.o: %.bpf.c $(OUTPUT)/vmlinux.h $(BPFOBJ) | $(OUTPUT) + $(call msg,BPF,$@) + $(Q)$(CLANG) -g -O2 -target bpf $(INCLUDES) \ + -c $(filter %.c,$^) -o $@ && \ + $(LLVM_STRIP) -g $@ + +$(OUTPUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR) +ifeq ($(VMLINUX_H),) + $(call msg,GEN,,$@) + $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@ +else + $(call msg,CP,,$@) + $(Q)cp "$(VMLINUX_H)" $@ +endif + +$(OUTPUT) $(LIBBPF_OUTPUT) $(BPFTOOL_OUTPUT): + $(call msg,MKDIR,$@) + $(Q)mkdir -p $@ + +$(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OUTPUT) + $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) \ + OUTPUT=$(abspath $(dir $@))/ prefix= \ + DESTDIR=$(LIBBPF_DESTDIR) $(abspath $@) install_headers + +ifeq ($(CROSS_COMPILE),) +$(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT) + $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC) \ + OUTPUT=$(BPFTOOL_OUTPUT)/ \ + LIBBPF_BOOTSTRAP_OUTPUT=$(LIBBPF_OUTPUT)/ \ + LIBBPF_BOOTSTRAP_DESTDIR=$(LIBBPF_DESTDIR)/ bootstrap +else +$(DEFAULT_BPFTOOL): $(BPFTOOL_OUTPUT) + $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC) \ + OUTPUT=$(BPFTOOL_OUTPUT)/ bootstrap +endif diff --git a/drivers/hid/bpf/progs/hid_bpf.h b/drivers/hid/bpf/progs/hid_bpf.h new file mode 100644 index 000000000000..7ee371cac2e1 --- /dev/null +++ b/drivers/hid/bpf/progs/hid_bpf.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2022 Benjamin Tissoires + */ + +#ifndef ____HID_BPF__H +#define ____HID_BPF__H + +struct hid_bpf_probe_args { + unsigned int hid; + unsigned int rdesc_size; + unsigned char rdesc[4096]; + int retval; +}; + +#endif /* ____HID_BPF__H */ diff --git a/drivers/hid/bpf/progs/hid_bpf_helpers.h b/drivers/hid/bpf/progs/hid_bpf_helpers.h new file mode 100644 index 000000000000..4c4e63a516b3 --- /dev/null +++ b/drivers/hid/bpf/progs/hid_bpf_helpers.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2022 Benjamin Tissoires + */ + +#ifndef __HID_BPF_HELPERS_H +#define __HID_BPF_HELPERS_H + +#include "vmlinux.h" +#include + +extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx, + unsigned int offset, + const size_t __sz) __ksym; +extern struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id) __ksym; +extern void hid_bpf_release_context(struct hid_bpf_ctx *ctx) __ksym; +extern int hid_bpf_hw_request(struct hid_bpf_ctx *ctx, + __u8 *data, + size_t buf__sz, + enum hid_report_type type, + enum hid_class_request reqtype) __ksym; + +#endif /* __HID_BPF_HELPERS_H */ diff --git a/drivers/hid/bpf/progs/hid_bpf_progs.h b/drivers/hid/bpf/progs/hid_bpf_progs.h new file mode 100644 index 000000000000..430e0fb47484 --- /dev/null +++ b/drivers/hid/bpf/progs/hid_bpf_progs.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +/* THIS FILE IS AUTOGENERATED BY build_progs_list.py ! */ + +#ifndef __HID_BPF_PROGS_H__ +#define __HID_BPF_PROGS_H__ + +/** + * struct hid_bpf_map: custom HID representation of a map + */ +struct hid_bpf_map { + unsigned int size; + unsigned int mmap_sz; + char *data; +}; + +/** + * struct hid_bpf_prog: custom HID representation of a program + */ +struct hid_bpf_prog { +}; + +/** + * struct hid_bpf_object: custom HID representation of a BPF object + * @map_cnt: number of maps available in the BPF object + * @prog_cnt: number of programs available + * @probe: index of the probe program if any (greater than prog_cnt if none) + */ +struct hid_bpf_object { + struct hid_device_id id; + unsigned int map_cnt; + struct hid_bpf_map maps[0]; + unsigned int prog_cnt; + struct hid_bpf_prog progs[0]; + unsigned int probe; + unsigned int rodata; + unsigned int data_sz; + char *data; + unsigned int insns_sz; + char *insns; +}; + +static struct hid_bpf_object hid_objects[] = { + + + { }, +}; + +#endif /* __HID_BPF_PROGS_H__ */ + diff --git a/tools/hid/build_progs_list.py b/tools/hid/build_progs_list.py new file mode 100755 index 000000000000..8103bc2f433f --- /dev/null +++ b/tools/hid/build_progs_list.py @@ -0,0 +1,231 @@ +#!/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2022 Benjamin Tissoires + +import argparse +import json +import re +import sys + +from pathlib import Path + + +def create_header(fp, max_maps_cnt, max_progs_cnt): + print( + f"""/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +/* THIS FILE IS AUTOGENERATED BY build_progs_list.py ! */ + +#ifndef __HID_BPF_PROGS_H__ +#define __HID_BPF_PROGS_H__ + +/** + * struct hid_bpf_map: custom HID representation of a map + */ +struct hid_bpf_map {{ + unsigned int size; + unsigned int mmap_sz; + char *data; +}}; + +/** + * struct hid_bpf_prog: custom HID representation of a program + */ +struct hid_bpf_prog {{ +}}; + +/** + * struct hid_bpf_object: custom HID representation of a BPF object + * @map_cnt: number of maps available in the BPF object + * @prog_cnt: number of programs available + * @probe: index of the probe program if any (greater than prog_cnt if none) + */ +struct hid_bpf_object {{ + struct hid_device_id id; + unsigned int map_cnt; + struct hid_bpf_map maps[{max_maps_cnt}]; + unsigned int prog_cnt; + struct hid_bpf_prog progs[{max_progs_cnt}]; + unsigned int probe; + unsigned int rodata; + unsigned int data_sz; + char *data; + unsigned int insns_sz; + char *insns; +}}; + +static struct hid_bpf_object hid_objects[] = {{ +""", + file=fp, + ) + + +def create_footer(fp): + print( + """ + { }, +}; + +#endif /* __HID_BPF_PROGS_H__ */ +""", + file=fp, + ) + + +def get_bus_group_vid_pid(json_data): + path_regex = re.compile( + r"b([0-9a-fA-F]{4})g([0-9a-fA-F]{4})v([0-9a-fA-F]{4})p([0-9a-fA-F]{4}).*" + ) + return path_regex.match(json_data["name"]) + + +def is_valid_bpf_json(json_data): + return get_bus_group_vid_pid(json_data) is not None and json_data["use_loader"] + + +def build_prog_list(args): + input_files = [Path(p) for p in args.path] + output = args.output + max_maps_cnt = 0 + max_progs_cnt = 0 + valid_files = [] + + for prog in input_files: + with open(prog) as f: + data = json.load(f) + if not is_valid_bpf_json(data): + print(f"ignoring {prog.relative_to('.')}", file=sys.stderr) + continue + generated_name = prog.name.replace(".json", ".hidbpf.h") + max_maps_cnt = max(max_maps_cnt, len(data["maps"])) + max_progs_cnt = max(max_progs_cnt, len(data["progs"])) + + valid_files.append(generated_name) + + create_header(output, max_maps_cnt, max_progs_cnt) + + valid_files.sort() + + for file in valid_files: + print(f'#include "{file}"', file=output) + + create_footer(output) + + +def write_c_data(bytes): + outputs = ['"', ''] + for b in bytes: + w = 2 if b == '0x00' else 4 + if len(outputs[-1]) + w > 78: + outputs.append('') + if b != "0x00": + outputs[-1] += f"\\x{b[2:]}" + else: + outputs[-1] += "\\0" + outputs[-1] += '"' + return '\\\n'.join(outputs) + + +def build_c_object(args): + input_file = Path(args.path[0]) + output = args.output + + with open(input_file) as f: + data = json.load(f) + + if not is_valid_bpf_json(data): + print(f"ignoring {input_file.relative_to('.')}", file=sys.stderr) + return + + try: + probe_idx = [p["name"] for p in data["progs"]].index("probe") + except ValueError: + probe_idx = len(data["progs"]) + 1 + + try: + rodata_idx = [m["ident"] for m in data["maps"]].index("rodata") + except ValueError: + rodata_idx = len(data["maps"]) + 1 + + header_marker = ( + f"__{input_file.name}__".replace(".", "_") + .replace("-", "_") + .replace("json", "hidbpf_h") + .upper() + ) + m = get_bus_group_vid_pid(data) + output.write( + f"""/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +/* THIS FILE IS AUTOGENERATED BY build_progs_list.py ! */ + +#ifndef {header_marker} +#define {header_marker} + +{{ + .id = {{ + .bus = 0x{m.group(1)}, + .group = 0x{m.group(2)}, + .vendor = 0x{m.group(3)}, + .product = 0x{m.group(4)}, + }}, + .map_cnt = {len(data['maps'])}, + .prog_cnt = {len(data['progs'])}, + .probe = {probe_idx}, + .rodata = {rodata_idx}, + .maps = {{""") + + for map in data['maps']: + output.write(f""" + {{ + .size = {map['size']}, + .mmap_sz = {map['mmap_sz']}, + .data = {write_c_data(map['data'])}, + }},""") + + output.write(f""" + }}, + .data_sz = {data['data_sz']}, + .data = {write_c_data(data['data'])}, + .insns_sz = {data['insns_sz']}, + .insns = {write_c_data(data['insns'])}, +}}, + +#endif /* {header_marker} */ +""" + ) + + +def main(): + ap = argparse.ArgumentParser(description="custom HID BPF json converter") + + def add_output(parser): + parser.add_argument( + "-o", + "--output", + nargs="?", + type=argparse.FileType("w"), + default=sys.stdout, + help="Output file, if not given, use stdout", + ) + + sp = ap.add_subparsers(help="sub-command help") + + obj_parser = sp.add_parser( + "build_prog", help="Convert a JSON into a generic HID BPF header" + ) + obj_parser.add_argument("path", nargs=1, help="Input file.", metavar="PATH") + add_output(obj_parser) + obj_parser.set_defaults(func=build_c_object) + + list_parser = sp.add_parser( + "build_list", help="Convert a list of JSON into a generic HID BPF header list" + ) + list_parser.add_argument("path", nargs="*", help="Input file(s).", metavar="PATH") + add_output(list_parser) + list_parser.set_defaults(func=build_prog_list) + + args = ap.parse_args() + args.func(args) + + +if __name__ == "__main__": + main() From patchwork Thu Nov 24 15:15:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055090 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3EB7CC46467 for ; Thu, 24 Nov 2022 15:19:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230103AbiKXPTJ (ORCPT ); Thu, 24 Nov 2022 10:19:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230017AbiKXPTC (ORCPT ); Thu, 24 Nov 2022 10:19:02 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 177DA16E8F6 for ; Thu, 24 Nov 2022 07:16:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302983; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=G4mRjiCLMtLsImdt9LVO/5YkmYrf/jxzVEf75LrlJsQ=; b=WMoqfhHIPur4m39uFdD55swI3TPWyip5MR+/YEd6VWpIz8tuCUueamx55JMG1Wo/cfoovM 4kou/7/hISLQ/ogpwR3j4M1hgXo2xNxsau3JIiIsNVXaRrr9PyeUSyWLh/59VlrteckzJ2 3h6tUnmmR8SrpAv7v7C3o0cwbaJbTZ4= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-360-LihkDvwXO72orWAoMDlcbQ-1; Thu, 24 Nov 2022 10:16:18 -0500 X-MC-Unique: LihkDvwXO72orWAoMDlcbQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8FBE58582B9; Thu, 24 Nov 2022 15:16:17 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id BD6CA40C2064; Thu, 24 Nov 2022 15:16:15 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 04/10] HID: add the bpf loader that can attach a generic hid-bpf program Date: Thu, 24 Nov 2022 16:15:57 +0100 Message-Id: <20221124151603.807536-5-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC When a device is added to the hid bus, we check if there are any known in-kernel bpf programs related to this device, and when found, we load them, run the probe syscall if any, and then attach and pin those programs to the HID device before presenting it to the userspace. There are still a few bits missing right now: - the list of programs should not be in kernel but in a separated module at least - the pinned program has an incorrect path (not namespaced to the device) - the pinned program stay around when the device is disconnected - we could use the firmware interface to replace the array of programs, but how do we distribute and install them? Signed-off-by: Benjamin Tissoires --- drivers/hid/bpf/Makefile | 3 +- drivers/hid/bpf/hid_bpf_dispatch.c | 3 +- drivers/hid/bpf/hid_bpf_loader.c | 243 +++++++++++++++++++++++++++++ drivers/hid/hid-core.c | 2 + include/linux/hid_bpf.h | 2 + 5 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 drivers/hid/bpf/hid_bpf_loader.c diff --git a/drivers/hid/bpf/Makefile b/drivers/hid/bpf/Makefile index cf55120cf7d6..d0c5fbc506b4 100644 --- a/drivers/hid/bpf/Makefile +++ b/drivers/hid/bpf/Makefile @@ -8,4 +8,5 @@ LIBBPF_INCLUDE = $(srctree)/tools/lib obj-$(CONFIG_HID_BPF) += hid_bpf.o CFLAGS_hid_bpf_dispatch.o += -I$(LIBBPF_INCLUDE) CFLAGS_hid_bpf_jmp_table.o += -I$(LIBBPF_INCLUDE) -hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o +CFLAGS_hid_bpf_loader.o += -I$(LIBBPF_INCLUDE) +hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o hid_bpf_loader.o diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c index c3920c7964dc..3c989e74d249 100644 --- a/drivers/hid/bpf/hid_bpf_dispatch.c +++ b/drivers/hid/bpf/hid_bpf_dispatch.c @@ -238,7 +238,8 @@ static int hid_bpf_allocate_event_data(struct hid_device *hdev) int hid_bpf_reconnect(struct hid_device *hdev) { - if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status)) + if (hdev->status & HID_STAT_ADDED && + !test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status)) return device_reprobe(&hdev->dev); return 0; diff --git a/drivers/hid/bpf/hid_bpf_loader.c b/drivers/hid/bpf/hid_bpf_loader.c new file mode 100644 index 000000000000..d2aa0a8e78c7 --- /dev/null +++ b/drivers/hid/bpf/hid_bpf_loader.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2022 Benjamin Tissoires + */ + +#include +#include +#include +#include + +#include "hid_bpf_dispatch.h" +#include "progs/hid_bpf.h" +#include "progs/hid_bpf_progs.h" + +struct generic_bpf_skel { + struct hid_bpf_object *obj; + struct bpf_map_desc *maps; + struct bpf_prog_desc *progs; + int *links; + void *rodata; + /* + * ctx needs to come last, it is populated by the bpf loader + * beyond the end of the struct, which we get through maps + * and progs above. + */ + struct bpf_loader_ctx ctx; +}; + +static size_t hid_bpf_get_obj_ctx_size(struct hid_bpf_object *obj) +{ + return sizeof(struct generic_bpf_skel) + + sizeof(struct bpf_map_desc) * obj->map_cnt + + sizeof(struct bpf_prog_desc) * obj->prog_cnt + + sizeof(int) * obj->prog_cnt; +} + +static void +generic_bpf_skel__detach(struct generic_bpf_skel *skel) +{ + int i; + + for (i = 0; i < skel->obj->prog_cnt; i++) + skel_closenz(skel->links[i]); +} + +static void +generic_bpf_skel__destroy(struct generic_bpf_skel *skel) +{ + int i; + + if (!skel) + return; + + generic_bpf_skel__detach(skel); + + for (i = 0; i < skel->obj->prog_cnt; i++) + skel_closenz(skel->progs[i].prog_fd); + + if (skel->obj->rodata < skel->obj->map_cnt) { + skel_free_map_data(skel->rodata, + skel->maps[skel->obj->rodata].initial_value, + skel->obj->maps[skel->obj->rodata].mmap_sz); + } + + for (i = 0; i < skel->obj->map_cnt; i++) + skel_closenz(skel->maps[i].map_fd); + + skel_free(skel); +} + +static struct generic_bpf_skel * +generic_bpf_skel__open(struct hid_bpf_object *obj) +{ + struct generic_bpf_skel *skel; + + skel = skel_alloc(hid_bpf_get_obj_ctx_size(obj)); + if (!skel) + goto cleanup; + skel->obj = obj; + skel->ctx.sz = hid_bpf_get_obj_ctx_size(obj) - offsetof(struct generic_bpf_skel, ctx); + + skel->maps = (struct bpf_map_desc *)(skel + 1); + skel->progs = (struct bpf_prog_desc *)(skel->maps + obj->map_cnt); + skel->links = (int *)(skel->progs + obj->prog_cnt); + + if (obj->rodata < obj->map_cnt) { + skel->rodata = skel_prep_map_data((void *)obj->maps[obj->rodata].data, + obj->maps[obj->rodata].mmap_sz, + obj->maps[obj->rodata].size); + + if (!skel->rodata) + goto cleanup; + skel->maps[obj->rodata].initial_value = (__u64) (long) skel->rodata; + } + + return (struct generic_bpf_skel *)skel; + +cleanup: + generic_bpf_skel__destroy((struct generic_bpf_skel *)skel); + return NULL; +} + +static int +generic_bpf_skel__load(struct generic_bpf_skel *skel) +{ + struct bpf_load_and_run_opts opts = {}; + int err; + + opts.ctx = &skel->ctx; + opts.data_sz = skel->obj->data_sz; + opts.data = (void *)skel->obj->data; + opts.insns_sz = skel->obj->insns_sz; + opts.insns = skel->obj->insns; + + err = bpf_load_and_run(&opts); + if (err < 0) + return err; + + if (skel->obj->rodata < skel->obj->map_cnt) { + skel->rodata = skel_finalize_map_data(&skel->maps[skel->obj->rodata].initial_value, + skel->obj->maps[skel->obj->rodata].mmap_sz, + PROT_READ, + skel->maps[skel->obj->rodata].map_fd); + if (!skel->rodata) + return -ENOMEM; + } + + return 0; +} + +static struct generic_bpf_skel * +generic_bpf_skel__open_and_load(struct hid_bpf_object *obj) +{ + struct generic_bpf_skel *skel; + + skel = generic_bpf_skel__open(obj); + if (!skel) + return NULL; + if (generic_bpf_skel__load(skel)) { + generic_bpf_skel__destroy(skel); + return NULL; + } + return skel; +} + +static int +execute_probe(struct hid_device *hdev, struct generic_bpf_skel *skel) +{ + const size_t test_run_attr_sz = offsetofend(union bpf_attr, test); + struct hid_bpf_probe_args *ctx; + union bpf_attr attr; + int err; + + /* early abort if there is no probe program */ + if (skel->obj->probe >= skel->obj->prog_cnt) + return 0; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + memset(&attr, 0, test_run_attr_sz); + + attr.test.prog_fd = skel->progs[skel->obj->probe].prog_fd; + + attr.test.ctx_in = (long) ctx; + attr.test.ctx_size_in = sizeof(*ctx); + + ctx->hid = hdev->id; + + ctx->rdesc_size = hdev->dev_rsize; + + memcpy(ctx->rdesc, hdev->dev_rdesc, + min_t(unsigned int, sizeof(ctx->rdesc), hdev->dev_rsize)); + + err = skel_sys_bpf(BPF_PROG_RUN, &attr, test_run_attr_sz); + if (err < 0 || (int)attr.test.retval < 0) { + if (err == 0) + err = (int)attr.test.retval; + } else { + err = ctx->retval; + } + + kfree(ctx); + return err; +} + +static void __hid_load_internal_bpf_program(struct hid_device *hdev, struct hid_bpf_object *obj) +{ + struct generic_bpf_skel *skel; + int err; + + skel = generic_bpf_skel__open_and_load(obj); + if (!skel) + return; + + err = execute_probe(hdev, skel); + if (err) + goto out; + + /* + * The bpf object is loaded and probe returned 0, we can bind + * all of its HID-BPF programs to the device. + */ + for (int i = 0; i < obj->prog_cnt; i++) { + int prog_fd = skel->progs[i].prog_fd; + enum hid_bpf_prog_type prog_type; + struct bpf_prog *prog; + + if (i == obj->probe) + continue; + + prog_type = hid_bpf_get_prog_attach_type(prog_fd); + + /* ignore non HID-BPF programs */ + if (prog_type < 0 || prog_type >= HID_BPF_PROG_TYPE_MAX) + continue; + + err = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, 0); + + if (!err) { + prog = bpf_prog_get(prog_fd); + /* TODO: prefix the name with 'hid/bus_vid_pid_id/' */ + err = bpf_prog_pin_kernel(prog->aux->name, prog); + if (err) + bpf_prog_put(prog); + } + } + + out: + generic_bpf_skel__destroy(skel); +} + +int hid_load_internal_bpf_programs(struct hid_device *hdev) +{ + struct hid_bpf_object *obj; + + for (obj = &hid_objects[0]; obj->id.bus; obj++) { + if (hid_match_one_id(hdev, &obj->id)) + __hid_load_internal_bpf_program(hdev, obj); + } + return 0; +} +EXPORT_SYMBOL_GPL(hid_load_internal_bpf_programs); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index fa4436b8101e..b27b4faad5bc 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2761,6 +2761,8 @@ int hid_add_device(struct hid_device *hdev) dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, hdev->vendor, hdev->product, hdev->id); + hid_load_internal_bpf_programs(hdev); + hid_debug_register(hdev, dev_name(&hdev->dev)); ret = device_add(&hdev->dev); if (!ret) diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h index 3ca85ab91325..2b06ddf64c1c 100644 --- a/include/linux/hid_bpf.h +++ b/include/linux/hid_bpf.h @@ -146,6 +146,7 @@ void hid_bpf_disconnect_device(struct hid_device *hdev); void hid_bpf_destroy_device(struct hid_device *hid); void hid_bpf_device_init(struct hid_device *hid); u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size); +int hid_load_internal_bpf_programs(struct hid_device *hdev); #else /* CONFIG_HID_BPF */ static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 *size, int interrupt) { return data; } @@ -157,6 +158,7 @@ static inline u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, u { return kmemdup(rdesc, *size, GFP_KERNEL); } +static inline int hid_load_internal_bpf_programs(struct hid_device *hdev) { return 0; } #endif /* CONFIG_HID_BPF */ From patchwork Thu Nov 24 15:15:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055088 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EDD9AC4321E for ; Thu, 24 Nov 2022 15:18:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229989AbiKXPSz (ORCPT ); Thu, 24 Nov 2022 10:18:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59552 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229548AbiKXPSy (ORCPT ); Thu, 24 Nov 2022 10:18:54 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 80D5416F0C0 for ; Thu, 24 Nov 2022 07:16:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302984; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a63w9CoIFkndcfzkV+UlHKPl/w2rk67fLhqjC6Ra/nQ=; b=HmsAvzJG7707Wwv/iqLX4lNEui/lBHrycjwvScZtZRshLry8vodwoFHEaCMAeE/57o4p/h 9k5K08VaTm+oxfBSVXyzePKSFDV7VssYBgEky4gacG+dOjWHkFBT/2JyD/6S4qiEpWLX9X WJEceEdGHnnvGbjgnXLsuDogspQ1FcY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-136-tAQIrwjqPDig82dTfIdrlw-1; Thu, 24 Nov 2022 10:16:20 -0500 X-MC-Unique: tAQIrwjqPDig82dTfIdrlw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A6B41185A78B; Thu, 24 Nov 2022 15:16:19 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id CB78040C2064; Thu, 24 Nov 2022 15:16:17 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 05/10] HID: add report descriptor override for the X-Keys XK24 Date: Thu, 24 Nov 2022 16:15:58 +0100 Message-Id: <20221124151603.807536-6-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC The current report descriptor of the XK-24 is hiding all programmable buttons. However, we can export them as such, so userspace do not need to reprogram the device itself and can have some handling depending on the application. Also add the compiled files as a demonstration of the output, but hopefully these outputs should be generated automatically when running make at the root of the kernel sources. Signed-off-by: Benjamin Tissoires --- .../bpf/progs/b0003g0001v05F3p0405-xk24.bpf.c | 106 +++++++ .../progs/b0003g0001v05F3p0405-xk24.hidbpf.h | 292 ++++++++++++++++++ drivers/hid/bpf/progs/hid_bpf_progs.h | 5 +- 3 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 drivers/hid/bpf/progs/b0003g0001v05F3p0405-xk24.bpf.c create mode 100644 drivers/hid/bpf/progs/b0003g0001v05F3p0405-xk24.hidbpf.h diff --git a/drivers/hid/bpf/progs/b0003g0001v05F3p0405-xk24.bpf.c b/drivers/hid/bpf/progs/b0003g0001v05F3p0405-xk24.bpf.c new file mode 100644 index 000000000000..736861988a94 --- /dev/null +++ b/drivers/hid/bpf/progs/b0003g0001v05F3p0405-xk24.bpf.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2022 Benjamin Tissoires + */ + +#include "vmlinux.h" +#include "hid_bpf_helpers.h" +#include + +static const __u8 fixed_rdesc[] = { + 0x05, 0x0c, // Usage Page (Consumer Devices) + 0x09, 0x01, // Usage (Consumer Control) + 0xa1, 0x01, // Collection (Application) + + 0xa1, 0x02, // Collection (Logical) + 0x05, 0x08, // Usage Page (LEDs) + 0x09, 0x4b, // Usage (Generic Indicator) + 0x75, 0x08, // Report Size (8) + 0x95, 0x23, // Report Count (35) + 0x91, 0x02, // Output (Data,Var,Abs) + 0xc0, // End Collection + + 0xa1, 0x02, // Collection (Logical) + 0x09, 0x00, // Usage (Undefined) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Cnst,Var,Abs) + 0x05, 0x09, // Usage Page (Button) + 0x09, 0xff, // Usage (Vendor Usage 0xff) + 0x75, 0x01, // Report Size (1) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs) + 0x95, 0x07, // Report Count (7) + 0x81, 0x03, // Input (Cnst,Var,Abs) + + 0x05, 0x0c, // Usage Page (Consumer Devices) + 0x09, 0x03, // Usage (Programmable Buttons) + 0xa1, 0x04, // Collection (Named_array) + 0x05, 0x09, // Usage Page (Button) + + 0x19, 0x01, // Usage Minimum (1) + 0x29, 0x06, // Usage Maximum (6) + 0x95, 0x06, // Report Count (6) + 0x81, 0x02, // Input (Data,Var,Abs) + 0x95, 0x02, // Report Count (2) + 0x81, 0x03, // Input (Cnst,Var,Abs) + + 0x19, 0x07, // Usage Minimum (7) + 0x29, 0x0c, // Usage Maximum (12) + 0x95, 0x06, // Report Count (6) + 0x81, 0x02, // Input (Data,Var,Abs) + 0x95, 0x02, // Report Count (2) + 0x81, 0x03, // Input (Cnst,Var,Abs) + + 0x19, 0x0d, // Usage Minimum (13) + 0x29, 0x12, // Usage Maximum (18) + 0x95, 0x06, // Report Count (6) + 0x81, 0x02, // Input (Data,Var,Abs) + 0x95, 0x02, // Report Count (2) + 0x81, 0x03, // Input (Cnst,Var,Abs) + + 0x19, 0x13, // Usage Minimum (19) + 0x29, 0x19, // Usage Maximum (24) + 0x95, 0x06, // Report Count (6) + 0x81, 0x02, // Input (Data,Var,Abs) + 0x95, 0x02, // Report Count (2) + 0x81, 0x03, // Input (Cnst,Var,Abs) + + 0xc0, // End Collection + + 0x75, 0x08, // Report Size (8) + 0x95, 0x1a, // Report Count (26) + 0x81, 0x03, // Input (Cnst,Var,Abs) + 0xc0, // End Collection + 0xc0, // End Collection +}; + +SEC("fmod_ret/hid_bpf_rdesc_fixup") +int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx) +{ + s16 y; + __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); + + if (!data) + return 0; /* EPERM check */ + + __builtin_memcpy(data, fixed_rdesc, sizeof(fixed_rdesc)); + + return sizeof(fixed_rdesc); + + return 0; +} + +SEC("syscall") +int probe(struct hid_bpf_probe_args *ctx) +{ + /* + * The device exports 3 interfaces. + */ + ctx->retval = ctx->rdesc_size != 33; + if (ctx->retval) + ctx->retval = -22; + + return 0; +} + +char _license[] SEC("license") = "GPL"; diff --git a/drivers/hid/bpf/progs/b0003g0001v05F3p0405-xk24.hidbpf.h b/drivers/hid/bpf/progs/b0003g0001v05F3p0405-xk24.hidbpf.h new file mode 100644 index 000000000000..f193d4dea6fd --- /dev/null +++ b/drivers/hid/bpf/progs/b0003g0001v05F3p0405-xk24.hidbpf.h @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +/* THIS FILE IS AUTOGENERATED BY build_progs_list.py ! */ + +#ifndef __B0003G0001V05F3P0405_XK24_HIDBPF_H__ +#define __B0003G0001V05F3P0405_XK24_HIDBPF_H__ + +{ + .id = { + .bus = 0x0003, + .group = 0x0001, + .vendor = 0x05F3, + .product = 0x0405, + }, + .map_cnt = 1, + .prog_cnt = 2, + .probe = 1, + .rodata = 0, + .maps = { + { + .size = 108, + .mmap_sz = 4096, + .data = "\ +\x05\x0c\x09\x01\xa1\x01\xa1\x02\x05\x08\x09\x4b\x75\x08\x95\x23\x91\x02\xc0\ +\xa1\x02\x09\0\x75\x08\x95\x01\x81\x03\x05\x09\x09\xff\x75\x01\x95\x01\x81\x02\ +\x95\x07\x81\x03\x05\x0c\x09\x03\xa1\x04\x05\x09\x19\x01\x29\x06\x95\x06\x81\ +\x02\x95\x02\x81\x03\x19\x07\x29\x0c\x95\x06\x81\x02\x95\x02\x81\x03\x19\x0d\ +\x29\x12\x95\x06\x81\x02\x95\x02\x81\x03\x19\x13\x29\x19\x95\x06\x81\x02\x95\ +\x02\x81\x03\xc0\x75\x08\x95\x1a\x81\x03\xc0\xc0", + }, + }, + .data_sz = 5088, + .data = "\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\xeb\x01\0\ +\x18\0\0\0\0\0\0\0\x28\x03\0\0\x28\x03\0\0\x4c\x03\0\0\0\0\0\0\0\0\0\x02\x02\0\ +\0\0\x01\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x0d\x04\0\0\0\x14\ +\0\0\0\x01\0\0\0\x18\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\x1c\0\0\0\x01\0\0\ +\x0c\x03\0\0\0\0\0\0\0\x03\0\0\x0d\x07\0\0\0\x41\x03\0\0\x0a\0\0\0\x41\x03\0\0\ +\x0d\0\0\0\x41\x03\0\0\x13\0\0\0\0\0\0\0\0\0\0\x02\x08\0\0\0\x58\x01\0\0\0\0\0\ +\x08\x09\0\0\0\x5d\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\x02\x0b\ +\0\0\0\x6b\x01\0\0\x05\0\0\x04\x20\0\0\0\x77\x01\0\0\x0c\0\0\0\0\0\0\0\x7d\x01\ +\0\0\x0e\0\0\0\x40\0\0\0\x81\x01\0\0\x0c\0\0\0\x80\0\0\0\x90\x01\0\0\x10\0\0\0\ +\xa0\0\0\0\0\0\0\0\x11\0\0\0\xc0\0\0\0\x9c\x01\0\0\0\0\0\x08\x0d\0\0\0\xa2\x01\ +\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x0f\0\0\0\0\0\0\0\0\0\0\ +\x0a\x28\0\0\0\xaf\x01\0\0\x04\0\0\x06\x04\0\0\0\xbf\x01\0\0\0\0\0\0\xd0\x01\0\ +\0\x01\0\0\0\xe2\x01\0\0\x02\0\0\0\xf5\x01\0\0\x03\0\0\0\0\0\0\0\x02\0\0\x05\ +\x04\0\0\0\x06\x02\0\0\x12\0\0\0\0\0\0\0\x0d\x02\0\0\x12\0\0\0\0\0\0\0\x12\x02\ +\0\0\0\0\0\x08\x04\0\0\0\0\0\0\0\0\0\0\x0a\x14\0\0\0\x18\x02\0\0\0\0\0\x08\x15\ +\0\0\0\x1f\x02\0\0\0\0\0\x08\x16\0\0\0\x2f\x02\0\0\0\0\0\x08\x17\0\0\0\x40\x02\ +\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\x4e\x02\0\0\x01\0\0\x0c\x06\0\0\0\0\0\0\0\0\ +\0\0\x02\x1a\0\0\0\x5f\x02\0\0\x04\0\0\x04\x0c\x10\0\0\x7d\x01\0\0\x0d\0\0\0\0\ +\0\0\0\x72\x02\0\0\x0d\0\0\0\x20\0\0\0\x7d\x02\0\0\x1b\0\0\0\x40\0\0\0\x06\x02\ +\0\0\x04\0\0\0\x40\x80\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x09\0\0\0\x1c\0\0\0\0\x10\ +\0\0\x83\x02\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\x0d\x04\0\0\0\ +\x14\0\0\0\x19\0\0\0\x97\x02\0\0\x01\0\0\x0c\x1d\0\0\0\x05\x03\0\0\0\0\0\x01\ +\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x1f\0\0\0\x1c\0\0\0\x04\0\0\0\ +\x0a\x03\0\0\0\0\0\x0e\x20\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x0a\x08\0\0\0\0\0\0\0\ +\0\0\0\x03\0\0\0\0\x22\0\0\0\x1c\0\0\0\x6c\0\0\0\x13\x03\0\0\0\0\0\x0e\x23\0\0\ +\0\0\0\0\0\x1f\x03\0\0\x01\0\0\x0f\x04\0\0\0\x29\0\0\0\0\0\0\0\x04\0\0\0\x26\ +\x03\0\0\x01\0\0\x0f\x6c\0\0\0\x24\0\0\0\0\0\0\0\x6c\0\0\0\x2e\x03\0\0\x01\0\0\ +\x0f\x04\0\0\0\x21\0\0\0\0\0\0\0\x04\0\0\0\x36\x03\0\0\0\0\0\x07\0\0\0\0\x41\ +\x03\0\0\0\0\0\x0e\x04\0\0\0\x01\0\0\0\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\ +\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x63\x74\x78\0\x69\x6e\x74\0\x68\x69\x64\ +\x5f\x66\x69\x78\x5f\x72\x64\x65\x73\x63\0\x66\x6d\x6f\x64\x5f\x72\x65\x74\x2f\ +\x68\x69\x64\x5f\x62\x70\x66\x5f\x72\x64\x65\x73\x63\x5f\x66\x69\x78\x75\x70\0\ +\x2f\x68\x6f\x6d\x65\x2f\x62\x74\x69\x73\x73\x6f\x69\x72\x2f\x53\x72\x63\x2f\ +\x68\x69\x64\x2f\x64\x72\x69\x76\x65\x72\x73\x2f\x68\x69\x64\x2f\x62\x70\x66\ +\x2f\x70\x72\x6f\x67\x73\x2f\x62\x30\x30\x30\x33\x67\x30\x30\x30\x31\x76\x30\ +\x35\x46\x33\x70\x30\x34\x30\x35\x2d\x78\x6b\x32\x34\x2e\x62\x70\x66\x2e\x63\0\ +\x69\x6e\x74\x20\x42\x50\x46\x5f\x50\x52\x4f\x47\x28\x68\x69\x64\x5f\x66\x69\ +\x78\x5f\x72\x64\x65\x73\x63\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x68\x69\x64\ +\x5f\x62\x70\x66\x5f\x63\x74\x78\x20\x2a\x68\x63\x74\x78\x29\0\x09\x5f\x5f\x75\ +\x38\x20\x2a\x64\x61\x74\x61\x20\x3d\x20\x68\x69\x64\x5f\x62\x70\x66\x5f\x67\ +\x65\x74\x5f\x64\x61\x74\x61\x28\x68\x63\x74\x78\x2c\x20\x30\x20\x2f\x2a\x20\ +\x6f\x66\x66\x73\x65\x74\x20\x2a\x2f\x2c\x20\x34\x30\x39\x36\x20\x2f\x2a\x20\ +\x73\x69\x7a\x65\x20\x2a\x2f\x29\x3b\0\x09\x69\x66\x20\x28\x21\x64\x61\x74\x61\ +\x29\0\x09\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x5f\x6d\x65\x6d\x63\x70\x79\x28\ +\x64\x61\x74\x61\x2c\x20\x66\x69\x78\x65\x64\x5f\x72\x64\x65\x73\x63\x2c\x20\ +\x73\x69\x7a\x65\x6f\x66\x28\x66\x69\x78\x65\x64\x5f\x72\x64\x65\x73\x63\x29\ +\x29\x3b\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\ +\x72\0\x68\x69\x64\x5f\x62\x70\x66\x5f\x63\x74\x78\0\x69\x6e\x64\x65\x78\0\x68\ +\x69\x64\0\x61\x6c\x6c\x6f\x63\x61\x74\x65\x64\x5f\x73\x69\x7a\x65\0\x72\x65\ +\x70\x6f\x72\x74\x5f\x74\x79\x70\x65\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\ +\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x68\x69\x64\x5f\x72\x65\x70\x6f\x72\x74\x5f\ +\x74\x79\x70\x65\0\x48\x49\x44\x5f\x49\x4e\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\ +\x54\0\x48\x49\x44\x5f\x4f\x55\x54\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\ +\x48\x49\x44\x5f\x46\x45\x41\x54\x55\x52\x45\x5f\x52\x45\x50\x4f\x52\x54\0\x48\ +\x49\x44\x5f\x52\x45\x50\x4f\x52\x54\x5f\x54\x59\x50\x45\x53\0\x72\x65\x74\x76\ +\x61\x6c\0\x73\x69\x7a\x65\0\x5f\x5f\x73\x33\x32\0\x73\x69\x7a\x65\x5f\x74\0\ +\x5f\x5f\x6b\x65\x72\x6e\x65\x6c\x5f\x73\x69\x7a\x65\x5f\x74\0\x5f\x5f\x6b\x65\ +\x72\x6e\x65\x6c\x5f\x75\x6c\x6f\x6e\x67\x5f\x74\0\x75\x6e\x73\x69\x67\x6e\x65\ +\x64\x20\x6c\x6f\x6e\x67\0\x68\x69\x64\x5f\x62\x70\x66\x5f\x67\x65\x74\x5f\x64\ +\x61\x74\x61\0\x68\x69\x64\x5f\x62\x70\x66\x5f\x70\x72\x6f\x62\x65\x5f\x61\x72\ +\x67\x73\0\x72\x64\x65\x73\x63\x5f\x73\x69\x7a\x65\0\x72\x64\x65\x73\x63\0\x5f\ +\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x70\ +\x72\x6f\x62\x65\0\x73\x79\x73\x63\x61\x6c\x6c\0\x30\x3a\x31\0\x09\x63\x74\x78\ +\x2d\x3e\x72\x65\x74\x76\x61\x6c\x20\x3d\x20\x63\x74\x78\x2d\x3e\x72\x64\x65\ +\x73\x63\x5f\x73\x69\x7a\x65\x20\x21\x3d\x20\x33\x33\x3b\0\x30\x3a\x33\0\x09\ +\x69\x66\x20\x28\x63\x74\x78\x2d\x3e\x72\x65\x74\x76\x61\x6c\x29\0\x09\x09\x63\ +\x74\x78\x2d\x3e\x72\x65\x74\x76\x61\x6c\x20\x3d\x20\x2d\x32\x32\x3b\0\x09\x72\ +\x65\x74\x75\x72\x6e\x20\x30\x3b\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\ +\x73\x65\0\x66\x69\x78\x65\x64\x5f\x72\x64\x65\x73\x63\0\x2e\x6b\x73\x79\x6d\ +\x73\0\x2e\x72\x6f\x64\x61\x74\x61\0\x6c\x69\x63\x65\x6e\x73\x65\0\x68\x69\x64\ +\x5f\x64\x65\x76\x69\x63\x65\0\x64\x75\x6d\x6d\x79\x5f\x6b\x73\x79\x6d\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x8c\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\0\0\ +\0\x04\0\0\0\x6c\0\0\0\x01\0\0\0\x80\x04\0\0\0\0\0\0\0\0\0\0\x62\x30\x30\x30\ +\x33\x67\x30\x30\x2e\x72\x6f\x64\x61\x74\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\x26\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\x05\x0c\x09\x01\xa1\x01\xa1\x02\x05\x08\x09\x4b\x75\ +\x08\x95\x23\x91\x02\xc0\xa1\x02\x09\0\x75\x08\x95\x01\x81\x03\x05\x09\x09\xff\ +\x75\x01\x95\x01\x81\x02\x95\x07\x81\x03\x05\x0c\x09\x03\xa1\x04\x05\x09\x19\ +\x01\x29\x06\x95\x06\x81\x02\x95\x02\x81\x03\x19\x07\x29\x0c\x95\x06\x81\x02\ +\x95\x02\x81\x03\x19\x0d\x29\x12\x95\x06\x81\x02\x95\x02\x81\x03\x19\x13\x29\ +\x19\x95\x06\x81\x02\x95\x02\x81\x03\xc0\x75\x08\x95\x1a\x81\x03\xc0\xc0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\x47\x50\x4c\0\0\0\0\0\x79\x11\0\0\0\0\0\0\xb7\x06\0\0\0\0\ +\0\0\xb7\x02\0\0\0\0\0\0\xb7\x03\0\0\0\x10\0\0\x85\x20\0\0\0\0\0\0\x15\0\x87\0\ +\0\0\0\0\xb7\x01\0\0\x1a\0\0\0\x73\x10\x67\0\0\0\0\0\xb7\x01\0\0\x13\0\0\0\x73\ +\x10\x58\0\0\0\0\0\xb7\x01\0\0\x12\0\0\0\x73\x10\x4e\0\0\0\0\0\xb7\x01\0\0\x0d\ +\0\0\0\x73\x10\x4c\0\0\0\0\0\xb7\x01\0\0\x06\0\0\0\x73\x10\x5c\0\0\0\0\0\x73\ +\x10\x50\0\0\0\0\0\x73\x10\x44\0\0\0\0\0\x73\x10\x38\0\0\0\0\0\x73\x10\x36\0\0\ +\0\0\0\xb7\x01\0\0\x29\0\0\0\x73\x10\x59\0\0\0\0\0\x73\x10\x4d\0\0\0\0\0\x73\ +\x10\x41\0\0\0\0\0\x73\x10\x35\0\0\0\0\0\xb7\x01\0\0\x19\0\0\0\x73\x10\x5a\0\0\ +\0\0\0\x73\x10\x57\0\0\0\0\0\x73\x10\x4b\0\0\0\0\0\x73\x10\x3f\0\0\0\0\0\x73\ +\x10\x33\0\0\0\0\0\xb7\x01\0\0\x04\0\0\0\x73\x10\x30\0\0\0\0\0\xb7\x01\0\0\x07\ +\0\0\0\x73\x10\x40\0\0\0\0\0\x73\x10\x28\0\0\0\0\0\xb7\x01\0\0\xff\0\0\0\x73\ +\x10\x20\0\0\0\0\0\xb7\x01\0\0\x03\0\0\0\x73\x10\x69\0\0\0\0\0\x73\x10\x62\0\0\ +\0\0\0\x73\x10\x56\0\0\0\0\0\x73\x10\x4a\0\0\0\0\0\x73\x10\x3e\0\0\0\0\0\x73\ +\x10\x2e\0\0\0\0\0\x73\x10\x2a\0\0\0\0\0\x73\x10\x1c\0\0\0\0\0\xb7\x01\0\0\x81\ +\0\0\0\x73\x10\x68\0\0\0\0\0\x73\x10\x61\0\0\0\0\0\x73\x10\x5d\0\0\0\0\0\x73\ +\x10\x55\0\0\0\0\0\x73\x10\x51\0\0\0\0\0\x73\x10\x49\0\0\0\0\0\x73\x10\x45\0\0\ +\0\0\0\x73\x10\x3d\0\0\0\0\0\x73\x10\x39\0\0\0\0\0\x73\x10\x29\0\0\0\0\0\x73\ +\x10\x25\0\0\0\0\0\x73\x10\x1b\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x73\x10\x16\0\0\0\ +\0\0\xb7\x01\0\0\xc0\0\0\0\x73\x10\x6b\0\0\0\0\0\x73\x10\x6a\0\0\0\0\0\x73\x10\ +\x63\0\0\0\0\0\x73\x10\x12\0\0\0\0\0\xb7\x01\0\0\x91\0\0\0\x73\x10\x10\0\0\0\0\ +\0\xb7\x01\0\0\x23\0\0\0\x73\x10\x0f\0\0\0\0\0\xb7\x01\0\0\x95\0\0\0\x73\x10\ +\x66\0\0\0\0\0\x73\x10\x5f\0\0\0\0\0\x73\x10\x5b\0\0\0\0\0\x73\x10\x53\0\0\0\0\ +\0\x73\x10\x4f\0\0\0\0\0\x73\x10\x47\0\0\0\0\0\x73\x10\x43\0\0\0\0\0\x73\x10\ +\x3b\0\0\0\0\0\x73\x10\x37\0\0\0\0\0\x73\x10\x27\0\0\0\0\0\x73\x10\x23\0\0\0\0\ +\0\x73\x10\x19\0\0\0\0\0\x73\x10\x0e\0\0\0\0\0\xb7\x01\0\0\x75\0\0\0\x73\x10\ +\x64\0\0\0\0\0\x73\x10\x21\0\0\0\0\0\x73\x10\x17\0\0\0\0\0\x73\x10\x0c\0\0\0\0\ +\0\xb7\x01\0\0\x4b\0\0\0\x73\x10\x0b\0\0\0\0\0\xb7\x01\0\0\x08\0\0\0\x73\x10\ +\x65\0\0\0\0\0\x73\x10\x18\0\0\0\0\0\x73\x10\x0d\0\0\0\0\0\x73\x10\x09\0\0\0\0\ +\0\xb7\x01\0\0\x02\0\0\0\x73\x10\x60\0\0\0\0\0\x73\x10\x5e\0\0\0\0\0\x73\x10\ +\x54\0\0\0\0\0\x73\x10\x52\0\0\0\0\0\x73\x10\x48\0\0\0\0\0\x73\x10\x46\0\0\0\0\ +\0\x73\x10\x3c\0\0\0\0\0\x73\x10\x3a\0\0\0\0\0\x73\x10\x26\0\0\0\0\0\x73\x10\ +\x14\0\0\0\0\0\x73\x10\x11\0\0\0\0\0\x73\x10\x07\0\0\0\0\0\xb7\x01\0\0\xa1\0\0\ +\0\x73\x10\x2f\0\0\0\0\0\x73\x10\x13\0\0\0\0\0\x73\x10\x06\0\0\0\0\0\x73\x10\ +\x04\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x73\x10\x34\0\0\0\0\0\x73\x10\x24\0\0\0\0\ +\0\x73\x10\x22\0\0\0\0\0\x73\x10\x1a\0\0\0\0\0\x73\x10\x05\0\0\0\0\0\x73\x10\ +\x03\0\0\0\0\0\xb7\x01\0\0\x09\0\0\0\x73\x10\x32\0\0\0\0\0\x73\x10\x2d\0\0\0\0\ +\0\x73\x10\x1f\0\0\0\0\0\x73\x10\x1e\0\0\0\0\0\x73\x10\x15\0\0\0\0\0\x73\x10\ +\x0a\0\0\0\0\0\x73\x10\x02\0\0\0\0\0\xb7\x01\0\0\x0c\0\0\0\x73\x10\x42\0\0\0\0\ +\0\x73\x10\x2c\0\0\0\0\0\x73\x10\x01\0\0\0\0\0\xb7\x01\0\0\x05\0\0\0\x73\x10\ +\x31\0\0\0\0\0\x73\x10\x2b\0\0\0\0\0\x73\x10\x1d\0\0\0\0\0\x73\x10\x08\0\0\0\0\ +\0\x73\x10\0\0\0\0\0\0\xb7\x06\0\0\x6c\0\0\0\xbf\x60\0\0\0\0\0\0\x95\0\0\0\0\0\ +\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\x47\0\0\0\x94\0\0\0\x05\x38\x01\0\x02\0\0\0\x47\ +\0\0\0\xca\0\0\0\x0f\x44\x01\0\x05\0\0\0\x47\0\0\0\x11\x01\0\0\x06\x4c\x01\0\ +\x07\0\0\0\x47\0\0\0\x1d\x01\0\0\x02\x58\x01\0\x8d\0\0\0\x47\0\0\0\x94\0\0\0\ +\x05\x38\x01\0\x1a\0\0\0\x8f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x69\x64\x5f\x66\x69\x78\x5f\x72\x64\ +\x65\x73\x63\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\ +\0\x10\0\0\0\0\0\0\0\0\0\0\0\x05\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x68\x69\x64\x5f\x62\x70\x66\x5f\x72\x64\ +\x65\x73\x63\x5f\x66\x69\x78\x75\x70\0\0\0\0\0\x68\x69\x64\x5f\x62\x70\x66\x5f\ +\x67\x65\x74\x5f\x64\x61\x74\x61\0\0\0\0\0\0\0\0\x47\x50\x4c\0\0\0\0\0\x61\x13\ +\x04\0\0\0\0\0\xb7\x02\0\0\x01\0\0\0\x55\x03\x01\0\x21\0\0\0\xb7\x02\0\0\0\0\0\ +\0\x63\x21\x08\x10\0\0\0\0\x61\x12\x08\x10\0\0\0\0\x15\x02\x03\0\0\0\0\0\x18\ +\x02\0\0\xea\xff\xff\xff\0\0\0\0\0\0\0\0\x63\x21\x08\x10\0\0\0\0\xb7\0\0\0\0\0\ +\0\0\x95\0\0\0\0\0\0\0\0\0\0\0\x1e\0\0\0\0\0\0\0\x47\0\0\0\xa9\x02\0\0\x15\x8c\ +\x01\0\x02\0\0\0\x47\0\0\0\xa9\x02\0\0\x20\x8c\x01\0\x04\0\0\0\x47\0\0\0\xa9\ +\x02\0\0\x0e\x8c\x01\0\x05\0\0\0\x47\0\0\0\xd3\x02\0\0\x0b\x90\x01\0\x06\0\0\0\ +\x47\0\0\0\xd3\x02\0\0\x06\x90\x01\0\x09\0\0\0\x47\0\0\0\xe5\x02\0\0\x0f\x94\ +\x01\0\x0a\0\0\0\x47\0\0\0\xfa\x02\0\0\x02\x9c\x01\0\0\0\0\0\x1a\0\0\0\xa5\x02\ +\0\0\0\0\0\0\x20\0\0\0\x1a\0\0\0\xcf\x02\0\0\0\0\0\0\x28\0\0\0\x1a\0\0\0\xcf\ +\x02\0\0\0\0\0\0\x48\0\0\0\x1a\0\0\0\xcf\x02\0\0\0\0\0\0\x1f\0\0\0\x0c\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\ +\0\x70\x72\x6f\x62\x65\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\ +\0\0\0\0\0\0\0\0\x01\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\x07\0\0\0\0\0\0\0\0\0\0\0\ +\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0", + .insns_sz = 2304, + .insns = "\ +\xbf\x16\0\0\0\0\0\0\xbf\xa1\0\0\0\0\0\0\x07\x01\0\0\x78\xff\xff\xff\xb7\x02\0\ +\0\x88\0\0\0\xb7\x03\0\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x05\0\x14\0\0\0\0\0\x61\ +\xa1\x78\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x7c\xff\ +\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x80\xff\0\0\0\0\xd5\ +\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x84\xff\0\0\0\0\xd5\x01\x01\0\0\ +\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x01\0\0\0\0\ +\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\xbf\x70\0\0\ +\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\ +\xa8\x0b\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\ +\0\0\xa4\x0b\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\ +\0\0\0\0\x98\x0b\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x05\0\0\ +\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x0b\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x12\0\ +\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x90\x0b\0\0\xb7\x03\0\0\x1c\0\0\0\x85\0\0\0\ +\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xd4\xff\0\0\0\0\x63\x7a\x78\xff\0\0\0\0\ +\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xe0\x0b\0\0\x63\x01\0\0\0\ +\0\0\0\x61\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\ +\xbc\x0b\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\ +\0\xb0\x0b\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\ +\xc5\x07\xc3\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x71\0\0\0\0\0\ +\0\x79\x63\x20\0\0\0\0\0\x15\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf8\ +\x0b\0\0\xb7\x02\0\0\x6c\0\0\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\0\0\0\x85\ +\0\0\0\x94\0\0\0\x05\0\x01\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x70\x0c\0\0\x63\ +\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x68\x0c\0\0\x18\x61\0\0\0\0\0\0\0\ +\0\0\0\x78\x0c\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xf8\x0b\0\0\ +\x18\x61\0\0\0\0\0\0\0\0\0\0\x80\x0c\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x02\0\ +\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x70\x0c\0\0\xb7\x03\0\0\x20\0\0\0\x85\0\0\0\ +\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x9f\xff\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x0c\0\0\x63\ +\x01\0\0\0\0\0\0\xb7\x01\0\0\x16\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x90\x0c\0\0\ +\xb7\x03\0\0\x04\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x92\xff\ +\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x98\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\ +\x80\x11\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xa0\x0c\0\0\x18\ +\x61\0\0\0\0\0\0\0\0\0\0\x78\x11\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\ +\0\0\0\x18\x11\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xc0\x11\0\0\x7b\x01\0\0\0\0\0\0\ +\x18\x60\0\0\0\0\0\0\0\0\0\0\x20\x11\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd0\x11\0\ +\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x70\x11\0\0\x18\x61\0\0\0\0\ +\0\0\0\0\0\0\xf0\x11\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xe8\x11\0\0\x7b\x01\0\0\0\0\0\0\x61\x60\x08\0\0\ +\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x88\x11\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\ +\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x8c\x11\0\0\x63\x01\0\0\0\0\0\0\x79\x60\ +\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x11\0\0\x7b\x01\0\0\0\0\0\0\x61\ +\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xb8\x11\0\0\x63\x01\0\0\0\0\0\ +\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\x12\0\0\xb7\x02\0\0\x14\0\0\0\xb7\x03\0\0\x0c\ +\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x5c\ +\xff\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x70\x11\0\0\x63\x70\x6c\0\0\0\0\0\x77\ +\x07\0\0\x20\0\0\0\x63\x70\x70\0\0\0\0\0\x18\x68\0\0\0\0\0\0\0\0\0\0\xc0\x0c\0\ +\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x18\x12\0\0\xb7\x02\0\0\x11\0\0\0\xb7\x03\0\0\ +\x0c\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\ +\x4d\xff\0\0\0\0\x75\x07\x03\0\0\0\0\0\x62\x08\x04\0\0\0\0\0\x6a\x08\x02\0\0\0\ +\0\0\x05\0\x0a\0\0\0\0\0\x63\x78\x04\0\0\0\0\0\xbf\x79\0\0\0\0\0\0\x77\x09\0\0\ +\x20\0\0\0\x55\x09\x02\0\0\0\0\0\x6a\x08\x02\0\0\0\0\0\x05\0\x04\0\0\0\0\0\x18\ +\x60\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\x63\x90\0\0\0\0\0\0\x6a\x08\x02\0\x40\0\0\0\ +\xb7\x01\0\0\x05\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x70\x11\0\0\xb7\x03\0\0\x8c\ +\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\ +\x01\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\ +\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xe0\x11\0\0\x61\x01\0\0\0\0\0\0\xd5\ +\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\xc5\x07\x2c\xff\0\0\ +\0\0\x63\x7a\x80\xff\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x30\x12\0\0\x18\x61\0\ +\0\0\0\0\0\0\0\0\0\x60\x13\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\ +\x38\x12\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x58\x13\0\0\x7b\x01\0\0\0\0\0\0\x18\ +\x60\0\0\0\0\0\0\0\0\0\0\x98\x12\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xa0\x13\0\0\ +\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xa0\x12\0\0\x18\x61\0\0\0\0\0\ +\0\0\0\0\0\xb0\x13\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x10\x13\ +\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd0\x13\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xc8\x13\0\0\x7b\x01\0\0\0\0\ +\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x68\x13\0\0\x63\x01\0\0\ +\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x6c\x13\0\0\x63\x01\ +\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x70\x13\0\0\x7b\ +\x01\0\0\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x98\x13\0\ +\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\x05\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x50\ +\x13\0\0\xb7\x03\0\0\x8c\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\ +\xf6\xfe\0\0\0\0\x63\x7a\x84\xff\0\0\0\0\x61\xa1\x78\xff\0\0\0\0\xd5\x01\x02\0\ +\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa0\x80\xff\0\0\0\0\x63\ +\x06\x28\0\0\0\0\0\x61\xa0\x84\xff\0\0\0\0\x63\x06\x2c\0\0\0\0\0\x18\x61\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x18\0\0\0\0\0\xb7\0\0\0\0\0\ +\0\0\x95\0\0\0\0\0\0\0", +}, + +#endif /* __B0003G0001V05F3P0405_XK24_HIDBPF_H__ */ diff --git a/drivers/hid/bpf/progs/hid_bpf_progs.h b/drivers/hid/bpf/progs/hid_bpf_progs.h index 430e0fb47484..be911c3c725b 100644 --- a/drivers/hid/bpf/progs/hid_bpf_progs.h +++ b/drivers/hid/bpf/progs/hid_bpf_progs.h @@ -28,9 +28,9 @@ struct hid_bpf_prog { struct hid_bpf_object { struct hid_device_id id; unsigned int map_cnt; - struct hid_bpf_map maps[0]; + struct hid_bpf_map maps[1]; unsigned int prog_cnt; - struct hid_bpf_prog progs[0]; + struct hid_bpf_prog progs[2]; unsigned int probe; unsigned int rodata; unsigned int data_sz; @@ -41,6 +41,7 @@ struct hid_bpf_object { static struct hid_bpf_object hid_objects[] = { +#include "b0003g0001v05F3p0405-xk24.hidbpf.h" { }, }; From patchwork Thu Nov 24 15:15:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055091 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7C9BC352A1 for ; Thu, 24 Nov 2022 15:19:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230034AbiKXPTM (ORCPT ); Thu, 24 Nov 2022 10:19:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230024AbiKXPTD (ORCPT ); Thu, 24 Nov 2022 10:19:03 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5290516903F for ; Thu, 24 Nov 2022 07:16:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302987; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nnQks2BxOzRnMOP9aelQae29VWIgWtLn+Wzeg2Waiik=; b=Ny9X8hiue12weqebCo23/JefHEReeXXsVgTGrwiL6hCLMDbwC2s1yjxm+LO2xolKLtqF6W /5C1WHw5FblvVHqcoc0FI4FXLBTzpapkyxSzafcA4v0vTnZ0/gZeJeuzO9UqrptJW2J61l A4xlpUQupgNOFWyajhJB1qE2yzWHVqs= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-541-Oec3o72EPpGcjuQUJS90Cg-1; Thu, 24 Nov 2022 10:16:22 -0500 X-MC-Unique: Oec3o72EPpGcjuQUJS90Cg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 9EE8E185A79C; Thu, 24 Nov 2022 15:16:21 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id E0CB140C2064; Thu, 24 Nov 2022 15:16:19 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 06/10] selftests: hid: add vmtest.sh Date: Thu, 24 Nov 2022 16:15:59 +0100 Message-Id: <20221124151603.807536-7-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC Similar-ish in many points from the script in selftests/bpf, with a few differences: - relies on boot2container instead of a plain qemu image (meaning that we can take any container in a registry as a base) - runs in the hid selftest dir, and such uses the test program from there Signed-off-by: Benjamin Tissoires --- tools/testing/selftests/hid/.gitignore | 1 + tools/testing/selftests/hid/config.common | 241 +++++++++++++++++++ tools/testing/selftests/hid/config.x86_64 | 4 + tools/testing/selftests/hid/vmtest.sh | 280 ++++++++++++++++++++++ 4 files changed, 526 insertions(+) create mode 100644 tools/testing/selftests/hid/config.common create mode 100644 tools/testing/selftests/hid/config.x86_64 create mode 100755 tools/testing/selftests/hid/vmtest.sh diff --git a/tools/testing/selftests/hid/.gitignore b/tools/testing/selftests/hid/.gitignore index a462ca6ab2c0..995af0670f69 100644 --- a/tools/testing/selftests/hid/.gitignore +++ b/tools/testing/selftests/hid/.gitignore @@ -2,3 +2,4 @@ bpftool *.skel.h /tools hid_bpf +results diff --git a/tools/testing/selftests/hid/config.common b/tools/testing/selftests/hid/config.common new file mode 100644 index 000000000000..0617275d93cc --- /dev/null +++ b/tools/testing/selftests/hid/config.common @@ -0,0 +1,241 @@ +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_9P_FS_SECURITY=y +CONFIG_9P_FS=y +CONFIG_AUDIT=y +CONFIG_BINFMT_MISC=y +CONFIG_BLK_CGROUP_IOLATENCY=y +CONFIG_BLK_CGROUP=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_BONDING=y +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y +CONFIG_BOOTTIME_TRACING=y +CONFIG_BSD_DISKLABEL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_RDMA=y +CONFIG_CGROUP_SCHED=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_WRITEBACK=y +CONFIG_CMA_AREAS=7 +CONFIG_CMA=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPUSETS=y +CONFIG_CRC_T10DIF=y +CONFIG_CRYPTO_BLAKE2B=y +CONFIG_CRYPTO_DEV_VIRTIO=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_XXHASH=y +CONFIG_DCB=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_CREDENTIALS=y +CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEFAULT_FQ_CODEL=y +CONFIG_DEFAULT_RENO=y +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DEVTMPFS=y +CONFIG_DMA_CMA=y +CONFIG_DNS_RESOLVER=y +CONFIG_EFI_STUB=y +CONFIG_EFI=y +CONFIG_EXPERT=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_FAIL_FUNCTION=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_VESA=y +CONFIG_FB=y +CONFIG_FONT_8x16=y +CONFIG_FONT_MINI_4x6=y +CONFIG_FONTS=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FUSE_FS=y +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_GART_IOMMU=y +CONFIG_GENERIC_PHY=y +CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_HPET=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HWPOISON_INJECT=y +CONFIG_HZ_1000=y +CONFIG_INET=y +CONFIG_INTEL_POWERCLAMP=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_NAT=y +CONFIG_IP6_NF_TARGET_MASQUERADE=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IRQ_POLL=y +CONFIG_JUMP_LABEL=y +CONFIG_KARMA_PARTITION=y +CONFIG_KEXEC=y +CONFIG_KPROBES=y +CONFIG_KSM=y +CONFIG_LEGACY_VSYSCALL_NONE=y +CONFIG_LOG_BUF_SHIFT=21 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=0 +CONFIG_LOGO=y +CONFIG_LSM="selinux,bpf,integrity" +CONFIG_MAC_PARTITION=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MCORE2=y +CONFIG_MEMCG=y +CONFIG_MEMORY_FAILURE=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_MODULES=y +CONFIG_NAMESPACES=y +CONFIG_NET_9P_VIRTIO=y +CONFIG_NET_9P=y +CONFIG_NET_ACT_BPF=y +CONFIG_NET_CLS_CGROUP=y +CONFIG_NETDEVICES=y +CONFIG_NET_EMATCH=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y +CONFIG_NETFILTER_XT_MATCH_BPF=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_NAT=y +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=y +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_NET_L3_MASTER_DEV=y +CONFIG_NETLABEL=y +CONFIG_NET_SCH_DEFAULT=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_FQ_CODEL=y +CONFIG_NET_TC_SKB_EXT=y +CONFIG_NET_VRF=y +CONFIG_NET=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_NAT_MASQUERADE=y +CONFIG_NF_NAT=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NO_HZ=y +CONFIG_NR_CPUS=128 +CONFIG_NUMA_BALANCING=y +CONFIG_NUMA=y +CONFIG_NVMEM=y +CONFIG_OSF_PARTITION=y +CONFIG_OVERLAY_FS_INDEX=y +CONFIG_OVERLAY_FS_METACOPY=y +CONFIG_OVERLAY_FS_XINO_AUTO=y +CONFIG_OVERLAY_FS=y +CONFIG_PACKET=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCI_IOV=y +CONFIG_PCI_MSI=y +CONFIG_PCI=y +CONFIG_PHYSICAL_ALIGN=0x1000000 +CONFIG_POSIX_MQUEUE=y +CONFIG_POWER_SUPPLY=y +CONFIG_PREEMPT=y +CONFIG_PRINTK_TIME=y +CONFIG_PROC_KCORE=y +CONFIG_PROFILING=y +CONFIG_PROVE_LOCKING=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_RC_DEVICES=y +CONFIG_RC_LOOPBACK=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_SCHEDSTATS=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SGI_PARTITION=y +CONFIG_SMP=y +CONFIG_SOCK_CGROUP_DATA=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_SYNC_FILE=y +CONFIG_SYSVIPC=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_MD5SIG=y +CONFIG_TLS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS=y +CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TUN=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_UNIX=y +CONFIG_USER_NS=y +CONFIG_VALIDATE_FS_PARSER=y +CONFIG_VETH=y +CONFIG_VIRT_DRIVERS=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_VIRTIO_FS=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_PCI=y +CONFIG_VLAN_8021Q=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_USER=y +CONFIG_ZEROPLUS_FF=y diff --git a/tools/testing/selftests/hid/config.x86_64 b/tools/testing/selftests/hid/config.x86_64 new file mode 100644 index 000000000000..a8721f403c21 --- /dev/null +++ b/tools/testing/selftests/hid/config.x86_64 @@ -0,0 +1,4 @@ +CONFIG_X86_ACPI_CPUFREQ=y +CONFIG_X86_CPUID=y +CONFIG_X86_MSR=y +CONFIG_X86_POWERNOW_K8=y diff --git a/tools/testing/selftests/hid/vmtest.sh b/tools/testing/selftests/hid/vmtest.sh new file mode 100755 index 000000000000..f124cf6b0d0f --- /dev/null +++ b/tools/testing/selftests/hid/vmtest.sh @@ -0,0 +1,280 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +set -u +set -e + +# This script currently only works for x86_64 +ARCH="$(uname -m)" +case "${ARCH}" in +x86_64) + QEMU_BINARY=qemu-system-x86_64 + BZIMAGE="arch/x86/boot/bzImage" + ;; +*) + echo "Unsupported architecture" + exit 1 + ;; +esac +DEFAULT_COMMAND="./hid_bpf" +OUTPUT_DIR="$PWD/results" +KCONFIG_REL_PATHS=("tools/testing/selftests/hid/config" "tools/testing/selftests/hid/config.common" "tools/testing/selftests/hid/config.${ARCH}") +B2C_URL="https://gitlab.freedesktop.org/mupuf/boot2container/-/raw/master/vm2c.py" +NUM_COMPILE_JOBS="$(nproc)" +LOG_FILE_BASE="$(date +"hid_selftests.%Y-%m-%d_%H-%M-%S")" +LOG_FILE="${LOG_FILE_BASE}.log" +EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status" + +usage() +{ + cat <] -- [] + + is the command you would normally run when you are in +tools/testing/selftests/bpf. e.g: + + $0 -- ./hid_bpf + +If no command is specified and a debug shell (-s) is not requested, +"${DEFAULT_COMMAND}" will be run by default. + +If you build your kernel using KBUILD_OUTPUT= or O= options, these +can be passed as environment variables to the script: + + O= $0 -- ./hid_bpf + +or + + KBUILD_OUTPUT= $0 -- ./hid_bpf + +Options: + + -u) Update the boot2container script to a newer version. + -d) Update the output directory (default: ${OUTPUT_DIR}) + -j) Number of jobs for compilation, similar to -j in make + (default: ${NUM_COMPILE_JOBS}) + -s) Instead of powering off the VM, start an interactive + shell. If is specified, the shell runs after + the command finishes executing +EOF +} + +download() +{ + local file="$1" + + echo "Downloading $file..." >&2 + curl -Lsf "$file" -o "${@:2}" +} + +recompile_kernel() +{ + local kernel_checkout="$1" + local make_command="$2" + + cd "${kernel_checkout}" + + ${make_command} olddefconfig + ${make_command} +} + +update_selftests() +{ + local kernel_checkout="$1" + local selftests_dir="${kernel_checkout}/tools/testing/selftests/hid" + + cd "${selftests_dir}" + ${make_command} +} + +run_vm() +{ + local b2c="$1" + local kernel_bzimage="$2" + local command="$3" + local post_command="" + + if ! which "${QEMU_BINARY}" &> /dev/null; then + cat < ${OUTPUT_DIR}/${EXIT_STATUS_FILE} + + set -e + + ${post_command} +} + +is_rel_path() +{ + local path="$1" + + [[ ${path:0:1} != "/" ]] +} + +do_update_kconfig() +{ + local kernel_checkout="$1" + local kconfig_file="$2" + + rm -f "$kconfig_file" 2> /dev/null + + for config in "${KCONFIG_REL_PATHS[@]}"; do + local kconfig_src="${kernel_checkout}/${config}" + cat "$kconfig_src" >> "$kconfig_file" + done +} + +update_kconfig() +{ + local kernel_checkout="$1" + local kconfig_file="$2" + + if [[ -f "${kconfig_file}" ]]; then + local local_modified="$(stat -c %Y "${kconfig_file}")" + + for config in "${KCONFIG_REL_PATHS[@]}"; do + local kconfig_src="${kernel_checkout}/${config}" + local src_modified="$(stat -c %Y "${kconfig_src}")" + # Only update the config if it has been updated after the + # previously cached config was created. This avoids + # unnecessarily compiling the kernel and selftests. + if [[ "${src_modified}" -gt "${local_modified}" ]]; then + do_update_kconfig "$kernel_checkout" "$kconfig_file" + # Once we have found one outdated configuration + # there is no need to check other ones. + break + fi + done + else + do_update_kconfig "$kernel_checkout" "$kconfig_file" + fi +} + +main() +{ + local script_dir="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" + local kernel_checkout=$(realpath "${script_dir}"/../../../../) + # By default the script searches for the kernel in the checkout directory but + # it also obeys environment variables O= and KBUILD_OUTPUT= + local kernel_bzimage="${kernel_checkout}/${BZIMAGE}" + local command="${DEFAULT_COMMAND}" + local update_b2c="no" + local debug_shell="no" + + while getopts ':hsud:j:' opt; do + case ${opt} in + u) + update_b2c="yes" + ;; + d) + OUTPUT_DIR="$OPTARG" + ;; + j) + NUM_COMPILE_JOBS="$OPTARG" + ;; + s) + command="/bin/sh" + debug_shell="yes" + ;; + h) + usage + exit 0 + ;; + \? ) + echo "Invalid Option: -$OPTARG" + usage + exit 1 + ;; + : ) + echo "Invalid Option: -$OPTARG requires an argument" + usage + exit 1 + ;; + esac + done + shift $((OPTIND -1)) + + # trap 'catch "$?"' EXIT + + if [[ "${debug_shell}" == "no" ]]; then + if [[ $# -eq 0 ]]; then + echo "No command specified, will run ${DEFAULT_COMMAND} in the vm" + else + command="$@" + + if [[ "${command}" == "/bin/bash" || "${command}" == "bash" ]] + then + debug_shell="yes" + fi + fi + fi + + local kconfig_file="${OUTPUT_DIR}/latest.config" + local make_command="make -j ${NUM_COMPILE_JOBS} KCONFIG_CONFIG=${kconfig_file}" + + # Figure out where the kernel is being built. + # O takes precedence over KBUILD_OUTPUT. + if [[ "${O:=""}" != "" ]]; then + if is_rel_path "${O}"; then + O="$(realpath "${PWD}/${O}")" + fi + kernel_bzimage="${O}/${BZIMAGE}" + make_command="${make_command} O=${O}" + elif [[ "${KBUILD_OUTPUT:=""}" != "" ]]; then + if is_rel_path "${KBUILD_OUTPUT}"; then + KBUILD_OUTPUT="$(realpath "${PWD}/${KBUILD_OUTPUT}")" + fi + kernel_bzimage="${KBUILD_OUTPUT}/${BZIMAGE}" + make_command="${make_command} KBUILD_OUTPUT=${KBUILD_OUTPUT}" + fi + + local b2c="${OUTPUT_DIR}/vm2c.py" + + echo "Output directory: ${OUTPUT_DIR}" + + mkdir -p "${OUTPUT_DIR}" + update_kconfig "${kernel_checkout}" "${kconfig_file}" + + recompile_kernel "${kernel_checkout}" "${make_command}" + + if [[ "${update_b2c}" == "no" && ! -f "${b2c}" ]]; then + echo "vm2c script not found in ${b2c}" + update_b2c="yes" + fi + + if [[ "${update_b2c}" == "yes" ]]; then + download $B2C_URL $b2c + chmod +x $b2c + fi + + update_selftests "${kernel_checkout}" "${make_command}" + run_vm $b2c "${kernel_bzimage}" "${command}" + if [[ "${debug_shell}" != "yes" ]]; then + echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}" + fi + + exit $(cat ${OUTPUT_DIR}/${EXIT_STATUS_FILE}) +} + +main "$@" From patchwork Thu Nov 24 15:16:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055092 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D50F3C4321E for ; Thu, 24 Nov 2022 15:19:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229622AbiKXPTN (ORCPT ); Thu, 24 Nov 2022 10:19:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59584 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230035AbiKXPTF (ORCPT ); Thu, 24 Nov 2022 10:19:05 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 80B9816F0DD for ; Thu, 24 Nov 2022 07:16:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302987; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ypQ0SpHVkNHir4A6yQp/geR9p4ucQgVAX8Ozo4Lqh9o=; b=VeF6BdDNnpGiJxF1hgW9XkenGgjrocLnYKdOQBCAXH4Swq7NKhb+VZfKNT17uNt+hR9Hio stSP8+5AXA02Sxz3WhYEXi62oufztoYGxoZD+5WWa3ZTr4HqPeSubbnMkeWbuR5x+XH5I1 LvG8picdAST0Akup+W8Qz6R4Y8dHgcA= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-312-k0Kc5RVSP-2hPsqur3AHug-1; Thu, 24 Nov 2022 10:16:24 -0500 X-MC-Unique: k0Kc5RVSP-2hPsqur3AHug-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C691E1C05B0C; Thu, 24 Nov 2022 15:16:23 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id D9C1840C2064; Thu, 24 Nov 2022 15:16:21 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 07/10] selftests: hid: Add a variant parameter so we can emulate specific devices Date: Thu, 24 Nov 2022 16:16:00 +0100 Message-Id: <20221124151603.807536-8-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC When testing with in-kernel bpf programs, we need to emulate a specific device, because otherwise we won't be loading the matching bpf program. Add a variant parameter to the fixture hid_bpf so that we can re-use it later with different devices. Signed-off-by: Benjamin Tissoires --- tools/testing/selftests/hid/hid_bpf.c | 75 +++++++++++++++++++-------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c index 6615c26fb5dd..738ddb2c6a62 100644 --- a/tools/testing/selftests/hid/hid_bpf.c +++ b/tools/testing/selftests/hid/hid_bpf.c @@ -114,6 +114,15 @@ static pthread_cond_t uhid_started = PTHREAD_COND_INITIALIZER; /* no need to protect uhid_stopped, only one thread accesses it */ static bool uhid_stopped; +struct hid_device_id { + int bus; + int vendor; + int product; + int version; + unsigned char *rdesc; + const size_t rdesc_sz; +}; + static int uhid_write(struct __test_metadata *_metadata, int fd, const struct uhid_event *ev) { ssize_t ret; @@ -131,7 +140,8 @@ static int uhid_write(struct __test_metadata *_metadata, int fd, const struct uh } } -static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb) +static int uhid_create(struct __test_metadata *_metadata, const struct hid_device_id *variant, + int fd, int rand_nb) { struct uhid_event ev; char buf[25]; @@ -141,12 +151,12 @@ static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb) memset(&ev, 0, sizeof(ev)); ev.type = UHID_CREATE; strcpy((char *)ev.u.create.name, buf); - ev.u.create.rd_data = rdesc; - ev.u.create.rd_size = sizeof(rdesc); - ev.u.create.bus = BUS_USB; - ev.u.create.vendor = 0x0001; - ev.u.create.product = 0x0a37; - ev.u.create.version = 0; + ev.u.create.rd_data = variant->rdesc; + ev.u.create.rd_size = variant->rdesc_sz; + ev.u.create.bus = variant->bus; + ev.u.create.vendor = variant->vendor; + ev.u.create.product = variant->product; + ev.u.create.version = variant->version; ev.u.create.country = 0; sprintf(buf, "%d", rand_nb); @@ -299,7 +309,8 @@ static int uhid_send_event(struct __test_metadata *_metadata, int fd, __u8 *buf, return uhid_write(_metadata, fd, &ev); } -static int setup_uhid(struct __test_metadata *_metadata, int rand_nb) +static int setup_uhid(struct __test_metadata *_metadata, const struct hid_device_id *variant, + int rand_nb) { int fd; const char *path = "/dev/uhid"; @@ -308,7 +319,7 @@ static int setup_uhid(struct __test_metadata *_metadata, int rand_nb) fd = open(path, O_RDWR | O_CLOEXEC); ASSERT_GE(fd, 0) TH_LOG("open uhid-cdev failed; %d", fd); - ret = uhid_create(_metadata, fd, rand_nb); + ret = uhid_create(_metadata, variant, fd, rand_nb); ASSERT_EQ(0, ret) { TH_LOG("create uhid device failed: %d", ret); close(fd); @@ -317,15 +328,19 @@ static int setup_uhid(struct __test_metadata *_metadata, int rand_nb) return fd; } -static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *dir) +static bool match_sysfs_device(int dev_id, const struct hid_device_id *variant, + const char *workdir, struct dirent *dir) { - const char *target = "0003:0001:0A37.*"; + char target[17] = "0003:0001:0A37.*"; char phys[512]; char uevent[1024]; char temp[512]; int fd, nread; bool found = false; + snprintf(target, sizeof(target), "0003:%04X:%04X.*", + variant->vendor, variant->product); + if (fnmatch(target, dir->d_name, 0)) return false; @@ -347,7 +362,7 @@ static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *d return found; } -static int get_hid_id(int dev_id) +static int get_hid_id(int dev_id, const struct hid_device_id *variant) { const char *workdir = "/sys/devices/virtual/misc/uhid"; const char *str_id; @@ -362,7 +377,7 @@ static int get_hid_id(int dev_id) d = opendir(workdir); if (d) { while ((dir = readdir(d)) != NULL) { - if (!match_sysfs_device(dev_id, workdir, dir)) + if (!match_sysfs_device(dev_id, variant, workdir, dir)) continue; str_id = dir->d_name + sizeof("0003:0001:0A37."); @@ -379,7 +394,7 @@ static int get_hid_id(int dev_id) return found; } -static int get_hidraw(int dev_id) +static int get_hidraw(int dev_id, const struct hid_device_id *variant) { const char *workdir = "/sys/devices/virtual/misc/uhid"; char sysfs[1024]; @@ -396,7 +411,7 @@ static int get_hidraw(int dev_id) continue; while ((dir = readdir(d)) != NULL) { - if (!match_sysfs_device(dev_id, workdir, dir)) + if (!match_sysfs_device(dev_id, variant, workdir, dir)) continue; sprintf(sysfs, "%s/%s/hidraw", workdir, dir->d_name); @@ -423,12 +438,12 @@ static int get_hidraw(int dev_id) return found; } -static int open_hidraw(int dev_id) +static int open_hidraw(int dev_id, const struct hid_device_id *variant) { int hidraw_number; char hidraw_path[64] = { 0 }; - hidraw_number = get_hidraw(dev_id); + hidraw_number = get_hidraw(dev_id, variant); if (hidraw_number < 0) return hidraw_number; @@ -445,6 +460,22 @@ FIXTURE(hid_bpf) { pthread_t tid; struct hid *skel; }; + +FIXTURE_VARIANT(hid_bpf) { + const struct hid_device_id id; +}; + +FIXTURE_VARIANT_ADD(hid_bpf, generic_device) { + .id = { + .bus = BUS_USB, + .vendor = 0x0001, + .product = 0x0a37, + .version = 0, + .rdesc = rdesc, + .rdesc_sz = sizeof(rdesc), + }, +}; + static void detach_bpf(FIXTURE_DATA(hid_bpf) * self) { if (self->hidraw_fd) @@ -478,10 +509,10 @@ FIXTURE_SETUP(hid_bpf) self->dev_id = rand() % 1024; - self->uhid_fd = setup_uhid(_metadata, self->dev_id); + self->uhid_fd = setup_uhid(_metadata, &variant->id, self->dev_id); - /* locate the uev, self, variant);ent file of the created device */ - self->hid_id = get_hid_id(self->dev_id); + /* locate the file of the created device */ + self->hid_id = get_hid_id(self->dev_id, &variant->id); ASSERT_GT(self->hid_id, 0) TEARDOWN_LOG("Could not locate uhid device id: %d", self->hid_id); @@ -546,7 +577,7 @@ static void load_programs(const struct test_program programs[], ASSERT_OK(args.retval) TH_LOG("attach_hid(%s): %d", programs[i].name, args.retval); } - self->hidraw_fd = open_hidraw(self->dev_id); + self->hidraw_fd = open_hidraw(self->dev_id, &variant->id); ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); } @@ -644,7 +675,7 @@ TEST_F(hid_bpf, test_attach_detach) /* detach the program */ detach_bpf(self); - self->hidraw_fd = open_hidraw(self->dev_id); + self->hidraw_fd = open_hidraw(self->dev_id, &variant->id); ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); /* inject another event */ From patchwork Thu Nov 24 15:16:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055094 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A83A0C43217 for ; Thu, 24 Nov 2022 15:19:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230109AbiKXPTy (ORCPT ); Thu, 24 Nov 2022 10:19:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230004AbiKXPTI (ORCPT ); Thu, 24 Nov 2022 10:19:08 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3B69016F0EC for ; Thu, 24 Nov 2022 07:16:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302989; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=boFPFiLPbdkddr+SwOKpAMOQtmzRdgMD7Ts21Pm6sEE=; b=bSi9Q46DlLrgVmZ5QjOGNyxNC7TlnLwAO6EXkndezCJbuFgSvwfuEv9V3k/MhCCdomWhU6 8BLixqI61ZUnyj6spNOD8kCgbHgeERs/FOVJ5QfX1PWYVMaU542iczuFJ/itU8yPOOmrMW q6hmDVbjFZZqN6HS5UXquBHB3z5zWLA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-67-MQYtX7HwMFyrXd4icQ2u4g-1; Thu, 24 Nov 2022 10:16:26 -0500 X-MC-Unique: MQYtX7HwMFyrXd4icQ2u4g-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BF918185A78B; Thu, 24 Nov 2022 15:16:25 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0BB6040C2064; Thu, 24 Nov 2022 15:16:23 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 08/10] selftests: hid: add XK-24 tests Date: Thu, 24 Nov 2022 16:16:01 +0100 Message-Id: <20221124151603.807536-9-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC this is the first device to be added in the kernel with a bpf program associated, so we better use it to ensure we get the things right. We define another fixture that will reuse everything from hid_bpf except for the variant parameters. And then we can use that easily in a new dedicated test. Signed-off-by: Benjamin Tissoires --- tools/testing/selftests/hid/hid_bpf.c | 72 +++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c index 738ddb2c6a62..4bdd1cfa7d13 100644 --- a/tools/testing/selftests/hid/hid_bpf.c +++ b/tools/testing/selftests/hid/hid_bpf.c @@ -520,6 +520,51 @@ FIXTURE_SETUP(hid_bpf) ASSERT_EQ(0, err) TEARDOWN_LOG("could not start udev listener: %d", err); } +static unsigned char xk24_rdesc[] = { + 0x05, 0x0c, // Usage Page (Consumer Devices) 0 + 0x09, 0x01, // Usage (Consumer Control) 2 + 0xa1, 0x01, // Collection (Application) 4 + 0xa1, 0x02, // Collection (Logical) 6 + 0x05, 0x08, // Usage Page (LEDs) 8 + 0x09, 0x4b, // Usage (Generic Indicator) 10 + 0x75, 0x08, // Report Size (8) 12 + 0x95, 0x23, // Report Count (35) 14 + 0x91, 0x02, // Output (Data,Var,Abs) 16 + 0xc0, // End Collection 18 + 0xa1, 0x02, // Collection (Logical) 19 + 0x05, 0x09, // Usage Page (Button) 21 + 0x09, 0x4b, // Usage (Vendor Usage 0x4b) 23 + 0x75, 0x08, // Report Size (8) 25 + 0x95, 0x20, // Report Count (32) 27 + 0x81, 0x02, // Input (Data,Var,Abs) 29 + 0xc0, // End Collection 31 + 0xc0, // End Collection 32 +}; + +#define _test_data_hid_bpf_xkeys _test_data_hid_bpf +#define _fixture_variant_hid_bpf_xkeys _fixture_variant_hid_bpf +FIXTURE(hid_bpf_xkeys); +FIXTURE_VARIANT(hid_bpf_xkeys); +FIXTURE_VARIANT_ADD(hid_bpf_xkeys, xk24) { + .id = { + .bus = BUS_USB, + .vendor = 0x05F3, + .product = 0x0405, + .version = 0, + .rdesc = xk24_rdesc, + .rdesc_sz = sizeof(xk24_rdesc), + }, +}; + +FIXTURE_SETUP(hid_bpf_xkeys) +{ + hid_bpf_setup(_metadata, self, variant); +} +FIXTURE_TEARDOWN(hid_bpf_xkeys) +{ + hid_bpf_teardown(_metadata, self, variant); +} + struct test_program { const char *name; int insert_head; @@ -846,6 +891,33 @@ TEST_F(hid_bpf, test_rdesc_fixup) ASSERT_EQ(rpt_desc.value[4], 0x42); } +/* + * Attach an emulated XK24, which has an in-tree eBPF program, and ensure + * we got it loaded. + */ +TEST_F(hid_bpf_xkeys, test_xk24) +{ + struct hidraw_report_descriptor rpt_desc = {0}; + int err, desc_size; + + /* open the kernel provided hidraw node */ + self->hidraw_fd = open_hidraw(self->dev_id, &variant->id); + ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); + + /* read the exposed report descriptor from hidraw */ + err = ioctl(self->hidraw_fd, HIDIOCGRDESCSIZE, &desc_size); + ASSERT_GE(err, 0) TH_LOG("error while reading HIDIOCGRDESCSIZE: %d", err); + + /* ensure the new size of the rdesc is bigger than the old one */ + ASSERT_GT(desc_size, sizeof(xk24_rdesc)); + + rpt_desc.size = desc_size; + err = ioctl(self->hidraw_fd, HIDIOCGRDESC, &rpt_desc); + ASSERT_GE(err, 0) TH_LOG("error while reading HIDIOCGRDESC: %d", err); + + ASSERT_EQ(rpt_desc.value[21], 0x09); +} + static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) { From patchwork Thu Nov 24 15:16:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055093 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34F57C433FE for ; Thu, 24 Nov 2022 15:19:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230117AbiKXPTw (ORCPT ); Thu, 24 Nov 2022 10:19:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230021AbiKXPTH (ORCPT ); Thu, 24 Nov 2022 10:19:07 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 66CCE16FB03 for ; Thu, 24 Nov 2022 07:16:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302993; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YVpzZ9PuKYYYwbqGuIV03fYvtpDzSokFyED3tXA9BEI=; b=B36Q3UMcI3tslgV4ugcVbiS3nMZJOWJby466rsrTGalxKcMkNFY18drczPk1itHTa7tywc 2EINR4TZAA+9aW2iY6daK/cKVetT9juW4wuD1Zx4C8QqLFHsf4/2uj1NEUzP34Pbl2Mk3P MHbcwkAnjKO97GQptIkA2DyvZ/kQ0nE= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-246-nlR9u26LOHi58kiUJjaWYA-1; Thu, 24 Nov 2022 10:16:28 -0500 X-MC-Unique: nlR9u26LOHi58kiUJjaWYA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B97293C01E0F; Thu, 24 Nov 2022 15:16:27 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id 06D4940C2064; Thu, 24 Nov 2022 15:16:25 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 09/10] selftests: hid: ensure the program is correctly pinned Date: Thu, 24 Nov 2022 16:16:02 +0100 Message-Id: <20221124151603.807536-10-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC Turns out that if bpffs was not mounted, the test was silently passing. So ensure it passes, but also force the mount of the bpffs in vmtest.sh so we get passing results. Signed-off-by: Benjamin Tissoires --- tools/testing/selftests/hid/hid_bpf.c | 3 ++- tools/testing/selftests/hid/vmtest.sh | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c index 4bdd1cfa7d13..3ae544bf24fe 100644 --- a/tools/testing/selftests/hid/hid_bpf.c +++ b/tools/testing/selftests/hid/hid_bpf.c @@ -712,7 +712,8 @@ TEST_F(hid_bpf, test_attach_detach) /* pin the program and immediately unpin it */ #define PIN_PATH "/sys/fs/bpf/hid_first_event" - bpf_program__pin(self->skel->progs.hid_first_event, PIN_PATH); + err = bpf_program__pin(self->skel->progs.hid_first_event, PIN_PATH); + ASSERT_OK(err) TH_LOG("error while calling bpf_program__pin"); remove(PIN_PATH); #undef PIN_PATH usleep(100000); diff --git a/tools/testing/selftests/hid/vmtest.sh b/tools/testing/selftests/hid/vmtest.sh index f124cf6b0d0f..bd60f65acb72 100755 --- a/tools/testing/selftests/hid/vmtest.sh +++ b/tools/testing/selftests/hid/vmtest.sh @@ -108,8 +108,10 @@ EOF if [[ "${debug_shell}" != "yes" ]] then touch ${OUTPUT_DIR}/${LOG_FILE} - command="set -o pipefail ; ${command} 2>&1 | tee ${OUTPUT_DIR}/${LOG_FILE}" + command="mount bpffs -t bpf /sys/fs/bpf/; set -o pipefail ; ${command} 2>&1 | tee ${OUTPUT_DIR}/${LOG_FILE}" post_command="cat ${OUTPUT_DIR}/${LOG_FILE}" + else + command="mount bpffs -t bpf /sys/fs/bpf/; ${command}" fi set +e From patchwork Thu Nov 24 15:16:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 13055095 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E89CC433FE for ; Thu, 24 Nov 2022 15:20:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230098AbiKXPUW (ORCPT ); Thu, 24 Nov 2022 10:20:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59552 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230105AbiKXPTx (ORCPT ); Thu, 24 Nov 2022 10:19:53 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4347116FB08 for ; Thu, 24 Nov 2022 07:16:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669302995; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EX0J0sgPn3/VZ/zS9HOQelAJB+dUZIbAy2+CqEVbXFE=; b=GzREFHSg4+JUYOVAqypnJ24KOCm44GSuva/NJ7uomTuWgtwGKR/N5u3RScAaMO7tEKOGaB uCvN412MK4jjZZoUaHph9G3LedPV+y+Rer+AlTGJRmSitPm6GHsiHCxzi3gU03y4wSIfkx DxmI8Pp7hX+H63klwXnn2Z1x07Dh6V0= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-518-6XjPAMALPxCvtgClpPRx1Q-1; Thu, 24 Nov 2022 10:16:30 -0500 X-MC-Unique: 6XjPAMALPxCvtgClpPRx1Q-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B6B801C05B0E; Thu, 24 Nov 2022 15:16:29 +0000 (UTC) Received: from plouf.redhat.com (unknown [10.39.193.200]) by smtp.corp.redhat.com (Postfix) with ESMTP id 01A3B40C2064; Thu, 24 Nov 2022 15:16:27 +0000 (UTC) From: Benjamin Tissoires To: Greg KH , Jiri Kosina , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Dmitry Torokhov Cc: Tero Kristo , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, Benjamin Tissoires Subject: [RFC hid v1 10/10] wip: vmtest aarch64 Date: Thu, 24 Nov 2022 16:16:03 +0100 Message-Id: <20221124151603.807536-11-benjamin.tissoires@redhat.com> In-Reply-To: <20221124151603.807536-1-benjamin.tissoires@redhat.com> References: <20221124151603.807536-1-benjamin.tissoires@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC untested Signed-off-by: Benjamin Tissoires --- tools/testing/selftests/hid/config.aarch64 | 39 ++++++++++++++++++++++ tools/testing/selftests/hid/vmtest.sh | 6 +++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/hid/config.aarch64 diff --git a/tools/testing/selftests/hid/config.aarch64 b/tools/testing/selftests/hid/config.aarch64 new file mode 100644 index 000000000000..76581bc6395b --- /dev/null +++ b/tools/testing/selftests/hid/config.aarch64 @@ -0,0 +1,39 @@ +# EFI +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_GENERIC_STUB=y +CONFIG_EFI_ARMSTUB_DTB_LOADER=y + +# Disable unsupported AARCH64 platforms +CONFIG_ARCH_ACTIONS=n +CONFIG_ARCH_SUNXI=n +CONFIG_ARCH_ALPINE=n +CONFIG_ARCH_APPLE=n +CONFIG_ARCH_BERLIN=n +CONFIG_ARCH_EXYNOS=n +CONFIG_ARCH_K3=n +CONFIG_ARCH_LAYERSCAPE=n +CONFIG_ARCH_LG1K=n +CONFIG_ARCH_HISI=n +CONFIG_ARCH_KEEMBAY=n +CONFIG_ARCH_MEDIATEK=n +CONFIG_ARCH_MESON=n +CONFIG_ARCH_MVEBU=n +CONFIG_ARCH_MXC=n +CONFIG_ARCH_QCOM=n +CONFIG_ARCH_RENESAS=n +CONFIG_ARCH_S32=n +CONFIG_ARCH_SEATTLE=n +CONFIG_ARCH_INTEL_SOCFPGA=n +CONFIG_ARCH_SYNQUACER=n +CONFIG_ARCH_TEGRA=n +CONFIG_ARCH_TESLA_FSD=n +CONFIG_ARCH_SPRD=n +CONFIG_ARCH_THUNDER=n +CONFIG_ARCH_THUNDER2=n +CONFIG_ARCH_UNIPHIER=n +CONFIG_ARCH_VEXPRESS=n +CONFIG_ARCH_VISCONTI=n +CONFIG_ARCH_XGENE=n +CONFIG_ARCH_ZYNQMP=n + +CONFIG_NET_VENDOR_MELLANOX=n diff --git a/tools/testing/selftests/hid/vmtest.sh b/tools/testing/selftests/hid/vmtest.sh index bd60f65acb72..d9e4a4c0557a 100755 --- a/tools/testing/selftests/hid/vmtest.sh +++ b/tools/testing/selftests/hid/vmtest.sh @@ -4,9 +4,13 @@ set -u set -e -# This script currently only works for x86_64 +# This script currently only works for x86_64 and aarch64. ARCH="$(uname -m)" case "${ARCH}" in +aarch64) + QEMU_BINARY=qemu-system-aarch64 + BZIMAGE="arch/aarch64/boot/bzImage" + ;; x86_64) QEMU_BINARY=qemu-system-x86_64 BZIMAGE="arch/x86/boot/bzImage"