Message ID | 1474667259-27290-9-git-send-email-daniel.kiper@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
>>> On 23.09.16 at 23:47, <daniel.kiper@oracle.com> wrote: > This way Xen can be loaded on EFI platforms using GRUB2 and > other boot loaders which support multiboot2 protocol. > > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com> > Acked-by: Jan Beulich <jbeulich@suse.com> > --- > v7 - suggestions/fixes: > - do not allocate twice memory for trampoline if we were > loaded via multiboot2 protocol on EFI platform, If you fix bugs not noticed by a reviewer but by yourself, please drop all acks/R-b-s covering the code in question. And then I'm afraid I haven't even been able to locate that change - could you please point out what you did where? > + /* > + * Initialize BSS (no nasty surprises!). > + * It must be done earlier than in BIOS case > + * because efi_multiboot2() touches it. > + */ > + lea .startof.(.bss)(%rip),%edi > + mov $.sizeof.(.bss),%ecx > + shr $3,%ecx > + xor %eax,%eax > + rep stosq > + > + pop %rdi > + > + /* > + * efi_multiboot2() is called according to System V AMD64 ABI: > + * - IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable, > + * - OUT: %rax - highest usable memory address below 1 MiB; > + * memory above this address is reserved for trampoline; > + * memory below this address is used for stack and as > + * a storage for boot data. How can you validly use memory below this address? (And I'd like to note that this also changed from v6, and the change to comments listed in the v7 section and supposedly suggested by me can't cover this, as I don't recall having asked for such an adjustment.) Jan
On 23/09/16 22:47, Daniel Kiper wrote: > + /* > + * Initialize BSS (no nasty surprises!). > + * It must be done earlier than in BIOS case > + * because efi_multiboot2() touches it. > + */ > + lea .startof.(.bss)(%rip),%edi > + mov $.sizeof.(.bss),%ecx Sorry, but you cannot use this syntax, for the same reasons why I won't accept Jan's patch making similar changes elsewhere. Amongst other issues, you will break the Clang build with it. ~Andrew
>>> On 26.09.16 at 16:19, <andrew.cooper3@citrix.com> wrote: > On 23/09/16 22:47, Daniel Kiper wrote: >> + /* >> + * Initialize BSS (no nasty surprises!). >> + * It must be done earlier than in BIOS case >> + * because efi_multiboot2() touches it. >> + */ >> + lea .startof.(.bss)(%rip),%edi >> + mov $.sizeof.(.bss),%ecx > > Sorry, but you cannot use this syntax, for the same reasons why I won't > accept Jan's patch making similar changes elsewhere. > > Amongst other issues, you will break the Clang build with it. Did you verify meanwhile that this doesn't work with llvm? Jan
On 26/09/16 15:33, Jan Beulich wrote: >>>> On 26.09.16 at 16:19, <andrew.cooper3@citrix.com> wrote: >> On 23/09/16 22:47, Daniel Kiper wrote: >>> + /* >>> + * Initialize BSS (no nasty surprises!). >>> + * It must be done earlier than in BIOS case >>> + * because efi_multiboot2() touches it. >>> + */ >>> + lea .startof.(.bss)(%rip),%edi >>> + mov $.sizeof.(.bss),%ecx >> Sorry, but you cannot use this syntax, for the same reasons why I won't >> accept Jan's patch making similar changes elsewhere. >> >> Amongst other issues, you will break the Clang build with it. > Did you verify meanwhile that this doesn't work with llvm? Yes. andrewcoop@andrewcoop:/local/xen.git/xen$ cat foo.c #include <stdio.h> static unsigned int x; int main(void) { asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" "mov $.sizeof.(.bss), %%rcx;" "mov $-1, %%rax;" "rep stosb;" ::: "memory", "rax", "rcx", "rdi"); printf("x: %#x\n", x); } andrewcoop@andrewcoop:/local/xen.git/xen$ gcc foo.c -o foo && ./foo x: 0xffffffff andrewcoop@andrewcoop:/local/xen.git/xen$ clang-3.8 foo.c -o foo && ./foo foo.c:7:18: error: unexpected token in memory operand asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" ^ <inline asm>:1:16: note: instantiated into assembly here lea .startof.(.bss)(%rip), %rdi;mov $.sizeof.(.bss), %rcx;mov $-1, %rax;rep stosb; ^ foo.c:7:18: error: unexpected token in argument list asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" ^ <inline asm>:1:47: note: instantiated into assembly here lea .startof.(.bss)(%rip), %rdi;mov $.sizeof.(.bss), %rcx;mov $-1, %rax;rep stosb; ^ 2 errors generated. ~Andrew
>>> On 26.09.16 at 16:40, <andrew.cooper3@citrix.com> wrote: > On 26/09/16 15:33, Jan Beulich wrote: >>>>> On 26.09.16 at 16:19, <andrew.cooper3@citrix.com> wrote: >>> On 23/09/16 22:47, Daniel Kiper wrote: >>>> + /* >>>> + * Initialize BSS (no nasty surprises!). >>>> + * It must be done earlier than in BIOS case >>>> + * because efi_multiboot2() touches it. >>>> + */ >>>> + lea .startof.(.bss)(%rip),%edi >>>> + mov $.sizeof.(.bss),%ecx >>> Sorry, but you cannot use this syntax, for the same reasons why I won't >>> accept Jan's patch making similar changes elsewhere. >>> >>> Amongst other issues, you will break the Clang build with it. >> Did you verify meanwhile that this doesn't work with llvm? > > Yes. > > andrewcoop@andrewcoop:/local/xen.git/xen$ cat foo.c > #include <stdio.h> > > static unsigned int x; > > int main(void) > { > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" > "mov $.sizeof.(.bss), %%rcx;" > "mov $-1, %%rax;" > "rep stosb;" > ::: "memory", "rax", "rcx", "rdi"); > printf("x: %#x\n", x); > } > andrewcoop@andrewcoop:/local/xen.git/xen$ gcc foo.c -o foo && ./foo > x: 0xffffffff > andrewcoop@andrewcoop:/local/xen.git/xen$ clang-3.8 foo.c -o foo && ./foo > foo.c:7:18: error: unexpected token in memory operand > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" > ^ > <inline asm>:1:16: note: instantiated into assembly here > lea .startof.(.bss)(%rip), %rdi;mov $.sizeof.(.bss), %rcx;mov > $-1, %rax;rep stosb; > ^ > foo.c:7:18: error: unexpected token in argument list > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" > ^ > <inline asm>:1:47: note: instantiated into assembly here > lea .startof.(.bss)(%rip), %rdi;mov $.sizeof.(.bss), %rcx;mov > $-1, %rax;rep stosb; > ^ > 2 errors generated. No, that's inline assembly, which does not match Daniel's use case. That's why I referred to llvm, as with assembly sources it should only be the linker which gets to see the symbols generated from those constructs (and if llvm supported them I'd then consider breaking out the assembly file changes from that patch of mine). Jan
On Mon, Sep 26, 2016 at 07:47:42AM -0600, Jan Beulich wrote: > >>> On 23.09.16 at 23:47, <daniel.kiper@oracle.com> wrote: > > This way Xen can be loaded on EFI platforms using GRUB2 and > > other boot loaders which support multiboot2 protocol. > > > > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com> > > Acked-by: Jan Beulich <jbeulich@suse.com> > > --- > > v7 - suggestions/fixes: > > - do not allocate twice memory for trampoline if we were > > loaded via multiboot2 protocol on EFI platform, > > If you fix bugs not noticed by a reviewer but by yourself, please > drop all acks/R-b-s covering the code in question. And then I'm OK. > afraid I haven't even been able to locate that change - could you > please point out what you did where? The change is very subtle. I add trampoline_setup label behind /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */ xor %cl, %cl instead of cmp %ecx,%edx /* compare with BDA value */ cmovb %edx,%ecx /* and use the smaller */ > > + /* > > + * Initialize BSS (no nasty surprises!). > > + * It must be done earlier than in BIOS case > > + * because efi_multiboot2() touches it. > > + */ > > + lea .startof.(.bss)(%rip),%edi > > + mov $.sizeof.(.bss),%ecx > > + shr $3,%ecx > > + xor %eax,%eax > > + rep stosq > > + > > + pop %rdi > > + > > + /* > > + * efi_multiboot2() is called according to System V AMD64 ABI: > > + * - IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable, > > + * - OUT: %rax - highest usable memory address below 1 MiB; > > + * memory above this address is reserved for trampoline; > > + * memory below this address is used for stack and as > > + * a storage for boot data. > > How can you validly use memory below this address? (And I'd like to Right, I should not do that blindly. As quick fix we can check in efi_arch_process_memory_map() that chosen memory region has size cfg.size plus let's say 64 KiB. Is it sufficient for you? However, I think that later (for 4.9?) we should consider what we discussed here https://lists.xen.org/archives/html/xen-devel/2016-09/msg01424.html > note that this also changed from v6, and the change to comments > listed in the v7 section and supposedly suggested by me can't cover > this, as I don't recall having asked for such an adjustment.) Ah, sorry about that. I should be more precise. Daniel
On Mon, Sep 26, 2016 at 09:12:40AM -0600, Jan Beulich wrote: > >>> On 26.09.16 at 16:40, <andrew.cooper3@citrix.com> wrote: > > On 26/09/16 15:33, Jan Beulich wrote: > >>>>> On 26.09.16 at 16:19, <andrew.cooper3@citrix.com> wrote: > >>> On 23/09/16 22:47, Daniel Kiper wrote: > >>>> + /* > >>>> + * Initialize BSS (no nasty surprises!). > >>>> + * It must be done earlier than in BIOS case > >>>> + * because efi_multiboot2() touches it. > >>>> + */ > >>>> + lea .startof.(.bss)(%rip),%edi > >>>> + mov $.sizeof.(.bss),%ecx > >>> Sorry, but you cannot use this syntax, for the same reasons why I won't > >>> accept Jan's patch making similar changes elsewhere. > >>> > >>> Amongst other issues, you will break the Clang build with it. > >> Did you verify meanwhile that this doesn't work with llvm? > > > > Yes. > > > > andrewcoop@andrewcoop:/local/xen.git/xen$ cat foo.c > > #include <stdio.h> > > > > static unsigned int x; > > > > int main(void) > > { > > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" > > "mov $.sizeof.(.bss), %%rcx;" > > "mov $-1, %%rax;" > > "rep stosb;" > > ::: "memory", "rax", "rcx", "rdi"); > > printf("x: %#x\n", x); > > } > > andrewcoop@andrewcoop:/local/xen.git/xen$ gcc foo.c -o foo && ./foo > > x: 0xffffffff > > andrewcoop@andrewcoop:/local/xen.git/xen$ clang-3.8 foo.c -o foo && ./foo > > foo.c:7:18: error: unexpected token in memory operand > > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" > > ^ > > <inline asm>:1:16: note: instantiated into assembly here > > lea .startof.(.bss)(%rip), %rdi;mov $.sizeof.(.bss), %rcx;mov > > $-1, %rax;rep stosb; > > ^ > > foo.c:7:18: error: unexpected token in argument list > > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" > > ^ > > <inline asm>:1:47: note: instantiated into assembly here > > lea .startof.(.bss)(%rip), %rdi;mov $.sizeof.(.bss), %rcx;mov > > $-1, %rax;rep stosb; > > ^ > > 2 errors generated. > > No, that's inline assembly, which does not match Daniel's use > case. That's why I referred to llvm, as with assembly sources it > should only be the linker which gets to see the symbols generated > from those constructs (and if llvm supported them I'd then consider > breaking out the assembly file changes from that patch of mine). Guys, may I suggest using sym_phys(__bss_start)/sym_phys(__bss_end) as it is in head.S right now? If .startof.()/.sizeof.() works as expected and both of you accept it then later we can move to new approach. Does it make sense? Daniel
>>> On 27.09.16 at 20:11, <daniel.kiper@oracle.com> wrote: > On Mon, Sep 26, 2016 at 07:47:42AM -0600, Jan Beulich wrote: >> >>> On 23.09.16 at 23:47, <daniel.kiper@oracle.com> wrote: >> > This way Xen can be loaded on EFI platforms using GRUB2 and >> > other boot loaders which support multiboot2 protocol. >> > >> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com> >> > Acked-by: Jan Beulich <jbeulich@suse.com> >> > --- >> > v7 - suggestions/fixes: >> > - do not allocate twice memory for trampoline if we were >> > loaded via multiboot2 protocol on EFI platform, >> >> If you fix bugs not noticed by a reviewer but by yourself, please >> drop all acks/R-b-s covering the code in question. And then I'm > > OK. > >> afraid I haven't even been able to locate that change - could you >> please point out what you did where? > > The change is very subtle. I add trampoline_setup label behind > > /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */ > xor %cl, %cl > > instead of > > cmp %ecx,%edx /* compare with BDA value */ > cmovb %edx,%ecx /* and use the smaller */ So how did you expect anyone having looked at previous version to spot that? Please, in your changes section, rather than tediously listing who suggested which change, please make that section useful for incremental reviews. >> > + /* >> > + * Initialize BSS (no nasty surprises!). >> > + * It must be done earlier than in BIOS case >> > + * because efi_multiboot2() touches it. >> > + */ >> > + lea .startof.(.bss)(%rip),%edi >> > + mov $.sizeof.(.bss),%ecx >> > + shr $3,%ecx >> > + xor %eax,%eax >> > + rep stosq >> > + >> > + pop %rdi >> > + >> > + /* >> > + * efi_multiboot2() is called according to System V AMD64 ABI: >> > + * - IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable, >> > + * - OUT: %rax - highest usable memory address below 1 MiB; >> > + * memory above this address is reserved for trampoline; >> > + * memory below this address is used for stack and as >> > + * a storage for boot data. >> >> How can you validly use memory below this address? (And I'd like to > > Right, I should not do that blindly. As quick fix we can check in > efi_arch_process_memory_map() > that chosen memory region has size cfg.size plus let's say 64 KiB. Is it sufficient > for you? Depends. Part of my problem here is that you convert, in your answer, my "validly" to "blindly". And then I'd like to see especially "storage for boot data" better qualified: What exactly is it that you mean to store there? I don't recall having noticed either this or that area being used as stack anywhere in the series, so I'm afraid I've overlooked something which may invalidate a good part of the review done. Jan
>>> On 27.09.16 at 20:21, <daniel.kiper@oracle.com> wrote: > On Mon, Sep 26, 2016 at 09:12:40AM -0600, Jan Beulich wrote: >> >>> On 26.09.16 at 16:40, <andrew.cooper3@citrix.com> wrote: >> > On 26/09/16 15:33, Jan Beulich wrote: >> >>>>> On 26.09.16 at 16:19, <andrew.cooper3@citrix.com> wrote: >> >>> On 23/09/16 22:47, Daniel Kiper wrote: >> >>>> + /* >> >>>> + * Initialize BSS (no nasty surprises!). >> >>>> + * It must be done earlier than in BIOS case >> >>>> + * because efi_multiboot2() touches it. >> >>>> + */ >> >>>> + lea .startof.(.bss)(%rip),%edi >> >>>> + mov $.sizeof.(.bss),%ecx >> >>> Sorry, but you cannot use this syntax, for the same reasons why I won't >> >>> accept Jan's patch making similar changes elsewhere. >> >>> >> >>> Amongst other issues, you will break the Clang build with it. >> >> Did you verify meanwhile that this doesn't work with llvm? >> > >> > Yes. >> > >> > andrewcoop@andrewcoop:/local/xen.git/xen$ cat foo.c >> > #include <stdio.h> >> > >> > static unsigned int x; >> > >> > int main(void) >> > { >> > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" >> > "mov $.sizeof.(.bss), %%rcx;" >> > "mov $-1, %%rax;" >> > "rep stosb;" >> > ::: "memory", "rax", "rcx", "rdi"); >> > printf("x: %#x\n", x); >> > } >> > andrewcoop@andrewcoop:/local/xen.git/xen$ gcc foo.c -o foo && ./foo >> > x: 0xffffffff >> > andrewcoop@andrewcoop:/local/xen.git/xen$ clang-3.8 foo.c -o foo && ./foo >> > foo.c:7:18: error: unexpected token in memory operand >> > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" >> > ^ >> > <inline asm>:1:16: note: instantiated into assembly here >> > lea .startof.(.bss)(%rip), %rdi;mov $.sizeof.(.bss), %rcx;mov >> > $-1, %rax;rep stosb; >> > ^ >> > foo.c:7:18: error: unexpected token in argument list >> > asm volatile("lea .startof.(.bss)(%%rip), %%rdi;" >> > ^ >> > <inline asm>:1:47: note: instantiated into assembly here >> > lea .startof.(.bss)(%rip), %rdi;mov $.sizeof.(.bss), %rcx;mov >> > $-1, %rax;rep stosb; >> > ^ >> > 2 errors generated. >> >> No, that's inline assembly, which does not match Daniel's use >> case. That's why I referred to llvm, as with assembly sources it >> should only be the linker which gets to see the symbols generated >> from those constructs (and if llvm supported them I'd then consider >> breaking out the assembly file changes from that patch of mine). > > Guys, may I suggest using sym_phys(__bss_start)/sym_phys(__bss_end) as > it is in head.S right now? If .startof.()/.sizeof.() works as expected > and both of you accept it then later we can move to new approach. Does > it make sense? While I dislike taking this step backwards, I guess that's the only viable option to move this patch closer to being ready to go in. Jan
On Wed, Sep 28, 2016 at 02:57:10AM -0600, Jan Beulich wrote: > >>> On 27.09.16 at 20:11, <daniel.kiper@oracle.com> wrote: > > On Mon, Sep 26, 2016 at 07:47:42AM -0600, Jan Beulich wrote: > >> >>> On 23.09.16 at 23:47, <daniel.kiper@oracle.com> wrote: > >> > This way Xen can be loaded on EFI platforms using GRUB2 and > >> > other boot loaders which support multiboot2 protocol. > >> > > >> > Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com> > >> > Acked-by: Jan Beulich <jbeulich@suse.com> > >> > --- > >> > v7 - suggestions/fixes: > >> > - do not allocate twice memory for trampoline if we were > >> > loaded via multiboot2 protocol on EFI platform, > >> > >> If you fix bugs not noticed by a reviewer but by yourself, please > >> drop all acks/R-b-s covering the code in question. And then I'm > > > > OK. > > > >> afraid I haven't even been able to locate that change - could you > >> please point out what you did where? > > > > The change is very subtle. I add trampoline_setup label behind > > > > /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */ > > xor %cl, %cl > > > > instead of > > > > cmp %ecx,%edx /* compare with BDA value */ > > cmovb %edx,%ecx /* and use the smaller */ > > So how did you expect anyone having looked at previous version > to spot that? Please, in your changes section, rather than > tediously listing who suggested which change, please make that > section useful for incremental reviews. I think that in general it is useful, however, I can agree that this thing could be described better. > >> > + /* > >> > + * Initialize BSS (no nasty surprises!). > >> > + * It must be done earlier than in BIOS case > >> > + * because efi_multiboot2() touches it. > >> > + */ > >> > + lea .startof.(.bss)(%rip),%edi > >> > + mov $.sizeof.(.bss),%ecx > >> > + shr $3,%ecx > >> > + xor %eax,%eax > >> > + rep stosq > >> > + > >> > + pop %rdi > >> > + > >> > + /* > >> > + * efi_multiboot2() is called according to System V AMD64 ABI: > >> > + * - IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable, > >> > + * - OUT: %rax - highest usable memory address below 1 MiB; > >> > + * memory above this address is reserved for trampoline; > >> > + * memory below this address is used for stack and as > >> > + * a storage for boot data. > >> > >> How can you validly use memory below this address? (And I'd like to > > > > Right, I should not do that blindly. As quick fix we can check in > > efi_arch_process_memory_map() > > that chosen memory region has size cfg.size plus let's say 64 KiB. Is it sufficient > > for you? > > Depends. Part of my problem here is that you convert, in your answer, > my "validly" to "blindly". And then I'd like to see especially "storage for I am not sure why the difference, IMO minor, is important for you here. > boot data" better qualified: What exactly is it that you mean to store > there? mbi struct created in reloc.c from original multiboot(2) data passed by boot loader. > I don't recall having noticed either this or that area being used > as stack anywhere in the series, so I'm afraid I've overlooked Hmmm... I do not know why I put stack here. It should be dropped from comment. Daniel
>>> On 28.09.16 at 11:39, <daniel.kiper@oracle.com> wrote: > On Wed, Sep 28, 2016 at 02:57:10AM -0600, Jan Beulich wrote: >> >>> On 27.09.16 at 20:11, <daniel.kiper@oracle.com> wrote: >> > On Mon, Sep 26, 2016 at 07:47:42AM -0600, Jan Beulich wrote: >> >> >>> On 23.09.16 at 23:47, <daniel.kiper@oracle.com> wrote: >> >> > + /* >> >> > + * Initialize BSS (no nasty surprises!). >> >> > + * It must be done earlier than in BIOS case >> >> > + * because efi_multiboot2() touches it. >> >> > + */ >> >> > + lea .startof.(.bss)(%rip),%edi >> >> > + mov $.sizeof.(.bss),%ecx >> >> > + shr $3,%ecx >> >> > + xor %eax,%eax >> >> > + rep stosq >> >> > + >> >> > + pop %rdi >> >> > + >> >> > + /* >> >> > + * efi_multiboot2() is called according to System V AMD64 ABI: >> >> > + * - IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable, >> >> > + * - OUT: %rax - highest usable memory address below 1 MiB; >> >> > + * memory above this address is reserved for trampoline; >> >> > + * memory below this address is used for stack and as >> >> > + * a storage for boot data. >> >> >> >> How can you validly use memory below this address? (And I'd like to >> > >> > Right, I should not do that blindly. As quick fix we can check in >> > efi_arch_process_memory_map() >> > that chosen memory region has size cfg.size plus let's say 64 KiB. Is it sufficient >> > for you? >> >> Depends. Part of my problem here is that you convert, in your answer, >> my "validly" to "blindly". And then I'd like to see especially "storage for > > I am not sure why the difference, IMO minor, is important for you here. Because I questioned any access to that area, yet you suggested accesses are okay with a little more checking. >> boot data" better qualified: What exactly is it that you mean to store >> there? > > mbi struct created in reloc.c from original multiboot(2) data passed by boot > loader. Ah, right. Please make the comment less vague then. And this then also gives you/us a means to determine what size would need to be available (64k looks to be way too much for mb1, but mb2 of course is much less bounded). Jan
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 383ff79..a371cde 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -89,6 +89,13 @@ multiboot2_header_start: 0, /* Number of the lines - no preference. */ \ 0 /* Number of bits per pixel - no preference. */ + /* Inhibit bootloader from calling ExitBootServices(). */ + mb2ht_init MB2_HT(EFI_BS), MB2_HT(OPTIONAL) + + /* EFI64 entry point. */ + mb2ht_init MB2_HT(ENTRY_ADDRESS_EFI64), MB2_HT(OPTIONAL), \ + sym_phys(__efi64_start) + /* Multiboot2 header end tag. */ mb2ht_init MB2_HT(END), MB2_HT(REQUIRED) .Lmultiboot2_header_end: @@ -100,20 +107,49 @@ multiboot2_header_start: gdt_boot_descr: .word 6*8-1 .long sym_phys(trampoline_gdt) + .long 0 /* Needed for 64-bit lgdt */ + +cs32_switch_addr: + .long sym_phys(cs32_switch) + .word BOOT_CS32 + + .align 4 +vga_text_buffer: + .long 0xb8000 .Lbad_cpu_msg: .asciz "ERR: Not a 64-bit CPU!" .Lbad_ldr_msg: .asciz "ERR: Not a Multiboot bootloader!" +.Lbad_ldr_nbs: .asciz "ERR: Bootloader shutdown EFI x64 boot services!" +.Lbad_ldr_nst: .asciz "ERR: EFI SystemTable is not provided by bootloader!" +.Lbad_ldr_nih: .asciz "ERR: EFI ImageHandle is not provided by bootloader!" +.Lbad_efi_msg: .asciz "ERR: EFI IA-32 platforms are not supported!" .section .init.text, "ax", @progbits bad_cpu: mov $(sym_phys(.Lbad_cpu_msg)),%esi # Error message - jmp print_err + jmp .Lget_vtb not_multiboot: mov $(sym_phys(.Lbad_ldr_msg)),%esi # Error message -print_err: - mov $0xB8000,%edi # VGA framebuffer -1: mov (%esi),%bl + jmp .Lget_vtb +.Lmb2_no_st: + mov $(sym_phys(.Lbad_ldr_nst)),%esi # Error message + jmp .Lget_vtb +.Lmb2_no_ih: + mov $(sym_phys(.Lbad_ldr_nih)),%esi # Error message + jmp .Lget_vtb +.Lmb2_no_bs: + mov $(sym_phys(.Lbad_ldr_nbs)),%esi # Error message + xor %edi,%edi # No VGA text buffer + jmp .Lsend_chr +.Lmb2_efi_ia_32: + mov $(sym_phys(.Lbad_efi_msg)),%esi # Error message + xor %edi,%edi # No VGA text buffer + jmp .Lsend_chr +.Lget_vtb: + mov sym_phys(vga_text_buffer),%edi +.Lsend_chr: + mov (%esi),%bl test %bl,%bl # Terminate on '\0' sentinel je .Lhalt mov $0x3f8+5,%dx # UART Line Status Register @@ -123,13 +159,181 @@ print_err: mov $0x3f8+0,%dx # UART Transmit Holding Register mov %bl,%al out %al,%dx # Send a character over the serial line - movsb # Write a character to the VGA framebuffer + test %edi,%edi # Is the VGA text buffer available? + jz .Lsend_chr + movsb # Write a character to the VGA text buffer mov $7,%al - stosb # Write an attribute to the VGA framebuffer - jmp 1b + stosb # Write an attribute to the VGA text buffer + jmp .Lsend_chr .Lhalt: hlt jmp .Lhalt + .code64 + +__efi64_start: + cld + + /* VGA is not available on EFI platforms. */ + movl $0,vga_text_buffer(%rip) + + /* Check for Multiboot2 bootloader. */ + cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax + je .Lefi_multiboot2_proto + + /* Jump to not_multiboot after switching CPU to x86_32 mode. */ + lea not_multiboot(%rip),%edi + jmp x86_32_switch + +.Lefi_multiboot2_proto: + /* Zero EFI SystemTable and EFI ImageHandle addresses. */ + xor %esi,%esi + xor %edi,%edi + + /* Skip Multiboot2 information fixed part. */ + lea (MB2_fixed_sizeof+MULTIBOOT2_TAG_ALIGN-1)(%rbx),%ecx + and $~(MULTIBOOT2_TAG_ALIGN-1),%ecx + +0: + /* Check Multiboot2 information total size. */ + mov %ecx,%r8d + sub %ebx,%r8d + cmp %r8d,MB2_fixed_total_size(%rbx) + jbe run_bs + + /* Are EFI boot services available? */ + cmpl $MULTIBOOT2_TAG_TYPE_EFI_BS,MB2_tag_type(%rcx) + jne 1f + + /* + * Yes, store that info in skip_realmode variable. I agree that + * its name is a bit unfortunate in this context, however, by the + * way we disable real mode and other legacy stuff which should + * not be run on EFI platforms. + */ + incb skip_realmode(%rip) + jmp 9f + +1: + /* Get EFI SystemTable address from Multiboot2 information. */ + cmpl $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx) + cmove MB2_efi64_st(%rcx),%rsi + je 9f + + /* Get EFI ImageHandle address from Multiboot2 information. */ + cmpl $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx) + cmove MB2_efi64_ih(%rcx),%rdi + je 9f + + /* Is it the end of Multiboot2 information? */ + cmpl $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx) + je run_bs + +9: + /* Go to next Multiboot2 information tag. */ + add MB2_tag_size(%rcx),%ecx + add $(MULTIBOOT2_TAG_ALIGN-1),%ecx + and $~(MULTIBOOT2_TAG_ALIGN-1),%ecx + jmp 0b + +run_bs: + /* Are EFI boot services available? */ + cmpb $0,skip_realmode(%rip) + jnz 0f + + /* Jump to .Lmb2_no_bs after switching CPU to x86_32 mode. */ + lea .Lmb2_no_bs(%rip),%edi + jmp x86_32_switch + +0: + /* Is EFI SystemTable address provided by boot loader? */ + test %rsi,%rsi + jnz 1f + + /* Jump to .Lmb2_no_st after switching CPU to x86_32 mode. */ + lea .Lmb2_no_st(%rip),%edi + jmp x86_32_switch + +1: + /* Is EFI ImageHandle address provided by boot loader? */ + test %rdi,%rdi + jnz 2f + + /* Jump to .Lmb2_no_ih after switching CPU to x86_32 mode. */ + lea .Lmb2_no_ih(%rip),%edi + jmp x86_32_switch + +2: + push %rax + push %rdi + + /* + * Initialize BSS (no nasty surprises!). + * It must be done earlier than in BIOS case + * because efi_multiboot2() touches it. + */ + lea .startof.(.bss)(%rip),%edi + mov $.sizeof.(.bss),%ecx + shr $3,%ecx + xor %eax,%eax + rep stosq + + pop %rdi + + /* + * efi_multiboot2() is called according to System V AMD64 ABI: + * - IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable, + * - OUT: %rax - highest usable memory address below 1 MiB; + * memory above this address is reserved for trampoline; + * memory below this address is used for stack and as + * a storage for boot data. + * + * MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO tag is not provided + * on EFI platforms. Hence, it could not be used like + * on legacy BIOS platforms. + */ + call efi_multiboot2 + + /* Convert memory address to bytes/16 and store it in safe place. */ + shr $4,%eax + mov %eax,%ecx + + pop %rax + + /* Jump to trampoline_setup after switching CPU to x86_32 mode. */ + lea trampoline_setup(%rip),%edi + +x86_32_switch: + cli + + /* Initialize GDTR. */ + lgdt gdt_boot_descr(%rip) + + /* Reload code selector. */ + ljmpl *cs32_switch_addr(%rip) + + .code32 + +cs32_switch: + /* Initialize basic data segments. */ + mov $BOOT_DS,%edx + mov %edx,%ds + mov %edx,%es + mov %edx,%ss + /* %esp is initialized later. */ + + /* Load null descriptor to unused segment registers. */ + xor %edx,%edx + mov %edx,%fs + mov %edx,%gs + + /* Disable paging. */ + mov %cr0,%edx + and $(~X86_CR0_PG),%edx + mov %edx,%cr0 + + /* Jump to earlier loaded address. */ + jmp *%edi + __start: cld cli @@ -157,7 +361,7 @@ __start: /* Not available? BDA value will be fine. */ cmovnz MB_mem_lower(%ebx),%edx - jmp trampoline_setup + jmp trampoline_bios_setup .Lmultiboot2_proto: /* Skip Multiboot2 information fixed part. */ @@ -169,16 +373,24 @@ __start: mov %ecx,%edi sub %ebx,%edi cmp %edi,MB2_fixed_total_size(%ebx) - jbe trampoline_setup + jbe trampoline_bios_setup /* Get mem_lower from Multiboot2 information. */ cmpl $MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,MB2_tag_type(%ecx) cmove MB2_mem_lower(%ecx),%edx - je trampoline_setup + je trampoline_bios_setup + + /* EFI IA-32 platforms are not supported. */ + cmpl $MULTIBOOT2_TAG_TYPE_EFI32,MB2_tag_type(%ecx) + je .Lmb2_efi_ia_32 + + /* Bootloader shutdown EFI x64 boot services. */ + cmpl $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%ecx) + je .Lmb2_no_bs /* Is it the end of Multiboot2 information? */ cmpl $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%ecx) - je trampoline_setup + je trampoline_bios_setup /* Go to next Multiboot2 information tag. */ add MB2_tag_size(%ecx),%ecx @@ -186,7 +398,7 @@ __start: and $~(MULTIBOOT2_TAG_ALIGN-1),%ecx jmp 0b -trampoline_setup: +trampoline_bios_setup: /* Set up trampoline segment 64k below EBDA */ movzwl 0x40e,%ecx /* EBDA segment */ cmp $0xa000,%ecx /* sanity check (high) */ @@ -202,16 +414,19 @@ trampoline_setup: * multiboot structure (if available) and use the smallest. */ cmp $0x100,%edx /* is the multiboot value too small? */ - jb 2f /* if so, do not use it */ + jb trampoline_setup /* if so, do not use it */ shl $10-4,%edx cmp %ecx,%edx /* compare with BDA value */ cmovb %edx,%ecx /* and use the smaller */ -2: /* Reserve 64kb for the trampoline */ + /* Reserve 64kb for the trampoline. */ sub $0x1000,%ecx /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */ xor %cl, %cl + +trampoline_setup: + /* Save trampoline address for later use. */ shl $4, %ecx mov %ecx,sym_phys(trampoline_phys) @@ -223,7 +438,14 @@ trampoline_setup: call reloc mov %eax,sym_phys(multiboot_ptr) - /* Initialize BSS (no nasty surprises!) */ + /* + * Do not zero BSS on EFI platform here. + * It was initialized earlier. + */ + cmpb $0,sym_phys(skip_realmode) + jnz 1f + + /* Initialize BSS (no nasty surprises!). */ mov $sym_phys(__bss_start),%edi mov $sym_phys(__bss_end),%ecx sub %edi,%ecx @@ -231,6 +453,7 @@ trampoline_setup: shr $2,%ecx rep stosl +1: /* Interrogate CPU extended features via CPUID. */ mov $0x80000000,%eax cpuid @@ -282,8 +505,13 @@ trampoline_setup: cmp $sym_phys(__trampoline_seg_stop),%edi jb 1b + /* Do not parse command line on EFI platform here. */ + cmpb $0,sym_phys(skip_realmode) + jnz 1f + call cmdline_parse_early +1: /* Switch to low-memory stack. */ mov sym_phys(trampoline_phys),%edi lea 0x10000(%edi),%esp diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index 62c010e..284cf97 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -210,12 +210,14 @@ static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size) static void __init efi_arch_pre_exit_boot(void) { - if ( !trampoline_phys ) - { - if ( !cfg.addr ) - blexit(L"No memory for trampoline"); + if ( trampoline_phys ) + return; + + if ( !cfg.addr ) + blexit(L"No memory for trampoline"); + + if ( efi_enabled(EFI_LOADER) ) relocate_trampoline(cfg.addr); - } } static void __init noreturn efi_arch_post_exit_boot(void) @@ -653,6 +655,43 @@ static bool_t __init efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable) static void efi_arch_flush_dcache_area(const void *vaddr, UINTN size) { } +paddr_t __init efi_multiboot2(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + UINTN cols, gop_mode = ~0, rows; + + __set_bit(EFI_BOOT, &efi_flags); + __set_bit(EFI_RS, &efi_flags); + + efi_init(ImageHandle, SystemTable); + + efi_console_set_mode(); + + if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode, + &cols, &rows) == EFI_SUCCESS ) + efi_arch_console_init(cols, rows); + + gop = efi_get_gop(); + + if ( gop ) + gop_mode = efi_find_gop_mode(gop, 0, 0, 0); + + efi_arch_edd(); + efi_arch_cpu(); + + efi_tables(); + setup_efi_pci(); + efi_variables(); + + if ( gop ) + efi_set_gop_mode(gop, gop_mode); + + efi_exit_boot(ImageHandle, SystemTable); + + /* Return highest usable memory address below 1 MiB. */ + return cfg.addr; +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c index bc9919c..232dd12 100644 --- a/xen/arch/x86/efi/stub.c +++ b/xen/arch/x86/efi/stub.c @@ -3,6 +3,44 @@ #include <xen/init.h> #include <xen/lib.h> #include <asm/page.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> + +/* + * Here we are in EFI stub. EFI calls are not supported due to lack + * of relevant functionality in compiler and/or linker. + * + * efi_multiboot2() is an exception. Please look below for more details. + */ + +paddr_t __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, + EFI_SYSTEM_TABLE *SystemTable) +{ + CHAR16 *err = L"Xen does not have EFI code build in!!!\r\nSystem halted!!!\r\n"; + SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr; + + StdErr = SystemTable->StdErr ? SystemTable->StdErr : SystemTable->ConOut; + + /* + * Print error message and halt the system. + * + * We have to open code MS x64 calling convention + * in assembly because here this convention may + * not be directly supported by C compiler. + */ + asm volatile( + " call %2 \n" + "0: hlt \n" + " jmp 0b \n" + : "+c" (StdErr), "+d" (err) : "g" (StdErr->OutputString) + : "rax", "r8", "r9", "r10", "r11", "memory"); + + unreachable(); +} bool efi_enabled(unsigned int feature) { diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c index b437a8f..2a22659 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -175,6 +175,8 @@ void __dummy__(void) OFFSET(MB2_tag_type, multiboot2_tag_t, type); OFFSET(MB2_tag_size, multiboot2_tag_t, size); OFFSET(MB2_mem_lower, multiboot2_tag_basic_meminfo_t, mem_lower); + OFFSET(MB2_efi64_st, multiboot2_tag_efi64_t, pointer); + OFFSET(MB2_efi64_ih, multiboot2_tag_efi64_ih_t, pointer); BLANK(); OFFSET(DOMAIN_vm_assist, struct domain, vm_assist); diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index 38baea3..f4b4e99 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -334,5 +334,5 @@ ASSERT(IS_ALIGNED(__init_end, PAGE_SIZE), "__init_end misaligned") ASSERT(IS_ALIGNED(trampoline_start, 4), "trampoline_start misaligned") ASSERT(IS_ALIGNED(trampoline_end, 4), "trampoline_end misaligned") -ASSERT(IS_ALIGNED(__bss_start, 4), "__bss_start misaligned") -ASSERT(IS_ALIGNED(__bss_end, 4), "__bss_end misaligned") +ASSERT(IS_ALIGNED(__bss_start, 8), "__bss_start misaligned") +ASSERT(IS_ALIGNED(__bss_end, 8), "__bss_end misaligned") diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 91df9b5..7e19f8a 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -83,6 +83,17 @@ static bool_t match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2); static void *ebmalloc(size_t size); #endif +static void efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable); +static void efi_console_set_mode(void); +static EFI_GRAPHICS_OUTPUT_PROTOCOL *efi_get_gop(void); +static UINTN efi_find_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, + UINTN cols, UINTN rows, UINTN depth); +static void efi_tables(void); +static void setup_efi_pci(void); +static void efi_variables(void); +static void efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop_mode); +static void efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable); + static const EFI_BOOT_SERVICES *__initdata efi_bs; static UINT32 __initdata efi_bs_revision; static EFI_HANDLE __initdata efi_ih;