All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] x86/boot: support to handle exception in early boot
@ 2019-05-07  8:52 Pingfan Liu
  2019-05-07  8:52 ` [PATCH 1/2] x86/idt: split out idt routines Pingfan Liu
  2019-05-07  8:52 ` [PATCH 2/2] x86/boot: set up idt for very early boot stage Pingfan Liu
  0 siblings, 2 replies; 3+ messages in thread
From: Pingfan Liu @ 2019-05-07  8:52 UTC (permalink / raw)
  To: x86
  Cc: Pingfan Liu, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Kirill A. Shutemov, Cao jin, Wei Huang, Chao Fan,
	Nicolai Stange, Dou Liyang, linux-kernel

The boot code becomes a little complicated, and hits some bugs, e.g.
Commit 3a63f70bf4c3a ("x86/boot: Early parse RSDP and save it in
boot_params") broke kexec boot on EFI systems.

There is few hint when bug happens. Catching the exception and printing
message can give a immediate help, instead of adding more debug_putstr() to
narraw down the problem.

Although no functional dependency, but in order to show message, the early
console should be ready. I have sent a separate series:
https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1992923.html
https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1992919.html

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Cao jin <caoj.fnst@cn.fujitsu.com>
Cc: Wei Huang <wei@redhat.com>
Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
Cc: Nicolai Stange <nstange@suse.de>
Cc: Dou Liyang <douly.fnst@cn.fujitsu.com>
Cc: linux-kernel@vger.kernel.org

Pingfan Liu (2):
  x86/idt: split out idt routines
  x86/boot: set up idt for very early boot stage

 arch/x86/boot/compressed/head_64.S | 11 +++++++
 arch/x86/boot/compressed/misc.c    | 61 ++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/idt.h         | 64 ++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/idt.c              | 58 +---------------------------------
 4 files changed, 137 insertions(+), 57 deletions(-)
 create mode 100644 arch/x86/include/asm/idt.h

-- 
2.7.4


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] x86/idt: split out idt routines
  2019-05-07  8:52 [PATCH 0/2] x86/boot: support to handle exception in early boot Pingfan Liu
@ 2019-05-07  8:52 ` Pingfan Liu
  2019-05-07  8:52 ` [PATCH 2/2] x86/boot: set up idt for very early boot stage Pingfan Liu
  1 sibling, 0 replies; 3+ messages in thread
From: Pingfan Liu @ 2019-05-07  8:52 UTC (permalink / raw)
  To: x86
  Cc: Pingfan Liu, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Kirill A. Shutemov, Cao jin, Wei Huang, Chao Fan,
	Nicolai Stange, Dou Liyang, linux-kernel

Some idt routines can be reused in early boot stage. Splitting them out.

Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Cao jin <caoj.fnst@cn.fujitsu.com>
Cc: Wei Huang <wei@redhat.com>
Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
Cc: Nicolai Stange <nstange@suse.de>
Cc: Dou Liyang <douly.fnst@cn.fujitsu.com>
Cc: linux-kernel@vger.kernel.org
---
 arch/x86/include/asm/idt.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/idt.c      | 58 +----------------------------------------
 2 files changed, 65 insertions(+), 57 deletions(-)
 create mode 100644 arch/x86/include/asm/idt.h

diff --git a/arch/x86/include/asm/idt.h b/arch/x86/include/asm/idt.h
new file mode 100644
index 0000000..147f128
--- /dev/null
+++ b/arch/x86/include/asm/idt.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_IDT_H
+#define _ASM_X86_IDT_H
+
+#include <asm/desc_defs.h>
+
+struct idt_data {
+	unsigned int	vector;
+	unsigned int	segment;
+	struct idt_bits	bits;
+	const void	*addr;
+};
+
+#define DPL0		0x0
+#define DPL3		0x3
+
+#define DEFAULT_STACK	0
+
+#define G(_vector, _addr, _ist, _type, _dpl, _segment)	\
+	{						\
+		.vector		= _vector,		\
+		.bits.ist	= _ist,			\
+		.bits.type	= _type,		\
+		.bits.dpl	= _dpl,			\
+		.bits.p		= 1,			\
+		.addr		= _addr,		\
+		.segment	= _segment,		\
+	}
+
+/* Interrupt gate */
+#define INTG(_vector, _addr)				\
+	G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL0, __KERNEL_CS)
+
+/* System interrupt gate */
+#define SYSG(_vector, _addr)				\
+	G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL3, __KERNEL_CS)
+
+/* Interrupt gate with interrupt stack */
+#define ISTG(_vector, _addr, _ist)			\
+	G(_vector, _addr, _ist, GATE_INTERRUPT, DPL0, __KERNEL_CS)
+
+/* System interrupt gate with interrupt stack */
+#define SISTG(_vector, _addr, _ist)			\
+	G(_vector, _addr, _ist, GATE_INTERRUPT, DPL3, __KERNEL_CS)
+
+/* Task gate */
+#define TSKG(_vector, _gdt)				\
+	G(_vector, NULL, DEFAULT_STACK, GATE_TASK, DPL0, _gdt << 3)
+
+static inline void idt_init_desc(gate_desc *gate, const struct idt_data *d)
+{
+	unsigned long addr = (unsigned long) d->addr;
+
+	gate->offset_low	= (u16) addr;
+	gate->segment		= (u16) d->segment;
+	gate->bits		= d->bits;
+	gate->offset_middle	= (u16) (addr >> 16);
+#ifdef CONFIG_X86_64
+	gate->offset_high	= (u32) (addr >> 32);
+	gate->reserved		= 0;
+#endif
+}
+
+#endif
diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c
index 01adea2..80b811a 100644
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -9,49 +9,7 @@
 #include <asm/proto.h>
 #include <asm/desc.h>
 #include <asm/hw_irq.h>
-
-struct idt_data {
-	unsigned int	vector;
-	unsigned int	segment;
-	struct idt_bits	bits;
-	const void	*addr;
-};
-
-#define DPL0		0x0
-#define DPL3		0x3
-
-#define DEFAULT_STACK	0
-
-#define G(_vector, _addr, _ist, _type, _dpl, _segment)	\
-	{						\
-		.vector		= _vector,		\
-		.bits.ist	= _ist,			\
-		.bits.type	= _type,		\
-		.bits.dpl	= _dpl,			\
-		.bits.p		= 1,			\
-		.addr		= _addr,		\
-		.segment	= _segment,		\
-	}
-
-/* Interrupt gate */
-#define INTG(_vector, _addr)				\
-	G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL0, __KERNEL_CS)
-
-/* System interrupt gate */
-#define SYSG(_vector, _addr)				\
-	G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL3, __KERNEL_CS)
-
-/* Interrupt gate with interrupt stack */
-#define ISTG(_vector, _addr, _ist)			\
-	G(_vector, _addr, _ist, GATE_INTERRUPT, DPL0, __KERNEL_CS)
-
-/* System interrupt gate with interrupt stack */
-#define SISTG(_vector, _addr, _ist)			\
-	G(_vector, _addr, _ist, GATE_INTERRUPT, DPL3, __KERNEL_CS)
-
-/* Task gate */
-#define TSKG(_vector, _gdt)				\
-	G(_vector, NULL, DEFAULT_STACK, GATE_TASK, DPL0, _gdt << 3)
+#include <asm/idt.h>
 
 /*
  * Early traps running on the DEFAULT_STACK because the other interrupt
@@ -202,20 +160,6 @@ const struct desc_ptr debug_idt_descr = {
 };
 #endif
 
-static inline void idt_init_desc(gate_desc *gate, const struct idt_data *d)
-{
-	unsigned long addr = (unsigned long) d->addr;
-
-	gate->offset_low	= (u16) addr;
-	gate->segment		= (u16) d->segment;
-	gate->bits		= d->bits;
-	gate->offset_middle	= (u16) (addr >> 16);
-#ifdef CONFIG_X86_64
-	gate->offset_high	= (u32) (addr >> 32);
-	gate->reserved		= 0;
-#endif
-}
-
 static void
 idt_setup_from_table(gate_desc *idt, const struct idt_data *t, int size, bool sys)
 {
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] x86/boot: set up idt for very early boot stage
  2019-05-07  8:52 [PATCH 0/2] x86/boot: support to handle exception in early boot Pingfan Liu
  2019-05-07  8:52 ` [PATCH 1/2] x86/idt: split out idt routines Pingfan Liu
@ 2019-05-07  8:52 ` Pingfan Liu
  1 sibling, 0 replies; 3+ messages in thread
From: Pingfan Liu @ 2019-05-07  8:52 UTC (permalink / raw)
  To: x86
  Cc: Pingfan Liu, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	H. Peter Anvin, Kirill A. Shutemov, Cao jin, Wei Huang, Chao Fan,
	Nicolai Stange, Dou Liyang, linux-kernel

The boot code becomes a little complicated, and hits some bugs, e.g.
Commit 3a63f70bf4c3a ("x86/boot: Early parse RSDP and save it in
boot_params") broke kexec boot on EFI systems.

There is few hint when bug happens. Catching the exception and printing
message can give a immediate help, instead of adding more debug_putstr() to
narraw down the problem.

At present, page fault exception handler is added. And the printed out
message looks like:
  early boot page fault:
  ENTRY(startup_64) is at: 000000047f67d200
  nip: 000000047fdeedd3
  fault address: fffffffeef6fde30

Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Cao jin <caoj.fnst@cn.fujitsu.com>
Cc: Wei Huang <wei@redhat.com>
Cc: Chao Fan <fanc.fnst@cn.fujitsu.com>
Cc: Nicolai Stange <nstange@suse.de>
Cc: Dou Liyang <douly.fnst@cn.fujitsu.com>
Cc: linux-kernel@vger.kernel.org
---
 arch/x86/boot/compressed/head_64.S | 11 +++++++
 arch/x86/boot/compressed/misc.c    | 61 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index e4a25f9..f589aa2 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -527,6 +527,10 @@ relocated:
 	shrq	$3, %rcx
 	rep	stosq
 
+	pushq	%rsi			/* Save the real mode argument */
+	leaq	startup_64(%rip), %rdi
+	call	setup_early_boot_idt
+	popq	%rsi
 /*
  * Do the extraction, and jump to the new kernel..
  */
@@ -659,6 +663,13 @@ no_longmode:
 
 #include "../../kernel/verify_cpu.S"
 
+	.code64
+.align 8
+ENTRY(boot_page_fault)
+	mov	8(%rsp), %rdi
+	call	do_boot_page_fault
+	iretq
+
 	.data
 gdt64:
 	.word	gdt_end - gdt
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 475a3c6..8aaa582 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -76,6 +76,11 @@ static int lines, cols;
 #ifdef CONFIG_KERNEL_LZ4
 #include "../../../../lib/decompress_unlz4.c"
 #endif
+
+#include "../../include/asm/desc.h"
+#include "../../include/asm/idt.h"
+#include "../../include/asm/traps.h"
+
 /*
  * NOTE: When adding a new decompressor, please update the analysis in
  * ../header.S.
@@ -429,3 +434,59 @@ void fortify_panic(const char *name)
 {
 	error("detected buffer overflow");
 }
+
+static unsigned long rt_startup_64;
+
+void do_boot_page_fault(unsigned long retaddr)
+{
+	struct desc_ptr idt = { .address = 0, .size = 0 };
+	unsigned long fault_address = read_cr2();
+
+	debug_putstr("early boot page fault:\n");
+	debug_putstr("ENTRY(startup_64) is at: ");
+	debug_puthex(rt_startup_64);
+	debug_putstr("\n");
+	debug_putstr("nip: ");
+	debug_puthex(retaddr);
+	debug_putstr("\n");
+	debug_putstr("fault address: ");
+	debug_puthex(fault_address);
+	debug_putstr("\n");
+
+	load_idt(&idt);
+}
+
+asmlinkage void boot_page_fault(void);
+
+static struct idt_data boot_idts[] = {
+	INTG(X86_TRAP_PF, 0),
+};
+
+static gate_desc early_boot_idt_table[IDT_ENTRIES] __page_aligned_bss;
+
+static struct desc_ptr early_boot_idt_descr __ro_after_init = {
+	.size		= (IDT_ENTRIES * 2 * sizeof(unsigned long)) - 1,
+};
+
+static void
+idt_setup_from_table(gate_desc *idt, const struct idt_data *t, int size)
+{
+	gate_desc desc;
+
+	for (; size > 0; t++, size--) {
+		idt_init_desc(&desc, t);
+		write_idt_entry(idt, t->vector, &desc);
+	}
+}
+
+void setup_early_boot_idt(unsigned long rip)
+{
+	rt_startup_64 = rip;
+	/* fill it with runtime address */
+	boot_idts[0].addr = boot_page_fault;
+	early_boot_idt_descr.address = (unsigned long)early_boot_idt_table;
+
+	idt_setup_from_table(early_boot_idt_table, boot_idts,
+		ARRAY_SIZE(boot_idts));
+	load_idt(&early_boot_idt_descr);
+}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-05-07  8:53 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-07  8:52 [PATCH 0/2] x86/boot: support to handle exception in early boot Pingfan Liu
2019-05-07  8:52 ` [PATCH 1/2] x86/idt: split out idt routines Pingfan Liu
2019-05-07  8:52 ` [PATCH 2/2] x86/boot: set up idt for very early boot stage Pingfan Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.