diff mbox series

[v2,5/6] x86/boot: Copy 16-bit boot variables back up to Xen image

Message ID 14720122f97667082d27153edd0e50aa6bc29e96.camel@infradead.org (mailing list archive)
State New, archived
Headers show
Series [v2,1/6] x86/boot: Remove gratuitous call back into low-memory code | expand

Commit Message

David Woodhouse Aug. 9, 2019, 3:02 p.m. UTC
From: David Woodhouse <dwmw@amazon.co.uk>

Ditch the bootsym() access from C code for the variables populated by
16-bit boot code. As well as being cleaner this also paves the way for
not having the 16-bit boot code in low memory for no-real-mode or EFI
loader boots at all.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 xen/arch/x86/boot/edd.S           |  2 ++
 xen/arch/x86/boot/head.S          | 16 +++++++++++++++
 xen/arch/x86/boot/mem.S           |  2 ++
 xen/arch/x86/boot/trampoline.S    | 33 ++++++++++++++++++++++++++++---
 xen/arch/x86/boot/video.S         | 30 +++++++++++++++-------------
 xen/arch/x86/platform_hypercall.c | 18 ++++++++---------
 xen/arch/x86/setup.c              | 22 ++++++++++-----------
 xen/arch/x86/xen.lds.S            |  8 +++++++-
 xen/include/asm-x86/edd.h         |  1 -
 9 files changed, 93 insertions(+), 39 deletions(-)

Comments

Jan Beulich Aug. 12, 2019, 10:24 a.m. UTC | #1
On 09.08.2019 17:02, David Woodhouse wrote:
> --- a/xen/arch/x86/boot/head.S
> +++ b/xen/arch/x86/boot/head.S
> @@ -733,6 +733,17 @@ trampoline_setup:
>          cmp     $sym_offs(__bootsym_seg_stop),%edi
>          jb      1b
>  
> +        /* Relocations for the boot data section. */
> +        mov     sym_fs(trampoline_phys),%edx
> +        add     $(boot_trampoline_end - boot_trampoline_start),%edx
> +        mov     $sym_offs(__bootdatasym_rel_start),%edi
> +1:
> +        mov     %fs:(%edi),%eax
> +        add     %edx,%fs:(%edi,%eax)
> +        add     $4,%edi
> +        cmp     $sym_offs(__bootdatasym_rel_stop),%edi
> +        jb      1b
> +
>          /* Do not parse command line on EFI platform here. */
>          cmpb    $0,sym_fs(efi_platform)
>          jnz     1f
> @@ -770,6 +781,11 @@ trampoline_setup:
>          mov     $((boot_trampoline_end - boot_trampoline_start) / 4),%ecx
>          rep movsl %fs:(%esi),%es:(%edi)
>  
> +        /* Copy boot data template to low memory. */
> +        mov     $sym_offs(bootdata_start),%esi
> +        mov     $((bootdata_end - bootdata_start + 3) / 4),%ecx
> +        rep movsl %fs:(%esi),%es:(%edi)

The new data arrangement should be described in the commit message.
Also just like for the trampoline copying I think it would be better
if you suitable aligned bootdata_start and bootdata_end, such that
you wouldn't need to add 3 here before dividing by 4.

> @@ -227,7 +231,7 @@ start64:
>          .word   0
>  idt_48: .word   0, 0, 0 # base = limit = 0
>          .word   0
> -gdt_48: .word   6*8-1
> +gdt_48: .word   7*8-1
>          .long   tramp32sym_rel(trampoline_gdt,4)

You don't grow trampoline_gdt here, so I think this change is
wrong. And if a change was needed at all (perhaps in the next
patch), then I think it would be better to replace the use of
literal numbers, using the difference of two labels instead
(the "end" lable preferably being a .L-prefixed one).

> --- a/xen/arch/x86/boot/video.S
> +++ b/xen/arch/x86/boot/video.S
> @@ -15,10 +15,10 @@
>   
>   #include "video.h"
>   
> -/* Scratch space layout: boot_trampoline_end to boot_trampoline_end+0x1000. */
> -#define modelist       bootsym(boot_trampoline_end)   /* 2kB (256 entries) */
> -#define vesa_glob_info (modelist + 0x800)        /* 1kB */
> -#define vesa_mode_info (vesa_glob_info + 0x400)  /* 1kB */
> +/* Scratch space layout: bootdata_end to bootdata_end+0x1000. */
> +#define modelist(t)       bootdatasym_rel(bootdata_end,2,t)         /* 2KiB (256 entries) */
> +#define vesa_glob_info(t) bootdatasym_rel((bootdata_end+0x800),2,t) /* 1KiB */
> +#define vesa_mode_info(t) bootdatasym_rel((bootdata_end+0xc00),2,t) /* 1KiB */
>   
>   /* Retrieve Extended Display Identification Data. */
>   #define CONFIG_FIRMWARE_EDID
> @@ -113,7 +113,7 @@ mopar2: movb    %al, _param(PARAM_VIDEO_LINES)
>   
>   # Fetching of VESA frame buffer parameters
>   mopar_gr:
> -        leaw    vesa_mode_info, %di
> +        leaw    vesa_mode_info(%di)

Just as a note, as I can't really see how to improve the situation:
The embedding of the relocation offset (2) in the macros is making
this code even more fragile, as they're now not usable anymore in
an arbitrary way (consider e.g. their use for the memory operand if
an insn which also requires an immediate). I think you want to at
least warn about this restriction in the comment above.

> @@ -291,6 +293,10 @@ SECTIONS
>     DECL_SECTION(.data) {
>          *(.data.page_aligned)
>          *(.data)
> +       . = ALIGN(16);
> +       __bootdata_start = .;
> +       *(.data.boot16)
> +       __bootdata_end = .;

Why 16-byte alignment?

Having reached the end of the patch without seeing the C-level
bootsym() go away (and as a result noticing that you didn't remove
all uses) - could you please explain in the commit message what
the replacement (or not) criteria are?

Jan
David Woodhouse Aug. 19, 2019, 3:25 p.m. UTC | #2
On Mon, 2019-08-12 at 12:24 +0200, Jan Beulich wrote:
> On 09.08.2019 17:02, David Woodhouse wrote:
> > --- a/xen/arch/x86/boot/head.S
> > +++ b/xen/arch/x86/boot/head.S
> > @@ -733,6 +733,17 @@ trampoline_setup:
> >          cmp     $sym_offs(__bootsym_seg_stop),%edi
> >          jb      1b
> >  
> > +        /* Relocations for the boot data section. */
> > +        mov     sym_fs(trampoline_phys),%edx
> > +        add     $(boot_trampoline_end - boot_trampoline_start),%edx
> > +        mov     $sym_offs(__bootdatasym_rel_start),%edi
> > +1:
> > +        mov     %fs:(%edi),%eax
> > +        add     %edx,%fs:(%edi,%eax)
> > +        add     $4,%edi
> > +        cmp     $sym_offs(__bootdatasym_rel_stop),%edi
> > +        jb      1b
> > +
> >          /* Do not parse command line on EFI platform here. */
> >          cmpb    $0,sym_fs(efi_platform)
> >          jnz     1f
> > @@ -770,6 +781,11 @@ trampoline_setup:
> >          mov     $((boot_trampoline_end - boot_trampoline_start) / 4),%ecx
> >          rep movsl %fs:(%esi),%es:(%edi)
> >  
> > +        /* Copy boot data template to low memory. */
> > +        mov     $sym_offs(bootdata_start),%esi
> > +        mov     $((bootdata_end - bootdata_start + 3) / 4),%ecx
> > +        rep movsl %fs:(%esi),%es:(%edi)
> 
> The new data arrangement should be described in the commit message.
> Also just like for the trampoline copying I think it would be better
> if you suitable aligned bootdata_start and bootdata_end, such that
> you wouldn't need to add 3 here before dividing by 4.

Ack.

> > @@ -227,7 +231,7 @@ start64:
> >          .word   0
> >  idt_48: .word   0, 0, 0 # base = limit = 0
> >          .word   0
> > -gdt_48: .word   6*8-1
> > +gdt_48: .word   7*8-1
> >          .long   tramp32sym_rel(trampoline_gdt,4)
> 
> You don't grow trampoline_gdt here, so I think this change is
> wrong. And if a change was needed at all (perhaps in the next
> patch), then I think it would be better to replace the use of
> literal numbers, using the difference of two labels instead
> (the "end" lable preferably being a .L-prefixed one).

I don't grow it but... count it ☺.

I do start using sym_fs() here in places that it wasn't before, so the
incorrect size started to *matter* because the BOOT_FS selector wasn't
included in the limit.

I will make sure I explicitly comment on that in the commit message; no
need for a code comment to explain why the limit actually *does* match
the size of the table.

> > --- a/xen/arch/x86/boot/video.S
> > +++ b/xen/arch/x86/boot/video.S
> > @@ -15,10 +15,10 @@
> >   
> >   #include "video.h"
> >   
> > -/* Scratch space layout: boot_trampoline_end to boot_trampoline_end+0x1000. */
> > -#define modelist       bootsym(boot_trampoline_end)   /* 2kB (256 entries) */
> > -#define vesa_glob_info (modelist + 0x800)        /* 1kB */
> > -#define vesa_mode_info (vesa_glob_info + 0x400)  /* 1kB */
> > +/* Scratch space layout: bootdata_end to bootdata_end+0x1000. */
> > +#define modelist(t)       bootdatasym_rel(bootdata_end,2,t)         /* 2KiB (256 entries) */
> > +#define vesa_glob_info(t) bootdatasym_rel((bootdata_end+0x800),2,t) /* 1KiB */
> > +#define vesa_mode_info(t) bootdatasym_rel((bootdata_end+0xc00),2,t) /* 1KiB */
> >   
> >   /* Retrieve Extended Display Identification Data. */
> >   #define CONFIG_FIRMWARE_EDID
> > @@ -113,7 +113,7 @@ mopar2: movb    %al, _param(PARAM_VIDEO_LINES)
> >   
> >   # Fetching of VESA frame buffer parameters
> >   mopar_gr:
> > -        leaw    vesa_mode_info, %di
> > +        leaw    vesa_mode_info(%di)
> 
> Just as a note, as I can't really see how to improve the situation:
> The embedding of the relocation offset (2) in the macros is making
> this code even more fragile, as they're now not usable anymore in
> an arbitrary way (consider e.g. their use for the memory operand if
> an insn which also requires an immediate). I think you want to at
> least warn about this restriction in the comment above.

Yeah. I file that one under "don't touch the VESA code unless you want
your brain to dribble out of your ears". Which was basically true
before I touched it too, in my defence ☺.

> > @@ -291,6 +293,10 @@ SECTIONS
> >     DECL_SECTION(.data) {
> >          *(.data.page_aligned)
> >          *(.data)
> > +       . = ALIGN(16);
> > +       __bootdata_start = .;
> > +       *(.data.boot16)
> > +       __bootdata_end = .;
> 
> Why 16-byte alignment?

Er... not sure. I think this (and the end) can be 4 as you suggest
elsewhere. Will make that change and retest.

> Having reached the end of the patch without seeing the C-level
> bootsym() go away (and as a result noticing that you didn't remove
> all uses) - could you please explain in the commit message what
> the replacement (or not) criteria are?

In the subsequent patch (6/6), bootsym() is indeed gone from C code,
and only trampsym() is left. The latter is for the permanent (not boot
time) trampoline used wakeup and for AP startup. As noted in the commit
message of that patch, the physical location of the Xen image isn't
mapped when those code paths run. So anything they need must be
relocated with them.
Jan Beulich Aug. 27, 2019, 8:59 a.m. UTC | #3
On 19.08.2019 17:25, David Woodhouse wrote:
> On Mon, 2019-08-12 at 12:24 +0200, Jan Beulich wrote:
>> On 09.08.2019 17:02, David Woodhouse wrote:
>>> @@ -227,7 +231,7 @@ start64:
>>>           .word   0
>>>   idt_48: .word   0, 0, 0 # base = limit = 0
>>>           .word   0
>>> -gdt_48: .word   6*8-1
>>> +gdt_48: .word   7*8-1
>>>           .long   tramp32sym_rel(trampoline_gdt,4)
>>
>> You don't grow trampoline_gdt here, so I think this change is
>> wrong. And if a change was needed at all (perhaps in the next
>> patch), then I think it would be better to replace the use of
>> literal numbers, using the difference of two labels instead
>> (the "end" lable preferably being a .L-prefixed one).
> 
> I don't grow it but... count it ☺.
> 
> I do start using sym_fs() here in places that it wasn't before, so the
> incorrect size started to *matter* because the BOOT_FS selector wasn't
> included in the limit.

Oh, I see - a (latent) bug introduced by b28044226e. Should perhaps
be a separate patch to fix this then (by, as suggested, using an
"end" label rather than hard coded numbers).

Jan
David Woodhouse Aug. 27, 2019, 9:19 a.m. UTC | #4
> On 19.08.2019 17:25, David Woodhouse wrote:
>> On Mon, 2019-08-12 at 12:24 +0200, Jan Beulich wrote:
>>> On 09.08.2019 17:02, David Woodhouse wrote:
>>>> @@ -227,7 +231,7 @@ start64:
>>>>           .word   0
>>>>   idt_48: .word   0, 0, 0 # base = limit = 0
>>>>           .word   0
>>>> -gdt_48: .word   6*8-1
>>>> +gdt_48: .word   7*8-1
>>>>           .long   tramp32sym_rel(trampoline_gdt,4)
>>>
>>> You don't grow trampoline_gdt here, so I think this change is
>>> wrong. And if a change was needed at all (perhaps in the next
>>> patch), then I think it would be better to replace the use of
>>> literal numbers, using the difference of two labels instead
>>> (the "end" lable preferably being a .L-prefixed one).
>>
>> I don't grow it but... count it ☺.
>>
>> I do start using sym_fs() here in places that it wasn't before, so the
>> incorrect size started to *matter* because the BOOT_FS selector wasn't
>> included in the limit.
>
> Oh, I see - a (latent) bug introduced by b28044226e. Should perhaps
> be a separate patch to fix this then (by, as suggested, using an
> "end" label rather than hard coded numbers).

Indeed. Andrew already posted a patch for that, which (along with his
others) I have rebased on top of my tree at
https://xenbits.xen.org/gitweb/?p=people/dwmw2/xen.git;a=shortlog;h=refs/heads/bootcleanup-andy
diff mbox series

Patch

diff --git a/xen/arch/x86/boot/edd.S b/xen/arch/x86/boot/edd.S
index 434bbbd960..138d04c964 100644
--- a/xen/arch/x86/boot/edd.S
+++ b/xen/arch/x86/boot/edd.S
@@ -163,6 +163,7 @@  edd_done:
 .Ledd_mbr_sig_skip:
         ret
 
+        .pushsection .data.boot16, "aw", @progbits
 GLOBAL(boot_edd_info_nr)
         .byte   0
 GLOBAL(boot_mbr_signature_nr)
@@ -171,3 +172,4 @@  GLOBAL(boot_mbr_signature)
         .fill   EDD_MBR_SIG_MAX*8,1,0
 GLOBAL(boot_edd_info)
         .fill   EDD_INFO_MAX * (EDDEXTSIZE + EDDPARMSIZE), 1, 0
+        .popsection
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index 556dab127f..104eb0eb3c 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -733,6 +733,17 @@  trampoline_setup:
         cmp     $sym_offs(__bootsym_seg_stop),%edi
         jb      1b
 
+        /* Relocations for the boot data section. */
+        mov     sym_fs(trampoline_phys),%edx
+        add     $(boot_trampoline_end - boot_trampoline_start),%edx
+        mov     $sym_offs(__bootdatasym_rel_start),%edi
+1:
+        mov     %fs:(%edi),%eax
+        add     %edx,%fs:(%edi,%eax)
+        add     $4,%edi
+        cmp     $sym_offs(__bootdatasym_rel_stop),%edi
+        jb      1b
+
         /* Do not parse command line on EFI platform here. */
         cmpb    $0,sym_fs(efi_platform)
         jnz     1f
@@ -770,6 +781,11 @@  trampoline_setup:
         mov     $((boot_trampoline_end - boot_trampoline_start) / 4),%ecx
         rep movsl %fs:(%esi),%es:(%edi)
 
+        /* Copy boot data template to low memory. */
+        mov     $sym_offs(bootdata_start),%esi
+        mov     $((bootdata_end - bootdata_start + 3) / 4),%ecx
+        rep movsl %fs:(%esi),%es:(%edi)
+
         /* Jump into the relocated trampoline. */
         lret
 
diff --git a/xen/arch/x86/boot/mem.S b/xen/arch/x86/boot/mem.S
index aa39608442..86f0fa9af7 100644
--- a/xen/arch/x86/boot/mem.S
+++ b/xen/arch/x86/boot/mem.S
@@ -67,6 +67,7 @@  get_memory_map:
         ret
 
         .align  4
+        .pushsection .data.boot16, "aw", @progbits
 GLOBAL(bios_e820map)
         .fill   E820_BIOS_MAX*20,1,0
 GLOBAL(bios_e820nr)
@@ -75,3 +76,4 @@  GLOBAL(lowmem_kb)
         .long   0
 GLOBAL(highmem_kb)
         .long   0
+	.popsection
diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S
index 26af9c6beb..b5517a44bb 100644
--- a/xen/arch/x86/boot/trampoline.S
+++ b/xen/arch/x86/boot/trampoline.S
@@ -47,11 +47,15 @@ 
         .long 111b - (off) - .;            \
         .popsection
 
-#define bootdatasym(s) ((s)-boot_trampoline_start)
+        .pushsection .data.boot16, "aw", @progbits
+GLOBAL(bootdata_start)
+        .popsection
+
+#define bootdatasym(s) ((s)-bootdata_start+(boot_trampoline_end-boot_trampoline_start))
 #define bootdatasym_rel(sym, off, opnd...) \
         bootdatasym(sym),##opnd;           \
 111:;                                      \
-        .pushsection .bootdatasym_rel, "a";\
+        .pushsection .bootsym_rel, "a";\
         .long 111b - (off) - .;            \
         .popsection
 
@@ -227,7 +231,7 @@  start64:
         .word   0
 idt_48: .word   0, 0, 0 # base = limit = 0
         .word   0
-gdt_48: .word   6*8-1
+gdt_48: .word   7*8-1
         .long   tramp32sym_rel(trampoline_gdt,4)
 
 /* The first page of trampoline is permanent, the rest boot-time only. */
@@ -318,6 +322,23 @@  trampoline_boot_cpu_entry:
         mov     %eax,%gs
         mov     %eax,%ss
 
+        /*
+         * Copy locally-gathered data back up into the Xen physical image
+         */
+        mov     $BOOT_FS,%eax
+        mov     %eax,%es
+
+        mov     $sym_offs(bootdata_end),%ecx
+        mov     $sym_offs(bootdata_start),%edi
+        sub     %edi,%ecx
+        mov     $bootdatasym_rel(bootdata_start,4,%esi)
+        rep movsb %ds:(%esi),%es:(%edi)
+
+        /*
+         * %es still points to BOOT_FS but trampoline_protmode_entry
+         * reloads it anyway.
+         */
+
         /* EBX == 0 indicates we are the BP (Boot Processor). */
         xor     %ebx,%ebx
 
@@ -345,8 +366,10 @@  vesa_size:
         .word   0,0,0                           /* width x depth x height */
 #endif
 
+        .pushsection .data.boot16, "aw", @progbits
 GLOBAL(kbd_shift_flags)
         .byte   0
+        .popsection
 
 rm_idt: .word   256*4-1, 0, 0
 
@@ -355,3 +378,7 @@  rm_idt: .word   256*4-1, 0, 0
 #ifdef CONFIG_VIDEO
 #include "video.S"
 #endif
+
+        .pushsection .data.boot16, "aw", @progbits
+GLOBAL(bootdata_end)
+        .popsection
diff --git a/xen/arch/x86/boot/video.S b/xen/arch/x86/boot/video.S
index 5087c6a4d5..4608464b77 100644
--- a/xen/arch/x86/boot/video.S
+++ b/xen/arch/x86/boot/video.S
@@ -15,10 +15,10 @@ 
 
 #include "video.h"
 
-/* Scratch space layout: boot_trampoline_end to boot_trampoline_end+0x1000. */
-#define modelist       bootsym(boot_trampoline_end)   /* 2kB (256 entries) */
-#define vesa_glob_info (modelist + 0x800)        /* 1kB */
-#define vesa_mode_info (vesa_glob_info + 0x400)  /* 1kB */
+/* Scratch space layout: bootdata_end to bootdata_end+0x1000. */
+#define modelist(t)       bootdatasym_rel(bootdata_end,2,t)         /* 2KiB (256 entries) */
+#define vesa_glob_info(t) bootdatasym_rel((bootdata_end+0x800),2,t) /* 1KiB */
+#define vesa_mode_info(t) bootdatasym_rel((bootdata_end+0xc00),2,t) /* 1KiB */
 
 /* Retrieve Extended Display Identification Data. */
 #define CONFIG_FIRMWARE_EDID
@@ -113,7 +113,7 @@  mopar2: movb    %al, _param(PARAM_VIDEO_LINES)
 
 # Fetching of VESA frame buffer parameters
 mopar_gr:
-        leaw    vesa_mode_info, %di
+        leaw    vesa_mode_info(%di)
         movb    $0x23, _param(PARAM_HAVE_VGA)
         movw    16(%di), %ax
         movw    %ax, _param(PARAM_LFB_LINELENGTH)
@@ -134,7 +134,7 @@  mopar_gr:
         movw    %ax, _param(PARAM_VESA_ATTRIB)
 
 # get video mem size
-        leaw    vesa_glob_info, %di
+        leaw    vesa_glob_info(%di)
         xorl    %eax, %eax
         movw    18(%di), %ax
         movl    %eax, _param(PARAM_LFB_SIZE)
@@ -226,7 +226,7 @@  an1:    call    prtstr
         leaw    bootsym(listhdr), %si   # Table header
         call    prtstr
         movb    $0x30, %dl              # DL holds mode number
-        leaw    modelist, %si
+        leaw    modelist(%si)
 lm1:    cmpw    $ASK_VGA, (%si)         # End?
         jz      lm2
 
@@ -435,13 +435,13 @@  setmenu:
         jmp     mode_set
 
 check_vesa:
-        leaw    vesa_glob_info, %di
+        leaw    vesa_glob_info(%di)
         movw    $0x4f00, %ax
         int     $0x10
         cmpw    $0x004f, %ax
         jnz     setbad
 
-        leaw    vesa_mode_info, %di
+        leaw    vesa_mode_info(%di)
         subb    $VIDEO_FIRST_VESA>>8, %bh
         movw    %bx, %cx                # Get mode information structure
         movw    $0x4f01, %ax
@@ -509,7 +509,7 @@  inidx:  outb    %al, %dx                # Read from indexed VGA register
 
 setvesabysize:
         call    mode_table
-        leaw    modelist,%si
+        leaw    modelist(%si)
 1:      add     $8,%si
         cmpw    $ASK_VGA,-8(%si)        # End?
         je      _setbad
@@ -669,7 +669,7 @@  mode_table:
         orw     %di, %di
         jnz     mtab1
 
-        leaw    modelist, %di           # Store standard modes:
+        leaw    modelist(%di)           # Store standard modes:
         movw    $VIDEO_80x25,(%di)      # The 80x25 mode (ALL)
         movw    $0x50,2(%di)
         movw    $0x19,4(%di)
@@ -684,7 +684,7 @@  mode_table:
 
         movw    $ASK_VGA, (%di)         # End marker
         movw    %di, bootsym(mt_end)
-mtab1:  leaw    modelist, %si           # SI=mode list, DI=list end
+mtab1:  leaw    modelist(%si)           # SI=mode list, DI=list end
 ret0:   ret
 
 # Modes usable on all standard VGAs
@@ -700,7 +700,7 @@  vga_modes_end:
 # Detect VESA modes.
 vesa_modes:
         movw    %di, %bp                # BP=original mode table end
-        leaw    vesa_glob_info, %di
+        leaw    vesa_glob_info(%di)
         movw    $0x4f00, %ax            # VESA Get card info call
         int     $0x10
         movw    %di, %si
@@ -897,7 +897,7 @@  store_edid:
         cmpb    $1, bootsym(opt_edid)   # EDID disabled on cmdline (edid=no)?
         je      .Lno_edid
 
-        leaw    vesa_glob_info, %di
+        leaw    vesa_glob_info(%di)
         movw    $0x4f00, %ax
         int     $0x10
         cmpw    $0x004f, %ax
@@ -990,6 +990,7 @@  name_bann:      .asciz  "Video adapter: "
 
 force_size:     .word   0       # Use this size instead of the one in BIOS vars
 
+        .pushsection .data.boot16, "aw", @progbits
 GLOBAL(boot_vid_info)
         .byte   0, 0    /* orig_x, orig_y */
         .byte   3       /* text mode 3    */
@@ -1001,3 +1002,4 @@  GLOBAL(boot_edid_info)
         .fill   128,1,0x13
 GLOBAL(boot_edid_caps)
         .word   0x1313
+        .popsection
diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c
index b19f6ec4ed..9a56bd8f84 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -318,10 +318,10 @@  ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
             u16 length;
 
             ret = -ESRCH;
-            if ( op->u.firmware_info.index >= bootsym(boot_edd_info_nr) )
+            if ( op->u.firmware_info.index >= boot_edd_info_nr )
                 break;
 
-            info = bootsym(boot_edd_info) + op->u.firmware_info.index;
+            info = boot_edd_info + op->u.firmware_info.index;
 
             /* Transfer the EDD info block. */
             ret = -EFAULT;
@@ -357,10 +357,10 @@  ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
             const struct mbr_signature *sig;
 
             ret = -ESRCH;
-            if ( op->u.firmware_info.index >= bootsym(boot_mbr_signature_nr) )
+            if ( op->u.firmware_info.index >= boot_mbr_signature_nr )
                 break;
 
-            sig = bootsym(boot_mbr_signature) + op->u.firmware_info.index;
+            sig = boot_mbr_signature + op->u.firmware_info.index;
 
             op->u.firmware_info.u.disk_mbr_signature.device = sig->device;
             op->u.firmware_info.u.disk_mbr_signature.mbr_signature =
@@ -376,13 +376,13 @@  ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
 #ifdef CONFIG_VIDEO
             if ( op->u.firmware_info.index != 0 )
                 break;
-            if ( *(u32 *)bootsym(boot_edid_info) == 0x13131313 )
+            if ( *(u32 *)boot_edid_info == 0x13131313 )
                 break;
 
             op->u.firmware_info.u.vbeddc_info.capabilities =
-                bootsym(boot_edid_caps);
+                boot_edid_caps;
             op->u.firmware_info.u.vbeddc_info.edid_transfer_time =
-                bootsym(boot_edid_caps) >> 8;
+                boot_edid_caps >> 8;
 
             ret = 0;
             if ( __copy_field_to_guest(u_xenpf_op, op, u.firmware_info.
@@ -390,7 +390,7 @@  ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
                  __copy_field_to_guest(u_xenpf_op, op, u.firmware_info.
                                        u.vbeddc_info.edid_transfer_time) ||
                  copy_to_compat(op->u.firmware_info.u.vbeddc_info.edid,
-                                bootsym(boot_edid_info), 128) )
+                                boot_edid_info, 128) )
                 ret = -EFAULT;
 #endif
             break;
@@ -407,7 +407,7 @@  ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
             if ( op->u.firmware_info.index != 0 )
                 break;
 
-            op->u.firmware_info.u.kbd_shift_flags = bootsym(kbd_shift_flags);
+            op->u.firmware_info.u.kbd_shift_flags = kbd_shift_flags;
 
             ret = 0;
             if ( __copy_field_to_guest(u_xenpf_op, op,
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 06e779368c..101c9dd272 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -509,7 +509,7 @@  extern struct boot_video_info boot_vid_info;
 static void __init parse_video_info(void)
 {
 #ifdef CONFIG_VIDEO
-    struct boot_video_info *bvi = &bootsym(boot_vid_info);
+    struct boot_video_info *bvi = &boot_vid_info;
 
     /* vga_console_info is filled directly on EFI platform. */
     if ( efi_enabled(EFI_BOOT) )
@@ -674,10 +674,10 @@  static char * __init cmdline_cook(char *p, const char *loader_name)
 
 static unsigned int __init copy_bios_e820(struct e820entry *map, unsigned int limit)
 {
-    unsigned int n = min(bootsym(bios_e820nr), limit);
+    unsigned int n = min(bios_e820nr, limit);
 
     if ( n )
-        memcpy(map, bootsym(bios_e820map), sizeof(*map) * n);
+        memcpy(map, bios_e820map, sizeof(*map) * n);
 
     return n;
 }
@@ -818,15 +818,15 @@  void __init noreturn __start_xen(unsigned long mbi_p)
     }
 
     /* Print VBE/DDC EDID information. */
-    if ( bootsym(boot_edid_caps) != 0x1313 )
+    if ( boot_edid_caps != 0x1313 )
     {
-        u16 caps = bootsym(boot_edid_caps);
+        u16 caps = boot_edid_caps;
         printk(" VBE/DDC methods:%s%s%s; ",
                (caps & 1) ? " V1" : "",
                (caps & 2) ? " V2" : "",
                !(caps & 3) ? " none" : "");
         printk("EDID transfer time: %d seconds\n", caps >> 8);
-        if ( *(u32 *)bootsym(boot_edid_info) == 0x13131313 )
+        if ( *(u32 *)boot_edid_info == 0x13131313 )
         {
             printk(" EDID info not retrieved because ");
             if ( !(caps & 3) )
@@ -841,9 +841,9 @@  void __init noreturn __start_xen(unsigned long mbi_p)
 
     printk("Disc information:\n");
     printk(" Found %d MBR signatures\n",
-           bootsym(boot_mbr_signature_nr));
+           boot_mbr_signature_nr);
     printk(" Found %d EDD information structures\n",
-           bootsym(boot_edd_info_nr));
+           boot_edd_info_nr);
 
     /* Check that we have at least one Multiboot module. */
     if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
@@ -926,14 +926,14 @@  void __init noreturn __start_xen(unsigned long mbi_p)
             bytes += map->size + 4;
         }
     }
-    else if ( bootsym(lowmem_kb) )
+    else if ( lowmem_kb )
     {
         memmap_type = "Xen-e801";
         e820_raw.map[0].addr = 0;
-        e820_raw.map[0].size = bootsym(lowmem_kb) << 10;
+        e820_raw.map[0].size = lowmem_kb << 10;
         e820_raw.map[0].type = E820_RAM;
         e820_raw.map[1].addr = 0x100000;
-        e820_raw.map[1].size = bootsym(highmem_kb) << 10;
+        e820_raw.map[1].size = highmem_kb << 10;
         e820_raw.map[1].type = E820_RAM;
         e820_raw.nr_map = 2;
     }
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 6968262a60..acc1e2d593 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -244,11 +244,13 @@  SECTIONS
        __trampoline32_rel_stop = .;
        __bootsym_rel_start = .;
        *(.bootsym_rel)
-       *(.bootdatasym_rel)
        __bootsym_rel_stop = .;
        __bootsym_seg_start = .;
        *(.bootsym_seg)
        __bootsym_seg_stop = .;
+       __bootdatasym_rel_start = .;
+       *(.bootdatasym_rel)
+       __bootdatasym_rel_stop = .;
        /*
         * struct alt_inst entries. From the header (alternative.h):
         * "Alternative instructions for different CPU types or capabilities"
@@ -291,6 +293,10 @@  SECTIONS
   DECL_SECTION(.data) {
        *(.data.page_aligned)
        *(.data)
+       . = ALIGN(16);
+       __bootdata_start = .;
+       *(.data.boot16)
+       __bootdata_end = .;
        *(.data.rel)
        *(.data.rel.*)
        CONSTRUCTORS
diff --git a/xen/include/asm-x86/edd.h b/xen/include/asm-x86/edd.h
index afaa23732a..a4d6b4d90e 100644
--- a/xen/include/asm-x86/edd.h
+++ b/xen/include/asm-x86/edd.h
@@ -143,7 +143,6 @@  struct __packed mbr_signature {
     u32 signature;
 };
 
-/* These all reside in the boot trampoline. Access via bootsym(). */
 extern struct mbr_signature boot_mbr_signature[];
 extern u8 boot_mbr_signature_nr;
 extern struct edd_info boot_edd_info[];