Date: Mon, 5 Nov 2018 22:54:03 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r340170 - in head/sys: amd64/include i386/include x86/x86 Message-ID: <201811052254.wA5Ms3ts089287@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@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); +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201811052254.wA5Ms3ts089287>