diff --git a/misc/services/life_mngr/command.c b/misc/services/life_mngr/command.c index 282ee51b5..6625655e1 100644 --- a/misc/services/life_mngr/command.c +++ b/misc/services/life_mngr/command.c @@ -33,6 +33,9 @@ GEN_CMD_OBJ(REQ_USER_VM_SHUTDOWN, REQ_USER_VM_SHUTDOWN_ID), \ GEN_CMD_OBJ(USER_VM_SHUTDOWN, USER_VM_SHUTDOWN_ID),\ GEN_CMD_OBJ(ACK_USER_VM_SHUTDOWN, ACK_USER_VM_SHUTDOWN_ID),\ + GEN_CMD_OBJ(REQ_USER_VM_REBOOT, REQ_USER_VM_REBOOT_ID), \ + GEN_CMD_OBJ(USER_VM_REBOOT, USER_VM_REBOOT_ID),\ + GEN_CMD_OBJ(ACK_USER_VM_REBOOT, ACK_USER_VM_REBOOT_ID),\ struct command dm_command_list[CMD_END] = {CMD_OBJS}; diff --git a/misc/services/life_mngr/command.h b/misc/services/life_mngr/command.h index d3b6a7a0e..6984e466e 100644 --- a/misc/services/life_mngr/command.h +++ b/misc/services/life_mngr/command.h @@ -17,9 +17,13 @@ #define ACK_TIMEOUT "ack_timeout" #define REQ_USER_VM_SHUTDOWN "req_user_vm_shutdown" #define USER_VM_SHUTDOWN "user_vm_shutdown" +#define REQ_USER_VM_REBOOT "req_user_vm_reboot" +#define USER_VM_REBOOT "user_vm_reboot" #define ACK_REQ_USER_VM_SHUTDOWN "ack_req_user_vm_shutdown" #define ACK_USER_VM_SHUTDOWN "ack_user_vm_shutdown" +#define ACK_REQ_USER_VM_REBOOT "ack_req_user_vm_reboot" +#define ACK_USER_VM_REBOOT "ack_user_vm_reboot" #define FAIL_CONNECT "fail_connect" #define USER_VM_DISCONNECT "user_vm_disconnect" #define S5_REJECTED "system shutdown request is rejected" @@ -27,6 +31,7 @@ #define SYNC_LEN (sizeof(SYNC_CMD)) #define POWEROFF "poweroff" +#define REBOOT "reboot" #define CMD_NAME_MAX 32U @@ -41,6 +46,9 @@ enum command_id { REQ_USER_VM_SHUTDOWN_ID, USER_VM_SHUTDOWN_ID, ACK_USER_VM_SHUTDOWN_ID, + REQ_USER_VM_REBOOT_ID, + USER_VM_REBOOT_ID, + ACK_USER_VM_REBOOT_ID, CMD_END, }; diff --git a/misc/services/life_mngr/command_handler.c b/misc/services/life_mngr/command_handler.c index fdcb8ed24..fc585098e 100644 --- a/misc/services/life_mngr/command_handler.c +++ b/misc/services/life_mngr/command_handler.c @@ -24,6 +24,12 @@ bool get_system_shutdown_flag(void) { return system_shutdown_flag; } + +bool user_vm_reboot_flag; +bool get_user_vm_reboot_flag(void) +{ + return user_vm_reboot_flag; +} /** * @brief check whether all acrn-dm instance have been exit or not * @@ -103,12 +109,12 @@ int socket_req_shutdown_service_vm_handler(void *arg, int fd) ret = send_socket_ack(arg, fd, ACK_REQ_SYS_SHUTDOWN); if (ret < 0) return 0; - enable_all_uart_channel_dev_resend(channel, POWEROFF_CMD, VM_SHUTDOWN_RETRY_TIMES); + start_all_uart_channel_dev_resend(channel, POWEROFF_CMD, VM_SHUTDOWN_RETRY_TIMES); notify_all_connected_uart_channel_dev(channel, POWEROFF_CMD); start_system_shutdown(); return 0; } -int socket_req_user_vm_shutdown_handler(void *arg, int fd) +static int req_user_vm_shutdown_reboot(void *arg, int fd, char *msg, char *ack_msg) { int ret; struct channel_dev *c_dev = NULL; @@ -127,18 +133,26 @@ int socket_req_user_vm_shutdown_handler(void *arg, int fd) client->name); return 0; } - ret = send_socket_ack(arg, fd, ACK_REQ_USER_VM_SHUTDOWN); + ret = send_socket_ack(arg, fd, ack_msg); if (ret < 0) { LOG_WRITE("Failed to send ACK by socket\n"); return 0; } - LOG_PRINTF("Foward guest shutdown request to user VM (%s) by UART\n", c_dev->name); - enable_uart_channel_dev_resend(c_dev, USER_VM_SHUTDOWN, MIN_RESEND_TIME); - ret = send_message_by_uart(c_dev->uart_device, USER_VM_SHUTDOWN, strlen(USER_VM_SHUTDOWN)); + LOG_PRINTF("Foward (%s) to user VM (%s) by UART\n", msg, c_dev->name); + start_uart_channel_dev_resend(c_dev, msg, MIN_RESEND_TIME); + ret = send_message_by_uart(c_dev->uart_device, msg, strlen(msg)); if (ret < 0) - LOG_WRITE("Failed to foward guest shutdown request to user VM by UART\n"); + LOG_PRINTF("Failed to foward (%s) to user VM by UART\n", msg); return ret; } +int socket_req_user_vm_shutdown_handler(void *arg, int fd) +{ + return req_user_vm_shutdown_reboot(arg, fd, USER_VM_SHUTDOWN, ACK_REQ_USER_VM_SHUTDOWN); +} +int socket_req_user_vm_reboot_handler(void *arg, int fd) +{ + return req_user_vm_shutdown_reboot(arg, fd, USER_VM_REBOOT, ACK_REQ_USER_VM_REBOOT); +} int socket_req_system_shutdown_user_vm_handler(void *arg, int fd) { int ret; @@ -158,7 +172,7 @@ int socket_req_system_shutdown_user_vm_handler(void *arg, int fd) return 0; } LOG_WRITE("Foward shutdown req to service VM by UART\n"); - enable_uart_channel_dev_resend(c_dev, REQ_SYS_SHUTDOWN, MIN_RESEND_TIME); + start_uart_channel_dev_resend(c_dev, REQ_SYS_SHUTDOWN, MIN_RESEND_TIME); ret = send_message_by_uart(c_dev->uart_device, REQ_SYS_SHUTDOWN, strlen(REQ_SYS_SHUTDOWN)); if (ret < 0) LOG_WRITE("Failed to foward system shutdown request to service VM by UART\n"); @@ -222,7 +236,7 @@ int req_shutdown_handler(void *arg, int fd) LOG_WRITE("Send acked message to user VM fail\n"); usleep(SECOND_TO_US); LOG_PRINTF("Send acked shutdown request message to user VM (%s)\n", c_dev->name); - enable_all_uart_channel_dev_resend(c, POWEROFF_CMD, VM_SHUTDOWN_RETRY_TIMES); + start_all_uart_channel_dev_resend(c, POWEROFF_CMD, VM_SHUTDOWN_RETRY_TIMES); notify_all_connected_uart_channel_dev(c, POWEROFF_CMD); usleep(2 * WAIT_RECV); return ret; @@ -244,7 +258,7 @@ int ack_poweroff_handler(void *arg, int fd) if (c_dev == NULL) return 0; LOG_PRINTF("Receive poweroff ACK from user VM (%s)\n", c_dev->name); - disable_uart_channel_dev_resend(c_dev); + stop_uart_channel_dev_resend(c_dev); disconnect_uart_channel_dev(c_dev, c); usleep(WAIT_USER_VM_POWEROFF); start_system_shutdown(); @@ -268,10 +282,10 @@ int ack_timeout_handler(void *arg, int fd) if (strncmp(c_dev->resend_buf, POWEROFF_CMD, strlen(POWEROFF_CMD)) == 0) ack_poweroff_handler(arg, fd); else - disable_uart_channel_dev_resend(c_dev); + stop_uart_channel_dev_resend(c_dev); return 0; } -int ack_user_vm_shutdown_cmd_handler(void *arg, int fd) +static int ack_user_vm_cmd(void *arg, int fd, char *ack_msg) { struct channel_dev *c_dev = NULL; struct uart_channel *c = (struct uart_channel *)arg; @@ -279,10 +293,19 @@ int ack_user_vm_shutdown_cmd_handler(void *arg, int fd) c_dev = find_uart_channel_dev(c, fd); if (c_dev == NULL) return 0; - LOG_PRINTF("Receive user VM shutdown ACK from user VM (%s)\n", c_dev->name); - disable_uart_channel_dev_resend(c_dev); + LOG_PRINTF("Receive (%s) from user VM (%s)\n", ack_msg, c_dev->name); + stop_uart_channel_dev_resend(c_dev); return 0; } +int ack_user_vm_shutdown_cmd_handler(void *arg, int fd) +{ + return ack_user_vm_cmd(arg, fd, ACK_USER_VM_SHUTDOWN); +} + +int ack_user_vm_reboot_cmd_handler(void *arg, int fd) +{ + return ack_user_vm_cmd(arg, fd, ACK_USER_VM_REBOOT); +} /** * @brief The handler of acked sync command of lifecycle manager in user VM * @@ -317,11 +340,11 @@ int acked_req_shutdown_handler(void *arg, int fd) c_dev = find_uart_channel_dev(c, fd); if (c_dev == NULL) return 0; - disable_uart_channel_dev_resend(c_dev); + stop_uart_channel_dev_resend(c_dev); LOG_WRITE("Receive shutdown request ACK from service VM\n"); return 0; } -static int user_vm_shutdown(struct uart_channel *c, int fd, char *ack) +static int user_vm_shutdown_reboot(struct uart_channel *c, int fd, char *ack, bool reboot) { int ret; struct channel_dev *c_dev = NULL; @@ -330,14 +353,18 @@ static int user_vm_shutdown(struct uart_channel *c, int fd, char *ack) if (c_dev == NULL) return 0; - LOG_WRITE("Receive poweroff message from service VM\n"); ret = send_message_by_uart(c_dev->uart_device, ack, strlen(ack)); - if (ret < 0) - LOG_WRITE("Failed to send poweroff ACK to service VM\n"); + if (ret < 0) { + LOG_PRINTF("Failed to send (%s) to service VM\n", ack); + } disconnect_uart_channel_dev(c_dev, c); usleep(2 * WAIT_RECV); close_socket(sock_server); - system_shutdown_flag = true; + if (reboot) { + user_vm_reboot_flag = true; + } else { + system_shutdown_flag = true; + } return 0; } /** @@ -351,13 +378,19 @@ int poweroff_cmd_handler(void *arg, int fd) { struct uart_channel *c = (struct uart_channel *)arg; - (void) user_vm_shutdown(c, fd, ACK_POWEROFF); + (void) user_vm_shutdown_reboot(c, fd, ACK_POWEROFF, false); return 0; } int user_vm_shutdown_cmd_handler(void *arg, int fd) { struct uart_channel *c = (struct uart_channel *)arg; - (void) user_vm_shutdown(c, fd, ACK_USER_VM_SHUTDOWN); + (void) user_vm_shutdown_reboot(c, fd, ACK_USER_VM_SHUTDOWN, false); + return 0; +} +int user_vm_reboot_cmd_handler(void *arg, int fd) +{ + struct uart_channel *c = (struct uart_channel *)arg; + (void) user_vm_shutdown_reboot(c, fd, ACK_USER_VM_REBOOT, true); return 0; } /** @@ -375,7 +408,7 @@ int ack_timeout_default_handler(void *arg, int fd) c_dev = find_uart_channel_dev(c, fd); if (c_dev == NULL) return 0; - disable_uart_channel_dev_resend(c_dev); + stop_uart_channel_dev_resend(c_dev); disconnect_uart_channel_dev(c_dev, c); close_socket(sock_server); LOG_PRINTF("Failed to receive ACK message from service VM (fd = %d)\n", fd); diff --git a/misc/services/life_mngr/command_handler.h b/misc/services/life_mngr/command_handler.h index eb5853107..e232831d7 100644 --- a/misc/services/life_mngr/command_handler.h +++ b/misc/services/life_mngr/command_handler.h @@ -13,6 +13,10 @@ extern struct socket_dev *sock_server; * @brief Get the system shutdown flag */ bool get_system_shutdown_flag(void); +/** + * @brief Get the reboot flag + */ +bool get_user_vm_reboot_flag(void); /** * @brief The handler of request system shutdown command on socket in service VM */ @@ -21,6 +25,10 @@ int socket_req_shutdown_service_vm_handler(void *arg, int fd); * @brief The handler of request user shutdown command on socket in service VM */ int socket_req_user_vm_shutdown_handler(void *arg, int fd); +/** + * @brief The handler of request user reboot command on socket in service VM + */ +int socket_req_user_vm_reboot_handler(void *arg, int fd); /** * @brief The handler of request system shutdown command on socket in user VM */ @@ -67,6 +75,15 @@ int ack_timeout_handler(void *arg, int fd); * @return indicate this command is handled successful or not */ int ack_user_vm_shutdown_cmd_handler(void *arg, int fd); +/** + * @brief The handler of ACK user vm reboot command of + * lifecycle manager in service VM + * + * @param arg uart channel instance + * @param fd the file directory of the uart which receives message + * @return indicate this command is handled successful or not + */ +int ack_user_vm_reboot_cmd_handler(void *arg, int fd); /** * @brief The handler of acked sync command of lifecycle manager in user VM * @@ -95,6 +112,10 @@ int poweroff_cmd_handler(void *arg, int fd); * @brief The handler of user VM shutdown command of lifecycle manager in user VM */ int user_vm_shutdown_cmd_handler(void *arg, int fd); +/** + * @brief The handler of user VM reboot command of lifecycle manager in user VM + */ +int user_vm_reboot_cmd_handler(void *arg, int fd); /** * @brief The handler of ACK timeout command of lifecycle manager in user VM * diff --git a/misc/services/life_mngr/life_mngr_win.c b/misc/services/life_mngr/life_mngr_win.c index 9b34bddb2..4d5a96492 100644 --- a/misc/services/life_mngr/life_mngr_win.c +++ b/misc/services/life_mngr/life_mngr_win.c @@ -18,6 +18,8 @@ #define ACK_POWEROFF "ack_poweroff" #define USER_VM_SHUTDOWN "user_vm_shutdown" #define ACK_USER_VM_SHUTDOWN "ack_user_vm_shutdown" +#define USER_VM_REBOOT "user_vm_reboot" +#define ACK_USER_VM_REBOOT "ack_user_vm_reboot" #define SYNC_FMT "sync:%s" #define S5_REJECTED "system shutdown request is rejected" @@ -44,14 +46,14 @@ void send_message_by_uart(HANDLE hCom, char *buf, unsigned int len) WriteFile(hCom, "\n", 1, &written, NULL); } -void enable_uart_resend(char *buf, unsigned int time) +void start_uart_resend(char *buf, unsigned int time) { if (resend_time < MIN_RESEND_TIME) resend_time = MIN_RESEND_TIME; strncpy(resend_buf, buf, BUFF_SIZE - 1); resend_time = time + 1U; } -void diable_uart_resend(void) +void stop_uart_resend(void) { memset(resend_buf, 0x0, BUFF_SIZE); resend_time = 0U; @@ -108,7 +110,7 @@ DWORD WINAPI open_socket_server(LPVOID lpParam) } while (strncmp(revData, REQ_SYS_SHUTDOWN, sizeof(REQ_SYS_SHUTDOWN)) != 0); Sleep(6U * MS_TO_SECOND); send(sClient, sendData, strlen(sendData), 0); - enable_uart_resend(REQ_SYS_SHUTDOWN, MIN_RESEND_TIME); + start_uart_resend(REQ_SYS_SHUTDOWN, MIN_RESEND_TIME); send_message_by_uart(hCom2, REQ_SYS_SHUTDOWN, sizeof(REQ_SYS_SHUTDOWN)); Sleep(2 * READ_INTERVAL); closesocket(sClient); @@ -165,6 +167,7 @@ int main() DWORD dwError; DWORD threadId; bool poweroff = false; + bool reboot = false; unsigned int retry_times; hCom2 = initCom("COM2"); @@ -177,7 +180,7 @@ int main() PurgeComm(hCom2, PURGE_TXABORT | PURGE_TXCLEAR); } snprintf(buf, sizeof(buf), SYNC_FMT, WIN_VM_NAME); - enable_uart_resend(buf, MIN_RESEND_TIME); + start_uart_resend(buf, MIN_RESEND_TIME); send_message_by_uart(hCom2, buf, strlen(buf)); /** * The lifecycle manager in Service VM checks sync message every 5 seconds @@ -216,10 +219,10 @@ int main() if (strncmp(recvbuf, ACK_SYNC, sizeof(ACK_SYNC)) == 0) { - diable_uart_resend(); + stop_uart_resend(); printf("Received acked sync message from service VM\n"); } else if (strncmp(recvbuf, ACK_REQ_SYS_SHUTDOWN, sizeof(ACK_REQ_SYS_SHUTDOWN)) == 0) { - diable_uart_resend(); + stop_uart_resend(); printf("Received acked system shutdown request from service VM\n"); } else if (strncmp(recvbuf, POWEROFF_CMD, sizeof(POWEROFF_CMD)) == 0) { printf("Received system shutdown message from service VM\n"); @@ -235,6 +238,13 @@ int main() printf("Windows VM will shutdown.\n"); poweroff = true; break; + } else if (strncmp(recvbuf, USER_VM_REBOOT, sizeof(USER_VM_REBOOT)) == 0) { + printf("Received guest reboot message from service VM\n"); + send_message_by_uart(hCom2, ACK_USER_VM_REBOOT, sizeof(ACK_USER_VM_REBOOT)); + Sleep(2 * READ_INTERVAL); + printf("Windows VM will reboot.\n"); + reboot = true; + break; } else { printf("Received invalid message (%s) from service VM.\n", recvbuf); } @@ -242,5 +252,7 @@ int main() CloseHandle(hCom2); if (poweroff) system("shutdown -s -t 0"); + if (reboot) + system("shutdown -r -t 0"); return 0; } diff --git a/misc/services/life_mngr/monitor.c b/misc/services/life_mngr/monitor.c index 0a576220c..1dbeddb57 100644 --- a/misc/services/life_mngr/monitor.c +++ b/misc/services/life_mngr/monitor.c @@ -93,6 +93,8 @@ int init_socket_server_and_shutdown_commands(bool service_vm) sock_server, REQ_SYS_SHUTDOWN); register_command_handler(socket_req_user_vm_shutdown_handler, sock_server, USER_VM_SHUTDOWN); + register_command_handler(socket_req_user_vm_reboot_handler, + sock_server, USER_VM_REBOOT); } else { register_command_handler(socket_req_system_shutdown_user_vm_handler, sock_server, REQ_SYS_SHUTDOWN); @@ -118,6 +120,7 @@ int init_uart_channel_devs_and_shutdown_commands(bool service_vm, char *uart_dev register_command_handler(ack_poweroff_handler, channel, ACK_POWEROFF); register_command_handler(ack_timeout_handler, channel, ACK_TIMEOUT); register_command_handler(ack_user_vm_shutdown_cmd_handler, channel, ACK_USER_VM_SHUTDOWN); + register_command_handler(ack_user_vm_reboot_cmd_handler, channel, ACK_USER_VM_REBOOT); ret = create_service_vm_uart_channel_dev(uart_dev_name); if (ret < 0) @@ -126,6 +129,7 @@ int init_uart_channel_devs_and_shutdown_commands(bool service_vm, char *uart_dev register_command_handler(acked_sync_handler, channel, ACK_SYNC); register_command_handler(poweroff_cmd_handler, channel, POWEROFF_CMD); register_command_handler(user_vm_shutdown_cmd_handler, channel, USER_VM_SHUTDOWN); + register_command_handler(user_vm_reboot_cmd_handler, channel, USER_VM_REBOOT); register_command_handler(acked_req_shutdown_handler, channel, ACK_REQ_SYS_SHUTDOWN); register_command_handler(ack_timeout_default_handler, channel, ACK_TIMEOUT); @@ -215,6 +219,11 @@ int main(int argc, char *argv[]) ret = system(POWEROFF); } while (ret < 0); } + if (get_user_vm_reboot_flag()) { + do { + ret = system(REBOOT); + } while (ret < 0); + } return 0; } diff --git a/misc/services/life_mngr/uart_channel.c b/misc/services/life_mngr/uart_channel.c index 83aa917c9..73c4ff83c 100644 --- a/misc/services/life_mngr/uart_channel.c +++ b/misc/services/life_mngr/uart_channel.c @@ -221,25 +221,25 @@ void stop_listen_uart_channel_dev(struct uart_channel *c) } } } -void enable_uart_channel_dev_resend(struct channel_dev *c_dev, char *resend_buf, unsigned int resend_time) +void start_uart_channel_dev_resend(struct channel_dev *c_dev, char *resend_buf, unsigned int resend_time) { if (resend_time < MIN_RESEND_TIME) resend_time = MIN_RESEND_TIME; strncpy(c_dev->resend_buf, resend_buf, CHANNEL_DEV_BUF_LEN - 1); c_dev->resend_time = resend_time + 1; } -void enable_all_uart_channel_dev_resend(struct uart_channel *c, char *msg, unsigned int resend_time) +void start_all_uart_channel_dev_resend(struct uart_channel *c, char *msg, unsigned int resend_time) { struct channel_dev *c_dev; /* Enable resend for all connected uart channel devices */ pthread_mutex_lock(&c->tty_conn_list_lock); LIST_FOREACH(c_dev, &c->tty_conn_head, list) { - enable_uart_channel_dev_resend(c_dev, msg, resend_time); + start_uart_channel_dev_resend(c_dev, msg, resend_time); } pthread_mutex_unlock(&c->tty_conn_list_lock); } -void disable_uart_channel_dev_resend(struct channel_dev *c_dev) +void stop_uart_channel_dev_resend(struct channel_dev *c_dev) { if (c_dev->resend_time == 1U) LOG_PRINTF("Timeout of receiving ACK message from (%s)\n", c_dev->name); diff --git a/misc/services/life_mngr/uart_channel.h b/misc/services/life_mngr/uart_channel.h index cb802c725..ab36c406f 100644 --- a/misc/services/life_mngr/uart_channel.h +++ b/misc/services/life_mngr/uart_channel.h @@ -125,15 +125,15 @@ void stop_listen_uart_channel_dev(struct uart_channel *c); * If ACK message is not received during specified time, resend * message. */ -void enable_uart_channel_dev_resend(struct channel_dev *c_dev, char *resend_buf, unsigned int resend_time); +void start_uart_channel_dev_resend(struct channel_dev *c_dev, char *resend_buf, unsigned int resend_time); /** - * @brief Enable resend for all connected uart channel devices + * @brief Start to resend for all connected uart channel devices */ -void enable_all_uart_channel_dev_resend(struct uart_channel *c, char *msg, unsigned int resend_time); +void start_all_uart_channel_dev_resend(struct uart_channel *c, char *msg, unsigned int resend_time); /** - * @brief Clear the uart channel device resending buffer and resending time + * @brief Stop the uart channel device resending buffer and resending time */ -void disable_uart_channel_dev_resend(struct channel_dev *c_dev); +void stop_uart_channel_dev_resend(struct channel_dev *c_dev); /** * @brief Broadcast message to each connected uart channel device */