diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index 8eeacbc3d5b9..0ebb661955bb 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -281,8 +281,9 @@ doreti_next: */ testl $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */ jz doreti_notvm86 - cmpl $1,in_vm86call /* are we in a vm86 call? XXXSMP */ - jne doreti_ast /* can handle ASTs now if not */ + movl PCPU(CURPCB),%ecx + testl $PCB_VM86CALL,PCB_FLAGS(%ecx) /* are we in a vm86 call? */ + jz doreti_ast /* can handle ASTS now if not */ jmp doreti_exit doreti_notvm86: diff --git a/sys/amd64/amd64/exception.s b/sys/amd64/amd64/exception.s index 8eeacbc3d5b9..0ebb661955bb 100644 --- a/sys/amd64/amd64/exception.s +++ b/sys/amd64/amd64/exception.s @@ -281,8 +281,9 @@ doreti_next: */ testl $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */ jz doreti_notvm86 - cmpl $1,in_vm86call /* are we in a vm86 call? XXXSMP */ - jne doreti_ast /* can handle ASTs now if not */ + movl PCPU(CURPCB),%ecx + testl $PCB_VM86CALL,PCB_FLAGS(%ecx) /* are we in a vm86 call? */ + jz doreti_ast /* can handle ASTS now if not */ jmp doreti_exit doreti_notvm86: diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index 5a8cf704dd22..47856455f099 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -146,6 +146,7 @@ ASSYM(PCB_SAVEFPU_SIZE, sizeof(union savefpu)); ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); ASSYM(PCB_SIZE, sizeof(struct pcb)); +ASSYM(PCB_VM86CALL, PCB_VM86CALL); ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno)); ASSYM(TF_ERR, offsetof(struct trapframe, tf_err)); diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index a23ce493a3b2..54c4af8ae911 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -260,7 +260,8 @@ trap(frame) #endif /* DEVICE_POLLING */ if ((ISPL(frame.tf_cs) == SEL_UPL) || - ((frame.tf_eflags & PSL_VM) && !in_vm86call)) { + ((frame.tf_eflags & PSL_VM) && + !(PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL))) { /* user trap */ sticks = td->td_kse->ke_sticks; @@ -311,9 +312,7 @@ trap(frame) case T_PROTFLT: /* general protection fault */ case T_STKFLT: /* stack fault */ if (frame.tf_eflags & PSL_VM) { - mtx_lock(&Giant); i = vm86_emulate((struct vm86frame *)&frame); - mtx_unlock(&Giant); if (i == 0) goto user; break; @@ -466,9 +465,7 @@ trap(frame) case T_PROTFLT: /* general protection fault */ case T_STKFLT: /* stack fault */ if (frame.tf_eflags & PSL_VM) { - mtx_lock(&Giant); i = vm86_emulate((struct vm86frame *)&frame); - mtx_unlock(&Giant); if (i != 0) /* * returns to original process @@ -482,7 +479,7 @@ trap(frame) /* FALL THROUGH */ case T_SEGNPFLT: /* segment not present fault */ - if (in_vm86call) + if (PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL) break; if (td->td_intr_nesting_level != 0) @@ -584,7 +581,8 @@ trap(frame) * debugging the kernel. */ /* XXX Giant */ - if (user_dbreg_trap() && !in_vm86call) { + if (user_dbreg_trap() && + !(PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL)) { /* * Reset breakpoint bits because the * processor doesn't diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h index 013fc00de596..c7a837b08782 100644 --- a/sys/amd64/include/pcb.h +++ b/sys/amd64/include/pcb.h @@ -67,6 +67,8 @@ struct pcb { #define PCB_DBREGS 0x02 /* process using debug registers */ #define PCB_NPXTRAP 0x04 /* npx trap pending */ #define PCB_NPXINITDONE 0x08 /* fpu state is initialized */ +#define PCB_VM86CALL 0x10 /* in vm86 call */ + caddr_t pcb_onfault; /* copyin/out fault recovery */ int pcb_gs; struct pcb_ext *pcb_ext; /* optional pcb extension */ diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s index 8eeacbc3d5b9..0ebb661955bb 100644 --- a/sys/i386/i386/exception.s +++ b/sys/i386/i386/exception.s @@ -281,8 +281,9 @@ doreti_next: */ testl $PSL_VM,TF_EFLAGS(%esp) /* are we in vm86 mode? */ jz doreti_notvm86 - cmpl $1,in_vm86call /* are we in a vm86 call? XXXSMP */ - jne doreti_ast /* can handle ASTs now if not */ + movl PCPU(CURPCB),%ecx + testl $PCB_VM86CALL,PCB_FLAGS(%ecx) /* are we in a vm86 call? */ + jz doreti_ast /* can handle ASTS now if not */ jmp doreti_exit doreti_notvm86: diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c index 5a8cf704dd22..47856455f099 100644 --- a/sys/i386/i386/genassym.c +++ b/sys/i386/i386/genassym.c @@ -146,6 +146,7 @@ ASSYM(PCB_SAVEFPU_SIZE, sizeof(union savefpu)); ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); ASSYM(PCB_SIZE, sizeof(struct pcb)); +ASSYM(PCB_VM86CALL, PCB_VM86CALL); ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno)); ASSYM(TF_ERR, offsetof(struct trapframe, tf_err)); diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index a23ce493a3b2..54c4af8ae911 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -260,7 +260,8 @@ trap(frame) #endif /* DEVICE_POLLING */ if ((ISPL(frame.tf_cs) == SEL_UPL) || - ((frame.tf_eflags & PSL_VM) && !in_vm86call)) { + ((frame.tf_eflags & PSL_VM) && + !(PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL))) { /* user trap */ sticks = td->td_kse->ke_sticks; @@ -311,9 +312,7 @@ trap(frame) case T_PROTFLT: /* general protection fault */ case T_STKFLT: /* stack fault */ if (frame.tf_eflags & PSL_VM) { - mtx_lock(&Giant); i = vm86_emulate((struct vm86frame *)&frame); - mtx_unlock(&Giant); if (i == 0) goto user; break; @@ -466,9 +465,7 @@ trap(frame) case T_PROTFLT: /* general protection fault */ case T_STKFLT: /* stack fault */ if (frame.tf_eflags & PSL_VM) { - mtx_lock(&Giant); i = vm86_emulate((struct vm86frame *)&frame); - mtx_unlock(&Giant); if (i != 0) /* * returns to original process @@ -482,7 +479,7 @@ trap(frame) /* FALL THROUGH */ case T_SEGNPFLT: /* segment not present fault */ - if (in_vm86call) + if (PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL) break; if (td->td_intr_nesting_level != 0) @@ -584,7 +581,8 @@ trap(frame) * debugging the kernel. */ /* XXX Giant */ - if (user_dbreg_trap() && !in_vm86call) { + if (user_dbreg_trap() && + !(PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL)) { /* * Reset breakpoint bits because the * processor doesn't diff --git a/sys/i386/i386/vm86.c b/sys/i386/i386/vm86.c index fac04041c3a7..0b79669faffc 100644 --- a/sys/i386/i386/vm86.c +++ b/sys/i386/i386/vm86.c @@ -425,12 +425,13 @@ vm86_initialize(void) pcb = &vml->vml_pcb; ext = &vml->vml_ext; - mtx_init(&vm86_lock, "vm86 lock", NULL, MTX_DEF); + mtx_init(&vm86_lock, "vm86 lock", NULL, MTX_SPIN); bzero(pcb, sizeof(struct pcb)); pcb->new_ptd = vm86pa | PG_V | PG_RW | PG_U; pcb->vm86_frame = vm86paddr - sizeof(struct vm86frame); pcb->pgtable_va = vm86paddr; + pcb->pcb_flags = PCB_VM86CALL; pcb->pcb_ext = ext; bzero(ext, sizeof(struct pcb_ext)); @@ -577,9 +578,9 @@ vm86_intcall(int intnum, struct vm86frame *vmf) return (EINVAL); vmf->vmf_trapno = intnum; - mtx_lock(&vm86_lock); + mtx_lock_spin(&vm86_lock); retval = vm86_bioscall(vmf); - mtx_unlock(&vm86_lock); + mtx_unlock_spin(&vm86_lock); return (retval); } @@ -599,7 +600,7 @@ vm86_datacall(intnum, vmf, vmc) u_int page; int i, entry, retval; - mtx_lock(&vm86_lock); + mtx_lock_spin(&vm86_lock); for (i = 0; i < vmc->npages; i++) { page = vtophys(vmc->pmap[i].kva & PG_FRAME); entry = vmc->pmap[i].pte_num; @@ -616,7 +617,7 @@ vm86_datacall(intnum, vmf, vmc) pte[entry] = vmc->pmap[i].old_pte; pmap_invalidate_page(kernel_pmap, vmc->pmap[i].kva); } - mtx_unlock(&vm86_lock); + mtx_unlock_spin(&vm86_lock); return (retval); } diff --git a/sys/i386/i386/vm86bios.s b/sys/i386/i386/vm86bios.s index db79295ccbbc..1f36e0e7b352 100644 --- a/sys/i386/i386/vm86bios.s +++ b/sys/i386/i386/vm86bios.s @@ -44,9 +44,8 @@ .data ALIGN_DATA - .globl in_vm86call, vm86pcb + .globl vm86pcb -in_vm86call: .long 0 vm86pcb: .long 0 .text @@ -129,8 +128,6 @@ ENTRY(vm86_bioscall) call vm86_prepcall /* finish setup */ - movl $1,in_vm86call /* set flag for trap() */ - /* * Return via doreti */ @@ -158,8 +155,6 @@ ENTRY(vm86_biosret) popl %eax movl %eax,%cr3 /* install old page table */ - movl $0,in_vm86call /* reset trapflag */ - movl PCPU(TSS_GDT),%ebx /* entry in GDT */ movl SCR_TSS0(%edx),%eax movl %eax,0(%ebx) /* restore first word */ diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h index 013fc00de596..c7a837b08782 100644 --- a/sys/i386/include/pcb.h +++ b/sys/i386/include/pcb.h @@ -67,6 +67,8 @@ struct pcb { #define PCB_DBREGS 0x02 /* process using debug registers */ #define PCB_NPXTRAP 0x04 /* npx trap pending */ #define PCB_NPXINITDONE 0x08 /* fpu state is initialized */ +#define PCB_VM86CALL 0x10 /* in vm86 call */ + caddr_t pcb_onfault; /* copyin/out fault recovery */ int pcb_gs; struct pcb_ext *pcb_ext; /* optional pcb extension */ diff --git a/sys/i386/include/vm86.h b/sys/i386/include/vm86.h index f20a689845b8..041504abab18 100644 --- a/sys/i386/include/vm86.h +++ b/sys/i386/include/vm86.h @@ -145,7 +145,6 @@ struct vm86_intcall_args { }; #ifdef _KERNEL -extern int in_vm86call; extern int vm86paddr; struct thread;