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

Re: [Xen-devel] [PATCH v3 5/5] x86/boot: Do not use trampoline for no-real-mode boot paths



On 21.08.2019 18:35, David Woodhouse wrote:
> From: David Woodhouse <dwmw@xxxxxxxxxxxx>
> 
> Where booted from EFI or with no-real-mode, there is no need to stomp
> on low memory with the 16-boot code. Instead, just go straight to
> trampoline_protmode_entry() at its physical location within the Xen
> image, having applied suitable relocations.
> 
> This means that the GDT has to be loaded with lgdtl because the 16-bit
> lgdt instruction would drop the high 8 bits of the gdt_trampoline
> address, causing failures if the Xen image was loaded above 16MiB.

There's a 2nd case where we assume an address not exceeding 16MiB:
The BOOT_PSEUDORM_{C,D}S entries on trampoline_gdt. While they'll
be unused (afaict) when not going through real mode, them getting
corrupted by applying relocations still seems somewhat risky to
me. I therefore wonder whether we shouldn't re-arrange this GDT's
layout in a prereq patch, such that theses two entries would go
last, and the GDT limit be reduced by two entries when skipping
real mode.

> --- a/xen/arch/x86/boot/head.S
> +++ b/xen/arch/x86/boot/head.S
> @@ -689,16 +689,23 @@ trampoline_setup:
>          lea     __PAGE_HYPERVISOR+sym_esi(l1_identmap),%edi
>          mov     %edi,sym_fs(l2_bootmap)
>  
> -        /* Apply relocations to bootstrap trampoline. */
> -        mov     sym_fs(trampoline_phys),%edx
> -        mov     $sym_offs(__trampoline_rel_start),%edi
> -1:
> -        mov     %fs:(%edi),%eax
> -        add     %edx,%fs:(%edi,%eax)
> -        add     $4,%edi
> -        cmp     $sym_offs(__trampoline_rel_stop),%edi
> -        jb      1b
> +        /* Do not parse command line on EFI platform here. */
> +        cmpb    $0,sym_fs(efi_platform)
> +        jnz     1f
>  
> +        /* Bail if there is no command line to parse. */
> +        mov     sym_fs(multiboot_ptr),%ebx
> +        testl   $MBI_CMDLINE,MB_flags(%ebx)
> +        jz      1f

As a really minor nit - I think it is generally better to have CMP
followed by JE/JNE, while (as you already have it) TEST/AND/OR are
better followed by JZ/JNZ. (Obviously this is a remark applicable to
the series as a whole.)

> @@ -90,6 +92,7 @@ GLOBAL(bootdata_start)
>   * It is entered in Real Mode, with %cs = trampoline_realmode_entry >> 4 and
>   * %ip = 0.
>   */
> +
>  GLOBAL(trampoline_realmode_entry)
>          mov     %cs,%ax
>          mov     %ax,%ds

I'd prefer if you didn't insert a blank line here, as the comment is
specifically associated with this label.

> @@ -97,7 +100,7 @@ GLOBAL(trampoline_realmode_entry)
>          cld
>          cli
>          lidt    trampsym(idt_48)
> -        lgdt    trampsym(gdt_48)
> +        lgdtl   trampsym(gdt_48)
>          mov     $1,%bl                    # EBX != 0 indicates we are an AP
>          xor     %ax, %ax
>          inc     %ax

As per the remark further up, trampoline_gdt's two entries (below
here) having a relocation associate with them should imo at least get
a comment added to state why (other than for the LGDTL here) there's
no issue with a relocation to an address above 16MiB.

> @@ -236,11 +239,23 @@ gdt_48: .word   7*8-1
>  
>  /* The first page of trampoline is permanent, the rest boot-time only. */
>  /* Reuse the boot trampoline on the 1st trampoline page as stack for wakeup. 
> */
> -        .equ    wakeup_stack, boot_trampoline_start + PAGE_SIZE
> +        .equ    wakeup_stack, perm_trampoline_start + PAGE_SIZE

Doesn't this, at the very least, render the comment stale?

>          .global wakeup_stack
>  
> +ENTRY(perm_trampoline_end)
> +
>  /* From here on early boot only. */
>  
> +ENTRY(boot_trampoline_start)
> +
> +        .word   0
> +boot16_idt:
> +        .word   0, 0, 0 # base = limit = 0
> +        .word   0
> +boot16_gdt:
> +        .word   7*8-1
> +        .long   tramp32sym_rel(trampoline_gdt,4)

As there's no change in this patch to how/where the boot trampoline
gets copied, am I understanding right that both end up at
trampoline_phys, just at different points in time? Otherwise I wonder
what the alignment of the relocated boot_trampoline_start end up
being, and hence whether the initial .word here is actually useful at
all.

> @@ -343,7 +358,8 @@ trampoline_boot_cpu_entry:
>          xor     %ebx,%ebx
>  
>          /* Jump to the common bootstrap entry point. */
> -        jmp     trampoline_protmode_entry
> +        mov     $tramp32sym_rel(trampoline_protmode_entry,4,%eax)
> +        jmp     *%eax

Do you really need to switch to an indirect branch here? I.e. can't
there be a relocation associated with the direct JMP's displacement?

> --- a/xen/arch/x86/setup.c
> +++ b/xen/arch/x86/setup.c
> @@ -679,6 +679,45 @@ static unsigned int __init copy_bios_e820(struct 
> e820entry *map, unsigned int li
>      return n;
>  }
>  
> +extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
> +extern const s32 __trampoline32_rel_start[], __trampoline32_rel_stop[];
> +
> +static void __init relocate_trampoline(unsigned long phys)
> +{
> +    const s32 *trampoline_ptr;
> +    uint32_t tramp32_delta;
> +
> +    /* Apply relocations to trampoline. */
> +    for ( trampoline_ptr = __trampoline_rel_start;
> +          trampoline_ptr < __trampoline_rel_stop;
> +          ++trampoline_ptr )
> +        *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
> +
> +    tramp32_delta = phys;
> +    if ( !efi_enabled(EFI_LOADER) )
> +    {
> +        /*
> +         * The non-EFI boot code uses the 32-bit trampoline in place
> +         * so will have relocated it to the physical address of
> +         * perm_trampoline_start already. Undo that as it needs to
> +         * run from low memory for AP startup, because the Xen
> +         * physical address range won't be mapped.
> +         */
> +        tramp32_delta -= trampoline_xen_phys_start;
> +        tramp32_delta -= (unsigned long)(perm_trampoline_start - 
> __XEN_VIRT_START);
> +    }
> +    for ( trampoline_ptr = __trampoline32_rel_start;
> +          trampoline_ptr < __trampoline32_rel_stop;
> +          ++trampoline_ptr )
> +    {
> +        *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += tramp32_delta;
> +    }

Along the lines of the loop further up, lease omit the braces here.

> --- a/xen/arch/x86/smpboot.c
> +++ b/xen/arch/x86/smpboot.c
> @@ -47,7 +47,7 @@
>  #include <asm/tboot.h>
>  #include <mach_apic.h>
>  
> -#define setup_trampoline()    (bootsym_phys(trampoline_realmode_entry))
> +#define setup_trampoline()    (trampsym_phys(trampoline_realmode_entry))

Would you mind taking the opportunity and strip the unnecessary pair
of parentheses here?

> --- a/xen/arch/x86/x86_64/mm.c
> +++ b/xen/arch/x86/x86_64/mm.c
> @@ -697,7 +697,7 @@ void __init zap_low_mappings(void)
>  
>      /* Replace with mapping of the boot trampoline only. */
>      map_pages_to_xen(trampoline_phys, maddr_to_mfn(trampoline_phys),
> -                     PFN_UP(boot_trampoline_end - boot_trampoline_start),
> +                     PFN_UP(perm_trampoline_end - perm_trampoline_start),
>                       __PAGE_HYPERVISOR);

You also want to adjust the comment then.

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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