From nobody Tue Sep 29 13:18:14 2026 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) (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 35B1F379C3E for ; Fri, 7 Aug 2026 07:40:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088453; cv=none; b=jKst8PHlyQHeXLbcpHJnlzPvEvN76e00Tttz/Y6ZGj7pOjdP709V1Ofs07TrpnkJ9wsV1AGjkMNaPc4F4iUeugJf1EuObRqHmbEuqCx50EhxYeVhORO9XVb4A4z2EbbmACNBaMtpyYST6nBp29B4At6JY3Att8zlBVFGlM+p9BI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088453; c=relaxed/simple; bh=XRjWR+Miez9ABrBTjcbrpXIpp8Y7F55xFix0sC+e4s0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=s4ADRGRhYgBa1LOD5b6qiB3Pxi8DIf7/JVp76v08Zhv/u7691HGCiJHbHpdOsPa98um1hAAaGER20aVCgrE9LS9P40xt+yw/sv9z5eec0xPHPxmO4SMrNr5NHBD/UQ6IiyfvGBXqqbprYmaZHlhHzu3/q16nW9CcPZv/KaaT3PY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=none smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b=Y03dLBLr; arc=none smtp.client-ip=209.85.221.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b="Y03dLBLr" Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-47f703a9e5dso1569155f8f.0 for ; Fri, 07 Aug 2026 00:40:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20251104.gappssmtp.com; s=20251104; t=1786088450; x=1786693250; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=37E29zaFhLGOrDb/ZTD96WxUaP6LZSPazQ7ZZ2/0O0I=; b=Y03dLBLrZvklntcaLJuPjYXR9VW+ycGwcGeDMdndTzfuqWm/V7TjSjIeMvkjo+CkoN RcjVL/ARmDZBn8SN4aRF5BmtjXJ3vfJggQs5oQS4JdugZP61EeE8UDGWxdJwPmiNb01K tQN3lk+a9GusYTSkR8Mqum5m+qvLWnmiqZGLjPywlD9M2Ehtg7rPPcs9ZQZ8idymvUU1 veX+lDz5eu8joy8BAKogHYnsUVDurA9GrK99UxdqYpvh0GB9XA7Z5n3tVd+cazvVRYP0 2XJSr4YRV/8Q9U93fgNas2DHxKaftf0JKWnxFfPdhydQvyIH/QGa5R3mMwdAeTmdlzUC Eb0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786088450; x=1786693250; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=37E29zaFhLGOrDb/ZTD96WxUaP6LZSPazQ7ZZ2/0O0I=; b=sO9Ac40qMOgkwtupotiLnCjY+LetPhqgkSjA57iROVSzpKTuI7YQDwLQJ12ofYy6h1 Yxg+lMUkoQ8XIug4zoJ8nS5RBOSHYxudPUZD1ODWxrGiK4dG0emRrKdIKpbIkWSxsfAu zCIT83hZuVPL2/6jC0OmC1AJ7Em38BoRqd+ePfAUFwVhNCqXQuUOVhnUOAgVCNbDrYw3 31mV2E8gIwzP2CRpDK7rGG6b8AeaWcjYUDoui28jcXKhY4yl+DhPpqD2fCmSbzZMhLGD W0lymjhshrWjiVjYAScHkwQ5Q6563Hv1oc4RHlokLSrSYBj/Yo9vi4G462ufO+1GVNXZ R2QQ== X-Forwarded-Encrypted: i=1; AHgh+Rrm/zWTD5eaIae02GWmfvXJHnSSJvD0MdMp9P7W3cLbg5cHrVp1T+434hmO+VlfmNsD2dyMixPLInPeQYQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwitsfsFMqugYDu788Y255NvQhXFdTVWarBMiyfq/Wyc/Eu3qe/ 2SqAyGhvc8XwmNlHXbXfUdtqotya0LEdFa7Nni9fENouvu5PSonIj09cYB7+RNNnxbl8 X-Gm-Gg: AR+sD13gouV8UWB/pOAx3B3OsfV2/4d2rfqaXTJN/37HPVkrkBFcFh62rUSFyWcVkee uIIMS4x4xPCCuaYC7sNaBSrgFE93PhVMfpXMnv3GX26x8yoZbpsmQFzeZxcA3g/UpuolC/7bXsJ VE/nhPwrPijaDWhS0EYsXQ9FVLK6CRNhJEhBZ50qRriTpLpITtf4JxmEJ8vCc3EHYCS41e+morS ZwsyzJIq3DLXPGqXbwNdzAnjns0boVpzwq5NDhEsx5jCbWwuLhU7RAtEQ31CmhQEDN4GmBaPY1H IXW9LKo3ehM4HostTzHmarjIZn4fQPXzHII/axcSnVw6WZ8e7jhweY+/A85Wjq2bstV4f3zB7lE DbGV0EvhQaD7snybIJ8Y6MfexfB9+o03MwT8S7VyPh+vSLCLfZxw3qRhq2sX6v6wBigIU0mVcWU mbzWHH+jS4rhna2F1YV4OhbzRmUoHWxeFvnOXAEQzaZxudO05KLRkpDkmWvbHd0EI= X-Received: by 2002:a5d:6f0c:0:b0:47e:9f16:c0bf with SMTP id ffacd0b85a97d-47fec63e205mr36677851f8f.30.1786088450464; Fri, 07 Aug 2026 00:40:50 -0700 (PDT) Received: from jp-linux.Home ([2001:8a0:f59c:a900:2600:fba1:8d1e:1692]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-480021f90f8sm2819904f8f.26.2026.08.07.00.40.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 00:40:49 -0700 (PDT) From: =?UTF-8?q?Jo=C3=A3o=20Peixoto?= To: gregkh@linuxfoundation.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: jose@osyx.tech, davidmcerdeira@osyx.tech, corbet@lwn.net, skhan@linuxfoundation.org, catalin.marinas@arm.com, will@kernel.org, linux@armlinux.org.uk, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, andrew.jones@oss.qualcomm.com, rdunlap@infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-riscv@lists.infradead.org Subject: [RFC PATCH v3 1/6] dt-bindings: bao: add IPC shared-memory device Date: Fri, 7 Aug 2026 08:39:28 +0100 Message-ID: <7fe7fbabed8d932a9d8d82e64c9c4d76100964c6.1786010512.git.jpeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add the device-tree binding for the Bao hypervisor IPC shared-memory device, used by a Bao guest to exchange data with a peer guest over a shared-memory region. Co-developed-by: Jos=C3=A9 Martins Signed-off-by: Jos=C3=A9 Martins Co-developed-by: David Cerdeira Signed-off-by: David Cerdeira Signed-off-by: Jo=C3=A3o Peixoto --- v3: - Describe the read and write channels through reg/reg-names instead of the custom read-channel/write-channel properties; drop those properties and t= he "id" property; add a vendor "bao,id" for the hypercall channel id; use a generic node name (shmem@...) (Krzysztof Kozlowski). - Clarify the "bao" vendor-prefix description. - Subject: drop the redundant trailing "binding" (Krzysztof Kozlowski). - Add Jos=C3=A9's and David's Co-developed-by/Signed-off-by. .../devicetree/bindings/bao/bao,ipcshmem.yaml | 59 +++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.yaml | 2 + 2 files changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/bao/bao,ipcshmem.yaml diff --git a/Documentation/devicetree/bindings/bao/bao,ipcshmem.yaml b/Docu= mentation/devicetree/bindings/bao/bao,ipcshmem.yaml new file mode 100644 index 000000000000..60947150d576 --- /dev/null +++ b/Documentation/devicetree/bindings/bao/bao,ipcshmem.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bao/bao,ipcshmem.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bao Hypervisor IPC Shared Memory Device + +maintainers: + - Jo=C3=A3o Peixoto + - Jos=C3=A9 Martins + - David Cerdeira + +description: | + Shared-memory device exposed by the Bao hypervisor to a guest so that it + can exchange data with a peer guest. The hypervisor provides two + contiguous memory regions, one the guest reads from (written by the peer) + and one the guest writes to (read by the peer). A write is signalled to + the peer through a hypercall identified by bao,id. + +properties: + compatible: + const: bao,ipcshmem + + reg: + items: + - description: region read by this guest and written by the peer + - description: region written by this guest and read by the peer + + reg-names: + items: + - const: read + - const: write + + bao,id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Hypervisor-assigned identifier of this shared-memory channel. The + guest passes it to the Bao hypercall that notifies the peer of a + write, so it must match the identifier configured for the channel in + the hypervisor. + +required: + - compatible + - reg + - reg-names + - bao,id + +additionalProperties: false + +examples: + - | + shmem@f0000000 { + compatible =3D "bao,ipcshmem"; + reg =3D <0xf0000000 0x2000>, + <0xf0002000 0x2000>; + reg-names =3D "read", "write"; + bao,id =3D <0>; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Docum= entation/devicetree/bindings/vendor-prefixes.yaml index 396044f368e7..b11b3dd995a5 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -231,6 +231,8 @@ patternProperties: description: Shenzhen AZW Technology Co., Ltd. "^baikal,.*": description: BAIKAL ELECTRONICS, JSC + "^bao,.*": + description: Bao Project (https://github.com/bao-project) "^bananapi,.*": description: BIPAI KEJI LIMITED "^beacon,.*": --=20 2.43.0 From nobody Tue Sep 29 13:18:14 2026 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.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 5B858381EAB for ; Fri, 7 Aug 2026 07:40:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088458; cv=none; b=d5yQQ4504EoU8i6WBSTeOuj7xVv8vlA8erzKmajACw8Nj+wxREAWICBKiUT/R0I+7Hwee9UAxp8pg6RdY7uZklogf0+HT705B8LxRfmll/fMaM0VkY6u6q8BxF+00fhvcuyVWMX1GjRg8g4djI9ytPSRzQwcLVYMfuynMUof3yI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088458; c=relaxed/simple; bh=RI1ztS0zrf7hxOtsfyFJq+LgY2SP3cAglteT/oakdkw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=O9SY9+rckFggERtLyZ4NI1n/Z3Jde4lf54KIIRNOvwPZk6Y7b9kDfYVPx5DfmIRFpuB+0mQXulAPEzmIG4+7z08NtdRgvWkzvBZ7uR7hw2JUOyw7cgrDwToa6sx6n2CwZP37MGV1mZkdEH/O7MkgjNFKd1WHhzpmHINbjX0QfS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=none smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b=hPVcvPj9; arc=none smtp.client-ip=209.85.221.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b="hPVcvPj9" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-47fe89fb333so1845120f8f.3 for ; Fri, 07 Aug 2026 00:40:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20251104.gappssmtp.com; s=20251104; t=1786088453; x=1786693253; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=6TawWsmxD8SDGcsqSwYUOGoy90jC/5REKfiUF4xQzCg=; b=hPVcvPj9OHaD8JFtWm6fW/rr4Byqb8yZG3QPwJ2RiESO0fwY83TIyc6TGD+PFY8RDz EpAKgpHDBt//g7G9GR4KpvaCzneXBPFuTLFUFxvdoYvUch9MR+nrjeKQsXqjPIBrgzYZ cHBodPFaEkzAWdgEojp0e36zvnId2zAe9iAUF+b08OUUxKH8Dtr/wXWydoJBUSXi+ZxY AxvT5gsdNUUaGWFJqtw9nxnkG9XPvGADPHeX+78Ow/scMVJ59rXWgOXalM89XP7BN1Ph yZoNjuBmH5TeFD1TQSeU7h+Kz24vyazI1sNXDLwF08x3SpbumDsgxx0dnxedboiB70// 39gQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786088453; x=1786693253; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=6TawWsmxD8SDGcsqSwYUOGoy90jC/5REKfiUF4xQzCg=; b=PYLobBZ8MlpEUa+IaXDOlk7lxBg4vzJF+dteFi9W0+Ee22SUxfiCdXGWEkrgOAdBX8 oObaU4h8EyMCxKl4ZYSTnZOH33k99A5wDFnq1iG4MDQ7i277m8S35GvL0l5UT9053Rmt PX+JiK/ZVaJ/Ipyf9jkDr6Ck5B17RfFMMnQ2SfA7eKVOtZcpflNJ3e8p42GvySnz1Lbc WfaIactgkGx++XtvaW5yCEkifk17sB3nMZNRCGG+VEwmP23YRFtLAzPbHZDc3cK+lmeJ 83oLKP1U1O/PSXnt+gPqZsaWR/adYk5CH8tJY9MRVbG89fi/sv4IIHT39Xckv3P4HSKQ mhNA== X-Forwarded-Encrypted: i=1; AHgh+Rqsgcan8AQzUTTEKzBkfqRzlmFVQiT2ATeZtBRczr65Ze8LH8UTZKEb+H98W5sM+D+hW3aTgi8/ma915Gc=@vger.kernel.org X-Gm-Message-State: AOJu0YzrYYsmr3cwfnqmerqBTKp0B6ZfyJ+yVw9KkGWNjMbjdSm2wfTE iZRimCeqCN4qN6Owq+ELaDLvbwmT+KekHhjzwhyaCv2CPJNR+2FFuXDr0x7X9gdksGdA X-Gm-Gg: AR+sD116+WjeTgpCE4oVPxXSl0KqLtXRO/vJ+9BxJUj3DFP1/2hBk3yYH1rGtoTqheY XhjLbL0TN1ufnoiXI6zZ3qRENo5qVDnjJduBnz2l5FZPOQIYWtrtVSs/mUQYz/MLcBgTTDIraaY VINReTiLjQgTRhVxSUFme1o7gizEbUc2NFdvbhhHYk8k6rtrxJKIIgvDWKFmTsq2dHRlYB1+30M jFe3kKlS9IP018ga6v36xOMl09VJN7PHY2ntK1Vi8/4Yb2tmSvUwbVmBNE+CNVK9UvBNgUHemxO 6eO7PO9a+Cg7Tk/eAQQT2iXbuMc4ls/VbQVk7N1UjFGToTlSJuSbDsgEK2e2G7Iq9Qbz5fccAD7 u/yBd/ld7NohrIJNlcL1mKHg6R9yR31KJENaI2IwTGJeT6s3IX/8mWcfs99k4DsQLnEHF7iewvR BZI8RQA7CQGwpDFfgxr8RM1E+uEqj1JVuvvnOjdAeq+eDOWvpyOcz3g1q4EIwIwO4= X-Received: by 2002:a5d:64c6:0:b0:47f:e742:91dc with SMTP id ffacd0b85a97d-47fec4f1448mr31780734f8f.7.1786088453591; Fri, 07 Aug 2026 00:40:53 -0700 (PDT) Received: from jp-linux.Home ([2001:8a0:f59c:a900:2600:fba1:8d1e:1692]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-480021f90f8sm2819904f8f.26.2026.08.07.00.40.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 00:40:52 -0700 (PDT) From: =?UTF-8?q?Jo=C3=A3o=20Peixoto?= To: gregkh@linuxfoundation.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: jose@osyx.tech, davidmcerdeira@osyx.tech, corbet@lwn.net, skhan@linuxfoundation.org, catalin.marinas@arm.com, will@kernel.org, linux@armlinux.org.uk, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, andrew.jones@oss.qualcomm.com, rdunlap@infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-riscv@lists.infradead.org Subject: [RFC PATCH v3 2/6] virt: bao: add IPC shared-memory driver Date: Fri, 7 Aug 2026 08:39:29 +0100 Message-ID: <33a72238392b1feb519d5721b5aacf693929e15c.1786010512.git.jpeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add a driver that lets guests running on the Bao static-partitioning hypervisor communicate through shared memory. Each guest is assigned a read and a write region within a shared-memory area described in the device tree. Userspace accesses the regions through a misc character device using read(), write() and mmap(). A write() notifies the peer guest through an architecture-specific hypercall (HVC on arm/arm64, SBI ecall on RISC-V). Co-developed-by: Jos=C3=A9 Martins Signed-off-by: Jos=C3=A9 Martins Co-developed-by: David Cerdeira Signed-off-by: David Cerdeira Signed-off-by: Jo=C3=A3o Peixoto --- v3: - Map the read and write regions from the two reg entries (by reg-name) instead of parsing read-channel/write-channel offsets; read the channel id from "bao,id"; mmap() now maps per region. - Drop the noisy dev_info() on successful probe. - Do the shared-memory range arithmetic in u64 to avoid a u32 overflow. - Fix the Kconfig help-text indentation (Randy Dunlap). - Add Jos=C3=A9's and David's Co-developed-by/Signed-off-by. arch/arm/include/asm/bao.h | 31 ++++ arch/arm64/include/asm/bao.h | 31 ++++ arch/riscv/include/asm/bao.h | 31 ++++ drivers/virt/Kconfig | 2 + drivers/virt/Makefile | 1 + drivers/virt/bao/Kconfig | 3 + drivers/virt/bao/Makefile | 3 + drivers/virt/bao/ipcshmem/Kconfig | 10 ++ drivers/virt/bao/ipcshmem/Makefile | 3 + drivers/virt/bao/ipcshmem/ipcshmem.c | 231 +++++++++++++++++++++++++++ 10 files changed, 346 insertions(+) create mode 100644 arch/arm/include/asm/bao.h create mode 100644 arch/arm64/include/asm/bao.h create mode 100644 arch/riscv/include/asm/bao.h create mode 100644 drivers/virt/bao/Kconfig create mode 100644 drivers/virt/bao/Makefile create mode 100644 drivers/virt/bao/ipcshmem/Kconfig create mode 100644 drivers/virt/bao/ipcshmem/Makefile create mode 100644 drivers/virt/bao/ipcshmem/ipcshmem.c diff --git a/arch/arm/include/asm/bao.h b/arch/arm/include/asm/bao.h new file mode 100644 index 000000000000..ba64d1a18f91 --- /dev/null +++ b/arch/arm/include/asm/bao.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Bao Hypervisor Hypercall Interface + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#ifndef __ASM_ARM_BAO_H +#define __ASM_ARM_BAO_H + +#include + +static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, + unsigned long ipcshmem_id) +{ + struct arm_smccc_res res; + + arm_smccc_hvc(ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, + ARM_SMCCC_OWNER_VENDOR_HYP, + hypercall_id), + ipcshmem_id, 0, 0, 0, 0, 0, 0, &res); + + return res.a0; +} + +#endif /* __ASM_ARM_BAO_H */ diff --git a/arch/arm64/include/asm/bao.h b/arch/arm64/include/asm/bao.h new file mode 100644 index 000000000000..ab9b283168e3 --- /dev/null +++ b/arch/arm64/include/asm/bao.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Bao Hypervisor Hypercall Interface + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#ifndef __ASM_ARM64_BAO_H +#define __ASM_ARM64_BAO_H + +#include + +static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, + unsigned long ipcshmem_id) +{ + struct arm_smccc_res res; + + arm_smccc_hvc(ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, + ARM_SMCCC_OWNER_VENDOR_HYP, + hypercall_id), + ipcshmem_id, 0, 0, 0, 0, 0, 0, &res); + + return res.a0; +} + +#endif /* __ASM_ARM64_BAO_H */ diff --git a/arch/riscv/include/asm/bao.h b/arch/riscv/include/asm/bao.h new file mode 100644 index 000000000000..d2c79a6a4ade --- /dev/null +++ b/arch/riscv/include/asm/bao.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Bao Hypervisor Hypercall Interface + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#ifndef __ASM_RISCV_BAO_H +#define __ASM_RISCV_BAO_H + +#include + +#define BAO_SBI_EXT_ID 0x08000ba0 + +static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, + unsigned long ipcshmem_id) +{ + struct sbiret ret; + + ret =3D sbi_ecall(BAO_SBI_EXT_ID, hypercall_id, ipcshmem_id, 0, 0, 0, 0, + 0); + + return ret.error; +} + +#endif /* __ASM_RISCV_BAO_H */ diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig index 52eb7e4ba71f..cb98c4c52fd1 100644 --- a/drivers/virt/Kconfig +++ b/drivers/virt/Kconfig @@ -47,6 +47,8 @@ source "drivers/virt/nitro_enclaves/Kconfig" =20 source "drivers/virt/acrn/Kconfig" =20 +source "drivers/virt/bao/Kconfig" + endif =20 source "drivers/virt/coco/Kconfig" diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile index f29901bd7820..623a671f8711 100644 --- a/drivers/virt/Makefile +++ b/drivers/virt/Makefile @@ -10,3 +10,4 @@ obj-y +=3D vboxguest/ obj-$(CONFIG_NITRO_ENCLAVES) +=3D nitro_enclaves/ obj-$(CONFIG_ACRN_HSM) +=3D acrn/ obj-y +=3D coco/ +obj-$(CONFIG_BAO_SHMEM) +=3D bao/ diff --git a/drivers/virt/bao/Kconfig b/drivers/virt/bao/Kconfig new file mode 100644 index 000000000000..4f7929d57475 --- /dev/null +++ b/drivers/virt/bao/Kconfig @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +source "drivers/virt/bao/ipcshmem/Kconfig" diff --git a/drivers/virt/bao/Makefile b/drivers/virt/bao/Makefile new file mode 100644 index 000000000000..68f5d3f282c4 --- /dev/null +++ b/drivers/virt/bao/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_BAO_SHMEM) +=3D ipcshmem/ diff --git a/drivers/virt/bao/ipcshmem/Kconfig b/drivers/virt/bao/ipcshmem/= Kconfig new file mode 100644 index 000000000000..b789e5ea1264 --- /dev/null +++ b/drivers/virt/bao/ipcshmem/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +config BAO_SHMEM + tristate "Bao hypervisor shared memory support" + help + This enables support for Bao shared memory communication. + It allows the kernel to interface with guests running under + the Bao hypervisor, providing a character device interface + for exchanging data through dedicated shared-memory regions. + + If unsure, say N. diff --git a/drivers/virt/bao/ipcshmem/Makefile b/drivers/virt/bao/ipcshmem= /Makefile new file mode 100644 index 000000000000..e027dcdb06aa --- /dev/null +++ b/drivers/virt/bao/ipcshmem/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_BAO_SHMEM) +=3D bao.o +bao-objs +=3D ipcshmem.o diff --git a/drivers/virt/bao/ipcshmem/ipcshmem.c b/drivers/virt/bao/ipcshm= em/ipcshmem.c new file mode 100644 index 000000000000..0d46d89ee788 --- /dev/null +++ b/drivers/virt/bao/ipcshmem/ipcshmem.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bao Hypervisor IPC Through Shared-memory Driver + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#define BAO_IPCSHMEM_NAME_LEN 16 + +/* IPC through shared-memory hypercall ID */ +#define BAO_IPCSHMEM_HYPERCALL_ID 0x1 + +struct bao_ipcshmem { + struct miscdevice miscdev; + u32 id; + char label[BAO_IPCSHMEM_NAME_LEN]; + void *read_base; + phys_addr_t read_phys; + size_t read_size; + void *write_base; + phys_addr_t write_phys; + size_t write_size; +}; + +static int bao_ipcshmem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct bao_ipcshmem *bao =3D filp->private_data; + unsigned long vsize =3D vma->vm_end - vma->vm_start; + unsigned long offset =3D vma->vm_pgoff << PAGE_SHIFT; + phys_addr_t region_phys; + size_t region_size; + + if (!vsize) + return -EINVAL; + + /* + * The read region is exposed at offset 0 and the write region right + * after it. A single mapping cannot span both regions, since they are + * not guaranteed to be physically contiguous. + */ + if (offset < bao->read_size) { + region_phys =3D bao->read_phys; + region_size =3D bao->read_size; + } else if (offset < bao->read_size + bao->write_size) { + offset -=3D bao->read_size; + region_phys =3D bao->write_phys; + region_size =3D bao->write_size; + } else { + return -EINVAL; + } + + if (vsize > region_size - offset) + return -EINVAL; + + region_phys +=3D offset; + if (!PAGE_ALIGNED(region_phys)) + return -EINVAL; + + return remap_pfn_range(vma, vma->vm_start, region_phys >> PAGE_SHIFT, + vsize, vma->vm_page_prot); +} + +static ssize_t bao_ipcshmem_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + struct bao_ipcshmem *bao =3D filp->private_data; + size_t available; + + if (*ppos >=3D bao->read_size) + return 0; + + available =3D bao->read_size - *ppos; + count =3D min(count, available); + + if (copy_to_user(buf, bao->read_base + *ppos, count)) + return -EFAULT; + + *ppos +=3D count; + return count; +} + +static ssize_t bao_ipcshmem_write(struct file *filp, const char __user *bu= f, + size_t count, loff_t *ppos) +{ + struct bao_ipcshmem *bao =3D filp->private_data; + size_t available; + + if (*ppos >=3D bao->write_size) + return 0; + + available =3D bao->write_size - *ppos; + count =3D min(count, available); + + if (copy_from_user(bao->write_base + *ppos, buf, count)) + return -EFAULT; + + *ppos +=3D count; + + /* Notify Bao hypervisor */ + bao_ipcshmem_hypercall(BAO_IPCSHMEM_HYPERCALL_ID, bao->id); + + return count; +} + +static int bao_ipcshmem_open(struct inode *inode, struct file *filp) +{ + struct bao_ipcshmem *bao; + + bao =3D container_of(filp->private_data, struct bao_ipcshmem, miscdev); + filp->private_data =3D bao; + + return 0; +} + +static int bao_ipcshmem_release(struct inode *inode, struct file *filp) +{ + filp->private_data =3D NULL; + return 0; +} + +static const struct file_operations bao_ipcshmem_fops =3D { + .owner =3D THIS_MODULE, + .read =3D bao_ipcshmem_read, + .write =3D bao_ipcshmem_write, + .mmap =3D bao_ipcshmem_mmap, + .open =3D bao_ipcshmem_open, + .release =3D bao_ipcshmem_release, +}; + +static int bao_ipcshmem_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct device_node *np =3D dev->of_node; + struct resource *read_res; + struct resource *write_res; + struct bao_ipcshmem *bao; + u32 id; + int ret; + + read_res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "read"); + if (!read_res) { + dev_err(dev, "missing 'read' shared memory region\n"); + return -ENODEV; + } + + write_res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "write"); + if (!write_res) { + dev_err(dev, "missing 'write' shared memory region\n"); + return -ENODEV; + } + + ret =3D of_property_read_u32(np, "bao,id", &id); + if (ret) { + dev_err(dev, "missing or invalid 'bao,id' property\n"); + return ret; + } + + bao =3D devm_kzalloc(dev, sizeof(*bao), GFP_KERNEL); + if (!bao) + return -ENOMEM; + + bao->read_base =3D devm_memremap(dev, read_res->start, + resource_size(read_res), MEMREMAP_WB); + if (IS_ERR(bao->read_base)) + return PTR_ERR(bao->read_base); + + bao->write_base =3D devm_memremap(dev, write_res->start, + resource_size(write_res), MEMREMAP_WB); + if (IS_ERR(bao->write_base)) + return PTR_ERR(bao->write_base); + + bao->id =3D id; + bao->read_phys =3D read_res->start; + bao->read_size =3D resource_size(read_res); + bao->write_phys =3D write_res->start; + bao->write_size =3D resource_size(write_res); + + scnprintf(bao->label, BAO_IPCSHMEM_NAME_LEN, "baoipc%u", id); + + bao->miscdev.minor =3D MISC_DYNAMIC_MINOR; + bao->miscdev.name =3D bao->label; + bao->miscdev.fops =3D &bao_ipcshmem_fops; + bao->miscdev.parent =3D dev; + + ret =3D misc_register(&bao->miscdev); + if (ret) { + dev_err(dev, "failed to register misc device: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, bao); + + return 0; +} + +static void bao_ipcshmem_remove(struct platform_device *pdev) +{ + struct bao_ipcshmem *bao =3D platform_get_drvdata(pdev); + + misc_deregister(&bao->miscdev); +} + +static const struct of_device_id of_bao_ipcshmem_match[] =3D { + { .compatible =3D "bao,ipcshmem" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_bao_ipcshmem_match); + +static struct platform_driver bao_ipcshmem_driver =3D { + .probe =3D bao_ipcshmem_probe, + .remove =3D bao_ipcshmem_remove, + .driver =3D { + .name =3D "baoipc", + .of_match_table =3D of_bao_ipcshmem_match, + }, +}; + +module_platform_driver(bao_ipcshmem_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Cerdeira "); +MODULE_AUTHOR("Jos=C3=A9 Martins "); +MODULE_AUTHOR("Jo=C3=A3o Peixoto "); +MODULE_DESCRIPTION("Bao Hypervisor IPC Through Shared-memory Driver"); --=20 2.43.0 From nobody Tue Sep 29 13:18:14 2026 Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.45]) (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 E93C83F6C27 for ; Fri, 7 Aug 2026 07:41:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088464; cv=none; b=nLPqTeTOS5Gme1EXpSWSaijY0Q4z3OR8az4ffG8UXs4MH7sJmz2CNXVu0RZquB1t0M6+EePQeNlBPE+aENRHCTZHYPoR6rt7nkOkbNm09H0rfc7MVnFy6qX2ePE0kI5Zl54oB3E4ZzKkwckvCCW9lk0pikF33EXLRd1tPeGT5Mg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088464; c=relaxed/simple; bh=ScMM9GxeeV5e3+9VHl4c/oHNnOx6+btkMBr+c9U/TL8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qPjyHsfxlaZqDDGyL2VcUb/RPoT2xdbaHgAWlIx+wLNCCB7/QXDvgl3MxUGGA9SmABUraMU5uwZpe+MXZedyoCvPADcaAn9wGuO4T3LdiOLsdWTTMN8udotEj2hYRt8yl/gjSDuwoPe/lM1c3h27kDVSDVqHFRj2EyeuE2moRzA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=none smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b=mk0Q56e6; arc=none smtp.client-ip=209.85.221.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b="mk0Q56e6" Received: by mail-wr1-f45.google.com with SMTP id ffacd0b85a97d-480033bdcf4so108091f8f.2 for ; Fri, 07 Aug 2026 00:41:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20251104.gappssmtp.com; s=20251104; t=1786088461; x=1786693261; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=hJeYOt804451rzDFy0He69vDtZSRNQGd+4J9yYwV0Co=; b=mk0Q56e6Cy2LvW00Ni9/Ph0MHah/nwulhc1nGETsd9S6PZMKaq+U46sXC9IM/iQGhW c7cuOu7s3+WZXAU41LLe6mUcA2SHS2nOOUptoPLoOZoGJW6isLn3K3fciN1WMyfzwHcI Dq7oAtwYDYbLGsAICWl4ZFITQActjNWF5pBG6IJZFwaLrmnGc3ld8lRl56FzOSC8Z+i5 RKHJeulm2dKN0txissaZQOev3FGwy6z8/jtoZp72I3W5rivoqglkHkPGCtU8fhYAkZbM RFOa6I2BkTz3y918t86aJd5Rh7WDSqjCdLQkxuUHrK9UnsxooQzBym0zGoL3Kn2qih7W X18w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786088461; x=1786693261; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=hJeYOt804451rzDFy0He69vDtZSRNQGd+4J9yYwV0Co=; b=in2oK7Alpk4npCN+OCOoFLZwFbSHsVhUt/IeDqLOf8G8mcXWZ7rvC2GAeJHox2XMjO ccJ06qptcD/o1knE9tn/iIJjYT4MQSwitUL4U/T+DcZRt+Z1rCDnBbpxpnBRkQzas6Kh ehzlqVu4wpH68b5AnSADlPinLn4A/EgpSsuJzgUrj7Vah3f3JrYgBlgJPcd/Os81ZFqm FmjNW8+m8l/e/6UMoUoMkMHWRCi+mKn7U9KVIB4VMWtkJVIJAi69oAXuk83xop5sUwZt 41qWe+G0potXopwJTEh8lgD/ut2UeIY5fqexg3wYvlBk36+XWd6RWjpUDAX6Imh/UiKx VlXg== X-Forwarded-Encrypted: i=1; AHgh+Rpju0u6bxgBcapMeI7jAAhAzAF7PEhsHn6aSL1QTuAIJ0vnU0Pu+Z3yVHTA0NRv+nQDA7iUAsPmOHmiKlY=@vger.kernel.org X-Gm-Message-State: AOJu0Yy2bJgGjiFYUVXXNhtwm4juX/7q0f1UtNU5Xe5Hz4+sW9V+ETVf 8AI+k41Pz7l8hfC5Ic7VEhyao9OmCKWjdjboI8qP3+I5NN0NKZca452cGFVzMBCiHWrw X-Gm-Gg: AR+sD104WQB++owOJqV7uBMoRH3dL3lRpRgcWPbPbl6NZV7mLQkDNWexGgFm5100T0c ScESCic2D6cmR1PBunB3i15JAHEihWJM2TpMHkXzH7LUzyqA5EBMOMWP6dIGbjf88VCF0Vh52dV 4+c0V8HZfwlBaFuQ2CwTqLzT36ox2Rfzr7MtdnsJp+7qgsMLK7qATc4C9bRfZN7vpDv05EYdunq qemqjbLkodpFLj0mDxsdT3eIRyAWnqhsGiSYwF3mYI7JmpmGvWW/NyFadkh2DT9Ky6zSpdUs2dP Uty0lity0hjxXYVtY1yqbvmIR0si1av97l1NwiJCIi2+FtDBUVQc45lYYJcBNBr3d94umevKHxV wlXwqg+/p2NyeON/d8GgGwFYoA/cCVMmw2bbWKfbqZOoh+Yun11YKQjAiXWP5d2uWvU2AfKbyWu dn8n+DKt6aCBF9S6Oz4eVIlAJs9xzNWoUkYJnK0JkgrDktkQhb5iYTek8aOgG+pdc= X-Received: by 2002:a05:6000:2586:b0:477:3986:9b54 with SMTP id ffacd0b85a97d-47fec62e2b4mr28868834f8f.20.1786088461227; Fri, 07 Aug 2026 00:41:01 -0700 (PDT) Received: from jp-linux.Home ([2001:8a0:f59c:a900:2600:fba1:8d1e:1692]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-480021f90f8sm2819904f8f.26.2026.08.07.00.40.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 00:41:00 -0700 (PDT) From: =?UTF-8?q?Jo=C3=A3o=20Peixoto?= To: gregkh@linuxfoundation.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: jose@osyx.tech, davidmcerdeira@osyx.tech, corbet@lwn.net, skhan@linuxfoundation.org, catalin.marinas@arm.com, will@kernel.org, linux@armlinux.org.uk, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, andrew.jones@oss.qualcomm.com, rdunlap@infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-riscv@lists.infradead.org Subject: [RFC PATCH v3 3/6] dt-bindings: bao: add I/O dispatcher device Date: Fri, 7 Aug 2026 08:39:30 +0100 Message-ID: <41e65cbe88021964afe55d9e3884ebc199928264.1786010512.git.jpeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add the device-tree binding for the Bao I/O dispatcher, present in backend VMs that service paravirtualised (VirtIO) I/O on behalf of frontend guests. Co-developed-by: Jos=C3=A9 Martins Signed-off-by: Jos=C3=A9 Martins Co-developed-by: David Cerdeira Signed-off-by: David Cerdeira Signed-off-by: Jo=C3=A3o Peixoto --- v3: - Model one node per backend device (single reg + single interrupt + "bao,id") instead of a single node describing many devices, following the gunyah and Mediatek Genio bindings (Krzysztof Kozlowski). - Add Jos=C3=A9's and David's Co-developed-by/Signed-off-by. .../bindings/bao/bao,io-dispatcher.yaml | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/devicetree/bindings/bao/bao,io-dispatcher= .yaml diff --git a/Documentation/devicetree/bindings/bao/bao,io-dispatcher.yaml b= /Documentation/devicetree/bindings/bao/bao,io-dispatcher.yaml new file mode 100644 index 000000000000..f118c6d486a6 --- /dev/null +++ b/Documentation/devicetree/bindings/bao/bao,io-dispatcher.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bao/bao,io-dispatcher.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bao Hypervisor I/O Dispatcher Device + +maintainers: + - Jo=C3=A3o Peixoto + - Jos=C3=A9 Martins + - David Cerdeira + +description: + Backend device exposed by the Bao hypervisor to a guest that services + paravirtualised (VirtIO) I/O on behalf of a frontend guest. Each device + owns one contiguous shared-memory region used to exchange I/O buffers + with its frontend, and one interrupt the hypervisor raises to signal a + pending I/O request. A backend guest that services several frontends + instantiates one node per backend device. + +properties: + compatible: + const: bao,io-dispatcher + + reg: + maxItems: 1 + description: + Shared-memory region used to exchange I/O buffers with the frontend. + + interrupts: + maxItems: 1 + description: + Interrupt raised by the hypervisor to signal a pending I/O request. + + bao,id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Hypervisor-assigned identifier of the backend device model. It must + match the identifier configured for the device model in the + hypervisor. + +required: + - compatible + - reg + - interrupts + - bao,id + +additionalProperties: false + +examples: + - | + shmem@50000000 { + compatible =3D "bao,io-dispatcher"; + reg =3D <0x50000000 0x01000000>; + interrupts =3D <0x0 0x08 0x1>; + bao,id =3D <0>; + }; --=20 2.43.0 From nobody Tue Sep 29 13:18:14 2026 Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.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 6D6D536AB4D for ; Fri, 7 Aug 2026 07:41:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088473; cv=none; b=j4FrABVswh/RpI249onsT2vCrJK+3sfzdCIT91sawduvxxke2MUb7eTEdbjt974BXyWQrE7cOfdbgp8sJPYeyN2nM4wwCNUSU9hr5ed7ZtHL/N3wGy2NiEkLj7A+FoJ42yleuLPjjPZtZs4wd5YKJVs/wEhauukIKh0iBybI9EE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088473; c=relaxed/simple; bh=q4/deaozqshmcsHd+u9E67lf771K2UDo81aK6DiwlIg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bEWwFg/jWu9TE6dH9Otk9XGXjf+ChxKC4Ct/EBulp4i4hrrHeFId3Vo1o0FzQqQ/bQ5Dx7U6RlDvDfGlRgrhq6cln2D3TncpOycNqMoyJEHKbw1qV8RKnI9NH6z0BU/l22yL/G6i82IIMfn1KebSoQz9ilbBQ1Ttdfniet2aQU4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=none smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b=Jga6nnU7; arc=none smtp.client-ip=209.85.221.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b="Jga6nnU7" Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-47f84023916so2793673f8f.3 for ; Fri, 07 Aug 2026 00:41:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20251104.gappssmtp.com; s=20251104; t=1786088465; x=1786693265; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=Zf7OKH4SxpZlk0E2lKNTLJ5v90lmRZkdQg/cKzqxaY8=; b=Jga6nnU71V4HlrirYpkTJR9iZPqSgabNsIGQLSh+7dMt4C6zBaGSFe9zdMS+Czkd1a J7eLWiNr3N2h92EkWOmxbyWeICS7KlcYWg+J9bTBQzRLHBUTemBrnf49tXjorb4xnJvC WBrfA/uiN0CC9+srcz3y/Ij+OlRNaXKxDSBfcFyG0fowEaDquErpr6xUiR/tgzZHGZyh rYifeqd7YwULHPUauK92tD5JOdPcdRy+9Pm4wJecnwZPohAeydNR7bZnrmWliRHytpGa 8w2bqyyCH67tK2lmW2FPGoWqHpUHUd7/mBfob86QNK3sdFuXYM9VMycylFUuRh5gWfHo txlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786088465; x=1786693265; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Zf7OKH4SxpZlk0E2lKNTLJ5v90lmRZkdQg/cKzqxaY8=; b=CfmdDatz0rGIqWITBaNy7t4BP0jqTOlfRZ0lS39q+9Affg3z8c2uaUvBYFx4nC/n5h 11jblbTT6E3nUGF8vyKCLsdhN9tZQHtio/onaEgeu4VKMU/3BJOxTb1XxBSXHgLL3rcj XWN3QfyrHeowjyosJPWCHt04eFIEn3MSc+p1ZsIo56wBGrYr0UwFSimj1010bu0UU44N JDy3jyaGugvAnEqtRq/qdm8tYk9o6AyhD04opYpGAIOBhCezYKES2dfrSIvhEiYM1GA5 X6MT9CwpKyjqpsfcRQ0p3gOG+t5KghKh5o6Gj8p22WVzaqRrCjKsAbc0SfrqTDr3qPsV 3VwQ== X-Forwarded-Encrypted: i=1; AHgh+RqOEuyz555GjVidxPu7LrFIOWYYA2rjppkoKL652/LC/GXoSihORS/rf+7hrsR+a+nbLkJG63zmzuyrhck=@vger.kernel.org X-Gm-Message-State: AOJu0YwFu7IQYX3Lm9FZbl0cVC2lNVoGtXWLwF2mMXi7XkPvmjLrnyZS mBmwaGbQJ+9JUh0IOiELmiQYipEdBwH26ToEwX1zMSYADqaZEXjML64c8DZtu+uY+5mq X-Gm-Gg: AR+sD10ADJ9UJhXwZRm94WgxjlcZTKb82DF+pdVKSKi1AeN8cuo7FUUiPaZ7EPdtmcS sVVXhwxCi+WehglTN8DBtaFSKLhWmrohC7SC64NxmHdCQ/rmozT5b463zkgah9h3NQnJQEwzm/n v8b8RseszG1rRQuAi4g+s7wyrYttrWN/krj+KGRZ6Ro5utrm+YJOXZ0MKC075nmMq5eydhKk1wN Z6UIz2xYbLiaB4UurpHCREG4HHaajPyl/mrhvi8X+4KuGGIiKNC/+rbbcoUFv5Zi2/+GKOM5Hcq shYmGlBzEnY0OJxsKGM+jfzgLPEDJFTPgWXkJT/CjYrt5NZH+2aiK6aS1LFFrMZlWP8aziNU42H CAhbCYxTStL33n3MDoqXn44QzQQLZP9BLqhi4m509IfGBUnoD6P07BbbaimgQ21dGlnoVaMtNV6 8jdiM/ryEi7HIvKsx+ZJMmJhxqmwMc2R+b3YNFHLsQ3uFT7XCyEtz3AKFItg3jenIE X-Received: by 2002:a05:6000:491e:b0:47d:ee9d:90c8 with SMTP id ffacd0b85a97d-47fec4e2910mr37918191f8f.3.1786088464244; Fri, 07 Aug 2026 00:41:04 -0700 (PDT) Received: from jp-linux.Home ([2001:8a0:f59c:a900:2600:fba1:8d1e:1692]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-480021f90f8sm2819904f8f.26.2026.08.07.00.41.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 00:41:03 -0700 (PDT) From: =?UTF-8?q?Jo=C3=A3o=20Peixoto?= To: gregkh@linuxfoundation.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: jose@osyx.tech, davidmcerdeira@osyx.tech, corbet@lwn.net, skhan@linuxfoundation.org, catalin.marinas@arm.com, will@kernel.org, linux@armlinux.org.uk, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, andrew.jones@oss.qualcomm.com, rdunlap@infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-riscv@lists.infradead.org Subject: [RFC PATCH v3 4/6] virt: bao: add I/O dispatcher driver Date: Fri, 7 Aug 2026 08:39:31 +0100 Message-ID: <2190b6e083a2f2e0485b27e5e203647189bb1d1d.1786010512.git.jpeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add the Bao I/O dispatcher, used by backend VMs to service I/O on behalf of frontend guests. It bridges Bao's Remote I/O mechanism to userspace VirtIO backend device models. Each backend device has a contiguous shared-memory region for exchanging I/O buffers with its frontend and an interrupt the hypervisor uses to signal pending requests. Userspace drives the dispatcher through a set of ioctls on a misc character device. Co-developed-by: Jos=C3=A9 Martins Signed-off-by: Jos=C3=A9 Martins Co-developed-by: David Cerdeira Signed-off-by: David Cerdeira Signed-off-by: Jo=C3=A3o Peixoto --- v3: - Bind one platform device per device model and expose one /dev/bao-dmX eac= h; drop the global DM list and its locking, the anonymous-inode fd, and the dispatcher indirection ioctl (BAO_IOCTL_DM_GET_INFO now lives in the DM f= ops). - Fix the DM leak on remove, free the misc-device name, and unwind the probe error path fully; validate "bao,id" against BAO_IO_MAX_DMS. - Initialise virtio_requests_lock and the hypercall context fields; drop the redundant control-client dispatch loop. - riscv: reference BAO_SBI_EXT_ID consistently, document that it uses the S= BI experimental extension space (RISC-V stays experimental until an SBI implementation ID is registered), and drop the redundant ecall input constraints (Andrew Jones). - Use kzalloc_obj() instead of kzalloc(sizeof(*x)). - Add Jos=C3=A9's and David's Co-developed-by/Signed-off-by. .../userspace-api/ioctl/ioctl-number.rst | 2 + arch/arm/include/asm/bao.h | 30 ++ arch/arm64/include/asm/bao.h | 30 ++ arch/riscv/include/asm/bao.h | 37 ++ drivers/virt/Makefile | 1 + drivers/virt/bao/Kconfig | 2 + drivers/virt/bao/Makefile | 1 + drivers/virt/bao/io-dispatcher/Kconfig | 16 + drivers/virt/bao/io-dispatcher/Makefile | 4 + drivers/virt/bao/io-dispatcher/bao_drv.h | 349 +++++++++++++++ drivers/virt/bao/io-dispatcher/dm.c | 316 ++++++++++++++ drivers/virt/bao/io-dispatcher/driver.c | 95 +++++ drivers/virt/bao/io-dispatcher/intc.c | 64 +++ drivers/virt/bao/io-dispatcher/io_client.c | 401 ++++++++++++++++++ .../virt/bao/io-dispatcher/io_dispatcher.c | 181 ++++++++ drivers/virt/bao/io-dispatcher/ioeventfd.c | 323 ++++++++++++++ drivers/virt/bao/io-dispatcher/irqfd.c | 314 ++++++++++++++ include/linux/bao.h | 41 ++ include/uapi/linux/bao.h | 96 +++++ 19 files changed, 2303 insertions(+) create mode 100644 drivers/virt/bao/io-dispatcher/Kconfig create mode 100644 drivers/virt/bao/io-dispatcher/Makefile create mode 100644 drivers/virt/bao/io-dispatcher/bao_drv.h create mode 100644 drivers/virt/bao/io-dispatcher/dm.c create mode 100644 drivers/virt/bao/io-dispatcher/driver.c create mode 100644 drivers/virt/bao/io-dispatcher/intc.c create mode 100644 drivers/virt/bao/io-dispatcher/io_client.c create mode 100644 drivers/virt/bao/io-dispatcher/io_dispatcher.c create mode 100644 drivers/virt/bao/io-dispatcher/ioeventfd.c create mode 100644 drivers/virt/bao/io-dispatcher/irqfd.c create mode 100644 include/linux/bao.h create mode 100644 include/uapi/linux/bao.h diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documenta= tion/userspace-api/ioctl/ioctl-number.rst index 3f0ef1e27eb0..3c6b0c060bab 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -346,6 +346,8 @@ Code Seq# Include File = Comments 0xA5 20-2F linux/surface_aggregator/dtx.h Mic= rosoft Surface DTX driver +0xA6 all uapi/linux/bao.h Bao= hypervisor + 0xAA 00-3F linux/uapi/linux/userfaultfd.h 0xAB 00-1F linux/nbd.h 0xAC 00-1F linux/raw.h diff --git a/arch/arm/include/asm/bao.h b/arch/arm/include/asm/bao.h index ba64d1a18f91..eca258cc94e3 100644 --- a/arch/arm/include/asm/bao.h +++ b/arch/arm/include/asm/bao.h @@ -14,6 +14,7 @@ #define __ASM_ARM_BAO_H =20 #include +#include =20 static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, unsigned long ipcshmem_id) @@ -28,4 +29,33 @@ static inline unsigned long bao_ipcshmem_hypercall(unsig= ned long hypercall_id, return res.a0; } =20 +static inline unsigned long +bao_remio_hypercall(struct bao_remio_hypercall_ctx *ctx) +{ + register int r0 asm("r0") =3D + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, + ARM_SMCCC_OWNER_VENDOR_HYP, BAO_REMIO_HYPERCALL_ID); + register u32 r1 asm("r1") =3D ctx->dm_id; + register u32 r2 asm("r2") =3D ctx->addr; + register u32 r3 asm("r3") =3D ctx->op; + register u32 r4 asm("r4") =3D ctx->value; + register u32 r5 asm("r5") =3D ctx->request_id; + register u32 r6 asm("r6") =3D 0; + + asm volatile("hvc 0\n\t" + : "=3Dr"(r0), "=3Dr"(r1), "=3Dr"(r2), "=3Dr"(r3), "=3Dr"(r4), + "=3Dr"(r5), "=3Dr"(r6) + : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5) + : "memory"); + + ctx->addr =3D r1; + ctx->op =3D r2; + ctx->value =3D r3; + ctx->access_width =3D r4; + ctx->request_id =3D r5; + ctx->npend_req =3D r6; + + return r0; +} + #endif /* __ASM_ARM_BAO_H */ diff --git a/arch/arm64/include/asm/bao.h b/arch/arm64/include/asm/bao.h index ab9b283168e3..1dc09a2c261b 100644 --- a/arch/arm64/include/asm/bao.h +++ b/arch/arm64/include/asm/bao.h @@ -14,6 +14,7 @@ #define __ASM_ARM64_BAO_H =20 #include +#include =20 static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, unsigned long ipcshmem_id) @@ -28,4 +29,33 @@ static inline unsigned long bao_ipcshmem_hypercall(unsig= ned long hypercall_id, return res.a0; } =20 +static inline unsigned long +bao_remio_hypercall(struct bao_remio_hypercall_ctx *ctx) +{ + register int x0 asm("x0") =3D + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, + ARM_SMCCC_OWNER_VENDOR_HYP, BAO_REMIO_HYPERCALL_ID); + register u64 x1 asm("x1") =3D ctx->dm_id; + register u64 x2 asm("x2") =3D ctx->addr; + register u64 x3 asm("x3") =3D ctx->op; + register u64 x4 asm("x4") =3D ctx->value; + register u64 x5 asm("x5") =3D ctx->request_id; + register u64 x6 asm("x6") =3D 0; + + asm volatile("hvc 0\n\t" + : "=3Dr"(x0), "=3Dr"(x1), "=3Dr"(x2), "=3Dr"(x3), "=3Dr"(x4), + "=3Dr"(x5), "=3Dr"(x6) + : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5) + : "memory"); + + ctx->addr =3D x1; + ctx->op =3D x2; + ctx->value =3D x3; + ctx->access_width =3D x4; + ctx->request_id =3D x5; + ctx->npend_req =3D x6; + + return x0; +} + #endif /* __ASM_ARM64_BAO_H */ diff --git a/arch/riscv/include/asm/bao.h b/arch/riscv/include/asm/bao.h index d2c79a6a4ade..6dc0cb13c94c 100644 --- a/arch/riscv/include/asm/bao.h +++ b/arch/riscv/include/asm/bao.h @@ -14,7 +14,16 @@ #define __ASM_RISCV_BAO_H =20 #include +#include =20 +/* + * Bao SBI extension ID. + * + * This currently lives in the SBI experimental extension space + * (0x08000000-0x08FFFFFF). A permanent ID has to be assigned through the + * RISC-V SBI specification before the RISC-V support can be considered + * stable; until then the RISC-V backend is experimental. + */ #define BAO_SBI_EXT_ID 0x08000ba0 =20 static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, @@ -28,4 +37,32 @@ static inline unsigned long bao_ipcshmem_hypercall(unsig= ned long hypercall_id, return ret.error; } =20 +static inline unsigned long +bao_remio_hypercall(struct bao_remio_hypercall_ctx *ctx) +{ + register uintptr_t a0 asm("a0") =3D (uintptr_t)(ctx->dm_id); + register uintptr_t a1 asm("a1") =3D (uintptr_t)(ctx->addr); + register uintptr_t a2 asm("a2") =3D (uintptr_t)(ctx->op); + register uintptr_t a3 asm("a3") =3D (uintptr_t)(ctx->value); + register uintptr_t a4 asm("a4") =3D (uintptr_t)(ctx->request_id); + register uintptr_t a5 asm("a5") =3D (uintptr_t)(0); + register uintptr_t a6 asm("a6") =3D (uintptr_t)(BAO_REMIO_HYPERCALL_ID); + register uintptr_t a7 asm("a7") =3D (uintptr_t)(BAO_SBI_EXT_ID); + + asm volatile("ecall" + : "+r"(a0), "+r"(a1), "+r"(a2), "+r"(a3), "+r"(a4), + "+r"(a5), "+r"(a6), "+r"(a7) + : + : "memory"); + + ctx->addr =3D a2; + ctx->op =3D a3; + ctx->value =3D a4; + ctx->access_width =3D a5; + ctx->request_id =3D a6; + ctx->npend_req =3D a7; + + return a0; +} + #endif /* __ASM_RISCV_BAO_H */ diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile index 623a671f8711..8bffc7ccd29e 100644 --- a/drivers/virt/Makefile +++ b/drivers/virt/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_NITRO_ENCLAVES) +=3D nitro_enclaves/ obj-$(CONFIG_ACRN_HSM) +=3D acrn/ obj-y +=3D coco/ obj-$(CONFIG_BAO_SHMEM) +=3D bao/ +obj-$(CONFIG_BAO_IO_DISPATCHER) +=3D bao/ diff --git a/drivers/virt/bao/Kconfig b/drivers/virt/bao/Kconfig index 4f7929d57475..ab08a20db8c4 100644 --- a/drivers/virt/bao/Kconfig +++ b/drivers/virt/bao/Kconfig @@ -1,3 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 =20 source "drivers/virt/bao/ipcshmem/Kconfig" + +source "drivers/virt/bao/io-dispatcher/Kconfig" diff --git a/drivers/virt/bao/Makefile b/drivers/virt/bao/Makefile index 68f5d3f282c4..c463f04cf206 100644 --- a/drivers/virt/bao/Makefile +++ b/drivers/virt/bao/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 =20 obj-$(CONFIG_BAO_SHMEM) +=3D ipcshmem/ +obj-$(CONFIG_BAO_IO_DISPATCHER) +=3D io-dispatcher/ diff --git a/drivers/virt/bao/io-dispatcher/Kconfig b/drivers/virt/bao/io-d= ispatcher/Kconfig new file mode 100644 index 000000000000..cf3e8df0f2f4 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +config BAO_IO_DISPATCHER + tristate "Bao Hypervisor I/O Dispatcher" + select EVENTFD + help + The Bao I/O Dispatcher is a kernel module for backend Linux VMs + running under the Bao hypervisor. It establishes the connection + between the Remote I/O system (Bao's mechanism for forwarding + I/O requests from frontend VMs to the backend VMs) and the + VirtIO backend device. + + This provides a unified API to support various VirtIO backends, + allowing Bao guests to perform I/O through the hypervisor + transparently. + + If unsure, say N. diff --git a/drivers/virt/bao/io-dispatcher/Makefile b/drivers/virt/bao/io-= dispatcher/Makefile new file mode 100644 index 000000000000..e18de1d1a026 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_BAO_IO_DISPATCHER) +=3D bao.o +bao-objs +=3D ioeventfd.o io_client.o io_dispatcher.o irqfd.o dm.o intc.o = driver.o + diff --git a/drivers/virt/bao/io-dispatcher/bao_drv.h b/drivers/virt/bao/io= -dispatcher/bao_drv.h new file mode 100644 index 000000000000..a93386028947 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/bao_drv.h @@ -0,0 +1,349 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Provides some definitions for the Bao Hypervisor modules + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#ifndef __BAO_DRV_H +#define __BAO_DRV_H + +#include +#include +#include +#include + +#define BAO_NAME_MAX_LEN 16 +#define BAO_IO_MAX_DMS 16 + +#define BAO_IOEVENTFD_FLAG_DATAMATCH BIT(1) +#define BAO_IOEVENTFD_FLAG_DEASSIGN BIT(2) +#define BAO_IRQFD_FLAG_DEASSIGN 1U +#define BAO_IO_CLIENT_DESTROYING 0U + +struct bao_dm; +struct bao_io_client; + +typedef int (*bao_io_client_handler_t)(struct bao_io_client *client, + struct bao_virtio_request *req); + +/** + * enum bao_io_op - Bao hypervisor I/O operation types + * @BAO_IO_WRITE: Write operation + * @BAO_IO_READ: Read operation + * @BAO_IO_ASK: Request operation information (e.g., MMIO address) + * @BAO_IO_NOTIFY: Notify I/O completion + */ +enum bao_io_op { + BAO_IO_WRITE =3D 0, + BAO_IO_READ, + BAO_IO_ASK, + BAO_IO_NOTIFY, +}; + +/** + * struct bao_io_client - Bao I/O client + * @name: Client name + * @dm: The DM that the client belongs to + * @list: List node for this bao_io_client + * @is_control: If this client is the control client + * @flags: Flags (BAO_IO_CLIENT_*) + * @virtio_requests: List of free I/O requests + * @range_list: I/O ranges + * @handler: I/O request handler for this client + * @thread: Kernel thread executing the handler + * @wq: Wait queue used for thread parking + * @priv: Private data for the handler + */ +struct bao_io_client { + char name[BAO_NAME_MAX_LEN]; + struct bao_dm *dm; + struct list_head list; + bool is_control; + unsigned long flags; + struct list_head virtio_requests; + + /* protects virtio_requests list */ + struct mutex virtio_requests_lock; + + struct list_head range_list; + + /* protects range_list */ + struct rw_semaphore range_lock; + + bao_io_client_handler_t handler; + struct task_struct *thread; + wait_queue_head_t wq; + void *priv; +}; + +/** + * struct bao_dm - Bao backend device model (DM) + * @info: DM information (id, shmem_addr, shmem_size, irq) + * @name: Backing storage for the misc device name + * @shmem_base_addr: The base address of the shared memory + * @ioeventfds: List of all ioeventfds + * @ioeventfd_client: Ioeventfd client + * @irqfds: List of all irqfds + * @irqfd_server: Workqueue responsible for irqfd handling + * @io_clients: List of all bao_io_client + * @control_client: Control client + * @miscdev: Character device exposing this DM to userspace + */ +struct bao_dm { + struct bao_dm_info info; + char name[BAO_NAME_MAX_LEN]; + void *shmem_base_addr; + + struct list_head ioeventfds; + + /* protects ioeventfds list */ + struct mutex ioeventfds_lock; + + struct bao_io_client *ioeventfd_client; + + struct list_head irqfds; + + /* protects irqfds list */ + struct mutex irqfds_lock; + + struct workqueue_struct *irqfd_server; + + /* protects io_clients list */ + struct rw_semaphore io_clients_lock; + + struct list_head io_clients; + struct bao_io_client *control_client; + + struct miscdevice miscdev; +}; + +/** + * struct bao_io_range - Represents a range of I/O addresses + * @list: List node for linking multiple ranges + * @start: Start address of the range + * @end: End address of the range (inclusive) + */ +struct bao_io_range { + struct list_head list; + u64 start; + u64 end; +}; + +/** + * bao_dm_create - Create a backend device model (DM) + * @info: DM information (id, shmem_addr, shmem_size, irq) + * @dev: Parent device (the backing platform device) + * + * Return: Pointer to the created DM on success, NULL on error. + */ +struct bao_dm *bao_dm_create(struct bao_dm_info *info, struct device *dev); + +/** + * bao_dm_destroy - Destroy a backend device model (DM) + * @dm: DM to be destroyed + */ +void bao_dm_destroy(struct bao_dm *dm); + +/** + * bao_io_client_create - Create a backend I/O client + * @dm: DM this client belongs to + * @handler: I/O client handler for requests + * @data: Private data passed to the handler + * @is_control: True if this is the control client + * @name: Name of the I/O client + * + * Return: Pointer to the created I/O client, NULL on failure. + */ +struct bao_io_client *bao_io_client_create(struct bao_dm *dm, + bao_io_client_handler_t handler, + void *data, bool is_control, + const char *name); + +/** + * bao_io_clients_destroy - Destroy all I/O clients of a DM + * @dm: DM whose I/O clients are to be destroyed + */ +void bao_io_clients_destroy(struct bao_dm *dm); + +/** + * bao_io_client_attach - Attach a thread to an I/O client + * @client: I/O client to attach + * + * The thread will wait for I/O requests on this client. + * + * Return: 0 on success, negative error code on failure. + */ +int bao_io_client_attach(struct bao_io_client *client); + +/** + * bao_io_client_range_add - Add an I/O range to monitor in a client + * @client: I/O client + * @start: Start address of the range + * @end: End address of the range (inclusive) + * + * Return: 0 on success, negative error code on failure. + */ +int bao_io_client_range_add(struct bao_io_client *client, u64 start, u64 e= nd); + +/** + * bao_io_client_range_del - Remove an I/O range from a client + * @client: I/O client + * @start: Start address of the range + * @end: End address of the range (inclusive) + */ +void bao_io_client_range_del(struct bao_io_client *client, u64 start, u64 = end); + +/** + * bao_io_client_request - Retrieve the oldest I/O request from a client + * @client: I/O client + * @req: Pointer to virtio request structure to fill + * + * Return: 0 on success, negative error code if no request is available. + */ +int bao_io_client_request(struct bao_io_client *client, + struct bao_virtio_request *req); + +/** + * bao_io_client_push_request - Push an I/O request into a client + * @client: I/O client + * @req: I/O request to push + * + * Return: True if a request was pushed, false otherwise. + */ +bool bao_io_client_push_request(struct bao_io_client *client, + struct bao_virtio_request *req); + +/** + * bao_io_client_pop_request - Pop the oldest I/O request from a client + * @client: I/O client + * @req: Buffer to store the popped request + * + * Return: True if a request was popped, false if the list was empty. + */ +bool bao_io_client_pop_request(struct bao_io_client *client, + struct bao_virtio_request *req); + +/** + * bao_io_client_find - Find the I/O client for a given request + * @dm: DM that the I/O request belongs to + * @req: I/O request to locate + * + * Return: Pointer to the I/O client handling the request, NULL if none fo= und. + */ +struct bao_io_client *bao_io_client_find(struct bao_dm *dm, + struct bao_virtio_request *req); + +/** + * bao_ioeventfd_client_init - Initialize the Ioeventfd client for a DM + * @dm: DM that the Ioeventfd client belongs to + * + * Return: 0 on success, negative error code on failure. + */ +int bao_ioeventfd_client_init(struct bao_dm *dm); + +/** + * bao_ioeventfd_client_destroy - Destroy the Ioeventfd client for a DM + * @dm: DM that the Ioeventfd client belongs to + */ +void bao_ioeventfd_client_destroy(struct bao_dm *dm); + +/** + * bao_ioeventfd_client_config - Configure an Ioeventfd client + * @dm: DM that the Ioeventfd client belongs to + * @config: Ioeventfd configuration to apply + * + * Return: 0 on success, negative error code on failure. + */ +int bao_ioeventfd_client_config(struct bao_dm *dm, + struct bao_ioeventfd *config); + +/** + * bao_irqfd_server_init - Initialize the Irqfd server for a DM + * @dm: DM that the Irqfd server belongs to + * + * Return: 0 on success, negative error code on failure. + */ +int bao_irqfd_server_init(struct bao_dm *dm); + +/** + * bao_irqfd_server_destroy - Destroy the Irqfd server for a DM + * @dm: DM that the Irqfd server belongs to + */ +void bao_irqfd_server_destroy(struct bao_dm *dm); + +/** + * bao_irqfd_server_config - Configure an Irqfd server + * @dm: DM that the Irqfd server belongs to + * @config: Irqfd configuration to apply + * + * Return: 0 on success, negative error code on failure. + */ +int bao_irqfd_server_config(struct bao_dm *dm, struct bao_irqfd *config); + +/** + * bao_io_dispatcher_init - Initialize the I/O Dispatcher for a DM + * @dm: DM to initialize on the I/O Dispatcher + * + * Return: 0 on success, negative error code on failure. + */ +int bao_io_dispatcher_init(struct bao_dm *dm); + +/** + * bao_io_dispatcher_destroy - Destroy the I/O Dispatcher for a DM + * @dm: DM to destroy on the I/O Dispatcher + */ +void bao_io_dispatcher_destroy(struct bao_dm *dm); + +/** + * bao_dispatch_io - Acquire and dispatch I/O requests from the Bao Hyperv= isor + * @dm: DM whose I/O clients will handle the requests + * + * Return: 0 on success, negative error code on failure. + */ +int bao_dispatch_io(struct bao_dm *dm); + +/** + * bao_io_dispatcher_pause - Pause the I/O Dispatcher for a DM + * @dm: DM to pause + */ +void bao_io_dispatcher_pause(struct bao_dm *dm); + +/** + * bao_io_dispatcher_resume - Resume the I/O Dispatcher for a DM + * @dm: DM to resume + */ +void bao_io_dispatcher_resume(struct bao_dm *dm); + +/** + * bao_intc_init - Register the interrupt controller for a DM + * @dm: DM that the interrupt controller belongs to + * + * Return: 0 on success, negative error code on failure. + */ +int bao_intc_init(struct bao_dm *dm); + +/** + * bao_intc_destroy - Unregister the interrupt controller for a DM + * @dm: DM that the interrupt controller belongs to + */ +void bao_intc_destroy(struct bao_dm *dm); + +/** + * bao_intc_setup_handler - Setup the interrupt controller handler + * @handler: Function pointer to the interrupt handler + * @dm: DM that the interrupt controller belongs to + */ +void bao_intc_setup_handler(void (*handler)(struct bao_dm *dm)); + +/** + * bao_intc_remove_handler - Remove the interrupt controller handler + */ +void bao_intc_remove_handler(void); + +#endif /* __BAO_DRV_H */ diff --git a/drivers/virt/bao/io-dispatcher/dm.c b/drivers/virt/bao/io-disp= atcher/dm.c new file mode 100644 index 000000000000..d8e2832e1c05 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/dm.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bao Hypervisor Backend Device Model (DM) + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#include "bao_drv.h" +#include +#include +#include +#include + +static int bao_dm_open(struct inode *inode, struct file *filp) +{ + struct bao_dm *dm =3D container_of(filp->private_data, struct bao_dm, + miscdev); + + filp->private_data =3D dm; + + return 0; +} + +static int bao_dm_release(struct inode *inode, struct file *filp) +{ + filp->private_data =3D NULL; + return 0; +} + +static long bao_dm_ioctl(struct file *filp, unsigned int cmd, unsigned lon= g arg) +{ + struct bao_dm *dm =3D filp->private_data; + int rc; + + if (WARN_ON_ONCE(!dm)) + return -ENODEV; + + switch (cmd) { + case BAO_IOCTL_DM_GET_INFO: { + struct bao_dm_info info =3D dm->info; + + if (copy_to_user((void __user *)arg, &info, sizeof(info))) + return -EFAULT; + + rc =3D 0; + break; + } + case BAO_IOCTL_IO_CLIENT_ATTACH: { + struct bao_virtio_request *req; + + req =3D memdup_user((void __user *)arg, sizeof(*req)); + if (IS_ERR(req)) { + rc =3D PTR_ERR(req); + break; + } + + if (!dm->control_client) { + rc =3D -ENOENT; + goto out_free; + } + + rc =3D bao_io_client_attach(dm->control_client); + if (rc) + goto out_free; + + rc =3D bao_io_client_request(dm->control_client, req); + if (rc) + goto out_free; + + if (copy_to_user((void __user *)arg, req, sizeof(*req))) { + rc =3D -EFAULT; + goto out_free; + } + + rc =3D 0; + +out_free: + kfree(req); + break; + } + case BAO_IOCTL_IO_REQUEST_COMPLETE: { + struct bao_virtio_request *req; + struct bao_remio_hypercall_ctx ctx; + + req =3D memdup_user((void __user *)arg, sizeof(*req)); + if (IS_ERR(req)) { + rc =3D PTR_ERR(req); + break; + } + + ctx.dm_id =3D req->dm_id; + ctx.addr =3D req->addr; + ctx.op =3D req->op; + ctx.value =3D req->value; + ctx.access_width =3D req->access_width; + ctx.request_id =3D req->request_id; + + rc =3D bao_remio_hypercall(&ctx); + kfree(req); + + break; + } + case BAO_IOCTL_IOEVENTFD: { + struct bao_ioeventfd ioeventfd; + + if (copy_from_user(&ioeventfd, (void __user *)arg, + sizeof(struct bao_ioeventfd))) + return -EFAULT; + + rc =3D bao_ioeventfd_client_config(dm, &ioeventfd); + break; + } + case BAO_IOCTL_IRQFD: { + struct bao_irqfd irqfd; + + if (copy_from_user(&irqfd, (void __user *)arg, + sizeof(struct bao_irqfd))) + return -EFAULT; + + rc =3D bao_irqfd_server_config(dm, &irqfd); + break; + } + default: + rc =3D -ENOTTY; + break; + } + + return rc; +} + +/** + * bao_dm_mmap - mmap backend DM shared memory to userspace + * @filp: File pointer for the DM device + * @vma: Virtual memory area for mapping + * + * Return: 0 on success, negative errno on failure + */ +static int bao_dm_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct bao_dm *dm =3D filp->private_data; + unsigned long vsize; + unsigned long offset; + phys_addr_t phys; + + if (WARN_ON_ONCE(!dm)) + return -ENODEV; + + vsize =3D vma->vm_end - vma->vm_start; + offset =3D vma->vm_pgoff << PAGE_SHIFT; + + if (!vsize || offset) + return -EINVAL; + + if (vsize > dm->info.shmem_size) + return -EINVAL; + + phys =3D dm->info.shmem_addr; + if (!PAGE_ALIGNED(phys)) + return -EINVAL; + + if (remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT, vsize, + vma->vm_page_prot)) + return -EFAULT; + + return 0; +} + +/** + * bao_dm_llseek - Adjust file offset for backend DM device + * @file: File pointer for the DM device + * @offset: Offset to seek + * @whence: Reference point (SEEK_SET, SEEK_CUR, SEEK_END) + * + * Return: New file position on success, negative errno on failure + */ +static loff_t bao_dm_llseek(struct file *file, loff_t offset, int whence) +{ + struct bao_dm *dm =3D file->private_data; + loff_t new_pos; + + if (WARN_ON_ONCE(!dm)) + return -ENODEV; + + switch (whence) { + case SEEK_SET: + new_pos =3D offset; + break; + case SEEK_CUR: + new_pos =3D file->f_pos + offset; + break; + case SEEK_END: + new_pos =3D dm->info.shmem_size + offset; + break; + default: + return -EINVAL; + } + + if (new_pos < 0 || new_pos > dm->info.shmem_size) + return -EINVAL; + + file->f_pos =3D new_pos; + return new_pos; +} + +static const struct file_operations bao_dm_fops =3D { + .owner =3D THIS_MODULE, + .open =3D bao_dm_open, + .release =3D bao_dm_release, + .unlocked_ioctl =3D bao_dm_ioctl, + .llseek =3D bao_dm_llseek, + .mmap =3D bao_dm_mmap, +}; + +struct bao_dm *bao_dm_create(struct bao_dm_info *info, struct device *dev) +{ + struct bao_dm *dm; + int ret; + + if (WARN_ON(!info)) + return NULL; + + dm =3D kzalloc_obj(*dm, GFP_KERNEL); + if (!dm) + return NULL; + + INIT_LIST_HEAD(&dm->io_clients); + init_rwsem(&dm->io_clients_lock); + + dm->info =3D *info; + + ret =3D bao_io_dispatcher_init(dm); + if (ret) { + dev_err(dev, "failed to init I/O dispatcher for DM %u\n", + dm->info.id); + goto err_free; + } + + snprintf(dm->name, sizeof(dm->name), "bao-ioctlc%u", dm->info.id); + dm->control_client =3D bao_io_client_create(dm, NULL, NULL, true, + dm->name); + if (!dm->control_client) { + dev_err(dev, "failed to create control client for DM %u\n", + dm->info.id); + goto err_destroy_dispatcher; + } + + if (bao_ioeventfd_client_init(dm)) { + dev_err(dev, "failed to initialize ioeventfd for DM %u\n", + dm->info.id); + goto err_destroy_io_clients; + } + + if (bao_irqfd_server_init(dm)) { + dev_err(dev, "failed to initialize irqfd for DM %u\n", + dm->info.id); + goto err_destroy_io_clients; + } + + dm->shmem_base_addr =3D memremap(dm->info.shmem_addr, dm->info.shmem_size, + MEMREMAP_WB); + if (!dm->shmem_base_addr) { + dev_err(dev, "failed to map memory region for DM %u\n", + dm->info.id); + goto err_destroy_irqfd; + } + + snprintf(dm->name, sizeof(dm->name), "bao-dm%u", dm->info.id); + dm->miscdev.minor =3D MISC_DYNAMIC_MINOR; + dm->miscdev.name =3D dm->name; + dm->miscdev.fops =3D &bao_dm_fops; + dm->miscdev.parent =3D dev; + + ret =3D misc_register(&dm->miscdev); + if (ret) { + dev_err(dev, "failed to register misc device for DM %u: %d\n", + dm->info.id, ret); + goto err_unmap; + } + + return dm; + +err_unmap: + memunmap(dm->shmem_base_addr); +err_destroy_irqfd: + bao_irqfd_server_destroy(dm); +err_destroy_io_clients: + bao_io_clients_destroy(dm); +err_destroy_dispatcher: + bao_io_dispatcher_destroy(dm); +err_free: + kfree(dm); + + return NULL; +} + +void bao_dm_destroy(struct bao_dm *dm) +{ + if (WARN_ON_ONCE(!dm)) + return; + + misc_deregister(&dm->miscdev); + + if (dm->shmem_base_addr) + memunmap(dm->shmem_base_addr); + + bao_irqfd_server_destroy(dm); + bao_io_clients_destroy(dm); + bao_io_dispatcher_destroy(dm); + + kfree(dm); +} diff --git a/drivers/virt/bao/io-dispatcher/driver.c b/drivers/virt/bao/io-= dispatcher/driver.c new file mode 100644 index 000000000000..1e90737e51c7 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/driver.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bao Hypervisor I/O Dispatcher Kernel Driver + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include +#include "bao_drv.h" + +static int bao_io_dispatcher_driver_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct bao_dm_info dm_info; + struct bao_dm *dm; + struct resource *r; + int irq; + u32 id; + int ret; + + r =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(dev, "missing shared memory resource\n"); + return -ENODEV; + } + + ret =3D of_property_read_u32(dev->of_node, "bao,id", &id); + if (ret) { + dev_err(dev, "missing or invalid 'bao,id' property\n"); + return ret; + } + + if (id >=3D BAO_IO_MAX_DMS) { + dev_err(dev, "'bao,id' %u out of range (max %u)\n", id, + BAO_IO_MAX_DMS - 1); + return -EINVAL; + } + + irq =3D platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + dm_info.id =3D id; + dm_info.shmem_addr =3D r->start; + dm_info.shmem_size =3D resource_size(r); + dm_info.irq =3D irq; + + dm =3D bao_dm_create(&dm_info, dev); + if (!dm) + return -EINVAL; + + ret =3D bao_intc_init(dm); + if (ret) { + dev_err(dev, "failed to register interrupt %d for DM %u\n", irq, + id); + bao_dm_destroy(dm); + return ret; + } + + platform_set_drvdata(pdev, dm); + + return 0; +} + +static void bao_io_dispatcher_driver_remove(struct platform_device *pdev) +{ + struct bao_dm *dm =3D platform_get_drvdata(pdev); + + bao_intc_destroy(dm); + bao_dm_destroy(dm); +} + +static const struct of_device_id bao_io_dispatcher_driver_dt_ids[] =3D { + { .compatible =3D "bao,io-dispatcher" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, bao_io_dispatcher_driver_dt_ids); + +static struct platform_driver bao_io_dispatcher_driver =3D { + .probe =3D bao_io_dispatcher_driver_probe, + .remove =3D bao_io_dispatcher_driver_remove, + .driver =3D { + .name =3D "bao-io-dispatcher", + .of_match_table =3D bao_io_dispatcher_driver_dt_ids, + }, +}; + +module_platform_driver(bao_io_dispatcher_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jo=C3=A3o Peixoto "); +MODULE_AUTHOR("David Cerdeira "); +MODULE_AUTHOR("Jos=C3=A9 Martins "); +MODULE_DESCRIPTION("Bao Hypervisor I/O Dispatcher Kernel Driver"); diff --git a/drivers/virt/bao/io-dispatcher/intc.c b/drivers/virt/bao/io-di= spatcher/intc.c new file mode 100644 index 000000000000..d9d2f0861639 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/intc.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bao Hypervisor I/O Dispatcher Interrupt Controller + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#include +#include "bao_drv.h" + +/* Top-level handler registered by the Bao interrupt controller */ +static void (*bao_intc_handler)(struct bao_dm *dm); + +/** + * bao_interrupt_handler - Top-level interrupt handler for Bao DM + * @irq: Interrupt number + * @dev: Pointer to the Bao device model (struct bao_dm) + * + * Invokes the registered Bao interrupt controller handler, if any. + */ +static irqreturn_t bao_interrupt_handler(int irq, void *dev) +{ + struct bao_dm *dm =3D (struct bao_dm *)dev; + + if (bao_intc_handler) + bao_intc_handler(dm); + + return IRQ_HANDLED; +} + +void bao_intc_setup_handler(void (*handler)(struct bao_dm *dm)) +{ + bao_intc_handler =3D handler; +} + +void bao_intc_remove_handler(void) +{ + bao_intc_handler =3D NULL; +} + +int bao_intc_init(struct bao_dm *dm) +{ + char name[BAO_NAME_MAX_LEN]; + + if (WARN_ON_ONCE(!dm)) + return -EINVAL; + + scnprintf(name, sizeof(name), "bao-iodintc%d", dm->info.id); + + return request_irq(dm->info.irq, bao_interrupt_handler, 0, name, dm); +} + +void bao_intc_destroy(struct bao_dm *dm) +{ + if (WARN_ON_ONCE(!dm)) + return; + + free_irq(dm->info.irq, dm); +} diff --git a/drivers/virt/bao/io-dispatcher/io_client.c b/drivers/virt/bao/= io-dispatcher/io_client.c new file mode 100644 index 000000000000..849631bad2f0 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/io_client.c @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bao Hypervisor I/O Client + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#include +#include +#include "bao_drv.h" + +/** + * struct bao_io_request - Bao I/O request structure + * @list: List node linking all requests + * @virtio_request: The VirtIO request payload + * + * Represents a single I/O request for a Bao I/O client. + */ +struct bao_io_request { + struct list_head list; + struct bao_virtio_request virtio_request; +}; + +/** + * bao_io_client_has_pending_requests - Check if an I/O client has pending= requests + * @client: The bao_io_client to check + * + * Return: True if has pending I/O requests, false otherwise. + */ +static inline bool +bao_io_client_has_pending_requests(struct bao_io_client *client) +{ + if (WARN_ON_ONCE(!client)) + return false; + + return !list_empty(&client->virtio_requests); +} + +/** + * bao_io_client_is_destroying - Check if an I/O client is being destroyed + * @client: The bao_io_client to check + * + * Return: True if the client is being destroyed, false otherwise. + */ +static inline bool bao_io_client_is_destroying(struct bao_io_client *clien= t) +{ + if (WARN_ON_ONCE(!client)) + return true; + + return test_bit(BAO_IO_CLIENT_DESTROYING, &client->flags); +} + +bool bao_io_client_push_request(struct bao_io_client *client, + struct bao_virtio_request *req) +{ + struct bao_io_request *io_req; + + if (WARN_ON_ONCE(!client || !req)) + return false; + + io_req =3D kzalloc_obj(*io_req, GFP_KERNEL); + if (!io_req) + return false; + + io_req->virtio_request =3D *req; + + mutex_lock(&client->virtio_requests_lock); + list_add_tail(&io_req->list, &client->virtio_requests); + mutex_unlock(&client->virtio_requests_lock); + + return true; +} + +bool bao_io_client_pop_request(struct bao_io_client *client, + struct bao_virtio_request *ret) +{ + struct bao_io_request *req; + + if (WARN_ON_ONCE(!client || !ret)) + return false; + + mutex_lock(&client->virtio_requests_lock); + + req =3D list_first_entry_or_null(&client->virtio_requests, + struct bao_io_request, list); + if (!req) { + mutex_unlock(&client->virtio_requests_lock); + return false; + } + + list_del(&req->list); + *ret =3D req->virtio_request; + + mutex_unlock(&client->virtio_requests_lock); + + kfree(req); + + return true; +} + +/** + * bao_io_client_destroy - Destroy an I/O client + * @client: The bao_io_client to destroy + */ +static void bao_io_client_destroy(struct bao_io_client *client) +{ + struct bao_io_client *range; + struct bao_io_client *next; + struct bao_dm *dm; + + if (WARN_ON_ONCE(!client)) + return; + + dm =3D client->dm; + + bao_io_dispatcher_pause(dm); + + set_bit(BAO_IO_CLIENT_DESTROYING, &client->flags); + + if (client->is_control) { + wake_up_interruptible(&client->wq); + } else { + bao_ioeventfd_client_destroy(dm); + if (client->thread) + kthread_stop(client->thread); + } + + down_write(&client->range_lock); + list_for_each_entry_safe(range, next, &client->range_list, list) { + list_del(&range->list); + kfree(range); + } + up_write(&client->range_lock); + + down_write(&dm->io_clients_lock); + if (client->is_control) + dm->control_client =3D NULL; + else + dm->ioeventfd_client =3D NULL; + + list_del(&client->list); + up_write(&dm->io_clients_lock); + + bao_io_dispatcher_resume(dm); + + kfree(client); +} + +void bao_io_clients_destroy(struct bao_dm *dm) +{ + struct bao_io_client *client, *next; + + if (WARN_ON_ONCE(!dm)) + return; + + list_for_each_entry_safe(client, next, &dm->io_clients, list) { + bao_io_client_destroy(client); + } +} + +int bao_io_client_attach(struct bao_io_client *client) +{ + if (WARN_ON_ONCE(!client)) + return -EINVAL; + + if (client->is_control) { + wait_event_interruptible(client->wq, + bao_io_client_has_pending_requests(client) || + bao_io_client_is_destroying(client)); + if (bao_io_client_is_destroying(client)) + return -EPERM; + } else { + wait_event_interruptible(client->wq, + bao_io_client_has_pending_requests(client) || + bao_io_client_is_destroying(client) || + kthread_should_stop()); + if (bao_io_client_is_destroying(client) || + kthread_should_stop()) { + if (kthread_should_stop()) + bao_io_client_destroy(client); + return -EPERM; + } + } + + return 0; +} + +/** + * bao_io_client_kernel_thread - Thread for processing a kernel I/O client + * @data: Pointer to the bao_io_client structure + * + * Return: 0 on completion + */ +static int bao_io_client_kernel_thread(void *data) +{ + struct bao_io_client *client =3D data; + struct bao_virtio_request req; + struct bao_remio_hypercall_ctx ctx; + bool stop =3D false; + int ret; + + if (WARN_ON_ONCE(!client)) + return -EINVAL; + + while (!stop && !kthread_should_stop()) { + ret =3D bao_io_client_attach(client); + if (ret < 0) { + stop =3D true; + break; + } + + while (bao_io_client_has_pending_requests(client) && !stop) { + if (!bao_io_client_pop_request(client, &req)) { + pr_err("%s: failed to pop I/O request\n", + __func__); + stop =3D true; + break; + } + + ret =3D client->handler(client, &req); + if (ret < 0) { + pr_warn("%s: client handler returned %d\n", + __func__, ret); + break; + } + + ctx.dm_id =3D req.dm_id; + ctx.op =3D req.op; + ctx.addr =3D req.addr; + ctx.value =3D req.value; + ctx.access_width =3D req.access_width; + ctx.request_id =3D req.request_id; + + if (bao_remio_hypercall(&ctx)) { + stop =3D true; + break; + } + } + } + + return 0; +} + +struct bao_io_client *bao_io_client_create(struct bao_dm *dm, + bao_io_client_handler_t handler, + void *data, bool is_control, + const char *name) +{ + struct bao_io_client *client; + + if (WARN_ON_ONCE(!dm || !name)) + return NULL; + + if (!handler && !is_control) + return NULL; + + client =3D kzalloc_obj(*client, GFP_KERNEL); + if (!client) + return NULL; + + client->handler =3D handler; + client->dm =3D dm; + client->priv =3D data; + client->is_control =3D is_control; + if (name) + strscpy(client->name, name, sizeof(client->name)); + + INIT_LIST_HEAD(&client->virtio_requests); + mutex_init(&client->virtio_requests_lock); + init_rwsem(&client->range_lock); + INIT_LIST_HEAD(&client->range_list); + init_waitqueue_head(&client->wq); + + if (client->handler) { + client->thread =3D kthread_run(bao_io_client_kernel_thread, + client, "%s-kthread", + client->name); + if (IS_ERR(client->thread)) { + kfree(client); + return NULL; + } + } + + down_write(&dm->io_clients_lock); + if (is_control) + dm->control_client =3D client; + else + dm->ioeventfd_client =3D client; + + list_add(&client->list, &dm->io_clients); + up_write(&dm->io_clients_lock); + + return client; +} + +int bao_io_client_request(struct bao_io_client *client, + struct bao_virtio_request *req) +{ + if (WARN_ON_ONCE(!client)) + return -EINVAL; + + if (!bao_io_client_pop_request(client, req)) + return -EFAULT; + + return 0; +} + +int bao_io_client_range_add(struct bao_io_client *client, u64 start, u64 e= nd) +{ + struct bao_io_range *range; + + if (WARN_ON_ONCE(!client)) + return -EINVAL; + + if (end < start) + return -EINVAL; + + range =3D kzalloc_obj(*range, GFP_KERNEL); + if (!range) + return -ENOMEM; + + range->start =3D start; + range->end =3D end; + + down_write(&client->range_lock); + list_add(&range->list, &client->range_list); + up_write(&client->range_lock); + + return 0; +} + +void bao_io_client_range_del(struct bao_io_client *client, u64 start, u64 = end) +{ + struct bao_io_range *range; + struct bao_io_range *tmp; + + if (WARN_ON_ONCE(!client)) + return; + + down_write(&client->range_lock); + list_for_each_entry_safe(range, tmp, &client->range_list, list) { + if (range->start =3D=3D start && range->end =3D=3D end) { + list_del(&range->list); + kfree(range); + break; + } + } + up_write(&client->range_lock); +} + +/** + * bao_io_request_in_range - Check if the I/O request is in the range + * @range: The I/O request range + * @req: The I/O request to be checked + * + * Return: True if the I/O request is in the range, false otherwise + */ +static bool bao_io_request_in_range(struct bao_io_range *range, + struct bao_virtio_request *req) +{ + if (WARN_ON_ONCE(!range || !req)) + return false; + + if (req->addr >=3D range->start && + (req->addr + req->access_width - 1) <=3D range->end) + return true; + + return false; +} + +struct bao_io_client *bao_io_client_find(struct bao_dm *dm, + struct bao_virtio_request *req) +{ + struct bao_io_client *client; + struct bao_io_client *found =3D NULL; + struct bao_io_range *range; + + if (WARN_ON_ONCE(!dm || !req)) + return NULL; + + list_for_each_entry(client, &dm->io_clients, list) { + down_read(&client->range_lock); + list_for_each_entry(range, &client->range_list, list) { + if (bao_io_request_in_range(range, req)) { + found =3D client; + break; + } + } + up_read(&client->range_lock); + + if (found) + break; + } + + return found ? found : dm->control_client; +} diff --git a/drivers/virt/bao/io-dispatcher/io_dispatcher.c b/drivers/virt/= bao/io-dispatcher/io_dispatcher.c new file mode 100644 index 000000000000..82161ae47cb6 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/io_dispatcher.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bao Hypervisor I/O Dispatcher + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#include +#include "bao_drv.h" + +/** + * struct bao_io_dispatcher_work - Work item for I/O dispatching + * @work: Work struct for scheduling on workqueue + * @dm: Pointer to the associated Bao device model + * + * Represents a single work item that dispatches I/O requests + * for a specific Bao device model. + */ +struct bao_io_dispatcher_work { + struct work_struct work; + struct bao_dm *dm; +}; + +/* Array of I/O dispatcher work items, one per Bao DM */ +static struct bao_io_dispatcher_work io_dispatcher_work[BAO_IO_MAX_DMS]; + +/* Workqueues dedicated to dispatching I/O requests for each Bao DM */ +static struct workqueue_struct *bao_io_dispatcher_wq[BAO_IO_MAX_DMS]; + +void bao_io_dispatcher_destroy(struct bao_dm *dm) +{ + if (WARN_ON_ONCE(!dm)) + return; + + if (bao_io_dispatcher_wq[dm->info.id]) { + bao_io_dispatcher_pause(dm); + + destroy_workqueue(bao_io_dispatcher_wq[dm->info.id]); + bao_io_dispatcher_wq[dm->info.id] =3D NULL; + + bao_intc_remove_handler(); + } +} + +int bao_dispatch_io(struct bao_dm *dm) +{ + struct bao_io_client *client; + struct bao_remio_hypercall_ctx ctx; + struct bao_virtio_request req; + + if (WARN_ON_ONCE(!dm)) + return -EINVAL; + + ctx.dm_id =3D dm->info.id; + ctx.op =3D BAO_IO_ASK; + ctx.addr =3D 0; + ctx.value =3D 0; + ctx.request_id =3D 0; + ctx.access_width =3D 0; + ctx.npend_req =3D 0; + + if (bao_remio_hypercall(&ctx)) + return -EFAULT; + + req.dm_id =3D ctx.dm_id; + req.op =3D ctx.op; + req.addr =3D ctx.addr; + req.value =3D ctx.value; + req.access_width =3D ctx.access_width; + req.request_id =3D ctx.request_id; + + down_read(&dm->io_clients_lock); + client =3D bao_io_client_find(dm, &req); + if (!client) { + up_read(&dm->io_clients_lock); + return -ENODEV; + } + + if (!bao_io_client_push_request(client, &req)) { + up_read(&dm->io_clients_lock); + return -EINVAL; + } + + wake_up_interruptible(&client->wq); + up_read(&dm->io_clients_lock); + + return ctx.npend_req; +} + +/** + * io_dispatcher - Workqueue handler for dispatching I/O + * @work: Work struct representing this dispatch operation + * + * Handles all pending I/O requests for the associated Bao DM. + * Executed in process context by the workqueue. + */ +static void io_dispatcher(struct work_struct *work) +{ + struct bao_io_dispatcher_work *bao_dm_work; + struct bao_dm *dm; + + if (WARN_ON_ONCE(!work)) + return; + + bao_dm_work =3D container_of(work, struct bao_io_dispatcher_work, work); + dm =3D bao_dm_work->dm; + + if (WARN_ON_ONCE(!dm)) + return; + + while (bao_dispatch_io(dm) > 0) + cpu_relax(); +} + +/** + * io_dispatcher_intc_handler - Interrupt handler for I/O requests + * @dm: Bao device model that triggered the interrupt + * + * Invoked by the interrupt controller when a new I/O request is available. + * Queues the corresponding work item onto the I/O dispatcher workqueue + * for processing in process context. + */ +static void io_dispatcher_intc_handler(struct bao_dm *dm) +{ + if (WARN_ON_ONCE(!dm || !bao_io_dispatcher_wq[dm->info.id])) + return; + + queue_work(bao_io_dispatcher_wq[dm->info.id], + &io_dispatcher_work[dm->info.id].work); +} + +void bao_io_dispatcher_pause(struct bao_dm *dm) +{ + if (WARN_ON_ONCE(!dm || !bao_io_dispatcher_wq[dm->info.id])) + return; + + bao_intc_remove_handler(); + + drain_workqueue(bao_io_dispatcher_wq[dm->info.id]); +} + +void bao_io_dispatcher_resume(struct bao_dm *dm) +{ + if (WARN_ON_ONCE(!dm || !bao_io_dispatcher_wq[dm->info.id])) + return; + + bao_intc_setup_handler(io_dispatcher_intc_handler); + + queue_work(bao_io_dispatcher_wq[dm->info.id], + &io_dispatcher_work[dm->info.id].work); +} + +int bao_io_dispatcher_init(struct bao_dm *dm) +{ + char name[BAO_NAME_MAX_LEN]; + + if (WARN_ON_ONCE(!dm)) + return -EINVAL; + + snprintf(name, sizeof(name), "bao-iodwq%u", dm->info.id); + + if (bao_io_dispatcher_wq[dm->info.id]) + return -EBUSY; + bao_io_dispatcher_wq[dm->info.id] =3D + alloc_workqueue(name, WQ_HIGHPRI | WQ_MEM_RECLAIM, 1); + if (!bao_io_dispatcher_wq[dm->info.id]) + return -ENOMEM; + + io_dispatcher_work[dm->info.id].dm =3D dm; + INIT_WORK(&io_dispatcher_work[dm->info.id].work, io_dispatcher); + + bao_intc_setup_handler(io_dispatcher_intc_handler); + + return 0; +} + diff --git a/drivers/virt/bao/io-dispatcher/ioeventfd.c b/drivers/virt/bao/= io-dispatcher/ioeventfd.c new file mode 100644 index 000000000000..8c6a69df7a51 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/ioeventfd.c @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bao Hypervisor Ioeventfd Client + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#include +#include "bao_drv.h" + +/** + * struct ioeventfd - Properties of an I/O eventfd + * @list: List node linking this ioeventfd + * @eventfd: Associated eventfd context + * @addr: Start address of the I/O range + * @data: Data used for matching (if not wildcard) + * @length: Length of the I/O range + * @wildcard: True if data matching is not required + * + * Represents an I/O eventfd registered for a Bao device model. + */ +struct ioeventfd { + struct list_head list; + struct eventfd_ctx *eventfd; + u64 addr; + u64 data; + int length; + bool wildcard; +}; + +/** + * bao_ioeventfd_shutdown - Release and remove an ioeventfd + * @dm: Bao device model owning the ioeventfd + * @p: Ioeventfd to shut down + */ +static void bao_ioeventfd_shutdown(struct bao_dm *dm, struct ioeventfd *p) +{ + lockdep_assert_held(&dm->ioeventfds_lock); + + if (WARN_ON_ONCE(!p)) + return; + + eventfd_ctx_put(p->eventfd); + list_del(&p->list); + kfree(p); +} + +/** + * bao_ioeventfd_config_valid - Validate ioeventfd configuration + * @config: Ioeventfd configuration + * + * Return: True if config is non-NULL, address+length does not wrap, + * and length is 1, 2, 4, or 8 bytes. + */ +static bool bao_ioeventfd_config_valid(struct bao_ioeventfd *config) +{ + if (WARN_ON_ONCE(!config)) + return false; + + if (config->addr + config->len < config->addr) + return false; + + if (!(config->len =3D=3D 1 || config->len =3D=3D 2 || config->len =3D=3D = 4 || + config->len =3D=3D 8)) + return false; + + return true; +} + +/** + * bao_ioeventfd_is_conflict - Check if an ioeventfd conflicts with existi= ng ones + * @dm: Bao device model + * @ioeventfd: Ioeventfd to check + * + * Return: True if an existing ioeventfd matches address, eventfd, + * and optionally data. + */ +static bool bao_ioeventfd_is_conflict(struct bao_dm *dm, + struct ioeventfd *ioeventfd) +{ + struct ioeventfd *p; + + lockdep_assert_held(&dm->ioeventfds_lock); + + if (WARN_ON_ONCE(!dm || !ioeventfd)) + return true; + + list_for_each_entry(p, &dm->ioeventfds, list) { + if (p->eventfd =3D=3D ioeventfd->eventfd && + p->addr =3D=3D ioeventfd->addr && + (p->wildcard || ioeventfd->wildcard || + p->data =3D=3D ioeventfd->data)) { + return true; + } + } + + return false; +} + +/** + * bao_ioeventfd_match - Find ioeventfd matching an I/O request + * @dm: Bao device model + * @addr: I/O request address + * @data: I/O request data + * @len: I/O request length + * + * Return: The matching ioeventfd, NULL if none matches. + */ +static struct ioeventfd *bao_ioeventfd_match(struct bao_dm *dm, u64 addr, + u64 data, int len) +{ + struct ioeventfd *p; + + lockdep_assert_held(&dm->ioeventfds_lock); + + if (WARN_ON_ONCE(!dm)) + return NULL; + + list_for_each_entry(p, &dm->ioeventfds, list) { + if (p->addr =3D=3D addr && p->length >=3D len && + (p->wildcard || p->data =3D=3D data)) { + return p; + } + } + + return NULL; +} + +/** + * bao_ioeventfd_assign - Assign and create an eventfd for a DM + * @dm: Bao device model to assign the eventfd to + * @config: Configuration of the eventfd to create + * + * Creates a new ioeventfd associated with the given eventfd and + * adds it to the Bao DM. Validates the configuration, checks for + * conflicts with existing ioeventfds, and registers the corresponding + * I/O client address range. Supports optional data matching for + * virtio 1.0 notifications; if not set, wildcard matching is used. + * + * Return: 0 on success, a negative error code on failure + */ +static int bao_ioeventfd_assign(struct bao_dm *dm, struct bao_ioeventfd *c= onfig) +{ + struct eventfd_ctx *eventfd; + struct ioeventfd *new; + int rc =3D 0; + + if (WARN_ON_ONCE(!dm || !config)) + return -EINVAL; + + if (!bao_ioeventfd_config_valid(config)) + return -EINVAL; + + eventfd =3D eventfd_ctx_fdget(config->fd); + if (IS_ERR(eventfd)) + return PTR_ERR(eventfd); + + new =3D kzalloc_obj(*new, GFP_KERNEL); + if (!new) { + rc =3D -ENOMEM; + goto err_put_eventfd; + } + + INIT_LIST_HEAD(&new->list); + new->addr =3D config->addr; + new->length =3D config->len; + new->eventfd =3D eventfd; + new->wildcard =3D !(config->flags & BAO_IOEVENTFD_FLAG_DATAMATCH); + if (!new->wildcard) + new->data =3D config->data; + + mutex_lock(&dm->ioeventfds_lock); + + if (bao_ioeventfd_is_conflict(dm, new)) { + rc =3D -EEXIST; + goto err_unlock_free; + } + + rc =3D bao_io_client_range_add(dm->ioeventfd_client, new->addr, + new->addr + new->length - 1); + if (rc < 0) + goto err_unlock_free; + + list_add_tail(&new->list, &dm->ioeventfds); + mutex_unlock(&dm->ioeventfds_lock); + + return 0; + +err_unlock_free: + mutex_unlock(&dm->ioeventfds_lock); + kfree(new); +err_put_eventfd: + eventfd_ctx_put(eventfd); + return rc; +} + +/** + * bao_ioeventfd_deassign - Deassign and destroy an eventfd from a DM + * @dm: Bao device model to deassign the eventfd from + * @config: Configuration of the eventfd to remove + * + * Return: 0 on success, a negative error code on failure + */ +static int bao_ioeventfd_deassign(struct bao_dm *dm, + struct bao_ioeventfd *config) +{ + struct ioeventfd *p; + struct eventfd_ctx *eventfd; + + if (WARN_ON_ONCE(!dm || !config)) + return -EINVAL; + + eventfd =3D eventfd_ctx_fdget(config->fd); + if (IS_ERR(eventfd)) + return PTR_ERR(eventfd); + + mutex_lock(&dm->ioeventfds_lock); + + list_for_each_entry(p, &dm->ioeventfds, list) { + if (p->eventfd !=3D eventfd) + continue; + + bao_io_client_range_del(dm->ioeventfd_client, p->addr, + p->addr + p->length - 1); + + bao_ioeventfd_shutdown(dm, p); + break; + } + + mutex_unlock(&dm->ioeventfds_lock); + eventfd_ctx_put(eventfd); + + return 0; +} + +/** + * bao_ioeventfd_handler - Handle an Ioeventfd client I/O request + * @client: Ioeventfd client associated with the request + * @req: I/O request to process + * + * Processes I/O requests from the Bao I/O client kernel thread + * (bao_io_client_kernel_thread). For READ operations, the value is + * ignored and set to 0 since virtio MMIO drivers only write to the + * `QueueNotify` field. WRITE operations are checked against the + * registered ioeventfds, and the corresponding eventfd is signaled + * if a match is found. + * + * Return: 0 on success, a negative error code on failure + */ +static int bao_ioeventfd_handler(struct bao_io_client *client, + struct bao_virtio_request *req) +{ + struct ioeventfd *p; + + if (WARN_ON_ONCE(!client || !req)) + return -EINVAL; + + if (req->op =3D=3D BAO_IO_READ) { + req->value =3D 0; + return 0; + } + + mutex_lock(&client->dm->ioeventfds_lock); + + p =3D bao_ioeventfd_match(client->dm, req->addr, req->value, + req->access_width); + if (p) + eventfd_signal(p->eventfd); + + mutex_unlock(&client->dm->ioeventfds_lock); + + return 0; +} + +int bao_ioeventfd_client_config(struct bao_dm *dm, struct bao_ioeventfd *c= onfig) +{ + if (WARN_ON_ONCE(!dm || !config)) + return -EINVAL; + + if (config->flags & BAO_IOEVENTFD_FLAG_DEASSIGN) + bao_ioeventfd_deassign(dm, config); + + return bao_ioeventfd_assign(dm, config); +} + +int bao_ioeventfd_client_init(struct bao_dm *dm) +{ + char name[BAO_NAME_MAX_LEN]; + + if (WARN_ON_ONCE(!dm)) + return -EINVAL; + + mutex_init(&dm->ioeventfds_lock); + INIT_LIST_HEAD(&dm->ioeventfds); + + snprintf(name, sizeof(name), "bao-ioevfdc%u", dm->info.id); + + dm->ioeventfd_client =3D bao_io_client_create(dm, bao_ioeventfd_handler, + NULL, false, name); + if (!dm->ioeventfd_client) + return -ENOMEM; + + return 0; +} + +void bao_ioeventfd_client_destroy(struct bao_dm *dm) +{ + struct ioeventfd *p; + struct ioeventfd *next; + + if (WARN_ON_ONCE(!dm)) + return; + + mutex_lock(&dm->ioeventfds_lock); + list_for_each_entry_safe(p, next, &dm->ioeventfds, list) + bao_ioeventfd_shutdown(dm, p); + mutex_unlock(&dm->ioeventfds_lock); +} diff --git a/drivers/virt/bao/io-dispatcher/irqfd.c b/drivers/virt/bao/io-d= ispatcher/irqfd.c new file mode 100644 index 000000000000..07b20365ecae --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/irqfd.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Bao Hypervisor Irqfd Server + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#include +#include +#include +#include +#include "bao_drv.h" + +/** + * struct irqfd - Properties of an IRQ eventfd + * @dm: Associated Bao device model + * @wait: Wait queue entry for blocking/waking + * @shutdown: Work struct for async shutdown + * @eventfd: Eventfd used to signal interrupts + * @list: List node within &bao_dm.irqfds + * @pt: Poll table for select/poll on the eventfd + * + * Represents an IRQ eventfd registered to a Bao device model. + */ +struct irqfd { + struct bao_dm *dm; + wait_queue_entry_t wait; + struct work_struct shutdown; + struct eventfd_ctx *eventfd; + struct list_head list; + poll_table pt; +}; + +/** + * bao_irqfd_shutdown - Release and remove an irqfd + * @irqfd: IRQ eventfd to shut down (lock must be held) + */ +static void bao_irqfd_shutdown(struct irqfd *irqfd) +{ + u64 cnt; + + if (WARN_ON_ONCE(!irqfd || !irqfd->dm)) + return; + + lockdep_assert_held(&irqfd->dm->irqfds_lock); + + list_del_init(&irqfd->list); + + eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt); + + eventfd_ctx_put(irqfd->eventfd); + + kfree(irqfd); +} + +/** + * bao_irqfd_inject - Inject a notify hypercall into the Bao hypervisor + * @id: Bao DM ID + * + * Return: 0 on success, -EFAULT if the hypercall fails. + */ +static int bao_irqfd_inject(int id) +{ + struct bao_remio_hypercall_ctx ctx =3D { + .dm_id =3D id, + .addr =3D 0, + .op =3D BAO_IO_NOTIFY, + .value =3D 0, + .access_width =3D 0, + .request_id =3D 0, + }; + + if (bao_remio_hypercall(&ctx)) + return -EFAULT; + + return 0; +} + +/** + * bao_irqfd_wakeup - Custom wake-up handler for eventfd signaling + * @wait: Wait queue entry + * @mode: Mode flags + * @sync: Sync indicator + * @key: Poll bits (cast from void *) + * + * Called by the Linux kernel poll table when the underlying eventfd is si= gnaled. + * Injects a Bao notify hypercall on POLLIN or schedules shutdown on POLLH= UP. + * + * Return: 0 on success, a negative error code on failure + */ +static int bao_irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, + int sync, void *key) +{ + struct irqfd *irqfd; + struct bao_dm *dm; + unsigned long poll_bits; + + if (WARN_ON_ONCE(!wait || !key)) + return -EINVAL; + + irqfd =3D container_of(wait, struct irqfd, wait); + dm =3D irqfd->dm; + poll_bits =3D (unsigned long)key; + + if (poll_bits & POLLIN) + bao_irqfd_inject(dm->info.id); + + if (poll_bits & POLLHUP) + queue_work(dm->irqfd_server, &irqfd->shutdown); + + return 0; +} + +/** + * bao_irqfd_poll_func - Register an IRQFD with a poll table + * @file: File to poll + * @wqh: Wait queue head + * @pt: Poll table + * + * Adds the irqfd's wait queue entry to the kernel wait queue for event mo= nitoring. + */ +static void bao_irqfd_poll_func(struct file *file, wait_queue_head_t *wqh, + poll_table *pt) +{ + struct irqfd *irqfd; + + if (WARN_ON_ONCE(!pt || !wqh)) + return; + + irqfd =3D container_of(pt, struct irqfd, pt); + add_wait_queue(wqh, &irqfd->wait); +} + +/** + * irqfd_shutdown_work - Workqueue handler to shutdown an irqfd + * @work: Work struct for the shutdown operation + * + * Removes and frees the irqfd from the DM under lock if it is still linke= d. + */ +static void irqfd_shutdown_work(struct work_struct *work) +{ + struct irqfd *irqfd; + struct bao_dm *dm; + + if (WARN_ON_ONCE(!work)) + return; + + irqfd =3D container_of(work, struct irqfd, shutdown); + dm =3D irqfd->dm; + + if (WARN_ON_ONCE(!dm)) + return; + + mutex_lock(&dm->irqfds_lock); + if (!list_empty(&irqfd->list)) + bao_irqfd_shutdown(irqfd); + mutex_unlock(&dm->irqfds_lock); +} + +/** + * bao_irqfd_assign - Assign an eventfd to a DM and create an irqfd + * @dm: Bao device model to assign the eventfd + * @args: Configuration of the irqfd to assign + * + * Return: 0 on success, a negative error code on failure + */ +static int bao_irqfd_assign(struct bao_dm *dm, struct bao_irqfd *args) +{ + struct eventfd_ctx *eventfd =3D NULL; + struct irqfd *irqfd; + struct irqfd *tmp; + __poll_t events; + struct fd f; + int ret =3D 0; + + if (WARN_ON_ONCE(!dm || !args)) + return -EINVAL; + + irqfd =3D kzalloc_obj(*irqfd, GFP_KERNEL); + if (!irqfd) + return -ENOMEM; + + irqfd->dm =3D dm; + INIT_LIST_HEAD(&irqfd->list); + INIT_WORK(&irqfd->shutdown, irqfd_shutdown_work); + + f =3D fdget(args->fd); + if (!fd_file(f)) { + ret =3D -EBADF; + goto out_free_irqfd; + } + + eventfd =3D eventfd_ctx_fileget(fd_file(f)); + if (IS_ERR(eventfd)) { + ret =3D PTR_ERR(eventfd); + goto out_fdput; + } + irqfd->eventfd =3D eventfd; + + init_waitqueue_func_entry(&irqfd->wait, bao_irqfd_wakeup); + init_poll_funcptr(&irqfd->pt, bao_irqfd_poll_func); + + mutex_lock(&dm->irqfds_lock); + list_for_each_entry(tmp, &dm->irqfds, list) { + if (irqfd->eventfd =3D=3D tmp->eventfd) { + ret =3D -EBUSY; + mutex_unlock(&dm->irqfds_lock); + goto out_put_eventfd; + } + } + list_add_tail(&irqfd->list, &dm->irqfds); + mutex_unlock(&dm->irqfds_lock); + + events =3D vfs_poll(fd_file(f), &irqfd->pt); + if (events & EPOLLIN) + bao_irqfd_inject(dm->info.id); + + fdput(f); + return 0; + +out_put_eventfd: + eventfd_ctx_put(eventfd); +out_fdput: + fdput(f); +out_free_irqfd: + kfree(irqfd); + return ret; +} + +/** + * bao_irqfd_deassign - Deassign an eventfd and destroy the associated irq= fd + * @dm: Bao device model to remove the irqfd from + * @args: Configuration of the irqfd to deassign + * + * Return: 0 on success, a negative error code on failure + */ +static int bao_irqfd_deassign(struct bao_dm *dm, struct bao_irqfd *args) +{ + struct irqfd *irqfd; + struct irqfd *tmp; + struct eventfd_ctx *eventfd; + + if (WARN_ON_ONCE(!dm || !args)) + return -EINVAL; + + eventfd =3D eventfd_ctx_fdget(args->fd); + if (IS_ERR(eventfd)) + return PTR_ERR(eventfd); + + mutex_lock(&dm->irqfds_lock); + list_for_each_entry_safe(irqfd, tmp, &dm->irqfds, list) { + if (irqfd->eventfd =3D=3D eventfd) { + bao_irqfd_shutdown(irqfd); + break; + } + } + mutex_unlock(&dm->irqfds_lock); + + eventfd_ctx_put(eventfd); + + return 0; +} + +int bao_irqfd_server_config(struct bao_dm *dm, struct bao_irqfd *config) +{ + if (WARN_ON_ONCE(!dm || !config)) + return -EINVAL; + + if (config->flags & BAO_IRQFD_FLAG_DEASSIGN) + return bao_irqfd_deassign(dm, config); + + return bao_irqfd_assign(dm, config); +} + +int bao_irqfd_server_init(struct bao_dm *dm) +{ + char name[BAO_NAME_MAX_LEN]; + + if (WARN_ON_ONCE(!dm)) + return -EINVAL; + + mutex_init(&dm->irqfds_lock); + INIT_LIST_HEAD(&dm->irqfds); + + snprintf(name, sizeof(name), "bao-ioirqfds%u", dm->info.id); + + dm->irqfd_server =3D alloc_workqueue(name, WQ_UNBOUND | WQ_HIGHPRI, 0); + if (!dm->irqfd_server) + return -ENOMEM; + + return 0; +} + +void bao_irqfd_server_destroy(struct bao_dm *dm) +{ + struct irqfd *irqfd; + struct irqfd *next; + + if (WARN_ON_ONCE(!dm)) + return; + + if (dm->irqfd_server) + destroy_workqueue(dm->irqfd_server); + + mutex_lock(&dm->irqfds_lock); + list_for_each_entry_safe(irqfd, next, &dm->irqfds, list) + bao_irqfd_shutdown(irqfd); + mutex_unlock(&dm->irqfds_lock); +} diff --git a/include/linux/bao.h b/include/linux/bao.h new file mode 100644 index 000000000000..076f071086b6 --- /dev/null +++ b/include/linux/bao.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Bao Hypervisor Linux Kernel Header file + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#ifndef _LINUX_BAO_H +#define _LINUX_BAO_H + +#include + +/* Remote I/O Hypercall ID */ +#define BAO_REMIO_HYPERCALL_ID 0x2 + +/** + * struct bao_remio_hypercall_ctx - REMIO hypercall context + * @dm_id: Device model identifier + * @addr: Target address + * @op: Operation code + * @value: Value to read/write + * @access_width: Access width in bytes + * @request_id: Request identifier + * @npend_req: Number of pending requests + */ +struct bao_remio_hypercall_ctx { + u64 dm_id; + u64 addr; + u64 op; + u64 value; + u64 access_width; + u64 request_id; + u64 npend_req; +}; + +#endif /* _LINUX_BAO_H */ diff --git a/include/uapi/linux/bao.h b/include/uapi/linux/bao.h new file mode 100644 index 000000000000..5c97595637e6 --- /dev/null +++ b/include/uapi/linux/bao.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Provides the Bao Hypervisor IOCTLs and global structures + * + * Copyright (c) Bao Project and Contributors. All rights reserved. + * + * Authors: + * Jo=C3=A3o Peixoto + * Jos=C3=A9 Martins + * David Cerdeira + */ + +#ifndef _UAPI_BAO_H +#define _UAPI_BAO_H + +#include + +/** + * struct bao_virtio_request - Parameters of a Bao VirtIO request + * @dm_id: Device model ID + * @addr: MMIO register address accessed + * @op: Operation type (WRITE =3D 0, READ, ASK, NOTIFY) + * @value: Value to write or read + * @access_width: Access width (VirtIO MMIO supports 4-byte aligned access= es) + * @request_id: Request ID of the I/O request + */ +struct bao_virtio_request { + __u64 dm_id; + __u64 addr; + __u64 op; + __u64 value; + __u64 access_width; + __u64 request_id; +}; + +/** + * struct bao_ioeventfd - Parameters of an ioeventfd request + * @fd: Eventfd file descriptor associated with the I/O request + * @flags: Logical OR of BAO_IOEVENTFD_FLAG_* + * @addr: Start address of the I/O range + * @len: Length of the I/O range + * @reserved: Reserved, must be 0 + * @data: Data for matching (used if data matching is enabled) + */ +struct bao_ioeventfd { + __u32 fd; + __u32 flags; + __u64 addr; + __u32 len; + __u32 reserved; + __u64 data; +}; + +/** + * struct bao_irqfd - Parameters of an IRQFD request + * @fd: File descriptor of the eventfd + * @flags: Flags associated with the eventfd + */ +struct bao_irqfd { + __s32 fd; + __u32 flags; +}; + +/** + * struct bao_dm_info - Parameters of a Bao device model + * @id: Virtual ID of the DM + * @shmem_addr: Base address of the shared memory + * @shmem_size: Size of the shared memory + * @irq: IRQ number + */ +struct bao_dm_info { + __u32 id; + __u64 shmem_addr; + __u64 shmem_size; + __u32 irq; +}; + +/* + * The ioctl type for Bao, documented in + * Documentation/userspace-api/ioctl/ioctl-number.rst + */ +#define BAO_IOCTL_TYPE 0xA6 + +/* + * Bao userspace IOCTL commands + * Follows Linux kernel convention, see Documentation/driver-api/ioctl.rst + */ +#define BAO_IOCTL_DM_GET_INFO _IOWR(BAO_IOCTL_TYPE, 0x01, struct bao_dm_in= fo) +#define BAO_IOCTL_IO_CLIENT_ATTACH \ + _IOWR(BAO_IOCTL_TYPE, 0x02, struct bao_virtio_request) +#define BAO_IOCTL_IO_REQUEST_COMPLETE \ + _IOW(BAO_IOCTL_TYPE, 0x03, struct bao_virtio_request) +#define BAO_IOCTL_IOEVENTFD _IOW(BAO_IOCTL_TYPE, 0x04, struct bao_ioeventf= d) +#define BAO_IOCTL_IRQFD _IOW(BAO_IOCTL_TYPE, 0x05, struct bao_irqfd) + +#endif /* _UAPI_BAO_H */ --=20 2.43.0 From nobody Tue Sep 29 13:18:14 2026 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.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 E0FE23793B8 for ; Fri, 7 Aug 2026 07:41:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088470; cv=none; b=twLfU9+mLxBMsx9yXENelfCLUWrGEgUEDCR/WhfMUcB7uM31e24dQF3jy7Ki92rG6E19mvbPryhAigTRNB+JZrRuM0Og2mFEiJP9L7tSU/oJntlYPxJqbYAPnrKuiMmEWqctqj5h8Rh5JXWXl8wjeevUhA7Em316a+xqapCmIQU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088470; c=relaxed/simple; bh=niIyvbJ1E7z3qzfkdpOp8zB62jyGHXdyNynklJyVodQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MfgGlJ9/UaltwjNIrPn7GPYA1nXXXhUW7EiPoidvUkVM27HFTsJI59r79bIf3nNKKebikO6csxahzbjsLXTZcNhGpfsSNAu4llIAhuAOL1cOxLv+ysi/9vKnMlYjvZ3LaHHY4BFcFrlcyipxfME/QzoUJHVmMsG2fQVw6Y4KU1M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=none smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b=FBopS/uj; arc=none smtp.client-ip=209.85.221.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b="FBopS/uj" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-47db714766aso1032315f8f.0 for ; Fri, 07 Aug 2026 00:41:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20251104.gappssmtp.com; s=20251104; t=1786088467; x=1786693267; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=F8aHbeVjWIKrFsYTmN2+DAuK82NyrvO/pruFApuuKdA=; b=FBopS/ujRa/zLNfV3FQJulcfsm43gQ/tRaFRkSrc4GGuPyaG9tGJwMQGuZfEw2TUER DKECEuFGerlo0wHpv4J4tybGzTJohLKU7tktxFkU3JGg606H+4Udqk6wBlyrJJzlCdly x2cePh24o9ikLbgzZIM35oMyOGVUXC8DKr8+M12aryoug8eqH0f60QWhJdtGEK45ma+F BJUdRTYBdJg1p9eVgnGVRYVUXHqCCB9MB6uU7qUnkcTpYNsXvj+F/BsSnIUaHN7n6pfV 3LhiLFqudPSIQhcrcohbLMh97e8q6Tu+W+LoRyFQ98XIf4rLSUvDlgBdJnBcls5ydbiG //8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786088467; x=1786693267; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=F8aHbeVjWIKrFsYTmN2+DAuK82NyrvO/pruFApuuKdA=; b=X8Caj1jErZRT8gKPfYsJGO3/YKa7rv/WZ0fgjA7UCo9wqzxRMLXIpKPhIbMx5l3mUZ Gg0sDs8JNx0pq9WY6n9XG2KQ5Rtug2WLA69yguiueFbDtU4PVwVD0Jf8LHZfayr7UWbr OSj+FiVYK36HCJ6VMxJJq6arph6wOKSF/lv2ZmWc8GThXUpwdYQiK35vX1EIlYzQggpP xy280cYqIUxCAtDbfukcbhmBTj6uOBbwqNfkqMV7Lq4v0+W54M4nXHOiLiBP8SmORAWb DYWzuW9ATBIfOS/GDmvbn6uYz4XYYvSZWrh89PFJqjYPOA5iKJmZLI+vVtBEBiQ64e0D 8OMg== X-Forwarded-Encrypted: i=1; AHgh+RoW+x0Y2zWmIud9mi45JNZJqRxxKZux/CVrTVNn7A/dQ1OTmLPBifVjzISpavAjlzOPsOQgk8rulLAk+1w=@vger.kernel.org X-Gm-Message-State: AOJu0YynPGokM/w2IFXoE60P+fBlmIOjjYn7jqeN8oYarwq2baIhFu// Q/NNOW7EEf1Wa24x5KFMXVogNYZri+zcniWtRnR3d+7rb4epMYdv+7+Plm9LpZ6RS+Ju X-Gm-Gg: AR+sD12BM/T5S7PmOC0G5U6VgPB0Ne2dGsl3joiubzbjNIo1ACNAKsAT9b0AFOAHpHm NI4YVnBwXEPoq1+AA9/mrZ81eiWz7NMA5+IfFzB1an84hTz+ykZZNs9ZMpa8Ir5pCytKh/JBVz8 vLvc3qqtn3rM7A5AIwnOK8zA8ycRrf5ftNVDtk5hDZqKnV+s31yidWKgH2kT7yuY7ZfDLZA6C9V 4j3PJ6NhBzO5eevdZqOSHmFZxdZoJ0jpZhFz4mIVf+2P0mwGcddoniSoCInBSScCcD3skh2t3zb LA2WPJnoWgmqpaUGXT4otNRtWfAnZ1zuCNTjcF5J+2gxDWo8mmw0Sy3hUCds1w9Hplu4pDkmflq o5xCMqAcEoODusMJrBFAkbgjEcyrpkfvvRykzOKyZw77jsOrJW+ZGsm2tHetEYs4RUaluI6R5dc kE5pLQZux2twK2mNJg7/K76IdLSf9X04oKIUkk4G1ZAoc5NIQpSO8UEj1efrGMYZM= X-Received: by 2002:a05:6000:2913:b0:47f:ecbb:55fa with SMTP id ffacd0b85a97d-47ff4bc1a11mr16115409f8f.5.1786088467028; Fri, 07 Aug 2026 00:41:07 -0700 (PDT) Received: from jp-linux.Home ([2001:8a0:f59c:a900:2600:fba1:8d1e:1692]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-480021f90f8sm2819904f8f.26.2026.08.07.00.41.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 00:41:06 -0700 (PDT) From: =?UTF-8?q?Jo=C3=A3o=20Peixoto?= To: gregkh@linuxfoundation.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: jose@osyx.tech, davidmcerdeira@osyx.tech, corbet@lwn.net, skhan@linuxfoundation.org, catalin.marinas@arm.com, will@kernel.org, linux@armlinux.org.uk, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, andrew.jones@oss.qualcomm.com, rdunlap@infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-riscv@lists.infradead.org Subject: [RFC PATCH v3 5/6] virt: bao: consolidate the IPC hypercall ID in include/linux/bao.h Date: Fri, 7 Aug 2026 08:39:32 +0100 Message-ID: X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The IPC shared-memory hypercall ID was passed as a parameter through each architecture's bao_ipcshmem_hypercall() and defined locally in ipcshmem.c. Define it once in include/linux/bao.h, next to the Remote I/O hypercall ID, and reference it directly from the arch helpers. As there is only one IPC hypercall, this also lets bao_ipcshmem_hypercall() drop its hypercall_id parameter. Signed-off-by: Jo=C3=A3o Peixoto --- v3: - Rewrite the commit message to explain why the ID is consolidated and to describe the bao_ipcshmem_hypercall() parameter removal it performs (Greg KH). - The helper now takes a single argument and fits on one line; unwrap the remaining few-char line wraps (Andrew Jones). arch/arm/include/asm/bao.h | 5 ++--- arch/arm64/include/asm/bao.h | 5 ++--- arch/riscv/include/asm/bao.h | 6 ++---- drivers/virt/bao/ipcshmem/ipcshmem.c | 5 +---- include/linux/bao.h | 3 +++ 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/arch/arm/include/asm/bao.h b/arch/arm/include/asm/bao.h index eca258cc94e3..a7d608493723 100644 --- a/arch/arm/include/asm/bao.h +++ b/arch/arm/include/asm/bao.h @@ -16,14 +16,13 @@ #include #include =20 -static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, - unsigned long ipcshmem_id) +static inline unsigned long bao_ipcshmem_hypercall(unsigned long ipcshmem_= id) { struct arm_smccc_res res; =20 arm_smccc_hvc(ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, ARM_SMCCC_OWNER_VENDOR_HYP, - hypercall_id), + BAO_IPCSHMEM_HYPERCALL_ID), ipcshmem_id, 0, 0, 0, 0, 0, 0, &res); =20 return res.a0; diff --git a/arch/arm64/include/asm/bao.h b/arch/arm64/include/asm/bao.h index 1dc09a2c261b..5bd2a8c9905d 100644 --- a/arch/arm64/include/asm/bao.h +++ b/arch/arm64/include/asm/bao.h @@ -16,14 +16,13 @@ #include #include =20 -static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, - unsigned long ipcshmem_id) +static inline unsigned long bao_ipcshmem_hypercall(unsigned long ipcshmem_= id) { struct arm_smccc_res res; =20 arm_smccc_hvc(ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, ARM_SMCCC_OWNER_VENDOR_HYP, - hypercall_id), + BAO_IPCSHMEM_HYPERCALL_ID), ipcshmem_id, 0, 0, 0, 0, 0, 0, &res); =20 return res.a0; diff --git a/arch/riscv/include/asm/bao.h b/arch/riscv/include/asm/bao.h index 6dc0cb13c94c..a587a6abd54e 100644 --- a/arch/riscv/include/asm/bao.h +++ b/arch/riscv/include/asm/bao.h @@ -26,13 +26,11 @@ */ #define BAO_SBI_EXT_ID 0x08000ba0 =20 -static inline unsigned long bao_ipcshmem_hypercall(unsigned long hypercall= _id, - unsigned long ipcshmem_id) +static inline unsigned long bao_ipcshmem_hypercall(unsigned long ipcshmem_= id) { struct sbiret ret; =20 - ret =3D sbi_ecall(BAO_SBI_EXT_ID, hypercall_id, ipcshmem_id, 0, 0, 0, 0, - 0); + ret =3D sbi_ecall(BAO_SBI_EXT_ID, BAO_IPCSHMEM_HYPERCALL_ID, ipcshmem_id,= 0, 0, 0, 0, 0); =20 return ret.error; } diff --git a/drivers/virt/bao/ipcshmem/ipcshmem.c b/drivers/virt/bao/ipcshm= em/ipcshmem.c index 0d46d89ee788..5bf37c1c7933 100644 --- a/drivers/virt/bao/ipcshmem/ipcshmem.c +++ b/drivers/virt/bao/ipcshmem/ipcshmem.c @@ -14,9 +14,6 @@ =20 #define BAO_IPCSHMEM_NAME_LEN 16 =20 -/* IPC through shared-memory hypercall ID */ -#define BAO_IPCSHMEM_HYPERCALL_ID 0x1 - struct bao_ipcshmem { struct miscdevice miscdev; u32 id; @@ -104,7 +101,7 @@ static ssize_t bao_ipcshmem_write(struct file *filp, co= nst char __user *buf, *ppos +=3D count; =20 /* Notify Bao hypervisor */ - bao_ipcshmem_hypercall(BAO_IPCSHMEM_HYPERCALL_ID, bao->id); + bao_ipcshmem_hypercall(bao->id); =20 return count; } diff --git a/include/linux/bao.h b/include/linux/bao.h index 076f071086b6..17d6ea472521 100644 --- a/include/linux/bao.h +++ b/include/linux/bao.h @@ -15,6 +15,9 @@ =20 #include =20 +/* IPC through shared-memory hypercall ID */ +#define BAO_IPCSHMEM_HYPERCALL_ID 0x1 + /* Remote I/O Hypercall ID */ #define BAO_REMIO_HYPERCALL_ID 0x2 =20 --=20 2.43.0 From nobody Tue Sep 29 13:18:14 2026 Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) (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 DC7A1463B6A for ; Fri, 7 Aug 2026 07:41:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088474; cv=none; b=POsHoIDBSymSUq3eM1PsKzzCE2Z+vVAiRCf2uBeQXlxNRQUOETzoRWqOJQ9YHSLLl6R3hxd8E9vQxnT9VfopOS3DbZ7HfPz+StsN/4QedB8P+vEFGvlD31PgSLXPBurleUIseCAOyri3rWihnRoia3AQe2DFpB9aWX+ycJ+tQNg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786088474; c=relaxed/simple; bh=xG15iNNB4iSjwj+E1PRwG/+wOUT70QeBoc+dFwOCJV4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nl1eFW8FoJy4zL5G82ODzfo9ogsTGHbbE1E//W4ma4KaZfU5KZgPzcSMDAnr3hK66TrLNToma+gYK77ZW3nweuHPO191CveP/m1x9lsuT8sirB/z8Xaog8gsUFxaAwvgEUMZL2ftisahdado/RpAlaQvW/qzC4EEvZOlFGH2nog= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=none smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b=Ax5p19kv; arc=none smtp.client-ip=209.85.221.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20251104.gappssmtp.com header.i=@osyx-tech.20251104.gappssmtp.com header.b="Ax5p19kv" Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-47fde295992so1464472f8f.0 for ; Fri, 07 Aug 2026 00:41:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20251104.gappssmtp.com; s=20251104; t=1786088470; x=1786693270; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=aSYQ6Hen3CMyNgjH1etqMkMNKiGDMJrXBqBRp7LU9i4=; b=Ax5p19kvi2vXf458Vtr7VSmSKUeAsEiwbzW6W9ut2yhikh15RrT3e8z4Dbx48i7zA8 IEFiM9g5xWk9rmdtR8C6+0xvnwZ8+a8tfBAMXCs7F3MmAr2yTbOOAjR788o0RphVcEN7 c6hXIA+TyqdXrxCWuixW1dWKHIg6gqVkkHJ57kubCf1a7nIwuXoQ9SarYZtp7+FxM62Q 1QOxIJ9wVjLum8x7IlZBDrtzREajw0c4VvQytMp6MtJdecDT1vgPtBg/7Td2wl+Qm5eF D70Hloa6KAEcruHDZUNo8tT+UjteVqggPIhub1V4NtjZyJrKx1vsuqlObSJHbn98+Up0 +jsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786088470; x=1786693270; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=aSYQ6Hen3CMyNgjH1etqMkMNKiGDMJrXBqBRp7LU9i4=; b=K+h4cQeQDYuNbfP1GEv0cmOEoJE+TtgcqVFJ8BfQDQHBUf9/DCuhN61xs5lgXZPPg3 rbn/oCOecx8LZCwoujrWkv8UQjYLZpOPBW/aZEEhyGu0esZETy082IVNzqNXl8s9yH4h HysJFZNM7B3dTAZYoco8SM2SkumsXufE8i8oxslF9xdWwheENgqZozV1XYXMyP/3pUkQ QBjLhmMMMJM/WVhvus7rGXJdUEpwP+U/KvVF77WEvVuodYGAQXGtOOHIUXmbDOl3NYYb RDFzmmg4WuBMD+qoEXtGa9H3JrS4D3F6HWAiENRuHt43f4pYQwFb0MXhHHlyVNDWchiF 3sLw== X-Forwarded-Encrypted: i=1; AHgh+RpwJM8lfsjswZQSHXGG3uFA6Rf5jJVwXpZBWOfLn6HlIQc5CoD3jcmw+CIL+OG52H8OdWxkNi6gUaQhWhY=@vger.kernel.org X-Gm-Message-State: AOJu0YytdudCIZSYTgOPhWXYsb8sd+hlm8SMI2uO77cbTpp2uu0ATrkK 0WyL8wLIq4C9LDUWF/6Wxx8y/x9EkcFdABvpOx5SX8H+kgY+LUPrSkSazvj9BBwCXT7h X-Gm-Gg: AR+sD110PmOHoqQbxaZjw99Pw8362SIG99c9cIoeCpjKxCdHjKH5nN7DxMxGKcIbAKF Ye8kq21LEdgbbP0AgDVEDpVHne1c2OmKuCpT4kuof4VPE5XfwRa0c05MSGYgjCCZkp5R04gkurO 66eD+0cGELzKYf1A4bW+VJcgjW/Hy47N0x24tlz/1iRPiV7GbqurpiGwPgKQIMPdqp85pQd2urF NVnWgSuFa6VXHlNdLRAC7o9QSCfCfyBAOs7FK4u/TA7vo5phfHkVPitQLei/WrbBNU1e81ZGGO4 ZWiSTWUARalfZ371Pn5AwWX7Hy+tr7E6VB2Ig7thTOurEWbF+69y+eDJXWuzqG8Lj8/jIOjzK2v 7OjPHF/E0bg/VSjCmtIbxr9yE/sxVdDuK37TXh9TZWva8vFIrR+baxtJKk5F9W7ksNVzkxyjPdE rqHU2kAcFqrqlekMFr/8AILoCJcAzHshcfdPM274V30uC0f8smGJIvA2GDISyWfXw= X-Received: by 2002:a05:6000:388:b0:47f:8cd3:4bed with SMTP id ffacd0b85a97d-47ff8694ef6mr16251068f8f.5.1786088470034; Fri, 07 Aug 2026 00:41:10 -0700 (PDT) Received: from jp-linux.Home ([2001:8a0:f59c:a900:2600:fba1:8d1e:1692]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-480021f90f8sm2819904f8f.26.2026.08.07.00.41.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 00:41:09 -0700 (PDT) From: =?UTF-8?q?Jo=C3=A3o=20Peixoto?= To: gregkh@linuxfoundation.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: jose@osyx.tech, davidmcerdeira@osyx.tech, corbet@lwn.net, skhan@linuxfoundation.org, catalin.marinas@arm.com, will@kernel.org, linux@armlinux.org.uk, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, andrew.jones@oss.qualcomm.com, rdunlap@infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-riscv@lists.infradead.org Subject: [RFC PATCH v3 6/6] MAINTAINERS: add Bao hypervisor entry Date: Fri, 7 Aug 2026 08:39:33 +0100 Message-ID: <08c7768ee758e2b65ae50dc9b801355f378106b8.1786010512.git.jpeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add a MAINTAINERS entry covering the Bao hypervisor drivers, the architecture headers, the in-kernel and UAPI headers, and the device-tree bindings. Signed-off-by: Jo=C3=A3o Peixoto --- v3: - Concise commit message (Krzysztof Kozlowski). MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a9..6a81a8da58f1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4519,6 +4519,19 @@ F: drivers/video/backlight/ F: include/linux/backlight.h F: include/linux/pwm_backlight.h =20 +BAO HYPERVISOR +M: Jos=C3=A9 Martins +M: David Cerdeira +M: Jo=C3=A3o Peixoto +S: Maintained +F: Documentation/devicetree/bindings/bao/ +F: arch/arm/include/asm/bao.h +F: arch/arm64/include/asm/bao.h +F: arch/riscv/include/asm/bao.h +F: drivers/virt/bao +F: include/linux/bao.h +F: include/uapi/linux/bao.h + BARCO P50 GPIO DRIVER M: Santosh Kumar Yadav M: Peter Korsgaard --=20 2.43.0