Get system state configuration from QEMU and patch DSDT with it.
QEMU may want to disable guest's S3/S4 support and it wants to distinguish
between regular powerdown and S4 powerdown. To support that new fw_cfg
option was added that passes supported system states and what value should
guest use to enter each state. States are passed in 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 7 bits. Patch also detects old QEMU and uses
values that work in backwards compatible way there.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
index 15299ee..2060686 100644
--- a/src/acpi-dsdt.dsl
+++ b/src/acpi-dsdt.dsl
@@ -664,38 +664,6 @@
}
}
-
-/****************************************************************
- * Suspend
- ****************************************************************/
-
- /*
- * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
- * must match piix4 emulation.
- */
- Name (\_S3, Package (0x04)
- {
- 0x01, /* PM1a_CNT.SLP_TYP */
- 0x01, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- Name (\_S4, Package (0x04)
- {
- Zero, /* PM1a_CNT.SLP_TYP */
- Zero, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- Name (\_S5, Package (0x04)
- {
- Zero, /* PM1a_CNT.SLP_TYP */
- Zero, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
-
-
/****************************************************************
* CPU hotplug
****************************************************************/
diff --git a/src/acpi.c b/src/acpi.c
index 365267b..55e4607 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -518,6 +518,8 @@
static void* build_pcihp(void)
{
+ char *sys_states;
+ int sys_state_size;
u32 rmvc_pcrm;
int i;
@@ -549,6 +551,19 @@
}
}
+ sys_states = romfile_loadfile("etc/system-states", &sys_state_size);
+ if (!sys_states || sys_state_size != 6)
+ sys_states = (char[]){128, 0, 0, 129, 128, 128};
+
+ if (!(sys_states[3] & 128))
+ ssdt[acpi_s3_name[0]] = 'X';
+ if (!(sys_states[4] & 128))
+ ssdt[acpi_s4_name[0]] = 'X';
+ else
+ ssdt[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = sys_states[4] & 127;
+ ((struct acpi_table_header*)ssdt)->checksum = 0;
+ ((struct acpi_table_header*)ssdt)->checksum -= checksum(ssdt, sizeof(ssdp_pcihp_aml));
+
return ssdt;
}
diff --git a/src/ssdt-pcihp.dsl b/src/ssdt-pcihp.dsl
index 4b435b8..12555e2 100644
--- a/src/ssdt-pcihp.dsl
+++ b/src/ssdt-pcihp.dsl
@@ -95,4 +95,40 @@
gen_pci_hotplug(1f)
}
}
+
+ Scope(\) {
+/****************************************************************
+ * Suspend
+ ****************************************************************/
+
+ /*
+ * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
+ * must match piix4 emulation.
+ */
+
+ ACPI_EXTRACT_NAME_STRING acpi_s3_name
+ Name (_S3, Package (0x04)
+ {
+ One, /* PM1a_CNT.SLP_TYP */
+ One, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ ACPI_EXTRACT_NAME_STRING acpi_s4_name
+ ACPI_EXTRACT_PKG_START acpi_s4_pkg
+ Name (_S4, Package (0x04)
+ {
+ 0x2, /* PM1a_CNT.SLP_TYP */
+ 0x2, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ Name (_S5, Package (0x04)
+ {
+ Zero, /* PM1a_CNT.SLP_TYP */
+ Zero, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ }
}