On Fri, Aug 4, 2023 at 6:04 PM Ard Biesheuvel <ardb@xxxxxxxxxx> wrote: > > 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. > > Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> Thanks! > --- > drivers/acpi/prmt.c | 8 ++++---- > drivers/firmware/efi/runtime-wrappers.c | 20 ++++++++++++++++++++ > include/linux/efi.h | 13 +++++++++++++ > 3 files changed, 37 insertions(+), 4 deletions(-) > > diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c > index 3d4c4620f9f95309..95be1c80db387faa 100644 > --- a/drivers/acpi/prmt.c > +++ b/drivers/acpi/prmt.c > @@ -53,7 +53,7 @@ static LIST_HEAD(prm_module_list); > > struct prm_handler_info { > guid_t guid; > - void *handler_addr; > + efi_acpi_prm_handler_t *handler_addr; > u64 static_data_buffer_addr; > u64 acpi_param_buffer_addr; > > @@ -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 b3ef208299ae591e..ce306cd1efdfda21 100644 > --- a/drivers/firmware/efi/runtime-wrappers.c > +++ b/drivers/firmware/efi/runtime-wrappers.c > @@ -212,6 +212,12 @@ static void efi_call_rts(struct work_struct *work) > efi_rts_work.QUERY_CAPSULE_CAPS.max_size, > efi_rts_work.QUERY_CAPSULE_CAPS.reset_type); > break; > + case EFI_ACPI_PRM_HANDLER: > + status = efi_call_virt_pointer(&efi_rts_work.ACPI_PRM_HANDLER, > + handler_addr, > + efi_rts_work.ACPI_PRM_HANDLER.param_buffer_addr, > + efi_rts_work.ACPI_PRM_HANDLER.context); > + break; > default: > /* > * Ideally, we should never reach here because a caller of this > @@ -475,3 +481,17 @@ void __init efi_native_runtime_setup(void) > efi.update_capsule = virt_efi_update_capsule; > efi.query_capsule_caps = virt_efi_query_capsule_caps; > } > + > +efi_status_t efi_call_acpi_prm_handler(efi_acpi_prm_handler_t *handler_addr, > + efi_physical_addr_t 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; > +} > diff --git a/include/linux/efi.h b/include/linux/efi.h > index c72715821016851b..065af735d90a411c 100644 > --- a/include/linux/efi.h > +++ b/include/linux/efi.h > @@ -1230,6 +1230,12 @@ extern int efi_tpm_final_log_size; > > extern unsigned long rci2_table_phys; > > +typedef efi_status_t (__efiapi efi_acpi_prm_handler_t)(efi_physical_addr_t, void *); > + > +efi_status_t efi_call_acpi_prm_handler(efi_acpi_prm_handler_t *handler_addr, > + efi_physical_addr_t param_buffer_addr, > + void *context); > + > /* > * efi_runtime_service() function identifiers. > * "NONE" is used by efi_recover_from_page_fault() to check if the page > @@ -1249,6 +1255,7 @@ enum efi_rts_ids { > EFI_RESET_SYSTEM, > EFI_UPDATE_CAPSULE, > EFI_QUERY_CAPSULE_CAPS, > + EFI_ACPI_PRM_HANDLER, > }; > > /* > @@ -1324,6 +1331,12 @@ struct efi_runtime_work { > u64 *max_size; > int *reset_type; > } QUERY_CAPSULE_CAPS; > + > + struct { > + efi_acpi_prm_handler_t *handler_addr; > + efi_physical_addr_t param_buffer_addr; > + void *context; > + } ACPI_PRM_HANDLER; > }; > efi_status_t status; > struct work_struct work; > -- > 2.39.2 >