diff mbox

[v3,16/16] x86: add multiboot2 protocol support for relocatable images

Message ID 1460723596-13261-17-git-send-email-daniel.kiper@oracle.com (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Kiper April 15, 2016, 12:33 p.m. UTC
Add multiboot2 protocol support for relocatable images. Only GRUB2 with
"multiboot2: Add support for relocatable images" patch understands
that feature. Older multiboot protocol (regardless of version)
compatible loaders ignore it and everything works as usual.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v3 - suggestions/fixes:
   - use %esi and %r15d instead of %ebp to store
     Xen image load base address,
   - rename some types and constants,
   - reformat xen/include/xen/multiboot2.h
     (suggested by Konrad Rzeszutek Wilk),
   - improve comments,
   - improve commit message
     (suggested by Konrad Rzeszutek Wilk).
---
 xen/arch/x86/boot/head.S          |   46 +++++++++++++++++++++++++++++--------
 xen/arch/x86/x86_64/asm-offsets.c |    1 +
 xen/include/xen/multiboot2.h      |   13 +++++++++++
 3 files changed, 50 insertions(+), 10 deletions(-)

Comments

Jan Beulich May 25, 2016, 11:03 a.m. UTC | #1
>>> On 15.04.16 at 14:33, <daniel.kiper@oracle.com> wrote:
> Add multiboot2 protocol support for relocatable images. Only GRUB2 with
> "multiboot2: Add support for relocatable images" patch understands
> that feature. Older multiboot protocol (regardless of version)
> compatible loaders ignore it and everything works as usual.

So with that I'm now sure that the previous patch is in need of a
better description.

> --- a/xen/arch/x86/boot/head.S
> +++ b/xen/arch/x86/boot/head.S
> @@ -79,6 +79,13 @@ multiboot2_header_start:
>          /* Align modules at page boundry. */
>          mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED)
>  
> +        /* Load address preference. */
> +        mb2ht_init MB2_HT(RELOCATABLE), MB2_HT(OPTIONAL), \
> +                   sym_offset(start), /* Min load address. */ \
> +                   0xffffffff, /* Max load address (4 GiB - 1). */ \

Hardly - that would allow us to be loaded at 4G - 2M, no matter
how large the image. Or else the comment is misleading.

> @@ -178,30 +185,39 @@ efi_multiboot2_proto:
>          and     $~(MULTIBOOT2_TAG_ALIGN-1),%rcx
>  
>  0:
> +        /* Get Xen image load base address from Multiboot2 information. */
> +        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%rcx)
> +        jne     1f
> +
> +        mov     MB2_load_base_addr(%rcx),%r15d
> +        sub     $XEN_IMG_OFFSET,%r15
> +        jmp     4f

Why do we need to read this from the table? Can't we easily calculate
this ourselves?

> +1:
>          /* Get EFI SystemTable address from Multiboot2 information. */
>          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx)
> -        jne     1f
> +        jne     2f
>  
>          mov     MB2_efi64_st(%rcx),%rsi
>  
>          /* Do not clear BSS twice and do not go into real mode. */
>          movb    $1,skip_realmode(%rip)
> -        jmp     3f
> +        jmp     4f
>  
> -1:
> +2:
>          /* Get EFI ImageHandle address from Multiboot2 information. */
>          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx)
> -        jne     2f
> +        jne     3f
>  
>          mov     MB2_efi64_ih(%rcx),%rdi
> -        jmp     3f
> +        jmp     4f
>  
> -2:
> +3:
>          /* Is it the end of Multiboot2 information? */
>          cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx)
>          je      run_bs
>  
> -3:
> +4:
>          /* Go to next Multiboot2 information tag. */
>          add     MB2_tag_size(%rcx),%ecx
>          add     $(MULTIBOOT2_TAG_ALIGN-1),%rcx

See why numeric labels are bad in situations like this? The (much)
earlier patch should use .L labels here, and the patch here then
should simply follow suit.

> @@ -313,14 +329,23 @@ multiboot2_proto:
>          and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
>  
>  0:
> +        /* Get Xen image load base address from Multiboot2 information. */
> +        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%ecx)
> +        jne     1f
> +
> +        mov     MB2_load_base_addr(%ecx),%esi
> +        sub     $XEN_IMG_OFFSET,%esi
> +        jmp     3f

The redundancy once again suggests some form of abstraction
(helper function, macro, ...).

Jan
Daniel Kiper June 1, 2016, 1:35 p.m. UTC | #2
On Wed, May 25, 2016 at 05:03:20AM -0600, Jan Beulich wrote:
> >>> On 15.04.16 at 14:33, <daniel.kiper@oracle.com> wrote:
> > Add multiboot2 protocol support for relocatable images. Only GRUB2 with
> > "multiboot2: Add support for relocatable images" patch understands
> > that feature. Older multiboot protocol (regardless of version)
> > compatible loaders ignore it and everything works as usual.
>
> So with that I'm now sure that the previous patch is in need of a
> better description.

OK.

> > --- a/xen/arch/x86/boot/head.S
> > +++ b/xen/arch/x86/boot/head.S
> > @@ -79,6 +79,13 @@ multiboot2_header_start:
> >          /* Align modules at page boundry. */
> >          mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED)
> >
> > +        /* Load address preference. */
> > +        mb2ht_init MB2_HT(RELOCATABLE), MB2_HT(OPTIONAL), \
> > +                   sym_offset(start), /* Min load address. */ \
> > +                   0xffffffff, /* Max load address (4 GiB - 1). */ \
>
> Hardly - that would allow us to be loaded at 4G - 2M, no matter
> how large the image. Or else the comment is misleading.

This is the highest address at which memory region allocated for image
may end. You should remember that image itself can be smaller (Xen
image is smaller) than its initial memory requirements.

> > @@ -178,30 +185,39 @@ efi_multiboot2_proto:
> >          and     $~(MULTIBOOT2_TAG_ALIGN-1),%rcx
> >
> >  0:
> > +        /* Get Xen image load base address from Multiboot2 information. */
> > +        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%rcx)
> > +        jne     1f
> > +
> > +        mov     MB2_load_base_addr(%rcx),%r15d
> > +        sub     $XEN_IMG_OFFSET,%r15
> > +        jmp     4f
>
> Why do we need to read this from the table? Can't we easily calculate
> this ourselves?

Potentially yes but why do not use data from boot loader?

> > +1:
> >          /* Get EFI SystemTable address from Multiboot2 information. */
> >          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx)
> > -        jne     1f
> > +        jne     2f
> >
> >          mov     MB2_efi64_st(%rcx),%rsi
> >
> >          /* Do not clear BSS twice and do not go into real mode. */
> >          movb    $1,skip_realmode(%rip)
> > -        jmp     3f
> > +        jmp     4f
> >
> > -1:
> > +2:
> >          /* Get EFI ImageHandle address from Multiboot2 information. */
> >          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx)
> > -        jne     2f
> > +        jne     3f
> >
> >          mov     MB2_efi64_ih(%rcx),%rdi
> > -        jmp     3f
> > +        jmp     4f
> >
> > -2:
> > +3:
> >          /* Is it the end of Multiboot2 information? */
> >          cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx)
> >          je      run_bs
> >
> > -3:
> > +4:
> >          /* Go to next Multiboot2 information tag. */
> >          add     MB2_tag_size(%rcx),%ecx
> >          add     $(MULTIBOOT2_TAG_ALIGN-1),%rcx
>
> See why numeric labels are bad in situations like this? The (much)
> earlier patch should use .L labels here, and the patch here then
> should simply follow suit.

Then we should change legacy multiboot (v1) code too. Just to be in line
new stuff here. Does it pays? And I am not sure that patching convenience
overweight convenience of numeric labels here.

> > @@ -313,14 +329,23 @@ multiboot2_proto:
> >          and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
> >
> >  0:
> > +        /* Get Xen image load base address from Multiboot2 information. */
> > +        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%ecx)
> > +        jne     1f
> > +
> > +        mov     MB2_load_base_addr(%ecx),%esi
> > +        sub     $XEN_IMG_OFFSET,%esi
> > +        jmp     3f
>
> The redundancy once again suggests some form of abstraction
> (helper function, macro, ...).

Do you suggest that we should macroize multiboot2 header accesses?

Daniel
Jan Beulich June 1, 2016, 2:44 p.m. UTC | #3
>>> On 01.06.16 at 15:35, <daniel.kiper@oracle.com> wrote:
> On Wed, May 25, 2016 at 05:03:20AM -0600, Jan Beulich wrote:
>> >>> On 15.04.16 at 14:33, <daniel.kiper@oracle.com> wrote:
>> > --- a/xen/arch/x86/boot/head.S
>> > +++ b/xen/arch/x86/boot/head.S
>> > @@ -79,6 +79,13 @@ multiboot2_header_start:
>> >          /* Align modules at page boundry. */
>> >          mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED)
>> >
>> > +        /* Load address preference. */
>> > +        mb2ht_init MB2_HT(RELOCATABLE), MB2_HT(OPTIONAL), \
>> > +                   sym_offset(start), /* Min load address. */ \
>> > +                   0xffffffff, /* Max load address (4 GiB - 1). */ \
>>
>> Hardly - that would allow us to be loaded at 4G - 2M, no matter
>> how large the image. Or else the comment is misleading.
> 
> This is the highest address at which memory region allocated for image
> may end.

You saying "end" then means the comment is misleading.

>> > @@ -178,30 +185,39 @@ efi_multiboot2_proto:
>> >          and     $~(MULTIBOOT2_TAG_ALIGN-1),%rcx
>> >
>> >  0:
>> > +        /* Get Xen image load base address from Multiboot2 information. */
>> > +        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%rcx)
>> > +        jne     1f
>> > +
>> > +        mov     MB2_load_base_addr(%rcx),%r15d
>> > +        sub     $XEN_IMG_OFFSET,%r15
>> > +        jmp     4f
>>
>> Why do we need to read this from the table? Can't we easily calculate
>> this ourselves?
> 
> Potentially yes but why do not use data from boot loader?

Because it's (a) likely easier to just calculate and (b) we should
perhaps trust ourselves more than an external entity?

>> > +1:
>> >          /* Get EFI SystemTable address from Multiboot2 information. */
>> >          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx)
>> > -        jne     1f
>> > +        jne     2f
>> >
>> >          mov     MB2_efi64_st(%rcx),%rsi
>> >
>> >          /* Do not clear BSS twice and do not go into real mode. */
>> >          movb    $1,skip_realmode(%rip)
>> > -        jmp     3f
>> > +        jmp     4f
>> >
>> > -1:
>> > +2:
>> >          /* Get EFI ImageHandle address from Multiboot2 information. */
>> >          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx)
>> > -        jne     2f
>> > +        jne     3f
>> >
>> >          mov     MB2_efi64_ih(%rcx),%rdi
>> > -        jmp     3f
>> > +        jmp     4f
>> >
>> > -2:
>> > +3:
>> >          /* Is it the end of Multiboot2 information? */
>> >          cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx)
>> >          je      run_bs
>> >
>> > -3:
>> > +4:
>> >          /* Go to next Multiboot2 information tag. */
>> >          add     MB2_tag_size(%rcx),%ecx
>> >          add     $(MULTIBOOT2_TAG_ALIGN-1),%rcx
>>
>> See why numeric labels are bad in situations like this? The (much)
>> earlier patch should use .L labels here, and the patch here then
>> should simply follow suit.
> 
> Then we should change legacy multiboot (v1) code too. Just to be in line
> new stuff here. Does it pays? And I am not sure that patching convenience
> overweight convenience of numeric labels here.

Well, it's always this same discussion: Bad examples shouldn't be
used as excuse to add further bad examples. If you feel like also
changing the mb1 code - go for it. But if you don't, I'm fine with
just new code avoiding old mistakes.

>> > @@ -313,14 +329,23 @@ multiboot2_proto:
>> >          and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
>> >
>> >  0:
>> > +        /* Get Xen image load base address from Multiboot2 information. */
>> > +        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%ecx)
>> > +        jne     1f
>> > +
>> > +        mov     MB2_load_base_addr(%ecx),%esi
>> > +        sub     $XEN_IMG_OFFSET,%esi
>> > +        jmp     3f
>>
>> The redundancy once again suggests some form of abstraction
>> (helper function, macro, ...).
> 
> Do you suggest that we should macroize multiboot2 header accesses?

The whole logic here. And if macros (rather than functions), then
I'm thinking of assembler macros more than of C ones. All I really
wish is that we don't have the same kind of code in multiple places,
even more so when we talk about assembly code.

Jan
Daniel Kiper June 1, 2016, 7:16 p.m. UTC | #4
On Wed, Jun 01, 2016 at 08:44:31AM -0600, Jan Beulich wrote:
> >>> On 01.06.16 at 15:35, <daniel.kiper@oracle.com> wrote:
> > On Wed, May 25, 2016 at 05:03:20AM -0600, Jan Beulich wrote:
> >> >>> On 15.04.16 at 14:33, <daniel.kiper@oracle.com> wrote:
> >> > --- a/xen/arch/x86/boot/head.S
> >> > +++ b/xen/arch/x86/boot/head.S
> >> > @@ -79,6 +79,13 @@ multiboot2_header_start:
> >> >          /* Align modules at page boundry. */
> >> >          mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED)
> >> >
> >> > +        /* Load address preference. */
> >> > +        mb2ht_init MB2_HT(RELOCATABLE), MB2_HT(OPTIONAL), \
> >> > +                   sym_offset(start), /* Min load address. */ \
> >> > +                   0xffffffff, /* Max load address (4 GiB - 1). */ \
> >>
> >> Hardly - that would allow us to be loaded at 4G - 2M, no matter
> >> how large the image. Or else the comment is misleading.
> >
> > This is the highest address at which memory region allocated for image
> > may end.
>
> You saying "end" then means the comment is misleading.
>
> >> > @@ -178,30 +185,39 @@ efi_multiboot2_proto:
> >> >          and     $~(MULTIBOOT2_TAG_ALIGN-1),%rcx
> >> >
> >> >  0:
> >> > +        /* Get Xen image load base address from Multiboot2 information. */
> >> > +        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%rcx)
> >> > +        jne     1f
> >> > +
> >> > +        mov     MB2_load_base_addr(%rcx),%r15d
> >> > +        sub     $XEN_IMG_OFFSET,%r15
> >> > +        jmp     4f
> >>
> >> Why do we need to read this from the table? Can't we easily calculate
> >> this ourselves?
> >
> > Potentially yes but why do not use data from boot loader?
>
> Because it's (a) likely easier to just calculate and (b) we should

In 64-bit mode yes but 32-bit mode requires additional call and pop.
Is it OK for you?

> perhaps trust ourselves more than an external entity?

:-)))

> >> > +1:
> >> >          /* Get EFI SystemTable address from Multiboot2 information. */
> >> >          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx)
> >> > -        jne     1f
> >> > +        jne     2f
> >> >
> >> >          mov     MB2_efi64_st(%rcx),%rsi
> >> >
> >> >          /* Do not clear BSS twice and do not go into real mode. */
> >> >          movb    $1,skip_realmode(%rip)
> >> > -        jmp     3f
> >> > +        jmp     4f
> >> >
> >> > -1:
> >> > +2:
> >> >          /* Get EFI ImageHandle address from Multiboot2 information. */
> >> >          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx)
> >> > -        jne     2f
> >> > +        jne     3f
> >> >
> >> >          mov     MB2_efi64_ih(%rcx),%rdi
> >> > -        jmp     3f
> >> > +        jmp     4f
> >> >
> >> > -2:
> >> > +3:
> >> >          /* Is it the end of Multiboot2 information? */
> >> >          cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx)
> >> >          je      run_bs
> >> >
> >> > -3:
> >> > +4:
> >> >          /* Go to next Multiboot2 information tag. */
> >> >          add     MB2_tag_size(%rcx),%ecx
> >> >          add     $(MULTIBOOT2_TAG_ALIGN-1),%rcx
> >>
> >> See why numeric labels are bad in situations like this? The (much)
> >> earlier patch should use .L labels here, and the patch here then
> >> should simply follow suit.
> >
> > Then we should change legacy multiboot (v1) code too. Just to be in line
> > new stuff here. Does it pays? And I am not sure that patching convenience
> > overweight convenience of numeric labels here.
>
> Well, it's always this same discussion: Bad examples shouldn't be
> used as excuse to add further bad examples. If you feel like also
> changing the mb1 code - go for it. But if you don't, I'm fine with
> just new code avoiding old mistakes.

Make sense. However, do you suggest that I should avoid numeric labels at all?
Probably they are useful in some situations.

Daniel
Jan Beulich June 2, 2016, 8:41 a.m. UTC | #5
>>> On 01.06.16 at 21:16, <daniel.kiper@oracle.com> wrote:
> On Wed, Jun 01, 2016 at 08:44:31AM -0600, Jan Beulich wrote:
>> >>> On 01.06.16 at 15:35, <daniel.kiper@oracle.com> wrote:
>> > On Wed, May 25, 2016 at 05:03:20AM -0600, Jan Beulich wrote:
>> >> >>> On 15.04.16 at 14:33, <daniel.kiper@oracle.com> wrote:
>> >> > @@ -178,30 +185,39 @@ efi_multiboot2_proto:
>> >> >          and     $~(MULTIBOOT2_TAG_ALIGN-1),%rcx
>> >> >
>> >> >  0:
>> >> > +        /* Get Xen image load base address from Multiboot2 information. */
>> >> > +        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%rcx)
>> >> > +        jne     1f
>> >> > +
>> >> > +        mov     MB2_load_base_addr(%rcx),%r15d
>> >> > +        sub     $XEN_IMG_OFFSET,%r15
>> >> > +        jmp     4f
>> >>
>> >> Why do we need to read this from the table? Can't we easily calculate
>> >> this ourselves?
>> >
>> > Potentially yes but why do not use data from boot loader?
>>
>> Because it's (a) likely easier to just calculate and (b) we should
> 
> In 64-bit mode yes but 32-bit mode requires additional call and pop.
> Is it OK for you?

If you don't already calculate that offset somewhere - sure.

>> >> > +1:
>> >> >          /* Get EFI SystemTable address from Multiboot2 information. */
>> >> >          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx)
>> >> > -        jne     1f
>> >> > +        jne     2f
>> >> >
>> >> >          mov     MB2_efi64_st(%rcx),%rsi
>> >> >
>> >> >          /* Do not clear BSS twice and do not go into real mode. */
>> >> >          movb    $1,skip_realmode(%rip)
>> >> > -        jmp     3f
>> >> > +        jmp     4f
>> >> >
>> >> > -1:
>> >> > +2:
>> >> >          /* Get EFI ImageHandle address from Multiboot2 information. */
>> >> >          cmpl    $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx)
>> >> > -        jne     2f
>> >> > +        jne     3f
>> >> >
>> >> >          mov     MB2_efi64_ih(%rcx),%rdi
>> >> > -        jmp     3f
>> >> > +        jmp     4f
>> >> >
>> >> > -2:
>> >> > +3:
>> >> >          /* Is it the end of Multiboot2 information? */
>> >> >          cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx)
>> >> >          je      run_bs
>> >> >
>> >> > -3:
>> >> > +4:
>> >> >          /* Go to next Multiboot2 information tag. */
>> >> >          add     MB2_tag_size(%rcx),%ecx
>> >> >          add     $(MULTIBOOT2_TAG_ALIGN-1),%rcx
>> >>
>> >> See why numeric labels are bad in situations like this? The (much)
>> >> earlier patch should use .L labels here, and the patch here then
>> >> should simply follow suit.
>> >
>> > Then we should change legacy multiboot (v1) code too. Just to be in line
>> > new stuff here. Does it pays? And I am not sure that patching convenience
>> > overweight convenience of numeric labels here.
>>
>> Well, it's always this same discussion: Bad examples shouldn't be
>> used as excuse to add further bad examples. If you feel like also
>> changing the mb1 code - go for it. But if you don't, I'm fine with
>> just new code avoiding old mistakes.
> 
> Make sense. However, do you suggest that I should avoid numeric labels at 
> all?
> Probably they are useful in some situations.

Yes, they are. So I'm not asking to do away with them altogether.

Jan
diff mbox

Patch

diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index e322270..dbf2555 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -79,6 +79,13 @@  multiboot2_header_start:
         /* Align modules at page boundry. */
         mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED)
 
+        /* Load address preference. */
+        mb2ht_init MB2_HT(RELOCATABLE), MB2_HT(OPTIONAL), \
+                   sym_offset(start), /* Min load address. */ \
+                   0xffffffff, /* Max load address (4 GiB - 1). */ \
+                   0x200000, /* Load address alignment (2 MiB). */ \
+                   MULTIBOOT2_LOAD_PREFERENCE_HIGH
+
         /* Console flags tag. */
         mb2ht_init MB2_HT(CONSOLE_FLAGS), MB2_HT(OPTIONAL), \
                    MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
@@ -178,30 +185,39 @@  efi_multiboot2_proto:
         and     $~(MULTIBOOT2_TAG_ALIGN-1),%rcx
 
 0:
+        /* Get Xen image load base address from Multiboot2 information. */
+        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%rcx)
+        jne     1f
+
+        mov     MB2_load_base_addr(%rcx),%r15d
+        sub     $XEN_IMG_OFFSET,%r15
+        jmp     4f
+
+1:
         /* Get EFI SystemTable address from Multiboot2 information. */
         cmpl    $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx)
-        jne     1f
+        jne     2f
 
         mov     MB2_efi64_st(%rcx),%rsi
 
         /* Do not clear BSS twice and do not go into real mode. */
         movb    $1,skip_realmode(%rip)
-        jmp     3f
+        jmp     4f
 
-1:
+2:
         /* Get EFI ImageHandle address from Multiboot2 information. */
         cmpl    $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx)
-        jne     2f
+        jne     3f
 
         mov     MB2_efi64_ih(%rcx),%rdi
-        jmp     3f
+        jmp     4f
 
-2:
+3:
         /* Is it the end of Multiboot2 information? */
         cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx)
         je      run_bs
 
-3:
+4:
         /* Go to next Multiboot2 information tag. */
         add     MB2_tag_size(%rcx),%ecx
         add     $(MULTIBOOT2_TAG_ALIGN-1),%rcx
@@ -313,14 +329,23 @@  multiboot2_proto:
         and     $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
 
 0:
+        /* Get Xen image load base address from Multiboot2 information. */
+        cmpl    $MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR,MB2_tag_type(%ecx)
+        jne     1f
+
+        mov     MB2_load_base_addr(%ecx),%esi
+        sub     $XEN_IMG_OFFSET,%esi
+        jmp     3f
+
+1:
         /* Get mem_lower from Multiboot2 information. */
         cmpl    $MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,MB2_tag_type(%ecx)
-        jne     1f
+        jne     2f
 
         mov     MB2_mem_lower(%ecx),%edx
-        jmp     trampoline_bios_setup
+        jmp     3f
 
-1:
+2:
         /* EFI mode is not supported via legacy BIOS path. */
         cmpl    $MULTIBOOT2_TAG_TYPE_EFI32,MB2_tag_type(%ecx)
         je      mb2_too_old
@@ -332,6 +357,7 @@  multiboot2_proto:
         cmpl    $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%ecx)
         je      trampoline_bios_setup
 
+3:
         /* Go to next Multiboot2 information tag. */
         add     MB2_tag_size(%ecx),%ecx
         add     $(MULTIBOOT2_TAG_ALIGN-1),%ecx
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index b7aed49..d227f28 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -172,6 +172,7 @@  void __dummy__(void)
     DEFINE(MB2_fixed_sizeof, sizeof(multiboot2_fixed_t));
     OFFSET(MB2_tag_type, multiboot2_tag_t, type);
     OFFSET(MB2_tag_size, multiboot2_tag_t, size);
+    OFFSET(MB2_load_base_addr, multiboot2_tag_load_base_addr_t, load_base_addr);
     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);
diff --git a/xen/include/xen/multiboot2.h b/xen/include/xen/multiboot2.h
index 0f113f1..a1d355c 100644
--- a/xen/include/xen/multiboot2.h
+++ b/xen/include/xen/multiboot2.h
@@ -59,11 +59,17 @@ 
 #define MULTIBOOT2_HEADER_TAG_EFI_BS			7
 #define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI32	8
 #define MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI64	9
+#define MULTIBOOT2_HEADER_TAG_RELOCATABLE		10
 
 /* Header tag flags. */
 #define MULTIBOOT2_HEADER_TAG_REQUIRED			0
 #define MULTIBOOT2_HEADER_TAG_OPTIONAL			1
 
+/* Where image should be loaded (suggestion not requirement). */
+#define MULTIBOOT2_LOAD_PREFERENCE_NONE			0
+#define MULTIBOOT2_LOAD_PREFERENCE_LOW			1
+#define MULTIBOOT2_LOAD_PREFERENCE_HIGH			2
+
 /* Header console tag console_flags. */
 #define MULTIBOOT2_CONSOLE_FLAGS_CONSOLE_REQUIRED	1
 #define MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED	2
@@ -90,6 +96,7 @@ 
 #define MULTIBOOT2_TAG_TYPE_EFI_BS			18
 #define MULTIBOOT2_TAG_TYPE_EFI32_IH			19
 #define MULTIBOOT2_TAG_TYPE_EFI64_IH			20
+#define MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR		21
 
 /* Multiboot 2 tag alignment. */
 #define MULTIBOOT2_TAG_ALIGN				8
@@ -120,6 +127,12 @@  typedef struct {
 typedef struct {
     u32 type;
     u32 size;
+    u32 load_base_addr;
+} multiboot2_tag_load_base_addr_t;
+
+typedef struct {
+    u32 type;
+    u32 size;
     char string[0];
 } multiboot2_tag_string_t;