diff mbox series

[v3,05/70] x86/kexec: Annotate embedded data with ELF metadata

Message ID 20220222152645.8844-4-andrew.cooper3@citrix.com (mailing list archive)
State New, archived
Headers show
Series x86: Support for CET Indirect Branch Tracking | expand

Commit Message

Andrew Cooper Feb. 22, 2022, 3:26 p.m. UTC
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 <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Wei Liu <wl@xen.org>

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 mbox series

Patch

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. */