mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-25 06:51:49 +00:00
dm: power button emulation by acrnctl command.
when UOS is running, "acrnctl suspend vm" and "acrnctl stop vm" commands are able to trigger a SCI interrupt, then UOS enters sleep or shutdown according to the default behavior of the power button. The default behavior is based on UOS power button setting. Tracked-On: #2560 Signed-off-by: Yuan Liu <yuan1.liu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
parent
32a7b4f179
commit
566e8824da
@ -44,14 +44,17 @@
|
|||||||
#include "mevent.h"
|
#include "mevent.h"
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
#include "lpc.h"
|
#include "lpc.h"
|
||||||
|
#include "monitor.h"
|
||||||
|
|
||||||
#define POWER_BUTTON_EVENT 116
|
#define POWER_BUTTON_EVENT 116
|
||||||
|
#define POWER_BUTTON_NAME "power_button"
|
||||||
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static struct mevent *power_button;
|
static struct mevent *power_button;
|
||||||
static sig_t old_power_handler;
|
static sig_t old_power_handler;
|
||||||
|
|
||||||
static struct mevent *input_evt0;
|
static struct mevent *input_evt0;
|
||||||
static int pwrbtn_fd = -1;
|
static int pwrbtn_fd = -1;
|
||||||
|
static bool monitor_run;
|
||||||
/*
|
/*
|
||||||
* Reset Control register at I/O port 0xcf9. Bit 2 forces a system
|
* Reset Control register at I/O port 0xcf9. Bit 2 forces a system
|
||||||
* reset when it transitions from 0 to 1. Bit 1 selects the type of
|
* reset when it transitions from 0 to 1. Bit 1 selects the type of
|
||||||
@ -217,11 +220,8 @@ INOUT_PORT(pm1_status, PM1A_EVT_ADDR, IOPORT_F_INOUT, pm1_status_handler);
|
|||||||
INOUT_PORT(pm1_enable, PM1A_EVT_ADDR + 2, IOPORT_F_INOUT, pm1_enable_handler);
|
INOUT_PORT(pm1_enable, PM1A_EVT_ADDR + 2, IOPORT_F_INOUT, pm1_enable_handler);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
power_button_handler(int signal, enum ev_type type, void *arg)
|
power_button_press_emulation(struct vmctx *ctx)
|
||||||
{
|
{
|
||||||
struct vmctx *ctx;
|
|
||||||
|
|
||||||
ctx = arg;
|
|
||||||
pthread_mutex_lock(&pm_lock);
|
pthread_mutex_lock(&pm_lock);
|
||||||
if (!(pm1_status & PM1_PWRBTN_STS)) {
|
if (!(pm1_status & PM1_PWRBTN_STS)) {
|
||||||
pm1_status |= PM1_PWRBTN_STS;
|
pm1_status |= PM1_PWRBTN_STS;
|
||||||
@ -230,6 +230,13 @@ power_button_handler(int signal, enum ev_type type, void *arg)
|
|||||||
pthread_mutex_unlock(&pm_lock);
|
pthread_mutex_unlock(&pm_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
power_button_handler(int signal, enum ev_type type, void *arg)
|
||||||
|
{
|
||||||
|
if (arg)
|
||||||
|
power_button_press_emulation(arg);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_event0_handler(int fd, enum ev_type type, void *arg)
|
input_event0_handler(int fd, enum ev_type type, void *arg)
|
||||||
{
|
{
|
||||||
@ -241,7 +248,7 @@ input_event0_handler(int fd, enum ev_type type, void *arg)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (ev.code == POWER_BUTTON_EVENT && ev.value == 1)
|
if (ev.code == POWER_BUTTON_EVENT && ev.value == 1)
|
||||||
power_button_handler(fd, type, arg);
|
power_button_press_emulation(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -297,6 +304,31 @@ pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
|||||||
INOUT_PORT(pm1_control, PM1A_CNT_ADDR, IOPORT_F_INOUT, pm1_control_handler);
|
INOUT_PORT(pm1_control, PM1A_CNT_ADDR, IOPORT_F_INOUT, pm1_control_handler);
|
||||||
SYSRES_IO(PM1A_EVT_ADDR, 8);
|
SYSRES_IO(PM1A_EVT_ADDR, 8);
|
||||||
|
|
||||||
|
static int
|
||||||
|
vm_stop_handler(void *arg)
|
||||||
|
{
|
||||||
|
if (!arg)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
power_button_press_emulation(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vm_suspend_handler(void *arg)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Invoke vm_stop_handler directly in here since suspend of UOS is
|
||||||
|
* set by UOS power button setting.
|
||||||
|
*/
|
||||||
|
return vm_stop_handler(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct monitor_vm_ops vm_ops = {
|
||||||
|
.stop = vm_stop_handler,
|
||||||
|
.suspend = vm_suspend_handler,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ACPI SMI Command Register
|
* ACPI SMI Command Register
|
||||||
*
|
*
|
||||||
@ -314,6 +346,11 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
|||||||
switch (*eax) {
|
switch (*eax) {
|
||||||
case ACPI_ENABLE:
|
case ACPI_ENABLE:
|
||||||
pm1_control |= PM1_SCI_EN;
|
pm1_control |= PM1_SCI_EN;
|
||||||
|
/*
|
||||||
|
* FIXME: ACPI_ENABLE/ACPI_DISABLE only impacts SCI_EN via SMI
|
||||||
|
* command register, not impact power button emulation. so need
|
||||||
|
* to remove all power button emulation from here.
|
||||||
|
*/
|
||||||
if (power_button == NULL) {
|
if (power_button == NULL) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -327,6 +364,10 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
|||||||
old_power_handler = signal(SIGTERM, SIG_IGN);
|
old_power_handler = signal(SIGTERM, SIG_IGN);
|
||||||
}
|
}
|
||||||
if (input_evt0 == NULL) {
|
if (input_evt0 == NULL) {
|
||||||
|
/*
|
||||||
|
* FIXME: check /sys/bus/acpi/devices/LNXPWRBN\:00/input to
|
||||||
|
* get input event node instead hardcode in here.
|
||||||
|
*/
|
||||||
pwrbtn_fd = open("/dev/input/event0", O_RDONLY);
|
pwrbtn_fd = open("/dev/input/event0", O_RDONLY);
|
||||||
if (pwrbtn_fd < 0)
|
if (pwrbtn_fd < 0)
|
||||||
fprintf(stderr, "open input event0 error=%d\n",
|
fprintf(stderr, "open input event0 error=%d\n",
|
||||||
@ -335,6 +376,19 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
|||||||
input_evt0 = mevent_add(pwrbtn_fd, EVF_READ,
|
input_evt0 = mevent_add(pwrbtn_fd, EVF_READ,
|
||||||
input_event0_handler, ctx, NULL, NULL);
|
input_event0_handler, ctx, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Suspend or shutdown UOS by acrnctl suspend and
|
||||||
|
* stop command.
|
||||||
|
*/
|
||||||
|
if (monitor_run == false) {
|
||||||
|
if (monitor_register_vm_ops(&vm_ops, ctx,
|
||||||
|
POWER_BUTTON_NAME) < 0)
|
||||||
|
fprintf(stderr,
|
||||||
|
"failed to register vm ops for power button\n");
|
||||||
|
else
|
||||||
|
monitor_run = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ACPI_DISABLE:
|
case ACPI_DISABLE:
|
||||||
pm1_control &= ~PM1_SCI_EN;
|
pm1_control &= ~PM1_SCI_EN;
|
||||||
|
Loading…
Reference in New Issue
Block a user