* [PATCH v7 1/5] x86/boot: Rework how 32bit C is linked/included for early boot
2024-10-29 10:29 [PATCH v7 0/5] Reuse 32 bit C code more safely Frediano Ziglio
@ 2024-10-29 10:29 ` Frediano Ziglio
2024-10-29 15:09 ` Andrew Cooper
2024-10-29 10:29 ` [PATCH v7 2/5] x86/boot: Reuse code to relocate trampoline Frediano Ziglio
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Frediano Ziglio @ 2024-10-29 10:29 UTC (permalink / raw)
To: xen-devel
Cc: Frediano Ziglio, Jan Beulich, Andrew Cooper, Roger Pau Monné,
Julien Grall, Stefano Stabellini, Anthony PERARD
Right now, the two functions which were really too complicated to write
in asm are compiled as 32bit PIC, linked to a blob and included
directly, using global asm() to arrange for them to have function semantics.
This is limiting and fragile; the use of data relocations will compile
fine but malfunction when used, creating hard-to-debug bugs.
Furthermore, we would like to increase the amount of C, to
deduplicate/unify Xen's boot logic, as well as making it easier to
follow. Therefore, rework how the 32bit objects are included.
Link all 32bit objects together first. This allows for sharing of logic
between translation units. Use differential linking and explicit
imports/exports to confirm that we only have the expected relocations,
and write the object back out as an assembly file so it can be linked
again as if it were 64bit, to integrate with the rest of Xen.
This allows for the use of external references (e.g. access to global
variables) with reasonable assurance of doing so safely.
No functional change.
Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
---
Changes since v2:
- removed W^X limitation, allowing data;
- added some comments to python script;
- added extension to python script;
- added header to generated assembly code from python script;
- added starting symbol to generated assembly code from python script
to make disassembly more clear;
- other minor style changes to python script.
Changes since v4:
- add build32.final.lds build32.other.lds to targets macro;
- place some comments over a rule, not inside;
- simplified linking and producing binary rule;
- renamed built_in_32 to built-in-32, coding style;
- fix minor indentation;
- put magic numbers in Makefile and propagate them;
- minor variable cleanups in Python script;
- add dependency to Python script.
Changes since v5:
- renamed "other" and "final" phases to "base" and "offset";
- use if_changed macro to generate built-in-32.S.
Changes since v6:
- update some indentation to make code more coherent;
- move some comments from commit message to code;
- rewrote commit message (Andrew Cooper);
- add missing file to .gitignore;
- rollback a change in section order.
---
xen/arch/x86/boot/.gitignore | 6 +-
xen/arch/x86/boot/Makefile | 66 +++++-
.../x86/boot/{build32.lds => build32.lds.S} | 35 ++-
xen/arch/x86/boot/cmdline.c | 12 -
xen/arch/x86/boot/head.S | 12 -
xen/arch/x86/boot/reloc.c | 14 --
xen/tools/combine_two_binaries.py | 220 ++++++++++++++++++
7 files changed, 314 insertions(+), 51 deletions(-)
rename xen/arch/x86/boot/{build32.lds => build32.lds.S} (66%)
create mode 100755 xen/tools/combine_two_binaries.py
diff --git a/xen/arch/x86/boot/.gitignore b/xen/arch/x86/boot/.gitignore
index a379db7988..595cef6a2c 100644
--- a/xen/arch/x86/boot/.gitignore
+++ b/xen/arch/x86/boot/.gitignore
@@ -1,3 +1,5 @@
/mkelf32
-/*.bin
-/*.lnk
+/build32.*.lds
+/built-in-32.*.bin
+/built-in-32.*.map
+/built-in-32.S
diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile
index 1199291d2b..230a99a1e5 100644
--- a/xen/arch/x86/boot/Makefile
+++ b/xen/arch/x86/boot/Makefile
@@ -1,4 +1,5 @@
obj-bin-y += head.o
+obj-bin-y += built-in-32.o
obj32 := cmdline.32.o
obj32 += reloc.32.o
@@ -9,9 +10,6 @@ targets += $(obj32)
obj32 := $(addprefix $(obj)/,$(obj32))
-$(obj)/head.o: AFLAGS-y += -Wa$(comma)-I$(obj)
-$(obj)/head.o: $(obj32:.32.o=.bin)
-
CFLAGS_x86_32 := $(subst -m64,-m32 -march=i686,$(XEN_TREEWIDE_CFLAGS))
$(call cc-options-add,CFLAGS_x86_32,CC,$(EMBEDDED_EXTRA_CFLAGS))
CFLAGS_x86_32 += -Werror -fno-builtin -g0 -msoft-float -mregparm=3
@@ -25,14 +23,66 @@ $(obj32): XEN_CFLAGS := $(CFLAGS_x86_32) -fpic
$(obj)/%.32.o: $(src)/%.c FORCE
$(call if_changed_rule,cc_o_c)
+orphan-handling-$(call ld-option,--orphan-handling=error) := --orphan-handling=error
LDFLAGS_DIRECT-$(call ld-option,--warn-rwx-segments) := --no-warn-rwx-segments
LDFLAGS_DIRECT += $(LDFLAGS_DIRECT-y)
LD32 := $(LD) $(subst x86_64,i386,$(LDFLAGS_DIRECT))
-%.bin: %.lnk
- $(OBJCOPY) -j .text -O binary $< $@
+# The parameters below tweak the generated linker scripts:
+# - text_gap: padding between .text section external symbols and code.
+# - text_diff: address of the .text section.
+#
+# Note external symbols are only affected by text_diff, while internal symbols
+# are affected by both text_diff and text_gap. Ensure the sum of gap and diff
+# is greater than 2^16 so that any 16bit relocations if present in the object
+# file turns into a build-time error.
+text_gap := 0x010200
+text_diff := 0x408020
+
+$(obj)/build32.base.lds: AFLAGS-y += -DGAP=$(text_gap) -DTEXT_DIFF=$(text_diff)
+$(obj)/build32.offset.lds: AFLAGS-y += -DGAP=$(text_gap) -DTEXT_DIFF=$(text_diff) -DFINAL
+$(obj)/build32.base.lds $(obj)/build32.offset.lds: $(src)/build32.lds.S FORCE
+ $(call if_changed_dep,cpp_lds_S)
+
+targets += build32.offset.lds build32.base.lds
+
+# Generate a single 32bit object.
+#
+# Resolve any relocations resulting from references between the translation
+# units. This ensures the same combined object file can be used to generate
+# multiple images with slightly different linker scripts.
+$(obj)/built-in-32.tmp.o: $(obj32)
+ $(LD32) -r -o $@ $^
+
+# Link bundle with a given layout and extract a binary from it.
+# The linker will allocate GOP and resolve symbols specified in the linker
+# script.
+# The conversion to binary avoids polluting global symbols not used externally;
+# also removes conflict with needed 64 bit GOP.
+# If possible we use --orphan-handling=error option to make sure we account
+# for all possible sections from C code.
+$(obj)/built-in-32.%.bin: $(obj)/build32.%.lds $(obj)/built-in-32.tmp.o
+ $(LD32) $(orphan-handling-y) -N -T $< -Map $(@:bin=map) -o $(@:bin=o) $(filter %.o,$^)
+ $(OBJCOPY) -j .text -O binary $(@:bin=o) $@
+ rm -f $(@:bin=o)
+
+quiet_cmd_combine = GEN $@
+cmd_combine = \
+ $(PYTHON) $(srctree)/tools/combine_two_binaries.py \
+ --gap $(text_gap) \
+ --text-diff $(text_diff) \
+ --script $(obj)/build32.offset.lds \
+ --bin1 $(obj)/built-in-32.base.bin \
+ --bin2 $(obj)/built-in-32.offset.bin \
+ --map $(obj)/built-in-32.offset.map \
+ --exports cmdline_parse_early,reloc \
+ --output $@
+
+targets += built-in-32.S
-%.lnk: %.32.o $(src)/build32.lds
- $(LD32) -N -T $(filter %.lds,$^) -o $@ $<
+# generate final object file combining and checking above binaries
+$(obj)/built-in-32.S: $(obj)/built-in-32.base.bin $(obj)/built-in-32.offset.bin \
+ $(srctree)/tools/combine_two_binaries.py FORCE
+ $(call if_changed,combine)
-clean-files := *.lnk *.bin
+clean-files := built-in-32.*.bin built-in-32.*.map build32.*.lds
diff --git a/xen/arch/x86/boot/build32.lds b/xen/arch/x86/boot/build32.lds.S
similarity index 66%
rename from xen/arch/x86/boot/build32.lds
rename to xen/arch/x86/boot/build32.lds.S
index 56edaa727b..d1b9dc6689 100644
--- a/xen/arch/x86/boot/build32.lds
+++ b/xen/arch/x86/boot/build32.lds.S
@@ -15,12 +15,37 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-ENTRY(_start)
+#ifdef FINAL
+# undef GAP
+# define GAP 0
+# define MULT 0
+# define TEXT_START
+#else
+# define MULT 1
+# define TEXT_START TEXT_DIFF
+#endif
+#define DECLARE_IMPORT(name) name = . + (__LINE__ * MULT)
+
+ENTRY(dummy_start)
SECTIONS
{
/* Merge code and data into one section. */
- .text : {
+ .text TEXT_START : {
+ /* Silence linker warning, we are not going to use it */
+ dummy_start = .;
+
+ /*
+ * Any symbols used should be declared below, this ensures which
+ * symbols are visible to the 32bit C boot code.
+ * With the exception of using external 32 bit function (maybe
+ * exported by head.S) they should point all to variables.
+ * Attention should be paid to pointers taking care of possible later
+ * relocation.
+ */
+ DECLARE_IMPORT(__base_relocs_start);
+ DECLARE_IMPORT(__base_relocs_end);
+ . = . + GAP;
*(.text)
*(.text.*)
*(.data)
@@ -30,7 +55,11 @@ SECTIONS
*(.bss)
*(.bss.*)
}
-
+ /DISCARD/ : {
+ *(.comment)
+ *(.comment.*)
+ *(.note.*)
+ }
/* Dynamic linkage sections. Collected simply so we can check they're empty. */
.got : {
*(.got)
diff --git a/xen/arch/x86/boot/cmdline.c b/xen/arch/x86/boot/cmdline.c
index fc9241ede9..196c580e91 100644
--- a/xen/arch/x86/boot/cmdline.c
+++ b/xen/arch/x86/boot/cmdline.c
@@ -18,18 +18,6 @@
* Linux kernel source (linux/lib/string.c).
*/
-/*
- * This entry point is entered from xen/arch/x86/boot/head.S with:
- * - %eax = &cmdline,
- * - %edx = &early_boot_opts.
- */
-asm (
- " .text \n"
- " .globl _start \n"
- "_start: \n"
- " jmp cmdline_parse_early \n"
- );
-
#include <xen/compiler.h>
#include <xen/kconfig.h>
#include <xen/macros.h>
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index c4de1dfab5..e0776e3896 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -759,18 +759,6 @@ trampoline_setup:
/* Jump into the relocated trampoline. */
lret
- /*
- * cmdline and reloc are written in C, and linked to be 32bit PIC with
- * entrypoints at 0 and using the fastcall convention.
- */
-FUNC_LOCAL(cmdline_parse_early)
- .incbin "cmdline.bin"
-END(cmdline_parse_early)
-
-FUNC_LOCAL(reloc)
- .incbin "reloc.bin"
-END(reloc)
-
ENTRY(trampoline_start)
#include "trampoline.S"
ENTRY(trampoline_end)
diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index 8c58affcd9..94b078d7b1 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -12,20 +12,6 @@
* Daniel Kiper <daniel.kiper@oracle.com>
*/
-/*
- * This entry point is entered from xen/arch/x86/boot/head.S with:
- * - %eax = MAGIC,
- * - %edx = INFORMATION_ADDRESS,
- * - %ecx = TOPMOST_LOW_MEMORY_STACK_ADDRESS.
- * - 0x04(%esp) = BOOT_VIDEO_INFO_ADDRESS.
- */
-asm (
- " .text \n"
- " .globl _start \n"
- "_start: \n"
- " jmp reloc \n"
- );
-
#include <xen/compiler.h>
#include <xen/macros.h>
#include <xen/types.h>
diff --git a/xen/tools/combine_two_binaries.py b/xen/tools/combine_two_binaries.py
new file mode 100755
index 0000000000..447c0d3bdb
--- /dev/null
+++ b/xen/tools/combine_two_binaries.py
@@ -0,0 +1,220 @@
+#!/usr/bin/env python3
+
+from __future__ import print_function
+import argparse
+import functools
+import re
+import struct
+import sys
+
+parser = argparse.ArgumentParser(description='Generate assembly file to merge into other code.')
+auto_int = functools.update_wrapper(lambda x: int(x, 0), int) # allows hex
+parser.add_argument('--script', dest='script',
+ required=True,
+ help='Linker script for extracting symbols')
+parser.add_argument('--bin1', dest='bin1',
+ required=True,
+ help='First binary')
+parser.add_argument('--bin2', dest='bin2',
+ required=True,
+ help='Second binary')
+parser.add_argument('--gap', dest='gap',
+ required=True,
+ type=auto_int,
+ help='Gap inserted at the start of code section')
+parser.add_argument('--text-diff', dest='text_diff',
+ required=True,
+ type=auto_int,
+ help='Difference between code section start')
+parser.add_argument('--output', dest='output',
+ help='Output file')
+parser.add_argument('--map', dest='mapfile',
+ help='Map file to read for symbols to export')
+parser.add_argument('--exports', dest='exports',
+ help='Symbols to export')
+parser.add_argument('--section-header', dest='section_header',
+ default='.section .init.text, "ax", @progbits',
+ help='Section header declaration')
+parser.add_argument('-v', '--verbose',
+ action='store_true')
+args = parser.parse_args()
+
+gap = args.gap
+text_diff = args.text_diff
+
+# Parse linker script for external symbols to use.
+# Next regex matches expanded DECLARE_IMPORT lines in linker script.
+symbol_re = re.compile(r'\s+(\S+)\s*=\s*\.\s*\+\s*\((\d+)\s*\*\s*0\s*\)\s*;')
+symbols = {}
+lines = {}
+for line in open(args.script):
+ m = symbol_re.match(line)
+ if not m:
+ continue
+ (name, line_num) = (m.group(1), int(m.group(2)))
+ if line_num == 0:
+ raise Exception("Invalid line number found:\n\t" + line)
+ if line_num in symbols:
+ raise Exception("Symbol with this line already present:\n\t" + line)
+ if name in lines:
+ raise Exception("Symbol with this name already present:\n\t" + name)
+ symbols[line_num] = name
+ lines[name] = line_num
+
+exports = []
+if args.exports is not None:
+ exports = dict([(name, None) for name in args.exports.split(',')])
+
+# Parse mapfile, look for ther symbols we want to export.
+if args.mapfile is not None:
+ symbol_re = re.compile(r'\s{15,}0x([0-9a-f]+)\s+(\S+)\n')
+ for line in open(args.mapfile):
+ m = symbol_re.match(line)
+ if not m or m.group(2) not in exports:
+ continue
+ addr = int(m.group(1), 16)
+ exports[m.group(2)] = addr
+for (name, addr) in exports.items():
+ if addr is None:
+ raise Exception("Required export symbols %s not found" % name)
+
+file1 = open(args.bin1, 'rb')
+file2 = open(args.bin2, 'rb')
+file1.seek(0, 2)
+size1 = file1.tell()
+file2.seek(0, 2)
+size2 = file2.tell()
+if size1 > size2:
+ file1, file2 = file2, file1
+ size1, size2 = size2, size1
+if size2 != size1 + gap:
+ raise Exception('File sizes do not match')
+del size2
+
+file1.seek(0, 0)
+data1 = file1.read(size1)
+del file1
+file2.seek(gap, 0)
+data2 = file2.read(size1)
+del file2
+
+max_line = max(symbols.keys())
+
+def to_int32(n):
+ '''Convert a number to signed 32 bit integer truncating if needed'''
+ mask = (1 << 32) - 1
+ h = 1 << 31
+ return (n & mask) ^ h - h
+
+i = 0
+references = {}
+internals = 0
+while i <= size1 - 4:
+ n1 = struct.unpack('<I', data1[i:i+4])[0]
+ n2 = struct.unpack('<I', data2[i:i+4])[0]
+ i += 1
+ # The two numbers are the same, no problems
+ if n1 == n2:
+ continue
+ # Try to understand why they are different
+ diff = to_int32(n1 - n2)
+ if diff == -gap: # this is an internal relocation
+ pos = i - 1
+ print("Internal relocation found at position %#x "
+ "n1=%#x n2=%#x diff=%#x" % (pos, n1, n2, diff),
+ file=sys.stderr)
+ i += 3
+ internals += 1
+ if internals >= 10:
+ break
+ continue
+ # This is a relative relocation to a symbol, accepted, code/data is
+ # relocatable.
+ if diff < gap and diff >= gap - max_line:
+ n = gap - diff
+ symbol = symbols.get(n)
+ # check we have a symbol
+ if symbol is None:
+ raise Exception("Cannot find symbol for line %d" % n)
+ pos = i - 1
+ if args.verbose:
+ print('Position %#x %d %s' % (pos, n, symbol), file=sys.stderr)
+ i += 3
+ references[pos] = symbol
+ continue
+ # First byte is the same, move to next byte
+ if diff & 0xff == 0 and i <= size1 - 4:
+ continue
+ # Probably a type of relocation we don't want or support
+ pos = i - 1
+ suggestion = ''
+ symbol = symbols.get(-diff - text_diff)
+ if symbol is not None:
+ suggestion = " Maybe %s is not defined as hidden?" % symbol
+ raise Exception("Unexpected difference found at %#x "
+ "n1=%#x n2=%#x diff=%#x gap=%#x.%s" % \
+ (pos, n1, n2, diff, gap, suggestion))
+if internals != 0:
+ raise Exception("Previous relocations found")
+
+def line_bytes(buf, out):
+ '''Output an assembly line with all bytes in "buf"'''
+ # Python 2 compatibility
+ if type(buf) == str:
+ print("\t.byte " + ','.join([str(ord(c)) for c in buf]), file=out)
+ else:
+ print("\t.byte " + ','.join([str(n) for n in buf]), file=out)
+
+def part(start, end, out):
+ '''Output bytes of "data" from "start" to "end"'''
+ while start < end:
+ e = min(start + 16, end)
+ line_bytes(data1[start:e], out)
+ start = e
+
+def reference(pos, out):
+ name = references[pos]
+ n = struct.unpack('<I', data1[pos:pos+4])[0]
+ sign = '+'
+ if n >= (1 << 31):
+ n -= (1 << 32)
+ n += pos
+ if n < 0:
+ n = -n
+ sign = '-'
+ print("\t.hidden %s\n"
+ "\t.long %s %s %#x - ." % (name, name, sign, n),
+ file=out)
+
+def output(out):
+ prev = 0
+ exports_by_addr = {}
+ for (sym, addr) in exports.items():
+ exports_by_addr.setdefault(addr, []).append(sym)
+ positions = list(references.keys())
+ positions += list(exports_by_addr.keys())
+ for pos in sorted(positions):
+ part(prev, pos, out)
+ prev = pos
+ if pos in references:
+ reference(pos, out)
+ prev = pos + 4
+ if pos in exports_by_addr:
+ for sym in exports_by_addr[pos]:
+ print("\t.global %s\n"
+ "\t.hidden %s\n"
+ "%s:" % (sym, sym, sym),
+ file=out)
+ part(prev, size1, out)
+
+out = sys.stdout
+if args.output is not None:
+ out = open(args.output, 'w')
+print('''/*
+ * File autogenerated by combine_two_binaries.py DO NOT EDIT
+ */''', file=out)
+print('\t' + args.section_header, file=out)
+print('obj32_start:', file=out)
+output(out)
+print('\n\t.section .note.GNU-stack,"",@progbits', file=out)
+out.flush()
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v7 2/5] x86/boot: Reuse code to relocate trampoline
2024-10-29 10:29 [PATCH v7 0/5] Reuse 32 bit C code more safely Frediano Ziglio
2024-10-29 10:29 ` [PATCH v7 1/5] x86/boot: Rework how 32bit C is linked/included for early boot Frediano Ziglio
@ 2024-10-29 10:29 ` Frediano Ziglio
2024-10-29 10:29 ` [PATCH v7 3/5] x86/boot: Use boot_vid_info variable directly from C code Frediano Ziglio
` (2 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Frediano Ziglio @ 2024-10-29 10:29 UTC (permalink / raw)
To: xen-devel
Cc: Frediano Ziglio, Jan Beulich, Andrew Cooper, Roger Pau Monné,
Daniel P. Smith, Marek Marczykowski-Górecki
Move code from efi-boot.h to a separate, new, reloc-trampoline.c file.
Reuse this new code, compiling it for 32bit as well, to replace assembly
code in head.S doing the same thing.
Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
Changes since v3:
- fixed a typo in comment;
- added Reviewed-by.
Changes since v5:
- do not add obj64 to targets, already done adding it to obj-bin-y.
Changes since v6:
- added Acked-by.
---
xen/arch/x86/boot/Makefile | 10 +++++---
xen/arch/x86/boot/build32.lds.S | 5 ++++
xen/arch/x86/boot/head.S | 23 +-----------------
xen/arch/x86/boot/reloc-trampoline.c | 36 ++++++++++++++++++++++++++++
xen/arch/x86/efi/efi-boot.h | 15 ++----------
5 files changed, 51 insertions(+), 38 deletions(-)
create mode 100644 xen/arch/x86/boot/reloc-trampoline.c
diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile
index 230a99a1e5..e102bd8c70 100644
--- a/xen/arch/x86/boot/Makefile
+++ b/xen/arch/x86/boot/Makefile
@@ -1,11 +1,15 @@
obj-bin-y += head.o
obj-bin-y += built-in-32.o
+obj-bin-y += $(obj64)
obj32 := cmdline.32.o
obj32 += reloc.32.o
+obj32 += reloc-trampoline.32.o
-nocov-y += $(obj32)
-noubsan-y += $(obj32)
+obj64 := reloc-trampoline.o
+
+nocov-y += $(obj32) $(obj64)
+noubsan-y += $(obj32) $(obj64)
targets += $(obj32)
obj32 := $(addprefix $(obj)/,$(obj32))
@@ -75,7 +79,7 @@ cmd_combine = \
--bin1 $(obj)/built-in-32.base.bin \
--bin2 $(obj)/built-in-32.offset.bin \
--map $(obj)/built-in-32.offset.map \
- --exports cmdline_parse_early,reloc \
+ --exports cmdline_parse_early,reloc,reloc_trampoline32 \
--output $@
targets += built-in-32.S
diff --git a/xen/arch/x86/boot/build32.lds.S b/xen/arch/x86/boot/build32.lds.S
index d1b9dc6689..27f0d7ac3c 100644
--- a/xen/arch/x86/boot/build32.lds.S
+++ b/xen/arch/x86/boot/build32.lds.S
@@ -45,6 +45,11 @@ SECTIONS
*/
DECLARE_IMPORT(__base_relocs_start);
DECLARE_IMPORT(__base_relocs_end);
+ DECLARE_IMPORT(__trampoline_rel_start);
+ DECLARE_IMPORT(__trampoline_rel_stop);
+ DECLARE_IMPORT(__trampoline_seg_start);
+ DECLARE_IMPORT(__trampoline_seg_stop);
+ DECLARE_IMPORT(trampoline_phys);
. = . + GAP;
*(.text)
*(.text.*)
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index e0776e3896..ade2c5c43d 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -706,28 +706,7 @@ trampoline_setup:
mov %edx, sym_offs(l1_bootmap)(%esi, %ecx, 8)
/* Apply relocations to bootstrap trampoline. */
- mov sym_esi(trampoline_phys), %edx
- lea sym_esi(__trampoline_rel_start), %edi
- lea sym_esi(__trampoline_rel_stop), %ecx
-1:
- mov (%edi), %eax
- add %edx, (%edi, %eax)
- add $4,%edi
-
- cmp %ecx, %edi
- jb 1b
-
- /* Patch in the trampoline segment. */
- shr $4,%edx
- lea sym_esi(__trampoline_seg_start), %edi
- lea sym_esi(__trampoline_seg_stop), %ecx
-1:
- mov (%edi), %eax
- mov %dx, (%edi, %eax)
- add $4,%edi
-
- cmp %ecx, %edi
- jb 1b
+ call reloc_trampoline32
/* Do not parse command line on EFI platform here. */
cmpb $0, sym_esi(efi_platform)
diff --git a/xen/arch/x86/boot/reloc-trampoline.c b/xen/arch/x86/boot/reloc-trampoline.c
new file mode 100644
index 0000000000..0a74c1e75a
--- /dev/null
+++ b/xen/arch/x86/boot/reloc-trampoline.c
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/compiler.h>
+#include <xen/stdint.h>
+#include <asm/trampoline.h>
+
+extern const int32_t __trampoline_rel_start[], __trampoline_rel_stop[];
+extern const int32_t __trampoline_seg_start[], __trampoline_seg_stop[];
+
+#if defined(__i386__)
+void reloc_trampoline32(void)
+#elif defined (__x86_64__)
+void reloc_trampoline64(void)
+#else
+#error Unknown architecture
+#endif
+{
+ unsigned long phys = trampoline_phys;
+ const int32_t *trampoline_ptr;
+
+ /*
+ * Apply relocations to trampoline.
+ *
+ * This modifies the trampoline in place within Xen, so that it will
+ * operate correctly when copied into place.
+ */
+ for ( trampoline_ptr = __trampoline_rel_start;
+ trampoline_ptr < __trampoline_rel_stop;
+ ++trampoline_ptr )
+ *(uint32_t *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
+
+ for ( trampoline_ptr = __trampoline_seg_start;
+ trampoline_ptr < __trampoline_seg_stop;
+ ++trampoline_ptr )
+ *(uint16_t *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
+}
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 3b26f0b0f5..3133985c88 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -103,27 +103,16 @@ static void __init efi_arch_relocate_image(unsigned long delta)
}
}
-extern const int32_t __trampoline_rel_start[], __trampoline_rel_stop[];
-extern const int32_t __trampoline_seg_start[], __trampoline_seg_stop[];
+void reloc_trampoline64(void);
static void __init relocate_trampoline(unsigned long phys)
{
- const int32_t *trampoline_ptr;
-
trampoline_phys = phys;
if ( !efi_enabled(EFI_LOADER) )
return;
- /* Apply relocations to trampoline. */
- for ( trampoline_ptr = __trampoline_rel_start;
- trampoline_ptr < __trampoline_rel_stop;
- ++trampoline_ptr )
- *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
- for ( trampoline_ptr = __trampoline_seg_start;
- trampoline_ptr < __trampoline_seg_stop;
- ++trampoline_ptr )
- *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
+ reloc_trampoline64();
}
static void __init place_string(u32 *addr, const char *s)
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v7 3/5] x86/boot: Use boot_vid_info variable directly from C code
2024-10-29 10:29 [PATCH v7 0/5] Reuse 32 bit C code more safely Frediano Ziglio
2024-10-29 10:29 ` [PATCH v7 1/5] x86/boot: Rework how 32bit C is linked/included for early boot Frediano Ziglio
2024-10-29 10:29 ` [PATCH v7 2/5] x86/boot: Reuse code to relocate trampoline Frediano Ziglio
@ 2024-10-29 10:29 ` Frediano Ziglio
2024-10-29 10:29 ` [PATCH v7 4/5] x86/boot: Use trampoline_phys " Frediano Ziglio
2024-10-29 10:29 ` [PATCH v7 5/5] x86/boot: Clarify comment Frediano Ziglio
4 siblings, 0 replies; 11+ messages in thread
From: Frediano Ziglio @ 2024-10-29 10:29 UTC (permalink / raw)
To: xen-devel
Cc: Frediano Ziglio, Jan Beulich, Andrew Cooper, Roger Pau Monné
No more need to pass from assembly code.
Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
Changes since v1:
- split the 2 variable changes into 2 commits.
Changes since v2:
- revert commit order.
---
xen/arch/x86/boot/build32.lds.S | 1 +
xen/arch/x86/boot/head.S | 10 +---------
xen/arch/x86/boot/reloc.c | 13 +++++--------
3 files changed, 7 insertions(+), 17 deletions(-)
diff --git a/xen/arch/x86/boot/build32.lds.S b/xen/arch/x86/boot/build32.lds.S
index 27f0d7ac3c..f20fc18977 100644
--- a/xen/arch/x86/boot/build32.lds.S
+++ b/xen/arch/x86/boot/build32.lds.S
@@ -50,6 +50,7 @@ SECTIONS
DECLARE_IMPORT(__trampoline_seg_start);
DECLARE_IMPORT(__trampoline_seg_stop);
DECLARE_IMPORT(trampoline_phys);
+ DECLARE_IMPORT(boot_vid_info);
. = . + GAP;
*(.text)
*(.text.*)
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index ade2c5c43d..5da7ac138f 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -514,18 +514,10 @@ trampoline_setup:
mov sym_esi(trampoline_phys), %ecx
add $TRAMPOLINE_SPACE,%ecx
-#ifdef CONFIG_VIDEO
- lea sym_esi(boot_vid_info), %edx
-#else
- xor %edx, %edx
-#endif
-
/* Save Multiboot / PVH info struct (after relocation) for later use. */
- push %edx /* Boot video info to be filled from MB2. */
mov %ebx, %edx /* Multiboot / PVH information address. */
- /* reloc(magic/eax, info/edx, trampoline/ecx, video/stk) using fastcall. */
+ /* reloc(magic/eax, info/edx, trampoline/ecx) using fastcall. */
call reloc
- add $4, %esp
#ifdef CONFIG_PVH_GUEST
cmpb $0, sym_esi(pvh_boot)
diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c
index 94b078d7b1..707d9c5f15 100644
--- a/xen/arch/x86/boot/reloc.c
+++ b/xen/arch/x86/boot/reloc.c
@@ -176,7 +176,7 @@ static multiboot_info_t *mbi_reloc(uint32_t mbi_in, memctx *ctx)
return mbi_out;
}
-static multiboot_info_t *mbi2_reloc(uint32_t mbi_in, uint32_t video_out, memctx *ctx)
+static multiboot_info_t *mbi2_reloc(uint32_t mbi_in, memctx *ctx)
{
const multiboot2_fixed_t *mbi_fix = _p(mbi_in);
const multiboot2_memory_map_t *mmap_src;
@@ -185,7 +185,7 @@ static multiboot_info_t *mbi2_reloc(uint32_t mbi_in, uint32_t video_out, memctx
memory_map_t *mmap_dst;
multiboot_info_t *mbi_out;
#ifdef CONFIG_VIDEO
- struct boot_video_info *video = NULL;
+ struct boot_video_info *video = &boot_vid_info;
#endif
uint32_t ptr;
unsigned int i, mod_idx = 0;
@@ -290,12 +290,11 @@ static multiboot_info_t *mbi2_reloc(uint32_t mbi_in, uint32_t video_out, memctx
#ifdef CONFIG_VIDEO
case MULTIBOOT2_TAG_TYPE_VBE:
- if ( video_out )
+ if ( video )
{
const struct vesa_ctrl_info *ci;
const struct vesa_mode_info *mi;
- video = _p(video_out);
ci = (const void *)get_mb2_data(tag, vbe, vbe_control_info);
mi = (const void *)get_mb2_data(tag, vbe, vbe_mode_info);
@@ -321,7 +320,6 @@ static multiboot_info_t *mbi2_reloc(uint32_t mbi_in, uint32_t video_out, memctx
if ( (get_mb2_data(tag, framebuffer, framebuffer_type) !=
MULTIBOOT2_FRAMEBUFFER_TYPE_RGB) )
{
- video_out = 0;
video = NULL;
}
break;
@@ -346,8 +344,7 @@ static multiboot_info_t *mbi2_reloc(uint32_t mbi_in, uint32_t video_out, memctx
}
/* SAF-1-safe */
-void *reloc(uint32_t magic, uint32_t in, uint32_t trampoline,
- uint32_t video_info)
+void *reloc(uint32_t magic, uint32_t in, uint32_t trampoline)
{
memctx ctx = { trampoline };
@@ -357,7 +354,7 @@ void *reloc(uint32_t magic, uint32_t in, uint32_t trampoline,
return mbi_reloc(in, &ctx);
case MULTIBOOT2_BOOTLOADER_MAGIC:
- return mbi2_reloc(in, video_info, &ctx);
+ return mbi2_reloc(in, &ctx);
case XEN_HVM_START_MAGIC_VALUE:
if ( IS_ENABLED(CONFIG_PVH_GUEST) )
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread