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:
parent
f57d0c27d3
commit
b1c2a1490d
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user