From patchwork Mon Jul 11 21:48:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Delyan Kratunov X-Patchwork-Id: 12914309 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 8DDEACCA47F for ; Mon, 11 Jul 2022 21:48:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230105AbiGKVsU (ORCPT ); Mon, 11 Jul 2022 17:48:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231166AbiGKVsS (ORCPT ); Mon, 11 Jul 2022 17:48:18 -0400 Received: from mx0a-00082601.pphosted.com (mx0a-00082601.pphosted.com [67.231.145.42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7F2382443 for ; Mon, 11 Jul 2022 14:48:17 -0700 (PDT) Received: from pps.filterd (m0109334.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 26BLWf9r028436 for ; Mon, 11 Jul 2022 14:48:17 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=facebook; bh=PjhTR0NdHUghZjZ7cWUS4LAULJYW+PLGtuDjSa2NSOY=; b=d3rOvQgrLfCD9GogYzCJ+evoMOj9/MZ1ra5qo38oYvjDClpoRpfqfr2ceUH4o22XWhvN Lq0G2HvTi1D8OERA3aA61XoEV0hs9xD9DTswrDLb3Xb/vAftP5KAxbbkQKERgFdy3fJi C8AvmEWE97m7IhkN0rZeh4s7OjcM1tNdFQI= Received: from nam02-bn1-obe.outbound.protection.outlook.com (mail-bn1nam07lp2046.outbound.protection.outlook.com [104.47.51.46]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3h79043syk-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 11 Jul 2022 14:48:17 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=WISi7YAGgi3XsMczleb8FETNhg4Hl1CjappqHI8ESGODHHmINPizO9xoN4tzGF7moLNYmAWdgL4ljgUGWVhIgDSmi61i1h85j1xgrWpVurekO3xVYSHZ92XFbzeYZw7+65TYIDanyKCah5TAGUjTuTvIny65nKRSsfAmNRmK39DzZwIqCad7L6e/MheRsSJDhVUbQPWfqeTcPesk8/vPyjpP7bVYAsSbmcl+ZY5v7tEwV5JYyvIu5senEBOzgD0KYJZLf+NcJmvf3G6GCSX4lvOLJZVtKfW5yRTc/6rPieE+RE3QpHFhpOFbs0nRDmk36D5VBIghooSg6zpkWkyzDA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=PjhTR0NdHUghZjZ7cWUS4LAULJYW+PLGtuDjSa2NSOY=; b=P5esYG2x0Yxk9yv8bzQtE41NCq0shBRtoJj5DAyjyqPqWKrweaeqNjSd7zQVebCNA7Y0tc8zpnDWehk4mfbVpLOswkQP3BQqcom6vkiozH/4klUWU628xdN8jPtRd1x6JXEo3wWiFQSohiKQM/pXdIeYuED0bHlv200dkY1FhTtlr7/W0JISHL1Ue00AEi8aq9z0NYgiihyhU+BO14nJ/sO/rot6Q3KSViDd3RdU4VRnlqmTA0cZ+RBauWN/r0ansCf7G7o+j9P2mkw6hKWa1SgkB0G/1afkIkc7oW6cQZK9m+mVsMpJO9Xy3TWQxaMvr9ifjJMeThONudo6eeswOA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=fb.com; dmarc=pass action=none header.from=fb.com; dkim=pass header.d=fb.com; arc=none Received: from SJ0PR15MB5154.namprd15.prod.outlook.com (2603:10b6:a03:423::6) by DM6PR15MB2522.namprd15.prod.outlook.com (2603:10b6:5:1a9::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.26; Mon, 11 Jul 2022 21:48:13 +0000 Received: from SJ0PR15MB5154.namprd15.prod.outlook.com ([fe80::ac52:e8fa:831f:237e]) by SJ0PR15MB5154.namprd15.prod.outlook.com ([fe80::ac52:e8fa:831f:237e%9]) with mapi id 15.20.5395.020; Mon, 11 Jul 2022 21:48:13 +0000 From: Delyan Kratunov To: "daniel@iogearbox.net" , "ast@kernel.org" , "andrii@kernel.org" , "bpf@vger.kernel.org" Subject: [PATCH RFC bpf-next 1/3] bpf: allow maps to hold bpf_delayed_work fields Thread-Topic: [PATCH RFC bpf-next 1/3] bpf: allow maps to hold bpf_delayed_work fields Thread-Index: AQHYlW/rlnricuCpGUCEoXjJ7Q5oaA== Date: Mon, 11 Jul 2022 21:48:13 +0000 Message-ID: <37859ca03aaaba23f60288de044a3a10d52a79b4.1657576063.git.delyank@fb.com> References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 87be4845-ad38-4fda-2392-08da63870e29 x-ms-traffictypediagnostic: DM6PR15MB2522:EE_ x-fb-source: Internal x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 9tHNUfUad+11PBNWSpZQNzvt8lXJSgnn22mErionW3ig21aYQPGvNF/0f1mvaGLyWZC9lzwJru2P8jsQDMgZhPEasdCe4o0rEBqfAbOPz1wsCIF7ncR5ady39bHTg1UwCbeV2T99rTUcqEG38AzAhNa8LMJ2TqGG4pQeFw6OO9b5LYxE7YeN+17c3W0fMWNf9ccW3fUOMohOmxV9GHLoRx4bBqQAcJaTWfjsZ8uACDr7ofR5dIJM7QAMBWipeSjZBdykpgy4VR3q4TIxIhOJqmgngonLrjCN39xb1LblTsFImdOulIQHmLVNqMTCuUCwzPhqAWaGyy0GtpxOo5mitHfZLnJBKqHR+U7ta7p39ABnaXH0yKdbVcIan4E+JsEfaGXz3RCYGjyYhv1clY1U9MBut7o9+IGcfWrvti0uJ1gJKRyvN/L2bpXD+bKOLQycfDN+VtUZzk8wQ83EEyKugT2Ot+TQ3s/E2bysdkE5L74LcgFoLmPQlaMEkefjwiR3xvCPiEfe6YqKt0SjFw0Mau4rvm7b6MKJ5UhK1SMWAQ5CmDQLf2RWGGs+/8YwtpaPdymO71lq+kwoPE6uLzqRr2E8E2tFWsX/rhyFS5yltgq0OQQqUdHSjgCS9Fu6QAmDUhjM7uOuh2kzlJSjHr2Wr1SxzGzv9pNladMQRWow/zD0M2xwxuQ4a0FCf17FB6n0GWhpCv1cZJBpQqHTtw/GwJgtE/lFoYpuR9axOXPyOmpypeWqOT/U1tb6Twcr+aTaEVL+IC7J/93ZZW0R45ubsVRrYw4i+LindX/G9YUy/fgat3pBsVf7G0i6iD+bLivL x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SJ0PR15MB5154.namprd15.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230016)(4636009)(396003)(136003)(366004)(346002)(39860400002)(376002)(38100700002)(186003)(122000001)(83380400001)(71200400001)(2616005)(36756003)(64756008)(8676002)(66476007)(316002)(110136005)(76116006)(66946007)(66446008)(91956017)(2906002)(6506007)(478600001)(41300700001)(6512007)(6486002)(38070700005)(8936002)(5660300002)(66556008)(86362001);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?q?4RI+VQyfh0je5eoFiEEs9H/?= =?iso-8859-1?q?nxesXGU1HQHVnTK9saVuYO2NEN4SAW6OjLn+nYMEGXNPjn59iHjnCSS5OlK7?= =?iso-8859-1?q?FtBJ6PPRQ+9OFQ8FM1rRBQt64WCDKZGw7JdGyVYU3/vDG+JAXETtJlLFnJxr?= =?iso-8859-1?q?Ks9n88VfnsOO7PgIV6uYNBMezkvN8tyooVdnIT3LhWcjHhHlpy63WGhiXZSk?= =?iso-8859-1?q?/o1yN70oeaPC3T4V3zE6bzHhQQHuJx0yD3Jkm7zADjynJcBHPqMUDX7Nnbz8?= =?iso-8859-1?q?U+77ECv1XI9nAtkUmd/WhqrWetbNkQV1jK1JdSHhinyP7lcbuRbLAJ30l9Zo?= =?iso-8859-1?q?QZgD+iYosZrngDN++SvtoJ0PNSeEG5yLBxKwD7pJZBxKjXReMvwOFqvq22kH?= =?iso-8859-1?q?yN1sPmmd50i8Tx2ua/v49z5wFLIrZsZnTmBooFn18g24m6+j6WyazonEB7ti?= =?iso-8859-1?q?lzyGGmTSFFyLVAWAj6t38O1rTtuQ+QLz4RScFYWbMBPzUZzLnP6IMPk9QHia?= =?iso-8859-1?q?UeIfu+DcazMIz/8zxDaNl2iXnip+sY/YInu8Cu31WutXoiInPrZCOkH1R5P8?= =?iso-8859-1?q?3LsmEEIxA6aCew7XgybF9j+abwSL/vGqNRwDUOGyzuJ+zP+PGzUTaCAJqAgb?= =?iso-8859-1?q?sT+lvU6vfkhREyCZnTFYioS8o6nZ9Dnr4RZXLehmoVtAz9TD0woqSShssdvH?= =?iso-8859-1?q?xjdWtBKu+Ko+w20cWMFHQCzRTdQqbapAX4nbyEb2MWNSrhaJnx6q8SyHq8Xd?= =?iso-8859-1?q?9zFzxmUAbV10hnNlKn2ZA20/UHg+Id6ilXJpptN4Zh8o/QBwJwFNIOxUgmu/?= =?iso-8859-1?q?o4lcTP6smFWg2gzPuK2Hb5tL8YR9dQKVTM6Ib1gBFU4sYbE5IOFZ5BznBQHC?= =?iso-8859-1?q?/xncsCB29AmlxBF0x555R1WZ97/PAvpsMRRU99cRYOKmEVjxsl3E0IhHTtFf?= =?iso-8859-1?q?JnksTFCXc3HJCeS+lIaNsj9aBZ8jHaYD6T0D0LYYEgEbgj84DxCmyjc+VDvP?= =?iso-8859-1?q?fRXRsq3NNxw96yAkv4bJe/hHSK9h4R+QjDjiSzg3NW2yOOfI3J1BpkPMW2wc?= =?iso-8859-1?q?mfIoyOJBHwFNeKQCRiLAb2D5LvU1XNzM0XNYFpxcBm4swi7JWXfEwbgBpz7P?= =?iso-8859-1?q?tJPlWxdMYisoG6H1Mbfecr4CbhzfrDuCaR2bQAyWxBvIYdQ/kIpIcb8IQL15?= =?iso-8859-1?q?VyH831ORG+bxjbreMYTBuS7jpZ+E9cghEglgw+4rJxhPB76CoehZyiqYo3Vl?= =?iso-8859-1?q?blfv3rh/nQAw1VRYRk/nH2bEo6Mv2LG+f3Z/HpYx1oWFzBkbFiL/h7n8ZT69?= =?iso-8859-1?q?1ThdruAYpiLsgZcxhKaSqV974gB2P+xualOEdNdYyOEvr1PxdpgdqfS7CfZo?= =?iso-8859-1?q?oEDk1qByfctK99dMYnZy0NRnDXFkRMa1Rtvqehw9zFnWMgz4UmbXxUlbxJV2?= =?iso-8859-1?q?tnIhK+A9iJWwpGW1i07giI8h4mbmVUxOm4xYtfX6MEOYuhLR+K+fqfcG3pbL?= =?iso-8859-1?q?RWKUqBsyYEJ9YVjL5xa1hxv7h97yp7AyhZkhiykLOIMO241Xfrll1qkvuYZU?= =?iso-8859-1?q?u9gp+H+M4rS+STAte86fY816cEzh7GbE2kt/kF6wcV0zy9xRqCNLl8hC4EWG?= =?iso-8859-1?q?LR6XseHLcdbj2Y2bdz5npoAgCZEU+nT5ZkxIjiA=3D=3D?= MIME-Version: 1.0 X-OriginatorOrg: fb.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: SJ0PR15MB5154.namprd15.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 87be4845-ad38-4fda-2392-08da63870e29 X-MS-Exchange-CrossTenant-originalarrivaltime: 11 Jul 2022 21:48:13.5345 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 8ae927fe-1255-47a7-a2af-5f3a069daaa2 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: 6XjTa58iBFAB4u9QlB/aVTTIhOc9RIGwlHePUkuSuYgXp00XxSxohQYtf9nUMQtG X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR15MB2522 X-Proofpoint-ORIG-GUID: 8AX_I2ZistJpvsoIIGLjiEHt-fyyy_IU X-Proofpoint-GUID: 8AX_I2ZistJpvsoIIGLjiEHt-fyyy_IU X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-07-11_25,2022-07-08_01,2022-06-22_01 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net X-Patchwork-State: RFC Similarly to bpf_timer, bpf_delayed_work represents a callback that will be executed at a later time, in a different execution context. Its treatment in maps is practically the same as timers (to a degree that perhaps calls for refactoring), except releasing the work does not need to release any resources - we will wait for pending executions in the program destruction path. Signed-off-by: Delyan Kratunov --- include/linux/bpf.h | 9 ++++++++- include/linux/btf.h | 1 + include/uapi/linux/bpf.h | 8 ++++++++ kernel/bpf/btf.c | 21 +++++++++++++++++++++ kernel/bpf/syscall.c | 24 ++++++++++++++++++++++-- kernel/bpf/verifier.c | 9 +++++++++ tools/include/uapi/linux/bpf.h | 8 ++++++++ 7 files changed, 77 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 0edd7d2c0064..ad9d2cfb0411 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -164,7 +164,8 @@ enum { BPF_MAP_VALUE_OFF_MAX = 8, BPF_MAP_OFF_ARR_MAX = BPF_MAP_VALUE_OFF_MAX + 1 + /* for bpf_spin_lock */ - 1, /* for bpf_timer */ + 1 + /* for bpf_timer */ + 1, /* for bpf_delayed_work */ }; enum bpf_kptr_type { @@ -212,6 +213,7 @@ struct bpf_map { int spin_lock_off; /* >=0 valid offset, <0 error */ struct bpf_map_value_off *kptr_off_tab; int timer_off; /* >=0 valid offset, <0 error */ + int delayed_work_off; /* >=0 valid offset, <0 error */ u32 id; int numa_node; u32 btf_key_type_id; @@ -256,6 +258,11 @@ static inline bool map_value_has_timer(const struct bpf_map *map) return map->timer_off >= 0; } +static inline bool map_value_has_delayed_work(const struct bpf_map *map) +{ + return map->delayed_work_off >= 0; +} + static inline bool map_value_has_kptrs(const struct bpf_map *map) { return !IS_ERR_OR_NULL(map->kptr_off_tab); diff --git a/include/linux/btf.h b/include/linux/btf.h index 1bfed7fa0428..2b8f473a6aa0 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -132,6 +132,7 @@ bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s, u32 expected_offset, u32 expected_size); int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t); int btf_find_timer(const struct btf *btf, const struct btf_type *t); +int btf_find_delayed_work(const struct btf *btf, const struct btf_type *t); struct bpf_map_value_off *btf_parse_kptrs(const struct btf *btf, const struct btf_type *t); bool btf_type_is_void(const struct btf_type *t); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index e81362891596..d68fc4f472f1 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -6691,6 +6691,14 @@ struct bpf_dynptr { __u64 :64; } __attribute__((aligned(8))); +struct bpf_delayed_work { + __u64 :64; + __u64 :64; + __u64 :64; + __u64 :64; + __u64 :64; +} __attribute__((aligned(8))); + struct bpf_sysctl { __u32 write; /* Sysctl is being read (= 0) or written (= 1). * Allows 1,2,4-byte read, but no write. diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index f08037c31dd7..e4ab52cc25fe 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -3196,6 +3196,7 @@ enum btf_field_type { BTF_FIELD_SPIN_LOCK, BTF_FIELD_TIMER, BTF_FIELD_KPTR, + BTF_FIELD_DELAYED_WORK, }; enum { @@ -3283,6 +3284,7 @@ static int btf_find_struct_field(const struct btf *btf, const struct btf_type *t switch (field_type) { case BTF_FIELD_SPIN_LOCK: case BTF_FIELD_TIMER: + case BTF_FIELD_DELAYED_WORK: ret = btf_find_struct(btf, member_type, off, sz, idx < info_cnt ? &info[idx] : &tmp); if (ret < 0) @@ -3333,6 +3335,7 @@ static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t, switch (field_type) { case BTF_FIELD_SPIN_LOCK: case BTF_FIELD_TIMER: + case BTF_FIELD_DELAYED_WORK: ret = btf_find_struct(btf, var_type, off, sz, idx < info_cnt ? &info[idx] : &tmp); if (ret < 0) @@ -3375,6 +3378,11 @@ static int btf_find_field(const struct btf *btf, const struct btf_type *t, sz = sizeof(struct bpf_timer); align = __alignof__(struct bpf_timer); break; + case BTF_FIELD_DELAYED_WORK: + name = "bpf_delayed_work"; + sz = sizeof(struct bpf_delayed_work); + align = __alignof__(struct bpf_delayed_work); + break; case BTF_FIELD_KPTR: name = NULL; sz = sizeof(u64); @@ -3421,6 +3429,19 @@ int btf_find_timer(const struct btf *btf, const struct btf_type *t) return info.off; } +int btf_find_delayed_work(const struct btf *btf, const struct btf_type *t) +{ + struct btf_field_info info; + int ret; + + ret = btf_find_field(btf, t, BTF_FIELD_DELAYED_WORK, &info, 1); + if (ret < 0) + return ret; + if (!ret) + return -ENOENT; + return info.off; +} + struct bpf_map_value_off *btf_parse_kptrs(const struct btf *btf, const struct btf_type *t) { diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 7d5af5b99f0d..041972305344 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -914,10 +914,11 @@ static int bpf_map_alloc_off_arr(struct bpf_map *map) bool has_spin_lock = map_value_has_spin_lock(map); bool has_timer = map_value_has_timer(map); bool has_kptrs = map_value_has_kptrs(map); + bool has_delayed_work = map_value_has_delayed_work(map); struct bpf_map_off_arr *off_arr; u32 i; - if (!has_spin_lock && !has_timer && !has_kptrs) { + if (!has_spin_lock && !has_timer && !has_kptrs && !has_delayed_work) { map->off_arr = NULL; return 0; } @@ -953,6 +954,13 @@ static int bpf_map_alloc_off_arr(struct bpf_map *map) } off_arr->cnt += tab->nr_off; } + if (has_delayed_work) { + i = off_arr->cnt; + + off_arr->field_off[i] = map->delayed_work_off; + off_arr->field_sz[i] = sizeof(struct bpf_delayed_work); + off_arr->cnt++; + } if (off_arr->cnt == 1) return 0; @@ -1014,6 +1022,16 @@ static int map_check_btf(struct bpf_map *map, const struct btf *btf, return -EOPNOTSUPP; } + map->delayed_work_off = btf_find_delayed_work(btf, value_type); + if (map_value_has_delayed_work(map)) { + if (map->map_flags & BPF_F_RDONLY_PROG) + return -EACCES; + if (map->map_type != BPF_MAP_TYPE_HASH && + map->map_type != BPF_MAP_TYPE_LRU_HASH && + map->map_type != BPF_MAP_TYPE_ARRAY) + return -EOPNOTSUPP; + } + map->kptr_off_tab = btf_parse_kptrs(btf, value_type); if (map_value_has_kptrs(map)) { if (!bpf_capable()) { @@ -1095,6 +1113,7 @@ static int map_create(union bpf_attr *attr) map->spin_lock_off = -EINVAL; map->timer_off = -EINVAL; + map->delayed_work_off = -EINVAL; if (attr->btf_key_type_id || attr->btf_value_type_id || /* Even the map's value is a kernel's struct, * the bpf_prog.o must have BTF to begin with @@ -1863,7 +1882,8 @@ static int map_freeze(const union bpf_attr *attr) return PTR_ERR(map); if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS || - map_value_has_timer(map) || map_value_has_kptrs(map)) { + map_value_has_timer(map) || map_value_has_kptrs(map) || + map_value_has_delayed_work(map)) { fdput(f); return -ENOTSUPP; } diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 2859901ffbe3..9fd311b7a1ff 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3817,6 +3817,15 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno, return -EACCES; } } + if (map_value_has_delayed_work(map) && src == ACCESS_DIRECT) { + u32 t = map->delayed_work_off; + + if (reg->smin_value + off < t + sizeof(struct bpf_delayed_work) && + t < reg->umax_value + off + size) { + verbose(env, "bpf_delayed_work cannot be accessed directly by load/store regno=%d off=%d\n", regno, off); + return -EACCES; + } + } if (map_value_has_kptrs(map)) { struct bpf_map_value_off *tab = map->kptr_off_tab; int i; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index e81362891596..d68fc4f472f1 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -6691,6 +6691,14 @@ struct bpf_dynptr { __u64 :64; } __attribute__((aligned(8))); +struct bpf_delayed_work { + __u64 :64; + __u64 :64; + __u64 :64; + __u64 :64; + __u64 :64; +} __attribute__((aligned(8))); + struct bpf_sysctl { __u32 write; /* Sysctl is being read (= 0) or written (= 1). * Allows 1,2,4-byte read, but no write. From patchwork Mon Jul 11 21:48:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Delyan Kratunov X-Patchwork-Id: 12914307 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 72B0BC433EF for ; Mon, 11 Jul 2022 21:48:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231394AbiGKVsT (ORCPT ); Mon, 11 Jul 2022 17:48:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229633AbiGKVsS (ORCPT ); Mon, 11 Jul 2022 17:48:18 -0400 Received: from mx0a-00082601.pphosted.com (mx0a-00082601.pphosted.com [67.231.145.42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E3B7E65578 for ; Mon, 11 Jul 2022 14:48:16 -0700 (PDT) Received: from pps.filterd (m0109334.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 26BLWf9p028436 for ; Mon, 11 Jul 2022 14:48:16 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=facebook; bh=2sSI9PbTTGAMT8nuUBd2BMAx9yVlMUjfUy8sF4c9ZTc=; b=anUNZRoTn9HmV3T8HYHYq/NukFAX9qGh2a3E7Z6M3X4MT+lhgwxSHTH071asjXNFbgyD Vf+ghdnq94fWVx3pg1LMiWj1/MT86lOP5/U4Zaq8yc7Nzn1nvvUKzJP9o+swyWc62pjM i4/+qJeIfq+wmz1uTyKWnX9c6WcYuRFoZrE= Received: from nam02-bn1-obe.outbound.protection.outlook.com (mail-bn1nam07lp2046.outbound.protection.outlook.com [104.47.51.46]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3h79043syk-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 11 Jul 2022 14:48:16 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=XoU5jN0ZEUDO9lbF/0Fqd5gEM1pQ58AYyYd9yLzi9ptTOxofLi0daUeOSEq+IdJeCrh1bQGO0RvKaaB3y1dyhOjue3+I9HMC/N2gO2agfkouP//H3fTKAO0nbcGd3adrobHVGREsNDHcvxiO4oub40Yuj3NVmAUfrj2xcprYQ7Pw7+f9egJpf7SL8VFCIrhkZS42tl+odejk0lyK5Hy5QR+QOnEgS97+yL+AT6eAky4UsPiGD7n8VkgvgQJpuRqjIeSz5pL0fAScnKJY6GiUHnKfoamGnFo+6a4M46B5aNIi3m1MVNwWLCciyapw4A+ripiIrIU2yh9TnCMS+aafsg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=2sSI9PbTTGAMT8nuUBd2BMAx9yVlMUjfUy8sF4c9ZTc=; b=loUgvgvg6an03MmvjOoXWgE9ngv7PPzf5uJCRxbnf1KxlD906kPW+lOGJqSXdD3uAoNBuQWAJM/EqsbUQ+yYU7DLgw9d7m7PvvFgSS1kGNF8o60ZbAMqKO1guFVtE0CCE3VvCWMxINJRzk2u8FXerwQCIkyD/PHhzHO+TN6JUtLwzosBvclKleijNUYf3PVyWImoSNCzKCrVyZKP18PuMeX6Z2wUUT1CCVG/9RTaKSJ/0ONcXbe5cJvRAX2pX09mty5egry0t2rJN2Dq7LvNoBELIvQFFRE+ILfuNk8kXA4hjoASj+qheY79uWXSYNufMiclhQ85dkenelXgxR/4lg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=fb.com; dmarc=pass action=none header.from=fb.com; dkim=pass header.d=fb.com; arc=none Received: from SJ0PR15MB5154.namprd15.prod.outlook.com (2603:10b6:a03:423::6) by DM6PR15MB2522.namprd15.prod.outlook.com (2603:10b6:5:1a9::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.26; Mon, 11 Jul 2022 21:48:12 +0000 Received: from SJ0PR15MB5154.namprd15.prod.outlook.com ([fe80::ac52:e8fa:831f:237e]) by SJ0PR15MB5154.namprd15.prod.outlook.com ([fe80::ac52:e8fa:831f:237e%9]) with mapi id 15.20.5395.020; Mon, 11 Jul 2022 21:48:12 +0000 From: Delyan Kratunov To: "daniel@iogearbox.net" , "ast@kernel.org" , "andrii@kernel.org" , "bpf@vger.kernel.org" Subject: [PATCH RFC bpf-next 2/3] bpf: add delayed_work mechanism Thread-Topic: [PATCH RFC bpf-next 2/3] bpf: add delayed_work mechanism Thread-Index: AQHYlW/riXkQtYrFGUiv4fNWBMwwQg== Date: Mon, 11 Jul 2022 21:48:12 +0000 Message-ID: <3d3027f5e13a37874b39c6363789bd55b4110be4.1657576063.git.delyank@fb.com> References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: eef3d5f1-080c-4e68-9989-08da63870da3 x-ms-traffictypediagnostic: DM6PR15MB2522:EE_ x-fb-source: Internal x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: gc8O2D+6xoTP/FupCsivappFzxbijeIMYfQe1gPQ3kjxjLnWZL45A5QxpXg7QYWYmwNlKZyhw5zHgVtlE2RuNpfK+pBRFH+frmpJZExpNLkN/n0FbhQTaX12YvZ3OEs08elICAwwmMk1tRv+YQk2IaUnkdnpyTtWNMHog4CgLfdZXm0bGmLAKPuu4FPEEDg4ItktFCn7d4Bo+8DhEQdjcFrKIHj9S4wSWVzckR8La/gJbIeMW8qF3Jd4880NQsoYIK8RtAmnS2xGEpWfaKgo1HnNk6U6WVdPIXHjoHAadWFqkMX+4s9NuL0RkRhm5N/G7ppgXk1enkxuHwodZuxH5hKws9+RgfuCmKgS9bHs91K/oYn90UV5XZbDmGF87oiOBB+CWKotyLl+AoLMQmvX8Ilf458nAPcsVKxAHNjRsK/KCLFfPZ4nP+cLjIWSNvTPLLoWSOBz77gXvXi6Wp6JJHXQNKeLrV3YoHM6LWjS8A6b/yJ0KsaPaVP4iNZQFF5kDupgoNu6xmTuAiY4uSIO2egd1zs2XstjQlSS1BDcqDpdgvZ+5nxF85n3bVFPsTf4jsSD6rgdruUoOB+z5UJFXCq6HLrQaH551Ti8iTBFRDuKjEA+b8WC563rfdjA5FYomLyIJvY81ZN4GeHQkxZzfNjJUHm3hcREPtn3WKsapOMcjVl5aX9VjEHobuyNGtNYr6VVQOSRUxLBKHyt3ZBkcVYIdLClbg+hYtZU5VXNG4tb7HWA84GW/jANBaj+D3ybDPU9ctURKM5CdXEmbmnfrwfHJX5YkFOikIC+SQz+Vnbwq83nrT+MVSL5VWSmF15q x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SJ0PR15MB5154.namprd15.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230016)(4636009)(396003)(136003)(366004)(346002)(39860400002)(376002)(38100700002)(186003)(122000001)(83380400001)(71200400001)(2616005)(36756003)(64756008)(8676002)(66476007)(316002)(110136005)(76116006)(66946007)(66446008)(91956017)(2906002)(6506007)(478600001)(41300700001)(6512007)(6486002)(38070700005)(8936002)(5660300002)(30864003)(66556008)(86362001)(579004);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?q?LZMf+RtnD7TyPMOInE22yKe?= =?iso-8859-1?q?7djSgBXoA3zyR3o64rVS5c/8XXWUieELgT/qBAB6njDa75ctho+9X3hnpvvC?= =?iso-8859-1?q?CKYqEVDf4PaAjSNGo9fzR7y+WtxvqZOVZSrrjeEE6I6A35c68+s5+VpZT79V?= =?iso-8859-1?q?JFwLWX+X0aKKQppa41Q33iBgLk/ecOltwhutwms2R0xWYuAiFUHA/wS9b4Qp?= =?iso-8859-1?q?/81JBBC9XHwVpMPWSzNWNNQDo1ZzZqByqEhsObXdzTQ4chZbcRoOFIPURBZD?= =?iso-8859-1?q?hiVTNYFoBY95or2Xii5K5mP0uBkrNz/sCGnZ8osdC1FwKh24wcK4okqzjLWk?= =?iso-8859-1?q?rKorn7Azmmet0oOwnHEZcClZE0RVE8CMP0n1QvKotQHWMHKA8+impkgT2EFv?= =?iso-8859-1?q?rZFY6yJQlkAC1ihJ1JEERYjInvD2oCjJfZz3pmoJJrhZ6efLKyflmTP2fGIZ?= =?iso-8859-1?q?WKrRwdy+9yYROEBWLVg98Dg5806I7DpT/HLSV4Pzd78N02EKMt+/bKLuVzOm?= =?iso-8859-1?q?EKwMUeOyTsAJcd+6aO9AowWjSmmk3x1risr/TVbGBVqcIAf0VSte2sPGZUhr?= =?iso-8859-1?q?S8caRlA+vDVs9bBjSQhvqP1rp/mN9khn5dDJpGWKfWVS945zcsBSC2qm/Gkm?= =?iso-8859-1?q?Iarta9TDJFCvBweP1jXupUr7ZOtOLhtEGyRhQhP99ZcCT76gpZJBdRQ6PJcZ?= =?iso-8859-1?q?eb9UEbO6YxOel8HXg4GgNxvYdtVIyPX7zPCFw4uGazpQJCy+suOoPrgMMLaV?= =?iso-8859-1?q?J1xqqBiNjhYNumo7pmwMXiMmpurqNfSAuno1SxKPBO5GxEbR2RzErKjTtKTQ?= =?iso-8859-1?q?CAC7Lyyb9TEAJdOvMERSpWnwG69boqaKR+Q1f9MLhPx/daavksHlzOW/YJ0P?= =?iso-8859-1?q?f/Sph7e/0B42n8NMbl++YBobytvoz4L6TdWHrTB1H9HT243Daqps77ujbVq9?= =?iso-8859-1?q?xFCjTxWF/w5y4eBmFyetp5wGbtuGOHJVnJKm7JLHYobDgcMyRpdAoVG4mcme?= =?iso-8859-1?q?jas00Laboh2t7yuVwUjCdA0o8/AddFStDe6gtHnVVVcRG8dY3mbe7tvx2JFL?= =?iso-8859-1?q?fe8tNjClWEiZxl8ikw3uc4gJz04Yy46ylN6SF8K74MrpuGPhMWNE0q+iz6cf?= =?iso-8859-1?q?nuKGkMt0EqfghSJ3ep3zA1ti2cCa71gB3XITciCud68WZfEuppzi9YokZ6XC?= =?iso-8859-1?q?I1aStIXn9f/50Ei0wuNejQZeWC1ch8s84NIFWf3+8KT32SOGtD+kdxTfd51w?= =?iso-8859-1?q?ycuXDTmrJ5+dI2bYy2Uo1DUDLSEgzUiFQJ5bUzhGs8hRuGNw1JMQriRyGM42?= =?iso-8859-1?q?nx7Ehy+EfmDFFBtDpQPJ49Qgi6UWUK0R5v4ML+pY/1DczZyfCh1iqmjqNY5p?= =?iso-8859-1?q?ml/WEoLVsnQdo0TtnYtUhfCym7DpLlOgS5clQbMQtd0R0Wt657thXK5OopKj?= =?iso-8859-1?q?KV+4hVmzdQ0KDNDTsMeq3jH2gbRTjArFQB4qKy2ZuAXQ2hf7Vbqiz2LSSIhC?= =?iso-8859-1?q?u/e2lQ2Cl1DPemiJhDfFLxBpRLIjt30X3zeTc2Lhr4nCbPHT+og5ona21JGF?= =?iso-8859-1?q?02Qfbyq2FSPbQOla34tRxy1FNLQYXpNRlclbKIqkLtdUHOphqFl+v5DUeRme?= =?iso-8859-1?q?y4DNgLLUoMBEBTKMimV13aFrwpECzlM/stS0WpA=3D=3D?= MIME-Version: 1.0 X-OriginatorOrg: fb.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: SJ0PR15MB5154.namprd15.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: eef3d5f1-080c-4e68-9989-08da63870da3 X-MS-Exchange-CrossTenant-originalarrivaltime: 11 Jul 2022 21:48:12.6594 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 8ae927fe-1255-47a7-a2af-5f3a069daaa2 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: dHGcmWIplnw5VI15VdgtshNz9kYUtH7yPJPi7/9AX65dpoJpeGYOyuYfcTG3Xiby X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR15MB2522 X-Proofpoint-ORIG-GUID: s-N0AK46H1vL3xO8_i1cZHIreCjyDi6Q X-Proofpoint-GUID: s-N0AK46H1vL3xO8_i1cZHIreCjyDi6Q X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-07-11_25,2022-07-08_01,2022-06-22_01 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net X-Patchwork-State: RFC Add a new helper function that can schedule a callback to execute in a different context. Initially, only irq_work (i.e. hardirq) is supported. A key consideration is that we need this to work in an NMI context. Therefore, we use a queue of pre-allocated llist nodes inside bpf_delayed_work, which we drain on a per-program basis. To avoid races on the bpf_delayed_work items, we implement a simple lock scheme based on cmpxchg ordering. Signed-off-by: Delyan Kratunov --- include/linux/bpf.h | 13 ++++ include/uapi/linux/bpf.h | 28 ++++++++ kernel/bpf/core.c | 8 +++ kernel/bpf/helpers.c | 92 ++++++++++++++++++++++++ kernel/bpf/verifier.c | 123 ++++++++++++++++++++++++++++++++- scripts/bpf_doc.py | 2 + tools/include/uapi/linux/bpf.h | 27 ++++++++ 7 files changed, 292 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index ad9d2cfb0411..7325a9a2d10b 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include struct bpf_verifier_env; struct bpf_verifier_log; @@ -460,6 +462,7 @@ enum bpf_arg_type { ARG_PTR_TO_TIMER, /* pointer to bpf_timer */ ARG_PTR_TO_KPTR, /* pointer to referenced kptr */ ARG_PTR_TO_DYNPTR, /* pointer to bpf_dynptr. See bpf_type_flag for dynptr type */ + ARG_PTR_TO_DELAYED_WORK,/* pointer to bpf_delayed_work */ __BPF_ARG_TYPE_MAX, /* Extended arg_types. */ @@ -1101,6 +1104,9 @@ struct bpf_prog_aux { u32 linfo_idx; u32 num_exentries; struct exception_table_entry *extable; + + /* initialized at load time if program uses delayed work helpers */ + struct bpf_delayed_irq_work *irq_work; union { struct work_struct work; struct rcu_head rcu; @@ -2526,4 +2532,11 @@ void bpf_dynptr_init(struct bpf_dynptr_kern *ptr, void *data, void bpf_dynptr_set_null(struct bpf_dynptr_kern *ptr); int bpf_dynptr_check_size(u32 size); +struct bpf_delayed_irq_work { + struct llist_head items; + struct irq_work work; + struct bpf_prog *prog; +}; +void bpf_delayed_work_irq_work_cb(struct irq_work *work); + #endif /* _LINUX_BPF_H */ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index d68fc4f472f1..dc0587bbbe7c 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -5325,6 +5325,29 @@ union bpf_attr { * **-EACCES** if the SYN cookie is not valid. * * **-EPROTONOSUPPORT** if CONFIG_IPV6 is not builtin. + * + * + * long bpf_delayed_work_submit(struct bpf_delayed_work *work, void *cb, void *data, int flags) + * Description + * Submits a function to execute in a different context. + * + * *work* must be a member in a map value. + * + * *cb* function to call + * + * *data* context to pass as sole argument to *cb*. Must be part of + * a map value or NULL. + * + * *flags* must be BPF_DELAYED_WORK_IRQWORK + * Return + * 0 when work is successfully submitted. + * + * **-EINVAL** if *cb* is NULL + * + * **-EOPNOTSUP** if called from an NMI handler on an + * architecture without NMI-safe cmpxchg + * + * **-EINVAL** if *work* is already in use */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5535,6 +5558,7 @@ union bpf_attr { FN(tcp_raw_gen_syncookie_ipv6), \ FN(tcp_raw_check_syncookie_ipv4), \ FN(tcp_raw_check_syncookie_ipv6), \ + FN(delayed_work_submit), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper @@ -6699,6 +6723,10 @@ struct bpf_delayed_work { __u64 :64; } __attribute__((aligned(8))); +enum { + BPF_DELAYED_WORK_IRQWORK = (1UL << 0), +}; + struct bpf_sysctl { __u32 write; /* Sysctl is being read (= 0) or written (= 1). * Allows 1,2,4-byte read, but no write. diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index b5ffebcce6cc..1f5093f9442b 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -2567,6 +2567,14 @@ static void bpf_prog_free_deferred(struct work_struct *work) int i; aux = container_of(work, struct bpf_prog_aux, work); + + /* We have already waited for a qs of the appropriate RCU variety, + * so we can expect no further submissions of work. Just wait for + * the currently scheduled work to finish before releasing anything. + */ + if (aux->irq_work) + irq_work_sync(&aux->irq_work->work); + #ifdef CONFIG_BPF_SYSCALL bpf_free_kfunc_btf_tab(aux->kfunc_btf_tab); #endif diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index a1c84d256f83..731547d34c35 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "../../lib/kstrtox.h" @@ -1575,6 +1577,94 @@ static const struct bpf_func_proto bpf_dynptr_data_proto = { .arg3_type = ARG_CONST_ALLOC_SIZE_OR_ZERO, }; +struct bpf_delayed_work_kern { + struct llist_node item; + u64 flags; /* used as a lock field */ + void (*cb)(void *); + void *data; +} __aligned(8); + +#define BPF_DELAYED_WORK_FREE (0) +#define BPF_DELAYED_WORK_CLAIMED (1) +#define BPF_DELAYED_WORK_READY (2) + +void bpf_delayed_work_irq_work_cb(struct irq_work *work) +{ + struct bpf_delayed_irq_work *bpf_irq_work = container_of(work, struct bpf_delayed_irq_work, work); + struct bpf_delayed_work_kern *work_item, *next; + struct llist_node *work_list = llist_del_all(&bpf_irq_work->items); + + /* Traverse in submission order to preserve ordering semantics */ + llist_reverse_order(work_list); + + llist_for_each_entry_safe(work_item, next, work_list, item) { + WARN_ONCE(work_item->flags != BPF_DELAYED_WORK_READY, "incomplete bpf_delayed_work found"); + + work_item->cb(work_item->data); + + work_item->cb = work_item->data = NULL; + bpf_prog_put(bpf_irq_work->prog); + xchg(&work_item->flags, BPF_DELAYED_WORK_FREE); + } +} + +BPF_CALL_5(bpf_delayed_work_submit, struct bpf_delayed_work_kern *, work, + void *, callback_fn, void *, data, int, flags, struct bpf_prog_aux *, aux) +{ + u64 ret; + struct bpf_prog *prog; + + BUILD_BUG_ON(sizeof(struct bpf_delayed_work_kern) > sizeof(struct bpf_delayed_work)); + BUILD_BUG_ON(__alignof__(struct bpf_delayed_work_kern) != __alignof__(struct bpf_delayed_work)); + BTF_TYPE_EMIT(struct bpf_delayed_work); + + if (callback_fn == NULL) + return -EINVAL; + + if (flags != BPF_DELAYED_WORK_IRQWORK) + return -EOPNOTSUPP; + + if (!IS_ENABLED(CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG) && in_nmi()) + return -EOPNOTSUPP; + + ret = cmpxchg(&work->flags, BPF_DELAYED_WORK_FREE, BPF_DELAYED_WORK_CLAIMED); + if (ret != 0) + return -EINVAL; + + work->data = data; + work->cb = callback_fn; + + ret = cmpxchg(&work->flags, BPF_DELAYED_WORK_CLAIMED, BPF_DELAYED_WORK_READY); + if (ret != BPF_DELAYED_WORK_CLAIMED) { + WARN_ONCE(ret != BPF_DELAYED_WORK_CLAIMED, "bpf_delayed_work item altered while claimed"); + return -EINVAL; + } + + /* Bump the ref count for every work item submitted by the program. */ + prog = bpf_prog_inc_not_zero(aux->prog); + if (IS_ERR(prog)) + return PTR_ERR(prog); + + llist_add(&work->item, &aux->irq_work->items); + + /* It's okay if this prog's irq_work is already submitted, + * it will walk the same list of callbacks anyway. + */ + (void) irq_work_queue(&aux->irq_work->work); + + return 0; +} + +const struct bpf_func_proto bpf_delayed_work_submit_proto = { + .func = bpf_delayed_work_submit, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_DELAYED_WORK, + .arg2_type = ARG_PTR_TO_FUNC, + .arg3_type = ARG_PTR_TO_MAP_VALUE, /* TODO: need ptr_to_map_value_mem */ + .arg4_type = ARG_ANYTHING, +}; + const struct bpf_func_proto bpf_get_current_task_proto __weak; const struct bpf_func_proto bpf_get_current_task_btf_proto __weak; const struct bpf_func_proto bpf_probe_read_user_proto __weak; @@ -1643,6 +1733,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_dynptr_write_proto; case BPF_FUNC_dynptr_data: return &bpf_dynptr_data_proto; + case BPF_FUNC_delayed_work_submit: + return &bpf_delayed_work_submit_proto; default: break; } diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 9fd311b7a1ff..212cbea5a382 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5490,6 +5490,55 @@ static int process_timer_func(struct bpf_verifier_env *env, int regno, return 0; } +static int process_delayed_work_func(struct bpf_verifier_env *env, int regno, + struct bpf_call_arg_meta *meta) +{ + struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; + bool is_const = tnum_is_const(reg->var_off); + struct bpf_map *map = reg->map_ptr; + u64 val = reg->var_off.value; + + if (!is_const) { + verbose(env, + "R%d doesn't have constant offset. bpf_delayed_work has to be at the constant offset\n", + regno); + return -EINVAL; + } + if (!map->btf) { + verbose(env, "map '%s' has to have BTF in order to use bpf_delayed_work\n", + map->name); + return -EINVAL; + } + if (!map_value_has_delayed_work(map)) { + if (map->delayed_work_off == -E2BIG) + verbose(env, + "map '%s' has more than one 'struct bpf_delayed_work'\n", + map->name); + else if (map->delayed_work_off == -ENOENT) + verbose(env, + "map '%s' doesn't have 'struct bpf_delayed_work'\n", + map->name); + else + verbose(env, + "map '%s' is not a struct type or bpf_delayed_work is mangled\n", + map->name); + return -EINVAL; + } + if (map->delayed_work_off != val + reg->off) { + verbose(env, "off %lld doesn't point to 'struct bpf_delayed_work' that is at %d\n", + val + reg->off, map->delayed_work_off); + return -EINVAL; + } + if (meta->map_ptr) { + verbose(env, "verifier bug. Two map pointers in a timer helper\n"); + return -EFAULT; + } + + meta->map_uid = reg->map_uid; + meta->map_ptr = map; + return 0; +} + static int process_kptr_func(struct bpf_verifier_env *env, int regno, struct bpf_call_arg_meta *meta) { @@ -5677,6 +5726,7 @@ static const struct bpf_reg_types stack_ptr_types = { .types = { PTR_TO_STACK } static const struct bpf_reg_types const_str_ptr_types = { .types = { PTR_TO_MAP_VALUE } }; static const struct bpf_reg_types timer_types = { .types = { PTR_TO_MAP_VALUE } }; static const struct bpf_reg_types kptr_types = { .types = { PTR_TO_MAP_VALUE } }; +static const struct bpf_reg_types delayed_work_types = { .types = { PTR_TO_MAP_VALUE } }; static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = { [ARG_PTR_TO_MAP_KEY] = &map_key_value_types, @@ -5704,6 +5754,7 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = { [ARG_PTR_TO_TIMER] = &timer_types, [ARG_PTR_TO_KPTR] = &kptr_types, [ARG_PTR_TO_DYNPTR] = &stack_ptr_types, + [ARG_PTR_TO_DELAYED_WORK] = &delayed_work_types, }; static int check_reg_type(struct bpf_verifier_env *env, u32 regno, @@ -6018,6 +6069,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, } else if (arg_type == ARG_PTR_TO_TIMER) { if (process_timer_func(env, regno, meta)) return -EACCES; + } else if (arg_type == ARG_PTR_TO_DELAYED_WORK) { + if (process_delayed_work_func(env, regno, meta)) + return -EACCES; } else if (arg_type == ARG_PTR_TO_FUNC) { meta->subprogno = reg->subprogno; } else if (base_type(arg_type) == ARG_PTR_TO_MEM) { @@ -6670,7 +6724,8 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn if (insn->code == (BPF_JMP | BPF_CALL) && insn->src_reg == 0 && - insn->imm == BPF_FUNC_timer_set_callback) { + (insn->imm == BPF_FUNC_timer_set_callback || + insn->imm == BPF_FUNC_delayed_work_submit)) { struct bpf_verifier_state *async_cb; /* there is no real recursion here. timer callbacks are async */ @@ -6898,6 +6953,30 @@ static int set_find_vma_callback_state(struct bpf_verifier_env *env, return 0; } +static int set_delayed_work_callback_state(struct bpf_verifier_env *env, + struct bpf_func_state *caller, + struct bpf_func_state *callee, + int insn_idx) +{ + /* bpf_delayed_work_submit(struct bpf_delayed_work *work, + * void *callback_fn, void *data, u64 flags); + * + * callback_fn(void *callback_ctx); + */ + callee->regs[BPF_REG_1].type = PTR_TO_MAP_VALUE; + __mark_reg_known_zero(&callee->regs[BPF_REG_1]); + callee->regs[BPF_REG_1].map_ptr = caller->regs[BPF_REG_3].map_ptr; + + /* unused */ + __mark_reg_not_init(env, &callee->regs[BPF_REG_2]); + __mark_reg_not_init(env, &callee->regs[BPF_REG_3]); + __mark_reg_not_init(env, &callee->regs[BPF_REG_4]); + __mark_reg_not_init(env, &callee->regs[BPF_REG_5]); + + callee->in_callback_fn = true; + return 0; +} + static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) { struct bpf_verifier_state *state = env->cur_state; @@ -7294,6 +7373,11 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn reg_type_str(env, regs[BPF_REG_1].type)); return -EACCES; } + break; + case BPF_FUNC_delayed_work_submit: + err = __check_func_call(env, insn, insn_idx_p, meta.subprogno, + set_delayed_work_callback_state); + break; } if (err) @@ -7468,6 +7552,21 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn if (func_id == BPF_FUNC_get_stackid || func_id == BPF_FUNC_get_stack) env->prog->call_get_stack = true; + if (func_id == BPF_FUNC_delayed_work_submit) { + struct bpf_delayed_irq_work *irq_work = kmalloc( + sizeof(struct bpf_delayed_irq_work), GFP_KERNEL); + if (!irq_work) { + verbose(env, "could not allocate irq_work"); + return -ENOMEM; + } + + init_llist_head(&irq_work->items); + irq_work->work = IRQ_WORK_INIT_HARD(&bpf_delayed_work_irq_work_cb); + irq_work->prog = env->prog; + env->prog->aux->irq_work = irq_work; + } + + if (func_id == BPF_FUNC_get_func_ip) { if (check_get_func_ip(env)) return -ENOTSUPP; @@ -14061,6 +14160,28 @@ static int do_misc_fixups(struct bpf_verifier_env *env) goto patch_call_imm; } + if (insn->imm == BPF_FUNC_delayed_work_submit) { + // Add aux as the 5th arg to delayed_work_submit + struct bpf_insn ld_addrs[2] = { + BPF_LD_IMM64(BPF_REG_5, (long)prog->aux), + }; + + insn_buf[0] = ld_addrs[0]; + insn_buf[1] = ld_addrs[1]; + insn_buf[2] = *insn; + cnt = 3; + + new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt); + if (!new_prog) + return -ENOMEM; + + delta += cnt - 1; + env->prog = prog = new_prog; + insn = new_prog->insnsi + i + delta; + goto patch_call_imm; + } + + if (insn->imm == BPF_FUNC_task_storage_get || insn->imm == BPF_FUNC_sk_storage_get || insn->imm == BPF_FUNC_inode_storage_get) { diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index a0ec321469bd..0dd43dc9f388 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -637,6 +637,7 @@ class PrinterHelpers(Printer): 'struct bpf_dynptr', 'struct iphdr', 'struct ipv6hdr', + 'struct bpf_delayed_work', ] known_types = { '...', @@ -690,6 +691,7 @@ class PrinterHelpers(Printer): 'struct bpf_dynptr', 'struct iphdr', 'struct ipv6hdr', + 'struct bpf_delayed_work', } mapped_types = { 'u8': '__u8', diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index d68fc4f472f1..461417159106 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -5325,6 +5325,28 @@ union bpf_attr { * **-EACCES** if the SYN cookie is not valid. * * **-EPROTONOSUPPORT** if CONFIG_IPV6 is not builtin. + * + * long bpf_delayed_work_submit(struct bpf_delayed_work *work, void *cb, void *data, int flags) + * Description + * Submits a function to execute in a different context. + * + * *work* must be a member in a map value. + * + * *cb* function to call + * + * *data* context to pass as sole argument to *cb*. Must be part of + * a map value or NULL. + * + * *flags* must be BPF_DELAYED_WORK_IRQWORK + * Return + * 0 when work is successfully submitted. + * + * **-EINVAL** if *cb* is NULL + * + * **-EOPNOTSUP** if called from an NMI handler on an + * architecture without NMI-safe cmpxchg + * + * **-EINVAL** if *work* is already in use */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5535,6 +5557,7 @@ union bpf_attr { FN(tcp_raw_gen_syncookie_ipv6), \ FN(tcp_raw_check_syncookie_ipv4), \ FN(tcp_raw_check_syncookie_ipv6), \ + FN(delayed_work_submit), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper @@ -6699,6 +6722,10 @@ struct bpf_delayed_work { __u64 :64; } __attribute__((aligned(8))); +enum { + BPF_DELAYED_WORK_IRQWORK = (1UL << 0), +}; + struct bpf_sysctl { __u32 write; /* Sysctl is being read (= 0) or written (= 1). * Allows 1,2,4-byte read, but no write. From patchwork Mon Jul 11 21:48:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Delyan Kratunov X-Patchwork-Id: 12914306 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 049A0C43334 for ; Mon, 11 Jul 2022 21:48:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231502AbiGKVsU (ORCPT ); Mon, 11 Jul 2022 17:48:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60900 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230105AbiGKVsS (ORCPT ); Mon, 11 Jul 2022 17:48:18 -0400 Received: from mx0a-00082601.pphosted.com (mx0a-00082601.pphosted.com [67.231.145.42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 01CC283F31 for ; Mon, 11 Jul 2022 14:48:18 -0700 (PDT) Received: from pps.filterd (m0148461.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 26BLWf00027654 for ; Mon, 11 Jul 2022 14:48:17 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=facebook; bh=qkojWeophnMvlPvkwgKFanYBFdjmz4fIHp1c5hfNn1w=; b=joosZSQ9MRfTcxOg6l0E6s4s9lNZcCNmSgA8uVvBRJcToCojyXHTiPXKCVNwKrpZbOev DYNqiODswVdnUvsvXub4zFpvJ3ST3PrGQ1Kh54OTPvGQFYmCSfFrM8BRgjYdcnY91dqD dcwNXqJCGJJ6tb4yuyrbSNNHXJm1v7NvLVY= Received: from nam04-mw2-obe.outbound.protection.outlook.com (mail-mw2nam04lp2170.outbound.protection.outlook.com [104.47.73.170]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3h76srm60k-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 11 Jul 2022 14:48:17 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NtEqtruojK56l62l0xhmwg/ibBjV50AGyH9DcDwMSt/kbg1mwCKpSTKkl4m9HXSCXt+/pp2496EKG+ZAa1MrVDBFBB/8OTyY1N8mdKZlqORqkNOjQxDGq8Dl5luRa2L+4XucM4hlfoJjfbWO1pQ4h5JY3KOKYvldl4bS0nLlOUFyhbKUhFpFXCsUMvXxkWNvNAJfvWBpOK5WRncnyWwyD/qlQE5+xgNk5BajTpENSBYhszlqS/X2sn8t/ja97Y/lDshtBqoOv9wVWimHlTIbo+4LZ3iPQn0x/s/qX1yPoWfztH2RKPI1MAmtF4ZPi9gztiuSTnfMk5VaWSi5n+edIA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=qkojWeophnMvlPvkwgKFanYBFdjmz4fIHp1c5hfNn1w=; b=bDw+MDnVJWNJ7/VbcGjlcIsHX3nzE/Uq8VsBxO7BQLjfR+n184xNgHKRUQs/gsgfCgABBvOPVWXKDrGx2OgLwLxQ0fzI7WmNLvHt9x9xlzRJDZuKYyTnY5+OF1Ehz4MjdZf/+wVn1fVTL3CcSKtF5a9GKTvzYxgadWMPC7TL6hl4IvUzwbR9BwQwAhiILkfxFNmU9QkvGwqvoVCNMJ7rPd5y6bMoHsarR8pcj1+sEFsN13H7IBwAo8mWSP1YJfftIvTjyMA+kPcut6bqhNjYss6MDbeYHl0FvWQsQYNLRmUvg4oSUb8cA6q7GmRGvjb5oCms0t/GcBZW9qgVGqIaHA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=fb.com; dmarc=pass action=none header.from=fb.com; dkim=pass header.d=fb.com; arc=none Received: from SJ0PR15MB5154.namprd15.prod.outlook.com (2603:10b6:a03:423::6) by MN2PR15MB3375.namprd15.prod.outlook.com (2603:10b6:208:39::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.26; Mon, 11 Jul 2022 21:48:14 +0000 Received: from SJ0PR15MB5154.namprd15.prod.outlook.com ([fe80::ac52:e8fa:831f:237e]) by SJ0PR15MB5154.namprd15.prod.outlook.com ([fe80::ac52:e8fa:831f:237e%9]) with mapi id 15.20.5395.020; Mon, 11 Jul 2022 21:48:14 +0000 From: Delyan Kratunov To: "daniel@iogearbox.net" , "ast@kernel.org" , "andrii@kernel.org" , "bpf@vger.kernel.org" Subject: [PATCH RFC bpf-next 3/3] selftests: delayed_work tests Thread-Topic: [PATCH RFC bpf-next 3/3] selftests: delayed_work tests Thread-Index: AQHYlW/squDxaqFKcUiJu7cMWIqu6w== Date: Mon, 11 Jul 2022 21:48:14 +0000 Message-ID: <32e573966bf7b4d43be0eb8e23d3d13c948606f6.1657576063.git.delyank@fb.com> References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 6a66239d-af04-4f06-8ebb-08da63870e9b x-ms-traffictypediagnostic: MN2PR15MB3375:EE_ x-fb-source: Internal x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: O34KQMxeELAm2CEC/G+YdPzZNz88aDqKVLBwvgSJYWQ9UqN89X0mbNKMiQ9adzowDBIuc8lGJkJwokc1TMM3nVMjZbuxe10w7WmTZl25B2yLGWcsCqYpnY7Et5H8LqMWv5zuy9Y9eG6uIMU9LfPbAUVMayD0+7NG8J9pMQpdFmTyr0C7dQ8Gst5Agy2OHSQh56JTUHA5Co3aHj67yFViOZrABoLgjFinKmdlhN+UiDEAraDLOXruIJNXulSM62jQfoZvitf5YhAd/oMWX4yy8vEg/sm6TmT5vMyLayMkvUBuy+X+Q8AFT5uarwiSXTKGoTjvanBugj1OdchnU3HndUPIcHtSogiOvpaVHqX3MwLs641haNnmgp7WmYEJPzD42juW7X+6B/QrDeN3f1VrWOv+/PqP88Ib0t28V1vozyRuJH7uJztfE8biATVSrm31agO7aK7IZPc76OkQRiR+JPwBYkLgpdOZEl7xX75wErdZ0QFqQZnDLBUCJ8zt83GzZIrECvdE5WqfZoF04lXkH36MWo1d57mn+RkERqppNRCaGry7FZ6meq12VqWOaqWr/FmDjlGVI3RP9fDX5Yviu6GJMgbT5Sza+Moy94Evz6Vi4mmiNHP0B/WB4xRxuwkd5ACL/opMwneFMqNzR66EvpiCSiIjjLip5ldsJ9FxeZTlrU5OKUn7nvtiQ+Tvkf2Og1ZVgnFXojJEYlBIQuQ28dfxZQtd2kcem9qpubCCAxUNA3CpQz+7E7pg60FvrBDQluem13LTy2BeEO506B1Eo8mFzOpq2KXeS2pSHy3V1qGwn0aE1VvCFH2UKSdQAu6s x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SJ0PR15MB5154.namprd15.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230016)(4636009)(366004)(396003)(136003)(376002)(346002)(39860400002)(38100700002)(2616005)(38070700005)(122000001)(186003)(66476007)(8676002)(66446008)(76116006)(5660300002)(8936002)(66556008)(66946007)(64756008)(2906002)(41300700001)(6512007)(71200400001)(478600001)(110136005)(91956017)(316002)(6506007)(6486002)(36756003)(86362001);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?q?wz+c9DBMVKCBH21pfxJFgi9?= =?iso-8859-1?q?U2EPFgtSne8v6eAKkcdhNZfppvU7ivE61aBuw2lFBQ7XY0OzF8UqLv7GYEP0?= =?iso-8859-1?q?ZZaGYBK9wSCH+3GqcDHyw10kuSVVHrxUtTMPW4gPz3ACm7/fnc/aDhe4EfuC?= =?iso-8859-1?q?St8xvQ0hONk2Kynfe5HKceqDSVkZpY9njSQQ67zzkJpqRe4HzAu8nRayw7tn?= =?iso-8859-1?q?u4Ij+DhhIQGA3aI1jChAdeFexhZDF7qM+ZxeHfkmQT7tmcpXGHv7pyWEiBxg?= =?iso-8859-1?q?UTJjYz7MalhppIhsM3nAHI63bWSC/wmWUKk816dEVPQMWOoj4KoOy8bD9xHj?= =?iso-8859-1?q?ImtXy2HD8N9v17KbjyRfDX4HItvGUXNfqqSHqdfsmxna2EIKHlk6fxEj+Y/J?= =?iso-8859-1?q?JINlX6kiZ5B3cFGF9u0sL4uiiBm7tSiCNYXenLve5EQaheEvRNJTPQ4kfixa?= =?iso-8859-1?q?7VAGZgr+JShYrro7iil16ge1fMok3wSOC0kGLEaQD3n1eSbddB5mFk/isw0L?= =?iso-8859-1?q?US5LsWVp8AvqPO61GNi+L3phDv9Q1OX71BKxMrizKZtXU012Ev/l4UA/4vj7?= =?iso-8859-1?q?okUil0PK4/LMf5MNDs/32Xy3bUaYSqC9zrojnNAWmceqN0RC9GdVNLuJlpRG?= =?iso-8859-1?q?1V6AetGdCfRXdcMpRjI8v1l3uXOvZyy1z5w9uqHtR4DAmaOKaq1hDjiOOmFH?= =?iso-8859-1?q?/VGnYFLxQPJpNIR4gefCK4cruB0kgdrJ2NBSgsaBXMN8q2WGwEDXI+kDbDe0?= =?iso-8859-1?q?3ZHf0++FAPZgjUtDc29/Hm0T/6LlwQuToo/D96L6/jkuQfPGR6L62jPhkvTU?= =?iso-8859-1?q?gd86a1ezPHl5np/aqMyNqsS4X47+0lpGmWuJxIuT7nPcO62mha3jRhbxq6QL?= =?iso-8859-1?q?BK0Tu7AkwmB3+VkdwMJih+lvqSsziZZpKiUXp1g/QF5TYwA7uNbN1dBqyF/l?= =?iso-8859-1?q?LdlHM3l2pHF0fiFv58rj/XzDgcM1BF5p/QhDK7fvlhjx5fxDbTTz70U9/JJp?= =?iso-8859-1?q?lILsnsqpeiBSbiSSDDmBIuXIKym+ig675cfQ2ALjsDeBm5OXOpi+k2IrFKVG?= =?iso-8859-1?q?zdYUPME68tSd4ogRS2QgYI5owPtRAXUSJPQMlq2FRcnR7AXjFe4JYzKqiwS7?= =?iso-8859-1?q?aZjhSxrntB3qqwXjbWnH+ZI/5NInHeBdIWpk1Ch1zSMqz6EHFUbgccXpFnjt?= =?iso-8859-1?q?YeBkHWbUOCBlFPA2LMG+82NocviLKiJaX3nIY/TPof2Dn6QTF3RVjO2ZQgA5?= =?iso-8859-1?q?00CjFDFIjniNIQyd7nUMweaC0D/waQokWBv1bJyRyga/zETfQGR0AsNWOjKx?= =?iso-8859-1?q?/+W9Fnu9+fVNtOmuQ7yBvF3bL6URTboSXabyQ2OJcA87PVMcCqLarU8ceU6J?= =?iso-8859-1?q?OzkXtgyncqbDe3pSNyWjbg2MsfM3nVpiHy6b/sqmsUMgfOnsiY8CejjeDMTR?= =?iso-8859-1?q?jsvbVBuOL7RfvqniUZ+i5wCuO79L7G3xo6ivYxPZIoZatUanSvS87lmSSF0/?= =?iso-8859-1?q?nYqjsjv/r4QjdxXvsrijXkAUYHE0zntMhfmeIPY+NC3X1zXSISOn0noo45FZ?= =?iso-8859-1?q?CY1wh1Bvova3C28/gzbhoioCk3mieOq31rrSJXBWOu+MYJXHt59ZPTrYKjs3?= =?iso-8859-1?q?5VMHFqNb6zmQZZ/bK8+7jMQvD7cfnnYoWZLUiww=3D=3D?= MIME-Version: 1.0 X-OriginatorOrg: fb.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: SJ0PR15MB5154.namprd15.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6a66239d-af04-4f06-8ebb-08da63870e9b X-MS-Exchange-CrossTenant-originalarrivaltime: 11 Jul 2022 21:48:14.2844 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 8ae927fe-1255-47a7-a2af-5f3a069daaa2 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: jfOwn769GdOVW1GKCt761PsSCyW15bGA8IROuUW8h4Fd2Fmt30hwqoLsHtrkjnNW X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR15MB3375 X-Proofpoint-ORIG-GUID: fgz5rPoZVT-PYnAd0hET9W_QCJVD2Rfb X-Proofpoint-GUID: fgz5rPoZVT-PYnAd0hET9W_QCJVD2Rfb X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-07-11_25,2022-07-08_01,2022-06-22_01 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org X-Patchwork-Delegate: bpf@iogearbox.net X-Patchwork-State: RFC Basic tests, will develop in further iterations. Signed-off-by: Delyan Kratunov --- .../selftests/bpf/prog_tests/delayed_work.c | 29 +++++++++ .../selftests/bpf/progs/delayed_irqwork.c | 59 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/delayed_work.c create mode 100644 tools/testing/selftests/bpf/progs/delayed_irqwork.c diff --git a/tools/testing/selftests/bpf/prog_tests/delayed_work.c b/tools/testing/selftests/bpf/prog_tests/delayed_work.c new file mode 100644 index 000000000000..80ed52c8f34c --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/delayed_work.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) Meta Platforms, Inc. and affiliates. */ + +#include +#include "delayed_irqwork.skel.h" + +void test_delayed_work(void) +{ + int err; + struct delayed_irqwork *skel; + + skel = delayed_irqwork__open(); + if (!ASSERT_OK_PTR(skel, "skel_open")) + return; + + err = delayed_irqwork__load(skel); + if (!ASSERT_OK(err, "skel_load")) + goto cleanup; + + err = delayed_irqwork__attach(skel); + if (!ASSERT_OK(err, "skel_attach")) + goto cleanup; + + /* trigger tracepoint */ + usleep(1000000); + +cleanup: + delayed_irqwork__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/delayed_irqwork.c b/tools/testing/selftests/bpf/progs/delayed_irqwork.c new file mode 100644 index 000000000000..9fde66616681 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/delayed_irqwork.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ +#include "vmlinux.h" + +#include "bpf_misc.h" +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +struct map_value_type { + struct bpf_delayed_work work; + struct { + __u32 arg1; + } data; +}; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 2); + __type(key, __u32); + __type(value, struct map_value_type); +} map1 SEC(".maps"); + +static __noinline int callback(void *args) +{ + struct map_value_type *val = args; + + bpf_printk("callback: %p, %x", val, val->data.arg1); + return 0; +} + +SEC("fentry/" SYS_PREFIX "sys_nanosleep") +int delayed_irqwork(void *ctx) +{ + int ret; + __u32 key = 0; + struct map_value_type *value = (struct map_value_type *) bpf_map_lookup_elem(&map1, &key); + + if (!value) { + bpf_printk("Could not get map value"); + return 0; + } + + value->data.arg1 = 0xcafe; + ret = bpf_delayed_work_submit(&value->work, callback, value, BPF_DELAYED_WORK_IRQWORK); + + key = 1; + value = (struct map_value_type *) bpf_map_lookup_elem(&map1, &key); + if (!value) { + bpf_printk("Could not get map value"); + return 0; + } + value->data.arg1 = 0xbeef; + ret = bpf_delayed_work_submit(&value->work, callback, value, BPF_DELAYED_WORK_IRQWORK); + + return 0; +}