diff options
author | kib <kib@FreeBSD.org> | 2017-09-11 08:48:36 +0000 |
---|---|---|
committer | Luiz Souza <luiz@netgate.com> | 2018-02-19 14:31:40 -0300 |
commit | 2589da26b930eaf9441b6bf27c0f410062adf507 (patch) | |
tree | f814d1d2fffd5b06bf6cc8ee0a35de86abc861ab /sys/amd64/include | |
parent | e4ceef150ec3bdd258987bf82d56662293bb1ace (diff) | |
download | FreeBSD-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.h | 7 | ||||
-rw-r--r-- | sys/amd64/include/pcb.h | 35 |
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_ */ |