acpica/acpica — pull request #21 by zetalog (2014-03-19 02:40:51+00:00)
Title: Linux tables

Let me try the github functionality.

There are 2 requirements reported from Linux community and we haven't
addressed all of them in ACPICA yet:

1. Mapping strategy for early boot stage
In Linux during early boot stages, there are booting code using ACPI
tables. During this stage, tables are mapped using early_ioremap(), the
pointers returned by this API are not safe to be used after this stage,
so the mapped pointers should not be stored in acpi_gbl_root_table_list.
This is handled with code invoking acpi_tb_delete_table() here and there
in ACPICA and a global variable acpi_gbl_permanent_mmap in Linux to
distinguish the 2 stages.
2. Freeing table mappings when no users
There are large tables in the world, it is not good always mapping them
in the virtual address space even there is no users interested in them.
But currently for Linux, it is impossible to achieve this, as the API
acpi_get_table() will always map the tables and never unmap them. So
if someone reads the ACPI tables accesible through Linux
/sys/firmware/acpi/tables, they will never get unmapped.

This patchset purifies the code in ACPICA that is supporting requirement 1
and implements requirement 2 by enfocing these rules:
1. ACPICA never fills acpi_table_desc.pointer if it is not interested in
this table (thus only tables containing definition blocks and FACS will
have this memeber filled).
2. ACPICA splits the state of acpi_table_desc stored in
acpi_gbl_root_table_list into "INSTALLED" and "VALIDATED":
1. "INSTALLED": in this state, acpi_table_desc.adress is valid and
acpi_table_desc.pointer is ensured to be NULL. So that ACPICA will
never be interested in the ACPI tables during early boot stage (i.e.,
during acpi_initialize_tables()).
2. "VALIDATED": in this state, acpi_table_desc.pointer is valid. Such
state will only appear during acpi_load_tables()/acpi_load_table()
and Load/LoadTable opcodes executions.

As code in ACPICA that is supporting requirement 1 is ambigious and easily
leaves bugs (some of them are fixed in this series), this patch makes
requirement 1 supporting code clearer by introducing the following APIs:
1. acpi_tb_install_table:
Table is in "INSTALLED" state after calling this function, thus
acpi_table_desc.pointer is NULL while acpi_table_desc.address is filled.
2. acpi_tb_uninstall_table:
The reversal of acpi_tb_install_table.
3. acpi_tb_validate_table:
Table is in "VALIDATED" state after calling this function, thus
acpi_table_desc.address and acpi_table_desc.pointer are all filled.
4. acpi_tb_invalidate_table:
The reversal of acpi_tb_invalidate_table.
5. acpi_tb_acquire_table:
When dealing with a acpi_table_header that is not maintained by
acpi_gbl_root_table_list, this internal API is used instead to make code
more readable.
6. acpi_tb_release_table:
The reversal of acpi_tb_acquire_table.
7. acpi_tb_override_table:
This function is renamed from acpi_tb_table_override(). Table is
remained in "INSTALLED" state after calling this function.
8. acpi_tb_verify_table:
This function is a combination of signature/checksum verification and
table validation. All tables are ensured to be verified before
installation and thus they are only validated after installation and
the verification needn't be called again.
The original acpi_tb_delete_table() invocations are replaced by either
acpi_tb_uninstall_table() or acpi_tb_invalidate_table() according to the
context where the original acpi_tb_delete_table() is invoked.
The original acpi_tb_verify_table() invocations are replaced by either
acpi_tb_verify_table() or acpi_tb_validate_table() according to the
context where the original acpi_tb_verify_table() is invoked.
The original acpi_tb_add_table() has been modified to accomodate to all
table loading invocations.

There are several trivial issues fixed in this patchset:
1. The acpi_table_desc.address is not synchronized with
acpi_table_desc.flags. Some ACPI_TABLE_ORIGIN_ALLOCATED address can not
be validated again after calling acpi_tb_delete_table().
2. There are memory leaks in acpi_tb_add_table().
3. There are redundant logics in acpi_tb_add_table() and
acpi_tb_parse_root_table() that can be merged.
4. Table checksums are not always been verified before installation.

After applying these series:
1. ACPICA handles table states in the following style:
===========================================================================
Stage Early - acpi_initialize_tables()
---------------------------------------------------------------------------
UNINSTALLED
acpi_tb_install_fixed_table(DSDT/FACS)/acpi_tb_install_non_fixed_table(others)
acpi_tb_verify_table(tmp_table_desc) <- checksums are verified only once and for all kinds of tables before installation
acpi_tb_validate_table(tmp_table_desc)
acpi_tb_override_table(tmp_table_desc) <- overrides happens before installation
acpi_tb_install_table(gbl_table_desc)
acpi_tb_invalidate_table(tmp_table_desc)
INSTALLED
===========================================================================
Stage Late - acpi_load_tables()
---------------------------------------------------------------------------
INSTALLED (All non DSDT/SSDT/PSDT/OEM/FACS remains INSTALLED as ACPICA does
not use them)
acpi_tb_validate_table(gbl_table_desc of DSDT/SSDT/PSDT/OEM/FACS)
VALIDATED (only DSDT/SSDT/PSDT/OEM/FACS)
===========================================================================

The patchset has been unit tested in AcpiExec by:
1. Initializing;
2. Executing exc_tbl ASLTS tests;
3. Executing "Load" command.
So that all original AcpiTbInstallTable() and AcpiTbOverrideTable()
invocations are covered.
It has also been linuxized and tested by booting an x86-64 machine with
CONFIG_ACPI enabled. There are "Load" opcodes executed in the kernel log.