mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
05a0501214
commit
adc947a3b8
|
@ -75,6 +75,11 @@ uses
|
|||
errno,
|
||||
thr_init;
|
||||
|
||||
function TID(thr:p_pthread):Integer; inline;
|
||||
begin
|
||||
Result:=thr^.tid;
|
||||
end;
|
||||
|
||||
function atomic_cmpset_acq_32(p:PDWORD;cmpval,newval:DWORD):DWORD; inline;
|
||||
begin
|
||||
Result:=System.InterlockedCompareExchange(p^,newval,cmpval);
|
||||
|
|
|
@ -122,7 +122,6 @@ uses
|
|||
vstat,
|
||||
vfs_subr,
|
||||
subr_uio,
|
||||
kern_time,
|
||||
kern_thr;
|
||||
|
||||
const
|
||||
|
|
|
@ -10,8 +10,7 @@ uses
|
|||
time,
|
||||
signal,
|
||||
signalvar,
|
||||
kern_thr,
|
||||
rtprio;
|
||||
kern_thr;
|
||||
|
||||
const
|
||||
SA_KILL =$01; // terminates process by default
|
||||
|
@ -113,8 +112,7 @@ uses
|
|||
kern_exit,
|
||||
kern_prot,
|
||||
kern_synch,
|
||||
vm_machdep,
|
||||
md_thread,
|
||||
md_context,
|
||||
md_proc,
|
||||
machdep,
|
||||
sched_ule,
|
||||
|
|
|
@ -56,7 +56,7 @@ implementation
|
|||
uses
|
||||
kern_thread,
|
||||
sched_ule,
|
||||
vm_machdep,
|
||||
md_sleep,
|
||||
rtprio;
|
||||
|
||||
function msleep(ident :Pointer;
|
||||
|
|
|
@ -84,7 +84,8 @@ implementation
|
|||
uses
|
||||
errno,
|
||||
systm,
|
||||
vm_machdep,
|
||||
md_sleep,
|
||||
md_context,
|
||||
machdep,
|
||||
md_proc,
|
||||
md_thread,
|
||||
|
|
|
@ -89,9 +89,8 @@ uses
|
|||
HAMT,
|
||||
errno,
|
||||
systm,
|
||||
trap,
|
||||
md_time,
|
||||
vm_machdep,
|
||||
md_sleep,
|
||||
kern_thread,
|
||||
sched_ule;
|
||||
|
||||
|
@ -1548,6 +1547,7 @@ begin
|
|||
end else
|
||||
begin
|
||||
ets:=TIMESPEC_TO_UNIT(timeout);
|
||||
tts:=ets;
|
||||
|
||||
cts:=0;
|
||||
Result:=kern_clock_gettime_unit(clockid,@cts);
|
||||
|
|
|
@ -38,7 +38,8 @@ uses
|
|||
systm,
|
||||
md_psl,
|
||||
kern_sig,
|
||||
trap;
|
||||
trap,
|
||||
md_context;
|
||||
|
||||
//clearing memory without AVX optimizations
|
||||
procedure bzero(ptr:Pointer;size:ptrint);
|
||||
|
@ -207,15 +208,14 @@ begin
|
|||
//xmm,ymm
|
||||
if ((tp^.tf_flags and TF_HASFPXSTATE)<>0) then
|
||||
begin
|
||||
get_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
||||
Result:=get_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
||||
end else
|
||||
begin
|
||||
//get md
|
||||
Result:=md_get_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
||||
end;
|
||||
if (Result<>0) then Exit;
|
||||
//xmm,ymm
|
||||
|
||||
mcp^.mc_fpformat:=_MC_FPFMT_XMM;
|
||||
|
||||
mcp^.mc_fsbase:=ptruint(td^.pcb_fsbase);
|
||||
mcp^.mc_gsbase:=ptruint(td^.pcb_gsbase);
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
unit md_sleep;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ntapi,
|
||||
windows,
|
||||
kern_thr;
|
||||
|
||||
function _umtxq_alloc:THandle;
|
||||
procedure _umtxq_free(h:THandle);
|
||||
function msleep_umtxq(h:THandle;timo:Int64):Integer; inline;
|
||||
function wakeup_umtxq(h:THandle):Integer; inline;
|
||||
|
||||
function msleep_td(timo:Int64):Integer; inline;
|
||||
function wakeup_td(td:p_kthread):Integer; inline;
|
||||
procedure md_yield; inline;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
errno,
|
||||
trap;
|
||||
|
||||
function ntw2px(n:Integer):Integer; inline;
|
||||
begin
|
||||
Case DWORD(n) of
|
||||
STATUS_SUCCESS :Result:=0;
|
||||
STATUS_ABANDONED :Result:=EPERM;
|
||||
STATUS_ALERTED :Result:=EINTR;
|
||||
STATUS_USER_APC :Result:=EINTR;
|
||||
STATUS_TIMEOUT :Result:=ETIMEDOUT;
|
||||
STATUS_ACCESS_VIOLATION:Result:=EFAULT;
|
||||
else
|
||||
Result:=EINVAL;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ntd2px(n:Integer):Integer; inline;
|
||||
begin
|
||||
Case DWORD(n) of
|
||||
STATUS_SUCCESS :Result:=ETIMEDOUT;
|
||||
STATUS_ABANDONED :Result:=EPERM;
|
||||
STATUS_ALERTED :Result:=EINTR;
|
||||
STATUS_USER_APC :Result:=EINTR;
|
||||
STATUS_ACCESS_VIOLATION:Result:=EFAULT;
|
||||
else
|
||||
Result:=EINVAL;
|
||||
end;
|
||||
end;
|
||||
|
||||
function _umtxq_alloc:THandle;
|
||||
var
|
||||
n:Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
n:=NtCreateEvent(@Result,EVENT_ALL_ACCESS,nil,SynchronizationEvent,False);
|
||||
Assert(n=0);
|
||||
end;
|
||||
|
||||
procedure _umtxq_free(h:THandle);
|
||||
begin
|
||||
NtClose(h);
|
||||
end;
|
||||
|
||||
function msleep_umtxq(h:THandle;timo:Int64):Integer; inline;
|
||||
begin
|
||||
if (timo=0) then
|
||||
begin
|
||||
timo:=NT_INFINITE;
|
||||
end else
|
||||
begin
|
||||
timo:=-timo;
|
||||
end;
|
||||
sig_sta;
|
||||
Result:=ntw2px(NtWaitForSingleObject(h,True,@timo));
|
||||
sig_cla;
|
||||
end;
|
||||
|
||||
function wakeup_umtxq(h:THandle):Integer; inline;
|
||||
begin
|
||||
Result:=ntw2px(NtSetEvent(h,nil));
|
||||
end;
|
||||
|
||||
function msleep_td(timo:Int64):Integer; inline;
|
||||
begin
|
||||
if (timo=0) then
|
||||
begin
|
||||
timo:=NT_INFINITE;
|
||||
end else
|
||||
begin
|
||||
timo:=-timo;
|
||||
end;
|
||||
sig_sta;
|
||||
Result:=ntd2px(NtDelayExecution(True,@timo));
|
||||
sig_cla;
|
||||
end;
|
||||
|
||||
procedure _apc_null(dwParam:PTRUINT); stdcall;
|
||||
begin
|
||||
end;
|
||||
|
||||
function wakeup_td(td:p_kthread):Integer; inline;
|
||||
begin
|
||||
Result:=ntw2px(NtQueueApcThread(td^.td_handle,@_apc_null,nil,nil,0));
|
||||
end;
|
||||
|
||||
procedure md_yield; inline;
|
||||
begin
|
||||
NtYieldExecution;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ function setrunnable(td:p_kthread):Integer;
|
|||
implementation
|
||||
|
||||
uses
|
||||
vm_machdep,
|
||||
md_sleep,
|
||||
md_thread;
|
||||
|
||||
procedure sched_fork_thread(td,childtd:p_kthread);
|
||||
|
|
|
@ -117,7 +117,7 @@ implementation
|
|||
uses
|
||||
errno,
|
||||
machdep,
|
||||
vm_machdep,
|
||||
md_context,
|
||||
kern_sig,
|
||||
sysent;
|
||||
|
||||
|
|
|
@ -1,394 +0,0 @@
|
|||
unit vm_machdep;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ntapi,
|
||||
windows,
|
||||
md_psl,
|
||||
ucontext,
|
||||
trap,
|
||||
kern_thr;
|
||||
|
||||
procedure ipi_sigreturn;
|
||||
function ipi_send_cpu(td:p_kthread):Integer;
|
||||
|
||||
function _umtxq_alloc:THandle;
|
||||
procedure _umtxq_free(h:THandle);
|
||||
function msleep_umtxq(h:THandle;timo:Int64):Integer; inline;
|
||||
function wakeup_umtxq(h:THandle):Integer; inline;
|
||||
|
||||
function msleep_td(timo:Int64):Integer; inline;
|
||||
function wakeup_td(td:p_kthread):Integer; inline;
|
||||
procedure md_yield; inline;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
errno,
|
||||
systm,
|
||||
machdep,
|
||||
md_context,
|
||||
signal,
|
||||
kern_sig,
|
||||
md_thread;
|
||||
|
||||
function ntw2px(n:Integer):Integer; inline;
|
||||
begin
|
||||
Case DWORD(n) of
|
||||
STATUS_SUCCESS :Result:=0;
|
||||
STATUS_ABANDONED :Result:=EPERM;
|
||||
STATUS_ALERTED :Result:=EINTR;
|
||||
STATUS_USER_APC :Result:=EINTR;
|
||||
STATUS_TIMEOUT :Result:=ETIMEDOUT;
|
||||
STATUS_ACCESS_VIOLATION:Result:=EFAULT;
|
||||
else
|
||||
Result:=EINVAL;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ntd2px(n:Integer):Integer; inline;
|
||||
begin
|
||||
Case DWORD(n) of
|
||||
STATUS_SUCCESS :Result:=ETIMEDOUT;
|
||||
STATUS_ABANDONED :Result:=EPERM;
|
||||
STATUS_ALERTED :Result:=EINTR;
|
||||
STATUS_USER_APC :Result:=EINTR;
|
||||
STATUS_ACCESS_VIOLATION:Result:=EFAULT;
|
||||
else
|
||||
Result:=EINVAL;
|
||||
end;
|
||||
end;
|
||||
|
||||
function _umtxq_alloc:THandle;
|
||||
var
|
||||
n:Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
n:=NtCreateEvent(@Result,EVENT_ALL_ACCESS,nil,SynchronizationEvent,False);
|
||||
Assert(n=0);
|
||||
end;
|
||||
|
||||
procedure _umtxq_free(h:THandle);
|
||||
begin
|
||||
NtClose(h);
|
||||
end;
|
||||
|
||||
function msleep_umtxq(h:THandle;timo:Int64):Integer; inline;
|
||||
begin
|
||||
if (timo=0) then
|
||||
begin
|
||||
timo:=NT_INFINITE;
|
||||
end else
|
||||
begin
|
||||
timo:=-timo;
|
||||
end;
|
||||
sig_sta;
|
||||
Result:=ntw2px(NtWaitForSingleObject(h,True,@timo));
|
||||
sig_cla;
|
||||
end;
|
||||
|
||||
function wakeup_umtxq(h:THandle):Integer; inline;
|
||||
begin
|
||||
Result:=ntw2px(NtSetEvent(h,nil));
|
||||
end;
|
||||
|
||||
function msleep_td(timo:Int64):Integer; inline;
|
||||
begin
|
||||
if (timo=0) then
|
||||
begin
|
||||
timo:=NT_INFINITE;
|
||||
end else
|
||||
begin
|
||||
timo:=-timo;
|
||||
end;
|
||||
sig_sta;
|
||||
Result:=ntd2px(NtDelayExecution(True,@timo));
|
||||
sig_cla;
|
||||
end;
|
||||
|
||||
procedure _apc_null(dwParam:PTRUINT); stdcall;
|
||||
begin
|
||||
end;
|
||||
|
||||
function wakeup_td(td:p_kthread):Integer; inline;
|
||||
begin
|
||||
Result:=ntw2px(NtQueueApcThread(td^.td_handle,@_apc_null,nil,nil,0));
|
||||
end;
|
||||
|
||||
procedure md_yield; inline;
|
||||
begin
|
||||
NtYieldExecution;
|
||||
end;
|
||||
|
||||
function cpu_get_iflag(td:p_kthread):PInteger; inline;
|
||||
begin
|
||||
Result:=@td^.td_teb^.iflag;
|
||||
end;
|
||||
|
||||
function IS_SYSTEM_STACK(td:p_kthread;rsp:qword):Boolean; inline;
|
||||
begin
|
||||
Result:=(rsp<=QWORD(td^.td_kstack)) and (rsp>(QWORD(td^.td_kstack)-SYS_STACK_SIZE));
|
||||
end;
|
||||
|
||||
function IS_SYSCALL(rip:qword):Boolean;
|
||||
var
|
||||
w:Word;
|
||||
begin
|
||||
Result:=False;
|
||||
if (rip<>0) then
|
||||
begin
|
||||
w:=0;
|
||||
NtReadVirtualMemory(NtCurrentProcess,@PWord(Rip)[-1],@w,SizeOf(Word),nil);
|
||||
Result:=(w=$050F);
|
||||
end;
|
||||
end;
|
||||
|
||||
function get_top_mem_td(td:p_kthread;size,align:qword):Pointer;
|
||||
begin
|
||||
Result:=System.Align(td^.td_ksttop,align);
|
||||
if ((Result+size)>=SPtr) then Exit(nil);
|
||||
end;
|
||||
|
||||
procedure ipi_sigreturn;
|
||||
var
|
||||
td:p_kthread;
|
||||
Context:PCONTEXT;
|
||||
regs:p_trapframe;
|
||||
begin
|
||||
td:=curkthread;
|
||||
regs:=td^.td_frame;
|
||||
|
||||
if ((regs^.tf_flags and TF_HASFPXSTATE)<>0) then
|
||||
begin
|
||||
//xmm,ymm
|
||||
Context:=get_top_mem_td(td,GetContextSize(CONTEXT_ALLX),16);
|
||||
Assert(Context<>nil);
|
||||
Context:=InitializeContextExtended(Context,CONTEXT_ALLX);
|
||||
end else
|
||||
begin
|
||||
//simple
|
||||
Context:=get_top_mem_td(td,SizeOf(TCONTEXT),16);
|
||||
Assert(Context<>nil);
|
||||
Context^:=Default(TCONTEXT);
|
||||
Context^.ContextFlags:=CONTEXT_INTEGER or CONTEXT_CONTROL;
|
||||
end;
|
||||
|
||||
Context^.Rdi:=regs^.tf_rdi;
|
||||
Context^.Rsi:=regs^.tf_rsi;
|
||||
Context^.Rdx:=regs^.tf_rdx;
|
||||
Context^.Rcx:=regs^.tf_rcx;
|
||||
Context^.R8 :=regs^.tf_r8 ;
|
||||
Context^.R9 :=regs^.tf_r9 ;
|
||||
Context^.Rax:=regs^.tf_rax;
|
||||
Context^.Rbx:=regs^.tf_rbx;
|
||||
Context^.Rbp:=regs^.tf_rbp;
|
||||
Context^.R10:=regs^.tf_r10;
|
||||
Context^.R11:=regs^.tf_r11;
|
||||
Context^.R12:=regs^.tf_r12;
|
||||
Context^.R13:=regs^.tf_r13;
|
||||
Context^.R14:=regs^.tf_r14;
|
||||
Context^.R15:=regs^.tf_r15;
|
||||
|
||||
Context^.Rip :=regs^.tf_rip;
|
||||
Context^.EFlags:=regs^.tf_rflags;
|
||||
Context^.Rsp :=regs^.tf_rsp;
|
||||
|
||||
Context^.SegGs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegEs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegDs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegCs:=KGDT64_R3_CODE or RPL_MASK;
|
||||
Context^.SegSs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegFs:=KGDT64_R3_CMTEB or RPL_MASK;
|
||||
|
||||
//xmm,ymm
|
||||
if ((regs^.tf_flags and TF_HASFPXSTATE)<>0) then
|
||||
begin
|
||||
_set_fpcontext(Context,@td^.td_fpstate);
|
||||
|
||||
regs^.tf_flags:=regs^.tf_flags and (not TF_HASFPXSTATE);
|
||||
end;
|
||||
//xmm,ymm
|
||||
|
||||
NtContinue(Context,False);
|
||||
end;
|
||||
|
||||
function ipi_send_cpu(td:p_kthread):Integer;
|
||||
label
|
||||
resume,
|
||||
tryagain;
|
||||
var
|
||||
td_handle:THandle;
|
||||
iflag :PInteger;
|
||||
Context :PCONTEXT;
|
||||
w:LARGE_INTEGER;
|
||||
sf:sigframe;
|
||||
sfp:p_sigframe;
|
||||
regs:p_trapframe;
|
||||
sp:QWORD;
|
||||
oonstack:Integer;
|
||||
begin
|
||||
Result :=0;
|
||||
td_handle:=td^.td_handle;
|
||||
iflag :=cpu_get_iflag(td);
|
||||
|
||||
PROC_LOCK;
|
||||
|
||||
tryagain:
|
||||
|
||||
if (NtSuspendThread(td_handle,nil)<>STATUS_SUCCESS) then
|
||||
begin
|
||||
PROC_UNLOCK;
|
||||
Exit(ESRCH);
|
||||
end;
|
||||
|
||||
w.QuadPart:=0;
|
||||
if (NtWaitForSingleObject(td_handle,False,@w)<>STATUS_TIMEOUT) then
|
||||
begin
|
||||
Result:=ESRCH;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
if ((iflag^ and SIG_ALTERABLE)<>0) then //alterable?
|
||||
begin
|
||||
NtQueueApcThread(td_handle,@_apc_null,nil,nil,0);
|
||||
Result:=0;
|
||||
goto resume;
|
||||
end else
|
||||
if (iflag^<>0) then //locked?
|
||||
begin
|
||||
Result:=0;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
Context:=get_top_mem_td(td,GetContextSize(CONTEXT_ALLX),16);
|
||||
Assert(Context<>nil);
|
||||
Context:=InitializeContextExtended(Context,CONTEXT_ALLX);
|
||||
|
||||
if (NtGetContextThread(td_handle,Context)<>STATUS_SUCCESS) then
|
||||
begin
|
||||
Result:=ESRCH;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
if IS_SYSTEM_STACK(td,Context^.Rsp) then //system?
|
||||
begin
|
||||
Result:=0;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
if IS_SYSCALL(Context^.Rip) then //system call in code without blocking
|
||||
begin
|
||||
NtResumeThread(td_handle,nil);
|
||||
w.QuadPart:=-10000;
|
||||
NtDelayExecution(False,@w); //100ms
|
||||
goto tryagain;
|
||||
end;
|
||||
|
||||
regs:=td^.td_frame;
|
||||
oonstack:=sigonstack(Context^.Rsp);
|
||||
|
||||
// Save user context.
|
||||
sf:=Default(sigframe);
|
||||
|
||||
sf.sf_uc.uc_sigmask:=td^.td_sigmask;
|
||||
sf.sf_uc.uc_stack :=td^.td_sigstk;
|
||||
|
||||
if ((td^.td_pflags and TDP_ALTSTACK)<>0) then
|
||||
begin
|
||||
if (oonstack<>0) then
|
||||
begin
|
||||
sf.sf_uc.uc_stack.ss_flags:=SS_ONSTACK;
|
||||
end else
|
||||
begin
|
||||
sf.sf_uc.uc_stack.ss_flags:=0;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
sf.sf_uc.uc_stack.ss_flags:=SS_DISABLE;
|
||||
end;
|
||||
|
||||
//copy frame
|
||||
regs^.tf_rdi:=Context^.Rdi;
|
||||
regs^.tf_rsi:=Context^.Rsi;
|
||||
regs^.tf_rdx:=Context^.Rdx;
|
||||
regs^.tf_rcx:=Context^.Rcx;
|
||||
regs^.tf_r8 :=Context^.R8 ;
|
||||
regs^.tf_r9 :=Context^.R9 ;
|
||||
regs^.tf_rax:=Context^.Rax;
|
||||
regs^.tf_rbx:=Context^.Rbx;
|
||||
regs^.tf_rbp:=Context^.Rbp;
|
||||
regs^.tf_r10:=Context^.R10;
|
||||
regs^.tf_r11:=Context^.R11;
|
||||
regs^.tf_r12:=Context^.R12;
|
||||
regs^.tf_r13:=Context^.R13;
|
||||
regs^.tf_r14:=Context^.R14;
|
||||
regs^.tf_r15:=Context^.R15;
|
||||
|
||||
regs^.tf_rip :=Context^.Rip;
|
||||
regs^.tf_rflags:=Context^.EFlags;
|
||||
regs^.tf_rsp :=Context^.Rsp;
|
||||
|
||||
regs^.tf_cs:=_ucodesel;
|
||||
regs^.tf_ds:=_udatasel;
|
||||
regs^.tf_ss:=_udatasel;
|
||||
regs^.tf_es:=_udatasel;
|
||||
regs^.tf_fs:=_ufssel;
|
||||
regs^.tf_gs:=_ugssel;
|
||||
regs^.tf_flags:=TF_HASSEGS;
|
||||
//copy frame
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_onstack:=oonstack;
|
||||
|
||||
Move(regs^,sf.sf_uc.uc_mcontext.mc_rdi,SizeOf(trapframe));
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_len:=sizeof(mcontext_t);
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_fsbase:=QWORD(td^.pcb_fsbase);
|
||||
sf.sf_uc.uc_mcontext.mc_gsbase:=QWORD(td^.pcb_gsbase);
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_flags:=_MC_HASSEGS or _MC_HASBASES or _MC_HASFPXSTATE;
|
||||
|
||||
//xmm,ymm
|
||||
_get_fpcontext(Context,@sf.sf_uc.uc_mcontext.mc_fpstate);
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_fpformat:=_MC_FPFMT_XMM;
|
||||
sf.sf_uc.uc_mcontext.mc_ownedfp :=_MC_FPOWNED_FPU;
|
||||
//xmm,ymm
|
||||
|
||||
sp:=QWORD(td^.td_kstack);
|
||||
|
||||
sp:=sp-sizeof(sigframe);
|
||||
|
||||
sfp:=p_sigframe(sp and (not $1F));
|
||||
|
||||
if (copyout(@sf,sfp,sizeof(sigframe))<>0) then
|
||||
begin
|
||||
Result:=EFAULT;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
Context^.Rsp:=QWORD(sfp);
|
||||
Context^.Rip:=QWORD(@sigipi);
|
||||
Context^.EFlags:=Context^.EFlags and (not (PSL_T or PSL_D));
|
||||
|
||||
set_pcb_flags(td,PCB_FULL_IRET);
|
||||
|
||||
if (NtSetContextThread(td_handle,Context)<>STATUS_SUCCESS) then
|
||||
begin
|
||||
Result:=ESRCH;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
resume:
|
||||
NtResumeThread(td_handle,nil);
|
||||
PROC_UNLOCK;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
|
@ -7,9 +7,8 @@ interface
|
|||
uses
|
||||
Windows,
|
||||
ntapi,
|
||||
signal,
|
||||
ucontext,
|
||||
machdep;
|
||||
kern_thr;
|
||||
|
||||
const
|
||||
XSTATE_LEGACY_FLOATING_POINT=0;
|
||||
|
@ -81,8 +80,28 @@ procedure _set_fpcontext(dst:PCONTEXT;xstate:Pointer);
|
|||
procedure _get_ucontext(src:PCONTEXT;dst:p_ucontext_t);
|
||||
procedure _set_ucontext(dst:PCONTEXT;src:p_ucontext_t);
|
||||
|
||||
function md_get_fpcontext(td:p_kthread;mcp:p_mcontext_t;xstate:Pointer):Integer;
|
||||
|
||||
procedure ipi_sigreturn;
|
||||
function ipi_send_cpu(td:p_kthread):Integer;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
errno,
|
||||
systm,
|
||||
trap,
|
||||
md_psl,
|
||||
signal,
|
||||
kern_sig,
|
||||
md_thread;
|
||||
|
||||
const
|
||||
_ucodesel=(8 shl 3) or 3;
|
||||
_udatasel=(7 shl 3) or 3;
|
||||
_ufssel =(2 shl 3) or 3;
|
||||
_ugssel =(3 shl 3) or 3;
|
||||
|
||||
function GetEnabledXStateFeatures:QWORD; stdcall external 'kernel32';
|
||||
|
||||
function InitializeContext(
|
||||
|
@ -316,5 +335,298 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
function cpu_get_iflag(td:p_kthread):PInteger; inline;
|
||||
begin
|
||||
Result:=@td^.td_teb^.iflag;
|
||||
end;
|
||||
|
||||
function IS_SYSTEM_STACK(td:p_kthread;rsp:qword):Boolean; inline;
|
||||
begin
|
||||
Result:=(rsp<=QWORD(td^.td_kstack)) and (rsp>(QWORD(td^.td_kstack)-SYS_STACK_SIZE));
|
||||
end;
|
||||
|
||||
function IS_SYSCALL(rip:qword):Boolean;
|
||||
var
|
||||
w:Word;
|
||||
begin
|
||||
Result:=False;
|
||||
if (rip<>0) then
|
||||
begin
|
||||
w:=0;
|
||||
NtReadVirtualMemory(NtCurrentProcess,@PWord(Rip)[-1],@w,SizeOf(Word),nil);
|
||||
Result:=(w=$050F);
|
||||
end;
|
||||
end;
|
||||
|
||||
function get_top_mem_td(td:p_kthread;size,align:qword):Pointer;
|
||||
begin
|
||||
Result:=System.Align(td^.td_ksttop,align);
|
||||
if ((Result+size)>=SPtr) then Exit(nil);
|
||||
end;
|
||||
|
||||
procedure _apc_null(dwParam:PTRUINT); stdcall;
|
||||
begin
|
||||
end;
|
||||
|
||||
function md_get_fpcontext(td:p_kthread;mcp:p_mcontext_t;xstate:Pointer):Integer;
|
||||
var
|
||||
td_handle:THandle;
|
||||
Context :PCONTEXT;
|
||||
begin
|
||||
Result :=0;
|
||||
td_handle:=td^.td_handle;
|
||||
|
||||
Context:=get_top_mem_td(td,GetContextSize(CONTEXT_XSTATE),16);
|
||||
Assert(Context<>nil);
|
||||
Context:=InitializeContextExtended(Context,CONTEXT_XSTATE);
|
||||
|
||||
if (NtGetContextThread(td_handle,Context)<>STATUS_SUCCESS) then
|
||||
begin
|
||||
Exit(ESRCH)
|
||||
end;
|
||||
|
||||
//xmm,ymm
|
||||
_get_fpcontext(Context,xstate);
|
||||
|
||||
mcp^.mc_fpformat:=_MC_FPFMT_XMM;
|
||||
mcp^.mc_ownedfp :=_MC_FPOWNED_FPU;
|
||||
//xmm,ymm
|
||||
end;
|
||||
|
||||
procedure ipi_sigreturn;
|
||||
var
|
||||
td:p_kthread;
|
||||
Context:PCONTEXT;
|
||||
regs:p_trapframe;
|
||||
begin
|
||||
td:=curkthread;
|
||||
regs:=td^.td_frame;
|
||||
|
||||
if ((regs^.tf_flags and TF_HASFPXSTATE)<>0) then
|
||||
begin
|
||||
//xmm,ymm
|
||||
Context:=get_top_mem_td(td,GetContextSize(CONTEXT_ALLX),16);
|
||||
Assert(Context<>nil);
|
||||
Context:=InitializeContextExtended(Context,CONTEXT_ALLX);
|
||||
end else
|
||||
begin
|
||||
//simple
|
||||
Context:=get_top_mem_td(td,SizeOf(TCONTEXT),16);
|
||||
Assert(Context<>nil);
|
||||
Context^:=Default(TCONTEXT);
|
||||
Context^.ContextFlags:=CONTEXT_INTEGER or CONTEXT_CONTROL;
|
||||
end;
|
||||
|
||||
Context^.Rdi:=regs^.tf_rdi;
|
||||
Context^.Rsi:=regs^.tf_rsi;
|
||||
Context^.Rdx:=regs^.tf_rdx;
|
||||
Context^.Rcx:=regs^.tf_rcx;
|
||||
Context^.R8 :=regs^.tf_r8 ;
|
||||
Context^.R9 :=regs^.tf_r9 ;
|
||||
Context^.Rax:=regs^.tf_rax;
|
||||
Context^.Rbx:=regs^.tf_rbx;
|
||||
Context^.Rbp:=regs^.tf_rbp;
|
||||
Context^.R10:=regs^.tf_r10;
|
||||
Context^.R11:=regs^.tf_r11;
|
||||
Context^.R12:=regs^.tf_r12;
|
||||
Context^.R13:=regs^.tf_r13;
|
||||
Context^.R14:=regs^.tf_r14;
|
||||
Context^.R15:=regs^.tf_r15;
|
||||
|
||||
Context^.Rip :=regs^.tf_rip;
|
||||
Context^.EFlags:=regs^.tf_rflags;
|
||||
Context^.Rsp :=regs^.tf_rsp;
|
||||
|
||||
Context^.SegGs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegEs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegDs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegCs:=KGDT64_R3_CODE or RPL_MASK;
|
||||
Context^.SegSs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegFs:=KGDT64_R3_CMTEB or RPL_MASK;
|
||||
|
||||
//xmm,ymm
|
||||
if ((regs^.tf_flags and TF_HASFPXSTATE)<>0) then
|
||||
begin
|
||||
_set_fpcontext(Context,@td^.td_fpstate);
|
||||
|
||||
regs^.tf_flags:=regs^.tf_flags and (not TF_HASFPXSTATE);
|
||||
end;
|
||||
//xmm,ymm
|
||||
|
||||
NtContinue(Context,False);
|
||||
end;
|
||||
|
||||
function ipi_send_cpu(td:p_kthread):Integer;
|
||||
label
|
||||
resume,
|
||||
tryagain;
|
||||
var
|
||||
td_handle:THandle;
|
||||
iflag :PInteger;
|
||||
Context :PCONTEXT;
|
||||
w:LARGE_INTEGER;
|
||||
sf:sigframe;
|
||||
sfp:p_sigframe;
|
||||
regs:p_trapframe;
|
||||
sp:QWORD;
|
||||
oonstack:Integer;
|
||||
begin
|
||||
Result :=0;
|
||||
td_handle:=td^.td_handle;
|
||||
iflag :=cpu_get_iflag(td);
|
||||
|
||||
PROC_LOCK;
|
||||
|
||||
tryagain:
|
||||
|
||||
if (NtSuspendThread(td_handle,nil)<>STATUS_SUCCESS) then
|
||||
begin
|
||||
PROC_UNLOCK;
|
||||
Exit(ESRCH);
|
||||
end;
|
||||
|
||||
w.QuadPart:=0;
|
||||
if (NtWaitForSingleObject(td_handle,False,@w)<>STATUS_TIMEOUT) then
|
||||
begin
|
||||
Result:=ESRCH;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
if ((iflag^ and SIG_ALTERABLE)<>0) then //alterable?
|
||||
begin
|
||||
NtQueueApcThread(td_handle,@_apc_null,nil,nil,0);
|
||||
Result:=0;
|
||||
goto resume;
|
||||
end else
|
||||
if (iflag^<>0) then //locked?
|
||||
begin
|
||||
Result:=0;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
Context:=get_top_mem_td(td,GetContextSize(CONTEXT_ALLX),16);
|
||||
Assert(Context<>nil);
|
||||
Context:=InitializeContextExtended(Context,CONTEXT_ALLX);
|
||||
|
||||
if (NtGetContextThread(td_handle,Context)<>STATUS_SUCCESS) then
|
||||
begin
|
||||
Result:=ESRCH;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
if IS_SYSTEM_STACK(td,Context^.Rsp) then //system?
|
||||
begin
|
||||
Result:=0;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
if IS_SYSCALL(Context^.Rip) then //system call in code without blocking
|
||||
begin
|
||||
NtResumeThread(td_handle,nil);
|
||||
w.QuadPart:=-10000;
|
||||
NtDelayExecution(False,@w); //100ms
|
||||
goto tryagain;
|
||||
end;
|
||||
|
||||
regs:=td^.td_frame;
|
||||
oonstack:=sigonstack(Context^.Rsp);
|
||||
|
||||
// Save user context.
|
||||
sf:=Default(sigframe);
|
||||
|
||||
sf.sf_uc.uc_sigmask:=td^.td_sigmask;
|
||||
sf.sf_uc.uc_stack :=td^.td_sigstk;
|
||||
|
||||
if ((td^.td_pflags and TDP_ALTSTACK)<>0) then
|
||||
begin
|
||||
if (oonstack<>0) then
|
||||
begin
|
||||
sf.sf_uc.uc_stack.ss_flags:=SS_ONSTACK;
|
||||
end else
|
||||
begin
|
||||
sf.sf_uc.uc_stack.ss_flags:=0;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
sf.sf_uc.uc_stack.ss_flags:=SS_DISABLE;
|
||||
end;
|
||||
|
||||
//copy frame
|
||||
regs^.tf_rdi:=Context^.Rdi;
|
||||
regs^.tf_rsi:=Context^.Rsi;
|
||||
regs^.tf_rdx:=Context^.Rdx;
|
||||
regs^.tf_rcx:=Context^.Rcx;
|
||||
regs^.tf_r8 :=Context^.R8 ;
|
||||
regs^.tf_r9 :=Context^.R9 ;
|
||||
regs^.tf_rax:=Context^.Rax;
|
||||
regs^.tf_rbx:=Context^.Rbx;
|
||||
regs^.tf_rbp:=Context^.Rbp;
|
||||
regs^.tf_r10:=Context^.R10;
|
||||
regs^.tf_r11:=Context^.R11;
|
||||
regs^.tf_r12:=Context^.R12;
|
||||
regs^.tf_r13:=Context^.R13;
|
||||
regs^.tf_r14:=Context^.R14;
|
||||
regs^.tf_r15:=Context^.R15;
|
||||
|
||||
regs^.tf_rip :=Context^.Rip;
|
||||
regs^.tf_rflags:=Context^.EFlags;
|
||||
regs^.tf_rsp :=Context^.Rsp;
|
||||
|
||||
regs^.tf_cs:=_ucodesel;
|
||||
regs^.tf_ds:=_udatasel;
|
||||
regs^.tf_ss:=_udatasel;
|
||||
regs^.tf_es:=_udatasel;
|
||||
regs^.tf_fs:=_ufssel;
|
||||
regs^.tf_gs:=_ugssel;
|
||||
regs^.tf_flags:=TF_HASSEGS;
|
||||
//copy frame
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_onstack:=oonstack;
|
||||
|
||||
Move(regs^,sf.sf_uc.uc_mcontext.mc_rdi,SizeOf(trapframe));
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_len:=sizeof(mcontext_t);
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_fsbase:=QWORD(td^.pcb_fsbase);
|
||||
sf.sf_uc.uc_mcontext.mc_gsbase:=QWORD(td^.pcb_gsbase);
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_flags:=_MC_HASSEGS or _MC_HASBASES or _MC_HASFPXSTATE;
|
||||
|
||||
//xmm,ymm
|
||||
_get_fpcontext(Context,@sf.sf_uc.uc_mcontext.mc_fpstate);
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_fpformat:=_MC_FPFMT_XMM;
|
||||
sf.sf_uc.uc_mcontext.mc_ownedfp :=_MC_FPOWNED_FPU;
|
||||
//xmm,ymm
|
||||
|
||||
sp:=QWORD(td^.td_kstack);
|
||||
|
||||
sp:=sp-sizeof(sigframe);
|
||||
|
||||
sfp:=p_sigframe(sp and (not $1F));
|
||||
|
||||
if (copyout(@sf,sfp,sizeof(sigframe))<>0) then
|
||||
begin
|
||||
Result:=EFAULT;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
Context^.Rsp:=QWORD(sfp);
|
||||
Context^.Rip:=QWORD(@sigipi);
|
||||
Context^.EFlags:=Context^.EFlags and (not (PSL_T or PSL_D));
|
||||
|
||||
set_pcb_flags(td,PCB_FULL_IRET);
|
||||
|
||||
if (NtSetContextThread(td_handle,Context)<>STATUS_SUCCESS) then
|
||||
begin
|
||||
Result:=ESRCH;
|
||||
goto resume;
|
||||
end;
|
||||
|
||||
resume:
|
||||
NtResumeThread(td_handle,nil);
|
||||
PROC_UNLOCK;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@ var
|
|||
iargs :t_i386_ioperm_args;
|
||||
begin
|
||||
Result:=0;
|
||||
i386base:=0;
|
||||
a64base :=0;
|
||||
|
||||
//read
|
||||
case op of
|
||||
|
|
|
@ -121,10 +121,6 @@
|
|||
<Filename Value="..\kern\trap.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\kern\vm_machdep.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\kern\kern_cpuset.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
|
@ -545,6 +541,10 @@
|
|||
<Filename Value="..\sys_machdep.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\kern\md_sleep.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
|
@ -80,7 +80,7 @@ uses
|
|||
md_proc,
|
||||
kern_ksched,
|
||||
kern_uuid,
|
||||
kern_gpo,
|
||||
kern_gpo, md_sleep,
|
||||
sys_machdep;
|
||||
|
||||
var
|
||||
|
|
|
@ -233,7 +233,7 @@ var
|
|||
nd:t_nameidata;
|
||||
mporoot,mpnroot:p_mount;
|
||||
vp,vporoot,vpdevfs:p_vnode;
|
||||
fspath:PChar;
|
||||
//fspath:PChar;
|
||||
error:Integer;
|
||||
begin
|
||||
mpnroot:=TAILQ_NEXT(mpdevfs,@mpdevfs^.mnt_list);
|
||||
|
|
Loading…
Reference in New Issue