IA32 exception handler: restore of instruction and data pointers
PATCH 1/1 IA32 exception handler: restore of instruction and data pointers
Hi,
One more patch in the series of IA32 exception handling patches. I had thought that during an IA32 exception handling, the fields cssel, ipoff, datasel and dataoff are READONLY information. But, as it turns out, they are not. They need to be restored while returning from the exception handler.
The attached patch does the following:
1) restores cssel, ipoff, datasel and dataoff properly during the return from exception handler
2) An additional check to maintain correctness while restoring the exception status word
Please let me know, if you need any more information on this.
Thanks,
-Venkatesh
ia64/ia32/ia32_signal.c renamed from ia64/ia32/ia32_signal.c.org1 +27 -5
@@ -165,10 +165,10 @@* sw ar.fsr(0:15) * tag ar.fsr(16:31) with odd numbered bits not used * (read returns 0, writes ignored) -* ipoff ar.fir(0:31) RO -* cssel ar.fir(32:47) RO -* dataoff ar.fdr(0:31) RO -* datasel ar.fdr(32:47) RO +* ipoff ar.fir(0:31) +* cssel ar.fir(32:47) +* dataoff ar.fdr(0:31) +* datasel ar.fdr(32:47) * * _st[(0+TOS)%8] f8 * _st[(1+TOS)%8] f9 (f8, f9 from ptregs)
@@ -328,7 +328,7 @@unsigned long num64, mxcsr;struct _fpreg_ia32 *fpregp;char buf[32 ]; -unsigned long fsr, fcr; +unsigned long fsr, fcr, fir, fdr;int fp_tos, fr8_st_map;if (!access_ok (VERIFY_READ , save,sizeof (*save)))
@@ -345,6 +345,8 @@*/ asmvolatile ("mov %0=ar.fsr;" :"=r" (fsr)); asmvolatile ("mov %0=ar.fcr;" :"=r" (fcr)); + asmvolatile ("mov %0=ar.fir;" :"=r" (fir)); + asmvolatile ("mov %0=ar.fdr;" :"=r" (fdr));__get_user (mxcsr, (unsigned int *)&save->mxcsr);/* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */
@@ -355,14 +357,34 @@/* setting bits 0..31 with sw and tag and 32..37 from mxcsr */ __get_user (lo, (unsigned int *)&save->sw); +/* set bits 15,7 (fsw.b, fsw.es) to reflect the current error status */ +if ( !(lo &0x7f ) ) + lo &= (~0x8080 );__get_user (hi, (unsigned int *)&save->tag); num64 = mxcsr &0x3f ; num64 = (num64 <<16 ) | (hi &0xffff ); num64 = (num64 <<16 ) | (lo &0xffff ); fsr = (fsr & (~0x3fffffffff )) | num64; +/* setting bits 0..47 with cssel and ipoff */ +__get_user (lo, (unsigned int *)&save->ipoff); +__get_user (hi, (unsigned int *)&save->cssel); + num64 = hi &0xffff ; + num64 = (num64 <<32 ) | lo; + fir = (fir & (~0xffffffffffff )) | num64; + +/* setting bits 0..47 with datasel and dataoff */ +__get_user (lo, (unsigned int *)&save->dataoff); +__get_user (hi, (unsigned int *)&save->datasel); + num64 = hi &0xffff ; + num64 = (num64 <<32 ) | lo; + fdr = (fdr & (~0xffffffffffff )) | num64; + asmvolatile ("mov ar.fsr=%0;" ::"r" (fsr)); asmvolatile ("mov ar.fcr=%0;" ::"r" (fcr)); + asmvolatile ("mov ar.fir=%0;" ::"r" (fir)); + asmvolatile ("mov ar.fdr=%0;" ::"r" (fdr)); +/* * restore f8, f9 onto pt_regs * restore f10..f15 onto live registers
ia64/ia32/ia32_signal.c renamed from ia64/ia32/ia32_signal.c.org1 +27 -5
@@ -165,10 +165,10 @@* sw ar.fsr(0:15) * tag ar.fsr(16:31) with odd numbered bits not used * (read returns 0, writes ignored) -* ipoff ar.fir(0:31) RO -* cssel ar.fir(32:47) RO -* dataoff ar.fdr(0:31) RO -* datasel ar.fdr(32:47) RO +* ipoff ar.fir(0:31) +* cssel ar.fir(32:47) +* dataoff ar.fdr(0:31) +* datasel ar.fdr(32:47) * * _st[(0+TOS)%8] f8 * _st[(1+TOS)%8] f9 (f8, f9 from ptregs)
@@ -328,7 +328,7 @@unsigned long num64, mxcsr;struct _fpreg_ia32 *fpregp;char buf[32 ]; -unsigned long fsr, fcr; +unsigned long fsr, fcr, fir, fdr;int fp_tos, fr8_st_map;if (!access_ok (VERIFY_READ , save,sizeof (*save)))
@@ -345,6 +345,8 @@*/ asmvolatile ("mov %0=ar.fsr;" :"=r" (fsr)); asmvolatile ("mov %0=ar.fcr;" :"=r" (fcr)); + asmvolatile ("mov %0=ar.fir;" :"=r" (fir)); + asmvolatile ("mov %0=ar.fdr;" :"=r" (fdr));__get_user (mxcsr, (unsigned int *)&save->mxcsr);/* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */
@@ -355,14 +357,34 @@/* setting bits 0..31 with sw and tag and 32..37 from mxcsr */ __get_user (lo, (unsigned int *)&save->sw); +/* set bits 15,7 (fsw.b, fsw.es) to reflect the current error status */ +if ( !(lo &0x7f ) ) + lo &= (~0x8080 );__get_user (hi, (unsigned int *)&save->tag); num64 = mxcsr &0x3f ; num64 = (num64 <<16 ) | (hi &0xffff ); num64 = (num64 <<16 ) | (lo &0xffff ); fsr = (fsr & (~0x3fffffffff )) | num64; +/* setting bits 0..47 with cssel and ipoff */ +__get_user (lo, (unsigned int *)&save->ipoff); +__get_user (hi, (unsigned int *)&save->cssel); + num64 = hi &0xffff ; + num64 = (num64 <<32 ) | lo; + fir = (fir & (~0xffffffffffff )) | num64; + +/* setting bits 0..47 with datasel and dataoff */ +__get_user (lo, (unsigned int *)&save->dataoff); +__get_user (hi, (unsigned int *)&save->datasel); + num64 = hi &0xffff ; + num64 = (num64 <<32 ) | lo; + fdr = (fdr & (~0xffffffffffff )) | num64; + asmvolatile ("mov ar.fsr=%0;" ::"r" (fsr)); asmvolatile ("mov ar.fcr=%0;" ::"r" (fcr)); + asmvolatile ("mov ar.fir=%0;" ::"r" (fir)); + asmvolatile ("mov ar.fdr=%0;" ::"r" (fdr)); +/* * restore f8, f9 onto pt_regs * restore f10..f15 onto live registers