From d3f8796887051e3975bed57bd7bc3c3def392841 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Thu, 17 Feb 2022 18:12:47 +0800
Subject: [PATCH 3/5] standard_vm: add FACS acpi table on x86 plantform

When a standard vm starts, the hardware reduced feature needs to
be turned off, so an additional FACS acpi table needs to be added

Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
---
 machine/src/standard_vm/mod.rs | 43 ++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/machine/src/standard_vm/mod.rs b/machine/src/standard_vm/mod.rs
index fe7435a..1fca3bf 100644
--- a/machine/src/standard_vm/mod.rs
+++ b/machine/src/standard_vm/mod.rs
@@ -111,6 +111,13 @@ trait StdMachineOps: AcpiBuilder {
 
         let mut xsdt_entries = Vec::new();
 
+        #[cfg(target_arch = "x86_64")]
+        {
+            let facs_addr = Self::build_facs_table(&acpi_tables, &mut loader)
+                .chain_err(|| "Failed to build ACPI FACS table")?;
+            xsdt_entries.push(facs_addr);
+        }
+
         let dsdt_addr = self
             .build_dsdt_table(&acpi_tables, &mut loader)
             .chain_err(|| "Failed to build ACPI DSDT table")?;
@@ -394,6 +401,42 @@ trait AcpiBuilder {
         Ok(fadt_begin as u64)
     }
 
+    /// Build ACPI FACS table, returns the offset of ACPI FACS table in `acpi_data`.
+    ///
+    /// # Arguments
+    ///
+    /// `acpi_data` - Bytes streams that ACPI tables converts to.
+    /// `loader` - ACPI table loader.
+    #[cfg(target_arch = "x86_64")]
+    fn build_facs_table(acpi_data: &Arc<Mutex<Vec<u8>>>, loader: &mut TableLoader) -> Result<u64>
+    where
+        Self: Sized,
+    {
+        let mut facs_data = vec![0_u8; 0x40];
+        // FACS table signature.
+        facs_data[0] = b'F';
+        facs_data[1] = b'A';
+        facs_data[2] = b'C';
+        facs_data[3] = b'S';
+        // FACS table length.
+        facs_data[4] = 0x40;
+
+        let mut locked_acpi_data = acpi_data.lock().unwrap();
+        let facs_begin = locked_acpi_data.len() as u32;
+        locked_acpi_data.extend(facs_data);
+        let facs_end = locked_acpi_data.len() as u32;
+        drop(locked_acpi_data);
+
+        loader.add_cksum_entry(
+            ACPI_TABLE_FILE,
+            facs_begin + TABLE_CHECKSUM_OFFSET,
+            facs_begin,
+            facs_end - facs_begin,
+        )?;
+
+        Ok(facs_begin as u64)
+    }
+
     /// Build ACPI XSDT table, returns the offset of ACPI XSDT table in `acpi_data`.
     ///
     /// # Arguments
-- 
2.25.1

