svn commit: r340170 - in head/sys: amd64/include i386/include x86/x86

John Baldwin jhb at FreeBSD.org
Mon Nov 5 22:54:06 UTC 2018


Author: jhb
Date: Mon Nov  5 22:54:03 2018
New Revision: 340170
URL: https://svnweb.freebsd.org/changeset/base/340170

Log:
  Add a custom implementation of cpu_lock_delay() for x86.
  
  Avoid using DELAY() since it can try to use spin locks on CPUs without
  a P-state invariant TSC.  For cpu_lock_delay(), always use the TSC if
  it exists (even if it is not P-state invariant) to delay for a
  microsecond.  If the TSC does not exist, read from I/O port 0x84 to
  delay instead.
  
  PR:		228768
  Reported by:	Roger Hammerstein <cheeky.m at live.com>
  Reviewed by:	kib
  MFC after:	3 days
  Differential Revision:	https://reviews.freebsd.org/D17851

Modified:
  head/sys/amd64/include/cpu.h
  head/sys/i386/include/cpu.h
  head/sys/x86/x86/delay.c

Modified: head/sys/amd64/include/cpu.h
==============================================================================
--- head/sys/amd64/include/cpu.h	Mon Nov  5 22:53:50 2018	(r340169)
+++ head/sys/amd64/include/cpu.h	Mon Nov  5 22:54:03 2018	(r340170)
@@ -50,7 +50,6 @@
 #define	cpu_getstack(td)		((td)->td_frame->tf_rsp)
 #define	cpu_setstack(td, ap)		((td)->td_frame->tf_rsp = (ap))
 #define	cpu_spinwait()			ia32_pause()
-#define	cpu_lock_delay()		DELAY(1)
 
 #define	TRAPF_USERMODE(framep) \
 	(ISPL((framep)->tf_cs) == SEL_UPL)
@@ -78,6 +77,7 @@ extern char	etext[];
 extern	void (*vmm_resume_p)(void);
 
 void	cpu_halt(void);
+void	cpu_lock_delay(void);
 void	cpu_reset(void);
 void	fork_trampoline(void);
 void	swi_vm(void *);

Modified: head/sys/i386/include/cpu.h
==============================================================================
--- head/sys/i386/include/cpu.h	Mon Nov  5 22:53:50 2018	(r340169)
+++ head/sys/i386/include/cpu.h	Mon Nov  5 22:54:03 2018	(r340170)
@@ -50,7 +50,6 @@
 #define	cpu_getstack(td)		((td)->td_frame->tf_esp)
 #define	cpu_setstack(td, ap)		((td)->td_frame->tf_esp = (ap))
 #define	cpu_spinwait()			ia32_pause()
-#define	cpu_lock_delay()		DELAY(1)
 
 #define	TRAPF_USERMODE(framep) \
 	((ISPL((framep)->tf_cs) == SEL_UPL) || ((framep)->tf_eflags & PSL_VM))
@@ -73,6 +72,7 @@ extern char	btext[];
 extern char	etext[];
 
 void	cpu_halt(void);
+void	cpu_lock_delay(void);
 void	cpu_reset(void);
 void	fork_trampoline(void);
 void	swi_vm(void *);

Modified: head/sys/x86/x86/delay.c
==============================================================================
--- head/sys/x86/x86/delay.c	Mon Nov  5 22:53:50 2018	(r340169)
+++ head/sys/x86/x86/delay.c	Mon Nov  5 22:54:03 2018	(r340170)
@@ -122,3 +122,22 @@ DELAY(int n)
 	init_ops.early_delay(n);
 	TSEXIT();
 }
+
+void
+cpu_lock_delay(void)
+{
+
+	/*
+	 * Use TSC to wait for a usec if present, otherwise fall back
+	 * to reading from port 0x84.  We can't call into timecounters
+	 * for this delay since timecounters might use spin locks.
+	 *
+	 * Note that unlike delay_tc(), this uses the TSC even if it
+	 * is not P-state invariant.  For this function it is ok to
+	 * wait even a few usecs.
+	 */
+	if (tsc_freq != 0)
+		delay_tsc(1);
+	else
+		inb(0x84);
+}


More information about the svn-src-all mailing list