acrn-hypervisor/misc/services/life_mngr/uart_channel.h
Xiangyang Wu ecf99c45a3 Misc: life_mngr: support user VM reboot
Add user VM reboot command and related command handler in
lifecycle manager to support user VM reboot.

Libvirt will send user VM reboot command to lifecycle manager
of service VM through socket, this command is forwarded to the
specified user VM, user VM will execute reboot command to start
reboot itself.

v1-->v2:
	Update some interfaces name to make it reable:
        (1) enable_uart_channel_dev_resend -->
	start_uart_channel_dev_resend
	(2) enable_all_uart_channel_dev_resend -->
	start_all_uart_channel_dev_resend
	(3) disable_uart_channel_dev_resend -->
	stop_uart_channel_dev_resend
	(4) get_reboot_flag --> get_user_vm_reboot_flag

Tracked-On: #5921

Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
2022-03-03 14:40:04 +08:00

147 lines
5.0 KiB
C

/*
* Copyright (C)2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _UART_CHANNEL_H_
#define _UART_CHANNEL_H_
#include <sys/queue.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/un.h>
#include "uart.h"
#define WAIT_USER_VM_POWEROFF (10*SECOND_TO_US)
#define CHANNEL_DEV_NAME_MAX 128U
#define CHANNEL_DEV_BUF_LEN 256U
#define MIN_RESEND_TIME 3U
#define LISTEN_INTERVAL (5 * SECOND_TO_US)
typedef void data_handler_f(const char *cmd_name, int fd);
struct channel_dev {
struct uart_dev *uart_device;
char name[CHANNEL_DEV_NAME_MAX]; /**< channel device name */
bool listening; /**< listen thread loop flag */
bool polling; /**< message polling thread loop flag */
pthread_t listen_thread;
pthread_t pool_thread;
char buf[CHANNEL_DEV_BUF_LEN]; /**< store received message */
LIST_ENTRY(channel_dev) list; /**< list node used in UART connection list */
LIST_ENTRY(channel_dev) open_list; /**< list node used UART opening list */
struct uart_channel *channel; /**< point to UART server */
sem_t dev_sem; /**< semaphore used to start polling message */
char resend_buf[CHANNEL_DEV_BUF_LEN]; /**< store the message that will be sent */
unsigned int resend_time; /**< the time which the message will be resent */
};
struct channel_config {
char identifier[CHANNEL_DEV_NAME_MAX]; /**< the user VM name which is configured by user */
};
struct uart_channel {
data_handler_f *data_handler;
LIST_HEAD(tty_head, channel_dev) tty_conn_head; /* UART connection list */
LIST_HEAD(tty_open_head, channel_dev) tty_open_head; /* UART opening list */
pthread_mutex_t tty_conn_list_lock;
struct channel_config conf;
};
/**
* @brief Initialize each field of uart channel instance, such as
* a lock and configuration of uart channel
*/
struct uart_channel *init_uart_channel(char *id);
/**
* @brief Create one uart channel device according to device name
*
* Create one channel device instance to store information about
* one uart channel device which will be opened.
* For master channel, create two threads, one thread
* is to listen and wait sync messaage from slave channel, another thread
* is to poll message from slave channel.
* For slave channel, create one thread to send sync message
* to master channel every 5 second until acked sync
* message is received from master channel and poll meessage from master channel.
*
* @param uart point to uart server
* @param path start address of the name of the device which will
* be opened
* @param fn the handler of handling message
*/
struct channel_dev *create_uart_channel_dev(struct uart_channel *c, char *path, data_handler_f *fn);
/**
* @brief Wait uart channel devices threads to exit
*/
void wait_uart_channel_devs_threads(struct uart_channel *c);
/**
* @brief Destroy uart channel and release channel device instance
*/
void deinit_uart_channel(struct uart_channel *c);
/**
* @brief Wait to connect device in uart channel
*
* Wait sync message from slave channel device, parse slave channel device
* indentifier from sync message, then add channel device into uart channel
* device connection list.
*/
void *listen_uart_channel_dev(void *arg);
/**
* @brief Wait to connect device in the uart channel
*
* Send sync message every 5 second and wait acked sync message from master
* channel device, add uart channel device instance into uart connection list.
*/
void *connect_uart_channel_dev(void *arg);
/**
* @brief Poll and dispatch message received from uart channel
*
* If resend time is set, this interface will resend message unit the ACK message
* is received.
*/
void *poll_and_dispatch_uart_channel_events(void *arg);
/**
* @brief Find uart channel device instance according to fd
*/
struct channel_dev *find_uart_channel_dev(struct uart_channel *c, int fd);
/**
* @brief Find uart channel device instance according to device name
*/
struct channel_dev *find_uart_channel_dev_by_name(struct uart_channel *c, char *name);
/**
* @brief Disconnect uart channel device instance
*/
void disconnect_uart_channel_dev(struct channel_dev *c_dev, struct uart_channel *c);
/**
* @brief Stop to listen uart channel device
*/
void stop_listen_uart_channel_dev(struct uart_channel *c);
/**
* @brief Set the uart channel device resending buffer and resending time
*
* If ACK message is not received during specified time, resend
* message.
*/
void start_uart_channel_dev_resend(struct channel_dev *c_dev, char *resend_buf, unsigned int resend_time);
/**
* @brief Start to resend for all connected uart channel devices
*/
void start_all_uart_channel_dev_resend(struct uart_channel *c, char *msg, unsigned int resend_time);
/**
* @brief Stop the uart channel device resending buffer and resending time
*/
void stop_uart_channel_dev_resend(struct channel_dev *c_dev);
/**
* @brief Broadcast message to each connected uart channel device
*/
void notify_all_connected_uart_channel_dev(struct uart_channel *c, char *msg);
/**
* @brief Check whether uart channel connection list is empty or not
*/
bool is_uart_channel_connection_list_empty(struct uart_channel *c);
#endif