haven: rm: Add VM Services - Console APIs

Add console APIs to emulate virtual console mechanism between SVM and
PVM to get the SVM messages to PVM for debug purpose.

Change-Id: I24ec2c427460195c83f5975de70f4ec5c4f2f763
Signed-off-by: Elliot Berman <[email protected]>
This commit is contained in:
Elliot Berman 2020-01-27 16:58:27 -08:00
commit ad9c03a8b0
3 changed files with 186 additions and 0 deletions

View file

@ -112,6 +112,27 @@ struct hh_vm_start_resp_payload {
u32 response;
} __packed;
/* Call: CONSOLE_OPEN, CONSOLE_CLOSE, CONSOLE_FLUSH */
struct hh_vm_console_common_req_payload {
u32 vmid;
u32 reserved0;
} __packed;
struct hh_vm_console_common_resp_payload {
u32 response;
} __packed;
/* Call: CONSOLE_WRITE */
struct hh_vm_console_write_req_payload {
u32 vmid;
u32 num_bytes;
u8 data[0];
} __packed;
struct hh_vm_console_write_resp_payload {
u32 response;
} __packed;
/* Message ID headers */
/* Call: VM_GET_HYP_RESOURCES */
#define HH_RM_RES_TYPE_DB_TX 0

View file

@ -5,6 +5,7 @@
*/
#include <linux/slab.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/haven/hh_msgq.h>
@ -407,3 +408,161 @@ int hh_rm_vm_start(int vmid)
return resp_payload->response;
}
EXPORT_SYMBOL(hh_rm_vm_start);
/**
* hh_rm_console_open: Open a console with a VM
* @vmid: The vmid of the vm to be started.
*/
int hh_rm_console_open(hh_vmid_t vmid)
{
struct hh_vm_console_common_resp_payload *resp_payload;
struct hh_vm_console_common_req_payload req_payload = {0};
size_t resp_payload_size;
int err = 0, reply_err_code = 0;
req_payload.vmid = vmid;
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_OPEN,
&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: CONSOLE_OPEN failed with err: %d\n",
__func__, err);
goto out;
}
if (resp_payload_size != sizeof(*resp_payload)) {
pr_err("%s: Invalid size received for CONSOLE_OPEN: %u\n",
__func__, resp_payload_size);
err = -EINVAL;
}
err = err ? : resp_payload->response;
kfree(resp_payload);
out:
return err;
}
EXPORT_SYMBOL(hh_rm_console_open);
/**
* hh_rm_console_close: Close a console with a VM
* @vmid: The vmid of the vm whose console to close.
*/
int hh_rm_console_close(hh_vmid_t vmid)
{
struct hh_vm_console_common_resp_payload *resp_payload;
struct hh_vm_console_common_req_payload req_payload = {0};
size_t resp_payload_size;
int err = 0, reply_err_code = 0;
req_payload.vmid = vmid;
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_CLOSE,
&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: CONSOLE_CLOSE failed with err: %d\n",
__func__, err);
goto out;
}
if (resp_payload_size != sizeof(*resp_payload)) {
pr_err("%s: Invalid size received for CONSOLE_CLOSE: %u\n",
__func__, resp_payload_size);
err = -EINVAL;
}
err = err ? : resp_payload->response;
kfree(resp_payload);
out:
return err;
}
EXPORT_SYMBOL(hh_rm_console_close);
/**
* hh_rm_console_write: Write to a VM's console
* @vmid: The vmid of the vm whose console to write to.
* @buf: Buffer to write to the VM's console
* @size: Size of the buffer
*/
int hh_rm_console_write(hh_vmid_t vmid, const char *buf, size_t size)
{
struct hh_vm_console_write_resp_payload *resp_payload;
struct hh_vm_console_write_req_payload *req_payload;
size_t resp_payload_size;
int err = 0, reply_err_code = 0;
size_t req_payload_size = sizeof(*req_payload) + size;
if (size < 1 || size > U32_MAX)
return -EINVAL;
req_payload = kzalloc(req_payload_size, GFP_KERNEL);
if (!req_payload)
return -ENOMEM;
req_payload->vmid = vmid;
req_payload->num_bytes = size;
memcpy(req_payload->data, buf, size);
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_WRITE,
req_payload, req_payload_size,
&resp_payload_size, &reply_err_code);
if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
err = PTR_ERR(resp_payload);
pr_err("%s: CONSOLE_WRITE failed with err: %d\n",
__func__, err);
goto out;
}
if (resp_payload_size != sizeof(*resp_payload)) {
pr_err("%s: Invalid size received for CONSOLE_WRITE: %u\n",
__func__, resp_payload_size);
err = -EINVAL;
}
err = err ? : resp_payload->response;
kfree(resp_payload);
out:
kfree(req_payload);
return err;
}
EXPORT_SYMBOL(hh_rm_console_write);
/**
* hh_rm_console_flush: Flush a console with a VM
* @vmid: The vmid of the vm whose console to flush
*/
int hh_rm_console_flush(hh_vmid_t vmid)
{
struct hh_vm_console_common_resp_payload *resp_payload;
struct hh_vm_console_common_req_payload req_payload = {0};
size_t resp_payload_size;
int err = 0, reply_err_code = 0;
req_payload.vmid = vmid;
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_FLUSH,
&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: CONSOLE_FLUSH failed with err: %d\n",
__func__, err);
goto out;
}
if (resp_payload_size != sizeof(*resp_payload)) {
pr_err("%s: Invalid size received for CONSOLE_FLUSH: %u\n",
__func__, resp_payload_size);
err = -EINVAL;
}
err = err ? : resp_payload->response;
kfree(resp_payload);
out:
return err;
}
EXPORT_SYMBOL(hh_rm_console_flush);