linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/21] Drivers for gunyah hypervisor
@ 2022-10-26 18:58 Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 01/21] docs: gunyah: Introduce Gunyah Hypervisor Elliot Berman
                   ` (20 more replies)
  0 siblings, 21 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Gunyah is a Type-1 hypervisor independent of any
high-level OS kernel, and runs in a higher CPU privilege level. It does
not depend on any lower-privileged OS kernel/code for its core
functionality. This increases its security and can support a much smaller
trusted computing base than a Type-2 hypervisor.

Gunyah is an open source hypervisor. The source repo is available at
https://github.com/quic/gunyah-hypervisor.

The diagram below shows the architecture.

::

         VM A                    VM B
     +-----+ +-----+  | +-----+ +-----+ +-----+
     |     | |     |  | |     | |     | |     |
 EL0 | APP | | APP |  | | APP | | APP | | APP |
     |     | |     |  | |     | |     | |     |
     +-----+ +-----+  | +-----+ +-----+ +-----+
 ---------------------|-------------------------
     +--------------+ | +----------------------+
     |              | | |                      |
 EL1 | Linux Kernel | | |Linux kernel/Other OS |   ...
     |              | | |                      |
     +--------------+ | +----------------------+
 --------hvc/smc------|------hvc/smc------------
     +----------------------------------------+
     |                                        |
 EL2 |            Gunyah Hypervisor           |
     |                                        |
     +----------------------------------------+

Gunyah provides these following features.

- Threads and Scheduling: The scheduler schedules virtual CPUs (VCPUs) on
physical CPUs and enables time-sharing of the CPUs.
- Memory Management: Gunyah tracks memory ownership and use of all memory
under its control. Memory partitioning between VMs is a fundamental
security feature.
- Interrupt Virtualization: All interrupts are handled in the hypervisor
and routed to the assigned VM.
- Inter-VM Communication: There are several different mechanisms provided
for communicating between VMs.
- Device Virtualization: Para-virtualization of devices is supported using
inter-VM communication. Low level system features and devices such as
interrupt controllers are supported with emulation where required.

This series adds the basic framework for detecting that Linux is running
under Gunyah as a virtual machine, communication with the Gunyah Resource
Manager, and a basic virtual machine manager capable of launching virtual
machines. In a future series, I'll add more functionality to the VM Manager,
but functionality is kept limited here to reduce the number of patches to
review.

Changes in v6:
 - *Replace gunyah-console with gunyah VM Manager*
 - Move include/asm-generic/gunyah.h into include/linux/gunyah.h
 - s/gunyah_msgq/gh_msgq/
 - Minor tweaks and documentation tidying based on comments from Jiri, Greg, Arnd, Dmitry, and Bagas.

Changes in v5: https://lore.kernel.org/all/20221011000840.289033-1-quic_eberman@quicinc.com/
 - Dropped sysfs nodes
 - Switch from aux bus to Gunyah RM bus for the subdevices
 - Cleaning up RM console

Changes in v4: https://lore.kernel.org/all/20220928195633.2348848-1-quic_eberman@quicinc.com/
 - Tidied up documentation throughout based on questions/feedback received
 - Switched message queue implementation to use mailboxes
 - Renamed "gunyah_device" as "gunyah_resource"

Changes in v3: https://lore.kernel.org/all/20220811214107.1074343-1-quic_eberman@quicinc.com/
 - /Maintained/Supported/ in MAINTAINERS
 - Tidied up documentation throughout based on questions/feedback received
 - Moved hypercalls into arch/arm64/gunyah/; following hyper-v's implementation
 - Drop opaque typedefs
 - Move sysfs nodes under /sys/hypervisor/gunyah/
 - Moved Gunyah console driver to drivers/tty/
 - Reworked gunyah_device design to drop the Gunyah bus.

Changes in v2: https://lore.kernel.org/all/20220801211240.597859-1-quic_eberman@quicinc.com/
 - DT bindings clean up
 - Switch hypercalls to follow SMCCC 

v1: https://lore.kernel.org/all/20220223233729.1571114-1-quic_eberman@quicinc.com/

Elliot Berman (21):
  docs: gunyah: Introduce Gunyah Hypervisor
  dt-bindings: Add binding for gunyah hypervisor
  gunyah: Common types and error codes for Gunyah hypercalls
  arm64: smccc: Include alternative-macros.h
  virt: gunyah: Add hypercalls to identify Gunyah
  virt: gunyah: Identify hypervisor version
  mailbox: Allow direct registration to a channel
  virt: gunyah: msgq: Add hypercalls to send and receive messages
  mailbox: Add Gunyah message queue mailbox
  gunyah: rsc_mgr: Add resource manager RPC core
  gunyah: rsc_mgr: Add subdevices bus
  gunyah: rsc_mgr: Add VM lifecycle RPC
  gunyah: vm_mgr: Introduce basic VM Manager
  gunyah: rsc_mgr: Add RPC for sharing memory
  gunyah: vm_mgr: Add/remove user memory regions
  gunyah: vm_mgr: Add ioctls to support basic non-proxy VM boot
  samples: Add sample userspace Gunyah VM Manager
  gunyah: rsc_mgr: Add platform ops on mem_lend/mem_reclaim
  firmware: qcom_scm: Use fixed width src vm bitmap
  firmware: qcom_scm: Register Gunyah platform ops
  docs: gunyah: Document Gunyah VM Manager

 .../bindings/firmware/gunyah-hypervisor.yaml  |  86 +++
 .../userspace-api/ioctl/ioctl-number.rst      |   1 +
 Documentation/virt/gunyah/index.rst           | 115 +++
 Documentation/virt/gunyah/message-queue.rst   |  63 ++
 Documentation/virt/gunyah/vm-manager.rst      |  94 +++
 Documentation/virt/index.rst                  |   1 +
 MAINTAINERS                                   |  13 +
 arch/arm64/Kbuild                             |   1 +
 arch/arm64/gunyah/Makefile                    |   1 +
 arch/arm64/gunyah/gunyah_hypercall.c          | 102 +++
 arch/arm64/include/uapi/asm/gunyah.h          |  17 +
 drivers/firmware/qcom_scm.c                   | 126 +++-
 drivers/mailbox/Kconfig                       |  10 +
 drivers/mailbox/Makefile                      |   2 +
 drivers/mailbox/gunyah-msgq.c                 | 225 ++++++
 drivers/mailbox/mailbox.c                     |  96 ++-
 drivers/misc/fastrpc.c                        |   6 +-
 drivers/net/wireless/ath/ath10k/qmi.c         |   4 +-
 drivers/remoteproc/qcom_q6v5_mss.c            |   8 +-
 drivers/soc/qcom/rmtfs_mem.c                  |   2 +-
 drivers/virt/Kconfig                          |   1 +
 drivers/virt/Makefile                         |   1 +
 drivers/virt/gunyah/Kconfig                   |  35 +
 drivers/virt/gunyah/Makefile                  |   7 +
 drivers/virt/gunyah/gunyah.c                  |  46 ++
 drivers/virt/gunyah/rsc_mgr.c                 | 690 ++++++++++++++++++
 drivers/virt/gunyah/rsc_mgr.h                 | 146 ++++
 drivers/virt/gunyah/rsc_mgr_bus.c             |  83 +++
 drivers/virt/gunyah/rsc_mgr_rpc.c             | 475 ++++++++++++
 drivers/virt/gunyah/vm_mgr.c                  | 288 ++++++++
 drivers/virt/gunyah/vm_mgr.h                  |  52 ++
 drivers/virt/gunyah/vm_mgr_mm.c               | 245 +++++++
 include/linux/arm-smccc.h                     |   1 +
 include/linux/gunyah.h                        | 167 +++++
 include/linux/gunyah_rsc_mgr.h                | 161 ++++
 include/linux/mailbox_client.h                |   1 +
 include/linux/mod_devicetable.h               |   8 +
 include/linux/qcom_scm.h                      |   2 +-
 include/uapi/linux/gunyah.h                   |  53 ++
 samples/Kconfig                               |  10 +
 samples/Makefile                              |   1 +
 samples/gunyah/.gitignore                     |   2 +
 samples/gunyah/Makefile                       |   6 +
 samples/gunyah/gunyah_vmm.c                   | 270 +++++++
 samples/gunyah/sample_vm.dts                  |  69 ++
 scripts/mod/devicetable-offsets.c             |   3 +
 scripts/mod/file2alias.c                      |  10 +
 47 files changed, 3763 insertions(+), 43 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
 create mode 100644 Documentation/virt/gunyah/index.rst
 create mode 100644 Documentation/virt/gunyah/message-queue.rst
 create mode 100644 Documentation/virt/gunyah/vm-manager.rst
 create mode 100644 arch/arm64/gunyah/Makefile
 create mode 100644 arch/arm64/gunyah/gunyah_hypercall.c
 create mode 100644 arch/arm64/include/uapi/asm/gunyah.h
 create mode 100644 drivers/mailbox/gunyah-msgq.c
 create mode 100644 drivers/virt/gunyah/Kconfig
 create mode 100644 drivers/virt/gunyah/Makefile
 create mode 100644 drivers/virt/gunyah/gunyah.c
 create mode 100644 drivers/virt/gunyah/rsc_mgr.c
 create mode 100644 drivers/virt/gunyah/rsc_mgr.h
 create mode 100644 drivers/virt/gunyah/rsc_mgr_bus.c
 create mode 100644 drivers/virt/gunyah/rsc_mgr_rpc.c
 create mode 100644 drivers/virt/gunyah/vm_mgr.c
 create mode 100644 drivers/virt/gunyah/vm_mgr.h
 create mode 100644 drivers/virt/gunyah/vm_mgr_mm.c
 create mode 100644 include/linux/gunyah.h
 create mode 100644 include/linux/gunyah_rsc_mgr.h
 create mode 100644 include/uapi/linux/gunyah.h
 create mode 100644 samples/gunyah/.gitignore
 create mode 100644 samples/gunyah/Makefile
 create mode 100644 samples/gunyah/gunyah_vmm.c
 create mode 100644 samples/gunyah/sample_vm.dts


base-commit: 247f34f7b80357943234f93f247a1ae6b6c3a740
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 01/21] docs: gunyah: Introduce Gunyah Hypervisor
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-11-02 12:35   ` Bagas Sanjaya
  2022-10-26 18:58 ` [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor Elliot Berman
                   ` (19 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Jonathan Corbet
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Will Deacon, Catalin Marinas, Arnd Bergmann,
	Greg Kroah-Hartman, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel

Gunyah is an open-source Type-1 hypervisor developed by Qualcomm. It
does not depend on any lower-privileged OS/kernel code for its core
functionality. This increases its security and can support a smaller
trusted computing based when compared to Type-2 hypervisors.

Add documentation describing the Gunyah hypervisor and the main
components of the Gunyah hypervisor which are of interest to Linux
virtualization development.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 Documentation/virt/gunyah/index.rst         | 114 ++++++++++++++++++++
 Documentation/virt/gunyah/message-queue.rst |  55 ++++++++++
 Documentation/virt/index.rst                |   1 +
 MAINTAINERS                                 |   7 ++
 4 files changed, 177 insertions(+)
 create mode 100644 Documentation/virt/gunyah/index.rst
 create mode 100644 Documentation/virt/gunyah/message-queue.rst

diff --git a/Documentation/virt/gunyah/index.rst b/Documentation/virt/gunyah/index.rst
new file mode 100644
index 000000000000..fbadbdd24da7
--- /dev/null
+++ b/Documentation/virt/gunyah/index.rst
@@ -0,0 +1,114 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================
+Gunyah Hypervisor
+=================
+
+.. toctree::
+   :maxdepth: 1
+
+   message-queue
+
+Gunyah is a Type-1 hypervisor which is independent of any OS kernel, and runs in
+a higher CPU privilege level. It does not depend on any lower-privileged operating system
+for its core functionality. This increases its security and can support a much smaller
+trusted computing base than a Type-2 hypervisor.
+
+Gunyah is an open source hypervisor. The source repo is available at
+https://github.com/quic/gunyah-hypervisor.
+
+Gunyah provides these following features.
+
+- Scheduling:
+
+  A scheduler for virtual CPUs (vCPUs) on physical CPUs and enables time-sharing
+  of the CPUs. Gunyah supports two models of scheduling:
+
+    1. "Behind the back" scheduling in which Gunyah hypervisor schedules vCPUS on its own.
+    2. "Proxy" scheduling in which a delegated VM can donate part of one of its vCPU slice
+       to another VM's vCPU via a hypercall.
+
+- Memory Management:
+
+  APIs handling memory, abstracted as objects, limiting direct use of physical
+  addresses. Memory ownership and usage tracking of all memory under its control.
+  Memory partitioning between VMs is a fundamental security feature.
+
+- Interrupt Virtualization:
+
+  Uses CPU hardware interrupt virtualization capabilities. Interrupts are handled
+  in the hypervisor and routed to the assigned VM.
+
+- Inter-VM Communication:
+
+  There are several different mechanisms provided for communicating between VMs.
+
+- Virtual platform:
+
+  Architectural devices such as interrupt controllers and CPU timers are directly provided
+  by the hypervisor as well as core virtual platform devices and system APIs such as ARM PSCI.
+
+- Device Virtualization:
+
+  Para-virtualization of devices is supported using inter-VM communication.
+
+Architectures supported
+=======================
+AArch64 with a GIC
+
+Resources and Capabilities
+==========================
+
+Some services or resources provided by the Gunyah hypervisor are described to a virtual machine by
+capability IDs. For instance, inter-VM communication is performed with doorbells and message queues.
+Gunyah allows access to manipulate that doorbell via the capability ID. These devices are described
+in Linux as a struct gunyah_resource.
+
+High level management of these resources is performed by the resource manager VM. RM informs a
+guest VM about resources it can access through either the device tree or via guest-initiated RPC.
+
+For each virtual machine, Gunyah maintains a table of resources which can be accessed by that VM.
+An entry in this table is called a "capability" and VMs can only access resources via this
+capability table. Hence, virtual Gunyah devices are referenced by a "capability IDs" and not a
+"resource IDs". A VM can have multiple capability IDs mapping to the same resource. If 2 VMs have
+access to the same resource, they may not be using the same capability ID to access that resource
+since the tables are independent per VM.
+
+Resource Manager
+================
+
+The resource manager (RM) is a privileged application VM supporting the Gunyah Hypervisor.
+It provides policy enforcement aspects of the virtualization system. The resource manager can
+be treated as an extension of the Hypervisor but is separated to its own partition to ensure
+that the hypervisor layer itself remains small and secure and to maintain a separation of policy
+and mechanism in the platform. On arm64, RM runs at NS-EL1 similar to other virtual machines.
+
+Communication with the resource manager from each guest VM happens with message-queue.rst. Details
+about the specific messages can be found in drivers/virt/gunyah/rsc_mgr.c
+
+::
+
+  +-------+   +--------+   +--------+
+  |  RM   |   |  VM_A  |   |  VM_B  |
+  +-.-.-.-+   +---.----+   +---.----+
+    | |           |            |
+  +-.-.-----------.------------.----+
+  | | \==========/             |    |
+  |  \========================/     |
+  |            Gunyah               |
+  +---------------------------------+
+
+The source for the resource manager is available at https://github.com/quic/gunyah-resource-manager.
+
+The resource manager provides the following features:
+
+- VM lifecycle management: allocating a VM, starting VMs, destruction of VMs
+- VM access control policy, including memory sharing and lending
+- Interrupt routing configuration
+- Forwarding of system-level events (e.g. VM shutdown) to owner VM
+
+When booting a virtual machine which uses a devicetree, resource manager overlays a
+/hypervisor node. This node can let Linux know it is running as a Gunyah guest VM,
+how to communicate with resource manager, and basic description and capabilities of
+this VM. See Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml for a description
+of this node.
diff --git a/Documentation/virt/gunyah/message-queue.rst b/Documentation/virt/gunyah/message-queue.rst
new file mode 100644
index 000000000000..c9f4d75e2291
--- /dev/null
+++ b/Documentation/virt/gunyah/message-queue.rst
@@ -0,0 +1,55 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Message Queues
+==============
+Message queue is a simple low-capacity IPC channel between two VMs. It is
+intended for sending small control and configuration messages. Each message
+queue object is unidirectional, so a full-duplex IPC channel requires a pair of
+objects.
+
+Messages can be up to 1024 bytes in length. Longer messages require a further
+protocol on top of the message queue messages themselves. For instance, communication
+with the resource manager adds a header field for sending longer messages via multiple
+message fragments.
+
+The diagram below shows how message queue works. A typical configuration involves
+2 message queues. Message queue 1 allows VM_A to send messages to VM_B. Message
+queue 2 allows VM_B to send messages to VM_A.
+
+1. VM_A sends a message of up to 1024 bytes in length. It raises a hypercall
+   with the message to inform the hypervisor to add the message to
+   message queue 1's queue.
+
+2. Gunyah raises the corresponding interrupt for VM_B when any of these happens:
+
+   a. gh_msgq_send has PUSH flag. Queue is immediately flushed. This is the typical case.
+   b. Explicility with gh_msgq_push command from VM_A.
+   c. Message queue has reached a threshold depth.
+
+3. VM_B calls gh_msgq_recv and Gunyah copies message to requested buffer.
+
+For VM_B to send a message to VM_A, the process is identical, except that hypercalls
+reference message queue 2's capability ID.
+
+::
+
+      +---------------+         +-----------------+         +---------------+
+      |      VM_A     |         |Gunyah hypervisor|         |      VM_B     |
+      |               |         |                 |         |               |
+      |               |         |                 |         |               |
+      |               |   Tx    |                 |         |               |
+      |               |-------->|                 | Rx vIRQ |               |
+      |gh_msgq_send() | Tx vIRQ |Message queue 1  |-------->|gh_msgq_recv() |
+      |               |<------- |                 |         |               |
+      |               |         |                 |         |               |
+      | Message Queue |         |                 |         | Message Queue |
+      | driver        |         |                 |         | driver        |
+      |               |         |                 |         |               |
+      |               |         |                 |         |               |
+      |               |         |                 |   Tx    |               |
+      |               | Rx vIRQ |                 |<--------|               |
+      |gh_msgq_recv() |<--------|Message queue 2  | Tx vIRQ |gh_msgq_send() |
+      |               |         |                 |-------->|               |
+      |               |         |                 |         |               |
+      |               |         |                 |         |               |
+      +---------------+         +-----------------+         +---------------+
diff --git a/Documentation/virt/index.rst b/Documentation/virt/index.rst
index 2f1cffa87b1b..418d540f5484 100644
--- a/Documentation/virt/index.rst
+++ b/Documentation/virt/index.rst
@@ -15,6 +15,7 @@ Linux Virtualization Support
    acrn/index
    coco/sev-guest
    hyperv/index
+   gunyah/index
 
 .. only:: html and subproject
 
diff --git a/MAINTAINERS b/MAINTAINERS
index e04d944005ba..9479cb3054cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8935,6 +8935,13 @@ L:	linux-efi@vger.kernel.org
 S:	Maintained
 F:	block/partitions/efi.*
 
+GUNYAH HYPERVISOR DRIVER
+M:	Elliot Berman <quic_eberman@quicinc.com>
+M:	Murali Nalajala <quic_mnalajal@quicinc.com>
+L:	linux-arm-msm@vger.kernel.org
+S:	Supported
+F:	Documentation/virt/gunyah/
+
 HABANALABS PCI DRIVER
 M:	Oded Gabbay <ogabbay@kernel.org>
 S:	Supported
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 01/21] docs: gunyah: Introduce Gunyah Hypervisor Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-27 19:57   ` Krzysztof Kozlowski
  2022-10-28  2:33   ` Jassi Brar
  2022-10-26 18:58 ` [PATCH v6 03/21] gunyah: Common types and error codes for Gunyah hypercalls Elliot Berman
                   ` (18 subsequent siblings)
  20 siblings, 2 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

When Linux is booted as a guest under the Gunyah hypervisor, the Gunyah
Resource Manager applies a devicetree overlay describing the virtual
platform configuration of the guest VM, such as the message queue
capability IDs for communicating with the Resource Manager. This
information is not otherwise discoverable by a VM: the Gunyah hypervisor
core does not provide a direct interface to discover capability IDs nor
a way to communicate with RM without having already known the
corresponding message queue capability ID. Add the DT bindings that
Gunyah adheres for the hypervisor node and message queues.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 .../bindings/firmware/gunyah-hypervisor.yaml  | 86 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 87 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml

diff --git a/Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml b/Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
new file mode 100644
index 000000000000..3a8c1c2157a4
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/firmware/gunyah-hypervisor.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Gunyah Hypervisor
+
+maintainers:
+  - Murali Nalajala <quic_mnalajal@quicinc.com>
+  - Elliot Berman <quic_eberman@quicinc.com>
+
+description: |+
+  Gunyah virtual machines use this information to determine the capability IDs
+  of the message queues used to communicate with the Gunyah Resource Manager.
+  See also: https://github.com/quic/gunyah-resource-manager/blob/develop/src/vm_creation/dto_construct.c
+
+properties:
+  compatible:
+    items:
+      - const: gunyah-hypervisor-1.0
+      - const: gunyah-hypervisor
+
+  "#address-cells":
+    description: Number of cells needed to represent 64-bit capability IDs.
+    const: 2
+
+  "#size-cells":
+    description: must be 0, because capability IDs are not memory address
+                  ranges and do not have a size.
+    const: 0
+
+patternProperties:
+  "^gunyah-resource-mgr(@.*)?":
+    type: object
+    description:
+      Resource Manager node which is required to communicate to Resource
+      Manager VM using Gunyah Message Queues.
+
+    properties:
+      compatible:
+        items:
+          - const: gunyah-resource-manager-1-0
+          - const: gunyah-resource-manager
+
+      reg:
+        items:
+          - description: Gunyah capability ID of the TX message queue
+          - description: Gunyah capability ID of the RX message queue
+
+      interrupts:
+        items:
+          - description: Interrupt for the TX message queue
+          - description: Interrupt for the RX message queue
+
+    additionalProperties: false
+
+    required:
+      - compatible
+      - reg
+      - interrupts
+
+additionalProperties: false
+
+required:
+  - compatible
+  - "#address-cells"
+  - "#size-cells"
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    hypervisor {
+        #address-cells = <2>;
+        #size-cells = <0>;
+        compatible = "gunyah-hypervisor-1.0", "gunyah-hypervisor";
+
+        gunyah-resource-mgr@0 {
+            compatible = "gunyah-resource-manager-1-0", "gunyah-resource-manager";
+            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX full IRQ */
+                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX empty IRQ */
+            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
+                  /* TX, RX cap ids */
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 9479cb3054cb..1de8d00dacb2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8940,6 +8940,7 @@ M:	Elliot Berman <quic_eberman@quicinc.com>
 M:	Murali Nalajala <quic_mnalajal@quicinc.com>
 L:	linux-arm-msm@vger.kernel.org
 S:	Supported
+F:	Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
 F:	Documentation/virt/gunyah/
 
 HABANALABS PCI DRIVER
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 03/21] gunyah: Common types and error codes for Gunyah hypercalls
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 01/21] docs: gunyah: Introduce Gunyah Hypervisor Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 19:47   ` Dmitry Baryshkov
  2022-10-26 18:58 ` [PATCH v6 04/21] arm64: smccc: Include alternative-macros.h Elliot Berman
                   ` (17 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Add architecture-independent standard error codes, types, and macros for
Gunyah hypercalls.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 MAINTAINERS            |  1 +
 include/linux/gunyah.h | 74 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)
 create mode 100644 include/linux/gunyah.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 1de8d00dacb2..5eec8618a087 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8942,6 +8942,7 @@ L:	linux-arm-msm@vger.kernel.org
 S:	Supported
 F:	Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
 F:	Documentation/virt/gunyah/
+F:	include/linux/gunyah.h
 
 HABANALABS PCI DRIVER
 M:	Oded Gabbay <ogabbay@kernel.org>
diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h
new file mode 100644
index 000000000000..824e20a11d27
--- /dev/null
+++ b/include/linux/gunyah.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _GUNYAH_H
+#define _GUNYAH_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+
+/* Common Gunyah macros */
+#define GH_CAPID_INVAL	U64_MAX
+#define GH_VMID_ROOT_VM	0xff
+
+#define GH_ERROR_OK			0
+
+#define GH_ERROR_UNIMPLEMENTED		-1
+#define GH_ERROR_RETRY			-2
+
+#define GH_ERROR_ARG_INVAL		1
+#define GH_ERROR_ARG_SIZE		2
+#define GH_ERROR_ARG_ALIGN		3
+
+#define GH_ERROR_NOMEM			10
+
+#define GH_ERROR_ADDR_OVFL		20
+#define GH_ERROR_ADDR_UNFL		21
+#define GH_ERROR_ADDR_INVAL		22
+
+#define GH_ERROR_DENIED			30
+#define GH_ERROR_BUSY			31
+#define GH_ERROR_IDLE			32
+
+#define GH_ERROR_IRQ_BOUND		40
+#define GH_ERROR_IRQ_UNBOUND		41
+
+#define GH_ERROR_CSPACE_CAP_NULL	50
+#define GH_ERROR_CSPACE_CAP_REVOKED	51
+#define GH_ERROR_CSPACE_WRONG_OBJ_TYPE	52
+#define GH_ERROR_CSPACE_INSUF_RIGHTS	53
+#define GH_ERROR_CSPACE_FULL		54
+
+#define GH_ERROR_MSGQUEUE_EMPTY		60
+#define GH_ERROR_MSGQUEUE_FULL		61
+
+static inline int gh_remap_error(int gh_error)
+{
+	switch (gh_error) {
+	case GH_ERROR_OK:
+		return 0;
+	case GH_ERROR_NOMEM:
+		return -ENOMEM;
+	case GH_ERROR_DENIED:
+	case GH_ERROR_CSPACE_CAP_NULL:
+	case GH_ERROR_CSPACE_CAP_REVOKED:
+	case GH_ERROR_CSPACE_WRONG_OBJ_TYPE:
+	case GH_ERROR_CSPACE_INSUF_RIGHTS:
+	case GH_ERROR_CSPACE_FULL:
+		return -EACCES;
+	case GH_ERROR_BUSY:
+	case GH_ERROR_IDLE:
+		return -EBUSY;
+	case GH_ERROR_IRQ_BOUND:
+	case GH_ERROR_IRQ_UNBOUND:
+	case GH_ERROR_MSGQUEUE_FULL:
+	case GH_ERROR_MSGQUEUE_EMPTY:
+		return -EPERM;
+	default:
+		return -EINVAL;
+	}
+}
+
+#endif
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 04/21] arm64: smccc: Include alternative-macros.h
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (2 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 03/21] gunyah: Common types and error codes for Gunyah hypercalls Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 19:46   ` Dmitry Baryshkov
  2022-10-26 18:58 ` [PATCH v6 05/21] virt: gunyah: Add hypercalls to identify Gunyah Elliot Berman
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Fix build error when CONFIG_ARM64_SVE is selected and
asm/alternative-macros.h wasn't implicitly included by another header.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 include/linux/arm-smccc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 220c8c60e021..6a627cdbbdec 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -383,6 +383,7 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 
 /* nVHE hypervisor doesn't have a current thread so needs separate checks */
 #if defined(CONFIG_ARM64_SVE) && !defined(__KVM_NVHE_HYPERVISOR__)
+#include <asm/alternative-macros.h>
 
 #define SMCCC_SVE_CHECK ALTERNATIVE("nop \n",  "bl __arm_smccc_sve_check \n", \
 				    ARM64_SVE)
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 05/21] virt: gunyah: Add hypercalls to identify Gunyah
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (3 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 04/21] arm64: smccc: Include alternative-macros.h Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 06/21] virt: gunyah: Identify hypervisor version Elliot Berman
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Add hypercalls to identify when Linux is running a virtual machine under
Gunyah.

There are two calls to help identify Gunyah:

1. gh_hypercall_get_uid() returns a UID when running under a Gunyah
   hypervisor.
2. gh_hypercall_hyp_identify() returns build information and a set of
   feature flags that are supported by Gunyah.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 MAINTAINERS                          |  2 +
 arch/arm64/Kbuild                    |  1 +
 arch/arm64/gunyah/Makefile           |  1 +
 arch/arm64/gunyah/gunyah_hypercall.c | 69 ++++++++++++++++++++++++++++
 drivers/virt/Kconfig                 |  1 +
 drivers/virt/gunyah/Kconfig          | 12 +++++
 include/linux/gunyah.h               | 25 ++++++++++
 7 files changed, 111 insertions(+)
 create mode 100644 arch/arm64/gunyah/Makefile
 create mode 100644 arch/arm64/gunyah/gunyah_hypercall.c
 create mode 100644 drivers/virt/gunyah/Kconfig

diff --git a/MAINTAINERS b/MAINTAINERS
index 5eec8618a087..211977dc344b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8942,6 +8942,8 @@ L:	linux-arm-msm@vger.kernel.org
 S:	Supported
 F:	Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
 F:	Documentation/virt/gunyah/
+F:	arch/arm64/gunyah/
+F:	drivers/virt/gunyah/
 F:	include/linux/gunyah.h
 
 HABANALABS PCI DRIVER
diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild
index 5bfbf7d79c99..e4847ba0e3c9 100644
--- a/arch/arm64/Kbuild
+++ b/arch/arm64/Kbuild
@@ -3,6 +3,7 @@ obj-y			+= kernel/ mm/ net/
 obj-$(CONFIG_KVM)	+= kvm/
 obj-$(CONFIG_XEN)	+= xen/
 obj-$(subst m,y,$(CONFIG_HYPERV))	+= hyperv/
+obj-$(CONFIG_GUNYAH)	+= gunyah/
 obj-$(CONFIG_CRYPTO)	+= crypto/
 
 # for cleaning
diff --git a/arch/arm64/gunyah/Makefile b/arch/arm64/gunyah/Makefile
new file mode 100644
index 000000000000..9fbc720b6fb6
--- /dev/null
+++ b/arch/arm64/gunyah/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_GUNYAH) += gunyah_hypercall.o
diff --git a/arch/arm64/gunyah/gunyah_hypercall.c b/arch/arm64/gunyah/gunyah_hypercall.c
new file mode 100644
index 000000000000..0beb3123d650
--- /dev/null
+++ b/arch/arm64/gunyah/gunyah_hypercall.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/module.h>
+#include <linux/gunyah.h>
+
+#define GH_CALL_TYPE_PLATFORM_CALL		0
+#define GH_CALL_TYPE_HYPERCALL			2
+#define GH_CALL_TYPE_SERVICE			3
+#define GH_CALL_TYPE_SHIFT			14
+#define GH_CALL_FUNCTION_NUM_MASK		0x3fff
+
+#define GH_FN_ID(type, num)	((type) << GH_CALL_TYPE_SHIFT | ((num) & GH_CALL_FUNCTION_NUM_MASK))
+
+#define GH_SERVICE(fn)		ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+						   ARM_SMCCC_OWNER_VENDOR_HYP, \
+						   GH_FN_ID(GH_CALL_TYPE_SERVICE, fn))
+
+#define GH_HYPERCALL_CALL_UID			GH_SERVICE(0x3f01)
+
+#define GH_HYPERCALL(fn)	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \
+						   ARM_SMCCC_OWNER_VENDOR_HYP, \
+						   GH_FN_ID(GH_CALL_TYPE_HYPERCALL, fn))
+
+#define GH_HYPERCALL_HYP_IDENTIFY		GH_HYPERCALL(0x0000)
+
+/**
+ * gh_hypercall_get_uid() - Returns a UID when running under a Gunyah hypervisor
+ * @uid: An array of 4 u32's (u32 uid[4];)
+ *
+ * Caller should compare the resulting UID to a list of known Gunyah UIDs to
+ * confirm that Linux is running as a guest of Gunyah.
+ */
+void gh_hypercall_get_uid(u32 uid[4])
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_hvc(GH_HYPERCALL_CALL_UID, &res);
+
+	uid[0] = res.a0;
+	uid[1] = res.a1;
+	uid[2] = res.a2;
+	uid[3] = res.a3;
+}
+EXPORT_SYMBOL_GPL(gh_hypercall_get_uid);
+
+/**
+ * gh_hypercall_hyp_identify() - Returns build information and feature flags
+ *                               supported by Gunyah.
+ * @hyp_identity: filled by the hypercall with the API info and feature flags.
+ */
+void gh_hypercall_hyp_identify(struct gh_hypercall_hyp_identify_resp *hyp_identity)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_hvc(GH_HYPERCALL_HYP_IDENTIFY, &res);
+
+	hyp_identity->api_info = res.a0;
+	hyp_identity->flags[0] = res.a1;
+	hyp_identity->flags[1] = res.a2;
+	hyp_identity->flags[2] = res.a3;
+}
+EXPORT_SYMBOL_GPL(gh_hypercall_hyp_identify);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Gunyah Hypervisor Hypercalls");
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
index 87ef258cec64..259dc2be6cad 100644
--- a/drivers/virt/Kconfig
+++ b/drivers/virt/Kconfig
@@ -52,4 +52,5 @@ source "drivers/virt/coco/efi_secret/Kconfig"
 
 source "drivers/virt/coco/sev-guest/Kconfig"
 
+source "drivers/virt/gunyah/Kconfig"
 endif
diff --git a/drivers/virt/gunyah/Kconfig b/drivers/virt/gunyah/Kconfig
new file mode 100644
index 000000000000..127156a678a6
--- /dev/null
+++ b/drivers/virt/gunyah/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config GUNYAH
+	tristate "Gunyah Virtualization drivers"
+	depends on ARM64
+	help
+	  The Gunyah drivers are the helper interfaces that runs in a guest VM
+	  such as basic inter-VM IPC and signaling mechanisms, and higher level
+	  services such as memory/device sharing, IRQ sharing, and so on.
+
+	  Say Y/M here to enable the drivers needed to interact in a Gunyah
+	  virtual environment.
diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h
index 824e20a11d27..2765d2b40198 100644
--- a/include/linux/gunyah.h
+++ b/include/linux/gunyah.h
@@ -6,6 +6,7 @@
 #ifndef _GUNYAH_H
 #define _GUNYAH_H
 
+#include <linux/bitfield.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 
@@ -71,4 +72,28 @@ static inline int gh_remap_error(int gh_error)
 	}
 }
 
+#define GUNYAH_API_V1			1
+
+#define GH_API_INFO_API_VERSION_MASK	GENMASK_ULL(13, 0)
+#define GH_API_INFO_BIG_ENDIAN		BIT_ULL(14)
+#define GH_API_INFO_IS_64BIT		BIT_ULL(15)
+#define GH_API_INFO_VARIANT_MASK	GENMASK_ULL(63, 56)
+
+#define GH_IDENTIFY_PARTITION_CSPACE		BIT_ULL(0)
+#define GH_IDENTIFY_DOORBELL			BIT_ULL(1)
+#define GH_IDENTIFY_MSGQUEUE			BIT_ULL(2)
+#define GH_IDENTIFY_VIC				BIT_ULL(3)
+#define GH_IDENTIFY_VPM				BIT_ULL(4)
+#define GH_IDENTIFY_VCPU			BIT_ULL(5)
+#define GH_IDENTIFY_MEMEXTENT			BIT_ULL(6)
+#define GH_IDENTIFY_TRACE_CTRL			BIT_ULL(7)
+
+struct gh_hypercall_hyp_identify_resp {
+	u64 api_info;
+	u64 flags[3];
+};
+
+void gh_hypercall_get_uid(u32 uid[4]);
+void gh_hypercall_hyp_identify(struct gh_hypercall_hyp_identify_resp *hyp_identity);
+
 #endif
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 06/21] virt: gunyah: Identify hypervisor version
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (4 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 05/21] virt: gunyah: Add hypercalls to identify Gunyah Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 07/21] mailbox: Allow direct registration to a channel Elliot Berman
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Export the version of Gunyah which is reported via the hyp_identify
hypercall. Increments of the major API version indicate possibly
backwards incompatible changes.

Export the hypervisor identity so that Gunyah drivers can act according
to the major API version.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/virt/Makefile        |  1 +
 drivers/virt/gunyah/Makefile |  1 +
 drivers/virt/gunyah/gunyah.c | 46 ++++++++++++++++++++++++++++++++++++
 include/linux/gunyah.h       |  6 +++++
 4 files changed, 54 insertions(+)
 create mode 100644 drivers/virt/gunyah/Makefile
 create mode 100644 drivers/virt/gunyah/gunyah.c

diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile
index 093674e05c40..10b87f934730 100644
--- a/drivers/virt/Makefile
+++ b/drivers/virt/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_NITRO_ENCLAVES)	+= nitro_enclaves/
 obj-$(CONFIG_ACRN_HSM)		+= acrn/
 obj-$(CONFIG_EFI_SECRET)	+= coco/efi_secret/
 obj-$(CONFIG_SEV_GUEST)		+= coco/sev-guest/
+obj-$(CONFIG_GUNYAH)		+= gunyah/
diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile
new file mode 100644
index 000000000000..2ac4ee64b89d
--- /dev/null
+++ b/drivers/virt/gunyah/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_GUNYAH) += gunyah.o
diff --git a/drivers/virt/gunyah/gunyah.c b/drivers/virt/gunyah/gunyah.c
new file mode 100644
index 000000000000..c34c9046fc08
--- /dev/null
+++ b/drivers/virt/gunyah/gunyah.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) "gunyah: " fmt
+
+#include <linux/gunyah.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+struct gh_hypercall_hyp_identify_resp gunyah_api;
+EXPORT_SYMBOL_GPL(gunyah_api);
+
+static const uint32_t gunyah_known_uuids[][4] = {
+	{0x19bd54bd, 0x0b37571b, 0x946f609b, 0x54539de6}, /* QC_HYP (Qualcomm's build) */
+	{0x673d5f14, 0x9265ce36, 0xa4535fdb, 0xc1d58fcd}, /* GUNYAH (open source build) */
+};
+
+static int __init gunyah_init(void)
+{
+	u32 uid[4];
+	int i;
+
+	gh_hypercall_get_uid(uid);
+
+	for (i = 0; i < ARRAY_SIZE(gunyah_known_uuids); i++)
+		if (!memcmp(uid, gunyah_known_uuids[i], sizeof(uid)))
+			break;
+
+	if (i == ARRAY_SIZE(gunyah_known_uuids))
+		return -ENODEV;
+
+	gh_hypercall_hyp_identify(&gunyah_api);
+
+	pr_info("Running under Gunyah hypervisor %llx/v%u\n",
+		FIELD_GET(GH_API_INFO_VARIANT_MASK, gunyah_api.api_info),
+		gh_api_version());
+
+	return 0;
+}
+arch_initcall(gunyah_init);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Gunyah Hypervisor Driver");
diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h
index 2765d2b40198..166156f69df9 100644
--- a/include/linux/gunyah.h
+++ b/include/linux/gunyah.h
@@ -92,6 +92,12 @@ struct gh_hypercall_hyp_identify_resp {
 	u64 api_info;
 	u64 flags[3];
 };
+extern struct gh_hypercall_hyp_identify_resp gunyah_api;
+
+static inline u16 gh_api_version(void)
+{
+	return FIELD_GET(GH_API_INFO_API_VERSION_MASK, gunyah_api.api_info);
+}
 
 void gh_hypercall_get_uid(u32 uid[4]);
 void gh_hypercall_hyp_identify(struct gh_hypercall_hyp_identify_resp *hyp_identity);
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 07/21] mailbox: Allow direct registration to a channel
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (5 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 06/21] virt: gunyah: Identify hypervisor version Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 08/21] virt: gunyah: msgq: Add hypercalls to send and receive messages Elliot Berman
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Jassi Brar
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Support virtual mailbox controllers and clients which are not platform
devices or come from the devicetree by allowing them to match client to
channel via some other mechanism.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/mailbox/mailbox.c      | 96 ++++++++++++++++++++++++----------
 include/linux/mailbox_client.h |  1 +
 2 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index 4229b9b5da98..adf36c05fa43 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -317,6 +317,71 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
 }
 EXPORT_SYMBOL_GPL(mbox_flush);
 
+static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
+{
+	struct device *dev = cl->dev;
+	unsigned long flags;
+	int ret;
+
+	if (chan->cl || !try_module_get(chan->mbox->dev->driver->owner)) {
+		dev_dbg(dev, "%s: mailbox not free\n", __func__);
+		return -EBUSY;
+	}
+
+	spin_lock_irqsave(&chan->lock, flags);
+	chan->msg_free = 0;
+	chan->msg_count = 0;
+	chan->active_req = NULL;
+	chan->cl = cl;
+	init_completion(&chan->tx_complete);
+
+	if (chan->txdone_method	== TXDONE_BY_POLL && cl->knows_txdone)
+		chan->txdone_method = TXDONE_BY_ACK;
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	if (chan->mbox->ops->startup) {
+		ret = chan->mbox->ops->startup(chan);
+
+		if (ret) {
+			dev_err(dev, "Unable to startup the chan (%d)\n", ret);
+			mbox_free_channel(chan);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * mbox_bind_client - Request a mailbox channel.
+ * @chan: The mailbox channel to bind the client to.
+ * @cl: Identity of the client requesting the channel.
+ *
+ * The Client specifies its requirements and capabilities while asking for
+ * a mailbox channel. It can't be called from atomic context.
+ * The channel is exclusively allocated and can't be used by another
+ * client before the owner calls mbox_free_channel.
+ * After assignment, any packet received on this channel will be
+ * handed over to the client via the 'rx_callback'.
+ * The framework holds reference to the client, so the mbox_client
+ * structure shouldn't be modified until the mbox_free_channel returns.
+ *
+ * Return: 0 if the channel was assigned to the client successfully.
+ *         <0 for request failure.
+ */
+int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
+{
+	int ret;
+
+	mutex_lock(&con_mutex);
+	ret = __mbox_bind_client(chan, cl);
+	mutex_unlock(&con_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mbox_bind_client);
+
 /**
  * mbox_request_channel - Request a mailbox channel.
  * @cl: Identity of the client requesting the channel.
@@ -340,7 +405,6 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
 	struct mbox_controller *mbox;
 	struct of_phandle_args spec;
 	struct mbox_chan *chan;
-	unsigned long flags;
 	int ret;
 
 	if (!dev || !dev->of_node) {
@@ -372,33 +436,9 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
 		return chan;
 	}
 
-	if (chan->cl || !try_module_get(mbox->dev->driver->owner)) {
-		dev_dbg(dev, "%s: mailbox not free\n", __func__);
-		mutex_unlock(&con_mutex);
-		return ERR_PTR(-EBUSY);
-	}
-
-	spin_lock_irqsave(&chan->lock, flags);
-	chan->msg_free = 0;
-	chan->msg_count = 0;
-	chan->active_req = NULL;
-	chan->cl = cl;
-	init_completion(&chan->tx_complete);
-
-	if (chan->txdone_method	== TXDONE_BY_POLL && cl->knows_txdone)
-		chan->txdone_method = TXDONE_BY_ACK;
-
-	spin_unlock_irqrestore(&chan->lock, flags);
-
-	if (chan->mbox->ops->startup) {
-		ret = chan->mbox->ops->startup(chan);
-
-		if (ret) {
-			dev_err(dev, "Unable to startup the chan (%d)\n", ret);
-			mbox_free_channel(chan);
-			chan = ERR_PTR(ret);
-		}
-	}
+	ret = __mbox_bind_client(chan, cl);
+	if (ret)
+		chan = ERR_PTR(ret);
 
 	mutex_unlock(&con_mutex);
 	return chan;
diff --git a/include/linux/mailbox_client.h b/include/linux/mailbox_client.h
index 65229a45590f..734694912ef7 100644
--- a/include/linux/mailbox_client.h
+++ b/include/linux/mailbox_client.h
@@ -37,6 +37,7 @@ struct mbox_client {
 	void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
 };
 
+int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl);
 struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
 					      const char *name);
 struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 08/21] virt: gunyah: msgq: Add hypercalls to send and receive messages
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (6 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 07/21] mailbox: Allow direct registration to a channel Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 09/21] mailbox: Add Gunyah message queue mailbox Elliot Berman
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Add hypercalls to send and receive messages on a Gunyah message queue.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 arch/arm64/gunyah/gunyah_hypercall.c | 33 ++++++++++++++++++++++++++++
 include/linux/gunyah.h               |  5 +++++
 2 files changed, 38 insertions(+)

diff --git a/arch/arm64/gunyah/gunyah_hypercall.c b/arch/arm64/gunyah/gunyah_hypercall.c
index 0beb3123d650..d28600909be4 100644
--- a/arch/arm64/gunyah/gunyah_hypercall.c
+++ b/arch/arm64/gunyah/gunyah_hypercall.c
@@ -26,6 +26,8 @@
 						   GH_FN_ID(GH_CALL_TYPE_HYPERCALL, fn))
 
 #define GH_HYPERCALL_HYP_IDENTIFY		GH_HYPERCALL(0x0000)
+#define GH_HYPERCALL_MSGQ_SEND			GH_HYPERCALL(0x001B)
+#define GH_HYPERCALL_MSGQ_RECV			GH_HYPERCALL(0x001C)
 
 /**
  * gh_hypercall_get_uid() - Returns a UID when running under a Gunyah hypervisor
@@ -65,5 +67,36 @@ void gh_hypercall_hyp_identify(struct gh_hypercall_hyp_identify_resp *hyp_identi
 }
 EXPORT_SYMBOL_GPL(gh_hypercall_hyp_identify);
 
+int gh_hypercall_msgq_send(u64 capid, size_t size, uintptr_t buff, int tx_flags, bool *ready)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_hvc(GH_HYPERCALL_MSGQ_SEND, capid, size, buff, tx_flags, 0, &res);
+
+	if (res.a0)
+		return res.a0;
+
+	*ready = res.a1;
+
+	return res.a0;
+}
+EXPORT_SYMBOL_GPL(gh_hypercall_msgq_send);
+
+int gh_hypercall_msgq_recv(u64 capid, uintptr_t buff, size_t size, size_t *recv_size, bool *ready)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_hvc(GH_HYPERCALL_MSGQ_RECV, capid, buff, size, 0, &res);
+
+	if (res.a0)
+		return res.a0;
+
+	*recv_size = res.a1;
+	*ready = res.a2;
+
+	return res.a0;
+}
+EXPORT_SYMBOL_GPL(gh_hypercall_msgq_recv);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Gunyah Hypervisor Hypercalls");
diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h
index 166156f69df9..c863cac4a3cf 100644
--- a/include/linux/gunyah.h
+++ b/include/linux/gunyah.h
@@ -102,4 +102,9 @@ static inline u16 gh_api_version(void)
 void gh_hypercall_get_uid(u32 uid[4]);
 void gh_hypercall_hyp_identify(struct gh_hypercall_hyp_identify_resp *hyp_identity);
 
+#define GH_HYPERCALL_MSGQ_TX_FLAGS_PUSH		BIT(0)
+
+int gh_hypercall_msgq_send(u64 capid, size_t size, uintptr_t buff, int tx_flags, bool *ready);
+int gh_hypercall_msgq_recv(u64 capid, uintptr_t buff, size_t size, size_t *recv_size, bool *ready);
+
 #endif
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 09/21] mailbox: Add Gunyah message queue mailbox
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (7 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 08/21] virt: gunyah: msgq: Add hypercalls to send and receive messages Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-27 13:55   ` Pavan Kondeti
  2022-10-26 18:58 ` [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core Elliot Berman
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Jassi Brar
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Gunyah message queues are a unidirectional inter-VM pipe for messages up
to 1024 bytes. This driver supports pairing a receiver message queue and
a transmitter message queue to expose a single mailbox channel.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 Documentation/virt/gunyah/message-queue.rst |   8 +
 MAINTAINERS                                 |   1 +
 drivers/mailbox/Kconfig                     |  10 +
 drivers/mailbox/Makefile                    |   2 +
 drivers/mailbox/gunyah-msgq.c               | 225 ++++++++++++++++++++
 include/linux/gunyah.h                      |  61 +++++-
 6 files changed, 305 insertions(+), 2 deletions(-)
 create mode 100644 drivers/mailbox/gunyah-msgq.c

diff --git a/Documentation/virt/gunyah/message-queue.rst b/Documentation/virt/gunyah/message-queue.rst
index c9f4d75e2291..7324fc616684 100644
--- a/Documentation/virt/gunyah/message-queue.rst
+++ b/Documentation/virt/gunyah/message-queue.rst
@@ -53,3 +53,11 @@ reference message queue 2's capability ID.
       |               |         |                 |         |               |
       |               |         |                 |         |               |
       +---------------+         +-----------------+         +---------------+
+
+Gunyah message queues are exposed as mailboxes. To create the mailbox, create
+a mbox_client and call `gh_msgq_init`. On receipt of the RX_READY interrupt,
+all messages in the RX message queue are read and pushed via the `rx_callback`
+of the registered mbox_client.
+
+.. kernel-doc:: drivers/mailbox/gunyah-msgq.c
+   :identifiers: gh_msgq_init
diff --git a/MAINTAINERS b/MAINTAINERS
index 211977dc344b..586539eadd3b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8943,6 +8943,7 @@ S:	Supported
 F:	Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
 F:	Documentation/virt/gunyah/
 F:	arch/arm64/gunyah/
+F:	drivers/mailbox/gunyah-msgq.c
 F:	drivers/virt/gunyah/
 F:	include/linux/gunyah.h
 
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 05d6fae800e3..baf9451c5f04 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -41,6 +41,16 @@ config IMX_MBOX
 	help
 	  Mailbox implementation for i.MX Messaging Unit (MU).
 
+config GUNYAH_MESSAGE_QUEUES
+	tristate "Gunyah Message Queue Mailbox"
+	depends on GUNYAH
+	help
+	  Mailbox implementation for Gunyah Message Queues. Gunyah message queues
+	  are an IPC mechanism to pass short messages between virtual machines
+	  running under the Gunyah hypervisor.
+
+	  Say Y here if you run Linux as a Gunyah virtual machine.
+
 config PLATFORM_MHU
 	tristate "Platform MHU Mailbox"
 	depends on OF
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index fc9376117111..5f929bb55e9a 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -55,6 +55,8 @@ obj-$(CONFIG_MTK_CMDQ_MBOX)	+= mtk-cmdq-mailbox.o
 
 obj-$(CONFIG_ZYNQMP_IPI_MBOX)	+= zynqmp-ipi-mailbox.o
 
+obj-$(CONFIG_GUNYAH)		+= gunyah-msgq.o
+
 obj-$(CONFIG_SUN6I_MSGBOX)	+= sun6i-msgbox.o
 
 obj-$(CONFIG_SPRD_MBOX)		+= sprd-mailbox.o
diff --git a/drivers/mailbox/gunyah-msgq.c b/drivers/mailbox/gunyah-msgq.c
new file mode 100644
index 000000000000..c4d2ede9334f
--- /dev/null
+++ b/drivers/mailbox/gunyah-msgq.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/gunyah.h>
+#include <linux/printk.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
+#define mbox_chan_to_msgq(chan) (container_of(chan->mbox, struct gh_msgq, mbox))
+
+static inline bool gh_msgq_has_tx(struct gh_msgq *msgq)
+{
+	return msgq->tx_ghrsc->type == GUNYAH_RESOURCE_TYPE_MSGQ_TX;
+}
+
+static inline bool gh_msgq_has_rx(struct gh_msgq *msgq)
+{
+	return msgq->rx_ghrsc->type == GUNYAH_RESOURCE_TYPE_MSGQ_RX;
+}
+
+static irqreturn_t gh_msgq_rx_irq_handler(int irq, void *data)
+{
+	struct gh_msgq *msgq = data;
+	struct gh_msgq_rx_data rx_data;
+	unsigned long gh_err;
+	ssize_t ret;
+	bool ready = false;
+
+	do {
+		gh_err = gh_hypercall_msgq_recv(msgq->rx_ghrsc->capid,
+				(uintptr_t)&rx_data.data, sizeof(rx_data.data),
+				&rx_data.length, &ready);
+		if (gh_err == GH_ERROR_OK) {
+			mbox_chan_received_data(gh_msgq_chan(msgq), &rx_data);
+		} else if (GH_ERROR_MSGQUEUE_EMPTY) {
+			break;
+		} else {
+			pr_warn("Failed to receive data from msgq for %s: %ld\n",
+				msgq->mbox.dev ? dev_name(msgq->mbox.dev) : "", ret);
+			break;
+		}
+	} while (ready);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t gh_msgq_tx_irq_handler(int irq, void *data)
+{
+	struct gh_msgq *msgq = data;
+
+	mbox_chan_txdone(gh_msgq_chan(msgq), 0);
+
+	return IRQ_HANDLED;
+}
+
+static void gh_msgq_txdone_tasklet(unsigned long data)
+{
+	struct gh_msgq *msgq = (struct gh_msgq *)data;
+
+	mbox_chan_txdone(gh_msgq_chan(msgq), msgq->last_status);
+}
+
+static int gh_msgq_send_data(struct mbox_chan *chan, void *data)
+{
+	struct gh_msgq *msgq = mbox_chan_to_msgq(chan);
+	struct gh_msgq_tx_data *msgq_data = data;
+	u64 tx_flags = 0;
+	unsigned long ret;
+	bool ready;
+
+	if (msgq_data->push)
+		tx_flags |= GH_HYPERCALL_MSGQ_TX_FLAGS_PUSH;
+
+	ret = gh_hypercall_msgq_send(msgq->tx_ghrsc->capid, msgq_data->length,
+					(uintptr_t)msgq_data->data, tx_flags, &ready);
+
+	/**
+	 * unlikely because Linux tracks state of msgq and should not try to
+	 * send message when msgq is full.
+	 */
+	if (unlikely(ret == GH_ERROR_MSGQUEUE_FULL))
+		return -EAGAIN;
+
+	/**
+	 * Propagate all other errors to client. If we return error to mailbox
+	 * framework, then no other messages can be sent and nobody will know
+	 * to retry this message.
+	 */
+	msgq->last_status = gh_remap_error(ret);
+
+	/**
+	 * This message was successfully sent, but message queue isn't ready to
+	 * receive more messages because it's now full. Mailbox framework
+	 * requires that we only report that message was transmitted only when
+	 * we're ready to transmit another message. We'll get that in the form
+	 * of tx IRQ once the other side starts to drain the msgq.
+	 */
+	if (ret == GH_ERROR_OK && !ready)
+		return 0;
+
+	/**
+	 * We can send more messages. Mailbox framework requires that tx done
+	 * happens asynchronously to sending the message. Gunyah message queues
+	 * tell us right away on the hypercall return whether we can send more
+	 * messages. To work around this, defer the txdone to a tasklet.
+	 */
+	tasklet_schedule(&msgq->txdone_tasklet);
+
+	return 0;
+}
+
+struct mbox_chan_ops gh_msgq_ops = {
+	.send_data = gh_msgq_send_data,
+};
+
+/**
+ * gh_msgq_init() - Initialize a Gunyah message queue with an mbox_client
+ * @parent: optional, device parent used for the mailbox controller
+ * @msgq: Pointer to the gh_msgq to initialize
+ * @cl: A mailbox client to bind to the mailbox channel that the message queue creates
+ * @tx_ghrsc: optional, the transmission side of the message queue
+ * @rx_ghrsc: optional, the receiving side of the message queue
+ *
+ * At least one of tx_ghrsc and rx_ghrsc should be not NULL. Most message queue use cases come with
+ * a pair of message queues to facilitiate bidirectional communication. When tx_ghrsc is set,
+ * the client can send messages with mbox_send_message(gh_msgq_chan(msgq), msg). When rx_ghrsc
+ * is set, the mbox_client should register an .rx_callback() and the message queue driver will
+ * push all available messages upon receiving the RX ready interrupt. The messages should be
+ * consumed or copied by the client right away as the gh_msgq_rx_data will be replaced/destroyed
+ * after the callback.
+ *
+ * Returns - 0 on success, negative otherwise
+ */
+int gh_msgq_init(struct device *parent, struct gh_msgq *msgq, struct mbox_client *cl,
+		     struct gunyah_resource *tx_ghrsc, struct gunyah_resource *rx_ghrsc)
+{
+	int ret;
+
+	/* Must have at least a tx_ghrsc or rx_ghrsc and that they are the right device types */
+	if ((!tx_ghrsc && !rx_ghrsc) ||
+	    (tx_ghrsc && tx_ghrsc->type != GUNYAH_RESOURCE_TYPE_MSGQ_TX) ||
+	    (rx_ghrsc && rx_ghrsc->type != GUNYAH_RESOURCE_TYPE_MSGQ_RX))
+		return -EINVAL;
+
+	msgq->tx_ghrsc = tx_ghrsc;
+	msgq->rx_ghrsc = rx_ghrsc;
+
+	msgq->mbox.dev = parent;
+	msgq->mbox.ops = &gh_msgq_ops;
+	msgq->mbox.chans = kcalloc(1, sizeof(*msgq->mbox.chans), GFP_KERNEL);
+	msgq->mbox.num_chans = 1;
+	msgq->mbox.txdone_irq = true;
+
+	if (gh_msgq_has_tx(msgq)) {
+		ret = request_irq(msgq->tx_ghrsc->irq, gh_msgq_tx_irq_handler, 0, "gh_msgq_tx",
+				msgq);
+		if (ret)
+			goto err_chans;
+	}
+
+	if (gh_msgq_has_rx(msgq)) {
+		ret = request_threaded_irq(msgq->rx_ghrsc->irq, NULL, gh_msgq_rx_irq_handler,
+						IRQF_ONESHOT, "gh_msgq_rx", msgq);
+		if (ret)
+			goto err_tx_irq;
+	}
+
+	tasklet_init(&msgq->txdone_tasklet, gh_msgq_txdone_tasklet, (unsigned long)msgq);
+
+	ret = mbox_controller_register(&msgq->mbox);
+	if (ret)
+		goto err_rx_irq;
+
+	ret = mbox_bind_client(gh_msgq_chan(msgq), cl);
+	if (ret)
+		goto err_mbox;
+
+	return 0;
+err_mbox:
+	mbox_controller_unregister(&msgq->mbox);
+err_rx_irq:
+	if (gh_msgq_has_rx(msgq))
+		free_irq(msgq->rx_ghrsc->irq, msgq);
+err_tx_irq:
+	if (gh_msgq_has_tx(msgq))
+		free_irq(msgq->tx_ghrsc->irq, msgq);
+err_chans:
+	kfree(msgq->mbox.chans);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_msgq_init);
+
+void gh_msgq_remove(struct gh_msgq *msgq)
+{
+	if (gh_msgq_has_rx(msgq))
+		free_irq(msgq->rx_ghrsc->irq, msgq);
+
+	if (gh_msgq_has_tx(msgq))
+		free_irq(msgq->tx_ghrsc->irq, msgq);
+
+	kfree(msgq->mbox.chans);
+}
+EXPORT_SYMBOL_GPL(gh_msgq_remove);
+
+
+static int __init gh_msgq_init_module(void)
+{
+	if (gh_api_version() != GUNYAH_API_V1) {
+		pr_warn("Unrecognized gunyah version: %u. Currently supported: %d\n",
+			gh_api_version(), GUNYAH_API_V1);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+module_init(gh_msgq_init_module);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Gunyah Message Queue Driver");
diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h
index c863cac4a3cf..e317d7ac938f 100644
--- a/include/linux/gunyah.h
+++ b/include/linux/gunyah.h
@@ -7,10 +7,67 @@
 #define _GUNYAH_H
 
 #include <linux/bitfield.h>
-#include <linux/types.h>
 #include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox_client.h>
+#include <linux/types.h>
+
+/* Follows resource manager's resource types for VM_GET_HYP_RESOURCES */
+enum gunyah_resource_type {
+	GUNYAH_RESOURCE_TYPE_BELL_TX	= 0,
+	GUNYAH_RESOURCE_TYPE_BELL_RX	= 1,
+	GUNYAH_RESOURCE_TYPE_MSGQ_TX	= 2,
+	GUNYAH_RESOURCE_TYPE_MSGQ_RX	= 3,
+	GUNYAH_RESOURCE_TYPE_VCPU	= 4,
+};
+
+struct gunyah_resource {
+	enum gunyah_resource_type type;
+	u64 capid;
+	int irq;
+};
+
+/**
+ * Gunyah Message Queues
+ */
+
+#define GH_MSGQ_MAX_MSG_SIZE	240
+
+struct gh_msgq_tx_data {
+	size_t length;
+	bool push;
+	char data[];
+};
+
+struct gh_msgq_rx_data {
+	size_t length;
+	char data[GH_MSGQ_MAX_MSG_SIZE];
+};
+
+struct gh_msgq {
+	struct gunyah_resource *tx_ghrsc;
+	struct gunyah_resource *rx_ghrsc;
+
+	/* msgq private */
+	int last_status;
+	struct mbox_controller mbox;
+	struct tasklet_struct txdone_tasklet;
+};
+
+
+int gh_msgq_init(struct device *parent, struct gh_msgq *msgq, struct mbox_client *cl,
+		     struct gunyah_resource *tx_ghrsc, struct gunyah_resource *rx_ghrsc);
+void gh_msgq_remove(struct gh_msgq *msgq);
+
+static inline struct mbox_chan *gh_msgq_chan(struct gh_msgq *msgq)
+{
+	return &msgq->mbox.chans[0];
+}
+
+/******************************************************************************/
+/* Common arch-independent macros and definitions for Gunyah hypercalls */
 
-/* Common Gunyah macros */
 #define GH_CAPID_INVAL	U64_MAX
 #define GH_VMID_ROOT_VM	0xff
 
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (8 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 09/21] mailbox: Add Gunyah message queue mailbox Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-11-01 18:02   ` Greg Kroah-Hartman
  2022-10-26 18:58 ` [PATCH v6 11/21] gunyah: rsc_mgr: Add subdevices bus Elliot Berman
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

The resource manager is a special virtual machine which is always
running on a Gunyah system. It provides APIs for creating and destroying
VMs, secure memory management, sharing/lending of memory between VMs,
and setup of inter-VM communication. Calls to the resource manager are
made via message queues.

This patch implements the basic probing and RPC mechanism to make those
API calls. Request/response calls can be made with gh_rm_call.
Drivers can also register to notifications pushed by RM via
gh_rm_register_notifier

Specific API calls that resource manager supports will be implemented in
subsequent patches.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 MAINTAINERS                    |   2 +-
 drivers/virt/gunyah/Kconfig    |  15 +
 drivers/virt/gunyah/Makefile   |   3 +
 drivers/virt/gunyah/rsc_mgr.c  | 602 +++++++++++++++++++++++++++++++++
 drivers/virt/gunyah/rsc_mgr.h  |  34 ++
 include/linux/gunyah_rsc_mgr.h |  26 ++
 6 files changed, 681 insertions(+), 1 deletion(-)
 create mode 100644 drivers/virt/gunyah/rsc_mgr.c
 create mode 100644 drivers/virt/gunyah/rsc_mgr.h
 create mode 100644 include/linux/gunyah_rsc_mgr.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 586539eadd3b..e072a0d2e553 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8945,7 +8945,7 @@ F:	Documentation/virt/gunyah/
 F:	arch/arm64/gunyah/
 F:	drivers/mailbox/gunyah-msgq.c
 F:	drivers/virt/gunyah/
-F:	include/linux/gunyah.h
+F:	include/linux/gunyah*.h
 
 HABANALABS PCI DRIVER
 M:	Oded Gabbay <ogabbay@kernel.org>
diff --git a/drivers/virt/gunyah/Kconfig b/drivers/virt/gunyah/Kconfig
index 127156a678a6..4de88d80aa7b 100644
--- a/drivers/virt/gunyah/Kconfig
+++ b/drivers/virt/gunyah/Kconfig
@@ -10,3 +10,18 @@ config GUNYAH
 
 	  Say Y/M here to enable the drivers needed to interact in a Gunyah
 	  virtual environment.
+
+config GUNYAH_RESORUCE_MANAGER
+	tristate "Gunyah Resource Manager"
+	select MAILBOX
+	select GUNYAH_MESSAGE_QUEUES
+	depends on GUNYAH
+	default y
+	help
+	  The resource manager (RM) is a privileged application VM supporting
+	  the Gunyah Hypervisor. Enable this driver to support communicating
+	  with Gunyah RM. This is typically required for a VM running under
+	  Gunyah wanting to have Gunyah-awareness.
+
+	  Say Y/M here if unsure.
+
diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile
index 2ac4ee64b89d..2c18b0a56413 100644
--- a/drivers/virt/gunyah/Makefile
+++ b/drivers/virt/gunyah/Makefile
@@ -1 +1,4 @@
 obj-$(CONFIG_GUNYAH) += gunyah.o
+
+gunyah_rsc_mgr-y += rsc_mgr.o
+obj-$(CONFIG_GUNYAH_RESORUCE_MANAGER) += gunyah_rsc_mgr.o
diff --git a/drivers/virt/gunyah/rsc_mgr.c b/drivers/virt/gunyah/rsc_mgr.c
new file mode 100644
index 000000000000..a9fde703cbbe
--- /dev/null
+++ b/drivers/virt/gunyah/rsc_mgr.c
@@ -0,0 +1,602 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) "gh_rsc_mgr: " fmt
+
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/gunyah.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/kthread.h>
+#include <linux/notifier.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/gunyah_rsc_mgr.h>
+#include <linux/platform_device.h>
+
+#include "rsc_mgr.h"
+
+/* Resource Manager Header */
+struct gh_rm_rpc_hdr {
+	u8 version : 4, hdr_words : 4;
+	u8 type : 2, fragments : 6;
+	u16 seq;
+	u32 msg_id;
+} __packed;
+
+/* Standard reply header */
+struct gh_rm_rpc_reply_hdr {
+	struct gh_rm_rpc_hdr rpc_hdr;
+	u32 err_code;
+} __packed;
+
+/* RPC Header versions */
+#define GH_RM_RPC_HDR_VERSION_ONE	0x1
+
+/* RPC Header words */
+#define GH_RM_RPC_HDR_WORDS		0x2
+
+/* RPC Message types */
+#define GH_RM_RPC_TYPE_CONT		0x0
+#define GH_RM_RPC_TYPE_REQ		0x1
+#define GH_RM_RPC_TYPE_RPLY		0x2
+#define GH_RM_RPC_TYPE_NOTIF		0x3
+
+#define GH_RM_MAX_NUM_FRAGMENTS		62
+
+#define GH_RM_MAX_MSG_SIZE	(GH_MSGQ_MAX_MSG_SIZE - sizeof(struct gh_rm_rpc_hdr))
+
+/**
+ * struct gh_rm_connection - Represents a complete message from resource manager
+ * @payload: Combined payload of all the fragments (msg headers stripped off).
+ * @size: Size of the payload.
+ * @ret: Linux return code, set in case there was an error processing connection
+ * @msg_id: Message ID from the header.
+ * @type: GH_RM_RPC_TYPE_RPLY or GH_RM_RPC_TYPE_NOTIF.
+ * @num_fragments: total number of fragments expected to be received.
+ * @fragments_received: fragments received so far.
+ * @rm_error: For request/reply sequences with standard replies.
+ * @seq: Sequence ID for the main message.
+ * @seq_done: Signals caller that the RM reply has been received
+ */
+struct gh_rm_connection {
+	void *payload;
+	size_t size;
+	int ret;
+	u32 msg_id;
+	u8 type;
+
+	u8 num_fragments;
+	u8 fragments_received;
+
+	/* only for req/reply sequence */
+	u32 rm_error;
+	u16 seq;
+	struct completion seq_done;
+};
+
+struct gh_rm_notif_complete {
+	struct gh_rm_connection *conn;
+	struct work_struct work;
+};
+
+struct gh_rsc_mgr {
+	struct gunyah_resource tx_ghrsc, rx_ghrsc;
+	struct gh_msgq msgq;
+	struct mbox_client msgq_client;
+	struct gh_rm_connection *active_rx_connection;
+	int last_tx_ret;
+
+	struct idr call_idr;
+	struct mutex call_idr_lock;
+
+	struct mutex send_lock;
+
+	struct work_struct recv_work;
+};
+
+static struct gh_rsc_mgr *__rsc_mgr;
+SRCU_NOTIFIER_HEAD_STATIC(gh_rm_notifier);
+
+static struct gh_rm_connection *gh_rm_alloc_connection(u32 msg_id, u8 type)
+{
+	struct gh_rm_connection *connection;
+
+	connection = kzalloc(sizeof(*connection), GFP_KERNEL);
+	if (!connection)
+		return NULL;
+
+	connection->type = type;
+	connection->msg_id = msg_id;
+
+	return connection;
+}
+
+static int gh_rm_init_connection_payload(struct gh_rm_connection *connection, void *msg,
+					size_t hdr_size, size_t msg_size)
+{
+	struct gh_rm_rpc_hdr *hdr = msg;
+	size_t max_buf_size, payload_size;
+
+	if (hdr_size > msg_size)
+		return -EINVAL;
+
+	payload_size = msg_size - hdr_size;
+
+	connection->num_fragments = hdr->fragments;
+	connection->fragments_received = 0;
+	connection->type = hdr->type;
+
+	/* There's not going to be any payload, no need to allocate buffer. */
+	if (!payload_size && !connection->num_fragments)
+		return 0;
+
+	/*
+	 * maximum payload size is GH_MSGQ_MAX_MSG_SIZE - hdr_size
+	 * and can received (hdr->fragments + 1) of those
+	 */
+	max_buf_size = (GH_MSGQ_MAX_MSG_SIZE - hdr_size) * (hdr->fragments + 1);
+
+	connection->payload = kzalloc(max_buf_size, GFP_KERNEL);
+	if (!connection->payload)
+		return -ENOMEM;
+
+	memcpy(connection->payload, msg + hdr_size, payload_size);
+	connection->size = payload_size;
+	return 0;
+}
+
+static void gh_rm_notif_work(struct work_struct *work)
+{
+	struct gh_rm_notif_complete *notif = container_of(work, struct gh_rm_notif_complete, work);
+	struct gh_rm_connection *connection = notif->conn;
+	u32 notif_id = connection->msg_id;
+	struct gh_rm_notification notification = {
+		.buff = connection->payload,
+		.size = connection->size,
+	};
+
+	srcu_notifier_call_chain(&gh_rm_notifier, notif_id, &notification);
+
+	kfree(connection->payload);
+	kfree(connection);
+	kfree(notif);
+}
+
+static struct gh_rm_connection *gh_rm_process_notif(struct gh_rsc_mgr *rsc_mgr,
+						    void *msg, size_t msg_size)
+{
+	struct gh_rm_rpc_hdr *hdr = msg;
+	struct gh_rm_connection *connection;
+
+	connection = gh_rm_alloc_connection(hdr->msg_id, hdr->type);
+	if (!connection) {
+		pr_err("Failed to alloc connection for notification, dropping.\n");
+		return NULL;
+	}
+
+	if (gh_rm_init_connection_payload(connection, msg, sizeof(*hdr), msg_size)) {
+		pr_err("Failed to alloc connection buffer for notification, dropping.\n");
+		kfree(connection);
+		return NULL;
+	}
+
+	return connection;
+}
+
+static struct gh_rm_connection *gh_rm_process_rply(struct gh_rsc_mgr *rsc_mgr,
+						   void *msg, size_t msg_size)
+{
+	struct gh_rm_rpc_reply_hdr *reply_hdr = msg;
+	struct gh_rm_rpc_hdr *hdr = msg;
+	struct gh_rm_connection *connection;
+
+	if (mutex_lock_interruptible(&rsc_mgr->call_idr_lock))
+		return ERR_PTR(-ERESTARTSYS);
+
+	connection = idr_find(&rsc_mgr->call_idr, hdr->seq);
+	mutex_unlock(&rsc_mgr->call_idr_lock);
+
+	if (!connection) {
+		pr_err("Failed to find connection for sequence %u\n", hdr->seq);
+		return NULL;
+	}
+	if (connection->msg_id != hdr->msg_id) {
+		pr_err("Reply for sequence %u expected msg_id: %x but got %x\n", hdr->seq,
+			connection->msg_id, hdr->msg_id);
+		/*
+		 * Don't complete connection and error the client, maybe
+		 * resource manager will send us the expected reply sequence soon.
+		 */
+		return NULL;
+	}
+
+	if (gh_rm_init_connection_payload(connection, msg, sizeof(*reply_hdr), msg_size)) {
+		pr_err("Failed to alloc connection buffer for sequence %d\n", hdr->seq);
+		/* Send connection complete and error the client. */
+		connection->ret = -ENOMEM;
+		complete(&connection->seq_done);
+		return NULL;
+	}
+
+	connection->rm_error = reply_hdr->err_code;
+	return connection;
+}
+
+static void gh_rm_process_cont(struct gh_rm_connection *connection, void *msg, size_t msg_size)
+{
+	struct gh_rm_rpc_hdr *hdr = msg;
+	size_t payload_size = msg_size - sizeof(*hdr);
+
+	/*
+	 * hdr->fragments and hdr->msg_id preserves the value from first reply
+	 * or notif message. To detect mishandling, check it's still intact.
+	 */
+	if (connection->msg_id != hdr->msg_id)
+		pr_warn("Appending mismatched continuation with id %d to connection with id %d\n",
+			hdr->msg_id, connection->msg_id);
+	if (connection->num_fragments != hdr->fragments)
+		pr_warn("Number of fragments mismatch for seq: %d\n", hdr->seq);
+
+	memcpy(connection->payload + connection->size, msg + sizeof(*hdr), payload_size);
+	connection->size += payload_size;
+	connection->fragments_received++;
+}
+
+static bool gh_rm_complete_connection(struct gh_rm_connection *connection)
+{
+	struct gh_rm_notif_complete *notif_work;
+
+	if (!connection)
+		return false;
+
+	if (connection->fragments_received != connection->num_fragments)
+		return false;
+
+	switch (connection->type) {
+	case GH_RM_RPC_TYPE_RPLY:
+		complete(&connection->seq_done);
+		break;
+	case GH_RM_RPC_TYPE_NOTIF:
+		notif_work = kzalloc(sizeof(*notif_work), GFP_KERNEL);
+		if (notif_work == NULL)
+			break;
+
+		notif_work->conn = connection;
+		INIT_WORK(&notif_work->work, gh_rm_notif_work);
+
+		schedule_work(&notif_work->work);
+		break;
+	default:
+		pr_err("Invalid message type (%d) received\n", connection->type);
+		break;
+	}
+
+	return true;
+}
+
+static void gh_rm_abort_connection(struct gh_rm_connection *connection)
+{
+	switch (connection->type) {
+	case GH_RM_RPC_TYPE_RPLY:
+		connection->ret = -EIO;
+		complete(&connection->seq_done);
+		break;
+	case GH_RM_RPC_TYPE_NOTIF:
+		fallthrough;
+	default:
+		kfree(connection->payload);
+		kfree(connection);
+	}
+}
+
+static void gh_rm_msgq_rx_data(struct mbox_client *cl, void *mssg)
+{
+	struct gh_rsc_mgr *rsc_mgr = container_of(cl, struct gh_rsc_mgr, msgq_client);
+	struct gh_msgq_rx_data *rx_data = mssg;
+	void *msg = rx_data->data;
+	size_t msg_size = rx_data->length;
+	struct gh_rm_rpc_hdr *hdr;
+
+	if (msg_size <= sizeof(struct gh_rm_rpc_hdr)) {
+		pr_err("Invalid message size received: %ld is too small\n", msg_size);
+		return;
+	}
+
+	hdr = msg;
+	switch (hdr->type) {
+	case GH_RM_RPC_TYPE_NOTIF:
+		if (rsc_mgr->active_rx_connection) {
+			/* Not possible per protocol. Do something better than BUG_ON */
+			pr_warn("Received start of new notification without finishing existing message series.\n");
+			gh_rm_abort_connection(rsc_mgr->active_rx_connection);
+		}
+		rsc_mgr->active_rx_connection = gh_rm_process_notif(rsc_mgr, msg, msg_size);
+		break;
+	case GH_RM_RPC_TYPE_RPLY:
+		if (rsc_mgr->active_rx_connection) {
+			/* Not possible per protocol. Do something better than BUG_ON */
+			pr_warn("Received start of new reply without finishing existing message series.\n");
+			gh_rm_abort_connection(rsc_mgr->active_rx_connection);
+		}
+		rsc_mgr->active_rx_connection = gh_rm_process_rply(rsc_mgr, msg, msg_size);
+		break;
+	case GH_RM_RPC_TYPE_CONT:
+		if (!rsc_mgr->active_rx_connection) {
+			pr_warn("Received a continuation message without receiving initial message\n");
+			break;
+		}
+		gh_rm_process_cont(rsc_mgr->active_rx_connection, msg, msg_size);
+		break;
+	default:
+		pr_err("Invalid message type (%d) received\n", hdr->type);
+		return;
+	}
+
+	if (gh_rm_complete_connection(rsc_mgr->active_rx_connection))
+		rsc_mgr->active_rx_connection = NULL;
+}
+
+static void gh_rm_msgq_tx_done(struct mbox_client *cl, void *mssg, int r)
+{
+	struct gh_rsc_mgr *rsc_mgr = container_of(cl, struct gh_rsc_mgr, msgq_client);
+
+	kfree(mssg);
+	rsc_mgr->last_tx_ret = r;
+}
+
+static int gh_rm_send_request(struct gh_rsc_mgr *rsc_mgr, u32 message_id,
+			      const void *req_buff, size_t req_buff_size,
+			      struct gh_rm_connection *connection)
+{
+	size_t buff_size_remaining = req_buff_size;
+	const void *req_buff_curr = req_buff;
+	struct gh_rm_rpc_hdr *hdr;
+	u32 cont_fragments = req_buff_size / GH_RM_MAX_MSG_SIZE;
+	size_t payload_size;
+	struct gh_msgq_tx_data *msg;
+	int i, ret;
+
+	if (WARN(cont_fragments > GH_RM_MAX_NUM_FRAGMENTS,
+		 "Limit exceeded for the number of fragments: %u\n", cont_fragments))
+		return -E2BIG;
+
+	ret = mutex_lock_interruptible(&rsc_mgr->send_lock);
+	if (ret)
+		return ret;
+
+	/* Consider also the 'request' packet for the loop count */
+	for (i = 0; i <= cont_fragments; i++) {
+		if (buff_size_remaining > GH_RM_MAX_MSG_SIZE) {
+			payload_size = GH_RM_MAX_MSG_SIZE;
+			buff_size_remaining -= payload_size;
+		} else {
+			payload_size = buff_size_remaining;
+		}
+
+		msg = kzalloc(sizeof(*msg) + GH_MSGQ_MAX_MSG_SIZE, GFP_KERNEL);
+		if (!msg) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		/* Fill header */
+		hdr = (struct gh_rm_rpc_hdr *)msg->data;
+		hdr->version = GH_RM_RPC_HDR_VERSION_ONE;
+		hdr->hdr_words = GH_RM_RPC_HDR_WORDS;
+		hdr->type = i == 0 ? GH_RM_RPC_TYPE_REQ : GH_RM_RPC_TYPE_CONT;
+		hdr->fragments = cont_fragments;
+		hdr->seq = connection->seq;
+		hdr->msg_id = message_id;
+
+		/* Copy payload */
+		memcpy(msg->data + sizeof(*hdr), req_buff_curr, payload_size);
+		req_buff_curr += payload_size;
+
+		/* Force the last fragment to immediately alert the receiver */
+		msg->push = i == cont_fragments;
+		msg->length = sizeof(*hdr) + payload_size;
+
+		ret = mbox_send_message(gh_msgq_chan(&rsc_mgr->msgq), msg);
+		if (ret < 0) {
+			kfree(msg);
+			break;
+		}
+
+		if (rsc_mgr->last_tx_ret) {
+			ret = rsc_mgr->last_tx_ret;
+			break;
+		}
+	}
+
+out:
+	mutex_unlock(&rsc_mgr->send_lock);
+	return ret < 0 ? ret : 0;
+}
+
+/**
+ * gh_rm_call: Achieve request-response type communication with RPC
+ * @message_id: The RM RPC message-id
+ * @req_buff: Request buffer that contains the payload
+ * @req_buff_size: Total size of the payload
+ * @resp_buf: Pointer to a response buffer
+ * @resp_buff_size: Size of the response buffer
+ *
+ * Make a request to the RM-VM and wait for reply back. For a successful
+ * response, the function returns the payload. The size of the payload is set in
+ * resp_buff_size. The resp_buf should be freed by the caller.
+ *
+ * Context: Process context. Will sleep waiting for reply.
+ * Return: >0 is standard reply error from RM. <0 on internal error.
+ */
+int gh_rm_call(u32 message_id, void *req_buff, size_t req_buff_size,
+	       void **resp_buf, size_t *resp_buff_size)
+{
+	struct gh_rm_connection *connection;
+	int ret;
+	struct gh_rsc_mgr *rsc_mgr = __rsc_mgr;
+
+	/* messaged_id 0 is reserved */
+	if (!message_id)
+		return -EINVAL;
+
+	if (!rsc_mgr)
+		return -EPROBE_DEFER;
+
+	connection = gh_rm_alloc_connection(message_id, GH_RM_RPC_TYPE_RPLY);
+	if (!connection)
+		return -ENOMEM;
+
+	init_completion(&connection->seq_done);
+
+	/* Allocate a new seq number for this connection */
+	if (mutex_lock_interruptible(&rsc_mgr->call_idr_lock)) {
+		kfree(connection);
+		return -ERESTARTSYS;
+	}
+	connection->seq = idr_alloc_cyclic(&rsc_mgr->call_idr, connection, 0, U16_MAX, GFP_KERNEL);
+	mutex_unlock(&rsc_mgr->call_idr_lock);
+
+	/* Send the request to the Resource Manager */
+	ret = gh_rm_send_request(rsc_mgr, message_id, req_buff, req_buff_size, connection);
+	if (ret < 0)
+		goto out;
+
+	/* Wait for response */
+	ret = wait_for_completion_interruptible(&connection->seq_done);
+	if (ret)
+		goto out;
+
+	if (connection->ret) {
+		ret = connection->ret;
+		kfree(connection->payload);
+		goto out;
+	}
+
+	if (connection->rm_error) {
+		ret = connection->rm_error;
+		kfree(connection->payload);
+		goto out;
+	}
+
+	*resp_buf = connection->payload;
+	*resp_buff_size = connection->size;
+
+out:
+	mutex_lock(&rsc_mgr->call_idr_lock);
+	idr_remove(&rsc_mgr->call_idr, connection->seq);
+	mutex_unlock(&rsc_mgr->call_idr_lock);
+
+	kfree(connection);
+	return ret;
+}
+
+int gh_rm_register_notifier(struct notifier_block *nb)
+{
+	return srcu_notifier_chain_register(&gh_rm_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(gh_rm_register_notifier);
+
+int gh_rm_unregister_notifier(struct notifier_block *nb)
+{
+	return srcu_notifier_chain_unregister(&gh_rm_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(gh_rm_unregister_notifier);
+
+static int gh_msgq_platform_probe_direction(struct platform_device *pdev,
+					u8 gh_type, int idx, struct gunyah_resource *ghrsc)
+{
+	int ret;
+	struct device_node *node = pdev->dev.of_node;
+
+	ghrsc->type = gh_type;
+
+	ghrsc->irq = platform_get_irq(pdev, idx);
+	if (ghrsc->irq < 0) {
+		dev_err(&pdev->dev, "Failed to get irq%d: %d\n", idx, ghrsc->irq);
+		return ghrsc->irq;
+	}
+
+	ret = of_property_read_u64_index(node, "reg", idx, &ghrsc->capid);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to get capid%d: %d\n", idx, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int gh_rm_drv_probe(struct platform_device *pdev)
+{
+	struct gh_rsc_mgr *rsc_mgr;
+	int ret;
+
+	rsc_mgr = devm_kzalloc(&pdev->dev, sizeof(*rsc_mgr), GFP_KERNEL);
+	if (!rsc_mgr)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, rsc_mgr);
+
+	mutex_init(&rsc_mgr->call_idr_lock);
+	idr_init(&rsc_mgr->call_idr);
+	mutex_init(&rsc_mgr->send_lock);
+
+	ret = gh_msgq_platform_probe_direction(pdev, GUNYAH_RESOURCE_TYPE_MSGQ_TX, 0,
+						&rsc_mgr->tx_ghrsc);
+	if (ret)
+		return ret;
+
+	ret = gh_msgq_platform_probe_direction(pdev, GUNYAH_RESOURCE_TYPE_MSGQ_RX, 1,
+						&rsc_mgr->rx_ghrsc);
+	if (ret)
+		return ret;
+
+	rsc_mgr->msgq_client.dev = &pdev->dev;
+	rsc_mgr->msgq_client.tx_block = true;
+	rsc_mgr->msgq_client.rx_callback = gh_rm_msgq_rx_data;
+	rsc_mgr->msgq_client.tx_done = gh_rm_msgq_tx_done;
+
+	ret = gh_msgq_init(&pdev->dev, &rsc_mgr->msgq, &rsc_mgr->msgq_client,
+				&rsc_mgr->tx_ghrsc, &rsc_mgr->rx_ghrsc);
+	if (ret)
+		return ret;
+
+	__rsc_mgr = rsc_mgr;
+
+	return 0;
+}
+
+static int gh_rm_drv_remove(struct platform_device *pdev)
+{
+	struct gh_rsc_mgr *rsc_mgr = platform_get_drvdata(pdev);
+
+	__rsc_mgr = NULL;
+
+	mbox_free_channel(gunyah_msgq_chan(&rsc_mgr->msgq));
+	gunyah_msgq_remove(&rsc_mgr->msgq);
+
+	return 0;
+}
+
+static const struct of_device_id gh_rm_of_match[] = {
+	{ .compatible = "gunyah-resource-manager" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, gh_rm_of_match);
+
+static struct platform_driver gh_rm_driver = {
+	.probe = gh_rm_drv_probe,
+	.remove = gh_rm_drv_remove,
+	.driver = {
+		.name = "gh_rsc_mgr",
+		.of_match_table = gh_rm_of_match,
+	},
+};
+module_platform_driver(gh_rsc_mgr_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Gunyah Resource Manager Driver");
diff --git a/drivers/virt/gunyah/rsc_mgr.h b/drivers/virt/gunyah/rsc_mgr.h
new file mode 100644
index 000000000000..e4f2499267bf
--- /dev/null
+++ b/drivers/virt/gunyah/rsc_mgr.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#ifndef __GH_RSC_MGR_PRIV_H
+#define __GH_RSC_MGR_PRIV_H
+
+#include <linux/gunyah.h>
+
+/* RM Error codes */
+#define GH_RM_ERROR_OK			0x0
+#define GH_RM_ERROR_UNIMPLEMENTED	0xFFFFFFFF
+#define GH_RM_ERROR_NOMEM		0x1
+#define GH_RM_ERROR_NORESOURCE		0x2
+#define GH_RM_ERROR_DENIED		0x3
+#define GH_RM_ERROR_INVALID		0x4
+#define GH_RM_ERROR_BUSY		0x5
+#define GH_RM_ERROR_ARGUMENT_INVALID	0x6
+#define GH_RM_ERROR_HANDLE_INVALID	0x7
+#define GH_RM_ERROR_VALIDATE_FAILED	0x8
+#define GH_RM_ERROR_MAP_FAILED		0x9
+#define GH_RM_ERROR_MEM_INVALID		0xA
+#define GH_RM_ERROR_MEM_INUSE		0xB
+#define GH_RM_ERROR_MEM_RELEASED	0xC
+#define GH_RM_ERROR_VMID_INVALID	0xD
+#define GH_RM_ERROR_LOOKUP_FAILED	0xE
+#define GH_RM_ERROR_IRQ_INVALID		0xF
+#define GH_RM_ERROR_IRQ_INUSE		0x10
+#define GH_RM_ERROR_IRQ_RELEASED	0x11
+
+int gh_rm_call(u32 message_id, void *req_buff, size_t req_buff_size,
+		void **resp_buf, size_t *resp_buff_size);
+
+#endif
diff --git a/include/linux/gunyah_rsc_mgr.h b/include/linux/gunyah_rsc_mgr.h
new file mode 100644
index 000000000000..b3b37225b7fb
--- /dev/null
+++ b/include/linux/gunyah_rsc_mgr.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _GUNYAH_RSC_MGR_H
+#define _GUNYAH_RSC_MGR_H
+
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/gunyah.h>
+
+#define GH_VMID_INVAL	U16_MAX
+
+/* Gunyah recognizes VMID0 as an alias to the current VM's ID */
+#define GH_VMID_SELF			0
+
+struct gh_rm_notification {
+	const void *buff;
+	const size_t size;
+};
+
+int gh_rm_register_notifier(struct notifier_block *nb);
+int gh_rm_unregister_notifier(struct notifier_block *nb);
+
+#endif
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 11/21] gunyah: rsc_mgr: Add subdevices bus
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (9 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 12/21] gunyah: rsc_mgr: Add VM lifecycle RPC Elliot Berman
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Greg Kroah-Hartman
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

Gunyah Resource Manager exposes an interface which should occupy a few
devices on Linux:
 - a remote procedure call framework to talk to RM
 - a virtual machine manager to launch VMs, share memory with them,
   schedule runtime for those VMs, and handle certain faults.

Create a virtual device bus for the console and VM Manager functions.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/virt/gunyah/Makefile      |  2 +-
 drivers/virt/gunyah/rsc_mgr.c     | 42 ++++++++++++++--
 drivers/virt/gunyah/rsc_mgr.h     | 10 ++++
 drivers/virt/gunyah/rsc_mgr_bus.c | 83 +++++++++++++++++++++++++++++++
 include/linux/gunyah_rsc_mgr.h    | 19 +++++++
 include/linux/mod_devicetable.h   |  8 +++
 scripts/mod/devicetable-offsets.c |  3 ++
 scripts/mod/file2alias.c          | 10 ++++
 8 files changed, 173 insertions(+), 4 deletions(-)
 create mode 100644 drivers/virt/gunyah/rsc_mgr_bus.c

diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile
index 2c18b0a56413..a9169af6c61f 100644
--- a/drivers/virt/gunyah/Makefile
+++ b/drivers/virt/gunyah/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_GUNYAH) += gunyah.o
 
-gunyah_rsc_mgr-y += rsc_mgr.o
+gunyah_rsc_mgr-y += rsc_mgr.o rsc_mgr_bus.o
 obj-$(CONFIG_GUNYAH_RESORUCE_MANAGER) += gunyah_rsc_mgr.o
diff --git a/drivers/virt/gunyah/rsc_mgr.c b/drivers/virt/gunyah/rsc_mgr.c
index a9fde703cbbe..f2f776edecb8 100644
--- a/drivers/virt/gunyah/rsc_mgr.c
+++ b/drivers/virt/gunyah/rsc_mgr.c
@@ -98,6 +98,8 @@ struct gh_rsc_mgr {
 	struct mutex send_lock;
 
 	struct work_struct recv_work;
+
+	struct gh_rm_device vm_mgr_dev;
 };
 
 static struct gh_rsc_mgr *__rsc_mgr;
@@ -567,17 +569,27 @@ static int gh_rm_drv_probe(struct platform_device *pdev)
 
 	__rsc_mgr = rsc_mgr;
 
+	ret = gh_rm_device_add(&rsc_mgr->vm_mgr_dev, &pdev->dev, GH_RM_DEVICE_VM_MGR);
+	if (ret)
+		goto err_msgq;
+
 	return 0;
+
+err_msgq:
+	gh_msgq_remove(&rsc_mgr->msgq);
+	return ret;
 }
 
 static int gh_rm_drv_remove(struct platform_device *pdev)
 {
 	struct gh_rsc_mgr *rsc_mgr = platform_get_drvdata(pdev);
 
+	gh_rm_device_delete(&rsc_mgr->vm_mgr_dev);
+
 	__rsc_mgr = NULL;
 
-	mbox_free_channel(gunyah_msgq_chan(&rsc_mgr->msgq));
-	gunyah_msgq_remove(&rsc_mgr->msgq);
+	mbox_free_channel(gh_msgq_chan(&rsc_mgr->msgq));
+	gh_msgq_remove(&rsc_mgr->msgq);
 
 	return 0;
 }
@@ -596,7 +608,31 @@ static struct platform_driver gh_rm_driver = {
 		.of_match_table = gh_rm_of_match,
 	},
 };
-module_platform_driver(gh_rsc_mgr_driver);
+
+static int __init gh_rm_init(void)
+{
+	int ret;
+
+	ret = gh_rm_bus_register();
+	if (ret) {
+		pr_err("Failed to register gh_rm_bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = platform_driver_register(&gh_rm_driver);
+	if (ret)
+		gh_rm_bus_unregister();
+
+	return ret;
+}
+subsys_initcall(gh_rm_init);
+
+static void __exit gh_rm_exit(void)
+{
+	platform_driver_unregister(&gh_rm_driver);
+	gh_rm_bus_unregister();
+}
+module_exit(gh_rm_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Gunyah Resource Manager Driver");
diff --git a/drivers/virt/gunyah/rsc_mgr.h b/drivers/virt/gunyah/rsc_mgr.h
index e4f2499267bf..129e9d514f2a 100644
--- a/drivers/virt/gunyah/rsc_mgr.h
+++ b/drivers/virt/gunyah/rsc_mgr.h
@@ -31,4 +31,14 @@
 int gh_rm_call(u32 message_id, void *req_buff, size_t req_buff_size,
 		void **resp_buf, size_t *resp_buff_size);
 
+struct gh_rm_device {
+	struct device dev;
+	const char *name;
+};
+
+int gh_rm_bus_register(void);
+void gh_rm_bus_unregister(void);
+int gh_rm_device_add(struct gh_rm_device *ghrm_dev, struct device *parent, const char *name);
+void gh_rm_device_delete(struct gh_rm_device *ghrm_dev);
+
 #endif
diff --git a/drivers/virt/gunyah/rsc_mgr_bus.c b/drivers/virt/gunyah/rsc_mgr_bus.c
new file mode 100644
index 000000000000..bbb3bdc747cc
--- /dev/null
+++ b/drivers/virt/gunyah/rsc_mgr_bus.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) "gh_rsc_mgr: " fmt
+
+#include <linux/device.h>
+#include <linux/gunyah_rsc_mgr.h>
+#include <linux/mod_devicetable.h>
+
+#include "rsc_mgr.h"
+
+#define to_gh_rm_device(dev)	container_of(dev, struct gh_rm_device, dev)
+#define to_gh_rm_driver(drv)	container_of(drv, struct gh_rm_driver, drv)
+
+static int gh_rm_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct gh_rm_device *ghrm_dev = to_gh_rm_device(dev);
+	struct gh_rm_driver *ghrm_drv = to_gh_rm_driver(drv);
+
+	return !strncmp(ghrm_dev->name, ghrm_drv->id_table->name, GUNYAH_RSC_MGR_NAME_SIZE);
+}
+
+static int gh_rm_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct gh_rm_device *ghrm_dev = to_gh_rm_device(dev);
+
+	return add_uevent_var(env, "MODALIAS=%s%s", GUNYAH_RSC_MGR_PREFIX, ghrm_dev->name);
+}
+
+static struct bus_type gh_rm_bus = {
+	.name = "gh_rsc_mgr",
+	.match = gh_rm_bus_match,
+	.uevent = gh_rm_bus_uevent,
+};
+
+int gh_rm_bus_register(void)
+{
+	return bus_register(&gh_rm_bus);
+}
+
+void gh_rm_bus_unregister(void)
+{
+	bus_unregister(&gh_rm_bus);
+}
+
+int gh_rm_device_add(struct gh_rm_device *ghrm_dev, struct device *parent, const char *name)
+{
+	ghrm_dev->dev.bus = &gh_rm_bus;
+	ghrm_dev->dev.parent = parent;
+	ghrm_dev->name = name;
+
+	device_initialize(&ghrm_dev->dev);
+
+	dev_set_name(&ghrm_dev->dev, "%s.%s", dev_name(parent), name);
+	return device_add(&ghrm_dev->dev);
+}
+
+void gh_rm_device_delete(struct gh_rm_device *ghrm_dev)
+{
+	device_del(&ghrm_dev->dev);
+}
+
+int __gh_rm_driver_register(struct gh_rm_driver *ghrm_drv, struct module *owner,
+				const char *modname)
+{
+	if (WARN_ON(!ghrm_drv->drv.probe) || WARN_ON(!ghrm_drv->id_table))
+		return -EINVAL;
+
+	ghrm_drv->drv.bus = &gh_rm_bus;
+	ghrm_drv->drv.owner = owner;
+	ghrm_drv->drv.mod_name = modname;
+
+	return driver_register(&ghrm_drv->drv);
+}
+EXPORT_SYMBOL_GPL(__gh_rm_driver_register);
+
+void gh_rm_driver_unregister(struct gh_rm_driver *ghrm_drv)
+{
+	driver_unregister(&ghrm_drv->drv);
+}
+EXPORT_SYMBOL_GPL(gh_rm_driver_unregister);
diff --git a/include/linux/gunyah_rsc_mgr.h b/include/linux/gunyah_rsc_mgr.h
index b3b37225b7fb..0eeb7202fa33 100644
--- a/include/linux/gunyah_rsc_mgr.h
+++ b/include/linux/gunyah_rsc_mgr.h
@@ -9,6 +9,8 @@
 #include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/gunyah.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
 
 #define GH_VMID_INVAL	U16_MAX
 
@@ -23,4 +25,21 @@ struct gh_rm_notification {
 int gh_rm_register_notifier(struct notifier_block *nb);
 int gh_rm_unregister_notifier(struct notifier_block *nb);
 
+#define GH_RM_DEVICE_VM_MGR		"vm_mgr"
+
+struct gh_rm_driver {
+	const struct gunyah_rsc_mgr_device_id *id_table;
+	struct device_driver drv;
+};
+
+int __gh_rm_driver_register(struct gh_rm_driver *ghrm_drv, struct module *owner,
+				const char *modname);
+#define gh_rm_driver_register(ghrm_drv) \
+	__gh_rm_driver_register(ghrm_drv, THIS_MODULE, KBUILD_MODNAME)
+
+void gh_rm_driver_unregister(struct gh_rm_driver *ghrm_drv);
+
+#define module_gh_rm_driver(ghrm_drv) \
+	module_driver(ghrm_drv, gh_rm_driver_register, gh_rm_driver_unregister)
+
 #endif
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 549590e9c644..c4dc0ee6ae00 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -911,4 +911,12 @@ struct ishtp_device_id {
 	kernel_ulong_t driver_data;
 };
 
+#define GUNYAH_RSC_MGR_NAME_SIZE 32
+#define GUNYAH_RSC_MGR_PREFIX "gh_rsc_mgr:"
+
+struct gunyah_rsc_mgr_device_id {
+	const char name[GUNYAH_RSC_MGR_NAME_SIZE];
+	kernel_ulong_t driver_data;
+};
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index c0d3bcb99138..7b6944ed9336 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -262,5 +262,8 @@ int main(void)
 	DEVID(ishtp_device_id);
 	DEVID_FIELD(ishtp_device_id, guid);
 
+	DEVID(gunyah_rsc_mgr_device_id);
+	DEVID_FIELD(gunyah_rsc_mgr_device_id, name);
+
 	return 0;
 }
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 80d973144fde..a02b9e8e02a8 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1452,6 +1452,15 @@ static int do_dfl_entry(const char *filename, void *symval, char *alias)
 	return 1;
 }
 
+/* Looks like: gh_rsc_mgr:S */
+static int do_gunyah_rsc_mgr_entry(const char *filename, void *symval, char *alias)
+{
+	DEF_FIELD_ADDR(symval, gunyah_rsc_mgr_device_id, name);
+	sprintf(alias, GUNYAH_RSC_MGR_PREFIX "%s", *name);
+
+	return 1;
+}
+
 /* Does namelen bytes of name exactly match the symbol? */
 static bool sym_is(const char *name, unsigned namelen, const char *symbol)
 {
@@ -1531,6 +1540,7 @@ static const struct devtable devtable[] = {
 	{"ssam", SIZE_ssam_device_id, do_ssam_entry},
 	{"dfl", SIZE_dfl_device_id, do_dfl_entry},
 	{"ishtp", SIZE_ishtp_device_id, do_ishtp_entry},
+	{"gh_rsc_mgr", SIZE_gunyah_rsc_mgr_device_id, do_gunyah_rsc_mgr_entry},
 };
 
 /* Create MODULE_ALIAS() statements.
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 12/21] gunyah: rsc_mgr: Add VM lifecycle RPC
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (10 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 11/21] gunyah: rsc_mgr: Add subdevices bus Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager Elliot Berman
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Add Gunyah Resource Manager RPC to launch an unauthenticated VM.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/virt/gunyah/Makefile      |   2 +-
 drivers/virt/gunyah/rsc_mgr.h     |  55 +++++++
 drivers/virt/gunyah/rsc_mgr_rpc.c | 264 ++++++++++++++++++++++++++++++
 include/linux/gunyah_rsc_mgr.h    |  54 ++++++
 4 files changed, 374 insertions(+), 1 deletion(-)
 create mode 100644 drivers/virt/gunyah/rsc_mgr_rpc.c

diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile
index a9169af6c61f..09c1bbd28b48 100644
--- a/drivers/virt/gunyah/Makefile
+++ b/drivers/virt/gunyah/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_GUNYAH) += gunyah.o
 
-gunyah_rsc_mgr-y += rsc_mgr.o rsc_mgr_bus.o
+gunyah_rsc_mgr-y += rsc_mgr.o rsc_mgr_rpc.o rsc_mgr_bus.o
 obj-$(CONFIG_GUNYAH_RESORUCE_MANAGER) += gunyah_rsc_mgr.o
diff --git a/drivers/virt/gunyah/rsc_mgr.h b/drivers/virt/gunyah/rsc_mgr.h
index 129e9d514f2a..247664b8b008 100644
--- a/drivers/virt/gunyah/rsc_mgr.h
+++ b/drivers/virt/gunyah/rsc_mgr.h
@@ -28,6 +28,61 @@
 #define GH_RM_ERROR_IRQ_INUSE		0x10
 #define GH_RM_ERROR_IRQ_RELEASED	0x11
 
+/* Message IDs: VM Management */
+#define GH_RM_RPC_VM_ALLOC_VMID			0x56000001
+#define GH_RM_RPC_VM_DEALLOC_VMID		0x56000002
+#define GH_RM_RPC_VM_START			0x56000004
+#define GH_RM_RPC_VM_STOP			0x56000005
+#define GH_RM_RPC_VM_CONFIG_IMAGE		0x56000009
+#define GH_RM_RPC_VM_INIT			0x5600000B
+#define GH_RM_RPC_VM_GET_HYP_RESOURCES		0x56000020
+#define GH_RM_RPC_VM_GET_VMID			0x56000024
+#define GH_RM_RPC_VM_SET_BOOT_CONTEXT		0x56000031
+
+/* Call: CONSOLE_OPEN, CONSOLE_CLOSE, CONSOLE_FLUSH */
+struct gh_vm_common_vmid_req {
+	u16 vmid;
+	u16 reserved0;
+} __packed;
+
+/* Call: VM_STOP */
+struct gh_vm_stop_req {
+	u16 vmid;
+	u8 flags;
+	u8 reserved;
+	u32 stop_reason;
+} __packed;
+
+/* Call: VM_CONFIG_IMAGE */
+struct gh_vm_config_image_req {
+	u16 vmid;
+	u16 auth_mech;
+	u32 mem_handle;
+	u32 image_offset_low;
+	u32 image_offset_high;
+	u32 image_size_low;
+	u32 image_size_high;
+	u32 dtb_offset_low;
+	u32 dtb_offset_high;
+	u32 dtb_size_low;
+	u32 dtb_size_high;
+} __packed;
+
+/* Call: GET_HYP_RESOURCES */
+struct gh_vm_get_hyp_resources_resp {
+	u32 n_entries;
+	struct gh_rm_hyp_resource entries[];
+} __packed;
+
+/* Call: SET_BOOT_CONTEXT */
+struct gh_vm_set_boot_context_req {
+	u16 vmid;
+	u8 reg_set;
+	u8 reg_idx;
+	u32 val_low;
+	u32 val_high;
+} __packed;
+
 int gh_rm_call(u32 message_id, void *req_buff, size_t req_buff_size,
 		void **resp_buf, size_t *resp_buff_size);
 
diff --git a/drivers/virt/gunyah/rsc_mgr_rpc.c b/drivers/virt/gunyah/rsc_mgr_rpc.c
new file mode 100644
index 000000000000..33d27690c16e
--- /dev/null
+++ b/drivers/virt/gunyah/rsc_mgr_rpc.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) "gh_rsc_mgr: " fmt
+
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/printk.h>
+#include <linux/gunyah_rsc_mgr.h>
+
+#include "rsc_mgr.h"
+
+/*
+ * Several RM calls take only a VMID as a parameter and give only standard
+ * response back. Deduplicate boilerplate code by using this common call.
+ */
+static int gh_rm_common_vmid_call(u32 message_id, u16 vmid)
+{
+	void *resp = NULL;
+	struct gh_vm_common_vmid_req req_payload = {
+		.vmid = vmid,
+	};
+	size_t resp_size;
+	int ret;
+
+	ret = gh_rm_call(message_id, &req_payload, sizeof(req_payload), &resp, &resp_size);
+	if (!ret)
+		kfree(resp);
+
+	WARN_ON(!ret && resp_size);
+
+	return ret;
+}
+
+/**
+ * gh_rm_alloc_vmid() - Allocate a new VM in Gunyah. Returns the VM identifier.
+ * @vmid: Use GH_VMID_INVAL to dynamically allocate a VM. A reserved VMID can also be requested
+ *        for a special-purpose platform-defined VM.
+ *
+ * Returns - the allocated VMID or negative value on error
+ */
+int gh_rm_alloc_vmid(u16 vmid)
+{
+	void *resp;
+	struct gh_vm_common_vmid_req req_payload = {
+		.vmid = vmid,
+	};
+	struct gh_vm_common_vmid_req *resp_payload;
+	size_t resp_size;
+	int ret;
+
+	if (vmid == GH_VMID_INVAL)
+		vmid = 0;
+
+	ret = gh_rm_call(GH_RM_RPC_VM_ALLOC_VMID, &req_payload, sizeof(req_payload), &resp,
+			&resp_size);
+	if (ret)
+		return ret;
+
+	if (!vmid) {
+		if (resp_size != sizeof(*resp_payload)) {
+			pr_warn("Incorrect response size for ALLOC_VMID: %lu\n", resp_size);
+			ret = -EINVAL;
+		} else {
+			resp_payload = resp;
+			ret = resp_payload->vmid;
+		}
+	} else if (resp_size) {
+		pr_warn("Received unexpected payload for ALLOC_VMID: %lu\n", resp_size);
+	}
+	kfree(resp);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_alloc_vmid);
+
+/**
+ * gh_rm_dealloc_vmid() - Dispose the VMID
+ * @vmid: VM identifier
+ */
+int gh_rm_dealloc_vmid(u16 vmid)
+{
+	return gh_rm_common_vmid_call(GH_RM_RPC_VM_DEALLOC_VMID, vmid);
+}
+EXPORT_SYMBOL_GPL(gh_rm_dealloc_vmid);
+
+/**
+ * gh_rm_vm_start() - Move the VM into "ready to run" state
+ * @vmid: VM identifier
+ *
+ * On VMs which use proxy scheduling, vcpu_run is needed to actually run the VM.
+ * On VMs which use Gunyah's scheduling, the vCPUs start executing in accordance with Gunyah
+ * scheduling policies.
+ */
+int gh_rm_vm_start(u16 vmid)
+{
+	return gh_rm_common_vmid_call(GH_RM_RPC_VM_START, vmid);
+}
+EXPORT_SYMBOL_GPL(gh_rm_vm_start);
+
+/**
+ * gh_rm_vm_stop() - Send a request to Resource Manager VM to stop a VM.
+ * @vmid: VM identifier
+ */
+int gh_rm_vm_stop(u16 vmid)
+{
+	struct gh_vm_stop_req req_payload = { 0 };
+	void *resp;
+	size_t resp_size;
+	int ret;
+
+	req_payload.vmid = vmid;
+
+	ret = gh_rm_call(GH_RM_RPC_VM_STOP, &req_payload, sizeof(req_payload), &resp, &resp_size);
+	if (ret)
+		return ret;
+	kfree(resp);
+
+	if (resp_size)
+		pr_warn("Received unexpected payload for VM_STOP: %lu\n", resp_size);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_vm_stop);
+
+int gh_rm_vm_configure(u16 vmid, enum gh_rm_vm_auth_mechanism auth_mechanism, u32 mem_handle,
+			u64 image_offset, u64 image_size, u64 dtb_offset, u64 dtb_size)
+{
+	struct gh_vm_config_image_req req_payload = { 0 };
+	void *resp;
+	size_t resp_size;
+	int ret;
+
+	req_payload.vmid = vmid;
+	req_payload.auth_mech = auth_mechanism;
+	req_payload.mem_handle = mem_handle;
+	req_payload.image_offset_low = image_offset;
+	req_payload.image_offset_high = image_offset >> 32;
+	req_payload.image_size_low = image_size;
+	req_payload.image_size_high = image_size >> 32;
+	req_payload.dtb_offset_low = dtb_offset;
+	req_payload.dtb_offset_high = dtb_offset >> 32;
+	req_payload.dtb_size_low = dtb_size;
+	req_payload.dtb_size_high = dtb_size >> 32;
+
+	ret = gh_rm_call(GH_RM_RPC_VM_CONFIG_IMAGE, &req_payload, sizeof(req_payload),
+			&resp, &resp_size);
+	if (ret)
+		return ret;
+	kfree(resp);
+
+	if (resp_size)
+		pr_warn("Received unexpected payload for VM_CONFIG_IMAGE: %lu\n", resp_size);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_vm_configure);
+
+/**
+ * gh_rm_vm_init() - Move the VM to initialized state.
+ * @vmid: VM identifier
+ *
+ * RM will allocate needed resources for the VM. After gh_rm_vm_init, gh_rm_get_hyp_resources()
+ * can be called to learn of the capabilities we can use with the new VM.
+ */
+int gh_rm_vm_init(u16 vmid)
+{
+	return gh_rm_common_vmid_call(GH_RM_RPC_VM_INIT, vmid);
+}
+EXPORT_SYMBOL_GPL(gh_rm_vm_init);
+
+/**
+ * gh_rm_get_hyp_resources() - Retrieve hypervisor resources (capabilities) associated with a VM
+ * @vmid: VMID of the other VM to get the resources of
+ * @resources: Set by gh_rm_get_hyp_resources and contains the returned hypervisor resources.
+ *
+ * Return: >=0 value indicates the number of gh_rm_hyp_resource entries filled into *resources
+ */
+ssize_t gh_rm_get_hyp_resources(u16 vmid, struct gh_rm_hyp_resource **resources)
+{
+	struct gh_vm_get_hyp_resources_resp *resp;
+	size_t resp_size;
+	int ret;
+	struct gh_vm_common_vmid_req req_payload = {0};
+
+	req_payload.vmid = vmid;
+
+	ret = gh_rm_call(GH_RM_RPC_VM_GET_HYP_RESOURCES,
+			 &req_payload, sizeof(req_payload),
+			 (void **)&resp, &resp_size);
+	if (ret)
+		return ret;
+
+	if (resp_size < sizeof(*resp) ||
+		(sizeof(*resp->entries) && (resp->n_entries > U32_MAX / sizeof(*resp->entries))) ||
+		(resp_size != sizeof(*resp) + (resp->n_entries * sizeof(*resp->entries)))) {
+		ret = -EIO;
+		goto out;
+	}
+
+	*resources = kmemdup(resp->entries, (resp->n_entries * sizeof(*resp->entries)), GFP_KERNEL);
+	ret = resp->n_entries;
+
+out:
+	kfree(resp);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_get_hyp_resources);
+
+/**
+ * gh_rm_get_vmid() - Retrieve VMID of this virtual machine
+ * @vmid: Filled with the VMID of this VM
+ */
+int gh_rm_get_vmid(u16 *vmid)
+{
+	void *resp;
+	size_t resp_size;
+	int ret;
+	int payload = 0;
+
+	ret = gh_rm_call(GH_RM_RPC_VM_GET_VMID, &payload, sizeof(payload), &resp, &resp_size);
+	if (ret)
+		return ret;
+
+	if (resp_size != sizeof(*vmid))
+		return -EIO;
+	*vmid = *(u16 *)resp;
+	kfree(resp);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_get_vmid);
+
+/**
+ * gh_rm_set_boot_context() - Set boot context of a VM
+ * @vmid: VM identifier
+ * @reg_set: Register Set
+ * @reg_idx: Index into the register set
+ * @value: Updated register value
+ */
+int gh_rm_set_boot_context(u16 vmid, u8 reg_set, u8 reg_idx, u64 value)
+{
+	struct gh_vm_set_boot_context_req req = { 0 };
+	int ret;
+	size_t resp_size;
+	void *resp;
+
+	req.vmid = vmid;
+	req.reg_set = reg_set;
+	req.reg_idx = reg_idx;
+	req.val_low = (value & 0xFFFFFFFF);
+	req.val_high = ((value >> 32) & 0xFFFFFFFF);
+
+	ret = gh_rm_call(GH_RM_RPC_VM_SET_BOOT_CONTEXT, &req, sizeof(req), &resp, &resp_size);
+	kfree(resp);
+
+	if (!ret && resp_size)
+		pr_warn("Received unexpected payload for SET_BOOT_CONTEXT: %lu\n", resp_size);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_set_boot_context);
diff --git a/include/linux/gunyah_rsc_mgr.h b/include/linux/gunyah_rsc_mgr.h
index 0eeb7202fa33..169497f894c8 100644
--- a/include/linux/gunyah_rsc_mgr.h
+++ b/include/linux/gunyah_rsc_mgr.h
@@ -25,6 +25,60 @@ struct gh_rm_notification {
 int gh_rm_register_notifier(struct notifier_block *nb);
 int gh_rm_unregister_notifier(struct notifier_block *nb);
 
+enum gh_rm_vm_status {
+	GH_RM_VM_STATUS_NO_STATE	= 0,
+	GH_RM_VM_STATUS_INIT		= 1,
+	GH_RM_VM_STATUS_READY		= 2,
+	GH_RM_VM_STATUS_RUNNING		= 3,
+	GH_RM_VM_STATUS_PAUSED		= 4,
+	GH_RM_VM_STATUS_LOAD		= 5,
+	GH_RM_VM_STATUS_AUTH		= 6,
+	GH_RM_VM_STATUS_INIT_FAILED	= 8,
+	GH_RM_VM_STATUS_EXITED		= 9,
+	GH_RM_VM_STATUS_RESETTING	= 10,
+	GH_RM_VM_STATUS_RESET		= 11,
+};
+
+/* RPC Calls */
+int gh_rm_alloc_vmid(u16 vmid);
+int gh_rm_dealloc_vmid(u16 vmid);
+int gh_rm_vm_start(u16 vmid);
+int gh_rm_vm_stop(u16 vmid);
+
+enum gh_rm_vm_auth_mechanism {
+	GH_RM_VM_AUTH_NONE		= 0,
+	GH_RM_VM_AUTH_QCOM_PIL_ELF	= 1,
+	GH_RM_VM_AUTH_QCOM_ANDROID_PVM	= 2,
+};
+
+int gh_rm_vm_configure(u16 vmid, enum gh_rm_vm_auth_mechanism auth_mechanism, u32 mem_handle,
+			u64 image_offset, u64 image_size, u64 dtb_offset, u64 dtb_size);
+int gh_rm_vm_init(u16 vmid);
+
+struct gh_rm_hyp_resource {
+	u8 type;
+	u8 reserved;
+	u16 partner_vmid;
+	u32 resource_handle;
+	u32 resource_label;
+	u32 cap_id_low;
+	u32 cap_id_high;
+	u32 virq_handle;
+	u32 virq;
+	u32 base_low;
+	u32 base_high;
+	u32 size_low;
+	u32 size_high;
+} __packed;
+
+ssize_t gh_rm_get_hyp_resources(u16 vmid, struct gh_rm_hyp_resource **resources);
+int gh_rm_get_vmid(u16 *vmid);
+
+#define GH_RM_BOOT_CONTEXT_REG_SET_REGISTERS	0
+#define GH_RM_BOOT_CONTEXT_REG_SET_PC		1
+#define GH_RM_BOOT_CONTEXT_REG_SET_SP_ELx	2
+int gh_rm_set_boot_context(u16 vmid, u8 reg_set, u8 reg_idx, u64 value);
+
 #define GH_RM_DEVICE_VM_MGR		"vm_mgr"
 
 struct gh_rm_driver {
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (11 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 12/21] gunyah: rsc_mgr: Add VM lifecycle RPC Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-11-02  5:14   ` Greg Kroah-Hartman
  2022-11-02  7:31   ` Arnd Bergmann
  2022-10-26 18:58 ` [PATCH v6 14/21] gunyah: rsc_mgr: Add RPC for sharing memory Elliot Berman
                   ` (7 subsequent siblings)
  20 siblings, 2 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Gunyah VM manager is a kernel moduel which exposes an interface to
Gunyah userspace to load, run, and interact with other Gunyah virtual
machines. The interface is a character device at /dev/gunyah.

Add a basic VM manager driver. Upcoming patches will add more ioctls
into this driver.

Co-developed-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 .../userspace-api/ioctl/ioctl-number.rst      |   1 +
 drivers/virt/gunyah/Kconfig                   |   8 +
 drivers/virt/gunyah/Makefile                  |   3 +
 drivers/virt/gunyah/vm_mgr.c                  | 152 ++++++++++++++++++
 drivers/virt/gunyah/vm_mgr.h                  |  17 ++
 include/uapi/linux/gunyah.h                   |  23 +++
 6 files changed, 204 insertions(+)
 create mode 100644 drivers/virt/gunyah/vm_mgr.c
 create mode 100644 drivers/virt/gunyah/vm_mgr.h
 create mode 100644 include/uapi/linux/gunyah.h

diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index 5f81e2a24a5c..1fa1a5877bd7 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -136,6 +136,7 @@ Code  Seq#    Include File                                           Comments
 'F'   DD     video/sstfb.h                                           conflict!
 'G'   00-3F  drivers/misc/sgi-gru/grulib.h                           conflict!
 'G'   00-0F  xen/gntalloc.h, xen/gntdev.h                            conflict!
+'G'   40-4f  linux/gunyah.h
 'H'   00-7F  linux/hiddev.h                                          conflict!
 'H'   00-0F  linux/hidraw.h                                          conflict!
 'H'   01     linux/mei.h                                             conflict!
diff --git a/drivers/virt/gunyah/Kconfig b/drivers/virt/gunyah/Kconfig
index 4de88d80aa7b..c5d239159118 100644
--- a/drivers/virt/gunyah/Kconfig
+++ b/drivers/virt/gunyah/Kconfig
@@ -25,3 +25,11 @@ config GUNYAH_RESORUCE_MANAGER
 
 	  Say Y/M here if unsure.
 
+config GUNYAH_VM_MANAGER
+	tristate "Gunyah VM Manager"
+	depends on GUNYAH_RESORUCE_MANAGER
+	help
+	  Gunyah VM manager is a kernel module which exposes an interface to
+	  Gunyah userspace to load, run, and interact with other Gunyah
+	  virtual machines. This module is required to launch other virtual
+	  machines.
diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile
index 09c1bbd28b48..a69b1e2273af 100644
--- a/drivers/virt/gunyah/Makefile
+++ b/drivers/virt/gunyah/Makefile
@@ -2,3 +2,6 @@ obj-$(CONFIG_GUNYAH) += gunyah.o
 
 gunyah_rsc_mgr-y += rsc_mgr.o rsc_mgr_rpc.o rsc_mgr_bus.o
 obj-$(CONFIG_GUNYAH_RESORUCE_MANAGER) += gunyah_rsc_mgr.o
+
+gunyah_vm_mgr-y += vm_mgr.o
+obj-$(CONFIG_GUNYAH_VM_MANAGER) += gunyah_vm_mgr.o
diff --git a/drivers/virt/gunyah/vm_mgr.c b/drivers/virt/gunyah/vm_mgr.c
new file mode 100644
index 000000000000..c48853dba11d
--- /dev/null
+++ b/drivers/virt/gunyah/vm_mgr.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) "gh_vm_mgr: " fmt
+
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
+#include <linux/gunyah_rsc_mgr.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+
+#include <uapi/linux/gunyah.h>
+
+#include "vm_mgr.h"
+
+static __must_check struct gunyah_vm *gunyah_vm_alloc(void)
+{
+	struct gunyah_vm *ghvm;
+	int ret;
+
+	ret = gh_rm_alloc_vmid(0);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	ghvm = kzalloc(sizeof(*ghvm), GFP_KERNEL);
+	if (!ghvm)
+		return ghvm;
+
+	ghvm->vmid = ret;
+
+	return ghvm;
+}
+
+static long gh_vm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	long r;
+
+	switch (cmd) {
+	default:
+		r = -ENOTTY;
+		break;
+	}
+
+	return r;
+}
+
+static int gh_vm_release(struct inode *inode, struct file *filp)
+{
+	struct gunyah_vm *ghvm = filp->private_data;
+
+	kfree(ghvm);
+	return 0;
+}
+
+static const struct file_operations gh_vm_fops = {
+	.unlocked_ioctl = gh_vm_ioctl,
+	.release = gh_vm_release,
+	.llseek = noop_llseek,
+};
+
+static long gh_dev_ioctl_create_vm(unsigned long arg)
+{
+	struct gunyah_vm *ghvm;
+	struct file *file;
+	int fd, err;
+
+	/* arg reserved for future use. */
+	if (arg)
+		return -EINVAL;
+
+	ghvm = gunyah_vm_alloc();
+	if (IS_ERR_OR_NULL(ghvm))
+		return PTR_ERR(ghvm) ? : -ENOMEM;
+
+	fd = get_unused_fd_flags(O_CLOEXEC);
+	if (fd < 0) {
+		err = fd;
+		goto err_destroy_vm;
+	}
+
+	file = anon_inode_getfile("gunyah-vm", &gh_vm_fops, ghvm, O_RDWR);
+	if (IS_ERR(file)) {
+		err = PTR_ERR(file);
+		goto err_put_fd;
+	}
+
+	fd_install(fd, file);
+
+	return fd;
+
+err_put_fd:
+	put_unused_fd(fd);
+err_destroy_vm:
+	kfree(ghvm);
+	return err;
+}
+
+static long gh_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case GH_CREATE_VM:
+		return gh_dev_ioctl_create_vm(arg);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct file_operations gh_dev_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= gh_dev_ioctl,
+	.llseek		= noop_llseek,
+};
+
+static struct miscdevice gh_dev = {
+	.name		= "gunyah",
+	.minor		= MISC_DYNAMIC_MINOR,
+	.fops		= &gh_dev_fops,
+};
+
+static int vm_mgr_probe(struct device *dev)
+{
+	return misc_register(&gh_dev);
+}
+
+static int vm_mgr_remove(struct device *dev)
+{
+	misc_deregister(&gh_dev);
+
+	return 0;
+}
+
+static struct gunyah_rsc_mgr_device_id vm_mgr_ids[] = {
+	{ .name = GH_RM_DEVICE_VM_MGR },
+	{}
+};
+MODULE_DEVICE_TABLE(gunyah_rsc_mgr, vm_mgr_ids);
+
+static struct gh_rm_driver vm_mgr_drv = {
+	.drv = {
+		.name = KBUILD_MODNAME,
+		.probe = vm_mgr_probe,
+		.remove = vm_mgr_remove,
+	},
+	.id_table = vm_mgr_ids,
+};
+module_gh_rm_driver(vm_mgr_drv);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Gunyah VM Manager");
+
diff --git a/drivers/virt/gunyah/vm_mgr.h b/drivers/virt/gunyah/vm_mgr.h
new file mode 100644
index 000000000000..d306ff5eac82
--- /dev/null
+++ b/drivers/virt/gunyah/vm_mgr.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _GH_PRIV_VM_MGR_H
+#define _GH_PRIV_VM_MGR_H
+
+#include <linux/gunyah_rsc_mgr.h>
+
+#include <uapi/linux/gunyah.h>
+
+struct gunyah_vm {
+	u16 vmid;
+};
+
+#endif
diff --git a/include/uapi/linux/gunyah.h b/include/uapi/linux/gunyah.h
new file mode 100644
index 000000000000..37ea6bd4c2fd
--- /dev/null
+++ b/include/uapi/linux/gunyah.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _UAPI_LINUX_GUNYAH
+#define _UAPI_LINUX_GUNYAH
+
+/*
+ * Userspace interface for /dev/gunyah - gunyah based virtual machine
+ */
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define GH_IOCTL_TYPE			'G'
+
+/*
+ * ioctls for /dev/gunyah fds:
+ */
+#define GH_CREATE_VM			_IO(GH_IOCTL_TYPE, 0x40) /* Returns a Gunyah VM fd */
+
+#endif
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 14/21] gunyah: rsc_mgr: Add RPC for sharing memory
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (12 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 15/21] gunyah: vm_mgr: Add/remove user memory regions Elliot Berman
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Gunyah resource manager provides API to manipulate stage 2 page tables.
Manipulations are represented as a memory parcel. Memory parcels
describe a list of memory regions (intermediate physical address and
size), a list of new permissions for VMs, and the memory type (DDR or
MMIO). Memory parcels are uniquely identified by a handle allocated by
Gunyah. There are a few types of memory parcel sharing which Gunyah
supports:

 - Sharing: the guest and host VM both have access
 - Lending: only the guest has access; host VM loses access
 - Donating: Permanently lent (not reclaimed even if guest shuts down)

Memory parcels that have been shared or lent can be reclaimed by the
host via an additional call. The reclaim operation restores the original
access the host VM had to the memory parcel and removes the access to
other VM.

One point to note that memory parcels don't describe where in the guest
VM the memory parcel should reside. The guest VM must accept the memory
parcel either explicitly via a "gh_rm_mem_accept" call (not introduced
here) or be configured to accept it automatically at boot. As the guest
VM accepts the memory parcel, it also mentions the IPA it wants to place
memory parcel.

Co-developed-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/virt/gunyah/rsc_mgr.h     |  44 +++++++
 drivers/virt/gunyah/rsc_mgr_rpc.c | 204 ++++++++++++++++++++++++++++++
 include/linux/gunyah_rsc_mgr.h    |  47 +++++++
 3 files changed, 295 insertions(+)

diff --git a/drivers/virt/gunyah/rsc_mgr.h b/drivers/virt/gunyah/rsc_mgr.h
index 247664b8b008..f6ed58405ef4 100644
--- a/drivers/virt/gunyah/rsc_mgr.h
+++ b/drivers/virt/gunyah/rsc_mgr.h
@@ -28,6 +28,12 @@
 #define GH_RM_ERROR_IRQ_INUSE		0x10
 #define GH_RM_ERROR_IRQ_RELEASED	0x11
 
+/* Message IDs: Memory Management */
+#define GH_RM_RPC_MEM_LEND			0x51000012
+#define GH_RM_RPC_MEM_SHARE			0x51000013
+#define GH_RM_RPC_MEM_RECLAIM			0x51000015
+#define GH_RM_RPC_MEM_APPEND			0x51000018
+
 /* Message IDs: VM Management */
 #define GH_RM_RPC_VM_ALLOC_VMID			0x56000001
 #define GH_RM_RPC_VM_DEALLOC_VMID		0x56000002
@@ -45,6 +51,44 @@ struct gh_vm_common_vmid_req {
 	u16 reserved0;
 } __packed;
 
+/* Call: MEM_LEND, MEM_SHARE */
+struct gh_mem_share_req_header {
+	u8 mem_type;
+	u8 reserved0;
+#define GH_MEM_SHARE_REQ_FLAGS_APPEND		BIT(1)
+	u8 flags;
+	u8 reserved1;
+	u32 label;
+} __packed;
+
+struct gh_mem_share_req_acl_section {
+	u32 n_entries;
+	struct gh_rm_mem_acl_entry entries[];
+};
+
+struct gh_mem_share_req_mem_section {
+	u16 n_entries;
+	u16 reserved0;
+	struct gh_rm_mem_entry entries[];
+};
+
+/* Call: MEM_RELEASE */
+struct gh_mem_release_req {
+	u32 mem_handle;
+	u8 flags;
+	u16 reserved0;
+	u8 reserved1;
+} __packed;
+
+/* Call: MEM_APPEND */
+struct gh_mem_append_req_header {
+	u32 mem_handle;
+#define GH_MEM_APPEND_REQ_FLAGS_END	BIT(0)
+	u8 flags;
+	u16 reserved0;
+	u8 reserved1;
+} __packed;
+
 /* Call: VM_STOP */
 struct gh_vm_stop_req {
 	u16 vmid;
diff --git a/drivers/virt/gunyah/rsc_mgr_rpc.c b/drivers/virt/gunyah/rsc_mgr_rpc.c
index 33d27690c16e..17f88c3d5726 100644
--- a/drivers/virt/gunyah/rsc_mgr_rpc.c
+++ b/drivers/virt/gunyah/rsc_mgr_rpc.c
@@ -12,6 +12,8 @@
 
 #include "rsc_mgr.h"
 
+#define GH_RM_MAX_MEM_ENTRIES	512
+
 /*
  * Several RM calls take only a VMID as a parameter and give only standard
  * response back. Deduplicate boilerplate code by using this common call.
@@ -34,6 +36,208 @@ static int gh_rm_common_vmid_call(u32 message_id, u16 vmid)
 	return ret;
 }
 
+static int _gh_rm_mem_append(u32 mem_handle, bool end_append,
+			struct gh_rm_mem_entry *mem_entries, size_t n_mem_entries)
+{
+	size_t msg_size = 0;
+	void *msg;
+	struct gh_mem_append_req_header *req_header;
+	struct gh_mem_share_req_mem_section *mem_section;
+	void *resp;
+	size_t resp_size;
+	int ret;
+
+	msg_size += sizeof(struct gh_mem_append_req_header);
+	msg_size += offsetof(struct gh_mem_share_req_mem_section, entries[n_mem_entries]);
+
+	msg = kzalloc(msg_size, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	req_header = msg;
+	mem_section = (void *)req_header + sizeof(struct gh_mem_append_req_header);
+
+	req_header->mem_handle = mem_handle;
+	if (end_append)
+		req_header->flags |= GH_MEM_APPEND_REQ_FLAGS_END;
+
+	mem_section->n_entries = n_mem_entries;
+	memcpy(mem_section->entries, mem_entries, sizeof(*mem_entries) * n_mem_entries);
+
+	ret = gh_rm_call(GH_RM_RPC_MEM_APPEND, msg, msg_size, &resp, &resp_size);
+	if (ret)
+		return ret;
+	kfree(resp);
+
+	if (resp_size)
+		pr_warn("Received unexpected payload for MEM_APPEND: %lu\n", resp_size);
+
+	return ret;
+}
+
+static int gh_rm_mem_append(u32 mem_handle, bool allow_append,
+			struct gh_rm_mem_entry *mem_entries, size_t n_mem_entries)
+{
+	bool end_append;
+	size_t n;
+	int ret = 0;
+
+	while (n_mem_entries) {
+		if (n_mem_entries > GH_RM_MAX_MEM_ENTRIES) {
+			end_append = false;
+			n = GH_RM_MAX_MEM_ENTRIES;
+		} else {
+			end_append = !allow_append;
+			n = n_mem_entries;
+		}
+
+		ret = _gh_rm_mem_append(mem_handle, end_append, mem_entries, n);
+		if (ret)
+			break;
+
+		mem_entries += n;
+		n_mem_entries -= n;
+	}
+
+	return ret;
+}
+
+static int gh_rm_mem_lend_common(u32 message_id, struct gh_rm_mem_parcel *p)
+{
+	size_t msg_size = 0, initial_n_mem_entries = p->n_mem_entries;
+	void *msg, *resp;
+	struct gh_mem_share_req_header *req_header;
+	struct gh_mem_share_req_acl_section *acl_section;
+	struct gh_mem_share_req_mem_section *mem_section;
+	u32 *mem_attr_section;
+	size_t resp_size;
+	int ret;
+
+	if (!p->acl_entries || !p->n_acl_entries || !p->mem_entries || !p->n_mem_entries ||
+	    p->n_acl_entries > U8_MAX)
+		return -EINVAL;
+
+	if (initial_n_mem_entries > GH_RM_MAX_MEM_ENTRIES)
+		initial_n_mem_entries = GH_RM_MAX_MEM_ENTRIES;
+
+	/* The format of the message goes:
+	 * request header
+	 * ACL entries (which VMs get what kind of access to this memory parcel)
+	 * Memory entries (list of memory regions to share)
+	 * Memory attributes (currently unused, we'll hard-code the size to 0)
+	 */
+	msg_size += sizeof(struct gh_mem_share_req_header);
+	msg_size += offsetof(struct gh_mem_share_req_acl_section, entries[p->n_acl_entries]);
+	msg_size += offsetof(struct gh_mem_share_req_mem_section, entries[initial_n_mem_entries]);
+	msg_size += sizeof(u32); /* for memory attributes, currently unused */
+
+	msg = kzalloc(msg_size, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	req_header = msg;
+	acl_section = (void *)req_header + sizeof(*req_header);
+	mem_section = (void *)acl_section + offsetof(struct gh_mem_share_req_acl_section,
+						entries[p->n_acl_entries]);
+	mem_attr_section = (void *)mem_section + offsetof(struct gh_mem_share_req_mem_section,
+						entries[initial_n_mem_entries]);
+
+	req_header->mem_type = p->mem_type;
+	if (initial_n_mem_entries != p->n_mem_entries)
+		req_header->flags |= GH_MEM_SHARE_REQ_FLAGS_APPEND;
+	req_header->label = p->label;
+
+	acl_section->n_entries = p->n_acl_entries;
+	memcpy(acl_section->entries, p->acl_entries, sizeof(*(p->acl_entries)) * p->n_acl_entries);
+
+	mem_section->n_entries = initial_n_mem_entries;
+	memcpy(mem_section->entries, p->mem_entries,
+		sizeof(*(p->mem_entries)) * initial_n_mem_entries);
+
+	/* Set n_entries for memory attribute section to 0 */
+	*mem_attr_section = 0;
+
+	ret = gh_rm_call(message_id, msg, msg_size, &resp, &resp_size);
+	if (ret)
+		return ret;
+
+	if (resp_size != sizeof(u32)) {
+		ret = -EIO;
+		goto out;
+	}
+
+	p->mem_handle = *(u32 *)resp;
+
+	if (initial_n_mem_entries != p->n_mem_entries) {
+		ret = gh_rm_mem_append(p->mem_handle, false, &p->mem_entries[initial_n_mem_entries],
+					p->n_mem_entries - initial_n_mem_entries);
+		if (ret)
+			gh_rm_mem_reclaim(p);
+	}
+
+out:
+	kfree(resp);
+	return ret;
+}
+
+/**
+ * gh_rm_mem_lend() - Lend memory to other virtual machines.
+ * @parcel: Package the memory information of the memory to be lent.
+ *
+ * Returns - 0 on success; negative value on failure
+ *
+ * Lending removes Linux's access to the memory while the memory parcel is lent.
+ */
+int gh_rm_mem_lend(struct gh_rm_mem_parcel *parcel)
+{
+	return gh_rm_mem_lend_common(GH_RM_RPC_MEM_LEND, parcel);
+}
+EXPORT_SYMBOL_GPL(gh_rm_mem_lend);
+
+
+/**
+ * gh_rm_mem_share() - Share memory with other virtual machines.
+ * @parcel: Package the memory information of the memory to be shared.
+ *
+ * Returns - 0 on success; negative value on failure
+ *
+ * Sharing keeps Linux's access to the memory while the memory parcel is shared.
+ */
+int gh_rm_mem_share(struct gh_rm_mem_parcel *parcel)
+{
+	return gh_rm_mem_lend_common(GH_RM_RPC_MEM_SHARE, parcel);
+}
+EXPORT_SYMBOL_GPL(gh_rm_mem_share);
+
+/**
+ * gh_rm_mem_reclaim() - Reclaim a memory parcel
+ * @parcel: Package the memory information of the memory to be reclaimed.
+ *
+ * Returns - 0 on success; negative value on failure
+ *
+ * RM maps the associated memory back into the stage-2 page tables of the owner VM.
+ */
+int gh_rm_mem_reclaim(struct gh_rm_mem_parcel *parcel)
+{
+	struct gh_mem_release_req req = {
+		.mem_handle = parcel->mem_handle,
+	};
+	size_t resp_size;
+	void *resp;
+	int ret;
+
+	ret = gh_rm_call(GH_RM_RPC_MEM_RECLAIM, &req, sizeof(req), &resp, &resp_size);
+	if (ret)
+		return ret;
+	kfree(resp);
+
+	if (resp_size)
+		pr_warn("Received unexpected payload for MEM_RECLAIM: %lu\n", resp_size);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_mem_reclaim);
+
 /**
  * gh_rm_alloc_vmid() - Allocate a new VM in Gunyah. Returns the VM identifier.
  * @vmid: Use GH_VMID_INVAL to dynamically allocate a VM. A reserved VMID can also be requested
diff --git a/include/linux/gunyah_rsc_mgr.h b/include/linux/gunyah_rsc_mgr.h
index 169497f894c8..78d516032f6a 100644
--- a/include/linux/gunyah_rsc_mgr.h
+++ b/include/linux/gunyah_rsc_mgr.h
@@ -13,6 +13,7 @@
 #include <linux/mod_devicetable.h>
 
 #define GH_VMID_INVAL	U16_MAX
+#define GH_MEM_HANDLE_INVAL	U32_MAX
 
 /* Gunyah recognizes VMID0 as an alias to the current VM's ID */
 #define GH_VMID_SELF			0
@@ -39,7 +40,53 @@ enum gh_rm_vm_status {
 	GH_RM_VM_STATUS_RESET		= 11,
 };
 
+struct gh_rm_mem_acl_entry {
+	u16 vmid;
+#define GH_RM_ACL_X		BIT(0)
+#define GH_RM_ACL_W		BIT(1)
+#define GH_RM_ACL_R		BIT(2)
+	u8 perms;
+	u8 reserved;
+} __packed;
+
+struct gh_rm_mem_entry {
+	u64 ipa_base;
+	u64 size;
+} __packed;
+
+enum gh_rm_mem_type {
+	GH_RM_MEM_TYPE_NORMAL	= 0,
+	GH_RM_MEM_TYPE_IO	= 1,
+};
+
+/*
+ * struct gh_rm_mem_parcel - Package info about memory to be lent/shared/donated/reclaimed
+ * @mem_type: The type of memory: normal (DDR) or IO
+ * @label: An client-specified identifier which can be used by the other VMs to identify the purpose
+ *         of the memory parcel.
+ * @acl_entries: An array of access control entries. Each entry specifies a VM and what access
+ *               is allowed for the memory parcel.
+ * @n_acl_entries: Count of the number of entries in the `acl_entries` array.
+ * @mem_entries: An list of regions to be associated with the memory parcel. Addresses should be
+ *               (intermediate) physical addresses from Linux's perspective.
+ * @n_mem_entries: Count of the number of entries in the `mem_entries` array.
+ * @mem_handle: On success, filled with memory handle that RM allocates for this memory parcel
+ */
+struct gh_rm_mem_parcel {
+	enum gh_rm_mem_type mem_type;
+	u32 label;
+	size_t n_acl_entries;
+	struct gh_rm_mem_acl_entry *acl_entries;
+	size_t n_mem_entries;
+	struct gh_rm_mem_entry *mem_entries;
+	u32 mem_handle;
+};
+
 /* RPC Calls */
+int gh_rm_mem_lend(struct gh_rm_mem_parcel *parcel);
+int gh_rm_mem_share(struct gh_rm_mem_parcel *parcel);
+int gh_rm_mem_reclaim(struct gh_rm_mem_parcel *parcel);
+
 int gh_rm_alloc_vmid(u16 vmid);
 int gh_rm_dealloc_vmid(u16 vmid);
 int gh_rm_vm_start(u16 vmid);
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 15/21] gunyah: vm_mgr: Add/remove user memory regions
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (13 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 14/21] gunyah: rsc_mgr: Add RPC for sharing memory Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 16/21] gunyah: vm_mgr: Add ioctls to support basic non-proxy VM boot Elliot Berman
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

When launching a virtual machine, Gunyah userspace allocates memory for
the guest and informs Gunyah about these memory regions through
SET_USER_MEMORY_REGION ioctl.

Co-developed-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/virt/gunyah/Makefile    |   2 +-
 drivers/virt/gunyah/vm_mgr.c    |  45 +++++++
 drivers/virt/gunyah/vm_mgr.h    |  26 ++++
 drivers/virt/gunyah/vm_mgr_mm.c | 226 ++++++++++++++++++++++++++++++++
 include/uapi/linux/gunyah.h     |  22 ++++
 5 files changed, 320 insertions(+), 1 deletion(-)
 create mode 100644 drivers/virt/gunyah/vm_mgr_mm.c

diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile
index a69b1e2273af..af1817dfeaf4 100644
--- a/drivers/virt/gunyah/Makefile
+++ b/drivers/virt/gunyah/Makefile
@@ -3,5 +3,5 @@ obj-$(CONFIG_GUNYAH) += gunyah.o
 gunyah_rsc_mgr-y += rsc_mgr.o rsc_mgr_rpc.o rsc_mgr_bus.o
 obj-$(CONFIG_GUNYAH_RESORUCE_MANAGER) += gunyah_rsc_mgr.o
 
-gunyah_vm_mgr-y += vm_mgr.o
+gunyah_vm_mgr-y += vm_mgr.o vm_mgr_mm.o
 obj-$(CONFIG_GUNYAH_VM_MANAGER) += gunyah_vm_mgr.o
diff --git a/drivers/virt/gunyah/vm_mgr.c b/drivers/virt/gunyah/vm_mgr.c
index c48853dba11d..a993e81a20e2 100644
--- a/drivers/virt/gunyah/vm_mgr.c
+++ b/drivers/virt/gunyah/vm_mgr.c
@@ -30,14 +30,55 @@ static __must_check struct gunyah_vm *gunyah_vm_alloc(void)
 
 	ghvm->vmid = ret;
 
+	mutex_init(&ghvm->mm_lock);
+	INIT_LIST_HEAD(&ghvm->memory_mappings);
+
 	return ghvm;
 }
 
 static long gh_vm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
+	struct gunyah_vm *ghvm = filp->private_data;
+	void __user *argp = (void __user *)arg;
 	long r;
 
 	switch (cmd) {
+	case GH_VM_SET_USER_MEM_REGION: {
+		struct gunyah_vm_memory_mapping *mapping;
+		struct gh_userspace_memory_region region;
+
+		r = -EFAULT;
+		if (copy_from_user(&region, argp, sizeof(region)))
+			break;
+
+		r = -EINVAL;
+		/* All other flag bits are reserved for future use */
+		if (region.flags & ~(GH_MEM_ALLOW_READ | GH_MEM_ALLOW_WRITE | GH_MEM_ALLOW_EXEC |
+			GH_MEM_LENT))
+			break;
+
+
+		if (region.memory_size) {
+			r = 0;
+			mapping = gh_vm_mem_mapping_alloc(ghvm, &region);
+			if (IS_ERR(mapping)) {
+				r = PTR_ERR(mapping);
+				break;
+			}
+		} else {
+			mapping = gh_vm_mem_mapping_find(ghvm, region.label);
+			if (IS_ERR(mapping)) {
+				r = PTR_ERR(mapping);
+				break;
+			}
+			r = 0;
+			if (!mapping)
+				break;
+			gh_vm_mem_mapping_reclaim(ghvm, mapping);
+			kfree(mapping);
+		}
+		break;
+	}
 	default:
 		r = -ENOTTY;
 		break;
@@ -49,7 +90,11 @@ static long gh_vm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 static int gh_vm_release(struct inode *inode, struct file *filp)
 {
 	struct gunyah_vm *ghvm = filp->private_data;
+	struct gunyah_vm_memory_mapping *mapping, *tmp;
 
+	list_for_each_entry_safe(mapping, tmp, &ghvm->memory_mappings, list) {
+		gh_vm_mem_mapping_reclaim(ghvm, mapping);
+	}
 	kfree(ghvm);
 	return 0;
 }
diff --git a/drivers/virt/gunyah/vm_mgr.h b/drivers/virt/gunyah/vm_mgr.h
index d306ff5eac82..ab1f0cb0758a 100644
--- a/drivers/virt/gunyah/vm_mgr.h
+++ b/drivers/virt/gunyah/vm_mgr.h
@@ -7,11 +7,37 @@
 #define _GH_PRIV_VM_MGR_H
 
 #include <linux/gunyah_rsc_mgr.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
 
 #include <uapi/linux/gunyah.h>
 
+enum gunyah_vm_mem_share_type {
+	VM_MEM_SHARE,
+	VM_MEM_LEND,
+};
+
+struct gunyah_vm_memory_mapping {
+	struct list_head list;
+	enum gunyah_vm_mem_share_type share_type;
+	struct gh_rm_mem_parcel parcel;
+
+	__u64 guest_phys_addr;
+	__u32 mem_size;
+	struct page **pages;
+	unsigned long npages;
+};
+
 struct gunyah_vm {
 	u16 vmid;
+
+	struct mutex mm_lock;
+	struct list_head memory_mappings;
 };
 
+struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_alloc(struct gunyah_vm *ghvm,
+							struct gh_userspace_memory_region *region);
+void gh_vm_mem_mapping_reclaim(struct gunyah_vm *ghvm, struct gunyah_vm_memory_mapping *mapping);
+struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_find(struct gunyah_vm *ghvm, u32 label);
+
 #endif
diff --git a/drivers/virt/gunyah/vm_mgr_mm.c b/drivers/virt/gunyah/vm_mgr_mm.c
new file mode 100644
index 000000000000..a5a57a38ee09
--- /dev/null
+++ b/drivers/virt/gunyah/vm_mgr_mm.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) "gh_vm_mgr: " fmt
+
+#include <linux/gunyah_rsc_mgr.h>
+#include <linux/mm.h>
+
+#include <uapi/linux/gunyah.h>
+
+#include "vm_mgr.h"
+
+static inline bool page_contiguous(phys_addr_t p, phys_addr_t t)
+{
+	return t - p == PAGE_SIZE;
+}
+
+static struct gunyah_vm_memory_mapping *__gh_vm_mem_mapping_find(struct gunyah_vm *ghvm, u32 label)
+{
+	struct gunyah_vm_memory_mapping *mapping;
+
+
+	list_for_each_entry(mapping, &ghvm->memory_mappings, list)
+		if (mapping->parcel.label == label)
+			return mapping;
+
+	return NULL;
+}
+
+void gh_vm_mem_mapping_reclaim(struct gunyah_vm *ghvm, struct gunyah_vm_memory_mapping *mapping)
+{
+	int i, ret = 0;
+
+	if (mapping->parcel.mem_handle != GH_MEM_HANDLE_INVAL) {
+		down_read(&ghvm->status_lock);
+		if (mapping->parcel.mem_handle == ghvm->primary_mem_handle &&
+			ghvm->vm_status == GH_RM_VM_STATUS_NO_STATE)
+			ghvm->primary_mem_handle = 0;
+		up_read(&ghvm->status_lock);
+		ret = gh_rm_mem_reclaim(&mapping->parcel);
+		if (ret)
+			pr_warn("Failed to reclaim memory parcel for label %d: %d\n",
+				mapping->parcel.label, ret);
+	}
+
+	if (!ret)
+		for (i = 0; i < mapping->npages; i++)
+			unpin_user_page(mapping->pages[i]);
+
+	kfree(mapping->pages);
+	kfree(mapping->parcel.acl_entries);
+	kfree(mapping->parcel.mem_entries);
+
+	mutex_lock(&ghvm->mm_lock);
+	list_del(&mapping->list);
+	mutex_unlock(&ghvm->mm_lock);
+}
+
+struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_find(struct gunyah_vm *ghvm, u32 label)
+{
+	struct gunyah_vm_memory_mapping *mapping;
+	int ret;
+
+	ret = mutex_lock_interruptible(&ghvm->mm_lock);
+	if (ret)
+		return ERR_PTR(ret);
+	mapping = __gh_vm_mem_mapping_find(ghvm, label);
+	mutex_unlock(&ghvm->mm_lock);
+	return mapping;
+}
+
+struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_alloc(struct gunyah_vm *ghvm,
+							struct gh_userspace_memory_region *region)
+{
+	phys_addr_t curr_page, prev_page;
+	struct gunyah_vm_memory_mapping *mapping, *tmp_mapping;
+	struct gh_rm_mem_entry *mem_entries;
+	int i, j, pinned, ret = 0;
+	struct gh_rm_mem_parcel *parcel;
+
+	if (!region->memory_size || !PAGE_ALIGNED(region->memory_size) ||
+		!PAGE_ALIGNED(region->userspace_addr))
+		return ERR_PTR(-EINVAL);
+
+	ret = mutex_lock_interruptible(&ghvm->mm_lock);
+	if (ret)
+		return ERR_PTR(ret);
+	mapping = __gh_vm_mem_mapping_find(ghvm, region->label);
+	if (mapping) {
+		mapping = ERR_PTR(-EEXIST);
+		goto unlock;
+	}
+
+	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+	if (!mapping) {
+		mapping = ERR_PTR(-ENOMEM);
+		goto unlock;
+	}
+
+	mapping->parcel.label = region->label;
+	mapping->guest_phys_addr = region->guest_phys_addr;
+	mapping->npages = region->memory_size >> PAGE_SHIFT;
+	parcel = &mapping->parcel;
+	parcel->mem_handle = GH_MEM_HANDLE_INVAL; /* to be filled later by mem_share/mem_lend */
+	parcel->mem_type = GH_RM_MEM_TYPE_NORMAL;
+
+	/* Check for overlap */
+	list_for_each_entry(tmp_mapping, &ghvm->memory_mappings, list) {
+		if (!((mapping->guest_phys_addr + (mapping->npages << PAGE_SHIFT) <=
+			tmp_mapping->guest_phys_addr) ||
+			(mapping->guest_phys_addr >=
+			tmp_mapping->guest_phys_addr + (tmp_mapping->npages << PAGE_SHIFT)))) {
+			ret = -EEXIST;
+			goto unlock;
+		}
+	}
+
+	list_add(&mapping->list, &ghvm->memory_mappings);
+unlock:
+	mutex_unlock(&ghvm->mm_lock);
+	if (ret)
+		goto free_mapping;
+
+	mapping->pages = kcalloc(mapping->npages, sizeof(*mapping->pages), GFP_KERNEL);
+	if (!mapping->pages) {
+		ret = -ENOMEM;
+		goto reclaim;
+	}
+
+	pinned = pin_user_pages_fast(region->userspace_addr, mapping->npages,
+					FOLL_WRITE | FOLL_LONGTERM, mapping->pages);
+	if (pinned < 0) {
+		ret = pinned;
+		goto reclaim;
+	} else if (pinned != mapping->npages) {
+		ret = -EFAULT;
+		mapping->npages = pinned; /* update npages for reclaim */
+		goto reclaim;
+	}
+
+	if (region->flags & GH_MEM_LENT) {
+		parcel->n_acl_entries = 1;
+		mapping->share_type = VM_MEM_LEND;
+	} else {
+		parcel->n_acl_entries = 2;
+		mapping->share_type = VM_MEM_SHARE;
+	}
+	parcel->acl_entries = kcalloc(parcel->n_acl_entries,
+						sizeof(*parcel->acl_entries),
+						GFP_KERNEL);
+	if (!parcel->acl_entries) {
+		ret = -ENOMEM;
+		goto reclaim;
+	}
+
+	parcel->acl_entries[0].vmid = ghvm->vmid;
+	if (region->flags & GH_MEM_ALLOW_READ)
+		parcel->acl_entries[0].perms |= GH_RM_ACL_R;
+	if (region->flags & GH_MEM_ALLOW_WRITE)
+		parcel->acl_entries[0].perms |= GH_RM_ACL_W;
+	if (region->flags & GH_MEM_ALLOW_EXEC)
+		parcel->acl_entries[0].perms |= GH_RM_ACL_X;
+
+	if (mapping->share_type == VM_MEM_SHARE) {
+		ret = gh_rm_get_vmid(&parcel->acl_entries[1].vmid);
+		if (ret)
+			goto reclaim;
+		/* Host assumed to have all these permissions. Gunyah will not
+		 * grant new permissions if host actually had less than RWX
+		 */
+		parcel->acl_entries[1].perms |= GH_RM_ACL_R | GH_RM_ACL_W | GH_RM_ACL_X;
+	}
+
+	mem_entries = kcalloc(mapping->npages, sizeof(*mem_entries), GFP_KERNEL);
+	if (!mem_entries) {
+		ret = -ENOMEM;
+		goto reclaim;
+	}
+
+	// reduce number of entries by combining contiguous pages into single memory entry
+	prev_page = mem_entries[0].ipa_base = page_to_phys(mapping->pages[0]);
+	mem_entries[0].size = PAGE_SIZE;
+	for (i = 1, j = 0; i < mapping->npages; i++) {
+		curr_page = page_to_phys(mapping->pages[i]);
+		if (page_contiguous(prev_page, curr_page)) {
+			mem_entries[j].size += PAGE_SIZE;
+		} else {
+			j++;
+			mem_entries[j].ipa_base = curr_page;
+			mem_entries[j].size = PAGE_SIZE;
+		}
+
+		prev_page = curr_page;
+	}
+
+	parcel->n_mem_entries = j + 1;
+	parcel->mem_entries = kmemdup(mem_entries, sizeof(*mem_entries) * parcel->n_mem_entries,
+					GFP_KERNEL);
+	kfree(mem_entries);
+	if (!parcel->mem_entries) {
+		ret = -ENOMEM;
+		goto reclaim;
+	}
+
+	switch (mapping->share_type) {
+	case VM_MEM_LEND:
+		ret = gh_rm_mem_lend(parcel);
+		break;
+	case VM_MEM_SHARE:
+		ret = gh_rm_mem_share(parcel);
+		break;
+	}
+	if (ret > 0)
+		ret = -EINVAL;
+	if (ret)
+		goto reclaim;
+
+	return mapping;
+reclaim:
+	gh_vm_mem_mapping_reclaim(ghvm, mapping);
+free_mapping:
+	kfree(mapping);
+	return ERR_PTR(ret);
+}
diff --git a/include/uapi/linux/gunyah.h b/include/uapi/linux/gunyah.h
index 37ea6bd4c2fd..93f4b99fcaf6 100644
--- a/include/uapi/linux/gunyah.h
+++ b/include/uapi/linux/gunyah.h
@@ -20,4 +20,26 @@
  */
 #define GH_CREATE_VM			_IO(GH_IOCTL_TYPE, 0x40) /* Returns a Gunyah VM fd */
 
+/*
+ * ioctls for VM fds
+ */
+struct gh_userspace_memory_region {
+	__u32 label;
+#define GH_MEM_ALLOW_READ	(1UL << 0)
+#define GH_MEM_ALLOW_WRITE	(1UL << 1)
+#define GH_MEM_ALLOW_EXEC	(1UL << 2)
+/*
+ * The guest will be lent the memory instead of shared.
+ * In other words, the guest has exclusive access to the memory region and the host loses access.
+ */
+#define GH_MEM_LENT		(1UL << 3)
+	__u32 flags;
+	__u64 guest_phys_addr;
+	__u64 memory_size;
+	__u64 userspace_addr;
+};
+
+#define GH_VM_SET_USER_MEM_REGION	_IOW(GH_IOCTL_TYPE, 0x41, \
+						struct gh_userspace_memory_region)
+
 #endif
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 16/21] gunyah: vm_mgr: Add ioctls to support basic non-proxy VM boot
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (14 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 15/21] gunyah: vm_mgr: Add/remove user memory regions Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 17/21] samples: Add sample userspace Gunyah VM Manager Elliot Berman
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Add remaining ioctls to support non-proxy VM boot:

 - Gunyah Resource Manager uses the VM's devicetree to configure the
   virtual machine. The location of the devicetree in the guest's
   virtual memory can be declared via the SET_DTB_CONFIG ioctl.
 - Trigger start of the virtual machine with VM_START ioctl.

Co-developed-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 arch/arm64/include/uapi/asm/gunyah.h | 17 ++++++
 drivers/virt/gunyah/vm_mgr.c         | 91 ++++++++++++++++++++++++++++
 drivers/virt/gunyah/vm_mgr.h         |  9 +++
 drivers/virt/gunyah/vm_mgr_mm.c      | 29 +++++++--
 include/uapi/linux/gunyah.h          |  8 +++
 5 files changed, 149 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm64/include/uapi/asm/gunyah.h

diff --git a/arch/arm64/include/uapi/asm/gunyah.h b/arch/arm64/include/uapi/asm/gunyah.h
new file mode 100644
index 000000000000..54986f075ef5
--- /dev/null
+++ b/arch/arm64/include/uapi/asm/gunyah.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _UAPI_ASM_GUNYAH
+#define _UAPI_ASM_GUNYAH
+
+#define GH_REG_GENERAL	0x10000
+#define GH_REG_X_MASK	0x1f
+#define GH_REG_SPECIAL	0x20000
+
+#define GH_REG_X(n)	(GH_REG_GENERAL | (n & GH_REG_X_MASK))
+#define GH_REG_PC	(GH_REG_SPECIAL)
+#define GH_REG_SP_EL1	(GH_REG_SPECIAL + 1)
+
+#endif
diff --git a/drivers/virt/gunyah/vm_mgr.c b/drivers/virt/gunyah/vm_mgr.c
index a993e81a20e2..3dae2fd9e412 100644
--- a/drivers/virt/gunyah/vm_mgr.c
+++ b/drivers/virt/gunyah/vm_mgr.c
@@ -9,6 +9,7 @@
 #include <linux/file.h>
 #include <linux/gunyah_rsc_mgr.h>
 #include <linux/miscdevice.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 
 #include <uapi/linux/gunyah.h>
@@ -32,10 +33,79 @@ static __must_check struct gunyah_vm *gunyah_vm_alloc(void)
 
 	mutex_init(&ghvm->mm_lock);
 	INIT_LIST_HEAD(&ghvm->memory_mappings);
+	init_rwsem(&ghvm->status_lock);
 
 	return ghvm;
 }
 
+static int gh_vm_start(struct gunyah_vm *ghvm)
+{
+	struct gunyah_vm_memory_mapping *mapping;
+	u64 dtb_offset;
+	u32 mem_handle;
+	int ret;
+
+	down_write(&ghvm->status_lock);
+	if (ghvm->vm_status != GH_RM_VM_STATUS_NO_STATE) {
+		up_write(&ghvm->status_lock);
+		return 0;
+	}
+
+	mapping = gh_vm_mem_mapping_find_mapping(ghvm,
+			ghvm->dtb_config.gpa, ghvm->dtb_config.size);
+	if (!mapping) {
+		pr_warn("Failed to find the memory_handle for DTB\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	mem_handle = mapping->parcel.mem_handle;
+	dtb_offset = ghvm->dtb_config.gpa - mapping->guest_phys_addr;
+
+	ret = gh_rm_vm_configure(ghvm->vmid, ghvm->auth, mem_handle,
+				0, 0, dtb_offset, ghvm->dtb_config.size);
+	if (ret) {
+		pr_warn("Failed to configure VM: %d\n", ret);
+		goto err;
+	}
+
+	ret = gh_rm_vm_init(ghvm->vmid);
+	if (ret) {
+		pr_warn("Failed to initialize VM: %d\n", ret);
+		goto err;
+	}
+
+	ret = gh_rm_vm_start(ghvm->vmid);
+	if (ret) {
+		pr_warn("Failed to start VM: %d\n", ret);
+		goto err;
+	}
+
+	ghvm->vm_status = GH_RM_VM_STATUS_READY;
+
+	up_write(&ghvm->status_lock);
+	return ret;
+err:
+	ghvm->vm_status = GH_RM_VM_STATUS_INIT_FAILED;
+	up_write(&ghvm->status_lock);
+	return ret;
+}
+
+static void gh_vm_stop(struct gunyah_vm *ghvm)
+{
+	int ret;
+
+	down_write(&ghvm->status_lock);
+	if (ghvm->vm_status == GH_RM_VM_STATUS_READY) {
+		ret = gh_rm_vm_stop(ghvm->vmid);
+		if (ret)
+			pr_warn("Failed to stop VM: %d\n", ret);
+	}
+
+	ghvm->vm_status = GH_RM_VM_STATUS_EXITED;
+	up_write(&ghvm->status_lock);
+}
+
 static long gh_vm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct gunyah_vm *ghvm = filp->private_data;
@@ -79,6 +149,25 @@ static long gh_vm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		}
 		break;
 	}
+	case GH_VM_SET_DTB_CONFIG: {
+		struct gh_vm_dtb_config dtb_config;
+
+		r = -EFAULT;
+		if (copy_from_user(&dtb_config, argp, sizeof(dtb_config)))
+			break;
+
+		dtb_config.size = PAGE_ALIGN(dtb_config.size);
+		ghvm->dtb_config = dtb_config;
+
+		r = 0;
+		break;
+	}
+	case GH_VM_START: {
+		r = gh_vm_start(ghvm);
+		if (r)
+			r = -EINVAL;
+		break;
+	}
 	default:
 		r = -ENOTTY;
 		break;
@@ -92,6 +181,8 @@ static int gh_vm_release(struct inode *inode, struct file *filp)
 	struct gunyah_vm *ghvm = filp->private_data;
 	struct gunyah_vm_memory_mapping *mapping, *tmp;
 
+	gh_vm_stop(ghvm);
+
 	list_for_each_entry_safe(mapping, tmp, &ghvm->memory_mappings, list) {
 		gh_vm_mem_mapping_reclaim(ghvm, mapping);
 	}
diff --git a/drivers/virt/gunyah/vm_mgr.h b/drivers/virt/gunyah/vm_mgr.h
index ab1f0cb0758a..38ce3a2d9329 100644
--- a/drivers/virt/gunyah/vm_mgr.h
+++ b/drivers/virt/gunyah/vm_mgr.h
@@ -9,6 +9,7 @@
 #include <linux/gunyah_rsc_mgr.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/rwsem.h>
 
 #include <uapi/linux/gunyah.h>
 
@@ -31,6 +32,12 @@ struct gunyah_vm_memory_mapping {
 struct gunyah_vm {
 	u16 vmid;
 
+	enum gh_rm_vm_auth_mechanism auth;
+	struct gh_vm_dtb_config dtb_config;
+
+	enum gh_rm_vm_status vm_status;
+	struct rw_semaphore status_lock;
+
 	struct mutex mm_lock;
 	struct list_head memory_mappings;
 };
@@ -39,5 +46,7 @@ struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_alloc(struct gunyah_vm *ghvm,
 							struct gh_userspace_memory_region *region);
 void gh_vm_mem_mapping_reclaim(struct gunyah_vm *ghvm, struct gunyah_vm_memory_mapping *mapping);
 struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_find(struct gunyah_vm *ghvm, u32 label);
+struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_find_mapping(struct gunyah_vm *ghvm,
+								u64 gpa, u32 size);
 
 #endif
diff --git a/drivers/virt/gunyah/vm_mgr_mm.c b/drivers/virt/gunyah/vm_mgr_mm.c
index a5a57a38ee09..a7ca9a2e1627 100644
--- a/drivers/virt/gunyah/vm_mgr_mm.c
+++ b/drivers/virt/gunyah/vm_mgr_mm.c
@@ -34,11 +34,6 @@ void gh_vm_mem_mapping_reclaim(struct gunyah_vm *ghvm, struct gunyah_vm_memory_m
 	int i, ret = 0;
 
 	if (mapping->parcel.mem_handle != GH_MEM_HANDLE_INVAL) {
-		down_read(&ghvm->status_lock);
-		if (mapping->parcel.mem_handle == ghvm->primary_mem_handle &&
-			ghvm->vm_status == GH_RM_VM_STATUS_NO_STATE)
-			ghvm->primary_mem_handle = 0;
-		up_read(&ghvm->status_lock);
 		ret = gh_rm_mem_reclaim(&mapping->parcel);
 		if (ret)
 			pr_warn("Failed to reclaim memory parcel for label %d: %d\n",
@@ -58,6 +53,30 @@ void gh_vm_mem_mapping_reclaim(struct gunyah_vm *ghvm, struct gunyah_vm_memory_m
 	mutex_unlock(&ghvm->mm_lock);
 }
 
+struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_find_mapping(struct gunyah_vm *ghvm,
+								u64 gpa, u32 size)
+{
+	struct gunyah_vm_memory_mapping *mapping = NULL;
+	int ret;
+
+	ret = mutex_lock_interruptible(&ghvm->mm_lock);
+	if (ret)
+		return ERR_PTR(ret);
+
+	list_for_each_entry(mapping, &ghvm->memory_mappings, list) {
+		if (gpa >= mapping->guest_phys_addr &&
+			(gpa + size <= mapping->guest_phys_addr +
+			(mapping->npages << PAGE_SHIFT))) {
+			goto unlock;
+		}
+	}
+
+	mapping = NULL;
+unlock:
+	mutex_unlock(&ghvm->mm_lock);
+	return mapping;
+}
+
 struct gunyah_vm_memory_mapping *gh_vm_mem_mapping_find(struct gunyah_vm *ghvm, u32 label)
 {
 	struct gunyah_vm_memory_mapping *mapping;
diff --git a/include/uapi/linux/gunyah.h b/include/uapi/linux/gunyah.h
index 93f4b99fcaf6..575cb1cbd215 100644
--- a/include/uapi/linux/gunyah.h
+++ b/include/uapi/linux/gunyah.h
@@ -42,4 +42,12 @@ struct gh_userspace_memory_region {
 #define GH_VM_SET_USER_MEM_REGION	_IOW(GH_IOCTL_TYPE, 0x41, \
 						struct gh_userspace_memory_region)
 
+struct gh_vm_dtb_config {
+	__u64 gpa;
+	__u64 size;
+};
+#define GH_VM_SET_DTB_CONFIG	_IOW(GH_IOCTL_TYPE, 0x42, struct gh_vm_dtb_config)
+
+#define GH_VM_START		_IO(GH_IOCTL_TYPE, 0x45)
+
 #endif
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 17/21] samples: Add sample userspace Gunyah VM Manager
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (15 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 16/21] gunyah: vm_mgr: Add ioctls to support basic non-proxy VM boot Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 18/21] gunyah: rsc_mgr: Add platform ops on mem_lend/mem_reclaim Elliot Berman
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Add a sample Gunyah VMM capable of launching a non-proxy scheduled VM.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 MAINTAINERS                  |   1 +
 samples/Kconfig              |  10 ++
 samples/Makefile             |   1 +
 samples/gunyah/.gitignore    |   2 +
 samples/gunyah/Makefile      |   6 +
 samples/gunyah/gunyah_vmm.c  | 270 +++++++++++++++++++++++++++++++++++
 samples/gunyah/sample_vm.dts |  69 +++++++++
 7 files changed, 359 insertions(+)
 create mode 100644 samples/gunyah/.gitignore
 create mode 100644 samples/gunyah/Makefile
 create mode 100644 samples/gunyah/gunyah_vmm.c
 create mode 100644 samples/gunyah/sample_vm.dts

diff --git a/MAINTAINERS b/MAINTAINERS
index e072a0d2e553..907a2267f0ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8946,6 +8946,7 @@ F:	arch/arm64/gunyah/
 F:	drivers/mailbox/gunyah-msgq.c
 F:	drivers/virt/gunyah/
 F:	include/linux/gunyah*.h
+F:	samples/gunyah/
 
 HABANALABS PCI DRIVER
 M:	Oded Gabbay <ogabbay@kernel.org>
diff --git a/samples/Kconfig b/samples/Kconfig
index 0d81c00289ee..197c8a3610e7 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -263,6 +263,16 @@ config SAMPLE_CORESIGHT_SYSCFG
 	  This demonstrates how a user may create their own CoreSight
 	  configurations and easily load them into the system at runtime.
 
+config SAMPLE_GUNYAH
+	bool "Build example Gunyah Virtual Machine Manager"
+	depends on CC_CAN_LINK && HEADERS_INSTALL
+	depends on GUNYAH_VM_MANAGER
+	help
+	  Build an example Gunyah VMM userspace program capable of launching
+	  a basic virtual machine under the Gunyah hypervisor.
+	  This demonstrates how to create a virtual machine under the Gunyah
+	  hypervisor.
+
 source "samples/rust/Kconfig"
 
 endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
index 9832ef3f8fcb..2600bd4b82f8 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_DEBUG_KMEMLEAK_TEST)	+= kmemleak/
 obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG)	+= coresight/
 obj-$(CONFIG_SAMPLE_FPROBE)		+= fprobe/
 obj-$(CONFIG_SAMPLES_RUST)		+= rust/
+obj-$(CONFIG_SAMPLE_GUNYAH)		+= gunyah/
diff --git a/samples/gunyah/.gitignore b/samples/gunyah/.gitignore
new file mode 100644
index 000000000000..adc7d1589fde
--- /dev/null
+++ b/samples/gunyah/.gitignore
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+/gunyah_vmm
diff --git a/samples/gunyah/Makefile b/samples/gunyah/Makefile
new file mode 100644
index 000000000000..faf14f9bb337
--- /dev/null
+++ b/samples/gunyah/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+userprogs-always-y += gunyah_vmm
+dtb-y += sample_vm.dtb
+
+userccflags += -I usr/include
diff --git a/samples/gunyah/gunyah_vmm.c b/samples/gunyah/gunyah_vmm.c
new file mode 100644
index 000000000000..ccc1786051f2
--- /dev/null
+++ b/samples/gunyah/gunyah_vmm.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/sysmacros.h>
+#define __USE_GNU
+#include <sys/mman.h>
+
+#include <linux/gunyah.h>
+
+struct vm_config {
+	int image_fd;
+	int dtb_fd;
+	int ramdisk_fd;
+
+	uint64_t guest_base;
+	uint64_t guest_size;
+
+	uint64_t image_offset;
+	off_t image_size;
+	uint64_t dtb_offset;
+	off_t dtb_size;
+	uint64_t ramdisk_offset;
+	off_t ramdisk_size;
+};
+
+static struct option options[] = {
+	{ "help", no_argument, NULL, 'h' },
+	{ "image", required_argument, NULL, 'i' },
+	{ "dtb", required_argument, NULL, 'd' },
+	{ "ramdisk", optional_argument, NULL, 'r' },
+	{ "base", optional_argument, NULL, 'B' },
+	{ "size", optional_argument, NULL, 'S' },
+	{ "image_offset", optional_argument, NULL, 'I' },
+	{ "dtb_offset", optional_argument, NULL, 'D' },
+	{ "ramdisk_offset", optional_argument, NULL, 'R' },
+	{ }
+};
+
+static void print_help(char *cmd)
+{
+	printf("gunyah_vmm, a sample tool to launch Gunyah VMs\n"
+	       "Usage: %s <options>\n"
+	       "       --help,    -h  this menu\n"
+	       "       --image,   -i <image> VM image file to load (e.g. a kernel Image) [Required]\n"
+	       "       --dtb,     -d <dtb>   Devicetree to load [Required]\n"
+	       "       --ramdisk, -r <ramdisk>  Ramdisk to load\n"
+	       "       --base,    -B <address>  Set the base address of guest's memory [Default: 0x80000000]\n"
+	       "       --size,    -S <number>   The number of bytes large to make the guest's memory [Default: 0x6400000 (100 MB)]\n"
+	       "       --image_offset, -I <number>  Offset into guest memory to load the VM image file [Default: 0x10000]\n"
+	       "        --dtb_offset,  -D <number>  Offset into guest memory to load the DTB [Default: 0]\n"
+	       "        --ramdisk_offset, -R <number>  Offset into guest memory to load a ramdisk [Default: 0x4600000]\n"
+	       , cmd);
+}
+
+int main(int argc, char **argv)
+{
+	int gunyah_fd, vm_fd, guest_fd;
+	struct gh_userspace_memory_region guest_mem_desc = { 0 };
+	struct gh_vm_dtb_config dtb_config = { 0 };
+	char *guest_mem;
+	struct vm_config config = {
+		/* Defaults good enough to boot static kernel and a basic ramdisk */
+		.ramdisk_fd = -1,
+		.guest_base = 0x80000000,
+		.guest_size = 104857600, /* 100 MB */
+		.image_offset = 0,
+		.dtb_offset = 0x45f0000,
+		.ramdisk_offset = 0x4600000, /* put at +70MB (30MB for ramdisk) */
+	};
+	struct stat st;
+	int opt, optidx, ret = 0;
+	long int l;
+
+	while ((opt = getopt_long(argc, argv, "hi:d:r:B:S:I:D:R:c:", options, &optidx)) != -1) {
+		switch (opt) {
+		case 'i':
+			config.image_fd = open(optarg, O_RDONLY | O_CLOEXEC);
+			if (config.image_fd < 0) {
+				perror("Failed to open image");
+				return -1;
+			}
+			if (stat(optarg, &st) < 0) {
+				perror("Failed to stat image");
+				return -1;
+			}
+			config.image_size = st.st_size;
+			break;
+		case 'd':
+			config.dtb_fd = open(optarg, O_RDONLY | O_CLOEXEC);
+			if (config.dtb_fd < 0) {
+				perror("Failed to open dtb");
+				return -1;
+			}
+			if (stat(optarg, &st) < 0) {
+				perror("Failed to stat dtb");
+				return -1;
+			}
+			config.dtb_size = st.st_size;
+			break;
+		case 'r':
+			config.ramdisk_fd = open(optarg, O_RDONLY | O_CLOEXEC);
+			if (config.ramdisk_fd < 0) {
+				perror("Failed to open ramdisk");
+				return -1;
+			}
+			if (stat(optarg, &st) < 0) {
+				perror("Failed to stat ramdisk");
+				return -1;
+			}
+			config.ramdisk_size = st.st_size;
+			break;
+		case 'B':
+			l = strtol(optarg, NULL, 0);
+			if (l == LONG_MIN) {
+				perror("Failed to parse base address");
+				return -1;
+			}
+			config.guest_base = l;
+			break;
+		case 'S':
+			l = strtol(optarg, NULL, 0);
+			if (l == LONG_MIN) {
+				perror("Failed to parse memory size");
+				return -1;
+			}
+			config.guest_size = l;
+			break;
+		case 'I':
+			l = strtol(optarg, NULL, 0);
+			if (l == LONG_MIN) {
+				perror("Failed to parse image offset");
+				return -1;
+			}
+			config.image_offset = l;
+			break;
+		case 'D':
+			l = strtol(optarg, NULL, 0);
+			if (l == LONG_MIN) {
+				perror("Failed to parse dtb offset");
+				return -1;
+			}
+			config.dtb_offset = l;
+			break;
+		case 'R':
+			l = strtol(optarg, NULL, 0);
+			if (l == LONG_MIN) {
+				perror("Failed to parse ramdisk offset");
+				return -1;
+			}
+			config.ramdisk_offset = l;
+			break;
+		case 'h':
+			print_help(argv[0]);
+			return 0;
+		default:
+			print_help(argv[0]);
+			return -1;
+		}
+	}
+
+	if (!config.image_fd || !config.dtb_fd) {
+		print_help(argv[0]);
+		return -1;
+	}
+
+	if (config.image_offset + config.image_size > config.guest_size) {
+		fprintf(stderr, "Image offset and size puts it outside guest memory. Make image smaller or increase guest memory size.\n");
+		return -1;
+	}
+
+	if (config.dtb_offset + config.dtb_size > config.guest_size) {
+		fprintf(stderr, "DTB offset and size puts it outside guest memory. Make dtb smaller or increase guest memory size.\n");
+		return -1;
+	}
+
+	if (config.ramdisk_fd == -1 &&
+		config.ramdisk_offset + config.ramdisk_size > config.guest_size) {
+		fprintf(stderr, "Ramdisk offset and size puts it outside guest memory. Make ramdisk smaller or increase guest memory size.\n");
+		return -1;
+	}
+
+	gunyah_fd = open("/dev/gunyah", O_RDWR | O_CLOEXEC);
+	if (gunyah_fd < 0) {
+		perror("Failed to open /dev/gunyah");
+		return -1;
+	}
+
+	vm_fd = ioctl(gunyah_fd, GH_CREATE_VM, 0);
+	if (vm_fd < 0) {
+		perror("Failed to create vm");
+		return -1;
+	}
+
+	guest_fd = memfd_create("guest_memory", MFD_CLOEXEC);
+	if (guest_fd < 0) {
+		perror("Failed to create guest memfd");
+		return -1;
+	}
+
+	if (ftruncate(guest_fd, config.guest_size) < 0) {
+		perror("Failed to grow guest memory");
+		return -1;
+	}
+
+	guest_mem = mmap(NULL, config.guest_size, PROT_READ | PROT_WRITE, MAP_SHARED, guest_fd, 0);
+	if (guest_mem == MAP_FAILED) {
+		perror("Not enough memory");
+		return -1;
+	}
+
+	if (read(config.image_fd, guest_mem + config.image_offset, config.image_size) < 0) {
+		perror("Failed to read image into guest memory");
+		return -1;
+	}
+
+	if (read(config.dtb_fd, guest_mem + config.dtb_offset, config.dtb_size) < 0) {
+		perror("Failed to read dtb into guest memory");
+		return -1;
+	}
+
+	if (config.ramdisk_fd > 0 &&
+		read(config.ramdisk_fd, guest_mem + config.ramdisk_offset,
+			config.ramdisk_size) < 0) {
+		perror("Failed to read ramdisk into guest memory");
+		return -1;
+	}
+
+	guest_mem_desc.label = 0;
+	guest_mem_desc.flags = GH_MEM_ALLOW_READ | GH_MEM_ALLOW_WRITE | GH_MEM_ALLOW_EXEC;
+	guest_mem_desc.guest_phys_addr = config.guest_base;
+	guest_mem_desc.memory_size = config.guest_size;
+	guest_mem_desc.userspace_addr = (__u64)guest_mem;
+
+	if (ioctl(vm_fd, GH_VM_SET_USER_MEM_REGION, &guest_mem_desc) < 0) {
+		perror("Failed to register guest memory with VM");
+		return -1;
+	}
+
+	dtb_config.gpa = config.dtb_offset;
+	dtb_config.size = config.dtb_size;
+	if (ioctl(vm_fd, GH_VM_SET_DTB_CONFIG, &dtb_config) < 0) {
+		perror("Failed to set DTB configuration for VM");
+		return -1;
+	}
+
+	ret = ioctl(vm_fd, GH_VM_START);
+	if (ret) {
+		perror("GH_VM_START failed");
+		return -1;
+	}
+
+	while (1)
+		sleep(10);
+
+	return 0;
+}
diff --git a/samples/gunyah/sample_vm.dts b/samples/gunyah/sample_vm.dts
new file mode 100644
index 000000000000..1c410d58c298
--- /dev/null
+++ b/samples/gunyah/sample_vm.dts
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&intc>;
+
+	chosen {
+		bootargs = "nokaslr";
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0 0>;
+		};
+	};
+
+	intc: interrupt-controller@3FFF0000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		interrupt-controller;
+		reg = <0 0x3FFF0000 0 0x10000>,
+		      <0 0x3FFD0000 0 0x20000>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		always-on;
+		interrupts = <1 13 0x108>,
+			     <1 14 0x108>,
+			     <1 11 0x108>,
+			     <1 10 0x108>;
+		clock-frequency = <19200000>;
+	};
+
+	gunyah-vm-config {
+		image-name = "linux_vm_0";
+		os-type = "linux";
+
+		memory {
+			#address-cells = <2>;
+			#size-cells = <2>;
+
+			base-address = <0 0x80000000>;
+		};
+
+		interrupts {
+			config = <&intc>;
+		};
+
+		vcpus {
+			affinity-map = < 0 >;
+			sched-priority = < (-1) >;
+			sched-timeslice = < 2000 >;
+		};
+	};
+};
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 18/21] gunyah: rsc_mgr: Add platform ops on mem_lend/mem_reclaim
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (16 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 17/21] samples: Add sample userspace Gunyah VM Manager Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 19/21] firmware: qcom_scm: Use fixed width src vm bitmap Elliot Berman
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On Qualcomm platforms, there is a firmware entity which controls access
to physical pages. In order to share memory with another VM, this entity
needs to be informed that the guest VM should have access to the memory.

Co-developed-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/virt/gunyah/rsc_mgr.c     | 52 +++++++++++++++++++++++++++++++
 drivers/virt/gunyah/rsc_mgr.h     |  3 ++
 drivers/virt/gunyah/rsc_mgr_rpc.c |  7 +++++
 include/linux/gunyah_rsc_mgr.h    | 12 ++++++-
 4 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/virt/gunyah/rsc_mgr.c b/drivers/virt/gunyah/rsc_mgr.c
index f2f776edecb8..6e590f2a8cfa 100644
--- a/drivers/virt/gunyah/rsc_mgr.c
+++ b/drivers/virt/gunyah/rsc_mgr.c
@@ -105,6 +105,13 @@ struct gh_rsc_mgr {
 static struct gh_rsc_mgr *__rsc_mgr;
 SRCU_NOTIFIER_HEAD_STATIC(gh_rm_notifier);
 
+/* Needs to be out of the gh_rsc_mgr struct as platform_ops might probe before
+ * rsc mgr probes. We can't defer the platform_ops because it might be that
+ * Linux is not a Gunyah guest.
+ */
+static struct gunyah_rm_platform_ops *rm_platform_ops;
+static DECLARE_RWSEM(rm_platform_ops_lock);
+
 static struct gh_rm_connection *gh_rm_alloc_connection(u32 msg_id, u8 type)
 {
 	struct gh_rm_connection *connection;
@@ -498,6 +505,51 @@ int gh_rm_call(u32 message_id, void *req_buff, size_t req_buff_size,
 	return ret;
 }
 
+int gh_rm_platform_pre_mem_share(struct gh_rm_mem_parcel *mem_parcel)
+{
+	int ret = 0;
+
+	down_read(&rm_platform_ops_lock);
+	if (rm_platform_ops && rm_platform_ops->pre_mem_share)
+		ret = rm_platform_ops->pre_mem_share(mem_parcel);
+	up_read(&rm_platform_ops_lock);
+	return ret;
+}
+
+int gh_rm_platform_post_mem_reclaim(struct gh_rm_mem_parcel *mem_parcel)
+{
+	int ret = 0;
+
+	down_read(&rm_platform_ops_lock);
+	if (rm_platform_ops && rm_platform_ops->post_mem_reclaim)
+		ret = rm_platform_ops->post_mem_reclaim(mem_parcel);
+	up_read(&rm_platform_ops_lock);
+	return ret;
+}
+
+int gh_rm_register_platform_ops(struct gunyah_rm_platform_ops *platform_ops)
+{
+	int ret = 0;
+
+	down_write(&rm_platform_ops_lock);
+	if (!rm_platform_ops)
+		rm_platform_ops = platform_ops;
+	else
+		ret = -EEXIST;
+	up_write(&rm_platform_ops_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_register_platform_ops);
+
+void gh_rm_unregister_platform_ops(struct gunyah_rm_platform_ops *platform_ops)
+{
+	down_write(&rm_platform_ops_lock);
+	if (rm_platform_ops == platform_ops)
+		rm_platform_ops = NULL;
+	up_write(&rm_platform_ops_lock);
+}
+EXPORT_SYMBOL_GPL(gh_rm_unregister_platform_ops);
+
 int gh_rm_register_notifier(struct notifier_block *nb)
 {
 	return srcu_notifier_chain_register(&gh_rm_notifier, nb);
diff --git a/drivers/virt/gunyah/rsc_mgr.h b/drivers/virt/gunyah/rsc_mgr.h
index f6ed58405ef4..49becf82edf7 100644
--- a/drivers/virt/gunyah/rsc_mgr.h
+++ b/drivers/virt/gunyah/rsc_mgr.h
@@ -130,6 +130,9 @@ struct gh_vm_set_boot_context_req {
 int gh_rm_call(u32 message_id, void *req_buff, size_t req_buff_size,
 		void **resp_buf, size_t *resp_buff_size);
 
+int gh_rm_platform_pre_mem_share(struct gh_rm_mem_parcel *mem_parcel);
+int gh_rm_platform_post_mem_reclaim(struct gh_rm_mem_parcel *mem_parcel);
+
 struct gh_rm_device {
 	struct device dev;
 	const char *name;
diff --git a/drivers/virt/gunyah/rsc_mgr_rpc.c b/drivers/virt/gunyah/rsc_mgr_rpc.c
index 17f88c3d5726..c7e3bb975640 100644
--- a/drivers/virt/gunyah/rsc_mgr_rpc.c
+++ b/drivers/virt/gunyah/rsc_mgr_rpc.c
@@ -120,6 +120,10 @@ static int gh_rm_mem_lend_common(u32 message_id, struct gh_rm_mem_parcel *p)
 	if (initial_n_mem_entries > GH_RM_MAX_MEM_ENTRIES)
 		initial_n_mem_entries = GH_RM_MAX_MEM_ENTRIES;
 
+	ret = gh_rm_platform_pre_mem_share(p);
+	if (ret)
+		return ret;
+
 	/* The format of the message goes:
 	 * request header
 	 * ACL entries (which VMs get what kind of access to this memory parcel)
@@ -163,6 +167,7 @@ static int gh_rm_mem_lend_common(u32 message_id, struct gh_rm_mem_parcel *p)
 
 	if (resp_size != sizeof(u32)) {
 		ret = -EIO;
+		gh_rm_platform_post_mem_reclaim(p);
 		goto out;
 	}
 
@@ -234,6 +239,8 @@ int gh_rm_mem_reclaim(struct gh_rm_mem_parcel *parcel)
 	if (resp_size)
 		pr_warn("Received unexpected payload for MEM_RECLAIM: %lu\n", resp_size);
 
+	ret = gh_rm_platform_post_mem_reclaim(parcel);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(gh_rm_mem_reclaim);
diff --git a/include/linux/gunyah_rsc_mgr.h b/include/linux/gunyah_rsc_mgr.h
index 78d516032f6a..6e5e67e96688 100644
--- a/include/linux/gunyah_rsc_mgr.h
+++ b/include/linux/gunyah_rsc_mgr.h
@@ -119,7 +119,6 @@ struct gh_rm_hyp_resource {
 } __packed;
 
 ssize_t gh_rm_get_hyp_resources(u16 vmid, struct gh_rm_hyp_resource **resources);
-int gh_rm_get_vmid(u16 *vmid);
 
 #define GH_RM_BOOT_CONTEXT_REG_SET_REGISTERS	0
 #define GH_RM_BOOT_CONTEXT_REG_SET_PC		1
@@ -143,4 +142,15 @@ void gh_rm_driver_unregister(struct gh_rm_driver *ghrm_drv);
 #define module_gh_rm_driver(ghrm_drv) \
 	module_driver(ghrm_drv, gh_rm_driver_register, gh_rm_driver_unregister)
 
+#if IS_ENABLED(CONFIG_GUNYAH)
+int gh_rm_register_platform_ops(struct gunyah_rm_platform_ops *platform_ops);
+void gh_rm_unregister_platform_ops(struct gunyah_rm_platform_ops *platform_ops);
+int gh_rm_get_vmid(u16 *vmid);
+#else
+static inline int gh_rm_register_platform_ops(struct gunyah_rm_platform_ops *platform_ops)
+	{ return 0; }
+static inline void gh_rm_unregister_platform_ops(struct gunyah_rm_platform_ops *platform_ops) { }
+static inline int gh_rm_get_vmid(u16 *vmid) { return -ENODEV; }
+#endif
+
 #endif
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 19/21] firmware: qcom_scm: Use fixed width src vm bitmap
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (17 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 18/21] gunyah: rsc_mgr: Add platform ops on mem_lend/mem_reclaim Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 20/21] firmware: qcom_scm: Register Gunyah platform ops Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 21/21] docs: gunyah: Document Gunyah VM Manager Elliot Berman
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Srinivas Kandagatla, Amol Maheshwari, Kalle Valo
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

The maximum VMID for assign_mem is 63. Use a u64 to represent this
bitmap instead of architecture-dependent "unsigned int" which varies in
size on 32-bit and 64-bit platforms.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/firmware/qcom_scm.c           | 12 +++++++-----
 drivers/misc/fastrpc.c                |  6 ++++--
 drivers/net/wireless/ath/ath10k/qmi.c |  4 ++--
 drivers/remoteproc/qcom_q6v5_mss.c    |  8 ++++----
 drivers/soc/qcom/rmtfs_mem.c          |  2 +-
 include/linux/qcom_scm.h              |  2 +-
 6 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index cdbfe54c8146..92763dce6477 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -898,7 +898,7 @@ static int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
  * Return negative errno on failure or 0 on success with @srcvm updated.
  */
 int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
-			unsigned int *srcvm,
+			u64 *srcvm,
 			const struct qcom_scm_vmperm *newvm,
 			unsigned int dest_cnt)
 {
@@ -915,9 +915,9 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
 	__le32 *src;
 	void *ptr;
 	int ret, i, b;
-	unsigned long srcvm_bits = *srcvm;
+	u64 srcvm_bits = *srcvm;
 
-	src_sz = hweight_long(srcvm_bits) * sizeof(*src);
+	src_sz = hweight64(srcvm_bits) * sizeof(*src);
 	mem_to_map_sz = sizeof(*mem_to_map);
 	dest_sz = dest_cnt * sizeof(*destvm);
 	ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) +
@@ -930,8 +930,10 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
 	/* Fill source vmid detail */
 	src = ptr;
 	i = 0;
-	for_each_set_bit(b, &srcvm_bits, BITS_PER_LONG)
-		src[i++] = cpu_to_le32(b);
+	for (b = 0; b < BITS_PER_TYPE(u64); b++) {
+		if (srcvm_bits & BIT(b))
+			src[i++] = cpu_to_le32(b);
+	}
 
 	/* Fill details of mem buff to map */
 	mem_to_map = ptr + ALIGN(src_sz, SZ_64);
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 7ff0b63c25e3..2ad388f99fe1 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -299,11 +299,13 @@ static void fastrpc_free_map(struct kref *ref)
 		if (map->attr & FASTRPC_ATTR_SECUREMAP) {
 			struct qcom_scm_vmperm perm;
 			int err = 0;
+			u64 src;
 
+			src = BIT(map->fl->cctx->vmperms[0].vmid);
 			perm.vmid = QCOM_SCM_VMID_HLOS;
 			perm.perm = QCOM_SCM_PERM_RWX;
 			err = qcom_scm_assign_mem(map->phys, map->size,
-				&(map->fl->cctx->vmperms[0].vmid), &perm, 1);
+				&src, &perm, 1);
 			if (err) {
 				dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
 						map->phys, map->size, err);
@@ -744,7 +746,7 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
 		 * If subsystem VMIDs are defined in DTSI, then do
 		 * hyp_assign from HLOS to those VM(s)
 		 */
-		unsigned int perms = BIT(QCOM_SCM_VMID_HLOS);
+		u64 perms = BIT(QCOM_SCM_VMID_HLOS);
 
 		map->attr = attr;
 		err = qcom_scm_assign_mem(map->phys, (u64)map->size, &perms,
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 66cb7a1e628a..6d1d87e1cdde 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -28,7 +28,7 @@ static int ath10k_qmi_map_msa_permission(struct ath10k_qmi *qmi,
 {
 	struct qcom_scm_vmperm dst_perms[3];
 	struct ath10k *ar = qmi->ar;
-	unsigned int src_perms;
+	u64 src_perms;
 	u32 perm_count;
 	int ret;
 
@@ -60,7 +60,7 @@ static int ath10k_qmi_unmap_msa_permission(struct ath10k_qmi *qmi,
 {
 	struct qcom_scm_vmperm dst_perms;
 	struct ath10k *ar = qmi->ar;
-	unsigned int src_perms;
+	u64 src_perms;
 	int ret;
 
 	src_perms = BIT(QCOM_SCM_VMID_MSS_MSA) | BIT(QCOM_SCM_VMID_WLAN);
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index fddb63cffee0..9e8bde7a7ec4 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -227,8 +227,8 @@ struct q6v5 {
 	bool has_qaccept_regs;
 	bool has_ext_cntl_regs;
 	bool has_vq6;
-	int mpss_perm;
-	int mba_perm;
+	u64 mpss_perm;
+	u64 mba_perm;
 	const char *hexagon_mdt_image;
 	int version;
 };
@@ -404,7 +404,7 @@ static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds,
 	}
 }
 
-static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm,
+static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, u64 *current_perm,
 				   bool local, bool remote, phys_addr_t addr,
 				   size_t size)
 {
@@ -939,7 +939,7 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw,
 	struct page *page;
 	dma_addr_t phys;
 	void *metadata;
-	int mdata_perm;
+	u64 mdata_perm;
 	int xferop_ret;
 	size_t size;
 	void *vaddr;
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index 0feaae357821..69991e47aa23 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -30,7 +30,7 @@ struct qcom_rmtfs_mem {
 
 	unsigned int client_id;
 
-	unsigned int perms;
+	u64 perms;
 };
 
 static ssize_t qcom_rmtfs_mem_show(struct device *dev,
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index f8335644a01a..77f7b5837216 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -96,7 +96,7 @@ extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
 					  u32 cp_nonpixel_start,
 					  u32 cp_nonpixel_size);
 extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
-			       unsigned int *src,
+			       u64 *src,
 			       const struct qcom_scm_vmperm *newvm,
 			       unsigned int dest_cnt);
 
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 20/21] firmware: qcom_scm: Register Gunyah platform ops
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (18 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 19/21] firmware: qcom_scm: Use fixed width src vm bitmap Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-10-26 18:58 ` [PATCH v6 21/21] docs: gunyah: Document Gunyah VM Manager Elliot Berman
  20 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Qualcomm platforms have a firmware entity which performs access control
to physical pages. Dynamically started Gunyah virtual machines use the
QCOM_SCM_RM_MANAGED_VMID for access. Linux thus needs to assign access
to the memory used by guest VMs. Gunyah doesn't do this operation for us
since it is the current VM (typically VMID_HLOS) delegating the access
and not Gunyah itself. Use the Gunyah platform ops to achieve this so
that only Qualcomm platforms attempt to make the needed SCM calls.

Co-developed-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 drivers/firmware/qcom_scm.c    | 114 +++++++++++++++++++++++++++++++++
 include/linux/gunyah_rsc_mgr.h |   5 ++
 2 files changed, 119 insertions(+)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 92763dce6477..6be7c71f8609 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -17,6 +17,7 @@
 #include <linux/clk.h>
 #include <linux/reset-controller.h>
 #include <linux/arm-smccc.h>
+#include <linux/gunyah_rsc_mgr.h>
 
 #include "qcom_scm.h"
 
@@ -27,6 +28,9 @@ module_param(download_mode, bool, 0);
 #define SCM_HAS_IFACE_CLK	BIT(1)
 #define SCM_HAS_BUS_CLK		BIT(2)
 
+#define QCOM_SCM_RM_MANAGED_VMID	0x3A
+#define QCOM_SCM_MAX_MANAGED_VMID	0x3F
+
 struct qcom_scm {
 	struct device *dev;
 	struct clk *core_clk;
@@ -1292,6 +1296,113 @@ int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
 }
 EXPORT_SYMBOL(qcom_scm_lmh_dcvsh);
 
+static int qcom_scm_gh_rm_pre_mem_share(struct gh_rm_mem_parcel *mem_parcel)
+{
+	struct qcom_scm_vmperm *new_perms;
+	u16 this_vmid;
+	u64 src, src_cpy;
+	int ret, i, n;
+
+	ret = gh_rm_get_vmid(&this_vmid);
+	if (ret)
+		return ret;
+
+	new_perms = kcalloc(mem_parcel->n_acl_entries, sizeof(*new_perms), GFP_KERNEL);
+	if (!new_perms)
+		return -ENOMEM;
+
+	for (n = 0; n < mem_parcel->n_acl_entries; n++) {
+		if (mem_parcel->acl_entries[n].vmid <= QCOM_SCM_MAX_MANAGED_VMID)
+			new_perms[n].vmid = mem_parcel->acl_entries[n].vmid;
+		else
+			new_perms[n].vmid = QCOM_SCM_RM_MANAGED_VMID;
+		if (mem_parcel->acl_entries[n].perms & GH_RM_ACL_X)
+			new_perms[n].perm |= QCOM_SCM_PERM_EXEC;
+		if (mem_parcel->acl_entries[n].perms & GH_RM_ACL_W)
+			new_perms[n].perm |= QCOM_SCM_PERM_WRITE;
+		if (mem_parcel->acl_entries[n].perms & GH_RM_ACL_R)
+			new_perms[n].perm |= QCOM_SCM_PERM_READ;
+	}
+
+	if (this_vmid <= QCOM_SCM_MAX_MANAGED_VMID)
+		src = (1ul << this_vmid);
+	else
+		src = (1ul << QCOM_SCM_RM_MANAGED_VMID);
+
+	for (i = 0; i < mem_parcel->n_mem_entries; i++) {
+		src_cpy = src;
+		ret = qcom_scm_assign_mem(mem_parcel->mem_entries[i].ipa_base,
+						mem_parcel->mem_entries[i].size,
+						&src_cpy, new_perms, mem_parcel->n_acl_entries);
+		if (ret) {
+			src = 0;
+			for (n = 0; n < mem_parcel->n_acl_entries; n++) {
+				if (mem_parcel->acl_entries[n].vmid <= QCOM_SCM_MAX_MANAGED_VMID)
+					src |= (1ul << mem_parcel->acl_entries[n].vmid);
+				else
+					src |= (1ul << QCOM_SCM_RM_MANAGED_VMID);
+			}
+
+			if (this_vmid <= QCOM_SCM_MAX_MANAGED_VMID)
+				new_perms[0].vmid = this_vmid;
+			else
+				new_perms[0].vmid = QCOM_SCM_RM_MANAGED_VMID;
+
+			for (i--; i >= 0; i--) {
+				src_cpy = src;
+				ret = qcom_scm_assign_mem(mem_parcel->mem_entries[i].ipa_base,
+								mem_parcel->mem_entries[i].size,
+								&src_cpy, new_perms, 1);
+				WARN_ON_ONCE(ret);
+			}
+			break;
+		}
+	}
+
+	kfree(new_perms);
+	return ret;
+}
+
+static int qcom_scm_gh_rm_post_mem_reclaim(struct gh_rm_mem_parcel *mem_parcel)
+{
+	struct qcom_scm_vmperm new_perms;
+	u16 this_vmid;
+	u64 src = 0;
+	int ret, i, n;
+
+
+	ret = gh_rm_get_vmid(&this_vmid);
+	if (ret)
+		return ret;
+
+	if (this_vmid <= QCOM_SCM_MAX_MANAGED_VMID)
+		new_perms.vmid = this_vmid;
+	else
+		new_perms.vmid = QCOM_SCM_RM_MANAGED_VMID;
+	new_perms.perm = QCOM_SCM_PERM_EXEC | QCOM_SCM_PERM_WRITE | QCOM_SCM_PERM_READ;
+
+	for (n = 0; n < mem_parcel->n_acl_entries; n++) {
+		if (mem_parcel->acl_entries[n].vmid <= QCOM_SCM_MAX_MANAGED_VMID)
+			src |= (1ul << mem_parcel->acl_entries[n].vmid);
+		else
+			src |= (1ul << QCOM_SCM_RM_MANAGED_VMID);
+	}
+
+	for (i = 0; i < mem_parcel->n_mem_entries; i++) {
+		ret = qcom_scm_assign_mem(mem_parcel->mem_entries[i].ipa_base,
+						mem_parcel->mem_entries[i].size,
+						&src, &new_perms, 1);
+		WARN_ON_ONCE(ret);
+	}
+
+	return ret;
+}
+
+static struct gunyah_rm_platform_ops qcom_scm_gh_rm_platform_ops = {
+	.pre_mem_share = qcom_scm_gh_rm_pre_mem_share,
+	.post_mem_reclaim = qcom_scm_gh_rm_post_mem_reclaim,
+};
+
 static int qcom_scm_find_dload_address(struct device *dev, u64 *addr)
 {
 	struct device_node *tcsr;
@@ -1414,6 +1525,9 @@ static int qcom_scm_probe(struct platform_device *pdev)
 	if (download_mode)
 		qcom_scm_set_download_mode(true);
 
+	if (gh_rm_register_platform_ops(&qcom_scm_gh_rm_platform_ops))
+		dev_warn(__scm->dev, "Gunyah RM platform ops were already registered\n");
+
 	return 0;
 }
 
diff --git a/include/linux/gunyah_rsc_mgr.h b/include/linux/gunyah_rsc_mgr.h
index 6e5e67e96688..710e9a045f02 100644
--- a/include/linux/gunyah_rsc_mgr.h
+++ b/include/linux/gunyah_rsc_mgr.h
@@ -142,6 +142,11 @@ void gh_rm_driver_unregister(struct gh_rm_driver *ghrm_drv);
 #define module_gh_rm_driver(ghrm_drv) \
 	module_driver(ghrm_drv, gh_rm_driver_register, gh_rm_driver_unregister)
 
+struct gunyah_rm_platform_ops {
+	int (*pre_mem_share)(struct gh_rm_mem_parcel *mem_parcel);
+	int (*post_mem_reclaim)(struct gh_rm_mem_parcel *mem_parcel);
+};
+
 #if IS_ENABLED(CONFIG_GUNYAH)
 int gh_rm_register_platform_ops(struct gunyah_rm_platform_ops *platform_ops);
 void gh_rm_unregister_platform_ops(struct gunyah_rm_platform_ops *platform_ops);
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* [PATCH v6 21/21] docs: gunyah: Document Gunyah VM Manager
  2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
                   ` (19 preceding siblings ...)
  2022-10-26 18:58 ` [PATCH v6 20/21] firmware: qcom_scm: Register Gunyah platform ops Elliot Berman
@ 2022-10-26 18:58 ` Elliot Berman
  2022-11-02 13:05   ` Bagas Sanjaya
  20 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 18:58 UTC (permalink / raw)
  To: Bjorn Andersson, Jonathan Corbet
  Cc: Elliot Berman, Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Will Deacon, Catalin Marinas, Arnd Bergmann,
	Greg Kroah-Hartman, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel

Document the ioctls and usage of Gunyah VM Manager driver.

Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
 Documentation/virt/gunyah/index.rst      |  1 +
 Documentation/virt/gunyah/vm-manager.rst | 94 ++++++++++++++++++++++++
 2 files changed, 95 insertions(+)
 create mode 100644 Documentation/virt/gunyah/vm-manager.rst

diff --git a/Documentation/virt/gunyah/index.rst b/Documentation/virt/gunyah/index.rst
index fbadbdd24da7..9019a03b6f3e 100644
--- a/Documentation/virt/gunyah/index.rst
+++ b/Documentation/virt/gunyah/index.rst
@@ -7,6 +7,7 @@ Gunyah Hypervisor
 .. toctree::
    :maxdepth: 1
 
+   vm-manager
    message-queue
 
 Gunyah is a Type-1 hypervisor which is independent of any OS kernel, and runs in
diff --git a/Documentation/virt/gunyah/vm-manager.rst b/Documentation/virt/gunyah/vm-manager.rst
new file mode 100644
index 000000000000..c232ba05de7e
--- /dev/null
+++ b/Documentation/virt/gunyah/vm-manager.rst
@@ -0,0 +1,94 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======================
+Virtual Machine Manager
+=======================
+
+The Gunyah Virtual Machine Manager is a Linux driver to support launching virtual machines.
+
+Summary
+=======
+
+Gunyah VMM presently supports launching non-proxy scheduled Linux-like virtual machines.
+
+Sample Userspace VMM
+====================
+
+A sample userspace VMM is included in samples/gunyah/ along with a sample minimal devicetree
+that can be used to launch a Linux-like virtual machine under Gunyah. To build this sample, enable
+CONFIG_SAMPLE_GUNYAH.
+
+IOCTLs and userspace VMM flows
+==============================
+
+The kernel exposes a char device interface at /dev/gunyah.
+
+To create a VM, use the GH_CREATE_VM ioctl. A successful call will return a "Gunyah VM" file descriptor.
+
+/dev/gunyah API Descriptions
+----------------------------
+
+GH_CREATE_VM
+~~~~~~~~~~~~
+
+Creates a Gunyah VM. The argument is reserved for future use and must be 0.
+
+Gunyah VM API Descriptions
+--------------------------
+
+GH_VM_SET_USER_MEM_REGION
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  struct gh_userspace_memory_region {
+	__u32 label;
+	__u32 flags;
+	__u64 guest_phys_addr;
+	__u64 memory_size;
+	__u64 userspace_addr;
+  };
+
+This ioctl allows the user to create or delete a memory parcel for a guest
+virtual machine. Each memory region is uniquely identified by a label;
+attempting to create two memory regions with the same label is not allowed.
+
+While VMM is guest-agnostic and allows runtime addition of memory regions,
+Linux guest virtual machines do not support accepting memory regions at runtime.
+Thus, memory regions should be provided before starting the VM and the VM
+configured to accept those memory regions at boot-up.
+
+The guest physical address is used by Linux to check the requested user regions
+do not overlap and to help find a corresponding memory region for calls like
+GH_VM_SET_DTB_CONFIG.
+
+To delete a memory region, call GH_VM_SET_USER_MEM_REGION with label set to the
+memory region of interest and memory_size set to 0.
+
+The flags field of gh_userspace_memory_region can set the following bits. All
+other bits must be 0 and are reserved for future use. The ioctl will return
+-EINVAL if an unsupported bit is detected.
+
+  - GH_MEM_ALLOW_READ/GH_MEM_ALLOW_WRITE/GH_MEM_ALLOW_EXEC sets read/write/exec permissions
+    for the guest, respectively.
+
+  - GH_MEM_LENT means that the memory will be unmapped from the host and be unaccessible by
+    the host while the guest has the region.
+
+GH_VM_SET_DTB_CONFIG
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  struct gh_vm_dtb_config {
+	__u64 gpa;
+	__u64 size;
+  };
+
+This ioctl sets the location of the VM's devicetree blob and is used by Gunyah
+Resource Manager to allocate resources.
+
+GH_VM_START
+~~~~~~~~~~~
+
+This ioctl starts the virtual machine.
-- 
2.25.1


_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 04/21] arm64: smccc: Include alternative-macros.h
  2022-10-26 18:58 ` [PATCH v6 04/21] arm64: smccc: Include alternative-macros.h Elliot Berman
@ 2022-10-26 19:46   ` Dmitry Baryshkov
  2022-10-26 20:23     ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Baryshkov @ 2022-10-26 19:46 UTC (permalink / raw)
  To: Elliot Berman, Bjorn Andersson, Mark Rutland, Lorenzo Pieralisi,
	Sudeep Holla
  Cc: Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Marc Zyngier, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Will Deacon, Catalin Marinas, Arnd Bergmann,
	Greg Kroah-Hartman, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel

On 26/10/2022 21:58, Elliot Berman wrote:
> Fix build error when CONFIG_ARM64_SVE is selected and
> asm/alternative-macros.h wasn't implicitly included by another header.

Please include the build error into the commit message to help anybody 
looking for the solution for the same issue.

> 
> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> ---
>   include/linux/arm-smccc.h | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index 220c8c60e021..6a627cdbbdec 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -383,6 +383,7 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>   
>   /* nVHE hypervisor doesn't have a current thread so needs separate checks */
>   #if defined(CONFIG_ARM64_SVE) && !defined(__KVM_NVHE_HYPERVISOR__)
> +#include <asm/alternative-macros.h>
>   
>   #define SMCCC_SVE_CHECK ALTERNATIVE("nop \n",  "bl __arm_smccc_sve_check \n", \
>   				    ARM64_SVE)

-- 
With best wishes
Dmitry


_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 03/21] gunyah: Common types and error codes for Gunyah hypercalls
  2022-10-26 18:58 ` [PATCH v6 03/21] gunyah: Common types and error codes for Gunyah hypercalls Elliot Berman
@ 2022-10-26 19:47   ` Dmitry Baryshkov
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Baryshkov @ 2022-10-26 19:47 UTC (permalink / raw)
  To: Elliot Berman, Bjorn Andersson
  Cc: Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla,
	Marc Zyngier, Rob Herring, Krzysztof Kozlowski, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On 26/10/2022 21:58, Elliot Berman wrote:
> Add architecture-independent standard error codes, types, and macros for
> Gunyah hypercalls.
> 
> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> ---
>   MAINTAINERS            |  1 +
>   include/linux/gunyah.h | 74 ++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 75 insertions(+)
>   create mode 100644 include/linux/gunyah.h

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

-- 
With best wishes
Dmitry


_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 04/21] arm64: smccc: Include alternative-macros.h
  2022-10-26 19:46   ` Dmitry Baryshkov
@ 2022-10-26 20:23     ` Elliot Berman
  2022-10-26 20:39       ` Dmitry Baryshkov
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-10-26 20:23 UTC (permalink / raw)
  To: Dmitry Baryshkov, Bjorn Andersson, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla
  Cc: Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Marc Zyngier, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Will Deacon, Catalin Marinas, Arnd Bergmann,
	Greg Kroah-Hartman, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel


On 10/26/2022 12:46 PM, Dmitry Baryshkov wrote:
> On 26/10/2022 21:58, Elliot Berman wrote:
>> Fix build error when CONFIG_ARM64_SVE is selected and
>> asm/alternative-macros.h wasn't implicitly included by another header.
> 
> Please include the build error into the commit message to help anybody 
> looking for the solution for the same issue.
> 

Now that the gunyah_hypercall implementation has been moved to its own 
module, this change isn't needed because asm/alternative-macros.h got 
implicitly included now. I can drop this, although not sure if we think 
it's still correct to have it?

After I got rid of the other header files, for reference:

In file included from arch/arm64/gunyah/gunyah_hypercall.c:6:
arch/arm64/gunyah/gunyah_hypercall.c: In function ‘gh_hypercall_msgq_send’:
./include/linux/arm-smccc.h:387:25: error: expected string literal 
before ‘ALTERNATIVE’
   387 | #define SMCCC_SVE_CHECK ALTERNATIVE("nop \n",  "bl 
__arm_smccc_sve_check \n", \

>>
>> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
>> ---
>>   include/linux/arm-smccc.h | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
>> index 220c8c60e021..6a627cdbbdec 100644
>> --- a/include/linux/arm-smccc.h
>> +++ b/include/linux/arm-smccc.h
>> @@ -383,6 +383,7 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, 
>> unsigned long a1,
>>   /* nVHE hypervisor doesn't have a current thread so needs separate 
>> checks */
>>   #if defined(CONFIG_ARM64_SVE) && !defined(__KVM_NVHE_HYPERVISOR__)
>> +#include <asm/alternative-macros.h>
>>   #define SMCCC_SVE_CHECK ALTERNATIVE("nop \n",  "bl 
>> __arm_smccc_sve_check \n", \
>>                       ARM64_SVE)
> 

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 04/21] arm64: smccc: Include alternative-macros.h
  2022-10-26 20:23     ` Elliot Berman
@ 2022-10-26 20:39       ` Dmitry Baryshkov
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Baryshkov @ 2022-10-26 20:39 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Marc Zyngier, Rob Herring, Krzysztof Kozlowski,
	Jonathan Corbet, Will Deacon, Catalin Marinas, Arnd Bergmann,
	Greg Kroah-Hartman, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel

On Wed, 26 Oct 2022 at 23:24, Elliot Berman <quic_eberman@quicinc.com> wrote:
>
>
> On 10/26/2022 12:46 PM, Dmitry Baryshkov wrote:
> > On 26/10/2022 21:58, Elliot Berman wrote:
> >> Fix build error when CONFIG_ARM64_SVE is selected and
> >> asm/alternative-macros.h wasn't implicitly included by another header.
> >
> > Please include the build error into the commit message to help anybody
> > looking for the solution for the same issue.
> >
>
> Now that the gunyah_hypercall implementation has been moved to its own
> module, this change isn't needed because asm/alternative-macros.h got
> implicitly included now. I can drop this, although not sure if we think
> it's still correct to have it?
>
> After I got rid of the other header files, for reference:
>
> In file included from arch/arm64/gunyah/gunyah_hypercall.c:6:
> arch/arm64/gunyah/gunyah_hypercall.c: In function ‘gh_hypercall_msgq_send’:
> ./include/linux/arm-smccc.h:387:25: error: expected string literal
> before ‘ALTERNATIVE’
>    387 | #define SMCCC_SVE_CHECK ALTERNATIVE("nop \n",  "bl
> __arm_smccc_sve_check \n", \

Please add this message to the commit log.

>
> >>
> >> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> >> ---
> >>   include/linux/arm-smccc.h | 1 +
> >>   1 file changed, 1 insertion(+)
> >>
> >> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> >> index 220c8c60e021..6a627cdbbdec 100644
> >> --- a/include/linux/arm-smccc.h
> >> +++ b/include/linux/arm-smccc.h
> >> @@ -383,6 +383,7 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0,
> >> unsigned long a1,
> >>   /* nVHE hypervisor doesn't have a current thread so needs separate
> >> checks */
> >>   #if defined(CONFIG_ARM64_SVE) && !defined(__KVM_NVHE_HYPERVISOR__)
> >> +#include <asm/alternative-macros.h>
> >>   #define SMCCC_SVE_CHECK ALTERNATIVE("nop \n",  "bl
> >> __arm_smccc_sve_check \n", \
> >>                       ARM64_SVE)
> >



-- 
With best wishes
Dmitry

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 09/21] mailbox: Add Gunyah message queue mailbox
  2022-10-26 18:58 ` [PATCH v6 09/21] mailbox: Add Gunyah message queue mailbox Elliot Berman
@ 2022-10-27 13:55   ` Pavan Kondeti
  2022-11-01 17:44     ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Pavan Kondeti @ 2022-10-27 13:55 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Jassi Brar, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Hi Elliot,

On Wed, Oct 26, 2022 at 11:58:34AM -0700, Elliot Berman wrote:
> Gunyah message queues are a unidirectional inter-VM pipe for messages up
> to 1024 bytes. This driver supports pairing a receiver message queue and
> a transmitter message queue to expose a single mailbox channel.
> 
> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>

<snip>

> +static irqreturn_t gh_msgq_tx_irq_handler(int irq, void *data)
> +{
> +	struct gh_msgq *msgq = data;
> +
> +	mbox_chan_txdone(gh_msgq_chan(msgq), 0);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void gh_msgq_txdone_tasklet(unsigned long data)
> +{
> +	struct gh_msgq *msgq = (struct gh_msgq *)data;
> +
> +	mbox_chan_txdone(gh_msgq_chan(msgq), msgq->last_status);
> +}
> +
> +static int gh_msgq_send_data(struct mbox_chan *chan, void *data)
> +{
> +	struct gh_msgq *msgq = mbox_chan_to_msgq(chan);
> +	struct gh_msgq_tx_data *msgq_data = data;
> +	u64 tx_flags = 0;
> +	unsigned long ret;
> +	bool ready;
> +
> +	if (msgq_data->push)
> +		tx_flags |= GH_HYPERCALL_MSGQ_TX_FLAGS_PUSH;
> +
> +	ret = gh_hypercall_msgq_send(msgq->tx_ghrsc->capid, msgq_data->length,
> +					(uintptr_t)msgq_data->data, tx_flags, &ready);
> +
> +	/**
> +	 * unlikely because Linux tracks state of msgq and should not try to
> +	 * send message when msgq is full.
> +	 */
> +	if (unlikely(ret == GH_ERROR_MSGQUEUE_FULL))
> +		return -EAGAIN;
> +
> +	/**
> +	 * Propagate all other errors to client. If we return error to mailbox
> +	 * framework, then no other messages can be sent and nobody will know
> +	 * to retry this message.
> +	 */
> +	msgq->last_status = gh_remap_error(ret);
> +
> +	/**
> +	 * This message was successfully sent, but message queue isn't ready to
> +	 * receive more messages because it's now full. Mailbox framework
> +	 * requires that we only report that message was transmitted only when
> +	 * we're ready to transmit another message. We'll get that in the form
> +	 * of tx IRQ once the other side starts to drain the msgq.
> +	 */
> +	if (ret == GH_ERROR_OK && !ready)
> +		return 0;
> +
> +	/**
> +	 * We can send more messages. Mailbox framework requires that tx done
> +	 * happens asynchronously to sending the message. Gunyah message queues
> +	 * tell us right away on the hypercall return whether we can send more
> +	 * messages. To work around this, defer the txdone to a tasklet.
> +	 */
> +	tasklet_schedule(&msgq->txdone_tasklet);
> +

Nice comments.

irq_work would be a better choice.

> +	return 0;
> +}
> +
> +struct mbox_chan_ops gh_msgq_ops = {
> +	.send_data = gh_msgq_send_data,
> +};
> +
> +/**
> + * gh_msgq_init() - Initialize a Gunyah message queue with an mbox_client
> + * @parent: optional, device parent used for the mailbox controller
> + * @msgq: Pointer to the gh_msgq to initialize
> + * @cl: A mailbox client to bind to the mailbox channel that the message queue creates
> + * @tx_ghrsc: optional, the transmission side of the message queue
> + * @rx_ghrsc: optional, the receiving side of the message queue
> + *
> + * At least one of tx_ghrsc and rx_ghrsc should be not NULL. Most message queue use cases come with
> + * a pair of message queues to facilitiate bidirectional communication. When tx_ghrsc is set,
> + * the client can send messages with mbox_send_message(gh_msgq_chan(msgq), msg). When rx_ghrsc
> + * is set, the mbox_client should register an .rx_callback() and the message queue driver will
> + * push all available messages upon receiving the RX ready interrupt. The messages should be
> + * consumed or copied by the client right away as the gh_msgq_rx_data will be replaced/destroyed
> + * after the callback.
> + *
> + * Returns - 0 on success, negative otherwise
> + */
> +int gh_msgq_init(struct device *parent, struct gh_msgq *msgq, struct mbox_client *cl,
> +		     struct gunyah_resource *tx_ghrsc, struct gunyah_resource *rx_ghrsc)
> +{
> +	int ret;
> +
> +	/* Must have at least a tx_ghrsc or rx_ghrsc and that they are the right device types */
> +	if ((!tx_ghrsc && !rx_ghrsc) ||
> +	    (tx_ghrsc && tx_ghrsc->type != GUNYAH_RESOURCE_TYPE_MSGQ_TX) ||
> +	    (rx_ghrsc && rx_ghrsc->type != GUNYAH_RESOURCE_TYPE_MSGQ_RX))
> +		return -EINVAL;
> +
> +	msgq->tx_ghrsc = tx_ghrsc;
> +	msgq->rx_ghrsc = rx_ghrsc;
> +
> +	msgq->mbox.dev = parent;
> +	msgq->mbox.ops = &gh_msgq_ops;
> +	msgq->mbox.chans = kcalloc(1, sizeof(*msgq->mbox.chans), GFP_KERNEL);

Error handling missing.

minor nit pick:

If you initialize num_chans to 1 before, then you can use that as the first
argument to kcalloc() which makes it more readable since you opted for kcalloc()
instead of kzalloc() there.

> +	msgq->mbox.num_chans = 1;
> +	msgq->mbox.txdone_irq = true;
> +
> +	if (gh_msgq_has_tx(msgq)) {
> +		ret = request_irq(msgq->tx_ghrsc->irq, gh_msgq_tx_irq_handler, 0, "gh_msgq_tx",
> +				msgq);
> +		if (ret)
> +			goto err_chans;
> +	}
> +
> +	if (gh_msgq_has_rx(msgq)) {
> +		ret = request_threaded_irq(msgq->rx_ghrsc->irq, NULL, gh_msgq_rx_irq_handler,
> +						IRQF_ONESHOT, "gh_msgq_rx", msgq);
> +		if (ret)
> +			goto err_tx_irq;
> +	}
> +
> +	tasklet_init(&msgq->txdone_tasklet, gh_msgq_txdone_tasklet, (unsigned long)msgq);

If you wish to use tasklets, use tasklet_setup().

> +
> +	ret = mbox_controller_register(&msgq->mbox);
> +	if (ret)
> +		goto err_rx_irq;
> +
> +	ret = mbox_bind_client(gh_msgq_chan(msgq), cl);
> +	if (ret)
> +		goto err_mbox;
> +
> +	return 0;
> +err_mbox:
> +	mbox_controller_unregister(&msgq->mbox);
> +err_rx_irq:
> +	if (gh_msgq_has_rx(msgq))
> +		free_irq(msgq->rx_ghrsc->irq, msgq);
> +err_tx_irq:
> +	if (gh_msgq_has_tx(msgq))
> +		free_irq(msgq->tx_ghrsc->irq, msgq);
> +err_chans:
> +	kfree(msgq->mbox.chans);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(gh_msgq_init);
> +
> +void gh_msgq_remove(struct gh_msgq *msgq)
> +{
> +	if (gh_msgq_has_rx(msgq))
> +		free_irq(msgq->rx_ghrsc->irq, msgq);
> +
> +	if (gh_msgq_has_tx(msgq))
> +		free_irq(msgq->tx_ghrsc->irq, msgq);
> +
> +	kfree(msgq->mbox.chans);
> +}
> +EXPORT_SYMBOL_GPL(gh_msgq_remove);
> +

Is gh_msgq_remove() supposed to undo every thing done in gh_msgq_init()?
ex: mbox controller and channel are not unregistered.

Thanks,
Pavan

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-10-26 18:58 ` [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor Elliot Berman
@ 2022-10-27 19:57   ` Krzysztof Kozlowski
  2022-10-28  2:33   ` Jassi Brar
  1 sibling, 0 replies; 67+ messages in thread
From: Krzysztof Kozlowski @ 2022-10-27 19:57 UTC (permalink / raw)
  To: Elliot Berman, Bjorn Andersson, Rob Herring, Krzysztof Kozlowski
  Cc: Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On 26/10/2022 14:58, Elliot Berman wrote:
> When Linux is booted as a guest under the Gunyah hypervisor, the Gunyah
> Resource Manager applies a devicetree overlay describing the virtual
> platform configuration of the guest VM, such as the message queue
> capability IDs for communicating with the Resource Manager. This
> information is not otherwise discoverable by a VM: the Gunyah hypervisor
> core does not provide a direct interface to discover capability IDs nor
> a way to communicate with RM without having already known the
> corresponding message queue capability ID. Add the DT bindings that
> Gunyah adheres for the hypervisor node and message queues.
> 
> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> ---
>  .../bindings/firmware/gunyah-hypervisor.yaml  | 86 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 87 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
> 
> diff --git a/Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml b/Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
> new file mode 100644
> index 000000000000..3a8c1c2157a4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/gunyah-hypervisor.yaml
> @@ -0,0 +1,86 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/firmware/gunyah-hypervisor.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Gunyah Hypervisor
> +
> +maintainers:
> +  - Murali Nalajala <quic_mnalajal@quicinc.com>
> +  - Elliot Berman <quic_eberman@quicinc.com>
> +
> +description: |+
> +  Gunyah virtual machines use this information to determine the capability IDs
> +  of the message queues used to communicate with the Gunyah Resource Manager.
> +  See also: https://github.com/quic/gunyah-resource-manager/blob/develop/src/vm_creation/dto_construct.c
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: gunyah-hypervisor-1.0
> +      - const: gunyah-hypervisor

You are sending next version while we still keep discussing old one...
and without necessary changes. Instead keep discussing the previous one
till we reach consensus.

These compatibles look wrong based on our discussion.

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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-10-26 18:58 ` [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor Elliot Berman
  2022-10-27 19:57   ` Krzysztof Kozlowski
@ 2022-10-28  2:33   ` Jassi Brar
  2022-11-01  3:19     ` Elliot Berman
  1 sibling, 1 reply; 67+ messages in thread
From: Jassi Brar @ 2022-10-28  2:33 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
.....
> +
> +        gunyah-resource-mgr@0 {
> +            compatible = "gunyah-resource-manager-1-0", "gunyah-resource-manager";
> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX full IRQ */
> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX empty IRQ */
> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
> +                  /* TX, RX cap ids */
> +        };
>
All these resources are used only by the mailbox controller driver.
So, this should be the mailbox controller node, rather than the
mailbox user.
One option is to load gunyah-resource-manager as a module that relies
on the gunyah-mailbox provider. That would also avoid the "Allow
direct registration to a channel" hack patch.

thanks.

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-10-28  2:33   ` Jassi Brar
@ 2022-11-01  3:19     ` Elliot Berman
  2022-11-01 16:23       ` Jassi Brar
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-01  3:19 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Hi Jassi,

On 10/27/2022 7:33 PM, Jassi Brar wrote:
 > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman 
<quic_eberman@quicinc.com> wrote:
 > .....
 >> +
 >> +        gunyah-resource-mgr@0 {
 >> +            compatible = "gunyah-resource-manager-1-0", 
"gunyah-resource-manager";
 >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX 
full IRQ */
 >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX 
empty IRQ */
 >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
 >> +                  /* TX, RX cap ids */
 >> +        };
 >>
 > All these resources are used only by the mailbox controller driver.
 > So, this should be the mailbox controller node, rather than the
 > mailbox user.> One option is to load gunyah-resource-manager as a 
module that relies
 > on the gunyah-mailbox provider. That would also avoid the "Allow
 > direct registration to a channel" hack patch.

A message queue to another guest VM wouldn't be known at boot time and 
thus couldn't be described on the devicetree. We will need "Allow direct 
registration to a channel" patch anyway to support those message queues. 
I would like to have one consistent mechanism to set up message queues.

- Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-01  3:19     ` Elliot Berman
@ 2022-11-01 16:23       ` Jassi Brar
  2022-11-01 20:35         ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Jassi Brar @ 2022-11-01 16:23 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>
> Hi Jassi,
>
> On 10/27/2022 7:33 PM, Jassi Brar wrote:
>  > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
> <quic_eberman@quicinc.com> wrote:
>  > .....
>  >> +
>  >> +        gunyah-resource-mgr@0 {
>  >> +            compatible = "gunyah-resource-manager-1-0",
> "gunyah-resource-manager";
>  >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
> full IRQ */
>  >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
> empty IRQ */
>  >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
>  >> +                  /* TX, RX cap ids */
>  >> +        };
>  >>
>  > All these resources are used only by the mailbox controller driver.
>  > So, this should be the mailbox controller node, rather than the
>  > mailbox user.> One option is to load gunyah-resource-manager as a
> module that relies
>  > on the gunyah-mailbox provider. That would also avoid the "Allow
>  > direct registration to a channel" hack patch.
>
> A message queue to another guest VM wouldn't be known at boot time and
> thus couldn't be described on the devicetree.
>
I think you need to implement of_xlate() ... or please tell me what
exactly you need to specify in the dt.

thnx.

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 09/21] mailbox: Add Gunyah message queue mailbox
  2022-10-27 13:55   ` Pavan Kondeti
@ 2022-11-01 17:44     ` Elliot Berman
  0 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-01 17:44 UTC (permalink / raw)
  To: Pavan Kondeti
  Cc: Bjorn Andersson, Jassi Brar, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel


On 10/27/2022 6:55 AM, Pavan Kondeti wrote:
> Hi Elliot,
> 
> On Wed, Oct 26, 2022 at 11:58:34AM -0700, Elliot Berman wrote:
>> Gunyah message queues are a unidirectional inter-VM pipe for messages up
>> to 1024 bytes. This driver supports pairing a receiver message queue and
>> a transmitter message queue to expose a single mailbox channel.
>>
>> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> 
> <snip>
> 
>> +static irqreturn_t gh_msgq_tx_irq_handler(int irq, void *data)
>> +{
>> +	struct gh_msgq *msgq = data;
>> +
>> +	mbox_chan_txdone(gh_msgq_chan(msgq), 0);
>> +
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +static void gh_msgq_txdone_tasklet(unsigned long data)
>> +{
>> +	struct gh_msgq *msgq = (struct gh_msgq *)data;
>> +
>> +	mbox_chan_txdone(gh_msgq_chan(msgq), msgq->last_status);
>> +}
>> +
>> +static int gh_msgq_send_data(struct mbox_chan *chan, void *data)
>> +{
>> +	struct gh_msgq *msgq = mbox_chan_to_msgq(chan);
>> +	struct gh_msgq_tx_data *msgq_data = data;
>> +	u64 tx_flags = 0;
>> +	unsigned long ret;
>> +	bool ready;
>> +
>> +	if (msgq_data->push)
>> +		tx_flags |= GH_HYPERCALL_MSGQ_TX_FLAGS_PUSH;
>> +
>> +	ret = gh_hypercall_msgq_send(msgq->tx_ghrsc->capid, msgq_data->length,
>> +					(uintptr_t)msgq_data->data, tx_flags, &ready);
>> +
>> +	/**
>> +	 * unlikely because Linux tracks state of msgq and should not try to
>> +	 * send message when msgq is full.
>> +	 */
>> +	if (unlikely(ret == GH_ERROR_MSGQUEUE_FULL))
>> +		return -EAGAIN;
>> +
>> +	/**
>> +	 * Propagate all other errors to client. If we return error to mailbox
>> +	 * framework, then no other messages can be sent and nobody will know
>> +	 * to retry this message.
>> +	 */
>> +	msgq->last_status = gh_remap_error(ret);
>> +
>> +	/**
>> +	 * This message was successfully sent, but message queue isn't ready to
>> +	 * receive more messages because it's now full. Mailbox framework
>> +	 * requires that we only report that message was transmitted only when
>> +	 * we're ready to transmit another message. We'll get that in the form
>> +	 * of tx IRQ once the other side starts to drain the msgq.
>> +	 */
>> +	if (ret == GH_ERROR_OK && !ready)
>> +		return 0;
>> +
>> +	/**
>> +	 * We can send more messages. Mailbox framework requires that tx done
>> +	 * happens asynchronously to sending the message. Gunyah message queues
>> +	 * tell us right away on the hypercall return whether we can send more
>> +	 * messages. To work around this, defer the txdone to a tasklet.
>> +	 */
>> +	tasklet_schedule(&msgq->txdone_tasklet);
>> +
> 
> Nice comments.
> 
> irq_work would be a better choice.
> 
>> +	return 0;
>> +}
>> +
>> +struct mbox_chan_ops gh_msgq_ops = {
>> +	.send_data = gh_msgq_send_data,
>> +};
>> +
>> +/**
>> + * gh_msgq_init() - Initialize a Gunyah message queue with an mbox_client
>> + * @parent: optional, device parent used for the mailbox controller
>> + * @msgq: Pointer to the gh_msgq to initialize
>> + * @cl: A mailbox client to bind to the mailbox channel that the message queue creates
>> + * @tx_ghrsc: optional, the transmission side of the message queue
>> + * @rx_ghrsc: optional, the receiving side of the message queue
>> + *
>> + * At least one of tx_ghrsc and rx_ghrsc should be not NULL. Most message queue use cases come with
>> + * a pair of message queues to facilitiate bidirectional communication. When tx_ghrsc is set,
>> + * the client can send messages with mbox_send_message(gh_msgq_chan(msgq), msg). When rx_ghrsc
>> + * is set, the mbox_client should register an .rx_callback() and the message queue driver will
>> + * push all available messages upon receiving the RX ready interrupt. The messages should be
>> + * consumed or copied by the client right away as the gh_msgq_rx_data will be replaced/destroyed
>> + * after the callback.
>> + *
>> + * Returns - 0 on success, negative otherwise
>> + */
>> +int gh_msgq_init(struct device *parent, struct gh_msgq *msgq, struct mbox_client *cl,
>> +		     struct gunyah_resource *tx_ghrsc, struct gunyah_resource *rx_ghrsc)
>> +{
>> +	int ret;
>> +
>> +	/* Must have at least a tx_ghrsc or rx_ghrsc and that they are the right device types */
>> +	if ((!tx_ghrsc && !rx_ghrsc) ||
>> +	    (tx_ghrsc && tx_ghrsc->type != GUNYAH_RESOURCE_TYPE_MSGQ_TX) ||
>> +	    (rx_ghrsc && rx_ghrsc->type != GUNYAH_RESOURCE_TYPE_MSGQ_RX))
>> +		return -EINVAL;
>> +
>> +	msgq->tx_ghrsc = tx_ghrsc;
>> +	msgq->rx_ghrsc = rx_ghrsc;
>> +
>> +	msgq->mbox.dev = parent;
>> +	msgq->mbox.ops = &gh_msgq_ops;
>> +	msgq->mbox.chans = kcalloc(1, sizeof(*msgq->mbox.chans), GFP_KERNEL);
> 
> Error handling missing.
> 
> minor nit pick:
> 
> If you initialize num_chans to 1 before, then you can use that as the first
> argument to kcalloc() which makes it more readable since you opted for kcalloc()
> instead of kzalloc() there.
> 
>> +	msgq->mbox.num_chans = 1;
>> +	msgq->mbox.txdone_irq = true;
>> +
>> +	if (gh_msgq_has_tx(msgq)) {
>> +		ret = request_irq(msgq->tx_ghrsc->irq, gh_msgq_tx_irq_handler, 0, "gh_msgq_tx",
>> +				msgq);
>> +		if (ret)
>> +			goto err_chans;
>> +	}
>> +
>> +	if (gh_msgq_has_rx(msgq)) {
>> +		ret = request_threaded_irq(msgq->rx_ghrsc->irq, NULL, gh_msgq_rx_irq_handler,
>> +						IRQF_ONESHOT, "gh_msgq_rx", msgq);
>> +		if (ret)
>> +			goto err_tx_irq;
>> +	}
>> +
>> +	tasklet_init(&msgq->txdone_tasklet, gh_msgq_txdone_tasklet, (unsigned long)msgq);
> 
> If you wish to use tasklets, use tasklet_setup().
> 
>> +
>> +	ret = mbox_controller_register(&msgq->mbox);
>> +	if (ret)
>> +		goto err_rx_irq;
>> +
>> +	ret = mbox_bind_client(gh_msgq_chan(msgq), cl);
>> +	if (ret)
>> +		goto err_mbox;
>> +
>> +	return 0;
>> +err_mbox:
>> +	mbox_controller_unregister(&msgq->mbox);
>> +err_rx_irq:
>> +	if (gh_msgq_has_rx(msgq))
>> +		free_irq(msgq->rx_ghrsc->irq, msgq);
>> +err_tx_irq:
>> +	if (gh_msgq_has_tx(msgq))
>> +		free_irq(msgq->tx_ghrsc->irq, msgq);
>> +err_chans:
>> +	kfree(msgq->mbox.chans);
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(gh_msgq_init);
>> +
>> +void gh_msgq_remove(struct gh_msgq *msgq)
>> +{
>> +	if (gh_msgq_has_rx(msgq))
>> +		free_irq(msgq->rx_ghrsc->irq, msgq);
>> +
>> +	if (gh_msgq_has_tx(msgq))
>> +		free_irq(msgq->tx_ghrsc->irq, msgq);
>> +
>> +	kfree(msgq->mbox.chans);
>> +}
>> +EXPORT_SYMBOL_GPL(gh_msgq_remove);
>> +
> 
> Is gh_msgq_remove() supposed to undo every thing done in gh_msgq_init()?
> ex: mbox controller and channel are not unregistered.
> 

Ah thanks for catching, updated this as well as rest of your comments.

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core
  2022-10-26 18:58 ` [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core Elliot Berman
@ 2022-11-01 18:02   ` Greg Kroah-Hartman
  2022-11-02  0:12     ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Greg Kroah-Hartman @ 2022-11-01 18:02 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

On Wed, Oct 26, 2022 at 11:58:35AM -0700, Elliot Berman wrote:
> The resource manager is a special virtual machine which is always
> running on a Gunyah system. It provides APIs for creating and destroying
> VMs, secure memory management, sharing/lending of memory between VMs,
> and setup of inter-VM communication. Calls to the resource manager are
> made via message queues.
> 
> This patch implements the basic probing and RPC mechanism to make those
> API calls. Request/response calls can be made with gh_rm_call.
> Drivers can also register to notifications pushed by RM via
> gh_rm_register_notifier
> 
> Specific API calls that resource manager supports will be implemented in
> subsequent patches.
> 
> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> ---
>  MAINTAINERS                    |   2 +-
>  drivers/virt/gunyah/Kconfig    |  15 +
>  drivers/virt/gunyah/Makefile   |   3 +
>  drivers/virt/gunyah/rsc_mgr.c  | 602 +++++++++++++++++++++++++++++++++
>  drivers/virt/gunyah/rsc_mgr.h  |  34 ++
>  include/linux/gunyah_rsc_mgr.h |  26 ++
>  6 files changed, 681 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/virt/gunyah/rsc_mgr.c
>  create mode 100644 drivers/virt/gunyah/rsc_mgr.h
>  create mode 100644 include/linux/gunyah_rsc_mgr.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 586539eadd3b..e072a0d2e553 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8945,7 +8945,7 @@ F:	Documentation/virt/gunyah/
>  F:	arch/arm64/gunyah/
>  F:	drivers/mailbox/gunyah-msgq.c
>  F:	drivers/virt/gunyah/
> -F:	include/linux/gunyah.h
> +F:	include/linux/gunyah*.h
>  
>  HABANALABS PCI DRIVER
>  M:	Oded Gabbay <ogabbay@kernel.org>
> diff --git a/drivers/virt/gunyah/Kconfig b/drivers/virt/gunyah/Kconfig
> index 127156a678a6..4de88d80aa7b 100644
> --- a/drivers/virt/gunyah/Kconfig
> +++ b/drivers/virt/gunyah/Kconfig
> @@ -10,3 +10,18 @@ config GUNYAH
>  
>  	  Say Y/M here to enable the drivers needed to interact in a Gunyah
>  	  virtual environment.
> +
> +config GUNYAH_RESORUCE_MANAGER
> +	tristate "Gunyah Resource Manager"
> +	select MAILBOX
> +	select GUNYAH_MESSAGE_QUEUES
> +	depends on GUNYAH
> +	default y

You only have "default y" if your machine can not boot without it.
Please do not add that here.

> +	help
> +	  The resource manager (RM) is a privileged application VM supporting
> +	  the Gunyah Hypervisor. Enable this driver to support communicating
> +	  with Gunyah RM. This is typically required for a VM running under
> +	  Gunyah wanting to have Gunyah-awareness.
> +
> +	  Say Y/M here if unsure.
> +
> diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile
> index 2ac4ee64b89d..2c18b0a56413 100644
> --- a/drivers/virt/gunyah/Makefile
> +++ b/drivers/virt/gunyah/Makefile
> @@ -1 +1,4 @@
>  obj-$(CONFIG_GUNYAH) += gunyah.o
> +
> +gunyah_rsc_mgr-y += rsc_mgr.o
> +obj-$(CONFIG_GUNYAH_RESORUCE_MANAGER) += gunyah_rsc_mgr.o
> diff --git a/drivers/virt/gunyah/rsc_mgr.c b/drivers/virt/gunyah/rsc_mgr.c
> new file mode 100644
> index 000000000000..a9fde703cbbe
> --- /dev/null
> +++ b/drivers/virt/gunyah/rsc_mgr.c
> @@ -0,0 +1,602 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#define pr_fmt(fmt) "gh_rsc_mgr: " fmt

This is a driver, you should never need this as you should be using the
dev_*() calls, not pr_*() calls as you always have access to a struct
device, right?

So you can drop this.


> +
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +#include <linux/mutex.h>
> +#include <linux/sched.h>
> +#include <linux/gunyah.h>
> +#include <linux/module.h>
> +#include <linux/of_irq.h>
> +#include <linux/kthread.h>
> +#include <linux/notifier.h>
> +#include <linux/workqueue.h>
> +#include <linux/completion.h>
> +#include <linux/gunyah_rsc_mgr.h>
> +#include <linux/platform_device.h>
> +
> +#include "rsc_mgr.h"
> +
> +/* Resource Manager Header */
> +struct gh_rm_rpc_hdr {
> +	u8 version : 4, hdr_words : 4;
> +	u8 type : 2, fragments : 6;

Ick, that's hard to read.  One variable per line please?

And why the bit packed stuff?  Are you sure this is the way to do this?
Why not use a bitmask instead?

> +	u16 seq;
> +	u32 msg_id;
> +} __packed;
> +
> +/* Standard reply header */
> +struct gh_rm_rpc_reply_hdr {
> +	struct gh_rm_rpc_hdr rpc_hdr;
> +	u32 err_code;
> +} __packed;
> +
> +/* RPC Header versions */
> +#define GH_RM_RPC_HDR_VERSION_ONE	0x1
> +
> +/* RPC Header words */
> +#define GH_RM_RPC_HDR_WORDS		0x2
> +
> +/* RPC Message types */
> +#define GH_RM_RPC_TYPE_CONT		0x0
> +#define GH_RM_RPC_TYPE_REQ		0x1
> +#define GH_RM_RPC_TYPE_RPLY		0x2
> +#define GH_RM_RPC_TYPE_NOTIF		0x3
> +
> +#define GH_RM_MAX_NUM_FRAGMENTS		62
> +
> +#define GH_RM_MAX_MSG_SIZE	(GH_MSGQ_MAX_MSG_SIZE - sizeof(struct gh_rm_rpc_hdr))
> +
> +/**
> + * struct gh_rm_connection - Represents a complete message from resource manager
> + * @payload: Combined payload of all the fragments (msg headers stripped off).
> + * @size: Size of the payload.
> + * @ret: Linux return code, set in case there was an error processing connection
> + * @msg_id: Message ID from the header.
> + * @type: GH_RM_RPC_TYPE_RPLY or GH_RM_RPC_TYPE_NOTIF.
> + * @num_fragments: total number of fragments expected to be received.
> + * @fragments_received: fragments received so far.
> + * @rm_error: For request/reply sequences with standard replies.
> + * @seq: Sequence ID for the main message.
> + * @seq_done: Signals caller that the RM reply has been received
> + */
> +struct gh_rm_connection {
> +	void *payload;
> +	size_t size;
> +	int ret;
> +	u32 msg_id;
> +	u8 type;
> +
> +	u8 num_fragments;
> +	u8 fragments_received;
> +
> +	/* only for req/reply sequence */
> +	u32 rm_error;
> +	u16 seq;
> +	struct completion seq_done;
> +};
> +
> +struct gh_rm_notif_complete {
> +	struct gh_rm_connection *conn;
> +	struct work_struct work;
> +};
> +
> +struct gh_rsc_mgr {
> +	struct gunyah_resource tx_ghrsc, rx_ghrsc;
> +	struct gh_msgq msgq;
> +	struct mbox_client msgq_client;
> +	struct gh_rm_connection *active_rx_connection;
> +	int last_tx_ret;
> +
> +	struct idr call_idr;
> +	struct mutex call_idr_lock;
> +
> +	struct mutex send_lock;
> +
> +	struct work_struct recv_work;
> +};
> +
> +static struct gh_rsc_mgr *__rsc_mgr;

Sorry, no, you don't get to just limit yourself to one of these.  Please
make this properly handle any number of "resource managers", static
variables like this is not ok.

> +SRCU_NOTIFIER_HEAD_STATIC(gh_rm_notifier);

Why do you need a notifier list?

Who will register for this?  For what?  Why?

> +static int gh_rm_drv_probe(struct platform_device *pdev)
> +{
> +	struct gh_rsc_mgr *rsc_mgr;
> +	int ret;
> +
> +	rsc_mgr = devm_kzalloc(&pdev->dev, sizeof(*rsc_mgr), GFP_KERNEL);
> +	if (!rsc_mgr)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, rsc_mgr);
> +
> +	mutex_init(&rsc_mgr->call_idr_lock);
> +	idr_init(&rsc_mgr->call_idr);
> +	mutex_init(&rsc_mgr->send_lock);
> +
> +	ret = gh_msgq_platform_probe_direction(pdev, GUNYAH_RESOURCE_TYPE_MSGQ_TX, 0,
> +						&rsc_mgr->tx_ghrsc);
> +	if (ret)
> +		return ret;
> +
> +	ret = gh_msgq_platform_probe_direction(pdev, GUNYAH_RESOURCE_TYPE_MSGQ_RX, 1,
> +						&rsc_mgr->rx_ghrsc);
> +	if (ret)
> +		return ret;
> +
> +	rsc_mgr->msgq_client.dev = &pdev->dev;

So your client device is the platform device, and not a new bridge
device that you create instead?  Why?


> +	rsc_mgr->msgq_client.tx_block = true;
> +	rsc_mgr->msgq_client.rx_callback = gh_rm_msgq_rx_data;
> +	rsc_mgr->msgq_client.tx_done = gh_rm_msgq_tx_done;
> +
> +	ret = gh_msgq_init(&pdev->dev, &rsc_mgr->msgq, &rsc_mgr->msgq_client,
> +				&rsc_mgr->tx_ghrsc, &rsc_mgr->rx_ghrsc);
> +	if (ret)
> +		return ret;
> +
> +	__rsc_mgr = rsc_mgr;
> +
> +	return 0;
> +}
> +static struct platform_driver gh_rm_driver = {
> +	.probe = gh_rm_drv_probe,
> +	.remove = gh_rm_drv_remove,
> +	.driver = {
> +		.name = "gh_rsc_mgr",
> +		.of_match_table = gh_rm_of_match,
> +	},

Wait, why is this a platform driver?  This is binding to a real device
on a real bus, not a random platform description in DT, right?

Or is it controlled by your DT?  I can't figure that out here, sorry.

thanks,

greg k-h

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-01 16:23       ` Jassi Brar
@ 2022-11-01 20:35         ` Elliot Berman
  2022-11-01 21:58           ` Jassi Brar
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-01 20:35 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel



On 11/1/2022 9:23 AM, Jassi Brar wrote:
> On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>
>> Hi Jassi,
>>
>> On 10/27/2022 7:33 PM, Jassi Brar wrote:
>>   > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
>> <quic_eberman@quicinc.com> wrote:
>>   > .....
>>   >> +
>>   >> +        gunyah-resource-mgr@0 {
>>   >> +            compatible = "gunyah-resource-manager-1-0",
>> "gunyah-resource-manager";
>>   >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
>> full IRQ */
>>   >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
>> empty IRQ */
>>   >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
>>   >> +                  /* TX, RX cap ids */
>>   >> +        };
>>   >>
>>   > All these resources are used only by the mailbox controller driver.
>>   > So, this should be the mailbox controller node, rather than the
>>   > mailbox user.> One option is to load gunyah-resource-manager as a
>> module that relies
>>   > on the gunyah-mailbox provider. That would also avoid the "Allow
>>   > direct registration to a channel" hack patch.
>>
>> A message queue to another guest VM wouldn't be known at boot time and
>> thus couldn't be described on the devicetree.
>>
> I think you need to implement of_xlate() ... or please tell me what
> exactly you need to specify in the dt.

Dynamically created virtual machines can't be known on the dt, so there 
is nothing to specify in the DT. There couldn't be a devicetree node for 
the message queue client because that client is only exists once the VM 
is created by userspace.

As a more concrete example, there is QRTR (net/qrtr) virtualization 
support which is implemented with Gunyah message queues. Whether a QRTR 
client needs to be for VM is only determined when launching the VM as 
well as which message queue resource the QRTR client should be using. 
Since many VMs could be running on a system, it's not possible to know 
the number of mailbox controllers (i.e. message queues) nor the number 
of mailbox clients (e.g. QRTR) as a static configuration in the DT.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-01 20:35         ` Elliot Berman
@ 2022-11-01 21:58           ` Jassi Brar
  2022-11-02  0:12             ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Jassi Brar @ 2022-11-01 21:58 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On Tue, Nov 1, 2022 at 3:35 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>
>
>
> On 11/1/2022 9:23 AM, Jassi Brar wrote:
> > On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>
> >> Hi Jassi,
> >>
> >> On 10/27/2022 7:33 PM, Jassi Brar wrote:
> >>   > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
> >> <quic_eberman@quicinc.com> wrote:
> >>   > .....
> >>   >> +
> >>   >> +        gunyah-resource-mgr@0 {
> >>   >> +            compatible = "gunyah-resource-manager-1-0",
> >> "gunyah-resource-manager";
> >>   >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
> >> full IRQ */
> >>   >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
> >> empty IRQ */
> >>   >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
> >>   >> +                  /* TX, RX cap ids */
> >>   >> +        };
> >>   >>
> >>   > All these resources are used only by the mailbox controller driver.
> >>   > So, this should be the mailbox controller node, rather than the
> >>   > mailbox user.> One option is to load gunyah-resource-manager as a
> >> module that relies
> >>   > on the gunyah-mailbox provider. That would also avoid the "Allow
> >>   > direct registration to a channel" hack patch.
> >>
> >> A message queue to another guest VM wouldn't be known at boot time and
> >> thus couldn't be described on the devicetree.
> >>
> > I think you need to implement of_xlate() ... or please tell me what
> > exactly you need to specify in the dt.
>
> Dynamically created virtual machines can't be known on the dt, so there
> is nothing to specify in the DT. There couldn't be a devicetree node for
> the message queue client because that client is only exists once the VM
> is created by userspace.
>
The underlying "physical channel" is the synchronous SMC instruction,
which remains 1 irrespective of the number of mailbox instances
created.
So basically you are sharing one resource among users. Why doesn't the
RM request the "smc instruction" channel once and share it among
users?

-j

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-01 21:58           ` Jassi Brar
@ 2022-11-02  0:12             ` Elliot Berman
  2022-11-02  2:01               ` Jassi Brar
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-02  0:12 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel



On 11/1/2022 2:58 PM, Jassi Brar wrote:
> On Tue, Nov 1, 2022 at 3:35 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>
>>
>>
>> On 11/1/2022 9:23 AM, Jassi Brar wrote:
>>> On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>
>>>> Hi Jassi,
>>>>
>>>> On 10/27/2022 7:33 PM, Jassi Brar wrote:
>>>>    > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
>>>> <quic_eberman@quicinc.com> wrote:
>>>>    > .....
>>>>    >> +
>>>>    >> +        gunyah-resource-mgr@0 {
>>>>    >> +            compatible = "gunyah-resource-manager-1-0",
>>>> "gunyah-resource-manager";
>>>>    >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
>>>> full IRQ */
>>>>    >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
>>>> empty IRQ */
>>>>    >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
>>>>    >> +                  /* TX, RX cap ids */
>>>>    >> +        };
>>>>    >>
>>>>    > All these resources are used only by the mailbox controller driver.
>>>>    > So, this should be the mailbox controller node, rather than the
>>>>    > mailbox user.> One option is to load gunyah-resource-manager as a
>>>> module that relies
>>>>    > on the gunyah-mailbox provider. That would also avoid the "Allow
>>>>    > direct registration to a channel" hack patch.
>>>>
>>>> A message queue to another guest VM wouldn't be known at boot time and
>>>> thus couldn't be described on the devicetree.
>>>>
>>> I think you need to implement of_xlate() ... or please tell me what
>>> exactly you need to specify in the dt.
>>
>> Dynamically created virtual machines can't be known on the dt, so there
>> is nothing to specify in the DT. There couldn't be a devicetree node for
>> the message queue client because that client is only exists once the VM
>> is created by userspace.
>>
> The underlying "physical channel" is the synchronous SMC instruction,
> which remains 1 irrespective of the number of mailbox instances
> created.

I disagree that the physical channel is the SMC instruction. Regardless 
though, there are num_online_cpus() "physical channels" with this 
perspective.

> So basically you are sharing one resource among users. Why doesn't the
> RM request the "smc instruction" channel once and share it among
> users?

I suppose in this scenario, a single mailbox channel would represent all 
message queues? This would cause Linux to serialize *all* message queue 
hypercalls. Sorry, I can only think negative implications.

Error handling needs to move into clients: if a TX message queue becomes 
full or an RX message queue becomes empty, then we'll need to return 
error back to the client right away. The clients would need to register 
for the RTS/RTR interrupts to know when to send/receive messages and 
have retry error handling. If the mailbox controller retried for the 
clients as currently proposed, then we could get into a scenario where a 
message queue could never be ready to send/receive and thus stuck 
forever trying to process that message. The effect here would be that 
the mailbox controller becomes a wrapper to some SMC instructions that 
aren't related at the SMC instruction level.

A single channel would limit performance of SMP systems because only one 
core could send/receive a message. There is no such limitation for 
message queues to behave like this.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core
  2022-11-01 18:02   ` Greg Kroah-Hartman
@ 2022-11-02  0:12     ` Elliot Berman
  2022-11-02  2:53       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-02  0:12 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/1/2022 11:02 AM, Greg Kroah-Hartman wrote:
> On Wed, Oct 26, 2022 at 11:58:35AM -0700, Elliot Berman wrote:
>> The resource manager is a special virtual machine which is always
>> running on a Gunyah system. It provides APIs for creating and destroying
>> VMs, secure memory management, sharing/lending of memory between VMs,
>> and setup of inter-VM communication. Calls to the resource manager are
>> made via message queues.
>>
>> This patch implements the basic probing and RPC mechanism to make those
>> API calls. Request/response calls can be made with gh_rm_call.
>> Drivers can also register to notifications pushed by RM via
>> gh_rm_register_notifier
>>
>> Specific API calls that resource manager supports will be implemented in
>> subsequent patches.
>>
>> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
>> ---
>>   MAINTAINERS                    |   2 +-
>>   drivers/virt/gunyah/Kconfig    |  15 +
>>   drivers/virt/gunyah/Makefile   |   3 +
>>   drivers/virt/gunyah/rsc_mgr.c  | 602 +++++++++++++++++++++++++++++++++
>>   drivers/virt/gunyah/rsc_mgr.h  |  34 ++
>>   include/linux/gunyah_rsc_mgr.h |  26 ++
>>   6 files changed, 681 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/virt/gunyah/rsc_mgr.c
>>   create mode 100644 drivers/virt/gunyah/rsc_mgr.h
>>   create mode 100644 include/linux/gunyah_rsc_mgr.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 586539eadd3b..e072a0d2e553 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -8945,7 +8945,7 @@ F:	Documentation/virt/gunyah/
>>   F:	arch/arm64/gunyah/
>>   F:	drivers/mailbox/gunyah-msgq.c
>>   F:	drivers/virt/gunyah/
>> -F:	include/linux/gunyah.h
>> +F:	include/linux/gunyah*.h
>>   
>>   HABANALABS PCI DRIVER
>>   M:	Oded Gabbay <ogabbay@kernel.org>
>> diff --git a/drivers/virt/gunyah/Kconfig b/drivers/virt/gunyah/Kconfig
>> index 127156a678a6..4de88d80aa7b 100644
>> --- a/drivers/virt/gunyah/Kconfig
>> +++ b/drivers/virt/gunyah/Kconfig
>> @@ -10,3 +10,18 @@ config GUNYAH
>>   
>>   	  Say Y/M here to enable the drivers needed to interact in a Gunyah
>>   	  virtual environment.
>> +
>> +config GUNYAH_RESORUCE_MANAGER
>> +	tristate "Gunyah Resource Manager"
>> +	select MAILBOX
>> +	select GUNYAH_MESSAGE_QUEUES
>> +	depends on GUNYAH
>> +	default y
> 
> You only have "default y" if your machine can not boot without it.
> Please do not add that here.
> 

There's a guideline in Documentation/kbuild/kconfig-language.rst to 
provide some sane defaults for subdriver behavior. Here, CONFIG_GUNYAH 
is default n. It's unlikely for someone to want to have Linux with base 
Gunyah support (hypercalls and hypervisor detection) without also having 
the Resource Manager driver. If it's better, I could change to default m?

>> +	help
>> +	  The resource manager (RM) is a privileged application VM supporting
>> +	  the Gunyah Hypervisor. Enable this driver to support communicating
>> +	  with Gunyah RM. This is typically required for a VM running under
>> +	  Gunyah wanting to have Gunyah-awareness.
>> +
>> +	  Say Y/M here if unsure.
>> +
>> diff --git a/drivers/virt/gunyah/Makefile b/drivers/virt/gunyah/Makefile
>> index 2ac4ee64b89d..2c18b0a56413 100644
>> --- a/drivers/virt/gunyah/Makefile
>> +++ b/drivers/virt/gunyah/Makefile
>> @@ -1 +1,4 @@
>>   obj-$(CONFIG_GUNYAH) += gunyah.o
>> +
>> +gunyah_rsc_mgr-y += rsc_mgr.o
>> +obj-$(CONFIG_GUNYAH_RESORUCE_MANAGER) += gunyah_rsc_mgr.o
>> diff --git a/drivers/virt/gunyah/rsc_mgr.c b/drivers/virt/gunyah/rsc_mgr.c
>> new file mode 100644
>> index 000000000000..a9fde703cbbe
>> --- /dev/null
>> +++ b/drivers/virt/gunyah/rsc_mgr.c
>> @@ -0,0 +1,602 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
>> + */
>> +
>> +#define pr_fmt(fmt) "gh_rsc_mgr: " fmt
> 
> This is a driver, you should never need this as you should be using the
> dev_*() calls, not pr_*() calls as you always have access to a struct
> device, right?
> 
> So you can drop this.
> 
> 

Ack

>> +
>> +#include <linux/of.h>
>> +#include <linux/slab.h>
>> +#include <linux/mutex.h>
>> +#include <linux/sched.h>
>> +#include <linux/gunyah.h>
>> +#include <linux/module.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/kthread.h>
>> +#include <linux/notifier.h>
>> +#include <linux/workqueue.h>
>> +#include <linux/completion.h>
>> +#include <linux/gunyah_rsc_mgr.h>
>> +#include <linux/platform_device.h>
>> +
>> +#include "rsc_mgr.h"
>> +
>> +/* Resource Manager Header */
>> +struct gh_rm_rpc_hdr {
>> +	u8 version : 4, hdr_words : 4;
>> +	u8 type : 2, fragments : 6;
> 
> Ick, that's hard to read.  One variable per line please?

Ack.

> And why the bit packed stuff?  Are you sure this is the way to do this?
> Why not use a bitmask instead?
> 

I felt bit packed implementation is cleaner and easier to map to 
understanding what the fields are used for.

>> +	u16 seq;
>> +	u32 msg_id;
>> +} __packed;
>> +
>> +/* Standard reply header */
>> +struct gh_rm_rpc_reply_hdr {
>> +	struct gh_rm_rpc_hdr rpc_hdr;
>> +	u32 err_code;
>> +} __packed;
>> +
>> +/* RPC Header versions */
>> +#define GH_RM_RPC_HDR_VERSION_ONE	0x1
>> +
>> +/* RPC Header words */
>> +#define GH_RM_RPC_HDR_WORDS		0x2
>> +
>> +/* RPC Message types */
>> +#define GH_RM_RPC_TYPE_CONT		0x0
>> +#define GH_RM_RPC_TYPE_REQ		0x1
>> +#define GH_RM_RPC_TYPE_RPLY		0x2
>> +#define GH_RM_RPC_TYPE_NOTIF		0x3
>> +
>> +#define GH_RM_MAX_NUM_FRAGMENTS		62
>> +
>> +#define GH_RM_MAX_MSG_SIZE	(GH_MSGQ_MAX_MSG_SIZE - sizeof(struct gh_rm_rpc_hdr))
>> +
>> +/**
>> + * struct gh_rm_connection - Represents a complete message from resource manager
>> + * @payload: Combined payload of all the fragments (msg headers stripped off).
>> + * @size: Size of the payload.
>> + * @ret: Linux return code, set in case there was an error processing connection
>> + * @msg_id: Message ID from the header.
>> + * @type: GH_RM_RPC_TYPE_RPLY or GH_RM_RPC_TYPE_NOTIF.
>> + * @num_fragments: total number of fragments expected to be received.
>> + * @fragments_received: fragments received so far.
>> + * @rm_error: For request/reply sequences with standard replies.
>> + * @seq: Sequence ID for the main message.
>> + * @seq_done: Signals caller that the RM reply has been received
>> + */
>> +struct gh_rm_connection {
>> +	void *payload;
>> +	size_t size;
>> +	int ret;
>> +	u32 msg_id;
>> +	u8 type;
>> +
>> +	u8 num_fragments;
>> +	u8 fragments_received;
>> +
>> +	/* only for req/reply sequence */
>> +	u32 rm_error;
>> +	u16 seq;
>> +	struct completion seq_done;
>> +};
>> +
>> +struct gh_rm_notif_complete {
>> +	struct gh_rm_connection *conn;
>> +	struct work_struct work;
>> +};
>> +
>> +struct gh_rsc_mgr {
>> +	struct gunyah_resource tx_ghrsc, rx_ghrsc;
>> +	struct gh_msgq msgq;
>> +	struct mbox_client msgq_client;
>> +	struct gh_rm_connection *active_rx_connection;
>> +	int last_tx_ret;
>> +
>> +	struct idr call_idr;
>> +	struct mutex call_idr_lock;
>> +
>> +	struct mutex send_lock;
>> +
>> +	struct work_struct recv_work;
>> +};
>> +
>> +static struct gh_rsc_mgr *__rsc_mgr;
> 
> Sorry, no, you don't get to just limit yourself to one of these.  Please
> make this properly handle any number of "resource managers", static
> variables like this is not ok.
> 

There will only ever be one resource manager. optee, psci, and qcom_scm 
use a similar approach.

>> +SRCU_NOTIFIER_HEAD_STATIC(gh_rm_notifier);
> 
> Why do you need a notifier list?
> 
> Who will register for this?  For what?  Why?
> 

The majority of notifications that RM sends to Linux will be related to 
VM state, e.g. "VM crashed." I've not added the handling in VM manager 
yet to reduce the number of patches in this series. It was used in the 
previous series for the console driver. I can remove for now and 
re-introduce it once VM manager makes use?

>> +static int gh_rm_drv_probe(struct platform_device *pdev)
>> +{
>> +	struct gh_rsc_mgr *rsc_mgr;
>> +	int ret;
>> +
>> +	rsc_mgr = devm_kzalloc(&pdev->dev, sizeof(*rsc_mgr), GFP_KERNEL);
>> +	if (!rsc_mgr)
>> +		return -ENOMEM;
>> +	platform_set_drvdata(pdev, rsc_mgr);
>> +
>> +	mutex_init(&rsc_mgr->call_idr_lock);
>> +	idr_init(&rsc_mgr->call_idr);
>> +	mutex_init(&rsc_mgr->send_lock);
>> +
>> +	ret = gh_msgq_platform_probe_direction(pdev, GUNYAH_RESOURCE_TYPE_MSGQ_TX, 0,
>> +						&rsc_mgr->tx_ghrsc);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = gh_msgq_platform_probe_direction(pdev, GUNYAH_RESOURCE_TYPE_MSGQ_RX, 1,
>> +						&rsc_mgr->rx_ghrsc);
>> +	if (ret)
>> +		return ret;
>> +
>> +	rsc_mgr->msgq_client.dev = &pdev->dev;
> 
> So your client device is the platform device, and not a new bridge
> device that you create instead?  Why?
> 

Answered below

>> +	rsc_mgr->msgq_client.tx_block = true;
>> +	rsc_mgr->msgq_client.rx_callback = gh_rm_msgq_rx_data;
>> +	rsc_mgr->msgq_client.tx_done = gh_rm_msgq_tx_done;
>> +
>> +	ret = gh_msgq_init(&pdev->dev, &rsc_mgr->msgq, &rsc_mgr->msgq_client,
>> +				&rsc_mgr->tx_ghrsc, &rsc_mgr->rx_ghrsc);
>> +	if (ret)
>> +		return ret;
>> +
>> +	__rsc_mgr = rsc_mgr;
>> +
>> +	return 0;
>> +}
>> +static struct platform_driver gh_rm_driver = {
>> +	.probe = gh_rm_drv_probe,
>> +	.remove = gh_rm_drv_remove,
>> +	.driver = {
>> +		.name = "gh_rsc_mgr",
>> +		.of_match_table = gh_rm_of_match,
>> +	},
> 
> Wait, why is this a platform driver?  This is binding to a real device
> on a real bus, not a random platform description in DT, right?

This a binding for a real device and not a "random platform description" 
in DT to get the driver probed.

> Or is it controlled by your DT?  I can't figure that out here, sorry.

There is some info in Patch 2 about why the DT node exists and how it 
looks. Essentially, The DT node is provided by Gunyah during boot and 
describes how Linux can communicate with resource manager.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-02  0:12             ` Elliot Berman
@ 2022-11-02  2:01               ` Jassi Brar
  2022-11-02 18:05                 ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Jassi Brar @ 2022-11-02  2:01 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On Tue, Nov 1, 2022 at 7:12 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>
>
>
> On 11/1/2022 2:58 PM, Jassi Brar wrote:
> > On Tue, Nov 1, 2022 at 3:35 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 11/1/2022 9:23 AM, Jassi Brar wrote:
> >>> On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>>>
> >>>> Hi Jassi,
> >>>>
> >>>> On 10/27/2022 7:33 PM, Jassi Brar wrote:
> >>>>    > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
> >>>> <quic_eberman@quicinc.com> wrote:
> >>>>    > .....
> >>>>    >> +
> >>>>    >> +        gunyah-resource-mgr@0 {
> >>>>    >> +            compatible = "gunyah-resource-manager-1-0",
> >>>> "gunyah-resource-manager";
> >>>>    >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
> >>>> full IRQ */
> >>>>    >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
> >>>> empty IRQ */
> >>>>    >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
> >>>>    >> +                  /* TX, RX cap ids */
> >>>>    >> +        };
> >>>>    >>
> >>>>    > All these resources are used only by the mailbox controller driver.
> >>>>    > So, this should be the mailbox controller node, rather than the
> >>>>    > mailbox user.> One option is to load gunyah-resource-manager as a
> >>>> module that relies
> >>>>    > on the gunyah-mailbox provider. That would also avoid the "Allow
> >>>>    > direct registration to a channel" hack patch.
> >>>>
> >>>> A message queue to another guest VM wouldn't be known at boot time and
> >>>> thus couldn't be described on the devicetree.
> >>>>
> >>> I think you need to implement of_xlate() ... or please tell me what
> >>> exactly you need to specify in the dt.
> >>
> >> Dynamically created virtual machines can't be known on the dt, so there
> >> is nothing to specify in the DT. There couldn't be a devicetree node for
> >> the message queue client because that client is only exists once the VM
> >> is created by userspace.
> >>
> > The underlying "physical channel" is the synchronous SMC instruction,
> > which remains 1 irrespective of the number of mailbox instances
> > created.
>
> I disagree that the physical channel is the SMC instruction. Regardless
> though, there are num_online_cpus() "physical channels" with this
> perspective.
>
> > So basically you are sharing one resource among users. Why doesn't the
> > RM request the "smc instruction" channel once and share it among
> > users?
>
> I suppose in this scenario, a single mailbox channel would represent all
> message queues? This would cause Linux to serialize *all* message queue
> hypercalls. Sorry, I can only think negative implications.
>
> Error handling needs to move into clients: if a TX message queue becomes
> full or an RX message queue becomes empty, then we'll need to return
> error back to the client right away. The clients would need to register
> for the RTS/RTR interrupts to know when to send/receive messages and
> have retry error handling. If the mailbox controller retried for the
> clients as currently proposed, then we could get into a scenario where a
> message queue could never be ready to send/receive and thus stuck
> forever trying to process that message. The effect here would be that
> the mailbox controller becomes a wrapper to some SMC instructions that
> aren't related at the SMC instruction level.
>
> A single channel would limit performance of SMP systems because only one
> core could send/receive a message. There is no such limitation for
> message queues to behave like this.
>
This is just an illusion. If Gunyah can handle multiple calls from a
VM parallely, even with the "bind-client-to-channel" hack you can't
make sure different channels run on different cpu cores.  If you are
ok with that, you could simply populate a mailbox controller with N
channels and allocate them in any order the clients ask.

-j

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core
  2022-11-02  0:12     ` Elliot Berman
@ 2022-11-02  2:53       ` Greg Kroah-Hartman
  2022-11-02 18:04         ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Greg Kroah-Hartman @ 2022-11-02  2:53 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

On Tue, Nov 01, 2022 at 05:12:58PM -0700, Elliot Berman wrote:
> 
> 
> On 11/1/2022 11:02 AM, Greg Kroah-Hartman wrote:
> > On Wed, Oct 26, 2022 at 11:58:35AM -0700, Elliot Berman wrote:
> > > The resource manager is a special virtual machine which is always
> > > running on a Gunyah system. It provides APIs for creating and destroying
> > > VMs, secure memory management, sharing/lending of memory between VMs,
> > > and setup of inter-VM communication. Calls to the resource manager are
> > > made via message queues.
> > > 
> > > This patch implements the basic probing and RPC mechanism to make those
> > > API calls. Request/response calls can be made with gh_rm_call.
> > > Drivers can also register to notifications pushed by RM via
> > > gh_rm_register_notifier
> > > 
> > > Specific API calls that resource manager supports will be implemented in
> > > subsequent patches.
> > > 
> > > Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
> > > ---
> > >   MAINTAINERS                    |   2 +-
> > >   drivers/virt/gunyah/Kconfig    |  15 +
> > >   drivers/virt/gunyah/Makefile   |   3 +
> > >   drivers/virt/gunyah/rsc_mgr.c  | 602 +++++++++++++++++++++++++++++++++
> > >   drivers/virt/gunyah/rsc_mgr.h  |  34 ++
> > >   include/linux/gunyah_rsc_mgr.h |  26 ++
> > >   6 files changed, 681 insertions(+), 1 deletion(-)
> > >   create mode 100644 drivers/virt/gunyah/rsc_mgr.c
> > >   create mode 100644 drivers/virt/gunyah/rsc_mgr.h
> > >   create mode 100644 include/linux/gunyah_rsc_mgr.h
> > > 
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index 586539eadd3b..e072a0d2e553 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -8945,7 +8945,7 @@ F:	Documentation/virt/gunyah/
> > >   F:	arch/arm64/gunyah/
> > >   F:	drivers/mailbox/gunyah-msgq.c
> > >   F:	drivers/virt/gunyah/
> > > -F:	include/linux/gunyah.h
> > > +F:	include/linux/gunyah*.h
> > >   HABANALABS PCI DRIVER
> > >   M:	Oded Gabbay <ogabbay@kernel.org>
> > > diff --git a/drivers/virt/gunyah/Kconfig b/drivers/virt/gunyah/Kconfig
> > > index 127156a678a6..4de88d80aa7b 100644
> > > --- a/drivers/virt/gunyah/Kconfig
> > > +++ b/drivers/virt/gunyah/Kconfig
> > > @@ -10,3 +10,18 @@ config GUNYAH
> > >   	  Say Y/M here to enable the drivers needed to interact in a Gunyah
> > >   	  virtual environment.
> > > +
> > > +config GUNYAH_RESORUCE_MANAGER
> > > +	tristate "Gunyah Resource Manager"
> > > +	select MAILBOX
> > > +	select GUNYAH_MESSAGE_QUEUES
> > > +	depends on GUNYAH
> > > +	default y
> > 
> > You only have "default y" if your machine can not boot without it.
> > Please do not add that here.
> > 
> 
> There's a guideline in Documentation/kbuild/kconfig-language.rst to provide
> some sane defaults for subdriver behavior. Here, CONFIG_GUNYAH is default n.
> It's unlikely for someone to want to have Linux with base Gunyah support
> (hypercalls and hypervisor detection) without also having the Resource
> Manager driver. If it's better, I could change to default m?

Why is this a separate build option at all anyway?  If you want
CONFIG_GUNYAH why would you ever turn this off?  So why even allow it to
be an option?  Just always built it depending on the main option.

> > > +/* Resource Manager Header */
> > > +struct gh_rm_rpc_hdr {
> > > +	u8 version : 4, hdr_words : 4;
> > > +	u8 type : 2, fragments : 6;
> > 
> > Ick, that's hard to read.  One variable per line please?
> 
> Ack.
> 
> > And why the bit packed stuff?  Are you sure this is the way to do this?
> > Why not use a bitmask instead?
> > 
> 
> I felt bit packed implementation is cleaner and easier to map to
> understanding what the fields are used for.

Ah, so this isn't what is on the "wire", then don't use a bitfield like
this, use a real variable and that will be faster and simpler to
understand.

> > > +static struct gh_rsc_mgr *__rsc_mgr;
> > 
> > Sorry, no, you don't get to just limit yourself to one of these.  Please
> > make this properly handle any number of "resource managers", static
> > variables like this is not ok.
> > 
> 
> There will only ever be one resource manager. optee, psci, and qcom_scm use
> a similar approach.

And all of those are also wrong.

There is no need for this variable at all, you are doing extra work to
make this a "single" device.  Just always work off of the device that
the driver core gave you and all is good and you will have no limits on
how many different ones you eventually get.  It will be less code
overall, so it's the right thing to do.

> > > +SRCU_NOTIFIER_HEAD_STATIC(gh_rm_notifier);
> > 
> > Why do you need a notifier list?
> > 
> > Who will register for this?  For what?  Why?
> > 
> 
> The majority of notifications that RM sends to Linux will be related to VM
> state, e.g. "VM crashed." I've not added the handling in VM manager yet to
> reduce the number of patches in this series. It was used in the previous
> series for the console driver. I can remove for now and re-introduce it once
> VM manager makes use?

Please remove if you are not using it.  Notifier lists are almost always
wrong when it comes to the driver model, so please don't add them now,
we can discuss it later if you feel it really needs to be introduced
then.

> > > +static struct platform_driver gh_rm_driver = {
> > > +	.probe = gh_rm_drv_probe,
> > > +	.remove = gh_rm_drv_remove,
> > > +	.driver = {
> > > +		.name = "gh_rsc_mgr",
> > > +		.of_match_table = gh_rm_of_match,
> > > +	},
> > 
> > Wait, why is this a platform driver?  This is binding to a real device
> > on a real bus, not a random platform description in DT, right?
> 
> This a binding for a real device and not a "random platform description" in
> DT to get the driver probed.
> 
> > Or is it controlled by your DT?  I can't figure that out here, sorry.
> 
> There is some info in Patch 2 about why the DT node exists and how it looks.
> Essentially, The DT node is provided by Gunyah during boot and describes how
> Linux can communicate with resource manager.

Ick, ok, for now let's leave this alone but for dynamic devices, you
should never use a platform device.  All devices that hang off of this
controller better not be platform devices, but belong to the bus type of
your new bus, right?

thanks,

greg k-h

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-10-26 18:58 ` [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager Elliot Berman
@ 2022-11-02  5:14   ` Greg Kroah-Hartman
  2022-11-02 18:45     ` Elliot Berman
  2022-11-02  7:31   ` Arnd Bergmann
  1 sibling, 1 reply; 67+ messages in thread
From: Greg Kroah-Hartman @ 2022-11-02  5:14 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

On Wed, Oct 26, 2022 at 11:58:38AM -0700, Elliot Berman wrote:
> +#define GH_CREATE_VM			_IO(GH_IOCTL_TYPE, 0x40) /* Returns a Gunyah VM fd */

Why 0x40?  Why not just use the same KVM ioctl numbers and names as you
are doing the same thing as them, right?

Normally your first ioctl is "0x01", not "0x40", so this feels really
odd.

thanks,

greg k-h

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-10-26 18:58 ` [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager Elliot Berman
  2022-11-02  5:14   ` Greg Kroah-Hartman
@ 2022-11-02  7:31   ` Arnd Bergmann
  2022-11-02 18:44     ` Elliot Berman
  1 sibling, 1 reply; 67+ messages in thread
From: Arnd Bergmann @ 2022-11-02  7:31 UTC (permalink / raw)
  To: Elliot Berman, Bjorn Andersson
  Cc: Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Greg Kroah-Hartman, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

On Wed, Oct 26, 2022, at 20:58, Elliot Berman wrote:

> +static const struct file_operations gh_vm_fops = {
> +	.unlocked_ioctl = gh_vm_ioctl,
> +	.release = gh_vm_release,
> +	.llseek = noop_llseek,
> +};

There should be a .compat_ioctl entry here, otherwise it is
impossible to use from 32-bit tasks. If all commands have
arguments passed through a pointer to a properly defined
structure, you can just set it to compat_ptr_ioctl.

> +static long gh_dev_ioctl_create_vm(unsigned long arg)
> +{
> +	struct gunyah_vm *ghvm;
> +	struct file *file;
> +	int fd, err;
> +
> +	/* arg reserved for future use. */
> +	if (arg)
> +		return -EINVAL;

Do you have something specific in mind here? If 'create'
is the only command you support, and it has no arguments,
it would be easier to do it implicitly during open() and
have each fd opened from /dev/gunyah represent a new VM.

> +	ghvm = gunyah_vm_alloc();
> +	if (IS_ERR_OR_NULL(ghvm))
> +		return PTR_ERR(ghvm) ? : -ENOMEM;

If you find yourself using IS_ERR_OR_NULL(), you have
usually made a mistake. In this case, the gunyah_vm_alloc()
function is badly defined and should just return -ENOMEM
for an allocation failure.

> +static struct gunyah_rsc_mgr_device_id vm_mgr_ids[] = {
> +	{ .name = GH_RM_DEVICE_VM_MGR },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(gunyah_rsc_mgr, vm_mgr_ids);
> +
> +static struct gh_rm_driver vm_mgr_drv = {
> +	.drv = {
> +		.name = KBUILD_MODNAME,
> +		.probe = vm_mgr_probe,
> +		.remove = vm_mgr_remove,
> +	},
> +	.id_table = vm_mgr_ids,
> +};
> +module_gh_rm_driver(vm_mgr_drv);

It looks like the gunyah_rsc_mgr_device_id in this case is
purely internal to the kernel, so you are adding abstraction
layers to something that does not need to be abstracted
because the host side has no corresponding concept of
devices.

I'm correct, you can just turn the entire bus/device/driver
structure within your code into simple function calls, where
the main code calls vm_mgr_probe() as an exported function
instead of creating a device.

      Arnd

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 01/21] docs: gunyah: Introduce Gunyah Hypervisor
  2022-10-26 18:58 ` [PATCH v6 01/21] docs: gunyah: Introduce Gunyah Hypervisor Elliot Berman
@ 2022-11-02 12:35   ` Bagas Sanjaya
  0 siblings, 0 replies; 67+ messages in thread
From: Bagas Sanjaya @ 2022-11-02 12:35 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Jonathan Corbet, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Will Deacon, Catalin Marinas,
	Arnd Bergmann, Greg Kroah-Hartman, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 651 bytes --]

On Wed, Oct 26, 2022 at 11:58:26AM -0700, Elliot Berman wrote:
> Gunyah is an open-source Type-1 hypervisor developed by Qualcomm. It
> does not depend on any lower-privileged OS/kernel code for its core
> functionality. This increases its security and can support a smaller
> trusted computing based when compared to Type-2 hypervisors.
> 
> Add documentation describing the Gunyah hypervisor and the main
> components of the Gunyah hypervisor which are of interest to Linux
> virtualization development.
> 

LGTM, thanks.

Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>

-- 
An old man doll... just what I always wanted! - Clara

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

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 21/21] docs: gunyah: Document Gunyah VM Manager
  2022-10-26 18:58 ` [PATCH v6 21/21] docs: gunyah: Document Gunyah VM Manager Elliot Berman
@ 2022-11-02 13:05   ` Bagas Sanjaya
  2022-11-02 18:04     ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Bagas Sanjaya @ 2022-11-02 13:05 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Jonathan Corbet, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Will Deacon, Catalin Marinas,
	Arnd Bergmann, Greg Kroah-Hartman, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 7546 bytes --]

On Wed, Oct 26, 2022 at 11:58:46AM -0700, Elliot Berman wrote:
> diff --git a/Documentation/virt/gunyah/vm-manager.rst b/Documentation/virt/gunyah/vm-manager.rst
> new file mode 100644
> index 000000000000..c232ba05de7e
> --- /dev/null
> +++ b/Documentation/virt/gunyah/vm-manager.rst
> @@ -0,0 +1,94 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +=======================
> +Virtual Machine Manager
> +=======================
> +
> +The Gunyah Virtual Machine Manager is a Linux driver to support launching virtual machines.
> +
> +Summary
> +=======
> +
> +Gunyah VMM presently supports launching non-proxy scheduled Linux-like virtual machines.
> +
> +Sample Userspace VMM
> +====================
> +
> +A sample userspace VMM is included in samples/gunyah/ along with a sample minimal devicetree
> +that can be used to launch a Linux-like virtual machine under Gunyah. To build this sample, enable
> +CONFIG_SAMPLE_GUNYAH.
> +
> +IOCTLs and userspace VMM flows
> +==============================
> +
> +The kernel exposes a char device interface at /dev/gunyah.
> +
> +To create a VM, use the GH_CREATE_VM ioctl. A successful call will return a "Gunyah VM" file descriptor.
> +
> +/dev/gunyah API Descriptions
> +----------------------------
> +
> +GH_CREATE_VM
> +~~~~~~~~~~~~
> +
> +Creates a Gunyah VM. The argument is reserved for future use and must be 0.
> +
> +Gunyah VM API Descriptions
> +--------------------------
> +
> +GH_VM_SET_USER_MEM_REGION
> +~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +::
> +
> +  struct gh_userspace_memory_region {
> +	__u32 label;
> +	__u32 flags;
> +	__u64 guest_phys_addr;
> +	__u64 memory_size;
> +	__u64 userspace_addr;
> +  };
> +
> +This ioctl allows the user to create or delete a memory parcel for a guest
> +virtual machine. Each memory region is uniquely identified by a label;
> +attempting to create two memory regions with the same label is not allowed.
> +
> +While VMM is guest-agnostic and allows runtime addition of memory regions,
> +Linux guest virtual machines do not support accepting memory regions at runtime.
> +Thus, memory regions should be provided before starting the VM and the VM
> +configured to accept those memory regions at boot-up.
> +
> +The guest physical address is used by Linux to check the requested user regions
> +do not overlap and to help find a corresponding memory region for calls like
> +GH_VM_SET_DTB_CONFIG.
> +
> +To delete a memory region, call GH_VM_SET_USER_MEM_REGION with label set to the
> +memory region of interest and memory_size set to 0.
> +
> +The flags field of gh_userspace_memory_region can set the following bits. All
> +other bits must be 0 and are reserved for future use. The ioctl will return
> +-EINVAL if an unsupported bit is detected.
> +
> +  - GH_MEM_ALLOW_READ/GH_MEM_ALLOW_WRITE/GH_MEM_ALLOW_EXEC sets read/write/exec permissions
> +    for the guest, respectively.
> +
> +  - GH_MEM_LENT means that the memory will be unmapped from the host and be unaccessible by
> +    the host while the guest has the region.
> +
> +GH_VM_SET_DTB_CONFIG
> +~~~~~~~~~~~~~~~~~~~~
> +
> +::
> +
> +  struct gh_vm_dtb_config {
> +	__u64 gpa;
> +	__u64 size;
> +  };
> +
> +This ioctl sets the location of the VM's devicetree blob and is used by Gunyah
> +Resource Manager to allocate resources.
> +
> +GH_VM_START
> +~~~~~~~~~~~
> +
> +This ioctl starts the virtual machine.

I think the wording can be better:

---- >8 ----

diff --git a/Documentation/virt/gunyah/vm-manager.rst b/Documentation/virt/gunyah/vm-manager.rst
index c232ba05de7e96..772fd970b91d7e 100644
--- a/Documentation/virt/gunyah/vm-manager.rst
+++ b/Documentation/virt/gunyah/vm-manager.rst
@@ -4,18 +4,15 @@
 Virtual Machine Manager
 =======================
 
-The Gunyah Virtual Machine Manager is a Linux driver to support launching virtual machines.
-
-Summary
-=======
-
-Gunyah VMM presently supports launching non-proxy scheduled Linux-like virtual machines.
+The Gunyah Virtual Machine Manager is a Linux driver for launching virtual
+machines using Gunyah. It presently supports launching non-proxy scheduled
+Linux-like virtual machines.
 
 Sample Userspace VMM
 ====================
 
-A sample userspace VMM is included in samples/gunyah/ along with a sample minimal devicetree
-that can be used to launch a Linux-like virtual machine under Gunyah. To build this sample, enable
+A sample userspace VMM is included in samples/gunyah/ along with a minimal
+devicetree that can be used to launch a VM. To build this sample, enable
 CONFIG_SAMPLE_GUNYAH.
 
 IOCTLs and userspace VMM flows
@@ -23,7 +20,8 @@ IOCTLs and userspace VMM flows
 
 The kernel exposes a char device interface at /dev/gunyah.
 
-To create a VM, use the GH_CREATE_VM ioctl. A successful call will return a "Gunyah VM" file descriptor.
+To create a VM, use the GH_CREATE_VM ioctl. A successful call will return a
+"Gunyah VM" file descriptor.
 
 /dev/gunyah API Descriptions
 ----------------------------
@@ -51,29 +49,28 @@ GH_VM_SET_USER_MEM_REGION
 
 This ioctl allows the user to create or delete a memory parcel for a guest
 virtual machine. Each memory region is uniquely identified by a label;
-attempting to create two memory regions with the same label is not allowed.
+attempting to create two regions with the same label is not allowed.
 
 While VMM is guest-agnostic and allows runtime addition of memory regions,
 Linux guest virtual machines do not support accepting memory regions at runtime.
-Thus, memory regions should be provided before starting the VM and the VM
-configured to accept those memory regions at boot-up.
+Thus, memory regions should be provided before starting the VM and the VM must
+be configured to accept these at boot-up.
 
-The guest physical address is used by Linux to check the requested user regions
-do not overlap and to help find a corresponding memory region for calls like
-GH_VM_SET_DTB_CONFIG.
+The guest physical address is used by Linux kernel to check that the requested
+user regions do not overlap and to help find the corresponding memory region
+for calls like GH_VM_SET_DTB_CONFIG.
 
 To delete a memory region, call GH_VM_SET_USER_MEM_REGION with label set to the
-memory region of interest and memory_size set to 0.
+desired region and memory_size set to 0.
 
-The flags field of gh_userspace_memory_region can set the following bits. All
+The flags field of gh_userspace_memory_region accepts the following bits. All
 other bits must be 0 and are reserved for future use. The ioctl will return
 -EINVAL if an unsupported bit is detected.
 
-  - GH_MEM_ALLOW_READ/GH_MEM_ALLOW_WRITE/GH_MEM_ALLOW_EXEC sets read/write/exec permissions
-    for the guest, respectively.
-
-  - GH_MEM_LENT means that the memory will be unmapped from the host and be unaccessible by
-    the host while the guest has the region.
+  - GH_MEM_ALLOW_READ/GH_MEM_ALLOW_WRITE/GH_MEM_ALLOW_EXEC sets read/write/exec
+    permissions for the guest, respectively.
+  - GH_MEM_LENT means that the memory will be unmapped from the host and be
+    unaccessible by the host while the guest has the region.
 
 GH_VM_SET_DTB_CONFIG
 ~~~~~~~~~~~~~~~~~~~~
@@ -91,4 +88,4 @@ Resource Manager to allocate resources.
 GH_VM_START
 ~~~~~~~~~~~
 
-This ioctl starts the virtual machine.
+This ioctl starts the VM.

Thanks. 

-- 
An old man doll... just what I always wanted! - Clara

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

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 21/21] docs: gunyah: Document Gunyah VM Manager
  2022-11-02 13:05   ` Bagas Sanjaya
@ 2022-11-02 18:04     ` Elliot Berman
  0 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-02 18:04 UTC (permalink / raw)
  To: Bagas Sanjaya
  Cc: Bjorn Andersson, Jonathan Corbet, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Will Deacon, Catalin Marinas,
	Arnd Bergmann, Greg Kroah-Hartman, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/2/2022 6:05 AM, Bagas Sanjaya wrote:
> On Wed, Oct 26, 2022 at 11:58:46AM -0700, Elliot Berman wrote:
>> diff --git a/Documentation/virt/gunyah/vm-manager.rst b/Documentation/virt/gunyah/vm-manager.rst
>> new file mode 100644
>> index 000000000000..c232ba05de7e
>> --- /dev/null
>> +++ b/Documentation/virt/gunyah/vm-manager.rst
>> @@ -0,0 +1,94 @@
>> +.. SPDX-License-Identifier: GPL-2.0
>> +
>> +=======================
>> +Virtual Machine Manager
>> +=======================
>> +
>> +The Gunyah Virtual Machine Manager is a Linux driver to support launching virtual machines.
>> +
>> +Summary
>> +=======
>> +
>> +Gunyah VMM presently supports launching non-proxy scheduled Linux-like virtual machines.
>> +
>> +Sample Userspace VMM
>> +====================
>> +
>> +A sample userspace VMM is included in samples/gunyah/ along with a sample minimal devicetree
>> +that can be used to launch a Linux-like virtual machine under Gunyah. To build this sample, enable
>> +CONFIG_SAMPLE_GUNYAH.
>> +
>> +IOCTLs and userspace VMM flows
>> +==============================
>> +
>> +The kernel exposes a char device interface at /dev/gunyah.
>> +
>> +To create a VM, use the GH_CREATE_VM ioctl. A successful call will return a "Gunyah VM" file descriptor.
>> +
>> +/dev/gunyah API Descriptions
>> +----------------------------
>> +
>> +GH_CREATE_VM
>> +~~~~~~~~~~~~
>> +
>> +Creates a Gunyah VM. The argument is reserved for future use and must be 0.
>> +
>> +Gunyah VM API Descriptions
>> +--------------------------
>> +
>> +GH_VM_SET_USER_MEM_REGION
>> +~~~~~~~~~~~~~~~~~~~~~~~~~
>> +
>> +::
>> +
>> +  struct gh_userspace_memory_region {
>> +	__u32 label;
>> +	__u32 flags;
>> +	__u64 guest_phys_addr;
>> +	__u64 memory_size;
>> +	__u64 userspace_addr;
>> +  };
>> +
>> +This ioctl allows the user to create or delete a memory parcel for a guest
>> +virtual machine. Each memory region is uniquely identified by a label;
>> +attempting to create two memory regions with the same label is not allowed.
>> +
>> +While VMM is guest-agnostic and allows runtime addition of memory regions,
>> +Linux guest virtual machines do not support accepting memory regions at runtime.
>> +Thus, memory regions should be provided before starting the VM and the VM
>> +configured to accept those memory regions at boot-up.
>> +
>> +The guest physical address is used by Linux to check the requested user regions
>> +do not overlap and to help find a corresponding memory region for calls like
>> +GH_VM_SET_DTB_CONFIG.
>> +
>> +To delete a memory region, call GH_VM_SET_USER_MEM_REGION with label set to the
>> +memory region of interest and memory_size set to 0.
>> +
>> +The flags field of gh_userspace_memory_region can set the following bits. All
>> +other bits must be 0 and are reserved for future use. The ioctl will return
>> +-EINVAL if an unsupported bit is detected.
>> +
>> +  - GH_MEM_ALLOW_READ/GH_MEM_ALLOW_WRITE/GH_MEM_ALLOW_EXEC sets read/write/exec permissions
>> +    for the guest, respectively.
>> +
>> +  - GH_MEM_LENT means that the memory will be unmapped from the host and be unaccessible by
>> +    the host while the guest has the region.
>> +
>> +GH_VM_SET_DTB_CONFIG
>> +~~~~~~~~~~~~~~~~~~~~
>> +
>> +::
>> +
>> +  struct gh_vm_dtb_config {
>> +	__u64 gpa;
>> +	__u64 size;
>> +  };
>> +
>> +This ioctl sets the location of the VM's devicetree blob and is used by Gunyah
>> +Resource Manager to allocate resources.
>> +
>> +GH_VM_START
>> +~~~~~~~~~~~
>> +
>> +This ioctl starts the virtual machine.
> 
> I think the wording can be better:
> 
> ---- >8 ----
> 
> diff --git a/Documentation/virt/gunyah/vm-manager.rst b/Documentation/virt/gunyah/vm-manager.rst
> index c232ba05de7e96..772fd970b91d7e 100644
> --- a/Documentation/virt/gunyah/vm-manager.rst
> +++ b/Documentation/virt/gunyah/vm-manager.rst
> @@ -4,18 +4,15 @@
>   Virtual Machine Manager
>   =======================
>   
> -The Gunyah Virtual Machine Manager is a Linux driver to support launching virtual machines.
> -
> -Summary
> -=======
> -
> -Gunyah VMM presently supports launching non-proxy scheduled Linux-like virtual machines.
> +The Gunyah Virtual Machine Manager is a Linux driver for launching virtual
> +machines using Gunyah. It presently supports launching non-proxy scheduled
> +Linux-like virtual machines.
>   
>   Sample Userspace VMM
>   ====================
>   
> -A sample userspace VMM is included in samples/gunyah/ along with a sample minimal devicetree
> -that can be used to launch a Linux-like virtual machine under Gunyah. To build this sample, enable
> +A sample userspace VMM is included in samples/gunyah/ along with a minimal
> +devicetree that can be used to launch a VM. To build this sample, enable
>   CONFIG_SAMPLE_GUNYAH.
>   
>   IOCTLs and userspace VMM flows
> @@ -23,7 +20,8 @@ IOCTLs and userspace VMM flows
>   
>   The kernel exposes a char device interface at /dev/gunyah.
>   
> -To create a VM, use the GH_CREATE_VM ioctl. A successful call will return a "Gunyah VM" file descriptor.
> +To create a VM, use the GH_CREATE_VM ioctl. A successful call will return a
> +"Gunyah VM" file descriptor.
>   
>   /dev/gunyah API Descriptions
>   ----------------------------
> @@ -51,29 +49,28 @@ GH_VM_SET_USER_MEM_REGION
>   
>   This ioctl allows the user to create or delete a memory parcel for a guest
>   virtual machine. Each memory region is uniquely identified by a label;
> -attempting to create two memory regions with the same label is not allowed.
> +attempting to create two regions with the same label is not allowed.
>   
>   While VMM is guest-agnostic and allows runtime addition of memory regions,
>   Linux guest virtual machines do not support accepting memory regions at runtime.
> -Thus, memory regions should be provided before starting the VM and the VM
> -configured to accept those memory regions at boot-up.
> +Thus, memory regions should be provided before starting the VM and the VM must
> +be configured to accept these at boot-up.
>   
> -The guest physical address is used by Linux to check the requested user regions
> -do not overlap and to help find a corresponding memory region for calls like
> -GH_VM_SET_DTB_CONFIG.
> +The guest physical address is used by Linux kernel to check that the requested
> +user regions do not overlap and to help find the corresponding memory region
> +for calls like GH_VM_SET_DTB_CONFIG.
>   
>   To delete a memory region, call GH_VM_SET_USER_MEM_REGION with label set to the
> -memory region of interest and memory_size set to 0.
> +desired region and memory_size set to 0.
>   
> -The flags field of gh_userspace_memory_region can set the following bits. All
> +The flags field of gh_userspace_memory_region accepts the following bits. All
>   other bits must be 0 and are reserved for future use. The ioctl will return
>   -EINVAL if an unsupported bit is detected.
>   
> -  - GH_MEM_ALLOW_READ/GH_MEM_ALLOW_WRITE/GH_MEM_ALLOW_EXEC sets read/write/exec permissions
> -    for the guest, respectively.
> -
> -  - GH_MEM_LENT means that the memory will be unmapped from the host and be unaccessible by
> -    the host while the guest has the region.
> +  - GH_MEM_ALLOW_READ/GH_MEM_ALLOW_WRITE/GH_MEM_ALLOW_EXEC sets read/write/exec
> +    permissions for the guest, respectively.
> +  - GH_MEM_LENT means that the memory will be unmapped from the host and be
> +    unaccessible by the host while the guest has the region.

One side question -- before, you asked that I add newline between the 
list entries. Here, you've removed them. When do I need the extra 
newline vs not?

https://lore.kernel.org/all/YzUUaIx+azyzFDNX@debian.me/

>   
>   GH_VM_SET_DTB_CONFIG
>   ~~~~~~~~~~~~~~~~~~~~
> @@ -91,4 +88,4 @@ Resource Manager to allocate resources.
>   GH_VM_START
>   ~~~~~~~~~~~
>   
> -This ioctl starts the virtual machine.
> +This ioctl starts the VM.
> 
> Thanks.
> 

Thanks for reviewing and providing all the suggestions. I've applied all 
of them.




_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core
  2022-11-02  2:53       ` Greg Kroah-Hartman
@ 2022-11-02 18:04         ` Elliot Berman
  2022-11-03  0:22           ` Greg Kroah-Hartman
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-02 18:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jassi Brar
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/1/2022 7:53 PM, Greg Kroah-Hartman wrote:
> On Tue, Nov 01, 2022 at 05:12:58PM -0700, Elliot Berman wrote:
>>
>>
>> On 11/1/2022 11:02 AM, Greg Kroah-Hartman wrote:
>>> On Wed, Oct 26, 2022 at 11:58:35AM -0700, Elliot Berman wrote:
>>>> The resource manager is a special virtual machine which is always
>>>> running on a Gunyah system. It provides APIs for creating and destroying
>>>> VMs, secure memory management, sharing/lending of memory between VMs,
>>>> and setup of inter-VM communication. Calls to the resource manager are
>>>> made via message queues.
>>>>
>>>> This patch implements the basic probing and RPC mechanism to make those
>>>> API calls. Request/response calls can be made with gh_rm_call.
>>>> Drivers can also register to notifications pushed by RM via
>>>> gh_rm_register_notifier
>>>>
>>>> Specific API calls that resource manager supports will be implemented in
>>>> subsequent patches.
>>>>
>>>> Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
>>>> ---
>>>>    MAINTAINERS                    |   2 +-
>>>>    drivers/virt/gunyah/Kconfig    |  15 +
>>>>    drivers/virt/gunyah/Makefile   |   3 +
>>>>    drivers/virt/gunyah/rsc_mgr.c  | 602 +++++++++++++++++++++++++++++++++
>>>>    drivers/virt/gunyah/rsc_mgr.h  |  34 ++
>>>>    include/linux/gunyah_rsc_mgr.h |  26 ++
>>>>    6 files changed, 681 insertions(+), 1 deletion(-)
>>>>    create mode 100644 drivers/virt/gunyah/rsc_mgr.c
>>>>    create mode 100644 drivers/virt/gunyah/rsc_mgr.h
>>>>    create mode 100644 include/linux/gunyah_rsc_mgr.h
>>>>
>>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>>> index 586539eadd3b..e072a0d2e553 100644
>>>> --- a/MAINTAINERS
>>>> +++ b/MAINTAINERS
>>>> @@ -8945,7 +8945,7 @@ F:	Documentation/virt/gunyah/
>>>>    F:	arch/arm64/gunyah/
>>>>    F:	drivers/mailbox/gunyah-msgq.c
>>>>    F:	drivers/virt/gunyah/
>>>> -F:	include/linux/gunyah.h
>>>> +F:	include/linux/gunyah*.h
>>>>    HABANALABS PCI DRIVER
>>>>    M:	Oded Gabbay <ogabbay@kernel.org>
>>>> diff --git a/drivers/virt/gunyah/Kconfig b/drivers/virt/gunyah/Kconfig
>>>> index 127156a678a6..4de88d80aa7b 100644
>>>> --- a/drivers/virt/gunyah/Kconfig
>>>> +++ b/drivers/virt/gunyah/Kconfig
>>>> @@ -10,3 +10,18 @@ config GUNYAH
>>>>    	  Say Y/M here to enable the drivers needed to interact in a Gunyah
>>>>    	  virtual environment.
>>>> +
>>>> +config GUNYAH_RESORUCE_MANAGER
>>>> +	tristate "Gunyah Resource Manager"
>>>> +	select MAILBOX
>>>> +	select GUNYAH_MESSAGE_QUEUES
>>>> +	depends on GUNYAH
>>>> +	default y
>>>
>>> You only have "default y" if your machine can not boot without it.
>>> Please do not add that here.
>>>
>>
>> There's a guideline in Documentation/kbuild/kconfig-language.rst to provide
>> some sane defaults for subdriver behavior. Here, CONFIG_GUNYAH is default n.
>> It's unlikely for someone to want to have Linux with base Gunyah support
>> (hypercalls and hypervisor detection) without also having the Resource
>> Manager driver. If it's better, I could change to default m?
> 
> Why is this a separate build option at all anyway?  If you want
> CONFIG_GUNYAH why would you ever turn this off?  So why even allow it to
> be an option?  Just always built it depending on the main option.
> 

Ack.

I'll also end up removing CONFIG_GUNYAH_MESSAGE_QUEUES from patch 9 as well.

>>>> +/* Resource Manager Header */
>>>> +struct gh_rm_rpc_hdr {
>>>> +	u8 version : 4, hdr_words : 4;
>>>> +	u8 type : 2, fragments : 6;
>>>
>>> Ick, that's hard to read.  One variable per line please?
>>
>> Ack.
>>
>>> And why the bit packed stuff?  Are you sure this is the way to do this?
>>> Why not use a bitmask instead?
>>>
>>
>> I felt bit packed implementation is cleaner and easier to map to
>> understanding what the fields are used for.
> 
> Ah, so this isn't what is on the "wire", then don't use a bitfield like
> this, use a real variable and that will be faster and simpler to
> understand.
> 

This is what's on the "wire". Whether I use bitfield or bit packed would 
be functionally the same and is just a cosmetic change IMO.

>>>> +static struct gh_rsc_mgr *__rsc_mgr;
>>>
>>> Sorry, no, you don't get to just limit yourself to one of these.  Please
>>> make this properly handle any number of "resource managers", static
>>> variables like this is not ok.
>>>
>>
>> There will only ever be one resource manager. optee, psci, and qcom_scm use
>> a similar approach.
> 
> And all of those are also wrong.
> 
> There is no need for this variable at all, you are doing extra work to
> make this a "single" device.  Just always work off of the device that
> the driver core gave you and all is good and you will have no limits on
> how many different ones you eventually get.  It will be less code
> overall, so it's the right thing to do.
> 

Ack

>>>> +SRCU_NOTIFIER_HEAD_STATIC(gh_rm_notifier);
>>>
>>> Why do you need a notifier list?
>>>
>>> Who will register for this?  For what?  Why?
>>>
>>
>> The majority of notifications that RM sends to Linux will be related to VM
>> state, e.g. "VM crashed." I've not added the handling in VM manager yet to
>> reduce the number of patches in this series. It was used in the previous
>> series for the console driver. I can remove for now and re-introduce it once
>> VM manager makes use?
> 
> Please remove if you are not using it.  Notifier lists are almost always
> wrong when it comes to the driver model, so please don't add them now,
> we can discuss it later if you feel it really needs to be introduced
> then.
> 

Ack

>>>> +static struct platform_driver gh_rm_driver = {
>>>> +	.probe = gh_rm_drv_probe,
>>>> +	.remove = gh_rm_drv_remove,
>>>> +	.driver = {
>>>> +		.name = "gh_rsc_mgr",
>>>> +		.of_match_table = gh_rm_of_match,
>>>> +	},
>>>
>>> Wait, why is this a platform driver?  This is binding to a real device
>>> on a real bus, not a random platform description in DT, right?
>>
>> This a binding for a real device and not a "random platform description" in
>> DT to get the driver probed.
>>
>>> Or is it controlled by your DT?  I can't figure that out here, sorry.
>>
>> There is some info in Patch 2 about why the DT node exists and how it looks.
>> Essentially, The DT node is provided by Gunyah during boot and describes how
>> Linux can communicate with resource manager.
> 
> Ick, ok, for now let's leave this alone but for dynamic devices, you
> should never use a platform device.  All devices that hang off of this
> controller better not be platform devices, but belong to the bus type of
> your new bus, right?
> 

That's correct.

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-02  2:01               ` Jassi Brar
@ 2022-11-02 18:05                 ` Elliot Berman
  2022-11-02 18:24                   ` Jassi Brar
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-02 18:05 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

Hi Jassi,

On 11/1/2022 7:01 PM, Jassi Brar wrote:
> On Tue, Nov 1, 2022 at 7:12 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>
>>
>>
>> On 11/1/2022 2:58 PM, Jassi Brar wrote:
>>> On Tue, Nov 1, 2022 at 3:35 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 11/1/2022 9:23 AM, Jassi Brar wrote:
>>>>> On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>>>
>>>>>> Hi Jassi,
>>>>>>
>>>>>> On 10/27/2022 7:33 PM, Jassi Brar wrote:
>>>>>>     > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
>>>>>> <quic_eberman@quicinc.com> wrote:
>>>>>>     > .....
>>>>>>     >> +
>>>>>>     >> +        gunyah-resource-mgr@0 {
>>>>>>     >> +            compatible = "gunyah-resource-manager-1-0",
>>>>>> "gunyah-resource-manager";
>>>>>>     >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
>>>>>> full IRQ */
>>>>>>     >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
>>>>>> empty IRQ */
>>>>>>     >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
>>>>>>     >> +                  /* TX, RX cap ids */
>>>>>>     >> +        };
>>>>>>     >>
>>>>>>     > All these resources are used only by the mailbox controller driver.
>>>>>>     > So, this should be the mailbox controller node, rather than the
>>>>>>     > mailbox user.> One option is to load gunyah-resource-manager as a
>>>>>> module that relies
>>>>>>     > on the gunyah-mailbox provider. That would also avoid the "Allow
>>>>>>     > direct registration to a channel" hack patch.
>>>>>>
>>>>>> A message queue to another guest VM wouldn't be known at boot time and
>>>>>> thus couldn't be described on the devicetree.
>>>>>>
>>>>> I think you need to implement of_xlate() ... or please tell me what
>>>>> exactly you need to specify in the dt.
>>>>
>>>> Dynamically created virtual machines can't be known on the dt, so there
>>>> is nothing to specify in the DT. There couldn't be a devicetree node for
>>>> the message queue client because that client is only exists once the VM
>>>> is created by userspace.
>>>>
>>> The underlying "physical channel" is the synchronous SMC instruction,
>>> which remains 1 irrespective of the number of mailbox instances
>>> created.
>>
>> I disagree that the physical channel is the SMC instruction. Regardless
>> though, there are num_online_cpus() "physical channels" with this
>> perspective.
>>
>>> So basically you are sharing one resource among users. Why doesn't the
>>> RM request the "smc instruction" channel once and share it among
>>> users?
>>
>> I suppose in this scenario, a single mailbox channel would represent all
>> message queues? This would cause Linux to serialize *all* message queue
>> hypercalls. Sorry, I can only think negative implications.
>>
>> Error handling needs to move into clients: if a TX message queue becomes
>> full or an RX message queue becomes empty, then we'll need to return
>> error back to the client right away. The clients would need to register
>> for the RTS/RTR interrupts to know when to send/receive messages and
>> have retry error handling. If the mailbox controller retried for the
>> clients as currently proposed, then we could get into a scenario where a
>> message queue could never be ready to send/receive and thus stuck
>> forever trying to process that message. The effect here would be that
>> the mailbox controller becomes a wrapper to some SMC instructions that
>> aren't related at the SMC instruction level.
>>
>> A single channel would limit performance of SMP systems because only one
>> core could send/receive a message. There is no such limitation for
>> message queues to behave like this.
>>
> This is just an illusion. If Gunyah can handle multiple calls from a
> VM parallely, even with the "bind-client-to-channel" hack you can't
> make sure different channels run on different cpu cores.  If you are
> ok with that, you could simply populate a mailbox controller with N
> channels and allocate them in any order the clients ask.

I wanted to make sure I understood the ask here completely. On what 
basis is N chosen? Who would be the mailbox clients?

Thanks,
Elliot


_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-02 18:05                 ` Elliot Berman
@ 2022-11-02 18:24                   ` Jassi Brar
  2022-11-02 23:23                     ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Jassi Brar @ 2022-11-02 18:24 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On Wed, Nov 2, 2022 at 1:06 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>
> Hi Jassi,
>
> On 11/1/2022 7:01 PM, Jassi Brar wrote:
> > On Tue, Nov 1, 2022 at 7:12 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 11/1/2022 2:58 PM, Jassi Brar wrote:
> >>> On Tue, Nov 1, 2022 at 3:35 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 11/1/2022 9:23 AM, Jassi Brar wrote:
> >>>>> On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>>>>>
> >>>>>> Hi Jassi,
> >>>>>>
> >>>>>> On 10/27/2022 7:33 PM, Jassi Brar wrote:
> >>>>>>     > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
> >>>>>> <quic_eberman@quicinc.com> wrote:
> >>>>>>     > .....
> >>>>>>     >> +
> >>>>>>     >> +        gunyah-resource-mgr@0 {
> >>>>>>     >> +            compatible = "gunyah-resource-manager-1-0",
> >>>>>> "gunyah-resource-manager";
> >>>>>>     >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
> >>>>>> full IRQ */
> >>>>>>     >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
> >>>>>> empty IRQ */
> >>>>>>     >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
> >>>>>>     >> +                  /* TX, RX cap ids */
> >>>>>>     >> +        };
> >>>>>>     >>
> >>>>>>     > All these resources are used only by the mailbox controller driver.
> >>>>>>     > So, this should be the mailbox controller node, rather than the
> >>>>>>     > mailbox user.> One option is to load gunyah-resource-manager as a
> >>>>>> module that relies
> >>>>>>     > on the gunyah-mailbox provider. That would also avoid the "Allow
> >>>>>>     > direct registration to a channel" hack patch.
> >>>>>>
> >>>>>> A message queue to another guest VM wouldn't be known at boot time and
> >>>>>> thus couldn't be described on the devicetree.
> >>>>>>
> >>>>> I think you need to implement of_xlate() ... or please tell me what
> >>>>> exactly you need to specify in the dt.
> >>>>
> >>>> Dynamically created virtual machines can't be known on the dt, so there
> >>>> is nothing to specify in the DT. There couldn't be a devicetree node for
> >>>> the message queue client because that client is only exists once the VM
> >>>> is created by userspace.
> >>>>
> >>> The underlying "physical channel" is the synchronous SMC instruction,
> >>> which remains 1 irrespective of the number of mailbox instances
> >>> created.
> >>
> >> I disagree that the physical channel is the SMC instruction. Regardless
> >> though, there are num_online_cpus() "physical channels" with this
> >> perspective.
> >>
> >>> So basically you are sharing one resource among users. Why doesn't the
> >>> RM request the "smc instruction" channel once and share it among
> >>> users?
> >>
> >> I suppose in this scenario, a single mailbox channel would represent all
> >> message queues? This would cause Linux to serialize *all* message queue
> >> hypercalls. Sorry, I can only think negative implications.
> >>
> >> Error handling needs to move into clients: if a TX message queue becomes
> >> full or an RX message queue becomes empty, then we'll need to return
> >> error back to the client right away. The clients would need to register
> >> for the RTS/RTR interrupts to know when to send/receive messages and
> >> have retry error handling. If the mailbox controller retried for the
> >> clients as currently proposed, then we could get into a scenario where a
> >> message queue could never be ready to send/receive and thus stuck
> >> forever trying to process that message. The effect here would be that
> >> the mailbox controller becomes a wrapper to some SMC instructions that
> >> aren't related at the SMC instruction level.
> >>
> >> A single channel would limit performance of SMP systems because only one
> >> core could send/receive a message. There is no such limitation for
> >> message queues to behave like this.
> >>
> > This is just an illusion. If Gunyah can handle multiple calls from a
> > VM parallely, even with the "bind-client-to-channel" hack you can't
> > make sure different channels run on different cpu cores.  If you are
> > ok with that, you could simply populate a mailbox controller with N
> > channels and allocate them in any order the clients ask.
>
> I wanted to make sure I understood the ask here completely. On what
> basis is N chosen? Who would be the mailbox clients?
>
A channel structure is cheap, so any number that is not likely to run
out. Say you have 10 possible users in a VM, set N=16. I know ideally
it should be precise and flexible but the gain in simplicity makes the
trade-off very acceptable.

thanks.

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-02  7:31   ` Arnd Bergmann
@ 2022-11-02 18:44     ` Elliot Berman
  2022-11-03  0:20       ` Greg Kroah-Hartman
  2022-11-03  9:39       ` Arnd Bergmann
  0 siblings, 2 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-02 18:44 UTC (permalink / raw)
  To: Arnd Bergmann, Bjorn Andersson, Dmitry Baryshkov
  Cc: Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla,
	Marc Zyngier, Rob Herring, Krzysztof Kozlowski, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel



On 11/2/2022 12:31 AM, Arnd Bergmann wrote:
> On Wed, Oct 26, 2022, at 20:58, Elliot Berman wrote:
> 
>> +static const struct file_operations gh_vm_fops = {
>> +	.unlocked_ioctl = gh_vm_ioctl,
>> +	.release = gh_vm_release,
>> +	.llseek = noop_llseek,
>> +};
> 
> There should be a .compat_ioctl entry here, otherwise it is
> impossible to use from 32-bit tasks. If all commands have
> arguments passed through a pointer to a properly defined
> structure, you can just set it to compat_ptr_ioctl.
> 

Ack.

>> +static long gh_dev_ioctl_create_vm(unsigned long arg)
>> +{
>> +	struct gunyah_vm *ghvm;
>> +	struct file *file;
>> +	int fd, err;
>> +
>> +	/* arg reserved for future use. */
>> +	if (arg)
>> +		return -EINVAL;
> 
> Do you have something specific in mind here? If 'create'
> is the only command you support, and it has no arguments,
> it would be easier to do it implicitly during open() and
> have each fd opened from /dev/gunyah represent a new VM.
> 

I'd like the argument here to support different types of virtual 
machines. I want to leave open what "different types" can be in case 
something new comes up in the future, but immediately "different type" 
would correspond to a few different authentication mechanisms for 
virtual machines that Gunyah supports.

In this series, I'm only supporting unauthenticated virtual machines 
because they are the simplest to get up and running from a Linux 
userspace. When I introduce the other authentication mechanisms, I'll 
expand much more on how they work, but I'll give quick overview here. 
Other authentication mechanisms that are currently supported by Gunyah 
are "protected VM" and, on Qualcomm platforms, "PIL/carveout VMs". 
Protected VMs are *loosely* similar to the protected firmware design for 
KVM and intended to support Android virtualization use cases. 
PIL/carevout VMs are special virtual machines that can run on Qualcomm 
firmware which authenticate in a way similar to remoteproc firmware (MDT 
loader).

>> +	ghvm = gunyah_vm_alloc();
>> +	if (IS_ERR_OR_NULL(ghvm))
>> +		return PTR_ERR(ghvm) ? : -ENOMEM;
> 
> If you find yourself using IS_ERR_OR_NULL(), you have
> usually made a mistake. In this case, the gunyah_vm_alloc()
> function is badly defined and should just return -ENOMEM
> for an allocation failure.
> 

Ack

>> +static struct gunyah_rsc_mgr_device_id vm_mgr_ids[] = {
>> +	{ .name = GH_RM_DEVICE_VM_MGR },
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(gunyah_rsc_mgr, vm_mgr_ids);
>> +
>> +static struct gh_rm_driver vm_mgr_drv = {
>> +	.drv = {
>> +		.name = KBUILD_MODNAME,
>> +		.probe = vm_mgr_probe,
>> +		.remove = vm_mgr_remove,
>> +	},
>> +	.id_table = vm_mgr_ids,
>> +};
>> +module_gh_rm_driver(vm_mgr_drv);
> 
> It looks like the gunyah_rsc_mgr_device_id in this case is
> purely internal to the kernel, so you are adding abstraction
> layers to something that does not need to be abstracted
> because the host side has no corresponding concept of
> devices.
> 
> I'm correct, you can just turn the entire bus/device/driver
> structure within your code into simple function calls, where
> the main code calls vm_mgr_probe() as an exported function
> instead of creating a device.

Ack. I can do this, although I am nervous about this snowballing into a 
situation where I have a mega-module.

 > Please stop beating everything in a single module.

https://lore.kernel.org/all/250945d2-3940-9830-63e5-beec5f44010b@linaro.org/

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-02  5:14   ` Greg Kroah-Hartman
@ 2022-11-02 18:45     ` Elliot Berman
  2022-11-03  0:24       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-02 18:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, mec
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

+Michael

On 11/1/2022 10:14 PM, Greg Kroah-Hartman wrote:
> On Wed, Oct 26, 2022 at 11:58:38AM -0700, Elliot Berman wrote:
>> +#define GH_CREATE_VM			_IO(GH_IOCTL_TYPE, 0x40) /* Returns a Gunyah VM fd */
> 
> Why 0x40?  Why not just use the same KVM ioctl numbers and names as you
> are doing the same thing as them, right?

We've designed so that there are a few ioctls that will feel similar to 
KVM ioctls since we know this design has been successful, but we don't 
intend to support KVM ioctls 1:1. Gunyah has different semantics for 
many of the name-identical ioctls. It seems odd to mix some re-used KVM 
ioctls with novel Gunyah ioctls?

> 
> Normally your first ioctl is "0x01", not "0x40", so this feels really
> odd.
> 

Documentation/userspace-api/ioctl/iocl-number.rst advises to pick an 
unused block. We picked ioctl code 'G' and unused sequence numbers under 
that code. I'm ok to move the block around.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-02 18:24                   ` Jassi Brar
@ 2022-11-02 23:23                     ` Elliot Berman
  2022-11-03  3:21                       ` Jassi Brar
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-02 23:23 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Bjorn Andersson, Murali Nalajala, Greg Kroah-Hartman,
	Krzysztof Kozlowski, Rob Herring, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/2/2022 11:24 AM, Jassi Brar wrote:
> On Wed, Nov 2, 2022 at 1:06 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>
>> Hi Jassi,
>>
>> On 11/1/2022 7:01 PM, Jassi Brar wrote:
>>> On Tue, Nov 1, 2022 at 7:12 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 11/1/2022 2:58 PM, Jassi Brar wrote:
>>>>> On Tue, Nov 1, 2022 at 3:35 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 11/1/2022 9:23 AM, Jassi Brar wrote:
>>>>>>> On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>>>>>
>>>>>>>> Hi Jassi,
>>>>>>>>
>>>>>>>> On 10/27/2022 7:33 PM, Jassi Brar wrote:
>>>>>>>>      > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
>>>>>>>> <quic_eberman@quicinc.com> wrote:
>>>>>>>>      > .....
>>>>>>>>      >> +
>>>>>>>>      >> +        gunyah-resource-mgr@0 {
>>>>>>>>      >> +            compatible = "gunyah-resource-manager-1-0",
>>>>>>>> "gunyah-resource-manager";
>>>>>>>>      >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
>>>>>>>> full IRQ */
>>>>>>>>      >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
>>>>>>>> empty IRQ */
>>>>>>>>      >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
>>>>>>>>      >> +                  /* TX, RX cap ids */
>>>>>>>>      >> +        };
>>>>>>>>      >>
>>>>>>>>      > All these resources are used only by the mailbox controller driver.
>>>>>>>>      > So, this should be the mailbox controller node, rather than the
>>>>>>>>      > mailbox user.> One option is to load gunyah-resource-manager as a
>>>>>>>> module that relies
>>>>>>>>      > on the gunyah-mailbox provider. That would also avoid the "Allow
>>>>>>>>      > direct registration to a channel" hack patch.
>>>>>>>>
>>>>>>>> A message queue to another guest VM wouldn't be known at boot time and
>>>>>>>> thus couldn't be described on the devicetree.
>>>>>>>>
>>>>>>> I think you need to implement of_xlate() ... or please tell me what
>>>>>>> exactly you need to specify in the dt.
>>>>>>
>>>>>> Dynamically created virtual machines can't be known on the dt, so there
>>>>>> is nothing to specify in the DT. There couldn't be a devicetree node for
>>>>>> the message queue client because that client is only exists once the VM
>>>>>> is created by userspace.
>>>>>>
>>>>> The underlying "physical channel" is the synchronous SMC instruction,
>>>>> which remains 1 irrespective of the number of mailbox instances
>>>>> created.
>>>>
>>>> I disagree that the physical channel is the SMC instruction. Regardless
>>>> though, there are num_online_cpus() "physical channels" with this
>>>> perspective.
>>>>
>>>>> So basically you are sharing one resource among users. Why doesn't the
>>>>> RM request the "smc instruction" channel once and share it among
>>>>> users?
>>>>
>>>> I suppose in this scenario, a single mailbox channel would represent all
>>>> message queues? This would cause Linux to serialize *all* message queue
>>>> hypercalls. Sorry, I can only think negative implications.
>>>>
>>>> Error handling needs to move into clients: if a TX message queue becomes
>>>> full or an RX message queue becomes empty, then we'll need to return
>>>> error back to the client right away. The clients would need to register
>>>> for the RTS/RTR interrupts to know when to send/receive messages and
>>>> have retry error handling. If the mailbox controller retried for the
>>>> clients as currently proposed, then we could get into a scenario where a
>>>> message queue could never be ready to send/receive and thus stuck
>>>> forever trying to process that message. The effect here would be that
>>>> the mailbox controller becomes a wrapper to some SMC instructions that
>>>> aren't related at the SMC instruction level.
>>>>
>>>> A single channel would limit performance of SMP systems because only one
>>>> core could send/receive a message. There is no such limitation for
>>>> message queues to behave like this.
>>>>
>>> This is just an illusion. If Gunyah can handle multiple calls from a
>>> VM parallely, even with the "bind-client-to-channel" hack you can't
>>> make sure different channels run on different cpu cores.  If you are
>>> ok with that, you could simply populate a mailbox controller with N
>>> channels and allocate them in any order the clients ask.
>>
>> I wanted to make sure I understood the ask here completely. On what
>> basis is N chosen? Who would be the mailbox clients?
>>
> A channel structure is cheap, so any number that is not likely to run
> out. Say you have 10 possible users in a VM, set N=16. I know ideally
> it should be precise and flexible but the gain in simplicity makes the
> trade-off very acceptable.

I think I get the direction you are thinking now. N is chosen based off 
of how many clients there might be. One mailbox controller will 
represent all message queues and each channel will be one message queue. 
There are some limitations that might make it more complex to implement 
than having 1 message queue per controller like I have now.

My interpretation is that mailbox controller knows the configuration of 
its channels before being bound to a client. For dynamically created 
message queues, the client would need tell the controller about the 
message queue configuration. I didn't find example where client is 
providing information about a channel to the controller.

  1. need a mechanism to allow the client to provide the 
gunyah_resources for the channel (i.e. the irqs and cap ids).
  2. Still need to have bind-client-to-channel patch since clients 
aren't real devices and so shouldn't be on DT.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-02 18:44     ` Elliot Berman
@ 2022-11-03  0:20       ` Greg Kroah-Hartman
  2022-11-03 22:33         ` Elliot Berman
  2022-11-03  9:39       ` Arnd Bergmann
  1 sibling, 1 reply; 67+ messages in thread
From: Greg Kroah-Hartman @ 2022-11-03  0:20 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Arnd Bergmann, Bjorn Andersson, Dmitry Baryshkov,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla,
	Marc Zyngier, Rob Herring, Krzysztof Kozlowski, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

On Wed, Nov 02, 2022 at 11:44:51AM -0700, Elliot Berman wrote:
> 
> 
> On 11/2/2022 12:31 AM, Arnd Bergmann wrote:
> > On Wed, Oct 26, 2022, at 20:58, Elliot Berman wrote:
> > 
> > > +static const struct file_operations gh_vm_fops = {
> > > +	.unlocked_ioctl = gh_vm_ioctl,
> > > +	.release = gh_vm_release,
> > > +	.llseek = noop_llseek,
> > > +};
> > 
> > There should be a .compat_ioctl entry here, otherwise it is
> > impossible to use from 32-bit tasks. If all commands have
> > arguments passed through a pointer to a properly defined
> > structure, you can just set it to compat_ptr_ioctl.
> > 
> 
> Ack.
> 
> > > +static long gh_dev_ioctl_create_vm(unsigned long arg)
> > > +{
> > > +	struct gunyah_vm *ghvm;
> > > +	struct file *file;
> > > +	int fd, err;
> > > +
> > > +	/* arg reserved for future use. */
> > > +	if (arg)
> > > +		return -EINVAL;
> > 
> > Do you have something specific in mind here? If 'create'
> > is the only command you support, and it has no arguments,
> > it would be easier to do it implicitly during open() and
> > have each fd opened from /dev/gunyah represent a new VM.
> > 
> 
> I'd like the argument here to support different types of virtual machines. I
> want to leave open what "different types" can be in case something new comes
> up in the future, but immediately "different type" would correspond to a few
> different authentication mechanisms for virtual machines that Gunyah
> supports.

Please don't add code that does not actually do something now, as that
makes it impossible to review properly, _AND_ no one knows what is going
to happen in the future.  In the future, you can just add a new ioctl
and all is good, no need to break working userspace by suddenly looking
at the arg value and doing something with it.

thanks,

greg k-h

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core
  2022-11-02 18:04         ` Elliot Berman
@ 2022-11-03  0:22           ` Greg Kroah-Hartman
  2022-11-03 22:07             ` Elliot Berman
  2022-11-03 22:09             ` Elliot Berman
  0 siblings, 2 replies; 67+ messages in thread
From: Greg Kroah-Hartman @ 2022-11-03  0:22 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Jassi Brar, Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

On Wed, Nov 02, 2022 at 11:04:45AM -0700, Elliot Berman wrote:
> > > > > +/* Resource Manager Header */
> > > > > +struct gh_rm_rpc_hdr {
> > > > > +	u8 version : 4, hdr_words : 4;
> > > > > +	u8 type : 2, fragments : 6;
> > > > 
> > > > Ick, that's hard to read.  One variable per line please?
> > > 
> > > Ack.
> > > 
> > > > And why the bit packed stuff?  Are you sure this is the way to do this?
> > > > Why not use a bitmask instead?
> > > > 
> > > 
> > > I felt bit packed implementation is cleaner and easier to map to
> > > understanding what the fields are used for.
> > 
> > Ah, so this isn't what is on the "wire", then don't use a bitfield like
> > this, use a real variable and that will be faster and simpler to
> > understand.
> > 
> 
> This is what's on the "wire". Whether I use bitfield or bit packed would be
> functionally the same and is just a cosmetic change IMO.

Ah, that wasn't obvious at all.

Usually using bitfields like this for "wire" protocols is not a good
idea (endian issues and all of that.)  Please use a bitmask instead, as
that way you know exactly what is happening, and the compiler can
usually generate much better code overall.

And as this is on the wire, please specify the endian values, _AND_ use
the proper kernel types for stuff that goes between user/kernel or
kernel/hardware, as you are not doing that here.

thanks,

greg k-h

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-02 18:45     ` Elliot Berman
@ 2022-11-03  0:24       ` Greg Kroah-Hartman
  2022-11-04  0:11         ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Greg Kroah-Hartman @ 2022-11-03  0:24 UTC (permalink / raw)
  To: Elliot Berman
  Cc: mec, Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

On Wed, Nov 02, 2022 at 11:45:12AM -0700, Elliot Berman wrote:
> +Michael
> 
> On 11/1/2022 10:14 PM, Greg Kroah-Hartman wrote:
> > On Wed, Oct 26, 2022 at 11:58:38AM -0700, Elliot Berman wrote:
> > > +#define GH_CREATE_VM			_IO(GH_IOCTL_TYPE, 0x40) /* Returns a Gunyah VM fd */
> > 
> > Why 0x40?  Why not just use the same KVM ioctl numbers and names as you
> > are doing the same thing as them, right?
> 
> We've designed so that there are a few ioctls that will feel similar to KVM
> ioctls since we know this design has been successful, but we don't intend to
> support KVM ioctls 1:1. Gunyah has different semantics for many of the
> name-identical ioctls. It seems odd to mix some re-used KVM ioctls with
> novel Gunyah ioctls?

Even if you don't support it 1:1, at least for the ones that are the
same thing, pick the same numbers as that's a nicer thing to do, right?

> > Normally your first ioctl is "0x01", not "0x40", so this feels really
> > odd.
> > 
> 
> Documentation/userspace-api/ioctl/iocl-number.rst advises to pick an unused
> block. We picked ioctl code 'G' and unused sequence numbers under that code.
> I'm ok to move the block around.

How do you know you picked an unused block?  It wasn't obvious where you
got these values from at all, and unfortunatly, no one really ever
updates that documentation file.  Luckily it never really matters.

thanks,

greg k-h

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-02 23:23                     ` Elliot Berman
@ 2022-11-03  3:21                       ` Jassi Brar
  2022-11-03 19:45                         ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Jassi Brar @ 2022-11-03  3:21 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Bjorn Andersson, Murali Nalajala, Greg Kroah-Hartman,
	Krzysztof Kozlowski, Rob Herring, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel

On Wed, Nov 2, 2022 at 6:23 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>
>
>
> On 11/2/2022 11:24 AM, Jassi Brar wrote:
> > On Wed, Nov 2, 2022 at 1:06 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>
> >> Hi Jassi,
> >>
> >> On 11/1/2022 7:01 PM, Jassi Brar wrote:
> >>> On Tue, Nov 1, 2022 at 7:12 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 11/1/2022 2:58 PM, Jassi Brar wrote:
> >>>>> On Tue, Nov 1, 2022 at 3:35 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> On 11/1/2022 9:23 AM, Jassi Brar wrote:
> >>>>>>> On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
> >>>>>>>>
> >>>>>>>> Hi Jassi,
> >>>>>>>>
> >>>>>>>> On 10/27/2022 7:33 PM, Jassi Brar wrote:
> >>>>>>>>      > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
> >>>>>>>> <quic_eberman@quicinc.com> wrote:
> >>>>>>>>      > .....
> >>>>>>>>      >> +
> >>>>>>>>      >> +        gunyah-resource-mgr@0 {
> >>>>>>>>      >> +            compatible = "gunyah-resource-manager-1-0",
> >>>>>>>> "gunyah-resource-manager";
> >>>>>>>>      >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
> >>>>>>>> full IRQ */
> >>>>>>>>      >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
> >>>>>>>> empty IRQ */
> >>>>>>>>      >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
> >>>>>>>>      >> +                  /* TX, RX cap ids */
> >>>>>>>>      >> +        };
> >>>>>>>>      >>
> >>>>>>>>      > All these resources are used only by the mailbox controller driver.
> >>>>>>>>      > So, this should be the mailbox controller node, rather than the
> >>>>>>>>      > mailbox user.> One option is to load gunyah-resource-manager as a
> >>>>>>>> module that relies
> >>>>>>>>      > on the gunyah-mailbox provider. That would also avoid the "Allow
> >>>>>>>>      > direct registration to a channel" hack patch.
> >>>>>>>>
> >>>>>>>> A message queue to another guest VM wouldn't be known at boot time and
> >>>>>>>> thus couldn't be described on the devicetree.
> >>>>>>>>
> >>>>>>> I think you need to implement of_xlate() ... or please tell me what
> >>>>>>> exactly you need to specify in the dt.
> >>>>>>
> >>>>>> Dynamically created virtual machines can't be known on the dt, so there
> >>>>>> is nothing to specify in the DT. There couldn't be a devicetree node for
> >>>>>> the message queue client because that client is only exists once the VM
> >>>>>> is created by userspace.
> >>>>>>
> >>>>> The underlying "physical channel" is the synchronous SMC instruction,
> >>>>> which remains 1 irrespective of the number of mailbox instances
> >>>>> created.
> >>>>
> >>>> I disagree that the physical channel is the SMC instruction. Regardless
> >>>> though, there are num_online_cpus() "physical channels" with this
> >>>> perspective.
> >>>>
> >>>>> So basically you are sharing one resource among users. Why doesn't the
> >>>>> RM request the "smc instruction" channel once and share it among
> >>>>> users?
> >>>>
> >>>> I suppose in this scenario, a single mailbox channel would represent all
> >>>> message queues? This would cause Linux to serialize *all* message queue
> >>>> hypercalls. Sorry, I can only think negative implications.
> >>>>
> >>>> Error handling needs to move into clients: if a TX message queue becomes
> >>>> full or an RX message queue becomes empty, then we'll need to return
> >>>> error back to the client right away. The clients would need to register
> >>>> for the RTS/RTR interrupts to know when to send/receive messages and
> >>>> have retry error handling. If the mailbox controller retried for the
> >>>> clients as currently proposed, then we could get into a scenario where a
> >>>> message queue could never be ready to send/receive and thus stuck
> >>>> forever trying to process that message. The effect here would be that
> >>>> the mailbox controller becomes a wrapper to some SMC instructions that
> >>>> aren't related at the SMC instruction level.
> >>>>
> >>>> A single channel would limit performance of SMP systems because only one
> >>>> core could send/receive a message. There is no such limitation for
> >>>> message queues to behave like this.
> >>>>
> >>> This is just an illusion. If Gunyah can handle multiple calls from a
> >>> VM parallely, even with the "bind-client-to-channel" hack you can't
> >>> make sure different channels run on different cpu cores.  If you are
> >>> ok with that, you could simply populate a mailbox controller with N
> >>> channels and allocate them in any order the clients ask.
> >>
> >> I wanted to make sure I understood the ask here completely. On what
> >> basis is N chosen? Who would be the mailbox clients?
> >>
> > A channel structure is cheap, so any number that is not likely to run
> > out. Say you have 10 possible users in a VM, set N=16. I know ideally
> > it should be precise and flexible but the gain in simplicity makes the
> > trade-off very acceptable.
>
> I think I get the direction you are thinking now. N is chosen based off
> of how many clients there might be. One mailbox controller will
> represent all message queues and each channel will be one message queue.
> There are some limitations that might make it more complex to implement
> than having 1 message queue per controller like I have now.
>
> My interpretation is that mailbox controller knows the configuration of
> its channels before being bound to a client. For dynamically created
> message queues, the client would need tell the controller about the
> message queue configuration. I didn't find example where client is
> providing information about a channel to the controller.
>
>   1. need a mechanism to allow the client to provide the
> gunyah_resources for the channel (i.e. the irqs and cap ids).
>
IIUC there is exactly one resource-manager in a VM. Right?
Looking at your code, TX and RX irq are used only by the mailbox
driver and are the same for all clients/users. So that should be a
property under the mailbox controller node. Not sure what cap ids are.

>   2. Still need to have bind-client-to-channel patch since clients
> aren't real devices and so shouldn't be on DT.
>
the clients may be virtual (serial, gpio etc) but the resource-manager
requires some mailbox hardware to communicate, so the resource-manager
should be the mailbox client (that further spawns virtual devices)

thnx.

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-02 18:44     ` Elliot Berman
  2022-11-03  0:20       ` Greg Kroah-Hartman
@ 2022-11-03  9:39       ` Arnd Bergmann
  2022-11-03 22:10         ` Elliot Berman
  1 sibling, 1 reply; 67+ messages in thread
From: Arnd Bergmann @ 2022-11-03  9:39 UTC (permalink / raw)
  To: Elliot Berman, Bjorn Andersson, Dmitry Baryshkov
  Cc: Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla,
	Marc Zyngier, Rob Herring, Krzysztof Kozlowski, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel

On Wed, Nov 2, 2022, at 19:44, Elliot Berman wrote:
> On 11/2/2022 12:31 AM, Arnd Bergmann wrote:
>>> +static long gh_dev_ioctl_create_vm(unsigned long arg)
>>> +{
>>> +	struct gunyah_vm *ghvm;
>>> +	struct file *file;
>>> +	int fd, err;
>>> +
>>> +	/* arg reserved for future use. */
>>> +	if (arg)
>>> +		return -EINVAL;
>> 
>> Do you have something specific in mind here? If 'create'
>> is the only command you support, and it has no arguments,
>> it would be easier to do it implicitly during open() and
>> have each fd opened from /dev/gunyah represent a new VM.
>> 
>
> I'd like the argument here to support different types of virtual 
> machines. I want to leave open what "different types" can be in case 
> something new comes up in the future, but immediately "different type" 
> would correspond to a few different authentication mechanisms for 
> virtual machines that Gunyah supports.
>
> In this series, I'm only supporting unauthenticated virtual machines 
> because they are the simplest to get up and running from a Linux 
> userspace. When I introduce the other authentication mechanisms, I'll 
> expand much more on how they work, but I'll give quick overview here. 
> Other authentication mechanisms that are currently supported by Gunyah 
> are "protected VM" and, on Qualcomm platforms, "PIL/carveout VMs". 
> Protected VMs are *loosely* similar to the protected firmware design for 
> KVM and intended to support Android virtualization use cases. 
> PIL/carevout VMs are special virtual machines that can run on Qualcomm 
> firmware which authenticate in a way similar to remoteproc firmware (MDT 
> loader).

Ok, thanks for the background. Having different types of virtual
machines does mean that you may need some complexity, but I would
still lean towards using the simpler context management of opening
the /dev/gunyah device node to get a new context, and then using
ioctls on each fd to manage that context, instead of going through
the extra indirection of having a secondary 'open context' command
that always requires opening two file descriptors.

>> I'm correct, you can just turn the entire bus/device/driver
>> structure within your code into simple function calls, where
>> the main code calls vm_mgr_probe() as an exported function
>> instead of creating a device.
>
> Ack. I can do this, although I am nervous about this snowballing into a 
> situation where I have a mega-module.
>
>  > Please stop beating everything in a single module.
>
> https://lore.kernel.org/all/250945d2-3940-9830-63e5-beec5f44010b@linaro.org/

I see you concern, but I wasn't suggesting having everything
in one module either. There are three common ways of splitting
things into separate modules:

- I suggested having the vm_mgr module as a library block that
  exports a few symbols which get used by the core module. The
  module doesn't do anything on its own, but loading the core
  module forces loading the vm_mgr.

- Alternatively one can do the opposite, and have symbols
  exported by the core module, with the vm_mgr module using
  it. This would make sense if you commonly have the core
  module loaded on virtual machines that do not need to manage
  other VMs.

- The method you have is to have a lower "bus" level that
  abstracts device providers from consumers, with both sides
  hooking into the bus. This makes sense for physical buses
  like PCI or USB where both the host driver and the function
  driver are unaware of implementation details of the other,
  but in your case it does not seem like a good fit.

        Arnd

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor
  2022-11-03  3:21                       ` Jassi Brar
@ 2022-11-03 19:45                         ` Elliot Berman
  0 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-03 19:45 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Bjorn Andersson, Murali Nalajala, Greg Kroah-Hartman,
	Krzysztof Kozlowski, Rob Herring, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/2/2022 8:21 PM, Jassi Brar wrote:
> On Wed, Nov 2, 2022 at 6:23 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>
>>
>>
>> On 11/2/2022 11:24 AM, Jassi Brar wrote:
>>> On Wed, Nov 2, 2022 at 1:06 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>
>>>> Hi Jassi,
>>>>
>>>> On 11/1/2022 7:01 PM, Jassi Brar wrote:
>>>>> On Tue, Nov 1, 2022 at 7:12 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 11/1/2022 2:58 PM, Jassi Brar wrote:
>>>>>>> On Tue, Nov 1, 2022 at 3:35 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 11/1/2022 9:23 AM, Jassi Brar wrote:
>>>>>>>>> On Mon, Oct 31, 2022 at 10:20 PM Elliot Berman <quic_eberman@quicinc.com> wrote:
>>>>>>>>>>
>>>>>>>>>> Hi Jassi,
>>>>>>>>>>
>>>>>>>>>> On 10/27/2022 7:33 PM, Jassi Brar wrote:
>>>>>>>>>>       > On Wed, Oct 26, 2022 at 1:59 PM Elliot Berman
>>>>>>>>>> <quic_eberman@quicinc.com> wrote:
>>>>>>>>>>       > .....
>>>>>>>>>>       >> +
>>>>>>>>>>       >> +        gunyah-resource-mgr@0 {
>>>>>>>>>>       >> +            compatible = "gunyah-resource-manager-1-0",
>>>>>>>>>> "gunyah-resource-manager";
>>>>>>>>>>       >> +            interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>, /* TX
>>>>>>>>>> full IRQ */
>>>>>>>>>>       >> +                         <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>; /* RX
>>>>>>>>>> empty IRQ */
>>>>>>>>>>       >> +            reg = <0x00000000 0x00000000>, <0x00000000 0x00000001>;
>>>>>>>>>>       >> +                  /* TX, RX cap ids */
>>>>>>>>>>       >> +        };
>>>>>>>>>>       >>
>>>>>>>>>>       > All these resources are used only by the mailbox controller driver.
>>>>>>>>>>       > So, this should be the mailbox controller node, rather than the
>>>>>>>>>>       > mailbox user.> One option is to load gunyah-resource-manager as a
>>>>>>>>>> module that relies
>>>>>>>>>>       > on the gunyah-mailbox provider. That would also avoid the "Allow
>>>>>>>>>>       > direct registration to a channel" hack patch.
>>>>>>>>>>
>>>>>>>>>> A message queue to another guest VM wouldn't be known at boot time and
>>>>>>>>>> thus couldn't be described on the devicetree.
>>>>>>>>>>
>>>>>>>>> I think you need to implement of_xlate() ... or please tell me what
>>>>>>>>> exactly you need to specify in the dt.
>>>>>>>>
>>>>>>>> Dynamically created virtual machines can't be known on the dt, so there
>>>>>>>> is nothing to specify in the DT. There couldn't be a devicetree node for
>>>>>>>> the message queue client because that client is only exists once the VM
>>>>>>>> is created by userspace.
>>>>>>>>
>>>>>>> The underlying "physical channel" is the synchronous SMC instruction,
>>>>>>> which remains 1 irrespective of the number of mailbox instances
>>>>>>> created.
>>>>>>
>>>>>> I disagree that the physical channel is the SMC instruction. Regardless
>>>>>> though, there are num_online_cpus() "physical channels" with this
>>>>>> perspective.
>>>>>>
>>>>>>> So basically you are sharing one resource among users. Why doesn't the
>>>>>>> RM request the "smc instruction" channel once and share it among
>>>>>>> users?
>>>>>>
>>>>>> I suppose in this scenario, a single mailbox channel would represent all
>>>>>> message queues? This would cause Linux to serialize *all* message queue
>>>>>> hypercalls. Sorry, I can only think negative implications.
>>>>>>
>>>>>> Error handling needs to move into clients: if a TX message queue becomes
>>>>>> full or an RX message queue becomes empty, then we'll need to return
>>>>>> error back to the client right away. The clients would need to register
>>>>>> for the RTS/RTR interrupts to know when to send/receive messages and
>>>>>> have retry error handling. If the mailbox controller retried for the
>>>>>> clients as currently proposed, then we could get into a scenario where a
>>>>>> message queue could never be ready to send/receive and thus stuck
>>>>>> forever trying to process that message. The effect here would be that
>>>>>> the mailbox controller becomes a wrapper to some SMC instructions that
>>>>>> aren't related at the SMC instruction level.
>>>>>>
>>>>>> A single channel would limit performance of SMP systems because only one
>>>>>> core could send/receive a message. There is no such limitation for
>>>>>> message queues to behave like this.
>>>>>>
>>>>> This is just an illusion. If Gunyah can handle multiple calls from a
>>>>> VM parallely, even with the "bind-client-to-channel" hack you can't
>>>>> make sure different channels run on different cpu cores.  If you are
>>>>> ok with that, you could simply populate a mailbox controller with N
>>>>> channels and allocate them in any order the clients ask.
>>>>
>>>> I wanted to make sure I understood the ask here completely. On what
>>>> basis is N chosen? Who would be the mailbox clients?
>>>>
>>> A channel structure is cheap, so any number that is not likely to run
>>> out. Say you have 10 possible users in a VM, set N=16. I know ideally
>>> it should be precise and flexible but the gain in simplicity makes the
>>> trade-off very acceptable.
>>
>> I think I get the direction you are thinking now. N is chosen based off
>> of how many clients there might be. One mailbox controller will
>> represent all message queues and each channel will be one message queue.
>> There are some limitations that might make it more complex to implement
>> than having 1 message queue per controller like I have now.
>>
>> My interpretation is that mailbox controller knows the configuration of
>> its channels before being bound to a client. For dynamically created
>> message queues, the client would need tell the controller about the
>> message queue configuration. I didn't find example where client is
>> providing information about a channel to the controller.
>>
>>    1. need a mechanism to allow the client to provide the
>> gunyah_resources for the channel (i.e. the irqs and cap ids).
>>
> IIUC there is exactly one resource-manager in a VM. Right?
> Looking at your code, TX and RX irq are used only by the mailbox
> driver and are the same for all clients/users. So that should be a
> property under the mailbox controller node. Not sure what cap ids are.
> 

Ah -- "message queues" are a generic inter-VM communication mechanism 
offered by Gunyah. One use case for message queues is to communicate 
with the resource-manager, but other message queues can exist between 
other virtual machines. Those other message queues use different TX and 
RX irq and have different client protocols.

In mailbox terminology, we have one known channel at boot-up time (the 
resource manager). That known channel can inform Linux about other 
channels at runtime. The client (not the controller) decodes received 
data from the channel to discover the new channels.

One approach we found was coming from pcc.c, which has their own 
request_channel function (pcc_mbox_request_channel). We could follow 
this approach as well...

>>    2. Still need to have bind-client-to-channel patch since clients
>> aren't real devices and so shouldn't be on DT.
>>
> the clients may be virtual (serial, gpio etc) but the resource-manager
> requires some mailbox hardware to communicate, so the resource-manager
> should be the mailbox client (that further spawns virtual devices)

Yes, this the design I'm aiming for. Also want to highlight that the 
resource-manager spawns Gunyah virtual devices such as message queue 
channels.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core
  2022-11-03  0:22           ` Greg Kroah-Hartman
@ 2022-11-03 22:07             ` Elliot Berman
  2022-11-03 22:09             ` Elliot Berman
  1 sibling, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-03 22:07 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Jassi Brar, Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/2/2022 5:22 PM, Greg Kroah-Hartman wrote:
> On Wed, Nov 02, 2022 at 11:04:45AM -0700, Elliot Berman wrote:
>>>>>> +/* Resource Manager Header */
>>>>>> +struct gh_rm_rpc_hdr {
>>>>>> +	u8 version : 4, hdr_words : 4;
>>>>>> +	u8 type : 2, fragments : 6;
>>>>>
>>>>> Ick, that's hard to read.  One variable per line please?
>>>>
>>>> Ack.
>>>>
>>>>> And why the bit packed stuff?  Are you sure this is the way to do this?
>>>>> Why not use a bitmask instead?
>>>>>
>>>>
>>>> I felt bit packed implementation is cleaner and easier to map to
>>>> understanding what the fields are used for.
>>>
>>> Ah, so this isn't what is on the "wire", then don't use a bitfield like
>>> this, use a real variable and that will be faster and simpler to
>>> understand.
>>>
>>
>> This is what's on the "wire". Whether I use bitfield or bit packed would be
>> functionally the same and is just a cosmetic change IMO.
> 
> Ah, that wasn't obvious at all.
> 
> Usually using bitfields like this for "wire" protocols is not a good
> idea (endian issues and all of that.)  Please use a bitmask instead, as
> that way you know exactly what is happening, and the compiler can
> usually generate much better code overall.
> 
> And as this is on the wire, please specify the endian values, _AND_ use
> the proper kernel types for stuff that goes between user/kernel or
> kernel/hardware, as you are not doing that here.

Ack

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core
  2022-11-03  0:22           ` Greg Kroah-Hartman
  2022-11-03 22:07             ` Elliot Berman
@ 2022-11-03 22:09             ` Elliot Berman
  1 sibling, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-03 22:09 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Jassi Brar, Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/2/2022 5:22 PM, Greg Kroah-Hartman wrote:
> On Wed, Nov 02, 2022 at 11:04:45AM -0700, Elliot Berman wrote:
>>>>>> +/* Resource Manager Header */
>>>>>> +struct gh_rm_rpc_hdr {
>>>>>> +	u8 version : 4, hdr_words : 4;
>>>>>> +	u8 type : 2, fragments : 6;
>>>>>
>>>>> Ick, that's hard to read.  One variable per line please?
>>>>
>>>> Ack.
>>>>
>>>>> And why the bit packed stuff?  Are you sure this is the way to do this?
>>>>> Why not use a bitmask instead?
>>>>>
>>>>
>>>> I felt bit packed implementation is cleaner and easier to map to
>>>> understanding what the fields are used for.
>>>
>>> Ah, so this isn't what is on the "wire", then don't use a bitfield like
>>> this, use a real variable and that will be faster and simpler to
>>> understand.
>>>
>>
>> This is what's on the "wire". Whether I use bitfield or bit packed would be
>> functionally the same and is just a cosmetic change IMO.
> 
> Ah, that wasn't obvious at all.
> 
> Usually using bitfields like this for "wire" protocols is not a good
> idea (endian issues and all of that.)  Please use a bitmask instead, as
> that way you know exactly what is happening, and the compiler can
> usually generate much better code overall.
> 
> And as this is on the wire, please specify the endian values, _AND_ use
> the proper kernel types for stuff that goes between user/kernel or
> kernel/hardware, as you are not doing that here.

Ack

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-03  9:39       ` Arnd Bergmann
@ 2022-11-03 22:10         ` Elliot Berman
  0 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-03 22:10 UTC (permalink / raw)
  To: Arnd Bergmann, Bjorn Andersson, Dmitry Baryshkov
  Cc: Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla,
	Marc Zyngier, Rob Herring, Krzysztof Kozlowski, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Greg Kroah-Hartman,
	Srinivas Kandagatla, Amol Maheshwari, Kalle Valo, devicetree,
	linux-doc, linux-arm-msm, linux-kernel



On 11/3/2022 2:39 AM, Arnd Bergmann wrote:
> On Wed, Nov 2, 2022, at 19:44, Elliot Berman wrote:
>> On 11/2/2022 12:31 AM, Arnd Bergmann wrote:
>>>> +static long gh_dev_ioctl_create_vm(unsigned long arg)
>>>> +{
>>>> +	struct gunyah_vm *ghvm;
>>>> +	struct file *file;
>>>> +	int fd, err;
>>>> +
>>>> +	/* arg reserved for future use. */
>>>> +	if (arg)
>>>> +		return -EINVAL;
>>>
>>> Do you have something specific in mind here? If 'create'
>>> is the only command you support, and it has no arguments,
>>> it would be easier to do it implicitly during open() and
>>> have each fd opened from /dev/gunyah represent a new VM.
>>>
>>
>> I'd like the argument here to support different types of virtual
>> machines. I want to leave open what "different types" can be in case
>> something new comes up in the future, but immediately "different type"
>> would correspond to a few different authentication mechanisms for
>> virtual machines that Gunyah supports.
>>
>> In this series, I'm only supporting unauthenticated virtual machines
>> because they are the simplest to get up and running from a Linux
>> userspace. When I introduce the other authentication mechanisms, I'll
>> expand much more on how they work, but I'll give quick overview here.
>> Other authentication mechanisms that are currently supported by Gunyah
>> are "protected VM" and, on Qualcomm platforms, "PIL/carveout VMs".
>> Protected VMs are *loosely* similar to the protected firmware design for
>> KVM and intended to support Android virtualization use cases.
>> PIL/carevout VMs are special virtual machines that can run on Qualcomm
>> firmware which authenticate in a way similar to remoteproc firmware (MDT
>> loader).
> 
> Ok, thanks for the background. Having different types of virtual
> machines does mean that you may need some complexity, but I would
> still lean towards using the simpler context management of opening
> the /dev/gunyah device node to get a new context, and then using
> ioctls on each fd to manage that context, instead of going through
> the extra indirection of having a secondary 'open context' command
> that always requires opening two file descriptors.
> 
>>> I'm correct, you can just turn the entire bus/device/driver
>>> structure within your code into simple function calls, where
>>> the main code calls vm_mgr_probe() as an exported function
>>> instead of creating a device.
>>
>> Ack. I can do this, although I am nervous about this snowballing into a
>> situation where I have a mega-module.
>>
>>   > Please stop beating everything in a single module.
>>
>> https://lore.kernel.org/all/250945d2-3940-9830-63e5-beec5f44010b@linaro.org/
> 
> I see you concern, but I wasn't suggesting having everything
> in one module either. There are three common ways of splitting
> things into separate modules:
> 
> - I suggested having the vm_mgr module as a library block that
>    exports a few symbols which get used by the core module. The
>    module doesn't do anything on its own, but loading the core
>    module forces loading the vm_mgr.
> 

Got the idea, I'll do this.

- Elliot

> - Alternatively one can do the opposite, and have symbols
>    exported by the core module, with the vm_mgr module using
>    it. This would make sense if you commonly have the core
>    module loaded on virtual machines that do not need to manage
>    other VMs.
> 
> - The method you have is to have a lower "bus" level that
>    abstracts device providers from consumers, with both sides
>    hooking into the bus. This makes sense for physical buses
>    like PCI or USB where both the host driver and the function
>    driver are unaware of implementation details of the other,
>    but in your case it does not seem like a good fit.
> 
>          Arnd

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-03  0:20       ` Greg Kroah-Hartman
@ 2022-11-03 22:33         ` Elliot Berman
  0 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-03 22:33 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Arnd Bergmann, Bjorn Andersson, Dmitry Baryshkov,
	Murali Nalajala, Trilok Soni, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross, Jassi Brar,
	linux-arm-kernel, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla,
	Marc Zyngier, Rob Herring, Krzysztof Kozlowski, Jonathan Corbet,
	Will Deacon, Catalin Marinas, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/2/2022 5:20 PM, Greg Kroah-Hartman wrote:
> On Wed, Nov 02, 2022 at 11:44:51AM -0700, Elliot Berman wrote:
>>
>>
>> On 11/2/2022 12:31 AM, Arnd Bergmann wrote:
>>> On Wed, Oct 26, 2022, at 20:58, Elliot Berman wrote:
>>>
>>>> +static const struct file_operations gh_vm_fops = {
>>>> +	.unlocked_ioctl = gh_vm_ioctl,
>>>> +	.release = gh_vm_release,
>>>> +	.llseek = noop_llseek,
>>>> +};
>>>
>>> There should be a .compat_ioctl entry here, otherwise it is
>>> impossible to use from 32-bit tasks. If all commands have
>>> arguments passed through a pointer to a properly defined
>>> structure, you can just set it to compat_ptr_ioctl.
>>>
>>
>> Ack.
>>
>>>> +static long gh_dev_ioctl_create_vm(unsigned long arg)
>>>> +{
>>>> +	struct gunyah_vm *ghvm;
>>>> +	struct file *file;
>>>> +	int fd, err;
>>>> +
>>>> +	/* arg reserved for future use. */
>>>> +	if (arg)
>>>> +		return -EINVAL;
>>>
>>> Do you have something specific in mind here? If 'create'
>>> is the only command you support, and it has no arguments,
>>> it would be easier to do it implicitly during open() and
>>> have each fd opened from /dev/gunyah represent a new VM.
>>>
>>
>> I'd like the argument here to support different types of virtual machines. I
>> want to leave open what "different types" can be in case something new comes
>> up in the future, but immediately "different type" would correspond to a few
>> different authentication mechanisms for virtual machines that Gunyah
>> supports.
> 
> Please don't add code that does not actually do something now, as that
> makes it impossible to review properly, _AND_ no one knows what is going
> to happen in the future.  In the future, you can just add a new ioctl
> and all is good, no need to break working userspace by suddenly looking
> at the arg value and doing something with it.
> 

I think the argument does something today and it's documented to need to 
be 0. If a userspace from the future provides non-zero value, Linux will 
correctly reject it because it doesn't know how to interpret the 
different VM types.

I can document it more clearly as the VM type field and support only the 
one VM type today.

Creating new ioctl for each VM type feels to me like I didn't design 
CREATE_VM ioctl right in first place.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-03  0:24       ` Greg Kroah-Hartman
@ 2022-11-04  0:11         ` Elliot Berman
  2022-11-04  8:10           ` Arnd Bergmann
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-04  0:11 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Arnd Bergmann, Srinivas Kandagatla,
	Amol Maheshwari, Kalle Valo, devicetree, linux-doc,
	linux-arm-msm, linux-kernel



On 11/2/2022 5:24 PM, Greg Kroah-Hartman wrote:
> On Wed, Nov 02, 2022 at 11:45:12AM -0700, Elliot Berman wrote:
>> +Michael
>>
>> On 11/1/2022 10:14 PM, Greg Kroah-Hartman wrote:
>>> On Wed, Oct 26, 2022 at 11:58:38AM -0700, Elliot Berman wrote:
>>>> +#define GH_CREATE_VM			_IO(GH_IOCTL_TYPE, 0x40) /* Returns a Gunyah VM fd */
>>>
>>> Why 0x40?  Why not just use the same KVM ioctl numbers and names as you
>>> are doing the same thing as them, right?
>>
>> We've designed so that there are a few ioctls that will feel similar to KVM
>> ioctls since we know this design has been successful, but we don't intend to
>> support KVM ioctls 1:1. Gunyah has different semantics for many of the
>> name-identical ioctls. It seems odd to mix some re-used KVM ioctls with
>> novel Gunyah ioctls?
> 
> Even if you don't support it 1:1, at least for the ones that are the
> same thing, pick the same numbers as that's a nicer thing to do, right?
> 

Does same thing == interpretation of arguments is the same? For
instance, GH_CREATE_VM and KVM_CREATE_VM interpret the arguments
differently. Same for KVM_SET_USERSPACE_MEMORY. The high level 
functionality should be similar for most all hypervisors since they will 
all support creating a VM and probably sharing memory with that VM. The 
arguments for that will necessarily look similar, but they will probably 
be subtly different because the hypervisors support different features.

I don't think userspace that supports both KVM and Gunyah will benefit 
much from re-using the same numbers since those re-used ioctl calls 
still need to sit within the context of a Gunyah VM.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-04  0:11         ` Elliot Berman
@ 2022-11-04  8:10           ` Arnd Bergmann
  2022-11-04 22:38             ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Arnd Bergmann @ 2022-11-04  8:10 UTC (permalink / raw)
  To: Elliot Berman, Greg Kroah-Hartman
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel

On Fri, Nov 4, 2022, at 01:11, Elliot Berman wrote:
> On 11/2/2022 5:24 PM, Greg Kroah-Hartman wrote:
>> On Wed, Nov 02, 2022 at 11:45:12AM -0700, Elliot Berman wrote:
>>
>> Even if you don't support it 1:1, at least for the ones that are the
>> same thing, pick the same numbers as that's a nicer thing to do, right?
>> 
>
> Does same thing == interpretation of arguments is the same? For
> instance, GH_CREATE_VM and KVM_CREATE_VM interpret the arguments
> differently. Same for KVM_SET_USERSPACE_MEMORY. The high level 
> functionality should be similar for most all hypervisors since they will 
> all support creating a VM and probably sharing memory with that VM. The 
> arguments for that will necessarily look similar, but they will probably 
> be subtly different because the hypervisors support different features.

I think in the ideal case, you should make the arguments and the
command codes the same for any command where that is possible. If
you come across a command that is shared with KVM but just needs
another flag, that would involve coordinating with the KVM maintainers
about sharing the definition so the same flag does not get reused
in an incompatible way.

For commands that cannot fit into the existing definition, there
should be a different command code, using your own namespace and
not the 0xAE block that KVM has. It still makes sense to follow
the argument structure roughly here, unless there is a technical
reason for making it different.

> I don't think userspace that supports both KVM and Gunyah will benefit 
> much from re-using the same numbers since those re-used ioctl calls 
> still need to sit within the context of a Gunyah VM.

One immediate benefit is for tools that work on running processes,
such as strace, gdb or qemu-user. If they encounter a known command,
they can correctly display the arguments etc.

Another benefit is for sharing portions of the VMM that live in
outside processes like vhost-user based device emulation that
interacts with irqfd, memfd etc. The more similar the command
interface is, the easier it gets to keep these tools portable.

      Arnd

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-04  8:10           ` Arnd Bergmann
@ 2022-11-04 22:38             ` Elliot Berman
  2022-11-05  4:19               ` Trilok Soni
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-04 22:38 UTC (permalink / raw)
  To: Arnd Bergmann, Greg Kroah-Hartman
  Cc: Bjorn Andersson, Murali Nalajala, Trilok Soni,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel



On 11/4/2022 1:10 AM, Arnd Bergmann wrote:
> On Fri, Nov 4, 2022, at 01:11, Elliot Berman wrote:
>> On 11/2/2022 5:24 PM, Greg Kroah-Hartman wrote:
>>> On Wed, Nov 02, 2022 at 11:45:12AM -0700, Elliot Berman wrote:
>>>
>>> Even if you don't support it 1:1, at least for the ones that are the
>>> same thing, pick the same numbers as that's a nicer thing to do, right?
>>>
>>
>> Does same thing == interpretation of arguments is the same? For
>> instance, GH_CREATE_VM and KVM_CREATE_VM interpret the arguments
>> differently. Same for KVM_SET_USERSPACE_MEMORY. The high level
>> functionality should be similar for most all hypervisors since they will
>> all support creating a VM and probably sharing memory with that VM. The
>> arguments for that will necessarily look similar, but they will probably
>> be subtly different because the hypervisors support different features.
> 
> I think in the ideal case, you should make the arguments and the
> command codes the same for any command where that is possible. If
> you come across a command that is shared with KVM but just needs
> another flag, that would involve coordinating with the KVM maintainers
> about sharing the definition so the same flag does not get reused
> in an incompatible way.
> 

I think the converse also needs to be true; KVM would need to check that
new flags don't get used in some incompatible way with Gunyah, even if
one of us is just -EINVAL'ing. I don't think Gunyah and KVM should be
reliant on the other reviewing shared ioctls.

The problem is a bit worse because "machine type" is architecture-
dependent whereas the planned Gunyah flags are architecture-independent.
KVM within itself re-uses flags between architectures so Gunyah would
need to reserve some flags from all architectures that KVM supports.

> For commands that cannot fit into the existing definition, there
> should be a different command code, using your own namespace and
> not the 0xAE block that KVM has. It still makes sense to follow
> the argument structure roughly here, unless there is a technical
> reason for making it different.
> 
>> I don't think userspace that supports both KVM and Gunyah will benefit
>> much from re-using the same numbers since those re-used ioctl calls
>> still need to sit within the context of a Gunyah VM.
> 
> One immediate benefit is for tools that work on running processes,
> such as strace, gdb or qemu-user. If they encounter a known command,
> they can correctly display the arguments etc.
> 

We can update these tools and anyway there will be different ioctls to
get started. There are important ioctls that wouldn't be correctly
displayed off the bat anyway; work would need to be done to support the
Gunyah ioctls either way. Whereas tooling update is temporary, the
coupling of KVM and Gunyah ioctls would be permanent.

> Another benefit is for sharing portions of the VMM that live in
> outside processes like vhost-user based device emulation that
> interacts with irqfd, memfd etc. The more similar the command
> interface is, the easier it gets to keep these tools portable.
> 

Hypervisor interfaces already have different ioctls for equivalent
functionality [1], so VMMs that want to scale to multiple hypervisors
already abstract out ioctl-level interfaces so there wouldn't be any
code-reuse even if Gunyah and KVM shared the same ioctl number. Between
hypervisors, the best case is there is design similarity for userspace,
which makes it easier to add new hypervisor support for VMMs and that's
what we are aiming for.

[1]: e.g. compare KVM, acrn, xen for implementing virtual interrupts.
KVM and acrn use independently implemented irqfd interfaces, xen has
totally different implementation called event channels.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-04 22:38             ` Elliot Berman
@ 2022-11-05  4:19               ` Trilok Soni
  2022-11-11  0:03                 ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Trilok Soni @ 2022-11-05  4:19 UTC (permalink / raw)
  To: Elliot Berman, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Bjorn Andersson, Murali Nalajala, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel

On 11/4/2022 3:38 PM, Elliot Berman wrote:
> 
> 
> On 11/4/2022 1:10 AM, Arnd Bergmann wrote:
>> On Fri, Nov 4, 2022, at 01:11, Elliot Berman wrote:
>>> On 11/2/2022 5:24 PM, Greg Kroah-Hartman wrote:
>>>> On Wed, Nov 02, 2022 at 11:45:12AM -0700, Elliot Berman wrote:
>>>>
>>>> Even if you don't support it 1:1, at least for the ones that are the
>>>> same thing, pick the same numbers as that's a nicer thing to do, right?
>>>>
>>>
>>> Does same thing == interpretation of arguments is the same? For
>>> instance, GH_CREATE_VM and KVM_CREATE_VM interpret the arguments
>>> differently. Same for KVM_SET_USERSPACE_MEMORY. The high level
>>> functionality should be similar for most all hypervisors since they will
>>> all support creating a VM and probably sharing memory with that VM. The
>>> arguments for that will necessarily look similar, but they will probably
>>> be subtly different because the hypervisors support different features.
>>
>> I think in the ideal case, you should make the arguments and the
>> command codes the same for any command where that is possible. If
>> you come across a command that is shared with KVM but just needs
>> another flag, that would involve coordinating with the KVM maintainers
>> about sharing the definition so the same flag does not get reused
>> in an incompatible way.
>>
> 
> I think the converse also needs to be true; KVM would need to check that
> new flags don't get used in some incompatible way with Gunyah, even if
> one of us is just -EINVAL'ing. I don't think Gunyah and KVM should be
> reliant on the other reviewing shared ioctls.
> 
> The problem is a bit worse because "machine type" is architecture-
> dependent whereas the planned Gunyah flags are architecture-independent.
> KVM within itself re-uses flags between architectures so Gunyah would
> need to reserve some flags from all architectures that KVM supports.

I agree w/ Elliot. We would like to keep Gunyah independent and not rely 
on the existing KVM ioctls space. We should allow new hypervisor drivers 
interfaces addition in Linux kernel without them relying on KVM.

> 
>> For commands that cannot fit into the existing definition, there
>> should be a different command code, using your own namespace and
>> not the 0xAE block that KVM has. It still makes sense to follow
>> the argument structure roughly here, unless there is a technical
>> reason for making it different.
>>
>>> I don't think userspace that supports both KVM and Gunyah will benefit
>>> much from re-using the same numbers since those re-used ioctl calls
>>> still need to sit within the context of a Gunyah VM.
>>
>> One immediate benefit is for tools that work on running processes,
>> such as strace, gdb or qemu-user. If they encounter a known command,
>> they can correctly display the arguments etc.
>>
> 
> We can update these tools and anyway there will be different ioctls to
> get started. There are important ioctls that wouldn't be correctly
> displayed off the bat anyway; work would need to be done to support the
> Gunyah ioctls either way. Whereas tooling update is temporary, the
> coupling of KVM and Gunyah ioctls would be permanent.

Agree, tools can be updated and that is the easy part as we grow the s/w 
stack around Gunyah in userspace, like we already do w/ CrosVM (Virtual 
Machine Manager) and QEMU will be next followed by rust-vmm. All of them 
can be done without Gunyah ioctls relying anything on the KVM ioctls. 
Elliot has also explained very well that we don't to go to KVM 
maintainers for any of our additions and we also don't want them to come 
to us, since there is no interoperability testing. It is best that both 
Hypervisors and their Linux interfaces evolve independently.

---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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-05  4:19               ` Trilok Soni
@ 2022-11-11  0:03                 ` Elliot Berman
  2022-11-11  6:24                   ` Greg Kroah-Hartman
  0 siblings, 1 reply; 67+ messages in thread
From: Elliot Berman @ 2022-11-11  0:03 UTC (permalink / raw)
  To: Trilok Soni, Arnd Bergmann, Greg Kroah-Hartman
  Cc: Bjorn Andersson, Murali Nalajala, Srivatsa Vaddagiri,
	Carl van Schaik, Prakruthi Deepak Heragu, Andy Gross,
	Dmitry Baryshkov, Jassi Brar, linux-arm-kernel, Mark Rutland,
	Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier, Rob Herring,
	Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel

Hi Arnd, Greg,

On 11/4/2022 9:19 PM, Trilok Soni wrote:
> On 11/4/2022 3:38 PM, Elliot Berman wrote:
>>
>>
>> On 11/4/2022 1:10 AM, Arnd Bergmann wrote:
>>> On Fri, Nov 4, 2022, at 01:11, Elliot Berman wrote:
>>>> On 11/2/2022 5:24 PM, Greg Kroah-Hartman wrote:
>>>>> On Wed, Nov 02, 2022 at 11:45:12AM -0700, Elliot Berman wrote:
>>>>>
>>>>> Even if you don't support it 1:1, at least for the ones that are the
>>>>> same thing, pick the same numbers as that's a nicer thing to do, 
>>>>> right?
>>>>>
>>>>
>>>> Does same thing == interpretation of arguments is the same? For
>>>> instance, GH_CREATE_VM and KVM_CREATE_VM interpret the arguments
>>>> differently. Same for KVM_SET_USERSPACE_MEMORY. The high level
>>>> functionality should be similar for most all hypervisors since they 
>>>> will
>>>> all support creating a VM and probably sharing memory with that VM. The
>>>> arguments for that will necessarily look similar, but they will 
>>>> probably
>>>> be subtly different because the hypervisors support different features.
>>>
>>> I think in the ideal case, you should make the arguments and the
>>> command codes the same for any command where that is possible. If
>>> you come across a command that is shared with KVM but just needs
>>> another flag, that would involve coordinating with the KVM maintainers
>>> about sharing the definition so the same flag does not get reused
>>> in an incompatible way.
>>>
>>
>> I think the converse also needs to be true; KVM would need to check that
>> new flags don't get used in some incompatible way with Gunyah, even if
>> one of us is just -EINVAL'ing. I don't think Gunyah and KVM should be
>> reliant on the other reviewing shared ioctls.
>>
>> The problem is a bit worse because "machine type" is architecture-
>> dependent whereas the planned Gunyah flags are architecture-independent.
>> KVM within itself re-uses flags between architectures so Gunyah would
>> need to reserve some flags from all architectures that KVM supports.
> 
> I agree w/ Elliot. We would like to keep Gunyah independent and not rely 
> on the existing KVM ioctls space. We should allow new hypervisor drivers 
> interfaces addition in Linux kernel without them relying on KVM.
> 
>>
>>> For commands that cannot fit into the existing definition, there
>>> should be a different command code, using your own namespace and
>>> not the 0xAE block that KVM has. It still makes sense to follow
>>> the argument structure roughly here, unless there is a technical
>>> reason for making it different.
>>>
>>>> I don't think userspace that supports both KVM and Gunyah will benefit
>>>> much from re-using the same numbers since those re-used ioctl calls
>>>> still need to sit within the context of a Gunyah VM.
>>>
>>> One immediate benefit is for tools that work on running processes,
>>> such as strace, gdb or qemu-user. If they encounter a known command,
>>> they can correctly display the arguments etc.
>>>
>>
>> We can update these tools and anyway there will be different ioctls to
>> get started. There are important ioctls that wouldn't be correctly
>> displayed off the bat anyway; work would need to be done to support the
>> Gunyah ioctls either way. Whereas tooling update is temporary, the
>> coupling of KVM and Gunyah ioctls would be permanent.
> 
> Agree, tools can be updated and that is the easy part as we grow the s/w 
> stack around Gunyah in userspace, like we already do w/ CrosVM (Virtual 
> Machine Manager) and QEMU will be next followed by rust-vmm. All of them 
> can be done without Gunyah ioctls relying anything on the KVM ioctls. 
> Elliot has also explained very well that we don't to go to KVM 
> maintainers for any of our additions and we also don't want them to come 
> to us, since there is no interoperability testing. It is best that both 
> Hypervisors and their Linux interfaces evolve independently.

Are above explanations reasonable to not re-use KVM ioctl numbers?

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-11  0:03                 ` Elliot Berman
@ 2022-11-11  6:24                   ` Greg Kroah-Hartman
  2022-11-11 17:08                     ` Elliot Berman
  0 siblings, 1 reply; 67+ messages in thread
From: Greg Kroah-Hartman @ 2022-11-11  6:24 UTC (permalink / raw)
  To: Elliot Berman
  Cc: Trilok Soni, Arnd Bergmann, Bjorn Andersson, Murali Nalajala,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel

On Thu, Nov 10, 2022 at 04:03:10PM -0800, Elliot Berman wrote:
> > Agree, tools can be updated and that is the easy part as we grow the s/w
> > stack around Gunyah in userspace, like we already do w/ CrosVM (Virtual
> > Machine Manager) and QEMU will be next followed by rust-vmm. All of them
> > can be done without Gunyah ioctls relying anything on the KVM ioctls.
> > Elliot has also explained very well that we don't to go to KVM
> > maintainers for any of our additions and we also don't want them to come
> > to us, since there is no interoperability testing. It is best that both
> > Hypervisors and their Linux interfaces evolve independently.
> 
> Are above explanations reasonable to not re-use KVM ioctl numbers?

Try getting close at least, where possible please.  As your ioctl
numbers didn't even start at 0, it's a bit odd...

thanks,

greg k-h

_______________________________________________
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] 67+ messages in thread

* Re: [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager
  2022-11-11  6:24                   ` Greg Kroah-Hartman
@ 2022-11-11 17:08                     ` Elliot Berman
  0 siblings, 0 replies; 67+ messages in thread
From: Elliot Berman @ 2022-11-11 17:08 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Trilok Soni, Arnd Bergmann, Bjorn Andersson, Murali Nalajala,
	Srivatsa Vaddagiri, Carl van Schaik, Prakruthi Deepak Heragu,
	Andy Gross, Dmitry Baryshkov, Jassi Brar, linux-arm-kernel,
	Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Marc Zyngier,
	Rob Herring, Krzysztof Kozlowski, Jonathan Corbet, Will Deacon,
	Catalin Marinas, Srinivas Kandagatla, Amol Maheshwari,
	Kalle Valo, devicetree, linux-doc, linux-arm-msm, linux-kernel



On 11/10/2022 10:24 PM, Greg Kroah-Hartman wrote:
> On Thu, Nov 10, 2022 at 04:03:10PM -0800, Elliot Berman wrote:
>>> Agree, tools can be updated and that is the easy part as we grow the s/w
>>> stack around Gunyah in userspace, like we already do w/ CrosVM (Virtual
>>> Machine Manager) and QEMU will be next followed by rust-vmm. All of them
>>> can be done without Gunyah ioctls relying anything on the KVM ioctls.
>>> Elliot has also explained very well that we don't to go to KVM
>>> maintainers for any of our additions and we also don't want them to come
>>> to us, since there is no interoperability testing. It is best that both
>>> Hypervisors and their Linux interfaces evolve independently.
>>
>> Are above explanations reasonable to not re-use KVM ioctl numbers?
> 
> Try getting close at least, where possible please.  As your ioctl
> numbers didn't even start at 0, it's a bit odd...

Ack, will do.

Thanks,
Elliot

_______________________________________________
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] 67+ messages in thread

end of thread, other threads:[~2022-11-11 17:10 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-26 18:58 [PATCH v6 00/21] Drivers for gunyah hypervisor Elliot Berman
2022-10-26 18:58 ` [PATCH v6 01/21] docs: gunyah: Introduce Gunyah Hypervisor Elliot Berman
2022-11-02 12:35   ` Bagas Sanjaya
2022-10-26 18:58 ` [PATCH v6 02/21] dt-bindings: Add binding for gunyah hypervisor Elliot Berman
2022-10-27 19:57   ` Krzysztof Kozlowski
2022-10-28  2:33   ` Jassi Brar
2022-11-01  3:19     ` Elliot Berman
2022-11-01 16:23       ` Jassi Brar
2022-11-01 20:35         ` Elliot Berman
2022-11-01 21:58           ` Jassi Brar
2022-11-02  0:12             ` Elliot Berman
2022-11-02  2:01               ` Jassi Brar
2022-11-02 18:05                 ` Elliot Berman
2022-11-02 18:24                   ` Jassi Brar
2022-11-02 23:23                     ` Elliot Berman
2022-11-03  3:21                       ` Jassi Brar
2022-11-03 19:45                         ` Elliot Berman
2022-10-26 18:58 ` [PATCH v6 03/21] gunyah: Common types and error codes for Gunyah hypercalls Elliot Berman
2022-10-26 19:47   ` Dmitry Baryshkov
2022-10-26 18:58 ` [PATCH v6 04/21] arm64: smccc: Include alternative-macros.h Elliot Berman
2022-10-26 19:46   ` Dmitry Baryshkov
2022-10-26 20:23     ` Elliot Berman
2022-10-26 20:39       ` Dmitry Baryshkov
2022-10-26 18:58 ` [PATCH v6 05/21] virt: gunyah: Add hypercalls to identify Gunyah Elliot Berman
2022-10-26 18:58 ` [PATCH v6 06/21] virt: gunyah: Identify hypervisor version Elliot Berman
2022-10-26 18:58 ` [PATCH v6 07/21] mailbox: Allow direct registration to a channel Elliot Berman
2022-10-26 18:58 ` [PATCH v6 08/21] virt: gunyah: msgq: Add hypercalls to send and receive messages Elliot Berman
2022-10-26 18:58 ` [PATCH v6 09/21] mailbox: Add Gunyah message queue mailbox Elliot Berman
2022-10-27 13:55   ` Pavan Kondeti
2022-11-01 17:44     ` Elliot Berman
2022-10-26 18:58 ` [PATCH v6 10/21] gunyah: rsc_mgr: Add resource manager RPC core Elliot Berman
2022-11-01 18:02   ` Greg Kroah-Hartman
2022-11-02  0:12     ` Elliot Berman
2022-11-02  2:53       ` Greg Kroah-Hartman
2022-11-02 18:04         ` Elliot Berman
2022-11-03  0:22           ` Greg Kroah-Hartman
2022-11-03 22:07             ` Elliot Berman
2022-11-03 22:09             ` Elliot Berman
2022-10-26 18:58 ` [PATCH v6 11/21] gunyah: rsc_mgr: Add subdevices bus Elliot Berman
2022-10-26 18:58 ` [PATCH v6 12/21] gunyah: rsc_mgr: Add VM lifecycle RPC Elliot Berman
2022-10-26 18:58 ` [PATCH v6 13/21] gunyah: vm_mgr: Introduce basic VM Manager Elliot Berman
2022-11-02  5:14   ` Greg Kroah-Hartman
2022-11-02 18:45     ` Elliot Berman
2022-11-03  0:24       ` Greg Kroah-Hartman
2022-11-04  0:11         ` Elliot Berman
2022-11-04  8:10           ` Arnd Bergmann
2022-11-04 22:38             ` Elliot Berman
2022-11-05  4:19               ` Trilok Soni
2022-11-11  0:03                 ` Elliot Berman
2022-11-11  6:24                   ` Greg Kroah-Hartman
2022-11-11 17:08                     ` Elliot Berman
2022-11-02  7:31   ` Arnd Bergmann
2022-11-02 18:44     ` Elliot Berman
2022-11-03  0:20       ` Greg Kroah-Hartman
2022-11-03 22:33         ` Elliot Berman
2022-11-03  9:39       ` Arnd Bergmann
2022-11-03 22:10         ` Elliot Berman
2022-10-26 18:58 ` [PATCH v6 14/21] gunyah: rsc_mgr: Add RPC for sharing memory Elliot Berman
2022-10-26 18:58 ` [PATCH v6 15/21] gunyah: vm_mgr: Add/remove user memory regions Elliot Berman
2022-10-26 18:58 ` [PATCH v6 16/21] gunyah: vm_mgr: Add ioctls to support basic non-proxy VM boot Elliot Berman
2022-10-26 18:58 ` [PATCH v6 17/21] samples: Add sample userspace Gunyah VM Manager Elliot Berman
2022-10-26 18:58 ` [PATCH v6 18/21] gunyah: rsc_mgr: Add platform ops on mem_lend/mem_reclaim Elliot Berman
2022-10-26 18:58 ` [PATCH v6 19/21] firmware: qcom_scm: Use fixed width src vm bitmap Elliot Berman
2022-10-26 18:58 ` [PATCH v6 20/21] firmware: qcom_scm: Register Gunyah platform ops Elliot Berman
2022-10-26 18:58 ` [PATCH v6 21/21] docs: gunyah: Document Gunyah VM Manager Elliot Berman
2022-11-02 13:05   ` Bagas Sanjaya
2022-11-02 18:04     ` Elliot Berman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).