From: Elliot Berman <quic_eberman@quicinc.com>
To: Alex Elder <elder@linaro.org>,
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>,
Murali Nalajal <quic_mnalajal@quicinc.com>,
Trilok Soni <quic_tsoni@quicinc.com>,
Srivatsa Vaddagiri <quic_svaddagi@quicinc.com>,
Carl van Schaik <quic_cvanscha@quicinc.com>,
Philip Derrin <quic_pderrin@quicinc.com>,
Prakruthi Deepak Heragu <quic_pheragu@quicinc.com>,
Jonathan Corbet <corbet@lwn.net>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Konrad Dybcio <konrad.dybcio@linaro.org>,
Bjorn Andersson <andersson@kernel.org>,
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>,
"Fuad Tabba" <tabba@google.com>,
Sean Christopherson <seanjc@google.com>,
"Andrew Morton" <akpm@linux-foundation.org>
Cc: <linux-arm-msm@vger.kernel.org>, <linux-doc@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>, <linux-mm@kvack.org>,
Elliot Berman <quic_eberman@quicinc.com>
Subject: [PATCH v16 11/34] virt: gunyah: Translate gh_rm_hyp_resource into gunyah_resource
Date: Tue, 9 Jan 2024 11:37:49 -0800 [thread overview]
Message-ID: <20240109-gunyah-v16-11-634904bf4ce9@quicinc.com> (raw)
In-Reply-To: <20240109-gunyah-v16-0-634904bf4ce9@quicinc.com>
When booting a Gunyah virtual machine, the host VM may gain capabilities
to interact with resources for the guest virtual machine. Examples of
such resources are vCPUs or message queues. To use those resources, we
need to translate the RM response into a gunyah_resource structure which
are useful to Linux drivers. Presently, Linux drivers need only to know
the type of resource, the capability ID, and an interrupt.
On ARM64 systems, the interrupt reported by Gunyah is the GIC interrupt
ID number and always a SPI or extended SPI.
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
arch/arm64/include/asm/gunyah.h | 36 +++++++++
drivers/virt/gunyah/rsc_mgr.c | 175 +++++++++++++++++++++++++++++++++++++++-
drivers/virt/gunyah/rsc_mgr.h | 5 ++
include/linux/gunyah.h | 3 +
4 files changed, 218 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/gunyah.h b/arch/arm64/include/asm/gunyah.h
new file mode 100644
index 000000000000..0cd3debe22b6
--- /dev/null
+++ b/arch/arm64/include/asm/gunyah.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#ifndef _ASM_GUNYAH_H
+#define _ASM_GUNYAH_H
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+
+static inline int arch_gunyah_fill_irq_fwspec_params(u32 virq,
+ struct irq_fwspec *fwspec)
+{
+ /* Assume that Gunyah gave us an SPI or ESPI; defensively check it */
+ if (WARN(virq < 32, "Unexpected virq: %d\n", virq)) {
+ return -EINVAL;
+ } else if (virq <= 1019) {
+ fwspec->param_count = 3;
+ fwspec->param[0] = 0; /* GIC_SPI */
+ fwspec->param[1] = virq - 32; /* virq 32 -> SPI 0 */
+ fwspec->param[2] = IRQ_TYPE_EDGE_RISING;
+ } else if (WARN(virq < 4096, "Unexpected virq: %d\n", virq)) {
+ return -EINVAL;
+ } else if (virq < 5120) {
+ fwspec->param_count = 3;
+ fwspec->param[0] = 2; /* GIC_ESPI */
+ fwspec->param[1] = virq - 4096; /* virq 4096 -> ESPI 0 */
+ fwspec->param[2] = IRQ_TYPE_EDGE_RISING;
+ } else {
+ WARN(1, "Unexpected virq: %d\n", virq);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+#endif
diff --git a/drivers/virt/gunyah/rsc_mgr.c b/drivers/virt/gunyah/rsc_mgr.c
index 45f9514cfe0e..efc0970ae4cc 100644
--- a/drivers/virt/gunyah/rsc_mgr.c
+++ b/drivers/virt/gunyah/rsc_mgr.c
@@ -9,9 +9,12 @@
#include <linux/mutex.h>
#include <linux/notifier.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
+#include <asm/gunyah.h>
+
#include "rsc_mgr.h"
#include "vm_mgr.h"
@@ -121,6 +124,7 @@ struct gunyah_rm_message {
* @send_ready: completed when we know Tx message queue can take more messages
* @nh: notifier chain for clients interested in RM notification messages
* @miscdev: /dev/gunyah
+ * @irq_domain: Domain to translate Gunyah hwirqs to Linux irqs
*/
struct gunyah_rm {
struct device *dev;
@@ -138,6 +142,7 @@ struct gunyah_rm {
struct blocking_notifier_head nh;
struct miscdevice miscdev;
+ struct irq_domain *irq_domain;
};
/**
@@ -178,6 +183,143 @@ static inline int gunyah_rm_error_remap(enum gunyah_rm_error rm_error)
}
}
+struct gunyah_irq_chip_data {
+ u32 gunyah_virq;
+};
+
+static struct irq_chip gunyah_rm_irq_chip = {
+ /* clang-format off */
+ .name = "Gunyah",
+ .irq_enable = irq_chip_enable_parent,
+ .irq_disable = irq_chip_disable_parent,
+ .irq_ack = irq_chip_ack_parent,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_mask_ack = irq_chip_mask_ack_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .irq_set_type = irq_chip_set_type_parent,
+ .irq_set_wake = irq_chip_set_wake_parent,
+ .irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
+ .irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_get_irqchip_state = irq_chip_get_parent_state,
+ .irq_set_irqchip_state = irq_chip_set_parent_state,
+ .flags = IRQCHIP_SET_TYPE_MASKED |
+ IRQCHIP_SKIP_SET_WAKE |
+ IRQCHIP_MASK_ON_SUSPEND,
+ /* clang-format on */
+};
+
+static int gunyah_rm_irq_domain_alloc(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ struct gunyah_irq_chip_data *chip_data, *spec = arg;
+ struct irq_fwspec parent_fwspec = {};
+ struct gunyah_rm *rm = d->host_data;
+ u32 gunyah_virq = spec->gunyah_virq;
+ int ret;
+
+ if (nr_irqs != 1)
+ return -EINVAL;
+
+ chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
+ if (!chip_data)
+ return -ENOMEM;
+
+ chip_data->gunyah_virq = gunyah_virq;
+
+ ret = irq_domain_set_hwirq_and_chip(d, virq, chip_data->gunyah_virq,
+ &gunyah_rm_irq_chip, chip_data);
+ if (ret)
+ goto err_free_irq_data;
+
+ parent_fwspec.fwnode = d->parent->fwnode;
+ ret = arch_gunyah_fill_irq_fwspec_params(chip_data->gunyah_virq,
+ &parent_fwspec);
+ if (ret) {
+ dev_err(rm->dev, "virq translation failed %u: %d\n",
+ chip_data->gunyah_virq, ret);
+ goto err_free_irq_data;
+ }
+
+ ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &parent_fwspec);
+ if (ret)
+ goto err_free_irq_data;
+
+ return ret;
+err_free_irq_data:
+ kfree(chip_data);
+ return ret;
+}
+
+static void gunyah_rm_irq_domain_free_single(struct irq_domain *d,
+ unsigned int virq)
+{
+ struct irq_data *irq_data;
+
+ irq_data = irq_domain_get_irq_data(d, virq);
+ if (!irq_data)
+ return;
+
+ kfree(irq_data->chip_data);
+ irq_data->chip_data = NULL;
+}
+
+static void gunyah_rm_irq_domain_free(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ unsigned int i;
+
+ for (i = 0; i < nr_irqs; i++)
+ gunyah_rm_irq_domain_free_single(d, virq);
+}
+
+static const struct irq_domain_ops gunyah_rm_irq_domain_ops = {
+ .alloc = gunyah_rm_irq_domain_alloc,
+ .free = gunyah_rm_irq_domain_free,
+};
+
+struct gunyah_resource *
+gunyah_rm_alloc_resource(struct gunyah_rm *rm,
+ struct gunyah_rm_hyp_resource *hyp_resource)
+{
+ struct gunyah_resource *ghrsc;
+ int ret;
+
+ ghrsc = kzalloc(sizeof(*ghrsc), GFP_KERNEL);
+ if (!ghrsc)
+ return NULL;
+
+ ghrsc->type = hyp_resource->type;
+ ghrsc->capid = le64_to_cpu(hyp_resource->cap_id);
+ ghrsc->irq = IRQ_NOTCONNECTED;
+ ghrsc->rm_label = le32_to_cpu(hyp_resource->resource_label);
+ if (hyp_resource->virq) {
+ struct gunyah_irq_chip_data irq_data = {
+ .gunyah_virq = le32_to_cpu(hyp_resource->virq),
+ };
+
+ ret = irq_domain_alloc_irqs(rm->irq_domain, 1, NUMA_NO_NODE,
+ &irq_data);
+ if (ret < 0) {
+ dev_err(rm->dev,
+ "Failed to allocate interrupt for resource %d label: %d: %d\n",
+ ghrsc->type, ghrsc->rm_label, ret);
+ kfree(ghrsc);
+ return NULL;
+ }
+ ghrsc->irq = ret;
+ }
+
+ return ghrsc;
+}
+
+void gunyah_rm_free_resource(struct gunyah_resource *ghrsc)
+{
+ irq_dispose_mapping(ghrsc->irq);
+ kfree(ghrsc);
+}
+
static int gunyah_rm_init_message_payload(struct gunyah_rm_message *message,
const void *msg, size_t hdr_size,
size_t msg_size)
@@ -712,6 +854,8 @@ static int gunyah_rm_probe_rx_msgq(struct gunyah_rm *rm,
static int gunyah_rm_probe(struct platform_device *pdev)
{
+ struct irq_domain *parent_irq_domain;
+ struct device_node *parent_irq_node;
struct gunyah_rm *rm;
int ret;
@@ -737,15 +881,43 @@ static int gunyah_rm_probe(struct platform_device *pdev)
if (ret)
return ret;
+ parent_irq_node = of_irq_find_parent(pdev->dev.of_node);
+ if (!parent_irq_node) {
+ dev_err(&pdev->dev,
+ "Failed to find interrupt parent of resource manager\n");
+ return -ENODEV;
+ }
+
+ parent_irq_domain = irq_find_host(parent_irq_node);
+ if (!parent_irq_domain) {
+ dev_err(&pdev->dev,
+ "Failed to find interrupt parent domain of resource manager\n");
+ return -ENODEV;
+ }
+
+ rm->irq_domain = irq_domain_add_hierarchy(parent_irq_domain, 0, 0,
+ pdev->dev.of_node,
+ &gunyah_rm_irq_domain_ops,
+ NULL);
+ if (!rm->irq_domain) {
+ dev_err(&pdev->dev, "Failed to add irq domain\n");
+ return -ENODEV;
+ }
+ rm->irq_domain->host_data = rm;
+
+ rm->miscdev.parent = &pdev->dev;
rm->miscdev.name = "gunyah";
rm->miscdev.minor = MISC_DYNAMIC_MINOR;
rm->miscdev.fops = &gunyah_dev_fops;
ret = misc_register(&rm->miscdev);
if (ret)
- return ret;
+ goto err_irq_domain;
return 0;
+err_irq_domain:
+ irq_domain_remove(rm->irq_domain);
+ return ret;
}
static void gunyah_rm_remove(struct platform_device *pdev)
@@ -753,6 +925,7 @@ static void gunyah_rm_remove(struct platform_device *pdev)
struct gunyah_rm *rm = platform_get_drvdata(pdev);
misc_deregister(&rm->miscdev);
+ irq_domain_remove(rm->irq_domain);
}
static const struct of_device_id gunyah_rm_of_match[] = {
diff --git a/drivers/virt/gunyah/rsc_mgr.h b/drivers/virt/gunyah/rsc_mgr.h
index 205b9ea735e5..52711de77bb7 100644
--- a/drivers/virt/gunyah/rsc_mgr.h
+++ b/drivers/virt/gunyah/rsc_mgr.h
@@ -99,6 +99,11 @@ struct gunyah_rm_hyp_resources {
int gunyah_rm_get_hyp_resources(struct gunyah_rm *rm, u16 vmid,
struct gunyah_rm_hyp_resources **resources);
+struct gunyah_resource *
+gunyah_rm_alloc_resource(struct gunyah_rm *rm,
+ struct gunyah_rm_hyp_resource *hyp_resource);
+void gunyah_rm_free_resource(struct gunyah_resource *ghrsc);
+
int gunyah_rm_call(struct gunyah_rm *rsc_mgr, u32 message_id,
const void *req_buf, size_t req_buf_size, void **resp_buf,
size_t *resp_buf_size);
diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h
index acd70f982425..ede8abb1b276 100644
--- a/include/linux/gunyah.h
+++ b/include/linux/gunyah.h
@@ -29,6 +29,9 @@ struct gunyah_resource {
enum gunyah_resource_type type;
u64 capid;
unsigned int irq;
+
+ struct list_head list;
+ u32 rm_label;
};
/******************************************************************************/
--
2.34.1
next prev parent reply other threads:[~2024-01-09 19:38 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-09 19:37 [PATCH v16 00/34] Drivers for Gunyah hypervisor Elliot Berman
2024-01-09 19:37 ` [PATCH v16 01/34] docs: gunyah: Introduce Gunyah Hypervisor Elliot Berman
2024-01-09 23:31 ` Randy Dunlap
2024-01-10 0:28 ` Elliot Berman
2024-01-10 0:31 ` Randy Dunlap
2024-01-09 19:37 ` [PATCH v16 02/34] dt-bindings: Add binding for gunyah hypervisor Elliot Berman
2024-01-09 19:37 ` [PATCH v16 03/34] gunyah: Common types and error codes for Gunyah hypercalls Elliot Berman
2024-01-09 19:37 ` [PATCH v16 04/34] virt: gunyah: Add hypercalls to identify Gunyah Elliot Berman
2024-01-09 19:37 ` [PATCH v16 05/34] virt: gunyah: Add hypervisor driver Elliot Berman
2024-01-09 19:37 ` [PATCH v16 06/34] virt: gunyah: msgq: Add hypercalls to send and receive messages Elliot Berman
2024-01-09 19:37 ` [PATCH v16 07/34] gunyah: rsc_mgr: Add resource manager RPC core Elliot Berman
2024-01-09 19:37 ` [PATCH v16 08/34] gunyah: vm_mgr: Introduce basic VM Manager Elliot Berman
2024-01-09 19:37 ` [PATCH v16 09/34] gunyah: rsc_mgr: Add VM lifecycle RPC Elliot Berman
2024-01-09 19:37 ` [PATCH v16 10/34] gunyah: vm_mgr: Add VM start/stop Elliot Berman
2024-01-09 19:37 ` Elliot Berman [this message]
2024-01-09 19:37 ` [PATCH v16 12/34] virt: gunyah: Add resource tickets Elliot Berman
2024-01-09 19:37 ` [PATCH v16 13/34] gunyah: vm_mgr: Add framework for VM Functions Elliot Berman
2024-01-09 19:37 ` [PATCH v16 14/34] virt: gunyah: Add hypercalls for running a vCPU Elliot Berman
2024-01-09 19:37 ` [PATCH v16 15/34] virt: gunyah: Add proxy-scheduled vCPUs Elliot Berman
2024-01-09 19:37 ` [PATCH v16 16/34] gunyah: Add hypercalls for demand paging Elliot Berman
2024-01-09 19:37 ` [PATCH v16 17/34] gunyah: rsc_mgr: Add memory parcel RPC Elliot Berman
2024-01-09 19:37 ` [PATCH v16 18/34] virt: gunyah: Add interfaces to map memory into guest address space Elliot Berman
2024-01-09 19:37 ` [PATCH v16 19/34] gunyah: rsc_mgr: Add platform ops on mem_lend/mem_reclaim Elliot Berman
2024-01-09 19:37 ` [PATCH v16 20/34] virt: gunyah: Add Qualcomm Gunyah platform ops Elliot Berman
2024-01-09 19:37 ` [PATCH v16 21/34] virt: gunyah: Implement guestmemfd Elliot Berman
2024-01-09 19:38 ` [PATCH v16 22/34] virt: gunyah: Add ioctl to bind guestmem to VMs Elliot Berman
2024-01-09 19:38 ` [PATCH v16 23/34] virt: gunyah: guestmem: Initialize RM mem parcels from guestmem Elliot Berman
2024-01-09 19:38 ` [PATCH v16 24/34] virt: gunyah: Share guest VM dtb configuration to Gunyah Elliot Berman
2024-01-09 19:38 ` [PATCH v16 25/34] gunyah: rsc_mgr: Add RPC to enable demand paging Elliot Berman
2024-01-09 19:38 ` [PATCH v16 26/34] mm/interval_tree: Export iter_first/iter_next Elliot Berman
2024-01-09 19:38 ` [PATCH v16 27/34] virt: gunyah: Enable demand paging Elliot Berman
2024-01-09 19:38 ` [PATCH v16 28/34] gunyah: rsc_mgr: Add RPC to set VM boot context Elliot Berman
2024-01-09 19:38 ` [PATCH v16 29/34] virt: gunyah: Allow userspace to initialize context of primary vCPU Elliot Berman
2024-01-09 19:38 ` [PATCH v16 30/34] virt: gunyah: Add hypercalls for sending doorbell Elliot Berman
2024-01-09 19:38 ` [PATCH v16 31/34] virt: gunyah: Add irqfd interface Elliot Berman
2024-01-09 19:38 ` [PATCH v16 32/34] virt: gunyah: Add IO handlers Elliot Berman
2024-01-09 19:38 ` [PATCH v16 33/34] virt: gunyah: Add ioeventfd Elliot Berman
2024-01-09 19:38 ` [PATCH v16 34/34] MAINTAINERS: Add Gunyah hypervisor drivers section Elliot Berman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240109-gunyah-v16-11-634904bf4ce9@quicinc.com \
--to=quic_eberman@quicinc.com \
--cc=akpm@linux-foundation.org \
--cc=andersson@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=devicetree@vger.kernel.org \
--cc=dmitry.baryshkov@linaro.org \
--cc=elder@linaro.org \
--cc=konrad.dybcio@linaro.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=quic_cvanscha@quicinc.com \
--cc=quic_mnalajal@quicinc.com \
--cc=quic_pderrin@quicinc.com \
--cc=quic_pheragu@quicinc.com \
--cc=quic_svaddagi@quicinc.com \
--cc=quic_tsoni@quicinc.com \
--cc=robh+dt@kernel.org \
--cc=seanjc@google.com \
--cc=srinivas.kandagatla@linaro.org \
--cc=tabba@google.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox