* [PATCH v9 1/4] x86/kexec: Add 8250 serial port output
2025-03-26 14:16 [PATCH v9 0/4] x86/kexec: Add exception handling for relocate_kernel David Woodhouse
@ 2025-03-26 14:16 ` David Woodhouse
2025-04-10 11:13 ` [tip: x86/asm] " tip-bot2 for David Woodhouse
2025-03-26 14:16 ` [PATCH v9 2/4] x86/kexec: Add 8250 MMIO " David Woodhouse
` (3 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: David Woodhouse @ 2025-03-26 14:16 UTC (permalink / raw)
To: kexec
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David Woodhouse, Kirill A . Shutemov, Kai Huang,
Nikolay Borisov, linux-kernel, Simon Horman, Dave Young,
Peter Zijlstra, jpoimboe, bsz
From: David Woodhouse <dwmw@amazon.co.uk>
If a serial port was configured for early_printk, use it for debug output
from the relocate_kernel exception handler too.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/include/asm/kexec.h | 1 +
arch/x86/kernel/early_printk.c | 6 +++++
arch/x86/kernel/relocate_kernel_64.S | 39 +++++++++++++++++++++++-----
3 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index fb4537c58b54..9601094ac0ba 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -64,6 +64,7 @@ extern unsigned long kexec_pa_table_page;
extern unsigned long kexec_pa_swap_page;
extern gate_desc kexec_debug_idt[];
extern unsigned char kexec_debug_exc_vectors[];
+extern uint16_t kexec_debug_8250_port;
#endif
/*
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index fc1714bad045..b756ebcbd827 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/console.h>
#include <linux/kernel.h>
+#include <linux/kexec.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/screen_info.h>
@@ -144,6 +145,11 @@ static __init void early_serial_hw_init(unsigned divisor)
static_call(serial_out)(early_serial_base, DLL, divisor & 0xff);
static_call(serial_out)(early_serial_base, DLH, (divisor >> 8) & 0xff);
static_call(serial_out)(early_serial_base, LCR, c & ~DLAB);
+
+#if defined(CONFIG_KEXEC_CORE) && defined(CONFIG_X86_64)
+ if (static_call_query(serial_in) == io_serial_in)
+ kexec_debug_8250_port = early_serial_base;
+#endif
}
#define DEFAULT_BAUD 9600
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 29cb399a34d4..21011cd19c48 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -39,6 +39,7 @@ SYM_DATA(kexec_va_control_page, .quad 0)
SYM_DATA(kexec_pa_table_page, .quad 0)
SYM_DATA(kexec_pa_swap_page, .quad 0)
SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0)
+SYM_DATA(kexec_debug_8250_port, .word 0)
.balign 16
SYM_DATA_START_LOCAL(kexec_debug_gdt)
@@ -380,24 +381,50 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
SYM_CODE_END(swap_pages)
/*
- * Generic 'print character' routine (as yet unimplemented)
+ * Generic 'print character' routine
* - %al: Character to be printed (may clobber %rax)
* - %rdx: MMIO address or port.
*/
-SYM_CODE_START_LOCAL_NOALIGN(pr_char)
+#define XMTRDY 0x20
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define LSR 5 /* Line Status */
+
+SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250)
UNWIND_HINT_FUNC
ANNOTATE_NOENDBR
+ addw $LSR, %dx
+ xchg %al, %ah
+.Lxmtrdy_loop:
+ inb %dx, %al
+ testb $XMTRDY, %al
+ jnz .Lready
+ rep nop
+ jmp .Lxmtrdy_loop
+
+.Lready:
+ subw $LSR, %dx
+ xchg %al, %ah
+ outb %al, %dx
+pr_char_null:
+ ANNOTATE_NOENDBR
+
ANNOTATE_UNRET_SAFE
ret
-SYM_CODE_END(pr_char)
+SYM_CODE_END(pr_char_8250)
/*
* Load pr_char function pointer into %rsi and load %rdx with whatever
* that function wants to see there (typically port/MMIO address).
*/
-.macro pr_setup
- /* No output; pr_char just returns */
- leaq pr_char(%rip), %rsi
+.macro pr_setup
+ leaq pr_char_8250(%rip), %rsi
+ movw kexec_debug_8250_port(%rip), %dx
+ testw %dx, %dx
+ jnz 1f
+
+ leaq pr_char_null(%rip), %rsi
+1:
.endm
/* Print the nybble in %bl, clobber %rax */
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [tip: x86/asm] x86/kexec: Add 8250 serial port output
2025-03-26 14:16 ` [PATCH v9 1/4] x86/kexec: Add 8250 serial port output David Woodhouse
@ 2025-04-10 11:13 ` tip-bot2 for David Woodhouse
0 siblings, 0 replies; 12+ messages in thread
From: tip-bot2 for David Woodhouse @ 2025-04-10 11:13 UTC (permalink / raw)
To: linux-tip-commits
Cc: David Woodhouse, Ingo Molnar, Andy Shevchenko, Brian Gerst,
Juergen Gross, H. Peter Anvin, Linus Torvalds, Josh Poimboeuf,
Kees Cook, Ard Biesheuvel, x86, linux-kernel
The following commit has been merged into the x86/asm branch of tip:
Commit-ID: d358b45120cc8da9f10d8c1e8ec3559f72525147
Gitweb: https://git.kernel.org/tip/d358b45120cc8da9f10d8c1e8ec3559f72525147
Author: David Woodhouse <dwmw@amazon.co.uk>
AuthorDate: Wed, 26 Mar 2025 14:16:01
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Thu, 10 Apr 2025 12:17:13 +02:00
x86/kexec: Add 8250 serial port output
If a serial port was configured for early_printk, use it for debug output
from the relocate_kernel exception handler too.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250326142404.256980-2-dwmw2@infradead.org
---
arch/x86/include/asm/kexec.h | 1 +-
arch/x86/kernel/early_printk.c | 6 ++++-
arch/x86/kernel/relocate_kernel_64.S | 39 ++++++++++++++++++++++-----
3 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index fb4537c..9601094 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -64,6 +64,7 @@ extern unsigned long kexec_pa_table_page;
extern unsigned long kexec_pa_swap_page;
extern gate_desc kexec_debug_idt[];
extern unsigned char kexec_debug_exc_vectors[];
+extern uint16_t kexec_debug_8250_port;
#endif
/*
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 611f27e..acb7d05 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/console.h>
#include <linux/kernel.h>
+#include <linux/kexec.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/screen_info.h>
@@ -144,6 +145,11 @@ static __init void early_serial_hw_init(unsigned divisor)
static_call(serial_out)(early_serial_base, DLL, divisor & 0xff);
static_call(serial_out)(early_serial_base, DLH, (divisor >> 8) & 0xff);
static_call(serial_out)(early_serial_base, LCR, c & ~DLAB);
+
+#if defined(CONFIG_KEXEC_CORE) && defined(CONFIG_X86_64)
+ if (static_call_query(serial_in) == io_serial_in)
+ kexec_debug_8250_port = early_serial_base;
+#endif
}
#define DEFAULT_BAUD 9600
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 29cb399..21011cd 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -39,6 +39,7 @@ SYM_DATA(kexec_va_control_page, .quad 0)
SYM_DATA(kexec_pa_table_page, .quad 0)
SYM_DATA(kexec_pa_swap_page, .quad 0)
SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0)
+SYM_DATA(kexec_debug_8250_port, .word 0)
.balign 16
SYM_DATA_START_LOCAL(kexec_debug_gdt)
@@ -380,24 +381,50 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
SYM_CODE_END(swap_pages)
/*
- * Generic 'print character' routine (as yet unimplemented)
+ * Generic 'print character' routine
* - %al: Character to be printed (may clobber %rax)
* - %rdx: MMIO address or port.
*/
-SYM_CODE_START_LOCAL_NOALIGN(pr_char)
+#define XMTRDY 0x20
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define LSR 5 /* Line Status */
+
+SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250)
UNWIND_HINT_FUNC
ANNOTATE_NOENDBR
+ addw $LSR, %dx
+ xchg %al, %ah
+.Lxmtrdy_loop:
+ inb %dx, %al
+ testb $XMTRDY, %al
+ jnz .Lready
+ rep nop
+ jmp .Lxmtrdy_loop
+
+.Lready:
+ subw $LSR, %dx
+ xchg %al, %ah
+ outb %al, %dx
+pr_char_null:
+ ANNOTATE_NOENDBR
+
ANNOTATE_UNRET_SAFE
ret
-SYM_CODE_END(pr_char)
+SYM_CODE_END(pr_char_8250)
/*
* Load pr_char function pointer into %rsi and load %rdx with whatever
* that function wants to see there (typically port/MMIO address).
*/
-.macro pr_setup
- /* No output; pr_char just returns */
- leaq pr_char(%rip), %rsi
+.macro pr_setup
+ leaq pr_char_8250(%rip), %rsi
+ movw kexec_debug_8250_port(%rip), %dx
+ testw %dx, %dx
+ jnz 1f
+
+ leaq pr_char_null(%rip), %rsi
+1:
.endm
/* Print the nybble in %bl, clobber %rax */
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v9 2/4] x86/kexec: Add 8250 MMIO serial port output
2025-03-26 14:16 [PATCH v9 0/4] x86/kexec: Add exception handling for relocate_kernel David Woodhouse
2025-03-26 14:16 ` [PATCH v9 1/4] x86/kexec: Add 8250 serial port output David Woodhouse
@ 2025-03-26 14:16 ` David Woodhouse
2025-04-10 11:13 ` [tip: x86/asm] " tip-bot2 for David Woodhouse
2025-03-26 14:16 ` [PATCH v9 3/4] x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier David Woodhouse
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: David Woodhouse @ 2025-03-26 14:16 UTC (permalink / raw)
To: kexec
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David Woodhouse, Kirill A . Shutemov, Kai Huang,
Nikolay Borisov, linux-kernel, Simon Horman, Dave Young,
Peter Zijlstra, jpoimboe, bsz
From: David Woodhouse <dwmw@amazon.co.uk>
This supports the same 32-bit MMIO-mapped 8250 as the early_printk code.
It's not clear why the early_printk code supports this form and only this
form; the actual runtime 8250_pci doesn't seem to support it. But having
hacked up QEMU to expose such a device, early_printk does work with it,
and now so does the kexec debug code.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/include/asm/kexec.h | 1 +
arch/x86/kernel/early_printk.c | 3 +++
arch/x86/kernel/machine_kexec_64.c | 17 +++++++++++++++++
arch/x86/kernel/relocate_kernel_64.S | 22 ++++++++++++++++++++++
4 files changed, 43 insertions(+)
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index 9601094ac0ba..f2ad77929d6e 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -65,6 +65,7 @@ extern unsigned long kexec_pa_swap_page;
extern gate_desc kexec_debug_idt[];
extern unsigned char kexec_debug_exc_vectors[];
extern uint16_t kexec_debug_8250_port;
+extern unsigned long kexec_debug_8250_mmio32;
#endif
/*
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index b756ebcbd827..3ad085de1353 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -295,6 +295,9 @@ static __init void early_pci_serial_init(char *s)
/* WARNING! assuming the address is always in the first 4G */
early_serial_base =
(unsigned long)early_ioremap(bar0 & PCI_BASE_ADDRESS_MEM_MASK, 0x10);
+#if defined(CONFIG_KEXEC_CORE) && defined(CONFIG_X86_64)
+ kexec_debug_8250_mmio32 = bar0 & PCI_BASE_ADDRESS_MEM_MASK;
+#endif
write_pci_config(bus, slot, func, PCI_COMMAND,
cmdreg|PCI_COMMAND_MEMORY);
}
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index cc73f9708464..ecb0da54abd1 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -76,6 +76,19 @@ map_acpi_tables(struct x86_mapping_info *info, pgd_t *level4p)
static int map_acpi_tables(struct x86_mapping_info *info, pgd_t *level4p) { return 0; }
#endif
+static int map_mmio_serial(struct x86_mapping_info *info, pgd_t *level4p)
+{
+ unsigned long mstart, mend;
+
+ if (!kexec_debug_8250_mmio32)
+ return 0;
+
+ mstart = kexec_debug_8250_mmio32 & PAGE_MASK;
+ mend = (kexec_debug_8250_mmio32 + PAGE_SIZE + 23) & PAGE_MASK;
+ pr_info("Map PCI serial at %lx - %lx\n", mstart, mend);
+ return kernel_ident_mapping_init(info, level4p, mstart, mend);
+}
+
#ifdef CONFIG_KEXEC_FILE
const struct kexec_file_ops * const kexec_file_loaders[] = {
&kexec_bzImage64_ops,
@@ -285,6 +298,10 @@ static int init_pgtable(struct kimage *image, unsigned long control_page)
if (result)
return result;
+ result = map_mmio_serial(&info, image->arch.pgd);
+ if (result)
+ return result;
+
/*
* This must be last because the intermediate page table pages it
* allocates will not be control pages and may overlap the image.
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 21011cd19c48..8808cfca6322 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -39,6 +39,7 @@ SYM_DATA(kexec_va_control_page, .quad 0)
SYM_DATA(kexec_pa_table_page, .quad 0)
SYM_DATA(kexec_pa_swap_page, .quad 0)
SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0)
+SYM_DATA(kexec_debug_8250_mmio32, .quad 0)
SYM_DATA(kexec_debug_8250_port, .word 0)
.balign 16
@@ -413,6 +414,22 @@ pr_char_null:
ret
SYM_CODE_END(pr_char_8250)
+SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250_mmio32)
+ UNWIND_HINT_FUNC
+ ANNOTATE_NOENDBR
+.Lxmtrdy_loop_mmio:
+ movb (LSR*4)(%rdx), %ah
+ testb $XMTRDY, %ah
+ jnz .Lready_mmio
+ rep nop
+ jmp .Lxmtrdy_loop_mmio
+
+.Lready_mmio:
+ movb %al, (%rdx)
+ ANNOTATE_UNRET_SAFE
+ ret
+SYM_CODE_END(pr_char_8250_mmio32)
+
/*
* Load pr_char function pointer into %rsi and load %rdx with whatever
* that function wants to see there (typically port/MMIO address).
@@ -423,6 +440,11 @@ SYM_CODE_END(pr_char_8250)
testw %dx, %dx
jnz 1f
+ leaq pr_char_8250_mmio32(%rip), %rsi
+ movq kexec_debug_8250_mmio32(%rip), %rdx
+ testq %rdx, %rdx
+ jnz 1f
+
leaq pr_char_null(%rip), %rsi
1:
.endm
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [tip: x86/asm] x86/kexec: Add 8250 MMIO serial port output
2025-03-26 14:16 ` [PATCH v9 2/4] x86/kexec: Add 8250 MMIO " David Woodhouse
@ 2025-04-10 11:13 ` tip-bot2 for David Woodhouse
0 siblings, 0 replies; 12+ messages in thread
From: tip-bot2 for David Woodhouse @ 2025-04-10 11:13 UTC (permalink / raw)
To: linux-tip-commits
Cc: David Woodhouse, Ingo Molnar, Andy Shevchenko, Brian Gerst,
Juergen Gross, H. Peter Anvin, Linus Torvalds, Josh Poimboeuf,
Kees Cook, Ard Biesheuvel, x86, linux-kernel
The following commit has been merged into the x86/asm branch of tip:
Commit-ID: 7516e7216bdfb9e2fab0a0ca3bd23cb2e61e46ed
Gitweb: https://git.kernel.org/tip/7516e7216bdfb9e2fab0a0ca3bd23cb2e61e46ed
Author: David Woodhouse <dwmw@amazon.co.uk>
AuthorDate: Wed, 26 Mar 2025 14:16:02
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Thu, 10 Apr 2025 12:17:14 +02:00
x86/kexec: Add 8250 MMIO serial port output
This supports the same 32-bit MMIO-mapped 8250 as the early_printk code.
It's not clear why the early_printk code supports this form and only this
form; the actual runtime 8250_pci doesn't seem to support it. But having
hacked up QEMU to expose such a device, early_printk does work with it,
and now so does the kexec debug code.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250326142404.256980-3-dwmw2@infradead.org
---
arch/x86/include/asm/kexec.h | 1 +
arch/x86/kernel/early_printk.c | 3 +++
arch/x86/kernel/machine_kexec_64.c | 17 +++++++++++++++++
arch/x86/kernel/relocate_kernel_64.S | 22 ++++++++++++++++++++++
4 files changed, 43 insertions(+)
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index 9601094..f2ad779 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -65,6 +65,7 @@ extern unsigned long kexec_pa_swap_page;
extern gate_desc kexec_debug_idt[];
extern unsigned char kexec_debug_exc_vectors[];
extern uint16_t kexec_debug_8250_port;
+extern unsigned long kexec_debug_8250_mmio32;
#endif
/*
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index acb7d05..9e8707d 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -333,6 +333,9 @@ static __init void early_pci_serial_init(char *s)
/* WARNING! assuming the address is always in the first 4G */
early_serial_base =
(unsigned long)early_ioremap(bar0 & PCI_BASE_ADDRESS_MEM_MASK, 0x10);
+#if defined(CONFIG_KEXEC_CORE) && defined(CONFIG_X86_64)
+ kexec_debug_8250_mmio32 = bar0 & PCI_BASE_ADDRESS_MEM_MASK;
+#endif
write_pci_config(bus, slot, func, PCI_COMMAND,
cmdreg|PCI_COMMAND_MEMORY);
}
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index cc73f97..ecb0da5 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -76,6 +76,19 @@ map_acpi_tables(struct x86_mapping_info *info, pgd_t *level4p)
static int map_acpi_tables(struct x86_mapping_info *info, pgd_t *level4p) { return 0; }
#endif
+static int map_mmio_serial(struct x86_mapping_info *info, pgd_t *level4p)
+{
+ unsigned long mstart, mend;
+
+ if (!kexec_debug_8250_mmio32)
+ return 0;
+
+ mstart = kexec_debug_8250_mmio32 & PAGE_MASK;
+ mend = (kexec_debug_8250_mmio32 + PAGE_SIZE + 23) & PAGE_MASK;
+ pr_info("Map PCI serial at %lx - %lx\n", mstart, mend);
+ return kernel_ident_mapping_init(info, level4p, mstart, mend);
+}
+
#ifdef CONFIG_KEXEC_FILE
const struct kexec_file_ops * const kexec_file_loaders[] = {
&kexec_bzImage64_ops,
@@ -285,6 +298,10 @@ static int init_pgtable(struct kimage *image, unsigned long control_page)
if (result)
return result;
+ result = map_mmio_serial(&info, image->arch.pgd);
+ if (result)
+ return result;
+
/*
* This must be last because the intermediate page table pages it
* allocates will not be control pages and may overlap the image.
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 21011cd..8808cfc 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -39,6 +39,7 @@ SYM_DATA(kexec_va_control_page, .quad 0)
SYM_DATA(kexec_pa_table_page, .quad 0)
SYM_DATA(kexec_pa_swap_page, .quad 0)
SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0)
+SYM_DATA(kexec_debug_8250_mmio32, .quad 0)
SYM_DATA(kexec_debug_8250_port, .word 0)
.balign 16
@@ -413,6 +414,22 @@ pr_char_null:
ret
SYM_CODE_END(pr_char_8250)
+SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250_mmio32)
+ UNWIND_HINT_FUNC
+ ANNOTATE_NOENDBR
+.Lxmtrdy_loop_mmio:
+ movb (LSR*4)(%rdx), %ah
+ testb $XMTRDY, %ah
+ jnz .Lready_mmio
+ rep nop
+ jmp .Lxmtrdy_loop_mmio
+
+.Lready_mmio:
+ movb %al, (%rdx)
+ ANNOTATE_UNRET_SAFE
+ ret
+SYM_CODE_END(pr_char_8250_mmio32)
+
/*
* Load pr_char function pointer into %rsi and load %rdx with whatever
* that function wants to see there (typically port/MMIO address).
@@ -423,6 +440,11 @@ SYM_CODE_END(pr_char_8250)
testw %dx, %dx
jnz 1f
+ leaq pr_char_8250_mmio32(%rip), %rsi
+ movq kexec_debug_8250_mmio32(%rip), %rdx
+ testq %rdx, %rdx
+ jnz 1f
+
leaq pr_char_null(%rip), %rsi
1:
.endm
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v9 3/4] x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier
2025-03-26 14:16 [PATCH v9 0/4] x86/kexec: Add exception handling for relocate_kernel David Woodhouse
2025-03-26 14:16 ` [PATCH v9 1/4] x86/kexec: Add 8250 serial port output David Woodhouse
2025-03-26 14:16 ` [PATCH v9 2/4] x86/kexec: Add 8250 MMIO " David Woodhouse
@ 2025-03-26 14:16 ` David Woodhouse
2025-04-01 9:48 ` Huang, Kai
2025-04-10 11:12 ` [tip: x86/asm] " tip-bot2 for David Woodhouse
2025-03-26 14:16 ` [PATCH v9 4/4] selftests/kexec: Add x86_64 selftest for kexec-jump and exception handling David Woodhouse
2025-04-10 7:26 ` [PATCH v9 0/4] x86/kexec: Add exception handling for relocate_kernel David Woodhouse
4 siblings, 2 replies; 12+ messages in thread
From: David Woodhouse @ 2025-03-26 14:16 UTC (permalink / raw)
To: kexec
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David Woodhouse, Kirill A . Shutemov, Kai Huang,
Nikolay Borisov, linux-kernel, Simon Horman, Dave Young,
Peter Zijlstra, jpoimboe, bsz
From: David Woodhouse <dwmw@amazon.co.uk>
Reduce the window during which exceptions are unhandled, by leaving the
GDT/IDT in place all the way into the relocate_kernel() function, until
the moment that %cr3 gets replaced.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/kernel/machine_kexec_64.c | 10 ++--------
arch/x86/kernel/relocate_kernel_64.S | 9 +++++++--
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index ecb0da54abd1..949c9e4bfad2 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -434,16 +434,10 @@ void __nocfi machine_kexec(struct kimage *image)
* with from a table in memory. At no other time is the
* descriptor table in memory accessed.
*
- * I take advantage of this here by force loading the
- * segments, before I zap the gdt with an invalid value.
+ * Take advantage of this here by force loading the segments,
+ * before the GDT is zapped with an invalid value.
*/
load_segments();
- /*
- * The gdt & idt are now invalid.
- * If you want to load them you must set up your own idt & gdt.
- */
- native_idt_invalidate();
- native_gdt_invalidate();
/* now call it */
image->start = relocate_kernel_ptr((unsigned long)image->head,
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 8808cfca6322..3062cb3efc44 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -79,8 +79,13 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
pushq %r15
pushf
- /* zero out flags, and disable interrupts */
- pushq $0
+ /* Invalidate GDT/IDT, zero out flags */
+ pushq $0
+ pushq $0
+
+ lidt (%rsp)
+ lgdt (%rsp)
+ addq $8, %rsp
popfq
/* Switch to the identity mapped page tables */
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v9 3/4] x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier
2025-03-26 14:16 ` [PATCH v9 3/4] x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier David Woodhouse
@ 2025-04-01 9:48 ` Huang, Kai
2025-04-01 9:53 ` David Woodhouse
2025-04-10 11:12 ` [tip: x86/asm] " tip-bot2 for David Woodhouse
1 sibling, 1 reply; 12+ messages in thread
From: Huang, Kai @ 2025-04-01 9:48 UTC (permalink / raw)
To: kexec@lists.infradead.org, dwmw2@infradead.org
Cc: dyoung@redhat.com, bsz@amazon.de, x86@kernel.org, bp@alien8.de,
peterz@infradead.org, hpa@zytor.com, mingo@redhat.com,
tglx@linutronix.de, kirill.shutemov@linux.intel.com,
linux-kernel@vger.kernel.org, horms@kernel.org, dwmw@amazon.co.uk,
dave.hansen@linux.intel.com, jpoimboe@kernel.org,
nik.borisov@suse.com
On Wed, 2025-03-26 at 14:16 +0000, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
>
> Reduce the window during which exceptions are unhandled, by leaving the
> GDT/IDT in place all the way into the relocate_kernel() function, until
> the moment that %cr3 gets replaced.
Seems the difference is only couple of instructions. Anyway ...
>
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Kai Huang <kai.huang@intel.com>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v9 3/4] x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier
2025-04-01 9:48 ` Huang, Kai
@ 2025-04-01 9:53 ` David Woodhouse
0 siblings, 0 replies; 12+ messages in thread
From: David Woodhouse @ 2025-04-01 9:53 UTC (permalink / raw)
To: Huang, Kai, kexec@lists.infradead.org
Cc: dyoung@redhat.com, bsz@amazon.de, x86@kernel.org, bp@alien8.de,
peterz@infradead.org, hpa@zytor.com, mingo@redhat.com,
tglx@linutronix.de, kirill.shutemov@linux.intel.com,
linux-kernel@vger.kernel.org, horms@kernel.org,
dave.hansen@linux.intel.com, jpoimboe@kernel.org,
nik.borisov@suse.com
[-- Attachment #1: Type: text/plain, Size: 967 bytes --]
On Tue, 2025-04-01 at 09:48 +0000, Huang, Kai wrote:
> On Wed, 2025-03-26 at 14:16 +0000, David Woodhouse wrote:
> > From: David Woodhouse <dwmw@amazon.co.uk>
> >
> > Reduce the window during which exceptions are unhandled, by leaving
> > the
> > GDT/IDT in place all the way into the relocate_kernel() function,
> > until
> > the moment that %cr3 gets replaced.
>
> Seems the difference is only couple of instructions. Anyway ...
It is, although that was important when I was trying to enable CET
because one of those instructions was the indirect call.
I've given up on CET now because it's largely pointless for that
particular call. But still, putting the GDT/IDT invalidation into
relocate_kernel.S means that we can further shrink the window if we
want to look at leaving MC enabled during the handover, etc.
> >
> > Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
>
> Reviewed-by: Kai Huang <kai.huang@intel.com>
Thanks.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* [tip: x86/asm] x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier
2025-03-26 14:16 ` [PATCH v9 3/4] x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier David Woodhouse
2025-04-01 9:48 ` Huang, Kai
@ 2025-04-10 11:12 ` tip-bot2 for David Woodhouse
1 sibling, 0 replies; 12+ messages in thread
From: tip-bot2 for David Woodhouse @ 2025-04-10 11:12 UTC (permalink / raw)
To: linux-tip-commits
Cc: David Woodhouse, Ingo Molnar, Brian Gerst, Juergen Gross,
H. Peter Anvin, Linus Torvalds, Josh Poimboeuf, Kees Cook,
Ard Biesheuvel, x86, linux-kernel
The following commit has been merged into the x86/asm branch of tip:
Commit-ID: de085ddd493bccb77a3ec1b99ae7466133540f4d
Gitweb: https://git.kernel.org/tip/de085ddd493bccb77a3ec1b99ae7466133540f4d
Author: David Woodhouse <dwmw@amazon.co.uk>
AuthorDate: Wed, 26 Mar 2025 14:16:03
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Thu, 10 Apr 2025 12:17:14 +02:00
x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier
Reduce the window during which exceptions are unhandled, by leaving the
GDT/IDT in place all the way into the relocate_kernel() function, until
the moment that %cr3 gets replaced.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250326142404.256980-4-dwmw2@infradead.org
---
arch/x86/kernel/machine_kexec_64.c | 10 ++--------
arch/x86/kernel/relocate_kernel_64.S | 9 +++++++--
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index ecb0da5..949c9e4 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -434,16 +434,10 @@ void __nocfi machine_kexec(struct kimage *image)
* with from a table in memory. At no other time is the
* descriptor table in memory accessed.
*
- * I take advantage of this here by force loading the
- * segments, before I zap the gdt with an invalid value.
+ * Take advantage of this here by force loading the segments,
+ * before the GDT is zapped with an invalid value.
*/
load_segments();
- /*
- * The gdt & idt are now invalid.
- * If you want to load them you must set up your own idt & gdt.
- */
- native_idt_invalidate();
- native_gdt_invalidate();
/* now call it */
image->start = relocate_kernel_ptr((unsigned long)image->head,
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 8808cfc..3062cb3 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -79,8 +79,13 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
pushq %r15
pushf
- /* zero out flags, and disable interrupts */
- pushq $0
+ /* Invalidate GDT/IDT, zero out flags */
+ pushq $0
+ pushq $0
+
+ lidt (%rsp)
+ lgdt (%rsp)
+ addq $8, %rsp
popfq
/* Switch to the identity mapped page tables */
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v9 4/4] selftests/kexec: Add x86_64 selftest for kexec-jump and exception handling
2025-03-26 14:16 [PATCH v9 0/4] x86/kexec: Add exception handling for relocate_kernel David Woodhouse
` (2 preceding siblings ...)
2025-03-26 14:16 ` [PATCH v9 3/4] x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier David Woodhouse
@ 2025-03-26 14:16 ` David Woodhouse
2025-04-10 11:12 ` [tip: x86/asm] " tip-bot2 for David Woodhouse
2025-04-10 7:26 ` [PATCH v9 0/4] x86/kexec: Add exception handling for relocate_kernel David Woodhouse
4 siblings, 1 reply; 12+ messages in thread
From: David Woodhouse @ 2025-03-26 14:16 UTC (permalink / raw)
To: kexec
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David Woodhouse, Kirill A . Shutemov, Kai Huang,
Nikolay Borisov, linux-kernel, Simon Horman, Dave Young,
Peter Zijlstra, jpoimboe, bsz
From: David Woodhouse <dwmw@amazon.co.uk>
Add a self test which exercises both the kexec-jump facility, and the
kexec exception handling.
Invoke a trivial payload which just does an int3 and returns,
flip-flopping its entry point for the next invocation between two
implementations of the same thing.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
tools/testing/selftests/kexec/Makefile | 7 ++
.../testing/selftests/kexec/test_kexec_jump.c | 72 +++++++++++++++++++
.../selftests/kexec/test_kexec_jump.sh | 42 +++++++++++
3 files changed, 121 insertions(+)
create mode 100644 tools/testing/selftests/kexec/test_kexec_jump.c
create mode 100755 tools/testing/selftests/kexec/test_kexec_jump.sh
diff --git a/tools/testing/selftests/kexec/Makefile b/tools/testing/selftests/kexec/Makefile
index 67fe7a46cb62..e3000ccb9a5d 100644
--- a/tools/testing/selftests/kexec/Makefile
+++ b/tools/testing/selftests/kexec/Makefile
@@ -8,6 +8,13 @@ ifeq ($(ARCH_PROCESSED),$(filter $(ARCH_PROCESSED),x86 ppc64le))
TEST_PROGS := test_kexec_load.sh test_kexec_file_load.sh
TEST_FILES := kexec_common_lib.sh
+include ../../../scripts/Makefile.arch
+
+ifeq ($(IS_64_BIT)$(ARCH_PROCESSED),1x86)
+TEST_PROGS += test_kexec_jump.sh
+test_kexec_jump.sh: $(OUTPUT)/test_kexec_jump
+endif
+
include ../lib.mk
endif
diff --git a/tools/testing/selftests/kexec/test_kexec_jump.c b/tools/testing/selftests/kexec/test_kexec_jump.c
new file mode 100644
index 000000000000..fbce287866f5
--- /dev/null
+++ b/tools/testing/selftests/kexec/test_kexec_jump.c
@@ -0,0 +1,72 @@
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/kexec.h>
+#include <linux/reboot.h>
+#include <sys/reboot.h>
+#include <sys/syscall.h>
+
+asm(
+ " .code64\n"
+ " .data\n"
+ "purgatory_start:\n"
+
+ // Trigger kexec debug exception handling
+ " int3\n"
+
+ // Set load address for next time
+ " leaq purgatory_start_b(%rip), %r11\n"
+ " movq %r11, 8(%rsp)\n"
+
+ // Back to Linux
+ " ret\n"
+
+ // Same again
+ "purgatory_start_b:\n"
+
+ // Trigger kexec debug exception handling
+ " int3\n"
+
+ // Set load address for next time
+ " leaq purgatory_start(%rip), %r11\n"
+ " movq %r11, 8(%rsp)\n"
+
+ // Back to Linux
+ " ret\n"
+
+ "purgatory_end:\n"
+ ".previous"
+);
+extern char purgatory_start[], purgatory_end[];
+
+int main (void)
+{
+ struct kexec_segment segment = {};
+ int ret;
+
+ segment.buf = purgatory_start;
+ segment.bufsz = purgatory_end - purgatory_start;
+ segment.mem = (void *)0x400000;
+ segment.memsz = 0x1000;
+ ret = syscall(__NR_kexec_load, 0x400000, 1, &segment, KEXEC_PRESERVE_CONTEXT);
+ if (ret) {
+ perror("kexec_load");
+ exit(1);
+ }
+
+ ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC);
+ if (ret) {
+ perror("kexec reboot");
+ exit(1);
+ }
+
+ ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC);
+ if (ret) {
+ perror("kexec reboot");
+ exit(1);
+ }
+ printf("Success\n");
+ return 0;
+}
+
diff --git a/tools/testing/selftests/kexec/test_kexec_jump.sh b/tools/testing/selftests/kexec/test_kexec_jump.sh
new file mode 100755
index 000000000000..6ae977054ba2
--- /dev/null
+++ b/tools/testing/selftests/kexec/test_kexec_jump.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Prevent loading a kernel image via the kexec_load syscall when
+# signatures are required. (Dependent on CONFIG_IMA_ARCH_POLICY.)
+
+TEST="$0"
+. ./kexec_common_lib.sh
+
+# kexec requires root privileges
+require_root_privileges
+
+# get the kernel config
+get_kconfig
+
+kconfig_enabled "CONFIG_KEXEC_JUMP=y" "kexec_jump is enabled"
+if [ $? -eq 0 ]; then
+ log_skip "kexec_jump is not enabled"
+fi
+
+kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled"
+ima_appraise=$?
+
+kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \
+ "IMA architecture specific policy enabled"
+arch_policy=$?
+
+get_secureboot_mode
+secureboot=$?
+
+if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ]; then
+ log_skip "Secure boot and CONFIG_IMA_ARCH_POLICY are enabled"
+fi
+
+./test_kexec_jump
+if [ $? -eq 0 ]; then
+ log_pass "kexec_jump succeeded"
+else
+ # The more likely failure mode if anything went wrong is that the
+ # kernel just crashes. But if we get back here, sure, whine anyway.
+ log_fail "kexec_jump failed"
+fi
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [tip: x86/asm] selftests/kexec: Add x86_64 selftest for kexec-jump and exception handling
2025-03-26 14:16 ` [PATCH v9 4/4] selftests/kexec: Add x86_64 selftest for kexec-jump and exception handling David Woodhouse
@ 2025-04-10 11:12 ` tip-bot2 for David Woodhouse
0 siblings, 0 replies; 12+ messages in thread
From: tip-bot2 for David Woodhouse @ 2025-04-10 11:12 UTC (permalink / raw)
To: linux-tip-commits
Cc: David Woodhouse, Ingo Molnar, Brian Gerst, Juergen Gross,
H. Peter Anvin, Linus Torvalds, Josh Poimboeuf, Kees Cook,
Ard Biesheuvel, x86, linux-kernel
The following commit has been merged into the x86/asm branch of tip:
Commit-ID: 7615b94b6371dab5d7d8c1ca4f95ed3f866e1c51
Gitweb: https://git.kernel.org/tip/7615b94b6371dab5d7d8c1ca4f95ed3f866e1c51
Author: David Woodhouse <dwmw@amazon.co.uk>
AuthorDate: Wed, 26 Mar 2025 14:16:04
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Thu, 10 Apr 2025 12:17:14 +02:00
selftests/kexec: Add x86_64 selftest for kexec-jump and exception handling
Add a self test which exercises both the kexec-jump facility, and the
kexec exception handling.
Invoke a trivial payload which just does an int3 and returns,
flip-flopping its entry point for the next invocation between two
implementations of the same thing.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250326142404.256980-5-dwmw2@infradead.org
---
tools/testing/selftests/kexec/Makefile | 7 +-
tools/testing/selftests/kexec/test_kexec_jump.c | 72 +++++++++++++++-
tools/testing/selftests/kexec/test_kexec_jump.sh | 42 +++++++++-
3 files changed, 121 insertions(+)
create mode 100644 tools/testing/selftests/kexec/test_kexec_jump.c
create mode 100755 tools/testing/selftests/kexec/test_kexec_jump.sh
diff --git a/tools/testing/selftests/kexec/Makefile b/tools/testing/selftests/kexec/Makefile
index 67fe7a4..e3000cc 100644
--- a/tools/testing/selftests/kexec/Makefile
+++ b/tools/testing/selftests/kexec/Makefile
@@ -8,6 +8,13 @@ ifeq ($(ARCH_PROCESSED),$(filter $(ARCH_PROCESSED),x86 ppc64le))
TEST_PROGS := test_kexec_load.sh test_kexec_file_load.sh
TEST_FILES := kexec_common_lib.sh
+include ../../../scripts/Makefile.arch
+
+ifeq ($(IS_64_BIT)$(ARCH_PROCESSED),1x86)
+TEST_PROGS += test_kexec_jump.sh
+test_kexec_jump.sh: $(OUTPUT)/test_kexec_jump
+endif
+
include ../lib.mk
endif
diff --git a/tools/testing/selftests/kexec/test_kexec_jump.c b/tools/testing/selftests/kexec/test_kexec_jump.c
new file mode 100644
index 0000000..fbce287
--- /dev/null
+++ b/tools/testing/selftests/kexec/test_kexec_jump.c
@@ -0,0 +1,72 @@
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/kexec.h>
+#include <linux/reboot.h>
+#include <sys/reboot.h>
+#include <sys/syscall.h>
+
+asm(
+ " .code64\n"
+ " .data\n"
+ "purgatory_start:\n"
+
+ // Trigger kexec debug exception handling
+ " int3\n"
+
+ // Set load address for next time
+ " leaq purgatory_start_b(%rip), %r11\n"
+ " movq %r11, 8(%rsp)\n"
+
+ // Back to Linux
+ " ret\n"
+
+ // Same again
+ "purgatory_start_b:\n"
+
+ // Trigger kexec debug exception handling
+ " int3\n"
+
+ // Set load address for next time
+ " leaq purgatory_start(%rip), %r11\n"
+ " movq %r11, 8(%rsp)\n"
+
+ // Back to Linux
+ " ret\n"
+
+ "purgatory_end:\n"
+ ".previous"
+);
+extern char purgatory_start[], purgatory_end[];
+
+int main (void)
+{
+ struct kexec_segment segment = {};
+ int ret;
+
+ segment.buf = purgatory_start;
+ segment.bufsz = purgatory_end - purgatory_start;
+ segment.mem = (void *)0x400000;
+ segment.memsz = 0x1000;
+ ret = syscall(__NR_kexec_load, 0x400000, 1, &segment, KEXEC_PRESERVE_CONTEXT);
+ if (ret) {
+ perror("kexec_load");
+ exit(1);
+ }
+
+ ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC);
+ if (ret) {
+ perror("kexec reboot");
+ exit(1);
+ }
+
+ ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC);
+ if (ret) {
+ perror("kexec reboot");
+ exit(1);
+ }
+ printf("Success\n");
+ return 0;
+}
+
diff --git a/tools/testing/selftests/kexec/test_kexec_jump.sh b/tools/testing/selftests/kexec/test_kexec_jump.sh
new file mode 100755
index 0000000..6ae9770
--- /dev/null
+++ b/tools/testing/selftests/kexec/test_kexec_jump.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Prevent loading a kernel image via the kexec_load syscall when
+# signatures are required. (Dependent on CONFIG_IMA_ARCH_POLICY.)
+
+TEST="$0"
+. ./kexec_common_lib.sh
+
+# kexec requires root privileges
+require_root_privileges
+
+# get the kernel config
+get_kconfig
+
+kconfig_enabled "CONFIG_KEXEC_JUMP=y" "kexec_jump is enabled"
+if [ $? -eq 0 ]; then
+ log_skip "kexec_jump is not enabled"
+fi
+
+kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled"
+ima_appraise=$?
+
+kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \
+ "IMA architecture specific policy enabled"
+arch_policy=$?
+
+get_secureboot_mode
+secureboot=$?
+
+if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ]; then
+ log_skip "Secure boot and CONFIG_IMA_ARCH_POLICY are enabled"
+fi
+
+./test_kexec_jump
+if [ $? -eq 0 ]; then
+ log_pass "kexec_jump succeeded"
+else
+ # The more likely failure mode if anything went wrong is that the
+ # kernel just crashes. But if we get back here, sure, whine anyway.
+ log_fail "kexec_jump failed"
+fi
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v9 0/4] x86/kexec: Add exception handling for relocate_kernel
2025-03-26 14:16 [PATCH v9 0/4] x86/kexec: Add exception handling for relocate_kernel David Woodhouse
` (3 preceding siblings ...)
2025-03-26 14:16 ` [PATCH v9 4/4] selftests/kexec: Add x86_64 selftest for kexec-jump and exception handling David Woodhouse
@ 2025-04-10 7:26 ` David Woodhouse
4 siblings, 0 replies; 12+ messages in thread
From: David Woodhouse @ 2025-04-10 7:26 UTC (permalink / raw)
To: kexec
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David Woodhouse, Kirill A . Shutemov, Kai Huang,
Nikolay Borisov, linux-kernel, Simon Horman, Dave Young,
Peter Zijlstra, jpoimboe, bsz
On 26 March 2025 15:16:00 CET, David Woodhouse <dwmw2@infradead.org> wrote:
>Continuing the drip-feed of the exception handling support, on top of the
>current tip/x86/asm branch. This adds output to the serial port configured
>by earlyprintk, reduces the window during which exceptions can't be handled
>during the transition from kernel to relocate_kernel environment, and adds
>a kselftest for the kexec-jump and exception handling.
>
>v9:
> • Rebase on top of partial merge into tip/x86/asm (commit 0717b1392dc7).
> • Add kselftest.
> • Update to cope with static_call() usage in earlyprintk.
> • Drop the attempt at adding CFI support for relocate_kernel().
>
>v8: https://lore.kernel.org/all/20250314173226.3062535-1-dwmw2@infradead.org/
> • Fix UNRET objtool warning in exc_handler.
> • Clean up magic numbers in stack frame for exc_handler.
> • Fix i386 build error due to making the debug support unconditional.
> • The int3 is still a [DO NOT APPLY] hack for later, and I plan to deal
> with that with a userspace test case based on
> http://david.woodhou.se/loadret.c which will exercise kexec-jump at the
> same time.
>
>v7: https://lore.kernel.org/kexec/20250312144257.2348250-1-dwmw2@infradead.org/
> • Drop CONFIG_KEXEC_DEBUG and make it all unconditional in order to
> "throw regressions back into the face of whoever manages to introduce
> them" (Ingo, https://lore.kernel.org/kexec/Z7rwA-qVauX7lY8G@gmail.com/)
> • Move IDT invalidation into relocate_kernel() itself.
>
>v6: https://lore.kernel.org/kexec/20250115191423.587774-1-dwmw2@infradead.org/
> • Rebase onto already-merged fixes in tip/x86/boot.
> • Move CONFIG_KEXEC_DEBUG to generic kernel/Kconfig.kexec as Bartosz is
> working on an Arm64 version.
>
>v5: https://lore.kernel.org/kexec/20241205153343.3275139-1-dwmw2@infradead.org/T/
> • Drop [RFC].
> • Drop _PAGE_NOPTISHADOW fix, which Ingo already took into tip/x86/urgent.
> • Add memory-mapped serial port support (32-bit MMIO spacing only).
>
>v4 (RFC): https://lore.kernel.org/kexec/20241127190343.44916-1-dwmw2@infradead.org/T/
> • Add _PAGE_NOPTISHADOW fix for the identmap code.
> • Drop explicit map of control page, which was masking the identmap bug.
>
>v3 (RFC): https://lore.kernel.org/kexec/20241125100815.2512-1-dwmw2@infradead.org/T/
> • Add CONFIG_KEXEC_DEBUG option and use earlyprintk config.
> • Allocate PGD separately from control page.
> • Explicitly map control page into identmap.
>
>V2 (RFC): https://lore.kernel.org/kexec/20241122224715.171751-1-dwmw2@infradead.org/T/
> • Introduce linker script, start to clean up data access.
>
>V1 (RFC): https://lore.kernel.org/kexec/20241103054019.3795299-1-dwmw2@infradead.org/T/
> • Initial proof-of-concept hacks.
>
>
>David Woodhouse (4):
> x86/kexec: Add 8250 serial port output
> x86/kexec: Add 8250 MMIO serial port output
> x86/kexec: Invalidate GDT/IDT from relocate_kernel() instead of earlier
> selftests/kexec: Add x86_64 selftest for kexec-jump and exception handling
>
> arch/x86/include/asm/kexec.h | 2 +
> arch/x86/kernel/early_printk.c | 9 +++
> arch/x86/kernel/machine_kexec_64.c | 27 ++++++---
> arch/x86/kernel/relocate_kernel_64.S | 70 ++++++++++++++++++++---
> tools/testing/selftests/kexec/Makefile | 7 +++
> tools/testing/selftests/kexec/test_kexec_jump.c | 72 ++++++++++++++++++++++++
> tools/testing/selftests/kexec/test_kexec_jump.sh | 42 ++++++++++++++
> 7 files changed, 213 insertions(+), 16 deletions(-)
>
>
Ping?
^ permalink raw reply [flat|nested] 12+ messages in thread