Re: [PATCH] mefi: add dynamic control interface for EFI runtime services
"Ard Biesheuvel" <[email protected]> Thu, 23 Jul 2026 08:37:23 +0200
| Newsgroups | org.kernel.vger.linux-efi,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
(cc Sebastian) On Sat, 4 Jul 2026, at 02:33, Junxiao Chang wrote: > Add an interface to dynamically enable or disable EFI runtime > services at runtime. By default, EFI runtime services remain > enabled, but they can be temporarily disabled to improve real-time > latency. > > Currently, EFI runtime services are typically disabled on RT > systems using kernel parameters such as "noefi" or "efi=disable". > However, this permanently disables EFI services, preventing use > cases such as UEFI firmware updates. > > With this change, EFI runtime services can be disabled during > execution of real-time workloads and re-enabled afterwards, > allowing better balance between real-time performance and firmware > service availability. > > Signed-off-by: Junxiao Chang <[email protected]> > --- > .../admin-guide/kernel-parameters.txt | 5 ++- > drivers/firmware/efi/efi.c | 39 +++++++++++++++++++ > 2 files changed, 43 insertions(+), 1 deletion(-) > > diff --git a/Documentation/admin-guide/kernel-parameters.txt > b/Documentation/admin-guide/kernel-parameters.txt > index b5493a7f8f228..533213101f808 100644 > --- a/Documentation/admin-guide/kernel-parameters.txt > +++ b/Documentation/admin-guide/kernel-parameters.txt > @@ -1595,7 +1595,8 @@ Kernel parameters > efi= [EFI,EARLY] > Format: { "debug", "disable_early_pci_dma", > "nochunk", "noruntime", "nosoftreserve", > - "novamap", "no_disable_early_pci_dma" } > + "novamap", "no_disable_early_pci_dma", > + "dynamic" } > debug: enable misc debug output. > disable_early_pci_dma: disable the busmaster bit on all > PCI bridges while in the EFI boot stub. > @@ -1612,6 +1613,8 @@ Kernel parameters > novamap: do not call SetVirtualAddressMap(). > no_disable_early_pci_dma: Leave the busmaster bit set > on all PCI bridges while in the EFI boot stub > + dynamic: enable EFI runtime services, which can be > + disabled via /sys/firmware/efi/dynamic_enable. > > efi_no_storage_paranoia [EFI,X86,EARLY] > Using this parameter you can use more than 50% of I'd prefer not to add a command line option for this. If the sysfs control is useful, we can enable it unconditionally, or depend on PREEMPT_RT. > diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c > index 0327a39d31fa5..18d5d99fab821 100644 > --- a/drivers/firmware/efi/efi.c > +++ b/drivers/firmware/efi/efi.c > @@ -81,6 +81,7 @@ struct mm_struct efi_mm = { > > struct workqueue_struct *efi_rts_wq; > > +static bool efi_in_dynamic __initdata; > static bool disable_runtime = IS_ENABLED(CONFIG_EFI_DISABLE_RUNTIME); > static int __init setup_noefi(char *arg) > { > @@ -115,6 +116,11 @@ static int __init parse_efi_cmdline(char *str) > if (parse_option_str(str, "runtime")) > disable_runtime = false; > > + if (parse_option_str(str, "dynamic")) { > + disable_runtime = false; > + efi_in_dynamic = true; > + } > + > if (parse_option_str(str, "nosoftreserve")) > set_bit(EFI_MEM_NO_SOFT_RESERVE, &efi.flags); > > @@ -401,6 +407,34 @@ static void __init efi_debugfs_init(void) > static inline void efi_debugfs_init(void) {} > #endif > > +static ssize_t efi_dynamic_show(struct kobject *kobj, struct > kobj_attribute *attr, char *buf) > +{ > + return sprintf(buf, "%d\n", efi_enabled(EFI_RUNTIME_SERVICES)); > +} > + > +static ssize_t efi_dynamic_store(struct kobject *kobj, struct > kobj_attribute *attr, > + const char *buf, size_t count) > +{ > + int ret; > + bool enable; > + > + ret = kstrtobool(buf, &enable); > + if (ret) > + return ret; > + > + if (enable) > + set_bit(EFI_RUNTIME_SERVICES, &efi.flags); > + else { > + clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); This is racy, no? > + if (efi_rts_wq) > + flush_workqueue(efi_rts_wq); > + } > + > + return count; > +} > +static struct kobj_attribute efi_dynamic_attr = > + __ATTR(dynamic_enable, 0644, efi_dynamic_show, efi_dynamic_store); > + > static int __init efipostcore_init(void) > { > if (!efi_enabled(EFI_RUNTIME_SERVICES)) > @@ -446,6 +480,11 @@ static int __init efisubsys_init(void) > goto err_destroy_wq; > } > > + if (efi_in_dynamic && efi.runtime_supported_mask) { > + if (sysfs_create_file(efi_kobj, &efi_dynamic_attr.attr)) > + pr_warn("unable to register efi dynamic sysfs interface\n"); > + } > + > if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE | > EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME)) { > error = generic_ops_register(); > -- > 2.43.0