mirror of https://github.com/red-prig/fpPS4.git
699 lines
15 KiB
Plaintext
699 lines
15 KiB
Plaintext
unit trap;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils,
|
|
ucontext,
|
|
kern_thr;
|
|
|
|
const
|
|
T_PRIVINFLT = 1; // privileged instruction
|
|
T_BPTFLT = 3; // breakpoint instruction
|
|
T_ARITHTRAP = 6; // arithmetic trap
|
|
T_PROTFLT = 9; // protection fault
|
|
T_TRCTRAP =10; // debug exception (sic)
|
|
T_PAGEFLT =12; // page fault
|
|
T_ALIGNFLT =14; // alignment fault
|
|
|
|
T_DIVIDE =18; // integer divide fault
|
|
T_NMI =19; // non-maskable trap
|
|
T_OFLOW =20; // overflow trap
|
|
T_BOUND =21; // bound instruction fault
|
|
T_DNA =22; // device not available fault
|
|
T_DOUBLEFLT =23; // double fault
|
|
T_FPOPFLT =24; // fp coprocessor operand fetch fault
|
|
T_TSSFLT =25; // invalid tss fault
|
|
T_SEGNPFLT =26; // segment not present fault
|
|
T_STKFLT =27; // stack fault
|
|
T_MCHK =28; // machine check trap
|
|
T_XMMFLT =29; // SIMD floating-point exception
|
|
T_RESERVED =30; // reserved (unknown)
|
|
T_DTRACE_RET=32; // DTrace pid return
|
|
|
|
// XXX most of the following codes aren't used, but could be.
|
|
|
|
// definitions for <sys/signal.h>
|
|
ILL_PRIVIN_FAULT=T_PRIVINFLT;
|
|
ILL_ALIGN_FAULT =T_ALIGNFLT ;
|
|
ILL_FPOP_FAULT =T_FPOPFLT ; // coprocessor operand fault
|
|
|
|
// codes for SIGBUS
|
|
BUS_PAGE_FAULT =T_PAGEFLT ; // page fault protection base
|
|
BUS_SEGNP_FAULT=T_SEGNPFLT; // segment not present
|
|
BUS_STK_FAULT =T_STKFLT ; // stack segment
|
|
BUS_SEGM_FAULT =T_RESERVED; // segment protection base
|
|
|
|
// Trap's coming from user mode
|
|
T_USER=$100;
|
|
|
|
MAX_TRAP_MSG=32;
|
|
|
|
trap_msg:array[0..MAX_TRAP_MSG] of PChar=(
|
|
'', // 0 unused
|
|
'privileged instruction fault', // 1 T_PRIVINFLT
|
|
'', // 2 unused
|
|
'breakpoint instruction fault', // 3 T_BPTFLT
|
|
'', // 4 unused
|
|
'', // 5 unused
|
|
'arithmetic trap', // 6 T_ARITHTRAP
|
|
'', // 7 unused
|
|
'', // 8 unused
|
|
'general protection fault', // 9 T_PROTFLT
|
|
'trace trap', // 10 T_TRCTRAP
|
|
'', // 11 unused
|
|
'page fault', // 12 T_PAGEFLT
|
|
'', // 13 unused
|
|
'alignment fault', // 14 T_ALIGNFLT
|
|
'', // 15 unused
|
|
'', // 16 unused
|
|
'', // 17 unused
|
|
'integer divide fault', // 18 T_DIVIDE
|
|
'non-maskable interrupt trap', // 19 T_NMI
|
|
'overflow trap', // 20 T_OFLOW
|
|
'FPU bounds check fault', // 21 T_BOUND
|
|
'FPU device not available', // 22 T_DNA
|
|
'double fault', // 23 T_DOUBLEFLT
|
|
'FPU operand fetch fault', // 24 T_FPOPFLT
|
|
'invalid TSS fault', // 25 T_TSSFLT
|
|
'segment not present fault', // 26 T_SEGNPFLT
|
|
'stack fault', // 27 T_STKFLT
|
|
'machine check trap', // 28 T_MCHK
|
|
'SIMD floating-point exception', // 29 T_XMMFLT
|
|
'reserved (unknown) fault', // 30 T_RESERVED
|
|
'', // 31 unused (reserved)
|
|
'DTrace pid return trap' // 32 T_DTRACE_RET
|
|
);
|
|
|
|
procedure _sig_lock;
|
|
procedure _sig_unlock;
|
|
|
|
procedure sig_lock;
|
|
procedure sig_unlock;
|
|
|
|
procedure fast_syscall;
|
|
procedure amd64_syscall;
|
|
|
|
procedure host_sigcode;
|
|
procedure host_sigipi;
|
|
|
|
function IS_TRAP_FUNC(rip:qword):Boolean;
|
|
|
|
function trap(frame:p_trapframe;usermode:Boolean):Integer;
|
|
function trap_pfault(frame:p_trapframe;usermode:Boolean):Integer;
|
|
|
|
implementation
|
|
|
|
uses
|
|
errno,
|
|
vm,
|
|
vmparam,
|
|
vm_map,
|
|
vm_fault,
|
|
machdep,
|
|
md_context,
|
|
signal,
|
|
kern_proc,
|
|
sys_bootparam,
|
|
subr_backtrace;
|
|
|
|
//
|
|
|
|
procedure _sig_lock; assembler; nostackframe;
|
|
asm
|
|
pushf
|
|
lock incl %gs:teb.iflag //lock interrupt
|
|
popf
|
|
end;
|
|
|
|
procedure _sig_unlock; assembler; nostackframe;
|
|
asm
|
|
pushf
|
|
lock decl %gs:teb.iflag //unlock interrupt
|
|
popf
|
|
end;
|
|
|
|
procedure sig_lock; assembler; nostackframe;
|
|
label
|
|
_exit;
|
|
asm
|
|
//prolog (debugger)
|
|
pushq %rbp
|
|
movq %rsp,%rbp
|
|
pushq %rax
|
|
pushf
|
|
|
|
movq $1,%rax
|
|
lock xadd %rax,%gs:teb.iflag //lock interrupt
|
|
test %rax,%rax
|
|
jnz _exit
|
|
|
|
movqq %gs:teb.thread,%rax //curkthread
|
|
testl TDF_AST,kthread.td_flags(%rax)
|
|
je _exit
|
|
|
|
mov $0,%rax
|
|
call fast_syscall
|
|
|
|
_exit:
|
|
//epilog (debugger)
|
|
popf
|
|
popq %rax
|
|
popq %rbp
|
|
end;
|
|
|
|
procedure sig_unlock; assembler; nostackframe;
|
|
label
|
|
_exit;
|
|
asm
|
|
//prolog (debugger)
|
|
pushq %rbp
|
|
movq %rsp,%rbp
|
|
pushq %rax
|
|
pushf
|
|
|
|
lock decl %gs:teb.iflag //unlock interrupt
|
|
jnz _exit
|
|
|
|
movqq %gs:teb.thread,%rax //curkthread
|
|
testl TDF_AST,kthread.td_flags(%rax)
|
|
je _exit
|
|
|
|
mov $0,%rax
|
|
call fast_syscall
|
|
|
|
_exit:
|
|
//epilog (debugger)
|
|
popf
|
|
popq %rax
|
|
popq %rbp
|
|
end;
|
|
|
|
type
|
|
tsyscall=function(rdi,rsi,rdx,rcx,r8,r9:QWORD):Integer;
|
|
|
|
var
|
|
sys_args_idx:array[0..5] of Byte=(
|
|
Byte(ptruint(@p_trapframe(nil)^.tf_rdi) div SizeOf(QWORD)),
|
|
Byte(ptruint(@p_trapframe(nil)^.tf_rsi) div SizeOf(QWORD)),
|
|
Byte(ptruint(@p_trapframe(nil)^.tf_rdx) div SizeOf(QWORD)),
|
|
Byte(ptruint(@p_trapframe(nil)^.tf_r10) div SizeOf(QWORD)),
|
|
Byte(ptruint(@p_trapframe(nil)^.tf_r8 ) div SizeOf(QWORD)),
|
|
Byte(ptruint(@p_trapframe(nil)^.tf_r9 ) div SizeOf(QWORD))
|
|
);
|
|
|
|
procedure print_syscall_args(var f:text;const header:RawByteString;td_frame:p_trapframe);
|
|
var
|
|
i,count:Integer;
|
|
str:shortstring;
|
|
begin
|
|
str:=header+#13#10;
|
|
|
|
count:=p_proc.p_sysent^.sv_table[td_frame^.tf_rax].sy_narg;
|
|
if (count<>0) then
|
|
begin
|
|
For i:=0 to count-1 do
|
|
begin
|
|
str:=str+' ['+IntToStr(i+1)+']:0x'+HexStr(PQWORD(td_frame)[sys_args_idx[i]],16)+#13#10;
|
|
end;
|
|
end;
|
|
|
|
Write(f,str);
|
|
end;
|
|
|
|
procedure print_error_syscall(td_frame:p_trapframe);
|
|
var
|
|
count:integer;
|
|
str:shortstring;
|
|
begin
|
|
thread_suspend_all(p_host_ipc_td);
|
|
|
|
count:=p_proc.p_sysent^.sv_table[td_frame^.tf_rax].sy_narg;
|
|
Assert(count<=6);
|
|
|
|
str:='Unhandled syscall:0x'+
|
|
IntToSTr(td_frame^.tf_rax)+':'+
|
|
p_proc.p_sysent^.sv_table[td_frame^.tf_rax].sy_name;
|
|
|
|
print_syscall_args(StdErr,str,td_frame);
|
|
|
|
print_backtrace_td(StdErr);
|
|
|
|
p_host_ipc.error(str);
|
|
|
|
Assert(false,p_proc.p_sysent^.sv_table[td_frame^.tf_rax].sy_name)
|
|
end;
|
|
|
|
procedure amd64_syscall;
|
|
var
|
|
td:p_kthread;
|
|
td_frame:p_trapframe;
|
|
scall:tsyscall;
|
|
rip:QWORD;
|
|
error:Integer;
|
|
is_guest:Boolean;
|
|
//
|
|
FPUCW:WORD;
|
|
MXCSR:DWORD;
|
|
begin
|
|
FPUCW:=Get8087CW;
|
|
MXCSR:=GetMXCSR;
|
|
|
|
//Call by ID table
|
|
|
|
td:=curkthread;
|
|
td_frame:=@td^.td_frame;
|
|
|
|
if (FPUCW<>__INITIAL_FPUCW__) then
|
|
begin
|
|
//writeln('changed FPUCW(0x',HexStr(FPUCW,4),') on ',td^.td_name);
|
|
end;
|
|
|
|
if ((MXCSR and __INITIAL_MXCSR__)<>__INITIAL_MXCSR__) then
|
|
begin
|
|
writeln('changed MXCSR(0x',HexStr((MXCSR and __INITIAL_MXCSR__),8),') on ',td^.td_name);
|
|
end;
|
|
|
|
td^.td_fpstate.XMM_SAVE_AREA.ControlWord:=FPUCW;
|
|
td^.td_fpstate.XMM_SAVE_AREA.MxCsr :=MXCSR;
|
|
|
|
cpu_fetch_syscall_args(td);
|
|
|
|
rip:=td_frame^.tf_rip;
|
|
error:=0;
|
|
scall:=nil;
|
|
is_guest:=False;
|
|
|
|
if (td_frame^.tf_rax<p_proc.p_sysent^.sv_size) then
|
|
begin
|
|
scall:=tsyscall(p_proc.p_sysent^.sv_table[td_frame^.tf_rax].sy_call);
|
|
if (scall=nil) then
|
|
begin
|
|
print_error_syscall(td_frame);
|
|
end;
|
|
end;
|
|
|
|
if (scall=nil) then
|
|
begin
|
|
error:=ENOSYS;
|
|
end else
|
|
begin
|
|
if (p_print_guest_syscall) then
|
|
if (td_frame^.tf_rax<p_proc.p_sysent^.sv_size) then
|
|
if is_guest_addr(td_frame^.tf_rip) then
|
|
begin
|
|
is_guest:=True;
|
|
print_syscall_args(stdout,'Guest syscall:'+p_proc.p_sysent^.sv_table[td_frame^.tf_rax].sy_name,td_frame);
|
|
end;
|
|
|
|
error:=scall(td_frame^.tf_rdi,
|
|
td_frame^.tf_rsi,
|
|
td_frame^.tf_rdx,
|
|
td_frame^.tf_r10,
|
|
td_frame^.tf_r8 ,
|
|
td_frame^.tf_r9 );
|
|
|
|
end;
|
|
|
|
if ((td^.td_pflags and TDP_NERRNO)=0) then
|
|
begin
|
|
td^.td_errno:=error;
|
|
end;
|
|
|
|
if is_guest then
|
|
Case error of
|
|
0:;
|
|
ERESTART:;
|
|
EJUSTRETURN:; //nothing
|
|
else
|
|
begin
|
|
Writeln('Guest syscall:',p_proc.p_sysent^.sv_table[td_frame^.tf_rax].sy_name,' error:',error);
|
|
|
|
print_backtrace_td(StdErr);
|
|
end;
|
|
end;
|
|
|
|
cpu_set_syscall_retval(td,error);
|
|
|
|
if (rip<>td^.td_frame.tf_rip) then
|
|
begin
|
|
set_pcb_flags(td,PCB_FULL_IRET); //call ipi_sigreturn
|
|
end;
|
|
|
|
//move to pcb?
|
|
Set8087CW(FPUCW);
|
|
SetMXCSR (MXCSR);
|
|
end;
|
|
|
|
procedure fast_syscall; assembler; nostackframe;
|
|
label
|
|
_align,
|
|
_restore,
|
|
_after_call,
|
|
_doreti,
|
|
_fail,
|
|
_ast,
|
|
_doreti_exit;
|
|
asm
|
|
//prolog (debugger)
|
|
pushq %rbp
|
|
movq %rsp,%rbp
|
|
|
|
movqq %rax,%r11 //save rax
|
|
movqq %rcx,%r10 //save rcx
|
|
|
|
pushf
|
|
pop %rcx //save flags to rcx
|
|
|
|
movqq %gs:teb.thread,%rax //curkthread
|
|
test %rax,%rax
|
|
jz _fail
|
|
|
|
testl PCB_IS_HLE,kthread.pcb_flags(%rax)
|
|
jne _align
|
|
|
|
movqq kthread.td_kstack.stack(%rax),%rsp //td_kstack (Implicit lock interrupt)
|
|
|
|
andl NOT_PCB_FULL_IRET,kthread.pcb_flags(%rax) //clear PCB_FULL_IRET
|
|
|
|
_align:
|
|
andq $-16,%rsp //align stack
|
|
|
|
movqq $0 ,kthread.td_frame.tf_rflags(%rax) //clear
|
|
movb %ch ,kthread.td_frame.tf_rflags(%rax) //save flags
|
|
|
|
movqq %rdi,kthread.td_frame.tf_rdi (%rax)
|
|
movqq %rsi,kthread.td_frame.tf_rsi (%rax)
|
|
movqq %rdx,kthread.td_frame.tf_rdx (%rax)
|
|
movqq $0,kthread.td_frame.tf_rcx (%rax)
|
|
movqq %r8 ,kthread.td_frame.tf_r8 (%rax)
|
|
movqq %r9 ,kthread.td_frame.tf_r9 (%rax)
|
|
movqq %r11,kthread.td_frame.tf_rax (%rax)
|
|
movqq %rbx,kthread.td_frame.tf_rbx (%rax)
|
|
movqq %r10,kthread.td_frame.tf_r10 (%rax)
|
|
movqq $0,kthread.td_frame.tf_r11 (%rax)
|
|
movqq %r12,kthread.td_frame.tf_r12 (%rax)
|
|
movqq %r13,kthread.td_frame.tf_r13 (%rax)
|
|
movqq %r14,kthread.td_frame.tf_r14 (%rax)
|
|
movqq %r15,kthread.td_frame.tf_r15 (%rax)
|
|
|
|
movqq $0 ,kthread.td_frame.tf_trapno(%rax)
|
|
movqq $0 ,kthread.td_frame.tf_addr (%rax)
|
|
movqq $0 ,kthread.td_frame.tf_flags (%rax)
|
|
movqq $5 ,kthread.td_frame.tf_err (%rax) //sizeof(call $32)
|
|
|
|
movqq (%rbp),%r11 //get prev rbp
|
|
movqq %r11,kthread.td_frame.tf_rbp(%rax)
|
|
|
|
lea 16(%rbp),%r11 //get prev rsp
|
|
movqq %r11,kthread.td_frame.tf_rsp(%rax)
|
|
|
|
movqq 8(%rbp),%r11 //get prev rip
|
|
movqq %r11,kthread.td_frame.tf_rip(%rax)
|
|
|
|
call amd64_syscall
|
|
|
|
_after_call:
|
|
|
|
movqq %gs:teb.thread,%rcx //curkthread
|
|
|
|
//Requested full context restore
|
|
testl PCB_FULL_IRET,kthread.pcb_flags(%rcx)
|
|
jnz _doreti
|
|
|
|
testl PCB_IS_HLE,kthread.pcb_flags(%rcx)
|
|
jne _restore
|
|
|
|
testl TDF_AST,kthread.td_flags(%rcx)
|
|
jne _ast
|
|
|
|
//Restore preserved registers.
|
|
|
|
_restore:
|
|
|
|
//get flags
|
|
movqq kthread.td_frame.tf_rflags(%rcx),%rax
|
|
push %rax
|
|
popf
|
|
|
|
movqq kthread.td_frame.tf_rdi(%rcx),%rdi
|
|
movqq kthread.td_frame.tf_rsi(%rcx),%rsi
|
|
movqq kthread.td_frame.tf_rdx(%rcx),%rdx
|
|
movqq kthread.td_frame.tf_rax(%rcx),%rax
|
|
|
|
movqq kthread.td_frame.tf_rsp(%rcx),%r11
|
|
lea -16(%r11),%r11
|
|
|
|
movqq %r11,%rsp //restore rsp (Implicit unlock interrupt)
|
|
|
|
movqq $0,%rcx
|
|
movqq $0,%r11
|
|
|
|
//epilog (debugger)
|
|
popq %rbp
|
|
ret
|
|
|
|
//fail (curkthread=nil)
|
|
_fail:
|
|
|
|
or $1,%rcx //set CF
|
|
push %rcx
|
|
popf
|
|
|
|
movqq $14,%rax //EFAULT
|
|
movqq $0,%rdx
|
|
movqq $0,%rcx
|
|
movqq $0,%r11
|
|
|
|
popq %rbp
|
|
ret
|
|
|
|
//ast
|
|
_ast:
|
|
|
|
call ast
|
|
jmp _after_call
|
|
|
|
//doreti
|
|
_doreti:
|
|
|
|
testl PCB_IS_HLE,kthread.pcb_flags(%rcx)
|
|
jne _doreti_exit
|
|
|
|
//%rcx=curkthread
|
|
testl TDF_AST,kthread.td_flags(%rcx)
|
|
je _doreti_exit
|
|
|
|
call ast
|
|
jmp _doreti
|
|
|
|
_doreti_exit:
|
|
|
|
//Restore full.
|
|
call ipi_sigreturn
|
|
hlt
|
|
//marker
|
|
.quad 0xDEADC0DEDEADC0DE
|
|
end;
|
|
|
|
procedure host_sigcode; assembler; nostackframe; public;
|
|
asm
|
|
call sigframe.sf_ahu(%rsp)
|
|
lea sigframe.sf_uc (%rsp),%rdi
|
|
pushq $0
|
|
movqq $417,%rax //sys_sigreturn
|
|
call fast_syscall
|
|
hlt
|
|
end;
|
|
|
|
var
|
|
guest_sigcode:array[0..21] of Byte=(
|
|
$ff,$14,$24, //CALL qword ptr [RSP]
|
|
$48,$8d,$7c,$24,$40, //LEA RDI,[RSP + 0x40]
|
|
$6a,$00, //PUSH 0x0
|
|
$48,$c7,$c0,$a1,$01,$00,$00, //MOV RAX,417
|
|
$0f,$05, //SYSCALL
|
|
$f4, //HLT
|
|
$eb,$fd //JMP -3
|
|
); public;
|
|
guest_szsigcode:Integer=Length(guest_sigcode); public;
|
|
|
|
procedure host_sigipi; assembler; nostackframe; public;
|
|
label
|
|
_ast,
|
|
_ast_exit;
|
|
asm
|
|
lea sigframe.sf_uc(%rsp),%rdi
|
|
call sys_sigreturn
|
|
|
|
//ast
|
|
_ast:
|
|
|
|
movqq %gs:teb.thread,%rax //curkthread
|
|
testl TDF_AST,kthread.td_flags(%rax)
|
|
je _ast_exit
|
|
|
|
call ast
|
|
jmp _ast
|
|
|
|
_ast_exit:
|
|
call ipi_sigreturn
|
|
hlt
|
|
end;
|
|
|
|
////
|
|
|
|
function IndexMarker(pbuf:Pointer):Pointer;
|
|
begin
|
|
Result:=nil;
|
|
while True do
|
|
begin
|
|
|
|
if (PQWORD(pbuf)^=QWORD($DEADC0DEDEADC0DE)) then
|
|
begin
|
|
Break;
|
|
end;
|
|
|
|
Inc(pbuf);
|
|
end;
|
|
Result:=pbuf;
|
|
end;
|
|
|
|
var
|
|
fast_syscall_end:Pointer=nil;
|
|
|
|
function IS_TRAP_FUNC(rip:qword):Boolean; public;
|
|
begin
|
|
if (fast_syscall_end=nil) then fast_syscall_end:=IndexMarker(@fast_syscall);
|
|
|
|
Result:=(
|
|
(rip>=QWORD(@fast_syscall)) and
|
|
(rip<=QWORD(fast_syscall_end)) //fast_syscall func size
|
|
);
|
|
end;
|
|
|
|
{
|
|
function IS_USERMODE(td:p_kthread;frame:p_trapframe):Boolean; inline;
|
|
begin
|
|
Result:=(frame^.tf_rsp>QWORD(td^.td_kstack.stack)) or (frame^.tf_rsp<=(QWORD(td^.td_kstack.sttop)));
|
|
end;
|
|
}
|
|
|
|
function trap(frame:p_trapframe;usermode:Boolean):Integer;
|
|
begin
|
|
Result:=0;
|
|
|
|
case frame^.tf_trapno of
|
|
T_PAGEFLT:
|
|
begin
|
|
Result:=trap_pfault(frame,usermode);
|
|
|
|
//print_backtrace_td(stderr);
|
|
//writeln;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure trap_fatal(frame:p_trapframe;eva:vm_offset_t;usermode:Boolean);
|
|
var
|
|
td:p_kthread;
|
|
trapno:Integer;
|
|
msg,msg2:pchar;
|
|
begin
|
|
trapno:=frame^.tf_trapno;
|
|
|
|
if (trapno <= MAX_TRAP_MSG) then
|
|
msg:=trap_msg[trapno]
|
|
else
|
|
msg:='UNKNOWN';
|
|
|
|
if usermode then
|
|
msg2:='user'
|
|
else
|
|
msg2:='kernel';
|
|
|
|
Writeln(StdErr,'Fatal trap ',trapno,': ',msg,' while in ',msg2,' mode');
|
|
|
|
Writeln(StdErr,'fault virtual address = 0x',HexStr(eva,16));
|
|
Writeln(StdErr,'instruction pointer = 0x',HexStr(frame^.tf_rip,16));
|
|
Writeln(StdErr,'stack pointer = 0x',HexStr(frame^.tf_rsp,16));
|
|
Writeln(StdErr,'frame pointer = 0x',HexStr(frame^.tf_rbp,16));
|
|
|
|
td:=curkthread;
|
|
if (td<>nil) then
|
|
begin
|
|
Writeln(StdErr,'td_ustack.stack = 0x',HexStr(td^.td_ustack.stack));
|
|
Writeln(StdErr,'td_ustack.sttop = 0x',HexStr(td^.td_ustack.sttop));
|
|
Writeln(StdErr,'td_kstack.stack = 0x',HexStr(td^.td_kstack.stack));
|
|
Writeln(StdErr,'td_kstack.sttop = 0x',HexStr(td^.td_kstack.sttop));
|
|
end;
|
|
end;
|
|
|
|
function trap_pfault(frame:p_trapframe;usermode:Boolean):Integer;
|
|
var
|
|
td:p_kthread;
|
|
eva:vm_offset_t;
|
|
map:vm_map_t;
|
|
rv:Integer;
|
|
begin
|
|
Result:=SIGSEGV;
|
|
|
|
td:=curkthread;
|
|
eva:=frame^.tf_addr;
|
|
|
|
if ((td^.td_pflags and TDP_NOFAULTING)<>0) then
|
|
begin
|
|
Writeln('TDP_NOFAULTING:',curkthread^.td_name);
|
|
Exit(SIGSEGV);
|
|
end;
|
|
|
|
if is_guest_addr(eva) then
|
|
begin
|
|
map:=p_proc.p_vmspace;
|
|
|
|
rv:=vm_fault.vm_fault(map,
|
|
frame^.tf_addr,
|
|
frame^.tf_rip,
|
|
frame^.tf_err,
|
|
VM_FAULT_NORMAL);
|
|
|
|
case rv of
|
|
0:Exit(0);
|
|
KERN_PROTECTION_FAILURE:Result:=SIGBUS;
|
|
else
|
|
Result:=SIGSEGV;
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
Writeln('not is_guest_addr:0x',HexStr(eva,16),':',curkthread^.td_name);
|
|
Result:=SIGSEGV;
|
|
end;
|
|
|
|
if (not usermode) then
|
|
begin
|
|
if (td^.pcb_onfault<>nil) then
|
|
begin
|
|
Writeln('pcb_onfault<:',HexStr(td^.pcb_onfault),':',curkthread^.td_name);
|
|
frame^.tf_rip:=QWORD(td^.pcb_onfault);
|
|
Exit(0);
|
|
end else
|
|
begin
|
|
trap_fatal(frame, eva, usermode);
|
|
Exit(-1);
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|
|
|