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:
committed by
Treehugger Robot
parent
4c11c572f4
commit
b387fa408e
@@ -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,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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user