[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 3/3] x86/boot: Rewrite EFI start part in C



On 10.09.2024 18:16, Frediano Ziglio wrote:
> No need to have it coded in assembly.

As to the title: It's the EFI/MB2 case you re-write. That wants reflecting
there, as the "normal" EFI start part is all C already anyway. I also
think you mean "partly"?

> @@ -255,34 +246,29 @@ __efi64_mb2_start:
>          rep stosq
>          mov     %edx, %eax

This can be dropped then, by making ...

> -        /* Check for Multiboot2 bootloader. */
> -        cmp     $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
> -        je      .Lefi_multiboot2_proto
> -
> -        /* Jump to .Lnot_multiboot after switching CPU to x86_32 mode. */
> -        lea     .Lnot_multiboot(%rip), %r15
> -        jmp     x86_32_switch
> +        /* Save Multiboot2 magic on the stack. */
> +        push    %rax

... this use %rdx.

> -.Lefi_multiboot2_proto:
> -        /* Zero EFI SystemTable, EFI ImageHandle addresses and cmdline. */
> -        xor     %esi,%esi
> -        xor     %edi,%edi
> -        xor     %edx,%edx
> +        /* Save Multiboot2 pointer on the stack. */
> +        push    %rbx

%rbx doesn't need preserving around a C function call (which will do
so itself if necessary). I understand a 2nd PUSH may be necessary
anyway, to keep the stack aligned, yet that then would need
commenting differently. Plus as long as we call our own functions
only, we don't require such alignment.

> -        /* Skip Multiboot2 information fixed part. */
> -        lea     (MB2_fixed_sizeof+MULTIBOOT2_TAG_ALIGN-1)(%rbx),%ecx
> -        and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
> +        /*
> +         * efi_parse_mbi2() is called according to System V AMD64 ABI:
> +         *   - IN:  %edi - Multiboot2 magic, %rsi - Multiboot2 pointer.
> +         *   - OUT: %eax - error string.

Nit: %rax according to the code below.

> +         */
> +        mov     %eax, %edi
> +        mov     %ebx, %esi

This latter one would better be a 64-bit MOV, for it being a pointer?

> +        call    efi_parse_mbi2
> +        test    %rax, %rax
> +        lea     .Ldirect_error(%rip), %r15
> +        jnz     x86_32_switch

As requested by Andrew in a related context: LEA first please to follow
the pattern allowing macro fusion, even if here it is less because of
performance concerns but more to avoid giving a bad example.

> --- a/xen/arch/x86/efi/Makefile
> +++ b/xen/arch/x86/efi/Makefile
> @@ -13,6 +13,7 @@ $(addprefix $(obj)/,$(EFIOBJ-y)): CFLAGS_stack_boundary := 
> $(cflags-stack-bounda
>  
>  obj-y := common-stub.o stub.o
>  obj-$(XEN_BUILD_EFI) := $(filter-out %.init.o,$(EFIOBJ-y))
> +obj-y += parse-mbi2.o

obj-bin-y I suppose, for it all being __init / __initdata, and hence the
string literals in particular also wanting to move to .init.rodata.

> --- /dev/null
> +++ b/xen/arch/x86/efi/parse-mbi2.c
> @@ -0,0 +1,54 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#include <xen/efi.h>
> +#include <xen/init.h>
> +#include <xen/multiboot2.h>
> +#include <asm/asm_defns.h>
> +#include <asm/efibind.h>
> +#include <efi/efidef.h>
> +#include <efi/eficapsule.h>
> +#include <efi/eficon.h>
> +#include <efi/efidevp.h>
> +#include <efi/efiapi.h>

I don't think all of these are needed? Please limit #include-s to just
what is actually used.

> +void asmlinkage __init efi_multiboot2(EFI_HANDLE ImageHandle,
> +                                      EFI_SYSTEM_TABLE *SystemTable,
> +                                      const char *cmdline);

This i now solely called from C code and hence shouldn't be asmlinkage.

> +const char *__init efi_parse_mbi2(uint32_t magic, const multiboot2_fixed_t 
> *mbi)

Whereas this, called from assembly code and not having / needing a
declaration, should be.

> +{
> +    const multiboot2_tag_t *tag;
> +    EFI_HANDLE ImageHandle = NULL;
> +    EFI_SYSTEM_TABLE *SystemTable = NULL;
> +    const char *cmdline = NULL;
> +    bool have_bs = false;
> +
> +    if ( magic != MULTIBOOT2_BOOTLOADER_MAGIC )
> +        return "ERR: Not a Multiboot bootloader!";

Assembly code merely re-used a message. Now that it separate, please make
it say "Multiboot2".

> +    /* Skip Multiboot2 information fixed part. */
> +    for ( tag = _p(ROUNDUP((unsigned long)(mbi + 1), MULTIBOOT2_TAG_ALIGN));

The comment is placed as if it applied to the entire loop. It wants to move
inside the for() to make clear it only applies to the loop setup.

> +          (void *)tag - (void *)mbi < mbi->total_size && tag->type != 
> MULTIBOOT2_TAG_TYPE_END;
> +          tag = _p(ROUNDUP((unsigned long)((void *)tag + tag->size), 
> MULTIBOOT2_TAG_ALIGN)) )

Now that this is done in C, I think the checking wants to be more
thorough, to no only make sure the start of a sub-struct is within
the specified size, but all of it (se we won't even access past
->total_size).

Further looks like there's a line length issue here.

Also please don't cast away const-ness from pointers.

> +    {
> +        if ( tag->type == MULTIBOOT2_TAG_TYPE_EFI_BS )
> +            have_bs = true;
> +        else if ( tag->type == MULTIBOOT2_TAG_TYPE_EFI64 )
> +            SystemTable = _p(((const multiboot2_tag_efi64_t *)tag)->pointer);
> +        else if ( tag->type == MULTIBOOT2_TAG_TYPE_EFI64_IH )
> +            ImageHandle = _p(((const multiboot2_tag_efi64_ih_t 
> *)tag)->pointer);
> +        else if ( tag->type == MULTIBOOT2_TAG_TYPE_CMDLINE )
> +            cmdline = ((const multiboot2_tag_string_t *)tag)->string;
> +    }
> +
> +    if ( !have_bs )
> +        return "ERR: Bootloader shutdown EFI x64 boot services!";
> +    if ( !SystemTable )
> +        return "ERR: EFI SystemTable is not provided by bootloader!";
> +    if ( !ImageHandle )
> +        return "ERR: EFI ImageHandle is not provided by bootloader!";
> +
> +    efi_multiboot2(ImageHandle, SystemTable, cmdline);

This being invoked from here now makes me wonder about the (new)
function's name and whether a separate new function is actually
needed: Can't the new code then be integrated right into
efi_multiboot2(), thus eliminating the question on the naming of
the function?

> --- a/xen/arch/x86/efi/stub.c
> +++ b/xen/arch/x86/efi/stub.c
> @@ -17,7 +17,8 @@
>   */
>  
>  void __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle,
> -                                    EFI_SYSTEM_TABLE *SystemTable)
> +                                    EFI_SYSTEM_TABLE *SystemTable,
> +                                    const char *cmdline)
>  {
>      static const CHAR16 __initconst err[] =
>          L"Xen does not have EFI code build in!\r\nSystem halted!\r\n";

This, if not a separate change, wants mentioning in the description.
It's a related observation that this wasn't properly updated, but
nothing that necessarily needs doing here. Question is whether the
declaration of the function wouldn't better go into a header now in
the first place.

Jan



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.