This patch makes OSv boot without requiring ACPI
to be present which for example is the case on firecracker.

We simply treat failure to find ACPI root pointer
as an indicator that ACPI is not available and
mark it off as such. Also if ACPI is off we power OSv off
using non-ACPI method and skip probing panic driver as it
relies on ACPI as well.

Lastly we skip MADT table parsing if APCI is off and
for now assume there is single vCPU only. Eventually
we should parse vCPU information from MP table as
an alternative.

Signed-off-by: Waldemar Kozaczuk <[email protected]>
---
 arch/x64/power.cc  | 26 ++++++++++++++++++--------
 arch/x64/smp.cc    | 15 ++++++++++++++-
 drivers/acpi.cc    | 17 +++++++++++++++--
 drivers/acpi.hh    |  1 +
 drivers/pvpanic.cc |  4 ++++
 5 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/arch/x64/power.cc b/arch/x64/power.cc
index 81849335..0dc1ebb8 100644
--- a/arch/x64/power.cc
+++ b/arch/x64/power.cc
@@ -15,6 +15,8 @@ extern "C" {
 #include "acpi.h"
 }
 
+#include <drivers/acpi.hh>
+
 namespace osv {
 
 void halt(void)
@@ -27,15 +29,23 @@ void halt(void)
 
 void poweroff(void)
 {
-    ACPI_STATUS status = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
-    if (ACPI_FAILURE(status)) {
-        debug("AcpiEnterSleepStatePrep failed: %s\n", 
AcpiFormatException(status));
-        halt();
+    if (acpi::is_enabled()) {
+        ACPI_STATUS status = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
+        if (ACPI_FAILURE(status)) {
+            debug("AcpiEnterSleepStatePrep failed: %s\n", 
AcpiFormatException(status));
+            halt();
+        }
+        status = AcpiEnterSleepState(ACPI_STATE_S5);
+        if (ACPI_FAILURE(status)) {
+            debug("AcpiEnterSleepState failed: %s\n", 
AcpiFormatException(status));
+            halt();
+        }
     }
-    status = AcpiEnterSleepState(ACPI_STATE_S5);
-    if (ACPI_FAILURE(status)) {
-        debug("AcpiEnterSleepState failed: %s\n", AcpiFormatException(status));
-        halt();
+    else {
+        // On hypervisors that do not support ACPI like firecracker we
+        // resort to a reset using the 8042 PS/2 Controller ("keyboard 
controller")
+        // as a way to shutdown the VM
+        processor::outb(0xfe, 0x64);
     }
 
     // We shouldn't get here on x86.
diff --git a/arch/x64/smp.cc b/arch/x64/smp.cc
index 073ef206..883216d3 100644
--- a/arch/x64/smp.cc
+++ b/arch/x64/smp.cc
@@ -15,6 +15,7 @@
 extern "C" {
 #include "acpi.h"
 }
+#include <drivers/acpi.hh>
 #include <boost/intrusive/parent_from_member.hpp>
 #include <osv/debug.hh>
 #include <osv/sched.hh>
@@ -74,7 +75,19 @@ void parse_madt()
 
 void smp_init()
 {
-    parse_madt();
+    if (acpi::is_enabled()) {
+        parse_madt();
+    }
+    else {
+        //TODO: This a nasty hack to support single vCPU. Eventually we should
+        // parse out equivalent information about all vCPUs from MP table
+        auto c = new sched::cpu(0);
+        c->arch.apic_id = 0;
+        c->arch.initstack.next = smp_stack_free;
+        smp_stack_free = &c->arch.initstack;
+        sched::cpus.push_back(c);
+    }
+
     sched::current_cpu = sched::cpus[0];
     for (auto c : sched::cpus) {
         c->incoming_wakeups = 
aligned_array_new<sched::cpu::incoming_wakeup_queue>(sched::cpus.size());
diff --git a/drivers/acpi.cc b/drivers/acpi.cc
index 506ca68f..451e8f79 100644
--- a/drivers/acpi.cc
+++ b/drivers/acpi.cc
@@ -52,7 +52,7 @@ ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer()
     ACPI_SIZE rsdp;
     auto st = AcpiFindRootPointer(&rsdp);
     if (ACPI_FAILURE(st)) {
-        abort();
+        return 0;
     }
     return rsdp;
 }
@@ -539,13 +539,20 @@ namespace acpi {
 
 static ACPI_TABLE_DESC TableArray[ACPI_MAX_INIT_TABLES];
 
+static bool enabled = false;
+
+bool is_enabled() {
+    return enabled;
+}
+
 void early_init()
 {
     ACPI_STATUS status;
 
     status = AcpiInitializeTables(TableArray, ACPI_MAX_INIT_TABLES, TRUE);
     if (ACPI_FAILURE(status)) {
-        acpi_e("AcpiInitializeTables failed: %s\n", 
AcpiFormatException(status));
+        //TODO: Report error differently -> AcpiFormatException seems to 
trigger exit on firecracker
+        //acpi_e("AcpiInitializeTables failed: %s\n", 
AcpiFormatException(status));
         return;
     }
 
@@ -569,6 +576,8 @@ void early_init()
         acpi_e("AcpiLoadTables failed: %s\n", AcpiFormatException(status));
         return;
     }
+
+    enabled = true;
 }
 
 UINT32 acpi_poweroff(void *unused)
@@ -581,6 +590,10 @@ UINT32 acpi_poweroff(void *unused)
 // The following function comes from the documentation example page 262
 void init()
 {
+    if (!enabled) {
+        return;
+    }
+
     ACPI_STATUS status;
 
 
diff --git a/drivers/acpi.hh b/drivers/acpi.hh
index 8373745b..10f82f58 100644
--- a/drivers/acpi.hh
+++ b/drivers/acpi.hh
@@ -12,6 +12,7 @@
 namespace acpi {
 
 void init();
+bool is_enabled();
 
 }
 
diff --git a/drivers/pvpanic.cc b/drivers/pvpanic.cc
index 2f114fb3..e643b5a0 100644
--- a/drivers/pvpanic.cc
+++ b/drivers/pvpanic.cc
@@ -21,6 +21,10 @@ static u32 port;
 
 void probe_and_setup()
 {
+    if (!acpi::is_enabled()) {
+        return;
+    }
+
     ACPI_BUFFER results;
     ACPI_OBJECT obj;
     ACPI_STATUS status;
-- 
2.19.1

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to