From nobody Sun Feb 8 08:36:49 2026 Received: from mail-wr1-f68.google.com (mail-wr1-f68.google.com [209.85.221.68]) (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 0195837A4AD for ; Wed, 7 Jan 2026 16:29:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.68 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803387; cv=none; b=ll3wf763nkk/FE+s9ZmQ9UxalYDnUUv1hYJpSnz0gwR9TuBiFljlCojsEk5DFPGEUGHk3TDYxrUyoStH9rz1yF6RZdGuFQK2+/7F/IhxoyAL7cbJvKLYI6b4tFjsCO4CINRU2gyAc1RwHrszLC7fIfVSR6TO6g7ya6v29p4BK8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803387; c=relaxed/simple; bh=oAuMYqefV0Wi9VhdkCSojuqJJYP2+QlUbyj1AsBLPnM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ttNxPtokaPDyTIOE47g0AaFrvYKwsq5sti2ZaGh0zaYZaEXCJrHLWGcy0c1UdXyMdFd5REISoJD/lbZJRiiXhBcehpUe4Pq2vZUrdf/vxnevoFga1LWNqxStGit7lp5Z/yj1BjbbNlhRhOzNljwWGFRl9SIV8S0XKsSV0u+Ro4Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=fail smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b=P1O1Q76z; arc=none smtp.client-ip=209.85.221.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b="P1O1Q76z" Received: by mail-wr1-f68.google.com with SMTP id ffacd0b85a97d-430f2ee2f00so1216463f8f.3 for ; Wed, 07 Jan 2026 08:29:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20230601.gappssmtp.com; s=20230601; t=1767803370; x=1768408170; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dvVGowKlmlOk8ufl2dgbwZUQhdQ7tHUGcyk69lSV+dw=; b=P1O1Q76zsdGjugbH1YnjP/PT/dZI5VPWJ5brFYqBVo7N8H/wFpA4po+K3s+sF8QV2a ImT7+3B7yTYQKFoq60wQJ4vfRMJk0S5nWsbBu2NrdK06h/GRYKOxZO1Q8iO/jqbEC7OS Mo2maFrGqXEIP0FOCLovs13kX/rOL5osL9f60W5kJZE9gnomuL3NN3aQTTUEDz+CQqyP oTPw8kF0aQ4AWIWVrQ1JWT/YtmpvzKQ67r0f6kVXE2L6RizZnCebiGYL1jAJqkQKWs2R u7XuVBQcjO6hz4PfppjFbytmy2bnxxfMEMiV6jF/o39VwZydVAAKP3t/RHfqsOrP4W1z dS3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767803370; x=1768408170; h=content-transfer-encoding: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; bh=dvVGowKlmlOk8ufl2dgbwZUQhdQ7tHUGcyk69lSV+dw=; b=PT/qN5Fa3fUlfkBVNQ8RqWi/bLKyJ3G52MdzM0IXGiKieg6FLt2fd3m+K/OaYgJ/5B 62yIi3gu/5xAvA9Nka63BvRFeMd/l2s1zYVEyJY6bFbhakYCgeD/GKxz/ay8ulvDL5Kz qRrJiM+xXP+bBtYK0NOR4tSssqRqFfiHLEPJLCVBl8FDUOuY6FkWDVLd/4M4ArAi9m+O EW64AiUitX7y5t0mMYJVI6UGXSkvGD5mRFBexSOv/argLRZbJaiBYpQoQ4fl+usV6v4Q qdtt6GxKLeYocb94g8/XrRTR1z+6QMKr2MeDMLmx5wiUVxmWkfMOCObKbzHPa7Z7tGwr Ezdg== X-Gm-Message-State: AOJu0Yz5P8ebDwD1BQqvnoziMvcOt5Nbd5pd1ObWWVBgtQJQQh23YNXc rVozS6iidU/sCG1OzuMRXIjR+gXwq27MGjKU6ABp3b1ysCbiwM1McwJyzbp2gGo81an3UuS87jZ K6iKIRQ== X-Gm-Gg: AY/fxX5YczTAQFS6MqbYlpnaPwp4UlamWaCHFuJLzu710F5CoZ8GnnI+X8nqZMpRJVg jO3PxuY64721N36N6oaWxliqFd77kwJd9z1le4Bwwlu58qrrT4tRaFs/9Yo0eaU78gLvGKQBBqm rPVKEMaZChSRdbdHidMmxFYhkgNF5plzEIy5oLgSWSh0HM7DVyj4BzGG4YCgNEjSqKo/j4mJPDl BD+B7FQlNVzGhicf+9KlObGNtZiTzFdqdtpnz9DYauZ5GfG9VaaAye1T4beKFWKvo2RtW1HCdAG 4UICe/IsNxARa4NyGrBDfRmGP0T9RFSky2pF90eu29S76CYCP0oTsKFm8hOQBvXOWr1n2M25CoJ X+DgMGauuRkjx6xmo21iz3HREnr2CfTAEaqJAWh0rgvrnsHji0bzBwvWIhyjxLZDkhl80R989at Fp3+qiNIRITRfto9DfSmu4muc/gMAF X-Google-Smtp-Source: AGHT+IGZvgVIRVCpFA27SlFxqTQCtBZyTJkVQlpD5nx0fxVjL9cGeTsV0wkJ5rzD4sY1Y62BW2/V+g== X-Received: by 2002:a05:6000:144f:b0:431:54c:6f8 with SMTP id ffacd0b85a97d-432c377239fmr3846262f8f.1.1767803370264; Wed, 07 Jan 2026 08:29:30 -0800 (PST) Received: from jp-linux.Home ([2001:8a0:f59c:a900:4a3c:13be:a1c0:7b9f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd5ff0b2sm11117030f8f.42.2026.01.07.08.29.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jan 2026 08:29:29 -0800 (PST) From: joaopeixoto@osyx.tech To: linux-kernel@vger.kernel.org Cc: ajd@linux.ibm.com, alex@ghiti.fr, aou@eecs.berkeley.edu, bagasdotme@gmail.com, catalin.marinas@arm.com, conor+dt@kernel.org, corbet@lwn.net, dan.j.williams@intel.com, davidmcerdeira@osyx.tech, devicetree@vger.kernel.org, dev@kael-k.io, gregkh@linuxfoundation.org, haren@linux.ibm.com, heiko@sntech.de, joaopeixoto@osyx.tech, jose@osyx.tech, kever.yang@rock-chips.com, krzk+dt@kernel.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, maddy@linux.ibm.com, mani@kernel.org, nathan@kernel.org, neil.armstrong@linaro.org, palmer@dabbelt.com, pjw@kernel.org, prabhakar.mahadev-lad.rj@bp.renesas.com, robh@kernel.org, will@kernel.org Subject: [PATCH 1/6] dt-bindings: Add Bao IPC shared memory driver binding Date: Wed, 7 Jan 2026 16:28:24 +0000 Message-ID: <20260107162829.416885-2-joaopeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260107162829.416885-1-joaopeixoto@osyx.tech> References: <20251224135217.25350-1-joaopeixoto@osyx.tech> <20260107162829.416885-1-joaopeixoto@osyx.tech> 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 From: Jo=C3=A3o Peixoto This patch introduces a device tree binding for the Bao IPC Shared Memory device, which enables communication between Bao hypervisor guests through dedicated shared-memory regions. Signed-off-by: Jo=C3=A3o Peixoto --- .../devicetree/bindings/bao/bao,ipcshmem.yaml | 82 +++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.yaml | 2 + 2 files changed, 84 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..fa91800db99a --- /dev/null +++ b/Documentation/devicetree/bindings/bao/bao,ipcshmem.yaml @@ -0,0 +1,82 @@ +# 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 IPC Shared Memory Device + +maintainers: + - Jos=C3=A9 Martins + - David Cerdeira + - Jo=C3=A3o Peixoto + +description: | + Shared memory based communication device for Bao hypervisor guests. + + The device describes a set of shared-memory regions used for + communication between Bao guests. Each guest instantiating this + device uses one region for reading data produced by a peer guest + and another region for writing data consumed by that peer. + +properties: + compatible: + const: bao,ipcshmem + + reg: + description: + Shared memory region used for IPC. + minItems: 2 + maxItems: 2 + + read-channel: + description: | + Shared-memory sub-region that this guest reads from. + + This region is written by the peer Bao guest and read by the + guest instantiating this device. + + Consists of two cells: + - offset into the shared-memory region defined by `reg` + - size in bytes + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 2 + + write-channel: + description: | + Shared-memory sub-region that this guest writes to. + + This region is written by the guest instantiating this device and + read by the peer Bao guest. + + Consists of two cells: + - offset into the shared-memory region defined by `reg` + - size in bytes + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 2 + + id: + description: + Driver instance ID. + $ref: /schemas/types.yaml#/definitions/uint32 + +required: + - compatible + - reg + - read-channel + - write-channel + - id + +additionalProperties: false + +examples: + - | + bao-ipc@f0000000 { + compatible =3D "bao,ipcshmem"; + reg =3D <0x0 0xf0000000 0x0 0x00010000>; + read-channel =3D <0x0 0x2000>; + write-channel =3D <0x2000 0x2000>; + id =3D <0>; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Docum= entation/devicetree/bindings/vendor-prefixes.yaml index c7591b2aec2a..c047fbd6b91a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -223,6 +223,8 @@ patternProperties: description: Shenzhen AZW Technology Co., Ltd. "^baikal,.*": description: BAIKAL ELECTRONICS, JSC + "^bao,.*": + description: Bao Hypervisor "^bananapi,.*": description: BIPAI KEJI LIMITED "^beacon,.*": --=20 2.43.0 From nobody Sun Feb 8 08:36:49 2026 Received: from mail-wr1-f65.google.com (mail-wr1-f65.google.com [209.85.221.65]) (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 EFF2837A49B for ; Wed, 7 Jan 2026 16:29:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.65 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803391; cv=none; b=YEwHN60PikugXug1R6E5Y0q5sRl4Rmi2VhSxzU43eP9mEh5Zs0rU6sxKT3pZv6uQK+3G2tDpT4bERwJwPohuu/afhdnDK0vQQDILY/RfDaKVH0C+sSdfZ6a49RqDGMnUOtaHLmoOlrFK62LFvGnt5vZ4o6wet9MgbMzywd22Ng4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803391; c=relaxed/simple; bh=zl1jwg2gKNm5qzsM288sPh+uUZsQUL35tLvVZtYaJ+g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Jhk7JNwZuhojA4n+LTDa27ow8B0FygmR7q160+wALUF0LtYcpyUUDpw4wKFosCc9J9NsKRzgEN//j05BOk2LXliaWZuhTIOa9VcigI410FGXzmLZ+w9YSZfjvliN6UE4mO3yKe88tt4cegvyIMzUZ2rr3PZF6p2xYyGUV/ctzxY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=fail smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b=Bkl12b/E; arc=none smtp.client-ip=209.85.221.65 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b="Bkl12b/E" Received: by mail-wr1-f65.google.com with SMTP id ffacd0b85a97d-43277900fb4so432098f8f.1 for ; Wed, 07 Jan 2026 08:29:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20230601.gappssmtp.com; s=20230601; t=1767803374; x=1768408174; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8HPNqrSFVKujuMbBVT0dC7TbAVMvjtBKRilIfMHMtDk=; b=Bkl12b/EcSCIfi5dU7mMkDgYpTRypb1lunBebb5qUH37ZLlPsfzkuR+g+LzOkjakE/ SeEWhjBvZR9gsrB1pvhgpyJQ5OfpwwUo2S3TqvWx6Toa0jdOfJiV1Lme24k8G9y2Qu7P qX/2q8EJt+OjKIq95nNiaH1Rbi84rAJ4VKf/X522Si7FNatCvf1sxPE8kgOav9W8c7sL yCeaDd2rKjXAqDoYGooKl+dBj0tweUVIzvCycIDqZyR00UtBMvCqayW5b9aYvXI7MX+S QTm185DOyJE3lgpE3GkczzshyC+IiiwCcboskYdMmDT9KpMdELYDyO8G7LYIHVk23I7U VR3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767803374; x=1768408174; h=content-transfer-encoding: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; bh=8HPNqrSFVKujuMbBVT0dC7TbAVMvjtBKRilIfMHMtDk=; b=RbvqSAMkKP2o/Bm8jalhbLXd3SSrfH1AnSleU2AcDhaTgXLOGu/nL4/XvQ10IZqB3J QQg5BP0LtqEDTNaPG6CIY+fWqUQl7+jJ4UGZrOLFIG2l5v8jQdqFYklJ/bliowk/qNzR Q8kCctLvYe0bIhiZoWmiJgIvORLFhzSshAszKWKmSGuA4ZotQbrowNaFReh7T4sd6iM7 SacZJmUc9RFa2aTEouqhUtAnHeqNEOk/bnFLOtCMVJODZbLGlhBsXRgzGRVoJ5gKGyxF IJRp0aVtJfsJ4lbGhEn/3tRJZnrOI9zegZt5oeaOpawlhR+qYGIf6N4wFyBYb4l+mm3m Mm/A== X-Gm-Message-State: AOJu0YwHERUbf9xIvdc00oDAn6OZkFZwAJeQkMUlURybJMWXcAep1asP iDHE9UZvCYcVLwHID5jfQKxVDY/EBB76RLA36tVaEM0Y6YUGsuVs0sgtYSf2PwxFwqA2GWtBMvW jH5pKMw== X-Gm-Gg: AY/fxX7i3R5STPGYPq5AKgHyzDDDFEASdcGUdIjMRLl8SC4Iim5T+8kIz+67fi/8CCf zXOCjMo9eo7XGFiWQKEJDFtQjTGdvYXsaFnFRVj8ssNgSXnk0G1dBswV8D5BzcdD0x3O27nXkDP 1C62bPA09cu6FiltCDpkdujP3fZeGYDspSfgVPW1pD6kdFqS1EqG+Z94/8nU0Kl/ymB5vraUasM F8FXrh6yejUbohXpXmn+CeEXJxPyevptCF+ldwDplSDIbExpPCVgh2g/cIO/zqH8LZxTpjMAdvD v7fV4Koqr/v69P91z+D9WHsi5H9WWotdkj2OEnzLA2hMyvOW3EHG11mzkGfNqi6CgrP6NHVK8ao QSK/4YGdZhtHz5gJHTDo9UNs00pVvWrccq7hgWTZS3aI3gebMwaJqMQYYtxl/yyCj1lSUOZzPCJ INCoh4RRCYip3ikDU8Nw== X-Google-Smtp-Source: AGHT+IGJrlF3s3eyP+Qr2nS5bqOk0Kkf15A73EhcdLN/8sE4VGXMhLijfR5Bmn2Z030dWid+RAstUg== X-Received: by 2002:a05:6000:208a:b0:431:8bf:f08c with SMTP id ffacd0b85a97d-432c376238amr4142095f8f.21.1767803373687; Wed, 07 Jan 2026 08:29:33 -0800 (PST) Received: from jp-linux.Home ([2001:8a0:f59c:a900:4a3c:13be:a1c0:7b9f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd5ff0b2sm11117030f8f.42.2026.01.07.08.29.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jan 2026 08:29:33 -0800 (PST) From: joaopeixoto@osyx.tech To: linux-kernel@vger.kernel.org Cc: ajd@linux.ibm.com, alex@ghiti.fr, aou@eecs.berkeley.edu, bagasdotme@gmail.com, catalin.marinas@arm.com, conor+dt@kernel.org, corbet@lwn.net, dan.j.williams@intel.com, davidmcerdeira@osyx.tech, devicetree@vger.kernel.org, dev@kael-k.io, gregkh@linuxfoundation.org, haren@linux.ibm.com, heiko@sntech.de, joaopeixoto@osyx.tech, jose@osyx.tech, kever.yang@rock-chips.com, krzk+dt@kernel.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, maddy@linux.ibm.com, mani@kernel.org, nathan@kernel.org, neil.armstrong@linaro.org, palmer@dabbelt.com, pjw@kernel.org, prabhakar.mahadev-lad.rj@bp.renesas.com, robh@kernel.org, will@kernel.org Subject: [PATCH 2/6] virt: bao: Add Bao IPC shared memory driver Date: Wed, 7 Jan 2026 16:28:25 +0000 Message-ID: <20260107162829.416885-3-joaopeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260107162829.416885-1-joaopeixoto@osyx.tech> References: <20251224135217.25350-1-joaopeixoto@osyx.tech> <20260107162829.416885-1-joaopeixoto@osyx.tech> 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 From: Jo=C3=A3o Peixoto This driver provides an interface for guests running on the Bao hypervisor to communicate with each other through shared-memory channels. Each guest is assigned a dedicated read and write region defined in the device tree. Userspace can access these regions via standard read/write/mmap operations. Writes to the write region trigger a hypervisor notification through an architecture-specific hypercall (HVC on ARM, SBI ecall on RISC-V). Signed-off-by: Jo=C3=A3o Peixoto --- 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 | 8 + drivers/virt/bao/ipcshmem/Makefile | 3 + drivers/virt/bao/ipcshmem/ipcshmem.c | 255 +++++++++++++++++++++++++++ 10 files changed, 368 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..9644d06be705 --- /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..a1819966b59b --- /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..35658f37e1bd --- /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..966bb75aa495 --- /dev/null +++ b/drivers/virt/bao/ipcshmem/Kconfig @@ -0,0 +1,8 @@ +# 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. 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..f3892d41248c --- /dev/null +++ b/drivers/virt/bao/ipcshmem/ipcshmem.c @@ -0,0 +1,255 @@ +// 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; + int id; + char label[BAO_IPCSHMEM_NAME_LEN]; + void *read_base; + size_t read_size; + void *write_base; + size_t write_size; + phys_addr_t physical_base; + size_t shmem_size; + void *shmem_base_addr; +}; + +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 paddr; + + if (!vsize) + return -EINVAL; + + if (offset >=3D bao->shmem_size || + vsize > bao->shmem_size - offset) + return -EINVAL; + + paddr =3D bao->physical_base + offset; + + if (!PAGE_ALIGNED(paddr)) + return -EINVAL; + + return remap_pfn_range(vma, vma->vm_start, paddr >> 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 *r; + struct bao_ipcshmem *bao; + resource_size_t shmem_size; + u32 write_offset; + u32 read_offset; + u32 write_size; + u32 read_size; + u32 id; + bool rd_in_range; + bool wr_in_range; + bool disjoint; + 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(np, "id", &id); + if (ret) { + dev_err(dev, "missing or invalid 'id' property\n"); + return ret; + } + + ret =3D of_property_read_u32_index(np, "read-channel", 0, &read_offset); + if (ret) { + dev_err(dev, "failed to read 'read-channel' offset: %d\n", ret); + return ret; + } + + ret =3D of_property_read_u32_index(np, "read-channel", 1, &read_size); + if (ret) { + dev_err(dev, "failed to read 'read-channel' size: %d\n", ret); + return ret; + } + + ret =3D of_property_read_u32_index(np, "write-channel", 0, &write_offset); + if (ret) { + dev_err(dev, "failed to read 'write-channel' offset: %d\n", ret); + return ret; + } + + ret =3D of_property_read_u32_index(np, "write-channel", 1, &write_size); + if (ret) { + dev_err(dev, "failed to read 'write-channel' size: %d\n", ret); + return ret; + } + + shmem_size =3D resource_size(r); + + rd_in_range =3D (read_offset + read_size) <=3D shmem_size; + wr_in_range =3D (write_offset + write_size) <=3D shmem_size; + disjoint =3D ((read_offset + read_size) <=3D write_offset) || + ((write_offset + write_size) <=3D read_offset); + + if (!rd_in_range || !wr_in_range || !disjoint) { + dev_err(dev, "invalid read/write channel ranges\n"); + return -EINVAL; + } + + bao =3D devm_kzalloc(dev, sizeof(*bao), GFP_KERNEL); + if (!bao) + return -ENOMEM; + + bao->shmem_base_addr =3D + devm_memremap(dev, r->start, shmem_size, MEMREMAP_WB); + if (!bao->shmem_base_addr) { + dev_err(dev, "failed to remap shared memory\n"); + return -ENOMEM; + } + + bao->id =3D id; + bao->read_size =3D read_size; + bao->write_size =3D write_size; + bao->read_base =3D (u8 *)bao->shmem_base_addr + read_offset; + bao->write_base =3D (u8 *)bao->shmem_base_addr + write_offset; + bao->physical_base =3D r->start; + bao->shmem_size =3D shmem_size; + + scnprintf(bao->label, BAO_IPCSHMEM_NAME_LEN, "baoipc%d", 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); + + dev_info(dev, "Bao IPC shared memory device '%s' registered\n", bao->labe= l); + return 0; +} + +static void bao_ipcshmem_remove(struct platform_device *pdev) +{ + struct bao_ipcshmem *bao =3D platform_get_drvdata(pdev); + + if (bao) + 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 Sun Feb 8 08:36:49 2026 Received: from mail-wr1-f65.google.com (mail-wr1-f65.google.com [209.85.221.65]) (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 B7FB237D1A7 for ; Wed, 7 Jan 2026 16:29:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.65 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803395; cv=none; b=teYM8A4CybiqpIpx9lK0nHVBxnOXO2sAuZZ+5ncRMr6ddkdnGfLpPCEdi4xjc7YCHLy2XefaD+RGVvAY1tLmZ6otZVuJOJgswmiYjoqccm+LdrQ2+y0+2ss43rSlPkwjyt6LZSZltIKTfWvLWVEKL8Yr50r/0k+nMhwVGsWqkpM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803395; c=relaxed/simple; bh=rLPl1zE7Upmz6OuVCre9yIxlCuXxDlH9iwpLAwe5XqA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HKOOXIad79ki+xfrID7J9aNv6VwijCHvQYYWt5BN9FVx8skbnjJIw8BmKItVm3pBuxWXDqatXtXRha3c5fSWlWWTmjnoNG2E6/XXJlVENbDR9XpRYVpF9LFDlWpzb9sOXt/LVlIf1yJOoh8YFxoYh9iPUcgfo2nyIdY/g+cqyfw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=fail smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b=iLvx/tSg; arc=none smtp.client-ip=209.85.221.65 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b="iLvx/tSg" Received: by mail-wr1-f65.google.com with SMTP id ffacd0b85a97d-42fbc305882so1182225f8f.0 for ; Wed, 07 Jan 2026 08:29:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20230601.gappssmtp.com; s=20230601; t=1767803377; x=1768408177; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NUMimnmdXF+2lmQCSaKYy80Xx8SLq3LRSYV8Quqc2EA=; b=iLvx/tSgpPTvGL+P9DpQHrzJo6RPGDMNLhBbwyw+AMJwYO9hhcH5yyM+w1SY7/27fP W9gNXX/WNbQvGhECwUai6NdO3bLN8RJl/dT9NWbcJdZ3zEDMvkRKwRfNCj2IkkHmx/Gj /2ncCfJEpeUL4EaxYfLAwZ8Q9gH41bx6xYlCkltYg6ZXij3ShPGZaEtRxa9K4GHVayVi JYnEjcdcD6Xpz1fw122nbrth0gMIkWTayG7rZpHhfO+l5+GrEfsJ3YHyUMo+FCEumUBy 4hnB2Zm7Xzs/yzVowYBVu5REU6zsPwjJFbmc0znU5eGUkJG0aJUnwuqGEsTqEToOGz20 zxKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767803377; x=1768408177; h=content-transfer-encoding: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; bh=NUMimnmdXF+2lmQCSaKYy80Xx8SLq3LRSYV8Quqc2EA=; b=i5huFveeo6GVRBMAzQNi3cahENwDQ/Yj5cTV4IWRdppQAKgTtr66znrDrWXbZzcitf U6ZFHFTBu07Ust469lB/mTBL0HhYjqE3asjerdv85UWyWwbvsI5TXQrIHCR6A7HdY0Qp MZ7CHJkozK18VdMw7aBsy7xCCJn2egWmQpdM0KuhuORtN7Ct1vS9wdP/qm+Y3O7LicbE eVrqPbNPevbdmR/EvfioVYp0E/ePsByl4azu7J1jH35fuKxO6D2zggzWz92b9d3khsS0 mM+3YyWnpp3Xj3WAaKsP9c/vB3Wa+o8h+NTyjt94agIE5qQrEnEUquGVZoa16qfx1sa6 EneQ== X-Gm-Message-State: AOJu0YxrlOxJ75zRwjSQgtjAjt3tEwoerPtmUw177ykTVHBtuaJXIiQt j6jl6vIUDPFNGfCH2SUXEqVzX4QGkYIueYxBn4HCx2HeIaS6UEvUsmLNxVOLocisimpRRdz49Mh s5zbDaQ== X-Gm-Gg: AY/fxX5k/KknGCsNqfLKwPRWftLUwbxZmd+PsktLs5LXAUuJ3gbGzRp3WU68CfZAGHR KHwVSVvP6aUv+8Wyd7lWEKXVbgOk7kgUeQUuzOP5V9IHFhU21k+ig1eZAz94TxSsKp1w7ECq4eF 1110rX+lo34O2cn5Q13LrquoBNurH9SAQne5B1M2nYjUzHwgTTjPyRda4FAf2AM5jb5g18ul5Ke h0krF/DbMd/ndUVlGvW87fOzOdA8UWo5SV6CbCmmqiOk1JRdRQa5MUYLA3I647upCkzZO4JnGKd vMBNJqxf5k/MvKoYijfVKtznDZ8wdMy/MiA5YzHCQzIV87eVP6Ah6vvr7BoOIEgF/T7GQAtuUqI MZ01+IKaOydHNlC1BwHJmaFJsO7D6MGpwIN7eMC3fwrDOqlIyammvEKYx8KA52YYT0qGXyhQWb4 nIKP28fFHYcHKkPTX/Jg== X-Google-Smtp-Source: AGHT+IHbte2Z9gfsJb68imADTi55zsYUmZZE1DMqWC4ozVwMek+FiE+B/1QJjWhTUxGd71ZKE6jVRA== X-Received: by 2002:a05:6000:310b:b0:432:5bac:3914 with SMTP id ffacd0b85a97d-432c374f46cmr3857592f8f.40.1767803376686; Wed, 07 Jan 2026 08:29:36 -0800 (PST) Received: from jp-linux.Home ([2001:8a0:f59c:a900:4a3c:13be:a1c0:7b9f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd5ff0b2sm11117030f8f.42.2026.01.07.08.29.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jan 2026 08:29:36 -0800 (PST) From: joaopeixoto@osyx.tech To: linux-kernel@vger.kernel.org Cc: ajd@linux.ibm.com, alex@ghiti.fr, aou@eecs.berkeley.edu, bagasdotme@gmail.com, catalin.marinas@arm.com, conor+dt@kernel.org, corbet@lwn.net, dan.j.williams@intel.com, davidmcerdeira@osyx.tech, devicetree@vger.kernel.org, dev@kael-k.io, gregkh@linuxfoundation.org, haren@linux.ibm.com, heiko@sntech.de, joaopeixoto@osyx.tech, jose@osyx.tech, kever.yang@rock-chips.com, krzk+dt@kernel.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, maddy@linux.ibm.com, mani@kernel.org, nathan@kernel.org, neil.armstrong@linaro.org, palmer@dabbelt.com, pjw@kernel.org, prabhakar.mahadev-lad.rj@bp.renesas.com, robh@kernel.org, will@kernel.org Subject: [PATCH 3/6] dt-bindings: Add Bao I/O dispatcher driver binding Date: Wed, 7 Jan 2026 16:28:26 +0000 Message-ID: <20260107162829.416885-4-joaopeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260107162829.416885-1-joaopeixoto@osyx.tech> References: <20251224135217.25350-1-joaopeixoto@osyx.tech> <20260107162829.416885-1-joaopeixoto@osyx.tech> 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 From: Jo=C3=A3o Peixoto This patch introduces a device tree binding for the Bao I/O Dispatcher, a device used in backend VMs running virtualized devices (e.g., VirtIO). Signed-off-by: Jo=C3=A3o Peixoto --- .../bindings/bao/bao,io-dispatcher.yaml | 75 +++++++++++++++++++ 1 file changed, 75 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..8ca450e4b9d5 --- /dev/null +++ b/Documentation/devicetree/bindings/bao/bao,io-dispatcher.yaml @@ -0,0 +1,75 @@ +# 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 I/O Dispatcher Device + +maintainers: + - Jo=C3=A3o Peixoto + - Jos=C3=A9 Martins + - David Cerdeira + +description: | + I/O Dispatcher device for Bao hypervisor guests that run virtualized + devices (e.g., VirtIO). + + This device is only required in backend VMs, which are responsible for + performing the actual I/O operations on physical hardware. Frontend + VMs, which only consume I/O services, do not require this device. + + The I/O Dispatcher provides access to one or more backend devices. + Each backend device is associated with a contiguous shared-memory + region used to exchange I/O buffers with the respective frontend + driver, and an interrupt used by the Bao hypervisor to notify the + backend VM of pending I/O requests. + +properties: + compatible: + const: bao,io-dispatcher + + reg: + description: | + Contiguous memory-mapped regions for each VirtIO backend device + managed by the I/O Dispatcher. + + Each region is used to exchange I/O buffers between the backend + and frontend devices. A single region corresponds to one + backend device. + minItems: 1 + maxItems: 64 + + interrupts: + description: | + Interrupts associated with the VirtIO backend devices. + + Each interrupt corresponds to a backend device and is used + by the Bao hypervisor to notify the backend VM of pending + I/O requests from the associated frontend driver. + minItems: 1 + maxItems: 64 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + bao-io-dispatcher@50000000 { + compatible =3D "bao,io-dispatcher"; + reg =3D <0x0 0x50000000 0x0 0x01000000 + 0x0 0x51000000 0x0 0x01000000 + 0x0 0x52000000 0x0 0x01000000 + 0x0 0x53000000 0x0 0x01000000 + 0x0 0x54000000 0x0 0x01000000>; + interrupts =3D <0x0 0x08 0x1 + 0x0 0x09 0x1 + 0x0 0x0a 0x1 + 0x0 0x0b 0x1 + 0x0 0x0c 0x1>; + interrupt-parent =3D <&gic>; + }; --=20 2.43.0 From nobody Sun Feb 8 08:36:49 2026 Received: from mail-wr1-f68.google.com (mail-wr1-f68.google.com [209.85.221.68]) (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 8967B37F118 for ; Wed, 7 Jan 2026 16:29:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.68 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803406; cv=none; b=kgHPJIE6P+NTiUHxZCJyFwoj5LeYloDagA2F0S84W+O5Z7VxxywpfLaGnsp8t3ZUtPlrb0/61M4eEcC2TtbWNjbW7we6SDD0SbCU9MzvHy4vi8XDt4K3/tc0vvmn6Ijf0heDe9NQ33V1E5Wm2qw+pTWO8zrIwNiLSk1XRnfv4Mk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803406; c=relaxed/simple; bh=nyUo3C8UkfDSApjJ1uL8glz6PHD9jlc/8OHRTaDDDW4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kt/YlfKLuAPZQBLGnkbs8c5gEK/8hpYYwLcZp7oTxBVt8205x19Fnt4aOBS+ocKfJwTixhySIzYH4tS/+N8hbGuecsO17gz9cnUd1RCMOVeFOyoc5jJ4o7B1fr2vddOBdOUwM65y+BgX+Kn8Og15YZMb0Nz8zpW0Z4b7ony1VSE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=fail smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b=Fq3YZS3f; arc=none smtp.client-ip=209.85.221.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b="Fq3YZS3f" Received: by mail-wr1-f68.google.com with SMTP id ffacd0b85a97d-430f9ffd4e8so475272f8f.0 for ; Wed, 07 Jan 2026 08:29:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20230601.gappssmtp.com; s=20230601; t=1767803381; x=1768408181; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kIH+PCFvKrCj97CXuV2HWuc5tubVh3H+qFJtI5Ujoh4=; b=Fq3YZS3fr8DP5ArwdmdkppmXaJOiq0f5zdwfYZpq7tyd4GoeZ0ZK1+rnBVIW7lxQ2E i+VVNPXXnCC1prtOq5Vti3QKS4rV1uC0w4Dg0D37wj3It8EqIqoZkX/4vEth/hIz4RaZ iatFJzJiRw+L5SyP3F2aQ1vB9INKskTZ8WOyU4plMgxvNRYYcNtdj7O+ld+YVGsU/FY5 fcG+UmXthNnbmNP4DuyztVaOj1fONcwFe3XCw0fJXUSfsmW5AKUeR2aXB5+FMBLE5QIr GQEsOE6wZf12OclcUotUpUr4OIsJ6Cg5oEEqmNLViFTImRBr9UU1Ugv0osdB50SfegGi ij9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767803381; x=1768408181; h=content-transfer-encoding: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; bh=kIH+PCFvKrCj97CXuV2HWuc5tubVh3H+qFJtI5Ujoh4=; b=e6jQsHA3qMF1EO58F+A48a5CsJJbm99JVovizSzKzQRO56FeniTfG+lRtoEzNN2SGr f7mtp38fWktAhlu4sNn825Jis5AgETDLSFYqt+CgE0Nw/iOk/IbWQmBbW1Cps/5ZSzY/ d6F7QSUjoIWcQ5AkSHpv+Xj13SDfgJh/BvCICmNi7vNV0/mghebvGqXV92cdcVi9zoSb vKf+qOrE7B+tA0NeV3REM7D2T6xHCU5hmGzEocG5mqm2CQjm3iNAHi2nITpr1qbE+Is+ Ko43+uDGx3HpR8nlOMK7Gxiulw1rTcq1SH450ssRjALW0H47UDJww/CxAlnfu1W1W5cP DfZg== X-Gm-Message-State: AOJu0YzwdP30Fcy6Am8z1cWPqd5FtJYZT+yJXg0ctL9t2OYzWyJF2vof KXLq0I0qKL4seJmo4yiowwt0Hk4t7JiBinhPgROEdviyL0AlPj3AFbUQecNNTkKeiUtNKPjc+IJ MClkMoDcQ X-Gm-Gg: AY/fxX7hh5Dwy/OQxA1jAKrQSIM40ff0XAEyCRTejb55sET1rPLMcNPSt1lWKpdgSWS b4mA9OgrDfiOP8we6rTDFfBeBBEIq/wXxeERWNuSJAQlbtD0c+7Q4Eq5Srm5bquQHLrO3BsZ7w2 y+AQfgwh9M0+omgGzXOENWJWLQXa4kcZes2fgqneQIbGTdYovT3PMNO9rvhwgDmLl7I7+dDRnLb Qkio8s5m5jM6ML8dW5eCC6GmiJJYwdPyeC7CoDCPsq+bfFubamRueD1p1zE20evYjNyRBvCWfCT bclvTzpmpZCQl6jrsWazAYl0V7TatB3Vxc5ec24uzmvfaR0pkgqCO1auSVa1fClbvknY/wRftWy JCJj0gkPnXvzkgh/HE/tm21yV8/l/+15II19AVuk3SKNb0Lua8WYYH1o48G+Pq0Ias9F0PCZ9iO 0T9aRwsAZOENpxsr/23g== X-Google-Smtp-Source: AGHT+IHguqVKZh4GYNxAC1OVxQLrSYRinVRFNFO1njYsQzvlAkB7qp5qZzHMN5bDU+nWiieyvWk6Zw== X-Received: by 2002:a05:6000:26cf:b0:432:59d4:f54a with SMTP id ffacd0b85a97d-432bcfe4b76mr8909375f8f.30.1767803379984; Wed, 07 Jan 2026 08:29:39 -0800 (PST) Received: from jp-linux.Home ([2001:8a0:f59c:a900:4a3c:13be:a1c0:7b9f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd5ff0b2sm11117030f8f.42.2026.01.07.08.29.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jan 2026 08:29:39 -0800 (PST) From: joaopeixoto@osyx.tech To: linux-kernel@vger.kernel.org Cc: ajd@linux.ibm.com, alex@ghiti.fr, aou@eecs.berkeley.edu, bagasdotme@gmail.com, catalin.marinas@arm.com, conor+dt@kernel.org, corbet@lwn.net, dan.j.williams@intel.com, davidmcerdeira@osyx.tech, devicetree@vger.kernel.org, dev@kael-k.io, gregkh@linuxfoundation.org, haren@linux.ibm.com, heiko@sntech.de, joaopeixoto@osyx.tech, jose@osyx.tech, kever.yang@rock-chips.com, krzk+dt@kernel.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, maddy@linux.ibm.com, mani@kernel.org, nathan@kernel.org, neil.armstrong@linaro.org, palmer@dabbelt.com, pjw@kernel.org, prabhakar.mahadev-lad.rj@bp.renesas.com, robh@kernel.org, will@kernel.org Subject: [PATCH 4/6] virt: bao: Add Bao I/O dispatcher driver Date: Wed, 7 Jan 2026 16:28:27 +0000 Message-ID: <20260107162829.416885-5-joaopeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260107162829.416885-1-joaopeixoto@osyx.tech> References: <20251224135217.25350-1-joaopeixoto@osyx.tech> <20260107162829.416885-1-joaopeixoto@osyx.tech> 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 From: Jo=C3=A3o Peixoto Introduce the Bao I/O Dispatcher, a kernel module for Bao hypervisor guests that run virtualized devices (e.g., VirtIO). This driver is only required in backend VMs, which are responsible for performing the actual I/O operations on physical hardware. Frontend VMs, which only consume I/O services, do not require this device. The I/O Dispatcher provides access to one or more backend devices. Each backend device is associated with a contiguous shared-memory region used to exchange I/O buffers with the respective frontend driver, and an interrupt used by the Bao hypervisor to notify the backend VM of pending I/O requests. Signed-off-by: Jo=C3=A3o Peixoto --- .../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 | 30 ++ drivers/virt/Makefile | 1 + drivers/virt/bao/Kconfig | 2 + drivers/virt/bao/Makefile | 1 + drivers/virt/bao/io-dispatcher/Kconfig | 15 + drivers/virt/bao/io-dispatcher/Makefile | 4 + drivers/virt/bao/io-dispatcher/bao_drv.h | 361 ++++++++++++++++ drivers/virt/bao/io-dispatcher/dm.c | 405 ++++++++++++++++++ drivers/virt/bao/io-dispatcher/driver.c | 185 ++++++++ drivers/virt/bao/io-dispatcher/intc.c | 64 +++ drivers/virt/bao/io-dispatcher/io_client.c | 405 ++++++++++++++++++ .../virt/bao/io-dispatcher/io_dispatcher.c | 179 ++++++++ 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 | 98 +++++ 19 files changed, 2490 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 7232b3544cec..b0dbc307a9cb 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -349,6 +349,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 9644d06be705..5ece9ecb1455 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 a1819966b59b..c7b7ec60c042 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 35658f37e1bd..f04e6cd33fa9 100644 --- a/arch/riscv/include/asm/bao.h +++ b/arch/riscv/include/asm/bao.h @@ -14,6 +14,7 @@ #define __ASM_RISCV_BAO_H =20 #include +#include =20 #define BAO_SBI_EXT_ID 0x08000ba0 =20 @@ -28,4 +29,33 @@ 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)(0x08000ba0); + + asm volatile("ecall" + : "+r"(a0), "+r"(a1), "+r"(a2), "+r"(a3), "+r"(a4), + "+r"(a5), "+r"(a6), "+r"(a7) + : "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..41c8c76c83b8 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/Kconfig @@ -0,0 +1,15 @@ +# 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. + 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..dd11be4484b1 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/bao_drv.h @@ -0,0 +1,361 @@ +/* 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 + +#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) + * @list: Entry within global list of all DMs + * @info: DM information (id, shmem_addr, shmem_size, irq, fd) + * @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 + * @refcount: Each open file holds a reference to the DM + */ +struct bao_dm { + struct list_head list; + struct bao_dm_info info; + 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; + + refcount_t refcount; +}; + +/** + * 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; +}; + +/* Global list of all Bao device models */ +extern struct list_head bao_dm_list; + +/* Lock protecting access to bao_dm_list */ +extern rwlock_t bao_dm_list_lock; + +/** + * bao_dm_create - Create a backend device model (DM) + * @info: DM information (id, shmem_addr, shmem_size, irq, fd) + * + * Return: Pointer to the created DM on success, NULL on error. + */ +struct bao_dm *bao_dm_create(struct bao_dm_info *info); + +/** + * bao_dm_destroy - Destroy a backend device model (DM) + * @dm: DM to be destroyed + */ +void bao_dm_destroy(struct bao_dm *dm); + +/** + * bao_dm_get_info - Retrieve information of a DM + * @info: Structure to be filled; id field must contain the DM ID + * + * Return: True on success, false on error. + */ +bool bao_dm_get_info(struct bao_dm_info *info); + +/** + * 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..12c321fc8a1c --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/dm.c @@ -0,0 +1,405 @@ +// 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 +#include + +/* + * List of all backend device models (DMs) + */ +LIST_HEAD(bao_dm_list); + +/* + * Lock to protect bao_dm_list + */ +DEFINE_RWLOCK(bao_dm_list_lock); + +static void bao_dm_get(struct bao_dm *dm) +{ + refcount_inc(&dm->refcount); +} + +static void bao_dm_put(struct bao_dm *dm) +{ + if (refcount_dec_and_test(&dm->refcount)) + kfree(dm); +} + +static int bao_dm_open(struct inode *inode, struct file *filp) +{ + return 0; +} + +static int bao_dm_release(struct inode *inode, struct file *filp) +{ + struct bao_dm *dm =3D filp->private_data; + + if (WARN_ON_ONCE(!dm)) + return -ENODEV; + + filp->private_data =3D NULL; + bao_dm_put(dm); + + 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_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 *bao =3D file->private_data; + loff_t new_pos; + + if (WARN_ON_ONCE(!bao)) + 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 bao->info.shmem_size + offset; + break; + default: + return -EINVAL; + } + + if (new_pos < 0 || new_pos > bao->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 bao_dm *dm; + struct bao_dm *tmp; + char name[BAO_NAME_MAX_LEN]; + + if (WARN_ON(!info)) + return NULL; + + dm =3D kzalloc(sizeof(*dm), GFP_KERNEL); + if (!dm) + return NULL; + + INIT_LIST_HEAD(&dm->list); + INIT_LIST_HEAD(&dm->io_clients); + init_rwsem(&dm->io_clients_lock); + + refcount_set(&dm->refcount, 1); + dm->info =3D *info; + + bao_io_dispatcher_init(dm); + + snprintf(name, sizeof(name), "bao-ioctlc%u", dm->info.id); + dm->control_client =3D bao_io_client_create(dm, NULL, NULL, true, name); + if (!dm->control_client) { + pr_err("%s: failed to create control client for DM %u\n", + __func__, dm->info.id); + goto err_remove_dm; + } + + if (bao_ioeventfd_client_init(dm)) { + pr_err("%s: failed to initialize ioeventfd for DM %u\n", + __func__, dm->info.id); + goto err_destroy_io_clients; + } + + if (bao_irqfd_server_init(dm)) { + pr_err("%s: failed to initialize irqfd for DM %u\n", __func__, + 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) { + pr_err("%s: failed to map memory region for DM %u\n", __func__, + dm->info.id); + goto err_destroy_irqfd; + } + + write_lock(&bao_dm_list_lock); + list_for_each_entry(tmp, &bao_dm_list, list) { + if (tmp->info.id =3D=3D info->id) { + write_unlock(&bao_dm_list_lock); + goto err_unmap; + } + } + list_add(&dm->list, &bao_dm_list); + write_unlock(&bao_dm_list_lock); + + 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_remove_dm: + kfree(dm); + + return NULL; +} + +void bao_dm_destroy(struct bao_dm *dm) +{ + if (WARN_ON_ONCE(!dm)) + return; + + write_lock(&bao_dm_list_lock); + list_del_init(&dm->list); + write_unlock(&bao_dm_list_lock); + + dm->info.id =3D 0; + dm->info.shmem_addr =3D 0; + dm->info.shmem_size =3D 0; + dm->info.irq =3D 0; + + if (dm->shmem_base_addr) + memunmap(dm->shmem_base_addr); + + if (dm->info.fd >=3D 0) + put_unused_fd(dm->info.fd); + + bao_irqfd_server_destroy(dm); + bao_io_clients_destroy(dm); + bao_io_dispatcher_destroy(dm); + + bao_dm_put(dm); +} + +/** + * bao_dm_create_anonymous_inode - Create an anonymous inode for a backend= DM + * @dm: The backend device model (DM) + * + * Creates an anonymous inode that exposes the backend DM to userspace. + * The frontend DM can use the returned file descriptor to request + * services from the backend DM directly. + * + * Return: File descriptor on success, negative errno on failure + */ +static int bao_dm_create_anonymous_inode(struct bao_dm *dm) +{ + char name[BAO_NAME_MAX_LEN]; + struct file *file; + int fd; + + if (WARN_ON_ONCE(!dm)) + return -EINVAL; + + fd =3D get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) + return fd; + + snprintf(name, sizeof(name), "bao-dm%u", dm->info.id); + bao_dm_get(dm); + file =3D anon_inode_getfile(name, &bao_dm_fops, dm, O_RDWR); + if (IS_ERR(file)) { + bao_dm_put(dm); + put_unused_fd(fd); + return PTR_ERR(file); + } + + fd_install(fd, file); + dm->info.fd =3D fd; + + return fd; +} + +bool bao_dm_get_info(struct bao_dm_info *info) +{ + struct bao_dm *dm; + bool found =3D false; + + if (WARN_ON_ONCE(!info)) + return false; + + read_lock(&bao_dm_list_lock); + list_for_each_entry(dm, &bao_dm_list, list) { + if (dm->info.id =3D=3D info->id) { + bao_dm_get(dm); + found =3D true; + break; + } + } + read_unlock(&bao_dm_list_lock); + + if (!found) + return false; + + info->shmem_addr =3D dm->info.shmem_addr; + info->shmem_size =3D dm->info.shmem_size; + info->irq =3D dm->info.irq; + info->fd =3D bao_dm_create_anonymous_inode(dm); + + bao_dm_put(dm); + + return true; +} diff --git a/drivers/virt/bao/io-dispatcher/driver.c b/drivers/virt/bao/io-= dispatcher/driver.c new file mode 100644 index 000000000000..488f9fb6e5f5 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/driver.c @@ -0,0 +1,185 @@ +// 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 +#include "bao_drv.h" + +struct bao_iodispatcher_drv { + struct miscdevice miscdev; +}; + +static int bao_io_dispatcher_driver_open(struct inode *inode, struct file = *filp) +{ + struct miscdevice *misc =3D filp->private_data; + struct bao_iodispatcher_drv *drv; + + drv =3D container_of(misc, struct bao_iodispatcher_drv, + miscdev); + filp->private_data =3D drv; + + return 0; +} + +static int bao_io_dispatcher_driver_release(struct inode *inode, + struct file *filp) +{ + filp->private_data =3D NULL; + return 0; +} + +static long bao_io_dispatcher_driver_ioctl(struct file *filp, unsigned int= cmd, + unsigned long arg) +{ + struct bao_dm_info *info; + + switch (cmd) { + case BAO_IOCTL_DM_GET_INFO: + info =3D memdup_user((void __user *)arg, sizeof(*info)); + if (IS_ERR(info)) + return PTR_ERR(info); + + if (!bao_dm_get_info(info)) { + kfree(info); + return -ENOENT; + } + + if (copy_to_user((void __user *)arg, info, sizeof(*info))) { + kfree(info); + return -EFAULT; + } + + kfree(info); + return 0; + + default: + return -ENOTTY; + } +} + +static const struct file_operations bao_io_dispatcher_driver_fops =3D { + .owner =3D THIS_MODULE, + .open =3D bao_io_dispatcher_driver_open, + .release =3D bao_io_dispatcher_driver_release, + .unlocked_ioctl =3D bao_io_dispatcher_driver_ioctl, +}; + +static int bao_io_dispatcher_driver_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct bao_iodispatcher_drv *drv; + struct bao_dm *dm; + struct bao_dm_info dm_info; + struct resource *r; + int ret; + int irq; + int i; + resource_size_t reg_size; + + drv =3D devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + for (i =3D 0; i < BAO_IO_MAX_DMS; i++) { + r =3D platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!r) + break; + + irq =3D platform_get_irq(pdev, i); + if (irq < 0) { + dev_err(dev, "failed to get IRQ at index %d\n", i); + ret =3D irq; + goto err_unregister_dms; + } + + reg_size =3D resource_size(r); + + dm_info.id =3D i; + dm_info.shmem_addr =3D (unsigned long)r->start; + dm_info.shmem_size =3D (unsigned long)reg_size; + dm_info.irq =3D irq; + dm_info.fd =3D 0; + + dm =3D bao_dm_create(&dm_info); + if (!dm) { + dev_err(dev, "failed to create Bao DM %d\n", i); + ret =3D -EINVAL; + goto err_unregister_dms; + } + + ret =3D bao_intc_init(dm); + if (ret) { + dev_err(dev, "failed to register interrupt %d\n", irq); + goto err_unregister_dms; + } + } + + drv->miscdev.minor =3D MISC_DYNAMIC_MINOR; + drv->miscdev.name =3D "bao-io-dispatcher"; + drv->miscdev.fops =3D &bao_io_dispatcher_driver_fops; + drv->miscdev.parent =3D dev; + + ret =3D misc_register(&drv->miscdev); + if (ret) { + dev_err(dev, "failed to register misc device: %d\n", ret); + goto err_unregister_irqs; + } + + platform_set_drvdata(pdev, drv); + + dev_info(dev, "Bao I/O dispatcher device registered\n"); + return 0; + +err_unregister_irqs: + list_for_each_entry(dm, &bao_dm_list, list) + bao_intc_destroy(dm); + +err_unregister_dms: + list_for_each_entry(dm, &bao_dm_list, list) + bao_dm_destroy(dm); + + return ret; +} + +static void bao_io_dispatcher_driver_remove(struct platform_device *pdev) +{ + struct bao_iodispatcher_drv *drv =3D platform_get_drvdata(pdev); + struct bao_dm *dm; + struct bao_dm *tmp; + + if (drv) + misc_deregister(&drv->miscdev); + + list_for_each_entry_safe(dm, tmp, &bao_dm_list, list) { + 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..40d8b6c1bd25 --- /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..ae258d7bb9bd --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/io_client.c @@ -0,0 +1,405 @@ +// 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(sizeof(*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(sizeof(*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); + 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); + + if (is_control) { + while (bao_dispatch_io(dm) > 0) + ; + } + + 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(sizeof(*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..15f6b8c6a439 --- /dev/null +++ b/drivers/virt/bao/io-dispatcher/io_dispatcher.c @@ -0,0 +1,179 @@ +// 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; + + 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..28172207ab57 --- /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(sizeof(*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..ba31c3c5feaa --- /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(sizeof(*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..5b06d2a17d21 --- /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..7713a73e4e4e --- /dev/null +++ b/include/uapi/linux/bao.h @@ -0,0 +1,98 @@ +/* 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 + * @fd: File descriptor of the DM + */ +struct bao_dm_info { + __u32 id; + __u64 shmem_addr; + __u64 shmem_size; + __u32 irq; + __s32 fd; +}; + +/* + * 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 Sun Feb 8 08:36:49 2026 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) (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 74D9B37D1C3 for ; Wed, 7 Jan 2026 16:29:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803411; cv=none; b=e/pb1DT0Xqo5vYe957IqcfSbCQNw3rXSwR81VDgmPnZd3uazkTlOvZd+mQrGGVPw7e/6eFiEoUV8aPBamcvbPkSjsFjzBCXalfiq7k8jvPWeA8PlOGN9ba7KFm+G4nqHNgJ0ar1RkjInX5hj9cWocTWvgdQyitEo7fyRsVg7zYo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803411; c=relaxed/simple; bh=8QHeTQ1XWPXrXIuaoG9PXPBKmQw6B9CxYPEzAKre7JY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=G2//YSWzACeMyaKk+X/qbOhW4XHq+lCe0ZPNdhyWpmxKhVzqn1PJfwgb+xuGEOIMtp9JMWswtFlhRAXXDKP3CtC1FEb+/TTA+OhR+zWApvTRU5NJbgAA8A5jsH3rT6p3GVVsRIKMqSQAWoPqoAyryX8/PlUoHh3vcJhMDeqvP8k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=fail smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b=Y4gUTC3M; arc=none smtp.client-ip=209.85.221.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b="Y4gUTC3M" Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-43260a5a096so1542428f8f.0 for ; Wed, 07 Jan 2026 08:29:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20230601.gappssmtp.com; s=20230601; t=1767803383; x=1768408183; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TGfMB1SwaAERf8A9+EJZzOGOMSv16YGZ4dbapv2DrTs=; b=Y4gUTC3MrooR8TXD8YTfru1jOcy5sBzZqUID9YizdinrPnvWdW2Y0efLIz9oqPq6Vp 1Q4j52k8fKwxnx0gOoHiyGhtxI4R9FGFfiB/kr0T60iqlCWfWw6JqIRAp75VM0PDFtq6 brCvvjqJuu7tTydsje8NLHxYlcU2A6P8JhYcT4KAAd9asEqTWtY7Bid9Bgrvw2Mbdzn9 NNYCui/Zg/cogop/y66l1QmIIxNJZIiwjAtX+JR/Ph5TvaI0c87ZiEj5Lw6Cli1wGbGS 3vXFefAMxI1k20ak/yt457w8DRBr1rlmtv5GnzoQYsbjAxISyl38OKmYDft4GOs54lsj Z3Mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767803383; x=1768408183; h=content-transfer-encoding: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; bh=TGfMB1SwaAERf8A9+EJZzOGOMSv16YGZ4dbapv2DrTs=; b=ozu5LwuMPoYPyz2ul+A/1fzbhwOvSQtF2i6BV2ak/5MbJey80qpXpCSOJm+4XLD0Kd H+6WbDEVLgICLViPa6Sv429c+90nOWaj3+xR57eCCKQJ5R6f7p2UCft04nftQcuRaMTc JE+X4Po2Sqc4tZCeEGNTfnIqCVqHBYI87UOJyU4gtjTspEr/nowZgpzBul2hznQgThOR XHibBJZsNj+xm42G4H8ES1gjop/bxcr8ah3ks/+XMuFTo3M/R1/uqp7jT2CLZ0ExXdOh 6UaCwq6rnnVlHK0wIafIW82OHoTCDfxmsUbCdTlngnq6IJ2AHB0K5iiX7C71z4p9gaKA KFxg== X-Gm-Message-State: AOJu0Ywqjl66aip0Yu+8VVciHSX0wjqTFaRc9LzBwXxr4obbrbDAip8X NjSPe3tbV6oTjJ7pG2mmnCPuYAJYT3fSeWSfJbVw3oCdWOEDdjohzluh9Ig6JSzkIH/N5PvEJkb ziPU0Aw== X-Gm-Gg: AY/fxX7z7QscTfpdkk6r4AzGVH0Hz0QL//k/aMFbJgL1IWAJcnyDELHxT6yVBAmAgm2 Rv5H3bBd3G0Nj3ji4Abs4uvV6f8BKktKYtiuWlaqhBkiVehYTPJnqxMQ0F5zJF/zWTtE1j5Yx2h tgn5R8dJd5K6MG9N037ENSM6YVTK3Ku/hPTTXdcdWJ07Vr13qQjRiR8N4bkbF7VmioQ1MT5Ap99 E7pC79uh5GYa/5q3fnWnjVfdLSt+wMz1Xkm6f05rYgXiZpdRCs2yJyhFFozatJ5/ewNBhx4KZ7L jWEdP0H+Ywp6zmuDNx0ssr4mwqdgPpQ9UshaUKoS70ToAzAQs9Rb75IUfrPpxUgv2M1MHTMgksH hh1vvVKm9+6TQLAgyKVrrQV7RW02OAV1AK6CbkdG4MzMaG8Ds+Dg02cxWd4fFd/YCjtBbfqhOMm rLWluMC06O/dm8Ppz7Bw== X-Google-Smtp-Source: AGHT+IHYX8ERrMEjplERjC6ixgzkBNgkXhYStxw+rahyUBYDlRtMCSfk+AGXhNnNExJ8kz9EYuCSDQ== X-Received: by 2002:adf:f4c9:0:b0:431:907:f324 with SMTP id ffacd0b85a97d-432c38d2312mr3237384f8f.61.1767803383134; Wed, 07 Jan 2026 08:29:43 -0800 (PST) Received: from jp-linux.Home ([2001:8a0:f59c:a900:4a3c:13be:a1c0:7b9f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd5ff0b2sm11117030f8f.42.2026.01.07.08.29.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jan 2026 08:29:42 -0800 (PST) From: joaopeixoto@osyx.tech To: linux-kernel@vger.kernel.org Cc: ajd@linux.ibm.com, alex@ghiti.fr, aou@eecs.berkeley.edu, bagasdotme@gmail.com, catalin.marinas@arm.com, conor+dt@kernel.org, corbet@lwn.net, dan.j.williams@intel.com, davidmcerdeira@osyx.tech, devicetree@vger.kernel.org, dev@kael-k.io, gregkh@linuxfoundation.org, haren@linux.ibm.com, heiko@sntech.de, joaopeixoto@osyx.tech, jose@osyx.tech, kever.yang@rock-chips.com, krzk+dt@kernel.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, maddy@linux.ibm.com, mani@kernel.org, nathan@kernel.org, neil.armstrong@linaro.org, palmer@dabbelt.com, pjw@kernel.org, prabhakar.mahadev-lad.rj@bp.renesas.com, robh@kernel.org, will@kernel.org Subject: [PATCH 5/6] virt: bao: Move BAO_IPCSHMEM_HYPERCALL_ID to common header Date: Wed, 7 Jan 2026 16:28:28 +0000 Message-ID: <20260107162829.416885-6-joaopeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260107162829.416885-1-joaopeixoto@osyx.tech> References: <20251224135217.25350-1-joaopeixoto@osyx.tech> <20260107162829.416885-1-joaopeixoto@osyx.tech> 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 From: Jo=C3=A3o Peixoto Move the IPC shared-memory hypercall ID from architecture-specific headers into include/linux/bao.h. Signed-off-by: Jo=C3=A3o Peixoto --- arch/arm/include/asm/bao.h | 5 ++--- arch/arm64/include/asm/bao.h | 5 ++--- arch/riscv/include/asm/bao.h | 7 +++---- drivers/virt/bao/ipcshmem/ipcshmem.c | 5 +---- include/linux/bao.h | 3 +++ 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/arm/include/asm/bao.h b/arch/arm/include/asm/bao.h index 5ece9ecb1455..7d13591fe669 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 c7b7ec60c042..409f4058d56e 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 f04e6cd33fa9..d168aba7d8ec 100644 --- a/arch/riscv/include/asm/bao.h +++ b/arch/riscv/include/asm/bao.h @@ -18,13 +18,12 @@ =20 #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 f3892d41248c..593e89cb76bd 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; int id; @@ -90,7 +87,7 @@ static ssize_t bao_ipcshmem_write(struct file *filp, cons= t 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 5b06d2a17d21..b29830374788 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 Sun Feb 8 08:36:49 2026 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B34203803DC for ; Wed, 7 Jan 2026 16:29:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803418; cv=none; b=UtJc47HmTzi+WXRXi6aNhyFYoJEH+0C2mnpUrsy0z5HJ/kViQlU53qXie7HH8FN9wAu+em2pTypjTDlgoJGjhU2TicsduegDxV/6I427WVL8VEHeg+eBrzj2ZfS8k+MBkzqnF/7GRvVKI6lGm3/yredcFnXP0ylsy6LWu1vF8R4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767803418; c=relaxed/simple; bh=9BATtieLEYCpEcZj+GM/kP3Ja9/0f7Z989r6IWgQnPo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NabUZtfbKGeAb7SQDr5hT41hFM1aPDmKUNY5LUEaTFVkQ/knes2vC3XADOtUDQzAhE1qPpFJ5kfw6DfLmXPWXalDKyNBVmt/k32vmel5h7XtRgXcUNVvF7GF/G9AJ6QYgRkXIbSF0Rqx8ESTaQ9G4GUjhC+fRrYSjza7x+8ImV8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech; spf=fail smtp.mailfrom=osyx.tech; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b=G0AV5DUC; arc=none smtp.client-ip=209.85.128.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=osyx.tech Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=osyx.tech Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=osyx-tech.20230601.gappssmtp.com header.i=@osyx-tech.20230601.gappssmtp.com header.b="G0AV5DUC" Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-47d59da3d81so4909555e9.0 for ; Wed, 07 Jan 2026 08:29:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osyx-tech.20230601.gappssmtp.com; s=20230601; t=1767803386; x=1768408186; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WihJclLNTP76N6hz6eqMpZoD5cMEZ14VPXp1pd6gG3I=; b=G0AV5DUCkIVoAqpgQWEX/9lUB5kktqCgXbewIHqswqeS6vW1szpPhKDO3upN7mluJJ YXpPKekVDudKt9P8u1LKtkd5th+etFVxOu1jKq12ZzSdCOZ33eCnErhUnHdfUs5A1CM1 fvmu3UjQz06XXV6T5cWVO1TuJZunEg4p0Mv3KeMnNerMb2JyW95c17WLAD7ag9Fkflnu vS4zM6fVM2D78ht+VFybuqzm6p19BuplW9EiQuu/TYK5rbOa8se1vV3KMSZrtBQFHVbk q+AVdORefAHg6G1d2lFuWoy1X2BzsSE/SKyQxY3kv5aXtxqCPfrXhLJCaoD7WG5pfpuL 57UQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767803386; x=1768408186; h=content-transfer-encoding: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; bh=WihJclLNTP76N6hz6eqMpZoD5cMEZ14VPXp1pd6gG3I=; b=e+fWLajTGCDeA2UmOKaK6lPjVhkYDunUb6FkZa6LSe9rJoQlHKkUnIQXI39nYFdc34 OJ2zDeqcN1bdfIDFcfCG4kqnuzIfV1qQSLvHnP242qMVOT9OARjtIgr0Sh99V8NXtcdH r51REEAcNkpkAbxjCcxd5CTEFpU4Mg5holLtIjRAnTDSMit3Wcyg48uneYWkIMz0mm+4 a29AFxl822u/cldIO1Ffc42PAEK3SSRoVv3chSbh0YhSBWMoUkniVRxJzJip1z7zOpWb CypmybkcjjnjMaGx4nr/3XPnthxwyXUq/7RKiyBFCpu6rMJmZy2qcX2x4Y/gFpKRrNRT bTKw== X-Gm-Message-State: AOJu0Yw5FjEGnnuA9MwbECgaBn6m6k3HYdmUfsBfwVClObUM1M65I2cc L6UrAeOsdJhhecEgPRXlwBeluyAjLXeOYjx6rvH23OvOJkLoBu0TfHa97TES/inFapX+zvZA0Ja BOrjvTg== X-Gm-Gg: AY/fxX49W6QvBwgPBSMbtrCrBEKoxQ30ZOXknirQUzO/W4ct6mwEMXORdT+W1FbIuXF fBaPt2AHTMY2cmNxDD9h/ogkaQO6b/P4a9ntAlRCeFp7KjVF30a7cGMYZQBSjy8/lRmc2OzFCvI xrR5EDLm9rCUcX2GlEsqHHJ6xUBiusJEaTxznV3VMd9odyXJBvgxzv7S2VvDHyOWEdLB8/qyWT3 NcjSQG4oqSwGbjRMAamjO8i3j9H0y/Hwjr3ngXnmW7PW6OXcgCPJEEoLF5S4kH5FhXdoL4CrgFE XHLFVcjzfxVMMi9dv07ylXHetVMDMBRpPqwOOICdV9KQqSMv5Nv5fr4z/lT60YWYCE2S3sDoZ2J ra2MOWUDt2GptG26GBM79JlACl5cgv2sq3+VA69tE0VJta5kfeTM30mbrPuCLBVALf5lCUkX8wt ZC//Qlqg3kZRmE7/bPFQ== X-Google-Smtp-Source: AGHT+IFKD1+c7SUjD7a/gByTTs7FpF1prAJlqO9osr5dmkMQRiIqO+8yFt3RtGpmL0uKFm0/tPDRBQ== X-Received: by 2002:a05:6000:a88:b0:432:c0b8:ee42 with SMTP id ffacd0b85a97d-432c0b8ef25mr5297882f8f.11.1767803385887; Wed, 07 Jan 2026 08:29:45 -0800 (PST) Received: from jp-linux.Home ([2001:8a0:f59c:a900:4a3c:13be:a1c0:7b9f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd5ff0b2sm11117030f8f.42.2026.01.07.08.29.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jan 2026 08:29:45 -0800 (PST) From: joaopeixoto@osyx.tech To: linux-kernel@vger.kernel.org Cc: ajd@linux.ibm.com, alex@ghiti.fr, aou@eecs.berkeley.edu, bagasdotme@gmail.com, catalin.marinas@arm.com, conor+dt@kernel.org, corbet@lwn.net, dan.j.williams@intel.com, davidmcerdeira@osyx.tech, devicetree@vger.kernel.org, dev@kael-k.io, gregkh@linuxfoundation.org, haren@linux.ibm.com, heiko@sntech.de, joaopeixoto@osyx.tech, jose@osyx.tech, kever.yang@rock-chips.com, krzk+dt@kernel.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, maddy@linux.ibm.com, mani@kernel.org, nathan@kernel.org, neil.armstrong@linaro.org, palmer@dabbelt.com, pjw@kernel.org, prabhakar.mahadev-lad.rj@bp.renesas.com, robh@kernel.org, will@kernel.org Subject: [PATCH 6/6] MAINTAINERS: Add entries for Bao hypervisor drivers, headers, and DT bindings Date: Wed, 7 Jan 2026 16:28:29 +0000 Message-ID: <20260107162829.416885-7-joaopeixoto@osyx.tech> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260107162829.416885-1-joaopeixoto@osyx.tech> References: <20251224135217.25350-1-joaopeixoto@osyx.tech> <20260107162829.416885-1-joaopeixoto@osyx.tech> 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 From: Jo=C3=A3o Peixoto Add MAINTAINERS entries for all the Bao hypervisor components. Signed-off-by: Jo=C3=A3o Peixoto --- MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index dc731d37c8fe..4286efb307b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4321,6 +4321,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