Scanning for embedded endbranch instructions involves parsing the .text
disassembly. Data in the kexec trampoline has no ELF metadata, so objdump
treats it as instructions and tries to disassemble. Convert:
ffff82d040396108 <compatibility_mode_far>:
ffff82d040396108: 00 00 add %al,(%rax)
ffff82d04039610a: 00 00 add %al,(%rax)
ffff82d04039610c: 10 00 adc %al,(%rax)
ffff82d04039610e <compat_mode_gdt_desc>:
ffff82d04039610e: 17 (bad)
...
ffff82d040396118 <compat_mode_gdt>:
...
ffff82d040396120: ff (bad)
ffff82d040396121: ff 00 incl (%rax)
ffff82d040396123: 00 00 add %al,(%rax)
ffff82d040396125: 93 xchg %eax,%ebx
ffff82d040396126: cf iret
ffff82d040396127: 00 ff add %bh,%bh
ffff82d040396129: ff 00 incl (%rax)
ffff82d04039612b: 00 00 add %al,(%rax)
ffff82d04039612d: 9b fwait
ffff82d04039612e: cf iret
...
ffff82d040396130 <compat_mode_idt>:
...
ffff82d0403961b6 <kexec_reloc_size>:
ffff82d0403961b6: b6 01 mov $0x1,%dh
...
to:
ffff82d040396108 <compatibility_mode_far>:
ffff82d040396108: 00 00 00 00 10 00 ......
ffff82d04039610e <compat_mode_gdt_desc>:
ffff82d04039610e: 17 00 00 00 00 00 00 00 00 00
..........
ffff82d040396118 <compat_mode_gdt>:
...
ffff82d040396120: ff ff 00 00 00 93 cf 00 ff ff 00 00 00 9b cf 00
................
ffff82d040396130 <compat_mode_idt>:
ffff82d040396130: 00 00 00 00 00 00 ......
ffff82d040396136 <reloc_stack>:
...
Most data just gains type and size metadata.
The reloc_stack label is the wrong end of the data block to have a size, so
move it to the lowest address and introduce .Lreloc_stack_base as a
replacement. Also, fix the fact that it is misaligned by 2 bytes.
While kexec_reloc_size could gain metadata, it's use in the linker
assertion (while correct) is deeply confusing to follow. Drop it entirely,
using a linker symbol instead to denote the end of the trampoline.
No functional change.
Signed-off-by: Andrew Cooper <[email protected]>
Reviewed-by: Jan Beulich <[email protected]>
---
CC: Jan Beulich <[email protected]>
CC: Roger Pau Monné <[email protected]>
CC: Wei Liu <[email protected]>
The remainder of the 32bit code has mode-invariant lengths, so disassembles
safely as 64bit. The only differences come from 32/64bit implicit register
sizes.
v2.1:
* New
v2.2:
* Fix stack alignment
---
xen/arch/x86/include/asm/machine_kexec.h | 2 +-
xen/arch/x86/machine_kexec.c | 2 +-
xen/arch/x86/x86_64/kexec_reloc.S | 23 ++++++++++++++++++-----
xen/arch/x86/xen.lds.S | 3 ++-
4 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/xen/arch/x86/include/asm/machine_kexec.h
b/xen/arch/x86/include/asm/machine_kexec.h
index ba0d469d077b..d4880818c1d9 100644
--- a/xen/arch/x86/include/asm/machine_kexec.h
+++ b/xen/arch/x86/include/asm/machine_kexec.h
@@ -9,7 +9,7 @@ extern void kexec_reloc(unsigned long reloc_code, unsigned long
reloc_pt,
unsigned long ind_maddr, unsigned long entry_maddr,
unsigned long flags);
-extern unsigned int kexec_reloc_size;
+extern const char kexec_reloc_end[];
#endif
diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c
index 08ec9fd43b1d..751a9efcaf6a 100644
--- a/xen/arch/x86/machine_kexec.c
+++ b/xen/arch/x86/machine_kexec.c
@@ -117,7 +117,7 @@ int machine_kexec_load(struct kexec_image *image)
}
code_page = __map_domain_page(image->control_code_page);
- memcpy(code_page, kexec_reloc, kexec_reloc_size);
+ memcpy(code_page, kexec_reloc, kexec_reloc_end - (char *)kexec_reloc);
unmap_domain_page(code_page);
/*
diff --git a/xen/arch/x86/x86_64/kexec_reloc.S
b/xen/arch/x86/x86_64/kexec_reloc.S
index d488d127cfb9..89316bc3a7ac 100644
--- a/xen/arch/x86/x86_64/kexec_reloc.S
+++ b/xen/arch/x86/x86_64/kexec_reloc.S
@@ -34,7 +34,7 @@ ENTRY(kexec_reloc)
movq %rcx, %rbp
/* Setup stack. */
- leaq (reloc_stack - kexec_reloc)(%rdi), %rsp
+ leaq (.Lreloc_stack_base - kexec_reloc)(%rdi), %rsp
/* Load reloc page table. */
movq %rsi, %cr3
@@ -175,10 +175,16 @@ compatibility_mode_far:
.long 0x00000000 /* set in call_32_bit above */
.word 0x0010
+ .type compatibility_mode_far, @object
+ .size compatibility_mode_far, . - compatibility_mode_far
+
compat_mode_gdt_desc:
.word .Lcompat_mode_gdt_end - compat_mode_gdt -1
.quad 0x0000000000000000 /* set in call_32_bit above */
+ .type compat_mode_gdt_desc, @object
+ .size compat_mode_gdt_desc, . - compat_mode_gdt_desc
+
.align 8
compat_mode_gdt:
.quad 0x0000000000000000 /* null */
@@ -186,16 +192,23 @@ compat_mode_gdt:
.quad 0x00cf9b000000ffff /* 0x0010 ring 0 code, compatibility */
.Lcompat_mode_gdt_end:
+ .type compat_mode_gdt, @object
+ .size compat_mode_gdt, . - compat_mode_gdt
+
compat_mode_idt:
.word 0 /* limit */
.long 0 /* base */
+ .type compat_mode_idt, @object
+ .size compat_mode_idt, . - compat_mode_idt
+
/*
* 16 words of stack are more than enough.
*/
- .fill 16,8,0
+ .align 8
reloc_stack:
+ .fill 16,8,0
+.Lreloc_stack_base:
- .globl kexec_reloc_size
-kexec_reloc_size:
- .long . - kexec_reloc
+ .type reloc_stack, @object
+ .size reloc_stack, . - reloc_stack
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 82ad8feb6e99..7ffecd463070 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -84,6 +84,7 @@ SECTIONS
_etextentry = .;
*(.text.kexec) /* Page aligned in the object file. */
+ kexec_reloc_end = .;
*(.text.cold)
*(.text.unlikely)
@@ -428,7 +429,7 @@ ASSERT(__2M_rwdata_end <= XEN_VIRT_END - XEN_VIRT_START +
__XEN_VIRT_START -
"Xen image overlaps stubs area")
#ifdef CONFIG_KEXEC
-ASSERT(kexec_reloc_size - kexec_reloc <= PAGE_SIZE, "kexec_reloc is too large")
+ASSERT(kexec_reloc_end - kexec_reloc <= PAGE_SIZE, "kexec_reloc is too large")
#endif
/* The Multiboot setup paths relies on this to simplify superpage PTE
creation. */
--
2.11.0