From patchwork Mon Jan 29 08:32:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767745 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95CB25576C; Mon, 29 Jan 2024 08:33:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.61.82.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517199; cv=none; b=LOU0TKs+BL40ZODWSv6JXUlg9xCfkf/7JySm7ShFwPPpm6hrVQcN7jgyGX3e3nVcQXF2lZMQJH7jP7Y3jdnr4hmSyHT703n+VomAvv6qX7fZBIPkIkhtYCxKVF87hVvOnGbYdMmRzB7pRF9XxG+c3xO0XrOuQQFAo5W2pct/mig= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517199; c=relaxed/simple; bh=rkIipSU1vNRGSSjvneoQbJ1tyx8Sjzo93Ou/lLVrVzA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VWqEp7kIy6w3GismVAajhWilSviKGZ4/JqXRpw3VSWb4dyLDw4iTGZBR9w8jple/kxtsDIRmpNldNDZvuIxa49ha+s7R4yqscQazEInRP/S0M86rmvVti+vrO6PUi3Uad9LgSDiX4q8yOXkCYC1TjLY6bK5JoxDg4YzcCrzaxXI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=ZbFfK2GQ; arc=none smtp.client-ip=210.61.82.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="ZbFfK2GQ" X-UUID: 088d45aebe8111eea2298b7352fd921d-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=eDYzYtOK7emgz2NcibSVM9p08YbBt9JuEMgMtcO71Ow=; b=ZbFfK2GQpsQL1M47cY9IfNsIgzH6qJLAH35Mn4wSBuJUlUdx82UXY3+XTN5Fk562sOwGj7MZDL5xk1hs67mZL1/IRiSYkX3GAUSG48YxanKyzuKqHxtFnRnLAxzu4FI7z2qBBX0fmru3j36mofwLmERZO6j/2nPBNtGcDVXS278=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:e3a646e8-2099-47bf-b87e-8139d5a8dfc8, IP:0, U RL:25,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION :release,TS:25 X-CID-META: VersionHash:6e16cf4, CLOUDID:da25c58e-e2c0-40b0-a8fe-7c7e47299109, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_ULN,TF_CID_SPAM_SNR X-UUID: 088d45aebe8111eea2298b7352fd921d-20240129 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 208504367; Mon, 29 Jan 2024 16:33:09 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by MTKMBS14N1.mediatek.inc (172.21.101.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:06 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:06 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , "Willix Yeh" , Kevenny Hsieh Subject: [PATCH v9 03/21] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor Date: Mon, 29 Jan 2024 16:32:44 +0800 Message-ID: <20240129083302.26044-4-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-AS-Result: No-10--11.112700-8.000000 X-TMASE-MatchedRID: l5qCKP2S+CbHCChNBbZThW3NvezwBrVmUXlp1FHYSPVfSPKGP39CrlYW wxB9tw0TJhXAZMA4h8Vncviyus0oC5/JE/eOMuX3vGTc5oROod7rpC+cgGEjuhHfiujuTbedOOF xXXPqKHnyga3Otdj4UogmzRSnu+RYqjvsBy5CHDu4jAucHcCqnZYcYQ11P5U/m5zZfbOy37EOsb dDU8hPqApsQGG0bIwTwKX8fpO+yjIFvymnGwMQKcgc0seoKgtWDcK8n+cR7XKbKItl61J/yUGDD kbg1gJk32mPO5tnasfCttcwYNipX8NbTFVOzjU8PZm5TtYsIfIFYU+GevBfScRAj2y1n1gN6fzS 33INfqs= X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--11.112700-8.000000 X-TMASE-Version: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-SNTS-SMTP: 9596F9895DA162A51FF1CBE38AC9F0D14A5FE35BB92D28E6B1A517C3B08B63FC2000:8 X-MTK: N From: "Yingshiuan Pan" Add documentation for GenieZone(gzvm) node. This node informs gzvm driver to start probing if geniezone hypervisor is available and able to do virtual machine operations. [Reason to use dt solution] - The GenieZone hypervisor serves as a vendor model for facilitating platform virtualization, with an implementation that is independent from Linuxism. - In contrast to the dt solution, our previous approach involved probing via hypercall to determine the existence of our hypervisor. However, this method raised concerns about potentially impacting all systems, including those without the GenieZone hypervisor embedded[ref]. Link: https://lore.kernel.org/all/2fe0c7f9-55fc-ae63-3631-8526a0212ccd@linaro.org/ Signed-off-by: Yingshiuan Pan Signed-off-by: Liju Chen Signed-off-by: Yi-De Wu --- .../hypervisor/mediatek,geniezone-hyp.yaml | 31 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml diff --git a/Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml b/Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml new file mode 100644 index 000000000000..ab89a4c310cb --- /dev/null +++ b/Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hypervisor/mediatek,geniezone-hyp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek GenieZone hypervisor + +maintainers: + - Yingshiuan Pan + +description: + This interface is designed for integrating GenieZone hypervisor into Android + Virtualization Framework(AVF) along with Crosvm as a VMM. + It acts like a wrapper for every hypercall to GenieZone hypervisor in + order to control guest VM lifecycles and virtual interrupt injections. + +properties: + compatible: + const: mediatek,geniezone-hyp + +required: + - compatible + +additionalProperties: false + +examples: + - | + hypervisor { + compatible = "mediatek,geniezone-hyp"; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 99ef21d90420..17a8e20d2baa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9017,6 +9017,7 @@ GENIEZONE HYPERVISOR DRIVER M: Yingshiuan Pan M: Ze-Yu Wang M: Yi-De Wu +F: Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml F: Documentation/virt/geniezone/ GENWQE (IBM Generic Workqueue Card) From patchwork Mon Jan 29 08:32:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767747 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB5CD54BED; Mon, 29 Jan 2024 08:33:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.244.123.138 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517197; cv=none; b=WhtPu05fuiMdujK7UITQb3Pc180py8dD5pFpHtBkJRASbpdDtdkp+/N1abLEBhP2kAjwQDTvCDXfIg0ORxwPAuPfp7TESxwQEYcmB30k3nmqaoqKDbcI5kjr49J8iEyMBtEbEF4TrAj2/pKKxNZvX9GIiiVu237sRPzHTai1/VE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517197; c=relaxed/simple; bh=Tmr5lCEEMqtKxdcE78CeFdZChdxELliPPEqDVBIMhvs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HCZROMfTYdvcVhJijK5nAp407W2OEiOxT7IgV9hG7BeHPoeHMhHeHQlThEDy5Jf1b3HJsiuvNYRNpipWLNdA7w+ZEvytbiAXDw+08OAMTZXotzb4s1eLd+O023RR1pR8wkLhZK5fQAGIxW2hQkZUUBjADCpkGzDKGNk+sulZxpE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=SHyt+AMN; arc=none smtp.client-ip=60.244.123.138 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="SHyt+AMN" X-UUID: 0741fd34be8111ee9e680517dc993faa-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=dQlCTAvKUL0hJV/gBIz1GZs6elkxxaPRAuCwjgz8LEk=; b=SHyt+AMNMaDRQd4bMtKhzZKHJ5OgPSDFjzwdWNxtCch7wYjL6XJ6lRsZLtDOjxPJPvaUYyoSA+3bhA23SAeKXMBM5w5Z2BaLFhqqPR2Q1gxk/yxmmayXqgY9+zF6aHscjeIlpW7h+KyECzjYQYuQ9FQP+onALAN0pA8fgGW6PFs=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:27fa8565-b94a-4de9-b48a-e7643be3a8ba, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:0c45de7f-4f93-4875-95e7-8c66ea833d57, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: 0741fd34be8111ee9e680517dc993faa-20240129 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 454162848; Mon, 29 Jan 2024 16:33:07 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:06 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:06 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , "Willix Yeh" , Kevenny Hsieh Subject: [PATCH v9 04/21] virt: geniezone: Add GenieZone hypervisor driver Date: Mon, 29 Jan 2024 16:32:45 +0800 Message-ID: <20240129083302.26044-5-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-AS-Result: No-10--15.609800-8.000000 X-TMASE-MatchedRID: Sr5xfaOZ+q/PwZWTvltloQI0yP/uoH+DUAjrAJWsTe9mU223IIioZfb9 MQK6DQClvfKrrb4bmIqy7ec+ITUwM2eIEG00SdU9drnuu4cCcfF/aDoolm3GXWJkJOQVCIpwMKw CZ7huGiG36SL29gBZ5pCCPgbCpGAQEx7gYK5Baw8mZusHWPhfCgXBq8VnFhCkGoH7Aor25l4faH aH7SYxz5w9wMcKngv65JZWpbmrOY42fA1oT3w9vBes/RxhysDbO69hrW/YgWHRziMbBeTI+Tt3v VezfYEfTdn5Fl2oZyZY/xqzfORJ/3+cOjB/YDBsE0Q83A2vD+sikU4xQFgb7nwqSr02aA0dg7M3 17/33cEKYu/xaKWCX6fkJPeWEebO8d2M04iWy/IdxBAG5/hkW0Dwj88nLgRT8cWgFw6wp7PJWfh nQliz3tm7+6JBp8fEN3vA/dbJqUbvk9E0156d6HuzDvI75j0sWwKGivsEuI1aW2Ktn+I8/l0E/8 jA12YdJmL4F1ztDueAMuqetGVetnyef22ep6XYymsk/wUE4hoD/dHyT/Xh7Q== X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--15.609800-8.000000 X-TMASE-Version: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-SNTS-SMTP: 338F2EE380E3B4DDD46FFAB655B4536FA10A52315D0582C82D83422240B16FB12000:8 X-MTK: N From: "Yingshiuan Pan" GenieZone hypervisor(gzvm) is a type-1 hypervisor that supports various virtual machine types and provides security features such as TEE-like scenarios and secure boot. It can create guest VMs for security use cases and has virtualization capabilities for both platform and interrupt. Although the hypervisor can be booted independently, it requires the assistance of GenieZone hypervisor kernel driver(gzvm-ko) to leverage the ability of Linux kernel for vCPU scheduling, memory management, inter-VM communication and virtio backend support. Add the basic hypervisor driver. Subsequent patches will add more supported features to this driver. Signed-off-by: Yingshiuan Pan Signed-off-by: Jerry Wang Signed-off-by: Liju Chen Signed-off-by: Yi-De Wu --- MAINTAINERS | 3 + arch/arm64/Kbuild | 1 + arch/arm64/geniezone/Makefile | 9 +++ arch/arm64/geniezone/gzvm_arch_common.h | 44 ++++++++++++ arch/arm64/geniezone/vm.c | 47 +++++++++++++ drivers/virt/Kconfig | 2 + drivers/virt/geniezone/Kconfig | 16 +++++ drivers/virt/geniezone/Makefile | 10 +++ drivers/virt/geniezone/gzvm_main.c | 89 +++++++++++++++++++++++++ include/linux/gzvm_drv.h | 25 +++++++ 10 files changed, 246 insertions(+) create mode 100644 arch/arm64/geniezone/Makefile create mode 100644 arch/arm64/geniezone/gzvm_arch_common.h create mode 100644 arch/arm64/geniezone/vm.c create mode 100644 drivers/virt/geniezone/Kconfig create mode 100644 drivers/virt/geniezone/Makefile create mode 100644 drivers/virt/geniezone/gzvm_main.c create mode 100644 include/linux/gzvm_drv.h diff --git a/MAINTAINERS b/MAINTAINERS index 17a8e20d2baa..0cb2d0599469 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9019,6 +9019,9 @@ M: Ze-Yu Wang M: Yi-De Wu F: Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml F: Documentation/virt/geniezone/ +F: arch/arm64/geniezone/ +F: drivers/virt/geniezone/ +F: include/linux/gzvm_drv.h GENWQE (IBM Generic Workqueue Card) M: Frank Haverkamp diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild index 5bfbf7d79c99..0c3cca572919 100644 --- a/arch/arm64/Kbuild +++ b/arch/arm64/Kbuild @@ -4,6 +4,7 @@ obj-$(CONFIG_KVM) += kvm/ obj-$(CONFIG_XEN) += xen/ obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/ obj-$(CONFIG_CRYPTO) += crypto/ +obj-$(CONFIG_MTK_GZVM) += geniezone/ # for cleaning subdir- += boot diff --git a/arch/arm64/geniezone/Makefile b/arch/arm64/geniezone/Makefile new file mode 100644 index 000000000000..2957898cdd05 --- /dev/null +++ b/arch/arm64/geniezone/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Main Makefile for gzvm, this one includes drivers/virt/geniezone/Makefile +# +include $(srctree)/drivers/virt/geniezone/Makefile + +gzvm-y += vm.o + +obj-$(CONFIG_MTK_GZVM) += gzvm.o diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h new file mode 100644 index 000000000000..f5bddcfe3a1f --- /dev/null +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +#ifndef __GZVM_ARCH_COMMON_H__ +#define __GZVM_ARCH_COMMON_H__ + +#include + +enum { + GZVM_FUNC_PROBE = 12, + NR_GZVM_FUNC, +}; + +#define SMC_ENTITY_MTK 59 +#define GZVM_FUNCID_START (0x1000) +#define GZVM_HCALL_ID(func) \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \ + SMC_ENTITY_MTK, (GZVM_FUNCID_START + (func))) + +#define MT_HVC_GZVM_PROBE GZVM_HCALL_ID(GZVM_FUNC_PROBE) + +/** + * gzvm_hypcall_wrapper() - the wrapper for hvc calls + * @a0: arguments passed in registers 0 + * @a1: arguments passed in registers 1 + * @a2: arguments passed in registers 2 + * @a3: arguments passed in registers 3 + * @a4: arguments passed in registers 4 + * @a5: arguments passed in registers 5 + * @a6: arguments passed in registers 6 + * @a7: arguments passed in registers 7 + * @res: result values from registers 0 to 3 + * + * Return: The wrapper helps caller to convert geniezone errno to Linux errno. + */ +int gzvm_hypcall_wrapper(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + unsigned long a6, unsigned long a7, + struct arm_smccc_res *res); + +#endif /* __GZVM_ARCH_COMMON_H__ */ diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c new file mode 100644 index 000000000000..e313aadec212 --- /dev/null +++ b/arch/arm64/geniezone/vm.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +#include +#include +#include + +#include +#include "gzvm_arch_common.h" + +/** + * gzvm_hypcall_wrapper() - the wrapper for hvc calls + * @a0: arguments passed in registers 0 + * @a1: arguments passed in registers 1 + * @a2: arguments passed in registers 2 + * @a3: arguments passed in registers 3 + * @a4: arguments passed in registers 4 + * @a5: arguments passed in registers 5 + * @a6: arguments passed in registers 6 + * @a7: arguments passed in registers 7 + * @res: result values from registers 0 to 3 + * + * Return: The wrapper helps caller to convert geniezone errno to Linux errno. + */ +int gzvm_hypcall_wrapper(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + unsigned long a6, unsigned long a7, + struct arm_smccc_res *res) +{ + arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res); + return gzvm_err_to_errno(res->a0); +} + +int gzvm_arch_probe(void) +{ + struct arm_smccc_res res; + int ret; + + ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_PROBE, 0, 0, 0, 0, 0, 0, 0, &res); + if (ret) + return -ENXIO; + + return 0; +} diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig index 40129b6f0eca..b4e9bddbcee7 100644 --- a/drivers/virt/Kconfig +++ b/drivers/virt/Kconfig @@ -50,4 +50,6 @@ source "drivers/virt/acrn/Kconfig" source "drivers/virt/coco/Kconfig" +source "drivers/virt/geniezone/Kconfig" + endif diff --git a/drivers/virt/geniezone/Kconfig b/drivers/virt/geniezone/Kconfig new file mode 100644 index 000000000000..b17c06c91074 --- /dev/null +++ b/drivers/virt/geniezone/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config MTK_GZVM + tristate "GenieZone Hypervisor driver for guest VM operation" + depends on ARM64 && EVENTFD + help + This driver, gzvm, enables to run guest VMs on MTK GenieZone + hypervisor. It exports kvm-like interfaces for VMM (e.g., crosvm) in + order to operate guest VMs on GenieZone hypervisor. + + GenieZone hypervisor now only supports MediaTek SoC and arm64 + architecture. + + Select M if you want it be built as a module (gzvm.ko). + + If unsure, say N. diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile new file mode 100644 index 000000000000..8c1f0053e773 --- /dev/null +++ b/drivers/virt/geniezone/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for GenieZone driver, this file should be include in arch's +# to avoid two ko being generated. +# + +GZVM_DIR ?= ../../../drivers/virt/geniezone + +gzvm-y := $(GZVM_DIR)/gzvm_main.o + diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c new file mode 100644 index 000000000000..f7d4f0646d97 --- /dev/null +++ b/drivers/virt/geniezone/gzvm_main.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * gzvm_err_to_errno() - Convert geniezone return value to standard errno + * + * @err: Return value from geniezone function return + * + * Return: Standard errno + */ +int gzvm_err_to_errno(unsigned long err) +{ + int gz_err = (int)err; + + switch (gz_err) { + case 0: + return 0; + case ERR_NO_MEMORY: + return -ENOMEM; + case ERR_NOT_SUPPORTED: + return -EOPNOTSUPP; + case ERR_NOT_IMPLEMENTED: + return -EOPNOTSUPP; + case ERR_FAULT: + return -EFAULT; + default: + break; + } + + return -EINVAL; +} + +static const struct file_operations gzvm_chardev_ops = { + .llseek = noop_llseek, +}; + +static struct miscdevice gzvm_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = KBUILD_MODNAME, + .fops = &gzvm_chardev_ops, +}; + +static int gzvm_drv_probe(struct platform_device *pdev) +{ + if (gzvm_arch_probe() != 0) { + dev_err(&pdev->dev, "Not found available conduit\n"); + return -ENODEV; + } + + return misc_register(&gzvm_dev); +} + +static int gzvm_drv_remove(struct platform_device *pdev) +{ + misc_deregister(&gzvm_dev); + return 0; +} + +static const struct of_device_id gzvm_of_match[] = { + { .compatible = "mediatek,geniezone-hyp" }, + {/* sentinel */}, +}; + +static struct platform_driver gzvm_driver = { + .probe = gzvm_drv_probe, + .remove = gzvm_drv_remove, + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .of_match_table = gzvm_of_match, + }, +}; + +module_platform_driver(gzvm_driver); + +MODULE_DEVICE_TABLE(of, gzvm_of_match); +MODULE_AUTHOR("MediaTek"); +MODULE_DESCRIPTION("GenieZone interface for VMM"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h new file mode 100644 index 000000000000..907f2f984de9 --- /dev/null +++ b/include/linux/gzvm_drv.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +#ifndef __GZVM_DRV_H__ +#define __GZVM_DRV_H__ + +/* + * These are the definitions of APIs between GenieZone hypervisor and driver, + * there's no need to be visible to uapi. Furthermore, we need GenieZone + * specific error code in order to map to Linux errno + */ +#define NO_ERROR (0) +#define ERR_NO_MEMORY (-5) +#define ERR_NOT_SUPPORTED (-24) +#define ERR_NOT_IMPLEMENTED (-27) +#define ERR_FAULT (-40) + +int gzvm_err_to_errno(unsigned long err); + +/* arch-dependant functions */ +int gzvm_arch_probe(void); + +#endif /* __GZVM_DRV_H__ */ From patchwork Mon Jan 29 08:32:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767749 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95C8654729; Mon, 29 Jan 2024 08:33:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.61.82.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517195; cv=none; b=TI8Ql40ljPMiYERx8oYORbRrW7ae4Qk24lBBvLG4hs+UAjamotq96fDmxQvtSOfjg0vMBNq9pADuoZ/i/kM/iItCq9cf7PoV06aaPF3QOLj+yZv1fRhzdhDctnCVJQkoRsxxsY3+aV3o+N6bzKrmR9cNgC8thFCg1gOmLXj+cjE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517195; c=relaxed/simple; bh=AGuTTKQ7CXAKAlwvGzuYLQDfdeaTjSkM7/0L/OosiUE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=taTdeUgbdnUOTtog764MlRx6Mdjnq22ofwsn1kI590bikzaHe+7ZKapJ9+Gpqd5javtOPrdsWuhSEri5pdpgSq2ci91DEoTGBN0ohuolzt2udFIALuBZhVlYrGzFZ7h9ee3vyYOSxOyJapphDV5UZUdolHGZcIhLdDiVdlKtugs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=Q2q0/ObX; arc=none smtp.client-ip=210.61.82.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="Q2q0/ObX" X-UUID: 0749ba9cbe8111eea2298b7352fd921d-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=kB27ZzY8HZww63nFt0lAk21dZIKVPm5gFX0cwieprok=; b=Q2q0/ObXW8tPfFF+ESnHmmG7PHgs7tdErO4LLeM6eAywX9aEp1ZI9Kdj62SO0oA6D/lFIKEuShNsfTI1uJgXLQIUd8z/QVgLXMSD8rug5U7tFk5O01OTVCVZ7716IvMrrZjwLcByx7vftxql1yhu+B+Q4h5OL9DYl3PI7HGydoo=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:a7e105ce-a2e7-4384-bc10-2743e08e97b5, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:364143fe-c16b-4159-a099-3b9d0558e447, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: 0749ba9cbe8111eea2298b7352fd921d-20240129 Received: from mtkmbs11n1.mediatek.inc [(172.21.101.185)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1396927037; Mon, 29 Jan 2024 16:33:07 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:06 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:06 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , Willix Yeh , Kevenny Hsieh Subject: [PATCH v9 05/21] virt: geniezone: Add vm support Date: Mon, 29 Jan 2024 16:32:46 +0800 Message-ID: <20240129083302.26044-6-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MTK: N From: "Yingshiuan Pan" The VM component is responsible for setting up the capability and memory management for the protected VMs. The capability is mainly about the lifecycle control and boot context initialization. Signed-off-by: Yingshiuan Pan Signed-off-by: Jerry Wang Signed-off-by: Liju Chen Signed-off-by: Yi-De Wu --- MAINTAINERS | 1 + arch/arm64/geniezone/gzvm_arch_common.h | 9 ++ arch/arm64/geniezone/vm.c | 29 +++++++ drivers/virt/geniezone/Makefile | 2 +- drivers/virt/geniezone/gzvm_main.c | 19 +++++ drivers/virt/geniezone/gzvm_vm.c | 107 ++++++++++++++++++++++++ include/linux/gzvm_drv.h | 26 ++++++ include/uapi/linux/gzvm.h | 25 ++++++ 8 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 drivers/virt/geniezone/gzvm_vm.c create mode 100644 include/uapi/linux/gzvm.h diff --git a/MAINTAINERS b/MAINTAINERS index 0cb2d0599469..3ecac8794ba9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9022,6 +9022,7 @@ F: Documentation/virt/geniezone/ F: arch/arm64/geniezone/ F: drivers/virt/geniezone/ F: include/linux/gzvm_drv.h +F: include/uapi/linux/gzvm.h GENWQE (IBM Generic Workqueue Card) M: Frank Haverkamp diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h index f5bddcfe3a1f..fdaa7849353d 100644 --- a/arch/arm64/geniezone/gzvm_arch_common.h +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -9,6 +9,8 @@ #include enum { + GZVM_FUNC_CREATE_VM = 0, + GZVM_FUNC_DESTROY_VM = 1, GZVM_FUNC_PROBE = 12, NR_GZVM_FUNC, }; @@ -19,6 +21,8 @@ enum { ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \ SMC_ENTITY_MTK, (GZVM_FUNCID_START + (func))) +#define MT_HVC_GZVM_CREATE_VM GZVM_HCALL_ID(GZVM_FUNC_CREATE_VM) +#define MT_HVC_GZVM_DESTROY_VM GZVM_HCALL_ID(GZVM_FUNC_DESTROY_VM) #define MT_HVC_GZVM_PROBE GZVM_HCALL_ID(GZVM_FUNC_PROBE) /** @@ -41,4 +45,9 @@ int gzvm_hypcall_wrapper(unsigned long a0, unsigned long a1, unsigned long a6, unsigned long a7, struct arm_smccc_res *res); +static inline u16 get_vmid_from_tuple(unsigned int tuple) +{ + return (u16)(tuple >> 16); +} + #endif /* __GZVM_ARCH_COMMON_H__ */ diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c index e313aadec212..a15bad13c2ee 100644 --- a/arch/arm64/geniezone/vm.c +++ b/arch/arm64/geniezone/vm.c @@ -7,9 +7,12 @@ #include #include +#include #include #include "gzvm_arch_common.h" +#define PAR_PA47_MASK ((((1UL << 48) - 1) >> 12) << 12) + /** * gzvm_hypcall_wrapper() - the wrapper for hvc calls * @a0: arguments passed in registers 0 @@ -45,3 +48,29 @@ int gzvm_arch_probe(void) return 0; } + +/** + * gzvm_arch_create_vm() - create vm + * @vm_type: VM type. Only supports Linux VM now. + * + * Return: + * * positive value - VM ID + * * -ENOMEM - Memory not enough for storing VM data + */ +int gzvm_arch_create_vm(unsigned long vm_type) +{ + struct arm_smccc_res res; + int ret; + + ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VM, vm_type, 0, 0, 0, 0, + 0, 0, &res); + return ret ? ret : res.a1; +} + +int gzvm_arch_destroy_vm(u16 vm_id) +{ + struct arm_smccc_res res; + + return gzvm_hypcall_wrapper(MT_HVC_GZVM_DESTROY_VM, vm_id, 0, 0, 0, 0, + 0, 0, &res); +} diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile index 8c1f0053e773..066efddc0b9c 100644 --- a/drivers/virt/geniezone/Makefile +++ b/drivers/virt/geniezone/Makefile @@ -6,5 +6,5 @@ GZVM_DIR ?= ../../../drivers/virt/geniezone -gzvm-y := $(GZVM_DIR)/gzvm_main.o +gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c index f7d4f0646d97..4e7d60067c55 100644 --- a/drivers/virt/geniezone/gzvm_main.c +++ b/drivers/virt/geniezone/gzvm_main.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -40,7 +41,24 @@ int gzvm_err_to_errno(unsigned long err) return -EINVAL; } +static long gzvm_dev_ioctl(struct file *filp, unsigned int cmd, + unsigned long user_args) +{ + long ret; + + switch (cmd) { + case GZVM_CREATE_VM: + ret = gzvm_dev_ioctl_create_vm(user_args); + return ret; + default: + break; + } + + return -ENOTTY; +} + static const struct file_operations gzvm_chardev_ops = { + .unlocked_ioctl = gzvm_dev_ioctl, .llseek = noop_llseek, }; @@ -62,6 +80,7 @@ static int gzvm_drv_probe(struct platform_device *pdev) static int gzvm_drv_remove(struct platform_device *pdev) { + gzvm_destroy_all_vms(); misc_deregister(&gzvm_dev); return 0; } diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c new file mode 100644 index 000000000000..d5e850af924a --- /dev/null +++ b/drivers/virt/geniezone/gzvm_vm.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_MUTEX(gzvm_list_lock); +static LIST_HEAD(gzvm_list); + +static void gzvm_destroy_vm(struct gzvm *gzvm) +{ + pr_debug("VM-%u is going to be destroyed\n", gzvm->vm_id); + + mutex_lock(&gzvm->lock); + + gzvm_arch_destroy_vm(gzvm->vm_id); + + mutex_lock(&gzvm_list_lock); + list_del(&gzvm->vm_list); + mutex_unlock(&gzvm_list_lock); + + mutex_unlock(&gzvm->lock); + + kfree(gzvm); +} + +static int gzvm_vm_release(struct inode *inode, struct file *filp) +{ + struct gzvm *gzvm = filp->private_data; + + gzvm_destroy_vm(gzvm); + return 0; +} + +static const struct file_operations gzvm_vm_fops = { + .release = gzvm_vm_release, + .llseek = noop_llseek, +}; + +static struct gzvm *gzvm_create_vm(unsigned long vm_type) +{ + int ret; + struct gzvm *gzvm; + + gzvm = kzalloc(sizeof(*gzvm), GFP_KERNEL); + if (!gzvm) + return ERR_PTR(-ENOMEM); + + ret = gzvm_arch_create_vm(vm_type); + if (ret < 0) { + kfree(gzvm); + return ERR_PTR(ret); + } + + gzvm->vm_id = ret; + gzvm->mm = current->mm; + mutex_init(&gzvm->lock); + + mutex_lock(&gzvm_list_lock); + list_add(&gzvm->vm_list, &gzvm_list); + mutex_unlock(&gzvm_list_lock); + + pr_debug("VM-%u is created\n", gzvm->vm_id); + + return gzvm; +} + +/** + * gzvm_dev_ioctl_create_vm - Create vm fd + * @vm_type: VM type. Only supports Linux VM now. + * + * Return: fd of vm, negative if error + */ +int gzvm_dev_ioctl_create_vm(unsigned long vm_type) +{ + struct gzvm *gzvm; + + gzvm = gzvm_create_vm(vm_type); + if (IS_ERR(gzvm)) + return PTR_ERR(gzvm); + + return anon_inode_getfd("gzvm-vm", &gzvm_vm_fops, gzvm, + O_RDWR | O_CLOEXEC); +} + +void gzvm_destroy_all_vms(void) +{ + struct gzvm *gzvm, *tmp; + + mutex_lock(&gzvm_list_lock); + if (list_empty(&gzvm_list)) + goto out; + + list_for_each_entry_safe(gzvm, tmp, &gzvm_list, vm_list) + gzvm_destroy_vm(gzvm); + +out: + mutex_unlock(&gzvm_list_lock); +} diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h index 907f2f984de9..f1dce23838e4 100644 --- a/include/linux/gzvm_drv.h +++ b/include/linux/gzvm_drv.h @@ -6,6 +6,12 @@ #ifndef __GZVM_DRV_H__ #define __GZVM_DRV_H__ +#include +#include +#include + +#define INVALID_VM_ID 0xffff + /* * These are the definitions of APIs between GenieZone hypervisor and driver, * there's no need to be visible to uapi. Furthermore, we need GenieZone @@ -17,9 +23,29 @@ #define ERR_NOT_IMPLEMENTED (-27) #define ERR_FAULT (-40) +/* + * The following data structures are for data transferring between driver and + * hypervisor, and they're aligned with hypervisor definitions + */ + +struct gzvm { + /* userspace tied to this vm */ + struct mm_struct *mm; + /* lock for list_add*/ + struct mutex lock; + struct list_head vm_list; + u16 vm_id; +}; + +int gzvm_dev_ioctl_create_vm(unsigned long vm_type); + int gzvm_err_to_errno(unsigned long err); +void gzvm_destroy_all_vms(void); + /* arch-dependant functions */ int gzvm_arch_probe(void); +int gzvm_arch_create_vm(unsigned long vm_type); +int gzvm_arch_destroy_vm(u16 vm_id); #endif /* __GZVM_DRV_H__ */ diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h new file mode 100644 index 000000000000..c26c7720fab7 --- /dev/null +++ b/include/uapi/linux/gzvm.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +/** + * DOC: UAPI of GenieZone Hypervisor + * + * This file declares common data structure shared among user space, + * kernel space, and GenieZone hypervisor. + */ +#ifndef __GZVM_H__ +#define __GZVM_H__ + +#include +#include +#include + +/* GZVM ioctls */ +#define GZVM_IOC_MAGIC 0x92 /* gz */ + +/* ioctls for /dev/gzvm fds */ +#define GZVM_CREATE_VM _IO(GZVM_IOC_MAGIC, 0x01) /* Returns a Geniezone VM fd */ + +#endif /* __GZVM_H__ */ From patchwork Mon Jan 29 08:32:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767746 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2CD454FA2; Mon, 29 Jan 2024 08:33:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.61.82.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517198; cv=none; b=ln9pbKYQLd25jZjRgOdrHq6f6zTtzHfnBlx1nrUe10ZZd9mNowS+ApWjuHvz6QcLW2dnycU7sn2ncmeVz1uxQMQ2MdgINAO3vshtX7BYZbG+Q1h6S11lH6HKzh811QQsoYp0uq9XQ42rwB/dNZL42+0R59dobruTDMTGSrG9Nx4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517198; c=relaxed/simple; bh=d/HKFUI8hh50BRa54hRp/5YDi/wL8fi9NB810tBUV9A=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BOQyLKFLTwevAPeRSe1czx3LN5exMuNiD3MFg5lE9v4TfFrN2zuTzgNl7hmd5FWEBICh0mxbSZ8vtD7qWVMxXGBH3eZhwAD1gwc+sRdmcjCX2vzbmG803AAjeNHwqjdxs8UivjkyHc6RZ9+HUCL4nniP+og6pBADz27vDzKnR3I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=XASyWn+K; arc=none smtp.client-ip=210.61.82.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="XASyWn+K" X-UUID: 0891723cbe8111eea2298b7352fd921d-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=5gPx+SvCXGER7GnieatvV+tmNhNHASAQ8QOTxwJ1eJc=; b=XASyWn+KAC168zCd90EOZyl6L/9zZk1C7rBk2/1U1KjnNNA39+DOYIlNL9O7joccuojwlAGvyGRY2QgGrv3Swpnq6qNE9J2V47Zt4gsp6Rym7+mDsguXvICmQ9u5wW1VcwN6+iVk+c02WQrz2yFq6obqzurgD2543djV28L52mI=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:d418c62a-a6f7-4d3f-a7ba-d7084a3518da, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:5c4143fe-c16b-4159-a099-3b9d0558e447, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: 0891723cbe8111eea2298b7352fd921d-20240129 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 469260788; Mon, 29 Jan 2024 16:33:09 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by MTKMBS14N1.mediatek.inc (172.21.101.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:06 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:06 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , "Willix Yeh" , Kevenny Hsieh Subject: [PATCH v9 07/21] virt: geniezone: Add vm capability check Date: Mon, 29 Jan 2024 16:32:48 +0800 Message-ID: <20240129083302.26044-8-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-AS-Result: No-10--3.735800-8.000000 X-TMASE-MatchedRID: c6n4reyclFZWj3HFS14pKxn0UD4GU5Iq5E5u1OdPWsTgr/zYTDOZCJeq sXSeEviPpSHzbpDtJi1Yo3G+rvxrNW94Ipa1otxoh2VzUlo4HVPt/okBLaEo+M3uTDyQRGk0dYJ 3pC9XNt458CIn96icLWYlLqTvfoxMaB/391PZDWi3fk4rFE3BtBmPWPgE2ntcTUobVis5Bb/u9+ Mep8zDYpheOPJgS4aTCAv9MNEYwNxJI5ZUl647UBRFJJyf5BJe3QfwsVk0Ubt2gyyw2xTBhf1xm +6sPsbYjBl0RjbQXISXuYt1xEu5a0MtQb0+DpubtxFEiW5Gm6anPaRHQocDjTVVoSY9yTVzHGkh VmkNW9p1MunoSzaYr4CE5xpCtDRTUbJFyh4XXyqYo/TPOlMB4bCh3zE4wqa8DUCRr8oin+k= X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--3.735800-8.000000 X-TMASE-Version: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-SNTS-SMTP: CDA61DB802DD83FC77A5A565618A523CCE20A41B06FD43B8AF14A2D46CC84A162000:8 X-MTK: N From: "Yingshiuan Pan" Inquire the `capability support` on GenieZone hypervisor. Example: `GZVM_CAP_PROTECTED_VM` or `GZVM_CAP_VM_GPA_SIZE`. Signed-off-by: Yingshiuan Pan Signed-off-by: Jerry Wang Signed-off-by: kevenny hsieh Signed-off-by: Liju Chen Signed-off-by: Yi-De Wu --- arch/arm64/geniezone/gzvm_arch_common.h | 2 + arch/arm64/geniezone/vm.c | 122 ++++++++++++++++++++++++ drivers/virt/geniezone/gzvm_main.c | 27 ++++++ drivers/virt/geniezone/gzvm_vm.c | 21 ++++ include/linux/gzvm_drv.h | 5 + include/uapi/linux/gzvm.h | 31 ++++++ 6 files changed, 208 insertions(+) diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h index 2f66e496dfae..383af0829f11 100644 --- a/arch/arm64/geniezone/gzvm_arch_common.h +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -13,6 +13,7 @@ enum { GZVM_FUNC_DESTROY_VM = 1, GZVM_FUNC_SET_MEMREGION = 4, GZVM_FUNC_PROBE = 12, + GZVM_FUNC_ENABLE_CAP = 13, NR_GZVM_FUNC, }; @@ -26,6 +27,7 @@ enum { #define MT_HVC_GZVM_DESTROY_VM GZVM_HCALL_ID(GZVM_FUNC_DESTROY_VM) #define MT_HVC_GZVM_SET_MEMREGION GZVM_HCALL_ID(GZVM_FUNC_SET_MEMREGION) #define MT_HVC_GZVM_PROBE GZVM_HCALL_ID(GZVM_FUNC_PROBE) +#define MT_HVC_GZVM_ENABLE_CAP GZVM_HCALL_ID(GZVM_FUNC_ENABLE_CAP) /** * gzvm_hypcall_wrapper() - the wrapper for hvc calls diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c index 998d6498ac5e..02f94c86fbf1 100644 --- a/arch/arm64/geniezone/vm.c +++ b/arch/arm64/geniezone/vm.c @@ -58,6 +58,40 @@ int gzvm_arch_set_memregion(u16 vm_id, size_t buf_size, buf_size, region, 0, 0, 0, 0, &res); } +static int gzvm_cap_vm_gpa_size(void __user *argp) +{ + __u64 value = CONFIG_ARM64_PA_BITS; + + if (copy_to_user(argp, &value, sizeof(__u64))) + return -EFAULT; + + return 0; +} + +int gzvm_arch_check_extension(struct gzvm *gzvm, __u64 cap, void __user *argp) +{ + int ret; + + switch (cap) { + case GZVM_CAP_PROTECTED_VM: { + __u64 success = 1; + + if (copy_to_user(argp, &success, sizeof(__u64))) + return -EFAULT; + + return 0; + } + case GZVM_CAP_VM_GPA_SIZE: { + ret = gzvm_cap_vm_gpa_size(argp); + return ret; + } + default: + break; + } + + return -EOPNOTSUPP; +} + /** * gzvm_arch_create_vm() - create vm * @vm_type: VM type. Only supports Linux VM now. @@ -83,3 +117,91 @@ int gzvm_arch_destroy_vm(u16 vm_id) return gzvm_hypcall_wrapper(MT_HVC_GZVM_DESTROY_VM, vm_id, 0, 0, 0, 0, 0, 0, &res); } + +static int gzvm_vm_arch_enable_cap(struct gzvm *gzvm, + struct gzvm_enable_cap *cap, + struct arm_smccc_res *res) +{ + return gzvm_hypcall_wrapper(MT_HVC_GZVM_ENABLE_CAP, gzvm->vm_id, + cap->cap, cap->args[0], cap->args[1], + cap->args[2], cap->args[3], cap->args[4], + res); +} + +/** + * gzvm_vm_ioctl_get_pvmfw_size() - Get pvmfw size from hypervisor, return + * in x1, and return to userspace in args + * @gzvm: Pointer to struct gzvm. + * @cap: Pointer to struct gzvm_enable_cap. + * @argp: Pointer to struct gzvm_enable_cap in user space. + * + * Return: + * * 0 - Succeed + * * -EINVAL - Hypervisor return invalid results + * * -EFAULT - Fail to copy back to userspace buffer + */ +static int gzvm_vm_ioctl_get_pvmfw_size(struct gzvm *gzvm, + struct gzvm_enable_cap *cap, + void __user *argp) +{ + struct arm_smccc_res res = {0}; + + if (gzvm_vm_arch_enable_cap(gzvm, cap, &res) != 0) + return -EINVAL; + + cap->args[1] = res.a1; + if (copy_to_user(argp, cap, sizeof(*cap))) + return -EFAULT; + + return 0; +} + +/** + * gzvm_vm_ioctl_cap_pvm() - Proceed GZVM_CAP_PROTECTED_VM's subcommands + * @gzvm: Pointer to struct gzvm. + * @cap: Pointer to struct gzvm_enable_cap. + * @argp: Pointer to struct gzvm_enable_cap in user space. + * + * Return: + * * 0 - Succeed + * * -EINVAL - Invalid subcommand or arguments + */ +static int gzvm_vm_ioctl_cap_pvm(struct gzvm *gzvm, + struct gzvm_enable_cap *cap, + void __user *argp) +{ + struct arm_smccc_res res = {0}; + int ret; + + switch (cap->args[0]) { + case GZVM_CAP_PVM_SET_PVMFW_GPA: + fallthrough; + case GZVM_CAP_PVM_SET_PROTECTED_VM: + ret = gzvm_vm_arch_enable_cap(gzvm, cap, &res); + return ret; + case GZVM_CAP_PVM_GET_PVMFW_SIZE: + ret = gzvm_vm_ioctl_get_pvmfw_size(gzvm, cap, argp); + return ret; + default: + break; + } + + return -EINVAL; +} + +int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, + struct gzvm_enable_cap *cap, + void __user *argp) +{ + int ret; + + switch (cap->cap) { + case GZVM_CAP_PROTECTED_VM: + ret = gzvm_vm_ioctl_cap_pvm(gzvm, cap, argp); + return ret; + default: + break; + } + + return -EINVAL; +} diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c index 4e7d60067c55..30f6c3975026 100644 --- a/drivers/virt/geniezone/gzvm_main.c +++ b/drivers/virt/geniezone/gzvm_main.c @@ -41,6 +41,28 @@ int gzvm_err_to_errno(unsigned long err) return -EINVAL; } +/** + * gzvm_dev_ioctl_check_extension() - Check if given capability is support + * or not + * + * @gzvm: Pointer to struct gzvm + * @args: Pointer in u64 from userspace + * + * Return: + * * 0 - Supported, no error + * * -EOPNOTSUPP - Unsupported + * * -EFAULT - Failed to get data from userspace + */ +long gzvm_dev_ioctl_check_extension(struct gzvm *gzvm, unsigned long args) +{ + __u64 cap; + void __user *argp = (void __user *)args; + + if (copy_from_user(&cap, argp, sizeof(uint64_t))) + return -EFAULT; + return gzvm_arch_check_extension(gzvm, cap, argp); +} + static long gzvm_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long user_args) { @@ -50,6 +72,11 @@ static long gzvm_dev_ioctl(struct file *filp, unsigned int cmd, case GZVM_CREATE_VM: ret = gzvm_dev_ioctl_create_vm(user_args); return ret; + case GZVM_CHECK_EXTENSION: + if (!user_args) + return -EINVAL; + ret = gzvm_dev_ioctl_check_extension(NULL, user_args); + return ret; default: break; } diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c index 326cc9e93d92..ba6bfb7ee6e5 100644 --- a/drivers/virt/geniezone/gzvm_vm.c +++ b/drivers/virt/geniezone/gzvm_vm.c @@ -98,6 +98,13 @@ gzvm_vm_ioctl_set_memory_region(struct gzvm *gzvm, return register_memslot_addr_range(gzvm, memslot); } +static int gzvm_vm_ioctl_enable_cap(struct gzvm *gzvm, + struct gzvm_enable_cap *cap, + void __user *argp) +{ + return gzvm_vm_ioctl_arch_enable_cap(gzvm, cap, argp); +} + /* gzvm_vm_ioctl() - Ioctl handler of VM FD */ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) @@ -107,6 +114,10 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl, struct gzvm *gzvm = filp->private_data; switch (ioctl) { + case GZVM_CHECK_EXTENSION: { + ret = gzvm_dev_ioctl_check_extension(gzvm, arg); + break; + } case GZVM_SET_USER_MEMORY_REGION: { struct gzvm_userspace_memory_region userspace_mem; @@ -117,6 +128,16 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl, ret = gzvm_vm_ioctl_set_memory_region(gzvm, &userspace_mem); break; } + case GZVM_ENABLE_CAP: { + struct gzvm_enable_cap cap; + + if (copy_from_user(&cap, argp, sizeof(cap))) { + ret = -EFAULT; + goto out; + } + ret = gzvm_vm_ioctl_enable_cap(gzvm, &cap, argp); + break; + } default: ret = -ENOTTY; } diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h index 81696b7b67cc..01c92e7eb230 100644 --- a/include/linux/gzvm_drv.h +++ b/include/linux/gzvm_drv.h @@ -73,6 +73,7 @@ struct gzvm { u16 vm_id; }; +long gzvm_dev_ioctl_check_extension(struct gzvm *gzvm, unsigned long args); int gzvm_dev_ioctl_create_vm(unsigned long vm_type); int gzvm_err_to_errno(unsigned long err); @@ -83,8 +84,12 @@ void gzvm_destroy_all_vms(void); int gzvm_arch_probe(void); int gzvm_arch_set_memregion(u16 vm_id, size_t buf_size, phys_addr_t region); +int gzvm_arch_check_extension(struct gzvm *gzvm, __u64 cap, void __user *argp); int gzvm_arch_create_vm(unsigned long vm_type); int gzvm_arch_destroy_vm(u16 vm_id); +int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, + struct gzvm_enable_cap *cap, + void __user *argp); u64 gzvm_gfn_to_hva_memslot(struct gzvm_memslot *memslot, u64 gfn); diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h index d2d5e6cfc2c9..77a58ee085df 100644 --- a/include/uapi/linux/gzvm.h +++ b/include/uapi/linux/gzvm.h @@ -16,12 +16,30 @@ #include #include +#define GZVM_CAP_VM_GPA_SIZE 0xa5 +#define GZVM_CAP_PROTECTED_VM 0xffbadab1 + +/* sub-commands put in args[0] for GZVM_CAP_PROTECTED_VM */ +#define GZVM_CAP_PVM_SET_PVMFW_GPA 0 +#define GZVM_CAP_PVM_GET_PVMFW_SIZE 1 +/* GZVM_CAP_PVM_SET_PROTECTED_VM only sets protected but not load pvmfw */ +#define GZVM_CAP_PVM_SET_PROTECTED_VM 2 + /* GZVM ioctls */ #define GZVM_IOC_MAGIC 0x92 /* gz */ /* ioctls for /dev/gzvm fds */ #define GZVM_CREATE_VM _IO(GZVM_IOC_MAGIC, 0x01) /* Returns a Geniezone VM fd */ +/* + * Check if the given capability is supported or not. + * The argument is capability. Ex. GZVM_CAP_PROTECTED_VM or GZVM_CAP_VM_GPA_SIZE + * return is 0 (supported, no error) + * return is -EOPNOTSUPP (unsupported) + * return is -EFAULT (failed to get the argument from userspace) + */ +#define GZVM_CHECK_EXTENSION _IO(GZVM_IOC_MAGIC, 0x03) + /* ioctls for VM fds */ /* for GZVM_SET_MEMORY_REGION */ struct gzvm_memory_region { @@ -48,4 +66,17 @@ struct gzvm_userspace_memory_region { #define GZVM_SET_USER_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x46, \ struct gzvm_userspace_memory_region) +/** + * struct gzvm_enable_cap: The `capability support` on GenieZone hypervisor + * @cap: `GZVM_CAP_ARM_PROTECTED_VM` or `GZVM_CAP_ARM_VM_IPA_SIZE` + * @args: x3-x7 registers can be used for additional args + */ +struct gzvm_enable_cap { + __u64 cap; + __u64 args[5]; +}; + +#define GZVM_ENABLE_CAP _IOW(GZVM_IOC_MAGIC, 0xa3, \ + struct gzvm_enable_cap) + #endif /* __GZVM_H__ */ From patchwork Mon Jan 29 08:32:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767741 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6EECC54FBD; Mon, 29 Jan 2024 08:33:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.244.123.138 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517201; cv=none; b=jT8zlzI7g6DZaGM6Otvdaezfy+Sw8gmHDAHNMZJkUuKcdhcNrwOrMbm0sFj42ZgstBlR1UJFlT8CG4wEk+MOKtCp2DXcg59RwAnJZt3z1dA1VwRwyHTCjGYiI9syTp5Us2ETCuf6SVyJTrjIQclFDusXpgztGfKyDx5Arl63Pk8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517201; c=relaxed/simple; bh=zWBHsZ6AYh3703MWDOxIYgsZiju6u8Dq1MW10LG6frA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AXNCRaklqiZgm8CJdXPYUNTCA2v0rQ+ItfaemoKPGtDz6YoZNKv+cnwNC4g3Y3NVNqzSiaLsrfzPSbFBEeBKI43ei4g/PPd+pK2enZSBerprX31SImrY17pFoo0zdlQChTkrcIzXiD6Ovmk2IH8t5BbMwSss4F6acYhM3LljJqk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=V1WABMh0; arc=none smtp.client-ip=60.244.123.138 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="V1WABMh0" X-UUID: 07441038be8111ee9e680517dc993faa-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=U3TEP3dAkPcvkoWfWKdIYWdRniHndVGe+clI8wgZc3s=; b=V1WABMh0jOze3dwHbn67gLJr5F/RddFv7et7cS2NlsCb3NEQJQEBSoA6JSO7//zgLITAf4kDwmTpY9C/zpwkS2M9C+wQti2RZz0fMft7LSKhi1u8zxif5OQ9zI0bFDA4q/nEI/IwnPRgoBUTUuEir5cC8BwXhyAApuXgYum69kQ=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:3c0a2e4a-1676-4284-a79b-beedecbdfb49, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:ca25c58e-e2c0-40b0-a8fe-7c7e47299109, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: 07441038be8111ee9e680517dc993faa-20240129 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 840427911; Mon, 29 Jan 2024 16:33:07 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:07 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:07 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , "Willix Yeh" , Kevenny Hsieh Subject: [PATCH v9 09/21] virt: geniezone: Add vcpu support Date: Mon, 29 Jan 2024 16:32:50 +0800 Message-ID: <20240129083302.26044-10-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-AS-Result: No-10--18.825600-8.000000 X-TMASE-MatchedRID: xdvY8iRyW2o0+65nJzb9bEraSPuPii4AtjHGWON8yeMKOjjtK9XSTadT v3G1Y/zd4Qs7pgHb9b2tsViygrLz2s3AmdtMjGJV7spMO3HwKCBMkOX0UoduuQ6QlBHhBZuwPJ0 5UREtjOWcPcDHCp4L+uSWVqW5qzmOj1OThq6Zp6Dd+fuf9kcaphnTGsoCuCpFa0TOsL14A2kNgl Bs2cTdnWGtx6H9FoUQThknSgzVzTwEW9SZtilh+6IBnfMCFBiCkKAa/khZ3iRHZg0gWH5yUeKaD 3hfR6D+rx4/7L5qckqqtaJ+n0md3Ll/NE0vQj9WdXu122+iJtpaeGF3HGG+AG3D6f6IpbLIzWYa DJYzIAkP/MiosmZn5GFCI7wMVGc6sbKenLqQS8CxNxaTG4Ot0rqGBW9J0YqjjNnoU1fopov2/TE Cug0ApS8y9Xabj8MFRXEJavFm0TC/3hCwO9Ho3KuXEMlVYQm0ZclaB0BNhrQgUEQTkIWiYjPn4y DW5yf3T/DGD5v9oMrNxOyh7U4qzfhDfjwsp9c4QpxiLlDD9FVVftPGBTR0rsWkDW4kV3Wa90viw o9jlehoT+utVu+8PlXZr9QXanLjLZXKgIDET/8ZgmFGHqyx6yEdaywSZvzOGtRDsD0yuYazI9xg BJUBhHfqPgWiRQSIJiyYViP4AGPSuXLpNqOJSTQlj13qze9pDcK8n+cR7XKbKItl61J/yZ+inTK 0bC9eKrauXd3MZDU980qe9xzB3A== X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--18.825600-8.000000 X-TMASE-Version: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-SNTS-SMTP: C07FDFF80E8857C62A178FF9DD6BFC81F338E37E237CFE67730EA508052E39E82000:8 X-MTK: N From: "Yingshiuan Pan" VMM use this interface to create vcpu instance which is a fd, and this fd will be for any vcpu operations, such as setting vcpu registers and accepts the most important ioctl GZVM_VCPU_RUN which requests GenieZone hypervisor to do context switch to execute VM's vcpu context. Signed-off-by: Yingshiuan Pan Signed-off-by: Jerry Wang Signed-off-by: kevenny hsieh Signed-off-by: Liju Chen Signed-off-by: Yi-De Wu --- arch/arm64/geniezone/Makefile | 2 +- arch/arm64/geniezone/gzvm_arch_common.h | 30 +++ arch/arm64/geniezone/vcpu.c | 80 ++++++++ arch/arm64/geniezone/vm.c | 12 ++ drivers/virt/geniezone/Makefile | 2 +- drivers/virt/geniezone/gzvm_vcpu.c | 251 ++++++++++++++++++++++++ drivers/virt/geniezone/gzvm_vm.c | 5 + include/linux/gzvm_drv.h | 23 +++ include/uapi/linux/gzvm.h | 163 +++++++++++++++ 9 files changed, 566 insertions(+), 2 deletions(-) create mode 100644 arch/arm64/geniezone/vcpu.c create mode 100644 drivers/virt/geniezone/gzvm_vcpu.c diff --git a/arch/arm64/geniezone/Makefile b/arch/arm64/geniezone/Makefile index 2957898cdd05..69b0a4abeab0 100644 --- a/arch/arm64/geniezone/Makefile +++ b/arch/arm64/geniezone/Makefile @@ -4,6 +4,6 @@ # include $(srctree)/drivers/virt/geniezone/Makefile -gzvm-y += vm.o +gzvm-y += vm.o vcpu.o obj-$(CONFIG_MTK_GZVM) += gzvm.o diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h index 383af0829f11..684c35e2d9bc 100644 --- a/arch/arm64/geniezone/gzvm_arch_common.h +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -11,9 +11,15 @@ enum { GZVM_FUNC_CREATE_VM = 0, GZVM_FUNC_DESTROY_VM = 1, + GZVM_FUNC_CREATE_VCPU = 2, + GZVM_FUNC_DESTROY_VCPU = 3, GZVM_FUNC_SET_MEMREGION = 4, + GZVM_FUNC_RUN = 5, + GZVM_FUNC_GET_ONE_REG = 8, + GZVM_FUNC_SET_ONE_REG = 9, GZVM_FUNC_PROBE = 12, GZVM_FUNC_ENABLE_CAP = 13, + GZVM_FUNC_INFORM_EXIT = 14, NR_GZVM_FUNC, }; @@ -25,9 +31,15 @@ enum { #define MT_HVC_GZVM_CREATE_VM GZVM_HCALL_ID(GZVM_FUNC_CREATE_VM) #define MT_HVC_GZVM_DESTROY_VM GZVM_HCALL_ID(GZVM_FUNC_DESTROY_VM) +#define MT_HVC_GZVM_CREATE_VCPU GZVM_HCALL_ID(GZVM_FUNC_CREATE_VCPU) +#define MT_HVC_GZVM_DESTROY_VCPU GZVM_HCALL_ID(GZVM_FUNC_DESTROY_VCPU) #define MT_HVC_GZVM_SET_MEMREGION GZVM_HCALL_ID(GZVM_FUNC_SET_MEMREGION) +#define MT_HVC_GZVM_RUN GZVM_HCALL_ID(GZVM_FUNC_RUN) +#define MT_HVC_GZVM_GET_ONE_REG GZVM_HCALL_ID(GZVM_FUNC_GET_ONE_REG) +#define MT_HVC_GZVM_SET_ONE_REG GZVM_HCALL_ID(GZVM_FUNC_SET_ONE_REG) #define MT_HVC_GZVM_PROBE GZVM_HCALL_ID(GZVM_FUNC_PROBE) #define MT_HVC_GZVM_ENABLE_CAP GZVM_HCALL_ID(GZVM_FUNC_ENABLE_CAP) +#define MT_HVC_GZVM_INFORM_EXIT GZVM_HCALL_ID(GZVM_FUNC_INFORM_EXIT) /** * gzvm_hypcall_wrapper() - the wrapper for hvc calls @@ -54,4 +66,22 @@ static inline u16 get_vmid_from_tuple(unsigned int tuple) return (u16)(tuple >> 16); } +static inline u16 get_vcpuid_from_tuple(unsigned int tuple) +{ + return (u16)(tuple & 0xffff); +} + +static inline unsigned int +assemble_vm_vcpu_tuple(u16 vmid, u16 vcpuid) +{ + return ((unsigned int)vmid << 16 | vcpuid); +} + +static inline void +disassemble_vm_vcpu_tuple(unsigned int tuple, u16 *vmid, u16 *vcpuid) +{ + *vmid = get_vmid_from_tuple(tuple); + *vcpuid = get_vcpuid_from_tuple(tuple); +} + #endif /* __GZVM_ARCH_COMMON_H__ */ diff --git a/arch/arm64/geniezone/vcpu.c b/arch/arm64/geniezone/vcpu.c new file mode 100644 index 000000000000..f6670bd77ad6 --- /dev/null +++ b/arch/arm64/geniezone/vcpu.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +#include +#include +#include + +#include +#include +#include "gzvm_arch_common.h" + +int gzvm_arch_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, __u64 reg_id, + bool is_write, __u64 *data) +{ + struct arm_smccc_res res; + unsigned long a1; + int ret; + + a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid); + if (!is_write) { + ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_GET_ONE_REG, + a1, reg_id, 0, 0, 0, 0, 0, &res); + if (ret == 0) + *data = res.a1; + } else { + ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_ONE_REG, + a1, reg_id, *data, 0, 0, 0, 0, &res); + } + + return ret; +} + +int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason) +{ + struct arm_smccc_res res; + unsigned long a1; + int ret; + + a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid); + ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_RUN, a1, 0, 0, 0, 0, 0, + 0, &res); + *exit_reason = res.a1; + return ret; +} + +int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid) +{ + struct arm_smccc_res res; + unsigned long a1; + + a1 = assemble_vm_vcpu_tuple(vm_id, vcpuid); + gzvm_hypcall_wrapper(MT_HVC_GZVM_DESTROY_VCPU, a1, 0, 0, 0, 0, 0, 0, + &res); + + return 0; +} + +/** + * gzvm_arch_create_vcpu() - Call smc to gz hypervisor to create vcpu + * @vm_id: vm id + * @vcpuid: vcpu id + * @run: Virtual address of vcpu->run + * + * Return: The wrapper helps caller to convert geniezone errno to Linux errno. + */ +int gzvm_arch_create_vcpu(u16 vm_id, int vcpuid, void *run) +{ + struct arm_smccc_res res; + unsigned long a1, a2; + int ret; + + a1 = assemble_vm_vcpu_tuple(vm_id, vcpuid); + a2 = (__u64)virt_to_phys(run); + ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VCPU, a1, a2, 0, 0, 0, 0, + 0, &res); + + return ret; +} diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c index b6a2bfa98b43..1fac10b98c11 100644 --- a/arch/arm64/geniezone/vm.c +++ b/arch/arm64/geniezone/vm.c @@ -37,6 +37,18 @@ int gzvm_hypcall_wrapper(unsigned long a0, unsigned long a1, return gzvm_err_to_errno(res->a0); } +int gzvm_arch_inform_exit(u16 vm_id) +{ + struct arm_smccc_res res; + int ret; + + ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_INFORM_EXIT, vm_id, 0, 0, 0, 0, 0, 0, &res); + if (ret) + return -ENXIO; + + return 0; +} + int gzvm_arch_probe(void) { struct arm_smccc_res res; diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile index 59fc4510a843..a630b919cda5 100644 --- a/drivers/virt/geniezone/Makefile +++ b/drivers/virt/geniezone/Makefile @@ -7,4 +7,4 @@ GZVM_DIR ?= ../../../drivers/virt/geniezone gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o \ - $(GZVM_DIR)/gzvm_mmu.o + $(GZVM_DIR)/gzvm_mmu.o $(GZVM_DIR)/gzvm_vcpu.o diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c new file mode 100644 index 000000000000..39c471d0d257 --- /dev/null +++ b/drivers/virt/geniezone/gzvm_vcpu.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* maximum size needed for holding an integer */ +#define ITOA_MAX_LEN 12 + +static long gzvm_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, + void __user *argp, + bool is_write) +{ + struct gzvm_one_reg reg; + void __user *reg_addr; + u64 data = 0; + u64 reg_size; + long ret; + + if (copy_from_user(®, argp, sizeof(reg))) + return -EFAULT; + + reg_addr = (void __user *)reg.addr; + reg_size = (reg.id & GZVM_REG_SIZE_MASK) >> GZVM_REG_SIZE_SHIFT; + reg_size = BIT(reg_size); + + if (reg_size != 1 && reg_size != 2 && reg_size != 4 && reg_size != 8) + return -EINVAL; + + if (is_write) { + /* GZ hypervisor would filter out invalid vcpu register access */ + if (copy_from_user(&data, reg_addr, reg_size)) + return -EFAULT; + } else { + return -EOPNOTSUPP; + } + + ret = gzvm_arch_vcpu_update_one_reg(vcpu, reg.id, is_write, &data); + + if (ret) + return ret; + + return 0; +} + +/** + * gzvm_vcpu_run() - Handle vcpu run ioctl, entry point to guest and exit + * point from guest + * @vcpu: Pointer to struct gzvm_vcpu + * @argp: Pointer to struct gzvm_vcpu_run in userspace + * + * Return: + * * 0 - Success. + * * Negative - Failure. + */ +static long gzvm_vcpu_run(struct gzvm_vcpu *vcpu, void __user *argp) +{ + bool need_userspace = false; + u64 exit_reason = 0; + + if (copy_from_user(vcpu->run, argp, sizeof(struct gzvm_vcpu_run))) + return -EFAULT; + + for (int i = 0; i < ARRAY_SIZE(vcpu->run->padding1); i++) { + if (vcpu->run->padding1[i]) + return -EINVAL; + } + + if (vcpu->run->immediate_exit == 1) + return -EINTR; + + while (!need_userspace && !signal_pending(current)) { + gzvm_arch_vcpu_run(vcpu, &exit_reason); + + switch (exit_reason) { + case GZVM_EXIT_MMIO: + need_userspace = true; + break; + /** + * it's geniezone's responsibility to fill corresponding data + * structure + */ + case GZVM_EXIT_HYPERCALL: + fallthrough; + case GZVM_EXIT_EXCEPTION: + fallthrough; + case GZVM_EXIT_DEBUG: + fallthrough; + case GZVM_EXIT_FAIL_ENTRY: + fallthrough; + case GZVM_EXIT_INTERNAL_ERROR: + fallthrough; + case GZVM_EXIT_SYSTEM_EVENT: + fallthrough; + case GZVM_EXIT_SHUTDOWN: + need_userspace = true; + break; + case GZVM_EXIT_IRQ: + fallthrough; + case GZVM_EXIT_GZ: + break; + case GZVM_EXIT_UNKNOWN: + fallthrough; + default: + pr_err("vcpu unknown exit\n"); + need_userspace = true; + goto out; + } + } + +out: + if (copy_to_user(argp, vcpu->run, sizeof(struct gzvm_vcpu_run))) + return -EFAULT; + if (signal_pending(current)) { + // invoke hvc to inform gz to map memory + gzvm_arch_inform_exit(vcpu->gzvm->vm_id); + return -ERESTARTSYS; + } + return 0; +} + +static long gzvm_vcpu_ioctl(struct file *filp, unsigned int ioctl, + unsigned long arg) +{ + int ret = -ENOTTY; + void __user *argp = (void __user *)arg; + struct gzvm_vcpu *vcpu = filp->private_data; + + switch (ioctl) { + case GZVM_RUN: + ret = gzvm_vcpu_run(vcpu, argp); + break; + case GZVM_GET_ONE_REG: + /* !is_write */ + ret = -EOPNOTSUPP; + break; + case GZVM_SET_ONE_REG: + /* is_write */ + ret = gzvm_vcpu_update_one_reg(vcpu, argp, true); + break; + default: + break; + } + + return ret; +} + +static const struct file_operations gzvm_vcpu_fops = { + .unlocked_ioctl = gzvm_vcpu_ioctl, + .llseek = noop_llseek, +}; + +/* caller must hold the vm lock */ +static void gzvm_destroy_vcpu(struct gzvm_vcpu *vcpu) +{ + if (!vcpu) + return; + + gzvm_arch_destroy_vcpu(vcpu->gzvm->vm_id, vcpu->vcpuid); + /* clean guest's data */ + memset(vcpu->run, 0, GZVM_VCPU_RUN_MAP_SIZE); + free_pages_exact(vcpu->run, GZVM_VCPU_RUN_MAP_SIZE); + kfree(vcpu); +} + +/** + * gzvm_destroy_vcpus() - Destroy all vcpus, caller has to hold the vm lock + * + * @gzvm: vm struct that owns the vcpus + */ +void gzvm_destroy_vcpus(struct gzvm *gzvm) +{ + int i; + + for (i = 0; i < GZVM_MAX_VCPUS; i++) { + gzvm_destroy_vcpu(gzvm->vcpus[i]); + gzvm->vcpus[i] = NULL; + } +} + +/* create_vcpu_fd() - Allocates an inode for the vcpu. */ +static int create_vcpu_fd(struct gzvm_vcpu *vcpu) +{ + /* sizeof("gzvm-vcpu:") + max(strlen(itoa(vcpuid))) + null */ + char name[10 + ITOA_MAX_LEN + 1]; + + snprintf(name, sizeof(name), "gzvm-vcpu:%d", vcpu->vcpuid); + return anon_inode_getfd(name, &gzvm_vcpu_fops, vcpu, O_RDWR | O_CLOEXEC); +} + +/** + * gzvm_vm_ioctl_create_vcpu() - for GZVM_CREATE_VCPU + * @gzvm: Pointer to struct gzvm + * @cpuid: equals arg + * + * Return: Fd of vcpu, negative errno if error occurs + */ +int gzvm_vm_ioctl_create_vcpu(struct gzvm *gzvm, u32 cpuid) +{ + struct gzvm_vcpu *vcpu; + int ret; + + if (cpuid >= GZVM_MAX_VCPUS) + return -EINVAL; + + vcpu = kzalloc(sizeof(*vcpu), GFP_KERNEL); + if (!vcpu) + return -ENOMEM; + + /** + * Allocate 2 pages for data sharing between driver and gz hypervisor + * + * |- page 0 -|- page 1 -| + * |gzvm_vcpu_run|......|hwstate|.......| + * + */ + vcpu->run = alloc_pages_exact(GZVM_VCPU_RUN_MAP_SIZE, + GFP_KERNEL_ACCOUNT | __GFP_ZERO); + if (!vcpu->run) { + ret = -ENOMEM; + goto free_vcpu; + } + vcpu->vcpuid = cpuid; + vcpu->gzvm = gzvm; + mutex_init(&vcpu->lock); + + ret = gzvm_arch_create_vcpu(gzvm->vm_id, vcpu->vcpuid, vcpu->run); + if (ret < 0) + goto free_vcpu_run; + + ret = create_vcpu_fd(vcpu); + if (ret < 0) + goto free_vcpu_run; + gzvm->vcpus[cpuid] = vcpu; + + return ret; + +free_vcpu_run: + free_pages_exact(vcpu->run, GZVM_VCPU_RUN_MAP_SIZE); +free_vcpu: + kfree(vcpu); + return ret; +} diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c index ba6bfb7ee6e5..ab5a96400f3c 100644 --- a/drivers/virt/geniezone/gzvm_vm.c +++ b/drivers/virt/geniezone/gzvm_vm.c @@ -118,6 +118,10 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl, ret = gzvm_dev_ioctl_check_extension(gzvm, arg); break; } + case GZVM_CREATE_VCPU: { + ret = gzvm_vm_ioctl_create_vcpu(gzvm, arg); + break; + } case GZVM_SET_USER_MEMORY_REGION: { struct gzvm_userspace_memory_region userspace_mem; @@ -151,6 +155,7 @@ static void gzvm_destroy_vm(struct gzvm *gzvm) mutex_lock(&gzvm->lock); + gzvm_destroy_vcpus(gzvm); gzvm_arch_destroy_vm(gzvm->vm_id); mutex_lock(&gzvm_list_lock); diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h index 8ba0ec36bc8c..8d4f162903f0 100644 --- a/include/linux/gzvm_drv.h +++ b/include/linux/gzvm_drv.h @@ -17,6 +17,7 @@ */ #define GZVM_PA_ERR_BAD (0x7ffULL << 52) +#define GZVM_VCPU_MMAP_SIZE PAGE_SIZE #define INVALID_VM_ID 0xffff /* @@ -34,8 +35,11 @@ * The following data structures are for data transferring between driver and * hypervisor, and they're aligned with hypervisor definitions */ +#define GZVM_MAX_VCPUS 8 #define GZVM_MAX_MEM_REGION 10 +#define GZVM_VCPU_RUN_MAP_SIZE (PAGE_SIZE * 2) + /* struct mem_region_addr_range - Identical to ffa memory constituent */ struct mem_region_addr_range { /* the base IPA of the constituent memory region, aligned to 4 kiB */ @@ -63,7 +67,16 @@ struct gzvm_memslot { u32 slot_id; }; +struct gzvm_vcpu { + struct gzvm *gzvm; + int vcpuid; + /* lock of vcpu*/ + struct mutex lock; + struct gzvm_vcpu_run *run; +}; + struct gzvm { + struct gzvm_vcpu *vcpus[GZVM_MAX_VCPUS]; /* userspace tied to this vm */ struct mm_struct *mm; struct gzvm_memslot memslot[GZVM_MAX_MEM_REGION]; @@ -80,6 +93,8 @@ int gzvm_err_to_errno(unsigned long err); void gzvm_destroy_all_vms(void); +void gzvm_destroy_vcpus(struct gzvm *gzvm); + /* arch-dependant functions */ int gzvm_arch_probe(void); int gzvm_arch_set_memregion(u16 vm_id, size_t buf_size, @@ -99,4 +114,12 @@ u64 gzvm_gfn_to_hva_memslot(struct gzvm_memslot *memslot, u64 gfn); int gzvm_vm_populate_mem_region(struct gzvm *gzvm, int slot_id); int gzvm_vm_allocate_guest_page(struct gzvm_memslot *slot, u64 gfn, u64 *pfn); +int gzvm_vm_ioctl_create_vcpu(struct gzvm *gzvm, u32 cpuid); +int gzvm_arch_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, __u64 reg_id, + bool is_write, __u64 *data); +int gzvm_arch_create_vcpu(u16 vm_id, int vcpuid, void *run); +int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason); +int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid); +int gzvm_arch_inform_exit(u16 vm_id); + #endif /* __GZVM_DRV_H__ */ diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h index 77a58ee085df..9753de18ea5e 100644 --- a/include/uapi/linux/gzvm.h +++ b/include/uapi/linux/gzvm.h @@ -25,6 +25,30 @@ /* GZVM_CAP_PVM_SET_PROTECTED_VM only sets protected but not load pvmfw */ #define GZVM_CAP_PVM_SET_PROTECTED_VM 2 +/* + * Architecture specific registers are to be defined and ORed with + * the arch identifier. + */ +#define GZVM_REG_ARCH_ARM64 FIELD_PREP(GENMASK_ULL(63, 56), 0x60) +#define GZVM_REG_ARCH_MASK FIELD_PREP(GENMASK_ULL(63, 56), 0xff) +/* + * Reg size = BIT((reg.id & GZVM_REG_SIZE_MASK) >> GZVM_REG_SIZE_SHIFT) bytes + */ +#define GZVM_REG_SIZE_SHIFT 52 +#define GZVM_REG_SIZE_MASK FIELD_PREP(GENMASK_ULL(63, 48), 0x00f0) + +#define GZVM_REG_SIZE_U8 FIELD_PREP(GENMASK_ULL(63, 48), 0x0000) +#define GZVM_REG_SIZE_U16 FIELD_PREP(GENMASK_ULL(63, 48), 0x0010) +#define GZVM_REG_SIZE_U32 FIELD_PREP(GENMASK_ULL(63, 48), 0x0020) +#define GZVM_REG_SIZE_U64 FIELD_PREP(GENMASK_ULL(63, 48), 0x0030) +#define GZVM_REG_SIZE_U128 FIELD_PREP(GENMASK_ULL(63, 48), 0x0040) +#define GZVM_REG_SIZE_U256 FIELD_PREP(GENMASK_ULL(63, 48), 0x0050) +#define GZVM_REG_SIZE_U512 FIELD_PREP(GENMASK_ULL(63, 48), 0x0060) +#define GZVM_REG_SIZE_U1024 FIELD_PREP(GENMASK_ULL(63, 48), 0x0070) +#define GZVM_REG_SIZE_U2048 FIELD_PREP(GENMASK_ULL(63, 48), 0x0080) + +#define GZVM_REG_TYPE_GENERAL2 FIELD_PREP(GENMASK(23, 16), 0x10) + /* GZVM ioctls */ #define GZVM_IOC_MAGIC 0x92 /* gz */ @@ -51,6 +75,11 @@ struct gzvm_memory_region { #define GZVM_SET_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x40, \ struct gzvm_memory_region) +/* + * GZVM_CREATE_VCPU receives as a parameter the vcpu slot, + * and returns a vcpu fd. + */ +#define GZVM_CREATE_VCPU _IO(GZVM_IOC_MAGIC, 0x41) /* for GZVM_SET_USER_MEMORY_REGION */ struct gzvm_userspace_memory_region { @@ -66,6 +95,127 @@ struct gzvm_userspace_memory_region { #define GZVM_SET_USER_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x46, \ struct gzvm_userspace_memory_region) +/* + * ioctls for vcpu fds + */ +#define GZVM_RUN _IO(GZVM_IOC_MAGIC, 0x80) + +/* VM exit reason */ +enum { + GZVM_EXIT_UNKNOWN = 0x92920000, + GZVM_EXIT_MMIO = 0x92920001, + GZVM_EXIT_HYPERCALL = 0x92920002, + GZVM_EXIT_IRQ = 0x92920003, + GZVM_EXIT_EXCEPTION = 0x92920004, + GZVM_EXIT_DEBUG = 0x92920005, + GZVM_EXIT_FAIL_ENTRY = 0x92920006, + GZVM_EXIT_INTERNAL_ERROR = 0x92920007, + GZVM_EXIT_SYSTEM_EVENT = 0x92920008, + GZVM_EXIT_SHUTDOWN = 0x92920009, + GZVM_EXIT_GZ = 0x9292000a, +}; + +/** + * struct gzvm_vcpu_run: Same purpose as kvm_run, this struct is + * shared between userspace, kernel and + * GenieZone hypervisor + * @exit_reason: The reason why gzvm_vcpu_run has stopped running the vCPU + * @immediate_exit: Polled when the vcpu is scheduled. + * If set, immediately returns -EINTR + * @padding1: Reserved for future-proof and must be zero filled + * @mmio: The nested struct in anonymous union. Handle mmio in host side + * @fail_entry: The nested struct in anonymous union. + * Handle invalid entry address at the first run + * @exception: The nested struct in anonymous union. + * Handle exception occurred in VM + * @hypercall: The nested struct in anonymous union. + * Some hypercalls issued from VM must be handled + * @internal: The nested struct in anonymous union. The errors from hypervisor + * @system_event: The nested struct in anonymous union. + * VM's PSCI must be handled by host + * @padding: Fix it to a reasonable size future-proof for keeping the same + * struct size when adding new variables in the union is needed + * + * Keep identical layout between the 3 modules + */ +struct gzvm_vcpu_run { + /* to userspace */ + __u32 exit_reason; + __u8 immediate_exit; + __u8 padding1[3]; + /* union structure of collection of guest exit reason */ + union { + /* GZVM_EXIT_MMIO */ + struct { + /* From FAR_EL2 */ + /* The address guest tries to access */ + __u64 phys_addr; + /* The value to be written (is_write is 1) or + * be filled by user for reads (is_write is 0) + */ + __u8 data[8]; + /* From ESR_EL2 as */ + /* The size of written data. + * Only the first `size` bytes of `data` are handled + */ + __u64 size; + /* From ESR_EL2 */ + /* The register number where the data is stored */ + __u32 reg_nr; + /* From ESR_EL2 */ + /* 1 for VM to perform a write or 0 for VM to perform a read */ + __u8 is_write; + } mmio; + /* GZVM_EXIT_FAIL_ENTRY */ + struct { + /* The reason codes about hardware entry failure */ + __u64 hardware_entry_failure_reason; + /* The current processor number via smp_processor_id() */ + __u32 cpu; + } fail_entry; + /* GZVM_EXIT_EXCEPTION */ + struct { + /* Which exception vector */ + __u32 exception; + /* Exception error codes */ + __u32 error_code; + } exception; + /* GZVM_EXIT_HYPERCALL */ + struct { + /* The hypercall's arguments */ + __u64 args[8]; /* in-out */ + } hypercall; + /* GZVM_EXIT_INTERNAL_ERROR */ + struct { + /* The errors codes about GZVM_EXIT_INTERNAL_ERROR */ + __u32 suberror; + /* The number of elements used in data[] */ + __u32 ndata; + /* Keep the detailed information about GZVM_EXIT_SYSTEM_EVENT */ + __u64 data[16]; + } internal; + /* GZVM_EXIT_SYSTEM_EVENT */ + struct { +#define GZVM_SYSTEM_EVENT_SHUTDOWN 1 +#define GZVM_SYSTEM_EVENT_RESET 2 +#define GZVM_SYSTEM_EVENT_CRASH 3 +#define GZVM_SYSTEM_EVENT_WAKEUP 4 +#define GZVM_SYSTEM_EVENT_SUSPEND 5 +#define GZVM_SYSTEM_EVENT_SEV_TERM 6 +#define GZVM_SYSTEM_EVENT_S2IDLE 7 + /* System event type. + * Ex. GZVM_SYSTEM_EVENT_SHUTDOWN or GZVM_SYSTEM_EVENT_RESET...etc. + */ + __u32 type; + /* The number of elements used in data[] */ + __u32 ndata; + /* Keep the detailed information about GZVM_EXIT_SYSTEM_EVENT */ + __u64 data[16]; + } system_event; + char padding[256]; + }; +}; + /** * struct gzvm_enable_cap: The `capability support` on GenieZone hypervisor * @cap: `GZVM_CAP_ARM_PROTECTED_VM` or `GZVM_CAP_ARM_VM_IPA_SIZE` @@ -79,4 +229,17 @@ struct gzvm_enable_cap { #define GZVM_ENABLE_CAP _IOW(GZVM_IOC_MAGIC, 0xa3, \ struct gzvm_enable_cap) +/* for GZVM_GET/SET_ONE_REG */ +struct gzvm_one_reg { + __u64 id; + __u64 addr; +}; + +#define GZVM_GET_ONE_REG _IOW(GZVM_IOC_MAGIC, 0xab, \ + struct gzvm_one_reg) +#define GZVM_SET_ONE_REG _IOW(GZVM_IOC_MAGIC, 0xac, \ + struct gzvm_one_reg) + +#define GZVM_REG_GENERIC 0x0000000000000000ULL + #endif /* __GZVM_H__ */ From patchwork Mon Jan 29 08:32:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767748 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E332554BEE; Mon, 29 Jan 2024 08:33:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.61.82.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517197; cv=none; b=htR0BlbEk2X+hMNdTTQJlqxEFhGBUDWlOzdyasKojf8BAmJHIPbo+BRIcZZiejMnwPWecNkdLIG4Jm8RnyPaBHUiUktJYEamUwGoc/M9VdJDh4buJnSA2D0qyakUPvwJ7kqz7uODsuRT8FOqL6D+kOLCfkgzMnsOF4W/3hHwZzE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517197; c=relaxed/simple; bh=df8OCIJIjXNql5SXELtIUahpHwCSZt1qI0mjlVq8JEk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ppcQrLWvYr9rQyNqCDf2dUsYQz57vW+O2HBlYPNPhNw5ibIZ9st8xyqeqL3F1kMXgupxP5K94wGmBqJTSq6QDIZ8l+ZghwAYWKt9z9K2cRvuemHoLBQyWXk/Se63IasDVctJF8egtBTp6Xj+sW+PDEQvtoz0UhiHeqbydpe5EZQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=hGTRznG5; arc=none smtp.client-ip=210.61.82.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="hGTRznG5" X-UUID: 083afa88be8111eea2298b7352fd921d-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=gEsqQaVw2fZPcKQ0vr0ik9mFatOLZX4Ha+8Q/xNUNjA=; b=hGTRznG5DPaew9lP7diCgmSB5/mocjDK8Vor4of8Z2fF5j67mfjBuOfNdTSuRDRthTvyo/R3mXHeMUhPkh5by5weYqBNmSJrFTsOkNjm0huUgOVk/e5v8PSmec17iZA1q+dnPPB2MiqHOiWnh5Da2gQu+9rRGP6O+sli3REqsgQ=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:f0c23d67-02dc-4e8c-a91d-f67602706d39, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:1945de7f-4f93-4875-95e7-8c66ea833d57, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0,NGT X-CID-BAS: 0,NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: 083afa88be8111eea2298b7352fd921d-20240129 Received: from mtkmbs13n2.mediatek.inc [(172.21.101.108)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 2072102808; Mon, 29 Jan 2024 16:33:09 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs13n1.mediatek.inc (172.21.101.193) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:08 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:08 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , Willix Yeh , Kevenny Hsieh Subject: [PATCH v9 13/21] virt: geniezone: Add memory region support Date: Mon, 29 Jan 2024 16:32:54 +0800 Message-ID: <20240129083302.26044-14-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MTK: N From: "Jerry Wang" Hypervisor might need to know the precise purpose of each memory region, so that it can provide specific memory protection. We add a new uapi to pass address and size of a memory region and its purpose. Signed-off-by: Jerry Wang Signed-off-by: Liju-clr Chen Signed-off-by: Yi-De Wu --- arch/arm64/geniezone/gzvm_arch_common.h | 2 ++ arch/arm64/geniezone/vm.c | 10 ++++++++++ drivers/virt/geniezone/gzvm_vm.c | 7 +++++++ include/linux/gzvm_drv.h | 3 +++ 4 files changed, 22 insertions(+) diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h index 67c7864c3afc..8d1406beeaed 100644 --- a/arch/arm64/geniezone/gzvm_arch_common.h +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -22,6 +22,7 @@ enum { GZVM_FUNC_PROBE = 12, GZVM_FUNC_ENABLE_CAP = 13, GZVM_FUNC_INFORM_EXIT = 14, + GZVM_FUNC_MEMREGION_PURPOSE = 15, NR_GZVM_FUNC, }; @@ -44,6 +45,7 @@ enum { #define MT_HVC_GZVM_PROBE GZVM_HCALL_ID(GZVM_FUNC_PROBE) #define MT_HVC_GZVM_ENABLE_CAP GZVM_HCALL_ID(GZVM_FUNC_ENABLE_CAP) #define MT_HVC_GZVM_INFORM_EXIT GZVM_HCALL_ID(GZVM_FUNC_INFORM_EXIT) +#define MT_HVC_GZVM_MEMREGION_PURPOSE GZVM_HCALL_ID(GZVM_FUNC_MEMREGION_PURPOSE) #define GIC_V3_NR_LRS 16 diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c index 1fac10b98c11..735a599f7da7 100644 --- a/arch/arm64/geniezone/vm.c +++ b/arch/arm64/geniezone/vm.c @@ -130,6 +130,16 @@ int gzvm_arch_destroy_vm(u16 vm_id) 0, 0, &res); } +int gzvm_arch_memregion_purpose(struct gzvm *gzvm, + struct gzvm_userspace_memory_region *mem) +{ + struct arm_smccc_res res; + + return gzvm_hypcall_wrapper(MT_HVC_GZVM_MEMREGION_PURPOSE, gzvm->vm_id, + mem->guest_phys_addr, mem->memory_size, + mem->flags, 0, 0, 0, &res); +} + static int gzvm_vm_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap, struct arm_smccc_res *res) diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c index d67bf647b615..4134605cbf7d 100644 --- a/drivers/virt/geniezone/gzvm_vm.c +++ b/drivers/virt/geniezone/gzvm_vm.c @@ -72,6 +72,7 @@ static int gzvm_vm_ioctl_set_memory_region(struct gzvm *gzvm, struct gzvm_userspace_memory_region *mem) { + int ret; struct vm_area_struct *vma; struct gzvm_memslot *memslot; unsigned long size; @@ -96,6 +97,12 @@ gzvm_vm_ioctl_set_memory_region(struct gzvm *gzvm, memslot->vma = vma; memslot->flags = mem->flags; memslot->slot_id = mem->slot; + + ret = gzvm_arch_memregion_purpose(gzvm, mem); + if (ret) { + pr_err("Failed to config memory region for the specified purpose\n"); + return -EFAULT; + } return register_memslot_addr_range(gzvm, memslot); } diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h index f467f8aef28c..6e081288d41e 100644 --- a/include/linux/gzvm_drv.h +++ b/include/linux/gzvm_drv.h @@ -154,6 +154,9 @@ void gzvm_drv_irqfd_exit(void); int gzvm_vm_irqfd_init(struct gzvm *gzvm); void gzvm_vm_irqfd_release(struct gzvm *gzvm); +int gzvm_arch_memregion_purpose(struct gzvm *gzvm, + struct gzvm_userspace_memory_region *mem); + int gzvm_init_ioeventfd(struct gzvm *gzvm); int gzvm_ioeventfd(struct gzvm *gzvm, struct gzvm_ioeventfd *args); bool gzvm_ioevent_write(struct gzvm_vcpu *vcpu, __u64 addr, int len, From patchwork Mon Jan 29 08:32:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767743 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 653AA55C28; Mon, 29 Jan 2024 08:33:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.244.123.138 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517201; cv=none; b=inWmEN0G7+AZhvlGMTlvp1myIfkigKqV7R4mICsAvRTzZ1saX6xQkPMv0emlB+Hh6FzOWYg9k0pAJFJ7m7pB10tTPlROyehQQ5eW86DEGaddGP0wEkUHDQkzjHJ5+x8q9mWOSxjhk0Ni2/9iXQD6BNs+fIRIJMxI4HIQrrqFfI4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517201; c=relaxed/simple; bh=aWAW7g/mQGr0Q+uXJPTbfh+7RhKJVYrZ0lZYXDFX3FE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hFte4qhfz2m7isHso4TIjwSmTMzFkgBMaPQu2fDIWcQj0ZgSq67WPIsvp1GGS16pwcI13/TbLsbKANBVnSwdubpB9sihjPLgVKC52YoWTafwwFIsSFtWtBxz1qIeLUZmi9B+EsTSwgqmKxnRXbXR4HRXMsMtEsGpmkW0yk1aSE4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=SnGSwbC6; arc=none smtp.client-ip=60.244.123.138 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="SnGSwbC6" X-UUID: 09c8ca1abe8111ee9e680517dc993faa-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=dAJ+F6oRSY6L+f2GMbS+4z3gw8hdhuCJ6CkYP9HGraU=; b=SnGSwbC6mKJUHF+mbaxwCQMMX806Kl6oK1NAfKK8uLf8/OtNEVSP56h27Zz9sZ/8R9ssJ5b5ZwIPidRAdGciKBgFAnwAQ9ph0+/FW3HzcGY0vdkEVgioF1sFGDeqMpuY3co4o+mDtBvDNk6iSV0F5ri9IcVLCvE6RxJCge1KS6c=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:7431edfc-a07a-426f-87df-1e85aeaf583a, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:2845de7f-4f93-4875-95e7-8c66ea833d57, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0,NGT X-CID-BAS: 0,NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: 09c8ca1abe8111ee9e680517dc993faa-20240129 Received: from mtkmbs13n2.mediatek.inc [(172.21.101.108)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 343817375; Mon, 29 Jan 2024 16:33:11 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by MTKMBS14N1.mediatek.inc (172.21.101.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:08 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:08 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , "Willix Yeh" , Kevenny Hsieh Subject: [PATCH v9 14/21] virt: geniezone: Add dtb config support Date: Mon, 29 Jan 2024 16:32:55 +0800 Message-ID: <20240129083302.26044-15-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-AS-Result: No-10--4.581200-8.000000 X-TMASE-MatchedRID: Ei0WBMmFdJhWj3HFS14pK3a57ruHAnHxf2g6KJZtxl1GL0g1nVmkYXB4 4IkzjfYy2hTOUzxi3QgS2fXvRIxFxjeE3zHLyrsy4pdq9sdj8LUpWss5kPUFdEuCjz4ggdtwiVt eKAOd9rjEfLh+b9VM4YAy6p60ZV62fJ5/bZ6npdjKayT/BQTiGvoYGtXkdu6SxX66abES0VbmFP ZczcrbaV9WXuLhSrPlKMHr5zzFy1jRmftpqdCETxWlqYs52zrhPAgtDxnHoPisMABqiZXzYRNRn hB8RTFvdATQdtPksR+3/JiWOe6GXXSWgQ2GpXdZbxffl9hhCBw= X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--4.581200-8.000000 X-TMASE-Version: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-SNTS-SMTP: 3C96B7BEC1847B5F47604C6917AC0E9D7482860BF47E1DACAB00F2BFBB0ED7A22000:8 X-MTK: N From: "Jerry Wang" Hypervisor might need to know the accurate address and size of dtb passed from userspace. And then hypervisor would parse the dtb and get vm information. Signed-off-by: Jerry Wang Signed-off-by: Liju-clr Chen Signed-off-by: Yi-De Wu --- arch/arm64/geniezone/gzvm_arch_common.h | 2 ++ arch/arm64/geniezone/vm.c | 9 +++++++++ drivers/virt/geniezone/gzvm_vm.c | 10 ++++++++++ include/linux/gzvm_drv.h | 1 + include/uapi/linux/gzvm.h | 14 ++++++++++++++ 5 files changed, 36 insertions(+) diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h index 8d1406beeaed..afb91713fc45 100644 --- a/arch/arm64/geniezone/gzvm_arch_common.h +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -23,6 +23,7 @@ enum { GZVM_FUNC_ENABLE_CAP = 13, GZVM_FUNC_INFORM_EXIT = 14, GZVM_FUNC_MEMREGION_PURPOSE = 15, + GZVM_FUNC_SET_DTB_CONFIG = 16, NR_GZVM_FUNC, }; @@ -46,6 +47,7 @@ enum { #define MT_HVC_GZVM_ENABLE_CAP GZVM_HCALL_ID(GZVM_FUNC_ENABLE_CAP) #define MT_HVC_GZVM_INFORM_EXIT GZVM_HCALL_ID(GZVM_FUNC_INFORM_EXIT) #define MT_HVC_GZVM_MEMREGION_PURPOSE GZVM_HCALL_ID(GZVM_FUNC_MEMREGION_PURPOSE) +#define MT_HVC_GZVM_SET_DTB_CONFIG GZVM_HCALL_ID(GZVM_FUNC_SET_DTB_CONFIG) #define GIC_V3_NR_LRS 16 diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c index 735a599f7da7..41ad1692dd18 100644 --- a/arch/arm64/geniezone/vm.c +++ b/arch/arm64/geniezone/vm.c @@ -140,6 +140,15 @@ int gzvm_arch_memregion_purpose(struct gzvm *gzvm, mem->flags, 0, 0, 0, &res); } +int gzvm_arch_set_dtb_config(struct gzvm *gzvm, struct gzvm_dtb_config *cfg) +{ + struct arm_smccc_res res; + + return gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_DTB_CONFIG, gzvm->vm_id, + cfg->dtb_addr, cfg->dtb_size, 0, 0, 0, 0, + &res); +} + static int gzvm_vm_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap, struct arm_smccc_res *res) diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c index 4134605cbf7d..538549ef405c 100644 --- a/drivers/virt/geniezone/gzvm_vm.c +++ b/drivers/virt/geniezone/gzvm_vm.c @@ -250,6 +250,16 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl, ret = gzvm_vm_ioctl_enable_cap(gzvm, &cap, argp); break; } + case GZVM_SET_DTB_CONFIG: { + struct gzvm_dtb_config cfg; + + if (copy_from_user(&cfg, argp, sizeof(cfg))) { + ret = -EFAULT; + goto out; + } + ret = gzvm_arch_set_dtb_config(gzvm, &cfg); + break; + } default: ret = -ENOTTY; } diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h index 6e081288d41e..aacedb9c74ca 100644 --- a/include/linux/gzvm_drv.h +++ b/include/linux/gzvm_drv.h @@ -156,6 +156,7 @@ void gzvm_vm_irqfd_release(struct gzvm *gzvm); int gzvm_arch_memregion_purpose(struct gzvm *gzvm, struct gzvm_userspace_memory_region *mem); +int gzvm_arch_set_dtb_config(struct gzvm *gzvm, struct gzvm_dtb_config *args); int gzvm_init_ioeventfd(struct gzvm *gzvm); int gzvm_ioeventfd(struct gzvm *gzvm, struct gzvm_ioeventfd *args); diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h index 7c4c95e7e574..09b1457f1270 100644 --- a/include/uapi/linux/gzvm.h +++ b/include/uapi/linux/gzvm.h @@ -359,4 +359,18 @@ struct gzvm_ioeventfd { #define GZVM_IOEVENTFD _IOW(GZVM_IOC_MAGIC, 0x79, struct gzvm_ioeventfd) +/** + * struct gzvm_dtb_config: store address and size of dtb passed from userspace + * + * @dtb_addr: dtb address set by VMM (guset memory) + * @dtb_size: dtb size + */ +struct gzvm_dtb_config { + __u64 dtb_addr; + __u64 dtb_size; +}; + +#define GZVM_SET_DTB_CONFIG _IOW(GZVM_IOC_MAGIC, 0xff, \ + struct gzvm_dtb_config) + #endif /* __GZVM_H__ */ From patchwork Mon Jan 29 08:32:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767744 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9444055E44; Mon, 29 Jan 2024 08:33:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.61.82.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517200; cv=none; b=kJ/jyRiFt97BkJdlX8DN2w+hBgbC2utAz1S7Cg1h7U7JklgHSMSrpXXbd0nNFb/2KWPGBzpkgwH5p3s13ETBqvP4eCkZwKMDU4CqFTIV7UAcfuZLj6CNkTmTTw9SA1mXX/yfnGt57qYEPjH2LAtuUoGaPjYB8C1FklPi0in6pHE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517200; c=relaxed/simple; bh=LIIFKHUwZr30x3CKXC93mBw9Fbu5evh1vdN5BWZeogU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ISmIYHZa0cvSDiD82HmMTStGY1n0Sdro6r37Q0LCIHOeJuTYcvNtN/Y0JQ69Gf2r7voKdWl+/njCJkfjwDsK8kEHIZSae8ccQVuC1m6l9R6+7ltKOYLniXAo9NXNyeWCydMckyzbaRKrPbVX4uMgvxJJ8hdF165cNK7CtkBBHKg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=DtajdotY; arc=none smtp.client-ip=210.61.82.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="DtajdotY" X-UUID: 087936ccbe8111eea2298b7352fd921d-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=vJ6SnD9MWpz/gLXXEictIBaqCdlg7dI3la2NXwfkwhU=; b=DtajdotYy9MZNQSYqr/AGypdFEbxzk/CxkjgV3ByozB7y2+AMjnNJMDVZNvBRcMe4lcLnscHI+oo3W+7NlWJJnvZYExerRfViyDFveyTTxYuaokYN2JrduI88KBFGvVZQcLKmyyZh3kWed+Jffc/3g3Jtl6fgSf5TZvUjbqWvT4=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:eba8fa69-8709-4f76-913b-a60749e96fda, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:b8185e83-8d4f-477b-89d2-1e3bdbef96d1, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: 087936ccbe8111eea2298b7352fd921d-20240129 Received: from mtkmbs10n1.mediatek.inc [(172.21.101.34)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1330966115; Mon, 29 Jan 2024 16:33:09 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:08 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:08 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , "Willix Yeh" , Kevenny Hsieh Subject: [PATCH v9 15/21] virt: geniezone: Add demand paging support Date: Mon, 29 Jan 2024 16:32:56 +0800 Message-ID: <20240129083302.26044-16-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-AS-Result: No-10--17.768100-8.000000 X-TMASE-MatchedRID: oTdiyqBUbz/fN9bhMNhpTUhwlOfYeSqxtDSfcMR+7ZOl4EP+dy+wBFme FuNCwtl4vfKrrb4bmIr2in0s6cYY8X45uBZmw209Bg/PsQ7Io2FAq6/y5AEOOlcZNuxCoduSwdk C9Ck+1Y6L1LF6ImdQDhd62hU8T8MrhQAimBygnyKEryjhqiyzyitovaaHxlUr70m3PKqB7tGKW8 BvXyLiE7NGh1y6CuUYYICOfGVBJhkGtTV246rrNLcPsR57JkIzCt59Uh3p/NVnerzbhugqsqmw5 s23nMRbW+5AYAhakwh8T/TWUlMbt9KK1Pn5CI9QdXu122+iJtq2McZY43zJ423D6f6IpbLISGGK QPXm3qarQS40bMqMVoJl/jaG2IOvH3WbO3ydfMICg1rav4R3DY4lnIgC6UzTQQ1XgvCe7sF1j44 ZYEw/4TbBFkyI1h9E8LlyAg2vp/phfSDU2do4zDTk6JGbrQhuc3ewuwbSaG7FpA1uJFd1mmjd66 WKC/o1q/mwkeU+RjGG184Y5LIraR8TzIzimOwPC24oEZ6SpSk6XEE7Yhw4FpRMZUCEHkRt X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--17.768100-8.000000 X-TMASE-Version: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-SNTS-SMTP: 7E0E6069382AFDA3521653DFCF99F7BB5D4D28421E2AF609D4AA5BB967BA201F2000:8 X-MTK: N From: "Yingshiuan Pan" This page fault handler helps GenieZone hypervisor to do demand paging. On a lower level translation fault, GenieZone hypervisor will first check the fault GPA (guest physical address or IPA in ARM) is valid e.g. within the registered memory region, then it will setup the vcpu_run->exit_reason with necessary information for returning to gzvm driver. With the fault information, the gzvm driver looks up the physical address and call the MT_HVC_GZVM_MAP_GUEST to request the hypervisor maps the found PA to the fault GPA (IPA). There is one exception, for protected vm, we will populate full VM's memory region in advance in order to improve performance. Signed-off-by: Yingshiuan Pan Signed-off-by: Jerry Wang Signed-off-by: kevenny hsieh Signed-off-by: Liju Chen Signed-off-by: Yi-De Wu --- arch/arm64/geniezone/gzvm_arch_common.h | 2 ++ arch/arm64/geniezone/vm.c | 9 ++++++ drivers/virt/geniezone/Makefile | 4 +-- drivers/virt/geniezone/gzvm_exception.c | 39 +++++++++++++++++++++++++ drivers/virt/geniezone/gzvm_main.c | 2 ++ drivers/virt/geniezone/gzvm_mmu.c | 38 ++++++++++++++++++++++++ drivers/virt/geniezone/gzvm_vcpu.c | 6 ++-- drivers/virt/geniezone/gzvm_vm.c | 25 ++++++++++++++++ include/linux/gzvm_drv.h | 7 +++++ include/uapi/linux/gzvm.h | 12 ++++++++ 10 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 drivers/virt/geniezone/gzvm_exception.c diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h index afb91713fc45..1f0c7a3fede8 100644 --- a/arch/arm64/geniezone/gzvm_arch_common.h +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -24,6 +24,7 @@ enum { GZVM_FUNC_INFORM_EXIT = 14, GZVM_FUNC_MEMREGION_PURPOSE = 15, GZVM_FUNC_SET_DTB_CONFIG = 16, + GZVM_FUNC_MAP_GUEST = 17, NR_GZVM_FUNC, }; @@ -48,6 +49,7 @@ enum { #define MT_HVC_GZVM_INFORM_EXIT GZVM_HCALL_ID(GZVM_FUNC_INFORM_EXIT) #define MT_HVC_GZVM_MEMREGION_PURPOSE GZVM_HCALL_ID(GZVM_FUNC_MEMREGION_PURPOSE) #define MT_HVC_GZVM_SET_DTB_CONFIG GZVM_HCALL_ID(GZVM_FUNC_SET_DTB_CONFIG) +#define MT_HVC_GZVM_MAP_GUEST GZVM_HCALL_ID(GZVM_FUNC_MAP_GUEST) #define GIC_V3_NR_LRS 16 diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c index 41ad1692dd18..a7a8a1bb6388 100644 --- a/arch/arm64/geniezone/vm.c +++ b/arch/arm64/geniezone/vm.c @@ -388,3 +388,12 @@ u64 gzvm_hva_to_pa_arch(u64 hva) return GZVM_PA_ERR_BAD; return par; } + +int gzvm_arch_map_guest(u16 vm_id, int memslot_id, u64 pfn, u64 gfn, + u64 nr_pages) +{ + struct arm_smccc_res res; + + return gzvm_hypcall_wrapper(MT_HVC_GZVM_MAP_GUEST, vm_id, memslot_id, + pfn, gfn, nr_pages, 0, 0, &res); +} diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile index 9956f4891df2..2e12870637d5 100644 --- a/drivers/virt/geniezone/Makefile +++ b/drivers/virt/geniezone/Makefile @@ -8,5 +8,5 @@ GZVM_DIR ?= ../../../drivers/virt/geniezone gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o \ $(GZVM_DIR)/gzvm_mmu.o $(GZVM_DIR)/gzvm_vcpu.o \ - $(GZVM_DIR)/gzvm_irqfd.o $(GZVM_DIR)/gzvm_ioeventfd.o - + $(GZVM_DIR)/gzvm_irqfd.o $(GZVM_DIR)/gzvm_ioeventfd.o \ + $(GZVM_DIR)/gzvm_exception.o diff --git a/drivers/virt/geniezone/gzvm_exception.c b/drivers/virt/geniezone/gzvm_exception.c new file mode 100644 index 000000000000..31fdb4ae8db4 --- /dev/null +++ b/drivers/virt/geniezone/gzvm_exception.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + */ + +#include +#include + +/** + * gzvm_handle_guest_exception() - Handle guest exception + * @vcpu: Pointer to struct gzvm_vcpu_run in userspace + * Return: + * * true - This exception has been processed, no need to back to VMM. + * * false - This exception has not been processed, require userspace. + */ +bool gzvm_handle_guest_exception(struct gzvm_vcpu *vcpu) +{ + int ret; + + for (int i = 0; i < ARRAY_SIZE(vcpu->run->exception.reserved); i++) { + if (vcpu->run->exception.reserved[i]) + return -EINVAL; + } + + switch (vcpu->run->exception.exception) { + case GZVM_EXCEPTION_PAGE_FAULT: + ret = gzvm_handle_page_fault(vcpu); + break; + case GZVM_EXCEPTION_UNKNOWN: + fallthrough; + default: + ret = -EFAULT; + } + + if (!ret) + return true; + else + return false; +} diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c index 4e5d1b83df4a..af5ab8949206 100644 --- a/drivers/virt/geniezone/gzvm_main.c +++ b/drivers/virt/geniezone/gzvm_main.c @@ -28,6 +28,8 @@ int gzvm_err_to_errno(unsigned long err) return 0; case ERR_NO_MEMORY: return -ENOMEM; + case ERR_INVALID_ARGS: + return -EINVAL; case ERR_NOT_SUPPORTED: return -EOPNOTSUPP; case ERR_NOT_IMPLEMENTED: diff --git a/drivers/virt/geniezone/gzvm_mmu.c b/drivers/virt/geniezone/gzvm_mmu.c index 3c87eee1321f..cc007944eaa5 100644 --- a/drivers/virt/geniezone/gzvm_mmu.c +++ b/drivers/virt/geniezone/gzvm_mmu.c @@ -114,3 +114,41 @@ int gzvm_vm_allocate_guest_page(struct gzvm_memslot *slot, u64 gfn, u64 *pfn) return 0; } +static int handle_single_demand_page(struct gzvm *vm, int memslot_id, u64 gfn) +{ + int ret; + u64 pfn; + + ret = gzvm_vm_allocate_guest_page(&vm->memslot[memslot_id], gfn, &pfn); + if (unlikely(ret)) + return -EFAULT; + + ret = gzvm_arch_map_guest(vm->vm_id, memslot_id, pfn, gfn, 1); + if (unlikely(ret)) + return -EFAULT; + + return 0; +} + +/** + * gzvm_handle_page_fault() - Handle guest page fault, find corresponding page + * for the faulting gpa + * @vcpu: Pointer to struct gzvm_vcpu_run of the faulting vcpu + * + * Return: + * * 0 - Success to handle guest page fault + * * -EFAULT - Failed to map phys addr to guest's GPA + */ +int gzvm_handle_page_fault(struct gzvm_vcpu *vcpu) +{ + struct gzvm *vm = vcpu->gzvm; + int memslot_id; + u64 gfn; + + gfn = PHYS_PFN(vcpu->run->exception.fault_gpa); + memslot_id = gzvm_find_memslot(vm, gfn); + if (unlikely(memslot_id < 0)) + return -EFAULT; + + return handle_single_demand_page(vm, memslot_id, gfn); +} diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c index 77138e749e9a..455ae2e4285c 100644 --- a/drivers/virt/geniezone/gzvm_vcpu.c +++ b/drivers/virt/geniezone/gzvm_vcpu.c @@ -113,9 +113,11 @@ static long gzvm_vcpu_run(struct gzvm_vcpu *vcpu, void __user *argp) * it's geniezone's responsibility to fill corresponding data * structure */ - case GZVM_EXIT_HYPERCALL: - fallthrough; case GZVM_EXIT_EXCEPTION: + if (!gzvm_handle_guest_exception(vcpu)) + need_userspace = true; + break; + case GZVM_EXIT_HYPERCALL: fallthrough; case GZVM_EXIT_DEBUG: fallthrough; diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c index 538549ef405c..9f7e44521de5 100644 --- a/drivers/virt/geniezone/gzvm_vm.c +++ b/drivers/virt/geniezone/gzvm_vm.c @@ -23,6 +23,31 @@ u64 gzvm_gfn_to_hva_memslot(struct gzvm_memslot *memslot, u64 gfn) return memslot->userspace_addr + offset * PAGE_SIZE; } +/** + * gzvm_find_memslot() - Find memslot containing this @gpa + * @vm: Pointer to struct gzvm + * @gfn: Guest frame number + * + * Return: + * * >=0 - Index of memslot + * * -EFAULT - Not found + */ +int gzvm_find_memslot(struct gzvm *vm, u64 gfn) +{ + int i; + + for (i = 0; i < GZVM_MAX_MEM_REGION; i++) { + if (vm->memslot[i].npages == 0) + continue; + + if (gfn >= vm->memslot[i].base_gfn && + gfn < vm->memslot[i].base_gfn + vm->memslot[i].npages) + return i; + } + + return -EFAULT; +} + /** * register_memslot_addr_range() - Register memory region to GenieZone * @gzvm: Pointer to struct gzvm diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h index aacedb9c74ca..f6e4c5152ee5 100644 --- a/include/linux/gzvm_drv.h +++ b/include/linux/gzvm_drv.h @@ -29,6 +29,7 @@ */ #define NO_ERROR (0) #define ERR_NO_MEMORY (-5) +#define ERR_INVALID_ARGS (-8) #define ERR_NOT_SUPPORTED (-24) #define ERR_NOT_IMPLEMENTED (-27) #define ERR_FAULT (-40) @@ -123,6 +124,8 @@ int gzvm_arch_set_memregion(u16 vm_id, size_t buf_size, int gzvm_arch_check_extension(struct gzvm *gzvm, __u64 cap, void __user *argp); int gzvm_arch_create_vm(unsigned long vm_type); int gzvm_arch_destroy_vm(u16 vm_id); +int gzvm_arch_map_guest(u16 vm_id, int memslot_id, u64 pfn, u64 gfn, + u64 nr_pages); int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap, void __user *argp); @@ -143,6 +146,10 @@ int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason); int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid); int gzvm_arch_inform_exit(u16 vm_id); +int gzvm_find_memslot(struct gzvm *vm, u64 gpa); +int gzvm_handle_page_fault(struct gzvm_vcpu *vcpu); +bool gzvm_handle_guest_exception(struct gzvm_vcpu *vcpu); + int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev); int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq, bool level); diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h index 09b1457f1270..73fd6a81116f 100644 --- a/include/uapi/linux/gzvm.h +++ b/include/uapi/linux/gzvm.h @@ -181,6 +181,12 @@ enum { GZVM_EXIT_GZ = 0x9292000a, }; +/* exception definitions of GZVM_EXIT_EXCEPTION */ +enum { + GZVM_EXCEPTION_UNKNOWN = 0x0, + GZVM_EXCEPTION_PAGE_FAULT = 0x1, +}; + /** * struct gzvm_vcpu_run: Same purpose as kvm_run, this struct is * shared between userspace, kernel and @@ -245,6 +251,12 @@ struct gzvm_vcpu_run { __u32 exception; /* Exception error codes */ __u32 error_code; + /* Fault GPA (guest physical address or IPA in ARM) */ + __u64 fault_gpa; + /* Future-proof reservation and reset to zero in hypervisor. + * Fill up to the union size, 256 bytes. + */ + __u64 reserved[30]; } exception; /* GZVM_EXIT_HYPERCALL */ struct { From patchwork Mon Jan 29 08:32:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767742 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5ECF155C26; Mon, 29 Jan 2024 08:33:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.61.82.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517201; cv=none; b=f/Eq6tF9fMFV1AGzy0o9K6cQwACvGT4dYXMBy+TDD22iWh5hz98G3USHod6K8idWIS5Q/Fo+anUfB95qfJiUKs/him1Vdbh7gCbwZlarFlInMJ6xWuTe0ncqeqbjhnnfTaNybdxDeR/8WTIDy000ALPaNE0Ib4FDE5mSNxHSg0w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517201; c=relaxed/simple; bh=CcoGmMYiLBvOY6qrJp/2XgbQDHY45ay+DF9F7DNr2dE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=vFGBHycREXst0NwlywH8/RhyEZHRAx/L3nCVbOpq6oaEUaOIJhwFmdjzg0kfwnFP1GABbJ1CFKcwrfhyE3kQZEK7jR4WtBeH75TR3Qu5rvQjCFw9Zk1QhWtjwW1h9e3GU0++trurwMXcoDPh1ej7OFtIrZlH1C7kZiaV9YBBZAc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=qoklRVRd; arc=none smtp.client-ip=210.61.82.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="qoklRVRd" X-UUID: 083e3ae0be8111eea2298b7352fd921d-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=amDS1oT+9SSlwW5Ms5N+nrxNfohILdwgW7lfesu4bjM=; b=qoklRVRdh1D7OehMX7KKy2cHTvn9vNdeyYQn2zoCqSoeuN5fjala1IR6DeQKceE/fGjIBPMBH2Teh0bS/4Gbalft77KcZQk+mujGDrpQaPDV5V4RkCaoTpJ/keEnnPGKnGOtAnOoYWtIMPgcaHyJzFffEdYnqf1OJjUaz2yN89Q=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:630dd6f3-9835-4fdb-b3f0-6097fd0e3dc2, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:dd25c58e-e2c0-40b0-a8fe-7c7e47299109, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES:1, SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: 083e3ae0be8111eea2298b7352fd921d-20240129 Received: from mtkmbs13n2.mediatek.inc [(172.21.101.108)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1348807959; Mon, 29 Jan 2024 16:33:09 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs13n1.mediatek.inc (172.21.101.193) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:08 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:08 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , Willix Yeh , Kevenny Hsieh Subject: [PATCH v9 16/21] virt: geniezone: Add block-based demand paging support Date: Mon, 29 Jan 2024 16:32:57 +0800 Message-ID: <20240129083302.26044-17-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MTK: N From: "Yingshiuan Pan" To balance memory usage and performance, GenieZone supports larger granularity demand paging, called block-based demand paging. Gzvm driver uses enable_cap to query the hypervisor if it supports block-based demand paging and the given granularity or not. Meanwhile, the gzvm driver allocates a shared buffer for storing the physical pages later. If the hypervisor supports, every time the gzvm driver handles guest page faults, it allocates more memory in advance (default: 2MB) for demand paging. And fills those physical pages into the allocated shared memory, then calls the hypervisor to map to guest's memory. The physical pages allocated for block-based demand paging is not necessary to be contiguous because in many cases, 2MB block is not followed. 1st, the memory is allocated because of VMM's page fault (VMM loads kernel image to guest memory before running). In this case, the page is allocated by the host kernel and using PAGE_SIZE. 2nd is that guest may return memory to host via ballooning and that is still 4KB (or PAGE_SIZE) granularity. Therefore, we do not have to allocate physically contiguous 2MB pages. Signed-off-by: Yingshiuan Pan Signed-off-by: Liju Chen Signed-off-by: Yi-De Wu --- arch/arm64/geniezone/gzvm_arch_common.h | 2 + arch/arm64/geniezone/vm.c | 19 ++++++++-- drivers/virt/geniezone/gzvm_mmu.c | 43 +++++++++++++++++++++- drivers/virt/geniezone/gzvm_vm.c | 49 +++++++++++++++++++++++++ include/linux/gzvm_drv.h | 16 ++++++++ include/uapi/linux/gzvm.h | 2 + 6 files changed, 127 insertions(+), 4 deletions(-) diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h index 1f0c7a3fede8..07c5e2df7a74 100644 --- a/arch/arm64/geniezone/gzvm_arch_common.h +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -25,6 +25,7 @@ enum { GZVM_FUNC_MEMREGION_PURPOSE = 15, GZVM_FUNC_SET_DTB_CONFIG = 16, GZVM_FUNC_MAP_GUEST = 17, + GZVM_FUNC_MAP_GUEST_BLOCK = 18, NR_GZVM_FUNC, }; @@ -50,6 +51,7 @@ enum { #define MT_HVC_GZVM_MEMREGION_PURPOSE GZVM_HCALL_ID(GZVM_FUNC_MEMREGION_PURPOSE) #define MT_HVC_GZVM_SET_DTB_CONFIG GZVM_HCALL_ID(GZVM_FUNC_SET_DTB_CONFIG) #define MT_HVC_GZVM_MAP_GUEST GZVM_HCALL_ID(GZVM_FUNC_MAP_GUEST) +#define MT_HVC_GZVM_MAP_GUEST_BLOCK GZVM_HCALL_ID(GZVM_FUNC_MAP_GUEST_BLOCK) #define GIC_V3_NR_LRS 16 diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c index a7a8a1bb6388..1841e3aed363 100644 --- a/arch/arm64/geniezone/vm.c +++ b/arch/arm64/geniezone/vm.c @@ -331,10 +331,11 @@ static int gzvm_vm_ioctl_cap_pvm(struct gzvm *gzvm, fallthrough; case GZVM_CAP_PVM_SET_PROTECTED_VM: /* - * To improve performance for protected VM, we have to populate VM's memory - * before VM booting + * If the hypervisor doesn't support block-based demand paging, we + * populate memory in advance to improve performance for protected VM. */ - populate_all_mem_regions(gzvm); + if (gzvm->demand_page_gran == PAGE_SIZE) + populate_all_mem_regions(gzvm); ret = gzvm_vm_arch_enable_cap(gzvm, cap, &res); return ret; case GZVM_CAP_PVM_GET_PVMFW_SIZE: @@ -351,12 +352,16 @@ int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap, void __user *argp) { + struct arm_smccc_res res = {0}; int ret; switch (cap->cap) { case GZVM_CAP_PROTECTED_VM: ret = gzvm_vm_ioctl_cap_pvm(gzvm, cap, argp); return ret; + case GZVM_CAP_BLOCK_BASED_DEMAND_PAGING: + ret = gzvm_vm_arch_enable_cap(gzvm, cap, &res); + return ret; default: break; } @@ -397,3 +402,11 @@ int gzvm_arch_map_guest(u16 vm_id, int memslot_id, u64 pfn, u64 gfn, return gzvm_hypcall_wrapper(MT_HVC_GZVM_MAP_GUEST, vm_id, memslot_id, pfn, gfn, nr_pages, 0, 0, &res); } + +int gzvm_arch_map_guest_block(u16 vm_id, int memslot_id, u64 gfn, u64 nr_pages) +{ + struct arm_smccc_res res; + + return gzvm_hypcall_wrapper(MT_HVC_GZVM_MAP_GUEST_BLOCK, vm_id, + memslot_id, gfn, nr_pages, 0, 0, 0, &res); +} diff --git a/drivers/virt/geniezone/gzvm_mmu.c b/drivers/virt/geniezone/gzvm_mmu.c index cc007944eaa5..98d296ff9c90 100644 --- a/drivers/virt/geniezone/gzvm_mmu.c +++ b/drivers/virt/geniezone/gzvm_mmu.c @@ -114,6 +114,44 @@ int gzvm_vm_allocate_guest_page(struct gzvm_memslot *slot, u64 gfn, u64 *pfn) return 0; } +static int handle_block_demand_page(struct gzvm *vm, int memslot_id, u64 gfn) +{ + u64 pfn, __gfn; + int ret, i; + + u32 nr_entries = GZVM_BLOCK_BASED_DEMAND_PAGE_SIZE / PAGE_SIZE; + struct gzvm_memslot *memslot = &vm->memslot[memslot_id]; + u64 start_gfn = ALIGN_DOWN(gfn, nr_entries); + u32 total_pages = memslot->npages; + u64 base_gfn = memslot->base_gfn; + + /* if the demand region is less than a block, adjust the nr_entries */ + if (start_gfn + nr_entries > base_gfn + total_pages) + nr_entries = base_gfn + total_pages - start_gfn; + + mutex_lock(&vm->demand_paging_lock); + for (i = 0, __gfn = start_gfn; i < nr_entries; i++, __gfn++) { + ret = gzvm_vm_allocate_guest_page(memslot, __gfn, &pfn); + if (unlikely(ret)) { + ret = -ERR_FAULT; + goto err_unlock; + } + vm->demand_page_buffer[i] = pfn; + } + + ret = gzvm_arch_map_guest_block(vm->vm_id, memslot_id, start_gfn, + nr_entries); + if (unlikely(ret)) { + ret = -EFAULT; + goto err_unlock; + } + +err_unlock: + mutex_unlock(&vm->demand_paging_lock); + + return ret; +} + static int handle_single_demand_page(struct gzvm *vm, int memslot_id, u64 gfn) { int ret; @@ -150,5 +188,8 @@ int gzvm_handle_page_fault(struct gzvm_vcpu *vcpu) if (unlikely(memslot_id < 0)) return -EFAULT; - return handle_single_demand_page(vm, memslot_id, gfn); + if (vm->demand_page_gran == PAGE_SIZE) + return handle_single_demand_page(vm, memslot_id, gfn); + else + return handle_block_demand_page(vm, memslot_id, gfn); } diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c index 9f7e44521de5..485d1e2097aa 100644 --- a/drivers/virt/geniezone/gzvm_vm.c +++ b/drivers/virt/geniezone/gzvm_vm.c @@ -294,6 +294,8 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl, static void gzvm_destroy_vm(struct gzvm *gzvm) { + size_t allocated_size; + pr_debug("VM-%u is going to be destroyed\n", gzvm->vm_id); mutex_lock(&gzvm->lock); @@ -306,6 +308,11 @@ static void gzvm_destroy_vm(struct gzvm *gzvm) list_del(&gzvm->vm_list); mutex_unlock(&gzvm_list_lock); + if (gzvm->demand_page_buffer) { + allocated_size = GZVM_BLOCK_BASED_DEMAND_PAGE_SIZE / PAGE_SIZE * sizeof(u64); + free_pages_exact(gzvm->demand_page_buffer, allocated_size); + } + mutex_unlock(&gzvm->lock); kfree(gzvm); @@ -325,6 +332,46 @@ static const struct file_operations gzvm_vm_fops = { .llseek = noop_llseek, }; +/** + * setup_vm_demand_paging - Query hypervisor suitable demand page size and set + * @vm: gzvm instance for setting up demand page size + * + * Return: void + */ +static void setup_vm_demand_paging(struct gzvm *vm) +{ + u32 buf_size = GZVM_BLOCK_BASED_DEMAND_PAGE_SIZE / PAGE_SIZE * sizeof(u64); + struct gzvm_enable_cap cap = {0}; + void *buffer; + int ret; + + mutex_init(&vm->demand_paging_lock); + buffer = alloc_pages_exact(buf_size, GFP_KERNEL); + if (!buffer) { + /* Fall back to use default page size for demand paging */ + vm->demand_page_gran = PAGE_SIZE; + vm->demand_page_buffer = NULL; + return; + } + + cap.cap = GZVM_CAP_BLOCK_BASED_DEMAND_PAGING; + cap.args[0] = GZVM_BLOCK_BASED_DEMAND_PAGE_SIZE; + cap.args[1] = (__u64)virt_to_phys(buffer); + /* demand_page_buffer is freed when destroy VM */ + vm->demand_page_buffer = buffer; + + ret = gzvm_vm_ioctl_enable_cap(vm, &cap, NULL); + if (ret == 0) { + vm->demand_page_gran = GZVM_BLOCK_BASED_DEMAND_PAGE_SIZE; + /* freed when destroy vm */ + vm->demand_page_buffer = buffer; + } else { + vm->demand_page_gran = PAGE_SIZE; + vm->demand_page_buffer = NULL; + free_pages_exact(buffer, buf_size); + } +} + static struct gzvm *gzvm_create_vm(unsigned long vm_type) { int ret; @@ -358,6 +405,8 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type) return ERR_PTR(ret); } + setup_vm_demand_paging(gzvm); + mutex_lock(&gzvm_list_lock); list_add(&gzvm->vm_list, &gzvm_list); mutex_unlock(&gzvm_list_lock); diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h index f6e4c5152ee5..b537f71465e7 100644 --- a/include/linux/gzvm_drv.h +++ b/include/linux/gzvm_drv.h @@ -44,6 +44,8 @@ #define GZVM_VCPU_RUN_MAP_SIZE (PAGE_SIZE * 2) +#define GZVM_BLOCK_BASED_DEMAND_PAGE_SIZE (2 * 1024 * 1024) /* 2MB */ + /* struct mem_region_addr_range - Identical to ffa memory constituent */ struct mem_region_addr_range { /* the base IPA of the constituent memory region, aligned to 4 kiB */ @@ -106,6 +108,19 @@ struct gzvm { struct srcu_struct irq_srcu; /* lock for irq injection */ struct mutex irq_lock; + + /* + * demand page granularity: how much memory we allocate for VM in a + * single page fault + */ + u32 demand_page_gran; + /* the mailbox for transferring large portion pages */ + u64 *demand_page_buffer; + /* + * lock for preventing multiple cpu using the same demand page mailbox + * at the same time + */ + struct mutex demand_paging_lock; }; long gzvm_dev_ioctl_check_extension(struct gzvm *gzvm, unsigned long args); @@ -126,6 +141,7 @@ int gzvm_arch_create_vm(unsigned long vm_type); int gzvm_arch_destroy_vm(u16 vm_id); int gzvm_arch_map_guest(u16 vm_id, int memslot_id, u64 pfn, u64 gfn, u64 nr_pages); +int gzvm_arch_map_guest_block(u16 vm_id, int memslot_id, u64 gfn, u64 nr_pages); int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap, void __user *argp); diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h index 73fd6a81116f..ce4c80bf254c 100644 --- a/include/uapi/linux/gzvm.h +++ b/include/uapi/linux/gzvm.h @@ -18,6 +18,8 @@ #define GZVM_CAP_VM_GPA_SIZE 0xa5 #define GZVM_CAP_PROTECTED_VM 0xffbadab1 +/* query hypervisor supported block-based demand page */ +#define GZVM_CAP_BLOCK_BASED_DEMAND_PAGING 0x9201 /* sub-commands put in args[0] for GZVM_CAP_PROTECTED_VM */ #define GZVM_CAP_PVM_SET_PVMFW_GPA 0 From patchwork Mon Jan 29 08:33:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-De Wu X-Patchwork-Id: 767740 Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 890AA57865; Mon, 29 Jan 2024 08:33:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.244.123.138 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517203; cv=none; b=NnoTunLOcxje/3fkPnJ6m+0benDL8k4aqOWdkTeWdCNP59U3E7iT+64xRop7+1GUKB0vKN6Mywkke6VR9v82DNTn/TrXBjfMhsR1fYkvGKnt+QWS7YOmZXyQG2vxBE98juhl0z86VGvT9wVK/NV+h9/tWs+ahWtUHtH0anKRs4E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706517203; c=relaxed/simple; bh=0OLRga1LcfHeQkjMoJOa+JV0bOzhYh3zwLeCH8fUSsE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YjCS5LUgwA6AzxiigSIv4AXAS4dgEjbEeozYbDqE/fDyQ/OaQqcEh3Fyj8akwHKoMsDiTxUiBk+WpBtaxuyfVVhhL+t+eyRdEyat3PomEeOPo/o3MwPK2m6dC25hsMZhu/LTEof6wVSvCTXpyHAlrrtyAQE2jAqfMFwtfACtUsQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com; spf=pass smtp.mailfrom=mediatek.com; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b=hJRq9Zt9; arc=none smtp.client-ip=60.244.123.138 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mediatek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mediatek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="hJRq9Zt9" X-UUID: 09257914be8111ee9e680517dc993faa-20240129 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=4aFHlKO68gkpQ2H5DEC8ScmJLpJQbxtvVULWLax4NcE=; b=hJRq9Zt9DKIWEjhwVt+oFt2PxzqrlLUWbhc9nweeP5+x5B58DFO6284fAC6G65DPjIFhJBlaYVkL3cQ7X8gKiCPOotAQfxddbCwL6vVeN9N8VdUJqq85nzhrkQwZZohOtizvcUpovEUJiiw02slJYjUki/evcggLWZ3lxmndU3s=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.36, REQID:0fa141f8-c87f-4633-a718-92c1152ef138, IP:0, U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6e16cf4, CLOUDID:c2185e83-8d4f-477b-89d2-1e3bdbef96d1, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES:1, SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0,NGT X-CID-BAS: 0,NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: 09257914be8111ee9e680517dc993faa-20240129 Received: from mtkmbs13n2.mediatek.inc [(172.21.101.108)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1672033661; Mon, 29 Jan 2024 16:33:10 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Mon, 29 Jan 2024 16:33:09 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Mon, 29 Jan 2024 16:33:09 +0800 From: Yi-De Wu To: Yingshiuan Pan , Ze-Yu Wang , Yi-De Wu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Catalin Marinas , Will Deacon , Richard Cochran , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , David Bradil , Trilok Soni , My Chuang , Shawn Hsiao , PeiLun Suei , Liju Chen , "Willix Yeh" , Kevenny Hsieh Subject: [PATCH v9 21/21] virt: geniezone: Enable PTP for synchronizing time between host and guest VMs Date: Mon, 29 Jan 2024 16:33:02 +0800 Message-ID: <20240129083302.26044-22-yi-de.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com> References: <20240129083302.26044-1-yi-de.wu@mediatek.com> Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-AS-Result: No-10--10.205400-8.000000 X-TMASE-MatchedRID: y128Pza/oi5PB4rXagQZ+5LPLrFS265P4Ob1SHQRSIgNqAa+u3rIYNwB sjzU/tkx4ZQqYHZtqxhYo3G+rvxrNao77AcuQhw7A9lly13c/gHt/okBLaEo+BjO8pfx4H7gcam vz988laISXSK8uF+jaPAL7Jj8ilE4LZbtj42l31G4jAucHcCqnZYcYQ11P5U/xKLCLOyCW5B25K XQ4QIGJr1A4/e8Np0k4I4a/QXu4NCR8u6DOJbzp8nUT+eskUQP7h2RrsKOiu0+gR+s21UkWIEpJ RcbelqdADXE8V3mpEVDNcDXkV4d67bfdDP+zORmdXz3l78F3YmkWoMjFfK3Xpsoi2XrUn/Jn6Kd MrRsL14qtq5d3cxkNZd/mwLf2BVU/u97Tz1Q+0kDBDLbZrqaEgJOsKQTld6amsvvnoS3ZploBmT SwRxjXg== X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--10.205400-8.000000 X-TMASE-Version: SMEX-14.0.0.3152-9.1.1006-23728.005 X-TM-SNTS-SMTP: A9B58409E70E1E727DD1BE319D4B6D809EFF4DB11FC966FF0DF0FAA8F2E88A3C2000:8 X-MTK: N From: "Kevenny Hsieh" Enabled Precision Time Protocol (PTP) for improved host-guest VM time synchronization, optimizing operations needing precise clock sync in virtual environment. Signed-off-by: Kevenny Hsieh Signed-off-by: Liju Chen Signed-off-by: Yi-De Wu --- arch/arm64/geniezone/Makefile | 2 +- arch/arm64/geniezone/gzvm_arch_common.h | 3 + arch/arm64/geniezone/hvc.c | 73 +++++++++++++++++++++++++ drivers/virt/geniezone/gzvm_exception.c | 3 +- include/linux/gzvm_drv.h | 1 + include/uapi/linux/gzvm.h | 1 + 6 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 arch/arm64/geniezone/hvc.c diff --git a/arch/arm64/geniezone/Makefile b/arch/arm64/geniezone/Makefile index 0e4f1087f9de..553a64a926dc 100644 --- a/arch/arm64/geniezone/Makefile +++ b/arch/arm64/geniezone/Makefile @@ -4,6 +4,6 @@ # include $(srctree)/drivers/virt/geniezone/Makefile -gzvm-y += vm.o vcpu.o vgic.o +gzvm-y += vm.o vcpu.o vgic.o hvc.o obj-$(CONFIG_MTK_GZVM) += gzvm.o diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h index fbaf2da792a4..e697223f0fd6 100644 --- a/arch/arm64/geniezone/gzvm_arch_common.h +++ b/arch/arm64/geniezone/gzvm_arch_common.h @@ -93,6 +93,8 @@ static inline u16 get_vcpuid_from_tuple(unsigned int tuple) * @__pad: add an explicit '__u32 __pad;' in the middle to make it clear * what the actual layout is. * @lr: The array of LRs(list registers). + * @vtimer_offset: The offset maintained by hypervisor that is host cycle count + * when guest VM startup. * * - Keep the same layout of hypervisor data struct. * - Sync list registers back for acking virtual device interrupt status. @@ -101,6 +103,7 @@ struct gzvm_vcpu_hwstate { __le32 nr_lrs; __le32 __pad; __le64 lr[GIC_V3_NR_LRS]; + __le64 vtimer_offset; }; static inline unsigned int diff --git a/arch/arm64/geniezone/hvc.c b/arch/arm64/geniezone/hvc.c new file mode 100644 index 000000000000..603db0fad3d8 --- /dev/null +++ b/arch/arm64/geniezone/hvc.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + */ +#include +#include +#include +#include +#include "gzvm_arch_common.h" + +#define GZVM_PTP_VIRT_COUNTER 0 +#define GZVM_PTP_PHYS_COUNTER 1 +/** + * gzvm_handle_ptp_time() - Sync time between host and guest VM + * @vcpu: Pointer to struct gzvm_vcpu_run in userspace + * @counter: Counter type from guest VM + * Return: Always return 0 because there are no cases of failure + * + * The following register values will be passed to the guest VM + * for time synchronization: + * regs->x0 (upper 32 bits) wall clock time + * regs->x1 (lower 32 bits) wall clock time + * regs->x2 (upper 32 bits) cycles + * regs->x3 (lower 32 bits) cycles + */ +static int gzvm_handle_ptp_time(struct gzvm_vcpu *vcpu, int counter) +{ + struct system_time_snapshot snapshot; + u64 cycles = 0; + + ktime_get_snapshot(&snapshot); + + switch (counter) { + case GZVM_PTP_VIRT_COUNTER: + cycles = snapshot.cycles - + le64_to_cpu(vcpu->hwstate->vtimer_offset); + break; + case GZVM_PTP_PHYS_COUNTER: + cycles = snapshot.cycles; + break; + default: + break; + } + + vcpu->run->hypercall.args[0] = upper_32_bits(snapshot.real); + vcpu->run->hypercall.args[1] = lower_32_bits(snapshot.real); + vcpu->run->hypercall.args[2] = upper_32_bits(cycles); + vcpu->run->hypercall.args[3] = lower_32_bits(cycles); + + return 0; +} + +/** + * gzvm_arch_handle_guest_hvc() - Handle architecture-related guest hvc + * @vcpu: Pointer to struct gzvm_vcpu_run in userspace + * Return: + * * true - This hvc has been processed, no need to back to VMM. + * * false - This hvc has not been processed, require userspace. + */ +bool gzvm_arch_handle_guest_hvc(struct gzvm_vcpu *vcpu) +{ + int ret, counter; + + switch (vcpu->run->hypercall.args[0]) { + case GZVM_HVC_PTP: + counter = vcpu->run->hypercall.args[1]; + ret = gzvm_handle_ptp_time(vcpu, counter); + return (ret == 0) ? true : false; + default: + break; + } + return false; +} diff --git a/drivers/virt/geniezone/gzvm_exception.c b/drivers/virt/geniezone/gzvm_exception.c index af26d1c82791..e6209b3b3a3e 100644 --- a/drivers/virt/geniezone/gzvm_exception.c +++ b/drivers/virt/geniezone/gzvm_exception.c @@ -56,7 +56,6 @@ bool gzvm_handle_guest_hvc(struct gzvm_vcpu *vcpu) ret = gzvm_handle_relinquish(vcpu, ipa); return (ret == 0) ? true : false; default: - break; + return gzvm_arch_handle_guest_hvc(vcpu); } - return false; } diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h index d532d2d31d43..ca8adf403d48 100644 --- a/include/linux/gzvm_drv.h +++ b/include/linux/gzvm_drv.h @@ -195,6 +195,7 @@ int gzvm_handle_page_fault(struct gzvm_vcpu *vcpu); bool gzvm_handle_guest_exception(struct gzvm_vcpu *vcpu); int gzvm_handle_relinquish(struct gzvm_vcpu *vcpu, phys_addr_t ipa); bool gzvm_handle_guest_hvc(struct gzvm_vcpu *vcpu); +bool gzvm_arch_handle_guest_hvc(struct gzvm_vcpu *vcpu); int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev); int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h index 205fcf7cdfa7..681917357ed0 100644 --- a/include/uapi/linux/gzvm.h +++ b/include/uapi/linux/gzvm.h @@ -191,6 +191,7 @@ enum { /* hypercall definitions of GZVM_EXIT_HYPERCALL */ enum { + GZVM_HVC_PTP = 0x86000001, GZVM_HVC_MEM_RELINQUISH = 0xc6000009, };