diff options
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/amd64/amd64/fpu.c | 6 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/locore.S | 11 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/trap.c | 14 |
3 files changed, 26 insertions, 5 deletions
diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c index 4e8365cc694..74cd263c015 100644 --- a/sys/arch/amd64/amd64/fpu.c +++ b/sys/arch/amd64/amd64/fpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fpu.c,v 1.35 2017/05/29 14:19:49 mpi Exp $ */ +/* $OpenBSD: fpu.c,v 1.36 2017/10/03 17:36:40 guenther Exp $ */ /* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */ /*- @@ -55,6 +55,8 @@ #include <dev/isa/isavar.h> +void xrstor_user(struct savefpu *_addr, uint64_t _mask); + /* * We do lazy initialization and switching using the TS bit in cr0 and the * MDP_USEDFPU bit in mdproc. @@ -253,7 +255,7 @@ fpudna(struct cpu_info *ci) p->p_md.md_flags |= MDP_USEDFPU; } else { if (xsave_mask) { - xrstor(sfp, xsave_mask); + xrstor_user(sfp, xsave_mask); } else { static double zero = 0.0; diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S index dbd2e2fbbaf..e0fa7144b62 100644 --- a/sys/arch/amd64/amd64/locore.S +++ b/sys/arch/amd64/amd64/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.87 2017/07/06 06:17:04 deraadt Exp $ */ +/* $OpenBSD: locore.S,v 1.88 2017/10/03 17:36:40 guenther Exp $ */ /* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */ /* @@ -691,6 +691,15 @@ _C_LABEL(doreti_iret): iretq #endif /* !defined(GPROF) && defined(DDBPROF) */ +ENTRY(xrstor_user) + movq %rsi, %rdx + movl %esi, %eax + shrq $32, %rdx + .globl xrstor_fault +xrstor_fault: + xrstor (%rdi) + ret + ENTRY(pagezero) movq $-PAGE_SIZE,%rdx subq %rdx,%rdi diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c index 726bea4394e..66278f198e8 100644 --- a/sys/arch/amd64/amd64/trap.c +++ b/sys/arch/amd64/amd64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.58 2017/09/16 02:03:40 guenther Exp $ */ +/* $OpenBSD: trap.c,v 1.59 2017/10/03 17:36:40 guenther Exp $ */ /* $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $ */ /*- @@ -144,7 +144,7 @@ trap(struct trapframe *frame) struct proc *p = curproc; int type = (int)frame->tf_trapno; struct pcb *pcb; - extern char doreti_iret[], resume_iret[]; + extern char doreti_iret[], resume_iret[], xrstor_fault[]; caddr_t onfault; int error; uint64_t cr2; @@ -204,6 +204,15 @@ trap(struct trapframe *frame) /*NOTREACHED*/ case T_PROTFLT: + /* + * Check for xrstor faulting because of invalid xstate + * We do this by looking at the address of the + * instruction that faulted. + */ + if (frame->tf_rip == (u_int64_t)xrstor_fault && p != NULL) { + fpusave_proc(p, 0); + goto user_trap; + } case T_SEGNPFLT: case T_ALIGNFLT: case T_TSSFLT: @@ -231,6 +240,7 @@ copyfault: case T_TSSFLT|T_USER: case T_SEGNPFLT|T_USER: case T_STKFLT|T_USER: +user_trap: #ifdef TRAP_SIGDEBUG printf("pid %d (%s): %s at rip %llx addr %llx\n", p->p_p->ps_pid, p->p_p->ps_comm, "BUS", |