FROMLIST: gunyah: vm_mgr: Introduce basic VM Manager

Gunyah VM manager is a kernel moduel which exposes an interface to
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.

Bug: 338347082
Link: https://lore.kernel.org/all/20240222-gunyah-v17-8-1e9da6763d38@quicinc.com/
Change-Id: I6fe1e2dec8366afa454a76b81bae568f5a80f9dd
Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Reviewed-by: Alex Elder <elder@linaro.org>
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>
Signed-off-by: Elliot Berman <elliot.berman@oss.qualcomm.com>
This commit is contained in:
Elliot Berman
2024-02-22 15:16:31 -08:00
committed by Treehugger Robot
parent 4c11c572f4
commit b387fa408e
7 changed files with 198 additions and 2 deletions
@@ -140,6 +140,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' 00-0F linux/gunyah.h conflict!
'H' 00-7F linux/hiddev.h conflict!
'H' 00-0F linux/hidraw.h conflict!
'H' 01 linux/mei.h conflict!
+1 -1
View File
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
gunyah_rsc_mgr-y += rsc_mgr.o
gunyah_rsc_mgr-y += rsc_mgr.o vm_mgr.o
obj-$(CONFIG_GUNYAH) += gunyah.o gunyah_rsc_mgr.o
+49 -1
View File
@@ -10,8 +10,10 @@
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include "rsc_mgr.h"
#include "vm_mgr.h"
/* clang-format off */
#define RM_RPC_API_VERSION_MASK GENMASK(3, 0)
@@ -118,6 +120,7 @@ struct gunyah_rm_message {
* @send_lock: synchronization to allow only one request to be sent at a time
* @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
*/
struct gunyah_rm {
struct device *dev;
@@ -133,6 +136,8 @@ struct gunyah_rm {
struct mutex send_lock;
struct completion send_ready;
struct blocking_notifier_head nh;
struct miscdevice miscdev;
};
/**
@@ -613,6 +618,36 @@ int gunyah_rm_notifier_unregister(struct gunyah_rm *rm,
}
EXPORT_SYMBOL_GPL(gunyah_rm_notifier_unregister);
struct device *gunyah_rm_get(struct gunyah_rm *rm)
{
return get_device(rm->miscdev.this_device);
}
EXPORT_SYMBOL_GPL(gunyah_rm_get);
void gunyah_rm_put(struct gunyah_rm *rm)
{
put_device(rm->miscdev.this_device);
}
EXPORT_SYMBOL_GPL(gunyah_rm_put);
static long gunyah_dev_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
struct miscdevice *miscdev = filp->private_data;
struct gunyah_rm *rm = container_of(miscdev, struct gunyah_rm, miscdev);
return gunyah_dev_vm_mgr_ioctl(rm, cmd, arg);
}
static const struct file_operations gunyah_dev_fops = {
/* clang-format off */
.owner = THIS_MODULE,
.unlocked_ioctl = gunyah_dev_ioctl,
.compat_ioctl = compat_ptr_ioctl,
.llseek = noop_llseek,
/* clang-format on */
};
static int gunyah_platform_probe_capability(struct platform_device *pdev,
int idx,
struct gunyah_resource *ghrsc)
@@ -699,7 +734,19 @@ static int gunyah_rm_probe(struct platform_device *pdev)
if (ret)
return ret;
return 0;
rm->miscdev.parent = &pdev->dev;
rm->miscdev.name = "gunyah";
rm->miscdev.minor = MISC_DYNAMIC_MINOR;
rm->miscdev.fops = &gunyah_dev_fops;
return misc_register(&rm->miscdev);
}
static void gunyah_rm_remove(struct platform_device *pdev)
{
struct gunyah_rm *rm = platform_get_drvdata(pdev);
misc_deregister(&rm->miscdev);
}
static const struct of_device_id gunyah_rm_of_match[] = {
@@ -710,6 +757,7 @@ MODULE_DEVICE_TABLE(of, gunyah_rm_of_match);
static struct platform_driver gunyah_rm_driver = {
.probe = gunyah_rm_probe,
.remove_new = gunyah_rm_remove,
.driver = {
.name = "gunyah_rsc_mgr",
.of_match_table = gunyah_rm_of_match,
+2
View File
@@ -17,6 +17,8 @@ int gunyah_rm_notifier_register(struct gunyah_rm *rm,
struct notifier_block *nb);
int gunyah_rm_notifier_unregister(struct gunyah_rm *rm,
struct notifier_block *nb);
struct device *gunyah_rm_get(struct gunyah_rm *rm);
void gunyah_rm_put(struct gunyah_rm *rm);
int gunyah_rm_call(struct gunyah_rm *rsc_mgr, u32 message_id,
+94
View File
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define pr_fmt(fmt) "gunyah_vm_mgr: " fmt
#include <linux/anon_inodes.h>
#include <linux/file.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <uapi/linux/gunyah.h>
#include "rsc_mgr.h"
#include "vm_mgr.h"
static __must_check struct gunyah_vm *gunyah_vm_alloc(struct gunyah_rm *rm)
{
struct gunyah_vm *ghvm;
ghvm = kzalloc(sizeof(*ghvm), GFP_KERNEL);
if (!ghvm)
return ERR_PTR(-ENOMEM);
ghvm->parent = gunyah_rm_get(rm);
ghvm->rm = rm;
return ghvm;
}
static int gunyah_vm_release(struct inode *inode, struct file *filp)
{
struct gunyah_vm *ghvm = filp->private_data;
gunyah_rm_put(ghvm->rm);
kfree(ghvm);
return 0;
}
static const struct file_operations gunyah_vm_fops = {
.owner = THIS_MODULE,
.release = gunyah_vm_release,
.llseek = noop_llseek,
};
static long gunyah_dev_ioctl_create_vm(struct gunyah_rm *rm, 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(rm);
if (IS_ERR(ghvm))
return PTR_ERR(ghvm);
fd = get_unused_fd_flags(O_CLOEXEC);
if (fd < 0) {
err = fd;
goto err_destroy_vm;
}
file = anon_inode_getfile("gunyah-vm", &gunyah_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:
gunyah_rm_put(ghvm->rm);
kfree(ghvm);
return err;
}
long gunyah_dev_vm_mgr_ioctl(struct gunyah_rm *rm, unsigned int cmd,
unsigned long arg)
{
switch (cmd) {
case GUNYAH_CREATE_VM:
return gunyah_dev_ioctl_create_vm(rm, arg);
default:
return -ENOTTY;
}
}
+28
View File
@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _GUNYAH_VM_MGR_PRIV_H
#define _GUNYAH_VM_MGR_PRIV_H
#include <linux/device.h>
#include <uapi/linux/gunyah.h>
#include "rsc_mgr.h"
long gunyah_dev_vm_mgr_ioctl(struct gunyah_rm *rm, unsigned int cmd,
unsigned long arg);
/**
* struct gunyah_vm - Main representation of a Gunyah Virtual machine
* @rm: Pointer to the resource manager struct to make RM calls
* @parent: For logging
*/
struct gunyah_vm {
struct gunyah_rm *rm;
struct device *parent;
};
#endif
+23
View File
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _UAPI_LINUX_GUNYAH_H
#define _UAPI_LINUX_GUNYAH_H
/*
* Userspace interface for /dev/gunyah - gunyah based virtual machine
*/
#include <linux/types.h>
#include <linux/ioctl.h>
#define GUNYAH_IOCTL_TYPE 'G'
/*
* ioctls for /dev/gunyah fds:
*/
#define GUNYAH_CREATE_VM _IO(GUNYAH_IOCTL_TYPE, 0x0) /* Returns a Gunyah VM fd */
#endif