mirror of https://github.com/red-prig/fpPS4.git
628 lines
14 KiB
Plaintext
628 lines
14 KiB
Plaintext
unit machdep;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
uses
|
|
signal,
|
|
signalvar,
|
|
ucontext,
|
|
kern_thr,
|
|
kern_proc;
|
|
|
|
const
|
|
GUFS32_SEL = 2; // User 32 bit %fs Descriptor
|
|
GUGS32_SEL = 3; // User 32 bit %gs Descriptor
|
|
GUDATA_SEL = 7; // User 32/64 bit Data Descriptor
|
|
GUCODE_SEL = 8; // User 64 bit Code Descriptor
|
|
|
|
_ucodesel=(GUCODE_SEL shl 3) or 3;
|
|
_udatasel=(GUDATA_SEL shl 3) or 3;
|
|
_ufssel =(GUFS32_SEL shl 3) or 3;
|
|
_ugssel =(GUGS32_SEL shl 3) or 3;
|
|
|
|
procedure bzero(ptr:Pointer;size:ptrint);
|
|
Procedure bmove(src,dst:Pointer;size:ptrint);
|
|
|
|
function cpu_getstack(td:p_kthread):QWORD;
|
|
procedure cpu_set_fsbase(td:p_kthread;base:Pointer);
|
|
procedure cpu_set_gsbase(td:p_kthread;base:Pointer);
|
|
procedure cpu_init_jit(td:p_kthread);
|
|
procedure cpu_fini_jit(td:p_kthread);
|
|
procedure cpu_fetch_syscall_args(td:p_kthread);
|
|
procedure cpu_set_syscall_retval(td:p_kthread;error:Integer);
|
|
procedure cpu_set_upcall_kse(td:p_kthread;entry,arg:Pointer;stack:p_stack_t);
|
|
|
|
function get_mcontext(td:p_kthread;mcp:p_mcontext_t;flags:Integer):Integer;
|
|
function get_mcontext2(td:p_kthread;mcp:p_mcontext_t;flags:Integer):Integer;
|
|
function set_mcontext(td:p_kthread;mcp:p_mcontext_t):Integer;
|
|
|
|
procedure sendsig(catcher:sig_t;ksi:p_ksiginfo;mask:p_sigset_t);
|
|
|
|
//
|
|
|
|
function sys_sigreturn(sigcntxp:Pointer):Integer;
|
|
|
|
procedure exec_setregs(td:p_kthread;entry,stack_base,stack_top:QWORD);
|
|
|
|
implementation
|
|
|
|
uses
|
|
errno,
|
|
systm,
|
|
kern_psl,
|
|
vm_map,
|
|
md_context;
|
|
|
|
//clearing memory without AVX optimizations
|
|
procedure bzero(ptr:Pointer;size:ptrint);
|
|
begin
|
|
while (size>0) do
|
|
begin
|
|
PByte(ptr)^:=0;
|
|
Inc(ptr);
|
|
Dec(size);
|
|
end;
|
|
end;
|
|
|
|
//move memory without AVX optimizations
|
|
Procedure bmove(src,dst:Pointer;size:ptrint);
|
|
begin
|
|
while (size>0) do
|
|
begin
|
|
PByte(dst)^:=PByte(src)^;
|
|
Inc(src);
|
|
Inc(dst);
|
|
Dec(size);
|
|
end;
|
|
end;
|
|
|
|
function cpu_getstack(td:p_kthread):QWORD;
|
|
begin
|
|
Result:=td^.td_frame.tf_rsp;
|
|
end;
|
|
|
|
procedure cpu_set_fsbase(td:p_kthread;base:Pointer);
|
|
begin
|
|
td^.pcb_fsbase:=base;
|
|
td^.td_teb^.fsbase:=base;
|
|
set_pcb_flags(td,PCB_FULL_IRET);
|
|
end;
|
|
|
|
procedure cpu_set_gsbase(td:p_kthread;base:Pointer);
|
|
begin
|
|
td^.pcb_gsbase:=base;
|
|
td^.td_teb^.gsbase:=base;
|
|
set_pcb_flags(td,PCB_FULL_IRET);
|
|
end;
|
|
|
|
procedure cpu_init_jit(td:p_kthread);
|
|
begin
|
|
//teb stack
|
|
teb_set_kernel(td);
|
|
//teb stack
|
|
end;
|
|
|
|
procedure cpu_fini_jit(td:p_kthread);
|
|
begin
|
|
//teb stack
|
|
teb_set_user(td);
|
|
//teb stack
|
|
end;
|
|
|
|
procedure cpu_fetch_syscall_args(td:p_kthread);
|
|
begin
|
|
td^.td_retval[0]:=0;
|
|
td^.td_retval[1]:=td^.td_frame.tf_rdx;
|
|
|
|
//teb stack
|
|
teb_set_kernel(td);
|
|
//teb stack
|
|
end;
|
|
|
|
procedure cpu_set_syscall_retval(td:p_kthread;error:Integer);
|
|
begin
|
|
Case error of
|
|
0:With td^.td_frame do
|
|
begin
|
|
tf_rax:=td^.td_retval[0];
|
|
tf_rdx:=td^.td_retval[1];
|
|
tf_rflags:=tf_rflags and (not PSL_C);
|
|
end;
|
|
ERESTART:
|
|
With td^.td_frame do
|
|
begin
|
|
//tf_err = size of syscall cmd
|
|
tf_rip:=tf_rip-td^.td_frame.tf_err;
|
|
tf_r10:=tf_rcx;
|
|
set_pcb_flags(td,PCB_FULL_IRET);
|
|
end;
|
|
EJUSTRETURN:; //nothing
|
|
else
|
|
With td^.td_frame do
|
|
begin
|
|
tf_rax:=error;
|
|
tf_rflags:=tf_rflags or PSL_C;
|
|
end;
|
|
end;
|
|
|
|
//teb stack
|
|
teb_set_user(td);
|
|
//teb stack
|
|
end;
|
|
|
|
procedure cpu_set_upcall_kse(td:p_kthread;entry,arg:Pointer;stack:p_stack_t);
|
|
begin
|
|
{
|
|
* Set the trap frame to point at the beginning of the uts
|
|
* function.
|
|
}
|
|
td^.td_frame.tf_rbp:=0;
|
|
td^.td_frame.tf_rsp:=(ptruint(stack^.ss_sp) + stack^.ss_size) and (not $F);
|
|
Dec(td^.td_frame.tf_rsp,8);
|
|
td^.td_frame.tf_rip:=ptruint(entry);
|
|
td^.td_frame.tf_ds:=_udatasel;
|
|
td^.td_frame.tf_es:=_udatasel;
|
|
td^.td_frame.tf_fs:=_ufssel;
|
|
td^.td_frame.tf_gs:=_ugssel;
|
|
td^.td_frame.tf_flags:=TF_HASSEGS;
|
|
|
|
{
|
|
* Pass the address of the mailbox for this kse to the uts
|
|
* function as a parameter on the stack.
|
|
}
|
|
td^.td_frame.tf_rdi:=ptruint(arg);
|
|
end;
|
|
|
|
function get_fpcontext(td:p_kthread;mcp:p_mcontext_t;xstate:Pointer):Integer;
|
|
begin
|
|
Result:=0;
|
|
|
|
mcp^.mc_flags :=mcp^.mc_flags or _MC_HASFPXSTATE;
|
|
mcp^.mc_fpformat:=_MC_FPFMT_XMM;
|
|
mcp^.mc_ownedfp :=_MC_FPOWNED_FPU;
|
|
|
|
bmove(@td^.td_fpstate,xstate,SizeOf(mcp^.mc_fpstate));
|
|
end;
|
|
|
|
function set_fpcontext(td:p_kthread;mcp:p_mcontext_t;xstate:Pointer):Integer;
|
|
begin
|
|
Result:=0;
|
|
|
|
if (mcp^.mc_fpformat=_MC_FPFMT_NODEV) then Exit(0);
|
|
|
|
if (mcp^.mc_fpformat<>_MC_FPFMT_XMM) then Exit(EINVAL);
|
|
|
|
if (mcp^.mc_ownedfp=_MC_FPOWNED_NONE) then Exit(0);
|
|
|
|
if (mcp^.mc_ownedfp=_MC_FPOWNED_FPU) or
|
|
(mcp^.mc_ownedfp=_MC_FPOWNED_PCB) then
|
|
begin
|
|
bmove(xstate,@td^.td_fpstate,SizeOf(mcp^.mc_fpstate));
|
|
td^.td_frame.tf_flags:=td^.td_frame.tf_flags or TF_HASFPXSTATE;
|
|
Exit(0);
|
|
end;
|
|
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
function get_mcontext(td:p_kthread;mcp:p_mcontext_t;flags:Integer):Integer;
|
|
var
|
|
tp:p_trapframe;
|
|
begin
|
|
tp:=@td^.td_frame;
|
|
|
|
PROC_LOCK();
|
|
mcp^.mc_onstack:=sigonstack(tp^.tf_rsp);
|
|
PROC_UNLOCK();
|
|
|
|
mcp^.mc_r15 :=tp^.tf_r15;
|
|
mcp^.mc_r14 :=tp^.tf_r14;
|
|
mcp^.mc_r13 :=tp^.tf_r13;
|
|
mcp^.mc_r12 :=tp^.tf_r12;
|
|
mcp^.mc_r11 :=tp^.tf_r11;
|
|
mcp^.mc_r10 :=tp^.tf_r10;
|
|
mcp^.mc_r9 :=tp^.tf_r9;
|
|
mcp^.mc_r8 :=tp^.tf_r8;
|
|
mcp^.mc_rdi :=tp^.tf_rdi;
|
|
mcp^.mc_rsi :=tp^.tf_rsi;
|
|
mcp^.mc_rbp :=tp^.tf_rbp;
|
|
mcp^.mc_rbx :=tp^.tf_rbx;
|
|
mcp^.mc_rcx :=tp^.tf_rcx;
|
|
mcp^.mc_rflags:=tp^.tf_rflags;
|
|
|
|
if ((flags and GET_MC_CLEAR_RET)<>0) then
|
|
begin
|
|
mcp^.mc_rax:=0;
|
|
mcp^.mc_rdx:=0;
|
|
mcp^.mc_rflags:=tp^.tf_rflags and (not PSL_C);
|
|
end else
|
|
begin
|
|
mcp^.mc_rax:=tp^.tf_rax;
|
|
mcp^.mc_rdx:=tp^.tf_rdx;
|
|
end;
|
|
|
|
mcp^.mc_rip :=tp^.tf_rip;
|
|
mcp^.mc_cs :=tp^.tf_cs;
|
|
mcp^.mc_rsp :=tp^.tf_rsp;
|
|
mcp^.mc_ss :=tp^.tf_ss;
|
|
mcp^.mc_ds :=tp^.tf_ds;
|
|
mcp^.mc_es :=tp^.tf_es;
|
|
mcp^.mc_fs :=tp^.tf_fs;
|
|
mcp^.mc_gs :=tp^.tf_gs;
|
|
mcp^.mc_flags:=tp^.tf_flags;
|
|
mcp^.mc_len :=sizeof(mcontext_t);
|
|
|
|
//xmm,ymm
|
|
if ((tp^.tf_flags and TF_HASFPXSTATE)<>0) then
|
|
begin
|
|
Result:=get_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
|
end else
|
|
begin
|
|
Result:=md_get_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
|
end;
|
|
if (Result<>0) then Exit;
|
|
//xmm,ymm
|
|
|
|
mcp^.mc_fsbase:=ptruint(td^.pcb_fsbase);
|
|
mcp^.mc_gsbase:=ptruint(td^.pcb_gsbase);
|
|
|
|
bzero(@mcp^.mc_spare,sizeof(mcp^.mc_spare));
|
|
|
|
Result:=0;
|
|
end;
|
|
|
|
//sce ext
|
|
|
|
function get_mcontext2(td:p_kthread;mcp:p_mcontext_t;flags:Integer):Integer;
|
|
var
|
|
tp:p_trapframe;
|
|
begin
|
|
tp:=@td^.td_frame;
|
|
|
|
mcp^.mc_onstack:=sigonstack(tp^.tf_rsp);
|
|
|
|
mcp^.mc_r15 :=tp^.tf_r15;
|
|
mcp^.mc_r14 :=tp^.tf_r14;
|
|
mcp^.mc_r13 :=tp^.tf_r13;
|
|
mcp^.mc_r12 :=tp^.tf_r12;
|
|
mcp^.mc_r11 :=tp^.tf_r11;
|
|
mcp^.mc_r10 :=tp^.tf_r10;
|
|
mcp^.mc_r9 :=tp^.tf_r9;
|
|
mcp^.mc_r8 :=tp^.tf_r8;
|
|
mcp^.mc_rdi :=tp^.tf_rdi;
|
|
mcp^.mc_rsi :=tp^.tf_rsi;
|
|
mcp^.mc_rbp :=tp^.tf_rbp;
|
|
mcp^.mc_rbx :=tp^.tf_rbx;
|
|
mcp^.mc_rcx :=tp^.tf_rcx;
|
|
mcp^.mc_rflags:=tp^.tf_rflags;
|
|
mcp^.mc_rax :=tp^.tf_rax;
|
|
mcp^.mc_rdx :=tp^.tf_rdx;
|
|
mcp^.mc_rip :=tp^.tf_rip;
|
|
mcp^.mc_cs :=tp^.tf_cs;
|
|
mcp^.mc_rsp :=tp^.tf_rsp;
|
|
mcp^.mc_ss :=tp^.tf_ss;
|
|
mcp^.mc_ds :=tp^.tf_ds;
|
|
mcp^.mc_es :=tp^.tf_es;
|
|
mcp^.mc_fs :=tp^.tf_fs;
|
|
mcp^.mc_gs :=tp^.tf_gs;
|
|
mcp^.mc_flags :=tp^.tf_flags;
|
|
mcp^.mc_len :=sizeof(mcontext_t);
|
|
|
|
//xmm,ymm
|
|
get_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
|
//xmm,ymm
|
|
|
|
mcp^.mc_fsbase:=ptruint(td^.pcb_fsbase);
|
|
mcp^.mc_gsbase:=ptruint(td^.pcb_gsbase);
|
|
|
|
bzero(@mcp^.mc_spare,sizeof(mcp^.mc_spare));
|
|
|
|
Result:=0;
|
|
end;
|
|
|
|
//sce ext
|
|
|
|
function set_mcontext(td:p_kthread;mcp:p_mcontext_t):Integer;
|
|
var
|
|
tp:p_trapframe;
|
|
rflags:QWORD;
|
|
begin
|
|
tp:=@td^.td_frame;
|
|
|
|
if (mcp^.mc_len<>sizeof(mcontext_t)) or
|
|
((mcp^.mc_flags and (not _MC_FLAG_MASK))<>0) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
//xmm,ymm
|
|
if ((mcp^.mc_rflags and _MC_HASFPXSTATE)<>0) then
|
|
begin
|
|
Result:=set_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
|
if (Result<>0) then Exit;
|
|
end;
|
|
//xmm,ymm
|
|
|
|
rflags:=(mcp^.mc_rflags and PSL_USERCHANGE) or
|
|
(tp^.tf_rflags and (not PSL_USERCHANGE));
|
|
|
|
tp^.tf_r15 :=mcp^.mc_r15;
|
|
tp^.tf_r14 :=mcp^.mc_r14;
|
|
tp^.tf_r13 :=mcp^.mc_r13;
|
|
tp^.tf_r12 :=mcp^.mc_r12;
|
|
tp^.tf_r11 :=mcp^.mc_r11;
|
|
tp^.tf_r10 :=mcp^.mc_r10;
|
|
tp^.tf_r9 :=mcp^.mc_r9;
|
|
tp^.tf_r8 :=mcp^.mc_r8;
|
|
tp^.tf_rdi :=mcp^.mc_rdi;
|
|
tp^.tf_rsi :=mcp^.mc_rsi;
|
|
tp^.tf_rbp :=mcp^.mc_rbp;
|
|
tp^.tf_rbx :=mcp^.mc_rbx;
|
|
tp^.tf_rdx :=mcp^.mc_rdx;
|
|
tp^.tf_rcx :=mcp^.mc_rcx;
|
|
tp^.tf_rax :=mcp^.mc_rax;
|
|
tp^.tf_rip :=mcp^.mc_rip;
|
|
tp^.tf_rflags:=rflags;
|
|
tp^.tf_rsp :=mcp^.mc_rsp;
|
|
tp^.tf_ss :=mcp^.mc_ss;
|
|
tp^.tf_flags :=mcp^.mc_flags;
|
|
|
|
if ((tp^.tf_flags and TF_HASSEGS)<>0) then
|
|
begin
|
|
tp^.tf_ds:=mcp^.mc_ds;
|
|
tp^.tf_es:=mcp^.mc_es;
|
|
tp^.tf_fs:=mcp^.mc_fs;
|
|
tp^.tf_gs:=mcp^.mc_gs;
|
|
end;
|
|
|
|
if ((mcp^.mc_flags and _MC_HASBASES)<>0) then
|
|
begin
|
|
cpu_set_fsbase(td,Pointer(mcp^.mc_fsbase));
|
|
cpu_set_gsbase(td,Pointer(mcp^.mc_gsbase));
|
|
end;
|
|
|
|
set_pcb_flags(td,PCB_FULL_IRET);
|
|
Result:=0;
|
|
end;
|
|
|
|
procedure host_sigcode; external;
|
|
|
|
function IS_SYSTEM_STACK(td:p_kthread;rsp:qword):Boolean; inline;
|
|
begin
|
|
Result:=(rsp<=QWORD(td^.td_kstack.stack)) and (rsp>(QWORD(td^.td_kstack.sttop)));
|
|
end;
|
|
|
|
procedure sendsig(catcher:sig_t;ksi:p_ksiginfo;mask:p_sigset_t);
|
|
var
|
|
td:p_kthread;
|
|
sf:sigframe;
|
|
sfp:p_sigframe;
|
|
regs:p_trapframe;
|
|
sp:QWORD;
|
|
sig,oonstack:Integer;
|
|
begin
|
|
td:=curkthread;
|
|
|
|
Writeln('sendsig');
|
|
|
|
sig:=ksi^.ksi_info.si_signo;
|
|
|
|
regs:=@td^.td_frame;
|
|
oonstack:=sigonstack(regs^.tf_rsp);
|
|
|
|
// Save user context.
|
|
sf:=Default(sigframe);
|
|
|
|
sf.sf_uc.uc_sigmask:=mask^;
|
|
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;
|
|
|
|
sf.sf_uc.uc_mcontext.mc_onstack:=oonstack;
|
|
|
|
//set segs
|
|
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:=regs^.tf_flags or TF_HASSEGS;
|
|
//set segs
|
|
|
|
bmove(@regs^.tf_rdi,@sf.sf_uc.uc_mcontext.mc_rdi,tf_copy_1);
|
|
bmove(@regs^.tf_err,@sf.sf_uc.uc_mcontext.mc_err,tf_copy_2);
|
|
|
|
sf.sf_uc.uc_mcontext.mc_lbrfrom:=QWORD(-1);
|
|
sf.sf_uc.uc_mcontext.mc_lbrto :=QWORD(-1);
|
|
|
|
sf.sf_uc.uc_mcontext.mc_len:=sizeof(mcontext_t);
|
|
|
|
//xmm,ymm
|
|
if ((regs^.tf_flags and TF_HASFPXSTATE)<>0) then
|
|
begin
|
|
get_fpcontext(td,@sf.sf_uc.uc_mcontext,@sf.sf_uc.uc_mcontext.mc_fpstate);
|
|
|
|
//reset fpcontext usage
|
|
regs^.tf_flags:=regs^.tf_flags and (not TF_HASFPXSTATE);
|
|
end;
|
|
//xmm,ymm
|
|
|
|
sf.sf_uc.uc_mcontext.mc_flags :=sf.sf_uc.uc_mcontext.mc_flags or _MC_HASBASES;
|
|
sf.sf_uc.uc_mcontext.mc_fsbase:=QWORD(td^.pcb_fsbase);
|
|
sf.sf_uc.uc_mcontext.mc_gsbase:=QWORD(td^.pcb_gsbase);
|
|
|
|
if ((td^.td_pflags and TDP_ALTSTACK)<>0) and
|
|
(oonstack=0) and
|
|
SIGISMEMBER(@p_sigacts.ps_sigonstack,sig) then
|
|
begin
|
|
sp:=QWORD(td^.td_sigstk.ss_sp)+td^.td_sigstk.ss_size;
|
|
end else
|
|
begin
|
|
sp:=regs^.tf_rsp-128;
|
|
end;
|
|
|
|
if IS_SYSTEM_STACK(td,sp) then
|
|
begin
|
|
Assert(false,'System stack on guest context?');
|
|
end;
|
|
|
|
sp:=sp-sizeof(sigframe);
|
|
|
|
sfp:=p_sigframe(sp and (not $1F));
|
|
|
|
regs^.tf_rdi:=sig;
|
|
regs^.tf_rdx:=QWORD(@sfp^.sf_uc);
|
|
|
|
if (SIGISMEMBER(@p_sigacts.ps_siginfo,sig)) then
|
|
begin
|
|
regs^.tf_rsi:=QWORD(@sfp^.sf_si);
|
|
sf.sf_ahu:=Pointer(catcher);
|
|
|
|
sf.sf_si:=ksi^.ksi_info;
|
|
sf.sf_si.si_signo:=sig;
|
|
|
|
regs^.tf_rcx:=QWORD(ksi^.ksi_info.si_addr);
|
|
end else
|
|
begin
|
|
regs^.tf_rsi:=ksi^.ksi_info.si_code;
|
|
regs^.tf_rcx:=QWORD(ksi^.ksi_info.si_addr);
|
|
sf.sf_ahu:=Pointer(catcher);
|
|
end;
|
|
|
|
ps_mtx_unlock;
|
|
PROC_UNLOCK;
|
|
|
|
if (copyout(@sf,sfp,sizeof(sigframe))<>0) then
|
|
begin
|
|
PROC_LOCK;
|
|
sigexit(td,SIGILL);
|
|
end;
|
|
|
|
regs^.tf_rsp:=QWORD(sfp);
|
|
|
|
if ((td^.pcb_flags and PCB_IS_JIT)=0) or
|
|
((td^.pcb_flags and PCB_IS_HLE)<>0) then
|
|
begin
|
|
regs^.tf_rip:=QWORD(@host_sigcode);
|
|
end else
|
|
begin
|
|
regs^.tf_rip:=QWORD(p_vmspace(p_proc.p_vmspace)^.sv_usrstack);
|
|
end;
|
|
|
|
regs^.tf_rflags:=regs^.tf_rflags and (not (PSL_T or PSL_D));
|
|
|
|
set_pcb_flags(td,PCB_FULL_IRET);
|
|
PROC_LOCK;
|
|
ps_mtx_lock;
|
|
end;
|
|
|
|
function sys_sigreturn(sigcntxp:Pointer):Integer;
|
|
var
|
|
td:p_kthread;
|
|
uc:ucontext_t;
|
|
regs:p_trapframe;
|
|
ucp:p_ucontext_t;
|
|
begin
|
|
td:=curkthread;
|
|
|
|
Writeln('sys_sigreturn');
|
|
|
|
Result:=copyin(sigcntxp,@uc,sizeof(ucontext_t));
|
|
if (Result<>0) then Exit;
|
|
|
|
if IS_SYSTEM_STACK(td,uc.uc_mcontext.mc_rsp) then
|
|
begin
|
|
Assert(false,'System stack on guest context?');
|
|
end;
|
|
|
|
ucp:=@uc;
|
|
if ((ucp^.uc_mcontext.mc_flags and (not _MC_FLAG_MASK))<>0) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
regs:=@td^.td_frame;
|
|
|
|
//xmm,ymm
|
|
if ((uc.uc_mcontext.mc_flags and _MC_HASFPXSTATE)<>0) then
|
|
begin
|
|
Result:=set_fpcontext(td,@ucp^.uc_mcontext,@ucp^.uc_mcontext.mc_fpstate);
|
|
if (Result<>0) then Exit;
|
|
end;
|
|
//xmm,ymm
|
|
|
|
bmove(@ucp^.uc_mcontext.mc_rdi,@regs^.tf_rdi,tf_copy_1);
|
|
bmove(@ucp^.uc_mcontext.mc_err,@regs^.tf_err,tf_copy_2);
|
|
|
|
if ((ucp^.uc_mcontext.mc_flags and _MC_HASBASES)<>0) then
|
|
begin
|
|
cpu_set_fsbase(td,Pointer(ucp^.uc_mcontext.mc_fsbase));
|
|
cpu_set_gsbase(td,Pointer(ucp^.uc_mcontext.mc_gsbase));
|
|
end;
|
|
|
|
kern_sigprocmask(td,SIG_SETMASK,@ucp^.uc_sigmask,nil,0);
|
|
|
|
set_pcb_flags(td,PCB_FULL_IRET);
|
|
Result:=EJUSTRETURN;
|
|
end;
|
|
|
|
procedure exec_setregs(td:p_kthread;entry,stack_base,stack_top:QWORD);
|
|
var
|
|
regs:p_trapframe;
|
|
begin
|
|
regs:=@td^.td_frame;
|
|
|
|
cpu_set_fsbase(td,nil);
|
|
cpu_set_gsbase(td,nil);
|
|
|
|
set_pcb_flags(td,PCB_FULL_IRET);
|
|
|
|
bzero(regs, sizeof(trapframe));
|
|
|
|
regs^.tf_rip :=entry;
|
|
regs^.tf_rsp :=((stack_base - 8) and (not $F)) + 8;
|
|
regs^.tf_rdi :=stack_base; // argv
|
|
regs^.tf_rflags:=PSL_USER or (regs^.tf_rflags and PSL_T);
|
|
regs^.tf_ss :=_udatasel;
|
|
regs^.tf_cs :=_ucodesel;
|
|
regs^.tf_ds :=_udatasel;
|
|
regs^.tf_es :=_udatasel;
|
|
regs^.tf_fs :=_ufssel;
|
|
regs^.tf_gs :=_ugssel;
|
|
regs^.tf_flags :=TF_HASSEGS;
|
|
|
|
//init FPU
|
|
fpuinit(td);
|
|
|
|
Set8087CW(__INITIAL_FPUCW__);
|
|
SetMXCSR (__INITIAL_MXCSR__);
|
|
|
|
//teb stack
|
|
td^.td_ustack.stack:=Pointer(stack_top );
|
|
td^.td_ustack.sttop:=Pointer(stack_base);
|
|
//teb stack
|
|
|
|
td^.td_retval[1]:=0;
|
|
end;
|
|
|
|
|
|
|
|
end.
|
|
|