From nobody Sun Feb 8 09:16:57 2026 Received: from mail-oo1-f48.google.com (mail-oo1-f48.google.com [209.85.161.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95EA8274672; Wed, 14 May 2025 10:58:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220316; cv=none; b=DvjOvnG8uRsc/ASlfoXfc5y0HVOKeGknkX/hM80Rxhiq0mX89566U5dtx2cscY65DZwpt4SIRqeYXusG8pKN/sFXEUSuC28m71UQ/5dsJoF8elnLLXXQCf3svO2ZIdy12B/pB+rnVCLgLHW+BF1v4OGToqENweUEr2a2eQtoU+c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220316; c=relaxed/simple; bh=+Jx0iphnXuSVjVB7a29W7yimG5/BrqeaURmJ1hW7NZg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UvKk9S/W/elONyf4fDF2kBWcJxRv9B9RLdQRc0vk1Cd1hKTvY1Zszz2hJ7wglHO9wOI52mn9+18uGNI+4eLcCk+XRM+C8zJHGpk9YnYD3gV/7AZHCqxjAIeI4N5DIzU6hvEMjHRhzRxX+Vvdlbb/Kg/32YBbQ/G6b8gy93KqfIg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YS6RoZ5g; arc=none smtp.client-ip=209.85.161.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YS6RoZ5g" Received: by mail-oo1-f48.google.com with SMTP id 006d021491bc7-6062e41916dso3248600eaf.1; Wed, 14 May 2025 03:58:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747220313; x=1747825113; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LKfsulkMnbgwajcoUFefYum3KXkpP1AWjoY1QW06NXk=; b=YS6RoZ5grZNuoSpHhXfmf/u4R5/Nfr5o2DyQ8v0BylKYwtobkWj88oaZLP4pbRbsDk dTibry7ioKXWPPozJFcnMh1/tZz2VRTUdctijxLrGk+o/NCAxu/NFpCJL5SV2Vd4CrnN 5TK3Qq008Nfj8Du0IqDF32no6XjD6sVgd3MgpGRtxS8JYkUYCd3AWfN3iEHo7HzJxMy5 URsvpsC1p278FUfs5+pMD4YowchWSbOtz8li3YDQVMQJ74Wqv6BOKiI2j5/Q8ppJl5LM GSCbBoiLuOTyRjtdQ3JGDpQuK1o/tkBEgofN1q6QG/rkYYa011KQnJqosAP4mjr5HkhC rRCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747220313; x=1747825113; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LKfsulkMnbgwajcoUFefYum3KXkpP1AWjoY1QW06NXk=; b=WGud1fMcRLGYjLR6bBvlVbF8nlMR8sEIHHrnikbJjCc26yeVFLpcRtzKwd3olz5wkQ zgqkIdmIJy8CWNFOwWG7fPrwF38OSJP7lbTTtEujnTWHO+8tn9gZAqRcJ+gxNkfXTGWi 2xNIlmVzPSZw68eoaBSreehFkAQEs8yC90GD7xjcHfXXBlh3sL6sS+OsA9Z0IT1sk7ax ihl1mj3zb7XlCXzBv52OfQZKMtC6RzfkA/b4TUaFo2kKWjAt91Isi/Hrpq5YYUx7zg7y aKrEiuxux7N3G0xdY/QWr8KFuUl5BtANKyHGkWLutiMZjuAiG9Os+hXr2zveUjT3PUe+ GpIw== X-Forwarded-Encrypted: i=1; AJvYcCVir54BQQVFDCtMPsm6WFxGxfCacTGBAJGY011BkBEf+mC/Idqo54sY5PJ1H8x/RMx8a5O3Gxvo0ptlUPPQurA=@vger.kernel.org, AJvYcCWtbGO04Y83N6F/+Wwa9Fz79m9Lju/tKzokJzAuAD6/SSR7BcHrgMyxFViXI7PUh7i+xac6GGDwTOv9iO8=@vger.kernel.org, AJvYcCX/qb8KSaZD2112ONldSfQkmfucbspTqcAkfrZwK/rSDf2h3yl4DlDcK1B82VmiAVaff3fHntJCCxKQ@vger.kernel.org X-Gm-Message-State: AOJu0YyMSVbxU9qpn5fH5ea4XQ83MVONmThdPoGk04E62GUVx6WobkoM yAL9+okp7vmZLyVzfMy2ebyAyhvzH2GGXjpLj0N8RWzvDOeGk6mA X-Gm-Gg: ASbGncsZlGUHn1MvNcQTB8QweZ6XXuw4mfRGQXM+fSYVGeGxoNwD8uqOc1+M34YD79D wE3XWWSOxxvgXDjZ2WopsH0bLV2UE7N4dFGoz5moxPqRVhoAFXg3daO1SzfR/33AGbS2lLWfx1V hLZaTHeGKIyPTyPZjVsli9lEwg3Y/xiCtHB47H3hVVxw+Zdd4+bfEZm23dS70y5tOFnIINhqzzc Pq38RDvU5S6zgFZUP6sCCQHtU7LjnsGc9t0sBNdmdtNWAGJdBsBR7MAhq+Wd1YePYOpOyAlpiwS JD7EUaNtwt81d++BUhe1+pSaU4NHdC62A4Z7lMoodsq4wEfD7FrkJ+lMCziHR93uB4rRjIWjOLS dPmjNOxp9ITMA4n0ZSOaY9eE= X-Google-Smtp-Source: AGHT+IE+1hE1Q+/pQh+mW7/Ct4/eU4EaXfpxLHVjbsq6qa5H2UcdCaWDv6SmoJgr82fypqkELLhKzg== X-Received: by 2002:a05:6870:4591:b0:296:e698:3227 with SMTP id 586e51a60fabf-2e348846b40mr1366801fac.36.1747220313459; Wed, 14 May 2025 03:58:33 -0700 (PDT) Received: from my-computer.lan (c-73-76-29-249.hsd1.tx.comcast.net. [73.76.29.249]) by smtp.googlemail.com with ESMTPSA id 586e51a60fabf-2dba060be9esm2654535fac.10.2025.05.14.03.58.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 May 2025 03:58:32 -0700 (PDT) From: Andrew Ballance To: dakr@kernel.org, a.hindborg@kernel.org, airlied@gmail.com, akpm@linux-foundation.org, alex.gaynor@gmail.com, aliceryhl@google.com, andrewjballance@gmail.com, andriy.shevchenko@linux.intel.com, arnd@arndb.de, benno.lossin@proton.me, bhelgaas@google.com, bjorn3_gh@protonmail.com, boqun.feng@gmail.com, daniel.almeida@collabora.com, fujita.tomonori@gmail.com, gary@garyguo.net, gregkh@linuxfoundation.org, kwilczynski@kernel.org, me@kloenk.dev, ojeda@kernel.org, raag.jadav@intel.com, rafael@kernel.org, simona@ffwll.ch, tmgross@umich.edu Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org Subject: [PATCH v2 1/6] rust: helpers: io: use macro to generate io accessor functions Date: Wed, 14 May 2025 05:57:29 -0500 Message-ID: <20250514105734.3898411-2-andrewjballance@gmail.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250514105734.3898411-1-andrewjballance@gmail.com> References: <20250514105734.3898411-1-andrewjballance@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fiona Behrens Generate the `rust_helper_read{b,w,l,q}`, `rust_helper_write{b,w,l,q}` and the relaxed version using a C macro. This removes a lot of redundant code and is in preparation for pio functions which uses a similar C macro. Signed-off-by: Fiona Behrens Signed-off-by: Andrew Ballance --- rust/helpers/io.c | 105 +++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 76 deletions(-) diff --git a/rust/helpers/io.c b/rust/helpers/io.c index 15ea187c5466..d419b5b3b7c7 100644 --- a/rust/helpers/io.c +++ b/rust/helpers/io.c @@ -12,90 +12,43 @@ void rust_helper_iounmap(void __iomem *addr) iounmap(addr); } =20 -u8 rust_helper_readb(const void __iomem *addr) -{ - return readb(addr); -} - -u16 rust_helper_readw(const void __iomem *addr) -{ - return readw(addr); -} - -u32 rust_helper_readl(const void __iomem *addr) -{ - return readl(addr); -} - +#define define_rust_io_read_helper(rust_name, name, type) \ + type rust_name(void __iomem *addr) \ + { \ + return name(addr); \ + } + +#define define_rust_io_write_helper(rust_name, name, type) \ + void rust_name(type value, void __iomem *addr) \ + { \ + name(value, addr); \ + } + +define_rust_io_read_helper(rust_helper_readb, readb, u8); +define_rust_io_read_helper(rust_helper_readw, readw, u16); +define_rust_io_read_helper(rust_helper_readl, readl, u32); #ifdef CONFIG_64BIT -u64 rust_helper_readq(const void __iomem *addr) -{ - return readq(addr); -} +define_rust_io_read_helper(rust_helper_readq, readq, u64); #endif =20 -void rust_helper_writeb(u8 value, void __iomem *addr) -{ - writeb(value, addr); -} - -void rust_helper_writew(u16 value, void __iomem *addr) -{ - writew(value, addr); -} - -void rust_helper_writel(u32 value, void __iomem *addr) -{ - writel(value, addr); -} - +define_rust_io_write_helper(rust_helper_writeb, writeb, u8); +define_rust_io_write_helper(rust_helper_writew, writew, u16); +define_rust_io_write_helper(rust_helper_writel, writel, u32); #ifdef CONFIG_64BIT -void rust_helper_writeq(u64 value, void __iomem *addr) -{ - writeq(value, addr); -} +define_rust_io_write_helper(rust_helper_writeq, writeq, u64); #endif =20 -u8 rust_helper_readb_relaxed(const void __iomem *addr) -{ - return readb_relaxed(addr); -} - -u16 rust_helper_readw_relaxed(const void __iomem *addr) -{ - return readw_relaxed(addr); -} - -u32 rust_helper_readl_relaxed(const void __iomem *addr) -{ - return readl_relaxed(addr); -} - +define_rust_io_read_helper(rust_helper_readb_relaxed, readb_relaxed, u8); +define_rust_io_read_helper(rust_helper_readw_relaxed, readw_relaxed, u16); +define_rust_io_read_helper(rust_helper_readl_relaxed, readl_relaxed, u32); #ifdef CONFIG_64BIT -u64 rust_helper_readq_relaxed(const void __iomem *addr) -{ - return readq_relaxed(addr); -} +define_rust_io_read_helper(rust_helper_readq_relaxed, readq_relaxed, u64); #endif =20 -void rust_helper_writeb_relaxed(u8 value, void __iomem *addr) -{ - writeb_relaxed(value, addr); -} - -void rust_helper_writew_relaxed(u16 value, void __iomem *addr) -{ - writew_relaxed(value, addr); -} - -void rust_helper_writel_relaxed(u32 value, void __iomem *addr) -{ - writel_relaxed(value, addr); -} - +define_rust_io_write_helper(rust_helper_writeb_relaxed, writeb_relaxed, u8= ); +define_rust_io_write_helper(rust_helper_writew_relaxed, writew_relaxed, u1= 6); +define_rust_io_write_helper(rust_helper_writel_relaxed, writel_relaxed, u3= 2); #ifdef CONFIG_64BIT -void rust_helper_writeq_relaxed(u64 value, void __iomem *addr) -{ - writeq_relaxed(value, addr); -} +define_rust_io_write_helper(rust_helper_writeq_relaxed, writeq_relaxed, u6= 4); #endif + --=20 2.49.0 From nobody Sun Feb 8 09:16:57 2026 Received: from mail-oi1-f171.google.com (mail-oi1-f171.google.com [209.85.167.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F7432741CD; Wed, 14 May 2025 10:58:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220324; cv=none; b=BP52jiN1DGLhMNz/0//VTS/XNEav2PR2TsrRuXvj/OwjyukVVw3gSR2Mur1G9eNaeA2WUC9p2qppukPymBAktxXSqWjgzQow+6DgRgqW1jzPioWKMJ6kfoIW6v1S79iZ7q5iF0b7ZyL+mJGHOBVOS8KegBSNBPdr0EPpohRZ2e8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220324; c=relaxed/simple; bh=rcepHT66z2If6ZasfARNe8zaP0VPeFMjjDuPmLz7KBc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O81eKKSE6M/gohxnHePzhlAs5WU2OupPI9hZ91fnO3FHwt7RUlYOlXRDRbbNcWos67IjED6eMSHz47f1iGi0fAKrsokYkXdfftIBY5xynwA2LwX1UI3aeTjRm8YwhLIQP3goaLuXzVxj2WT8WK1VpbQryDLyugNfVtqPXy5EAfc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YK/RR5OJ; arc=none smtp.client-ip=209.85.167.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YK/RR5OJ" Received: by mail-oi1-f171.google.com with SMTP id 5614622812f47-3fa6c54cc1aso4435802b6e.1; Wed, 14 May 2025 03:58:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747220319; x=1747825119; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=L2YGwKqeTKSa1sCOAsRfi0xawxji0Kb2n2VWufPyqvc=; b=YK/RR5OJoC6zjlMAXUGyXhFEQBbPJYjimHHG3q9YliOjXx4f4rid/UpwgVn7/zpVI7 E6F0ijtahBx8n3vGcJHADf+CwdpRz0OLq9IQnabGnJxb3yaBwwXx0tJPfD/4EqQOThTq LgPjqqjI0j2tqrIF2TS6/0L4WZm7CUc6XurWprmok+cX5j5crpECJ2E1ph2LlViGudug Fr16HHqHF3qQkKCsZOq8JbMm5jXcjs87s4DmYkT6q5D8K0ig4z+AtNLegMqk/KDMsKIu OoZ1zmV+0LmoJoXh4wRs+l+m7Y4JiAL+99ZtMMSyAN4rathq6wZogwEXi5Su6GGPtn1i 2LKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747220319; x=1747825119; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=L2YGwKqeTKSa1sCOAsRfi0xawxji0Kb2n2VWufPyqvc=; b=rA8RigbFKR8ZUaA57Hlsd294WGToiHao8rygRZ+0VcLz2pROPTg1jMPVp8OzGpUx8d /LX0hDHdJOSU+7YsPUqOBvDuxmxMIzFbx6oAd3zhOyZeOEuxj9wByN4JQA3MCUPJEy8O oksv+C7WNl6bLrEAyviHftDymhlv/geav2bSq84XNYV3DVHwEng4BdAdGBPNSxePXW/1 sUiwhpTtJJL/F58PzPiaJMOyr5i9CgI/vyzzlsXHw/HIpKQdbupWlLxTljSJZoy3TxLz 75SJkVUcuNf9YRWPiuy+MNBQ8VvVecWAry8Z+LWdWabP0N7m8aFO2SOA0UAMCpIKaPAv Ol2g== X-Forwarded-Encrypted: i=1; AJvYcCVflvh38cbL3PcfF8830IAgUETBVKR96CotKwvlXk7YMqcnVuICT2+J1eKFBfupe3u3Cg9brlaSCEOCwByjnyc=@vger.kernel.org, AJvYcCXGDsaaLYx/eYhhSu7k+LdzO/nH5Y7qvHIWkCsSz++dsOgA/ggMViVY7K87+Y+YsDdyLSJ1/thtcOvk@vger.kernel.org, AJvYcCXhWijmhO81njWme1p4BU2HNUWN3rbXH+Z58iLMPyNFWYSK0O+71XcHFMu4M4RNkIVmiLc3mKqwnCDkTmI=@vger.kernel.org X-Gm-Message-State: AOJu0YxCCRA5dUmYC+V0oB1dg+CDj2O3Wmw2zywWQKnh0lU5S3McARM+ s/JVi2Bf3ns6NbKlkIQX6zqATLCWg3y5oqEgYT2pJr/3kLRf+yD+ X-Gm-Gg: ASbGncuDfH4E3eGnC/oSPx33F7qzNZULnHwP1ptTEKPwNIJ1q1E/rTgvNJVQwvT+A7u xo4p00SbHjntEmIOjmjH4in1o2CycbMbmPUbkoIIFwcK/c2JGcJsm4Ak5qM3Gi6y9gbBdm5xaY6 VLR4j2Ai/4+vOvKpm9sG/gmn1wVTTkSn8/aSbkLwDgB1rdocX03srDGK+M5zloUhBYaOj3kgGHJ lAORFAxW33aCmYjlIwt9BLTlH7oCSRobUja2jN5mYwik9c+4ltOYBNM1OpAdnXg8LUmKzPt9pGr 2hhmKrN3Cx+w4BRrxRCqrCz82JOL1tojIgiEVWKw3vp5iUQAj383twPmNzzqPqS/5ops+hQOQcj MEtXoMzgBB9stzOxdUmRndu0= X-Google-Smtp-Source: AGHT+IFIDv/Mb+Rtohkq/d/uAhGwS+ySqBGkomUOW9Wg//NzmgduJyMW2cnWhHvDAA3xrhuoO0IgrA== X-Received: by 2002:a05:6870:96a6:b0:29d:c832:7ef6 with SMTP id 586e51a60fabf-2e3488725c5mr1367585fac.39.1747220318966; Wed, 14 May 2025 03:58:38 -0700 (PDT) Received: from my-computer.lan (c-73-76-29-249.hsd1.tx.comcast.net. [73.76.29.249]) by smtp.googlemail.com with ESMTPSA id 586e51a60fabf-2dba060be9esm2654535fac.10.2025.05.14.03.58.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 May 2025 03:58:38 -0700 (PDT) From: Andrew Ballance To: dakr@kernel.org, a.hindborg@kernel.org, airlied@gmail.com, akpm@linux-foundation.org, alex.gaynor@gmail.com, aliceryhl@google.com, andrewjballance@gmail.com, andriy.shevchenko@linux.intel.com, arnd@arndb.de, benno.lossin@proton.me, bhelgaas@google.com, bjorn3_gh@protonmail.com, boqun.feng@gmail.com, daniel.almeida@collabora.com, fujita.tomonori@gmail.com, gary@garyguo.net, gregkh@linuxfoundation.org, kwilczynski@kernel.org, me@kloenk.dev, ojeda@kernel.org, raag.jadav@intel.com, rafael@kernel.org, simona@ffwll.ch, tmgross@umich.edu Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org Subject: [PATCH v2 2/6] rust: io: make Io use IoAccess trait Date: Wed, 14 May 2025 05:57:30 -0500 Message-ID: <20250514105734.3898411-3-andrewjballance@gmail.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250514105734.3898411-1-andrewjballance@gmail.com> References: <20250514105734.3898411-1-andrewjballance@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fiona Behrens makes the Io struct use the new traits (`IoAccess`, `IoAccess64`, `IoAccessRelaxed` and `IoAccess64Relaxed)` to perform io. This allows to later implement a generic Io framework. update pci,rust_driver_pci.rs, nova-core and a devres doc test to use the new io api. Signed-off-by: Fiona Behrens Co-developed-by: Andrew Ballance Signed-off-by: Andrew Ballance --- drivers/gpu/nova-core/regs.rs | 1 + rust/kernel/devres.rs | 4 +- rust/kernel/io.rs | 438 +++++++++++++++++++------------- rust/kernel/pci.rs | 2 +- samples/rust/rust_driver_pci.rs | 4 +- 5 files changed, 263 insertions(+), 186 deletions(-) diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index b1a25b86ef17..079c3d275a47 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 =20 use crate::driver::Bar0; +use kernel::io::IoAccess; =20 // TODO // diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index ddb1ce4a78d9..88d145821ca8 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -45,7 +45,7 @@ struct DevresInner { /// # Example /// /// ```no_run -/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{I= o, IoRaw}}; +/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{I= o, IoRaw, IoAccess}}; /// # use core::ops::Deref; /// /// // See also [`pci::Bar`] for a real example. @@ -80,7 +80,7 @@ struct DevresInner { /// /// fn deref(&self) -> &Self::Target { /// // SAFETY: The memory range stored in `self` has been properly= mapped in `Self::new`. -/// unsafe { Io::from_raw(&self.0) } +/// unsafe { Io::from_raw_ref(&self.0) } /// } /// } /// # fn no_run() -> Result<(), Error> { diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 72d80a6f131e..368167d57863 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -7,6 +7,210 @@ use crate::error::{code::EINVAL, Result}; use crate::{bindings, build_assert}; =20 +/// Private macro to define the [`IoAccess`] functions. +macro_rules! define_io_access_function { + (@read_derived $(#[$attr:meta])* $name_unchecked:ident, $vis:vis $name= :ident, $try_vis:vis $try_name:ident, $type_name:ty) =3D> { + /// Read data from a given offset known at compile time. + /// + /// Bound checks are perfomed on compile time, hence if the offset is = not known at compile + /// time, the build will fail. + $(#[$attr])* + #[inline] + $vis fn $name(&self, offset: usize) -> $type_name { + build_assert!(offset_valid::<$type_name>(offset, SIZE)); + + // SAFETY: offset checked to be valid above. + unsafe { self.$name_unchecked(offset) } + } + + /// Read data from a given offset. + /// + /// Bound checks are performed at runtime, it fails if the offset (plu= s type size) is + /// out of bounds. + $(#[$attr])* + #[inline] + $try_vis fn $try_name(&self, offset: usize) -> Result<$type_name> { + if !(offset_valid::<$type_name>(offset, self.maxsize())) { + return Err(EINVAL); + } + + // SAFETY: offset checked to be valid above. + Ok(unsafe { self.$name_unchecked(offset) }) + } + }; + (@read $(#[$attr:meta])* $name_unchecked:ident, $name:ident, $try_name= :ident, $type_name:ty) =3D> { + /// Read data from a given offset without doing any bound checks. + /// The offset is relative to the base address of Self. + /// + /// # Safety + /// + /// The offset has to be valid for self. + $(#[$attr])* + unsafe fn $name_unchecked(&self, offset: usize) -> $type_name; + + define_io_access_function!(@read_derived $(#[$attr])* $name_unchecked,= $name, $try_name, $type_name); + }; + (@read $($(#[$attr:meta])* $name_unchecked:ident, $name:ident, $try_na= me:ident, $type_name:ty;)+) =3D> { + $( + define_io_access_function!(@read $(#[$attr])* $name_unchecked, $na= me, $try_name, $type_name); + )* + }; + (@write_derived $(#[$attr:meta])* $name_unchecked:ident, $vis:vis $nam= e:ident, $try_vis:vis $try_name:ident, $type_name:ty) =3D> { + /// Write data to a given offset known at compile time. + /// Bound checks are performed at compile time, hence if the offset is= not known at compile + /// time, the build will fail. + $(#[$attr])* + #[inline] + $vis fn $name(&self, value: $type_name, offset: usize) { + build_assert!(offset_valid::<$type_name>(offset, SIZE)); + + // SAFETY: offset checked to be valid above. + unsafe { self.$name_unchecked(value, offset) } + } + + /// Write data to a given offset. + /// + /// Bound checks are performed at runtime, it fails if the offset (plu= s the type size) is + /// out of bounds. + $(#[$attr])* + #[inline] + $try_vis fn $try_name(&self, value: $type_name, offset: usize) -> Resu= lt { + if !(offset_valid::<$type_name>(offset, self.maxsize())) { + return Err(EINVAL); + } + + // SAFETY: offset checked to be valid above. + Ok(unsafe { self.$name_unchecked(value, offset) }) + } + }; + (@write $(#[$attr:meta])* $name_unchecked:ident, $name:ident, $try_nam= e:ident, $type_name:ty) =3D> { + /// Write data to a given offset without doing any bound checks. + /// The offset is relative to the base address of self. + /// + /// # Safety + /// + /// The offset has to be valid for Self. + $(#[$attr])* + unsafe fn $name_unchecked(&self, value: $type_name, offset: usize); + + define_io_access_function!(@write_derived $(#[$attr])* $name_unchecked= , $name, $try_name, $type_name); + }; + (@write $($(#[$attr:meta])* $name_unchecked:ident, $name:ident, $try_n= ame:ident, $type_name:ty;)+) =3D> { + $( + define_io_access_function!(@write $(#[$attr])* $name_unchecked, $n= ame, $try_name, $type_name); + )* + }; +} + +/// Private macro to generate accessor functions that call the correct C f= unctions given as `fn_c`. +/// +/// This takes either `@read` or `@write` to generate a single read or wri= te accessor function. +/// +/// This also can take a list of read write pairs to generate both at the = same time. +macro_rules! impl_accessor_fn { + (@read $(#[$attr:meta])* $vis:vis $fn_rust:ident, $fn_c:ident, $type_n= ame:ty) =3D> { + $(#[$attr])* + $vis unsafe fn $fn_rust(&self, offset: usize) -> $type_name { + // SAFETY: by the safety requirement of the function `self.addr() = + offset` is valid to read + // TODO: once MSRV is >=3D 1.79.0 replace `+` with `unchecked_add` + unsafe { bindings::$fn_c((self.addr() + offset) as _) as _ } + } + }; + (@write $(#[$attr:meta])* $vis:vis $fn_rust:ident, $fn_c:ident, $type_= name:ty) =3D> { + $(#[$attr])* + $vis unsafe fn $fn_rust(&self, value: $type_name, offset: usize) { + // SAFETY: + // by the safety requirement of the function `self.addr() + offset= ` is valid to write + // TODO: once MSRV is >=3D 1.79.0 replace `+` with `unchecked_add` + unsafe { bindings::$fn_c(value, (self.addr() + offset) as _) as _ } + } + }; + ( + $( + $(#[$attr:meta])* + $vis_read:vis $fn_rust_read:ident, $fn_c_read:ident, + $vis_write:vis $fn_rust_write:ident, $fn_c_write:ident, + $type_name:ty $(;)? + )+ + ) =3D> { + $( + impl_accessor_fn!(@read $(#[$attr])* $vis_read $fn_rust_read, $fn_= c_read, $type_name); + impl_accessor_fn!(@write $(#[$attr])* $vis_write $fn_rust_write, $= fn_c_write, $type_name); + )+ + }; +} + +/// Check if the offset is valid to still support the type U in the given = size +const fn offset_valid(offset: usize, size: usize) -> bool { + let type_size =3D core::mem::size_of::(); + if let Some(end) =3D offset.checked_add(type_size) { + end <=3D size && offset % type_size =3D=3D 0 + } else { + false + } +} + +/// Io Access functions. +/// +/// # Safety +/// +/// `SIZE` and `maxsize()` has to always be valid to add to the base addre= ss. +pub unsafe trait IoAccess { + /// Returns the maximum size of the accessed IO area. + fn maxsize(&self) -> usize; + + /// Returns the base address of the accessed IO area. + fn addr(&self) -> usize; + + define_io_access_function!(@read + read8_unchecked, read8, try_read8, u8; + read16_unchecked, read16, try_read16, u16; + read32_unchecked, read32, try_read32, u32; + ); + + define_io_access_function!(@write + write8_unchecked, write8, try_write8, u8; + write16_unchecked, write16, try_write16, u16; + write32_unchecked, write32, try_write32, u32; + ); +} + +/// Extending trait of [`IoAccess`] offering 64 bit functions. +#[cfg(CONFIG_64BIT)] +pub trait IoAccess64: IoAccess { + define_io_access_function!(@read read64_unchecked, read64, try_read64,= u64); + define_io_access_function!(@write write64_unchecked, write64, try_writ= e64, u64); +} + +/// Io Relaxed Access functions. +/// +/// Similar to [`IoAccess`] but using relaxed memory boundries. +pub trait IoAccessRelaxed: IoAccess { + define_io_access_function!(@read + read8_relaxed_unchecked, read8_relaxed, try_read8_relaxed, u8; + read16_relaxed_unchecked, read16_relaxed, try_read16_relaxed, u16; + read32_relaxed_unchecked, read32_relaxed, try_read32_relaxed, u32; + ); + + define_io_access_function!(@write + write8_relaxed_unchecked, write8_relaxed, try_write8_relaxed, u8; + write16_relaxed_unchecked, write16_relaxed, try_write16_relaxed, u= 16; + write32_relaxed_unchecked, write32_relaxed, try_write32_relaxed, u= 32; + ); +} + +/// Extending trait of [`IoAccessRelaxed`] offering 64 bit functions. +#[cfg(CONFIG_64BIT)] +pub trait IoAccess64Relaxed: IoAccess { + define_io_access_function!(@read + read64_relaxed_unchecked, read64_relaxed, try_read64_relaxed, u64; + ); + + define_io_access_function!(@write + write64_relaxed_unchecked, write64_relaxed, try_write64_relaxed, u= 64; + ); +} + /// Raw representation of an MMIO region. /// /// By itself, the existence of an instance of this structure does not pro= vide any guarantees that @@ -43,218 +247,88 @@ pub fn maxsize(&self) -> usize { } } =20 -/// IO-mapped memory, starting at the base address @addr and spanning @max= len bytes. +/// IO-mapped memory, starting at the base address [`addr`] and spanning [= `maxsize`] bytes. /// /// The creator (usually a subsystem / bus such as PCI) is responsible for= creating the -/// mapping, performing an additional region request etc. -/// -/// # Invariant -/// -/// `addr` is the start and `maxsize` the length of valid I/O mapped memor= y region of size -/// `maxsize`. -/// -/// # Examples -/// -/// ```no_run -/// # use kernel::{bindings, io::{Io, IoRaw}}; -/// # use core::ops::Deref; +/// mapping, performing an additional region request, etc. /// -/// // See also [`pci::Bar`] for a real example. -/// struct IoMem(IoRaw); +/// # Invariants /// -/// impl IoMem { -/// /// # Safety -/// /// -/// /// [`paddr`, `paddr` + `SIZE`) must be a valid MMIO region that i= s mappable into the CPUs -/// /// virtual address space. -/// unsafe fn new(paddr: usize) -> Result{ -/// // SAFETY: By the safety requirements of this function [`paddr= `, `paddr` + `SIZE`) is -/// // valid for `ioremap`. -/// let addr =3D unsafe { bindings::ioremap(paddr as _, SIZE as _)= }; -/// if addr.is_null() { -/// return Err(ENOMEM); -/// } +/// [`addr`] is the start and [`maxsize`] the length of valid I/O mapped m= emory region of +/// size [`maxsize`]. /// -/// Ok(IoMem(IoRaw::new(addr as _, SIZE)?)) -/// } -/// } +/// [`addr`] is valid to access with the C [`read`]/[`write`] family of fu= nctions. /// -/// impl Drop for IoMem { -/// fn drop(&mut self) { -/// // SAFETY: `self.0.addr()` is guaranteed to be properly mapped= by `Self::new`. -/// unsafe { bindings::iounmap(self.0.addr() as _); }; -/// } -/// } -/// -/// impl Deref for IoMem { -/// type Target =3D Io; -/// -/// fn deref(&self) -> &Self::Target { -/// // SAFETY: The memory range stored in `self` has been properly= mapped in `Self::new`. -/// unsafe { Io::from_raw(&self.0) } -/// } -/// } -/// -///# fn no_run() -> Result<(), Error> { -/// // SAFETY: Invalid usage for example purposes. -/// let iomem =3D unsafe { IoMem::<{ core::mem::size_of::() }>::new(0= xBAAAAAAD)? }; -/// iomem.write32(0x42, 0x0); -/// assert!(iomem.try_write32(0x42, 0x0).is_ok()); -/// assert!(iomem.try_write32(0x42, 0x4).is_err()); -/// # Ok(()) -/// # } -/// ``` +/// [`addr`]: IoAccess::addr +/// [`maxsize`]: IoAccess::maxsize +/// [`read`]: https://docs.kernel.org/driver-api/device-io.html#difference= s-between-i-o-access-functions +/// [`write`]: https://docs.kernel.org/driver-api/device-io.html#differenc= es-between-i-o-access-functions #[repr(transparent)] pub struct Io(IoRaw); =20 -macro_rules! define_read { - ($(#[$attr:meta])* $name:ident, $try_name:ident, $c_fn:ident -> $type_= name:ty) =3D> { - /// Read IO data from a given offset known at compile time. - /// - /// Bound checks are performed on compile time, hence if the offse= t is not known at compile - /// time, the build will fail. - $(#[$attr])* - #[inline] - pub fn $name(&self, offset: usize) -> $type_name { - let addr =3D self.io_addr_assert::<$type_name>(offset); - - // SAFETY: By the type invariant `addr` is a valid address for= MMIO operations. - unsafe { bindings::$c_fn(addr as _) } - } - - /// Read IO data from a given offset. - /// - /// Bound checks are performed on runtime, it fails if the offset = (plus the type size) is - /// out of bounds. - $(#[$attr])* - pub fn $try_name(&self, offset: usize) -> Result<$type_name> { - let addr =3D self.io_addr::<$type_name>(offset)?; - - // SAFETY: By the type invariant `addr` is a valid address for= MMIO operations. - Ok(unsafe { bindings::$c_fn(addr as _) }) - } - }; -} - -macro_rules! define_write { - ($(#[$attr:meta])* $name:ident, $try_name:ident, $c_fn:ident <- $type_= name:ty) =3D> { - /// Write IO data from a given offset known at compile time. - /// - /// Bound checks are performed on compile time, hence if the offse= t is not known at compile - /// time, the build will fail. - $(#[$attr])* - #[inline] - pub fn $name(&self, value: $type_name, offset: usize) { - let addr =3D self.io_addr_assert::<$type_name>(offset); - - // SAFETY: By the type invariant `addr` is a valid address for= MMIO operations. - unsafe { bindings::$c_fn(value, addr as _, ) } - } - - /// Write IO data from a given offset. - /// - /// Bound checks are performed on runtime, it fails if the offset = (plus the type size) is - /// out of bounds. - $(#[$attr])* - pub fn $try_name(&self, value: $type_name, offset: usize) -> Resul= t { - let addr =3D self.io_addr::<$type_name>(offset)?; - - // SAFETY: By the type invariant `addr` is a valid address for= MMIO operations. - unsafe { bindings::$c_fn(value, addr as _) } - Ok(()) - } - }; -} - impl Io { - /// Converts an `IoRaw` into an `Io` instance, providing the accessors= to the MMIO mapping. + /// Convert a [`IoRaw`] into an [`MMIo`] instance, providing the acces= sors to the MMIO mapping. /// /// # Safety /// - /// Callers must ensure that `addr` is the start of a valid I/O mapped= memory region of size - /// `maxsize`. - pub unsafe fn from_raw(raw: &IoRaw) -> &Self { - // SAFETY: `Io` is a transparent wrapper around `IoRaw`. - unsafe { &*core::ptr::from_ref(raw).cast() } - } - - /// Returns the base address of this mapping. + /// Callers must ensure that `addr` is the start of a valid I/O mapped= memory region of + /// size `maxsize`. #[inline] - pub fn addr(&self) -> usize { - self.0.addr() - } - - /// Returns the maximum size of this mapping. - #[inline] - pub fn maxsize(&self) -> usize { - self.0.maxsize() + pub unsafe fn from_raw(raw: IoRaw) -> Self { + Self(raw) } =20 + /// Convert a ref to [`IoRaw`] into an [`MMIo`] instance, providing th= e accessors to the + /// MMIo mapping. + /// + /// # Safety + /// + /// Callers must ensure that `addr` is the start of a valid I/O mapped= memory region of + /// size `maxsize`. #[inline] - const fn offset_valid(offset: usize, size: usize) -> bool { - let type_size =3D core::mem::size_of::(); - if let Some(end) =3D offset.checked_add(type_size) { - end <=3D size && offset % type_size =3D=3D 0 - } else { - false - } + pub unsafe fn from_raw_ref(raw: &IoRaw) -> &Self { + // SAFETY: `MMIo` is a transparent wrapper around `IoRaw`. + unsafe { &*core::ptr::from_ref(raw).cast() } } +} =20 +// SAFETY: as per invariant `raw` is valid +unsafe impl IoAccess for Io { #[inline] - fn io_addr(&self, offset: usize) -> Result { - if !Self::offset_valid::(offset, self.maxsize()) { - return Err(EINVAL); - } - - // Probably no need to check, since the safety requirements of `Se= lf::new` guarantee that - // this can't overflow. - self.addr().checked_add(offset).ok_or(EINVAL) + fn maxsize(&self) -> usize { + self.0.maxsize() } =20 #[inline] - fn io_addr_assert(&self, offset: usize) -> usize { - build_assert!(Self::offset_valid::(offset, SIZE)); - - self.addr() + offset + fn addr(&self) -> usize { + self.0.addr() } =20 - define_read!(read8, try_read8, readb -> u8); - define_read!(read16, try_read16, readw -> u16); - define_read!(read32, try_read32, readl -> u32); - define_read!( - #[cfg(CONFIG_64BIT)] - read64, - try_read64, - readq -> u64 + impl_accessor_fn!( + read8_unchecked, readb, write8_unchecked, writeb, u8; + read16_unchecked, readw, write16_unchecked, writew, u16; + read32_unchecked, readl, write32_unchecked, writel, u32; ); +} =20 - define_read!(read8_relaxed, try_read8_relaxed, readb_relaxed -> u8); - define_read!(read16_relaxed, try_read16_relaxed, readw_relaxed -> u16); - define_read!(read32_relaxed, try_read32_relaxed, readl_relaxed -> u32); - define_read!( - #[cfg(CONFIG_64BIT)] - read64_relaxed, - try_read64_relaxed, - readq_relaxed -> u64 +#[cfg(CONFIG_64BIT)] +impl IoAccess64 for Io { + impl_accessor_fn!( + read64_unchecked, readq, write64_unchecked, writeq, u64; ); +} =20 - define_write!(write8, try_write8, writeb <- u8); - define_write!(write16, try_write16, writew <- u16); - define_write!(write32, try_write32, writel <- u32); - define_write!( - #[cfg(CONFIG_64BIT)] - write64, - try_write64, - writeq <- u64 +impl IoAccessRelaxed for Io { + impl_accessor_fn!( + read8_relaxed_unchecked, readb_relaxed, write8_relaxed_unchecked, = writeb_relaxed, u8; + read16_relaxed_unchecked, readw_relaxed, write16_relaxed_unchecked= , writew_relaxed, u16; + read32_relaxed_unchecked, readl_relaxed, write32_relaxed_unchecked= , writel_relaxed, u32; ); +} =20 - define_write!(write8_relaxed, try_write8_relaxed, writeb_relaxed <- u8= ); - define_write!(write16_relaxed, try_write16_relaxed, writew_relaxed <- = u16); - define_write!(write32_relaxed, try_write32_relaxed, writel_relaxed <- = u32); - define_write!( - #[cfg(CONFIG_64BIT)] - write64_relaxed, - try_write64_relaxed, - writeq_relaxed <- u64 +#[cfg(CONFIG_64BIT)] +impl IoAccess64Relaxed for Io { + impl_accessor_fn!( + read64_relaxed_unchecked, readq_relaxed, write64_relaxed_unchecked= , writeq_relaxed, u64; ); } diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index c97d6d470b28..9f5ca22d327a 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -356,7 +356,7 @@ impl Deref for Bar { =20 fn deref(&self) -> &Self::Target { // SAFETY: By the type invariant of `Self`, the MMIO range in `sel= f.io` is properly mapped. - unsafe { Io::from_raw(&self.io) } + unsafe { Io::from_raw_ref(&self.io) } } } =20 diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 2bb260aebc9e..a8d292f4c1b3 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -4,7 +4,9 @@ //! //! To make this driver probe, QEMU must be run with `-device pci-testdev`. =20 -use kernel::{bindings, c_str, device::Core, devres::Devres, pci, prelude::= *, types::ARef}; +use kernel::{ + bindings, c_str, device::Core, devres::Devres, io::IoAccess, pci, prel= ude::*, types::ARef, +}; =20 struct Regs; =20 --=20 2.49.0 From nobody Sun Feb 8 09:16:57 2026 Received: from mail-oi1-f170.google.com (mail-oi1-f170.google.com [209.85.167.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 379BC274653; Wed, 14 May 2025 10:58:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220326; cv=none; b=I7d5qc46mi78Zn4k02o2eTFmKFD+qXQUyT/9+tSlVrSqjpW8dI19hgWrxANVGhgimFYTR6gxOmZwNQnQ4eNR6tFIUNUBu6uZkMzoMBX7ka4AQcD4yYvRl+eSown2FntCORWAD36tuAhk0zyeaZJH+IFEX3LmANTKsGbzwXcwXWw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220326; c=relaxed/simple; bh=jBgr148jVjpuH58QBz4LCDpFD8RJBQ4LvEXTuUaGFZA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lgTS8gQZcVZsBmOzPe83XPLQX8SQrbT2fpVCi17nn/olDyCO/dMtMllTaasMfWx8pp2V953PPRomJjU9wTI/1w9iCa3jGZUa+ROF+EkgFYMQiKMt+nRgsaIF66Zqu/RP2qZ5xphOG68TItMFKk5xKmaYE8DrTKq90KXKdgDBTeQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IoeNiWFZ; arc=none smtp.client-ip=209.85.167.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IoeNiWFZ" Received: by mail-oi1-f170.google.com with SMTP id 5614622812f47-3fa6c54cdb2so5612884b6e.3; Wed, 14 May 2025 03:58:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747220324; x=1747825124; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Hu8TOexpRWewY07dDXJsWt38JoGIzWPjMFqMEoSL2F8=; b=IoeNiWFZeEgh+MGNph0GV7QEHVLZGJbXsY/XR6i5r9C9+XnrSlz1XVGsFvsw3XLMf+ NeUj1OxiKgTs6zbg/0mxDOwMSeMy9GkpDye/fk9AsUdm1Mfk4t5fOMDe+CSk6fOizEI1 pZZPcGqIRTP4MZv15G65ahV3mhH4Qf6Z6mfkBYFEeGp0yHO2XM69Qr9gImO7yjAy6ONr EqawbKlgzbFOGSKWtlJLJxgErQOzUWYWNBD3jGrOFkkfZBnZCWQkS80Zv9LseT3hOQtE ErFzZHPL3CWK1ikA0QDcXla1MxuQtMRV+TMNLCQWjDYITHtiSsVq1AQ0UNomwepgb0GP tf3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747220324; x=1747825124; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Hu8TOexpRWewY07dDXJsWt38JoGIzWPjMFqMEoSL2F8=; b=MoNHz9UAhmAIOeEZGNj1Z17jjQNvy/jnKo2FOq0IFXv/guFhb8U2yJwQ58AzksaoCA kKysDxcgnKo1eTtZzJ8MiOA44JLQxUNm67tHq7RGRwPFDfijut0gWgfPgzOQX2yVLMPV jXe8wBv/GO6OnCX9loSBS+GFHrIKtZyfKA5YbI3zPGP3TXsXA+1fh3gVb2QMaBqKQWt7 iRstyARXGJjDoje2rWEE1XrvU97dxMzi5lHMF98XfzI5Wzij+GGq0eIzTGrwurAiHjc1 dlt0+eVGBiWhF8uW85A4WW6wgJEXip0QS7rJCnYa9DL6nksFAJRLnYvFd0UcE4yphiTt m4oA== X-Forwarded-Encrypted: i=1; AJvYcCX+9TykxuAAs5yG0h6CWfSUaIv+eux3rjskz81c4EdRKHyuZXteVY4ebRA85R7I2lzWq8+lsb89YKubm2U=@vger.kernel.org, AJvYcCXEWuSuCZOe91cPHiaR/PXKero+7uEyUOW12jVCRsTdQhi+k55O27ik+t4mZXnjCPP9fhtsL8tl6nbj@vger.kernel.org, AJvYcCXJX71H/vE4gl50SVis7u7IvZNP26aQ2jIWAQvZ/fA1wV0WaSHJWcpKNVOn+Td7yLvUFCpN7Q+ORKqsPcVn0oE=@vger.kernel.org X-Gm-Message-State: AOJu0YxHGQ/1Z0AAjdCKI1rWcUTIFya7uYcVwwFoooCYD+SeTwMJY5TG WY2W2UXa8ZVa1pzbaQ0gHmu4j5PKN4kPLeZ8VBF+esaJiZuBEaak X-Gm-Gg: ASbGnct20RK0odA25lyW5EdIskSwaLjT96QUnygcCLUBbvAb2yqAllPBet08tI9lXCU At3M22GP9bK2qgB3nc8AohsCZr0KXKFBgZO4WSSdD/xHdGUfIMAg5FFzKHEAEIczwYrAPvQbUWt 8qnt6FypCOIPWx3k/PpcRhiVLffZU1RJTgH4inRNe1rxhuDrrbRxbnV8wACW6RpMUkUVvpWKsCq 6kYny0uIQilORhtXAfLYysELJhmbEcKDX2paKanTyfCO6cSaozbeByX+LQ/el14QVckKsP5I/Gz IXcUzTmEM7y/nPgFd9Gt9si4PekOOgrYwb4Q/gSLxvlnecxpI+t+mIvFHm1crcxNXsFSdbaAbvU V+6Y5WThUxy+RrNVFniehwRk= X-Google-Smtp-Source: AGHT+IGXkVccnY53tGuxSpCAUCholjM/YozYw8rMeLEOV6h73hwItyLwj6abwZHjjSwc7RwgLDceeg== X-Received: by 2002:a05:6870:b022:b0:2e0:15a3:3b0f with SMTP id 586e51a60fabf-2e348815239mr1434508fac.31.1747220324164; Wed, 14 May 2025 03:58:44 -0700 (PDT) Received: from my-computer.lan (c-73-76-29-249.hsd1.tx.comcast.net. [73.76.29.249]) by smtp.googlemail.com with ESMTPSA id 586e51a60fabf-2dba060be9esm2654535fac.10.2025.05.14.03.58.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 May 2025 03:58:43 -0700 (PDT) From: Andrew Ballance To: dakr@kernel.org, a.hindborg@kernel.org, airlied@gmail.com, akpm@linux-foundation.org, alex.gaynor@gmail.com, aliceryhl@google.com, andrewjballance@gmail.com, andriy.shevchenko@linux.intel.com, arnd@arndb.de, benno.lossin@proton.me, bhelgaas@google.com, bjorn3_gh@protonmail.com, boqun.feng@gmail.com, daniel.almeida@collabora.com, fujita.tomonori@gmail.com, gary@garyguo.net, gregkh@linuxfoundation.org, kwilczynski@kernel.org, me@kloenk.dev, ojeda@kernel.org, raag.jadav@intel.com, rafael@kernel.org, simona@ffwll.ch, tmgross@umich.edu Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org Subject: [PATCH v2 3/6] rust: io: add new Io type Date: Wed, 14 May 2025 05:57:31 -0500 Message-ID: <20250514105734.3898411-4-andrewjballance@gmail.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250514105734.3898411-1-andrewjballance@gmail.com> References: <20250514105734.3898411-1-andrewjballance@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" adds a new Io type that uses the C ioread/iowrite family of functions and implements the IoAccess trait for it and renames the old `Io` to `MMIo`. Signed-off-by: Andrew Ballance --- rust/helpers/io.c | 7 ++++ rust/kernel/io.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/rust/helpers/io.c b/rust/helpers/io.c index d419b5b3b7c7..a138914523c8 100644 --- a/rust/helpers/io.c +++ b/rust/helpers/io.c @@ -52,3 +52,10 @@ define_rust_io_write_helper(rust_helper_writel_relaxed, = writel_relaxed, u32); define_rust_io_write_helper(rust_helper_writeq_relaxed, writeq_relaxed, u6= 4); #endif =20 +define_rust_io_read_helper(rust_helper_ioread8, ioread8, u8); +define_rust_io_read_helper(rust_helper_ioread16, ioread16, u16); +define_rust_io_read_helper(rust_helper_ioread32, ioread32, u32); + +define_rust_io_write_helper(rust_helper_iowrite8, iowrite8, u8); +define_rust_io_write_helper(rust_helper_iowrite16, iowrite16, u16); +define_rust_io_write_helper(rust_helper_iowrite32, iowrite32, u32); diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 368167d57863..ce044c155b16 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -264,9 +264,9 @@ pub fn maxsize(&self) -> usize { /// [`read`]: https://docs.kernel.org/driver-api/device-io.html#difference= s-between-i-o-access-functions /// [`write`]: https://docs.kernel.org/driver-api/device-io.html#differenc= es-between-i-o-access-functions #[repr(transparent)] -pub struct Io(IoRaw); +pub struct MMIo(IoRaw); =20 -impl Io { +impl MMIo { /// Convert a [`IoRaw`] into an [`MMIo`] instance, providing the acces= sors to the MMIO mapping. /// /// # Safety @@ -293,7 +293,7 @@ pub unsafe fn from_raw_ref(raw: &IoRaw) -> &Self { } =20 // SAFETY: as per invariant `raw` is valid -unsafe impl IoAccess for Io { +unsafe impl IoAccess for MMIo { #[inline] fn maxsize(&self) -> usize { self.0.maxsize() @@ -312,13 +312,13 @@ fn addr(&self) -> usize { } =20 #[cfg(CONFIG_64BIT)] -impl IoAccess64 for Io { +impl IoAccess64 for MMIo { impl_accessor_fn!( read64_unchecked, readq, write64_unchecked, writeq, u64; ); } =20 -impl IoAccessRelaxed for Io { +impl IoAccessRelaxed for MMIo { impl_accessor_fn!( read8_relaxed_unchecked, readb_relaxed, write8_relaxed_unchecked, = writeb_relaxed, u8; read16_relaxed_unchecked, readw_relaxed, write16_relaxed_unchecked= , writew_relaxed, u16; @@ -327,8 +327,93 @@ impl IoAccessRelaxed for Io { } =20 #[cfg(CONFIG_64BIT)] -impl IoAccess64Relaxed for Io { +impl IoAccess64Relaxed for MMIo { impl_accessor_fn!( read64_relaxed_unchecked, readq_relaxed, write64_relaxed_unchecked= , writeq_relaxed, u64; ); } + +/// Io that can be either PortIo or MMIo, +/// starting at the base address [`addr`] and spanning [`maxsize`] bytes. +/// +/// The creator (usually a subsystem / bus such as PCI) is responsible for= creating the +/// mapping, performing an additional region request, etc. +/// +/// # Invariants +/// +/// [`addr`] is the start and [`maxsize`] the length of a valid io region = of size [`maxsize`]. +/// +/// [`addr`] is valid to access with the C [`ioread`]/[`iowrite`] family o= f functions. +/// +/// [`addr`]: IoAccess::addr +/// [`maxsize`]: IoAccess::maxsize +/// [`ioread`]: https://docs.kernel.org/driver-api/device-io.html#differen= ces-between-i-o-access-functions +/// [`iowrite`]: https://docs.kernel.org/driver-api/device-io.html#differe= nces-between-i-o-access-functions +#[repr(transparent)] +pub struct Io(IoRaw); + +impl Io { + /// Convert a [`IoRaw`] into an [`Io`] instance, providing the accesso= rs to the + /// Io mapping. + /// + /// # Safety + /// + /// Callers must ensure that `addr` is the start of a valid I/O region= of size `maxsize`. + /// + /// ``` + /// use kernel::io::{IoRaw, Io, IoAccess}; + /// + /// let raw =3D IoRaw::<2>::new(0xDEADBEEFC0DE, 2).unwrap(); + /// // SAFETY: test, value is not actually written to. + /// let io: Io<2> =3D unsafe { Io::from_raw(raw) }; + /// # assert_eq!(0xDEADBEEFC0DE, io.addr()); + /// # assert_eq!(2, io.maxsize()); + /// ``` + pub unsafe fn from_raw(raw: IoRaw) -> Self { + Self(raw) + } + + /// Convert a ref to [`IoRaw`] into an [`Io`] instance, providing the = accessors to + /// the Io mapping. + /// + /// # Safety + /// + /// Callers must ensure that `addr` is the start of a valid I/O mapped= memory region of + /// size `maxsize`. + /// + /// # Examples + /// + /// ``` + /// use kernel::io::{IoRaw, Io, IoAccess}; + /// + /// let raw =3D IoRaw::<2>::new(0xDEADBEEFC0DE, 2).unwrap(); + /// // SAFETY: test, value is not actually written to. + /// let io: &Io<2> =3D unsafe { Io::from_raw_ref(&raw) }; + /// # assert_eq!(raw.addr(), io.addr()); + /// # assert_eq!(raw.maxsize(), io.maxsize()); + /// ``` + #[inline] + pub unsafe fn from_raw_ref(raw: &IoRaw) -> &Self { + // SAFETY: `Io` is a transparent wrapper around `IoRaw`. + unsafe { &*core::ptr::from_ref(raw).cast() } + } +} + +// SAFETY: as per invariant `raw` is valid +unsafe impl IoAccess for Io { + #[inline] + fn addr(&self) -> usize { + self.0.addr() + } + + #[inline] + fn maxsize(&self) -> usize { + self.0.maxsize() + } + + impl_accessor_fn!( + read8_unchecked, ioread8, write8_unchecked, iowrite8, u8; + read16_unchecked, ioread16, write16_unchecked, iowrite16, u16; + read32_unchecked, ioread32, write32_unchecked, iowrite32, u32; + ); +} --=20 2.49.0 From nobody Sun Feb 8 09:16:57 2026 Received: from mail-oo1-f42.google.com (mail-oo1-f42.google.com [209.85.161.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F2D18276037; Wed, 14 May 2025 10:58:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220331; cv=none; b=MQCSlGG4F4o9kxmzWNhipfcdBxH/cUFZjXB27Xf/Ubu7DBDjptykkYfd8JiYa6esedGNQvun6QabX2KcOibPGRdwwbB8EqICGdTbmsQpMdyKM/E6IsLABW8UzU/VT1n87n4Df8BMt6TJVQiD/YYBcStbqpn1CHOjuE0SbOaP/E8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220331; c=relaxed/simple; bh=us24YMHGRBi3hbg2xCpl1Wl1HHgJcRn3NEPuZn3iX2g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KvtCYwjsfpJuPe7twiW7csMLxwwsC8q1wL8ktuujRjdrDkoyZ1BEfSKZhocFPzv4l2fNQQZkBMFBhOTw0r2BMnpDpCJEpMyesG4lrsBCXD/BdrDJCT5gt52maf0a9gqTvlsCzuH3vkrUNAkEH2ZMeto2QYUMbjUEu8M4puuLIuk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=c43CIYPx; arc=none smtp.client-ip=209.85.161.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="c43CIYPx" Received: by mail-oo1-f42.google.com with SMTP id 006d021491bc7-601b6146b9cso3309795eaf.0; Wed, 14 May 2025 03:58:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747220329; x=1747825129; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VovI2MJA5yrsgZVuWzhEGgze0o42B0tngXC0Xns04F8=; b=c43CIYPxfJCcIX6eQF9XANR3MTlH9zKw8NcRI6XCvCgknuVF7xoPZUsYbsq1nZJs6y l7Ai1IifHm91MCEnR+OkeR7ErWgq9pgr+Z8Bltg12SPVUBatIyCbv9jrkl/T0IFTR1Pd X+292gehftco2yMYCKfBHJLYAogA45/tZU0ZD27YojUA501JtPq12DprK7/ZLdb1GIST waRi+lHvF+hZsdDXWK83mOID1ITxgdqnbybZzFlHSHMjbwpXwVrQSLSMbJ1yKwyqn40K cSTd2CDcIJCisEerxmfZawy/BAdF39JEGsRkAzMRukAu6IiAWXF/Tkpw0dn2MWBGoyTD jYZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747220329; x=1747825129; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VovI2MJA5yrsgZVuWzhEGgze0o42B0tngXC0Xns04F8=; b=hLm961nelIEsZds+GDJRkbAAItf7BUNZtC7MpOTopuWF4SxJwm4RXCa1pNHD9U/i0q 8IRcSeS0HHaAB6IMXBgml9pCYLVD+oksX6Zpu67fK6DTrDl7obwVGsXveLM5ypcGlSxM vjjuawzhXZoivXfZT4UZ76aTULlUVHRYljWIX5bp/3QRrVLm3cBNdlStLLoq/pzD7gWJ VTbymecVym5ZwbO8M8T/cyXrJEfk5fVVgIUh97RP2NqOjjWKtFbS4VA14QHgXdnXtV3l 7BK1flGnI9ra5OVs07gHkIzSvtJJdTvRFoy36K51FwBlgmpPE7uhEsXmgQY9EFKllmrX +/1g== X-Forwarded-Encrypted: i=1; AJvYcCU0zI+MX/uir3sBIPYbD/S5wU+o6csn6lGjZQS9+psK9u1cZmJQUCBhtrg5G3vU2LBkC4omHjt1OC5f@vger.kernel.org, AJvYcCVtqC/pwpCSCqT0R7xgn0Cn+9jytbAO7ars4iai7Thfm6ir80ji4U3apg0xRgR0fEjL3WfIXh4sbig8Ozc=@vger.kernel.org, AJvYcCW9FL/7Pomy6M7gWA6Fwg83gc765WbyUEPRaO/aEeIkt7dDRNdyFK4Fe29191jA7Jd2ePelGessn1SaueeWUMI=@vger.kernel.org X-Gm-Message-State: AOJu0YzoPhkRcfoe5iEgIUnynkqgM65IwawXOeFlOsXFLgWQsf9DL6jk Ko+MoW3fasJUqFAE4uOHH8ciEm4Z4S+319GEFsA53qRcU/ol/iAt X-Gm-Gg: ASbGncuMHFOcZSU1tr2vWEzzPuVtrqChQsNgovNgkU1SUeF/gHVNwnwfy5atyGNCpzX N0+yTBb+N4L9rYqMjkhVwygSduNM1asI0hPegi9TWnzOdcjcBzVEW5Rq5kd82+gmaXye45lR31M L3/3/d5qKPymcGpwCFZrk9ndmyDXf3fn7NQSwwA2REqbdJgeUlv9a6OynUkWVbO1F6pVtPa0oI6 zABPdAErgdSrNesmqtXH3zWcJlfWMh7X82srA76m8e53a779WJcbnY4PnKwi4vkRAoqDDJUEwNn PhnhRJuw5Dz6xq218eos94IrKBGqiQN5ejfUCSKqXnvmCUpzLE2fqtk5N3Ni9j/HZ7pAW/YMyJX I08XRawf7w1gUGppb1iP+EWI= X-Google-Smtp-Source: AGHT+IGvL6lH6ONZZTZw0JVilpcjbjUVXYPilV66tx5v9oXHgFKQIvgBVSwhNCuPOSNDrDvg0lp6Sw== X-Received: by 2002:a05:6870:95a3:b0:2d4:c19a:94e5 with SMTP id 586e51a60fabf-2e34885828emr1280774fac.39.1747220328945; Wed, 14 May 2025 03:58:48 -0700 (PDT) Received: from my-computer.lan (c-73-76-29-249.hsd1.tx.comcast.net. [73.76.29.249]) by smtp.googlemail.com with ESMTPSA id 586e51a60fabf-2dba060be9esm2654535fac.10.2025.05.14.03.58.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 May 2025 03:58:48 -0700 (PDT) From: Andrew Ballance To: dakr@kernel.org, a.hindborg@kernel.org, airlied@gmail.com, akpm@linux-foundation.org, alex.gaynor@gmail.com, aliceryhl@google.com, andrewjballance@gmail.com, andriy.shevchenko@linux.intel.com, arnd@arndb.de, benno.lossin@proton.me, bhelgaas@google.com, bjorn3_gh@protonmail.com, boqun.feng@gmail.com, daniel.almeida@collabora.com, fujita.tomonori@gmail.com, gary@garyguo.net, gregkh@linuxfoundation.org, kwilczynski@kernel.org, me@kloenk.dev, ojeda@kernel.org, raag.jadav@intel.com, rafael@kernel.org, simona@ffwll.ch, tmgross@umich.edu Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org Subject: [PATCH v2 4/6] rust: io: implement Debug for IoRaw and add some doctests Date: Wed, 14 May 2025 05:57:32 -0500 Message-ID: <20250514105734.3898411-5-andrewjballance@gmail.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250514105734.3898411-1-andrewjballance@gmail.com> References: <20250514105734.3898411-1-andrewjballance@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Fiona Behrens Implement `Debug` for `kernel::io::IoRaw` which also outputs the const generic SIZE as a field. Add some doctests to `IoRaw::new` and `MMIo::from_raw(_ref)`. Signed-off-by: Fiona Behrens Signed-off-by: Andrew Ballance --- rust/kernel/io.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index ce044c155b16..9445451f4b02 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -226,6 +226,33 @@ pub struct IoRaw { =20 impl IoRaw { /// Returns a new `IoRaw` instance on success, an error otherwise. + /// + /// # Examples + /// + /// Const generic size 0, only allowing runtime checks: + /// ``` + /// use kernel::io::IoRaw; + /// + /// let raw: IoRaw<0> =3D IoRaw::new(0xDEADBEEFC0DE, 8).unwrap(); + /// # assert_eq!(raw.addr(), 0xDEADBEEFC0DE); + /// # assert_eq!(raw.maxsize(), 8); + /// ``` + /// + /// Const generic size equals maxsize: + /// ``` + /// use kernel::io::IoRaw; + /// + /// let raw: IoRaw<8> =3D IoRaw::new(0xDEADBEEFC0DE, 8).unwrap(); + /// # assert_eq!(raw.addr(), 0xDEADBEEFC0DE); + /// # assert_eq!(raw.maxsize(), 8); + /// ``` + /// + /// Const generic size bigger then maxsize: + /// ``` + /// use kernel::io::IoRaw; + /// + /// IoRaw::<16>::new(0xDEADBEEFC0DE, 8).unwrap_err(); + /// ``` pub fn new(addr: usize, maxsize: usize) -> Result { if maxsize < SIZE { return Err(EINVAL); @@ -247,6 +274,16 @@ pub fn maxsize(&self) -> usize { } } =20 +impl core::fmt::Debug for IoRaw { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("IoRaw") + .field("SIZE", &SIZE) + .field("addr", &self.addr) + .field("maxsize", &self.maxsize) + .finish() + } +} + /// IO-mapped memory, starting at the base address [`addr`] and spanning [= `maxsize`] bytes. /// /// The creator (usually a subsystem / bus such as PCI) is responsible for= creating the @@ -263,6 +300,7 @@ pub fn maxsize(&self) -> usize { /// [`maxsize`]: IoAccess::maxsize /// [`read`]: https://docs.kernel.org/driver-api/device-io.html#difference= s-between-i-o-access-functions /// [`write`]: https://docs.kernel.org/driver-api/device-io.html#differenc= es-between-i-o-access-functions +#[derive(Debug)] #[repr(transparent)] pub struct MMIo(IoRaw); =20 @@ -273,6 +311,18 @@ impl MMIo { /// /// Callers must ensure that `addr` is the start of a valid I/O mapped= memory region of /// size `maxsize`. + /// + /// # Examples + /// + /// ``` + /// use kernel::io::{IoRaw, MMIo, IoAccess}; + /// + /// let raw =3D IoRaw::<2>::new(0xDEADBEEFC0DE, 2).unwrap(); + /// // SAFETY: test, value is not actually written to. + /// let mmio: MMIo<2> =3D unsafe { MMIo::from_raw(raw) }; + /// # assert_eq!(0xDEADBEEFC0DE, mmio.addr()); + /// # assert_eq!(2, mmio.maxsize()); + /// ``` #[inline] pub unsafe fn from_raw(raw: IoRaw) -> Self { Self(raw) @@ -285,6 +335,18 @@ pub unsafe fn from_raw(raw: IoRaw) -> Self { /// /// Callers must ensure that `addr` is the start of a valid I/O mapped= memory region of /// size `maxsize`. + /// + /// # Examples + /// + /// ``` + /// use kernel::io::{IoRaw, MMIo, IoAccess}; + /// + /// let raw =3D IoRaw::<2>::new(0xDEADBEEFC0DE, 2).unwrap(); + /// // SAFETY: test, value is not actually written to. + /// let mmio: &MMIo<2> =3D unsafe { MMIo::from_raw_ref(&raw) }; + /// # assert_eq!(raw.addr(), mmio.addr()); + /// # assert_eq!(raw.maxsize(), mmio.maxsize()); + /// ``` #[inline] pub unsafe fn from_raw_ref(raw: &IoRaw) -> &Self { // SAFETY: `MMIo` is a transparent wrapper around `IoRaw`. @@ -349,6 +411,7 @@ impl IoAccess64Relaxed for MMI= o { /// [`maxsize`]: IoAccess::maxsize /// [`ioread`]: https://docs.kernel.org/driver-api/device-io.html#differen= ces-between-i-o-access-functions /// [`iowrite`]: https://docs.kernel.org/driver-api/device-io.html#differe= nces-between-i-o-access-functions +#[derive(Debug)] #[repr(transparent)] pub struct Io(IoRaw); =20 --=20 2.49.0 From nobody Sun Feb 8 09:16:57 2026 Received: from mail-ot1-f52.google.com (mail-ot1-f52.google.com [209.85.210.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EBB65277027; Wed, 14 May 2025 10:58:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220333; cv=none; b=Qp95105YKBG2Q95CYFIDBdDthafxHFshlRdo3zOkocMrsg1xeI17Z3k+iWPQ/ABaRuKOFezUdvFyKH7vkGj/BbSndzvTTOP1grAYRXtQMRAwNr0GM35KiXigXOkdntttr309cbFfdWMSW4r5zChn/BAeGqCQFECh1rY1SOgGFcI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220333; c=relaxed/simple; bh=Ez8ztq/dtERycj7TA7MDDVE9xQFvHtmZjoqvVWAmmLs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dURsEaXphIXots5V2hgVPuOQy98NG9zOS/UV/4KGHrT8kqXYSFWt/x2UOxr7JuR6KDeIq3rrgoy6N7RA5cl4tDFxucmpmV/sr7LzpRhMEQvgA7IiLzuWq+V3FtykWjj6YUgOJbcM/PX3qLJqYD00nbPdLv1qn4OSpob8mcwqPDs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=frzLdKLu; arc=none smtp.client-ip=209.85.210.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="frzLdKLu" Received: by mail-ot1-f52.google.com with SMTP id 46e09a7af769-72c173211feso1809628a34.1; Wed, 14 May 2025 03:58:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747220331; x=1747825131; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=z1MHzNKHnQubokyBvFDPePXlfvpf87qUBVJo47Tv4gY=; b=frzLdKLueGFwiQglXw2UliMrob5RejwIAngBxKiQ70YjLQFWqet//L3V/cV6V82q/w cZD/YKevZOmJCiAxSRmv4rJLcTLp25eE2xW83/JZzhP0xEnQPsyMkCAt23ItoLTMIcX4 kM5bu/OfWNvp0xdgjKtWtxiX451hQ/ZUyz8xYa/5Vp5nqRqG5wxOFeR5LOt6GgeS06Wq 6v9t55C8V70VMSyEYfmJf9tDikU4BZcJhMBVszFHXqV1StXbb4rHVqHN8faxWndvGJz0 rLy2YpRZ3pdW6LJHbxo3LAMtJQjTCjG9/o+qYSvUb5t6YfgYgL4uvvpEXZEs/juj/Cnc 01PA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747220331; x=1747825131; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z1MHzNKHnQubokyBvFDPePXlfvpf87qUBVJo47Tv4gY=; b=kz6jbyWJL8bn2Nv7WdiOdL7hyb7aMflVQc54d22g6domTx3IKf6Ux/aqmB3fTjmexd Hvl9iIUPqpIAt2sfs+gtnP5BqQ18yuLsQnW4FzqWx6EafyxMGgnNnByly9NZrnxeCjpB WibQ7U024G/Ut7RdsXQoNraeB/GyAKiuMxSbuSERQwIEGV5GbJ75GBnpaPOydXTmDPW7 mCExjU/6pqplEZOuV5+VnBVDGBUZE3Xy0NTZQQP1DgEnuVqvgEZq285dtBM78cjux6rj 4BOjFWRZ1pKfvDQaP+nca4Q28mkvx5owWUwTE8Zs6i6lc559eVKa8FavHmYAx5E/iIsd Joxw== X-Forwarded-Encrypted: i=1; AJvYcCUPXcsx/YUEjj/Q/NutkWAYvpeLrEpuBnFh4prnqg3BWXY5987tzIwqBkk7StxfmfApvnEunQy5Y7W5TOq3Bdc=@vger.kernel.org, AJvYcCVcdrojbwbu59/7aJc5LfuJSeUrvRkSxvdG7p5kyStH738hF/D9xhHaPoJDP9LWzEsalokJpg76kGxe@vger.kernel.org, AJvYcCWXjtkZjZ822F3olmQLDfkhoDHD91gB1swyr50Ra3NP1RkdX9trPckIBmmJnh6VEByoat8WHLAlzyqz6sw=@vger.kernel.org X-Gm-Message-State: AOJu0YwmlyWXaPMtZshTM7XTZejAhuGDWgoXnHlDTEmJPZ0w0B/83eCV ddaN5y2f3NjZvo/vVF1IgLO/Y8kW26ZBK+OsWsairf0IBkyvqgmb X-Gm-Gg: ASbGncvqbO74kpmEmLTQCmki5/1eGRCHFRejYGhFABdRRqd2hZAYaeFHtLCwwUhHh1T gN6fDto3uZsijvaJav1HKy0r4+OgiFx8USgC+rwe0b2/Mg45DupaFIopW81dAe0K0iLcmlza9VV QIuGv/SE+nhCrzkgrGwbGAEK5rQUXN56p+SOtHvNJSaaGVmfCVeNArZrFHa1DHwun+leFc+Q4Sg ubCcEV5/m7mYf3/NFuszjtylI09pKCg1XP9dWIUhi8971WWc9JwPp+FJS+Kqp4oQbjFUOctRwLk gO7CyhRXIWvB+v1JGUllcq0qo8IF/E8pbQd/9x3ekGO7DRAsV1yAo+bJrVkBz2pdJMunL7F8AOM i2aPCFtcW2WIVagghmu0cmYU= X-Google-Smtp-Source: AGHT+IEvmuwiWZKjw7O4HiUgZ9VtQ/B2bT9Vp8sHqWzneblXp8y9RdB4sfskbtrUucD6vPheSQTSNw== X-Received: by 2002:a05:6870:5251:b0:2c2:4e19:1cdf with SMTP id 586e51a60fabf-2e3488110b8mr1366100fac.25.1747220330682; Wed, 14 May 2025 03:58:50 -0700 (PDT) Received: from my-computer.lan (c-73-76-29-249.hsd1.tx.comcast.net. [73.76.29.249]) by smtp.googlemail.com with ESMTPSA id 586e51a60fabf-2dba060be9esm2654535fac.10.2025.05.14.03.58.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 May 2025 03:58:50 -0700 (PDT) From: Andrew Ballance To: dakr@kernel.org, a.hindborg@kernel.org, airlied@gmail.com, akpm@linux-foundation.org, alex.gaynor@gmail.com, aliceryhl@google.com, andrewjballance@gmail.com, andriy.shevchenko@linux.intel.com, arnd@arndb.de, benno.lossin@proton.me, bhelgaas@google.com, bjorn3_gh@protonmail.com, boqun.feng@gmail.com, daniel.almeida@collabora.com, fujita.tomonori@gmail.com, gary@garyguo.net, gregkh@linuxfoundation.org, kwilczynski@kernel.org, me@kloenk.dev, ojeda@kernel.org, raag.jadav@intel.com, rafael@kernel.org, simona@ffwll.ch, tmgross@umich.edu Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org Subject: [PATCH v2 5/6] rust: io: add from_raw_cookie functions Date: Wed, 14 May 2025 05:57:33 -0500 Message-ID: <20250514105734.3898411-6-andrewjballance@gmail.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250514105734.3898411-1-andrewjballance@gmail.com> References: <20250514105734.3898411-1-andrewjballance@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" adds a `from_raw_cookie` function to the IoAccess trait. `from_raw_cookie` attempts to convert a iomem address that can be accessed by the ioread/iowrite family of C functions into either a `Io` or `MMIo`. This is done so that devices that know what type of Io they are at compile time can give a hint about their type. Suggested-by: Danilo Krummrich Signed-off-by: Andrew Ballance --- rust/kernel/io.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 9445451f4b02..81b26602d3bc 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -6,6 +6,47 @@ =20 use crate::error::{code::EINVAL, Result}; use crate::{bindings, build_assert}; +use io_backend::*; + +/// `io_backend` is private and implements the config specific logic for +/// `IoAccess::from_raw_cookie`. +#[cfg(all(CONFIG_X86, CONFIG_GENERIC_IOMAP))] +mod io_backend { + // if on x86, generic_iomap is enabled so copy the logic + // from IO_COND in `lib/iomap.c` + + // values copied from `lib/iomap.c` + const PIO_OFFSET: usize =3D 0x10000; + const PIO_RESERVED: usize =3D 0x40000; + + #[inline] + pub(super) fn is_mmio(addr: usize) -> bool { + addr >=3D PIO_RESERVED + } + + #[inline] + pub(super) fn is_portio(addr: usize) -> bool { + !is_mmio(addr) && addr > PIO_OFFSET + } +} +#[cfg(not(CONFIG_GENERIC_IOMAP))] +mod io_backend { + // for everyone who does not use generic iomap + // except for alpha and parisc, neither of which has a rust compiler, + // ioread/iowrite is defined in `include/asm-generic/io.h`. + // + // for these ioread/iowrite, maps to read/write. + // so allow any io to be converted because they use the same backend + #[inline] + pub(super) fn is_mmio(_addr: usize) -> bool { + true + } + + #[inline] + pub(super) fn is_portio(_addr: usize) -> bool { + false + } +} =20 /// Private macro to define the [`IoAccess`] functions. macro_rules! define_io_access_function { @@ -162,6 +203,14 @@ pub unsafe trait IoAccess { /// Returns the base address of the accessed IO area. fn addr(&self) -> usize; =20 + /// Attempts to create a `Self` from a [`IoRaw`]. + /// + /// # Safety + /// `raw` should be a io cookie that can be accessed by the C `ioread`= /`iowrite` functions + unsafe fn from_raw_cookie(raw: IoRaw) -> Result + where + Self: Sized; + define_io_access_function!(@read read8_unchecked, read8, try_read8, u8; read16_unchecked, read16, try_read16, u16; @@ -366,6 +415,18 @@ fn addr(&self) -> usize { self.0.addr() } =20 + unsafe fn from_raw_cookie(raw: IoRaw) -> Result + where + Self: Sized, + { + if is_mmio(raw.addr()) { + // INVARIANT: `addr` is checked so it should be ok to access w= ith read/write + Ok(Self(raw)) + } else { + Err(EINVAL) + } + } + impl_accessor_fn!( read8_unchecked, readb, write8_unchecked, writeb, u8; read16_unchecked, readw, write16_unchecked, writew, u16; @@ -474,6 +535,18 @@ fn maxsize(&self) -> usize { self.0.maxsize() } =20 + unsafe fn from_raw_cookie(raw: IoRaw) -> Result + where + Self: Sized, + { + if is_mmio(raw.addr()) || is_portio(raw.addr()) { + // INVARIANT: `addr` is not touched so it should be able to be= read with ioread/iowrite + Ok(Self(raw)) + } else { + Err(EINVAL) + } + } + impl_accessor_fn!( read8_unchecked, ioread8, write8_unchecked, iowrite8, u8; read16_unchecked, ioread16, write16_unchecked, iowrite16, u16; --=20 2.49.0 From nobody Sun Feb 8 09:16:57 2026 Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A9D47276053; Wed, 14 May 2025 10:58:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220335; cv=none; b=lX1Qx/Ro5Ss5PTCHSxZuFonQ08FFXVRRpxzFg/BAw20xsc6wsycZ+XErNg01Uaq6qnz2yfGfTjon3NgYElYvntSeojpQD07XoBRUZvKgH98gGQYutkEQAQPy2tdm4L0j79//APR6f6wODUOrqmqd9C/HRyNxVYSJiopZrPXTjuI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747220335; c=relaxed/simple; bh=bDOrowS5NDCnhOqDvuFplAJW+UVvxHo3B+vHfABMAP8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=suwU0eV3hxOXxOIxwiMjgWyq0fPtKMwVTZ1sZBlbpUEkEKPzEmrYzoOvN3OoHpT1I8Dr/IiR7tlw3Ida5O2frush7o9pWtVLfKrN40DTvLIW7O+mkRb6F5h7rv8LJodh7Tj5S7bxJtYRxYnd83p5fiCKX1yXQF31SQPgNiRctnc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FrQIKYJM; arc=none smtp.client-ip=209.85.210.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FrQIKYJM" Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-72c40235c34so1871294a34.3; Wed, 14 May 2025 03:58:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747220333; x=1747825133; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qD5w6c0a6kvz0Ef85ipEl+D0Znk2XoV05BpXME7RAZc=; b=FrQIKYJMrfTtP/dxB3ZECMuHLMNKQWKfe8gzy1uN1qEbPirkfSxJ39237KQ8XLuptI NVLaci8dfX+LjFelEEYOOrM/e6WgCh/CYvmbCjuu6tXEqkMFNaYcdpW5cqMX1RQzKML3 uphyQLRsg2HfaGrRtlei/EURIlN6d3W1R5+iTtVu0KE+rZlSPvVy5NR/GRxd2hVbS3dz +y9itwxhRqNzWSArcJ7pLSh5qHJ3EQ3TBG70T2FUkoyD6L3DNL5z3EaCRAbN+hM1rNho r8NFMFNTr4gxVmV3LnNPnCQMQ0reFPSEVsIURdDN2OjGqnWfSVrrTODeG1uVS5tKubeV WVlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747220333; x=1747825133; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qD5w6c0a6kvz0Ef85ipEl+D0Znk2XoV05BpXME7RAZc=; b=ESYS668TAYaUNO1e17LW9qjdsI6pnUS6qaANaiHiw/wFp0ci3w5sOxt88eNEYZ2WXT Ecb2ITLIbU/g163Rez3uKT/UzpuZ1+fJQhvbn5AgopPOg95mhalWfhljyGoeimezo1lf AgdRYEMBJ747pDy3Edi/2ppuzOUMPsyjsmOzFC2/7Qr9JtytnGIPwcomU/vzxFyNChI/ VRcg5vx92Ze+fDQLduaIA3lgXWva2V+MDOf2RIxkUx2SEbDKjVBLzWnqj/cv8FeyO9EL Ndpe/bJuwA7JvK89emxC+kQ/7xYr33nu4/S9TdnvmwR/DZMKf7b2WAB9tFmzJQPNSHHc dNjw== X-Forwarded-Encrypted: i=1; AJvYcCUpT4mUcXfksiDyhzD4W4bvFvgxQZKGc3bdMbyrQX2EYyshx8dw+myn9RKUWeQ+Gi1t2094AGP9fFFDTqs=@vger.kernel.org, AJvYcCUthJPjkYUOJhhBjVlPorcYXFd/8f4lvlNVo+AovQvquA+vFfpNo/55JIP85zpu7cwx2qVtoptQmUWxEYvXoDE=@vger.kernel.org, AJvYcCXGXcuu+4Q3+/qVFc5M9OOtAnceqXhdHfHXiVeplTg6ibBAw19bqA75+cZVA1cxehA+Si/rDjXsI7CD@vger.kernel.org X-Gm-Message-State: AOJu0YxCGyiFnZuNoMG2I1x0hyYILaT72S34eDy0p6lDPcjoemrGgMJ1 pVEEz5OIFl6voFSBoW/gK4QSG0qEmeTuuSvAFEYAZx/dkmAPeCYO X-Gm-Gg: ASbGncu+7+j7J5GL98NRwky5i0sAX6e+KgjvO3ryWvFYS7KGN9lNOAtUo/4v4hXfsCZ msia5NvcE4MT50D2QT85JiR87+Xn0KoWTZSBSxA1SGF5vXgaAhVHh3x0JrVqoo+3bUNaCNjrYT4 Udrpx/QDjoWmjv3PD10PJO363ueAVb+tdLNwc4rAF3TX0/tIOev4BhTEcu57zgSomVdQSHC/oRM nDsYFwgXZXfAS0hVzJKqVmk7WKgQnuHHON1J+Ey2dJb90WUCaw/qCzx4FtrXUNECmqJkc95EPxg 8YrLmRmIeDrnXN6/f1SEKk/4AyrqJMmjU9kDq0kwicw5n+tJZTyk3pstlZbjXjr350jaRKZ5ut8 tUKU4tAuiJOdWufyu4RFsCQz8wPrchZWXpA== X-Google-Smtp-Source: AGHT+IE54MfSAuxodqlDuPCWb0IgGKv5g1H7LzyyZwbg9zyX4LOVBOAb43K73rSiK2QfFtlG75L38w== X-Received: by 2002:a05:6830:368f:b0:727:345d:3b72 with SMTP id 46e09a7af769-734e144c500mr1437251a34.16.1747220332495; Wed, 14 May 2025 03:58:52 -0700 (PDT) Received: from my-computer.lan (c-73-76-29-249.hsd1.tx.comcast.net. [73.76.29.249]) by smtp.googlemail.com with ESMTPSA id 586e51a60fabf-2dba060be9esm2654535fac.10.2025.05.14.03.58.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 May 2025 03:58:52 -0700 (PDT) From: Andrew Ballance To: dakr@kernel.org, a.hindborg@kernel.org, airlied@gmail.com, akpm@linux-foundation.org, alex.gaynor@gmail.com, aliceryhl@google.com, andrewjballance@gmail.com, andriy.shevchenko@linux.intel.com, arnd@arndb.de, benno.lossin@proton.me, bhelgaas@google.com, bjorn3_gh@protonmail.com, boqun.feng@gmail.com, daniel.almeida@collabora.com, fujita.tomonori@gmail.com, gary@garyguo.net, gregkh@linuxfoundation.org, kwilczynski@kernel.org, me@kloenk.dev, ojeda@kernel.org, raag.jadav@intel.com, rafael@kernel.org, simona@ffwll.ch, tmgross@umich.edu Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org Subject: [PATCH v2 6/6] rust: pci: make Bar generic over Io Date: Wed, 14 May 2025 05:57:34 -0500 Message-ID: <20250514105734.3898411-7-andrewjballance@gmail.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250514105734.3898411-1-andrewjballance@gmail.com> References: <20250514105734.3898411-1-andrewjballance@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" renames `Bar` to `RawBar` and makes it generic over `IoAccess`. a user can give a compile time suggestion when mapping a bar so that the type of io can be known. updates nova-core and rust_driver_pci to use new bar api. Suggested-by: Danilo Krummrich Signed-off-by: Andrew Ballance --- drivers/gpu/nova-core/driver.rs | 4 +- rust/kernel/pci.rs | 101 +++++++++++++++++++++++++------- samples/rust/rust_driver_pci.rs | 2 +- 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index a08fb6599267..c03283d1e60e 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -11,7 +11,7 @@ pub(crate) struct NovaCore { } =20 const BAR0_SIZE: usize =3D 8; -pub(crate) type Bar0 =3D pci::Bar; +pub(crate) type Bar0 =3D pci::MMIoBar; =20 kernel::pci_device_table!( PCI_TABLE, @@ -33,7 +33,7 @@ fn probe(pdev: &pci::Device, _info: &Self::IdInfo) = -> Result(0, c_str!("nova-c= ore/bar0"))?; + let bar =3D pdev.iomap_region_sized_mmio::(0, c_str!("n= ova-core/bar0"))?; =20 let this =3D KBox::pin_init( try_pin_init!(Self { diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 9f5ca22d327a..42fbe597b06e 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -11,8 +11,7 @@ devres::Devres, driver, error::{to_result, Result}, - io::Io, - io::IoRaw, + io::{Io, IoAccess, IoRaw, MMIo}, str::CStr, types::{ARef, ForeignOwnable, Opaque}, ThisModule, @@ -259,15 +258,21 @@ pub struct Device( /// /// # Invariants /// -/// `Bar` always holds an `IoRaw` inststance that holds a valid pointer to= the start of the I/O +/// `Bar` always holds an `I` inststance that holds a valid pointer to the= start of the I/O /// memory mapped PCI bar and its size. -pub struct Bar { +pub struct RawBar =3D Io>= { pdev: ARef, - io: IoRaw, + io: I, num: i32, } =20 -impl Bar { +/// a pci bar that can be either PortIo or MMIo +pub type IoBar =3D RawBar>; + +/// a pci bar that maps a [`MMIo`]. +pub type MMIoBar =3D RawBar>; + +impl> RawBar { fn new(pdev: &Device, num: u32, name: &CStr) -> Result { let len =3D pdev.resource_len(num)?; if len =3D=3D 0 { @@ -299,7 +304,7 @@ fn new(pdev: &Device, num: u32, name: &CStr) -> Result<= Self> { return Err(ENOMEM); } =20 - let io =3D match IoRaw::new(ioptr, len as usize) { + let raw =3D match IoRaw::new(ioptr, len as usize) { Ok(io) =3D> io, Err(err) =3D> { // SAFETY: @@ -311,7 +316,22 @@ fn new(pdev: &Device, num: u32, name: &CStr) -> Result= { } }; =20 - Ok(Bar { + // SAFETY: + // - `raw` is from `pci_iomap` + // - addresses from `pci_iomap` should be accesed through ioread/i= owrite + let io =3D match unsafe { I::from_raw_cookie(raw) } { + Ok(io) =3D> io, + Err(err) =3D> { + // SAFETY: + // `pdev` is valid by the invariants of `Device`. + // `ioptr` is guaranteed to be the start of a valid I/O ma= pped memory region. + // `num` is checked for validity by a previous call to `De= vice::resource_len`. + unsafe { Self::do_release(pdev, ioptr, num) }; + return Err(err); + } + }; + + Ok(RawBar { pdev: pdev.into(), io, num, @@ -338,25 +358,24 @@ fn release(&self) { } } =20 -impl Bar { +impl RawBar { fn index_is_valid(index: u32) -> bool { // A `struct pci_dev` owns an array of resources with at most `PCI= _NUM_RESOURCES` entries. index < bindings::PCI_NUM_RESOURCES } } =20 -impl Drop for Bar { +impl> Drop for RawBar { fn drop(&mut self) { self.release(); } } =20 -impl Deref for Bar { - type Target =3D Io; +impl> Deref for RawBar { + type Target =3D I; =20 fn deref(&self) -> &Self::Target { - // SAFETY: By the type invariant of `Self`, the MMIO range in `sel= f.io` is properly mapped. - unsafe { Io::from_raw_ref(&self.io) } + &self.io } } =20 @@ -379,7 +398,7 @@ pub fn device_id(&self) -> u16 { =20 /// Returns the size of the given PCI bar resource. pub fn resource_len(&self, bar: u32) -> Result { - if !Bar::index_is_valid(bar) { + if !RawBar::index_is_valid(bar) { return Err(EINVAL); } =20 @@ -389,22 +408,62 @@ pub fn resource_len(&self, bar: u32) -> Result { Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into= ()?) }) } =20 - /// Mapps an entire PCI-BAR after performing a region-request on it. I= /O operation bound checks + /// Maps an entire PCI-BAR after performing a region-request on it. I/= O operation bound checks /// can be performed on compile time for offsets (plus the requested t= ype size) < SIZE. pub fn iomap_region_sized( &self, bar: u32, name: &CStr, - ) -> Result>> { - let bar =3D Bar::::new(self, bar, name)?; + ) -> Result>> { + self.iomap_region_sized_hint::>(bar, name) + } + + /// Maps an entire PCI-BAR after performing a region-request on it. + pub fn iomap_region(&self, bar: u32, name: &CStr) -> Result> { + self.iomap_region_sized::<0>(bar, name) + } + + /// Maps an entire PCI-BAR after performing a region-request on it. I/= O operation bound checks + /// can be performed on compile time for offsets (plus the requested t= ype size) < SIZE. + /// where it is known that the bar is [`MMIo`] + pub fn iomap_region_sized_mmio( + &self, + bar: u32, + name: &CStr, + ) -> Result>> { + self.iomap_region_sized_hint::>(bar, name) + } + + /// Maps an entire PCI-BAR after performing a region-request on it. + /// where it is known that the bar is [`MMIo`] + pub fn iomap_region_mmio(&self, bar: u32, name: &CStr) -> Result> { + self.iomap_region_sized_hint::<0, MMIo<0>>(bar, name) + } + + /// Maps an entire PCI-BAR after performing a region-request where the + /// type of Io backend is known at compile time. + pub fn iomap_region_hint( + &self, + bar: u32, + name: &CStr, + ) -> Result>> { + let bar =3D RawBar::<0, I>::new(self, bar, name)?; let devres =3D Devres::new(self.as_ref(), bar, GFP_KERNEL)?; =20 Ok(devres) } + /// Maps an entire PCI-BAR after performing a region-request where the + /// type of Io backend is known at compile time. I/O operation bound c= hecks + /// can be performed on compile time for offsets (plus the requested t= ype size) < SIZE. + pub fn iomap_region_sized_hint>( + &self, + bar: u32, + name: &CStr, + ) -> Result>> { + let bar =3D RawBar::::new(self, bar, name)?; + let devres =3D Devres::new(self.as_ref(), bar, GFP_KERNEL)?; =20 - /// Mapps an entire PCI-BAR after performing a region-request on it. - pub fn iomap_region(&self, bar: u32, name: &CStr) -> Result> { - self.iomap_region_sized::<0>(bar, name) + Ok(devres) } } =20 diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index a8d292f4c1b3..b645155142db 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -18,7 +18,7 @@ impl Regs { const END: usize =3D 0x10; } =20 -type Bar0 =3D pci::Bar<{ Regs::END }>; +type Bar0 =3D pci::IoBar<{ Regs::END }>; =20 #[derive(Debug)] struct TestIndex(u8); --=20 2.49.0