ref: 5be936a1926529abc8c9a0aa2cdca81d8e6583ec
parent: 61a8b5c8037a78843815eccc225487b27b1547a7
author: cinap_lenrek <cinap_lenrek@localhost>
date: Wed Jul 20 03:48:33 EDT 2011
pc/trap: cleanup exception handling
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -168,9 +168,7 @@
void trapinit0(void);
int tas(void*);
int tryrdmsr(int, vlong*);
-void tryrdmsrbody(void);
int trywrmsr(int, vlong);
-void trywrmsrbody(void);
uvlong tscticks(uvlong*);
ulong umbmalloc(ulong, int, int);
void umbfree(ulong, int);
--- a/sys/src/9/pc/l.s
+++ b/sys/src/9/pc/l.s
@@ -695,7 +695,7 @@
TEXT tryrdmsr(SB), $0 /* model-specific register */
MOVL $0, BP
MOVL index+0(FP), CX
-TEXT tryrdmsrbody(SB), $0
+TEXT _tryrdmsrinst(SB), $0
RDMSR
MOVL vlong+4(FP), CX /* &vlong */
MOVL AX, 0(CX) /* lo */
@@ -715,7 +715,7 @@
MOVL index+0(FP), CX
MOVL lo+4(FP), AX
MOVL hi+8(FP), DX
-TEXT trywrmsrbody(SB), $0
+TEXT _trywrmsrinst(SB), $0
WRMSR
MOVL BP, AX
RET
@@ -1065,11 +1065,16 @@
TEXT forkret(SB), $0
POPL AX
POPAL
+TEXT _forkretpopgs(SB), $0
POPL GS
+TEXT _forkretpopfs(SB), $0
POPL FS
+TEXT _forkretpopes(SB), $0
POPL ES
+TEXT _forkretpopds(SB), $0
POPL DS
ADDL $8, SP /* pop error code and trap type */
+TEXT _forkretiret(SB), $0
IRETL
TEXT vectortable(SB), $0
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -425,51 +425,48 @@
;
}
- if(vno == VectorGPF || vno == VectorSNP){
- ulong *sp;
- uchar *pc;
+ if(!user){
+ void (*pc)(void);
+ ulong *sp;
- /* l.s */
+ extern void _forkretpopgs(void);
+ extern void _forkretpopfs(void);
+ extern void _forkretpopes(void);
+ extern void _forkretpopds(void);
+ extern void _forkretiret(void);
+ extern void _tryrdmsrinst(void);
+ extern void _trywrmsrinst(void);
+
extern void load_fs(ulong);
extern void load_gs(ulong);
- /*
- * CS, SS, DS and ES are initialized by strayintr
- * in l.s. initialize the others too so we dont trap
- * again when restoring the old context.
- */
load_fs(NULLSEL);
load_gs(NULLSEL);
- pc = (uchar*)ureg->pc;
- sp = (ulong*)&ureg->sp;
+ sp = (ulong*)&ureg->sp; /* kernel stack */
+ pc = (void*)ureg->pc;
- /*
- * we test for the instructions used by forkret()
- * to load the segments and replace the selectors
- * on the (kernel) stack with null selectors.
- */
- switch(pc[0]){
- case 0x0f: /* POP GS/FS */
- if(pc[1] != 0xa9 && pc[1] != 0xa1)
- break;
- case 0x07: /* POP ES */
- case 0x1f: /* POP DS */
- sp[0] = NULLSEL;
- return;
- case 0xcf: /* IRET */
- sp[1] = UESEL; /* CS */
- sp[4] = UDSEL; /* SS */
- return;
+ if(pc == _forkretpopgs || pc == _forkretpopfs ||
+ pc == _forkretpopes || pc == _forkretpopds){
+ if(vno == VectorGPF || vno == VectorSNP){
+ sp[0] = NULLSEL;
+ return;
+ }
+ } else if(pc == _forkretiret){
+ if(vno == VectorGPF || vno == VectorSNP){
+ sp[1] = UESEL; /* CS */
+ sp[4] = UDSEL; /* SS */
+ return;
+ }
+ } else if(pc == _tryrdmsrinst || pc == _trywrmsrinst){
+ if(vno == VectorGPF){
+ ureg->bp = -1;
+ ureg->pc += 2;
+ return;
+ }
}
}
- if(vno == VectorGPF && !user &&
- (ureg->pc == (ulong)(void*)tryrdmsrbody ||
- ureg->pc == (ulong)(void*)trywrmsrbody)){
- ureg->bp = -1;
- ureg->pc += 2;
- return;
- }
+
dumpregs(ureg);
if(!user){
ureg->sp = (ulong)&ureg->sp;