haven: Add VM management support for clients

Add VM management APIs so that clients can start VMs and allocate/get
vmids associated with VMs.

Change-Id: I7a9138a9479665f6c09aae98390a30c23011b3b1
Signed-off-by: Prakruthi Deepak Heragu <pheragu@codeaurora.org>
Signed-off-by: Elliot Berman <eberman@codeaurora.org>
This commit is contained in:
Prakruthi Deepak Heragu 2020-01-14 14:03:25 -08:00 committed by Elliot Berman
parent f57d0c27d3
commit b1c2a1490d
4 changed files with 192 additions and 0 deletions

View File

@ -27,6 +27,11 @@ struct hh_rm_rpc_reply_hdr {
u32 err_code;
} __packed;
/* VM specific properties to be cached */
struct hh_vm_property {
hh_vmid_t vmid;
};
/* RPC Header versions */
#define HH_RM_RPC_HDR_VERSION_ONE 0x1
@ -87,6 +92,26 @@ struct hh_rm_rpc_reply_hdr {
/* End Call type Message IDs */
/* End RPC Message IDs */
/* Call: VM_ALLOCATE */
struct hh_vm_allocate_req_payload {
u8 vmid:4;
u8 reserved:4;
} __packed;
struct hh_vm_allocate_resp_payload {
u32 vmid;
} __packed;
/* Call: VM_START */
struct hh_vm_start_req_payload {
u8 vmid:4;
u8 reserved:4;
} __packed;
struct hh_vm_start_resp_payload {
u32 response;
} __packed;
/* Message ID headers */
/* Call: VM_GET_HYP_RESOURCES */
#define HH_RM_RES_TYPE_DB_TX 0
@ -129,6 +154,8 @@ struct hh_vm_irq_accept_resp_payload {
/* End Message ID headers */
/* Common function declerations */
int hh_update_vm_prop_table(enum hh_vm_names vm_name,
struct hh_vm_property *vm_prop);
void *hh_rm_call(hh_rm_msgid_t message_id,
void *req_buff, size_t req_buff_size,
size_t *resp_buff_size, int *reply_err_code);

View File

@ -12,6 +12,65 @@
#include "hh_rm_drv_private.h"
static struct hh_vm_property hh_vm_table[HH_VM_MAX];
int hh_update_vm_prop_table(enum hh_vm_names vm_name,
struct hh_vm_property *vm_prop)
{
if (vm_prop->vmid <= 0)
return -EINVAL;
hh_vm_table[vm_name].vmid = vm_prop->vmid;
return 0;
}
/**
* hh_rm_get_vmid: Translate VM name to vmid
* @vm_name: VM name to lookup
* @vmid: out pointer to store found vmid if VM is ofund
*
* If no VM is known to RM with the supplied name, -EINVAL is returned.
* 0 otherwise.
*/
int hh_rm_get_vmid(enum hh_vm_names vm_name, hh_vmid_t *vmid)
{
hh_vmid_t _vmid = hh_vm_table[vm_name].vmid;
if (!_vmid) {
pr_err("%s: No vmid associated with the vm\n", __func__);
return -EINVAL;
}
if (vmid)
*vmid = _vmid;
return 0;
}
EXPORT_SYMBOL(hh_rm_get_vmid);
/**
* hh_rm_get_vm_name: Translate vmid to vm name
* @vmid: vmid to lookup
* @vm_name: out pointer to store found VM name if vmid is found
*
* If no VM is known to RM with the supplied VMID, -EINVAL is returned.
* 0 otherwise.
*/
int hh_rm_get_vm_name(hh_vmid_t vmid, enum hh_vm_names *vm_name)
{
enum hh_vm_names i;
for (i = 0; i < HH_VM_MAX; i++)
if (hh_vm_table[i].vmid == vmid) {
if (vm_name)
*vm_name = i;
return 0;
}
return -EINVAL;
}
EXPORT_SYMBOL(hh_rm_get_vm_name);
/**
* hh_rm_vm_get_hyp_res: Get info about a series of resources for this VM
* @vmid: vmid whose info is needed. Pass 0 for self
@ -125,3 +184,97 @@ out:
kfree(resp_payload);
return ret;
}
/**
* hh_rm_vm_alloc_vmid: Return a vmid associated with the vm loaded into
* memory. This call should be called only during
initialization.
* @vm_name: The enum value of the vm that has been loaded.
*
* The function encodes the error codes via ERR_PTR. Hence, the caller is
* responsible to check it with IS_ERR_OR_NULL().
*/
int hh_rm_vm_alloc_vmid(enum hh_vm_names vm_name)
{
struct hh_vm_allocate_resp_payload *resp_payload;
struct hh_vm_allocate_req_payload req_payload;
size_t resp_payload_size;
struct hh_vm_property vm_prop;
int err, reply_err_code;
/* Look up for the vm_name<->vmid pair if already present.
* If so, return.
*/
if (!hh_vm_table[vm_name].vmid) {
pr_err("%s: VM_ALLOCATE already called for this VM\n",
__func__);
return -EINVAL;
}
req_payload.vmid = 0;
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_ALLOCATE,
&req_payload, sizeof(req_payload),
&resp_payload_size, &reply_err_code);
if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
err = PTR_ERR(resp_payload);
pr_err("%s: VM_ALLOCATE failed with err: %d\n",
__func__, err);
return err;
}
if (resp_payload_size != sizeof(*resp_payload)) {
pr_err("%s: Invalid size received for VM_ALLOCATE: %u\n",
__func__, resp_payload_size);
kfree(resp_payload);
return -EINVAL;
}
vm_prop.vmid = resp_payload->vmid;
err = hh_update_vm_prop_table(vm_name, &vm_prop);
if (err) {
pr_err("%s: Invalid vmid sent for updating table: %u\n",
__func__, resp_payload_size);
return -EINVAL;
}
return resp_payload->vmid;
}
EXPORT_SYMBOL(hh_rm_vm_alloc_vmid);
/**
* hh_rm_vm_start: Send a request to Resource Manager VM to start a VM.
* @vmid: The vmid of the vm to be started.
*
* The function encodes the error codes via ERR_PTR. Hence, the caller is
* responsible to check it with IS_ERR_OR_NULL().
*/
int hh_rm_vm_start(int vmid)
{
struct hh_vm_start_resp_payload *resp_payload;
struct hh_vm_start_req_payload req_payload;
size_t resp_payload_size;
int err, reply_err_code;
req_payload.vmid = (hh_vmid_t) vmid;
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_START,
&req_payload, sizeof(req_payload),
&resp_payload_size, &reply_err_code);
if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
err = PTR_ERR(resp_payload);
pr_err("%s: VM_ALLOCATE failed with err: %d\n",
__func__, err);
return err;
}
if (resp_payload_size != sizeof(*resp_payload)) {
pr_err("%s: Invalid size received for VM_IRQ_ACCEPT: %u\n",
__func__, resp_payload_size);
kfree(resp_payload);
return -EINVAL;
}
return resp_payload->response;
}
EXPORT_SYMBOL(hh_rm_vm_start);

View File

@ -15,4 +15,10 @@ typedef u32 hh_label_t;
typedef u64 hh_capid_t;
typedef u64 hh_dbl_flags_t;
enum hh_vm_names {
HH_PRIMARY_VM,
HH_TRUSTED_VM,
HH_VM_MAX
};
#endif

View File

@ -116,4 +116,10 @@ int hh_rm_register_notifier(struct notifier_block *nb);
int hh_rm_unregister_notifier(struct notifier_block *nb);
int hh_rm_vm_irq_accept(hh_virq_handle_t virq_handle, int virq);
/* Client APIs for VM management */
int hh_rm_vm_alloc_vmid(enum hh_vm_names vm_name);
int hh_rm_get_vmid(enum hh_vm_names vm_name, hh_vmid_t *vmid);
int hh_rm_get_vm_name(hh_vmid_t vmid, enum hh_vm_names *vm_name);
int hh_rm_vm_start(int vmid);
#endif