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
This commit is contained in:
parent
c35530f464
commit
7f7f6f85a1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=340170
@ -50,7 +50,6 @@
|
|||||||
#define cpu_getstack(td) ((td)->td_frame->tf_rsp)
|
#define cpu_getstack(td) ((td)->td_frame->tf_rsp)
|
||||||
#define cpu_setstack(td, ap) ((td)->td_frame->tf_rsp = (ap))
|
#define cpu_setstack(td, ap) ((td)->td_frame->tf_rsp = (ap))
|
||||||
#define cpu_spinwait() ia32_pause()
|
#define cpu_spinwait() ia32_pause()
|
||||||
#define cpu_lock_delay() DELAY(1)
|
|
||||||
|
|
||||||
#define TRAPF_USERMODE(framep) \
|
#define TRAPF_USERMODE(framep) \
|
||||||
(ISPL((framep)->tf_cs) == SEL_UPL)
|
(ISPL((framep)->tf_cs) == SEL_UPL)
|
||||||
@ -78,6 +77,7 @@ extern char etext[];
|
|||||||
extern void (*vmm_resume_p)(void);
|
extern void (*vmm_resume_p)(void);
|
||||||
|
|
||||||
void cpu_halt(void);
|
void cpu_halt(void);
|
||||||
|
void cpu_lock_delay(void);
|
||||||
void cpu_reset(void);
|
void cpu_reset(void);
|
||||||
void fork_trampoline(void);
|
void fork_trampoline(void);
|
||||||
void swi_vm(void *);
|
void swi_vm(void *);
|
||||||
|
@ -50,7 +50,6 @@
|
|||||||
#define cpu_getstack(td) ((td)->td_frame->tf_esp)
|
#define cpu_getstack(td) ((td)->td_frame->tf_esp)
|
||||||
#define cpu_setstack(td, ap) ((td)->td_frame->tf_esp = (ap))
|
#define cpu_setstack(td, ap) ((td)->td_frame->tf_esp = (ap))
|
||||||
#define cpu_spinwait() ia32_pause()
|
#define cpu_spinwait() ia32_pause()
|
||||||
#define cpu_lock_delay() DELAY(1)
|
|
||||||
|
|
||||||
#define TRAPF_USERMODE(framep) \
|
#define TRAPF_USERMODE(framep) \
|
||||||
((ISPL((framep)->tf_cs) == SEL_UPL) || ((framep)->tf_eflags & PSL_VM))
|
((ISPL((framep)->tf_cs) == SEL_UPL) || ((framep)->tf_eflags & PSL_VM))
|
||||||
@ -73,6 +72,7 @@ extern char btext[];
|
|||||||
extern char etext[];
|
extern char etext[];
|
||||||
|
|
||||||
void cpu_halt(void);
|
void cpu_halt(void);
|
||||||
|
void cpu_lock_delay(void);
|
||||||
void cpu_reset(void);
|
void cpu_reset(void);
|
||||||
void fork_trampoline(void);
|
void fork_trampoline(void);
|
||||||
void swi_vm(void *);
|
void swi_vm(void *);
|
||||||
|
@ -122,3 +122,22 @@ DELAY(int n)
|
|||||||
init_ops.early_delay(n);
|
init_ops.early_delay(n);
|
||||||
TSEXIT();
|
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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user