{"id":2225771,"url":"http://patchwork.ozlabs.org/api/patches/2225771/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-pci/patch/20260421-io_projection-v2-6-4c251c692ef4@garyguo.net/","project":{"id":28,"url":"http://patchwork.ozlabs.org/api/projects/28/?format=json","name":"Linux PCI development","link_name":"linux-pci","list_id":"linux-pci.vger.kernel.org","list_email":"linux-pci@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260421-io_projection-v2-6-4c251c692ef4@garyguo.net>","list_archive_url":null,"date":"2026-04-21T14:56:17","name":"[v2,06/11] rust: io: add view type","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"b22d329fb50e000d4674c927bc10a5928ca840e2","submitter":{"id":76823,"url":"http://patchwork.ozlabs.org/api/people/76823/?format=json","name":"Gary Guo","email":"gary@garyguo.net"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-pci/patch/20260421-io_projection-v2-6-4c251c692ef4@garyguo.net/mbox/","series":[{"id":500833,"url":"http://patchwork.ozlabs.org/api/series/500833/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-pci/list/?series=500833","date":"2026-04-21T14:56:19","name":"rust: I/O type generalization and projection","version":2,"mbox":"http://patchwork.ozlabs.org/series/500833/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2225771/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2225771/checks/","tags":{},"related":[],"headers":{"Return-Path":"\n <linux-pci+bounces-52841-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-pci@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=garyguo.net header.i=@garyguo.net header.a=rsa-sha256\n header.s=selector1 header.b=IGLO17Mb;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c15:e001:75::12fc:5321; helo=sin.lore.kernel.org;\n envelope-from=linux-pci+bounces-52841-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net\n header.b=\"IGLO17Mb\"","smtp.subspace.kernel.org;\n arc=fail smtp.client-ip=52.101.196.131","smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=garyguo.net","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=garyguo.net","dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=garyguo.net;"],"Received":["from sin.lore.kernel.org (sin.lore.kernel.org\n [IPv6:2600:3c15:e001:75::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g0QTx3R3fz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 00:58:45 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sin.lore.kernel.org (Postfix) with ESMTP id 9AE64301C3C0\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 21 Apr 2026 14:56:53 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 5E2A43DA5B9;\n\tTue, 21 Apr 2026 14:56:37 +0000 (UTC)","from LO3P265CU004.outbound.protection.outlook.com\n (mail-uksouthazon11020131.outbound.protection.outlook.com [52.101.196.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 993583D9DDC;\n\tTue, 21 Apr 2026 14:56:35 +0000 (UTC)","from LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:488::16)\n by CWLP265MB5674.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:1b0::13) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9846.16; Tue, 21 Apr\n 2026 14:56:29 +0000","from LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM\n ([fe80::1c3:ceba:21b4:9986]) by LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM\n ([fe80::1c3:ceba:21b4:9986%4]) with mapi id 15.20.9846.016; Tue, 21 Apr 2026\n 14:56:29 +0000"],"ARC-Seal":["i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776783397; cv=fail;\n b=mXsjUD9fIDf+Pc6dHgfpJZFFoqdHyIZMT8H7P8EMpn3mLbqTWrYo3EVcrUsXx74NH6E0gr6jZ5vp3foPCu06XXq2WthdA7tNfesDANt4HzYhIax1c5tRE2rpxzNQAVmHghqQ/Qu/PhFKRtnTGlWdDfqexkiB4Ym/GEYGqFadthE=","i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=DDP4tCAp3YY3lju2em9ny5IpDr/vzo5sS0bdww7i6120UPrtvhwed4zsRWFOQkfS6t1mtQ3/Oity4BUp5O6ov1m1rDeTvbDV7l1XNHzvWjpLE+mrvw+nxaamuW2xNfG6TqvNHMU9jmyjFsI1KY3SQfbUQCTJa738oJJkFwTFqGca8j17iQsTpQ/DXJHjFPr1VQI69ADLKjFHCQ1cKRZe+zvZk9etVhUnKHXtZHf5hZ20VzvGlSAJwJF2iGnBhvFkBrX7NHTDzAwga1k0ec1VEu/WuYJew+Wx3Bs5qp1EEggeW0H3Klk9uWvNTR/AXWokzMNgjGKI9YPbA2INp0Q8vw=="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776783397; c=relaxed/simple;\n\tbh=Aiz1SAzAaI4xDUYeDbA1tGyZD1iLdIGo9Omh+b0S9cE=;\n\th=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To:\n\t To:Cc:MIME-Version;\n b=GCkYAFg2zFkQH1g9ii3vt9XJn9JoYu1PaedZ1XBgZBUd1Cu6z+BaSfYuoG4qY560QLU4PYWgqa3DEofgQtzWg2PuAV2qV3S+uqEaICw1ZfWg0FQkZdgODVC9DwtfhBspUStSBfkTJR9xXrh2lN1J6fD/ztSuaLpFlo2Qoe2TuvA=","i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=NBCRkNd4yS+sbgCTUuQCjj+vsx4wEQlficT2OEM7beE=;\n b=QDPjGn89zOvuriPriIbx/aAFN+A48yX0FMxZSAQ+hZi+HBSoyFO193fQEWd6inVkK4KFcNyXZKDe2BgkrUL2HqHuMMdD3ZWH/s6PRTEm2H/yDtnmHp1h2YVM8IjKz75nAQsyxGjilEBve0Jw1ufrI98o4Mu3zoN3D7aD2txZuLeB0xo/kYV7YG+M6bVyRaKd5N/MfFbgnFks9txrkXMEYJPI58Q0zs1UrpWHFnK/XFIHKNMTlqQsUCuXuPYJD4N1HPp9Xk/TEwYbeWHKJ6dmAehVNgr5XfpQLkYUcQupCfF8ei2L93Xu9DZrOBgNk07Uxozhl56hpwLV+4dKR1V35w=="],"ARC-Authentication-Results":["i=2; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=garyguo.net;\n spf=pass smtp.mailfrom=garyguo.net;\n dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net\n header.b=IGLO17Mb; arc=fail smtp.client-ip=52.101.196.131","i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net;\n dkim=pass header.d=garyguo.net; arc=none"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net;\n s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=NBCRkNd4yS+sbgCTUuQCjj+vsx4wEQlficT2OEM7beE=;\n b=IGLO17MbXGUWXVtGRpwpXP+pxvt5b+zSXUS88ICW0d9cj/Qu3m5nArJrH0yH/5HPCz3PwrryjfafZIV4g3HGyJvG35bkyCdccTuIF8VrO9R1xMnRojD5gPjx2SYZCQSePdKyZ03aremYQ9DtIuZB37zZ8yuOB1InblREdLnw4h4=","From":"Gary Guo <gary@garyguo.net>","Date":"Tue, 21 Apr 2026 15:56:17 +0100","Subject":"[PATCH v2 06/11] rust: io: add view type","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","Message-Id":"<20260421-io_projection-v2-6-4c251c692ef4@garyguo.net>","References":"<20260421-io_projection-v2-0-4c251c692ef4@garyguo.net>","In-Reply-To":"<20260421-io_projection-v2-0-4c251c692ef4@garyguo.net>","To":"Greg Kroah-Hartman <gregkh@linuxfoundation.org>,\n  \"Rafael J. Wysocki\" <rafael@kernel.org>, Danilo Krummrich <dakr@kernel.org>,\n  Miguel Ojeda <ojeda@kernel.org>, Boqun Feng <boqun@kernel.org>,\n  Gary Guo <gary@garyguo.net>,\n =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= <bjorn3_gh@protonmail.com>,\n  Benno Lossin <lossin@kernel.org>, Andreas Hindborg <a.hindborg@kernel.org>,\n  Alice Ryhl <aliceryhl@google.com>, Trevor Gross <tmgross@umich.edu>,\n  Daniel Almeida <daniel.almeida@collabora.com>,\n  Bjorn Helgaas <bhelgaas@google.com>,\n =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= <kwilczynski@kernel.org>,\n  Abdiel Janulgue <abdiel.janulgue@gmail.com>,\n  Robin Murphy <robin.murphy@arm.com>,\n  Alexandre Courbot <acourbot@nvidia.com>, David Airlie <airlied@gmail.com>,\n  Simona Vetter <simona@ffwll.ch>","Cc":"driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org,\n linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,\n nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org","X-Mailer":"b4 0.15.1","X-Developer-Signature":"v=1; a=ed25519-sha256; t=1776783386; l=5749;\n i=gary@garyguo.net; s=20221204; h=from:subject:message-id;\n bh=Aiz1SAzAaI4xDUYeDbA1tGyZD1iLdIGo9Omh+b0S9cE=;\n b=nCrvfstnb2bvYiKMDfOSPCaiv0BoY0hMKfa4+nDIeuRoo33zRi9gM+3Ue8jnRMcVG39vMm/eX\n MtOYjTn6YtoBtAK7MWmQoyXhS0z6D+SoqXT+pPWIyVCz4q28gNytRLg","X-Developer-Key":"i=gary@garyguo.net; a=ed25519;\n pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo=","X-ClientProxiedBy":"LO4P123CA0142.GBRP123.PROD.OUTLOOK.COM\n (2603:10a6:600:193::21) To LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM\n (2603:10a6:600:488::16)","Precedence":"bulk","X-Mailing-List":"linux-pci@vger.kernel.org","List-Id":"<linux-pci.vger.kernel.org>","List-Subscribe":"<mailto:linux-pci+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-pci+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","X-MS-PublicTrafficType":"Email","X-MS-TrafficTypeDiagnostic":"LOVP265MB8871:EE_|CWLP265MB5674:EE_","X-MS-Office365-Filtering-Correlation-Id":"28f11079-18c8-41d1-7aa9-08de9fb62b5e","X-MS-Exchange-SenderADCheck":"1","X-MS-Exchange-AntiSpam-Relay":"0","X-Microsoft-Antispam":"\n\tBCL:0;ARA:13230040|1800799024|376014|7416014|10070799003|366016|921020|22082099003|18002099003|56012099003;","X-Microsoft-Antispam-Message-Info":"\n\t7J5YxYfOO0KE9wVilg4vvkJUIbGrUwPiWBY0LsonuhnDZB4JhOct5I3UyjF+C1qnPnEu1TH2S9DcoO0EyENcaoCuq6El9fAOTgbbXu//aul7GFTNAByIJuQ1uIzAyNV9zlGKcM6BokQ8v/YwSpkxy1TB0tdMW0wJwZt/Uuioqb3CRr6UBtpYkfIJhw7RhqueBo6zlKlUTXOqkrOUYgCyzD4+aKftfoMGi3p9ZDUZDEvRGf9YivBMDTjGaTXobFok6Ao7lIdRgDBnaN80jvyMERMdjNyYiYbbf1iEM/SGNRuNADgmwBLZJV+kK6pZ/EjGvsPLk6bGsxof/ClW3EBcQA3CKXinBLBNQbdi3X3kvsllSMaiY+bEjazj5H6V3fEZgVfE4wzVlNWF8khhiMcYbdxjFQajjo31D7GqbOaUwl5gJLIGNGV1TyanDpVCvoUlq8LblLyLglSExElXTtHhVS5dcYELhxZiBr0UA1/FUYt30H6czbfVmwUdFz9PUpqzOsAbOC/Qyy/n6v6zEZsKXtDC3gqhU+iuhFLK6Mearg1ZxmUzwHzQdyVk/aSn5DBpsXG3VsjBuQ0+O3OZGQKM2A+B4HmCpfQzfcLxBcG1MBtwQbEW1ShJK1fK/g0kbdEwGeIRbGjZrMziQZKs0Qh8EkRY06xYBWMmVPPvt91ejVGAjrNUA8S6nJ0EzwTNFeN3qInIhUCVm56mrQhLUeBQlO6WXZY3pmQEKtIJIgBUuVh+n2PiiR03S4Y/RTCR2j1otttrFbsgH4TqOZ4vnaYCsQ==","X-Forefront-Antispam-Report":"\n\tCIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(7416014)(10070799003)(366016)(921020)(22082099003)(18002099003)(56012099003);DIR:OUT;SFP:1102;","X-MS-Exchange-AntiSpam-MessageData-ChunkCount":"1","X-MS-Exchange-AntiSpam-MessageData-0":"=?utf-8?q?+2xG614y3KXYavGipCwREDbUYZh1?=\n\t=?utf-8?q?vjhlHps86Yp7UXV6wVhpNa73UejXhtgpdNkklQz1rIdc5/2wKuoXF7gGBAcQI3gQa?=\n\t=?utf-8?q?FeroUnHMMwar2xPTQW/YAsWqSA2IQF1KxVY3klzFhYBPun6T/DLOPrjUxPpjc2zoB?=\n\t=?utf-8?q?+ZhN6Vl9co8lBIdkV/eRb+ejHGDWPG/BFu3s5IDqMX4BB5OG+08zQKTy/WYm+23pz?=\n\t=?utf-8?q?Gh4sg4kxqmsHSuU5ICI0ai9hQA9mQJpx4GqcDVPHArJjau8G3EuUmjUbU7mTsyNZB?=\n\t=?utf-8?q?48G4DWQI9b1iC6x79hyk8UQcDZBMSc+ZQ5Q2K77XY+rVNh8Bs31vW/Kg3yTCRri5O?=\n\t=?utf-8?q?D45Z97FbJp7LyoPw7UlORm9uJHNc8ApH6e4CMZqKH52Xf1b4PiQ8gS7GQgLtRJAHU?=\n\t=?utf-8?q?8mefoHZhLSNrzJfEeCgN0pwyt496GbTBjHoTPtXv8P4zdPLyKUJMJ+dpk7pTCe6Ea?=\n\t=?utf-8?q?6GX9rtrULj02crdatei9R4OQqB7Ndm6xWpos1QZn3jxDGi/yKz6UfeBMqsac6IYqw?=\n\t=?utf-8?q?TrlfBLoLNe762wj25POm0YPMaiU0uk0QWQTG/YFfWue54069SWecl/Yv1OkhymoU0?=\n\t=?utf-8?q?nFGZVOAclOoMxw4cm+zAAsbNdeyKnclCqjxWYBeuDRk0ipIVAER5Fc05P3mEA23cy?=\n\t=?utf-8?q?YtytC7C6C5b3PEouz5WCIe9Z+ODukjj3uqvz5RPunjuuMgttIDRNyyjTvTWYwXVbk?=\n\t=?utf-8?q?oaiUa766A/C2p/gPKGL2BNv2hbznX1aoLXxN8vzeWvgC/QjwO1q+VhpgCYr7SLbB9?=\n\t=?utf-8?q?9p1T3Q9sPaWCvDTFj5hUdcwz7puBGll5QiyrLwbPtLcRTSJc42DMigZOHDj9XLKSv?=\n\t=?utf-8?q?VgYZzerliLgZDPg/Y6DDZck0+ARtrIp99lbxGpUR9BJZfYJt/T5Z71tH0wwQjdC4y?=\n\t=?utf-8?q?haTfuLnycCcb9pEZqiZ0+nYzxF9ixv5GPZjciorrp597jr+2HIwit+PWEIkQ95zzf?=\n\t=?utf-8?q?rgUeVCZrdnGEavOdh0IPNZ2wt1IguKMk/JRDS/gYNGiWf7WcINYwW5m3x2ToToqOq?=\n\t=?utf-8?q?ZENMeuQEoF2eMlYAicAoOBRSx/fQiGla41OffnDsmjdayjxYbQTR4MZInIr6kc2tL?=\n\t=?utf-8?q?TTUKvb05GcMrxRsM5yQ+zOKTJ5qe3wDAMCVMfJI2WDD4tpR7gHSLo2vBY7jwhOTcb?=\n\t=?utf-8?q?fXxWAgp8fyxndnuqddYm2lJt2WqwagknMXpPVtqH+I4AjOTEx81V+k17u/r1mrG1f?=\n\t=?utf-8?q?+TsGYrC8yMT46+H3WQTPIKIb1LEJ/aiFjst38+3HCQ9dP9OxwDnG5YDWEel5YAZZt?=\n\t=?utf-8?q?aZ21c9kF9pfYjvL1a+jGbKuj8lu+kIxNuaTjHGfWz9rGcbdXnLzm7K6rPeNzB5uMO?=\n\t=?utf-8?q?kf2LSgux2F5GauQs2b2SYdEQJQ0h9ueCwcCUGhdptKtp6HR2GZZYguXyJa3lSIUf2?=\n\t=?utf-8?q?t3QujpDds6xQjg5fqcm/EpFRcBS7qczs0+/3dzmtqezXGhow2ii4dQqHxKCsJKQ3o?=\n\t=?utf-8?q?ktKLUZvbsLv99Sr1xGt+Xgz2ZGSIJmfX5sfHf1NtHMMz2C4b41BVRFaNGDRMenvfr?=\n\t=?utf-8?q?AiGPialOvs+WvEbjsaWX697ITP7qOCcv04yO4BDgfKyfoiWAQRaPi65GjSqmQybiK?=\n\t=?utf-8?q?OzFSbi7oN7XZIl53tnLTIvvrkr1/3n1wPS1urnS/wygtAt3hiX/7Xie5REMlQbGYL?=\n\t=?utf-8?q?t+Cuw582kU5ydWuEm3x/ylQhMfNsVTnA=3D=3D?=","X-OriginatorOrg":"garyguo.net","X-MS-Exchange-CrossTenant-Network-Message-Id":"\n 28f11079-18c8-41d1-7aa9-08de9fb62b5e","X-MS-Exchange-CrossTenant-AuthSource":"LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM","X-MS-Exchange-CrossTenant-AuthAs":"Internal","X-MS-Exchange-CrossTenant-OriginalArrivalTime":"21 Apr 2026 14:56:29.4443\n (UTC)","X-MS-Exchange-CrossTenant-FromEntityHeader":"Hosted","X-MS-Exchange-CrossTenant-Id":"bbc898ad-b10f-4e10-8552-d9377b823d45","X-MS-Exchange-CrossTenant-MailboxType":"HOSTED","X-MS-Exchange-CrossTenant-UserPrincipalName":"\n 1Syz8XJXVkI6KKLCpM9rZmI6lTHNlMxjzta7D73csoPArsab/AkmuOkZk9NFHov1vgmuOBQRP6XHP2OMMxVyug==","X-MS-Exchange-Transport-CrossTenantHeadersStamped":"CWLP265MB5674"},"content":"The view may be created statically via I/O projection using `io_project!()`\nmacro to perform compile-time checks, or created by type-casting an\nexisting view type with `try_cast()` function, where the size and alignment\nchecks are performed at runtime.\n\nReviewed-by: Andreas Hindborg <a.hindborg@kernel.org>\nSigned-off-by: Gary Guo <gary@garyguo.net>\n---\n rust/kernel/io.rs | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 146 insertions(+), 1 deletion(-)","diff":"diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs\nindex a13be8c5fd2d..869071d47a13 100644\n--- a/rust/kernel/io.rs\n+++ b/rust/kernel/io.rs\n@@ -7,7 +7,11 @@\n use crate::{\n     bindings,\n     prelude::*,\n-    ptr::KnownSize, //\n+    ptr::KnownSize,\n+    transmute::{\n+        AsBytes,\n+        FromBytes, //\n+    }, //\n };\n \n pub mod mem;\n@@ -297,6 +301,13 @@ pub trait Io {\n     /// Type of this I/O region. For untyped I/O regions, [`Region`] type can be used.\n     type Type: ?Sized + KnownSize;\n \n+    /// Get a [`View`] covering the entire region.\n+    #[inline]\n+    fn as_view(&self) -> View<'_, Self, Self::Type> {\n+        // SAFETY: This is an empty projection, so it trivially satisfies the invariant.\n+        unsafe { View::new_unchecked(self, self.as_ptr()) }\n+    }\n+\n     /// Returns the base pointer of this mapping.\n     ///\n     /// This is a pointer to capture metadata. The specific meaning of the pointer depends on\n@@ -912,3 +923,137 @@ pub fn relaxed(&self) -> &RelaxedMmio<T> {\n     readq_relaxed,\n     writeq_relaxed\n );\n+\n+/// A view into an I/O region.\n+///\n+/// # Invariants\n+///\n+/// - `ptr` is aligned for `T`\n+/// - `ptr` has same provenance as `io.as_ptr()`\n+/// - `ptr.byte_offset_from(io.as_ptr())` is between 0 to\n+///   `KnownSize::size(io.as_ptr()) - KnownSize::size(ptr)`.\n+///\n+/// These invariants are trivially satisfied if the pointer is created via pointer projection.\n+pub struct View<'a, IO: ?Sized, T: ?Sized> {\n+    io: &'a IO,\n+    ptr: *mut T,\n+}\n+\n+impl<'a, IO: ?Sized, T: ?Sized> View<'a, IO, T> {\n+    // For `io_project!` macro use only.\n+    #[doc(hidden)]\n+    #[inline]\n+    pub fn as_view(&self) -> Self {\n+        *self\n+    }\n+\n+    /// Create a view of a provided I/O region.\n+    ///\n+    /// # Safety\n+    ///\n+    /// `ptr` must satisfy the invariants of the view type.\n+    #[inline]\n+    pub unsafe fn new_unchecked(io: &'a IO, ptr: *mut T) -> Self {\n+        // INVARIANT: Per function safety requirement.\n+        Self { io, ptr }\n+    }\n+\n+    /// Obtain the underlying I/O region.\n+    #[inline]\n+    pub fn io(self) -> &'a IO {\n+        self.io\n+    }\n+\n+    /// Obtain a pointer to the subview.\n+    ///\n+    /// The interpretation of the pointer depends on the underlying I/O region.\n+    #[inline]\n+    pub fn as_ptr(self) -> *mut T {\n+        self.ptr\n+    }\n+}\n+\n+impl<IO: ?Sized, T: ?Sized> Clone for View<'_, IO, T> {\n+    #[inline]\n+    fn clone(&self) -> Self {\n+        *self\n+    }\n+}\n+\n+impl<IO: ?Sized, T: ?Sized> Copy for View<'_, IO, T> {}\n+\n+impl<'a, IO: ?Sized, T: ?Sized> View<'a, IO, T> {\n+    /// Try to convert this view into a different typed I/O view.\n+    ///\n+    /// The target type must be of same or smaller size to current type, and the current view must\n+    /// be properly aligned for the target type.\n+    #[inline]\n+    pub fn try_cast<U>(self) -> Result<View<'a, IO, U>>\n+    where\n+        T: KnownSize + FromBytes + AsBytes,\n+        U: FromBytes + AsBytes,\n+    {\n+        if size_of::<U>() > KnownSize::size(self.ptr) {\n+            return Err(EINVAL);\n+        }\n+\n+        if self.ptr.addr() % align_of::<U>() != 0 {\n+            return Err(EINVAL);\n+        }\n+\n+        // INVARIANT: We have checked bounds and alignment.\n+        Ok(View {\n+            io: self.io,\n+            ptr: self.ptr.cast(),\n+        })\n+    }\n+}\n+\n+/// Project an I/O type to a subview of it.\n+///\n+/// The syntax is of form `io_project!(io, proj)` where `io` is an expression to a type that\n+/// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!).\n+///\n+/// In addition to projecting from [`Io`], you may also project from a [`View`] of an [`Io`].\n+///\n+/// # Examples\n+///\n+/// ```\n+/// use kernel::io::{\n+///     io_project,\n+///     Mmio,\n+///     View,\n+/// };\n+/// struct MyStruct { field: u32, }\n+///\n+/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.\n+/// unsafe impl kernel::transmute::FromBytes for MyStruct{};\n+/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.\n+/// unsafe impl kernel::transmute::AsBytes for MyStruct{};\n+///\n+/// # fn test(mmio: &Mmio<[MyStruct]>) -> Result {\n+/// // let mmio: Mmio<[MyStruct]>;\n+/// let field: View<'_, _, u32> = io_project!(mmio, [try: 1].field);\n+/// let whole: View<'_, _, MyStruct> = io_project!(mmio, [try: 2]);\n+/// let nested: View<'_, Mmio<_>, u32> = io_project!(whole, .field);\n+/// # Ok::<(), Error>(()) }\n+#[macro_export]\n+#[doc(hidden)]\n+macro_rules! io_project {\n+    ($io:expr, $($proj:tt)*) => {{\n+        // Bring `as_view` to scope.\n+        use $crate::io::Io as _;\n+\n+        // Convert IO to view for unified handling.\n+        // This also takes advantage to deref coercion.\n+        let view: $crate::io::View<'_, _, _> = $io.as_view();\n+        let ptr = $crate::ptr::project!(\n+            mut view.as_ptr(), $($proj)*\n+        );\n+        // SAFETY: projection of a projection is still a valid projection.\n+        unsafe { $crate::io::View::new_unchecked(view.io(), ptr) }\n+    }};\n+}\n+\n+#[doc(inline)]\n+pub use crate::io_project;\n","prefixes":["v2","06/11"]}