All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hans de Goede <hdegoede@redhat.com>
To: Ard Biesheuvel <ardb@kernel.org>, linux-efi@vger.kernel.org
Cc: Matthew Garrett <matthewgarrett@google.com>,
	Ingo Molnar <mingo@kernel.org>, Andy Lutomirski <luto@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Arvind Sankar <nivedita@alum.mit.edu>
Subject: Re: [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls
Date: Sat, 21 Dec 2019 22:22:17 +0100	[thread overview]
Message-ID: <e7fc88c6-6281-f69b-ef9b-71572e40d6b9@redhat.com> (raw)
In-Reply-To: <20191218170139.9468-11-ardb@kernel.org>

Hi Ard,

On 18-12-2019 18:01, Ard Biesheuvel wrote:
> We use special wrapper routines to invoke firmware services in the
> native case as well as the mixed mode case. For mixed mode, the need
> is obvious, but for the native cases, we can simply rely on the
> compiler to generate the indirect call, given that GCC now has
> support for the MS calling convention (and has had it for quite some
> time now). Note that on i386, the decompressor and the EFI stub are not
> built with -mregparm=3 like the rest of the i386 kernel, so we can
> safely allow the compiler to emit the indirect calls here as well.
> 
> So drop all the wrappers and indirection, and switch to either native
> calls, or direct calls into the thunk routine for mixed mode.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

I'm afraid that this patch breaks the boot on one of my machines.

Specifically this patch breaks my GDP pocket machine. This is a Cherry
Trail device with a 64 UEFI running a 64 bit kernel build.

As soon as I cherry pick this patch into my personal 5.5.0-rc2 based
tree, the GPD pocket stops booting and it stop so early on that I get 0
debug output. I guess I could try adding a few pr_efi_err calls
and see if those still do something.

I noticed that you have made some changes to this patch, I've
tried updating it to the version from your efistub-x86-cleanup-v3
branch, commit id a37d90a2c570a25926fd1645482cb9f3c1d042a0
and I have also cherry-picked the latest version of all preceding
commits, unfortunately even with the new version, the GPD pocket
still hangs at boot.

Unfortunately the nature of this patch makes it hard to figure
out the root cause of this issue...

I've also tried another Cherry Trail device with 64 bit UEFI and
that does not suffer from this problem.

Regards,

Hans



> ---
>   arch/x86/boot/compressed/Makefile      |  2 +-
>   arch/x86/boot/compressed/efi_stub_32.S | 87 --------------------
>   arch/x86/boot/compressed/efi_stub_64.S |  5 --
>   arch/x86/boot/compressed/head_32.S     |  6 --
>   arch/x86/boot/compressed/head_64.S     | 12 ---
>   arch/x86/include/asm/efi.h             | 30 +++----
>   arch/x86/platform/efi/efi_64.c         |  2 -
>   7 files changed, 17 insertions(+), 127 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> index aa976adb7094..a20f55c59753 100644
> --- a/arch/x86/boot/compressed/Makefile
> +++ b/arch/x86/boot/compressed/Makefile
> @@ -89,7 +89,7 @@ vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
>   
>   $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
>   
> -vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
> +vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o \
>   	$(objtree)/drivers/firmware/efi/libstub/lib.a
>   vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
>   
> diff --git a/arch/x86/boot/compressed/efi_stub_32.S b/arch/x86/boot/compressed/efi_stub_32.S
> deleted file mode 100644
> index ed6c351d34ed..000000000000
> --- a/arch/x86/boot/compressed/efi_stub_32.S
> +++ /dev/null
> @@ -1,87 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -/*
> - * EFI call stub for IA32.
> - *
> - * This stub allows us to make EFI calls in physical mode with interrupts
> - * turned off. Note that this implementation is different from the one in
> - * arch/x86/platform/efi/efi_stub_32.S because we're _already_ in physical
> - * mode at this point.
> - */
> -
> -#include <linux/linkage.h>
> -#include <asm/page_types.h>
> -
> -/*
> - * efi_call_phys(void *, ...) is a function with variable parameters.
> - * All the callers of this function assure that all the parameters are 4-bytes.
> - */
> -
> -/*
> - * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save.
> - * So we'd better save all of them at the beginning of this function and restore
> - * at the end no matter how many we use, because we can not assure EFI runtime
> - * service functions will comply with gcc calling convention, too.
> - */
> -
> -.text
> -SYM_FUNC_START(efi_call_phys)
> -	/*
> -	 * 0. The function can only be called in Linux kernel. So CS has been
> -	 * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
> -	 * the values of these registers are the same. And, the corresponding
> -	 * GDT entries are identical. So I will do nothing about segment reg
> -	 * and GDT, but change GDT base register in prelog and epilog.
> -	 */
> -
> -	/*
> -	 * 1. Because we haven't been relocated by this point we need to
> -	 * use relative addressing.
> -	 */
> -	call	1f
> -1:	popl	%edx
> -	subl	$1b, %edx
> -
> -	/*
> -	 * 2. Now on the top of stack is the return
> -	 * address in the caller of efi_call_phys(), then parameter 1,
> -	 * parameter 2, ..., param n. To make things easy, we save the return
> -	 * address of efi_call_phys in a global variable.
> -	 */
> -	popl	%ecx
> -	movl	%ecx, saved_return_addr(%edx)
> -	/* get the function pointer into ECX*/
> -	popl	%ecx
> -	movl	%ecx, efi_rt_function_ptr(%edx)
> -
> -	/*
> -	 * 3. Call the physical function.
> -	 */
> -	call	*%ecx
> -
> -	/*
> -	 * 4. Balance the stack. And because EAX contain the return value,
> -	 * we'd better not clobber it. We need to calculate our address
> -	 * again because %ecx and %edx are not preserved across EFI function
> -	 * calls.
> -	 */
> -	call	1f
> -1:	popl	%edx
> -	subl	$1b, %edx
> -
> -	movl	efi_rt_function_ptr(%edx), %ecx
> -	pushl	%ecx
> -
> -	/*
> -	 * 10. Push the saved return address onto the stack and return.
> -	 */
> -	movl	saved_return_addr(%edx), %ecx
> -	pushl	%ecx
> -	ret
> -SYM_FUNC_END(efi_call_phys)
> -.previous
> -
> -.data
> -saved_return_addr:
> -	.long 0
> -efi_rt_function_ptr:
> -	.long 0
> diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S
> deleted file mode 100644
> index 99494dff2113..000000000000
> --- a/arch/x86/boot/compressed/efi_stub_64.S
> +++ /dev/null
> @@ -1,5 +0,0 @@
> -#include <asm/segment.h>
> -#include <asm/msr.h>
> -#include <asm/processor-flags.h>
> -
> -#include "../../platform/efi/efi_stub_64.S"
> diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
> index 40468ab49b9b..7da4dfc53df6 100644
> --- a/arch/x86/boot/compressed/head_32.S
> +++ b/arch/x86/boot/compressed/head_32.S
> @@ -161,9 +161,7 @@ SYM_FUNC_START(efi_pe_entry)
>   	popl	%ecx
>   	movl	%ecx, efi32_config+8(%esi)	/* EFI System table pointer */
>   
> -	/* Relocate efi_config->call() */
>   	leal	efi32_config(%esi), %eax
> -	add	%esi, 28(%eax)
>   	pushl	%eax
>   
>   	call	make_boot_params
> @@ -188,9 +186,7 @@ SYM_FUNC_START(efi32_stub_entry)
>   	movl	%ecx, efi32_config(%esi)	/* Handle */
>   	movl	%edx, efi32_config+8(%esi)	/* EFI System table pointer */
>   
> -	/* Relocate efi_config->call() */
>   	leal	efi32_config(%esi), %eax
> -	add	%esi, 28(%eax)
>   	pushl	%eax
>   2:
>   	call	efi_main
> @@ -266,8 +262,6 @@ SYM_FUNC_END(.Lrelocated)
>   	.data
>   efi32_config:
>   	.fill 7,4,0
> -	.long efi_call_phys
> -	.long 0
>   	.byte 0
>   #endif
>   
> diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> index 58a512e33d8d..6dc6a7ebb9e1 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -458,11 +458,6 @@ SYM_FUNC_START(efi_pe_entry)
>   1:	popq	%rbp
>   	subq	$1b, %rbp
>   
> -	/*
> -	 * Relocate efi_config->call().
> -	 */
> -	addq	%rbp, efi64_config+40(%rip)
> -
>   	movq	%rax, %rdi
>   	call	make_boot_params
>   	cmpq	$0,%rax
> @@ -477,11 +472,6 @@ handover_entry:
>   1:	popq	%rbp
>   	subq	$1b, %rbp
>   
> -	/*
> -	 * Relocate efi_config->call().
> -	 */
> -	movq	efi_config(%rip), %rax
> -	addq	%rbp, 40(%rax)
>   2:
>   	movq	efi_config(%rip), %rdi
>   	call	efi_main
> @@ -683,14 +673,12 @@ SYM_DATA_LOCAL(efi_config, .quad 0)
>   #ifdef CONFIG_EFI_MIXED
>   SYM_DATA_START(efi32_config)
>   	.fill	5,8,0
> -	.quad	efi64_thunk
>   	.byte	0
>   SYM_DATA_END(efi32_config)
>   #endif
>   
>   SYM_DATA_START(efi64_config)
>   	.fill	5,8,0
> -	.quad	efi_call
>   	.byte	1
>   SYM_DATA_END(efi64_config)
>   #endif /* CONFIG_EFI_STUB */
> diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
> index 183cd49e0495..e0789ec5c9f6 100644
> --- a/arch/x86/include/asm/efi.h
> +++ b/arch/x86/include/asm/efi.h
> @@ -152,6 +152,7 @@ struct efi_setup_data {
>   extern u64 efi_setup;
>   
>   #ifdef CONFIG_EFI
> +extern efi_status_t efi64_thunk(u32, ...);
>   
>   static inline bool efi_is_mixed(void)
>   {
> @@ -205,7 +206,6 @@ struct efi_config {
>   	efi_runtime_services_t *runtime_services;
>   	efi_boot_services_t *boot_services;
>   	efi_simple_text_output_protocol_t *text_output;
> -	efi_status_t (*call)(unsigned long, ...);
>   	bool is64;
>   } __packed;
>   
> @@ -235,30 +235,32 @@ static inline bool efi_is_native(void)
>   			(unsigned long)(attr), (attr))
>   
>   #define efi_table_attr(table, attr, instance) ({			\
> -	__typeof__(((table##_t *)0)->attr) __ret;			\
> +	__typeof__(instance->attr) __ret;				\
>   	if (efi_is_native()) {						\
> -		__ret = ((table##_t *)(unsigned long)instance)->attr;	\
> +		__ret = instance->attr;					\
>   	} else {							\
> -		__ret = (__typeof__(__ret))efi_mixed_mode_cast(		\
> -		((table##_t *)(unsigned long)instance)->mixed_mode.attr);\
> +		__ret = (__typeof__(__ret))				\
> +			efi_mixed_mode_cast(instance->mixed_mode.attr);	\
>   	}								\
>   	__ret;								\
>   })
>   
>   #define efi_call_proto(protocol, f, instance, ...)			\
> -	__efi_early()->call((unsigned long)				\
> -				efi_table_attr(protocol, f, instance),	\
> -		instance, ##__VA_ARGS__)
> +	(efi_is_native()						\
> +		? instance->f(instance, ##__VA_ARGS__)			\
> +		: efi64_thunk(instance->mixed_mode.f, instance,	##__VA_ARGS__))
>   
>   #define efi_call_early(f, ...)						\
> -	__efi_early()->call((unsigned long)				\
> -				efi_table_attr(efi_boot_services, f,	\
> -		__efi_early()->boot_services), __VA_ARGS__)
> +	(efi_is_native()						\
> +		? __efi_early()->boot_services->f(__VA_ARGS__)		\
> +		: efi64_thunk(__efi_early()->boot_services->mixed_mode.f,\
> +			__VA_ARGS__))
>   
>   #define efi_call_runtime(f, ...)					\
> -	__efi_early()->call((unsigned long)				\
> -				efi_table_attr(efi_runtime_services, f,	\
> -		__efi_early()->runtime_services), __VA_ARGS__)
> +	(efi_is_native()						\
> +		? __efi_early()->runtime_services->f(__VA_ARGS__)	\
> +		: efi64_thunk(__efi_early()->runtime_services->mixed_mode.f,\
> +			__VA_ARGS__))
>   
>   extern bool efi_reboot_required(void);
>   extern bool efi_is_table_address(unsigned long phys_addr);
> diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
> index 885e50a707a6..03c2ed3c645c 100644
> --- a/arch/x86/platform/efi/efi_64.c
> +++ b/arch/x86/platform/efi/efi_64.c
> @@ -635,8 +635,6 @@ void efi_switch_mm(struct mm_struct *mm)
>   }
>   
>   #ifdef CONFIG_EFI_MIXED
> -extern efi_status_t efi64_thunk(u32, ...);
> -
>   static DEFINE_SPINLOCK(efi_runtime_lock);
>   
>   #define runtime_service32(func)						 \
> 


  reply	other threads:[~2019-12-21 21:22 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-18 17:01 [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 01/21] efi/libstub: remove unused __efi_call_early() macro Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 02/21] efi/x86: rename efi_is_native() to efi_is_mixed() Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 03/21] efi/libstub: use a helper to iterate over a EFI handle array Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 04/21] efi/libstub: extend native protocol definitions with mixed_mode aliases Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 05/21] efi/libstub: distinguish between native/mixed not 32/64 bit Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 06/21] efi/libstub/x86: use mixed mode helpers to populate efi_config Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 07/21] efi/libstub: drop explicit 32/64-bit protocol definitions Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 08/21] efi/libstub: use stricter typing for firmware function pointers Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 09/21] efi/libstub: annotate firmware routines as __efiapi Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 10/21] efi/libstub/x86: avoid thunking for native firmware calls Ard Biesheuvel
2019-12-21 21:22   ` Hans de Goede [this message]
2019-12-22 12:02     ` Ard Biesheuvel
2019-12-22 12:37       ` Ard Biesheuvel
2019-12-22 12:46       ` Andy Lutomirski
2019-12-22 15:29         ` Ard Biesheuvel
2019-12-22 21:12           ` Arvind Sankar
2019-12-22 21:25             ` Ard Biesheuvel
2019-12-23 11:49       ` Hans de Goede
2019-12-23 12:00         ` Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 11/21] efi/libstub: get rid of 'sys_table_arg' macro parameter Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 12/21] efi/libstub: unify the efi_char16_printk implementations Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 13/21] efi/libstub/x86: drop __efi_early() export of efi_config struct Ard Biesheuvel
2019-12-24 19:34   ` Hans de Goede
2019-12-25 14:42     ` Ard Biesheuvel
2019-12-27 22:44       ` Hans de Goede
2019-12-27 22:51         ` Ard Biesheuvel
2019-12-31 23:04   ` Arvind Sankar
2020-01-01 18:13     ` Ard Biesheuvel
2020-01-01 19:08       ` Arvind Sankar
2020-01-02  7:33         ` Ard Biesheuvel
2020-01-02 14:06           ` Arvind Sankar
2020-01-02 15:20             ` Ard Biesheuvel
2020-01-02 15:51               ` Arvind Sankar
2020-01-02 15:58                 ` Ard Biesheuvel
2020-01-02 16:28                   ` Ard Biesheuvel
2020-01-02 16:59                     ` Ard Biesheuvel
2020-01-02 17:26                       ` Arvind Sankar
2020-01-02 17:30                         ` Ard Biesheuvel
2020-01-02 17:41                           ` Arvind Sankar
2020-01-02 17:48                             ` Ard Biesheuvel
2020-01-02 18:10                               ` Arvind Sankar
2020-01-02 18:38                                 ` Ard Biesheuvel
2020-01-03 14:16                                   ` Arvind Sankar
2020-01-03 14:23                                     ` Ard Biesheuvel
2020-01-02 18:38                               ` Arvind Sankar
2020-01-02 16:59                     ` Arvind Sankar
2020-01-02 17:03                       ` Ard Biesheuvel
2020-01-02 17:21                         ` Arvind Sankar
2019-12-18 17:01 ` [PATCH v2 14/21] efi/libstub: drop sys_table_arg from printk routines Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 15/21] efi/libstub: remove 'sys_table_arg' from all function prototypes Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 16/21] efi/libstub: drop protocol argument from efi_call_proto() macro Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 17/21] efi/libstub: drop 'table' argument from efi_table_attr() macro Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 18/21] efi/libstub: use 'func' not 'f' as macro parameter Ard Biesheuvel
2019-12-31 16:51   ` Arvind Sankar
2019-12-31 17:06     ` Ard Biesheuvel
2019-12-31 17:36       ` Arvind Sankar
2019-12-18 17:01 ` [PATCH v2 19/21] efi/libstub: tidy up types and names of global cmdline variables Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 20/21] efi/libstub: import type definitions for creating and signalling events Ard Biesheuvel
2019-12-18 17:01 ` [PATCH v2 21/21] efi: Allow disabling PCI busmastering on bridges during boot Ard Biesheuvel
2019-12-19  2:50   ` Andy Lutomirski
2019-12-19 13:17     ` Ard Biesheuvel
2019-12-19 20:04       ` Matthew Garrett
2019-12-19 20:04   ` Matthew Garrett
2019-12-20  7:06     ` Ard Biesheuvel
2019-12-20  7:17       ` Andy Lutomirski
2019-12-20  8:11         ` Ard Biesheuvel
2019-12-20 19:41           ` Arvind Sankar
2020-01-02 14:46             ` Laszlo Ersek
2020-01-02 15:40               ` Ard Biesheuvel
2019-12-20 20:43       ` Matthew Garrett
2019-12-21 16:44         ` Ard Biesheuvel
2019-12-21 21:24           ` Matthew Garrett
2019-12-21 22:54             ` Arvind Sankar
2019-12-23 14:02               ` Ard Biesheuvel
2019-12-23 15:46                 ` Arvind Sankar
2019-12-23 15:58                   ` Ard Biesheuvel
2019-12-23 16:12                     ` Arvind Sankar
2019-12-23 20:57                   ` Matthew Garrett
2020-02-06 14:30   ` Hans de Goede
2020-02-06 14:35     ` Ard Biesheuvel
2020-03-04 10:38       ` Hans de Goede
2020-03-04 18:26         ` Ard Biesheuvel
2020-03-04 18:49           ` Hans de Goede
2020-03-04 21:59             ` Ard Biesheuvel
2019-12-19 11:12 ` [PATCH v2 00/21] efi/x86: confine type unsafe casting to mixed mode Hans de Goede
2019-12-19 13:22   ` Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e7fc88c6-6281-f69b-ef9b-71572e40d6b9@redhat.com \
    --to=hdegoede@redhat.com \
    --cc=ardb@kernel.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=matthewgarrett@google.com \
    --cc=mingo@kernel.org \
    --cc=nivedita@alum.mit.edu \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.