459ae5ea5a
This patch adds two things. First it allows QEMU to distinguish between regular powerdown and S4 powerdown. Later separate QMP notification will be added for S4 powerdown. Second it allows S3/S4 states to be disabled from QEMU command line. Some guests known to be broken with regards to power management, but allow to use it anyway. Using new properties management will be able to disable S3/S4 for such guests. Supported system state are passed to a firmware using new fw_cfg file. The file contains 6 byte array. Each byte represents one system state. If byte at offset X has its MSB set it means that system state X is supported and to enter it guest should use the value from lowest 3 bits. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
156 lines
4.8 KiB
C
156 lines
4.8 KiB
C
#ifndef QEMU_HW_ACPI_H
|
|
#define QEMU_HW_ACPI_H
|
|
/*
|
|
* Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
|
|
* VA Linux Systems Japan K.K.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/* from linux include/acpi/actype.h */
|
|
/* Default ACPI register widths */
|
|
|
|
#define ACPI_GPE_REGISTER_WIDTH 8
|
|
#define ACPI_PM1_REGISTER_WIDTH 16
|
|
#define ACPI_PM2_REGISTER_WIDTH 8
|
|
#define ACPI_PM_TIMER_WIDTH 32
|
|
|
|
/* PM Timer ticks per second (HZ) */
|
|
#define PM_TIMER_FREQUENCY 3579545
|
|
|
|
|
|
/* ACPI fixed hardware registers */
|
|
|
|
/* from linux/drivers/acpi/acpica/aclocal.h */
|
|
/* Masks used to access the bit_registers */
|
|
|
|
/* PM1x_STS */
|
|
#define ACPI_BITMASK_TIMER_STATUS 0x0001
|
|
#define ACPI_BITMASK_BUS_MASTER_STATUS 0x0010
|
|
#define ACPI_BITMASK_GLOBAL_LOCK_STATUS 0x0020
|
|
#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100
|
|
#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200
|
|
#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400
|
|
#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
|
|
#define ACPI_BITMASK_WAKE_STATUS 0x8000
|
|
|
|
#define ACPI_BITMASK_ALL_FIXED_STATUS (\
|
|
ACPI_BITMASK_TIMER_STATUS | \
|
|
ACPI_BITMASK_BUS_MASTER_STATUS | \
|
|
ACPI_BITMASK_GLOBAL_LOCK_STATUS | \
|
|
ACPI_BITMASK_POWER_BUTTON_STATUS | \
|
|
ACPI_BITMASK_SLEEP_BUTTON_STATUS | \
|
|
ACPI_BITMASK_RT_CLOCK_STATUS | \
|
|
ACPI_BITMASK_WAKE_STATUS)
|
|
|
|
/* PM1x_EN */
|
|
#define ACPI_BITMASK_TIMER_ENABLE 0x0001
|
|
#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE 0x0020
|
|
#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100
|
|
#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200
|
|
#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400
|
|
#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
|
|
|
|
/* PM1x_CNT */
|
|
#define ACPI_BITMASK_SCI_ENABLE 0x0001
|
|
#define ACPI_BITMASK_BUS_MASTER_RLD 0x0002
|
|
#define ACPI_BITMASK_GLOBAL_LOCK_RELEASE 0x0004
|
|
#define ACPI_BITMASK_SLEEP_TYPE 0x1C00
|
|
#define ACPI_BITMASK_SLEEP_ENABLE 0x2000
|
|
|
|
/* PM2_CNT */
|
|
#define ACPI_BITMASK_ARB_DISABLE 0x0001
|
|
|
|
/* structs */
|
|
typedef struct ACPIPMTimer ACPIPMTimer;
|
|
typedef struct ACPIPM1EVT ACPIPM1EVT;
|
|
typedef struct ACPIPM1CNT ACPIPM1CNT;
|
|
typedef struct ACPIGPE ACPIGPE;
|
|
typedef struct ACPIREGS ACPIREGS;
|
|
|
|
typedef void (*acpi_update_sci_fn)(ACPIREGS *ar);
|
|
|
|
struct ACPIPMTimer {
|
|
QEMUTimer *timer;
|
|
int64_t overflow_time;
|
|
|
|
acpi_update_sci_fn update_sci;
|
|
};
|
|
|
|
struct ACPIPM1EVT {
|
|
uint16_t sts;
|
|
uint16_t en;
|
|
};
|
|
|
|
struct ACPIPM1CNT {
|
|
uint16_t cnt;
|
|
};
|
|
|
|
struct ACPIGPE {
|
|
uint32_t blk;
|
|
uint8_t len;
|
|
|
|
uint8_t *sts;
|
|
uint8_t *en;
|
|
};
|
|
|
|
struct ACPIREGS {
|
|
ACPIPMTimer tmr;
|
|
ACPIGPE gpe;
|
|
struct {
|
|
ACPIPM1EVT evt;
|
|
ACPIPM1CNT cnt;
|
|
} pm1;
|
|
Notifier wakeup;
|
|
};
|
|
|
|
/* PM_TMR */
|
|
void acpi_pm_tmr_update(ACPIREGS *ar, bool enable);
|
|
void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar);
|
|
uint32_t acpi_pm_tmr_get(ACPIREGS *ar);
|
|
void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci);
|
|
void acpi_pm_tmr_reset(ACPIREGS *ar);
|
|
|
|
#include "qemu-timer.h"
|
|
static inline int64_t acpi_pm_tmr_get_clock(void)
|
|
{
|
|
return muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
|
|
get_ticks_per_sec());
|
|
}
|
|
|
|
/* PM1a_EVT: piix and ich9 don't implement PM1b. */
|
|
uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar);
|
|
void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val);
|
|
void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val);
|
|
void acpi_pm1_evt_power_down(ACPIREGS *ar);
|
|
void acpi_pm1_evt_reset(ACPIREGS *ar);
|
|
|
|
/* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
|
|
void acpi_pm1_cnt_init(ACPIREGS *ar);
|
|
void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4);
|
|
void acpi_pm1_cnt_update(ACPIREGS *ar,
|
|
bool sci_enable, bool sci_disable);
|
|
void acpi_pm1_cnt_reset(ACPIREGS *ar);
|
|
|
|
/* GPE0 */
|
|
void acpi_gpe_init(ACPIREGS *ar, uint8_t len);
|
|
void acpi_gpe_blk(ACPIREGS *ar, uint32_t blk);
|
|
void acpi_gpe_reset(ACPIREGS *ar);
|
|
|
|
void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val);
|
|
uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr);
|
|
|
|
#endif /* !QEMU_HW_ACPI_H */
|