From ee4b23ccac038bd616d83771373cf8a5bf2a0d24 Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 1 May 2004 15:59:17 +0000 Subject: [PATCH] * x86_64 exception handling fixed --- rtl/linux/osmain.inc | 13 ++++-- rtl/linux/ossysc.inc | 41 ++++++++++++++----- rtl/linux/signal.inc | 53 +++++++++++++++++++++++-- rtl/linux/x86_64/sighnd.inc | 79 +++++++++++++++++++++---------------- rtl/x86_64/x86_64.inc | 12 +++++- 5 files changed, 148 insertions(+), 50 deletions(-) diff --git a/rtl/linux/osmain.inc b/rtl/linux/osmain.inc index fc4d889557..cc1128ff95 100644 --- a/rtl/linux/osmain.inc +++ b/rtl/linux/osmain.inc @@ -507,8 +507,6 @@ var act: SigActionRec; Procedure InstallSignals; -var - oldact: SigActionRec; begin { Initialize the sigaction structure } { all flags and information set to zero } @@ -516,7 +514,11 @@ begin { initialize handler } act.sa_handler := signalhandler(@SignalToRunError); {$ifdef RTSIGACTION} - act.sa_flags:=4; + act.sa_flags:=4 +{$ifdef x86_64} + or $4000000 +{$endif x86_64} + ; {$endif RTSIGACTION} FpSigAction(SIGFPE,@act,nil); FpSigAction(SIGSEGV,@act,nil); @@ -584,7 +586,10 @@ end; { $Log$ - Revision 1.16 2004-04-27 20:47:00 florian + Revision 1.17 2004-05-01 15:59:17 florian + * x86_64 exception handling fixed + + Revision 1.16 2004/04/27 20:47:00 florian * tried to fix x86-64 signal handling Revision 1.15 2004/04/22 21:16:35 peter diff --git a/rtl/linux/ossysc.inc b/rtl/linux/ossysc.inc index 126081fd06..a8ad66189f 100644 --- a/rtl/linux/ossysc.inc +++ b/rtl/linux/ossysc.inc @@ -15,6 +15,13 @@ **************************************************************************** } +{$ifdef CPUARM} +{$define RTSIGACTION} +{$endif CPUARM} + +{$ifdef CPUx86_64} +{$define RTSIGACTION} +{$endif CPUx86_64} {$I syscallh.inc} {$I ostypes.inc} @@ -206,14 +213,6 @@ end; If OldAct is non-nil the previous action is saved there. } -{$ifdef CPUARM} -{$define RTSIGACTION} -{$endif CPUARM} - -{$ifdef CPUx86_64} -{$define RTSIGACTION} -{$endif CPUx86_64} - function Fpsigaction(sig: cint; act : psigactionrec; oact : psigactionrec): cint; [public, alias : 'FPC_SYSC_SIGACTION']; { @@ -452,6 +451,27 @@ begin Fpreadlink:=do_syscall(syscall_nr_readlink, TSysParam(name),TSysParam(linkname),maxlen); end; + +function FPSigProcMask(how:cint;nset : psigset;oset : psigset):cint; [public, alias : 'FPC_SYSC_SIGPROCMASK']; + +{ + Change the list of currently blocked signals. + How determines which signals will be blocked : + SigBlock : Add SSet to the current list of blocked signals + SigUnBlock : Remove the signals in SSet from the list of blocked signals. + SigSetMask : Set the list of blocked signals to SSet + if OldSSet is non-null, the old set will be saved there. +} + +begin +{$ifdef RTSIGACTION} + FPsigprocmask:=do_syscall(syscall_nr_rt_sigprocmask,TSysParam(how),TSysParam(nset),TSysParam(oset),TSysParam(8)); +{$else RTSIGACTION} + FPsigprocmask:=do_syscall(syscall_nr_sigprocmask,TSysParam(how),TSysParam(nset),TSysParam(oset),TSysParam(8)); +{$endif RTSIGACTION} +end; + + Function FpNanoSleep(req : ptimespec;rem : ptimespec):cint; [public, alias : 'FPC_SYSC_NANOSLEEP']; begin FpNanoSleep:=Do_SysCall(syscall_nr_nanosleep,TSysParam(req),TSysParam(rem)); @@ -509,7 +529,10 @@ end; { $Log$ - Revision 1.23 2004-04-27 20:47:00 florian + Revision 1.24 2004-05-01 15:59:17 florian + * x86_64 exception handling fixed + + Revision 1.23 2004/04/27 20:47:00 florian * tried to fix x86-64 signal handling Revision 1.22 2004/04/25 07:18:49 florian diff --git a/rtl/linux/signal.inc b/rtl/linux/signal.inc index e528550900..081637e0bb 100644 --- a/rtl/linux/signal.inc +++ b/rtl/linux/signal.inc @@ -242,9 +242,53 @@ type {$endif cpusparc} {$ifdef cpux86_64} -{ get it from glibc/sysdeps/unix/sysv/linux/x86_64/sys/uncontext.h } + + p_fpstate = ^_fpstate; + _fpstate = packed record + cwd, + swd, + twd, // Note this is not the same as the 32bit/x87/FSAVE twd + fop : word; + rip, + rdp : qword; + mxcsr, + mxcsr_mask : dword; + st_space : array[0..31] of dword; // 8*16 bytes for each FP-reg + xmm_space : array[0..63] of dword; // 16*16 bytes for each XMM-reg + reserved2 : array[0..23] of dword; + end; + PSigContextRec = ^SigContextRec; - SigContextRec = record + SigContextRec = packed record + __pad00 : array[0..4] of qword; + r8, + r9, + r10, + r11, + r12, + r13, + r14, + r15, + rdi, + rsi, + rbp, + rbx, + rdx, + rax, + rcx, + rsp, + rip, + eflags : qword; + cs, + gs, + fs, + __pad0 : word; + err, + trapno, + oldmask, + cr2 : qword; + fpstate : p_fpstate; // zero when no FPU context */ + reserved1 : array[0..7] of qword; end; {$endif cpux86_64} @@ -376,7 +420,10 @@ type { $Log$ - Revision 1.18 2004-04-27 20:47:00 florian + Revision 1.19 2004-05-01 15:59:17 florian + * x86_64 exception handling fixed + + Revision 1.18 2004/04/27 20:47:00 florian * tried to fix x86-64 signal handling Revision 1.17 2004/03/27 14:35:13 florian diff --git a/rtl/linux/x86_64/sighnd.inc b/rtl/linux/x86_64/sighnd.inc index e312d92b5e..7c1f23398d 100644 --- a/rtl/linux/x86_64/sighnd.inc +++ b/rtl/linux/x86_64/sighnd.inc @@ -20,31 +20,43 @@ const FPU_All = $7f; -function GetFPUState(const SigContext : SigContextRec) : longint; +function GetFPUState(const SigContext : SigContextRec) : word; + begin + if assigned(SigContext.fpstate) then + GetfpuState:=SigContext.fpstate^.swd; + {$ifdef SYSTEM_DEBUG} + writeln('xx:',sigcontext.en_tw,' ',sigcontext.en_cw); + {$endif SYSTEM_DEBUG} + {$ifdef SYSTEM_DEBUG} + Writeln(stderr,'FpuState = ',result); + {$endif SYSTEM_DEBUG} + end; + +function reenable_signal(sig : longint) : boolean; +var + e,olde : TSigSet; + i,j : byte; begin -{!!!!!!! - if assigned(SigContext.fpstate) then - GetfpuState:=SigContext.fpstate^.sw; -{$ifdef SYSTEM_DEBUG} - writeln('xx:',sigcontext.en_tw,' ',sigcontext.en_cw); -{$endif SYSTEM_DEBUG} -{$ifdef SYSTEM_DEBUG} - Writeln(stderr,'FpuState = ',GetFpuState); -{$endif SYSTEM_DEBUG} -} + fillchar(e,sizeof(e),#0); + { set is 1 based PM } + dec(sig); + i:=sig mod 32; + j:=sig div 32; + e[j]:=1 shl i; + fpsigprocmask(SIG_UNBLOCK,@e,nil); + reenable_signal:=geterrno=0; end; -procedure SignalToRunerror(Sig: longint; SigContext: SigContextRec); cdecl; - -var - res,fpustate : word; -begin - res:=0; - case sig of - SIGFPE : - begin - { this is not allways necessary but I don't know yet - how to tell if it is or not PM } +procedure SignalToRunerror(sig : longint; SigContext: SigContextRec); cdecl; + var + res,fpustate : word; + begin + res:=0; + case sig of + SIGFPE : + begin + { this is not allways necessary but I don't know yet + how to tell if it is or not PM } res:=200; fpustate:=GetFPUState(SigContext); if (FpuState and FPU_All) <> 0 then @@ -65,23 +77,24 @@ begin else res:=207; {'Coprocessor Error'} end; - sysResetFPU; + SysResetFPU; end; - SIGILL, - SIGBUS, - SIGSEGV : + SIGILL, + SIGBUS, + SIGSEGV: res:=216; + end; + reenable_signal(sig); + if res<>0 then + HandleErrorAddrFrame(res,pointer(SigContext.rip),pointer(SigContext.rbp)); end; -{ give runtime error at the position where the signal was raised } -{!!!! - if res<>0 then - HandleErrorAddrFrame(res,pointer(SigContext.eip),pointer(SigContext.ebp)); -} -end; { $Log$ - Revision 1.1 2004-02-05 01:16:12 florian + Revision 1.2 2004-05-01 15:59:17 florian + * x86_64 exception handling fixed + + Revision 1.1 2004/02/05 01:16:12 florian + completed x86-64/linux system unit Revision 1.2 2003/11/01 01:58:11 marco diff --git a/rtl/x86_64/x86_64.inc b/rtl/x86_64/x86_64.inc index 2220867440..c486ddf546 100644 --- a/rtl/x86_64/x86_64.inc +++ b/rtl/x86_64/x86_64.inc @@ -343,9 +343,19 @@ const FPU_StackOverflow = $40; FPU_ExceptionMask = $ff; +{$define FPC_SYSTEM_HAS_SYSRESETFPU} +Procedure SysResetFPU;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} +asm + fninit + fldcw fpucw +end; + { $Log$ - Revision 1.11 2004-04-29 19:50:13 peter + Revision 1.12 2004-05-01 15:59:17 florian + * x86_64 exception handling fixed + + Revision 1.11 2004/04/29 19:50:13 peter * x86-64 fixes Revision 1.10 2004/04/26 15:55:01 peter