ANDROID: virt: gunyah: Sync with latest documentation and sample

Sync with latest documentation and sample code from v14 of Gunyah
patches:

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

Bug: 287037804
Change-Id: I8893922e6b8096fdd5dff1b22ebce96e72cdb7c3
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
This commit is contained in:
Elliot Berman 2023-06-12 09:49:48 -07:00 committed by Carlos Llamas
parent 60662882b7
commit 705a9b5feb
6 changed files with 69 additions and 45 deletions

View File

@ -136,7 +136,7 @@ Code Seq# Include File Comments
'F' DD video/sstfb.h conflict! 'F' DD video/sstfb.h conflict!
'G' 00-3F drivers/misc/sgi-gru/grulib.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 xen/gntalloc.h, xen/gntdev.h conflict!
'G' 00-0f linux/gunyah.h conflict! 'G' 00-0F linux/gunyah.h conflict!
'H' 00-7F linux/hiddev.h conflict! 'H' 00-7F linux/hiddev.h conflict!
'H' 00-0F linux/hidraw.h conflict! 'H' 00-0F linux/hidraw.h conflict!
'H' 01 linux/mei.h conflict! 'H' 01 linux/mei.h conflict!

View File

@ -7,14 +7,12 @@ Virtual Machine Manager
The Gunyah Virtual Machine Manager is a Linux driver to support launching The Gunyah Virtual Machine Manager is a Linux driver to support launching
virtual machines using Gunyah. virtual machines using Gunyah.
Except for some basic information about the location of initial binaries, Configuration of a Gunyah virtual machine is done via a devicetree. When the VM
most of the configuration about a Gunyah virtual machine is described in the is launched, memory is provided by the host VM which contains the devictree.
VM's devicetree. The devicetree is generated by userspace. Interacting with the Gunyah reads the devicetree to configure the memory map and create resources
virtual machine is still done via the kernel and VM configuration requires some such as vCPUs for the VM. Memory can be shared with the VM with
of the corresponding functionality to be set up in the kernel. For instance, `GH_VM_SET_USER_MEM_REGION`_. Userspace can interact with the resources in Linux
sharing userspace memory with a VM is done via the `GH_VM_SET_USER_MEM_REGION`_ by adding "functions" to the VM.
ioctl. The VM itself is configured to use the memory region via the
devicetree.
Gunyah Functions Gunyah Functions
================ ================
@ -56,6 +54,9 @@ GH_CREATE_VM
~~~~~~~~~~~~ ~~~~~~~~~~~~
Creates a Gunyah VM. The argument is reserved for future use and must be 0. Creates a Gunyah VM. The argument is reserved for future use and must be 0.
A successful call will return a Gunyah VM file descriptor. See
`Gunyah VM API Descriptions`_ for list of IOCTLs that can be made on this file
file descriptor.
Gunyah VM API Descriptions Gunyah VM API Descriptions
-------------------------- --------------------------
@ -70,8 +71,8 @@ unique per virtual machine.
While VMM is guest-agnostic and allows runtime addition of memory regions, While VMM is guest-agnostic and allows runtime addition of memory regions,
Linux guest virtual machines do not support accepting memory regions at runtime. 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 must Thus, for Linux guests, memory regions should be provided before starting the VM
be configured to accept these at boot-up. and the VM must be configured via the devicetree to accept these at boot-up.
The guest physical address is used by Linux kernel to check that the requested 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 user regions do not overlap and to help find the corresponding memory region
@ -87,7 +88,7 @@ GH_VM_SET_DTB_CONFIG
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
This ioctl sets the location of the VM's devicetree blob and is used by Gunyah This ioctl sets the location of the VM's devicetree blob and is used by Gunyah
Resource Manager to allocate resources. The guest physical memory should be part Resource Manager to allocate resources. The guest physical memory must be part
of the primary memory parcel provided to the VM prior to GH_VM_START. of the primary memory parcel provided to the VM prior to GH_VM_START.
.. kernel-doc:: include/uapi/linux/gunyah.h .. kernel-doc:: include/uapi/linux/gunyah.h
@ -104,7 +105,7 @@ GH_VM_ADD_FUNCTION
This ioctl registers a Gunyah VM function with the VM manager. The VM function This ioctl registers a Gunyah VM function with the VM manager. The VM function
is described with a &struct gh_fn_desc.type and some arguments for that type. is described with a &struct gh_fn_desc.type and some arguments for that type.
Typically, the function is added before the VM starts, but the function doesn't Typically, the function is added before the VM starts, but the function doesn't
"operate" until the VM starts with `GH_VM_START`_. For example, vCPU ioclts will "operate" until the VM starts with `GH_VM_START`_. For example, vCPU ioctls will
all return an error until the VM starts because the vCPUs don't exist until the all return an error until the VM starts because the vCPUs don't exist until the
VM is started. This allows the VMM to set up all the kernel functions needed for VM is started. This allows the VMM to set up all the kernel functions needed for
the VM *before* the VM starts. the VM *before* the VM starts.

View File

@ -123,7 +123,7 @@ struct gh_rm_connection {
/** /**
* struct gh_rm - private data for communicating w/Gunyah resource manager * struct gh_rm - private data for communicating w/Gunyah resource manager
* @dev: pointer to device * @dev: pointer to RM platform device
* @tx_ghrsc: message queue resource to TX to RM * @tx_ghrsc: message queue resource to TX to RM
* @rx_ghrsc: message queue resource to RX from RM * @rx_ghrsc: message queue resource to RX from RM
* @msgq: mailbox instance of TX/RX resources above * @msgq: mailbox instance of TX/RX resources above

View File

@ -617,7 +617,7 @@ static int gh_vm_ensure_started(struct gh_vm *ghvm)
if (ret) if (ret)
return ret; return ret;
/** gh_vm_start() is guaranteed to bring status out of /** gh_vm_start() is guaranteed to bring status out of
* GH_RM_VM_STATUS_LOAD, thus inifitely recursive call is not * GH_RM_VM_STATUS_LOAD, thus infinitely recursive call is not
* possible * possible
*/ */
return gh_vm_ensure_started(ghvm); return gh_vm_ensure_started(ghvm);

View File

@ -21,6 +21,16 @@ int __must_check gh_vm_get(struct gh_vm *ghvm);
void gh_vm_put(struct gh_vm *ghvm); void gh_vm_put(struct gh_vm *ghvm);
struct gh_vm_function_instance; struct gh_vm_function_instance;
/**
* struct gh_vm_function - Represents a function type
* @type: value from &enum gh_fn_type
* @name: friendly name for debug purposes
* @mod: owner of the function type
* @bind: Called when a new function of this type has been allocated.
* @unbind: Called when the function instance is being destroyed.
* @compare: Compare function instance @f's argument to the provided arg.
* Return true if they are equivalent. Used on GH_VM_REMOVE_FUNCTION.
*/
struct gh_vm_function { struct gh_vm_function {
u32 type; u32 type;
const char *name; const char *name;
@ -84,9 +94,26 @@ void gh_vm_function_unregister(struct gh_vm_function *f);
module_gh_vm_function(_name); \ module_gh_vm_function(_name); \
MODULE_ALIAS_GH_VM_FUNCTION(_type, _idx) MODULE_ALIAS_GH_VM_FUNCTION(_type, _idx)
/**
* struct gh_vm_resource_ticket - Represents a ticket to reserve exclusive access to VM resource(s)
* @vm_list: for @gh_vm->resource_tickets
* @resources: List of resource(s) associated with this ticket(members are from @gh_resource->list)
* @resource_type: Type of resource this ticket reserves
* @label: Label of the resource from resource manager this ticket reserves.
* @owner: owner of the ticket
* @populate: callback provided by the ticket owner and called when a resource is found that
* matches @resource_type and @label. Note that this callback could be called
* multiple times if userspace created mutliple resources with the same type/label.
* This callback may also have significant delay after gh_vm_add_resource_ticket()
* since gh_vm_add_resource_ticket() could be called before the VM starts.
* @unpopulate: callback provided by the ticket owner and called when the ticket owner should no
* no longer use the resource provided in the argument. When unpopulate() returns,
* the ticket owner should not be able to use the resource any more as the resource
* might being freed.
*/
struct gh_vm_resource_ticket { struct gh_vm_resource_ticket {
struct list_head vm_list; /* for gh_vm's resource tickets list */ struct list_head vm_list;
struct list_head resources; /* resources associated with this ticket */ struct list_head resources;
enum gh_resource_type resource_type; enum gh_resource_type resource_type;
u32 label; u32 label;

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -21,6 +21,11 @@
#include <linux/gunyah.h> #include <linux/gunyah.h>
#define DEFAULT_GUEST_BASE 0x80000000
#define DEFAULT_GUEST_SIZE 0x6400000 /* 100 MiB */
#define DEFAULT_DTB_OFFSET 0x45f0000 /* 70MiB - 64 KiB */
#define DEFAULT_RAMDISK_OFFSET 0x4600000 /* 70MiB */
struct vm_config { struct vm_config {
int image_fd; int image_fd;
int dtb_fd; int dtb_fd;
@ -29,7 +34,6 @@ struct vm_config {
uint64_t guest_base; uint64_t guest_base;
uint64_t guest_size; uint64_t guest_size;
uint64_t image_offset;
off_t image_size; off_t image_size;
uint64_t dtb_offset; uint64_t dtb_offset;
off_t dtb_size; off_t dtb_size;
@ -44,7 +48,6 @@ static struct option options[] = {
{ "ramdisk", optional_argument, NULL, 'r' }, { "ramdisk", optional_argument, NULL, 'r' },
{ "base", optional_argument, NULL, 'B' }, { "base", optional_argument, NULL, 'B' },
{ "size", optional_argument, NULL, 'S' }, { "size", optional_argument, NULL, 'S' },
{ "image_offset", optional_argument, NULL, 'I' },
{ "dtb_offset", optional_argument, NULL, 'D' }, { "dtb_offset", optional_argument, NULL, 'D' },
{ "ramdisk_offset", optional_argument, NULL, 'R' }, { "ramdisk_offset", optional_argument, NULL, 'R' },
{ } { }
@ -58,12 +61,12 @@ static void print_help(char *cmd)
" --image, -i <image> VM image file to load (e.g. a kernel Image) [Required]\n" " --image, -i <image> VM image file to load (e.g. a kernel Image) [Required]\n"
" --dtb, -d <dtb> Devicetree file to load [Required]\n" " --dtb, -d <dtb> Devicetree file to load [Required]\n"
" --ramdisk, -r <ramdisk> Ramdisk file to load\n" " --ramdisk, -r <ramdisk> Ramdisk file to load\n"
" --base, -B <address> Set the base address of guest's memory [Default: 0x80000000]\n" " --base, -B <address> Set the base address of guest's memory [Default: 0x%08x]\n"
" --size, -S <number> The number of bytes large to make the guest's memory [Default: 0x6400000 (100 MB)]\n" " --size, -S <number> The number of bytes large to make the guest's memory [Default: 0x%08x]\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: 0x%08x]\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: 0x%08x]\n"
" --ramdisk_offset, -R <number> Offset into guest memory to load a ramdisk [Default: 0x4600000]\n" , cmd, DEFAULT_GUEST_BASE, DEFAULT_GUEST_SIZE,
, cmd); DEFAULT_DTB_OFFSET, DEFAULT_RAMDISK_OFFSET);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@ -74,18 +77,19 @@ int main(int argc, char **argv)
char *guest_mem; char *guest_mem;
struct vm_config config = { struct vm_config config = {
/* Defaults good enough to boot static kernel and a basic ramdisk */ /* Defaults good enough to boot static kernel and a basic ramdisk */
.image_fd = -1,
.dtb_fd = -1,
.ramdisk_fd = -1, .ramdisk_fd = -1,
.guest_base = 0x80000000, .guest_base = DEFAULT_GUEST_BASE,
.guest_size = 0x6400000, /* 100 MB */ .guest_size = DEFAULT_GUEST_SIZE,
.image_offset = 0, .dtb_offset = DEFAULT_DTB_OFFSET,
.dtb_offset = 0x45f0000, .ramdisk_offset = DEFAULT_RAMDISK_OFFSET,
.ramdisk_offset = 0x4600000, /* put at +70MB (30MB for ramdisk) */
}; };
struct stat st; struct stat st;
int opt, optidx, ret = 0; int opt, optidx, ret = 0;
long l; long l;
while ((opt = getopt_long(argc, argv, "hi:d:r:B:S:I:D:R:c:", options, &optidx)) != -1) { while ((opt = getopt_long(argc, argv, "hi:d:r:B:S:D:R:c:", options, &optidx)) != -1) {
switch (opt) { switch (opt) {
case 'i': case 'i':
config.image_fd = open(optarg, O_RDONLY | O_CLOEXEC); config.image_fd = open(optarg, O_RDONLY | O_CLOEXEC);
@ -139,14 +143,6 @@ int main(int argc, char **argv)
} }
config.guest_size = l; config.guest_size = l;
break; 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': case 'D':
l = strtol(optarg, NULL, 0); l = strtol(optarg, NULL, 0);
if (l == LONG_MIN) { if (l == LONG_MIN) {
@ -172,13 +168,13 @@ int main(int argc, char **argv)
} }
} }
if (!config.image_fd || !config.dtb_fd) { if (config.image_fd == -1 || config.dtb_fd == -1) {
print_help(argv[0]); print_help(argv[0]);
return -1; return -1;
} }
if (config.image_offset + config.image_size > config.guest_size) { if (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"); fprintf(stderr, "Image size puts it outside guest memory. Make image smaller or increase guest memory size.\n");
return -1; return -1;
} }
@ -222,7 +218,7 @@ int main(int argc, char **argv)
return -1; return -1;
} }
if (read(config.image_fd, guest_mem + config.image_offset, config.image_size) < 0) { if (read(config.image_fd, guest_mem, config.image_size) < 0) {
perror("Failed to read image into guest memory"); perror("Failed to read image into guest memory");
return -1; return -1;
} }
@ -264,7 +260,7 @@ int main(int argc, char **argv)
} }
while (1) while (1)
sleep(10); pause();
return 0; return 0;
} }