Received: by 2002:a6b:fb09:0:0:0:0:0 with SMTP id h9csp1908154iog; Tue, 14 Jun 2022 16:34:09 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tdOaTKXshTXwTtFxNPG18J4iLKLi/zeyr8xBdRv+TY7G4bipOJJ4FauVYl3YDHhM3a9E2D X-Received: by 2002:a17:902:c2c3:b0:168:ca2d:3c46 with SMTP id c3-20020a170902c2c300b00168ca2d3c46mr6508657pla.42.1655249649253; Tue, 14 Jun 2022 16:34:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655249649; cv=none; d=google.com; s=arc-20160816; b=TkYGMvhO7V0Y4lInzIx4ve5VqNhkjkhuByKX+kMT1DKB46ZD7xCNdezDDfFpYigfuQ zT+fpEVHwNZ2lTMxC55v6y3JXiyzF2beN9xs2N12ufRAZrQfRri9n5Zwf+58AxeIOxMs keqxeYUSz94UiLyH/i+lonqXh16eJQtK/krpg+oSZ9BmyYt59g6QFeaAVN3l3nA7Sc5S kv+rOWeolUAg1yn927qs6uh4S0fDL+WDrPAsvzkZn9ic3rsHbTohNrmEnPgzTKCIbYN1 jhPN6VtJa+QHXWDmFibwYkzYkgUn3vteJpwPRdsiLsw33In+w1fTRAJBUoEY1wT0tgal ky5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version; bh=+BlywHEHWwAikA1BIx+1HObwxJemRBodVSJxjZAvyH0=; b=Bw+a3HoEmzqWQRcZ7dnDsrDLmEwqh9+sUnRRyGuriCTqur0QK/Giz/Tw0jqkvGvuK/ NcqU8cy8YQw4KWgZRunvxHdnvGDuLUhxkmzlZo3BmCBImaG3zFRKNwJ0voGedCfnwnZm yo/fbUZ0Q8iFNj6M//sr7pz4AuSIq4Dbbg58J7MMZy3rsfushAPwVDuLwgFDB7bGG88N 9IBktsmd6u2zwMN7V4DSiv4KbPNkA+EWI+zWeNSyI2077Bq2exyt/07OmkWZzK/KVZW2 JEbTJ9GPAVUZRzROkpPNmhY1EwRVZHiEVSWUj167IE/7SUZyRTvF/3vRTDE6szJnWL+K 4ooA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i1-20020a1709026ac100b0016400fa42f2si14206538plt.454.2022.06.14.16.33.27; Tue, 14 Jun 2022 16:34:09 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353017AbiFNWop (ORCPT + 99 others); Tue, 14 Jun 2022 18:44:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231621AbiFNWon (ORCPT ); Tue, 14 Jun 2022 18:44:43 -0400 Received: from mail-oa1-f44.google.com (mail-oa1-f44.google.com [209.85.160.44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 16CEA527FF; Tue, 14 Jun 2022 15:44:43 -0700 (PDT) Received: by mail-oa1-f44.google.com with SMTP id 586e51a60fabf-f2a4c51c45so14373551fac.9; Tue, 14 Jun 2022 15:44:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=+BlywHEHWwAikA1BIx+1HObwxJemRBodVSJxjZAvyH0=; b=oek8ORgLW920YK+aBF4RjJQ+66CJReyk51tWXZ0Ss6MAV8UmvfIr1Z1bfH9yMZZUIb xXqir0BHTbtml6r1JXLJoKEEPncPnua6TOz9xPj9fIz2dBkbqeaNz9K6HiSFc3xVys9v hPDsWraLEzExfKyuS/wxWDhXM3qx+/Rku+Fwk6yLfpoGjqMhTHYzeWiP+GhLxwEt1Rj6 nBZeO5P4FBhZ82cGae8pqT/UDqbItDTvXqWnL+kLePURN07liQQ/EBDru7Kzr2HyKid4 EdIR3My73lezA7lBQE9sJoF/cmuzaKVBvvG64btEpDRSrg0a3an63HRCtGSoXERTBxJP dkiQ== X-Gm-Message-State: AJIora801HdU2doKnRFQJKBykyf/SbOCFHCBjIRcMW7iUWV6le5Lz6BT 7ScTeaCMhjZu8TJz9YYnWVymWkp0Sq/eJC69TRc= X-Received: by 2002:a05:6870:4585:b0:fb:5105:76b8 with SMTP id y5-20020a056870458500b000fb510576b8mr3627210oao.92.1655246682311; Tue, 14 Jun 2022 15:44:42 -0700 (PDT) MIME-Version: 1.0 References: <20220614143353.1559597-1-irogers@google.com> <20220614143353.1559597-5-irogers@google.com> In-Reply-To: <20220614143353.1559597-5-irogers@google.com> From: Namhyung Kim Date: Tue, 14 Jun 2022 15:44:31 -0700 Message-ID: Subject: Re: [PATCH v2 4/6] perf cpumap: Fix alignment for masks in event encoding To: Ian Rogers Cc: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , James Clark , Kees Cook , "Gustavo A. R. Silva" , Adrian Hunter , Riccardo Mancini , German Gomez , Colin Ian King , Song Liu , Dave Marchevsky , Athira Rajeev , Alexey Bayduraev , Leo Yan , linux-perf-users , linux-kernel , Stephane Eranian Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Ian, On Tue, Jun 14, 2022 at 7:34 AM Ian Rogers wrote: > > A mask encoding of a cpu map is laid out as: > u16 nr > u16 long_size > unsigned long mask[]; > However, the mask may be 8-byte aligned meaning there is a 4-byte pad > after long_size. This means 32-bit and 64-bit builds see the mask as > being at different offsets. On top of this the structure is in the byte > data[] encoded as: > u16 type > char data[] > This means the mask's struct isn't the required 4 or 8 byte aligned, but > is offset by 2. Consequently the long reads and writes are causing > undefined behavior as the alignment is broken. > > Fix the mask struct by creating explicit 32 and 64-bit variants, use a > union to avoid data[] and casts; the struct must be packed so the > layout matches the existing perf.data layout. Taking an address of a > member of a packed struct breaks alignment so pass the packed > perf_record_cpu_map_data to functions, so they can access variables with > the right alignment. > > As the 64-bit version has 4 bytes of padding, optimizing writing to only > write the 32-bit version. > > Signed-off-by: Ian Rogers > --- > tools/lib/perf/include/perf/event.h | 36 +++++++++++-- > tools/perf/tests/cpumap.c | 19 ++++--- > tools/perf/util/cpumap.c | 80 +++++++++++++++++++++++------ > tools/perf/util/cpumap.h | 4 +- > tools/perf/util/session.c | 30 +++++------ > tools/perf/util/synthetic-events.c | 34 +++++++----- > 6 files changed, 143 insertions(+), 60 deletions(-) > > diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h > index e7758707cadd..d2d32589758a 100644 > --- a/tools/lib/perf/include/perf/event.h > +++ b/tools/lib/perf/include/perf/event.h > @@ -6,6 +6,7 @@ > #include > #include > #include > +#include > #include /* pid_t */ > > #define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem)) > @@ -153,20 +154,47 @@ enum { > PERF_CPU_MAP__MASK = 1, > }; > > +/* > + * Array encoding of a perf_cpu_map where nr is the number of entries in cpu[] > + * and each entry is a value for a CPU in the map. > + */ > struct cpu_map_entries { > __u16 nr; > __u16 cpu[]; > }; > > -struct perf_record_record_cpu_map { > +/* Bitmap encoding of a perf_cpu_map where bitmap entries are 32-bit. */ > +struct perf_record_mask_cpu_map32 { > + /* Number of mask values. */ > __u16 nr; > + /* Constant 4. */ > __u16 long_size; > - unsigned long mask[]; > + /* Bitmap data. */ > + __u32 mask[]; > }; > > -struct perf_record_cpu_map_data { > +/* Bitmap encoding of a perf_cpu_map where bitmap entries are 64-bit. */ > +struct perf_record_mask_cpu_map64 { > + /* Number of mask values. */ > + __u16 nr; > + /* Constant 8. */ > + __u16 long_size; > + /* Legacy padding. */ > + char __pad[4]; > + /* Bitmap data. */ > + __u64 mask[]; > +}; > + > +struct __packed perf_record_cpu_map_data { > __u16 type; > - char data[]; > + union { > + /* Used when type == PERF_CPU_MAP__CPUS. */ > + struct cpu_map_entries cpus_data; > + /* Used when type == PERF_CPU_MAP__MASK and long_size == 4. */ > + struct perf_record_mask_cpu_map32 mask32_data; > + /* Used when type == PERF_CPU_MAP__MASK and long_size == 8. */ > + struct perf_record_mask_cpu_map64 mask64_data; > + }; > }; How about moving the 'type' to the union as well? This way we don't need to pack the entire struct and can have a common struct for 32 and 64 bit.. struct cpu_map_entries { __u16 type; __u16 nr; __u16 cpu[]; }; struct perf_record_mask_cpu_map { __u16 type; __u16 nr; __u16 long_size; // still needed? __u16 pad; unsigned long mask[]; }; // changed it to union union perf_record_cpu_map_data { __u16 type; struct cpu_map_entries cpus_data; struct perf_record_mask_cpu_map mask_data; }; Thanks, Namhyung