svn commit: r354889 - head/sys/amd64/amd64

Konstantin Belousov kib at FreeBSD.org
Wed Nov 20 11:12:20 UTC 2019


Author: kib
Date: Wed Nov 20 11:12:19 2019
New Revision: 354889
URL: https://svnweb.freebsd.org/changeset/base/354889

Log:
  amd64: in double fault handler, do not rely on sane gsbase value.
  
  Typical reasons for doublefault faults are either kernel stack
  overflow or bugs in the code that manipulates protection CPU state.
  The later code is the code which often has to set up gsbase for
  kernel.  Switching to explicit load of GSBASE MSR in the fault handler
  makes it more probable to output a useful information.
  
  Now all IST handlers have nmi_pcpu structure on top of their stacks.
  
  It would be even more useful to save gsbase value at the moment of the
  fault.  I did not this because I do not want to modify PCB layout now.
  
  Tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Modified:
  head/sys/amd64/amd64/exception.S
  head/sys/amd64/amd64/machdep.c
  head/sys/amd64/amd64/mp_machdep.c

Modified: head/sys/amd64/amd64/exception.S
==============================================================================
--- head/sys/amd64/amd64/exception.S	Wed Nov 20 10:27:43 2019	(r354888)
+++ head/sys/amd64/amd64/exception.S	Wed Nov 20 11:12:19 2019	(r354889)
@@ -345,10 +345,11 @@ IDTVEC(dblfault)
 	pushfq
 	andq	$~(PSL_D | PSL_AC),(%rsp)
 	popfq
-	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
-	jz	1f			/* already running with kernel GS.base */
-	swapgs
-1:	lfence
+	movq	TF_SIZE(%rsp),%rdx
+	movl	%edx,%eax
+	shrq	$32,%rdx
+	movl	$MSR_GSBASE,%ecx
+	wrmsr
 	movq	%cr3,%rax
 	movq	%rax,PCPU(SAVED_UCR3)
 	movq	PCPU(KCR3),%rax

Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c	Wed Nov 20 10:27:43 2019	(r354888)
+++ head/sys/amd64/amd64/machdep.c	Wed Nov 20 11:12:19 2019	(r354889)
@@ -1575,7 +1575,9 @@ amd64_bsp_ist_init(struct pcpu *pc)
 	tssp = &pc->pc_common_tss;
 
 	/* doublefault stack space, runs on ist1 */
-	tssp->tss_ist1 = (long)&dblfault_stack[sizeof(dblfault_stack)];
+	np = ((struct nmi_pcpu *)&dblfault_stack[sizeof(dblfault_stack)]) - 1;
+	np->np_pcpu = (register_t)pc;
+	tssp->tss_ist1 = (long)np;
 
 	/*
 	 * NMI stack, runs on ist2.  The pcpu pointer is stored just

Modified: head/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- head/sys/amd64/amd64/mp_machdep.c	Wed Nov 20 10:27:43 2019	(r354888)
+++ head/sys/amd64/amd64/mp_machdep.c	Wed Nov 20 11:12:19 2019	(r354889)
@@ -314,18 +314,24 @@ init_secondary(void)
 	    IOPERM_BITMAP_SIZE;
 	pc->pc_common_tss.tss_rsp0 = 0;
 
-	pc->pc_common_tss.tss_ist1 = (long)&doublefault_stack[PAGE_SIZE];
+	/* The doublefault stack runs on IST1. */
+	np = ((struct nmi_pcpu *)&doublefault_stack[PAGE_SIZE]) - 1;
+	np->np_pcpu = (register_t)pc;
+	pc->pc_common_tss.tss_ist1 = (long)np;
 
 	/* The NMI stack runs on IST2. */
 	np = ((struct nmi_pcpu *) &nmi_stack[PAGE_SIZE]) - 1;
+	np->np_pcpu = (register_t)pc;
 	pc->pc_common_tss.tss_ist2 = (long)np;
 
 	/* The MC# stack runs on IST3. */
 	np = ((struct nmi_pcpu *) &mce_stack[PAGE_SIZE]) - 1;
+	np->np_pcpu = (register_t)pc;
 	pc->pc_common_tss.tss_ist3 = (long)np;
 
 	/* The DB# stack runs on IST4. */
 	np = ((struct nmi_pcpu *) &dbg_stack[PAGE_SIZE]) - 1;
+	np->np_pcpu = (register_t)pc;
 	pc->pc_common_tss.tss_ist4 = (long)np;
 
 	/* Prepare private GDT */
@@ -340,18 +346,6 @@ init_secondary(void)
 	ap_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
 	ap_gdt.rd_base = (u_long)gdt;
 	lgdt(&ap_gdt);			/* does magic intra-segment return */
-
-	/* Save the per-cpu pointer for use by the NMI handler. */
-	np = ((struct nmi_pcpu *) &nmi_stack[PAGE_SIZE]) - 1;
-	np->np_pcpu = (register_t)pc;
-
-	/* Save the per-cpu pointer for use by the MC# handler. */
-	np = ((struct nmi_pcpu *) &mce_stack[PAGE_SIZE]) - 1;
-	np->np_pcpu = (register_t)pc;
-
-	/* Save the per-cpu pointer for use by the DB# handler. */
-	np = ((struct nmi_pcpu *) &dbg_stack[PAGE_SIZE]) - 1;
-	np->np_pcpu = (register_t)pc;
 
 	wrmsr(MSR_FSBASE, 0);		/* User value */
 	wrmsr(MSR_GSBASE, (u_int64_t)pc);


More information about the svn-src-head mailing list