mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-18 19:57:31 +00:00
IOC mediator: Implement state transfer framework
Implements state transfer framework to support IOC lifecycle virtualization. Four states will be involved in this framework includes INIT, ACTIVE,SUSPENDING and SUSPENDED. Signed-off-by: Liu Yuan <yuan1.liu@intel.com> Reviewed-by: Wang Yu <yu1.wang@intel.com> Reviewed-by: Liu Shuo <shuo.a.liu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
92da8f4954
commit
11208dd6d5
@ -139,6 +139,59 @@ static int dummy1_sfd = -1;
|
||||
static int dummy2_sfd = -1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IOC State Transfer
|
||||
*
|
||||
* +-----------+ RESUME EVENT +-----------+
|
||||
* | INIT +<---------------------------+ SUSPENDED |
|
||||
* +-----+-----+ +-----------+
|
||||
* | ^
|
||||
* | |
|
||||
* |HB ACTIVE |SHUTDOWN
|
||||
* |EVENT |EVENT
|
||||
* | |
|
||||
* | |
|
||||
* v RAM REFRESH EVENT/ |
|
||||
* +-----+-----+ HB INACTIVE EVENT +-----+-----+
|
||||
* | ACTIVE +--------------------------->+SUSPENDING |
|
||||
* +-----------+ +-----------+
|
||||
*
|
||||
* INIT state: The state is IOC mediator initialized IOC state, all of CBC
|
||||
* protocol packats are handler normally. In this state, UOS has
|
||||
* not yet sent active heartbeat.
|
||||
*
|
||||
* ACTIVE state: Enter this state if HB ACTIVE event is triggered that indicates
|
||||
* UOS state has been active and need to set the bit 23(SoC active
|
||||
* bit) in the wakeup reason.
|
||||
*
|
||||
* SUSPENDING state: Enter this state if RAM REFRESH event or HB INACTIVE event
|
||||
* is triggered, the related event handler needs to set the
|
||||
* suspend or shutdown to PM DM and begin to drop the queued
|
||||
* CBC protocol packets.
|
||||
*
|
||||
* SUSPENDED state: Enter this state if SHUTDOWN event is triggered to close all
|
||||
* native CBC char devices. The IOC mediator will be enter to
|
||||
* sleeping until RESUME event is triggered that re-opens
|
||||
* closed native CBC char devices and transfer to INIT state.
|
||||
*/
|
||||
static int process_hb_active_event(struct ioc_dev *ioc);
|
||||
static int process_ram_refresh_event(struct ioc_dev *ioc);
|
||||
static int process_hb_inactive_event(struct ioc_dev *ioc);
|
||||
static int process_shutdown_event(struct ioc_dev *ioc);
|
||||
static int process_resume_event(struct ioc_dev *ioc);
|
||||
static struct ioc_state_info ioc_state_tbl[] = {
|
||||
{IOC_S_INIT, IOC_S_ACTIVE, IOC_E_HB_ACTIVE,
|
||||
process_hb_active_event},
|
||||
{IOC_S_ACTIVE, IOC_S_SUSPENDING, IOC_E_RAM_REFRESH,
|
||||
process_ram_refresh_event},
|
||||
{IOC_S_ACTIVE, IOC_S_SUSPENDING, IOC_E_HB_INACTIVE,
|
||||
process_hb_inactive_event},
|
||||
{IOC_S_SUSPENDING, IOC_S_SUSPENDED, IOC_E_SHUTDOWN,
|
||||
process_shutdown_event},
|
||||
{IOC_S_SUSPENDED, IOC_S_INIT, IOC_E_RESUME,
|
||||
process_resume_event},
|
||||
};
|
||||
|
||||
/*
|
||||
* IOC channels definition.
|
||||
*/
|
||||
@ -163,6 +216,7 @@ static struct ioc_ch_info ioc_ch_tbl[] = {
|
||||
{IOC_INIT_FD, IOC_NP_RAW10, IOC_NATIVE_RAW10, IOC_CH_ON},
|
||||
{IOC_INIT_FD, IOC_NP_RAW11, IOC_NATIVE_RAW11, IOC_CH_ON},
|
||||
{IOC_INIT_FD, IOC_DP_NONE, IOC_VIRTUAL_UART, IOC_CH_ON},
|
||||
{IOC_INIT_FD, IOC_DP_NONE, IOC_LOCAL_EVENT, IOC_CH_ON}
|
||||
#ifdef IOC_DUMMY
|
||||
{IOC_INIT_FD, IOC_NP_FLF, IOC_NATIVE_DUMMY0, IOC_CH_ON},
|
||||
{IOC_INIT_FD, IOC_NP_FSIG, IOC_NATIVE_DUMMY1, IOC_CH_ON},
|
||||
@ -564,6 +618,7 @@ ioc_ch_init(struct ioc_dev *ioc)
|
||||
{
|
||||
int i, fd;
|
||||
struct ioc_ch_info *chl;
|
||||
int pipe_fds[2];
|
||||
|
||||
for (i = 0, chl = ioc_ch_tbl; i < ARRAY_SIZE(ioc_ch_tbl); i++, chl++) {
|
||||
if (chl->stat == IOC_CH_OFF)
|
||||
@ -578,6 +633,15 @@ ioc_ch_init(struct ioc_dev *ioc)
|
||||
case IOC_VIRTUAL_UART:
|
||||
fd = ioc_open_virtual_uart(virtual_uart_path);
|
||||
break;
|
||||
case IOC_LOCAL_EVENT:
|
||||
if (!pipe(pipe_fds)) {
|
||||
fd = pipe_fds[0];
|
||||
ioc->evt_fd = pipe_fds[1];
|
||||
} else {
|
||||
fd = IOC_INIT_FD;
|
||||
DPRINTF("%s", "ioc open event fd failed\r\n");
|
||||
}
|
||||
break;
|
||||
#ifdef IOC_DUMMY
|
||||
/*
|
||||
* TODO: check open if success for dummy fd
|
||||
@ -606,7 +670,8 @@ ioc_ch_init(struct ioc_dev *ioc)
|
||||
* if can not open lifecycle or virtual UART
|
||||
* ioc needs to exit initilization with failure
|
||||
*/
|
||||
if (fd < 0 && (i == IOC_NATIVE_LFCC || i == IOC_VIRTUAL_UART))
|
||||
if (fd < 0 && (i == IOC_NATIVE_LFCC || i == IOC_VIRTUAL_UART ||
|
||||
i == IOC_LOCAL_EVENT))
|
||||
return -1;
|
||||
|
||||
chl->fd = fd;
|
||||
@ -702,6 +767,85 @@ cbc_request_dequeue(struct ioc_dev *ioc, enum cbc_queue_type qtype)
|
||||
return free;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process hb active event before transfer to next state
|
||||
*/
|
||||
static int
|
||||
process_hb_active_event(struct ioc_dev *ioc)
|
||||
{
|
||||
/* TODO: Need implementation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process ram refresh event before transfer to next state
|
||||
*/
|
||||
static int
|
||||
process_ram_refresh_event(struct ioc_dev *ioc)
|
||||
{
|
||||
/* TODO: Need implementation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process hb inactive event before transfer to next state
|
||||
*/
|
||||
static int
|
||||
process_hb_inactive_event(struct ioc_dev *ioc)
|
||||
{
|
||||
/* TODO: Need implementation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process shutdown reason event before transfer to next state
|
||||
*/
|
||||
static int
|
||||
process_shutdown_event(struct ioc_dev *ioc)
|
||||
{
|
||||
/* TODO: Need implementation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process resume event before transfer to next state
|
||||
*/
|
||||
static int
|
||||
process_resume_event(struct ioc_dev *ioc)
|
||||
{
|
||||
/* TODO: Need implementation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process IOC local events
|
||||
*/
|
||||
static void
|
||||
ioc_process_events(struct ioc_dev *ioc, enum ioc_ch_id id)
|
||||
{
|
||||
int i;
|
||||
uint8_t evt;
|
||||
|
||||
/* Get one event */
|
||||
if (ioc_ch_recv(id, &evt, sizeof(evt)) < 0) {
|
||||
DPRINTF("%s", "ioc state gets event failed\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ioc_state_tbl); i++) {
|
||||
if (evt == ioc_state_tbl[i].evt &&
|
||||
ioc->state == ioc_state_tbl[i].cur_stat) {
|
||||
if (ioc_state_tbl[i].handler &&
|
||||
ioc_state_tbl[i].handler(ioc) == 0)
|
||||
ioc->state = ioc_state_tbl[i].next_stat;
|
||||
else
|
||||
DPRINTF("ioc state switching failed,%d->%d\r\n",
|
||||
ioc_state_tbl[i].cur_stat,
|
||||
ioc_state_tbl[i].next_stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a cbc_request with CBC link frame and add the cbc_request to
|
||||
* the rx queue tail.
|
||||
@ -816,6 +960,9 @@ ioc_dispatch(struct ioc_dev *ioc, struct ioc_ch_info *chl)
|
||||
case IOC_VIRTUAL_UART:
|
||||
ioc_process_rx(ioc, chl->id);
|
||||
break;
|
||||
case IOC_LOCAL_EVENT:
|
||||
ioc_process_events(ioc, chl->id);
|
||||
break;
|
||||
default:
|
||||
DPRINTF("ioc dispatch got wrong channel:%d\r\n", chl->id);
|
||||
break;
|
||||
@ -881,6 +1028,7 @@ ioc_rx_thread(void *arg)
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
packet.cfg = &ioc->rx_config;
|
||||
packet.boot_reason = ioc_boot_reason;
|
||||
|
||||
for (;;) {
|
||||
pthread_mutex_lock(&ioc->rx_mtx);
|
||||
while (SIMPLEQ_EMPTY(&ioc->rx_qhead)) {
|
||||
@ -933,6 +1081,7 @@ ioc_tx_thread(void *arg)
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
packet.cfg = &ioc->tx_config;
|
||||
packet.boot_reason = ioc_boot_reason;
|
||||
|
||||
for (;;) {
|
||||
pthread_mutex_lock(&ioc->tx_mtx);
|
||||
while (SIMPLEQ_EMPTY(&ioc->tx_qhead)) {
|
||||
@ -1095,12 +1244,19 @@ ioc_init(struct vmctx *ctx)
|
||||
for (i = 0; i < IOC_MAX_REQUESTS; i++)
|
||||
SIMPLEQ_INSERT_TAIL(&ioc->free_qhead, ioc->pool + i, me_queue);
|
||||
|
||||
/* Initialize IOC state */
|
||||
ioc->state = IOC_S_INIT;
|
||||
|
||||
/* Set event fd to default value */
|
||||
ioc->evt_fd = IOC_INIT_FD;
|
||||
|
||||
/*
|
||||
* Initialize native CBC cdev and virtual UART.
|
||||
*/
|
||||
if (ioc_ch_init(ioc) != 0)
|
||||
goto chl_err;
|
||||
|
||||
|
||||
/* Initlialize CBC rx/tx signal and group whitelists */
|
||||
wlist_init_signal(cbc_rx_signal_table, ARRAY_SIZE(cbc_rx_signal_table),
|
||||
wlist_rx_signal_table,
|
||||
@ -1175,6 +1331,8 @@ work_err:
|
||||
chl_err:
|
||||
ioc_ch_deinit();
|
||||
pthread_mutex_destroy(&ioc->free_mtx);
|
||||
if (ioc->evt_fd >= 0)
|
||||
close(ioc->evt_fd);
|
||||
close(ioc->epfd);
|
||||
alloc_err:
|
||||
free(ioc->evts);
|
||||
@ -1200,6 +1358,8 @@ ioc_deinit(struct vmctx *ctx)
|
||||
}
|
||||
ioc_kill_workers(ioc);
|
||||
ioc_ch_deinit();
|
||||
if (ioc->evt_fd >= 0)
|
||||
close(ioc->evt_fd);
|
||||
close(ioc->epfd);
|
||||
free(ioc->evts);
|
||||
free(ioc->pool);
|
||||
|
@ -526,6 +526,7 @@ enum ioc_ch_id {
|
||||
IOC_NATIVE_RAW10, /* Native /dev/cbc-raw10 */
|
||||
IOC_NATIVE_RAW11, /* Native /dev/cbc-raw11 */
|
||||
IOC_VIRTUAL_UART, /* Virtual UART */
|
||||
IOC_LOCAL_EVENT, /* Local channel for IOC event */
|
||||
IOC_NATIVE_DUMMY0, /* Native fake lifecycle channel */
|
||||
IOC_NATIVE_DUMMY1, /* Native fake signal channel */
|
||||
IOC_NATIVE_DUMMY2, /* Native Fake oem raw channel */
|
||||
@ -575,8 +576,8 @@ enum cbc_queue_type {
|
||||
*/
|
||||
enum cbc_request_type {
|
||||
CBC_REQ_T_PROT, /* CBC protocol request */
|
||||
CBC_REQ_T_VMM_S3, /* VMM suspend request */
|
||||
CBC_REQ_T_VMM_S5, /* VMM shutdown request */
|
||||
CBC_REQ_T_SUSPEND, /* CBC suspend request */
|
||||
CBC_REQ_T_SHUTDOWN, /* CBC shutdown request */
|
||||
CBC_REQ_T_SOC /* SOC state update request */
|
||||
};
|
||||
|
||||
@ -656,6 +657,28 @@ struct cbc_request {
|
||||
SIMPLEQ_ENTRY(cbc_request) me_queue;
|
||||
};
|
||||
|
||||
/*
|
||||
* IOC state types.
|
||||
*/
|
||||
enum ioc_state_type {
|
||||
IOC_S_INIT,
|
||||
IOC_S_ACTIVE,
|
||||
IOC_S_SUSPENDING,
|
||||
IOC_S_SUSPENDED
|
||||
};
|
||||
|
||||
/*
|
||||
* IOC event types.
|
||||
*/
|
||||
enum ioc_event_type {
|
||||
IOC_E_INVALID,
|
||||
IOC_E_HB_ACTIVE,
|
||||
IOC_E_RAM_REFRESH,
|
||||
IOC_E_HB_INACTIVE,
|
||||
IOC_E_SHUTDOWN,
|
||||
IOC_E_RESUME
|
||||
};
|
||||
|
||||
/*
|
||||
* CBC packet is mainly structure for CBC protocol process.
|
||||
*/
|
||||
@ -684,6 +707,8 @@ struct ioc_dev {
|
||||
char name[16]; /* Core thread name */
|
||||
int closing; /* Close IOC mediator device flag */
|
||||
int epfd; /* Epoll fd */
|
||||
int32_t evt_fd; /* Pipe write fd to trigger one event */
|
||||
enum ioc_state_type state; /* IOC state type */
|
||||
struct epoll_event *evts; /* Epoll events table */
|
||||
struct cbc_request *pool; /* CBC requests pool */
|
||||
struct cbc_ring ring; /* Ring buffer */
|
||||
@ -708,6 +733,16 @@ struct ioc_dev {
|
||||
void (*ioc_dev_tx)(struct cbc_pkt *pkt);
|
||||
};
|
||||
|
||||
/*
|
||||
* IOC state information.
|
||||
*/
|
||||
struct ioc_state_info {
|
||||
enum ioc_state_type cur_stat;
|
||||
enum ioc_state_type next_stat;
|
||||
enum ioc_event_type evt;
|
||||
int32_t (*handler)(struct ioc_dev *ioc);
|
||||
};
|
||||
|
||||
/* Parse IOC parameters */
|
||||
int ioc_parse(const char *opts);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user