summaryrefslogtreecommitdiffstats
path: root/sys/amd64/include
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2017-09-11 08:48:36 +0000
committerLuiz Souza <luiz@netgate.com>2018-02-19 14:31:40 -0300
commit2589da26b930eaf9441b6bf27c0f410062adf507 (patch)
treef814d1d2fffd5b06bf6cc8ee0a35de86abc861ab /sys/amd64/include
parente4ceef150ec3bdd258987bf82d56662293bb1ace (diff)
downloadFreeBSD-src-2589da26b930eaf9441b6bf27c0f410062adf507.zip
FreeBSD-src-2589da26b930eaf9441b6bf27c0f410062adf507.tar.gz
MFC r322762, r322799, r322832, r322833:
Make WRFSBASE and WRGSBASE instructions functional. (cherry picked from commit b1a7a7418e73251aad628dc4f9418e550a9fd3d7)
Diffstat (limited to 'sys/amd64/include')
-rw-r--r--sys/amd64/include/asmacros.h7
-rw-r--r--sys/amd64/include/pcb.h35
2 files changed, 11 insertions, 31 deletions
diff --git a/sys/amd64/include/asmacros.h b/sys/amd64/include/asmacros.h
index d5652c4..d463bfe 100644
--- a/sys/amd64/include/asmacros.h
+++ b/sys/amd64/include/asmacros.h
@@ -177,7 +177,12 @@
movw %es,TF_ES(%rsp) ; \
movw %ds,TF_DS(%rsp) ; \
movl $TF_HASSEGS,TF_FLAGS(%rsp) ; \
- cld
+ cld ; \
+ testb $SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel ? */ \
+ jz 2f ; /* yes, leave PCB_FULL_IRET alone */ \
+ movq PCPU(CURPCB),%r8 ; \
+ andl $~PCB_FULL_IRET,PCB_FLAGS(%r8) ; \
+2:
#define POP_FRAME \
movq TF_RDI(%rsp),%rdi ; \
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index 8078073..8d0dce9 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -119,40 +119,15 @@ struct susppcb {
#ifdef _KERNEL
struct trapframe;
-/*
- * The pcb_flags is only modified by current thread, or by other threads
- * when current thread is stopped. However, current thread may change it
- * from the interrupt context in cpu_switch(), or in the trap handler.
- * When we read-modify-write pcb_flags from C sources, compiler may generate
- * code that is not atomic regarding the interrupt handler. If a trap or
- * interrupt happens and any flag is modified from the handler, it can be
- * clobbered with the cached value later. Therefore, we implement setting
- * and clearing flags with single-instruction functions, which do not race
- * with possible modification of the flags from the trap or interrupt context,
- * because traps and interrupts are executed only on instruction boundary.
- */
-static __inline void
-set_pcb_flags(struct pcb *pcb, const u_int flags)
-{
-
- __asm __volatile("orl %1,%0"
- : "=m" (pcb->pcb_flags) : "ir" (flags), "m" (pcb->pcb_flags)
- : "cc");
-}
-
-static __inline void
-clear_pcb_flags(struct pcb *pcb, const u_int flags)
-{
-
- __asm __volatile("andl %1,%0"
- : "=m" (pcb->pcb_flags) : "ir" (~flags), "m" (pcb->pcb_flags)
- : "cc");
-}
-
+void clear_pcb_flags(struct pcb *pcb, const u_int flags);
void makectx(struct trapframe *, struct pcb *);
+void set_pcb_flags(struct pcb *pcb, const u_int flags);
+void set_pcb_flags_raw(struct pcb *pcb, const u_int flags);
int savectx(struct pcb *) __returns_twice;
void resumectx(struct pcb *);
+/* Ensure that pcb_gsbase and pcb_fsbase are up to date */
+#define update_pcb_bases(pcb) set_pcb_flags((pcb), PCB_FULL_IRET)
#endif
#endif /* _AMD64_PCB_H_ */
OpenPOWER on IntegriCloud