summaryrefslogtreecommitdiff
path: root/drivers/acpi/acpica/tbdata.c
diff options
context:
space:
mode:
authorJessica Clarke <jrtc27@jrtc27.com>2021-12-22 19:22:28 +0300
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2021-12-27 19:01:28 +0300
commit5d6e59665d8bb0f8fa4d47726a93326f8ddfb448 (patch)
treea195f97831af3aee644c44919bccb60415f36fe3 /drivers/acpi/acpica/tbdata.c
parentca25f92b72d25457653dbf2a81f322235804fb05 (diff)
downloadlinux-5d6e59665d8bb0f8fa4d47726a93326f8ddfb448.tar.xz
ACPICA: Use original pointer for virtual origin tables
ACPICA commit dfa3feffa8f760b686207d09dc880cd2f26c72af Currently the pointer to the table is cast to acpi_physical_address and later cast back to a pointer to be dereferenced. Whether or not this is supported is implementation-defined. On CHERI, and thus Arm's experimental Morello prototype architecture, pointers are represented as capabilities, which are unforgeable bounded pointers, providing always-on fine-grained spatial memory safety. This means that any pointer cast to a plain integer will lose all its associated metadata, and when cast back to a pointer it will give a null-derived pointer (one that has the same metadata as null but an address equal to the integer) that will trap on any dereference. As a result, this is an implementation where acpi_physical_address cannot be used as a hack to store real pointers. Thus, alter the lifecycle of table descriptors. Internal physical tables keep the current behaviour where only the address is set on install, and the pointer is set on acquire. Virtual tables (internal and external) now store the pointer on initialisation and use that on acquire (which will redundantly set *table_ptr to itself, but changing that is both unnecessary and overly complicated as acpi_tb_acquire_table is called with both a pointer to a variable and a pointer to Table->Pointer itself). This requires propagating the (possible) table pointer everywhere in order to make sure pointers make it through to acpi_tb_acquire_temp_table, which requires a change to the acpi_install_table interface. Instead of taking an ACPI_PHYSADDR_TYPE and a boolean indicating whether it's physical or virtual, it is now split into acpi_install_table (that takes an external virtual table pointer) and acpi_install_physical_table (that takes an ACPI_PHYSADDR_TYPE for an internal physical table address). This also has the benefit of providing a cleaner API. Link: https://github.com/acpica/acpica/commit/dfa3feff Signed-off-by: Bob Moore <robert.moore@intel.com> [ rjw: Adjust the code in tables.c to match interface changes ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/tbdata.c')
-rw-r--r--drivers/acpi/acpica/tbdata.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c
index ebbca109edcb..89f08de67e6d 100644
--- a/drivers/acpi/acpica/tbdata.c
+++ b/drivers/acpi/acpica/tbdata.c
@@ -89,14 +89,27 @@ acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
{
/*
- * Initialize the table descriptor. Set the pointer to NULL, since the
- * table is not fully mapped at this time.
+ * Initialize the table descriptor. Set the pointer to NULL for external
+ * tables, since the table is not fully mapped at this time.
*/
memset(table_desc, 0, sizeof(struct acpi_table_desc));
table_desc->address = address;
table_desc->length = table->length;
table_desc->flags = flags;
ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
+
+ switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
+ case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
+ case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
+
+ table_desc->pointer = table;
+ break;
+
+ case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
+ default:
+
+ break;
+ }
}
/*******************************************************************************
@@ -132,9 +145,7 @@ acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
- table = ACPI_CAST_PTR(struct acpi_table_header,
- ACPI_PHYSADDR_TO_PTR(table_desc->
- address));
+ table = table_desc->pointer;
break;
default:
@@ -196,6 +207,8 @@ acpi_tb_release_table(struct acpi_table_header *table,
* PARAMETERS: table_desc - Table descriptor to be acquired
* address - Address of the table
* flags - Allocation flags of the table
+ * table - Pointer to the table (required for virtual
+ * origins, optional for physical)
*
* RETURN: Status
*
@@ -208,49 +221,52 @@ acpi_tb_release_table(struct acpi_table_header *table,
acpi_status
acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
- acpi_physical_address address, u8 flags)
+ acpi_physical_address address,
+ u8 flags, struct acpi_table_header *table)
{
- struct acpi_table_header *table_header;
+ u8 mapped_table = FALSE;
switch (flags & ACPI_TABLE_ORIGIN_MASK) {
case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
/* Get the length of the full table from the header */
- table_header =
- acpi_os_map_memory(address,
- sizeof(struct acpi_table_header));
- if (!table_header) {
- return (AE_NO_MEMORY);
+ if (!table) {
+ table =
+ acpi_os_map_memory(address,
+ sizeof(struct
+ acpi_table_header));
+ if (!table) {
+ return (AE_NO_MEMORY);
+ }
+
+ mapped_table = TRUE;
}
- acpi_tb_init_table_descriptor(table_desc, address, flags,
- table_header);
- acpi_os_unmap_memory(table_header,
- sizeof(struct acpi_table_header));
- return (AE_OK);
+ break;
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
- table_header = ACPI_CAST_PTR(struct acpi_table_header,
- ACPI_PHYSADDR_TO_PTR(address));
- if (!table_header) {
- return (AE_NO_MEMORY);
+ if (!table) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- acpi_tb_init_table_descriptor(table_desc, address, flags,
- table_header);
- return (AE_OK);
+ break;
default:
- break;
+ /* Table is not valid yet */
+
+ return (AE_NO_MEMORY);
}
- /* Table is not valid yet */
+ acpi_tb_init_table_descriptor(table_desc, address, flags, table);
+ if (mapped_table) {
+ acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+ }
- return (AE_NO_MEMORY);
+ return (AE_OK);
}
/*******************************************************************************
@@ -335,7 +351,19 @@ void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
acpi_tb_release_table(table_desc->pointer, table_desc->length,
table_desc->flags);
- table_desc->pointer = NULL;
+
+ switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
+ case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
+
+ table_desc->pointer = NULL;
+ break;
+
+ case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
+ case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
+ default:
+
+ break;
+ }
return_VOID;
}
@@ -959,6 +987,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node)
*
* PARAMETERS: address - Physical address of the table
* flags - Allocation flags of the table
+ * table - Pointer to the table (required for
+ * virtual origins, optional for
+ * physical)
* override - Whether override should be performed
* table_index - Where table index is returned
*
@@ -970,7 +1001,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node)
acpi_status
acpi_tb_install_and_load_table(acpi_physical_address address,
- u8 flags, u8 override, u32 *table_index)
+ u8 flags,
+ struct acpi_table_header *table,
+ u8 override, u32 *table_index)
{
acpi_status status;
u32 i;
@@ -979,7 +1012,7 @@ acpi_tb_install_and_load_table(acpi_physical_address address,
/* Install the table and load it into the namespace */
- status = acpi_tb_install_standard_table(address, flags, TRUE,
+ status = acpi_tb_install_standard_table(address, flags, table, TRUE,
override, &i);
if (ACPI_FAILURE(status)) {
goto exit;