IOC mediator: Implement VM monitor operations

This patch implements VM monitor operations including stop/suspend/resume.
For other VM monitor operations(pause/unpause/query), IOC mediator would not
register callbacks for them since there is no requirements from VM Manager.

Signed-off-by: Yuan Liu <yuan1.liu@intel.com>
Reviewed-by: Yu Wang <yu1.wang@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
This commit is contained in:
Yuan Liu 2018-06-20 16:44:59 +08:00 committed by lijinxia
parent 32fccb2f43
commit 48067b1cab
3 changed files with 169 additions and 5 deletions

View File

@ -67,6 +67,7 @@
#include "ioc.h"
#include "vmmapi.h"
#include "monitor.h"
/* For debugging log to a file */
static int ioc_debug;
@ -126,6 +127,38 @@ static int dummy1_sfd = -1;
static int dummy2_sfd = -1;
#endif
/*
* VM Manager interfaces description.
*
* +---------+ +---------+ +---------+
* |IOC | VM stop |VM | |SOS |
* |Mediator |<----------------+Manager | |Lifecycle|
* | | | | | |
* | | VM suspend | | | |
* | |<----------------+ | | |
* | | | | | |
* | | VM resume | | | |
* | |<----------------+ | | |
* | |get_wakeup_reason| |get wakeup reason| |
* | |for resume flow | |via unix socket | |
* | +---------------->| +---------------->| |
* +---------+ +---------+ +---------+
*
* Only support stop/resume/suspend in IOC mediator currently.
* For resume request, IOC mediator will get the wakeup reason from SOS
* lifecycle service, then pass to UOS once received HB INIT from UOS.
* For stop and suspend requests, they are implemented as wakeup reason of
* ignition button.
*/
static int vm_stop_handler(void *arg);
static int vm_resume_handler(void *arg);
static int vm_suspend_handler(void *arg);
static struct monitor_vm_ops vm_ops = {
.stop = vm_stop_handler,
.resume = vm_resume_handler,
.suspend = vm_suspend_handler,
};
/*
* IOC State Transfer
*
@ -1301,6 +1334,72 @@ ioc_is_platform_supported(void)
return stat(IOC_NP_ESIG, &st);
}
/*
* The callback to handle with VM stop request.
* To emulate ignition off wakeup reason including set force S5 bit.
*/
static int
vm_stop_handler(void *arg)
{
struct ioc_dev *ioc = arg;
if (!ioc) {
DPRINTF("%s", "ioc vm stop gets NULL pointer\r\n");
return -1;
}
ioc->vm_req = VM_REQ_STOP;
return 0;
}
/*
* The callback to handle with VM suspend.
* To emulate ignition off wakeup reason.
*/
static int
vm_suspend_handler(void *arg)
{
struct ioc_dev *ioc = arg;
if (!ioc) {
DPRINTF("%s", "ioc vm suspend gets NULL pointer\r\n");
return -1;
}
ioc->vm_req = VM_REQ_SUSPEND;
return 0;
}
/*
* The callback to handle with VM resume.
* To get wakeup reason and trigger IOC_E_RESUME event.
*/
static int
vm_resume_handler(void *arg)
{
struct ioc_dev *ioc = arg;
uint32_t reason;
if (!ioc) {
DPRINTF("%s", "ioc vm resume gets NULL pointer\r\n");
return -1;
}
reason = get_wakeup_reason();
if (!reason) {
DPRINTF("%s", "ioc vm resume gets invalid wakeup reason \r\n");
return -1;
}
/*
* Change VM request to resume for stopping the emulation of suspend
* and shutdown wakeup reasons.
*/
ioc->vm_req = VM_REQ_RESUME;
ioc->boot_reason = reason;
ioc_update_event(ioc->evt_fd, IOC_E_RESUME);
return 0;
}
/*
* To get IOC bootup reason and virtual UART path for communication
* between IOC mediator and virtual UART.
@ -1367,6 +1466,14 @@ ioc_init(struct vmctx *ctx)
if (ioc->epfd < 0)
goto alloc_err;
/*
* Register IOC mediator VM ops for stop/suspend/resume.
*/
if (monitor_register_vm_ops(&vm_ops, ioc, "ioc_dm") < 0) {
DPRINTF("%s", "ioc register to VM monitor failed\r\n");
goto alloc_err;
}
/*
* Put all buffered CBC requests on the free queue, the free queue is
* used to be a cbc_request buffer.

View File

@ -601,7 +601,7 @@ cbc_update_wakeup_reason(struct cbc_pkt *pkt, uint32_t reason)
/*
* Mask the bits of wakeup reason that are not allowed by IOC mediator.
* Only allow Ignition button, cardoor, RTC and SoC currently.
* Only allow Ignition button, cardoor, RTC, SOC and force S5 currently.
*/
reason &= CBC_WK_RSN_ALL;
@ -814,6 +814,45 @@ cbc_rx_handler(struct cbc_pkt *pkt)
}
}
/*
* Convert VM request to the wakeup reason.
*/
static bool
send_wakeup_reason_of_vm_request(struct cbc_pkt *pkt)
{
uint32_t reason;
switch (pkt->ioc->vm_req) {
case VM_REQ_STOP:
/*
* Force S5 and SoC bits are set for emulating
* shutdown wakeup reason that VM initiates stop
*/
reason = CBC_WK_RSN_FS5 | CBC_WK_RSN_SOC;
break;
case VM_REQ_SUSPEND:
/*
* Only SoC bit is set for emulating suspend
* wakeup reason that VM initiates suspend.
*/
reason = CBC_WK_RSN_SOC;
break;
default:
/*
* There is no need to emulate wakeup reasons for VM_REQ_RESUME
* and VM_REQ_NONE VM requests since VM manager just only asks
* IOC mediator to emulate ignition off wakeup reason for
* VM_REQ_STOP and VM_REQ_SUSPEND, otherwise call primary
* periodic wakeup reason.
*/
return false;
}
cbc_update_wakeup_reason(pkt, reason);
cbc_send_pkt(pkt);
return true;
}
/*
* Tx handler mainly processes tx direction data flow,
* the tx direction is that native CBC cdevs -> virtual UART.
@ -824,7 +863,12 @@ cbc_tx_handler(struct cbc_pkt *pkt)
if (pkt->req->rtype == CBC_REQ_T_PROT && pkt->ioc->cbc_enable) {
switch (pkt->req->id) {
case IOC_NATIVE_LFCC:
cbc_process_wakeup_reason(pkt);
/* Check VM request firstly */
if (send_wakeup_reason_of_vm_request(pkt) == false) {
/* Primary periodic wakeup reason */
cbc_process_wakeup_reason(pkt);
}
break;
case IOC_NATIVE_SIGNAL:
cbc_process_signal(pkt);

View File

@ -77,17 +77,19 @@
#define CBC_WK_RSN_BTN (1 << 5) /* CBC wakeup reason field button */
#define CBC_WK_RSN_RTC (1 << 9) /* CBC wakeup reason field rtc */
#define CBC_WK_RSN_DOR (1 << 11) /* CBC wakeup reason field cardoor */
#define CBC_WK_RSN_FS5 (1 << 22) /* CBC wakeup reason field force S5 */
#define CBC_WK_RSN_SOC (1 << 23) /* CBC wakeup reason field soc */
/* CBC wakeup reason filed suspend or shutdown */
#define CBC_WK_RSN_SHUTDOWN (0)
/*
* IOC mediator permits button, rtc and cardoor wakeup reasons which comes from
* IOC firmware, others will be masked.
* IOC mediator permits ignition button, cardoor, RTC, SOC and force S5 wakeup
* reasons which comes from IOC firmware, others will be masked.
*/
#define CBC_WK_RSN_ALL \
(CBC_WK_RSN_BTN | CBC_WK_RSN_RTC | CBC_WK_RSN_DOR | CBC_WK_RSN_SOC)
(CBC_WK_RSN_BTN | CBC_WK_RSN_RTC | CBC_WK_RSN_DOR | CBC_WK_RSN_SOC | \
CBC_WK_RSN_FS5)
/*
* CBC ring buffer is used to buffer bytes before build one complete CBC frame.
@ -660,6 +662,16 @@ enum ioc_event_type {
IOC_E_RESUME
};
/*
* VM request types.
*/
enum vm_request_type {
VM_REQ_NONE,
VM_REQ_STOP,
VM_REQ_SUSPEND,
VM_REQ_RESUME
};
/*
* CBC packet is mainly structure for CBC protocol process.
*/
@ -691,6 +703,7 @@ struct ioc_dev {
int epfd; /* Epoll fd */
int32_t evt_fd; /* Pipe write fd to trigger one event */
uint32_t boot_reason; /* Boot or resume wakeup reason */
enum vm_request_type vm_req; /* Request from VM Manager (acrnctl) */
enum ioc_state_type state; /* IOC state type */
struct epoll_event *evts; /* Epoll events table */
struct cbc_request *pool; /* CBC requests pool */