summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/trap.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@localhost>2011-07-20 07:48:33 +0200
committercinap_lenrek <cinap_lenrek@localhost>2011-07-20 07:48:33 +0200
commit5be936a1926529abc8c9a0aa2cdca81d8e6583ec (patch)
treeaf81d873e2be42bc15ea112bb125970cc313302c /sys/src/9/pc/trap.c
parent61a8b5c8037a78843815eccc225487b27b1547a7 (diff)
pc/trap: cleanup exception handling
Diffstat (limited to 'sys/src/9/pc/trap.c')
-rw-r--r--sys/src/9/pc/trap.c69
1 files changed, 33 insertions, 36 deletions
diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c
index ba52895ea..686f9e53e 100644
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -425,51 +425,48 @@ trap(Ureg* ureg)
;
}
- if(vno == VectorGPF || vno == VectorSNP){
- ulong *sp;
- uchar *pc;
+ if(!user){
+ void (*pc)(void);
+ ulong *sp;
+
+ 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);
- /* l.s */
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;
-
- /*
- * 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;
+ sp = (ulong*)&ureg->sp; /* kernel stack */
+ pc = (void*)ureg->pc;
+
+ 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;