44
44
#include "mevent.h"
45
45
#include "irq.h"
46
46
#include "lpc.h"
47
+ #include "monitor.h"
47
48
48
49
#define POWER_BUTTON_EVENT 116
50
+ #define POWER_BUTTON_NAME "power_button"
49
51
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER ;
50
52
static struct mevent * power_button ;
51
53
static sig_t old_power_handler ;
52
54
53
55
static struct mevent * input_evt0 ;
54
56
static int pwrbtn_fd = -1 ;
57
+ static bool monitor_run ;
55
58
/*
56
59
* Reset Control register at I/O port 0xcf9. Bit 2 forces a system
57
60
* 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);
217
220
INOUT_PORT (pm1_enable , PM1A_EVT_ADDR + 2 , IOPORT_F_INOUT , pm1_enable_handler );
218
221
219
222
static void
220
- power_button_handler ( int signal , enum ev_type type , void * arg )
223
+ power_button_press_emulation ( struct vmctx * ctx )
221
224
{
222
- struct vmctx * ctx ;
223
-
224
- ctx = arg ;
225
225
pthread_mutex_lock (& pm_lock );
226
226
if (!(pm1_status & PM1_PWRBTN_STS )) {
227
227
pm1_status |= PM1_PWRBTN_STS ;
@@ -230,6 +230,13 @@ power_button_handler(int signal, enum ev_type type, void *arg)
230
230
pthread_mutex_unlock (& pm_lock );
231
231
}
232
232
233
+ static void
234
+ power_button_handler (int signal , enum ev_type type , void * arg )
235
+ {
236
+ if (arg )
237
+ power_button_press_emulation (arg );
238
+ }
239
+
233
240
static void
234
241
input_event0_handler (int fd , enum ev_type type , void * arg )
235
242
{
@@ -241,7 +248,7 @@ input_event0_handler(int fd, enum ev_type type, void *arg)
241
248
return ;
242
249
243
250
if (ev .code == POWER_BUTTON_EVENT && ev .value == 1 )
244
- power_button_handler ( fd , type , arg );
251
+ power_button_press_emulation ( arg );
245
252
}
246
253
247
254
/*
@@ -297,6 +304,31 @@ pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
297
304
INOUT_PORT (pm1_control , PM1A_CNT_ADDR , IOPORT_F_INOUT , pm1_control_handler );
298
305
SYSRES_IO (PM1A_EVT_ADDR , 8 );
299
306
307
+ static int
308
+ vm_stop_handler (void * arg )
309
+ {
310
+ if (!arg )
311
+ return - EINVAL ;
312
+
313
+ power_button_press_emulation (arg );
314
+ return 0 ;
315
+ }
316
+
317
+ static int
318
+ vm_suspend_handler (void * arg )
319
+ {
320
+ /*
321
+ * Invoke vm_stop_handler directly in here since suspend of UOS is
322
+ * set by UOS power button setting.
323
+ */
324
+ return vm_stop_handler (arg );
325
+ }
326
+
327
+ static struct monitor_vm_ops vm_ops = {
328
+ .stop = vm_stop_handler ,
329
+ .suspend = vm_suspend_handler ,
330
+ };
331
+
300
332
/*
301
333
* ACPI SMI Command Register
302
334
*
@@ -314,6 +346,11 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
314
346
switch (* eax ) {
315
347
case ACPI_ENABLE :
316
348
pm1_control |= PM1_SCI_EN ;
349
+ /*
350
+ * FIXME: ACPI_ENABLE/ACPI_DISABLE only impacts SCI_EN via SMI
351
+ * command register, not impact power button emulation. so need
352
+ * to remove all power button emulation from here.
353
+ */
317
354
if (power_button == NULL ) {
318
355
319
356
/*
@@ -327,6 +364,10 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
327
364
old_power_handler = signal (SIGTERM , SIG_IGN );
328
365
}
329
366
if (input_evt0 == NULL ) {
367
+ /*
368
+ * FIXME: check /sys/bus/acpi/devices/LNXPWRBN\:00/input to
369
+ * get input event node instead hardcode in here.
370
+ */
330
371
pwrbtn_fd = open ("/dev/input/event0" , O_RDONLY );
331
372
if (pwrbtn_fd < 0 )
332
373
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,
335
376
input_evt0 = mevent_add (pwrbtn_fd , EVF_READ ,
336
377
input_event0_handler , ctx , NULL , NULL );
337
378
}
379
+
380
+ /*
381
+ * Suspend or shutdown UOS by acrnctl suspend and
382
+ * stop command.
383
+ */
384
+ if (monitor_run == false) {
385
+ if (monitor_register_vm_ops (& vm_ops , ctx ,
386
+ POWER_BUTTON_NAME ) < 0 )
387
+ fprintf (stderr ,
388
+ "failed to register vm ops for power button\n" );
389
+ else
390
+ monitor_run = true;
391
+ }
338
392
break ;
339
393
case ACPI_DISABLE :
340
394
pm1_control &= ~PM1_SCI_EN ;
0 commit comments