On Fri, 18 Dec, at 11:29:51AM, sylvain.chouleur@xxxxxxxxx wrote: > From: Sylvain Chouleur <sylvain.chouleur@xxxxxxxxx> > > This patch adds an implementation of EFI runtime services wappers which > allow interrupts and preemption during execution of BIOS code. > > It's needed by Broxton platform which requires the OS to do the write > of the non volatile variables. To do that, the OS will receive an > interrupt coming from the firmware to notify that it must write the > data. > > BIOS code must be executed using a specific PGD. This is currently > done by efi_call() which force value of CR3 before calling BIOS and > restore previous value after. > > We use a dedicated kthread which will execute all interruptible runtime > services. This efi_kthread is special because it has it's own mm_struct > whereas kthread should not have one. This mm_struct contains the EFI PGD > so the scheduler will load it before running any BIOS code. > > Obviously, an interruptible runtime service must never be called from an > interrupt context. EFI pstore is the only use case here, that's why we > require it to be disabled when activating interruptible runtime services. > > Signed-off-by: Sylvain Chouleur <sylvain.chouleur@xxxxxxxxx> > --- > arch/x86/Kconfig | 14 +++ > arch/x86/include/asm/efi.h | 1 + > arch/x86/platform/efi/Makefile | 1 + > arch/x86/platform/efi/efi_32.c | 5 + > arch/x86/platform/efi/efi_64.c | 5 + > arch/x86/platform/efi/efi_interruptible.c | 191 ++++++++++++++++++++++++++++++ > 6 files changed, 217 insertions(+) > create mode 100644 arch/x86/platform/efi/efi_interruptible.c > > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig > index db3622f22b61..3ddd5a9cab30 100644 > --- a/arch/x86/Kconfig > +++ b/arch/x86/Kconfig > @@ -1720,6 +1720,20 @@ config EFI_MIXED > > If unsure, say N. > > +if X86_64 > +config EFI_INTERRUPTIBLE > + bool "Interruptible Efi Runtime Services" > + depends on EFI && !EFI_VARS_PSTORE > + default n > + help > + This is an interruptible implementation of efi runtime > + services wrappers. If you say Y, BIOS code could be > + interrupted and preempted as a standard process. Enable this > + only if you are sure that your BIOS will support > + interruptible efi calls > + In doubt, say "N". > +endif > + These words should be a little more assertive. Almost everyone is going to want to turn this feature off. > +static efi_status_t > +non_blocking_not_allowed(__attribute__((unused)) efi_char16_t *name, > + __attribute__((unused)) efi_guid_t *vendor, > + __attribute__((unused)) u32 attr, > + __attribute__((unused)) unsigned long data_size, > + __attribute__((unused)) void *data) > +{ > + pr_err("efi_interruptible: non bloking operation is not allowed\n"); > + return EFI_UNSUPPORTED; > +} Typo, s/bloking/blocking/ > +static int efi_interruptible_panic_notifier_call( > + struct notifier_block *notifier, > + unsigned long what, void *data) > +{ > + static struct efivars generic_efivars; > + static struct efivar_operations generic_ops; > + > + generic_ops.get_variable = efi.get_variable; > + generic_ops.set_variable = efi.set_variable; > + generic_ops.get_next_variable = efi.get_next_variable; > + generic_ops.query_variable_store = efi_query_variable_store; > + > + efivars_register(&generic_efivars, &generic_ops, efivars_kobject()); > + > + return NOTIFY_DONE; > +} > + > +static struct notifier_block panic_nb = { > + .notifier_call = efi_interruptible_panic_notifier_call, > + .priority = 100, > +}; > + What's the purpose of this? The only reason you'd want to do this that I can think of is because you'd want efi-pstore to run and attempt to save some crash data for you. But you can't build with efi-pstore enable and CONFIG_EFI_INTERRUPTIBLE. I'd be tempted to just delete this notifier code. > +static struct task_struct *efi_kworker_task; > +static struct efivar_operations interruptible_ops; > +static __init int efi_interruptible_init(void) > +{ > + int ret; > + > + efi_kworker_task = kthread_create(kthread_worker_fn, &efi_kworker, > + "efi_kthread"); > + if (IS_ERR(efi_kworker_task)) { > + pr_err("efi_interruptible: Failed to create kthread\n"); > + ret = PTR_ERR(efi_kworker_task); > + efi_kworker_task = NULL; > + return ret; > + } > + > + efi_kworker_task->mm = mm_alloc(); > + efi_kworker_task->active_mm = efi_kworker_task->mm; > + efi_kworker_task->mm->pgd = efi_get_pgd(); > + wake_up_process(efi_kworker_task); > + > + atomic_notifier_chain_register(&panic_notifier_list, &panic_nb); > + > + interruptible_ops.get_variable = get_variable_interruptible; > + interruptible_ops.set_variable = set_variable_interruptible; > + interruptible_ops.set_variable_nonblocking = non_blocking_not_allowed; > + interruptible_ops.get_next_variable = get_next_variable_interruptible; > + interruptible_ops.query_variable_store = efi_query_variable_store; > + return efivars_register(&interruptible_efivars, &interruptible_ops, > + efivars_kobject()); > +} > + Is there some way we can match DMI/PCI identifiers for Broxton so that we don't start seeing people accidentally running with preemptible EFI services on non-BXT hardware? -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html