From adc947a3b8d612caac4036a6ea5f0e65cc7abe1c Mon Sep 17 00:00:00 2001 From: Pavel <68122101+red-prig@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:25:54 +0300 Subject: [PATCH] + --- kernel/libthr/thr_umtx.pas | 5 + sys/fs/ufs/md_vnops.pas | 1 - sys/kern/kern_sig.pas | 6 +- sys/kern/kern_synch.pas | 2 +- sys/kern/kern_thread.pas | 3 +- sys/kern/kern_umtx.pas | 4 +- sys/kern/machdep.pas | 10 +- sys/kern/md_sleep.pas | 119 +++++++++++ sys/kern/sched_ule.pas | 2 +- sys/kern/trap.pas | 2 +- sys/kern/vm_machdep.pas | 394 ------------------------------------- sys/md_context.pas | 316 ++++++++++++++++++++++++++++- sys/sys_machdep.pas | 2 + sys/test/project1.lpi | 8 +- sys/test/project1.lpr | 2 +- sys/vfs/vfs_mountroot.pas | 2 +- 16 files changed, 460 insertions(+), 418 deletions(-) create mode 100644 sys/kern/md_sleep.pas delete mode 100644 sys/kern/vm_machdep.pas diff --git a/kernel/libthr/thr_umtx.pas b/kernel/libthr/thr_umtx.pas index b573b76f..31022933 100644 --- a/kernel/libthr/thr_umtx.pas +++ b/kernel/libthr/thr_umtx.pas @@ -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); diff --git a/sys/fs/ufs/md_vnops.pas b/sys/fs/ufs/md_vnops.pas index 4a202bc8..4764fe39 100644 --- a/sys/fs/ufs/md_vnops.pas +++ b/sys/fs/ufs/md_vnops.pas @@ -122,7 +122,6 @@ uses vstat, vfs_subr, subr_uio, - kern_time, kern_thr; const diff --git a/sys/kern/kern_sig.pas b/sys/kern/kern_sig.pas index 4cdfa573..08c79ee0 100644 --- a/sys/kern/kern_sig.pas +++ b/sys/kern/kern_sig.pas @@ -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, diff --git a/sys/kern/kern_synch.pas b/sys/kern/kern_synch.pas index f1b7895f..97b9e72f 100644 --- a/sys/kern/kern_synch.pas +++ b/sys/kern/kern_synch.pas @@ -56,7 +56,7 @@ implementation uses kern_thread, sched_ule, - vm_machdep, + md_sleep, rtprio; function msleep(ident :Pointer; diff --git a/sys/kern/kern_thread.pas b/sys/kern/kern_thread.pas index 862ed8c1..d1e93160 100644 --- a/sys/kern/kern_thread.pas +++ b/sys/kern/kern_thread.pas @@ -84,7 +84,8 @@ implementation uses errno, systm, - vm_machdep, + md_sleep, + md_context, machdep, md_proc, md_thread, diff --git a/sys/kern/kern_umtx.pas b/sys/kern/kern_umtx.pas index 43101c64..4081fef0 100644 --- a/sys/kern/kern_umtx.pas +++ b/sys/kern/kern_umtx.pas @@ -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); diff --git a/sys/kern/machdep.pas b/sys/kern/machdep.pas index 23e22605..e6f28707 100644 --- a/sys/kern/machdep.pas +++ b/sys/kern/machdep.pas @@ -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); diff --git a/sys/kern/md_sleep.pas b/sys/kern/md_sleep.pas new file mode 100644 index 00000000..a6ccfc93 --- /dev/null +++ b/sys/kern/md_sleep.pas @@ -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. + + + diff --git a/sys/kern/sched_ule.pas b/sys/kern/sched_ule.pas index 981c1a6b..8f1ea547 100644 --- a/sys/kern/sched_ule.pas +++ b/sys/kern/sched_ule.pas @@ -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); diff --git a/sys/kern/trap.pas b/sys/kern/trap.pas index 486d5834..b66deb4e 100644 --- a/sys/kern/trap.pas +++ b/sys/kern/trap.pas @@ -117,7 +117,7 @@ implementation uses errno, machdep, - vm_machdep, + md_context, kern_sig, sysent; diff --git a/sys/kern/vm_machdep.pas b/sys/kern/vm_machdep.pas deleted file mode 100644 index 2c09de1e..00000000 --- a/sys/kern/vm_machdep.pas +++ /dev/null @@ -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. - - - diff --git a/sys/md_context.pas b/sys/md_context.pas index 7f357569..2bff5408 100644 --- a/sys/md_context.pas +++ b/sys/md_context.pas @@ -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. diff --git a/sys/sys_machdep.pas b/sys/sys_machdep.pas index baa634cc..3e84e8bb 100644 --- a/sys/sys_machdep.pas +++ b/sys/sys_machdep.pas @@ -57,6 +57,8 @@ var iargs :t_i386_ioperm_args; begin Result:=0; + i386base:=0; + a64base :=0; //read case op of diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index 6215404c..285757cb 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -121,10 +121,6 @@ - - - - @@ -545,6 +541,10 @@ + + + + diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index e0fcf78e..f7aa8661 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -80,7 +80,7 @@ uses md_proc, kern_ksched, kern_uuid, - kern_gpo, + kern_gpo, md_sleep, sys_machdep; var diff --git a/sys/vfs/vfs_mountroot.pas b/sys/vfs/vfs_mountroot.pas index 13aac80c..01cbb140 100644 --- a/sys/vfs/vfs_mountroot.pas +++ b/sys/vfs/vfs_mountroot.pas @@ -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);