From: Waldemar Kozaczuk <[email protected]>
Committer: Nadav Har'El <[email protected]>
Branch: master
Make OSv boot without ACPI present
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]>
---
diff --git a/arch/x64/power.cc b/arch/x64/power.cc
--- 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,25 @@ 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();
- }
- status = AcpiEnterSleepState(ACPI_STATE_S5);
- if (ACPI_FAILURE(status)) {
- debug("AcpiEnterSleepState 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();
+ }
+ } 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
+ //TODO: Figure out if there is another method we could try
+ // first to to power off on non-firecracker platforms
+ // without using ACPI
+ processor::outb(0xfe, 0x64);
}
// We shouldn't get here on x86.
diff --git a/arch/x64/smp.cc b/arch/x64/smp.cc
--- 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>
@@ -72,9 +73,26 @@ void parse_madt()
debug(fmt("%d CPUs detected\n") % nr_cpus);
}
+void parse_mp_table()
+{
+ //TODO: This a nasty hack to support single vCPU. Eventually we should
+ // parse out equivalent information about all vCPUs from MP table. For
+ // details please see
https://wiki.osdev.org/Symmetric_Multiprocessing#Finding_information_using_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);
+}
+
void smp_init()
{
- parse_madt();
+ if (acpi::is_enabled()) {
+ parse_madt();
+ } else {
+ parse_mp_table();
+ }
+
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
--- a/drivers/acpi.cc
+++ b/drivers/acpi.cc
@@ -539,8 +539,21 @@ namespace acpi {
static ACPI_TABLE_DESC TableArray[ACPI_MAX_INIT_TABLES];
+static bool enabled = false;
+
+bool is_enabled() {
+ return enabled;
+}
+
void early_init()
{
+ ACPI_SIZE rsdp;
+ auto st = AcpiFindRootPointer(&rsdp);
+ if (ACPI_FAILURE(st)) {
+ acpi_w("Warning: Failed to find ACPI root pointer!\n");
+ return;
+ }
+
ACPI_STATUS status;
status = AcpiInitializeTables(TableArray, ACPI_MAX_INIT_TABLES, TRUE);
@@ -569,6 +582,8 @@ void early_init()
acpi_e("AcpiLoadTables failed: %s\n", AcpiFormatException(status));
return;
}
+
+ enabled = true;
}
UINT32 acpi_poweroff(void *unused)
@@ -581,6 +596,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
--- 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
--- 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;
--
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.