WIP move acpica to just the suspend syscall
Change-Id: I411583a3e21bd655efe146b011eb60dc8aa3effa
diff --git a/kernel/arch/x86/include/arch/x86/acpi.h b/kernel/arch/x86/include/arch/x86/acpi.h
index 7e32978..005a307 100644
--- a/kernel/arch/x86/include/arch/x86/acpi.h
+++ b/kernel/arch/x86/include/arch/x86/acpi.h
@@ -6,20 +6,16 @@
#pragma once
-#include <acpica/acpi.h>
#include <arch/x86/bootstrap16.h>
#include <stdint.h>
-__BEGIN_CDECLS
-
// Initiates a transition to the requested ACPI S-state.
//
// This must not be called before bootstrap16 is configured to handle the resume.
//
// This must be called from a kernel thread, unless it is a transition to
// S5 (poweroff). Failure to do so may result in loss of usermode register state.
-ACPI_STATUS x86_acpi_transition_s_state(struct x86_realmode_entry_data_registers* regs,
+extern "C"
+uint32_t x86_acpi_transition_s_state(struct x86_realmode_entry_data_registers* regs,
uint8_t target_s_state,
uint8_t sleep_type_a, uint8_t sleep_type_b);
-
-__END_CDECLS
diff --git a/kernel/lib/acpi_lite/acpi_lite.cpp b/kernel/lib/acpi_lite/acpi_lite.cpp
index f149862..29bc868 100644
--- a/kernel/lib/acpi_lite/acpi_lite.cpp
+++ b/kernel/lib/acpi_lite/acpi_lite.cpp
@@ -145,7 +145,11 @@
}
if (!memcmp(sig, header->sig, 4)) {
- return header;
+ // validate the checksum
+ uint8_t c = acpi_checksum(header, header->length);
+ if (c == 0) {
+ return header;
+ }
}
}
diff --git a/kernel/lib/acpi_lite/include/lib/acpi_lite.h b/kernel/lib/acpi_lite/include/lib/acpi_lite.h
index e26f72d..c7867dd 100644
--- a/kernel/lib/acpi_lite/include/lib/acpi_lite.h
+++ b/kernel/lib/acpi_lite/include/lib/acpi_lite.h
@@ -51,6 +51,17 @@
};
} __PACKED;
+struct acpi_generic_address_ {
+ uint8_t address_space_id;
+ uint8_t register_bit_width;
+ uint8_t register_bit_offset;
+ uint8_t access_size;
+ uint64_t address;
+} __PACKED;
+
+#define ACPI_ADDR_SPACE_MEMORY 0
+#define ACPI_ADDR_SPACE_IO 1
+
#define ACPI_RSDT_SIG "RSDT"
#define ACPI_XSDT_SIG "XSDT"
@@ -68,14 +79,7 @@
uint8_t length;
} __PACKED;
-struct acpi_generic_address_ {
- uint8_t address_space_id;
- uint8_t register_bit_width;
- uint8_t register_bit_offset;
- uint8_t access_size;
- uint64_t address;
-} __PACKED;
-
+#define ACPI_HPET_SIG "HPET"
struct acpi_hpet_table {
acpi_sdt_header header;
uint32_t id;
@@ -95,7 +99,7 @@
// MADT table describes processors and interrupt controllers
// type 0: local apic
-// #define ACPI_MADT_TYPE_LOCAL_APIC 0
+#define ACPI_MADT_TYPE_LOCAL_APIC 0
struct acpi_madt_local_apic_entry {
acpi_sub_table_header header;
uint8_t processor_id;
@@ -106,7 +110,7 @@
#define ACPI_MADT_FLAG_ENABLED 0x1
// type 1: io apic
-// #define ACPI_MADT_TYPE_IO_APIC 1
+#define ACPI_MADT_TYPE_IO_APIC 1
struct acpi_madt_io_apic_entry {
acpi_sub_table_header header;
uint8_t io_apic_id;
@@ -116,7 +120,7 @@
} __PACKED;
// type 2: interrupt source override
-// #define ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE 2
+#define ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE 2
struct acpi_madt_int_source_override_entry {
acpi_sub_table_header header;
uint8_t bus;
diff --git a/kernel/platform/pc/acpi.cpp b/kernel/platform/pc/acpi.cpp
index 8cf93bc..721658a 100644
--- a/kernel/platform/pc/acpi.cpp
+++ b/kernel/platform/pc/acpi.cpp
@@ -16,68 +16,6 @@
#define LOCAL_TRACE 1
-#include <acpica/acpi.h>
-
-#if 0
-#define ACPI_MAX_INIT_TABLES 32
-static ACPI_TABLE_DESC acpi_tables[ACPI_MAX_INIT_TABLES];
-static bool acpi_initialized = false;
-
-/**
- * @brief Initialize early-access ACPI tables
- *
- * This function enables *only* the ACPICA Table Manager subsystem.
- * The rest of the ACPI subsystem will remain uninitialized.
- */
-void platform_init_acpi_tables(uint level) {
- DEBUG_ASSERT(!acpi_initialized);
-
- ACPI_STATUS status;
- status = AcpiInitializeTables(acpi_tables, ACPI_MAX_INIT_TABLES, FALSE);
-
- if (status == AE_NOT_FOUND) {
- TRACEF("WARNING: could not find ACPI tables\n");
- return;
- } else if (status == AE_NO_MEMORY) {
- TRACEF("WARNING: could not initialize ACPI tables\n");
- return;
- } else if (status != AE_OK) {
- TRACEF("WARNING: could not initialize ACPI tables for unknown reason\n");
- return;
- }
-
- acpi_initialized = true;
- LTRACEF("ACPI tables initialized\n");
-}
-
-/* initialize ACPI tables as soon as we have a working VM */
-LK_INIT_HOOK(acpi_tables, &platform_init_acpi_tables, LK_INIT_LEVEL_VM + 1);
-
-static zx_status_t acpi_get_madt_record_limits(uintptr_t* start, uintptr_t* end) {
- ACPI_TABLE_HEADER* table = NULL;
- ACPI_STATUS status = AcpiGetTable((char*)ACPI_SIG_MADT, 1, &table);
- if (status != AE_OK) {
- TRACEF("could not find MADT\n");
- return ZX_ERR_NOT_FOUND;
- }
- ACPI_TABLE_MADT* madt = (ACPI_TABLE_MADT*)table;
- uintptr_t records_start = ((uintptr_t)madt) + sizeof(*madt);
- uintptr_t records_end = ((uintptr_t)madt) + madt->Header.Length;
- if (records_start >= records_end) {
- TRACEF("MADT wraps around address space\n");
- return ZX_ERR_INTERNAL;
- }
- // Shouldn't be too many records
- if (madt->Header.Length > 4096) {
- TRACEF("MADT suspiciously long: %u\n", madt->Header.Length);
- return ZX_ERR_INTERNAL;
- }
- *start = records_start;
- *end = records_end;
- return ZX_OK;
-}
-#endif
-
/* @brief Enumerate all functioning CPUs and their APIC IDs
*
* If apic_ids is NULL, just returns the number of logical processors
@@ -182,7 +120,7 @@
}
uint32_t count = 0;
- acpi_process_madt_entries_etc(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+ acpi_process_madt_entries_etc(ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE,
[isos, &count, len](const void *_entry, size_t entry_len) {
auto entry = static_cast<const acpi_madt_int_source_override_entry*>(_entry);
@@ -241,34 +179,34 @@
* @return ZX_OK on success.
*/
zx_status_t platform_find_hpet(struct acpi_hpet_descriptor* hpet) {
-#if 0
- ACPI_TABLE_HEADER* table = NULL;
- ACPI_STATUS status = AcpiGetTable((char*)ACPI_SIG_HPET, 1, &table);
- if (status != AE_OK) {
- TRACEF("could not find HPET\n");
- return ZX_ERR_NOT_FOUND;
- }
- ACPI_TABLE_HPET* hpet_tbl = (ACPI_TABLE_HPET*)table;
- if (hpet_tbl->Header.Length != sizeof(ACPI_TABLE_HPET)) {
- TRACEF("Unexpected HPET table length\n");
+ const acpi_sdt_header* header = acpi_get_table_by_sig(ACPI_HPET_SIG);
+ if (!header) {
return ZX_ERR_NOT_FOUND;
}
- hpet->minimum_tick = hpet_tbl->MinimumTick;
- hpet->sequence = hpet_tbl->Sequence;
- hpet->address = hpet_tbl->Address.Address;
- switch (hpet_tbl->Address.SpaceId) {
- case ACPI_ADR_SPACE_SYSTEM_IO:
+ if (header->revision != 1) {
+ return ZX_ERR_NOT_FOUND;
+ }
+
+ if (header->length != sizeof(acpi_hpet_table)) {
+ return ZX_ERR_NOT_FOUND;
+ }
+
+ const acpi_hpet_table* table = reinterpret_cast<const acpi_hpet_table*>(header);
+
+ hpet->minimum_tick = table->minimum_tick;
+ hpet->sequence = table->sequence;
+ hpet->address = table->address.address;
+ switch (table->address.address_space_id) {
+ case ACPI_ADDR_SPACE_IO:
hpet->port_io = true;
break;
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+ case ACPI_ADDR_SPACE_MEMORY:
hpet->port_io = false;
break;
default:
return ZX_ERR_NOT_SUPPORTED;
}
+ TRACE;
return ZX_OK;
-#endif
-
- return ZX_ERR_NOT_SUPPORTED;
}
diff --git a/kernel/platform/pc/hpet.cpp b/kernel/platform/pc/hpet.cpp
index e58fc02..f96e404 100644
--- a/kernel/platform/pc/hpet.cpp
+++ b/kernel/platform/pc/hpet.cpp
@@ -105,6 +105,10 @@
_hpet_ticks_per_ms = 1000000000000ULL / tick_period_in_fs;
min_ticks_ahead = 100000000ULL / tick_period_in_fs;
hpet_present = true;
+
+ dprintf(INFO, "HPET: detected at %#" PRIx64 " ticks per ms %" PRIu64 " num timers %hhu\n",
+ hpet_desc.address, _hpet_ticks_per_ms, num_timers);
+
return;
fail:
diff --git a/kernel/platform/pc/rules.mk b/kernel/platform/pc/rules.mk
index c4ed207..04397c4 100644
--- a/kernel/platform/pc/rules.mk
+++ b/kernel/platform/pc/rules.mk
@@ -28,7 +28,6 @@
$(LOCAL_DIR)/timer.cpp \
MODULE_DEPS += \
- third_party/lib/acpica \
third_party/lib/cksum \
kernel/lib/acpi_lite \
kernel/lib/cbuf \
diff --git a/kernel/syscalls/rules.mk b/kernel/syscalls/rules.mk
index 955fca8..d576975 100644
--- a/kernel/syscalls/rules.mk
+++ b/kernel/syscalls/rules.mk
@@ -47,6 +47,8 @@
MODULE_SRCS += $(LOCAL_DIR)/system_x86.cpp \
$(LOCAL_DIR)/ddk_x86.cpp \
+MODULE_DEPS += third_party/lib/acpica
+
else ifeq ($(ARCH),arm64)
MODULE_SRCS += $(LOCAL_DIR)/system_arm64.cpp \
$(LOCAL_DIR)/ddk_arm64.cpp \
diff --git a/kernel/syscalls/system_x86.cpp b/kernel/syscalls/system_x86.cpp
index 9e84c2a..1a96c58 100644
--- a/kernel/syscalls/system_x86.cpp
+++ b/kernel/syscalls/system_x86.cpp
@@ -11,6 +11,7 @@
#include <fbl/auto_call.h>
#include <inttypes.h>
#include <kernel/timer.h>
+#include <lk/init.h>
#include <platform.h>
#include <trace.h>
#include <vm/vm_aspace.h>
@@ -28,6 +29,39 @@
namespace {
+#define ACPI_MAX_INIT_TABLES 32
+//static ACPI_TABLE_DESC acpi_tables[ACPI_MAX_INIT_TABLES];
+static bool acpi_initialized = false;
+
+/**
+ * @brief Initialize early-access ACPI tables
+ *
+ * This function enables *only* the ACPICA Table Manager subsystem.
+ * The rest of the ACPI subsystem will remain uninitialized.
+ */
+void init_acpica_tables(uint level) {
+ DEBUG_ASSERT(!acpi_initialized);
+
+ ACPI_STATUS status;
+ status = AcpiInitializeTables(nullptr, ACPI_MAX_INIT_TABLES, FALSE);
+
+ if (status == AE_NOT_FOUND) {
+ TRACEF("WARNING: could not find ACPI tables\n");
+ return;
+ } else if (status == AE_NO_MEMORY) {
+ TRACEF("WARNING: could not initialize ACPI tables\n");
+ return;
+ } else if (status != AE_OK) {
+ TRACEF("WARNING: could not initialize ACPI tables for unknown reason\n");
+ return;
+ }
+
+ acpi_initialized = true;
+ LTRACEF("ACPI tables initialized\n");
+}
+
+LK_INIT_HOOK(acpica_tables, &init_acpica_tables, LK_INIT_LEVEL_THREADING);
+
// This thread performs the work for suspend/resume. We use a separate thread
// rather than the invoking thread to let us lean on the context switch code
// path to persist all of the usermode thread state that is not saved on a plain
@@ -151,6 +185,10 @@
}
zx_status_t acpi_transition_s_state(const zx_system_powerctl_arg_t* arg) {
+ if (!acpi_initialized) {
+ return ZX_ERR_BAD_STATE;
+ }
+
uint8_t target_s_state = arg->acpi_transition_s_state.target_s_state;
uint8_t sleep_type_a = arg->acpi_transition_s_state.sleep_type_a;
uint8_t sleep_type_b = arg->acpi_transition_s_state.sleep_type_b;
@@ -192,10 +230,10 @@
DEBUG_ASSERT(target_s_state == 5);
arch_disable_ints();
- ACPI_STATUS acpi_status = x86_acpi_transition_s_state(®s, target_s_state,
+ auto acpi_status = x86_acpi_transition_s_state(®s, target_s_state,
sleep_type_a, sleep_type_b);
arch_enable_ints();
- if (acpi_status != AE_OK) {
+ if (acpi_status != 0) {
return ZX_ERR_INTERNAL;
}
}