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;
|
u32 err_code;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/* VM specific properties to be cached */
|
||||||
|
struct hh_vm_property {
|
||||||
|
hh_vmid_t vmid;
|
||||||
|
};
|
||||||
|
|
||||||
/* RPC Header versions */
|
/* RPC Header versions */
|
||||||
#define HH_RM_RPC_HDR_VERSION_ONE 0x1
|
#define HH_RM_RPC_HDR_VERSION_ONE 0x1
|
||||||
|
|
||||||
@ -87,6 +92,26 @@ struct hh_rm_rpc_reply_hdr {
|
|||||||
/* End Call type Message IDs */
|
/* End Call type Message IDs */
|
||||||
/* End RPC 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 */
|
/* Message ID headers */
|
||||||
/* Call: VM_GET_HYP_RESOURCES */
|
/* Call: VM_GET_HYP_RESOURCES */
|
||||||
#define HH_RM_RES_TYPE_DB_TX 0
|
#define HH_RM_RES_TYPE_DB_TX 0
|
||||||
@ -129,6 +154,8 @@ struct hh_vm_irq_accept_resp_payload {
|
|||||||
/* End Message ID headers */
|
/* End Message ID headers */
|
||||||
|
|
||||||
/* Common function declerations */
|
/* 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 *hh_rm_call(hh_rm_msgid_t message_id,
|
||||||
void *req_buff, size_t req_buff_size,
|
void *req_buff, size_t req_buff_size,
|
||||||
size_t *resp_buff_size, int *reply_err_code);
|
size_t *resp_buff_size, int *reply_err_code);
|
||||||
|
@ -12,6 +12,65 @@
|
|||||||
|
|
||||||
#include "hh_rm_drv_private.h"
|
#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
|
* 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
|
* @vmid: vmid whose info is needed. Pass 0 for self
|
||||||
@ -125,3 +184,97 @@ out:
|
|||||||
kfree(resp_payload);
|
kfree(resp_payload);
|
||||||
return ret;
|
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_capid_t;
|
||||||
typedef u64 hh_dbl_flags_t;
|
typedef u64 hh_dbl_flags_t;
|
||||||
|
|
||||||
|
enum hh_vm_names {
|
||||||
|
HH_PRIMARY_VM,
|
||||||
|
HH_TRUSTED_VM,
|
||||||
|
HH_VM_MAX
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#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_unregister_notifier(struct notifier_block *nb);
|
||||||
int hh_rm_vm_irq_accept(hh_virq_handle_t virq_handle, int virq);
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user