All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/7] GenieZone hypervisor drivers
@ 2023-04-28 10:36 ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

This series is based on linux-next, tag: next-20230427.

Changes in v2:
- Refactor: move to drivers/virt/geniezone
- Refactor: decouple arch-dependent and arch-independent
- Check pending signal before entering guest context
- Fix reviewer's comments

Yi-De Wu (7):
  docs: geniezone: Introduce GenieZone hypervisor
  dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  virt: geniezone: Introduce GenieZone hypervisor support
  virt: geniezone: Add vcpu support
  virt: geniezone: Add irqchip support for virtual interrupt injection
  virt: geniezone: Add irqfd support
  virt: geniezone: Add ioeventfd support

 .../hypervisor/mediatek,geniezone-hyp.yaml    |  31 +
 Documentation/virt/geniezone/introduction.rst |  34 ++
 MAINTAINERS                                   |  13 +
 arch/arm64/Kbuild                             |   1 +
 arch/arm64/geniezone/Makefile                 |   9 +
 arch/arm64/geniezone/gzvm_arch.c              | 280 +++++++++
 arch/arm64/geniezone/gzvm_arch.h              |  92 +++
 arch/arm64/geniezone/gzvm_irqchip.c           | 108 ++++
 arch/arm64/include/uapi/asm/gzvm_arch.h       |  47 ++
 drivers/virt/Kconfig                          |   2 +
 drivers/virt/geniezone/Kconfig                |  17 +
 drivers/virt/geniezone/Makefile               |  12 +
 drivers/virt/geniezone/gzvm_ioeventfd.c       | 263 +++++++++
 drivers/virt/geniezone/gzvm_irqfd.c           | 536 ++++++++++++++++++
 drivers/virt/geniezone/gzvm_main.c            | 151 +++++
 drivers/virt/geniezone/gzvm_vcpu.c            | 260 +++++++++
 drivers/virt/geniezone/gzvm_vm.c              | 447 +++++++++++++++
 include/linux/gzvm_drv.h                      | 154 +++++
 include/uapi/asm-generic/gzvm_arch.h          |  10 +
 include/uapi/linux/gzvm.h                     | 274 +++++++++
 20 files changed, 2741 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hypervisor/mediatek,
 geniezone-hyp.yaml
 create mode 100644 Documentation/virt/geniezone/introduction.rst
 create mode 100644 arch/arm64/geniezone/Makefile
 create mode 100644 arch/arm64/geniezone/gzvm_arch.c
 create mode 100644 arch/arm64/geniezone/gzvm_arch.h
 create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c
 create mode 100644 arch/arm64/include/uapi/asm/gzvm_arch.h
 create mode 100644 drivers/virt/geniezone/Kconfig
 create mode 100644 drivers/virt/geniezone/Makefile
 create mode 100644 drivers/virt/geniezone/gzvm_ioeventfd.c
 create mode 100644 drivers/virt/geniezone/gzvm_irqfd.c
 create mode 100644 drivers/virt/geniezone/gzvm_main.c
 create mode 100644 drivers/virt/geniezone/gzvm_vcpu.c
 create mode 100644 drivers/virt/geniezone/gzvm_vm.c
 create mode 100644 include/linux/gzvm_drv.h
 create mode 100644 include/uapi/asm-generic/gzvm_arch.h
 create mode 100644 include/uapi/linux/gzvm.h

-- 
2.18.0


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v2 0/7] GenieZone hypervisor drivers
@ 2023-04-28 10:36 ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

This series is based on linux-next, tag: next-20230427.

Changes in v2:
- Refactor: move to drivers/virt/geniezone
- Refactor: decouple arch-dependent and arch-independent
- Check pending signal before entering guest context
- Fix reviewer's comments

Yi-De Wu (7):
  docs: geniezone: Introduce GenieZone hypervisor
  dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  virt: geniezone: Introduce GenieZone hypervisor support
  virt: geniezone: Add vcpu support
  virt: geniezone: Add irqchip support for virtual interrupt injection
  virt: geniezone: Add irqfd support
  virt: geniezone: Add ioeventfd support

 .../hypervisor/mediatek,geniezone-hyp.yaml    |  31 +
 Documentation/virt/geniezone/introduction.rst |  34 ++
 MAINTAINERS                                   |  13 +
 arch/arm64/Kbuild                             |   1 +
 arch/arm64/geniezone/Makefile                 |   9 +
 arch/arm64/geniezone/gzvm_arch.c              | 280 +++++++++
 arch/arm64/geniezone/gzvm_arch.h              |  92 +++
 arch/arm64/geniezone/gzvm_irqchip.c           | 108 ++++
 arch/arm64/include/uapi/asm/gzvm_arch.h       |  47 ++
 drivers/virt/Kconfig                          |   2 +
 drivers/virt/geniezone/Kconfig                |  17 +
 drivers/virt/geniezone/Makefile               |  12 +
 drivers/virt/geniezone/gzvm_ioeventfd.c       | 263 +++++++++
 drivers/virt/geniezone/gzvm_irqfd.c           | 536 ++++++++++++++++++
 drivers/virt/geniezone/gzvm_main.c            | 151 +++++
 drivers/virt/geniezone/gzvm_vcpu.c            | 260 +++++++++
 drivers/virt/geniezone/gzvm_vm.c              | 447 +++++++++++++++
 include/linux/gzvm_drv.h                      | 154 +++++
 include/uapi/asm-generic/gzvm_arch.h          |  10 +
 include/uapi/linux/gzvm.h                     | 274 +++++++++
 20 files changed, 2741 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hypervisor/mediatek,
 geniezone-hyp.yaml
 create mode 100644 Documentation/virt/geniezone/introduction.rst
 create mode 100644 arch/arm64/geniezone/Makefile
 create mode 100644 arch/arm64/geniezone/gzvm_arch.c
 create mode 100644 arch/arm64/geniezone/gzvm_arch.h
 create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c
 create mode 100644 arch/arm64/include/uapi/asm/gzvm_arch.h
 create mode 100644 drivers/virt/geniezone/Kconfig
 create mode 100644 drivers/virt/geniezone/Makefile
 create mode 100644 drivers/virt/geniezone/gzvm_ioeventfd.c
 create mode 100644 drivers/virt/geniezone/gzvm_irqfd.c
 create mode 100644 drivers/virt/geniezone/gzvm_main.c
 create mode 100644 drivers/virt/geniezone/gzvm_vcpu.c
 create mode 100644 drivers/virt/geniezone/gzvm_vm.c
 create mode 100644 include/linux/gzvm_drv.h
 create mode 100644 include/uapi/asm-generic/gzvm_arch.h
 create mode 100644 include/uapi/linux/gzvm.h

-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v2 1/7] docs: geniezone: Introduce GenieZone hypervisor
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 10:36   ` Yi-De Wu
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

GenieZone is MediaTek proprietary hypervisor solution, and it is running
in EL2 stand alone as a type-I hypervisor. It is a pure EL2
implementation which implies it does not rely any specific host VM, and
this behavior improves GenieZone's security as it limits its interface.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 Documentation/virt/geniezone/introduction.rst | 34 +++++++++++++++++++
 MAINTAINERS                                   |  6 ++++
 2 files changed, 40 insertions(+)
 create mode 100644 Documentation/virt/geniezone/introduction.rst

diff --git a/Documentation/virt/geniezone/introduction.rst b/Documentation/virt/geniezone/introduction.rst
new file mode 100644
index 000000000000..1fffd6cbb4db
--- /dev/null
+++ b/Documentation/virt/geniezone/introduction.rst
@@ -0,0 +1,34 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================
+GenieZone Introduction
+======================
+
+
+Overview
+========
+GenieZone is MediaTek proprietary hypervisor solution, and it is running in EL2
+stand alone as a type-I hypervisor. It is a pure EL2 implementation which
+implies it does not rely any specific host VM, and this behavior improves
+GenieZone's security as it limits its interface.
+
+To enable guest VMs running, a driver (gzvm) is provided for VMM (virtual
+machine monitor) to operate. Currently, the gzvm driver supports only crosvm.
+
+
+Supported Architecture
+======================
+GenieZone now only supports MediaTek arm64 SoC.
+
+
+Platform Virtualization
+=======================
+We leverages arm64's timer virtualization and gic virtualization for timer and
+interrupts controller.
+
+
+Device Virtualizaton
+====================
+We adopts VMM's virtio devices emulations by passing io trap to VMM, and virtio
+is a well-known and widely used virtual device implementation.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 4b8971cba764..db8915114b86 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8694,6 +8694,12 @@ F:	include/vdso/
 F:	kernel/time/vsyscall.c
 F:	lib/vdso/
 
+GENIEZONE HYPERVISOR DRIVER
+M:	Yingshiuan Pan <yingshiuan.pan@mediatek.com>
+M:	Ze-Yu Wang <ze-yu.wang@mediatek.com>
+M:	Yi-De Wu <yi-de.wu@mediatek.com>
+F:	Documentation/virt/geniezone/
+
 GENWQE (IBM Generic Workqueue Card)
 M:	Frank Haverkamp <haver@linux.ibm.com>
 S:	Supported
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 1/7] docs: geniezone: Introduce GenieZone hypervisor
@ 2023-04-28 10:36   ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

GenieZone is MediaTek proprietary hypervisor solution, and it is running
in EL2 stand alone as a type-I hypervisor. It is a pure EL2
implementation which implies it does not rely any specific host VM, and
this behavior improves GenieZone's security as it limits its interface.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 Documentation/virt/geniezone/introduction.rst | 34 +++++++++++++++++++
 MAINTAINERS                                   |  6 ++++
 2 files changed, 40 insertions(+)
 create mode 100644 Documentation/virt/geniezone/introduction.rst

diff --git a/Documentation/virt/geniezone/introduction.rst b/Documentation/virt/geniezone/introduction.rst
new file mode 100644
index 000000000000..1fffd6cbb4db
--- /dev/null
+++ b/Documentation/virt/geniezone/introduction.rst
@@ -0,0 +1,34 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================
+GenieZone Introduction
+======================
+
+
+Overview
+========
+GenieZone is MediaTek proprietary hypervisor solution, and it is running in EL2
+stand alone as a type-I hypervisor. It is a pure EL2 implementation which
+implies it does not rely any specific host VM, and this behavior improves
+GenieZone's security as it limits its interface.
+
+To enable guest VMs running, a driver (gzvm) is provided for VMM (virtual
+machine monitor) to operate. Currently, the gzvm driver supports only crosvm.
+
+
+Supported Architecture
+======================
+GenieZone now only supports MediaTek arm64 SoC.
+
+
+Platform Virtualization
+=======================
+We leverages arm64's timer virtualization and gic virtualization for timer and
+interrupts controller.
+
+
+Device Virtualizaton
+====================
+We adopts VMM's virtio devices emulations by passing io trap to VMM, and virtio
+is a well-known and widely used virtual device implementation.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 4b8971cba764..db8915114b86 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8694,6 +8694,12 @@ F:	include/vdso/
 F:	kernel/time/vsyscall.c
 F:	lib/vdso/
 
+GENIEZONE HYPERVISOR DRIVER
+M:	Yingshiuan Pan <yingshiuan.pan@mediatek.com>
+M:	Ze-Yu Wang <ze-yu.wang@mediatek.com>
+M:	Yi-De Wu <yi-de.wu@mediatek.com>
+F:	Documentation/virt/geniezone/
+
 GENWQE (IBM Generic Workqueue Card)
 M:	Frank Haverkamp <haver@linux.ibm.com>
 S:	Supported
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 10:36   ` Yi-De Wu
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

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.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 .../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..9dc0831cf175
--- /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,gzvm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek GenieZone hypervisor
+
+maintainers:
+  - Yingshiuan Pan <yingshiuan.pan@mediatek.com>
+
+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 hypercalls 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 db8915114b86..1e911d1d9741 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8698,6 +8698,7 @@ GENIEZONE HYPERVISOR DRIVER
 M:	Yingshiuan Pan <yingshiuan.pan@mediatek.com>
 M:	Ze-Yu Wang <ze-yu.wang@mediatek.com>
 M:	Yi-De Wu <yi-de.wu@mediatek.com>
+F:	Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml
 F:	Documentation/virt/geniezone/
 
 GENWQE (IBM Generic Workqueue Card)
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
@ 2023-04-28 10:36   ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

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.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 .../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..9dc0831cf175
--- /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,gzvm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek GenieZone hypervisor
+
+maintainers:
+  - Yingshiuan Pan <yingshiuan.pan@mediatek.com>
+
+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 hypercalls 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 db8915114b86..1e911d1d9741 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8698,6 +8698,7 @@ GENIEZONE HYPERVISOR DRIVER
 M:	Yingshiuan Pan <yingshiuan.pan@mediatek.com>
 M:	Ze-Yu Wang <ze-yu.wang@mediatek.com>
 M:	Yi-De Wu <yi-de.wu@mediatek.com>
+F:	Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml
 F:	Documentation/virt/geniezone/
 
 GENWQE (IBM Generic Workqueue Card)
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 10:36   ` Yi-De Wu
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

GenieZone is MediaTek hypervisor solution, and it is running in EL2
stand alone as a type-I hypervisor. This patch exports a set of ioctl
interfaces for userspace VMM (e.g., crosvm) to operate guest VMs
lifecycle (creation and destroy) on GenieZone.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 MAINTAINERS                             |   6 +
 arch/arm64/Kbuild                       |   1 +
 arch/arm64/geniezone/Makefile           |   9 +
 arch/arm64/geniezone/gzvm_arch.c        | 189 +++++++++++++
 arch/arm64/geniezone/gzvm_arch.h        |  50 ++++
 arch/arm64/include/uapi/asm/gzvm_arch.h |  18 ++
 drivers/virt/Kconfig                    |   2 +
 drivers/virt/geniezone/Kconfig          |  17 ++
 drivers/virt/geniezone/Makefile         |  10 +
 drivers/virt/geniezone/gzvm_main.c      | 146 ++++++++++
 drivers/virt/geniezone/gzvm_vm.c        | 336 ++++++++++++++++++++++++
 include/linux/gzvm_drv.h                |  98 +++++++
 include/uapi/asm-generic/gzvm_arch.h    |  10 +
 include/uapi/linux/gzvm.h               |  99 +++++++
 14 files changed, 991 insertions(+)
 create mode 100644 arch/arm64/geniezone/Makefile
 create mode 100644 arch/arm64/geniezone/gzvm_arch.c
 create mode 100644 arch/arm64/geniezone/gzvm_arch.h
 create mode 100644 arch/arm64/include/uapi/asm/gzvm_arch.h
 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 drivers/virt/geniezone/gzvm_vm.c
 create mode 100644 include/linux/gzvm_drv.h
 create mode 100644 include/uapi/asm-generic/gzvm_arch.h
 create mode 100644 include/uapi/linux/gzvm.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 1e911d1d9741..09a8ccf77b01 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8700,6 +8700,12 @@ M:	Ze-Yu Wang <ze-yu.wang@mediatek.com>
 M:	Yi-De Wu <yi-de.wu@mediatek.com>
 F:	Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml
 F:	Documentation/virt/geniezone/
+F:	arch/arm64/geniezone/
+F:	arch/arm64/include/uapi/asm/gzvm_arch.h
+F:	drivers/virt/geniezone/
+F:	include/linux/gzvm_drv.h
+F	include/uapi/asm-generic/gzvm_arch.h
+F:	include/uapi/linux/gzvm.h
 
 GENWQE (IBM Generic Workqueue Card)
 M:	Frank Haverkamp <haver@linux.ibm.com>
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..5720c076d73c
--- /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 += gzvm_arch.o
+
+obj-$(CONFIG_MTK_GZVM) += gzvm.o
diff --git a/arch/arm64/geniezone/gzvm_arch.c b/arch/arm64/geniezone/gzvm_arch.c
new file mode 100644
index 000000000000..2fc76f7d440f
--- /dev/null
+++ b/arch/arm64/geniezone/gzvm_arch.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+
+#include <linux/gzvm.h>
+#include <linux/gzvm_drv.h>
+#include "gzvm_arch.h"
+
+/**
+ * geniezone_hypercall_wrapper()
+ *
+ * Return: The wrapper helps caller to convert geniezone errno to Linux errno.
+ */
+static 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 gz_err_to_errno(res->a0);
+}
+
+int gzvm_arch_probe(void)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_hvc(MT_HVC_GZVM_PROBE, 0, 0, 0, 0, 0, 0, 0, &res);
+	if (res.a0 == 0)
+		return 0;
+
+	return -ENXIO;
+}
+
+int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
+			    phys_addr_t region)
+{
+	struct arm_smccc_res res;
+
+	return gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_MEMREGION, vm_id,
+				    buf_size, region, 0, 0, 0, 0, &res);
+}
+
+static int gzvm_cap_arm_vm_ipa_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 = -EOPNOTSUPP;
+
+	switch (cap) {
+	case GZVM_CAP_ARM_PROTECTED_VM: {
+		__u64 success = 1;
+
+		if (copy_to_user(argp, &success, sizeof(__u64)))
+			return -EFAULT;
+		ret = 0;
+		break;
+	}
+	case GZVM_CAP_ARM_VM_IPA_SIZE: {
+		ret = gzvm_cap_arm_vm_ipa_size(argp);
+		break;
+	}
+	default:
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+/**
+ * gzvm_arch_create_vm()
+ *
+ * Return:
+ * * positive value	- VM ID
+ * * -ENOMEM		- Memory not enough for storing VM data
+ */
+int gzvm_arch_create_vm(void)
+{
+	struct arm_smccc_res res;
+	int ret;
+
+	ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VM, 0, 0, 0, 0, 0, 0, 0,
+				   &res);
+
+	if (ret == 0)
+		return res.a1;
+	else
+		return ret;
+}
+
+int gzvm_arch_destroy_vm(gzvm_id_t 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);
+}
+
+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.
+ *
+ * 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_ARM_PROTECTED_VM's subcommands
+ *
+ * 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)
+{
+	int ret = -EINVAL;
+	struct arm_smccc_res res = {0};
+
+	switch (cap->args[0]) {
+	case GZVM_CAP_ARM_PVM_SET_PVMFW_IPA:
+		ret = gzvm_vm_arch_enable_cap(gzvm, cap, &res);
+		break;
+	case GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE:
+		ret = gzvm_vm_ioctl_get_pvmfw_size(gzvm, cap, argp);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap,
+				  void __user *argp)
+{
+	int ret = -EINVAL;
+
+	switch (cap->cap) {
+	case GZVM_CAP_ARM_PROTECTED_VM:
+		ret = gzvm_vm_ioctl_cap_pvm(gzvm, cap, argp);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
diff --git a/arch/arm64/geniezone/gzvm_arch.h b/arch/arm64/geniezone/gzvm_arch.h
new file mode 100644
index 000000000000..dd0b7b5f7c65
--- /dev/null
+++ b/arch/arm64/geniezone/gzvm_arch.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __GZ_ARCH_H__
+#define __GZ_ARCH_H__
+
+#include <linux/arm-smccc.h>
+
+enum {
+	GZVM_FUNC_CREATE_VM = 0,
+	GZVM_FUNC_DESTROY_VM,
+	GZVM_FUNC_CREATE_VCPU,
+	GZVM_FUNC_DESTROY_VCPU,
+	GZVM_FUNC_SET_MEMREGION,
+	GZVM_FUNC_RUN,
+	GZVM_FUNC_GET_REGS,
+	GZVM_FUNC_SET_REGS,
+	GZVM_FUNC_GET_ONE_REG,
+	GZVM_FUNC_SET_ONE_REG,
+	GZVM_FUNC_IRQ_LINE,
+	GZVM_FUNC_CREATE_DEVICE,
+	GZVM_FUNC_PROBE,
+	GZVM_FUNC_ENABLE_CAP,
+	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_32,	\
+			   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_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_REGS		GZVM_HCALL_ID(GZVM_FUNC_GET_REGS)
+#define MT_HVC_GZVM_SET_REGS		GZVM_HCALL_ID(GZVM_FUNC_SET_REGS)
+#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_IRQ_LINE		GZVM_HCALL_ID(GZVM_FUNC_IRQ_LINE)
+#define MT_HVC_GZVM_CREATE_DEVICE	GZVM_HCALL_ID(GZVM_FUNC_CREATE_DEVICE)
+#define MT_HVC_GZVM_PROBE		GZVM_HCALL_ID(GZVM_FUNC_PROBE)
+#define MT_HVC_GZVM_ENABLE_CAP		GZVM_HCALL_ID(GZVM_FUNC_ENABLE_CAP)
+
+#endif /* __GZVM_ARCH_H__ */
diff --git a/arch/arm64/include/uapi/asm/gzvm_arch.h b/arch/arm64/include/uapi/asm/gzvm_arch.h
new file mode 100644
index 000000000000..e7927f3dcb11
--- /dev/null
+++ b/arch/arm64/include/uapi/asm/gzvm_arch.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __GZVM_ARCH_H__
+#define __GZVM_ARCH_H__
+
+#include <linux/types.h>
+
+#define GZVM_CAP_ARM_VM_IPA_SIZE	165
+#define GZVM_CAP_ARM_PROTECTED_VM	0xffbadab1
+
+/* sub-commands put in args[0] for GZVM_CAP_ARM_PROTECTED_VM */
+#define GZVM_CAP_ARM_PVM_SET_PVMFW_IPA		0
+#define GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE		1
+
+#endif /* __GZVM_ARCH_H__ */
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
index f79ab13a5c28..9bbf0bdf672c 100644
--- a/drivers/virt/Kconfig
+++ b/drivers/virt/Kconfig
@@ -54,4 +54,6 @@ source "drivers/virt/coco/sev-guest/Kconfig"
 
 source "drivers/virt/coco/tdx-guest/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..6fad3c30f8d9
--- /dev/null
+++ b/drivers/virt/geniezone/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config MTK_GZVM
+	tristate "GenieZone Hypervisor driver for guest VM operation"
+	depends on ARM64
+	depends on KVM
+	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..066efddc0b9c
--- /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 $(GZVM_DIR)/gzvm_vm.o
+
diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c
new file mode 100644
index 000000000000..e3fe3ad9ffce
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_main.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/anon_inodes.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/kdev_t.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gzvm_drv.h>
+
+struct platform_device *gzvm_debug_dev;
+
+/**
+ * gz_err_to_errno() - Convert geniezone return value to standard errno
+ *
+ * @err: Return value from geniezone function return
+ *
+ * Return: Standard errno
+ */
+int gz_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;
+}
+
+/**
+ * gzvm_dev_ioctl_check_extension() - Check if given capability is support
+ *				      or not
+ *
+ * @gzvm:
+ * @args: Pointer in u64 from userspace
+ *
+ * Return:
+ * * 0			- Support, no error
+ * * -EOPNOTSUPP	- Not support
+ * * -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)
+{
+	long ret = -ENOTTY;
+
+	switch (cmd) {
+	case GZVM_CREATE_VM:
+		ret = gzvm_dev_ioctl_create_vm(user_args);
+		break;
+	case GZVM_CHECK_EXTENSION:
+		if (!user_args)
+			return -EINVAL;
+		ret = gzvm_dev_ioctl_check_extension(NULL, user_args);
+		break;
+	default:
+		ret = -ENOTTY;
+	}
+
+	return ret;
+}
+
+static const struct file_operations gzvm_chardev_ops = {
+	.unlocked_ioctl = gzvm_dev_ioctl,
+	.llseek		= noop_llseek,
+};
+
+static struct miscdevice gzvm_dev = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = MODULE_NAME,
+	.fops = &gzvm_chardev_ops,
+};
+
+static int gzvm_drv_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (gzvm_arch_probe() != 0) {
+		dev_err(&pdev->dev, "Not found available conduit\n");
+		return -ENODEV;
+	}
+
+	ret = misc_register(&gzvm_dev);
+	if (ret)
+		return ret;
+	gzvm_debug_dev = pdev;
+
+	return 0;
+}
+
+static int gzvm_drv_remove(struct platform_device *pdev)
+{
+	destroy_all_vm();
+	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 = MODULE_NAME,
+		.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/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
new file mode 100644
index 000000000000..58471dd899fb
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
+#include <linux/kdev_t.h>
+#include <linux/kvm_host.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/gzvm_drv.h>
+
+static DEFINE_MUTEX(gzvm_list_lock);
+static LIST_HEAD(gzvm_list);
+
+/**
+ * gzvm_gfn_to_pfn_memslot() - Translate gfn (guest ipa) to pfn (host pa),
+ *			       result is in @pfn
+ *
+ * Leverage KVM's gfn_to_pfn_memslot(). Because gfn_to_pfn_memslot() needs
+ * kvm_memory_slot as parameter, this function populates necessary fileds
+ * for calling gfn_to_pfn_memslot().
+ *
+ * Return:
+ * * 0			- Succeed
+ * * -EFAULT		- Failed to convert
+ */
+static int gzvm_gfn_to_pfn_memslot(struct gzvm_memslot *memslot, u64 gfn, u64 *pfn)
+{
+	hfn_t __pfn;
+	struct kvm_memory_slot kvm_slot = {0};
+
+	kvm_slot.base_gfn = memslot->base_gfn;
+	kvm_slot.npages = memslot->npages;
+	kvm_slot.dirty_bitmap = NULL;
+	kvm_slot.userspace_addr = memslot->userspace_addr;
+	kvm_slot.flags = memslot->flags;
+	kvm_slot.id = memslot->slot_id;
+	kvm_slot.as_id = 0;
+
+	__pfn = gfn_to_pfn_memslot(&kvm_slot, gfn);
+	if (is_error_noslot_pfn(__pfn)) {
+		*pfn = 0;
+		return -EFAULT;
+	}
+
+	*pfn = __pfn;
+	return 0;
+}
+
+/**
+ * fill_constituents() - Populate pa to buffer until full
+ *
+ * Return: how many pages we've fill in, negative if error
+ */
+static int fill_constituents(struct mem_region_addr_range *consti,
+			     int *consti_cnt, int max_nr_consti, gfn_t gfn,
+			     u32 total_pages, struct gzvm_memslot *slot)
+{
+	int i, nr_pages;
+	hfn_t pfn, prev_pfn;
+	gfn_t gfn_end;
+
+	if (unlikely(total_pages == 0))
+		return -EINVAL;
+	gfn_end = gfn + total_pages;
+
+	/* entry 0 */
+	if (gzvm_gfn_to_pfn_memslot(slot, gfn, &pfn) != 0)
+		return -EFAULT;
+	consti[0].address = PFN_PHYS(pfn);
+	consti[0].pg_cnt = 1;
+	gfn++;
+	prev_pfn = pfn;
+	i = 0;
+	nr_pages = 1;
+	while (i < max_nr_consti && gfn < gfn_end) {
+		if (gzvm_gfn_to_pfn_memslot(slot, gfn, &pfn) != 0)
+			return -EFAULT;
+		if (pfn == (prev_pfn + 1)) {
+			consti[i].pg_cnt++;
+		} else {
+			i++;
+			if (i >= max_nr_consti)
+				break;
+			consti[i].address = PFN_PHYS(pfn);
+			consti[i].pg_cnt = 1;
+		}
+		prev_pfn = pfn;
+		gfn++;
+		nr_pages++;
+	}
+	if (i == max_nr_consti)
+		*consti_cnt = i;
+	else
+		*consti_cnt = (i + 1);
+
+	return nr_pages;
+}
+
+/* register_memslot_addr_range() - Register memory region to GZ */
+static int
+register_memslot_addr_range(struct gzvm *gzvm, struct gzvm_memslot *memslot)
+{
+	struct gzvm_memory_region_ranges *region;
+	u32 buf_size;
+	int max_nr_consti, remain_pages;
+	gfn_t gfn, gfn_end;
+
+	buf_size = PAGE_SIZE * 2;
+	region = alloc_pages_exact(buf_size, GFP_KERNEL);
+	if (!region)
+		return -ENOMEM;
+	max_nr_consti = (buf_size - sizeof(*region)) /
+			sizeof(struct mem_region_addr_range);
+
+	region->slot = memslot->slot_id;
+	remain_pages = memslot->npages;
+	gfn = memslot->base_gfn;
+	gfn_end = gfn + remain_pages;
+	while (gfn < gfn_end) {
+		int nr_pages;
+
+		nr_pages = fill_constituents(region->constituents,
+					     &region->constituent_cnt,
+					     max_nr_consti, gfn,
+					     remain_pages, memslot);
+		region->gpa = PFN_PHYS(gfn);
+		region->total_pages = nr_pages;
+
+		remain_pages -= nr_pages;
+		gfn += nr_pages;
+
+		if (gzvm_arch_set_memregion(gzvm->vm_id, buf_size,
+					    virt_to_phys(region))) {
+			dev_err(&gzvm_debug_dev->dev,
+				"Failed to register memregion to hypervisor\n");
+			free_pages_exact(region, buf_size);
+			return -EFAULT;
+		}
+	}
+	free_pages_exact(region, buf_size);
+	return 0;
+}
+
+/**
+ * gzvm_vm_ioctl_set_memory_region() - Set memory region of guest
+ *
+ * @mem: input memory region from user
+ *
+ * Return:
+ * * -EXIO		- memslot is out-of-range
+ * * -EFAULT		- Cannot find corresponding vma
+ * * -EINVAL		- region size and vma size does not match
+ */
+static int
+gzvm_vm_ioctl_set_memory_region(struct gzvm *gzvm,
+				struct gzvm_userspace_memory_region *mem)
+{
+	struct vm_area_struct *vma;
+	struct gzvm_memslot *memslot;
+	unsigned long size;
+	__u32 slot;
+
+	slot = mem->slot;
+	if (slot >= GZVM_MAX_MEM_REGION)
+		return -ENXIO;
+	memslot = &gzvm->memslot[slot];
+
+	vma = vma_lookup(gzvm->mm, mem->userspace_addr);
+	if (!vma)
+		return -EFAULT;
+
+	size = vma->vm_end - vma->vm_start;
+	if (size != mem->memory_size)
+		return -EINVAL;
+
+	memslot->base_gfn = __phys_to_pfn(mem->guest_phys_addr);
+	memslot->npages = size >> PAGE_SHIFT;
+	memslot->userspace_addr = mem->userspace_addr;
+	memslot->vma = vma;
+	memslot->flags = mem->flags;
+	memslot->slot_id = mem->slot;
+	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)
+{
+	long ret = -ENOTTY;
+	void __user *argp = (void __user *)arg;
+	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;
+
+		ret = -EFAULT;
+		if (copy_from_user(&userspace_mem, argp,
+				   sizeof(userspace_mem)))
+			goto out;
+		ret = gzvm_vm_ioctl_set_memory_region(gzvm, &userspace_mem);
+		break;
+	}
+	case GZVM_ENABLE_CAP: {
+		struct gzvm_enable_cap cap;
+
+		ret = -EFAULT;
+		if (copy_from_user(&cap, argp, sizeof(cap)))
+			goto out;
+
+		ret = gzvm_vm_ioctl_enable_cap(gzvm, &cap, argp);
+		break;
+	}
+	default:
+		ret = -ENOTTY;
+	}
+out:
+	return ret;
+}
+
+static void gzvm_destroy_vm(struct gzvm *gzvm)
+{
+	dev_info(&gzvm_debug_dev->dev,
+		 "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,
+	.unlocked_ioctl = gzvm_vm_ioctl,
+	.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();
+	if (ret < 0)
+		goto err;
+
+	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_info("VM-%u is created\n", gzvm->vm_id);
+
+	return gzvm;
+
+err:
+	kfree(gzvm);
+	return ERR_PTR(ret);
+}
+
+/**
+ * gzvm_dev_ioctl_create_vm - Create vm fd
+ *
+ * Return: fd of vm, negative if error
+ */
+int gzvm_dev_ioctl_create_vm(unsigned long vm_type)
+{
+	struct gzvm *gzvm;
+	int ret;
+
+	gzvm = gzvm_create_vm(vm_type);
+	if (IS_ERR(gzvm)) {
+		ret = PTR_ERR(gzvm);
+		goto error;
+	}
+
+	ret = anon_inode_getfd("gzvm-vm", &gzvm_vm_fops, gzvm,
+			       O_RDWR | O_CLOEXEC);
+	if (ret < 0)
+		goto error;
+
+error:
+	return ret;
+}
+
+void destroy_all_vm(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
new file mode 100644
index 000000000000..f2cfbf87c113
--- /dev/null
+++ b/include/linux/gzvm_drv.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __GZVM_DRV_H__
+#define __GZVM_DRV_H__
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/gzvm.h>
+
+#define MODULE_NAME	"gzvm"
+#define GZVM_VCPU_MMAP_SIZE  PAGE_SIZE
+#define INVALID_VM_ID   0xffff
+
+/**
+ * These are the efinitions 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)
+
+static inline gzvm_id_t get_vmid_from_tuple(unsigned int tuple)
+{
+	return (gzvm_id_t)(tuple >> 16);
+}
+
+/**
+ * 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
+
+/* 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 */
+	__u64 address;
+	/* the number of 4 kiB pages in the constituent memory region. */
+	__u32 pg_cnt;
+	__u32 reserved;
+};
+
+struct gzvm_memory_region_ranges {
+	__u32 slot;
+	__u32 constituent_cnt;
+	__u64 total_pages;
+	__u64 gpa;
+	struct mem_region_addr_range constituents[];
+};
+
+/* struct gzvm_memslot - VM's memory slot descriptor */
+struct gzvm_memslot {
+	u64 base_gfn;			/* begin of guest page frame */
+	unsigned long npages;		/* number of pages this slot covers */
+	unsigned long userspace_addr;	/* corresponding userspace va */
+	struct vm_area_struct *vma;	/* vma related to this userspace addr */
+	u32 flags;
+	u32 slot_id;
+};
+
+struct gzvm {
+	/* userspace tied to this vm */
+	struct mm_struct *mm;
+	struct gzvm_memslot memslot[GZVM_MAX_MEM_REGION];
+	/* lock for list_add*/
+	struct mutex lock;
+	struct list_head vm_list;
+	gzvm_id_t 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 gz_err_to_errno(unsigned long err);
+
+void destroy_all_vm(void);
+
+/* arch-dependant functions */
+int gzvm_arch_probe(void);
+int gzvm_arch_set_memregion(gzvm_id_t 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(void);
+int gzvm_arch_destroy_vm(gzvm_id_t vm_id);
+int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm,
+				  struct gzvm_enable_cap *cap,
+				  void __user *argp);
+
+extern struct platform_device *gzvm_debug_dev;
+
+#endif /* __GZVM_DRV_H__ */
diff --git a/include/uapi/asm-generic/gzvm_arch.h b/include/uapi/asm-generic/gzvm_arch.h
new file mode 100644
index 000000000000..c4cc12716c91
--- /dev/null
+++ b/include/uapi/asm-generic/gzvm_arch.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __ASM_GENERIC_GZVM_ARCH_H
+#define __ASM_GENERIC_GZVM_ARCH_H
+/* geniezone only supports aarch64 platform for now */
+
+#endif /* __ASM_GENERIC_GZVM_ARCH_H */
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
new file mode 100644
index 000000000000..1d157647a580
--- /dev/null
+++ b/include/uapi/linux/gzvm.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __GZVM_H__
+#define __GZVM_H__
+
+#include <linux/const.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/* geniezone only supports aarch64 platform for now */
+#if defined(__aarch64__)
+#include <asm/gzvm_arch.h>
+#endif
+
+
+/**
+ * DOC: This file declares common data structure shared between userspace,
+ *	kernel space, and GZ.
+ */
+
+typedef __u16 gzvm_id_t;
+typedef __u16 gzvm_vcpu_id_t;
+
+/* GZVM ioctls */
+#define GZVM_IOC_MAGIC			0x92	/* gz */
+
+/* ioctls for /dev/gzvm fds */
+#define GZVM_GET_API_VERSION       _IO(GZVM_IOC_MAGIC,   0x00)
+#define GZVM_CREATE_VM             _IO(GZVM_IOC_MAGIC,   0x01)
+
+#define GZVM_CHECK_EXTENSION       _IO(GZVM_IOC_MAGIC,   0x03)
+
+/* ioctls for VM fds */
+/* for GZVM_SET_MEMORY_REGION */
+struct gzvm_memory_region {
+	__u32 slot;
+	__u32 flags;
+	__u64 guest_phys_addr;
+	__u64 memory_size; /* bytes */
+};
+
+#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 {
+	__u32 slot;
+	__u32 flags;
+	__u64 guest_phys_addr;
+	__u64 memory_size; /* bytes */
+	__u64 userspace_addr; /* start of the userspace allocated memory */
+};
+
+#define GZVM_SET_USER_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x46, \
+					struct gzvm_userspace_memory_region)
+
+/* for GZVM_IRQ_LINE */
+/* GZVM_IRQ_LINE irq field index values */
+#define GZVM_IRQ_VCPU2_SHIFT		28
+#define GZVM_IRQ_VCPU2_MASK		0xf
+#define GZVM_IRQ_TYPE_SHIFT		24
+#define GZVM_IRQ_TYPE_MASK		0xf
+#define GZVM_IRQ_VCPU_SHIFT		16
+#define GZVM_IRQ_VCPU_MASK		0xff
+#define GZVM_IRQ_NUM_SHIFT		0
+#define GZVM_IRQ_NUM_MASK		0xffff
+
+/* irq_type field */
+#define GZVM_IRQ_TYPE_CPU		0
+#define GZVM_IRQ_TYPE_SPI		1
+#define GZVM_IRQ_TYPE_PPI		2
+
+/* out-of-kernel GIC cpu interrupt injection irq_number field */
+#define GZVM_IRQ_CPU_IRQ		0
+#define GZVM_IRQ_CPU_FIQ		1
+
+/* ioctls for vcpu fds */
+#define GZVM_RUN                   _IO(GZVM_IOC_MAGIC,   0x80)
+
+/* for GZVM_ENABLE_CAP */
+struct gzvm_enable_cap {
+	/* in */
+	__u64 cap;
+	/* we have total 5 (8 - 3) registers can be used for additional args */
+	__u64 args[5];
+};
+
+#define GZVM_ENABLE_CAP            _IOW(GZVM_IOC_MAGIC,  0xa3, \
+					struct gzvm_enable_cap)
+
+#endif /* __GZVM_H__ */
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
@ 2023-04-28 10:36   ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

GenieZone is MediaTek hypervisor solution, and it is running in EL2
stand alone as a type-I hypervisor. This patch exports a set of ioctl
interfaces for userspace VMM (e.g., crosvm) to operate guest VMs
lifecycle (creation and destroy) on GenieZone.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 MAINTAINERS                             |   6 +
 arch/arm64/Kbuild                       |   1 +
 arch/arm64/geniezone/Makefile           |   9 +
 arch/arm64/geniezone/gzvm_arch.c        | 189 +++++++++++++
 arch/arm64/geniezone/gzvm_arch.h        |  50 ++++
 arch/arm64/include/uapi/asm/gzvm_arch.h |  18 ++
 drivers/virt/Kconfig                    |   2 +
 drivers/virt/geniezone/Kconfig          |  17 ++
 drivers/virt/geniezone/Makefile         |  10 +
 drivers/virt/geniezone/gzvm_main.c      | 146 ++++++++++
 drivers/virt/geniezone/gzvm_vm.c        | 336 ++++++++++++++++++++++++
 include/linux/gzvm_drv.h                |  98 +++++++
 include/uapi/asm-generic/gzvm_arch.h    |  10 +
 include/uapi/linux/gzvm.h               |  99 +++++++
 14 files changed, 991 insertions(+)
 create mode 100644 arch/arm64/geniezone/Makefile
 create mode 100644 arch/arm64/geniezone/gzvm_arch.c
 create mode 100644 arch/arm64/geniezone/gzvm_arch.h
 create mode 100644 arch/arm64/include/uapi/asm/gzvm_arch.h
 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 drivers/virt/geniezone/gzvm_vm.c
 create mode 100644 include/linux/gzvm_drv.h
 create mode 100644 include/uapi/asm-generic/gzvm_arch.h
 create mode 100644 include/uapi/linux/gzvm.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 1e911d1d9741..09a8ccf77b01 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8700,6 +8700,12 @@ M:	Ze-Yu Wang <ze-yu.wang@mediatek.com>
 M:	Yi-De Wu <yi-de.wu@mediatek.com>
 F:	Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml
 F:	Documentation/virt/geniezone/
+F:	arch/arm64/geniezone/
+F:	arch/arm64/include/uapi/asm/gzvm_arch.h
+F:	drivers/virt/geniezone/
+F:	include/linux/gzvm_drv.h
+F	include/uapi/asm-generic/gzvm_arch.h
+F:	include/uapi/linux/gzvm.h
 
 GENWQE (IBM Generic Workqueue Card)
 M:	Frank Haverkamp <haver@linux.ibm.com>
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..5720c076d73c
--- /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 += gzvm_arch.o
+
+obj-$(CONFIG_MTK_GZVM) += gzvm.o
diff --git a/arch/arm64/geniezone/gzvm_arch.c b/arch/arm64/geniezone/gzvm_arch.c
new file mode 100644
index 000000000000..2fc76f7d440f
--- /dev/null
+++ b/arch/arm64/geniezone/gzvm_arch.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+
+#include <linux/gzvm.h>
+#include <linux/gzvm_drv.h>
+#include "gzvm_arch.h"
+
+/**
+ * geniezone_hypercall_wrapper()
+ *
+ * Return: The wrapper helps caller to convert geniezone errno to Linux errno.
+ */
+static 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 gz_err_to_errno(res->a0);
+}
+
+int gzvm_arch_probe(void)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_hvc(MT_HVC_GZVM_PROBE, 0, 0, 0, 0, 0, 0, 0, &res);
+	if (res.a0 == 0)
+		return 0;
+
+	return -ENXIO;
+}
+
+int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
+			    phys_addr_t region)
+{
+	struct arm_smccc_res res;
+
+	return gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_MEMREGION, vm_id,
+				    buf_size, region, 0, 0, 0, 0, &res);
+}
+
+static int gzvm_cap_arm_vm_ipa_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 = -EOPNOTSUPP;
+
+	switch (cap) {
+	case GZVM_CAP_ARM_PROTECTED_VM: {
+		__u64 success = 1;
+
+		if (copy_to_user(argp, &success, sizeof(__u64)))
+			return -EFAULT;
+		ret = 0;
+		break;
+	}
+	case GZVM_CAP_ARM_VM_IPA_SIZE: {
+		ret = gzvm_cap_arm_vm_ipa_size(argp);
+		break;
+	}
+	default:
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+/**
+ * gzvm_arch_create_vm()
+ *
+ * Return:
+ * * positive value	- VM ID
+ * * -ENOMEM		- Memory not enough for storing VM data
+ */
+int gzvm_arch_create_vm(void)
+{
+	struct arm_smccc_res res;
+	int ret;
+
+	ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VM, 0, 0, 0, 0, 0, 0, 0,
+				   &res);
+
+	if (ret == 0)
+		return res.a1;
+	else
+		return ret;
+}
+
+int gzvm_arch_destroy_vm(gzvm_id_t 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);
+}
+
+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.
+ *
+ * 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_ARM_PROTECTED_VM's subcommands
+ *
+ * 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)
+{
+	int ret = -EINVAL;
+	struct arm_smccc_res res = {0};
+
+	switch (cap->args[0]) {
+	case GZVM_CAP_ARM_PVM_SET_PVMFW_IPA:
+		ret = gzvm_vm_arch_enable_cap(gzvm, cap, &res);
+		break;
+	case GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE:
+		ret = gzvm_vm_ioctl_get_pvmfw_size(gzvm, cap, argp);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap,
+				  void __user *argp)
+{
+	int ret = -EINVAL;
+
+	switch (cap->cap) {
+	case GZVM_CAP_ARM_PROTECTED_VM:
+		ret = gzvm_vm_ioctl_cap_pvm(gzvm, cap, argp);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
diff --git a/arch/arm64/geniezone/gzvm_arch.h b/arch/arm64/geniezone/gzvm_arch.h
new file mode 100644
index 000000000000..dd0b7b5f7c65
--- /dev/null
+++ b/arch/arm64/geniezone/gzvm_arch.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __GZ_ARCH_H__
+#define __GZ_ARCH_H__
+
+#include <linux/arm-smccc.h>
+
+enum {
+	GZVM_FUNC_CREATE_VM = 0,
+	GZVM_FUNC_DESTROY_VM,
+	GZVM_FUNC_CREATE_VCPU,
+	GZVM_FUNC_DESTROY_VCPU,
+	GZVM_FUNC_SET_MEMREGION,
+	GZVM_FUNC_RUN,
+	GZVM_FUNC_GET_REGS,
+	GZVM_FUNC_SET_REGS,
+	GZVM_FUNC_GET_ONE_REG,
+	GZVM_FUNC_SET_ONE_REG,
+	GZVM_FUNC_IRQ_LINE,
+	GZVM_FUNC_CREATE_DEVICE,
+	GZVM_FUNC_PROBE,
+	GZVM_FUNC_ENABLE_CAP,
+	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_32,	\
+			   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_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_REGS		GZVM_HCALL_ID(GZVM_FUNC_GET_REGS)
+#define MT_HVC_GZVM_SET_REGS		GZVM_HCALL_ID(GZVM_FUNC_SET_REGS)
+#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_IRQ_LINE		GZVM_HCALL_ID(GZVM_FUNC_IRQ_LINE)
+#define MT_HVC_GZVM_CREATE_DEVICE	GZVM_HCALL_ID(GZVM_FUNC_CREATE_DEVICE)
+#define MT_HVC_GZVM_PROBE		GZVM_HCALL_ID(GZVM_FUNC_PROBE)
+#define MT_HVC_GZVM_ENABLE_CAP		GZVM_HCALL_ID(GZVM_FUNC_ENABLE_CAP)
+
+#endif /* __GZVM_ARCH_H__ */
diff --git a/arch/arm64/include/uapi/asm/gzvm_arch.h b/arch/arm64/include/uapi/asm/gzvm_arch.h
new file mode 100644
index 000000000000..e7927f3dcb11
--- /dev/null
+++ b/arch/arm64/include/uapi/asm/gzvm_arch.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __GZVM_ARCH_H__
+#define __GZVM_ARCH_H__
+
+#include <linux/types.h>
+
+#define GZVM_CAP_ARM_VM_IPA_SIZE	165
+#define GZVM_CAP_ARM_PROTECTED_VM	0xffbadab1
+
+/* sub-commands put in args[0] for GZVM_CAP_ARM_PROTECTED_VM */
+#define GZVM_CAP_ARM_PVM_SET_PVMFW_IPA		0
+#define GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE		1
+
+#endif /* __GZVM_ARCH_H__ */
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
index f79ab13a5c28..9bbf0bdf672c 100644
--- a/drivers/virt/Kconfig
+++ b/drivers/virt/Kconfig
@@ -54,4 +54,6 @@ source "drivers/virt/coco/sev-guest/Kconfig"
 
 source "drivers/virt/coco/tdx-guest/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..6fad3c30f8d9
--- /dev/null
+++ b/drivers/virt/geniezone/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config MTK_GZVM
+	tristate "GenieZone Hypervisor driver for guest VM operation"
+	depends on ARM64
+	depends on KVM
+	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..066efddc0b9c
--- /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 $(GZVM_DIR)/gzvm_vm.o
+
diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c
new file mode 100644
index 000000000000..e3fe3ad9ffce
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_main.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/anon_inodes.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/kdev_t.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gzvm_drv.h>
+
+struct platform_device *gzvm_debug_dev;
+
+/**
+ * gz_err_to_errno() - Convert geniezone return value to standard errno
+ *
+ * @err: Return value from geniezone function return
+ *
+ * Return: Standard errno
+ */
+int gz_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;
+}
+
+/**
+ * gzvm_dev_ioctl_check_extension() - Check if given capability is support
+ *				      or not
+ *
+ * @gzvm:
+ * @args: Pointer in u64 from userspace
+ *
+ * Return:
+ * * 0			- Support, no error
+ * * -EOPNOTSUPP	- Not support
+ * * -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)
+{
+	long ret = -ENOTTY;
+
+	switch (cmd) {
+	case GZVM_CREATE_VM:
+		ret = gzvm_dev_ioctl_create_vm(user_args);
+		break;
+	case GZVM_CHECK_EXTENSION:
+		if (!user_args)
+			return -EINVAL;
+		ret = gzvm_dev_ioctl_check_extension(NULL, user_args);
+		break;
+	default:
+		ret = -ENOTTY;
+	}
+
+	return ret;
+}
+
+static const struct file_operations gzvm_chardev_ops = {
+	.unlocked_ioctl = gzvm_dev_ioctl,
+	.llseek		= noop_llseek,
+};
+
+static struct miscdevice gzvm_dev = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = MODULE_NAME,
+	.fops = &gzvm_chardev_ops,
+};
+
+static int gzvm_drv_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (gzvm_arch_probe() != 0) {
+		dev_err(&pdev->dev, "Not found available conduit\n");
+		return -ENODEV;
+	}
+
+	ret = misc_register(&gzvm_dev);
+	if (ret)
+		return ret;
+	gzvm_debug_dev = pdev;
+
+	return 0;
+}
+
+static int gzvm_drv_remove(struct platform_device *pdev)
+{
+	destroy_all_vm();
+	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 = MODULE_NAME,
+		.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/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
new file mode 100644
index 000000000000..58471dd899fb
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
+#include <linux/kdev_t.h>
+#include <linux/kvm_host.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/gzvm_drv.h>
+
+static DEFINE_MUTEX(gzvm_list_lock);
+static LIST_HEAD(gzvm_list);
+
+/**
+ * gzvm_gfn_to_pfn_memslot() - Translate gfn (guest ipa) to pfn (host pa),
+ *			       result is in @pfn
+ *
+ * Leverage KVM's gfn_to_pfn_memslot(). Because gfn_to_pfn_memslot() needs
+ * kvm_memory_slot as parameter, this function populates necessary fileds
+ * for calling gfn_to_pfn_memslot().
+ *
+ * Return:
+ * * 0			- Succeed
+ * * -EFAULT		- Failed to convert
+ */
+static int gzvm_gfn_to_pfn_memslot(struct gzvm_memslot *memslot, u64 gfn, u64 *pfn)
+{
+	hfn_t __pfn;
+	struct kvm_memory_slot kvm_slot = {0};
+
+	kvm_slot.base_gfn = memslot->base_gfn;
+	kvm_slot.npages = memslot->npages;
+	kvm_slot.dirty_bitmap = NULL;
+	kvm_slot.userspace_addr = memslot->userspace_addr;
+	kvm_slot.flags = memslot->flags;
+	kvm_slot.id = memslot->slot_id;
+	kvm_slot.as_id = 0;
+
+	__pfn = gfn_to_pfn_memslot(&kvm_slot, gfn);
+	if (is_error_noslot_pfn(__pfn)) {
+		*pfn = 0;
+		return -EFAULT;
+	}
+
+	*pfn = __pfn;
+	return 0;
+}
+
+/**
+ * fill_constituents() - Populate pa to buffer until full
+ *
+ * Return: how many pages we've fill in, negative if error
+ */
+static int fill_constituents(struct mem_region_addr_range *consti,
+			     int *consti_cnt, int max_nr_consti, gfn_t gfn,
+			     u32 total_pages, struct gzvm_memslot *slot)
+{
+	int i, nr_pages;
+	hfn_t pfn, prev_pfn;
+	gfn_t gfn_end;
+
+	if (unlikely(total_pages == 0))
+		return -EINVAL;
+	gfn_end = gfn + total_pages;
+
+	/* entry 0 */
+	if (gzvm_gfn_to_pfn_memslot(slot, gfn, &pfn) != 0)
+		return -EFAULT;
+	consti[0].address = PFN_PHYS(pfn);
+	consti[0].pg_cnt = 1;
+	gfn++;
+	prev_pfn = pfn;
+	i = 0;
+	nr_pages = 1;
+	while (i < max_nr_consti && gfn < gfn_end) {
+		if (gzvm_gfn_to_pfn_memslot(slot, gfn, &pfn) != 0)
+			return -EFAULT;
+		if (pfn == (prev_pfn + 1)) {
+			consti[i].pg_cnt++;
+		} else {
+			i++;
+			if (i >= max_nr_consti)
+				break;
+			consti[i].address = PFN_PHYS(pfn);
+			consti[i].pg_cnt = 1;
+		}
+		prev_pfn = pfn;
+		gfn++;
+		nr_pages++;
+	}
+	if (i == max_nr_consti)
+		*consti_cnt = i;
+	else
+		*consti_cnt = (i + 1);
+
+	return nr_pages;
+}
+
+/* register_memslot_addr_range() - Register memory region to GZ */
+static int
+register_memslot_addr_range(struct gzvm *gzvm, struct gzvm_memslot *memslot)
+{
+	struct gzvm_memory_region_ranges *region;
+	u32 buf_size;
+	int max_nr_consti, remain_pages;
+	gfn_t gfn, gfn_end;
+
+	buf_size = PAGE_SIZE * 2;
+	region = alloc_pages_exact(buf_size, GFP_KERNEL);
+	if (!region)
+		return -ENOMEM;
+	max_nr_consti = (buf_size - sizeof(*region)) /
+			sizeof(struct mem_region_addr_range);
+
+	region->slot = memslot->slot_id;
+	remain_pages = memslot->npages;
+	gfn = memslot->base_gfn;
+	gfn_end = gfn + remain_pages;
+	while (gfn < gfn_end) {
+		int nr_pages;
+
+		nr_pages = fill_constituents(region->constituents,
+					     &region->constituent_cnt,
+					     max_nr_consti, gfn,
+					     remain_pages, memslot);
+		region->gpa = PFN_PHYS(gfn);
+		region->total_pages = nr_pages;
+
+		remain_pages -= nr_pages;
+		gfn += nr_pages;
+
+		if (gzvm_arch_set_memregion(gzvm->vm_id, buf_size,
+					    virt_to_phys(region))) {
+			dev_err(&gzvm_debug_dev->dev,
+				"Failed to register memregion to hypervisor\n");
+			free_pages_exact(region, buf_size);
+			return -EFAULT;
+		}
+	}
+	free_pages_exact(region, buf_size);
+	return 0;
+}
+
+/**
+ * gzvm_vm_ioctl_set_memory_region() - Set memory region of guest
+ *
+ * @mem: input memory region from user
+ *
+ * Return:
+ * * -EXIO		- memslot is out-of-range
+ * * -EFAULT		- Cannot find corresponding vma
+ * * -EINVAL		- region size and vma size does not match
+ */
+static int
+gzvm_vm_ioctl_set_memory_region(struct gzvm *gzvm,
+				struct gzvm_userspace_memory_region *mem)
+{
+	struct vm_area_struct *vma;
+	struct gzvm_memslot *memslot;
+	unsigned long size;
+	__u32 slot;
+
+	slot = mem->slot;
+	if (slot >= GZVM_MAX_MEM_REGION)
+		return -ENXIO;
+	memslot = &gzvm->memslot[slot];
+
+	vma = vma_lookup(gzvm->mm, mem->userspace_addr);
+	if (!vma)
+		return -EFAULT;
+
+	size = vma->vm_end - vma->vm_start;
+	if (size != mem->memory_size)
+		return -EINVAL;
+
+	memslot->base_gfn = __phys_to_pfn(mem->guest_phys_addr);
+	memslot->npages = size >> PAGE_SHIFT;
+	memslot->userspace_addr = mem->userspace_addr;
+	memslot->vma = vma;
+	memslot->flags = mem->flags;
+	memslot->slot_id = mem->slot;
+	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)
+{
+	long ret = -ENOTTY;
+	void __user *argp = (void __user *)arg;
+	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;
+
+		ret = -EFAULT;
+		if (copy_from_user(&userspace_mem, argp,
+				   sizeof(userspace_mem)))
+			goto out;
+		ret = gzvm_vm_ioctl_set_memory_region(gzvm, &userspace_mem);
+		break;
+	}
+	case GZVM_ENABLE_CAP: {
+		struct gzvm_enable_cap cap;
+
+		ret = -EFAULT;
+		if (copy_from_user(&cap, argp, sizeof(cap)))
+			goto out;
+
+		ret = gzvm_vm_ioctl_enable_cap(gzvm, &cap, argp);
+		break;
+	}
+	default:
+		ret = -ENOTTY;
+	}
+out:
+	return ret;
+}
+
+static void gzvm_destroy_vm(struct gzvm *gzvm)
+{
+	dev_info(&gzvm_debug_dev->dev,
+		 "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,
+	.unlocked_ioctl = gzvm_vm_ioctl,
+	.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();
+	if (ret < 0)
+		goto err;
+
+	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_info("VM-%u is created\n", gzvm->vm_id);
+
+	return gzvm;
+
+err:
+	kfree(gzvm);
+	return ERR_PTR(ret);
+}
+
+/**
+ * gzvm_dev_ioctl_create_vm - Create vm fd
+ *
+ * Return: fd of vm, negative if error
+ */
+int gzvm_dev_ioctl_create_vm(unsigned long vm_type)
+{
+	struct gzvm *gzvm;
+	int ret;
+
+	gzvm = gzvm_create_vm(vm_type);
+	if (IS_ERR(gzvm)) {
+		ret = PTR_ERR(gzvm);
+		goto error;
+	}
+
+	ret = anon_inode_getfd("gzvm-vm", &gzvm_vm_fops, gzvm,
+			       O_RDWR | O_CLOEXEC);
+	if (ret < 0)
+		goto error;
+
+error:
+	return ret;
+}
+
+void destroy_all_vm(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
new file mode 100644
index 000000000000..f2cfbf87c113
--- /dev/null
+++ b/include/linux/gzvm_drv.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __GZVM_DRV_H__
+#define __GZVM_DRV_H__
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/gzvm.h>
+
+#define MODULE_NAME	"gzvm"
+#define GZVM_VCPU_MMAP_SIZE  PAGE_SIZE
+#define INVALID_VM_ID   0xffff
+
+/**
+ * These are the efinitions 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)
+
+static inline gzvm_id_t get_vmid_from_tuple(unsigned int tuple)
+{
+	return (gzvm_id_t)(tuple >> 16);
+}
+
+/**
+ * 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
+
+/* 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 */
+	__u64 address;
+	/* the number of 4 kiB pages in the constituent memory region. */
+	__u32 pg_cnt;
+	__u32 reserved;
+};
+
+struct gzvm_memory_region_ranges {
+	__u32 slot;
+	__u32 constituent_cnt;
+	__u64 total_pages;
+	__u64 gpa;
+	struct mem_region_addr_range constituents[];
+};
+
+/* struct gzvm_memslot - VM's memory slot descriptor */
+struct gzvm_memslot {
+	u64 base_gfn;			/* begin of guest page frame */
+	unsigned long npages;		/* number of pages this slot covers */
+	unsigned long userspace_addr;	/* corresponding userspace va */
+	struct vm_area_struct *vma;	/* vma related to this userspace addr */
+	u32 flags;
+	u32 slot_id;
+};
+
+struct gzvm {
+	/* userspace tied to this vm */
+	struct mm_struct *mm;
+	struct gzvm_memslot memslot[GZVM_MAX_MEM_REGION];
+	/* lock for list_add*/
+	struct mutex lock;
+	struct list_head vm_list;
+	gzvm_id_t 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 gz_err_to_errno(unsigned long err);
+
+void destroy_all_vm(void);
+
+/* arch-dependant functions */
+int gzvm_arch_probe(void);
+int gzvm_arch_set_memregion(gzvm_id_t 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(void);
+int gzvm_arch_destroy_vm(gzvm_id_t vm_id);
+int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm,
+				  struct gzvm_enable_cap *cap,
+				  void __user *argp);
+
+extern struct platform_device *gzvm_debug_dev;
+
+#endif /* __GZVM_DRV_H__ */
diff --git a/include/uapi/asm-generic/gzvm_arch.h b/include/uapi/asm-generic/gzvm_arch.h
new file mode 100644
index 000000000000..c4cc12716c91
--- /dev/null
+++ b/include/uapi/asm-generic/gzvm_arch.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __ASM_GENERIC_GZVM_ARCH_H
+#define __ASM_GENERIC_GZVM_ARCH_H
+/* geniezone only supports aarch64 platform for now */
+
+#endif /* __ASM_GENERIC_GZVM_ARCH_H */
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
new file mode 100644
index 000000000000..1d157647a580
--- /dev/null
+++ b/include/uapi/linux/gzvm.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#ifndef __GZVM_H__
+#define __GZVM_H__
+
+#include <linux/const.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/* geniezone only supports aarch64 platform for now */
+#if defined(__aarch64__)
+#include <asm/gzvm_arch.h>
+#endif
+
+
+/**
+ * DOC: This file declares common data structure shared between userspace,
+ *	kernel space, and GZ.
+ */
+
+typedef __u16 gzvm_id_t;
+typedef __u16 gzvm_vcpu_id_t;
+
+/* GZVM ioctls */
+#define GZVM_IOC_MAGIC			0x92	/* gz */
+
+/* ioctls for /dev/gzvm fds */
+#define GZVM_GET_API_VERSION       _IO(GZVM_IOC_MAGIC,   0x00)
+#define GZVM_CREATE_VM             _IO(GZVM_IOC_MAGIC,   0x01)
+
+#define GZVM_CHECK_EXTENSION       _IO(GZVM_IOC_MAGIC,   0x03)
+
+/* ioctls for VM fds */
+/* for GZVM_SET_MEMORY_REGION */
+struct gzvm_memory_region {
+	__u32 slot;
+	__u32 flags;
+	__u64 guest_phys_addr;
+	__u64 memory_size; /* bytes */
+};
+
+#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 {
+	__u32 slot;
+	__u32 flags;
+	__u64 guest_phys_addr;
+	__u64 memory_size; /* bytes */
+	__u64 userspace_addr; /* start of the userspace allocated memory */
+};
+
+#define GZVM_SET_USER_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x46, \
+					struct gzvm_userspace_memory_region)
+
+/* for GZVM_IRQ_LINE */
+/* GZVM_IRQ_LINE irq field index values */
+#define GZVM_IRQ_VCPU2_SHIFT		28
+#define GZVM_IRQ_VCPU2_MASK		0xf
+#define GZVM_IRQ_TYPE_SHIFT		24
+#define GZVM_IRQ_TYPE_MASK		0xf
+#define GZVM_IRQ_VCPU_SHIFT		16
+#define GZVM_IRQ_VCPU_MASK		0xff
+#define GZVM_IRQ_NUM_SHIFT		0
+#define GZVM_IRQ_NUM_MASK		0xffff
+
+/* irq_type field */
+#define GZVM_IRQ_TYPE_CPU		0
+#define GZVM_IRQ_TYPE_SPI		1
+#define GZVM_IRQ_TYPE_PPI		2
+
+/* out-of-kernel GIC cpu interrupt injection irq_number field */
+#define GZVM_IRQ_CPU_IRQ		0
+#define GZVM_IRQ_CPU_FIQ		1
+
+/* ioctls for vcpu fds */
+#define GZVM_RUN                   _IO(GZVM_IOC_MAGIC,   0x80)
+
+/* for GZVM_ENABLE_CAP */
+struct gzvm_enable_cap {
+	/* in */
+	__u64 cap;
+	/* we have total 5 (8 - 3) registers can be used for additional args */
+	__u64 args[5];
+};
+
+#define GZVM_ENABLE_CAP            _IOW(GZVM_IOC_MAGIC,  0xa3, \
+					struct gzvm_enable_cap)
+
+#endif /* __GZVM_H__ */
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 4/7] virt: geniezone: Add vcpu support
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 10:36   ` Yi-De Wu
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

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 <yingshiuan.pan@mediatek.com>
Signed-off-by: Jerry Wang <ze-yu.wang@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 arch/arm64/geniezone/gzvm_arch.c        |  72 ++++++++
 arch/arm64/geniezone/gzvm_arch.h        |  24 +++
 arch/arm64/include/uapi/asm/gzvm_arch.h |  29 +++
 drivers/virt/geniezone/Makefile         |   3 +-
 drivers/virt/geniezone/gzvm_vcpu.c      | 234 ++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_vm.c        |  48 ++---
 include/linux/gzvm_drv.h                |  26 ++-
 include/uapi/linux/gzvm.h               | 130 +++++++++++--
 8 files changed, 519 insertions(+), 47 deletions(-)
 create mode 100644 drivers/virt/geniezone/gzvm_vcpu.c

diff --git a/arch/arm64/geniezone/gzvm_arch.c b/arch/arm64/geniezone/gzvm_arch.c
index 2fc76f7d440f..3c91f3f1ae50 100644
--- a/arch/arm64/geniezone/gzvm_arch.c
+++ b/arch/arm64/geniezone/gzvm_arch.c
@@ -187,3 +187,75 @@ int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap
 
 	return ret;
 }
+
+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;
+
+	/* reg id follows KVM's encoding */
+	switch (reg_id & GZVM_REG_ARM_COPROC_MASK) {
+	case GZVM_REG_ARM_CORE:
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	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(gzvm_id_t 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
+ * @run: Virtual address of vcpu->run
+ */
+int gzvm_arch_create_vcpu(gzvm_id_t 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/gzvm_arch.h b/arch/arm64/geniezone/gzvm_arch.h
index dd0b7b5f7c65..ecc24ff4e244 100644
--- a/arch/arm64/geniezone/gzvm_arch.h
+++ b/arch/arm64/geniezone/gzvm_arch.h
@@ -47,4 +47,28 @@ 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)
 
+static inline gzvm_id_t get_vmid_from_tuple(unsigned int tuple)
+{
+	return (gzvm_id_t)(tuple >> 16);
+}
+
+static inline gzvm_vcpu_id_t get_vcpuid_from_tuple(unsigned int tuple)
+{
+	return (gzvm_vcpu_id_t)(tuple & 0xffff);
+}
+
+static inline unsigned int
+assemble_vm_vcpu_tuple(gzvm_id_t vmid, gzvm_vcpu_id_t vcpuid)
+{
+	return ((unsigned int)vmid << 16 | vcpuid);
+}
+
+static inline void
+disassemble_vm_vcpu_tuple(unsigned int tuple, gzvm_id_t *vmid,
+			  gzvm_vcpu_id_t *vcpuid)
+{
+	*vmid = get_vmid_from_tuple(tuple);
+	*vcpuid = get_vcpuid_from_tuple(tuple);
+}
+
 #endif /* __GZVM_ARCH_H__ */
diff --git a/arch/arm64/include/uapi/asm/gzvm_arch.h b/arch/arm64/include/uapi/asm/gzvm_arch.h
index e7927f3dcb11..3e66087f635f 100644
--- a/arch/arm64/include/uapi/asm/gzvm_arch.h
+++ b/arch/arm64/include/uapi/asm/gzvm_arch.h
@@ -15,4 +15,33 @@
 #define GZVM_CAP_ARM_PVM_SET_PVMFW_IPA		0
 #define GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE		1
 
+/*
+ * Architecture specific registers are to be defined in arch headers and
+ * ORed with the arch identifier.
+ */
+#define GZVM_REG_ARM		0x4000000000000000ULL
+#define GZVM_REG_ARM64		0x6000000000000000ULL
+
+#define GZVM_REG_SIZE_SHIFT	52
+#define GZVM_REG_SIZE_MASK	0x00f0000000000000ULL
+#define GZVM_REG_SIZE_U8	0x0000000000000000ULL
+#define GZVM_REG_SIZE_U16	0x0010000000000000ULL
+#define GZVM_REG_SIZE_U32	0x0020000000000000ULL
+#define GZVM_REG_SIZE_U64	0x0030000000000000ULL
+#define GZVM_REG_SIZE_U128	0x0040000000000000ULL
+#define GZVM_REG_SIZE_U256	0x0050000000000000ULL
+#define GZVM_REG_SIZE_U512	0x0060000000000000ULL
+#define GZVM_REG_SIZE_U1024	0x0070000000000000ULL
+#define GZVM_REG_SIZE_U2048	0x0080000000000000ULL
+
+#define GZVM_REG_ARCH_MASK	0xff00000000000000ULL
+
+/* If you need to interpret the index values, here is the key: */
+#define GZVM_REG_ARM_COPROC_MASK	0x000000000FFF0000
+#define GZVM_REG_ARM_COPROC_SHIFT	16
+
+/* Normal registers are mapped as coprocessor 16. */
+#define GZVM_REG_ARM_CORE		(0x0010 << GZVM_REG_ARM_COPROC_SHIFT)
+#define GZVM_REG_ARM_CORE_REG(name)	(offsetof(struct gzvm_regs, name) / sizeof(__u32))
+
 #endif /* __GZVM_ARCH_H__ */
diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile
index 066efddc0b9c..8ebf2db0c970 100644
--- a/drivers/virt/geniezone/Makefile
+++ b/drivers/virt/geniezone/Makefile
@@ -6,5 +6,6 @@
 
 GZVM_DIR ?= ../../../drivers/virt/geniezone
 
-gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o
+gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.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..65b1a2372b30
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <asm/sysreg.h>
+#include <linux/anon_inodes.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gzvm_drv.h>
+
+/* 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(&reg, 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 (is_write) {
+		if (copy_from_user(&data, reg_addr, reg_size))
+			return -EFAULT;
+	}
+
+	ret = gzvm_arch_vcpu_update_one_reg(vcpu, reg.id, is_write, &data);
+
+	if (ret)
+		return ret;
+
+	if (!is_write) {
+		if (copy_to_user(reg_addr, &data, reg_size))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+/**
+ * gzvm_vcpu_run() - Handle vcpu run ioctl, entry point to guest and exit
+ *		     point from guest
+ * @argp: pointer to struct gzvm_vcpu_run in userspace
+ */
+static long gzvm_vcpu_run(struct gzvm_vcpu *vcpu, void * __user argp)
+{
+	bool need_userspace = false;
+	u64 exit_reason;
+
+	if (copy_from_user(vcpu->run, argp, sizeof(struct gzvm_vcpu_run)))
+		return -EFAULT;
+
+	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:
+			break;
+		case GZVM_EXIT_UNKNOWN:
+			fallthrough;
+		default:
+			dev_err(&gzvm_debug_dev->dev, "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))
+		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 = gzvm_vcpu_update_one_reg(vcpu, argp, false);
+		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 */
+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()
+ *
+ * @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 58471dd899fb..5542065e82c6 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -9,6 +9,7 @@
 #include <linux/kvm_host.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gzvm_drv.h>
 
@@ -59,9 +60,10 @@ static int fill_constituents(struct mem_region_addr_range *consti,
 			     int *consti_cnt, int max_nr_consti, gfn_t gfn,
 			     u32 total_pages, struct gzvm_memslot *slot)
 {
-	int i, nr_pages;
 	hfn_t pfn, prev_pfn;
 	gfn_t gfn_end;
+	int nr_pages = 1;
+	int i = 0;
 
 	if (unlikely(total_pages == 0))
 		return -EINVAL;
@@ -74,8 +76,6 @@ static int fill_constituents(struct mem_region_addr_range *consti,
 	consti[0].pg_cnt = 1;
 	gfn++;
 	prev_pfn = pfn;
-	i = 0;
-	nr_pages = 1;
 	while (i < max_nr_consti && gfn < gfn_end) {
 		if (gzvm_gfn_to_pfn_memslot(slot, gfn, &pfn) != 0)
 			return -EFAULT;
@@ -92,10 +92,10 @@ static int fill_constituents(struct mem_region_addr_range *consti,
 		gfn++;
 		nr_pages++;
 	}
-	if (i == max_nr_consti)
-		*consti_cnt = i;
-	else
-		*consti_cnt = (i + 1);
+
+	if (i != max_nr_consti)
+		i++;
+	*consti_cnt = i;
 
 	return nr_pages;
 }
@@ -105,9 +105,9 @@ static int
 register_memslot_addr_range(struct gzvm *gzvm, struct gzvm_memslot *memslot)
 {
 	struct gzvm_memory_region_ranges *region;
-	u32 buf_size;
-	int max_nr_consti, remain_pages;
 	gfn_t gfn, gfn_end;
+	int max_nr_consti, remain_pages;
+	u32 buf_size;
 
 	buf_size = PAGE_SIZE * 2;
 	region = alloc_pages_exact(buf_size, GFP_KERNEL);
@@ -206,6 +206,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;
 
@@ -242,6 +246,8 @@ static void gzvm_destroy_vm(struct gzvm *gzvm)
 
 	gzvm_arch_destroy_vm(gzvm->vm_id);
 
+	gzvm_destroy_vcpus(gzvm);
+
 	mutex_lock(&gzvm_list_lock);
 	list_del(&gzvm->vm_list);
 	mutex_unlock(&gzvm_list_lock);
@@ -275,8 +281,10 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
 		return ERR_PTR(-ENOMEM);
 
 	ret = gzvm_arch_create_vm();
-	if (ret < 0)
-		goto err;
+	if (ret < 0) {
+		kfree(gzvm);
+		return ERR_PTR(ret);
+	}
 
 	gzvm->vm_id = ret;
 	gzvm->mm = current->mm;
@@ -289,10 +297,6 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
 	pr_info("VM-%u is created\n", gzvm->vm_id);
 
 	return gzvm;
-
-err:
-	kfree(gzvm);
-	return ERR_PTR(ret);
 }
 
 /**
@@ -306,18 +310,14 @@ int gzvm_dev_ioctl_create_vm(unsigned long vm_type)
 	int ret;
 
 	gzvm = gzvm_create_vm(vm_type);
-	if (IS_ERR(gzvm)) {
-		ret = PTR_ERR(gzvm);
-		goto error;
-	}
+	if (IS_ERR(gzvm))
+		return PTR_ERR(gzvm);
 
 	ret = anon_inode_getfd("gzvm-vm", &gzvm_vm_fops, gzvm,
 			       O_RDWR | O_CLOEXEC);
-	if (ret < 0)
-		goto error;
-
-error:
-	return ret;
+	if (ret)
+		return ret;
+	return 0;
 }
 
 void destroy_all_vm(void)
diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h
index f2cfbf87c113..5736ddf97741 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -26,18 +26,15 @@
 #define ERR_NOT_IMPLEMENTED     (-27)
 #define ERR_FAULT               (-40)
 
-static inline gzvm_id_t get_vmid_from_tuple(unsigned int tuple)
-{
-	return (gzvm_id_t)(tuple >> 16);
-}
-
-/**
+/*
  * 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 */
@@ -65,7 +62,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];
@@ -82,6 +88,8 @@ int gz_err_to_errno(unsigned long err);
 
 void destroy_all_vm(void);
 
+void gzvm_destroy_vcpus(struct gzvm *gzvm);
+
 /* arch-dependant functions */
 int gzvm_arch_probe(void);
 int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
@@ -92,6 +100,12 @@ int gzvm_arch_destroy_vm(gzvm_id_t vm_id);
 int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm,
 				  struct gzvm_enable_cap *cap,
 				  void __user *argp);
+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(gzvm_id_t vm_id, int vcpuid, void *run);
+int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason);
+int gzvm_arch_destroy_vcpu(gzvm_id_t vm_id, int vcpuid);
 
 extern struct platform_device *gzvm_debug_dev;
 
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
index 1d157647a580..6462961299eb 100644
--- a/include/uapi/linux/gzvm.h
+++ b/include/uapi/linux/gzvm.h
@@ -3,6 +3,12 @@
  * 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__
 
@@ -16,11 +22,6 @@
 #endif
 
 
-/**
- * DOC: This file declares common data structure shared between userspace,
- *	kernel space, and GZ.
- */
-
 typedef __u16 gzvm_id_t;
 typedef __u16 gzvm_vcpu_id_t;
 
@@ -44,26 +45,30 @@ 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.
+/**
+ * for irqfd, GZVM_CREATE_VCPU receives as a parameter the vcpu slot,
+ * and returns a vcpu fd.
  */
 #define GZVM_CREATE_VCPU           _IO(GZVM_IOC_MAGIC,   0x41)
 
+#define GZVM_ENABLE_CAP            _IOW(GZVM_IOC_MAGIC,  0xa3, \
+					struct gzvm_enable_cap)
+
 /* for GZVM_SET_USER_MEMORY_REGION */
 struct gzvm_userspace_memory_region {
 	__u32 slot;
 	__u32 flags;
 	__u64 guest_phys_addr;
-	__u64 memory_size; /* bytes */
-	__u64 userspace_addr; /* start of the userspace allocated memory */
+	/* bytes */
+	__u64 memory_size;
+	/* start of the userspace allocated memory */
+	__u64 userspace_addr;
 };
 
 #define GZVM_SET_USER_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x46, \
 					struct gzvm_userspace_memory_region)
 
-/* for GZVM_IRQ_LINE */
-/* GZVM_IRQ_LINE irq field index values */
+/* for GZVM_IRQ_LINE, irq field index values */
 #define GZVM_IRQ_VCPU2_SHIFT		28
 #define GZVM_IRQ_VCPU2_MASK		0xf
 #define GZVM_IRQ_TYPE_SHIFT		24
@@ -85,15 +90,108 @@ 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,
+	GZVM_EXIT_HYPERCALL,
+	GZVM_EXIT_IRQ,
+	GZVM_EXIT_EXCEPTION,
+	GZVM_EXIT_DEBUG,
+	GZVM_EXIT_FAIL_ENTRY,
+	GZVM_EXIT_INTERNAL_ERROR,
+	GZVM_EXIT_SYSTEM_EVENT,
+	GZVM_EXIT_SHUTDOWN,
+};
+
+/**
+ * struct gzvm_cpu_run: Same purpose as kvm_run, this struct is
+ *			shared between userspace, kernel and
+ *			GenieZone hypervisor
+ *
+ * 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 */
+			__u64 phys_addr;
+			__u8 data[8];
+			/* from ESR_EL2 as */
+			__u64 size;
+			/* from ESR_EL2 */
+			__u32 reg_nr;
+			/* from ESR_EL2 */
+			__u8 is_write;
+		} mmio;
+		/* GZVM_EXIT_FAIL_ENTRY */
+		struct {
+			__u64 hardware_entry_failure_reason;
+			__u32 cpu;
+		} fail_entry;
+		/* GZVM_EXIT_EXCEPTION */
+		struct {
+			__u32 exception;
+			__u32 error_code;
+		} exception;
+		/* GZVM_EXIT_HYPERCALL */
+		struct {
+			__u64 args[8];	/* in-out */
+		} hypercall;
+		/* GZVM_EXIT_INTERNAL_ERROR */
+		struct {
+			__u32 suberror;
+			__u32 ndata;
+			__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
+			__u32 type;
+			__u32 ndata;
+			__u64 data[16];
+		} system_event;
+		/* Fix the size of the union. */
+		char padding[256];
+	};
+};
+
 /* for GZVM_ENABLE_CAP */
 struct gzvm_enable_cap {
-	/* in */
-	__u64 cap;
-	/* we have total 5 (8 - 3) registers can be used for additional args */
-	__u64 args[5];
+			 /* in */
+			__u64 cap;
+			/**
+			 * we have total 5 (8 - 3) registers can be used for
+			 * additional args
+			 */
+			 __u64 args[5];
 };
 
 #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__ */
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 4/7] virt: geniezone: Add vcpu support
@ 2023-04-28 10:36   ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

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 <yingshiuan.pan@mediatek.com>
Signed-off-by: Jerry Wang <ze-yu.wang@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 arch/arm64/geniezone/gzvm_arch.c        |  72 ++++++++
 arch/arm64/geniezone/gzvm_arch.h        |  24 +++
 arch/arm64/include/uapi/asm/gzvm_arch.h |  29 +++
 drivers/virt/geniezone/Makefile         |   3 +-
 drivers/virt/geniezone/gzvm_vcpu.c      | 234 ++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_vm.c        |  48 ++---
 include/linux/gzvm_drv.h                |  26 ++-
 include/uapi/linux/gzvm.h               | 130 +++++++++++--
 8 files changed, 519 insertions(+), 47 deletions(-)
 create mode 100644 drivers/virt/geniezone/gzvm_vcpu.c

diff --git a/arch/arm64/geniezone/gzvm_arch.c b/arch/arm64/geniezone/gzvm_arch.c
index 2fc76f7d440f..3c91f3f1ae50 100644
--- a/arch/arm64/geniezone/gzvm_arch.c
+++ b/arch/arm64/geniezone/gzvm_arch.c
@@ -187,3 +187,75 @@ int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap
 
 	return ret;
 }
+
+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;
+
+	/* reg id follows KVM's encoding */
+	switch (reg_id & GZVM_REG_ARM_COPROC_MASK) {
+	case GZVM_REG_ARM_CORE:
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	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(gzvm_id_t 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
+ * @run: Virtual address of vcpu->run
+ */
+int gzvm_arch_create_vcpu(gzvm_id_t 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/gzvm_arch.h b/arch/arm64/geniezone/gzvm_arch.h
index dd0b7b5f7c65..ecc24ff4e244 100644
--- a/arch/arm64/geniezone/gzvm_arch.h
+++ b/arch/arm64/geniezone/gzvm_arch.h
@@ -47,4 +47,28 @@ 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)
 
+static inline gzvm_id_t get_vmid_from_tuple(unsigned int tuple)
+{
+	return (gzvm_id_t)(tuple >> 16);
+}
+
+static inline gzvm_vcpu_id_t get_vcpuid_from_tuple(unsigned int tuple)
+{
+	return (gzvm_vcpu_id_t)(tuple & 0xffff);
+}
+
+static inline unsigned int
+assemble_vm_vcpu_tuple(gzvm_id_t vmid, gzvm_vcpu_id_t vcpuid)
+{
+	return ((unsigned int)vmid << 16 | vcpuid);
+}
+
+static inline void
+disassemble_vm_vcpu_tuple(unsigned int tuple, gzvm_id_t *vmid,
+			  gzvm_vcpu_id_t *vcpuid)
+{
+	*vmid = get_vmid_from_tuple(tuple);
+	*vcpuid = get_vcpuid_from_tuple(tuple);
+}
+
 #endif /* __GZVM_ARCH_H__ */
diff --git a/arch/arm64/include/uapi/asm/gzvm_arch.h b/arch/arm64/include/uapi/asm/gzvm_arch.h
index e7927f3dcb11..3e66087f635f 100644
--- a/arch/arm64/include/uapi/asm/gzvm_arch.h
+++ b/arch/arm64/include/uapi/asm/gzvm_arch.h
@@ -15,4 +15,33 @@
 #define GZVM_CAP_ARM_PVM_SET_PVMFW_IPA		0
 #define GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE		1
 
+/*
+ * Architecture specific registers are to be defined in arch headers and
+ * ORed with the arch identifier.
+ */
+#define GZVM_REG_ARM		0x4000000000000000ULL
+#define GZVM_REG_ARM64		0x6000000000000000ULL
+
+#define GZVM_REG_SIZE_SHIFT	52
+#define GZVM_REG_SIZE_MASK	0x00f0000000000000ULL
+#define GZVM_REG_SIZE_U8	0x0000000000000000ULL
+#define GZVM_REG_SIZE_U16	0x0010000000000000ULL
+#define GZVM_REG_SIZE_U32	0x0020000000000000ULL
+#define GZVM_REG_SIZE_U64	0x0030000000000000ULL
+#define GZVM_REG_SIZE_U128	0x0040000000000000ULL
+#define GZVM_REG_SIZE_U256	0x0050000000000000ULL
+#define GZVM_REG_SIZE_U512	0x0060000000000000ULL
+#define GZVM_REG_SIZE_U1024	0x0070000000000000ULL
+#define GZVM_REG_SIZE_U2048	0x0080000000000000ULL
+
+#define GZVM_REG_ARCH_MASK	0xff00000000000000ULL
+
+/* If you need to interpret the index values, here is the key: */
+#define GZVM_REG_ARM_COPROC_MASK	0x000000000FFF0000
+#define GZVM_REG_ARM_COPROC_SHIFT	16
+
+/* Normal registers are mapped as coprocessor 16. */
+#define GZVM_REG_ARM_CORE		(0x0010 << GZVM_REG_ARM_COPROC_SHIFT)
+#define GZVM_REG_ARM_CORE_REG(name)	(offsetof(struct gzvm_regs, name) / sizeof(__u32))
+
 #endif /* __GZVM_ARCH_H__ */
diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile
index 066efddc0b9c..8ebf2db0c970 100644
--- a/drivers/virt/geniezone/Makefile
+++ b/drivers/virt/geniezone/Makefile
@@ -6,5 +6,6 @@
 
 GZVM_DIR ?= ../../../drivers/virt/geniezone
 
-gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o
+gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.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..65b1a2372b30
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <asm/sysreg.h>
+#include <linux/anon_inodes.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gzvm_drv.h>
+
+/* 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(&reg, 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 (is_write) {
+		if (copy_from_user(&data, reg_addr, reg_size))
+			return -EFAULT;
+	}
+
+	ret = gzvm_arch_vcpu_update_one_reg(vcpu, reg.id, is_write, &data);
+
+	if (ret)
+		return ret;
+
+	if (!is_write) {
+		if (copy_to_user(reg_addr, &data, reg_size))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+/**
+ * gzvm_vcpu_run() - Handle vcpu run ioctl, entry point to guest and exit
+ *		     point from guest
+ * @argp: pointer to struct gzvm_vcpu_run in userspace
+ */
+static long gzvm_vcpu_run(struct gzvm_vcpu *vcpu, void * __user argp)
+{
+	bool need_userspace = false;
+	u64 exit_reason;
+
+	if (copy_from_user(vcpu->run, argp, sizeof(struct gzvm_vcpu_run)))
+		return -EFAULT;
+
+	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:
+			break;
+		case GZVM_EXIT_UNKNOWN:
+			fallthrough;
+		default:
+			dev_err(&gzvm_debug_dev->dev, "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))
+		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 = gzvm_vcpu_update_one_reg(vcpu, argp, false);
+		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 */
+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()
+ *
+ * @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 58471dd899fb..5542065e82c6 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -9,6 +9,7 @@
 #include <linux/kvm_host.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gzvm_drv.h>
 
@@ -59,9 +60,10 @@ static int fill_constituents(struct mem_region_addr_range *consti,
 			     int *consti_cnt, int max_nr_consti, gfn_t gfn,
 			     u32 total_pages, struct gzvm_memslot *slot)
 {
-	int i, nr_pages;
 	hfn_t pfn, prev_pfn;
 	gfn_t gfn_end;
+	int nr_pages = 1;
+	int i = 0;
 
 	if (unlikely(total_pages == 0))
 		return -EINVAL;
@@ -74,8 +76,6 @@ static int fill_constituents(struct mem_region_addr_range *consti,
 	consti[0].pg_cnt = 1;
 	gfn++;
 	prev_pfn = pfn;
-	i = 0;
-	nr_pages = 1;
 	while (i < max_nr_consti && gfn < gfn_end) {
 		if (gzvm_gfn_to_pfn_memslot(slot, gfn, &pfn) != 0)
 			return -EFAULT;
@@ -92,10 +92,10 @@ static int fill_constituents(struct mem_region_addr_range *consti,
 		gfn++;
 		nr_pages++;
 	}
-	if (i == max_nr_consti)
-		*consti_cnt = i;
-	else
-		*consti_cnt = (i + 1);
+
+	if (i != max_nr_consti)
+		i++;
+	*consti_cnt = i;
 
 	return nr_pages;
 }
@@ -105,9 +105,9 @@ static int
 register_memslot_addr_range(struct gzvm *gzvm, struct gzvm_memslot *memslot)
 {
 	struct gzvm_memory_region_ranges *region;
-	u32 buf_size;
-	int max_nr_consti, remain_pages;
 	gfn_t gfn, gfn_end;
+	int max_nr_consti, remain_pages;
+	u32 buf_size;
 
 	buf_size = PAGE_SIZE * 2;
 	region = alloc_pages_exact(buf_size, GFP_KERNEL);
@@ -206,6 +206,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;
 
@@ -242,6 +246,8 @@ static void gzvm_destroy_vm(struct gzvm *gzvm)
 
 	gzvm_arch_destroy_vm(gzvm->vm_id);
 
+	gzvm_destroy_vcpus(gzvm);
+
 	mutex_lock(&gzvm_list_lock);
 	list_del(&gzvm->vm_list);
 	mutex_unlock(&gzvm_list_lock);
@@ -275,8 +281,10 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
 		return ERR_PTR(-ENOMEM);
 
 	ret = gzvm_arch_create_vm();
-	if (ret < 0)
-		goto err;
+	if (ret < 0) {
+		kfree(gzvm);
+		return ERR_PTR(ret);
+	}
 
 	gzvm->vm_id = ret;
 	gzvm->mm = current->mm;
@@ -289,10 +297,6 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
 	pr_info("VM-%u is created\n", gzvm->vm_id);
 
 	return gzvm;
-
-err:
-	kfree(gzvm);
-	return ERR_PTR(ret);
 }
 
 /**
@@ -306,18 +310,14 @@ int gzvm_dev_ioctl_create_vm(unsigned long vm_type)
 	int ret;
 
 	gzvm = gzvm_create_vm(vm_type);
-	if (IS_ERR(gzvm)) {
-		ret = PTR_ERR(gzvm);
-		goto error;
-	}
+	if (IS_ERR(gzvm))
+		return PTR_ERR(gzvm);
 
 	ret = anon_inode_getfd("gzvm-vm", &gzvm_vm_fops, gzvm,
 			       O_RDWR | O_CLOEXEC);
-	if (ret < 0)
-		goto error;
-
-error:
-	return ret;
+	if (ret)
+		return ret;
+	return 0;
 }
 
 void destroy_all_vm(void)
diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h
index f2cfbf87c113..5736ddf97741 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -26,18 +26,15 @@
 #define ERR_NOT_IMPLEMENTED     (-27)
 #define ERR_FAULT               (-40)
 
-static inline gzvm_id_t get_vmid_from_tuple(unsigned int tuple)
-{
-	return (gzvm_id_t)(tuple >> 16);
-}
-
-/**
+/*
  * 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 */
@@ -65,7 +62,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];
@@ -82,6 +88,8 @@ int gz_err_to_errno(unsigned long err);
 
 void destroy_all_vm(void);
 
+void gzvm_destroy_vcpus(struct gzvm *gzvm);
+
 /* arch-dependant functions */
 int gzvm_arch_probe(void);
 int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
@@ -92,6 +100,12 @@ int gzvm_arch_destroy_vm(gzvm_id_t vm_id);
 int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm,
 				  struct gzvm_enable_cap *cap,
 				  void __user *argp);
+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(gzvm_id_t vm_id, int vcpuid, void *run);
+int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason);
+int gzvm_arch_destroy_vcpu(gzvm_id_t vm_id, int vcpuid);
 
 extern struct platform_device *gzvm_debug_dev;
 
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
index 1d157647a580..6462961299eb 100644
--- a/include/uapi/linux/gzvm.h
+++ b/include/uapi/linux/gzvm.h
@@ -3,6 +3,12 @@
  * 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__
 
@@ -16,11 +22,6 @@
 #endif
 
 
-/**
- * DOC: This file declares common data structure shared between userspace,
- *	kernel space, and GZ.
- */
-
 typedef __u16 gzvm_id_t;
 typedef __u16 gzvm_vcpu_id_t;
 
@@ -44,26 +45,30 @@ 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.
+/**
+ * for irqfd, GZVM_CREATE_VCPU receives as a parameter the vcpu slot,
+ * and returns a vcpu fd.
  */
 #define GZVM_CREATE_VCPU           _IO(GZVM_IOC_MAGIC,   0x41)
 
+#define GZVM_ENABLE_CAP            _IOW(GZVM_IOC_MAGIC,  0xa3, \
+					struct gzvm_enable_cap)
+
 /* for GZVM_SET_USER_MEMORY_REGION */
 struct gzvm_userspace_memory_region {
 	__u32 slot;
 	__u32 flags;
 	__u64 guest_phys_addr;
-	__u64 memory_size; /* bytes */
-	__u64 userspace_addr; /* start of the userspace allocated memory */
+	/* bytes */
+	__u64 memory_size;
+	/* start of the userspace allocated memory */
+	__u64 userspace_addr;
 };
 
 #define GZVM_SET_USER_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x46, \
 					struct gzvm_userspace_memory_region)
 
-/* for GZVM_IRQ_LINE */
-/* GZVM_IRQ_LINE irq field index values */
+/* for GZVM_IRQ_LINE, irq field index values */
 #define GZVM_IRQ_VCPU2_SHIFT		28
 #define GZVM_IRQ_VCPU2_MASK		0xf
 #define GZVM_IRQ_TYPE_SHIFT		24
@@ -85,15 +90,108 @@ 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,
+	GZVM_EXIT_HYPERCALL,
+	GZVM_EXIT_IRQ,
+	GZVM_EXIT_EXCEPTION,
+	GZVM_EXIT_DEBUG,
+	GZVM_EXIT_FAIL_ENTRY,
+	GZVM_EXIT_INTERNAL_ERROR,
+	GZVM_EXIT_SYSTEM_EVENT,
+	GZVM_EXIT_SHUTDOWN,
+};
+
+/**
+ * struct gzvm_cpu_run: Same purpose as kvm_run, this struct is
+ *			shared between userspace, kernel and
+ *			GenieZone hypervisor
+ *
+ * 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 */
+			__u64 phys_addr;
+			__u8 data[8];
+			/* from ESR_EL2 as */
+			__u64 size;
+			/* from ESR_EL2 */
+			__u32 reg_nr;
+			/* from ESR_EL2 */
+			__u8 is_write;
+		} mmio;
+		/* GZVM_EXIT_FAIL_ENTRY */
+		struct {
+			__u64 hardware_entry_failure_reason;
+			__u32 cpu;
+		} fail_entry;
+		/* GZVM_EXIT_EXCEPTION */
+		struct {
+			__u32 exception;
+			__u32 error_code;
+		} exception;
+		/* GZVM_EXIT_HYPERCALL */
+		struct {
+			__u64 args[8];	/* in-out */
+		} hypercall;
+		/* GZVM_EXIT_INTERNAL_ERROR */
+		struct {
+			__u32 suberror;
+			__u32 ndata;
+			__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
+			__u32 type;
+			__u32 ndata;
+			__u64 data[16];
+		} system_event;
+		/* Fix the size of the union. */
+		char padding[256];
+	};
+};
+
 /* for GZVM_ENABLE_CAP */
 struct gzvm_enable_cap {
-	/* in */
-	__u64 cap;
-	/* we have total 5 (8 - 3) registers can be used for additional args */
-	__u64 args[5];
+			 /* in */
+			__u64 cap;
+			/**
+			 * we have total 5 (8 - 3) registers can be used for
+			 * additional args
+			 */
+			 __u64 args[5];
 };
 
 #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__ */
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 10:36   ` Yi-De Wu
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

Enable GenieZone to handle virtual interrupt injection request.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 arch/arm64/geniezone/Makefile       |  2 +-
 arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
 arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
 arch/arm64/geniezone/gzvm_irqchip.c | 88 +++++++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_vm.c    | 75 ++++++++++++++++++++++++
 include/linux/gzvm_drv.h            |  4 ++
 include/uapi/linux/gzvm.h           | 38 ++++++++++++-
 7 files changed, 235 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c

diff --git a/arch/arm64/geniezone/Makefile b/arch/arm64/geniezone/Makefile
index 5720c076d73c..82af1ed870bc 100644
--- a/arch/arm64/geniezone/Makefile
+++ b/arch/arm64/geniezone/Makefile
@@ -4,6 +4,6 @@
 #
 include $(srctree)/drivers/virt/geniezone/Makefile
 
-gzvm-y += gzvm_arch.o
+gzvm-y += gzvm_arch.o gzvm_irqchip.o
 
 obj-$(CONFIG_MTK_GZVM) += gzvm.o
diff --git a/arch/arm64/geniezone/gzvm_arch.c b/arch/arm64/geniezone/gzvm_arch.c
index 3c91f3f1ae50..16ab5d4fd5b8 100644
--- a/arch/arm64/geniezone/gzvm_arch.c
+++ b/arch/arm64/geniezone/gzvm_arch.c
@@ -16,11 +16,10 @@
  *
  * Return: The wrapper helps caller to convert geniezone errno to Linux errno.
  */
-static 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)
+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 gz_err_to_errno(res->a0);
@@ -259,3 +258,18 @@ int gzvm_arch_create_vcpu(gzvm_id_t vm_id, int vcpuid, void *run)
 
 	return ret;
 }
+
+int gzvm_arch_create_device(gzvm_id_t vm_id, struct gzvm_create_device *gzvm_dev)
+{
+	struct arm_smccc_res res;
+
+	return gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_DEVICE, vm_id,
+				    virt_to_phys(gzvm_dev), 0, 0, 0, 0, 0, &res);
+}
+
+int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
+			 u32 irq, bool level)
+{
+	/* default use spi */
+	return gzvm_vgic_inject_spi(gzvm, vcpu_idx, irq, level);
+}
diff --git a/arch/arm64/geniezone/gzvm_arch.h b/arch/arm64/geniezone/gzvm_arch.h
index ecc24ff4e244..205bd0901333 100644
--- a/arch/arm64/geniezone/gzvm_arch.h
+++ b/arch/arm64/geniezone/gzvm_arch.h
@@ -71,4 +71,15 @@ disassemble_vm_vcpu_tuple(unsigned int tuple, gzvm_id_t *vmid,
 	*vcpuid = get_vcpuid_from_tuple(tuple);
 }
 
+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);
+
+void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu);
+int gzvm_vgic_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
+			 u32 irq, bool level);
+int gzvm_vgic_inject_spi(struct gzvm *gzvm, unsigned int vcpu_idx,
+			 u32 spi_irq, bool level);
+
 #endif /* __GZVM_ARCH_H__ */
diff --git a/arch/arm64/geniezone/gzvm_irqchip.c b/arch/arm64/geniezone/gzvm_irqchip.c
new file mode 100644
index 000000000000..c46bd34fee1b
--- /dev/null
+++ b/arch/arm64/geniezone/gzvm_irqchip.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/irqchip/arm-gic-v3.h>
+#include <kvm/arm_vgic.h>
+
+#include <linux/gzvm.h>
+#include <linux/gzvm_drv.h>
+#include "gzvm_arch.h"
+
+/**
+ * gzvm_sync_vgic_state() - Check all LRs synced from gz hypervisor
+ *
+ * Traverse all LRs, see if any EOIed vint, notify_acked_irq if any.
+ * GZ does not fold/unfold everytime KVM_RUN, so we have to traverse all saved
+ * LRs. It will not takes much more time comparing to fold/unfold everytime
+ * GZVM_RUN, because there are only few LRs.
+ */
+void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu)
+{
+}
+
+/* is_irq_valid() - Check the irq number and irq_type are matched */
+static bool is_irq_valid(u32 irq, u32 irq_type)
+{
+	switch (irq_type) {
+	case GZVM_IRQ_TYPE_CPU:
+		/*  0 ~ 15: SGI */
+		if (likely(irq <= GZVM_IRQ_CPU_FIQ))
+			return true;
+		break;
+	case GZVM_IRQ_TYPE_PPI:
+		/* 16 ~ 31: PPI */
+		if (likely(irq >= VGIC_NR_SGIS && irq < VGIC_NR_PRIVATE_IRQS))
+			return true;
+		break;
+	case GZVM_IRQ_TYPE_SPI:
+		/* 32 ~ : SPT */
+		if (likely(irq >= VGIC_NR_PRIVATE_IRQS))
+			return true;
+		break;
+	default:
+		return false;
+	}
+	return false;
+}
+
+/**
+ * gzvm_vgic_inject_irq() - Inject virtual interrupt to a VM
+ * @vcpu_idx: vcpu index, only valid if PPI
+ * @irq: irq number
+ * @level: 1 if true else 0
+ */
+int gzvm_vgic_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
+			 u32 irq, bool level)
+{
+	unsigned long a1 = assemble_vm_vcpu_tuple(gzvm->vm_id, vcpu_idx);
+	struct arm_smccc_res res;
+
+	if (!unlikely(is_irq_valid(irq, irq_type)))
+		return -EINVAL;
+
+	gzvm_hypcall_wrapper(MT_HVC_GZVM_IRQ_LINE, a1, irq, level,
+			     0, 0, 0, 0, &res);
+	if (res.a0) {
+		pr_err("Failed to set IRQ level (%d) to irq#%u on vcpu %d with ret=%d\n",
+		       level, irq, vcpu_idx, (int)res.a0);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+/**
+ * gzvm_vgic_inject_spi() - Inject virtual spi interrupt
+ *
+ * @spi_irq: This is spi interrupt number (starts from 0 instead of 32)
+ *
+ * Return 0 if succeed else other negative values indicating each errors
+ */
+int gzvm_vgic_inject_spi(struct gzvm *gzvm, unsigned int vcpu_idx,
+			 u32 spi_irq, bool level)
+{
+	return gzvm_vgic_inject_irq(gzvm, 0, GZVM_IRQ_TYPE_SPI,
+				    spi_irq + VGIC_NR_PRIVATE_IRQS, level);
+}
diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
index 5542065e82c6..a5444541b745 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -186,6 +186,67 @@ gzvm_vm_ioctl_set_memory_region(struct gzvm *gzvm,
 	return register_memslot_addr_range(gzvm, memslot);
 }
 
+static int gzvm_vm_ioctl_irq_line(struct gzvm *gzvm,
+				  struct gzvm_irq_level *irq_level)
+{
+	u32 irq = irq_level->irq;
+	unsigned int irq_type, vcpu_idx, irq_num;
+	bool level = irq_level->level;
+
+	irq_type = (irq >> GZVM_IRQ_TYPE_SHIFT) & GZVM_IRQ_TYPE_MASK;
+	vcpu_idx = (irq >> GZVM_IRQ_VCPU_SHIFT) & GZVM_IRQ_VCPU_MASK;
+	vcpu_idx += ((irq >> GZVM_IRQ_VCPU2_SHIFT) & GZVM_IRQ_VCPU2_MASK) *
+		(GZVM_IRQ_VCPU_MASK + 1);
+	irq_num = (irq >> GZVM_IRQ_NUM_SHIFT) & GZVM_IRQ_NUM_MASK;
+
+	return gzvm_arch_inject_irq(gzvm, vcpu_idx, irq_num, irq_type, level);
+}
+
+static int gzvm_vm_ioctl_create_device(struct gzvm *gzvm, void __user *argp)
+{
+	struct gzvm_create_device *gzvm_dev;
+	void *dev_data = NULL;
+	int ret;
+
+	gzvm_dev = (struct gzvm_create_device *)alloc_pages_exact(PAGE_SIZE,
+								  GFP_KERNEL);
+	if (!gzvm_dev)
+		return -ENOMEM;
+	if (copy_from_user(gzvm_dev, argp, sizeof(*gzvm_dev))) {
+		ret = -EFAULT;
+		goto err_free_dev;
+	}
+
+	if (gzvm_dev->attr_addr != 0 && gzvm_dev->attr_size != 0) {
+		size_t attr_size = gzvm_dev->attr_size;
+		void __user *attr_addr = (void __user *)gzvm_dev->attr_addr;
+
+		/* Size of device specific data should not be over a page. */
+		if (attr_size > PAGE_SIZE)
+			return -EINVAL;
+
+		dev_data = alloc_pages_exact(attr_size, GFP_KERNEL);
+		if (!dev_data) {
+			ret = -ENOMEM;
+			goto err_free_dev;
+		}
+
+		if (copy_from_user(dev_data, attr_addr, attr_size)) {
+			ret = -EFAULT;
+			goto err_free_dev_data;
+		}
+		gzvm_dev->attr_addr = virt_to_phys(dev_data);
+	}
+
+	ret = gzvm_arch_create_device(gzvm->vm_id, gzvm_dev);
+err_free_dev_data:
+	if (dev_data)
+		free_pages_exact(dev_data, 0);
+err_free_dev:
+	free_pages_exact(gzvm_dev, 0);
+	return ret;
+}
+
 static int gzvm_vm_ioctl_enable_cap(struct gzvm *gzvm,
 				    struct gzvm_enable_cap *cap,
 				    void __user *argp)
@@ -220,6 +281,20 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl,
 		ret = gzvm_vm_ioctl_set_memory_region(gzvm, &userspace_mem);
 		break;
 	}
+	case GZVM_IRQ_LINE: {
+		struct gzvm_irq_level irq_event;
+
+		ret = -EFAULT;
+		if (copy_from_user(&irq_event, argp, sizeof(irq_event)))
+			goto out;
+
+		ret = gzvm_vm_ioctl_irq_line(gzvm, &irq_event);
+		break;
+	}
+	case GZVM_CREATE_DEVICE: {
+		ret = gzvm_vm_ioctl_create_device(gzvm, argp);
+		break;
+	}
 	case GZVM_ENABLE_CAP: {
 		struct gzvm_enable_cap cap;
 
diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h
index 5736ddf97741..1e7c81597e9a 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -107,6 +107,10 @@ int gzvm_arch_create_vcpu(gzvm_id_t vm_id, int vcpuid, void *run);
 int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason);
 int gzvm_arch_destroy_vcpu(gzvm_id_t vm_id, int vcpuid);
 
+int gzvm_arch_create_device(gzvm_id_t vm_id, struct gzvm_create_device *gzvm_dev);
+int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
+			 u32 irq, bool level);
+
 extern struct platform_device *gzvm_debug_dev;
 
 #endif /* __GZVM_DRV_H__ */
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
index 6462961299eb..2f56a53efb27 100644
--- a/include/uapi/linux/gzvm.h
+++ b/include/uapi/linux/gzvm.h
@@ -87,7 +87,43 @@ struct gzvm_userspace_memory_region {
 #define GZVM_IRQ_CPU_IRQ		0
 #define GZVM_IRQ_CPU_FIQ		1
 
-/* ioctls for vcpu fds */
+struct gzvm_irq_level {
+	union {
+		__u32 irq;
+		__s32 status;
+	};
+	__u32 level;
+};
+
+#define GZVM_IRQ_LINE              _IOW(GZVM_IOC_MAGIC,  0x61, \
+					struct gzvm_irq_level)
+
+enum gzvm_device_type {
+	GZVM_DEV_TYPE_ARM_VGIC_V3_DIST,
+	GZVM_DEV_TYPE_ARM_VGIC_V3_REDIST,
+	GZVM_DEV_TYPE_MAX,
+};
+
+struct gzvm_create_device {
+	__u32 dev_type;			/* device type */
+	__u32 id;			/* out: device id */
+	__u64 flags;			/* device specific flags */
+	__u64 dev_addr;			/* device ipa address in VM's view */
+	__u64 dev_reg_size;		/* device register range size */
+	/*
+	 * If user -> kernel, this is user virtual address of device specific
+	 * attributes (if needed). If kernel->hypervisor, this is ipa.
+	 */
+	__u64 attr_addr;
+	__u64 attr_size;		/* size of device specific attributes */
+};
+
+#define GZVM_CREATE_DEVICE	   _IOWR(GZVM_IOC_MAGIC,  0xe0, \
+					struct gzvm_create_device)
+
+/*
+ * ioctls for vcpu fds
+ */
 #define GZVM_RUN                   _IO(GZVM_IOC_MAGIC,   0x80)
 
 /* VM exit reason */
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
@ 2023-04-28 10:36   ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

Enable GenieZone to handle virtual interrupt injection request.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 arch/arm64/geniezone/Makefile       |  2 +-
 arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
 arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
 arch/arm64/geniezone/gzvm_irqchip.c | 88 +++++++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_vm.c    | 75 ++++++++++++++++++++++++
 include/linux/gzvm_drv.h            |  4 ++
 include/uapi/linux/gzvm.h           | 38 ++++++++++++-
 7 files changed, 235 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c

diff --git a/arch/arm64/geniezone/Makefile b/arch/arm64/geniezone/Makefile
index 5720c076d73c..82af1ed870bc 100644
--- a/arch/arm64/geniezone/Makefile
+++ b/arch/arm64/geniezone/Makefile
@@ -4,6 +4,6 @@
 #
 include $(srctree)/drivers/virt/geniezone/Makefile
 
-gzvm-y += gzvm_arch.o
+gzvm-y += gzvm_arch.o gzvm_irqchip.o
 
 obj-$(CONFIG_MTK_GZVM) += gzvm.o
diff --git a/arch/arm64/geniezone/gzvm_arch.c b/arch/arm64/geniezone/gzvm_arch.c
index 3c91f3f1ae50..16ab5d4fd5b8 100644
--- a/arch/arm64/geniezone/gzvm_arch.c
+++ b/arch/arm64/geniezone/gzvm_arch.c
@@ -16,11 +16,10 @@
  *
  * Return: The wrapper helps caller to convert geniezone errno to Linux errno.
  */
-static 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)
+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 gz_err_to_errno(res->a0);
@@ -259,3 +258,18 @@ int gzvm_arch_create_vcpu(gzvm_id_t vm_id, int vcpuid, void *run)
 
 	return ret;
 }
+
+int gzvm_arch_create_device(gzvm_id_t vm_id, struct gzvm_create_device *gzvm_dev)
+{
+	struct arm_smccc_res res;
+
+	return gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_DEVICE, vm_id,
+				    virt_to_phys(gzvm_dev), 0, 0, 0, 0, 0, &res);
+}
+
+int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
+			 u32 irq, bool level)
+{
+	/* default use spi */
+	return gzvm_vgic_inject_spi(gzvm, vcpu_idx, irq, level);
+}
diff --git a/arch/arm64/geniezone/gzvm_arch.h b/arch/arm64/geniezone/gzvm_arch.h
index ecc24ff4e244..205bd0901333 100644
--- a/arch/arm64/geniezone/gzvm_arch.h
+++ b/arch/arm64/geniezone/gzvm_arch.h
@@ -71,4 +71,15 @@ disassemble_vm_vcpu_tuple(unsigned int tuple, gzvm_id_t *vmid,
 	*vcpuid = get_vcpuid_from_tuple(tuple);
 }
 
+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);
+
+void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu);
+int gzvm_vgic_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
+			 u32 irq, bool level);
+int gzvm_vgic_inject_spi(struct gzvm *gzvm, unsigned int vcpu_idx,
+			 u32 spi_irq, bool level);
+
 #endif /* __GZVM_ARCH_H__ */
diff --git a/arch/arm64/geniezone/gzvm_irqchip.c b/arch/arm64/geniezone/gzvm_irqchip.c
new file mode 100644
index 000000000000..c46bd34fee1b
--- /dev/null
+++ b/arch/arm64/geniezone/gzvm_irqchip.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/irqchip/arm-gic-v3.h>
+#include <kvm/arm_vgic.h>
+
+#include <linux/gzvm.h>
+#include <linux/gzvm_drv.h>
+#include "gzvm_arch.h"
+
+/**
+ * gzvm_sync_vgic_state() - Check all LRs synced from gz hypervisor
+ *
+ * Traverse all LRs, see if any EOIed vint, notify_acked_irq if any.
+ * GZ does not fold/unfold everytime KVM_RUN, so we have to traverse all saved
+ * LRs. It will not takes much more time comparing to fold/unfold everytime
+ * GZVM_RUN, because there are only few LRs.
+ */
+void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu)
+{
+}
+
+/* is_irq_valid() - Check the irq number and irq_type are matched */
+static bool is_irq_valid(u32 irq, u32 irq_type)
+{
+	switch (irq_type) {
+	case GZVM_IRQ_TYPE_CPU:
+		/*  0 ~ 15: SGI */
+		if (likely(irq <= GZVM_IRQ_CPU_FIQ))
+			return true;
+		break;
+	case GZVM_IRQ_TYPE_PPI:
+		/* 16 ~ 31: PPI */
+		if (likely(irq >= VGIC_NR_SGIS && irq < VGIC_NR_PRIVATE_IRQS))
+			return true;
+		break;
+	case GZVM_IRQ_TYPE_SPI:
+		/* 32 ~ : SPT */
+		if (likely(irq >= VGIC_NR_PRIVATE_IRQS))
+			return true;
+		break;
+	default:
+		return false;
+	}
+	return false;
+}
+
+/**
+ * gzvm_vgic_inject_irq() - Inject virtual interrupt to a VM
+ * @vcpu_idx: vcpu index, only valid if PPI
+ * @irq: irq number
+ * @level: 1 if true else 0
+ */
+int gzvm_vgic_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
+			 u32 irq, bool level)
+{
+	unsigned long a1 = assemble_vm_vcpu_tuple(gzvm->vm_id, vcpu_idx);
+	struct arm_smccc_res res;
+
+	if (!unlikely(is_irq_valid(irq, irq_type)))
+		return -EINVAL;
+
+	gzvm_hypcall_wrapper(MT_HVC_GZVM_IRQ_LINE, a1, irq, level,
+			     0, 0, 0, 0, &res);
+	if (res.a0) {
+		pr_err("Failed to set IRQ level (%d) to irq#%u on vcpu %d with ret=%d\n",
+		       level, irq, vcpu_idx, (int)res.a0);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+/**
+ * gzvm_vgic_inject_spi() - Inject virtual spi interrupt
+ *
+ * @spi_irq: This is spi interrupt number (starts from 0 instead of 32)
+ *
+ * Return 0 if succeed else other negative values indicating each errors
+ */
+int gzvm_vgic_inject_spi(struct gzvm *gzvm, unsigned int vcpu_idx,
+			 u32 spi_irq, bool level)
+{
+	return gzvm_vgic_inject_irq(gzvm, 0, GZVM_IRQ_TYPE_SPI,
+				    spi_irq + VGIC_NR_PRIVATE_IRQS, level);
+}
diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
index 5542065e82c6..a5444541b745 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -186,6 +186,67 @@ gzvm_vm_ioctl_set_memory_region(struct gzvm *gzvm,
 	return register_memslot_addr_range(gzvm, memslot);
 }
 
+static int gzvm_vm_ioctl_irq_line(struct gzvm *gzvm,
+				  struct gzvm_irq_level *irq_level)
+{
+	u32 irq = irq_level->irq;
+	unsigned int irq_type, vcpu_idx, irq_num;
+	bool level = irq_level->level;
+
+	irq_type = (irq >> GZVM_IRQ_TYPE_SHIFT) & GZVM_IRQ_TYPE_MASK;
+	vcpu_idx = (irq >> GZVM_IRQ_VCPU_SHIFT) & GZVM_IRQ_VCPU_MASK;
+	vcpu_idx += ((irq >> GZVM_IRQ_VCPU2_SHIFT) & GZVM_IRQ_VCPU2_MASK) *
+		(GZVM_IRQ_VCPU_MASK + 1);
+	irq_num = (irq >> GZVM_IRQ_NUM_SHIFT) & GZVM_IRQ_NUM_MASK;
+
+	return gzvm_arch_inject_irq(gzvm, vcpu_idx, irq_num, irq_type, level);
+}
+
+static int gzvm_vm_ioctl_create_device(struct gzvm *gzvm, void __user *argp)
+{
+	struct gzvm_create_device *gzvm_dev;
+	void *dev_data = NULL;
+	int ret;
+
+	gzvm_dev = (struct gzvm_create_device *)alloc_pages_exact(PAGE_SIZE,
+								  GFP_KERNEL);
+	if (!gzvm_dev)
+		return -ENOMEM;
+	if (copy_from_user(gzvm_dev, argp, sizeof(*gzvm_dev))) {
+		ret = -EFAULT;
+		goto err_free_dev;
+	}
+
+	if (gzvm_dev->attr_addr != 0 && gzvm_dev->attr_size != 0) {
+		size_t attr_size = gzvm_dev->attr_size;
+		void __user *attr_addr = (void __user *)gzvm_dev->attr_addr;
+
+		/* Size of device specific data should not be over a page. */
+		if (attr_size > PAGE_SIZE)
+			return -EINVAL;
+
+		dev_data = alloc_pages_exact(attr_size, GFP_KERNEL);
+		if (!dev_data) {
+			ret = -ENOMEM;
+			goto err_free_dev;
+		}
+
+		if (copy_from_user(dev_data, attr_addr, attr_size)) {
+			ret = -EFAULT;
+			goto err_free_dev_data;
+		}
+		gzvm_dev->attr_addr = virt_to_phys(dev_data);
+	}
+
+	ret = gzvm_arch_create_device(gzvm->vm_id, gzvm_dev);
+err_free_dev_data:
+	if (dev_data)
+		free_pages_exact(dev_data, 0);
+err_free_dev:
+	free_pages_exact(gzvm_dev, 0);
+	return ret;
+}
+
 static int gzvm_vm_ioctl_enable_cap(struct gzvm *gzvm,
 				    struct gzvm_enable_cap *cap,
 				    void __user *argp)
@@ -220,6 +281,20 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl,
 		ret = gzvm_vm_ioctl_set_memory_region(gzvm, &userspace_mem);
 		break;
 	}
+	case GZVM_IRQ_LINE: {
+		struct gzvm_irq_level irq_event;
+
+		ret = -EFAULT;
+		if (copy_from_user(&irq_event, argp, sizeof(irq_event)))
+			goto out;
+
+		ret = gzvm_vm_ioctl_irq_line(gzvm, &irq_event);
+		break;
+	}
+	case GZVM_CREATE_DEVICE: {
+		ret = gzvm_vm_ioctl_create_device(gzvm, argp);
+		break;
+	}
 	case GZVM_ENABLE_CAP: {
 		struct gzvm_enable_cap cap;
 
diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h
index 5736ddf97741..1e7c81597e9a 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -107,6 +107,10 @@ int gzvm_arch_create_vcpu(gzvm_id_t vm_id, int vcpuid, void *run);
 int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason);
 int gzvm_arch_destroy_vcpu(gzvm_id_t vm_id, int vcpuid);
 
+int gzvm_arch_create_device(gzvm_id_t vm_id, struct gzvm_create_device *gzvm_dev);
+int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
+			 u32 irq, bool level);
+
 extern struct platform_device *gzvm_debug_dev;
 
 #endif /* __GZVM_DRV_H__ */
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
index 6462961299eb..2f56a53efb27 100644
--- a/include/uapi/linux/gzvm.h
+++ b/include/uapi/linux/gzvm.h
@@ -87,7 +87,43 @@ struct gzvm_userspace_memory_region {
 #define GZVM_IRQ_CPU_IRQ		0
 #define GZVM_IRQ_CPU_FIQ		1
 
-/* ioctls for vcpu fds */
+struct gzvm_irq_level {
+	union {
+		__u32 irq;
+		__s32 status;
+	};
+	__u32 level;
+};
+
+#define GZVM_IRQ_LINE              _IOW(GZVM_IOC_MAGIC,  0x61, \
+					struct gzvm_irq_level)
+
+enum gzvm_device_type {
+	GZVM_DEV_TYPE_ARM_VGIC_V3_DIST,
+	GZVM_DEV_TYPE_ARM_VGIC_V3_REDIST,
+	GZVM_DEV_TYPE_MAX,
+};
+
+struct gzvm_create_device {
+	__u32 dev_type;			/* device type */
+	__u32 id;			/* out: device id */
+	__u64 flags;			/* device specific flags */
+	__u64 dev_addr;			/* device ipa address in VM's view */
+	__u64 dev_reg_size;		/* device register range size */
+	/*
+	 * If user -> kernel, this is user virtual address of device specific
+	 * attributes (if needed). If kernel->hypervisor, this is ipa.
+	 */
+	__u64 attr_addr;
+	__u64 attr_size;		/* size of device specific attributes */
+};
+
+#define GZVM_CREATE_DEVICE	   _IOWR(GZVM_IOC_MAGIC,  0xe0, \
+					struct gzvm_create_device)
+
+/*
+ * ioctls for vcpu fds
+ */
 #define GZVM_RUN                   _IO(GZVM_IOC_MAGIC,   0x80)
 
 /* VM exit reason */
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 6/7] virt: geniezone: Add irqfd support
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 10:36   ` Yi-De Wu
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

irqfd enables other threads than vcpu threads to inject virtual
interrupt through irqfd asynchronously rather through ioctl interface.
This interface is necessary for VMM which creates separated thread for
IO handling or uses vhost devices.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 arch/arm64/geniezone/gzvm_arch.c    |   5 +
 arch/arm64/geniezone/gzvm_arch.h    |   7 +
 arch/arm64/geniezone/gzvm_irqchip.c |  22 +-
 drivers/virt/geniezone/Makefile     |   2 +-
 drivers/virt/geniezone/gzvm_irqfd.c | 536 ++++++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_main.c  |   5 +
 drivers/virt/geniezone/gzvm_vcpu.c  |   1 +
 drivers/virt/geniezone/gzvm_vm.c    |  19 +
 include/linux/gzvm_drv.h            |  27 ++
 include/uapi/linux/gzvm.h           |  20 +-
 10 files changed, 641 insertions(+), 3 deletions(-)
 create mode 100644 drivers/virt/geniezone/gzvm_irqfd.c

diff --git a/arch/arm64/geniezone/gzvm_arch.c b/arch/arm64/geniezone/gzvm_arch.c
index 16ab5d4fd5b8..19ac7c1a4743 100644
--- a/arch/arm64/geniezone/gzvm_arch.c
+++ b/arch/arm64/geniezone/gzvm_arch.c
@@ -273,3 +273,8 @@ int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
 	/* default use spi */
 	return gzvm_vgic_inject_spi(gzvm, vcpu_idx, irq, level);
 }
+
+void gzvm_sync_hwstate(struct gzvm_vcpu *vcpu)
+{
+	gzvm_sync_vgic_state(vcpu);
+}
diff --git a/arch/arm64/geniezone/gzvm_arch.h b/arch/arm64/geniezone/gzvm_arch.h
index 205bd0901333..e8d7c82efb50 100644
--- a/arch/arm64/geniezone/gzvm_arch.h
+++ b/arch/arm64/geniezone/gzvm_arch.h
@@ -47,6 +47,8 @@ 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 GIC_V3_NR_LRS			16
+
 static inline gzvm_id_t get_vmid_from_tuple(unsigned int tuple)
 {
 	return (gzvm_id_t)(tuple >> 16);
@@ -57,6 +59,11 @@ static inline gzvm_vcpu_id_t get_vcpuid_from_tuple(unsigned int tuple)
 	return (gzvm_vcpu_id_t)(tuple & 0xffff);
 }
 
+struct gzvm_vcpu_hwstate {
+	__u32 nr_lrs;
+	__u64 lr[GIC_V3_NR_LRS];
+};
+
 static inline unsigned int
 assemble_vm_vcpu_tuple(gzvm_id_t vmid, gzvm_vcpu_id_t vcpuid)
 {
diff --git a/arch/arm64/geniezone/gzvm_irqchip.c b/arch/arm64/geniezone/gzvm_irqchip.c
index c46bd34fee1b..1887cbb58fc6 100644
--- a/arch/arm64/geniezone/gzvm_irqchip.c
+++ b/arch/arm64/geniezone/gzvm_irqchip.c
@@ -10,8 +10,15 @@
 #include <linux/gzvm_drv.h>
 #include "gzvm_arch.h"
 
+static bool lr_signals_eoi(uint64_t lr_val)
+{
+	return !(lr_val & ICH_LR_STATE) && (lr_val & ICH_LR_EOI) &&
+		 !(lr_val & ICH_LR_HW);
+}
+
 /**
- * gzvm_sync_vgic_state() - Check all LRs synced from gz hypervisor
+ * gzvm_sync_vgic_state() - Check all LRs synced from gz hypervisor.
+ * @vcpu: Pointer to gzvm_vcpu.
  *
  * Traverse all LRs, see if any EOIed vint, notify_acked_irq if any.
  * GZ does not fold/unfold everytime KVM_RUN, so we have to traverse all saved
@@ -20,6 +27,19 @@
  */
 void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu)
 {
+	int i;
+
+	for (i = 0; i < vcpu->hwstate->nr_lrs; i++) {
+		u32 vintid;
+		u64 lr_val = vcpu->hwstate->lr[i];
+		/* 0 means unused */
+		if (!lr_val)
+			continue;
+
+		vintid = lr_val & ICH_LR_VIRTUAL_ID_MASK;
+		if (lr_signals_eoi(lr_val))
+			gzvm_notify_acked_irq(vcpu->gzvm, vintid - VGIC_NR_PRIVATE_IRQS);
+	}
 }
 
 /* is_irq_valid() - Check the irq number and irq_type are matched */
diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile
index 8ebf2db0c970..8517549e7dfb 100644
--- a/drivers/virt/geniezone/Makefile
+++ b/drivers/virt/geniezone/Makefile
@@ -7,5 +7,5 @@
 GZVM_DIR ?= ../../../drivers/virt/geniezone
 
 gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o \
-	  $(GZVM_DIR)/gzvm_vcpu.o
+	  $(GZVM_DIR)/gzvm_vcpu.o $(GZVM_DIR)/gzvm_irqfd.o
 
diff --git a/drivers/virt/geniezone/gzvm_irqfd.c b/drivers/virt/geniezone/gzvm_irqfd.c
new file mode 100644
index 000000000000..2594b2fe2e4e
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_irqfd.c
@@ -0,0 +1,536 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/eventfd.h>
+#include <linux/syscalls.h>
+#include <linux/gzvm_drv.h>
+
+struct gzvm_irq_ack_notifier {
+	struct hlist_node link;
+	unsigned int gsi;
+	void (*irq_acked)(struct gzvm_irq_ack_notifier *ian);
+};
+
+/**
+ * struct gzvm_kernel_irqfd_resampler - irqfd resampler descriptor.
+ * @gzvm: Poiner to gzvm.
+ * @list_head list: List of resampling struct _irqfd objects sharing this gsi.
+ *		    RCU list modified under gzvm->irqfds.resampler_lock.
+ * @notifier: gzvm irq ack notifier.
+ * @list_head link: Entry in list of gzvm->irqfd.resampler_list.
+ *		    Use for sharing esamplers among irqfds on the same gsi.
+ *		    Accessed and modified under gzvm->irqfds.resampler_lock.
+ *
+ * Resampling irqfds are a special variety of irqfds used to emulate
+ * level triggered interrupts.  The interrupt is asserted on eventfd
+ * trigger.  On acknowledgment through the irq ack notifier, the
+ * interrupt is de-asserted and userspace is notified through the
+ * resamplefd.  All resamplers on the same gsi are de-asserted
+ * together, so we don't need to track the state of each individual
+ * user.  We can also therefore share the same irq source ID.
+ */
+struct gzvm_kernel_irqfd_resampler {
+	struct gzvm *gzvm;
+
+	struct list_head list;
+	struct gzvm_irq_ack_notifier notifier;
+
+	struct list_head link;
+};
+
+/**
+ * struct gzvm_kernel_irqfd: gzvm kernel irqfd descriptor.
+ * @gzvm: Pointer to gzvm.
+ * @wait: Wait queue entry.
+ * @gsi: Used for level IRQ fast-path.
+ * @resampler: The resampler used by this irqfd (resampler-only).
+ * @resamplefd: Eventfd notified on resample (resampler-only).
+ * @resampler_link: Entry in list of irqfds for a resampler (resampler-only).
+ * @eventfd: Used for setup/shutdown.
+ */
+struct gzvm_kernel_irqfd {
+	struct gzvm *gzvm;
+	wait_queue_entry_t wait;
+
+	int gsi;
+
+	struct gzvm_kernel_irqfd_resampler *resampler;
+
+	struct eventfd_ctx *resamplefd;
+
+	struct list_head resampler_link;
+
+	struct eventfd_ctx *eventfd;
+	struct list_head list;
+	poll_table pt;
+	struct work_struct shutdown;
+};
+
+static struct workqueue_struct *irqfd_cleanup_wq;
+
+/**
+ * irqfd_set_spi(): irqfd to inject virtual interrupt.
+ * @gzvm: Pointer to gzvm.
+ * @irq_source_id: irq source id.
+ * @irq: This is spi interrupt number (starts from 0 instead of 32).
+ * @level: irq triggered level.
+ * @line_status: irq status.
+ */
+static void irqfd_set_spi(struct gzvm *gzvm, int irq_source_id, u32 irq,
+			  int level, bool line_status)
+{
+	if (level)
+		gzvm_arch_inject_irq(gzvm, irq_source_id, 0, irq, level);
+}
+
+/**
+ * irqfd_resampler_ack() - Notify all of the resampler irqfds using this GSI
+ *			   when IRQ de-assert once.
+ * @ian: Pointer to gzvm_irq_ack_notifier.
+ *
+ * Since resampler irqfds share an IRQ source ID, we de-assert once
+ * then notify all of the resampler irqfds using this GSI.  We can't
+ * do multiple de-asserts or we risk racing with incoming re-asserts.
+ */
+static void irqfd_resampler_ack(struct gzvm_irq_ack_notifier *ian)
+{
+	struct gzvm_kernel_irqfd_resampler *resampler;
+	struct gzvm *gzvm;
+	struct gzvm_kernel_irqfd *irqfd;
+	int idx;
+
+	resampler = container_of(ian,
+				 struct gzvm_kernel_irqfd_resampler, notifier);
+	gzvm = resampler->gzvm;
+
+	irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
+		      resampler->notifier.gsi, 0, false);
+
+	idx = srcu_read_lock(&gzvm->irq_srcu);
+
+	list_for_each_entry_srcu(irqfd, &resampler->list, resampler_link,
+				 srcu_read_lock_held(&gzvm->irq_srcu)) {
+		eventfd_signal(irqfd->resamplefd, 1);
+	}
+
+	srcu_read_unlock(&gzvm->irq_srcu, idx);
+}
+
+static void gzvm_register_irq_ack_notifier(struct gzvm *gzvm,
+					   struct gzvm_irq_ack_notifier *ian)
+{
+	mutex_lock(&gzvm->irq_lock);
+	hlist_add_head_rcu(&ian->link, &gzvm->irq_ack_notifier_list);
+	mutex_unlock(&gzvm->irq_lock);
+}
+
+static void gzvm_unregister_irq_ack_notifier(struct gzvm *gzvm,
+					     struct gzvm_irq_ack_notifier *ian)
+{
+	mutex_lock(&gzvm->irq_lock);
+	hlist_del_init_rcu(&ian->link);
+	mutex_unlock(&gzvm->irq_lock);
+	synchronize_srcu(&gzvm->irq_srcu);
+}
+
+static void irqfd_resampler_shutdown(struct gzvm_kernel_irqfd *irqfd)
+{
+	struct gzvm_kernel_irqfd_resampler *resampler = irqfd->resampler;
+	struct gzvm *gzvm = resampler->gzvm;
+
+	mutex_lock(&gzvm->irqfds.resampler_lock);
+
+	list_del_rcu(&irqfd->resampler_link);
+	synchronize_srcu(&gzvm->irq_srcu);
+
+	if (list_empty(&resampler->list)) {
+		list_del(&resampler->link);
+		gzvm_unregister_irq_ack_notifier(gzvm, &resampler->notifier);
+		irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
+			      resampler->notifier.gsi, 0, false);
+		kfree(resampler);
+	}
+
+	mutex_unlock(&gzvm->irqfds.resampler_lock);
+}
+
+/**
+ * irqfd_shutdown() - Race-free decouple logic (ordering is critical).
+ * @work: Pointer to work_struct.
+ */
+static void irqfd_shutdown(struct work_struct *work)
+{
+	struct gzvm_kernel_irqfd *irqfd =
+		container_of(work, struct gzvm_kernel_irqfd, shutdown);
+	struct gzvm *gzvm = irqfd->gzvm;
+	u64 cnt;
+
+	/* Make sure irqfd has been initialized in assign path. */
+	synchronize_srcu(&gzvm->irq_srcu);
+
+	/*
+	 * Synchronize with the wait-queue and unhook ourselves to prevent
+	 * further events.
+	 */
+	eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt);
+
+	if (irqfd->resampler) {
+		irqfd_resampler_shutdown(irqfd);
+		eventfd_ctx_put(irqfd->resamplefd);
+	}
+
+	/*
+	 * It is now safe to release the object's resources
+	 */
+	eventfd_ctx_put(irqfd->eventfd);
+	kfree(irqfd);
+}
+
+/**
+ * irqfd_is_active() - Assumes gzvm->irqfds.lock is held.
+ * @irqfd: Pointer to gzvm_kernel_irqfd.
+ */
+static bool irqfd_is_active(struct gzvm_kernel_irqfd *irqfd)
+{
+	return list_empty(&irqfd->list) ? false : true;
+}
+
+/**
+ * irqfd_deactivate() - Mark the irqfd as inactive and schedule it for removal.
+ *			assumes gzvm->irqfds.lock is held.
+ * @irqfd: Pointer to gzvm_kernel_irqfd.
+ */
+static void irqfd_deactivate(struct gzvm_kernel_irqfd *irqfd)
+{
+	if (!irqfd_is_active(irqfd))
+		return;
+
+	list_del_init(&irqfd->list);
+
+	queue_work(irqfd_cleanup_wq, &irqfd->shutdown);
+}
+
+/**
+ * irqfd_wakeup() - Wake up irqfd to do virtual interrupt injection.
+ * @wait: Pointer to wait_queue_entry_t.
+ * @mode:
+ * @sync:
+ * @key:
+ */
+static int irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync,
+			void *key)
+{
+	struct gzvm_kernel_irqfd *irqfd =
+		container_of(wait, struct gzvm_kernel_irqfd, wait);
+	__poll_t flags = key_to_poll(key);
+	struct gzvm *gzvm = irqfd->gzvm;
+
+	if (flags & EPOLLIN) {
+		u64 cnt;
+
+		eventfd_ctx_do_read(irqfd->eventfd, &cnt);
+		/* gzvm's irq injection is not blocked, don't need workq */
+		irqfd_set_spi(gzvm, GZVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi,
+			      1, false);
+	}
+
+	if (flags & EPOLLHUP) {
+		/* The eventfd is closing, detach from GZVM */
+		unsigned long iflags;
+
+		spin_lock_irqsave(&gzvm->irqfds.lock, iflags);
+
+		/*
+		 * Do more check if someone deactivated the irqfd before
+		 * we could acquire the irqfds.lock.
+		 */
+		if (irqfd_is_active(irqfd))
+			irqfd_deactivate(irqfd);
+
+		spin_unlock_irqrestore(&gzvm->irqfds.lock, iflags);
+	}
+
+	return 0;
+}
+
+static void irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh,
+				    poll_table *pt)
+{
+	struct gzvm_kernel_irqfd *irqfd =
+		container_of(pt, struct gzvm_kernel_irqfd, pt);
+	add_wait_queue_priority(wqh, &irqfd->wait);
+}
+
+static int gzvm_irqfd_assign(struct gzvm *gzvm, struct gzvm_irqfd *args)
+{
+	struct gzvm_kernel_irqfd *irqfd, *tmp;
+	struct fd f;
+	struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
+	int ret;
+	__poll_t events;
+	int idx;
+
+	irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT);
+	if (!irqfd)
+		return -ENOMEM;
+
+	irqfd->gzvm = gzvm;
+	irqfd->gsi = args->gsi;
+	irqfd->resampler = NULL;
+
+	INIT_LIST_HEAD(&irqfd->list);
+	INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
+
+	f = fdget(args->fd);
+	if (!f.file) {
+		ret = -EBADF;
+		goto out;
+	}
+
+	eventfd = eventfd_ctx_fileget(f.file);
+	if (IS_ERR(eventfd)) {
+		ret = PTR_ERR(eventfd);
+		goto fail;
+	}
+
+	irqfd->eventfd = eventfd;
+
+	if (args->flags & GZVM_IRQFD_FLAG_RESAMPLE) {
+		struct gzvm_kernel_irqfd_resampler *resampler;
+
+		resamplefd = eventfd_ctx_fdget(args->resamplefd);
+		if (IS_ERR(resamplefd)) {
+			ret = PTR_ERR(resamplefd);
+			goto fail;
+		}
+
+		irqfd->resamplefd = resamplefd;
+		INIT_LIST_HEAD(&irqfd->resampler_link);
+
+		mutex_lock(&gzvm->irqfds.resampler_lock);
+
+		list_for_each_entry(resampler,
+				    &gzvm->irqfds.resampler_list, link) {
+			if (resampler->notifier.gsi == irqfd->gsi) {
+				irqfd->resampler = resampler;
+				break;
+			}
+		}
+
+		if (!irqfd->resampler) {
+			resampler = kzalloc(sizeof(*resampler),
+					    GFP_KERNEL_ACCOUNT);
+			if (!resampler) {
+				ret = -ENOMEM;
+				mutex_unlock(&gzvm->irqfds.resampler_lock);
+				goto fail;
+			}
+
+			resampler->gzvm = gzvm;
+			INIT_LIST_HEAD(&resampler->list);
+			resampler->notifier.gsi = irqfd->gsi;
+			resampler->notifier.irq_acked = irqfd_resampler_ack;
+			INIT_LIST_HEAD(&resampler->link);
+
+			list_add(&resampler->link, &gzvm->irqfds.resampler_list);
+			gzvm_register_irq_ack_notifier(gzvm,
+						       &resampler->notifier);
+			irqfd->resampler = resampler;
+		}
+
+		list_add_rcu(&irqfd->resampler_link, &irqfd->resampler->list);
+		synchronize_srcu(&gzvm->irq_srcu);
+
+		mutex_unlock(&gzvm->irqfds.resampler_lock);
+	}
+
+	/*
+	 * Install our own custom wake-up handling so we are notified via
+	 * a callback whenever someone signals the underlying eventfd
+	 */
+	init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup);
+	init_poll_funcptr(&irqfd->pt, irqfd_ptable_queue_proc);
+
+	spin_lock_irq(&gzvm->irqfds.lock);
+
+	ret = 0;
+	list_for_each_entry(tmp, &gzvm->irqfds.items, list) {
+		if (irqfd->eventfd != tmp->eventfd)
+			continue;
+		/* This fd is used for another irq already. */
+		pr_err("already used: gsi=%d fd=%d\n", args->gsi, args->fd);
+		ret = -EBUSY;
+		spin_unlock_irq(&gzvm->irqfds.lock);
+		goto fail;
+	}
+
+	idx = srcu_read_lock(&gzvm->irq_srcu);
+
+	list_add_tail(&irqfd->list, &gzvm->irqfds.items);
+
+	spin_unlock_irq(&gzvm->irqfds.lock);
+
+	/*
+	 * Check if there was an event already pending on the eventfd
+	 * before we registered, and trigger it as if we didn't miss it.
+	 */
+	events = vfs_poll(f.file, &irqfd->pt);
+
+	/* In case there is already a pending event */
+	if (events & EPOLLIN)
+		irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
+			      irqfd->gsi, 1, false);
+
+	srcu_read_unlock(&gzvm->irq_srcu, idx);
+
+	/*
+	 * do not drop the file until the irqfd is fully initialized, otherwise
+	 * we might race against the EPOLLHUP
+	 */
+	fdput(f);
+	return 0;
+
+fail:
+	if (irqfd->resampler)
+		irqfd_resampler_shutdown(irqfd);
+
+	if (resamplefd && !IS_ERR(resamplefd))
+		eventfd_ctx_put(resamplefd);
+
+	if (eventfd && !IS_ERR(eventfd))
+		eventfd_ctx_put(eventfd);
+
+	fdput(f);
+
+out:
+	kfree(irqfd);
+	return ret;
+}
+
+static void gzvm_notify_acked_gsi(struct gzvm *gzvm, int gsi)
+{
+	struct gzvm_irq_ack_notifier *gian;
+
+	hlist_for_each_entry_srcu(gian, &gzvm->irq_ack_notifier_list,
+				  link, srcu_read_lock_held(&gzvm->irq_srcu))
+		if (gian->gsi == gsi)
+			gian->irq_acked(gian);
+}
+
+void gzvm_notify_acked_irq(struct gzvm *gzvm, unsigned int gsi)
+{
+	int idx;
+
+	idx = srcu_read_lock(&gzvm->irq_srcu);
+	gzvm_notify_acked_gsi(gzvm, gsi);
+	srcu_read_unlock(&gzvm->irq_srcu, idx);
+}
+
+/**
+ * gzvm_irqfd_deassign() - Shutdown any irqfd's that match fd+gsi.
+ * @gzvm: Pointer to gzvm.
+ * @args: Pointer to gzvm_irqfd.
+ */
+static int gzvm_irqfd_deassign(struct gzvm *gzvm, struct gzvm_irqfd *args)
+{
+	struct gzvm_kernel_irqfd *irqfd, *tmp;
+	struct eventfd_ctx *eventfd;
+
+	eventfd = eventfd_ctx_fdget(args->fd);
+	if (IS_ERR(eventfd))
+		return PTR_ERR(eventfd);
+
+	spin_lock_irq(&gzvm->irqfds.lock);
+
+	list_for_each_entry_safe(irqfd, tmp, &gzvm->irqfds.items, list) {
+		if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi)
+			irqfd_deactivate(irqfd);
+	}
+
+	spin_unlock_irq(&gzvm->irqfds.lock);
+	eventfd_ctx_put(eventfd);
+
+	/*
+	 * Block until we know all outstanding shutdown jobs have completed
+	 * so that we guarantee there will not be any more interrupts on this
+	 * gsi once this deassign function returns.
+	 */
+	flush_workqueue(irqfd_cleanup_wq);
+
+	return 0;
+}
+
+int gzvm_irqfd(struct gzvm *gzvm, struct gzvm_irqfd *args)
+{
+	if (args->flags &
+	    ~(GZVM_IRQFD_FLAG_DEASSIGN | GZVM_IRQFD_FLAG_RESAMPLE))
+		return -EINVAL;
+
+	if (args->flags & GZVM_IRQFD_FLAG_DEASSIGN)
+		return gzvm_irqfd_deassign(gzvm, args);
+
+	return gzvm_irqfd_assign(gzvm, args);
+}
+
+/**
+ * gzvm_vm_irqfd_init() - Initialize irqfd data structure per VM
+ */
+int gzvm_vm_irqfd_init(struct gzvm *gzvm)
+{
+	mutex_init(&gzvm->irq_lock);
+
+	spin_lock_init(&gzvm->irqfds.lock);
+	INIT_LIST_HEAD(&gzvm->irqfds.items);
+	INIT_LIST_HEAD(&gzvm->irqfds.resampler_list);
+	if (init_srcu_struct(&gzvm->irq_srcu))
+		return -EINVAL;
+	INIT_HLIST_HEAD(&gzvm->irq_ack_notifier_list);
+	mutex_init(&gzvm->irqfds.resampler_lock);
+
+	return 0;
+}
+
+/**
+ * gzvm_irqfd_release() - This function is called as the gzvm VM fd is being
+ *			  released. Shutdown all irqfds that still remain open.
+ * @gzvm: Pointer to gzvm.
+ */
+void gzvm_vm_irqfd_release(struct gzvm *gzvm)
+{
+	struct gzvm_kernel_irqfd *irqfd, *tmp;
+
+	spin_lock_irq(&gzvm->irqfds.lock);
+
+	list_for_each_entry_safe(irqfd, tmp, &gzvm->irqfds.items, list)
+		irqfd_deactivate(irqfd);
+
+	spin_unlock_irq(&gzvm->irqfds.lock);
+
+	/*
+	 * Block until we know all outstanding shutdown jobs have completed.
+	 */
+	flush_workqueue(irqfd_cleanup_wq);
+}
+
+/**
+ * gzvm_irqfd_init() - Erase flushing work items when a VM exits.
+ *
+ * Create a host-wide workqueue for issuing deferred shutdown requests
+ * aggregated from all vm* instances. We need our own isolated
+ * queue to ease flushing work items when a VM exits.
+ */
+int gzvm_drv_irqfd_init(void)
+{
+	irqfd_cleanup_wq = alloc_workqueue("gzvm-irqfd-cleanup", 0, 0);
+	if (!irqfd_cleanup_wq)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void gzvm_drv_irqfd_exit(void)
+{
+	destroy_workqueue(irqfd_cleanup_wq);
+}
diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c
index e3fe3ad9ffce..121816a09c8e 100644
--- a/drivers/virt/geniezone/gzvm_main.c
+++ b/drivers/virt/geniezone/gzvm_main.c
@@ -113,11 +113,16 @@ static int gzvm_drv_probe(struct platform_device *pdev)
 		return ret;
 	gzvm_debug_dev = pdev;
 
+	ret = gzvm_drv_irqfd_init();
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
 static int gzvm_drv_remove(struct platform_device *pdev)
 {
+	gzvm_drv_irqfd_exit();
 	destroy_all_vm();
 	misc_deregister(&gzvm_dev);
 	return 0;
diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c
index 65b1a2372b30..faee2ee64639 100644
--- a/drivers/virt/geniezone/gzvm_vcpu.c
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -211,6 +211,7 @@ int gzvm_vm_ioctl_create_vcpu(struct gzvm *gzvm, u32 cpuid)
 		ret = -ENOMEM;
 		goto free_vcpu;
 	}
+	vcpu->hwstate = (void *)vcpu->run + PAGE_SIZE;
 	vcpu->vcpuid = cpuid;
 	vcpu->gzvm = gzvm;
 	mutex_init(&vcpu->lock);
diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
index a5444541b745..eb34d7ba94a2 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -295,6 +295,15 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl,
 		ret = gzvm_vm_ioctl_create_device(gzvm, argp);
 		break;
 	}
+	case GZVM_IRQFD: {
+		struct gzvm_irqfd data;
+
+		ret = -EFAULT;
+		if (copy_from_user(&data, argp, sizeof(data)))
+			goto out;
+		ret = gzvm_irqfd(gzvm, &data);
+		break;
+	}
 	case GZVM_ENABLE_CAP: {
 		struct gzvm_enable_cap cap;
 
@@ -319,6 +328,8 @@ static void gzvm_destroy_vm(struct gzvm *gzvm)
 
 	mutex_lock(&gzvm->lock);
 
+	gzvm_vm_irqfd_release(gzvm);
+	gzvm_destroy_vcpus(gzvm);
 	gzvm_arch_destroy_vm(gzvm->vm_id);
 
 	gzvm_destroy_vcpus(gzvm);
@@ -365,6 +376,14 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
 	gzvm->mm = current->mm;
 	mutex_init(&gzvm->lock);
 
+	ret = gzvm_vm_irqfd_init(gzvm);
+	if (ret) {
+		dev_err(&gzvm_debug_dev->dev,
+			"Failed to initialize irqfd\n");
+		kfree(gzvm);
+		return ERR_PTR(ret);
+	}
+
 	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 1e7c81597e9a..a54a7915c514 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -10,6 +10,7 @@
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/gzvm.h>
+#include <linux/srcu.h>
 
 #define MODULE_NAME	"gzvm"
 #define GZVM_VCPU_MMAP_SIZE  PAGE_SIZE
@@ -25,6 +26,8 @@
 #define ERR_NOT_SUPPORTED       (-24)
 #define ERR_NOT_IMPLEMENTED     (-27)
 #define ERR_FAULT               (-40)
+#define GZVM_USERSPACE_IRQ_SOURCE_ID            0
+#define GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID       1
 
 /*
  * The following data structures are for data transferring between driver and
@@ -68,6 +71,7 @@ struct gzvm_vcpu {
 	/* lock of vcpu*/
 	struct mutex lock;
 	struct gzvm_vcpu_run *run;
+	struct gzvm_vcpu_hwstate *hwstate;
 };
 
 struct gzvm {
@@ -77,8 +81,23 @@ struct gzvm {
 	struct gzvm_memslot memslot[GZVM_MAX_MEM_REGION];
 	/* lock for list_add*/
 	struct mutex lock;
+
+	struct {
+		/* lock for irqfds list operation */
+		spinlock_t        lock;
+		struct list_head  items;
+		struct list_head  resampler_list;
+		/* lock for irqfds resampler */
+		struct mutex      resampler_lock;
+	} irqfds;
+
 	struct list_head vm_list;
 	gzvm_id_t vm_id;
+
+	struct hlist_head irq_ack_notifier_list;
+	struct srcu_struct irq_srcu;
+	/* lock for irq injection */
+	struct mutex irq_lock;
 };
 
 long gzvm_dev_ioctl_check_extension(struct gzvm *gzvm, unsigned long args);
@@ -111,6 +130,14 @@ int gzvm_arch_create_device(gzvm_id_t vm_id, struct gzvm_create_device *gzvm_dev
 int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
 			 u32 irq, bool level);
 
+void gzvm_notify_acked_irq(struct gzvm *gzvm, unsigned int gsi);
+int gzvm_irqfd(struct gzvm *gzvm, struct gzvm_irqfd *args);
+int gzvm_drv_irqfd_init(void);
+void gzvm_drv_irqfd_exit(void);
+int gzvm_vm_irqfd_init(struct gzvm *gzvm);
+void gzvm_vm_irqfd_release(struct gzvm *gzvm);
+void gzvm_sync_hwstate(struct gzvm_vcpu *vcpu);
+
 extern struct platform_device *gzvm_debug_dev;
 
 #endif /* __GZVM_DRV_H__ */
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
index 2f56a53efb27..b878b25ff963 100644
--- a/include/uapi/linux/gzvm.h
+++ b/include/uapi/linux/gzvm.h
@@ -230,4 +230,22 @@ struct gzvm_one_reg {
 
 #define GZVM_REG_GENERIC	   0x0000000000000000ULL
 
-#endif /* __GZVM_H__ */
+#define GZVM_IRQFD_FLAG_DEASSIGN	(1 << 0)
+/**
+ * GZVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
+ * the irqfd to operate in resampling mode for level triggered interrupt
+ * emulation.
+ */
+#define GZVM_IRQFD_FLAG_RESAMPLE	(1 << 1)
+
+struct gzvm_irqfd {
+	__u32 fd;
+	__u32 gsi;
+	__u32 flags;
+	__u32 resamplefd;
+	__u8  pad[16];
+};
+
+#define GZVM_IRQFD	_IOW(GZVM_IOC_MAGIC, 0x76, struct gzvm_irqfd)
+
+#endif /* __GZVM__H__ */
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 6/7] virt: geniezone: Add irqfd support
@ 2023-04-28 10:36   ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

irqfd enables other threads than vcpu threads to inject virtual
interrupt through irqfd asynchronously rather through ioctl interface.
This interface is necessary for VMM which creates separated thread for
IO handling or uses vhost devices.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 arch/arm64/geniezone/gzvm_arch.c    |   5 +
 arch/arm64/geniezone/gzvm_arch.h    |   7 +
 arch/arm64/geniezone/gzvm_irqchip.c |  22 +-
 drivers/virt/geniezone/Makefile     |   2 +-
 drivers/virt/geniezone/gzvm_irqfd.c | 536 ++++++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_main.c  |   5 +
 drivers/virt/geniezone/gzvm_vcpu.c  |   1 +
 drivers/virt/geniezone/gzvm_vm.c    |  19 +
 include/linux/gzvm_drv.h            |  27 ++
 include/uapi/linux/gzvm.h           |  20 +-
 10 files changed, 641 insertions(+), 3 deletions(-)
 create mode 100644 drivers/virt/geniezone/gzvm_irqfd.c

diff --git a/arch/arm64/geniezone/gzvm_arch.c b/arch/arm64/geniezone/gzvm_arch.c
index 16ab5d4fd5b8..19ac7c1a4743 100644
--- a/arch/arm64/geniezone/gzvm_arch.c
+++ b/arch/arm64/geniezone/gzvm_arch.c
@@ -273,3 +273,8 @@ int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
 	/* default use spi */
 	return gzvm_vgic_inject_spi(gzvm, vcpu_idx, irq, level);
 }
+
+void gzvm_sync_hwstate(struct gzvm_vcpu *vcpu)
+{
+	gzvm_sync_vgic_state(vcpu);
+}
diff --git a/arch/arm64/geniezone/gzvm_arch.h b/arch/arm64/geniezone/gzvm_arch.h
index 205bd0901333..e8d7c82efb50 100644
--- a/arch/arm64/geniezone/gzvm_arch.h
+++ b/arch/arm64/geniezone/gzvm_arch.h
@@ -47,6 +47,8 @@ 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 GIC_V3_NR_LRS			16
+
 static inline gzvm_id_t get_vmid_from_tuple(unsigned int tuple)
 {
 	return (gzvm_id_t)(tuple >> 16);
@@ -57,6 +59,11 @@ static inline gzvm_vcpu_id_t get_vcpuid_from_tuple(unsigned int tuple)
 	return (gzvm_vcpu_id_t)(tuple & 0xffff);
 }
 
+struct gzvm_vcpu_hwstate {
+	__u32 nr_lrs;
+	__u64 lr[GIC_V3_NR_LRS];
+};
+
 static inline unsigned int
 assemble_vm_vcpu_tuple(gzvm_id_t vmid, gzvm_vcpu_id_t vcpuid)
 {
diff --git a/arch/arm64/geniezone/gzvm_irqchip.c b/arch/arm64/geniezone/gzvm_irqchip.c
index c46bd34fee1b..1887cbb58fc6 100644
--- a/arch/arm64/geniezone/gzvm_irqchip.c
+++ b/arch/arm64/geniezone/gzvm_irqchip.c
@@ -10,8 +10,15 @@
 #include <linux/gzvm_drv.h>
 #include "gzvm_arch.h"
 
+static bool lr_signals_eoi(uint64_t lr_val)
+{
+	return !(lr_val & ICH_LR_STATE) && (lr_val & ICH_LR_EOI) &&
+		 !(lr_val & ICH_LR_HW);
+}
+
 /**
- * gzvm_sync_vgic_state() - Check all LRs synced from gz hypervisor
+ * gzvm_sync_vgic_state() - Check all LRs synced from gz hypervisor.
+ * @vcpu: Pointer to gzvm_vcpu.
  *
  * Traverse all LRs, see if any EOIed vint, notify_acked_irq if any.
  * GZ does not fold/unfold everytime KVM_RUN, so we have to traverse all saved
@@ -20,6 +27,19 @@
  */
 void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu)
 {
+	int i;
+
+	for (i = 0; i < vcpu->hwstate->nr_lrs; i++) {
+		u32 vintid;
+		u64 lr_val = vcpu->hwstate->lr[i];
+		/* 0 means unused */
+		if (!lr_val)
+			continue;
+
+		vintid = lr_val & ICH_LR_VIRTUAL_ID_MASK;
+		if (lr_signals_eoi(lr_val))
+			gzvm_notify_acked_irq(vcpu->gzvm, vintid - VGIC_NR_PRIVATE_IRQS);
+	}
 }
 
 /* is_irq_valid() - Check the irq number and irq_type are matched */
diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile
index 8ebf2db0c970..8517549e7dfb 100644
--- a/drivers/virt/geniezone/Makefile
+++ b/drivers/virt/geniezone/Makefile
@@ -7,5 +7,5 @@
 GZVM_DIR ?= ../../../drivers/virt/geniezone
 
 gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o \
-	  $(GZVM_DIR)/gzvm_vcpu.o
+	  $(GZVM_DIR)/gzvm_vcpu.o $(GZVM_DIR)/gzvm_irqfd.o
 
diff --git a/drivers/virt/geniezone/gzvm_irqfd.c b/drivers/virt/geniezone/gzvm_irqfd.c
new file mode 100644
index 000000000000..2594b2fe2e4e
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_irqfd.c
@@ -0,0 +1,536 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/eventfd.h>
+#include <linux/syscalls.h>
+#include <linux/gzvm_drv.h>
+
+struct gzvm_irq_ack_notifier {
+	struct hlist_node link;
+	unsigned int gsi;
+	void (*irq_acked)(struct gzvm_irq_ack_notifier *ian);
+};
+
+/**
+ * struct gzvm_kernel_irqfd_resampler - irqfd resampler descriptor.
+ * @gzvm: Poiner to gzvm.
+ * @list_head list: List of resampling struct _irqfd objects sharing this gsi.
+ *		    RCU list modified under gzvm->irqfds.resampler_lock.
+ * @notifier: gzvm irq ack notifier.
+ * @list_head link: Entry in list of gzvm->irqfd.resampler_list.
+ *		    Use for sharing esamplers among irqfds on the same gsi.
+ *		    Accessed and modified under gzvm->irqfds.resampler_lock.
+ *
+ * Resampling irqfds are a special variety of irqfds used to emulate
+ * level triggered interrupts.  The interrupt is asserted on eventfd
+ * trigger.  On acknowledgment through the irq ack notifier, the
+ * interrupt is de-asserted and userspace is notified through the
+ * resamplefd.  All resamplers on the same gsi are de-asserted
+ * together, so we don't need to track the state of each individual
+ * user.  We can also therefore share the same irq source ID.
+ */
+struct gzvm_kernel_irqfd_resampler {
+	struct gzvm *gzvm;
+
+	struct list_head list;
+	struct gzvm_irq_ack_notifier notifier;
+
+	struct list_head link;
+};
+
+/**
+ * struct gzvm_kernel_irqfd: gzvm kernel irqfd descriptor.
+ * @gzvm: Pointer to gzvm.
+ * @wait: Wait queue entry.
+ * @gsi: Used for level IRQ fast-path.
+ * @resampler: The resampler used by this irqfd (resampler-only).
+ * @resamplefd: Eventfd notified on resample (resampler-only).
+ * @resampler_link: Entry in list of irqfds for a resampler (resampler-only).
+ * @eventfd: Used for setup/shutdown.
+ */
+struct gzvm_kernel_irqfd {
+	struct gzvm *gzvm;
+	wait_queue_entry_t wait;
+
+	int gsi;
+
+	struct gzvm_kernel_irqfd_resampler *resampler;
+
+	struct eventfd_ctx *resamplefd;
+
+	struct list_head resampler_link;
+
+	struct eventfd_ctx *eventfd;
+	struct list_head list;
+	poll_table pt;
+	struct work_struct shutdown;
+};
+
+static struct workqueue_struct *irqfd_cleanup_wq;
+
+/**
+ * irqfd_set_spi(): irqfd to inject virtual interrupt.
+ * @gzvm: Pointer to gzvm.
+ * @irq_source_id: irq source id.
+ * @irq: This is spi interrupt number (starts from 0 instead of 32).
+ * @level: irq triggered level.
+ * @line_status: irq status.
+ */
+static void irqfd_set_spi(struct gzvm *gzvm, int irq_source_id, u32 irq,
+			  int level, bool line_status)
+{
+	if (level)
+		gzvm_arch_inject_irq(gzvm, irq_source_id, 0, irq, level);
+}
+
+/**
+ * irqfd_resampler_ack() - Notify all of the resampler irqfds using this GSI
+ *			   when IRQ de-assert once.
+ * @ian: Pointer to gzvm_irq_ack_notifier.
+ *
+ * Since resampler irqfds share an IRQ source ID, we de-assert once
+ * then notify all of the resampler irqfds using this GSI.  We can't
+ * do multiple de-asserts or we risk racing with incoming re-asserts.
+ */
+static void irqfd_resampler_ack(struct gzvm_irq_ack_notifier *ian)
+{
+	struct gzvm_kernel_irqfd_resampler *resampler;
+	struct gzvm *gzvm;
+	struct gzvm_kernel_irqfd *irqfd;
+	int idx;
+
+	resampler = container_of(ian,
+				 struct gzvm_kernel_irqfd_resampler, notifier);
+	gzvm = resampler->gzvm;
+
+	irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
+		      resampler->notifier.gsi, 0, false);
+
+	idx = srcu_read_lock(&gzvm->irq_srcu);
+
+	list_for_each_entry_srcu(irqfd, &resampler->list, resampler_link,
+				 srcu_read_lock_held(&gzvm->irq_srcu)) {
+		eventfd_signal(irqfd->resamplefd, 1);
+	}
+
+	srcu_read_unlock(&gzvm->irq_srcu, idx);
+}
+
+static void gzvm_register_irq_ack_notifier(struct gzvm *gzvm,
+					   struct gzvm_irq_ack_notifier *ian)
+{
+	mutex_lock(&gzvm->irq_lock);
+	hlist_add_head_rcu(&ian->link, &gzvm->irq_ack_notifier_list);
+	mutex_unlock(&gzvm->irq_lock);
+}
+
+static void gzvm_unregister_irq_ack_notifier(struct gzvm *gzvm,
+					     struct gzvm_irq_ack_notifier *ian)
+{
+	mutex_lock(&gzvm->irq_lock);
+	hlist_del_init_rcu(&ian->link);
+	mutex_unlock(&gzvm->irq_lock);
+	synchronize_srcu(&gzvm->irq_srcu);
+}
+
+static void irqfd_resampler_shutdown(struct gzvm_kernel_irqfd *irqfd)
+{
+	struct gzvm_kernel_irqfd_resampler *resampler = irqfd->resampler;
+	struct gzvm *gzvm = resampler->gzvm;
+
+	mutex_lock(&gzvm->irqfds.resampler_lock);
+
+	list_del_rcu(&irqfd->resampler_link);
+	synchronize_srcu(&gzvm->irq_srcu);
+
+	if (list_empty(&resampler->list)) {
+		list_del(&resampler->link);
+		gzvm_unregister_irq_ack_notifier(gzvm, &resampler->notifier);
+		irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
+			      resampler->notifier.gsi, 0, false);
+		kfree(resampler);
+	}
+
+	mutex_unlock(&gzvm->irqfds.resampler_lock);
+}
+
+/**
+ * irqfd_shutdown() - Race-free decouple logic (ordering is critical).
+ * @work: Pointer to work_struct.
+ */
+static void irqfd_shutdown(struct work_struct *work)
+{
+	struct gzvm_kernel_irqfd *irqfd =
+		container_of(work, struct gzvm_kernel_irqfd, shutdown);
+	struct gzvm *gzvm = irqfd->gzvm;
+	u64 cnt;
+
+	/* Make sure irqfd has been initialized in assign path. */
+	synchronize_srcu(&gzvm->irq_srcu);
+
+	/*
+	 * Synchronize with the wait-queue and unhook ourselves to prevent
+	 * further events.
+	 */
+	eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt);
+
+	if (irqfd->resampler) {
+		irqfd_resampler_shutdown(irqfd);
+		eventfd_ctx_put(irqfd->resamplefd);
+	}
+
+	/*
+	 * It is now safe to release the object's resources
+	 */
+	eventfd_ctx_put(irqfd->eventfd);
+	kfree(irqfd);
+}
+
+/**
+ * irqfd_is_active() - Assumes gzvm->irqfds.lock is held.
+ * @irqfd: Pointer to gzvm_kernel_irqfd.
+ */
+static bool irqfd_is_active(struct gzvm_kernel_irqfd *irqfd)
+{
+	return list_empty(&irqfd->list) ? false : true;
+}
+
+/**
+ * irqfd_deactivate() - Mark the irqfd as inactive and schedule it for removal.
+ *			assumes gzvm->irqfds.lock is held.
+ * @irqfd: Pointer to gzvm_kernel_irqfd.
+ */
+static void irqfd_deactivate(struct gzvm_kernel_irqfd *irqfd)
+{
+	if (!irqfd_is_active(irqfd))
+		return;
+
+	list_del_init(&irqfd->list);
+
+	queue_work(irqfd_cleanup_wq, &irqfd->shutdown);
+}
+
+/**
+ * irqfd_wakeup() - Wake up irqfd to do virtual interrupt injection.
+ * @wait: Pointer to wait_queue_entry_t.
+ * @mode:
+ * @sync:
+ * @key:
+ */
+static int irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync,
+			void *key)
+{
+	struct gzvm_kernel_irqfd *irqfd =
+		container_of(wait, struct gzvm_kernel_irqfd, wait);
+	__poll_t flags = key_to_poll(key);
+	struct gzvm *gzvm = irqfd->gzvm;
+
+	if (flags & EPOLLIN) {
+		u64 cnt;
+
+		eventfd_ctx_do_read(irqfd->eventfd, &cnt);
+		/* gzvm's irq injection is not blocked, don't need workq */
+		irqfd_set_spi(gzvm, GZVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi,
+			      1, false);
+	}
+
+	if (flags & EPOLLHUP) {
+		/* The eventfd is closing, detach from GZVM */
+		unsigned long iflags;
+
+		spin_lock_irqsave(&gzvm->irqfds.lock, iflags);
+
+		/*
+		 * Do more check if someone deactivated the irqfd before
+		 * we could acquire the irqfds.lock.
+		 */
+		if (irqfd_is_active(irqfd))
+			irqfd_deactivate(irqfd);
+
+		spin_unlock_irqrestore(&gzvm->irqfds.lock, iflags);
+	}
+
+	return 0;
+}
+
+static void irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh,
+				    poll_table *pt)
+{
+	struct gzvm_kernel_irqfd *irqfd =
+		container_of(pt, struct gzvm_kernel_irqfd, pt);
+	add_wait_queue_priority(wqh, &irqfd->wait);
+}
+
+static int gzvm_irqfd_assign(struct gzvm *gzvm, struct gzvm_irqfd *args)
+{
+	struct gzvm_kernel_irqfd *irqfd, *tmp;
+	struct fd f;
+	struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
+	int ret;
+	__poll_t events;
+	int idx;
+
+	irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT);
+	if (!irqfd)
+		return -ENOMEM;
+
+	irqfd->gzvm = gzvm;
+	irqfd->gsi = args->gsi;
+	irqfd->resampler = NULL;
+
+	INIT_LIST_HEAD(&irqfd->list);
+	INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
+
+	f = fdget(args->fd);
+	if (!f.file) {
+		ret = -EBADF;
+		goto out;
+	}
+
+	eventfd = eventfd_ctx_fileget(f.file);
+	if (IS_ERR(eventfd)) {
+		ret = PTR_ERR(eventfd);
+		goto fail;
+	}
+
+	irqfd->eventfd = eventfd;
+
+	if (args->flags & GZVM_IRQFD_FLAG_RESAMPLE) {
+		struct gzvm_kernel_irqfd_resampler *resampler;
+
+		resamplefd = eventfd_ctx_fdget(args->resamplefd);
+		if (IS_ERR(resamplefd)) {
+			ret = PTR_ERR(resamplefd);
+			goto fail;
+		}
+
+		irqfd->resamplefd = resamplefd;
+		INIT_LIST_HEAD(&irqfd->resampler_link);
+
+		mutex_lock(&gzvm->irqfds.resampler_lock);
+
+		list_for_each_entry(resampler,
+				    &gzvm->irqfds.resampler_list, link) {
+			if (resampler->notifier.gsi == irqfd->gsi) {
+				irqfd->resampler = resampler;
+				break;
+			}
+		}
+
+		if (!irqfd->resampler) {
+			resampler = kzalloc(sizeof(*resampler),
+					    GFP_KERNEL_ACCOUNT);
+			if (!resampler) {
+				ret = -ENOMEM;
+				mutex_unlock(&gzvm->irqfds.resampler_lock);
+				goto fail;
+			}
+
+			resampler->gzvm = gzvm;
+			INIT_LIST_HEAD(&resampler->list);
+			resampler->notifier.gsi = irqfd->gsi;
+			resampler->notifier.irq_acked = irqfd_resampler_ack;
+			INIT_LIST_HEAD(&resampler->link);
+
+			list_add(&resampler->link, &gzvm->irqfds.resampler_list);
+			gzvm_register_irq_ack_notifier(gzvm,
+						       &resampler->notifier);
+			irqfd->resampler = resampler;
+		}
+
+		list_add_rcu(&irqfd->resampler_link, &irqfd->resampler->list);
+		synchronize_srcu(&gzvm->irq_srcu);
+
+		mutex_unlock(&gzvm->irqfds.resampler_lock);
+	}
+
+	/*
+	 * Install our own custom wake-up handling so we are notified via
+	 * a callback whenever someone signals the underlying eventfd
+	 */
+	init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup);
+	init_poll_funcptr(&irqfd->pt, irqfd_ptable_queue_proc);
+
+	spin_lock_irq(&gzvm->irqfds.lock);
+
+	ret = 0;
+	list_for_each_entry(tmp, &gzvm->irqfds.items, list) {
+		if (irqfd->eventfd != tmp->eventfd)
+			continue;
+		/* This fd is used for another irq already. */
+		pr_err("already used: gsi=%d fd=%d\n", args->gsi, args->fd);
+		ret = -EBUSY;
+		spin_unlock_irq(&gzvm->irqfds.lock);
+		goto fail;
+	}
+
+	idx = srcu_read_lock(&gzvm->irq_srcu);
+
+	list_add_tail(&irqfd->list, &gzvm->irqfds.items);
+
+	spin_unlock_irq(&gzvm->irqfds.lock);
+
+	/*
+	 * Check if there was an event already pending on the eventfd
+	 * before we registered, and trigger it as if we didn't miss it.
+	 */
+	events = vfs_poll(f.file, &irqfd->pt);
+
+	/* In case there is already a pending event */
+	if (events & EPOLLIN)
+		irqfd_set_spi(gzvm, GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
+			      irqfd->gsi, 1, false);
+
+	srcu_read_unlock(&gzvm->irq_srcu, idx);
+
+	/*
+	 * do not drop the file until the irqfd is fully initialized, otherwise
+	 * we might race against the EPOLLHUP
+	 */
+	fdput(f);
+	return 0;
+
+fail:
+	if (irqfd->resampler)
+		irqfd_resampler_shutdown(irqfd);
+
+	if (resamplefd && !IS_ERR(resamplefd))
+		eventfd_ctx_put(resamplefd);
+
+	if (eventfd && !IS_ERR(eventfd))
+		eventfd_ctx_put(eventfd);
+
+	fdput(f);
+
+out:
+	kfree(irqfd);
+	return ret;
+}
+
+static void gzvm_notify_acked_gsi(struct gzvm *gzvm, int gsi)
+{
+	struct gzvm_irq_ack_notifier *gian;
+
+	hlist_for_each_entry_srcu(gian, &gzvm->irq_ack_notifier_list,
+				  link, srcu_read_lock_held(&gzvm->irq_srcu))
+		if (gian->gsi == gsi)
+			gian->irq_acked(gian);
+}
+
+void gzvm_notify_acked_irq(struct gzvm *gzvm, unsigned int gsi)
+{
+	int idx;
+
+	idx = srcu_read_lock(&gzvm->irq_srcu);
+	gzvm_notify_acked_gsi(gzvm, gsi);
+	srcu_read_unlock(&gzvm->irq_srcu, idx);
+}
+
+/**
+ * gzvm_irqfd_deassign() - Shutdown any irqfd's that match fd+gsi.
+ * @gzvm: Pointer to gzvm.
+ * @args: Pointer to gzvm_irqfd.
+ */
+static int gzvm_irqfd_deassign(struct gzvm *gzvm, struct gzvm_irqfd *args)
+{
+	struct gzvm_kernel_irqfd *irqfd, *tmp;
+	struct eventfd_ctx *eventfd;
+
+	eventfd = eventfd_ctx_fdget(args->fd);
+	if (IS_ERR(eventfd))
+		return PTR_ERR(eventfd);
+
+	spin_lock_irq(&gzvm->irqfds.lock);
+
+	list_for_each_entry_safe(irqfd, tmp, &gzvm->irqfds.items, list) {
+		if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi)
+			irqfd_deactivate(irqfd);
+	}
+
+	spin_unlock_irq(&gzvm->irqfds.lock);
+	eventfd_ctx_put(eventfd);
+
+	/*
+	 * Block until we know all outstanding shutdown jobs have completed
+	 * so that we guarantee there will not be any more interrupts on this
+	 * gsi once this deassign function returns.
+	 */
+	flush_workqueue(irqfd_cleanup_wq);
+
+	return 0;
+}
+
+int gzvm_irqfd(struct gzvm *gzvm, struct gzvm_irqfd *args)
+{
+	if (args->flags &
+	    ~(GZVM_IRQFD_FLAG_DEASSIGN | GZVM_IRQFD_FLAG_RESAMPLE))
+		return -EINVAL;
+
+	if (args->flags & GZVM_IRQFD_FLAG_DEASSIGN)
+		return gzvm_irqfd_deassign(gzvm, args);
+
+	return gzvm_irqfd_assign(gzvm, args);
+}
+
+/**
+ * gzvm_vm_irqfd_init() - Initialize irqfd data structure per VM
+ */
+int gzvm_vm_irqfd_init(struct gzvm *gzvm)
+{
+	mutex_init(&gzvm->irq_lock);
+
+	spin_lock_init(&gzvm->irqfds.lock);
+	INIT_LIST_HEAD(&gzvm->irqfds.items);
+	INIT_LIST_HEAD(&gzvm->irqfds.resampler_list);
+	if (init_srcu_struct(&gzvm->irq_srcu))
+		return -EINVAL;
+	INIT_HLIST_HEAD(&gzvm->irq_ack_notifier_list);
+	mutex_init(&gzvm->irqfds.resampler_lock);
+
+	return 0;
+}
+
+/**
+ * gzvm_irqfd_release() - This function is called as the gzvm VM fd is being
+ *			  released. Shutdown all irqfds that still remain open.
+ * @gzvm: Pointer to gzvm.
+ */
+void gzvm_vm_irqfd_release(struct gzvm *gzvm)
+{
+	struct gzvm_kernel_irqfd *irqfd, *tmp;
+
+	spin_lock_irq(&gzvm->irqfds.lock);
+
+	list_for_each_entry_safe(irqfd, tmp, &gzvm->irqfds.items, list)
+		irqfd_deactivate(irqfd);
+
+	spin_unlock_irq(&gzvm->irqfds.lock);
+
+	/*
+	 * Block until we know all outstanding shutdown jobs have completed.
+	 */
+	flush_workqueue(irqfd_cleanup_wq);
+}
+
+/**
+ * gzvm_irqfd_init() - Erase flushing work items when a VM exits.
+ *
+ * Create a host-wide workqueue for issuing deferred shutdown requests
+ * aggregated from all vm* instances. We need our own isolated
+ * queue to ease flushing work items when a VM exits.
+ */
+int gzvm_drv_irqfd_init(void)
+{
+	irqfd_cleanup_wq = alloc_workqueue("gzvm-irqfd-cleanup", 0, 0);
+	if (!irqfd_cleanup_wq)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void gzvm_drv_irqfd_exit(void)
+{
+	destroy_workqueue(irqfd_cleanup_wq);
+}
diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c
index e3fe3ad9ffce..121816a09c8e 100644
--- a/drivers/virt/geniezone/gzvm_main.c
+++ b/drivers/virt/geniezone/gzvm_main.c
@@ -113,11 +113,16 @@ static int gzvm_drv_probe(struct platform_device *pdev)
 		return ret;
 	gzvm_debug_dev = pdev;
 
+	ret = gzvm_drv_irqfd_init();
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
 static int gzvm_drv_remove(struct platform_device *pdev)
 {
+	gzvm_drv_irqfd_exit();
 	destroy_all_vm();
 	misc_deregister(&gzvm_dev);
 	return 0;
diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c
index 65b1a2372b30..faee2ee64639 100644
--- a/drivers/virt/geniezone/gzvm_vcpu.c
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -211,6 +211,7 @@ int gzvm_vm_ioctl_create_vcpu(struct gzvm *gzvm, u32 cpuid)
 		ret = -ENOMEM;
 		goto free_vcpu;
 	}
+	vcpu->hwstate = (void *)vcpu->run + PAGE_SIZE;
 	vcpu->vcpuid = cpuid;
 	vcpu->gzvm = gzvm;
 	mutex_init(&vcpu->lock);
diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
index a5444541b745..eb34d7ba94a2 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -295,6 +295,15 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl,
 		ret = gzvm_vm_ioctl_create_device(gzvm, argp);
 		break;
 	}
+	case GZVM_IRQFD: {
+		struct gzvm_irqfd data;
+
+		ret = -EFAULT;
+		if (copy_from_user(&data, argp, sizeof(data)))
+			goto out;
+		ret = gzvm_irqfd(gzvm, &data);
+		break;
+	}
 	case GZVM_ENABLE_CAP: {
 		struct gzvm_enable_cap cap;
 
@@ -319,6 +328,8 @@ static void gzvm_destroy_vm(struct gzvm *gzvm)
 
 	mutex_lock(&gzvm->lock);
 
+	gzvm_vm_irqfd_release(gzvm);
+	gzvm_destroy_vcpus(gzvm);
 	gzvm_arch_destroy_vm(gzvm->vm_id);
 
 	gzvm_destroy_vcpus(gzvm);
@@ -365,6 +376,14 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
 	gzvm->mm = current->mm;
 	mutex_init(&gzvm->lock);
 
+	ret = gzvm_vm_irqfd_init(gzvm);
+	if (ret) {
+		dev_err(&gzvm_debug_dev->dev,
+			"Failed to initialize irqfd\n");
+		kfree(gzvm);
+		return ERR_PTR(ret);
+	}
+
 	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 1e7c81597e9a..a54a7915c514 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -10,6 +10,7 @@
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/gzvm.h>
+#include <linux/srcu.h>
 
 #define MODULE_NAME	"gzvm"
 #define GZVM_VCPU_MMAP_SIZE  PAGE_SIZE
@@ -25,6 +26,8 @@
 #define ERR_NOT_SUPPORTED       (-24)
 #define ERR_NOT_IMPLEMENTED     (-27)
 #define ERR_FAULT               (-40)
+#define GZVM_USERSPACE_IRQ_SOURCE_ID            0
+#define GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID       1
 
 /*
  * The following data structures are for data transferring between driver and
@@ -68,6 +71,7 @@ struct gzvm_vcpu {
 	/* lock of vcpu*/
 	struct mutex lock;
 	struct gzvm_vcpu_run *run;
+	struct gzvm_vcpu_hwstate *hwstate;
 };
 
 struct gzvm {
@@ -77,8 +81,23 @@ struct gzvm {
 	struct gzvm_memslot memslot[GZVM_MAX_MEM_REGION];
 	/* lock for list_add*/
 	struct mutex lock;
+
+	struct {
+		/* lock for irqfds list operation */
+		spinlock_t        lock;
+		struct list_head  items;
+		struct list_head  resampler_list;
+		/* lock for irqfds resampler */
+		struct mutex      resampler_lock;
+	} irqfds;
+
 	struct list_head vm_list;
 	gzvm_id_t vm_id;
+
+	struct hlist_head irq_ack_notifier_list;
+	struct srcu_struct irq_srcu;
+	/* lock for irq injection */
+	struct mutex irq_lock;
 };
 
 long gzvm_dev_ioctl_check_extension(struct gzvm *gzvm, unsigned long args);
@@ -111,6 +130,14 @@ int gzvm_arch_create_device(gzvm_id_t vm_id, struct gzvm_create_device *gzvm_dev
 int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx, u32 irq_type,
 			 u32 irq, bool level);
 
+void gzvm_notify_acked_irq(struct gzvm *gzvm, unsigned int gsi);
+int gzvm_irqfd(struct gzvm *gzvm, struct gzvm_irqfd *args);
+int gzvm_drv_irqfd_init(void);
+void gzvm_drv_irqfd_exit(void);
+int gzvm_vm_irqfd_init(struct gzvm *gzvm);
+void gzvm_vm_irqfd_release(struct gzvm *gzvm);
+void gzvm_sync_hwstate(struct gzvm_vcpu *vcpu);
+
 extern struct platform_device *gzvm_debug_dev;
 
 #endif /* __GZVM_DRV_H__ */
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
index 2f56a53efb27..b878b25ff963 100644
--- a/include/uapi/linux/gzvm.h
+++ b/include/uapi/linux/gzvm.h
@@ -230,4 +230,22 @@ struct gzvm_one_reg {
 
 #define GZVM_REG_GENERIC	   0x0000000000000000ULL
 
-#endif /* __GZVM_H__ */
+#define GZVM_IRQFD_FLAG_DEASSIGN	(1 << 0)
+/**
+ * GZVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
+ * the irqfd to operate in resampling mode for level triggered interrupt
+ * emulation.
+ */
+#define GZVM_IRQFD_FLAG_RESAMPLE	(1 << 1)
+
+struct gzvm_irqfd {
+	__u32 fd;
+	__u32 gsi;
+	__u32 flags;
+	__u32 resamplefd;
+	__u8  pad[16];
+};
+
+#define GZVM_IRQFD	_IOW(GZVM_IOC_MAGIC, 0x76, struct gzvm_irqfd)
+
+#endif /* __GZVM__H__ */
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 7/7] virt: geniezone: Add ioeventfd support
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 10:36   ` Yi-De Wu
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

Ioeventfd leverages eventfd to provide asynchronous notification
mechanism for VMM. VMM can register a mmio address and bind with an
eventfd. Once a mmio trap occurs on this registered region, its
corresponding eventfd will be notified.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 drivers/virt/geniezone/Makefile         |   3 +-
 drivers/virt/geniezone/gzvm_ioeventfd.c | 263 ++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_vcpu.c      |  29 ++-
 drivers/virt/geniezone/gzvm_vm.c        |  17 ++
 include/linux/gzvm_drv.h                |  11 +
 include/uapi/linux/gzvm.h               |  23 +++
 6 files changed, 343 insertions(+), 3 deletions(-)
 create mode 100644 drivers/virt/geniezone/gzvm_ioeventfd.c

diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile
index 8517549e7dfb..b1ecdd235a4e 100644
--- a/drivers/virt/geniezone/Makefile
+++ b/drivers/virt/geniezone/Makefile
@@ -7,5 +7,6 @@
 GZVM_DIR ?= ../../../drivers/virt/geniezone
 
 gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o \
-	  $(GZVM_DIR)/gzvm_vcpu.o $(GZVM_DIR)/gzvm_irqfd.o
+	  $(GZVM_DIR)/gzvm_vcpu.o $(GZVM_DIR)/gzvm_irqfd.o \
+	  $(GZVM_DIR)/gzvm_ioeventfd.o
 
diff --git a/drivers/virt/geniezone/gzvm_ioeventfd.c b/drivers/virt/geniezone/gzvm_ioeventfd.c
new file mode 100644
index 000000000000..f5664cab98c3
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_ioeventfd.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/syscalls.h>
+#include <linux/gzvm.h>
+#include <linux/gzvm_drv.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+struct gzvm_ioevent {
+	struct list_head list;
+	__u64 addr;
+	__u32 len;
+	struct eventfd_ctx  *evt_ctx;
+	__u64 datamatch;
+	bool wildcard;
+};
+
+/**
+ * ioeventfd_check_collision() - Check collison assumes gzvm->slots_lock held.
+ * @gzvm: Pointer to gzvm.
+ * @p: Pointer to gzvm_ioevent.
+ */
+static bool ioeventfd_check_collision(struct gzvm *gzvm, struct gzvm_ioevent *p)
+{
+	struct gzvm_ioevent *_p;
+
+	list_for_each_entry(_p, &gzvm->ioevents, list)
+		if (_p->addr == p->addr &&
+		    (!_p->len || !p->len ||
+		     (_p->len == p->len &&
+		      (_p->wildcard || p->wildcard ||
+		       _p->datamatch == p->datamatch))))
+			return true;
+
+	return false;
+}
+
+static void gzvm_ioevent_release(struct gzvm_ioevent *p)
+{
+	eventfd_ctx_put(p->evt_ctx);
+	list_del(&p->list);
+	kfree(p);
+}
+
+static bool gzvm_ioevent_in_range(struct gzvm_ioevent *p, __u64 addr, int len,
+				  const void *val)
+{
+	u64 _val;
+
+	if (addr != p->addr)
+		/* address must be precise for a hit */
+		return false;
+
+	if (!p->len)
+		/* length = 0 means only look at the address, so always a hit */
+		return true;
+
+	if (len != p->len)
+		/* address-range must be precise for a hit */
+		return false;
+
+	if (p->wildcard)
+		/* all else equal, wildcard is always a hit */
+		return true;
+
+	/* otherwise, we have to actually compare the data */
+
+	WARN_ON_ONCE(!IS_ALIGNED((unsigned long)val, len));
+
+	switch (len) {
+	case 1:
+		_val = *(u8 *)val;
+		break;
+	case 2:
+		_val = *(u16 *)val;
+		break;
+	case 4:
+		_val = *(u32 *)val;
+		break;
+	case 8:
+		_val = *(u64 *)val;
+		break;
+	default:
+		return false;
+	}
+
+	return _val == p->datamatch;
+}
+
+static int gzvm_deassign_ioeventfd(struct gzvm *gzvm,
+				   struct gzvm_ioeventfd *args)
+{
+	struct gzvm_ioevent *p, *tmp;
+	struct eventfd_ctx *evt_ctx;
+	int ret = -ENOENT;
+	bool wildcard;
+
+	evt_ctx = eventfd_ctx_fdget(args->fd);
+	if (IS_ERR(evt_ctx))
+		return PTR_ERR(evt_ctx);
+
+	wildcard = !(args->flags & GZVM_IOEVENTFD_FLAG_DATAMATCH);
+
+	mutex_lock(&gzvm->lock);
+
+	list_for_each_entry_safe(p, tmp, &gzvm->ioevents, list) {
+		if (p->evt_ctx != evt_ctx  ||
+		    p->addr != args->addr  ||
+		    p->len != args->len ||
+		    p->wildcard != wildcard)
+			continue;
+
+		if (!p->wildcard && p->datamatch != args->datamatch)
+			continue;
+
+		gzvm_ioevent_release(p);
+		ret = 0;
+		break;
+	}
+
+	mutex_unlock(&gzvm->lock);
+
+	/* got in the front of this function */
+	eventfd_ctx_put(evt_ctx);
+
+	return ret;
+}
+
+static int gzvm_assign_ioeventfd(struct gzvm *gzvm, struct gzvm_ioeventfd *args)
+{
+	struct eventfd_ctx *evt_ctx;
+	struct gzvm_ioevent *evt;
+	int ret;
+
+	evt_ctx = eventfd_ctx_fdget(args->fd);
+	if (IS_ERR(evt_ctx))
+		return PTR_ERR(evt_ctx);
+
+	evt = kmalloc(sizeof(*evt), GFP_KERNEL);
+	if (!evt)
+		return -ENOMEM;
+	*evt = (struct gzvm_ioevent) {
+		.addr = args->addr,
+		.len = args->len,
+		.evt_ctx = evt_ctx,
+	};
+	if (args->flags & GZVM_IOEVENTFD_FLAG_DATAMATCH) {
+		evt->datamatch = args->datamatch;
+		evt->wildcard = false;
+	} else {
+		evt->wildcard = true;
+	}
+
+	if (ioeventfd_check_collision(gzvm, evt)) {
+		ret = -EEXIST;
+		goto err_free;
+	}
+
+	mutex_lock(&gzvm->lock);
+	list_add_tail(&evt->list, &gzvm->ioevents);
+	mutex_unlock(&gzvm->lock);
+
+	return 0;
+
+err_free:
+	kfree(evt);
+	eventfd_ctx_put(evt_ctx);
+	return ret;
+}
+
+/**
+ * gzvm_ioeventfd_check_valid() - Check user arguments is valid.
+ * @args: Pointer to gzvm_ioeventfd.
+ *
+ * Return true if user arguments are valid.
+ * Return false if user arguments are invalid.
+ */
+static bool gzvm_ioeventfd_check_valid(struct gzvm_ioeventfd *args)
+{
+	/* must be natural-word sized, or 0 to ignore length */
+	switch (args->len) {
+	case 0:
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		break;
+	default:
+		return false;
+	}
+
+	/* check for range overflow */
+	if (args->addr + args->len < args->addr)
+		return false;
+
+	/* check for extra flags that we don't understand */
+	if (args->flags & ~GZVM_IOEVENTFD_VALID_FLAG_MASK)
+		return false;
+
+	/* ioeventfd with no length can't be combined with DATAMATCH */
+	if (!args->len && (args->flags & GZVM_IOEVENTFD_FLAG_DATAMATCH))
+		return false;
+
+	/* gzvm does not support pio bus ioeventfd */
+	if (args->flags & GZVM_IOEVENTFD_FLAG_PIO)
+		return false;
+
+	return true;
+}
+
+/**
+ * gzvm_ioeventfd() - Register ioevent to ioevent list.
+ * @gzvm: Pointer to gzvm.
+ * @args: Pointer to gzvm_ioeventfd.
+ */
+int gzvm_ioeventfd(struct gzvm *gzvm, struct gzvm_ioeventfd *args)
+{
+	if (gzvm_ioeventfd_check_valid(args) == false)
+		return -EINVAL;
+
+	if (args->flags & GZVM_IOEVENTFD_FLAG_DEASSIGN)
+		return gzvm_deassign_ioeventfd(gzvm, args);
+	return gzvm_assign_ioeventfd(gzvm, args);
+}
+
+/**
+ * gzvm_ioevent_write() - Travers this vm's registered ioeventfd to see if
+ *			  need notifying it.
+ * @vcpu: Pointer to vcpu.
+ * @addr: mmio address.
+ * @len: mmio size.
+ * @val: Pointer to void.
+ *
+ * Return true if this io is already sent to ioeventfd's listener.
+ * Return false if we cannot find any ioeventfd registering this mmio write.
+ */
+bool gzvm_ioevent_write(struct gzvm_vcpu *vcpu, __u64 addr, int len,
+			const void *val)
+{
+	struct gzvm_ioevent *e;
+
+	list_for_each_entry(e, &vcpu->gzvm->ioevents, list) {
+		if (gzvm_ioevent_in_range(e, addr, len, val)) {
+			eventfd_signal(e->evt_ctx, 1);
+			return true;
+		}
+	}
+	return false;
+}
+
+int gzvm_init_ioeventfd(struct gzvm *gzvm)
+{
+	INIT_LIST_HEAD(&gzvm->ioevents);
+
+	return 0;
+}
diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c
index faee2ee64639..cd5f5735ec3b 100644
--- a/drivers/virt/geniezone/gzvm_vcpu.c
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -49,10 +49,34 @@ static long gzvm_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, void * __user argp,
 	return 0;
 }
 
+/**
+ * gzvm_vcpu_handle_mmio() - Handle mmio in kernel space.
+ * @vcpu: Pointer to vcpu.
+ *
+ * Return:
+ * * true - This mmio exit has been processed.
+ * * false - This mmio exit has not been processed, require userspace.
+ */
+static bool gzvm_vcpu_handle_mmio(struct gzvm_vcpu *vcpu)
+{
+	__u64 addr;
+	__u32 len;
+	const void *val_ptr;
+
+	/* So far, we don't have in-kernel mmio read handler */
+	if (!vcpu->run->mmio.is_write)
+		return false;
+	addr = vcpu->run->mmio.phys_addr;
+	len = vcpu->run->mmio.size;
+	val_ptr = &vcpu->run->mmio.data;
+
+	return gzvm_ioevent_write(vcpu, addr, len, val_ptr);
+}
+
 /**
  * gzvm_vcpu_run() - Handle vcpu run ioctl, entry point to guest and exit
  *		     point from guest
- * @argp: pointer to struct gzvm_vcpu_run in userspace
+ * @argp: Pointer to struct gzvm_vcpu_run in userspace
  */
 static long gzvm_vcpu_run(struct gzvm_vcpu *vcpu, void * __user argp)
 {
@@ -70,7 +94,8 @@ static long gzvm_vcpu_run(struct gzvm_vcpu *vcpu, void * __user argp)
 
 		switch (exit_reason) {
 		case GZVM_EXIT_MMIO:
-			need_userspace = true;
+			if (!gzvm_vcpu_handle_mmio(vcpu))
+				need_userspace = true;
 			break;
 		/**
 		 * it's geniezone's responsibility to fill corresponding data
diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
index eb34d7ba94a2..6d31c25cec6b 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -304,6 +304,15 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl,
 		ret = gzvm_irqfd(gzvm, &data);
 		break;
 	}
+	case GZVM_IOEVENTFD: {
+		struct gzvm_ioeventfd data;
+
+		ret = -EFAULT;
+		if (copy_from_user(&data, argp, sizeof(data)))
+			goto out;
+		ret = gzvm_ioeventfd(gzvm, &data);
+		break;
+	}
 	case GZVM_ENABLE_CAP: {
 		struct gzvm_enable_cap cap;
 
@@ -384,6 +393,14 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
 		return ERR_PTR(ret);
 	}
 
+	ret = gzvm_init_ioeventfd(gzvm);
+	if (ret) {
+		dev_err(&gzvm_debug_dev->dev,
+			"Failed to initialize ioeventfd\n");
+		kfree(gzvm);
+		return ERR_PTR(ret);
+	}
+
 	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 a54a7915c514..3c9f617d6bf1 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -6,6 +6,7 @@
 #ifndef __GZVM_DRV_H__
 #define __GZVM_DRV_H__
 
+#include <linux/eventfd.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
@@ -91,6 +92,8 @@ struct gzvm {
 		struct mutex      resampler_lock;
 	} irqfds;
 
+	struct list_head ioevents;
+
 	struct list_head vm_list;
 	gzvm_id_t vm_id;
 
@@ -140,4 +143,12 @@ void gzvm_sync_hwstate(struct gzvm_vcpu *vcpu);
 
 extern struct platform_device *gzvm_debug_dev;
 
+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,
+			const void *val);
+void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt);
+struct vm_area_struct *vma_lookup(struct mm_struct *mm, unsigned long addr);
+void add_wait_queue_priority(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
+
 #endif /* __GZVM_DRV_H__ */
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
index b878b25ff963..02adb0305f70 100644
--- a/include/uapi/linux/gzvm.h
+++ b/include/uapi/linux/gzvm.h
@@ -248,4 +248,27 @@ struct gzvm_irqfd {
 
 #define GZVM_IRQFD	_IOW(GZVM_IOC_MAGIC, 0x76, struct gzvm_irqfd)
 
+enum {
+	gzvm_ioeventfd_flag_nr_datamatch,
+	gzvm_ioeventfd_flag_nr_pio,
+	gzvm_ioeventfd_flag_nr_deassign,
+	gzvm_ioeventfd_flag_nr_max,
+};
+
+#define GZVM_IOEVENTFD_FLAG_DATAMATCH	(1 << gzvm_ioeventfd_flag_nr_datamatch)
+#define GZVM_IOEVENTFD_FLAG_PIO		(1 << gzvm_ioeventfd_flag_nr_pio)
+#define GZVM_IOEVENTFD_FLAG_DEASSIGN	(1 << gzvm_ioeventfd_flag_nr_deassign)
+#define GZVM_IOEVENTFD_VALID_FLAG_MASK	((1 << gzvm_ioeventfd_flag_nr_max) - 1)
+
+struct gzvm_ioeventfd {
+	__u64 datamatch;
+	__u64 addr;        /* legal pio/mmio address */
+	__u32 len;         /* 1, 2, 4, or 8 bytes; or 0 to ignore length */
+	__s32 fd;
+	__u32 flags;
+	__u8  pad[36];
+};
+
+#define GZVM_IOEVENTFD	_IOW(GZVM_IOC_MAGIC, 0x79, struct gzvm_ioeventfd)
+
 #endif /* __GZVM__H__ */
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 7/7] virt: geniezone: Add ioeventfd support
@ 2023-04-28 10:36   ` Yi-De Wu
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu @ 2023-04-28 10:36 UTC (permalink / raw)
  To: Yingshiuan Pan, Ze-Yu Wang, Yi-De Wu, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>

Ioeventfd leverages eventfd to provide asynchronous notification
mechanism for VMM. VMM can register a mmio address and bind with an
eventfd. Once a mmio trap occurs on this registered region, its
corresponding eventfd will be notified.

Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
 drivers/virt/geniezone/Makefile         |   3 +-
 drivers/virt/geniezone/gzvm_ioeventfd.c | 263 ++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_vcpu.c      |  29 ++-
 drivers/virt/geniezone/gzvm_vm.c        |  17 ++
 include/linux/gzvm_drv.h                |  11 +
 include/uapi/linux/gzvm.h               |  23 +++
 6 files changed, 343 insertions(+), 3 deletions(-)
 create mode 100644 drivers/virt/geniezone/gzvm_ioeventfd.c

diff --git a/drivers/virt/geniezone/Makefile b/drivers/virt/geniezone/Makefile
index 8517549e7dfb..b1ecdd235a4e 100644
--- a/drivers/virt/geniezone/Makefile
+++ b/drivers/virt/geniezone/Makefile
@@ -7,5 +7,6 @@
 GZVM_DIR ?= ../../../drivers/virt/geniezone
 
 gzvm-y := $(GZVM_DIR)/gzvm_main.o $(GZVM_DIR)/gzvm_vm.o \
-	  $(GZVM_DIR)/gzvm_vcpu.o $(GZVM_DIR)/gzvm_irqfd.o
+	  $(GZVM_DIR)/gzvm_vcpu.o $(GZVM_DIR)/gzvm_irqfd.o \
+	  $(GZVM_DIR)/gzvm_ioeventfd.o
 
diff --git a/drivers/virt/geniezone/gzvm_ioeventfd.c b/drivers/virt/geniezone/gzvm_ioeventfd.c
new file mode 100644
index 000000000000..f5664cab98c3
--- /dev/null
+++ b/drivers/virt/geniezone/gzvm_ioeventfd.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/syscalls.h>
+#include <linux/gzvm.h>
+#include <linux/gzvm_drv.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+struct gzvm_ioevent {
+	struct list_head list;
+	__u64 addr;
+	__u32 len;
+	struct eventfd_ctx  *evt_ctx;
+	__u64 datamatch;
+	bool wildcard;
+};
+
+/**
+ * ioeventfd_check_collision() - Check collison assumes gzvm->slots_lock held.
+ * @gzvm: Pointer to gzvm.
+ * @p: Pointer to gzvm_ioevent.
+ */
+static bool ioeventfd_check_collision(struct gzvm *gzvm, struct gzvm_ioevent *p)
+{
+	struct gzvm_ioevent *_p;
+
+	list_for_each_entry(_p, &gzvm->ioevents, list)
+		if (_p->addr == p->addr &&
+		    (!_p->len || !p->len ||
+		     (_p->len == p->len &&
+		      (_p->wildcard || p->wildcard ||
+		       _p->datamatch == p->datamatch))))
+			return true;
+
+	return false;
+}
+
+static void gzvm_ioevent_release(struct gzvm_ioevent *p)
+{
+	eventfd_ctx_put(p->evt_ctx);
+	list_del(&p->list);
+	kfree(p);
+}
+
+static bool gzvm_ioevent_in_range(struct gzvm_ioevent *p, __u64 addr, int len,
+				  const void *val)
+{
+	u64 _val;
+
+	if (addr != p->addr)
+		/* address must be precise for a hit */
+		return false;
+
+	if (!p->len)
+		/* length = 0 means only look at the address, so always a hit */
+		return true;
+
+	if (len != p->len)
+		/* address-range must be precise for a hit */
+		return false;
+
+	if (p->wildcard)
+		/* all else equal, wildcard is always a hit */
+		return true;
+
+	/* otherwise, we have to actually compare the data */
+
+	WARN_ON_ONCE(!IS_ALIGNED((unsigned long)val, len));
+
+	switch (len) {
+	case 1:
+		_val = *(u8 *)val;
+		break;
+	case 2:
+		_val = *(u16 *)val;
+		break;
+	case 4:
+		_val = *(u32 *)val;
+		break;
+	case 8:
+		_val = *(u64 *)val;
+		break;
+	default:
+		return false;
+	}
+
+	return _val == p->datamatch;
+}
+
+static int gzvm_deassign_ioeventfd(struct gzvm *gzvm,
+				   struct gzvm_ioeventfd *args)
+{
+	struct gzvm_ioevent *p, *tmp;
+	struct eventfd_ctx *evt_ctx;
+	int ret = -ENOENT;
+	bool wildcard;
+
+	evt_ctx = eventfd_ctx_fdget(args->fd);
+	if (IS_ERR(evt_ctx))
+		return PTR_ERR(evt_ctx);
+
+	wildcard = !(args->flags & GZVM_IOEVENTFD_FLAG_DATAMATCH);
+
+	mutex_lock(&gzvm->lock);
+
+	list_for_each_entry_safe(p, tmp, &gzvm->ioevents, list) {
+		if (p->evt_ctx != evt_ctx  ||
+		    p->addr != args->addr  ||
+		    p->len != args->len ||
+		    p->wildcard != wildcard)
+			continue;
+
+		if (!p->wildcard && p->datamatch != args->datamatch)
+			continue;
+
+		gzvm_ioevent_release(p);
+		ret = 0;
+		break;
+	}
+
+	mutex_unlock(&gzvm->lock);
+
+	/* got in the front of this function */
+	eventfd_ctx_put(evt_ctx);
+
+	return ret;
+}
+
+static int gzvm_assign_ioeventfd(struct gzvm *gzvm, struct gzvm_ioeventfd *args)
+{
+	struct eventfd_ctx *evt_ctx;
+	struct gzvm_ioevent *evt;
+	int ret;
+
+	evt_ctx = eventfd_ctx_fdget(args->fd);
+	if (IS_ERR(evt_ctx))
+		return PTR_ERR(evt_ctx);
+
+	evt = kmalloc(sizeof(*evt), GFP_KERNEL);
+	if (!evt)
+		return -ENOMEM;
+	*evt = (struct gzvm_ioevent) {
+		.addr = args->addr,
+		.len = args->len,
+		.evt_ctx = evt_ctx,
+	};
+	if (args->flags & GZVM_IOEVENTFD_FLAG_DATAMATCH) {
+		evt->datamatch = args->datamatch;
+		evt->wildcard = false;
+	} else {
+		evt->wildcard = true;
+	}
+
+	if (ioeventfd_check_collision(gzvm, evt)) {
+		ret = -EEXIST;
+		goto err_free;
+	}
+
+	mutex_lock(&gzvm->lock);
+	list_add_tail(&evt->list, &gzvm->ioevents);
+	mutex_unlock(&gzvm->lock);
+
+	return 0;
+
+err_free:
+	kfree(evt);
+	eventfd_ctx_put(evt_ctx);
+	return ret;
+}
+
+/**
+ * gzvm_ioeventfd_check_valid() - Check user arguments is valid.
+ * @args: Pointer to gzvm_ioeventfd.
+ *
+ * Return true if user arguments are valid.
+ * Return false if user arguments are invalid.
+ */
+static bool gzvm_ioeventfd_check_valid(struct gzvm_ioeventfd *args)
+{
+	/* must be natural-word sized, or 0 to ignore length */
+	switch (args->len) {
+	case 0:
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		break;
+	default:
+		return false;
+	}
+
+	/* check for range overflow */
+	if (args->addr + args->len < args->addr)
+		return false;
+
+	/* check for extra flags that we don't understand */
+	if (args->flags & ~GZVM_IOEVENTFD_VALID_FLAG_MASK)
+		return false;
+
+	/* ioeventfd with no length can't be combined with DATAMATCH */
+	if (!args->len && (args->flags & GZVM_IOEVENTFD_FLAG_DATAMATCH))
+		return false;
+
+	/* gzvm does not support pio bus ioeventfd */
+	if (args->flags & GZVM_IOEVENTFD_FLAG_PIO)
+		return false;
+
+	return true;
+}
+
+/**
+ * gzvm_ioeventfd() - Register ioevent to ioevent list.
+ * @gzvm: Pointer to gzvm.
+ * @args: Pointer to gzvm_ioeventfd.
+ */
+int gzvm_ioeventfd(struct gzvm *gzvm, struct gzvm_ioeventfd *args)
+{
+	if (gzvm_ioeventfd_check_valid(args) == false)
+		return -EINVAL;
+
+	if (args->flags & GZVM_IOEVENTFD_FLAG_DEASSIGN)
+		return gzvm_deassign_ioeventfd(gzvm, args);
+	return gzvm_assign_ioeventfd(gzvm, args);
+}
+
+/**
+ * gzvm_ioevent_write() - Travers this vm's registered ioeventfd to see if
+ *			  need notifying it.
+ * @vcpu: Pointer to vcpu.
+ * @addr: mmio address.
+ * @len: mmio size.
+ * @val: Pointer to void.
+ *
+ * Return true if this io is already sent to ioeventfd's listener.
+ * Return false if we cannot find any ioeventfd registering this mmio write.
+ */
+bool gzvm_ioevent_write(struct gzvm_vcpu *vcpu, __u64 addr, int len,
+			const void *val)
+{
+	struct gzvm_ioevent *e;
+
+	list_for_each_entry(e, &vcpu->gzvm->ioevents, list) {
+		if (gzvm_ioevent_in_range(e, addr, len, val)) {
+			eventfd_signal(e->evt_ctx, 1);
+			return true;
+		}
+	}
+	return false;
+}
+
+int gzvm_init_ioeventfd(struct gzvm *gzvm)
+{
+	INIT_LIST_HEAD(&gzvm->ioevents);
+
+	return 0;
+}
diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c
index faee2ee64639..cd5f5735ec3b 100644
--- a/drivers/virt/geniezone/gzvm_vcpu.c
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -49,10 +49,34 @@ static long gzvm_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, void * __user argp,
 	return 0;
 }
 
+/**
+ * gzvm_vcpu_handle_mmio() - Handle mmio in kernel space.
+ * @vcpu: Pointer to vcpu.
+ *
+ * Return:
+ * * true - This mmio exit has been processed.
+ * * false - This mmio exit has not been processed, require userspace.
+ */
+static bool gzvm_vcpu_handle_mmio(struct gzvm_vcpu *vcpu)
+{
+	__u64 addr;
+	__u32 len;
+	const void *val_ptr;
+
+	/* So far, we don't have in-kernel mmio read handler */
+	if (!vcpu->run->mmio.is_write)
+		return false;
+	addr = vcpu->run->mmio.phys_addr;
+	len = vcpu->run->mmio.size;
+	val_ptr = &vcpu->run->mmio.data;
+
+	return gzvm_ioevent_write(vcpu, addr, len, val_ptr);
+}
+
 /**
  * gzvm_vcpu_run() - Handle vcpu run ioctl, entry point to guest and exit
  *		     point from guest
- * @argp: pointer to struct gzvm_vcpu_run in userspace
+ * @argp: Pointer to struct gzvm_vcpu_run in userspace
  */
 static long gzvm_vcpu_run(struct gzvm_vcpu *vcpu, void * __user argp)
 {
@@ -70,7 +94,8 @@ static long gzvm_vcpu_run(struct gzvm_vcpu *vcpu, void * __user argp)
 
 		switch (exit_reason) {
 		case GZVM_EXIT_MMIO:
-			need_userspace = true;
+			if (!gzvm_vcpu_handle_mmio(vcpu))
+				need_userspace = true;
 			break;
 		/**
 		 * it's geniezone's responsibility to fill corresponding data
diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
index eb34d7ba94a2..6d31c25cec6b 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -304,6 +304,15 @@ static long gzvm_vm_ioctl(struct file *filp, unsigned int ioctl,
 		ret = gzvm_irqfd(gzvm, &data);
 		break;
 	}
+	case GZVM_IOEVENTFD: {
+		struct gzvm_ioeventfd data;
+
+		ret = -EFAULT;
+		if (copy_from_user(&data, argp, sizeof(data)))
+			goto out;
+		ret = gzvm_ioeventfd(gzvm, &data);
+		break;
+	}
 	case GZVM_ENABLE_CAP: {
 		struct gzvm_enable_cap cap;
 
@@ -384,6 +393,14 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
 		return ERR_PTR(ret);
 	}
 
+	ret = gzvm_init_ioeventfd(gzvm);
+	if (ret) {
+		dev_err(&gzvm_debug_dev->dev,
+			"Failed to initialize ioeventfd\n");
+		kfree(gzvm);
+		return ERR_PTR(ret);
+	}
+
 	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 a54a7915c514..3c9f617d6bf1 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -6,6 +6,7 @@
 #ifndef __GZVM_DRV_H__
 #define __GZVM_DRV_H__
 
+#include <linux/eventfd.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
@@ -91,6 +92,8 @@ struct gzvm {
 		struct mutex      resampler_lock;
 	} irqfds;
 
+	struct list_head ioevents;
+
 	struct list_head vm_list;
 	gzvm_id_t vm_id;
 
@@ -140,4 +143,12 @@ void gzvm_sync_hwstate(struct gzvm_vcpu *vcpu);
 
 extern struct platform_device *gzvm_debug_dev;
 
+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,
+			const void *val);
+void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt);
+struct vm_area_struct *vma_lookup(struct mm_struct *mm, unsigned long addr);
+void add_wait_queue_priority(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
+
 #endif /* __GZVM_DRV_H__ */
diff --git a/include/uapi/linux/gzvm.h b/include/uapi/linux/gzvm.h
index b878b25ff963..02adb0305f70 100644
--- a/include/uapi/linux/gzvm.h
+++ b/include/uapi/linux/gzvm.h
@@ -248,4 +248,27 @@ struct gzvm_irqfd {
 
 #define GZVM_IRQFD	_IOW(GZVM_IOC_MAGIC, 0x76, struct gzvm_irqfd)
 
+enum {
+	gzvm_ioeventfd_flag_nr_datamatch,
+	gzvm_ioeventfd_flag_nr_pio,
+	gzvm_ioeventfd_flag_nr_deassign,
+	gzvm_ioeventfd_flag_nr_max,
+};
+
+#define GZVM_IOEVENTFD_FLAG_DATAMATCH	(1 << gzvm_ioeventfd_flag_nr_datamatch)
+#define GZVM_IOEVENTFD_FLAG_PIO		(1 << gzvm_ioeventfd_flag_nr_pio)
+#define GZVM_IOEVENTFD_FLAG_DEASSIGN	(1 << gzvm_ioeventfd_flag_nr_deassign)
+#define GZVM_IOEVENTFD_VALID_FLAG_MASK	((1 << gzvm_ioeventfd_flag_nr_max) - 1)
+
+struct gzvm_ioeventfd {
+	__u64 datamatch;
+	__u64 addr;        /* legal pio/mmio address */
+	__u32 len;         /* 1, 2, 4, or 8 bytes; or 0 to ignore length */
+	__s32 fd;
+	__u32 flags;
+	__u8  pad[36];
+};
+
+#define GZVM_IOEVENTFD	_IOW(GZVM_IOC_MAGIC, 0x79, struct gzvm_ioeventfd)
+
 #endif /* __GZVM__H__ */
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 0/7] GenieZone hypervisor drivers
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 12:25   ` Krzysztof Kozlowski
  -1 siblings, 0 replies; 66+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-28 12:25 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

On 28/04/2023 12:36, Yi-De Wu wrote:
> This series is based on linux-next, tag: next-20230427.
> 
> Changes in v2:
> - Refactor: move to drivers/virt/geniezone
> - Refactor: decouple arch-dependent and arch-independent
> - Check pending signal before entering guest context
> - Fix reviewer's comments
> 

Please explain what is Geniezone, where we can find it, what's the plan
for open-sourcing it etc.

That's what cover letter is for.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 0/7] GenieZone hypervisor drivers
@ 2023-04-28 12:25   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 66+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-28 12:25 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

On 28/04/2023 12:36, Yi-De Wu wrote:
> This series is based on linux-next, tag: next-20230427.
> 
> Changes in v2:
> - Refactor: move to drivers/virt/geniezone
> - Refactor: decouple arch-dependent and arch-independent
> - Check pending signal before entering guest context
> - Fix reviewer's comments
> 

Please explain what is Geniezone, where we can find it, what's the plan
for open-sourcing it etc.

That's what cover letter is for.

Best regards,
Krzysztof


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 0/7] GenieZone hypervisor drivers
  2023-04-28 10:36 ` Yi-De Wu
@ 2023-04-28 12:26   ` Krzysztof Kozlowski
  -1 siblings, 0 replies; 66+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-28 12:26 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

On 28/04/2023 12:36, Yi-De Wu wrote:
> This series is based on linux-next, tag: next-20230427.
> 
> Changes in v2:
> - Refactor: move to drivers/virt/geniezone
> - Refactor: decouple arch-dependent and arch-independent
> - Check pending signal before entering guest context
> - Fix reviewer's comments

You need to be specific about what you changed.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 0/7] GenieZone hypervisor drivers
@ 2023-04-28 12:26   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 66+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-28 12:26 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: devicetree, linux-kernel, linux-doc, linux-arm-kernel,
	linux-arch, linux-mediatek, David Bradil, Trilok Soni, Jade Shih,
	Miles Chen, Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei,
	Liju Chen

On 28/04/2023 12:36, Yi-De Wu wrote:
> This series is based on linux-next, tag: next-20230427.
> 
> Changes in v2:
> - Refactor: move to drivers/virt/geniezone
> - Refactor: decouple arch-dependent and arch-independent
> - Check pending signal before entering guest context
> - Fix reviewer's comments

You need to be specific about what you changed.

Best regards,
Krzysztof


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-04-28 10:36   ` Yi-De Wu
@ 2023-04-28 14:52     ` Rob Herring
  -1 siblings, 0 replies; 66+ messages in thread
From: Rob Herring @ 2023-04-28 14:52 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Catalin Marinas, Liju Chen, PeiLun Suei, Yingshiuan Pan,
	Krzysztof Kozlowski, Ivan Tseng, Trilok Soni, linux-doc,
	Ze-Yu Wang, Jonathan Corbet, Miles Chen, linux-mediatek,
	linux-arch, Jade Shih, linux-kernel, My Chuang, Shawn Hsiao,
	devicetree, Arnd Bergmann, linux-arm-kernel, Matthias Brugger,
	AngeloGioacchino Del Regno, Will Deacon, Rob Herring,
	David Bradil


On Fri, 28 Apr 2023 18:36:17 +0800, Yi-De Wu wrote:
> From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> 
> 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.
> 
> Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> ---
>  .../hypervisor/mediatek,geniezone-hyp.yaml    | 31 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 32 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
./Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml: $id: relative path/filename doesn't match actual path or filename
	expected: http://devicetree.org/schemas/hypervisor/mediatek,geniezone-hyp.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230428103622.18291-3-yi-de.wu@mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
@ 2023-04-28 14:52     ` Rob Herring
  0 siblings, 0 replies; 66+ messages in thread
From: Rob Herring @ 2023-04-28 14:52 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Catalin Marinas, Liju Chen, PeiLun Suei, Yingshiuan Pan,
	Krzysztof Kozlowski, Ivan Tseng, Trilok Soni, linux-doc,
	Ze-Yu Wang, Jonathan Corbet, Miles Chen, linux-mediatek,
	linux-arch, Jade Shih, linux-kernel, My Chuang, Shawn Hsiao,
	devicetree, Arnd Bergmann, linux-arm-kernel, Matthias Brugger,
	AngeloGioacchino Del Regno, Will Deacon, Rob Herring,
	David Bradil


On Fri, 28 Apr 2023 18:36:17 +0800, Yi-De Wu wrote:
> From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> 
> 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.
> 
> Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> ---
>  .../hypervisor/mediatek,geniezone-hyp.yaml    | 31 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 32 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
./Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml: $id: relative path/filename doesn't match actual path or filename
	expected: http://devicetree.org/schemas/hypervisor/mediatek,geniezone-hyp.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230428103622.18291-3-yi-de.wu@mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-04-28 10:36   ` Yi-De Wu
@ 2023-04-28 16:19     ` kernel test robot
  -1 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2023-04-28 16:19 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: oe-kbuild-all, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Yi-De,

kernel test robot noticed the following build errors:

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on robh/for-next arnd-asm-generic/master linus/master v6.3 next-20230427]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20230428103622.18291-4-yi-de.wu%40mediatek.com
patch subject: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
config: x86_64-randconfig-a004 (https://download.01.org/0day-ci/archive/20230429/202304290052.49kcXbnl-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/0e3f05a6e4547eb309032d047115a47d8f59641d
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
        git checkout 0e3f05a6e4547eb309032d047115a47d8f59641d
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=x86_64 olddefconfig
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304290052.49kcXbnl-lkp@intel.com/

All errors (new ones prefixed by >>):

>> usr/include/linux/gzvm.h:15: included file 'asm-x86/gzvm_arch.h' is not exported

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
@ 2023-04-28 16:19     ` kernel test robot
  0 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2023-04-28 16:19 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: oe-kbuild-all, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Yi-De,

kernel test robot noticed the following build errors:

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on robh/for-next arnd-asm-generic/master linus/master v6.3 next-20230427]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20230428103622.18291-4-yi-de.wu%40mediatek.com
patch subject: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
config: x86_64-randconfig-a004 (https://download.01.org/0day-ci/archive/20230429/202304290052.49kcXbnl-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/0e3f05a6e4547eb309032d047115a47d8f59641d
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
        git checkout 0e3f05a6e4547eb309032d047115a47d8f59641d
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=x86_64 olddefconfig
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304290052.49kcXbnl-lkp@intel.com/

All errors (new ones prefixed by >>):

>> usr/include/linux/gzvm.h:15: included file 'asm-x86/gzvm_arch.h' is not exported

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-04-28 10:36   ` Yi-De Wu
@ 2023-04-28 17:53     ` kernel test robot
  -1 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2023-04-28 17:53 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: llvm, oe-kbuild-all, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Yi-De,

kernel test robot noticed the following build errors:

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on robh/for-next arnd-asm-generic/master linus/master v6.3 next-20230427]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20230428103622.18291-4-yi-de.wu%40mediatek.com
patch subject: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
config: x86_64-randconfig-a016 (https://download.01.org/0day-ci/archive/20230429/202304290120.5Ad0n6XR-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/0e3f05a6e4547eb309032d047115a47d8f59641d
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
        git checkout 0e3f05a6e4547eb309032d047115a47d8f59641d
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304290120.5Ad0n6XR-lkp@intel.com/

All errors (new ones prefixed by >>):

>> usr/include/linux/gzvm.h:15: included file 'asm-x86/gzvm_arch.h' is not exported

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
@ 2023-04-28 17:53     ` kernel test robot
  0 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2023-04-28 17:53 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: llvm, oe-kbuild-all, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Yi-De,

kernel test robot noticed the following build errors:

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on robh/for-next arnd-asm-generic/master linus/master v6.3 next-20230427]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20230428103622.18291-4-yi-de.wu%40mediatek.com
patch subject: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
config: x86_64-randconfig-a016 (https://download.01.org/0day-ci/archive/20230429/202304290120.5Ad0n6XR-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/0e3f05a6e4547eb309032d047115a47d8f59641d
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
        git checkout 0e3f05a6e4547eb309032d047115a47d8f59641d
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304290120.5Ad0n6XR-lkp@intel.com/

All errors (new ones prefixed by >>):

>> usr/include/linux/gzvm.h:15: included file 'asm-x86/gzvm_arch.h' is not exported

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
  2023-04-28 10:36   ` Yi-De Wu
@ 2023-04-28 18:59     ` Marc Zyngier
  -1 siblings, 0 replies; 66+ messages in thread
From: Marc Zyngier @ 2023-04-28 18:59 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Catalin Marinas, Will Deacon, Arnd Bergmann,
	Matthias Brugger, AngeloGioacchino Del Regno, devicetree,
	linux-kernel, linux-doc, linux-arm-kernel, linux-arch,
	linux-mediatek, David Bradil, Trilok Soni, Jade Shih, Miles Chen,
	Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei, Liju Chen

On 2023-04-28 11:36, Yi-De Wu wrote:
> From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> 
> Enable GenieZone to handle virtual interrupt injection request.
> 
> Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> ---
>  arch/arm64/geniezone/Makefile       |  2 +-
>  arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
>  arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
>  arch/arm64/geniezone/gzvm_irqchip.c | 88 +++++++++++++++++++++++++++++
>  drivers/virt/geniezone/gzvm_vm.c    | 75 ++++++++++++++++++++++++
>  include/linux/gzvm_drv.h            |  4 ++
>  include/uapi/linux/gzvm.h           | 38 ++++++++++++-
>  7 files changed, 235 insertions(+), 7 deletions(-)
>  create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c

[...]

> +++ b/arch/arm64/geniezone/gzvm_irqchip.c
> @@ -0,0 +1,88 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <kvm/arm_vgic.h>

NAK.

There is no way you can rely on anything from KVM in
your own hypervisor code.

> +
> +#include <linux/gzvm.h>
> +#include <linux/gzvm_drv.h>
> +#include "gzvm_arch.h"
> +
> +/**
> + * gzvm_sync_vgic_state() - Check all LRs synced from gz hypervisor
> + *
> + * Traverse all LRs, see if any EOIed vint, notify_acked_irq if any.
> + * GZ does not fold/unfold everytime KVM_RUN, so we have to traverse 
> all saved
> + * LRs. It will not takes much more time comparing to fold/unfold 
> everytime
> + * GZVM_RUN, because there are only few LRs.
> + */
> +void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu)
> +{
> +}
> +
> +/* is_irq_valid() - Check the irq number and irq_type are matched */
> +static bool is_irq_valid(u32 irq, u32 irq_type)
> +{
> +	switch (irq_type) {
> +	case GZVM_IRQ_TYPE_CPU:
> +		/*  0 ~ 15: SGI */
> +		if (likely(irq <= GZVM_IRQ_CPU_FIQ))
> +			return true;
> +		break;
> +	case GZVM_IRQ_TYPE_PPI:
> +		/* 16 ~ 31: PPI */
> +		if (likely(irq >= VGIC_NR_SGIS && irq < VGIC_NR_PRIVATE_IRQS))

What happens if I redefine all these macros tomorrow? None of
this code should rely on anything that is *INTERNAL* to KVM.

         M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
@ 2023-04-28 18:59     ` Marc Zyngier
  0 siblings, 0 replies; 66+ messages in thread
From: Marc Zyngier @ 2023-04-28 18:59 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Catalin Marinas, Will Deacon, Arnd Bergmann,
	Matthias Brugger, AngeloGioacchino Del Regno, devicetree,
	linux-kernel, linux-doc, linux-arm-kernel, linux-arch,
	linux-mediatek, David Bradil, Trilok Soni, Jade Shih, Miles Chen,
	Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei, Liju Chen

On 2023-04-28 11:36, Yi-De Wu wrote:
> From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> 
> Enable GenieZone to handle virtual interrupt injection request.
> 
> Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> ---
>  arch/arm64/geniezone/Makefile       |  2 +-
>  arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
>  arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
>  arch/arm64/geniezone/gzvm_irqchip.c | 88 +++++++++++++++++++++++++++++
>  drivers/virt/geniezone/gzvm_vm.c    | 75 ++++++++++++++++++++++++
>  include/linux/gzvm_drv.h            |  4 ++
>  include/uapi/linux/gzvm.h           | 38 ++++++++++++-
>  7 files changed, 235 insertions(+), 7 deletions(-)
>  create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c

[...]

> +++ b/arch/arm64/geniezone/gzvm_irqchip.c
> @@ -0,0 +1,88 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <kvm/arm_vgic.h>

NAK.

There is no way you can rely on anything from KVM in
your own hypervisor code.

> +
> +#include <linux/gzvm.h>
> +#include <linux/gzvm_drv.h>
> +#include "gzvm_arch.h"
> +
> +/**
> + * gzvm_sync_vgic_state() - Check all LRs synced from gz hypervisor
> + *
> + * Traverse all LRs, see if any EOIed vint, notify_acked_irq if any.
> + * GZ does not fold/unfold everytime KVM_RUN, so we have to traverse 
> all saved
> + * LRs. It will not takes much more time comparing to fold/unfold 
> everytime
> + * GZVM_RUN, because there are only few LRs.
> + */
> +void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu)
> +{
> +}
> +
> +/* is_irq_valid() - Check the irq number and irq_type are matched */
> +static bool is_irq_valid(u32 irq, u32 irq_type)
> +{
> +	switch (irq_type) {
> +	case GZVM_IRQ_TYPE_CPU:
> +		/*  0 ~ 15: SGI */
> +		if (likely(irq <= GZVM_IRQ_CPU_FIQ))
> +			return true;
> +		break;
> +	case GZVM_IRQ_TYPE_PPI:
> +		/* 16 ~ 31: PPI */
> +		if (likely(irq >= VGIC_NR_SGIS && irq < VGIC_NR_PRIVATE_IRQS))

What happens if I redefine all these macros tomorrow? None of
this code should rely on anything that is *INTERNAL* to KVM.

         M.
-- 
Jazz is not dead. It just smells funny...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-04-28 10:36   ` Yi-De Wu
@ 2023-04-28 20:07     ` kernel test robot
  -1 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2023-04-28 20:07 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: oe-kbuild-all, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Yi-De,

kernel test robot noticed the following build warnings:

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on robh/for-next arnd-asm-generic/master linus/master v6.3 next-20230428]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20230428103622.18291-4-yi-de.wu%40mediatek.com
patch subject: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
config: arm64-allyesconfig (https://download.01.org/0day-ci/archive/20230429/202304290334.fCw7PKYU-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/0e3f05a6e4547eb309032d047115a47d8f59641d
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
        git checkout 0e3f05a6e4547eb309032d047115a47d8f59641d
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash arch/arm64/geniezone/ drivers/virt/geniezone/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304290334.fCw7PKYU-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> arch/arm64/geniezone/gzvm_arch.c:112:5: warning: no previous prototype for 'gzvm_vm_arch_enable_cap' [-Wmissing-prototypes]
     112 | int gzvm_vm_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap,
         |     ^~~~~~~~~~~~~~~~~~~~~~~
--
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a0' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a1' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a2' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a3' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a4' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a5' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a6' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a7' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'res' not described in 'gzvm_hypcall_wrapper'
>> arch/arm64/geniezone/gzvm_arch.c:24: warning: expecting prototype for geniezone_hypercall_wrapper(). Prototype was for gzvm_hypcall_wrapper() instead
   arch/arm64/geniezone/gzvm_arch.c:133: warning: Function parameter or member 'gzvm' not described in 'gzvm_vm_ioctl_get_pvmfw_size'
   arch/arm64/geniezone/gzvm_arch.c:133: warning: Function parameter or member 'cap' not described in 'gzvm_vm_ioctl_get_pvmfw_size'
   arch/arm64/geniezone/gzvm_arch.c:133: warning: Function parameter or member 'argp' not described in 'gzvm_vm_ioctl_get_pvmfw_size'
   arch/arm64/geniezone/gzvm_arch.c:155: warning: Function parameter or member 'gzvm' not described in 'gzvm_vm_ioctl_cap_pvm'
   arch/arm64/geniezone/gzvm_arch.c:155: warning: Function parameter or member 'cap' not described in 'gzvm_vm_ioctl_cap_pvm'
   arch/arm64/geniezone/gzvm_arch.c:155: warning: Function parameter or member 'argp' not described in 'gzvm_vm_ioctl_cap_pvm'


vim +/gzvm_vm_arch_enable_cap +112 arch/arm64/geniezone/gzvm_arch.c

    13	
    14	/**
    15	 * geniezone_hypercall_wrapper()
    16	 *
    17	 * Return: The wrapper helps caller to convert geniezone errno to Linux errno.
    18	 */
    19	static int gzvm_hypcall_wrapper(unsigned long a0, unsigned long a1,
    20					unsigned long a2, unsigned long a3,
    21					unsigned long a4, unsigned long a5,
    22					unsigned long a6, unsigned long a7,
    23					struct arm_smccc_res *res)
  > 24	{
    25		arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
    26		return gz_err_to_errno(res->a0);
    27	}
    28	
    29	int gzvm_arch_probe(void)
    30	{
    31		struct arm_smccc_res res;
    32	
    33		arm_smccc_hvc(MT_HVC_GZVM_PROBE, 0, 0, 0, 0, 0, 0, 0, &res);
    34		if (res.a0 == 0)
    35			return 0;
    36	
    37		return -ENXIO;
    38	}
    39	
    40	int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
    41				    phys_addr_t region)
    42	{
    43		struct arm_smccc_res res;
    44	
    45		return gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_MEMREGION, vm_id,
    46					    buf_size, region, 0, 0, 0, 0, &res);
    47	}
    48	
    49	static int gzvm_cap_arm_vm_ipa_size(void __user *argp)
    50	{
    51		__u64 value = CONFIG_ARM64_PA_BITS;
    52	
    53		if (copy_to_user(argp, &value, sizeof(__u64)))
    54			return -EFAULT;
    55	
    56		return 0;
    57	}
    58	
    59	int gzvm_arch_check_extension(struct gzvm *gzvm, __u64 cap, void __user *argp)
    60	{
    61		int ret = -EOPNOTSUPP;
    62	
    63		switch (cap) {
    64		case GZVM_CAP_ARM_PROTECTED_VM: {
    65			__u64 success = 1;
    66	
    67			if (copy_to_user(argp, &success, sizeof(__u64)))
    68				return -EFAULT;
    69			ret = 0;
    70			break;
    71		}
    72		case GZVM_CAP_ARM_VM_IPA_SIZE: {
    73			ret = gzvm_cap_arm_vm_ipa_size(argp);
    74			break;
    75		}
    76		default:
    77			ret = -EOPNOTSUPP;
    78		}
    79	
    80		return ret;
    81	}
    82	
    83	/**
    84	 * gzvm_arch_create_vm()
    85	 *
    86	 * Return:
    87	 * * positive value	- VM ID
    88	 * * -ENOMEM		- Memory not enough for storing VM data
    89	 */
    90	int gzvm_arch_create_vm(void)
    91	{
    92		struct arm_smccc_res res;
    93		int ret;
    94	
    95		ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VM, 0, 0, 0, 0, 0, 0, 0,
    96					   &res);
    97	
    98		if (ret == 0)
    99			return res.a1;
   100		else
   101			return ret;
   102	}
   103	
   104	int gzvm_arch_destroy_vm(gzvm_id_t vm_id)
   105	{
   106		struct arm_smccc_res res;
   107	
   108		return gzvm_hypcall_wrapper(MT_HVC_GZVM_DESTROY_VM, vm_id, 0, 0, 0, 0,
   109					    0, 0, &res);
   110	}
   111	
 > 112	int gzvm_vm_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap,
   113				    struct arm_smccc_res *res)
   114	{
   115		return gzvm_hypcall_wrapper(MT_HVC_GZVM_ENABLE_CAP, gzvm->vm_id,
   116					   cap->cap, cap->args[0], cap->args[1],
   117					   cap->args[2], cap->args[3], cap->args[4],
   118					   res);
   119	}
   120	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
@ 2023-04-28 20:07     ` kernel test robot
  0 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2023-04-28 20:07 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: oe-kbuild-all, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Yi-De,

kernel test robot noticed the following build warnings:

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on robh/for-next arnd-asm-generic/master linus/master v6.3 next-20230428]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20230428103622.18291-4-yi-de.wu%40mediatek.com
patch subject: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
config: arm64-allyesconfig (https://download.01.org/0day-ci/archive/20230429/202304290334.fCw7PKYU-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/0e3f05a6e4547eb309032d047115a47d8f59641d
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
        git checkout 0e3f05a6e4547eb309032d047115a47d8f59641d
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash arch/arm64/geniezone/ drivers/virt/geniezone/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304290334.fCw7PKYU-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> arch/arm64/geniezone/gzvm_arch.c:112:5: warning: no previous prototype for 'gzvm_vm_arch_enable_cap' [-Wmissing-prototypes]
     112 | int gzvm_vm_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap,
         |     ^~~~~~~~~~~~~~~~~~~~~~~
--
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a0' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a1' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a2' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a3' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a4' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a5' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a6' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'a7' not described in 'gzvm_hypcall_wrapper'
   arch/arm64/geniezone/gzvm_arch.c:24: warning: Function parameter or member 'res' not described in 'gzvm_hypcall_wrapper'
>> arch/arm64/geniezone/gzvm_arch.c:24: warning: expecting prototype for geniezone_hypercall_wrapper(). Prototype was for gzvm_hypcall_wrapper() instead
   arch/arm64/geniezone/gzvm_arch.c:133: warning: Function parameter or member 'gzvm' not described in 'gzvm_vm_ioctl_get_pvmfw_size'
   arch/arm64/geniezone/gzvm_arch.c:133: warning: Function parameter or member 'cap' not described in 'gzvm_vm_ioctl_get_pvmfw_size'
   arch/arm64/geniezone/gzvm_arch.c:133: warning: Function parameter or member 'argp' not described in 'gzvm_vm_ioctl_get_pvmfw_size'
   arch/arm64/geniezone/gzvm_arch.c:155: warning: Function parameter or member 'gzvm' not described in 'gzvm_vm_ioctl_cap_pvm'
   arch/arm64/geniezone/gzvm_arch.c:155: warning: Function parameter or member 'cap' not described in 'gzvm_vm_ioctl_cap_pvm'
   arch/arm64/geniezone/gzvm_arch.c:155: warning: Function parameter or member 'argp' not described in 'gzvm_vm_ioctl_cap_pvm'


vim +/gzvm_vm_arch_enable_cap +112 arch/arm64/geniezone/gzvm_arch.c

    13	
    14	/**
    15	 * geniezone_hypercall_wrapper()
    16	 *
    17	 * Return: The wrapper helps caller to convert geniezone errno to Linux errno.
    18	 */
    19	static int gzvm_hypcall_wrapper(unsigned long a0, unsigned long a1,
    20					unsigned long a2, unsigned long a3,
    21					unsigned long a4, unsigned long a5,
    22					unsigned long a6, unsigned long a7,
    23					struct arm_smccc_res *res)
  > 24	{
    25		arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
    26		return gz_err_to_errno(res->a0);
    27	}
    28	
    29	int gzvm_arch_probe(void)
    30	{
    31		struct arm_smccc_res res;
    32	
    33		arm_smccc_hvc(MT_HVC_GZVM_PROBE, 0, 0, 0, 0, 0, 0, 0, &res);
    34		if (res.a0 == 0)
    35			return 0;
    36	
    37		return -ENXIO;
    38	}
    39	
    40	int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
    41				    phys_addr_t region)
    42	{
    43		struct arm_smccc_res res;
    44	
    45		return gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_MEMREGION, vm_id,
    46					    buf_size, region, 0, 0, 0, 0, &res);
    47	}
    48	
    49	static int gzvm_cap_arm_vm_ipa_size(void __user *argp)
    50	{
    51		__u64 value = CONFIG_ARM64_PA_BITS;
    52	
    53		if (copy_to_user(argp, &value, sizeof(__u64)))
    54			return -EFAULT;
    55	
    56		return 0;
    57	}
    58	
    59	int gzvm_arch_check_extension(struct gzvm *gzvm, __u64 cap, void __user *argp)
    60	{
    61		int ret = -EOPNOTSUPP;
    62	
    63		switch (cap) {
    64		case GZVM_CAP_ARM_PROTECTED_VM: {
    65			__u64 success = 1;
    66	
    67			if (copy_to_user(argp, &success, sizeof(__u64)))
    68				return -EFAULT;
    69			ret = 0;
    70			break;
    71		}
    72		case GZVM_CAP_ARM_VM_IPA_SIZE: {
    73			ret = gzvm_cap_arm_vm_ipa_size(argp);
    74			break;
    75		}
    76		default:
    77			ret = -EOPNOTSUPP;
    78		}
    79	
    80		return ret;
    81	}
    82	
    83	/**
    84	 * gzvm_arch_create_vm()
    85	 *
    86	 * Return:
    87	 * * positive value	- VM ID
    88	 * * -ENOMEM		- Memory not enough for storing VM data
    89	 */
    90	int gzvm_arch_create_vm(void)
    91	{
    92		struct arm_smccc_res res;
    93		int ret;
    94	
    95		ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VM, 0, 0, 0, 0, 0, 0, 0,
    96					   &res);
    97	
    98		if (ret == 0)
    99			return res.a1;
   100		else
   101			return ret;
   102	}
   103	
   104	int gzvm_arch_destroy_vm(gzvm_id_t vm_id)
   105	{
   106		struct arm_smccc_res res;
   107	
   108		return gzvm_hypcall_wrapper(MT_HVC_GZVM_DESTROY_VM, vm_id, 0, 0, 0, 0,
   109					    0, 0, &res);
   110	}
   111	
 > 112	int gzvm_vm_arch_enable_cap(struct gzvm *gzvm, struct gzvm_enable_cap *cap,
   113				    struct arm_smccc_res *res)
   114	{
   115		return gzvm_hypcall_wrapper(MT_HVC_GZVM_ENABLE_CAP, gzvm->vm_id,
   116					   cap->cap, cap->args[0], cap->args[1],
   117					   cap->args[2], cap->args[3], cap->args[4],
   118					   res);
   119	}
   120	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-04-28 10:36   ` Yi-De Wu
@ 2023-04-28 21:24     ` Rob Herring
  -1 siblings, 0 replies; 66+ messages in thread
From: Rob Herring @ 2023-04-28 21:24 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Krzysztof Kozlowski, Jonathan Corbet,
	Catalin Marinas, Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

On Fri, Apr 28, 2023 at 06:36:17PM +0800, Yi-De Wu wrote:
> From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> 
> 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.

Why can't the driver just try and do virtual machine operations to see 
if the hypervisor is there? IOW, make your software interfaces 
discoverable. DT is for non-discoverable hardware.

Rob

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
@ 2023-04-28 21:24     ` Rob Herring
  0 siblings, 0 replies; 66+ messages in thread
From: Rob Herring @ 2023-04-28 21:24 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Krzysztof Kozlowski, Jonathan Corbet,
	Catalin Marinas, Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

On Fri, Apr 28, 2023 at 06:36:17PM +0800, Yi-De Wu wrote:
> From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> 
> 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.

Why can't the driver just try and do virtual machine operations to see 
if the hypervisor is there? IOW, make your software interfaces 
discoverable. DT is for non-discoverable hardware.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-04-28 10:36   ` Yi-De Wu
@ 2023-04-28 22:12     ` Marc Zyngier
  -1 siblings, 0 replies; 66+ messages in thread
From: Marc Zyngier @ 2023-04-28 22:12 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Catalin Marinas, Will Deacon, Arnd Bergmann,
	Matthias Brugger, AngeloGioacchino Del Regno, devicetree,
	linux-kernel, linux-doc, linux-arm-kernel, linux-arch,
	linux-mediatek, David Bradil, Trilok Soni, Jade Shih, Miles Chen,
	Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei, Liju Chen

On 2023-04-28 11:36, Yi-De Wu wrote:
> From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> 
> GenieZone is MediaTek hypervisor solution, and it is running in EL2
> stand alone as a type-I hypervisor. This patch exports a set of ioctl
> interfaces for userspace VMM (e.g., crosvm) to operate guest VMs
> lifecycle (creation and destroy) on GenieZone.
> 
> Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> ---
>  MAINTAINERS                             |   6 +
>  arch/arm64/Kbuild                       |   1 +
>  arch/arm64/geniezone/Makefile           |   9 +
>  arch/arm64/geniezone/gzvm_arch.c        | 189 +++++++++++++
>  arch/arm64/geniezone/gzvm_arch.h        |  50 ++++
>  arch/arm64/include/uapi/asm/gzvm_arch.h |  18 ++
>  drivers/virt/Kconfig                    |   2 +
>  drivers/virt/geniezone/Kconfig          |  17 ++
>  drivers/virt/geniezone/Makefile         |  10 +
>  drivers/virt/geniezone/gzvm_main.c      | 146 ++++++++++
>  drivers/virt/geniezone/gzvm_vm.c        | 336 ++++++++++++++++++++++++
>  include/linux/gzvm_drv.h                |  98 +++++++
>  include/uapi/asm-generic/gzvm_arch.h    |  10 +
>  include/uapi/linux/gzvm.h               |  99 +++++++
>  14 files changed, 991 insertions(+)
>  create mode 100644 arch/arm64/geniezone/Makefile
>  create mode 100644 arch/arm64/geniezone/gzvm_arch.c
>  create mode 100644 arch/arm64/geniezone/gzvm_arch.h
>  create mode 100644 arch/arm64/include/uapi/asm/gzvm_arch.h
>  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 drivers/virt/geniezone/gzvm_vm.c
>  create mode 100644 include/linux/gzvm_drv.h
>  create mode 100644 include/uapi/asm-generic/gzvm_arch.h
>  create mode 100644 include/uapi/linux/gzvm.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1e911d1d9741..09a8ccf77b01 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8700,6 +8700,12 @@ M:	Ze-Yu Wang <ze-yu.wang@mediatek.com>
>  M:	Yi-De Wu <yi-de.wu@mediatek.com>
>  
> F:	Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml
>  F:	Documentation/virt/geniezone/
> +F:	arch/arm64/geniezone/
> +F:	arch/arm64/include/uapi/asm/gzvm_arch.h
> +F:	drivers/virt/geniezone/
> +F:	include/linux/gzvm_drv.h
> +F	include/uapi/asm-generic/gzvm_arch.h
> +F:	include/uapi/linux/gzvm.h
> 
>  GENWQE (IBM Generic Workqueue Card)
>  M:	Frank Haverkamp <haver@linux.ibm.com>
> 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..5720c076d73c
> --- /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 += gzvm_arch.o
> +
> +obj-$(CONFIG_MTK_GZVM) += gzvm.o
> diff --git a/arch/arm64/geniezone/gzvm_arch.c 
> b/arch/arm64/geniezone/gzvm_arch.c
> new file mode 100644
> index 000000000000..2fc76f7d440f
> --- /dev/null
> +++ b/arch/arm64/geniezone/gzvm_arch.c
> @@ -0,0 +1,189 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#include <linux/arm-smccc.h>
> +#include <linux/err.h>
> +#include <linux/uaccess.h>
> +
> +#include <linux/gzvm.h>
> +#include <linux/gzvm_drv.h>
> +#include "gzvm_arch.h"
> +
> +/**
> + * geniezone_hypercall_wrapper()
> + *
> + * Return: The wrapper helps caller to convert geniezone errno to 
> Linux errno.
> + */
> +static 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 gz_err_to_errno(res->a0);
> +}
> +
> +int gzvm_arch_probe(void)
> +{
> +	struct arm_smccc_res res;
> +
> +	arm_smccc_hvc(MT_HVC_GZVM_PROBE, 0, 0, 0, 0, 0, 0, 0, &res);
> +	if (res.a0 == 0)
> +		return 0;
> +
> +	return -ENXIO;
> +}
> +
> +int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
> +			    phys_addr_t region)
> +{
> +	struct arm_smccc_res res;
> +
> +	return gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_MEMREGION, vm_id,
> +				    buf_size, region, 0, 0, 0, 0, &res);
> +}
> +
> +static int gzvm_cap_arm_vm_ipa_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 = -EOPNOTSUPP;
> +
> +	switch (cap) {
> +	case GZVM_CAP_ARM_PROTECTED_VM: {
> +		__u64 success = 1;
> +
> +		if (copy_to_user(argp, &success, sizeof(__u64)))
> +			return -EFAULT;
> +		ret = 0;
> +		break;
> +	}
> +	case GZVM_CAP_ARM_VM_IPA_SIZE: {
> +		ret = gzvm_cap_arm_vm_ipa_size(argp);
> +		break;
> +	}
> +	default:
> +		ret = -EOPNOTSUPP;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * gzvm_arch_create_vm()
> + *
> + * Return:
> + * * positive value	- VM ID
> + * * -ENOMEM		- Memory not enough for storing VM data
> + */
> +int gzvm_arch_create_vm(void)
> +{
> +	struct arm_smccc_res res;
> +	int ret;
> +
> +	ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VM, 0, 0, 0, 0, 0, 0, 
> 0,
> +				   &res);
> +
> +	if (ret == 0)
> +		return res.a1;
> +	else
> +		return ret;
> +}
> +
> +int gzvm_arch_destroy_vm(gzvm_id_t 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);
> +}
> +
> +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.
> + *
> + * 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_ARM_PROTECTED_VM's 
> subcommands
> + *
> + * 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)
> +{
> +	int ret = -EINVAL;
> +	struct arm_smccc_res res = {0};
> +
> +	switch (cap->args[0]) {
> +	case GZVM_CAP_ARM_PVM_SET_PVMFW_IPA:
> +		ret = gzvm_vm_arch_enable_cap(gzvm, cap, &res);
> +		break;
> +	case GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE:
> +		ret = gzvm_vm_ioctl_get_pvmfw_size(gzvm, cap, argp);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct
> gzvm_enable_cap *cap,
> +				  void __user *argp)
> +{
> +	int ret = -EINVAL;
> +
> +	switch (cap->cap) {
> +	case GZVM_CAP_ARM_PROTECTED_VM:
> +		ret = gzvm_vm_ioctl_cap_pvm(gzvm, cap, argp);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> diff --git a/arch/arm64/geniezone/gzvm_arch.h 
> b/arch/arm64/geniezone/gzvm_arch.h
> new file mode 100644
> index 000000000000..dd0b7b5f7c65
> --- /dev/null
> +++ b/arch/arm64/geniezone/gzvm_arch.h
> @@ -0,0 +1,50 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#ifndef __GZ_ARCH_H__
> +#define __GZ_ARCH_H__
> +
> +#include <linux/arm-smccc.h>
> +
> +enum {
> +	GZVM_FUNC_CREATE_VM = 0,
> +	GZVM_FUNC_DESTROY_VM,
> +	GZVM_FUNC_CREATE_VCPU,
> +	GZVM_FUNC_DESTROY_VCPU,
> +	GZVM_FUNC_SET_MEMREGION,
> +	GZVM_FUNC_RUN,
> +	GZVM_FUNC_GET_REGS,
> +	GZVM_FUNC_SET_REGS,
> +	GZVM_FUNC_GET_ONE_REG,
> +	GZVM_FUNC_SET_ONE_REG,
> +	GZVM_FUNC_IRQ_LINE,
> +	GZVM_FUNC_CREATE_DEVICE,
> +	GZVM_FUNC_PROBE,
> +	GZVM_FUNC_ENABLE_CAP,
> +	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_32,	\
> +			   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_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_REGS		GZVM_HCALL_ID(GZVM_FUNC_GET_REGS)
> +#define MT_HVC_GZVM_SET_REGS		GZVM_HCALL_ID(GZVM_FUNC_SET_REGS)
> +#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_IRQ_LINE		GZVM_HCALL_ID(GZVM_FUNC_IRQ_LINE)
> +#define 
> MT_HVC_GZVM_CREATE_DEVICE	GZVM_HCALL_ID(GZVM_FUNC_CREATE_DEVICE)
> +#define MT_HVC_GZVM_PROBE		GZVM_HCALL_ID(GZVM_FUNC_PROBE)
> +#define MT_HVC_GZVM_ENABLE_CAP		GZVM_HCALL_ID(GZVM_FUNC_ENABLE_CAP)
> +
> +#endif /* __GZVM_ARCH_H__ */
> diff --git a/arch/arm64/include/uapi/asm/gzvm_arch.h
> b/arch/arm64/include/uapi/asm/gzvm_arch.h
> new file mode 100644
> index 000000000000..e7927f3dcb11
> --- /dev/null
> +++ b/arch/arm64/include/uapi/asm/gzvm_arch.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#ifndef __GZVM_ARCH_H__
> +#define __GZVM_ARCH_H__
> +
> +#include <linux/types.h>
> +
> +#define GZVM_CAP_ARM_VM_IPA_SIZE	165
> +#define GZVM_CAP_ARM_PROTECTED_VM	0xffbadab1
> +
> +/* sub-commands put in args[0] for GZVM_CAP_ARM_PROTECTED_VM */
> +#define GZVM_CAP_ARM_PVM_SET_PVMFW_IPA		0
> +#define GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE		1
> +
> +#endif /* __GZVM_ARCH_H__ */
> diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
> index f79ab13a5c28..9bbf0bdf672c 100644
> --- a/drivers/virt/Kconfig
> +++ b/drivers/virt/Kconfig
> @@ -54,4 +54,6 @@ source "drivers/virt/coco/sev-guest/Kconfig"
> 
>  source "drivers/virt/coco/tdx-guest/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..6fad3c30f8d9
> --- /dev/null
> +++ b/drivers/virt/geniezone/Kconfig
> @@ -0,0 +1,17 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +config MTK_GZVM
> +	tristate "GenieZone Hypervisor driver for guest VM operation"
> +	depends on ARM64
> +	depends on KVM

NAK.

Either this is KVM, and this code serves no purpose, or it is a 
standalone
hypervisor, and it *cannot* have a dependency on KVM.

[...]

> +/**
> + * gzvm_gfn_to_pfn_memslot() - Translate gfn (guest ipa) to pfn (host 
> pa),
> + *			       result is in @pfn
> + *
> + * Leverage KVM's gfn_to_pfn_memslot(). Because gfn_to_pfn_memslot() 
> needs
> + * kvm_memory_slot as parameter, this function populates necessary 
> fileds
> + * for calling gfn_to_pfn_memslot().
> + *
> + * Return:
> + * * 0			- Succeed
> + * * -EFAULT		- Failed to convert
> + */
> +static int gzvm_gfn_to_pfn_memslot(struct gzvm_memslot *memslot, u64
> gfn, u64 *pfn)
> +{
> +	hfn_t __pfn;
> +	struct kvm_memory_slot kvm_slot = {0};
> +
> +	kvm_slot.base_gfn = memslot->base_gfn;
> +	kvm_slot.npages = memslot->npages;
> +	kvm_slot.dirty_bitmap = NULL;
> +	kvm_slot.userspace_addr = memslot->userspace_addr;
> +	kvm_slot.flags = memslot->flags;
> +	kvm_slot.id = memslot->slot_id;
> +	kvm_slot.as_id = 0;
> +
> +	__pfn = gfn_to_pfn_memslot(&kvm_slot, gfn);

Again, I absolutely oppose this horror. This is internal to KVM,
and we want to be able to change this without having to mess
with your own code that we cannot test anyway.

What if we start using the extra fields that you don't populate
as they mean nothing to you? Or add a backpointer to the kvm
structure to do fancy accounting?

You have your own hypervisor, that's well and good. Since your
main argument is that it is supposed to be standalone, make it
*really* standalone and don't use KVM as a prop.

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
@ 2023-04-28 22:12     ` Marc Zyngier
  0 siblings, 0 replies; 66+ messages in thread
From: Marc Zyngier @ 2023-04-28 22:12 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Catalin Marinas, Will Deacon, Arnd Bergmann,
	Matthias Brugger, AngeloGioacchino Del Regno, devicetree,
	linux-kernel, linux-doc, linux-arm-kernel, linux-arch,
	linux-mediatek, David Bradil, Trilok Soni, Jade Shih, Miles Chen,
	Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei, Liju Chen

On 2023-04-28 11:36, Yi-De Wu wrote:
> From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> 
> GenieZone is MediaTek hypervisor solution, and it is running in EL2
> stand alone as a type-I hypervisor. This patch exports a set of ioctl
> interfaces for userspace VMM (e.g., crosvm) to operate guest VMs
> lifecycle (creation and destroy) on GenieZone.
> 
> Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> ---
>  MAINTAINERS                             |   6 +
>  arch/arm64/Kbuild                       |   1 +
>  arch/arm64/geniezone/Makefile           |   9 +
>  arch/arm64/geniezone/gzvm_arch.c        | 189 +++++++++++++
>  arch/arm64/geniezone/gzvm_arch.h        |  50 ++++
>  arch/arm64/include/uapi/asm/gzvm_arch.h |  18 ++
>  drivers/virt/Kconfig                    |   2 +
>  drivers/virt/geniezone/Kconfig          |  17 ++
>  drivers/virt/geniezone/Makefile         |  10 +
>  drivers/virt/geniezone/gzvm_main.c      | 146 ++++++++++
>  drivers/virt/geniezone/gzvm_vm.c        | 336 ++++++++++++++++++++++++
>  include/linux/gzvm_drv.h                |  98 +++++++
>  include/uapi/asm-generic/gzvm_arch.h    |  10 +
>  include/uapi/linux/gzvm.h               |  99 +++++++
>  14 files changed, 991 insertions(+)
>  create mode 100644 arch/arm64/geniezone/Makefile
>  create mode 100644 arch/arm64/geniezone/gzvm_arch.c
>  create mode 100644 arch/arm64/geniezone/gzvm_arch.h
>  create mode 100644 arch/arm64/include/uapi/asm/gzvm_arch.h
>  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 drivers/virt/geniezone/gzvm_vm.c
>  create mode 100644 include/linux/gzvm_drv.h
>  create mode 100644 include/uapi/asm-generic/gzvm_arch.h
>  create mode 100644 include/uapi/linux/gzvm.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1e911d1d9741..09a8ccf77b01 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8700,6 +8700,12 @@ M:	Ze-Yu Wang <ze-yu.wang@mediatek.com>
>  M:	Yi-De Wu <yi-de.wu@mediatek.com>
>  
> F:	Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-hyp.yaml
>  F:	Documentation/virt/geniezone/
> +F:	arch/arm64/geniezone/
> +F:	arch/arm64/include/uapi/asm/gzvm_arch.h
> +F:	drivers/virt/geniezone/
> +F:	include/linux/gzvm_drv.h
> +F	include/uapi/asm-generic/gzvm_arch.h
> +F:	include/uapi/linux/gzvm.h
> 
>  GENWQE (IBM Generic Workqueue Card)
>  M:	Frank Haverkamp <haver@linux.ibm.com>
> 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..5720c076d73c
> --- /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 += gzvm_arch.o
> +
> +obj-$(CONFIG_MTK_GZVM) += gzvm.o
> diff --git a/arch/arm64/geniezone/gzvm_arch.c 
> b/arch/arm64/geniezone/gzvm_arch.c
> new file mode 100644
> index 000000000000..2fc76f7d440f
> --- /dev/null
> +++ b/arch/arm64/geniezone/gzvm_arch.c
> @@ -0,0 +1,189 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#include <linux/arm-smccc.h>
> +#include <linux/err.h>
> +#include <linux/uaccess.h>
> +
> +#include <linux/gzvm.h>
> +#include <linux/gzvm_drv.h>
> +#include "gzvm_arch.h"
> +
> +/**
> + * geniezone_hypercall_wrapper()
> + *
> + * Return: The wrapper helps caller to convert geniezone errno to 
> Linux errno.
> + */
> +static 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 gz_err_to_errno(res->a0);
> +}
> +
> +int gzvm_arch_probe(void)
> +{
> +	struct arm_smccc_res res;
> +
> +	arm_smccc_hvc(MT_HVC_GZVM_PROBE, 0, 0, 0, 0, 0, 0, 0, &res);
> +	if (res.a0 == 0)
> +		return 0;
> +
> +	return -ENXIO;
> +}
> +
> +int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
> +			    phys_addr_t region)
> +{
> +	struct arm_smccc_res res;
> +
> +	return gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_MEMREGION, vm_id,
> +				    buf_size, region, 0, 0, 0, 0, &res);
> +}
> +
> +static int gzvm_cap_arm_vm_ipa_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 = -EOPNOTSUPP;
> +
> +	switch (cap) {
> +	case GZVM_CAP_ARM_PROTECTED_VM: {
> +		__u64 success = 1;
> +
> +		if (copy_to_user(argp, &success, sizeof(__u64)))
> +			return -EFAULT;
> +		ret = 0;
> +		break;
> +	}
> +	case GZVM_CAP_ARM_VM_IPA_SIZE: {
> +		ret = gzvm_cap_arm_vm_ipa_size(argp);
> +		break;
> +	}
> +	default:
> +		ret = -EOPNOTSUPP;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * gzvm_arch_create_vm()
> + *
> + * Return:
> + * * positive value	- VM ID
> + * * -ENOMEM		- Memory not enough for storing VM data
> + */
> +int gzvm_arch_create_vm(void)
> +{
> +	struct arm_smccc_res res;
> +	int ret;
> +
> +	ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VM, 0, 0, 0, 0, 0, 0, 
> 0,
> +				   &res);
> +
> +	if (ret == 0)
> +		return res.a1;
> +	else
> +		return ret;
> +}
> +
> +int gzvm_arch_destroy_vm(gzvm_id_t 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);
> +}
> +
> +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.
> + *
> + * 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_ARM_PROTECTED_VM's 
> subcommands
> + *
> + * 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)
> +{
> +	int ret = -EINVAL;
> +	struct arm_smccc_res res = {0};
> +
> +	switch (cap->args[0]) {
> +	case GZVM_CAP_ARM_PVM_SET_PVMFW_IPA:
> +		ret = gzvm_vm_arch_enable_cap(gzvm, cap, &res);
> +		break;
> +	case GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE:
> +		ret = gzvm_vm_ioctl_get_pvmfw_size(gzvm, cap, argp);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct
> gzvm_enable_cap *cap,
> +				  void __user *argp)
> +{
> +	int ret = -EINVAL;
> +
> +	switch (cap->cap) {
> +	case GZVM_CAP_ARM_PROTECTED_VM:
> +		ret = gzvm_vm_ioctl_cap_pvm(gzvm, cap, argp);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> diff --git a/arch/arm64/geniezone/gzvm_arch.h 
> b/arch/arm64/geniezone/gzvm_arch.h
> new file mode 100644
> index 000000000000..dd0b7b5f7c65
> --- /dev/null
> +++ b/arch/arm64/geniezone/gzvm_arch.h
> @@ -0,0 +1,50 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#ifndef __GZ_ARCH_H__
> +#define __GZ_ARCH_H__
> +
> +#include <linux/arm-smccc.h>
> +
> +enum {
> +	GZVM_FUNC_CREATE_VM = 0,
> +	GZVM_FUNC_DESTROY_VM,
> +	GZVM_FUNC_CREATE_VCPU,
> +	GZVM_FUNC_DESTROY_VCPU,
> +	GZVM_FUNC_SET_MEMREGION,
> +	GZVM_FUNC_RUN,
> +	GZVM_FUNC_GET_REGS,
> +	GZVM_FUNC_SET_REGS,
> +	GZVM_FUNC_GET_ONE_REG,
> +	GZVM_FUNC_SET_ONE_REG,
> +	GZVM_FUNC_IRQ_LINE,
> +	GZVM_FUNC_CREATE_DEVICE,
> +	GZVM_FUNC_PROBE,
> +	GZVM_FUNC_ENABLE_CAP,
> +	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_32,	\
> +			   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_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_REGS		GZVM_HCALL_ID(GZVM_FUNC_GET_REGS)
> +#define MT_HVC_GZVM_SET_REGS		GZVM_HCALL_ID(GZVM_FUNC_SET_REGS)
> +#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_IRQ_LINE		GZVM_HCALL_ID(GZVM_FUNC_IRQ_LINE)
> +#define 
> MT_HVC_GZVM_CREATE_DEVICE	GZVM_HCALL_ID(GZVM_FUNC_CREATE_DEVICE)
> +#define MT_HVC_GZVM_PROBE		GZVM_HCALL_ID(GZVM_FUNC_PROBE)
> +#define MT_HVC_GZVM_ENABLE_CAP		GZVM_HCALL_ID(GZVM_FUNC_ENABLE_CAP)
> +
> +#endif /* __GZVM_ARCH_H__ */
> diff --git a/arch/arm64/include/uapi/asm/gzvm_arch.h
> b/arch/arm64/include/uapi/asm/gzvm_arch.h
> new file mode 100644
> index 000000000000..e7927f3dcb11
> --- /dev/null
> +++ b/arch/arm64/include/uapi/asm/gzvm_arch.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + */
> +
> +#ifndef __GZVM_ARCH_H__
> +#define __GZVM_ARCH_H__
> +
> +#include <linux/types.h>
> +
> +#define GZVM_CAP_ARM_VM_IPA_SIZE	165
> +#define GZVM_CAP_ARM_PROTECTED_VM	0xffbadab1
> +
> +/* sub-commands put in args[0] for GZVM_CAP_ARM_PROTECTED_VM */
> +#define GZVM_CAP_ARM_PVM_SET_PVMFW_IPA		0
> +#define GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE		1
> +
> +#endif /* __GZVM_ARCH_H__ */
> diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
> index f79ab13a5c28..9bbf0bdf672c 100644
> --- a/drivers/virt/Kconfig
> +++ b/drivers/virt/Kconfig
> @@ -54,4 +54,6 @@ source "drivers/virt/coco/sev-guest/Kconfig"
> 
>  source "drivers/virt/coco/tdx-guest/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..6fad3c30f8d9
> --- /dev/null
> +++ b/drivers/virt/geniezone/Kconfig
> @@ -0,0 +1,17 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +config MTK_GZVM
> +	tristate "GenieZone Hypervisor driver for guest VM operation"
> +	depends on ARM64
> +	depends on KVM

NAK.

Either this is KVM, and this code serves no purpose, or it is a 
standalone
hypervisor, and it *cannot* have a dependency on KVM.

[...]

> +/**
> + * gzvm_gfn_to_pfn_memslot() - Translate gfn (guest ipa) to pfn (host 
> pa),
> + *			       result is in @pfn
> + *
> + * Leverage KVM's gfn_to_pfn_memslot(). Because gfn_to_pfn_memslot() 
> needs
> + * kvm_memory_slot as parameter, this function populates necessary 
> fileds
> + * for calling gfn_to_pfn_memslot().
> + *
> + * Return:
> + * * 0			- Succeed
> + * * -EFAULT		- Failed to convert
> + */
> +static int gzvm_gfn_to_pfn_memslot(struct gzvm_memslot *memslot, u64
> gfn, u64 *pfn)
> +{
> +	hfn_t __pfn;
> +	struct kvm_memory_slot kvm_slot = {0};
> +
> +	kvm_slot.base_gfn = memslot->base_gfn;
> +	kvm_slot.npages = memslot->npages;
> +	kvm_slot.dirty_bitmap = NULL;
> +	kvm_slot.userspace_addr = memslot->userspace_addr;
> +	kvm_slot.flags = memslot->flags;
> +	kvm_slot.id = memslot->slot_id;
> +	kvm_slot.as_id = 0;
> +
> +	__pfn = gfn_to_pfn_memslot(&kvm_slot, gfn);

Again, I absolutely oppose this horror. This is internal to KVM,
and we want to be able to change this without having to mess
with your own code that we cannot test anyway.

What if we start using the extra fields that you don't populate
as they mean nothing to you? Or add a backpointer to the kvm
structure to do fancy accounting?

You have your own hypervisor, that's well and good. Since your
main argument is that it is supposed to be standalone, make it
*really* standalone and don't use KVM as a prop.

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-04-28 22:12     ` Marc Zyngier
@ 2023-04-28 22:48       ` Trilok Soni
  -1 siblings, 0 replies; 66+ messages in thread
From: Trilok Soni @ 2023-04-28 22:48 UTC (permalink / raw)
  To: Marc Zyngier, Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Catalin Marinas, Will Deacon, Arnd Bergmann,
	Matthias Brugger, AngeloGioacchino Del Regno, devicetree,
	linux-kernel, linux-doc, linux-arm-kernel, linux-arch,
	linux-mediatek, David Bradil, Jade Shih, Miles Chen, Ivan Tseng,
	My Chuang, Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Marc,

> 
> [...]
> 
>> +/**
>> + * gzvm_gfn_to_pfn_memslot() - Translate gfn (guest ipa) to pfn (host 
>> pa),
>> + *                   result is in @pfn
>> + *
>> + * Leverage KVM's gfn_to_pfn_memslot(). Because gfn_to_pfn_memslot() 
>> needs
>> + * kvm_memory_slot as parameter, this function populates necessary 
>> fileds
>> + * for calling gfn_to_pfn_memslot().
>> + *
>> + * Return:
>> + * * 0            - Succeed
>> + * * -EFAULT        - Failed to convert
>> + */
>> +static int gzvm_gfn_to_pfn_memslot(struct gzvm_memslot *memslot, u64
>> gfn, u64 *pfn)
>> +{
>> +    hfn_t __pfn;
>> +    struct kvm_memory_slot kvm_slot = {0};
>> +
>> +    kvm_slot.base_gfn = memslot->base_gfn;
>> +    kvm_slot.npages = memslot->npages;
>> +    kvm_slot.dirty_bitmap = NULL;
>> +    kvm_slot.userspace_addr = memslot->userspace_addr;
>> +    kvm_slot.flags = memslot->flags;
>> +    kvm_slot.id = memslot->slot_id;
>> +    kvm_slot.as_id = 0;
>> +
>> +    __pfn = gfn_to_pfn_memslot(&kvm_slot, gfn);
> 
> Again, I absolutely oppose this horror. This is internal to KVM,
> and we want to be able to change this without having to mess
> with your own code that we cannot test anyway.
> 
> What if we start using the extra fields that you don't populate
> as they mean nothing to you? Or add a backpointer to the kvm
> structure to do fancy accounting?
> 
> You have your own hypervisor, that's well and good. Since your
> main argument is that it is supposed to be standalone, make it
> *really* standalone and don't use KVM as a prop.


Agreed, same comments were made earlier too. I would prefer that 
GenieZone have its own identify rather than sharing the 
APIs/data-structures here.

---Trilok Soni

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
@ 2023-04-28 22:48       ` Trilok Soni
  0 siblings, 0 replies; 66+ messages in thread
From: Trilok Soni @ 2023-04-28 22:48 UTC (permalink / raw)
  To: Marc Zyngier, Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Catalin Marinas, Will Deacon, Arnd Bergmann,
	Matthias Brugger, AngeloGioacchino Del Regno, devicetree,
	linux-kernel, linux-doc, linux-arm-kernel, linux-arch,
	linux-mediatek, David Bradil, Jade Shih, Miles Chen, Ivan Tseng,
	My Chuang, Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Marc,

> 
> [...]
> 
>> +/**
>> + * gzvm_gfn_to_pfn_memslot() - Translate gfn (guest ipa) to pfn (host 
>> pa),
>> + *                   result is in @pfn
>> + *
>> + * Leverage KVM's gfn_to_pfn_memslot(). Because gfn_to_pfn_memslot() 
>> needs
>> + * kvm_memory_slot as parameter, this function populates necessary 
>> fileds
>> + * for calling gfn_to_pfn_memslot().
>> + *
>> + * Return:
>> + * * 0            - Succeed
>> + * * -EFAULT        - Failed to convert
>> + */
>> +static int gzvm_gfn_to_pfn_memslot(struct gzvm_memslot *memslot, u64
>> gfn, u64 *pfn)
>> +{
>> +    hfn_t __pfn;
>> +    struct kvm_memory_slot kvm_slot = {0};
>> +
>> +    kvm_slot.base_gfn = memslot->base_gfn;
>> +    kvm_slot.npages = memslot->npages;
>> +    kvm_slot.dirty_bitmap = NULL;
>> +    kvm_slot.userspace_addr = memslot->userspace_addr;
>> +    kvm_slot.flags = memslot->flags;
>> +    kvm_slot.id = memslot->slot_id;
>> +    kvm_slot.as_id = 0;
>> +
>> +    __pfn = gfn_to_pfn_memslot(&kvm_slot, gfn);
> 
> Again, I absolutely oppose this horror. This is internal to KVM,
> and we want to be able to change this without having to mess
> with your own code that we cannot test anyway.
> 
> What if we start using the extra fields that you don't populate
> as they mean nothing to you? Or add a backpointer to the kvm
> structure to do fancy accounting?
> 
> You have your own hypervisor, that's well and good. Since your
> main argument is that it is supposed to be standalone, make it
> *really* standalone and don't use KVM as a prop.


Agreed, same comments were made earlier too. I would prefer that 
GenieZone have its own identify rather than sharing the 
APIs/data-structures here.

---Trilok Soni

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 4/7] virt: geniezone: Add vcpu support
  2023-04-28 10:36   ` Yi-De Wu
@ 2023-04-29  6:34     ` kernel test robot
  -1 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2023-04-29  6:34 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: oe-kbuild-all, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Yi-De,

kernel test robot noticed the following build warnings:

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on robh/for-next arnd-asm-generic/master linus/master v6.3 next-20230428]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20230428103622.18291-5-yi-de.wu%40mediatek.com
patch subject: [PATCH v2 4/7] virt: geniezone: Add vcpu support
config: arm64-allyesconfig (https://download.01.org/0day-ci/archive/20230429/202304291412.EiKEO9uy-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/d4ced06ba2f149b099e9bf745a0e451c43e9d823
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
        git checkout d4ced06ba2f149b099e9bf745a0e451c43e9d823
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304291412.EiKEO9uy-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> arch/arm64/geniezone/../../../drivers/virt/geniezone/gzvm_vcpu.c:145:6: warning: no previous prototype for 'gzvm_destroy_vcpu' [-Wmissing-prototypes]
     145 | void gzvm_destroy_vcpu(struct gzvm_vcpu *vcpu)
         |      ^~~~~~~~~~~~~~~~~


vim +/gzvm_destroy_vcpu +145 arch/arm64/geniezone/../../../drivers/virt/geniezone/gzvm_vcpu.c

   143	
   144	/* caller must hold the vm lock */
 > 145	void gzvm_destroy_vcpu(struct gzvm_vcpu *vcpu)
   146	{
   147		if (!vcpu)
   148			return;
   149	
   150		gzvm_arch_destroy_vcpu(vcpu->gzvm->vm_id, vcpu->vcpuid);
   151		/* clean guest's data */
   152		memset(vcpu->run, 0, GZVM_VCPU_RUN_MAP_SIZE);
   153		free_pages_exact(vcpu->run, GZVM_VCPU_RUN_MAP_SIZE);
   154		kfree(vcpu);
   155	}
   156	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 4/7] virt: geniezone: Add vcpu support
@ 2023-04-29  6:34     ` kernel test robot
  0 siblings, 0 replies; 66+ messages in thread
From: kernel test robot @ 2023-04-29  6:34 UTC (permalink / raw)
  To: Yi-De Wu, Yingshiuan Pan, Ze-Yu Wang, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Catalin Marinas,
	Will Deacon, Arnd Bergmann, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: oe-kbuild-all, devicetree, linux-kernel, linux-doc,
	linux-arm-kernel, linux-arch, linux-mediatek, David Bradil,
	Trilok Soni, Jade Shih, Miles Chen, Ivan Tseng, My Chuang,
	Shawn Hsiao, PeiLun Suei, Liju Chen

Hi Yi-De,

kernel test robot noticed the following build warnings:

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on robh/for-next arnd-asm-generic/master linus/master v6.3 next-20230428]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20230428103622.18291-5-yi-de.wu%40mediatek.com
patch subject: [PATCH v2 4/7] virt: geniezone: Add vcpu support
config: arm64-allyesconfig (https://download.01.org/0day-ci/archive/20230429/202304291412.EiKEO9uy-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/d4ced06ba2f149b099e9bf745a0e451c43e9d823
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yi-De-Wu/docs-geniezone-Introduce-GenieZone-hypervisor/20230428-183738
        git checkout d4ced06ba2f149b099e9bf745a0e451c43e9d823
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304291412.EiKEO9uy-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> arch/arm64/geniezone/../../../drivers/virt/geniezone/gzvm_vcpu.c:145:6: warning: no previous prototype for 'gzvm_destroy_vcpu' [-Wmissing-prototypes]
     145 | void gzvm_destroy_vcpu(struct gzvm_vcpu *vcpu)
         |      ^~~~~~~~~~~~~~~~~


vim +/gzvm_destroy_vcpu +145 arch/arm64/geniezone/../../../drivers/virt/geniezone/gzvm_vcpu.c

   143	
   144	/* caller must hold the vm lock */
 > 145	void gzvm_destroy_vcpu(struct gzvm_vcpu *vcpu)
   146	{
   147		if (!vcpu)
   148			return;
   149	
   150		gzvm_arch_destroy_vcpu(vcpu->gzvm->vm_id, vcpu->vcpuid);
   151		/* clean guest's data */
   152		memset(vcpu->run, 0, GZVM_VCPU_RUN_MAP_SIZE);
   153		free_pages_exact(vcpu->run, GZVM_VCPU_RUN_MAP_SIZE);
   154		kfree(vcpu);
   155	}
   156	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-04-28 14:52     ` Rob Herring
  (?)
@ 2023-05-12  6:42     ` Yi-De Wu (吳一德)
  2023-05-12 16:34       ` Trilok Soni
  -1 siblings, 1 reply; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-12  6:42 UTC (permalink / raw)
  To: robh
  Cc: corbet, linux-mediatek, quic_tsoni,
	MY Chuang (莊明躍),
	linux-kernel, arnd, devicetree, robh+dt, linux-arm-kernel,
	angelogioacchino.delregno, PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, Shawn Hsiao (蕭志祥),
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, Miles Chen (陳民樺),
	matthias.bgg, linux-doc, Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	linux-arch, will

On Fri, 2023-04-28 at 09:52 -0500, Rob Herring wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, 28 Apr 2023 18:36:17 +0800, Yi-De Wu wrote:
> > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > 
> > 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.
> > 
> > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > ---
> >  .../hypervisor/mediatek,geniezone-hyp.yaml    | 31
> > +++++++++++++++++++
> >  MAINTAINERS                                   |  1 +
> >  2 files changed, 32 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-
> > hyp.yaml
> > 
> 
> My bot found errors running 'make DT_CHECKER_FLAGS=-m
> dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> ./Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-
> hyp.yaml: $id: relative path/filename doesn't match actual path or
> filename
>         expected: 
> https://urldefense.com/v3/__http://devicetree.org/schemas/hypervisor/mediatek,geniezone-hyp.yaml*__;Iw!!CTRNKA9wMg0ARbw!joIOXbICM7UGvy3XBEJvfzSKO7s61efB87_NX5cqpUqpu5ot5cuzw50A8-8ledZT9_7ifsB2sKzxSD0$
> 
> doc reference errors (make refcheckdocs):
> 
> See 
> https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230428103622.18291-3-yi-de.wu@mediatek.com
> 
> The base for the series is generally the latest rc1. A different
> dependency
> should be noted in *this* patch.
> 
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up
> to
> date:
> 
> pip3 install dtschema --upgrade
> 
> Please check and re-submit after running the above command yourself.
> Note
> that DT_SCHEMA_FILES can be set to your schema file to speed up
> checking
> your schema. However, it must be unset to test all examples with your
> schema.
> 

Noted, we've run the yaml check and we are going to re-submit the
latest version in v3.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-04-28 21:24     ` Rob Herring
  (?)
@ 2023-05-12  6:42     ` Yi-De Wu (吳一德)
  2023-05-12 11:01       ` Conor Dooley
  2023-06-26  9:05         ` Yi-De Wu (吳一德)
  -1 siblings, 2 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-12  6:42 UTC (permalink / raw)
  To: robh
  Cc: corbet, linux-kernel, linux-mediatek, angelogioacchino.delregno,
	MY Chuang (莊明躍),
	linux-arch, devicetree, quic_tsoni,
	Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

On Fri, 2023-04-28 at 16:24 -0500, Rob Herring wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, Apr 28, 2023 at 06:36:17PM +0800, Yi-De Wu wrote:
> > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > 
> > 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.
> 
> Why can't the driver just try and do virtual machine operations to
> see
> if the hypervisor is there? IOW, make your software interfaces
> discoverable. DT is for non-discoverable hardware.
> 
> Rob

Can do, our hypervisor is discoverable through invoking probing
hypercall, and we use the device tree to prevent unnecessary module
loading on all systems.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-04-28 22:12     ` Marc Zyngier
  (?)
  (?)
@ 2023-05-12  7:17     ` Yi-De Wu (吳一德)
  2023-05-12  9:59       ` Marc Zyngier
  -1 siblings, 1 reply; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-12  7:17 UTC (permalink / raw)
  To: maz
  Cc: corbet, linux-kernel, robh+dt, angelogioacchino.delregno,
	linux-mediatek, linux-arch, MY Chuang (莊明躍),
	devicetree, quic_tsoni, Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

On Fri, 2023-04-28 at 23:12 +0100, Marc Zyngier wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 2023-04-28 11:36, Yi-De Wu wrote:
> > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > 
> > GenieZone is MediaTek hypervisor solution, and it is running in EL2
> > stand alone as a type-I hypervisor. This patch exports a set of
> > ioctl
> > interfaces for userspace VMM (e.g., crosvm) to operate guest VMs
> > lifecycle (creation and destroy) on GenieZone.
> > 
> > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > ---
> >  MAINTAINERS                             |   6 +
> >  arch/arm64/Kbuild                       |   1 +
> >  arch/arm64/geniezone/Makefile           |   9 +
> >  arch/arm64/geniezone/gzvm_arch.c        | 189 +++++++++++++
> >  arch/arm64/geniezone/gzvm_arch.h        |  50 ++++
> >  arch/arm64/include/uapi/asm/gzvm_arch.h |  18 ++
> >  drivers/virt/Kconfig                    |   2 +
> >  drivers/virt/geniezone/Kconfig          |  17 ++
> >  drivers/virt/geniezone/Makefile         |  10 +
> >  drivers/virt/geniezone/gzvm_main.c      | 146 ++++++++++
> >  drivers/virt/geniezone/gzvm_vm.c        | 336
> > ++++++++++++++++++++++++
> >  include/linux/gzvm_drv.h                |  98 +++++++
> >  include/uapi/asm-generic/gzvm_arch.h    |  10 +
> >  include/uapi/linux/gzvm.h               |  99 +++++++
> >  14 files changed, 991 insertions(+)
> >  create mode 100644 arch/arm64/geniezone/Makefile
> >  create mode 100644 arch/arm64/geniezone/gzvm_arch.c
> >  create mode 100644 arch/arm64/geniezone/gzvm_arch.h
> >  create mode 100644 arch/arm64/include/uapi/asm/gzvm_arch.h
> >  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 drivers/virt/geniezone/gzvm_vm.c
> >  create mode 100644 include/linux/gzvm_drv.h
> >  create mode 100644 include/uapi/asm-generic/gzvm_arch.h
> >  create mode 100644 include/uapi/linux/gzvm.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 1e911d1d9741..09a8ccf77b01 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -8700,6 +8700,12 @@ M:     Ze-Yu Wang <ze-yu.wang@mediatek.com>
> >  M:   Yi-De Wu <yi-de.wu@mediatek.com>
> > 
> > F:    Documentation/devicetree/bindings/hypervisor/mediatek,geniezo
> > ne-hyp.yaml
> >  F:   Documentation/virt/geniezone/
> > +F:   arch/arm64/geniezone/
> > +F:   arch/arm64/include/uapi/asm/gzvm_arch.h
> > +F:   drivers/virt/geniezone/
> > +F:   include/linux/gzvm_drv.h
> > +F    include/uapi/asm-generic/gzvm_arch.h
> > +F:   include/uapi/linux/gzvm.h
> > 
> >  GENWQE (IBM Generic Workqueue Card)
> >  M:   Frank Haverkamp <haver@linux.ibm.com>
> > 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..5720c076d73c
> > --- /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 += gzvm_arch.o
> > +
> > +obj-$(CONFIG_MTK_GZVM) += gzvm.o
> > diff --git a/arch/arm64/geniezone/gzvm_arch.c
> > b/arch/arm64/geniezone/gzvm_arch.c
> > new file mode 100644
> > index 000000000000..2fc76f7d440f
> > --- /dev/null
> > +++ b/arch/arm64/geniezone/gzvm_arch.c
> > @@ -0,0 +1,189 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2023 MediaTek Inc.
> > + */
> > +
> > +#include <linux/arm-smccc.h>
> > +#include <linux/err.h>
> > +#include <linux/uaccess.h>
> > +
> > +#include <linux/gzvm.h>
> > +#include <linux/gzvm_drv.h>
> > +#include "gzvm_arch.h"
> > +
> > +/**
> > + * geniezone_hypercall_wrapper()
> > + *
> > + * Return: The wrapper helps caller to convert geniezone errno to
> > Linux errno.
> > + */
> > +static 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 gz_err_to_errno(res->a0);
> > +}
> > +
> > +int gzvm_arch_probe(void)
> > +{
> > +     struct arm_smccc_res res;
> > +
> > +     arm_smccc_hvc(MT_HVC_GZVM_PROBE, 0, 0, 0, 0, 0, 0, 0, &res);
> > +     if (res.a0 == 0)
> > +             return 0;
> > +
> > +     return -ENXIO;
> > +}
> > +
> > +int gzvm_arch_set_memregion(gzvm_id_t vm_id, size_t buf_size,
> > +                         phys_addr_t region)
> > +{
> > +     struct arm_smccc_res res;
> > +
> > +     return gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_MEMREGION, vm_id,
> > +                                 buf_size, region, 0, 0, 0, 0,
> > &res);
> > +}
> > +
> > +static int gzvm_cap_arm_vm_ipa_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 = -EOPNOTSUPP;
> > +
> > +     switch (cap) {
> > +     case GZVM_CAP_ARM_PROTECTED_VM: {
> > +             __u64 success = 1;
> > +
> > +             if (copy_to_user(argp, &success, sizeof(__u64)))
> > +                     return -EFAULT;
> > +             ret = 0;
> > +             break;
> > +     }
> > +     case GZVM_CAP_ARM_VM_IPA_SIZE: {
> > +             ret = gzvm_cap_arm_vm_ipa_size(argp);
> > +             break;
> > +     }
> > +     default:
> > +             ret = -EOPNOTSUPP;
> > +     }
> > +
> > +     return ret;
> > +}
> > +
> > +/**
> > + * gzvm_arch_create_vm()
> > + *
> > + * Return:
> > + * * positive value  - VM ID
> > + * * -ENOMEM         - Memory not enough for storing VM data
> > + */
> > +int gzvm_arch_create_vm(void)
> > +{
> > +     struct arm_smccc_res res;
> > +     int ret;
> > +
> > +     ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VM, 0, 0, 0, 0,
> > 0, 0,
> > 0,
> > +                                &res);
> > +
> > +     if (ret == 0)
> > +             return res.a1;
> > +     else
> > +             return ret;
> > +}
> > +
> > +int gzvm_arch_destroy_vm(gzvm_id_t 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);
> > +}
> > +
> > +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.
> > + *
> > + * 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_ARM_PROTECTED_VM's
> > subcommands
> > + *
> > + * 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)
> > +{
> > +     int ret = -EINVAL;
> > +     struct arm_smccc_res res = {0};
> > +
> > +     switch (cap->args[0]) {
> > +     case GZVM_CAP_ARM_PVM_SET_PVMFW_IPA:
> > +             ret = gzvm_vm_arch_enable_cap(gzvm, cap, &res);
> > +             break;
> > +     case GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE:
> > +             ret = gzvm_vm_ioctl_get_pvmfw_size(gzvm, cap, argp);
> > +             break;
> > +     default:
> > +             ret = -EINVAL;
> > +             break;
> > +     }
> > +
> > +     return ret;
> > +}
> > +
> > +int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm, struct
> > gzvm_enable_cap *cap,
> > +                               void __user *argp)
> > +{
> > +     int ret = -EINVAL;
> > +
> > +     switch (cap->cap) {
> > +     case GZVM_CAP_ARM_PROTECTED_VM:
> > +             ret = gzvm_vm_ioctl_cap_pvm(gzvm, cap, argp);
> > +             break;
> > +     default:
> > +             ret = -EINVAL;
> > +             break;
> > +     }
> > +
> > +     return ret;
> > +}
> > diff --git a/arch/arm64/geniezone/gzvm_arch.h
> > b/arch/arm64/geniezone/gzvm_arch.h
> > new file mode 100644
> > index 000000000000..dd0b7b5f7c65
> > --- /dev/null
> > +++ b/arch/arm64/geniezone/gzvm_arch.h
> > @@ -0,0 +1,50 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2023 MediaTek Inc.
> > + */
> > +
> > +#ifndef __GZ_ARCH_H__
> > +#define __GZ_ARCH_H__
> > +
> > +#include <linux/arm-smccc.h>
> > +
> > +enum {
> > +     GZVM_FUNC_CREATE_VM = 0,
> > +     GZVM_FUNC_DESTROY_VM,
> > +     GZVM_FUNC_CREATE_VCPU,
> > +     GZVM_FUNC_DESTROY_VCPU,
> > +     GZVM_FUNC_SET_MEMREGION,
> > +     GZVM_FUNC_RUN,
> > +     GZVM_FUNC_GET_REGS,
> > +     GZVM_FUNC_SET_REGS,
> > +     GZVM_FUNC_GET_ONE_REG,
> > +     GZVM_FUNC_SET_ONE_REG,
> > +     GZVM_FUNC_IRQ_LINE,
> > +     GZVM_FUNC_CREATE_DEVICE,
> > +     GZVM_FUNC_PROBE,
> > +     GZVM_FUNC_ENABLE_CAP,
> > +     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_32,       \
> > +                        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_DESTRO
> > Y_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_REGS         GZVM_HCALL_ID(GZVM_FUNC_GET_REGS)
> > +#define
> > MT_HVC_GZVM_SET_REGS         GZVM_HCALL_ID(GZVM_FUNC_SET_REGS)
> > +#define
> > MT_HVC_GZVM_GET_ONE_REG              GZVM_HCALL_ID(GZVM_FUNC_GET_ON
> > E_REG)
> > +#define
> > MT_HVC_GZVM_SET_ONE_REG              GZVM_HCALL_ID(GZVM_FUNC_SET_ON
> > E_REG)
> > +#define
> > MT_HVC_GZVM_IRQ_LINE         GZVM_HCALL_ID(GZVM_FUNC_IRQ_LINE)
> > +#define
> > MT_HVC_GZVM_CREATE_DEVICE     GZVM_HCALL_ID(GZVM_FUNC_CREATE_DEVICE
> > )
> > +#define
> > MT_HVC_GZVM_PROBE            GZVM_HCALL_ID(GZVM_FUNC_PROBE)
> > +#define
> > MT_HVC_GZVM_ENABLE_CAP               GZVM_HCALL_ID(GZVM_FUNC_ENABLE
> > _CAP)
> > +
> > +#endif /* __GZVM_ARCH_H__ */
> > diff --git a/arch/arm64/include/uapi/asm/gzvm_arch.h
> > b/arch/arm64/include/uapi/asm/gzvm_arch.h
> > new file mode 100644
> > index 000000000000..e7927f3dcb11
> > --- /dev/null
> > +++ b/arch/arm64/include/uapi/asm/gzvm_arch.h
> > @@ -0,0 +1,18 @@
> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > +/*
> > + * Copyright (c) 2023 MediaTek Inc.
> > + */
> > +
> > +#ifndef __GZVM_ARCH_H__
> > +#define __GZVM_ARCH_H__
> > +
> > +#include <linux/types.h>
> > +
> > +#define GZVM_CAP_ARM_VM_IPA_SIZE     165
> > +#define GZVM_CAP_ARM_PROTECTED_VM    0xffbadab1
> > +
> > +/* sub-commands put in args[0] for GZVM_CAP_ARM_PROTECTED_VM */
> > +#define GZVM_CAP_ARM_PVM_SET_PVMFW_IPA               0
> > +#define GZVM_CAP_ARM_PVM_GET_PVMFW_SIZE              1
> > +
> > +#endif /* __GZVM_ARCH_H__ */
> > diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
> > index f79ab13a5c28..9bbf0bdf672c 100644
> > --- a/drivers/virt/Kconfig
> > +++ b/drivers/virt/Kconfig
> > @@ -54,4 +54,6 @@ source "drivers/virt/coco/sev-guest/Kconfig"
> > 
> >  source "drivers/virt/coco/tdx-guest/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..6fad3c30f8d9
> > --- /dev/null
> > +++ b/drivers/virt/geniezone/Kconfig
> > @@ -0,0 +1,17 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +
> > +config MTK_GZVM
> > +     tristate "GenieZone Hypervisor driver for guest VM operation"
> > +     depends on ARM64
> > +     depends on KVM
> 
> NAK.
> 
> Either this is KVM, and this code serves no purpose, or it is a
> standalone
> hypervisor, and it *cannot* have a dependency on KVM.
> 
> [...]
> 

In order to be self-contained and avoid dependency like with KVM, may
we leverage KVM's symbol, macro e.g. VGIC_NR_SGIS,
VGIC_NR_PRIVATE_IRQS...etc, and copy or rename the related part to
*/geniezone/?

> > +/**
> > + * gzvm_gfn_to_pfn_memslot() - Translate gfn (guest ipa) to pfn
> > (host
> > pa),
> > + *                          result is in @pfn
> > + *
> > + * Leverage KVM's gfn_to_pfn_memslot(). Because
> > gfn_to_pfn_memslot()
> > needs
> > + * kvm_memory_slot as parameter, this function populates necessary
> > fileds
> > + * for calling gfn_to_pfn_memslot().
> > + *
> > + * Return:
> > + * * 0                       - Succeed
> > + * * -EFAULT         - Failed to convert
> > + */
> > +static int gzvm_gfn_to_pfn_memslot(struct gzvm_memslot *memslot,
> > u64
> > gfn, u64 *pfn)
> > +{
> > +     hfn_t __pfn;
> > +     struct kvm_memory_slot kvm_slot = {0};
> > +
> > +     kvm_slot.base_gfn = memslot->base_gfn;
> > +     kvm_slot.npages = memslot->npages;
> > +     kvm_slot.dirty_bitmap = NULL;
> > +     kvm_slot.userspace_addr = memslot->userspace_addr;
> > +     kvm_slot.flags = memslot->flags;
> > +     kvm_slot.id = memslot->slot_id;
> > +     kvm_slot.as_id = 0;
> > +
> > +     __pfn = gfn_to_pfn_memslot(&kvm_slot, gfn);
> 
> Again, I absolutely oppose this horror. This is internal to KVM,
> and we want to be able to change this without having to mess
> with your own code that we cannot test anyway.
> 
> What if we start using the extra fields that you don't populate
> as they mean nothing to you? Or add a backpointer to the kvm
> structure to do fancy accounting?
> 
> You have your own hypervisor, that's well and good. Since your
> main argument is that it is supposed to be standalone, make it
> *really* standalone and don't use KVM as a prop.
> 
> Thanks,
> 
>          M.
> --
> Jazz is not dead. It just smells funny...

Same with previous discussion, we'd like to copy or rename the related
part from KVM and keep the maintainance at our own if it's ok.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-04-28 22:48       ` Trilok Soni
  (?)
@ 2023-05-12  7:18       ` Yi-De Wu (吳一德)
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-12  7:18 UTC (permalink / raw)
  To: maz, quic_tsoni
  Cc: corbet, linux-kernel, robh+dt, angelogioacchino.delregno,
	linux-mediatek, linux-arch, MY Chuang (莊明躍),
	devicetree, Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

On Fri, 2023-04-28 at 15:48 -0700, Trilok Soni wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Hi Marc,
> 
> > 
> > [...]
> > 
> > > +/**
> > > + * gzvm_gfn_to_pfn_memslot() - Translate gfn (guest ipa) to pfn
> > > (host
> > > pa),
> > > + *                   result is in @pfn
> > > + *
> > > + * Leverage KVM's gfn_to_pfn_memslot(). Because
> > > gfn_to_pfn_memslot()
> > > needs
> > > + * kvm_memory_slot as parameter, this function populates
> > > necessary
> > > fileds
> > > + * for calling gfn_to_pfn_memslot().
> > > + *
> > > + * Return:
> > > + * * 0            - Succeed
> > > + * * -EFAULT        - Failed to convert
> > > + */
> > > +static int gzvm_gfn_to_pfn_memslot(struct gzvm_memslot *memslot,
> > > u64
> > > gfn, u64 *pfn)
> > > +{
> > > +    hfn_t __pfn;
> > > +    struct kvm_memory_slot kvm_slot = {0};
> > > +
> > > +    kvm_slot.base_gfn = memslot->base_gfn;
> > > +    kvm_slot.npages = memslot->npages;
> > > +    kvm_slot.dirty_bitmap = NULL;
> > > +    kvm_slot.userspace_addr = memslot->userspace_addr;
> > > +    kvm_slot.flags = memslot->flags;
> > > +    kvm_slot.id = memslot->slot_id;
> > > +    kvm_slot.as_id = 0;
> > > +
> > > +    __pfn = gfn_to_pfn_memslot(&kvm_slot, gfn);
> > 
> > Again, I absolutely oppose this horror. This is internal to KVM,
> > and we want to be able to change this without having to mess
> > with your own code that we cannot test anyway.
> > 
> > What if we start using the extra fields that you don't populate
> > as they mean nothing to you? Or add a backpointer to the kvm
> > structure to do fancy accounting?
> > 
> > You have your own hypervisor, that's well and good. Since your
> > main argument is that it is supposed to be standalone, make it
> > *really* standalone and don't use KVM as a prop.
> 
> 
> Agreed, same comments were made earlier too. I would prefer that
> GenieZone have its own identify rather than sharing the
> APIs/data-structures here.
> 
> ---Trilok Soni

Same with previous discussion, we'd like to copy or rename the related 
part from KVM and keep the maintainance at our own if it's ok.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
  2023-04-28 18:59     ` Marc Zyngier
  (?)
@ 2023-05-12  7:19     ` Yi-De Wu (吳一德)
  2023-05-12  7:51       ` Marc Zyngier
  -1 siblings, 1 reply; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-12  7:19 UTC (permalink / raw)
  To: maz
  Cc: corbet, linux-kernel, robh+dt, angelogioacchino.delregno,
	linux-mediatek, linux-arch, MY Chuang (莊明躍),
	devicetree, quic_tsoni, Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

On Fri, 2023-04-28 at 19:59 +0100, Marc Zyngier wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 2023-04-28 11:36, Yi-De Wu wrote:
> > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > 
> > Enable GenieZone to handle virtual interrupt injection request.
> > 
> > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > ---
> >  arch/arm64/geniezone/Makefile       |  2 +-
> >  arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
> >  arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
> >  arch/arm64/geniezone/gzvm_irqchip.c | 88
> > +++++++++++++++++++++++++++++
> >  drivers/virt/geniezone/gzvm_vm.c    | 75 ++++++++++++++++++++++++
> >  include/linux/gzvm_drv.h            |  4 ++
> >  include/uapi/linux/gzvm.h           | 38 ++++++++++++-
> >  7 files changed, 235 insertions(+), 7 deletions(-)
> >  create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c
> 
> [...]
> 
> > +++ b/arch/arm64/geniezone/gzvm_irqchip.c
> > @@ -0,0 +1,88 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2023 MediaTek Inc.
> > + */
> > +
> > +#include <linux/irqchip/arm-gic-v3.h>
> > +#include <kvm/arm_vgic.h>
> 
> NAK.
> 
> There is no way you can rely on anything from KVM in
> your own hypervisor code.
> 

Same with previous discussion, we'd like to copy or rename the related 
part from KVM and keep the maintainance at our own if it's ok.

> > +
> > +#include <linux/gzvm.h>
> > +#include <linux/gzvm_drv.h>
> > +#include "gzvm_arch.h"
> > +
> > +/**
> > + * gzvm_sync_vgic_state() - Check all LRs synced from gz
> > hypervisor
> > + *
> > + * Traverse all LRs, see if any EOIed vint, notify_acked_irq if
> > any.
> > + * GZ does not fold/unfold everytime KVM_RUN, so we have to
> > traverse
> > all saved
> > + * LRs. It will not takes much more time comparing to fold/unfold
> > everytime
> > + * GZVM_RUN, because there are only few LRs.
> > + */
> > +void gzvm_sync_vgic_state(struct gzvm_vcpu *vcpu)
> > +{
> > +}
> > +
> > +/* is_irq_valid() - Check the irq number and irq_type are matched
> > */
> > +static bool is_irq_valid(u32 irq, u32 irq_type)
> > +{
> > +     switch (irq_type) {
> > +     case GZVM_IRQ_TYPE_CPU:
> > +             /*  0 ~ 15: SGI */
> > +             if (likely(irq <= GZVM_IRQ_CPU_FIQ))
> > +                     return true;
> > +             break;
> > +     case GZVM_IRQ_TYPE_PPI:
> > +             /* 16 ~ 31: PPI */
> > +             if (likely(irq >= VGIC_NR_SGIS && irq <
> > VGIC_NR_PRIVATE_IRQS))
> 
> What happens if I redefine all these macros tomorrow? None of
> this code should rely on anything that is *INTERNAL* to KVM.
> 
>          M.
> --
> Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
  2023-05-12  7:19     ` Yi-De Wu (吳一德)
@ 2023-05-12  7:51       ` Marc Zyngier
  2023-05-12  8:16         ` Yi-De Wu (吳一德)
  0 siblings, 1 reply; 66+ messages in thread
From: Marc Zyngier @ 2023-05-12  7:51 UTC (permalink / raw)
  To: "Yi-De Wu (吳一德)"
  Cc: corbet, linux-kernel, robh+dt, angelogioacchino.delregno,
	linux-mediatek, linux-arch,
	"MY Chuang (莊明躍)",
	devicetree, quic_tsoni,
	"Shawn Hsiao (蕭志祥)",
	"Miles Chen (陳民樺)",
	"PeiLun Suei (隋培倫)",
	"Liju-clr Chen (陳麗如)",
	"Jades Shih (施向玨)",
	catalin.marinas, dbrazdil, linux-arm-kernel,
	"Yingshiuan Pan (潘穎軒)",
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	"Ze-yu Wang (王澤宇)",
	will, "Ivan Tseng (曾志軒)"

On Fri, 12 May 2023 08:19:31 +0100,
"Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> 
> On Fri, 2023-04-28 at 19:59 +0100, Marc Zyngier wrote:
> > External email : Please do not click links or open attachments until
> > you have verified the sender or the content.
> > 
> > 
> > On 2023-04-28 11:36, Yi-De Wu wrote:
> > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > 
> > > Enable GenieZone to handle virtual interrupt injection request.
> > > 
> > > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > > ---
> > >  arch/arm64/geniezone/Makefile       |  2 +-
> > >  arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
> > >  arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
> > >  arch/arm64/geniezone/gzvm_irqchip.c | 88
> > > +++++++++++++++++++++++++++++
> > >  drivers/virt/geniezone/gzvm_vm.c    | 75 ++++++++++++++++++++++++
> > >  include/linux/gzvm_drv.h            |  4 ++
> > >  include/uapi/linux/gzvm.h           | 38 ++++++++++++-
> > >  7 files changed, 235 insertions(+), 7 deletions(-)
> > >  create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c
> > 
> > [...]
> > 
> > > +++ b/arch/arm64/geniezone/gzvm_irqchip.c
> > > @@ -0,0 +1,88 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Copyright (c) 2023 MediaTek Inc.
> > > + */
> > > +
> > > +#include <linux/irqchip/arm-gic-v3.h>
> > > +#include <kvm/arm_vgic.h>
> > 
> > NAK.
> > 
> > There is no way you can rely on anything from KVM in
> > your own hypervisor code.
> > 
> 
> Same with previous discussion, we'd like to copy or rename the related 
> part from KVM and keep the maintainance at our own if it's ok.

Why do you need *ANY* of the KVM stuff? Please fully enumerate these
dependencies and why you have them.

Directly using KVM stuff for something completely unrelated is not OK,
and will never be.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
  2023-05-12  7:51       ` Marc Zyngier
@ 2023-05-12  8:16         ` Yi-De Wu (吳一德)
  2023-05-12  9:57           ` Marc Zyngier
  0 siblings, 1 reply; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-12  8:16 UTC (permalink / raw)
  To: maz
  Cc: corbet, linux-kernel, linux-mediatek, robh+dt,
	MY Chuang (莊明躍),
	quic_tsoni, krzysztof.kozlowski+dt, devicetree,
	Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, Shawn Hsiao (蕭志祥),
	linux-arm-kernel, Miles Chen (陳民樺),
	matthias.bgg, Yingshiuan Pan (潘穎軒),
	linux-arch, arnd, angelogioacchino.delregno, linux-doc, will

On Fri, 2023-05-12 at 08:51 +0100, Marc Zyngier wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, 12 May 2023 08:19:31 +0100,
> "Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> > 
> > On Fri, 2023-04-28 at 19:59 +0100, Marc Zyngier wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On 2023-04-28 11:36, Yi-De Wu wrote:
> > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > 
> > > > Enable GenieZone to handle virtual interrupt injection request.
> > > > 
> > > > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > > > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > > > ---
> > > >  arch/arm64/geniezone/Makefile       |  2 +-
> > > >  arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
> > > >  arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
> > > >  arch/arm64/geniezone/gzvm_irqchip.c | 88
> > > > +++++++++++++++++++++++++++++
> > > >  drivers/virt/geniezone/gzvm_vm.c    | 75
> > > > ++++++++++++++++++++++++
> > > >  include/linux/gzvm_drv.h            |  4 ++
> > > >  include/uapi/linux/gzvm.h           | 38 ++++++++++++-
> > > >  7 files changed, 235 insertions(+), 7 deletions(-)
> > > >  create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c
> > > 
> > > [...]
> > > 
> > > > +++ b/arch/arm64/geniezone/gzvm_irqchip.c
> > > > @@ -0,0 +1,88 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/*
> > > > + * Copyright (c) 2023 MediaTek Inc.
> > > > + */
> > > > +
> > > > +#include <linux/irqchip/arm-gic-v3.h>
> > > > +#include <kvm/arm_vgic.h>
> > > 
> > > NAK.
> > > 
> > > There is no way you can rely on anything from KVM in
> > > your own hypervisor code.
> > > 
> > 
> > Same with previous discussion, we'd like to copy or rename the
> > related
> > part from KVM and keep the maintainance at our own if it's ok.
> 
> Why do you need *ANY* of the KVM stuff? Please fully enumerate these
> dependencies and why you have them.
> 
> Directly using KVM stuff for something completely unrelated is not
> OK,
> and will never be.
> 
>         M.
> 
> --
> Without deviation from the norm, progress is not possible.

The particular part we'd like to leverage from KVM are as followed
1. `gfn_to_pfn_memslot` to convert guest physical address(or
intermediate physical address) to physical address
2. get ARM's number of interrupt of different types e.g. number of SGI,
number of PPI...etc


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
  2023-05-12  8:16         ` Yi-De Wu (吳一德)
@ 2023-05-12  9:57           ` Marc Zyngier
  2023-05-22  4:32               ` Yi-De Wu (吳一德)
  0 siblings, 1 reply; 66+ messages in thread
From: Marc Zyngier @ 2023-05-12  9:57 UTC (permalink / raw)
  To: "Yi-De Wu (吳一德)"
  Cc: corbet, linux-kernel, linux-mediatek, robh+dt,
	"MY Chuang (莊明躍)",
	quic_tsoni, krzysztof.kozlowski+dt, devicetree,
	"Ivan Tseng (曾志軒)",
	"Ze-yu Wang (王澤宇)",
	"PeiLun Suei (隋培倫)",
	"Liju-clr Chen (陳麗如)",
	"Jades Shih (施向玨)",
	catalin.marinas, dbrazdil,
	"Shawn Hsiao (蕭志祥)",
	linux-arm-kernel, "Miles Chen (陳民樺)",
	matthias.bgg, "Yingshiuan Pan (潘穎軒)",
	linux-arch, arnd, angelogioacchino.delregno, linux-doc, will

On Fri, 12 May 2023 09:16:58 +0100,
"Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> 
> On Fri, 2023-05-12 at 08:51 +0100, Marc Zyngier wrote:
> > External email : Please do not click links or open attachments until
> > you have verified the sender or the content.
> > 
> > 
> > On Fri, 12 May 2023 08:19:31 +0100,
> > "Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> > > 
> > > On Fri, 2023-04-28 at 19:59 +0100, Marc Zyngier wrote:
> > > > External email : Please do not click links or open attachments
> > > > until
> > > > you have verified the sender or the content.
> > > > 
> > > > 
> > > > On 2023-04-28 11:36, Yi-De Wu wrote:
> > > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > > 
> > > > > Enable GenieZone to handle virtual interrupt injection request.
> > > > > 
> > > > > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > > > > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > > > > ---
> > > > >  arch/arm64/geniezone/Makefile       |  2 +-
> > > > >  arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
> > > > >  arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
> > > > >  arch/arm64/geniezone/gzvm_irqchip.c | 88
> > > > > +++++++++++++++++++++++++++++
> > > > >  drivers/virt/geniezone/gzvm_vm.c    | 75
> > > > > ++++++++++++++++++++++++
> > > > >  include/linux/gzvm_drv.h            |  4 ++
> > > > >  include/uapi/linux/gzvm.h           | 38 ++++++++++++-
> > > > >  7 files changed, 235 insertions(+), 7 deletions(-)
> > > > >  create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c
> > > > 
> > > > [...]
> > > > 
> > > > > +++ b/arch/arm64/geniezone/gzvm_irqchip.c
> > > > > @@ -0,0 +1,88 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > +/*
> > > > > + * Copyright (c) 2023 MediaTek Inc.
> > > > > + */
> > > > > +
> > > > > +#include <linux/irqchip/arm-gic-v3.h>
> > > > > +#include <kvm/arm_vgic.h>
> > > > 
> > > > NAK.
> > > > 
> > > > There is no way you can rely on anything from KVM in
> > > > your own hypervisor code.
> > > > 
> > > 
> > > Same with previous discussion, we'd like to copy or rename the
> > > related
> > > part from KVM and keep the maintainance at our own if it's ok.
> > 
> > Why do you need *ANY* of the KVM stuff? Please fully enumerate these
> > dependencies and why you have them.
> > 
> > Directly using KVM stuff for something completely unrelated is not
> > OK,
> > and will never be.
> > 
> >         M.
> > 
> > --
> > Without deviation from the norm, progress is not possible.
> 
> The particular part we'd like to leverage from KVM are as followed
> 1. `gfn_to_pfn_memslot` to convert guest physical address(or
> intermediate physical address) to physical address

What is a memslot in your hypervisor? How does it relate to KVM's?
What about the use of struct kvm?

I'm sorry, but your use of *internal* structures and API would make it
impossible for us to make any further change without potentially
affecting your hypervisor. Which is closed source and untestable.

To sum it up, I'm strongly opposed to any use of these data
structures.  If you can spot some commonalities, expose them as a
0-cost abstraction. But don't use them as is your code.

> 2. get ARM's number of interrupt of different types e.g. number of SGI,
> number of PPI...etc

These are architectural constants, and you can define your own. That
will cost you nothing but a handful of #define, and keep the two
subsystem independent.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-05-12  7:17     ` Yi-De Wu (吳一德)
@ 2023-05-12  9:59       ` Marc Zyngier
  2023-05-22  4:29           ` Yi-De Wu (吳一德)
  0 siblings, 1 reply; 66+ messages in thread
From: Marc Zyngier @ 2023-05-12  9:59 UTC (permalink / raw)
  To: "Yi-De Wu (吳一德)"
  Cc: corbet, linux-kernel, robh+dt, angelogioacchino.delregno,
	linux-mediatek, linux-arch,
	"MY Chuang (莊明躍)",
	devicetree, quic_tsoni,
	"Shawn Hsiao (蕭志祥)",
	"Miles Chen (陳民樺)",
	"PeiLun Suei (隋培倫)",
	"Liju-clr Chen (陳麗如)",
	"Jades Shih (施向玨)",
	catalin.marinas, dbrazdil, linux-arm-kernel,
	"Yingshiuan Pan (潘穎軒)",
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	"Ze-yu Wang (王澤宇)",
	will, "Ivan Tseng (曾志軒)"

On Fri, 12 May 2023 08:17:58 +0100,
"Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> 
> On Fri, 2023-04-28 at 23:12 +0100, Marc Zyngier wrote:
> > External email : Please do not click links or open attachments until
> > you have verified the sender or the content.
> > 
> > 
> > On 2023-04-28 11:36, Yi-De Wu wrote:
> > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > 
> > > +config MTK_GZVM
> > > +     tristate "GenieZone Hypervisor driver for guest VM operation"
> > > +     depends on ARM64
> > > +     depends on KVM
> > 
> > NAK.
> > 
> > Either this is KVM, and this code serves no purpose, or it is a
> > standalone
> > hypervisor, and it *cannot* have a dependency on KVM.
> > 
> > [...]
> > 
> 
> In order to be self-contained and avoid dependency like with KVM, may
> we leverage KVM's symbol, macro e.g. VGIC_NR_SGIS,
> VGIC_NR_PRIVATE_IRQS...etc, and copy or rename the related part to
> */geniezone/?

Again, these are architected constants. You can have your own. You can
already consider any use of a KVM structure or symbol as a bug.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-05-12  6:42     ` Yi-De Wu (吳一德)
@ 2023-05-12 11:01       ` Conor Dooley
  2023-05-22  3:28           ` Yi-De Wu (吳一德)
  2023-06-26  9:05         ` Yi-De Wu (吳一德)
  1 sibling, 1 reply; 66+ messages in thread
From: Conor Dooley @ 2023-05-12 11:01 UTC (permalink / raw)
  To: Yi-De Wu (吳一德)
  Cc: robh, corbet, linux-kernel, linux-mediatek,
	angelogioacchino.delregno, MY Chuang (莊明躍),
	linux-arch, devicetree, quic_tsoni,
	Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

[-- Attachment #1: Type: text/plain, Size: 1235 bytes --]

On Fri, May 12, 2023 at 06:42:51AM +0000, Yi-De Wu (吳一德) wrote:
> On Fri, 2023-04-28 at 16:24 -0500, Rob Herring wrote:
> > External email : Please do not click links or open attachments until
> > you have verified the sender or the content.
> > 
> > 
> > On Fri, Apr 28, 2023 at 06:36:17PM +0800, Yi-De Wu wrote:
> > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > 
> > > 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.
> > 
> > Why can't the driver just try and do virtual machine operations to
> > see
> > if the hypervisor is there? IOW, make your software interfaces
> > discoverable. DT is for non-discoverable hardware.
> > 
> > Rob
> 
> Can do, our hypervisor is discoverable through invoking probing
> hypercall, and we use the device tree to prevent unnecessary module
> loading on all systems.

Please do not wait until immediately prior to submitting version N+1
before replying to any of the comments on version N.
This creates a confusing scenario, where some review comments may be
missed due to parallel discussion.

Thanks,
Conor.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-05-12  6:42     ` Yi-De Wu (吳一德)
@ 2023-05-12 16:34       ` Trilok Soni
  2023-05-22  3:45           ` Yi-De Wu (吳一德)
  0 siblings, 1 reply; 66+ messages in thread
From: Trilok Soni @ 2023-05-12 16:34 UTC (permalink / raw)
  To: Yi-De Wu (吳一德), robh
  Cc: corbet, linux-mediatek, MY Chuang (莊明躍),
	linux-kernel, arnd, devicetree, robh+dt, linux-arm-kernel,
	angelogioacchino.delregno, PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, Shawn Hsiao (蕭志祥),
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, Miles Chen (陳民樺),
	matthias.bgg, linux-doc, Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	linux-arch, will

On 5/11/2023 11:42 PM, Yi-De Wu (吳一德) wrote:
> On Fri, 2023-04-28 at 09:52 -0500, Rob Herring wrote:
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>> 
>> 
>> On Fri, 28 Apr 2023 18:36:17 +0800, Yi-De Wu wrote:
>> > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
>> > 
>> > 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.
>> > 
>> > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
>> > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
>> > ---
>> >  .../hypervisor/mediatek,geniezone-hyp.yaml    | 31
>> > +++++++++++++++++++
>> >  MAINTAINERS                                   |  1 +
>> >  2 files changed, 32 insertions(+)
>> >  create mode 100644
>> > Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-
>> > hyp.yaml
>> > 
>> 
>> My bot found errors running 'make DT_CHECKER_FLAGS=-m
>> dt_binding_check'
>> on your patch (DT_CHECKER_FLAGS is new in v5.13):
>> 
>> yamllint warnings/errors:
>> 
>> dtschema/dtc warnings/errors:
>> ./Documentation/devicetree/bindings/hypervisor/mediatek,geniezone-
>> hyp.yaml: $id: relative path/filename doesn't match actual path or
>> filename
>>         expected: 
>> https://urldefense.com/v3/__http://devicetree.org/schemas/hypervisor/mediatek,geniezone-hyp.yaml*__;Iw!!CTRNKA9wMg0ARbw!joIOXbICM7UGvy3XBEJvfzSKO7s61efB87_NX5cqpUqpu5ot5cuzw50A8-8ledZT9_7ifsB2sKzxSD0$
>> 
>> doc reference errors (make refcheckdocs):
>> 
>> See 
>> https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230428103622.18291-3-yi-de.wu@mediatek.com
>> 
>> The base for the series is generally the latest rc1. A different
>> dependency
>> should be noted in *this* patch.
>> 
>> If you already ran 'make dt_binding_check' and didn't see the above
>> error(s), then make sure 'yamllint' is installed and dt-schema is up
>> to
>> date:
>> 
>> pip3 install dtschema --upgrade
>> 
>> Please check and re-submit after running the above command yourself.
>> Note
>> that DT_SCHEMA_FILES can be set to your schema file to speed up
>> checking
>> your schema. However, it must be unset to test all examples with your
>> schema.
>> 
> 
> Noted, we've run the yaml check and we are going to re-submit the
> latest version in v3.
> 
> ************* MEDIATEK Confidentiality Notice ********************
> The information contained in this e-mail message (including any
> attachments) may be confidential, proprietary, privileged, or otherwise
> exempt from disclosure under applicable laws. It is intended to be
> conveyed only to the designated recipient(s). Any use, dissemination,
> distribution, printing, retaining or copying of this e-mail (including its
> attachments) by unintended recipient(s) is strictly prohibited and may
> be unlawful. If you are not an intended recipient of this e-mail, or believe
> that you have received this e-mail in error, please notify the sender
> immediately (by replying to this e-mail), delete any and all copies of
> this e-mail (including any attachments) from your system, and do not
> disclose the content of this e-mail to any other person. Thank you!

Do you want us to reply w/ such a big confidentiality notice?


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 1/7] docs: geniezone: Introduce GenieZone hypervisor
  2023-04-28 10:36   ` Yi-De Wu
  (?)
@ 2023-05-12 16:51   ` Pavel Machek
  2023-05-22  5:45       ` Yi-De Wu (吳一德)
  -1 siblings, 1 reply; 66+ messages in thread
From: Pavel Machek @ 2023-05-12 16:51 UTC (permalink / raw)
  To: Yi-De Wu
  Cc: Yingshiuan Pan, Ze-Yu Wang, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Catalin Marinas, Will Deacon, Arnd Bergmann,
	Matthias Brugger, AngeloGioacchino Del Regno, devicetree,
	linux-kernel, linux-doc, linux-arm-kernel, linux-arch,
	linux-mediatek, David Bradil, Trilok Soni, Jade Shih, Miles Chen,
	Ivan Tseng, My Chuang, Shawn Hsiao, PeiLun Suei, Liju Chen

Hi!

> GenieZone is MediaTek proprietary hypervisor solution, and it is running
> in EL2 stand alone as a type-I hypervisor. It is a pure EL2
> implementation which implies it does not rely any specific host VM, and
> this behavior improves GenieZone's security as it limits its interface.

> +++ b/Documentation/virt/geniezone/introduction.rst
> @@ -0,0 +1,34 @@

> +Platform Virtualization
> +=======================
> +We leverages arm64's timer virtualization and gic virtualization for timer and
> +interrupts controller.

'interrupt'.

> +Device Virtualizaton
> +====================
> +We adopts VMM's virtio devices emulations by passing io trap to
> VMM, and virtio

'adopt', 'device emulation'

> +is a well-known and widely used virtual device implementation.
> +

Plus, I'd expect documentation to be more detailed or have pointer
where
to learn more.

BR,							Pavel

-- 

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 0/7] GenieZone hypervisor drivers
  2023-04-28 12:25   ` Krzysztof Kozlowski
@ 2023-05-16  7:53     ` Yi-De Wu (吳一德)
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-16  7:53 UTC (permalink / raw)
  To: corbet, robh+dt, angelogioacchino.delregno, krzysztof.kozlowski,
	catalin.marinas, Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd,
	Ze-yu Wang (王澤宇),
	will
  Cc: linux-kernel, linux-mediatek, quic_tsoni,
	MY Chuang (莊明躍),
	Yipei Chang (張伊佩),
	devicetree, PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	dbrazdil, linux-arm-kernel,
	Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	linux-arch, linux-doc, Ivan Tseng (曾志軒)

On Fri, 2023-04-28 at 14:25 +0200, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 28/04/2023 12:36, Yi-De Wu wrote:
> > This series is based on linux-next, tag: next-20230427.
> > 
> > Changes in v2:
> > - Refactor: move to drivers/virt/geniezone
> > - Refactor: decouple arch-dependent and arch-independent
> > - Check pending signal before entering guest context
> > - Fix reviewer's comments
> > 
> 
> Please explain what is Geniezone, where we can find it, what's the
> plan
> for open-sourcing it etc.
> 
> That's what cover letter is for.
> 
> Best regards,
> Krzysztof
> 
The introdution of GenieZone in cover letter in v1 was missing in v2.
We've brought it back in v3, and would keep it updated in the future.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 0/7] GenieZone hypervisor drivers
@ 2023-05-16  7:53     ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-16  7:53 UTC (permalink / raw)
  To: corbet, robh+dt, angelogioacchino.delregno, krzysztof.kozlowski,
	catalin.marinas, Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd,
	Ze-yu Wang (王澤宇),
	will
  Cc: linux-kernel, linux-mediatek, quic_tsoni,
	MY Chuang (莊明躍),
	Yipei Chang (張伊佩),
	devicetree, PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	dbrazdil, linux-arm-kernel,
	Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	linux-arch, linux-doc, Ivan Tseng (曾志軒)

On Fri, 2023-04-28 at 14:25 +0200, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 28/04/2023 12:36, Yi-De Wu wrote:
> > This series is based on linux-next, tag: next-20230427.
> > 
> > Changes in v2:
> > - Refactor: move to drivers/virt/geniezone
> > - Refactor: decouple arch-dependent and arch-independent
> > - Check pending signal before entering guest context
> > - Fix reviewer's comments
> > 
> 
> Please explain what is Geniezone, where we can find it, what's the
> plan
> for open-sourcing it etc.
> 
> That's what cover letter is for.
> 
> Best regards,
> Krzysztof
> 
The introdution of GenieZone in cover letter in v1 was missing in v2.
We've brought it back in v3, and would keep it updated in the future.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 0/7] GenieZone hypervisor drivers
  2023-04-28 12:26   ` Krzysztof Kozlowski
@ 2023-05-22  3:18     ` Yi-De Wu (吳一德)
  -1 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  3:18 UTC (permalink / raw)
  To: corbet, robh+dt, angelogioacchino.delregno, krzysztof.kozlowski,
	catalin.marinas, Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd,
	Ze-yu Wang (王澤宇),
	will
  Cc: linux-kernel, linux-mediatek, quic_tsoni,
	MY Chuang (莊明躍),
	devicetree, PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	dbrazdil, yipei.chang, linux-arm-kernel,
	Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	linux-arch, linux-doc, Ivan Tseng (曾志軒)

On Fri, 2023-04-28 at 14:26 +0200, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 28/04/2023 12:36, Yi-De Wu wrote:
> > This series is based on linux-next, tag: next-20230427.
> > 
> > Changes in v2:
> > - Refactor: move to drivers/virt/geniezone
> > - Refactor: decouple arch-dependent and arch-independent
> > - Check pending signal before entering guest context
> > - Fix reviewer's comments
> 
> You need to be specific about what you changed.
> 
> Best regards,
> Krzysztof
> 

Noted, we would specify more clearly on the code change in the
changelog.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 0/7] GenieZone hypervisor drivers
@ 2023-05-22  3:18     ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  3:18 UTC (permalink / raw)
  To: corbet, robh+dt, angelogioacchino.delregno, krzysztof.kozlowski,
	catalin.marinas, Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd,
	Ze-yu Wang (王澤宇),
	will
  Cc: linux-kernel, linux-mediatek, quic_tsoni,
	MY Chuang (莊明躍),
	devicetree, PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	dbrazdil, yipei.chang, linux-arm-kernel,
	Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	linux-arch, linux-doc, Ivan Tseng (曾志軒)

On Fri, 2023-04-28 at 14:26 +0200, Krzysztof Kozlowski wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 28/04/2023 12:36, Yi-De Wu wrote:
> > This series is based on linux-next, tag: next-20230427.
> > 
> > Changes in v2:
> > - Refactor: move to drivers/virt/geniezone
> > - Refactor: decouple arch-dependent and arch-independent
> > - Check pending signal before entering guest context
> > - Fix reviewer's comments
> 
> You need to be specific about what you changed.
> 
> Best regards,
> Krzysztof
> 

Noted, we would specify more clearly on the code change in the
changelog.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-05-12 11:01       ` Conor Dooley
@ 2023-05-22  3:28           ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  3:28 UTC (permalink / raw)
  To: conor.dooley
  Cc: corbet, linux-kernel, linux-mediatek,
	MY Chuang (莊明躍),
	quic_tsoni, krzysztof.kozlowski+dt, devicetree,
	Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	yipei.chang, PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, robh,
	Shawn Hsiao (蕭志祥),
	linux-arm-kernel, Miles Chen (陳民樺),
	matthias.bgg, Yingshiuan Pan (潘穎軒),
	linux-arch, arnd, angelogioacchino.delregno, linux-doc, will

On Fri, 2023-05-12 at 12:01 +0100, Conor Dooley wrote:
> On Fri, May 12, 2023 at 06:42:51AM +0000, Yi-De Wu (吳一德) wrote:
> > On Fri, 2023-04-28 at 16:24 -0500, Rob Herring wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On Fri, Apr 28, 2023 at 06:36:17PM +0800, Yi-De Wu wrote:
> > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > 
> > > > 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.
> > > 
> > > Why can't the driver just try and do virtual machine operations
> > > to
> > > see
> > > if the hypervisor is there? IOW, make your software interfaces
> > > discoverable. DT is for non-discoverable hardware.
> > > 
> > > Rob
> > 
> > Can do, our hypervisor is discoverable through invoking probing
> > hypercall, and we use the device tree to prevent unnecessary module
> > loading on all systems.
> 
> Please do not wait until immediately prior to submitting version N+1
> before replying to any of the comments on version N.
> This creates a confusing scenario, where some review comments may be
> missed due to parallel discussion.
> 
> Thanks,
> Conor.
> 
Noted, we would stop updating newer version until there's some
consensus to do so.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
@ 2023-05-22  3:28           ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  3:28 UTC (permalink / raw)
  To: conor.dooley
  Cc: corbet, linux-kernel, linux-mediatek,
	MY Chuang (莊明躍),
	quic_tsoni, krzysztof.kozlowski+dt, devicetree,
	Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	yipei.chang, PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, robh,
	Shawn Hsiao (蕭志祥),
	linux-arm-kernel, Miles Chen (陳民樺),
	matthias.bgg, Yingshiuan Pan (潘穎軒),
	linux-arch, arnd, angelogioacchino.delregno, linux-doc, will

On Fri, 2023-05-12 at 12:01 +0100, Conor Dooley wrote:
> On Fri, May 12, 2023 at 06:42:51AM +0000, Yi-De Wu (吳一德) wrote:
> > On Fri, 2023-04-28 at 16:24 -0500, Rob Herring wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On Fri, Apr 28, 2023 at 06:36:17PM +0800, Yi-De Wu wrote:
> > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > 
> > > > 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.
> > > 
> > > Why can't the driver just try and do virtual machine operations
> > > to
> > > see
> > > if the hypervisor is there? IOW, make your software interfaces
> > > discoverable. DT is for non-discoverable hardware.
> > > 
> > > Rob
> > 
> > Can do, our hypervisor is discoverable through invoking probing
> > hypercall, and we use the device tree to prevent unnecessary module
> > loading on all systems.
> 
> Please do not wait until immediately prior to submitting version N+1
> before replying to any of the comments on version N.
> This creates a confusing scenario, where some review comments may be
> missed due to parallel discussion.
> 
> Thanks,
> Conor.
> 
Noted, we would stop updating newer version until there's some
consensus to do so.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-05-12 16:34       ` Trilok Soni
@ 2023-05-22  3:45           ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  3:45 UTC (permalink / raw)
  To: robh, quic_tsoni
  Cc: corbet, linux-kernel, robh+dt,
	MY Chuang (莊明躍),
	linux-mediatek, linux-arch, devicetree, will,
	Ze-yu Wang (王澤宇),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, yipei.chang, linux-arm-kernel,
	Shawn Hsiao (蕭志祥),
	Yingshiuan Pan (潘穎軒),
	Miles Chen (陳民樺),
	krzysztof.kozlowski+dt, arnd, matthias.bgg,
	angelogioacchino.delregno, linux-doc,
	Ivan Tseng (曾志軒)

On Fri, 2023-05-12 at 09:34 -0700, Trilok Soni wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 5/11/2023 11:42 PM, Yi-De Wu (吳一德) wrote:
> > On Fri, 2023-04-28 at 09:52 -0500, Rob Herring wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On Fri, 28 Apr 2023 18:36:17 +0800, Yi-De Wu wrote:
> > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > 
> > > > 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.
> > > > 
> > > > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > > > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > > > ---
> > > >  .../hypervisor/mediatek,geniezone-hyp.yaml    | 31
> > > > +++++++++++++++++++
> > > >  MAINTAINERS                                   |  1 +
> > > >  2 files changed, 32 insertions(+)
> > > >  create mode 100644
> > > > Documentation/devicetree/bindings/hypervisor/mediatek,geniezone
> > > > -
> > > > hyp.yaml
> > > > 
> > > 
> > > My bot found errors running 'make DT_CHECKER_FLAGS=-m
> > > dt_binding_check'
> > > on your patch (DT_CHECKER_FLAGS is new in v5.13):
> > > 
> > > yamllint warnings/errors:
> > > 
> > > dtschema/dtc warnings/errors:
> > > ./Documentation/devicetree/bindings/hypervisor/mediatek,geniezone
> > > -
> > > hyp.yaml: $id: relative path/filename doesn't match actual path
> > > or
> > > filename
> > >         expected:
> > > 
https://urldefense.com/v3/__http://devicetree.org/schemas/hypervisor/mediatek,geniezone-hyp.yaml*__;Iw!!CTRNKA9wMg0ARbw!joIOXbICM7UGvy3XBEJvfzSKO7s61efB87_NX5cqpUqpu5ot5cuzw50A8-8ledZT9_7ifsB2sKzxSD0$
> > > 
> > > doc reference errors (make refcheckdocs):
> > > 
> > > See
> > > 
https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230428103622.18291-3-yi-de.wu@mediatek.com
> > > 
> > > The base for the series is generally the latest rc1. A different
> > > dependency
> > > should be noted in *this* patch.
> > > 
> > > If you already ran 'make dt_binding_check' and didn't see the
> > > above
> > > error(s), then make sure 'yamllint' is installed and dt-schema is
> > > up
> > > to
> > > date:
> > > 
> > > pip3 install dtschema --upgrade
> > > 
> > > Please check and re-submit after running the above command
> > > yourself.
> > > Note
> > > that DT_SCHEMA_FILES can be set to your schema file to speed up
> > > checking
> > > your schema. However, it must be unset to test all examples with
> > > your
> > > schema.
> > > 
> > 
> > Noted, we've run the yaml check and we are going to re-submit the
> > latest version in v3.
> > 
> > ************* MEDIATEK Confidentiality Notice ********************
> > The information contained in this e-mail message (including any
> > attachments) may be confidential, proprietary, privileged, or
> > otherwise
> > exempt from disclosure under applicable laws. It is intended to be
> > conveyed only to the designated recipient(s). Any use,
> > dissemination,
> > distribution, printing, retaining or copying of this e-mail
> > (including its
> > attachments) by unintended recipient(s) is strictly prohibited and
> > may
> > be unlawful. If you are not an intended recipient of this e-mail,
> > or believe
> > that you have received this e-mail in error, please notify the
> > sender
> > immediately (by replying to this e-mail), delete any and all copies
> > of
> > this e-mail (including any attachments) from your system, and do
> > not
> > disclose the content of this e-mail to any other person. Thank you!
> 
> Do you want us to reply w/ such a big confidentiality notice?
> 

My apology to this mistake, our mail server wasn't configured properly.
We've added all related mailing list to our disclaimer-free bypassing
list to prevent such issues from happening again.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
@ 2023-05-22  3:45           ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  3:45 UTC (permalink / raw)
  To: robh, quic_tsoni
  Cc: corbet, linux-kernel, robh+dt,
	MY Chuang (莊明躍),
	linux-mediatek, linux-arch, devicetree, will,
	Ze-yu Wang (王澤宇),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, yipei.chang, linux-arm-kernel,
	Shawn Hsiao (蕭志祥),
	Yingshiuan Pan (潘穎軒),
	Miles Chen (陳民樺),
	krzysztof.kozlowski+dt, arnd, matthias.bgg,
	angelogioacchino.delregno, linux-doc,
	Ivan Tseng (曾志軒)

On Fri, 2023-05-12 at 09:34 -0700, Trilok Soni wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On 5/11/2023 11:42 PM, Yi-De Wu (吳一德) wrote:
> > On Fri, 2023-04-28 at 09:52 -0500, Rob Herring wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On Fri, 28 Apr 2023 18:36:17 +0800, Yi-De Wu wrote:
> > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > 
> > > > 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.
> > > > 
> > > > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > > > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > > > ---
> > > >  .../hypervisor/mediatek,geniezone-hyp.yaml    | 31
> > > > +++++++++++++++++++
> > > >  MAINTAINERS                                   |  1 +
> > > >  2 files changed, 32 insertions(+)
> > > >  create mode 100644
> > > > Documentation/devicetree/bindings/hypervisor/mediatek,geniezone
> > > > -
> > > > hyp.yaml
> > > > 
> > > 
> > > My bot found errors running 'make DT_CHECKER_FLAGS=-m
> > > dt_binding_check'
> > > on your patch (DT_CHECKER_FLAGS is new in v5.13):
> > > 
> > > yamllint warnings/errors:
> > > 
> > > dtschema/dtc warnings/errors:
> > > ./Documentation/devicetree/bindings/hypervisor/mediatek,geniezone
> > > -
> > > hyp.yaml: $id: relative path/filename doesn't match actual path
> > > or
> > > filename
> > >         expected:
> > > 
https://urldefense.com/v3/__http://devicetree.org/schemas/hypervisor/mediatek,geniezone-hyp.yaml*__;Iw!!CTRNKA9wMg0ARbw!joIOXbICM7UGvy3XBEJvfzSKO7s61efB87_NX5cqpUqpu5ot5cuzw50A8-8ledZT9_7ifsB2sKzxSD0$
> > > 
> > > doc reference errors (make refcheckdocs):
> > > 
> > > See
> > > 
https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230428103622.18291-3-yi-de.wu@mediatek.com
> > > 
> > > The base for the series is generally the latest rc1. A different
> > > dependency
> > > should be noted in *this* patch.
> > > 
> > > If you already ran 'make dt_binding_check' and didn't see the
> > > above
> > > error(s), then make sure 'yamllint' is installed and dt-schema is
> > > up
> > > to
> > > date:
> > > 
> > > pip3 install dtschema --upgrade
> > > 
> > > Please check and re-submit after running the above command
> > > yourself.
> > > Note
> > > that DT_SCHEMA_FILES can be set to your schema file to speed up
> > > checking
> > > your schema. However, it must be unset to test all examples with
> > > your
> > > schema.
> > > 
> > 
> > Noted, we've run the yaml check and we are going to re-submit the
> > latest version in v3.
> > 
> > ************* MEDIATEK Confidentiality Notice ********************
> > The information contained in this e-mail message (including any
> > attachments) may be confidential, proprietary, privileged, or
> > otherwise
> > exempt from disclosure under applicable laws. It is intended to be
> > conveyed only to the designated recipient(s). Any use,
> > dissemination,
> > distribution, printing, retaining or copying of this e-mail
> > (including its
> > attachments) by unintended recipient(s) is strictly prohibited and
> > may
> > be unlawful. If you are not an intended recipient of this e-mail,
> > or believe
> > that you have received this e-mail in error, please notify the
> > sender
> > immediately (by replying to this e-mail), delete any and all copies
> > of
> > this e-mail (including any attachments) from your system, and do
> > not
> > disclose the content of this e-mail to any other person. Thank you!
> 
> Do you want us to reply w/ such a big confidentiality notice?
> 

My apology to this mistake, our mail server wasn't configured properly.
We've added all related mailing list to our disclaimer-free bypassing
list to prevent such issues from happening again.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
  2023-05-12  9:59       ` Marc Zyngier
@ 2023-05-22  4:29           ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  4:29 UTC (permalink / raw)
  To: maz
  Cc: corbet, linux-kernel, linux-mediatek, robh+dt,
	MY Chuang (莊明躍),
	quic_tsoni, krzysztof.kozlowski+dt, devicetree,
	Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, yipei.chang,
	Shawn Hsiao (蕭志祥),
	linux-arm-kernel, Miles Chen (陳民樺),
	matthias.bgg, Yingshiuan Pan (潘穎軒),
	linux-arch, arnd, angelogioacchino.delregno, linux-doc, will

On Fri, 2023-05-12 at 10:59 +0100, Marc Zyngier wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, 12 May 2023 08:17:58 +0100,
> "Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> > 
> > On Fri, 2023-04-28 at 23:12 +0100, Marc Zyngier wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On 2023-04-28 11:36, Yi-De Wu wrote:
> > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > 
> > > > +config MTK_GZVM
> > > > +     tristate "GenieZone Hypervisor driver for guest VM
> > > > operation"
> > > > +     depends on ARM64
> > > > +     depends on KVM
> > > 
> > > NAK.
> > > 
> > > Either this is KVM, and this code serves no purpose, or it is a
> > > standalone
> > > hypervisor, and it *cannot* have a dependency on KVM.
> > > 
> > > [...]
> > > 
> > 
> > In order to be self-contained and avoid dependency like with KVM,
> > may
> > we leverage KVM's symbol, macro e.g. VGIC_NR_SGIS,
> > VGIC_NR_PRIVATE_IRQS...etc, and copy or rename the related part to
> > */geniezone/?
> 
> Again, these are architected constants. You can have your own. You
> can
> already consider any use of a KVM structure or symbol as a bug.
> 
>         M.
> 
> --
> Without deviation from the norm, progress is not possible.

Noted, we've received clear messages and agreed the current usage on
KVM's data structure and function prototype should be treated as bugs.
We would provide our own implementation on v4 to solve this issue.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support
@ 2023-05-22  4:29           ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  4:29 UTC (permalink / raw)
  To: maz
  Cc: corbet, linux-kernel, linux-mediatek, robh+dt,
	MY Chuang (莊明躍),
	quic_tsoni, krzysztof.kozlowski+dt, devicetree,
	Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, yipei.chang,
	Shawn Hsiao (蕭志祥),
	linux-arm-kernel, Miles Chen (陳民樺),
	matthias.bgg, Yingshiuan Pan (潘穎軒),
	linux-arch, arnd, angelogioacchino.delregno, linux-doc, will

On Fri, 2023-05-12 at 10:59 +0100, Marc Zyngier wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, 12 May 2023 08:17:58 +0100,
> "Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> > 
> > On Fri, 2023-04-28 at 23:12 +0100, Marc Zyngier wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On 2023-04-28 11:36, Yi-De Wu wrote:
> > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > 
> > > > +config MTK_GZVM
> > > > +     tristate "GenieZone Hypervisor driver for guest VM
> > > > operation"
> > > > +     depends on ARM64
> > > > +     depends on KVM
> > > 
> > > NAK.
> > > 
> > > Either this is KVM, and this code serves no purpose, or it is a
> > > standalone
> > > hypervisor, and it *cannot* have a dependency on KVM.
> > > 
> > > [...]
> > > 
> > 
> > In order to be self-contained and avoid dependency like with KVM,
> > may
> > we leverage KVM's symbol, macro e.g. VGIC_NR_SGIS,
> > VGIC_NR_PRIVATE_IRQS...etc, and copy or rename the related part to
> > */geniezone/?
> 
> Again, these are architected constants. You can have your own. You
> can
> already consider any use of a KVM structure or symbol as a bug.
> 
>         M.
> 
> --
> Without deviation from the norm, progress is not possible.

Noted, we've received clear messages and agreed the current usage on
KVM's data structure and function prototype should be treated as bugs.
We would provide our own implementation on v4 to solve this issue.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
  2023-05-12  9:57           ` Marc Zyngier
@ 2023-05-22  4:32               ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  4:32 UTC (permalink / raw)
  To: maz
  Cc: corbet, linux-kernel, linux-mediatek, quic_tsoni,
	MY Chuang (莊明躍),
	robh+dt, Yingshiuan Pan (潘穎軒),
	devicetree, linux-doc, angelogioacchino.delregno,
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, yipei.chang,
	Shawn Hsiao (蕭志祥),
	krzysztof.kozlowski+dt, Miles Chen (陳民樺),
	linux-arm-kernel, matthias.bgg, linux-arch,
	Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	arnd, will

On Fri, 2023-05-12 at 10:57 +0100, Marc Zyngier wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, 12 May 2023 09:16:58 +0100,
> "Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> > 
> > On Fri, 2023-05-12 at 08:51 +0100, Marc Zyngier wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On Fri, 12 May 2023 08:19:31 +0100,
> > > "Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> > > > 
> > > > On Fri, 2023-04-28 at 19:59 +0100, Marc Zyngier wrote:
> > > > > External email : Please do not click links or open
> > > > > attachments
> > > > > until
> > > > > you have verified the sender or the content.
> > > > > 
> > > > > 
> > > > > On 2023-04-28 11:36, Yi-De Wu wrote:
> > > > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > > > 
> > > > > > Enable GenieZone to handle virtual interrupt injection
> > > > > > request.
> > > > > > 
> > > > > > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > > > > > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > > > > > ---
> > > > > >  arch/arm64/geniezone/Makefile       |  2 +-
> > > > > >  arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
> > > > > >  arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
> > > > > >  arch/arm64/geniezone/gzvm_irqchip.c | 88
> > > > > > +++++++++++++++++++++++++++++
> > > > > >  drivers/virt/geniezone/gzvm_vm.c    | 75
> > > > > > ++++++++++++++++++++++++
> > > > > >  include/linux/gzvm_drv.h            |  4 ++
> > > > > >  include/uapi/linux/gzvm.h           | 38 ++++++++++++-
> > > > > >  7 files changed, 235 insertions(+), 7 deletions(-)
> > > > > >  create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c
> > > > > 
> > > > > [...]
> > > > > 
> > > > > > +++ b/arch/arm64/geniezone/gzvm_irqchip.c
> > > > > > @@ -0,0 +1,88 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > +/*
> > > > > > + * Copyright (c) 2023 MediaTek Inc.
> > > > > > + */
> > > > > > +
> > > > > > +#include <linux/irqchip/arm-gic-v3.h>
> > > > > > +#include <kvm/arm_vgic.h>
> > > > > 
> > > > > NAK.
> > > > > 
> > > > > There is no way you can rely on anything from KVM in
> > > > > your own hypervisor code.
> > > > > 
> > > > 
> > > > Same with previous discussion, we'd like to copy or rename the
> > > > related
> > > > part from KVM and keep the maintainance at our own if it's ok.
> > > 
> > > Why do you need *ANY* of the KVM stuff? Please fully enumerate
> > > these
> > > dependencies and why you have them.
> > > 
> > > Directly using KVM stuff for something completely unrelated is
> > > not
> > > OK,
> > > and will never be.
> > > 
> > >         M.
> > > 
> > > --
> > > Without deviation from the norm, progress is not possible.
> > 
> > The particular part we'd like to leverage from KVM are as followed
> > 1. `gfn_to_pfn_memslot` to convert guest physical address(or
> > intermediate physical address) to physical address
> 
> What is a memslot in your hypervisor? How does it relate to KVM's?
> What about the use of struct kvm?
> 
> I'm sorry, but your use of *internal* structures and API would make
> it
> impossible for us to make any further change without potentially
> affecting your hypervisor. Which is closed source and untestable.
> 
> To sum it up, I'm strongly opposed to any use of these data
> structures.  If you can spot some commonalities, expose them as a
> 0-cost abstraction. But don't use them as is your code.
> 
> > 2. get ARM's number of interrupt of different types e.g. number of
> > SGI,
> > number of PPI...etc
> 
> These are architectural constants, and you can define your own. That
> will cost you nothing but a handful of #define, and keep the two
> subsystem independent.
> 
>         M.
> 
> --
> Without deviation from the norm, progress is not possible.

As per discussion, we would define our own constants here and keep the
subsystem indepedent.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection
@ 2023-05-22  4:32               ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  4:32 UTC (permalink / raw)
  To: maz
  Cc: corbet, linux-kernel, linux-mediatek, quic_tsoni,
	MY Chuang (莊明躍),
	robh+dt, Yingshiuan Pan (潘穎軒),
	devicetree, linux-doc, angelogioacchino.delregno,
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, yipei.chang,
	Shawn Hsiao (蕭志祥),
	krzysztof.kozlowski+dt, Miles Chen (陳民樺),
	linux-arm-kernel, matthias.bgg, linux-arch,
	Ivan Tseng (曾志軒),
	Ze-yu Wang (王澤宇),
	arnd, will

On Fri, 2023-05-12 at 10:57 +0100, Marc Zyngier wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, 12 May 2023 09:16:58 +0100,
> "Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> > 
> > On Fri, 2023-05-12 at 08:51 +0100, Marc Zyngier wrote:
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > 
> > > 
> > > On Fri, 12 May 2023 08:19:31 +0100,
> > > "Yi-De Wu (吳一德)" <Yi-De.Wu@mediatek.com> wrote:
> > > > 
> > > > On Fri, 2023-04-28 at 19:59 +0100, Marc Zyngier wrote:
> > > > > External email : Please do not click links or open
> > > > > attachments
> > > > > until
> > > > > you have verified the sender or the content.
> > > > > 
> > > > > 
> > > > > On 2023-04-28 11:36, Yi-De Wu wrote:
> > > > > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > > > > 
> > > > > > Enable GenieZone to handle virtual interrupt injection
> > > > > > request.
> > > > > > 
> > > > > > Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
> > > > > > Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
> > > > > > ---
> > > > > >  arch/arm64/geniezone/Makefile       |  2 +-
> > > > > >  arch/arm64/geniezone/gzvm_arch.c    | 24 ++++++--
> > > > > >  arch/arm64/geniezone/gzvm_arch.h    | 11 ++++
> > > > > >  arch/arm64/geniezone/gzvm_irqchip.c | 88
> > > > > > +++++++++++++++++++++++++++++
> > > > > >  drivers/virt/geniezone/gzvm_vm.c    | 75
> > > > > > ++++++++++++++++++++++++
> > > > > >  include/linux/gzvm_drv.h            |  4 ++
> > > > > >  include/uapi/linux/gzvm.h           | 38 ++++++++++++-
> > > > > >  7 files changed, 235 insertions(+), 7 deletions(-)
> > > > > >  create mode 100644 arch/arm64/geniezone/gzvm_irqchip.c
> > > > > 
> > > > > [...]
> > > > > 
> > > > > > +++ b/arch/arm64/geniezone/gzvm_irqchip.c
> > > > > > @@ -0,0 +1,88 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > +/*
> > > > > > + * Copyright (c) 2023 MediaTek Inc.
> > > > > > + */
> > > > > > +
> > > > > > +#include <linux/irqchip/arm-gic-v3.h>
> > > > > > +#include <kvm/arm_vgic.h>
> > > > > 
> > > > > NAK.
> > > > > 
> > > > > There is no way you can rely on anything from KVM in
> > > > > your own hypervisor code.
> > > > > 
> > > > 
> > > > Same with previous discussion, we'd like to copy or rename the
> > > > related
> > > > part from KVM and keep the maintainance at our own if it's ok.
> > > 
> > > Why do you need *ANY* of the KVM stuff? Please fully enumerate
> > > these
> > > dependencies and why you have them.
> > > 
> > > Directly using KVM stuff for something completely unrelated is
> > > not
> > > OK,
> > > and will never be.
> > > 
> > >         M.
> > > 
> > > --
> > > Without deviation from the norm, progress is not possible.
> > 
> > The particular part we'd like to leverage from KVM are as followed
> > 1. `gfn_to_pfn_memslot` to convert guest physical address(or
> > intermediate physical address) to physical address
> 
> What is a memslot in your hypervisor? How does it relate to KVM's?
> What about the use of struct kvm?
> 
> I'm sorry, but your use of *internal* structures and API would make
> it
> impossible for us to make any further change without potentially
> affecting your hypervisor. Which is closed source and untestable.
> 
> To sum it up, I'm strongly opposed to any use of these data
> structures.  If you can spot some commonalities, expose them as a
> 0-cost abstraction. But don't use them as is your code.
> 
> > 2. get ARM's number of interrupt of different types e.g. number of
> > SGI,
> > number of PPI...etc
> 
> These are architectural constants, and you can define your own. That
> will cost you nothing but a handful of #define, and keep the two
> subsystem independent.
> 
>         M.
> 
> --
> Without deviation from the norm, progress is not possible.

As per discussion, we would define our own constants here and keep the
subsystem indepedent.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 1/7] docs: geniezone: Introduce GenieZone hypervisor
  2023-05-12 16:51   ` Pavel Machek
@ 2023-05-22  5:45       ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  5:45 UTC (permalink / raw)
  To: pavel
  Cc: corbet, linux-kernel, robh+dt, angelogioacchino.delregno,
	linux-mediatek, linux-arch, MY Chuang (莊明躍),
	devicetree, quic_tsoni, Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, yipei.chang, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

On Fri, 2023-05-12 at 18:51 +0200, Pavel Machek wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Hi!
> 
> > GenieZone is MediaTek proprietary hypervisor solution, and it is
> > running
> > in EL2 stand alone as a type-I hypervisor. It is a pure EL2
> > implementation which implies it does not rely any specific host VM,
> > and
> > this behavior improves GenieZone's security as it limits its
> > interface.
> > +++ b/Documentation/virt/geniezone/introduction.rst
> > @@ -0,0 +1,34 @@
> > +Platform Virtualization
> > +=======================
> > +We leverages arm64's timer virtualization and gic virtualization
> > for timer and
> > +interrupts controller.
> 
> 'interrupt'.
> 
Noted.

> > +Device Virtualizaton
> > +====================
> > +We adopts VMM's virtio devices emulations by passing io trap to
> > VMM, and virtio
> 
> 'adopt', 'device emulation'
> 
Noted.

> > +is a well-known and widely used virtual device implementation.
> > +
> 
> Plus, I'd expect documentation to be more detailed or have pointer
> where
> to learn more.
> 
> BR,                                                     Pavel
> 
> --
Sure, we tend to enumerate the high-level features of GenieZone and the
design considerations of each module on the next version of our
documentation.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 1/7] docs: geniezone: Introduce GenieZone hypervisor
@ 2023-05-22  5:45       ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-05-22  5:45 UTC (permalink / raw)
  To: pavel
  Cc: corbet, linux-kernel, robh+dt, angelogioacchino.delregno,
	linux-mediatek, linux-arch, MY Chuang (莊明躍),
	devicetree, quic_tsoni, Shawn Hsiao (蕭志祥),
	Miles Chen (陳民樺),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	yi-de.wu, Jades Shih (施向玨),
	catalin.marinas, dbrazdil, yipei.chang, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

On Fri, 2023-05-12 at 18:51 +0200, Pavel Machek wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Hi!
> 
> > GenieZone is MediaTek proprietary hypervisor solution, and it is
> > running
> > in EL2 stand alone as a type-I hypervisor. It is a pure EL2
> > implementation which implies it does not rely any specific host VM,
> > and
> > this behavior improves GenieZone's security as it limits its
> > interface.
> > +++ b/Documentation/virt/geniezone/introduction.rst
> > @@ -0,0 +1,34 @@
> > +Platform Virtualization
> > +=======================
> > +We leverages arm64's timer virtualization and gic virtualization
> > for timer and
> > +interrupts controller.
> 
> 'interrupt'.
> 
Noted.

> > +Device Virtualizaton
> > +====================
> > +We adopts VMM's virtio devices emulations by passing io trap to
> > VMM, and virtio
> 
> 'adopt', 'device emulation'
> 
Noted.

> > +is a well-known and widely used virtual device implementation.
> > +
> 
> Plus, I'd expect documentation to be more detailed or have pointer
> where
> to learn more.
> 
> BR,                                                     Pavel
> 
> --
Sure, we tend to enumerate the high-level features of GenieZone and the
design considerations of each module on the next version of our
documentation.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
  2023-05-12  6:42     ` Yi-De Wu (吳一德)
@ 2023-06-26  9:05         ` Yi-De Wu (吳一德)
  2023-06-26  9:05         ` Yi-De Wu (吳一德)
  1 sibling, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-06-26  9:05 UTC (permalink / raw)
  To: robh
  Cc: corbet, linux-kernel, linux-mediatek, angelogioacchino.delregno,
	MY Chuang (莊明躍),
	linux-arch, devicetree, quic_tsoni,
	Shawn Hsiao (蕭志祥),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

On Fri, 2023-05-12 at 14:42 +0800, Yi-De Wu wrote:
> On Fri, 2023-04-28 at 16:24 -0500, Rob Herring wrote:
> > External email : Please do not click links or open attachments
> > until
> > you have verified the sender or the content.
> > 
> > 
> > On Fri, Apr 28, 2023 at 06:36:17PM +0800, Yi-De Wu wrote:
> > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > 
> > > 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.
> > 
> > Why can't the driver just try and do virtual machine operations to
> > see
> > if the hypervisor is there? IOW, make your software interfaces
> > discoverable. DT is for non-discoverable hardware.
> > 
> > Rob
> 
> Can do, our hypervisor is discoverable through invoking probing
> hypercall, and we use the device tree to prevent unnecessary module
> loading on all systems.

hi Rob,

We'd like to continue with the argument whether to use dt here. As per
our previous discussion, we knew that dt is for non-discoverable
hardware. However, probing on all devices could possibly raise the
worries about polluting other users with redundant system overhead in
our v4 patches[1].

Are there any concerns from your side if we were to take the dt back in
v5 patches and keep it as simple as possible just to initialize our
hypervisor exclusively? Something similar to what we proposed
before[2].

Reference:
[1] 
https://lore.kernel.org/lkml/2fe0c7f9-55fc-ae63-3631-8526a0212ccd@linaro.org/
[2] 
https://android-review.googlesource.com/c/kernel/common/+/2447547/1..2/drivers/virt/geniezone/gzvm_main.c#b112

Regards,
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek GenieZone hypervisor
@ 2023-06-26  9:05         ` Yi-De Wu (吳一德)
  0 siblings, 0 replies; 66+ messages in thread
From: Yi-De Wu (吳一德) @ 2023-06-26  9:05 UTC (permalink / raw)
  To: robh
  Cc: corbet, linux-kernel, linux-mediatek, angelogioacchino.delregno,
	MY Chuang (莊明躍),
	linux-arch, devicetree, quic_tsoni,
	Shawn Hsiao (蕭志祥),
	PeiLun Suei (隋培倫),
	Liju-clr Chen (陳麗如),
	Jades Shih (施向玨),
	catalin.marinas, dbrazdil, linux-arm-kernel,
	Yingshiuan Pan (潘穎軒),
	krzysztof.kozlowski+dt, matthias.bgg, arnd, linux-doc,
	Ze-yu Wang (王澤宇),
	will, Ivan Tseng (曾志軒)

On Fri, 2023-05-12 at 14:42 +0800, Yi-De Wu wrote:
> On Fri, 2023-04-28 at 16:24 -0500, Rob Herring wrote:
> > External email : Please do not click links or open attachments
> > until
> > you have verified the sender or the content.
> > 
> > 
> > On Fri, Apr 28, 2023 at 06:36:17PM +0800, Yi-De Wu wrote:
> > > From: "Yingshiuan Pan" <yingshiuan.pan@mediatek.com>
> > > 
> > > 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.
> > 
> > Why can't the driver just try and do virtual machine operations to
> > see
> > if the hypervisor is there? IOW, make your software interfaces
> > discoverable. DT is for non-discoverable hardware.
> > 
> > Rob
> 
> Can do, our hypervisor is discoverable through invoking probing
> hypercall, and we use the device tree to prevent unnecessary module
> loading on all systems.

hi Rob,

We'd like to continue with the argument whether to use dt here. As per
our previous discussion, we knew that dt is for non-discoverable
hardware. However, probing on all devices could possibly raise the
worries about polluting other users with redundant system overhead in
our v4 patches[1].

Are there any concerns from your side if we were to take the dt back in
v5 patches and keep it as simple as possible just to initialize our
hypervisor exclusively? Something similar to what we proposed
before[2].

Reference:
[1] 
https://lore.kernel.org/lkml/2fe0c7f9-55fc-ae63-3631-8526a0212ccd@linaro.org/
[2] 
https://android-review.googlesource.com/c/kernel/common/+/2447547/1..2/drivers/virt/geniezone/gzvm_main.c#b112

Regards,

^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2023-06-26  9:08 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-28 10:36 [PATCH v2 0/7] GenieZone hypervisor drivers Yi-De Wu
2023-04-28 10:36 ` Yi-De Wu
2023-04-28 10:36 ` [PATCH v2 1/7] docs: geniezone: Introduce GenieZone hypervisor Yi-De Wu
2023-04-28 10:36   ` Yi-De Wu
2023-05-12 16:51   ` Pavel Machek
2023-05-22  5:45     ` Yi-De Wu (吳一德)
2023-05-22  5:45       ` Yi-De Wu (吳一德)
2023-04-28 10:36 ` [PATCH v2 2/7] dt-bindings: hypervisor: Add MediaTek " Yi-De Wu
2023-04-28 10:36   ` Yi-De Wu
2023-04-28 14:52   ` Rob Herring
2023-04-28 14:52     ` Rob Herring
2023-05-12  6:42     ` Yi-De Wu (吳一德)
2023-05-12 16:34       ` Trilok Soni
2023-05-22  3:45         ` Yi-De Wu (吳一德)
2023-05-22  3:45           ` Yi-De Wu (吳一德)
2023-04-28 21:24   ` Rob Herring
2023-04-28 21:24     ` Rob Herring
2023-05-12  6:42     ` Yi-De Wu (吳一德)
2023-05-12 11:01       ` Conor Dooley
2023-05-22  3:28         ` Yi-De Wu (吳一德)
2023-05-22  3:28           ` Yi-De Wu (吳一德)
2023-06-26  9:05       ` Yi-De Wu (吳一德)
2023-06-26  9:05         ` Yi-De Wu (吳一德)
2023-04-28 10:36 ` [PATCH v2 3/7] virt: geniezone: Introduce GenieZone hypervisor support Yi-De Wu
2023-04-28 10:36   ` Yi-De Wu
2023-04-28 16:19   ` kernel test robot
2023-04-28 16:19     ` kernel test robot
2023-04-28 17:53   ` kernel test robot
2023-04-28 17:53     ` kernel test robot
2023-04-28 20:07   ` kernel test robot
2023-04-28 20:07     ` kernel test robot
2023-04-28 22:12   ` Marc Zyngier
2023-04-28 22:12     ` Marc Zyngier
2023-04-28 22:48     ` Trilok Soni
2023-04-28 22:48       ` Trilok Soni
2023-05-12  7:18       ` Yi-De Wu (吳一德)
2023-05-12  7:17     ` Yi-De Wu (吳一德)
2023-05-12  9:59       ` Marc Zyngier
2023-05-22  4:29         ` Yi-De Wu (吳一德)
2023-05-22  4:29           ` Yi-De Wu (吳一德)
2023-04-28 10:36 ` [PATCH v2 4/7] virt: geniezone: Add vcpu support Yi-De Wu
2023-04-28 10:36   ` Yi-De Wu
2023-04-29  6:34   ` kernel test robot
2023-04-29  6:34     ` kernel test robot
2023-04-28 10:36 ` [PATCH v2 5/7] virt: geniezone: Add irqchip support for virtual interrupt injection Yi-De Wu
2023-04-28 10:36   ` Yi-De Wu
2023-04-28 18:59   ` Marc Zyngier
2023-04-28 18:59     ` Marc Zyngier
2023-05-12  7:19     ` Yi-De Wu (吳一德)
2023-05-12  7:51       ` Marc Zyngier
2023-05-12  8:16         ` Yi-De Wu (吳一德)
2023-05-12  9:57           ` Marc Zyngier
2023-05-22  4:32             ` Yi-De Wu (吳一德)
2023-05-22  4:32               ` Yi-De Wu (吳一德)
2023-04-28 10:36 ` [PATCH v2 6/7] virt: geniezone: Add irqfd support Yi-De Wu
2023-04-28 10:36   ` Yi-De Wu
2023-04-28 10:36 ` [PATCH v2 7/7] virt: geniezone: Add ioeventfd support Yi-De Wu
2023-04-28 10:36   ` Yi-De Wu
2023-04-28 12:25 ` [PATCH v2 0/7] GenieZone hypervisor drivers Krzysztof Kozlowski
2023-04-28 12:25   ` Krzysztof Kozlowski
2023-05-16  7:53   ` Yi-De Wu (吳一德)
2023-05-16  7:53     ` Yi-De Wu (吳一德)
2023-04-28 12:26 ` Krzysztof Kozlowski
2023-04-28 12:26   ` Krzysztof Kozlowski
2023-05-22  3:18   ` Yi-De Wu (吳一德)
2023-05-22  3:18     ` Yi-De Wu (吳一德)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.