[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241122224715.171751-15-dwmw2@infradead.org>
Date: Fri, 22 Nov 2024 22:38:23 +0000
From: David Woodhouse <dwmw2@...radead.org>
To: kexec@...ts.infradead.org
Cc: Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>,
Borislav Petkov <bp@...en8.de>,
Dave Hansen <dave.hansen@...ux.intel.com>,
x86@...nel.org,
"H. Peter Anvin" <hpa@...or.com>,
David Woodhouse <dwmw@...zon.co.uk>,
"Kirill A. Shutemov" <kirill.shutemov@...ux.intel.com>,
Kai Huang <kai.huang@...el.com>,
Nikolay Borisov <nik.borisov@...e.com>,
linux-kernel@...r.kernel.org,
Simon Horman <horms@...nel.org>,
Dave Young <dyoung@...hat.com>,
Peter Zijlstra <peterz@...radead.org>,
jpoimboe@...nel.org
Subject: [RFC PATCH v2 14/16] x86/kexec: Debugging support: Load an IDT and basic exception entry points
From: David Woodhouse <dwmw@...zon.co.uk>
Signed-off-by: David Woodhouse <dwmw@...zon.co.uk>
---
arch/x86/kernel/relocate_kernel_64.S | 114 +++++++++++++++++++++++++++
1 file changed, 114 insertions(+)
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 5c174829f794..4ace2577afc6 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -40,6 +40,9 @@ SYM_DATA(kexec_pa_swap_page, .quad 0)
SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0)
#ifdef DEBUG
+ /* Size of each exception handler referenced by the IDT */
+#define EXC_HANDLER_SIZE 6 /* pushi, pushi, 2-byte jmp */
+
SYM_DATA_START_LOCAL(reloc_kernel_gdt)
.balign 16
.word reloc_kernel_gdt_end - reloc_kernel_gdt - 1
@@ -108,6 +111,11 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
int3
SYM_CODE_END(relocate_kernel)
+#ifdef DEBUG
+ UNWIND_HINT_UNDEFINED
+ .balign 0x100 /* relocate_kernel will be overwritten with an IDT */
+#endif
+
SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
UNWIND_HINT_END_OF_STACK
/*
@@ -137,6 +145,52 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
/* Test that we can load segments */
movq %ds, %rax
movq %rax, %ds
+
+ /* Load address of reloc_kernel, at start of this page, into %rsi */
+ lea relocate_kernel(%rip), %rsi
+
+ /*
+ * Build an IDT descriptor in %rax/%rbx. The address is in the low 16
+ * and high 16 bits of %rax, and low 32 of %rbx. The niddle 32 bits
+ * of %rax hold the selector/ist/flags which are hard-coded below.
+ */
+ movq %rsi, %rax // 1234567890abcdef
+
+ andq $-0xFFFF, %rax // 1234567890ab....
+ shlq $16, %rax // 567890ab........
+
+ movq $0x8F000010, %rcx // Present, DPL0, Interrupt Gate, __KERNEL_CS.
+ orq %rcx, %rax // 567890ab8F000010
+ shlq $16, %rax // 90ab8F000010....
+
+ movq %rsi, %rcx
+ andq $0xffff, %rcx // ............cdef
+ orq %rcx, %rax // 90ab87000010cdef
+
+ movq %rsi, %rbx
+ shrq $32, %rbx
+
+ /*
+ * The descriptor was built using the address of relocate_kernel. Add
+ * the required offset to point to the actual entry points.
+ */
+ addq $(exc_vectors - relocate_kernel), %rax
+
+ /* Loop 16 times to handle exception 0-15 */
+ movq $16, %rcx
+1:
+ movq %rax, (%rsi)
+ movq %rbx, 8(%rsi)
+ addq $16, %rsi
+ addq $EXC_HANDLER_SIZE, %rax
+ loop 1b
+
+ /* Now put an IDTR on the stack (temporarily) to load it */
+ subq $0x100, %rsi
+ pushq %rsi
+ pushw $0xff
+ lidt (%rsp)
+ addq $10, %rsp
#endif /* DEBUG */
/*
@@ -345,3 +399,63 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
int3
SYM_CODE_END(swap_pages)
+#ifdef DEBUG
+SYM_CODE_START_LOCAL_NOALIGN(exc_vectors)
+ /* Each of these is 6 bytes. */
+.macro vec_err exc
+ UNWIND_HINT_ENTRY
+ . = exc_vectors + (\exc * EXC_HANDLER_SIZE)
+ nop
+ nop
+ pushq $\exc
+ jmp exc_handler
+.endm
+
+.macro vec_noerr exc
+ UNWIND_HINT_ENTRY
+ . = exc_vectors + (\exc * EXC_HANDLER_SIZE)
+ pushq $0
+ pushq $\exc
+ jmp exc_handler
+.endm
+
+ vec_noerr 0 // #DE
+ vec_noerr 1 // #DB
+ vec_noerr 2 // #NMI
+ vec_noerr 3 // #BP
+ vec_noerr 4 // #OF
+ vec_noerr 5 // #BR
+ vec_noerr 6 // #UD
+ vec_noerr 7 // #NM
+ vec_err 8 // #DF
+ vec_noerr 9
+ vec_err 10 // #TS
+ vec_err 11 // #NP
+ vec_err 12 // #SS
+ vec_err 13 // #GP
+ vec_err 14 // #PF
+ vec_noerr 15
+SYM_CODE_END(exc_vectors)
+
+SYM_CODE_START_LOCAL_NOALIGN(exc_handler)
+ pushq %rax
+ pushq %rdx
+ movw $0x3f8, %dx
+ movb $'A', %al
+ outb %al, %dx
+ popq %rdx
+ popq %rax
+
+ /* Only return from int3 */
+ cmpq $3, (%rsp)
+ jne .Ldie
+
+ addq $16, %rsp
+ iretq
+
+.Ldie:
+ hlt
+ jmp .Ldie
+
+SYM_CODE_END(exc_handler)
+#endif /* DEBUG */
--
2.47.0
Powered by blists - more mailing lists