From ad9c03a8b039d11daec66a5d155b8ed6133148bc Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 27 Jan 2020 16:58:27 -0800 Subject: [PATCH] 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 --- drivers/virt/haven/hh_rm_drv_private.h | 21 ++++ drivers/virt/haven/hh_rm_iface.c | 159 +++++++++++++++++++++++++ include/linux/haven/hh_rm_drv.h | 6 + 3 files changed, 186 insertions(+) diff --git a/drivers/virt/haven/hh_rm_drv_private.h b/drivers/virt/haven/hh_rm_drv_private.h index 0a1a39d85ab2..21c3d10e2a45 100644 --- a/drivers/virt/haven/hh_rm_drv_private.h +++ b/drivers/virt/haven/hh_rm_drv_private.h @@ -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 diff --git a/drivers/virt/haven/hh_rm_iface.c b/drivers/virt/haven/hh_rm_iface.c index 23f54ccf86aa..9f72464fa40c 100644 --- a/drivers/virt/haven/hh_rm_iface.c +++ b/drivers/virt/haven/hh_rm_iface.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -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); diff --git a/include/linux/haven/hh_rm_drv.h b/include/linux/haven/hh_rm_drv.h index 6dacbb758dd0..0f9368231a92 100644 --- a/include/linux/haven/hh_rm_drv.h +++ b/include/linux/haven/hh_rm_drv.h @@ -125,4 +125,10 @@ 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); +/* Client APIs for VM Services */ +int hh_rm_console_open(hh_vmid_t vmid); +int hh_rm_console_close(hh_vmid_t vmid); +int hh_rm_console_write(hh_vmid_t vmid, const char *buf, size_t size); +int hh_rm_console_flush(hh_vmid_t vmid); + #endif