On Fri, Feb 22, 2019 at 4:13 PM Waldemar Kozaczuk <[email protected]> wrote:
> 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 | 30 +++++++++++++++++++++--------- > arch/x64/smp.cc | 20 +++++++++++++++++++- > drivers/acpi.cc | 19 +++++++++++++++++++ > drivers/acpi.hh | 1 + > drivers/pvpanic.cc | 4 ++++ > 5 files changed, 64 insertions(+), 10 deletions(-) > > diff --git a/arch/x64/power.cc b/arch/x64/power.cc > index 81849335..61d56bcc 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,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); > I'll commit this patch for now, but I'm guessing this will have to change later. The firecracker guys don't seem to love this behavior either: https://github.com/firecracker-microvm/firecracker/issues/598 > } > > // We shouldn't get here on x86. > diff --git a/arch/x64/smp.cc b/arch/x64/smp.cc > index 073ef206..2869d6e2 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> > @@ -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 > index 506ca68f..4a38a32e 100644 > --- 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 > 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. > -- 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.
