diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-07-20 07:48:33 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-07-20 07:48:33 +0200 |
commit | 5be936a1926529abc8c9a0aa2cdca81d8e6583ec (patch) | |
tree | af81d873e2be42bc15ea112bb125970cc313302c /sys/src/9/pc/trap.c | |
parent | 61a8b5c8037a78843815eccc225487b27b1547a7 (diff) |
pc/trap: cleanup exception handling
Diffstat (limited to 'sys/src/9/pc/trap.c')
-rw-r--r-- | sys/src/9/pc/trap.c | 69 |
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; |