From: Ard Biesheuvel Date: Sun, 2 Jul 2023 09:57:34 +0000 (+0200) Subject: acpi/prmt: Use EFI runtime sandbox to invoke PRM handlers X-Git-Tag: v6.6.7~2108^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5894cf571e14fb393a4d0a82538de032127b9d8b;p=platform%2Fkernel%2Flinux-starfive.git acpi/prmt: Use EFI runtime sandbox to invoke PRM handlers Instead of bypassing the kernel's adaptation layer for performing EFI runtime calls, wire up ACPI PRM handling into it. This means these calls can no longer occur concurrently with EFI runtime calls, and will be made from the EFI runtime workqueue. It also means any page faults occurring during PRM handling will be identified correctly as originating in firmware code. Acked-by: Rafael J. Wysocki Signed-off-by: Ard Biesheuvel --- diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 00dd309b..cee82b4 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -581,7 +581,7 @@ config ACPI_VIOT config ACPI_PRMT bool "Platform Runtime Mechanism Support" - depends on EFI && (X86_64 || ARM64) + depends on EFI_RUNTIME_WRAPPERS && (X86_64 || ARM64) default y help Platform Runtime Mechanism (PRM) is a firmware interface exposing a diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 71b9ada..7020584 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -260,9 +260,9 @@ static acpi_status acpi_platformrt_space_handler(u32 function, context.static_data_buffer = handler->static_data_buffer_addr; context.mmio_ranges = module->mmio_info; - status = efi_call_virt_pointer(handler, handler_addr, - handler->acpi_param_buffer_addr, - &context); + status = efi_call_acpi_prm_handler(handler->handler_addr, + handler->acpi_param_buffer_addr, + &context); if (status == EFI_SUCCESS) { buffer->prm_status = PRM_HANDLER_SUCCESS; } else { diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index afe9248..e89484a 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -108,6 +108,12 @@ union efi_rts_args { u64 *max_size; int *reset_type; } QUERY_CAPSULE_CAPS; + + struct { + efi_status_t (__efiapi *acpi_prm_handler)(u64, void *); + u64 param_buffer_addr; + void *context; + } ACPI_PRM_HANDLER; }; struct efi_runtime_work efi_rts_work; @@ -283,6 +289,13 @@ static void efi_call_rts(struct work_struct *work) args->QUERY_CAPSULE_CAPS.max_size, args->QUERY_CAPSULE_CAPS.reset_type); break; + case EFI_ACPI_PRM_HANDLER: +#ifdef CONFIG_ACPI_PRMT + status = arch_efi_call_virt(args, ACPI_PRM_HANDLER.acpi_prm_handler, + args->ACPI_PRM_HANDLER.param_buffer_addr, + args->ACPI_PRM_HANDLER.context); + break; +#endif default: /* * Ideally, we should never reach here because a caller of this @@ -560,3 +573,21 @@ void efi_native_runtime_setup(void) efi.update_capsule = virt_efi_update_capsule; efi.query_capsule_caps = virt_efi_query_capsule_caps; } + +#ifdef CONFIG_ACPI_PRMT + +efi_status_t +efi_call_acpi_prm_handler(efi_status_t (__efiapi *handler_addr)(u64, void *), + u64 param_buffer_addr, void *context) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_queue_work(ACPI_PRM_HANDLER, handler_addr, + param_buffer_addr, context); + up(&efi_runtime_lock); + return status; +} + +#endif diff --git a/include/linux/efi.h b/include/linux/efi.h index e0b346b..5a1e39d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1228,6 +1228,10 @@ extern int efi_tpm_final_log_size; extern unsigned long rci2_table_phys; +efi_status_t +efi_call_acpi_prm_handler(efi_status_t (__efiapi *handler_addr)(u64, void *), + u64 param_buffer_addr, void *context); + /* * efi_runtime_service() function identifiers. * "NONE" is used by efi_recover_from_page_fault() to check if the page @@ -1247,6 +1251,7 @@ enum efi_rts_ids { EFI_RESET_SYSTEM, EFI_UPDATE_CAPSULE, EFI_QUERY_CAPSULE_CAPS, + EFI_ACPI_PRM_HANDLER, }; union efi_rts_args;