1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2013 Hudson River Trading LLC 5 * Written by: John H. Baldwin <jhb@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 /* 30 * Copyright 2018 Joyent, Inc. 31 * Copyright 2020 Oxide Computer Company 32 */ 33 34 35 #include <sys/types.h> 36 #include <machine/vmm.h> 37 38 #include <assert.h> 39 #include <errno.h> 40 #include <pthread.h> 41 #ifndef __FreeBSD__ 42 #include <stdlib.h> 43 #endif 44 #include <signal.h> 45 #include <vmmapi.h> 46 47 #include "acpi.h" 48 #include "inout.h" 49 #ifdef __FreeBSD__ 50 #include "mevent.h" 51 #endif 52 #include "pci_irq.h" 53 #include "pci_lpc.h" 54 55 static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER; 56 #ifdef __FreeBSD__ 57 static struct mevent *power_button; 58 static sig_t old_power_handler; 59 #else 60 struct vmctx *pwr_ctx; 61 #endif 62 63 static unsigned gpe0_active; 64 static unsigned gpe0_enabled; 65 static const unsigned gpe0_valid = (1u << GPE_VMGENC); 66 67 /* 68 * Reset Control register at I/O port 0xcf9. Bit 2 forces a system 69 * reset when it transitions from 0 to 1. Bit 1 selects the type of 70 * reset to attempt: 0 selects a "soft" reset, and 1 selects a "hard" 71 * reset. 72 */ 73 static int 74 reset_handler(struct vmctx *ctx __unused, int in, 75 int port __unused, int bytes, uint32_t *eax, void *arg __unused) 76 { 77 int error; 78 79 static uint8_t reset_control; 80 81 if (bytes != 1) 82 return (-1); 83 if (in) 84 *eax = reset_control; 85 else { 86 reset_control = *eax; 87 88 /* Treat hard and soft resets the same. */ 89 if (reset_control & 0x4) { 90 error = vm_suspend(ctx, VM_SUSPEND_RESET); 91 assert(error == 0 || errno == EALREADY); 92 } 93 } 94 return (0); 95 } 96 INOUT_PORT(reset_reg, 0xCF9, IOPORT_F_INOUT, reset_handler); 97 98 /* 99 * ACPI's SCI is a level-triggered interrupt. 100 */ 101 static int sci_active; 102 103 static void 104 sci_assert(struct vmctx *ctx) 105 { 106 107 if (sci_active) 108 return; 109 vm_isa_assert_irq(ctx, SCI_INT, SCI_INT); 110 sci_active = 1; 111 } 112 113 static void 114 sci_deassert(struct vmctx *ctx) 115 { 116 117 if (!sci_active) 118 return; 119 vm_isa_deassert_irq(ctx, SCI_INT, SCI_INT); 120 sci_active = 0; 121 } 122 123 /* 124 * Power Management 1 Event Registers 125 * 126 * The only power management event supported is a power button upon 127 * receiving SIGTERM. 128 */ 129 static uint16_t pm1_enable, pm1_status; 130 131 #define PM1_TMR_STS 0x0001 132 #define PM1_BM_STS 0x0010 133 #define PM1_GBL_STS 0x0020 134 #define PM1_PWRBTN_STS 0x0100 135 #define PM1_SLPBTN_STS 0x0200 136 #define PM1_RTC_STS 0x0400 137 #define PM1_WAK_STS 0x8000 138 139 #define PM1_TMR_EN 0x0001 140 #define PM1_GBL_EN 0x0020 141 #define PM1_PWRBTN_EN 0x0100 142 #define PM1_SLPBTN_EN 0x0200 143 #define PM1_RTC_EN 0x0400 144 145 static void 146 sci_update(struct vmctx *ctx) 147 { 148 int need_sci; 149 150 /* See if the SCI should be active or not. */ 151 need_sci = 0; 152 if ((pm1_enable & PM1_TMR_EN) && (pm1_status & PM1_TMR_STS)) 153 need_sci = 1; 154 if ((pm1_enable & PM1_GBL_EN) && (pm1_status & PM1_GBL_STS)) 155 need_sci = 1; 156 if ((pm1_enable & PM1_PWRBTN_EN) && (pm1_status & PM1_PWRBTN_STS)) 157 need_sci = 1; 158 if ((pm1_enable & PM1_SLPBTN_EN) && (pm1_status & PM1_SLPBTN_STS)) 159 need_sci = 1; 160 if ((pm1_enable & PM1_RTC_EN) && (pm1_status & PM1_RTC_STS)) 161 need_sci = 1; 162 if ((gpe0_enabled & gpe0_active) != 0) 163 need_sci = 1; 164 165 if (need_sci) 166 sci_assert(ctx); 167 else 168 sci_deassert(ctx); 169 } 170 171 static int 172 pm1_status_handler(struct vmctx *ctx, int in, 173 int port __unused, int bytes, uint32_t *eax, void *arg __unused) 174 { 175 176 if (bytes != 2) 177 return (-1); 178 179 pthread_mutex_lock(&pm_lock); 180 if (in) 181 *eax = pm1_status; 182 else { 183 /* 184 * Writes are only permitted to clear certain bits by 185 * writing 1 to those flags. 186 */ 187 pm1_status &= ~(*eax & (PM1_WAK_STS | PM1_RTC_STS | 188 PM1_SLPBTN_STS | PM1_PWRBTN_STS | PM1_BM_STS)); 189 sci_update(ctx); 190 } 191 pthread_mutex_unlock(&pm_lock); 192 return (0); 193 } 194 195 static int 196 pm1_enable_handler(struct vmctx *ctx, int in, 197 int port __unused, int bytes, uint32_t *eax, void *arg __unused) 198 { 199 200 if (bytes != 2) 201 return (-1); 202 203 pthread_mutex_lock(&pm_lock); 204 if (in) 205 *eax = pm1_enable; 206 else { 207 /* 208 * Only permit certain bits to be set. We never use 209 * the global lock, but ACPI-CA whines profusely if it 210 * can't set GBL_EN. 211 */ 212 pm1_enable = *eax & (PM1_RTC_EN | PM1_PWRBTN_EN | PM1_GBL_EN); 213 sci_update(ctx); 214 } 215 pthread_mutex_unlock(&pm_lock); 216 return (0); 217 } 218 INOUT_PORT(pm1_status, PM1A_EVT_ADDR, IOPORT_F_INOUT, pm1_status_handler); 219 INOUT_PORT(pm1_enable, PM1A_EVT_ADDR + 2, IOPORT_F_INOUT, pm1_enable_handler); 220 221 #ifdef __FreeBSD__ 222 static void 223 power_button_handler(int signal __unused, enum ev_type type __unused, void *arg) 224 { 225 struct vmctx *ctx; 226 227 ctx = arg; 228 pthread_mutex_lock(&pm_lock); 229 if (!(pm1_status & PM1_PWRBTN_STS)) { 230 pm1_status |= PM1_PWRBTN_STS; 231 sci_update(ctx); 232 } 233 pthread_mutex_unlock(&pm_lock); 234 } 235 236 #else 237 /* 238 * Initiate graceful power off. 239 */ 240 /*ARGSUSED*/ 241 static void 242 power_button_handler(int signal, siginfo_t *type, void *cp) 243 { 244 /* 245 * In theory, taking the 'pm_lock' mutex from within this signal 246 * handler could lead to deadlock if the main thread already held this 247 * mutex. In reality, this mutex is local to this file and all of the 248 * other usage in this file only occurs in functions which are FreeBSD 249 * specific (and thus currently not used). Thus, for consistency with 250 * the other code in this file, we take the mutex, but in the future, 251 * if these other functions are ever enabled for use on non-FreeBSD 252 * systems and these functions could be called directly by a thread 253 * (which would then hold the mutex), then we need to revisit the use 254 * of this mutex in this signal handler. 255 */ 256 pthread_mutex_lock(&pm_lock); 257 if (!(pm1_status & PM1_PWRBTN_STS)) { 258 pm1_status |= PM1_PWRBTN_STS; 259 sci_update(pwr_ctx); 260 } 261 pthread_mutex_unlock(&pm_lock); 262 } 263 #endif 264 265 /* 266 * Power Management 1 Control Register 267 * 268 * This is mostly unimplemented except that we wish to handle writes that 269 * set SPL_EN to handle S5 (soft power off). 270 */ 271 static uint16_t pm1_control; 272 273 #define PM1_SCI_EN 0x0001 274 #define PM1_SLP_TYP 0x1c00 275 #define PM1_SLP_EN 0x2000 276 #define PM1_ALWAYS_ZERO 0xc003 277 278 static int 279 pm1_control_handler(struct vmctx *ctx, int in, 280 int port __unused, int bytes, uint32_t *eax, void *arg __unused) 281 { 282 int error; 283 284 if (bytes != 2) 285 return (-1); 286 if (in) 287 *eax = pm1_control; 288 else { 289 /* 290 * Various bits are write-only or reserved, so force them 291 * to zero in pm1_control. Always preserve SCI_EN as OSPM 292 * can never change it. 293 */ 294 pm1_control = (pm1_control & PM1_SCI_EN) | 295 (*eax & ~(PM1_SLP_EN | PM1_ALWAYS_ZERO)); 296 297 /* 298 * If SLP_EN is set, check for S5. Bhyve's _S5_ method 299 * says that '5' should be stored in SLP_TYP for S5. 300 */ 301 if (*eax & PM1_SLP_EN) { 302 if ((pm1_control & PM1_SLP_TYP) >> 10 == 5) { 303 error = vm_suspend(ctx, VM_SUSPEND_POWEROFF); 304 assert(error == 0 || errno == EALREADY); 305 } 306 } 307 } 308 return (0); 309 } 310 INOUT_PORT(pm1_control, PM1A_CNT_ADDR, IOPORT_F_INOUT, pm1_control_handler); 311 #ifdef __FreeBSD__ 312 SYSRES_IO(PM1A_EVT_ADDR, 8); 313 #endif 314 315 void 316 acpi_raise_gpe(struct vmctx *ctx, unsigned bit) 317 { 318 unsigned mask; 319 320 assert(bit < (IO_GPE0_LEN * (8 / 2))); 321 mask = (1u << bit); 322 assert((mask & ~gpe0_valid) == 0); 323 324 pthread_mutex_lock(&pm_lock); 325 gpe0_active |= mask; 326 sci_update(ctx); 327 pthread_mutex_unlock(&pm_lock); 328 } 329 330 static int 331 gpe0_sts(struct vmctx *ctx, int in, int port __unused, 332 int bytes, uint32_t *eax, void *arg __unused) 333 { 334 /* 335 * ACPI 6.2 specifies the GPE register blocks are accessed 336 * byte-at-a-time. 337 */ 338 if (bytes != 1) 339 return (-1); 340 341 pthread_mutex_lock(&pm_lock); 342 if (in) 343 *eax = gpe0_active; 344 else { 345 /* W1C */ 346 gpe0_active &= ~(*eax & gpe0_valid); 347 sci_update(ctx); 348 } 349 pthread_mutex_unlock(&pm_lock); 350 return (0); 351 } 352 INOUT_PORT(gpe0_sts, IO_GPE0_STS, IOPORT_F_INOUT, gpe0_sts); 353 354 static int 355 gpe0_en(struct vmctx *ctx, int in, int port __unused, 356 int bytes, uint32_t *eax, void *arg __unused) 357 { 358 if (bytes != 1) 359 return (-1); 360 361 pthread_mutex_lock(&pm_lock); 362 if (in) 363 *eax = gpe0_enabled; 364 else { 365 gpe0_enabled = (*eax & gpe0_valid); 366 sci_update(ctx); 367 } 368 pthread_mutex_unlock(&pm_lock); 369 return (0); 370 } 371 INOUT_PORT(gpe0_en, IO_GPE0_EN, IOPORT_F_INOUT, gpe0_en); 372 373 /* 374 * ACPI SMI Command Register 375 * 376 * This write-only register is used to enable and disable ACPI. 377 */ 378 static int 379 smi_cmd_handler(struct vmctx *ctx, int in, int port __unused, 380 int bytes, uint32_t *eax, void *arg __unused) 381 { 382 383 assert(!in); 384 if (bytes != 1) 385 return (-1); 386 387 pthread_mutex_lock(&pm_lock); 388 switch (*eax) { 389 case BHYVE_ACPI_ENABLE: 390 pm1_control |= PM1_SCI_EN; 391 #ifdef __FreeBSD__ 392 if (power_button == NULL) { 393 power_button = mevent_add(SIGTERM, EVF_SIGNAL, 394 power_button_handler, ctx); 395 old_power_handler = signal(SIGTERM, SIG_IGN); 396 } 397 #endif 398 break; 399 case BHYVE_ACPI_DISABLE: 400 pm1_control &= ~PM1_SCI_EN; 401 #ifdef __FreeBSD__ 402 if (power_button != NULL) { 403 mevent_delete(power_button); 404 power_button = NULL; 405 signal(SIGTERM, old_power_handler); 406 } 407 #endif 408 break; 409 } 410 pthread_mutex_unlock(&pm_lock); 411 return (0); 412 } 413 INOUT_PORT(smi_cmd, SMI_CMD, IOPORT_F_OUT, smi_cmd_handler); 414 #ifdef __FreeBSD__ 415 SYSRES_IO(SMI_CMD, 1); 416 #endif 417 418 void 419 sci_init(struct vmctx *ctx) 420 { 421 422 /* 423 * Mark ACPI's SCI as level trigger and bump its use count 424 * in the PIRQ router. 425 */ 426 pci_irq_use(SCI_INT); 427 vm_isa_set_irq_trigger(ctx, SCI_INT, LEVEL_TRIGGER); 428 429 #ifndef __FreeBSD__ 430 { 431 /* 432 * Install SIGTERM signal handler for graceful power off. 433 */ 434 struct sigaction act; 435 436 pwr_ctx = ctx; 437 act.sa_flags = 0; 438 act.sa_sigaction = power_button_handler; 439 (void) sigaction(SIGTERM, &act, NULL); 440 } 441 #endif 442 } 443 444 #ifndef __FreeBSD__ 445 void pmtmr_init(struct vmctx *ctx) 446 { 447 int err; 448 449 /* Attach in-kernel PM timer emulation to correct IO port */ 450 err = vm_pmtmr_set_location(ctx, IO_PMTMR); 451 assert(err == 0); 452 } 453 #endif 454