From patchwork Tue Feb 21 01:32:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Stabellini X-Patchwork-Id: 9583787 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 308C46047C for ; Tue, 21 Feb 2017 01:35:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0F135288D3 for ; Tue, 21 Feb 2017 01:35:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 01A6028909; Tue, 21 Feb 2017 01:35:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id AB220288D3 for ; Tue, 21 Feb 2017 01:35:49 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cfzJs-00026z-UB; Tue, 21 Feb 2017 01:32:44 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cfzJr-00026t-Vp for xen-devel@lists.xenproject.org; Tue, 21 Feb 2017 01:32:44 +0000 Received: from [193.109.254.147] by server-10.bemta-6.messagelabs.com id 30/E7-13192-BB89BA85; Tue, 21 Feb 2017 01:32:43 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrPLMWRWlGSWpSXmKPExsVybKJsh+6uGas jDN68lLf4vmUykwOjx+EPV1gCGKNYM/OS8isSWDN+XFzEWHAlsGLmnreMDYwT1LoYuTiEBKYy SnS8/c0K4Rxikrg/aSZbFyMnB5uAocTfJ5vAbBEBJYl7qyYzgdjMAm1MEkffh4LYwgIpEnvf9 TKD2CwCqhJrdt4Gq+EVcJO4f2QDWFxCQE7i5LHJrBB2hsS8njlQtpfEohuXoGw1iavnNjFPYO RZwMiwilGjOLWoLLVI19hAL6koMz2jJDcxM0fX0MBMLze1uDgxPTUnMalYLzk/dxMj0PMMQLC D8e/awEOMkhxMSqK8d5asihDiS8pPqcxILM6ILyrNSS0+xCjDwaEkwbt7+uoIIcGi1PTUirTM HGAIwqQlOHiURHiXg6R5iwsSc4sz0yFSpxh1OU7dOP2SSYglLz8vVUqcdz9IkQBIUUZpHtwIW DxcYpSVEuZlBDpKiKcgtSg3swRV/hWjOAejkjDvOpApPJl5JXCbXgEdwQR0xE2PlSBHlCQipK QaGEVmBc+M/fzt6oIvmq7qz1LXz8t6Z9j0daGZi2ewvsq3a34qjtFTXptUGtuWbz1U/eXd4fO WQSe3ZbFN9HzC3Ka2jP3NN3W5s2LlrAEXdm0o2pxzrfA+i+LDnoaaH+qV6rdkFa2m103ILY35 eZ170l+nXbPUH4mmanOm2TXe3P318qeCs4s/bldiKc5INNRiLipOBADwckazggIAAA== X-Env-Sender: sstabellini@kernel.org X-Msg-Ref: server-10.tower-27.messagelabs.com!1487640761!64768545!1 X-Originating-IP: [198.145.29.136] X-SpamReason: No, hits=0.3 required=7.0 tests=MAILTO_TO_SPAM_ADDR X-StarScan-Received: X-StarScan-Version: 9.2.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 7182 invoked from network); 21 Feb 2017 01:32:42 -0000 Received: from mail.kernel.org (HELO mail.kernel.org) (198.145.29.136) by server-10.tower-27.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 21 Feb 2017 01:32:42 -0000 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 19A7D20121; Tue, 21 Feb 2017 01:32:39 +0000 (UTC) Received: from sstabellini-ThinkPad-X260.hil-pdxphhh.sea.wayport.net (ip-64-134-128-59.public.wayport.net [64.134.128.59]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 576EA2011B; Tue, 21 Feb 2017 01:32:37 +0000 (UTC) From: Stefano Stabellini To: xen-devel@lists.xenproject.org Date: Mon, 20 Feb 2017 17:32:35 -0800 Message-Id: <1487640755-12356-1-git-send-email-sstabellini@kernel.org> X-Mailer: git-send-email 1.9.1 X-Virus-Scanned: ClamAV using ClamSMTP Cc: sstabellini@kernel.org, oleksandr_andrushchenko@epam.com, andr2000@gmail.com, andrii.anisov@gmail.com, Stefano Stabellini , vlad.babchuk@gmail.com, al1img@gmail.com, JBeulich@suse.com, joculator@gmail.com Subject: [Xen-devel] [PATCH v2] ring.h: introduce macros to handle monodirectional rings with multiple req sizes X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This patch introduces macros, structs and functions to handle rings in the format described by docs/misc/pvcalls.markdown and docs/misc/9pfs.markdown. The index page (struct __name##_data_intf) contains the indexes and the grant refs to setup two rings. Indexes page +----------------------+ |@0 $NAME_data_intf: | |@76: ring_order = 1 | |@80: ref[0]+ | |@84: ref[1]+ | | | | | | | +----------------------+ | v (data ring) +-------+-----------+ | @0->4098: in | | ref[0] | |-------------------| | @4099->8196: out | | ref[1] | +-------------------+ $NAME_read_packet and $NAME_write_packet are provided to read or write any data struct from/to the ring. In pvcalls, they are unused. In xen 9pfs, they are used to read or write the 9pfs header. In other protocols they could be used to read/write the whole request structure. See docs/misc/9pfs.markdown:Ring Usage to learn how to check how much data is on the ring, and how to handle notifications. There is a ring_size parameter to most functions so that protocols using these macros don't have to have a statically defined ring order at build time. In pvcalls for example, each new ring could have a different order. These macros don't help you share the indexes page or the event channels needed for notifications. You can do that with other out of band mechanisms, such as xenstore or another ring. Signed-off-by: Stefano Stabellini CC: konrad.wilk@oracle.com CC: andr2000@gmail.com CC: oleksandr_andrushchenko@epam.com CC: andrii.anisov@gmail.com CC: vlad.babchuk@gmail.com CC: al1img@gmail.com CC: joculator@gmail.com CC: JBeulich@suse.com --- Changes in v2: - fix typo - remove leading underscores from names - use UL - do not parenthesize parameters - code readability improvements Give a look at the following branch to see how they are used with pvcalls and xen-9pfs (the drivers are still work in progress): git://git.kernel.org/pub/scm/linux/kernel/git/sstabellini/xen.git 9pfs-async-v5 --- xen/include/public/io/ring.h | 114 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/xen/include/public/io/ring.h b/xen/include/public/io/ring.h index 801c0da..381be70 100644 --- a/xen/include/public/io/ring.h +++ b/xen/include/public/io/ring.h @@ -313,6 +313,120 @@ typedef struct __name##_back_ring __name##_back_ring_t (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ } while (0) + +/* + * DEFINE_XEN_FLEX_RING defines two monodirectional rings and functions + * to check if there is data on the ring, and to read and write to them. + * + * XEN_FLEX_RING_SIZE + * Convenience macro to calculate the size of one of the two rings + * from the overall order. + * + * $NAME_mask + * Function to apply the size mask to an index, to reduce the index + * within the range [0-size]. + * + * $NAME_read_packet + * Function to read a defined amount of data from the ring. The amount + * of data read is sizeof(__packet_t). + * + * $NAME_write_packet + * Function to write a defined amount of data to the ring. The amount + * of data to write is sizeof(__packet_t). + * + * $NAME_data_intf + * Indexes page, shared between frontend and backend. It also + * contains the array of grant refs. Different protocols can have + * extensions to the basic format, in such cases please define your + * own data_intf struct. + * + * $NAME_queued + * Function to calculate how many bytes are currently on the ring, + * ready to be read. It can also be used to calculate how much free + * space is currently on the ring (ring_size - $NAME_queued()). + */ +#define XEN_FLEX_RING_SIZE(order) \ + (1UL << (order + PAGE_SHIFT - 1)) + +#define DEFINE_XEN_FLEX_RING(name, packet_t) \ + \ +static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size) \ +{ \ + return (idx & (ring_size - 1)); \ +} \ + \ +static inline RING_IDX name##_mask_order(RING_IDX idx, RING_IDX ring_order) \ +{ \ + return (idx & (XEN_FLEX_RING_SIZE(ring_order) - 1)); \ +} \ + \ +static inline void name##_read_packet(char *buf, \ + RING_IDX *masked_prod, RING_IDX *masked_cons, \ + RING_IDX ring_size, packet_t *h) { \ + if (*masked_cons < *masked_prod || \ + sizeof(*h) <= ring_size - *masked_cons) { \ + memcpy(h, buf + *masked_cons, sizeof(*h)); \ + } else { \ + memcpy(h, buf + *masked_cons, ring_size - *masked_cons); \ + memcpy((char *)h + ring_size - *masked_cons, buf, \ + sizeof(*h) - (ring_size - *masked_cons)); \ + } \ + *masked_cons = name##_mask(*masked_cons + sizeof(*h), ring_size); \ +} \ + \ +static inline void name##_write_packet(char *buf, \ + RING_IDX *masked_prod, RING_IDX *masked_cons, \ + RING_IDX ring_size, packet_t *h) { \ + if (*masked_prod < *masked_cons || \ + sizeof(*h) <= ring_size - *masked_prod) { \ + memcpy(buf + *masked_prod, h, sizeof(*h)); \ + } else { \ + memcpy(buf + *masked_prod, h, ring_size - *masked_prod); \ + memcpy(buf, (char *)h + (ring_size - *masked_prod), \ + sizeof(*h) - (ring_size - *masked_prod)); \ + } \ + *masked_prod = name##_mask(*masked_prod + sizeof(*h), ring_size); \ +} \ + \ +struct name##_data { \ + unsigned char *in; /* half of the allocation */ \ + unsigned char *out; /* half of the allocation */ \ +}; \ + \ +struct name##_data_intf { \ + RING_IDX in_cons, in_prod; \ + \ + uint8_t pad1[56]; \ + \ + RING_IDX out_cons, out_prod; \ + \ + uint8_t pad2[56]; \ + \ + RING_IDX ring_order; \ + grant_ref_t ref[]; \ +}; \ + \ +static inline RING_IDX name##_queued(RING_IDX prod, \ + RING_IDX cons, RING_IDX ring_size) \ +{ \ + RING_IDX size; \ + \ + if (prod == cons) \ + return 0; \ + \ + prod = name##_mask(prod, ring_size); \ + cons = name##_mask(cons, ring_size); \ + \ + if (prod == cons) \ + return ring_size; \ + \ + if (prod > cons) \ + size = prod - cons; \ + else \ + size = ring_size - (cons - prod); \ + return size; \ +}; + #endif /* __XEN_PUBLIC_IO_RING_H__ */ /*